From 83fcfe68d99377ccf301188c4be57e03c6942837 Mon Sep 17 00:00:00 2001 From: Thomas Krennwallner Date: Sun, 11 Dec 2016 12:12:35 +0000 Subject: [PATCH 1/1] Import gringo_5.1.0.orig.tar.gz [dgit import orig gringo_5.1.0.orig.tar.gz] --- .gitignore | 17 + .travis.yml | 33 + .ycm_extra_conf.py | 182 + CHANGES | 141 + COPYING | 674 + INSTALL | 213 + README.md | 28 + SConscript | 535 + SConstruct | 154 + app/cexample/main.c | 63 + app/clingo/src/clasp/clasp_app.cpp | 675 + app/clingo/src/clasp/clasp_app.h | 209 + app/clingo/src/clingo_app.cc | 213 + app/clingo/src/clingo_app.hh | 68 + app/clingo/src/main.cc | 27 + app/clingo/tests/lp/bio.cmd | 1 + app/clingo/tests/lp/bio.lp | 37 + app/clingo/tests/lp/bio.sol | 30 + app/clingo/tests/lp/project.cmd | 1 + app/clingo/tests/lp/project.lp | 7 + app/clingo/tests/lp/project.sol | 4 + app/clingo/tests/lp/show.lp | 16 + app/clingo/tests/lp/show.sol | 25 + app/clingo/tests/lp/subset.cmd | 1 + app/clingo/tests/lp/subset.lp | 12 + app/clingo/tests/lp/subset.sol | 246 + app/clingo/tests/lua/assumptions1.lp | 11 + app/clingo/tests/lua/assumptions1.sol | 3 + app/clingo/tests/lua/assumptions2.lp | 11 + app/clingo/tests/lua/assumptions2.sol | 3 + app/clingo/tests/lua/assumptions3.lp | 12 + app/clingo/tests/lua/assumptions3.sol | 5 + app/clingo/tests/lua/assumptions4.lp | 26 + app/clingo/tests/lua/assumptions4.sol | 7 + app/clingo/tests/lua/blocksworld1.lp | 231 + app/clingo/tests/lua/blocksworld1.sol | 12 + app/clingo/tests/lua/conformant1.lp | 294 + app/clingo/tests/lua/conformant1.sol | 48 + app/clingo/tests/lua/conformant2.lp | 198 + app/clingo/tests/lua/conformant2.sol | 17 + app/clingo/tests/lua/conformant3.lp | 332 + app/clingo/tests/lua/conformant3.sol | 230 + app/clingo/tests/lua/cover-lua.lp | 111 + app/clingo/tests/lua/cover-lua.sol | 6 + app/clingo/tests/lua/csp-shrinking.lp | 16 + app/clingo/tests/lua/csp-shrinking.sol | 54 + app/clingo/tests/lua/domain.lp | 33 + app/clingo/tests/lua/domain.sol | 3 + app/clingo/tests/lua/externals.lp | 19 + app/clingo/tests/lua/externals.sol | 10 + app/clingo/tests/lua/iclingo.lp | 25 + app/clingo/tests/lua/iclingo.sol | 7 + app/clingo/tests/lua/icolor.lp | 45 + app/clingo/tests/lua/icolor.sol | 5 + app/clingo/tests/lua/inccsp-onmodel.cmd | 1 + app/clingo/tests/lua/inccsp-onmodel.lp | 37 + app/clingo/tests/lua/inccsp-onmodel.sol | 21 + app/clingo/tests/lua/inccsp.lp | 14 + app/clingo/tests/lua/inccsp.sol | 21 + app/clingo/tests/lua/incshow.lp | 12 + app/clingo/tests/lua/incshow.sol | 21 + app/clingo/tests/lua/mutex-bug.lp | 124 + app/clingo/tests/lua/mutex-bug.sol | 7 + app/clingo/tests/lua/parse-term.lp | 14 + app/clingo/tests/lua/parse-term.sol | 3 + app/clingo/tests/lua/project_bug.lp | 13 + app/clingo/tests/lua/project_bug.sol | 3 + app/clingo/tests/lua/propagator.cmd | 1 + app/clingo/tests/lua/propagator.lp | 371 + app/clingo/tests/lua/propagator.sol | 5 + app/clingo/tests/lua/queens.lp | 39 + app/clingo/tests/lua/queens.sol | 1236 + app/clingo/tests/lua/robots.lp | 212 + app/clingo/tests/lua/robots.sol | 8 + app/clingo/tests/lua/setconfig.lp | 28 + app/clingo/tests/lua/setconfig.sol | 12 + app/clingo/tests/lua/show.lp | 56 + app/clingo/tests/lua/show.sol | 7 + app/clingo/tests/lua/sokoban.lp | 125 + app/clingo/tests/lua/sokoban.sol | 16 + app/clingo/tests/lua/sokoban_back.lp | 137 + app/clingo/tests/lua/sokoban_back.sol | 16 + app/clingo/tests/lua/sokoban_para.lp | 168 + app/clingo/tests/lua/sokoban_para.sol | 21 + app/clingo/tests/lua/solitaire_para.lp | 140 + app/clingo/tests/lua/solitaire_para.sol | 23 + app/clingo/tests/lua/solitaire_sort.lp | 193 + app/clingo/tests/lua/solitaire_sort.sol | 20 + app/clingo/tests/lua/test.lp | 61 + app/clingo/tests/lua/test.sol | 35 + app/clingo/tests/lua/theory-term-types.lp | 17 + app/clingo/tests/lua/theory-term-types.sol | 3 + app/clingo/tests/lua/theory.lp | 72 + app/clingo/tests/lua/theory.sol | 3 + app/clingo/tests/lua/toh.lp | 105 + app/clingo/tests/lua/toh.sol | 35 + app/clingo/tests/lua/unsat-sync.lp | 11 + app/clingo/tests/lua/unsat-sync.sol | 3 + app/clingo/tests/python/assumptions1.lp | 13 + app/clingo/tests/python/assumptions1.sol | 3 + app/clingo/tests/python/assumptions2.lp | 13 + app/clingo/tests/python/assumptions2.sol | 3 + app/clingo/tests/python/assumptions3.lp | 14 + app/clingo/tests/python/assumptions3.sol | 5 + app/clingo/tests/python/assumptions4.lp | 19 + app/clingo/tests/python/assumptions4.sol | 7 + app/clingo/tests/python/ast.lp | 121 + app/clingo/tests/python/ast.sol | 3 + app/clingo/tests/python/ast2.lp | 132 + app/clingo/tests/python/ast2.sol | 3 + app/clingo/tests/python/ast3.lp | 142 + app/clingo/tests/python/ast3.sol | 3 + app/clingo/tests/python/blocksworld1.lp | 216 + app/clingo/tests/python/blocksworld1.sol | 12 + app/clingo/tests/python/cover-py.lp | 90 + app/clingo/tests/python/cover-py.sol | 6 + app/clingo/tests/python/domain.lp | 27 + app/clingo/tests/python/domain.sol | 3 + app/clingo/tests/python/externals.lp | 19 + app/clingo/tests/python/externals.sol | 10 + app/clingo/tests/python/iclingo.lp | 22 + app/clingo/tests/python/iclingo.sol | 7 + app/clingo/tests/python/interrupt.lp | 23 + app/clingo/tests/python/interrupt.sol | 7 + app/clingo/tests/python/parse-term.lp | 14 + app/clingo/tests/python/parse-term.sol | 3 + app/clingo/tests/python/project.lp | 197 + app/clingo/tests/python/project.sol | 28 + app/clingo/tests/python/propagator.cmd | 1 + app/clingo/tests/python/propagator.lp | 236 + app/clingo/tests/python/propagator.sol | 5 + app/clingo/tests/python/queens.lp | 37 + app/clingo/tests/python/queens.sol | 1236 + app/clingo/tests/python/setconfig.lp | 29 + app/clingo/tests/python/setconfig.sol | 12 + app/clingo/tests/python/show.lp | 51 + app/clingo/tests/python/show.sol | 7 + app/clingo/tests/python/sokoban.cmd | 1 + app/clingo/tests/python/sokoban.lp | 105 + app/clingo/tests/python/sokoban.sol | 14 + app/clingo/tests/python/tag.lp | 33 + app/clingo/tests/python/tag.sol | 5 + app/clingo/tests/python/test.lp | 57 + app/clingo/tests/python/test.sol | 45 + app/clingo/tests/run.py | 169 + app/example/main.cc | 47 + app/gringo/main.cc | 430 + app/lpconvert/lpconvert.cpp | 108 + app/luaclingo/src/main.cc | 43 + app/pyclingo/src/main.cc | 50 + app/reify/main.cc | 102 + app/web/main.cc | 69 + examples/c/ast.c | 206 + examples/c/backend.c | 143 + examples/c/configuration.c | 117 + examples/c/control.c | 98 + examples/c/model.c | 170 + examples/c/propagator.c | 329 + examples/c/solve-async.c | 126 + examples/c/solve-iteratively.c | 107 + examples/c/statistics.c | 192 + examples/c/symbol.c | 101 + examples/c/symbolic-atoms.c | 120 + examples/c/theory-atoms.c | 149 + examples/c/version.c | 14 + examples/clingo/addclause/README | 5 + examples/clingo/addclause/addclause-lua.lp | 18 + examples/clingo/addclause/addclause-py.lp | 18 + examples/clingo/blocksworld/README | 13 + examples/clingo/blocksworld/blocks_01.lp | 27 + examples/clingo/blocksworld/control_01.lua | 11 + examples/clingo/blocksworld/control_01.out | 235 + examples/clingo/blocksworld/lua.lp | 126 + examples/clingo/blocksworld/lua_interpret.lp | 21 + examples/clingo/blocksworld/world.lp | 130 + examples/clingo/commit/README | 7 + examples/clingo/commit/commit-lua.lp | 17 + examples/clingo/commit/commit-py.lp | 14 + examples/clingo/commit/encoding.lp | 5 + examples/clingo/consequences/README | 6 + examples/clingo/consequences/brave-lua.lp | 44 + examples/clingo/consequences/brave-py.lp | 24 + examples/clingo/consequences/example.lp | 4 + examples/clingo/context/README | 6 + examples/clingo/context/context-lua.lp | 30 + examples/clingo/context/context-py.lp | 21 + examples/clingo/context/encoding.lp | 1 + examples/clingo/controller-async/README | 8 + examples/clingo/controller-async/client.lp | 15 + .../clingo/controller-async/controller.py | 121 + examples/clingo/controller-processes/README | 11 + .../clingo/controller-processes/client.lp | 15 + .../clingo/controller-processes/client.py | 73 + .../clingo/controller-processes/server.py | 99 + examples/clingo/controller-threads/README | 8 + examples/clingo/controller-threads/client.lp | 15 + .../clingo/controller-threads/controller.py | 153 + examples/clingo/cover/README | 5 + examples/clingo/cover/control-lua.lp | 82 + examples/clingo/cover/control-py.lp | 60 + examples/clingo/cover/cover.lp | 9 + examples/clingo/cover/instance.lp | 8 + examples/clingo/cover/preprocess.lp | 14 + examples/clingo/domains/README | 6 + examples/clingo/domains/domains-lua.lp | 24 + examples/clingo/domains/domains-py.lp | 19 + examples/clingo/domains/instance.lp | 5 + examples/clingo/dot-propagator/README | 6 + examples/clingo/dot-propagator/dot.lp | 31 + examples/clingo/dot-propagator/test.lp | 5 + examples/clingo/enum-assumption/README | 8 + .../clingo/enum-assumption/example-lua.lp | 20 + examples/clingo/enum-assumption/example-py.lp | 19 + .../GraphColouring/encodings/encoding.lp | 31 + .../instances/0004-graph_colouring-125-0.lp | 1687 + .../instances/0005-graph_colouring-125-0.lp | 1649 + .../instances/0007-graph_colouring-125-0.lp | 1609 + .../instances/0008-graph_colouring-125-0.lp | 1677 + .../instances/0013-graph_colouring-130-0.lp | 1714 + .../instances/0021-graph_colouring-135-0.lp | 1981 + .../instances/0022-graph_colouring-135-0.lp | 2043 + .../instances/0023-graph_colouring-135-0.lp | 1869 + .../instances/0025-graph_colouring-135-0.lp | 1995 + .../instances/0032-graph_colouring-140-0.lp | 2226 + .../instances/0036-graph_colouring-140-0.lp | 2126 + .../instances/0039-graph_colouring-140-0.lp | 2174 + .../instances/0040-graph_colouring-140-0.lp | 2214 + .../instances/0046-graph_colouring-145-0.lp | 2345 + .../instances/0047-graph_colouring-145-0.lp | 2177 + .../instances/0048-graph_colouring-145-0.lp | 2233 + .../instances/0050-graph_colouring-145-0.lp | 2219 + .../instances/0056-graph_colouring-150-0.lp | 2252 + .../instances/0059-graph_colouring-150-0.lp | 2374 + .../instances/0060-graph_colouring-150-0.lp | 2472 + .../PartnerUnits/encodings/encoding.lp | 66 + .../instances/100-partner_units-100-0.lp | 744 + .../instances/102-partner_units-100-0.lp | 744 + .../114-partner_units_polynomial-100-0.lp | 746 + .../115-partner_units_polynomial-100-0.lp | 746 + .../119-partner_units_polynomial-100-0.lp | 746 + .../127-partner_units_polynomial-100-0.lp | 740 + .../instances/153-partner_units-100-0.lp | 748 + .../instances/154-partner_units-100-0.lp | 746 + .../instances/156-partner_units-100-0.lp | 742 + .../instances/161-partner_units-100-0.lp | 742 + .../175-partner_units_polynomial-75-0.lp | 780 + .../180-partner_units_polynomial-47-0.lp | 366 + .../188-partner_units_polynomial-57-0.lp | 588 + .../196-partner_units_polynomial-59-0.lp | 412 + .../26-partner_units_polynomial-60-0.lp | 620 + .../52-partner_units_polynomial-100-0.lp | 744 + .../58-partner_units_polynomial-100-0.lp | 740 + .../69-partner_units_polynomial-100-0.lp | 744 + .../instances/91-partner_units-100-0.lp | 742 + .../instances/99-partner_units-100-0.lp | 748 + examples/clingo/expansion/README | 33 + examples/clingo/expansion/main.py | 92 + examples/clingo/external/README | 3 + examples/clingo/external/external-lua.lp | 14 + examples/clingo/external/external-py.lp | 14 + examples/clingo/external/external.lp | 8 + examples/clingo/iclingo/README | 10 + examples/clingo/iclingo/example.lp | 16 + examples/clingo/iclingo/incmode-int.lp | 1 + examples/clingo/iclingo/incmode-lua.lp | 40 + examples/clingo/iclingo/incmode-py.lp | 33 + examples/clingo/include/README | 5 + examples/clingo/include/encoding-lua.lp | 13 + examples/clingo/include/encoding-py.lp | 12 + examples/clingo/include/include.lp | 1 + examples/clingo/incqueens/README | 7 + examples/clingo/incqueens/incqueens-lua.lp | 20 + examples/clingo/incqueens/incqueens-py.lp | 18 + examples/clingo/incqueens/incqueens.lp | 23 + examples/clingo/itersolve/README | 5 + examples/clingo/itersolve/itersolve-lua.lp | 19 + examples/clingo/itersolve/itersolve-py.lp | 9 + examples/clingo/itersolve/program.lp | 1 + examples/clingo/load/README | 7 + examples/clingo/load/load-lua.lp | 16 + examples/clingo/load/load-py.lp | 15 + examples/clingo/load/program.lp | 3 + examples/clingo/onmodel/README | 9 + examples/clingo/onmodel/onmodel-lua.lp | 42 + examples/clingo/onmodel/onmodel-py.lp | 31 + examples/clingo/planning/README | 6 + examples/clingo/planning/convert.lp | 28 + examples/clingo/planning/convert.sh | 2 + examples/clingo/planning/encoding.lp | 90 + examples/clingo/planning/instances/coins01.lp | 139 + examples/clingo/planning/instances/comm02.lp | 179 + examples/clingo/planning/instances/comm03.lp | 239 + examples/clingo/planning/instances/comm05.lp | 371 + examples/clingo/planning/instances/uts01.lp | 37 + examples/clingo/planning/planning-lua.lp | 37 + examples/clingo/pydoc/README | 3 + examples/clingo/pydoc/pydoc-lib.py | 12 + examples/clingo/pydoc/pydoc.lp | 15 + examples/clingo/robots/README | 13 + examples/clingo/robots/board.lp | 42 + .../clingo/robots/img/arrow_blue_east.gif | Bin 0 -> 680 bytes .../clingo/robots/img/arrow_blue_north.gif | Bin 0 -> 643 bytes .../clingo/robots/img/arrow_blue_south.gif | Bin 0 -> 657 bytes .../clingo/robots/img/arrow_blue_west.gif | Bin 0 -> 679 bytes .../clingo/robots/img/arrow_green_east.gif | Bin 0 -> 697 bytes .../clingo/robots/img/arrow_green_north.gif | Bin 0 -> 704 bytes .../clingo/robots/img/arrow_green_south.gif | Bin 0 -> 714 bytes .../clingo/robots/img/arrow_green_west.gif | Bin 0 -> 690 bytes examples/clingo/robots/img/arrow_red_east.gif | Bin 0 -> 680 bytes .../clingo/robots/img/arrow_red_north.gif | Bin 0 -> 643 bytes .../clingo/robots/img/arrow_red_south.gif | Bin 0 -> 657 bytes examples/clingo/robots/img/arrow_red_west.gif | Bin 0 -> 679 bytes .../clingo/robots/img/arrow_yellow_east.gif | Bin 0 -> 680 bytes .../clingo/robots/img/arrow_yellow_north.gif | Bin 0 -> 640 bytes .../clingo/robots/img/arrow_yellow_south.gif | Bin 0 -> 658 bytes .../clingo/robots/img/arrow_yellow_west.gif | Bin 0 -> 679 bytes examples/clingo/robots/img/moon_blue.gif | Bin 0 -> 1121 bytes examples/clingo/robots/img/moon_green.gif | Bin 0 -> 1137 bytes examples/clingo/robots/img/moon_red.gif | Bin 0 -> 1121 bytes examples/clingo/robots/img/moon_yellow.gif | Bin 0 -> 1120 bytes examples/clingo/robots/img/move_blue_east.gif | Bin 0 -> 637 bytes .../clingo/robots/img/move_blue_north.gif | Bin 0 -> 634 bytes .../clingo/robots/img/move_blue_south.gif | Bin 0 -> 627 bytes examples/clingo/robots/img/move_blue_west.gif | Bin 0 -> 647 bytes .../clingo/robots/img/move_green_east.gif | Bin 0 -> 624 bytes .../clingo/robots/img/move_green_north.gif | Bin 0 -> 639 bytes .../clingo/robots/img/move_green_south.gif | Bin 0 -> 657 bytes .../clingo/robots/img/move_green_west.gif | Bin 0 -> 653 bytes examples/clingo/robots/img/move_red_east.gif | Bin 0 -> 616 bytes examples/clingo/robots/img/move_red_north.gif | Bin 0 -> 634 bytes examples/clingo/robots/img/move_red_south.gif | Bin 0 -> 627 bytes examples/clingo/robots/img/move_red_west.gif | Bin 0 -> 647 bytes .../clingo/robots/img/move_yellow_east.gif | Bin 0 -> 631 bytes .../clingo/robots/img/move_yellow_north.gif | Bin 0 -> 631 bytes .../clingo/robots/img/move_yellow_south.gif | Bin 0 -> 627 bytes .../clingo/robots/img/move_yellow_west.gif | Bin 0 -> 643 bytes examples/clingo/robots/img/random_robot.gif | Bin 0 -> 1415 bytes examples/clingo/robots/img/robot_blue.gif | Bin 0 -> 687 bytes examples/clingo/robots/img/robot_green.gif | Bin 0 -> 1142 bytes examples/clingo/robots/img/robot_red.gif | Bin 0 -> 687 bytes examples/clingo/robots/img/robot_yellow.gif | Bin 0 -> 685 bytes examples/clingo/robots/img/saturn_blue.gif | Bin 0 -> 763 bytes examples/clingo/robots/img/saturn_green.gif | Bin 0 -> 825 bytes examples/clingo/robots/img/saturn_red.gif | Bin 0 -> 763 bytes examples/clingo/robots/img/saturn_yellow.gif | Bin 0 -> 763 bytes examples/clingo/robots/img/star_blue.gif | Bin 0 -> 721 bytes examples/clingo/robots/img/star_green.gif | Bin 0 -> 757 bytes examples/clingo/robots/img/star_red.gif | Bin 0 -> 721 bytes examples/clingo/robots/img/star_yellow.gif | Bin 0 -> 723 bytes examples/clingo/robots/img/sun_blue.gif | Bin 0 -> 1147 bytes examples/clingo/robots/img/sun_green.gif | Bin 0 -> 1155 bytes examples/clingo/robots/img/sun_red.gif | Bin 0 -> 1147 bytes examples/clingo/robots/img/sun_yellow.gif | Bin 0 -> 1144 bytes examples/clingo/robots/img/tile_left.gif | Bin 0 -> 1724 bytes examples/clingo/robots/img/tile_right.gif | Bin 0 -> 1770 bytes examples/clingo/robots/img/wall_north.gif | Bin 0 -> 1136 bytes examples/clingo/robots/img/wall_west.gif | Bin 0 -> 1171 bytes examples/clingo/robots/robots.lp | 35 + examples/clingo/robots/visualize.py | 475 + examples/clingo/setconf/README | 5 + examples/clingo/setconf/setconf-lua.lp | 52 + examples/clingo/setconf/setconf-py.lp | 49 + examples/clingo/solitaire/README | 53 + examples/clingo/solitaire/instance.lp | 37 + examples/clingo/solitaire/solitaire.lp | 33 + examples/clingo/solitaire/visualize.py | 165 + examples/clingo/solve-async/README | 6 + examples/clingo/solve-async/program.lp | 5 + examples/clingo/solve-async/solve-async-py.lp | 20 + examples/clingo/stats/README | 8 + examples/clingo/stats/example.lp | 5 + examples/clingo/stats/stats-lua.lp | 18 + examples/clingo/stats/stats-py.lp | 14 + examples/clingo/unblock/README | 11 + examples/clingo/unblock/inst1.lp | 15 + examples/clingo/unblock/inst2.lp | 18 + examples/clingo/unblock/inst3.lp | 11 + examples/clingo/unblock/inst4.lp | 14 + examples/clingo/unblock/inst5.lp | 42 + examples/clingo/unblock/unblock.lp | 48 + examples/clingo/unblock/visualize.py | 179 + examples/gringo/acyc/README | 5 + examples/gringo/acyc/encoding.lp | 7 + examples/gringo/acyc/instance.lp | 3 + examples/gringo/ast/README | 6 + examples/gringo/ast/example.lp | 7 + examples/gringo/ast/visitor.lp | 72 + examples/gringo/gbie/README | 9 + examples/gringo/gbie/gbie1.lp | 47 + examples/gringo/gbie/gbie2.lp | 32 + examples/gringo/gbie/instances/sat_01.lp | 33 + examples/gringo/gbie/instances/sat_02.lp | 95144 ++++++++++++++++ examples/gringo/gbie/instances/sat_03.lp | 81956 +++++++++++++ examples/gringo/gbie/instances/unsat_01.lp | 42 + examples/gringo/gbie/instances/unsat_02.lp | 83951 ++++++++++++++ examples/gringo/project/README | 5 + examples/gringo/project/example.lp | 5 + examples/gringo/queens/README | 6 + examples/gringo/queens/queens1.lp | 15 + examples/gringo/queens/queens2.lp | 18 + examples/gringo/rec-cond/README | 4 + examples/gringo/rec-cond/encoding.lp | 61 + examples/gringo/rec-cond/instance.lp | 132 + examples/gringo/subset/README | 6 + examples/gringo/subset/example.lp | 7 + examples/gringo/toh/README | 6 + examples/gringo/toh/tohE.lp | 22 + examples/gringo/toh/tohI.lp | 6 + examples/reify/README | 24 + examples/reify/example1.lp | 5 + examples/reify/example2.lp | 220 + examples/reify/meta.lp | 39 + examples/reify/metaD.lp | 85 + examples/reify/metaO.lp | 79 + examples/test.sh | 129 + libclasp/clasp/asp_preprocessor.h | 127 + libclasp/clasp/cb_enumerator.h | 66 + libclasp/clasp/clasp_facade.h | 490 + libclasp/clasp/claspfwd.h | 73 + libclasp/clasp/clause.h | 541 + libclasp/clasp/cli/clasp_cli_configs.inl | 91 + libclasp/clasp/cli/clasp_cli_options.inl | 493 + libclasp/clasp/cli/clasp_options.h | 311 + libclasp/clasp/cli/clasp_output.h | 251 + libclasp/clasp/cli/clifwd.h | 32 + libclasp/clasp/clingo.h | 144 + libclasp/clasp/constraint.h | 584 + libclasp/clasp/dependency_graph.h | 472 + libclasp/clasp/enumerator.h | 321 + libclasp/clasp/heuristics.h | 399 + libclasp/clasp/literal.h | 243 + libclasp/clasp/logic_program.h | 644 + libclasp/clasp/logic_program_types.h | 640 + libclasp/clasp/lookahead.h | 239 + libclasp/clasp/minimize_constraint.h | 571 + libclasp/clasp/model_enumerators.h | 117 + libclasp/clasp/parallel_solve.h | 368 + libclasp/clasp/parser.h | 187 + libclasp/clasp/pod_vector.h | 103 + libclasp/clasp/program_builder.h | 248 + libclasp/clasp/satelite.h | 170 + libclasp/clasp/shared_context.h | 939 + libclasp/clasp/solve_algorithms.h | 271 + libclasp/clasp/solver.h | 1072 + libclasp/clasp/solver_strategies.h | 528 + libclasp/clasp/solver_types.h | 793 + libclasp/clasp/statistics.h | 301 + libclasp/clasp/unfounded_check.h | 306 + libclasp/clasp/util/atomic.h | 128 + libclasp/clasp/util/hash_map.h | 77 + libclasp/clasp/util/indexed_priority_queue.h | 216 + libclasp/clasp/util/left_right_sequence.h | 350 + libclasp/clasp/util/misc_types.h | 431 + libclasp/clasp/util/multi_queue.h | 256 + libclasp/clasp/util/mutex.h | 88 + libclasp/clasp/util/platform.h | 212 + libclasp/clasp/util/pod_vector.h | 558 + libclasp/clasp/util/thread.h | 44 + libclasp/clasp/util/timer.h | 72 + libclasp/clasp/util/type_manip.h | 137 + libclasp/clasp/weight_constraint.h | 229 + libclasp/libclasp.vcxproj | 213 + libclasp/libclasp.vcxproj.filters | 254 + libclasp/src/asp_preprocessor.cpp | 540 + libclasp/src/cb_enumerator.cpp | 349 + libclasp/src/clasp_facade.cpp | 1053 + libclasp/src/clasp_options.cpp | 1008 + libclasp/src/clasp_output.cpp | 1143 + libclasp/src/clause.cpp | 1073 + libclasp/src/clingo.cpp | 280 + libclasp/src/constraint.cpp | 97 + libclasp/src/dependency_graph.cpp | 1064 + libclasp/src/enumerator.cpp | 307 + libclasp/src/heuristics.cpp | 951 + libclasp/src/logic_program.cpp | 2071 + libclasp/src/logic_program_types.cpp | 1397 + libclasp/src/lookahead.cpp | 392 + libclasp/src/minimize_constraint.cpp | 1370 + libclasp/src/model_enumerators.cpp | 313 + libclasp/src/parallel_solve.cpp | 1170 + libclasp/src/parser.cpp | 511 + libclasp/src/program_builder.cpp | 375 + libclasp/src/satelite.cpp | 618 + libclasp/src/shared_context.cpp | 1121 + libclasp/src/solve_algorithms.cpp | 433 + libclasp/src/solver.cpp | 1845 + libclasp/src/solver_strategies.cpp | 310 + libclasp/src/solver_types.cpp | 303 + libclasp/src/statistics.cpp | 265 + libclasp/src/timer.cpp | 104 + libclasp/src/unfounded_check.cpp | 784 + libclasp/src/weight_constraint.cpp | 596 + libclingo/clingo/clingocontrol.hh | 417 + libclingo/src/clingocontrol.cc | 789 + libclingo/tests/ast.cc | 285 + libclingo/tests/catch.hpp | 10509 ++ libclingo/tests/clingo.cc | 534 + libclingo/tests/main.cc | 22 + libclingo/tests/propagator.cc | 643 + libclingo/tests/symbol.cc | 106 + libclingo/tests/tests.hh | 56 + libclingo/tests/variant.cc | 75 + libgringo/clingo.h | 3254 + libgringo/clingo.hh | 2079 + libgringo/gringo/backend.hh | 60 + libgringo/gringo/backtrace.hh | 119 + libgringo/gringo/base.hh | 280 + libgringo/gringo/bug.hh | 81 + libgringo/gringo/clonable.hh | 50 + libgringo/gringo/comparable.hh | 42 + libgringo/gringo/control.hh | 284 + libgringo/gringo/domain.hh | 601 + libgringo/gringo/graph.hh | 159 + libgringo/gringo/ground/binders.hh | 204 + libgringo/gringo/ground/dependency.hh | 296 + libgringo/gringo/ground/instantiation.hh | 126 + libgringo/gringo/ground/literal.hh | 62 + libgringo/gringo/ground/literals.hh | 184 + libgringo/gringo/ground/program.hh | 68 + libgringo/gringo/ground/statement.hh | 46 + libgringo/gringo/ground/statements.hh | 1274 + libgringo/gringo/ground/types.hh | 41 + libgringo/gringo/hash_set.hh | 615 + libgringo/gringo/hashable.hh | 68 + libgringo/gringo/indexed.hh | 95 + libgringo/gringo/input/aggregate.hh | 209 + libgringo/gringo/input/aggregates.hh | 452 + libgringo/gringo/input/groundtermparser.hh | 65 + libgringo/gringo/input/literal.hh | 95 + libgringo/gringo/input/literals.hh | 226 + libgringo/gringo/input/nongroundparser.hh | 103 + libgringo/gringo/input/program.hh | 88 + libgringo/gringo/input/programbuilder.hh | 653 + libgringo/gringo/input/statement.hh | 58 + libgringo/gringo/input/theory.hh | 189 + libgringo/gringo/input/types.hh | 52 + libgringo/gringo/intervals.hh | 370 + libgringo/gringo/lexerstate.hh | 331 + libgringo/gringo/locatable.hh | 153 + libgringo/gringo/logger.hh | 127 + libgringo/gringo/lua.hh | 49 + libgringo/gringo/output/aggregates.hh | 94 + libgringo/gringo/output/backends.hh | 46 + libgringo/gringo/output/literal.hh | 204 + libgringo/gringo/output/literals.hh | 1328 + libgringo/gringo/output/output.hh | 107 + libgringo/gringo/output/statement.hh | 64 + libgringo/gringo/output/statements.hh | 493 + libgringo/gringo/output/theory.hh | 287 + libgringo/gringo/output/types.hh | 59 + libgringo/gringo/primes.hh | 43 + libgringo/gringo/printable.hh | 46 + libgringo/gringo/python.hh | 45 + libgringo/gringo/safetycheck.hh | 186 + libgringo/gringo/scripts.hh | 58 + libgringo/gringo/symbol.hh | 298 + libgringo/gringo/term.hh | 826 + libgringo/gringo/terms.hh | 269 + libgringo/gringo/types.hh | 39 + libgringo/gringo/utility.hh | 745 + libgringo/gringo/version.hh | 29 + libgringo/src/backend.cc | 74 + libgringo/src/control.cc | 3792 + libgringo/src/ground/instantiation.cc | 165 + libgringo/src/ground/literals.cc | 492 + libgringo/src/ground/program.cc | 165 + libgringo/src/ground/statements.cc | 2654 + libgringo/src/input/aggregate.cc | 125 + libgringo/src/input/aggregates.cc | 2237 + libgringo/src/input/groundtermgrammar.yy | 149 + libgringo/src/input/groundtermlexer.xh | 76 + libgringo/src/input/groundtermparser.cc | 109 + libgringo/src/input/literal.cc | 63 + libgringo/src/input/literals.cc | 503 + libgringo/src/input/nongroundgrammar.yy | 1013 + libgringo/src/input/nongroundlexer.xch | 219 + libgringo/src/input/nongroundparser.cc | 391 + libgringo/src/input/program.cc | 263 + libgringo/src/input/programbuilder.cc | 1935 + libgringo/src/input/statement.cc | 320 + libgringo/src/input/theory.cc | 574 + libgringo/src/lua.cc | 2752 + libgringo/src/output/aggregates.cc | 440 + libgringo/src/output/literal.cc | 63 + libgringo/src/output/literals.cc | 1844 + libgringo/src/output/output.cc | 446 + libgringo/src/output/statement.cc | 55 + libgringo/src/output/statements.cc | 967 + libgringo/src/output/theory.cc | 756 + libgringo/src/primes.cc | 192 + libgringo/src/python.cc | 6424 ++ libgringo/src/scripts.cc | 55 + libgringo/src/symbol.cc | 482 + libgringo/src/term.cc | 1893 + libgringo/src/terms.cc | 441 + libgringo/tests/catch.hpp | 10485 ++ libgringo/tests/graph.cc | 83 + libgringo/tests/ground/dependency.cc | 209 + libgringo/tests/ground/grounder_helper.hh | 107 + libgringo/tests/ground/instantiation.cc | 1119 + libgringo/tests/ground/literal.cc | 175 + libgringo/tests/ground/program.cc | 255 + libgringo/tests/ground/theory.cc | 246 + libgringo/tests/input/aggregate.cc | 414 + libgringo/tests/input/aggregate_helper.hh | 89 + libgringo/tests/input/lit_helper.hh | 93 + libgringo/tests/input/literal.cc | 171 + libgringo/tests/input/nongroundgrammar.cc | 1272 + libgringo/tests/input/nongroundlexer.cc | 91 + libgringo/tests/input/parse_term.cc | 64 + libgringo/tests/input/program.cc | 230 + libgringo/tests/input/programbuilder.cc | 305 + libgringo/tests/intervals.cc | 377 + libgringo/tests/lua.cc | 171 + libgringo/tests/main.cc | 21 + libgringo/tests/output/aspcomp13.cc | 2523 + libgringo/tests/output/incremental.cc | 305 + libgringo/tests/output/lparse.cc | 1290 + libgringo/tests/output/solver_helper.hh | 141 + libgringo/tests/output/theory.cc | 240 + libgringo/tests/output/warnings.cc | 86 + libgringo/tests/python.cc | 171 + libgringo/tests/safetycheck.cc | 74 + libgringo/tests/symbol.cc | 204 + libgringo/tests/term.cc | 323 + libgringo/tests/term_helper.hh | 101 + libgringo/tests/tests.hh | 321 + libgringo/tests/unique_vec.cc | 55 + libgringo/tests/utility.cc | 214 + liblp/potassco/aspif.h | 130 + liblp/potassco/aspif_text.h | 70 + liblp/potassco/basic_types.h | 334 + liblp/potassco/clingo.h | 211 + liblp/potassco/convert.h | 94 + liblp/potassco/match_basic_types.h | 266 + liblp/potassco/rule_utils.h | 142 + liblp/potassco/smodels.h | 188 + liblp/potassco/theory_data.h | 408 + liblp/src/aspif.cpp | 284 + liblp/src/aspif_text.cpp | 324 + liblp/src/clingo.cpp | 29 + liblp/src/convert.cpp | 325 + liblp/src/match_basic_types.cpp | 380 + liblp/src/rule_utils.cpp | 231 + liblp/src/smodels.cpp | 385 + liblp/src/theory_data.cpp | 328 + liblp/tests/CMakeLists.txt | 5 + liblp/tests/aspif.cpp | 521 + liblp/tests/catch.hpp | 9427 ++ liblp/tests/common.h | 82 + liblp/tests/main.cpp | 2 + liblp/tests/smodels.cpp | 602 + liblp/tests/text.cpp | 153 + libprogram_opts/program_opts/application.h | 132 + libprogram_opts/program_opts/detail/alarm.h | 74 + .../program_opts/detail/notifier.h | 58 + .../program_opts/detail/refcountable.h | 72 + .../program_opts/detail/value_store.h | 87 + libprogram_opts/program_opts/errors.h | 109 + libprogram_opts/program_opts/mapped_value.h | 92 + .../program_opts/program_options.h | 527 + libprogram_opts/program_opts/string_convert.h | 280 + libprogram_opts/program_opts/typed_value.h | 247 + libprogram_opts/program_opts/value.h | 211 + libprogram_opts/program_opts/value_store.h | 152 + libprogram_opts/src/alarm.cpp | 161 + libprogram_opts/src/application.cpp | 265 + libprogram_opts/src/program_options.cpp | 962 + libprogram_opts/src/string_convert.cpp | 257 + libprogram_opts/src/value_store.cpp | 81 + libreify/reify/program.hh | 114 + libreify/reify/util.hh | 111 + libreify/src/program.cc | 236 + libreify/tests/catch.hpp | 10485 ++ libreify/tests/main.cc | 2 + libreify/tests/program.cc | 118 + 676 files changed, 489868 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 .ycm_extra_conf.py create mode 100644 CHANGES create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 README.md create mode 100644 SConscript create mode 100644 SConstruct create mode 100644 app/cexample/main.c create mode 100644 app/clingo/src/clasp/clasp_app.cpp create mode 100644 app/clingo/src/clasp/clasp_app.h create mode 100644 app/clingo/src/clingo_app.cc create mode 100644 app/clingo/src/clingo_app.hh create mode 100644 app/clingo/src/main.cc create mode 100644 app/clingo/tests/lp/bio.cmd create mode 100644 app/clingo/tests/lp/bio.lp create mode 100644 app/clingo/tests/lp/bio.sol create mode 100644 app/clingo/tests/lp/project.cmd create mode 100644 app/clingo/tests/lp/project.lp create mode 100644 app/clingo/tests/lp/project.sol create mode 100644 app/clingo/tests/lp/show.lp create mode 100644 app/clingo/tests/lp/show.sol create mode 100644 app/clingo/tests/lp/subset.cmd create mode 100644 app/clingo/tests/lp/subset.lp create mode 100644 app/clingo/tests/lp/subset.sol create mode 100644 app/clingo/tests/lua/assumptions1.lp create mode 100644 app/clingo/tests/lua/assumptions1.sol create mode 100644 app/clingo/tests/lua/assumptions2.lp create mode 100644 app/clingo/tests/lua/assumptions2.sol create mode 100644 app/clingo/tests/lua/assumptions3.lp create mode 100644 app/clingo/tests/lua/assumptions3.sol create mode 100644 app/clingo/tests/lua/assumptions4.lp create mode 100644 app/clingo/tests/lua/assumptions4.sol create mode 100644 app/clingo/tests/lua/blocksworld1.lp create mode 100644 app/clingo/tests/lua/blocksworld1.sol create mode 100644 app/clingo/tests/lua/conformant1.lp create mode 100644 app/clingo/tests/lua/conformant1.sol create mode 100644 app/clingo/tests/lua/conformant2.lp create mode 100644 app/clingo/tests/lua/conformant2.sol create mode 100644 app/clingo/tests/lua/conformant3.lp create mode 100644 app/clingo/tests/lua/conformant3.sol create mode 100644 app/clingo/tests/lua/cover-lua.lp create mode 100644 app/clingo/tests/lua/cover-lua.sol create mode 100644 app/clingo/tests/lua/csp-shrinking.lp create mode 100644 app/clingo/tests/lua/csp-shrinking.sol create mode 100644 app/clingo/tests/lua/domain.lp create mode 100644 app/clingo/tests/lua/domain.sol create mode 100644 app/clingo/tests/lua/externals.lp create mode 100644 app/clingo/tests/lua/externals.sol create mode 100644 app/clingo/tests/lua/iclingo.lp create mode 100644 app/clingo/tests/lua/iclingo.sol create mode 100644 app/clingo/tests/lua/icolor.lp create mode 100644 app/clingo/tests/lua/icolor.sol create mode 100644 app/clingo/tests/lua/inccsp-onmodel.cmd create mode 100644 app/clingo/tests/lua/inccsp-onmodel.lp create mode 100644 app/clingo/tests/lua/inccsp-onmodel.sol create mode 100644 app/clingo/tests/lua/inccsp.lp create mode 100644 app/clingo/tests/lua/inccsp.sol create mode 100644 app/clingo/tests/lua/incshow.lp create mode 100644 app/clingo/tests/lua/incshow.sol create mode 100644 app/clingo/tests/lua/mutex-bug.lp create mode 100644 app/clingo/tests/lua/mutex-bug.sol create mode 100644 app/clingo/tests/lua/parse-term.lp create mode 100644 app/clingo/tests/lua/parse-term.sol create mode 100644 app/clingo/tests/lua/project_bug.lp create mode 100644 app/clingo/tests/lua/project_bug.sol create mode 100644 app/clingo/tests/lua/propagator.cmd create mode 100644 app/clingo/tests/lua/propagator.lp create mode 100644 app/clingo/tests/lua/propagator.sol create mode 100644 app/clingo/tests/lua/queens.lp create mode 100644 app/clingo/tests/lua/queens.sol create mode 100644 app/clingo/tests/lua/robots.lp create mode 100644 app/clingo/tests/lua/robots.sol create mode 100644 app/clingo/tests/lua/setconfig.lp create mode 100644 app/clingo/tests/lua/setconfig.sol create mode 100644 app/clingo/tests/lua/show.lp create mode 100644 app/clingo/tests/lua/show.sol create mode 100644 app/clingo/tests/lua/sokoban.lp create mode 100644 app/clingo/tests/lua/sokoban.sol create mode 100644 app/clingo/tests/lua/sokoban_back.lp create mode 100644 app/clingo/tests/lua/sokoban_back.sol create mode 100644 app/clingo/tests/lua/sokoban_para.lp create mode 100644 app/clingo/tests/lua/sokoban_para.sol create mode 100644 app/clingo/tests/lua/solitaire_para.lp create mode 100644 app/clingo/tests/lua/solitaire_para.sol create mode 100644 app/clingo/tests/lua/solitaire_sort.lp create mode 100644 app/clingo/tests/lua/solitaire_sort.sol create mode 100644 app/clingo/tests/lua/test.lp create mode 100644 app/clingo/tests/lua/test.sol create mode 100644 app/clingo/tests/lua/theory-term-types.lp create mode 100644 app/clingo/tests/lua/theory-term-types.sol create mode 100644 app/clingo/tests/lua/theory.lp create mode 100644 app/clingo/tests/lua/theory.sol create mode 100644 app/clingo/tests/lua/toh.lp create mode 100644 app/clingo/tests/lua/toh.sol create mode 100644 app/clingo/tests/lua/unsat-sync.lp create mode 100644 app/clingo/tests/lua/unsat-sync.sol create mode 100644 app/clingo/tests/python/assumptions1.lp create mode 100644 app/clingo/tests/python/assumptions1.sol create mode 100644 app/clingo/tests/python/assumptions2.lp create mode 100644 app/clingo/tests/python/assumptions2.sol create mode 100644 app/clingo/tests/python/assumptions3.lp create mode 100644 app/clingo/tests/python/assumptions3.sol create mode 100644 app/clingo/tests/python/assumptions4.lp create mode 100644 app/clingo/tests/python/assumptions4.sol create mode 100644 app/clingo/tests/python/ast.lp create mode 100644 app/clingo/tests/python/ast.sol create mode 100644 app/clingo/tests/python/ast2.lp create mode 100644 app/clingo/tests/python/ast2.sol create mode 100644 app/clingo/tests/python/ast3.lp create mode 100644 app/clingo/tests/python/ast3.sol create mode 100644 app/clingo/tests/python/blocksworld1.lp create mode 100644 app/clingo/tests/python/blocksworld1.sol create mode 100644 app/clingo/tests/python/cover-py.lp create mode 100644 app/clingo/tests/python/cover-py.sol create mode 100644 app/clingo/tests/python/domain.lp create mode 100644 app/clingo/tests/python/domain.sol create mode 100644 app/clingo/tests/python/externals.lp create mode 100644 app/clingo/tests/python/externals.sol create mode 100644 app/clingo/tests/python/iclingo.lp create mode 100644 app/clingo/tests/python/iclingo.sol create mode 100644 app/clingo/tests/python/interrupt.lp create mode 100644 app/clingo/tests/python/interrupt.sol create mode 100644 app/clingo/tests/python/parse-term.lp create mode 100644 app/clingo/tests/python/parse-term.sol create mode 100644 app/clingo/tests/python/project.lp create mode 100644 app/clingo/tests/python/project.sol create mode 100644 app/clingo/tests/python/propagator.cmd create mode 100644 app/clingo/tests/python/propagator.lp create mode 100644 app/clingo/tests/python/propagator.sol create mode 100644 app/clingo/tests/python/queens.lp create mode 100644 app/clingo/tests/python/queens.sol create mode 100644 app/clingo/tests/python/setconfig.lp create mode 100644 app/clingo/tests/python/setconfig.sol create mode 100644 app/clingo/tests/python/show.lp create mode 100644 app/clingo/tests/python/show.sol create mode 100644 app/clingo/tests/python/sokoban.cmd create mode 100644 app/clingo/tests/python/sokoban.lp create mode 100644 app/clingo/tests/python/sokoban.sol create mode 100644 app/clingo/tests/python/tag.lp create mode 100644 app/clingo/tests/python/tag.sol create mode 100644 app/clingo/tests/python/test.lp create mode 100644 app/clingo/tests/python/test.sol create mode 100755 app/clingo/tests/run.py create mode 100644 app/example/main.cc create mode 100644 app/gringo/main.cc create mode 100644 app/lpconvert/lpconvert.cpp create mode 100644 app/luaclingo/src/main.cc create mode 100644 app/pyclingo/src/main.cc create mode 100644 app/reify/main.cc create mode 100644 app/web/main.cc create mode 100644 examples/c/ast.c create mode 100644 examples/c/backend.c create mode 100644 examples/c/configuration.c create mode 100644 examples/c/control.c create mode 100644 examples/c/model.c create mode 100644 examples/c/propagator.c create mode 100644 examples/c/solve-async.c create mode 100644 examples/c/solve-iteratively.c create mode 100644 examples/c/statistics.c create mode 100644 examples/c/symbol.c create mode 100644 examples/c/symbolic-atoms.c create mode 100644 examples/c/theory-atoms.c create mode 100644 examples/c/version.c create mode 100644 examples/clingo/addclause/README create mode 100644 examples/clingo/addclause/addclause-lua.lp create mode 100644 examples/clingo/addclause/addclause-py.lp create mode 100644 examples/clingo/blocksworld/README create mode 100644 examples/clingo/blocksworld/blocks_01.lp create mode 100644 examples/clingo/blocksworld/control_01.lua create mode 100644 examples/clingo/blocksworld/control_01.out create mode 100644 examples/clingo/blocksworld/lua.lp create mode 100644 examples/clingo/blocksworld/lua_interpret.lp create mode 100644 examples/clingo/blocksworld/world.lp create mode 100644 examples/clingo/commit/README create mode 100644 examples/clingo/commit/commit-lua.lp create mode 100644 examples/clingo/commit/commit-py.lp create mode 100644 examples/clingo/commit/encoding.lp create mode 100644 examples/clingo/consequences/README create mode 100644 examples/clingo/consequences/brave-lua.lp create mode 100644 examples/clingo/consequences/brave-py.lp create mode 100644 examples/clingo/consequences/example.lp create mode 100644 examples/clingo/context/README create mode 100644 examples/clingo/context/context-lua.lp create mode 100644 examples/clingo/context/context-py.lp create mode 100644 examples/clingo/context/encoding.lp create mode 100644 examples/clingo/controller-async/README create mode 100644 examples/clingo/controller-async/client.lp create mode 100755 examples/clingo/controller-async/controller.py create mode 100644 examples/clingo/controller-processes/README create mode 100644 examples/clingo/controller-processes/client.lp create mode 100644 examples/clingo/controller-processes/client.py create mode 100644 examples/clingo/controller-processes/server.py create mode 100644 examples/clingo/controller-threads/README create mode 100644 examples/clingo/controller-threads/client.lp create mode 100755 examples/clingo/controller-threads/controller.py create mode 100644 examples/clingo/cover/README create mode 100644 examples/clingo/cover/control-lua.lp create mode 100644 examples/clingo/cover/control-py.lp create mode 100644 examples/clingo/cover/cover.lp create mode 100644 examples/clingo/cover/instance.lp create mode 100644 examples/clingo/cover/preprocess.lp create mode 100644 examples/clingo/domains/README create mode 100644 examples/clingo/domains/domains-lua.lp create mode 100644 examples/clingo/domains/domains-py.lp create mode 100644 examples/clingo/domains/instance.lp create mode 100644 examples/clingo/dot-propagator/README create mode 100644 examples/clingo/dot-propagator/dot.lp create mode 100644 examples/clingo/dot-propagator/test.lp create mode 100644 examples/clingo/enum-assumption/README create mode 100644 examples/clingo/enum-assumption/example-lua.lp create mode 100644 examples/clingo/enum-assumption/example-py.lp create mode 100644 examples/clingo/expansion/GraphColouring/encodings/encoding.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0004-graph_colouring-125-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0005-graph_colouring-125-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0007-graph_colouring-125-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0008-graph_colouring-125-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0013-graph_colouring-130-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0021-graph_colouring-135-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0022-graph_colouring-135-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0023-graph_colouring-135-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0025-graph_colouring-135-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0032-graph_colouring-140-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0036-graph_colouring-140-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0039-graph_colouring-140-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0040-graph_colouring-140-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0046-graph_colouring-145-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0047-graph_colouring-145-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0048-graph_colouring-145-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0050-graph_colouring-145-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0056-graph_colouring-150-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0059-graph_colouring-150-0.lp create mode 100644 examples/clingo/expansion/GraphColouring/instances/0060-graph_colouring-150-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/encodings/encoding.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/100-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/102-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/114-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/115-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/119-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/127-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/153-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/154-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/156-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/161-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/175-partner_units_polynomial-75-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/180-partner_units_polynomial-47-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/188-partner_units_polynomial-57-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/196-partner_units_polynomial-59-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/26-partner_units_polynomial-60-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/52-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/58-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/69-partner_units_polynomial-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/91-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/PartnerUnits/instances/99-partner_units-100-0.lp create mode 100644 examples/clingo/expansion/README create mode 100755 examples/clingo/expansion/main.py create mode 100644 examples/clingo/external/README create mode 100644 examples/clingo/external/external-lua.lp create mode 100644 examples/clingo/external/external-py.lp create mode 100644 examples/clingo/external/external.lp create mode 100644 examples/clingo/iclingo/README create mode 100644 examples/clingo/iclingo/example.lp create mode 100644 examples/clingo/iclingo/incmode-int.lp create mode 100644 examples/clingo/iclingo/incmode-lua.lp create mode 100644 examples/clingo/iclingo/incmode-py.lp create mode 100644 examples/clingo/include/README create mode 100644 examples/clingo/include/encoding-lua.lp create mode 100644 examples/clingo/include/encoding-py.lp create mode 100644 examples/clingo/include/include.lp create mode 100644 examples/clingo/incqueens/README create mode 100644 examples/clingo/incqueens/incqueens-lua.lp create mode 100644 examples/clingo/incqueens/incqueens-py.lp create mode 100644 examples/clingo/incqueens/incqueens.lp create mode 100644 examples/clingo/itersolve/README create mode 100644 examples/clingo/itersolve/itersolve-lua.lp create mode 100644 examples/clingo/itersolve/itersolve-py.lp create mode 100644 examples/clingo/itersolve/program.lp create mode 100644 examples/clingo/load/README create mode 100644 examples/clingo/load/load-lua.lp create mode 100644 examples/clingo/load/load-py.lp create mode 100644 examples/clingo/load/program.lp create mode 100644 examples/clingo/onmodel/README create mode 100644 examples/clingo/onmodel/onmodel-lua.lp create mode 100644 examples/clingo/onmodel/onmodel-py.lp create mode 100644 examples/clingo/planning/README create mode 100644 examples/clingo/planning/convert.lp create mode 100755 examples/clingo/planning/convert.sh create mode 100644 examples/clingo/planning/encoding.lp create mode 100644 examples/clingo/planning/instances/coins01.lp create mode 100644 examples/clingo/planning/instances/comm02.lp create mode 100644 examples/clingo/planning/instances/comm03.lp create mode 100644 examples/clingo/planning/instances/comm05.lp create mode 100644 examples/clingo/planning/instances/uts01.lp create mode 100644 examples/clingo/planning/planning-lua.lp create mode 100644 examples/clingo/pydoc/README create mode 100755 examples/clingo/pydoc/pydoc-lib.py create mode 100644 examples/clingo/pydoc/pydoc.lp create mode 100644 examples/clingo/robots/README create mode 100644 examples/clingo/robots/board.lp create mode 100644 examples/clingo/robots/img/arrow_blue_east.gif create mode 100644 examples/clingo/robots/img/arrow_blue_north.gif create mode 100644 examples/clingo/robots/img/arrow_blue_south.gif create mode 100644 examples/clingo/robots/img/arrow_blue_west.gif create mode 100644 examples/clingo/robots/img/arrow_green_east.gif create mode 100644 examples/clingo/robots/img/arrow_green_north.gif create mode 100644 examples/clingo/robots/img/arrow_green_south.gif create mode 100644 examples/clingo/robots/img/arrow_green_west.gif create mode 100644 examples/clingo/robots/img/arrow_red_east.gif create mode 100644 examples/clingo/robots/img/arrow_red_north.gif create mode 100644 examples/clingo/robots/img/arrow_red_south.gif create mode 100644 examples/clingo/robots/img/arrow_red_west.gif create mode 100644 examples/clingo/robots/img/arrow_yellow_east.gif create mode 100644 examples/clingo/robots/img/arrow_yellow_north.gif create mode 100644 examples/clingo/robots/img/arrow_yellow_south.gif create mode 100644 examples/clingo/robots/img/arrow_yellow_west.gif create mode 100644 examples/clingo/robots/img/moon_blue.gif create mode 100644 examples/clingo/robots/img/moon_green.gif create mode 100644 examples/clingo/robots/img/moon_red.gif create mode 100644 examples/clingo/robots/img/moon_yellow.gif create mode 100644 examples/clingo/robots/img/move_blue_east.gif create mode 100644 examples/clingo/robots/img/move_blue_north.gif create mode 100644 examples/clingo/robots/img/move_blue_south.gif create mode 100644 examples/clingo/robots/img/move_blue_west.gif create mode 100644 examples/clingo/robots/img/move_green_east.gif create mode 100644 examples/clingo/robots/img/move_green_north.gif create mode 100644 examples/clingo/robots/img/move_green_south.gif create mode 100644 examples/clingo/robots/img/move_green_west.gif create mode 100644 examples/clingo/robots/img/move_red_east.gif create mode 100644 examples/clingo/robots/img/move_red_north.gif create mode 100644 examples/clingo/robots/img/move_red_south.gif create mode 100644 examples/clingo/robots/img/move_red_west.gif create mode 100644 examples/clingo/robots/img/move_yellow_east.gif create mode 100644 examples/clingo/robots/img/move_yellow_north.gif create mode 100644 examples/clingo/robots/img/move_yellow_south.gif create mode 100644 examples/clingo/robots/img/move_yellow_west.gif create mode 100644 examples/clingo/robots/img/random_robot.gif create mode 100644 examples/clingo/robots/img/robot_blue.gif create mode 100644 examples/clingo/robots/img/robot_green.gif create mode 100644 examples/clingo/robots/img/robot_red.gif create mode 100644 examples/clingo/robots/img/robot_yellow.gif create mode 100644 examples/clingo/robots/img/saturn_blue.gif create mode 100644 examples/clingo/robots/img/saturn_green.gif create mode 100644 examples/clingo/robots/img/saturn_red.gif create mode 100644 examples/clingo/robots/img/saturn_yellow.gif create mode 100644 examples/clingo/robots/img/star_blue.gif create mode 100644 examples/clingo/robots/img/star_green.gif create mode 100644 examples/clingo/robots/img/star_red.gif create mode 100644 examples/clingo/robots/img/star_yellow.gif create mode 100644 examples/clingo/robots/img/sun_blue.gif create mode 100644 examples/clingo/robots/img/sun_green.gif create mode 100644 examples/clingo/robots/img/sun_red.gif create mode 100644 examples/clingo/robots/img/sun_yellow.gif create mode 100644 examples/clingo/robots/img/tile_left.gif create mode 100644 examples/clingo/robots/img/tile_right.gif create mode 100644 examples/clingo/robots/img/wall_north.gif create mode 100644 examples/clingo/robots/img/wall_west.gif create mode 100644 examples/clingo/robots/robots.lp create mode 100755 examples/clingo/robots/visualize.py create mode 100644 examples/clingo/setconf/README create mode 100644 examples/clingo/setconf/setconf-lua.lp create mode 100644 examples/clingo/setconf/setconf-py.lp create mode 100644 examples/clingo/solitaire/README create mode 100644 examples/clingo/solitaire/instance.lp create mode 100644 examples/clingo/solitaire/solitaire.lp create mode 100755 examples/clingo/solitaire/visualize.py create mode 100644 examples/clingo/solve-async/README create mode 100644 examples/clingo/solve-async/program.lp create mode 100644 examples/clingo/solve-async/solve-async-py.lp create mode 100644 examples/clingo/stats/README create mode 100644 examples/clingo/stats/example.lp create mode 100644 examples/clingo/stats/stats-lua.lp create mode 100644 examples/clingo/stats/stats-py.lp create mode 100644 examples/clingo/unblock/README create mode 100644 examples/clingo/unblock/inst1.lp create mode 100644 examples/clingo/unblock/inst2.lp create mode 100644 examples/clingo/unblock/inst3.lp create mode 100644 examples/clingo/unblock/inst4.lp create mode 100644 examples/clingo/unblock/inst5.lp create mode 100644 examples/clingo/unblock/unblock.lp create mode 100755 examples/clingo/unblock/visualize.py create mode 100644 examples/gringo/acyc/README create mode 100644 examples/gringo/acyc/encoding.lp create mode 100644 examples/gringo/acyc/instance.lp create mode 100644 examples/gringo/ast/README create mode 100644 examples/gringo/ast/example.lp create mode 100644 examples/gringo/ast/visitor.lp create mode 100644 examples/gringo/gbie/README create mode 100644 examples/gringo/gbie/gbie1.lp create mode 100644 examples/gringo/gbie/gbie2.lp create mode 100644 examples/gringo/gbie/instances/sat_01.lp create mode 100644 examples/gringo/gbie/instances/sat_02.lp create mode 100644 examples/gringo/gbie/instances/sat_03.lp create mode 100644 examples/gringo/gbie/instances/unsat_01.lp create mode 100644 examples/gringo/gbie/instances/unsat_02.lp create mode 100644 examples/gringo/project/README create mode 100644 examples/gringo/project/example.lp create mode 100644 examples/gringo/queens/README create mode 100644 examples/gringo/queens/queens1.lp create mode 100644 examples/gringo/queens/queens2.lp create mode 100644 examples/gringo/rec-cond/README create mode 100644 examples/gringo/rec-cond/encoding.lp create mode 100644 examples/gringo/rec-cond/instance.lp create mode 100644 examples/gringo/subset/README create mode 100644 examples/gringo/subset/example.lp create mode 100644 examples/gringo/toh/README create mode 100644 examples/gringo/toh/tohE.lp create mode 100644 examples/gringo/toh/tohI.lp create mode 100644 examples/reify/README create mode 100644 examples/reify/example1.lp create mode 100644 examples/reify/example2.lp create mode 100644 examples/reify/meta.lp create mode 100644 examples/reify/metaD.lp create mode 100644 examples/reify/metaO.lp create mode 100755 examples/test.sh create mode 100644 libclasp/clasp/asp_preprocessor.h create mode 100644 libclasp/clasp/cb_enumerator.h create mode 100644 libclasp/clasp/clasp_facade.h create mode 100644 libclasp/clasp/claspfwd.h create mode 100644 libclasp/clasp/clause.h create mode 100644 libclasp/clasp/cli/clasp_cli_configs.inl create mode 100644 libclasp/clasp/cli/clasp_cli_options.inl create mode 100644 libclasp/clasp/cli/clasp_options.h create mode 100644 libclasp/clasp/cli/clasp_output.h create mode 100644 libclasp/clasp/cli/clifwd.h create mode 100644 libclasp/clasp/clingo.h create mode 100644 libclasp/clasp/constraint.h create mode 100644 libclasp/clasp/dependency_graph.h create mode 100644 libclasp/clasp/enumerator.h create mode 100644 libclasp/clasp/heuristics.h create mode 100644 libclasp/clasp/literal.h create mode 100644 libclasp/clasp/logic_program.h create mode 100644 libclasp/clasp/logic_program_types.h create mode 100644 libclasp/clasp/lookahead.h create mode 100644 libclasp/clasp/minimize_constraint.h create mode 100644 libclasp/clasp/model_enumerators.h create mode 100644 libclasp/clasp/parallel_solve.h create mode 100644 libclasp/clasp/parser.h create mode 100644 libclasp/clasp/pod_vector.h create mode 100644 libclasp/clasp/program_builder.h create mode 100644 libclasp/clasp/satelite.h create mode 100644 libclasp/clasp/shared_context.h create mode 100644 libclasp/clasp/solve_algorithms.h create mode 100644 libclasp/clasp/solver.h create mode 100644 libclasp/clasp/solver_strategies.h create mode 100644 libclasp/clasp/solver_types.h create mode 100644 libclasp/clasp/statistics.h create mode 100644 libclasp/clasp/unfounded_check.h create mode 100644 libclasp/clasp/util/atomic.h create mode 100644 libclasp/clasp/util/hash_map.h create mode 100644 libclasp/clasp/util/indexed_priority_queue.h create mode 100644 libclasp/clasp/util/left_right_sequence.h create mode 100644 libclasp/clasp/util/misc_types.h create mode 100644 libclasp/clasp/util/multi_queue.h create mode 100644 libclasp/clasp/util/mutex.h create mode 100644 libclasp/clasp/util/platform.h create mode 100644 libclasp/clasp/util/pod_vector.h create mode 100644 libclasp/clasp/util/thread.h create mode 100644 libclasp/clasp/util/timer.h create mode 100644 libclasp/clasp/util/type_manip.h create mode 100644 libclasp/clasp/weight_constraint.h create mode 100644 libclasp/libclasp.vcxproj create mode 100644 libclasp/libclasp.vcxproj.filters create mode 100644 libclasp/src/asp_preprocessor.cpp create mode 100644 libclasp/src/cb_enumerator.cpp create mode 100644 libclasp/src/clasp_facade.cpp create mode 100644 libclasp/src/clasp_options.cpp create mode 100644 libclasp/src/clasp_output.cpp create mode 100644 libclasp/src/clause.cpp create mode 100644 libclasp/src/clingo.cpp create mode 100644 libclasp/src/constraint.cpp create mode 100644 libclasp/src/dependency_graph.cpp create mode 100644 libclasp/src/enumerator.cpp create mode 100644 libclasp/src/heuristics.cpp create mode 100644 libclasp/src/logic_program.cpp create mode 100644 libclasp/src/logic_program_types.cpp create mode 100644 libclasp/src/lookahead.cpp create mode 100644 libclasp/src/minimize_constraint.cpp create mode 100644 libclasp/src/model_enumerators.cpp create mode 100644 libclasp/src/parallel_solve.cpp create mode 100644 libclasp/src/parser.cpp create mode 100644 libclasp/src/program_builder.cpp create mode 100644 libclasp/src/satelite.cpp create mode 100644 libclasp/src/shared_context.cpp create mode 100644 libclasp/src/solve_algorithms.cpp create mode 100644 libclasp/src/solver.cpp create mode 100644 libclasp/src/solver_strategies.cpp create mode 100644 libclasp/src/solver_types.cpp create mode 100644 libclasp/src/statistics.cpp create mode 100644 libclasp/src/timer.cpp create mode 100644 libclasp/src/unfounded_check.cpp create mode 100644 libclasp/src/weight_constraint.cpp create mode 100644 libclingo/clingo/clingocontrol.hh create mode 100644 libclingo/src/clingocontrol.cc create mode 100644 libclingo/tests/ast.cc create mode 100644 libclingo/tests/catch.hpp create mode 100644 libclingo/tests/clingo.cc create mode 100644 libclingo/tests/main.cc create mode 100644 libclingo/tests/propagator.cc create mode 100644 libclingo/tests/symbol.cc create mode 100644 libclingo/tests/tests.hh create mode 100644 libclingo/tests/variant.cc create mode 100644 libgringo/clingo.h create mode 100644 libgringo/clingo.hh create mode 100644 libgringo/gringo/backend.hh create mode 100644 libgringo/gringo/backtrace.hh create mode 100644 libgringo/gringo/base.hh create mode 100644 libgringo/gringo/bug.hh create mode 100644 libgringo/gringo/clonable.hh create mode 100644 libgringo/gringo/comparable.hh create mode 100644 libgringo/gringo/control.hh create mode 100644 libgringo/gringo/domain.hh create mode 100644 libgringo/gringo/graph.hh create mode 100644 libgringo/gringo/ground/binders.hh create mode 100644 libgringo/gringo/ground/dependency.hh create mode 100644 libgringo/gringo/ground/instantiation.hh create mode 100644 libgringo/gringo/ground/literal.hh create mode 100644 libgringo/gringo/ground/literals.hh create mode 100644 libgringo/gringo/ground/program.hh create mode 100644 libgringo/gringo/ground/statement.hh create mode 100644 libgringo/gringo/ground/statements.hh create mode 100644 libgringo/gringo/ground/types.hh create mode 100644 libgringo/gringo/hash_set.hh create mode 100644 libgringo/gringo/hashable.hh create mode 100644 libgringo/gringo/indexed.hh create mode 100644 libgringo/gringo/input/aggregate.hh create mode 100644 libgringo/gringo/input/aggregates.hh create mode 100644 libgringo/gringo/input/groundtermparser.hh create mode 100644 libgringo/gringo/input/literal.hh create mode 100644 libgringo/gringo/input/literals.hh create mode 100644 libgringo/gringo/input/nongroundparser.hh create mode 100644 libgringo/gringo/input/program.hh create mode 100644 libgringo/gringo/input/programbuilder.hh create mode 100644 libgringo/gringo/input/statement.hh create mode 100644 libgringo/gringo/input/theory.hh create mode 100644 libgringo/gringo/input/types.hh create mode 100644 libgringo/gringo/intervals.hh create mode 100644 libgringo/gringo/lexerstate.hh create mode 100644 libgringo/gringo/locatable.hh create mode 100644 libgringo/gringo/logger.hh create mode 100644 libgringo/gringo/lua.hh create mode 100644 libgringo/gringo/output/aggregates.hh create mode 100644 libgringo/gringo/output/backends.hh create mode 100644 libgringo/gringo/output/literal.hh create mode 100644 libgringo/gringo/output/literals.hh create mode 100644 libgringo/gringo/output/output.hh create mode 100644 libgringo/gringo/output/statement.hh create mode 100644 libgringo/gringo/output/statements.hh create mode 100644 libgringo/gringo/output/theory.hh create mode 100644 libgringo/gringo/output/types.hh create mode 100644 libgringo/gringo/primes.hh create mode 100644 libgringo/gringo/printable.hh create mode 100644 libgringo/gringo/python.hh create mode 100644 libgringo/gringo/safetycheck.hh create mode 100644 libgringo/gringo/scripts.hh create mode 100644 libgringo/gringo/symbol.hh create mode 100644 libgringo/gringo/term.hh create mode 100644 libgringo/gringo/terms.hh create mode 100644 libgringo/gringo/types.hh create mode 100644 libgringo/gringo/utility.hh create mode 100644 libgringo/gringo/version.hh create mode 100644 libgringo/src/backend.cc create mode 100644 libgringo/src/control.cc create mode 100644 libgringo/src/ground/instantiation.cc create mode 100644 libgringo/src/ground/literals.cc create mode 100644 libgringo/src/ground/program.cc create mode 100644 libgringo/src/ground/statements.cc create mode 100644 libgringo/src/input/aggregate.cc create mode 100644 libgringo/src/input/aggregates.cc create mode 100644 libgringo/src/input/groundtermgrammar.yy create mode 100644 libgringo/src/input/groundtermlexer.xh create mode 100644 libgringo/src/input/groundtermparser.cc create mode 100644 libgringo/src/input/literal.cc create mode 100644 libgringo/src/input/literals.cc create mode 100644 libgringo/src/input/nongroundgrammar.yy create mode 100644 libgringo/src/input/nongroundlexer.xch create mode 100644 libgringo/src/input/nongroundparser.cc create mode 100644 libgringo/src/input/program.cc create mode 100644 libgringo/src/input/programbuilder.cc create mode 100644 libgringo/src/input/statement.cc create mode 100644 libgringo/src/input/theory.cc create mode 100644 libgringo/src/lua.cc create mode 100644 libgringo/src/output/aggregates.cc create mode 100644 libgringo/src/output/literal.cc create mode 100644 libgringo/src/output/literals.cc create mode 100644 libgringo/src/output/output.cc create mode 100644 libgringo/src/output/statement.cc create mode 100644 libgringo/src/output/statements.cc create mode 100644 libgringo/src/output/theory.cc create mode 100644 libgringo/src/primes.cc create mode 100644 libgringo/src/python.cc create mode 100644 libgringo/src/scripts.cc create mode 100644 libgringo/src/symbol.cc create mode 100644 libgringo/src/term.cc create mode 100644 libgringo/src/terms.cc create mode 100644 libgringo/tests/catch.hpp create mode 100644 libgringo/tests/graph.cc create mode 100644 libgringo/tests/ground/dependency.cc create mode 100644 libgringo/tests/ground/grounder_helper.hh create mode 100644 libgringo/tests/ground/instantiation.cc create mode 100644 libgringo/tests/ground/literal.cc create mode 100644 libgringo/tests/ground/program.cc create mode 100644 libgringo/tests/ground/theory.cc create mode 100644 libgringo/tests/input/aggregate.cc create mode 100644 libgringo/tests/input/aggregate_helper.hh create mode 100644 libgringo/tests/input/lit_helper.hh create mode 100644 libgringo/tests/input/literal.cc create mode 100644 libgringo/tests/input/nongroundgrammar.cc create mode 100644 libgringo/tests/input/nongroundlexer.cc create mode 100644 libgringo/tests/input/parse_term.cc create mode 100644 libgringo/tests/input/program.cc create mode 100644 libgringo/tests/input/programbuilder.cc create mode 100644 libgringo/tests/intervals.cc create mode 100644 libgringo/tests/lua.cc create mode 100644 libgringo/tests/main.cc create mode 100644 libgringo/tests/output/aspcomp13.cc create mode 100644 libgringo/tests/output/incremental.cc create mode 100644 libgringo/tests/output/lparse.cc create mode 100644 libgringo/tests/output/solver_helper.hh create mode 100644 libgringo/tests/output/theory.cc create mode 100644 libgringo/tests/output/warnings.cc create mode 100644 libgringo/tests/python.cc create mode 100644 libgringo/tests/safetycheck.cc create mode 100644 libgringo/tests/symbol.cc create mode 100644 libgringo/tests/term.cc create mode 100644 libgringo/tests/term_helper.hh create mode 100644 libgringo/tests/tests.hh create mode 100644 libgringo/tests/unique_vec.cc create mode 100644 libgringo/tests/utility.cc create mode 100644 liblp/potassco/aspif.h create mode 100644 liblp/potassco/aspif_text.h create mode 100644 liblp/potassco/basic_types.h create mode 100644 liblp/potassco/clingo.h create mode 100644 liblp/potassco/convert.h create mode 100644 liblp/potassco/match_basic_types.h create mode 100644 liblp/potassco/rule_utils.h create mode 100644 liblp/potassco/smodels.h create mode 100644 liblp/potassco/theory_data.h create mode 100644 liblp/src/aspif.cpp create mode 100644 liblp/src/aspif_text.cpp create mode 100644 liblp/src/clingo.cpp create mode 100644 liblp/src/convert.cpp create mode 100644 liblp/src/match_basic_types.cpp create mode 100644 liblp/src/rule_utils.cpp create mode 100644 liblp/src/smodels.cpp create mode 100644 liblp/src/theory_data.cpp create mode 100644 liblp/tests/CMakeLists.txt create mode 100644 liblp/tests/aspif.cpp create mode 100644 liblp/tests/catch.hpp create mode 100644 liblp/tests/common.h create mode 100644 liblp/tests/main.cpp create mode 100644 liblp/tests/smodels.cpp create mode 100644 liblp/tests/text.cpp create mode 100644 libprogram_opts/program_opts/application.h create mode 100644 libprogram_opts/program_opts/detail/alarm.h create mode 100644 libprogram_opts/program_opts/detail/notifier.h create mode 100644 libprogram_opts/program_opts/detail/refcountable.h create mode 100644 libprogram_opts/program_opts/detail/value_store.h create mode 100644 libprogram_opts/program_opts/errors.h create mode 100644 libprogram_opts/program_opts/mapped_value.h create mode 100644 libprogram_opts/program_opts/program_options.h create mode 100644 libprogram_opts/program_opts/string_convert.h create mode 100644 libprogram_opts/program_opts/typed_value.h create mode 100644 libprogram_opts/program_opts/value.h create mode 100644 libprogram_opts/program_opts/value_store.h create mode 100644 libprogram_opts/src/alarm.cpp create mode 100644 libprogram_opts/src/application.cpp create mode 100644 libprogram_opts/src/program_options.cpp create mode 100644 libprogram_opts/src/string_convert.cpp create mode 100644 libprogram_opts/src/value_store.cpp create mode 100644 libreify/reify/program.hh create mode 100644 libreify/reify/util.hh create mode 100644 libreify/src/program.cc create mode 100644 libreify/tests/catch.hpp create mode 100644 libreify/tests/main.cc create mode 100644 libreify/tests/program.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4df41fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +*.swp +.sconf_temp +.sconsign.dblite +build +*.pyc +doc +*.opendb +Debug +Release +ReleaseScript +.vs +*.db +*.vcxproj.user +x64 +libgringo/generated +homewv.sh +.nfs* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e7c186c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,33 @@ +# Use container-based distribution +sudo: false +language: c++ +matrix: + include: + - os: linux + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + - re2c + - liblua5.1-0-dev + - zsh + - os: osx + osx_image: xcode8 + +before_install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install lua bison re2c scons; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew link bison --force; fi + +script: + - mkdir build + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then echo "CXX = 'clang++'" > build/debug.py; else echo "CXX = 'g++-5'" > build/debug.py; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then echo "CC = 'clang'" >> build/debug.py; else echo "CC = 'gcc-5'" >> build/debug.py; fi + - echo "CXXFLAGS = ['-std=c++11', '-O2', '-W', '-Wall']" >> build/debug.py + - echo "LINKFLAGS = ['-std=c++11']" >> build/debug.py + - scons -j3 + - scons -j3 example cexample + - scons -j3 test diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 0000000..1a52428 --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,182 @@ +# This file is NOT licensed under the GPLv3, which is the license for the rest +# of YouCompleteMe. +# +# Here's the license text for this file: +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# For more information, please refer to + +import os +import os.path +import ycm_core + +# These are the compilation flags that will be used in case there's no +# compilation database set (by default, one is not set). +# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR. +flags = [ +'-Wall', +'-Wextra', +'-Werror', +'-Wno-long-long', +'-Wno-variadic-macros', +'-Wno-#pragma-messages', +'-fexceptions', +'-DNDEBUG', +'-xc++', +'-std=c++11', +'-stdlib=libc++', +'-Iapp/gringo', +'-Iapp/shared/include', +'-Iapp/clingo/src', +'-Ilibgringo', +'-Ilibgringo/src', +'-Ilibclingo', +'-Ilibcclingo', +'-Ilibreify', +'-Ilibreify/src', +'-Iliblp', +'-Iliblpconvert', +'-Ilibpotassco', +'-Ilibclasp', +'-Ilibprogram_opts', +'-Ibuild/debug/libgringo', +'-Ibuild/debug/libgringo/src', +'-Ibuild/debug/libreify', +'-Ibuild/debug/libreify/src', +'-I{home}/local/opt/libcxx/include'.format(home=os.path.expanduser("~")), +'-I{home}/local/opt/libcxx/include/c++/v1'.format(home=os.path.expanduser("~")), +'-I/home/wv/bin/linux/64/gcc-4.9/include/c++/v1', +'-Ilibgringo/tests', +'-I/usr/include/python2.7', +'-I/usr/include/lua5.1', +'-DWITH_PYTHON', +'-DWITH_LUA', +'-DWITH_THREADS=1', +'-DCLASP_USE_STD_THREAD=1' +] + + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# You can get CMake to generate this file for you by adding: +# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 ) +# to your CMakeLists.txt file. +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = '' + +if os.path.exists( compilation_database_folder ): + database = ycm_core.CompilationDatabase( compilation_database_folder ) +else: + database = None + +SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] + +def DirectoryOfThisScript(): + return os.path.dirname( os.path.abspath( __file__ ) ) + + +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return list( flags ) + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + new_flag = os.path.join( working_directory, flag ) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith( path_flag ): + path = flag[ len( path_flag ): ] + new_flag = path_flag + os.path.join( working_directory, path ) + break + + if new_flag: + new_flags.append( new_flag ) + return new_flags + + +def IsHeaderFile( filename ): + extension = os.path.splitext( filename )[ 1 ] + return extension in [ '.h', '.hxx', '.hpp', '.hh' ] + + +def GetCompilationInfoForFile( filename ): + # The compilation_commands.json file generated by CMake does not have entries + # for header files. So we do our best by asking the db for flags for a + # corresponding source file, if any. If one exists, the flags for that file + # should be good enough. + if IsHeaderFile( filename ): + basename = os.path.splitext( filename )[ 0 ] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists( replacement_file ): + compilation_info = database.GetCompilationInfoForFile( + replacement_file ) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile( filename ) + + +def FlagsForFile( filename, **kwargs ): + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile( filename ) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_ ) + + # NOTE: This is just for YouCompleteMe; it's highly likely that your project + # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR + # ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. + try: + final_flags.remove( '-stdlib=libc++' ) + except ValueError: + pass + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) + + return { + 'flags': final_flags, + 'do_cache': True + } diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..0d884e2 --- /dev/null +++ b/CHANGES @@ -0,0 +1,141 @@ +clingo 5.1.0 + * update to clasp 3.2.1 + * add interface to add variables during propagation + * add interface to inspect ground rules (C/C++ only) + * add experimental interface to access clasp facade (C/C++ only) + * fixed smodels output (--output=smodels) +clingo 5.0.0 + * cleanup of python and lua API (breaks backwards compatibility) + * added new aspif output format replacing the old smodels format + * added input language support for clasp features + * #edge directives to add acyclicity constraints + * #project directives for enumeration of projected models + * #heuristic directives to steer clasp's search + * added theory atoms to write aggregate like constructs + * added stable C API documented with doxygen + * added experimental C++ API based on C API + * added theory propagator interface to clingo APIs + * added support for compilation with Visual Studio 2015 + * improved data structures to reduce memory consumption on typical input + * updated to clasp version 3.2.0 + patches +gringo/clingo 4.5.4 + * fixed bug when creating multiple Control objects + (affects lua only) + * fixed bug when trying to configure more solvers than in portfolio + (affects python only) + * fixed #disjoint constraints + * improved build scripts + * added option to keep facts in normal rules +gringo/clingo 4.5.3 + * fixed regression w.r.t gringo 4.4 in translation of conditional literals + * fixed projection in incremental programs + * fixed bug with (double) negative literals in minimize constraints +gringo/clingo 4.5.2 + * fixed memory leak in python API when enumerating models + * updated to clasp version 3.1.3 +gringo/clingo 4.5.1 + * ground term parser returns None/nil for undefined terms now + * added warning if a global variable occurs in a tuple of an aggregate element + * added auto detection of libraries + * changed option --update-domains into API function Control:cleanup_domains + * fixed domain cleanup when used with minimize constraints + * fixed grounding of recursive disjunctions (regression in 4.5.0) + * fixed Control.stats in lua bindings + * fixed a bug in clingo that would print 0-ary classically negated atoms wrongly +gringo/clingo 4.5.0 + * fixed grounding of recursive aggregates + * fixed usage of lua_next + * fixed bug when applying constant definitions + * updated underlying clasp to version 3.1.1 + * added support for negation in front of relation literals + * added option --update-domains to cleanup gringo's domains + using clasp's top-level assignment when solving incrementally + * added domain inspection to scripting interface + * added term parser to scripting interface + * added support for python 3 (experimental) + * added support for one elementary tuples + * added support for unary - operator in front of functions and symbols + * added support for recursive nonmonotone aggregate via translation + * added program reify to reify logic programs + * added option to rewrite minimize constaints for use with reify + * changed inbuilt iclingo mode + (breaks backwards compatibility) + * changed handling of pools, intervals, and undefined operations according to AG + (breaks backwards compatibility) + * changed handling of ==, it is treated like = now + * changed SolveFuture.interrupt to SolveFuture.cancel + (breaks backwards compatibility) +gringo/clingo 4.4.0 + * updated underlying clasp to version 3.1.0 + * this version brings numerous fixes regarding incremental solving + * scripting API changes + * ground takes a list of programs to ground now and immediately starts + grounding (breaks backwards compatibility) + * asolve has been renamed to solveAsync + (breaks backwards compatibility) + * the solver configuration is better integrated now + (breaks backwards compatibility) + * solver statistics are a property now + (breaks backwards compatibility) + * added a method to add clauses during solving + * added load method to load files + * added solveIter method to iterate over methods without using a callback + * added optional assumptions to solve/solveAsync/solveIter method + * enableEnumAssumption became a property + * added library that can be imported in python + * rules with fact heads where not simplified in all cases + * fixed grounding of recursive aggregates + * fixed translation of aggregates with multiple guards +gringo/clingo 4.3.0 + * fixed bug with incremental parameters in minimize constraints + * fixed handling of empty tuples + * fixed translation of conditional literals + * fixed translation of factual body aggregates + * fixed bug not properly recognizing aggregates as non-monotone + * fixed bug not properly grounding recursive head aggregates + * fixed bug with recursive negated aggregates + * fixed bug with head aggregates with multiple elements + * improved handling of conditional literals + * added method to get optimization values of model in scripting language + * clingo uses clasp 3.0 now +gringo/clingo 4.2.1 + * fixed bug in simplification of aggregates + * fixed bug with raw strings in macros + * fixed compilation issues with older glibc versions + * fixed output for enumeration of cautious consequences + * fixed bugs in clasp library + * fixed race in parallel model enumeration + * fixed incremental optimization + * fixed cleanup up of learnt constraints during incremental solving + * workaround for libstdc++'s bad choice for hash on 32bit arches +gringo/clingo 4.2 + * added clingo + * supports very flexible scripting support + * can cover iclingo and oclingo functionality now + * added stack traces to lua error messages + * added support for incremental optimization + * improved python error messages + * renamed gringo.Function to gringo.Fun + * removed luabind dependency + * removed boost-python dependency + * consistently use not instead of #not as keyword for negation + * fixed translation of conditions in head aggregates + * fixed replacement of constants + * fixed grounding of recursive head aggregates + * fixed translation of head aggregates + * fixed show statements for CSP variables (condition was ignored) + * fixed plain text output of body aggregates + * added a ton of new bugs +gringo 4.1 + * added scripting languages python and lua + * added -c option to define constants + * added constraints over integer variables + * linear constraints + * disjoint constraints + * show statements for constraint variables + * (experimental and subject to change) + * improved translation of disjunctions + * fixed include directives + * fixed preprocessing of definitions + * fixed lparse translation of optimization constructs + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..373728d --- /dev/null +++ b/INSTALL @@ -0,0 +1,213 @@ +Requirements +============ + +- a c++11 conforming compiler + gcc version 4.9 (earlier versions will not work) + clang version 3.1 (using either libstdc++ provided by gcc 4.9 or libc++) + other compilers might work +- the bison parser generator + version 3.0 is tested (produces warnings to stay backwards-compatible) + version 2.5 and newer should work (earlier versions will not work) +- the re2c lexer generator + version 0.13.5 is tested + newer versions should work +- the scons build system + version 2.2 is tested + version 2.1 and newer should work + +Optional Dependencies +--------------------- + +- the python script language (optional) + version 2.7 is tested +- the lua script language (optional) + version 5.1 is tested + version 5.2 should work + +Compilation +=========== + +Note that for building gringo/clingo/reify/lpconvert, you need a recent C++ +compiler. To build gringo and clingo in their default configurations in release +mode, run: + scons --build-dir=release + +There is no installation target. To use gringo, clingo, reify, or lpconvert use +the binaries/libraries in the build/release folder: + build/release/gringo + build/release/clingo + build/release/reify + build/release/lpconvert + +For enabling lua/python/threading support, please see the Enabling Scripting +Support Section. + +Troubleshooting +--------------- + +If configuration fails, always inspect the build log, e.g.: + build/release.log + +It contains all the compiler invocations performed when testing the +configuration, along with generated error messages. Typically, this makes it +very easy to fix the problem. + + +Build Options +============= + +To get an overview over the variables that can be set for building +gringo/clingo, please run: + scons --help + +You can edit build/release.py to edit these values. Make sure to generate the +file beforehand: + scons configure --build-dir=release + +The scons scripts try to automatically find libraries using python-config and +pkg-config. Relevant parts of the configuration are: + $ grep "PYTHON_CONFIG\|PKG_CONFIG" build/release.py + PYTHON_CONFIG = None + PKG_CONFIG = 'pkg-config' + +By default python-config is used to obtain compile and link flags for building +with python. This can be disabled by setting PYTHON_CONFIG to None to always +use pkg-config. + + +Enabling Scripting Support +-------------------------- + +By default the build script tries to automatically detect available libraries +on the system and sets the configuration accordingly. If detection fails, you +have to set the respective library names and (typically) the paths to the +includes. The relevant portions of the configuration file are: + $ grep "CPPPATH\|WITH_PYTHON\|WITH_LUA" build/release.py + CPPPATH = ['/usr/include/python2.7', '/usr/include/lua5.1'] + WITH_PYTHON = 'python2.7' + WITH_LUA = 'lua5.1' + +Make sure to match the version numbers above with what is installed on your +system. Depending on your system further paths might have to be adjusted - +e.g., LIBPATH if libraries are installed in non-default locations. + +Building the Python Module +-------------------------- + +If python support is enabled, the additional target pyclingo is available. + scons --build-dir=release pyclingo + +This will build a library called clingo that can be imported in python. Make +sure it is put somewhere under the PYTHONPATH. Then import clingo in your +python script. The module itself is documented using python's docstrings. + build/release/python/clingo.{so,dll,dylib} + +The documentation for the clingo module is available online: + https://potassco.org/clingo/ + +Building the Lua Module +----------------------- + +If lua support is enabled, the additional target pyclingo is available. + scons --build-dir=release luaclingo + +This will build a library called clingo that can be imported in lua: + build/release/lua/clingo.{so,dll,dylib} + +Enabling Threading +------------------ + +By default multi-threading is enabled using posix threads. The relevant part +in the configuration is: + $ grep "WITH_THREADS" build/release.py + WITH_THREADS = 'posix' + +Depending on your system further paths might have to be adjusted - e.g., +CPPPATH, LIBPATH if the library is installed in a non-default location. + + +Testing +======= + +The test target can be used to run unit and acceptance tests: + $ scons --build-dir=release test + +Notes for Windows Users +======================= + +With a few tweaks gringo/clingo can be compiled using the Mingw-w64 compiler. +The binaries on Sourceforge have been compiled with a Mingw-w64 based +cross-compiler. + +Additionally, gringo can be compiled under Windows using cygwin. All +additional software is available via cygwin and cygwinports. I cannot test +this myself because I do not have a Windows installation. You might encounter +problems. Patches to improve compatibility are welcome. + +Note that I had problems with cygwin's bison and had to resort to another bison +port (for some reason I had to delete the last line of the generated parser): + win flex-bison + +Relevant parts of the configuration: +$ grep "CXX\|CPPPATH\|WITH_PYTHON\|WITH_LUA" build/release.py +CXX = 'g++' +CPPPATH = ['/usr/include/python2.7'] +WITH_PYTHON = 'python2.7.dll' +WITH_LUA = 'lua.dll' + + +Notes for Mac Users +=================== + +gringo/clingo has successfully been built using software provided by macports. + +This are the relevant installed packages: + $ port installed \ + | grep "lua\|clang-3.3\|bison\|re2c\|scons\| python27" \ + | grep active + bison @2.7.1_0+universal (active) + clang-3.3 @3.3_1+analyzer+python27+universal (active) + python27 @2.7.5_1+universal (active) + lua @5.2.2_1+universal (active) + re2c @0.13.5_0 (active) + scons @2.3.0_0 (active) + +Relevant parts of the configuration: + $ grep "CXX\|CPPPATH\|WITH_PYTHON\|WITH_LUA\|LIBPATH\|WITH_THREADS\|BISON\|RE2C" build/release.py + CXX = '/opt/local/bin/clang++-mp-3.3' + CPPPATH = ['/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7', '/opt/local/include'] + LIBPATH = ['/opt/local/lib'] + BISON = '/opt/local/bin/bison' + RE2C = '/opt/local/bin/re2c' + WITH_PYTHON = 'python2.7' + WITH_LUA = 'lua' + WITH_THREADS = 'posix' + +Note that the clang and python versions provided by the latest Xcode release +can be used to compile gringo/clingo. The binaries provided on the github +page are built using these. + + +Links +===== + +http://clang.llvm.org/ +http://cygwin.com/ +http://cygwinports.com/ +http://gcc.gnu.org/ +http://libcxx.llvm.org/ +http://llvm.org/ +http://mingw-w64.sourceforge.net/ +https://potassco.org/ +https://potassco.org/clingo/ +https://github.com/potassco/ +https://github.com/potassco/clingo +http://re2c.org/ +https://github.com/philsquared/Catch +http://sourceforge.net/projects/winflexbison/ +http://virtualenv.pypa.io +http://www.gnu.org/software/bison/ +http://www.lua.org/ +http://www.macports.org/ +http://www.python.org/ +http://www.scons.org/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9b8fdc --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +Gringo is a grounder that, given an input program with first-order variables, +computes an equivalent ground (variable-free) program. Its output can be +processed further with answer set solver clasp. Starting with gringo series 5, +its output is no longer compatible with solvers like smodels or cmodels reading +smodels format. + +Clingo combines both gringo and clasp into a monolithic system. This way it +offers more control over the grounding and solving process than gringo and +clasp can offer individually: multi-shot solving. + +The Python and Lua clingo modules offer the functionality of clingo in the +respective scripting language. + +Reify is a small utility that reifies logic programs given in aspif format. +It produces a set of facts, which can be processed further with gringo. + +Lpconvert is a converter between gringo's aspif and smodels format. + +Please consult the following resources for further information: + + - CHANGES: changes between different releases + - INSTALL: installation instructions and software requirements + - examples: a folder with examples each having a focus on certain features + (many examples require clingo) + +For more information please visit the project website: + + http://potassco.org diff --git a/SConscript b/SConscript new file mode 100644 index 0000000..0ab4e7a --- /dev/null +++ b/SConscript @@ -0,0 +1,535 @@ +#!/usr/bin/python +# {{{1 GPL License + +# This file is part of gringo - a grounder for logic programs. +# Copyright (C) 2013 Roland Kaminski + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# {{{1 Preamble + +import os +import types +from os.path import join + +# {{{1 Auxiliary functions + +def find_files(env, path): + oldcwd = os.getcwd() + try: + os.chdir(Dir('#').abspath) + sources = [] + for root, dirnames, filenames in os.walk(path): + for filename in filenames: + if filename.endswith(".c") or filename.endswith(".cc") or filename.endswith(".cpp"): + sources.append(os.path.join(root, filename)) + if filename.endswith(".yy"): + target = os.path.join(root, filename[:-3], "grammar.cc") + source = "#"+os.path.join(root, filename) + sources.append(target) + env.Bison(target, source) + if filename.endswith(".xh"): + target = os.path.join(root, filename[:-3] + ".hh") + source = "#"+os.path.join(root, filename) + env.Re2c(target, source) + if filename.endswith(".xch"): + target = os.path.join(root, filename[:-4] + ".hh") + source = "#"+os.path.join(root, filename) + env.Re2cCond(target, source) + return sources + finally: + os.chdir(oldcwd) + +def shared(env, sources): + return [env.SharedObject(x) for x in sources] + +def bison_emit(target, source, env): + path = os.path.split(str(target[0]))[0]; + target += [os.path.join(path, "grammar.hh"), os.path.join(path, "grammar.out")] + return target, source + +def CheckBison(context): + context.Message('Checking for bison 2.5... ') + (result, output) = context.TryAction("${BISON} ${SOURCE} -o ${TARGET}", '%require "2.5"\n%%\nstart:', ".y") + context.Result(result) + return result + +def CheckRe2c(context): + context.Message('Checking for re2c... ') + (result, output) = context.TryAction("${RE2C} ${SOURCE}", '', ".x") + context.Result(result) + return result + +def CheckMyFun(context, name, code, header): + source = header + "\nint main() {\n" + code + "\nreturn 0; }" + context.Message('Checking for C++ function ' + name + '()... ') + result = context.TryLink(source, '.cc') + context.Result(result) + return result + +def CheckThreadLocal(context): + source = "thread_local int x = 0; \nint main() {\nreturn x; }" + context.Message('Checking for C++ thread_local keyword... ') + result = context.TryLink(source, '.cc') + context.Result(result) + return result + +def CheckLibs(context, name, libs, header): + context.Message("Checking for C++ library {0}... ".format(name)) + libs = [libs] if isinstance(libs, types.StringTypes) else libs + old = context.env["LIBS"][:] + for lib in libs: + if os.path.isabs(lib): + context.env.Append(LIBS=File(lib)) + else: + context.env.Append(LIBS=lib) + result = context.TryLink("#include <{0}>\nint main() {{ }}\n".format(header), '.cc') + context.Result(result) + if result == 0: + context.env["LIBS"] = old + return result + +def CheckWithPkgConfig(context, name, versions): + context.Message("Auto-detecting {0} ({1})... ".format(name, context.env["PKG_CONFIG"])) + result = False + if context.env['PKG_CONFIG'] is not None and \ + context.TryAction('${PKG_CONFIG} --atleast-pkgconfig-version=0')[0]: + for version in versions: + if context.TryAction('${{PKG_CONFIG}} --exists "{0}"'.format(version))[0]: + context.env.ParseConfig('${{PKG_CONFIG}} --cflags --libs {0}'.format(version)) + result = True + break + context.Result(result) + return result + +def CheckPythonConfig(context): + context.Message("Auto-detecting python ({0})... ".format(context.env['PYTHON_CONFIG'])) + if context.env['PYTHON_CONFIG'] is not None: + result = context.TryAction('${PYTHON_CONFIG} --ldflags --includes')[0] + if result: + content = context.env.backtick('{0} --ldflags --includes'.format(context.env['PYTHON_CONFIG'])) + flags = [] + for option in content.split(): + if option.startswith("-I"): flags.append(option) + if option.startswith("-L"): flags.append(option) + if option.startswith("-l"): flags.append(option) + old_libs = context.env['LIBS'][:] + old_cpppath = context.env['CPPPATH'][:] + old_libpath = context.env['LIBPATH'][:] + context.env.MergeFlags(' '.join(flags)) + result = context.TryLink("#include \nint main() { }\n", ".cc") + if not result: + context.env['LIBS'] = old_libs + context.env['LIBPATH'] = old_libpath + context.env['CPPPATH'] = old_cpppath + else: + result = False + context.Result(result) + return result + +# {{{1 Basic environment + +Import('env') + +base_env = env.Clone() + +bison_action = Action("${BISON} -r all --report-file=${str(TARGET)[:-3]}.out -o ${TARGET} ${SOURCE} ${test}") + +bison_builder = Builder( + action = bison_action, + emitter = bison_emit, + suffix = '.cc', + src_suffix = '.yy' + ) + +re2c_action = Action("${RE2C} -o ${TARGET} ${SOURCE}") + +re2c_builder = Builder( + action = re2c_action, + suffix = '.hh', + src_suffix = '.xh' + ) + +re2c_cond_action = Action("${RE2C} -c -o ${TARGET} ${SOURCE}") + +re2c_cond_builder = Builder( + action = re2c_cond_action, + suffix = '.hh', + src_suffix = '.xch' + ) + +env['ENV']['PATH'] = os.environ['PATH'] +if 'LD_LIBRARY_PATH' in os.environ: env['ENV']['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH'] +env['BUILDERS']['Bison'] = bison_builder +env['BUILDERS']['Re2c'] = re2c_builder +env['BUILDERS']['Re2cCond'] = re2c_cond_builder + +# {{{1 Gringo specific configuration + +log_file = join("build", GetOption('build_dir') + ".log") +conf = Configure(env, custom_tests={'CheckBison' : CheckBison, 'CheckRe2c' : CheckRe2c, 'CheckMyFun' : CheckMyFun, 'CheckLibs' : CheckLibs, 'CheckWithPkgConfig' : CheckWithPkgConfig, 'CheckPythonConfig' : CheckPythonConfig, 'CheckThreadLocal' : CheckThreadLocal}, log_file=log_file) +DEFS = {} +failure = False + +if not conf.CheckBison(): + print 'error: no usable bison version found' + failure = True + +if not conf.CheckRe2c(): + print 'error: no usable re2c version found' + failure = True + +if not conf.CheckCXX(): + print 'error: no usable C++ compiler found' + print "Please check the log file for further information: " + log_file + Exit(1) + +if not conf.CheckSHCXX(): + print 'error: no usable (shared) C++ compiler found' + print "Please check the log file for further information: " + log_file + Exit(1) + +if not conf.CheckThreadLocal(): + DEFS["GRINGO_NO_THREAD_LOCAL"] = 1 + +with_python = False +if env['WITH_PYTHON'] == "auto": + if conf.CheckPythonConfig() or \ + conf.CheckWithPkgConfig("python", ["python", "python2", "python-2.7", "python-2.6", "python-2.5", "python-2.4", "python3", "python-3.4", "python-3.3", "python-3.2", "python-3.1", "python-3.0"]): + with_python = True + DEFS["WITH_PYTHON"] = 1 +elif env['WITH_PYTHON']: + if not conf.CheckLibs("python", env['WITH_PYTHON'], "Python.h"): + print 'error: python library not found' + failure = True + else: + with_python = True + DEFS["WITH_PYTHON"] = 1 + +with_lua = False +if env['WITH_LUA'] == "auto": + if conf.CheckWithPkgConfig("lua", ["lua", "lua5.1", "lua-5.1", "lua5.2", "lua-5.2", "lua5.3", "lua-5.3"]): + with_lua = True + DEFS["WITH_LUA"] = 1 +elif env['WITH_LUA']: + if not conf.CheckLibs("lua", env['WITH_LUA'], "lua.hpp"): + print 'error: lua library not found' + failure = True + else: + with_lua = True + DEFS["WITH_LUA"] = 1 + +if not conf.CheckMyFun('snprintf', 'char buf[256]; snprintf (buf,256,"");', '#include '): + if conf.CheckMyFun('__builtin_snprintf', 'char buf[256]; __builtin_snprintf (buf,256,"");', '#include '): + DEFS['snprintf']='__builtin_snprintf' + +if not conf.CheckMyFun('vsnprintf', 'char buf[256]; va_list args; vsnprintf (buf,256,"", args);', "#include \n#include "): + if conf.CheckMyFun('__builtin_vsnprintf', 'char buf[256]; va_list args; __builtin_vsnprintf (buf,256,"", args);', "#include \n#include "): + DEFS['vsnprintf']='__builtin_vsnprintf' + +if not conf.CheckMyFun('std::to_string', 'std::to_string(10);', "#include "): + DEFS['MISSING_STD_TO_STRING']=1 + +env = conf.Finish() +env.PrependUnique(LIBPATH=[Dir('.')]) +env.Append(CPPDEFINES=DEFS) + +# {{{1 Clasp specific configuration + +claspEnv = env.Clone() +claspConf = Configure(claspEnv, custom_tests = {'CheckLibs' : CheckLibs, 'CheckWithPkgConfig' : CheckWithPkgConfig}, log_file = join("build", GetOption('build_dir') + ".log")) +DEFS = {} + +DEFS["WITH_THREADS"] = 0 +if env['WITH_THREADS'] is not None: + DEFS["WITH_THREADS"] = 1 + DEFS["CLASP_USE_STD_THREAD"] = 1 + if env['WITH_THREADS'] == "posix": + # Note: configuration differs between gcc and clang here + # gcc needs -pthread, clang needs -lpthread + claspConf.env.Append(CPPFLAGS=["-pthread"]) + claspConf.env.Append(LIBS=["pthread"]) + elif env['WITH_THREADS'] == "windows": + pass # nohing to do + else: + print 'error: unknown thread model' + failure = True + + +claspEnv = claspConf.Finish() +claspEnv.Append(CPPDEFINES=DEFS) + +# {{{1 Check configuration + +if failure: + print "Please check the log file for further information: " + log_file + Exit(1) + +# {{{1 Opts: Library + +LIBOPTS_SOURCES = find_files(env, 'libprogram_opts/src') +LIBOPTS_HEADERS = [Dir('#libprogram_opts'), Dir('#libprogram_opts/src')] + +optsEnv = env.Clone() +optsEnv.Append(CPPPATH = LIBOPTS_HEADERS) + +optsLib = optsEnv.StaticLibrary('libprogram_opts', LIBOPTS_SOURCES) +optsLibS = optsEnv.StaticLibrary('libprogram_opts_shared', shared(optsEnv, LIBOPTS_SOURCES)) + +# {{{1 Lp: Library + +LIBLP_SOURCES = find_files(env, 'liblp/src') +LIBLP_HEADERS = [Dir('#liblp'), Dir('#liblp/src')] + +lpEnv = env.Clone() +lpEnv.Append(CPPPATH = LIBLP_HEADERS) + +lpLib = lpEnv.StaticLibrary('liblp', LIBLP_SOURCES) +lpLibS = lpEnv.StaticLibrary('liblp_shared', shared(lpEnv, LIBLP_SOURCES)) + +# {{{1 Clasp: Library + +LIBCLASP_SOURCES = find_files(env, 'libclasp/src') +LIBCLASP_HEADERS = [Dir('#libclasp'), Dir('#libclasp/src')] + LIBOPTS_HEADERS + LIBLP_HEADERS + +claspEnv.Append(CPPPATH = LIBCLASP_HEADERS) + +claspLib = claspEnv.StaticLibrary('libclasp', LIBCLASP_SOURCES) +claspLibS = claspEnv.StaticLibrary('libclasp_shared', shared(claspEnv, LIBCLASP_SOURCES)) + +# {{{1 Gringo: Library + +LIBGRINGO_SOURCES = find_files(env, 'libgringo/src') +LIBGRINGO_HEADERS = [Dir('#libgringo'), 'libgringo/src', 'libreify'] + LIBLP_HEADERS + +gringoEnv = env.Clone() +gringoEnv.Append(CPPPATH = LIBGRINGO_HEADERS) + +gringoLib = gringoEnv.StaticLibrary('libgringo', LIBGRINGO_SOURCES) +gringoLibS = gringoEnv.StaticLibrary('libgringo_shared', shared(gringoEnv, LIBGRINGO_SOURCES)) + +# {{{1 Reify: Library + +LIBREIFY_SOURCES = find_files(env, 'libreify/src') +LIBREIFY_HEADERS = [Dir('#libreify'), 'libreify/src'] + LIBGRINGO_HEADERS + +reifyEnv = env.Clone() +reifyEnv.Append(CPPPATH = LIBREIFY_HEADERS) + +reifyLib = reifyEnv.StaticLibrary('libreify', LIBREIFY_SOURCES) +reifyLibS = reifyEnv.StaticLibrary('libreify_shared', shared(reifyEnv, LIBREIFY_SOURCES)) + +# {{{1 Clingo: Library + +LIBCLINGO_SOURCES = find_files(env, 'libclingo/src') +LIBCLINGO_HEADERS = [Dir('#libclingo')] + LIBGRINGO_HEADERS + LIBCLASP_HEADERS + +clingoEnv = claspEnv.Clone() +clingoEnv.Append(CPPPATH = LIBCLINGO_HEADERS) + +clingoLib = clingoEnv.StaticLibrary('libclingo', LIBCLINGO_SOURCES) +clingoLibS = clingoEnv.StaticLibrary('libclingo_shared', shared(clingoEnv, LIBCLINGO_SOURCES)) + +clingoSharedEnv = clingoEnv.Clone() +clingoSharedEnv.Prepend(LIBS = [gringoLibS, reifyLibS, claspLibS, optsLibS, lpLibS]) +clingoSharedLib = clingoSharedEnv.SharedLibrary('libclingo', shared(clingoEnv, LIBCLINGO_SOURCES)) +clingoSharedEnv.Alias('libclingo', clingoSharedLib) + +# {{{1 Gringo: Program + +GRINGO_SOURCES = find_files(env, 'app/gringo') + +gringoProgramEnv = gringoEnv.Clone() +gringoProgramEnv.Append(CPPPATH = LIBOPTS_HEADERS) +gringoProgramEnv.Prepend(LIBS=[ gringoLib, optsLib, reifyLib, lpLib ]) + +gringoProgram = gringoProgramEnv.Program('gringo', GRINGO_SOURCES) +gringoProgramEnv.Alias('gringo', gringoProgram) + +if not env.GetOption('clean'): + Default(gringoProgram) + +# {{{1 Clingo: Program + +CLINGO_SOURCES = find_files(env, 'app/clingo/src') + +clingoProgramEnv = claspEnv.Clone() +clingoProgramEnv.Prepend(LIBS=[ clingoLib, gringoLib, reifyLib, claspLib, optsLib, lpLib ]) +clingoProgramEnv.Append(CPPPATH = LIBCLINGO_HEADERS) + +clingoProgram = clingoProgramEnv.Program('clingo', CLINGO_SOURCES) +clingoProgramEnv.Alias('clingo', clingoProgram) + +if not env.GetOption('clean'): + Default(clingoProgram) + +# {{{1 Web: Program + +WEB_SOURCES = [ clingoProgramEnv.Object(x) for x in find_files(env, 'app/clingo/src') if x != 'app/clingo/src/main.cc' ] + find_files(env, 'app/web') + +webProgramEnv = claspEnv.Clone() +webProgramEnv.Prepend(LIBS=[ clingoLib, gringoLib, reifyLib, claspLib, optsLib, lpLib ]) +webProgramEnv.Append(CPPPATH = LIBCLINGO_HEADERS + [Dir('#app/clingo/src')]) + +webProgram = webProgramEnv.Program('clingo.html', WEB_SOURCES) +webProgramEnv.Alias('web', webProgram) + +# {{{1 Example: Program + +EXAMPLE_SOURCES = find_files(env, 'app/example') + +exampleProgramEnv = claspEnv.Clone() +exampleProgramEnv.Prepend(LIBS=["clingo"]) +exampleProgramEnv.Append(CPPPATH = LIBCLINGO_HEADERS) + +exampleProgram = exampleProgramEnv.Program('example', EXAMPLE_SOURCES) +exampleProgramEnv.Alias('example', exampleProgram) + +# {{{1 C-Example: Program + +CEXAMPLE_SOURCES = find_files(env, 'app/cexample') + +cexampleProgramEnv = base_env.Clone() +cexampleProgramEnv.Prepend(LIBPATH=[Dir(".")]) +cexampleProgramEnv.Prepend(LIBS=["clingo"]) +cexampleProgramEnv["LINKFLAGS"] = base_env["CLINKFLAGS"] +cexampleProgramEnv.Append(CPPPATH = ["libgringo"]) + +cexampleProgram = cexampleProgramEnv.Program('cexample', CEXAMPLE_SOURCES) +cexampleProgramEnv.Alias('cexample', cexampleProgram) + +# {{{1 Reify: Program + +REIFY_SOURCES = find_files(env, 'app/reify') + +reifyProgramEnv = reifyEnv.Clone() +reifyProgramEnv.Prepend(LIBS=[ reifyLib, optsLib, lpLib ]) +reifyProgramEnv.Append(CPPPATH = LIBOPTS_HEADERS) + +reifyProgram = reifyProgramEnv.Program('reify', REIFY_SOURCES) +reifyProgramEnv.Alias('reify', reifyProgram) + +if not env.GetOption('clean'): + Default(reifyProgram) + +# {{{1 Lpconvert: Program + +LPCONVERT_SOURCES = find_files(env, 'app/lpconvert') +LPCONVERT_HEADERS = [Dir('#libprogram_opts')] + +lpconvertProgramEnv = lpEnv.Clone() +lpconvertProgramEnv.Prepend(LIBS=[ lpLib, optsLib ]) +lpconvertProgramEnv.Append(CPPPATH = LPCONVERT_HEADERS) + +lpconvertProgram = lpconvertProgramEnv.Program('lpconvert', LPCONVERT_SOURCES) +lpconvertProgramEnv.Alias('lpconvert', lpconvertProgram) + +if not env.GetOption('clean'): + Default(lpconvertProgram) + +# {{{1 PyClingo + LuaClingo + +if with_python: + PYCLINGO_SOURCES = find_files(env, 'app/pyclingo/src') + + pyclingoEnv = clingoEnv.Clone() + pyclingoEnv["LIBPREFIX"] = "" + pyclingoEnv.Prepend(LIBS = [clingoLibS, gringoLibS, claspLibS, optsLibS, reifyLibS, lpLibS]) + + pyclingo = pyclingoEnv.SharedLibrary('python/clingo.so', PYCLINGO_SOURCES) + pyclingoEnv.Alias('pyclingo', pyclingo) + if not env.GetOption('clean'): + Default(pyclingo) + +if with_lua: + LUACLINGO_SOURCES = find_files(env, 'app/luaclingo/src') + + luaclingoEnv = clingoEnv.Clone() + luaclingoEnv["LIBPREFIX"] = "" + luaclingoEnv.Prepend(LIBS = [clingoLibS, gringoLibS, claspLibS, optsLibS, reifyLibS, lpLibS]) + + luaclingo = luaclingoEnv.SharedLibrary('lua/clingo.so', LUACLINGO_SOURCES) + luaclingoEnv.Alias('luaclingo', luaclingo) + if not env.GetOption('clean'): + Default(luaclingo) + +# {{{1 Gringo: Tests + +TEST_LIBGRINGO_SOURCES = find_files(env, 'libgringo/tests') + +gringoTestEnv = claspEnv.Clone() +gringoTestEnv.Append(CPPPATH = LIBGRINGO_HEADERS + LIBCLASP_HEADERS) +gringoTestEnv.Prepend(LIBS = [gringoLib, claspLib, reifyLib, lpLib]) + +testGringoProgram = gringoTestEnv.Program('test_libgringo', TEST_LIBGRINGO_SOURCES) +AlwaysBuild(gringoTestEnv.Alias('test-libgringo', [testGringoProgram], testGringoProgram[0].path + (" " + GetOption("test_case") if GetOption("test_case") else ""))) +if 'libgringo' in env['TESTS']: + AlwaysBuild(gringoTestEnv.Alias('test', [testGringoProgram], testGringoProgram[0].path + (" " + GetOption("test_case") if GetOption("test_case") else ""))) + +# {{{1 Reify: Tests + +TEST_LIBREIFY_SOURCES = find_files(env, 'libreify/tests') + +reifyTestEnv = env.Clone() +reifyTestEnv.Append(CPPPATH = LIBREIFY_HEADERS) +reifyTestEnv.Prepend(LIBS = [reifyLib, lpLib]) + +testReifyProgram = reifyTestEnv.Program('test_libreify', TEST_LIBREIFY_SOURCES) +AlwaysBuild(reifyTestEnv.Alias('test-libreify', [testReifyProgram], testReifyProgram[0].path)) +if 'libreify' in env['TESTS']: + AlwaysBuild(reifyTestEnv.Alias('test', [testReifyProgram], testReifyProgram[0].path)) + +# {{{1 Liblp: Tests + +TEST_LIBLP_SOURCES = find_files(env, 'liblp/tests') + +lpTestEnv = env.Clone() +lpTestEnv.Append(CPPPATH = LIBLP_HEADERS) +lpTestEnv.Prepend(LIBS = [lpLib]) + +testLpProgram = lpTestEnv.Program('test_liblp', TEST_LIBLP_SOURCES) +AlwaysBuild(lpTestEnv.Alias('test-liblp', [testLpProgram], testLpProgram[0].path)) +if "liblp" in env["TESTS"]: + AlwaysBuild(lpTestEnv.Alias('test', [testLpProgram], testLpProgram[0].path)) + +# {{{1 Libclingo: Tests + +TEST_CLINGO_SOURCES = find_files(env, 'libclingo/tests') + +clingoTestEnv = env.Clone() +clingoTestEnv.Append(CPPPATH = LIBCLINGO_HEADERS) +clingoTestEnv.Prepend(LIBS = [clingoLib, gringoLib, claspLib, optsLib, reifyLib, lpLib]) + +clingoTestProgram = clingoTestEnv.Program('test_libclingo', TEST_CLINGO_SOURCES) +AlwaysBuild(clingoTestEnv.Alias('test-libclingo', [clingoTestProgram], clingoTestProgram[0].path)) +if "libclingo" in env["TESTS"]: + AlwaysBuild(clingoTestEnv.Alias('test', [clingoTestProgram], clingoTestProgram[0].path)) + +# {{{1 Clingo: Tests + +clingoTestCommand = env.Command('clingo-test', clingoProgram, 'python app/clingo/tests/run.py -c $SOURCE run' + (" -- -t8" if env["WITH_THREADS"] is not None else "")) +env.AlwaysBuild(env.Alias('test-clingo', [clingoTestCommand])) +if "clingo" in env["TESTS"]: + env.AlwaysBuild(env.Alias('test', [clingoTestCommand])) + +# {{{1 Clingo: Configure + +clingoConfigure = env.Alias('configure', []) + +# {{{1 Ctags + +ctagsCommand = env.Command('ctags', [], 'ctags --c++-kinds=+p --fields=+imaS --extra=+q -R libgringo app') +ctagsAlias = env.Alias('tags', [ctagsCommand]) +env.AlwaysBuild(ctagsCommand) + diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..974e0b8 --- /dev/null +++ b/SConstruct @@ -0,0 +1,154 @@ +#!/usr/bin/python +# {{{ GPL License + +# This file is part of gringo - a grounder for logic programs. +# Copyright (C) 2013 Roland Kaminski + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# }}} + +from os import mkdir +from os.path import join, exists + +if not exists("build"): mkdir("build") + +AddOption('--build-dir', default='debug', metavar='DIR', nargs=1, type='string', dest='build_dir') +AddOption('--test-case', default=None, metavar='NAME', nargs=1, type='string', dest='test_case') + +# Note: workaround for scons limitation (try to get a hand on the internal option parser) + +opts_file = join("build", GetOption('build_dir') + ".py") + +opts = Variables(opts_file, ARGUMENTS) +opts.AddVariables( + ('CXX' , 'C++ compiler'), + ('CC' , 'C compiler'), + ('CXXFLAGS' , 'C++ compiler flags'), + ('CFLAGS' , 'C compiler flags'), + ('CPPPATH' , 'include paths'), + ('CPPDEFINES' , 'defines'), + ('LIBS' , 'additional libraries'), + ('LIBPATH' , 'library paths'), + ('LINKFLAGS' , 'C++ linker flags'), + ('CLINKFLAGS' , 'C linker flags'), + ('RPATH' , 'library paths to embedd into binaries'), + ('AR' , 'path to ar'), + ('ARFLAGS' , 'ar flags'), + ('RANLIB' , 'path to ranlib'), + ('BISON' , 'path to bison'), + ('RE2C' , 'path to re2c'), + ('PYTHON_CONFIG' , 'path to python-config'), + ('PKG_CONFIG' , 'path to pkg-config'), + ('WITH_PYTHON' , 'enable python integration; None, "auto", or library name or path'), + ('WITH_LUA' , 'enable lua integration; None, "auto", library name, or path'), + ('WITH_THREADS' , 'enable thread support in clasp library; "posix", "windows", or None'), + ('TESTS' , 'enable specific unit tests; [libgringo, libreify, liblp]'), + ) + +env = Environment() +env['BISON'] = 'bison' +env['RE2C'] = 're2c' +env['PYTHON_CONFIG'] = 'python-config' +env['PKG_CONFIG'] = 'pkg-config' +env['CXX'] = 'c++' +env['CC'] = 'cc' +env['CXXFLAGS'] = ['-std=c++11', '-O0', '-g', '-Wall', '-W', '-pedantic', '-fvisibility=hidden'] +env['CFLAGS'] = ['-O0', '-g', '-Wall'] +env['LIBS'] = [] +env['LINKFLAGS'] = ['-std=c++11', '-O0'] +env['CLINKFLAGS'] = [] +env['CPPDEFINES'] = {} +env['CPPPATH'] = [] +env['LIBPATH'] = [] +env['RPATH'] = [] +env['WITH_PYTHON'] = 'auto' +env['WITH_LUA'] = 'auto' +env['WITH_THREADS'] = 'posix' +env['TESTS'] = ['libreify', 'libgringo', 'libclingo', 'liblp', 'clingo'] + +if GetOption("build_dir") == "static": + env['CXXFLAGS'] = ['-std=c++11', '-O3', '-Wall', '-fvisibility=hidden'] + env['CFLAGS'] = ['-O3', '-Wall'] + env['LINKFLAGS'] = ['-std=c++11', '-O3', '-static'] + env['CPPDEFINES']['NDEBUG'] = 1 +elif GetOption("build_dir") == "release": + env['CXXFLAGS'] = ['-std=c++11', '-O3', '-Wall', '-fvisibility=hidden'] + env['CFLAGS'] = ['-O3', '-Wall'] + env['LINKFLAGS'] = ['-std=c++11', '-O3'] + env['CPPDEFINES']['NDEBUG'] = 1 +elif GetOption("build_dir") == "js": + # NOTE: web is the only working target and there is still the .html suffix missing + env['CXXFLAGS'] = ['-std=c++11', '-Os', '-Wall', '-s', 'DISABLE_EXCEPTION_CATCHING=0'] + env['LINKFLAGS'] = ['-std=c++11', '-Os', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-s', 'EXPORTED_FUNCTIONS=\'["_run"]\''] + env['CXX'] = "em++" + env['AR'] = 'emar' + env['RANLIB'] = 'emranlib' + env['CPPDEFINES']['NDEBUG'] = 1 + env['WITH_PYTHON'] = None + env['WITH_LUA'] = None + env['WITH_THREADS'] = None + +opts.Update(env) +opts.Save(opts_file, env) +opts.FormatVariableHelpText = lambda env, opt, help, default, actual, other: "%10s: %s (%s)\n" % (opt, help, actual) + +Help( +""" +usage: scons [OPTION] [TARGET] ... + +Options: + --build-dir=DIR Sets the build directory to build/DIR. If DIR is + release or static then options are set, + respectively. Otherwise, debug options are set. + Furthermore the special build dir js sets options + to build with emscripten. Afterwards, target web + can be used to build clingo for the web browser. + Default: debug + --test-case=NAME Selects which test case to run. If empty all + tests will be executed. + Default: '' + +Targets: + configure Only configure and build nothing. + gringo Build gringo (built by default). + clingo Build clingo (built by default). + reify Build reify (built by default). + lpconvert Build lpconvert (built by default). + pyclingo Python module (built if python support enabled). + luaclingo Lua module (built if lua support enabled). + test-clingo Run clingo specific acceptence tests. + test-libclingo Run unit tests for libclingo. + test-libgringo Run unit tests for libgringo. + test-liblp Run unit tests for liblp. + test-libreify Run unit tests for librefiy. + libclingo Build shared clingo library. + example Build example app using libclingo. + cexample Build example app using clingo's C interface. + tags Generate ctags file. + web Build clingo for the web (use with build-dir js). + +Variables: +""" + opts.GenerateHelpText(env)) + +# Notes to use gold linker: +# scons --build=gold \ +# CXXFLAGS="-std=c++11 -O4 -Wall" \ +# LINKFLAGS="-O4 -B build/gold/ld-gold/" \ +# RANLIB=true \ +# ARFLAGS="rc --plugin /usr/lib/llvm/LLVMgold.so" + +if not env.GetOption('help'): + SConscript('SConscript', variant_dir=join('build', GetOption('build_dir')), duplicate=0, exports=['env', 'opts']) + diff --git a/app/cexample/main.c b/app/cexample/main.c new file mode 100644 index 0000000..182d64a --- /dev/null +++ b/app/cexample/main.c @@ -0,0 +1,63 @@ +#include +#include +#include + +#define EM(ret, msg) \ + if (!(ret)) { \ + fprintf(stderr, "example failed with: %s\n", (msg) ? (msg) : "unknown error"); \ + goto cleanup; \ + } +#define E(e) EM((e), clingo_error_message()) +#define A(ptr, type, old_n, new_n, msg) \ + if (old_n < new_n) { \ + type *ptr ## _new = (type*)realloc(ptr, new_n * sizeof(type)); \ + EM(ptr ## _new, (msg)); \ + ptr = ptr ## _new; \ + old_n = new_n; \ + } + +void logger(clingo_warning_t code, char const *message, void *data) { + (void)code; + (void)data; + fprintf(stderr, "%s\n", message); + fflush(stderr); +} + +int main(int argc, char const **argv) { + clingo_control_t *ctl = NULL; + clingo_solve_iteratively_t *solve_it = NULL; + clingo_part_t parts[] = {{ "base", NULL, 0 }}; + clingo_symbol_t *atoms = NULL; + size_t n; + size_t atoms_n = 0; + char *str = NULL; + size_t str_n = 0; + E(clingo_control_new(argv+1, argc-1, &logger, NULL, 20, &ctl)); + E(clingo_control_add(ctl, "base", NULL, 0, "a :- not b. b :- not a.")); + E(clingo_control_ground(ctl, parts, 1, NULL, NULL)); + E(clingo_control_solve_iteratively(ctl, NULL, 0, &solve_it)); + for (;;) { + clingo_model_t *m; + clingo_symbol_t const *atoms_it, *atoms_ie; + E(clingo_solve_iteratively_next(solve_it, &m)); + if (!m) { break; } + E(clingo_model_symbols_size(m, clingo_show_type_atoms | clingo_show_type_csp, &n)); + A(atoms, clingo_symbol_t, atoms_n, n, "failed to allocate memory for atoms"); + E(clingo_model_symbols(m, clingo_show_type_atoms | clingo_show_type_csp, atoms, n)); + printf("Model:"); + for (atoms_it = atoms, atoms_ie = atoms + n; atoms_it != atoms_ie; ++atoms_it) { + E(clingo_symbol_to_string_size(*atoms_it, &n)); + A(str, char, str_n, n, "failed to allocate memory for symbol's string"); + E(clingo_symbol_to_string(*atoms_it, str, n)); + printf(" %s", str); + } + printf("\n"); + } +cleanup: + if (str) { free(str); } + if (atoms) { free(atoms); } + if (solve_it) { clingo_solve_iteratively_close(solve_it); } + if (ctl) { clingo_control_free(ctl); } + return clingo_error_code(); +} + diff --git a/app/clingo/src/clasp/clasp_app.cpp b/app/clingo/src/clasp/clasp_app.cpp new file mode 100644 index 0000000..31f2b70 --- /dev/null +++ b/app/clingo/src/clasp/clasp_app.cpp @@ -0,0 +1,675 @@ +// +// Copyright (c) 2006-2012, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include "clasp_app.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#define snprintf _snprintf +#pragma warning (disable : 4996) +#endif +#include + +#if defined( __linux__ ) +#include +#if defined(_FPU_EXTENDED) && defined(_FPU_SINGLE) && defined(_FPU_DOUBLE) +#define FPU_SWITCH_DOUBLE(oldW) _FPU_GETCW(oldW);\ + unsigned __t = ((oldW) & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE;\ + _FPU_SETCW(__t) +#define FPU_RESTORE_DOUBLE(oldW) _FPU_SETCW(oldW) +#endif +#elif defined (_MSC_VER) && !defined(_WIN64) +#include +#define FPU_SWITCH_DOUBLE(oldW) \ + (oldW) = _controlfp(0, 0); \ + _controlfp(_PC_53, _MCW_PC); +#define FPU_RESTORE_DOUBLE(oldW) \ + _controlfp((oldW), _MCW_PC); +#pragma fenv_access (on) +#endif + +#if !defined(FPU_SWITCH_DOUBLE) +#define FPU_SWITCH_DOUBLE(x) +#define FPU_RESTORE_DOUBLE(x) +#endif + +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Some helpers +///////////////////////////////////////////////////////////////////////////////////////// +unsigned doubleMode_g = ((unsigned)(sizeof(void*)*CHAR_BIT)) < 64; +double shutdownTime_g; +static const std::string stdinStr = "stdin"; +static const std::string stdoutStr = "stdout"; +inline bool isStdIn(const std::string& in) { return in == "-" || in == stdinStr; } +inline bool isStdOut(const std::string& out) { return out == "-" || out == stdoutStr; } +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspAppOptions +///////////////////////////////////////////////////////////////////////////////////////// +namespace Cli { +ClaspAppOptions::ClaspAppOptions() : outf(0), compute(0), ifs(' '), hideAux(false), onlyPre(0), printPort(false) { + quiet[0] = quiet[1] = quiet[2] = static_cast(UCHAR_MAX); +} +void ClaspAppOptions::initOptions(ProgramOptions::OptionContext& root) { + using namespace ProgramOptions; + OptionGroup basic("Basic Options"); + basic.addOptions() + ("quiet,q" , notify(this, &ClaspAppOptions::mappedOpts)->implicit("2,2,2")->arg(""), + "Configure printing of models, costs, and calls\n" + " %A: [,][,]\n" + " : print {0=all|1=last|2=no} models\n" + " : print {0=all|1=last|2=no} optimize values []\n" + " : print {0=all|1=last|2=no} call steps [2]") + ("pre", notify(this, &ClaspAppOptions::mappedOpts)->arg("")->implicit("1"), "Print simplified program and exit\n" + " %A: Output format: {1=auto|2=aspif}") + ("print-portfolio" , flag(printPort), "Print default portfolio and exit") + ("outf,@1", storeTo(outf)->arg(""), "Use {0=default|1=competition|2=JSON|3=no} output") + ("out-atomf,@1" , storeTo(outAtom), "Set atom format string (
?%%0?)")
+		("out-ifs,@1"   , notify(this, &ClaspAppOptions::mappedOpts), "Set internal field separator")
+		("out-hide-aux,@1" , flag(hideAux), "Hide auxiliary atoms in answers")
+		("lemma-in,@1"     , storeTo(lemmaIn)->arg(""), "Read additional lemmas from %A")
+		("lemma-out,@1"    , storeTo(lemmaLog)->arg(""), "Log learnt lemmas to %A")
+		("lemma-out-lbd,@1", storeTo(lemma.lbdMax)->arg(""), "Only log lemmas with lbd <= %A")
+		("lemma-out-max,@1", storeTo(lemma.logMax)->arg(""), "Stop logging after %A lemmas")
+		("lemma-out-dom,@1", notify(this, &ClaspAppOptions::mappedOpts), "Log lemmas over  variables")
+		("lemma-out-txt,@1", flag(lemma.logText), "Log lemmas as ground integrity constraints")
+		("hcc-out,@1", storeTo(hccOut)->arg(""), "Write non-hcf programs to %A.#scc")
+		("file,f,@2" , storeTo(input)->composing(), "Input files")
+		("compute,@2", storeTo(compute)->arg(""), "Force given literal to true")
+	;
+	root.add(basic);
+}
+bool ClaspAppOptions::mappedOpts(ClaspAppOptions* this_, const std::string& name, const std::string& value) {
+	if (name == "quiet") {
+		const char* err = 0;
+		uint32      q[3]= {uint32(UCHAR_MAX),uint32(UCHAR_MAX),uint32(UCHAR_MAX)};
+		int      parsed = bk_lib::xconvert(value.c_str(), q, &err);
+		for (int i = 0; i != parsed; ++i) { this_->quiet[i] = static_cast(q[i]); }
+		return parsed && *err == 0;
+	}
+	else if (name == "out-ifs") {
+		if (value.empty() || value.size() > 2) { return false;}
+		if (value.size() == 1) { this_->ifs = value[0]; return true; }
+		if (value[1] == 't')   { this_->ifs = '\t'; return true; }
+		if (value[1] == 'n')   { this_->ifs = '\n'; return true; }
+		if (value[1] == 'v')   { this_->ifs = '\v'; return true; }
+		if (value[1] == '\\')  { this_->ifs = '\\'; return true; }
+	}
+	else if (name == "lemma-out-dom") {
+		return (this_->lemma.domOut = (strcasecmp(value.c_str(), "output") == 0)) == true || strcasecmp(value.c_str(), "input") == 0;
+	}
+	else if (name == "pre") {
+		return value.size() == 1 && (this_->onlyPre = static_cast(Potassco::BufferedStream::toDigit(value[0]))) <= 2;
+	}
+	return false;
+}
+bool ClaspAppOptions::validateOptions(const ProgramOptions::ParsedOptions&) {
+	if (quiet[1] == static_cast(UCHAR_MAX)) { quiet[1] = quiet[0]; }
+	return true;
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+// ClaspAppBase
+/////////////////////////////////////////////////////////////////////////////////////////
+ClaspAppBase::ClaspAppBase() { }
+ClaspAppBase::~ClaspAppBase(){ }
+const int* ClaspAppBase::getSignals() const {
+	static const int signals[] = {
+		SIGINT, SIGTERM
+#if !defined (_WIN32)
+		, SIGUSR1, SIGUSR2, SIGQUIT, SIGHUP, SIGXCPU, SIGXFSZ
+#endif
+		, 0};
+		return signals;
+}
+bool ClaspAppBase::parsePositional(const std::string& t, std::string& out) {
+	int num;
+	if   (bk_lib::string_cast(t, num)) { out = "number"; }
+	else                               { out = "file";   }
+	return true;
+}
+void ClaspAppBase::initOptions(ProgramOptions::OptionContext& root) {
+	claspConfig_.addOptions(root);
+	claspAppOpts_.initOptions(root);
+	root.find("verbose")->get()->value()->defaultsTo("1");
+}
+
+void ClaspAppBase::validateOptions(const ProgramOptions::OptionContext&, const ProgramOptions::ParsedOptions& parsed, const ProgramOptions::ParsedValues& values) {
+	if (claspAppOpts_.printPort) {
+		printTemplate();
+		exit(E_UNKNOWN);
+	}
+	setExitCode(E_NO_RUN);
+	using ProgramOptions::Error;
+	ProblemType pt = getProblemType();
+	if (!claspAppOpts_.validateOptions(parsed) || !claspConfig_.finalize(parsed, pt, true)) {
+		throw Error("command-line error!");
+	}
+	ClaspAppOptions& app = claspAppOpts_;
+	if (!app.lemmaLog.empty() && !isStdOut(app.lemmaLog)) {
+		if (std::find(app.input.begin(), app.input.end(), app.lemmaLog) != app.input.end() || app.lemmaIn == app.lemmaLog) {
+			throw Error("'lemma-out': cowardly refusing to overwrite input file!");
+		}
+	}
+	if (!app.lemmaIn.empty() && !isStdIn(app.lemmaIn) && !std::ifstream(app.lemmaIn.c_str()).is_open()) {
+		error("'lemma-in': could not open file!");
+		exit(E_NO_RUN);
+	}
+	for (std::size_t i = 1; i < app.input.size(); ++i) {
+		if (!isStdIn(app.input[i]) && !std::ifstream(app.input[i].c_str()).is_open()) {
+			throw Error(ClaspStringBuffer().appendFormat("'%s': could not open input file!", app.input[i].c_str()).c_str());
+		}
+	}
+	if (app.onlyPre && pt != Problem_t::Asp) {
+		throw Error("Option '--pre' only supported for ASP!");
+	}
+	setExitCode(0);
+	storeCommandArgs(values);
+}
+void ClaspAppBase::setup() {
+	ProblemType pt = getProblemType();
+	clasp_         = new ClaspFacade();
+	if (!claspAppOpts_.onlyPre) {
+		if (doubleMode_g) { FPU_SWITCH_DOUBLE(doubleMode_g); }
+		out_ = createOutput(pt);
+		Event::Verbosity verb	= (Event::Verbosity)std::min(verbose(), (uint32)Event::verbosity_max);
+		if (out_.get() && out_->verbosity() < (uint32)verb) { verb = (Event::Verbosity)out_->verbosity(); }
+		if (!claspAppOpts_.lemmaLog.empty()) {
+			logger_ = new LemmaLogger(claspAppOpts_.lemmaLog.c_str(), claspAppOpts_.lemma);
+		}
+		EventHandler::setVerbosity(Event::subsystem_facade , verb);
+		EventHandler::setVerbosity(Event::subsystem_load   , verb);
+		EventHandler::setVerbosity(Event::subsystem_prepare, verb);
+		EventHandler::setVerbosity(Event::subsystem_solve  , verb);
+		clasp_->ctx.setEventHandler(this, logger_.get() == 0 ? SharedContext::report_default : SharedContext::report_conflict);
+	}
+}
+
+void ClaspAppBase::shutdown() {
+	if (!clasp_.get()) { return; }
+	if (logger_.get()) { logger_->close(); }
+	lemmaIn_ = 0;
+	const ClaspFacade::Summary& result = clasp_->shutdown();
+	if (shutdownTime_g) {
+		shutdownTime_g += RealTime::getTime();
+		char msg[80];
+		info(clasp_format(msg, sizeof(msg), "Shutdown completed in %.3f seconds", shutdownTime_g));
+	}
+	if (out_.get()) { out_->shutdown(result); }
+	setExitCode(getExitCode() | exitCode(result));
+	if (doubleMode_g) { FPU_RESTORE_DOUBLE(doubleMode_g); doubleMode_g = 1; }
+}
+
+void ClaspAppBase::run() {
+	if (out_.get()) {
+		Potassco::Span in = !claspAppOpts_.input.empty() ? Potassco::toSpan(claspAppOpts_.input) : Potassco::toSpan(&stdinStr, 1);
+		out_->run(getName(), getVersion(), Potassco::begin(in), Potassco::end(in));
+	}
+	try        { run(*clasp_); }
+	catch(...) {
+		try { blockSignals(); setExitCode(E_ERROR); throw; }
+		catch (const std::bad_alloc&  ) { setExitCode(E_MEMORY); error("std::bad_alloc"); }
+		catch (const std::exception& e) { error(e.what()); }
+		catch (...)                     { ; }
+	}
+}
+
+bool ClaspAppBase::onSignal(int sig) {
+	if (!clasp_.get() || !clasp_->interrupt(sig)) {
+		info("INTERRUPTED by signal!");
+		setExitCode(E_INTERRUPT);
+		shutdown();
+		exit(getExitCode());
+	}
+	else {
+		// multiple threads are active - shutdown was initiated
+		shutdownTime_g = -RealTime::getTime();
+		info("Sending shutdown signal...");
+	}
+	return false; // ignore all future signals
+}
+
+void ClaspAppBase::onEvent(const Event& ev) {
+	const LogEvent* log = event_cast(ev);
+	if (log && log->isWarning()) {
+		warn(log->msg);
+		return;
+	}
+	else if (const NewConflictEvent* cfl = event_cast(ev)) {
+		if (logger_.get()) { logger_->add(*cfl->solver, *cfl->learnt, cfl->info); }
+		return;
+	}
+	if (out_.get()) {
+		blockSignals();
+		out_->onEvent(ev);
+		unblockSignals(true);
+	}
+}
+
+bool ClaspAppBase::onModel(const Solver& s, const Model& m) {
+	bool ret = true;
+	if (out_.get() && !out_->quiet()) {
+		blockSignals();
+		ret = out_->onModel(s, m);
+		unblockSignals(true);
+	}
+	return ret;
+}
+bool ClaspAppBase::onUnsat(const Solver& s, const Model& m) {
+	bool ret = true;
+	if (out_.get() && !out_->quiet()) {
+		blockSignals();
+		ret = out_->onUnsat(s, m);
+		unblockSignals(true);
+	}
+	return ret;
+}
+
+int ClaspAppBase::exitCode(const RunSummary& run) const {
+	int ec = 0;
+	if (run.sat())               { ec |= E_SAT;       }
+	if (run.complete())          { ec |= E_EXHAUST;   }
+	if (run.result.interrupted()){ ec |= E_INTERRUPT; }
+	return ec;
+}
+
+void ClaspAppBase::printTemplate() const {
+	printf(
+		"# clasp %s configuration file\n"
+		"# A configuration file contains a (possibly empty) list of configurations.\n"
+		"# Each of which must have the following format:\n"
+		"#   [()]: \n"
+		"# where  is a string that must not contain ':',\n"
+		"#  is one of clasp's default configs (and optional)\n"
+		"# and     is a command-line string of clasp options in long-format, e.g.\n"
+		"# ('--heuristic=vsids --restarts=L,100').\n"
+		"#\n"
+		"# SEE: clasp --help\n"
+		"#\n"
+		"# NOTE: The options '--configuration' and '--tester' must not occur in a\n"
+		"#       configuration file. Furthermore, global options are ignored in all\n"
+		"#       but the first configuration.\n"
+		"#\n"
+		"# NOTE: Options given on the command-line are added to all configurations in a\n"
+		"#       configuration file. If an option is given both on the command-line and\n"
+		"#       in a configuration file, the one from the command-line is preferred.\n"
+		"#\n"
+		"# NOTE: If, after adding command-line options, a configuration\n"
+		"#       contains mutually exclusive options an error is raised.\n"
+		"#\n", CLASP_VERSION);
+	for (ConfigIter it = ClaspCliConfig::getConfig(Clasp::Cli::config_many); it.valid(); it.next()) {
+		printf("%s: %s\n", it.name(), it.args());
+	}
+}
+
+void ClaspAppBase::printVersion() {
+	ProgramOptions::Application::printVersion();
+	printLibClaspVersion();
+}
+
+void ClaspAppBase::printLibClaspVersion() const {
+	if (strcmp(getName(), "clasp") != 0) {
+		printf("libclasp version %s\n", CLASP_VERSION);
+	}
+	printf("Configuration: WITH_THREADS=%d", WITH_THREADS);
+#if defined(WITH_THREADS) && defined(TBB_VERSION_MAJOR) && WITH_THREADS
+	printf(" (Intel TBB version %d.%d)", TBB_VERSION_MAJOR, TBB_VERSION_MINOR);
+#endif
+	printf("\n%s\n", CLASP_LEGAL);
+	fflush(stdout);
+}
+
+void ClaspAppBase::printHelp(const ProgramOptions::OptionContext& root) {
+	ProgramOptions::Application::printHelp(root);
+	if (root.getActiveDescLevel() >= ProgramOptions::desc_level_e1) {
+		printf("[asp] %s\n", ClaspCliConfig::getDefaults(Problem_t::Asp));
+		printf("[cnf] %s\n", ClaspCliConfig::getDefaults(Problem_t::Sat));
+		printf("[opb] %s\n", ClaspCliConfig::getDefaults(Problem_t::Pb));
+	}
+	if (root.getActiveDescLevel() >= ProgramOptions::desc_level_e2) {
+		printf("\nDefault configurations:\n");
+		printDefaultConfigs();
+	}
+	fflush(stdout);
+}
+
+void ClaspAppBase::printDefaultConfigs() const {
+	uint32 minW = 2, maxW = 80;
+	std::string cmd;
+	for (int i = Clasp::Cli::config_default+1; i != Clasp::Cli::config_default_max_value; ++i) {
+		ConfigIter it = ClaspCliConfig::getConfig(static_cast(i));
+		printf("%s:\n%*c", it.name(), minW-1, ' ');
+		cmd = it.args();
+		// split options into formatted lines
+		std::size_t sz = cmd.size(), off = 0, n = maxW - minW;
+		while (n < sz) {
+			while (n != off  && cmd[n] != ' ') { --n; }
+			if (n != off) { cmd[n] = 0; printf("%s\n%*c", &cmd[off], minW-1, ' '); }
+			else          { break; }
+			off = n+1;
+			n   = (maxW - minW) + off;
+		}
+		printf("%s\n", cmd.c_str()+off);
+	}
+}
+void ClaspAppBase::writeNonHcfs(const PrgDepGraph& graph) const {
+	char buf[10];
+	for (PrgDepGraph::NonHcfIter it = graph.nonHcfBegin(), end = graph.nonHcfEnd(); it != end; ++it) {
+		snprintf(buf, 10, ".%u", (*it)->id());
+		WriteCnf cnf(claspAppOpts_.hccOut + buf);
+		const SharedContext& ctx = (*it)->ctx();
+		cnf.writeHeader(ctx.numVars(), ctx.numConstraints());
+		cnf.write(ctx.numVars(), ctx.shortImplications());
+		Solver::DBRef db = ctx.master()->constraints();
+		for (uint32 i = 0; i != db.size(); ++i) {
+			if (ClauseHead* x = db[i]->clause()) { cnf.write(x); }
+		}
+		for (uint32 i = 0; i != ctx.master()->trail().size(); ++i) {
+			cnf.write(ctx.master()->trail()[i]);
+		}
+		cnf.close();
+	}
+}
+std::istream& ClaspAppBase::getStream(bool reopen) const {
+	static std::ifstream file;
+	static bool isOpen = false;
+	if (!isOpen || reopen) {
+		file.close();
+		isOpen = true;
+		if (!claspAppOpts_.input.empty() && !isStdIn(claspAppOpts_.input[0])) {
+			file.open(claspAppOpts_.input[0].c_str());
+			if (!file.is_open()) {
+				throw std::runtime_error(ClaspStringBuffer().appendFormat("Can not read from '%s'", claspAppOpts_.input[0].c_str()).c_str());
+			}
+		}
+	}
+	return file.is_open() ? file : std::cin;
+}
+
+// Creates output object suitable for given input format
+Output* ClaspAppBase::createOutput(ProblemType f) {
+	SingleOwnerPtr out;
+	if (claspAppOpts_.outf == ClaspAppOptions::out_none) {
+		return 0;
+	}
+	if (claspAppOpts_.outf != ClaspAppOptions::out_json || claspAppOpts_.onlyPre) {
+		TextOutput::Format outFormat = TextOutput::format_asp;
+		if      (f == Problem_t::Sat){ outFormat = TextOutput::format_sat09; }
+		else if (f == Problem_t::Pb) { outFormat = TextOutput::format_pb09;  }
+		else if (f == Problem_t::Asp && claspAppOpts_.outf == ClaspAppOptions::out_comp) {
+			outFormat = TextOutput::format_aspcomp;
+		}
+		out.reset(new TextOutput(verbose(), outFormat, claspAppOpts_.outAtom.c_str(), claspAppOpts_.ifs));
+		if (claspConfig_.solve.maxSat && f == Problem_t::Sat) {
+			static_cast(out.get())->result[TextOutput::res_sat] = "UNKNOWN";
+		}
+	}
+	else {
+		out.reset(new JsonOutput(verbose()));
+	}
+	if (claspAppOpts_.quiet[0] != static_cast(UCHAR_MAX)) {
+		out->setModelQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[0]));
+	}
+	if (claspAppOpts_.quiet[1] != static_cast(UCHAR_MAX)) {
+		out->setOptQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[1]));
+	}
+	if (claspAppOpts_.quiet[2] != static_cast(UCHAR_MAX)) {
+		out->setCallQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[2]));
+	}
+	if (claspAppOpts_.hideAux && clasp_.get()) {
+		clasp_->ctx.output.setFilter('_');
+	}
+	return out.release();
+}
+void ClaspAppBase::storeCommandArgs(const ProgramOptions::ParsedValues&) {
+	/* We don't need the values */
+}
+void ClaspAppBase::handleStartOptions(ClaspFacade& clasp) {
+	if (!clasp.incremental()) {
+		claspConfig_.releaseOptions();
+	}
+	if (claspAppOpts_.compute && clasp.program()->type() == Problem_t::Asp) {
+		Potassco::Lit_t lit = Potassco::neg(claspAppOpts_.compute);
+		static_cast(clasp.program())->addRule(Potassco::Head_t::Disjunctive, Potassco::toSpan(), Potassco::toSpan(&lit, 1));
+	}
+	if (!claspAppOpts_.lemmaIn.empty()) {
+		class LemmaIn : public Potassco::AspifInput {
+		public:
+			typedef Potassco::AbstractProgram PrgAdapter;
+			LemmaIn(const std::string& fn, PrgAdapter* prg) : Potassco::AspifInput(*prg), prg_(prg) {
+				if (!isStdIn(fn)) { file_.open(fn.c_str()); }
+				CLASP_FAIL_IF(!accept(getStream()), "'lemma-in': invalid input file");
+			}
+			~LemmaIn() { delete prg_; }
+		private:
+			std::istream& getStream() { return file_.is_open() ? file_ : std::cin; }
+			PrgAdapter*   prg_;
+			std::ifstream file_;
+		};
+		SingleOwnerPtr prgTemp;
+		if (clasp.program()->type() == Problem_t::Asp) { prgTemp = new Asp::LogicProgramAdapter(*static_cast(clasp.program())); }
+		else { prgTemp = new BasicProgramAdapter(*clasp.program()); }
+		lemmaIn_ = new LemmaIn(claspAppOpts_.lemmaIn, prgTemp.release());
+	}
+}
+bool ClaspAppBase::handlePostGroundOptions(ProgramBuilder& prg) {
+	if (!claspAppOpts_.onlyPre) {
+		if (lemmaIn_.get()) { lemmaIn_->parse(); }
+		if (logger_.get())  { logger_->startStep(prg, clasp_->incremental()); }
+		return true;
+	}
+	prg.endProgram();
+	if (prg.type() == Problem_t::Asp) {
+		Asp::LogicProgram& asp = static_cast(prg);
+		AspParser::Format outf = claspAppOpts_.onlyPre == 2 || !asp.supportsSmodels() ? AspParser::format_aspif : AspParser::format_smodels;
+		AspParser::write(asp, std::cout, outf);
+	}
+	else {
+		error("Option '--pre': unsupported input format!");
+		setExitCode(E_ERROR);
+	}
+	return false;
+}
+bool ClaspAppBase::handlePreSolveOptions(ClaspFacade& clasp) {
+	if (!claspAppOpts_.hccOut.empty() && clasp.ctx.sccGraph.get()){ writeNonHcfs(*clasp.ctx.sccGraph); }
+	return true;
+}
+void ClaspAppBase::run(ClaspFacade& clasp) {
+	clasp.start(claspConfig_, getStream());
+	handleStartOptions(clasp);
+	while (clasp.read()) {
+		if (handlePostGroundOptions(*clasp.program())) {
+			clasp.prepare();
+			if (handlePreSolveOptions(clasp)) { clasp.solve(); }
+		}
+	}
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+// ClaspApp
+/////////////////////////////////////////////////////////////////////////////////////////
+ClaspApp::ClaspApp() {}
+
+ProblemType ClaspApp::getProblemType() {
+	return ClaspFacade::detectProblemType(getStream());
+}
+
+void ClaspApp::run(ClaspFacade& clasp) {
+	ClaspAppBase::run(clasp);
+}
+
+void ClaspApp::printHelp(const ProgramOptions::OptionContext& root) {
+	ClaspAppBase::printHelp(root);
+	printf("\nclasp is part of Potassco: %s\n", "https://potassco.org/clasp/");
+	printf("Get help/report bugs via : %s\n", "https://potassco.org/support/");
+	fflush(stdout);
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+// LemmaLogger
+/////////////////////////////////////////////////////////////////////////////////////////
+LemmaLogger::LemmaLogger(const std::string& to, const Options& o)
+	: str_(isStdOut(to) ? stdout : fopen(to.c_str(), "w"))
+	, inputType_(Problem_t::Asp)
+	, options_(o)
+	, step_(0) {
+	CLASP_FAIL_IF(!str_, "Could not open lemma log file '%s'!", to.c_str());
+}
+LemmaLogger::~LemmaLogger() { close(); }
+void LemmaLogger::startStep(ProgramBuilder& prg, bool inc) {
+	logged_ = 0;
+	++step_;
+	if (!options_.logText) {
+		if (step_ == 1) { fprintf(str_, "asp 1 0 0%s\n", inc ? " incremental" : ""); }
+		else            { fprintf(str_, "0\n"); }
+	}
+	if ((inputType_ = static_cast(prg.type())) == Problem_t::Asp && prg.endProgram()) {
+		// create solver variable to potassco literal mapping
+		Asp::LogicProgram& asp = static_cast(prg);
+		for (Asp::Atom_t a = asp.startAtom(); a != asp.startAuxAtom(); ++a) {
+			Literal sLit = asp.getLiteral(a);
+			if (sLit.var() >= solver2asp_.size()) {
+				solver2asp_.resize(sLit.var() + 1, 0);
+			}
+			Potassco::Lit_t& p = solver2asp_[sLit.var()];
+			if (!p || (!sLit.sign() && p < 0)) {
+				p = !sLit.sign() ? Potassco::lit(a) : Potassco::neg(a);
+			}
+		}
+	}
+	solver2NameIdx_.clear();
+	if (options_.logText && prg.endProgram()) {
+		const SharedContext& ctx = *prg.ctx();
+		for (OutputTable::pred_iterator beg = ctx.output.pred_begin(), it = beg, end = ctx.output.pred_end(); it != end; ++it) {
+			Var v = it->cond.var();
+			if (ctx.varInfo(v).output()) {
+				if (solver2NameIdx_.size() <= v) { solver2NameIdx_.resize(v + 1, UINT32_MAX); }
+				solver2NameIdx_[v] = static_cast(it - beg);
+			}
+		}
+	}
+}
+void LemmaLogger::add(const Solver& s, const LitVec& cc, const ConstraintInfo& info) {
+	LitVec temp;
+	const LitVec* out = &cc;
+	uint32 lbd = info.lbd();
+	if (lbd > options_.lbdMax || logged_ >= options_.logMax) { return; }
+	if (info.aux() || options_.domOut || std::find_if(cc.begin(), cc.end(), std::not1(std::bind1st(std::mem_fun(&Solver::inputVar), &s))) != cc.end()) {
+		uint8 vf = options_.domOut ? VarInfo::Input|VarInfo::Output : VarInfo::Input;
+		if (!s.resolveToFlagged(cc, vf, temp, lbd) || lbd > options_.lbdMax) { return; }
+		out = &temp;
+	}
+	ClaspStringBuffer lemma;
+	if (options_.logText) { formatText(*out, s.sharedContext()->output, lbd, lemma); }
+	else                  { formatAspif(*out, lbd, lemma); }
+	fwrite(lemma.c_str(), sizeof(char), lemma.size(), str_);
+	++logged_;
+}
+void LemmaLogger::formatAspif(const LitVec& cc, uint32, ClaspStringBuffer& out) const {
+	out.appendFormat("1 0 0 0 %u", (uint32)cc.size());
+	for (LitVec::const_iterator it = cc.begin(), end = cc.end(); it != end; ++it) {
+		Literal sLit = ~*it; // clause -> constraint
+		Potassco::Lit_t a = toInt(sLit);
+		if (inputType_ == Problem_t::Asp) {
+			a = sLit.var() < solver2asp_.size() ? solver2asp_[sLit.var()] : 0;
+			if (!a) { return; }
+			if (sLit.sign() != (a < 0)) { a = -a; }
+		}
+		out.appendFormat(" %d", a);
+	}
+	out.append("\n");
+}
+void LemmaLogger::formatText(const LitVec& cc, const OutputTable& tab, uint32 lbd, ClaspStringBuffer& out) const {
+	out.append(":-");
+	const char* sep = " ";
+	for (LitVec::const_iterator it = cc.begin(), end = cc.end(); it != end; ++it) {
+		Literal sLit = ~*it; // clause -> constraint
+		uint32 idx = sLit.var() < solver2NameIdx_.size() ? solver2NameIdx_[sLit.var()] : UINT32_MAX;
+		if (idx != UINT32_MAX) {
+			const OutputTable::PredType& p = *(tab.pred_begin() + idx);
+			assert(sLit.var() == p.cond.var());
+			out.appendFormat("%s%s%s", sep, sLit.sign() != p.cond.sign() ? "not " : "", p.name.c_str());
+		}
+		else {
+			if (inputType_ == Problem_t::Asp) {
+				Potassco::Lit_t a = sLit.var() < solver2asp_.size() ? solver2asp_[sLit.var()] : 0;
+				if (!a) { return; }
+				if (sLit.sign() != (a < 0)) { a = -a; }
+				sLit = Literal(Potassco::atom(a), a < 0);
+			}
+			out.appendFormat("%s%s__atom(%u)", sep, sLit.sign() ? "not " : "", sLit.var());
+		}
+		sep = ", ";
+	}
+	out.appendFormat(".  %%lbd = %u\n", lbd);
+}
+void LemmaLogger::close() {
+	if (!str_) { return; }
+	if (!options_.logText) { fprintf(str_, "0\n"); }
+	fflush(str_);
+	if (str_ != stdout) { fclose(str_); }
+	str_ = 0;
+	solver2asp_.clear();
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+// WriteCnf
+/////////////////////////////////////////////////////////////////////////////////////////
+WriteCnf::WriteCnf(const std::string& outFile) : str_(fopen(outFile.c_str(), "w")) {
+	CLASP_FAIL_IF(!str_, "Could not open cnf file '%s'!", outFile.c_str());
+}
+WriteCnf::~WriteCnf() { close(); }
+void WriteCnf::writeHeader(uint32 numVars, uint32 numCons) {
+	fprintf(str_, "p cnf %u %u\n", numVars, numCons);
+}
+void WriteCnf::write(ClauseHead* h) {
+	lits_.clear();
+	h->toLits(lits_);
+	for (LitVec::const_iterator it = lits_.begin(), end = lits_.end(); it != end; ++it) {
+		fprintf(str_, "%d ", toInt(*it));
+	}
+	fprintf(str_, "%d\n", 0);
+}
+void WriteCnf::write(Var maxVar, const ShortImplicationsGraph& g) {
+	for (Var v = 1; v <= maxVar; ++v) {
+		g.forEach(posLit(v), *this);
+		g.forEach(negLit(v), *this);
+	}
+}
+void WriteCnf::write(Literal u) {
+	fprintf(str_, "%d 0\n", toInt(u));
+}
+bool WriteCnf::unary(Literal p, Literal x) const {
+	return p.rep() >= x.rep() || fprintf(str_, "%d %d 0\n", toInt(~p), toInt(x)) > 0;
+}
+bool WriteCnf::binary(Literal p, Literal x, Literal y) const {
+	return p.rep() >= x.rep() || p.rep() >= y.rep() || fprintf(str_, "%d %d %d 0\n", toInt(~p), toInt(x), toInt(y)) > 0;
+}
+void WriteCnf::close() {
+	if (str_) {
+		fflush(str_);
+		fclose(str_);
+		str_ = 0;
+	}
+}
+
+}} // end of namespace Clasp::Cli
+
diff --git a/app/clingo/src/clasp/clasp_app.h b/app/clingo/src/clasp/clasp_app.h
new file mode 100644
index 0000000..86e5fbc
--- /dev/null
+++ b/app/clingo/src/clasp/clasp_app.h
@@ -0,0 +1,209 @@
+//
+// Copyright (c) 2006-2012, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#ifndef CLASP_CLASP_APP_H_INCLUDED
+#define CLASP_CLASP_APP_H_INCLUDED
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+namespace Clasp { namespace Cli {
+/////////////////////////////////////////////////////////////////////////////////////////
+// clasp exit codes
+/////////////////////////////////////////////////////////////////////////////////////////
+enum ExitCode {
+	E_UNKNOWN   = 0,  /*!< Satisfiablity of problem not knwon; search not started.    */
+	E_INTERRUPT = 1,  /*!< Run was interrupted.                                       */
+	E_SAT       = 10, /*!< At least one model was found.                              */
+	E_EXHAUST   = 20, /*!< Search-space was completely examined.                      */
+	E_MEMORY    = 33, /*!< Run was interrupted by out of memory exception.            */
+	E_ERROR     = 65, /*!< Run was interrupted by internal error.                     */
+	E_NO_RUN    = 128 /*!< Search not started because of syntax or command line error.*/
+};
+/////////////////////////////////////////////////////////////////////////////////////////
+// clasp app helpers
+/////////////////////////////////////////////////////////////////////////////////////////
+class WriteCnf {
+public:
+	WriteCnf(const std::string& outFile);
+	~WriteCnf();
+	void writeHeader(uint32 numVars, uint32 numCons);
+	void write(Var maxVar, const ShortImplicationsGraph& g);
+	void write(ClauseHead* h);
+	void write(Literal unit);
+	void close();
+	bool unary(Literal, Literal) const;
+	bool binary(Literal, Literal, Literal) const;
+private:
+	WriteCnf(const WriteCnf&);
+	WriteCnf& operator=(const WriteCnf&);
+	FILE*  str_;
+	LitVec lits_;
+};
+class LemmaLogger {
+public:
+	struct Options {
+		Options() : logMax(UINT32_MAX), lbdMax(UINT32_MAX), domOut(false), logText(false) {}
+		uint32 logMax;  // log at most logMax lemmas
+		uint32 lbdMax;  // only log lemmas with lbd <= lbdMax
+		bool   domOut;  // only log lemmas that can be expressed over out variables
+		bool   logText; // log lemmas in ground lp format
+	};
+	LemmaLogger(const std::string& outFile, const Options& opts);
+	~LemmaLogger();
+	void startStep(ProgramBuilder& prg, bool inc);
+	void add(const Solver& s, const LitVec& cc, const ConstraintInfo& info);
+	void close();
+private:
+	typedef PodVector::type Var2Idx;
+	typedef Atomic_t::type Counter;
+	LemmaLogger(const LemmaLogger&);
+	LemmaLogger& operator=(const LemmaLogger&);
+	void formatAspif(const LitVec& cc, uint32 lbd, ClaspStringBuffer& out)  const;
+	void formatText(const LitVec& cc, const OutputTable& tab, uint32 lbd, ClaspStringBuffer& out) const;
+	FILE*            str_;
+	Potassco::LitVec solver2asp_;
+	Var2Idx          solver2NameIdx_;
+	ProblemType      inputType_;
+	Options          options_;
+	int              step_;
+	Counter          logged_;
+};
+/////////////////////////////////////////////////////////////////////////////////////////
+// clasp specific application options
+/////////////////////////////////////////////////////////////////////////////////////////
+struct ClaspAppOptions {
+	typedef LemmaLogger::Options LogOptions;
+	ClaspAppOptions();
+	typedef std::vector  StringSeq;
+	static bool mappedOpts(ClaspAppOptions*, const std::string&, const std::string&);
+	void initOptions(ProgramOptions::OptionContext& root);
+	bool validateOptions(const ProgramOptions::ParsedOptions& parsed);
+	StringSeq   input;     // list of input files - only first used!
+	std::string lemmaLog;  // optional file name for writing learnt lemmas
+	std::string lemmaIn;   // optional file name for reading learnt lemmas
+	std::string hccOut;    // optional file name for writing scc programs
+	std::string outAtom;   // optional format string for atoms
+	uint32      outf;      // output format
+	int         compute;   // force literal compute to true
+	LogOptions  lemma;     // options for lemma logging
+	char        ifs;       // output field separator
+	bool        hideAux;   // output aux atoms?
+	uint8       quiet[3];  // configure printing of models, optimization values, and call steps
+	uint8       onlyPre;   // run preprocessor and exit
+	bool        printPort; // print portfolio and exit
+	enum OutputFormat { out_def = 0, out_comp = 1, out_json = 2, out_none = 3 };
+};
+/////////////////////////////////////////////////////////////////////////////////////////
+// clasp application base
+/////////////////////////////////////////////////////////////////////////////////////////
+// Base class for applications using the clasp library.
+class ClaspAppBase : public ProgramOptions::Application, public Clasp::EventHandler {
+public:
+	typedef ClaspFacade::Summary  RunSummary;
+	typedef ProgramOptions::PosOption PosOption;
+protected:
+	using ProgramOptions::Application::run;
+	ClaspAppBase();
+	~ClaspAppBase();
+	// -------------------------------------------------------------------------------------------
+	// Functions to be implemented by subclasses
+	virtual ProblemType   getProblemType()             = 0;
+	virtual void          run(ClaspFacade& clasp)      = 0;
+	virtual Output*       createOutput(ProblemType f);
+	virtual void          storeCommandArgs(const ProgramOptions::ParsedValues& values);
+	// -------------------------------------------------------------------------------------------
+	// Helper functions that subclasses might call during run
+	void handleStartOptions(ClaspFacade& clasp);
+	bool handlePostGroundOptions(ProgramBuilder& prg);
+	bool handlePreSolveOptions(ClaspFacade& clasp);
+	// -------------------------------------------------------------------------------------------
+	// Application functions
+	virtual const int*  getSignals()    const;
+	virtual HelpOpt     getHelpOption() const { return HelpOpt("Print {1=basic|2=more|3=full} help and exit", 3); }
+	virtual PosOption   getPositional() const { return parsePositional; }
+	virtual void        initOptions(ProgramOptions::OptionContext& root);
+	virtual void        validateOptions(const ProgramOptions::OptionContext& root, const ProgramOptions::ParsedOptions& parsed, const ProgramOptions::ParsedValues& values);
+	virtual void        setup();
+	virtual void        run();
+	virtual void        shutdown();
+	virtual bool        onSignal(int);
+	virtual void        printHelp(const ProgramOptions::OptionContext& root);
+	virtual void        printVersion();
+	static  bool        parsePositional(const std::string& s, std::string& out);
+	// -------------------------------------------------------------------------------------------
+	// Event handler
+	virtual void onEvent(const Event& ev);
+	virtual bool onModel(const Solver& s, const Model& m);
+	virtual bool onUnsat(const Solver& s, const Model& m);
+	// -------------------------------------------------------------------------------------------
+	// Status information & output
+	int  exitCode(const RunSummary& sol)    const;
+	void printTemplate()                    const;
+	void printDefaultConfigs()              const;
+	void printLibClaspVersion()             const;
+	std::istream& getStream(bool reopen = false) const;
+	// -------------------------------------------------------------------------------------------
+	// Functions called in handlePreSolveOptions()
+	void writeNonHcfs(const PrgDepGraph& graph) const;
+	typedef Potassco::ProgramReader     LemmaReader;
+	typedef SingleOwnerPtr      OutPtr;
+	typedef SingleOwnerPtr ClaspPtr;
+	typedef SingleOwnerPtr LogPtr;
+	typedef SingleOwnerPtr LemmaPtr;
+	ClaspCliConfig  claspConfig_;
+	ClaspAppOptions claspAppOpts_;
+	ClaspPtr        clasp_;
+	OutPtr          out_;
+	LogPtr          logger_;
+	LemmaPtr        lemmaIn_;
+};
+/////////////////////////////////////////////////////////////////////////////////////////
+// clasp application
+/////////////////////////////////////////////////////////////////////////////////////////
+// Standalone clasp application.
+class ClaspApp : public ClaspAppBase {
+public:
+	ClaspApp();
+	const char* getName()       const { return "clasp"; }
+	const char* getVersion()    const { return CLASP_VERSION; }
+	const char* getUsage()      const {
+		return
+			"[number] [options] [file]\n"
+			"Compute at most  models (0=all) of the instance given in ";
+	}
+protected:
+	virtual ProblemType getProblemType();
+	virtual void        run(ClaspFacade& clasp);
+	virtual void        printHelp(const ProgramOptions::OptionContext& root);
+private:
+	ClaspApp(const ClaspApp&);
+	ClaspApp& operator=(const ClaspApp&);
+};
+}}
+#endif
diff --git a/app/clingo/src/clingo_app.cc b/app/clingo/src/clingo_app.cc
new file mode 100644
index 0000000..51a2a21
--- /dev/null
+++ b/app/clingo/src/clingo_app.cc
@@ -0,0 +1,213 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+// Copyright (C) 2013  Roland Kaminski
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#ifdef WITH_PYTHON
+#  include 
+#endif
+#ifdef WITH_LUA
+#  include 
+#endif
+#include "clingo_app.hh"
+#include 
+#include 
+
+using namespace Clasp;
+using namespace Clasp::Cli;
+
+// {{{ declaration of ClingoApp
+
+ClingoApp::ClingoApp() { }
+
+static bool parseConst(const std::string& str, std::vector& out) {
+    out.push_back(str);
+    return true;
+}
+
+static bool parseText(const std::string&, ClingoOptions& out) {
+    out.outputFormat = Gringo::Output::OutputFormat::TEXT;
+    return true;
+}
+
+void ClingoApp::initOptions(ProgramOptions::OptionContext& root) {
+    using namespace ProgramOptions;
+    BaseType::initOptions(root);
+    grOpts_.defines.clear();
+    grOpts_.verbose = false;
+    OptionGroup gringo("Gringo Options");
+    gringo.addOptions()
+        ("text", storeTo(grOpts_, parseText)->flag(), "Print plain text format")
+        ("const,c", storeTo(grOpts_.defines, parseConst)->composing()->arg("="), "Replace term occurrences of  with ")
+        ("output,o", storeTo(grOpts_.outputFormat = Gringo::Output::OutputFormat::INTERMEDIATE, values()
+          ("intermediate", Gringo::Output::OutputFormat::INTERMEDIATE)
+          ("text", Gringo::Output::OutputFormat::TEXT)
+          ("reify", Gringo::Output::OutputFormat::REIFY)
+          ("smodels", Gringo::Output::OutputFormat::SMODELS)), "Choose output format:\n"
+             "      intermediate: print intermediate format\n"
+             "      text        : print plain text format\n"
+             "      reify       : print program as reified facts\n"
+             "      smodels     : print smodels format\n"
+             "                    (only supports basic features)")
+        ("output-debug", storeTo(grOpts_.outputOptions.debug = Gringo::Output::OutputDebug::NONE, values()
+          ("none", Gringo::Output::OutputDebug::NONE)
+          ("text", Gringo::Output::OutputDebug::TEXT)
+          ("translate", Gringo::Output::OutputDebug::TRANSLATE)
+          ("all", Gringo::Output::OutputDebug::ALL)), "Print debug information during output:\n"
+         "      none     : no additional info\n"
+         "      text     : print rules as plain text (prefix %%)\n"
+         "      translate: print translated rules as plain text (prefix %%%%)\n"
+         "      all      : combines text and translate")
+        ("warn,W"                   , storeTo(grOpts_, parseWarning)->arg("")->composing(), "Enable/disable warnings:\n"
+         "      none:                     disable all warnings\n"
+         "      all:                      enable all warnings\n"
+         "      [no-]atom-undefined:      a :- b.\n"
+         "      [no-]file-included:       #include \"a.lp\". #include \"a.lp\".\n"
+         "      [no-]operation-undefined: p(1/0).\n"
+         "      [no-]variable-unbounded:  $x > 10.\n"
+         "      [no-]global-variable:     :- #count { X } = 1, X = 1.\n"
+         "      [no-]other:               clasp related and uncategorized warnings")
+        ("rewrite-minimize"         , flag(grOpts_.rewriteMinimize = false), "Rewrite minimize constraints into rules")
+        ("keep-facts"               , flag(grOpts_.keepFacts = false), "Do not remove facts from normal rules")
+        ("reify-sccs"               , flag(grOpts_.outputOptions.reifySCCs = false), "Calculate SCCs for reified output")
+        ("reify-steps"              , flag(grOpts_.outputOptions.reifySteps = false), "Add step numbers to reified output")
+        ("foobar,@4"                , storeTo(grOpts_.foobar, parseFoobar) , "Foobar")
+        ;
+    root.add(gringo);
+
+    OptionGroup basic("Basic Options");
+    basic.addOptions()
+        ("mode", storeTo(mode_ = mode_clingo, values()
+            ("clingo", mode_clingo)
+            ("clasp", mode_clasp)
+            ("gringo", mode_gringo)),
+         "Run in {clingo|clasp|gringo} mode\n")
+        ;
+    root.add(basic);
+}
+
+void ClingoApp::validateOptions(const ProgramOptions::OptionContext& root, const ProgramOptions::ParsedOptions& parsed, const ProgramOptions::ParsedValues& vals) {
+    BaseType::validateOptions(root, parsed, vals);
+    if (parsed.count("text") > 0) {
+        if (parsed.count("output") > 0) {
+            error("'--text' and '--output' are mutually exclusive!");
+            exit(E_NO_RUN);
+        }
+        if (parsed.count("mode") > 0 && mode_ != mode_gringo) {
+            error("'--text' can only be used with '--mode=gringo'!");
+            exit(E_NO_RUN);
+        }
+        mode_ = mode_gringo;
+    }
+    if (parsed.count("output") > 0) {
+        if (parsed.count("mode") > 0 && mode_ != mode_gringo) {
+            error("'--output' can only be used with '--mode=gringo'!");
+            exit(E_NO_RUN);
+        }
+        mode_ = mode_gringo;
+    }
+}
+
+ProblemType ClingoApp::getProblemType() {
+    if (mode_ != mode_clasp) return Problem_t::Asp;
+    return ClaspFacade::detectProblemType(getStream());
+}
+Output* ClingoApp::createOutput(ProblemType f) {
+    if (mode_ == mode_gringo) return 0;
+    return BaseType::createOutput(f);
+}
+
+void ClingoApp::printHelp(const ProgramOptions::OptionContext& root) {
+    BaseType::printHelp(root);
+    printf("\nclingo is part of Potassco: %s\n", "https://potassco.org/clingo");
+    printf("Get help/report bugs via : https://potassco.org/support\n");
+    fflush(stdout);
+}
+
+void ClingoApp::printVersion() {
+    ProgramOptions::Application::printVersion();
+    printf("\n");
+    printf("libgringo version " GRINGO_VERSION "\n");
+    printf("Configuration: "
+#ifdef WITH_PYTHON
+        "with Python " PY_VERSION
+#else
+        "without Python"
+#endif
+        ", "
+#ifdef WITH_LUA
+        "with " LUA_RELEASE
+#else
+        "without Lua"
+#endif
+        "\n");
+    printf("Copyright (C) Roland Kaminski\n");
+    printf("License GPLv3+: GNU GPL version 3 or later \n");
+    printf("Gringo is free software: you are free to change and redistribute it.\n");
+    printf("There is NO WARRANTY, to the extent permitted by law.\n");
+    printf("\n");
+    BaseType::printLibClaspVersion();
+}
+bool ClingoApp::onModel(Clasp::Solver const& s, Clasp::Model const& m) {
+    bool ret = !grd || grd->onModel(m);
+    return BaseType::onModel(s, m) && ret;
+}
+void ClingoApp::shutdown() {
+    // TODO: can be removed in future...
+    //       or could be bound differently given the new interface...
+#if WITH_THREADS
+    if (grd) {
+        grd->solveIter_   = nullptr;
+        grd->solveFuture_ = nullptr;
+    }
+#endif
+    Clasp::Cli::ClaspAppBase::shutdown();
+}
+void ClingoApp::onEvent(Event const& ev) {
+#if WITH_THREADS
+    Clasp::ClaspFacade::StepReady const *r = Clasp::event_cast(ev);
+    if (r && grd) { grd->onFinish(r->summary->result); }
+#endif
+    BaseType::onEvent(ev);
+}
+void ClingoApp::run(Clasp::ClaspFacade& clasp) {
+    try {
+        using namespace std::placeholders;
+        if (mode_ != mode_clasp) {
+            ProblemType     pt  = getProblemType();
+            ProgramBuilder* prg = &clasp.start(claspConfig_, pt);
+            grOpts_.verbose = verbose() == UINT_MAX;
+            Asp::LogicProgram* lp = mode_ != mode_gringo ? static_cast(prg) : 0;
+            grd = Gringo::gringo_make_unique(module.scripts, mode_ == mode_clingo, clasp_.get(), claspConfig_, std::bind(&ClingoApp::handlePostGroundOptions, this, _1), std::bind(&ClingoApp::handlePreSolveOptions, this, _1), nullptr, 20);
+            grd->parse(claspAppOpts_.input, grOpts_, lp);
+            grd->main();
+        }
+        else {
+            ClaspAppBase::run(clasp);
+        }
+    }
+    catch (Gringo::GringoError const &e) {
+        std::cerr << e.what() << std::endl;
+        throw std::runtime_error("fatal error");
+    }
+    catch (...) { throw; }
+}
+
+// }}}
+
diff --git a/app/clingo/src/clingo_app.hh b/app/clingo/src/clingo_app.hh
new file mode 100644
index 0000000..2503708
--- /dev/null
+++ b/app/clingo/src/clingo_app.hh
@@ -0,0 +1,68 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+// Copyright (C) 2013  Roland Kaminski
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#ifndef _GRINGO_CLINGOAPP_HH
+#define _GRINGO_CLINGOAPP_HH
+
+#include "clasp/clasp_app.h"
+#include "gringo/version.hh"
+#include "clingo/clingocontrol.hh"
+
+// Standalone clingo application.
+class ClingoApp : public Clasp::Cli::ClaspAppBase {
+    using StringVec   = std::vector;
+    using Output      = Clasp::Cli::Output;
+    using ProblemType = Clasp::ProblemType;
+    using BaseType    = Clasp::Cli::ClaspAppBase;
+    enum class ConfigUpdate { KEEP, REPLACE };
+public:
+    ClingoApp();
+    const char* getName()    const override { return "clingo"; }
+    const char* getVersion() const override { return GRINGO_VERSION; }
+    const char* getUsage()   const override { return "[number] [options] [files]"; }
+
+    void shutdown() override;
+protected:
+    enum Mode { mode_clingo = 0, mode_clasp = 1, mode_gringo = 2 };
+    void        initOptions(ProgramOptions::OptionContext& root) override;
+    void        validateOptions(const ProgramOptions::OptionContext& root, const ProgramOptions::ParsedOptions& parsed, const ProgramOptions::ParsedValues& vals) override;
+
+    ProblemType getProblemType() override;
+    void        run(Clasp::ClaspFacade& clasp) override;
+    Output*     createOutput(ProblemType f) override;
+    void        printHelp(const ProgramOptions::OptionContext& root) override;
+    void        printVersion() override;
+
+    // -------------------------------------------------------------------------------------------
+    // Event handler
+    void onEvent(const Clasp::Event& ev) override;
+    bool onModel(const Clasp::Solver& s, const Clasp::Model& m) override;
+    // -------------------------------------------------------------------------------------------
+private:
+    ClingoApp(const ClingoApp&);
+    ClingoApp& operator=(const ClingoApp&);
+    ClingoOptions grOpts_;
+    Mode mode_;
+    DefaultGringoModule module;
+    std::unique_ptr grd;
+};
+
+#endif // _GRINGO_CLINGOAPP_HH
diff --git a/app/clingo/src/main.cc b/app/clingo/src/main.cc
new file mode 100644
index 0000000..c923e61
--- /dev/null
+++ b/app/clingo/src/main.cc
@@ -0,0 +1,27 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#include "clingo_app.hh"
+
+int main(int argc, char** argv) {
+    ClingoApp app;
+    return app.main(argc, argv);
+}
+
diff --git a/app/clingo/tests/lp/bio.cmd b/app/clingo/tests/lp/bio.cmd
new file mode 100644
index 0000000..8b9b36d
--- /dev/null
+++ b/app/clingo/tests/lp/bio.cmd
@@ -0,0 +1 @@
+--opt-mode=optN -q1,1
diff --git a/app/clingo/tests/lp/bio.lp b/app/clingo/tests/lp/bio.lp
new file mode 100644
index 0000000..bf4ac26
--- /dev/null
+++ b/app/clingo/tests/lp/bio.lp
@@ -0,0 +1,37 @@
+#const h=3.
+
+time(0..h).
+volume(1..10).
+
+0 $<= $b(T) $<= 20 :- time(T).
+0 $<= $f(T) $<= 20 :- time(T).
+
+1 $<= $m $<= 16.
+
+$b(0) $= 10.
+$f(0) $= 10.
+
+$b(T) $= 2 $* $b(T-1) $- $m      :- time(T), T>0.
+$f(T) $=      $f(T-1) $- $b(T-1) :- time(T), T>0, not exogenous(T).
+
+$f(T) $=      $f(T-1) $- $b(T-1) $+ V :- add(V,T), volume(V), time(T), T>0.
+
+ { add(V,T) : volume(V) } 1 :- time(T), T>0.
+
+exogenous(T) :- add(V,T).
+
+#minimize{ 1@2,T : exogenous(T) }.
+#minimize{ V@1,T : add(V,T) }.
+#minimize{ 1@3,X : $m $>= X, X=1..16 }.
+
+query(T) :- $b(T) $>10, $f(T) $<5, time(T), T>0.
+% query(T) :- $b(T) $> 10, time(T), T>0.
+
+ :- not query(h).
+
+#show.
+#show $b/1.
+#show $f/1.
+#show add/2.
+#show $m/0.
+
diff --git a/app/clingo/tests/lp/bio.sol b/app/clingo/tests/lp/bio.sol
new file mode 100644
index 0000000..96a297e
--- /dev/null
+++ b/app/clingo/tests/lp/bio.sol
@@ -0,0 +1,30 @@
+Step: 1
+add(10,1) add(10,2) add(4,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=9 f(3)=0 m=9
+add(10,1) add(10,3) add(4,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=3 f(3)=0 m=9
+add(10,1) add(5,2) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=4 f(3)=0 m=9
+add(10,1) add(5,3) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=8 f(3)=0 m=9
+add(10,1) add(6,2) add(8,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=5 f(3)=0 m=9
+add(10,1) add(6,3) add(8,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=7 f(3)=0 m=9
+add(10,1) add(7,2) add(7,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=10 f(2)=6 f(3)=0 m=9
+add(10,2) add(10,3) add(4,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=4 f(2)=3 f(3)=0 m=9
+add(10,2) add(5,1) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=5 f(2)=4 f(3)=0 m=9
+add(10,2) add(5,3) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=8 f(3)=0 m=9
+add(10,2) add(6,1) add(8,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=6 f(2)=5 f(3)=0 m=9
+add(10,2) add(6,3) add(8,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=7 f(3)=0 m=9
+add(10,2) add(7,1) add(7,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=6 f(3)=0 m=9
+add(10,3) add(5,1) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=5 f(2)=3 f(3)=0 m=9
+add(10,3) add(5,2) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=3 f(3)=0 m=9
+add(10,3) add(6,1) add(8,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=6 f(2)=3 f(3)=0 m=9
+add(10,3) add(6,2) add(8,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=3 f(3)=0 m=9
+add(10,3) add(7,1) add(7,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=3 f(3)=0 m=9
+add(6,1) add(9,2) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=6 f(2)=4 f(3)=0 m=9
+add(6,2) add(9,1) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=4 f(3)=0 m=9
+add(6,3) add(9,1) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=7 f(3)=0 m=9
+add(7,1) add(8,2) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=4 f(3)=0 m=9
+add(7,1) add(8,3) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=7 f(2)=5 f(3)=0 m=9
+add(7,2) add(8,1) add(9,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=4 f(3)=0 m=9
+add(7,2) add(8,3) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=5 f(3)=0 m=9
+add(7,3) add(8,1) add(9,2) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=6 f(3)=0 m=9
+add(7,3) add(8,2) add(9,1) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=9 f(2)=6 f(3)=0 m=9
+add(8,1) add(8,2) add(8,3) b(0)=10 b(1)=11 b(2)=13 b(3)=17 f(0)=10 f(1)=8 f(2)=5 f(3)=0 m=9
+OPTIMUM FOUND
diff --git a/app/clingo/tests/lp/project.cmd b/app/clingo/tests/lp/project.cmd
new file mode 100644
index 0000000..2561c66
--- /dev/null
+++ b/app/clingo/tests/lp/project.cmd
@@ -0,0 +1 @@
+--project
diff --git a/app/clingo/tests/lp/project.lp b/app/clingo/tests/lp/project.lp
new file mode 100644
index 0000000..09284d2
--- /dev/null
+++ b/app/clingo/tests/lp/project.lp
@@ -0,0 +1,7 @@
+#project p(X).
+#show p/1.
+
+1 { p(1..2) } 1.
+1 { q(1..2) } 1.
+
+
diff --git a/app/clingo/tests/lp/project.sol b/app/clingo/tests/lp/project.sol
new file mode 100644
index 0000000..96c5d94
--- /dev/null
+++ b/app/clingo/tests/lp/project.sol
@@ -0,0 +1,4 @@
+Step: 1
+p(1)
+p(2)
+SAT
diff --git a/app/clingo/tests/lp/show.lp b/app/clingo/tests/lp/show.lp
new file mode 100644
index 0000000..804cdda
--- /dev/null
+++ b/app/clingo/tests/lp/show.lp
@@ -0,0 +1,16 @@
+#include .
+#show show/0.
+#const imin=4.
+
+1 { p(1..4) } 1.
+
+#show p(X) : p(X).
+
+#program step(k).
+
+q(k+1), k < 3.
+:- p(X), q(X), k < 3.
+
+{show} :- k == 3.
+#show p(1..4) : show, k == 3.
+
diff --git a/app/clingo/tests/lp/show.sol b/app/clingo/tests/lp/show.sol
new file mode 100644
index 0000000..3c12471
--- /dev/null
+++ b/app/clingo/tests/lp/show.sol
@@ -0,0 +1,25 @@
+Step: 1
+p(1)
+p(2)
+p(3)
+p(4)
+Step: 2
+p(1)
+p(2)
+p(3)
+p(4)
+Step: 3
+p(1)
+p(2)
+p(3)
+p(4)
+Step: 4
+p(1)
+p(1) p(2) p(3) p(4) show
+p(1) p(2) p(3) p(4) show
+p(1) p(2) p(3) p(4) show
+p(1) p(2) p(3) p(4) show
+p(2)
+p(3)
+p(4)
+SAT
diff --git a/app/clingo/tests/lp/subset.cmd b/app/clingo/tests/lp/subset.cmd
new file mode 100644
index 0000000..6f9a85a
--- /dev/null
+++ b/app/clingo/tests/lp/subset.cmd
@@ -0,0 +1 @@
+--heuristic=domain
diff --git a/app/clingo/tests/lp/subset.lp b/app/clingo/tests/lp/subset.lp
new file mode 100644
index 0000000..17cc614
--- /dev/null
+++ b/app/clingo/tests/lp/subset.lp
@@ -0,0 +1,12 @@
+#heuristic p(1..2). [1,false]
+#heuristic p(2..3). [2@1,true]
+#heuristic p(3..4). [1,sign]
+#heuristic p(4..5). [2@3,level]
+#heuristic p(5..6). [3@4,factor]
+#heuristic p(6..7). [3@4,init]
+
+3 { p(1..10) }.
+2 { p(1..5) }.
+4 { p(3..8) }.
+2 { p(7..9) }.
+3 { p(2..9) }.
diff --git a/app/clingo/tests/lp/subset.sol b/app/clingo/tests/lp/subset.sol
new file mode 100644
index 0000000..8945e4b
--- /dev/null
+++ b/app/clingo/tests/lp/subset.sol
@@ -0,0 +1,246 @@
+Step: 1
+p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8)
+p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(9)
+p(1) p(10) p(2) p(3) p(4) p(5) p(6) p(8) p(9)
+p(1) p(10) p(2) p(3) p(4) p(5) p(7) p(8)
+p(1) p(10) p(2) p(3) p(4) p(5) p(7) p(8) p(9)
+p(1) p(10) p(2) p(3) p(4) p(5) p(7) p(9)
+p(1) p(10) p(2) p(3) p(4) p(5) p(8) p(9)
+p(1) p(10) p(2) p(3) p(4) p(6) p(7) p(8)
+p(1) p(10) p(2) p(3) p(4) p(6) p(7) p(8) p(9)
+p(1) p(10) p(2) p(3) p(4) p(6) p(7) p(9)
+p(1) p(10) p(2) p(3) p(4) p(6) p(8) p(9)
+p(1) p(10) p(2) p(3) p(4) p(7) p(8)
+p(1) p(10) p(2) p(3) p(4) p(7) p(8) p(9)
+p(1) p(10) p(2) p(3) p(5) p(6) p(7) p(8)
+p(1) p(10) p(2) p(3) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(2) p(3) p(5) p(6) p(7) p(9)
+p(1) p(10) p(2) p(3) p(5) p(6) p(8) p(9)
+p(1) p(10) p(2) p(3) p(5) p(7) p(8)
+p(1) p(10) p(2) p(3) p(5) p(7) p(8) p(9)
+p(1) p(10) p(2) p(3) p(6) p(7) p(8)
+p(1) p(10) p(2) p(3) p(6) p(7) p(8) p(9)
+p(1) p(10) p(2) p(4) p(5) p(6) p(7) p(8)
+p(1) p(10) p(2) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(2) p(4) p(5) p(6) p(7) p(9)
+p(1) p(10) p(2) p(4) p(5) p(6) p(8) p(9)
+p(1) p(10) p(2) p(4) p(5) p(7) p(8)
+p(1) p(10) p(2) p(4) p(5) p(7) p(8) p(9)
+p(1) p(10) p(2) p(4) p(6) p(7) p(8)
+p(1) p(10) p(2) p(4) p(6) p(7) p(8) p(9)
+p(1) p(10) p(2) p(5) p(6) p(7) p(8)
+p(1) p(10) p(2) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(3) p(4) p(5) p(6) p(7) p(8)
+p(1) p(10) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(3) p(4) p(5) p(6) p(7) p(9)
+p(1) p(10) p(3) p(4) p(5) p(6) p(8) p(9)
+p(1) p(10) p(3) p(4) p(5) p(7) p(8)
+p(1) p(10) p(3) p(4) p(5) p(7) p(8) p(9)
+p(1) p(10) p(3) p(4) p(5) p(7) p(9)
+p(1) p(10) p(3) p(4) p(5) p(8) p(9)
+p(1) p(10) p(3) p(4) p(6) p(7) p(8)
+p(1) p(10) p(3) p(4) p(6) p(7) p(8) p(9)
+p(1) p(10) p(3) p(4) p(6) p(7) p(9)
+p(1) p(10) p(3) p(4) p(6) p(8) p(9)
+p(1) p(10) p(3) p(4) p(7) p(8)
+p(1) p(10) p(3) p(4) p(7) p(8) p(9)
+p(1) p(10) p(3) p(5) p(6) p(7) p(8)
+p(1) p(10) p(3) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(3) p(5) p(6) p(7) p(9)
+p(1) p(10) p(3) p(5) p(6) p(8) p(9)
+p(1) p(10) p(3) p(5) p(7) p(8)
+p(1) p(10) p(3) p(5) p(7) p(8) p(9)
+p(1) p(10) p(3) p(6) p(7) p(8)
+p(1) p(10) p(3) p(6) p(7) p(8) p(9)
+p(1) p(10) p(4) p(5) p(6) p(7) p(8)
+p(1) p(10) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(10) p(4) p(5) p(6) p(7) p(9)
+p(1) p(10) p(4) p(5) p(6) p(8) p(9)
+p(1) p(10) p(4) p(5) p(7) p(8)
+p(1) p(10) p(4) p(5) p(7) p(8) p(9)
+p(1) p(10) p(4) p(6) p(7) p(8)
+p(1) p(10) p(4) p(6) p(7) p(8) p(9)
+p(1) p(10) p(5) p(6) p(7) p(8)
+p(1) p(10) p(5) p(6) p(7) p(8) p(9)
+p(1) p(2) p(3) p(4) p(5) p(6) p(7) p(8)
+p(1) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(2) p(3) p(4) p(5) p(6) p(7) p(9)
+p(1) p(2) p(3) p(4) p(5) p(6) p(8) p(9)
+p(1) p(2) p(3) p(4) p(5) p(7) p(8)
+p(1) p(2) p(3) p(4) p(5) p(7) p(8) p(9)
+p(1) p(2) p(3) p(4) p(5) p(7) p(9)
+p(1) p(2) p(3) p(4) p(5) p(8) p(9)
+p(1) p(2) p(3) p(4) p(6) p(7) p(8)
+p(1) p(2) p(3) p(4) p(6) p(7) p(8) p(9)
+p(1) p(2) p(3) p(4) p(6) p(7) p(9)
+p(1) p(2) p(3) p(4) p(6) p(8) p(9)
+p(1) p(2) p(3) p(4) p(7) p(8)
+p(1) p(2) p(3) p(4) p(7) p(8) p(9)
+p(1) p(2) p(3) p(5) p(6) p(7) p(8)
+p(1) p(2) p(3) p(5) p(6) p(7) p(8) p(9)
+p(1) p(2) p(3) p(5) p(6) p(7) p(9)
+p(1) p(2) p(3) p(5) p(6) p(8) p(9)
+p(1) p(2) p(3) p(5) p(7) p(8)
+p(1) p(2) p(3) p(5) p(7) p(8) p(9)
+p(1) p(2) p(3) p(6) p(7) p(8)
+p(1) p(2) p(3) p(6) p(7) p(8) p(9)
+p(1) p(2) p(4) p(5) p(6) p(7) p(8)
+p(1) p(2) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(2) p(4) p(5) p(6) p(7) p(9)
+p(1) p(2) p(4) p(5) p(6) p(8) p(9)
+p(1) p(2) p(4) p(5) p(7) p(8)
+p(1) p(2) p(4) p(5) p(7) p(8) p(9)
+p(1) p(2) p(4) p(6) p(7) p(8)
+p(1) p(2) p(4) p(6) p(7) p(8) p(9)
+p(1) p(2) p(5) p(6) p(7) p(8)
+p(1) p(2) p(5) p(6) p(7) p(8) p(9)
+p(1) p(3) p(4) p(5) p(6) p(7) p(8)
+p(1) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(3) p(4) p(5) p(6) p(7) p(9)
+p(1) p(3) p(4) p(5) p(6) p(8) p(9)
+p(1) p(3) p(4) p(5) p(7) p(8)
+p(1) p(3) p(4) p(5) p(7) p(8) p(9)
+p(1) p(3) p(4) p(5) p(7) p(9)
+p(1) p(3) p(4) p(5) p(8) p(9)
+p(1) p(3) p(4) p(6) p(7) p(8)
+p(1) p(3) p(4) p(6) p(7) p(8) p(9)
+p(1) p(3) p(4) p(6) p(7) p(9)
+p(1) p(3) p(4) p(6) p(8) p(9)
+p(1) p(3) p(4) p(7) p(8)
+p(1) p(3) p(4) p(7) p(8) p(9)
+p(1) p(3) p(5) p(6) p(7) p(8)
+p(1) p(3) p(5) p(6) p(7) p(8) p(9)
+p(1) p(3) p(5) p(6) p(7) p(9)
+p(1) p(3) p(5) p(6) p(8) p(9)
+p(1) p(3) p(5) p(7) p(8)
+p(1) p(3) p(5) p(7) p(8) p(9)
+p(1) p(3) p(6) p(7) p(8)
+p(1) p(3) p(6) p(7) p(8) p(9)
+p(1) p(4) p(5) p(6) p(7) p(8)
+p(1) p(4) p(5) p(6) p(7) p(8) p(9)
+p(1) p(4) p(5) p(6) p(7) p(9)
+p(1) p(4) p(5) p(6) p(8) p(9)
+p(1) p(4) p(5) p(7) p(8)
+p(1) p(4) p(5) p(7) p(8) p(9)
+p(1) p(4) p(6) p(7) p(8)
+p(1) p(4) p(6) p(7) p(8) p(9)
+p(1) p(5) p(6) p(7) p(8)
+p(1) p(5) p(6) p(7) p(8) p(9)
+p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8)
+p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(10) p(2) p(3) p(4) p(5) p(6) p(7) p(9)
+p(10) p(2) p(3) p(4) p(5) p(6) p(8) p(9)
+p(10) p(2) p(3) p(4) p(5) p(7) p(8)
+p(10) p(2) p(3) p(4) p(5) p(7) p(8) p(9)
+p(10) p(2) p(3) p(4) p(5) p(7) p(9)
+p(10) p(2) p(3) p(4) p(5) p(8) p(9)
+p(10) p(2) p(3) p(4) p(6) p(7) p(8)
+p(10) p(2) p(3) p(4) p(6) p(7) p(8) p(9)
+p(10) p(2) p(3) p(4) p(6) p(7) p(9)
+p(10) p(2) p(3) p(4) p(6) p(8) p(9)
+p(10) p(2) p(3) p(4) p(7) p(8)
+p(10) p(2) p(3) p(4) p(7) p(8) p(9)
+p(10) p(2) p(3) p(5) p(6) p(7) p(8)
+p(10) p(2) p(3) p(5) p(6) p(7) p(8) p(9)
+p(10) p(2) p(3) p(5) p(6) p(7) p(9)
+p(10) p(2) p(3) p(5) p(6) p(8) p(9)
+p(10) p(2) p(3) p(5) p(7) p(8)
+p(10) p(2) p(3) p(5) p(7) p(8) p(9)
+p(10) p(2) p(3) p(6) p(7) p(8)
+p(10) p(2) p(3) p(6) p(7) p(8) p(9)
+p(10) p(2) p(4) p(5) p(6) p(7) p(8)
+p(10) p(2) p(4) p(5) p(6) p(7) p(8) p(9)
+p(10) p(2) p(4) p(5) p(6) p(7) p(9)
+p(10) p(2) p(4) p(5) p(6) p(8) p(9)
+p(10) p(2) p(4) p(5) p(7) p(8)
+p(10) p(2) p(4) p(5) p(7) p(8) p(9)
+p(10) p(2) p(4) p(6) p(7) p(8)
+p(10) p(2) p(4) p(6) p(7) p(8) p(9)
+p(10) p(2) p(5) p(6) p(7) p(8)
+p(10) p(2) p(5) p(6) p(7) p(8) p(9)
+p(10) p(3) p(4) p(5) p(6) p(7) p(8)
+p(10) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(10) p(3) p(4) p(5) p(6) p(7) p(9)
+p(10) p(3) p(4) p(5) p(6) p(8) p(9)
+p(10) p(3) p(4) p(5) p(7) p(8)
+p(10) p(3) p(4) p(5) p(7) p(8) p(9)
+p(10) p(3) p(4) p(5) p(7) p(9)
+p(10) p(3) p(4) p(5) p(8) p(9)
+p(10) p(3) p(4) p(6) p(7) p(8)
+p(10) p(3) p(4) p(6) p(7) p(8) p(9)
+p(10) p(3) p(4) p(6) p(7) p(9)
+p(10) p(3) p(4) p(6) p(8) p(9)
+p(10) p(3) p(4) p(7) p(8)
+p(10) p(3) p(4) p(7) p(8) p(9)
+p(10) p(3) p(5) p(6) p(7) p(8)
+p(10) p(3) p(5) p(6) p(7) p(8) p(9)
+p(10) p(3) p(5) p(6) p(7) p(9)
+p(10) p(3) p(5) p(6) p(8) p(9)
+p(10) p(3) p(5) p(7) p(8)
+p(10) p(3) p(5) p(7) p(8) p(9)
+p(10) p(4) p(5) p(6) p(7) p(8)
+p(10) p(4) p(5) p(6) p(7) p(8) p(9)
+p(10) p(4) p(5) p(6) p(7) p(9)
+p(10) p(4) p(5) p(6) p(8) p(9)
+p(10) p(4) p(5) p(7) p(8)
+p(10) p(4) p(5) p(7) p(8) p(9)
+p(2) p(3) p(4) p(5) p(6) p(7) p(8)
+p(2) p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(2) p(3) p(4) p(5) p(6) p(7) p(9)
+p(2) p(3) p(4) p(5) p(6) p(8) p(9)
+p(2) p(3) p(4) p(5) p(7) p(8)
+p(2) p(3) p(4) p(5) p(7) p(8) p(9)
+p(2) p(3) p(4) p(5) p(7) p(9)
+p(2) p(3) p(4) p(5) p(8) p(9)
+p(2) p(3) p(4) p(6) p(7) p(8)
+p(2) p(3) p(4) p(6) p(7) p(8) p(9)
+p(2) p(3) p(4) p(6) p(7) p(9)
+p(2) p(3) p(4) p(6) p(8) p(9)
+p(2) p(3) p(4) p(7) p(8)
+p(2) p(3) p(4) p(7) p(8) p(9)
+p(2) p(3) p(5) p(6) p(7) p(8)
+p(2) p(3) p(5) p(6) p(7) p(8) p(9)
+p(2) p(3) p(5) p(6) p(7) p(9)
+p(2) p(3) p(5) p(6) p(8) p(9)
+p(2) p(3) p(5) p(7) p(8)
+p(2) p(3) p(5) p(7) p(8) p(9)
+p(2) p(3) p(6) p(7) p(8)
+p(2) p(3) p(6) p(7) p(8) p(9)
+p(2) p(4) p(5) p(6) p(7) p(8)
+p(2) p(4) p(5) p(6) p(7) p(8) p(9)
+p(2) p(4) p(5) p(6) p(7) p(9)
+p(2) p(4) p(5) p(6) p(8) p(9)
+p(2) p(4) p(5) p(7) p(8)
+p(2) p(4) p(5) p(7) p(8) p(9)
+p(2) p(4) p(6) p(7) p(8)
+p(2) p(4) p(6) p(7) p(8) p(9)
+p(2) p(5) p(6) p(7) p(8)
+p(2) p(5) p(6) p(7) p(8) p(9)
+p(3) p(4) p(5) p(6) p(7) p(8)
+p(3) p(4) p(5) p(6) p(7) p(8) p(9)
+p(3) p(4) p(5) p(6) p(7) p(9)
+p(3) p(4) p(5) p(6) p(8) p(9)
+p(3) p(4) p(5) p(7) p(8)
+p(3) p(4) p(5) p(7) p(8) p(9)
+p(3) p(4) p(5) p(7) p(9)
+p(3) p(4) p(5) p(8) p(9)
+p(3) p(4) p(6) p(7) p(8)
+p(3) p(4) p(6) p(7) p(8) p(9)
+p(3) p(4) p(6) p(7) p(9)
+p(3) p(4) p(6) p(8) p(9)
+p(3) p(4) p(7) p(8)
+p(3) p(4) p(7) p(8) p(9)
+p(3) p(5) p(6) p(7) p(8)
+p(3) p(5) p(6) p(7) p(8) p(9)
+p(3) p(5) p(6) p(7) p(9)
+p(3) p(5) p(6) p(8) p(9)
+p(3) p(5) p(7) p(8)
+p(3) p(5) p(7) p(8) p(9)
+p(4) p(5) p(6) p(7) p(8)
+p(4) p(5) p(6) p(7) p(8) p(9)
+p(4) p(5) p(6) p(7) p(9)
+p(4) p(5) p(6) p(8) p(9)
+p(4) p(5) p(7) p(8)
+p(4) p(5) p(7) p(8) p(9)
+SAT
diff --git a/app/clingo/tests/lua/assumptions1.lp b/app/clingo/tests/lua/assumptions1.lp
new file mode 100644
index 0000000..164e935
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions1.lp
@@ -0,0 +1,11 @@
+#script (lua)
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:solve(nil, {{clingo.Function("a"), true}})
+end
+
+#end.
+
+{ a }.
+b :- a.
diff --git a/app/clingo/tests/lua/assumptions1.sol b/app/clingo/tests/lua/assumptions1.sol
new file mode 100644
index 0000000..97448c9
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions1.sol
@@ -0,0 +1,3 @@
+Step: 1
+a b
+SAT
diff --git a/app/clingo/tests/lua/assumptions2.lp b/app/clingo/tests/lua/assumptions2.lp
new file mode 100644
index 0000000..8fb2ff8
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions2.lp
@@ -0,0 +1,11 @@
+#script (lua)
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:solve(nil, {{clingo.Function("b"), true}})
+end
+
+#end.
+
+{ a }.
+b :- a.
diff --git a/app/clingo/tests/lua/assumptions2.sol b/app/clingo/tests/lua/assumptions2.sol
new file mode 100644
index 0000000..97448c9
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions2.sol
@@ -0,0 +1,3 @@
+Step: 1
+a b
+SAT
diff --git a/app/clingo/tests/lua/assumptions3.lp b/app/clingo/tests/lua/assumptions3.lp
new file mode 100644
index 0000000..8d3c1e7
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions3.lp
@@ -0,0 +1,12 @@
+#script (lua)
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:solve(nil, {{clingo.Function("a"), true}, {clingo.Function("b"), false}, {clingo.Function("d"), true}})
+    prg:solve(nil, {{clingo.Function("a"), false}, {clingo.Function("c"), true}})
+end
+
+#end.
+
+#external d.
+{ a; b; c }.
diff --git a/app/clingo/tests/lua/assumptions3.sol b/app/clingo/tests/lua/assumptions3.sol
new file mode 100644
index 0000000..589474a
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions3.sol
@@ -0,0 +1,5 @@
+Step: 1
+Step: 2
+b c
+c
+SAT
diff --git a/app/clingo/tests/lua/assumptions4.lp b/app/clingo/tests/lua/assumptions4.lp
new file mode 100644
index 0000000..c05a6f4
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions4.lp
@@ -0,0 +1,26 @@
+#script (lua)
+
+function on_model(m)
+    return true
+end
+
+function on_finish(ret)
+end
+
+function main(prg)
+    local assumptions = {{clingo.Function("a"), true}}
+    prg:ground({{"base", {}}})
+    prg:solve(on_model, assumptions)
+    prg:solve(on_model, assumptions)
+    local it = prg:solve_iter(assumptions)
+    local ret = pcall(function()
+        for m in it:iter() do
+        end
+    end)
+    it:close()
+end
+
+#end.
+
+{ a }.
+b :- a.
diff --git a/app/clingo/tests/lua/assumptions4.sol b/app/clingo/tests/lua/assumptions4.sol
new file mode 100644
index 0000000..9e8af8d
--- /dev/null
+++ b/app/clingo/tests/lua/assumptions4.sol
@@ -0,0 +1,7 @@
+Step: 1
+a b
+Step: 2
+a b
+Step: 3
+a b
+SAT
diff --git a/app/clingo/tests/lua/blocksworld1.lp b/app/clingo/tests/lua/blocksworld1.lp
new file mode 100644
index 0000000..382e2ad
--- /dev/null
+++ b/app/clingo/tests/lua/blocksworld1.lp
@@ -0,0 +1,231 @@
+% show instances of selected predicates only
+#show.
+
+% output stack representation
+#show order/4.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for generating states providing relative block positions, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program state(k,t).
+
+% a block's scope includes the table (labeled 0) and blocks with smaller numbers
+scope(k,0,t).
+scope(k,I,t) :- scope(I,0,t), I < k.
+
+% order(1,k,I,t) provides the closest block I in scope above k, if any at time t
+#count{ I : order(1,k,I,t) : scope(k,I,t), 0 < I } 1.
+
+% order(-1,k,I,t) provides the closest block/table I in scope below k at time t
+1 #count{ I : order(-1,k,I,t) : scope(k,I,t) } 1.
+
+% trace order/4 to derive transitive closure of objects in scope above/below k
+trans(D,k,I,t) :- order(D,k,I,t).
+trans(D,k,I,t) :- trans(D,k,J,t), order(D,J,I,t).
+trans(D,k,J,t) :- trans(D,k,I,t), order(-D,J,I,t), scope(k,J,t).
+
+% state constraint that the table is transitively below block k (redundant)
+ :- not trans(-1,k,0,t).
+
+% state constraint propagating immediate above/below relationships
+ :- order(-1,k,I,t), order(1,k,J,t), not order(-1,J,I,t), not order(1,I,J,t).
+
+% state constraint aligning immediate and transitive above/below relationships
+ :- order(-D,k,J,t), order(D,J,I,t), not trans(D,k,I,t), 0 < I. % D=-1 redundant
+
+% state constraint directing transitive above/below relationships on convergence
+ :- order(D,k,I,t), order(D,J,I,t), not trans(-D,k,J,t), scope(k,J,t), 0 < I.
+
+% rules below are volatile with life span 1
+% #program volatile(k,t).
+
+#external scope(k,0,t+1).
+
+% goal state conditions
+ :- goal_above(k,I), not trans(-1,k,I,t), not scope(k,0,t+1).
+ :- goal_below(k,I), not trans(1,k,I,t), not scope(k,0,t+1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for generating moves having a block as object and target, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program move(k,t).
+
+% external atoms indicating involvement of blocks with greater numbers in move
+#external change(-1,k,I,t) : scope(I,0,t), I <= k.
+#external change( 1,k,I,t) : scope(I,0,t-1), I <= k.
+#external change(-1,k,t).
+#external change( 1,k,t).
+
+% output object and target block of move
+#show object(k,t) : object(k,t).
+#show target(k,t) : target(k,t).
+
+% propagate role as move object (via D=1) or target (via D=-1) to smaller block
+change(1,k-1,I,t) :- order(1,k,I,t), scope(I,0,t-1), not order(1,k,I,t-1).
+change(D,k-1,I,t) :- order(D,k,I,t-(D+|D|)/2), scope(k,0,t-1), 0 < I,
+                     not order(D,k,I,t+(D-|D|)/2).
+change(D,k-1,I,t) :- change(D,k,I,t), I < k. % , scope(I,0,t-(D+|D|)/2).
+
+% combine possibilities how move affects block as object (D=1) or target (D=-1)
+affect(-D,k,t) :- order(D,k,I,t+(D-|D|)/2), scope(I,0,t-1) : D == 1;
+                  not order(D,k,I,t-(D+|D|)/2).
+affect( D,k,t) :- change(D,k,k,t). % , scope(k,0,t-(D+|D|)/2).
+
+% propagate existence of some move object or target to smaller blocks and table
+change(D,k-1,t) :- affect(D,k,t).
+change(D,k-1,t) :- change(D,k,t).
+
+% derive moved object and corresponding target
+object(k,t) :- affect(1,k,t).
+target(k,t) :- affect(-1,k,t), not change(-1,k,t).
+
+% moved object must be unique
+ :- object(k,t), change(1,k,t).
+
+% moved object must be free
+ :- object(k,t), order(1,k,_,t-1).
+ :- object(I,t), order(-1,k,I,t-1).
+
+% moved object must not go under (unmoved) pre-existing block
+ :- object(k,t), order(1,k,I,t), scope(I,0,t-1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for deriving target table from move without target block, using %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program table(t).
+
+% external atoms indicating involvement of blocks with greater numbers in move
+#external change(-1,0,t).
+#external change( 1,0,t).
+
+% output target table of move
+#show target(0,t) : target(0,t).
+
+% derive table as target of move
+target(0,t) :- change(1,0,t), not change(-1,0,t).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for establishing consistent initial position for a block, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program init(k,t).
+
+% no appearance under unmoved pre-existing block
+ :- order(1,k,I,t), scope(I,0,t-1), not object(I,t).
+
+% initial state conditions
+ :- init_above(k,I), not trans(-1,k,I,t).
+ :- init_below(k,I), not trans(1,k,I,t).
+% clingo-4-banane clingo-4-blocksworld.lp clingo-4-main.lp 0
+
+#script (lua)
+
+function main(prg)
+    parts = {}
+    parts[#parts+1] = {"init", {1, 0}}
+    parts[#parts+1] = {"state", {1, 0}}
+    prg:cleanup()
+    prg:ground(parts)
+	prg:solve()
+
+    parts = {}
+    parts[#parts+1] = {"base_2", {}}
+    parts[#parts+1] = {"init", {2,0}}
+    parts[#parts+1] = {"state", {2,0}}
+	for i=1,2 do
+        parts[#parts+1] = {"table", {i}}
+		for j=1,2 do
+            parts[#parts+1] = {"state", {j,i}}
+		    parts[#parts+1] = {"move", {j,i}}
+        end
+    end
+    prg:cleanup()
+    prg:ground(parts)
+	prg:solve()
+
+    parts = {}
+	parts[#parts+1] = {"base_3", {}}
+	parts[#parts+1] = {"init", {3,0}}
+	parts[#parts+1] = {"state", {3,0}}
+	for i=1,3 do
+		parts[#parts+1] = {"state", {3,i}}
+		parts[#parts+1] = {"move", {3,i}}
+    end
+	for j=1,2 do
+		parts[#parts+1] = {"state", {j,3}}
+		parts[#parts+1] = {"move", {j,3}}
+    end
+	parts[#parts+1] = {"table", {3}}
+    prg:cleanup()
+    prg:ground(parts)
+	prg:solve()
+
+    parts = {}
+	parts[#parts+1] = {"base_4", {}}
+	parts[#parts+1] = {"init", {4,0}}
+	parts[#parts+1] = {"state", {4,0}}
+	for i=1, 4 do
+		parts[#parts+1] = {"state", {4,i}}
+		parts[#parts+1] = {"move", {4,i}}
+    end
+	for j = 1, 3 do
+		parts[#parts+1] = {"state", {j,4}}
+		parts[#parts+1] = {"move", {j,4}}
+    end
+	parts[#parts+1] = {"table", {4}}
+    prg:cleanup()
+    prg:ground(parts)
+	prg:solve()
+
+    parts = {}
+	parts[#parts+1] = {"base_5", {}}
+	parts[#parts+1] = {"init", {5,1}}
+	for i=1, 7 do
+		parts[#parts+1] = {"state", {5,i}}
+		parts[#parts+1] = {"move", {5,i}}
+    end
+	for i=5, 7 do
+		parts[#parts+1] = {"table", {i}}
+		for j=1, 4 do
+			parts[#parts+1] = {"state", {j,i}}
+			parts[#parts+1] = {"move", {j,i}}
+        end
+    end
+    prg:cleanup()
+    prg:ground(parts)
+	prg:solve()
+end
+#end.
+
+#program base_2.
+
+init_above(2,1).
+goal_below(2,1).
+
+#program base_3.
+
+init_above(3,2).
+goal_below(3,1).
+
+#program base_4.
+
+init_above(4,2).
+init_below(4,3).
+goal_above(4,3).
+goal_below(4,1).
+
+#program base_5.
+
+init_above(5,1).
+init_below(5,3).
+goal_above(5,2).
diff --git a/app/clingo/tests/lua/blocksworld1.sol b/app/clingo/tests/lua/blocksworld1.sol
new file mode 100644
index 0000000..2c41088
--- /dev/null
+++ b/app/clingo/tests/lua/blocksworld1.sol
@@ -0,0 +1,12 @@
+Step: 1
+order(-1,1,0,0)
+Step: 2
+object(1,2) object(2,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,2,0,1) order(-1,2,0,2) order(-1,2,1,0) order(1,2,1,2) target(0,1) target(2,2)
+Step: 3
+object(1,3) object(2,2) object(3,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,2,0,2) order(-1,2,0,3) order(-1,2,1,0) order(-1,2,1,1) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,2,0) order(1,2,1,3) order(1,3,2,2) order(1,3,2,3) target(0,1) target(2,3) target(3,2)
+Step: 4
+object(1,4) object(2,3) object(3,1) object(4,2) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,2,0,3) order(-1,2,0,4) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,2,0) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,3,2) order(-1,4,3,3) order(-1,4,3,4) order(1,2,1,4) order(1,3,2,3) order(1,3,2,4) order(1,4,2,3) order(1,4,2,4) order(1,4,3,0) target(0,1) target(2,4) target(3,2) target(4,3)
+Step: 5
+object(1,6) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,7) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,0,6) order(-1,5,1,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,6) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,3,1) target(0,2) target(0,3) target(1,7) target(2,6) target(3,4) target(4,5) target(5,1)
+object(1,7) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,6) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,2,6) order(-1,5,2,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,1,7) order(1,5,3,1) target(0,2) target(0,3) target(2,6) target(3,4) target(4,5) target(5,1) target(5,7)
+SAT
diff --git a/app/clingo/tests/lua/conformant1.lp b/app/clingo/tests/lua/conformant1.lp
new file mode 100644
index 0000000..9d35ae4
--- /dev/null
+++ b/app/clingo/tests/lua/conformant1.lp
@@ -0,0 +1,294 @@
+#script (lua) 
+function main(prg)
+    local step   = 0
+    local check  = false
+    while true do
+        parts = {}
+        if step > 0 then
+            parts[#parts+1] = {"step", {step}}
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"state", {step}}
+        if check then
+            parts[#parts+1] = {"check", {step}}
+        end
+        prg:release_external(clingo.Function("vol", {step-1}))
+        prg:cleanup()
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("vol", {step}), true)
+        local ret = prg:solve()
+        if ret.satisfiable then
+            if not check and prg:get_const("nocheck") == nil then
+                check = true
+                parts = {}
+                parts[#parts+1] = {"check", {step}}
+                prg:cleanup()
+                prg:ground(parts)
+                ret = prg:solve()
+                if ret.satisfiable then
+                    break
+                end
+            else 
+                break
+            end
+        end
+        step = step+1
+    end
+end
+#end.
+
+#program warnings. % silence warnings
+
+goal_or(0,(0;neg(0)),0) :- #false.
+
+#program base.
+
+lit(F)      :- fluent(F).
+lit(neg(F)) :- fluent(F).
+
+complement(F,F,neg(F)) :- fluent(F).
+complement(F,neg(F)) :- fluent(F).
+complement(neg(F),F) :- fluent(F).
+
+fluent(F,F)      :- fluent(F).
+fluent(neg(F),F) :- fluent(F).
+
+contradict(F)  :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2),
+                  #false : condition(A,M,N1), condition(A,L,N2), complement(L,M).
+
+{ holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M).
+  holds(F,0)   :- initially(L), complement(F,L,M).
+
+holds_oneof(N,B)  :- 
+    initially_oneof(N,_,B);
+    not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M);
+        holds(F,0) : initially_oneof(N,L,B), complement(F,L,M).
+
+ :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1.
+ % just bizarre!
+ :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M).
+ :-     holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M).
+
+#program step(t).
+
+1 { occurs(A,t) : action(A) } 1.
+ :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M).
+ :- occurs(A,t), executable(A,M),     holds(F,t-1), complement(F,L,M).
+
+holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N).
+holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t).
+ :- contradict(F), complement(F,L,M), holds((L),t), holds((M),t).
+
+caused(L,t) :- occurs(A,t), effect(A,L,N), 
+               not holds(F',t-1) : condition(A,M',N), complement(F',L',M');
+                   holds(F',t-1) : condition(A,L',N), complement(F',L',M').
+holds(F,t) :- caused(L,t), complement(F,L,M).
+holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t).
+ :- caused((L),t), caused((M),t), contradict(F), complement(F,L,M).
+
+#program state(t).
+#external vol(t).
+
+ :- goal_or(N,_,_);
+    not holds(F,t) : goal_or(N,L,_), complement(F,L,M);
+        holds(F,t) : goal_or(N,M,_), complement(F,L,M);
+    vol(t).
+ :- goal(L), not holds(F,t), complement(F,L,M), vol(t).
+ :- goal(M),     holds(F,t), complement(F,L,M), vol(t).
+
+#program check(t).
+
+%%%%%%% base
+
+alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L), not initially(M), vol(t).
+alt_holds(L,0,t) :- initially(L), vol(t).
+
+pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B),                  alt_holds(L,0,t) : initially_oneof(N,L,B).
+not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t).
+
+bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }.
+bottom(t) :- vol(t), initially_oneof(N,_,_),     not_holds_oneof(N,B,t) : initially_oneof(N,_,B).
+bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t).
+
+%%%%%%% transition
+
+not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t).
+not_caused(L,T,t)      :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t).
+
+alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t).
+alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t).
+
+%%%%%%% state
+
+not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t).
+pos_executable(T,t)   :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t).
+pos_goal_or(N,t) :- goal_or(N,L,B), alt_holds(L,t,t), vol(t).
+pos_goal_or(N,t) :- goal_or(N,L,B), goal(L), vol(t).
+
+bottom(t) :- pos_goal_or(N,t)  : goal_or(N,_,_); 
+             alt_holds(L,t,t)  : goal(L);
+             pos_executable(R,t)     : R = 1..t; 
+             not_contradict(F,S,t) : contradict(F), S = 1..t;
+             vol(t).
+
+%%%%%%% saturation
+
+alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L), not initially(M), vol(t).
+
+:- not bottom(t), vol(t).
+
+#show occurs/2.
+
+#program base.
+
+fluent(cpa_at(cpa_f1, cpa_p1)).
+fluent(cpa_inside(cpa_e1)).
+fluent(cpa_at(cpa_f1, cpa_p0)).
+fluent(cpa_have(cpa_c0)).
+fluent(cpa_have(cpa_c1)).
+fluent(cpa_at(cpa_f0, cpa_p1)).
+fluent(cpa_inside(cpa_e0)).
+fluent(cpa_at(cpa_f0, cpa_p0)).
+fluent(cpa_in(cpa_e0, cpa_f0)).
+fluent(cpa_in(cpa_e0, cpa_f1)).
+fluent(cpa_in(cpa_e1, cpa_f0)).
+fluent(cpa_in(cpa_e1, cpa_f1)).
+fluent(cpa_coin_at(cpa_c0, cpa_f1, cpa_p0)).
+fluent(cpa_coin_at(cpa_c0, cpa_f1, cpa_p1)).
+fluent(cpa_coin_at(cpa_c1, cpa_f1, cpa_p0)).
+fluent(cpa_coin_at(cpa_c1, cpa_f1, cpa_p1)).
+
+%% actions ------ 
+
+action(cpa_collect(cpa_c0, cpa_f0, cpa_p0)).
+action(cpa_collect(cpa_c0, cpa_f0, cpa_p1)).
+action(cpa_collect(cpa_c0, cpa_f1, cpa_p0)).
+action(cpa_collect(cpa_c0, cpa_f1, cpa_p1)).
+action(cpa_collect(cpa_c1, cpa_f0, cpa_p0)).
+action(cpa_collect(cpa_c1, cpa_f0, cpa_p1)).
+action(cpa_collect(cpa_c1, cpa_f1, cpa_p0)).
+action(cpa_collect(cpa_c1, cpa_f1, cpa_p1)).
+action(cpa_go_down(cpa_e0, cpa_f1, cpa_f0)).
+action(cpa_go_down(cpa_e1, cpa_f1, cpa_f0)).
+action(cpa_go_up(cpa_e0, cpa_f0, cpa_f1)).
+action(cpa_go_up(cpa_e1, cpa_f0, cpa_f1)).
+action(cpa_move_left(cpa_f0, cpa_p1, cpa_p0)).
+action(cpa_move_left(cpa_f1, cpa_p1, cpa_p0)).
+action(cpa_move_right(cpa_f0, cpa_p0, cpa_p1)).
+action(cpa_move_right(cpa_f1, cpa_p0, cpa_p1)).
+action(cpa_step_in(cpa_e0, cpa_f0, cpa_p0)).
+action(cpa_step_in(cpa_e0, cpa_f1, cpa_p0)).
+action(cpa_step_in(cpa_e1, cpa_f0, cpa_p1)).
+action(cpa_step_in(cpa_e1, cpa_f1, cpa_p1)).
+action(cpa_step_out(cpa_e0, cpa_f0, cpa_p0)).
+action(cpa_step_out(cpa_e0, cpa_f1, cpa_p0)).
+action(cpa_step_out(cpa_e1, cpa_f0, cpa_p1)).
+action(cpa_step_out(cpa_e1, cpa_f1, cpa_p1)).
+
+%% executable ------ 
+
+executable(cpa_collect(cpa_c0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_collect(cpa_c0, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_collect(cpa_c1, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_collect(cpa_c1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_inside(cpa_e0)).
+executable(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_inside(cpa_e0)).
+executable(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_inside(cpa_e1)).
+executable(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_inside(cpa_e1)).
+
+%% effects ------ 
+
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_have(cpa_c0),1).
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p0),neg(cpa_coin_at(cpa_c0, cpa_f1, cpa_p0)),1).
+condition(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_coin_at(cpa_c0, cpa_f1, cpa_p0),1).
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_have(cpa_c0),1).
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p1),neg(cpa_coin_at(cpa_c0, cpa_f1, cpa_p1)),1).
+condition(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_coin_at(cpa_c0, cpa_f1, cpa_p1),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_have(cpa_c1),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p0),neg(cpa_coin_at(cpa_c1, cpa_f1, cpa_p0)),1).
+condition(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_coin_at(cpa_c1, cpa_f1, cpa_p0),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_have(cpa_c1),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p1),neg(cpa_coin_at(cpa_c1, cpa_f1, cpa_p1)),1).
+condition(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_coin_at(cpa_c1, cpa_f1, cpa_p1),1).
+effect(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),neg(cpa_in(cpa_e0, cpa_f1)),1).
+condition(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),neg(cpa_in(cpa_e1, cpa_f1)),1).
+condition(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),cpa_in(cpa_e1, cpa_f1),1).
+effect(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),neg(cpa_in(cpa_e0, cpa_f0)),1).
+condition(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),cpa_in(cpa_e1, cpa_f1),1).
+effect(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),neg(cpa_in(cpa_e1, cpa_f0)),1).
+condition(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),neg(cpa_at(cpa_f0, cpa_p1)),1).
+effect(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),cpa_at(cpa_f0, cpa_p0),1).
+effect(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),neg(cpa_at(cpa_f1, cpa_p1)),1).
+effect(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),cpa_at(cpa_f1, cpa_p0),1).
+effect(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),neg(cpa_at(cpa_f0, cpa_p0)),1).
+effect(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),cpa_at(cpa_f0, cpa_p1),1).
+effect(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),neg(cpa_at(cpa_f1, cpa_p0)),1).
+effect(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),cpa_at(cpa_f1, cpa_p1),1).
+effect(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_inside(cpa_e0),1).
+effect(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),neg(cpa_at(cpa_f0, cpa_p0)),1).
+condition(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_inside(cpa_e0),1).
+effect(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),neg(cpa_at(cpa_f1, cpa_p0)),1).
+condition(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_inside(cpa_e1),1).
+effect(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),neg(cpa_at(cpa_f0, cpa_p1)),1).
+condition(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_inside(cpa_e1),1).
+effect(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),neg(cpa_at(cpa_f1, cpa_p1)),1).
+condition(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_in(cpa_e1, cpa_f1),1).
+effect(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0),1).
+effect(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),neg(cpa_inside(cpa_e0)),1).
+condition(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0),1).
+effect(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),neg(cpa_inside(cpa_e0)),1).
+condition(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1),1).
+effect(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),neg(cpa_inside(cpa_e1)),1).
+condition(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1),1).
+effect(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),neg(cpa_inside(cpa_e1)),1).
+condition(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_in(cpa_e1, cpa_f1),1).
+
+%% initial state ------ 
+
+initially(cpa_at(cpa_f0, cpa_p0)).
+initially(neg(cpa_at(cpa_f0, cpa_p1))).
+initially(neg(cpa_at(cpa_f1, cpa_p0))).
+initially(neg(cpa_at(cpa_f1, cpa_p1))).
+initially(neg(cpa_inside(cpa_e0))).
+initially(neg(cpa_inside(cpa_e1))).
+initially(neg(cpa_have(cpa_c0))).
+initially(neg(cpa_have(cpa_c1))).
+initially_oneof(1,cpa_in(cpa_e0, cpa_f0),1).
+initially_oneof(1,cpa_in(cpa_e0, cpa_f1),2).
+initially_oneof(2,cpa_in(cpa_e1, cpa_f0),1).
+initially_oneof(2,cpa_in(cpa_e1, cpa_f1),2).
+initially_oneof(3,cpa_coin_at(cpa_c0, cpa_f1, cpa_p0),1).
+initially_oneof(3,cpa_coin_at(cpa_c1, cpa_f1, cpa_p0),1).
+initially_oneof(3,cpa_coin_at(cpa_c0, cpa_f1, cpa_p1),2).
+initially_oneof(3,cpa_coin_at(cpa_c1, cpa_f1, cpa_p1),2).
+
+%% goal state ---------- 
+
+goal(cpa_have(cpa_c0)).
+goal(cpa_have(cpa_c1)).
+
diff --git a/app/clingo/tests/lua/conformant1.sol b/app/clingo/tests/lua/conformant1.sol
new file mode 100644
index 0000000..bf06a11
--- /dev/null
+++ b/app/clingo/tests/lua/conformant1.sol
@@ -0,0 +1,48 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),4) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),4) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),4) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),2) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),1) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),3)
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+Step: 11
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),8) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),9) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p0),6) occurs(cpa_collect(cpa_c0,cpa_f1,cpa_p1),9) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p0),5) occurs(cpa_collect(cpa_c1,cpa_f1,cpa_p1),8) occurs(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),1) occurs(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),3) occurs(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),7) occurs(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),2) occurs(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),4)
+SAT
diff --git a/app/clingo/tests/lua/conformant2.lp b/app/clingo/tests/lua/conformant2.lp
new file mode 100644
index 0000000..d59fb2b
--- /dev/null
+++ b/app/clingo/tests/lua/conformant2.lp
@@ -0,0 +1,198 @@
+#script (lua) 
+function main(prg)
+    local step   = 0
+    local check  = false
+    while true do
+        parts = {}
+        if step > 0 then
+            parts[#parts+1] = {"step", {step}}
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"state", {step}}
+        if check then
+            parts[#parts+1] = {"check", {step}}
+        end
+        prg:release_external(clingo.Function("vol", {step-1}))
+        prg:cleanup()
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("vol", {step}), true)
+        local ret = prg:solve()
+        if ret.satisfiable then
+            if not check and prg:get_const("nocheck") == nil then
+                check = true
+                parts = {}
+                parts[#parts+1] = {"check", {step}}
+                prg:cleanup()
+                prg:ground(parts)
+                ret = prg:solve()
+                if ret.satisfiable then
+                    break
+                end
+            else 
+                break
+            end
+        end
+        step = step+1
+    end
+end
+#end.
+
+#program warnings. % silence warnings
+
+goal_or(0,(0;neg(0)),0) :- #false.
+
+#program base.
+
+lit(F)      :- fluent(F).
+lit(neg(F)) :- fluent(F).
+
+complement(F,F,neg(F)) :- fluent(F).
+complement(F,neg(F)) :- fluent(F).
+complement(neg(F),F) :- fluent(F).
+
+fluent(F,F)      :- fluent(F).
+fluent(neg(F),F) :- fluent(F).
+
+contradict(F)  :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2),
+                  #false : condition(A,M,N1), condition(A,L,N2), complement(L,M).
+
+{ holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M).
+  holds(F,0)   :- initially(L), complement(F,L,M).
+
+holds_oneof(N,B)  :- 
+    initially_oneof(N,_,B);
+    not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M);
+        holds(F,0) : initially_oneof(N,L,B), complement(F,L,M).
+
+ :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1.
+ % just bizarre!
+ :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M).
+ :-     holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M).
+
+#program step(t).
+
+1 { occurs(A,t) : action(A) } 1.
+ :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M).
+ :- occurs(A,t), executable(A,M),     holds(F,t-1), complement(F,L,M).
+
+holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N).
+holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t).
+ :- contradict(F), complement(F,L,M), holds((L),t), holds((M),t).
+
+caused(L,t) :- occurs(A,t), effect(A,L,N), 
+               not holds(F',t-1) : condition(A,M',N), complement(F',L',M');
+                   holds(F',t-1) : condition(A,L',N), complement(F',L',M').
+holds(F,t) :- caused(L,t), complement(F,L,M).
+holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t).
+ :- caused((L),t), caused((M),t), contradict(F), complement(F,L,M).
+
+#program state(t).
+#external vol(t).
+
+ :- goal_or(N,_,_);
+    not holds(F,t) : goal_or(N,L,_), complement(F,L,M);
+        holds(F,t) : goal_or(N,M,_), complement(F,L,M);
+    vol(t).
+ :- goal(L), not holds(F,t), complement(F,L,M), vol(t).
+ :- goal(M),     holds(F,t), complement(F,L,M), vol(t).
+
+#program check(t).
+
+%%%%%%% base
+
+alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L), not initially(M), vol(t).
+alt_holds(L,0,t) :- initially(L), vol(t).
+
+pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B),                  alt_holds(L,0,t) : initially_oneof(N,L,B).
+not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t).
+
+bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }.
+bottom(t) :- vol(t), initially_oneof(N,_,_),     not_holds_oneof(N,B,t) : initially_oneof(N,_,B).
+bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t).
+
+%%%%%%% transition
+
+not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t).
+not_caused(L,T,t)      :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t).
+
+alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t).
+alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t).
+
+%%%%%%% state
+
+not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t).
+pos_executable(T,t)   :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t).
+pos_goal_or(N,t) :- goal_or(N,L,B), alt_holds(L,t,t), vol(t).
+pos_goal_or(N,t) :- goal_or(N,L,B), goal(L), vol(t).
+
+bottom(t) :- pos_goal_or(N,t)  : goal_or(N,_,_); 
+             alt_holds(L,t,t)  : goal(L);
+             pos_executable(R,t)     : R = 1..t; 
+             not_contradict(F,S,t) : contradict(F), S = 1..t;
+             vol(t).
+
+%%%%%%% saturation
+
+alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L), not initially(M), vol(t).
+
+:- not bottom(t), vol(t).
+
+#show occurs/2.
+
+#program base.
+
+fluent(cpa_started).
+fluent(cpa_visited(cpa_n1)).
+fluent(cpa_visited(cpa_n2)).
+fluent(cpa_at(cpa_n1)).
+fluent(cpa_at(cpa_n2)).
+
+%% actions ------ 
+
+action(cpa_start(cpa_n1)).
+action(cpa_start(cpa_n2)).
+action(cpa_travel(cpa_n1, cpa_n1)).
+action(cpa_travel(cpa_n1, cpa_n2)).
+action(cpa_travel(cpa_n2, cpa_n1)).
+action(cpa_travel(cpa_n2, cpa_n2)).
+
+%% executable ------ 
+
+executable(cpa_start(cpa_n1),true).
+executable(cpa_start(cpa_n2),true).
+executable(cpa_travel(cpa_n1, cpa_n1),cpa_started).
+executable(cpa_travel(cpa_n1, cpa_n2),cpa_started).
+executable(cpa_travel(cpa_n2, cpa_n1),cpa_started).
+executable(cpa_travel(cpa_n2, cpa_n2),cpa_started).
+
+%% effects ------ 
+
+effect(cpa_start(cpa_n1),cpa_started,1).
+effect(cpa_start(cpa_n1),cpa_visited(cpa_n1),1).
+condition(cpa_start(cpa_n1),cpa_at(cpa_n1),1).
+effect(cpa_start(cpa_n2),cpa_started,1).
+effect(cpa_start(cpa_n2),cpa_visited(cpa_n2),1).
+condition(cpa_start(cpa_n2),cpa_at(cpa_n2),1).
+effect(cpa_travel(cpa_n1, cpa_n2),cpa_visited(cpa_n2),1).
+effect(cpa_travel(cpa_n1, cpa_n2),cpa_at(cpa_n2),1).
+effect(cpa_travel(cpa_n1, cpa_n2),neg(cpa_at(cpa_n1)),1).
+condition(cpa_travel(cpa_n1, cpa_n2),cpa_at(cpa_n1),1).
+effect(cpa_travel(cpa_n2, cpa_n1),cpa_visited(cpa_n1),1).
+effect(cpa_travel(cpa_n2, cpa_n1),cpa_at(cpa_n1),1).
+effect(cpa_travel(cpa_n2, cpa_n1),neg(cpa_at(cpa_n2)),1).
+condition(cpa_travel(cpa_n2, cpa_n1),cpa_at(cpa_n2),1).
+
+%% initial state ------ 
+
+initially(neg(cpa_visited(cpa_n1))).
+initially(neg(cpa_visited(cpa_n2))).
+initially(neg(cpa_started)).
+initially_oneof(1,cpa_at(cpa_n1),1).
+initially_oneof(1,cpa_at(cpa_n2),2).
+
+%% goal state ---------- 
+
+goal(cpa_visited(cpa_n1)).
+goal(cpa_visited(cpa_n2)).
+
diff --git a/app/clingo/tests/lua/conformant2.sol b/app/clingo/tests/lua/conformant2.sol
new file mode 100644
index 0000000..1971a3a
--- /dev/null
+++ b/app/clingo/tests/lua/conformant2.sol
@@ -0,0 +1,17 @@
+Step: 1
+Step: 2
+Step: 3
+occurs(cpa_start(cpa_n1),1) occurs(cpa_travel(cpa_n1,cpa_n2),2)
+occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n2,cpa_n1),2)
+Step: 4
+Step: 5
+Step: 6
+occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4)
+occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4)
+occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3)
+occurs(cpa_start(cpa_n1),1) occurs(cpa_start(cpa_n2),2) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3)
+occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4)
+occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),3) occurs(cpa_travel(cpa_n2,cpa_n1),4)
+occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3)
+occurs(cpa_start(cpa_n1),2) occurs(cpa_start(cpa_n2),1) occurs(cpa_travel(cpa_n1,cpa_n2),4) occurs(cpa_travel(cpa_n2,cpa_n1),3)
+SAT
diff --git a/app/clingo/tests/lua/conformant3.lp b/app/clingo/tests/lua/conformant3.lp
new file mode 100644
index 0000000..7f96654
--- /dev/null
+++ b/app/clingo/tests/lua/conformant3.lp
@@ -0,0 +1,332 @@
+#script (lua) 
+function main(prg)
+    local step   = 0
+    local check  = false
+    while true do
+        parts = {}
+        if step > 0 then
+            parts[#parts+1] = {"step", {step}}
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"state", {step}}
+        if check then
+            parts[#parts+1] = {"check", {step}}
+        end
+        prg:release_external(clingo.Function("vol", {step-1}))
+        prg:cleanup()
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("vol", {step}), true)
+        local ret = prg:solve()
+        if ret.satisfiable then
+            if not check and prg:get_const("nocheck") == nil then
+                check = true
+                parts = {}
+                parts[#parts+1] = {"check", {step}}
+                prg:cleanup()
+                prg:ground(parts)
+                ret = prg:solve()
+                if ret.satisfiable then
+                    break
+                end
+            else 
+                break
+            end
+        end
+        step = step+1
+    end
+end
+#end.
+
+#program warnings. % silence warnings
+
+goal_or(0,(0;neg(0)),0) :- #false.
+
+#program base.
+
+lit(F)      :- fluent(F).
+lit(neg(F)) :- fluent(F).
+
+complement(F,F,neg(F)) :- fluent(F).
+complement(F,neg(F)) :- fluent(F).
+complement(neg(F),F) :- fluent(F).
+
+fluent(F,F)      :- fluent(F).
+fluent(neg(F),F) :- fluent(F).
+
+contradict(F)  :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2),
+                  #false : condition(A,M,N1), condition(A,L,N2), complement(L,M).
+
+{ holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M).
+  holds(F,0)   :- initially(L), complement(F,L,M).
+
+holds_oneof(N,B)  :- 
+    initially_oneof(N,_,B);
+    not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M);
+        holds(F,0) : initially_oneof(N,L,B), complement(F,L,M).
+
+ :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1.
+ % just bizarre!
+ :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M).
+ :-     holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M).
+
+#program step(t).
+
+1 { occurs(A,t) : action(A) } 1.
+ :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M).
+ :- occurs(A,t), executable(A,M),     holds(F,t-1), complement(F,L,M).
+
+holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N).
+holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t).
+ :- contradict(F), complement(F,L,M), holds((L),t), holds((M),t).
+
+caused(L,t) :- occurs(A,t), effect(A,L,N), 
+               not holds(F',t-1) : condition(A,M',N), complement(F',L',M');
+                   holds(F',t-1) : condition(A,L',N), complement(F',L',M').
+holds(F,t) :- caused(L,t), complement(F,L,M).
+holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t).
+ :- caused((L),t), caused((M),t), contradict(F), complement(F,L,M).
+
+#program state(t).
+#external vol(t).
+
+ :- goal_or(N,_,_);
+    not holds(F,t) : goal_or(N,L,_), complement(F,L,M);
+        holds(F,t) : goal_or(N,M,_), complement(F,L,M);
+    vol(t).
+ :- goal(L), not holds(F,t), complement(F,L,M), vol(t).
+ :- goal(M),     holds(F,t), complement(F,L,M), vol(t).
+
+#program check(t).
+
+%%%%%%% base
+
+alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L), not initially(M), vol(t).
+alt_holds(L,0,t) :- initially(L), vol(t).
+
+pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B),                  alt_holds(L,0,t) : initially_oneof(N,L,B).
+not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t).
+
+bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }.
+bottom(t) :- vol(t), initially_oneof(N,_,_),     not_holds_oneof(N,B,t) : initially_oneof(N,_,B).
+bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t).
+
+%%%%%%% transition
+
+not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t).
+not_caused(L,T,t)      :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t).
+
+alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t).
+alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t).
+
+%%%%%%% state
+
+not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t).
+pos_executable(T,t)   :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t).
+pos_goal_or(N,t) :- goal_or(N,L,B), alt_holds(L,t,t), vol(t).
+pos_goal_or(N,t) :- goal_or(N,L,B), goal(L), vol(t).
+
+bottom(t) :- pos_goal_or(N,t)  : goal_or(N,_,_); 
+             alt_holds(L,t,t)  : goal(L);
+             pos_executable(R,t)     : R = 1..t; 
+             not_contradict(F,S,t) : contradict(F), S = 1..t;
+             vol(t).
+
+%%%%%%% saturation
+
+alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L), not initially(M), vol(t).
+
+:- not bottom(t), vol(t).
+
+#show occurs/2.
+
+#program base.
+
+fluent(cpa_current_stage(cpa_s5)).
+fluent(cpa_bad(cpa_p2)).
+fluent(cpa_ok(cpa_p2)).
+fluent(cpa_current_stage(cpa_s4)).
+fluent(cpa_bad(cpa_p1)).
+fluent(cpa_ok(cpa_p1)).
+fluent(cpa_current_stage(cpa_s3)).
+fluent(cpa_read(cpa_p2)).
+fluent(cpa_bad(cpa_p0)).
+fluent(cpa_ok(cpa_p0)).
+fluent(cpa_current_stage(cpa_s2)).
+fluent(cpa_read(cpa_p1)).
+fluent(cpa_current_stage(cpa_s1)).
+fluent(cpa_read(cpa_p0)).
+fluent(cpa_current_stage(cpa_s0)).
+fluent(cpa_in_channel(cpa_p0)).
+fluent(cpa_in_channel(cpa_p1)).
+fluent(cpa_in_channel(cpa_p2)).
+fluent(cpa_noisy(cpa_p0)).
+fluent(cpa_noisy(cpa_p1)).
+fluent(cpa_noisy(cpa_p2)).
+
+%% actions ------ 
+
+action(cpa_certify(cpa_p0)).
+action(cpa_certify(cpa_p1)).
+action(cpa_certify(cpa_p2)).
+action(cpa_reset(cpa_s1)).
+action(cpa_reset(cpa_s2)).
+action(cpa_reset(cpa_s3)).
+action(cpa_reset(cpa_s4)).
+action(cpa_reset(cpa_s5)).
+action(cpa_advance(cpa_s0, cpa_s1)).
+action(cpa_advance(cpa_s1, cpa_s2)).
+action(cpa_advance(cpa_s2, cpa_s3)).
+action(cpa_advance(cpa_s3, cpa_s4)).
+action(cpa_advance(cpa_s4, cpa_s5)).
+action(cpa_obtain(cpa_p0, cpa_s0)).
+action(cpa_obtain(cpa_p1, cpa_s1)).
+action(cpa_obtain(cpa_p2, cpa_s2)).
+action(cpa_request_copy(cpa_p0, cpa_s0)).
+action(cpa_request_copy(cpa_p0, cpa_s1)).
+action(cpa_request_copy(cpa_p0, cpa_s2)).
+action(cpa_request_copy(cpa_p0, cpa_s3)).
+action(cpa_request_copy(cpa_p0, cpa_s4)).
+action(cpa_request_copy(cpa_p0, cpa_s5)).
+action(cpa_request_copy(cpa_p1, cpa_s0)).
+action(cpa_request_copy(cpa_p1, cpa_s1)).
+action(cpa_request_copy(cpa_p1, cpa_s2)).
+action(cpa_request_copy(cpa_p1, cpa_s3)).
+action(cpa_request_copy(cpa_p1, cpa_s4)).
+action(cpa_request_copy(cpa_p1, cpa_s5)).
+action(cpa_request_copy(cpa_p2, cpa_s0)).
+action(cpa_request_copy(cpa_p2, cpa_s1)).
+action(cpa_request_copy(cpa_p2, cpa_s2)).
+action(cpa_request_copy(cpa_p2, cpa_s3)).
+action(cpa_request_copy(cpa_p2, cpa_s4)).
+action(cpa_request_copy(cpa_p2, cpa_s5)).
+
+%% executable ------ 
+
+executable(cpa_certify(cpa_p0),cpa_read(cpa_p0)).
+executable(cpa_certify(cpa_p1),cpa_read(cpa_p1)).
+executable(cpa_certify(cpa_p2),cpa_read(cpa_p2)).
+executable(cpa_reset(cpa_s1),cpa_current_stage(cpa_s1)).
+executable(cpa_reset(cpa_s2),cpa_current_stage(cpa_s2)).
+executable(cpa_reset(cpa_s3),cpa_current_stage(cpa_s3)).
+executable(cpa_reset(cpa_s4),cpa_current_stage(cpa_s4)).
+executable(cpa_reset(cpa_s5),cpa_current_stage(cpa_s5)).
+executable(cpa_advance(cpa_s0, cpa_s1),cpa_current_stage(cpa_s0)).
+executable(cpa_advance(cpa_s1, cpa_s2),cpa_current_stage(cpa_s1)).
+executable(cpa_advance(cpa_s2, cpa_s3),cpa_current_stage(cpa_s2)).
+executable(cpa_advance(cpa_s3, cpa_s4),cpa_current_stage(cpa_s3)).
+executable(cpa_advance(cpa_s4, cpa_s5),cpa_current_stage(cpa_s4)).
+executable(cpa_obtain(cpa_p0, cpa_s0),cpa_current_stage(cpa_s0)).
+executable(cpa_obtain(cpa_p1, cpa_s1),cpa_current_stage(cpa_s1)).
+executable(cpa_obtain(cpa_p2, cpa_s2),cpa_current_stage(cpa_s2)).
+executable(cpa_request_copy(cpa_p0, cpa_s0),cpa_current_stage(cpa_s0)).
+executable(cpa_request_copy(cpa_p0, cpa_s1),cpa_current_stage(cpa_s1)).
+executable(cpa_request_copy(cpa_p0, cpa_s2),cpa_current_stage(cpa_s2)).
+executable(cpa_request_copy(cpa_p0, cpa_s3),cpa_current_stage(cpa_s3)).
+executable(cpa_request_copy(cpa_p0, cpa_s4),cpa_current_stage(cpa_s4)).
+executable(cpa_request_copy(cpa_p0, cpa_s5),cpa_current_stage(cpa_s5)).
+executable(cpa_request_copy(cpa_p1, cpa_s0),cpa_current_stage(cpa_s0)).
+executable(cpa_request_copy(cpa_p1, cpa_s1),cpa_current_stage(cpa_s1)).
+executable(cpa_request_copy(cpa_p1, cpa_s2),cpa_current_stage(cpa_s2)).
+executable(cpa_request_copy(cpa_p1, cpa_s3),cpa_current_stage(cpa_s3)).
+executable(cpa_request_copy(cpa_p1, cpa_s4),cpa_current_stage(cpa_s4)).
+executable(cpa_request_copy(cpa_p1, cpa_s5),cpa_current_stage(cpa_s5)).
+executable(cpa_request_copy(cpa_p2, cpa_s0),cpa_current_stage(cpa_s0)).
+executable(cpa_request_copy(cpa_p2, cpa_s1),cpa_current_stage(cpa_s1)).
+executable(cpa_request_copy(cpa_p2, cpa_s2),cpa_current_stage(cpa_s2)).
+executable(cpa_request_copy(cpa_p2, cpa_s3),cpa_current_stage(cpa_s3)).
+executable(cpa_request_copy(cpa_p2, cpa_s4),cpa_current_stage(cpa_s4)).
+executable(cpa_request_copy(cpa_p2, cpa_s5),cpa_current_stage(cpa_s5)).
+
+%% effects ------ 
+
+effect(cpa_certify(cpa_p0),cpa_bad(cpa_p0),1).
+condition(cpa_certify(cpa_p0),cpa_noisy(cpa_p0),1).
+effect(cpa_certify(cpa_p0),cpa_ok(cpa_p0),2).
+condition(cpa_certify(cpa_p0),neg(cpa_noisy(cpa_p0)),2).
+effect(cpa_certify(cpa_p1),cpa_bad(cpa_p1),1).
+condition(cpa_certify(cpa_p1),cpa_noisy(cpa_p1),1).
+effect(cpa_certify(cpa_p1),cpa_ok(cpa_p1),2).
+condition(cpa_certify(cpa_p1),neg(cpa_noisy(cpa_p1)),2).
+effect(cpa_certify(cpa_p2),cpa_bad(cpa_p2),1).
+condition(cpa_certify(cpa_p2),cpa_noisy(cpa_p2),1).
+effect(cpa_certify(cpa_p2),cpa_ok(cpa_p2),2).
+condition(cpa_certify(cpa_p2),neg(cpa_noisy(cpa_p2)),2).
+effect(cpa_reset(cpa_s1),neg(cpa_current_stage(cpa_s1)),1).
+effect(cpa_reset(cpa_s1),cpa_current_stage(cpa_s0),1).
+effect(cpa_reset(cpa_s2),neg(cpa_current_stage(cpa_s2)),1).
+effect(cpa_reset(cpa_s2),cpa_current_stage(cpa_s0),1).
+effect(cpa_reset(cpa_s3),neg(cpa_current_stage(cpa_s3)),1).
+effect(cpa_reset(cpa_s3),cpa_current_stage(cpa_s0),1).
+effect(cpa_reset(cpa_s4),neg(cpa_current_stage(cpa_s4)),1).
+effect(cpa_reset(cpa_s4),cpa_current_stage(cpa_s0),1).
+effect(cpa_reset(cpa_s5),neg(cpa_current_stage(cpa_s5)),1).
+effect(cpa_reset(cpa_s5),cpa_current_stage(cpa_s0),1).
+effect(cpa_advance(cpa_s0, cpa_s1),cpa_current_stage(cpa_s1),1).
+effect(cpa_advance(cpa_s0, cpa_s1),neg(cpa_current_stage(cpa_s0)),1).
+effect(cpa_advance(cpa_s1, cpa_s2),cpa_current_stage(cpa_s2),1).
+effect(cpa_advance(cpa_s1, cpa_s2),neg(cpa_current_stage(cpa_s1)),1).
+effect(cpa_advance(cpa_s2, cpa_s3),cpa_current_stage(cpa_s3),1).
+effect(cpa_advance(cpa_s2, cpa_s3),neg(cpa_current_stage(cpa_s2)),1).
+effect(cpa_advance(cpa_s3, cpa_s4),cpa_current_stage(cpa_s4),1).
+effect(cpa_advance(cpa_s3, cpa_s4),neg(cpa_current_stage(cpa_s3)),1).
+effect(cpa_advance(cpa_s4, cpa_s5),cpa_current_stage(cpa_s5),1).
+effect(cpa_advance(cpa_s4, cpa_s5),neg(cpa_current_stage(cpa_s4)),1).
+effect(cpa_obtain(cpa_p0, cpa_s0),neg(cpa_in_channel(cpa_p0)),1).
+effect(cpa_obtain(cpa_p0, cpa_s0),cpa_read(cpa_p0),1).
+condition(cpa_obtain(cpa_p0, cpa_s0),cpa_in_channel(cpa_p0),1).
+effect(cpa_obtain(cpa_p1, cpa_s1),neg(cpa_in_channel(cpa_p1)),1).
+effect(cpa_obtain(cpa_p1, cpa_s1),cpa_read(cpa_p1),1).
+condition(cpa_obtain(cpa_p1, cpa_s1),cpa_in_channel(cpa_p1),1).
+effect(cpa_obtain(cpa_p2, cpa_s2),neg(cpa_in_channel(cpa_p2)),1).
+effect(cpa_obtain(cpa_p2, cpa_s2),cpa_read(cpa_p2),1).
+condition(cpa_obtain(cpa_p2, cpa_s2),cpa_in_channel(cpa_p2),1).
+effect(cpa_request_copy(cpa_p0, cpa_s0),cpa_in_channel(cpa_p0),1).
+effect(cpa_request_copy(cpa_p0, cpa_s0),neg(cpa_read(cpa_p0)),1).
+effect(cpa_request_copy(cpa_p0, cpa_s0),neg(cpa_noisy(cpa_p0)),1).
+effect(cpa_request_copy(cpa_p0, cpa_s0),neg(cpa_bad(cpa_p0)),1).
+condition(cpa_request_copy(cpa_p0, cpa_s0),cpa_bad(cpa_p0),1).
+effect(cpa_request_copy(cpa_p1, cpa_s1),cpa_in_channel(cpa_p1),1).
+effect(cpa_request_copy(cpa_p1, cpa_s1),neg(cpa_read(cpa_p1)),1).
+effect(cpa_request_copy(cpa_p1, cpa_s1),neg(cpa_noisy(cpa_p1)),1).
+effect(cpa_request_copy(cpa_p1, cpa_s1),neg(cpa_bad(cpa_p1)),1).
+condition(cpa_request_copy(cpa_p1, cpa_s1),cpa_bad(cpa_p1),1).
+effect(cpa_request_copy(cpa_p2, cpa_s2),cpa_in_channel(cpa_p2),1).
+effect(cpa_request_copy(cpa_p2, cpa_s2),neg(cpa_read(cpa_p2)),1).
+effect(cpa_request_copy(cpa_p2, cpa_s2),neg(cpa_noisy(cpa_p2)),1).
+effect(cpa_request_copy(cpa_p2, cpa_s2),neg(cpa_bad(cpa_p2)),1).
+condition(cpa_request_copy(cpa_p2, cpa_s2),cpa_bad(cpa_p2),1).
+
+%% initial state ------ 
+
+initially(cpa_current_stage(cpa_s0)).
+initially(cpa_in_channel(cpa_p0)).
+initially(cpa_in_channel(cpa_p1)).
+initially(cpa_in_channel(cpa_p2)).
+initially(neg(cpa_current_stage(cpa_s1))).
+initially(neg(cpa_current_stage(cpa_s2))).
+initially(neg(cpa_current_stage(cpa_s3))).
+initially(neg(cpa_current_stage(cpa_s4))).
+initially(neg(cpa_current_stage(cpa_s5))).
+initially(neg(cpa_read(cpa_p0))).
+initially(neg(cpa_read(cpa_p1))).
+initially(neg(cpa_read(cpa_p2))).
+initially(neg(cpa_bad(cpa_p0))).
+initially(neg(cpa_bad(cpa_p1))).
+initially(neg(cpa_bad(cpa_p2))).
+initially(neg(cpa_ok(cpa_p0))).
+initially(neg(cpa_ok(cpa_p1))).
+initially(neg(cpa_ok(cpa_p2))).
+initially_oneof(1,cpa_noisy(cpa_p0),1).
+initially_oneof(1,cpa_noisy(cpa_p2),1).
+initially_oneof(1,cpa_noisy(cpa_p1),1).
+initially_oneof(1,neg(cpa_noisy(cpa_p0)),2).
+initially_oneof(1,neg(cpa_noisy(cpa_p2)),2).
+initially_oneof(1,neg(cpa_noisy(cpa_p1)),2).
+
+%% goal state ---------- 
+
+goal(cpa_ok(cpa_p0)).
+goal(cpa_ok(cpa_p1)).
+goal(cpa_ok(cpa_p2)).
+
diff --git a/app/clingo/tests/lua/conformant3.sol b/app/clingo/tests/lua/conformant3.sol
new file mode 100644
index 0000000..f101897
--- /dev/null
+++ b/app/clingo/tests/lua/conformant3.sol
@@ -0,0 +1,230 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),6) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),4) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),6) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),5)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),3) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),4) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),2) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),4) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),3) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),6) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),5) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),7) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),6)
+occurs(cpa_advance(cpa_s0,cpa_s1),3) occurs(cpa_advance(cpa_s1,cpa_s2),6) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),5) occurs(cpa_certify(cpa_p2),8) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p1,cpa_s1),4) occurs(cpa_obtain(cpa_p2,cpa_s2),7)
+Step: 10
+Step: 11
+Step: 12
+Step: 13
+Step: 14
+Step: 15
+Step: 16
+Step: 17
+Step: 18
+Step: 19
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),10) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),12) occurs(cpa_certify(cpa_p2),15) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),11) occurs(cpa_obtain(cpa_p2,cpa_s2),14) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),13)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),13) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),14) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),15) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),16) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),17) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),10) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p1),10) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p1,cpa_s1),9) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),6) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),7) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),8) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),5) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),9) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),7) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),6) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),8) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),12) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),13) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),14) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),15) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),16) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),11) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),17) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),13) occurs(cpa_certify(cpa_p2),16) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),12) occurs(cpa_obtain(cpa_p2,cpa_s2),15) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),14)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+occurs(cpa_advance(cpa_s0,cpa_s1),6) occurs(cpa_advance(cpa_s1,cpa_s2),12) occurs(cpa_certify(cpa_p0),2) occurs(cpa_certify(cpa_p0),5) occurs(cpa_certify(cpa_p1),11) occurs(cpa_certify(cpa_p1),8) occurs(cpa_certify(cpa_p2),14) occurs(cpa_certify(cpa_p2),17) occurs(cpa_obtain(cpa_p0,cpa_s0),1) occurs(cpa_obtain(cpa_p0,cpa_s0),4) occurs(cpa_obtain(cpa_p1,cpa_s1),10) occurs(cpa_obtain(cpa_p1,cpa_s1),7) occurs(cpa_obtain(cpa_p2,cpa_s2),13) occurs(cpa_obtain(cpa_p2,cpa_s2),16) occurs(cpa_request_copy(cpa_p0,cpa_s0),3) occurs(cpa_request_copy(cpa_p1,cpa_s1),9) occurs(cpa_request_copy(cpa_p2,cpa_s2),15)
+SAT
diff --git a/app/clingo/tests/lua/cover-lua.lp b/app/clingo/tests/lua/cover-lua.lp
new file mode 100644
index 0000000..0d0091f
--- /dev/null
+++ b/app/clingo/tests/lua/cover-lua.lp
@@ -0,0 +1,111 @@
+#script (lua)
+
+clingo = require("clingo")
+
+State = { }
+State.__index = State
+
+function State.new()
+    local x = { 
+        leaves = {},
+        last   = nil
+    }
+    setmetatable(x, State)
+    return x
+end
+
+function State:fix(k)
+    local leaf = self.leaves[k.number-1]
+    if leaf then
+        return leaf
+    else
+        return {}
+    end
+end
+
+function State:on_model(m)
+    self.last = m:symbols{atoms=true}
+    for key,atom in ipairs(self.last) do
+        if atom.name == "leaf" then
+            local args = atom.arguments
+            self.leaves[args[1]] = args[2]
+        end
+    end
+end
+
+function State:prepare_instance(k)
+    local edges = {}
+    local cover = {}
+    local vertices = {}
+    for key,atom in ipairs(self.last) do
+        if atom.name == "edge" then
+            local args = atom.arguments
+            if args[1].number == k-1 then
+                edges[#edges + 1] = clingo.Tuple{args[2], args[3]}
+                vertices[#vertices + 1] = args[2]
+                vertices[#vertices + 1] = args[3]
+            end
+        end
+        if atom.name == "cover" then
+            cover[#cover + 1] = atom.arguments[2]
+        end
+    end
+    self.edge = function (self) return edges end
+    self.vertex = function (self) return vertices end
+    self.cover = function (self) return cover end
+end
+
+function State:run(prg)
+    local pre = clingo.Control()
+    pre:add("base", {}, "\
+edge(a,(b;c)).\n\
+edge(b,(c;d)).\n\
+edge(d,e).\n\
+edge(e,f).\n\
+\n\
+edge(x,(a;c)). % edge to keep something to solve\n\
+\n\
+edge(X,Y) :- edge(Y,X).\n\
+vertex(X) :- edge(X,Y;Y,X).\n\
+\n\
+edge(0,X,Y) :- edge(X,Y).\n")
+    pre:add("step", {"k"}, "\
+:- not leaf(k-1,@fix(k)).\n\
+\n\
+1 { leaf(k,X) : vertex(X) } 1.\n\
+cover(k,X) :- edge(k-1,X,Y), leaf(k,Y).\n\
+edge(k,X,Y) :- edge(k-1,X,Y), not cover(k,X), not cover(k,Y).\n\
+\n\
+:- edge(k-1,X,Y), leaf(k,Y), edge(k-1,Y,Z), X < Z.\n\
+:- leaf(k,Y), not edge(k-1,_,Y).\n")
+    pre:ground({{"base", {}}}, self)
+    local ret = pre:solve(function(...) self:on_model(...) end)
+    local k = 0
+    while ret.satisfiable do
+        k = k + 1
+        pre:cleanup()
+        pre:ground({{"step", {k}}}, self)
+        ret = pre:solve(function(...) self:on_model(...) end)
+    end
+    self:prepare_instance(k)
+    prg:add("base", {}, "\
+vertex(X) :- X = @vertex().\n\
+edge(X,Y) :- (X,Y) = @edge().\n\
+cover(X)  :- X = @cover().\n\
+\n\
+{ cover(X) : vertex(X) }.\n\
+:- edge(X,Y), not cover(X), not cover(Y).\n\
+%#minimize { 1,X : cover(X) }.\n\
+\n\
+#show cover/1.\n")
+    prg:ground({{"base", {}}}, self)
+    prg.configuration.solve.models = 0
+    prg:solve()
+end
+
+function main(prg)
+    local s = State.new(prg)
+    s:run(prg)
+end
+
+#end.
diff --git a/app/clingo/tests/lua/cover-lua.sol b/app/clingo/tests/lua/cover-lua.sol
new file mode 100644
index 0000000..00cf084
--- /dev/null
+++ b/app/clingo/tests/lua/cover-lua.sol
@@ -0,0 +1,6 @@
+Step: 1
+cover(a) cover(b) cover(c) cover(e)
+cover(a) cover(b) cover(c) cover(e) cover(x)
+cover(a) cover(b) cover(e) cover(x)
+cover(b) cover(c) cover(e) cover(x)
+SAT
diff --git a/app/clingo/tests/lua/csp-shrinking.lp b/app/clingo/tests/lua/csp-shrinking.lp
new file mode 100644
index 0000000..1f1e30b
--- /dev/null
+++ b/app/clingo/tests/lua/csp-shrinking.lp
@@ -0,0 +1,16 @@
+%!clingo scratch/csp-shrinking.lp 0 -q -V0
+
+#script (lua)
+
+function main(prg)
+    for i=10,-2,-3 do
+        prg:ground({{"p", {i}}})
+        prg:solve()
+    end
+end
+
+#end.
+
+#program p(k).
+
+-k $<= $x $<= k.
diff --git a/app/clingo/tests/lua/csp-shrinking.sol b/app/clingo/tests/lua/csp-shrinking.sol
new file mode 100644
index 0000000..84af15c
--- /dev/null
+++ b/app/clingo/tests/lua/csp-shrinking.sol
@@ -0,0 +1,54 @@
+Step: 1
+x=-1
+x=-10
+x=-2
+x=-3
+x=-4
+x=-5
+x=-6
+x=-7
+x=-8
+x=-9
+x=0
+x=1
+x=10
+x=2
+x=3
+x=4
+x=5
+x=6
+x=7
+x=8
+x=9
+Step: 2
+x=-1
+x=-2
+x=-3
+x=-4
+x=-5
+x=-6
+x=-7
+x=0
+x=1
+x=2
+x=3
+x=4
+x=5
+x=6
+x=7
+Step: 3
+x=-1
+x=-2
+x=-3
+x=-4
+x=0
+x=1
+x=2
+x=3
+x=4
+Step: 4
+x=-1
+x=0
+x=1
+Step: 5
+UNSAT
diff --git a/app/clingo/tests/lua/domain.lp b/app/clingo/tests/lua/domain.lp
new file mode 100644
index 0000000..020363b
--- /dev/null
+++ b/app/clingo/tests/lua/domain.lp
@@ -0,0 +1,33 @@
+p(1).
+{ p(3) }. 
+#external p(1..3).
+
+q(X) :- p(X).
+
+#script (lua)
+
+
+
+clingo = require("clingo")
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    print "Solving..."
+    print "Answer: 1"
+    out = "universe(" .. tostring(#prg.symbolic_atoms) .. ")"
+    for x in prg.symbolic_atoms:iter() do
+        out = out .. " domain(" .. tostring(x.symbol) .. "," .. tostring(x.is_fact) .. "," .. tostring(x.is_external) .. ")"
+    end
+    out = out .. " in_domain(p(2)," .. tostring(prg.symbolic_atoms:lookup(clingo.Function("p", {3})) ~= nil) .. ")"
+    out = out .. " in_domain(p(4)," .. tostring(prg.symbolic_atoms:lookup(clingo.Function("p", {4})) ~= nil) .. ")"
+    for x in prg.symbolic_atoms:by_signature("p", 1) do
+        out = out .. " domain_of_p(" .. tostring(x.symbol) .. "," .. tostring(x.is_fact) .. "," .. tostring(x.is_external) .. ")"
+    end
+    for i,x in ipairs(prg.symbolic_atoms.signatures) do
+        out = out .. " sig(" .. x[1] .. "," .. tostring(x[2]) .. ")"
+    end
+    print (out)
+    io.flush()
+end
+
+#end. 
diff --git a/app/clingo/tests/lua/domain.sol b/app/clingo/tests/lua/domain.sol
new file mode 100644
index 0000000..001ec75
--- /dev/null
+++ b/app/clingo/tests/lua/domain.sol
@@ -0,0 +1,3 @@
+Step: 1
+domain(p(1),true,false) domain(p(2),false,true) domain(p(3),false,false) domain(q(1),true,false) domain(q(2),false,false) domain(q(3),false,false) domain_of_p(p(1),true,false) domain_of_p(p(2),false,true) domain_of_p(p(3),false,false) in_domain(p(2),true) in_domain(p(4),false) sig(p,1) sig(q,1) universe(6)
+UNKNOWN
diff --git a/app/clingo/tests/lua/externals.lp b/app/clingo/tests/lua/externals.lp
new file mode 100644
index 0000000..97847b0
--- /dev/null
+++ b/app/clingo/tests/lua/externals.lp
@@ -0,0 +1,19 @@
+#script (lua)
+
+Function = clingo.Function
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:assign_external(Function("a"), true)
+    prg:solve()
+    prg:assign_external(Function("a"), false)
+    prg:solve()
+    prg:assign_external(Function("a"), nil)
+    prg:solve()
+    prg:release_external(Function("a"))
+    prg:solve()
+end
+
+#end.
+
+#external a.
diff --git a/app/clingo/tests/lua/externals.sol b/app/clingo/tests/lua/externals.sol
new file mode 100644
index 0000000..9e8f54e
--- /dev/null
+++ b/app/clingo/tests/lua/externals.sol
@@ -0,0 +1,10 @@
+Step: 1
+a
+Step: 2
+
+Step: 3
+
+a
+Step: 4
+
+SAT
diff --git a/app/clingo/tests/lua/iclingo.lp b/app/clingo/tests/lua/iclingo.lp
new file mode 100644
index 0000000..8a26889
--- /dev/null
+++ b/app/clingo/tests/lua/iclingo.lp
@@ -0,0 +1,25 @@
+#program step(k).
+
+#external vol(k).
+p(k).
+:- vol(k), not 5 { p(K) : K <= k }.
+
+#script (lua)
+
+function main(prg)
+    step = 0
+    while true do
+        if step > 0 then
+            prg:release_external(clingo.Function("vol", {step-1}))
+        end
+        prg:ground({{"step", {step}}})
+        prg:assign_external(clingo.Function("vol", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
diff --git a/app/clingo/tests/lua/iclingo.sol b/app/clingo/tests/lua/iclingo.sol
new file mode 100644
index 0000000..be1ef8b
--- /dev/null
+++ b/app/clingo/tests/lua/iclingo.sol
@@ -0,0 +1,7 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+p(0) p(1) p(2) p(3) p(4) vol(4)
+SAT
diff --git a/app/clingo/tests/lua/icolor.lp b/app/clingo/tests/lua/icolor.lp
new file mode 100644
index 0000000..ff52e97
--- /dev/null
+++ b/app/clingo/tests/lua/icolor.lp
@@ -0,0 +1,45 @@
+% clingo-4.3.0 instance.lp color.ilp -c imin=7 0
+
+#include .
+
+#program check(k).
+:- query(0), k == 0.
+
+#program step(k).
+
+node(X)   :- node(X,k).
+edge(X,Y) :- edge(X,Y,k).
+color(C)  :- color(C,k).
+
+new(X,C,k) :- node(X,k), color(C).
+new(X,C,k) :- node(X), color(C,k).
+
+new(X,Y,C,k) :- edge(X,Y,k), color(C).
+new(X,Y,C,k) :- edge(X,Y), new(X,C,k).
+new(X,Y,C,k) :- edge(X,Y), node(Y,k), color(C).
+
+{ assign(X,C) } :- new(X,C,k).
+
+assigned(X,C) :- new(X,C,k), assign(X,C).
+assigned(X,C) :- new(X,C,k), assigned(X,C+1).
+:- new(X,C,k), assign(X,C-1), assigned(X,C).
+:- node(X,k), not assigned(X,1).
+
+:- new(X,Y,C,k), assign(X,C), assign(Y,C). % , edge(X,Y)
+
+#external assigned(X,1)   : node(X,k).
+#external assigned(X,C+1) : new(X,C,k).
+
+#show assign/2.
+% clingo-4 instance.lp color.lp 0
+% clingo-4.3.0 instance.lp color.ilp -c imin=7 0
+
+#program base.
+
+node(1,1).
+color(1,2).
+color(2,3).
+node(2,4).
+edge(1,2,5).
+node(3,6). edge(2,3,6).
+color(3,7).
diff --git a/app/clingo/tests/lua/icolor.sol b/app/clingo/tests/lua/icolor.sol
new file mode 100644
index 0000000..798dac8
--- /dev/null
+++ b/app/clingo/tests/lua/icolor.sol
@@ -0,0 +1,5 @@
+Step: 1
+Step: 2
+Step: 3
+assign(1,1)
+SAT
diff --git a/app/clingo/tests/lua/inccsp-onmodel.cmd b/app/clingo/tests/lua/inccsp-onmodel.cmd
new file mode 100644
index 0000000..b6f4e05
--- /dev/null
+++ b/app/clingo/tests/lua/inccsp-onmodel.cmd
@@ -0,0 +1 @@
+--outf=3
diff --git a/app/clingo/tests/lua/inccsp-onmodel.lp b/app/clingo/tests/lua/inccsp-onmodel.lp
new file mode 100644
index 0000000..6184f7b
--- /dev/null
+++ b/app/clingo/tests/lua/inccsp-onmodel.lp
@@ -0,0 +1,37 @@
+#script (lua)
+
+function make_on_model()
+    print ("Solving...")
+    counter = 1
+    return function (m)
+        print ("Answer: "  .. tostring(counter))
+        print (m)
+        counter = counter + 1
+    end
+end
+
+function main(prg)
+    prg:ground({{"base", {}}, {"check", {0}}})
+    prg:solve(make_on_model())
+    prg:ground({{"check", {1}}})
+    prg:solve(make_on_model())
+    prg:ground({{"check", {2}}})
+    prg:solve(make_on_model())
+    prg:ground({{"check", {3}}})
+    prg:solve(make_on_model())
+    print ("SATISFIABLE")
+	print ()
+end
+
+#end.
+
+#program base.
+
+1 { p(0..3) } 1.
+
+$x $= 1.
+
+#program check(k).
+
+#show p/1.
+#show $x : p(k).
diff --git a/app/clingo/tests/lua/inccsp-onmodel.sol b/app/clingo/tests/lua/inccsp-onmodel.sol
new file mode 100644
index 0000000..1b58170
--- /dev/null
+++ b/app/clingo/tests/lua/inccsp-onmodel.sol
@@ -0,0 +1,21 @@
+Step: 1
+p(0) x=1
+p(1)
+p(2)
+p(3)
+Step: 2
+p(0) x=1
+p(1) x=1
+p(2)
+p(3)
+Step: 3
+p(0) x=1
+p(1) x=1
+p(2) x=1
+p(3)
+Step: 4
+p(0) x=1
+p(1) x=1
+p(2) x=1
+p(3) x=1
+SAT
diff --git a/app/clingo/tests/lua/inccsp.lp b/app/clingo/tests/lua/inccsp.lp
new file mode 100644
index 0000000..35808e6
--- /dev/null
+++ b/app/clingo/tests/lua/inccsp.lp
@@ -0,0 +1,14 @@
+#include .
+
+#const imin=4.
+
+#program base.
+
+1 { p(0..3) } 1.
+
+$x $= 1.
+
+#program check(k).
+
+#show p/1.
+#show $x : p(k).
diff --git a/app/clingo/tests/lua/inccsp.sol b/app/clingo/tests/lua/inccsp.sol
new file mode 100644
index 0000000..1b58170
--- /dev/null
+++ b/app/clingo/tests/lua/inccsp.sol
@@ -0,0 +1,21 @@
+Step: 1
+p(0) x=1
+p(1)
+p(2)
+p(3)
+Step: 2
+p(0) x=1
+p(1) x=1
+p(2)
+p(3)
+Step: 3
+p(0) x=1
+p(1) x=1
+p(2) x=1
+p(3)
+Step: 4
+p(0) x=1
+p(1) x=1
+p(2) x=1
+p(3) x=1
+SAT
diff --git a/app/clingo/tests/lua/incshow.lp b/app/clingo/tests/lua/incshow.lp
new file mode 100644
index 0000000..2b083d3
--- /dev/null
+++ b/app/clingo/tests/lua/incshow.lp
@@ -0,0 +1,12 @@
+#include .
+
+#const imin=4.
+
+#program base.
+
+1 { p(0..3) } 1.
+
+#program check(k).
+
+#show p/1.
+#show x : p(k).
diff --git a/app/clingo/tests/lua/incshow.sol b/app/clingo/tests/lua/incshow.sol
new file mode 100644
index 0000000..57a2600
--- /dev/null
+++ b/app/clingo/tests/lua/incshow.sol
@@ -0,0 +1,21 @@
+Step: 1
+p(0) x
+p(1)
+p(2)
+p(3)
+Step: 2
+p(0) x
+p(1) x
+p(2)
+p(3)
+Step: 3
+p(0) x
+p(1) x
+p(2) x
+p(3)
+Step: 4
+p(0) x
+p(1) x
+p(2) x
+p(3) x
+SAT
diff --git a/app/clingo/tests/lua/mutex-bug.lp b/app/clingo/tests/lua/mutex-bug.lp
new file mode 100644
index 0000000..be58343
--- /dev/null
+++ b/app/clingo/tests/lua/mutex-bug.lp
@@ -0,0 +1,124 @@
+#script (lua) 
+function main(prg)
+    prg:ground({{"base", {}}, {"plan_graph_base", {}}})
+
+    for step = 1,3,1 do
+        prg:ground({{"plan_graph_step", {step}}})
+        prg:solve()
+    end
+--  Comment line 8 and uncomment line 11
+--  prg:solve()
+end
+#end.
+
+#program plan_graph_base.
+valid_f(FLUENT, 1) :- init(FLUENT).
+valid_f1(FLUENT, 1) :- init(FLUENT).
+
+#program plan_graph_step(time).
+
+%Encoding 1
+
+valid_a(ACT, time) :- action(ACT); valid_f(FLUENT, time) : pre(ACT, FLUENT);
+            not mutex(F1, F2, time) : req_both(ACT, F1, F2).
+
+valid_pre(ACT, FLUENT, time) :- valid_a(ACT, time), pre(ACT, FLUENT).
+valid_add(ACT, FLUENT, time) :- valid_a(ACT, time), addadd(ACT, FLUENT).
+valid_f(FLUENT, time + 1) :- valid_add(_, FLUENT, time).
+
+mutex_actions(A1, A2, time) :- valid_a(A1, time), valid_a(A2, time), conflicting(A1, A2).
+
+mutex_a_with_f(A1, P2, time) :- mutex(P1, P2, time), valid_pre(A1, P1, time).
+mutex_actions(A1, A2, time) :- mutex_a_with_f(A1, P2, time), valid_pre(A2, P2, time).
+%mutex_actions(A1, A2, time) :- mutex(P1, P2, time), valid_pre(A1, P1, time), valid_pre(A2, P2, time).
+
+mutex_a_sym(A1, A2, time; A2, A1, time) :- mutex_actions(A1, A2, time).
+
+closes(A2, F1, time) :- valid_a(A2, time), valid_f(F1, time+1); mutex_a_sym(A1, A2, time) : valid_add(A1, F1, time).
+mutex(F1, F2, time+1) :- F1 < F2, valid_f(F1, time+1), valid_f(F2, time+1);
+            closes(A2, F1, time) : valid_add(A2, F2, time).
+
+% Encoding 2:
+% Identical to encoding 1 except for lines 32 and 33 vs. line 57.
+% However these should generate identical groundings, but they don't for some reason
+
+valid_a1(ACT, time) :- action(ACT); valid_f1(FLUENT, time) : pre(ACT, FLUENT);
+            not mutex1(F1, F2, time) : req_both(ACT, F1, F2).
+
+valid_pre1(ACT, FLUENT, time) :- valid_a1(ACT, time), pre(ACT, FLUENT).
+valid_add1(ACT, FLUENT, time) :- valid_a1(ACT, time), addadd(ACT, FLUENT).
+valid_f1(FLUENT, time + 1) :- valid_add1(_, FLUENT, time).
+
+mutex_actions1(A1, A2, time) :- valid_a1(A1, time), valid_a1(A2, time), conflicting(A1, A2).
+
+%mutex_a_with_f1(A1, P2, time) :- mutex1(P1, P2, time), valid_pre1(A1, P1, time).
+%mutex_actions1(A1, A2, time) :- mutex_a_with_f1(A1, P2, time), valid_pre1(A2, P2, time).
+mutex_actions1(A1, A2, time) :- mutex1(P1, P2, time), valid_pre1(A1, P1, time), valid_pre1(A2, P2, time).
+
+mutex_a_sym1(A1, A2, time; A2, A1, time) :- mutex_actions1(A1, A2, time).
+
+closes1(A2, F1, time) :- valid_a1(A2, time), valid_f1(F1, time+1); mutex_a_sym1(A1, A2, time) : valid_add1(A1, F1, time).
+mutex1(F1, F2, time+1) :- F1 < F2, valid_f1(F1, time+1), valid_f1(F2, time+1);
+            closes1(A2, F1, time) : valid_add1(A2, F2, time).
+
+% diff reports if the two encodings are not the same
+
+diff(A1, A2, time) :- mutex_actions1(A1, A2, time), not mutex_actions(A1, A2, time).
+diff(A1, A2, time) :- mutex_actions(A1, A2, time), not mutex_actions1(A1, A2, time).
+
+#program base.
+
+#show diff/3.
+
+preserve_action(preserve(F)) :- fact(F).
+action(A) :- preserve_action(A).
+pre(preserve(F), F) :- fact(F).
+addadd(preserve(F), F) :- fact(F).
+
+prepre(A, F) :- pre(A, F), not del(A, F).
+deldel(A, F) :- del(A, F), not pre(A, F).
+predel(A, F) :- pre(A, F), del(A, F).
+addadd(A, F) :- add(A, F), not pre(A, F), not del(A, F).
+
+conflicting(A1, A2) :- pre(A1, F), del(A2, F), A1 != A2.
+
+req_both(ACT, F1, F2) :- pre(ACT, F1), pre(ACT, F2), F1 < F2.
+
+type(object).
+type(ferry, object).
+fact(at_ferry(X)) :- type(X, object).
+fact(at(X, Y)) :- type(X, object), type(Y, object).
+fact(on(X, Y)) :- type(X, object), type(Y, object).
+fact(empty_ferry).
+action(debark(X, Y)) :- type(X, object), type(Y, object), auto__(X), place__(Y).
+pre(debark(X, Y), on(X, ferry)) :- action(debark(X, Y)).
+pre(debark(X, Y), at_ferry(Y)) :- action(debark(X, Y)).
+add(debark(X, Y), at(X, Y)) :- action(debark(X, Y)).
+add(debark(X, Y), empty_ferry) :- action(debark(X, Y)).
+del(debark(X, Y), on(X, ferry)) :- action(debark(X, Y)).
+action(sail(X, Y)) :- type(X, object), type(Y, object), place__(X), place__(Y).
+pre(sail(X, Y), at_ferry(X)) :- action(sail(X, Y)).
+add(sail(X, Y), at_ferry(Y)) :- action(sail(X, Y)).
+del(sail(X, Y), at_ferry(X)) :- action(sail(X, Y)).
+action(board(X, Y)) :- type(X, object), type(Y, object), place__(Y), auto__(X).
+pre(board(X, Y), at(X, Y)) :- action(board(X, Y)).
+pre(board(X, Y), at_ferry(Y)) :- action(board(X, Y)).
+pre(board(X, Y), empty_ferry) :- action(board(X, Y)).
+add(board(X, Y), on(X, ferry)) :- action(board(X, Y)).
+del(board(X, Y), at(X, Y)) :- action(board(X, Y)).
+del(board(X, Y), empty_ferry) :- action(board(X, Y)).
+type(c1, object).
+type(b, object).
+type(c2, object).
+type(a, object).
+place__(a).
+place__(b).
+auto__(c1).
+auto__(c2).
+init(at(c1, a)).
+init(at(c2, a)).
+init(at_ferry(a)).
+init(empty_ferry).
+goal(at(c1, b)).
+goal(at(c2, b)).
+
diff --git a/app/clingo/tests/lua/mutex-bug.sol b/app/clingo/tests/lua/mutex-bug.sol
new file mode 100644
index 0000000..4ff07fa
--- /dev/null
+++ b/app/clingo/tests/lua/mutex-bug.sol
@@ -0,0 +1,7 @@
+Step: 1
+
+Step: 2
+
+Step: 3
+
+SAT
diff --git a/app/clingo/tests/lua/parse-term.lp b/app/clingo/tests/lua/parse-term.lp
new file mode 100644
index 0000000..ddb3405
--- /dev/null
+++ b/app/clingo/tests/lua/parse-term.lp
@@ -0,0 +1,14 @@
+#script (lua)
+
+c = clingo.Control()
+
+function get()
+    return { clingo.parse_term("1"), clingo.parse_term("p(1+2)"), clingo.parse_term("-p"), clingo.parse_term("-p(1)") }
+end
+
+c:ground({{"base", {}}})
+c:solve()
+
+#end.
+
+p(@get()).
diff --git a/app/clingo/tests/lua/parse-term.sol b/app/clingo/tests/lua/parse-term.sol
new file mode 100644
index 0000000..8d2055c
--- /dev/null
+++ b/app/clingo/tests/lua/parse-term.sol
@@ -0,0 +1,3 @@
+Step: 1
+p(-p(1)) p(-p) p(1) p(p(3))
+SAT
diff --git a/app/clingo/tests/lua/project_bug.lp b/app/clingo/tests/lua/project_bug.lp
new file mode 100644
index 0000000..d06232f
--- /dev/null
+++ b/app/clingo/tests/lua/project_bug.lp
@@ -0,0 +1,13 @@
+#script (lua)
+
+function main(ctl)
+    ctl:ground({{"base",{}}})
+    ctl:add("rules", {}, "r :- q(_), p.")
+    ctl:ground({{"rules", {}}})
+    ctl:solve()
+end
+
+#end.
+
+p.
+q(1).
diff --git a/app/clingo/tests/lua/project_bug.sol b/app/clingo/tests/lua/project_bug.sol
new file mode 100644
index 0000000..190c2d0
--- /dev/null
+++ b/app/clingo/tests/lua/project_bug.sol
@@ -0,0 +1,3 @@
+Step: 1
+p q(1) r
+SAT
diff --git a/app/clingo/tests/lua/propagator.cmd b/app/clingo/tests/lua/propagator.cmd
new file mode 100644
index 0000000..cf70a96
--- /dev/null
+++ b/app/clingo/tests/lua/propagator.cmd
@@ -0,0 +1 @@
+-q1,1
diff --git a/app/clingo/tests/lua/propagator.lp b/app/clingo/tests/lua/propagator.lp
new file mode 100644
index 0000000..56063ac
--- /dev/null
+++ b/app/clingo/tests/lua/propagator.lp
@@ -0,0 +1,371 @@
+#script (lua)
+
+require("clingo")
+
+-- {{{1 Aux
+
+function max(a, b) 
+    if a < b then
+        return b
+    else
+        return a
+    end
+end
+
+function table.unique(t)
+    local res, n = 1, #t
+    for i = 2, n do
+        if t[i] ~= t[i-1] then
+            res = res + 1
+            t[res] = t[i]
+        end
+    end
+    for i = res+1, n do
+        t[i] = nil
+    end
+end
+
+function table.copy(t)
+    local u = {}
+    for i, v in pairs(t) do
+        u[i] = v
+    end
+    return u
+end
+
+function table.find(t, k)
+    for _, v in pairs(t) do
+        if v == k then
+            return true
+        end
+    end
+    return false
+end
+
+function table.tostring(t)
+    local r, c = "", false
+    for _, k in ipairs(t) do
+        if c then
+            r = r .. ","
+        else
+            c = true
+        end
+        r = r .. tostring(k)
+    end
+    return r
+end
+
+function table.append(t, v)
+    t[#t+1] = v
+end
+
+function table.setdefault(t, k, d)
+    local x = t[k]
+    if x == nil then
+        x = d
+        t[k] = x
+    end
+    return x
+end
+
+function table.keys(t)
+    local keys = {}
+    for k, _ in pairs(t) do
+        table.append(keys, k)
+    end
+    return keys
+end
+
+-- {{{1 State
+
+local State = { }
+State.__index = State
+
+function State.new(pat_len, seq_len)
+    local self = setmetatable({ }, State)
+    self.seq_active = {}
+    self.stack = {}
+    self.trail = {}
+    self.pat = {}
+    self.pat_assigned = 0
+    self.pat_len = pat_len
+    self.seq_len = seq_len
+    for i = 1, seq_len do
+        self.seq_active[i] = true
+    end
+    return self
+end
+
+-- {{{1 Propagator
+
+local Propagator = { }
+Propagator.__index = Propagator
+
+-- {{{2 Initialization
+
+function Propagator.new()
+    local self = setmetatable({ }, Propagator)
+    self.__seq_atoms = {}
+    self.__pat_atoms = {}
+    self.__occ_list = {}
+    self.__item_map = {}
+    self.__item_num = 0
+    self.__pat_len = 0
+    return self
+end
+
+function Propagator:__map_item(item)
+    local mapped = self.__item_map[item]
+    if mapped == nil then
+        self.__item_num = self.__item_num + 1
+        mapped = self.__item_num
+        self.__item_map[item] = mapped
+    end
+    return mapped
+end
+
+function Propagator:__add_seq_atom(init, sid, atom)
+    assert(self.__seq_atoms[sid] == nil)
+    self.__seq_atoms[sid] = {init:solver_literal(atom.literal), {}}
+    for _, elem in ipairs(atom.elements) do
+        local index, item = elem.terms[1].number + 1, elem.terms[2]
+        assert(index >= 1)
+        local item = self:__map_item(tostring(item))
+        self.__seq_atoms[sid][2][index] = item
+    end
+end
+
+function Propagator:__add_pat_atoms(init, atom)
+    for _, elem in ipairs(atom.elements) do
+        local lit = init:solver_literal(elem.condition_id)
+        local index, item = elem.terms[1].number + 1, elem.terms[2]
+        assert(index >= 1)
+        local item = self:__map_item(tostring(item))
+        local pat = {index, item}
+        local pat_atom = self.__pat_atoms[lit]
+        if pat_atom == nil then
+            init:add_watch(lit)
+            pat_atom = {}
+            self.__pat_atoms[lit] = pat_atom
+        end
+        pat_atom[#pat_atom + 1] = pat
+        self.__pat_len = max(self.__pat_len, index)
+    end
+end
+
+function Propagator:__init_occ_list()
+    for i = 1, self.__item_num do
+        self.__occ_list[#self.__occ_list + 1] = {}
+    end
+    local sid = 1
+    for _, seq in ipairs(self.__seq_atoms) do
+        local set = table.copy(seq[2])
+        table.sort(set)
+        table.unique(set)
+        for _, item in ipairs(set) do
+            assert(item ~= nil)
+            table.append(self.__occ_list[item], sid)
+        end
+        sid = sid + 1
+    end
+end
+
+function Propagator:init(init)
+    for atom in init.theory_atoms do
+        term = atom.term
+        args = term.arguments
+        if term.name == "seq" and #args == 1 then
+            self:__add_seq_atom(init, args[1].number + 1, atom)
+        end
+        if term.name == "pat" and #args == 0 then
+            self:__add_pat_atoms(init, atom)
+        end
+    end
+    self:__init_occ_list()
+    for i = 1, init.threads do
+        init:set_state(i, State.new(self.__pat_len, #self.__seq_atoms))
+    end
+end
+
+-- {{{2 Propagation
+
+function Propagator:__propagate_sequence_lit(state, control, sid, lit)
+    --print ("    propagate_lit: " .. tostring(sid) .. "/" .. tostring(lit))
+    state.seq_active[sid] = false
+    table.append(state.stack, -sid)
+    if not control.assignment:is_true(lit) then
+        local klaus = {lit}
+        for i = 1, self.__pat_len do
+            local pat = state.pat[i]
+            if pat ~= nil then
+                table.append(klaus, -pat[1])
+            end
+        end
+        --print ("      add_clause: " .. table.tostring(klaus))
+        return control:add_clause{klaus} and control:propagate()
+    end
+    return true
+end
+
+function Propagator:__propagate_sequence(state, control, sid, lit, items)
+    --print ("  propagate sequence: " .. tostring(sid) .. "/" .. tostring(lit) .. "/" .. table.tostring(items))
+    if state.pat_assigned < self.__pat_len and control.assignment:is_false(lit) then
+        return true
+    end
+    local iid = 1
+    for i = 1, self.__pat_len do
+        pat = state.pat[i]
+        while true do
+            if iid > #items then
+                return self:__propagate_sequence_lit(state, control, sid, -lit)
+            end
+            iid = iid + 1
+            if pat == nil or items[iid-1] == pat[2] then
+                break
+            end
+        end
+    end
+    return state.pat_assigned < self.__pat_len or self:__propagate_sequence_lit(state, control, sid, lit)
+end
+
+function Propagator:propagate(control, changes, state)
+    --print ("propagate: " .. table.tostring(changes))
+    if #state.trail == 0 or state.trail[#state.trail][1] < control.assignment.decision_level then
+        table.append(state.trail, {control.assignment.decision_level, #state.stack + 1})
+    end
+    for _, lit in ipairs(changes) do
+        for _, pat in ipairs(self.__pat_atoms[lit]) do
+            if state.pat[pat[1]] ~= nil then
+                assert(false)
+                -- this case should not occur if the pattern is generated properly
+                local old = state.pat[pat[1]][1]
+                assert(control.assignment:is_true(old))
+                if not control:add_clause{{-lit, -old}} or not control:propagate() then
+                    return
+                end
+            else
+                table.append(state.stack, pat[1])
+                state.pat_assigned = state.pat_assigned + 1
+                state.pat[pat[1]] = {lit, pat[2]}
+                for _, sid in ipairs(self.__occ_list[pat[2]]) do
+                    local atom = self.__seq_atoms[sid]
+                    if state.seq_active[sid] and not self:__propagate_sequence(state, control, sid, atom[1], atom[2]) then
+                        return
+                    end
+                end
+            end
+        end
+    end
+end
+
+function Propagator:undo(id, assign, changes, state)
+    --print ("undo: " .. table.tostring(changes))
+    sid = state.trail[#state.trail][2]
+    for i = sid, #state.stack do
+        psid = state.stack[i]
+        if psid >= 1 then
+            state.pat[psid] = nil
+            state.pat_assigned = state.pat_assigned - 1
+        else
+            state.seq_active[-psid] = true
+        end
+        state.stack[i] = nil
+    end
+    state.trail[#state.trail] = nil
+end
+
+-- {{{1 Main
+
+function main(c)
+    c.configuration.solve.opt_mode = "optN"
+    c:ground({ {"base", {}} })
+    c:register_propagator(Propagator.new())
+    -- :- not sup(U), seq(U,_,_), n == 0.
+    if c:get_const("n").number == 0 then
+        local grouped = {}
+        for atom in c.symbolic_atoms:by_signature("seq", 3) do
+            table.append(table.setdefault(grouped, atom.symbol.arguments[1].number, {}), atom.literal)
+        end
+        local keys = table.keys(grouped)
+        table.sort(keys)
+        for _, key in ipairs(keys) do
+            local a = c.backend:add_atom()
+            for _, l in ipairs(grouped[key]) do
+                c.backend:add_rule{{a}, {l}}
+            end
+            c.backend:add_rule{{}, {-c.symbolic_atoms:lookup(clingo.Function("sup", {key})).literal, a}}
+        end
+    end
+    -- :- sup(U), pat(_,I), not seq(U,_,I).
+    local grouped_pat, grouped_seq = {}, {}
+    for atom in c.symbolic_atoms:by_signature("pat", 2) do
+        table.append(table.setdefault(grouped_pat, tostring(atom.symbol.arguments[2]), {}), atom.literal)
+    end
+    for atom in c.symbolic_atoms:by_signature("seq", 3) do
+        local a, b = atom.symbol.arguments[1], atom.symbol.arguments[3]
+        grouped_seq[tostring(a) .. "," .. tostring(b)] = true
+    end
+    local projected_pat, projected_seq = {}, {}
+    local keys = table.keys(grouped_pat)
+    table.sort(keys)
+    for _, key in ipairs(keys) do
+        local a = c.backend:add_atom()
+        for _, l in ipairs(grouped_pat[key]) do
+            c.backend:add_rule{{a}, {l}}
+        end
+        projected_pat[key] = a
+    end
+    for atom in c.symbolic_atoms:by_signature("sup", 1) do
+        for _, key in ipairs(keys) do
+            local a, b = atom.symbol.arguments[1], key
+            if not grouped_seq[tostring(a) .. "," .. tostring(b)] then
+                c.backend:add_rule{{}, {atom.literal, projected_pat[key]}}
+            end
+        end
+    end
+    c:solve()
+end
+
+-- }}}1
+
+#end.
+
+% {{{1 ASP
+
+#show pat/2.
+
+#theory seq {
+    term { };
+    &seq/1 : term, body;
+    &pat/0 : term, directive
+}.
+
+#const n = 5.
+
+1 { pat(P,I) : seq(_,_,I) } 1 :- P = 0..(n-1).
+
+&pat { P,I : pat(P,I) }.
+sup(U) :- &seq(U) { P,I : seq(U,P,I) }, seq(U,_,_).
+
+#maximize { 1,U : sup(U) }.
+
+% abaca
+seq(0,0,a).
+seq(0,1,b).
+seq(0,2,a).
+seq(0,3,c).
+seq(0,4,a).
+
+% abdca
+seq(1,0,a).
+seq(1,1,b).
+seq(1,2,d).
+seq(1,3,c).
+seq(1,4,a).
+
+% aedca
+seq(2,0,a).
+seq(2,1,e).
+seq(2,2,d).
+seq(2,3,c).
+seq(2,4,a).
diff --git a/app/clingo/tests/lua/propagator.sol b/app/clingo/tests/lua/propagator.sol
new file mode 100644
index 0000000..cfca62c
--- /dev/null
+++ b/app/clingo/tests/lua/propagator.sol
@@ -0,0 +1,5 @@
+Step: 1
+pat(0,a) pat(1,b) pat(2,a) pat(3,c) pat(4,a)
+pat(0,a) pat(1,b) pat(2,d) pat(3,c) pat(4,a)
+pat(0,a) pat(1,e) pat(2,d) pat(3,c) pat(4,a)
+OPTIMUM FOUND
diff --git a/app/clingo/tests/lua/queens.lp b/app/clingo/tests/lua/queens.lp
new file mode 100644
index 0000000..2e7dc7e
--- /dev/null
+++ b/app/clingo/tests/lua/queens.lp
@@ -0,0 +1,39 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    stop = 10
+    while true do
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+        end
+        prg:ground({{"cumulative", {step}}})
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if step == stop then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#program cumulative(k).
+
+dim(k).
+
+{q(X,k) : dim(X)}.
+{q(k,Y) : dim(Y), Y 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#program base.
+
+dim(1..dimension).
+
+robot(red).
+robot(blue).
+robot(green).
+robot(yellow).
+
+direction(north).
+direction(east).
+direction(south).
+direction(west).
+
+% blockages
+blocked(I,J,D) :- barrier(I,J,D),direction(D),dim(I),dim(J).
+
+blocked(1..dimension,1           ,north).
+blocked(   dimension,1..dimension,east ).
+blocked(1..dimension,   dimension,south).
+blocked(           1,1..dimension,west ).
+
+blocked(I+1,J,west ) :- blocked(I,J,east ), dim(I), dim(J), I1.
+blocked(I,J-1,south) :- blocked(I,J,north), dim(I), dim(J), J>1.
+
+% this should simplify sth.
+dir(west, -1,  0).
+dir(east,  1,  0).
+dir(north, 0, -1).
+dir(south, 0,  1).
+
+#program cumulative(t).
+
+% which places are reachable by a robot
+reachable(R, I + DI, J + DJ, D, t) :- not blocked2(I, J, t), dir(D, DI, DJ), go(R, D, t), position(R, I, J, t - 1), dim(I), dim(J).
+reachable(R, I + DI, J + DJ, D, t) :- not blocked2(I, J, t), reachable(R, I, J, D, t), dir(D, DI, DJ), go(R, D, t), dim(I), dim(J).
+
+% no crossing of blockages or robots
+blocked2(I, J, t) :- blocked(I, J, D), go(R, D, t).
+blocked2(I - DI, J - DJ, t) :- position(R, I, J, t - 1), selectDir(D, t), dir(D, DI, DJ).
+
+% move it (no stopping if there is neither a blockage nor a robot)
+position(R, I, J, t) :- reachable(R, I, J, D, t), not reachable(R, I + DI, J + DJ, D, t), dir(D, DI, DJ), go(R, D, t).
+
+% one has to be moved
+moved(t) :- reachable(R, I, J, D, t).
+ :- not moved(t).
+
+% inertia
+position(R, I, J, t) :- position(R, I, J, t - 1), not selectRobot(R, t), robot(R), dim(I),dim(J).
+
+% plan generator
+1 { selectRobot(R, t) : robot(R) } 1.
+1 { selectDir(D,t)    : direction(D) } 1.
+
+go(R, D, t) :- selectRobot(R, t), selectDir(D,t).
+
+%#show moved/4.
+#show go/3.
+#show position/4.
+%#show reachable/4.
+
+% Authentic board from Ricochet Robots (Rasende Roboter) by Alex Randolph
+
+#const dimension=16.
+
+#external volatile(t).
+
+% --- Uncomment an integrity constraint to pose a query
+%   - numbers indicated minimum number of moves  
+%   - sometimes a heuristics was better than another
+
+:- instance(1), not position(red,      5,2,t), volatile(t).  % red moon:        9, vmtf 
+:- instance(2), not position(red,     15,2,t), volatile(t).  % red triangle:   10, ?
+:- instance(3), not position(green,    2,3,t), volatile(t).  % green triangle:  9, berkmin
+:- instance(4), not position(blue,    12,3,t), volatile(t).  % blue star:       8, ?
+:- instance(5), not position(yellow,   7,4,t), volatile(t).  % yellow star:    11, ?
+:- instance(6), not position(blue,     4,7,t), volatile(t).  % blue saturn:     8, ?
+:- instance(7), not position(green,   14,7,t), volatile(t).  % green moon:      3, ?
+:- instance(8), not position(yellow,  11,8,t), volatile(t).  % yellow saturn:  13, vmtf??
+:- instance(9), not position(yellow,  5,10,t), volatile(t).  % yellow moon:     2, ?
+:- instance(10), not position(green,  2,11,t), volatile(t).  % green star:     11, ?
+:- instance(11), not position(red,   14,11,t), volatile(t).  % red star:        9, ?
+:- instance(12), not position(green, 11,12,t), volatile(t).  % green saturn:   11, ?
+:- instance(13), not position(yellow,15,13,t), volatile(t).  % yellow star:     9, ?
+:- instance(14), not position(blue,   7,14,t), volatile(t).  % blue star:       6, ?
+:- instance(15), not position(red,    3,15,t), volatile(t).  % red saturn:      5, ?
+:- instance(16), not position(blue,  10,15,t), volatile(t).  % blue moon:      12, vsids?
+
+%:- not position(red,1,1,t), t==0.
+%:- not position(blue,1,16,t), t==0.
+%:- not position(green,16,1,t), t==0.
+%:- not position(yellow,16,16,t), t==0.
+%:- not go(red,east,t), t==1.
+:- not position(blue,1,16,t), t==1.
+%:- not position(green,16,1,t), t==1.
+%:- not position(yellow,16,16,t), t==1.
+%:- not position(red,2,1,t), t==1.
+%:- not go(red,south,t), t==2.
+%:- not position(blue,1,16,t), t==2.
+:- not position(green,16,1,t), t==2.
+%:- not position(yellow,16,16,t), t==2.
+%:- not position(red,2,2,t), t==2.
+%:- not go(red,east,t), t==3.
+%:- not position(blue,1,16,t), t==3.
+%:- not position(green,16,1,t), t==3.
+%:- not position(yellow,16,16,t), t==3.
+:- not position(red,4,2,t), t==3.
+%:- not go(red,north,t), t==4.
+%:- not position(blue,1,16,t), t==4.
+%:- not position(green,16,1,t), t==4.
+%:- not position(yellow,16,16,t), t==4.
+%:- not position(red,4,1,t), t==4.
+%:- not go(red,west,t), t==5.
+%:- not position(blue,1,16,t), t==5.
+%:- not position(green,16,1,t), t==5.
+%:- not position(yellow,16,16,t), t==5.
+%:- not position(red,3,1,t), t==5.
+:- not go(red,south,t), t==6.
+%:- not position(blue,1,16,t), t==6.
+%:- not position(green,16,1,t), t==6.
+%:- not position(yellow,16,16,t), t==6.
+%:- not position(red,3,15,t), t==6.
+
+#program base.
+
+instance(15).
+
+position(red,1,1,0).
+position(blue,1,dimension,0).
+position(green,dimension,1,0).
+position(yellow,dimension,dimension,0).
+
+barrier( 2, 1,east).
+barrier(10, 1,east).
+barrier( 4, 2,east).
+barrier(14, 2,east).
+barrier( 2, 3,east).
+barrier( 11,3,east).
+barrier( 7, 4,east).
+barrier( 3, 7,east).
+barrier( 14,7,east).
+barrier( 7, 8,east). % middle
+barrier( 10,8,west). % middle
+barrier( 11,8,east).
+barrier( 7, 9,east). % middle
+barrier( 10,9,west). % middle
+barrier( 4,10,east).
+barrier( 2,11,east).
+barrier( 8,11,east).
+barrier(13,11,east).
+barrier(11,12,east).
+barrier(14,13,east).
+barrier( 6,14,east).
+barrier(3, 15,east).
+barrier(10,15,east).
+barrier(4, 16,east).
+barrier(12,16,east).
+
+barrier( 5, 1,south).
+barrier(15, 1,south).
+barrier( 2, 2,south).
+barrier(12, 3,south).
+barrier( 7, 4,south).
+barrier(16, 4,south).
+barrier( 1, 6,south).
+barrier( 4, 7,south).
+barrier( 8, 7,south). % middle
+barrier( 9, 7,south). % middle
+barrier(11, 7,south).
+barrier(14, 7,south).
+barrier(16, 9,south).
+barrier( 2,10,south).
+barrier( 5,10,south).
+barrier( 8,10,north). % middle
+barrier( 9,10,north). % middle
+barrier( 9,10,south).
+barrier(14,10,south).
+barrier( 1,12,south).
+barrier(11,12,south).
+barrier( 7,13,south).
+barrier(15,13,south).
+barrier(10,14,south).
+barrier( 3,15,south).
+
diff --git a/app/clingo/tests/lua/robots.sol b/app/clingo/tests/lua/robots.sol
new file mode 100644
index 0000000..cca8a79
--- /dev/null
+++ b/app/clingo/tests/lua/robots.sol
@@ -0,0 +1,8 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+go(red,east,1) go(red,east,3) go(red,north,4) go(red,south,2) go(red,south,6) go(red,west,5) position(blue,1,16,0) position(blue,1,16,1) position(blue,1,16,2) position(blue,1,16,3) position(blue,1,16,4) position(blue,1,16,5) position(blue,1,16,6) position(green,16,1,0) position(green,16,1,1) position(green,16,1,2) position(green,16,1,3) position(green,16,1,4) position(green,16,1,5) position(green,16,1,6) position(red,1,1,0) position(red,2,1,1) position(red,2,2,2) position(red,3,1,5) position(red,3,15,6) position(red,4,1,4) position(red,4,2,3) position(yellow,16,16,0) position(yellow,16,16,1) position(yellow,16,16,2) position(yellow,16,16,3) position(yellow,16,16,4) position(yellow,16,16,5) position(yellow,16,16,6)
+SAT
diff --git a/app/clingo/tests/lua/setconfig.lp b/app/clingo/tests/lua/setconfig.lp
new file mode 100644
index 0000000..48cc504
--- /dev/null
+++ b/app/clingo/tests/lua/setconfig.lp
@@ -0,0 +1,28 @@
+#script (lua)
+
+function main(prg)
+    prg:ground({{"step1", {}}})
+    prg:assign_external(clingo.Function("f"), true)
+    prg.configuration.solve.models = 1
+    prg:solve()
+    prg:ground({{"step2", {}}})
+    prg:assign_external(clingo.Function("f"), false)
+    prg.configuration.solve.models = 0
+    prg:solve()
+end
+
+#end.
+
+#program step1.
+
+#external f.
+{ a; b; c }.
+
+#show f/0.
+
+#program step2.
+
+#show a : a.
+#show b : b.
+#show c : c.
+
diff --git a/app/clingo/tests/lua/setconfig.sol b/app/clingo/tests/lua/setconfig.sol
new file mode 100644
index 0000000..32dfa0d
--- /dev/null
+++ b/app/clingo/tests/lua/setconfig.sol
@@ -0,0 +1,12 @@
+Step: 1
+f
+Step: 2
+
+a
+a b
+a b c
+a c
+b
+b c
+c
+SAT
diff --git a/app/clingo/tests/lua/show.lp b/app/clingo/tests/lua/show.lp
new file mode 100644
index 0000000..978c50f
--- /dev/null
+++ b/app/clingo/tests/lua/show.lp
@@ -0,0 +1,56 @@
+#script (lua)
+
+models = {}
+
+function getModels()
+    return models
+end
+
+function normalize(terms)
+    table.sort(terms)
+    return terms
+end
+
+function split(model)
+    terms = {}
+    for i in string.gmatch(tostring(model), "%S+") do terms[#terms+1] = i end
+    table.sort(terms)
+    return terms
+end
+
+function on_model(model)
+    models[#models+1] = clingo.Function("model", split(model))
+    models[#models+1] = clingo.Function("shown", normalize(model:symbols{shown=true}))
+    models[#models+1] = clingo.Function("atoms", normalize(model:symbols{atoms=true}))
+    models[#models+1] = clingo.Function("terms", normalize(model:symbols{terms=true}))
+    models[#models+1] = clingo.Function("csp",   normalize(model:symbols{csp=true}))
+end
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:solve(on_model)
+    prg:ground({{"result", {}}})
+    prg:solve()
+end
+
+#end.
+
+$1 $= 11.
+{ b }.
+c.
+$x $= 42.
+$y(1) $= 13.
+$y(2) $= 23.
+$z $= 7.
+#show $1.
+#show c/0.
+#show a : b.
+#show $x/0.
+#show $y(1) : b.
+#show $y(2) : not b.
+#show $y(3) : b.
+
+#program result.
+res(X) :- X = @getModels(). 
+#show res/1.
+
diff --git a/app/clingo/tests/lua/show.sol b/app/clingo/tests/lua/show.sol
new file mode 100644
index 0000000..f2951cd
--- /dev/null
+++ b/app/clingo/tests/lua/show.sol
@@ -0,0 +1,7 @@
+Step: 1
+1=11 a c x=42 y(1)=13
+1=11 c x=42 y(2)=23
+Step: 2
+1=11 a c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(1)=13
+1=11 c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(2)=23
+SAT
diff --git a/app/clingo/tests/lua/sokoban.lp b/app/clingo/tests/lua/sokoban.lp
new file mode 100644
index 0000000..3985146
--- /dev/null
+++ b/app/clingo/tests/lua/sokoban.lp
@@ -0,0 +1,125 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    while true do
+        parts = {}
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+            prg:cleanup()
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#show push_from/4.
+#show push_to/4.
+
+#program base.
+
+% convert my instances
+square(X, Y)        :- field(X, Y).
+target_square(X, Y) :- target(X, Y).
+initial_box(X, Y)   :- stone(X, Y).
+initial_at(X, Y)    :- start(X, Y).
+
+% possible directions
+direction(u).
+direction(d).
+direction(r).
+direction(l).
+
+% possible moves
+dir(u,  0,  1).
+dir(d,  0, -1).
+dir(r,  1,  0).
+dir(l, -1,  0).
+
+% reachable places at timestep 0
+route(X, Y, 0) :- initial_at(X, Y).
+route(X, Y, 0) :- dir(D, DX, DY), route(X + DX, Y + DY, 0), not box(X, Y, 0), square(X, Y).
+
+% box positions at timestep 0
+box(X, Y, 0) :- initial_box(X, Y).
+
+#program cumulative(k).
+
+% reachable places at timestep k
+route(X, Y, k) :- at(X, Y, k), square(X, Y).
+route(X, Y, k) :- dir(D, DX, DY), route(X + DX, Y + DY, k), not box(X, Y, k), square(X, Y).
+
+% select a place to push from (must be reachable and have a box to push)
+1 { push_from(X, Y, D, k) : square(X, Y), direction(D) } 1.
+ :- push_from(X, Y, D, k), not route(X, Y, k - 1), square(X, Y), direction(D).
+ :- push_from(X, Y, D, k), not box(X + DX, Y + DY, k - 1), square(X, Y), dir(D, DX, DY).
+
+% push the box 1 or more fields into direction D (but at least one)
+push(X, Y, D, k) :- push_from(X, Y, D, k).
+{ push(X + DX, Y + DY, D, k) } :- push(X, Y, D, k), square(X, Y), dir(D, DX, DY).
+ :- push(X, Y, D, k), not square(X + 2 * DX, Y + 2 * DY), dir(D, DX, DY).
+ :- push(X, Y, D, k), box(X + 2 * DX, Y + 2 * DY, k - 1), dir(D, DX, DY).
+
+% the last push is the final location (one could try to encode this using a min???)
+push_to(X + DX, Y + DY, D, k) :- push(X, Y, D, k), not push(X + DX, Y + DY, D, k), dir(D, DX, DY).
+
+% the player stands behind the pushed box
+at(X, Y, k) :- push_to(X, Y, D, k).
+
+% put the pushed box at the new location
+box(X + DX, Y + DY, k) :- push_to(X, Y, D, k), dir(D, DX, DY).
+% all other boxes stay where they are
+box(X, Y, k) :- box(X, Y, k - 1), square(X, Y), not push_from(X - DX, Y - DY, D, k) : dir(D, DX, DY).
+
+% assert redundant moves
+ :- push_to(X, Y, D, k - 1), push_from(X, Y, D, k).
+
+#external volatile(k).
+
+% the goal :)
+ :- target_square(X, Y), not box(X, Y, k), volatile(k).
+
+#program base.
+
+initial_at(1,1).
+square(1, 1).
+square(2, 1).
+square(3, 1).
+target_square(3, 1).
+square(4, 1).
+square(1, 2).
+square(3, 2).
+initial_box(3, 2).
+target_square(3, 2).
+square(4, 2).
+square(5, 2).
+initial_box(5, 2).
+square(6, 2).
+square(7, 2).
+square(1, 3).
+square(2, 3).
+initial_box(2, 3).
+square(3, 3).
+target_square(3, 3).
+square(4, 3).
+initial_box(4, 3).
+square(5, 3).
+square(7, 3).
+square(3, 4).
+target_square(3, 4).
+square(5, 4).
+square(6, 4).
+square(7, 4).
+square(3, 5).
+square(4, 5).
+square(5, 5).
diff --git a/app/clingo/tests/lua/sokoban.sol b/app/clingo/tests/lua/sokoban.sol
new file mode 100644
index 0000000..5d0c013
--- /dev/null
+++ b/app/clingo/tests/lua/sokoban.sol
@@ -0,0 +1,16 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+Step: 11
+push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,5) push_from(4,2,r,1) push_from(5,3,l,10) push_from(5,4,d,9) push_from(6,2,l,11) push_from(7,2,l,6) push_to(2,1,r,8) push_to(3,1,l,5) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,11) push_to(4,2,l,6) push_to(4,3,l,10) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9)
+push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,5) push_from(4,2,r,1) push_from(5,3,l,11) push_from(5,4,d,9) push_from(6,2,l,10) push_from(7,2,l,6) push_to(2,1,r,8) push_to(3,1,l,5) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,10) push_to(4,2,l,6) push_to(4,3,l,11) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9)
+push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,6) push_from(4,2,r,1) push_from(5,3,l,10) push_from(5,4,d,9) push_from(6,2,l,11) push_from(7,2,l,5) push_to(2,1,r,8) push_to(3,1,l,6) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,11) push_to(4,2,l,5) push_to(4,3,l,10) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9)
+push_from(1,1,r,8) push_from(1,3,r,3) push_from(3,1,u,7) push_from(3,3,d,4) push_from(3,3,r,2) push_from(4,1,l,6) push_from(4,2,r,1) push_from(5,3,l,11) push_from(5,4,d,9) push_from(6,2,l,10) push_from(7,2,l,5) push_to(2,1,r,8) push_to(3,1,l,6) push_to(3,2,d,4) push_to(3,3,r,3) push_to(3,3,u,7) push_to(4,2,l,10) push_to(4,2,l,5) push_to(4,3,l,11) push_to(4,3,r,2) push_to(5,2,r,1) push_to(5,3,d,9)
+SAT
diff --git a/app/clingo/tests/lua/sokoban_back.lp b/app/clingo/tests/lua/sokoban_back.lp
new file mode 100644
index 0000000..46659f1
--- /dev/null
+++ b/app/clingo/tests/lua/sokoban_back.lp
@@ -0,0 +1,137 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    while true do
+        parts = {}
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+            prg:cleanup()
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#show push_from/3.
+#show push_to/3.
+
+#program base.
+
+% convert my instances
+square(X, Y)        :- field(X, Y).
+target_square(X, Y) :- target(X, Y).
+initial_box(X, Y)   :- stone(X, Y).
+initial_at(X, Y)    :- start(X, Y).
+
+box(X,Y,0) :- target_square(X,Y).
+
+direction(u).
+direction(d).
+direction(r).
+direction(l).
+
+#program cumulative(k).
+
+1{push_to(X,Y,-k) : square(X,Y)}1.
+:- push_to(X,Y,-k), not box(X,Y,-k+1), square(X,Y).
+
+1{push_dir(D,-k) : direction(D)}1.
+:- push_to(X,Y,-k), push_dir(u,-k), square(X,Y), not square(X,Y-1).
+:- push_to(X,Y,-k), push_dir(d,-k), square(X,Y), not square(X,Y+1).
+:- push_to(X,Y,-k), push_dir(r,-k), square(X,Y), not square(X-1,Y).
+:- push_to(X,Y,-k), push_dir(l,-k), square(X,Y), not square(X+1,Y).
+
+push(X,Y-1,u,-k) :- push_to(X,Y,-k), push_dir(u,-k), square(X,Y).
+push(X,Y+1,d,-k) :- push_to(X,Y,-k), push_dir(d,-k), square(X,Y).
+push(X-1,Y,r,-k) :- push_to(X,Y,-k), push_dir(r,-k), square(X,Y).
+push(X+1,Y,l,-k) :- push_to(X,Y,-k), push_dir(l,-k), square(X,Y).
+{push(X,Y-1,u,-k)} :- push(X,Y,u,-k), square(X,Y).
+{push(X,Y+1,d,-k)} :- push(X,Y,d,-k), square(X,Y).
+{push(X-1,Y,r,-k)} :- push(X,Y,r,-k), square(X,Y).
+{push(X+1,Y,l,-k)} :- push(X,Y,l,-k), square(X,Y).
+
+:- push(X,Y,D,-k), box(X,Y,-k+1), square(X,Y), direction(D).
+:- push(X,Y,u,-k), square(X,Y), not square(X,Y-1).
+:- push(X,Y,d,-k), square(X,Y), not square(X,Y+1).
+:- push(X,Y,r,-k), square(X,Y), not square(X-1,Y).
+:- push(X,Y,l,-k), square(X,Y), not square(X+1,Y).
+
+push_from(X,Y,-k) :- push(X,Y,u,-k), not push(X,Y-1,u,-k), square(X,Y).
+push_from(X,Y,-k) :- push(X,Y,d,-k), not push(X,Y+1,d,-k), square(X,Y).
+push_from(X,Y,-k) :- push(X,Y,r,-k), not push(X-1,Y,r,-k), square(X,Y).
+push_from(X,Y,-k) :- push(X,Y,l,-k), not push(X+1,Y,l,-k), square(X,Y).
+
+box(X,Y,-k) :- push_from(X,Y,-k), square(X,Y).
+box(X,Y,-k) :- box(X,Y,-k+1), not push_to(X,Y,-k), square(X,Y).
+
+at(X,Y-1,-k) :- push_from(X,Y,-k), push_dir(u,-k), square(X,Y).
+at(X,Y+1,-k) :- push_from(X,Y,-k), push_dir(d,-k), square(X,Y).
+at(X-1,Y,-k) :- push_from(X,Y,-k), push_dir(r,-k), square(X,Y).
+at(X+1,Y,-k) :- push_from(X,Y,-k), push_dir(l,-k), square(X,Y).
+
+:- at(X,Y,-k), box(X,Y,-k+1), square(X,Y).
+
+route(X,Y,-k) :- at(X,Y,-k), square(X,Y).
+route(X,Y,-k) :- route(X+1,Y,-k), not box(X,Y,-k), square(X,Y).
+route(X,Y,-k) :- route(X-1,Y,-k), not box(X,Y,-k), square(X,Y).
+route(X,Y,-k) :- route(X,Y+1,-k), not box(X,Y,-k), square(X,Y).
+route(X,Y,-k) :- route(X,Y-1,-k), not box(X,Y,-k), square(X,Y).
+
+:- push_to(X,Y,-k), push_dir(u,-k), not route(X,Y-1,-k+1), square(X,Y), k > 1.
+:- push_to(X,Y,-k), push_dir(d,-k), not route(X,Y+1,-k+1), square(X,Y), k > 1.
+:- push_to(X,Y,-k), push_dir(r,-k), not route(X-1,Y,-k+1), square(X,Y), k > 1.
+:- push_to(X,Y,-k), push_dir(l,-k), not route(X+1,Y,-k+1), square(X,Y), k > 1.
+
+:- push_to(X,Y,-k), push_from(X,Y,-k+1), push_dir(D,-k), push_dir(D,-k+1), direction(D), square(X,Y), k > 1.
+
+#external volatile(k).
+
+:- initial_box(X,Y), not box(X,Y,-k), volatile(k).
+:- initial_at(X,Y), not route(X,Y,-k), volatile(k).
+
+#program base.
+
+initial_at(1,1).
+square(1, 1).
+square(2, 1).
+square(3, 1).
+target_square(3, 1).
+square(4, 1).
+square(1, 2).
+square(3, 2).
+initial_box(3, 2).
+target_square(3, 2).
+square(4, 2).
+square(5, 2).
+initial_box(5, 2).
+square(6, 2).
+square(7, 2).
+square(1, 3).
+square(2, 3).
+initial_box(2, 3).
+square(3, 3).
+target_square(3, 3).
+square(4, 3).
+initial_box(4, 3).
+square(5, 3).
+square(7, 3).
+square(3, 4).
+target_square(3, 4).
+square(5, 4).
+square(6, 4).
+square(7, 4).
+square(3, 5).
+square(4, 5).
+square(5, 5).
+
diff --git a/app/clingo/tests/lua/sokoban_back.sol b/app/clingo/tests/lua/sokoban_back.sol
new file mode 100644
index 0000000..beaaf50
--- /dev/null
+++ b/app/clingo/tests/lua/sokoban_back.sol
@@ -0,0 +1,16 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+Step: 11
+push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-6) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-1) push_from(4,3,-10) push_from(5,2,-11) push_from(5,2,-2) push_from(5,3,-3) push_from(6,2,-7) push_to(2,1,-6) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-2) push_to(3,2,-7) push_to(3,3,-1) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11)
+push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-6) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-10) push_from(4,3,-2) push_from(5,2,-1) push_from(5,2,-11) push_from(5,3,-3) push_from(6,2,-7) push_to(2,1,-6) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-1) push_to(3,2,-7) push_to(3,3,-2) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11)
+push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-7) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-1) push_from(4,3,-10) push_from(5,2,-11) push_from(5,2,-2) push_from(5,3,-3) push_from(6,2,-6) push_to(2,1,-7) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-2) push_to(3,2,-6) push_to(3,3,-1) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11)
+push_from(2,1,-4) push_from(2,3,-9) push_from(3,1,-7) push_from(3,2,-5) push_from(3,2,-8) push_from(4,3,-10) push_from(4,3,-2) push_from(5,2,-1) push_from(5,2,-11) push_from(5,3,-3) push_from(6,2,-6) push_to(2,1,-7) push_to(3,1,-4) push_to(3,1,-8) push_to(3,2,-1) push_to(3,2,-6) push_to(3,3,-2) push_to(3,4,-5) push_to(4,3,-9) push_to(5,2,-3) push_to(5,3,-10) push_to(6,2,-11)
+SAT
diff --git a/app/clingo/tests/lua/sokoban_para.lp b/app/clingo/tests/lua/sokoban_para.lp
new file mode 100644
index 0000000..f11911f
--- /dev/null
+++ b/app/clingo/tests/lua/sokoban_para.lp
@@ -0,0 +1,168 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    while true do
+        parts = {}
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+            prg:cleanup()
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#show push_box/4.
+#show push_to/4.
+#show at/3.
+
+#program base.
+
+% possible directions
+direction(u).
+direction(d).
+direction(r).
+direction(l).
+
+% possible moves
+dir(u,  0,  1).
+dir(d,  0, -1).
+dir(r,  1,  0).
+dir(l, -1,  0).
+
+% box positions at timestep 0
+box(X, Y, 0) :- initial_box(X, Y).
+
+% player at timestep 0
+at(X, Y, 0) :- initial_at(X, Y).
+
+#program cumulative(k).
+
+% reachable places at timestep k
+routePre(X, Y, k) :- at(X, Y, k - 1), square(X, Y).
+routePre(X, Y, k) :- dir(D, DX, DY), routePre(X + DX, Y + DY, k), not box(X, Y, k - 1), square(X, Y).
+
+routePost(X, Y, k) :- at(X, Y, k), square(X, Y).
+routePost(X, Y, k) :- dir(D, DX, DY), routePost(X + DX, Y + DY, k), not box(X, Y, k - 1), not box(X, Y, k), square(X, Y).
+
+% move the player (this could be restricted to moves behind boxes)
+1 { at(X, Y, k) : square(X, Y) } 1.
+ :- not routePre(X, Y, k), at(X, Y, k).
+ :- box(X, Y, k), at(X, Y, k).
+
+% select at least one box to push into exactly one direction (must be reachable and have a box to push)
+1 { push_box(X, Y, D, k) : square(X, Y), direction(D) }.
+ :- push_box(X, Y, D, k), not routePre(X - DX, Y - DY, k), dir(D, DX, DY).
+ :- push_box(X, Y, D, k), not routePost(X - DX, Y - DY, k), dir(D, DX, DY).
+ :- push_box(X, Y, D, k), not box(X, Y, k - 1).
+ :- push_box(X, Y, D1, k), push_box(X, Y, D2, k), D1 != D2.
+
+% push the box 1 or more fields into direction D (but at least one)
+push(X + DX, Y + DY, D, k) :- push_box(X, Y, D, k), dir(D, DX, DY).
+{ push(X + DX, Y + DY, D, k) } :- push(X, Y, D, k), square(X, Y), dir(D, DX, DY).
+ :- push(X, Y, D, k), not square(X, Y).
+ :- push(X, Y, D, k), box(X, Y, k - 1).
+
+% the last push is the final location
+push_to(X, Y, D, k) :- push(X, Y, D, k), not push(X + DX, Y + DY, D, k), dir(D, DX, DY).
+ :- push_to(X, Y, D1, k), push_to(X, Y, D2, k), D1 != D2.
+
+% put the pushed box at the new location
+box(X, Y, k) :- push_to(X, Y, D, k).
+% all other boxes stay where they are
+box(X, Y, k) :- box(X, Y, k - 1), square(X, Y), not push_box(X, Y, D, k) : direction(D).
+
+% assert redundant moves
+% :- push_box(X, Y, D, k - 1), push_from(X, Y, D, k).
+
+#external volatile(k).
+% the goal :)
+ :- target_square(X, Y), not box(X, Y, k), volatile(k).
+
+% restrict search space a little
+:- not at(1,1,k), k==0.
+:- not at(1,1,k), k==6.
+:- not at(1,1,k), k==8.
+:- not at(7,2,k), k==7.
+:- not at(1,3,k), k==1.
+:- not at(1,3,k), k==3.
+:- not at(2,3,k), k==5.
+:- not at(3,3,k), k==2.
+:- not at(5,4,k), k==9.
+:- not at(5,5,k), k==4.
+:- not push_box(3,2,u,k), k==7.
+:- not push_box(5,2,r,k), k==1.
+:- not push_box(4,3,r,k), k==2.
+:- not push_box(5,2,r,k), k==3.
+:- not push_box(2,3,r,k), k==3.
+:- not push_box(5,2,r,k), k==5.
+:- not push_box(2,1,r,k), k==8.
+:- not push_box(3,2,d,k), k==4.
+:- not push_box(5,3,d,k), k==9.
+:- not push_box(6,2,l,k), k==2.
+:- not push_box(6,2,l,k), k==4.
+:- not push_box(3,1,l,k), k==5.
+:- not push_box(6,2,l,k), k==6.
+:- not push_box(5,2,l,k), k==10.
+:- not push_box(4,3,l,k), k==10.
+:- not push_to(3,4,u,k), k==7.
+:- not push_to(6,2,r,k), k==1.
+:- not push_to(5,3,r,k), k==2.
+:- not push_to(6,2,r,k), k==3.
+:- not push_to(4,3,r,k), k==3.
+:- not push_to(6,2,r,k), k==5.
+:- not push_to(3,1,r,k), k==8.
+:- not push_to(3,1,d,k), k==4.
+:- not push_to(5,2,d,k), k==9.
+:- not push_to(5,2,l,k), k==2.
+:- not push_to(5,2,l,k), k==4.
+:- not push_to(2,1,l,k), k==5.
+:- not push_to(3,2,l,k), k==6.
+:- not push_to(3,2,l,k), k==10.
+:- not push_to(3,3,l,k), k==10.
+
+#program base.
+
+initial_at(1,1).
+square(1, 1).
+square(2, 1).
+square(3, 1).
+target_square(3, 1).
+square(4, 1).
+square(1, 2).
+square(3, 2).
+initial_box(3, 2).
+target_square(3, 2).
+square(4, 2).
+square(5, 2).
+initial_box(5, 2).
+square(6, 2).
+square(7, 2).
+square(1, 3).
+square(2, 3).
+initial_box(2, 3).
+square(3, 3).
+target_square(3, 3).
+square(4, 3).
+initial_box(4, 3).
+square(5, 3).
+square(7, 3).
+square(3, 4).
+target_square(3, 4).
+square(5, 4).
+square(6, 4).
+square(7, 4).
+square(3, 5).
+square(4, 5).
+square(5, 5).
diff --git a/app/clingo/tests/lua/sokoban_para.sol b/app/clingo/tests/lua/sokoban_para.sol
new file mode 100644
index 0000000..db32a45
--- /dev/null
+++ b/app/clingo/tests/lua/sokoban_para.sol
@@ -0,0 +1,21 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(3,5,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(4,5,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,3,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,10) at(5,4,9) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,10) at(5,5,4) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(6,2,10) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(6,4,10) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(7,2,10) at(7,2,7) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(7,2,7) at(7,3,10) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+at(1,1,0) at(1,1,6) at(1,1,8) at(1,3,1) at(1,3,3) at(2,3,5) at(3,3,2) at(5,4,9) at(5,5,4) at(7,2,7) at(7,4,10) push_box(2,1,r,8) push_box(2,3,r,3) push_box(3,1,l,5) push_box(3,2,d,4) push_box(3,2,u,7) push_box(4,3,l,10) push_box(4,3,r,2) push_box(5,2,l,10) push_box(5,2,r,1) push_box(5,2,r,3) push_box(5,2,r,5) push_box(5,3,d,9) push_box(6,2,l,2) push_box(6,2,l,4) push_box(6,2,l,6) push_to(2,1,l,5) push_to(3,1,d,4) push_to(3,1,r,8) push_to(3,2,l,10) push_to(3,2,l,6) push_to(3,3,l,10) push_to(3,4,u,7) push_to(4,3,r,3) push_to(5,2,d,9) push_to(5,2,l,2) push_to(5,2,l,4) push_to(5,3,r,2) push_to(6,2,r,1) push_to(6,2,r,3) push_to(6,2,r,5)
+SAT
diff --git a/app/clingo/tests/lua/solitaire_para.lp b/app/clingo/tests/lua/solitaire_para.lp
new file mode 100644
index 0000000..dcd8e1d
--- /dev/null
+++ b/app/clingo/tests/lua/solitaire_para.lp
@@ -0,0 +1,140 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    while true do
+        parts = {}
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable or step == 13 then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#show jump/4.
+#const n=31.
+
+#program base.
+
+%     -------
+%     |o|o|o|
+%     -------
+%     |o|o|o|
+% ---------------
+% |o|o|o|o|o|o|o|
+% ---------------
+% |o|o|o| |o|o|o|
+% ---------------
+% |o|o|o|o|o|o|o|
+% ---------------
+%     |o|o|o|
+%     -------
+%     |o|o|o|
+%     -------
+%
+%
+
+% the field
+field(0, 0).
+field(X, Y) :- stone(X, Y).
+
+% the 3x3 quads
+stone(-1 ..  1, -3 .. -1).
+stone(-3 .. -1, -1 ..  1).
+stone( 1 ..  3, -1 ..  1).
+stone(-1 ..  1,  1 ..  3).
+
+dir(west;east;north;south).
+
+dir(west , -1,  0).
+dir(east ,  1,  0).
+dir(north,  0, -1).
+dir(south,  0,  1).
+
+stone(X, Y, 0) :- stone(X, Y).
+
+% possible jumps
+field(X, Y, D) :- field(X, Y), field(X + 2 * DX, Y + 2 * DY), dir(D, DX, DY).
+
+#program cumulative(t).
+
+% fix the first jump to avoid symmetries
+jump(0,-2,south,t) :- t == 1.
+
+% choose one stone
+1 { jump(X, Y, D, t) : field(X, Y, D)  }.
+
+% fail if no stone at position
+ :- jump(X, Y, D, t), not stone(X, Y, t - 1).
+% fail if stone at target
+ :- jump(X, Y, D, t), stone(X + 2 * DX, Y + 2 * DY, t - 1), dir(D, DX, DY).
+% fail if no stone to jump over
+ :- jump(X, Y, D, t), not stone(X + DX, Y + DY, t - 1), dir(D, DX, DY).
+
+% a stone may not jump in two directions
+ :- jump(X, Y, D1, t), jump(X, Y, D2, t), D1 != D2.
+% fail if two stones jumped over the same location
+ :- jump(X1, Y1, D1, t), jump(X2, Y2, D2, t), dir(D1, DX1, DY1), dir(D2, DX2, DY2), X1 + DX1 == X2 + DX2, Y1 + DY1 == Y2 + DY2, D1 != D2.
+% fail if two stones jumped at the same target
+ :- jump(X1, Y1, D1, t), jump(X2, Y2, D2, t), dir(D1, DX1, DY1), dir(D2, DX2, DY2), X1 + 2 * DX1 == X2 + 2 * DX2, Y1 + 2 * DY1 == Y2 + 2 * DY2, D1 != D2.
+% a removed stone may not jump
+ :- jump(X, Y, D, t), removed(X, Y, t).
+
+% place the new stone
+stone(X + 2 * DX, Y + 2 * DY, t) :- jump(X, Y, D, t), dir(D, DX, DY).
+% mark the moved stone
+jumped(X, Y, t) :- jump(X, Y, D, t).
+% remove the stone
+removed(X + DX, Y + DY, t) :- jump(X, Y, D, t), dir(D, DX, DY).
+% keep other stones
+stone(X, Y, t) :- field(X, Y), stone(X, Y, t - 1), not jumped(X, Y, t), not removed(X, Y, t).
+
+% restrict search space a little
+:- not jump(0,-2,south,t), t==1.
+:- not jump(0,-1,east,t), t==4.
+:- not jump(-1,1,east,t), t==4.
+:- not jump(-2,-1,east,t), t==5.
+:- not jump(-1,-3,east,t), t==6.
+:- not jump(-3,0,east,t), t==7.
+:- not jump(-3,1,east,t), t==7.
+:- not jump(-3,-1,east,t), t==8.
+:- not jump(0,1,east,t), t==10.
+:- not jump(-1,2,east,t), t==11.
+:- not jump(1,-3,south,t), t==5.
+:- not jump(1,-3,south,t), t==7.
+:- not jump(-1,0,south,t), t==8.
+:- not jump(-1,-2,south,t), t==9.
+:- not jump(3,-1,south,t), t==9.
+:- not jump(0,-1,south,t), t==9.
+:- not jump(-1,0,south,t), t==10.
+:- not jump(2,-1,west,t), t==2.
+:- not jump(0,-1,west,t), t==7.
+:- not jump(2,-1,west,t), t==8.
+:- not jump(3,1,west,t), t==11.
+:- not jump(2,0,west,t), t==13.
+:- not jump(1,1,north,t), t==3.
+:- not jump(-1,3,north,t), t==5.
+:- not jump(1,2,north,t), t==5.
+:- not jump(1,0,north,t), t==6.
+:- not jump(-1,1,north,t), t==6.
+:- not jump(-1,3,north,t), t==9.
+:- not jump(1,2,north,t), t==12.
+
+#external volatile(t).
+
+% there shall be at least n free places
+ :- { not stone(X, Y, t) : field(X, Y) } n, volatile(t).
+% the last stone shall be in the center
+ :- not stone(0, 0, t), volatile(t).
+
diff --git a/app/clingo/tests/lua/solitaire_para.sol b/app/clingo/tests/lua/solitaire_para.sol
new file mode 100644
index 0000000..43105c6
--- /dev/null
+++ b/app/clingo/tests/lua/solitaire_para.sol
@@ -0,0 +1,23 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+Step: 11
+Step: 12
+Step: 13
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,6) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,6)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,6) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,7)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,6) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,8)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,7) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,6)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,7) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,7)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,7) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,8)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,8) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,6)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,8) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,7)
+jump(-1,-2,south,9) jump(-1,-3,east,6) jump(-1,0,south,10) jump(-1,0,south,8) jump(-1,1,east,4) jump(-1,1,north,6) jump(-1,2,east,11) jump(-1,3,north,5) jump(-1,3,north,9) jump(-2,-1,east,5) jump(-3,-1,east,8) jump(-3,0,east,7) jump(-3,1,east,7) jump(0,-1,east,4) jump(0,-1,south,9) jump(0,-1,west,7) jump(0,-2,south,1) jump(0,1,east,10) jump(1,-3,south,5) jump(1,-3,south,7) jump(1,0,north,6) jump(1,1,north,3) jump(1,2,north,12) jump(1,2,north,5) jump(1,3,west,8) jump(2,-1,west,2) jump(2,-1,west,8) jump(2,0,west,13) jump(3,-1,south,9) jump(3,1,west,11) jump(3,1,west,8)
+SAT
diff --git a/app/clingo/tests/lua/solitaire_sort.lp b/app/clingo/tests/lua/solitaire_sort.lp
new file mode 100644
index 0000000..dba8b2c
--- /dev/null
+++ b/app/clingo/tests/lua/solitaire_sort.lp
@@ -0,0 +1,193 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    while true do
+        parts = {}
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#const parallel=yes. % replace by anything else than "yes" to disable parallel jumps
+#const clear=32.     % (minimum) number of cleared grid cells in goal configuration
+
+#program base.
+
+% grid cells
+
+gc(f(c,1..2,3..5)). gc(f(c,3..5,1..7)). gc(f(c,6..7,3..5)).
+
+% initial configuration
+
+                            in(f(c,3,1)). in(f(c,4,1)). in(f(c,5,1)).
+                            in(f(c,3,2)). in(f(c,4,2)). in(f(c,5,2)).
+in(f(c,1,3)). in(f(c,2,3)). in(f(c,3,3)). in(f(c,4,3)). in(f(c,5,3)). in(f(c,6,3)). in(f(c,7,3)).
+in(f(c,1,4)). in(f(c,2,4)). in(f(c,3,4)).               in(f(c,5,4)). in(f(c,6,4)). in(f(c,7,4)).
+in(f(c,1,5)). in(f(c,2,5)). in(f(c,3,5)). in(f(c,4,5)). in(f(c,5,5)). in(f(c,6,5)). in(f(c,7,5)).
+                            in(f(c,3,6)). in(f(c,4,6)). in(f(c,5,6)).
+                            in(f(c,3,7)). in(f(c,4,7)). in(f(c,5,7)).
+
+% goal configurations(s)
+
+on(f(c,4,4)).
+un(clear).
+
+% generic predicates for sorting
+
+sort(I,J) :- sort(I), sort(J), I < J, #false : sort(K), I < K, K < J.
+prec(I,J) :- sort(I,J), not lead(J).
+succ(J)   :- prec(_,J).
+succ(I,J) :- prec(I,J), succ(I).
+
+% sort possible jumps
+
+dir(-1,0). dir(0,-1). dir(0,1). dir(1,0).
+
+sort(f(j,X-D,Y-E,X+D,Y+E)) :- gc(f(c,X,Y)), dir(D,E), gc(f(c,X-D,Y-E)), gc(f(c,X+D,Y+E)).
+lead(f(j,X,Y,XX,YY))       :- sort(f(j,X,Y,XX,YY)), not sort(f(j,V,W,VV,WW),f(j,X,Y,XX,YY))
+                                                      : sort(f(j,V,W,VV,WW),f(j,X,Y,XX,YY)).
+
+% sort jumps wrt target grid cells
+
+sort(f(i,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)).
+lead(f(i,X,Y,XX,YY)) :- sort(f(i,X,Y,XX,YY)), not sort(f(i,X,Y,VV,WW),f(i,X,Y,XX,YY))
+                                                : sort(f(i,X,Y,VV,WW),f(i,X,Y,XX,YY)).
+
+% sort jumps wrt cleared grid cells
+
+sort(f(k,XX,YY,X,Y,XX,YY))             :- sort(f(j,X,Y,XX,YY)).
+sort(f(k,(X+XX)/2,(Y+YY)/2,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)).
+lead(f(k,XXX,YYY,X,Y,XX,YY)) :- sort(f(k,XXX,YYY,X,Y,XX,YY)),
+                            not sort(f(k,XXX,YYY,V,W,VV,WW),f(k,XXX,YYY,X,Y,XX,YY))
+                              : sort(f(k,XXX,YYY,V,W,VV,WW),f(k,XXX,YYY,X,Y,XX,YY)).
+
+% sort jumps wrt smallest cleared or target grid cells (if parallel moves disabled)
+
+sort(f(l,0,XX,YY,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)), (XX,YY) < (X,Y), parallel != yes.
+sort(f(l,1,-X,-Y,X,Y,XX,YY)) :- sort(f(j,X,Y,XX,YY)), (X,Y) < (XX,YY), parallel != yes.
+lead(f(l,L,AA,BB,X,Y,XX,YY)) :- sort(f(l,L,AA,BB,X,Y,XX,YY)),
+                            not sort(f(l,M,CC,DD,V,W,VV,WW),f(l,L,AA,BB,X,Y,XX,YY))
+                              : sort(f(l,M,CC,DD,V,W,VV,WW),f(l,L,AA,BB,X,Y,XX,YY)).
+
+% calculate grid symmetries
+
+axis(x,M+N) :- M = #min { X : gc(f(c,X,_)) }, N = #max { X : gc(f(c,X,_)) }.
+axis(y,M+N) :- M = #min { Y : gc(f(c,_,Y)) }, N = #max { Y : gc(f(c,_,Y)) }.
+
+swap(0,f(c,X,Y),f(c,X,Y))      :- gc(f(c,X,Y)).
+swap(1,f(c,X,Y),f(c,N-X,Y))    :- gc(f(c,X,Y)), axis(x,N).
+swap(S+2,f(c,X,Y),f(c,XX,N-Y)) :- swap(S,f(c,X,Y),f(c,XX,Y)), axis(y,N), S < 2.
+swap(S+4,f(c,X,Y),f(c,YY,XX))  :- swap(S,f(c,X,Y),f(c,XX,YY)), S < 4.
+
+sort(f(s,S,XX,YY,X,Y)) :- swap(S,f(c,X,Y),f(c,XX,YY)), (X,Y) != (XX,YY).
+lead(f(s,S,XX,YY,X,Y)) :- sort(f(s,S,XX,YY,X,Y)), not sort(f(s,S,VV,WW,V,W),f(s,S,XX,YY,X,Y))
+                                                    : sort(f(s,S,VV,WW,V,W),f(s,S,XX,YY,X,Y)).
+
+asym(f(s,S,XX,YY,X,Y)) :- sort(f(s,S,XX,YY,X,Y)), not sort(f(s,S,X,Y,XX,YY)).
+
+less(f(s,S,XX,YY,X,Y)) :- sort(f(s,S,XX,YY,X,Y)), (XX,YY) < (X,Y).
+
+here(I)   :- less(I), lead(I).
+here(I,J) :- less(J), prec(I,J).
+
+more(I,J) :- prec(I,J), here(J,_).
+more(I,J) :- prec(I,J), more(J,_).
+more(I)   :- more(I,_), lead(I).
+
+% initial configuration
+
+hold(C,0) :- in(C).
+
+#program cumulative(t).
+
+% generate jumps
+
+poss(f(j,X,Y,XX,YY),t) :- sort(f(j,X,Y,XX,YY)), not hold(f(c,X,Y),t-1),
+                          hold(f(c,XXX,YYY),t-1) : sort(f(k,XXX,YYY,X,Y,XX,YY)).
+
+{ move(J,t) } :- poss(J,t).
+
+% propagate effects of jumps
+
+fill(J,t)                      :- move(J,t), succ(J).
+fill(f(i,X,Y,XX,YY),t)         :- move(f(j,X,Y,XX,YY),t), succ(f(i,X,Y,XX,YY)).
+fill(f(k,XXX,YYY,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), succ(f(k,XXX,YYY,X,Y,XX,YY)).
+fill(f(l,L,AA,BB,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), succ(f(l,L,AA,BB,X,Y,XX,YY)).
+fill(I,t)                      :- fill(J,t), succ(I,J).
+
+grep(I,t)                      :- fill(J,t), prec(I,J), lead(I).
+grep(J,t)                      :- move(J,t), lead(J).
+grep(f(i,X,Y,XX,YY),t)         :- move(f(j,X,Y,XX,YY),t), lead(f(i,X,Y,XX,YY)).
+grep(f(k,XXX,YYY,X,Y,XX,YY),t) :- move(f(j,X,Y,XX,YY),t), lead(f(k,XXX,YYY,X,Y,XX,YY)).
+
+% assert application of some jump
+
+ :- lead(f(j,X,Y,XX,YY)), not grep(f(j,X,Y,XX,YY),t).
+
+% forbid parallel jumps (if disabled)
+
+ :- prec(I,J), move(I,t), fill(J,t), parallel != yes.
+
+% forbid conflicting parallel jumps (if parallel jumps not disabled)
+
+ :- prec(f(i,X,Y,XX,YY),J), move(f(j,X,Y,XX,YY),t), fill(J,t), parallel == yes.
+ :- prec(f(k,XXX,YYY,X,Y,XX,YY),J), move(f(j,X,Y,XX,YY),t), fill(J,t), parallel == yes.
+
+% successor configuration
+
+hold(f(c,X,Y),t)     :- grep(f(i,X,Y,_,_),t).
+hold(f(c,XXX,YYY),t) :- hold(f(c,XXX,YYY),t-1), lead(f(k,XXX,YYY,X,Y,XX,YY)),
+                        not grep(f(k,XXX,YYY,X,Y,XX,YY),t).
+
+% assert order among independent jumps
+
+ :- move(I,t), poss(I,t-1), parallel == yes.
+ :- move(f(j,X,Y,XX,YY),t), poss(f(j,X,Y,XX,YY),t-1), parallel != yes,
+    fill(f(l,L,AA,BB,X,Y,XX,YY),t-1) : succ(f(l,L,AA,BB,X,Y,XX,YY)).
+
+% assert lexicographically smallest successor configuration wrt symmetric configurations
+
+diff(S,t) :- sort(f(s,S,XX,YY,X,Y)), hold(f(c,X,Y),t-1), not hold(f(c,XX,YY),t-1).
+ :- asym(f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t-1), not hold(f(c,X,Y),t-1), not diff(S,t).
+
+comp(S,f(s,S,XX,YY,X,Y),t) :- more(f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t).
+comp(S,f(s,S,XX,YY,X,Y),t) :- more(f(s,S,XX,YY,X,Y)), not hold(f(c,X,Y),t).
+comp(S,f(s,S,XX,YY,X,Y),t) :- more(I,f(s,S,XX,YY,X,Y)), comp(S,I,t), hold(f(c,XX,YY),t).
+comp(S,f(s,S,XX,YY,X,Y),t) :- more(I,f(s,S,XX,YY,X,Y)), comp(S,I,t), not hold(f(c,X,Y),t).
+
+ :- here(f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t), not hold(f(c,X,Y),t), not diff(S,t).
+ :- here(I,f(s,S,XX,YY,X,Y)), hold(f(c,XX,YY),t), not hold(f(c,X,Y),t), not diff(S,t),
+    comp(S,I,t).
+
+% limit search space ...
+
+:- not move(f(j,4,4,2,4),t), t == 1.
+:- not move(f(j,5,3,5,1),t), t == 5.
+:- not move(f(j,5,1,3,1),t), t == 6.
+:- not move(f(j,5,2,5,4),t), t == 6.
+:- not move(f(j,5,5,7,5),t), t == 6.
+:- not move(f(j,6,5,4,5),t), t == 7.
+:- not move(f(j,5,3,5,1),t), t == 7.
+:- not move(f(j,4,4,4,6),t), t == 13.
+
+#external volatile(t).
+% assert goal configuration(s)
+
+ :- on(C), not hold(C,t), volatile(t).
+ :- un(N), not N { not hold(C,t) : gc(C) }, volatile(t).
+
+#show move/2.
diff --git a/app/clingo/tests/lua/solitaire_sort.sol b/app/clingo/tests/lua/solitaire_sort.sol
new file mode 100644
index 0000000..64c4278
--- /dev/null
+++ b/app/clingo/tests/lua/solitaire_sort.sol
@@ -0,0 +1,20 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+Step: 11
+Step: 12
+Step: 13
+move(f(j,1,3,1,5),4) move(f(j,2,3,4,3),4) move(f(j,2,5,4,5),10) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,1,3),5) move(f(j,3,3,5,3),10) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),9) move(f(j,3,5,3,3),11) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,3,4,5),5) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,2,5),6) move(f(j,4,5,6,5),9) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,3,7,3),9) move(f(j,5,4,5,6),5) move(f(j,5,4,7,4),7) move(f(j,5,5,5,3),8) move(f(j,5,5,7,5),6) move(f(j,6,5,4,5),7)
+move(f(j,1,3,1,5),4) move(f(j,2,3,4,3),4) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,1,3),5) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),8) move(f(j,3,5,3,7),10) move(f(j,3,5,3,7),8) move(f(j,3,6,3,4),7) move(f(j,3,6,3,4),9) move(f(j,3,7,5,7),9) move(f(j,4,3,6,3),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,4,6,4),10) move(f(j,4,5,2,5),12) move(f(j,4,5,4,3),9) move(f(j,4,6,4,4),11) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,4,5,6),5) move(f(j,5,4,5,6),9) move(f(j,5,5,7,5),6) move(f(j,5,5,7,5),8) move(f(j,5,6,3,6),6) move(f(j,6,5,4,5),7) move(f(j,7,5,7,3),7)
+move(f(j,1,3,1,5),6) move(f(j,2,3,4,3),6) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),5) move(f(j,3,3,1,3),7) move(f(j,3,3,3,5),3) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),4) move(f(j,3,5,3,7),4) move(f(j,3,5,3,7),6) move(f(j,3,6,3,4),5) move(f(j,3,7,5,7),5) move(f(j,4,3,6,3),11) move(f(j,4,3,6,3),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),8) move(f(j,4,5,4,3),12) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,3,3),9) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,4,5,6),5) move(f(j,5,5,7,5),6) move(f(j,5,5,7,5),8) move(f(j,6,3,6,5),10) move(f(j,6,5,4,5),7) move(f(j,6,5,4,5),9) move(f(j,7,5,7,3),7)
+move(f(j,1,3,1,5),7) move(f(j,2,3,4,3),10) move(f(j,2,3,4,3),7) move(f(j,2,4,4,4),4) move(f(j,2,5,2,3),11) move(f(j,3,3,1,3),6) move(f(j,3,3,1,3),8) move(f(j,3,4,3,2),5) move(f(j,3,4,5,4),2) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,3,6,3),4) move(f(j,4,3,6,3),9) move(f(j,4,4,2,4),1) move(f(j,4,4,4,2),3) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,2,5),6) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,4,5,6),3) move(f(j,5,5,7,5),4) move(f(j,5,5,7,5),6) move(f(j,6,3,6,5),8) move(f(j,6,5,4,5),5) move(f(j,6,5,4,5),7) move(f(j,7,5,7,3),5)
+move(f(j,2,4,4,4),3) move(f(j,2,5,4,5),10) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,5,3),10) move(f(j,3,4,1,4),7) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),9) move(f(j,3,4,3,6),4) move(f(j,3,5,1,5),5) move(f(j,3,5,3,3),11) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),6) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,6,5),9) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,3,7,3),9) move(f(j,5,4,5,6),5) move(f(j,5,4,7,4),7) move(f(j,5,5,5,3),8) move(f(j,5,5,7,5),6) move(f(j,6,5,4,5),7)
+move(f(j,2,4,4,4),3) move(f(j,2,5,4,5),10) move(f(j,3,2,5,2),3) move(f(j,3,3,1,3),3) move(f(j,3,3,5,3),10) move(f(j,3,4,1,4),9) move(f(j,3,4,3,2),2) move(f(j,3,4,3,2),7) move(f(j,3,4,3,6),4) move(f(j,3,5,1,5),5) move(f(j,3,5,3,3),11) move(f(j,3,5,3,7),7) move(f(j,3,5,3,7),9) move(f(j,3,6,3,4),6) move(f(j,3,6,3,4),8) move(f(j,3,7,5,7),8) move(f(j,4,4,2,4),1) move(f(j,4,4,4,6),13) move(f(j,4,5,2,5),12) move(f(j,4,5,6,5),9) move(f(j,5,1,3,1),6) move(f(j,5,2,5,4),4) move(f(j,5,2,5,4),6) move(f(j,5,3,5,1),5) move(f(j,5,3,5,1),7) move(f(j,5,3,7,3),9) move(f(j,5,4,5,6),5) move(f(j,5,4,7,4),7) move(f(j,5,5,5,3),8) move(f(j,5,5,7,5),6) move(f(j,6,5,4,5),7)
+SAT
diff --git a/app/clingo/tests/lua/test.lp b/app/clingo/tests/lua/test.lp
new file mode 100644
index 0000000..f296712
--- /dev/null
+++ b/app/clingo/tests/lua/test.lp
@@ -0,0 +1,61 @@
+#script (lua)
+
+function map(func, array)
+  for i,v in ipairs(array) do
+    array[i] = func(v)
+  end
+  return array
+end
+
+function sorted(t)
+    table.sort(t)
+    return t
+end
+
+function on_model(x)
+    print("Answer: 42")
+    print(
+           "hasA(" ..        tostring(x:contains(clingo.Function("a"))) .. ") "
+        .. "hasVolatile(" .. tostring(x:contains(clingo.Function("volatile", {9}))) .. ") "
+        .. "model(" ..       table.concat(sorted(map(tostring, x:symbols{shown=true})), ",") .. ") ")
+    io.flush()
+end
+
+function main (prg)
+    n = prg:get_const("n").number
+    parts = {}
+    parts[#parts+1] = {"base", {}}
+    prg:ground(parts)
+    prg:solve()
+    parts = {}
+    prg:add("test", {"x"}, "test(x).")
+    parts[#parts+1] = {"test", {clingo.Function("f", {1,2})}}
+    for i=1,n do
+        parts[#parts+1] = {"cumulative", {i}}
+        prg:ground(parts)
+        parts = {}
+        ret = prg:solve(on_model)
+        print("Answer: 42")
+        print(tostring(ret))
+        io.flush()
+    end
+end
+
+#end.
+
+#const n = 10.
+
+#program base.
+
+a.
+
+#program cumulative(k).
+
+1 { c(k) } 1.
+q(k) :- c(k).
+r(k,X) :- test(X).
+
+#external volatile(k).
+ :- not c(5), not volatile(k).
+volatile(k-1).
+
diff --git a/app/clingo/tests/lua/test.sol b/app/clingo/tests/lua/test.sol
new file mode 100644
index 0000000..0baaec7
--- /dev/null
+++ b/app/clingo/tests/lua/test.sol
@@ -0,0 +1,35 @@
+Step: 1
+a
+Step: 2
+UNSAT
+Step: 3
+UNSAT
+Step: 4
+UNSAT
+Step: 5
+UNSAT
+Step: 6
+SAT
+a c(1) c(2) c(3) c(4) c(5) q(1) q(2) q(3) q(4) q(5) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),q(1),q(2),q(3),q(4),q(5),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4))
+Step: 7
+SAT
+a c(1) c(2) c(3) c(4) c(5) c(6) q(1) q(2) q(3) q(4) q(5) q(6) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),q(1),q(2),q(3),q(4),q(5),q(6),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5))
+Step: 8
+SAT
+a c(1) c(2) c(3) c(4) c(5) c(6) c(7) q(1) q(2) q(3) q(4) q(5) q(6) q(7) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),q(1),q(2),q(3),q(4),q(5),q(6),q(7),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6))
+Step: 9
+SAT
+a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7))
+Step: 10
+SAT
+a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8))
+Step: 11
+SAT
+a c(1) c(10) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(10) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(10,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8) volatile(9)
+hasA(true) hasVolatile(true) model(a,c(1),c(10),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(10),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(10,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8),volatile(9))
+SAT
diff --git a/app/clingo/tests/lua/theory-term-types.lp b/app/clingo/tests/lua/theory-term-types.lp
new file mode 100644
index 0000000..9aec8c8
--- /dev/null
+++ b/app/clingo/tests/lua/theory-term-types.lp
@@ -0,0 +1,17 @@
+#script (lua)
+clingo = require("clingo")
+
+function types() 
+    return {
+        tostring(clingo.TheoryTermType.Tuple),
+        tostring(clingo.TheoryTermType.List),
+        tostring(clingo.TheoryTermType.Set),
+        tostring(clingo.TheoryTermType.Function),
+        tostring(clingo.TheoryTermType.Symbol),
+        tostring(clingo.TheoryTermType.Number),
+    }
+end
+#end.
+
+p(@types()).
+
diff --git a/app/clingo/tests/lua/theory-term-types.sol b/app/clingo/tests/lua/theory-term-types.sol
new file mode 100644
index 0000000..0f83c3e
--- /dev/null
+++ b/app/clingo/tests/lua/theory-term-types.sol
@@ -0,0 +1,3 @@
+Step: 1
+p("Function") p("List") p("Number") p("Set") p("Symbol") p("Tuple")
+SAT
diff --git a/app/clingo/tests/lua/theory.lp b/app/clingo/tests/lua/theory.lp
new file mode 100644
index 0000000..f3e9077
--- /dev/null
+++ b/app/clingo/tests/lua/theory.lp
@@ -0,0 +1,72 @@
+#script (lua)
+clingo = require("clingo")
+
+t = {}
+
+function get() 
+    return t
+end
+
+function convert_term(t)
+    if t.type == clingo.TheoryTermType.Function then
+        a = {}
+        for i, x in ipairs(t.arguments) do
+            a[#a+1] = convert_term(x)
+        end
+        return clingo.Tuple({t.name, clingo.Tuple(a)})
+    elseif t.type == clingo.TheoryTermType.Number then
+        return t.number
+    elseif t.type == clingo.TheoryTermType.Symbol then
+        return t.name
+    else
+        return clingo.Function("unimplemented")
+    end
+
+end
+
+function main(c)
+    c:ground({{"base",{}}})
+    for x in c.theory_atoms do
+        r = {}
+        r[#r+1] = convert_term(x.term)
+        e = {}
+        for i,y in ipairs(x.elements) do
+            cond = {}
+            for i, z in ipairs(y.condition) do
+                cond[#cond+1] = "n/a"
+            end
+            Tuple = {}
+            for i, z in ipairs(y.terms) do
+                Tuple[#Tuple+1] = convert_term(z)
+            end
+            e[#e+1] = clingo.Tuple({clingo.Tuple(Tuple), clingo.Tuple(cond)})
+        end
+        r[#r+1] = clingo.Tuple(e)
+        if x.guard ~= nil then
+            r[#r+1] = clingo.Tuple({x.guard[1], convert_term(x.guard[2])})
+        end
+        t[#t+1] = clingo.Tuple(r)
+    end
+    c:ground({{"theory",{}}})
+    c:solve()
+end
+
+#end.
+
+#theory t {
+  t { 
+    + : 1, binary, left;
+    - : 1, binary, left
+  };
+  &a/0: t, any;
+  &b/0: t, {=}, t, any
+}.
+
+2 { p; q } 2.
+
+&a{ a+b : p,q; 1,c-d}.
+&a{ 1,c-d}.
+&b{ } = a+b.
+
+#program theory.
+p(@get()).
diff --git a/app/clingo/tests/lua/theory.sol b/app/clingo/tests/lua/theory.sol
new file mode 100644
index 0000000..c25cf1a
--- /dev/null
+++ b/app/clingo/tests/lua/theory.sol
@@ -0,0 +1,3 @@
+Step: 1
+p p(("a",(((("+",("a","b")),),("n/a","n/a")),((1,("-",("c","d"))),())))) p(("a",(((1,("-",("c","d"))),()),))) p(("b",(),("=",("+",("a","b"))))) q
+SAT
diff --git a/app/clingo/tests/lua/toh.lp b/app/clingo/tests/lua/toh.lp
new file mode 100644
index 0000000..ea4ee00
--- /dev/null
+++ b/app/clingo/tests/lua/toh.lp
@@ -0,0 +1,105 @@
+#script (lua)
+
+function main(prg)
+    step = 1
+    while true do
+        parts = {}
+        if step > 1 then
+            prg:release_external(clingo.Function("volatile", {step-1}))
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"cumulative", {step}}
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("volatile", {step}), true)
+        ret = prg:solve()
+        if ret.satisfiable then
+            break
+        end
+        step = step + 1
+    end
+end
+
+#end.
+
+#show put/3.
+
+#program cumulative(k).
+
+1{move(N,k)  : disk(N), N > 3}1.
+1{where(N,k) : disk(N)}1.
+
+on(M,N,k) :- disk(M;N), move(M,k), where(N,k).
+on(M,N,k) :- disk(M;N), on(M,N,k-1), not move(M,k).
+
+:- disk(N), move(N,k-1), move(N,k).
+:- disk(M;N), on(M,N,k-1), move(N,k).
+:- disk(M;N), on(M,N,k-1), where(N,k).
+:- disk(M;N), on(M,N,k), M <= N.
+
+put(M,N,k) :- disk(M;N), move(M,k), where(N,k).
+
+#external volatile(k).
+
+:- goal_on(X,Y), not on(X,Y,k), volatile(k).
+
+% restrict search space a little
+%:- not put(9,8,k), k==1.
+%:- not put(4,3,k), k==2.
+%:- not put(9,4,k), k==3.
+%:- not put(8,1,k), k==4.
+:- not put(9,8,k), k==5.
+%:- not put(7,4,k), k==6.
+%:- not put(9,6,k), k==7.
+%:- not put(8,7,k), k==8.
+%:- not put(9,8,k), k==9.
+%:- not put(6,1,k), k==10.
+%:- not put(9,6,k), k==11.
+%:- not put(8,5,k), k==12.
+%:- not put(9,8,k), k==13.
+%:- not put(7,6,k), k==14.
+%:- not put(9,4,k), k==15.
+:- not put(8,7,k), k==16.
+%:- not put(9,8,k), k==17.
+%:- not put(5,4,k), k==18.
+%:- not put(9,2,k), k==19.
+%:- not put(8,5,k), k==20.
+:- not put(9,8,k), k==21.
+%:- not put(7,2,k), k==22.
+%:- not put(9,6,k), k==23.
+%:- not put(8,7,k), k==24.
+%:- not put(9,8,k), k==25.
+:- not put(6,5,k), k==26.
+%:- not put(9,6,k), k==27.
+%:- not put(8,1,k), k==28.
+%:- not put(9,8,k), k==29.
+:- not put(7,6,k), k==30.
+%:- not put(9,2,k), k==31.
+%:- not put(8,7,k), k==32.
+%:- not put(9,8,k), k==33.
+#program base.
+
+on(X,Y,0) :- init_on(X,Y).
+disk(1).
+disk(2).
+disk(3).
+disk(4).
+disk(5).
+disk(6).
+disk(7).
+disk(8).
+disk(9).
+
+init_on(9,4).
+init_on(4,1).
+init_on(8,7).
+init_on(7,6).
+init_on(6,5).
+init_on(5,2).
+
+goal_on(4,3).
+goal_on(5,4).
+goal_on(6,5).
+goal_on(7,6).
+goal_on(8,7).
+goal_on(9,8).
diff --git a/app/clingo/tests/lua/toh.sol b/app/clingo/tests/lua/toh.sol
new file mode 100644
index 0000000..d73a751
--- /dev/null
+++ b/app/clingo/tests/lua/toh.sol
@@ -0,0 +1,35 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+Step: 10
+Step: 11
+Step: 12
+Step: 13
+Step: 14
+Step: 15
+Step: 16
+Step: 17
+Step: 18
+Step: 19
+Step: 20
+Step: 21
+Step: 22
+Step: 23
+Step: 24
+Step: 25
+Step: 26
+Step: 27
+Step: 28
+Step: 29
+Step: 30
+Step: 31
+Step: 32
+Step: 33
+put(4,3,2) put(5,4,18) put(6,1,10) put(6,5,26) put(7,2,22) put(7,4,6) put(7,6,14) put(7,6,30) put(8,1,28) put(8,1,4) put(8,5,12) put(8,5,20) put(8,7,16) put(8,7,24) put(8,7,32) put(8,7,8) put(9,2,19) put(9,2,31) put(9,4,15) put(9,4,3) put(9,6,11) put(9,6,23) put(9,6,27) put(9,6,7) put(9,8,1) put(9,8,13) put(9,8,17) put(9,8,21) put(9,8,25) put(9,8,29) put(9,8,33) put(9,8,5) put(9,8,9)
+SAT
diff --git a/app/clingo/tests/lua/unsat-sync.lp b/app/clingo/tests/lua/unsat-sync.lp
new file mode 100644
index 0000000..45677d1
--- /dev/null
+++ b/app/clingo/tests/lua/unsat-sync.lp
@@ -0,0 +1,11 @@
+:-.
+
+#script (lua)
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:solve()
+    prg:solve()
+end
+
+#end.
diff --git a/app/clingo/tests/lua/unsat-sync.sol b/app/clingo/tests/lua/unsat-sync.sol
new file mode 100644
index 0000000..e1431af
--- /dev/null
+++ b/app/clingo/tests/lua/unsat-sync.sol
@@ -0,0 +1,3 @@
+Step: 1
+Step: 2
+UNSAT
diff --git a/app/clingo/tests/python/assumptions1.lp b/app/clingo/tests/python/assumptions1.lp
new file mode 100644
index 0000000..b3c30f4
--- /dev/null
+++ b/app/clingo/tests/python/assumptions1.lp
@@ -0,0 +1,13 @@
+#script (python)
+
+import sys
+from clingo import Function
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve(assumptions=[(Function("a"), True)])
+
+#end.
+
+{ a }.
+b :- a.
diff --git a/app/clingo/tests/python/assumptions1.sol b/app/clingo/tests/python/assumptions1.sol
new file mode 100644
index 0000000..97448c9
--- /dev/null
+++ b/app/clingo/tests/python/assumptions1.sol
@@ -0,0 +1,3 @@
+Step: 1
+a b
+SAT
diff --git a/app/clingo/tests/python/assumptions2.lp b/app/clingo/tests/python/assumptions2.lp
new file mode 100644
index 0000000..c8e8673
--- /dev/null
+++ b/app/clingo/tests/python/assumptions2.lp
@@ -0,0 +1,13 @@
+#script (python)
+
+import sys
+from clingo import Function
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve(assumptions=[(Function("b"), True)])
+
+#end.
+
+{ a }.
+b :- a.
diff --git a/app/clingo/tests/python/assumptions2.sol b/app/clingo/tests/python/assumptions2.sol
new file mode 100644
index 0000000..97448c9
--- /dev/null
+++ b/app/clingo/tests/python/assumptions2.sol
@@ -0,0 +1,3 @@
+Step: 1
+a b
+SAT
diff --git a/app/clingo/tests/python/assumptions3.lp b/app/clingo/tests/python/assumptions3.lp
new file mode 100644
index 0000000..9f8668e
--- /dev/null
+++ b/app/clingo/tests/python/assumptions3.lp
@@ -0,0 +1,14 @@
+#script (python)
+
+import sys
+from clingo import Function
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve(assumptions=[(Function("a"), True), (Function("b"), False), (Function("d"), True)])
+    prg.solve(assumptions=[(Function("a"), False), (Function("c"), True)])
+
+#end.  
+
+#external d.
+{ a; b; c }.
diff --git a/app/clingo/tests/python/assumptions3.sol b/app/clingo/tests/python/assumptions3.sol
new file mode 100644
index 0000000..589474a
--- /dev/null
+++ b/app/clingo/tests/python/assumptions3.sol
@@ -0,0 +1,5 @@
+Step: 1
+Step: 2
+b c
+c
+SAT
diff --git a/app/clingo/tests/python/assumptions4.lp b/app/clingo/tests/python/assumptions4.lp
new file mode 100644
index 0000000..f0d036c
--- /dev/null
+++ b/app/clingo/tests/python/assumptions4.lp
@@ -0,0 +1,19 @@
+#script (python)
+
+import sys
+from clingo import Function
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve(assumptions=[(Function("a"), True)])
+
+    f = prg.solve_async(assumptions=[(Function("a"), True)])
+    f.wait()
+
+    with prg.solve_iter(assumptions=[(Function("a"), True)]) as it:
+        for model in it: pass
+
+#end.
+
+{ a }.
+b :- a.
diff --git a/app/clingo/tests/python/assumptions4.sol b/app/clingo/tests/python/assumptions4.sol
new file mode 100644
index 0000000..9e8af8d
--- /dev/null
+++ b/app/clingo/tests/python/assumptions4.sol
@@ -0,0 +1,7 @@
+Step: 1
+a b
+Step: 2
+a b
+Step: 3
+a b
+SAT
diff --git a/app/clingo/tests/python/ast.lp b/app/clingo/tests/python/ast.lp
new file mode 100644
index 0000000..674b3c2
--- /dev/null
+++ b/app/clingo/tests/python/ast.lp
@@ -0,0 +1,121 @@
+#script (python)
+
+import clingo
+import clingo.ast as ast
+
+def get_type(x):
+    return x.atom.type if x.type == ast.ASTType.Literal else x.type
+
+def add(r):
+    return [(n, clingo.Function("ok" if str(x) == s and get_type(x) == t else "fail")) for n, (x, s, t) in zip(range(len(r)), r)]
+
+def test():
+    loc = None
+    id_i = ast.Id(loc, "i")
+    trm_v = ast.Variable(loc, "X")
+    trm_s = ast.Symbol(loc, 2)
+    trm_u = ast.UnaryOperation(loc, ast.UnaryOperator.Absolute, trm_v)
+    trm_b = ast.BinaryOperation(loc, ast.BinaryOperator.Multiplication, trm_u, trm_s)
+    trm_f = ast.Function(loc, "f", [trm_v,trm_s,trm_u,trm_b], True)
+    trm_p = ast.Pool(loc, [trm_s,trm_v])
+    csp_p = ast.CSPProduct(loc, trm_s, trm_v)
+    csp_s = ast.CSPSum(loc, [csp_p, csp_p])
+    csp_g = ast.CSPGuard(ast.ComparisonOperator.Equal, csp_s)
+    lit_b = ast.BooleanConstant(True);
+    lit_s = ast.Literal(loc, ast.Sign.Negation, ast.SymbolicAtom(ast.Function(loc, "p", [trm_s], False)));
+    lit_r = ast.Comparison(ast.ComparisonOperator.LessThan, trm_v, trm_s)
+    lit_c = ast.CSPLiteral(loc, csp_s, [csp_g])
+    lit_l = ast.ConditionalLiteral(loc, lit_s, [lit_b])
+    agg_g = ast.AggregateGuard(ast.ComparisonOperator.NotEqual, trm_s)
+    agg_l = ast.Literal(loc, ast.Sign.Negation, ast.Aggregate(loc, None, [lit_l], agg_g))
+    agg_e = ast.BodyAggregateElement([trm_s, trm_v], [lit_b])
+    agg_t = ast.Literal(loc, ast.Sign.DoubleNegation, ast.BodyAggregate(loc, agg_g, ast.AggregateFunction.Sum, [agg_e], None))
+    agg_m = ast.Aggregate(loc, agg_g, [lit_l], agg_g)
+    agg_f = ast.HeadAggregateElement([trm_s, trm_v], lit_l)
+    agg_u = ast.HeadAggregate(loc, agg_g, ast.AggregateFunction.Sum, [agg_f], None)
+    agg_d = ast.Disjunction(loc, [lit_l, lit_l])
+    agg_h = ast.DisjointElement(loc, [trm_v, trm_s], csp_s, [lit_b, lit_s])
+    agg_i = ast.Literal(loc, ast.Sign.DoubleNegation, ast.Disjoint(loc, [agg_h]))
+    tha_s = ast.TheorySequence(loc, ast.TheorySequenceType.Set, [trm_v, trm_s])
+    tha_f = ast.TheoryFunction(loc, "f", [tha_s, trm_s])
+    tha_e = ast.TheoryUnparsedTermElement(["+", "-"], trm_s)
+    tha_u = ast.TheoryUnparsedTerm(loc, [tha_e, tha_e])
+    tha_g = ast.TheoryGuard("!!", trm_s)
+    tha_h = ast.TheoryAtomElement([trm_v, trm_s], [lit_b])
+    tha_a = ast.TheoryAtom(loc, trm_v, [tha_h], tha_g)
+    thd_o = ast.TheoryOperatorDefinition(loc, "-", 7, ast.TheoryOperatorType.Unary)
+    thd_t = ast.TheoryTermDefinition(loc, "t", [thd_o])
+    thd_g = ast.TheoryGuardDefinition([">", "<"], "t")
+    thd_a = ast.TheoryAtomDefinition(loc, ast.TheoryAtomType.Any, "p", 2, "t", thd_g)
+    thd_d = ast.TheoryDefinition(loc, "x", [thd_t], [thd_a])
+    stm_r = ast.Rule(loc, lit_s, [lit_s])
+    stm_c = ast.Definition(loc, "x", trm_s, True)
+    stm_s = ast.ShowSignature(loc, "x", 2, True, True)
+    stm_t = ast.ShowTerm(loc, trm_s, [lit_s], True)
+    stm_m = ast.Minimize(loc, trm_s, trm_s, [trm_v], [lit_s])
+    stm_p = ast.Script(loc, ast.ScriptType.Python, "blub!")
+    stm_q = ast.Program(loc, "p", [id_i])
+    stm_e = ast.External(loc, trm_s, [lit_s])
+    stm_a = ast.Edge(loc, trm_s, trm_s, [lit_s])
+    stm_h = ast.Heuristic(loc, trm_s, [lit_s], trm_s, trm_s, trm_s)
+    stm_x = ast.ProjectAtom(loc, trm_s, [lit_s])
+    stm_y = ast.ProjectSignature(loc, "p", 2, True)
+    return add([
+        (id_i, "i", ast.ASTType.Id),
+        (trm_v, "X", ast.ASTType.Variable),
+        (trm_s, "2", ast.ASTType.Symbol),
+        (trm_u, "|X|", ast.ASTType.UnaryOperation),
+        (trm_b, "(|X|*2)", ast.ASTType.BinaryOperation),
+        (trm_f, "@f(X,2,|X|,(|X|*2))", ast.ASTType.Function),
+        (trm_p, "(2;X)", ast.ASTType.Pool),
+        (csp_p, "2$*$X", ast.ASTType.CSPProduct),
+        (csp_s, "2$*$X$+2$*$X", ast.ASTType.CSPSum),
+        (csp_g, "$=2$*$X$+2$*$X", ast.ASTType.CSPGuard),
+        (lit_b, "#true", ast.ASTType.BooleanConstant),
+        (lit_s, "not p(2)", ast.ASTType.SymbolicAtom),
+        (lit_r, "X<2", ast.ASTType.Comparison),
+        (lit_c, "2$*$X$+2$*$X$=2$*$X$+2$*$X", ast.ASTType.CSPLiteral),
+        (lit_l, "not p(2) : #true", ast.ASTType.ConditionalLiteral),
+        (agg_g, "AggregateGuard(!=, 2)", ast.ASTType.AggregateGuard),
+        (agg_l, "not { not p(2) : #true } != 2", ast.ASTType.Aggregate),
+        (agg_e, "2,X : #true", ast.ASTType.BodyAggregateElement),
+        (agg_t, "not not 2 != #sum { 2,X : #true }", ast.ASTType.BodyAggregate),
+        (agg_m, "2 != { not p(2) : #true } != 2", ast.ASTType.Aggregate),
+        (agg_f, "2,X : not p(2) : #true", ast.ASTType.HeadAggregateElement),
+        (agg_u, "2 != #sum { 2,X : not p(2) : #true }", ast.ASTType.HeadAggregate),
+        (agg_d, "not p(2) : #true; not p(2) : #true", ast.ASTType.Disjunction),
+        (agg_h, "X,2 : 2$*$X$+2$*$X : #true,not p(2)", ast.ASTType.DisjointElement),
+        (agg_i, "not not #disjoint { X,2 : 2$*$X$+2$*$X : #true,not p(2) }", ast.ASTType.Disjoint),
+        (tha_s, "{X,2}", ast.ASTType.TheorySequence),
+        (tha_f, "f({X,2},2)", ast.ASTType.TheoryFunction),
+        (tha_e, "+ - 2", ast.ASTType.TheoryUnparsedTermElement),
+        (tha_u, "(+ - 2 + - 2)", ast.ASTType.TheoryUnparsedTerm),
+        (tha_g, "!! 2", ast.ASTType.TheoryGuard),
+        (tha_h, "X,2 : #true", ast.ASTType.TheoryAtomElement),
+        (tha_a, "&X { X,2 : #true } !! 2", ast.ASTType.TheoryAtom),
+        (thd_o, "- : 7, unary", ast.ASTType.TheoryOperatorDefinition),
+        (thd_t, "t {\n  - : 7, unary\n}", ast.ASTType.TheoryTermDefinition),
+        (thd_g, "{ >, < }, t", ast.ASTType.TheoryGuardDefinition),
+        (thd_a, "&p/2 : t, { >, < }, t, any", ast.ASTType.TheoryAtomDefinition),
+        (thd_d, "#theory x {\n  t {\n    - : 7, unary\n  };\n  &p/2 : t, { >, < }, t, any\n}.", ast.ASTType.TheoryDefinition),
+        (stm_r, "not p(2) :- not p(2).", ast.ASTType.Rule),
+        (stm_c, "#const x = 2. [default]", ast.ASTType.Definition),
+        (stm_s, "#show $x/2.", ast.ASTType.ShowSignature),
+        (stm_t, "#show $2 : not p(2).", ast.ASTType.ShowTerm),
+        (stm_m, ":~ not p(2). [2@2,X]", ast.ASTType.Minimize),
+        (stm_p, "blub!", ast.ASTType.Script),
+        (stm_q, "#program p(i).", ast.ASTType.Program),
+        (stm_e, "#external 2 : not p(2).", ast.ASTType.External),
+        (stm_a, "#edge (2,2) : not p(2).", ast.ASTType.Edge),
+        (stm_h, "#heuristic 2 : not p(2). [2@2,2]", ast.ASTType.Heuristic),
+        (stm_x, "#project 2 : not p(2).", ast.ASTType.ProjectAtom),
+        (stm_y, "#project p/2.", ast.ASTType.ProjectSignature),
+    ])
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve()
+
+#end.
+
+test(N,R) :- (N,R) = @test().
diff --git a/app/clingo/tests/python/ast.sol b/app/clingo/tests/python/ast.sol
new file mode 100644
index 0000000..c779e4d
--- /dev/null
+++ b/app/clingo/tests/python/ast.sol
@@ -0,0 +1,3 @@
+Step: 1
+test(0,ok) test(1,ok) test(10,ok) test(11,ok) test(12,ok) test(13,ok) test(14,ok) test(15,ok) test(16,ok) test(17,ok) test(18,ok) test(19,ok) test(2,ok) test(20,ok) test(21,ok) test(22,ok) test(23,ok) test(24,ok) test(25,ok) test(26,ok) test(27,ok) test(28,ok) test(29,ok) test(3,ok) test(30,ok) test(31,ok) test(32,ok) test(33,ok) test(34,ok) test(35,ok) test(36,ok) test(37,ok) test(38,ok) test(39,ok) test(4,ok) test(40,ok) test(41,ok) test(42,ok) test(43,ok) test(44,ok) test(45,ok) test(46,ok) test(47,ok) test(48,ok) test(5,ok) test(6,ok) test(7,ok) test(8,ok) test(9,ok)
+SAT
diff --git a/app/clingo/tests/python/ast2.lp b/app/clingo/tests/python/ast2.lp
new file mode 100644
index 0000000..4c3c16f
--- /dev/null
+++ b/app/clingo/tests/python/ast2.lp
@@ -0,0 +1,132 @@
+#script (python)
+
+import clingo
+
+def parse(s):
+    ret = []
+    clingo.parse_program(s, lambda stm: ret.append(str(stm)))
+    return ret[1:]
+
+def check(l):
+    ret = []
+    for n, (p, r) in zip(range(len(l)), l):
+        ret.append((n, clingo.Function("ok" if parse(p) == r else "fail")))
+    return ret
+
+def stm():
+    return check([
+        ("a.", ["a."]),
+        ("a:-b.", ["a :- b."]),
+        ("#const a=10.", ["#const a = 10. [default]"]),
+        ("#show a/1.", ["#show a/1."]),
+        ("#show $a/1.", ["#show $a/1."]),
+        ("#show a : b.", ["#show a : b."]),
+        ("#show $a : b.", ["#show $a : b."]),
+        ("#minimize{ 1:b }.", [":~ b. [1@0]"]),
+        ("#script (python) 42 #" + "end.", ["#script (python) 42 #" + "end."]),
+        ("#program p(k).", ["#program p(k)."]),
+        ("#external p(k).", ["#external p(k)."]),
+        ("#external p(k) : a, b.", ["#external p(k) : a; b."]),
+        ("#edge (u,v) : a, b.", ["#edge (u,v) : a; b."]),
+        ("#heuristic a : b, c. [L@P,level]", ["#heuristic a : b; c. [L@P,level]"]),
+        ("#project a : b.", ["#project a : b."]),
+        ("#project a/2.", ["#project a/2."]),
+        ("#theory x {}.", ["#theory x {\n}."]),
+    ])
+
+def thd():
+    return check([
+        ("#theory x { t { ++ : 1, unary } }.", ["#theory x {\n  t {\n    ++ : 1, unary\n  }\n}."]),
+        ("#theory x { &a/0 : t, any }.", ["#theory x {\n  &a/0 : t, any\n}."]),
+        ("#theory x { &a/0 : t, {+, -}, u, any }.", ["#theory x {\n  &a/0 : t, { +, - }, u, any\n}."]),
+    ])
+
+def bdl():
+    return check([
+        (":-a.", ["#false :- a."]),
+        (":-not a.", ["#false :- not a."]),
+        (":-not not a.", ["#false :- not not a."]),
+        (":-a:b.", ["#false :- a : b."]),
+        (":-a:b,c;d.", ["#false :- a : b, c; d."]),
+        (":-1{a:b,c;e}2.", ["#false :- 1 <= { a : b, c; e :  } <= 2."]),
+        (":-{a:b,c;e}2.", ["#false :- 2 >= { a : b, c; e :  }."]),
+        (":-1#min{1,2:b,c;1:e}2.", ["#false :- 1 <= #min { 1,2 : b, c; 1 : e } <= 2."]),
+        (":-&p { 1 : a,b; 2 : c }.", ["#false :- &p { 1 : a,b; 2 : c }."]),
+        (":-#disjoint {1,2:$x:a,b}.", ["#false :- #disjoint { 1,2 : 1$*$x : a,b }."]),
+    ])
+
+def hdl():
+    return check([
+        ("a.", ["a."]),
+        ("a:b.", ["a : b."]),
+        ("a:b,c;d.", ["d : ; a : b, c."]),
+        ("1{a:b,c;e}2.", ["1 <= { a : b, c; e :  } <= 2."]),
+        ("{a:b,c;e}2.", ["2 >= { a : b, c; e :  }."]),
+        ("1#min{1,2:h:b,c;1:e}2.", ["1 <= #min { 1,2 : h : b, c; 1 : e :  } <= 2."]),
+        ("&p { 1 : a,b; 2 : c }.", ["&p { 1 : a,b; 2 : c }."]),
+        ("&p { 1 : a,b; 2 : c } ** 33.", ["&p { 1 : a,b; 2 : c } ** 33."]),
+    ])
+
+def lit():
+    return check([
+        ("#true.", ["#true."]),
+        ("#false.", ["#false."]),
+        ("a.", ["a."]),
+        ("not a.", ["not a."]),
+        ("not not a.", ["not not a."]),
+        ("1 != 3.", ["1!=3."]),
+        ("1 $< 2 $< 3.", ["1$<2$<3."]),
+        ("1 $< 2 $< 3.", ["1$<2$<3."]),
+    ])
+
+def trm():
+    return check([
+        ("p(a).", ["p(a)."]),
+        ("p(X).", ["p(X)."]),
+        ("p(-a).", ["p(-a)."]),
+        ("p(~a).", ["p(~a)."]),
+        ("p(|a|).", ["p(|a|)."]),
+        ("p((a+b)).", ["p((a+b))."]),
+        ("p((a-b)).", ["p((a-b))."]),
+        ("p((a*b)).", ["p((a*b))."]),
+        ("p((a/b)).", ["p((a/b))."]),
+        ("p((a\\b)).", ["p((a\\b))."]),
+        ("p((a?b)).", ["p((a?b))."]),
+        ("p((a^b)).", ["p((a^b))."]),
+        ("p(a..b).", ["p((a..b))."]),
+        ("p((),(1,),f(),f(1,2)).", ["p((),(1,),f,f(1,2))."]),
+        ("p(a;b).", ["(p(a);p(b))."]),
+        ("p((a,;b)).", ["p(((a,);b))."]),
+        ("1 $+ 3 $* $x $+ 7 $< 2 $< 3.", ["1$+3$*$x$+7$<2$<3."]),
+    ])
+
+def tht():
+    return check([
+        ("&p{ } !! a.", ["&p {  } !! a."]),
+        ("&p{ } !! X.", ["&p {  } !! X."]),
+        ("&p{ } !! [].", ["&p {  } !! []."]),
+        ("&p{ } !! [1].", ["&p {  } !! [1]."]),
+        ("&p{ } !! [1,2].", ["&p {  } !! [1,2]."]),
+        ("&p{ } !! ().", ["&p {  } !! ()."]),
+        ("&p{ } !! (a).", ["&p {  } !! a."]),
+        ("&p{ } !! (a,).", ["&p {  } !! (a,)."]),
+        ("&p{ } !! {}.", ["&p {  } !! {}."]),
+        ("&p{ } !! f().", ["&p {  } !! f."]),
+        ("&p{ } !! f(a,1).", ["&p {  } !! f(a,1)."]),
+        ("&p{ } !! 1 + (x + y * z).", ["&p {  } !! (1 + (x + y * z))."]),
+    ])
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve()
+
+#end.
+
+stm(N,R) :- (N,R) = @stm().
+thd(N,R) :- (N,R) = @thd().
+bdl(N,R) :- (N,R) = @bdl().
+hdl(N,R) :- (N,R) = @hdl().
+lit(N,R) :- (N,R) = @lit().
+trm(N,R) :- (N,R) = @trm().
+tht(N,R) :- (N,R) = @tht().
+
diff --git a/app/clingo/tests/python/ast2.sol b/app/clingo/tests/python/ast2.sol
new file mode 100644
index 0000000..336f9d2
--- /dev/null
+++ b/app/clingo/tests/python/ast2.sol
@@ -0,0 +1,3 @@
+Step: 1
+bdl(0,ok) bdl(1,ok) bdl(2,ok) bdl(3,ok) bdl(4,ok) bdl(5,ok) bdl(6,ok) bdl(7,ok) bdl(8,ok) bdl(9,ok) hdl(0,ok) hdl(1,ok) hdl(2,ok) hdl(3,ok) hdl(4,ok) hdl(5,ok) hdl(6,ok) hdl(7,ok) lit(0,ok) lit(1,ok) lit(2,ok) lit(3,ok) lit(4,ok) lit(5,ok) lit(6,ok) lit(7,ok) stm(0,ok) stm(1,ok) stm(10,ok) stm(11,ok) stm(12,ok) stm(13,ok) stm(14,ok) stm(15,ok) stm(16,ok) stm(2,ok) stm(3,ok) stm(4,ok) stm(5,ok) stm(6,ok) stm(7,ok) stm(8,ok) stm(9,ok) thd(0,ok) thd(1,ok) thd(2,ok) tht(0,ok) tht(1,ok) tht(10,ok) tht(11,ok) tht(2,ok) tht(3,ok) tht(4,ok) tht(5,ok) tht(6,ok) tht(7,ok) tht(8,ok) tht(9,ok) trm(0,ok) trm(1,ok) trm(10,ok) trm(11,ok) trm(12,ok) trm(13,ok) trm(14,ok) trm(15,ok) trm(16,ok) trm(2,ok) trm(3,ok) trm(4,ok) trm(5,ok) trm(6,ok) trm(7,ok) trm(8,ok) trm(9,ok)
+SAT
diff --git a/app/clingo/tests/python/ast3.lp b/app/clingo/tests/python/ast3.lp
new file mode 100644
index 0000000..fcf891e
--- /dev/null
+++ b/app/clingo/tests/python/ast3.lp
@@ -0,0 +1,142 @@
+#script (python)
+
+import clingo
+
+def solve(s):
+    prg = clingo.Control(["0", "-Wno-operation-undefined"])
+    with prg.builder() as b:
+        clingo.parse_program(s, lambda stm: b.add(stm))
+    prg.ground([("base", [])])
+    ret = []
+    prg.solve(on_model=lambda m: ret.append(sorted(m.symbols(shown=True))))
+    return str(sorted(ret))
+
+def parse(s):
+    prg = clingo.Control([])
+    with prg.builder() as b:
+        clingo.parse_program(s, lambda stm: b.add(stm))
+    prg.ground([("base", [])])
+    return str([x for x in prg.theory_atoms])
+
+def check(l, t = "", s=solve):
+    ret = []
+    for n, (p, r) in zip(range(len(l)), l):
+        ret.append((n, clingo.Function("ok" if s(p+t) == r else "fail")))
+    return ret
+
+def stm():
+    return check([
+        ("a.", "[[a]]"),
+        ("a. c. b :- a, c.", "[[a, b, c]]"),
+        ("#const a=10. p(a).", "[[p(10)]]"),
+        ("a. b. #show a/0.", "[[a]]"),
+        ("$a$=1. $b$=2. #show $a/0.", "[[$(a,1)]]"),
+        ("a. #show b : a.", "[[a, b]]"),
+        ("$a$=1. $b$=2. #show. #show $a.", "[[$(a,1)]]"),
+        ("#minimize{ 1:b; 2:a }. {a;b}. :- not a, not b.", "[[b]]"),
+        # NOTE: atm the script code is not evaluated...
+        ("#script (python) def x() return 32; end #"+ "end. p(@x()).", "[[]]"),
+        ("#edge (u,v) : a. #edge (v,u) : b. {a;b}.", "[[], [a], [b]]"),
+        ("#theory x {}.", "[[]]"),
+        ("#external a.", "[[]]"),
+        ("#heuristic a : b, c. [1@2,level] b. c.", "[[b, c]]"),
+        ("#project a.", "[[]]"),
+        ("#project a/0.", "[[]]"),
+    ])
+
+def bdl():
+    return check([
+        ("{a}. :-a.", "[[]]"),
+        ("{a}. :-not a.", "[[a]]"),
+        ("{a}. :-not not a.", "[[]]"),
+        (":-a:b. 0{a; b}0.", "[]"),
+        (":-0{a:b;c}1. {a;b;c}.", "[[a, b, c]]"),
+        (":-0#min{1,2:a,b;2:c}2. {a;b;c}.", "[[], [a], [b]]"),
+        ("1 $<= $x $<= 2. 1 $<= $y $<= 2. :- #disjoint {1:$x; 2:$y}.", "[[$(x,1), $(y,1)], [$(x,2), $(y,2)]]"),
+    ])
+
+def hdl():
+    return check([
+        ("a.", "[[a]]"),
+        ("not a. a :- #false.", "[[]]"),
+        ("not not a. a :- #false.", "[]"),
+        ("a:b;c.{b}.", "[[a, b], [b, c], [c]]"),
+        ("1{a:b;b}2.", "[[a, b], [b]]"),
+        ("#min{1,2:a;2:c}1.", "[[a], [a, c]]"),
+    ])
+
+def lit():
+    return check([
+        ("a.", "[[a]]"),
+        ("1=1.", "[[]]"),
+        ("1!=1.", "[]"),
+        ("#true.", "[[]]"),
+        ("#false.", "[]"),
+        ("1 $< 2 $< 3.", "[[]]"),
+        ("2 $< 3 $< 1.", "[]"),
+    ])
+
+def trm():
+    return check([
+        ("p(a).", "[[p(a)]]"),
+        ("p(X) :- X=a.", "[[p(a)]]"),
+        ("p(-1).", "[[p(-1)]]"),
+        ("p(|1|).", "[[p(1)]]"),
+        ("p((3+2)).", "[[p(5)]]"),
+        ("p((3-2)).", "[[p(1)]]"),
+        ("p((3*2)).", "[[p(6)]]"),
+        ("p((7/2)).", "[[p(3)]]"),
+        ("p((7\\2)).", "[[p(1)]]"),
+        ("p((7?2)).", "[[p(7)]]"),
+        ("p((7^2)).", "[[p(5)]]"),
+        ("p(3..3).", "[[p(3)]]"),
+        ("p(a;b).", "[[p(a), p(b)]]"),
+        ("p((),(1,),f(),f(1,2)).", "[[p((),(1,),f,f(1,2))]]"),
+        ("p((a,;b)).", "[[p(b), p((a,))]]"),
+        ("12 $< 1 $+ 3 $* $x $+ 7 $< 17. 0 $<= x $<= 4.", "[[$(x,2)]]"),
+    ])
+
+def tht():
+    theory = '''
+        #theory x {
+            t {
+                * : 1, binary, left;
+                ^ : 2, binary, right;
+                - : 3, unary
+            };
+            &a/0 : t, directive;
+            &b/0 : t, {=}, t, any
+        }.
+        '''
+    return check([
+        ("&a{}.", "[&a{}]"),
+        ("&a{1,2,3:a,b}. {a;b}.", "[&a{1,2,3: a,b}]"),
+        ("&b{} = a.", "[&b{}=a]"),
+        ("&b{} = X:-X=1.", "[&b{}=1]"),
+        ("&b{} = [].", "[&b{}=[]]"),
+        ("&b{} = [1].", "[&b{}=[1]]"),
+        ("&b{} = [1,2].", "[&b{}=[1,2]]"),
+        ("&b{} = ().", "[&b{}=()]"),
+        ("&b{} = (a).", "[&b{}=a]"),
+        ("&b{} = (a,).", "[&b{}=(a,)]"),
+        ("&b{} = {}.", "[&b{}={}]"),
+        ("&b{} = f().", "[&b{}=f()]"),
+        ("&b{} = f(a,1).", "[&b{}=f(a,1)]"),
+        ("&b{} = a*x.", "[&b{}=(a*x)]"),
+        ("&b{} = -a*x*y^z^u.", "[&b{}=(((-a)*x)*(y^(z^u)))]"),
+        ("&b{} = -(a*x*y^z^u).", "[&b{}=(-((a*x)*(y^(z^u))))]"),
+    ], theory, parse)
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve()
+
+#end.
+
+stm(N,R) :- (N,R) = @stm().
+bdl(N,R) :- (N,R) = @bdl().
+hdl(N,R) :- (N,R) = @hdl().
+lit(N,R) :- (N,R) = @lit().
+trm(N,R) :- (N,R) = @trm().
+tht(N,R) :- (N,R) = @tht().
+
diff --git a/app/clingo/tests/python/ast3.sol b/app/clingo/tests/python/ast3.sol
new file mode 100644
index 0000000..7508be5
--- /dev/null
+++ b/app/clingo/tests/python/ast3.sol
@@ -0,0 +1,3 @@
+Step: 1
+bdl(0,ok) bdl(1,ok) bdl(2,ok) bdl(3,ok) bdl(4,ok) bdl(5,ok) bdl(6,ok) hdl(0,ok) hdl(1,ok) hdl(2,ok) hdl(3,ok) hdl(4,ok) hdl(5,ok) lit(0,ok) lit(1,ok) lit(2,ok) lit(3,ok) lit(4,ok) lit(5,ok) lit(6,ok) stm(0,ok) stm(1,ok) stm(10,ok) stm(11,ok) stm(12,ok) stm(13,ok) stm(14,ok) stm(2,ok) stm(3,ok) stm(4,ok) stm(5,ok) stm(6,ok) stm(7,ok) stm(8,ok) stm(9,ok) tht(0,ok) tht(1,ok) tht(10,ok) tht(11,ok) tht(12,ok) tht(13,ok) tht(14,ok) tht(15,ok) tht(2,ok) tht(3,ok) tht(4,ok) tht(5,ok) tht(6,ok) tht(7,ok) tht(8,ok) tht(9,ok) trm(0,ok) trm(1,ok) trm(10,ok) trm(11,ok) trm(12,ok) trm(13,ok) trm(14,ok) trm(15,ok) trm(2,ok) trm(3,ok) trm(4,ok) trm(5,ok) trm(6,ok) trm(7,ok) trm(8,ok) trm(9,ok)
+SAT
diff --git a/app/clingo/tests/python/blocksworld1.lp b/app/clingo/tests/python/blocksworld1.lp
new file mode 100644
index 0000000..abc0d62
--- /dev/null
+++ b/app/clingo/tests/python/blocksworld1.lp
@@ -0,0 +1,216 @@
+% show instances of selected predicates only
+#show.
+
+% output stack representation
+#show order/4.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for generating states providing relative block positions, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program state(k,t).
+
+% a block's scope includes the table (labeled 0) and blocks with smaller numbers
+scope(k,0,t).
+scope(k,I,t) :- scope(I,0,t), I < k.
+
+% order(1,k,I,t) provides the closest block I in scope above k, if any at time t
+#count{ I : order(1,k,I,t) : scope(k,I,t), 0 < I } 1.
+
+% order(-1,k,I,t) provides the closest block/table I in scope below k at time t
+1 #count{ I : order(-1,k,I,t) : scope(k,I,t) } 1.
+
+% trace order/4 to derive transitive closure of objects in scope above/below k
+trans(D,k,I,t) :- order(D,k,I,t).
+trans(D,k,I,t) :- trans(D,k,J,t), order(D,J,I,t).
+trans(D,k,J,t) :- trans(D,k,I,t), order(-D,J,I,t), scope(k,J,t).
+
+% state constraint that the table is transitively below block k (redundant)
+ :- not trans(-1,k,0,t).
+
+% state constraint propagating immediate above/below relationships
+ :- order(-1,k,I,t), order(1,k,J,t), not order(-1,J,I,t), not order(1,I,J,t).
+
+% state constraint aligning immediate and transitive above/below relationships
+ :- order(-D,k,J,t), order(D,J,I,t), not trans(D,k,I,t), 0 < I. % D=-1 redundant
+
+% state constraint directing transitive above/below relationships on convergence
+ :- order(D,k,I,t), order(D,J,I,t), not trans(-D,k,J,t), scope(k,J,t), 0 < I.
+
+% rules below are volatile with life span 1
+% #program volatile(k,t).
+
+#external scope(k,0,t+1).
+
+% goal state conditions
+ :- goal_above(k,I), not trans(-1,k,I,t), not scope(k,0,t+1).
+ :- goal_below(k,I), not trans(1,k,I,t), not scope(k,0,t+1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for generating moves having a block as object and target, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program move(k,t).
+
+% external atoms indicating involvement of blocks with greater numbers in move
+#external change(-1,k,I,t) : scope(I,0,t), I <= k.
+#external change( 1,k,I,t) : scope(I,0,t-1), I <= k.
+#external change(-1,k,t).
+#external change( 1,k,t).
+
+% output object and target block of move
+#show object(k,t) : object(k,t).
+#show target(k,t) : target(k,t).
+
+% propagate role as move object (via D=1) or target (via D=-1) to smaller block
+change(1,k-1,I,t) :- order(1,k,I,t), scope(I,0,t-1), not order(1,k,I,t-1).
+change(D,k-1,I,t) :- order(D,k,I,t-(D+|D|)/2), scope(k,0,t-1), 0 < I,
+                     not order(D,k,I,t+(D-|D|)/2).
+change(D,k-1,I,t) :- change(D,k,I,t), I < k. % , scope(I,0,t-(D+|D|)/2).
+
+% combine possibilities how move affects block as object (D=1) or target (D=-1)
+affect(-D,k,t) :- order(D,k,I,t+(D-|D|)/2), scope(I,0,t-1) : D == 1;
+                  not order(D,k,I,t-(D+|D|)/2).
+affect( D,k,t) :- change(D,k,k,t). % , scope(k,0,t-(D+|D|)/2).
+
+% propagate existence of some move object or target to smaller blocks and table
+change(D,k-1,t) :- affect(D,k,t).
+change(D,k-1,t) :- change(D,k,t).
+
+% derive moved object and corresponding target
+object(k,t) :- affect(1,k,t).
+target(k,t) :- affect(-1,k,t), not change(-1,k,t).
+
+% moved object must be unique
+ :- object(k,t), change(1,k,t).
+
+% moved object must be free
+ :- object(k,t), order(1,k,_,t-1).
+ :- object(I,t), order(-1,k,I,t-1).
+
+% moved object must not go under (unmoved) pre-existing block
+ :- object(k,t), order(1,k,I,t), scope(I,0,t-1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for deriving target table from move without target block, using %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program table(t).
+
+% external atoms indicating involvement of blocks with greater numbers in move
+#external change(-1,0,t).
+#external change( 1,0,t).
+
+% output target table of move
+#show target(0,t) : target(0,t).
+
+% derive table as target of move
+target(0,t) :- change(1,0,t), not change(-1,0,t).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for establishing consistent initial position for a block, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program init(k,t).
+
+% no appearance under unmoved pre-existing block
+ :- order(1,k,I,t), scope(I,0,t-1), not object(I,t).
+
+% initial state conditions
+ :- init_above(k,I), not trans(-1,k,I,t).
+ :- init_below(k,I), not trans(1,k,I,t).
+% clingo-4-banane clingo-4-blocksworld.lp clingo-4-main.lp 0
+
+#script (python)
+
+def main(prg):
+    parts = []
+    parts.append(("init", [1,0]))
+    parts.append(("state", [1,0]))
+    prg.ground(parts)
+    prg.solve()
+
+    parts = []
+    parts.append(("base_2", []))
+    parts.append(("init", [2,0]))
+    parts.append(("state", [2,0]))
+    for i in range(1, 3):
+        parts.append(("table", [i]))
+        for j in range(1, 3):
+            parts.append(("state", [j,i]))
+            parts.append(("move", [j,i]))
+    prg.ground(parts)
+    prg.solve()
+
+    parts = []
+    parts.append(("base_3", []))
+    parts.append(("init", [3,0]))
+    parts.append(("state", [3,0]))
+    for i in range(1, 4):
+        parts.append(("state", [3,i]))
+        parts.append(("move", [3,i]))
+    for j in range(1, 3):
+        parts.append(("state", [j,3]))
+        parts.append(("move", [j,3]))
+    parts.append(("table", [3]))
+    prg.ground(parts)
+    prg.solve()
+
+    parts = []
+    parts.append(("base_4", []))
+    parts.append(("init", [4,0]))
+    parts.append(("state", [4,0]))
+    for i in range(1, 5):
+        parts.append(("state", [4,i]))
+        parts.append(("move", [4,i]))
+    for j in range(1, 4):
+        parts.append(("state", [j,4]))
+        parts.append(("move", [j,4]))
+    parts.append(("table", [4]))
+    prg.ground(parts)
+    prg.solve()
+
+    parts = []
+    parts.append(("base_5", []))
+    parts.append(("init", [5,1]))
+    for i in range(1, 8):
+        parts.append(("state", [5,i]))
+        parts.append(("move", [5,i]))
+    for i in range(5, 8):
+        parts.append(("table", [i]))
+        for j in range(1, 5):
+            parts.append(("state", [j,i]))
+            parts.append(("move", [j,i]))
+    prg.ground(parts)
+    prg.solve()
+#end.
+
+#program base_2.
+
+init_above(2,1).
+goal_below(2,1).
+
+#program base_3.
+
+init_above(3,2).
+goal_below(3,1).
+
+#program base_4.
+
+init_above(4,2).
+init_below(4,3).
+goal_above(4,3).
+goal_below(4,1).
+
+#program base_5.
+
+init_above(5,1).
+init_below(5,3).
+goal_above(5,2).
diff --git a/app/clingo/tests/python/blocksworld1.sol b/app/clingo/tests/python/blocksworld1.sol
new file mode 100644
index 0000000..2c41088
--- /dev/null
+++ b/app/clingo/tests/python/blocksworld1.sol
@@ -0,0 +1,12 @@
+Step: 1
+order(-1,1,0,0)
+Step: 2
+object(1,2) object(2,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,2,0,1) order(-1,2,0,2) order(-1,2,1,0) order(1,2,1,2) target(0,1) target(2,2)
+Step: 3
+object(1,3) object(2,2) object(3,1) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,2,0,2) order(-1,2,0,3) order(-1,2,1,0) order(-1,2,1,1) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,2,0) order(1,2,1,3) order(1,3,2,2) order(1,3,2,3) target(0,1) target(2,3) target(3,2)
+Step: 4
+object(1,4) object(2,3) object(3,1) object(4,2) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,2,0,3) order(-1,2,0,4) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,3,0,1) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,2,0) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,3,2) order(-1,4,3,3) order(-1,4,3,4) order(1,2,1,4) order(1,3,2,3) order(1,3,2,4) order(1,4,2,3) order(1,4,2,4) order(1,4,3,0) target(0,1) target(2,4) target(3,2) target(4,3)
+Step: 5
+object(1,6) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,7) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,0,6) order(-1,5,1,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,6) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,3,1) target(0,2) target(0,3) target(1,7) target(2,6) target(3,4) target(4,5) target(5,1)
+object(1,7) object(2,5) object(3,1) object(3,2) object(4,4) object(5,3) object(5,6) order(-1,1,0,0) order(-1,1,0,1) order(-1,1,0,2) order(-1,1,0,3) order(-1,1,0,4) order(-1,1,0,5) order(-1,1,0,6) order(-1,1,0,7) order(-1,2,0,5) order(-1,2,0,6) order(-1,2,0,7) order(-1,2,1,0) order(-1,2,1,1) order(-1,2,1,2) order(-1,2,1,3) order(-1,2,1,4) order(-1,3,0,2) order(-1,3,0,3) order(-1,3,0,4) order(-1,3,0,5) order(-1,3,0,6) order(-1,3,0,7) order(-1,3,2,0) order(-1,3,2,1) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,4,3,4) order(-1,4,3,5) order(-1,4,3,6) order(-1,4,3,7) order(-1,5,0,3) order(-1,5,0,4) order(-1,5,0,5) order(-1,5,2,6) order(-1,5,2,7) order(-1,5,4,1) order(-1,5,4,2) order(1,2,1,7) order(1,3,2,5) order(1,3,2,6) order(1,3,2,7) order(1,4,2,5) order(1,4,2,6) order(1,4,2,7) order(1,4,3,0) order(1,4,3,1) order(1,5,1,7) order(1,5,3,1) target(0,2) target(0,3) target(2,6) target(3,4) target(4,5) target(5,1) target(5,7)
+SAT
diff --git a/app/clingo/tests/python/cover-py.lp b/app/clingo/tests/python/cover-py.lp
new file mode 100644
index 0000000..20815d0
--- /dev/null
+++ b/app/clingo/tests/python/cover-py.lp
@@ -0,0 +1,90 @@
+#script (python)
+
+import clingo
+import sys
+
+class State:
+    def __init__(self):
+        self.leaves = {}
+        self.last = None
+
+    def fix(self, k):
+        return self.leaves.get(k.number-1, [])
+
+    def on_model(self, m):
+        self.last = m.symbols(atoms=True)
+        for atom in self.last:
+            if atom.name == "leaf":
+                args = atom.arguments
+                self.leaves[args[0]] = args[1]
+
+    def prepare_instance(self, k):
+        edges = []
+        cover = []
+        vertices = set()
+        for atom in self.last:
+            if atom.name == "edge":
+                args = atom.arguments
+                if args[0].number == k-1:
+                    edges.append((args[1], args[2]))
+                    vertices.add(args[1])
+                    vertices.add(args[2])
+            if atom.name == "cover":
+                cover.append(atom.arguments[1])
+        vertices = list(vertices)
+        setattr(self, "edge", lambda: edges)
+        setattr(self, "cover", lambda: cover)
+        setattr(self, "vertex", lambda: vertices)
+
+    def run(self, prg):
+        pre = clingo.Control()
+        pre.add("base", [], """
+edge(a,(b;c)).
+edge(b,(c;d)).
+edge(d,e).
+edge(e,f).
+
+edge(x,(a;c)). % edge to keep something to solve
+
+edge(X,Y) :- edge(Y,X).
+vertex(X) :- edge(X,Y;Y,X).
+
+edge(0,X,Y) :- edge(X,Y).
+        """)
+        pre.add("step", ["k"], """
+:- not leaf(k-1,@fix(k)).
+
+1 { leaf(k,X) : vertex(X) } 1.
+cover(k,X) :- edge(k-1,X,Y), leaf(k,Y).
+edge(k,X,Y) :- edge(k-1,X,Y), not cover(k,X), not cover(k,Y).
+
+:- edge(k-1,X,Y), leaf(k,Y), edge(k-1,Y,Z), X < Z.
+:- leaf(k,Y), not edge(k-1,_,Y).
+        """)
+        pre.ground([("base", [])])
+        ret = pre.solve(on_model = self.on_model)
+        k = 0
+        while ret.satisfiable is True:
+            k = k + 1
+            pre.cleanup()
+            pre.ground([("step", [k])], self)
+            ret = pre.solve(on_model = self.on_model)
+        self.prepare_instance(k)
+        prg.add("base", [], """
+vertex(X) :- X = @vertex().
+edge(X,Y) :- (X,Y) = @edge().
+cover(X)  :- X = @cover().
+
+{ cover(X) : vertex(X) }.
+:- edge(X,Y), not cover(X), not cover(Y).
+%#minimize { 1,X : cover(X) }.
+#show cover/1.
+        """)
+        prg.ground([("base", [])], self)
+        prg.solve()
+
+def main(prg):
+    s = State()
+    s.run(prg)
+
+#end.
diff --git a/app/clingo/tests/python/cover-py.sol b/app/clingo/tests/python/cover-py.sol
new file mode 100644
index 0000000..00cf084
--- /dev/null
+++ b/app/clingo/tests/python/cover-py.sol
@@ -0,0 +1,6 @@
+Step: 1
+cover(a) cover(b) cover(c) cover(e)
+cover(a) cover(b) cover(c) cover(e) cover(x)
+cover(a) cover(b) cover(e) cover(x)
+cover(b) cover(c) cover(e) cover(x)
+SAT
diff --git a/app/clingo/tests/python/domain.lp b/app/clingo/tests/python/domain.lp
new file mode 100644
index 0000000..9bdc19e
--- /dev/null
+++ b/app/clingo/tests/python/domain.lp
@@ -0,0 +1,27 @@
+p(1).
+{ p(3) }. 
+#external p(1..3).
+
+q(X) :- p(X).
+
+#script (python)
+
+import clingo, sys
+
+def main(prg):
+    prg.ground([("base", [])])
+    print ("Solving...")
+    print ("Answer: 1")
+    out = ("universe(" + str(len(prg.symbolic_atoms)) + ")")
+    for x in prg.symbolic_atoms:
+        out = out + " domain(" + str(x.symbol) + "," + str(x.is_fact).lower() + "," + str(x.is_external).lower() + ")"
+    out = out + " in_domain(p(2)," + str(prg.symbolic_atoms[clingo.Function("p", [3])] is not None).lower() + ")"
+    out = out + " in_domain(p(4)," + str(prg.symbolic_atoms[clingo.Function("p", [4])] is not None).lower() + ")"
+    for x in prg.symbolic_atoms.by_signature("p", 1):
+        out = out + " domain_of_p(" + str(x.symbol) + "," + str(x.is_fact).lower() + "," + str(x.is_external).lower() + ")"
+    for x in prg.symbolic_atoms.signatures:
+        out = out + " sig(" + x[0] + "," + str(x[1]) + ")"
+    print (out)
+    sys.stdout.flush()
+
+#end. 
diff --git a/app/clingo/tests/python/domain.sol b/app/clingo/tests/python/domain.sol
new file mode 100644
index 0000000..001ec75
--- /dev/null
+++ b/app/clingo/tests/python/domain.sol
@@ -0,0 +1,3 @@
+Step: 1
+domain(p(1),true,false) domain(p(2),false,true) domain(p(3),false,false) domain(q(1),true,false) domain(q(2),false,false) domain(q(3),false,false) domain_of_p(p(1),true,false) domain_of_p(p(2),false,true) domain_of_p(p(3),false,false) in_domain(p(2),true) in_domain(p(4),false) sig(p,1) sig(q,1) universe(6)
+UNKNOWN
diff --git a/app/clingo/tests/python/externals.lp b/app/clingo/tests/python/externals.lp
new file mode 100644
index 0000000..b398337
--- /dev/null
+++ b/app/clingo/tests/python/externals.lp
@@ -0,0 +1,19 @@
+#script (python)
+
+import sys
+from clingo import Function
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.assign_external(Function("a"), True)
+    prg.solve()
+    prg.assign_external(Function("a"), False)
+    prg.solve()
+    prg.assign_external(Function("a"), None)
+    prg.solve()
+    prg.release_external(Function("a"))
+    prg.solve()
+
+#end.
+
+#external a.
diff --git a/app/clingo/tests/python/externals.sol b/app/clingo/tests/python/externals.sol
new file mode 100644
index 0000000..9e8f54e
--- /dev/null
+++ b/app/clingo/tests/python/externals.sol
@@ -0,0 +1,10 @@
+Step: 1
+a
+Step: 2
+
+Step: 3
+
+a
+Step: 4
+
+SAT
diff --git a/app/clingo/tests/python/iclingo.lp b/app/clingo/tests/python/iclingo.lp
new file mode 100644
index 0000000..e3b3dca
--- /dev/null
+++ b/app/clingo/tests/python/iclingo.lp
@@ -0,0 +1,22 @@
+#program step(k).
+
+#external vol(k).
+p(k).
+:- vol(k), not 5 { p(K) : K <= k }.
+
+#script (python)
+
+from clingo import *
+
+def main(prg):
+    step = 0
+    while True:
+        if step > 0: prg.release_external(Function("vol", [step-1]))
+        prg.ground([("step", [step])])
+        prg.assign_external(Function("vol", [step]), True)
+        ret = prg.solve()
+        if ret.satisfiable is True:
+            break
+        step += 1
+
+#end.
diff --git a/app/clingo/tests/python/iclingo.sol b/app/clingo/tests/python/iclingo.sol
new file mode 100644
index 0000000..be1ef8b
--- /dev/null
+++ b/app/clingo/tests/python/iclingo.sol
@@ -0,0 +1,7 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+p(0) p(1) p(2) p(3) p(4) vol(4)
+SAT
diff --git a/app/clingo/tests/python/interrupt.lp b/app/clingo/tests/python/interrupt.lp
new file mode 100644
index 0000000..537a069
--- /dev/null
+++ b/app/clingo/tests/python/interrupt.lp
@@ -0,0 +1,23 @@
+#script (python) 
+
+import clingo
+
+def main(prg):
+    prg.ground([("pigeon", [])])
+    for i in range(0,2):
+        prg.assign_external(clingo.Function("p"), True)
+        prg.solve()
+        prg.assign_external(clingo.Function("p"), False)
+        f = prg.solve_async()
+        f.wait(0.01)
+        f.cancel()
+
+#end.
+
+#const n = 190.
+
+#program pigeon.
+#external p.
+
+1 { p(X); q(X) } 1 :- X = 1..n, not p.
+:- not n+1 { p(1..n); q(1..n) }, not p.
diff --git a/app/clingo/tests/python/interrupt.sol b/app/clingo/tests/python/interrupt.sol
new file mode 100644
index 0000000..31733d7
--- /dev/null
+++ b/app/clingo/tests/python/interrupt.sol
@@ -0,0 +1,7 @@
+Step: 1
+p
+Step: 2
+Step: 3
+p
+Step: 4
+UNKNOWN
diff --git a/app/clingo/tests/python/parse-term.lp b/app/clingo/tests/python/parse-term.lp
new file mode 100644
index 0000000..94e076a
--- /dev/null
+++ b/app/clingo/tests/python/parse-term.lp
@@ -0,0 +1,14 @@
+#script (python)
+
+import clingo
+
+c = clingo.Control()
+def get():
+    return [ clingo.parse_term('1'), clingo.parse_term('p(1+2)'), clingo.parse_term('-p'), clingo.parse_term('-p(1)') ]
+
+c.ground([("base", [])])
+c.solve()
+
+#end.
+
+p(@get()).
diff --git a/app/clingo/tests/python/parse-term.sol b/app/clingo/tests/python/parse-term.sol
new file mode 100644
index 0000000..8d2055c
--- /dev/null
+++ b/app/clingo/tests/python/parse-term.sol
@@ -0,0 +1,3 @@
+Step: 1
+p(-p(1)) p(-p) p(1) p(p(3))
+SAT
diff --git a/app/clingo/tests/python/project.lp b/app/clingo/tests/python/project.lp
new file mode 100644
index 0000000..71ca12e
--- /dev/null
+++ b/app/clingo/tests/python/project.lp
@@ -0,0 +1,197 @@
+% Programme de fouille de motifs séquentiels (occurrences minimales)
+% author : T. Guyet
+% date : 02/2014
+% 
+% parametres de la ligne de commande:
+%   * -c th=? : fixe le seuil (3 par default)
+%   * -c ml=? : profondeur de la recherche (taille max des motifs) (4 par default)
+%
+% ces deux valeurs sont remplacées par des constantes du programme :
+%   - th : seuil de frequence, valeur par defaut 3 : elle peut être modifiée par eds parametres lors de l'appel du programme
+%   - nbs : nombre de symboles : defini lors de la construction de la séquence
+#const th = 3.
+
+% liste des symboles fréquents
+symb(S) :- th { seq(P,S) }, S=1..nbs.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% partie visualisation
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%#show occ/3. %ne pas afficher les occ pour l'option project 
+#show pattern/2.
+%#show symb/1.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% partie Contrôle de la résolution
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#script(python)
+import sys, os
+from clingo import *
+if sys.version_info[0] >= 3:
+    import io as StringIO
+else:
+    import StringIO
+
+modelid = 0
+
+patterns=list()
+
+def readsequence(filename):
+    seq = list()
+    src = StringIO.StringIO("""1 5
+2 2
+3 5
+4 2
+5 5
+6 2
+7 1
+8 2
+9 4
+10 2
+11 1
+12 6
+13 1
+14 2
+15 5
+16 3
+17 3
+18 1
+19 3
+20 2
+""")
+    if src is None:
+        print ("invalid filename:" + str(filename))
+        return None
+    predpos=0
+    for line in src:
+        lineelem = line.rstrip('\n\r').lstrip(' ').split(' ')
+        pos=lineelem[0]
+        if( pos==predpos ) :
+            print ("invalid sequence : simultaneous events are not allowed")
+            return None
+        predpos=pos
+        seq.append( int(lineelem[1]) )
+    src.close()
+    return seq
+
+def genASPsequence(seq, prg):
+    i=1
+    #ajout de la constante pour le nombre de symboles
+    s="#const nbs = "+str(max(seq)) +"."
+    prg.add("base",[], s )
+    for n in seq:
+        s='seq('+str(i)+","+str(n)+').'
+        prg.add("base", [], s)
+        i=i+1
+
+def on_model(model):
+    pattern={} # map qui associe le numero d'instance à un numero de structure
+    
+    for atom in model.symbols(atoms=True):
+        if atom.name()=="pattern":
+            args = atom.arguments
+            pattern[ args[0] ]=args[1]
+    
+    found=False
+    for i in patterns:
+        if i==pattern:
+            found=True
+            break
+    if not found:
+        patterns.append( pattern )
+
+def main(prg):
+    #Chargement du jeu de données
+    theseq = readsequence("we_cmp.seq.minepi")
+    genASPsequence(theseq, prg)
+    prg.configuration.solve.project = 1
+    prg.configuration.solve.models  = 0
+    d = prg.get_const("ml")
+    if d is None:
+        d=4
+    else:
+        d = d.number
+    
+    prg.ground([("base",[])])
+    prg.solve()
+    
+    for k in range(2,d+1):
+        prg.ground([("incr",[k])])
+        prg.solve()
+#end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% partie Base
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% génération de tous les motifs de taille 1
+1{ pattern(1, P) : symb(P) } 1.
+
+% on genere les occurrences pour chacun des patterns-singletons : le numero de l'instance est la position initiale (unique) !
+{ occ(P, 1, P) : seq(P, S) } :- pattern(1,S).
+
+% pour imposer d'avoir nécessairement toutes les occurrenres d'un motifs (et pas simplement des sous-ensembles):
+:- seq(P, S), not occ(P, 1, P), pattern(1,S).
+
+%%%%%%%%%%%%
+%% cas des tailles 2
+%1{ pattern(2, P) : symb(P) } 1.
+
+% extention des occurrences du motif
+%0{ occ(I,2,Q) : seq(Q,S), pattern(2,S), Q>P } 1 :- occ(I, 1, P).
+
+%:- occ(I, 1, P), occ(I, 2, Q), seq(P',S), pattern(2,S), PP } 1 :- occ(I, n-1, P).
+%0{ possocc(I,n,Q) : seq(Q,S), pattern(n,S), Q>P } 1 :- occ(I, n-1, P).
+
+%#show occ/3.
+
+%
+%#external closed(1..nbs).
+%% pour savoir si le motif plus petit est fermé par l'ajout de S:
+%nbnext(I,n-1,N) :- occ(I, n-1, P), N={ occ(I,n,Q) }.
+%closed(S) :- { nbnext(I,n-1,N) : N=0 } 0, pattern(n,S).
+%#show closed/1.
+
+
+% On prend le premier symbole de la fin du motif juste apres la fin d'une occurrence du motif "inferieur" :
+:- occ(I, n-1, P), occ(I, n, Q), seq(P',S), pattern(n,S), P= 0)
+            item = self.__map_item(str(item))
+            resize(self.__seq_atoms[sid][1], index + 1);
+            self.__seq_atoms[sid][1][index] = item
+
+    def __add_pat_atoms(self, init, atom):
+        for elem in atom.elements:
+            lit = init.solver_literal(elem.condition_id)
+            index, item = elem.terms
+            index = index.number
+            assert(index >= 0)
+            item = self.__map_item(str(item))
+            pat = (index, item)
+            if lit not in self.__pat_atoms:
+                init.add_watch(lit)
+            self.__pat_atoms.setdefault(lit, []).append(pat)
+            self.__pat_len = max(self.__pat_len, index + 1)
+
+    def __init_occ_list(self):
+        for item in self.__item_map:
+            self.__occ_list.append([])
+        sid = 0
+        for seq in self.__seq_atoms:
+            for item in set(seq[1]):
+                assert(item is not None)
+                self.__occ_list[item].append(sid)
+            sid += 1
+
+    def init(self, init):
+        for atom in init.theory_atoms:
+            term = atom.term
+            args = term.arguments
+            if term.name == "seq" and len(args) == 1:
+                self.__add_seq_atom(init, args[0].number, atom)
+            if term.name == "pat" and len(args) == 0:
+                self.__add_pat_atoms(init, atom)
+        self.__init_occ_list()
+
+    # {{{1 Tracing Functions
+    def __str_item(self, iid):
+        for item, jid in self.__item_map.iteritems():
+            if iid == jid:
+                return item
+
+    def __str_items(self, items):
+        s = ""
+        for item in items:
+            s+= self.__str_item(item)
+        return s
+
+    def __str_pat(self, state):
+        s = ""
+        for pat in state.pat:
+            s+= "." if pat is None else self.__str_item(pat[1])
+        return s
+
+    def __str_seq(self, lit):
+        for seq in self.__seq_atoms:
+            if seq[0] == lit:
+                return self.__str_items(seq[1])
+
+    # {{{1 Propagation
+
+    def __propagate_sequence_lit(self, state, control, sid, lit):
+        state.seq_active[sid] = None
+        state.stack.append(-sid-1)
+        if not control.assignment.is_true(lit):
+            klaus = [lit]
+            for pat in state.pat:
+                if pat is not None:
+                    klaus.append(-pat[0])
+            return control.add_clause(klaus) and control.propagate()
+        return True
+
+    def __propagate_sequence(self, state, control, sid, lit, items):
+        if state.pat_assigned < self.__pat_len and control.assignment.is_false(lit):
+            return True
+        iid = 0
+        for pat in state.pat:
+            while True:
+                if iid == len(items):
+                    return self.__propagate_sequence_lit(state, control, sid, -lit)
+                iid+= 1
+                if pat is None or items[iid-1] == pat[1]:
+                    break
+        return state.pat_assigned < self.__pat_len or self.__propagate_sequence_lit(state, control, sid, lit)
+
+    def propagate(self, control, changes):
+        state = self.__state(control.thread_id)
+        if len(state.trail) == 0 or state.trail[-1][0] < control.assignment.decision_level:
+            state.trail.append((control.assignment.decision_level, len(state.stack)))
+        for lit in changes:
+            for pat in self.__pat_atoms[lit]:
+                if state.pat[pat[0]] is not None:
+                    # this case should not occur if the pattern is generated properly
+                    old = state.pat[pat[0]][0]
+                    assert(control.assignment.is_true(old))
+                    control.add_clause([-lit, -old]) and control.propagate()
+                    return
+                else:
+                    state.stack.append(pat[0])
+                    state.pat_assigned+= 1
+                    state.pat[pat[0]] = (lit, pat[1])
+                    for sid in self.__occ_list[pat[1]]:
+                        if state.seq_active[sid] and not self.__propagate_sequence(state, control, sid, *self.__seq_atoms[sid]):
+                            return
+
+    def undo(self, thread_id, assign, undo):
+        state = self.__state(thread_id)
+        sid = state.trail[-1][1]
+        for psid in state.stack[sid:]:
+            if psid >= 0:
+                state.pat[psid] = None
+                state.pat_assigned-= 1
+            else:
+                state.seq_active[-psid-1] = True
+        del state.stack[sid:]
+        state.trail.pop()
+
+    # }}}1
+
+def main(prg):
+    prg.configuration.solve.opt_mode = "optN"
+    prg.register_propagator(Propagator())
+    prg.ground([("base", [])])
+    # :- not sup(U), seq(U,_,_), n == 0.
+    if prg.get_const("n").number == 0:
+        grouped = {}
+        for atom in prg.symbolic_atoms.by_signature("seq", 3):
+            grouped.setdefault(atom.symbol.arguments[0], []).append(atom.literal)
+        for key, value in sorted(grouped.items()):
+            a = prg.backend.add_atom()
+            for l in value:
+                prg.backend.add_rule([a], [l])
+            prg.backend.add_rule([], [-prg.symbolic_atoms[clingo.Function("sup", [key])].literal, a])
+    # :- sup(U), pat(_,I), not seq(U,_,I).
+    grouped_pat, grouped_seq = {}, set()
+    for atom in prg.symbolic_atoms.by_signature("pat", 2):
+        grouped_pat.setdefault(atom.symbol.arguments[1], []).append(atom.literal)
+    for atom in prg.symbolic_atoms.by_signature("seq", 3):
+        grouped_seq.add((atom.symbol.arguments[0], atom.symbol.arguments[2]))
+    projected_pat, projected_seq = {}, {}
+    for key, value in sorted(grouped_pat.items()):
+        a = prg.backend.add_atom()
+        for l in value:
+            prg.backend.add_rule([a], [l])
+        projected_pat[key] = a
+    for atom in prg.symbolic_atoms.by_signature("sup", 1):
+        for key, lit in sorted(projected_pat.items()):
+            if (atom.symbol.arguments[0], key) not in grouped_seq:
+                prg.backend.add_rule([], [atom.literal, lit])
+    prg.solve()
+
+#end.
+
+#show pat/2.
+
+#theory seq {
+    term { };
+    &seq/1 : term, body;
+    &pat/0 : term, directive
+}.
+
+#const n = 5.
+
+1 { pat(P,I) : seq(_,_,I) } 1 :- P = 0..(n-1).
+
+&pat { P,I : pat(P,I) }.
+sup(U) :- &seq(U) { P,I : seq(U,P,I) }, seq(U,_,_).
+
+#maximize { 1,U : sup(U) }.
+
+% abaca
+seq(0,0,a).
+seq(0,1,b).
+seq(0,2,a).
+seq(0,3,c).
+seq(0,4,a).
+
+% abdca
+seq(1,0,a).
+seq(1,1,b).
+seq(1,2,d).
+seq(1,3,c).
+seq(1,4,a).
+
+% aedca
+seq(2,0,a).
+seq(2,1,e).
+seq(2,2,d).
+seq(2,3,c).
+seq(2,4,a).
diff --git a/app/clingo/tests/python/propagator.sol b/app/clingo/tests/python/propagator.sol
new file mode 100644
index 0000000..cfca62c
--- /dev/null
+++ b/app/clingo/tests/python/propagator.sol
@@ -0,0 +1,5 @@
+Step: 1
+pat(0,a) pat(1,b) pat(2,a) pat(3,c) pat(4,a)
+pat(0,a) pat(1,b) pat(2,d) pat(3,c) pat(4,a)
+pat(0,a) pat(1,e) pat(2,d) pat(3,c) pat(4,a)
+OPTIMUM FOUND
diff --git a/app/clingo/tests/python/queens.lp b/app/clingo/tests/python/queens.lp
new file mode 100644
index 0000000..77b213e
--- /dev/null
+++ b/app/clingo/tests/python/queens.lp
@@ -0,0 +1,37 @@
+#script (python)
+
+import clingo
+
+def main(prg):
+    step = 1
+    stop = 10
+    while True:
+        if step > 1:
+            prg.release_external(clingo.Function("volatile", [step-1]))
+        prg.ground([("cumulative", [step])])
+        prg.assign_external(clingo.Function("volatile", [step]), True)
+        ret = prg.solve()
+        if step == stop:
+            break
+        step = step + 1
+
+#end.
+
+#program cumulative(k).
+
+dim(k).
+
+{q(X,k) : dim(X)}.
+{q(k,Y) : dim(Y), Y 0 else Function(name)
+
+def on_model(model):
+    models.append(fun("model", split(model)))
+    models.append(fun("shown", sorted(model.symbols(shown=True))))
+    models.append(fun("atoms", sorted(model.symbols(atoms=True))))
+    models.append(fun("terms", sorted(model.symbols(terms=True))))
+    models.append(fun("csp",   sorted(model.symbols(csp=True))))
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve(on_model)
+    prg.ground([("result", [])])
+    prg.solve()
+
+#end.
+
+$1 $= 11.
+{ b }.
+c.
+$x $= 42.
+$y(1) $= 13.
+$y(2) $= 23.
+$z $= 7.
+#show $1.
+#show c/0.
+#show a : b.
+#show $x/0.
+#show $y(1) : b.
+#show $y(2) : not b.
+#show $y(3) : b.
+
+#program result.
+res(X) :- X = @getModels(). 
+#show res/1.
+
diff --git a/app/clingo/tests/python/show.sol b/app/clingo/tests/python/show.sol
new file mode 100644
index 0000000..f2951cd
--- /dev/null
+++ b/app/clingo/tests/python/show.sol
@@ -0,0 +1,7 @@
+Step: 1
+1=11 a c x=42 y(1)=13
+1=11 c x=42 y(2)=23
+Step: 2
+1=11 a c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(1)=13
+1=11 c res(atoms(b,c)) res(atoms(c)) res(csp($(1,11),$(x,42),$(z,7),$(y(1),13),$(y(2),23))) res(model("1=11","a","c","x=42","y(1)=13")) res(model("1=11","c","x=42","y(2)=23")) res(shown(a,c,$(1,11),$(x,42),$(y(1),13))) res(shown(c,$(1,11),$(x,42),$(y(2),23))) res(terms(a)) res(terms) x=42 y(2)=23
+SAT
diff --git a/app/clingo/tests/python/sokoban.cmd b/app/clingo/tests/python/sokoban.cmd
new file mode 100644
index 0000000..461dbd4
--- /dev/null
+++ b/app/clingo/tests/python/sokoban.cmd
@@ -0,0 +1 @@
+-q1,2
diff --git a/app/clingo/tests/python/sokoban.lp b/app/clingo/tests/python/sokoban.lp
new file mode 100644
index 0000000..2a1db82
--- /dev/null
+++ b/app/clingo/tests/python/sokoban.lp
@@ -0,0 +1,105 @@
+#script(python)
+
+from clingo import Function, SolveResult
+from sys import stderr
+
+def main(prg):
+    prg.configuration.solve.opt_mode = "optN"
+    prg.configuration.solve.models  = 0
+    t = 0
+    e = 2
+    parts = []
+    parts.append(("base", []))
+    parts.append(("state", [t]))
+    while True:
+        prg.ground(parts)
+        prg.release_external(Function("volatile", [t-1]))
+        prg.cleanup()
+        prg.assign_external(Function("volatile", [t]), True)
+        ret = prg.solve()
+        if ret.satisfiable is False and t > 20: break
+        if ret.satisfiable is True:
+            e -= 1
+            if e == 0: break
+        t += 1
+        parts = []
+        parts.append(("trans", [t]))
+        parts.append(("state", [t]))
+
+#end.
+
+#program base.
+
+dir(u, 0, 1).
+dir(d, 0,-1).
+dir(r, 1, 0).
+dir(l,-1, 0).
+
+box(X,Y,0) :- initial_box(X,Y).
+at(X,Y,0)  :- initial_at(X,Y).
+
+#program trans(t).
+
+% reachable places
+route(X,Y,t)       :- at(X,Y,t-1).
+route(X+DX,Y+DY,t) :- route(X,Y,t), dir(D,DX,DY), square(X+DX,Y+DY), not box(X+DX,Y+DY,t-1).
+
+% select place to move from
+1 { push_from(X,Y,D,t) : route(X,Y,t), dir(D,DX,DY), square(X+DX,Y+DY), box(X+DX,Y+DY,t-1) } 1.
+
+% move horizontally or vertically
+move(X,Y,D,t)           :- push_from(X,Y,D,t).
+{ move(X+DX,Y+DY,D,t) } :- move(X,Y,D,t), dir(D,DX,DY), square(X+2*DX,Y+2*DY), not box(X+2*DX,Y+2*DY,t-1).
+
+% target location
+move_to(X,Y,D,t)     :- move(X,Y,D,t), not move(X+DX,Y+DY,D,t), dir(D,DX,DY).
+push_to(X+DX,Y+DY,t) :- move_to(X,Y,D,t), dir(D,DX,DY).
+
+% state transition
+at(X-DX,Y-DY,t) :- move_to(X,Y,D,t), dir(D,DX,DY).
+box(X,Y,t)      :- push_to(X,Y,t).
+box(X,Y,t)      :- box(X,Y,t-1), not push_from(X-DX,Y-DY,D,t) : dir(D,DX,DY).
+
+#show push_from(X,Y,t) : push_from(X,Y,D,t).
+#show move_to(X,Y,t) : move_to(X,Y,D,t).
+#show push_to/3.
+
+#program state(t).
+
+#minimize { X@1,Y,t : box(X,Y,t) }.
+#minimize { Y@2,X,t : box(X,Y,t) }.
+
+#external volatile(t).
+
+ :- target_square(X,Y), not box(X,Y,t), volatile(t).
+
+#program base.
+
+square(1, 1).
+target_square(1, 1).
+square(2, 1).
+target_square(2, 1).
+square(1, 2).
+target_square(1, 2).
+square(2, 2).
+target_square(2, 2).
+initial_at(5,3).
+square(1, 3).
+square(2, 3).
+initial_box(2, 3).
+square(3, 3).
+square(4, 3).
+initial_box(4, 3).
+square(5, 3).
+square(1, 4).
+square(2, 4).
+square(3, 4).
+initial_box(3, 4).
+square(4, 4).
+initial_box(4, 4).
+square(5, 4).
+square(1, 5).
+square(2, 5).
+square(3, 5).
+square(4, 5).
+square(5, 5).
diff --git a/app/clingo/tests/python/sokoban.sol b/app/clingo/tests/python/sokoban.sol
new file mode 100644
index 0000000..19875c6
--- /dev/null
+++ b/app/clingo/tests/python/sokoban.sol
@@ -0,0 +1,14 @@
+Step: 1
+Step: 2
+Step: 3
+Step: 4
+Step: 5
+Step: 6
+Step: 7
+Step: 8
+Step: 9
+move_to(1,2,3) move_to(1,3,6) move_to(2,2,1) move_to(2,3,2) move_to(2,3,8) move_to(2,4,5) move_to(3,3,7) move_to(3,4,4) push_from(1,4,3) push_from(1,5,6) push_from(2,4,1) push_from(2,4,8) push_from(3,5,4) push_from(4,3,7) push_from(5,3,2) push_from(5,4,5) push_to(1,1,3) push_to(1,2,6) push_to(1,3,2) push_to(1,4,5) push_to(2,1,1) push_to(2,2,8) push_to(2,3,7) push_to(3,3,4)
+Step: 10
+move_to(1,2,3) move_to(1,3,6) move_to(1,3,9) move_to(2,2,1) move_to(2,3,2) move_to(2,3,8) move_to(2,4,5) move_to(3,3,7) move_to(3,4,4) push_from(1,3,9) push_from(1,4,3) push_from(1,5,6) push_from(2,4,1) push_from(2,4,8) push_from(3,5,4) push_from(4,3,7) push_from(5,3,2) push_from(5,4,5) push_to(1,1,3) push_to(1,2,6) push_to(1,2,9) push_to(1,3,2) push_to(1,4,5) push_to(2,1,1) push_to(2,2,8) push_to(2,3,7) push_to(3,3,4)
+move_to(1,2,3) move_to(1,3,6) move_to(2,2,1) move_to(2,3,2) move_to(2,3,8) move_to(2,3,9) move_to(2,4,5) move_to(3,3,7) move_to(3,4,4) push_from(1,4,3) push_from(1,5,6) push_from(2,3,9) push_from(2,4,1) push_from(2,4,8) push_from(3,5,4) push_from(4,3,7) push_from(5,3,2) push_from(5,4,5) push_to(1,1,3) push_to(1,2,6) push_to(1,3,2) push_to(1,4,5) push_to(2,1,1) push_to(2,2,8) push_to(2,2,9) push_to(2,3,7) push_to(3,3,4)
+OPTIMUM FOUND
diff --git a/app/clingo/tests/python/tag.lp b/app/clingo/tests/python/tag.lp
new file mode 100644
index 0000000..894aa81
--- /dev/null
+++ b/app/clingo/tests/python/tag.lp
@@ -0,0 +1,33 @@
+#script(python)
+class Tag:
+    def __init__(self):
+        pass
+
+    def init(self, init):
+        for atom in init.symbolic_atoms:
+            init.add_watch(init.solver_literal(atom.literal))
+            init.add_watch(-init.solver_literal(atom.literal))
+
+    def propagate(self, control, changes):
+        global add
+        if add: control.add_clause([],tag=True)
+        return True
+
+    def undo(self, thread_id, assign, undo):
+        pass
+
+    def check(self, control):
+        return True
+
+def main(prg):
+    global add
+    add=True
+    prg.ground([("base", [])])
+    prg.register_propagator(Tag())
+    ret=prg.solve()
+    add=not add
+    ret=prg.solve()
+
+#end.
+
+{a}.
diff --git a/app/clingo/tests/python/tag.sol b/app/clingo/tests/python/tag.sol
new file mode 100644
index 0000000..afa0c0f
--- /dev/null
+++ b/app/clingo/tests/python/tag.sol
@@ -0,0 +1,5 @@
+Step: 1
+Step: 2
+
+a
+SAT
diff --git a/app/clingo/tests/python/test.lp b/app/clingo/tests/python/test.lp
new file mode 100644
index 0000000..8c35a17
--- /dev/null
+++ b/app/clingo/tests/python/test.lp
@@ -0,0 +1,57 @@
+#script (python)
+
+import clingo
+import sys
+
+def writeln(s):
+    sys.stdout.write(str(s))
+    sys.stdout.write("\n")
+    sys.stdout.flush()
+
+def on_model(x):
+    writeln("Answer: 42")
+    writeln(
+          "hasA(" +        str(x.contains(clingo.Function("a"))).lower() + ") "
+        + "hasVolatile(" + str(x.contains(clingo.Function("volatile", [9]))).lower() + ") "
+        + "model(" +       ",".join(sorted(map(str, x.symbols(shown=True)))) + ") ")
+
+def on_finish(ret):
+    writeln("Answer: 42")
+    writeln(str(ret) + "_" + str(ret.interrupted).lower())
+
+def main (prg):
+    n = prg.get_const("n").number
+    parts = []
+    parts.append(("base", []))
+    prg.ground(parts)
+    prg.solve()
+    prg.add("test", ["x"], "test(x).")
+    parts.append(("test", [clingo.Function("f", [1,2])]))
+    for i in range(1,n+1):
+        parts.append(("cumulative", [i]))
+        prg.ground(parts)
+        parts = []
+        f = prg.solve_async(on_model, on_finish)
+        f.wait(0)
+        ret = f.get()
+        writeln("Answer: 42")
+        writeln(ret)
+
+#end.
+
+#const n = 10.
+
+#program base.
+
+a.
+
+#program cumulative(k).
+
+1 { c(k) } 1.
+q(k) :- c(k).
+r(k,X) :- test(X).
+
+#external volatile(k).
+ :- not c(5), not volatile(k).
+volatile(k-1).
+
diff --git a/app/clingo/tests/python/test.sol b/app/clingo/tests/python/test.sol
new file mode 100644
index 0000000..f3729f2
--- /dev/null
+++ b/app/clingo/tests/python/test.sol
@@ -0,0 +1,45 @@
+Step: 1
+a
+Step: 2
+UNSAT
+UNSAT_false
+Step: 3
+UNSAT
+UNSAT_false
+Step: 4
+UNSAT
+UNSAT_false
+Step: 5
+UNSAT
+UNSAT_false
+Step: 6
+SAT
+SAT_false
+a c(1) c(2) c(3) c(4) c(5) q(1) q(2) q(3) q(4) q(5) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),q(1),q(2),q(3),q(4),q(5),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4))
+Step: 7
+SAT
+SAT_false
+a c(1) c(2) c(3) c(4) c(5) c(6) q(1) q(2) q(3) q(4) q(5) q(6) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),q(1),q(2),q(3),q(4),q(5),q(6),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5))
+Step: 8
+SAT
+SAT_false
+a c(1) c(2) c(3) c(4) c(5) c(6) c(7) q(1) q(2) q(3) q(4) q(5) q(6) q(7) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),q(1),q(2),q(3),q(4),q(5),q(6),q(7),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6))
+Step: 9
+SAT
+SAT_false
+a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7))
+Step: 10
+SAT
+SAT_false
+a c(1) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8)
+hasA(true) hasVolatile(false) model(a,c(1),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8))
+Step: 11
+SAT
+SAT_false
+a c(1) c(10) c(2) c(3) c(4) c(5) c(6) c(7) c(8) c(9) q(1) q(10) q(2) q(3) q(4) q(5) q(6) q(7) q(8) q(9) r(1,f(1,2)) r(10,f(1,2)) r(2,f(1,2)) r(3,f(1,2)) r(4,f(1,2)) r(5,f(1,2)) r(6,f(1,2)) r(7,f(1,2)) r(8,f(1,2)) r(9,f(1,2)) test(f(1,2)) volatile(0) volatile(1) volatile(2) volatile(3) volatile(4) volatile(5) volatile(6) volatile(7) volatile(8) volatile(9)
+hasA(true) hasVolatile(true) model(a,c(1),c(10),c(2),c(3),c(4),c(5),c(6),c(7),c(8),c(9),q(1),q(10),q(2),q(3),q(4),q(5),q(6),q(7),q(8),q(9),r(1,f(1,2)),r(10,f(1,2)),r(2,f(1,2)),r(3,f(1,2)),r(4,f(1,2)),r(5,f(1,2)),r(6,f(1,2)),r(7,f(1,2)),r(8,f(1,2)),r(9,f(1,2)),test(f(1,2)),volatile(0),volatile(1),volatile(2),volatile(3),volatile(4),volatile(5),volatile(6),volatile(7),volatile(8),volatile(9))
+SAT
diff --git a/app/clingo/tests/run.py b/app/clingo/tests/run.py
new file mode 100755
index 0000000..ef9e8a9
--- /dev/null
+++ b/app/clingo/tests/run.py
@@ -0,0 +1,169 @@
+#!/usr/bin/python
+
+import os
+import os.path
+import sys
+import subprocess as sp
+import difflib as dl
+import argparse
+
+parser = argparse.ArgumentParser(description="""
+Can be used to run and normalize tests.
+Additional options can be passed to clingo by adding them at the end of the command line preceded by '--'.
+""")
+parser.add_argument('-c', '--clingo', default=None, help="path to clingo executable")
+
+subparsers = parser.add_subparsers(dest="action", help="sub-command --help")
+subparsers.required = True
+parser_run = subparsers.add_parser('run', help='run all tests')
+parser_normalize = subparsers.add_parser('normalize', help='normalize the output of clingo')
+parser_normalize.add_argument("file")
+
+argv = sys.argv[1:]
+extra_argv = []
+if "--" in argv:
+    extra_argv = argv[argv.index("--")+1:]
+    argv       = argv[:argv.index("--")]
+
+parse_ret = parser.parse_args(argv)
+
+if parse_ret.action is None:
+    print (parser.usage)
+    exit(0)
+
+clingo = parse_ret.clingo
+
+def find_clingo():
+    clingos = [
+        "build/debug/clingo",
+        "build/release/clingo",
+        "x64/ReleaseScript/clingo.exe",
+        "ReleaseScript/clingo.exe",
+        "x64/Release/clingo.exe",
+        "Release/clingo.exe",
+        "x64/DebugScript/clingo.exe",
+        "DebugScript/clingo.exe",
+        "x64/Debug/clingo.exe",
+        "Debug/clingo.exe",
+        ]
+    for x in clingos:
+        x = os.path.normpath("{}/../../../{}".format(wd, x))
+        if os.path.exists(x):
+            return x
+    return None
+
+wd = os.path.normpath(os.path.dirname(__file__))
+if clingo is None:
+    clingo = find_clingo()
+
+if clingo is None:
+    print ("no usable clingo version found")
+    exit(1)
+
+def reorder(out):
+    return out
+    res = []
+    current = []
+    for line in out.splitlines():
+        if line.startswith("Step: ") or line.startswith("SAT") or line.startswith("UNSAT") or line.startswith("UNKNOWN") or line.startswith("OPTIMUM FOUND"):
+            res.extend(sorted(current))
+            res.append(line)
+            current = []
+        else:
+            current.append(" ".join(sorted(line.split(" "))))
+    return "\n".join(res)
+
+def normalize(out):
+    state=0
+    current=[]
+    step=0
+    result="ERROR"
+    norm=[]
+    for line in out.split('\n'):
+        if state == 1:
+            if step > 0:
+                norm.append("Step: {}".format(step))
+                models = []
+                for model in current:
+                    models.append(" ".join(sorted(model)))
+                for model in sorted(models):
+                    norm.append(model)
+            step += 1
+            state = 0
+            current = []
+        if state == 2:
+            current.append(line.strip().split(" "))
+            state=0
+        elif line.startswith("Solving..."):
+            state = 1
+        elif line.startswith("Answer: "):
+            state = 2
+        elif line.startswith("SATISFIABLE"):
+            result="SAT"
+            state=1
+        elif line.startswith("UNSATISFIABLE"):
+            result="UNSAT"
+            state=1
+        elif line.startswith("UNKNOWN"):
+            result="UNKNOWN"
+            state=1
+        elif line.startswith("OPTIMUM FOUND"):
+            result="OPTIMUM FOUND"
+            state=1
+    norm.append(result)
+    norm.append("")
+    return "\n".join(norm)
+
+if parse_ret.action == "normalize":
+    args = [clingo, "0", parse_ret.file, "-Wnone"]
+    b = os.path.splitext(parse_ret.file)[0]
+    if os.path.exists(b + ".cmd"):
+        for x in open(b + ".cmd"):
+            args.extend(x.strip().split())
+    args.extend(extra_argv)
+    out, err = sp.Popen(args, stderr=sp.PIPE, stdout=sp.PIPE, universal_newlines=True).communicate()
+    sys.stdout.write(normalize(out))
+    exit(0)
+if parse_ret.action == "run":
+    total  = 0
+    failed = 0
+
+    for root, dirs, files in os.walk(wd):
+        for f in sorted(files):
+            if f.endswith(".lp"):
+                total+= 1
+                b = os.path.join(root, f[:-3])
+                sys.stdout.flush()
+                args = [clingo, "0", b + ".lp", "-Wnone"]
+                if os.path.exists(b + ".cmd"):
+                    for x in open(b + ".cmd"):
+                        args.extend(x.strip().split())
+                args.extend(extra_argv)
+                out, err = sp.Popen(args, stderr=sp.PIPE, stdout=sp.PIPE, universal_newlines=True).communicate()
+                norm = normalize(out)
+                sol  = reorder(open(b + ".sol").read())
+                if norm != sol:
+                    failed+= 1
+                    print
+                    print ("-" * 79)
+                    print (" ".join(args))
+                    print ("." * 79)
+                    print
+                    print ("FAILED:")
+                    d = dl.Differ()
+                    for line in list(d.compare(sol.splitlines(), norm.splitlines())):
+                        if not line.startswith(" "):
+                            print (line)
+                    print
+                sys.stdout.flush()
+
+    print ("=" * 79)
+    if failed > 0:
+        print ("Some tests failed ({} of {} test cases)".format(failed, total))
+        print
+        exit(1)
+    else:
+        print ("All tests passed ({} test cases)".format(total))
+        print
+        exit(0)
+
diff --git a/app/example/main.cc b/app/example/main.cc
new file mode 100644
index 0000000..68bb0a4
--- /dev/null
+++ b/app/example/main.cc
@@ -0,0 +1,47 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+// Copyright (C) 2013  Roland Kaminski
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#include 
+#include 
+
+using namespace Clingo;
+
+int main(int argc, char const **argv) {
+    try {
+        Logger logger = [](Clingo::WarningCode, char const *message) {
+            std::cerr << message << std::endl;
+        };
+        Control ctl{{argv+1, size_t(argc-1)}, logger, 20};
+        ctl.add("base", {}, "a :- not b. b :- not a.");
+        ctl.ground({{"base", {}}});
+        for (auto m : ctl.solve_iteratively()) {
+            std::cout << "Model:";
+            for (auto &atom : m.symbols()) {
+                std::cout << " " << atom;
+            }
+            std::cout << "\n";
+        };
+    }
+    catch (std::exception const &e) {
+        std::cerr << "example failed with: " << e.what() << std::endl;
+    }
+}
+
diff --git a/app/gringo/main.cc b/app/gringo/main.cc
new file mode 100644
index 0000000..75a6431
--- /dev/null
+++ b/app/gringo/main.cc
@@ -0,0 +1,430 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Roland Kaminski
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#ifdef WITH_PYTHON
+#  include 
+#endif
+#ifdef WITH_LUA
+#  include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct GringoOptions {
+    using Foobar = std::vector;
+    ProgramOptions::StringSeq     defines;
+    Gringo::Output::OutputOptions outputOptions;
+    Gringo::Output::OutputFormat  outputFormat          = Gringo::Output::OutputFormat::INTERMEDIATE;
+    bool                          verbose               = false;
+    bool                          wNoOperationUndefined = false;
+    bool                          wNoAtomUndef          = false;
+    bool                          wNoFileIncluded       = false;
+    bool                          wNoVariableUnbounded  = false;
+    bool                          wNoGlobalVariable     = false;
+    bool                          wNoOther              = false;
+    bool                          rewriteMinimize       = false;
+    bool                          keepFacts             = false;
+    Foobar                        foobar;
+};
+
+static inline std::vector split(std::string const &source, char const *delimiter = " ", bool keepEmpty = false) {
+    std::vector results;
+    size_t prev = 0;
+    size_t next = 0;
+    while ((next = source.find_first_of(delimiter, prev)) != std::string::npos) {
+        if (keepEmpty || (next - prev != 0)) { results.push_back(source.substr(prev, next - prev)); }
+        prev = next + 1;
+    }
+    if (prev < source.size()) { results.push_back(source.substr(prev)); }
+    return results;
+}
+
+static inline bool parseFoobar(const std::string& str, GringoOptions::Foobar& foobar) {
+    for (auto &x : split(str, ",")) {
+        auto y = split(x, "/");
+        if (y.size() != 2) { return false; }
+        unsigned a;
+        if (!bk_lib::string_cast(y[1], a)) { return false; }
+        bool sign = !y[0].empty() && y[0][0] == '-';
+        if (sign) { y[0] = y[0].substr(1); }
+        foobar.emplace_back(y[0].c_str(), a, sign);
+    }
+    return true;
+}
+
+#define LOG if (opts.verbose) std::cerr
+struct IncrementalControl : Gringo::Control, Gringo::GringoModule {
+    using StringVec = std::vector;
+    IncrementalControl(Gringo::Output::OutputBase &out, StringVec const &files, GringoOptions const &opts)
+    : out(out)
+    , scripts(*this)
+    , pb(scripts, prg, out, defs, opts.rewriteMinimize)
+    , parser(pb)
+    , opts(opts) {
+        using namespace Gringo;
+        out.keepFacts = opts.keepFacts;
+        logger_.enable(clingo_warning_operation_undefined, !opts.wNoOperationUndefined);
+        logger_.enable(clingo_warning_atom_undefined, !opts.wNoAtomUndef);
+        logger_.enable(clingo_warning_variable_unbounded, !opts.wNoVariableUnbounded);
+        logger_.enable(clingo_warning_file_included, !opts.wNoFileIncluded);
+        logger_.enable(clingo_warning_global_variable, !opts.wNoGlobalVariable);
+        logger_.enable(clingo_warning_other, !opts.wNoOther);
+        for (auto &x : opts.defines) {
+            LOG << "define: " << x << std::endl;
+            parser.parseDefine(x, logger_);
+        }
+        for (auto &x : files) {
+            LOG << "file: " << x << std::endl;
+            parser.pushFile(std::string(x), logger_);
+        }
+        if (files.empty()) {
+            LOG << "reading from stdin" << std::endl;
+            parser.pushFile("-", logger_);
+        }
+        parse();
+    }
+    Gringo::Logger &logger() override {
+        return logger_;
+    }
+    void parse() {
+        if (!parser.empty()) {
+            parser.parse(logger_);
+            defs.init(logger_);
+            parsed = true;
+        }
+    }
+    void ground(Gringo::Control::GroundVec const &parts, Gringo::Context *context) override {
+        // NOTE: it would be cool to have assumptions in the lparse output
+        auto exit = Gringo::onExit([this]{ scripts.context = nullptr; });
+        scripts.context = context;
+        parse();
+        if (parsed) {
+            LOG << "************** parsed program **************" << std::endl << prg;
+            prg.rewrite(defs, logger_);
+            LOG << "************* rewritten program ************" << std::endl << prg;
+            prg.check(logger_);
+            if (logger_.hasError()) {
+                throw std::runtime_error("grounding stopped because of errors");
+            }
+            parsed = false;
+        }
+        if (!grounded) {
+            if (!initialized_) {
+                initialized_ = true;
+                out.init(incremental_);
+            }
+            out.beginStep();
+            grounded = true;
+        }
+        if (!parts.empty()) {
+            Gringo::Ground::Parameters params;
+            for (auto &x : parts) { params.add(x.first, Gringo::SymVec(x.second)); }
+            Gringo::Ground::Program gPrg(prg.toGround(out.data, logger_));
+            LOG << "************* intermediate program *************" << std::endl << gPrg << std::endl;
+            LOG << "*************** grounded program ***************" << std::endl;
+            gPrg.ground(params, scripts, out, false, logger_);
+        }
+    }
+    void add(std::string const &name, Gringo::FWStringVec const ¶ms, std::string const &part) override {
+        Gringo::Location loc("", 1, 1, "", 1, 1);
+        Gringo::Input::IdVec idVec;
+        for (auto &x : params) { idVec.emplace_back(loc, x); }
+        parser.pushBlock(name, std::move(idVec), part, logger_);
+        parse();
+    }
+    Gringo::Symbol getConst(std::string const &name) override {
+        parse();
+        auto ret = defs.defs().find(name.c_str());
+        if (ret != defs.defs().end()) {
+            bool undefined = false;
+            Gringo::Symbol val = std::get<2>(ret->second)->eval(undefined, logger_);
+            if (!undefined) { return val; }
+        }
+        return Gringo::Symbol();
+    }
+    void load(std::string const &filename) override {
+        parser.pushFile(std::string(filename), logger_);
+        parse();
+    }
+    bool blocked() override { return false; }
+    Gringo::SolveResult solve(ModelHandler, Assumptions &&ass) override {
+        if (!ass.empty()) { std::cerr << "warning: the lparse format does not support assumptions" << std::endl; }
+        grounded = false;
+        out.endStep(true, logger_);
+        out.reset();
+        const_cast(out.data.theory().data()).reset();
+        return {Gringo::SolveResult::Unknown, false, false};
+    }
+    Gringo::SolveIter *solveIter(Assumptions &&) override {
+        throw std::runtime_error("solving not supported in gringo");
+    }
+    void interrupt() override {
+        throw std::runtime_error("interrupting not supported in gringo");
+    }
+    void *claspFacade() override {
+        return nullptr;
+    }
+    void beginAdd() override {
+        parse();
+    }
+    void add(clingo_ast_statement_t const &stm) override {
+        Gringo::Input::parseStatement(pb, logger_, stm);
+    }
+    void endAdd() override {
+        defs.init(logger_);
+    }
+    void registerObserver(std::unique_ptr prg) override {
+        out.registerObserver(std::move(prg));
+    }
+    Gringo::SolveFuture *solveAsync(ModelHandler, FinishHandler, Assumptions &&) override { throw std::runtime_error("asynchronous solving not supported"); }
+    Potassco::AbstractStatistics *statistics() override { throw std::runtime_error("statistics not supported (yet)"); }
+    void assignExternal(Gringo::Symbol ext, Potassco::Value_t val) override {
+        auto atm = out.find(ext);
+        if (atm.second && atm.first->hasUid()) {
+            Gringo::Id_t offset = atm.first - atm.second->begin();
+            Gringo::Output::External external(Gringo::Output::LiteralId{Gringo::NAF::POS, Gringo::Output::AtomType::Predicate, offset, atm.second->domainOffset()}, val);
+            out.output(external);
+        }
+    }
+    Gringo::SymbolicAtoms &getDomain() override { throw std::runtime_error("domain introspection not supported"); }
+    Gringo::ConfigProxy &getConf() override { throw std::runtime_error("configuration not supported"); }
+    void registerPropagator(Gringo::UProp, bool) override { throw std::runtime_error("theory propagators not supported"); }
+    void useEnumAssumption(bool) override { }
+    bool useEnumAssumption() override { return false; }
+    virtual ~IncrementalControl() { }
+    Gringo::Symbol parseValue(std::string const &str, Gringo::Logger::Printer, unsigned) override { return termParser.parse(str, logger_); }
+    Gringo::Control *newControl(int, char const * const *, Gringo::Logger::Printer, unsigned) override { throw std::logic_error("new control instances not supported"); }
+    Gringo::TheoryData const &theory() const override { return out.data.theoryInterface(); }
+    void cleanupDomains() override { }
+    Gringo::Backend *backend() override { return out.backend(); }
+    Potassco::Atom_t addProgramAtom() override { return out.data.newAtom(); }
+    Gringo::Input::GroundTermParser        termParser;
+    Gringo::Output::OutputBase            &out;
+    Gringo::Scripts                        scripts;
+    Gringo::Defines                        defs;
+    Gringo::Input::Program                 prg;
+    Gringo::Input::NongroundProgramBuilder pb;
+    Gringo::Input::NonGroundParser         parser;
+    GringoOptions const                   &opts;
+    Gringo::Logger                         logger_;
+    std::unique_ptr builder;
+    bool                                   parsed = false;
+    bool                                   grounded = false;
+    bool initialized_ = false;
+    bool incremental_ = true;
+};
+#undef LOG
+
+static bool parseConst(const std::string& str, std::vector& out) {
+    out.push_back(str);
+    return true;
+}
+
+inline void enableAll(GringoOptions& out, bool enable) {
+    out.wNoAtomUndef          = !enable;
+    out.wNoFileIncluded       = !enable;
+    out.wNoOperationUndefined = !enable;
+    out.wNoVariableUnbounded  = !enable;
+    out.wNoGlobalVariable     = !enable;
+    out.wNoOther              = !enable;
+}
+
+inline bool parseWarning(const std::string& str, GringoOptions& out) {
+    if (str == "none")                     { enableAll(out, false);             return true; }
+    if (str == "all")                      { enableAll(out, true);              return true; }
+    if (str == "no-atom-undefined")        { out.wNoAtomUndef          = true;  return true; }
+    if (str ==    "atom-undefined")        { out.wNoAtomUndef          = false; return true; }
+    if (str == "no-file-included")         { out.wNoFileIncluded       = true;  return true; }
+    if (str ==    "file-included")         { out.wNoFileIncluded       = false; return true; }
+    if (str == "no-operation-undefined")   { out.wNoOperationUndefined = true;  return true; }
+    if (str ==    "operation-undefined")   { out.wNoOperationUndefined = false; return true; }
+    if (str == "no-variable-unbounded")    { out.wNoVariableUnbounded  = true;  return true; }
+    if (str ==    "variable-unbounded")    { out.wNoVariableUnbounded  = false; return true; }
+    if (str == "no-global-variable")       { out.wNoGlobalVariable     = true;  return true; }
+    if (str ==    "global-variable")       { out.wNoGlobalVariable     = false; return true; }
+    if (str == "no-other")                 { out.wNoOther              = true;  return true; }
+    if (str ==    "other")                 { out.wNoOther              = false; return true; }
+    return false;
+}
+
+static bool parseText(const std::string&, GringoOptions& out) {
+    out.outputFormat = Gringo::Output::OutputFormat::TEXT;
+    return true;
+}
+
+struct GringoApp : public ProgramOptions::Application {
+    using StringSeq = std::vector;
+    virtual const char* getName() const    { return "gringo"; }
+    virtual const char* getVersion() const { return GRINGO_VERSION; }
+    virtual void initOptions(ProgramOptions::OptionContext& root) {
+        using namespace ProgramOptions;
+        grOpts_.defines.clear();
+        grOpts_.verbose = false;
+        OptionGroup gringo("Gringo Options");
+        gringo.addOptions()
+            ("text,t", storeTo(grOpts_, parseText)->flag(), "Print plain text format")
+            ("const,c", storeTo(grOpts_.defines, parseConst)->composing()->arg("="), "Replace term occurrences of  with ")
+            ("output,o", storeTo(grOpts_.outputFormat = Gringo::Output::OutputFormat::INTERMEDIATE, values()
+              ("intermediate", Gringo::Output::OutputFormat::INTERMEDIATE)
+              ("text", Gringo::Output::OutputFormat::TEXT)
+              ("reify", Gringo::Output::OutputFormat::REIFY)
+              ("smodels", Gringo::Output::OutputFormat::SMODELS)), "Choose output format:\n"
+             "      intermediate: print intermediate format\n"
+             "      text        : print plain text format\n"
+             "      reify       : print program as reified facts\n"
+             "      smodels     : print smodels format\n"
+             "                    (only supports basic features)")
+            ("output-debug", storeTo(grOpts_.outputOptions.debug = Gringo::Output::OutputDebug::NONE, values()
+              ("none", Gringo::Output::OutputDebug::NONE)
+              ("text", Gringo::Output::OutputDebug::TEXT)
+              ("translate", Gringo::Output::OutputDebug::TRANSLATE)
+              ("all", Gringo::Output::OutputDebug::ALL)), "Print debug information during output:\n"
+             "      none     : no additional info\n"
+             "      text     : print rules as plain text (prefix %%)\n"
+             "      translate: print translated rules as plain text (prefix %%%%)\n"
+             "      all      : combines text and translate")
+            ("warn,W", storeTo(grOpts_, parseWarning)->arg("")->composing(), "Enable/disable warnings:\n"
+             "      none:                     disable all warnings\n"
+             "      all:                      enable all warnings\n"
+             "      [no-]atom-undefined:      a :- b.\n"
+             "      [no-]file-included:       #include \"a.lp\". #include \"a.lp\".\n"
+             "      [no-]operation-undefined: p(1/0).\n"
+             "      [no-]variable-unbounded:  $x > 10.\n"
+             "      [no-]global-variable:     :- #count { X } = 1, X = 1.\n"
+             "      [no-]other:               uncategorized warnings")
+            ("rewrite-minimize", flag(grOpts_.rewriteMinimize = false), "Rewrite minimize constraints into rules")
+            ("keep-facts", flag(grOpts_.keepFacts = false), "Do not remove facts from normal rules")
+            ("reify-sccs", flag(grOpts_.outputOptions.reifySCCs = false), "Calculate SCCs for reified output")
+            ("reify-steps", flag(grOpts_.outputOptions.reifySteps = false), "Add step numbers to reified output")
+            ("foobar,@4", storeTo(grOpts_.foobar, parseFoobar), "Foobar")
+            ;
+        root.add(gringo);
+        OptionGroup basic("Basic Options");
+        basic.addOptions()
+            ("file,f,@2", storeTo(input_)->composing(), "Input files")
+            ;
+        root.add(basic);
+    }
+    virtual void validateOptions(const ProgramOptions::OptionContext&, const ProgramOptions::ParsedOptions&, const ProgramOptions::ParsedValues&) { }
+    virtual void setup() { }
+    static bool parsePositional(std::string const &, std::string& out) {
+        out = "file";
+        return true;
+    }
+    virtual ProgramOptions::PosOption getPositional() const { return parsePositional; }
+
+    virtual void printHelp(const ProgramOptions::OptionContext& root) {
+        printf("%s version %s\n", getName(), getVersion());
+        printUsage();
+        ProgramOptions::FileOut out(stdout);
+        root.description(out);
+        printf("\n");
+        printUsage();
+    }
+
+    virtual void printVersion() {
+        Application::printVersion();
+        printf(
+            "Configuration: "
+#ifdef WITH_PYTHON
+            "with Python " PY_VERSION
+#else
+            "without Python"
+#endif
+            ", "
+#ifdef WITH_LUA
+            "with " LUA_RELEASE
+#else
+            "without Lua"
+#endif
+            "\n"
+            "Copyright (C) Roland Kaminski\n"
+            "License GPLv3+: GNU GPL version 3 or later \n"
+            "Gringo is free software: you are free to change and redistribute it.\n"
+            "There is NO WARRANTY, to the extent permitted by law.\n"
+            );
+        fflush(stdout);
+    }
+
+    void ground(Gringo::Output::OutputBase &out) {
+        using namespace Gringo;
+        IncrementalControl inc(out, input_, grOpts_);
+        if (inc.scripts.callable("main")) {
+            inc.incremental_ = true;
+            inc.scripts.main(inc);
+        }
+        else {
+            Gringo::Control::GroundVec parts;
+            parts.emplace_back("base", SymVec{});
+            inc.incremental_ = false;
+            inc.ground(parts, nullptr);
+            inc.solve(nullptr, {});
+        }
+    }
+
+    virtual void run() {
+        try {
+            using namespace Gringo;
+            grOpts_.verbose = verbose() == UINT_MAX;
+            Output::OutputPredicates outPreds;
+            for (auto &x : grOpts_.foobar) {
+                outPreds.emplace_back(Location("",1,1,"", 1,1), x, false);
+            }
+            Potassco::TheoryData data;
+            data.update();
+            Output::OutputBase out(data, std::move(outPreds), std::cout, grOpts_.outputFormat, grOpts_.outputOptions);
+            ground(out);
+        }
+        catch (Gringo::GringoError const &e) {
+            std::cerr << e.what() << std::endl;
+            throw std::runtime_error("fatal error");
+        }
+        catch (...) { throw; }
+    }
+private:
+    StringSeq     input_;
+    GringoOptions grOpts_;
+};
+
+int main(int argc, char **argv) {
+    GringoApp app;
+    return app.main(argc, argv);
+}
+
+Clingo::Control::Control(StringSpan, Logger, unsigned)
+: impl_(nullptr)
+{
+	throw std::logic_error("cannot happen");
+}
diff --git a/app/lpconvert/lpconvert.cpp b/app/lpconvert/lpconvert.cpp
new file mode 100644
index 0000000..1054d30
--- /dev/null
+++ b/app/lpconvert/lpconvert.cpp
@@ -0,0 +1,108 @@
+// 
+// Copyright (c) 2015, Benjamin Kaufmann
+// 
+// This file is part of Potassco.
+// 
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+// 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+using namespace ProgramOptions;
+
+class LpConvert : public ProgramOptions::Application {
+public:
+	virtual const char* getName()       const { return "lpconvert"; }
+	virtual const char* getVersion()    const { return "1.0.0"; }
+	virtual PosOption   getPositional() const { return &positional; }
+	virtual const char* getUsage()      const {
+		return
+			"[options] []\n"
+			"Convert program in  or standard input";
+	}
+	virtual void initOptions(OptionContext& root);
+	virtual void validateOptions(const OptionContext&, const ParsedOptions&, const ParsedValues&) {}
+	virtual void setup() {}
+	virtual void run();
+private:
+	static bool positional(const std::string&, std::string& optOut) {
+		optOut = "input";
+		return true;
+	}
+	static int error(int line, const char* what) {
+		fprintf(stderr, "*** ERROR: In line %d: %s\n", line, what);
+		static_cast(Application::getInstance())->exit(EXIT_FAILURE);
+		return EXIT_FAILURE;
+	}
+	std::string input_;
+	std::string output_;
+	bool potassco_;
+	bool filter_;
+};
+
+void LpConvert::initOptions(OptionContext& root) {
+	OptionGroup convert("Conversion Options");
+	convert.addOptions()
+		("input,i,@2", storeTo(input_),  "Input file")
+		("potassco,p", flag(potassco_ = false), "Enable potassco extensions")
+		("filter,f", flag(filter_ = false), "Hide converted potassco predicates")
+		("output,o", storeTo(output_)->arg(""), "Write output to  (default: stdout)")
+	;
+	root.add(convert);
+}
+void LpConvert::run() {
+	std::ifstream iFile;
+	std::ofstream oFile;
+	if (!input_.empty() && input_ != "-") {
+		iFile.open(input_.c_str());
+		if (!iFile.is_open()) { throw std::runtime_error("Could not open input file!"); }
+	}
+	if (!output_.empty() && output_ != "-") {
+		if (input_ == output_) { throw std::runtime_error("Input and output must be different!"); }
+		oFile.open(output_.c_str());
+		if (!oFile.is_open()) { throw std::runtime_error("Could not open output file!"); }
+	}
+	std::istream& in = iFile.is_open() ? iFile : std::cin;
+	std::ostream& os = oFile.is_open() ? oFile : std::cout;
+	if (in.peek() == 'a') {
+		Potassco::SmodelsOutput writer(os, potassco_, 0);
+		Potassco::SmodelsConvert converter(writer, potassco_);
+		Potassco::readAspif(in, converter, &error);
+	}
+	else if (std::isdigit(in.peek())) {
+		Potassco::AspifOutput out(os);
+		Potassco::SmodelsInput::Options opts;
+		if (potassco_) {
+			opts.enableClaspExt().convertEdges().convertHeuristic();
+			if (filter_) { opts.dropConverted(); }
+		}
+		Potassco::readSmodels(in, out, &error, opts);
+	}
+	else {
+		throw std::runtime_error("Unrecognized input format!");
+	}
+	iFile.close();
+	oFile.close();
+}
+
+int main(int argc, char** argv) {
+	LpConvert app;
+	return app.main(argc, argv);
+}
diff --git a/app/luaclingo/src/main.cc b/app/luaclingo/src/main.cc
new file mode 100644
index 0000000..6686327
--- /dev/null
+++ b/app/luaclingo/src/main.cc
@@ -0,0 +1,43 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#include 
+#include "gringo/lua.hh"
+#include "clingo/clingocontrol.hh"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#   define GRINGO_VISIBILITY_DEFAULT __declspec (dllexport)
+#else
+#   define GRINGO_VISIBILITY_DEFAULT __attribute__ ((visibility ("default")))
+#endif
+
+namespace {
+
+DefaultGringoModule g_module;
+
+} // namespace
+
+extern "C" GRINGO_VISIBILITY_DEFAULT int luaopen_clingo(lua_State *L) {
+    try                             { Gringo::Lua::initlib(L, g_module); }
+    catch (std::exception const &e) { luaL_error(L, e.what()); }
+    catch (...)                     { luaL_error(L, "unknown error"); }
+    return 1;
+}
+
diff --git a/app/pyclingo/src/main.cc b/app/pyclingo/src/main.cc
new file mode 100644
index 0000000..a11361c
--- /dev/null
+++ b/app/pyclingo/src/main.cc
@@ -0,0 +1,50 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+#include "Python.h"
+#include "gringo/python.hh"
+#include "clingo/clingocontrol.hh"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#   define GRINGO_VISIBILITY_DEFAULT __declspec (dllexport)
+#else
+#   define GRINGO_VISIBILITY_DEFAULT __attribute__ ((visibility ("default")))
+#endif
+
+namespace {
+
+DefaultGringoModule g_module;
+
+} // namespace
+
+#if PY_MAJOR_VERSION >= 3
+#define INITRETURN return (PyObject *)
+#define INITFAIL return nullptr;
+extern "C" GRINGO_VISIBILITY_DEFAULT PyObject *PyInit_clingo() {
+#else
+#define INITRETURN
+#define INITFAIL return;
+extern "C" GRINGO_VISIBILITY_DEFAULT void initclingo() {
+#endif
+    try                             { INITRETURN Gringo::Python::initlib(g_module); }
+    catch (std::bad_alloc const &e) { PyErr_SetString(PyExc_MemoryError, e.what()); INITFAIL }
+    catch (std::exception const &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); INITFAIL }
+    catch (...)                     { PyErr_SetString(PyExc_RuntimeError, "unknown error"); INITFAIL }
+}
+
diff --git a/app/reify/main.cc b/app/reify/main.cc
new file mode 100644
index 0000000..6eb98a8
--- /dev/null
+++ b/app/reify/main.cc
@@ -0,0 +1,102 @@
+// {{{ GPL License
+
+// This file is part of reify - a grounder for logic programs.
+// Copyright (C) 2013  Roland Kaminski
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#include 
+#include 
+#include 
+#include "reify/program.hh"
+#include "gringo/version.hh"
+
+struct ReifyOptions {
+    bool calculateSCCs = false;
+    bool reifyStep     = false;
+};
+
+class ReifyApp : public ProgramOptions::Application {
+public:
+    virtual const char* getName() const    { return "reify"; }
+
+    virtual const char* getVersion() const { return GRINGO_VERSION; }
+
+protected:
+    virtual void initOptions(ProgramOptions::OptionContext& root) {
+        using namespace ProgramOptions;
+        OptionGroup reify("Reify Options");
+        reify.addOptions()
+            ("sccs,c", flag(opts_.calculateSCCs), "calculate strongly connected components\n")
+            ("steps,s", flag(opts_.reifyStep), "add step numbers to generated facts\n");
+        root.add(reify);
+        OptionGroup basic("Basic Options");
+        basic.addOptions()
+            ("file,f,@2", storeTo(input_), "Input files")
+            ;
+        root.add(basic);
+    }
+
+    virtual void validateOptions(const ProgramOptions::OptionContext&, const ProgramOptions::ParsedOptions&, const ProgramOptions::ParsedValues&) { }
+
+    virtual void setup() { }
+
+    static bool parsePositional(std::string const &, std::string& out) {
+        out = "file";
+        return true;
+    }
+
+    virtual ProgramOptions::PosOption getPositional() const { return parsePositional; }
+
+    virtual void printHelp(const ProgramOptions::OptionContext& root) {
+        printf("%s version %s\n", getName(), getVersion());
+        printUsage();
+        ProgramOptions::FileOut out(stdout);
+        root.description(out);
+        printf("\n");
+        printUsage();
+    }
+
+    virtual void printVersion() {
+        Application::printVersion();
+        printf(
+            "Copyright (C) Roland Kaminski\n"
+            "License GPLv3+: GNU GPL version 3 or later \n"
+            "Reify is free software: you are free to change and redistribute it.\n"
+            "There is NO WARRANTY, to the extent permitted by law.\n");
+        fflush(stdout);
+    }
+
+    virtual void run() {
+        Reify::Reifier reify(std::cout, opts_.calculateSCCs, opts_.reifyStep);
+        if (input_.empty() || input_ == "-") {
+            reify.parse(std::cin);
+        }
+        else {
+            std::ifstream ifs(input_);
+            reify.parse(ifs);
+        }
+    }
+private:
+    std::string input_;
+    ReifyOptions opts_;
+};
+
+int main(int argc, char **argv) {
+    ReifyApp app;
+    return app.main(argc, argv);
+}
+
diff --git a/app/web/main.cc b/app/web/main.cc
new file mode 100644
index 0000000..dcb3c55
--- /dev/null
+++ b/app/web/main.cc
@@ -0,0 +1,69 @@
+// {{{ GPL License
+
+// This file is part of gringo - a grounder for logic programs.
+// Copyright (C) 2013  Benjamin Kaufmann
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see .
+
+// }}}
+
+#include "clingo_app.hh"
+#include 
+
+class ExitException : public std::exception {
+public:
+    ExitException(int status) : status_(status) {
+        std::ostringstream oss;
+        oss << "exited with status: " << status_;
+        msg_ = oss.str();
+    }
+    int status() const { return status_; }
+    char const *what() const noexcept { return msg_.c_str(); }
+    ~ExitException() = default;
+private:
+    std::string msg_;
+    int status_;
+};
+
+struct WebApp : ClingoApp {
+    void exit(int status) const {
+        throw ExitException(status);
+    }
+};
+
+extern "C" int run(char const *program, char const *options) {
+    try {
+        std::streambuf* orig = std::cin.rdbuf();
+        auto exit(Gringo::onExit([orig]{ std::cin.rdbuf(orig); }));
+        std::istringstream input(program);
+        std::cin.rdbuf(input.rdbuf());
+        std::vector> opts;
+        opts.emplace_back(std::initializer_list{'c','l','i','n','g','o','\0'});
+        std::istringstream iss(options);
+        for (std::istream_iterator it(iss), ie; it != ie; ++it) {
+            opts.emplace_back(it->c_str(), it->c_str() + it->size() + 1);
+        }
+        std::vector args;
+        for (auto &opt : opts) {
+            args.emplace_back(opt.data());
+        }
+        WebApp app;
+        args.emplace_back(nullptr);
+        return app.main(args.size()-2, args.data());
+    }
+    catch (ExitException const &e) {
+        return e.status();
+    }
+}
+
diff --git a/examples/c/ast.c b/examples/c/ast.c
new file mode 100644
index 0000000..1e9e63c
--- /dev/null
+++ b/examples/c/ast.c
@@ -0,0 +1,206 @@
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+typedef struct {
+  clingo_ast_term_t atom;
+  clingo_program_builder_t *builder;
+} on_statement_data;
+
+// adds atom enable to all rule bodies
+bool on_statement (clingo_ast_statement_t const *stm, on_statement_data *data) {
+  bool ret = true;
+  clingo_ast_rule_t rule;
+  clingo_ast_body_literal_t *body = NULL;
+  clingo_ast_literal_t lit;
+  clingo_ast_statement_t stm2;
+
+  // pass through all statements that are not rules
+  if (stm->type != clingo_ast_statement_type_rule) {
+    if (!clingo_program_builder_add(data->builder, stm)) { goto error; }
+    goto out;
+  }
+
+  // allocate space to hold the current rule body + one literal
+  body = (clingo_ast_body_literal_t*)malloc(sizeof(clingo_ast_body_literal_t) * (stm->rule->size + 1));
+  if (!body) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for rule body");
+    goto error;
+  }
+
+  // copy the current rule body
+  for (size_t i = 0; i < stm->rule->size; ++i) {
+    body[i] = stm->rule->body[i];
+  }
+
+  // create atom enable
+  lit.symbol   = &data->atom;
+  lit.location = data->atom.location;
+  lit.type     = clingo_ast_literal_type_symbolic;
+  lit.sign     = clingo_ast_sign_none;
+
+  // add atom enable to the rule body
+  body[stm->rule->size].location = data->atom.location;
+  body[stm->rule->size].type     = clingo_ast_body_literal_type_literal;
+  body[stm->rule->size].sign     = clingo_ast_sign_none;
+  body[stm->rule->size].literal  = &lit;
+
+  // initialize the rule
+  rule.head = stm->rule->head;
+  rule.size = stm->rule->size + 1;
+  rule.body = body;
+
+  // initialize the statement
+  stm2.location = stm->location;
+  stm2.type     = stm->type;
+  stm2.rule     = &rule;
+
+  // add the rewritten statement to the program
+  if (!clingo_program_builder_add(data->builder, &stm2)) { goto error; }
+
+  goto out;
+error:
+  ret = false;
+out:
+  if (body) { free(body); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_symbol_t sym;
+  clingo_location_t location;
+  clingo_ast_statement_t stm;
+  clingo_ast_external_t ext;
+  on_statement_data data;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // get the program builder
+  if (!clingo_control_program_builder(ctl, &data.builder)) { goto error; }
+
+  // initialize the location
+  location.begin_line   = location.end_line   = 0;
+  location.begin_column = location.end_column = 0;
+  location.begin_file   = location.end_file   = "";
+
+  // initilize atom to add
+  if (!clingo_symbol_create_id("enable", true, &sym)) { goto error; }
+  data.atom.location = location;
+  data.atom.type = clingo_ast_term_type_symbol;
+  data.atom.symbol = sym;
+
+  // begin building a program
+  if (!clingo_program_builder_begin(data.builder)) { goto error; }
+
+  // get the AST of the program
+  if (!clingo_parse_program("a :- not b. b :- not a.", (clingo_ast_callback_t*)on_statement, &data, NULL, NULL, 20)) { goto error; }
+
+  // add the external statement: #external enable.
+  ext.atom = data.atom;
+  ext.body = NULL;
+  ext.size = 0;
+  stm.location = location;
+  stm.type = clingo_ast_statement_type_external;
+  stm.external = &ext;
+  if (!clingo_program_builder_add(data.builder, &stm)) { goto error; }
+
+  // finish building a program
+  if (!clingo_program_builder_end(data.builder)) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve with external enable = false
+  printf("Solving with enable = false...\n");
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+  // solve with external enable = true
+  printf("Solving with enable = true...\n");
+  if (!clingo_control_assign_external(ctl, sym, clingo_truth_value_true)) { goto error; }
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+  // solve with external enable = false
+  printf("Solving with enable = false...\n");
+  if (!clingo_control_assign_external(ctl, sym, clingo_truth_value_false)) { goto error; }
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/backend.c b/examples/c/backend.c
new file mode 100644
index 0000000..75c51b0
--- /dev/null
+++ b/examples/c/backend.c
@@ -0,0 +1,143 @@
+#include 
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  size_t offset;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl;
+  clingo_symbolic_atoms_t *atoms;
+  clingo_backend_t *backend;
+  clingo_atom_t atom_ids[4];
+  char const *atom_strings[] = {"a", "b", "c"};
+  clingo_literal_t body[2];
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "{a; b; c}.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // get the container for symbolic atoms
+  if (!clingo_control_symbolic_atoms(ctl, &atoms)) { goto error; }
+  // get the ids of atoms a, b, and c
+  offset = 0;
+  for (char const **it = atom_strings, **ie = it + sizeof(atom_strings) / sizeof(*atom_strings); it != ie; ++it) {
+    clingo_symbol_t sym;
+    clingo_symbolic_atom_iterator_t atom_it, atom_ie;
+    clingo_literal_t lit;
+    bool equal;
+
+    // lookup the atom
+    if (!clingo_symbol_create_id(*it, true, &sym)) { goto error; }
+    if (!clingo_symbolic_atoms_find(atoms, sym, &atom_it)) { goto error; }
+    if (!clingo_symbolic_atoms_end(atoms, &atom_ie)) { goto error; }
+    if (!clingo_symbolic_atoms_iterator_is_equal_to(atoms, atom_it, atom_ie, &equal)) { goto error; }
+    assert(!equal); (void)equal;
+
+    // get the atom's id
+    if (!clingo_symbolic_atoms_literal(atoms, atom_it, &lit)) { goto error; }
+    atom_ids[offset++] = lit;
+  }
+
+  // get the backend
+  if (!clingo_control_backend(ctl, &backend)) { goto error; }
+
+  // add an additional atom (called d below)
+  if (!clingo_backend_add_atom(backend, &atom_ids[3])) { goto error; }
+
+  // add rule: d :- a, b.
+  body[0] = atom_ids[0];
+  body[1] = atom_ids[1];
+  if (!clingo_backend_rule(backend, false, &atom_ids[3], 1, body, sizeof(body)/sizeof(*body))) { goto error; }
+
+  // add rule: :- not d, c.
+  body[0] = -(clingo_literal_t)atom_ids[3];
+  body[1] = atom_ids[2];
+  if (!clingo_backend_rule(backend, false, NULL, 0, body, sizeof(body)/sizeof(*body))) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/configuration.c b/examples/c/configuration.c
new file mode 100644
index 0000000..79bb324
--- /dev/null
+++ b/examples/c/configuration.c
@@ -0,0 +1,117 @@
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+  clingo_configuration_t *conf;
+  clingo_id_t root_key, sub_key;
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // get the configuration object and its root key
+  if (!clingo_control_configuration(ctl, &conf)) { goto error; }
+  if (!clingo_configuration_root(conf, &root_key)) { goto error; }
+
+  // configure to enumerate all models
+  if (!clingo_configuration_map_at(conf, root_key, "solve.models", &sub_key)) { goto error; }
+  if (!clingo_configuration_value_set(conf, sub_key, "0")) { goto error; }
+
+  // configure the first solver to use the berkmin heuristic
+  if (!clingo_configuration_map_at(conf, root_key, "solver", &sub_key)) { goto error; }
+  if (!clingo_configuration_array_at(conf, sub_key, 0, &sub_key)) { goto error; }
+  if (!clingo_configuration_map_at(conf, sub_key, "heuristic", &sub_key)) { goto error; }
+  if (!clingo_configuration_value_set(conf, sub_key, "berkmin")) { goto error; }
+  // note that the solver entry can be used both as an array and a map
+  // if used as a map, this simply sets the configuration of the first solver and
+  // is equivalent to the code above
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "a :- not b. b :- not a.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/control.c b/examples/c/control.c
new file mode 100644
index 0000000..08f78f8
--- /dev/null
+++ b/examples/c/control.c
@@ -0,0 +1,98 @@
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "a :- not b. b :- not a.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/model.c b/examples/c/model.c
new file mode 100644
index 0000000..e9e4c91
--- /dev/null
+++ b/examples/c/model.c
@@ -0,0 +1,170 @@
+#define __STDC_FORMAT_MACROS
+#include 
+#include 
+#include 
+#include 
+
+typedef struct model_buffer {
+  clingo_symbol_t *symbols;
+  size_t           symbols_n;
+  char            *string;
+  size_t           string_n;
+} model_buffer_t;
+
+void free_model_buffer(model_buffer_t *buf) {
+  if (buf->symbols) {
+    free(buf->symbols);
+    buf->symbols   = NULL;
+    buf->symbols_n = 0;
+  }
+
+  if (buf->string) {
+    free(buf->string);
+    buf->string   = NULL;
+    buf->string_n = 0;
+  }
+}
+
+bool print_symbol(clingo_symbol_t symbol, model_buffer_t *buf) {
+  bool ret = true;
+  char *string;
+  size_t n;
+
+  // determine size of the string representation of the next symbol in the model
+  if (!clingo_symbol_to_string_size(symbol, &n)) { goto error; }
+
+  if (buf->string_n < n) {
+    // allocate required memory to hold the symbol's string
+    if (!(string = (char*)realloc(buf->string, sizeof(*buf->string) * n))) {
+      clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+      goto error;
+    }
+
+    buf->string   = string;
+    buf->string_n = n;
+  }
+
+  // retrieve the symbol's string
+  if (!clingo_symbol_to_string(symbol, buf->string, n)) { goto error; }
+  printf("%s", buf->string);
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  return ret;
+}
+
+bool print_model(clingo_model_t *model, model_buffer_t *buf, char const *label, clingo_show_type_bitset_t show) {
+  bool ret = true;
+  clingo_symbol_t *symbols;
+  size_t n;
+  clingo_symbol_t const *it, *ie;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, show, &n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (buf->symbols_n < n) {
+    if (!(symbols = (clingo_symbol_t*)malloc(sizeof(*buf->symbols) * n))) {
+      clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+      goto error;
+    }
+
+    buf->symbols   = symbols;
+    buf->symbols_n = n;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, show, buf->symbols, n)) { goto error; }
+
+  printf("%s:", label);
+
+  for (it = buf->symbols, ie = buf->symbols + n; it != ie; ++it) {
+    printf(" ");
+    if (!print_symbol(*it, buf)) { goto error; }
+  }
+
+  printf("\n");
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  return ret;
+}
+
+bool on_model(clingo_model_t *model, model_buffer_t *data, bool *goon) {
+  bool ret = true;
+  uint64_t number;
+  clingo_model_type_t type;
+  char const *type_string = "";
+
+  // get model type
+  if (!clingo_model_type(model, &type)) { goto error; }
+
+  switch ((enum clingo_model_type)type) {
+    case clingo_model_type_stable_model:          { type_string = "Stable model"; break; }
+    case clingo_model_type_brave_consequences:    { type_string = "Brave consequences"; break; }
+    case clingo_model_type_cautious_consequences: { type_string = "Cautious consequences"; break; }
+  }
+
+  // get running number of model
+  if (!clingo_model_number(model, &number)) { goto error; }
+
+  printf("%s %" PRIu64 ":\n", type_string, number);
+
+  if (!print_model(model, data, "  shown", clingo_show_type_shown)) { goto error; }
+  if (!print_model(model, data, "  atoms", clingo_show_type_atoms)) { goto error; }
+  if (!print_model(model, data, "  terms", clingo_show_type_terms)) { goto error; }
+  if (!print_model(model, data, " ~atoms", clingo_show_type_complement
+                                         | clingo_show_type_atoms)) { goto error; }
+
+  // continue solving after a model has been reported
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+  model_buffer_t buf = {NULL, 0, NULL, 0};
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "1 {a; b} 1. #show c : b. #show a/0.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, (clingo_model_callback_t*)on_model, &buf, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  free_model_buffer(&buf);
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/propagator.c b/examples/c/propagator.c
new file mode 100644
index 0000000..d2cab8c
--- /dev/null
+++ b/examples/c/propagator.c
@@ -0,0 +1,329 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// state information for individual solving threads
+typedef struct {
+  // assignment of pigeons to holes
+  // (hole number -> pigeon placement literal or zero)
+  clingo_literal_t *holes;
+  size_t size;
+} state_t;
+
+// state information for the propagator
+typedef struct {
+  // mapping from solver literals capturing pigeon placements to hole numbers
+  // (solver literal -> hole number or zero)
+  int *pigeons;
+  size_t pigeons_size;
+  // array of states
+  state_t *states;
+  size_t states_size;
+} propagator_t;
+
+// returns the offset'th numeric argument of the function symbol sym
+bool get_arg(clingo_symbol_t sym, int offset, int *num) {
+  clingo_symbol_t const *args;
+  size_t args_size;
+
+  // get the arguments of the function symbol
+  if (!clingo_symbol_arguments(sym, &args, &args_size)) { return false; }
+  // get the requested numeric argument
+  if (!clingo_symbol_number(args[offset], num)) { return false; }
+
+  return true;
+}
+
+bool init(clingo_propagate_init_t *init, propagator_t *data) {
+  // the total number of holes pigeons can be assigned too
+  int holes = 0;
+  size_t threads = clingo_propagate_init_number_of_threads(init);
+  // stores the (numeric) maximum of the solver literals capturing pigeon placements
+  // note that the code below assumes that this literal is not negative
+  // which holds for the pigeon problem but not in general
+  clingo_literal_t max = 0;
+  clingo_symbolic_atoms_t *atoms;
+  clingo_signature_t sig;
+  clingo_symbolic_atom_iterator_t atoms_it, atoms_ie;
+  // ensure that solve can be called multiple times
+  // for simplicity, the case that additional holes or pigeons to assign are grounded is not handled here
+  if (data->states != NULL) {
+    // in principle the number of threads can increase between solve calls by changing the configuration
+    // this case is not handled (elegantly) here
+    if (threads > data->states_size) {
+      clingo_set_error(clingo_error_runtime, "more threads than states");
+    }
+    return true;
+  }
+  // allocate memory for exactly one state per thread
+  if (!(data->states = (state_t*)malloc(sizeof(*data->states) * threads))) {
+    clingo_set_error(clingo_error_bad_alloc, "allocation failed");
+    return false;
+  }
+  memset(data->states, 0, sizeof(*data->states) * threads);
+  data->states_size = threads;
+
+  // the propagator monitors place/2 atoms and dectects conflicting assignments
+  // first get the symbolic atoms handle
+  if (!clingo_propagate_init_symbolic_atoms(init, &atoms)) { return false; }
+  // create place/2 signature to filter symbolic atoms with
+  if (!clingo_signature_create("place", 2, true, &sig)) { return false; }
+  // get an iterator after the last place/2 atom
+  // (atom order corresponds to grounding order (and is unpredictable))
+  if (!clingo_symbolic_atoms_end(atoms, &atoms_ie)) { return false; }
+
+  // loop over the place/2 atoms in two passes
+  // the first pass determines the maximum placement literal
+  // the second pass allocates memory for data structures based on the first pass
+  for (int pass = 0; pass < 2; ++pass) {
+    // get an iterator to the first place/2 atom
+    if (!clingo_symbolic_atoms_begin(atoms, &sig, &atoms_it)) { return false; }
+    if (pass == 1) {
+      // allocate memory for the assignemnt literal -> hole mapping
+      if (!(data->pigeons = (int*)malloc(sizeof(*data->pigeons) * (max + 1)))) {
+        clingo_set_error(clingo_error_bad_alloc, "allocation failed");
+        return false;
+      }
+      data->pigeons_size = max + 1;
+    }
+    while (true) {
+      int h;
+      bool equal;
+      clingo_literal_t lit;
+      clingo_symbol_t sym;
+
+      // stop iteration if the end is reached
+      if (!clingo_symbolic_atoms_iterator_is_equal_to(atoms, atoms_it, atoms_ie, &equal)) { return false; }
+      if (equal) { break; }
+
+      // get the solver literal for the placement atom
+      if (!clingo_symbolic_atoms_literal(atoms, atoms_it, &lit)) { return false; }
+      if (!clingo_propagate_init_solver_literal(init, lit, &lit)) { return false; }
+
+      if (pass == 0) {
+        // determine the maximum literal
+        assert(lit > 0);
+        if (lit > max) { max = lit; }
+      }
+      else {
+        // extract the hole number from the atom
+        if (!clingo_symbolic_atoms_symbol(atoms, atoms_it, &sym)) { return false; }
+        if (!get_arg(sym, 1, &h)) { return false; }
+
+        // initialize the assignemnt literal -> hole mapping
+        data->pigeons[lit] = h;
+
+        // watch the assignment literal
+        if (!clingo_propagate_init_add_watch(init, lit)) { return false; }
+
+        // update the total number of holes
+        if (h + 1 > holes)   { holes = h + 1; }
+      }
+
+      // advance to the next placement atom
+      if (!clingo_symbolic_atoms_next(atoms, atoms_it, &atoms_it)) { return false; }
+    }
+  }
+
+  // initialize the per solver thread state information
+  for (size_t i = 0; i < threads; ++i) {
+    if (!(data->states[i].holes = (clingo_literal_t*)malloc(sizeof(*data->states[i].holes) * holes))) {
+      clingo_set_error(clingo_error_bad_alloc, "allocation failed");
+      return false;
+    }
+    // initially no pigeons are assigned to any holes
+    // so the hole -> literal mapping is initialized with zero
+    // which is not a valid literal
+    memset(data->states[i].holes, 0, sizeof(*data->states[i].holes) * holes);
+    data->states[i].size = holes;
+  }
+
+  return true;
+}
+
+bool propagate(clingo_propagate_control_t *control, const clingo_literal_t *changes, size_t size, propagator_t *data) {
+  // get the thread specific state
+  state_t state = data->states[clingo_propagate_control_thread_id(control)];
+
+  // apply and check the pigeon assignments done by the solver
+  for (size_t i = 0; i < size; ++i) {
+    // the freshly assigned literal
+    clingo_literal_t lit = changes[i];
+    // a pointer to the previously assigned literal
+    clingo_literal_t *prev = state.holes + data->pigeons[lit];
+
+    // update the placement if no literal was assigned previously
+    if (*prev == 0) { *prev = lit; }
+    // create a conflicting clause and propagate it
+    else {
+      // current and previous literal must not hold together
+      clingo_literal_t clause[] = { -lit, -*prev };
+      // stores the result when adding a clause or propagationg
+      // if result is false propagation must stop for the solver to backtrack
+      bool result;
+
+      // add the clause
+      if (!clingo_propagate_control_add_clause(control, clause, sizeof(clause)/sizeof(*clause), clingo_clause_type_learnt, &result)) { return false; }
+      if (!result) { return true; }
+
+      // propagate it
+      if (!clingo_propagate_control_propagate(control, &result)) { return false; }
+      if (!result) { return true; }
+
+      // must not happen because the clause above is conflicting by construction
+      assert(false);
+    }
+  }
+
+  return true;
+}
+
+bool undo(clingo_propagate_control_t *control, const clingo_literal_t *changes, size_t size, propagator_t *data) {
+  // get the thread specific state
+  state_t state = data->states[clingo_propagate_control_thread_id(control)];
+
+  // undo the assignments made in propagate
+  for (size_t i = 0; i < size; ++i) {
+    clingo_literal_t lit = changes[i];
+    int hole = data->pigeons[lit];
+
+    if (state.holes[hole] == lit) {
+      // undo the assignment
+      state.holes[hole] = 0;
+    }
+  }
+
+  return true;
+}
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  // arguments to the pigeon program part
+  clingo_symbol_t args[2];
+  // the pigeon program part having the number of holes and pigeons as parameters
+  clingo_part_t parts[] = {{ "pigeon", args, sizeof(args)/sizeof(*args) }};
+  // parameters for the pigeon part
+  char const *params[] = {"h", "p"};
+  // create a propagator with the functions above
+  // using the default implementation for the model check
+  clingo_propagator_t prop = {
+    (bool (*) (clingo_propagate_init_t *, void *))init,
+    (bool (*) (clingo_propagate_control_t *, clingo_literal_t const *, size_t, void *))propagate,
+    (bool (*) (clingo_propagate_control_t *, clingo_literal_t const *, size_t, void *))undo,
+    NULL
+  };
+  // user data for the propagator
+  propagator_t prop_data = { NULL, 0, NULL, 0 };
+
+  // set the number of holes
+  clingo_symbol_create_number(8, &args[0]);
+  // set the number of pigeons
+  clingo_symbol_create_number(9, &args[1]);
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // register the propagator
+  if (!clingo_control_register_propagator(ctl, prop, &prop_data, false)) { goto error; }
+
+  // add a logic program to the pigeon part
+  if (!clingo_control_add(ctl, "pigeon", params, sizeof(params)/sizeof(*params),
+                          "1 { place(P,H) : H = 1..h } 1 :- P = 1..p.")) { goto error; }
+
+  // ground the pigeon part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  // free the propagator state
+  if (prop_data.pigeons) { free(prop_data.pigeons); }
+  if (prop_data.states_size > 0) {
+    for (size_t i = 0; i < prop_data.states_size; ++i) {
+      if (prop_data.states[i].holes) {
+        free(prop_data.states[i].holes);
+      }
+    }
+    free(prop_data.states);
+  }
+
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/solve-async.c b/examples/c/solve-async.c
new file mode 100644
index 0000000..ae9df0e
--- /dev/null
+++ b/examples/c/solve-async.c
@@ -0,0 +1,126 @@
+#include 
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+bool on_finish(clingo_solve_result_bitset_t result, atomic_flag *running) {
+  (void)result;
+  atomic_flag_clear(running);
+  return true;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  atomic_flag running = ATOMIC_FLAG_INIT;
+  uint64_t samples = 0;
+  uint64_t incircle = 0;
+  uint64_t x, y;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_solve_async_t *async = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "#const n = 17."
+                                                "1 { p(X); q(X) } 1 :- X = 1..n."
+                                                ":- not n+1 { p(1..n); q(1..n) }.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  atomic_flag_test_and_set(&running);
+  // solve using a model callback
+  if (!clingo_control_solve_async(ctl, on_model, NULL, (clingo_finish_callback_t*)on_finish, &running, NULL, 0, &async)) { goto error; }
+
+  // let's approximate pi
+  while (atomic_flag_test_and_set(&running)) {
+    ++samples;
+    x = rand();
+    y = rand();
+    if (x * x + y * y <= (uint64_t)RAND_MAX * RAND_MAX) { incircle+= 1; }
+  }
+
+  printf("pi = %g\n", 4.0*incircle/samples);
+
+  // get the result (and make sure the search is running because calling the finish handler is still part of the search)
+  if (!clingo_solve_async_get(async, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/solve-iteratively.c b/examples/c/solve-iteratively.c
new file mode 100644
index 0000000..551a4eb
--- /dev/null
+++ b/examples/c/solve-iteratively.c
@@ -0,0 +1,107 @@
+#include 
+#include 
+#include 
+
+bool print_model(clingo_model_t *model) {
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_iteratively_t *it = NULL;
+  clingo_model_t *model;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "a :- not b. b :- not a.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve_iteratively(ctl, NULL, 0, &it)) { goto error; }
+
+  for (;;) {
+    // get the next model
+    if (!clingo_solve_iteratively_next(it, &model)) { goto error; }
+
+    // stop if the search space has been exhausted or the requested number of models found
+    if (!model) { break; }
+    if (!print_model(model)) { goto error; }
+  }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (it)  { clingo_solve_iteratively_close(it); }
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/statistics.c b/examples/c/statistics.c
new file mode 100644
index 0000000..d655230
--- /dev/null
+++ b/examples/c/statistics.c
@@ -0,0 +1,192 @@
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+void print_prefix(int depth) {
+  for (int i = 0; i < depth; ++i) {
+    printf("  ");
+  }
+}
+
+// recursively print the statistics object
+bool print_statistics(clingo_statistics_t *stats, uint64_t key, int depth) {
+  bool ret = true;
+  clingo_statistics_type_t type;
+
+  // get the type of an entry and switch over its various values
+  if (!clingo_statistics_type(stats, key, &type)) { goto error; }
+  switch ((enum clingo_statistics_type)type) {
+    // print values
+    case clingo_statistics_type_value: {
+      double value;
+
+      // print value (with prefix for readability)
+      print_prefix(depth);
+      if (!clingo_statistics_value_get(stats, key, &value)) { goto error; }
+      printf("%g\n", value);
+
+      break;
+    }
+
+    // print arrays
+    case clingo_statistics_type_array: {
+      size_t size;
+
+      // loop over array elements
+      if (!clingo_statistics_array_size(stats, key, &size)) { goto error; }
+      for (size_t i = 0; i < size; ++i) {
+        uint64_t subkey;
+
+        // print array offset (with prefix for readability)
+        if (!clingo_statistics_array_at(stats, key, i, &subkey)) { goto error; }
+        print_prefix(depth);
+        printf("%zu:\n", i);
+
+        // recursively print subentry
+        if (!print_statistics(stats, subkey, depth+1)) { goto error; }
+      }
+      break;
+    }
+
+    // print maps
+    case clingo_statistics_type_map: {
+      size_t size;
+
+      // loop over map elements
+      if (!clingo_statistics_map_size(stats, key, &size)) { goto error; }
+      for (size_t i = 0; i < size; ++i) {
+        char const *name;
+        uint64_t subkey;
+
+        // get and print map name (with prefix for readability)
+        if (!clingo_statistics_map_subkey_name(stats, key, i, &name)) { goto error; }
+        if (!clingo_statistics_map_at(stats, key, name, &subkey)) { goto error; }
+        print_prefix(depth);
+        printf("%s:\n", name);
+
+        // recursively print subentry
+        if (!print_statistics(stats, subkey, depth+1)) { goto error; }
+      }
+    }
+
+    // this case won't occur if the statistics are traversed like this
+    case clingo_statistics_type_empty: { goto out; }
+  }
+
+  goto out;
+error:
+  ret = false;
+out:
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+  clingo_configuration_t *conf;
+  clingo_id_t conf_root, conf_sub;
+  clingo_statistics_t *stats;
+  uint64_t stats_key;
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // get the configuration object and its root key
+  if (!clingo_control_configuration(ctl, &conf)) { goto error; }
+  if (!clingo_configuration_root(conf, &conf_root)) { goto error; }
+  // and set the statistics level to one to get more statistics
+  if (!clingo_configuration_map_at(conf, conf_root, "stats", &conf_sub)) { goto error; }
+  if (!clingo_configuration_value_set(conf, conf_sub, "1")) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "a :- not b. b :- not a.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  // get the statistics object, get the root key, then print the statistics recursively
+  if (!clingo_control_statistics(ctl, &stats)) { goto error; }
+  if (!clingo_statistics_root(stats, &stats_key)) { goto error; }
+  if (!print_statistics(stats, stats_key, 0)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/symbol.c b/examples/c/symbol.c
new file mode 100644
index 0000000..f61b407
--- /dev/null
+++ b/examples/c/symbol.c
@@ -0,0 +1,101 @@
+#define __STDC_FORMAT_MACROS
+#include 
+#include 
+#include 
+#include 
+#include 
+
+typedef struct {
+  char            *string;
+  size_t           string_n;
+} string_buffer_t;
+
+void free_string_buffer(string_buffer_t *buf) {
+  if (buf->string) {
+    free(buf->string);
+    buf->string   = NULL;
+    buf->string_n = 0;
+  }
+}
+
+bool print_symbol(clingo_symbol_t symbol, string_buffer_t *buf) {
+  bool ret = true;
+  char *string;
+  size_t n;
+
+  // determine size of the string representation of the next symbol in the model
+  if (!clingo_symbol_to_string_size(symbol, &n)) { goto error; }
+
+  if (buf->string_n < n) {
+    // allocate required memory to hold the symbol's string
+    if (!(string = (char*)realloc(buf->string, sizeof(*buf->string) * n))) {
+      clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+      goto error;
+    }
+
+    buf->string   = string;
+    buf->string_n = n;
+  }
+
+  // retrieve the symbol's string
+  if (!clingo_symbol_to_string(symbol, buf->string, n)) { goto error; }
+  printf("%s", buf->string);
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  return ret;
+}
+
+int main() {
+  char const *error_message;
+  int ret = 0;
+  clingo_symbol_t symbols[3];
+  string_buffer_t buf = { NULL, 0 };
+  clingo_symbol_t const *args;
+  size_t size;
+
+  // create a number, identifier (function without arguments), and a function symbol
+  clingo_symbol_create_number(42, &symbols[0]);
+  if (!clingo_symbol_create_id("x", true, &symbols[1])) { goto error; }
+  if (!clingo_symbol_create_function("x", symbols, 2, true, &symbols[2])) { goto error; }
+
+  // print the symbols along with their hash values
+  for (size_t i = 0; i < sizeof(symbols) / sizeof(*symbols); ++i) {
+    printf("the hash of ");
+    if (!print_symbol(symbols[i], &buf)) { goto error; }
+    printf(" is %zu\n", clingo_symbol_hash(symbols[i]));
+  }
+
+  // compare symbols
+  if (!clingo_symbol_arguments(symbols[2], &args, &size)) { goto error; }
+  assert(size == 2);
+  // equal to comparison
+  for (size_t i = 0; i < size; ++i) {
+    if (!print_symbol(symbols[0], &buf)) { goto error; }
+    printf(" %s ", clingo_symbol_is_equal_to(symbols[0], args[i]) ? "is equal to" : "is not equal to");
+    if (!print_symbol(args[i], &buf)) { goto error; }
+    printf("\n");
+  }
+  // less than comparison
+  if (!print_symbol(symbols[0], &buf)) { goto error; }
+  printf(" %s ", clingo_symbol_is_less_than(symbols[0], symbols[1]) ? "is less than" : "is not less than");
+  if (!print_symbol(symbols[1], &buf)) { goto error; }
+  printf("\n");
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  free_string_buffer(&buf);
+
+  return ret;
+}
+
diff --git a/examples/c/symbolic-atoms.c b/examples/c/symbolic-atoms.c
new file mode 100644
index 0000000..e697b73
--- /dev/null
+++ b/examples/c/symbolic-atoms.c
@@ -0,0 +1,120 @@
+#include 
+#include 
+#include 
+
+typedef struct string_buffer {
+  char   *string;
+  size_t  string_n;
+} string_buffer_t;
+
+void free_string_buffer(string_buffer_t *buf) {
+  if (buf->string) {
+    free(buf->string);
+    buf->string   = NULL;
+    buf->string_n = 0;
+  }
+}
+
+bool print_symbol(clingo_symbol_t symbol, string_buffer_t *buf) {
+  bool ret = true;
+  char *string;
+  size_t n;
+
+  // determine size of the string representation of the next symbol in the model
+  if (!clingo_symbol_to_string_size(symbol, &n)) { goto error; }
+
+  if (buf->string_n < n) {
+    // allocate required memory to hold the symbol's string
+    if (!(string = (char*)realloc(buf->string, sizeof(*buf->string) * n))) {
+      clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+      goto error;
+    }
+
+    buf->string   = string;
+    buf->string_n = n;
+  }
+
+  // retrieve the symbol's string
+  if (!clingo_symbol_to_string(symbol, buf->string, n)) { goto error; }
+
+  printf("%s", buf->string);
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  string_buffer_t buf = {NULL, 0};
+  int ret = 0;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+  clingo_symbolic_atoms_t *atoms;
+  clingo_symbolic_atom_iterator_t it_atoms, ie_atoms;
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0, "a. {b}. #external c.")) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // get symbolic atoms
+  if (!clingo_control_symbolic_atoms(ctl, &atoms)) { goto error; }
+
+  // get begin and end iterator
+  if (!clingo_symbolic_atoms_begin(atoms, NULL, &it_atoms)) { goto error; }
+
+  if (!clingo_symbolic_atoms_end(atoms, &ie_atoms)) { goto error; }
+
+  printf("Symbolic atoms:\n");
+
+  for (;;) {
+    bool equal, fact, external;
+    clingo_symbol_t symbol;
+
+    // check if we are at the end of the sequence
+    if (!clingo_symbolic_atoms_iterator_is_equal_to(atoms, it_atoms, ie_atoms, &equal)) { goto error; }
+
+    if (equal) { break; }
+
+    // get the associated symbol
+    if (!clingo_symbolic_atoms_symbol(atoms, it_atoms, &symbol)) { goto error; }
+
+    // determine if the atom is fact or external
+    if (!clingo_symbolic_atoms_is_fact(atoms, it_atoms, &fact)) { goto error; }
+    if (!clingo_symbolic_atoms_is_external(atoms, it_atoms, &external)) { goto error; }
+
+    printf("  ");
+
+    if (!print_symbol(symbol, &buf)) { goto error; }
+    if (fact) { printf(", fact"); }
+    if (external) { printf(", external"); }
+
+    printf("\n");
+
+    // advance the next element in the sequence
+    if (!clingo_symbolic_atoms_next(atoms, it_atoms, &it_atoms)) { goto error; }
+  }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  free_string_buffer(&buf);
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/theory-atoms.c b/examples/c/theory-atoms.c
new file mode 100644
index 0000000..0954672
--- /dev/null
+++ b/examples/c/theory-atoms.c
@@ -0,0 +1,149 @@
+#include 
+#include 
+#include 
+#include 
+
+bool on_model(clingo_model_t *model, void *data, bool *goon) {
+  (void)data;
+  bool ret = true;
+  clingo_symbol_t *atoms = NULL;
+  size_t atoms_n;
+  clingo_symbol_t const *it, *ie;
+  char *str = NULL;
+  size_t str_n = 0;
+
+  // determine the number of (shown) symbols in the model
+  if (!clingo_model_symbols_size(model, clingo_show_type_shown, &atoms_n)) { goto error; }
+
+  // allocate required memory to hold all the symbols
+  if (!(atoms = (clingo_symbol_t*)malloc(sizeof(*atoms) * atoms_n))) {
+    clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for atoms");
+    goto error;
+  }
+
+  // retrieve the symbols in the model
+  if (!clingo_model_symbols(model, clingo_show_type_shown, atoms, atoms_n)) { goto error; }
+
+  printf("Model:");
+
+  for (it = atoms, ie = atoms + atoms_n; it != ie; ++it) {
+    size_t n;
+    char *str_new;
+
+    // determine size of the string representation of the next symbol in the model
+    if (!clingo_symbol_to_string_size(*it, &n)) { goto error; }
+
+    if (str_n < n) {
+      // allocate required memory to hold the symbol's string
+      if (!(str_new = (char*)realloc(str, sizeof(*str) * n))) {
+        clingo_set_error(clingo_error_bad_alloc, "could not allocate memory for symbol's string");
+        goto error;
+      }
+
+      str = str_new;
+      str_n = n;
+    }
+
+    // retrieve the symbol's string
+    if (!clingo_symbol_to_string(*it, str, n)) { goto error; }
+
+    printf(" %s", str);
+  }
+
+  printf("\n");
+  *goon = true;
+  goto out;
+
+error:
+  ret = false;
+
+out:
+  if (atoms) { free(atoms); }
+  if (str)   { free(str); }
+
+  return ret;
+}
+
+int main(int argc, char const **argv) {
+  char const *error_message;
+  int ret = 0;
+  size_t size;
+  clingo_solve_result_bitset_t solve_ret;
+  clingo_control_t *ctl = NULL;
+  clingo_part_t parts[] = {{ "base", NULL, 0 }};
+  clingo_theory_atoms_t *atoms;
+  clingo_literal_t lit = 0;
+
+  // create a control object and pass command line arguments
+  if (!clingo_control_new(argv+1, argc-1, NULL, NULL, 20, &ctl) != 0) { goto error; }
+
+  // add a logic program to the base part
+  if (!clingo_control_add(ctl, "base", NULL, 0,
+    "#theory t {"
+    "  term   { + : 1, binary, left };"
+    "  &a/0 : term, any;"
+    "  &b/1 : term, {=}, term, any"
+    "}."
+    "x :- &a { 1+2 }."
+    "y :- &b(3) { } = 17."
+    )) { goto error; }
+
+  // ground the base part
+  if (!clingo_control_ground(ctl, parts, 1, NULL, NULL)) { goto error; }
+
+  // get the theory atoms container
+  if (!clingo_control_theory_atoms(ctl, &atoms)) { goto error; }
+
+  // print the number of grounded theory atoms
+  if (!clingo_theory_atoms_size(atoms, &size)) { goto error; }
+  printf("number of grounded theory atoms: %zu\n", size);
+
+  // verify that theory atom b has a guard
+  for (clingo_id_t atom = 0; atom < size; ++atom) {
+    clingo_id_t term;
+    char const *name;
+
+    // get the term associated with the theory atom
+    if (!clingo_theory_atoms_atom_term(atoms, atom, &term)) { goto error; }
+    // get the name associated with the theory atom
+    if (!clingo_theory_atoms_term_name(atoms, term, &name)) { goto error; }
+    // we got theory atom b/1 here
+    if (strcmp(name, "b") == 0) {
+      bool guard;
+      if (!clingo_theory_atoms_atom_has_guard(atoms, atom, &guard)) { goto error; }
+      printf("theory atom b/1 has a guard: %s\n", guard ? "true" : "false");
+      // get the literal associated with the theory atom
+      if (!clingo_theory_atoms_atom_literal(atoms, atom, &lit)) { goto error; }
+      break;
+    }
+  }
+
+  // use the backend to assume that the theory atom is true
+  // (note that only symbolic literals can be passed as assumptions to a solve call;
+  // the backend accepts any aspif literal)
+  if (lit != 0) {
+    clingo_backend_t *backend;
+
+    // get the backend
+    if (!clingo_control_backend(ctl, &backend)) { goto error; }
+    // add the assumption
+    if (!clingo_backend_assume(backend, &lit, 1)) { goto error; }
+  }
+
+  // solve using a model callback
+  if (!clingo_control_solve(ctl, on_model, NULL, NULL, 0, &solve_ret)) { goto error; }
+
+  goto out;
+
+error:
+  if (!(error_message = clingo_error_message())) { error_message = "error"; }
+
+  printf("%s\n", error_message);
+  ret = clingo_error_code();
+
+out:
+  if (ctl) { clingo_control_free(ctl); }
+
+  return ret;
+}
+
diff --git a/examples/c/version.c b/examples/c/version.c
new file mode 100644
index 0000000..2676c8a
--- /dev/null
+++ b/examples/c/version.c
@@ -0,0 +1,14 @@
+#include 
+#include 
+#include 
+
+int main() {
+  int major, minor, revision;
+
+  clingo_version(&major, &minor, &revision);
+
+  printf("Hello, this is clingo version %d.%d.%d.\n", major, minor, revision);
+
+  return 0;
+}
+
diff --git a/examples/clingo/addclause/README b/examples/clingo/addclause/README
new file mode 100644
index 0000000..e36136c
--- /dev/null
+++ b/examples/clingo/addclause/README
@@ -0,0 +1,5 @@
+This example shows how to add clauses/nogoods in the model callback.
+
+Example calls:
+    clingo addclause-py.lp 0
+    clingo addclause-lua.lp 0
diff --git a/examples/clingo/addclause/addclause-lua.lp b/examples/clingo/addclause/addclause-lua.lp
new file mode 100644
index 0000000..e178b40
--- /dev/null
+++ b/examples/clingo/addclause/addclause-lua.lp
@@ -0,0 +1,18 @@
+#script (lua)
+
+function main(prg)
+    on_model = function (m)
+        m.context:add_clause({{clingo.Function("a"), false}, {clingo.Function("b"), false}})
+        m.context:add_nogood({{clingo.Function("c"), true}, {clingo.Function("d"), true}})
+    end
+
+    prg.configuration.solve.models = 0
+    prg:ground({{"base", {}}})
+    prg:solve(on_model)
+    print "and again"
+    prg:solve()
+end
+
+#end.
+
+2 { a; b; c; d }.
diff --git a/examples/clingo/addclause/addclause-py.lp b/examples/clingo/addclause/addclause-py.lp
new file mode 100644
index 0000000..8f2d916
--- /dev/null
+++ b/examples/clingo/addclause/addclause-py.lp
@@ -0,0 +1,18 @@
+#script (python)
+
+import clingo
+
+def main(prg):
+    def on_model(m):
+        m.context.add_clause([(clingo.Function("a"), False), (clingo.Function("b"), False)])
+        m.context.add_nogood([(clingo.Function("c"), True), (clingo.Function("d"), True)])
+
+    prg.configuration.solve.models = 0
+    prg.ground([("base", [])])
+    prg.solve(on_model = on_model)
+    print "and again"
+    prg.solve()
+
+#end.
+
+2 { a; b; c; d }.
diff --git a/examples/clingo/blocksworld/README b/examples/clingo/blocksworld/README
new file mode 100644
index 0000000..eef6c11
--- /dev/null
+++ b/examples/clingo/blocksworld/README
@@ -0,0 +1,13 @@
+The input files used to solve expansible blocksworld problems with clingo are:
+
+- world.lp: clingo encoding consisting of several program parts
+
+- blocks_01.lp: base facts providing initial and goal conditions for six blocks
+
+- lua.lp: routines for incremental grounding and solving w.r.t. blocks and time
+
+- lua_interpret.lp: main procedure for reading and executing code
+
+- control_01.lua: lua instructions for successive solving based on blocks_01.lp
+
+See control_01.out for an example invocation and corresponding output.
diff --git a/examples/clingo/blocksworld/blocks_01.lp b/examples/clingo/blocksworld/blocks_01.lp
new file mode 100644
index 0000000..a1842ac
--- /dev/null
+++ b/examples/clingo/blocksworld/blocks_01.lp
@@ -0,0 +1,27 @@
+#program base_2.
+
+init_above(2,1).
+goal_below(2,1).
+
+#program base_3.
+
+init_above(3,2).
+goal_below(3,1).
+
+#program base_4.
+
+init_above(4,2).
+init_below(4,3).
+goal_above(4,3).
+goal_below(4,1).
+
+#program base_5.
+
+init_above(5,1).
+init_below(5,3).
+goal_above(5,2).
+
+#program base_6.
+
+init_above(6,1).
+goal_below(6,3).
diff --git a/examples/clingo/blocksworld/control_01.lua b/examples/clingo/blocksworld/control_01.lua
new file mode 100644
index 0000000..a6071ad
--- /dev/null
+++ b/examples/clingo/blocksworld/control_01.lua
@@ -0,0 +1,11 @@
+setdebugg(true)
+-- setdebugs(false)
+for i = 1, 4 do
+  parts = {}
+  addblock(0)
+  incsolve()
+end
+addblock(1)
+incsolve()
+addblock(0)
+incsolve()
diff --git a/examples/clingo/blocksworld/control_01.out b/examples/clingo/blocksworld/control_01.out
new file mode 100644
index 0000000..e638c1b
--- /dev/null
+++ b/examples/clingo/blocksworld/control_01.out
@@ -0,0 +1,235 @@
+$ cat control_01.lua | clingo lua.lp blocks_01.lp world.lp lua_interpret.lp 0
+
+clingo version 4.1
+Reading from lua.lp ...
+Ground: base_1
+Ground: init(1,0)
+Ground: state(1,0)
+=============
+TIME 0
+Solving...
+Answer: 1
+order(-1,1,0,0)
+SATISFIABLE
+=============
+Ground: base_2
+Ground: init(2,0)
+Ground: state(2,0)
+=============
+TIME 0
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(1)
+Ground: state(1,1)
+Ground: move(1,1)
+Ground: state(2,1)
+Ground: move(2,1)
+=============
+TIME 1
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(2)
+Ground: state(1,2)
+Ground: move(1,2)
+Ground: state(2,2)
+Ground: move(2,2)
+=============
+TIME 2
+Solving...
+Answer: 1
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,0,1) object(2,1) target(0,1) order(-1,1,0,2) order(1,2,1,2) order(-1,2,0,2) object(1,2) target(2,2)
+SATISFIABLE
+=============
+Ground: base_3
+Ground: init(3,0)
+Ground: state(3,0)
+Ground: move(3,1)
+Ground: state(3,1)
+Ground: move(3,2)
+Ground: state(3,2)
+=============
+TIME 2
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(3)
+Ground: state(1,3)
+Ground: move(1,3)
+Ground: state(2,3)
+Ground: move(2,3)
+Ground: state(3,3)
+Ground: move(3,3)
+=============
+TIME 3
+Solving...
+Answer: 1
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,1,1) target(0,1) order(-1,1,0,2) order(-1,2,0,2) object(2,2) order(-1,3,2,0) order(-1,3,0,1) order(1,3,2,2) order(-1,3,0,2) object(3,1) target(3,2) order(-1,1,0,3) order(1,2,1,3) order(-1,2,0,3) order(1,3,2,3) order(-1,3,0,3) object(1,3) target(2,3)
+SATISFIABLE
+=============
+Ground: base_4
+Ground: init(4,0)
+Ground: state(4,0)
+Ground: move(4,1)
+Ground: state(4,1)
+Ground: move(4,2)
+Ground: state(4,2)
+Ground: move(4,3)
+Ground: state(4,3)
+=============
+TIME 3
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(4)
+Ground: state(1,4)
+Ground: move(1,4)
+Ground: state(2,4)
+Ground: move(2,4)
+Ground: state(3,4)
+Ground: move(3,4)
+Ground: state(4,4)
+Ground: move(4,4)
+=============
+TIME 4
+Solving...
+Answer: 1
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,1,1) target(0,1) order(-1,1,0,2) order(-1,2,1,2) order(-1,3,2,0) order(-1,3,0,1) order(-1,3,0,2) object(3,1) target(3,2) order(-1,1,0,3) order(-1,2,0,3) order(1,3,2,3) order(-1,3,0,3) object(2,3) order(1,4,3,0) order(-1,4,2,0) order(-1,4,2,1) order(-1,4,3,2) order(1,4,2,3) order(-1,4,3,3) object(4,2) target(4,3) order(-1,1,0,4) order(1,2,1,4) order(-1,2,0,4) order(1,3,2,4) order(-1,3,0,4) order(1,4,2,4) order(-1,4,3,4) object(1,4) target(2,4)
+SATISFIABLE
+=============
+Ground: base_5
+Ground: init(5,1)
+Ground: state(5,1)
+Ground: move(5,1)
+Ground: move(5,2)
+Ground: state(5,2)
+Ground: move(5,3)
+Ground: state(5,3)
+Ground: move(5,4)
+Ground: state(5,4)
+=============
+TIME 4
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(5)
+Ground: state(1,5)
+Ground: move(1,5)
+Ground: state(2,5)
+Ground: move(2,5)
+Ground: state(3,5)
+Ground: move(3,5)
+Ground: state(4,5)
+Ground: move(4,5)
+Ground: state(5,5)
+Ground: move(5,5)
+=============
+TIME 5
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(6)
+Ground: state(1,6)
+Ground: move(1,6)
+Ground: state(2,6)
+Ground: move(2,6)
+Ground: state(3,6)
+Ground: move(3,6)
+Ground: state(4,6)
+Ground: move(4,6)
+Ground: state(5,6)
+Ground: move(5,6)
+=============
+TIME 6
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(7)
+Ground: state(1,7)
+Ground: move(1,7)
+Ground: state(2,7)
+Ground: move(2,7)
+Ground: state(3,7)
+Ground: move(3,7)
+Ground: state(4,7)
+Ground: move(4,7)
+Ground: state(5,7)
+Ground: move(5,7)
+=============
+TIME 7
+Solving...
+Answer: 1
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,1,1) order(-1,1,0,2) order(-1,2,1,2) target(0,2) order(-1,3,2,0) order(-1,3,2,1) order(-1,3,0,2) object(3,1) object(3,2) order(-1,1,0,3) order(-1,2,1,3) order(-1,3,0,3) target(0,3) order(1,4,3,0) order(-1,4,2,0) order(1,4,3,1) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,1,0,4) order(-1,2,1,4) order(-1,3,0,4) order(-1,4,3,4) object(4,4) target(3,4) order(1,5,3,1) order(-1,5,4,1) order(-1,5,4,2) order(-1,5,0,3) order(-1,5,0,4) object(5,3) target(5,1) order(-1,1,0,5) order(-1,2,0,5) order(1,3,2,5) order(-1,3,0,5) order(1,4,2,5) order(-1,4,3,5) order(-1,5,0,5) object(2,5) target(4,5) order(-1,1,0,6) order(1,2,1,6) order(-1,2,0,6) order(1,3,2,6) order(-1,3,0,6) order(1,4,2,6) order(-1,4,3,6) order(-1,5,0,6) object(1,6) target(2,6) order(-1,1,0,7) order(1,2,1,7) order(-1,2,0,7) order(1,3,2,7) order(-1,3,0,7) order(1,4,2,7) order(-1,4,3,7) order(-1,5,1,7) object(5,7) target(1,7)
+Answer: 2
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,1,1) order(-1,1,0,2) order(-1,2,1,2) target(0,2) order(-1,3,2,0) order(-1,3,2,1) order(-1,3,0,2) object(3,1) object(3,2) order(-1,1,0,3) order(-1,2,1,3) order(-1,3,0,3) target(0,3) order(1,4,3,0) order(-1,4,2,0) order(1,4,3,1) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,1,0,4) order(-1,2,1,4) order(-1,3,0,4) order(-1,4,3,4) object(4,4) target(3,4) order(1,5,3,1) order(-1,5,4,1) order(-1,5,4,2) order(-1,5,0,3) order(-1,5,0,4) object(5,3) target(5,1) order(-1,1,0,5) order(-1,2,0,5) order(1,3,2,5) order(-1,3,0,5) order(1,4,2,5) order(-1,4,3,5) order(-1,5,0,5) object(2,5) target(4,5) order(-1,1,0,6) order(-1,2,0,6) order(1,3,2,6) order(-1,3,0,6) order(1,4,2,6) order(-1,4,3,6) order(-1,5,2,6) object(5,6) target(2,6) order(-1,1,0,7) order(1,2,1,7) order(-1,2,0,7) order(1,3,2,7) order(-1,3,0,7) order(1,4,2,7) order(-1,4,3,7) order(1,5,1,7) order(-1,5,2,7) object(1,7) target(5,7)
+SATISFIABLE
+=============
+Ground: base_6
+Ground: init(6,0)
+Ground: state(6,0)
+Ground: move(6,1)
+Ground: state(6,1)
+Ground: move(6,2)
+Ground: state(6,2)
+Ground: move(6,3)
+Ground: state(6,3)
+Ground: move(6,4)
+Ground: state(6,4)
+Ground: move(6,5)
+Ground: state(6,5)
+Ground: move(6,6)
+Ground: state(6,6)
+Ground: move(6,7)
+Ground: state(6,7)
+=============
+TIME 7
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(8)
+Ground: state(1,8)
+Ground: move(1,8)
+Ground: state(2,8)
+Ground: move(2,8)
+Ground: state(3,8)
+Ground: move(3,8)
+Ground: state(4,8)
+Ground: move(4,8)
+Ground: state(5,8)
+Ground: move(5,8)
+Ground: state(6,8)
+Ground: move(6,8)
+=============
+TIME 8
+Solving...
+UNSATISFIABLE
+=============
+Ground: table(9)
+Ground: state(1,9)
+Ground: move(1,9)
+Ground: state(2,9)
+Ground: move(2,9)
+Ground: state(3,9)
+Ground: move(3,9)
+Ground: state(4,9)
+Ground: move(4,9)
+Ground: state(5,9)
+Ground: move(5,9)
+Ground: state(6,9)
+Ground: move(6,9)
+=============
+TIME 9
+Solving...
+Answer: 1
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,1,1) order(-1,1,0,2) order(-1,2,1,2) target(0,2) order(-1,3,2,0) order(-1,3,2,1) order(-1,3,0,2) object(3,1) object(3,2) order(-1,1,0,3) order(-1,2,1,3) order(-1,3,0,3) target(0,3) order(1,4,3,0) order(-1,4,2,0) order(1,4,3,1) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,1,0,4) order(-1,2,1,4) order(-1,3,0,4) order(-1,4,2,4) target(0,4) order(1,5,3,1) order(-1,5,4,1) order(-1,5,4,2) order(-1,5,0,3) order(-1,5,0,4) object(5,3) target(5,1) order(-1,1,0,5) order(-1,2,1,5) order(-1,3,0,5) order(-1,4,2,5) order(-1,5,0,5) object(3,5) order(-1,1,0,6) order(-1,2,1,6) order(-1,3,0,6) order(-1,4,3,6) order(-1,5,0,6) object(4,6) target(3,6) order(-1,1,0,7) order(-1,2,0,7) order(1,3,2,7) order(-1,3,0,7) order(1,4,2,7) order(-1,4,3,7) order(-1,5,0,7) object(2,7) target(4,7) order(1,6,3,0) order(-1,6,4,0) order(1,6,5,1) order(-1,6,4,1) order(1,6,5,2) order(-1,6,4,2) order(-1,6,4,3) order(-1,6,0,4) order(1,6,3,5) order(-1,6,0,5) order(1,6,3,6) order(-1,6,0,6) order(1,6,3,7) order(-1,6,0,7) object(6,4) target(6,5) order(-1,1,0,8) order(-1,2,0,8) order(1,3,2,8) order(-1,3,0,8) order(1,4,2,8) order(-1,4,3,8) order(-1,5,2,8) order(1,6,3,8) order(-1,6,0,8) object(5,8) target(2,8) order(-1,1,0,9) order(1,2,1,9) order(-1,2,0,9) order(1,3,2,9) order(-1,3,0,9) order(1,4,2,9) order(-1,4,3,9) order(1,5,1,9) order(-1,5,2,9) order(1,6,3,9) order(-1,6,0,9) object(1,9) target(5,9)
+Answer: 2
+order(-1,1,0,0) order(-1,2,1,0) order(-1,1,0,1) order(-1,2,1,1) order(-1,1,0,2) order(-1,2,1,2) target(0,2) order(-1,3,2,0) order(-1,3,2,1) order(-1,3,0,2) object(3,1) object(3,2) order(-1,1,0,3) order(-1,2,1,3) order(-1,3,0,3) target(0,3) order(1,4,3,0) order(-1,4,2,0) order(1,4,3,1) order(-1,4,2,1) order(-1,4,2,2) order(-1,4,2,3) order(-1,1,0,4) order(-1,2,1,4) order(-1,3,0,4) order(-1,4,2,4) target(0,4) order(1,5,3,1) order(-1,5,4,1) order(-1,5,4,2) order(-1,5,0,3) order(-1,5,0,4) object(5,3) target(5,1) order(-1,1,0,5) order(-1,2,1,5) order(-1,3,0,5) order(-1,4,2,5) order(-1,5,0,5) object(3,5) order(-1,1,0,6) order(-1,2,1,6) order(-1,3,0,6) order(-1,4,3,6) order(-1,5,0,6) object(4,6) target(3,6) order(-1,1,0,7) order(-1,2,0,7) order(1,3,2,7) order(-1,3,0,7) order(1,4,2,7) order(-1,4,3,7) order(-1,5,0,7) object(2,7) target(4,7) order(1,6,3,0) order(-1,6,4,0) order(1,6,5,1) order(-1,6,4,1) order(1,6,5,2) order(-1,6,4,2) order(-1,6,4,3) order(-1,6,0,4) order(1,6,3,5) order(-1,6,0,5) order(1,6,3,6) order(-1,6,0,6) order(1,6,3,7) order(-1,6,0,7) object(6,4) target(6,5) order(-1,1,0,8) order(1,2,1,8) order(-1,2,0,8) order(1,3,2,8) order(-1,3,0,8) order(1,4,2,8) order(-1,4,3,8) order(-1,5,0,8) order(1,6,3,8) order(-1,6,0,8) object(1,8) target(2,8) order(-1,1,0,9) order(1,2,1,9) order(-1,2,0,9) order(1,3,2,9) order(-1,3,0,9) order(1,4,2,9) order(-1,4,3,9) order(-1,5,1,9) order(1,6,3,9) order(-1,6,0,9) object(5,9) target(1,9)
+SATISFIABLE
+=============
+SATISFIABLE
+
+Models       : 7
+Calls        : 15
+Time         : 0.068s (Solving: 0.01s 1st Model: 0.00s Unsat: 0.01s)
+CPU Time     : 0.060s
diff --git a/examples/clingo/blocksworld/lua.lp b/examples/clingo/blocksworld/lua.lp
new file mode 100644
index 0000000..a6c0c85
--- /dev/null
+++ b/examples/clingo/blocksworld/lua.lp
@@ -0,0 +1,126 @@
+#script(lua)
+
+-- VARIABLES --
+
+parts = {}
+
+-- indicate solving approaches or grounding instructions, respectively
+debugs = true -- false
+debugg = false -- true
+
+-- maximum time stamp for solving approaches
+limit = math.huge
+
+-- smallest and current time stamp
+iinit = 0
+time = 0
+
+-- sequence number for blocks
+block = 0
+
+-- FUNCTIONS --
+
+-- integrate a block appearing at time stamp "init"
+
+function addblock(init)
+  if limit < init then time = init end
+  if limit < time then return end
+  if init < iinit then
+    for t = init+1, iinit do
+      if debugg then print("Ground: table("..t..")") end
+      parts[#parts+1] = {"table", {t}}
+      for k = 1, block do
+        if debugg then print("Ground: move("..k..","..t..")") end
+        parts[#parts+1] = {"move", {k, t}}
+      end
+    end
+    iinit = init
+  end
+  rollout(init)
+  block = block+1
+  if debugg then print("Ground: base_"..block) end
+  parts[#parts+1] = {"base_"..block, {}}
+  if debugg then print("Ground: init("..block..","..init..")") end
+  parts[#parts+1] = {"init", {block, init}}
+  if debugg then print("Ground: state("..block..","..init..")") end
+  parts[#parts+1] = {"state", {block, init}}
+  for t = iinit+1, time do
+    if debugg then print("Ground: move("..block..","..t..")") end
+    parts[#parts+1] = {"move", {block, t}}
+    if init < t then
+      if debugg then print("Ground: state("..block..","..t..")") end
+      parts[#parts+1] = {"state", {block, t}}
+    end
+  end
+end
+
+-- ground encoding parts beyond current time stamp up to "next"
+
+function rollout(next)
+  if limit < next then
+    time = next
+    return
+  end
+  if time < next then
+    time = time+1
+    if debugg then print("Ground: table("..time..")") end
+    parts[#parts+1] = {"table", {time}}
+    for k = 1, block do
+      if debugg then print("Ground: state("..k..","..time..")") end
+      parts[#parts+1] = {"state", {k, time}}
+      if debugg then print("Ground: move("..k..","..time..")") end
+      parts[#parts+1] = {"move", {k, time}}
+    end
+    rollout(next)
+  end
+end
+
+-- incrementally solve and ground for increasing time stamps until a plan exists
+
+function incsolve()
+  if limit < time then return end
+  if debugs then
+    print("=============")
+    print("TIME "..time)
+  end
+  prg:ground(parts)
+  parts = {}
+  ret = prg:solve()
+  if debugs then
+    if     ret.satisfiable   then print "SATISFIABLE"
+    elseif ret.unsatisfiable then print "UNSATISFIABLE"
+    elseif ret.unknown       then print "UNKNOWN"
+    end
+    print("=============")
+  end
+  if ret.unsatisfiable then
+    rollout(time+1)
+    incsolve()
+  end
+end
+
+-- AUXILIARY FUNCTIONS --
+
+function setdebugg(debug)
+  debugg = debug
+end
+
+function setdebugs(debug)
+  debugs = debug
+end
+
+function setdebug(debug)
+  debugg = debug
+  debugs = debug
+end
+
+function setlimit(custom)
+  limit = custom
+end
+
+function setiinit(custom)
+  iinit = custom
+  time = iinit
+end
+
+#end.
diff --git a/examples/clingo/blocksworld/lua_interpret.lp b/examples/clingo/blocksworld/lua_interpret.lp
new file mode 100644
index 0000000..11cf8c2
--- /dev/null
+++ b/examples/clingo/blocksworld/lua_interpret.lp
@@ -0,0 +1,21 @@
+#script(lua)
+
+prg = nil
+
+function main(program)
+  prg = program
+  exec = ""
+  repeat
+    line = io.read()
+    if line ~= nil then
+      exec = exec..line.."\n"
+      func = loadstring(exec)
+      if func ~= nil then
+        func()
+        exec = ""
+      end
+    end
+  until line == nil
+end
+
+#end.
diff --git a/examples/clingo/blocksworld/world.lp b/examples/clingo/blocksworld/world.lp
new file mode 100644
index 0000000..fba9c47
--- /dev/null
+++ b/examples/clingo/blocksworld/world.lp
@@ -0,0 +1,130 @@
+% show instances of selected predicates only
+#show.
+
+% output stack representation
+#show order/4.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for generating states providing relative block positions, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program state(k,t).
+
+% a block's scope includes the table (labeled 0) and blocks with smaller numbers
+scope(k,0,t).
+scope(k,I,t) :- scope(I,0,t), I < k.
+
+% order(1,k,I,t) provides the closest block I in scope above k, if any at time t
+#count{ I : order(1,k,I,t) : scope(k,I,t), 0 < I } 1.
+
+% order(-1,k,I,t) provides the closest block/table I in scope below k at time t
+1 #count{ I : order(-1,k,I,t) : scope(k,I,t) } 1.
+
+% trace order/4 to derive transitive closure of objects in scope above/below k
+trans(D,k,I,t) :- order(D,k,I,t).
+trans(D,k,I,t) :- trans(D,k,J,t), order(D,J,I,t).
+trans(D,k,J,t) :- trans(D,k,I,t), order(-D,J,I,t), scope(k,J,t).
+
+% state constraint that the table is transitively below block k (redundant)
+ :- not trans(-1,k,0,t).
+
+% state constraint propagating immediate above/below relationships
+ :- order(-1,k,I,t), order(1,k,J,t), not order(-1,J,I,t), not order(1,I,J,t).
+
+% state constraint aligning immediate and transitive above/below relationships
+ :- order(-D,k,J,t), order(D,J,I,t), not trans(D,k,I,t), 0 < I. % D=-1 redundant
+
+% state constraint directing transitive above/below relationships on convergence
+ :- order(D,k,I,t), order(D,J,I,t), not trans(-D,k,J,t), scope(k,J,t), 0 < I.
+
+% rules below are volatile with life span 1
+% #program volatile(k,t).
+
+#external scope(k,0,t+1).
+
+% goal state conditions
+ :- goal_above(k,I), not trans(-1,k,I,t), not scope(k,0,t+1).
+ :- goal_below(k,I), not trans(1,k,I,t), not scope(k,0,t+1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for generating moves having a block as object and target, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program move(k,t).
+
+% external atoms indicating involvement of blocks with greater numbers in move
+#external change(-1,k,I,t) : scope(I,0,t), I <= k.
+#external change( 1,k,I,t) : scope(I,0,t-1), I <= k.
+% #external change((-1;1),k,t).
+#external change(-1,k,t).
+#external change( 1,k,t).
+
+% output object and target block of move
+#show object(k,t) : object(k,t).
+#show target(k,t) : target(k,t).
+
+% propagate role as move object (via D=1) or target (via D=-1) to smaller block
+change(1,k-1,I,t) :- order(1,k,I,t), scope(I,0,t-1), not order(1,k,I,t-1).
+change(D,k-1,I,t) :- order(D,k,I,t-(D+|D|)/2), scope(k,0,t-1), 0 < I,
+                     not order(D,k,I,t+(D-|D|)/2).
+change(D,k-1,I,t) :- change(D,k,I,t), I < k. % , scope(I,0,t-(D+|D|)/2).
+
+% combine possibilities how move affects block as object (D=1) or target (D=-1)
+affect(-D,k,t) :- order(D,k,I,t+(D-|D|)/2), scope(I,0,t-1) : D == 1;
+                  not order(D,k,I,t-(D+|D|)/2).
+affect( D,k,t) :- change(D,k,k,t). % , scope(k,0,t-(D+|D|)/2).
+
+% propagate existence of some move object or target to smaller blocks and table
+change(D,k-1,t) :- affect(D,k,t).
+change(D,k-1,t) :- change(D,k,t).
+
+% derive moved object and corresponding target
+object(k,t) :- affect(1,k,t).
+target(k,t) :- affect(-1,k,t), not change(-1,k,t).
+
+% moved object must be unique
+ :- object(k,t), change(1,k,t).
+
+% moved object must be free
+ :- object(k,t), order(1,k,_,t-1).
+ :- object(I,t), order(-1,k,I,t-1).
+
+% moved object must not go under (unmoved) pre-existing block
+ :- object(k,t), order(1,k,I,t), scope(I,0,t-1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for deriving target table from move without target block, using %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program table(t).
+
+% external atoms indicating involvement of blocks with greater numbers in move
+% #external change((-1;1),0,t).
+#external change(-1,0,t).
+#external change( 1,0,t).
+
+% output target table of move
+#show target(0,t) : target(0,t).
+
+% derive table as target of move
+target(0,t) :- change(1,0,t), not change(-1,0,t).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% program part for establishing consistent initial position for a block, using %
+% - parameter k for block number                                               %
+% - parameter t for step number at instantiation                               %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#program init(k,t).
+
+% no appearance under unmoved pre-existing block
+ :- order(1,k,I,t), scope(I,0,t-1), not object(I,t).
+
+% initial state conditions
+ :- init_above(k,I), not trans(-1,k,I,t).
+ :- init_below(k,I), not trans(1,k,I,t).
diff --git a/examples/clingo/commit/README b/examples/clingo/commit/README
new file mode 100644
index 0000000..ced6c83
--- /dev/null
+++ b/examples/clingo/commit/README
@@ -0,0 +1,7 @@
+This example illustrates the use of the commit function.
+
+Example calls:
+  clingo commit-lua.lp encoding.lp
+  clingo commit-py.lp encoding.lp
+  gringo --text commit-lua.lp encoding.lp
+  gringo --text commit-py.lp encoding.lp
diff --git a/examples/clingo/commit/commit-lua.lp b/examples/clingo/commit/commit-lua.lp
new file mode 100644
index 0000000..f645f82
--- /dev/null
+++ b/examples/clingo/commit/commit-lua.lp
@@ -0,0 +1,17 @@
+#script (lua)
+
+function echo(x)
+    print (x)
+    return x
+end
+
+function main(prg)
+    prg:ground({{"test", {1}}})
+    print ("---------- commited ----------")
+    prg:ground({{"test", {2}}, {"test", {3}}})
+    print ("---------- commited ----------")
+    prg:ground({{"test", {4}}})
+    prg:solve()
+end
+
+#end.
diff --git a/examples/clingo/commit/commit-py.lp b/examples/clingo/commit/commit-py.lp
new file mode 100644
index 0000000..4fa577c
--- /dev/null
+++ b/examples/clingo/commit/commit-py.lp
@@ -0,0 +1,14 @@
+#script (python)
+
+def echo(x):
+    print (x);
+    return x
+
+def main(prg):
+    prg.ground([("test", [1])])
+    print "---------- commited ----------"
+    prg.ground([("test", [2]), ("test", [3])])
+    print "---------- commited ----------"
+    prg.ground([("test", [4])])
+    prg.solve()
+#end.
diff --git a/examples/clingo/commit/encoding.lp b/examples/clingo/commit/encoding.lp
new file mode 100644
index 0000000..ed53c83
--- /dev/null
+++ b/examples/clingo/commit/encoding.lp
@@ -0,0 +1,5 @@
+#program test(i).
+
+{ p(@echo(i)) }.
+
+#minimize { i:not p(i) }.
diff --git a/examples/clingo/consequences/README b/examples/clingo/consequences/README
new file mode 100644
index 0000000..c4659b5
--- /dev/null
+++ b/examples/clingo/consequences/README
@@ -0,0 +1,6 @@
+This example shows how to enumerate brave consequences using clingo's ability
+to intercept models.
+
+Example calls:
+    clingo brave-py.lp example.lp
+    clingo brave-lua.lp example.lp
diff --git a/examples/clingo/consequences/brave-lua.lp b/examples/clingo/consequences/brave-lua.lp
new file mode 100644
index 0000000..490a776
--- /dev/null
+++ b/examples/clingo/consequences/brave-lua.lp
@@ -0,0 +1,44 @@
+#script(lua)
+
+brave = {}
+
+function on_model(m)
+    for _, x in ipairs(m:symbols{atoms=true}) do
+        if x.name == "holds" then
+            brave[tostring(x.arguments[1])] = true
+        end
+    end
+end
+
+function is_brave(x)
+    if brave[tostring(x)] then
+        return 1
+    else
+        return 0
+    end
+end
+
+function main(prg)
+    local n = 0
+    prg:ground({{"base", {}}})
+    while prg:solve(on_model).satisfiable do
+        if n > 10 then break end
+        n = n + 1
+        prg:ground({{"brave", {}}})
+    end
+    local ans = ""
+    for x, _ in pairs(brave) do
+        if ans ~= "" then
+            ans = ans .. ", "
+        end
+        ans = ans .. tostring(x)
+    end
+    print(string.format("brave consequences: %s", ans))
+end
+
+#end.
+
+#program brave.
+
+:- not holds(X) : atom(X), @is_brave(X) == 0.
+
diff --git a/examples/clingo/consequences/brave-py.lp b/examples/clingo/consequences/brave-py.lp
new file mode 100644
index 0000000..a42bc52
--- /dev/null
+++ b/examples/clingo/consequences/brave-py.lp
@@ -0,0 +1,24 @@
+#script(python)
+
+import clingo
+
+brave = set()
+
+def on_model(m):
+    for x in m.symbols(atoms=True):
+        if x.name == "holds": brave.add(x.arguments[0])
+
+def is_brave(x): return x in brave
+
+def main(prg):
+    prg.ground([("base", [])])
+    while prg.solve(on_model).satisfiable:
+        prg.ground([("brave", [])])
+    print "brave consequences: {0}".format(", ".join(str(x) for x in sorted(brave)))
+
+#end.
+
+#program brave.
+
+:- not holds(X) : atom(X), @is_brave(X) == 0.
+
diff --git a/examples/clingo/consequences/example.lp b/examples/clingo/consequences/example.lp
new file mode 100644
index 0000000..d17ea19
--- /dev/null
+++ b/examples/clingo/consequences/example.lp
@@ -0,0 +1,4 @@
+atom(p(1..10);q).
+{ holds(X) : atom(X) } 3.
+holds(p(X)) :- holds(p(X-1)), atom(p(X)),     holds(q).
+holds(p(X)) :- holds(p(X+1)), atom(p(X)), not holds(q).
diff --git a/examples/clingo/context/README b/examples/clingo/context/README
new file mode 100644
index 0000000..48c9daa
--- /dev/null
+++ b/examples/clingo/context/README
@@ -0,0 +1,6 @@
+This example shows how to use Python classes or Lua tables to organize code
+using the scripting interface.
+
+Example calls:
+    clingo context-py.lp encoding.lp --outf=3 0
+    clingo context-lua.lp encoding.lp --outf=3 0
diff --git a/examples/clingo/context/context-lua.lp b/examples/clingo/context/context-lua.lp
new file mode 100644
index 0000000..e13db27
--- /dev/null
+++ b/examples/clingo/context/context-lua.lp
@@ -0,0 +1,30 @@
+#script (lua) 
+
+State = { }
+State.__index = State
+
+function State.new(val)
+    local x = { value = val }
+    setmetatable(x, State)
+    return x
+end
+
+function State:test(value)
+    return self.value + value.number
+end
+
+function State:on_model(m)
+    print(tostring(m))
+end
+
+function State:run(prg)
+    prg:ground({{"base", {}}}, self)
+    prg:solve(function (...) self:on_model(...) end)
+end
+
+function main(prg) 
+    x = State.new(21)
+    x:run(prg)
+end
+
+#end.
diff --git a/examples/clingo/context/context-py.lp b/examples/clingo/context/context-py.lp
new file mode 100644
index 0000000..fc8ec77
--- /dev/null
+++ b/examples/clingo/context/context-py.lp
@@ -0,0 +1,21 @@
+#script (python) 
+
+class State:
+    def __init__(self, value):
+        self.value = value
+
+    def test(self, value):
+        return self.value + value.number
+    
+    def __on_model(self, m):
+        print (m)
+
+    def run(self, prg):
+        prg.ground([("base", [])], self)
+        prg.solve(self.__on_model)
+        
+def main(prg):
+    x = State(21)
+    x.run(prg)
+
+#end.
diff --git a/examples/clingo/context/encoding.lp b/examples/clingo/context/encoding.lp
new file mode 100644
index 0000000..ce5adec
--- /dev/null
+++ b/examples/clingo/context/encoding.lp
@@ -0,0 +1 @@
+p(@test(21)).
diff --git a/examples/clingo/controller-async/README b/examples/clingo/controller-async/README
new file mode 100644
index 0000000..f9edc7f
--- /dev/null
+++ b/examples/clingo/controller-async/README
@@ -0,0 +1,8 @@
+This example shows how clingo's asynchronous solving capabilities can be used
+in a master-worker scenario.
+
+To start call:
+    python controller.py
+
+The solver can then be controlled from the command line. An overview of the
+available commands is printed on the screen.
diff --git a/examples/clingo/controller-async/client.lp b/examples/clingo/controller-async/client.lp
new file mode 100644
index 0000000..a0a42d7
--- /dev/null
+++ b/examples/clingo/controller-async/client.lp
@@ -0,0 +1,15 @@
+#const m = 10.
+#const n = 190.
+
+#program pigeon.
+#external p.
+
+1 { p(X); q(X) } 1 :- X = 1..n, p.
+:- not n+1 { p(1..n); q(1..n) }, p.
+
+#program sleep(k).
+#external sleep(k).
+
+1 { p(k,X); q(k,X) } 1 :- X = 1..m, sleep(k), not p.
+:- not m+1 { p(k,1..m); q(k,1..m) }, sleep(k), not p.
+
diff --git a/examples/clingo/controller-async/controller.py b/examples/clingo/controller-async/controller.py
new file mode 100755
index 0000000..d63afc7
--- /dev/null
+++ b/examples/clingo/controller-async/controller.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+
+import os
+import readline
+import atexit
+import signal
+import clingo
+from threading import Condition
+
+class Controller:
+    def __init__(self):
+        histfile = os.path.join(os.path.expanduser("~"), ".controller")
+        try: readline.read_history_file(histfile)
+        except IOError: pass
+        readline.parse_and_bind('tab: complete')
+        def complete(commands, text, state):
+            matches = []
+            if state == 0: matches = [ c for c in commands if c.startswith(text) ]
+            return matches[state] if state < len(matches) else None
+        readline.set_completer(lambda text, state: complete(['more_pigeon_please', 'less_pigeon_please', 'solve', 'exit'], text, state))
+        atexit.register(readline.write_history_file, histfile)
+        self.solving = False
+        self.condition = Condition()
+
+    def register_solver(self, solver):
+        self.solver = solver
+
+    def interrupt(self, a, b):
+        signal.signal(signal.SIGINT, signal.SIG_IGN)
+        self.solver.stop()
+
+    def on_finish(self, ret):
+        self.message = "finish: " + str(ret) + (" (INTERRUPTED)" if ret.interrupted else "")
+        self.condition.acquire()
+        self.solving = False
+        self.condition.notify()
+        self.condition.release()
+
+    def run(self):
+        print
+        print "this prompt accepts the following commands:"
+        print "  solve              - start solving"
+        print "  exit/EOF           - terminate the solver"
+        print "  Ctrl-C             - interrupt current search"
+        print "  less_pigeon_please - select an easy problem"
+        print "  more_pigeon_please - select a difficult problem"
+        print
+
+        pyInt = signal.getsignal(signal.SIGINT)
+        while True:
+            signal.signal(signal.SIGINT, pyInt)
+            try:
+                line = raw_input('> ')
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
+            except EOFError:
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
+                line = "exit"
+                print line
+            except KeyboardInterrupt:
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
+                print
+                continue
+            if line == "solve":
+                print "Solving..."
+                self.solving = True
+                self.solver.start(self.on_finish)
+                signal.signal(signal.SIGINT, self.interrupt)
+                self.condition.acquire()
+                while self.solving:
+                    # NOTE: we need a timeout to catch signals
+                    self.condition.wait(float("inf"))
+                self.condition.release()
+                self.solver.finish()
+                for model in self.solver.models:
+                    print "model: " + model
+                print self.message
+            elif line == "exit":
+                break
+            elif line == "less_pigeon_please":
+                self.solver.set_more_pigeon(False)
+            elif line == "more_pigeon_please":
+                self.solver.set_more_pigeon(True)
+            else:
+                print "unknown command: " + line
+
+class Solver:
+    def __init__(self):
+        self.k   = 0
+        self.prg = clingo.Control()
+        self.prg.load("client.lp")
+        self.prg.ground([("pigeon", []), ("sleep",  [self.k])])
+        self.prg.assign_external(clingo.Function("sleep", [self.k]), True)
+        self.ret = None
+        self.models = []
+
+    def on_model(self, model):
+        self.models.append(str(model))
+
+    def start(self, on_finish):
+        if self.ret is not None and not self.ret.unknown():
+            self.k = self.k + 1
+            self.prg.ground([("sleep", [self.k])])
+            self.prg.release_external(clingo.Function("sleep", [self.k-1]))
+            self.prg.assign_external(clingo.Function("sleep", [self.k]), True)
+        self.future = self.prg.solve_async(on_model=self.on_model, on_finish=on_finish)
+
+    def stop(self):
+        self.future.cancel()
+
+    def finish(self):
+        ret = self.future.get()
+        return ret
+
+    def set_more_pigeon(self, more):
+        self.prg.assign_external(clingo.Function("p"), more)
+
+st = Solver()
+ct = Controller()
+ct.register_solver(st)
+ct.run()
+
diff --git a/examples/clingo/controller-processes/README b/examples/clingo/controller-processes/README
new file mode 100644
index 0000000..04b467b
--- /dev/null
+++ b/examples/clingo/controller-processes/README
@@ -0,0 +1,11 @@
+This example shows how clingo's asynchronous solving capabilities can be used
+in a client server scenario.
+
+To start the server, execute: 
+    python server.py
+
+Afterwards, start the client:
+    python client.py
+
+The client can then be controlled from the server. An overview of the available
+commands is printed on the screen.
diff --git a/examples/clingo/controller-processes/client.lp b/examples/clingo/controller-processes/client.lp
new file mode 100644
index 0000000..a0a42d7
--- /dev/null
+++ b/examples/clingo/controller-processes/client.lp
@@ -0,0 +1,15 @@
+#const m = 10.
+#const n = 190.
+
+#program pigeon.
+#external p.
+
+1 { p(X); q(X) } 1 :- X = 1..n, p.
+:- not n+1 { p(1..n); q(1..n) }, p.
+
+#program sleep(k).
+#external sleep(k).
+
+1 { p(k,X); q(k,X) } 1 :- X = 1..m, sleep(k), not p.
+:- not m+1 { p(k,1..m); q(k,1..m) }, sleep(k), not p.
+
diff --git a/examples/clingo/controller-processes/client.py b/examples/clingo/controller-processes/client.py
new file mode 100644
index 0000000..44bf5f8
--- /dev/null
+++ b/examples/clingo/controller-processes/client.py
@@ -0,0 +1,73 @@
+import socket
+import os
+import errno
+import clingo
+
+class Receiver:
+    def __init__(self, conn):
+        self.conn = conn
+        self.data = bytearray()
+    def readline(self):
+        pos = self.data.find("\n")
+        while pos < 0:
+            while True:
+                try: self.data.extend(self.conn.recv(4096))
+                except socket.error as (code, msg):
+                    if code != errno.EINTR: raise
+                else: break
+            pos = self. data.find("\n")
+        msg = self.data[:pos]
+        self.data = self.data[pos+1:]
+        return msg
+
+class States:
+    SOLVE = 1
+    IDLE  = 2
+
+def main(prg):
+    with open(".controller.PORT", "r") as f:
+        p = int(f.read())
+    os.remove(".controller.PORT")
+    conn = socket.create_connection(("127.0.0.1", p))
+    try:
+        recv  = Receiver(conn)
+        state = States.IDLE
+        k     = 0
+        prg.ground([("pigeon", []), ("sleep",  [k])])
+        prg.assign_external(clingo.Function("sleep", [k]), True)
+        while True:
+            if state == States.SOLVE:
+                f = prg.solve_async(
+                    on_model  = lambda model: conn.sendall("Answer: " + str(model) + "\n"),
+                    on_finish = lambda ret:   conn.sendall("finish:" + str(ret) + (":INTERRUPTED" if ret.interrupted else "") + "\n"))
+            msg = recv.readline()
+            if state == States.SOLVE:
+                f.cancel()
+                ret = f.get()
+            else:
+                ret = None
+            if msg == "interrupt":
+                state = States.IDLE
+            elif msg == "exit":
+                return
+            elif msg == "less_pigeon_please":
+                prg.assign_external(clingo.Function("p"), False)
+                state = States.IDLE
+            elif msg == "more_pigeon_please":
+                prg.assign_external(clingo.Function("p"), True)
+                state = States.IDLE
+            elif msg == "solve":
+                state = States.SOLVE
+            else: raise(RuntimeError("unexpected message: " + msg))
+            if ret is not None and not ret.unknown:
+                k = k + 1
+                prg.ground([("sleep", [k])])
+                prg.release_external(clingo.Function("sleep", [k-1]))
+                prg.assign_external(clingo.Function("sleep", [k]), True)
+    finally:
+        conn.close()
+
+prg = clingo.Control()
+prg.load("client.lp")
+main(prg)
+
diff --git a/examples/clingo/controller-processes/server.py b/examples/clingo/controller-processes/server.py
new file mode 100644
index 0000000..631023a
--- /dev/null
+++ b/examples/clingo/controller-processes/server.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+
+import socket
+import os
+import readline
+import atexit
+import random
+import signal
+import errno
+
+histfile = os.path.join(os.path.expanduser("~"), ".controller")
+try: readline.read_history_file(histfile)
+except IOError: pass
+readline.parse_and_bind('tab: complete')
+def complete(commands, text, state):
+    matches = []
+    if state == 0: matches = [ c for c in commands if c.startswith(text) ]
+    return matches[state] if state < len(matches) else None
+readline.set_completer(lambda text, state: complete(['more_pigeon_please', 'less_pigeon_please', 'solve', 'exit'], text, state))
+atexit.register(readline.write_history_file, histfile)
+
+def handleMessages(conn):
+    def interrupt(conn):
+        signal.signal(signal.SIGINT, signal.SIG_IGN)
+        conn.sendall("interrupt\n")
+    signal.signal(signal.SIGINT, lambda a, b: interrupt(conn))
+    data = bytearray()
+    while True:
+        while True:
+            try: data.extend(conn.recv(4096))
+            except socket.error as (code, msg):
+                if code != errno.EINTR: raise
+            else: break
+        pos = data.find("\n")
+        while pos >= 0:
+            (msg, data) = data.split("\n", 1)
+            if msg.startswith("finish:"):
+                msg = msg.split(":")
+                print(msg[1] + (" (interrupted)" if len(msg) > 2 else ""))
+                return
+            elif msg.startswith("Answer:"):
+                print(msg)
+                pos = data.find("\n")
+    signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+try:
+    for i in range(0,10):
+        try:
+            p = random.randrange(1000, 60000)
+            s.bind(("", p))
+        except socket.error as (code, msg):
+            if code != errno.EADDRINUSE: raise
+            continue
+        else:
+            with open(".controller.PORT", "w") as f: f.write(str(p))
+            print "waiting for connections..."
+            break
+        raise "no port found"
+    s.listen(1)
+    conn, addr = s.accept()
+    print
+    print "this prompt accepts the following commands:"
+    print "  solve              - start solving"
+    print "  exit/EOF           - terminate the solver"
+    print "  Ctrl-C             - interrupt current search"
+    print "  less_pigeon_please - select an easy problem"
+    print "  more_pigeon_please - select a difficult problem"
+    print
+
+    pyInt = signal.getsignal(signal.SIGINT)
+    while True:
+        signal.signal(signal.SIGINT, pyInt)
+        try:
+            line = raw_input('> ')
+            signal.signal(signal.SIGINT, signal.SIG_IGN)
+        except EOFError:
+            signal.signal(signal.SIGINT, signal.SIG_IGN)
+            line = "exit"
+            print line
+        except KeyboardInterrupt:
+            signal.signal(signal.SIGINT, signal.SIG_IGN)
+            print
+            continue
+        if line == "solve":
+            conn.sendall("solve\n")
+            handleMessages(conn)
+        elif line == "exit":
+            conn.sendall("exit\n")
+            break
+        elif line in ["less_pigeon_please", "more_pigeon_please"]:
+            conn.sendall(line + "\n")
+        else:
+            print "unknown command: " + line
+except KeyboardInterrupt:
+    raise
+finally:
+    s.close()
+
diff --git a/examples/clingo/controller-threads/README b/examples/clingo/controller-threads/README
new file mode 100644
index 0000000..53b1431
--- /dev/null
+++ b/examples/clingo/controller-threads/README
@@ -0,0 +1,8 @@
+This example shows how clingo's asynchronous solving capabilities can be used
+in a client server scenario using the threading module.
+
+To start call:
+    python controller.py
+
+The solver can then be controlled from the command line. An overview of the
+available commands is printed on the screen.
diff --git a/examples/clingo/controller-threads/client.lp b/examples/clingo/controller-threads/client.lp
new file mode 100644
index 0000000..a0a42d7
--- /dev/null
+++ b/examples/clingo/controller-threads/client.lp
@@ -0,0 +1,15 @@
+#const m = 10.
+#const n = 190.
+
+#program pigeon.
+#external p.
+
+1 { p(X); q(X) } 1 :- X = 1..n, p.
+:- not n+1 { p(1..n); q(1..n) }, p.
+
+#program sleep(k).
+#external sleep(k).
+
+1 { p(k,X); q(k,X) } 1 :- X = 1..m, sleep(k), not p.
+:- not m+1 { p(k,1..m); q(k,1..m) }, sleep(k), not p.
+
diff --git a/examples/clingo/controller-threads/controller.py b/examples/clingo/controller-threads/controller.py
new file mode 100755
index 0000000..59e449b
--- /dev/null
+++ b/examples/clingo/controller-threads/controller.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+import os
+import readline
+import atexit
+import signal
+import clingo
+from threading import Thread, Condition
+
+class Connection:
+    def __init__(self):
+        self.condition = Condition()
+        self.messages = []
+
+    def receive(self, timeout=None):
+        self.condition.acquire()
+        while len(self.messages) == 0:
+            self.condition.wait(timeout)
+        message = self.messages.pop()
+        self.condition.release()
+        return message
+
+    def send(self, message):
+        self.condition.acquire()
+        self.messages.append(message)
+        self.condition.notify()
+        self.condition.release()
+
+class Controller:
+    def __init__(self):
+        histfile = os.path.join(os.path.expanduser("~"), ".controller")
+        try: readline.read_history_file(histfile)
+        except IOError: pass
+        readline.parse_and_bind('tab: complete')
+        def complete(commands, text, state):
+            matches = []
+            if state == 0: matches = [ c for c in commands if c.startswith(text) ]
+            return matches[state] if state < len(matches) else None
+        readline.set_completer(lambda text, state: complete(['more_pigeon_please', 'less_pigeon_please', 'solve', 'exit'], text, state))
+        atexit.register(readline.write_history_file, histfile)
+        self.input  = Connection()
+        self.output = None
+
+    def register_connection(self, connection):
+        self.output = connection
+
+    def interrupt(self, a, b):
+        signal.signal(signal.SIGINT, signal.SIG_IGN)
+        self.output.send("interrupt")
+
+    def run(self):
+        print
+        print "this prompt accepts the following commands:"
+        print "  solve              - start solving"
+        print "  exit/EOF           - terminate the solver"
+        print "  Ctrl-C             - interrupt current search"
+        print "  less_pigeon_please - select an easy problem"
+        print "  more_pigeon_please - select a difficult problem"
+        print
+
+        pyInt = signal.getsignal(signal.SIGINT)
+        while True:
+            signal.signal(signal.SIGINT, pyInt)
+            try:
+                line = raw_input('> ')
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
+            except EOFError:
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
+                line = "exit"
+                print line
+            except KeyboardInterrupt:
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
+                print
+                continue
+            if line == "solve":
+                print "Solving..."
+                self.output.send("solve")
+                signal.signal(signal.SIGINT, self.interrupt)
+                # NOTE: we need a timeout to catch signals
+                msg = self.input.receive(float("inf"))
+                print msg
+            elif line == "exit":
+                self.output.send("exit")
+                break
+            elif line in ["less_pigeon_please", "more_pigeon_please"]:
+                self.output.send(line)
+            else:
+                print "unknown command: " + line
+
+class SolveThread(Thread):
+    STATE_SOLVE = 1
+    STATE_IDLE  = 2
+    STATE_EXIT  = 3
+
+    def __init__(self, connection):
+        Thread.__init__(self)
+        self.k   = 0
+        self.prg = clingo.Control()
+        self.prg.load("client.lp")
+        self.prg.ground([("pigeon", []), ("sleep",  [self.k])])
+        self.prg.assign_external(clingo.Function("sleep", [self.k]), True)
+        self.state = SolveThread.STATE_IDLE
+        self.input = Connection()
+        self.output = connection
+
+    def on_model(self, model):
+        self.output.send("answer: " + str(model)),
+
+    def on_finish(self, ret):
+        self.output.send("finish: " + str(ret) + (" (INTERRUPTED)" if ret.interrupted else ""))
+
+    def handle_message(self, msg):
+        if msg == "interrupt":
+            self.state = SolveThread.STATE_IDLE
+        elif msg == "exit":
+            self.state = SolveThread.STATE_EXIT
+        elif msg == "less_pigeon_please":
+            self.prg.assign_external(clingo.Function("p"), False)
+            self.state = SolveThread.STATE_IDLE
+        elif msg == "more_pigeon_please":
+            self.prg.assign_external(clingo.Function("p"), True)
+            self.state = SolveThread.STATE_IDLE
+        elif msg == "solve":
+            self.state = SolveThread.STATE_SOLVE
+        else: raise(RuntimeError("unexpected message: " + msg))
+
+    def run(self):
+        while True:
+            if self.state == SolveThread.STATE_SOLVE:
+                f = self.prg.solve_async(on_model=self.on_model, on_finish=self.on_finish)
+            msg = self.input.receive()
+            if self.state == SolveThread.STATE_SOLVE:
+                f.cancel()
+                ret = f.get()
+            else:
+                ret = None
+            self.handle_message(msg)
+            if self.state == SolveThread.STATE_EXIT:
+                return
+            elif ret is not None and not ret.unknown:
+                self.k = self.k + 1
+                self.prg.ground([("sleep", [self.k])])
+                self.prg.release_external(clingo.Function("sleep", [self.k-1]))
+                self.prg.assign_external(clingo.Function("sleep", [self.k]), True)
+
+ct = Controller()
+st = SolveThread(ct.input)
+ct.register_connection(st.input)
+
+st.start()
+ct.run()
+st.join()
+
diff --git a/examples/clingo/cover/README b/examples/clingo/cover/README
new file mode 100644
index 0000000..226c83d
--- /dev/null
+++ b/examples/clingo/cover/README
@@ -0,0 +1,5 @@
+Encoding to calculate a vertex cover for a graph. A simple preprocessing
+procedure is applied to reduce the graph size before calculating the cover.
+
+$ clingo control-py.lp
+$ clingo control-lua.lp
diff --git a/examples/clingo/cover/control-lua.lp b/examples/clingo/cover/control-lua.lp
new file mode 100644
index 0000000..8978682
--- /dev/null
+++ b/examples/clingo/cover/control-lua.lp
@@ -0,0 +1,82 @@
+#script (lua)
+
+clingo = require("clingo")
+
+State = { }
+State.__index = State
+
+function State.new()
+    local x = { 
+        leaves = {},
+        last   = nil
+    }
+    setmetatable(x, State)
+    return x
+end
+
+function State:fix(k)
+    local leaf = self.leaves[k.number-1]
+    if leaf then
+        return leaf
+    else
+        return {}
+    end
+end
+
+function State:on_model(m)
+    self.last = m:symbols{atoms=true}
+    for key,atom in ipairs(self.last) do
+        if atom.name == "leaf" then
+            local args = atom.arguments
+            self.leaves[args[1]] = args[2]
+        end
+    end
+end
+
+function State:prepare_instance(k)
+    edges = {}
+    cover = {}
+    vertices = {}
+    for key,atom in ipairs(self.last) do
+        if atom.name == "edge" then
+            args = atom.arguments
+            if args[1].number == k-1 then
+                edges[#edges + 1] = clingo.Tuple{args[2], args[3]}
+                vertices[#vertices + 1] = args[2]
+                vertices[#vertices + 1] = args[3]
+            end
+        end
+        if atom.name == "cover" then
+            cover[#cover + 1] = atom.arguments[2]
+        end
+    end
+    self.edge = function (self) return edges end
+    self.vertex = function (self) return vertices end
+    self.cover = function (self) return cover end
+end
+
+function State:run(prg)
+    local pre = clingo.Control()
+    pre:load("instance.lp")
+    pre:load("preprocess.lp")
+    pre:ground({{"base", {}}})
+    local ret = pre:solve(function(...) self:on_model(...) end)
+    local k = 0
+    while ret.satisfiable do
+        k = k + 1
+        pre:cleanup()
+        pre:ground({{"step", {k}}}, self)
+        ret = pre:solve(function(...) self:on_model(...) end)
+    end
+    self:prepare_instance(k)
+    prg:load("cover.lp")
+    prg:ground({{"base", {}}}, self)
+    prg:solve()
+end
+
+function main(prg)
+    local s = State.new(prg)
+    s:run(prg)
+end
+
+#end.
diff --git a/examples/clingo/cover/control-py.lp b/examples/clingo/cover/control-py.lp
new file mode 100644
index 0000000..0174a32
--- /dev/null
+++ b/examples/clingo/cover/control-py.lp
@@ -0,0 +1,60 @@
+#script (python)
+
+import clingo
+import sys
+
+class State:
+    def __init__(self):
+        self.leaves = {}
+        self.last = None
+
+    def fix(self, k):
+        return self.leaves.get(k.number-1, [])
+
+    def on_model(self, m):
+        self.last = m.symbols(atoms=True)
+        for atom in self.last:
+            if atom.name == "leaf":
+                args = atom.arguments
+                self.leaves[args[0]] = args[1]
+
+    def prepare_instance(self, k):
+        edges = []
+        cover = []
+        vertices = set()
+        for atom in self.last:
+            if atom.name == "edge":
+                args = atom.arguments
+                if args[0].number == k-1:
+                    edges.append((args[1], args[2]))
+                    vertices.add(args[1])
+                    vertices.add(args[2])
+            if atom.name == "cover":
+                cover.append(atom.arguments[1])
+        vertices = list(vertices)
+        setattr(self, "edge", lambda: edges)
+        setattr(self, "cover", lambda: cover)
+        setattr(self, "vertex", lambda: vertices)
+
+    def run(self, prg):
+        pre = clingo.Control()
+        pre.load("instance.lp")
+        pre.load("preprocess.lp")
+        pre.ground([("base", [])])
+        ret = pre.solve(on_model = self.on_model)
+        k = 0
+        while ret.satisfiable:
+            k = k + 1
+            pre.cleanup()
+            pre.ground([("step", [k])], self)
+            ret = pre.solve(on_model = self.on_model)
+        self.prepare_instance(k)
+        prg.load("cover.lp")
+        prg.ground([("base", [])], self)
+        prg.solve()
+
+def main(prg):
+    s = State()
+    s.run(prg)
+
+#end.
diff --git a/examples/clingo/cover/cover.lp b/examples/clingo/cover/cover.lp
new file mode 100644
index 0000000..6060421
--- /dev/null
+++ b/examples/clingo/cover/cover.lp
@@ -0,0 +1,9 @@
+vertex(X) :- X = @vertex().
+edge(X,Y) :- (X,Y) = @edge().
+cover(X)  :- X = @cover().
+
+{ cover(X) : vertex(X) }.
+:- edge(X,Y), not cover(X), not cover(Y).
+#minimize { 1,X : cover(X) }.
+
+#show cover/1.
diff --git a/examples/clingo/cover/instance.lp b/examples/clingo/cover/instance.lp
new file mode 100644
index 0000000..fce366c
--- /dev/null
+++ b/examples/clingo/cover/instance.lp
@@ -0,0 +1,8 @@
+edge(a,(b;c)).
+edge(b,(c;d;e)).
+edge(d,f).
+
+edge(x,(a;c)). % edge to keep something to solve
+
+edge(X,Y) :- edge(Y,X).
+vertex(X) :- edge(X,Y;Y,X).
diff --git a/examples/clingo/cover/preprocess.lp b/examples/clingo/cover/preprocess.lp
new file mode 100644
index 0000000..de0caa9
--- /dev/null
+++ b/examples/clingo/cover/preprocess.lp
@@ -0,0 +1,14 @@
+#program base.
+
+edge(0,X,Y) :- edge(X,Y).
+
+#program step(k).
+
+:- not leaf(k-1,@fix(k)).
+
+1 { leaf(k,X) : vertex(X) } 1.
+cover(k,X) :- edge(k-1,X,Y), leaf(k,Y).
+edge(k,X,Y) :- edge(k-1,X,Y), not cover(k,X), not cover(k,Y).
+
+:- edge(k-1,X,Y), leaf(k,Y), edge(k-1,Y,Z), X < Z.
+:- leaf(k,Y), not edge(k-1,_,Y).
diff --git a/examples/clingo/domains/README b/examples/clingo/domains/README
new file mode 100644
index 0000000..b8dff60
--- /dev/null
+++ b/examples/clingo/domains/README
@@ -0,0 +1,6 @@
+This example shows how to inspect the domains of the grounder. Note that this
+example requires clingo - this functionality is not available for gringo.
+
+Example Calls:
+    clingo domains-py.lp instance.lp
+    clingo domains-lua.lp instance.lp
diff --git a/examples/clingo/domains/domains-lua.lp b/examples/clingo/domains/domains-lua.lp
new file mode 100644
index 0000000..4f3f8de
--- /dev/null
+++ b/examples/clingo/domains/domains-lua.lp
@@ -0,0 +1,24 @@
+#script (lua)
+
+clingo = require("clingo")
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    print ("universe:" .. tostring(#prg.symbolic_atoms))
+    for x in prg.symbolic_atoms:iter() do
+        print (x.symbol, x.is_fact, x.is_external)
+    end
+    print ("p(2) is in domain: " .. tostring(prg.symbolic_atoms:lookup(clingo.Function("p", {3})) ~= nil))
+    print ("p(4) is in domain: " .. tostring(prg.symbolic_atoms:lookup(clingo.Function("p", {4})) ~= nil))
+    print ("domain of p/1:")
+    for x in prg.symbolic_atoms:by_signature("p", 1) do
+        print (x.symbol, x.is_fact, x.is_external)
+    end
+    print ("signatures:")
+    for i,x in ipairs(prg.symbolic_atoms.signatures) do
+        if x[3] then s = "" else s = "~" end
+        print (s .. x[1] .. "/" .. tostring(x[2]))
+    end
+end
+
+#end. 
diff --git a/examples/clingo/domains/domains-py.lp b/examples/clingo/domains/domains-py.lp
new file mode 100644
index 0000000..dda3466
--- /dev/null
+++ b/examples/clingo/domains/domains-py.lp
@@ -0,0 +1,19 @@
+#script (python)
+
+import clingo
+
+def main(prg):
+    prg.ground([("base", [])])
+    print ("universe: " + str(len(prg.symbolic_atoms)))
+    for x in prg.symbolic_atoms:
+        print (x.symbol, x.is_fact, x.is_external)
+    print ("p(2) is in domain: " + str(prg.symbolic_atoms[clingo.Function("p", {3})] is not None))
+    print ("p(4) is in domain: " + str(prg.symbolic_atoms[clingo.Function("p", {4})] is not None))
+    print ("domain of p/1")
+    for x in prg.symbolic_atoms.by_signature("p", 1):
+        print (x.symbol, x.is_fact, x.is_external)
+    print ("signatures")
+    for x in prg.symbolic_atoms.signatures:
+        print (("~" if not x[2] else "") + x[0] + "/" + str(x[1]))
+
+#end. 
diff --git a/examples/clingo/domains/instance.lp b/examples/clingo/domains/instance.lp
new file mode 100644
index 0000000..e100d7b
--- /dev/null
+++ b/examples/clingo/domains/instance.lp
@@ -0,0 +1,5 @@
+p(1).
+{ p(3) }. 
+#external p(1..3).
+
+q(X) :- p(X).
diff --git a/examples/clingo/dot-propagator/README b/examples/clingo/dot-propagator/README
new file mode 100644
index 0000000..22a7123
--- /dev/null
+++ b/examples/clingo/dot-propagator/README
@@ -0,0 +1,6 @@
+This example shows a simple propagator, which actually does not propagate
+anything.  Instead it prints a dot whenever an atom becomes true during search
+and deletes a dot when the corresponding atom is free again.
+
+Example call:
+  clingo dot.lp test.lp -V0
diff --git a/examples/clingo/dot-propagator/dot.lp b/examples/clingo/dot-propagator/dot.lp
new file mode 100644
index 0000000..6d1a381
--- /dev/null
+++ b/examples/clingo/dot-propagator/dot.lp
@@ -0,0 +1,31 @@
+#script (python)
+
+import sys
+import time
+
+class Propagator:
+    def init(self, init):
+        self.sleep = .1
+        for atom in init.symbolic_atoms:
+            init.add_watch(init.solver_literal(atom.literal))
+
+    def propagate(self, ctl, changes):
+        for l in changes:
+            sys.stdout.write(".")
+            sys.stdout.flush()
+            time.sleep(self.sleep)
+        return True
+
+    def undo(self, solver_id, assign, undo):
+        for l in undo:
+            sys.stdout.write("\b \b")
+            sys.stdout.flush()
+            time.sleep(self.sleep)
+
+def main(prg):
+    prg.register_propagator(Propagator())
+    prg.ground([("base", [])])
+    prg.solve()
+    sys.stdout.write("\n")
+
+#end.
diff --git a/examples/clingo/dot-propagator/test.lp b/examples/clingo/dot-propagator/test.lp
new file mode 100644
index 0000000..1eebbc0
--- /dev/null
+++ b/examples/clingo/dot-propagator/test.lp
@@ -0,0 +1,5 @@
+#const n=6.
+p(1..n).
+h(1..(n-1)).
+1 { a(P,H) : h(H) } 1 :- p(P).
+:- 2 { a(P,H) }, h(H).
diff --git a/examples/clingo/enum-assumption/README b/examples/clingo/enum-assumption/README
new file mode 100644
index 0000000..fd60ab4
--- /dev/null
+++ b/examples/clingo/enum-assumption/README
@@ -0,0 +1,8 @@
+This example shows how to use the enumeration assumption. Note that calls to
+solve are only repeatable if this assumption is enabled. If it is disabled, an
+(implementation dependend) subset of the clauses learnt during enumeration of
+solutions is kept.
+
+Example calls:
+  clingo example-py.lp
+  clingo example-lua.lp
diff --git a/examples/clingo/enum-assumption/example-lua.lp b/examples/clingo/enum-assumption/example-lua.lp
new file mode 100644
index 0000000..d257587
--- /dev/null
+++ b/examples/clingo/enum-assumption/example-lua.lp
@@ -0,0 +1,20 @@
+#script (lua)
+
+function main(prg)
+    prg.configuration.solve.models = 0
+    print(prg.use_enumeration_assumption)
+    prg:ground({{"base", {}}})
+    prg.use_enumeration_assumption = true
+    print("===================== Solve ========================")
+    prg:solve()
+    prg.use_enumeration_assumption = false
+    print("===================== Solve ========================")
+    prg:solve()
+    print("===================== Solve ========================")
+    prg:solve()
+    print(prg.use_enumeration_assumption)
+end
+
+#end.
+
+{ a; b; c }.
diff --git a/examples/clingo/enum-assumption/example-py.lp b/examples/clingo/enum-assumption/example-py.lp
new file mode 100644
index 0000000..cc703b9
--- /dev/null
+++ b/examples/clingo/enum-assumption/example-py.lp
@@ -0,0 +1,19 @@
+#script (python)
+
+def main(prg):
+    prg.configuration.solve.models = 0
+    print prg.use_enumeration_assumption
+    prg.ground([("base", [])])
+    prg.use_enumeration_assumption = True
+    print "===================== Solve ========================"
+    prg.solve()
+    prg.use_enumeration_assumption = False
+    print "===================== Solve ========================"
+    prg.solve()
+    print "===================== Solve ========================"
+    prg.solve()
+    print prg.use_enumeration_assumption
+
+#end.
+
+{ a; b; c }.
diff --git a/examples/clingo/expansion/GraphColouring/encodings/encoding.lp b/examples/clingo/expansion/GraphColouring/encodings/encoding.lp
new file mode 100644
index 0000000..ec4e5d2
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/encodings/encoding.lp
@@ -0,0 +1,31 @@
+#program object(m,k).
+#external assigned(m,1).
+
+vertex(m).
+:- not assigned(m,1).
+
+next(m,C,k) :- color(C).
+
+next(m,N,C,k) :- edge(m,N), vertex(N), color(C).
+next(N,m,C,k) :- edge(N,m), vertex(N), color(C).
+
+#program horizon(c,k).
+
+color(c).
+
+next(M,c,k) :- vertex(M).
+
+next(M,N,c,k) :- edge(M,N), vertex(M), vertex(N).
+
+#program expand(k).
+#external assigned(M,C+1) : next(M,C,k).
+
+{ assign(M,C) } :- next(M,C,k).
+
+assigned(M,C) :- assign(M,C), next(M,C,k).
+assigned(M,C) :- assigned(M,C+1), next(M,C,k).
+:- assign(M,C-1), assigned(M,C), next(M,C,k).
+
+:- assign(M,C), assign(N,C), next(M,N,C,k).
+
+#show assign/2.
diff --git a/examples/clingo/expansion/GraphColouring/instances/0004-graph_colouring-125-0.lp b/examples/clingo/expansion/GraphColouring/instances/0004-graph_colouring-125-0.lp
new file mode 100644
index 0000000..ad8e4a5
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0004-graph_colouring-125-0.lp
@@ -0,0 +1,1687 @@
+#const n=125.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+edge(1,28).
+edge(28,1).
+edge(1,29).
+edge(29,1).
+edge(1,43).
+edge(43,1).
+edge(1,52).
+edge(52,1).
+edge(1,56).
+edge(56,1).
+edge(1,62).
+edge(62,1).
+edge(1,67).
+edge(67,1).
+edge(1,85).
+edge(85,1).
+edge(1,95).
+edge(95,1).
+edge(1,112).
+edge(112,1).
+edge(1,121).
+edge(121,1).
+edge(2,36).
+edge(36,2).
+edge(2,56).
+edge(56,2).
+edge(2,57).
+edge(57,2).
+edge(2,58).
+edge(58,2).
+edge(2,68).
+edge(68,2).
+edge(2,71).
+edge(71,2).
+edge(2,74).
+edge(74,2).
+edge(2,75).
+edge(75,2).
+edge(2,88).
+edge(88,2).
+edge(2,91).
+edge(91,2).
+edge(2,114).
+edge(114,2).
+edge(2,123).
+edge(123,2).
+edge(3,25).
+edge(25,3).
+edge(3,36).
+edge(36,3).
+edge(3,40).
+edge(40,3).
+edge(3,62).
+edge(62,3).
+edge(3,73).
+edge(73,3).
+edge(3,75).
+edge(75,3).
+edge(3,76).
+edge(76,3).
+edge(3,80).
+edge(80,3).
+edge(3,92).
+edge(92,3).
+edge(3,111).
+edge(111,3).
+edge(3,122).
+edge(122,3).
+edge(4,17).
+edge(17,4).
+edge(4,29).
+edge(29,4).
+edge(4,42).
+edge(42,4).
+edge(4,52).
+edge(52,4).
+edge(4,61).
+edge(61,4).
+edge(4,64).
+edge(64,4).
+edge(4,109).
+edge(109,4).
+edge(5,24).
+edge(24,5).
+edge(5,26).
+edge(26,5).
+edge(5,27).
+edge(27,5).
+edge(5,37).
+edge(37,5).
+edge(5,43).
+edge(43,5).
+edge(5,55).
+edge(55,5).
+edge(5,76).
+edge(76,5).
+edge(5,81).
+edge(81,5).
+edge(5,99).
+edge(99,5).
+edge(5,100).
+edge(100,5).
+edge(5,113).
+edge(113,5).
+edge(5,123).
+edge(123,5).
+edge(6,18).
+edge(18,6).
+edge(6,20).
+edge(20,6).
+edge(6,44).
+edge(44,6).
+edge(6,57).
+edge(57,6).
+edge(6,64).
+edge(64,6).
+edge(6,66).
+edge(66,6).
+edge(6,79).
+edge(79,6).
+edge(6,82).
+edge(82,6).
+edge(6,94).
+edge(94,6).
+edge(6,107).
+edge(107,6).
+edge(7,45).
+edge(45,7).
+edge(7,49).
+edge(49,7).
+edge(7,60).
+edge(60,7).
+edge(7,85).
+edge(85,7).
+edge(7,90).
+edge(90,7).
+edge(7,91).
+edge(91,7).
+edge(7,96).
+edge(96,7).
+edge(7,98).
+edge(98,7).
+edge(7,100).
+edge(100,7).
+edge(7,102).
+edge(102,7).
+edge(7,104).
+edge(104,7).
+edge(7,105).
+edge(105,7).
+edge(7,110).
+edge(110,7).
+edge(7,112).
+edge(112,7).
+edge(7,119).
+edge(119,7).
+edge(8,18).
+edge(18,8).
+edge(8,26).
+edge(26,8).
+edge(8,29).
+edge(29,8).
+edge(8,43).
+edge(43,8).
+edge(8,45).
+edge(45,8).
+edge(8,53).
+edge(53,8).
+edge(8,61).
+edge(61,8).
+edge(8,65).
+edge(65,8).
+edge(8,85).
+edge(85,8).
+edge(8,87).
+edge(87,8).
+edge(8,99).
+edge(99,8).
+edge(8,113).
+edge(113,8).
+edge(8,118).
+edge(118,8).
+edge(9,22).
+edge(22,9).
+edge(9,24).
+edge(24,9).
+edge(9,32).
+edge(32,9).
+edge(9,36).
+edge(36,9).
+edge(9,37).
+edge(37,9).
+edge(9,43).
+edge(43,9).
+edge(9,57).
+edge(57,9).
+edge(9,62).
+edge(62,9).
+edge(9,66).
+edge(66,9).
+edge(9,68).
+edge(68,9).
+edge(9,107).
+edge(107,9).
+edge(9,118).
+edge(118,9).
+edge(9,120).
+edge(120,9).
+edge(9,124).
+edge(124,9).
+edge(10,23).
+edge(23,10).
+edge(10,35).
+edge(35,10).
+edge(10,36).
+edge(36,10).
+edge(10,37).
+edge(37,10).
+edge(10,64).
+edge(64,10).
+edge(10,83).
+edge(83,10).
+edge(10,85).
+edge(85,10).
+edge(10,101).
+edge(101,10).
+edge(10,116).
+edge(116,10).
+edge(10,117).
+edge(117,10).
+edge(11,15).
+edge(15,11).
+edge(11,16).
+edge(16,11).
+edge(11,29).
+edge(29,11).
+edge(11,43).
+edge(43,11).
+edge(11,44).
+edge(44,11).
+edge(11,45).
+edge(45,11).
+edge(11,55).
+edge(55,11).
+edge(11,56).
+edge(56,11).
+edge(11,58).
+edge(58,11).
+edge(11,68).
+edge(68,11).
+edge(11,70).
+edge(70,11).
+edge(11,77).
+edge(77,11).
+edge(11,80).
+edge(80,11).
+edge(11,91).
+edge(91,11).
+edge(11,104).
+edge(104,11).
+edge(11,107).
+edge(107,11).
+edge(11,124).
+edge(124,11).
+edge(12,14).
+edge(14,12).
+edge(12,15).
+edge(15,12).
+edge(12,18).
+edge(18,12).
+edge(12,39).
+edge(39,12).
+edge(12,48).
+edge(48,12).
+edge(12,54).
+edge(54,12).
+edge(12,65).
+edge(65,12).
+edge(12,75).
+edge(75,12).
+edge(12,77).
+edge(77,12).
+edge(12,83).
+edge(83,12).
+edge(12,88).
+edge(88,12).
+edge(12,98).
+edge(98,12).
+edge(12,107).
+edge(107,12).
+edge(13,25).
+edge(25,13).
+edge(13,44).
+edge(44,13).
+edge(13,49).
+edge(49,13).
+edge(13,55).
+edge(55,13).
+edge(13,63).
+edge(63,13).
+edge(13,87).
+edge(87,13).
+edge(13,91).
+edge(91,13).
+edge(13,99).
+edge(99,13).
+edge(13,111).
+edge(111,13).
+edge(13,112).
+edge(112,13).
+edge(13,120).
+edge(120,13).
+edge(13,121).
+edge(121,13).
+edge(14,30).
+edge(30,14).
+edge(14,36).
+edge(36,14).
+edge(14,37).
+edge(37,14).
+edge(14,51).
+edge(51,14).
+edge(14,58).
+edge(58,14).
+edge(14,61).
+edge(61,14).
+edge(14,67).
+edge(67,14).
+edge(14,81).
+edge(81,14).
+edge(14,82).
+edge(82,14).
+edge(14,86).
+edge(86,14).
+edge(14,93).
+edge(93,14).
+edge(15,22).
+edge(22,15).
+edge(15,38).
+edge(38,15).
+edge(15,46).
+edge(46,15).
+edge(15,64).
+edge(64,15).
+edge(15,68).
+edge(68,15).
+edge(15,74).
+edge(74,15).
+edge(15,90).
+edge(90,15).
+edge(15,97).
+edge(97,15).
+edge(15,104).
+edge(104,15).
+edge(15,107).
+edge(107,15).
+edge(15,109).
+edge(109,15).
+edge(15,112).
+edge(112,15).
+edge(15,117).
+edge(117,15).
+edge(16,52).
+edge(52,16).
+edge(16,66).
+edge(66,16).
+edge(16,69).
+edge(69,16).
+edge(16,71).
+edge(71,16).
+edge(16,92).
+edge(92,16).
+edge(16,106).
+edge(106,16).
+edge(17,42).
+edge(42,17).
+edge(17,59).
+edge(59,17).
+edge(17,69).
+edge(69,17).
+edge(17,77).
+edge(77,17).
+edge(17,87).
+edge(87,17).
+edge(17,93).
+edge(93,17).
+edge(17,99).
+edge(99,17).
+edge(17,101).
+edge(101,17).
+edge(17,105).
+edge(105,17).
+edge(17,118).
+edge(118,17).
+edge(17,120).
+edge(120,17).
+edge(17,121).
+edge(121,17).
+edge(18,30).
+edge(30,18).
+edge(18,32).
+edge(32,18).
+edge(18,40).
+edge(40,18).
+edge(18,47).
+edge(47,18).
+edge(18,64).
+edge(64,18).
+edge(18,76).
+edge(76,18).
+edge(18,78).
+edge(78,18).
+edge(18,84).
+edge(84,18).
+edge(18,98).
+edge(98,18).
+edge(18,100).
+edge(100,18).
+edge(18,101).
+edge(101,18).
+edge(18,106).
+edge(106,18).
+edge(18,107).
+edge(107,18).
+edge(18,111).
+edge(111,18).
+edge(18,121).
+edge(121,18).
+edge(19,22).
+edge(22,19).
+edge(19,28).
+edge(28,19).
+edge(19,32).
+edge(32,19).
+edge(19,34).
+edge(34,19).
+edge(19,56).
+edge(56,19).
+edge(19,66).
+edge(66,19).
+edge(19,83).
+edge(83,19).
+edge(19,91).
+edge(91,19).
+edge(19,94).
+edge(94,19).
+edge(19,96).
+edge(96,19).
+edge(19,111).
+edge(111,19).
+edge(19,123).
+edge(123,19).
+edge(20,22).
+edge(22,20).
+edge(20,43).
+edge(43,20).
+edge(20,57).
+edge(57,20).
+edge(20,67).
+edge(67,20).
+edge(20,78).
+edge(78,20).
+edge(20,110).
+edge(110,20).
+edge(21,27).
+edge(27,21).
+edge(21,39).
+edge(39,21).
+edge(21,64).
+edge(64,21).
+edge(21,69).
+edge(69,21).
+edge(21,84).
+edge(84,21).
+edge(21,107).
+edge(107,21).
+edge(21,114).
+edge(114,21).
+edge(21,120).
+edge(120,21).
+edge(22,35).
+edge(35,22).
+edge(22,42).
+edge(42,22).
+edge(22,51).
+edge(51,22).
+edge(22,61).
+edge(61,22).
+edge(22,65).
+edge(65,22).
+edge(22,72).
+edge(72,22).
+edge(22,80).
+edge(80,22).
+edge(22,106).
+edge(106,22).
+edge(22,112).
+edge(112,22).
+edge(22,121).
+edge(121,22).
+edge(23,26).
+edge(26,23).
+edge(23,35).
+edge(35,23).
+edge(23,36).
+edge(36,23).
+edge(23,50).
+edge(50,23).
+edge(23,63).
+edge(63,23).
+edge(23,69).
+edge(69,23).
+edge(23,97).
+edge(97,23).
+edge(23,105).
+edge(105,23).
+edge(23,119).
+edge(119,23).
+edge(24,27).
+edge(27,24).
+edge(24,55).
+edge(55,24).
+edge(24,60).
+edge(60,24).
+edge(24,72).
+edge(72,24).
+edge(24,87).
+edge(87,24).
+edge(24,88).
+edge(88,24).
+edge(24,91).
+edge(91,24).
+edge(24,93).
+edge(93,24).
+edge(24,99).
+edge(99,24).
+edge(24,102).
+edge(102,24).
+edge(24,117).
+edge(117,24).
+edge(25,28).
+edge(28,25).
+edge(25,48).
+edge(48,25).
+edge(25,52).
+edge(52,25).
+edge(25,70).
+edge(70,25).
+edge(25,92).
+edge(92,25).
+edge(25,94).
+edge(94,25).
+edge(25,99).
+edge(99,25).
+edge(25,113).
+edge(113,25).
+edge(26,31).
+edge(31,26).
+edge(26,50).
+edge(50,26).
+edge(26,57).
+edge(57,26).
+edge(26,66).
+edge(66,26).
+edge(26,68).
+edge(68,26).
+edge(26,99).
+edge(99,26).
+edge(26,102).
+edge(102,26).
+edge(26,110).
+edge(110,26).
+edge(27,34).
+edge(34,27).
+edge(27,51).
+edge(51,27).
+edge(27,58).
+edge(58,27).
+edge(27,64).
+edge(64,27).
+edge(27,71).
+edge(71,27).
+edge(27,76).
+edge(76,27).
+edge(27,77).
+edge(77,27).
+edge(27,83).
+edge(83,27).
+edge(27,90).
+edge(90,27).
+edge(27,107).
+edge(107,27).
+edge(27,120).
+edge(120,27).
+edge(27,122).
+edge(122,27).
+edge(28,36).
+edge(36,28).
+edge(28,44).
+edge(44,28).
+edge(28,57).
+edge(57,28).
+edge(28,62).
+edge(62,28).
+edge(28,81).
+edge(81,28).
+edge(28,84).
+edge(84,28).
+edge(28,88).
+edge(88,28).
+edge(28,94).
+edge(94,28).
+edge(28,106).
+edge(106,28).
+edge(28,111).
+edge(111,28).
+edge(28,118).
+edge(118,28).
+edge(28,119).
+edge(119,28).
+edge(29,39).
+edge(39,29).
+edge(29,53).
+edge(53,29).
+edge(29,60).
+edge(60,29).
+edge(29,69).
+edge(69,29).
+edge(29,82).
+edge(82,29).
+edge(29,86).
+edge(86,29).
+edge(29,109).
+edge(109,29).
+edge(29,117).
+edge(117,29).
+edge(29,118).
+edge(118,29).
+edge(30,33).
+edge(33,30).
+edge(30,67).
+edge(67,30).
+edge(30,85).
+edge(85,30).
+edge(30,93).
+edge(93,30).
+edge(30,95).
+edge(95,30).
+edge(30,98).
+edge(98,30).
+edge(30,114).
+edge(114,30).
+edge(30,117).
+edge(117,30).
+edge(31,59).
+edge(59,31).
+edge(31,69).
+edge(69,31).
+edge(31,74).
+edge(74,31).
+edge(31,79).
+edge(79,31).
+edge(31,94).
+edge(94,31).
+edge(31,101).
+edge(101,31).
+edge(31,103).
+edge(103,31).
+edge(31,112).
+edge(112,31).
+edge(32,56).
+edge(56,32).
+edge(32,67).
+edge(67,32).
+edge(32,71).
+edge(71,32).
+edge(32,78).
+edge(78,32).
+edge(32,86).
+edge(86,32).
+edge(32,93).
+edge(93,32).
+edge(32,106).
+edge(106,32).
+edge(32,116).
+edge(116,32).
+edge(32,119).
+edge(119,32).
+edge(33,56).
+edge(56,33).
+edge(33,71).
+edge(71,33).
+edge(33,92).
+edge(92,33).
+edge(33,94).
+edge(94,33).
+edge(33,111).
+edge(111,33).
+edge(34,42).
+edge(42,34).
+edge(34,55).
+edge(55,34).
+edge(34,62).
+edge(62,34).
+edge(34,65).
+edge(65,34).
+edge(34,82).
+edge(82,34).
+edge(34,83).
+edge(83,34).
+edge(34,87).
+edge(87,34).
+edge(34,94).
+edge(94,34).
+edge(35,42).
+edge(42,35).
+edge(35,70).
+edge(70,35).
+edge(35,91).
+edge(91,35).
+edge(35,95).
+edge(95,35).
+edge(36,49).
+edge(49,36).
+edge(36,53).
+edge(53,36).
+edge(36,57).
+edge(57,36).
+edge(36,62).
+edge(62,36).
+edge(36,84).
+edge(84,36).
+edge(36,85).
+edge(85,36).
+edge(36,95).
+edge(95,36).
+edge(36,102).
+edge(102,36).
+edge(36,112).
+edge(112,36).
+edge(36,115).
+edge(115,36).
+edge(36,117).
+edge(117,36).
+edge(37,58).
+edge(58,37).
+edge(37,83).
+edge(83,37).
+edge(37,84).
+edge(84,37).
+edge(37,86).
+edge(86,37).
+edge(37,91).
+edge(91,37).
+edge(37,97).
+edge(97,37).
+edge(37,98).
+edge(98,37).
+edge(37,121).
+edge(121,37).
+edge(38,42).
+edge(42,38).
+edge(38,45).
+edge(45,38).
+edge(38,55).
+edge(55,38).
+edge(38,56).
+edge(56,38).
+edge(38,62).
+edge(62,38).
+edge(38,98).
+edge(98,38).
+edge(38,100).
+edge(100,38).
+edge(38,105).
+edge(105,38).
+edge(38,120).
+edge(120,38).
+edge(38,121).
+edge(121,38).
+edge(38,124).
+edge(124,38).
+edge(39,46).
+edge(46,39).
+edge(39,52).
+edge(52,39).
+edge(39,63).
+edge(63,39).
+edge(39,80).
+edge(80,39).
+edge(39,88).
+edge(88,39).
+edge(39,92).
+edge(92,39).
+edge(39,111).
+edge(111,39).
+edge(39,120).
+edge(120,39).
+edge(40,52).
+edge(52,40).
+edge(40,56).
+edge(56,40).
+edge(40,60).
+edge(60,40).
+edge(40,71).
+edge(71,40).
+edge(40,79).
+edge(79,40).
+edge(40,94).
+edge(94,40).
+edge(40,95).
+edge(95,40).
+edge(40,105).
+edge(105,40).
+edge(40,118).
+edge(118,40).
+edge(40,120).
+edge(120,40).
+edge(40,124).
+edge(124,40).
+edge(41,44).
+edge(44,41).
+edge(41,70).
+edge(70,41).
+edge(41,71).
+edge(71,41).
+edge(41,85).
+edge(85,41).
+edge(41,92).
+edge(92,41).
+edge(41,102).
+edge(102,41).
+edge(41,105).
+edge(105,41).
+edge(41,114).
+edge(114,41).
+edge(41,122).
+edge(122,41).
+edge(42,47).
+edge(47,42).
+edge(42,68).
+edge(68,42).
+edge(42,79).
+edge(79,42).
+edge(42,81).
+edge(81,42).
+edge(42,104).
+edge(104,42).
+edge(42,105).
+edge(105,42).
+edge(42,107).
+edge(107,42).
+edge(43,44).
+edge(44,43).
+edge(43,45).
+edge(45,43).
+edge(43,47).
+edge(47,43).
+edge(43,48).
+edge(48,43).
+edge(43,50).
+edge(50,43).
+edge(43,56).
+edge(56,43).
+edge(43,70).
+edge(70,43).
+edge(43,71).
+edge(71,43).
+edge(43,81).
+edge(81,43).
+edge(43,82).
+edge(82,43).
+edge(43,83).
+edge(83,43).
+edge(43,91).
+edge(91,43).
+edge(43,102).
+edge(102,43).
+edge(43,109).
+edge(109,43).
+edge(43,123).
+edge(123,43).
+edge(44,52).
+edge(52,44).
+edge(44,55).
+edge(55,44).
+edge(44,60).
+edge(60,44).
+edge(44,65).
+edge(65,44).
+edge(44,75).
+edge(75,44).
+edge(44,79).
+edge(79,44).
+edge(44,90).
+edge(90,44).
+edge(44,92).
+edge(92,44).
+edge(44,97).
+edge(97,44).
+edge(44,109).
+edge(109,44).
+edge(44,117).
+edge(117,44).
+edge(44,122).
+edge(122,44).
+edge(45,54).
+edge(54,45).
+edge(45,55).
+edge(55,45).
+edge(45,72).
+edge(72,45).
+edge(45,75).
+edge(75,45).
+edge(45,77).
+edge(77,45).
+edge(45,101).
+edge(101,45).
+edge(45,122).
+edge(122,45).
+edge(45,123).
+edge(123,45).
+edge(46,61).
+edge(61,46).
+edge(46,63).
+edge(63,46).
+edge(46,69).
+edge(69,46).
+edge(46,72).
+edge(72,46).
+edge(46,76).
+edge(76,46).
+edge(46,90).
+edge(90,46).
+edge(46,122).
+edge(122,46).
+edge(47,71).
+edge(71,47).
+edge(47,77).
+edge(77,47).
+edge(47,83).
+edge(83,47).
+edge(47,86).
+edge(86,47).
+edge(47,91).
+edge(91,47).
+edge(47,93).
+edge(93,47).
+edge(47,122).
+edge(122,47).
+edge(48,52).
+edge(52,48).
+edge(48,60).
+edge(60,48).
+edge(48,64).
+edge(64,48).
+edge(48,73).
+edge(73,48).
+edge(48,75).
+edge(75,48).
+edge(48,80).
+edge(80,48).
+edge(48,81).
+edge(81,48).
+edge(48,84).
+edge(84,48).
+edge(48,85).
+edge(85,48).
+edge(48,89).
+edge(89,48).
+edge(48,93).
+edge(93,48).
+edge(48,107).
+edge(107,48).
+edge(48,123).
+edge(123,48).
+edge(49,53).
+edge(53,49).
+edge(49,74).
+edge(74,49).
+edge(49,75).
+edge(75,49).
+edge(49,78).
+edge(78,49).
+edge(49,84).
+edge(84,49).
+edge(49,87).
+edge(87,49).
+edge(49,90).
+edge(90,49).
+edge(49,95).
+edge(95,49).
+edge(49,101).
+edge(101,49).
+edge(49,124).
+edge(124,49).
+edge(50,54).
+edge(54,50).
+edge(50,65).
+edge(65,50).
+edge(50,78).
+edge(78,50).
+edge(50,88).
+edge(88,50).
+edge(50,91).
+edge(91,50).
+edge(50,101).
+edge(101,50).
+edge(50,112).
+edge(112,50).
+edge(51,56).
+edge(56,51).
+edge(51,69).
+edge(69,51).
+edge(51,73).
+edge(73,51).
+edge(51,84).
+edge(84,51).
+edge(51,86).
+edge(86,51).
+edge(51,98).
+edge(98,51).
+edge(51,111).
+edge(111,51).
+edge(51,117).
+edge(117,51).
+edge(52,59).
+edge(59,52).
+edge(52,66).
+edge(66,52).
+edge(52,76).
+edge(76,52).
+edge(52,77).
+edge(77,52).
+edge(52,82).
+edge(82,52).
+edge(52,85).
+edge(85,52).
+edge(52,120).
+edge(120,52).
+edge(53,63).
+edge(63,53).
+edge(53,65).
+edge(65,53).
+edge(53,77).
+edge(77,53).
+edge(53,85).
+edge(85,53).
+edge(53,96).
+edge(96,53).
+edge(53,108).
+edge(108,53).
+edge(53,125).
+edge(125,53).
+edge(54,62).
+edge(62,54).
+edge(54,73).
+edge(73,54).
+edge(54,76).
+edge(76,54).
+edge(54,78).
+edge(78,54).
+edge(54,86).
+edge(86,54).
+edge(54,94).
+edge(94,54).
+edge(54,118).
+edge(118,54).
+edge(55,71).
+edge(71,55).
+edge(55,77).
+edge(77,55).
+edge(55,83).
+edge(83,55).
+edge(55,100).
+edge(100,55).
+edge(55,103).
+edge(103,55).
+edge(55,108).
+edge(108,55).
+edge(55,113).
+edge(113,55).
+edge(56,62).
+edge(62,56).
+edge(56,64).
+edge(64,56).
+edge(56,72).
+edge(72,56).
+edge(56,78).
+edge(78,56).
+edge(56,80).
+edge(80,56).
+edge(56,85).
+edge(85,56).
+edge(56,95).
+edge(95,56).
+edge(56,107).
+edge(107,56).
+edge(57,59).
+edge(59,57).
+edge(57,64).
+edge(64,57).
+edge(57,66).
+edge(66,57).
+edge(57,78).
+edge(78,57).
+edge(57,81).
+edge(81,57).
+edge(57,86).
+edge(86,57).
+edge(57,93).
+edge(93,57).
+edge(57,97).
+edge(97,57).
+edge(57,107).
+edge(107,57).
+edge(57,116).
+edge(116,57).
+edge(58,71).
+edge(71,58).
+edge(58,91).
+edge(91,58).
+edge(58,114).
+edge(114,58).
+edge(59,78).
+edge(78,59).
+edge(59,85).
+edge(85,59).
+edge(59,92).
+edge(92,59).
+edge(59,101).
+edge(101,59).
+edge(59,115).
+edge(115,59).
+edge(60,83).
+edge(83,60).
+edge(60,85).
+edge(85,60).
+edge(60,92).
+edge(92,60).
+edge(60,110).
+edge(110,60).
+edge(60,113).
+edge(113,60).
+edge(61,62).
+edge(62,61).
+edge(61,65).
+edge(65,61).
+edge(61,74).
+edge(74,61).
+edge(61,84).
+edge(84,61).
+edge(61,105).
+edge(105,61).
+edge(61,124).
+edge(124,61).
+edge(62,97).
+edge(97,62).
+edge(62,106).
+edge(106,62).
+edge(62,107).
+edge(107,62).
+edge(62,116).
+edge(116,62).
+edge(63,65).
+edge(65,63).
+edge(63,66).
+edge(66,63).
+edge(63,72).
+edge(72,63).
+edge(63,73).
+edge(73,63).
+edge(63,84).
+edge(84,63).
+edge(63,90).
+edge(90,63).
+edge(63,94).
+edge(94,63).
+edge(63,120).
+edge(120,63).
+edge(64,67).
+edge(67,64).
+edge(64,76).
+edge(76,64).
+edge(64,88).
+edge(88,64).
+edge(64,91).
+edge(91,64).
+edge(64,100).
+edge(100,64).
+edge(64,110).
+edge(110,64).
+edge(65,72).
+edge(72,65).
+edge(65,79).
+edge(79,65).
+edge(65,82).
+edge(82,65).
+edge(65,92).
+edge(92,65).
+edge(65,100).
+edge(100,65).
+edge(65,108).
+edge(108,65).
+edge(66,67).
+edge(67,66).
+edge(66,71).
+edge(71,66).
+edge(66,74).
+edge(74,66).
+edge(67,74).
+edge(74,67).
+edge(67,79).
+edge(79,67).
+edge(67,95).
+edge(95,67).
+edge(67,99).
+edge(99,67).
+edge(67,115).
+edge(115,67).
+edge(67,123).
+edge(123,67).
+edge(68,81).
+edge(81,68).
+edge(68,88).
+edge(88,68).
+edge(68,96).
+edge(96,68).
+edge(68,120).
+edge(120,68).
+edge(69,72).
+edge(72,69).
+edge(69,91).
+edge(91,69).
+edge(69,117).
+edge(117,69).
+edge(70,72).
+edge(72,70).
+edge(70,100).
+edge(100,70).
+edge(70,105).
+edge(105,70).
+edge(70,107).
+edge(107,70).
+edge(70,116).
+edge(116,70).
+edge(70,121).
+edge(121,70).
+edge(70,123).
+edge(123,70).
+edge(71,84).
+edge(84,71).
+edge(71,92).
+edge(92,71).
+edge(71,95).
+edge(95,71).
+edge(71,102).
+edge(102,71).
+edge(71,112).
+edge(112,71).
+edge(71,117).
+edge(117,71).
+edge(71,124).
+edge(124,71).
+edge(72,87).
+edge(87,72).
+edge(72,88).
+edge(88,72).
+edge(72,94).
+edge(94,72).
+edge(72,109).
+edge(109,72).
+edge(72,116).
+edge(116,72).
+edge(72,123).
+edge(123,72).
+edge(72,124).
+edge(124,72).
+edge(73,76).
+edge(76,73).
+edge(73,87).
+edge(87,73).
+edge(73,114).
+edge(114,73).
+edge(74,87).
+edge(87,74).
+edge(74,88).
+edge(88,74).
+edge(74,103).
+edge(103,74).
+edge(74,125).
+edge(125,74).
+edge(75,81).
+edge(81,75).
+edge(75,84).
+edge(84,75).
+edge(75,92).
+edge(92,75).
+edge(75,96).
+edge(96,75).
+edge(75,115).
+edge(115,75).
+edge(76,80).
+edge(80,76).
+edge(76,89).
+edge(89,76).
+edge(76,104).
+edge(104,76).
+edge(76,112).
+edge(112,76).
+edge(77,78).
+edge(78,77).
+edge(77,80).
+edge(80,77).
+edge(77,83).
+edge(83,77).
+edge(77,86).
+edge(86,77).
+edge(77,89).
+edge(89,77).
+edge(77,90).
+edge(90,77).
+edge(77,94).
+edge(94,77).
+edge(77,96).
+edge(96,77).
+edge(77,98).
+edge(98,77).
+edge(77,101).
+edge(101,77).
+edge(77,102).
+edge(102,77).
+edge(77,108).
+edge(108,77).
+edge(78,83).
+edge(83,78).
+edge(78,84).
+edge(84,78).
+edge(78,88).
+edge(88,78).
+edge(78,90).
+edge(90,78).
+edge(78,93).
+edge(93,78).
+edge(78,105).
+edge(105,78).
+edge(78,117).
+edge(117,78).
+edge(78,119).
+edge(119,78).
+edge(78,120).
+edge(120,78).
+edge(78,122).
+edge(122,78).
+edge(79,81).
+edge(81,79).
+edge(79,118).
+edge(118,79).
+edge(80,81).
+edge(81,80).
+edge(80,85).
+edge(85,80).
+edge(80,88).
+edge(88,80).
+edge(80,98).
+edge(98,80).
+edge(80,107).
+edge(107,80).
+edge(80,113).
+edge(113,80).
+edge(80,125).
+edge(125,80).
+edge(81,89).
+edge(89,81).
+edge(81,98).
+edge(98,81).
+edge(81,111).
+edge(111,81).
+edge(81,123).
+edge(123,81).
+edge(82,86).
+edge(86,82).
+edge(82,96).
+edge(96,82).
+edge(83,92).
+edge(92,83).
+edge(83,111).
+edge(111,83).
+edge(83,115).
+edge(115,83).
+edge(84,89).
+edge(89,84).
+edge(84,100).
+edge(100,84).
+edge(84,101).
+edge(101,84).
+edge(84,105).
+edge(105,84).
+edge(84,122).
+edge(122,84).
+edge(85,91).
+edge(91,85).
+edge(85,94).
+edge(94,85).
+edge(85,109).
+edge(109,85).
+edge(85,120).
+edge(120,85).
+edge(85,121).
+edge(121,85).
+edge(85,124).
+edge(124,85).
+edge(86,101).
+edge(101,86).
+edge(86,122).
+edge(122,86).
+edge(87,92).
+edge(92,87).
+edge(87,102).
+edge(102,87).
+edge(87,111).
+edge(111,87).
+edge(88,93).
+edge(93,88).
+edge(88,105).
+edge(105,88).
+edge(89,91).
+edge(91,89).
+edge(89,98).
+edge(98,89).
+edge(89,114).
+edge(114,89).
+edge(89,116).
+edge(116,89).
+edge(90,98).
+edge(98,90).
+edge(90,99).
+edge(99,90).
+edge(90,122).
+edge(122,90).
+edge(91,96).
+edge(96,91).
+edge(91,110).
+edge(110,91).
+edge(92,93).
+edge(93,92).
+edge(92,115).
+edge(115,92).
+edge(93,95).
+edge(95,93).
+edge(93,106).
+edge(106,93).
+edge(93,112).
+edge(112,93).
+edge(95,107).
+edge(107,95).
+edge(95,108).
+edge(108,95).
+edge(95,111).
+edge(111,95).
+edge(95,113).
+edge(113,95).
+edge(96,99).
+edge(99,96).
+edge(96,100).
+edge(100,96).
+edge(96,104).
+edge(104,96).
+edge(96,120).
+edge(120,96).
+edge(96,124).
+edge(124,96).
+edge(97,100).
+edge(100,97).
+edge(97,111).
+edge(111,97).
+edge(97,113).
+edge(113,97).
+edge(97,115).
+edge(115,97).
+edge(97,121).
+edge(121,97).
+edge(98,114).
+edge(114,98).
+edge(98,122).
+edge(122,98).
+edge(98,123).
+edge(123,98).
+edge(99,108).
+edge(108,99).
+edge(99,113).
+edge(113,99).
+edge(99,118).
+edge(118,99).
+edge(99,124).
+edge(124,99).
+edge(100,109).
+edge(109,100).
+edge(100,110).
+edge(110,100).
+edge(101,110).
+edge(110,101).
+edge(101,112).
+edge(112,101).
+edge(101,122).
+edge(122,101).
+edge(102,107).
+edge(107,102).
+edge(102,112).
+edge(112,102).
+edge(102,117).
+edge(117,102).
+edge(103,109).
+edge(109,103).
+edge(103,112).
+edge(112,103).
+edge(104,106).
+edge(106,104).
+edge(104,107).
+edge(107,104).
+edge(105,110).
+edge(110,105).
+edge(105,113).
+edge(113,105).
+edge(106,111).
+edge(111,106).
+edge(106,122).
+edge(122,106).
+edge(107,118).
+edge(118,107).
+edge(109,110).
+edge(110,109).
+edge(109,121).
+edge(121,109).
+edge(110,111).
+edge(111,110).
+edge(110,121).
+edge(121,110).
+edge(111,112).
+edge(112,111).
+edge(111,116).
+edge(116,111).
+edge(111,120).
+edge(120,111).
+edge(111,124).
+edge(124,111).
+edge(112,115).
+edge(115,112).
+edge(112,119).
+edge(119,112).
+edge(113,115).
+edge(115,113).
+edge(117,124).
+edge(124,117).
+edge(119,123).
+edge(123,119).
+edge(119,124).
+edge(124,119).
+edge(122,123).
+edge(123,122).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0005-graph_colouring-125-0.lp b/examples/clingo/expansion/GraphColouring/instances/0005-graph_colouring-125-0.lp
new file mode 100644
index 0000000..b7372a7
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0005-graph_colouring-125-0.lp
@@ -0,0 +1,1649 @@
+#const n=125.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+edge(1,22).
+edge(22,1).
+edge(1,28).
+edge(28,1).
+edge(1,29).
+edge(29,1).
+edge(1,41).
+edge(41,1).
+edge(1,50).
+edge(50,1).
+edge(1,53).
+edge(53,1).
+edge(1,57).
+edge(57,1).
+edge(1,65).
+edge(65,1).
+edge(1,69).
+edge(69,1).
+edge(1,83).
+edge(83,1).
+edge(1,88).
+edge(88,1).
+edge(1,89).
+edge(89,1).
+edge(1,120).
+edge(120,1).
+edge(2,41).
+edge(41,2).
+edge(2,63).
+edge(63,2).
+edge(2,73).
+edge(73,2).
+edge(2,74).
+edge(74,2).
+edge(2,78).
+edge(78,2).
+edge(2,86).
+edge(86,2).
+edge(2,93).
+edge(93,2).
+edge(2,95).
+edge(95,2).
+edge(2,105).
+edge(105,2).
+edge(2,109).
+edge(109,2).
+edge(3,5).
+edge(5,3).
+edge(3,34).
+edge(34,3).
+edge(3,38).
+edge(38,3).
+edge(3,58).
+edge(58,3).
+edge(3,73).
+edge(73,3).
+edge(3,74).
+edge(74,3).
+edge(3,78).
+edge(78,3).
+edge(3,79).
+edge(79,3).
+edge(3,80).
+edge(80,3).
+edge(3,114).
+edge(114,3).
+edge(4,13).
+edge(13,4).
+edge(4,26).
+edge(26,4).
+edge(4,50).
+edge(50,4).
+edge(4,51).
+edge(51,4).
+edge(4,54).
+edge(54,4).
+edge(4,55).
+edge(55,4).
+edge(4,63).
+edge(63,4).
+edge(4,71).
+edge(71,4).
+edge(4,83).
+edge(83,4).
+edge(4,100).
+edge(100,4).
+edge(4,115).
+edge(115,4).
+edge(5,12).
+edge(12,5).
+edge(5,23).
+edge(23,5).
+edge(5,25).
+edge(25,5).
+edge(5,27).
+edge(27,5).
+edge(5,39).
+edge(39,5).
+edge(5,45).
+edge(45,5).
+edge(5,51).
+edge(51,5).
+edge(5,57).
+edge(57,5).
+edge(5,63).
+edge(63,5).
+edge(5,67).
+edge(67,5).
+edge(5,70).
+edge(70,5).
+edge(5,97).
+edge(97,5).
+edge(5,115).
+edge(115,5).
+edge(6,9).
+edge(9,6).
+edge(6,26).
+edge(26,6).
+edge(6,39).
+edge(39,6).
+edge(6,57).
+edge(57,6).
+edge(6,73).
+edge(73,6).
+edge(6,84).
+edge(84,6).
+edge(6,86).
+edge(86,6).
+edge(6,90).
+edge(90,6).
+edge(6,96).
+edge(96,6).
+edge(6,110).
+edge(110,6).
+edge(6,119).
+edge(119,6).
+edge(7,9).
+edge(9,7).
+edge(7,20).
+edge(20,7).
+edge(7,35).
+edge(35,7).
+edge(7,38).
+edge(38,7).
+edge(7,44).
+edge(44,7).
+edge(7,52).
+edge(52,7).
+edge(7,55).
+edge(55,7).
+edge(7,57).
+edge(57,7).
+edge(7,64).
+edge(64,7).
+edge(7,69).
+edge(69,7).
+edge(7,70).
+edge(70,7).
+edge(7,76).
+edge(76,7).
+edge(7,85).
+edge(85,7).
+edge(7,86).
+edge(86,7).
+edge(7,124).
+edge(124,7).
+edge(8,14).
+edge(14,8).
+edge(8,17).
+edge(17,8).
+edge(8,28).
+edge(28,8).
+edge(8,39).
+edge(39,8).
+edge(8,58).
+edge(58,8).
+edge(8,61).
+edge(61,8).
+edge(8,65).
+edge(65,8).
+edge(8,72).
+edge(72,8).
+edge(8,99).
+edge(99,8).
+edge(8,101).
+edge(101,8).
+edge(8,111).
+edge(111,8).
+edge(8,112).
+edge(112,8).
+edge(9,10).
+edge(10,9).
+edge(9,11).
+edge(11,9).
+edge(9,24).
+edge(24,9).
+edge(9,28).
+edge(28,9).
+edge(9,33).
+edge(33,9).
+edge(9,35).
+edge(35,9).
+edge(9,73).
+edge(73,9).
+edge(9,75).
+edge(75,9).
+edge(9,80).
+edge(80,9).
+edge(9,103).
+edge(103,9).
+edge(9,108).
+edge(108,9).
+edge(9,123).
+edge(123,9).
+edge(10,18).
+edge(18,10).
+edge(10,26).
+edge(26,10).
+edge(10,34).
+edge(34,10).
+edge(10,39).
+edge(39,10).
+edge(10,42).
+edge(42,10).
+edge(10,43).
+edge(43,10).
+edge(10,50).
+edge(50,10).
+edge(10,54).
+edge(54,10).
+edge(10,60).
+edge(60,10).
+edge(10,64).
+edge(64,10).
+edge(10,66).
+edge(66,10).
+edge(10,71).
+edge(71,10).
+edge(10,74).
+edge(74,10).
+edge(10,97).
+edge(97,10).
+edge(10,124).
+edge(124,10).
+edge(11,18).
+edge(18,11).
+edge(11,35).
+edge(35,11).
+edge(11,50).
+edge(50,11).
+edge(11,51).
+edge(51,11).
+edge(11,60).
+edge(60,11).
+edge(11,63).
+edge(63,11).
+edge(11,108).
+edge(108,11).
+edge(11,115).
+edge(115,11).
+edge(11,116).
+edge(116,11).
+edge(11,119).
+edge(119,11).
+edge(11,120).
+edge(120,11).
+edge(11,124).
+edge(124,11).
+edge(12,25).
+edge(25,12).
+edge(12,27).
+edge(27,12).
+edge(12,31).
+edge(31,12).
+edge(12,37).
+edge(37,12).
+edge(12,40).
+edge(40,12).
+edge(12,44).
+edge(44,12).
+edge(12,51).
+edge(51,12).
+edge(12,52).
+edge(52,12).
+edge(12,58).
+edge(58,12).
+edge(12,80).
+edge(80,12).
+edge(12,82).
+edge(82,12).
+edge(12,107).
+edge(107,12).
+edge(13,16).
+edge(16,13).
+edge(13,33).
+edge(33,13).
+edge(13,38).
+edge(38,13).
+edge(13,40).
+edge(40,13).
+edge(13,82).
+edge(82,13).
+edge(13,89).
+edge(89,13).
+edge(14,19).
+edge(19,14).
+edge(14,46).
+edge(46,14).
+edge(14,48).
+edge(48,14).
+edge(14,49).
+edge(49,14).
+edge(14,54).
+edge(54,14).
+edge(14,57).
+edge(57,14).
+edge(14,64).
+edge(64,14).
+edge(14,80).
+edge(80,14).
+edge(14,89).
+edge(89,14).
+edge(14,97).
+edge(97,14).
+edge(14,99).
+edge(99,14).
+edge(14,107).
+edge(107,14).
+edge(14,108).
+edge(108,14).
+edge(14,110).
+edge(110,14).
+edge(14,115).
+edge(115,14).
+edge(15,41).
+edge(41,15).
+edge(15,46).
+edge(46,15).
+edge(15,50).
+edge(50,15).
+edge(15,74).
+edge(74,15).
+edge(15,79).
+edge(79,15).
+edge(15,87).
+edge(87,15).
+edge(15,90).
+edge(90,15).
+edge(15,91).
+edge(91,15).
+edge(15,98).
+edge(98,15).
+edge(15,102).
+edge(102,15).
+edge(15,104).
+edge(104,15).
+edge(15,106).
+edge(106,15).
+edge(15,112).
+edge(112,15).
+edge(15,115).
+edge(115,15).
+edge(15,117).
+edge(117,15).
+edge(15,124).
+edge(124,15).
+edge(16,17).
+edge(17,16).
+edge(16,35).
+edge(35,16).
+edge(16,43).
+edge(43,16).
+edge(16,45).
+edge(45,16).
+edge(16,46).
+edge(46,16).
+edge(16,58).
+edge(58,16).
+edge(16,61).
+edge(61,16).
+edge(16,91).
+edge(91,16).
+edge(16,93).
+edge(93,16).
+edge(16,100).
+edge(100,16).
+edge(17,42).
+edge(42,17).
+edge(17,44).
+edge(44,17).
+edge(17,60).
+edge(60,17).
+edge(17,62).
+edge(62,17).
+edge(17,66).
+edge(66,17).
+edge(17,67).
+edge(67,17).
+edge(17,85).
+edge(85,17).
+edge(17,91).
+edge(91,17).
+edge(17,93).
+edge(93,17).
+edge(17,105).
+edge(105,17).
+edge(18,30).
+edge(30,18).
+edge(18,35).
+edge(35,18).
+edge(18,61).
+edge(61,18).
+edge(18,62).
+edge(62,18).
+edge(18,84).
+edge(84,18).
+edge(18,85).
+edge(85,18).
+edge(18,103).
+edge(103,18).
+edge(18,107).
+edge(107,18).
+edge(18,110).
+edge(110,18).
+edge(19,20).
+edge(20,19).
+edge(19,22).
+edge(22,19).
+edge(19,24).
+edge(24,19).
+edge(19,29).
+edge(29,19).
+edge(19,36).
+edge(36,19).
+edge(19,40).
+edge(40,19).
+edge(19,64).
+edge(64,19).
+edge(19,91).
+edge(91,19).
+edge(19,92).
+edge(92,19).
+edge(19,104).
+edge(104,19).
+edge(19,115).
+edge(115,19).
+edge(19,116).
+edge(116,19).
+edge(19,124).
+edge(124,19).
+edge(20,27).
+edge(27,20).
+edge(20,35).
+edge(35,20).
+edge(20,44).
+edge(44,20).
+edge(20,67).
+edge(67,20).
+edge(20,75).
+edge(75,20).
+edge(20,98).
+edge(98,20).
+edge(20,124).
+edge(124,20).
+edge(20,125).
+edge(125,20).
+edge(21,25).
+edge(25,21).
+edge(21,29).
+edge(29,21).
+edge(21,41).
+edge(41,21).
+edge(21,50).
+edge(50,21).
+edge(21,52).
+edge(52,21).
+edge(21,54).
+edge(54,21).
+edge(21,80).
+edge(80,21).
+edge(21,81).
+edge(81,21).
+edge(21,83).
+edge(83,21).
+edge(21,93).
+edge(93,21).
+edge(21,99).
+edge(99,21).
+edge(21,111).
+edge(111,21).
+edge(22,46).
+edge(46,22).
+edge(22,55).
+edge(55,22).
+edge(22,70).
+edge(70,22).
+edge(22,73).
+edge(73,22).
+edge(22,93).
+edge(93,22).
+edge(23,27).
+edge(27,23).
+edge(23,28).
+edge(28,23).
+edge(23,29).
+edge(29,23).
+edge(23,30).
+edge(30,23).
+edge(23,37).
+edge(37,23).
+edge(23,43).
+edge(43,23).
+edge(23,51).
+edge(51,23).
+edge(23,57).
+edge(57,23).
+edge(23,66).
+edge(66,23).
+edge(23,70).
+edge(70,23).
+edge(23,77).
+edge(77,23).
+edge(23,85).
+edge(85,23).
+edge(23,109).
+edge(109,23).
+edge(23,123).
+edge(123,23).
+edge(24,48).
+edge(48,24).
+edge(24,52).
+edge(52,24).
+edge(24,56).
+edge(56,24).
+edge(24,86).
+edge(86,24).
+edge(24,98).
+edge(98,24).
+edge(24,119).
+edge(119,24).
+edge(24,120).
+edge(120,24).
+edge(24,125).
+edge(125,24).
+edge(25,28).
+edge(28,25).
+edge(25,33).
+edge(33,25).
+edge(25,64).
+edge(64,25).
+edge(25,68).
+edge(68,25).
+edge(25,71).
+edge(71,25).
+edge(25,74).
+edge(74,25).
+edge(25,84).
+edge(84,25).
+edge(25,93).
+edge(93,25).
+edge(25,99).
+edge(99,25).
+edge(25,112).
+edge(112,25).
+edge(25,118).
+edge(118,25).
+edge(26,30).
+edge(30,26).
+edge(26,32).
+edge(32,26).
+edge(26,54).
+edge(54,26).
+edge(26,64).
+edge(64,26).
+edge(26,76).
+edge(76,26).
+edge(26,77).
+edge(77,26).
+edge(26,78).
+edge(78,26).
+edge(26,79).
+edge(79,26).
+edge(26,83).
+edge(83,26).
+edge(26,84).
+edge(84,26).
+edge(26,86).
+edge(86,26).
+edge(26,91).
+edge(91,26).
+edge(26,99).
+edge(99,26).
+edge(26,104).
+edge(104,26).
+edge(26,110).
+edge(110,26).
+edge(26,119).
+edge(119,26).
+edge(26,120).
+edge(120,26).
+edge(26,124).
+edge(124,26).
+edge(27,59).
+edge(59,27).
+edge(27,68).
+edge(68,27).
+edge(27,75).
+edge(75,27).
+edge(27,76).
+edge(76,27).
+edge(27,90).
+edge(90,27).
+edge(27,97).
+edge(97,27).
+edge(27,99).
+edge(99,27).
+edge(27,103).
+edge(103,27).
+edge(27,105).
+edge(105,27).
+edge(28,31).
+edge(31,28).
+edge(28,47).
+edge(47,28).
+edge(28,58).
+edge(58,28).
+edge(28,73).
+edge(73,28).
+edge(28,97).
+edge(97,28).
+edge(29,30).
+edge(30,29).
+edge(29,47).
+edge(47,29).
+edge(29,64).
+edge(64,29).
+edge(29,70).
+edge(70,29).
+edge(29,85).
+edge(85,29).
+edge(29,112).
+edge(112,29).
+edge(29,114).
+edge(114,29).
+edge(29,122).
+edge(122,29).
+edge(29,125).
+edge(125,29).
+edge(30,33).
+edge(33,30).
+edge(30,44).
+edge(44,30).
+edge(30,53).
+edge(53,30).
+edge(30,76).
+edge(76,30).
+edge(30,85).
+edge(85,30).
+edge(30,89).
+edge(89,30).
+edge(30,104).
+edge(104,30).
+edge(30,111).
+edge(111,30).
+edge(30,116).
+edge(116,30).
+edge(31,48).
+edge(48,31).
+edge(31,53).
+edge(53,31).
+edge(31,65).
+edge(65,31).
+edge(31,79).
+edge(79,31).
+edge(31,93).
+edge(93,31).
+edge(31,105).
+edge(105,31).
+edge(31,116).
+edge(116,31).
+edge(31,117).
+edge(117,31).
+edge(32,41).
+edge(41,32).
+edge(32,42).
+edge(42,32).
+edge(32,46).
+edge(46,32).
+edge(32,52).
+edge(52,32).
+edge(32,55).
+edge(55,32).
+edge(32,59).
+edge(59,32).
+edge(32,73).
+edge(73,32).
+edge(32,74).
+edge(74,32).
+edge(32,86).
+edge(86,32).
+edge(32,102).
+edge(102,32).
+edge(32,110).
+edge(110,32).
+edge(32,111).
+edge(111,32).
+edge(33,35).
+edge(35,33).
+edge(33,39).
+edge(39,33).
+edge(33,40).
+edge(40,33).
+edge(33,41).
+edge(41,33).
+edge(33,45).
+edge(45,33).
+edge(33,85).
+edge(85,33).
+edge(33,114).
+edge(114,33).
+edge(33,122).
+edge(122,33).
+edge(34,38).
+edge(38,34).
+edge(34,40).
+edge(40,34).
+edge(34,51).
+edge(51,34).
+edge(34,54).
+edge(54,34).
+edge(34,61).
+edge(61,34).
+edge(34,74).
+edge(74,34).
+edge(34,84).
+edge(84,34).
+edge(34,109).
+edge(109,34).
+edge(34,114).
+edge(114,34).
+edge(35,42).
+edge(42,35).
+edge(35,45).
+edge(45,35).
+edge(35,48).
+edge(48,35).
+edge(35,86).
+edge(86,35).
+edge(36,46).
+edge(46,36).
+edge(36,52).
+edge(52,36).
+edge(36,66).
+edge(66,36).
+edge(36,67).
+edge(67,36).
+edge(36,69).
+edge(69,36).
+edge(36,73).
+edge(73,36).
+edge(36,75).
+edge(75,36).
+edge(36,76).
+edge(76,36).
+edge(36,92).
+edge(92,36).
+edge(36,98).
+edge(98,36).
+edge(36,110).
+edge(110,36).
+edge(36,121).
+edge(121,36).
+edge(37,42).
+edge(42,37).
+edge(37,60).
+edge(60,37).
+edge(37,63).
+edge(63,37).
+edge(37,72).
+edge(72,37).
+edge(37,77).
+edge(77,37).
+edge(37,89).
+edge(89,37).
+edge(37,101).
+edge(101,37).
+edge(37,108).
+edge(108,37).
+edge(37,109).
+edge(109,37).
+edge(38,56).
+edge(56,38).
+edge(38,58).
+edge(58,38).
+edge(38,72).
+edge(72,38).
+edge(38,85).
+edge(85,38).
+edge(38,108).
+edge(108,38).
+edge(39,47).
+edge(47,39).
+edge(39,75).
+edge(75,39).
+edge(39,76).
+edge(76,39).
+edge(39,87).
+edge(87,39).
+edge(39,94).
+edge(94,39).
+edge(39,104).
+edge(104,39).
+edge(39,111).
+edge(111,39).
+edge(39,124).
+edge(124,39).
+edge(40,45).
+edge(45,40).
+edge(40,59).
+edge(59,40).
+edge(40,72).
+edge(72,40).
+edge(40,84).
+edge(84,40).
+edge(40,101).
+edge(101,40).
+edge(40,113).
+edge(113,40).
+edge(40,114).
+edge(114,40).
+edge(40,117).
+edge(117,40).
+edge(41,46).
+edge(46,41).
+edge(41,80).
+edge(80,41).
+edge(41,82).
+edge(82,41).
+edge(41,86).
+edge(86,41).
+edge(41,87).
+edge(87,41).
+edge(41,92).
+edge(92,41).
+edge(41,97).
+edge(97,41).
+edge(41,106).
+edge(106,41).
+edge(41,122).
+edge(122,41).
+edge(42,43).
+edge(43,42).
+edge(42,67).
+edge(67,42).
+edge(42,69).
+edge(69,42).
+edge(42,87).
+edge(87,42).
+edge(42,109).
+edge(109,42).
+edge(42,113).
+edge(113,42).
+edge(42,117).
+edge(117,42).
+edge(43,53).
+edge(53,43).
+edge(43,65).
+edge(65,43).
+edge(43,67).
+edge(67,43).
+edge(43,69).
+edge(69,43).
+edge(43,73).
+edge(73,43).
+edge(43,80).
+edge(80,43).
+edge(43,82).
+edge(82,43).
+edge(43,90).
+edge(90,43).
+edge(43,112).
+edge(112,43).
+edge(43,120).
+edge(120,43).
+edge(43,123).
+edge(123,43).
+edge(44,51).
+edge(51,44).
+edge(44,71).
+edge(71,44).
+edge(44,91).
+edge(91,44).
+edge(44,105).
+edge(105,44).
+edge(44,112).
+edge(112,44).
+edge(44,116).
+edge(116,44).
+edge(44,123).
+edge(123,44).
+edge(44,124).
+edge(124,44).
+edge(45,71).
+edge(71,45).
+edge(45,74).
+edge(74,45).
+edge(45,99).
+edge(99,45).
+edge(45,100).
+edge(100,45).
+edge(45,106).
+edge(106,45).
+edge(45,107).
+edge(107,45).
+edge(45,123).
+edge(123,45).
+edge(46,59).
+edge(59,46).
+edge(46,63).
+edge(63,46).
+edge(46,71).
+edge(71,46).
+edge(46,85).
+edge(85,46).
+edge(46,94).
+edge(94,46).
+edge(46,115).
+edge(115,46).
+edge(46,118).
+edge(118,46).
+edge(47,61).
+edge(61,47).
+edge(47,81).
+edge(81,47).
+edge(47,91).
+edge(91,47).
+edge(47,101).
+edge(101,47).
+edge(47,103).
+edge(103,47).
+edge(47,111).
+edge(111,47).
+edge(47,121).
+edge(121,47).
+edge(47,125).
+edge(125,47).
+edge(48,57).
+edge(57,48).
+edge(48,58).
+edge(58,48).
+edge(48,78).
+edge(78,48).
+edge(48,88).
+edge(88,48).
+edge(48,103).
+edge(103,48).
+edge(48,104).
+edge(104,48).
+edge(49,97).
+edge(97,49).
+edge(49,101).
+edge(101,49).
+edge(49,110).
+edge(110,49).
+edge(49,113).
+edge(113,49).
+edge(49,117).
+edge(117,49).
+edge(49,119).
+edge(119,49).
+edge(49,124).
+edge(124,49).
+edge(50,65).
+edge(65,50).
+edge(50,70).
+edge(70,50).
+edge(50,72).
+edge(72,50).
+edge(50,79).
+edge(79,50).
+edge(50,90).
+edge(90,50).
+edge(50,107).
+edge(107,50).
+edge(50,111).
+edge(111,50).
+edge(50,117).
+edge(117,50).
+edge(51,54).
+edge(54,51).
+edge(51,60).
+edge(60,51).
+edge(51,72).
+edge(72,51).
+edge(51,89).
+edge(89,51).
+edge(51,103).
+edge(103,51).
+edge(51,106).
+edge(106,51).
+edge(51,111).
+edge(111,51).
+edge(51,122).
+edge(122,51).
+edge(52,70).
+edge(70,52).
+edge(52,117).
+edge(117,52).
+edge(52,119).
+edge(119,52).
+edge(52,125).
+edge(125,52).
+edge(53,80).
+edge(80,53).
+edge(53,93).
+edge(93,53).
+edge(53,98).
+edge(98,53).
+edge(53,108).
+edge(108,53).
+edge(53,112).
+edge(112,53).
+edge(54,65).
+edge(65,54).
+edge(54,92).
+edge(92,54).
+edge(54,99).
+edge(99,54).
+edge(54,107).
+edge(107,54).
+edge(54,114).
+edge(114,54).
+edge(54,117).
+edge(117,54).
+edge(54,118).
+edge(118,54).
+edge(54,120).
+edge(120,54).
+edge(54,124).
+edge(124,54).
+edge(54,125).
+edge(125,54).
+edge(55,73).
+edge(73,55).
+edge(55,79).
+edge(79,55).
+edge(55,85).
+edge(85,55).
+edge(55,89).
+edge(89,55).
+edge(55,98).
+edge(98,55).
+edge(55,101).
+edge(101,55).
+edge(55,104).
+edge(104,55).
+edge(55,109).
+edge(109,55).
+edge(55,113).
+edge(113,55).
+edge(56,64).
+edge(64,56).
+edge(56,66).
+edge(66,56).
+edge(56,76).
+edge(76,56).
+edge(56,81).
+edge(81,56).
+edge(56,87).
+edge(87,56).
+edge(56,96).
+edge(96,56).
+edge(56,112).
+edge(112,56).
+edge(57,60).
+edge(60,57).
+edge(57,71).
+edge(71,57).
+edge(57,80).
+edge(80,57).
+edge(57,88).
+edge(88,57).
+edge(57,123).
+edge(123,57).
+edge(58,59).
+edge(59,58).
+edge(58,60).
+edge(60,58).
+edge(58,74).
+edge(74,58).
+edge(58,76).
+edge(76,58).
+edge(58,89).
+edge(89,58).
+edge(58,106).
+edge(106,58).
+edge(58,122).
+edge(122,58).
+edge(59,65).
+edge(65,59).
+edge(59,67).
+edge(67,59).
+edge(59,77).
+edge(77,59).
+edge(59,79).
+edge(79,59).
+edge(59,89).
+edge(89,59).
+edge(59,108).
+edge(108,59).
+edge(59,110).
+edge(110,59).
+edge(59,117).
+edge(117,59).
+edge(60,61).
+edge(61,60).
+edge(60,64).
+edge(64,60).
+edge(60,65).
+edge(65,60).
+edge(60,79).
+edge(79,60).
+edge(60,82).
+edge(82,60).
+edge(60,97).
+edge(97,60).
+edge(60,104).
+edge(104,60).
+edge(60,109).
+edge(109,60).
+edge(60,117).
+edge(117,60).
+edge(60,119).
+edge(119,60).
+edge(61,75).
+edge(75,61).
+edge(61,90).
+edge(90,61).
+edge(61,91).
+edge(91,61).
+edge(61,108).
+edge(108,61).
+edge(61,111).
+edge(111,61).
+edge(61,112).
+edge(112,61).
+edge(61,114).
+edge(114,61).
+edge(62,89).
+edge(89,62).
+edge(62,113).
+edge(113,62).
+edge(62,115).
+edge(115,62).
+edge(63,68).
+edge(68,63).
+edge(63,74).
+edge(74,63).
+edge(63,89).
+edge(89,63).
+edge(63,93).
+edge(93,63).
+edge(63,116).
+edge(116,63).
+edge(63,119).
+edge(119,63).
+edge(64,71).
+edge(71,64).
+edge(64,82).
+edge(82,64).
+edge(64,94).
+edge(94,64).
+edge(64,102).
+edge(102,64).
+edge(64,106).
+edge(106,64).
+edge(64,120).
+edge(120,64).
+edge(65,67).
+edge(67,65).
+edge(65,69).
+edge(69,65).
+edge(65,80).
+edge(80,65).
+edge(65,88).
+edge(88,65).
+edge(65,109).
+edge(109,65).
+edge(66,68).
+edge(68,66).
+edge(66,86).
+edge(86,66).
+edge(66,88).
+edge(88,66).
+edge(66,91).
+edge(91,66).
+edge(66,106).
+edge(106,66).
+edge(66,107).
+edge(107,66).
+edge(66,113).
+edge(113,66).
+edge(67,81).
+edge(81,67).
+edge(67,94).
+edge(94,67).
+edge(67,98).
+edge(98,67).
+edge(67,103).
+edge(103,67).
+edge(67,110).
+edge(110,67).
+edge(67,119).
+edge(119,67).
+edge(68,90).
+edge(90,68).
+edge(68,107).
+edge(107,68).
+edge(69,80).
+edge(80,69).
+edge(69,90).
+edge(90,69).
+edge(69,96).
+edge(96,69).
+edge(69,97).
+edge(97,69).
+edge(69,99).
+edge(99,69).
+edge(69,116).
+edge(116,69).
+edge(69,119).
+edge(119,69).
+edge(69,123).
+edge(123,69).
+edge(70,72).
+edge(72,70).
+edge(70,73).
+edge(73,70).
+edge(70,98).
+edge(98,70).
+edge(70,100).
+edge(100,70).
+edge(70,102).
+edge(102,70).
+edge(70,116).
+edge(116,70).
+edge(70,125).
+edge(125,70).
+edge(71,80).
+edge(80,71).
+edge(71,85).
+edge(85,71).
+edge(71,94).
+edge(94,71).
+edge(71,117).
+edge(117,71).
+edge(72,82).
+edge(82,72).
+edge(72,93).
+edge(93,72).
+edge(72,94).
+edge(94,72).
+edge(72,96).
+edge(96,72).
+edge(72,107).
+edge(107,72).
+edge(72,117).
+edge(117,72).
+edge(73,77).
+edge(77,73).
+edge(73,79).
+edge(79,73).
+edge(73,85).
+edge(85,73).
+edge(73,99).
+edge(99,73).
+edge(73,102).
+edge(102,73).
+edge(73,110).
+edge(110,73).
+edge(73,118).
+edge(118,73).
+edge(73,123).
+edge(123,73).
+edge(74,93).
+edge(93,74).
+edge(74,102).
+edge(102,74).
+edge(75,83).
+edge(83,75).
+edge(75,89).
+edge(89,75).
+edge(75,92).
+edge(92,75).
+edge(75,120).
+edge(120,75).
+edge(75,123).
+edge(123,75).
+edge(76,78).
+edge(78,76).
+edge(76,79).
+edge(79,76).
+edge(76,88).
+edge(88,76).
+edge(76,89).
+edge(89,76).
+edge(76,105).
+edge(105,76).
+edge(76,109).
+edge(109,76).
+edge(76,112).
+edge(112,76).
+edge(77,85).
+edge(85,77).
+edge(77,87).
+edge(87,77).
+edge(77,101).
+edge(101,77).
+edge(77,105).
+edge(105,77).
+edge(77,109).
+edge(109,77).
+edge(78,88).
+edge(88,78).
+edge(78,100).
+edge(100,78).
+edge(78,118).
+edge(118,78).
+edge(79,95).
+edge(95,79).
+edge(79,106).
+edge(106,79).
+edge(79,109).
+edge(109,79).
+edge(79,123).
+edge(123,79).
+edge(80,84).
+edge(84,80).
+edge(80,87).
+edge(87,80).
+edge(81,85).
+edge(85,81).
+edge(81,96).
+edge(96,81).
+edge(81,98).
+edge(98,81).
+edge(81,103).
+edge(103,81).
+edge(81,109).
+edge(109,81).
+edge(81,110).
+edge(110,81).
+edge(81,115).
+edge(115,81).
+edge(82,99).
+edge(99,82).
+edge(82,102).
+edge(102,82).
+edge(82,113).
+edge(113,82).
+edge(82,119).
+edge(119,82).
+edge(82,120).
+edge(120,82).
+edge(83,92).
+edge(92,83).
+edge(83,110).
+edge(110,83).
+edge(83,112).
+edge(112,83).
+edge(83,122).
+edge(122,83).
+edge(84,86).
+edge(86,84).
+edge(84,89).
+edge(89,84).
+edge(84,123).
+edge(123,84).
+edge(85,87).
+edge(87,85).
+edge(85,95).
+edge(95,85).
+edge(85,101).
+edge(101,85).
+edge(86,89).
+edge(89,86).
+edge(86,98).
+edge(98,86).
+edge(86,103).
+edge(103,86).
+edge(86,114).
+edge(114,86).
+edge(86,117).
+edge(117,86).
+edge(86,120).
+edge(120,86).
+edge(86,122).
+edge(122,86).
+edge(87,108).
+edge(108,87).
+edge(87,112).
+edge(112,87).
+edge(88,99).
+edge(99,88).
+edge(88,103).
+edge(103,88).
+edge(88,108).
+edge(108,88).
+edge(88,110).
+edge(110,88).
+edge(88,125).
+edge(125,88).
+edge(89,92).
+edge(92,89).
+edge(89,95).
+edge(95,89).
+edge(89,103).
+edge(103,89).
+edge(89,118).
+edge(118,89).
+edge(90,115).
+edge(115,90).
+edge(90,118).
+edge(118,90).
+edge(91,110).
+edge(110,91).
+edge(92,93).
+edge(93,92).
+edge(92,99).
+edge(99,92).
+edge(92,104).
+edge(104,92).
+edge(92,106).
+edge(106,92).
+edge(93,104).
+edge(104,93).
+edge(93,115).
+edge(115,93).
+edge(93,122).
+edge(122,93).
+edge(94,114).
+edge(114,94).
+edge(95,97).
+edge(97,95).
+edge(95,115).
+edge(115,95).
+edge(96,120).
+edge(120,96).
+edge(97,99).
+edge(99,97).
+edge(97,110).
+edge(110,97).
+edge(97,113).
+edge(113,97).
+edge(97,122).
+edge(122,97).
+edge(101,124).
+edge(124,101).
+edge(102,111).
+edge(111,102).
+edge(102,116).
+edge(116,102).
+edge(103,125).
+edge(125,103).
+edge(104,112).
+edge(112,104).
+edge(104,119).
+edge(119,104).
+edge(104,120).
+edge(120,104).
+edge(105,111).
+edge(111,105).
+edge(105,112).
+edge(112,105).
+edge(105,119).
+edge(119,105).
+edge(106,115).
+edge(115,106).
+edge(106,123).
+edge(123,106).
+edge(107,112).
+edge(112,107).
+edge(107,113).
+edge(113,107).
+edge(107,117).
+edge(117,107).
+edge(107,125).
+edge(125,107).
+edge(108,113).
+edge(113,108).
+edge(108,114).
+edge(114,108).
+edge(108,117).
+edge(117,108).
+edge(109,111).
+edge(111,109).
+edge(109,112).
+edge(112,109).
+edge(109,122).
+edge(122,109).
+edge(110,122).
+edge(122,110).
+edge(112,122).
+edge(122,112).
+edge(113,114).
+edge(114,113).
+edge(113,117).
+edge(117,113).
+edge(114,122).
+edge(122,114).
+edge(114,123).
+edge(123,114).
+edge(115,121).
+edge(121,115).
+edge(115,123).
+edge(123,115).
+edge(116,120).
+edge(120,116).
+edge(117,121).
+edge(121,117).
+edge(118,124).
+edge(124,118).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0007-graph_colouring-125-0.lp b/examples/clingo/expansion/GraphColouring/instances/0007-graph_colouring-125-0.lp
new file mode 100644
index 0000000..7324cc7
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0007-graph_colouring-125-0.lp
@@ -0,0 +1,1609 @@
+#const n=125.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+edge(1,3).
+edge(3,1).
+edge(1,18).
+edge(18,1).
+edge(1,21).
+edge(21,1).
+edge(1,22).
+edge(22,1).
+edge(1,27).
+edge(27,1).
+edge(1,50).
+edge(50,1).
+edge(1,54).
+edge(54,1).
+edge(1,60).
+edge(60,1).
+edge(1,77).
+edge(77,1).
+edge(1,81).
+edge(81,1).
+edge(2,18).
+edge(18,2).
+edge(2,22).
+edge(22,2).
+edge(2,36).
+edge(36,2).
+edge(2,40).
+edge(40,2).
+edge(2,55).
+edge(55,2).
+edge(2,71).
+edge(71,2).
+edge(2,75).
+edge(75,2).
+edge(2,96).
+edge(96,2).
+edge(3,5).
+edge(5,3).
+edge(3,6).
+edge(6,3).
+edge(3,19).
+edge(19,3).
+edge(3,20).
+edge(20,3).
+edge(3,23).
+edge(23,3).
+edge(3,35).
+edge(35,3).
+edge(3,37).
+edge(37,3).
+edge(3,50).
+edge(50,3).
+edge(3,57).
+edge(57,3).
+edge(3,59).
+edge(59,3).
+edge(3,61).
+edge(61,3).
+edge(3,93).
+edge(93,3).
+edge(3,94).
+edge(94,3).
+edge(3,111).
+edge(111,3).
+edge(3,116).
+edge(116,3).
+edge(3,117).
+edge(117,3).
+edge(3,120).
+edge(120,3).
+edge(4,9).
+edge(9,4).
+edge(4,35).
+edge(35,4).
+edge(4,70).
+edge(70,4).
+edge(4,83).
+edge(83,4).
+edge(4,90).
+edge(90,4).
+edge(4,106).
+edge(106,4).
+edge(4,108).
+edge(108,4).
+edge(4,111).
+edge(111,4).
+edge(4,114).
+edge(114,4).
+edge(4,118).
+edge(118,4).
+edge(5,14).
+edge(14,5).
+edge(5,16).
+edge(16,5).
+edge(5,28).
+edge(28,5).
+edge(5,35).
+edge(35,5).
+edge(5,45).
+edge(45,5).
+edge(5,47).
+edge(47,5).
+edge(5,71).
+edge(71,5).
+edge(6,12).
+edge(12,6).
+edge(6,23).
+edge(23,6).
+edge(6,31).
+edge(31,6).
+edge(6,34).
+edge(34,6).
+edge(6,38).
+edge(38,6).
+edge(6,54).
+edge(54,6).
+edge(6,56).
+edge(56,6).
+edge(6,75).
+edge(75,6).
+edge(6,84).
+edge(84,6).
+edge(6,85).
+edge(85,6).
+edge(6,94).
+edge(94,6).
+edge(6,95).
+edge(95,6).
+edge(6,96).
+edge(96,6).
+edge(6,100).
+edge(100,6).
+edge(6,107).
+edge(107,6).
+edge(6,117).
+edge(117,6).
+edge(6,119).
+edge(119,6).
+edge(7,18).
+edge(18,7).
+edge(7,21).
+edge(21,7).
+edge(7,32).
+edge(32,7).
+edge(7,44).
+edge(44,7).
+edge(7,48).
+edge(48,7).
+edge(7,52).
+edge(52,7).
+edge(7,64).
+edge(64,7).
+edge(7,65).
+edge(65,7).
+edge(7,66).
+edge(66,7).
+edge(7,70).
+edge(70,7).
+edge(7,73).
+edge(73,7).
+edge(7,80).
+edge(80,7).
+edge(7,85).
+edge(85,7).
+edge(7,107).
+edge(107,7).
+edge(7,111).
+edge(111,7).
+edge(7,115).
+edge(115,7).
+edge(7,119).
+edge(119,7).
+edge(7,122).
+edge(122,7).
+edge(8,10).
+edge(10,8).
+edge(8,42).
+edge(42,8).
+edge(8,44).
+edge(44,8).
+edge(8,51).
+edge(51,8).
+edge(8,70).
+edge(70,8).
+edge(8,76).
+edge(76,8).
+edge(8,77).
+edge(77,8).
+edge(8,111).
+edge(111,8).
+edge(8,113).
+edge(113,8).
+edge(8,114).
+edge(114,8).
+edge(8,125).
+edge(125,8).
+edge(9,41).
+edge(41,9).
+edge(9,42).
+edge(42,9).
+edge(9,46).
+edge(46,9).
+edge(9,51).
+edge(51,9).
+edge(9,56).
+edge(56,9).
+edge(9,65).
+edge(65,9).
+edge(9,66).
+edge(66,9).
+edge(9,67).
+edge(67,9).
+edge(9,68).
+edge(68,9).
+edge(9,71).
+edge(71,9).
+edge(9,76).
+edge(76,9).
+edge(9,88).
+edge(88,9).
+edge(9,91).
+edge(91,9).
+edge(9,95).
+edge(95,9).
+edge(9,97).
+edge(97,9).
+edge(9,109).
+edge(109,9).
+edge(10,16).
+edge(16,10).
+edge(10,22).
+edge(22,10).
+edge(10,39).
+edge(39,10).
+edge(10,42).
+edge(42,10).
+edge(10,45).
+edge(45,10).
+edge(10,64).
+edge(64,10).
+edge(10,82).
+edge(82,10).
+edge(10,83).
+edge(83,10).
+edge(10,88).
+edge(88,10).
+edge(10,98).
+edge(98,10).
+edge(10,111).
+edge(111,10).
+edge(11,12).
+edge(12,11).
+edge(11,14).
+edge(14,11).
+edge(11,36).
+edge(36,11).
+edge(11,37).
+edge(37,11).
+edge(11,45).
+edge(45,11).
+edge(11,48).
+edge(48,11).
+edge(11,53).
+edge(53,11).
+edge(11,58).
+edge(58,11).
+edge(11,73).
+edge(73,11).
+edge(11,80).
+edge(80,11).
+edge(11,91).
+edge(91,11).
+edge(11,92).
+edge(92,11).
+edge(11,106).
+edge(106,11).
+edge(12,33).
+edge(33,12).
+edge(12,35).
+edge(35,12).
+edge(12,46).
+edge(46,12).
+edge(12,66).
+edge(66,12).
+edge(12,92).
+edge(92,12).
+edge(12,105).
+edge(105,12).
+edge(13,18).
+edge(18,13).
+edge(13,44).
+edge(44,13).
+edge(13,53).
+edge(53,13).
+edge(13,70).
+edge(70,13).
+edge(13,103).
+edge(103,13).
+edge(13,115).
+edge(115,13).
+edge(13,125).
+edge(125,13).
+edge(14,17).
+edge(17,14).
+edge(14,23).
+edge(23,14).
+edge(14,27).
+edge(27,14).
+edge(14,39).
+edge(39,14).
+edge(14,61).
+edge(61,14).
+edge(14,64).
+edge(64,14).
+edge(14,73).
+edge(73,14).
+edge(14,77).
+edge(77,14).
+edge(14,86).
+edge(86,14).
+edge(14,92).
+edge(92,14).
+edge(14,97).
+edge(97,14).
+edge(14,101).
+edge(101,14).
+edge(14,114).
+edge(114,14).
+edge(14,116).
+edge(116,14).
+edge(14,125).
+edge(125,14).
+edge(15,29).
+edge(29,15).
+edge(15,32).
+edge(32,15).
+edge(15,39).
+edge(39,15).
+edge(15,76).
+edge(76,15).
+edge(15,80).
+edge(80,15).
+edge(15,83).
+edge(83,15).
+edge(15,115).
+edge(115,15).
+edge(16,18).
+edge(18,16).
+edge(16,26).
+edge(26,16).
+edge(16,33).
+edge(33,16).
+edge(16,48).
+edge(48,16).
+edge(16,56).
+edge(56,16).
+edge(16,75).
+edge(75,16).
+edge(16,80).
+edge(80,16).
+edge(16,82).
+edge(82,16).
+edge(16,84).
+edge(84,16).
+edge(16,93).
+edge(93,16).
+edge(16,97).
+edge(97,16).
+edge(16,101).
+edge(101,16).
+edge(16,120).
+edge(120,16).
+edge(17,39).
+edge(39,17).
+edge(17,59).
+edge(59,17).
+edge(17,62).
+edge(62,17).
+edge(17,65).
+edge(65,17).
+edge(17,93).
+edge(93,17).
+edge(17,102).
+edge(102,17).
+edge(17,103).
+edge(103,17).
+edge(18,21).
+edge(21,18).
+edge(18,27).
+edge(27,18).
+edge(18,35).
+edge(35,18).
+edge(18,40).
+edge(40,18).
+edge(18,45).
+edge(45,18).
+edge(18,47).
+edge(47,18).
+edge(18,49).
+edge(49,18).
+edge(18,70).
+edge(70,18).
+edge(18,85).
+edge(85,18).
+edge(18,95).
+edge(95,18).
+edge(18,96).
+edge(96,18).
+edge(18,101).
+edge(101,18).
+edge(19,24).
+edge(24,19).
+edge(19,29).
+edge(29,19).
+edge(19,48).
+edge(48,19).
+edge(19,60).
+edge(60,19).
+edge(19,61).
+edge(61,19).
+edge(19,74).
+edge(74,19).
+edge(19,80).
+edge(80,19).
+edge(19,81).
+edge(81,19).
+edge(19,83).
+edge(83,19).
+edge(19,97).
+edge(97,19).
+edge(19,106).
+edge(106,19).
+edge(19,113).
+edge(113,19).
+edge(19,120).
+edge(120,19).
+edge(19,122).
+edge(122,19).
+edge(20,24).
+edge(24,20).
+edge(20,36).
+edge(36,20).
+edge(20,56).
+edge(56,20).
+edge(20,70).
+edge(70,20).
+edge(20,73).
+edge(73,20).
+edge(20,75).
+edge(75,20).
+edge(20,79).
+edge(79,20).
+edge(20,81).
+edge(81,20).
+edge(20,87).
+edge(87,20).
+edge(20,96).
+edge(96,20).
+edge(20,97).
+edge(97,20).
+edge(20,99).
+edge(99,20).
+edge(20,115).
+edge(115,20).
+edge(20,117).
+edge(117,20).
+edge(21,22).
+edge(22,21).
+edge(21,33).
+edge(33,21).
+edge(21,39).
+edge(39,21).
+edge(21,42).
+edge(42,21).
+edge(21,51).
+edge(51,21).
+edge(21,58).
+edge(58,21).
+edge(21,59).
+edge(59,21).
+edge(21,83).
+edge(83,21).
+edge(21,96).
+edge(96,21).
+edge(21,99).
+edge(99,21).
+edge(21,103).
+edge(103,21).
+edge(21,106).
+edge(106,21).
+edge(21,109).
+edge(109,21).
+edge(21,114).
+edge(114,21).
+edge(21,118).
+edge(118,21).
+edge(21,125).
+edge(125,21).
+edge(22,32).
+edge(32,22).
+edge(22,48).
+edge(48,22).
+edge(22,68).
+edge(68,22).
+edge(22,74).
+edge(74,22).
+edge(22,91).
+edge(91,22).
+edge(22,93).
+edge(93,22).
+edge(22,105).
+edge(105,22).
+edge(22,112).
+edge(112,22).
+edge(22,113).
+edge(113,22).
+edge(23,25).
+edge(25,23).
+edge(23,52).
+edge(52,23).
+edge(23,58).
+edge(58,23).
+edge(23,61).
+edge(61,23).
+edge(23,62).
+edge(62,23).
+edge(23,69).
+edge(69,23).
+edge(23,72).
+edge(72,23).
+edge(23,103).
+edge(103,23).
+edge(23,114).
+edge(114,23).
+edge(23,115).
+edge(115,23).
+edge(23,119).
+edge(119,23).
+edge(24,25).
+edge(25,24).
+edge(24,32).
+edge(32,24).
+edge(24,33).
+edge(33,24).
+edge(24,69).
+edge(69,24).
+edge(24,77).
+edge(77,24).
+edge(24,81).
+edge(81,24).
+edge(24,91).
+edge(91,24).
+edge(24,101).
+edge(101,24).
+edge(24,110).
+edge(110,24).
+edge(24,121).
+edge(121,24).
+edge(25,27).
+edge(27,25).
+edge(25,29).
+edge(29,25).
+edge(25,42).
+edge(42,25).
+edge(25,49).
+edge(49,25).
+edge(25,61).
+edge(61,25).
+edge(25,65).
+edge(65,25).
+edge(25,71).
+edge(71,25).
+edge(25,81).
+edge(81,25).
+edge(25,85).
+edge(85,25).
+edge(25,91).
+edge(91,25).
+edge(25,92).
+edge(92,25).
+edge(25,99).
+edge(99,25).
+edge(25,114).
+edge(114,25).
+edge(25,117).
+edge(117,25).
+edge(25,119).
+edge(119,25).
+edge(25,120).
+edge(120,25).
+edge(26,94).
+edge(94,26).
+edge(26,97).
+edge(97,26).
+edge(26,109).
+edge(109,26).
+edge(26,122).
+edge(122,26).
+edge(27,39).
+edge(39,27).
+edge(27,40).
+edge(40,27).
+edge(27,43).
+edge(43,27).
+edge(27,46).
+edge(46,27).
+edge(27,76).
+edge(76,27).
+edge(27,89).
+edge(89,27).
+edge(27,92).
+edge(92,27).
+edge(27,93).
+edge(93,27).
+edge(27,98).
+edge(98,27).
+edge(27,100).
+edge(100,27).
+edge(27,104).
+edge(104,27).
+edge(27,110).
+edge(110,27).
+edge(27,121).
+edge(121,27).
+edge(28,30).
+edge(30,28).
+edge(28,31).
+edge(31,28).
+edge(28,38).
+edge(38,28).
+edge(28,47).
+edge(47,28).
+edge(28,51).
+edge(51,28).
+edge(28,54).
+edge(54,28).
+edge(28,57).
+edge(57,28).
+edge(28,69).
+edge(69,28).
+edge(28,83).
+edge(83,28).
+edge(28,84).
+edge(84,28).
+edge(28,101).
+edge(101,28).
+edge(29,34).
+edge(34,29).
+edge(29,53).
+edge(53,29).
+edge(29,66).
+edge(66,29).
+edge(29,70).
+edge(70,29).
+edge(29,73).
+edge(73,29).
+edge(29,78).
+edge(78,29).
+edge(29,82).
+edge(82,29).
+edge(29,85).
+edge(85,29).
+edge(29,119).
+edge(119,29).
+edge(29,124).
+edge(124,29).
+edge(30,87).
+edge(87,30).
+edge(30,89).
+edge(89,30).
+edge(30,97).
+edge(97,30).
+edge(30,123).
+edge(123,30).
+edge(31,80).
+edge(80,31).
+edge(31,82).
+edge(82,31).
+edge(31,118).
+edge(118,31).
+edge(32,38).
+edge(38,32).
+edge(32,43).
+edge(43,32).
+edge(32,44).
+edge(44,32).
+edge(32,50).
+edge(50,32).
+edge(32,52).
+edge(52,32).
+edge(32,54).
+edge(54,32).
+edge(32,68).
+edge(68,32).
+edge(32,96).
+edge(96,32).
+edge(32,99).
+edge(99,32).
+edge(32,100).
+edge(100,32).
+edge(32,106).
+edge(106,32).
+edge(33,43).
+edge(43,33).
+edge(33,44).
+edge(44,33).
+edge(33,52).
+edge(52,33).
+edge(33,66).
+edge(66,33).
+edge(33,70).
+edge(70,33).
+edge(33,77).
+edge(77,33).
+edge(33,90).
+edge(90,33).
+edge(33,91).
+edge(91,33).
+edge(33,92).
+edge(92,33).
+edge(34,35).
+edge(35,34).
+edge(34,47).
+edge(47,34).
+edge(34,63).
+edge(63,34).
+edge(34,68).
+edge(68,34).
+edge(34,74).
+edge(74,34).
+edge(34,84).
+edge(84,34).
+edge(34,122).
+edge(122,34).
+edge(35,43).
+edge(43,35).
+edge(35,53).
+edge(53,35).
+edge(35,71).
+edge(71,35).
+edge(35,87).
+edge(87,35).
+edge(35,123).
+edge(123,35).
+edge(36,42).
+edge(42,36).
+edge(36,46).
+edge(46,36).
+edge(36,116).
+edge(116,36).
+edge(36,125).
+edge(125,36).
+edge(37,46).
+edge(46,37).
+edge(37,50).
+edge(50,37).
+edge(37,67).
+edge(67,37).
+edge(37,96).
+edge(96,37).
+edge(37,99).
+edge(99,37).
+edge(37,112).
+edge(112,37).
+edge(38,53).
+edge(53,38).
+edge(38,56).
+edge(56,38).
+edge(38,81).
+edge(81,38).
+edge(38,84).
+edge(84,38).
+edge(38,85).
+edge(85,38).
+edge(38,87).
+edge(87,38).
+edge(38,106).
+edge(106,38).
+edge(38,125).
+edge(125,38).
+edge(39,46).
+edge(46,39).
+edge(39,57).
+edge(57,39).
+edge(39,62).
+edge(62,39).
+edge(39,68).
+edge(68,39).
+edge(39,104).
+edge(104,39).
+edge(39,109).
+edge(109,39).
+edge(39,119).
+edge(119,39).
+edge(39,121).
+edge(121,39).
+edge(40,42).
+edge(42,40).
+edge(40,51).
+edge(51,40).
+edge(40,61).
+edge(61,40).
+edge(40,62).
+edge(62,40).
+edge(40,89).
+edge(89,40).
+edge(40,94).
+edge(94,40).
+edge(40,101).
+edge(101,40).
+edge(40,122).
+edge(122,40).
+edge(41,48).
+edge(48,41).
+edge(41,58).
+edge(58,41).
+edge(41,63).
+edge(63,41).
+edge(41,64).
+edge(64,41).
+edge(41,82).
+edge(82,41).
+edge(41,84).
+edge(84,41).
+edge(41,89).
+edge(89,41).
+edge(41,92).
+edge(92,41).
+edge(41,105).
+edge(105,41).
+edge(41,107).
+edge(107,41).
+edge(41,108).
+edge(108,41).
+edge(41,110).
+edge(110,41).
+edge(41,113).
+edge(113,41).
+edge(42,54).
+edge(54,42).
+edge(42,60).
+edge(60,42).
+edge(42,62).
+edge(62,42).
+edge(42,66).
+edge(66,42).
+edge(42,97).
+edge(97,42).
+edge(42,114).
+edge(114,42).
+edge(42,124).
+edge(124,42).
+edge(43,48).
+edge(48,43).
+edge(43,61).
+edge(61,43).
+edge(43,68).
+edge(68,43).
+edge(43,71).
+edge(71,43).
+edge(44,61).
+edge(61,44).
+edge(44,62).
+edge(62,44).
+edge(44,65).
+edge(65,44).
+edge(44,79).
+edge(79,44).
+edge(44,80).
+edge(80,44).
+edge(44,100).
+edge(100,44).
+edge(44,109).
+edge(109,44).
+edge(44,110).
+edge(110,44).
+edge(44,111).
+edge(111,44).
+edge(44,125).
+edge(125,44).
+edge(45,58).
+edge(58,45).
+edge(45,62).
+edge(62,45).
+edge(45,70).
+edge(70,45).
+edge(45,86).
+edge(86,45).
+edge(45,87).
+edge(87,45).
+edge(45,94).
+edge(94,45).
+edge(46,63).
+edge(63,46).
+edge(46,84).
+edge(84,46).
+edge(46,101).
+edge(101,46).
+edge(46,104).
+edge(104,46).
+edge(46,109).
+edge(109,46).
+edge(46,115).
+edge(115,46).
+edge(47,50).
+edge(50,47).
+edge(47,61).
+edge(61,47).
+edge(47,63).
+edge(63,47).
+edge(47,64).
+edge(64,47).
+edge(47,71).
+edge(71,47).
+edge(47,78).
+edge(78,47).
+edge(47,86).
+edge(86,47).
+edge(47,120).
+edge(120,47).
+edge(47,123).
+edge(123,47).
+edge(48,67).
+edge(67,48).
+edge(48,85).
+edge(85,48).
+edge(48,90).
+edge(90,48).
+edge(49,54).
+edge(54,49).
+edge(49,58).
+edge(58,49).
+edge(49,61).
+edge(61,49).
+edge(49,62).
+edge(62,49).
+edge(49,66).
+edge(66,49).
+edge(49,79).
+edge(79,49).
+edge(49,85).
+edge(85,49).
+edge(49,86).
+edge(86,49).
+edge(49,92).
+edge(92,49).
+edge(49,93).
+edge(93,49).
+edge(49,121).
+edge(121,49).
+edge(50,51).
+edge(51,50).
+edge(50,56).
+edge(56,50).
+edge(50,57).
+edge(57,50).
+edge(50,71).
+edge(71,50).
+edge(50,85).
+edge(85,50).
+edge(50,88).
+edge(88,50).
+edge(50,102).
+edge(102,50).
+edge(50,103).
+edge(103,50).
+edge(50,117).
+edge(117,50).
+edge(50,118).
+edge(118,50).
+edge(50,119).
+edge(119,50).
+edge(51,66).
+edge(66,51).
+edge(51,72).
+edge(72,51).
+edge(51,74).
+edge(74,51).
+edge(51,87).
+edge(87,51).
+edge(51,102).
+edge(102,51).
+edge(51,119).
+edge(119,51).
+edge(51,124).
+edge(124,51).
+edge(52,105).
+edge(105,52).
+edge(52,113).
+edge(113,52).
+edge(52,123).
+edge(123,52).
+edge(53,77).
+edge(77,53).
+edge(53,79).
+edge(79,53).
+edge(53,83).
+edge(83,53).
+edge(53,95).
+edge(95,53).
+edge(53,106).
+edge(106,53).
+edge(53,115).
+edge(115,53).
+edge(53,116).
+edge(116,53).
+edge(53,117).
+edge(117,53).
+edge(53,122).
+edge(122,53).
+edge(54,101).
+edge(101,54).
+edge(54,103).
+edge(103,54).
+edge(54,108).
+edge(108,54).
+edge(54,120).
+edge(120,54).
+edge(54,125).
+edge(125,54).
+edge(55,73).
+edge(73,55).
+edge(55,86).
+edge(86,55).
+edge(55,93).
+edge(93,55).
+edge(55,94).
+edge(94,55).
+edge(55,117).
+edge(117,55).
+edge(56,57).
+edge(57,56).
+edge(56,106).
+edge(106,56).
+edge(56,112).
+edge(112,56).
+edge(56,119).
+edge(119,56).
+edge(57,59).
+edge(59,57).
+edge(57,61).
+edge(61,57).
+edge(57,72).
+edge(72,57).
+edge(57,97).
+edge(97,57).
+edge(57,98).
+edge(98,57).
+edge(57,100).
+edge(100,57).
+edge(57,113).
+edge(113,57).
+edge(57,120).
+edge(120,57).
+edge(58,63).
+edge(63,58).
+edge(58,67).
+edge(67,58).
+edge(58,74).
+edge(74,58).
+edge(58,117).
+edge(117,58).
+edge(58,121).
+edge(121,58).
+edge(59,63).
+edge(63,59).
+edge(59,67).
+edge(67,59).
+edge(59,80).
+edge(80,59).
+edge(59,88).
+edge(88,59).
+edge(59,106).
+edge(106,59).
+edge(59,107).
+edge(107,59).
+edge(59,109).
+edge(109,59).
+edge(59,119).
+edge(119,59).
+edge(60,78).
+edge(78,60).
+edge(60,85).
+edge(85,60).
+edge(60,89).
+edge(89,60).
+edge(60,96).
+edge(96,60).
+edge(60,98).
+edge(98,60).
+edge(60,111).
+edge(111,60).
+edge(60,120).
+edge(120,60).
+edge(60,121).
+edge(121,60).
+edge(60,123).
+edge(123,60).
+edge(60,125).
+edge(125,60).
+edge(61,65).
+edge(65,61).
+edge(61,70).
+edge(70,61).
+edge(61,74).
+edge(74,61).
+edge(61,80).
+edge(80,61).
+edge(61,100).
+edge(100,61).
+edge(61,102).
+edge(102,61).
+edge(61,104).
+edge(104,61).
+edge(61,118).
+edge(118,61).
+edge(62,72).
+edge(72,62).
+edge(62,73).
+edge(73,62).
+edge(62,84).
+edge(84,62).
+edge(62,87).
+edge(87,62).
+edge(62,99).
+edge(99,62).
+edge(62,106).
+edge(106,62).
+edge(62,114).
+edge(114,62).
+edge(62,122).
+edge(122,62).
+edge(63,102).
+edge(102,63).
+edge(64,65).
+edge(65,64).
+edge(64,75).
+edge(75,64).
+edge(64,77).
+edge(77,64).
+edge(64,84).
+edge(84,64).
+edge(64,90).
+edge(90,64).
+edge(64,103).
+edge(103,64).
+edge(64,113).
+edge(113,64).
+edge(65,81).
+edge(81,65).
+edge(65,89).
+edge(89,65).
+edge(65,91).
+edge(91,65).
+edge(66,67).
+edge(67,66).
+edge(66,69).
+edge(69,66).
+edge(66,71).
+edge(71,66).
+edge(66,85).
+edge(85,66).
+edge(66,90).
+edge(90,66).
+edge(66,102).
+edge(102,66).
+edge(66,108).
+edge(108,66).
+edge(67,79).
+edge(79,67).
+edge(67,122).
+edge(122,67).
+edge(68,74).
+edge(74,68).
+edge(68,77).
+edge(77,68).
+edge(68,78).
+edge(78,68).
+edge(68,90).
+edge(90,68).
+edge(68,91).
+edge(91,68).
+edge(68,98).
+edge(98,68).
+edge(69,81).
+edge(81,69).
+edge(69,85).
+edge(85,69).
+edge(69,89).
+edge(89,69).
+edge(69,90).
+edge(90,69).
+edge(69,103).
+edge(103,69).
+edge(69,113).
+edge(113,69).
+edge(69,124).
+edge(124,69).
+edge(70,86).
+edge(86,70).
+edge(70,111).
+edge(111,70).
+edge(70,112).
+edge(112,70).
+edge(70,113).
+edge(113,70).
+edge(70,120).
+edge(120,70).
+edge(71,84).
+edge(84,71).
+edge(71,91).
+edge(91,71).
+edge(71,107).
+edge(107,71).
+edge(71,125).
+edge(125,71).
+edge(72,77).
+edge(77,72).
+edge(72,80).
+edge(80,72).
+edge(72,83).
+edge(83,72).
+edge(72,100).
+edge(100,72).
+edge(72,114).
+edge(114,72).
+edge(73,99).
+edge(99,73).
+edge(73,121).
+edge(121,73).
+edge(74,76).
+edge(76,74).
+edge(74,89).
+edge(89,74).
+edge(74,98).
+edge(98,74).
+edge(74,102).
+edge(102,74).
+edge(74,106).
+edge(106,74).
+edge(74,108).
+edge(108,74).
+edge(74,120).
+edge(120,74).
+edge(75,111).
+edge(111,75).
+edge(75,114).
+edge(114,75).
+edge(75,120).
+edge(120,75).
+edge(76,93).
+edge(93,76).
+edge(76,109).
+edge(109,76).
+edge(76,118).
+edge(118,76).
+edge(77,83).
+edge(83,77).
+edge(77,116).
+edge(116,77).
+edge(77,125).
+edge(125,77).
+edge(78,84).
+edge(84,78).
+edge(78,87).
+edge(87,78).
+edge(78,89).
+edge(89,78).
+edge(78,119).
+edge(119,78).
+edge(79,82).
+edge(82,79).
+edge(79,89).
+edge(89,79).
+edge(79,98).
+edge(98,79).
+edge(79,99).
+edge(99,79).
+edge(79,101).
+edge(101,79).
+edge(79,103).
+edge(103,79).
+edge(79,108).
+edge(108,79).
+edge(79,124).
+edge(124,79).
+edge(79,125).
+edge(125,79).
+edge(80,88).
+edge(88,80).
+edge(80,93).
+edge(93,80).
+edge(80,99).
+edge(99,80).
+edge(80,100).
+edge(100,80).
+edge(80,118).
+edge(118,80).
+edge(81,86).
+edge(86,81).
+edge(81,104).
+edge(104,81).
+edge(81,106).
+edge(106,81).
+edge(81,107).
+edge(107,81).
+edge(81,109).
+edge(109,81).
+edge(81,112).
+edge(112,81).
+edge(81,120).
+edge(120,81).
+edge(82,84).
+edge(84,82).
+edge(82,106).
+edge(106,82).
+edge(82,115).
+edge(115,82).
+edge(82,118).
+edge(118,82).
+edge(82,121).
+edge(121,82).
+edge(82,124).
+edge(124,82).
+edge(83,102).
+edge(102,83).
+edge(83,125).
+edge(125,83).
+edge(84,88).
+edge(88,84).
+edge(84,95).
+edge(95,84).
+edge(84,117).
+edge(117,84).
+edge(84,118).
+edge(118,84).
+edge(84,125).
+edge(125,84).
+edge(85,104).
+edge(104,85).
+edge(85,120).
+edge(120,85).
+edge(86,111).
+edge(111,86).
+edge(86,116).
+edge(116,86).
+edge(86,123).
+edge(123,86).
+edge(87,113).
+edge(113,87).
+edge(88,89).
+edge(89,88).
+edge(89,99).
+edge(99,89).
+edge(89,111).
+edge(111,89).
+edge(89,116).
+edge(116,89).
+edge(89,118).
+edge(118,89).
+edge(89,119).
+edge(119,89).
+edge(89,123).
+edge(123,89).
+edge(90,114).
+edge(114,90).
+edge(92,96).
+edge(96,92).
+edge(92,105).
+edge(105,92).
+edge(92,111).
+edge(111,92).
+edge(92,116).
+edge(116,92).
+edge(92,119).
+edge(119,92).
+edge(92,123).
+edge(123,92).
+edge(93,96).
+edge(96,93).
+edge(94,103).
+edge(103,94).
+edge(94,123).
+edge(123,94).
+edge(95,103).
+edge(103,95).
+edge(95,104).
+edge(104,95).
+edge(95,109).
+edge(109,95).
+edge(95,111).
+edge(111,95).
+edge(96,100).
+edge(100,96).
+edge(96,103).
+edge(103,96).
+edge(97,104).
+edge(104,97).
+edge(97,114).
+edge(114,97).
+edge(97,117).
+edge(117,97).
+edge(97,118).
+edge(118,97).
+edge(98,104).
+edge(104,98).
+edge(98,108).
+edge(108,98).
+edge(98,109).
+edge(109,98).
+edge(98,111).
+edge(111,98).
+edge(98,115).
+edge(115,98).
+edge(98,122).
+edge(122,98).
+edge(99,107).
+edge(107,99).
+edge(99,108).
+edge(108,99).
+edge(99,124).
+edge(124,99).
+edge(100,107).
+edge(107,100).
+edge(100,124).
+edge(124,100).
+edge(101,120).
+edge(120,101).
+edge(102,117).
+edge(117,102).
+edge(102,119).
+edge(119,102).
+edge(102,123).
+edge(123,102).
+edge(103,123).
+edge(123,103).
+edge(105,108).
+edge(108,105).
+edge(105,115).
+edge(115,105).
+edge(105,117).
+edge(117,105).
+edge(106,108).
+edge(108,106).
+edge(107,109).
+edge(109,107).
+edge(107,111).
+edge(111,107).
+edge(107,120).
+edge(120,107).
+edge(108,113).
+edge(113,108).
+edge(108,124).
+edge(124,108).
+edge(110,113).
+edge(113,110).
+edge(110,114).
+edge(114,110).
+edge(110,117).
+edge(117,110).
+edge(111,120).
+edge(120,111).
+edge(113,118).
+edge(118,113).
+edge(113,122).
+edge(122,113).
+edge(113,124).
+edge(124,113).
+edge(114,115).
+edge(115,114).
+edge(114,120).
+edge(120,114).
+edge(114,125).
+edge(125,114).
+edge(116,117).
+edge(117,116).
+edge(117,125).
+edge(125,117).
+edge(119,123).
+edge(123,119).
+edge(122,124).
+edge(124,122).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0008-graph_colouring-125-0.lp b/examples/clingo/expansion/GraphColouring/instances/0008-graph_colouring-125-0.lp
new file mode 100644
index 0000000..1c80e1f
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0008-graph_colouring-125-0.lp
@@ -0,0 +1,1677 @@
+#const n=125.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+edge(1,3).
+edge(3,1).
+edge(1,26).
+edge(26,1).
+edge(1,38).
+edge(38,1).
+edge(1,42).
+edge(42,1).
+edge(1,45).
+edge(45,1).
+edge(1,48).
+edge(48,1).
+edge(1,58).
+edge(58,1).
+edge(1,61).
+edge(61,1).
+edge(1,63).
+edge(63,1).
+edge(1,64).
+edge(64,1).
+edge(1,83).
+edge(83,1).
+edge(1,90).
+edge(90,1).
+edge(1,93).
+edge(93,1).
+edge(1,97).
+edge(97,1).
+edge(1,102).
+edge(102,1).
+edge(1,109).
+edge(109,1).
+edge(2,5).
+edge(5,2).
+edge(2,18).
+edge(18,2).
+edge(2,19).
+edge(19,2).
+edge(2,20).
+edge(20,2).
+edge(2,21).
+edge(21,2).
+edge(2,37).
+edge(37,2).
+edge(2,44).
+edge(44,2).
+edge(2,51).
+edge(51,2).
+edge(2,64).
+edge(64,2).
+edge(2,71).
+edge(71,2).
+edge(2,86).
+edge(86,2).
+edge(2,87).
+edge(87,2).
+edge(2,94).
+edge(94,2).
+edge(2,111).
+edge(111,2).
+edge(2,123).
+edge(123,2).
+edge(2,124).
+edge(124,2).
+edge(3,25).
+edge(25,3).
+edge(3,27).
+edge(27,3).
+edge(3,29).
+edge(29,3).
+edge(3,46).
+edge(46,3).
+edge(3,52).
+edge(52,3).
+edge(3,70).
+edge(70,3).
+edge(3,75).
+edge(75,3).
+edge(3,106).
+edge(106,3).
+edge(3,112).
+edge(112,3).
+edge(3,116).
+edge(116,3).
+edge(3,118).
+edge(118,3).
+edge(4,5).
+edge(5,4).
+edge(4,10).
+edge(10,4).
+edge(4,37).
+edge(37,4).
+edge(4,41).
+edge(41,4).
+edge(4,43).
+edge(43,4).
+edge(4,49).
+edge(49,4).
+edge(4,54).
+edge(54,4).
+edge(4,64).
+edge(64,4).
+edge(4,68).
+edge(68,4).
+edge(4,73).
+edge(73,4).
+edge(4,76).
+edge(76,4).
+edge(4,78).
+edge(78,4).
+edge(4,87).
+edge(87,4).
+edge(4,92).
+edge(92,4).
+edge(4,95).
+edge(95,4).
+edge(4,97).
+edge(97,4).
+edge(5,11).
+edge(11,5).
+edge(5,29).
+edge(29,5).
+edge(5,62).
+edge(62,5).
+edge(5,65).
+edge(65,5).
+edge(5,105).
+edge(105,5).
+edge(5,117).
+edge(117,5).
+edge(5,118).
+edge(118,5).
+edge(6,10).
+edge(10,6).
+edge(6,31).
+edge(31,6).
+edge(6,47).
+edge(47,6).
+edge(6,52).
+edge(52,6).
+edge(6,55).
+edge(55,6).
+edge(6,75).
+edge(75,6).
+edge(6,88).
+edge(88,6).
+edge(6,96).
+edge(96,6).
+edge(6,102).
+edge(102,6).
+edge(6,112).
+edge(112,6).
+edge(6,118).
+edge(118,6).
+edge(7,10).
+edge(10,7).
+edge(7,30).
+edge(30,7).
+edge(7,36).
+edge(36,7).
+edge(7,42).
+edge(42,7).
+edge(7,43).
+edge(43,7).
+edge(7,44).
+edge(44,7).
+edge(7,49).
+edge(49,7).
+edge(7,65).
+edge(65,7).
+edge(7,67).
+edge(67,7).
+edge(7,77).
+edge(77,7).
+edge(7,81).
+edge(81,7).
+edge(7,102).
+edge(102,7).
+edge(7,122).
+edge(122,7).
+edge(8,22).
+edge(22,8).
+edge(8,25).
+edge(25,8).
+edge(8,28).
+edge(28,8).
+edge(8,61).
+edge(61,8).
+edge(8,62).
+edge(62,8).
+edge(8,77).
+edge(77,8).
+edge(8,89).
+edge(89,8).
+edge(8,98).
+edge(98,8).
+edge(8,100).
+edge(100,8).
+edge(8,113).
+edge(113,8).
+edge(8,115).
+edge(115,8).
+edge(9,27).
+edge(27,9).
+edge(9,29).
+edge(29,9).
+edge(9,33).
+edge(33,9).
+edge(9,35).
+edge(35,9).
+edge(9,47).
+edge(47,9).
+edge(9,58).
+edge(58,9).
+edge(9,71).
+edge(71,9).
+edge(9,72).
+edge(72,9).
+edge(9,92).
+edge(92,9).
+edge(9,103).
+edge(103,9).
+edge(9,116).
+edge(116,9).
+edge(9,118).
+edge(118,9).
+edge(10,17).
+edge(17,10).
+edge(10,38).
+edge(38,10).
+edge(10,61).
+edge(61,10).
+edge(10,73).
+edge(73,10).
+edge(10,78).
+edge(78,10).
+edge(10,80).
+edge(80,10).
+edge(10,84).
+edge(84,10).
+edge(10,89).
+edge(89,10).
+edge(10,93).
+edge(93,10).
+edge(10,103).
+edge(103,10).
+edge(10,109).
+edge(109,10).
+edge(10,118).
+edge(118,10).
+edge(11,16).
+edge(16,11).
+edge(11,44).
+edge(44,11).
+edge(11,56).
+edge(56,11).
+edge(11,59).
+edge(59,11).
+edge(11,77).
+edge(77,11).
+edge(11,83).
+edge(83,11).
+edge(11,93).
+edge(93,11).
+edge(11,107).
+edge(107,11).
+edge(11,117).
+edge(117,11).
+edge(12,21).
+edge(21,12).
+edge(12,52).
+edge(52,12).
+edge(12,63).
+edge(63,12).
+edge(12,64).
+edge(64,12).
+edge(12,67).
+edge(67,12).
+edge(12,86).
+edge(86,12).
+edge(12,91).
+edge(91,12).
+edge(12,93).
+edge(93,12).
+edge(12,115).
+edge(115,12).
+edge(13,17).
+edge(17,13).
+edge(13,23).
+edge(23,13).
+edge(13,48).
+edge(48,13).
+edge(13,55).
+edge(55,13).
+edge(13,57).
+edge(57,13).
+edge(13,68).
+edge(68,13).
+edge(13,78).
+edge(78,13).
+edge(13,95).
+edge(95,13).
+edge(14,19).
+edge(19,14).
+edge(14,38).
+edge(38,14).
+edge(14,62).
+edge(62,14).
+edge(14,76).
+edge(76,14).
+edge(14,80).
+edge(80,14).
+edge(14,81).
+edge(81,14).
+edge(14,83).
+edge(83,14).
+edge(14,88).
+edge(88,14).
+edge(14,105).
+edge(105,14).
+edge(14,110).
+edge(110,14).
+edge(14,124).
+edge(124,14).
+edge(15,22).
+edge(22,15).
+edge(15,40).
+edge(40,15).
+edge(15,42).
+edge(42,15).
+edge(15,49).
+edge(49,15).
+edge(15,59).
+edge(59,15).
+edge(15,61).
+edge(61,15).
+edge(15,69).
+edge(69,15).
+edge(15,73).
+edge(73,15).
+edge(15,76).
+edge(76,15).
+edge(15,84).
+edge(84,15).
+edge(15,104).
+edge(104,15).
+edge(15,111).
+edge(111,15).
+edge(15,112).
+edge(112,15).
+edge(15,117).
+edge(117,15).
+edge(15,121).
+edge(121,15).
+edge(16,19).
+edge(19,16).
+edge(16,46).
+edge(46,16).
+edge(16,49).
+edge(49,16).
+edge(16,60).
+edge(60,16).
+edge(16,66).
+edge(66,16).
+edge(16,72).
+edge(72,16).
+edge(16,82).
+edge(82,16).
+edge(16,99).
+edge(99,16).
+edge(16,113).
+edge(113,16).
+edge(16,114).
+edge(114,16).
+edge(16,115).
+edge(115,16).
+edge(17,21).
+edge(21,17).
+edge(17,33).
+edge(33,17).
+edge(17,38).
+edge(38,17).
+edge(17,53).
+edge(53,17).
+edge(17,70).
+edge(70,17).
+edge(17,75).
+edge(75,17).
+edge(17,89).
+edge(89,17).
+edge(17,121).
+edge(121,17).
+edge(18,21).
+edge(21,18).
+edge(18,28).
+edge(28,18).
+edge(18,31).
+edge(31,18).
+edge(18,33).
+edge(33,18).
+edge(18,35).
+edge(35,18).
+edge(18,49).
+edge(49,18).
+edge(18,59).
+edge(59,18).
+edge(18,64).
+edge(64,18).
+edge(18,66).
+edge(66,18).
+edge(18,82).
+edge(82,18).
+edge(18,88).
+edge(88,18).
+edge(18,94).
+edge(94,18).
+edge(18,97).
+edge(97,18).
+edge(19,24).
+edge(24,19).
+edge(19,32).
+edge(32,19).
+edge(19,47).
+edge(47,19).
+edge(19,61).
+edge(61,19).
+edge(19,63).
+edge(63,19).
+edge(19,74).
+edge(74,19).
+edge(19,79).
+edge(79,19).
+edge(19,85).
+edge(85,19).
+edge(19,95).
+edge(95,19).
+edge(19,114).
+edge(114,19).
+edge(20,24).
+edge(24,20).
+edge(20,26).
+edge(26,20).
+edge(20,48).
+edge(48,20).
+edge(20,55).
+edge(55,20).
+edge(20,68).
+edge(68,20).
+edge(20,70).
+edge(70,20).
+edge(20,73).
+edge(73,20).
+edge(20,84).
+edge(84,20).
+edge(20,95).
+edge(95,20).
+edge(20,96).
+edge(96,20).
+edge(20,112).
+edge(112,20).
+edge(21,23).
+edge(23,21).
+edge(21,30).
+edge(30,21).
+edge(21,34).
+edge(34,21).
+edge(21,53).
+edge(53,21).
+edge(21,63).
+edge(63,21).
+edge(21,65).
+edge(65,21).
+edge(21,73).
+edge(73,21).
+edge(21,74).
+edge(74,21).
+edge(21,75).
+edge(75,21).
+edge(21,81).
+edge(81,21).
+edge(21,89).
+edge(89,21).
+edge(21,92).
+edge(92,21).
+edge(21,96).
+edge(96,21).
+edge(21,105).
+edge(105,21).
+edge(21,106).
+edge(106,21).
+edge(21,108).
+edge(108,21).
+edge(21,110).
+edge(110,21).
+edge(22,31).
+edge(31,22).
+edge(22,36).
+edge(36,22).
+edge(22,46).
+edge(46,22).
+edge(22,52).
+edge(52,22).
+edge(22,58).
+edge(58,22).
+edge(22,70).
+edge(70,22).
+edge(22,71).
+edge(71,22).
+edge(22,83).
+edge(83,22).
+edge(22,105).
+edge(105,22).
+edge(22,111).
+edge(111,22).
+edge(22,117).
+edge(117,22).
+edge(22,120).
+edge(120,22).
+edge(23,24).
+edge(24,23).
+edge(23,34).
+edge(34,23).
+edge(23,42).
+edge(42,23).
+edge(23,45).
+edge(45,23).
+edge(23,46).
+edge(46,23).
+edge(23,49).
+edge(49,23).
+edge(23,68).
+edge(68,23).
+edge(23,69).
+edge(69,23).
+edge(23,72).
+edge(72,23).
+edge(23,77).
+edge(77,23).
+edge(23,90).
+edge(90,23).
+edge(23,92).
+edge(92,23).
+edge(23,96).
+edge(96,23).
+edge(23,106).
+edge(106,23).
+edge(23,125).
+edge(125,23).
+edge(24,34).
+edge(34,24).
+edge(24,56).
+edge(56,24).
+edge(24,73).
+edge(73,24).
+edge(24,81).
+edge(81,24).
+edge(24,86).
+edge(86,24).
+edge(24,93).
+edge(93,24).
+edge(24,114).
+edge(114,24).
+edge(24,117).
+edge(117,24).
+edge(24,121).
+edge(121,24).
+edge(25,27).
+edge(27,25).
+edge(25,31).
+edge(31,25).
+edge(25,38).
+edge(38,25).
+edge(25,40).
+edge(40,25).
+edge(25,51).
+edge(51,25).
+edge(25,68).
+edge(68,25).
+edge(25,77).
+edge(77,25).
+edge(25,80).
+edge(80,25).
+edge(25,90).
+edge(90,25).
+edge(25,99).
+edge(99,25).
+edge(25,107).
+edge(107,25).
+edge(25,111).
+edge(111,25).
+edge(25,112).
+edge(112,25).
+edge(26,29).
+edge(29,26).
+edge(26,32).
+edge(32,26).
+edge(26,34).
+edge(34,26).
+edge(26,61).
+edge(61,26).
+edge(26,63).
+edge(63,26).
+edge(26,67).
+edge(67,26).
+edge(26,70).
+edge(70,26).
+edge(26,106).
+edge(106,26).
+edge(26,120).
+edge(120,26).
+edge(26,122).
+edge(122,26).
+edge(27,30).
+edge(30,27).
+edge(27,61).
+edge(61,27).
+edge(27,71).
+edge(71,27).
+edge(27,80).
+edge(80,27).
+edge(27,97).
+edge(97,27).
+edge(27,107).
+edge(107,27).
+edge(27,110).
+edge(110,27).
+edge(27,123).
+edge(123,27).
+edge(28,33).
+edge(33,28).
+edge(28,38).
+edge(38,28).
+edge(28,51).
+edge(51,28).
+edge(28,52).
+edge(52,28).
+edge(28,57).
+edge(57,28).
+edge(28,78).
+edge(78,28).
+edge(28,89).
+edge(89,28).
+edge(28,93).
+edge(93,28).
+edge(28,95).
+edge(95,28).
+edge(28,124).
+edge(124,28).
+edge(29,32).
+edge(32,29).
+edge(29,45).
+edge(45,29).
+edge(29,51).
+edge(51,29).
+edge(29,67).
+edge(67,29).
+edge(29,109).
+edge(109,29).
+edge(29,111).
+edge(111,29).
+edge(29,122).
+edge(122,29).
+edge(29,123).
+edge(123,29).
+edge(30,37).
+edge(37,30).
+edge(30,52).
+edge(52,30).
+edge(30,55).
+edge(55,30).
+edge(30,69).
+edge(69,30).
+edge(30,70).
+edge(70,30).
+edge(30,97).
+edge(97,30).
+edge(30,109).
+edge(109,30).
+edge(31,50).
+edge(50,31).
+edge(31,68).
+edge(68,31).
+edge(31,76).
+edge(76,31).
+edge(31,112).
+edge(112,31).
+edge(31,117).
+edge(117,31).
+edge(31,121).
+edge(121,31).
+edge(31,123).
+edge(123,31).
+edge(31,124).
+edge(124,31).
+edge(32,36).
+edge(36,32).
+edge(32,56).
+edge(56,32).
+edge(32,58).
+edge(58,32).
+edge(32,59).
+edge(59,32).
+edge(32,66).
+edge(66,32).
+edge(32,99).
+edge(99,32).
+edge(32,110).
+edge(110,32).
+edge(32,118).
+edge(118,32).
+edge(32,125).
+edge(125,32).
+edge(33,37).
+edge(37,33).
+edge(33,43).
+edge(43,33).
+edge(33,83).
+edge(83,33).
+edge(33,84).
+edge(84,33).
+edge(33,94).
+edge(94,33).
+edge(33,111).
+edge(111,33).
+edge(33,125).
+edge(125,33).
+edge(34,68).
+edge(68,34).
+edge(34,88).
+edge(88,34).
+edge(34,93).
+edge(93,34).
+edge(34,97).
+edge(97,34).
+edge(34,99).
+edge(99,34).
+edge(34,103).
+edge(103,34).
+edge(34,105).
+edge(105,34).
+edge(34,109).
+edge(109,34).
+edge(34,122).
+edge(122,34).
+edge(35,58).
+edge(58,35).
+edge(35,75).
+edge(75,35).
+edge(35,85).
+edge(85,35).
+edge(35,92).
+edge(92,35).
+edge(35,96).
+edge(96,35).
+edge(35,100).
+edge(100,35).
+edge(35,103).
+edge(103,35).
+edge(35,105).
+edge(105,35).
+edge(35,108).
+edge(108,35).
+edge(35,110).
+edge(110,35).
+edge(35,121).
+edge(121,35).
+edge(36,43).
+edge(43,36).
+edge(36,64).
+edge(64,36).
+edge(36,66).
+edge(66,36).
+edge(36,79).
+edge(79,36).
+edge(36,80).
+edge(80,36).
+edge(36,82).
+edge(82,36).
+edge(36,83).
+edge(83,36).
+edge(36,86).
+edge(86,36).
+edge(36,87).
+edge(87,36).
+edge(36,88).
+edge(88,36).
+edge(36,92).
+edge(92,36).
+edge(36,93).
+edge(93,36).
+edge(36,103).
+edge(103,36).
+edge(36,105).
+edge(105,36).
+edge(36,123).
+edge(123,36).
+edge(37,42).
+edge(42,37).
+edge(37,82).
+edge(82,37).
+edge(37,125).
+edge(125,37).
+edge(38,59).
+edge(59,38).
+edge(38,69).
+edge(69,38).
+edge(38,70).
+edge(70,38).
+edge(38,76).
+edge(76,38).
+edge(38,78).
+edge(78,38).
+edge(38,87).
+edge(87,38).
+edge(38,97).
+edge(97,38).
+edge(38,101).
+edge(101,38).
+edge(38,107).
+edge(107,38).
+edge(38,118).
+edge(118,38).
+edge(39,49).
+edge(49,39).
+edge(39,60).
+edge(60,39).
+edge(39,74).
+edge(74,39).
+edge(39,89).
+edge(89,39).
+edge(39,96).
+edge(96,39).
+edge(39,101).
+edge(101,39).
+edge(39,106).
+edge(106,39).
+edge(39,112).
+edge(112,39).
+edge(40,52).
+edge(52,40).
+edge(40,55).
+edge(55,40).
+edge(40,61).
+edge(61,40).
+edge(40,69).
+edge(69,40).
+edge(40,86).
+edge(86,40).
+edge(40,100).
+edge(100,40).
+edge(40,103).
+edge(103,40).
+edge(40,125).
+edge(125,40).
+edge(41,42).
+edge(42,41).
+edge(41,45).
+edge(45,41).
+edge(41,52).
+edge(52,41).
+edge(41,63).
+edge(63,41).
+edge(41,70).
+edge(70,41).
+edge(41,73).
+edge(73,41).
+edge(41,88).
+edge(88,41).
+edge(41,107).
+edge(107,41).
+edge(41,113).
+edge(113,41).
+edge(42,67).
+edge(67,42).
+edge(42,95).
+edge(95,42).
+edge(42,97).
+edge(97,42).
+edge(42,114).
+edge(114,42).
+edge(42,117).
+edge(117,42).
+edge(43,45).
+edge(45,43).
+edge(43,50).
+edge(50,43).
+edge(43,54).
+edge(54,43).
+edge(43,56).
+edge(56,43).
+edge(43,61).
+edge(61,43).
+edge(43,63).
+edge(63,43).
+edge(43,78).
+edge(78,43).
+edge(43,86).
+edge(86,43).
+edge(43,95).
+edge(95,43).
+edge(43,99).
+edge(99,43).
+edge(43,118).
+edge(118,43).
+edge(43,122).
+edge(122,43).
+edge(44,45).
+edge(45,44).
+edge(44,48).
+edge(48,44).
+edge(44,70).
+edge(70,44).
+edge(44,76).
+edge(76,44).
+edge(44,83).
+edge(83,44).
+edge(44,85).
+edge(85,44).
+edge(44,89).
+edge(89,44).
+edge(44,97).
+edge(97,44).
+edge(44,102).
+edge(102,44).
+edge(44,109).
+edge(109,44).
+edge(44,111).
+edge(111,44).
+edge(45,46).
+edge(46,45).
+edge(45,59).
+edge(59,45).
+edge(45,66).
+edge(66,45).
+edge(45,67).
+edge(67,45).
+edge(45,99).
+edge(99,45).
+edge(45,114).
+edge(114,45).
+edge(45,123).
+edge(123,45).
+edge(45,125).
+edge(125,45).
+edge(46,51).
+edge(51,46).
+edge(46,53).
+edge(53,46).
+edge(46,59).
+edge(59,46).
+edge(46,64).
+edge(64,46).
+edge(46,66).
+edge(66,46).
+edge(46,69).
+edge(69,46).
+edge(46,71).
+edge(71,46).
+edge(46,83).
+edge(83,46).
+edge(46,103).
+edge(103,46).
+edge(46,107).
+edge(107,46).
+edge(46,118).
+edge(118,46).
+edge(47,78).
+edge(78,47).
+edge(47,80).
+edge(80,47).
+edge(47,91).
+edge(91,47).
+edge(47,96).
+edge(96,47).
+edge(47,124).
+edge(124,47).
+edge(48,51).
+edge(51,48).
+edge(48,52).
+edge(52,48).
+edge(48,60).
+edge(60,48).
+edge(48,70).
+edge(70,48).
+edge(48,82).
+edge(82,48).
+edge(48,95).
+edge(95,48).
+edge(48,108).
+edge(108,48).
+edge(48,113).
+edge(113,48).
+edge(48,119).
+edge(119,48).
+edge(48,122).
+edge(122,48).
+edge(49,64).
+edge(64,49).
+edge(49,72).
+edge(72,49).
+edge(49,86).
+edge(86,49).
+edge(49,97).
+edge(97,49).
+edge(49,119).
+edge(119,49).
+edge(49,122).
+edge(122,49).
+edge(50,55).
+edge(55,50).
+edge(50,63).
+edge(63,50).
+edge(50,72).
+edge(72,50).
+edge(50,94).
+edge(94,50).
+edge(50,118).
+edge(118,50).
+edge(50,122).
+edge(122,50).
+edge(51,53).
+edge(53,51).
+edge(51,63).
+edge(63,51).
+edge(51,72).
+edge(72,51).
+edge(51,83).
+edge(83,51).
+edge(51,91).
+edge(91,51).
+edge(51,125).
+edge(125,51).
+edge(52,62).
+edge(62,52).
+edge(52,63).
+edge(63,52).
+edge(52,96).
+edge(96,52).
+edge(52,117).
+edge(117,52).
+edge(52,118).
+edge(118,52).
+edge(53,58).
+edge(58,53).
+edge(53,59).
+edge(59,53).
+edge(53,65).
+edge(65,53).
+edge(53,69).
+edge(69,53).
+edge(53,77).
+edge(77,53).
+edge(53,84).
+edge(84,53).
+edge(53,88).
+edge(88,53).
+edge(53,92).
+edge(92,53).
+edge(53,96).
+edge(96,53).
+edge(53,100).
+edge(100,53).
+edge(53,109).
+edge(109,53).
+edge(54,57).
+edge(57,54).
+edge(54,59).
+edge(59,54).
+edge(54,94).
+edge(94,54).
+edge(55,56).
+edge(56,55).
+edge(55,93).
+edge(93,55).
+edge(55,106).
+edge(106,55).
+edge(55,113).
+edge(113,55).
+edge(55,118).
+edge(118,55).
+edge(56,60).
+edge(60,56).
+edge(56,82).
+edge(82,56).
+edge(56,87).
+edge(87,56).
+edge(56,98).
+edge(98,56).
+edge(56,102).
+edge(102,56).
+edge(56,105).
+edge(105,56).
+edge(56,107).
+edge(107,56).
+edge(56,120).
+edge(120,56).
+edge(57,70).
+edge(70,57).
+edge(57,72).
+edge(72,57).
+edge(57,85).
+edge(85,57).
+edge(57,89).
+edge(89,57).
+edge(57,94).
+edge(94,57).
+edge(57,99).
+edge(99,57).
+edge(57,105).
+edge(105,57).
+edge(57,125).
+edge(125,57).
+edge(58,60).
+edge(60,58).
+edge(58,62).
+edge(62,58).
+edge(58,72).
+edge(72,58).
+edge(58,80).
+edge(80,58).
+edge(58,82).
+edge(82,58).
+edge(58,83).
+edge(83,58).
+edge(58,86).
+edge(86,58).
+edge(58,91).
+edge(91,58).
+edge(58,93).
+edge(93,58).
+edge(58,105).
+edge(105,58).
+edge(58,120).
+edge(120,58).
+edge(59,76).
+edge(76,59).
+edge(59,78).
+edge(78,59).
+edge(59,96).
+edge(96,59).
+edge(59,121).
+edge(121,59).
+edge(60,64).
+edge(64,60).
+edge(60,66).
+edge(66,60).
+edge(60,70).
+edge(70,60).
+edge(60,77).
+edge(77,60).
+edge(60,84).
+edge(84,60).
+edge(60,86).
+edge(86,60).
+edge(60,100).
+edge(100,60).
+edge(60,101).
+edge(101,60).
+edge(60,103).
+edge(103,60).
+edge(60,113).
+edge(113,60).
+edge(60,115).
+edge(115,60).
+edge(60,116).
+edge(116,60).
+edge(60,119).
+edge(119,60).
+edge(60,122).
+edge(122,60).
+edge(61,69).
+edge(69,61).
+edge(61,89).
+edge(89,61).
+edge(61,94).
+edge(94,61).
+edge(61,109).
+edge(109,61).
+edge(61,115).
+edge(115,61).
+edge(61,119).
+edge(119,61).
+edge(61,120).
+edge(120,61).
+edge(62,73).
+edge(73,62).
+edge(62,92).
+edge(92,62).
+edge(62,98).
+edge(98,62).
+edge(63,68).
+edge(68,63).
+edge(63,83).
+edge(83,63).
+edge(63,86).
+edge(86,63).
+edge(63,99).
+edge(99,63).
+edge(63,114).
+edge(114,63).
+edge(63,115).
+edge(115,63).
+edge(63,122).
+edge(122,63).
+edge(63,124).
+edge(124,63).
+edge(64,83).
+edge(83,64).
+edge(64,87).
+edge(87,64).
+edge(64,90).
+edge(90,64).
+edge(64,92).
+edge(92,64).
+edge(64,116).
+edge(116,64).
+edge(64,124).
+edge(124,64).
+edge(65,66).
+edge(66,65).
+edge(65,68).
+edge(68,65).
+edge(65,75).
+edge(75,65).
+edge(65,82).
+edge(82,65).
+edge(65,88).
+edge(88,65).
+edge(65,93).
+edge(93,65).
+edge(65,101).
+edge(101,65).
+edge(65,123).
+edge(123,65).
+edge(66,76).
+edge(76,66).
+edge(66,77).
+edge(77,66).
+edge(66,88).
+edge(88,66).
+edge(66,101).
+edge(101,66).
+edge(66,110).
+edge(110,66).
+edge(66,111).
+edge(111,66).
+edge(66,114).
+edge(114,66).
+edge(66,120).
+edge(120,66).
+edge(66,121).
+edge(121,66).
+edge(66,122).
+edge(122,66).
+edge(66,125).
+edge(125,66).
+edge(67,70).
+edge(70,67).
+edge(67,74).
+edge(74,67).
+edge(67,101).
+edge(101,67).
+edge(67,107).
+edge(107,67).
+edge(68,83).
+edge(83,68).
+edge(68,104).
+edge(104,68).
+edge(69,74).
+edge(74,69).
+edge(69,77).
+edge(77,69).
+edge(69,97).
+edge(97,69).
+edge(70,73).
+edge(73,70).
+edge(70,89).
+edge(89,70).
+edge(70,98).
+edge(98,70).
+edge(70,111).
+edge(111,70).
+edge(71,73).
+edge(73,71).
+edge(71,85).
+edge(85,71).
+edge(71,107).
+edge(107,71).
+edge(71,114).
+edge(114,71).
+edge(71,116).
+edge(116,71).
+edge(71,118).
+edge(118,71).
+edge(72,84).
+edge(84,72).
+edge(72,94).
+edge(94,72).
+edge(72,113).
+edge(113,72).
+edge(72,115).
+edge(115,72).
+edge(72,118).
+edge(118,72).
+edge(72,124).
+edge(124,72).
+edge(73,79).
+edge(79,73).
+edge(73,81).
+edge(81,73).
+edge(73,90).
+edge(90,73).
+edge(73,91).
+edge(91,73).
+edge(73,96).
+edge(96,73).
+edge(73,97).
+edge(97,73).
+edge(73,117).
+edge(117,73).
+edge(73,123).
+edge(123,73).
+edge(73,125).
+edge(125,73).
+edge(74,82).
+edge(82,74).
+edge(74,90).
+edge(90,74).
+edge(74,115).
+edge(115,74).
+edge(75,84).
+edge(84,75).
+edge(76,85).
+edge(85,76).
+edge(76,123).
+edge(123,76).
+edge(77,83).
+edge(83,77).
+edge(77,95).
+edge(95,77).
+edge(77,100).
+edge(100,77).
+edge(77,104).
+edge(104,77).
+edge(77,106).
+edge(106,77).
+edge(77,107).
+edge(107,77).
+edge(77,108).
+edge(108,77).
+edge(77,109).
+edge(109,77).
+edge(77,116).
+edge(116,77).
+edge(78,96).
+edge(96,78).
+edge(78,107).
+edge(107,78).
+edge(79,108).
+edge(108,79).
+edge(79,109).
+edge(109,79).
+edge(80,82).
+edge(82,80).
+edge(80,84).
+edge(84,80).
+edge(80,101).
+edge(101,80).
+edge(80,110).
+edge(110,80).
+edge(81,84).
+edge(84,81).
+edge(81,90).
+edge(90,81).
+edge(81,98).
+edge(98,81).
+edge(81,101).
+edge(101,81).
+edge(81,104).
+edge(104,81).
+edge(81,108).
+edge(108,81).
+edge(82,96).
+edge(96,82).
+edge(82,102).
+edge(102,82).
+edge(82,109).
+edge(109,82).
+edge(82,121).
+edge(121,82).
+edge(83,101).
+edge(101,83).
+edge(83,106).
+edge(106,83).
+edge(83,115).
+edge(115,83).
+edge(85,103).
+edge(103,85).
+edge(85,111).
+edge(111,85).
+edge(85,112).
+edge(112,85).
+edge(86,109).
+edge(109,86).
+edge(86,123).
+edge(123,86).
+edge(87,92).
+edge(92,87).
+edge(87,96).
+edge(96,87).
+edge(87,105).
+edge(105,87).
+edge(87,113).
+edge(113,87).
+edge(87,116).
+edge(116,87).
+edge(88,109).
+edge(109,88).
+edge(88,115).
+edge(115,88).
+edge(88,120).
+edge(120,88).
+edge(88,125).
+edge(125,88).
+edge(89,94).
+edge(94,89).
+edge(89,102).
+edge(102,89).
+edge(89,105).
+edge(105,89).
+edge(89,122).
+edge(122,89).
+edge(90,92).
+edge(92,90).
+edge(90,111).
+edge(111,90).
+edge(91,102).
+edge(102,91).
+edge(91,122).
+edge(122,91).
+edge(91,124).
+edge(124,91).
+edge(92,93).
+edge(93,92).
+edge(92,95).
+edge(95,92).
+edge(92,119).
+edge(119,92).
+edge(92,121).
+edge(121,92).
+edge(92,124).
+edge(124,92).
+edge(93,116).
+edge(116,93).
+edge(94,123).
+edge(123,94).
+edge(95,111).
+edge(111,95).
+edge(95,121).
+edge(121,95).
+edge(95,124).
+edge(124,95).
+edge(96,119).
+edge(119,96).
+edge(97,98).
+edge(98,97).
+edge(97,116).
+edge(116,97).
+edge(97,120).
+edge(120,97).
+edge(97,124).
+edge(124,97).
+edge(97,125).
+edge(125,97).
+edge(98,107).
+edge(107,98).
+edge(98,108).
+edge(108,98).
+edge(98,109).
+edge(109,98).
+edge(98,110).
+edge(110,98).
+edge(98,120).
+edge(120,98).
+edge(99,104).
+edge(104,99).
+edge(100,109).
+edge(109,100).
+edge(100,110).
+edge(110,100).
+edge(101,113).
+edge(113,101).
+edge(101,114).
+edge(114,101).
+edge(101,117).
+edge(117,101).
+edge(101,119).
+edge(119,101).
+edge(102,109).
+edge(109,102).
+edge(102,111).
+edge(111,102).
+edge(104,107).
+edge(107,104).
+edge(104,125).
+edge(125,104).
+edge(105,113).
+edge(113,105).
+edge(105,123).
+edge(123,105).
+edge(106,122).
+edge(122,106).
+edge(107,111).
+edge(111,107).
+edge(107,116).
+edge(116,107).
+edge(107,117).
+edge(117,107).
+edge(107,120).
+edge(120,107).
+edge(107,121).
+edge(121,107).
+edge(107,123).
+edge(123,107).
+edge(108,119).
+edge(119,108).
+edge(108,124).
+edge(124,108).
+edge(110,115).
+edge(115,110).
+edge(110,118).
+edge(118,110).
+edge(110,125).
+edge(125,110).
+edge(111,118).
+edge(118,111).
+edge(112,124).
+edge(124,112).
+edge(113,115).
+edge(115,113).
+edge(114,120).
+edge(120,114).
+edge(118,121).
+edge(121,118).
+edge(119,123).
+edge(123,119).
+edge(120,125).
+edge(125,120).
+edge(121,125).
+edge(125,121).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0013-graph_colouring-130-0.lp b/examples/clingo/expansion/GraphColouring/instances/0013-graph_colouring-130-0.lp
new file mode 100644
index 0000000..224a0f3
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0013-graph_colouring-130-0.lp
@@ -0,0 +1,1714 @@
+#const n=130.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+edge(1,5).
+edge(5,1).
+edge(1,35).
+edge(35,1).
+edge(1,37).
+edge(37,1).
+edge(1,44).
+edge(44,1).
+edge(1,64).
+edge(64,1).
+edge(1,76).
+edge(76,1).
+edge(1,78).
+edge(78,1).
+edge(1,85).
+edge(85,1).
+edge(1,86).
+edge(86,1).
+edge(1,88).
+edge(88,1).
+edge(1,96).
+edge(96,1).
+edge(1,102).
+edge(102,1).
+edge(1,114).
+edge(114,1).
+edge(1,121).
+edge(121,1).
+edge(1,124).
+edge(124,1).
+edge(1,125).
+edge(125,1).
+edge(1,128).
+edge(128,1).
+edge(1,130).
+edge(130,1).
+edge(2,6).
+edge(6,2).
+edge(2,16).
+edge(16,2).
+edge(2,29).
+edge(29,2).
+edge(2,33).
+edge(33,2).
+edge(2,35).
+edge(35,2).
+edge(2,38).
+edge(38,2).
+edge(2,79).
+edge(79,2).
+edge(2,83).
+edge(83,2).
+edge(2,103).
+edge(103,2).
+edge(2,122).
+edge(122,2).
+edge(2,125).
+edge(125,2).
+edge(2,126).
+edge(126,2).
+edge(2,129).
+edge(129,2).
+edge(3,7).
+edge(7,3).
+edge(3,10).
+edge(10,3).
+edge(3,26).
+edge(26,3).
+edge(3,40).
+edge(40,3).
+edge(3,42).
+edge(42,3).
+edge(3,55).
+edge(55,3).
+edge(3,74).
+edge(74,3).
+edge(3,79).
+edge(79,3).
+edge(3,90).
+edge(90,3).
+edge(3,100).
+edge(100,3).
+edge(3,127).
+edge(127,3).
+edge(4,8).
+edge(8,4).
+edge(4,16).
+edge(16,4).
+edge(4,17).
+edge(17,4).
+edge(4,28).
+edge(28,4).
+edge(4,31).
+edge(31,4).
+edge(4,35).
+edge(35,4).
+edge(4,43).
+edge(43,4).
+edge(4,54).
+edge(54,4).
+edge(4,57).
+edge(57,4).
+edge(4,77).
+edge(77,4).
+edge(4,82).
+edge(82,4).
+edge(4,87).
+edge(87,4).
+edge(4,91).
+edge(91,4).
+edge(4,92).
+edge(92,4).
+edge(4,124).
+edge(124,4).
+edge(5,15).
+edge(15,5).
+edge(5,19).
+edge(19,5).
+edge(5,28).
+edge(28,5).
+edge(5,31).
+edge(31,5).
+edge(5,55).
+edge(55,5).
+edge(5,58).
+edge(58,5).
+edge(5,93).
+edge(93,5).
+edge(5,99).
+edge(99,5).
+edge(5,100).
+edge(100,5).
+edge(5,113).
+edge(113,5).
+edge(5,124).
+edge(124,5).
+edge(5,125).
+edge(125,5).
+edge(5,126).
+edge(126,5).
+edge(5,128).
+edge(128,5).
+edge(5,129).
+edge(129,5).
+edge(6,30).
+edge(30,6).
+edge(6,34).
+edge(34,6).
+edge(6,53).
+edge(53,6).
+edge(6,70).
+edge(70,6).
+edge(6,75).
+edge(75,6).
+edge(6,78).
+edge(78,6).
+edge(6,85).
+edge(85,6).
+edge(6,111).
+edge(111,6).
+edge(6,122).
+edge(122,6).
+edge(7,18).
+edge(18,7).
+edge(7,29).
+edge(29,7).
+edge(7,60).
+edge(60,7).
+edge(7,67).
+edge(67,7).
+edge(7,82).
+edge(82,7).
+edge(7,88).
+edge(88,7).
+edge(7,91).
+edge(91,7).
+edge(7,107).
+edge(107,7).
+edge(7,122).
+edge(122,7).
+edge(8,16).
+edge(16,8).
+edge(8,23).
+edge(23,8).
+edge(8,27).
+edge(27,8).
+edge(8,32).
+edge(32,8).
+edge(8,37).
+edge(37,8).
+edge(8,47).
+edge(47,8).
+edge(8,57).
+edge(57,8).
+edge(8,68).
+edge(68,8).
+edge(8,75).
+edge(75,8).
+edge(8,79).
+edge(79,8).
+edge(8,97).
+edge(97,8).
+edge(8,107).
+edge(107,8).
+edge(8,112).
+edge(112,8).
+edge(8,121).
+edge(121,8).
+edge(8,125).
+edge(125,8).
+edge(9,13).
+edge(13,9).
+edge(9,30).
+edge(30,9).
+edge(9,50).
+edge(50,9).
+edge(9,51).
+edge(51,9).
+edge(9,86).
+edge(86,9).
+edge(9,99).
+edge(99,9).
+edge(9,102).
+edge(102,9).
+edge(9,110).
+edge(110,9).
+edge(9,116).
+edge(116,9).
+edge(10,15).
+edge(15,10).
+edge(10,19).
+edge(19,10).
+edge(10,24).
+edge(24,10).
+edge(10,36).
+edge(36,10).
+edge(10,37).
+edge(37,10).
+edge(10,47).
+edge(47,10).
+edge(10,65).
+edge(65,10).
+edge(10,96).
+edge(96,10).
+edge(10,98).
+edge(98,10).
+edge(10,126).
+edge(126,10).
+edge(11,26).
+edge(26,11).
+edge(11,27).
+edge(27,11).
+edge(11,34).
+edge(34,11).
+edge(11,59).
+edge(59,11).
+edge(11,71).
+edge(71,11).
+edge(11,74).
+edge(74,11).
+edge(11,85).
+edge(85,11).
+edge(11,110).
+edge(110,11).
+edge(11,111).
+edge(111,11).
+edge(11,113).
+edge(113,11).
+edge(11,115).
+edge(115,11).
+edge(11,126).
+edge(126,11).
+edge(11,127).
+edge(127,11).
+edge(12,18).
+edge(18,12).
+edge(12,27).
+edge(27,12).
+edge(12,58).
+edge(58,12).
+edge(12,60).
+edge(60,12).
+edge(12,89).
+edge(89,12).
+edge(12,116).
+edge(116,12).
+edge(12,129).
+edge(129,12).
+edge(13,20).
+edge(20,13).
+edge(13,23).
+edge(23,13).
+edge(13,27).
+edge(27,13).
+edge(13,29).
+edge(29,13).
+edge(13,32).
+edge(32,13).
+edge(13,59).
+edge(59,13).
+edge(13,77).
+edge(77,13).
+edge(13,79).
+edge(79,13).
+edge(13,81).
+edge(81,13).
+edge(13,93).
+edge(93,13).
+edge(13,94).
+edge(94,13).
+edge(13,104).
+edge(104,13).
+edge(13,111).
+edge(111,13).
+edge(13,112).
+edge(112,13).
+edge(13,121).
+edge(121,13).
+edge(13,124).
+edge(124,13).
+edge(13,125).
+edge(125,13).
+edge(13,130).
+edge(130,13).
+edge(14,37).
+edge(37,14).
+edge(14,43).
+edge(43,14).
+edge(14,46).
+edge(46,14).
+edge(14,51).
+edge(51,14).
+edge(14,54).
+edge(54,14).
+edge(14,72).
+edge(72,14).
+edge(14,81).
+edge(81,14).
+edge(14,87).
+edge(87,14).
+edge(15,44).
+edge(44,15).
+edge(15,58).
+edge(58,15).
+edge(15,69).
+edge(69,15).
+edge(15,75).
+edge(75,15).
+edge(15,103).
+edge(103,15).
+edge(15,104).
+edge(104,15).
+edge(15,111).
+edge(111,15).
+edge(15,129).
+edge(129,15).
+edge(16,32).
+edge(32,16).
+edge(16,40).
+edge(40,16).
+edge(16,42).
+edge(42,16).
+edge(16,74).
+edge(74,16).
+edge(16,82).
+edge(82,16).
+edge(16,90).
+edge(90,16).
+edge(16,110).
+edge(110,16).
+edge(16,123).
+edge(123,16).
+edge(17,21).
+edge(21,17).
+edge(17,31).
+edge(31,17).
+edge(17,32).
+edge(32,17).
+edge(17,42).
+edge(42,17).
+edge(17,46).
+edge(46,17).
+edge(17,50).
+edge(50,17).
+edge(17,58).
+edge(58,17).
+edge(17,63).
+edge(63,17).
+edge(17,81).
+edge(81,17).
+edge(17,87).
+edge(87,17).
+edge(17,108).
+edge(108,17).
+edge(17,109).
+edge(109,17).
+edge(17,110).
+edge(110,17).
+edge(17,126).
+edge(126,17).
+edge(17,129).
+edge(129,17).
+edge(18,26).
+edge(26,18).
+edge(18,32).
+edge(32,18).
+edge(18,42).
+edge(42,18).
+edge(18,62).
+edge(62,18).
+edge(18,68).
+edge(68,18).
+edge(18,76).
+edge(76,18).
+edge(18,77).
+edge(77,18).
+edge(18,82).
+edge(82,18).
+edge(18,84).
+edge(84,18).
+edge(18,92).
+edge(92,18).
+edge(18,94).
+edge(94,18).
+edge(18,95).
+edge(95,18).
+edge(18,117).
+edge(117,18).
+edge(19,31).
+edge(31,19).
+edge(19,45).
+edge(45,19).
+edge(19,51).
+edge(51,19).
+edge(19,72).
+edge(72,19).
+edge(19,91).
+edge(91,19).
+edge(19,102).
+edge(102,19).
+edge(19,105).
+edge(105,19).
+edge(19,112).
+edge(112,19).
+edge(19,116).
+edge(116,19).
+edge(19,119).
+edge(119,19).
+edge(19,122).
+edge(122,19).
+edge(19,124).
+edge(124,19).
+edge(20,21).
+edge(21,20).
+edge(20,41).
+edge(41,20).
+edge(20,51).
+edge(51,20).
+edge(20,68).
+edge(68,20).
+edge(20,80).
+edge(80,20).
+edge(20,86).
+edge(86,20).
+edge(20,95).
+edge(95,20).
+edge(20,109).
+edge(109,20).
+edge(20,116).
+edge(116,20).
+edge(20,129).
+edge(129,20).
+edge(21,23).
+edge(23,21).
+edge(21,27).
+edge(27,21).
+edge(21,38).
+edge(38,21).
+edge(21,58).
+edge(58,21).
+edge(21,59).
+edge(59,21).
+edge(21,91).
+edge(91,21).
+edge(21,101).
+edge(101,21).
+edge(21,109).
+edge(109,21).
+edge(21,117).
+edge(117,21).
+edge(22,24).
+edge(24,22).
+edge(22,49).
+edge(49,22).
+edge(22,62).
+edge(62,22).
+edge(22,77).
+edge(77,22).
+edge(22,83).
+edge(83,22).
+edge(23,25).
+edge(25,23).
+edge(23,33).
+edge(33,23).
+edge(23,50).
+edge(50,23).
+edge(23,52).
+edge(52,23).
+edge(23,58).
+edge(58,23).
+edge(23,69).
+edge(69,23).
+edge(23,79).
+edge(79,23).
+edge(23,100).
+edge(100,23).
+edge(23,102).
+edge(102,23).
+edge(23,106).
+edge(106,23).
+edge(23,115).
+edge(115,23).
+edge(23,123).
+edge(123,23).
+edge(24,30).
+edge(30,24).
+edge(24,33).
+edge(33,24).
+edge(24,48).
+edge(48,24).
+edge(24,93).
+edge(93,24).
+edge(24,94).
+edge(94,24).
+edge(24,115).
+edge(115,24).
+edge(24,117).
+edge(117,24).
+edge(25,34).
+edge(34,25).
+edge(25,44).
+edge(44,25).
+edge(25,78).
+edge(78,25).
+edge(25,96).
+edge(96,25).
+edge(25,108).
+edge(108,25).
+edge(25,109).
+edge(109,25).
+edge(25,118).
+edge(118,25).
+edge(26,30).
+edge(30,26).
+edge(26,41).
+edge(41,26).
+edge(26,46).
+edge(46,26).
+edge(26,47).
+edge(47,26).
+edge(26,53).
+edge(53,26).
+edge(26,79).
+edge(79,26).
+edge(26,123).
+edge(123,26).
+edge(26,129).
+edge(129,26).
+edge(27,34).
+edge(34,27).
+edge(27,35).
+edge(35,27).
+edge(27,48).
+edge(48,27).
+edge(27,64).
+edge(64,27).
+edge(27,93).
+edge(93,27).
+edge(27,112).
+edge(112,27).
+edge(27,124).
+edge(124,27).
+edge(28,40).
+edge(40,28).
+edge(28,45).
+edge(45,28).
+edge(28,50).
+edge(50,28).
+edge(28,54).
+edge(54,28).
+edge(28,87).
+edge(87,28).
+edge(28,88).
+edge(88,28).
+edge(28,110).
+edge(110,28).
+edge(28,115).
+edge(115,28).
+edge(29,35).
+edge(35,29).
+edge(29,70).
+edge(70,29).
+edge(29,77).
+edge(77,29).
+edge(29,91).
+edge(91,29).
+edge(29,98).
+edge(98,29).
+edge(29,101).
+edge(101,29).
+edge(29,102).
+edge(102,29).
+edge(29,125).
+edge(125,29).
+edge(29,126).
+edge(126,29).
+edge(30,34).
+edge(34,30).
+edge(30,40).
+edge(40,30).
+edge(30,42).
+edge(42,30).
+edge(30,53).
+edge(53,30).
+edge(30,60).
+edge(60,30).
+edge(30,67).
+edge(67,30).
+edge(30,78).
+edge(78,30).
+edge(30,79).
+edge(79,30).
+edge(30,83).
+edge(83,30).
+edge(30,88).
+edge(88,30).
+edge(30,91).
+edge(91,30).
+edge(30,97).
+edge(97,30).
+edge(30,98).
+edge(98,30).
+edge(30,111).
+edge(111,30).
+edge(30,112).
+edge(112,30).
+edge(30,113).
+edge(113,30).
+edge(30,114).
+edge(114,30).
+edge(30,128).
+edge(128,30).
+edge(31,36).
+edge(36,31).
+edge(31,47).
+edge(47,31).
+edge(31,49).
+edge(49,31).
+edge(31,52).
+edge(52,31).
+edge(31,61).
+edge(61,31).
+edge(31,79).
+edge(79,31).
+edge(31,108).
+edge(108,31).
+edge(31,128).
+edge(128,31).
+edge(32,42).
+edge(42,32).
+edge(32,66).
+edge(66,32).
+edge(32,74).
+edge(74,32).
+edge(32,85).
+edge(85,32).
+edge(32,101).
+edge(101,32).
+edge(32,103).
+edge(103,32).
+edge(32,118).
+edge(118,32).
+edge(33,37).
+edge(37,33).
+edge(33,39).
+edge(39,33).
+edge(33,46).
+edge(46,33).
+edge(33,50).
+edge(50,33).
+edge(33,66).
+edge(66,33).
+edge(33,80).
+edge(80,33).
+edge(33,83).
+edge(83,33).
+edge(33,90).
+edge(90,33).
+edge(33,97).
+edge(97,33).
+edge(33,109).
+edge(109,33).
+edge(33,121).
+edge(121,33).
+edge(33,125).
+edge(125,33).
+edge(33,128).
+edge(128,33).
+edge(34,42).
+edge(42,34).
+edge(34,57).
+edge(57,34).
+edge(34,78).
+edge(78,34).
+edge(34,84).
+edge(84,34).
+edge(34,86).
+edge(86,34).
+edge(34,111).
+edge(111,34).
+edge(34,120).
+edge(120,34).
+edge(34,125).
+edge(125,34).
+edge(34,128).
+edge(128,34).
+edge(35,44).
+edge(44,35).
+edge(35,45).
+edge(45,35).
+edge(35,58).
+edge(58,35).
+edge(35,61).
+edge(61,35).
+edge(35,63).
+edge(63,35).
+edge(35,88).
+edge(88,35).
+edge(35,124).
+edge(124,35).
+edge(36,39).
+edge(39,36).
+edge(36,45).
+edge(45,36).
+edge(36,48).
+edge(48,36).
+edge(36,53).
+edge(53,36).
+edge(36,61).
+edge(61,36).
+edge(36,86).
+edge(86,36).
+edge(36,102).
+edge(102,36).
+edge(36,107).
+edge(107,36).
+edge(36,119).
+edge(119,36).
+edge(36,128).
+edge(128,36).
+edge(36,130).
+edge(130,36).
+edge(37,48).
+edge(48,37).
+edge(37,53).
+edge(53,37).
+edge(37,61).
+edge(61,37).
+edge(37,86).
+edge(86,37).
+edge(37,101).
+edge(101,37).
+edge(37,119).
+edge(119,37).
+edge(37,122).
+edge(122,37).
+edge(37,129).
+edge(129,37).
+edge(37,130).
+edge(130,37).
+edge(38,62).
+edge(62,38).
+edge(38,68).
+edge(68,38).
+edge(38,69).
+edge(69,38).
+edge(38,98).
+edge(98,38).
+edge(38,103).
+edge(103,38).
+edge(38,119).
+edge(119,38).
+edge(39,44).
+edge(44,39).
+edge(39,53).
+edge(53,39).
+edge(39,57).
+edge(57,39).
+edge(39,64).
+edge(64,39).
+edge(39,69).
+edge(69,39).
+edge(39,72).
+edge(72,39).
+edge(39,99).
+edge(99,39).
+edge(39,103).
+edge(103,39).
+edge(39,119).
+edge(119,39).
+edge(39,124).
+edge(124,39).
+edge(39,125).
+edge(125,39).
+edge(40,51).
+edge(51,40).
+edge(40,56).
+edge(56,40).
+edge(40,62).
+edge(62,40).
+edge(40,66).
+edge(66,40).
+edge(40,76).
+edge(76,40).
+edge(40,85).
+edge(85,40).
+edge(40,86).
+edge(86,40).
+edge(40,89).
+edge(89,40).
+edge(41,83).
+edge(83,41).
+edge(41,91).
+edge(91,41).
+edge(42,51).
+edge(51,42).
+edge(42,63).
+edge(63,42).
+edge(42,64).
+edge(64,42).
+edge(42,75).
+edge(75,42).
+edge(42,89).
+edge(89,42).
+edge(42,95).
+edge(95,42).
+edge(42,96).
+edge(96,42).
+edge(42,103).
+edge(103,42).
+edge(42,109).
+edge(109,42).
+edge(42,111).
+edge(111,42).
+edge(42,117).
+edge(117,42).
+edge(42,123).
+edge(123,42).
+edge(43,50).
+edge(50,43).
+edge(43,73).
+edge(73,43).
+edge(43,81).
+edge(81,43).
+edge(43,94).
+edge(94,43).
+edge(43,96).
+edge(96,43).
+edge(43,106).
+edge(106,43).
+edge(43,124).
+edge(124,43).
+edge(43,129).
+edge(129,43).
+edge(44,52).
+edge(52,44).
+edge(44,83).
+edge(83,44).
+edge(44,114).
+edge(114,44).
+edge(44,118).
+edge(118,44).
+edge(44,126).
+edge(126,44).
+edge(45,48).
+edge(48,45).
+edge(45,55).
+edge(55,45).
+edge(45,58).
+edge(58,45).
+edge(45,71).
+edge(71,45).
+edge(45,74).
+edge(74,45).
+edge(45,82).
+edge(82,45).
+edge(45,87).
+edge(87,45).
+edge(45,95).
+edge(95,45).
+edge(45,96).
+edge(96,45).
+edge(45,108).
+edge(108,45).
+edge(45,115).
+edge(115,45).
+edge(45,124).
+edge(124,45).
+edge(45,130).
+edge(130,45).
+edge(46,61).
+edge(61,46).
+edge(46,71).
+edge(71,46).
+edge(46,80).
+edge(80,46).
+edge(46,87).
+edge(87,46).
+edge(46,97).
+edge(97,46).
+edge(46,108).
+edge(108,46).
+edge(46,114).
+edge(114,46).
+edge(46,126).
+edge(126,46).
+edge(47,71).
+edge(71,47).
+edge(47,73).
+edge(73,47).
+edge(47,98).
+edge(98,47).
+edge(47,100).
+edge(100,47).
+edge(47,105).
+edge(105,47).
+edge(48,56).
+edge(56,48).
+edge(48,59).
+edge(59,48).
+edge(48,82).
+edge(82,48).
+edge(48,85).
+edge(85,48).
+edge(48,88).
+edge(88,48).
+edge(48,94).
+edge(94,48).
+edge(48,99).
+edge(99,48).
+edge(48,100).
+edge(100,48).
+edge(48,101).
+edge(101,48).
+edge(48,107).
+edge(107,48).
+edge(48,109).
+edge(109,48).
+edge(48,112).
+edge(112,48).
+edge(49,95).
+edge(95,49).
+edge(49,97).
+edge(97,49).
+edge(49,110).
+edge(110,49).
+edge(49,116).
+edge(116,49).
+edge(50,53).
+edge(53,50).
+edge(50,58).
+edge(58,50).
+edge(50,65).
+edge(65,50).
+edge(50,118).
+edge(118,50).
+edge(50,122).
+edge(122,50).
+edge(51,56).
+edge(56,51).
+edge(51,71).
+edge(71,51).
+edge(51,82).
+edge(82,51).
+edge(51,84).
+edge(84,51).
+edge(51,98).
+edge(98,51).
+edge(52,75).
+edge(75,52).
+edge(52,91).
+edge(91,52).
+edge(52,97).
+edge(97,52).
+edge(52,99).
+edge(99,52).
+edge(52,106).
+edge(106,52).
+edge(52,115).
+edge(115,52).
+edge(52,118).
+edge(118,52).
+edge(52,130).
+edge(130,52).
+edge(53,76).
+edge(76,53).
+edge(53,84).
+edge(84,53).
+edge(53,107).
+edge(107,53).
+edge(53,122).
+edge(122,53).
+edge(53,124).
+edge(124,53).
+edge(54,62).
+edge(62,54).
+edge(54,63).
+edge(63,54).
+edge(54,75).
+edge(75,54).
+edge(54,86).
+edge(86,54).
+edge(54,92).
+edge(92,54).
+edge(54,107).
+edge(107,54).
+edge(54,118).
+edge(118,54).
+edge(54,119).
+edge(119,54).
+edge(54,121).
+edge(121,54).
+edge(55,58).
+edge(58,55).
+edge(55,67).
+edge(67,55).
+edge(55,75).
+edge(75,55).
+edge(55,77).
+edge(77,55).
+edge(55,79).
+edge(79,55).
+edge(55,98).
+edge(98,55).
+edge(55,107).
+edge(107,55).
+edge(55,118).
+edge(118,55).
+edge(55,122).
+edge(122,55).
+edge(55,126).
+edge(126,55).
+edge(56,72).
+edge(72,56).
+edge(56,85).
+edge(85,56).
+edge(56,97).
+edge(97,56).
+edge(56,114).
+edge(114,56).
+edge(56,122).
+edge(122,56).
+edge(56,130).
+edge(130,56).
+edge(57,78).
+edge(78,57).
+edge(57,86).
+edge(86,57).
+edge(57,90).
+edge(90,57).
+edge(57,93).
+edge(93,57).
+edge(57,97).
+edge(97,57).
+edge(57,100).
+edge(100,57).
+edge(58,64).
+edge(64,58).
+edge(58,81).
+edge(81,58).
+edge(58,87).
+edge(87,58).
+edge(58,105).
+edge(105,58).
+edge(58,116).
+edge(116,58).
+edge(58,118).
+edge(118,58).
+edge(58,126).
+edge(126,58).
+edge(59,60).
+edge(60,59).
+edge(59,65).
+edge(65,59).
+edge(59,73).
+edge(73,59).
+edge(59,77).
+edge(77,59).
+edge(59,91).
+edge(91,59).
+edge(59,97).
+edge(97,59).
+edge(59,114).
+edge(114,59).
+edge(59,116).
+edge(116,59).
+edge(59,117).
+edge(117,59).
+edge(59,123).
+edge(123,59).
+edge(59,129).
+edge(129,59).
+edge(60,73).
+edge(73,60).
+edge(60,81).
+edge(81,60).
+edge(60,89).
+edge(89,60).
+edge(61,63).
+edge(63,61).
+edge(61,67).
+edge(67,61).
+edge(61,69).
+edge(69,61).
+edge(61,72).
+edge(72,61).
+edge(61,73).
+edge(73,61).
+edge(61,79).
+edge(79,61).
+edge(61,80).
+edge(80,61).
+edge(61,89).
+edge(89,61).
+edge(61,91).
+edge(91,61).
+edge(61,116).
+edge(116,61).
+edge(61,117).
+edge(117,61).
+edge(62,68).
+edge(68,62).
+edge(62,85).
+edge(85,62).
+edge(62,100).
+edge(100,62).
+edge(62,113).
+edge(113,62).
+edge(62,128).
+edge(128,62).
+edge(63,82).
+edge(82,63).
+edge(63,85).
+edge(85,63).
+edge(63,97).
+edge(97,63).
+edge(63,127).
+edge(127,63).
+edge(64,71).
+edge(71,64).
+edge(64,76).
+edge(76,64).
+edge(64,80).
+edge(80,64).
+edge(64,94).
+edge(94,64).
+edge(64,96).
+edge(96,64).
+edge(64,114).
+edge(114,64).
+edge(64,122).
+edge(122,64).
+edge(64,130).
+edge(130,64).
+edge(65,82).
+edge(82,65).
+edge(65,94).
+edge(94,65).
+edge(65,101).
+edge(101,65).
+edge(65,117).
+edge(117,65).
+edge(66,69).
+edge(69,66).
+edge(66,70).
+edge(70,66).
+edge(66,128).
+edge(128,66).
+edge(67,69).
+edge(69,67).
+edge(67,78).
+edge(78,67).
+edge(67,79).
+edge(79,67).
+edge(67,87).
+edge(87,67).
+edge(67,103).
+edge(103,67).
+edge(67,107).
+edge(107,67).
+edge(67,116).
+edge(116,67).
+edge(67,120).
+edge(120,67).
+edge(68,76).
+edge(76,68).
+edge(68,79).
+edge(79,68).
+edge(68,88).
+edge(88,68).
+edge(68,97).
+edge(97,68).
+edge(68,98).
+edge(98,68).
+edge(68,101).
+edge(101,68).
+edge(68,127).
+edge(127,68).
+edge(69,70).
+edge(70,69).
+edge(69,81).
+edge(81,69).
+edge(69,87).
+edge(87,69).
+edge(69,89).
+edge(89,69).
+edge(69,104).
+edge(104,69).
+edge(69,110).
+edge(110,69).
+edge(69,120).
+edge(120,69).
+edge(69,121).
+edge(121,69).
+edge(70,98).
+edge(98,70).
+edge(70,115).
+edge(115,70).
+edge(70,124).
+edge(124,70).
+edge(71,73).
+edge(73,71).
+edge(71,80).
+edge(80,71).
+edge(71,85).
+edge(85,71).
+edge(71,99).
+edge(99,71).
+edge(71,110).
+edge(110,71).
+edge(72,77).
+edge(77,72).
+edge(72,87).
+edge(87,72).
+edge(72,88).
+edge(88,72).
+edge(72,92).
+edge(92,72).
+edge(72,97).
+edge(97,72).
+edge(72,108).
+edge(108,72).
+edge(72,111).
+edge(111,72).
+edge(73,89).
+edge(89,73).
+edge(73,97).
+edge(97,73).
+edge(73,98).
+edge(98,73).
+edge(73,102).
+edge(102,73).
+edge(73,106).
+edge(106,73).
+edge(74,76).
+edge(76,74).
+edge(74,78).
+edge(78,74).
+edge(74,85).
+edge(85,74).
+edge(74,89).
+edge(89,74).
+edge(74,114).
+edge(114,74).
+edge(74,115).
+edge(115,74).
+edge(74,116).
+edge(116,74).
+edge(74,121).
+edge(121,74).
+edge(74,123).
+edge(123,74).
+edge(74,124).
+edge(124,74).
+edge(75,80).
+edge(80,75).
+edge(75,89).
+edge(89,75).
+edge(76,77).
+edge(77,76).
+edge(76,82).
+edge(82,76).
+edge(76,88).
+edge(88,76).
+edge(76,125).
+edge(125,76).
+edge(77,79).
+edge(79,77).
+edge(77,83).
+edge(83,77).
+edge(77,89).
+edge(89,77).
+edge(77,105).
+edge(105,77).
+edge(78,82).
+edge(82,78).
+edge(78,90).
+edge(90,78).
+edge(78,92).
+edge(92,78).
+edge(78,95).
+edge(95,78).
+edge(78,117).
+edge(117,78).
+edge(78,124).
+edge(124,78).
+edge(78,127).
+edge(127,78).
+edge(79,95).
+edge(95,79).
+edge(79,98).
+edge(98,79).
+edge(79,101).
+edge(101,79).
+edge(79,113).
+edge(113,79).
+edge(80,84).
+edge(84,80).
+edge(80,98).
+edge(98,80).
+edge(80,118).
+edge(118,80).
+edge(80,129).
+edge(129,80).
+edge(81,82).
+edge(82,81).
+edge(81,87).
+edge(87,81).
+edge(81,109).
+edge(109,81).
+edge(81,111).
+edge(111,81).
+edge(81,115).
+edge(115,81).
+edge(81,130).
+edge(130,81).
+edge(82,84).
+edge(84,82).
+edge(82,97).
+edge(97,82).
+edge(82,104).
+edge(104,82).
+edge(82,130).
+edge(130,82).
+edge(83,86).
+edge(86,83).
+edge(83,97).
+edge(97,83).
+edge(83,111).
+edge(111,83).
+edge(83,116).
+edge(116,83).
+edge(84,90).
+edge(90,84).
+edge(84,97).
+edge(97,84).
+edge(84,100).
+edge(100,84).
+edge(84,125).
+edge(125,84).
+edge(85,93).
+edge(93,85).
+edge(85,97).
+edge(97,85).
+edge(85,112).
+edge(112,85).
+edge(85,121).
+edge(121,85).
+edge(86,87).
+edge(87,86).
+edge(86,92).
+edge(92,86).
+edge(86,100).
+edge(100,86).
+edge(86,113).
+edge(113,86).
+edge(86,122).
+edge(122,86).
+edge(86,126).
+edge(126,86).
+edge(86,128).
+edge(128,86).
+edge(87,93).
+edge(93,87).
+edge(87,101).
+edge(101,87).
+edge(87,104).
+edge(104,87).
+edge(87,113).
+edge(113,87).
+edge(87,118).
+edge(118,87).
+edge(88,100).
+edge(100,88).
+edge(88,111).
+edge(111,88).
+edge(89,110).
+edge(110,89).
+edge(89,113).
+edge(113,89).
+edge(89,130).
+edge(130,89).
+edge(90,93).
+edge(93,90).
+edge(90,105).
+edge(105,90).
+edge(90,112).
+edge(112,90).
+edge(90,115).
+edge(115,90).
+edge(90,118).
+edge(118,90).
+edge(90,120).
+edge(120,90).
+edge(91,98).
+edge(98,91).
+edge(91,105).
+edge(105,91).
+edge(91,108).
+edge(108,91).
+edge(91,113).
+edge(113,91).
+edge(91,118).
+edge(118,91).
+edge(91,129).
+edge(129,91).
+edge(92,102).
+edge(102,92).
+edge(92,107).
+edge(107,92).
+edge(92,108).
+edge(108,92).
+edge(92,114).
+edge(114,92).
+edge(92,118).
+edge(118,92).
+edge(92,125).
+edge(125,92).
+edge(93,104).
+edge(104,93).
+edge(94,96).
+edge(96,94).
+edge(94,104).
+edge(104,94).
+edge(94,107).
+edge(107,94).
+edge(94,114).
+edge(114,94).
+edge(94,115).
+edge(115,94).
+edge(95,105).
+edge(105,95).
+edge(95,128).
+edge(128,95).
+edge(96,110).
+edge(110,96).
+edge(96,113).
+edge(113,96).
+edge(96,123).
+edge(123,96).
+edge(96,126).
+edge(126,96).
+edge(98,104).
+edge(104,98).
+edge(98,107).
+edge(107,98).
+edge(98,118).
+edge(118,98).
+edge(98,119).
+edge(119,98).
+edge(98,122).
+edge(122,98).
+edge(101,104).
+edge(104,101).
+edge(101,110).
+edge(110,101).
+edge(101,115).
+edge(115,101).
+edge(101,123).
+edge(123,101).
+edge(101,125).
+edge(125,101).
+edge(102,126).
+edge(126,102).
+edge(103,104).
+edge(104,103).
+edge(103,109).
+edge(109,103).
+edge(103,123).
+edge(123,103).
+edge(103,127).
+edge(127,103).
+edge(104,107).
+edge(107,104).
+edge(105,106).
+edge(106,105).
+edge(105,111).
+edge(111,105).
+edge(106,116).
+edge(116,106).
+edge(106,117).
+edge(117,106).
+edge(106,126).
+edge(126,106).
+edge(107,109).
+edge(109,107).
+edge(107,124).
+edge(124,107).
+edge(107,128).
+edge(128,107).
+edge(108,125).
+edge(125,108).
+edge(109,115).
+edge(115,109).
+edge(109,116).
+edge(116,109).
+edge(109,118).
+edge(118,109).
+edge(109,127).
+edge(127,109).
+edge(109,128).
+edge(128,109).
+edge(110,118).
+edge(118,110).
+edge(111,116).
+edge(116,111).
+edge(111,117).
+edge(117,111).
+edge(111,120).
+edge(120,111).
+edge(112,115).
+edge(115,112).
+edge(112,119).
+edge(119,112).
+edge(112,121).
+edge(121,112).
+edge(113,118).
+edge(118,113).
+edge(113,122).
+edge(122,113).
+edge(113,124).
+edge(124,113).
+edge(113,125).
+edge(125,113).
+edge(115,118).
+edge(118,115).
+edge(115,119).
+edge(119,115).
+edge(116,118).
+edge(118,116).
+edge(116,125).
+edge(125,116).
+edge(119,128).
+edge(128,119).
+edge(120,126).
+edge(126,120).
+edge(121,125).
+edge(125,121).
+edge(122,123).
+edge(123,122).
+edge(127,130).
+edge(130,127).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0021-graph_colouring-135-0.lp b/examples/clingo/expansion/GraphColouring/instances/0021-graph_colouring-135-0.lp
new file mode 100644
index 0000000..1eaf8b8
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0021-graph_colouring-135-0.lp
@@ -0,0 +1,1981 @@
+#const n=135.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+edge(1,33).
+edge(33,1).
+edge(1,54).
+edge(54,1).
+edge(1,80).
+edge(80,1).
+edge(1,81).
+edge(81,1).
+edge(1,82).
+edge(82,1).
+edge(1,84).
+edge(84,1).
+edge(1,109).
+edge(109,1).
+edge(1,119).
+edge(119,1).
+edge(1,127).
+edge(127,1).
+edge(2,13).
+edge(13,2).
+edge(2,27).
+edge(27,2).
+edge(2,36).
+edge(36,2).
+edge(2,45).
+edge(45,2).
+edge(2,52).
+edge(52,2).
+edge(2,67).
+edge(67,2).
+edge(2,73).
+edge(73,2).
+edge(2,76).
+edge(76,2).
+edge(2,100).
+edge(100,2).
+edge(2,107).
+edge(107,2).
+edge(2,108).
+edge(108,2).
+edge(2,126).
+edge(126,2).
+edge(2,131).
+edge(131,2).
+edge(3,40).
+edge(40,3).
+edge(3,42).
+edge(42,3).
+edge(3,44).
+edge(44,3).
+edge(3,51).
+edge(51,3).
+edge(3,78).
+edge(78,3).
+edge(3,86).
+edge(86,3).
+edge(3,87).
+edge(87,3).
+edge(3,88).
+edge(88,3).
+edge(3,97).
+edge(97,3).
+edge(3,102).
+edge(102,3).
+edge(3,120).
+edge(120,3).
+edge(3,133).
+edge(133,3).
+edge(4,24).
+edge(24,4).
+edge(4,30).
+edge(30,4).
+edge(4,33).
+edge(33,4).
+edge(4,49).
+edge(49,4).
+edge(4,54).
+edge(54,4).
+edge(4,62).
+edge(62,4).
+edge(4,63).
+edge(63,4).
+edge(4,65).
+edge(65,4).
+edge(4,71).
+edge(71,4).
+edge(4,102).
+edge(102,4).
+edge(4,111).
+edge(111,4).
+edge(4,129).
+edge(129,4).
+edge(4,134).
+edge(134,4).
+edge(5,8).
+edge(8,5).
+edge(5,33).
+edge(33,5).
+edge(5,37).
+edge(37,5).
+edge(5,41).
+edge(41,5).
+edge(5,50).
+edge(50,5).
+edge(5,66).
+edge(66,5).
+edge(5,74).
+edge(74,5).
+edge(5,90).
+edge(90,5).
+edge(5,95).
+edge(95,5).
+edge(5,97).
+edge(97,5).
+edge(5,124).
+edge(124,5).
+edge(5,133).
+edge(133,5).
+edge(5,134).
+edge(134,5).
+edge(6,17).
+edge(17,6).
+edge(6,19).
+edge(19,6).
+edge(6,30).
+edge(30,6).
+edge(6,63).
+edge(63,6).
+edge(6,69).
+edge(69,6).
+edge(6,81).
+edge(81,6).
+edge(6,99).
+edge(99,6).
+edge(6,102).
+edge(102,6).
+edge(6,125).
+edge(125,6).
+edge(7,23).
+edge(23,7).
+edge(7,27).
+edge(27,7).
+edge(7,43).
+edge(43,7).
+edge(7,52).
+edge(52,7).
+edge(7,63).
+edge(63,7).
+edge(7,75).
+edge(75,7).
+edge(7,81).
+edge(81,7).
+edge(7,92).
+edge(92,7).
+edge(7,100).
+edge(100,7).
+edge(7,118).
+edge(118,7).
+edge(7,119).
+edge(119,7).
+edge(7,124).
+edge(124,7).
+edge(7,133).
+edge(133,7).
+edge(8,15).
+edge(15,8).
+edge(8,44).
+edge(44,8).
+edge(8,49).
+edge(49,8).
+edge(8,70).
+edge(70,8).
+edge(8,72).
+edge(72,8).
+edge(8,74).
+edge(74,8).
+edge(8,75).
+edge(75,8).
+edge(8,91).
+edge(91,8).
+edge(8,93).
+edge(93,8).
+edge(8,104).
+edge(104,8).
+edge(8,105).
+edge(105,8).
+edge(9,12).
+edge(12,9).
+edge(9,16).
+edge(16,9).
+edge(9,56).
+edge(56,9).
+edge(9,57).
+edge(57,9).
+edge(9,67).
+edge(67,9).
+edge(9,75).
+edge(75,9).
+edge(9,81).
+edge(81,9).
+edge(9,83).
+edge(83,9).
+edge(9,86).
+edge(86,9).
+edge(9,90).
+edge(90,9).
+edge(9,99).
+edge(99,9).
+edge(9,104).
+edge(104,9).
+edge(9,132).
+edge(132,9).
+edge(9,133).
+edge(133,9).
+edge(9,134).
+edge(134,9).
+edge(10,18).
+edge(18,10).
+edge(10,20).
+edge(20,10).
+edge(10,34).
+edge(34,10).
+edge(10,36).
+edge(36,10).
+edge(10,37).
+edge(37,10).
+edge(10,49).
+edge(49,10).
+edge(10,56).
+edge(56,10).
+edge(10,65).
+edge(65,10).
+edge(10,69).
+edge(69,10).
+edge(10,70).
+edge(70,10).
+edge(10,77).
+edge(77,10).
+edge(10,80).
+edge(80,10).
+edge(10,108).
+edge(108,10).
+edge(10,119).
+edge(119,10).
+edge(10,120).
+edge(120,10).
+edge(10,121).
+edge(121,10).
+edge(10,129).
+edge(129,10).
+edge(11,17).
+edge(17,11).
+edge(11,22).
+edge(22,11).
+edge(11,26).
+edge(26,11).
+edge(11,43).
+edge(43,11).
+edge(11,55).
+edge(55,11).
+edge(11,75).
+edge(75,11).
+edge(11,76).
+edge(76,11).
+edge(11,79).
+edge(79,11).
+edge(11,93).
+edge(93,11).
+edge(11,94).
+edge(94,11).
+edge(11,110).
+edge(110,11).
+edge(11,119).
+edge(119,11).
+edge(12,15).
+edge(15,12).
+edge(12,31).
+edge(31,12).
+edge(12,32).
+edge(32,12).
+edge(12,34).
+edge(34,12).
+edge(12,39).
+edge(39,12).
+edge(12,48).
+edge(48,12).
+edge(12,61).
+edge(61,12).
+edge(12,62).
+edge(62,12).
+edge(12,71).
+edge(71,12).
+edge(12,95).
+edge(95,12).
+edge(12,99).
+edge(99,12).
+edge(12,120).
+edge(120,12).
+edge(13,20).
+edge(20,13).
+edge(13,41).
+edge(41,13).
+edge(13,45).
+edge(45,13).
+edge(13,48).
+edge(48,13).
+edge(13,53).
+edge(53,13).
+edge(13,55).
+edge(55,13).
+edge(13,57).
+edge(57,13).
+edge(13,63).
+edge(63,13).
+edge(13,66).
+edge(66,13).
+edge(13,69).
+edge(69,13).
+edge(13,71).
+edge(71,13).
+edge(13,79).
+edge(79,13).
+edge(13,115).
+edge(115,13).
+edge(13,120).
+edge(120,13).
+edge(13,123).
+edge(123,13).
+edge(13,130).
+edge(130,13).
+edge(14,18).
+edge(18,14).
+edge(14,20).
+edge(20,14).
+edge(14,23).
+edge(23,14).
+edge(14,24).
+edge(24,14).
+edge(14,27).
+edge(27,14).
+edge(14,54).
+edge(54,14).
+edge(14,55).
+edge(55,14).
+edge(14,70).
+edge(70,14).
+edge(14,90).
+edge(90,14).
+edge(14,92).
+edge(92,14).
+edge(14,94).
+edge(94,14).
+edge(14,97).
+edge(97,14).
+edge(14,98).
+edge(98,14).
+edge(14,104).
+edge(104,14).
+edge(14,110).
+edge(110,14).
+edge(14,111).
+edge(111,14).
+edge(14,127).
+edge(127,14).
+edge(15,22).
+edge(22,15).
+edge(15,26).
+edge(26,15).
+edge(15,30).
+edge(30,15).
+edge(15,40).
+edge(40,15).
+edge(15,42).
+edge(42,15).
+edge(15,66).
+edge(66,15).
+edge(15,75).
+edge(75,15).
+edge(15,80).
+edge(80,15).
+edge(15,101).
+edge(101,15).
+edge(15,107).
+edge(107,15).
+edge(15,109).
+edge(109,15).
+edge(15,110).
+edge(110,15).
+edge(15,122).
+edge(122,15).
+edge(15,126).
+edge(126,15).
+edge(15,132).
+edge(132,15).
+edge(16,35).
+edge(35,16).
+edge(16,36).
+edge(36,16).
+edge(16,45).
+edge(45,16).
+edge(16,50).
+edge(50,16).
+edge(16,51).
+edge(51,16).
+edge(16,58).
+edge(58,16).
+edge(16,62).
+edge(62,16).
+edge(16,70).
+edge(70,16).
+edge(16,75).
+edge(75,16).
+edge(16,80).
+edge(80,16).
+edge(16,88).
+edge(88,16).
+edge(16,123).
+edge(123,16).
+edge(16,124).
+edge(124,16).
+edge(16,127).
+edge(127,16).
+edge(16,131).
+edge(131,16).
+edge(16,133).
+edge(133,16).
+edge(17,52).
+edge(52,17).
+edge(17,66).
+edge(66,17).
+edge(17,67).
+edge(67,17).
+edge(17,106).
+edge(106,17).
+edge(17,113).
+edge(113,17).
+edge(17,121).
+edge(121,17).
+edge(18,22).
+edge(22,18).
+edge(18,47).
+edge(47,18).
+edge(18,51).
+edge(51,18).
+edge(18,59).
+edge(59,18).
+edge(18,65).
+edge(65,18).
+edge(18,67).
+edge(67,18).
+edge(18,69).
+edge(69,18).
+edge(18,70).
+edge(70,18).
+edge(18,90).
+edge(90,18).
+edge(18,98).
+edge(98,18).
+edge(18,106).
+edge(106,18).
+edge(18,115).
+edge(115,18).
+edge(18,133).
+edge(133,18).
+edge(19,30).
+edge(30,19).
+edge(19,32).
+edge(32,19).
+edge(19,38).
+edge(38,19).
+edge(19,48).
+edge(48,19).
+edge(19,50).
+edge(50,19).
+edge(19,65).
+edge(65,19).
+edge(19,79).
+edge(79,19).
+edge(19,101).
+edge(101,19).
+edge(19,122).
+edge(122,19).
+edge(20,31).
+edge(31,20).
+edge(20,32).
+edge(32,20).
+edge(20,38).
+edge(38,20).
+edge(20,39).
+edge(39,20).
+edge(20,58).
+edge(58,20).
+edge(20,79).
+edge(79,20).
+edge(20,109).
+edge(109,20).
+edge(20,112).
+edge(112,20).
+edge(20,113).
+edge(113,20).
+edge(20,123).
+edge(123,20).
+edge(20,129).
+edge(129,20).
+edge(20,131).
+edge(131,20).
+edge(20,133).
+edge(133,20).
+edge(21,35).
+edge(35,21).
+edge(21,42).
+edge(42,21).
+edge(21,47).
+edge(47,21).
+edge(21,82).
+edge(82,21).
+edge(21,91).
+edge(91,21).
+edge(21,97).
+edge(97,21).
+edge(21,124).
+edge(124,21).
+edge(21,133).
+edge(133,21).
+edge(21,135).
+edge(135,21).
+edge(22,25).
+edge(25,22).
+edge(22,32).
+edge(32,22).
+edge(22,37).
+edge(37,22).
+edge(22,39).
+edge(39,22).
+edge(22,44).
+edge(44,22).
+edge(22,62).
+edge(62,22).
+edge(22,65).
+edge(65,22).
+edge(22,70).
+edge(70,22).
+edge(22,80).
+edge(80,22).
+edge(22,96).
+edge(96,22).
+edge(22,98).
+edge(98,22).
+edge(22,112).
+edge(112,22).
+edge(22,115).
+edge(115,22).
+edge(22,118).
+edge(118,22).
+edge(22,122).
+edge(122,22).
+edge(23,26).
+edge(26,23).
+edge(23,27).
+edge(27,23).
+edge(23,59).
+edge(59,23).
+edge(23,66).
+edge(66,23).
+edge(23,71).
+edge(71,23).
+edge(23,75).
+edge(75,23).
+edge(23,81).
+edge(81,23).
+edge(23,89).
+edge(89,23).
+edge(23,105).
+edge(105,23).
+edge(23,107).
+edge(107,23).
+edge(23,124).
+edge(124,23).
+edge(24,26).
+edge(26,24).
+edge(24,32).
+edge(32,24).
+edge(24,41).
+edge(41,24).
+edge(24,45).
+edge(45,24).
+edge(24,66).
+edge(66,24).
+edge(24,69).
+edge(69,24).
+edge(24,71).
+edge(71,24).
+edge(24,78).
+edge(78,24).
+edge(24,82).
+edge(82,24).
+edge(24,98).
+edge(98,24).
+edge(24,100).
+edge(100,24).
+edge(24,117).
+edge(117,24).
+edge(24,130).
+edge(130,24).
+edge(24,135).
+edge(135,24).
+edge(25,27).
+edge(27,25).
+edge(25,35).
+edge(35,25).
+edge(25,37).
+edge(37,25).
+edge(25,43).
+edge(43,25).
+edge(25,45).
+edge(45,25).
+edge(25,54).
+edge(54,25).
+edge(25,59).
+edge(59,25).
+edge(25,81).
+edge(81,25).
+edge(25,85).
+edge(85,25).
+edge(25,100).
+edge(100,25).
+edge(25,102).
+edge(102,25).
+edge(25,110).
+edge(110,25).
+edge(25,132).
+edge(132,25).
+edge(26,28).
+edge(28,26).
+edge(26,35).
+edge(35,26).
+edge(26,39).
+edge(39,26).
+edge(26,40).
+edge(40,26).
+edge(26,45).
+edge(45,26).
+edge(26,56).
+edge(56,26).
+edge(26,65).
+edge(65,26).
+edge(26,72).
+edge(72,26).
+edge(26,89).
+edge(89,26).
+edge(26,91).
+edge(91,26).
+edge(26,120).
+edge(120,26).
+edge(26,122).
+edge(122,26).
+edge(26,125).
+edge(125,26).
+edge(27,38).
+edge(38,27).
+edge(27,58).
+edge(58,27).
+edge(27,60).
+edge(60,27).
+edge(27,63).
+edge(63,27).
+edge(27,66).
+edge(66,27).
+edge(27,70).
+edge(70,27).
+edge(27,73).
+edge(73,27).
+edge(27,81).
+edge(81,27).
+edge(27,82).
+edge(82,27).
+edge(27,92).
+edge(92,27).
+edge(27,94).
+edge(94,27).
+edge(27,105).
+edge(105,27).
+edge(27,106).
+edge(106,27).
+edge(27,110).
+edge(110,27).
+edge(27,115).
+edge(115,27).
+edge(27,123).
+edge(123,27).
+edge(28,37).
+edge(37,28).
+edge(28,55).
+edge(55,28).
+edge(28,57).
+edge(57,28).
+edge(28,100).
+edge(100,28).
+edge(28,110).
+edge(110,28).
+edge(28,132).
+edge(132,28).
+edge(29,48).
+edge(48,29).
+edge(29,52).
+edge(52,29).
+edge(29,62).
+edge(62,29).
+edge(29,67).
+edge(67,29).
+edge(29,72).
+edge(72,29).
+edge(29,73).
+edge(73,29).
+edge(29,77).
+edge(77,29).
+edge(29,128).
+edge(128,29).
+edge(30,36).
+edge(36,30).
+edge(30,42).
+edge(42,30).
+edge(30,57).
+edge(57,30).
+edge(30,77).
+edge(77,30).
+edge(31,39).
+edge(39,31).
+edge(31,45).
+edge(45,31).
+edge(31,51).
+edge(51,31).
+edge(31,54).
+edge(54,31).
+edge(31,63).
+edge(63,31).
+edge(31,72).
+edge(72,31).
+edge(31,78).
+edge(78,31).
+edge(31,82).
+edge(82,31).
+edge(31,93).
+edge(93,31).
+edge(31,96).
+edge(96,31).
+edge(31,97).
+edge(97,31).
+edge(31,102).
+edge(102,31).
+edge(31,110).
+edge(110,31).
+edge(31,117).
+edge(117,31).
+edge(32,33).
+edge(33,32).
+edge(32,38).
+edge(38,32).
+edge(32,44).
+edge(44,32).
+edge(32,52).
+edge(52,32).
+edge(32,55).
+edge(55,32).
+edge(32,69).
+edge(69,32).
+edge(32,84).
+edge(84,32).
+edge(32,87).
+edge(87,32).
+edge(32,95).
+edge(95,32).
+edge(32,99).
+edge(99,32).
+edge(32,102).
+edge(102,32).
+edge(32,127).
+edge(127,32).
+edge(33,49).
+edge(49,33).
+edge(33,58).
+edge(58,33).
+edge(33,60).
+edge(60,33).
+edge(33,73).
+edge(73,33).
+edge(33,74).
+edge(74,33).
+edge(33,77).
+edge(77,33).
+edge(33,82).
+edge(82,33).
+edge(33,103).
+edge(103,33).
+edge(33,116).
+edge(116,33).
+edge(33,123).
+edge(123,33).
+edge(33,126).
+edge(126,33).
+edge(33,131).
+edge(131,33).
+edge(34,40).
+edge(40,34).
+edge(34,64).
+edge(64,34).
+edge(34,67).
+edge(67,34).
+edge(34,69).
+edge(69,34).
+edge(34,88).
+edge(88,34).
+edge(34,92).
+edge(92,34).
+edge(34,96).
+edge(96,34).
+edge(34,117).
+edge(117,34).
+edge(34,133).
+edge(133,34).
+edge(35,37).
+edge(37,35).
+edge(35,38).
+edge(38,35).
+edge(35,41).
+edge(41,35).
+edge(35,48).
+edge(48,35).
+edge(35,56).
+edge(56,35).
+edge(35,60).
+edge(60,35).
+edge(35,65).
+edge(65,35).
+edge(35,70).
+edge(70,35).
+edge(35,71).
+edge(71,35).
+edge(35,105).
+edge(105,35).
+edge(35,118).
+edge(118,35).
+edge(36,40).
+edge(40,36).
+edge(36,42).
+edge(42,36).
+edge(36,55).
+edge(55,36).
+edge(36,59).
+edge(59,36).
+edge(36,71).
+edge(71,36).
+edge(36,77).
+edge(77,36).
+edge(36,90).
+edge(90,36).
+edge(36,92).
+edge(92,36).
+edge(37,39).
+edge(39,37).
+edge(37,77).
+edge(77,37).
+edge(37,88).
+edge(88,37).
+edge(37,99).
+edge(99,37).
+edge(37,112).
+edge(112,37).
+edge(37,114).
+edge(114,37).
+edge(37,121).
+edge(121,37).
+edge(37,127).
+edge(127,37).
+edge(37,132).
+edge(132,37).
+edge(38,55).
+edge(55,38).
+edge(38,69).
+edge(69,38).
+edge(38,74).
+edge(74,38).
+edge(38,75).
+edge(75,38).
+edge(38,77).
+edge(77,38).
+edge(38,78).
+edge(78,38).
+edge(38,86).
+edge(86,38).
+edge(38,92).
+edge(92,38).
+edge(38,99).
+edge(99,38).
+edge(38,105).
+edge(105,38).
+edge(38,108).
+edge(108,38).
+edge(38,112).
+edge(112,38).
+edge(38,120).
+edge(120,38).
+edge(38,123).
+edge(123,38).
+edge(38,128).
+edge(128,38).
+edge(38,135).
+edge(135,38).
+edge(39,52).
+edge(52,39).
+edge(39,67).
+edge(67,39).
+edge(39,70).
+edge(70,39).
+edge(39,71).
+edge(71,39).
+edge(39,79).
+edge(79,39).
+edge(39,80).
+edge(80,39).
+edge(39,104).
+edge(104,39).
+edge(39,112).
+edge(112,39).
+edge(40,42).
+edge(42,40).
+edge(40,51).
+edge(51,40).
+edge(40,56).
+edge(56,40).
+edge(40,57).
+edge(57,40).
+edge(40,59).
+edge(59,40).
+edge(40,66).
+edge(66,40).
+edge(40,90).
+edge(90,40).
+edge(40,103).
+edge(103,40).
+edge(41,57).
+edge(57,41).
+edge(41,61).
+edge(61,41).
+edge(41,62).
+edge(62,41).
+edge(41,63).
+edge(63,41).
+edge(41,74).
+edge(74,41).
+edge(41,80).
+edge(80,41).
+edge(41,87).
+edge(87,41).
+edge(41,90).
+edge(90,41).
+edge(41,96).
+edge(96,41).
+edge(41,116).
+edge(116,41).
+edge(42,46).
+edge(46,42).
+edge(42,47).
+edge(47,42).
+edge(42,60).
+edge(60,42).
+edge(42,68).
+edge(68,42).
+edge(42,74).
+edge(74,42).
+edge(42,76).
+edge(76,42).
+edge(42,83).
+edge(83,42).
+edge(42,88).
+edge(88,42).
+edge(42,90).
+edge(90,42).
+edge(42,99).
+edge(99,42).
+edge(42,105).
+edge(105,42).
+edge(42,106).
+edge(106,42).
+edge(42,113).
+edge(113,42).
+edge(42,114).
+edge(114,42).
+edge(42,119).
+edge(119,42).
+edge(42,130).
+edge(130,42).
+edge(43,46).
+edge(46,43).
+edge(43,53).
+edge(53,43).
+edge(43,62).
+edge(62,43).
+edge(43,77).
+edge(77,43).
+edge(43,87).
+edge(87,43).
+edge(43,93).
+edge(93,43).
+edge(43,95).
+edge(95,43).
+edge(43,97).
+edge(97,43).
+edge(43,121).
+edge(121,43).
+edge(43,126).
+edge(126,43).
+edge(43,131).
+edge(131,43).
+edge(44,51).
+edge(51,44).
+edge(44,52).
+edge(52,44).
+edge(44,54).
+edge(54,44).
+edge(44,90).
+edge(90,44).
+edge(44,105).
+edge(105,44).
+edge(44,110).
+edge(110,44).
+edge(44,111).
+edge(111,44).
+edge(44,116).
+edge(116,44).
+edge(44,121).
+edge(121,44).
+edge(45,49).
+edge(49,45).
+edge(45,56).
+edge(56,45).
+edge(45,59).
+edge(59,45).
+edge(45,71).
+edge(71,45).
+edge(45,74).
+edge(74,45).
+edge(45,75).
+edge(75,45).
+edge(45,76).
+edge(76,45).
+edge(45,78).
+edge(78,45).
+edge(45,83).
+edge(83,45).
+edge(45,89).
+edge(89,45).
+edge(45,105).
+edge(105,45).
+edge(45,107).
+edge(107,45).
+edge(45,119).
+edge(119,45).
+edge(45,125).
+edge(125,45).
+edge(45,132).
+edge(132,45).
+edge(46,53).
+edge(53,46).
+edge(46,55).
+edge(55,46).
+edge(46,57).
+edge(57,46).
+edge(46,72).
+edge(72,46).
+edge(46,76).
+edge(76,46).
+edge(46,96).
+edge(96,46).
+edge(46,101).
+edge(101,46).
+edge(46,103).
+edge(103,46).
+edge(46,114).
+edge(114,46).
+edge(46,120).
+edge(120,46).
+edge(46,124).
+edge(124,46).
+edge(46,129).
+edge(129,46).
+edge(47,51).
+edge(51,47).
+edge(47,55).
+edge(55,47).
+edge(47,83).
+edge(83,47).
+edge(47,84).
+edge(84,47).
+edge(47,90).
+edge(90,47).
+edge(47,95).
+edge(95,47).
+edge(47,98).
+edge(98,47).
+edge(47,104).
+edge(104,47).
+edge(47,128).
+edge(128,47).
+edge(47,133).
+edge(133,47).
+edge(47,134).
+edge(134,47).
+edge(48,54).
+edge(54,48).
+edge(48,86).
+edge(86,48).
+edge(48,111).
+edge(111,48).
+edge(48,124).
+edge(124,48).
+edge(48,126).
+edge(126,48).
+edge(48,130).
+edge(130,48).
+edge(49,55).
+edge(55,49).
+edge(49,68).
+edge(68,49).
+edge(49,83).
+edge(83,49).
+edge(49,89).
+edge(89,49).
+edge(49,96).
+edge(96,49).
+edge(49,104).
+edge(104,49).
+edge(49,117).
+edge(117,49).
+edge(49,131).
+edge(131,49).
+edge(49,135).
+edge(135,49).
+edge(50,77).
+edge(77,50).
+edge(50,99).
+edge(99,50).
+edge(50,102).
+edge(102,50).
+edge(50,104).
+edge(104,50).
+edge(50,108).
+edge(108,50).
+edge(50,110).
+edge(110,50).
+edge(50,118).
+edge(118,50).
+edge(50,121).
+edge(121,50).
+edge(50,129).
+edge(129,50).
+edge(50,131).
+edge(131,50).
+edge(50,134).
+edge(134,50).
+edge(51,53).
+edge(53,51).
+edge(51,55).
+edge(55,51).
+edge(51,63).
+edge(63,51).
+edge(51,65).
+edge(65,51).
+edge(51,67).
+edge(67,51).
+edge(51,85).
+edge(85,51).
+edge(51,102).
+edge(102,51).
+edge(51,105).
+edge(105,51).
+edge(51,118).
+edge(118,51).
+edge(51,125).
+edge(125,51).
+edge(52,68).
+edge(68,52).
+edge(52,91).
+edge(91,52).
+edge(52,99).
+edge(99,52).
+edge(52,106).
+edge(106,52).
+edge(52,108).
+edge(108,52).
+edge(52,114).
+edge(114,52).
+edge(52,117).
+edge(117,52).
+edge(52,132).
+edge(132,52).
+edge(53,59).
+edge(59,53).
+edge(53,63).
+edge(63,53).
+edge(53,86).
+edge(86,53).
+edge(53,88).
+edge(88,53).
+edge(53,93).
+edge(93,53).
+edge(53,123).
+edge(123,53).
+edge(53,133).
+edge(133,53).
+edge(54,57).
+edge(57,54).
+edge(54,78).
+edge(78,54).
+edge(54,99).
+edge(99,54).
+edge(54,110).
+edge(110,54).
+edge(54,113).
+edge(113,54).
+edge(54,131).
+edge(131,54).
+edge(54,133).
+edge(133,54).
+edge(54,135).
+edge(135,54).
+edge(55,64).
+edge(64,55).
+edge(55,75).
+edge(75,55).
+edge(55,84).
+edge(84,55).
+edge(55,86).
+edge(86,55).
+edge(55,87).
+edge(87,55).
+edge(55,110).
+edge(110,55).
+edge(55,112).
+edge(112,55).
+edge(55,126).
+edge(126,55).
+edge(55,130).
+edge(130,55).
+edge(55,131).
+edge(131,55).
+edge(55,132).
+edge(132,55).
+edge(55,133).
+edge(133,55).
+edge(56,70).
+edge(70,56).
+edge(56,72).
+edge(72,56).
+edge(56,74).
+edge(74,56).
+edge(56,89).
+edge(89,56).
+edge(56,107).
+edge(107,56).
+edge(56,108).
+edge(108,56).
+edge(56,128).
+edge(128,56).
+edge(56,134).
+edge(134,56).
+edge(57,58).
+edge(58,57).
+edge(57,79).
+edge(79,57).
+edge(57,88).
+edge(88,57).
+edge(57,89).
+edge(89,57).
+edge(57,106).
+edge(106,57).
+edge(57,112).
+edge(112,57).
+edge(57,116).
+edge(116,57).
+edge(57,118).
+edge(118,57).
+edge(57,123).
+edge(123,57).
+edge(58,65).
+edge(65,58).
+edge(58,68).
+edge(68,58).
+edge(58,69).
+edge(69,58).
+edge(58,90).
+edge(90,58).
+edge(58,91).
+edge(91,58).
+edge(58,96).
+edge(96,58).
+edge(58,120).
+edge(120,58).
+edge(58,128).
+edge(128,58).
+edge(59,80).
+edge(80,59).
+edge(59,92).
+edge(92,59).
+edge(59,109).
+edge(109,59).
+edge(59,115).
+edge(115,59).
+edge(59,116).
+edge(116,59).
+edge(59,128).
+edge(128,59).
+edge(60,76).
+edge(76,60).
+edge(60,87).
+edge(87,60).
+edge(60,91).
+edge(91,60).
+edge(60,99).
+edge(99,60).
+edge(60,100).
+edge(100,60).
+edge(60,115).
+edge(115,60).
+edge(61,70).
+edge(70,61).
+edge(61,71).
+edge(71,61).
+edge(61,77).
+edge(77,61).
+edge(61,103).
+edge(103,61).
+edge(61,110).
+edge(110,61).
+edge(61,113).
+edge(113,61).
+edge(61,134).
+edge(134,61).
+edge(62,75).
+edge(75,62).
+edge(62,90).
+edge(90,62).
+edge(62,91).
+edge(91,62).
+edge(62,99).
+edge(99,62).
+edge(62,117).
+edge(117,62).
+edge(62,123).
+edge(123,62).
+edge(62,134).
+edge(134,62).
+edge(63,66).
+edge(66,63).
+edge(63,68).
+edge(68,63).
+edge(63,71).
+edge(71,63).
+edge(63,79).
+edge(79,63).
+edge(63,95).
+edge(95,63).
+edge(63,113).
+edge(113,63).
+edge(63,118).
+edge(118,63).
+edge(64,66).
+edge(66,64).
+edge(64,75).
+edge(75,64).
+edge(64,83).
+edge(83,64).
+edge(64,87).
+edge(87,64).
+edge(64,105).
+edge(105,64).
+edge(64,107).
+edge(107,64).
+edge(64,112).
+edge(112,64).
+edge(64,121).
+edge(121,64).
+edge(65,78).
+edge(78,65).
+edge(65,84).
+edge(84,65).
+edge(65,97).
+edge(97,65).
+edge(65,101).
+edge(101,65).
+edge(65,103).
+edge(103,65).
+edge(65,106).
+edge(106,65).
+edge(65,109).
+edge(109,65).
+edge(65,132).
+edge(132,65).
+edge(66,67).
+edge(67,66).
+edge(66,74).
+edge(74,66).
+edge(66,75).
+edge(75,66).
+edge(67,74).
+edge(74,67).
+edge(67,79).
+edge(79,67).
+edge(67,90).
+edge(90,67).
+edge(67,98).
+edge(98,67).
+edge(67,117).
+edge(117,67).
+edge(67,133).
+edge(133,67).
+edge(68,74).
+edge(74,68).
+edge(68,77).
+edge(77,68).
+edge(68,87).
+edge(87,68).
+edge(68,96).
+edge(96,68).
+edge(68,108).
+edge(108,68).
+edge(68,111).
+edge(111,68).
+edge(68,122).
+edge(122,68).
+edge(69,71).
+edge(71,69).
+edge(69,75).
+edge(75,69).
+edge(69,89).
+edge(89,69).
+edge(69,92).
+edge(92,69).
+edge(69,93).
+edge(93,69).
+edge(69,97).
+edge(97,69).
+edge(69,102).
+edge(102,69).
+edge(69,110).
+edge(110,69).
+edge(69,115).
+edge(115,69).
+edge(69,132).
+edge(132,69).
+edge(70,96).
+edge(96,70).
+edge(70,108).
+edge(108,70).
+edge(70,111).
+edge(111,70).
+edge(70,118).
+edge(118,70).
+edge(70,129).
+edge(129,70).
+edge(70,135).
+edge(135,70).
+edge(71,73).
+edge(73,71).
+edge(71,75).
+edge(75,71).
+edge(71,85).
+edge(85,71).
+edge(71,89).
+edge(89,71).
+edge(71,91).
+edge(91,71).
+edge(71,94).
+edge(94,71).
+edge(71,109).
+edge(109,71).
+edge(71,121).
+edge(121,71).
+edge(71,125).
+edge(125,71).
+edge(71,126).
+edge(126,71).
+edge(72,76).
+edge(76,72).
+edge(72,97).
+edge(97,72).
+edge(72,134).
+edge(134,72).
+edge(73,82).
+edge(82,73).
+edge(73,84).
+edge(84,73).
+edge(73,89).
+edge(89,73).
+edge(73,104).
+edge(104,73).
+edge(73,116).
+edge(116,73).
+edge(73,131).
+edge(131,73).
+edge(73,134).
+edge(134,73).
+edge(73,135).
+edge(135,73).
+edge(74,84).
+edge(84,74).
+edge(74,91).
+edge(91,74).
+edge(74,101).
+edge(101,74).
+edge(74,106).
+edge(106,74).
+edge(74,109).
+edge(109,74).
+edge(74,110).
+edge(110,74).
+edge(74,116).
+edge(116,74).
+edge(74,125).
+edge(125,74).
+edge(74,129).
+edge(129,74).
+edge(75,79).
+edge(79,75).
+edge(75,96).
+edge(96,75).
+edge(75,99).
+edge(99,75).
+edge(75,101).
+edge(101,75).
+edge(75,102).
+edge(102,75).
+edge(75,104).
+edge(104,75).
+edge(75,107).
+edge(107,75).
+edge(75,112).
+edge(112,75).
+edge(75,116).
+edge(116,75).
+edge(75,119).
+edge(119,75).
+edge(75,122).
+edge(122,75).
+edge(75,134).
+edge(134,75).
+edge(76,78).
+edge(78,76).
+edge(76,84).
+edge(84,76).
+edge(76,91).
+edge(91,76).
+edge(76,92).
+edge(92,76).
+edge(76,94).
+edge(94,76).
+edge(77,88).
+edge(88,77).
+edge(77,94).
+edge(94,77).
+edge(77,105).
+edge(105,77).
+edge(77,108).
+edge(108,77).
+edge(77,114).
+edge(114,77).
+edge(78,82).
+edge(82,78).
+edge(78,99).
+edge(99,78).
+edge(78,109).
+edge(109,78).
+edge(78,132).
+edge(132,78).
+edge(79,82).
+edge(82,79).
+edge(79,84).
+edge(84,79).
+edge(79,122).
+edge(122,79).
+edge(79,134).
+edge(134,79).
+edge(80,87).
+edge(87,80).
+edge(80,93).
+edge(93,80).
+edge(80,114).
+edge(114,80).
+edge(80,118).
+edge(118,80).
+edge(80,123).
+edge(123,80).
+edge(81,85).
+edge(85,81).
+edge(81,88).
+edge(88,81).
+edge(81,89).
+edge(89,81).
+edge(81,90).
+edge(90,81).
+edge(81,97).
+edge(97,81).
+edge(81,106).
+edge(106,81).
+edge(81,129).
+edge(129,81).
+edge(82,83).
+edge(83,82).
+edge(82,109).
+edge(109,82).
+edge(82,124).
+edge(124,82).
+edge(83,116).
+edge(116,83).
+edge(83,125).
+edge(125,83).
+edge(84,86).
+edge(86,84).
+edge(84,125).
+edge(125,84).
+edge(84,135).
+edge(135,84).
+edge(85,101).
+edge(101,85).
+edge(85,128).
+edge(128,85).
+edge(86,105).
+edge(105,86).
+edge(86,111).
+edge(111,86).
+edge(86,126).
+edge(126,86).
+edge(87,94).
+edge(94,87).
+edge(87,105).
+edge(105,87).
+edge(87,128).
+edge(128,87).
+edge(88,103).
+edge(103,88).
+edge(88,106).
+edge(106,88).
+edge(88,112).
+edge(112,88).
+edge(88,117).
+edge(117,88).
+edge(89,95).
+edge(95,89).
+edge(89,99).
+edge(99,89).
+edge(89,119).
+edge(119,89).
+edge(89,134).
+edge(134,89).
+edge(89,135).
+edge(135,89).
+edge(90,111).
+edge(111,90).
+edge(90,131).
+edge(131,90).
+edge(91,92).
+edge(92,91).
+edge(91,101).
+edge(101,91).
+edge(91,103).
+edge(103,91).
+edge(91,112).
+edge(112,91).
+edge(91,113).
+edge(113,91).
+edge(91,125).
+edge(125,91).
+edge(92,103).
+edge(103,92).
+edge(92,108).
+edge(108,92).
+edge(92,126).
+edge(126,92).
+edge(93,95).
+edge(95,93).
+edge(93,99).
+edge(99,93).
+edge(93,121).
+edge(121,93).
+edge(93,127).
+edge(127,93).
+edge(94,98).
+edge(98,94).
+edge(94,103).
+edge(103,94).
+edge(94,111).
+edge(111,94).
+edge(94,131).
+edge(131,94).
+edge(94,132).
+edge(132,94).
+edge(94,135).
+edge(135,94).
+edge(95,99).
+edge(99,95).
+edge(95,127).
+edge(127,95).
+edge(96,121).
+edge(121,96).
+edge(97,101).
+edge(101,97).
+edge(97,108).
+edge(108,97).
+edge(97,129).
+edge(129,97).
+edge(97,135).
+edge(135,97).
+edge(98,114).
+edge(114,98).
+edge(98,118).
+edge(118,98).
+edge(98,122).
+edge(122,98).
+edge(98,128).
+edge(128,98).
+edge(98,130).
+edge(130,98).
+edge(99,102).
+edge(102,99).
+edge(99,104).
+edge(104,99).
+edge(99,108).
+edge(108,99).
+edge(99,113).
+edge(113,99).
+edge(99,133).
+edge(133,99).
+edge(100,113).
+edge(113,100).
+edge(102,105).
+edge(105,102).
+edge(102,106).
+edge(106,102).
+edge(102,110).
+edge(110,102).
+edge(102,111).
+edge(111,102).
+edge(102,133).
+edge(133,102).
+edge(103,105).
+edge(105,103).
+edge(103,106).
+edge(106,103).
+edge(103,109).
+edge(109,103).
+edge(103,110).
+edge(110,103).
+edge(103,125).
+edge(125,103).
+edge(104,107).
+edge(107,104).
+edge(104,108).
+edge(108,104).
+edge(104,124).
+edge(124,104).
+edge(105,111).
+edge(111,105).
+edge(106,110).
+edge(110,106).
+edge(106,133).
+edge(133,106).
+edge(107,125).
+edge(125,107).
+edge(108,115).
+edge(115,108).
+edge(108,117).
+edge(117,108).
+edge(108,125).
+edge(125,108).
+edge(109,120).
+edge(120,109).
+edge(109,128).
+edge(128,109).
+edge(110,116).
+edge(116,110).
+edge(110,119).
+edge(119,110).
+edge(110,122).
+edge(122,110).
+edge(110,125).
+edge(125,110).
+edge(111,116).
+edge(116,111).
+edge(111,135).
+edge(135,111).
+edge(112,113).
+edge(113,112).
+edge(112,117).
+edge(117,112).
+edge(112,119).
+edge(119,112).
+edge(112,133).
+edge(133,112).
+edge(113,133).
+edge(133,113).
+edge(114,116).
+edge(116,114).
+edge(114,125).
+edge(125,114).
+edge(114,127).
+edge(127,114).
+edge(114,134).
+edge(134,114).
+edge(115,135).
+edge(135,115).
+edge(117,119).
+edge(119,117).
+edge(117,122).
+edge(122,117).
+edge(117,129).
+edge(129,117).
+edge(117,130).
+edge(130,117).
+edge(118,126).
+edge(126,118).
+edge(119,126).
+edge(126,119).
+edge(119,129).
+edge(129,119).
+edge(119,134).
+edge(134,119).
+edge(120,123).
+edge(123,120).
+edge(120,129).
+edge(129,120).
+edge(121,127).
+edge(127,121).
+edge(121,131).
+edge(131,121).
+edge(123,135).
+edge(135,123).
+edge(126,130).
+edge(130,126).
+edge(126,131).
+edge(131,126).
+edge(127,131).
+edge(131,127).
+edge(128,132).
+edge(132,128).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0022-graph_colouring-135-0.lp b/examples/clingo/expansion/GraphColouring/instances/0022-graph_colouring-135-0.lp
new file mode 100644
index 0000000..59f3020
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0022-graph_colouring-135-0.lp
@@ -0,0 +1,2043 @@
+#const n=135.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+edge(1,27).
+edge(27,1).
+edge(1,36).
+edge(36,1).
+edge(1,58).
+edge(58,1).
+edge(1,62).
+edge(62,1).
+edge(1,66).
+edge(66,1).
+edge(1,67).
+edge(67,1).
+edge(1,78).
+edge(78,1).
+edge(1,103).
+edge(103,1).
+edge(1,107).
+edge(107,1).
+edge(1,110).
+edge(110,1).
+edge(1,121).
+edge(121,1).
+edge(2,11).
+edge(11,2).
+edge(2,12).
+edge(12,2).
+edge(2,16).
+edge(16,2).
+edge(2,24).
+edge(24,2).
+edge(2,25).
+edge(25,2).
+edge(2,38).
+edge(38,2).
+edge(2,75).
+edge(75,2).
+edge(2,78).
+edge(78,2).
+edge(2,83).
+edge(83,2).
+edge(2,112).
+edge(112,2).
+edge(2,119).
+edge(119,2).
+edge(2,121).
+edge(121,2).
+edge(2,129).
+edge(129,2).
+edge(3,32).
+edge(32,3).
+edge(3,36).
+edge(36,3).
+edge(3,39).
+edge(39,3).
+edge(3,45).
+edge(45,3).
+edge(3,55).
+edge(55,3).
+edge(3,56).
+edge(56,3).
+edge(3,66).
+edge(66,3).
+edge(3,67).
+edge(67,3).
+edge(3,78).
+edge(78,3).
+edge(3,81).
+edge(81,3).
+edge(3,101).
+edge(101,3).
+edge(3,108).
+edge(108,3).
+edge(3,119).
+edge(119,3).
+edge(4,23).
+edge(23,4).
+edge(4,25).
+edge(25,4).
+edge(4,35).
+edge(35,4).
+edge(4,38).
+edge(38,4).
+edge(4,39).
+edge(39,4).
+edge(4,53).
+edge(53,4).
+edge(4,77).
+edge(77,4).
+edge(4,82).
+edge(82,4).
+edge(4,94).
+edge(94,4).
+edge(4,109).
+edge(109,4).
+edge(4,120).
+edge(120,4).
+edge(4,123).
+edge(123,4).
+edge(4,133).
+edge(133,4).
+edge(5,16).
+edge(16,5).
+edge(5,32).
+edge(32,5).
+edge(5,43).
+edge(43,5).
+edge(5,49).
+edge(49,5).
+edge(5,58).
+edge(58,5).
+edge(5,62).
+edge(62,5).
+edge(5,104).
+edge(104,5).
+edge(5,113).
+edge(113,5).
+edge(5,128).
+edge(128,5).
+edge(5,129).
+edge(129,5).
+edge(5,132).
+edge(132,5).
+edge(5,133).
+edge(133,5).
+edge(6,7).
+edge(7,6).
+edge(6,13).
+edge(13,6).
+edge(6,33).
+edge(33,6).
+edge(6,36).
+edge(36,6).
+edge(6,40).
+edge(40,6).
+edge(6,48).
+edge(48,6).
+edge(6,57).
+edge(57,6).
+edge(6,63).
+edge(63,6).
+edge(6,73).
+edge(73,6).
+edge(6,103).
+edge(103,6).
+edge(6,111).
+edge(111,6).
+edge(6,120).
+edge(120,6).
+edge(6,126).
+edge(126,6).
+edge(6,132).
+edge(132,6).
+edge(7,9).
+edge(9,7).
+edge(7,11).
+edge(11,7).
+edge(7,16).
+edge(16,7).
+edge(7,17).
+edge(17,7).
+edge(7,23).
+edge(23,7).
+edge(7,47).
+edge(47,7).
+edge(7,49).
+edge(49,7).
+edge(7,72).
+edge(72,7).
+edge(7,93).
+edge(93,7).
+edge(7,109).
+edge(109,7).
+edge(7,124).
+edge(124,7).
+edge(8,16).
+edge(16,8).
+edge(8,19).
+edge(19,8).
+edge(8,24).
+edge(24,8).
+edge(8,25).
+edge(25,8).
+edge(8,45).
+edge(45,8).
+edge(8,57).
+edge(57,8).
+edge(8,62).
+edge(62,8).
+edge(8,65).
+edge(65,8).
+edge(8,69).
+edge(69,8).
+edge(8,76).
+edge(76,8).
+edge(8,77).
+edge(77,8).
+edge(8,120).
+edge(120,8).
+edge(8,128).
+edge(128,8).
+edge(9,25).
+edge(25,9).
+edge(9,33).
+edge(33,9).
+edge(9,35).
+edge(35,9).
+edge(9,52).
+edge(52,9).
+edge(9,58).
+edge(58,9).
+edge(9,73).
+edge(73,9).
+edge(9,114).
+edge(114,9).
+edge(9,124).
+edge(124,9).
+edge(9,127).
+edge(127,9).
+edge(10,27).
+edge(27,10).
+edge(10,28).
+edge(28,10).
+edge(10,39).
+edge(39,10).
+edge(10,58).
+edge(58,10).
+edge(10,69).
+edge(69,10).
+edge(10,90).
+edge(90,10).
+edge(10,110).
+edge(110,10).
+edge(10,112).
+edge(112,10).
+edge(10,117).
+edge(117,10).
+edge(10,132).
+edge(132,10).
+edge(11,14).
+edge(14,11).
+edge(11,17).
+edge(17,11).
+edge(11,22).
+edge(22,11).
+edge(11,31).
+edge(31,11).
+edge(11,37).
+edge(37,11).
+edge(11,40).
+edge(40,11).
+edge(11,56).
+edge(56,11).
+edge(11,59).
+edge(59,11).
+edge(11,63).
+edge(63,11).
+edge(11,65).
+edge(65,11).
+edge(11,85).
+edge(85,11).
+edge(11,89).
+edge(89,11).
+edge(11,90).
+edge(90,11).
+edge(11,92).
+edge(92,11).
+edge(11,95).
+edge(95,11).
+edge(11,113).
+edge(113,11).
+edge(11,115).
+edge(115,11).
+edge(12,20).
+edge(20,12).
+edge(12,25).
+edge(25,12).
+edge(12,32).
+edge(32,12).
+edge(12,33).
+edge(33,12).
+edge(12,45).
+edge(45,12).
+edge(12,55).
+edge(55,12).
+edge(12,64).
+edge(64,12).
+edge(12,68).
+edge(68,12).
+edge(12,71).
+edge(71,12).
+edge(12,72).
+edge(72,12).
+edge(12,80).
+edge(80,12).
+edge(12,84).
+edge(84,12).
+edge(12,88).
+edge(88,12).
+edge(12,109).
+edge(109,12).
+edge(12,124).
+edge(124,12).
+edge(12,125).
+edge(125,12).
+edge(12,127).
+edge(127,12).
+edge(13,28).
+edge(28,13).
+edge(13,61).
+edge(61,13).
+edge(13,74).
+edge(74,13).
+edge(13,77).
+edge(77,13).
+edge(13,97).
+edge(97,13).
+edge(13,105).
+edge(105,13).
+edge(13,115).
+edge(115,13).
+edge(13,117).
+edge(117,13).
+edge(13,119).
+edge(119,13).
+edge(13,130).
+edge(130,13).
+edge(13,133).
+edge(133,13).
+edge(14,15).
+edge(15,14).
+edge(14,23).
+edge(23,14).
+edge(14,24).
+edge(24,14).
+edge(14,31).
+edge(31,14).
+edge(14,38).
+edge(38,14).
+edge(14,44).
+edge(44,14).
+edge(14,50).
+edge(50,14).
+edge(14,52).
+edge(52,14).
+edge(14,80).
+edge(80,14).
+edge(14,81).
+edge(81,14).
+edge(14,85).
+edge(85,14).
+edge(14,88).
+edge(88,14).
+edge(14,96).
+edge(96,14).
+edge(14,102).
+edge(102,14).
+edge(14,111).
+edge(111,14).
+edge(14,113).
+edge(113,14).
+edge(14,133).
+edge(133,14).
+edge(15,16).
+edge(16,15).
+edge(15,28).
+edge(28,15).
+edge(15,31).
+edge(31,15).
+edge(15,34).
+edge(34,15).
+edge(15,81).
+edge(81,15).
+edge(15,84).
+edge(84,15).
+edge(15,94).
+edge(94,15).
+edge(15,96).
+edge(96,15).
+edge(15,103).
+edge(103,15).
+edge(15,114).
+edge(114,15).
+edge(15,117).
+edge(117,15).
+edge(15,122).
+edge(122,15).
+edge(15,127).
+edge(127,15).
+edge(16,29).
+edge(29,16).
+edge(16,44).
+edge(44,16).
+edge(16,51).
+edge(51,16).
+edge(16,69).
+edge(69,16).
+edge(16,71).
+edge(71,16).
+edge(16,105).
+edge(105,16).
+edge(16,128).
+edge(128,16).
+edge(16,129).
+edge(129,16).
+edge(17,18).
+edge(18,17).
+edge(17,50).
+edge(50,17).
+edge(17,54).
+edge(54,17).
+edge(17,85).
+edge(85,17).
+edge(17,106).
+edge(106,17).
+edge(17,124).
+edge(124,17).
+edge(17,129).
+edge(129,17).
+edge(17,131).
+edge(131,17).
+edge(17,132).
+edge(132,17).
+edge(18,46).
+edge(46,18).
+edge(18,63).
+edge(63,18).
+edge(18,68).
+edge(68,18).
+edge(18,71).
+edge(71,18).
+edge(18,80).
+edge(80,18).
+edge(18,81).
+edge(81,18).
+edge(18,87).
+edge(87,18).
+edge(18,114).
+edge(114,18).
+edge(18,115).
+edge(115,18).
+edge(18,128).
+edge(128,18).
+edge(19,21).
+edge(21,19).
+edge(19,25).
+edge(25,19).
+edge(19,35).
+edge(35,19).
+edge(19,52).
+edge(52,19).
+edge(19,90).
+edge(90,19).
+edge(19,97).
+edge(97,19).
+edge(19,103).
+edge(103,19).
+edge(19,115).
+edge(115,19).
+edge(20,40).
+edge(40,20).
+edge(20,43).
+edge(43,20).
+edge(20,45).
+edge(45,20).
+edge(20,57).
+edge(57,20).
+edge(20,70).
+edge(70,20).
+edge(20,72).
+edge(72,20).
+edge(20,78).
+edge(78,20).
+edge(20,81).
+edge(81,20).
+edge(20,88).
+edge(88,20).
+edge(20,98).
+edge(98,20).
+edge(20,102).
+edge(102,20).
+edge(20,103).
+edge(103,20).
+edge(20,110).
+edge(110,20).
+edge(20,115).
+edge(115,20).
+edge(20,117).
+edge(117,20).
+edge(21,41).
+edge(41,21).
+edge(21,44).
+edge(44,21).
+edge(21,57).
+edge(57,21).
+edge(21,61).
+edge(61,21).
+edge(21,99).
+edge(99,21).
+edge(21,129).
+edge(129,21).
+edge(21,130).
+edge(130,21).
+edge(21,131).
+edge(131,21).
+edge(22,25).
+edge(25,22).
+edge(22,34).
+edge(34,22).
+edge(22,37).
+edge(37,22).
+edge(22,54).
+edge(54,22).
+edge(22,58).
+edge(58,22).
+edge(22,65).
+edge(65,22).
+edge(22,68).
+edge(68,22).
+edge(22,73).
+edge(73,22).
+edge(22,97).
+edge(97,22).
+edge(22,110).
+edge(110,22).
+edge(22,113).
+edge(113,22).
+edge(22,114).
+edge(114,22).
+edge(22,124).
+edge(124,22).
+edge(22,126).
+edge(126,22).
+edge(23,36).
+edge(36,23).
+edge(23,40).
+edge(40,23).
+edge(23,43).
+edge(43,23).
+edge(23,44).
+edge(44,23).
+edge(23,57).
+edge(57,23).
+edge(23,60).
+edge(60,23).
+edge(23,62).
+edge(62,23).
+edge(23,64).
+edge(64,23).
+edge(23,67).
+edge(67,23).
+edge(23,71).
+edge(71,23).
+edge(23,73).
+edge(73,23).
+edge(23,131).
+edge(131,23).
+edge(23,133).
+edge(133,23).
+edge(24,28).
+edge(28,24).
+edge(24,29).
+edge(29,24).
+edge(24,36).
+edge(36,24).
+edge(24,37).
+edge(37,24).
+edge(24,38).
+edge(38,24).
+edge(24,43).
+edge(43,24).
+edge(24,44).
+edge(44,24).
+edge(24,69).
+edge(69,24).
+edge(24,72).
+edge(72,24).
+edge(24,79).
+edge(79,24).
+edge(24,81).
+edge(81,24).
+edge(24,89).
+edge(89,24).
+edge(24,104).
+edge(104,24).
+edge(24,105).
+edge(105,24).
+edge(24,113).
+edge(113,24).
+edge(24,117).
+edge(117,24).
+edge(24,132).
+edge(132,24).
+edge(25,33).
+edge(33,25).
+edge(25,41).
+edge(41,25).
+edge(25,45).
+edge(45,25).
+edge(25,53).
+edge(53,25).
+edge(25,56).
+edge(56,25).
+edge(25,65).
+edge(65,25).
+edge(25,71).
+edge(71,25).
+edge(25,79).
+edge(79,25).
+edge(25,81).
+edge(81,25).
+edge(25,95).
+edge(95,25).
+edge(25,132).
+edge(132,25).
+edge(26,33).
+edge(33,26).
+edge(26,50).
+edge(50,26).
+edge(26,63).
+edge(63,26).
+edge(26,81).
+edge(81,26).
+edge(26,84).
+edge(84,26).
+edge(26,98).
+edge(98,26).
+edge(26,115).
+edge(115,26).
+edge(26,116).
+edge(116,26).
+edge(26,120).
+edge(120,26).
+edge(26,127).
+edge(127,26).
+edge(27,50).
+edge(50,27).
+edge(27,54).
+edge(54,27).
+edge(27,56).
+edge(56,27).
+edge(27,63).
+edge(63,27).
+edge(27,86).
+edge(86,27).
+edge(27,87).
+edge(87,27).
+edge(27,90).
+edge(90,27).
+edge(27,94).
+edge(94,27).
+edge(27,105).
+edge(105,27).
+edge(27,110).
+edge(110,27).
+edge(27,111).
+edge(111,27).
+edge(27,119).
+edge(119,27).
+edge(27,129).
+edge(129,27).
+edge(27,130).
+edge(130,27).
+edge(27,134).
+edge(134,27).
+edge(28,34).
+edge(34,28).
+edge(28,36).
+edge(36,28).
+edge(28,47).
+edge(47,28).
+edge(28,54).
+edge(54,28).
+edge(28,65).
+edge(65,28).
+edge(28,66).
+edge(66,28).
+edge(28,76).
+edge(76,28).
+edge(28,81).
+edge(81,28).
+edge(28,86).
+edge(86,28).
+edge(28,88).
+edge(88,28).
+edge(28,105).
+edge(105,28).
+edge(28,109).
+edge(109,28).
+edge(28,129).
+edge(129,28).
+edge(28,132).
+edge(132,28).
+edge(29,35).
+edge(35,29).
+edge(29,39).
+edge(39,29).
+edge(29,41).
+edge(41,29).
+edge(29,43).
+edge(43,29).
+edge(29,45).
+edge(45,29).
+edge(29,47).
+edge(47,29).
+edge(29,52).
+edge(52,29).
+edge(29,72).
+edge(72,29).
+edge(29,73).
+edge(73,29).
+edge(29,81).
+edge(81,29).
+edge(29,84).
+edge(84,29).
+edge(29,96).
+edge(96,29).
+edge(29,103).
+edge(103,29).
+edge(29,104).
+edge(104,29).
+edge(29,109).
+edge(109,29).
+edge(29,117).
+edge(117,29).
+edge(29,120).
+edge(120,29).
+edge(29,128).
+edge(128,29).
+edge(30,38).
+edge(38,30).
+edge(30,45).
+edge(45,30).
+edge(30,50).
+edge(50,30).
+edge(30,54).
+edge(54,30).
+edge(30,73).
+edge(73,30).
+edge(30,78).
+edge(78,30).
+edge(30,101).
+edge(101,30).
+edge(30,124).
+edge(124,30).
+edge(30,128).
+edge(128,30).
+edge(31,32).
+edge(32,31).
+edge(31,34).
+edge(34,31).
+edge(31,38).
+edge(38,31).
+edge(31,44).
+edge(44,31).
+edge(31,45).
+edge(45,31).
+edge(31,51).
+edge(51,31).
+edge(31,55).
+edge(55,31).
+edge(31,57).
+edge(57,31).
+edge(31,66).
+edge(66,31).
+edge(31,70).
+edge(70,31).
+edge(31,74).
+edge(74,31).
+edge(31,78).
+edge(78,31).
+edge(31,83).
+edge(83,31).
+edge(31,102).
+edge(102,31).
+edge(31,121).
+edge(121,31).
+edge(31,122).
+edge(122,31).
+edge(32,39).
+edge(39,32).
+edge(32,45).
+edge(45,32).
+edge(32,52).
+edge(52,32).
+edge(32,59).
+edge(59,32).
+edge(32,70).
+edge(70,32).
+edge(32,74).
+edge(74,32).
+edge(32,77).
+edge(77,32).
+edge(32,83).
+edge(83,32).
+edge(32,92).
+edge(92,32).
+edge(32,95).
+edge(95,32).
+edge(32,96).
+edge(96,32).
+edge(32,115).
+edge(115,32).
+edge(32,133).
+edge(133,32).
+edge(32,134).
+edge(134,32).
+edge(33,46).
+edge(46,33).
+edge(33,54).
+edge(54,33).
+edge(33,57).
+edge(57,33).
+edge(33,62).
+edge(62,33).
+edge(33,72).
+edge(72,33).
+edge(33,76).
+edge(76,33).
+edge(33,85).
+edge(85,33).
+edge(33,87).
+edge(87,33).
+edge(33,99).
+edge(99,33).
+edge(33,100).
+edge(100,33).
+edge(33,119).
+edge(119,33).
+edge(33,121).
+edge(121,33).
+edge(33,125).
+edge(125,33).
+edge(34,36).
+edge(36,34).
+edge(34,37).
+edge(37,34).
+edge(34,52).
+edge(52,34).
+edge(34,53).
+edge(53,34).
+edge(34,74).
+edge(74,34).
+edge(34,88).
+edge(88,34).
+edge(34,89).
+edge(89,34).
+edge(34,99).
+edge(99,34).
+edge(34,107).
+edge(107,34).
+edge(34,114).
+edge(114,34).
+edge(34,117).
+edge(117,34).
+edge(34,121).
+edge(121,34).
+edge(34,126).
+edge(126,34).
+edge(34,129).
+edge(129,34).
+edge(35,41).
+edge(41,35).
+edge(35,46).
+edge(46,35).
+edge(35,47).
+edge(47,35).
+edge(35,48).
+edge(48,35).
+edge(35,49).
+edge(49,35).
+edge(35,55).
+edge(55,35).
+edge(35,62).
+edge(62,35).
+edge(35,67).
+edge(67,35).
+edge(35,68).
+edge(68,35).
+edge(35,77).
+edge(77,35).
+edge(35,81).
+edge(81,35).
+edge(35,97).
+edge(97,35).
+edge(35,102).
+edge(102,35).
+edge(35,111).
+edge(111,35).
+edge(35,112).
+edge(112,35).
+edge(35,115).
+edge(115,35).
+edge(35,123).
+edge(123,35).
+edge(35,127).
+edge(127,35).
+edge(36,45).
+edge(45,36).
+edge(36,58).
+edge(58,36).
+edge(36,63).
+edge(63,36).
+edge(36,67).
+edge(67,36).
+edge(36,74).
+edge(74,36).
+edge(36,111).
+edge(111,36).
+edge(36,119).
+edge(119,36).
+edge(36,133).
+edge(133,36).
+edge(37,53).
+edge(53,37).
+edge(37,57).
+edge(57,37).
+edge(37,62).
+edge(62,37).
+edge(37,71).
+edge(71,37).
+edge(37,94).
+edge(94,37).
+edge(37,109).
+edge(109,37).
+edge(37,112).
+edge(112,37).
+edge(37,124).
+edge(124,37).
+edge(37,125).
+edge(125,37).
+edge(38,44).
+edge(44,38).
+edge(38,47).
+edge(47,38).
+edge(38,51).
+edge(51,38).
+edge(38,80).
+edge(80,38).
+edge(38,84).
+edge(84,38).
+edge(38,92).
+edge(92,38).
+edge(38,95).
+edge(95,38).
+edge(38,99).
+edge(99,38).
+edge(38,100).
+edge(100,38).
+edge(38,112).
+edge(112,38).
+edge(38,125).
+edge(125,38).
+edge(39,86).
+edge(86,39).
+edge(39,105).
+edge(105,39).
+edge(39,106).
+edge(106,39).
+edge(39,132).
+edge(132,39).
+edge(40,41).
+edge(41,40).
+edge(40,50).
+edge(50,40).
+edge(40,51).
+edge(51,40).
+edge(40,68).
+edge(68,40).
+edge(40,71).
+edge(71,40).
+edge(40,81).
+edge(81,40).
+edge(40,85).
+edge(85,40).
+edge(40,87).
+edge(87,40).
+edge(40,98).
+edge(98,40).
+edge(40,109).
+edge(109,40).
+edge(40,113).
+edge(113,40).
+edge(40,115).
+edge(115,40).
+edge(40,133).
+edge(133,40).
+edge(40,135).
+edge(135,40).
+edge(41,44).
+edge(44,41).
+edge(41,52).
+edge(52,41).
+edge(41,71).
+edge(71,41).
+edge(41,73).
+edge(73,41).
+edge(41,76).
+edge(76,41).
+edge(41,77).
+edge(77,41).
+edge(41,83).
+edge(83,41).
+edge(41,90).
+edge(90,41).
+edge(41,107).
+edge(107,41).
+edge(41,108).
+edge(108,41).
+edge(41,112).
+edge(112,41).
+edge(41,113).
+edge(113,41).
+edge(41,116).
+edge(116,41).
+edge(41,119).
+edge(119,41).
+edge(41,126).
+edge(126,41).
+edge(41,129).
+edge(129,41).
+edge(41,135).
+edge(135,41).
+edge(42,56).
+edge(56,42).
+edge(42,58).
+edge(58,42).
+edge(42,76).
+edge(76,42).
+edge(42,91).
+edge(91,42).
+edge(42,109).
+edge(109,42).
+edge(42,116).
+edge(116,42).
+edge(42,122).
+edge(122,42).
+edge(43,69).
+edge(69,43).
+edge(43,83).
+edge(83,43).
+edge(43,89).
+edge(89,43).
+edge(43,99).
+edge(99,43).
+edge(43,106).
+edge(106,43).
+edge(43,112).
+edge(112,43).
+edge(43,114).
+edge(114,43).
+edge(43,133).
+edge(133,43).
+edge(44,54).
+edge(54,44).
+edge(44,59).
+edge(59,44).
+edge(44,65).
+edge(65,44).
+edge(44,77).
+edge(77,44).
+edge(44,78).
+edge(78,44).
+edge(44,91).
+edge(91,44).
+edge(44,109).
+edge(109,44).
+edge(44,110).
+edge(110,44).
+edge(44,118).
+edge(118,44).
+edge(45,75).
+edge(75,45).
+edge(45,84).
+edge(84,45).
+edge(45,96).
+edge(96,45).
+edge(45,102).
+edge(102,45).
+edge(45,103).
+edge(103,45).
+edge(45,111).
+edge(111,45).
+edge(45,120).
+edge(120,45).
+edge(45,122).
+edge(122,45).
+edge(45,129).
+edge(129,45).
+edge(46,56).
+edge(56,46).
+edge(46,94).
+edge(94,46).
+edge(46,105).
+edge(105,46).
+edge(46,109).
+edge(109,46).
+edge(46,110).
+edge(110,46).
+edge(46,129).
+edge(129,46).
+edge(47,79).
+edge(79,47).
+edge(47,86).
+edge(86,47).
+edge(47,98).
+edge(98,47).
+edge(47,106).
+edge(106,47).
+edge(47,117).
+edge(117,47).
+edge(47,132).
+edge(132,47).
+edge(48,49).
+edge(49,48).
+edge(48,53).
+edge(53,48).
+edge(48,59).
+edge(59,48).
+edge(48,64).
+edge(64,48).
+edge(48,65).
+edge(65,48).
+edge(48,70).
+edge(70,48).
+edge(48,71).
+edge(71,48).
+edge(48,81).
+edge(81,48).
+edge(48,85).
+edge(85,48).
+edge(48,94).
+edge(94,48).
+edge(48,95).
+edge(95,48).
+edge(49,57).
+edge(57,49).
+edge(49,69).
+edge(69,49).
+edge(49,100).
+edge(100,49).
+edge(49,118).
+edge(118,49).
+edge(50,57).
+edge(57,50).
+edge(50,81).
+edge(81,50).
+edge(50,85).
+edge(85,50).
+edge(50,86).
+edge(86,50).
+edge(50,100).
+edge(100,50).
+edge(50,104).
+edge(104,50).
+edge(50,105).
+edge(105,50).
+edge(50,108).
+edge(108,50).
+edge(50,118).
+edge(118,50).
+edge(50,133).
+edge(133,50).
+edge(51,52).
+edge(52,51).
+edge(51,53).
+edge(53,51).
+edge(51,54).
+edge(54,51).
+edge(51,57).
+edge(57,51).
+edge(51,58).
+edge(58,51).
+edge(51,62).
+edge(62,51).
+edge(51,66).
+edge(66,51).
+edge(51,72).
+edge(72,51).
+edge(51,75).
+edge(75,51).
+edge(51,76).
+edge(76,51).
+edge(51,79).
+edge(79,51).
+edge(51,87).
+edge(87,51).
+edge(51,104).
+edge(104,51).
+edge(51,108).
+edge(108,51).
+edge(51,110).
+edge(110,51).
+edge(51,116).
+edge(116,51).
+edge(51,117).
+edge(117,51).
+edge(51,130).
+edge(130,51).
+edge(51,131).
+edge(131,51).
+edge(51,133).
+edge(133,51).
+edge(52,53).
+edge(53,52).
+edge(52,75).
+edge(75,52).
+edge(52,85).
+edge(85,52).
+edge(52,94).
+edge(94,52).
+edge(52,100).
+edge(100,52).
+edge(52,102).
+edge(102,52).
+edge(53,55).
+edge(55,53).
+edge(53,64).
+edge(64,53).
+edge(53,69).
+edge(69,53).
+edge(53,80).
+edge(80,53).
+edge(53,81).
+edge(81,53).
+edge(53,87).
+edge(87,53).
+edge(53,98).
+edge(98,53).
+edge(53,102).
+edge(102,53).
+edge(53,134).
+edge(134,53).
+edge(54,75).
+edge(75,54).
+edge(54,111).
+edge(111,54).
+edge(54,133).
+edge(133,54).
+edge(55,57).
+edge(57,55).
+edge(55,80).
+edge(80,55).
+edge(55,93).
+edge(93,55).
+edge(55,107).
+edge(107,55).
+edge(55,116).
+edge(116,55).
+edge(55,132).
+edge(132,55).
+edge(56,58).
+edge(58,56).
+edge(56,59).
+edge(59,56).
+edge(56,61).
+edge(61,56).
+edge(56,68).
+edge(68,56).
+edge(56,76).
+edge(76,56).
+edge(56,88).
+edge(88,56).
+edge(56,95).
+edge(95,56).
+edge(56,100).
+edge(100,56).
+edge(56,111).
+edge(111,56).
+edge(56,112).
+edge(112,56).
+edge(56,114).
+edge(114,56).
+edge(56,118).
+edge(118,56).
+edge(56,124).
+edge(124,56).
+edge(56,125).
+edge(125,56).
+edge(56,135).
+edge(135,56).
+edge(57,62).
+edge(62,57).
+edge(57,66).
+edge(66,57).
+edge(57,75).
+edge(75,57).
+edge(57,86).
+edge(86,57).
+edge(57,95).
+edge(95,57).
+edge(57,97).
+edge(97,57).
+edge(57,106).
+edge(106,57).
+edge(57,108).
+edge(108,57).
+edge(57,121).
+edge(121,57).
+edge(57,122).
+edge(122,57).
+edge(58,82).
+edge(82,58).
+edge(58,94).
+edge(94,58).
+edge(58,130).
+edge(130,58).
+edge(58,133).
+edge(133,58).
+edge(59,69).
+edge(69,59).
+edge(59,77).
+edge(77,59).
+edge(59,78).
+edge(78,59).
+edge(59,99).
+edge(99,59).
+edge(59,101).
+edge(101,59).
+edge(59,107).
+edge(107,59).
+edge(59,108).
+edge(108,59).
+edge(59,110).
+edge(110,59).
+edge(59,111).
+edge(111,59).
+edge(59,126).
+edge(126,59).
+edge(60,62).
+edge(62,60).
+edge(60,74).
+edge(74,60).
+edge(60,84).
+edge(84,60).
+edge(60,98).
+edge(98,60).
+edge(60,102).
+edge(102,60).
+edge(60,107).
+edge(107,60).
+edge(60,110).
+edge(110,60).
+edge(60,118).
+edge(118,60).
+edge(61,66).
+edge(66,61).
+edge(61,67).
+edge(67,61).
+edge(61,73).
+edge(73,61).
+edge(61,98).
+edge(98,61).
+edge(61,101).
+edge(101,61).
+edge(61,121).
+edge(121,61).
+edge(61,127).
+edge(127,61).
+edge(61,133).
+edge(133,61).
+edge(62,83).
+edge(83,62).
+edge(62,89).
+edge(89,62).
+edge(62,107).
+edge(107,62).
+edge(62,133).
+edge(133,62).
+edge(63,72).
+edge(72,63).
+edge(63,73).
+edge(73,63).
+edge(63,78).
+edge(78,63).
+edge(63,86).
+edge(86,63).
+edge(63,106).
+edge(106,63).
+edge(63,107).
+edge(107,63).
+edge(63,110).
+edge(110,63).
+edge(63,129).
+edge(129,63).
+edge(64,70).
+edge(70,64).
+edge(64,84).
+edge(84,64).
+edge(64,87).
+edge(87,64).
+edge(64,120).
+edge(120,64).
+edge(64,127).
+edge(127,64).
+edge(65,72).
+edge(72,65).
+edge(65,96).
+edge(96,65).
+edge(65,110).
+edge(110,65).
+edge(65,121).
+edge(121,65).
+edge(65,123).
+edge(123,65).
+edge(66,68).
+edge(68,66).
+edge(66,71).
+edge(71,66).
+edge(66,86).
+edge(86,66).
+edge(66,97).
+edge(97,66).
+edge(66,98).
+edge(98,66).
+edge(66,118).
+edge(118,66).
+edge(66,121).
+edge(121,66).
+edge(66,122).
+edge(122,66).
+edge(66,128).
+edge(128,66).
+edge(67,82).
+edge(82,67).
+edge(67,84).
+edge(84,67).
+edge(67,87).
+edge(87,67).
+edge(67,120).
+edge(120,67).
+edge(67,131).
+edge(131,67).
+edge(68,79).
+edge(79,68).
+edge(68,92).
+edge(92,68).
+edge(68,104).
+edge(104,68).
+edge(68,116).
+edge(116,68).
+edge(68,132).
+edge(132,68).
+edge(68,133).
+edge(133,68).
+edge(69,78).
+edge(78,69).
+edge(69,127).
+edge(127,69).
+edge(69,130).
+edge(130,69).
+edge(70,71).
+edge(71,70).
+edge(70,76).
+edge(76,70).
+edge(70,99).
+edge(99,70).
+edge(70,127).
+edge(127,70).
+edge(70,128).
+edge(128,70).
+edge(71,85).
+edge(85,71).
+edge(71,94).
+edge(94,71).
+edge(71,99).
+edge(99,71).
+edge(71,102).
+edge(102,71).
+edge(71,105).
+edge(105,71).
+edge(71,111).
+edge(111,71).
+edge(71,116).
+edge(116,71).
+edge(71,118).
+edge(118,71).
+edge(71,125).
+edge(125,71).
+edge(72,88).
+edge(88,72).
+edge(72,92).
+edge(92,72).
+edge(72,94).
+edge(94,72).
+edge(72,96).
+edge(96,72).
+edge(72,113).
+edge(113,72).
+edge(72,135).
+edge(135,72).
+edge(73,83).
+edge(83,73).
+edge(73,90).
+edge(90,73).
+edge(73,95).
+edge(95,73).
+edge(73,97).
+edge(97,73).
+edge(73,98).
+edge(98,73).
+edge(73,99).
+edge(99,73).
+edge(73,106).
+edge(106,73).
+edge(73,112).
+edge(112,73).
+edge(73,113).
+edge(113,73).
+edge(73,127).
+edge(127,73).
+edge(74,90).
+edge(90,74).
+edge(74,94).
+edge(94,74).
+edge(74,96).
+edge(96,74).
+edge(74,110).
+edge(110,74).
+edge(74,130).
+edge(130,74).
+edge(75,86).
+edge(86,75).
+edge(75,112).
+edge(112,75).
+edge(75,114).
+edge(114,75).
+edge(75,116).
+edge(116,75).
+edge(75,132).
+edge(132,75).
+edge(76,83).
+edge(83,76).
+edge(76,92).
+edge(92,76).
+edge(76,105).
+edge(105,76).
+edge(76,132).
+edge(132,76).
+edge(77,89).
+edge(89,77).
+edge(77,92).
+edge(92,77).
+edge(77,93).
+edge(93,77).
+edge(77,95).
+edge(95,77).
+edge(77,100).
+edge(100,77).
+edge(78,80).
+edge(80,78).
+edge(78,82).
+edge(82,78).
+edge(78,89).
+edge(89,78).
+edge(78,108).
+edge(108,78).
+edge(78,114).
+edge(114,78).
+edge(78,118).
+edge(118,78).
+edge(78,120).
+edge(120,78).
+edge(78,134).
+edge(134,78).
+edge(79,85).
+edge(85,79).
+edge(79,107).
+edge(107,79).
+edge(79,122).
+edge(122,79).
+edge(80,95).
+edge(95,80).
+edge(80,107).
+edge(107,80).
+edge(80,110).
+edge(110,80).
+edge(80,121).
+edge(121,80).
+edge(80,134).
+edge(134,80).
+edge(81,92).
+edge(92,81).
+edge(81,104).
+edge(104,81).
+edge(81,107).
+edge(107,81).
+edge(81,113).
+edge(113,81).
+edge(81,118).
+edge(118,81).
+edge(81,127).
+edge(127,81).
+edge(81,133).
+edge(133,81).
+edge(82,88).
+edge(88,82).
+edge(82,96).
+edge(96,82).
+edge(82,100).
+edge(100,82).
+edge(82,103).
+edge(103,82).
+edge(82,104).
+edge(104,82).
+edge(83,91).
+edge(91,83).
+edge(83,94).
+edge(94,83).
+edge(83,101).
+edge(101,83).
+edge(83,107).
+edge(107,83).
+edge(83,108).
+edge(108,83).
+edge(83,116).
+edge(116,83).
+edge(83,126).
+edge(126,83).
+edge(83,132).
+edge(132,83).
+edge(83,133).
+edge(133,83).
+edge(83,134).
+edge(134,83).
+edge(84,88).
+edge(88,84).
+edge(84,93).
+edge(93,84).
+edge(84,99).
+edge(99,84).
+edge(85,91).
+edge(91,85).
+edge(85,95).
+edge(95,85).
+edge(85,99).
+edge(99,85).
+edge(85,118).
+edge(118,85).
+edge(86,87).
+edge(87,86).
+edge(86,89).
+edge(89,86).
+edge(86,91).
+edge(91,86).
+edge(86,98).
+edge(98,86).
+edge(86,108).
+edge(108,86).
+edge(86,128).
+edge(128,86).
+edge(86,130).
+edge(130,86).
+edge(87,99).
+edge(99,87).
+edge(87,101).
+edge(101,87).
+edge(87,102).
+edge(102,87).
+edge(87,109).
+edge(109,87).
+edge(87,127).
+edge(127,87).
+edge(88,89).
+edge(89,88).
+edge(88,91).
+edge(91,88).
+edge(88,98).
+edge(98,88).
+edge(88,105).
+edge(105,88).
+edge(88,109).
+edge(109,88).
+edge(89,90).
+edge(90,89).
+edge(89,134).
+edge(134,89).
+edge(90,92).
+edge(92,90).
+edge(90,107).
+edge(107,90).
+edge(90,134).
+edge(134,90).
+edge(91,111).
+edge(111,91).
+edge(91,116).
+edge(116,91).
+edge(91,120).
+edge(120,91).
+edge(91,123).
+edge(123,91).
+edge(91,128).
+edge(128,91).
+edge(91,130).
+edge(130,91).
+edge(92,95).
+edge(95,92).
+edge(92,97).
+edge(97,92).
+edge(92,107).
+edge(107,92).
+edge(92,130).
+edge(130,92).
+edge(92,135).
+edge(135,92).
+edge(93,121).
+edge(121,93).
+edge(94,95).
+edge(95,94).
+edge(94,118).
+edge(118,94).
+edge(94,123).
+edge(123,94).
+edge(95,111).
+edge(111,95).
+edge(95,123).
+edge(123,95).
+edge(95,133).
+edge(133,95).
+edge(96,97).
+edge(97,96).
+edge(96,109).
+edge(109,96).
+edge(96,117).
+edge(117,96).
+edge(96,121).
+edge(121,96).
+edge(96,127).
+edge(127,96).
+edge(96,132).
+edge(132,96).
+edge(97,106).
+edge(106,97).
+edge(97,107).
+edge(107,97).
+edge(97,127).
+edge(127,97).
+edge(98,104).
+edge(104,98).
+edge(98,106).
+edge(106,98).
+edge(98,120).
+edge(120,98).
+edge(98,121).
+edge(121,98).
+edge(98,126).
+edge(126,98).
+edge(98,132).
+edge(132,98).
+edge(99,105).
+edge(105,99).
+edge(99,117).
+edge(117,99).
+edge(99,121).
+edge(121,99).
+edge(99,132).
+edge(132,99).
+edge(100,106).
+edge(106,100).
+edge(100,109).
+edge(109,100).
+edge(100,114).
+edge(114,100).
+edge(100,117).
+edge(117,100).
+edge(100,129).
+edge(129,100).
+edge(100,130).
+edge(130,100).
+edge(100,132).
+edge(132,100).
+edge(101,102).
+edge(102,101).
+edge(101,109).
+edge(109,101).
+edge(101,130).
+edge(130,101).
+edge(101,131).
+edge(131,101).
+edge(102,107).
+edge(107,102).
+edge(102,109).
+edge(109,102).
+edge(102,116).
+edge(116,102).
+edge(102,123).
+edge(123,102).
+edge(102,128).
+edge(128,102).
+edge(102,135).
+edge(135,102).
+edge(103,104).
+edge(104,103).
+edge(103,109).
+edge(109,103).
+edge(103,111).
+edge(111,103).
+edge(103,117).
+edge(117,103).
+edge(103,121).
+edge(121,103).
+edge(103,131).
+edge(131,103).
+edge(103,133).
+edge(133,103).
+edge(104,113).
+edge(113,104).
+edge(105,111).
+edge(111,105).
+edge(106,119).
+edge(119,106).
+edge(106,128).
+edge(128,106).
+edge(106,131).
+edge(131,106).
+edge(106,132).
+edge(132,106).
+edge(107,109).
+edge(109,107).
+edge(107,125).
+edge(125,107).
+edge(107,132).
+edge(132,107).
+edge(108,111).
+edge(111,108).
+edge(108,133).
+edge(133,108).
+edge(108,135).
+edge(135,108).
+edge(109,125).
+edge(125,109).
+edge(109,134).
+edge(134,109).
+edge(110,124).
+edge(124,110).
+edge(110,131).
+edge(131,110).
+edge(110,133).
+edge(133,110).
+edge(111,121).
+edge(121,111).
+edge(111,130).
+edge(130,111).
+edge(112,117).
+edge(117,112).
+edge(112,122).
+edge(122,112).
+edge(112,125).
+edge(125,112).
+edge(112,129).
+edge(129,112).
+edge(112,130).
+edge(130,112).
+edge(113,129).
+edge(129,113).
+edge(114,120).
+edge(120,114).
+edge(114,132).
+edge(132,114).
+edge(115,122).
+edge(122,115).
+edge(115,124).
+edge(124,115).
+edge(115,132).
+edge(132,115).
+edge(116,125).
+edge(125,116).
+edge(116,134).
+edge(134,116).
+edge(117,130).
+edge(130,117).
+edge(118,129).
+edge(129,118).
+edge(119,120).
+edge(120,119).
+edge(119,127).
+edge(127,119).
+edge(120,130).
+edge(130,120).
+edge(121,122).
+edge(122,121).
+edge(121,130).
+edge(130,121).
+edge(121,134).
+edge(134,121).
+edge(122,128).
+edge(128,122).
+edge(122,133).
+edge(133,122).
+edge(123,128).
+edge(128,123).
+edge(123,131).
+edge(131,123).
+edge(124,126).
+edge(126,124).
+edge(125,131).
+edge(131,125).
+edge(126,130).
+edge(130,126).
+edge(126,135).
+edge(135,126).
+edge(128,130).
+edge(130,128).
+edge(129,130).
+edge(130,129).
+edge(131,133).
+edge(133,131).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0023-graph_colouring-135-0.lp b/examples/clingo/expansion/GraphColouring/instances/0023-graph_colouring-135-0.lp
new file mode 100644
index 0000000..4f822e5
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0023-graph_colouring-135-0.lp
@@ -0,0 +1,1869 @@
+#const n=135.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+edge(1,10).
+edge(10,1).
+edge(1,14).
+edge(14,1).
+edge(1,47).
+edge(47,1).
+edge(1,62).
+edge(62,1).
+edge(1,67).
+edge(67,1).
+edge(1,80).
+edge(80,1).
+edge(1,82).
+edge(82,1).
+edge(1,91).
+edge(91,1).
+edge(1,99).
+edge(99,1).
+edge(1,102).
+edge(102,1).
+edge(1,117).
+edge(117,1).
+edge(2,5).
+edge(5,2).
+edge(2,7).
+edge(7,2).
+edge(2,18).
+edge(18,2).
+edge(2,38).
+edge(38,2).
+edge(2,73).
+edge(73,2).
+edge(2,85).
+edge(85,2).
+edge(2,102).
+edge(102,2).
+edge(2,103).
+edge(103,2).
+edge(2,106).
+edge(106,2).
+edge(2,109).
+edge(109,2).
+edge(2,124).
+edge(124,2).
+edge(3,21).
+edge(21,3).
+edge(3,27).
+edge(27,3).
+edge(3,33).
+edge(33,3).
+edge(3,44).
+edge(44,3).
+edge(3,50).
+edge(50,3).
+edge(3,58).
+edge(58,3).
+edge(3,63).
+edge(63,3).
+edge(3,67).
+edge(67,3).
+edge(3,72).
+edge(72,3).
+edge(3,73).
+edge(73,3).
+edge(3,89).
+edge(89,3).
+edge(3,93).
+edge(93,3).
+edge(3,99).
+edge(99,3).
+edge(3,106).
+edge(106,3).
+edge(3,113).
+edge(113,3).
+edge(4,22).
+edge(22,4).
+edge(4,47).
+edge(47,4).
+edge(4,51).
+edge(51,4).
+edge(4,56).
+edge(56,4).
+edge(4,70).
+edge(70,4).
+edge(4,80).
+edge(80,4).
+edge(4,83).
+edge(83,4).
+edge(4,85).
+edge(85,4).
+edge(4,93).
+edge(93,4).
+edge(4,119).
+edge(119,4).
+edge(4,123).
+edge(123,4).
+edge(5,19).
+edge(19,5).
+edge(5,24).
+edge(24,5).
+edge(5,34).
+edge(34,5).
+edge(5,35).
+edge(35,5).
+edge(5,57).
+edge(57,5).
+edge(5,101).
+edge(101,5).
+edge(5,117).
+edge(117,5).
+edge(5,133).
+edge(133,5).
+edge(6,43).
+edge(43,6).
+edge(6,63).
+edge(63,6).
+edge(6,65).
+edge(65,6).
+edge(6,75).
+edge(75,6).
+edge(6,90).
+edge(90,6).
+edge(6,91).
+edge(91,6).
+edge(6,96).
+edge(96,6).
+edge(6,98).
+edge(98,6).
+edge(6,99).
+edge(99,6).
+edge(6,109).
+edge(109,6).
+edge(6,119).
+edge(119,6).
+edge(6,129).
+edge(129,6).
+edge(7,12).
+edge(12,7).
+edge(7,17).
+edge(17,7).
+edge(7,19).
+edge(19,7).
+edge(7,26).
+edge(26,7).
+edge(7,34).
+edge(34,7).
+edge(7,46).
+edge(46,7).
+edge(7,61).
+edge(61,7).
+edge(7,67).
+edge(67,7).
+edge(7,74).
+edge(74,7).
+edge(7,79).
+edge(79,7).
+edge(7,84).
+edge(84,7).
+edge(7,103).
+edge(103,7).
+edge(7,105).
+edge(105,7).
+edge(8,9).
+edge(9,8).
+edge(8,23).
+edge(23,8).
+edge(8,42).
+edge(42,8).
+edge(8,47).
+edge(47,8).
+edge(8,48).
+edge(48,8).
+edge(8,51).
+edge(51,8).
+edge(8,55).
+edge(55,8).
+edge(8,66).
+edge(66,8).
+edge(8,84).
+edge(84,8).
+edge(8,85).
+edge(85,8).
+edge(8,104).
+edge(104,8).
+edge(8,106).
+edge(106,8).
+edge(8,118).
+edge(118,8).
+edge(8,122).
+edge(122,8).
+edge(8,131).
+edge(131,8).
+edge(9,21).
+edge(21,9).
+edge(9,30).
+edge(30,9).
+edge(9,31).
+edge(31,9).
+edge(9,40).
+edge(40,9).
+edge(9,62).
+edge(62,9).
+edge(9,66).
+edge(66,9).
+edge(9,67).
+edge(67,9).
+edge(9,69).
+edge(69,9).
+edge(9,97).
+edge(97,9).
+edge(9,105).
+edge(105,9).
+edge(9,106).
+edge(106,9).
+edge(9,108).
+edge(108,9).
+edge(9,116).
+edge(116,9).
+edge(9,117).
+edge(117,9).
+edge(9,120).
+edge(120,9).
+edge(9,128).
+edge(128,9).
+edge(10,33).
+edge(33,10).
+edge(10,40).
+edge(40,10).
+edge(10,53).
+edge(53,10).
+edge(10,55).
+edge(55,10).
+edge(10,58).
+edge(58,10).
+edge(10,78).
+edge(78,10).
+edge(10,111).
+edge(111,10).
+edge(10,119).
+edge(119,10).
+edge(10,120).
+edge(120,10).
+edge(10,130).
+edge(130,10).
+edge(10,131).
+edge(131,10).
+edge(10,132).
+edge(132,10).
+edge(11,15).
+edge(15,11).
+edge(11,18).
+edge(18,11).
+edge(11,20).
+edge(20,11).
+edge(11,26).
+edge(26,11).
+edge(11,33).
+edge(33,11).
+edge(11,34).
+edge(34,11).
+edge(11,35).
+edge(35,11).
+edge(11,38).
+edge(38,11).
+edge(11,45).
+edge(45,11).
+edge(11,55).
+edge(55,11).
+edge(11,97).
+edge(97,11).
+edge(11,117).
+edge(117,11).
+edge(11,130).
+edge(130,11).
+edge(12,13).
+edge(13,12).
+edge(12,14).
+edge(14,12).
+edge(12,17).
+edge(17,12).
+edge(12,25).
+edge(25,12).
+edge(12,48).
+edge(48,12).
+edge(12,66).
+edge(66,12).
+edge(12,72).
+edge(72,12).
+edge(12,89).
+edge(89,12).
+edge(12,107).
+edge(107,12).
+edge(12,108).
+edge(108,12).
+edge(12,120).
+edge(120,12).
+edge(12,127).
+edge(127,12).
+edge(12,132).
+edge(132,12).
+edge(13,18).
+edge(18,13).
+edge(13,20).
+edge(20,13).
+edge(13,41).
+edge(41,13).
+edge(13,48).
+edge(48,13).
+edge(13,51).
+edge(51,13).
+edge(13,60).
+edge(60,13).
+edge(13,68).
+edge(68,13).
+edge(13,74).
+edge(74,13).
+edge(13,78).
+edge(78,13).
+edge(13,94).
+edge(94,13).
+edge(13,126).
+edge(126,13).
+edge(13,129).
+edge(129,13).
+edge(14,23).
+edge(23,14).
+edge(14,24).
+edge(24,14).
+edge(14,27).
+edge(27,14).
+edge(14,57).
+edge(57,14).
+edge(14,59).
+edge(59,14).
+edge(14,60).
+edge(60,14).
+edge(14,73).
+edge(73,14).
+edge(14,116).
+edge(116,14).
+edge(14,120).
+edge(120,14).
+edge(14,121).
+edge(121,14).
+edge(15,21).
+edge(21,15).
+edge(15,25).
+edge(25,15).
+edge(15,34).
+edge(34,15).
+edge(15,39).
+edge(39,15).
+edge(15,42).
+edge(42,15).
+edge(15,54).
+edge(54,15).
+edge(15,76).
+edge(76,15).
+edge(15,90).
+edge(90,15).
+edge(15,94).
+edge(94,15).
+edge(15,109).
+edge(109,15).
+edge(15,111).
+edge(111,15).
+edge(15,115).
+edge(115,15).
+edge(15,123).
+edge(123,15).
+edge(16,41).
+edge(41,16).
+edge(16,49).
+edge(49,16).
+edge(16,51).
+edge(51,16).
+edge(16,59).
+edge(59,16).
+edge(16,60).
+edge(60,16).
+edge(16,75).
+edge(75,16).
+edge(16,95).
+edge(95,16).
+edge(16,96).
+edge(96,16).
+edge(16,107).
+edge(107,16).
+edge(16,109).
+edge(109,16).
+edge(16,111).
+edge(111,16).
+edge(16,120).
+edge(120,16).
+edge(16,122).
+edge(122,16).
+edge(17,34).
+edge(34,17).
+edge(17,40).
+edge(40,17).
+edge(17,60).
+edge(60,17).
+edge(17,77).
+edge(77,17).
+edge(17,79).
+edge(79,17).
+edge(17,117).
+edge(117,17).
+edge(18,20).
+edge(20,18).
+edge(18,21).
+edge(21,18).
+edge(18,35).
+edge(35,18).
+edge(18,44).
+edge(44,18).
+edge(18,48).
+edge(48,18).
+edge(18,52).
+edge(52,18).
+edge(18,61).
+edge(61,18).
+edge(18,72).
+edge(72,18).
+edge(18,76).
+edge(76,18).
+edge(18,80).
+edge(80,18).
+edge(18,99).
+edge(99,18).
+edge(18,100).
+edge(100,18).
+edge(18,106).
+edge(106,18).
+edge(18,110).
+edge(110,18).
+edge(18,116).
+edge(116,18).
+edge(18,120).
+edge(120,18).
+edge(18,135).
+edge(135,18).
+edge(19,21).
+edge(21,19).
+edge(19,24).
+edge(24,19).
+edge(19,26).
+edge(26,19).
+edge(19,31).
+edge(31,19).
+edge(19,40).
+edge(40,19).
+edge(19,41).
+edge(41,19).
+edge(19,42).
+edge(42,19).
+edge(19,54).
+edge(54,19).
+edge(19,84).
+edge(84,19).
+edge(19,89).
+edge(89,19).
+edge(19,119).
+edge(119,19).
+edge(19,125).
+edge(125,19).
+edge(19,130).
+edge(130,19).
+edge(19,133).
+edge(133,19).
+edge(20,42).
+edge(42,20).
+edge(20,70).
+edge(70,20).
+edge(20,72).
+edge(72,20).
+edge(20,85).
+edge(85,20).
+edge(20,108).
+edge(108,20).
+edge(20,116).
+edge(116,20).
+edge(20,118).
+edge(118,20).
+edge(20,133).
+edge(133,20).
+edge(21,34).
+edge(34,21).
+edge(21,105).
+edge(105,21).
+edge(21,110).
+edge(110,21).
+edge(21,122).
+edge(122,21).
+edge(21,123).
+edge(123,21).
+edge(22,57).
+edge(57,22).
+edge(22,61).
+edge(61,22).
+edge(22,64).
+edge(64,22).
+edge(22,65).
+edge(65,22).
+edge(22,67).
+edge(67,22).
+edge(22,82).
+edge(82,22).
+edge(22,83).
+edge(83,22).
+edge(22,92).
+edge(92,22).
+edge(22,109).
+edge(109,22).
+edge(22,123).
+edge(123,22).
+edge(22,130).
+edge(130,22).
+edge(22,133).
+edge(133,22).
+edge(23,29).
+edge(29,23).
+edge(23,31).
+edge(31,23).
+edge(23,32).
+edge(32,23).
+edge(23,35).
+edge(35,23).
+edge(23,37).
+edge(37,23).
+edge(23,48).
+edge(48,23).
+edge(23,50).
+edge(50,23).
+edge(23,60).
+edge(60,23).
+edge(23,82).
+edge(82,23).
+edge(23,92).
+edge(92,23).
+edge(23,104).
+edge(104,23).
+edge(23,111).
+edge(111,23).
+edge(24,29).
+edge(29,24).
+edge(24,33).
+edge(33,24).
+edge(24,46).
+edge(46,24).
+edge(24,55).
+edge(55,24).
+edge(24,74).
+edge(74,24).
+edge(24,80).
+edge(80,24).
+edge(24,84).
+edge(84,24).
+edge(24,85).
+edge(85,24).
+edge(24,90).
+edge(90,24).
+edge(24,92).
+edge(92,24).
+edge(24,111).
+edge(111,24).
+edge(24,126).
+edge(126,24).
+edge(25,61).
+edge(61,25).
+edge(25,71).
+edge(71,25).
+edge(25,80).
+edge(80,25).
+edge(25,82).
+edge(82,25).
+edge(25,83).
+edge(83,25).
+edge(25,85).
+edge(85,25).
+edge(25,91).
+edge(91,25).
+edge(25,112).
+edge(112,25).
+edge(25,113).
+edge(113,25).
+edge(25,119).
+edge(119,25).
+edge(25,122).
+edge(122,25).
+edge(25,123).
+edge(123,25).
+edge(25,130).
+edge(130,25).
+edge(25,133).
+edge(133,25).
+edge(26,33).
+edge(33,26).
+edge(26,34).
+edge(34,26).
+edge(26,41).
+edge(41,26).
+edge(26,68).
+edge(68,26).
+edge(26,88).
+edge(88,26).
+edge(26,111).
+edge(111,26).
+edge(26,118).
+edge(118,26).
+edge(26,125).
+edge(125,26).
+edge(27,31).
+edge(31,27).
+edge(27,51).
+edge(51,27).
+edge(27,54).
+edge(54,27).
+edge(27,68).
+edge(68,27).
+edge(27,72).
+edge(72,27).
+edge(27,79).
+edge(79,27).
+edge(27,82).
+edge(82,27).
+edge(27,93).
+edge(93,27).
+edge(27,95).
+edge(95,27).
+edge(27,98).
+edge(98,27).
+edge(27,103).
+edge(103,27).
+edge(27,105).
+edge(105,27).
+edge(27,116).
+edge(116,27).
+edge(28,48).
+edge(48,28).
+edge(28,62).
+edge(62,28).
+edge(28,79).
+edge(79,28).
+edge(28,92).
+edge(92,28).
+edge(28,106).
+edge(106,28).
+edge(28,108).
+edge(108,28).
+edge(28,124).
+edge(124,28).
+edge(28,130).
+edge(130,28).
+edge(29,32).
+edge(32,29).
+edge(29,33).
+edge(33,29).
+edge(29,36).
+edge(36,29).
+edge(29,44).
+edge(44,29).
+edge(29,45).
+edge(45,29).
+edge(29,54).
+edge(54,29).
+edge(29,65).
+edge(65,29).
+edge(29,82).
+edge(82,29).
+edge(29,93).
+edge(93,29).
+edge(29,105).
+edge(105,29).
+edge(29,128).
+edge(128,29).
+edge(29,133).
+edge(133,29).
+edge(30,37).
+edge(37,30).
+edge(30,38).
+edge(38,30).
+edge(30,42).
+edge(42,30).
+edge(30,47).
+edge(47,30).
+edge(30,57).
+edge(57,30).
+edge(30,58).
+edge(58,30).
+edge(30,72).
+edge(72,30).
+edge(30,79).
+edge(79,30).
+edge(31,41).
+edge(41,31).
+edge(31,53).
+edge(53,31).
+edge(31,69).
+edge(69,31).
+edge(31,73).
+edge(73,31).
+edge(31,84).
+edge(84,31).
+edge(31,97).
+edge(97,31).
+edge(31,98).
+edge(98,31).
+edge(31,110).
+edge(110,31).
+edge(32,34).
+edge(34,32).
+edge(32,61).
+edge(61,32).
+edge(32,88).
+edge(88,32).
+edge(32,99).
+edge(99,32).
+edge(32,104).
+edge(104,32).
+edge(32,122).
+edge(122,32).
+edge(33,35).
+edge(35,33).
+edge(33,39).
+edge(39,33).
+edge(33,48).
+edge(48,33).
+edge(33,64).
+edge(64,33).
+edge(33,74).
+edge(74,33).
+edge(33,97).
+edge(97,33).
+edge(33,100).
+edge(100,33).
+edge(33,103).
+edge(103,33).
+edge(33,107).
+edge(107,33).
+edge(33,115).
+edge(115,33).
+edge(33,132).
+edge(132,33).
+edge(34,41).
+edge(41,34).
+edge(34,50).
+edge(50,34).
+edge(34,98).
+edge(98,34).
+edge(34,104).
+edge(104,34).
+edge(34,107).
+edge(107,34).
+edge(34,129).
+edge(129,34).
+edge(35,43).
+edge(43,35).
+edge(35,68).
+edge(68,35).
+edge(35,101).
+edge(101,35).
+edge(35,102).
+edge(102,35).
+edge(35,107).
+edge(107,35).
+edge(35,113).
+edge(113,35).
+edge(35,126).
+edge(126,35).
+edge(36,42).
+edge(42,36).
+edge(36,45).
+edge(45,36).
+edge(36,46).
+edge(46,36).
+edge(36,50).
+edge(50,36).
+edge(36,74).
+edge(74,36).
+edge(36,78).
+edge(78,36).
+edge(36,80).
+edge(80,36).
+edge(36,87).
+edge(87,36).
+edge(36,91).
+edge(91,36).
+edge(36,92).
+edge(92,36).
+edge(36,103).
+edge(103,36).
+edge(36,105).
+edge(105,36).
+edge(36,113).
+edge(113,36).
+edge(36,115).
+edge(115,36).
+edge(36,117).
+edge(117,36).
+edge(36,122).
+edge(122,36).
+edge(36,123).
+edge(123,36).
+edge(36,126).
+edge(126,36).
+edge(36,129).
+edge(129,36).
+edge(37,42).
+edge(42,37).
+edge(37,44).
+edge(44,37).
+edge(37,45).
+edge(45,37).
+edge(37,46).
+edge(46,37).
+edge(37,65).
+edge(65,37).
+edge(37,82).
+edge(82,37).
+edge(37,92).
+edge(92,37).
+edge(37,123).
+edge(123,37).
+edge(37,132).
+edge(132,37).
+edge(37,133).
+edge(133,37).
+edge(38,44).
+edge(44,38).
+edge(38,50).
+edge(50,38).
+edge(38,52).
+edge(52,38).
+edge(38,54).
+edge(54,38).
+edge(38,73).
+edge(73,38).
+edge(38,75).
+edge(75,38).
+edge(38,84).
+edge(84,38).
+edge(38,94).
+edge(94,38).
+edge(38,135).
+edge(135,38).
+edge(39,47).
+edge(47,39).
+edge(39,48).
+edge(48,39).
+edge(39,65).
+edge(65,39).
+edge(39,79).
+edge(79,39).
+edge(39,86).
+edge(86,39).
+edge(39,93).
+edge(93,39).
+edge(39,101).
+edge(101,39).
+edge(39,109).
+edge(109,39).
+edge(39,115).
+edge(115,39).
+edge(39,116).
+edge(116,39).
+edge(39,129).
+edge(129,39).
+edge(40,41).
+edge(41,40).
+edge(40,42).
+edge(42,40).
+edge(40,54).
+edge(54,40).
+edge(40,58).
+edge(58,40).
+edge(40,60).
+edge(60,40).
+edge(40,66).
+edge(66,40).
+edge(40,68).
+edge(68,40).
+edge(40,72).
+edge(72,40).
+edge(40,75).
+edge(75,40).
+edge(40,77).
+edge(77,40).
+edge(40,94).
+edge(94,40).
+edge(40,102).
+edge(102,40).
+edge(40,107).
+edge(107,40).
+edge(40,127).
+edge(127,40).
+edge(41,48).
+edge(48,41).
+edge(41,49).
+edge(49,41).
+edge(41,51).
+edge(51,41).
+edge(41,75).
+edge(75,41).
+edge(41,83).
+edge(83,41).
+edge(41,96).
+edge(96,41).
+edge(41,99).
+edge(99,41).
+edge(41,118).
+edge(118,41).
+edge(42,46).
+edge(46,42).
+edge(42,48).
+edge(48,42).
+edge(42,63).
+edge(63,42).
+edge(42,70).
+edge(70,42).
+edge(42,88).
+edge(88,42).
+edge(42,100).
+edge(100,42).
+edge(42,103).
+edge(103,42).
+edge(42,106).
+edge(106,42).
+edge(42,118).
+edge(118,42).
+edge(42,119).
+edge(119,42).
+edge(42,131).
+edge(131,42).
+edge(43,48).
+edge(48,43).
+edge(43,51).
+edge(51,43).
+edge(43,78).
+edge(78,43).
+edge(43,87).
+edge(87,43).
+edge(43,92).
+edge(92,43).
+edge(43,109).
+edge(109,43).
+edge(43,111).
+edge(111,43).
+edge(43,126).
+edge(126,43).
+edge(43,127).
+edge(127,43).
+edge(44,59).
+edge(59,44).
+edge(44,89).
+edge(89,44).
+edge(44,116).
+edge(116,44).
+edge(44,121).
+edge(121,44).
+edge(44,130).
+edge(130,44).
+edge(45,47).
+edge(47,45).
+edge(45,49).
+edge(49,45).
+edge(45,53).
+edge(53,45).
+edge(45,56).
+edge(56,45).
+edge(45,67).
+edge(67,45).
+edge(45,86).
+edge(86,45).
+edge(45,90).
+edge(90,45).
+edge(45,95).
+edge(95,45).
+edge(45,103).
+edge(103,45).
+edge(45,104).
+edge(104,45).
+edge(46,55).
+edge(55,46).
+edge(46,58).
+edge(58,46).
+edge(46,63).
+edge(63,46).
+edge(46,78).
+edge(78,46).
+edge(46,83).
+edge(83,46).
+edge(46,85).
+edge(85,46).
+edge(46,117).
+edge(117,46).
+edge(46,121).
+edge(121,46).
+edge(46,124).
+edge(124,46).
+edge(47,48).
+edge(48,47).
+edge(47,51).
+edge(51,47).
+edge(47,58).
+edge(58,47).
+edge(47,69).
+edge(69,47).
+edge(47,79).
+edge(79,47).
+edge(47,82).
+edge(82,47).
+edge(47,83).
+edge(83,47).
+edge(47,86).
+edge(86,47).
+edge(47,99).
+edge(99,47).
+edge(47,100).
+edge(100,47).
+edge(47,110).
+edge(110,47).
+edge(48,58).
+edge(58,48).
+edge(48,77).
+edge(77,48).
+edge(48,87).
+edge(87,48).
+edge(48,89).
+edge(89,48).
+edge(48,92).
+edge(92,48).
+edge(48,104).
+edge(104,48).
+edge(49,52).
+edge(52,49).
+edge(49,55).
+edge(55,49).
+edge(49,64).
+edge(64,49).
+edge(49,68).
+edge(68,49).
+edge(49,76).
+edge(76,49).
+edge(49,94).
+edge(94,49).
+edge(49,99).
+edge(99,49).
+edge(49,106).
+edge(106,49).
+edge(49,107).
+edge(107,49).
+edge(49,114).
+edge(114,49).
+edge(49,118).
+edge(118,49).
+edge(50,55).
+edge(55,50).
+edge(50,86).
+edge(86,50).
+edge(50,92).
+edge(92,50).
+edge(50,101).
+edge(101,50).
+edge(50,108).
+edge(108,50).
+edge(50,113).
+edge(113,50).
+edge(50,127).
+edge(127,50).
+edge(50,128).
+edge(128,50).
+edge(51,65).
+edge(65,51).
+edge(51,66).
+edge(66,51).
+edge(51,69).
+edge(69,51).
+edge(51,82).
+edge(82,51).
+edge(51,114).
+edge(114,51).
+edge(51,123).
+edge(123,51).
+edge(52,59).
+edge(59,52).
+edge(52,76).
+edge(76,52).
+edge(52,79).
+edge(79,52).
+edge(52,94).
+edge(94,52).
+edge(52,105).
+edge(105,52).
+edge(52,110).
+edge(110,52).
+edge(52,113).
+edge(113,52).
+edge(52,116).
+edge(116,52).
+edge(52,131).
+edge(131,52).
+edge(53,61).
+edge(61,53).
+edge(53,69).
+edge(69,53).
+edge(53,91).
+edge(91,53).
+edge(53,122).
+edge(122,53).
+edge(54,72).
+edge(72,54).
+edge(54,76).
+edge(76,54).
+edge(54,83).
+edge(83,54).
+edge(54,87).
+edge(87,54).
+edge(54,89).
+edge(89,54).
+edge(54,94).
+edge(94,54).
+edge(54,101).
+edge(101,54).
+edge(54,104).
+edge(104,54).
+edge(54,108).
+edge(108,54).
+edge(54,116).
+edge(116,54).
+edge(54,120).
+edge(120,54).
+edge(55,66).
+edge(66,55).
+edge(55,67).
+edge(67,55).
+edge(55,77).
+edge(77,55).
+edge(55,98).
+edge(98,55).
+edge(55,101).
+edge(101,55).
+edge(55,106).
+edge(106,55).
+edge(55,115).
+edge(115,55).
+edge(55,129).
+edge(129,55).
+edge(55,131).
+edge(131,55).
+edge(56,58).
+edge(58,56).
+edge(56,59).
+edge(59,56).
+edge(56,60).
+edge(60,56).
+edge(56,61).
+edge(61,56).
+edge(56,66).
+edge(66,56).
+edge(56,68).
+edge(68,56).
+edge(56,74).
+edge(74,56).
+edge(56,102).
+edge(102,56).
+edge(56,105).
+edge(105,56).
+edge(56,124).
+edge(124,56).
+edge(57,63).
+edge(63,57).
+edge(57,80).
+edge(80,57).
+edge(57,98).
+edge(98,57).
+edge(57,120).
+edge(120,57).
+edge(57,125).
+edge(125,57).
+edge(57,130).
+edge(130,57).
+edge(58,66).
+edge(66,58).
+edge(58,73).
+edge(73,58).
+edge(58,80).
+edge(80,58).
+edge(58,88).
+edge(88,58).
+edge(58,94).
+edge(94,58).
+edge(58,117).
+edge(117,58).
+edge(58,135).
+edge(135,58).
+edge(59,71).
+edge(71,59).
+edge(59,73).
+edge(73,59).
+edge(59,83).
+edge(83,59).
+edge(59,104).
+edge(104,59).
+edge(59,107).
+edge(107,59).
+edge(59,117).
+edge(117,59).
+edge(59,134).
+edge(134,59).
+edge(60,62).
+edge(62,60).
+edge(60,64).
+edge(64,60).
+edge(60,85).
+edge(85,60).
+edge(60,88).
+edge(88,60).
+edge(60,91).
+edge(91,60).
+edge(60,111).
+edge(111,60).
+edge(60,112).
+edge(112,60).
+edge(60,117).
+edge(117,60).
+edge(61,65).
+edge(65,61).
+edge(61,86).
+edge(86,61).
+edge(61,87).
+edge(87,61).
+edge(61,88).
+edge(88,61).
+edge(61,90).
+edge(90,61).
+edge(61,93).
+edge(93,61).
+edge(61,101).
+edge(101,61).
+edge(61,117).
+edge(117,61).
+edge(61,126).
+edge(126,61).
+edge(61,135).
+edge(135,61).
+edge(62,65).
+edge(65,62).
+edge(62,68).
+edge(68,62).
+edge(62,73).
+edge(73,62).
+edge(62,77).
+edge(77,62).
+edge(62,88).
+edge(88,62).
+edge(62,93).
+edge(93,62).
+edge(62,116).
+edge(116,62).
+edge(63,65).
+edge(65,63).
+edge(63,70).
+edge(70,63).
+edge(63,73).
+edge(73,63).
+edge(63,108).
+edge(108,63).
+edge(63,113).
+edge(113,63).
+edge(63,125).
+edge(125,63).
+edge(64,86).
+edge(86,64).
+edge(64,90).
+edge(90,64).
+edge(64,122).
+edge(122,64).
+edge(64,124).
+edge(124,64).
+edge(64,127).
+edge(127,64).
+edge(65,77).
+edge(77,65).
+edge(65,86).
+edge(86,65).
+edge(65,100).
+edge(100,65).
+edge(65,103).
+edge(103,65).
+edge(65,111).
+edge(111,65).
+edge(65,117).
+edge(117,65).
+edge(65,121).
+edge(121,65).
+edge(65,132).
+edge(132,65).
+edge(66,67).
+edge(67,66).
+edge(66,95).
+edge(95,66).
+edge(66,98).
+edge(98,66).
+edge(66,104).
+edge(104,66).
+edge(66,107).
+edge(107,66).
+edge(66,129).
+edge(129,66).
+edge(66,132).
+edge(132,66).
+edge(67,70).
+edge(70,67).
+edge(67,79).
+edge(79,67).
+edge(67,86).
+edge(86,67).
+edge(67,131).
+edge(131,67).
+edge(68,82).
+edge(82,68).
+edge(68,88).
+edge(88,68).
+edge(68,99).
+edge(99,68).
+edge(68,100).
+edge(100,68).
+edge(68,107).
+edge(107,68).
+edge(69,87).
+edge(87,69).
+edge(69,90).
+edge(90,69).
+edge(69,99).
+edge(99,69).
+edge(69,101).
+edge(101,69).
+edge(69,106).
+edge(106,69).
+edge(69,116).
+edge(116,69).
+edge(69,120).
+edge(120,69).
+edge(69,122).
+edge(122,69).
+edge(69,130).
+edge(130,69).
+edge(69,132).
+edge(132,69).
+edge(70,71).
+edge(71,70).
+edge(70,76).
+edge(76,70).
+edge(70,79).
+edge(79,70).
+edge(70,92).
+edge(92,70).
+edge(70,110).
+edge(110,70).
+edge(70,111).
+edge(111,70).
+edge(70,116).
+edge(116,70).
+edge(70,124).
+edge(124,70).
+edge(70,127).
+edge(127,70).
+edge(70,132).
+edge(132,70).
+edge(71,72).
+edge(72,71).
+edge(71,83).
+edge(83,71).
+edge(71,86).
+edge(86,71).
+edge(71,105).
+edge(105,71).
+edge(71,112).
+edge(112,71).
+edge(71,123).
+edge(123,71).
+edge(71,130).
+edge(130,71).
+edge(72,74).
+edge(74,72).
+edge(72,102).
+edge(102,72).
+edge(72,113).
+edge(113,72).
+edge(72,123).
+edge(123,72).
+edge(72,135).
+edge(135,72).
+edge(73,89).
+edge(89,73).
+edge(73,111).
+edge(111,73).
+edge(73,112).
+edge(112,73).
+edge(73,114).
+edge(114,73).
+edge(74,85).
+edge(85,74).
+edge(74,91).
+edge(91,74).
+edge(74,99).
+edge(99,74).
+edge(74,100).
+edge(100,74).
+edge(74,115).
+edge(115,74).
+edge(75,76).
+edge(76,75).
+edge(75,82).
+edge(82,75).
+edge(75,89).
+edge(89,75).
+edge(75,92).
+edge(92,75).
+edge(75,96).
+edge(96,75).
+edge(75,97).
+edge(97,75).
+edge(75,99).
+edge(99,75).
+edge(75,101).
+edge(101,75).
+edge(75,105).
+edge(105,75).
+edge(75,113).
+edge(113,75).
+edge(75,117).
+edge(117,75).
+edge(75,127).
+edge(127,75).
+edge(76,84).
+edge(84,76).
+edge(76,99).
+edge(99,76).
+edge(76,106).
+edge(106,76).
+edge(76,111).
+edge(111,76).
+edge(76,113).
+edge(113,76).
+edge(76,121).
+edge(121,76).
+edge(77,117).
+edge(117,77).
+edge(77,131).
+edge(131,77).
+edge(78,89).
+edge(89,78).
+edge(78,94).
+edge(94,78).
+edge(78,113).
+edge(113,78).
+edge(78,118).
+edge(118,78).
+edge(79,80).
+edge(80,79).
+edge(79,86).
+edge(86,79).
+edge(79,89).
+edge(89,79).
+edge(79,99).
+edge(99,79).
+edge(79,101).
+edge(101,79).
+edge(79,120).
+edge(120,79).
+edge(79,121).
+edge(121,79).
+edge(79,125).
+edge(125,79).
+edge(80,87).
+edge(87,80).
+edge(80,91).
+edge(91,80).
+edge(80,116).
+edge(116,80).
+edge(80,126).
+edge(126,80).
+edge(80,127).
+edge(127,80).
+edge(80,130).
+edge(130,80).
+edge(81,96).
+edge(96,81).
+edge(81,99).
+edge(99,81).
+edge(81,101).
+edge(101,81).
+edge(81,133).
+edge(133,81).
+edge(82,112).
+edge(112,82).
+edge(82,124).
+edge(124,82).
+edge(83,108).
+edge(108,83).
+edge(83,114).
+edge(114,83).
+edge(83,125).
+edge(125,83).
+edge(83,130).
+edge(130,83).
+edge(84,105).
+edge(105,84).
+edge(84,107).
+edge(107,84).
+edge(84,128).
+edge(128,84).
+edge(85,88).
+edge(88,85).
+edge(85,95).
+edge(95,85).
+edge(85,98).
+edge(98,85).
+edge(85,113).
+edge(113,85).
+edge(85,115).
+edge(115,85).
+edge(85,116).
+edge(116,85).
+edge(85,127).
+edge(127,85).
+edge(85,132).
+edge(132,85).
+edge(86,103).
+edge(103,86).
+edge(86,106).
+edge(106,86).
+edge(86,118).
+edge(118,86).
+edge(86,125).
+edge(125,86).
+edge(86,130).
+edge(130,86).
+edge(87,99).
+edge(99,87).
+edge(87,101).
+edge(101,87).
+edge(87,116).
+edge(116,87).
+edge(87,119).
+edge(119,87).
+edge(87,124).
+edge(124,87).
+edge(87,128).
+edge(128,87).
+edge(87,131).
+edge(131,87).
+edge(88,106).
+edge(106,88).
+edge(88,113).
+edge(113,88).
+edge(88,119).
+edge(119,88).
+edge(89,98).
+edge(98,89).
+edge(89,111).
+edge(111,89).
+edge(89,113).
+edge(113,89).
+edge(89,129).
+edge(129,89).
+edge(90,120).
+edge(120,90).
+edge(90,121).
+edge(121,90).
+edge(90,131).
+edge(131,90).
+edge(90,134).
+edge(134,90).
+edge(91,97).
+edge(97,91).
+edge(91,107).
+edge(107,91).
+edge(91,110).
+edge(110,91).
+edge(91,111).
+edge(111,91).
+edge(91,114).
+edge(114,91).
+edge(91,121).
+edge(121,91).
+edge(91,135).
+edge(135,91).
+edge(92,114).
+edge(114,92).
+edge(93,105).
+edge(105,93).
+edge(93,107).
+edge(107,93).
+edge(93,113).
+edge(113,93).
+edge(93,122).
+edge(122,93).
+edge(93,129).
+edge(129,93).
+edge(94,100).
+edge(100,94).
+edge(94,108).
+edge(108,94).
+edge(94,117).
+edge(117,94).
+edge(94,124).
+edge(124,94).
+edge(95,99).
+edge(99,95).
+edge(95,127).
+edge(127,95).
+edge(96,104).
+edge(104,96).
+edge(97,104).
+edge(104,97).
+edge(97,110).
+edge(110,97).
+edge(98,100).
+edge(100,98).
+edge(98,122).
+edge(122,98).
+edge(98,124).
+edge(124,98).
+edge(99,125).
+edge(125,99).
+edge(99,126).
+edge(126,99).
+edge(101,110).
+edge(110,101).
+edge(101,113).
+edge(113,101).
+edge(101,131).
+edge(131,101).
+edge(101,134).
+edge(134,101).
+edge(102,104).
+edge(104,102).
+edge(102,116).
+edge(116,102).
+edge(102,123).
+edge(123,102).
+edge(103,116).
+edge(116,103).
+edge(104,114).
+edge(114,104).
+edge(104,117).
+edge(117,104).
+edge(104,119).
+edge(119,104).
+edge(104,122).
+edge(122,104).
+edge(105,107).
+edge(107,105).
+edge(105,119).
+edge(119,105).
+edge(106,108).
+edge(108,106).
+edge(106,109).
+edge(109,106).
+edge(107,122).
+edge(122,107).
+edge(107,123).
+edge(123,107).
+edge(107,128).
+edge(128,107).
+edge(108,112).
+edge(112,108).
+edge(108,114).
+edge(114,108).
+edge(108,115).
+edge(115,108).
+edge(108,117).
+edge(117,108).
+edge(108,118).
+edge(118,108).
+edge(109,110).
+edge(110,109).
+edge(109,119).
+edge(119,109).
+edge(109,122).
+edge(122,109).
+edge(109,123).
+edge(123,109).
+edge(111,112).
+edge(112,111).
+edge(111,124).
+edge(124,111).
+edge(112,115).
+edge(115,112).
+edge(112,128).
+edge(128,112).
+edge(113,117).
+edge(117,113).
+edge(113,130).
+edge(130,113).
+edge(114,124).
+edge(124,114).
+edge(114,130).
+edge(130,114).
+edge(115,121).
+edge(121,115).
+edge(117,131).
+edge(131,117).
+edge(117,134).
+edge(134,117).
+edge(118,134).
+edge(134,118).
+edge(119,135).
+edge(135,119).
+edge(120,123).
+edge(123,120).
+edge(120,128).
+edge(128,120).
+edge(122,123).
+edge(123,122).
+edge(122,127).
+edge(127,122).
+edge(123,125).
+edge(125,123).
+edge(123,129).
+edge(129,123).
+edge(126,133).
+edge(133,126).
+edge(127,132).
+edge(132,127).
+edge(128,135).
+edge(135,128).
+edge(129,134).
+edge(134,129).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0025-graph_colouring-135-0.lp b/examples/clingo/expansion/GraphColouring/instances/0025-graph_colouring-135-0.lp
new file mode 100644
index 0000000..77061f3
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0025-graph_colouring-135-0.lp
@@ -0,0 +1,1995 @@
+#const n=135.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+edge(1,4).
+edge(4,1).
+edge(1,44).
+edge(44,1).
+edge(1,45).
+edge(45,1).
+edge(1,46).
+edge(46,1).
+edge(1,57).
+edge(57,1).
+edge(1,60).
+edge(60,1).
+edge(1,65).
+edge(65,1).
+edge(1,76).
+edge(76,1).
+edge(1,106).
+edge(106,1).
+edge(1,109).
+edge(109,1).
+edge(1,110).
+edge(110,1).
+edge(1,114).
+edge(114,1).
+edge(1,135).
+edge(135,1).
+edge(2,12).
+edge(12,2).
+edge(2,34).
+edge(34,2).
+edge(2,36).
+edge(36,2).
+edge(2,48).
+edge(48,2).
+edge(2,63).
+edge(63,2).
+edge(2,101).
+edge(101,2).
+edge(2,109).
+edge(109,2).
+edge(2,120).
+edge(120,2).
+edge(2,135).
+edge(135,2).
+edge(3,29).
+edge(29,3).
+edge(3,35).
+edge(35,3).
+edge(3,38).
+edge(38,3).
+edge(3,42).
+edge(42,3).
+edge(3,45).
+edge(45,3).
+edge(3,47).
+edge(47,3).
+edge(3,53).
+edge(53,3).
+edge(3,63).
+edge(63,3).
+edge(3,66).
+edge(66,3).
+edge(3,68).
+edge(68,3).
+edge(3,70).
+edge(70,3).
+edge(3,76).
+edge(76,3).
+edge(3,90).
+edge(90,3).
+edge(3,94).
+edge(94,3).
+edge(3,97).
+edge(97,3).
+edge(3,106).
+edge(106,3).
+edge(3,108).
+edge(108,3).
+edge(3,119).
+edge(119,3).
+edge(3,121).
+edge(121,3).
+edge(3,127).
+edge(127,3).
+edge(4,13).
+edge(13,4).
+edge(4,14).
+edge(14,4).
+edge(4,28).
+edge(28,4).
+edge(4,30).
+edge(30,4).
+edge(4,43).
+edge(43,4).
+edge(4,49).
+edge(49,4).
+edge(4,57).
+edge(57,4).
+edge(4,67).
+edge(67,4).
+edge(4,71).
+edge(71,4).
+edge(4,72).
+edge(72,4).
+edge(4,102).
+edge(102,4).
+edge(4,114).
+edge(114,4).
+edge(4,116).
+edge(116,4).
+edge(4,125).
+edge(125,4).
+edge(4,134).
+edge(134,4).
+edge(5,30).
+edge(30,5).
+edge(5,41).
+edge(41,5).
+edge(5,46).
+edge(46,5).
+edge(5,64).
+edge(64,5).
+edge(5,103).
+edge(103,5).
+edge(5,106).
+edge(106,5).
+edge(5,133).
+edge(133,5).
+edge(6,36).
+edge(36,6).
+edge(6,49).
+edge(49,6).
+edge(6,57).
+edge(57,6).
+edge(6,78).
+edge(78,6).
+edge(6,89).
+edge(89,6).
+edge(6,90).
+edge(90,6).
+edge(6,101).
+edge(101,6).
+edge(6,111).
+edge(111,6).
+edge(6,117).
+edge(117,6).
+edge(6,119).
+edge(119,6).
+edge(6,124).
+edge(124,6).
+edge(6,135).
+edge(135,6).
+edge(7,10).
+edge(10,7).
+edge(7,25).
+edge(25,7).
+edge(7,32).
+edge(32,7).
+edge(7,33).
+edge(33,7).
+edge(7,50).
+edge(50,7).
+edge(7,54).
+edge(54,7).
+edge(7,58).
+edge(58,7).
+edge(7,60).
+edge(60,7).
+edge(7,65).
+edge(65,7).
+edge(7,66).
+edge(66,7).
+edge(7,69).
+edge(69,7).
+edge(7,71).
+edge(71,7).
+edge(7,73).
+edge(73,7).
+edge(7,77).
+edge(77,7).
+edge(7,80).
+edge(80,7).
+edge(7,82).
+edge(82,7).
+edge(7,101).
+edge(101,7).
+edge(7,108).
+edge(108,7).
+edge(7,120).
+edge(120,7).
+edge(7,125).
+edge(125,7).
+edge(7,130).
+edge(130,7).
+edge(7,133).
+edge(133,7).
+edge(8,22).
+edge(22,8).
+edge(8,35).
+edge(35,8).
+edge(8,40).
+edge(40,8).
+edge(8,51).
+edge(51,8).
+edge(8,60).
+edge(60,8).
+edge(8,67).
+edge(67,8).
+edge(8,69).
+edge(69,8).
+edge(8,73).
+edge(73,8).
+edge(8,77).
+edge(77,8).
+edge(8,100).
+edge(100,8).
+edge(8,131).
+edge(131,8).
+edge(8,134).
+edge(134,8).
+edge(9,24).
+edge(24,9).
+edge(9,27).
+edge(27,9).
+edge(9,44).
+edge(44,9).
+edge(9,70).
+edge(70,9).
+edge(9,76).
+edge(76,9).
+edge(9,81).
+edge(81,9).
+edge(9,84).
+edge(84,9).
+edge(9,93).
+edge(93,9).
+edge(9,97).
+edge(97,9).
+edge(9,110).
+edge(110,9).
+edge(9,120).
+edge(120,9).
+edge(9,122).
+edge(122,9).
+edge(9,127).
+edge(127,9).
+edge(9,129).
+edge(129,9).
+edge(9,132).
+edge(132,9).
+edge(10,23).
+edge(23,10).
+edge(10,35).
+edge(35,10).
+edge(10,38).
+edge(38,10).
+edge(10,39).
+edge(39,10).
+edge(10,45).
+edge(45,10).
+edge(10,46).
+edge(46,10).
+edge(10,58).
+edge(58,10).
+edge(10,59).
+edge(59,10).
+edge(10,62).
+edge(62,10).
+edge(10,64).
+edge(64,10).
+edge(10,82).
+edge(82,10).
+edge(10,94).
+edge(94,10).
+edge(10,102).
+edge(102,10).
+edge(10,123).
+edge(123,10).
+edge(10,127).
+edge(127,10).
+edge(11,21).
+edge(21,11).
+edge(11,56).
+edge(56,11).
+edge(11,90).
+edge(90,11).
+edge(11,97).
+edge(97,11).
+edge(11,117).
+edge(117,11).
+edge(11,119).
+edge(119,11).
+edge(11,126).
+edge(126,11).
+edge(11,129).
+edge(129,11).
+edge(12,20).
+edge(20,12).
+edge(12,36).
+edge(36,12).
+edge(12,39).
+edge(39,12).
+edge(12,63).
+edge(63,12).
+edge(12,70).
+edge(70,12).
+edge(12,84).
+edge(84,12).
+edge(12,85).
+edge(85,12).
+edge(12,96).
+edge(96,12).
+edge(12,111).
+edge(111,12).
+edge(12,122).
+edge(122,12).
+edge(12,135).
+edge(135,12).
+edge(13,18).
+edge(18,13).
+edge(13,22).
+edge(22,13).
+edge(13,30).
+edge(30,13).
+edge(13,48).
+edge(48,13).
+edge(13,58).
+edge(58,13).
+edge(13,75).
+edge(75,13).
+edge(13,81).
+edge(81,13).
+edge(13,102).
+edge(102,13).
+edge(13,104).
+edge(104,13).
+edge(14,19).
+edge(19,14).
+edge(14,39).
+edge(39,14).
+edge(14,62).
+edge(62,14).
+edge(14,74).
+edge(74,14).
+edge(14,81).
+edge(81,14).
+edge(14,82).
+edge(82,14).
+edge(14,90).
+edge(90,14).
+edge(14,101).
+edge(101,14).
+edge(14,103).
+edge(103,14).
+edge(14,134).
+edge(134,14).
+edge(15,19).
+edge(19,15).
+edge(15,32).
+edge(32,15).
+edge(15,37).
+edge(37,15).
+edge(15,47).
+edge(47,15).
+edge(15,53).
+edge(53,15).
+edge(15,85).
+edge(85,15).
+edge(15,115).
+edge(115,15).
+edge(16,17).
+edge(17,16).
+edge(16,25).
+edge(25,16).
+edge(16,44).
+edge(44,16).
+edge(16,54).
+edge(54,16).
+edge(16,59).
+edge(59,16).
+edge(16,61).
+edge(61,16).
+edge(16,62).
+edge(62,16).
+edge(16,97).
+edge(97,16).
+edge(16,115).
+edge(115,16).
+edge(16,118).
+edge(118,16).
+edge(17,33).
+edge(33,17).
+edge(17,35).
+edge(35,17).
+edge(17,41).
+edge(41,17).
+edge(17,58).
+edge(58,17).
+edge(17,66).
+edge(66,17).
+edge(17,67).
+edge(67,17).
+edge(17,70).
+edge(70,17).
+edge(17,72).
+edge(72,17).
+edge(17,74).
+edge(74,17).
+edge(17,88).
+edge(88,17).
+edge(17,96).
+edge(96,17).
+edge(17,100).
+edge(100,17).
+edge(17,113).
+edge(113,17).
+edge(17,123).
+edge(123,17).
+edge(17,125).
+edge(125,17).
+edge(17,131).
+edge(131,17).
+edge(18,20).
+edge(20,18).
+edge(18,32).
+edge(32,18).
+edge(18,35).
+edge(35,18).
+edge(18,63).
+edge(63,18).
+edge(18,96).
+edge(96,18).
+edge(18,102).
+edge(102,18).
+edge(18,104).
+edge(104,18).
+edge(18,112).
+edge(112,18).
+edge(19,40).
+edge(40,19).
+edge(19,45).
+edge(45,19).
+edge(19,48).
+edge(48,19).
+edge(19,50).
+edge(50,19).
+edge(19,67).
+edge(67,19).
+edge(19,75).
+edge(75,19).
+edge(19,81).
+edge(81,19).
+edge(19,87).
+edge(87,19).
+edge(19,104).
+edge(104,19).
+edge(19,107).
+edge(107,19).
+edge(19,108).
+edge(108,19).
+edge(19,113).
+edge(113,19).
+edge(19,116).
+edge(116,19).
+edge(20,39).
+edge(39,20).
+edge(20,44).
+edge(44,20).
+edge(20,54).
+edge(54,20).
+edge(20,63).
+edge(63,20).
+edge(20,65).
+edge(65,20).
+edge(20,86).
+edge(86,20).
+edge(20,94).
+edge(94,20).
+edge(20,100).
+edge(100,20).
+edge(20,105).
+edge(105,20).
+edge(20,121).
+edge(121,20).
+edge(21,25).
+edge(25,21).
+edge(21,32).
+edge(32,21).
+edge(21,34).
+edge(34,21).
+edge(21,37).
+edge(37,21).
+edge(21,49).
+edge(49,21).
+edge(21,65).
+edge(65,21).
+edge(21,75).
+edge(75,21).
+edge(21,86).
+edge(86,21).
+edge(21,93).
+edge(93,21).
+edge(21,95).
+edge(95,21).
+edge(21,97).
+edge(97,21).
+edge(21,99).
+edge(99,21).
+edge(21,104).
+edge(104,21).
+edge(21,123).
+edge(123,21).
+edge(21,124).
+edge(124,21).
+edge(21,130).
+edge(130,21).
+edge(22,38).
+edge(38,22).
+edge(22,41).
+edge(41,22).
+edge(22,78).
+edge(78,22).
+edge(22,97).
+edge(97,22).
+edge(22,98).
+edge(98,22).
+edge(22,101).
+edge(101,22).
+edge(22,111).
+edge(111,22).
+edge(22,122).
+edge(122,22).
+edge(22,130).
+edge(130,22).
+edge(22,132).
+edge(132,22).
+edge(23,31).
+edge(31,23).
+edge(23,34).
+edge(34,23).
+edge(23,46).
+edge(46,23).
+edge(23,52).
+edge(52,23).
+edge(23,56).
+edge(56,23).
+edge(23,57).
+edge(57,23).
+edge(23,74).
+edge(74,23).
+edge(23,102).
+edge(102,23).
+edge(23,109).
+edge(109,23).
+edge(23,117).
+edge(117,23).
+edge(23,128).
+edge(128,23).
+edge(24,30).
+edge(30,24).
+edge(24,36).
+edge(36,24).
+edge(24,37).
+edge(37,24).
+edge(24,38).
+edge(38,24).
+edge(24,51).
+edge(51,24).
+edge(24,57).
+edge(57,24).
+edge(24,65).
+edge(65,24).
+edge(24,81).
+edge(81,24).
+edge(25,33).
+edge(33,25).
+edge(25,37).
+edge(37,25).
+edge(25,48).
+edge(48,25).
+edge(25,59).
+edge(59,25).
+edge(25,61).
+edge(61,25).
+edge(25,78).
+edge(78,25).
+edge(25,82).
+edge(82,25).
+edge(25,93).
+edge(93,25).
+edge(25,103).
+edge(103,25).
+edge(25,107).
+edge(107,25).
+edge(25,115).
+edge(115,25).
+edge(25,119).
+edge(119,25).
+edge(25,134).
+edge(134,25).
+edge(26,32).
+edge(32,26).
+edge(26,42).
+edge(42,26).
+edge(26,60).
+edge(60,26).
+edge(26,65).
+edge(65,26).
+edge(26,77).
+edge(77,26).
+edge(26,108).
+edge(108,26).
+edge(26,109).
+edge(109,26).
+edge(26,112).
+edge(112,26).
+edge(26,117).
+edge(117,26).
+edge(26,130).
+edge(130,26).
+edge(26,135).
+edge(135,26).
+edge(27,43).
+edge(43,27).
+edge(27,49).
+edge(49,27).
+edge(27,60).
+edge(60,27).
+edge(27,63).
+edge(63,27).
+edge(27,69).
+edge(69,27).
+edge(27,72).
+edge(72,27).
+edge(27,79).
+edge(79,27).
+edge(27,94).
+edge(94,27).
+edge(27,97).
+edge(97,27).
+edge(27,101).
+edge(101,27).
+edge(27,105).
+edge(105,27).
+edge(27,134).
+edge(134,27).
+edge(28,48).
+edge(48,28).
+edge(28,54).
+edge(54,28).
+edge(28,62).
+edge(62,28).
+edge(28,65).
+edge(65,28).
+edge(28,66).
+edge(66,28).
+edge(28,79).
+edge(79,28).
+edge(28,84).
+edge(84,28).
+edge(28,92).
+edge(92,28).
+edge(28,96).
+edge(96,28).
+edge(28,101).
+edge(101,28).
+edge(28,114).
+edge(114,28).
+edge(28,115).
+edge(115,28).
+edge(28,118).
+edge(118,28).
+edge(28,121).
+edge(121,28).
+edge(28,129).
+edge(129,28).
+edge(28,133).
+edge(133,28).
+edge(29,31).
+edge(31,29).
+edge(29,43).
+edge(43,29).
+edge(29,75).
+edge(75,29).
+edge(29,77).
+edge(77,29).
+edge(29,90).
+edge(90,29).
+edge(29,92).
+edge(92,29).
+edge(29,94).
+edge(94,29).
+edge(29,114).
+edge(114,29).
+edge(29,124).
+edge(124,29).
+edge(29,132).
+edge(132,29).
+edge(30,34).
+edge(34,30).
+edge(30,39).
+edge(39,30).
+edge(30,44).
+edge(44,30).
+edge(30,48).
+edge(48,30).
+edge(30,49).
+edge(49,30).
+edge(30,65).
+edge(65,30).
+edge(30,68).
+edge(68,30).
+edge(30,76).
+edge(76,30).
+edge(30,86).
+edge(86,30).
+edge(30,87).
+edge(87,30).
+edge(30,110).
+edge(110,30).
+edge(30,114).
+edge(114,30).
+edge(30,115).
+edge(115,30).
+edge(30,125).
+edge(125,30).
+edge(31,44).
+edge(44,31).
+edge(31,62).
+edge(62,31).
+edge(31,67).
+edge(67,31).
+edge(31,74).
+edge(74,31).
+edge(31,75).
+edge(75,31).
+edge(31,78).
+edge(78,31).
+edge(31,82).
+edge(82,31).
+edge(31,94).
+edge(94,31).
+edge(31,99).
+edge(99,31).
+edge(31,124).
+edge(124,31).
+edge(31,132).
+edge(132,31).
+edge(32,36).
+edge(36,32).
+edge(32,50).
+edge(50,32).
+edge(32,61).
+edge(61,32).
+edge(32,71).
+edge(71,32).
+edge(32,95).
+edge(95,32).
+edge(32,107).
+edge(107,32).
+edge(32,132).
+edge(132,32).
+edge(33,35).
+edge(35,33).
+edge(33,48).
+edge(48,33).
+edge(33,61).
+edge(61,33).
+edge(33,62).
+edge(62,33).
+edge(33,71).
+edge(71,33).
+edge(33,103).
+edge(103,33).
+edge(33,107).
+edge(107,33).
+edge(33,111).
+edge(111,33).
+edge(33,112).
+edge(112,33).
+edge(33,114).
+edge(114,33).
+edge(33,121).
+edge(121,33).
+edge(33,134).
+edge(134,33).
+edge(34,49).
+edge(49,34).
+edge(34,55).
+edge(55,34).
+edge(34,78).
+edge(78,34).
+edge(34,105).
+edge(105,34).
+edge(34,115).
+edge(115,34).
+edge(34,124).
+edge(124,34).
+edge(35,38).
+edge(38,35).
+edge(35,48).
+edge(48,35).
+edge(35,63).
+edge(63,35).
+edge(35,81).
+edge(81,35).
+edge(35,87).
+edge(87,35).
+edge(35,91).
+edge(91,35).
+edge(35,102).
+edge(102,35).
+edge(35,103).
+edge(103,35).
+edge(35,105).
+edge(105,35).
+edge(35,107).
+edge(107,35).
+edge(35,112).
+edge(112,35).
+edge(35,113).
+edge(113,35).
+edge(36,75).
+edge(75,36).
+edge(36,78).
+edge(78,36).
+edge(36,82).
+edge(82,36).
+edge(36,88).
+edge(88,36).
+edge(36,93).
+edge(93,36).
+edge(36,98).
+edge(98,36).
+edge(36,112).
+edge(112,36).
+edge(36,113).
+edge(113,36).
+edge(36,126).
+edge(126,36).
+edge(36,131).
+edge(131,36).
+edge(37,55).
+edge(55,37).
+edge(37,60).
+edge(60,37).
+edge(37,74).
+edge(74,37).
+edge(37,76).
+edge(76,37).
+edge(37,86).
+edge(86,37).
+edge(37,87).
+edge(87,37).
+edge(37,94).
+edge(94,37).
+edge(37,108).
+edge(108,37).
+edge(37,116).
+edge(116,37).
+edge(37,128).
+edge(128,37).
+edge(37,134).
+edge(134,37).
+edge(38,49).
+edge(49,38).
+edge(38,83).
+edge(83,38).
+edge(38,126).
+edge(126,38).
+edge(38,127).
+edge(127,38).
+edge(38,129).
+edge(129,38).
+edge(38,131).
+edge(131,38).
+edge(39,51).
+edge(51,39).
+edge(39,79).
+edge(79,39).
+edge(39,88).
+edge(88,39).
+edge(39,95).
+edge(95,39).
+edge(39,99).
+edge(99,39).
+edge(39,100).
+edge(100,39).
+edge(39,101).
+edge(101,39).
+edge(39,115).
+edge(115,39).
+edge(39,116).
+edge(116,39).
+edge(40,42).
+edge(42,40).
+edge(40,46).
+edge(46,40).
+edge(40,60).
+edge(60,40).
+edge(40,61).
+edge(61,40).
+edge(40,62).
+edge(62,40).
+edge(40,64).
+edge(64,40).
+edge(40,71).
+edge(71,40).
+edge(40,77).
+edge(77,40).
+edge(40,90).
+edge(90,40).
+edge(40,95).
+edge(95,40).
+edge(40,121).
+edge(121,40).
+edge(40,131).
+edge(131,40).
+edge(40,134).
+edge(134,40).
+edge(41,44).
+edge(44,41).
+edge(41,50).
+edge(50,41).
+edge(41,53).
+edge(53,41).
+edge(41,54).
+edge(54,41).
+edge(41,65).
+edge(65,41).
+edge(41,71).
+edge(71,41).
+edge(41,80).
+edge(80,41).
+edge(41,81).
+edge(81,41).
+edge(41,96).
+edge(96,41).
+edge(41,99).
+edge(99,41).
+edge(41,104).
+edge(104,41).
+edge(41,123).
+edge(123,41).
+edge(41,130).
+edge(130,41).
+edge(41,131).
+edge(131,41).
+edge(42,79).
+edge(79,42).
+edge(42,83).
+edge(83,42).
+edge(42,91).
+edge(91,42).
+edge(42,104).
+edge(104,42).
+edge(42,107).
+edge(107,42).
+edge(42,110).
+edge(110,42).
+edge(42,112).
+edge(112,42).
+edge(42,118).
+edge(118,42).
+edge(42,129).
+edge(129,42).
+edge(43,44).
+edge(44,43).
+edge(43,72).
+edge(72,43).
+edge(43,86).
+edge(86,43).
+edge(43,89).
+edge(89,43).
+edge(43,110).
+edge(110,43).
+edge(43,116).
+edge(116,43).
+edge(44,45).
+edge(45,44).
+edge(44,62).
+edge(62,44).
+edge(44,65).
+edge(65,44).
+edge(44,66).
+edge(66,44).
+edge(44,75).
+edge(75,44).
+edge(44,97).
+edge(97,44).
+edge(44,112).
+edge(112,44).
+edge(44,118).
+edge(118,44).
+edge(44,124).
+edge(124,44).
+edge(44,126).
+edge(126,44).
+edge(44,131).
+edge(131,44).
+edge(45,46).
+edge(46,45).
+edge(45,55).
+edge(55,45).
+edge(45,58).
+edge(58,45).
+edge(45,63).
+edge(63,45).
+edge(45,88).
+edge(88,45).
+edge(45,101).
+edge(101,45).
+edge(45,102).
+edge(102,45).
+edge(45,121).
+edge(121,45).
+edge(45,131).
+edge(131,45).
+edge(46,48).
+edge(48,46).
+edge(46,50).
+edge(50,46).
+edge(46,51).
+edge(51,46).
+edge(46,59).
+edge(59,46).
+edge(46,67).
+edge(67,46).
+edge(46,75).
+edge(75,46).
+edge(46,76).
+edge(76,46).
+edge(46,78).
+edge(78,46).
+edge(46,83).
+edge(83,46).
+edge(46,107).
+edge(107,46).
+edge(46,134).
+edge(134,46).
+edge(47,51).
+edge(51,47).
+edge(47,52).
+edge(52,47).
+edge(47,59).
+edge(59,47).
+edge(47,75).
+edge(75,47).
+edge(47,81).
+edge(81,47).
+edge(47,93).
+edge(93,47).
+edge(47,97).
+edge(97,47).
+edge(47,100).
+edge(100,47).
+edge(47,102).
+edge(102,47).
+edge(47,120).
+edge(120,47).
+edge(47,125).
+edge(125,47).
+edge(47,126).
+edge(126,47).
+edge(48,62).
+edge(62,48).
+edge(48,64).
+edge(64,48).
+edge(48,79).
+edge(79,48).
+edge(48,80).
+edge(80,48).
+edge(48,82).
+edge(82,48).
+edge(48,91).
+edge(91,48).
+edge(49,56).
+edge(56,49).
+edge(49,63).
+edge(63,49).
+edge(49,73).
+edge(73,49).
+edge(49,83).
+edge(83,49).
+edge(49,87).
+edge(87,49).
+edge(49,97).
+edge(97,49).
+edge(49,99).
+edge(99,49).
+edge(49,109).
+edge(109,49).
+edge(49,130).
+edge(130,49).
+edge(50,65).
+edge(65,50).
+edge(50,78).
+edge(78,50).
+edge(50,86).
+edge(86,50).
+edge(50,99).
+edge(99,50).
+edge(50,103).
+edge(103,50).
+edge(50,121).
+edge(121,50).
+edge(50,125).
+edge(125,50).
+edge(51,54).
+edge(54,51).
+edge(51,66).
+edge(66,51).
+edge(51,69).
+edge(69,51).
+edge(51,81).
+edge(81,51).
+edge(51,99).
+edge(99,51).
+edge(51,123).
+edge(123,51).
+edge(52,57).
+edge(57,52).
+edge(52,64).
+edge(64,52).
+edge(52,68).
+edge(68,52).
+edge(52,69).
+edge(69,52).
+edge(52,72).
+edge(72,52).
+edge(52,81).
+edge(81,52).
+edge(52,121).
+edge(121,52).
+edge(53,64).
+edge(64,53).
+edge(53,65).
+edge(65,53).
+edge(53,70).
+edge(70,53).
+edge(53,73).
+edge(73,53).
+edge(53,75).
+edge(75,53).
+edge(53,79).
+edge(79,53).
+edge(53,92).
+edge(92,53).
+edge(53,105).
+edge(105,53).
+edge(53,119).
+edge(119,53).
+edge(54,60).
+edge(60,54).
+edge(54,64).
+edge(64,54).
+edge(54,73).
+edge(73,54).
+edge(54,88).
+edge(88,54).
+edge(54,92).
+edge(92,54).
+edge(54,97).
+edge(97,54).
+edge(54,103).
+edge(103,54).
+edge(54,117).
+edge(117,54).
+edge(54,125).
+edge(125,54).
+edge(54,132).
+edge(132,54).
+edge(55,64).
+edge(64,55).
+edge(55,78).
+edge(78,55).
+edge(55,105).
+edge(105,55).
+edge(55,110).
+edge(110,55).
+edge(55,111).
+edge(111,55).
+edge(55,124).
+edge(124,55).
+edge(55,125).
+edge(125,55).
+edge(56,67).
+edge(67,56).
+edge(56,73).
+edge(73,56).
+edge(56,82).
+edge(82,56).
+edge(56,106).
+edge(106,56).
+edge(56,109).
+edge(109,56).
+edge(56,111).
+edge(111,56).
+edge(56,113).
+edge(113,56).
+edge(56,128).
+edge(128,56).
+edge(57,63).
+edge(63,57).
+edge(57,65).
+edge(65,57).
+edge(57,75).
+edge(75,57).
+edge(57,78).
+edge(78,57).
+edge(57,80).
+edge(80,57).
+edge(57,85).
+edge(85,57).
+edge(57,100).
+edge(100,57).
+edge(57,105).
+edge(105,57).
+edge(58,69).
+edge(69,58).
+edge(58,74).
+edge(74,58).
+edge(58,84).
+edge(84,58).
+edge(58,88).
+edge(88,58).
+edge(58,92).
+edge(92,58).
+edge(58,107).
+edge(107,58).
+edge(58,110).
+edge(110,58).
+edge(58,133).
+edge(133,58).
+edge(59,62).
+edge(62,59).
+edge(59,105).
+edge(105,59).
+edge(59,135).
+edge(135,59).
+edge(60,61).
+edge(61,60).
+edge(60,89).
+edge(89,60).
+edge(60,126).
+edge(126,60).
+edge(60,128).
+edge(128,60).
+edge(60,129).
+edge(129,60).
+edge(60,133).
+edge(133,60).
+edge(61,83).
+edge(83,61).
+edge(61,84).
+edge(84,61).
+edge(61,128).
+edge(128,61).
+edge(62,65).
+edge(65,62).
+edge(62,69).
+edge(69,62).
+edge(62,87).
+edge(87,62).
+edge(62,89).
+edge(89,62).
+edge(62,105).
+edge(105,62).
+edge(62,114).
+edge(114,62).
+edge(62,115).
+edge(115,62).
+edge(62,116).
+edge(116,62).
+edge(62,118).
+edge(118,62).
+edge(62,126).
+edge(126,62).
+edge(62,130).
+edge(130,62).
+edge(62,135).
+edge(135,62).
+edge(63,78).
+edge(78,63).
+edge(63,88).
+edge(88,63).
+edge(63,101).
+edge(101,63).
+edge(63,105).
+edge(105,63).
+edge(63,131).
+edge(131,63).
+edge(63,132).
+edge(132,63).
+edge(64,74).
+edge(74,64).
+edge(64,92).
+edge(92,64).
+edge(64,102).
+edge(102,64).
+edge(64,104).
+edge(104,64).
+edge(64,107).
+edge(107,64).
+edge(64,109).
+edge(109,64).
+edge(64,129).
+edge(129,64).
+edge(64,134).
+edge(134,64).
+edge(65,71).
+edge(71,65).
+edge(65,82).
+edge(82,65).
+edge(65,83).
+edge(83,65).
+edge(65,99).
+edge(99,65).
+edge(65,111).
+edge(111,65).
+edge(65,118).
+edge(118,65).
+edge(66,71).
+edge(71,66).
+edge(66,83).
+edge(83,66).
+edge(66,90).
+edge(90,66).
+edge(66,96).
+edge(96,66).
+edge(66,102).
+edge(102,66).
+edge(66,104).
+edge(104,66).
+edge(66,115).
+edge(115,66).
+edge(66,128).
+edge(128,66).
+edge(66,132).
+edge(132,66).
+edge(67,71).
+edge(71,67).
+edge(67,72).
+edge(72,67).
+edge(67,73).
+edge(73,67).
+edge(67,77).
+edge(77,67).
+edge(67,118).
+edge(118,67).
+edge(67,122).
+edge(122,67).
+edge(68,73).
+edge(73,68).
+edge(68,134).
+edge(134,68).
+edge(69,76).
+edge(76,69).
+edge(69,79).
+edge(79,69).
+edge(69,88).
+edge(88,69).
+edge(69,90).
+edge(90,69).
+edge(69,106).
+edge(106,69).
+edge(69,107).
+edge(107,69).
+edge(69,108).
+edge(108,69).
+edge(69,111).
+edge(111,69).
+edge(69,114).
+edge(114,69).
+edge(69,125).
+edge(125,69).
+edge(70,72).
+edge(72,70).
+edge(70,78).
+edge(78,70).
+edge(70,86).
+edge(86,70).
+edge(70,87).
+edge(87,70).
+edge(70,94).
+edge(94,70).
+edge(70,95).
+edge(95,70).
+edge(70,109).
+edge(109,70).
+edge(70,112).
+edge(112,70).
+edge(71,89).
+edge(89,71).
+edge(71,100).
+edge(100,71).
+edge(71,130).
+edge(130,71).
+edge(72,77).
+edge(77,72).
+edge(72,78).
+edge(78,72).
+edge(72,87).
+edge(87,72).
+edge(72,94).
+edge(94,72).
+edge(72,114).
+edge(114,72).
+edge(73,102).
+edge(102,73).
+edge(73,119).
+edge(119,73).
+edge(73,130).
+edge(130,73).
+edge(74,87).
+edge(87,74).
+edge(74,88).
+edge(88,74).
+edge(74,92).
+edge(92,74).
+edge(74,109).
+edge(109,74).
+edge(74,114).
+edge(114,74).
+edge(74,122).
+edge(122,74).
+edge(74,132).
+edge(132,74).
+edge(74,134).
+edge(134,74).
+edge(75,76).
+edge(76,75).
+edge(75,81).
+edge(81,75).
+edge(75,82).
+edge(82,75).
+edge(75,115).
+edge(115,75).
+edge(76,87).
+edge(87,76).
+edge(76,89).
+edge(89,76).
+edge(76,92).
+edge(92,76).
+edge(76,97).
+edge(97,76).
+edge(76,112).
+edge(112,76).
+edge(76,116).
+edge(116,76).
+edge(76,121).
+edge(121,76).
+edge(76,123).
+edge(123,76).
+edge(76,127).
+edge(127,76).
+edge(77,79).
+edge(79,77).
+edge(77,82).
+edge(82,77).
+edge(77,88).
+edge(88,77).
+edge(77,91).
+edge(91,77).
+edge(77,104).
+edge(104,77).
+edge(77,106).
+edge(106,77).
+edge(77,118).
+edge(118,77).
+edge(78,101).
+edge(101,78).
+edge(78,106).
+edge(106,78).
+edge(78,111).
+edge(111,78).
+edge(78,115).
+edge(115,78).
+edge(78,126).
+edge(126,78).
+edge(79,84).
+edge(84,79).
+edge(79,92).
+edge(92,79).
+edge(79,98).
+edge(98,79).
+edge(79,99).
+edge(99,79).
+edge(79,100).
+edge(100,79).
+edge(79,113).
+edge(113,79).
+edge(79,120).
+edge(120,79).
+edge(79,131).
+edge(131,79).
+edge(79,132).
+edge(132,79).
+edge(80,83).
+edge(83,80).
+edge(80,86).
+edge(86,80).
+edge(80,95).
+edge(95,80).
+edge(80,107).
+edge(107,80).
+edge(80,116).
+edge(116,80).
+edge(80,117).
+edge(117,80).
+edge(80,129).
+edge(129,80).
+edge(81,124).
+edge(124,81).
+edge(82,87).
+edge(87,82).
+edge(82,105).
+edge(105,82).
+edge(82,106).
+edge(106,82).
+edge(82,114).
+edge(114,82).
+edge(82,121).
+edge(121,82).
+edge(82,135).
+edge(135,82).
+edge(83,87).
+edge(87,83).
+edge(83,96).
+edge(96,83).
+edge(83,99).
+edge(99,83).
+edge(83,121).
+edge(121,83).
+edge(83,128).
+edge(128,83).
+edge(84,88).
+edge(88,84).
+edge(84,91).
+edge(91,84).
+edge(84,113).
+edge(113,84).
+edge(84,119).
+edge(119,84).
+edge(84,122).
+edge(122,84).
+edge(85,87).
+edge(87,85).
+edge(85,89).
+edge(89,85).
+edge(85,90).
+edge(90,85).
+edge(85,91).
+edge(91,85).
+edge(85,102).
+edge(102,85).
+edge(85,112).
+edge(112,85).
+edge(85,124).
+edge(124,85).
+edge(85,133).
+edge(133,85).
+edge(86,89).
+edge(89,86).
+edge(86,91).
+edge(91,86).
+edge(86,92).
+edge(92,86).
+edge(86,112).
+edge(112,86).
+edge(86,129).
+edge(129,86).
+edge(86,133).
+edge(133,86).
+edge(87,88).
+edge(88,87).
+edge(87,100).
+edge(100,87).
+edge(87,102).
+edge(102,87).
+edge(87,110).
+edge(110,87).
+edge(87,115).
+edge(115,87).
+edge(87,121).
+edge(121,87).
+edge(87,125).
+edge(125,87).
+edge(88,101).
+edge(101,88).
+edge(88,104).
+edge(104,88).
+edge(89,90).
+edge(90,89).
+edge(89,102).
+edge(102,89).
+edge(89,110).
+edge(110,89).
+edge(89,122).
+edge(122,89).
+edge(89,132).
+edge(132,89).
+edge(90,110).
+edge(110,90).
+edge(90,133).
+edge(133,90).
+edge(91,93).
+edge(93,91).
+edge(91,96).
+edge(96,91).
+edge(91,101).
+edge(101,91).
+edge(91,120).
+edge(120,91).
+edge(91,121).
+edge(121,91).
+edge(91,124).
+edge(124,91).
+edge(91,130).
+edge(130,91).
+edge(92,106).
+edge(106,92).
+edge(92,114).
+edge(114,92).
+edge(92,122).
+edge(122,92).
+edge(92,126).
+edge(126,92).
+edge(93,98).
+edge(98,93).
+edge(93,106).
+edge(106,93).
+edge(93,113).
+edge(113,93).
+edge(93,114).
+edge(114,93).
+edge(93,115).
+edge(115,93).
+edge(93,129).
+edge(129,93).
+edge(93,135).
+edge(135,93).
+edge(94,121).
+edge(121,94).
+edge(94,134).
+edge(134,94).
+edge(95,97).
+edge(97,95).
+edge(95,114).
+edge(114,95).
+edge(95,124).
+edge(124,95).
+edge(95,126).
+edge(126,95).
+edge(95,127).
+edge(127,95).
+edge(96,100).
+edge(100,96).
+edge(96,102).
+edge(102,96).
+edge(96,107).
+edge(107,96).
+edge(96,125).
+edge(125,96).
+edge(96,131).
+edge(131,96).
+edge(97,99).
+edge(99,97).
+edge(97,104).
+edge(104,97).
+edge(97,122).
+edge(122,97).
+edge(97,125).
+edge(125,97).
+edge(97,131).
+edge(131,97).
+edge(98,102).
+edge(102,98).
+edge(98,107).
+edge(107,98).
+edge(98,108).
+edge(108,98).
+edge(98,109).
+edge(109,98).
+edge(98,118).
+edge(118,98).
+edge(98,127).
+edge(127,98).
+edge(99,108).
+edge(108,99).
+edge(99,117).
+edge(117,99).
+edge(99,122).
+edge(122,99).
+edge(99,132).
+edge(132,99).
+edge(100,109).
+edge(109,100).
+edge(100,114).
+edge(114,100).
+edge(100,123).
+edge(123,100).
+edge(100,128).
+edge(128,100).
+edge(100,131).
+edge(131,100).
+edge(100,133).
+edge(133,100).
+edge(101,116).
+edge(116,101).
+edge(101,118).
+edge(118,101).
+edge(101,125).
+edge(125,101).
+edge(102,111).
+edge(111,102).
+edge(102,131).
+edge(131,102).
+edge(103,107).
+edge(107,103).
+edge(103,110).
+edge(110,103).
+edge(103,117).
+edge(117,103).
+edge(103,118).
+edge(118,103).
+edge(103,123).
+edge(123,103).
+edge(103,126).
+edge(126,103).
+edge(103,127).
+edge(127,103).
+edge(103,133).
+edge(133,103).
+edge(104,108).
+edge(108,104).
+edge(104,109).
+edge(109,104).
+edge(104,110).
+edge(110,104).
+edge(104,115).
+edge(115,104).
+edge(104,129).
+edge(129,104).
+edge(105,114).
+edge(114,105).
+edge(105,128).
+edge(128,105).
+edge(105,133).
+edge(133,105).
+edge(106,112).
+edge(112,106).
+edge(106,115).
+edge(115,106).
+edge(106,125).
+edge(125,106).
+edge(107,112).
+edge(112,107).
+edge(107,123).
+edge(123,107).
+edge(107,124).
+edge(124,107).
+edge(107,128).
+edge(128,107).
+edge(107,133).
+edge(133,107).
+edge(108,109).
+edge(109,108).
+edge(108,117).
+edge(117,108).
+edge(108,124).
+edge(124,108).
+edge(109,118).
+edge(118,109).
+edge(109,122).
+edge(122,109).
+edge(109,123).
+edge(123,109).
+edge(109,127).
+edge(127,109).
+edge(109,130).
+edge(130,109).
+edge(109,131).
+edge(131,109).
+edge(110,116).
+edge(116,110).
+edge(110,118).
+edge(118,110).
+edge(110,132).
+edge(132,110).
+edge(110,135).
+edge(135,110).
+edge(111,131).
+edge(131,111).
+edge(112,116).
+edge(116,112).
+edge(112,117).
+edge(117,112).
+edge(112,123).
+edge(123,112).
+edge(112,126).
+edge(126,112).
+edge(113,118).
+edge(118,113).
+edge(113,134).
+edge(134,113).
+edge(114,115).
+edge(115,114).
+edge(114,130).
+edge(130,114).
+edge(115,118).
+edge(118,115).
+edge(115,119).
+edge(119,115).
+edge(115,134).
+edge(134,115).
+edge(116,126).
+edge(126,116).
+edge(116,128).
+edge(128,116).
+edge(116,131).
+edge(131,116).
+edge(117,123).
+edge(123,117).
+edge(117,125).
+edge(125,117).
+edge(117,131).
+edge(131,117).
+edge(118,120).
+edge(120,118).
+edge(118,124).
+edge(124,118).
+edge(119,132).
+edge(132,119).
+edge(120,121).
+edge(121,120).
+edge(120,129).
+edge(129,120).
+edge(121,132).
+edge(132,121).
+edge(122,134).
+edge(134,122).
+edge(123,135).
+edge(135,123).
+edge(124,126).
+edge(126,124).
+edge(125,131).
+edge(131,125).
+edge(126,127).
+edge(127,126).
+edge(130,133).
+edge(133,130).
+edge(130,134).
+edge(134,130).
+edge(131,132).
+edge(132,131).
+edge(134,135).
+edge(135,134).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0032-graph_colouring-140-0.lp b/examples/clingo/expansion/GraphColouring/instances/0032-graph_colouring-140-0.lp
new file mode 100644
index 0000000..0e3e465
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0032-graph_colouring-140-0.lp
@@ -0,0 +1,2226 @@
+#const n=140.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+edge(1,7).
+edge(7,1).
+edge(1,10).
+edge(10,1).
+edge(1,32).
+edge(32,1).
+edge(1,41).
+edge(41,1).
+edge(1,43).
+edge(43,1).
+edge(1,47).
+edge(47,1).
+edge(1,49).
+edge(49,1).
+edge(1,50).
+edge(50,1).
+edge(1,66).
+edge(66,1).
+edge(1,68).
+edge(68,1).
+edge(1,69).
+edge(69,1).
+edge(1,85).
+edge(85,1).
+edge(1,89).
+edge(89,1).
+edge(1,117).
+edge(117,1).
+edge(1,131).
+edge(131,1).
+edge(1,138).
+edge(138,1).
+edge(2,8).
+edge(8,2).
+edge(2,16).
+edge(16,2).
+edge(2,47).
+edge(47,2).
+edge(2,51).
+edge(51,2).
+edge(2,52).
+edge(52,2).
+edge(2,57).
+edge(57,2).
+edge(2,65).
+edge(65,2).
+edge(2,71).
+edge(71,2).
+edge(2,72).
+edge(72,2).
+edge(2,87).
+edge(87,2).
+edge(2,88).
+edge(88,2).
+edge(2,89).
+edge(89,2).
+edge(2,112).
+edge(112,2).
+edge(2,133).
+edge(133,2).
+edge(2,136).
+edge(136,2).
+edge(3,28).
+edge(28,3).
+edge(3,31).
+edge(31,3).
+edge(3,45).
+edge(45,3).
+edge(3,58).
+edge(58,3).
+edge(3,109).
+edge(109,3).
+edge(3,110).
+edge(110,3).
+edge(3,122).
+edge(122,3).
+edge(3,125).
+edge(125,3).
+edge(3,127).
+edge(127,3).
+edge(3,140).
+edge(140,3).
+edge(4,13).
+edge(13,4).
+edge(4,18).
+edge(18,4).
+edge(4,25).
+edge(25,4).
+edge(4,35).
+edge(35,4).
+edge(4,55).
+edge(55,4).
+edge(4,59).
+edge(59,4).
+edge(4,64).
+edge(64,4).
+edge(4,69).
+edge(69,4).
+edge(4,77).
+edge(77,4).
+edge(4,88).
+edge(88,4).
+edge(4,90).
+edge(90,4).
+edge(4,106).
+edge(106,4).
+edge(4,111).
+edge(111,4).
+edge(4,113).
+edge(113,4).
+edge(4,116).
+edge(116,4).
+edge(4,117).
+edge(117,4).
+edge(5,8).
+edge(8,5).
+edge(5,34).
+edge(34,5).
+edge(5,68).
+edge(68,5).
+edge(5,76).
+edge(76,5).
+edge(5,77).
+edge(77,5).
+edge(5,80).
+edge(80,5).
+edge(5,83).
+edge(83,5).
+edge(5,94).
+edge(94,5).
+edge(5,98).
+edge(98,5).
+edge(5,108).
+edge(108,5).
+edge(5,112).
+edge(112,5).
+edge(5,115).
+edge(115,5).
+edge(5,140).
+edge(140,5).
+edge(6,17).
+edge(17,6).
+edge(6,21).
+edge(21,6).
+edge(6,48).
+edge(48,6).
+edge(6,50).
+edge(50,6).
+edge(6,53).
+edge(53,6).
+edge(6,70).
+edge(70,6).
+edge(6,75).
+edge(75,6).
+edge(6,90).
+edge(90,6).
+edge(6,94).
+edge(94,6).
+edge(6,96).
+edge(96,6).
+edge(6,100).
+edge(100,6).
+edge(6,109).
+edge(109,6).
+edge(6,115).
+edge(115,6).
+edge(6,125).
+edge(125,6).
+edge(6,139).
+edge(139,6).
+edge(7,10).
+edge(10,7).
+edge(7,12).
+edge(12,7).
+edge(7,25).
+edge(25,7).
+edge(7,27).
+edge(27,7).
+edge(7,28).
+edge(28,7).
+edge(7,44).
+edge(44,7).
+edge(7,57).
+edge(57,7).
+edge(7,58).
+edge(58,7).
+edge(7,64).
+edge(64,7).
+edge(7,74).
+edge(74,7).
+edge(7,88).
+edge(88,7).
+edge(7,118).
+edge(118,7).
+edge(7,133).
+edge(133,7).
+edge(8,29).
+edge(29,8).
+edge(8,45).
+edge(45,8).
+edge(8,58).
+edge(58,8).
+edge(8,59).
+edge(59,8).
+edge(8,64).
+edge(64,8).
+edge(8,76).
+edge(76,8).
+edge(8,83).
+edge(83,8).
+edge(8,94).
+edge(94,8).
+edge(8,117).
+edge(117,8).
+edge(9,28).
+edge(28,9).
+edge(9,45).
+edge(45,9).
+edge(9,46).
+edge(46,9).
+edge(9,53).
+edge(53,9).
+edge(9,71).
+edge(71,9).
+edge(9,75).
+edge(75,9).
+edge(9,79).
+edge(79,9).
+edge(9,80).
+edge(80,9).
+edge(9,123).
+edge(123,9).
+edge(9,133).
+edge(133,9).
+edge(10,11).
+edge(11,10).
+edge(10,28).
+edge(28,10).
+edge(10,37).
+edge(37,10).
+edge(10,38).
+edge(38,10).
+edge(10,45).
+edge(45,10).
+edge(10,56).
+edge(56,10).
+edge(10,65).
+edge(65,10).
+edge(10,69).
+edge(69,10).
+edge(10,80).
+edge(80,10).
+edge(10,83).
+edge(83,10).
+edge(10,84).
+edge(84,10).
+edge(10,95).
+edge(95,10).
+edge(10,96).
+edge(96,10).
+edge(10,99).
+edge(99,10).
+edge(10,101).
+edge(101,10).
+edge(10,102).
+edge(102,10).
+edge(10,103).
+edge(103,10).
+edge(10,104).
+edge(104,10).
+edge(10,109).
+edge(109,10).
+edge(10,117).
+edge(117,10).
+edge(10,128).
+edge(128,10).
+edge(10,135).
+edge(135,10).
+edge(10,138).
+edge(138,10).
+edge(11,14).
+edge(14,11).
+edge(11,17).
+edge(17,11).
+edge(11,25).
+edge(25,11).
+edge(11,36).
+edge(36,11).
+edge(11,45).
+edge(45,11).
+edge(11,54).
+edge(54,11).
+edge(11,71).
+edge(71,11).
+edge(11,79).
+edge(79,11).
+edge(11,110).
+edge(110,11).
+edge(11,117).
+edge(117,11).
+edge(11,119).
+edge(119,11).
+edge(11,133).
+edge(133,11).
+edge(11,134).
+edge(134,11).
+edge(12,26).
+edge(26,12).
+edge(12,32).
+edge(32,12).
+edge(12,36).
+edge(36,12).
+edge(12,44).
+edge(44,12).
+edge(12,45).
+edge(45,12).
+edge(12,48).
+edge(48,12).
+edge(12,54).
+edge(54,12).
+edge(12,57).
+edge(57,12).
+edge(12,63).
+edge(63,12).
+edge(12,66).
+edge(66,12).
+edge(12,73).
+edge(73,12).
+edge(12,91).
+edge(91,12).
+edge(12,134).
+edge(134,12).
+edge(12,135).
+edge(135,12).
+edge(13,16).
+edge(16,13).
+edge(13,26).
+edge(26,13).
+edge(13,54).
+edge(54,13).
+edge(13,70).
+edge(70,13).
+edge(13,82).
+edge(82,13).
+edge(13,89).
+edge(89,13).
+edge(13,102).
+edge(102,13).
+edge(13,105).
+edge(105,13).
+edge(13,114).
+edge(114,13).
+edge(13,134).
+edge(134,13).
+edge(14,46).
+edge(46,14).
+edge(14,55).
+edge(55,14).
+edge(14,81).
+edge(81,14).
+edge(14,88).
+edge(88,14).
+edge(14,92).
+edge(92,14).
+edge(14,97).
+edge(97,14).
+edge(14,105).
+edge(105,14).
+edge(14,108).
+edge(108,14).
+edge(14,111).
+edge(111,14).
+edge(15,19).
+edge(19,15).
+edge(15,34).
+edge(34,15).
+edge(15,37).
+edge(37,15).
+edge(15,43).
+edge(43,15).
+edge(15,58).
+edge(58,15).
+edge(15,75).
+edge(75,15).
+edge(15,76).
+edge(76,15).
+edge(15,80).
+edge(80,15).
+edge(15,89).
+edge(89,15).
+edge(15,100).
+edge(100,15).
+edge(15,112).
+edge(112,15).
+edge(15,115).
+edge(115,15).
+edge(15,123).
+edge(123,15).
+edge(16,19).
+edge(19,16).
+edge(16,29).
+edge(29,16).
+edge(16,35).
+edge(35,16).
+edge(16,38).
+edge(38,16).
+edge(16,39).
+edge(39,16).
+edge(16,43).
+edge(43,16).
+edge(16,45).
+edge(45,16).
+edge(16,49).
+edge(49,16).
+edge(16,67).
+edge(67,16).
+edge(16,68).
+edge(68,16).
+edge(16,71).
+edge(71,16).
+edge(16,73).
+edge(73,16).
+edge(16,76).
+edge(76,16).
+edge(16,79).
+edge(79,16).
+edge(16,92).
+edge(92,16).
+edge(16,113).
+edge(113,16).
+edge(16,118).
+edge(118,16).
+edge(16,131).
+edge(131,16).
+edge(17,24).
+edge(24,17).
+edge(17,47).
+edge(47,17).
+edge(17,55).
+edge(55,17).
+edge(17,61).
+edge(61,17).
+edge(17,65).
+edge(65,17).
+edge(17,69).
+edge(69,17).
+edge(17,71).
+edge(71,17).
+edge(17,97).
+edge(97,17).
+edge(17,98).
+edge(98,17).
+edge(17,104).
+edge(104,17).
+edge(17,124).
+edge(124,17).
+edge(17,138).
+edge(138,17).
+edge(18,21).
+edge(21,18).
+edge(18,23).
+edge(23,18).
+edge(18,28).
+edge(28,18).
+edge(18,39).
+edge(39,18).
+edge(18,46).
+edge(46,18).
+edge(18,63).
+edge(63,18).
+edge(18,65).
+edge(65,18).
+edge(18,66).
+edge(66,18).
+edge(18,89).
+edge(89,18).
+edge(18,102).
+edge(102,18).
+edge(18,104).
+edge(104,18).
+edge(18,120).
+edge(120,18).
+edge(18,122).
+edge(122,18).
+edge(19,23).
+edge(23,19).
+edge(19,40).
+edge(40,19).
+edge(19,42).
+edge(42,19).
+edge(19,50).
+edge(50,19).
+edge(19,57).
+edge(57,19).
+edge(19,73).
+edge(73,19).
+edge(19,77).
+edge(77,19).
+edge(19,80).
+edge(80,19).
+edge(19,101).
+edge(101,19).
+edge(19,111).
+edge(111,19).
+edge(19,127).
+edge(127,19).
+edge(19,131).
+edge(131,19).
+edge(20,21).
+edge(21,20).
+edge(20,23).
+edge(23,20).
+edge(20,49).
+edge(49,20).
+edge(20,51).
+edge(51,20).
+edge(20,56).
+edge(56,20).
+edge(20,67).
+edge(67,20).
+edge(20,74).
+edge(74,20).
+edge(20,96).
+edge(96,20).
+edge(20,116).
+edge(116,20).
+edge(20,125).
+edge(125,20).
+edge(20,129).
+edge(129,20).
+edge(20,131).
+edge(131,20).
+edge(21,37).
+edge(37,21).
+edge(21,89).
+edge(89,21).
+edge(21,93).
+edge(93,21).
+edge(21,103).
+edge(103,21).
+edge(21,117).
+edge(117,21).
+edge(21,120).
+edge(120,21).
+edge(21,129).
+edge(129,21).
+edge(21,137).
+edge(137,21).
+edge(21,140).
+edge(140,21).
+edge(22,46).
+edge(46,22).
+edge(22,68).
+edge(68,22).
+edge(22,71).
+edge(71,22).
+edge(22,74).
+edge(74,22).
+edge(22,77).
+edge(77,22).
+edge(22,86).
+edge(86,22).
+edge(22,91).
+edge(91,22).
+edge(22,102).
+edge(102,22).
+edge(22,103).
+edge(103,22).
+edge(22,105).
+edge(105,22).
+edge(22,123).
+edge(123,22).
+edge(22,138).
+edge(138,22).
+edge(23,28).
+edge(28,23).
+edge(23,32).
+edge(32,23).
+edge(23,34).
+edge(34,23).
+edge(23,36).
+edge(36,23).
+edge(23,39).
+edge(39,23).
+edge(23,57).
+edge(57,23).
+edge(23,61).
+edge(61,23).
+edge(23,67).
+edge(67,23).
+edge(23,68).
+edge(68,23).
+edge(23,70).
+edge(70,23).
+edge(23,71).
+edge(71,23).
+edge(23,74).
+edge(74,23).
+edge(23,76).
+edge(76,23).
+edge(23,90).
+edge(90,23).
+edge(23,102).
+edge(102,23).
+edge(23,111).
+edge(111,23).
+edge(23,115).
+edge(115,23).
+edge(23,119).
+edge(119,23).
+edge(23,124).
+edge(124,23).
+edge(23,127).
+edge(127,23).
+edge(23,135).
+edge(135,23).
+edge(23,140).
+edge(140,23).
+edge(24,27).
+edge(27,24).
+edge(24,32).
+edge(32,24).
+edge(24,33).
+edge(33,24).
+edge(24,43).
+edge(43,24).
+edge(24,55).
+edge(55,24).
+edge(24,56).
+edge(56,24).
+edge(24,60).
+edge(60,24).
+edge(24,76).
+edge(76,24).
+edge(24,85).
+edge(85,24).
+edge(24,86).
+edge(86,24).
+edge(24,95).
+edge(95,24).
+edge(24,97).
+edge(97,24).
+edge(24,99).
+edge(99,24).
+edge(24,105).
+edge(105,24).
+edge(24,122).
+edge(122,24).
+edge(25,26).
+edge(26,25).
+edge(25,29).
+edge(29,25).
+edge(25,38).
+edge(38,25).
+edge(25,44).
+edge(44,25).
+edge(25,48).
+edge(48,25).
+edge(25,52).
+edge(52,25).
+edge(25,57).
+edge(57,25).
+edge(25,58).
+edge(58,25).
+edge(25,59).
+edge(59,25).
+edge(25,62).
+edge(62,25).
+edge(25,69).
+edge(69,25).
+edge(25,77).
+edge(77,25).
+edge(25,90).
+edge(90,25).
+edge(25,95).
+edge(95,25).
+edge(25,110).
+edge(110,25).
+edge(25,113).
+edge(113,25).
+edge(25,120).
+edge(120,25).
+edge(25,122).
+edge(122,25).
+edge(25,126).
+edge(126,25).
+edge(25,129).
+edge(129,25).
+edge(25,136).
+edge(136,25).
+edge(26,30).
+edge(30,26).
+edge(26,49).
+edge(49,26).
+edge(26,62).
+edge(62,26).
+edge(26,78).
+edge(78,26).
+edge(26,98).
+edge(98,26).
+edge(26,100).
+edge(100,26).
+edge(26,125).
+edge(125,26).
+edge(26,135).
+edge(135,26).
+edge(26,138).
+edge(138,26).
+edge(27,38).
+edge(38,27).
+edge(27,40).
+edge(40,27).
+edge(27,42).
+edge(42,27).
+edge(27,64).
+edge(64,27).
+edge(27,89).
+edge(89,27).
+edge(27,104).
+edge(104,27).
+edge(27,113).
+edge(113,27).
+edge(27,119).
+edge(119,27).
+edge(27,133).
+edge(133,27).
+edge(27,138).
+edge(138,27).
+edge(28,36).
+edge(36,28).
+edge(28,42).
+edge(42,28).
+edge(28,64).
+edge(64,28).
+edge(28,65).
+edge(65,28).
+edge(28,77).
+edge(77,28).
+edge(28,79).
+edge(79,28).
+edge(28,96).
+edge(96,28).
+edge(28,107).
+edge(107,28).
+edge(28,112).
+edge(112,28).
+edge(28,126).
+edge(126,28).
+edge(29,42).
+edge(42,29).
+edge(29,63).
+edge(63,29).
+edge(29,71).
+edge(71,29).
+edge(29,78).
+edge(78,29).
+edge(29,99).
+edge(99,29).
+edge(29,110).
+edge(110,29).
+edge(29,119).
+edge(119,29).
+edge(29,124).
+edge(124,29).
+edge(30,41).
+edge(41,30).
+edge(30,54).
+edge(54,30).
+edge(30,67).
+edge(67,30).
+edge(30,84).
+edge(84,30).
+edge(30,94).
+edge(94,30).
+edge(30,100).
+edge(100,30).
+edge(30,104).
+edge(104,30).
+edge(30,107).
+edge(107,30).
+edge(30,127).
+edge(127,30).
+edge(30,140).
+edge(140,30).
+edge(31,37).
+edge(37,31).
+edge(31,38).
+edge(38,31).
+edge(31,42).
+edge(42,31).
+edge(31,46).
+edge(46,31).
+edge(31,48).
+edge(48,31).
+edge(31,65).
+edge(65,31).
+edge(31,70).
+edge(70,31).
+edge(31,73).
+edge(73,31).
+edge(31,79).
+edge(79,31).
+edge(31,116).
+edge(116,31).
+edge(31,117).
+edge(117,31).
+edge(32,33).
+edge(33,32).
+edge(32,37).
+edge(37,32).
+edge(32,38).
+edge(38,32).
+edge(32,40).
+edge(40,32).
+edge(32,46).
+edge(46,32).
+edge(32,48).
+edge(48,32).
+edge(32,58).
+edge(58,32).
+edge(32,65).
+edge(65,32).
+edge(32,68).
+edge(68,32).
+edge(32,76).
+edge(76,32).
+edge(32,85).
+edge(85,32).
+edge(32,86).
+edge(86,32).
+edge(32,91).
+edge(91,32).
+edge(32,110).
+edge(110,32).
+edge(32,122).
+edge(122,32).
+edge(32,140).
+edge(140,32).
+edge(33,42).
+edge(42,33).
+edge(33,45).
+edge(45,33).
+edge(33,64).
+edge(64,33).
+edge(33,67).
+edge(67,33).
+edge(33,76).
+edge(76,33).
+edge(33,83).
+edge(83,33).
+edge(33,98).
+edge(98,33).
+edge(33,127).
+edge(127,33).
+edge(33,130).
+edge(130,33).
+edge(33,136).
+edge(136,33).
+edge(34,40).
+edge(40,34).
+edge(34,46).
+edge(46,34).
+edge(34,81).
+edge(81,34).
+edge(34,89).
+edge(89,34).
+edge(34,95).
+edge(95,34).
+edge(34,99).
+edge(99,34).
+edge(34,111).
+edge(111,34).
+edge(34,124).
+edge(124,34).
+edge(34,130).
+edge(130,34).
+edge(34,140).
+edge(140,34).
+edge(35,40).
+edge(40,35).
+edge(35,44).
+edge(44,35).
+edge(35,51).
+edge(51,35).
+edge(35,63).
+edge(63,35).
+edge(35,76).
+edge(76,35).
+edge(35,86).
+edge(86,35).
+edge(35,108).
+edge(108,35).
+edge(35,129).
+edge(129,35).
+edge(35,131).
+edge(131,35).
+edge(36,44).
+edge(44,36).
+edge(36,48).
+edge(48,36).
+edge(36,59).
+edge(59,36).
+edge(36,66).
+edge(66,36).
+edge(36,73).
+edge(73,36).
+edge(36,90).
+edge(90,36).
+edge(36,92).
+edge(92,36).
+edge(36,93).
+edge(93,36).
+edge(36,104).
+edge(104,36).
+edge(36,105).
+edge(105,36).
+edge(36,132).
+edge(132,36).
+edge(36,136).
+edge(136,36).
+edge(37,38).
+edge(38,37).
+edge(37,44).
+edge(44,37).
+edge(37,48).
+edge(48,37).
+edge(37,49).
+edge(49,37).
+edge(37,56).
+edge(56,37).
+edge(37,60).
+edge(60,37).
+edge(37,69).
+edge(69,37).
+edge(37,88).
+edge(88,37).
+edge(37,91).
+edge(91,37).
+edge(37,105).
+edge(105,37).
+edge(37,108).
+edge(108,37).
+edge(37,122).
+edge(122,37).
+edge(37,124).
+edge(124,37).
+edge(37,129).
+edge(129,37).
+edge(37,132).
+edge(132,37).
+edge(38,64).
+edge(64,38).
+edge(38,67).
+edge(67,38).
+edge(38,68).
+edge(68,38).
+edge(38,83).
+edge(83,38).
+edge(38,97).
+edge(97,38).
+edge(38,107).
+edge(107,38).
+edge(38,111).
+edge(111,38).
+edge(38,113).
+edge(113,38).
+edge(38,115).
+edge(115,38).
+edge(38,123).
+edge(123,38).
+edge(38,134).
+edge(134,38).
+edge(39,42).
+edge(42,39).
+edge(39,44).
+edge(44,39).
+edge(39,46).
+edge(46,39).
+edge(39,50).
+edge(50,39).
+edge(39,53).
+edge(53,39).
+edge(39,70).
+edge(70,39).
+edge(39,82).
+edge(82,39).
+edge(39,84).
+edge(84,39).
+edge(39,85).
+edge(85,39).
+edge(39,88).
+edge(88,39).
+edge(39,91).
+edge(91,39).
+edge(39,96).
+edge(96,39).
+edge(39,107).
+edge(107,39).
+edge(39,110).
+edge(110,39).
+edge(39,128).
+edge(128,39).
+edge(39,130).
+edge(130,39).
+edge(40,76).
+edge(76,40).
+edge(40,78).
+edge(78,40).
+edge(40,92).
+edge(92,40).
+edge(40,104).
+edge(104,40).
+edge(40,111).
+edge(111,40).
+edge(40,114).
+edge(114,40).
+edge(40,115).
+edge(115,40).
+edge(40,123).
+edge(123,40).
+edge(40,135).
+edge(135,40).
+edge(41,47).
+edge(47,41).
+edge(41,62).
+edge(62,41).
+edge(41,64).
+edge(64,41).
+edge(41,66).
+edge(66,41).
+edge(41,72).
+edge(72,41).
+edge(41,103).
+edge(103,41).
+edge(41,113).
+edge(113,41).
+edge(41,117).
+edge(117,41).
+edge(41,128).
+edge(128,41).
+edge(41,129).
+edge(129,41).
+edge(42,47).
+edge(47,42).
+edge(42,53).
+edge(53,42).
+edge(42,59).
+edge(59,42).
+edge(42,64).
+edge(64,42).
+edge(42,69).
+edge(69,42).
+edge(42,72).
+edge(72,42).
+edge(42,73).
+edge(73,42).
+edge(42,74).
+edge(74,42).
+edge(42,77).
+edge(77,42).
+edge(42,85).
+edge(85,42).
+edge(42,92).
+edge(92,42).
+edge(42,94).
+edge(94,42).
+edge(42,95).
+edge(95,42).
+edge(42,102).
+edge(102,42).
+edge(42,130).
+edge(130,42).
+edge(43,50).
+edge(50,43).
+edge(43,52).
+edge(52,43).
+edge(43,62).
+edge(62,43).
+edge(43,64).
+edge(64,43).
+edge(43,68).
+edge(68,43).
+edge(43,79).
+edge(79,43).
+edge(43,87).
+edge(87,43).
+edge(43,89).
+edge(89,43).
+edge(43,97).
+edge(97,43).
+edge(43,103).
+edge(103,43).
+edge(43,113).
+edge(113,43).
+edge(43,131).
+edge(131,43).
+edge(43,137).
+edge(137,43).
+edge(44,68).
+edge(68,44).
+edge(44,69).
+edge(69,44).
+edge(44,77).
+edge(77,44).
+edge(44,83).
+edge(83,44).
+edge(44,86).
+edge(86,44).
+edge(44,104).
+edge(104,44).
+edge(44,108).
+edge(108,44).
+edge(44,114).
+edge(114,44).
+edge(44,119).
+edge(119,44).
+edge(44,128).
+edge(128,44).
+edge(45,47).
+edge(47,45).
+edge(45,50).
+edge(50,45).
+edge(45,78).
+edge(78,45).
+edge(45,83).
+edge(83,45).
+edge(45,84).
+edge(84,45).
+edge(45,85).
+edge(85,45).
+edge(45,122).
+edge(122,45).
+edge(45,126).
+edge(126,45).
+edge(45,132).
+edge(132,45).
+edge(45,135).
+edge(135,45).
+edge(45,136).
+edge(136,45).
+edge(45,137).
+edge(137,45).
+edge(45,138).
+edge(138,45).
+edge(46,51).
+edge(51,46).
+edge(46,52).
+edge(52,46).
+edge(46,64).
+edge(64,46).
+edge(46,74).
+edge(74,46).
+edge(46,101).
+edge(101,46).
+edge(46,113).
+edge(113,46).
+edge(46,123).
+edge(123,46).
+edge(47,50).
+edge(50,47).
+edge(47,58).
+edge(58,47).
+edge(47,73).
+edge(73,47).
+edge(47,77).
+edge(77,47).
+edge(47,90).
+edge(90,47).
+edge(47,97).
+edge(97,47).
+edge(47,98).
+edge(98,47).
+edge(47,102).
+edge(102,47).
+edge(47,108).
+edge(108,47).
+edge(47,116).
+edge(116,47).
+edge(48,52).
+edge(52,48).
+edge(48,62).
+edge(62,48).
+edge(48,63).
+edge(63,48).
+edge(48,66).
+edge(66,48).
+edge(48,81).
+edge(81,48).
+edge(48,83).
+edge(83,48).
+edge(48,90).
+edge(90,48).
+edge(48,91).
+edge(91,48).
+edge(48,95).
+edge(95,48).
+edge(48,98).
+edge(98,48).
+edge(48,110).
+edge(110,48).
+edge(48,114).
+edge(114,48).
+edge(48,121).
+edge(121,48).
+edge(48,131).
+edge(131,48).
+edge(49,52).
+edge(52,49).
+edge(49,53).
+edge(53,49).
+edge(49,61).
+edge(61,49).
+edge(49,66).
+edge(66,49).
+edge(49,68).
+edge(68,49).
+edge(49,85).
+edge(85,49).
+edge(49,86).
+edge(86,49).
+edge(49,89).
+edge(89,49).
+edge(49,91).
+edge(91,49).
+edge(49,96).
+edge(96,49).
+edge(49,103).
+edge(103,49).
+edge(49,108).
+edge(108,49).
+edge(49,109).
+edge(109,49).
+edge(50,83).
+edge(83,50).
+edge(50,88).
+edge(88,50).
+edge(50,94).
+edge(94,50).
+edge(50,123).
+edge(123,50).
+edge(50,128).
+edge(128,50).
+edge(50,136).
+edge(136,50).
+edge(50,140).
+edge(140,50).
+edge(51,56).
+edge(56,51).
+edge(51,58).
+edge(58,51).
+edge(51,60).
+edge(60,51).
+edge(51,61).
+edge(61,51).
+edge(51,63).
+edge(63,51).
+edge(51,67).
+edge(67,51).
+edge(51,76).
+edge(76,51).
+edge(51,77).
+edge(77,51).
+edge(51,88).
+edge(88,51).
+edge(51,92).
+edge(92,51).
+edge(51,93).
+edge(93,51).
+edge(51,94).
+edge(94,51).
+edge(51,96).
+edge(96,51).
+edge(51,110).
+edge(110,51).
+edge(51,112).
+edge(112,51).
+edge(51,125).
+edge(125,51).
+edge(51,127).
+edge(127,51).
+edge(51,134).
+edge(134,51).
+edge(52,55).
+edge(55,52).
+edge(52,57).
+edge(57,52).
+edge(52,58).
+edge(58,52).
+edge(52,65).
+edge(65,52).
+edge(52,91).
+edge(91,52).
+edge(52,102).
+edge(102,52).
+edge(52,110).
+edge(110,52).
+edge(52,115).
+edge(115,52).
+edge(52,121).
+edge(121,52).
+edge(52,123).
+edge(123,52).
+edge(52,128).
+edge(128,52).
+edge(52,130).
+edge(130,52).
+edge(52,132).
+edge(132,52).
+edge(53,63).
+edge(63,53).
+edge(53,66).
+edge(66,53).
+edge(53,97).
+edge(97,53).
+edge(54,60).
+edge(60,54).
+edge(54,61).
+edge(61,54).
+edge(54,86).
+edge(86,54).
+edge(54,90).
+edge(90,54).
+edge(54,91).
+edge(91,54).
+edge(54,94).
+edge(94,54).
+edge(54,110).
+edge(110,54).
+edge(54,121).
+edge(121,54).
+edge(54,130).
+edge(130,54).
+edge(55,67).
+edge(67,55).
+edge(55,68).
+edge(68,55).
+edge(55,72).
+edge(72,55).
+edge(55,78).
+edge(78,55).
+edge(55,79).
+edge(79,55).
+edge(55,85).
+edge(85,55).
+edge(55,90).
+edge(90,55).
+edge(55,94).
+edge(94,55).
+edge(55,97).
+edge(97,55).
+edge(55,115).
+edge(115,55).
+edge(55,117).
+edge(117,55).
+edge(55,126).
+edge(126,55).
+edge(55,133).
+edge(133,55).
+edge(55,140).
+edge(140,55).
+edge(56,71).
+edge(71,56).
+edge(56,83).
+edge(83,56).
+edge(56,85).
+edge(85,56).
+edge(56,126).
+edge(126,56).
+edge(56,130).
+edge(130,56).
+edge(57,72).
+edge(72,57).
+edge(57,76).
+edge(76,57).
+edge(57,84).
+edge(84,57).
+edge(57,86).
+edge(86,57).
+edge(57,89).
+edge(89,57).
+edge(57,102).
+edge(102,57).
+edge(57,122).
+edge(122,57).
+edge(57,129).
+edge(129,57).
+edge(57,135).
+edge(135,57).
+edge(57,136).
+edge(136,57).
+edge(58,81).
+edge(81,58).
+edge(58,87).
+edge(87,58).
+edge(58,98).
+edge(98,58).
+edge(58,112).
+edge(112,58).
+edge(58,116).
+edge(116,58).
+edge(58,120).
+edge(120,58).
+edge(59,66).
+edge(66,59).
+edge(59,71).
+edge(71,59).
+edge(59,85).
+edge(85,59).
+edge(59,88).
+edge(88,59).
+edge(59,100).
+edge(100,59).
+edge(59,119).
+edge(119,59).
+edge(59,120).
+edge(120,59).
+edge(59,122).
+edge(122,59).
+edge(59,124).
+edge(124,59).
+edge(59,127).
+edge(127,59).
+edge(59,139).
+edge(139,59).
+edge(60,75).
+edge(75,60).
+edge(60,86).
+edge(86,60).
+edge(60,95).
+edge(95,60).
+edge(60,98).
+edge(98,60).
+edge(60,101).
+edge(101,60).
+edge(60,130).
+edge(130,60).
+edge(61,73).
+edge(73,61).
+edge(61,93).
+edge(93,61).
+edge(61,96).
+edge(96,61).
+edge(61,102).
+edge(102,61).
+edge(61,109).
+edge(109,61).
+edge(61,112).
+edge(112,61).
+edge(61,122).
+edge(122,61).
+edge(61,140).
+edge(140,61).
+edge(62,88).
+edge(88,62).
+edge(62,98).
+edge(98,62).
+edge(62,106).
+edge(106,62).
+edge(62,113).
+edge(113,62).
+edge(62,139).
+edge(139,62).
+edge(63,71).
+edge(71,63).
+edge(63,73).
+edge(73,63).
+edge(63,74).
+edge(74,63).
+edge(63,131).
+edge(131,63).
+edge(64,68).
+edge(68,64).
+edge(64,89).
+edge(89,64).
+edge(64,90).
+edge(90,64).
+edge(64,95).
+edge(95,64).
+edge(64,106).
+edge(106,64).
+edge(64,117).
+edge(117,64).
+edge(64,126).
+edge(126,64).
+edge(64,130).
+edge(130,64).
+edge(64,134).
+edge(134,64).
+edge(64,138).
+edge(138,64).
+edge(65,69).
+edge(69,65).
+edge(65,73).
+edge(73,65).
+edge(65,103).
+edge(103,65).
+edge(65,116).
+edge(116,65).
+edge(65,123).
+edge(123,65).
+edge(65,138).
+edge(138,65).
+edge(66,67).
+edge(67,66).
+edge(66,75).
+edge(75,66).
+edge(66,77).
+edge(77,66).
+edge(66,79).
+edge(79,66).
+edge(66,83).
+edge(83,66).
+edge(66,89).
+edge(89,66).
+edge(66,100).
+edge(100,66).
+edge(66,102).
+edge(102,66).
+edge(66,105).
+edge(105,66).
+edge(66,115).
+edge(115,66).
+edge(66,118).
+edge(118,66).
+edge(66,133).
+edge(133,66).
+edge(66,134).
+edge(134,66).
+edge(66,137).
+edge(137,66).
+edge(67,119).
+edge(119,67).
+edge(67,126).
+edge(126,67).
+edge(67,128).
+edge(128,67).
+edge(67,129).
+edge(129,67).
+edge(67,130).
+edge(130,67).
+edge(67,140).
+edge(140,67).
+edge(68,70).
+edge(70,68).
+edge(68,86).
+edge(86,68).
+edge(68,93).
+edge(93,68).
+edge(68,96).
+edge(96,68).
+edge(68,98).
+edge(98,68).
+edge(68,114).
+edge(114,68).
+edge(68,119).
+edge(119,68).
+edge(68,124).
+edge(124,68).
+edge(68,126).
+edge(126,68).
+edge(68,131).
+edge(131,68).
+edge(69,85).
+edge(85,69).
+edge(69,101).
+edge(101,69).
+edge(69,102).
+edge(102,69).
+edge(69,111).
+edge(111,69).
+edge(69,130).
+edge(130,69).
+edge(69,139).
+edge(139,69).
+edge(70,90).
+edge(90,70).
+edge(70,102).
+edge(102,70).
+edge(70,120).
+edge(120,70).
+edge(70,129).
+edge(129,70).
+edge(70,138).
+edge(138,70).
+edge(70,140).
+edge(140,70).
+edge(71,82).
+edge(82,71).
+edge(71,85).
+edge(85,71).
+edge(71,93).
+edge(93,71).
+edge(71,116).
+edge(116,71).
+edge(71,118).
+edge(118,71).
+edge(71,137).
+edge(137,71).
+edge(71,140).
+edge(140,71).
+edge(72,78).
+edge(78,72).
+edge(72,82).
+edge(82,72).
+edge(72,85).
+edge(85,72).
+edge(72,93).
+edge(93,72).
+edge(72,100).
+edge(100,72).
+edge(72,112).
+edge(112,72).
+edge(72,119).
+edge(119,72).
+edge(72,139).
+edge(139,72).
+edge(73,77).
+edge(77,73).
+edge(73,81).
+edge(81,73).
+edge(73,82).
+edge(82,73).
+edge(73,116).
+edge(116,73).
+edge(74,75).
+edge(75,74).
+edge(74,78).
+edge(78,74).
+edge(74,89).
+edge(89,74).
+edge(74,97).
+edge(97,74).
+edge(74,105).
+edge(105,74).
+edge(74,110).
+edge(110,74).
+edge(74,114).
+edge(114,74).
+edge(74,116).
+edge(116,74).
+edge(74,123).
+edge(123,74).
+edge(74,129).
+edge(129,74).
+edge(75,79).
+edge(79,75).
+edge(75,88).
+edge(88,75).
+edge(75,102).
+edge(102,75).
+edge(75,105).
+edge(105,75).
+edge(75,112).
+edge(112,75).
+edge(75,113).
+edge(113,75).
+edge(75,115).
+edge(115,75).
+edge(75,135).
+edge(135,75).
+edge(75,136).
+edge(136,75).
+edge(75,139).
+edge(139,75).
+edge(76,82).
+edge(82,76).
+edge(76,109).
+edge(109,76).
+edge(76,110).
+edge(110,76).
+edge(76,112).
+edge(112,76).
+edge(76,114).
+edge(114,76).
+edge(76,123).
+edge(123,76).
+edge(76,127).
+edge(127,76).
+edge(76,130).
+edge(130,76).
+edge(77,85).
+edge(85,77).
+edge(77,91).
+edge(91,77).
+edge(77,104).
+edge(104,77).
+edge(77,108).
+edge(108,77).
+edge(77,117).
+edge(117,77).
+edge(77,124).
+edge(124,77).
+edge(77,140).
+edge(140,77).
+edge(78,92).
+edge(92,78).
+edge(78,105).
+edge(105,78).
+edge(78,109).
+edge(109,78).
+edge(78,113).
+edge(113,78).
+edge(78,122).
+edge(122,78).
+edge(78,135).
+edge(135,78).
+edge(78,140).
+edge(140,78).
+edge(79,80).
+edge(80,79).
+edge(79,83).
+edge(83,79).
+edge(79,98).
+edge(98,79).
+edge(79,99).
+edge(99,79).
+edge(79,106).
+edge(106,79).
+edge(79,136).
+edge(136,79).
+edge(79,137).
+edge(137,79).
+edge(80,87).
+edge(87,80).
+edge(80,90).
+edge(90,80).
+edge(80,94).
+edge(94,80).
+edge(80,95).
+edge(95,80).
+edge(80,109).
+edge(109,80).
+edge(80,140).
+edge(140,80).
+edge(81,83).
+edge(83,81).
+edge(81,84).
+edge(84,81).
+edge(81,87).
+edge(87,81).
+edge(81,98).
+edge(98,81).
+edge(81,103).
+edge(103,81).
+edge(81,110).
+edge(110,81).
+edge(81,140).
+edge(140,81).
+edge(82,124).
+edge(124,82).
+edge(82,135).
+edge(135,82).
+edge(83,90).
+edge(90,83).
+edge(83,100).
+edge(100,83).
+edge(83,104).
+edge(104,83).
+edge(83,108).
+edge(108,83).
+edge(83,115).
+edge(115,83).
+edge(83,120).
+edge(120,83).
+edge(83,137).
+edge(137,83).
+edge(84,103).
+edge(103,84).
+edge(84,107).
+edge(107,84).
+edge(84,111).
+edge(111,84).
+edge(84,116).
+edge(116,84).
+edge(84,125).
+edge(125,84).
+edge(84,128).
+edge(128,84).
+edge(84,136).
+edge(136,84).
+edge(85,102).
+edge(102,85).
+edge(85,105).
+edge(105,85).
+edge(85,111).
+edge(111,85).
+edge(85,119).
+edge(119,85).
+edge(85,122).
+edge(122,85).
+edge(85,126).
+edge(126,85).
+edge(85,131).
+edge(131,85).
+edge(85,140).
+edge(140,85).
+edge(86,112).
+edge(112,86).
+edge(86,115).
+edge(115,86).
+edge(86,131).
+edge(131,86).
+edge(86,134).
+edge(134,86).
+edge(87,90).
+edge(90,87).
+edge(87,97).
+edge(97,87).
+edge(87,100).
+edge(100,87).
+edge(88,96).
+edge(96,88).
+edge(89,92).
+edge(92,89).
+edge(89,107).
+edge(107,89).
+edge(89,137).
+edge(137,89).
+edge(89,139).
+edge(139,89).
+edge(90,92).
+edge(92,90).
+edge(90,96).
+edge(96,90).
+edge(90,102).
+edge(102,90).
+edge(90,103).
+edge(103,90).
+edge(90,107).
+edge(107,90).
+edge(91,107).
+edge(107,91).
+edge(91,110).
+edge(110,91).
+edge(91,115).
+edge(115,91).
+edge(91,120).
+edge(120,91).
+edge(91,132).
+edge(132,91).
+edge(91,138).
+edge(138,91).
+edge(91,139).
+edge(139,91).
+edge(92,94).
+edge(94,92).
+edge(92,96).
+edge(96,92).
+edge(92,102).
+edge(102,92).
+edge(92,113).
+edge(113,92).
+edge(92,127).
+edge(127,92).
+edge(92,133).
+edge(133,92).
+edge(92,135).
+edge(135,92).
+edge(93,95).
+edge(95,93).
+edge(93,131).
+edge(131,93).
+edge(93,136).
+edge(136,93).
+edge(93,140).
+edge(140,93).
+edge(94,96).
+edge(96,94).
+edge(94,131).
+edge(131,94).
+edge(95,109).
+edge(109,95).
+edge(95,110).
+edge(110,95).
+edge(95,111).
+edge(111,95).
+edge(95,122).
+edge(122,95).
+edge(95,135).
+edge(135,95).
+edge(96,104).
+edge(104,96).
+edge(96,114).
+edge(114,96).
+edge(96,119).
+edge(119,96).
+edge(96,126).
+edge(126,96).
+edge(96,137).
+edge(137,96).
+edge(97,120).
+edge(120,97).
+edge(97,125).
+edge(125,97).
+edge(98,104).
+edge(104,98).
+edge(98,109).
+edge(109,98).
+edge(98,119).
+edge(119,98).
+edge(98,136).
+edge(136,98).
+edge(99,128).
+edge(128,99).
+edge(99,132).
+edge(132,99).
+edge(99,133).
+edge(133,99).
+edge(100,103).
+edge(103,100).
+edge(100,109).
+edge(109,100).
+edge(100,131).
+edge(131,100).
+edge(100,140).
+edge(140,100).
+edge(101,102).
+edge(102,101).
+edge(101,111).
+edge(111,101).
+edge(101,128).
+edge(128,101).
+edge(101,133).
+edge(133,101).
+edge(101,139).
+edge(139,101).
+edge(102,103).
+edge(103,102).
+edge(102,108).
+edge(108,102).
+edge(102,111).
+edge(111,102).
+edge(102,126).
+edge(126,102).
+edge(102,127).
+edge(127,102).
+edge(102,134).
+edge(134,102).
+edge(103,104).
+edge(104,103).
+edge(103,123).
+edge(123,103).
+edge(104,105).
+edge(105,104).
+edge(104,110).
+edge(110,104).
+edge(104,119).
+edge(119,104).
+edge(104,120).
+edge(120,104).
+edge(104,128).
+edge(128,104).
+edge(105,128).
+edge(128,105).
+edge(106,111).
+edge(111,106).
+edge(106,123).
+edge(123,106).
+edge(107,119).
+edge(119,107).
+edge(107,127).
+edge(127,107).
+edge(108,127).
+edge(127,108).
+edge(108,131).
+edge(131,108).
+edge(109,110).
+edge(110,109).
+edge(109,114).
+edge(114,109).
+edge(109,120).
+edge(120,109).
+edge(109,121).
+edge(121,109).
+edge(109,124).
+edge(124,109).
+edge(109,133).
+edge(133,109).
+edge(109,135).
+edge(135,109).
+edge(109,136).
+edge(136,109).
+edge(109,137).
+edge(137,109).
+edge(110,119).
+edge(119,110).
+edge(110,124).
+edge(124,110).
+edge(110,137).
+edge(137,110).
+edge(111,119).
+edge(119,111).
+edge(111,120).
+edge(120,111).
+edge(111,122).
+edge(122,111).
+edge(111,124).
+edge(124,111).
+edge(111,129).
+edge(129,111).
+edge(112,121).
+edge(121,112).
+edge(112,124).
+edge(124,112).
+edge(112,129).
+edge(129,112).
+edge(112,131).
+edge(131,112).
+edge(112,133).
+edge(133,112).
+edge(113,121).
+edge(121,113).
+edge(113,129).
+edge(129,113).
+edge(113,131).
+edge(131,113).
+edge(113,132).
+edge(132,113).
+edge(114,120).
+edge(120,114).
+edge(115,132).
+edge(132,115).
+edge(117,118).
+edge(118,117).
+edge(117,133).
+edge(133,117).
+edge(118,129).
+edge(129,118).
+edge(118,135).
+edge(135,118).
+edge(119,132).
+edge(132,119).
+edge(120,125).
+edge(125,120).
+edge(120,128).
+edge(128,120).
+edge(120,140).
+edge(140,120).
+edge(121,130).
+edge(130,121).
+edge(121,135).
+edge(135,121).
+edge(121,139).
+edge(139,121).
+edge(123,133).
+edge(133,123).
+edge(123,136).
+edge(136,123).
+edge(124,132).
+edge(132,124).
+edge(125,128).
+edge(128,125).
+edge(126,134).
+edge(134,126).
+edge(127,130).
+edge(130,127).
+edge(127,138).
+edge(138,127).
+edge(129,135).
+edge(135,129).
+edge(129,136).
+edge(136,129).
+edge(130,134).
+edge(134,130).
+edge(130,135).
+edge(135,130).
+edge(133,134).
+edge(134,133).
+edge(133,136).
+edge(136,133).
+edge(133,138).
+edge(138,133).
+edge(133,139).
+edge(139,133).
+edge(134,136).
+edge(136,134).
+edge(136,137).
+edge(137,136).
+edge(136,139).
+edge(139,136).
+edge(138,139).
+edge(139,138).
+edge(139,140).
+edge(140,139).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0036-graph_colouring-140-0.lp b/examples/clingo/expansion/GraphColouring/instances/0036-graph_colouring-140-0.lp
new file mode 100644
index 0000000..56021ab
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0036-graph_colouring-140-0.lp
@@ -0,0 +1,2126 @@
+#const n=140.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+edge(1,16).
+edge(16,1).
+edge(1,52).
+edge(52,1).
+edge(1,68).
+edge(68,1).
+edge(1,79).
+edge(79,1).
+edge(1,81).
+edge(81,1).
+edge(1,87).
+edge(87,1).
+edge(1,99).
+edge(99,1).
+edge(1,118).
+edge(118,1).
+edge(1,135).
+edge(135,1).
+edge(1,136).
+edge(136,1).
+edge(2,5).
+edge(5,2).
+edge(2,20).
+edge(20,2).
+edge(2,22).
+edge(22,2).
+edge(2,37).
+edge(37,2).
+edge(2,47).
+edge(47,2).
+edge(2,72).
+edge(72,2).
+edge(2,74).
+edge(74,2).
+edge(2,101).
+edge(101,2).
+edge(2,128).
+edge(128,2).
+edge(2,131).
+edge(131,2).
+edge(3,19).
+edge(19,3).
+edge(3,22).
+edge(22,3).
+edge(3,24).
+edge(24,3).
+edge(3,33).
+edge(33,3).
+edge(3,44).
+edge(44,3).
+edge(3,58).
+edge(58,3).
+edge(3,63).
+edge(63,3).
+edge(3,65).
+edge(65,3).
+edge(3,115).
+edge(115,3).
+edge(3,119).
+edge(119,3).
+edge(4,27).
+edge(27,4).
+edge(4,33).
+edge(33,4).
+edge(4,38).
+edge(38,4).
+edge(4,42).
+edge(42,4).
+edge(4,56).
+edge(56,4).
+edge(4,60).
+edge(60,4).
+edge(4,65).
+edge(65,4).
+edge(4,67).
+edge(67,4).
+edge(4,80).
+edge(80,4).
+edge(4,83).
+edge(83,4).
+edge(4,87).
+edge(87,4).
+edge(4,103).
+edge(103,4).
+edge(4,120).
+edge(120,4).
+edge(4,121).
+edge(121,4).
+edge(4,137).
+edge(137,4).
+edge(5,14).
+edge(14,5).
+edge(5,21).
+edge(21,5).
+edge(5,42).
+edge(42,5).
+edge(5,50).
+edge(50,5).
+edge(5,62).
+edge(62,5).
+edge(5,72).
+edge(72,5).
+edge(5,83).
+edge(83,5).
+edge(5,87).
+edge(87,5).
+edge(5,116).
+edge(116,5).
+edge(5,121).
+edge(121,5).
+edge(5,126).
+edge(126,5).
+edge(5,128).
+edge(128,5).
+edge(6,10).
+edge(10,6).
+edge(6,26).
+edge(26,6).
+edge(6,27).
+edge(27,6).
+edge(6,40).
+edge(40,6).
+edge(6,52).
+edge(52,6).
+edge(6,54).
+edge(54,6).
+edge(6,58).
+edge(58,6).
+edge(6,59).
+edge(59,6).
+edge(6,65).
+edge(65,6).
+edge(6,127).
+edge(127,6).
+edge(6,134).
+edge(134,6).
+edge(6,135).
+edge(135,6).
+edge(6,137).
+edge(137,6).
+edge(6,140).
+edge(140,6).
+edge(7,48).
+edge(48,7).
+edge(7,58).
+edge(58,7).
+edge(7,139).
+edge(139,7).
+edge(7,140).
+edge(140,7).
+edge(8,9).
+edge(9,8).
+edge(8,12).
+edge(12,8).
+edge(8,13).
+edge(13,8).
+edge(8,16).
+edge(16,8).
+edge(8,18).
+edge(18,8).
+edge(8,22).
+edge(22,8).
+edge(8,40).
+edge(40,8).
+edge(8,52).
+edge(52,8).
+edge(8,53).
+edge(53,8).
+edge(8,56).
+edge(56,8).
+edge(8,76).
+edge(76,8).
+edge(8,85).
+edge(85,8).
+edge(8,95).
+edge(95,8).
+edge(8,102).
+edge(102,8).
+edge(8,104).
+edge(104,8).
+edge(8,115).
+edge(115,8).
+edge(8,117).
+edge(117,8).
+edge(8,122).
+edge(122,8).
+edge(9,15).
+edge(15,9).
+edge(9,27).
+edge(27,9).
+edge(9,31).
+edge(31,9).
+edge(9,32).
+edge(32,9).
+edge(9,52).
+edge(52,9).
+edge(9,57).
+edge(57,9).
+edge(9,89).
+edge(89,9).
+edge(9,92).
+edge(92,9).
+edge(9,99).
+edge(99,9).
+edge(9,104).
+edge(104,9).
+edge(9,109).
+edge(109,9).
+edge(9,112).
+edge(112,9).
+edge(9,119).
+edge(119,9).
+edge(9,130).
+edge(130,9).
+edge(9,137).
+edge(137,9).
+edge(10,23).
+edge(23,10).
+edge(10,25).
+edge(25,10).
+edge(10,96).
+edge(96,10).
+edge(10,111).
+edge(111,10).
+edge(10,131).
+edge(131,10).
+edge(11,22).
+edge(22,11).
+edge(11,39).
+edge(39,11).
+edge(11,41).
+edge(41,11).
+edge(11,55).
+edge(55,11).
+edge(11,57).
+edge(57,11).
+edge(11,79).
+edge(79,11).
+edge(11,83).
+edge(83,11).
+edge(11,90).
+edge(90,11).
+edge(11,96).
+edge(96,11).
+edge(11,104).
+edge(104,11).
+edge(11,114).
+edge(114,11).
+edge(11,122).
+edge(122,11).
+edge(11,127).
+edge(127,11).
+edge(11,138).
+edge(138,11).
+edge(12,18).
+edge(18,12).
+edge(12,35).
+edge(35,12).
+edge(12,36).
+edge(36,12).
+edge(12,51).
+edge(51,12).
+edge(12,55).
+edge(55,12).
+edge(12,56).
+edge(56,12).
+edge(12,68).
+edge(68,12).
+edge(12,70).
+edge(70,12).
+edge(12,91).
+edge(91,12).
+edge(12,103).
+edge(103,12).
+edge(12,128).
+edge(128,12).
+edge(12,138).
+edge(138,12).
+edge(13,53).
+edge(53,13).
+edge(13,57).
+edge(57,13).
+edge(13,62).
+edge(62,13).
+edge(13,83).
+edge(83,13).
+edge(13,97).
+edge(97,13).
+edge(13,125).
+edge(125,13).
+edge(13,131).
+edge(131,13).
+edge(13,134).
+edge(134,13).
+edge(13,138).
+edge(138,13).
+edge(14,16).
+edge(16,14).
+edge(14,23).
+edge(23,14).
+edge(14,30).
+edge(30,14).
+edge(14,34).
+edge(34,14).
+edge(14,43).
+edge(43,14).
+edge(14,58).
+edge(58,14).
+edge(14,65).
+edge(65,14).
+edge(14,82).
+edge(82,14).
+edge(14,87).
+edge(87,14).
+edge(14,92).
+edge(92,14).
+edge(14,105).
+edge(105,14).
+edge(14,125).
+edge(125,14).
+edge(14,131).
+edge(131,14).
+edge(14,135).
+edge(135,14).
+edge(15,20).
+edge(20,15).
+edge(15,22).
+edge(22,15).
+edge(15,40).
+edge(40,15).
+edge(15,50).
+edge(50,15).
+edge(15,64).
+edge(64,15).
+edge(15,65).
+edge(65,15).
+edge(15,70).
+edge(70,15).
+edge(15,81).
+edge(81,15).
+edge(15,123).
+edge(123,15).
+edge(16,18).
+edge(18,16).
+edge(16,29).
+edge(29,16).
+edge(16,40).
+edge(40,16).
+edge(16,46).
+edge(46,16).
+edge(16,67).
+edge(67,16).
+edge(16,68).
+edge(68,16).
+edge(16,103).
+edge(103,16).
+edge(16,106).
+edge(106,16).
+edge(16,118).
+edge(118,16).
+edge(16,120).
+edge(120,16).
+edge(16,130).
+edge(130,16).
+edge(16,131).
+edge(131,16).
+edge(17,20).
+edge(20,17).
+edge(17,40).
+edge(40,17).
+edge(17,45).
+edge(45,17).
+edge(17,65).
+edge(65,17).
+edge(17,89).
+edge(89,17).
+edge(17,90).
+edge(90,17).
+edge(17,95).
+edge(95,17).
+edge(17,96).
+edge(96,17).
+edge(17,108).
+edge(108,17).
+edge(17,109).
+edge(109,17).
+edge(17,120).
+edge(120,17).
+edge(17,125).
+edge(125,17).
+edge(17,131).
+edge(131,17).
+edge(17,139).
+edge(139,17).
+edge(18,26).
+edge(26,18).
+edge(18,43).
+edge(43,18).
+edge(18,62).
+edge(62,18).
+edge(18,64).
+edge(64,18).
+edge(18,88).
+edge(88,18).
+edge(18,98).
+edge(98,18).
+edge(18,102).
+edge(102,18).
+edge(18,138).
+edge(138,18).
+edge(19,30).
+edge(30,19).
+edge(19,31).
+edge(31,19).
+edge(19,38).
+edge(38,19).
+edge(19,51).
+edge(51,19).
+edge(19,54).
+edge(54,19).
+edge(19,57).
+edge(57,19).
+edge(19,59).
+edge(59,19).
+edge(19,65).
+edge(65,19).
+edge(19,74).
+edge(74,19).
+edge(19,98).
+edge(98,19).
+edge(19,103).
+edge(103,19).
+edge(19,119).
+edge(119,19).
+edge(19,136).
+edge(136,19).
+edge(20,31).
+edge(31,20).
+edge(20,36).
+edge(36,20).
+edge(20,46).
+edge(46,20).
+edge(20,48).
+edge(48,20).
+edge(20,69).
+edge(69,20).
+edge(20,70).
+edge(70,20).
+edge(20,78).
+edge(78,20).
+edge(20,86).
+edge(86,20).
+edge(20,92).
+edge(92,20).
+edge(20,94).
+edge(94,20).
+edge(20,102).
+edge(102,20).
+edge(20,103).
+edge(103,20).
+edge(20,104).
+edge(104,20).
+edge(20,105).
+edge(105,20).
+edge(20,110).
+edge(110,20).
+edge(20,112).
+edge(112,20).
+edge(20,116).
+edge(116,20).
+edge(20,120).
+edge(120,20).
+edge(20,121).
+edge(121,20).
+edge(20,124).
+edge(124,20).
+edge(20,126).
+edge(126,20).
+edge(20,132).
+edge(132,20).
+edge(21,23).
+edge(23,21).
+edge(21,43).
+edge(43,21).
+edge(21,49).
+edge(49,21).
+edge(21,52).
+edge(52,21).
+edge(21,54).
+edge(54,21).
+edge(21,64).
+edge(64,21).
+edge(21,67).
+edge(67,21).
+edge(21,73).
+edge(73,21).
+edge(21,78).
+edge(78,21).
+edge(21,83).
+edge(83,21).
+edge(21,113).
+edge(113,21).
+edge(21,115).
+edge(115,21).
+edge(21,132).
+edge(132,21).
+edge(21,138).
+edge(138,21).
+edge(22,38).
+edge(38,22).
+edge(22,40).
+edge(40,22).
+edge(22,56).
+edge(56,22).
+edge(22,69).
+edge(69,22).
+edge(22,107).
+edge(107,22).
+edge(22,111).
+edge(111,22).
+edge(22,118).
+edge(118,22).
+edge(23,27).
+edge(27,23).
+edge(23,28).
+edge(28,23).
+edge(23,45).
+edge(45,23).
+edge(23,52).
+edge(52,23).
+edge(23,58).
+edge(58,23).
+edge(23,68).
+edge(68,23).
+edge(23,77).
+edge(77,23).
+edge(23,100).
+edge(100,23).
+edge(23,104).
+edge(104,23).
+edge(23,107).
+edge(107,23).
+edge(23,108).
+edge(108,23).
+edge(23,116).
+edge(116,23).
+edge(23,117).
+edge(117,23).
+edge(23,123).
+edge(123,23).
+edge(23,135).
+edge(135,23).
+edge(24,27).
+edge(27,24).
+edge(24,28).
+edge(28,24).
+edge(24,31).
+edge(31,24).
+edge(24,43).
+edge(43,24).
+edge(24,48).
+edge(48,24).
+edge(24,53).
+edge(53,24).
+edge(24,66).
+edge(66,24).
+edge(24,77).
+edge(77,24).
+edge(24,78).
+edge(78,24).
+edge(24,107).
+edge(107,24).
+edge(24,125).
+edge(125,24).
+edge(24,131).
+edge(131,24).
+edge(24,134).
+edge(134,24).
+edge(24,135).
+edge(135,24).
+edge(25,41).
+edge(41,25).
+edge(25,42).
+edge(42,25).
+edge(25,53).
+edge(53,25).
+edge(25,56).
+edge(56,25).
+edge(25,69).
+edge(69,25).
+edge(25,75).
+edge(75,25).
+edge(25,79).
+edge(79,25).
+edge(25,82).
+edge(82,25).
+edge(25,103).
+edge(103,25).
+edge(25,126).
+edge(126,25).
+edge(26,32).
+edge(32,26).
+edge(26,45).
+edge(45,26).
+edge(26,46).
+edge(46,26).
+edge(26,50).
+edge(50,26).
+edge(26,58).
+edge(58,26).
+edge(26,61).
+edge(61,26).
+edge(26,65).
+edge(65,26).
+edge(26,72).
+edge(72,26).
+edge(26,80).
+edge(80,26).
+edge(26,83).
+edge(83,26).
+edge(26,91).
+edge(91,26).
+edge(26,97).
+edge(97,26).
+edge(26,111).
+edge(111,26).
+edge(26,117).
+edge(117,26).
+edge(26,120).
+edge(120,26).
+edge(26,132).
+edge(132,26).
+edge(26,133).
+edge(133,26).
+edge(26,134).
+edge(134,26).
+edge(27,35).
+edge(35,27).
+edge(27,53).
+edge(53,27).
+edge(27,67).
+edge(67,27).
+edge(27,75).
+edge(75,27).
+edge(27,84).
+edge(84,27).
+edge(27,94).
+edge(94,27).
+edge(27,122).
+edge(122,27).
+edge(27,129).
+edge(129,27).
+edge(27,135).
+edge(135,27).
+edge(27,139).
+edge(139,27).
+edge(28,35).
+edge(35,28).
+edge(28,38).
+edge(38,28).
+edge(28,45).
+edge(45,28).
+edge(28,57).
+edge(57,28).
+edge(28,68).
+edge(68,28).
+edge(28,100).
+edge(100,28).
+edge(28,105).
+edge(105,28).
+edge(28,111).
+edge(111,28).
+edge(28,112).
+edge(112,28).
+edge(28,113).
+edge(113,28).
+edge(28,124).
+edge(124,28).
+edge(28,126).
+edge(126,28).
+edge(28,135).
+edge(135,28).
+edge(29,48).
+edge(48,29).
+edge(29,58).
+edge(58,29).
+edge(29,61).
+edge(61,29).
+edge(29,76).
+edge(76,29).
+edge(29,81).
+edge(81,29).
+edge(29,84).
+edge(84,29).
+edge(29,86).
+edge(86,29).
+edge(29,91).
+edge(91,29).
+edge(29,95).
+edge(95,29).
+edge(29,122).
+edge(122,29).
+edge(30,32).
+edge(32,30).
+edge(30,33).
+edge(33,30).
+edge(30,52).
+edge(52,30).
+edge(30,54).
+edge(54,30).
+edge(30,55).
+edge(55,30).
+edge(30,56).
+edge(56,30).
+edge(30,84).
+edge(84,30).
+edge(30,86).
+edge(86,30).
+edge(30,90).
+edge(90,30).
+edge(30,94).
+edge(94,30).
+edge(30,105).
+edge(105,30).
+edge(30,110).
+edge(110,30).
+edge(30,111).
+edge(111,30).
+edge(30,120).
+edge(120,30).
+edge(30,125).
+edge(125,30).
+edge(31,48).
+edge(48,31).
+edge(31,50).
+edge(50,31).
+edge(31,60).
+edge(60,31).
+edge(31,81).
+edge(81,31).
+edge(31,98).
+edge(98,31).
+edge(31,108).
+edge(108,31).
+edge(31,125).
+edge(125,31).
+edge(31,138).
+edge(138,31).
+edge(32,54).
+edge(54,32).
+edge(32,61).
+edge(61,32).
+edge(32,67).
+edge(67,32).
+edge(32,75).
+edge(75,32).
+edge(32,81).
+edge(81,32).
+edge(32,82).
+edge(82,32).
+edge(32,84).
+edge(84,32).
+edge(32,92).
+edge(92,32).
+edge(32,97).
+edge(97,32).
+edge(32,104).
+edge(104,32).
+edge(32,120).
+edge(120,32).
+edge(32,136).
+edge(136,32).
+edge(33,57).
+edge(57,33).
+edge(33,58).
+edge(58,33).
+edge(33,64).
+edge(64,33).
+edge(33,80).
+edge(80,33).
+edge(33,87).
+edge(87,33).
+edge(33,91).
+edge(91,33).
+edge(33,96).
+edge(96,33).
+edge(33,99).
+edge(99,33).
+edge(33,107).
+edge(107,33).
+edge(33,111).
+edge(111,33).
+edge(33,117).
+edge(117,33).
+edge(33,123).
+edge(123,33).
+edge(33,126).
+edge(126,33).
+edge(33,129).
+edge(129,33).
+edge(34,42).
+edge(42,34).
+edge(34,60).
+edge(60,34).
+edge(34,75).
+edge(75,34).
+edge(34,92).
+edge(92,34).
+edge(34,95).
+edge(95,34).
+edge(34,98).
+edge(98,34).
+edge(34,103).
+edge(103,34).
+edge(34,106).
+edge(106,34).
+edge(34,111).
+edge(111,34).
+edge(34,124).
+edge(124,34).
+edge(34,130).
+edge(130,34).
+edge(34,131).
+edge(131,34).
+edge(34,137).
+edge(137,34).
+edge(35,44).
+edge(44,35).
+edge(35,48).
+edge(48,35).
+edge(35,53).
+edge(53,35).
+edge(35,63).
+edge(63,35).
+edge(35,70).
+edge(70,35).
+edge(35,76).
+edge(76,35).
+edge(35,80).
+edge(80,35).
+edge(35,82).
+edge(82,35).
+edge(35,105).
+edge(105,35).
+edge(35,106).
+edge(106,35).
+edge(35,115).
+edge(115,35).
+edge(35,122).
+edge(122,35).
+edge(35,129).
+edge(129,35).
+edge(36,39).
+edge(39,36).
+edge(36,51).
+edge(51,36).
+edge(36,56).
+edge(56,36).
+edge(36,62).
+edge(62,36).
+edge(36,67).
+edge(67,36).
+edge(36,104).
+edge(104,36).
+edge(36,114).
+edge(114,36).
+edge(36,115).
+edge(115,36).
+edge(36,117).
+edge(117,36).
+edge(36,122).
+edge(122,36).
+edge(36,123).
+edge(123,36).
+edge(36,130).
+edge(130,36).
+edge(36,136).
+edge(136,36).
+edge(36,138).
+edge(138,36).
+edge(37,50).
+edge(50,37).
+edge(37,60).
+edge(60,37).
+edge(37,61).
+edge(61,37).
+edge(37,100).
+edge(100,37).
+edge(37,105).
+edge(105,37).
+edge(37,138).
+edge(138,37).
+edge(38,45).
+edge(45,38).
+edge(38,47).
+edge(47,38).
+edge(38,52).
+edge(52,38).
+edge(38,88).
+edge(88,38).
+edge(38,89).
+edge(89,38).
+edge(38,116).
+edge(116,38).
+edge(38,123).
+edge(123,38).
+edge(38,137).
+edge(137,38).
+edge(39,45).
+edge(45,39).
+edge(39,58).
+edge(58,39).
+edge(39,63).
+edge(63,39).
+edge(39,67).
+edge(67,39).
+edge(39,81).
+edge(81,39).
+edge(39,86).
+edge(86,39).
+edge(39,89).
+edge(89,39).
+edge(39,91).
+edge(91,39).
+edge(39,101).
+edge(101,39).
+edge(39,105).
+edge(105,39).
+edge(39,106).
+edge(106,39).
+edge(39,128).
+edge(128,39).
+edge(39,130).
+edge(130,39).
+edge(40,42).
+edge(42,40).
+edge(40,45).
+edge(45,40).
+edge(40,63).
+edge(63,40).
+edge(40,80).
+edge(80,40).
+edge(40,81).
+edge(81,40).
+edge(40,85).
+edge(85,40).
+edge(40,86).
+edge(86,40).
+edge(40,92).
+edge(92,40).
+edge(40,93).
+edge(93,40).
+edge(40,98).
+edge(98,40).
+edge(40,108).
+edge(108,40).
+edge(40,110).
+edge(110,40).
+edge(40,112).
+edge(112,40).
+edge(40,114).
+edge(114,40).
+edge(40,120).
+edge(120,40).
+edge(40,135).
+edge(135,40).
+edge(41,42).
+edge(42,41).
+edge(41,69).
+edge(69,41).
+edge(41,80).
+edge(80,41).
+edge(41,93).
+edge(93,41).
+edge(41,97).
+edge(97,41).
+edge(41,99).
+edge(99,41).
+edge(41,106).
+edge(106,41).
+edge(41,113).
+edge(113,41).
+edge(41,114).
+edge(114,41).
+edge(41,119).
+edge(119,41).
+edge(41,125).
+edge(125,41).
+edge(41,131).
+edge(131,41).
+edge(41,140).
+edge(140,41).
+edge(42,52).
+edge(52,42).
+edge(42,61).
+edge(61,42).
+edge(42,64).
+edge(64,42).
+edge(42,71).
+edge(71,42).
+edge(42,78).
+edge(78,42).
+edge(42,82).
+edge(82,42).
+edge(42,93).
+edge(93,42).
+edge(42,96).
+edge(96,42).
+edge(42,99).
+edge(99,42).
+edge(42,114).
+edge(114,42).
+edge(42,129).
+edge(129,42).
+edge(42,136).
+edge(136,42).
+edge(43,54).
+edge(54,43).
+edge(43,61).
+edge(61,43).
+edge(43,71).
+edge(71,43).
+edge(43,77).
+edge(77,43).
+edge(43,79).
+edge(79,43).
+edge(43,82).
+edge(82,43).
+edge(43,84).
+edge(84,43).
+edge(43,91).
+edge(91,43).
+edge(43,99).
+edge(99,43).
+edge(43,101).
+edge(101,43).
+edge(43,107).
+edge(107,43).
+edge(43,130).
+edge(130,43).
+edge(43,139).
+edge(139,43).
+edge(44,45).
+edge(45,44).
+edge(44,47).
+edge(47,44).
+edge(44,64).
+edge(64,44).
+edge(44,71).
+edge(71,44).
+edge(44,88).
+edge(88,44).
+edge(44,90).
+edge(90,44).
+edge(44,93).
+edge(93,44).
+edge(44,101).
+edge(101,44).
+edge(44,112).
+edge(112,44).
+edge(44,123).
+edge(123,44).
+edge(45,52).
+edge(52,45).
+edge(45,69).
+edge(69,45).
+edge(45,81).
+edge(81,45).
+edge(45,91).
+edge(91,45).
+edge(45,94).
+edge(94,45).
+edge(45,119).
+edge(119,45).
+edge(45,135).
+edge(135,45).
+edge(46,47).
+edge(47,46).
+edge(46,49).
+edge(49,46).
+edge(46,61).
+edge(61,46).
+edge(46,73).
+edge(73,46).
+edge(46,85).
+edge(85,46).
+edge(46,104).
+edge(104,46).
+edge(46,106).
+edge(106,46).
+edge(46,110).
+edge(110,46).
+edge(46,115).
+edge(115,46).
+edge(46,120).
+edge(120,46).
+edge(46,124).
+edge(124,46).
+edge(46,127).
+edge(127,46).
+edge(47,64).
+edge(64,47).
+edge(47,66).
+edge(66,47).
+edge(47,75).
+edge(75,47).
+edge(47,81).
+edge(81,47).
+edge(47,97).
+edge(97,47).
+edge(47,117).
+edge(117,47).
+edge(47,129).
+edge(129,47).
+edge(47,139).
+edge(139,47).
+edge(48,49).
+edge(49,48).
+edge(48,51).
+edge(51,48).
+edge(48,62).
+edge(62,48).
+edge(48,64).
+edge(64,48).
+edge(48,67).
+edge(67,48).
+edge(48,96).
+edge(96,48).
+edge(48,97).
+edge(97,48).
+edge(48,109).
+edge(109,48).
+edge(48,122).
+edge(122,48).
+edge(48,128).
+edge(128,48).
+edge(48,134).
+edge(134,48).
+edge(48,137).
+edge(137,48).
+edge(49,73).
+edge(73,49).
+edge(49,77).
+edge(77,49).
+edge(49,80).
+edge(80,49).
+edge(49,120).
+edge(120,49).
+edge(49,124).
+edge(124,49).
+edge(49,126).
+edge(126,49).
+edge(49,129).
+edge(129,49).
+edge(50,73).
+edge(73,50).
+edge(50,89).
+edge(89,50).
+edge(50,111).
+edge(111,50).
+edge(50,118).
+edge(118,50).
+edge(50,129).
+edge(129,50).
+edge(51,52).
+edge(52,51).
+edge(51,53).
+edge(53,51).
+edge(51,63).
+edge(63,51).
+edge(51,68).
+edge(68,51).
+edge(51,75).
+edge(75,51).
+edge(51,86).
+edge(86,51).
+edge(51,89).
+edge(89,51).
+edge(51,93).
+edge(93,51).
+edge(51,98).
+edge(98,51).
+edge(51,100).
+edge(100,51).
+edge(51,108).
+edge(108,51).
+edge(51,110).
+edge(110,51).
+edge(51,115).
+edge(115,51).
+edge(51,117).
+edge(117,51).
+edge(51,135).
+edge(135,51).
+edge(51,139).
+edge(139,51).
+edge(52,62).
+edge(62,52).
+edge(52,70).
+edge(70,52).
+edge(52,91).
+edge(91,52).
+edge(52,99).
+edge(99,52).
+edge(52,100).
+edge(100,52).
+edge(52,101).
+edge(101,52).
+edge(53,67).
+edge(67,53).
+edge(53,68).
+edge(68,53).
+edge(53,106).
+edge(106,53).
+edge(53,116).
+edge(116,53).
+edge(53,121).
+edge(121,53).
+edge(53,122).
+edge(122,53).
+edge(53,130).
+edge(130,53).
+edge(53,131).
+edge(131,53).
+edge(53,132).
+edge(132,53).
+edge(54,58).
+edge(58,54).
+edge(54,65).
+edge(65,54).
+edge(54,67).
+edge(67,54).
+edge(54,76).
+edge(76,54).
+edge(54,90).
+edge(90,54).
+edge(54,99).
+edge(99,54).
+edge(54,103).
+edge(103,54).
+edge(54,125).
+edge(125,54).
+edge(55,67).
+edge(67,55).
+edge(55,73).
+edge(73,55).
+edge(55,92).
+edge(92,55).
+edge(55,96).
+edge(96,55).
+edge(55,126).
+edge(126,55).
+edge(55,132).
+edge(132,55).
+edge(55,134).
+edge(134,55).
+edge(55,139).
+edge(139,55).
+edge(56,66).
+edge(66,56).
+edge(56,88).
+edge(88,56).
+edge(56,94).
+edge(94,56).
+edge(56,98).
+edge(98,56).
+edge(56,107).
+edge(107,56).
+edge(56,116).
+edge(116,56).
+edge(56,119).
+edge(119,56).
+edge(56,129).
+edge(129,56).
+edge(56,133).
+edge(133,56).
+edge(57,66).
+edge(66,57).
+edge(57,84).
+edge(84,57).
+edge(57,89).
+edge(89,57).
+edge(57,113).
+edge(113,57).
+edge(58,59).
+edge(59,58).
+edge(58,67).
+edge(67,58).
+edge(58,72).
+edge(72,58).
+edge(58,74).
+edge(74,58).
+edge(58,86).
+edge(86,58).
+edge(58,87).
+edge(87,58).
+edge(58,101).
+edge(101,58).
+edge(58,109).
+edge(109,58).
+edge(58,131).
+edge(131,58).
+edge(58,137).
+edge(137,58).
+edge(59,63).
+edge(63,59).
+edge(59,66).
+edge(66,59).
+edge(59,69).
+edge(69,59).
+edge(59,79).
+edge(79,59).
+edge(59,93).
+edge(93,59).
+edge(59,100).
+edge(100,59).
+edge(59,108).
+edge(108,59).
+edge(59,115).
+edge(115,59).
+edge(59,117).
+edge(117,59).
+edge(59,128).
+edge(128,59).
+edge(59,131).
+edge(131,59).
+edge(59,139).
+edge(139,59).
+edge(60,63).
+edge(63,60).
+edge(60,65).
+edge(65,60).
+edge(60,69).
+edge(69,60).
+edge(60,71).
+edge(71,60).
+edge(60,76).
+edge(76,60).
+edge(60,77).
+edge(77,60).
+edge(60,78).
+edge(78,60).
+edge(60,81).
+edge(81,60).
+edge(60,88).
+edge(88,60).
+edge(60,96).
+edge(96,60).
+edge(60,99).
+edge(99,60).
+edge(60,102).
+edge(102,60).
+edge(60,115).
+edge(115,60).
+edge(60,120).
+edge(120,60).
+edge(61,67).
+edge(67,61).
+edge(61,69).
+edge(69,61).
+edge(61,71).
+edge(71,61).
+edge(61,89).
+edge(89,61).
+edge(61,90).
+edge(90,61).
+edge(61,96).
+edge(96,61).
+edge(61,118).
+edge(118,61).
+edge(62,63).
+edge(63,62).
+edge(62,77).
+edge(77,62).
+edge(62,99).
+edge(99,62).
+edge(62,106).
+edge(106,62).
+edge(62,128).
+edge(128,62).
+edge(62,133).
+edge(133,62).
+edge(63,80).
+edge(80,63).
+edge(63,81).
+edge(81,63).
+edge(63,87).
+edge(87,63).
+edge(63,104).
+edge(104,63).
+edge(63,113).
+edge(113,63).
+edge(63,128).
+edge(128,63).
+edge(64,73).
+edge(73,64).
+edge(64,75).
+edge(75,64).
+edge(64,89).
+edge(89,64).
+edge(64,100).
+edge(100,64).
+edge(64,111).
+edge(111,64).
+edge(64,114).
+edge(114,64).
+edge(64,123).
+edge(123,64).
+edge(64,126).
+edge(126,64).
+edge(64,128).
+edge(128,64).
+edge(65,77).
+edge(77,65).
+edge(65,91).
+edge(91,65).
+edge(65,97).
+edge(97,65).
+edge(65,105).
+edge(105,65).
+edge(65,121).
+edge(121,65).
+edge(65,123).
+edge(123,65).
+edge(65,132).
+edge(132,65).
+edge(65,136).
+edge(136,65).
+edge(65,137).
+edge(137,65).
+edge(66,71).
+edge(71,66).
+edge(66,102).
+edge(102,66).
+edge(66,104).
+edge(104,66).
+edge(66,117).
+edge(117,66).
+edge(66,126).
+edge(126,66).
+edge(66,140).
+edge(140,66).
+edge(67,71).
+edge(71,67).
+edge(67,86).
+edge(86,67).
+edge(67,90).
+edge(90,67).
+edge(67,97).
+edge(97,67).
+edge(67,111).
+edge(111,67).
+edge(68,69).
+edge(69,68).
+edge(68,90).
+edge(90,68).
+edge(68,91).
+edge(91,68).
+edge(68,132).
+edge(132,68).
+edge(68,140).
+edge(140,68).
+edge(69,123).
+edge(123,69).
+edge(69,128).
+edge(128,69).
+edge(69,134).
+edge(134,69).
+edge(69,135).
+edge(135,69).
+edge(69,140).
+edge(140,69).
+edge(70,78).
+edge(78,70).
+edge(70,79).
+edge(79,70).
+edge(70,80).
+edge(80,70).
+edge(70,89).
+edge(89,70).
+edge(70,99).
+edge(99,70).
+edge(70,115).
+edge(115,70).
+edge(70,116).
+edge(116,70).
+edge(70,121).
+edge(121,70).
+edge(71,74).
+edge(74,71).
+edge(71,97).
+edge(97,71).
+edge(71,100).
+edge(100,71).
+edge(71,122).
+edge(122,71).
+edge(71,137).
+edge(137,71).
+edge(72,75).
+edge(75,72).
+edge(72,79).
+edge(79,72).
+edge(72,85).
+edge(85,72).
+edge(72,88).
+edge(88,72).
+edge(72,91).
+edge(91,72).
+edge(72,96).
+edge(96,72).
+edge(72,122).
+edge(122,72).
+edge(72,136).
+edge(136,72).
+edge(73,78).
+edge(78,73).
+edge(73,95).
+edge(95,73).
+edge(73,102).
+edge(102,73).
+edge(73,126).
+edge(126,73).
+edge(73,130).
+edge(130,73).
+edge(74,80).
+edge(80,74).
+edge(74,92).
+edge(92,74).
+edge(74,94).
+edge(94,74).
+edge(74,105).
+edge(105,74).
+edge(74,123).
+edge(123,74).
+edge(74,126).
+edge(126,74).
+edge(74,138).
+edge(138,74).
+edge(75,84).
+edge(84,75).
+edge(75,88).
+edge(88,75).
+edge(75,90).
+edge(90,75).
+edge(75,100).
+edge(100,75).
+edge(75,113).
+edge(113,75).
+edge(75,115).
+edge(115,75).
+edge(75,120).
+edge(120,75).
+edge(75,133).
+edge(133,75).
+edge(75,135).
+edge(135,75).
+edge(76,84).
+edge(84,76).
+edge(76,108).
+edge(108,76).
+edge(76,123).
+edge(123,76).
+edge(76,138).
+edge(138,76).
+edge(77,97).
+edge(97,77).
+edge(77,101).
+edge(101,77).
+edge(77,102).
+edge(102,77).
+edge(77,103).
+edge(103,77).
+edge(77,114).
+edge(114,77).
+edge(77,115).
+edge(115,77).
+edge(77,118).
+edge(118,77).
+edge(77,122).
+edge(122,77).
+edge(77,135).
+edge(135,77).
+edge(77,139).
+edge(139,77).
+edge(78,79).
+edge(79,78).
+edge(78,99).
+edge(99,78).
+edge(78,113).
+edge(113,78).
+edge(79,92).
+edge(92,79).
+edge(79,99).
+edge(99,79).
+edge(79,102).
+edge(102,79).
+edge(79,110).
+edge(110,79).
+edge(79,120).
+edge(120,79).
+edge(79,123).
+edge(123,79).
+edge(79,133).
+edge(133,79).
+edge(80,122).
+edge(122,80).
+edge(81,88).
+edge(88,81).
+edge(81,99).
+edge(99,81).
+edge(81,104).
+edge(104,81).
+edge(81,109).
+edge(109,81).
+edge(81,112).
+edge(112,81).
+edge(81,138).
+edge(138,81).
+edge(82,100).
+edge(100,82).
+edge(82,103).
+edge(103,82).
+edge(82,124).
+edge(124,82).
+edge(82,127).
+edge(127,82).
+edge(83,101).
+edge(101,83).
+edge(83,106).
+edge(106,83).
+edge(83,122).
+edge(122,83).
+edge(83,124).
+edge(124,83).
+edge(83,135).
+edge(135,83).
+edge(83,136).
+edge(136,83).
+edge(83,139).
+edge(139,83).
+edge(84,101).
+edge(101,84).
+edge(84,110).
+edge(110,84).
+edge(84,116).
+edge(116,84).
+edge(84,120).
+edge(120,84).
+edge(84,133).
+edge(133,84).
+edge(84,134).
+edge(134,84).
+edge(84,138).
+edge(138,84).
+edge(84,139).
+edge(139,84).
+edge(85,98).
+edge(98,85).
+edge(85,113).
+edge(113,85).
+edge(85,118).
+edge(118,85).
+edge(85,122).
+edge(122,85).
+edge(85,125).
+edge(125,85).
+edge(85,128).
+edge(128,85).
+edge(85,140).
+edge(140,85).
+edge(86,88).
+edge(88,86).
+edge(86,105).
+edge(105,86).
+edge(86,106).
+edge(106,86).
+edge(86,121).
+edge(121,86).
+edge(86,124).
+edge(124,86).
+edge(86,129).
+edge(129,86).
+edge(86,137).
+edge(137,86).
+edge(87,93).
+edge(93,87).
+edge(87,94).
+edge(94,87).
+edge(87,101).
+edge(101,87).
+edge(87,118).
+edge(118,87).
+edge(87,119).
+edge(119,87).
+edge(87,133).
+edge(133,87).
+edge(87,140).
+edge(140,87).
+edge(88,90).
+edge(90,88).
+edge(88,98).
+edge(98,88).
+edge(88,111).
+edge(111,88).
+edge(88,131).
+edge(131,88).
+edge(88,137).
+edge(137,88).
+edge(89,96).
+edge(96,89).
+edge(89,99).
+edge(99,89).
+edge(89,102).
+edge(102,89).
+edge(89,135).
+edge(135,89).
+edge(90,104).
+edge(104,90).
+edge(90,114).
+edge(114,90).
+edge(90,117).
+edge(117,90).
+edge(90,118).
+edge(118,90).
+edge(90,137).
+edge(137,90).
+edge(90,138).
+edge(138,90).
+edge(90,140).
+edge(140,90).
+edge(91,95).
+edge(95,91).
+edge(91,96).
+edge(96,91).
+edge(91,101).
+edge(101,91).
+edge(91,109).
+edge(109,91).
+edge(91,125).
+edge(125,91).
+edge(91,127).
+edge(127,91).
+edge(91,135).
+edge(135,91).
+edge(92,102).
+edge(102,92).
+edge(92,119).
+edge(119,92).
+edge(92,132).
+edge(132,92).
+edge(92,137).
+edge(137,92).
+edge(93,126).
+edge(126,93).
+edge(93,130).
+edge(130,93).
+edge(94,100).
+edge(100,94).
+edge(94,101).
+edge(101,94).
+edge(94,110).
+edge(110,94).
+edge(94,126).
+edge(126,94).
+edge(94,129).
+edge(129,94).
+edge(95,100).
+edge(100,95).
+edge(95,102).
+edge(102,95).
+edge(95,113).
+edge(113,95).
+edge(95,114).
+edge(114,95).
+edge(95,122).
+edge(122,95).
+edge(96,99).
+edge(99,96).
+edge(96,119).
+edge(119,96).
+edge(96,135).
+edge(135,96).
+edge(96,137).
+edge(137,96).
+edge(97,101).
+edge(101,97).
+edge(97,109).
+edge(109,97).
+edge(97,117).
+edge(117,97).
+edge(97,120).
+edge(120,97).
+edge(97,123).
+edge(123,97).
+edge(98,132).
+edge(132,98).
+edge(99,108).
+edge(108,99).
+edge(99,119).
+edge(119,99).
+edge(99,122).
+edge(122,99).
+edge(99,124).
+edge(124,99).
+edge(99,132).
+edge(132,99).
+edge(100,101).
+edge(101,100).
+edge(100,131).
+edge(131,100).
+edge(101,103).
+edge(103,101).
+edge(101,117).
+edge(117,101).
+edge(102,104).
+edge(104,102).
+edge(102,128).
+edge(128,102).
+edge(102,137).
+edge(137,102).
+edge(102,140).
+edge(140,102).
+edge(104,114).
+edge(114,104).
+edge(104,116).
+edge(116,104).
+edge(104,122).
+edge(122,104).
+edge(104,125).
+edge(125,104).
+edge(104,131).
+edge(131,104).
+edge(105,125).
+edge(125,105).
+edge(105,132).
+edge(132,105).
+edge(105,134).
+edge(134,105).
+edge(105,135).
+edge(135,105).
+edge(106,129).
+edge(129,106).
+edge(106,130).
+edge(130,106).
+edge(106,138).
+edge(138,106).
+edge(106,140).
+edge(140,106).
+edge(107,111).
+edge(111,107).
+edge(107,120).
+edge(120,107).
+edge(107,121).
+edge(121,107).
+edge(107,129).
+edge(129,107).
+edge(107,130).
+edge(130,107).
+edge(107,134).
+edge(134,107).
+edge(107,138).
+edge(138,107).
+edge(108,124).
+edge(124,108).
+edge(109,126).
+edge(126,109).
+edge(109,135).
+edge(135,109).
+edge(109,138).
+edge(138,109).
+edge(110,126).
+edge(126,110).
+edge(110,130).
+edge(130,110).
+edge(111,114).
+edge(114,111).
+edge(111,124).
+edge(124,111).
+edge(111,132).
+edge(132,111).
+edge(112,120).
+edge(120,112).
+edge(113,114).
+edge(114,113).
+edge(113,116).
+edge(116,113).
+edge(113,117).
+edge(117,113).
+edge(113,122).
+edge(122,113).
+edge(114,117).
+edge(117,114).
+edge(114,123).
+edge(123,114).
+edge(114,129).
+edge(129,114).
+edge(115,116).
+edge(116,115).
+edge(115,128).
+edge(128,115).
+edge(115,129).
+edge(129,115).
+edge(115,136).
+edge(136,115).
+edge(116,121).
+edge(121,116).
+edge(116,123).
+edge(123,116).
+edge(116,127).
+edge(127,116).
+edge(117,127).
+edge(127,117).
+edge(118,119).
+edge(119,118).
+edge(118,127).
+edge(127,118).
+edge(119,124).
+edge(124,119).
+edge(119,127).
+edge(127,119).
+edge(119,136).
+edge(136,119).
+edge(119,138).
+edge(138,119).
+edge(119,139).
+edge(139,119).
+edge(120,131).
+edge(131,120).
+edge(120,133).
+edge(133,120).
+edge(120,134).
+edge(134,120).
+edge(121,131).
+edge(131,121).
+edge(121,133).
+edge(133,121).
+edge(121,136).
+edge(136,121).
+edge(121,138).
+edge(138,121).
+edge(121,139).
+edge(139,121).
+edge(122,130).
+edge(130,122).
+edge(122,139).
+edge(139,122).
+edge(123,124).
+edge(124,123).
+edge(123,135).
+edge(135,123).
+edge(123,136).
+edge(136,123).
+edge(124,127).
+edge(127,124).
+edge(125,138).
+edge(138,125).
+edge(126,134).
+edge(134,126).
+edge(126,136).
+edge(136,126).
+edge(127,130).
+edge(130,127).
+edge(127,131).
+edge(131,127).
+edge(127,139).
+edge(139,127).
+edge(128,133).
+edge(133,128).
+edge(128,136).
+edge(136,128).
+edge(129,131).
+edge(131,129).
+edge(129,136).
+edge(136,129).
+edge(130,134).
+edge(134,130).
+edge(132,136).
+edge(136,132).
+edge(132,137).
+edge(137,132).
+edge(133,136).
+edge(136,133).
+edge(134,136).
+edge(136,134).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0039-graph_colouring-140-0.lp b/examples/clingo/expansion/GraphColouring/instances/0039-graph_colouring-140-0.lp
new file mode 100644
index 0000000..a5baafc
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0039-graph_colouring-140-0.lp
@@ -0,0 +1,2174 @@
+#const n=140.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+edge(1,16).
+edge(16,1).
+edge(1,32).
+edge(32,1).
+edge(1,36).
+edge(36,1).
+edge(1,55).
+edge(55,1).
+edge(1,61).
+edge(61,1).
+edge(1,72).
+edge(72,1).
+edge(1,86).
+edge(86,1).
+edge(1,101).
+edge(101,1).
+edge(1,107).
+edge(107,1).
+edge(1,121).
+edge(121,1).
+edge(2,7).
+edge(7,2).
+edge(2,12).
+edge(12,2).
+edge(2,18).
+edge(18,2).
+edge(2,24).
+edge(24,2).
+edge(2,30).
+edge(30,2).
+edge(2,44).
+edge(44,2).
+edge(2,50).
+edge(50,2).
+edge(2,51).
+edge(51,2).
+edge(2,63).
+edge(63,2).
+edge(2,70).
+edge(70,2).
+edge(2,85).
+edge(85,2).
+edge(2,106).
+edge(106,2).
+edge(2,110).
+edge(110,2).
+edge(2,111).
+edge(111,2).
+edge(2,115).
+edge(115,2).
+edge(2,119).
+edge(119,2).
+edge(3,7).
+edge(7,3).
+edge(3,33).
+edge(33,3).
+edge(3,41).
+edge(41,3).
+edge(3,56).
+edge(56,3).
+edge(3,86).
+edge(86,3).
+edge(3,88).
+edge(88,3).
+edge(3,90).
+edge(90,3).
+edge(3,120).
+edge(120,3).
+edge(3,123).
+edge(123,3).
+edge(3,139).
+edge(139,3).
+edge(4,10).
+edge(10,4).
+edge(4,28).
+edge(28,4).
+edge(4,30).
+edge(30,4).
+edge(4,32).
+edge(32,4).
+edge(4,33).
+edge(33,4).
+edge(4,40).
+edge(40,4).
+edge(4,45).
+edge(45,4).
+edge(4,49).
+edge(49,4).
+edge(4,58).
+edge(58,4).
+edge(4,73).
+edge(73,4).
+edge(4,95).
+edge(95,4).
+edge(4,103).
+edge(103,4).
+edge(4,107).
+edge(107,4).
+edge(4,109).
+edge(109,4).
+edge(4,114).
+edge(114,4).
+edge(4,118).
+edge(118,4).
+edge(4,119).
+edge(119,4).
+edge(4,130).
+edge(130,4).
+edge(5,8).
+edge(8,5).
+edge(5,14).
+edge(14,5).
+edge(5,16).
+edge(16,5).
+edge(5,24).
+edge(24,5).
+edge(5,36).
+edge(36,5).
+edge(5,43).
+edge(43,5).
+edge(5,48).
+edge(48,5).
+edge(5,92).
+edge(92,5).
+edge(5,99).
+edge(99,5).
+edge(5,107).
+edge(107,5).
+edge(5,115).
+edge(115,5).
+edge(5,127).
+edge(127,5).
+edge(5,135).
+edge(135,5).
+edge(5,136).
+edge(136,5).
+edge(6,11).
+edge(11,6).
+edge(6,78).
+edge(78,6).
+edge(6,87).
+edge(87,6).
+edge(6,89).
+edge(89,6).
+edge(6,92).
+edge(92,6).
+edge(6,123).
+edge(123,6).
+edge(6,139).
+edge(139,6).
+edge(6,140).
+edge(140,6).
+edge(7,25).
+edge(25,7).
+edge(7,26).
+edge(26,7).
+edge(7,29).
+edge(29,7).
+edge(7,50).
+edge(50,7).
+edge(7,52).
+edge(52,7).
+edge(7,53).
+edge(53,7).
+edge(7,80).
+edge(80,7).
+edge(7,96).
+edge(96,7).
+edge(7,105).
+edge(105,7).
+edge(7,108).
+edge(108,7).
+edge(7,120).
+edge(120,7).
+edge(7,131).
+edge(131,7).
+edge(8,18).
+edge(18,8).
+edge(8,27).
+edge(27,8).
+edge(8,37).
+edge(37,8).
+edge(8,38).
+edge(38,8).
+edge(8,58).
+edge(58,8).
+edge(8,62).
+edge(62,8).
+edge(8,63).
+edge(63,8).
+edge(8,69).
+edge(69,8).
+edge(8,73).
+edge(73,8).
+edge(8,79).
+edge(79,8).
+edge(8,100).
+edge(100,8).
+edge(8,103).
+edge(103,8).
+edge(8,108).
+edge(108,8).
+edge(8,125).
+edge(125,8).
+edge(8,132).
+edge(132,8).
+edge(9,24).
+edge(24,9).
+edge(9,34).
+edge(34,9).
+edge(9,41).
+edge(41,9).
+edge(9,46).
+edge(46,9).
+edge(9,52).
+edge(52,9).
+edge(9,111).
+edge(111,9).
+edge(9,114).
+edge(114,9).
+edge(9,115).
+edge(115,9).
+edge(9,130).
+edge(130,9).
+edge(9,139).
+edge(139,9).
+edge(9,140).
+edge(140,9).
+edge(10,11).
+edge(11,10).
+edge(10,44).
+edge(44,10).
+edge(10,69).
+edge(69,10).
+edge(10,73).
+edge(73,10).
+edge(10,76).
+edge(76,10).
+edge(10,79).
+edge(79,10).
+edge(10,81).
+edge(81,10).
+edge(10,87).
+edge(87,10).
+edge(10,88).
+edge(88,10).
+edge(10,93).
+edge(93,10).
+edge(10,103).
+edge(103,10).
+edge(10,110).
+edge(110,10).
+edge(10,126).
+edge(126,10).
+edge(10,127).
+edge(127,10).
+edge(10,133).
+edge(133,10).
+edge(11,16).
+edge(16,11).
+edge(11,17).
+edge(17,11).
+edge(11,25).
+edge(25,11).
+edge(11,63).
+edge(63,11).
+edge(11,98).
+edge(98,11).
+edge(11,108).
+edge(108,11).
+edge(11,131).
+edge(131,11).
+edge(11,133).
+edge(133,11).
+edge(11,134).
+edge(134,11).
+edge(11,139).
+edge(139,11).
+edge(12,14).
+edge(14,12).
+edge(12,15).
+edge(15,12).
+edge(12,20).
+edge(20,12).
+edge(12,22).
+edge(22,12).
+edge(12,65).
+edge(65,12).
+edge(12,67).
+edge(67,12).
+edge(12,71).
+edge(71,12).
+edge(12,75).
+edge(75,12).
+edge(12,80).
+edge(80,12).
+edge(12,88).
+edge(88,12).
+edge(12,89).
+edge(89,12).
+edge(12,104).
+edge(104,12).
+edge(12,124).
+edge(124,12).
+edge(12,127).
+edge(127,12).
+edge(13,24).
+edge(24,13).
+edge(13,25).
+edge(25,13).
+edge(13,30).
+edge(30,13).
+edge(13,36).
+edge(36,13).
+edge(13,38).
+edge(38,13).
+edge(13,43).
+edge(43,13).
+edge(13,79).
+edge(79,13).
+edge(13,93).
+edge(93,13).
+edge(13,118).
+edge(118,13).
+edge(13,128).
+edge(128,13).
+edge(13,132).
+edge(132,13).
+edge(13,137).
+edge(137,13).
+edge(14,21).
+edge(21,14).
+edge(14,22).
+edge(22,14).
+edge(14,29).
+edge(29,14).
+edge(14,33).
+edge(33,14).
+edge(14,41).
+edge(41,14).
+edge(14,50).
+edge(50,14).
+edge(14,60).
+edge(60,14).
+edge(14,72).
+edge(72,14).
+edge(14,75).
+edge(75,14).
+edge(14,78).
+edge(78,14).
+edge(14,113).
+edge(113,14).
+edge(14,122).
+edge(122,14).
+edge(14,126).
+edge(126,14).
+edge(14,137).
+edge(137,14).
+edge(15,29).
+edge(29,15).
+edge(15,35).
+edge(35,15).
+edge(15,59).
+edge(59,15).
+edge(15,61).
+edge(61,15).
+edge(15,70).
+edge(70,15).
+edge(15,74).
+edge(74,15).
+edge(15,90).
+edge(90,15).
+edge(15,101).
+edge(101,15).
+edge(15,112).
+edge(112,15).
+edge(15,115).
+edge(115,15).
+edge(15,117).
+edge(117,15).
+edge(15,127).
+edge(127,15).
+edge(15,136).
+edge(136,15).
+edge(16,21).
+edge(21,16).
+edge(16,33).
+edge(33,16).
+edge(16,43).
+edge(43,16).
+edge(16,51).
+edge(51,16).
+edge(16,71).
+edge(71,16).
+edge(16,72).
+edge(72,16).
+edge(16,75).
+edge(75,16).
+edge(16,91).
+edge(91,16).
+edge(16,128).
+edge(128,16).
+edge(17,19).
+edge(19,17).
+edge(17,32).
+edge(32,17).
+edge(17,40).
+edge(40,17).
+edge(17,50).
+edge(50,17).
+edge(17,58).
+edge(58,17).
+edge(17,69).
+edge(69,17).
+edge(17,71).
+edge(71,17).
+edge(17,72).
+edge(72,17).
+edge(17,88).
+edge(88,17).
+edge(17,93).
+edge(93,17).
+edge(17,109).
+edge(109,17).
+edge(17,115).
+edge(115,17).
+edge(17,119).
+edge(119,17).
+edge(17,120).
+edge(120,17).
+edge(17,127).
+edge(127,17).
+edge(17,133).
+edge(133,17).
+edge(18,20).
+edge(20,18).
+edge(18,25).
+edge(25,18).
+edge(18,27).
+edge(27,18).
+edge(18,40).
+edge(40,18).
+edge(18,58).
+edge(58,18).
+edge(18,71).
+edge(71,18).
+edge(18,101).
+edge(101,18).
+edge(18,123).
+edge(123,18).
+edge(19,23).
+edge(23,19).
+edge(19,26).
+edge(26,19).
+edge(19,36).
+edge(36,19).
+edge(19,48).
+edge(48,19).
+edge(19,52).
+edge(52,19).
+edge(19,54).
+edge(54,19).
+edge(19,57).
+edge(57,19).
+edge(19,58).
+edge(58,19).
+edge(19,62).
+edge(62,19).
+edge(19,77).
+edge(77,19).
+edge(19,82).
+edge(82,19).
+edge(19,101).
+edge(101,19).
+edge(19,116).
+edge(116,19).
+edge(19,131).
+edge(131,19).
+edge(19,136).
+edge(136,19).
+edge(20,25).
+edge(25,20).
+edge(20,30).
+edge(30,20).
+edge(20,63).
+edge(63,20).
+edge(20,66).
+edge(66,20).
+edge(20,78).
+edge(78,20).
+edge(20,80).
+edge(80,20).
+edge(20,96).
+edge(96,20).
+edge(20,108).
+edge(108,20).
+edge(20,112).
+edge(112,20).
+edge(20,125).
+edge(125,20).
+edge(20,126).
+edge(126,20).
+edge(20,135).
+edge(135,20).
+edge(21,31).
+edge(31,21).
+edge(21,47).
+edge(47,21).
+edge(21,62).
+edge(62,21).
+edge(21,71).
+edge(71,21).
+edge(21,80).
+edge(80,21).
+edge(21,81).
+edge(81,21).
+edge(21,83).
+edge(83,21).
+edge(21,92).
+edge(92,21).
+edge(21,97).
+edge(97,21).
+edge(21,100).
+edge(100,21).
+edge(21,103).
+edge(103,21).
+edge(21,109).
+edge(109,21).
+edge(21,117).
+edge(117,21).
+edge(21,121).
+edge(121,21).
+edge(21,126).
+edge(126,21).
+edge(22,25).
+edge(25,22).
+edge(22,35).
+edge(35,22).
+edge(22,54).
+edge(54,22).
+edge(22,99).
+edge(99,22).
+edge(22,110).
+edge(110,22).
+edge(22,112).
+edge(112,22).
+edge(22,124).
+edge(124,22).
+edge(22,126).
+edge(126,22).
+edge(23,28).
+edge(28,23).
+edge(23,45).
+edge(45,23).
+edge(23,71).
+edge(71,23).
+edge(23,99).
+edge(99,23).
+edge(23,105).
+edge(105,23).
+edge(23,121).
+edge(121,23).
+edge(23,123).
+edge(123,23).
+edge(23,125).
+edge(125,23).
+edge(24,29).
+edge(29,24).
+edge(24,37).
+edge(37,24).
+edge(24,38).
+edge(38,24).
+edge(24,46).
+edge(46,24).
+edge(24,57).
+edge(57,24).
+edge(24,72).
+edge(72,24).
+edge(24,101).
+edge(101,24).
+edge(24,110).
+edge(110,24).
+edge(24,124).
+edge(124,24).
+edge(25,32).
+edge(32,25).
+edge(25,37).
+edge(37,25).
+edge(25,54).
+edge(54,25).
+edge(25,59).
+edge(59,25).
+edge(25,71).
+edge(71,25).
+edge(25,78).
+edge(78,25).
+edge(25,108).
+edge(108,25).
+edge(25,129).
+edge(129,25).
+edge(25,140).
+edge(140,25).
+edge(26,27).
+edge(27,26).
+edge(26,46).
+edge(46,26).
+edge(26,48).
+edge(48,26).
+edge(26,49).
+edge(49,26).
+edge(26,75).
+edge(75,26).
+edge(26,76).
+edge(76,26).
+edge(26,85).
+edge(85,26).
+edge(26,87).
+edge(87,26).
+edge(26,89).
+edge(89,26).
+edge(26,91).
+edge(91,26).
+edge(26,97).
+edge(97,26).
+edge(26,98).
+edge(98,26).
+edge(26,109).
+edge(109,26).
+edge(26,110).
+edge(110,26).
+edge(26,126).
+edge(126,26).
+edge(26,135).
+edge(135,26).
+edge(27,29).
+edge(29,27).
+edge(27,30).
+edge(30,27).
+edge(27,52).
+edge(52,27).
+edge(27,78).
+edge(78,27).
+edge(27,79).
+edge(79,27).
+edge(27,81).
+edge(81,27).
+edge(27,96).
+edge(96,27).
+edge(28,37).
+edge(37,28).
+edge(28,40).
+edge(40,28).
+edge(28,58).
+edge(58,28).
+edge(28,62).
+edge(62,28).
+edge(28,70).
+edge(70,28).
+edge(28,76).
+edge(76,28).
+edge(28,78).
+edge(78,28).
+edge(28,101).
+edge(101,28).
+edge(28,106).
+edge(106,28).
+edge(28,115).
+edge(115,28).
+edge(28,119).
+edge(119,28).
+edge(28,138).
+edge(138,28).
+edge(29,44).
+edge(44,29).
+edge(29,50).
+edge(50,29).
+edge(29,52).
+edge(52,29).
+edge(29,88).
+edge(88,29).
+edge(29,89).
+edge(89,29).
+edge(29,97).
+edge(97,29).
+edge(29,99).
+edge(99,29).
+edge(29,104).
+edge(104,29).
+edge(29,124).
+edge(124,29).
+edge(29,127).
+edge(127,29).
+edge(30,51).
+edge(51,30).
+edge(30,62).
+edge(62,30).
+edge(30,107).
+edge(107,30).
+edge(30,113).
+edge(113,30).
+edge(30,116).
+edge(116,30).
+edge(30,131).
+edge(131,30).
+edge(31,39).
+edge(39,31).
+edge(31,52).
+edge(52,31).
+edge(31,66).
+edge(66,31).
+edge(31,72).
+edge(72,31).
+edge(31,80).
+edge(80,31).
+edge(31,82).
+edge(82,31).
+edge(31,88).
+edge(88,31).
+edge(31,96).
+edge(96,31).
+edge(31,101).
+edge(101,31).
+edge(31,129).
+edge(129,31).
+edge(31,131).
+edge(131,31).
+edge(31,135).
+edge(135,31).
+edge(31,138).
+edge(138,31).
+edge(32,34).
+edge(34,32).
+edge(32,58).
+edge(58,32).
+edge(32,60).
+edge(60,32).
+edge(32,67).
+edge(67,32).
+edge(32,74).
+edge(74,32).
+edge(32,87).
+edge(87,32).
+edge(32,97).
+edge(97,32).
+edge(32,110).
+edge(110,32).
+edge(32,111).
+edge(111,32).
+edge(33,39).
+edge(39,33).
+edge(33,62).
+edge(62,33).
+edge(33,67).
+edge(67,33).
+edge(33,83).
+edge(83,33).
+edge(33,86).
+edge(86,33).
+edge(33,96).
+edge(96,33).
+edge(33,108).
+edge(108,33).
+edge(33,110).
+edge(110,33).
+edge(33,117).
+edge(117,33).
+edge(33,121).
+edge(121,33).
+edge(33,123).
+edge(123,33).
+edge(34,40).
+edge(40,34).
+edge(34,43).
+edge(43,34).
+edge(34,49).
+edge(49,34).
+edge(34,50).
+edge(50,34).
+edge(34,61).
+edge(61,34).
+edge(34,65).
+edge(65,34).
+edge(34,72).
+edge(72,34).
+edge(34,76).
+edge(76,34).
+edge(34,94).
+edge(94,34).
+edge(34,101).
+edge(101,34).
+edge(34,110).
+edge(110,34).
+edge(34,114).
+edge(114,34).
+edge(34,115).
+edge(115,34).
+edge(34,125).
+edge(125,34).
+edge(34,129).
+edge(129,34).
+edge(34,132).
+edge(132,34).
+edge(34,135).
+edge(135,34).
+edge(35,41).
+edge(41,35).
+edge(35,45).
+edge(45,35).
+edge(35,46).
+edge(46,35).
+edge(35,51).
+edge(51,35).
+edge(35,65).
+edge(65,35).
+edge(35,66).
+edge(66,35).
+edge(35,68).
+edge(68,35).
+edge(35,71).
+edge(71,35).
+edge(35,75).
+edge(75,35).
+edge(35,88).
+edge(88,35).
+edge(35,109).
+edge(109,35).
+edge(35,118).
+edge(118,35).
+edge(35,130).
+edge(130,35).
+edge(36,38).
+edge(38,36).
+edge(36,49).
+edge(49,36).
+edge(36,55).
+edge(55,36).
+edge(36,58).
+edge(58,36).
+edge(36,69).
+edge(69,36).
+edge(36,74).
+edge(74,36).
+edge(36,79).
+edge(79,36).
+edge(36,101).
+edge(101,36).
+edge(36,108).
+edge(108,36).
+edge(36,115).
+edge(115,36).
+edge(36,120).
+edge(120,36).
+edge(36,129).
+edge(129,36).
+edge(36,130).
+edge(130,36).
+edge(36,139).
+edge(139,36).
+edge(37,40).
+edge(40,37).
+edge(37,45).
+edge(45,37).
+edge(37,61).
+edge(61,37).
+edge(37,67).
+edge(67,37).
+edge(37,71).
+edge(71,37).
+edge(37,87).
+edge(87,37).
+edge(37,88).
+edge(88,37).
+edge(37,100).
+edge(100,37).
+edge(37,101).
+edge(101,37).
+edge(37,103).
+edge(103,37).
+edge(37,106).
+edge(106,37).
+edge(37,108).
+edge(108,37).
+edge(37,118).
+edge(118,37).
+edge(37,132).
+edge(132,37).
+edge(38,40).
+edge(40,38).
+edge(38,43).
+edge(43,38).
+edge(38,53).
+edge(53,38).
+edge(38,63).
+edge(63,38).
+edge(38,68).
+edge(68,38).
+edge(38,87).
+edge(87,38).
+edge(38,91).
+edge(91,38).
+edge(38,98).
+edge(98,38).
+edge(38,102).
+edge(102,38).
+edge(38,108).
+edge(108,38).
+edge(38,112).
+edge(112,38).
+edge(38,123).
+edge(123,38).
+edge(38,138).
+edge(138,38).
+edge(38,140).
+edge(140,38).
+edge(39,50).
+edge(50,39).
+edge(39,55).
+edge(55,39).
+edge(39,56).
+edge(56,39).
+edge(39,60).
+edge(60,39).
+edge(39,89).
+edge(89,39).
+edge(39,90).
+edge(90,39).
+edge(39,94).
+edge(94,39).
+edge(39,96).
+edge(96,39).
+edge(39,99).
+edge(99,39).
+edge(39,102).
+edge(102,39).
+edge(39,113).
+edge(113,39).
+edge(39,123).
+edge(123,39).
+edge(39,128).
+edge(128,39).
+edge(39,130).
+edge(130,39).
+edge(39,134).
+edge(134,39).
+edge(40,42).
+edge(42,40).
+edge(40,83).
+edge(83,40).
+edge(40,117).
+edge(117,40).
+edge(40,119).
+edge(119,40).
+edge(40,120).
+edge(120,40).
+edge(40,128).
+edge(128,40).
+edge(40,134).
+edge(134,40).
+edge(40,136).
+edge(136,40).
+edge(40,137).
+edge(137,40).
+edge(40,139).
+edge(139,40).
+edge(41,54).
+edge(54,41).
+edge(41,55).
+edge(55,41).
+edge(41,62).
+edge(62,41).
+edge(41,67).
+edge(67,41).
+edge(41,88).
+edge(88,41).
+edge(41,100).
+edge(100,41).
+edge(41,102).
+edge(102,41).
+edge(41,105).
+edge(105,41).
+edge(41,112).
+edge(112,41).
+edge(41,122).
+edge(122,41).
+edge(41,134).
+edge(134,41).
+edge(42,56).
+edge(56,42).
+edge(42,57).
+edge(57,42).
+edge(42,68).
+edge(68,42).
+edge(42,74).
+edge(74,42).
+edge(42,76).
+edge(76,42).
+edge(42,80).
+edge(80,42).
+edge(42,84).
+edge(84,42).
+edge(42,85).
+edge(85,42).
+edge(42,86).
+edge(86,42).
+edge(42,99).
+edge(99,42).
+edge(42,100).
+edge(100,42).
+edge(42,105).
+edge(105,42).
+edge(42,126).
+edge(126,42).
+edge(42,129).
+edge(129,42).
+edge(42,131).
+edge(131,42).
+edge(43,48).
+edge(48,43).
+edge(43,65).
+edge(65,43).
+edge(43,66).
+edge(66,43).
+edge(43,68).
+edge(68,43).
+edge(43,70).
+edge(70,43).
+edge(43,77).
+edge(77,43).
+edge(43,80).
+edge(80,43).
+edge(43,97).
+edge(97,43).
+edge(43,127).
+edge(127,43).
+edge(43,138).
+edge(138,43).
+edge(44,51).
+edge(51,44).
+edge(44,57).
+edge(57,44).
+edge(44,60).
+edge(60,44).
+edge(44,81).
+edge(81,44).
+edge(44,83).
+edge(83,44).
+edge(44,84).
+edge(84,44).
+edge(44,110).
+edge(110,44).
+edge(44,117).
+edge(117,44).
+edge(44,122).
+edge(122,44).
+edge(44,130).
+edge(130,44).
+edge(44,135).
+edge(135,44).
+edge(45,46).
+edge(46,45).
+edge(45,51).
+edge(51,45).
+edge(45,54).
+edge(54,45).
+edge(45,80).
+edge(80,45).
+edge(45,82).
+edge(82,45).
+edge(45,93).
+edge(93,45).
+edge(45,94).
+edge(94,45).
+edge(45,96).
+edge(96,45).
+edge(45,99).
+edge(99,45).
+edge(45,127).
+edge(127,45).
+edge(45,130).
+edge(130,45).
+edge(46,58).
+edge(58,46).
+edge(46,63).
+edge(63,46).
+edge(46,64).
+edge(64,46).
+edge(46,70).
+edge(70,46).
+edge(46,83).
+edge(83,46).
+edge(46,87).
+edge(87,46).
+edge(46,90).
+edge(90,46).
+edge(46,95).
+edge(95,46).
+edge(46,127).
+edge(127,46).
+edge(46,130).
+edge(130,46).
+edge(46,139).
+edge(139,46).
+edge(46,140).
+edge(140,46).
+edge(47,73).
+edge(73,47).
+edge(47,116).
+edge(116,47).
+edge(47,117).
+edge(117,47).
+edge(47,121).
+edge(121,47).
+edge(47,123).
+edge(123,47).
+edge(47,130).
+edge(130,47).
+edge(48,52).
+edge(52,48).
+edge(48,70).
+edge(70,48).
+edge(48,76).
+edge(76,48).
+edge(48,83).
+edge(83,48).
+edge(48,91).
+edge(91,48).
+edge(48,94).
+edge(94,48).
+edge(48,103).
+edge(103,48).
+edge(48,108).
+edge(108,48).
+edge(48,110).
+edge(110,48).
+edge(48,111).
+edge(111,48).
+edge(48,113).
+edge(113,48).
+edge(48,123).
+edge(123,48).
+edge(48,136).
+edge(136,48).
+edge(49,52).
+edge(52,49).
+edge(49,56).
+edge(56,49).
+edge(49,77).
+edge(77,49).
+edge(49,104).
+edge(104,49).
+edge(49,121).
+edge(121,49).
+edge(49,124).
+edge(124,49).
+edge(49,137).
+edge(137,49).
+edge(50,59).
+edge(59,50).
+edge(50,60).
+edge(60,50).
+edge(50,63).
+edge(63,50).
+edge(50,64).
+edge(64,50).
+edge(50,65).
+edge(65,50).
+edge(50,69).
+edge(69,50).
+edge(50,72).
+edge(72,50).
+edge(50,73).
+edge(73,50).
+edge(50,76).
+edge(76,50).
+edge(50,80).
+edge(80,50).
+edge(50,85).
+edge(85,50).
+edge(50,93).
+edge(93,50).
+edge(50,94).
+edge(94,50).
+edge(50,95).
+edge(95,50).
+edge(50,99).
+edge(99,50).
+edge(50,110).
+edge(110,50).
+edge(50,113).
+edge(113,50).
+edge(50,117).
+edge(117,50).
+edge(50,127).
+edge(127,50).
+edge(50,134).
+edge(134,50).
+edge(51,65).
+edge(65,51).
+edge(51,68).
+edge(68,51).
+edge(51,70).
+edge(70,51).
+edge(51,90).
+edge(90,51).
+edge(51,93).
+edge(93,51).
+edge(51,94).
+edge(94,51).
+edge(51,95).
+edge(95,51).
+edge(51,98).
+edge(98,51).
+edge(51,110).
+edge(110,51).
+edge(51,130).
+edge(130,51).
+edge(52,67).
+edge(67,52).
+edge(52,77).
+edge(77,52).
+edge(52,78).
+edge(78,52).
+edge(52,102).
+edge(102,52).
+edge(52,106).
+edge(106,52).
+edge(52,109).
+edge(109,52).
+edge(52,111).
+edge(111,52).
+edge(52,125).
+edge(125,52).
+edge(52,128).
+edge(128,52).
+edge(52,137).
+edge(137,52).
+edge(53,55).
+edge(55,53).
+edge(53,61).
+edge(61,53).
+edge(53,67).
+edge(67,53).
+edge(53,69).
+edge(69,53).
+edge(53,70).
+edge(70,53).
+edge(53,71).
+edge(71,53).
+edge(53,115).
+edge(115,53).
+edge(53,122).
+edge(122,53).
+edge(53,124).
+edge(124,53).
+edge(53,131).
+edge(131,53).
+edge(53,138).
+edge(138,53).
+edge(54,61).
+edge(61,54).
+edge(54,76).
+edge(76,54).
+edge(54,81).
+edge(81,54).
+edge(54,84).
+edge(84,54).
+edge(54,97).
+edge(97,54).
+edge(54,101).
+edge(101,54).
+edge(54,104).
+edge(104,54).
+edge(54,121).
+edge(121,54).
+edge(55,71).
+edge(71,55).
+edge(55,81).
+edge(81,55).
+edge(55,105).
+edge(105,55).
+edge(55,113).
+edge(113,55).
+edge(55,132).
+edge(132,55).
+edge(55,137).
+edge(137,55).
+edge(56,70).
+edge(70,56).
+edge(56,82).
+edge(82,56).
+edge(56,86).
+edge(86,56).
+edge(56,93).
+edge(93,56).
+edge(56,95).
+edge(95,56).
+edge(56,102).
+edge(102,56).
+edge(56,119).
+edge(119,56).
+edge(56,139).
+edge(139,56).
+edge(57,64).
+edge(64,57).
+edge(57,72).
+edge(72,57).
+edge(57,76).
+edge(76,57).
+edge(57,78).
+edge(78,57).
+edge(57,98).
+edge(98,57).
+edge(57,113).
+edge(113,57).
+edge(57,124).
+edge(124,57).
+edge(57,131).
+edge(131,57).
+edge(58,63).
+edge(63,58).
+edge(58,76).
+edge(76,58).
+edge(58,80).
+edge(80,58).
+edge(58,97).
+edge(97,58).
+edge(58,100).
+edge(100,58).
+edge(58,104).
+edge(104,58).
+edge(58,105).
+edge(105,58).
+edge(58,109).
+edge(109,58).
+edge(58,112).
+edge(112,58).
+edge(58,119).
+edge(119,58).
+edge(58,120).
+edge(120,58).
+edge(58,121).
+edge(121,58).
+edge(58,122).
+edge(122,58).
+edge(58,125).
+edge(125,58).
+edge(58,130).
+edge(130,58).
+edge(59,70).
+edge(70,59).
+edge(59,89).
+edge(89,59).
+edge(59,109).
+edge(109,59).
+edge(59,110).
+edge(110,59).
+edge(59,120).
+edge(120,59).
+edge(59,122).
+edge(122,59).
+edge(59,125).
+edge(125,59).
+edge(60,63).
+edge(63,60).
+edge(60,67).
+edge(67,60).
+edge(60,72).
+edge(72,60).
+edge(60,82).
+edge(82,60).
+edge(60,109).
+edge(109,60).
+edge(60,131).
+edge(131,60).
+edge(60,137).
+edge(137,60).
+edge(61,73).
+edge(73,61).
+edge(61,82).
+edge(82,61).
+edge(61,96).
+edge(96,61).
+edge(61,98).
+edge(98,61).
+edge(61,101).
+edge(101,61).
+edge(61,102).
+edge(102,61).
+edge(61,107).
+edge(107,61).
+edge(61,129).
+edge(129,61).
+edge(62,72).
+edge(72,62).
+edge(62,76).
+edge(76,62).
+edge(62,90).
+edge(90,62).
+edge(62,93).
+edge(93,62).
+edge(62,95).
+edge(95,62).
+edge(62,106).
+edge(106,62).
+edge(62,108).
+edge(108,62).
+edge(62,110).
+edge(110,62).
+edge(62,128).
+edge(128,62).
+edge(62,135).
+edge(135,62).
+edge(62,136).
+edge(136,62).
+edge(63,65).
+edge(65,63).
+edge(63,87).
+edge(87,63).
+edge(63,104).
+edge(104,63).
+edge(63,105).
+edge(105,63).
+edge(63,116).
+edge(116,63).
+edge(63,118).
+edge(118,63).
+edge(63,119).
+edge(119,63).
+edge(63,120).
+edge(120,63).
+edge(63,133).
+edge(133,63).
+edge(63,140).
+edge(140,63).
+edge(64,78).
+edge(78,64).
+edge(64,81).
+edge(81,64).
+edge(64,96).
+edge(96,64).
+edge(64,101).
+edge(101,64).
+edge(64,105).
+edge(105,64).
+edge(64,117).
+edge(117,64).
+edge(64,132).
+edge(132,64).
+edge(64,136).
+edge(136,64).
+edge(65,68).
+edge(68,65).
+edge(65,83).
+edge(83,65).
+edge(65,91).
+edge(91,65).
+edge(65,99).
+edge(99,65).
+edge(65,105).
+edge(105,65).
+edge(65,124).
+edge(124,65).
+edge(65,136).
+edge(136,65).
+edge(65,140).
+edge(140,65).
+edge(66,87).
+edge(87,66).
+edge(66,95).
+edge(95,66).
+edge(66,112).
+edge(112,66).
+edge(66,113).
+edge(113,66).
+edge(66,125).
+edge(125,66).
+edge(67,77).
+edge(77,67).
+edge(67,96).
+edge(96,67).
+edge(67,115).
+edge(115,67).
+edge(67,119).
+edge(119,67).
+edge(67,140).
+edge(140,67).
+edge(68,69).
+edge(69,68).
+edge(68,75).
+edge(75,68).
+edge(68,98).
+edge(98,68).
+edge(68,111).
+edge(111,68).
+edge(68,122).
+edge(122,68).
+edge(68,126).
+edge(126,68).
+edge(68,135).
+edge(135,68).
+edge(69,74).
+edge(74,69).
+edge(69,79).
+edge(79,69).
+edge(69,84).
+edge(84,69).
+edge(69,94).
+edge(94,69).
+edge(69,96).
+edge(96,69).
+edge(69,99).
+edge(99,69).
+edge(69,103).
+edge(103,69).
+edge(69,119).
+edge(119,69).
+edge(69,130).
+edge(130,69).
+edge(69,134).
+edge(134,69).
+edge(70,80).
+edge(80,70).
+edge(70,93).
+edge(93,70).
+edge(70,96).
+edge(96,70).
+edge(70,97).
+edge(97,70).
+edge(70,127).
+edge(127,70).
+edge(70,136).
+edge(136,70).
+edge(70,137).
+edge(137,70).
+edge(71,73).
+edge(73,71).
+edge(71,85).
+edge(85,71).
+edge(72,104).
+edge(104,72).
+edge(72,118).
+edge(118,72).
+edge(72,120).
+edge(120,72).
+edge(72,132).
+edge(132,72).
+edge(73,83).
+edge(83,73).
+edge(73,99).
+edge(99,73).
+edge(73,101).
+edge(101,73).
+edge(73,109).
+edge(109,73).
+edge(74,75).
+edge(75,74).
+edge(74,87).
+edge(87,74).
+edge(74,92).
+edge(92,74).
+edge(74,103).
+edge(103,74).
+edge(74,111).
+edge(111,74).
+edge(75,78).
+edge(78,75).
+edge(75,80).
+edge(80,75).
+edge(75,88).
+edge(88,75).
+edge(75,90).
+edge(90,75).
+edge(75,115).
+edge(115,75).
+edge(75,120).
+edge(120,75).
+edge(75,125).
+edge(125,75).
+edge(75,128).
+edge(128,75).
+edge(75,129).
+edge(129,75).
+edge(75,130).
+edge(130,75).
+edge(75,136).
+edge(136,75).
+edge(76,95).
+edge(95,76).
+edge(76,100).
+edge(100,76).
+edge(76,105).
+edge(105,76).
+edge(76,113).
+edge(113,76).
+edge(76,120).
+edge(120,76).
+edge(76,129).
+edge(129,76).
+edge(76,137).
+edge(137,76).
+edge(76,138).
+edge(138,76).
+edge(76,140).
+edge(140,76).
+edge(77,83).
+edge(83,77).
+edge(77,100).
+edge(100,77).
+edge(77,109).
+edge(109,77).
+edge(77,118).
+edge(118,77).
+edge(77,135).
+edge(135,77).
+edge(77,136).
+edge(136,77).
+edge(78,89).
+edge(89,78).
+edge(78,113).
+edge(113,78).
+edge(78,120).
+edge(120,78).
+edge(78,124).
+edge(124,78).
+edge(78,125).
+edge(125,78).
+edge(78,132).
+edge(132,78).
+edge(78,135).
+edge(135,78).
+edge(79,92).
+edge(92,79).
+edge(79,102).
+edge(102,79).
+edge(79,114).
+edge(114,79).
+edge(79,115).
+edge(115,79).
+edge(79,118).
+edge(118,79).
+edge(79,128).
+edge(128,79).
+edge(79,131).
+edge(131,79).
+edge(79,140).
+edge(140,79).
+edge(80,109).
+edge(109,80).
+edge(80,111).
+edge(111,80).
+edge(80,125).
+edge(125,80).
+edge(81,83).
+edge(83,81).
+edge(81,88).
+edge(88,81).
+edge(81,105).
+edge(105,81).
+edge(81,108).
+edge(108,81).
+edge(81,123).
+edge(123,81).
+edge(82,105).
+edge(105,82).
+edge(82,108).
+edge(108,82).
+edge(82,114).
+edge(114,82).
+edge(82,135).
+edge(135,82).
+edge(82,137).
+edge(137,82).
+edge(83,85).
+edge(85,83).
+edge(83,87).
+edge(87,83).
+edge(83,90).
+edge(90,83).
+edge(83,96).
+edge(96,83).
+edge(83,98).
+edge(98,83).
+edge(83,111).
+edge(111,83).
+edge(83,119).
+edge(119,83).
+edge(83,126).
+edge(126,83).
+edge(83,128).
+edge(128,83).
+edge(83,131).
+edge(131,83).
+edge(83,134).
+edge(134,83).
+edge(84,94).
+edge(94,84).
+edge(84,107).
+edge(107,84).
+edge(84,115).
+edge(115,84).
+edge(84,125).
+edge(125,84).
+edge(85,95).
+edge(95,85).
+edge(85,100).
+edge(100,85).
+edge(85,101).
+edge(101,85).
+edge(85,107).
+edge(107,85).
+edge(85,121).
+edge(121,85).
+edge(85,125).
+edge(125,85).
+edge(85,137).
+edge(137,85).
+edge(86,97).
+edge(97,86).
+edge(86,104).
+edge(104,86).
+edge(86,105).
+edge(105,86).
+edge(86,120).
+edge(120,86).
+edge(86,130).
+edge(130,86).
+edge(87,104).
+edge(104,87).
+edge(87,109).
+edge(109,87).
+edge(87,118).
+edge(118,87).
+edge(87,123).
+edge(123,87).
+edge(87,126).
+edge(126,87).
+edge(87,127).
+edge(127,87).
+edge(87,135).
+edge(135,87).
+edge(88,95).
+edge(95,88).
+edge(88,107).
+edge(107,88).
+edge(88,108).
+edge(108,88).
+edge(88,113).
+edge(113,88).
+edge(88,125).
+edge(125,88).
+edge(88,135).
+edge(135,88).
+edge(89,92).
+edge(92,89).
+edge(89,94).
+edge(94,89).
+edge(89,98).
+edge(98,89).
+edge(89,102).
+edge(102,89).
+edge(89,106).
+edge(106,89).
+edge(89,138).
+edge(138,89).
+edge(90,114).
+edge(114,90).
+edge(90,117).
+edge(117,90).
+edge(90,121).
+edge(121,90).
+edge(90,124).
+edge(124,90).
+edge(90,128).
+edge(128,90).
+edge(90,133).
+edge(133,90).
+edge(90,137).
+edge(137,90).
+edge(90,140).
+edge(140,90).
+edge(91,92).
+edge(92,91).
+edge(91,99).
+edge(99,91).
+edge(91,111).
+edge(111,91).
+edge(91,119).
+edge(119,91).
+edge(91,120).
+edge(120,91).
+edge(91,121).
+edge(121,91).
+edge(91,132).
+edge(132,91).
+edge(92,96).
+edge(96,92).
+edge(92,102).
+edge(102,92).
+edge(92,107).
+edge(107,92).
+edge(92,117).
+edge(117,92).
+edge(92,127).
+edge(127,92).
+edge(92,130).
+edge(130,92).
+edge(93,108).
+edge(108,93).
+edge(93,115).
+edge(115,93).
+edge(93,121).
+edge(121,93).
+edge(93,126).
+edge(126,93).
+edge(93,131).
+edge(131,93).
+edge(94,97).
+edge(97,94).
+edge(94,114).
+edge(114,94).
+edge(94,135).
+edge(135,94).
+edge(95,103).
+edge(103,95).
+edge(95,104).
+edge(104,95).
+edge(95,111).
+edge(111,95).
+edge(95,136).
+edge(136,95).
+edge(96,98).
+edge(98,96).
+edge(96,109).
+edge(109,96).
+edge(96,110).
+edge(110,96).
+edge(96,123).
+edge(123,96).
+edge(96,140).
+edge(140,96).
+edge(97,104).
+edge(104,97).
+edge(97,106).
+edge(106,97).
+edge(97,115).
+edge(115,97).
+edge(97,118).
+edge(118,97).
+edge(97,125).
+edge(125,97).
+edge(97,129).
+edge(129,97).
+edge(98,99).
+edge(99,98).
+edge(98,109).
+edge(109,98).
+edge(98,131).
+edge(131,98).
+edge(98,132).
+edge(132,98).
+edge(99,112).
+edge(112,99).
+edge(99,139).
+edge(139,99).
+edge(100,104).
+edge(104,100).
+edge(100,120).
+edge(120,100).
+edge(100,122).
+edge(122,100).
+edge(100,128).
+edge(128,100).
+edge(101,140).
+edge(140,101).
+edge(102,116).
+edge(116,102).
+edge(102,136).
+edge(136,102).
+edge(103,104).
+edge(104,103).
+edge(103,111).
+edge(111,103).
+edge(103,126).
+edge(126,103).
+edge(103,132).
+edge(132,103).
+edge(104,108).
+edge(108,104).
+edge(104,110).
+edge(110,104).
+edge(104,114).
+edge(114,104).
+edge(104,137).
+edge(137,104).
+edge(104,139).
+edge(139,104).
+edge(104,140).
+edge(140,104).
+edge(105,110).
+edge(110,105).
+edge(105,112).
+edge(112,105).
+edge(105,138).
+edge(138,105).
+edge(106,109).
+edge(109,106).
+edge(106,112).
+edge(112,106).
+edge(106,113).
+edge(113,106).
+edge(106,119).
+edge(119,106).
+edge(106,128).
+edge(128,106).
+edge(106,138).
+edge(138,106).
+edge(107,125).
+edge(125,107).
+edge(107,132).
+edge(132,107).
+edge(107,137).
+edge(137,107).
+edge(108,112).
+edge(112,108).
+edge(108,117).
+edge(117,108).
+edge(108,126).
+edge(126,108).
+edge(108,134).
+edge(134,108).
+edge(109,117).
+edge(117,109).
+edge(110,113).
+edge(113,110).
+edge(110,118).
+edge(118,110).
+edge(110,137).
+edge(137,110).
+edge(111,125).
+edge(125,111).
+edge(111,138).
+edge(138,111).
+edge(111,140).
+edge(140,111).
+edge(112,125).
+edge(125,112).
+edge(112,132).
+edge(132,112).
+edge(112,140).
+edge(140,112).
+edge(113,129).
+edge(129,113).
+edge(113,136).
+edge(136,113).
+edge(113,137).
+edge(137,113).
+edge(114,124).
+edge(124,114).
+edge(115,116).
+edge(116,115).
+edge(115,122).
+edge(122,115).
+edge(115,129).
+edge(129,115).
+edge(115,130).
+edge(130,115).
+edge(115,132).
+edge(132,115).
+edge(116,123).
+edge(123,116).
+edge(116,130).
+edge(130,116).
+edge(116,131).
+edge(131,116).
+edge(116,132).
+edge(132,116).
+edge(116,136).
+edge(136,116).
+edge(117,123).
+edge(123,117).
+edge(117,124).
+edge(124,117).
+edge(117,139).
+edge(139,117).
+edge(117,140).
+edge(140,117).
+edge(118,121).
+edge(121,118).
+edge(119,125).
+edge(125,119).
+edge(119,129).
+edge(129,119).
+edge(119,132).
+edge(132,119).
+edge(120,125).
+edge(125,120).
+edge(120,134).
+edge(134,120).
+edge(121,128).
+edge(128,121).
+edge(122,129).
+edge(129,122).
+edge(123,134).
+edge(134,123).
+edge(124,127).
+edge(127,124).
+edge(124,129).
+edge(129,124).
+edge(125,127).
+edge(127,125).
+edge(125,128).
+edge(128,125).
+edge(127,138).
+edge(138,127).
+edge(128,133).
+edge(133,128).
+edge(128,138).
+edge(138,128).
+edge(129,133).
+edge(133,129).
+edge(130,139).
+edge(139,130).
+edge(132,135).
+edge(135,132).
+edge(133,140).
+edge(140,133).
+edge(135,138).
+edge(138,135).
+edge(135,140).
+edge(140,135).
+edge(136,139).
+edge(139,136).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0040-graph_colouring-140-0.lp b/examples/clingo/expansion/GraphColouring/instances/0040-graph_colouring-140-0.lp
new file mode 100644
index 0000000..16663b3
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0040-graph_colouring-140-0.lp
@@ -0,0 +1,2214 @@
+#const n=140.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+edge(1,6).
+edge(6,1).
+edge(1,7).
+edge(7,1).
+edge(1,22).
+edge(22,1).
+edge(1,29).
+edge(29,1).
+edge(1,48).
+edge(48,1).
+edge(1,50).
+edge(50,1).
+edge(1,51).
+edge(51,1).
+edge(1,62).
+edge(62,1).
+edge(1,69).
+edge(69,1).
+edge(1,75).
+edge(75,1).
+edge(1,103).
+edge(103,1).
+edge(1,104).
+edge(104,1).
+edge(1,110).
+edge(110,1).
+edge(1,111).
+edge(111,1).
+edge(1,117).
+edge(117,1).
+edge(1,127).
+edge(127,1).
+edge(1,129).
+edge(129,1).
+edge(2,26).
+edge(26,2).
+edge(2,28).
+edge(28,2).
+edge(2,30).
+edge(30,2).
+edge(2,44).
+edge(44,2).
+edge(2,65).
+edge(65,2).
+edge(2,67).
+edge(67,2).
+edge(2,77).
+edge(77,2).
+edge(2,78).
+edge(78,2).
+edge(2,100).
+edge(100,2).
+edge(2,115).
+edge(115,2).
+edge(2,120).
+edge(120,2).
+edge(2,127).
+edge(127,2).
+edge(2,130).
+edge(130,2).
+edge(2,136).
+edge(136,2).
+edge(3,14).
+edge(14,3).
+edge(3,16).
+edge(16,3).
+edge(3,22).
+edge(22,3).
+edge(3,23).
+edge(23,3).
+edge(3,34).
+edge(34,3).
+edge(3,70).
+edge(70,3).
+edge(3,83).
+edge(83,3).
+edge(3,91).
+edge(91,3).
+edge(3,111).
+edge(111,3).
+edge(3,140).
+edge(140,3).
+edge(4,16).
+edge(16,4).
+edge(4,23).
+edge(23,4).
+edge(4,50).
+edge(50,4).
+edge(4,53).
+edge(53,4).
+edge(4,54).
+edge(54,4).
+edge(4,60).
+edge(60,4).
+edge(4,73).
+edge(73,4).
+edge(4,98).
+edge(98,4).
+edge(4,104).
+edge(104,4).
+edge(4,108).
+edge(108,4).
+edge(4,114).
+edge(114,4).
+edge(4,121).
+edge(121,4).
+edge(4,125).
+edge(125,4).
+edge(4,128).
+edge(128,4).
+edge(4,133).
+edge(133,4).
+edge(4,135).
+edge(135,4).
+edge(5,8).
+edge(8,5).
+edge(5,12).
+edge(12,5).
+edge(5,13).
+edge(13,5).
+edge(5,29).
+edge(29,5).
+edge(5,44).
+edge(44,5).
+edge(5,49).
+edge(49,5).
+edge(5,65).
+edge(65,5).
+edge(5,79).
+edge(79,5).
+edge(5,81).
+edge(81,5).
+edge(5,107).
+edge(107,5).
+edge(5,115).
+edge(115,5).
+edge(5,123).
+edge(123,5).
+edge(5,125).
+edge(125,5).
+edge(5,129).
+edge(129,5).
+edge(6,9).
+edge(9,6).
+edge(6,12).
+edge(12,6).
+edge(6,14).
+edge(14,6).
+edge(6,36).
+edge(36,6).
+edge(6,37).
+edge(37,6).
+edge(6,51).
+edge(51,6).
+edge(6,72).
+edge(72,6).
+edge(6,82).
+edge(82,6).
+edge(6,84).
+edge(84,6).
+edge(6,100).
+edge(100,6).
+edge(6,105).
+edge(105,6).
+edge(6,118).
+edge(118,6).
+edge(6,133).
+edge(133,6).
+edge(6,134).
+edge(134,6).
+edge(7,9).
+edge(9,7).
+edge(7,11).
+edge(11,7).
+edge(7,22).
+edge(22,7).
+edge(7,34).
+edge(34,7).
+edge(7,60).
+edge(60,7).
+edge(7,68).
+edge(68,7).
+edge(7,71).
+edge(71,7).
+edge(7,75).
+edge(75,7).
+edge(7,113).
+edge(113,7).
+edge(7,119).
+edge(119,7).
+edge(8,12).
+edge(12,8).
+edge(8,23).
+edge(23,8).
+edge(8,35).
+edge(35,8).
+edge(8,69).
+edge(69,8).
+edge(8,71).
+edge(71,8).
+edge(8,77).
+edge(77,8).
+edge(8,78).
+edge(78,8).
+edge(8,79).
+edge(79,8).
+edge(8,80).
+edge(80,8).
+edge(8,93).
+edge(93,8).
+edge(8,114).
+edge(114,8).
+edge(8,115).
+edge(115,8).
+edge(8,121).
+edge(121,8).
+edge(8,125).
+edge(125,8).
+edge(8,128).
+edge(128,8).
+edge(8,129).
+edge(129,8).
+edge(8,133).
+edge(133,8).
+edge(9,23).
+edge(23,9).
+edge(9,29).
+edge(29,9).
+edge(9,32).
+edge(32,9).
+edge(9,38).
+edge(38,9).
+edge(9,49).
+edge(49,9).
+edge(9,51).
+edge(51,9).
+edge(9,58).
+edge(58,9).
+edge(9,60).
+edge(60,9).
+edge(9,62).
+edge(62,9).
+edge(9,64).
+edge(64,9).
+edge(9,66).
+edge(66,9).
+edge(9,73).
+edge(73,9).
+edge(9,87).
+edge(87,9).
+edge(9,90).
+edge(90,9).
+edge(9,93).
+edge(93,9).
+edge(9,94).
+edge(94,9).
+edge(9,139).
+edge(139,9).
+edge(10,19).
+edge(19,10).
+edge(10,24).
+edge(24,10).
+edge(10,32).
+edge(32,10).
+edge(10,36).
+edge(36,10).
+edge(10,59).
+edge(59,10).
+edge(10,72).
+edge(72,10).
+edge(10,76).
+edge(76,10).
+edge(10,77).
+edge(77,10).
+edge(10,80).
+edge(80,10).
+edge(10,95).
+edge(95,10).
+edge(10,96).
+edge(96,10).
+edge(10,123).
+edge(123,10).
+edge(10,140).
+edge(140,10).
+edge(11,74).
+edge(74,11).
+edge(11,101).
+edge(101,11).
+edge(11,106).
+edge(106,11).
+edge(11,119).
+edge(119,11).
+edge(11,125).
+edge(125,11).
+edge(11,128).
+edge(128,11).
+edge(11,131).
+edge(131,11).
+edge(12,35).
+edge(35,12).
+edge(12,40).
+edge(40,12).
+edge(12,46).
+edge(46,12).
+edge(12,48).
+edge(48,12).
+edge(12,64).
+edge(64,12).
+edge(12,72).
+edge(72,12).
+edge(12,104).
+edge(104,12).
+edge(12,106).
+edge(106,12).
+edge(12,120).
+edge(120,12).
+edge(12,127).
+edge(127,12).
+edge(12,128).
+edge(128,12).
+edge(12,137).
+edge(137,12).
+edge(12,139).
+edge(139,12).
+edge(12,140).
+edge(140,12).
+edge(13,19).
+edge(19,13).
+edge(13,22).
+edge(22,13).
+edge(13,23).
+edge(23,13).
+edge(13,26).
+edge(26,13).
+edge(13,37).
+edge(37,13).
+edge(13,38).
+edge(38,13).
+edge(13,40).
+edge(40,13).
+edge(13,56).
+edge(56,13).
+edge(13,57).
+edge(57,13).
+edge(13,64).
+edge(64,13).
+edge(13,74).
+edge(74,13).
+edge(13,76).
+edge(76,13).
+edge(13,77).
+edge(77,13).
+edge(13,82).
+edge(82,13).
+edge(13,84).
+edge(84,13).
+edge(13,91).
+edge(91,13).
+edge(13,96).
+edge(96,13).
+edge(13,101).
+edge(101,13).
+edge(13,102).
+edge(102,13).
+edge(13,111).
+edge(111,13).
+edge(13,113).
+edge(113,13).
+edge(13,118).
+edge(118,13).
+edge(13,122).
+edge(122,13).
+edge(13,126).
+edge(126,13).
+edge(13,129).
+edge(129,13).
+edge(13,130).
+edge(130,13).
+edge(13,135).
+edge(135,13).
+edge(14,20).
+edge(20,14).
+edge(14,38).
+edge(38,14).
+edge(14,57).
+edge(57,14).
+edge(14,66).
+edge(66,14).
+edge(14,90).
+edge(90,14).
+edge(14,102).
+edge(102,14).
+edge(14,115).
+edge(115,14).
+edge(14,120).
+edge(120,14).
+edge(14,130).
+edge(130,14).
+edge(14,132).
+edge(132,14).
+edge(14,135).
+edge(135,14).
+edge(15,28).
+edge(28,15).
+edge(15,32).
+edge(32,15).
+edge(15,36).
+edge(36,15).
+edge(15,41).
+edge(41,15).
+edge(15,53).
+edge(53,15).
+edge(15,65).
+edge(65,15).
+edge(15,69).
+edge(69,15).
+edge(15,74).
+edge(74,15).
+edge(15,80).
+edge(80,15).
+edge(15,82).
+edge(82,15).
+edge(15,126).
+edge(126,15).
+edge(15,128).
+edge(128,15).
+edge(15,131).
+edge(131,15).
+edge(15,139).
+edge(139,15).
+edge(16,25).
+edge(25,16).
+edge(16,26).
+edge(26,16).
+edge(16,32).
+edge(32,16).
+edge(16,34).
+edge(34,16).
+edge(16,39).
+edge(39,16).
+edge(16,46).
+edge(46,16).
+edge(16,60).
+edge(60,16).
+edge(16,63).
+edge(63,16).
+edge(16,64).
+edge(64,16).
+edge(16,67).
+edge(67,16).
+edge(16,76).
+edge(76,16).
+edge(16,110).
+edge(110,16).
+edge(16,123).
+edge(123,16).
+edge(17,18).
+edge(18,17).
+edge(17,35).
+edge(35,17).
+edge(17,49).
+edge(49,17).
+edge(17,73).
+edge(73,17).
+edge(17,82).
+edge(82,17).
+edge(17,85).
+edge(85,17).
+edge(17,94).
+edge(94,17).
+edge(17,117).
+edge(117,17).
+edge(17,122).
+edge(122,17).
+edge(17,139).
+edge(139,17).
+edge(18,58).
+edge(58,18).
+edge(18,68).
+edge(68,18).
+edge(18,69).
+edge(69,18).
+edge(18,82).
+edge(82,18).
+edge(18,86).
+edge(86,18).
+edge(18,89).
+edge(89,18).
+edge(18,95).
+edge(95,18).
+edge(18,96).
+edge(96,18).
+edge(18,103).
+edge(103,18).
+edge(18,104).
+edge(104,18).
+edge(18,129).
+edge(129,18).
+edge(19,27).
+edge(27,19).
+edge(19,34).
+edge(34,19).
+edge(19,52).
+edge(52,19).
+edge(19,55).
+edge(55,19).
+edge(19,56).
+edge(56,19).
+edge(19,57).
+edge(57,19).
+edge(19,62).
+edge(62,19).
+edge(19,69).
+edge(69,19).
+edge(19,72).
+edge(72,19).
+edge(19,76).
+edge(76,19).
+edge(19,90).
+edge(90,19).
+edge(19,98).
+edge(98,19).
+edge(19,104).
+edge(104,19).
+edge(19,114).
+edge(114,19).
+edge(19,134).
+edge(134,19).
+edge(19,138).
+edge(138,19).
+edge(20,33).
+edge(33,20).
+edge(20,39).
+edge(39,20).
+edge(20,44).
+edge(44,20).
+edge(20,45).
+edge(45,20).
+edge(20,66).
+edge(66,20).
+edge(20,82).
+edge(82,20).
+edge(20,97).
+edge(97,20).
+edge(20,98).
+edge(98,20).
+edge(20,102).
+edge(102,20).
+edge(20,105).
+edge(105,20).
+edge(20,112).
+edge(112,20).
+edge(20,117).
+edge(117,20).
+edge(20,130).
+edge(130,20).
+edge(20,131).
+edge(131,20).
+edge(20,135).
+edge(135,20).
+edge(21,27).
+edge(27,21).
+edge(21,31).
+edge(31,21).
+edge(21,34).
+edge(34,21).
+edge(21,39).
+edge(39,21).
+edge(21,44).
+edge(44,21).
+edge(21,49).
+edge(49,21).
+edge(21,51).
+edge(51,21).
+edge(21,56).
+edge(56,21).
+edge(21,60).
+edge(60,21).
+edge(21,65).
+edge(65,21).
+edge(21,66).
+edge(66,21).
+edge(21,101).
+edge(101,21).
+edge(21,106).
+edge(106,21).
+edge(21,110).
+edge(110,21).
+edge(22,27).
+edge(27,22).
+edge(22,42).
+edge(42,22).
+edge(22,49).
+edge(49,22).
+edge(22,58).
+edge(58,22).
+edge(22,71).
+edge(71,22).
+edge(22,73).
+edge(73,22).
+edge(22,82).
+edge(82,22).
+edge(22,90).
+edge(90,22).
+edge(22,103).
+edge(103,22).
+edge(22,136).
+edge(136,22).
+edge(23,25).
+edge(25,23).
+edge(23,45).
+edge(45,23).
+edge(23,56).
+edge(56,23).
+edge(23,69).
+edge(69,23).
+edge(23,88).
+edge(88,23).
+edge(23,91).
+edge(91,23).
+edge(23,92).
+edge(92,23).
+edge(23,93).
+edge(93,23).
+edge(23,94).
+edge(94,23).
+edge(23,95).
+edge(95,23).
+edge(23,96).
+edge(96,23).
+edge(23,107).
+edge(107,23).
+edge(23,118).
+edge(118,23).
+edge(23,120).
+edge(120,23).
+edge(23,123).
+edge(123,23).
+edge(23,132).
+edge(132,23).
+edge(23,135).
+edge(135,23).
+edge(24,36).
+edge(36,24).
+edge(24,48).
+edge(48,24).
+edge(24,72).
+edge(72,24).
+edge(24,81).
+edge(81,24).
+edge(24,82).
+edge(82,24).
+edge(24,83).
+edge(83,24).
+edge(24,84).
+edge(84,24).
+edge(24,110).
+edge(110,24).
+edge(24,114).
+edge(114,24).
+edge(24,121).
+edge(121,24).
+edge(24,123).
+edge(123,24).
+edge(25,32).
+edge(32,25).
+edge(25,41).
+edge(41,25).
+edge(25,89).
+edge(89,25).
+edge(25,94).
+edge(94,25).
+edge(25,99).
+edge(99,25).
+edge(25,101).
+edge(101,25).
+edge(25,110).
+edge(110,25).
+edge(25,112).
+edge(112,25).
+edge(25,126).
+edge(126,25).
+edge(25,131).
+edge(131,25).
+edge(25,140).
+edge(140,25).
+edge(26,28).
+edge(28,26).
+edge(26,75).
+edge(75,26).
+edge(26,99).
+edge(99,26).
+edge(26,101).
+edge(101,26).
+edge(26,112).
+edge(112,26).
+edge(26,115).
+edge(115,26).
+edge(26,127).
+edge(127,26).
+edge(26,130).
+edge(130,26).
+edge(26,135).
+edge(135,26).
+edge(27,33).
+edge(33,27).
+edge(27,34).
+edge(34,27).
+edge(27,43).
+edge(43,27).
+edge(27,70).
+edge(70,27).
+edge(27,74).
+edge(74,27).
+edge(27,78).
+edge(78,27).
+edge(27,100).
+edge(100,27).
+edge(27,108).
+edge(108,27).
+edge(27,122).
+edge(122,27).
+edge(27,127).
+edge(127,27).
+edge(27,129).
+edge(129,27).
+edge(27,131).
+edge(131,27).
+edge(27,134).
+edge(134,27).
+edge(27,135).
+edge(135,27).
+edge(28,46).
+edge(46,28).
+edge(28,50).
+edge(50,28).
+edge(28,57).
+edge(57,28).
+edge(28,64).
+edge(64,28).
+edge(28,67).
+edge(67,28).
+edge(28,96).
+edge(96,28).
+edge(28,109).
+edge(109,28).
+edge(28,118).
+edge(118,28).
+edge(28,135).
+edge(135,28).
+edge(28,140).
+edge(140,28).
+edge(29,31).
+edge(31,29).
+edge(29,56).
+edge(56,29).
+edge(29,61).
+edge(61,29).
+edge(29,68).
+edge(68,29).
+edge(29,80).
+edge(80,29).
+edge(29,82).
+edge(82,29).
+edge(29,91).
+edge(91,29).
+edge(29,96).
+edge(96,29).
+edge(29,97).
+edge(97,29).
+edge(29,119).
+edge(119,29).
+edge(29,137).
+edge(137,29).
+edge(30,35).
+edge(35,30).
+edge(30,43).
+edge(43,30).
+edge(30,48).
+edge(48,30).
+edge(30,56).
+edge(56,30).
+edge(30,61).
+edge(61,30).
+edge(30,63).
+edge(63,30).
+edge(30,67).
+edge(67,30).
+edge(30,72).
+edge(72,30).
+edge(30,75).
+edge(75,30).
+edge(30,80).
+edge(80,30).
+edge(30,103).
+edge(103,30).
+edge(30,104).
+edge(104,30).
+edge(30,108).
+edge(108,30).
+edge(30,130).
+edge(130,30).
+edge(30,134).
+edge(134,30).
+edge(31,45).
+edge(45,31).
+edge(31,47).
+edge(47,31).
+edge(31,50).
+edge(50,31).
+edge(31,54).
+edge(54,31).
+edge(31,84).
+edge(84,31).
+edge(31,88).
+edge(88,31).
+edge(31,93).
+edge(93,31).
+edge(31,120).
+edge(120,31).
+edge(31,134).
+edge(134,31).
+edge(31,135).
+edge(135,31).
+edge(31,136).
+edge(136,31).
+edge(31,138).
+edge(138,31).
+edge(32,39).
+edge(39,32).
+edge(32,40).
+edge(40,32).
+edge(32,44).
+edge(44,32).
+edge(32,53).
+edge(53,32).
+edge(32,63).
+edge(63,32).
+edge(32,84).
+edge(84,32).
+edge(32,95).
+edge(95,32).
+edge(32,97).
+edge(97,32).
+edge(32,103).
+edge(103,32).
+edge(32,108).
+edge(108,32).
+edge(32,132).
+edge(132,32).
+edge(32,133).
+edge(133,32).
+edge(32,139).
+edge(139,32).
+edge(33,51).
+edge(51,33).
+edge(33,53).
+edge(53,33).
+edge(33,54).
+edge(54,33).
+edge(33,63).
+edge(63,33).
+edge(33,72).
+edge(72,33).
+edge(33,81).
+edge(81,33).
+edge(33,92).
+edge(92,33).
+edge(33,102).
+edge(102,33).
+edge(33,106).
+edge(106,33).
+edge(33,117).
+edge(117,33).
+edge(33,131).
+edge(131,33).
+edge(34,36).
+edge(36,34).
+edge(34,42).
+edge(42,34).
+edge(34,43).
+edge(43,34).
+edge(34,47).
+edge(47,34).
+edge(34,67).
+edge(67,34).
+edge(34,86).
+edge(86,34).
+edge(34,100).
+edge(100,34).
+edge(34,115).
+edge(115,34).
+edge(34,130).
+edge(130,34).
+edge(35,48).
+edge(48,35).
+edge(35,89).
+edge(89,35).
+edge(35,93).
+edge(93,35).
+edge(35,104).
+edge(104,35).
+edge(35,113).
+edge(113,35).
+edge(35,120).
+edge(120,35).
+edge(35,136).
+edge(136,35).
+edge(36,39).
+edge(39,36).
+edge(36,40).
+edge(40,36).
+edge(36,42).
+edge(42,36).
+edge(36,44).
+edge(44,36).
+edge(36,58).
+edge(58,36).
+edge(36,76).
+edge(76,36).
+edge(36,85).
+edge(85,36).
+edge(36,92).
+edge(92,36).
+edge(36,110).
+edge(110,36).
+edge(36,121).
+edge(121,36).
+edge(36,128).
+edge(128,36).
+edge(36,134).
+edge(134,36).
+edge(37,39).
+edge(39,37).
+edge(37,45).
+edge(45,37).
+edge(37,55).
+edge(55,37).
+edge(37,57).
+edge(57,37).
+edge(37,80).
+edge(80,37).
+edge(37,86).
+edge(86,37).
+edge(37,91).
+edge(91,37).
+edge(37,98).
+edge(98,37).
+edge(37,99).
+edge(99,37).
+edge(37,112).
+edge(112,37).
+edge(37,138).
+edge(138,37).
+edge(38,39).
+edge(39,38).
+edge(38,46).
+edge(46,38).
+edge(38,48).
+edge(48,38).
+edge(38,52).
+edge(52,38).
+edge(38,64).
+edge(64,38).
+edge(38,65).
+edge(65,38).
+edge(38,91).
+edge(91,38).
+edge(38,94).
+edge(94,38).
+edge(38,131).
+edge(131,38).
+edge(39,58).
+edge(58,39).
+edge(39,62).
+edge(62,39).
+edge(39,92).
+edge(92,39).
+edge(39,98).
+edge(98,39).
+edge(39,100).
+edge(100,39).
+edge(39,102).
+edge(102,39).
+edge(39,118).
+edge(118,39).
+edge(39,129).
+edge(129,39).
+edge(40,48).
+edge(48,40).
+edge(40,60).
+edge(60,40).
+edge(40,76).
+edge(76,40).
+edge(40,88).
+edge(88,40).
+edge(40,89).
+edge(89,40).
+edge(40,94).
+edge(94,40).
+edge(40,119).
+edge(119,40).
+edge(41,52).
+edge(52,41).
+edge(41,53).
+edge(53,41).
+edge(41,85).
+edge(85,41).
+edge(41,94).
+edge(94,41).
+edge(41,99).
+edge(99,41).
+edge(41,100).
+edge(100,41).
+edge(41,103).
+edge(103,41).
+edge(41,104).
+edge(104,41).
+edge(41,118).
+edge(118,41).
+edge(41,138).
+edge(138,41).
+edge(42,54).
+edge(54,42).
+edge(42,69).
+edge(69,42).
+edge(42,84).
+edge(84,42).
+edge(42,89).
+edge(89,42).
+edge(42,90).
+edge(90,42).
+edge(42,96).
+edge(96,42).
+edge(42,104).
+edge(104,42).
+edge(42,109).
+edge(109,42).
+edge(42,122).
+edge(122,42).
+edge(42,130).
+edge(130,42).
+edge(42,132).
+edge(132,42).
+edge(42,138).
+edge(138,42).
+edge(42,140).
+edge(140,42).
+edge(43,50).
+edge(50,43).
+edge(43,60).
+edge(60,43).
+edge(43,61).
+edge(61,43).
+edge(43,66).
+edge(66,43).
+edge(43,68).
+edge(68,43).
+edge(43,76).
+edge(76,43).
+edge(43,86).
+edge(86,43).
+edge(43,92).
+edge(92,43).
+edge(43,96).
+edge(96,43).
+edge(43,98).
+edge(98,43).
+edge(43,112).
+edge(112,43).
+edge(43,116).
+edge(116,43).
+edge(43,119).
+edge(119,43).
+edge(43,123).
+edge(123,43).
+edge(43,127).
+edge(127,43).
+edge(43,134).
+edge(134,43).
+edge(44,62).
+edge(62,44).
+edge(44,81).
+edge(81,44).
+edge(44,82).
+edge(82,44).
+edge(44,94).
+edge(94,44).
+edge(44,100).
+edge(100,44).
+edge(44,103).
+edge(103,44).
+edge(44,111).
+edge(111,44).
+edge(44,121).
+edge(121,44).
+edge(44,134).
+edge(134,44).
+edge(44,136).
+edge(136,44).
+edge(45,46).
+edge(46,45).
+edge(45,48).
+edge(48,45).
+edge(45,72).
+edge(72,45).
+edge(45,76).
+edge(76,45).
+edge(45,78).
+edge(78,45).
+edge(45,92).
+edge(92,45).
+edge(45,104).
+edge(104,45).
+edge(45,105).
+edge(105,45).
+edge(45,117).
+edge(117,45).
+edge(45,132).
+edge(132,45).
+edge(45,133).
+edge(133,45).
+edge(45,136).
+edge(136,45).
+edge(46,49).
+edge(49,46).
+edge(46,69).
+edge(69,46).
+edge(46,120).
+edge(120,46).
+edge(46,130).
+edge(130,46).
+edge(47,75).
+edge(75,47).
+edge(47,81).
+edge(81,47).
+edge(47,106).
+edge(106,47).
+edge(47,115).
+edge(115,47).
+edge(47,128).
+edge(128,47).
+edge(47,135).
+edge(135,47).
+edge(47,139).
+edge(139,47).
+edge(48,59).
+edge(59,48).
+edge(48,60).
+edge(60,48).
+edge(48,81).
+edge(81,48).
+edge(48,108).
+edge(108,48).
+edge(48,127).
+edge(127,48).
+edge(49,72).
+edge(72,49).
+edge(49,82).
+edge(82,49).
+edge(49,92).
+edge(92,49).
+edge(49,96).
+edge(96,49).
+edge(49,97).
+edge(97,49).
+edge(49,107).
+edge(107,49).
+edge(49,117).
+edge(117,49).
+edge(49,138).
+edge(138,49).
+edge(50,56).
+edge(56,50).
+edge(50,65).
+edge(65,50).
+edge(50,67).
+edge(67,50).
+edge(50,71).
+edge(71,50).
+edge(50,95).
+edge(95,50).
+edge(50,100).
+edge(100,50).
+edge(50,102).
+edge(102,50).
+edge(50,103).
+edge(103,50).
+edge(50,119).
+edge(119,50).
+edge(50,128).
+edge(128,50).
+edge(50,129).
+edge(129,50).
+edge(51,60).
+edge(60,51).
+edge(51,67).
+edge(67,51).
+edge(51,81).
+edge(81,51).
+edge(51,83).
+edge(83,51).
+edge(51,96).
+edge(96,51).
+edge(51,117).
+edge(117,51).
+edge(51,128).
+edge(128,51).
+edge(51,139).
+edge(139,51).
+edge(52,55).
+edge(55,52).
+edge(52,68).
+edge(68,52).
+edge(52,75).
+edge(75,52).
+edge(52,88).
+edge(88,52).
+edge(52,93).
+edge(93,52).
+edge(52,100).
+edge(100,52).
+edge(52,129).
+edge(129,52).
+edge(52,133).
+edge(133,52).
+edge(52,134).
+edge(134,52).
+edge(52,136).
+edge(136,52).
+edge(53,64).
+edge(64,53).
+edge(53,65).
+edge(65,53).
+edge(53,70).
+edge(70,53).
+edge(53,75).
+edge(75,53).
+edge(53,83).
+edge(83,53).
+edge(53,84).
+edge(84,53).
+edge(53,90).
+edge(90,53).
+edge(53,106).
+edge(106,53).
+edge(53,114).
+edge(114,53).
+edge(53,125).
+edge(125,53).
+edge(53,132).
+edge(132,53).
+edge(53,134).
+edge(134,53).
+edge(54,79).
+edge(79,54).
+edge(54,80).
+edge(80,54).
+edge(54,81).
+edge(81,54).
+edge(54,90).
+edge(90,54).
+edge(54,94).
+edge(94,54).
+edge(54,116).
+edge(116,54).
+edge(54,122).
+edge(122,54).
+edge(54,134).
+edge(134,54).
+edge(55,58).
+edge(58,55).
+edge(55,71).
+edge(71,55).
+edge(55,85).
+edge(85,55).
+edge(55,89).
+edge(89,55).
+edge(55,90).
+edge(90,55).
+edge(55,101).
+edge(101,55).
+edge(55,102).
+edge(102,55).
+edge(55,105).
+edge(105,55).
+edge(55,130).
+edge(130,55).
+edge(55,136).
+edge(136,55).
+edge(56,57).
+edge(57,56).
+edge(56,68).
+edge(68,56).
+edge(56,100).
+edge(100,56).
+edge(56,106).
+edge(106,56).
+edge(56,137).
+edge(137,56).
+edge(56,139).
+edge(139,56).
+edge(57,77).
+edge(77,57).
+edge(57,83).
+edge(83,57).
+edge(57,100).
+edge(100,57).
+edge(57,110).
+edge(110,57).
+edge(57,129).
+edge(129,57).
+edge(57,139).
+edge(139,57).
+edge(58,62).
+edge(62,58).
+edge(58,70).
+edge(70,58).
+edge(58,85).
+edge(85,58).
+edge(58,95).
+edge(95,58).
+edge(58,122).
+edge(122,58).
+edge(58,127).
+edge(127,58).
+edge(58,137).
+edge(137,58).
+edge(59,92).
+edge(92,59).
+edge(59,94).
+edge(94,59).
+edge(59,96).
+edge(96,59).
+edge(59,100).
+edge(100,59).
+edge(59,120).
+edge(120,59).
+edge(59,121).
+edge(121,59).
+edge(59,130).
+edge(130,59).
+edge(59,132).
+edge(132,59).
+edge(59,133).
+edge(133,59).
+edge(60,63).
+edge(63,60).
+edge(60,65).
+edge(65,60).
+edge(60,84).
+edge(84,60).
+edge(60,99).
+edge(99,60).
+edge(60,104).
+edge(104,60).
+edge(60,115).
+edge(115,60).
+edge(60,116).
+edge(116,60).
+edge(60,124).
+edge(124,60).
+edge(60,133).
+edge(133,60).
+edge(61,62).
+edge(62,61).
+edge(61,73).
+edge(73,61).
+edge(61,84).
+edge(84,61).
+edge(61,87).
+edge(87,61).
+edge(61,106).
+edge(106,61).
+edge(61,119).
+edge(119,61).
+edge(61,125).
+edge(125,61).
+edge(62,93).
+edge(93,62).
+edge(62,101).
+edge(101,62).
+edge(62,102).
+edge(102,62).
+edge(62,103).
+edge(103,62).
+edge(62,113).
+edge(113,62).
+edge(63,103).
+edge(103,63).
+edge(63,120).
+edge(120,63).
+edge(63,125).
+edge(125,63).
+edge(63,135).
+edge(135,63).
+edge(63,138).
+edge(138,63).
+edge(64,71).
+edge(71,64).
+edge(64,81).
+edge(81,64).
+edge(64,84).
+edge(84,64).
+edge(64,86).
+edge(86,64).
+edge(64,89).
+edge(89,64).
+edge(64,95).
+edge(95,64).
+edge(64,126).
+edge(126,64).
+edge(64,137).
+edge(137,64).
+edge(65,82).
+edge(82,65).
+edge(65,92).
+edge(92,65).
+edge(65,98).
+edge(98,65).
+edge(65,100).
+edge(100,65).
+edge(65,104).
+edge(104,65).
+edge(65,116).
+edge(116,65).
+edge(65,117).
+edge(117,65).
+edge(66,72).
+edge(72,66).
+edge(66,80).
+edge(80,66).
+edge(66,83).
+edge(83,66).
+edge(66,94).
+edge(94,66).
+edge(66,110).
+edge(110,66).
+edge(66,111).
+edge(111,66).
+edge(66,131).
+edge(131,66).
+edge(67,73).
+edge(73,67).
+edge(67,81).
+edge(81,67).
+edge(67,84).
+edge(84,67).
+edge(67,85).
+edge(85,67).
+edge(67,91).
+edge(91,67).
+edge(67,96).
+edge(96,67).
+edge(67,103).
+edge(103,67).
+edge(67,123).
+edge(123,67).
+edge(67,137).
+edge(137,67).
+edge(67,139).
+edge(139,67).
+edge(68,70).
+edge(70,68).
+edge(68,73).
+edge(73,68).
+edge(68,74).
+edge(74,68).
+edge(68,82).
+edge(82,68).
+edge(68,85).
+edge(85,68).
+edge(68,86).
+edge(86,68).
+edge(68,91).
+edge(91,68).
+edge(68,101).
+edge(101,68).
+edge(68,108).
+edge(108,68).
+edge(68,110).
+edge(110,68).
+edge(68,116).
+edge(116,68).
+edge(68,118).
+edge(118,68).
+edge(68,121).
+edge(121,68).
+edge(68,130).
+edge(130,68).
+edge(68,131).
+edge(131,68).
+edge(69,71).
+edge(71,69).
+edge(69,78).
+edge(78,69).
+edge(69,91).
+edge(91,69).
+edge(69,92).
+edge(92,69).
+edge(69,100).
+edge(100,69).
+edge(69,101).
+edge(101,69).
+edge(69,105).
+edge(105,69).
+edge(69,120).
+edge(120,69).
+edge(70,75).
+edge(75,70).
+edge(70,83).
+edge(83,70).
+edge(70,94).
+edge(94,70).
+edge(70,96).
+edge(96,70).
+edge(70,123).
+edge(123,70).
+edge(70,135).
+edge(135,70).
+edge(70,140).
+edge(140,70).
+edge(71,72).
+edge(72,71).
+edge(71,74).
+edge(74,71).
+edge(71,76).
+edge(76,71).
+edge(71,90).
+edge(90,71).
+edge(71,95).
+edge(95,71).
+edge(71,98).
+edge(98,71).
+edge(71,105).
+edge(105,71).
+edge(71,115).
+edge(115,71).
+edge(71,128).
+edge(128,71).
+edge(71,133).
+edge(133,71).
+edge(71,137).
+edge(137,71).
+edge(72,85).
+edge(85,72).
+edge(72,117).
+edge(117,72).
+edge(72,120).
+edge(120,72).
+edge(72,123).
+edge(123,72).
+edge(72,126).
+edge(126,72).
+edge(72,130).
+edge(130,72).
+edge(72,131).
+edge(131,72).
+edge(72,134).
+edge(134,72).
+edge(72,139).
+edge(139,72).
+edge(73,74).
+edge(74,73).
+edge(73,82).
+edge(82,73).
+edge(73,88).
+edge(88,73).
+edge(73,92).
+edge(92,73).
+edge(73,103).
+edge(103,73).
+edge(73,108).
+edge(108,73).
+edge(73,129).
+edge(129,73).
+edge(74,104).
+edge(104,74).
+edge(74,107).
+edge(107,74).
+edge(74,111).
+edge(111,74).
+edge(74,113).
+edge(113,74).
+edge(74,115).
+edge(115,74).
+edge(74,140).
+edge(140,74).
+edge(75,79).
+edge(79,75).
+edge(75,95).
+edge(95,75).
+edge(75,111).
+edge(111,75).
+edge(75,114).
+edge(114,75).
+edge(75,119).
+edge(119,75).
+edge(75,120).
+edge(120,75).
+edge(75,122).
+edge(122,75).
+edge(75,125).
+edge(125,75).
+edge(75,128).
+edge(128,75).
+edge(75,136).
+edge(136,75).
+edge(76,81).
+edge(81,76).
+edge(76,88).
+edge(88,76).
+edge(76,98).
+edge(98,76).
+edge(76,106).
+edge(106,76).
+edge(76,111).
+edge(111,76).
+edge(76,122).
+edge(122,76).
+edge(76,128).
+edge(128,76).
+edge(76,133).
+edge(133,76).
+edge(76,134).
+edge(134,76).
+edge(77,93).
+edge(93,77).
+edge(77,98).
+edge(98,77).
+edge(77,106).
+edge(106,77).
+edge(77,108).
+edge(108,77).
+edge(77,109).
+edge(109,77).
+edge(77,115).
+edge(115,77).
+edge(77,118).
+edge(118,77).
+edge(77,137).
+edge(137,77).
+edge(78,89).
+edge(89,78).
+edge(78,99).
+edge(99,78).
+edge(78,101).
+edge(101,78).
+edge(78,107).
+edge(107,78).
+edge(79,95).
+edge(95,79).
+edge(79,97).
+edge(97,79).
+edge(79,102).
+edge(102,79).
+edge(79,114).
+edge(114,79).
+edge(79,127).
+edge(127,79).
+edge(79,134).
+edge(134,79).
+edge(79,135).
+edge(135,79).
+edge(80,93).
+edge(93,80).
+edge(80,97).
+edge(97,80).
+edge(80,99).
+edge(99,80).
+edge(80,100).
+edge(100,80).
+edge(80,112).
+edge(112,80).
+edge(80,117).
+edge(117,80).
+edge(80,119).
+edge(119,80).
+edge(80,122).
+edge(122,80).
+edge(80,125).
+edge(125,80).
+edge(80,126).
+edge(126,80).
+edge(80,137).
+edge(137,80).
+edge(81,91).
+edge(91,81).
+edge(81,97).
+edge(97,81).
+edge(81,101).
+edge(101,81).
+edge(81,108).
+edge(108,81).
+edge(81,120).
+edge(120,81).
+edge(81,124).
+edge(124,81).
+edge(81,125).
+edge(125,81).
+edge(81,139).
+edge(139,81).
+edge(82,93).
+edge(93,82).
+edge(82,104).
+edge(104,82).
+edge(82,108).
+edge(108,82).
+edge(82,112).
+edge(112,82).
+edge(82,125).
+edge(125,82).
+edge(82,132).
+edge(132,82).
+edge(82,135).
+edge(135,82).
+edge(83,84).
+edge(84,83).
+edge(83,90).
+edge(90,83).
+edge(83,94).
+edge(94,83).
+edge(83,97).
+edge(97,83).
+edge(83,122).
+edge(122,83).
+edge(83,125).
+edge(125,83).
+edge(84,101).
+edge(101,84).
+edge(84,108).
+edge(108,84).
+edge(84,115).
+edge(115,84).
+edge(84,116).
+edge(116,84).
+edge(84,131).
+edge(131,84).
+edge(84,134).
+edge(134,84).
+edge(84,136).
+edge(136,84).
+edge(84,137).
+edge(137,84).
+edge(84,140).
+edge(140,84).
+edge(85,93).
+edge(93,85).
+edge(85,97).
+edge(97,85).
+edge(85,99).
+edge(99,85).
+edge(85,113).
+edge(113,85).
+edge(86,90).
+edge(90,86).
+edge(86,91).
+edge(91,86).
+edge(86,108).
+edge(108,86).
+edge(86,116).
+edge(116,86).
+edge(86,118).
+edge(118,86).
+edge(86,119).
+edge(119,86).
+edge(86,127).
+edge(127,86).
+edge(87,100).
+edge(100,87).
+edge(87,102).
+edge(102,87).
+edge(87,130).
+edge(130,87).
+edge(88,93).
+edge(93,88).
+edge(88,105).
+edge(105,88).
+edge(88,114).
+edge(114,88).
+edge(88,125).
+edge(125,88).
+edge(88,137).
+edge(137,88).
+edge(89,108).
+edge(108,89).
+edge(89,117).
+edge(117,89).
+edge(89,128).
+edge(128,89).
+edge(89,138).
+edge(138,89).
+edge(90,96).
+edge(96,90).
+edge(90,109).
+edge(109,90).
+edge(90,112).
+edge(112,90).
+edge(90,137).
+edge(137,90).
+edge(91,111).
+edge(111,91).
+edge(91,130).
+edge(130,91).
+edge(91,135).
+edge(135,91).
+edge(91,137).
+edge(137,91).
+edge(92,101).
+edge(101,92).
+edge(92,111).
+edge(111,92).
+edge(92,125).
+edge(125,92).
+edge(93,103).
+edge(103,93).
+edge(93,106).
+edge(106,93).
+edge(93,107).
+edge(107,93).
+edge(93,127).
+edge(127,93).
+edge(93,134).
+edge(134,93).
+edge(94,118).
+edge(118,94).
+edge(94,127).
+edge(127,94).
+edge(94,138).
+edge(138,94).
+edge(94,140).
+edge(140,94).
+edge(95,103).
+edge(103,95).
+edge(95,112).
+edge(112,95).
+edge(95,131).
+edge(131,95).
+edge(95,138).
+edge(138,95).
+edge(96,97).
+edge(97,96).
+edge(96,103).
+edge(103,96).
+edge(96,104).
+edge(104,96).
+edge(96,111).
+edge(111,96).
+edge(96,126).
+edge(126,96).
+edge(97,99).
+edge(99,97).
+edge(97,100).
+edge(100,97).
+edge(97,103).
+edge(103,97).
+edge(97,112).
+edge(112,97).
+edge(97,117).
+edge(117,97).
+edge(97,120).
+edge(120,97).
+edge(97,122).
+edge(122,97).
+edge(98,105).
+edge(105,98).
+edge(98,113).
+edge(113,98).
+edge(98,121).
+edge(121,98).
+edge(98,126).
+edge(126,98).
+edge(98,138).
+edge(138,98).
+edge(99,116).
+edge(116,99).
+edge(99,120).
+edge(120,99).
+edge(99,123).
+edge(123,99).
+edge(99,127).
+edge(127,99).
+edge(100,108).
+edge(108,100).
+edge(100,115).
+edge(115,100).
+edge(100,122).
+edge(122,100).
+edge(100,127).
+edge(127,100).
+edge(100,129).
+edge(129,100).
+edge(101,102).
+edge(102,101).
+edge(101,106).
+edge(106,101).
+edge(101,108).
+edge(108,101).
+edge(101,113).
+edge(113,101).
+edge(101,126).
+edge(126,101).
+edge(101,128).
+edge(128,101).
+edge(102,107).
+edge(107,102).
+edge(102,109).
+edge(109,102).
+edge(102,113).
+edge(113,102).
+edge(102,123).
+edge(123,102).
+edge(102,127).
+edge(127,102).
+edge(102,132).
+edge(132,102).
+edge(103,104).
+edge(104,103).
+edge(103,105).
+edge(105,103).
+edge(103,131).
+edge(131,103).
+edge(103,138).
+edge(138,103).
+edge(104,105).
+edge(105,104).
+edge(104,107).
+edge(107,104).
+edge(104,109).
+edge(109,104).
+edge(104,119).
+edge(119,104).
+edge(105,107).
+edge(107,105).
+edge(105,127).
+edge(127,105).
+edge(105,131).
+edge(131,105).
+edge(105,138).
+edge(138,105).
+edge(106,113).
+edge(113,106).
+edge(106,126).
+edge(126,106).
+edge(106,132).
+edge(132,106).
+edge(107,112).
+edge(112,107).
+edge(107,136).
+edge(136,107).
+edge(107,140).
+edge(140,107).
+edge(108,116).
+edge(116,108).
+edge(108,120).
+edge(120,108).
+edge(108,129).
+edge(129,108).
+edge(108,140).
+edge(140,108).
+edge(109,116).
+edge(116,109).
+edge(110,115).
+edge(115,110).
+edge(110,121).
+edge(121,110).
+edge(110,134).
+edge(134,110).
+edge(111,112).
+edge(112,111).
+edge(111,118).
+edge(118,111).
+edge(111,125).
+edge(125,111).
+edge(111,127).
+edge(127,111).
+edge(111,128).
+edge(128,111).
+edge(111,138).
+edge(138,111).
+edge(112,114).
+edge(114,112).
+edge(112,122).
+edge(122,112).
+edge(112,126).
+edge(126,112).
+edge(112,128).
+edge(128,112).
+edge(113,122).
+edge(122,113).
+edge(113,125).
+edge(125,113).
+edge(113,128).
+edge(128,113).
+edge(113,132).
+edge(132,113).
+edge(113,135).
+edge(135,113).
+edge(114,118).
+edge(118,114).
+edge(114,135).
+edge(135,114).
+edge(114,137).
+edge(137,114).
+edge(115,118).
+edge(118,115).
+edge(115,133).
+edge(133,115).
+edge(115,137).
+edge(137,115).
+edge(115,139).
+edge(139,115).
+edge(116,120).
+edge(120,116).
+edge(116,128).
+edge(128,116).
+edge(116,129).
+edge(129,116).
+edge(116,139).
+edge(139,116).
+edge(117,125).
+edge(125,117).
+edge(118,119).
+edge(119,118).
+edge(118,125).
+edge(125,118).
+edge(118,128).
+edge(128,118).
+edge(118,130).
+edge(130,118).
+edge(118,138).
+edge(138,118).
+edge(118,139).
+edge(139,118).
+edge(120,127).
+edge(127,120).
+edge(120,130).
+edge(130,120).
+edge(121,122).
+edge(122,121).
+edge(121,124).
+edge(124,121).
+edge(122,136).
+edge(136,122).
+edge(123,130).
+edge(130,123).
+edge(123,139).
+edge(139,123).
+edge(123,140).
+edge(140,123).
+edge(124,134).
+edge(134,124).
+edge(124,140).
+edge(140,124).
+edge(126,127).
+edge(127,126).
+edge(127,129).
+edge(129,127).
+edge(129,131).
+edge(131,129).
+edge(129,137).
+edge(137,129).
+edge(131,137).
+edge(137,131).
+edge(132,139).
+edge(139,132).
+edge(133,140).
+edge(140,133).
+edge(135,140).
+edge(140,135).
+edge(137,140).
+edge(140,137).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0046-graph_colouring-145-0.lp b/examples/clingo/expansion/GraphColouring/instances/0046-graph_colouring-145-0.lp
new file mode 100644
index 0000000..f1cc3c8
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0046-graph_colouring-145-0.lp
@@ -0,0 +1,2345 @@
+#const n=145.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+edge(1,17).
+edge(17,1).
+edge(1,21).
+edge(21,1).
+edge(1,35).
+edge(35,1).
+edge(1,39).
+edge(39,1).
+edge(1,42).
+edge(42,1).
+edge(1,59).
+edge(59,1).
+edge(1,67).
+edge(67,1).
+edge(1,71).
+edge(71,1).
+edge(1,77).
+edge(77,1).
+edge(1,82).
+edge(82,1).
+edge(1,106).
+edge(106,1).
+edge(1,132).
+edge(132,1).
+edge(1,144).
+edge(144,1).
+edge(2,6).
+edge(6,2).
+edge(2,23).
+edge(23,2).
+edge(2,24).
+edge(24,2).
+edge(2,28).
+edge(28,2).
+edge(2,34).
+edge(34,2).
+edge(2,45).
+edge(45,2).
+edge(2,52).
+edge(52,2).
+edge(2,62).
+edge(62,2).
+edge(2,72).
+edge(72,2).
+edge(2,85).
+edge(85,2).
+edge(2,90).
+edge(90,2).
+edge(2,98).
+edge(98,2).
+edge(2,117).
+edge(117,2).
+edge(2,123).
+edge(123,2).
+edge(2,128).
+edge(128,2).
+edge(2,130).
+edge(130,2).
+edge(2,132).
+edge(132,2).
+edge(3,5).
+edge(5,3).
+edge(3,10).
+edge(10,3).
+edge(3,32).
+edge(32,3).
+edge(3,41).
+edge(41,3).
+edge(3,44).
+edge(44,3).
+edge(3,45).
+edge(45,3).
+edge(3,53).
+edge(53,3).
+edge(3,58).
+edge(58,3).
+edge(3,66).
+edge(66,3).
+edge(3,79).
+edge(79,3).
+edge(3,81).
+edge(81,3).
+edge(3,107).
+edge(107,3).
+edge(3,113).
+edge(113,3).
+edge(3,134).
+edge(134,3).
+edge(3,138).
+edge(138,3).
+edge(3,142).
+edge(142,3).
+edge(4,13).
+edge(13,4).
+edge(4,17).
+edge(17,4).
+edge(4,18).
+edge(18,4).
+edge(4,22).
+edge(22,4).
+edge(4,56).
+edge(56,4).
+edge(4,65).
+edge(65,4).
+edge(4,71).
+edge(71,4).
+edge(4,72).
+edge(72,4).
+edge(4,78).
+edge(78,4).
+edge(4,90).
+edge(90,4).
+edge(4,92).
+edge(92,4).
+edge(4,96).
+edge(96,4).
+edge(4,98).
+edge(98,4).
+edge(4,105).
+edge(105,4).
+edge(4,118).
+edge(118,4).
+edge(5,18).
+edge(18,5).
+edge(5,32).
+edge(32,5).
+edge(5,50).
+edge(50,5).
+edge(5,59).
+edge(59,5).
+edge(5,65).
+edge(65,5).
+edge(5,81).
+edge(81,5).
+edge(5,86).
+edge(86,5).
+edge(5,94).
+edge(94,5).
+edge(5,100).
+edge(100,5).
+edge(5,110).
+edge(110,5).
+edge(5,119).
+edge(119,5).
+edge(5,129).
+edge(129,5).
+edge(5,134).
+edge(134,5).
+edge(6,22).
+edge(22,6).
+edge(6,30).
+edge(30,6).
+edge(6,35).
+edge(35,6).
+edge(6,51).
+edge(51,6).
+edge(6,54).
+edge(54,6).
+edge(6,56).
+edge(56,6).
+edge(6,60).
+edge(60,6).
+edge(6,68).
+edge(68,6).
+edge(6,75).
+edge(75,6).
+edge(6,81).
+edge(81,6).
+edge(6,123).
+edge(123,6).
+edge(6,144).
+edge(144,6).
+edge(7,15).
+edge(15,7).
+edge(7,34).
+edge(34,7).
+edge(7,92).
+edge(92,7).
+edge(7,97).
+edge(97,7).
+edge(7,129).
+edge(129,7).
+edge(7,133).
+edge(133,7).
+edge(7,134).
+edge(134,7).
+edge(7,141).
+edge(141,7).
+edge(7,144).
+edge(144,7).
+edge(8,16).
+edge(16,8).
+edge(8,30).
+edge(30,8).
+edge(8,32).
+edge(32,8).
+edge(8,35).
+edge(35,8).
+edge(8,48).
+edge(48,8).
+edge(8,57).
+edge(57,8).
+edge(8,64).
+edge(64,8).
+edge(8,86).
+edge(86,8).
+edge(8,87).
+edge(87,8).
+edge(8,108).
+edge(108,8).
+edge(8,125).
+edge(125,8).
+edge(8,137).
+edge(137,8).
+edge(8,140).
+edge(140,8).
+edge(8,142).
+edge(142,8).
+edge(9,26).
+edge(26,9).
+edge(9,30).
+edge(30,9).
+edge(9,36).
+edge(36,9).
+edge(9,41).
+edge(41,9).
+edge(9,44).
+edge(44,9).
+edge(9,45).
+edge(45,9).
+edge(9,90).
+edge(90,9).
+edge(9,99).
+edge(99,9).
+edge(9,109).
+edge(109,9).
+edge(9,114).
+edge(114,9).
+edge(9,115).
+edge(115,9).
+edge(9,120).
+edge(120,9).
+edge(9,123).
+edge(123,9).
+edge(9,126).
+edge(126,9).
+edge(9,135).
+edge(135,9).
+edge(9,136).
+edge(136,9).
+edge(9,139).
+edge(139,9).
+edge(10,11).
+edge(11,10).
+edge(10,12).
+edge(12,10).
+edge(10,13).
+edge(13,10).
+edge(10,27).
+edge(27,10).
+edge(10,31).
+edge(31,10).
+edge(10,41).
+edge(41,10).
+edge(10,64).
+edge(64,10).
+edge(10,72).
+edge(72,10).
+edge(10,73).
+edge(73,10).
+edge(10,92).
+edge(92,10).
+edge(10,103).
+edge(103,10).
+edge(10,118).
+edge(118,10).
+edge(10,122).
+edge(122,10).
+edge(10,124).
+edge(124,10).
+edge(10,126).
+edge(126,10).
+edge(10,141).
+edge(141,10).
+edge(10,142).
+edge(142,10).
+edge(11,44).
+edge(44,11).
+edge(11,49).
+edge(49,11).
+edge(11,56).
+edge(56,11).
+edge(11,77).
+edge(77,11).
+edge(11,94).
+edge(94,11).
+edge(11,107).
+edge(107,11).
+edge(11,116).
+edge(116,11).
+edge(11,118).
+edge(118,11).
+edge(11,144).
+edge(144,11).
+edge(12,72).
+edge(72,12).
+edge(12,77).
+edge(77,12).
+edge(12,92).
+edge(92,12).
+edge(12,95).
+edge(95,12).
+edge(12,98).
+edge(98,12).
+edge(12,110).
+edge(110,12).
+edge(12,127).
+edge(127,12).
+edge(12,142).
+edge(142,12).
+edge(13,24).
+edge(24,13).
+edge(13,33).
+edge(33,13).
+edge(13,35).
+edge(35,13).
+edge(13,39).
+edge(39,13).
+edge(13,42).
+edge(42,13).
+edge(13,50).
+edge(50,13).
+edge(13,53).
+edge(53,13).
+edge(13,61).
+edge(61,13).
+edge(13,100).
+edge(100,13).
+edge(13,114).
+edge(114,13).
+edge(13,125).
+edge(125,13).
+edge(13,140).
+edge(140,13).
+edge(14,22).
+edge(22,14).
+edge(14,24).
+edge(24,14).
+edge(14,28).
+edge(28,14).
+edge(14,32).
+edge(32,14).
+edge(14,52).
+edge(52,14).
+edge(14,58).
+edge(58,14).
+edge(14,65).
+edge(65,14).
+edge(14,68).
+edge(68,14).
+edge(14,74).
+edge(74,14).
+edge(14,78).
+edge(78,14).
+edge(14,86).
+edge(86,14).
+edge(14,101).
+edge(101,14).
+edge(14,117).
+edge(117,14).
+edge(14,120).
+edge(120,14).
+edge(14,138).
+edge(138,14).
+edge(14,142).
+edge(142,14).
+edge(15,16).
+edge(16,15).
+edge(15,39).
+edge(39,15).
+edge(15,67).
+edge(67,15).
+edge(15,78).
+edge(78,15).
+edge(15,84).
+edge(84,15).
+edge(15,88).
+edge(88,15).
+edge(15,90).
+edge(90,15).
+edge(15,93).
+edge(93,15).
+edge(15,115).
+edge(115,15).
+edge(15,126).
+edge(126,15).
+edge(15,133).
+edge(133,15).
+edge(15,135).
+edge(135,15).
+edge(15,144).
+edge(144,15).
+edge(16,22).
+edge(22,16).
+edge(16,33).
+edge(33,16).
+edge(16,42).
+edge(42,16).
+edge(16,46).
+edge(46,16).
+edge(16,47).
+edge(47,16).
+edge(16,56).
+edge(56,16).
+edge(16,60).
+edge(60,16).
+edge(16,64).
+edge(64,16).
+edge(16,69).
+edge(69,16).
+edge(17,51).
+edge(51,17).
+edge(17,53).
+edge(53,17).
+edge(17,55).
+edge(55,17).
+edge(17,87).
+edge(87,17).
+edge(17,108).
+edge(108,17).
+edge(17,112).
+edge(112,17).
+edge(17,116).
+edge(116,17).
+edge(17,132).
+edge(132,17).
+edge(17,143).
+edge(143,17).
+edge(18,19).
+edge(19,18).
+edge(18,31).
+edge(31,18).
+edge(18,34).
+edge(34,18).
+edge(18,36).
+edge(36,18).
+edge(18,41).
+edge(41,18).
+edge(18,67).
+edge(67,18).
+edge(18,77).
+edge(77,18).
+edge(18,110).
+edge(110,18).
+edge(18,127).
+edge(127,18).
+edge(18,130).
+edge(130,18).
+edge(18,135).
+edge(135,18).
+edge(19,23).
+edge(23,19).
+edge(19,26).
+edge(26,19).
+edge(19,38).
+edge(38,19).
+edge(19,49).
+edge(49,19).
+edge(19,62).
+edge(62,19).
+edge(19,69).
+edge(69,19).
+edge(19,74).
+edge(74,19).
+edge(19,109).
+edge(109,19).
+edge(19,112).
+edge(112,19).
+edge(19,122).
+edge(122,19).
+edge(19,124).
+edge(124,19).
+edge(19,126).
+edge(126,19).
+edge(19,144).
+edge(144,19).
+edge(20,33).
+edge(33,20).
+edge(20,34).
+edge(34,20).
+edge(20,50).
+edge(50,20).
+edge(20,54).
+edge(54,20).
+edge(20,63).
+edge(63,20).
+edge(20,76).
+edge(76,20).
+edge(20,97).
+edge(97,20).
+edge(20,113).
+edge(113,20).
+edge(20,115).
+edge(115,20).
+edge(20,117).
+edge(117,20).
+edge(20,129).
+edge(129,20).
+edge(21,22).
+edge(22,21).
+edge(21,23).
+edge(23,21).
+edge(21,26).
+edge(26,21).
+edge(21,28).
+edge(28,21).
+edge(21,34).
+edge(34,21).
+edge(21,56).
+edge(56,21).
+edge(21,110).
+edge(110,21).
+edge(21,123).
+edge(123,21).
+edge(21,140).
+edge(140,21).
+edge(22,44).
+edge(44,22).
+edge(22,49).
+edge(49,22).
+edge(22,68).
+edge(68,22).
+edge(22,89).
+edge(89,22).
+edge(22,91).
+edge(91,22).
+edge(22,98).
+edge(98,22).
+edge(22,106).
+edge(106,22).
+edge(22,112).
+edge(112,22).
+edge(22,120).
+edge(120,22).
+edge(22,123).
+edge(123,22).
+edge(22,128).
+edge(128,22).
+edge(23,30).
+edge(30,23).
+edge(23,39).
+edge(39,23).
+edge(23,42).
+edge(42,23).
+edge(23,54).
+edge(54,23).
+edge(23,83).
+edge(83,23).
+edge(23,88).
+edge(88,23).
+edge(23,95).
+edge(95,23).
+edge(23,106).
+edge(106,23).
+edge(23,109).
+edge(109,23).
+edge(23,123).
+edge(123,23).
+edge(23,139).
+edge(139,23).
+edge(23,141).
+edge(141,23).
+edge(24,25).
+edge(25,24).
+edge(24,32).
+edge(32,24).
+edge(24,40).
+edge(40,24).
+edge(24,57).
+edge(57,24).
+edge(24,61).
+edge(61,24).
+edge(24,62).
+edge(62,24).
+edge(24,82).
+edge(82,24).
+edge(24,89).
+edge(89,24).
+edge(24,106).
+edge(106,24).
+edge(24,117).
+edge(117,24).
+edge(24,126).
+edge(126,24).
+edge(24,135).
+edge(135,24).
+edge(25,42).
+edge(42,25).
+edge(25,47).
+edge(47,25).
+edge(25,48).
+edge(48,25).
+edge(25,60).
+edge(60,25).
+edge(25,67).
+edge(67,25).
+edge(25,88).
+edge(88,25).
+edge(25,100).
+edge(100,25).
+edge(25,123).
+edge(123,25).
+edge(25,135).
+edge(135,25).
+edge(26,29).
+edge(29,26).
+edge(26,68).
+edge(68,26).
+edge(26,72).
+edge(72,26).
+edge(26,75).
+edge(75,26).
+edge(26,78).
+edge(78,26).
+edge(26,81).
+edge(81,26).
+edge(26,82).
+edge(82,26).
+edge(26,92).
+edge(92,26).
+edge(26,102).
+edge(102,26).
+edge(26,109).
+edge(109,26).
+edge(26,142).
+edge(142,26).
+edge(27,32).
+edge(32,27).
+edge(27,41).
+edge(41,27).
+edge(27,43).
+edge(43,27).
+edge(27,48).
+edge(48,27).
+edge(27,50).
+edge(50,27).
+edge(27,73).
+edge(73,27).
+edge(27,97).
+edge(97,27).
+edge(27,109).
+edge(109,27).
+edge(27,117).
+edge(117,27).
+edge(27,121).
+edge(121,27).
+edge(27,136).
+edge(136,27).
+edge(28,39).
+edge(39,28).
+edge(28,58).
+edge(58,28).
+edge(28,62).
+edge(62,28).
+edge(28,64).
+edge(64,28).
+edge(28,69).
+edge(69,28).
+edge(28,89).
+edge(89,28).
+edge(28,92).
+edge(92,28).
+edge(28,105).
+edge(105,28).
+edge(28,115).
+edge(115,28).
+edge(28,117).
+edge(117,28).
+edge(28,120).
+edge(120,28).
+edge(28,124).
+edge(124,28).
+edge(29,42).
+edge(42,29).
+edge(29,48).
+edge(48,29).
+edge(29,54).
+edge(54,29).
+edge(29,70).
+edge(70,29).
+edge(29,76).
+edge(76,29).
+edge(29,81).
+edge(81,29).
+edge(29,118).
+edge(118,29).
+edge(29,128).
+edge(128,29).
+edge(29,138).
+edge(138,29).
+edge(29,145).
+edge(145,29).
+edge(30,37).
+edge(37,30).
+edge(30,53).
+edge(53,30).
+edge(30,60).
+edge(60,30).
+edge(30,63).
+edge(63,30).
+edge(30,71).
+edge(71,30).
+edge(30,74).
+edge(74,30).
+edge(30,90).
+edge(90,30).
+edge(30,112).
+edge(112,30).
+edge(30,113).
+edge(113,30).
+edge(30,127).
+edge(127,30).
+edge(30,135).
+edge(135,30).
+edge(31,47).
+edge(47,31).
+edge(31,69).
+edge(69,31).
+edge(31,81).
+edge(81,31).
+edge(31,92).
+edge(92,31).
+edge(31,94).
+edge(94,31).
+edge(31,102).
+edge(102,31).
+edge(31,105).
+edge(105,31).
+edge(31,107).
+edge(107,31).
+edge(31,144).
+edge(144,31).
+edge(32,34).
+edge(34,32).
+edge(32,43).
+edge(43,32).
+edge(32,46).
+edge(46,32).
+edge(32,49).
+edge(49,32).
+edge(32,63).
+edge(63,32).
+edge(32,85).
+edge(85,32).
+edge(32,87).
+edge(87,32).
+edge(32,91).
+edge(91,32).
+edge(32,95).
+edge(95,32).
+edge(32,99).
+edge(99,32).
+edge(32,110).
+edge(110,32).
+edge(32,114).
+edge(114,32).
+edge(32,139).
+edge(139,32).
+edge(32,145).
+edge(145,32).
+edge(33,36).
+edge(36,33).
+edge(33,47).
+edge(47,33).
+edge(33,51).
+edge(51,33).
+edge(33,57).
+edge(57,33).
+edge(33,59).
+edge(59,33).
+edge(33,85).
+edge(85,33).
+edge(33,96).
+edge(96,33).
+edge(33,119).
+edge(119,33).
+edge(33,121).
+edge(121,33).
+edge(33,140).
+edge(140,33).
+edge(34,37).
+edge(37,34).
+edge(34,51).
+edge(51,34).
+edge(34,52).
+edge(52,34).
+edge(34,63).
+edge(63,34).
+edge(34,65).
+edge(65,34).
+edge(34,68).
+edge(68,34).
+edge(34,69).
+edge(69,34).
+edge(34,76).
+edge(76,34).
+edge(34,78).
+edge(78,34).
+edge(34,79).
+edge(79,34).
+edge(34,85).
+edge(85,34).
+edge(34,101).
+edge(101,34).
+edge(34,111).
+edge(111,34).
+edge(34,130).
+edge(130,34).
+edge(34,132).
+edge(132,34).
+edge(34,133).
+edge(133,34).
+edge(34,140).
+edge(140,34).
+edge(35,48).
+edge(48,35).
+edge(35,64).
+edge(64,35).
+edge(35,71).
+edge(71,35).
+edge(35,74).
+edge(74,35).
+edge(35,75).
+edge(75,35).
+edge(35,102).
+edge(102,35).
+edge(35,117).
+edge(117,35).
+edge(35,143).
+edge(143,35).
+edge(36,48).
+edge(48,36).
+edge(36,50).
+edge(50,36).
+edge(36,61).
+edge(61,36).
+edge(36,75).
+edge(75,36).
+edge(36,78).
+edge(78,36).
+edge(36,89).
+edge(89,36).
+edge(36,95).
+edge(95,36).
+edge(36,110).
+edge(110,36).
+edge(36,113).
+edge(113,36).
+edge(36,118).
+edge(118,36).
+edge(36,133).
+edge(133,36).
+edge(36,138).
+edge(138,36).
+edge(37,45).
+edge(45,37).
+edge(37,48).
+edge(48,37).
+edge(37,55).
+edge(55,37).
+edge(37,59).
+edge(59,37).
+edge(37,61).
+edge(61,37).
+edge(37,76).
+edge(76,37).
+edge(37,77).
+edge(77,37).
+edge(37,85).
+edge(85,37).
+edge(37,96).
+edge(96,37).
+edge(38,51).
+edge(51,38).
+edge(38,54).
+edge(54,38).
+edge(38,58).
+edge(58,38).
+edge(38,67).
+edge(67,38).
+edge(38,71).
+edge(71,38).
+edge(38,82).
+edge(82,38).
+edge(38,87).
+edge(87,38).
+edge(38,91).
+edge(91,38).
+edge(38,99).
+edge(99,38).
+edge(38,100).
+edge(100,38).
+edge(38,108).
+edge(108,38).
+edge(38,110).
+edge(110,38).
+edge(38,112).
+edge(112,38).
+edge(38,120).
+edge(120,38).
+edge(38,129).
+edge(129,38).
+edge(38,133).
+edge(133,38).
+edge(38,134).
+edge(134,38).
+edge(38,143).
+edge(143,38).
+edge(39,59).
+edge(59,39).
+edge(39,77).
+edge(77,39).
+edge(39,89).
+edge(89,39).
+edge(39,92).
+edge(92,39).
+edge(39,100).
+edge(100,39).
+edge(39,102).
+edge(102,39).
+edge(39,103).
+edge(103,39).
+edge(39,104).
+edge(104,39).
+edge(39,108).
+edge(108,39).
+edge(39,113).
+edge(113,39).
+edge(39,123).
+edge(123,39).
+edge(39,136).
+edge(136,39).
+edge(39,145).
+edge(145,39).
+edge(40,48).
+edge(48,40).
+edge(40,53).
+edge(53,40).
+edge(40,65).
+edge(65,40).
+edge(40,73).
+edge(73,40).
+edge(40,79).
+edge(79,40).
+edge(40,80).
+edge(80,40).
+edge(40,85).
+edge(85,40).
+edge(40,90).
+edge(90,40).
+edge(40,96).
+edge(96,40).
+edge(40,113).
+edge(113,40).
+edge(40,116).
+edge(116,40).
+edge(40,129).
+edge(129,40).
+edge(41,45).
+edge(45,41).
+edge(41,50).
+edge(50,41).
+edge(41,109).
+edge(109,41).
+edge(41,111).
+edge(111,41).
+edge(41,120).
+edge(120,41).
+edge(41,126).
+edge(126,41).
+edge(41,134).
+edge(134,41).
+edge(41,143).
+edge(143,41).
+edge(42,47).
+edge(47,42).
+edge(42,50).
+edge(50,42).
+edge(42,54).
+edge(54,42).
+edge(42,68).
+edge(68,42).
+edge(42,70).
+edge(70,42).
+edge(42,73).
+edge(73,42).
+edge(42,93).
+edge(93,42).
+edge(42,106).
+edge(106,42).
+edge(42,112).
+edge(112,42).
+edge(42,120).
+edge(120,42).
+edge(42,127).
+edge(127,42).
+edge(42,141).
+edge(141,42).
+edge(43,45).
+edge(45,43).
+edge(43,50).
+edge(50,43).
+edge(43,51).
+edge(51,43).
+edge(43,52).
+edge(52,43).
+edge(43,61).
+edge(61,43).
+edge(43,71).
+edge(71,43).
+edge(43,113).
+edge(113,43).
+edge(43,114).
+edge(114,43).
+edge(43,120).
+edge(120,43).
+edge(43,124).
+edge(124,43).
+edge(44,46).
+edge(46,44).
+edge(44,50).
+edge(50,44).
+edge(44,69).
+edge(69,44).
+edge(44,76).
+edge(76,44).
+edge(44,81).
+edge(81,44).
+edge(44,95).
+edge(95,44).
+edge(44,99).
+edge(99,44).
+edge(44,101).
+edge(101,44).
+edge(44,106).
+edge(106,44).
+edge(44,113).
+edge(113,44).
+edge(44,125).
+edge(125,44).
+edge(44,142).
+edge(142,44).
+edge(45,47).
+edge(47,45).
+edge(45,50).
+edge(50,45).
+edge(45,56).
+edge(56,45).
+edge(45,57).
+edge(57,45).
+edge(45,66).
+edge(66,45).
+edge(45,67).
+edge(67,45).
+edge(45,82).
+edge(82,45).
+edge(45,92).
+edge(92,45).
+edge(45,94).
+edge(94,45).
+edge(45,96).
+edge(96,45).
+edge(45,99).
+edge(99,45).
+edge(45,100).
+edge(100,45).
+edge(45,108).
+edge(108,45).
+edge(45,137).
+edge(137,45).
+edge(46,56).
+edge(56,46).
+edge(46,64).
+edge(64,46).
+edge(46,65).
+edge(65,46).
+edge(46,69).
+edge(69,46).
+edge(46,81).
+edge(81,46).
+edge(46,97).
+edge(97,46).
+edge(46,103).
+edge(103,46).
+edge(46,117).
+edge(117,46).
+edge(46,137).
+edge(137,46).
+edge(46,140).
+edge(140,46).
+edge(47,74).
+edge(74,47).
+edge(47,79).
+edge(79,47).
+edge(47,97).
+edge(97,47).
+edge(47,104).
+edge(104,47).
+edge(47,117).
+edge(117,47).
+edge(47,125).
+edge(125,47).
+edge(47,139).
+edge(139,47).
+edge(48,58).
+edge(58,48).
+edge(48,87).
+edge(87,48).
+edge(48,95).
+edge(95,48).
+edge(48,111).
+edge(111,48).
+edge(48,139).
+edge(139,48).
+edge(48,143).
+edge(143,48).
+edge(49,54).
+edge(54,49).
+edge(49,65).
+edge(65,49).
+edge(49,81).
+edge(81,49).
+edge(49,86).
+edge(86,49).
+edge(49,95).
+edge(95,49).
+edge(49,99).
+edge(99,49).
+edge(49,105).
+edge(105,49).
+edge(49,110).
+edge(110,49).
+edge(49,122).
+edge(122,49).
+edge(49,126).
+edge(126,49).
+edge(49,130).
+edge(130,49).
+edge(49,137).
+edge(137,49).
+edge(49,142).
+edge(142,49).
+edge(50,59).
+edge(59,50).
+edge(50,61).
+edge(61,50).
+edge(50,79).
+edge(79,50).
+edge(50,94).
+edge(94,50).
+edge(50,102).
+edge(102,50).
+edge(50,109).
+edge(109,50).
+edge(50,113).
+edge(113,50).
+edge(50,114).
+edge(114,50).
+edge(50,123).
+edge(123,50).
+edge(50,135).
+edge(135,50).
+edge(50,142).
+edge(142,50).
+edge(50,145).
+edge(145,50).
+edge(51,74).
+edge(74,51).
+edge(51,100).
+edge(100,51).
+edge(51,110).
+edge(110,51).
+edge(51,128).
+edge(128,51).
+edge(52,64).
+edge(64,52).
+edge(52,95).
+edge(95,52).
+edge(52,98).
+edge(98,52).
+edge(52,126).
+edge(126,52).
+edge(52,136).
+edge(136,52).
+edge(52,143).
+edge(143,52).
+edge(53,61).
+edge(61,53).
+edge(53,62).
+edge(62,53).
+edge(53,65).
+edge(65,53).
+edge(53,93).
+edge(93,53).
+edge(53,97).
+edge(97,53).
+edge(53,100).
+edge(100,53).
+edge(53,110).
+edge(110,53).
+edge(53,111).
+edge(111,53).
+edge(53,123).
+edge(123,53).
+edge(53,129).
+edge(129,53).
+edge(53,134).
+edge(134,53).
+edge(53,136).
+edge(136,53).
+edge(54,58).
+edge(58,54).
+edge(54,69).
+edge(69,54).
+edge(54,75).
+edge(75,54).
+edge(54,84).
+edge(84,54).
+edge(54,91).
+edge(91,54).
+edge(54,93).
+edge(93,54).
+edge(54,104).
+edge(104,54).
+edge(54,112).
+edge(112,54).
+edge(54,133).
+edge(133,54).
+edge(54,144).
+edge(144,54).
+edge(55,57).
+edge(57,55).
+edge(55,75).
+edge(75,55).
+edge(55,76).
+edge(76,55).
+edge(55,83).
+edge(83,55).
+edge(55,91).
+edge(91,55).
+edge(55,97).
+edge(97,55).
+edge(55,103).
+edge(103,55).
+edge(55,140).
+edge(140,55).
+edge(56,80).
+edge(80,56).
+edge(56,83).
+edge(83,56).
+edge(56,84).
+edge(84,56).
+edge(56,87).
+edge(87,56).
+edge(56,99).
+edge(99,56).
+edge(56,104).
+edge(104,56).
+edge(56,112).
+edge(112,56).
+edge(56,119).
+edge(119,56).
+edge(56,121).
+edge(121,56).
+edge(56,132).
+edge(132,56).
+edge(56,135).
+edge(135,56).
+edge(57,71).
+edge(71,57).
+edge(57,76).
+edge(76,57).
+edge(57,90).
+edge(90,57).
+edge(57,109).
+edge(109,57).
+edge(57,116).
+edge(116,57).
+edge(57,129).
+edge(129,57).
+edge(57,136).
+edge(136,57).
+edge(58,60).
+edge(60,58).
+edge(58,69).
+edge(69,58).
+edge(58,91).
+edge(91,58).
+edge(58,103).
+edge(103,58).
+edge(58,110).
+edge(110,58).
+edge(58,116).
+edge(116,58).
+edge(58,138).
+edge(138,58).
+edge(58,140).
+edge(140,58).
+edge(58,141).
+edge(141,58).
+edge(58,145).
+edge(145,58).
+edge(59,61).
+edge(61,59).
+edge(59,73).
+edge(73,59).
+edge(59,80).
+edge(80,59).
+edge(59,81).
+edge(81,59).
+edge(59,85).
+edge(85,59).
+edge(59,99).
+edge(99,59).
+edge(59,100).
+edge(100,59).
+edge(59,104).
+edge(104,59).
+edge(59,107).
+edge(107,59).
+edge(59,119).
+edge(119,59).
+edge(59,124).
+edge(124,59).
+edge(59,139).
+edge(139,59).
+edge(60,100).
+edge(100,60).
+edge(60,106).
+edge(106,60).
+edge(60,123).
+edge(123,60).
+edge(60,125).
+edge(125,60).
+edge(61,66).
+edge(66,61).
+edge(61,67).
+edge(67,61).
+edge(61,83).
+edge(83,61).
+edge(61,84).
+edge(84,61).
+edge(61,85).
+edge(85,61).
+edge(61,88).
+edge(88,61).
+edge(61,94).
+edge(94,61).
+edge(61,95).
+edge(95,61).
+edge(61,104).
+edge(104,61).
+edge(61,131).
+edge(131,61).
+edge(61,132).
+edge(132,61).
+edge(61,134).
+edge(134,61).
+edge(62,78).
+edge(78,62).
+edge(62,112).
+edge(112,62).
+edge(62,126).
+edge(126,62).
+edge(62,137).
+edge(137,62).
+edge(63,96).
+edge(96,63).
+edge(63,100).
+edge(100,63).
+edge(63,109).
+edge(109,63).
+edge(63,140).
+edge(140,63).
+edge(64,66).
+edge(66,64).
+edge(64,70).
+edge(70,64).
+edge(64,86).
+edge(86,64).
+edge(64,108).
+edge(108,64).
+edge(64,112).
+edge(112,64).
+edge(64,139).
+edge(139,64).
+edge(65,66).
+edge(66,65).
+edge(65,68).
+edge(68,65).
+edge(65,71).
+edge(71,65).
+edge(65,107).
+edge(107,65).
+edge(65,109).
+edge(109,65).
+edge(65,117).
+edge(117,65).
+edge(65,118).
+edge(118,65).
+edge(65,134).
+edge(134,65).
+edge(65,136).
+edge(136,65).
+edge(65,140).
+edge(140,65).
+edge(66,104).
+edge(104,66).
+edge(66,109).
+edge(109,66).
+edge(66,113).
+edge(113,66).
+edge(66,119).
+edge(119,66).
+edge(66,120).
+edge(120,66).
+edge(66,123).
+edge(123,66).
+edge(66,125).
+edge(125,66).
+edge(67,70).
+edge(70,67).
+edge(67,72).
+edge(72,67).
+edge(67,79).
+edge(79,67).
+edge(67,81).
+edge(81,67).
+edge(67,111).
+edge(111,67).
+edge(67,116).
+edge(116,67).
+edge(67,125).
+edge(125,67).
+edge(67,132).
+edge(132,67).
+edge(67,140).
+edge(140,67).
+edge(68,70).
+edge(70,68).
+edge(68,71).
+edge(71,68).
+edge(68,87).
+edge(87,68).
+edge(68,99).
+edge(99,68).
+edge(68,100).
+edge(100,68).
+edge(68,116).
+edge(116,68).
+edge(68,117).
+edge(117,68).
+edge(68,121).
+edge(121,68).
+edge(68,122).
+edge(122,68).
+edge(68,123).
+edge(123,68).
+edge(68,138).
+edge(138,68).
+edge(69,75).
+edge(75,69).
+edge(69,79).
+edge(79,69).
+edge(69,80).
+edge(80,69).
+edge(69,95).
+edge(95,69).
+edge(69,107).
+edge(107,69).
+edge(69,108).
+edge(108,69).
+edge(69,116).
+edge(116,69).
+edge(69,126).
+edge(126,69).
+edge(69,128).
+edge(128,69).
+edge(69,135).
+edge(135,69).
+edge(69,136).
+edge(136,69).
+edge(69,144).
+edge(144,69).
+edge(70,80).
+edge(80,70).
+edge(70,89).
+edge(89,70).
+edge(70,123).
+edge(123,70).
+edge(70,129).
+edge(129,70).
+edge(70,139).
+edge(139,70).
+edge(70,145).
+edge(145,70).
+edge(71,73).
+edge(73,71).
+edge(71,83).
+edge(83,71).
+edge(71,84).
+edge(84,71).
+edge(71,85).
+edge(85,71).
+edge(71,91).
+edge(91,71).
+edge(71,107).
+edge(107,71).
+edge(71,110).
+edge(110,71).
+edge(71,116).
+edge(116,71).
+edge(71,117).
+edge(117,71).
+edge(72,76).
+edge(76,72).
+edge(72,83).
+edge(83,72).
+edge(72,85).
+edge(85,72).
+edge(72,96).
+edge(96,72).
+edge(72,105).
+edge(105,72).
+edge(72,106).
+edge(106,72).
+edge(72,112).
+edge(112,72).
+edge(72,122).
+edge(122,72).
+edge(72,124).
+edge(124,72).
+edge(72,133).
+edge(133,72).
+edge(73,76).
+edge(76,73).
+edge(73,87).
+edge(87,73).
+edge(73,120).
+edge(120,73).
+edge(73,134).
+edge(134,73).
+edge(73,142).
+edge(142,73).
+edge(74,95).
+edge(95,74).
+edge(74,102).
+edge(102,74).
+edge(74,107).
+edge(107,74).
+edge(74,112).
+edge(112,74).
+edge(74,113).
+edge(113,74).
+edge(74,140).
+edge(140,74).
+edge(75,82).
+edge(82,75).
+edge(75,89).
+edge(89,75).
+edge(75,95).
+edge(95,75).
+edge(75,98).
+edge(98,75).
+edge(75,129).
+edge(129,75).
+edge(75,133).
+edge(133,75).
+edge(75,137).
+edge(137,75).
+edge(76,82).
+edge(82,76).
+edge(76,83).
+edge(83,76).
+edge(76,101).
+edge(101,76).
+edge(76,119).
+edge(119,76).
+edge(76,123).
+edge(123,76).
+edge(76,126).
+edge(126,76).
+edge(76,128).
+edge(128,76).
+edge(76,134).
+edge(134,76).
+edge(76,139).
+edge(139,76).
+edge(76,144).
+edge(144,76).
+edge(77,88).
+edge(88,77).
+edge(77,92).
+edge(92,77).
+edge(77,98).
+edge(98,77).
+edge(77,99).
+edge(99,77).
+edge(77,108).
+edge(108,77).
+edge(77,116).
+edge(116,77).
+edge(77,119).
+edge(119,77).
+edge(77,123).
+edge(123,77).
+edge(77,126).
+edge(126,77).
+edge(77,131).
+edge(131,77).
+edge(77,137).
+edge(137,77).
+edge(77,144).
+edge(144,77).
+edge(78,83).
+edge(83,78).
+edge(78,96).
+edge(96,78).
+edge(78,97).
+edge(97,78).
+edge(78,100).
+edge(100,78).
+edge(78,110).
+edge(110,78).
+edge(78,120).
+edge(120,78).
+edge(78,124).
+edge(124,78).
+edge(78,126).
+edge(126,78).
+edge(78,131).
+edge(131,78).
+edge(78,133).
+edge(133,78).
+edge(78,144).
+edge(144,78).
+edge(79,88).
+edge(88,79).
+edge(79,95).
+edge(95,79).
+edge(79,96).
+edge(96,79).
+edge(79,97).
+edge(97,79).
+edge(79,101).
+edge(101,79).
+edge(79,102).
+edge(102,79).
+edge(79,109).
+edge(109,79).
+edge(79,123).
+edge(123,79).
+edge(79,126).
+edge(126,79).
+edge(80,91).
+edge(91,80).
+edge(80,116).
+edge(116,80).
+edge(80,134).
+edge(134,80).
+edge(80,135).
+edge(135,80).
+edge(80,141).
+edge(141,80).
+edge(80,142).
+edge(142,80).
+edge(81,90).
+edge(90,81).
+edge(81,92).
+edge(92,81).
+edge(81,107).
+edge(107,81).
+edge(81,115).
+edge(115,81).
+edge(81,136).
+edge(136,81).
+edge(81,142).
+edge(142,81).
+edge(81,143).
+edge(143,81).
+edge(82,84).
+edge(84,82).
+edge(82,89).
+edge(89,82).
+edge(82,94).
+edge(94,82).
+edge(82,103).
+edge(103,82).
+edge(82,104).
+edge(104,82).
+edge(82,114).
+edge(114,82).
+edge(82,125).
+edge(125,82).
+edge(82,126).
+edge(126,82).
+edge(82,134).
+edge(134,82).
+edge(82,140).
+edge(140,82).
+edge(82,141).
+edge(141,82).
+edge(83,84).
+edge(84,83).
+edge(83,91).
+edge(91,83).
+edge(83,99).
+edge(99,83).
+edge(83,105).
+edge(105,83).
+edge(83,109).
+edge(109,83).
+edge(83,117).
+edge(117,83).
+edge(83,119).
+edge(119,83).
+edge(83,126).
+edge(126,83).
+edge(83,139).
+edge(139,83).
+edge(83,145).
+edge(145,83).
+edge(84,87).
+edge(87,84).
+edge(84,92).
+edge(92,84).
+edge(84,96).
+edge(96,84).
+edge(84,125).
+edge(125,84).
+edge(84,129).
+edge(129,84).
+edge(84,136).
+edge(136,84).
+edge(85,92).
+edge(92,85).
+edge(85,114).
+edge(114,85).
+edge(85,120).
+edge(120,85).
+edge(85,126).
+edge(126,85).
+edge(85,134).
+edge(134,85).
+edge(85,137).
+edge(137,85).
+edge(85,139).
+edge(139,85).
+edge(85,142).
+edge(142,85).
+edge(85,145).
+edge(145,85).
+edge(86,97).
+edge(97,86).
+edge(86,109).
+edge(109,86).
+edge(86,111).
+edge(111,86).
+edge(86,124).
+edge(124,86).
+edge(86,129).
+edge(129,86).
+edge(86,140).
+edge(140,86).
+edge(87,90).
+edge(90,87).
+edge(87,97).
+edge(97,87).
+edge(87,102).
+edge(102,87).
+edge(87,122).
+edge(122,87).
+edge(87,143).
+edge(143,87).
+edge(88,112).
+edge(112,88).
+edge(88,115).
+edge(115,88).
+edge(88,119).
+edge(119,88).
+edge(88,121).
+edge(121,88).
+edge(88,126).
+edge(126,88).
+edge(88,129).
+edge(129,88).
+edge(88,141).
+edge(141,88).
+edge(88,142).
+edge(142,88).
+edge(89,95).
+edge(95,89).
+edge(89,101).
+edge(101,89).
+edge(89,125).
+edge(125,89).
+edge(89,137).
+edge(137,89).
+edge(89,138).
+edge(138,89).
+edge(89,139).
+edge(139,89).
+edge(90,93).
+edge(93,90).
+edge(90,109).
+edge(109,90).
+edge(90,111).
+edge(111,90).
+edge(90,122).
+edge(122,90).
+edge(90,127).
+edge(127,90).
+edge(90,139).
+edge(139,90).
+edge(90,140).
+edge(140,90).
+edge(91,109).
+edge(109,91).
+edge(91,115).
+edge(115,91).
+edge(91,118).
+edge(118,91).
+edge(91,123).
+edge(123,91).
+edge(91,129).
+edge(129,91).
+edge(92,113).
+edge(113,92).
+edge(93,97).
+edge(97,93).
+edge(93,111).
+edge(111,93).
+edge(93,129).
+edge(129,93).
+edge(93,140).
+edge(140,93).
+edge(93,141).
+edge(141,93).
+edge(94,95).
+edge(95,94).
+edge(94,98).
+edge(98,94).
+edge(94,116).
+edge(116,94).
+edge(94,119).
+edge(119,94).
+edge(94,120).
+edge(120,94).
+edge(94,122).
+edge(122,94).
+edge(94,126).
+edge(126,94).
+edge(94,128).
+edge(128,94).
+edge(94,135).
+edge(135,94).
+edge(95,98).
+edge(98,95).
+edge(95,101).
+edge(101,95).
+edge(95,106).
+edge(106,95).
+edge(95,107).
+edge(107,95).
+edge(95,110).
+edge(110,95).
+edge(95,119).
+edge(119,95).
+edge(95,123).
+edge(123,95).
+edge(95,133).
+edge(133,95).
+edge(95,135).
+edge(135,95).
+edge(95,140).
+edge(140,95).
+edge(96,105).
+edge(105,96).
+edge(96,111).
+edge(111,96).
+edge(96,128).
+edge(128,96).
+edge(96,142).
+edge(142,96).
+edge(96,145).
+edge(145,96).
+edge(97,115).
+edge(115,97).
+edge(97,138).
+edge(138,97).
+edge(97,140).
+edge(140,97).
+edge(97,143).
+edge(143,97).
+edge(97,144).
+edge(144,97).
+edge(98,102).
+edge(102,98).
+edge(98,105).
+edge(105,98).
+edge(98,109).
+edge(109,98).
+edge(98,111).
+edge(111,98).
+edge(98,112).
+edge(112,98).
+edge(98,128).
+edge(128,98).
+edge(98,134).
+edge(134,98).
+edge(98,138).
+edge(138,98).
+edge(98,143).
+edge(143,98).
+edge(100,104).
+edge(104,100).
+edge(100,105).
+edge(105,100).
+edge(100,107).
+edge(107,100).
+edge(100,117).
+edge(117,100).
+edge(100,119).
+edge(119,100).
+edge(100,129).
+edge(129,100).
+edge(100,133).
+edge(133,100).
+edge(100,139).
+edge(139,100).
+edge(100,145).
+edge(145,100).
+edge(101,131).
+edge(131,101).
+edge(101,140).
+edge(140,101).
+edge(101,142).
+edge(142,101).
+edge(101,143).
+edge(143,101).
+edge(102,106).
+edge(106,102).
+edge(102,145).
+edge(145,102).
+edge(103,127).
+edge(127,103).
+edge(103,132).
+edge(132,103).
+edge(103,136).
+edge(136,103).
+edge(103,138).
+edge(138,103).
+edge(103,140).
+edge(140,103).
+edge(103,142).
+edge(142,103).
+edge(104,108).
+edge(108,104).
+edge(104,109).
+edge(109,104).
+edge(104,112).
+edge(112,104).
+edge(104,127).
+edge(127,104).
+edge(104,130).
+edge(130,104).
+edge(104,132).
+edge(132,104).
+edge(105,113).
+edge(113,105).
+edge(105,137).
+edge(137,105).
+edge(105,138).
+edge(138,105).
+edge(106,108).
+edge(108,106).
+edge(106,110).
+edge(110,106).
+edge(106,114).
+edge(114,106).
+edge(106,117).
+edge(117,106).
+edge(106,131).
+edge(131,106).
+edge(106,134).
+edge(134,106).
+edge(107,114).
+edge(114,107).
+edge(107,120).
+edge(120,107).
+edge(107,134).
+edge(134,107).
+edge(107,142).
+edge(142,107).
+edge(108,120).
+edge(120,108).
+edge(108,126).
+edge(126,108).
+edge(108,137).
+edge(137,108).
+edge(108,141).
+edge(141,108).
+edge(109,111).
+edge(111,109).
+edge(109,113).
+edge(113,109).
+edge(109,116).
+edge(116,109).
+edge(109,119).
+edge(119,109).
+edge(109,124).
+edge(124,109).
+edge(109,126).
+edge(126,109).
+edge(109,127).
+edge(127,109).
+edge(109,133).
+edge(133,109).
+edge(109,138).
+edge(138,109).
+edge(109,140).
+edge(140,109).
+edge(109,144).
+edge(144,109).
+edge(110,122).
+edge(122,110).
+edge(110,129).
+edge(129,110).
+edge(110,131).
+edge(131,110).
+edge(110,135).
+edge(135,110).
+edge(110,144).
+edge(144,110).
+edge(110,145).
+edge(145,110).
+edge(111,119).
+edge(119,111).
+edge(111,124).
+edge(124,111).
+edge(111,131).
+edge(131,111).
+edge(111,133).
+edge(133,111).
+edge(112,124).
+edge(124,112).
+edge(112,144).
+edge(144,112).
+edge(113,115).
+edge(115,113).
+edge(113,128).
+edge(128,113).
+edge(113,129).
+edge(129,113).
+edge(113,132).
+edge(132,113).
+edge(114,121).
+edge(121,114).
+edge(114,132).
+edge(132,114).
+edge(114,136).
+edge(136,114).
+edge(115,120).
+edge(120,115).
+edge(115,122).
+edge(122,115).
+edge(115,123).
+edge(123,115).
+edge(115,125).
+edge(125,115).
+edge(115,131).
+edge(131,115).
+edge(115,139).
+edge(139,115).
+edge(115,140).
+edge(140,115).
+edge(116,118).
+edge(118,116).
+edge(116,119).
+edge(119,116).
+edge(116,139).
+edge(139,116).
+edge(116,144).
+edge(144,116).
+edge(117,122).
+edge(122,117).
+edge(117,125).
+edge(125,117).
+edge(117,127).
+edge(127,117).
+edge(117,130).
+edge(130,117).
+edge(118,125).
+edge(125,118).
+edge(118,135).
+edge(135,118).
+edge(118,137).
+edge(137,118).
+edge(119,121).
+edge(121,119).
+edge(119,128).
+edge(128,119).
+edge(119,130).
+edge(130,119).
+edge(119,131).
+edge(131,119).
+edge(119,135).
+edge(135,119).
+edge(120,123).
+edge(123,120).
+edge(120,129).
+edge(129,120).
+edge(120,139).
+edge(139,120).
+edge(120,141).
+edge(141,120).
+edge(121,125).
+edge(125,121).
+edge(121,132).
+edge(132,121).
+edge(122,135).
+edge(135,122).
+edge(122,137).
+edge(137,122).
+edge(122,140).
+edge(140,122).
+edge(123,132).
+edge(132,123).
+edge(123,133).
+edge(133,123).
+edge(124,133).
+edge(133,124).
+edge(124,140).
+edge(140,124).
+edge(124,144).
+edge(144,124).
+edge(125,130).
+edge(130,125).
+edge(125,133).
+edge(133,125).
+edge(125,134).
+edge(134,125).
+edge(125,137).
+edge(137,125).
+edge(125,141).
+edge(141,125).
+edge(127,128).
+edge(128,127).
+edge(127,133).
+edge(133,127).
+edge(127,135).
+edge(135,127).
+edge(127,136).
+edge(136,127).
+edge(128,138).
+edge(138,128).
+edge(128,140).
+edge(140,128).
+edge(128,144).
+edge(144,128).
+edge(129,133).
+edge(133,129).
+edge(130,134).
+edge(134,130).
+edge(131,134).
+edge(134,131).
+edge(131,136).
+edge(136,131).
+edge(132,136).
+edge(136,132).
+edge(132,139).
+edge(139,132).
+edge(133,135).
+edge(135,133).
+edge(134,145).
+edge(145,134).
+edge(135,140).
+edge(140,135).
+edge(135,144).
+edge(144,135).
+edge(137,144).
+edge(144,137).
+edge(139,142).
+edge(142,139).
+edge(140,141).
+edge(141,140).
+edge(140,142).
+edge(142,140).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0047-graph_colouring-145-0.lp b/examples/clingo/expansion/GraphColouring/instances/0047-graph_colouring-145-0.lp
new file mode 100644
index 0000000..94df63e
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0047-graph_colouring-145-0.lp
@@ -0,0 +1,2177 @@
+#const n=145.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+edge(1,7).
+edge(7,1).
+edge(1,17).
+edge(17,1).
+edge(1,51).
+edge(51,1).
+edge(1,66).
+edge(66,1).
+edge(1,76).
+edge(76,1).
+edge(1,81).
+edge(81,1).
+edge(1,84).
+edge(84,1).
+edge(1,117).
+edge(117,1).
+edge(1,126).
+edge(126,1).
+edge(1,131).
+edge(131,1).
+edge(1,135).
+edge(135,1).
+edge(1,137).
+edge(137,1).
+edge(1,139).
+edge(139,1).
+edge(1,140).
+edge(140,1).
+edge(2,8).
+edge(8,2).
+edge(2,29).
+edge(29,2).
+edge(2,32).
+edge(32,2).
+edge(2,46).
+edge(46,2).
+edge(2,55).
+edge(55,2).
+edge(2,70).
+edge(70,2).
+edge(2,89).
+edge(89,2).
+edge(2,122).
+edge(122,2).
+edge(2,133).
+edge(133,2).
+edge(3,7).
+edge(7,3).
+edge(3,10).
+edge(10,3).
+edge(3,19).
+edge(19,3).
+edge(3,20).
+edge(20,3).
+edge(3,30).
+edge(30,3).
+edge(3,47).
+edge(47,3).
+edge(3,55).
+edge(55,3).
+edge(3,56).
+edge(56,3).
+edge(3,65).
+edge(65,3).
+edge(3,91).
+edge(91,3).
+edge(3,109).
+edge(109,3).
+edge(3,114).
+edge(114,3).
+edge(3,129).
+edge(129,3).
+edge(3,134).
+edge(134,3).
+edge(3,143).
+edge(143,3).
+edge(4,31).
+edge(31,4).
+edge(4,47).
+edge(47,4).
+edge(4,50).
+edge(50,4).
+edge(4,57).
+edge(57,4).
+edge(4,60).
+edge(60,4).
+edge(4,68).
+edge(68,4).
+edge(4,81).
+edge(81,4).
+edge(4,95).
+edge(95,4).
+edge(4,108).
+edge(108,4).
+edge(4,116).
+edge(116,4).
+edge(4,133).
+edge(133,4).
+edge(4,136).
+edge(136,4).
+edge(4,139).
+edge(139,4).
+edge(4,144).
+edge(144,4).
+edge(5,12).
+edge(12,5).
+edge(5,16).
+edge(16,5).
+edge(5,32).
+edge(32,5).
+edge(5,33).
+edge(33,5).
+edge(5,42).
+edge(42,5).
+edge(5,43).
+edge(43,5).
+edge(5,50).
+edge(50,5).
+edge(5,68).
+edge(68,5).
+edge(5,72).
+edge(72,5).
+edge(5,99).
+edge(99,5).
+edge(5,121).
+edge(121,5).
+edge(5,129).
+edge(129,5).
+edge(5,137).
+edge(137,5).
+edge(5,141).
+edge(141,5).
+edge(6,25).
+edge(25,6).
+edge(6,28).
+edge(28,6).
+edge(6,36).
+edge(36,6).
+edge(6,40).
+edge(40,6).
+edge(6,42).
+edge(42,6).
+edge(6,60).
+edge(60,6).
+edge(6,70).
+edge(70,6).
+edge(6,77).
+edge(77,6).
+edge(6,111).
+edge(111,6).
+edge(6,125).
+edge(125,6).
+edge(7,9).
+edge(9,7).
+edge(7,11).
+edge(11,7).
+edge(7,12).
+edge(12,7).
+edge(7,22).
+edge(22,7).
+edge(7,26).
+edge(26,7).
+edge(7,34).
+edge(34,7).
+edge(7,35).
+edge(35,7).
+edge(7,40).
+edge(40,7).
+edge(7,46).
+edge(46,7).
+edge(7,60).
+edge(60,7).
+edge(7,65).
+edge(65,7).
+edge(7,68).
+edge(68,7).
+edge(7,76).
+edge(76,7).
+edge(7,80).
+edge(80,7).
+edge(7,94).
+edge(94,7).
+edge(7,109).
+edge(109,7).
+edge(7,111).
+edge(111,7).
+edge(7,131).
+edge(131,7).
+edge(7,137).
+edge(137,7).
+edge(8,52).
+edge(52,8).
+edge(8,55).
+edge(55,8).
+edge(8,63).
+edge(63,8).
+edge(8,81).
+edge(81,8).
+edge(8,87).
+edge(87,8).
+edge(8,88).
+edge(88,8).
+edge(8,98).
+edge(98,8).
+edge(8,138).
+edge(138,8).
+edge(8,139).
+edge(139,8).
+edge(8,141).
+edge(141,8).
+edge(8,143).
+edge(143,8).
+edge(9,18).
+edge(18,9).
+edge(9,24).
+edge(24,9).
+edge(9,30).
+edge(30,9).
+edge(9,34).
+edge(34,9).
+edge(9,38).
+edge(38,9).
+edge(9,66).
+edge(66,9).
+edge(9,67).
+edge(67,9).
+edge(9,73).
+edge(73,9).
+edge(9,79).
+edge(79,9).
+edge(9,81).
+edge(81,9).
+edge(9,102).
+edge(102,9).
+edge(9,107).
+edge(107,9).
+edge(9,116).
+edge(116,9).
+edge(9,120).
+edge(120,9).
+edge(9,133).
+edge(133,9).
+edge(9,144).
+edge(144,9).
+edge(9,145).
+edge(145,9).
+edge(10,13).
+edge(13,10).
+edge(10,41).
+edge(41,10).
+edge(10,50).
+edge(50,10).
+edge(10,52).
+edge(52,10).
+edge(10,61).
+edge(61,10).
+edge(10,64).
+edge(64,10).
+edge(10,69).
+edge(69,10).
+edge(10,74).
+edge(74,10).
+edge(10,80).
+edge(80,10).
+edge(10,111).
+edge(111,10).
+edge(10,115).
+edge(115,10).
+edge(10,128).
+edge(128,10).
+edge(10,142).
+edge(142,10).
+edge(11,13).
+edge(13,11).
+edge(11,14).
+edge(14,11).
+edge(11,67).
+edge(67,11).
+edge(11,94).
+edge(94,11).
+edge(11,97).
+edge(97,11).
+edge(11,109).
+edge(109,11).
+edge(11,124).
+edge(124,11).
+edge(12,19).
+edge(19,12).
+edge(12,23).
+edge(23,12).
+edge(12,24).
+edge(24,12).
+edge(12,30).
+edge(30,12).
+edge(12,51).
+edge(51,12).
+edge(12,61).
+edge(61,12).
+edge(12,66).
+edge(66,12).
+edge(12,84).
+edge(84,12).
+edge(12,87).
+edge(87,12).
+edge(12,93).
+edge(93,12).
+edge(12,115).
+edge(115,12).
+edge(12,119).
+edge(119,12).
+edge(12,130).
+edge(130,12).
+edge(12,141).
+edge(141,12).
+edge(13,19).
+edge(19,13).
+edge(13,21).
+edge(21,13).
+edge(13,27).
+edge(27,13).
+edge(13,32).
+edge(32,13).
+edge(13,42).
+edge(42,13).
+edge(13,48).
+edge(48,13).
+edge(13,70).
+edge(70,13).
+edge(13,79).
+edge(79,13).
+edge(13,87).
+edge(87,13).
+edge(13,111).
+edge(111,13).
+edge(13,134).
+edge(134,13).
+edge(14,16).
+edge(16,14).
+edge(14,25).
+edge(25,14).
+edge(14,27).
+edge(27,14).
+edge(14,33).
+edge(33,14).
+edge(14,41).
+edge(41,14).
+edge(14,42).
+edge(42,14).
+edge(14,61).
+edge(61,14).
+edge(14,75).
+edge(75,14).
+edge(14,87).
+edge(87,14).
+edge(14,91).
+edge(91,14).
+edge(14,93).
+edge(93,14).
+edge(14,94).
+edge(94,14).
+edge(14,106).
+edge(106,14).
+edge(14,119).
+edge(119,14).
+edge(14,144).
+edge(144,14).
+edge(15,38).
+edge(38,15).
+edge(15,43).
+edge(43,15).
+edge(15,76).
+edge(76,15).
+edge(15,102).
+edge(102,15).
+edge(15,104).
+edge(104,15).
+edge(15,114).
+edge(114,15).
+edge(15,119).
+edge(119,15).
+edge(15,138).
+edge(138,15).
+edge(16,18).
+edge(18,16).
+edge(16,22).
+edge(22,16).
+edge(16,39).
+edge(39,16).
+edge(16,44).
+edge(44,16).
+edge(16,56).
+edge(56,16).
+edge(16,58).
+edge(58,16).
+edge(16,63).
+edge(63,16).
+edge(16,71).
+edge(71,16).
+edge(16,88).
+edge(88,16).
+edge(16,93).
+edge(93,16).
+edge(16,106).
+edge(106,16).
+edge(17,22).
+edge(22,17).
+edge(17,27).
+edge(27,17).
+edge(17,62).
+edge(62,17).
+edge(17,67).
+edge(67,17).
+edge(17,104).
+edge(104,17).
+edge(17,106).
+edge(106,17).
+edge(17,125).
+edge(125,17).
+edge(17,144).
+edge(144,17).
+edge(18,37).
+edge(37,18).
+edge(18,44).
+edge(44,18).
+edge(18,53).
+edge(53,18).
+edge(18,71).
+edge(71,18).
+edge(18,82).
+edge(82,18).
+edge(18,92).
+edge(92,18).
+edge(18,94).
+edge(94,18).
+edge(18,110).
+edge(110,18).
+edge(18,114).
+edge(114,18).
+edge(18,119).
+edge(119,18).
+edge(18,121).
+edge(121,18).
+edge(18,125).
+edge(125,18).
+edge(18,129).
+edge(129,18).
+edge(18,137).
+edge(137,18).
+edge(19,23).
+edge(23,19).
+edge(19,48).
+edge(48,19).
+edge(19,59).
+edge(59,19).
+edge(19,78).
+edge(78,19).
+edge(19,81).
+edge(81,19).
+edge(19,86).
+edge(86,19).
+edge(19,98).
+edge(98,19).
+edge(19,118).
+edge(118,19).
+edge(19,140).
+edge(140,19).
+edge(20,22).
+edge(22,20).
+edge(20,30).
+edge(30,20).
+edge(20,31).
+edge(31,20).
+edge(20,32).
+edge(32,20).
+edge(20,37).
+edge(37,20).
+edge(20,45).
+edge(45,20).
+edge(20,50).
+edge(50,20).
+edge(20,56).
+edge(56,20).
+edge(20,64).
+edge(64,20).
+edge(20,67).
+edge(67,20).
+edge(20,69).
+edge(69,20).
+edge(20,74).
+edge(74,20).
+edge(20,75).
+edge(75,20).
+edge(20,76).
+edge(76,20).
+edge(20,108).
+edge(108,20).
+edge(20,124).
+edge(124,20).
+edge(20,130).
+edge(130,20).
+edge(20,137).
+edge(137,20).
+edge(20,143).
+edge(143,20).
+edge(20,144).
+edge(144,20).
+edge(20,145).
+edge(145,20).
+edge(21,32).
+edge(32,21).
+edge(21,45).
+edge(45,21).
+edge(21,59).
+edge(59,21).
+edge(21,60).
+edge(60,21).
+edge(21,64).
+edge(64,21).
+edge(21,65).
+edge(65,21).
+edge(21,70).
+edge(70,21).
+edge(21,73).
+edge(73,21).
+edge(21,76).
+edge(76,21).
+edge(21,80).
+edge(80,21).
+edge(21,82).
+edge(82,21).
+edge(21,91).
+edge(91,21).
+edge(21,95).
+edge(95,21).
+edge(21,97).
+edge(97,21).
+edge(21,99).
+edge(99,21).
+edge(21,109).
+edge(109,21).
+edge(21,130).
+edge(130,21).
+edge(21,138).
+edge(138,21).
+edge(22,27).
+edge(27,22).
+edge(22,34).
+edge(34,22).
+edge(22,54).
+edge(54,22).
+edge(22,56).
+edge(56,22).
+edge(22,78).
+edge(78,22).
+edge(22,87).
+edge(87,22).
+edge(22,89).
+edge(89,22).
+edge(22,105).
+edge(105,22).
+edge(22,106).
+edge(106,22).
+edge(22,122).
+edge(122,22).
+edge(22,123).
+edge(123,22).
+edge(22,134).
+edge(134,22).
+edge(22,137).
+edge(137,22).
+edge(22,142).
+edge(142,22).
+edge(22,143).
+edge(143,22).
+edge(23,31).
+edge(31,23).
+edge(23,47).
+edge(47,23).
+edge(23,52).
+edge(52,23).
+edge(23,63).
+edge(63,23).
+edge(23,64).
+edge(64,23).
+edge(23,74).
+edge(74,23).
+edge(23,84).
+edge(84,23).
+edge(23,92).
+edge(92,23).
+edge(23,96).
+edge(96,23).
+edge(23,105).
+edge(105,23).
+edge(23,117).
+edge(117,23).
+edge(23,119).
+edge(119,23).
+edge(23,124).
+edge(124,23).
+edge(23,133).
+edge(133,23).
+edge(24,27).
+edge(27,24).
+edge(24,28).
+edge(28,24).
+edge(24,34).
+edge(34,24).
+edge(24,57).
+edge(57,24).
+edge(24,65).
+edge(65,24).
+edge(24,89).
+edge(89,24).
+edge(24,93).
+edge(93,24).
+edge(24,97).
+edge(97,24).
+edge(24,104).
+edge(104,24).
+edge(24,120).
+edge(120,24).
+edge(24,122).
+edge(122,24).
+edge(24,129).
+edge(129,24).
+edge(25,28).
+edge(28,25).
+edge(25,63).
+edge(63,25).
+edge(25,67).
+edge(67,25).
+edge(25,70).
+edge(70,25).
+edge(25,83).
+edge(83,25).
+edge(25,96).
+edge(96,25).
+edge(25,104).
+edge(104,25).
+edge(25,107).
+edge(107,25).
+edge(25,115).
+edge(115,25).
+edge(25,119).
+edge(119,25).
+edge(25,133).
+edge(133,25).
+edge(25,135).
+edge(135,25).
+edge(26,33).
+edge(33,26).
+edge(26,47).
+edge(47,26).
+edge(26,49).
+edge(49,26).
+edge(26,58).
+edge(58,26).
+edge(26,76).
+edge(76,26).
+edge(26,80).
+edge(80,26).
+edge(26,85).
+edge(85,26).
+edge(26,92).
+edge(92,26).
+edge(26,97).
+edge(97,26).
+edge(26,108).
+edge(108,26).
+edge(27,30).
+edge(30,27).
+edge(27,43).
+edge(43,27).
+edge(27,49).
+edge(49,27).
+edge(27,50).
+edge(50,27).
+edge(27,53).
+edge(53,27).
+edge(27,76).
+edge(76,27).
+edge(27,97).
+edge(97,27).
+edge(27,103).
+edge(103,27).
+edge(27,111).
+edge(111,27).
+edge(27,116).
+edge(116,27).
+edge(27,119).
+edge(119,27).
+edge(27,121).
+edge(121,27).
+edge(27,135).
+edge(135,27).
+edge(27,136).
+edge(136,27).
+edge(27,145).
+edge(145,27).
+edge(28,45).
+edge(45,28).
+edge(28,82).
+edge(82,28).
+edge(28,83).
+edge(83,28).
+edge(28,94).
+edge(94,28).
+edge(28,101).
+edge(101,28).
+edge(28,106).
+edge(106,28).
+edge(28,113).
+edge(113,28).
+edge(28,115).
+edge(115,28).
+edge(28,117).
+edge(117,28).
+edge(28,121).
+edge(121,28).
+edge(28,125).
+edge(125,28).
+edge(28,131).
+edge(131,28).
+edge(28,139).
+edge(139,28).
+edge(29,46).
+edge(46,29).
+edge(29,47).
+edge(47,29).
+edge(29,63).
+edge(63,29).
+edge(29,72).
+edge(72,29).
+edge(29,75).
+edge(75,29).
+edge(29,76).
+edge(76,29).
+edge(29,78).
+edge(78,29).
+edge(29,90).
+edge(90,29).
+edge(29,94).
+edge(94,29).
+edge(29,101).
+edge(101,29).
+edge(29,110).
+edge(110,29).
+edge(29,132).
+edge(132,29).
+edge(30,53).
+edge(53,30).
+edge(30,69).
+edge(69,30).
+edge(30,73).
+edge(73,30).
+edge(30,82).
+edge(82,30).
+edge(30,92).
+edge(92,30).
+edge(30,93).
+edge(93,30).
+edge(30,97).
+edge(97,30).
+edge(30,113).
+edge(113,30).
+edge(30,128).
+edge(128,30).
+edge(30,130).
+edge(130,30).
+edge(30,132).
+edge(132,30).
+edge(30,138).
+edge(138,30).
+edge(30,139).
+edge(139,30).
+edge(31,50).
+edge(50,31).
+edge(31,64).
+edge(64,31).
+edge(31,91).
+edge(91,31).
+edge(31,95).
+edge(95,31).
+edge(31,102).
+edge(102,31).
+edge(31,103).
+edge(103,31).
+edge(31,145).
+edge(145,31).
+edge(32,33).
+edge(33,32).
+edge(32,45).
+edge(45,32).
+edge(32,47).
+edge(47,32).
+edge(32,53).
+edge(53,32).
+edge(32,59).
+edge(59,32).
+edge(32,68).
+edge(68,32).
+edge(32,91).
+edge(91,32).
+edge(32,100).
+edge(100,32).
+edge(32,104).
+edge(104,32).
+edge(32,128).
+edge(128,32).
+edge(33,37).
+edge(37,33).
+edge(33,48).
+edge(48,33).
+edge(33,58).
+edge(58,33).
+edge(33,62).
+edge(62,33).
+edge(33,73).
+edge(73,33).
+edge(33,75).
+edge(75,33).
+edge(33,82).
+edge(82,33).
+edge(33,117).
+edge(117,33).
+edge(33,118).
+edge(118,33).
+edge(33,127).
+edge(127,33).
+edge(33,138).
+edge(138,33).
+edge(33,141).
+edge(141,33).
+edge(34,52).
+edge(52,34).
+edge(34,59).
+edge(59,34).
+edge(34,64).
+edge(64,34).
+edge(34,69).
+edge(69,34).
+edge(34,80).
+edge(80,34).
+edge(34,89).
+edge(89,34).
+edge(34,97).
+edge(97,34).
+edge(34,121).
+edge(121,34).
+edge(35,42).
+edge(42,35).
+edge(35,54).
+edge(54,35).
+edge(35,62).
+edge(62,35).
+edge(35,63).
+edge(63,35).
+edge(35,68).
+edge(68,35).
+edge(35,80).
+edge(80,35).
+edge(35,89).
+edge(89,35).
+edge(35,101).
+edge(101,35).
+edge(35,104).
+edge(104,35).
+edge(35,105).
+edge(105,35).
+edge(35,116).
+edge(116,35).
+edge(35,144).
+edge(144,35).
+edge(36,41).
+edge(41,36).
+edge(36,66).
+edge(66,36).
+edge(36,68).
+edge(68,36).
+edge(36,71).
+edge(71,36).
+edge(36,107).
+edge(107,36).
+edge(36,145).
+edge(145,36).
+edge(37,52).
+edge(52,37).
+edge(37,56).
+edge(56,37).
+edge(37,62).
+edge(62,37).
+edge(37,65).
+edge(65,37).
+edge(37,73).
+edge(73,37).
+edge(37,75).
+edge(75,37).
+edge(37,76).
+edge(76,37).
+edge(37,77).
+edge(77,37).
+edge(37,103).
+edge(103,37).
+edge(37,141).
+edge(141,37).
+edge(38,49).
+edge(49,38).
+edge(38,55).
+edge(55,38).
+edge(38,57).
+edge(57,38).
+edge(38,67).
+edge(67,38).
+edge(38,79).
+edge(79,38).
+edge(38,80).
+edge(80,38).
+edge(38,84).
+edge(84,38).
+edge(38,86).
+edge(86,38).
+edge(38,98).
+edge(98,38).
+edge(38,115).
+edge(115,38).
+edge(38,119).
+edge(119,38).
+edge(38,129).
+edge(129,38).
+edge(38,133).
+edge(133,38).
+edge(38,143).
+edge(143,38).
+edge(39,40).
+edge(40,39).
+edge(39,50).
+edge(50,39).
+edge(39,51).
+edge(51,39).
+edge(39,58).
+edge(58,39).
+edge(39,65).
+edge(65,39).
+edge(39,99).
+edge(99,39).
+edge(40,57).
+edge(57,40).
+edge(40,58).
+edge(58,40).
+edge(40,68).
+edge(68,40).
+edge(40,80).
+edge(80,40).
+edge(40,90).
+edge(90,40).
+edge(40,93).
+edge(93,40).
+edge(40,125).
+edge(125,40).
+edge(40,132).
+edge(132,40).
+edge(40,145).
+edge(145,40).
+edge(41,70).
+edge(70,41).
+edge(41,72).
+edge(72,41).
+edge(41,75).
+edge(75,41).
+edge(41,79).
+edge(79,41).
+edge(41,91).
+edge(91,41).
+edge(41,95).
+edge(95,41).
+edge(41,96).
+edge(96,41).
+edge(41,102).
+edge(102,41).
+edge(41,109).
+edge(109,41).
+edge(41,110).
+edge(110,41).
+edge(41,114).
+edge(114,41).
+edge(42,44).
+edge(44,42).
+edge(42,56).
+edge(56,42).
+edge(42,61).
+edge(61,42).
+edge(42,63).
+edge(63,42).
+edge(42,66).
+edge(66,42).
+edge(42,71).
+edge(71,42).
+edge(42,75).
+edge(75,42).
+edge(42,76).
+edge(76,42).
+edge(42,87).
+edge(87,42).
+edge(42,96).
+edge(96,42).
+edge(42,98).
+edge(98,42).
+edge(42,109).
+edge(109,42).
+edge(42,110).
+edge(110,42).
+edge(42,114).
+edge(114,42).
+edge(42,119).
+edge(119,42).
+edge(42,124).
+edge(124,42).
+edge(42,139).
+edge(139,42).
+edge(42,140).
+edge(140,42).
+edge(43,44).
+edge(44,43).
+edge(43,47).
+edge(47,43).
+edge(43,50).
+edge(50,43).
+edge(43,53).
+edge(53,43).
+edge(43,57).
+edge(57,43).
+edge(43,61).
+edge(61,43).
+edge(43,69).
+edge(69,43).
+edge(43,70).
+edge(70,43).
+edge(43,73).
+edge(73,43).
+edge(43,74).
+edge(74,43).
+edge(43,85).
+edge(85,43).
+edge(43,90).
+edge(90,43).
+edge(43,91).
+edge(91,43).
+edge(43,117).
+edge(117,43).
+edge(43,120).
+edge(120,43).
+edge(43,121).
+edge(121,43).
+edge(43,122).
+edge(122,43).
+edge(43,124).
+edge(124,43).
+edge(43,136).
+edge(136,43).
+edge(44,84).
+edge(84,44).
+edge(44,92).
+edge(92,44).
+edge(44,93).
+edge(93,44).
+edge(44,110).
+edge(110,44).
+edge(45,55).
+edge(55,45).
+edge(45,65).
+edge(65,45).
+edge(45,71).
+edge(71,45).
+edge(45,79).
+edge(79,45).
+edge(45,81).
+edge(81,45).
+edge(45,111).
+edge(111,45).
+edge(45,134).
+edge(134,45).
+edge(45,136).
+edge(136,45).
+edge(45,137).
+edge(137,45).
+edge(45,144).
+edge(144,45).
+edge(46,48).
+edge(48,46).
+edge(46,74).
+edge(74,46).
+edge(46,92).
+edge(92,46).
+edge(46,100).
+edge(100,46).
+edge(46,138).
+edge(138,46).
+edge(46,141).
+edge(141,46).
+edge(47,54).
+edge(54,47).
+edge(47,59).
+edge(59,47).
+edge(47,77).
+edge(77,47).
+edge(47,86).
+edge(86,47).
+edge(47,89).
+edge(89,47).
+edge(47,120).
+edge(120,47).
+edge(47,128).
+edge(128,47).
+edge(47,136).
+edge(136,47).
+edge(47,138).
+edge(138,47).
+edge(47,141).
+edge(141,47).
+edge(48,49).
+edge(49,48).
+edge(48,59).
+edge(59,48).
+edge(48,69).
+edge(69,48).
+edge(48,78).
+edge(78,48).
+edge(48,87).
+edge(87,48).
+edge(48,133).
+edge(133,48).
+edge(48,142).
+edge(142,48).
+edge(49,61).
+edge(61,49).
+edge(49,65).
+edge(65,49).
+edge(49,67).
+edge(67,49).
+edge(49,83).
+edge(83,49).
+edge(49,87).
+edge(87,49).
+edge(49,98).
+edge(98,49).
+edge(49,136).
+edge(136,49).
+edge(49,143).
+edge(143,49).
+edge(49,145).
+edge(145,49).
+edge(50,63).
+edge(63,50).
+edge(50,85).
+edge(85,50).
+edge(50,97).
+edge(97,50).
+edge(50,121).
+edge(121,50).
+edge(50,134).
+edge(134,50).
+edge(51,53).
+edge(53,51).
+edge(51,58).
+edge(58,51).
+edge(51,67).
+edge(67,51).
+edge(51,81).
+edge(81,51).
+edge(51,99).
+edge(99,51).
+edge(51,105).
+edge(105,51).
+edge(51,108).
+edge(108,51).
+edge(51,109).
+edge(109,51).
+edge(51,111).
+edge(111,51).
+edge(51,118).
+edge(118,51).
+edge(51,134).
+edge(134,51).
+edge(52,59).
+edge(59,52).
+edge(52,61).
+edge(61,52).
+edge(52,130).
+edge(130,52).
+edge(53,62).
+edge(62,53).
+edge(53,69).
+edge(69,53).
+edge(53,79).
+edge(79,53).
+edge(53,80).
+edge(80,53).
+edge(53,81).
+edge(81,53).
+edge(53,92).
+edge(92,53).
+edge(53,96).
+edge(96,53).
+edge(53,115).
+edge(115,53).
+edge(53,132).
+edge(132,53).
+edge(53,139).
+edge(139,53).
+edge(54,58).
+edge(58,54).
+edge(54,62).
+edge(62,54).
+edge(54,93).
+edge(93,54).
+edge(54,99).
+edge(99,54).
+edge(54,104).
+edge(104,54).
+edge(54,106).
+edge(106,54).
+edge(54,118).
+edge(118,54).
+edge(54,136).
+edge(136,54).
+edge(55,57).
+edge(57,55).
+edge(55,72).
+edge(72,55).
+edge(55,104).
+edge(104,55).
+edge(55,105).
+edge(105,55).
+edge(55,112).
+edge(112,55).
+edge(55,124).
+edge(124,55).
+edge(55,138).
+edge(138,55).
+edge(56,62).
+edge(62,56).
+edge(56,70).
+edge(70,56).
+edge(56,92).
+edge(92,56).
+edge(56,113).
+edge(113,56).
+edge(56,114).
+edge(114,56).
+edge(56,124).
+edge(124,56).
+edge(56,139).
+edge(139,56).
+edge(57,66).
+edge(66,57).
+edge(57,67).
+edge(67,57).
+edge(57,88).
+edge(88,57).
+edge(57,98).
+edge(98,57).
+edge(57,99).
+edge(99,57).
+edge(57,109).
+edge(109,57).
+edge(57,117).
+edge(117,57).
+edge(57,130).
+edge(130,57).
+edge(57,133).
+edge(133,57).
+edge(57,141).
+edge(141,57).
+edge(58,61).
+edge(61,58).
+edge(58,75).
+edge(75,58).
+edge(58,96).
+edge(96,58).
+edge(58,122).
+edge(122,58).
+edge(59,62).
+edge(62,59).
+edge(59,73).
+edge(73,59).
+edge(59,87).
+edge(87,59).
+edge(59,95).
+edge(95,59).
+edge(59,136).
+edge(136,59).
+edge(59,140).
+edge(140,59).
+edge(60,68).
+edge(68,60).
+edge(60,70).
+edge(70,60).
+edge(60,95).
+edge(95,60).
+edge(60,96).
+edge(96,60).
+edge(60,104).
+edge(104,60).
+edge(60,110).
+edge(110,60).
+edge(61,66).
+edge(66,61).
+edge(61,67).
+edge(67,61).
+edge(61,77).
+edge(77,61).
+edge(61,87).
+edge(87,61).
+edge(61,101).
+edge(101,61).
+edge(61,122).
+edge(122,61).
+edge(61,144).
+edge(144,61).
+edge(62,64).
+edge(64,62).
+edge(62,70).
+edge(70,62).
+edge(62,72).
+edge(72,62).
+edge(62,76).
+edge(76,62).
+edge(62,86).
+edge(86,62).
+edge(62,93).
+edge(93,62).
+edge(62,122).
+edge(122,62).
+edge(62,125).
+edge(125,62).
+edge(62,127).
+edge(127,62).
+edge(62,130).
+edge(130,62).
+edge(63,70).
+edge(70,63).
+edge(63,72).
+edge(72,63).
+edge(63,85).
+edge(85,63).
+edge(63,98).
+edge(98,63).
+edge(63,106).
+edge(106,63).
+edge(63,108).
+edge(108,63).
+edge(63,109).
+edge(109,63).
+edge(63,120).
+edge(120,63).
+edge(63,126).
+edge(126,63).
+edge(63,130).
+edge(130,63).
+edge(63,131).
+edge(131,63).
+edge(64,74).
+edge(74,64).
+edge(64,87).
+edge(87,64).
+edge(64,101).
+edge(101,64).
+edge(65,81).
+edge(81,65).
+edge(65,85).
+edge(85,65).
+edge(65,110).
+edge(110,65).
+edge(65,117).
+edge(117,65).
+edge(65,132).
+edge(132,65).
+edge(65,138).
+edge(138,65).
+edge(65,145).
+edge(145,65).
+edge(66,67).
+edge(67,66).
+edge(66,83).
+edge(83,66).
+edge(66,84).
+edge(84,66).
+edge(66,88).
+edge(88,66).
+edge(66,94).
+edge(94,66).
+edge(66,111).
+edge(111,66).
+edge(66,115).
+edge(115,66).
+edge(66,140).
+edge(140,66).
+edge(66,142).
+edge(142,66).
+edge(67,72).
+edge(72,67).
+edge(67,73).
+edge(73,67).
+edge(67,82).
+edge(82,67).
+edge(67,83).
+edge(83,67).
+edge(67,86).
+edge(86,67).
+edge(67,100).
+edge(100,67).
+edge(67,101).
+edge(101,67).
+edge(67,109).
+edge(109,67).
+edge(67,112).
+edge(112,67).
+edge(67,123).
+edge(123,67).
+edge(67,131).
+edge(131,67).
+edge(67,135).
+edge(135,67).
+edge(68,75).
+edge(75,68).
+edge(68,96).
+edge(96,68).
+edge(68,119).
+edge(119,68).
+edge(68,132).
+edge(132,68).
+edge(69,70).
+edge(70,69).
+edge(69,71).
+edge(71,69).
+edge(69,79).
+edge(79,69).
+edge(69,85).
+edge(85,69).
+edge(69,90).
+edge(90,69).
+edge(69,92).
+edge(92,69).
+edge(69,99).
+edge(99,69).
+edge(69,104).
+edge(104,69).
+edge(69,105).
+edge(105,69).
+edge(69,116).
+edge(116,69).
+edge(69,144).
+edge(144,69).
+edge(70,92).
+edge(92,70).
+edge(70,97).
+edge(97,70).
+edge(70,119).
+edge(119,70).
+edge(70,125).
+edge(125,70).
+edge(70,136).
+edge(136,70).
+edge(70,141).
+edge(141,70).
+edge(71,75).
+edge(75,71).
+edge(71,78).
+edge(78,71).
+edge(71,87).
+edge(87,71).
+edge(71,93).
+edge(93,71).
+edge(71,100).
+edge(100,71).
+edge(71,111).
+edge(111,71).
+edge(71,115).
+edge(115,71).
+edge(71,133).
+edge(133,71).
+edge(72,77).
+edge(77,72).
+edge(72,82).
+edge(82,72).
+edge(72,90).
+edge(90,72).
+edge(72,117).
+edge(117,72).
+edge(72,126).
+edge(126,72).
+edge(72,132).
+edge(132,72).
+edge(72,137).
+edge(137,72).
+edge(73,116).
+edge(116,73).
+edge(73,117).
+edge(117,73).
+edge(73,121).
+edge(121,73).
+edge(73,130).
+edge(130,73).
+edge(73,131).
+edge(131,73).
+edge(74,76).
+edge(76,74).
+edge(74,83).
+edge(83,74).
+edge(74,98).
+edge(98,74).
+edge(74,107).
+edge(107,74).
+edge(74,119).
+edge(119,74).
+edge(74,135).
+edge(135,74).
+edge(74,136).
+edge(136,74).
+edge(74,139).
+edge(139,74).
+edge(75,93).
+edge(93,75).
+edge(75,107).
+edge(107,75).
+edge(75,125).
+edge(125,75).
+edge(75,126).
+edge(126,75).
+edge(75,131).
+edge(131,75).
+edge(76,118).
+edge(118,76).
+edge(76,130).
+edge(130,76).
+edge(76,139).
+edge(139,76).
+edge(77,78).
+edge(78,77).
+edge(77,103).
+edge(103,77).
+edge(77,109).
+edge(109,77).
+edge(77,137).
+edge(137,77).
+edge(77,143).
+edge(143,77).
+edge(78,79).
+edge(79,78).
+edge(78,97).
+edge(97,78).
+edge(78,98).
+edge(98,78).
+edge(78,105).
+edge(105,78).
+edge(78,117).
+edge(117,78).
+edge(78,135).
+edge(135,78).
+edge(79,85).
+edge(85,79).
+edge(79,86).
+edge(86,79).
+edge(79,94).
+edge(94,79).
+edge(79,117).
+edge(117,79).
+edge(79,121).
+edge(121,79).
+edge(79,129).
+edge(129,79).
+edge(79,136).
+edge(136,79).
+edge(79,143).
+edge(143,79).
+edge(79,145).
+edge(145,79).
+edge(80,81).
+edge(81,80).
+edge(80,83).
+edge(83,80).
+edge(80,115).
+edge(115,80).
+edge(80,121).
+edge(121,80).
+edge(80,129).
+edge(129,80).
+edge(80,135).
+edge(135,80).
+edge(80,140).
+edge(140,80).
+edge(81,82).
+edge(82,81).
+edge(81,85).
+edge(85,81).
+edge(81,90).
+edge(90,81).
+edge(81,104).
+edge(104,81).
+edge(81,108).
+edge(108,81).
+edge(81,115).
+edge(115,81).
+edge(81,122).
+edge(122,81).
+edge(81,126).
+edge(126,81).
+edge(81,130).
+edge(130,81).
+edge(81,136).
+edge(136,81).
+edge(82,112).
+edge(112,82).
+edge(82,115).
+edge(115,82).
+edge(82,123).
+edge(123,82).
+edge(82,129).
+edge(129,82).
+edge(82,130).
+edge(130,82).
+edge(82,140).
+edge(140,82).
+edge(83,95).
+edge(95,83).
+edge(83,105).
+edge(105,83).
+edge(83,107).
+edge(107,83).
+edge(83,110).
+edge(110,83).
+edge(83,118).
+edge(118,83).
+edge(84,85).
+edge(85,84).
+edge(84,89).
+edge(89,84).
+edge(84,93).
+edge(93,84).
+edge(84,115).
+edge(115,84).
+edge(84,116).
+edge(116,84).
+edge(84,123).
+edge(123,84).
+edge(84,131).
+edge(131,84).
+edge(84,133).
+edge(133,84).
+edge(85,91).
+edge(91,85).
+edge(85,99).
+edge(99,85).
+edge(85,100).
+edge(100,85).
+edge(85,114).
+edge(114,85).
+edge(85,119).
+edge(119,85).
+edge(85,132).
+edge(132,85).
+edge(86,113).
+edge(113,86).
+edge(86,127).
+edge(127,86).
+edge(86,135).
+edge(135,86).
+edge(86,138).
+edge(138,86).
+edge(86,141).
+edge(141,86).
+edge(86,142).
+edge(142,86).
+edge(87,88).
+edge(88,87).
+edge(87,90).
+edge(90,87).
+edge(87,99).
+edge(99,87).
+edge(87,103).
+edge(103,87).
+edge(87,112).
+edge(112,87).
+edge(87,118).
+edge(118,87).
+edge(87,119).
+edge(119,87).
+edge(87,122).
+edge(122,87).
+edge(87,135).
+edge(135,87).
+edge(87,138).
+edge(138,87).
+edge(87,141).
+edge(141,87).
+edge(88,93).
+edge(93,88).
+edge(88,95).
+edge(95,88).
+edge(88,106).
+edge(106,88).
+edge(88,111).
+edge(111,88).
+edge(88,113).
+edge(113,88).
+edge(88,115).
+edge(115,88).
+edge(88,123).
+edge(123,88).
+edge(88,138).
+edge(138,88).
+edge(89,91).
+edge(91,89).
+edge(89,92).
+edge(92,89).
+edge(89,98).
+edge(98,89).
+edge(89,110).
+edge(110,89).
+edge(89,128).
+edge(128,89).
+edge(89,131).
+edge(131,89).
+edge(90,98).
+edge(98,90).
+edge(91,99).
+edge(99,91).
+edge(91,121).
+edge(121,91).
+edge(91,122).
+edge(122,91).
+edge(91,127).
+edge(127,91).
+edge(91,143).
+edge(143,91).
+edge(92,101).
+edge(101,92).
+edge(92,113).
+edge(113,92).
+edge(92,118).
+edge(118,92).
+edge(92,135).
+edge(135,92).
+edge(92,144).
+edge(144,92).
+edge(93,127).
+edge(127,93).
+edge(94,117).
+edge(117,94).
+edge(94,123).
+edge(123,94).
+edge(94,129).
+edge(129,94).
+edge(94,145).
+edge(145,94).
+edge(95,96).
+edge(96,95).
+edge(95,106).
+edge(106,95).
+edge(95,113).
+edge(113,95).
+edge(95,118).
+edge(118,95).
+edge(95,119).
+edge(119,95).
+edge(95,120).
+edge(120,95).
+edge(95,121).
+edge(121,95).
+edge(95,126).
+edge(126,95).
+edge(95,129).
+edge(129,95).
+edge(95,132).
+edge(132,95).
+edge(96,104).
+edge(104,96).
+edge(96,107).
+edge(107,96).
+edge(96,108).
+edge(108,96).
+edge(96,116).
+edge(116,96).
+edge(96,122).
+edge(122,96).
+edge(96,126).
+edge(126,96).
+edge(96,130).
+edge(130,96).
+edge(97,132).
+edge(132,97).
+edge(98,113).
+edge(113,98).
+edge(98,118).
+edge(118,98).
+edge(98,126).
+edge(126,98).
+edge(98,140).
+edge(140,98).
+edge(98,145).
+edge(145,98).
+edge(100,103).
+edge(103,100).
+edge(100,107).
+edge(107,100).
+edge(100,114).
+edge(114,100).
+edge(100,120).
+edge(120,100).
+edge(100,144).
+edge(144,100).
+edge(101,103).
+edge(103,101).
+edge(101,108).
+edge(108,101).
+edge(101,114).
+edge(114,101).
+edge(101,132).
+edge(132,101).
+edge(101,138).
+edge(138,101).
+edge(101,143).
+edge(143,101).
+edge(102,124).
+edge(124,102).
+edge(102,127).
+edge(127,102).
+edge(102,131).
+edge(131,102).
+edge(102,133).
+edge(133,102).
+edge(103,107).
+edge(107,103).
+edge(103,116).
+edge(116,103).
+edge(103,123).
+edge(123,103).
+edge(103,126).
+edge(126,103).
+edge(103,139).
+edge(139,103).
+edge(104,119).
+edge(119,104).
+edge(104,124).
+edge(124,104).
+edge(104,130).
+edge(130,104).
+edge(104,132).
+edge(132,104).
+edge(104,136).
+edge(136,104).
+edge(105,128).
+edge(128,105).
+edge(105,133).
+edge(133,105).
+edge(105,135).
+edge(135,105).
+edge(105,142).
+edge(142,105).
+edge(106,107).
+edge(107,106).
+edge(106,108).
+edge(108,106).
+edge(106,132).
+edge(132,106).
+edge(107,115).
+edge(115,107).
+edge(107,121).
+edge(121,107).
+edge(107,131).
+edge(131,107).
+edge(107,140).
+edge(140,107).
+edge(107,143).
+edge(143,107).
+edge(107,145).
+edge(145,107).
+edge(108,128).
+edge(128,108).
+edge(108,139).
+edge(139,108).
+edge(109,123).
+edge(123,109).
+edge(109,125).
+edge(125,109).
+edge(110,138).
+edge(138,110).
+edge(111,130).
+edge(130,111).
+edge(111,134).
+edge(134,111).
+edge(111,138).
+edge(138,111).
+edge(112,118).
+edge(118,112).
+edge(112,119).
+edge(119,112).
+edge(112,126).
+edge(126,112).
+edge(112,132).
+edge(132,112).
+edge(112,137).
+edge(137,112).
+edge(112,138).
+edge(138,112).
+edge(112,144).
+edge(144,112).
+edge(113,119).
+edge(119,113).
+edge(113,125).
+edge(125,113).
+edge(114,133).
+edge(133,114).
+edge(114,137).
+edge(137,114).
+edge(114,141).
+edge(141,114).
+edge(115,117).
+edge(117,115).
+edge(115,123).
+edge(123,115).
+edge(115,125).
+edge(125,115).
+edge(116,117).
+edge(117,116).
+edge(116,118).
+edge(118,116).
+edge(116,119).
+edge(119,116).
+edge(116,130).
+edge(130,116).
+edge(117,128).
+edge(128,117).
+edge(117,135).
+edge(135,117).
+edge(117,144).
+edge(144,117).
+edge(118,119).
+edge(119,118).
+edge(119,130).
+edge(130,119).
+edge(119,131).
+edge(131,119).
+edge(119,143).
+edge(143,119).
+edge(120,126).
+edge(126,120).
+edge(120,133).
+edge(133,120).
+edge(120,134).
+edge(134,120).
+edge(120,137).
+edge(137,120).
+edge(120,138).
+edge(138,120).
+edge(121,123).
+edge(123,121).
+edge(121,126).
+edge(126,121).
+edge(121,127).
+edge(127,121).
+edge(121,142).
+edge(142,121).
+edge(122,127).
+edge(127,122).
+edge(122,134).
+edge(134,122).
+edge(122,145).
+edge(145,122).
+edge(123,125).
+edge(125,123).
+edge(123,131).
+edge(131,123).
+edge(124,133).
+edge(133,124).
+edge(124,137).
+edge(137,124).
+edge(124,143).
+edge(143,124).
+edge(125,127).
+edge(127,125).
+edge(125,129).
+edge(129,125).
+edge(125,137).
+edge(137,125).
+edge(125,143).
+edge(143,125).
+edge(126,136).
+edge(136,126).
+edge(126,139).
+edge(139,126).
+edge(126,141).
+edge(141,126).
+edge(127,129).
+edge(129,127).
+edge(127,132).
+edge(132,127).
+edge(127,143).
+edge(143,127).
+edge(128,142).
+edge(142,128).
+edge(129,131).
+edge(131,129).
+edge(129,140).
+edge(140,129).
+edge(130,134).
+edge(134,130).
+edge(130,136).
+edge(136,130).
+edge(132,138).
+edge(138,132).
+edge(132,139).
+edge(139,132).
+edge(133,135).
+edge(135,133).
+edge(134,139).
+edge(139,134).
+edge(134,144).
+edge(144,134).
+edge(135,137).
+edge(137,135).
+edge(136,138).
+edge(138,136).
+edge(136,140).
+edge(140,136).
+edge(137,141).
+edge(141,137).
+edge(138,143).
+edge(143,138).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0048-graph_colouring-145-0.lp b/examples/clingo/expansion/GraphColouring/instances/0048-graph_colouring-145-0.lp
new file mode 100644
index 0000000..94478b6
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0048-graph_colouring-145-0.lp
@@ -0,0 +1,2233 @@
+#const n=145.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+edge(1,6).
+edge(6,1).
+edge(1,22).
+edge(22,1).
+edge(1,31).
+edge(31,1).
+edge(1,49).
+edge(49,1).
+edge(1,56).
+edge(56,1).
+edge(1,72).
+edge(72,1).
+edge(1,74).
+edge(74,1).
+edge(1,86).
+edge(86,1).
+edge(1,94).
+edge(94,1).
+edge(1,111).
+edge(111,1).
+edge(2,7).
+edge(7,2).
+edge(2,11).
+edge(11,2).
+edge(2,14).
+edge(14,2).
+edge(2,23).
+edge(23,2).
+edge(2,36).
+edge(36,2).
+edge(2,40).
+edge(40,2).
+edge(2,58).
+edge(58,2).
+edge(2,67).
+edge(67,2).
+edge(2,73).
+edge(73,2).
+edge(2,76).
+edge(76,2).
+edge(2,97).
+edge(97,2).
+edge(2,98).
+edge(98,2).
+edge(2,101).
+edge(101,2).
+edge(2,120).
+edge(120,2).
+edge(2,121).
+edge(121,2).
+edge(2,125).
+edge(125,2).
+edge(2,134).
+edge(134,2).
+edge(2,136).
+edge(136,2).
+edge(2,141).
+edge(141,2).
+edge(2,143).
+edge(143,2).
+edge(3,6).
+edge(6,3).
+edge(3,15).
+edge(15,3).
+edge(3,16).
+edge(16,3).
+edge(3,19).
+edge(19,3).
+edge(3,23).
+edge(23,3).
+edge(3,24).
+edge(24,3).
+edge(3,55).
+edge(55,3).
+edge(3,62).
+edge(62,3).
+edge(3,84).
+edge(84,3).
+edge(3,113).
+edge(113,3).
+edge(3,116).
+edge(116,3).
+edge(3,119).
+edge(119,3).
+edge(3,136).
+edge(136,3).
+edge(3,138).
+edge(138,3).
+edge(4,12).
+edge(12,4).
+edge(4,14).
+edge(14,4).
+edge(4,32).
+edge(32,4).
+edge(4,47).
+edge(47,4).
+edge(4,60).
+edge(60,4).
+edge(4,69).
+edge(69,4).
+edge(4,103).
+edge(103,4).
+edge(4,105).
+edge(105,4).
+edge(4,114).
+edge(114,4).
+edge(4,120).
+edge(120,4).
+edge(4,122).
+edge(122,4).
+edge(4,125).
+edge(125,4).
+edge(4,127).
+edge(127,4).
+edge(5,24).
+edge(24,5).
+edge(5,37).
+edge(37,5).
+edge(5,39).
+edge(39,5).
+edge(5,46).
+edge(46,5).
+edge(5,64).
+edge(64,5).
+edge(5,80).
+edge(80,5).
+edge(5,95).
+edge(95,5).
+edge(5,97).
+edge(97,5).
+edge(5,103).
+edge(103,5).
+edge(5,112).
+edge(112,5).
+edge(5,114).
+edge(114,5).
+edge(5,126).
+edge(126,5).
+edge(5,138).
+edge(138,5).
+edge(6,12).
+edge(12,6).
+edge(6,17).
+edge(17,6).
+edge(6,18).
+edge(18,6).
+edge(6,26).
+edge(26,6).
+edge(6,34).
+edge(34,6).
+edge(6,63).
+edge(63,6).
+edge(6,75).
+edge(75,6).
+edge(6,77).
+edge(77,6).
+edge(6,87).
+edge(87,6).
+edge(6,100).
+edge(100,6).
+edge(6,107).
+edge(107,6).
+edge(6,111).
+edge(111,6).
+edge(6,122).
+edge(122,6).
+edge(6,126).
+edge(126,6).
+edge(6,136).
+edge(136,6).
+edge(6,144).
+edge(144,6).
+edge(7,41).
+edge(41,7).
+edge(7,46).
+edge(46,7).
+edge(7,56).
+edge(56,7).
+edge(7,58).
+edge(58,7).
+edge(7,67).
+edge(67,7).
+edge(7,68).
+edge(68,7).
+edge(7,86).
+edge(86,7).
+edge(7,87).
+edge(87,7).
+edge(7,89).
+edge(89,7).
+edge(7,90).
+edge(90,7).
+edge(7,93).
+edge(93,7).
+edge(7,122).
+edge(122,7).
+edge(7,132).
+edge(132,7).
+edge(7,142).
+edge(142,7).
+edge(8,14).
+edge(14,8).
+edge(8,15).
+edge(15,8).
+edge(8,22).
+edge(22,8).
+edge(8,34).
+edge(34,8).
+edge(8,38).
+edge(38,8).
+edge(8,39).
+edge(39,8).
+edge(8,42).
+edge(42,8).
+edge(8,54).
+edge(54,8).
+edge(8,58).
+edge(58,8).
+edge(8,62).
+edge(62,8).
+edge(8,65).
+edge(65,8).
+edge(8,76).
+edge(76,8).
+edge(8,94).
+edge(94,8).
+edge(8,95).
+edge(95,8).
+edge(8,101).
+edge(101,8).
+edge(8,125).
+edge(125,8).
+edge(8,136).
+edge(136,8).
+edge(9,14).
+edge(14,9).
+edge(9,16).
+edge(16,9).
+edge(9,39).
+edge(39,9).
+edge(9,65).
+edge(65,9).
+edge(9,96).
+edge(96,9).
+edge(9,98).
+edge(98,9).
+edge(9,106).
+edge(106,9).
+edge(9,125).
+edge(125,9).
+edge(9,144).
+edge(144,9).
+edge(10,18).
+edge(18,10).
+edge(10,32).
+edge(32,10).
+edge(10,40).
+edge(40,10).
+edge(10,46).
+edge(46,10).
+edge(10,47).
+edge(47,10).
+edge(10,49).
+edge(49,10).
+edge(10,51).
+edge(51,10).
+edge(10,77).
+edge(77,10).
+edge(10,99).
+edge(99,10).
+edge(10,112).
+edge(112,10).
+edge(10,115).
+edge(115,10).
+edge(10,138).
+edge(138,10).
+edge(11,14).
+edge(14,11).
+edge(11,22).
+edge(22,11).
+edge(11,48).
+edge(48,11).
+edge(11,53).
+edge(53,11).
+edge(11,58).
+edge(58,11).
+edge(11,64).
+edge(64,11).
+edge(11,67).
+edge(67,11).
+edge(11,73).
+edge(73,11).
+edge(11,85).
+edge(85,11).
+edge(11,93).
+edge(93,11).
+edge(11,99).
+edge(99,11).
+edge(11,105).
+edge(105,11).
+edge(11,123).
+edge(123,11).
+edge(11,124).
+edge(124,11).
+edge(11,130).
+edge(130,11).
+edge(11,138).
+edge(138,11).
+edge(11,139).
+edge(139,11).
+edge(12,13).
+edge(13,12).
+edge(12,23).
+edge(23,12).
+edge(12,35).
+edge(35,12).
+edge(12,37).
+edge(37,12).
+edge(12,40).
+edge(40,12).
+edge(12,52).
+edge(52,12).
+edge(12,70).
+edge(70,12).
+edge(12,72).
+edge(72,12).
+edge(12,93).
+edge(93,12).
+edge(12,102).
+edge(102,12).
+edge(12,105).
+edge(105,12).
+edge(12,117).
+edge(117,12).
+edge(12,129).
+edge(129,12).
+edge(12,138).
+edge(138,12).
+edge(13,47).
+edge(47,13).
+edge(13,48).
+edge(48,13).
+edge(13,84).
+edge(84,13).
+edge(13,88).
+edge(88,13).
+edge(13,97).
+edge(97,13).
+edge(13,110).
+edge(110,13).
+edge(13,117).
+edge(117,13).
+edge(13,131).
+edge(131,13).
+edge(14,19).
+edge(19,14).
+edge(14,26).
+edge(26,14).
+edge(14,30).
+edge(30,14).
+edge(14,35).
+edge(35,14).
+edge(14,46).
+edge(46,14).
+edge(14,49).
+edge(49,14).
+edge(14,53).
+edge(53,14).
+edge(14,58).
+edge(58,14).
+edge(14,65).
+edge(65,14).
+edge(14,66).
+edge(66,14).
+edge(14,68).
+edge(68,14).
+edge(14,86).
+edge(86,14).
+edge(14,87).
+edge(87,14).
+edge(14,98).
+edge(98,14).
+edge(14,99).
+edge(99,14).
+edge(14,127).
+edge(127,14).
+edge(14,130).
+edge(130,14).
+edge(15,23).
+edge(23,15).
+edge(15,38).
+edge(38,15).
+edge(15,42).
+edge(42,15).
+edge(15,44).
+edge(44,15).
+edge(15,57).
+edge(57,15).
+edge(15,98).
+edge(98,15).
+edge(15,103).
+edge(103,15).
+edge(15,105).
+edge(105,15).
+edge(15,114).
+edge(114,15).
+edge(15,143).
+edge(143,15).
+edge(16,35).
+edge(35,16).
+edge(16,58).
+edge(58,16).
+edge(16,61).
+edge(61,16).
+edge(16,68).
+edge(68,16).
+edge(16,74).
+edge(74,16).
+edge(16,78).
+edge(78,16).
+edge(16,89).
+edge(89,16).
+edge(16,94).
+edge(94,16).
+edge(16,107).
+edge(107,16).
+edge(16,114).
+edge(114,16).
+edge(16,117).
+edge(117,16).
+edge(16,122).
+edge(122,16).
+edge(16,130).
+edge(130,16).
+edge(16,131).
+edge(131,16).
+edge(16,133).
+edge(133,16).
+edge(16,135).
+edge(135,16).
+edge(16,142).
+edge(142,16).
+edge(17,22).
+edge(22,17).
+edge(17,23).
+edge(23,17).
+edge(17,39).
+edge(39,17).
+edge(17,43).
+edge(43,17).
+edge(17,56).
+edge(56,17).
+edge(17,61).
+edge(61,17).
+edge(17,67).
+edge(67,17).
+edge(17,83).
+edge(83,17).
+edge(17,85).
+edge(85,17).
+edge(17,88).
+edge(88,17).
+edge(17,95).
+edge(95,17).
+edge(17,99).
+edge(99,17).
+edge(17,105).
+edge(105,17).
+edge(17,120).
+edge(120,17).
+edge(17,135).
+edge(135,17).
+edge(18,51).
+edge(51,18).
+edge(18,52).
+edge(52,18).
+edge(18,65).
+edge(65,18).
+edge(18,69).
+edge(69,18).
+edge(18,87).
+edge(87,18).
+edge(18,91).
+edge(91,18).
+edge(18,97).
+edge(97,18).
+edge(18,106).
+edge(106,18).
+edge(18,109).
+edge(109,18).
+edge(18,117).
+edge(117,18).
+edge(18,136).
+edge(136,18).
+edge(18,141).
+edge(141,18).
+edge(19,32).
+edge(32,19).
+edge(19,39).
+edge(39,19).
+edge(19,42).
+edge(42,19).
+edge(19,50).
+edge(50,19).
+edge(19,53).
+edge(53,19).
+edge(19,59).
+edge(59,19).
+edge(19,66).
+edge(66,19).
+edge(19,97).
+edge(97,19).
+edge(19,101).
+edge(101,19).
+edge(19,107).
+edge(107,19).
+edge(19,113).
+edge(113,19).
+edge(19,116).
+edge(116,19).
+edge(19,120).
+edge(120,19).
+edge(19,145).
+edge(145,19).
+edge(20,34).
+edge(34,20).
+edge(20,44).
+edge(44,20).
+edge(20,48).
+edge(48,20).
+edge(20,50).
+edge(50,20).
+edge(20,89).
+edge(89,20).
+edge(20,92).
+edge(92,20).
+edge(20,99).
+edge(99,20).
+edge(20,108).
+edge(108,20).
+edge(20,110).
+edge(110,20).
+edge(20,111).
+edge(111,20).
+edge(20,115).
+edge(115,20).
+edge(20,123).
+edge(123,20).
+edge(20,142).
+edge(142,20).
+edge(20,144).
+edge(144,20).
+edge(21,30).
+edge(30,21).
+edge(21,37).
+edge(37,21).
+edge(21,41).
+edge(41,21).
+edge(21,59).
+edge(59,21).
+edge(21,82).
+edge(82,21).
+edge(21,98).
+edge(98,21).
+edge(21,121).
+edge(121,21).
+edge(21,123).
+edge(123,21).
+edge(21,124).
+edge(124,21).
+edge(21,138).
+edge(138,21).
+edge(21,142).
+edge(142,21).
+edge(21,144).
+edge(144,21).
+edge(22,24).
+edge(24,22).
+edge(22,31).
+edge(31,22).
+edge(22,47).
+edge(47,22).
+edge(22,58).
+edge(58,22).
+edge(22,61).
+edge(61,22).
+edge(22,63).
+edge(63,22).
+edge(22,66).
+edge(66,22).
+edge(22,69).
+edge(69,22).
+edge(22,78).
+edge(78,22).
+edge(22,83).
+edge(83,22).
+edge(22,114).
+edge(114,22).
+edge(22,129).
+edge(129,22).
+edge(22,131).
+edge(131,22).
+edge(22,139).
+edge(139,22).
+edge(22,141).
+edge(141,22).
+edge(23,24).
+edge(24,23).
+edge(23,28).
+edge(28,23).
+edge(23,34).
+edge(34,23).
+edge(23,38).
+edge(38,23).
+edge(23,40).
+edge(40,23).
+edge(23,41).
+edge(41,23).
+edge(23,47).
+edge(47,23).
+edge(23,53).
+edge(53,23).
+edge(23,76).
+edge(76,23).
+edge(23,78).
+edge(78,23).
+edge(23,105).
+edge(105,23).
+edge(23,113).
+edge(113,23).
+edge(23,123).
+edge(123,23).
+edge(23,129).
+edge(129,23).
+edge(23,130).
+edge(130,23).
+edge(23,139).
+edge(139,23).
+edge(24,82).
+edge(82,24).
+edge(24,129).
+edge(129,24).
+edge(24,134).
+edge(134,24).
+edge(24,140).
+edge(140,24).
+edge(25,26).
+edge(26,25).
+edge(25,27).
+edge(27,25).
+edge(25,32).
+edge(32,25).
+edge(25,42).
+edge(42,25).
+edge(25,49).
+edge(49,25).
+edge(25,52).
+edge(52,25).
+edge(25,58).
+edge(58,25).
+edge(25,66).
+edge(66,25).
+edge(25,73).
+edge(73,25).
+edge(25,88).
+edge(88,25).
+edge(25,89).
+edge(89,25).
+edge(25,101).
+edge(101,25).
+edge(25,107).
+edge(107,25).
+edge(25,108).
+edge(108,25).
+edge(25,109).
+edge(109,25).
+edge(25,121).
+edge(121,25).
+edge(25,122).
+edge(122,25).
+edge(25,130).
+edge(130,25).
+edge(25,132).
+edge(132,25).
+edge(25,135).
+edge(135,25).
+edge(26,38).
+edge(38,26).
+edge(26,43).
+edge(43,26).
+edge(26,53).
+edge(53,26).
+edge(26,56).
+edge(56,26).
+edge(26,59).
+edge(59,26).
+edge(26,64).
+edge(64,26).
+edge(26,65).
+edge(65,26).
+edge(26,66).
+edge(66,26).
+edge(26,76).
+edge(76,26).
+edge(26,84).
+edge(84,26).
+edge(26,97).
+edge(97,26).
+edge(26,98).
+edge(98,26).
+edge(26,102).
+edge(102,26).
+edge(26,105).
+edge(105,26).
+edge(26,123).
+edge(123,26).
+edge(26,128).
+edge(128,26).
+edge(26,131).
+edge(131,26).
+edge(27,53).
+edge(53,27).
+edge(27,55).
+edge(55,27).
+edge(27,64).
+edge(64,27).
+edge(27,67).
+edge(67,27).
+edge(27,74).
+edge(74,27).
+edge(27,81).
+edge(81,27).
+edge(27,83).
+edge(83,27).
+edge(27,96).
+edge(96,27).
+edge(27,97).
+edge(97,27).
+edge(27,98).
+edge(98,27).
+edge(27,102).
+edge(102,27).
+edge(27,111).
+edge(111,27).
+edge(27,135).
+edge(135,27).
+edge(28,37).
+edge(37,28).
+edge(28,44).
+edge(44,28).
+edge(28,56).
+edge(56,28).
+edge(28,67).
+edge(67,28).
+edge(28,68).
+edge(68,28).
+edge(28,72).
+edge(72,28).
+edge(28,88).
+edge(88,28).
+edge(28,103).
+edge(103,28).
+edge(28,121).
+edge(121,28).
+edge(28,134).
+edge(134,28).
+edge(28,141).
+edge(141,28).
+edge(28,144).
+edge(144,28).
+edge(29,32).
+edge(32,29).
+edge(29,36).
+edge(36,29).
+edge(29,42).
+edge(42,29).
+edge(29,46).
+edge(46,29).
+edge(29,49).
+edge(49,29).
+edge(29,78).
+edge(78,29).
+edge(29,79).
+edge(79,29).
+edge(29,80).
+edge(80,29).
+edge(29,84).
+edge(84,29).
+edge(29,87).
+edge(87,29).
+edge(29,106).
+edge(106,29).
+edge(29,111).
+edge(111,29).
+edge(29,115).
+edge(115,29).
+edge(29,116).
+edge(116,29).
+edge(29,127).
+edge(127,29).
+edge(29,145).
+edge(145,29).
+edge(30,36).
+edge(36,30).
+edge(30,38).
+edge(38,30).
+edge(30,41).
+edge(41,30).
+edge(30,46).
+edge(46,30).
+edge(30,58).
+edge(58,30).
+edge(30,74).
+edge(74,30).
+edge(30,77).
+edge(77,30).
+edge(30,85).
+edge(85,30).
+edge(30,93).
+edge(93,30).
+edge(30,99).
+edge(99,30).
+edge(30,106).
+edge(106,30).
+edge(30,127).
+edge(127,30).
+edge(31,34).
+edge(34,31).
+edge(31,46).
+edge(46,31).
+edge(31,47).
+edge(47,31).
+edge(31,53).
+edge(53,31).
+edge(31,57).
+edge(57,31).
+edge(31,72).
+edge(72,31).
+edge(31,73).
+edge(73,31).
+edge(31,81).
+edge(81,31).
+edge(31,83).
+edge(83,31).
+edge(31,99).
+edge(99,31).
+edge(31,103).
+edge(103,31).
+edge(31,111).
+edge(111,31).
+edge(31,117).
+edge(117,31).
+edge(31,118).
+edge(118,31).
+edge(31,126).
+edge(126,31).
+edge(31,132).
+edge(132,31).
+edge(31,136).
+edge(136,31).
+edge(32,35).
+edge(35,32).
+edge(32,38).
+edge(38,32).
+edge(32,61).
+edge(61,32).
+edge(32,90).
+edge(90,32).
+edge(32,95).
+edge(95,32).
+edge(32,98).
+edge(98,32).
+edge(32,99).
+edge(99,32).
+edge(32,106).
+edge(106,32).
+edge(32,110).
+edge(110,32).
+edge(32,121).
+edge(121,32).
+edge(32,129).
+edge(129,32).
+edge(32,141).
+edge(141,32).
+edge(32,142).
+edge(142,32).
+edge(33,47).
+edge(47,33).
+edge(33,51).
+edge(51,33).
+edge(33,57).
+edge(57,33).
+edge(33,71).
+edge(71,33).
+edge(33,81).
+edge(81,33).
+edge(33,104).
+edge(104,33).
+edge(33,118).
+edge(118,33).
+edge(33,121).
+edge(121,33).
+edge(33,124).
+edge(124,33).
+edge(33,129).
+edge(129,33).
+edge(34,72).
+edge(72,34).
+edge(34,75).
+edge(75,34).
+edge(34,89).
+edge(89,34).
+edge(34,94).
+edge(94,34).
+edge(34,96).
+edge(96,34).
+edge(34,101).
+edge(101,34).
+edge(34,104).
+edge(104,34).
+edge(34,118).
+edge(118,34).
+edge(34,135).
+edge(135,34).
+edge(34,139).
+edge(139,34).
+edge(34,141).
+edge(141,34).
+edge(35,42).
+edge(42,35).
+edge(35,57).
+edge(57,35).
+edge(35,63).
+edge(63,35).
+edge(35,64).
+edge(64,35).
+edge(35,67).
+edge(67,35).
+edge(35,69).
+edge(69,35).
+edge(35,86).
+edge(86,35).
+edge(35,120).
+edge(120,35).
+edge(35,126).
+edge(126,35).
+edge(36,48).
+edge(48,36).
+edge(36,50).
+edge(50,36).
+edge(36,61).
+edge(61,36).
+edge(36,75).
+edge(75,36).
+edge(36,80).
+edge(80,36).
+edge(36,84).
+edge(84,36).
+edge(36,101).
+edge(101,36).
+edge(36,117).
+edge(117,36).
+edge(36,120).
+edge(120,36).
+edge(36,126).
+edge(126,36).
+edge(37,43).
+edge(43,37).
+edge(37,58).
+edge(58,37).
+edge(37,64).
+edge(64,37).
+edge(37,71).
+edge(71,37).
+edge(37,91).
+edge(91,37).
+edge(37,107).
+edge(107,37).
+edge(37,114).
+edge(114,37).
+edge(37,120).
+edge(120,37).
+edge(37,140).
+edge(140,37).
+edge(38,41).
+edge(41,38).
+edge(38,54).
+edge(54,38).
+edge(38,73).
+edge(73,38).
+edge(38,75).
+edge(75,38).
+edge(38,87).
+edge(87,38).
+edge(38,88).
+edge(88,38).
+edge(38,100).
+edge(100,38).
+edge(38,101).
+edge(101,38).
+edge(38,108).
+edge(108,38).
+edge(38,109).
+edge(109,38).
+edge(38,119).
+edge(119,38).
+edge(38,121).
+edge(121,38).
+edge(38,124).
+edge(124,38).
+edge(38,127).
+edge(127,38).
+edge(39,40).
+edge(40,39).
+edge(39,49).
+edge(49,39).
+edge(39,50).
+edge(50,39).
+edge(39,62).
+edge(62,39).
+edge(39,78).
+edge(78,39).
+edge(39,81).
+edge(81,39).
+edge(39,89).
+edge(89,39).
+edge(39,95).
+edge(95,39).
+edge(39,107).
+edge(107,39).
+edge(39,113).
+edge(113,39).
+edge(39,130).
+edge(130,39).
+edge(39,133).
+edge(133,39).
+edge(39,138).
+edge(138,39).
+edge(40,50).
+edge(50,40).
+edge(40,55).
+edge(55,40).
+edge(40,64).
+edge(64,40).
+edge(40,65).
+edge(65,40).
+edge(40,69).
+edge(69,40).
+edge(40,79).
+edge(79,40).
+edge(40,103).
+edge(103,40).
+edge(40,104).
+edge(104,40).
+edge(40,112).
+edge(112,40).
+edge(40,140).
+edge(140,40).
+edge(40,145).
+edge(145,40).
+edge(41,61).
+edge(61,41).
+edge(41,66).
+edge(66,41).
+edge(41,73).
+edge(73,41).
+edge(41,87).
+edge(87,41).
+edge(41,113).
+edge(113,41).
+edge(41,116).
+edge(116,41).
+edge(41,117).
+edge(117,41).
+edge(41,125).
+edge(125,41).
+edge(42,53).
+edge(53,42).
+edge(42,89).
+edge(89,42).
+edge(42,93).
+edge(93,42).
+edge(42,102).
+edge(102,42).
+edge(42,113).
+edge(113,42).
+edge(42,133).
+edge(133,42).
+edge(43,79).
+edge(79,43).
+edge(43,96).
+edge(96,43).
+edge(43,126).
+edge(126,43).
+edge(43,137).
+edge(137,43).
+edge(43,139).
+edge(139,43).
+edge(43,142).
+edge(142,43).
+edge(43,145).
+edge(145,43).
+edge(44,49).
+edge(49,44).
+edge(44,50).
+edge(50,44).
+edge(44,63).
+edge(63,44).
+edge(44,98).
+edge(98,44).
+edge(44,117).
+edge(117,44).
+edge(44,129).
+edge(129,44).
+edge(45,64).
+edge(64,45).
+edge(45,86).
+edge(86,45).
+edge(45,103).
+edge(103,45).
+edge(45,121).
+edge(121,45).
+edge(45,124).
+edge(124,45).
+edge(45,128).
+edge(128,45).
+edge(45,129).
+edge(129,45).
+edge(45,134).
+edge(134,45).
+edge(46,48).
+edge(48,46).
+edge(46,61).
+edge(61,46).
+edge(46,65).
+edge(65,46).
+edge(46,67).
+edge(67,46).
+edge(46,70).
+edge(70,46).
+edge(46,73).
+edge(73,46).
+edge(46,79).
+edge(79,46).
+edge(46,88).
+edge(88,46).
+edge(46,108).
+edge(108,46).
+edge(46,118).
+edge(118,46).
+edge(46,127).
+edge(127,46).
+edge(46,128).
+edge(128,46).
+edge(46,130).
+edge(130,46).
+edge(46,139).
+edge(139,46).
+edge(47,54).
+edge(54,47).
+edge(47,60).
+edge(60,47).
+edge(47,105).
+edge(105,47).
+edge(47,116).
+edge(116,47).
+edge(47,124).
+edge(124,47).
+edge(47,135).
+edge(135,47).
+edge(47,143).
+edge(143,47).
+edge(48,49).
+edge(49,48).
+edge(48,59).
+edge(59,48).
+edge(48,78).
+edge(78,48).
+edge(48,86).
+edge(86,48).
+edge(48,101).
+edge(101,48).
+edge(48,113).
+edge(113,48).
+edge(48,114).
+edge(114,48).
+edge(48,129).
+edge(129,48).
+edge(48,143).
+edge(143,48).
+edge(48,144).
+edge(144,48).
+edge(49,79).
+edge(79,49).
+edge(49,81).
+edge(81,49).
+edge(49,94).
+edge(94,49).
+edge(49,112).
+edge(112,49).
+edge(49,114).
+edge(114,49).
+edge(49,124).
+edge(124,49).
+edge(49,125).
+edge(125,49).
+edge(49,132).
+edge(132,49).
+edge(50,51).
+edge(51,50).
+edge(50,58).
+edge(58,50).
+edge(50,60).
+edge(60,50).
+edge(50,63).
+edge(63,50).
+edge(50,64).
+edge(64,50).
+edge(50,66).
+edge(66,50).
+edge(50,79).
+edge(79,50).
+edge(50,83).
+edge(83,50).
+edge(50,92).
+edge(92,50).
+edge(50,97).
+edge(97,50).
+edge(50,110).
+edge(110,50).
+edge(50,127).
+edge(127,50).
+edge(50,130).
+edge(130,50).
+edge(51,57).
+edge(57,51).
+edge(51,65).
+edge(65,51).
+edge(51,66).
+edge(66,51).
+edge(51,85).
+edge(85,51).
+edge(51,125).
+edge(125,51).
+edge(52,81).
+edge(81,52).
+edge(52,101).
+edge(101,52).
+edge(52,106).
+edge(106,52).
+edge(52,108).
+edge(108,52).
+edge(52,115).
+edge(115,52).
+edge(52,122).
+edge(122,52).
+edge(52,125).
+edge(125,52).
+edge(52,129).
+edge(129,52).
+edge(52,143).
+edge(143,52).
+edge(53,68).
+edge(68,53).
+edge(53,72).
+edge(72,53).
+edge(53,85).
+edge(85,53).
+edge(53,95).
+edge(95,53).
+edge(53,107).
+edge(107,53).
+edge(53,130).
+edge(130,53).
+edge(53,138).
+edge(138,53).
+edge(53,145).
+edge(145,53).
+edge(54,75).
+edge(75,54).
+edge(54,80).
+edge(80,54).
+edge(54,84).
+edge(84,54).
+edge(54,93).
+edge(93,54).
+edge(54,95).
+edge(95,54).
+edge(54,99).
+edge(99,54).
+edge(54,113).
+edge(113,54).
+edge(54,119).
+edge(119,54).
+edge(54,128).
+edge(128,54).
+edge(55,60).
+edge(60,55).
+edge(55,65).
+edge(65,55).
+edge(55,69).
+edge(69,55).
+edge(55,79).
+edge(79,55).
+edge(55,83).
+edge(83,55).
+edge(55,85).
+edge(85,55).
+edge(55,106).
+edge(106,55).
+edge(55,111).
+edge(111,55).
+edge(55,119).
+edge(119,55).
+edge(55,120).
+edge(120,55).
+edge(55,129).
+edge(129,55).
+edge(56,58).
+edge(58,56).
+edge(56,61).
+edge(61,56).
+edge(56,86).
+edge(86,56).
+edge(56,116).
+edge(116,56).
+edge(56,120).
+edge(120,56).
+edge(56,125).
+edge(125,56).
+edge(56,139).
+edge(139,56).
+edge(57,64).
+edge(64,57).
+edge(57,65).
+edge(65,57).
+edge(57,72).
+edge(72,57).
+edge(57,74).
+edge(74,57).
+edge(57,84).
+edge(84,57).
+edge(57,88).
+edge(88,57).
+edge(57,115).
+edge(115,57).
+edge(57,120).
+edge(120,57).
+edge(57,123).
+edge(123,57).
+edge(58,80).
+edge(80,58).
+edge(58,97).
+edge(97,58).
+edge(58,103).
+edge(103,58).
+edge(58,115).
+edge(115,58).
+edge(58,132).
+edge(132,58).
+edge(59,65).
+edge(65,59).
+edge(59,70).
+edge(70,59).
+edge(59,79).
+edge(79,59).
+edge(59,104).
+edge(104,59).
+edge(59,144).
+edge(144,59).
+edge(60,62).
+edge(62,60).
+edge(60,74).
+edge(74,60).
+edge(60,83).
+edge(83,60).
+edge(60,84).
+edge(84,60).
+edge(60,91).
+edge(91,60).
+edge(60,95).
+edge(95,60).
+edge(60,101).
+edge(101,60).
+edge(60,111).
+edge(111,60).
+edge(60,122).
+edge(122,60).
+edge(60,133).
+edge(133,60).
+edge(61,65).
+edge(65,61).
+edge(61,68).
+edge(68,61).
+edge(61,74).
+edge(74,61).
+edge(61,76).
+edge(76,61).
+edge(61,79).
+edge(79,61).
+edge(61,91).
+edge(91,61).
+edge(61,92).
+edge(92,61).
+edge(61,102).
+edge(102,61).
+edge(61,119).
+edge(119,61).
+edge(61,135).
+edge(135,61).
+edge(61,145).
+edge(145,61).
+edge(62,67).
+edge(67,62).
+edge(62,83).
+edge(83,62).
+edge(62,116).
+edge(116,62).
+edge(62,131).
+edge(131,62).
+edge(62,134).
+edge(134,62).
+edge(62,137).
+edge(137,62).
+edge(62,142).
+edge(142,62).
+edge(63,74).
+edge(74,63).
+edge(63,87).
+edge(87,63).
+edge(63,97).
+edge(97,63).
+edge(63,101).
+edge(101,63).
+edge(63,104).
+edge(104,63).
+edge(63,111).
+edge(111,63).
+edge(63,112).
+edge(112,63).
+edge(63,120).
+edge(120,63).
+edge(63,129).
+edge(129,63).
+edge(64,69).
+edge(69,64).
+edge(64,80).
+edge(80,64).
+edge(64,96).
+edge(96,64).
+edge(64,122).
+edge(122,64).
+edge(64,135).
+edge(135,64).
+edge(64,139).
+edge(139,64).
+edge(65,68).
+edge(68,65).
+edge(65,78).
+edge(78,65).
+edge(65,82).
+edge(82,65).
+edge(65,85).
+edge(85,65).
+edge(65,92).
+edge(92,65).
+edge(65,96).
+edge(96,65).
+edge(65,110).
+edge(110,65).
+edge(65,116).
+edge(116,65).
+edge(65,120).
+edge(120,65).
+edge(65,128).
+edge(128,65).
+edge(65,129).
+edge(129,65).
+edge(65,130).
+edge(130,65).
+edge(65,134).
+edge(134,65).
+edge(65,142).
+edge(142,65).
+edge(66,77).
+edge(77,66).
+edge(66,78).
+edge(78,66).
+edge(66,105).
+edge(105,66).
+edge(67,82).
+edge(82,67).
+edge(67,117).
+edge(117,67).
+edge(67,128).
+edge(128,67).
+edge(67,130).
+edge(130,67).
+edge(67,136).
+edge(136,67).
+edge(68,73).
+edge(73,68).
+edge(68,78).
+edge(78,68).
+edge(68,86).
+edge(86,68).
+edge(68,97).
+edge(97,68).
+edge(68,102).
+edge(102,68).
+edge(68,113).
+edge(113,68).
+edge(68,114).
+edge(114,68).
+edge(68,120).
+edge(120,68).
+edge(68,127).
+edge(127,68).
+edge(68,136).
+edge(136,68).
+edge(68,140).
+edge(140,68).
+edge(69,72).
+edge(72,69).
+edge(69,125).
+edge(125,69).
+edge(69,126).
+edge(126,69).
+edge(69,128).
+edge(128,69).
+edge(69,144).
+edge(144,69).
+edge(70,72).
+edge(72,70).
+edge(70,80).
+edge(80,70).
+edge(70,81).
+edge(81,70).
+edge(70,85).
+edge(85,70).
+edge(70,94).
+edge(94,70).
+edge(70,110).
+edge(110,70).
+edge(70,115).
+edge(115,70).
+edge(70,116).
+edge(116,70).
+edge(70,118).
+edge(118,70).
+edge(70,121).
+edge(121,70).
+edge(71,74).
+edge(74,71).
+edge(71,81).
+edge(81,71).
+edge(71,86).
+edge(86,71).
+edge(71,99).
+edge(99,71).
+edge(71,107).
+edge(107,71).
+edge(71,110).
+edge(110,71).
+edge(71,116).
+edge(116,71).
+edge(71,130).
+edge(130,71).
+edge(71,139).
+edge(139,71).
+edge(72,73).
+edge(73,72).
+edge(72,76).
+edge(76,72).
+edge(72,97).
+edge(97,72).
+edge(72,117).
+edge(117,72).
+edge(72,120).
+edge(120,72).
+edge(72,124).
+edge(124,72).
+edge(72,127).
+edge(127,72).
+edge(72,130).
+edge(130,72).
+edge(72,132).
+edge(132,72).
+edge(73,77).
+edge(77,73).
+edge(73,86).
+edge(86,73).
+edge(73,106).
+edge(106,73).
+edge(73,115).
+edge(115,73).
+edge(73,119).
+edge(119,73).
+edge(73,122).
+edge(122,73).
+edge(73,123).
+edge(123,73).
+edge(74,75).
+edge(75,74).
+edge(74,77).
+edge(77,74).
+edge(74,83).
+edge(83,74).
+edge(74,100).
+edge(100,74).
+edge(74,109).
+edge(109,74).
+edge(74,122).
+edge(122,74).
+edge(74,123).
+edge(123,74).
+edge(75,81).
+edge(81,75).
+edge(75,113).
+edge(113,75).
+edge(75,139).
+edge(139,75).
+edge(75,144).
+edge(144,75).
+edge(76,77).
+edge(77,76).
+edge(76,79).
+edge(79,76).
+edge(76,86).
+edge(86,76).
+edge(76,113).
+edge(113,76).
+edge(77,88).
+edge(88,77).
+edge(77,90).
+edge(90,77).
+edge(77,103).
+edge(103,77).
+edge(77,104).
+edge(104,77).
+edge(77,112).
+edge(112,77).
+edge(77,121).
+edge(121,77).
+edge(77,125).
+edge(125,77).
+edge(77,126).
+edge(126,77).
+edge(77,128).
+edge(128,77).
+edge(78,91).
+edge(91,78).
+edge(78,93).
+edge(93,78).
+edge(78,98).
+edge(98,78).
+edge(78,105).
+edge(105,78).
+edge(78,110).
+edge(110,78).
+edge(78,118).
+edge(118,78).
+edge(78,123).
+edge(123,78).
+edge(78,137).
+edge(137,78).
+edge(78,142).
+edge(142,78).
+edge(78,144).
+edge(144,78).
+edge(79,95).
+edge(95,79).
+edge(79,111).
+edge(111,79).
+edge(79,134).
+edge(134,79).
+edge(79,139).
+edge(139,79).
+edge(80,86).
+edge(86,80).
+edge(80,95).
+edge(95,80).
+edge(80,99).
+edge(99,80).
+edge(80,118).
+edge(118,80).
+edge(80,145).
+edge(145,80).
+edge(81,83).
+edge(83,81).
+edge(81,102).
+edge(102,81).
+edge(81,104).
+edge(104,81).
+edge(81,137).
+edge(137,81).
+edge(81,139).
+edge(139,81).
+edge(81,144).
+edge(144,81).
+edge(82,94).
+edge(94,82).
+edge(82,101).
+edge(101,82).
+edge(82,110).
+edge(110,82).
+edge(82,119).
+edge(119,82).
+edge(82,139).
+edge(139,82).
+edge(82,143).
+edge(143,82).
+edge(83,105).
+edge(105,83).
+edge(83,125).
+edge(125,83).
+edge(84,100).
+edge(100,84).
+edge(84,101).
+edge(101,84).
+edge(84,118).
+edge(118,84).
+edge(84,144).
+edge(144,84).
+edge(85,91).
+edge(91,85).
+edge(85,92).
+edge(92,85).
+edge(85,108).
+edge(108,85).
+edge(85,127).
+edge(127,85).
+edge(86,88).
+edge(88,86).
+edge(86,91).
+edge(91,86).
+edge(86,106).
+edge(106,86).
+edge(86,109).
+edge(109,86).
+edge(86,122).
+edge(122,86).
+edge(86,130).
+edge(130,86).
+edge(86,134).
+edge(134,86).
+edge(86,137).
+edge(137,86).
+edge(86,141).
+edge(141,86).
+edge(87,95).
+edge(95,87).
+edge(87,100).
+edge(100,87).
+edge(87,104).
+edge(104,87).
+edge(87,108).
+edge(108,87).
+edge(87,118).
+edge(118,87).
+edge(87,125).
+edge(125,87).
+edge(87,144).
+edge(144,87).
+edge(88,94).
+edge(94,88).
+edge(88,112).
+edge(112,88).
+edge(88,117).
+edge(117,88).
+edge(88,118).
+edge(118,88).
+edge(88,122).
+edge(122,88).
+edge(88,126).
+edge(126,88).
+edge(89,93).
+edge(93,89).
+edge(89,94).
+edge(94,89).
+edge(89,97).
+edge(97,89).
+edge(89,100).
+edge(100,89).
+edge(89,101).
+edge(101,89).
+edge(89,102).
+edge(102,89).
+edge(89,120).
+edge(120,89).
+edge(89,142).
+edge(142,89).
+edge(90,96).
+edge(96,90).
+edge(90,97).
+edge(97,90).
+edge(90,142).
+edge(142,90).
+edge(90,143).
+edge(143,90).
+edge(90,144).
+edge(144,90).
+edge(91,104).
+edge(104,91).
+edge(91,107).
+edge(107,91).
+edge(91,121).
+edge(121,91).
+edge(91,135).
+edge(135,91).
+edge(91,138).
+edge(138,91).
+edge(91,139).
+edge(139,91).
+edge(92,96).
+edge(96,92).
+edge(92,102).
+edge(102,92).
+edge(92,105).
+edge(105,92).
+edge(92,108).
+edge(108,92).
+edge(92,115).
+edge(115,92).
+edge(92,121).
+edge(121,92).
+edge(92,130).
+edge(130,92).
+edge(92,138).
+edge(138,92).
+edge(93,115).
+edge(115,93).
+edge(93,121).
+edge(121,93).
+edge(93,130).
+edge(130,93).
+edge(93,134).
+edge(134,93).
+edge(93,137).
+edge(137,93).
+edge(94,99).
+edge(99,94).
+edge(94,105).
+edge(105,94).
+edge(94,132).
+edge(132,94).
+edge(95,98).
+edge(98,95).
+edge(95,129).
+edge(129,95).
+edge(95,140).
+edge(140,95).
+edge(96,99).
+edge(99,96).
+edge(96,106).
+edge(106,96).
+edge(96,112).
+edge(112,96).
+edge(96,126).
+edge(126,96).
+edge(96,130).
+edge(130,96).
+edge(96,132).
+edge(132,96).
+edge(96,133).
+edge(133,96).
+edge(96,135).
+edge(135,96).
+edge(96,141).
+edge(141,96).
+edge(96,142).
+edge(142,96).
+edge(96,144).
+edge(144,96).
+edge(97,100).
+edge(100,97).
+edge(97,102).
+edge(102,97).
+edge(97,115).
+edge(115,97).
+edge(97,116).
+edge(116,97).
+edge(97,117).
+edge(117,97).
+edge(97,118).
+edge(118,97).
+edge(97,121).
+edge(121,97).
+edge(98,141).
+edge(141,98).
+edge(99,105).
+edge(105,99).
+edge(99,114).
+edge(114,99).
+edge(99,135).
+edge(135,99).
+edge(99,142).
+edge(142,99).
+edge(100,116).
+edge(116,100).
+edge(100,125).
+edge(125,100).
+edge(100,131).
+edge(131,100).
+edge(100,132).
+edge(132,100).
+edge(101,130).
+edge(130,101).
+edge(101,145).
+edge(145,101).
+edge(102,108).
+edge(108,102).
+edge(102,109).
+edge(109,102).
+edge(102,115).
+edge(115,102).
+edge(103,107).
+edge(107,103).
+edge(103,108).
+edge(108,103).
+edge(103,129).
+edge(129,103).
+edge(103,140).
+edge(140,103).
+edge(104,111).
+edge(111,104).
+edge(104,127).
+edge(127,104).
+edge(105,113).
+edge(113,105).
+edge(105,114).
+edge(114,105).
+edge(105,117).
+edge(117,105).
+edge(105,133).
+edge(133,105).
+edge(105,135).
+edge(135,105).
+edge(105,143).
+edge(143,105).
+edge(105,145).
+edge(145,105).
+edge(106,111).
+edge(111,106).
+edge(106,122).
+edge(122,106).
+edge(106,123).
+edge(123,106).
+edge(106,127).
+edge(127,106).
+edge(106,135).
+edge(135,106).
+edge(106,141).
+edge(141,106).
+edge(107,108).
+edge(108,107).
+edge(107,134).
+edge(134,107).
+edge(108,127).
+edge(127,108).
+edge(108,128).
+edge(128,108).
+edge(109,110).
+edge(110,109).
+edge(109,111).
+edge(111,109).
+edge(109,116).
+edge(116,109).
+edge(109,117).
+edge(117,109).
+edge(109,138).
+edge(138,109).
+edge(109,140).
+edge(140,109).
+edge(109,141).
+edge(141,109).
+edge(110,111).
+edge(111,110).
+edge(110,140).
+edge(140,110).
+edge(111,114).
+edge(114,111).
+edge(111,144).
+edge(144,111).
+edge(112,118).
+edge(118,112).
+edge(112,124).
+edge(124,112).
+edge(113,134).
+edge(134,113).
+edge(113,137).
+edge(137,113).
+edge(113,139).
+edge(139,113).
+edge(114,135).
+edge(135,114).
+edge(114,137).
+edge(137,114).
+edge(114,145).
+edge(145,114).
+edge(115,120).
+edge(120,115).
+edge(115,128).
+edge(128,115).
+edge(115,136).
+edge(136,115).
+edge(115,139).
+edge(139,115).
+edge(115,142).
+edge(142,115).
+edge(116,122).
+edge(122,116).
+edge(116,125).
+edge(125,116).
+edge(116,133).
+edge(133,116).
+edge(117,119).
+edge(119,117).
+edge(117,131).
+edge(131,117).
+edge(117,137).
+edge(137,117).
+edge(118,129).
+edge(129,118).
+edge(119,130).
+edge(130,119).
+edge(119,135).
+edge(135,119).
+edge(120,123).
+edge(123,120).
+edge(120,127).
+edge(127,120).
+edge(121,123).
+edge(123,121).
+edge(121,124).
+edge(124,121).
+edge(121,131).
+edge(131,121).
+edge(123,128).
+edge(128,123).
+edge(123,134).
+edge(134,123).
+edge(123,139).
+edge(139,123).
+edge(124,127).
+edge(127,124).
+edge(124,142).
+edge(142,124).
+edge(125,129).
+edge(129,125).
+edge(125,131).
+edge(131,125).
+edge(126,134).
+edge(134,126).
+edge(126,139).
+edge(139,126).
+edge(127,145).
+edge(145,127).
+edge(128,133).
+edge(133,128).
+edge(128,139).
+edge(139,128).
+edge(129,134).
+edge(134,129).
+edge(129,138).
+edge(138,129).
+edge(129,139).
+edge(139,129).
+edge(130,145).
+edge(145,130).
+edge(131,135).
+edge(135,131).
+edge(131,137).
+edge(137,131).
+edge(131,145).
+edge(145,131).
+edge(135,144).
+edge(144,135).
+edge(136,144).
+edge(144,136).
+edge(138,142).
+edge(142,138).
+edge(139,143).
+edge(143,139).
+edge(140,144).
+edge(144,140).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0050-graph_colouring-145-0.lp b/examples/clingo/expansion/GraphColouring/instances/0050-graph_colouring-145-0.lp
new file mode 100644
index 0000000..ef4867e
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0050-graph_colouring-145-0.lp
@@ -0,0 +1,2219 @@
+#const n=145.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+edge(1,8).
+edge(8,1).
+edge(1,15).
+edge(15,1).
+edge(1,27).
+edge(27,1).
+edge(1,39).
+edge(39,1).
+edge(1,52).
+edge(52,1).
+edge(1,64).
+edge(64,1).
+edge(1,81).
+edge(81,1).
+edge(1,86).
+edge(86,1).
+edge(1,89).
+edge(89,1).
+edge(1,118).
+edge(118,1).
+edge(1,119).
+edge(119,1).
+edge(1,127).
+edge(127,1).
+edge(1,134).
+edge(134,1).
+edge(2,20).
+edge(20,2).
+edge(2,21).
+edge(21,2).
+edge(2,40).
+edge(40,2).
+edge(2,89).
+edge(89,2).
+edge(2,90).
+edge(90,2).
+edge(2,100).
+edge(100,2).
+edge(2,102).
+edge(102,2).
+edge(2,107).
+edge(107,2).
+edge(2,111).
+edge(111,2).
+edge(2,116).
+edge(116,2).
+edge(2,128).
+edge(128,2).
+edge(2,132).
+edge(132,2).
+edge(3,10).
+edge(10,3).
+edge(3,19).
+edge(19,3).
+edge(3,29).
+edge(29,3).
+edge(3,34).
+edge(34,3).
+edge(3,35).
+edge(35,3).
+edge(3,44).
+edge(44,3).
+edge(3,45).
+edge(45,3).
+edge(3,64).
+edge(64,3).
+edge(3,88).
+edge(88,3).
+edge(3,89).
+edge(89,3).
+edge(3,92).
+edge(92,3).
+edge(3,99).
+edge(99,3).
+edge(3,103).
+edge(103,3).
+edge(3,111).
+edge(111,3).
+edge(3,112).
+edge(112,3).
+edge(3,122).
+edge(122,3).
+edge(3,127).
+edge(127,3).
+edge(3,129).
+edge(129,3).
+edge(3,133).
+edge(133,3).
+edge(3,139).
+edge(139,3).
+edge(3,143).
+edge(143,3).
+edge(4,7).
+edge(7,4).
+edge(4,23).
+edge(23,4).
+edge(4,27).
+edge(27,4).
+edge(4,32).
+edge(32,4).
+edge(4,50).
+edge(50,4).
+edge(4,55).
+edge(55,4).
+edge(4,66).
+edge(66,4).
+edge(4,79).
+edge(79,4).
+edge(4,82).
+edge(82,4).
+edge(4,96).
+edge(96,4).
+edge(4,118).
+edge(118,4).
+edge(4,123).
+edge(123,4).
+edge(4,129).
+edge(129,4).
+edge(5,18).
+edge(18,5).
+edge(5,28).
+edge(28,5).
+edge(5,61).
+edge(61,5).
+edge(5,68).
+edge(68,5).
+edge(5,70).
+edge(70,5).
+edge(5,73).
+edge(73,5).
+edge(5,81).
+edge(81,5).
+edge(5,94).
+edge(94,5).
+edge(5,95).
+edge(95,5).
+edge(5,106).
+edge(106,5).
+edge(5,110).
+edge(110,5).
+edge(5,117).
+edge(117,5).
+edge(5,128).
+edge(128,5).
+edge(5,136).
+edge(136,5).
+edge(5,143).
+edge(143,5).
+edge(6,17).
+edge(17,6).
+edge(6,23).
+edge(23,6).
+edge(6,29).
+edge(29,6).
+edge(6,36).
+edge(36,6).
+edge(6,39).
+edge(39,6).
+edge(6,64).
+edge(64,6).
+edge(6,72).
+edge(72,6).
+edge(6,79).
+edge(79,6).
+edge(6,93).
+edge(93,6).
+edge(6,99).
+edge(99,6).
+edge(6,101).
+edge(101,6).
+edge(6,109).
+edge(109,6).
+edge(6,114).
+edge(114,6).
+edge(7,9).
+edge(9,7).
+edge(7,31).
+edge(31,7).
+edge(7,37).
+edge(37,7).
+edge(7,49).
+edge(49,7).
+edge(7,50).
+edge(50,7).
+edge(7,58).
+edge(58,7).
+edge(7,62).
+edge(62,7).
+edge(7,71).
+edge(71,7).
+edge(7,73).
+edge(73,7).
+edge(7,90).
+edge(90,7).
+edge(7,98).
+edge(98,7).
+edge(7,115).
+edge(115,7).
+edge(7,133).
+edge(133,7).
+edge(8,24).
+edge(24,8).
+edge(8,45).
+edge(45,8).
+edge(8,68).
+edge(68,8).
+edge(8,75).
+edge(75,8).
+edge(8,77).
+edge(77,8).
+edge(8,80).
+edge(80,8).
+edge(8,84).
+edge(84,8).
+edge(8,93).
+edge(93,8).
+edge(8,114).
+edge(114,8).
+edge(8,125).
+edge(125,8).
+edge(8,131).
+edge(131,8).
+edge(9,13).
+edge(13,9).
+edge(9,22).
+edge(22,9).
+edge(9,41).
+edge(41,9).
+edge(9,51).
+edge(51,9).
+edge(9,61).
+edge(61,9).
+edge(9,65).
+edge(65,9).
+edge(9,79).
+edge(79,9).
+edge(9,89).
+edge(89,9).
+edge(9,90).
+edge(90,9).
+edge(9,97).
+edge(97,9).
+edge(9,100).
+edge(100,9).
+edge(9,115).
+edge(115,9).
+edge(9,118).
+edge(118,9).
+edge(9,120).
+edge(120,9).
+edge(9,122).
+edge(122,9).
+edge(9,130).
+edge(130,9).
+edge(9,132).
+edge(132,9).
+edge(9,133).
+edge(133,9).
+edge(10,19).
+edge(19,10).
+edge(10,27).
+edge(27,10).
+edge(10,33).
+edge(33,10).
+edge(10,42).
+edge(42,10).
+edge(10,77).
+edge(77,10).
+edge(10,78).
+edge(78,10).
+edge(10,83).
+edge(83,10).
+edge(10,91).
+edge(91,10).
+edge(10,125).
+edge(125,10).
+edge(10,136).
+edge(136,10).
+edge(10,139).
+edge(139,10).
+edge(10,140).
+edge(140,10).
+edge(11,26).
+edge(26,11).
+edge(11,33).
+edge(33,11).
+edge(11,40).
+edge(40,11).
+edge(11,78).
+edge(78,11).
+edge(11,89).
+edge(89,11).
+edge(11,106).
+edge(106,11).
+edge(11,111).
+edge(111,11).
+edge(11,143).
+edge(143,11).
+edge(12,15).
+edge(15,12).
+edge(12,16).
+edge(16,12).
+edge(12,18).
+edge(18,12).
+edge(12,19).
+edge(19,12).
+edge(12,34).
+edge(34,12).
+edge(12,39).
+edge(39,12).
+edge(12,43).
+edge(43,12).
+edge(12,51).
+edge(51,12).
+edge(12,60).
+edge(60,12).
+edge(12,81).
+edge(81,12).
+edge(12,83).
+edge(83,12).
+edge(12,108).
+edge(108,12).
+edge(12,122).
+edge(122,12).
+edge(12,123).
+edge(123,12).
+edge(12,129).
+edge(129,12).
+edge(13,28).
+edge(28,13).
+edge(13,34).
+edge(34,13).
+edge(13,54).
+edge(54,13).
+edge(13,57).
+edge(57,13).
+edge(13,69).
+edge(69,13).
+edge(13,70).
+edge(70,13).
+edge(13,80).
+edge(80,13).
+edge(13,89).
+edge(89,13).
+edge(13,91).
+edge(91,13).
+edge(13,94).
+edge(94,13).
+edge(13,95).
+edge(95,13).
+edge(13,119).
+edge(119,13).
+edge(13,138).
+edge(138,13).
+edge(14,15).
+edge(15,14).
+edge(14,46).
+edge(46,14).
+edge(14,58).
+edge(58,14).
+edge(14,60).
+edge(60,14).
+edge(14,61).
+edge(61,14).
+edge(14,62).
+edge(62,14).
+edge(14,72).
+edge(72,14).
+edge(14,83).
+edge(83,14).
+edge(14,88).
+edge(88,14).
+edge(14,89).
+edge(89,14).
+edge(14,100).
+edge(100,14).
+edge(14,102).
+edge(102,14).
+edge(14,119).
+edge(119,14).
+edge(14,131).
+edge(131,14).
+edge(14,133).
+edge(133,14).
+edge(15,33).
+edge(33,15).
+edge(15,40).
+edge(40,15).
+edge(15,44).
+edge(44,15).
+edge(15,71).
+edge(71,15).
+edge(15,109).
+edge(109,15).
+edge(15,140).
+edge(140,15).
+edge(16,21).
+edge(21,16).
+edge(16,37).
+edge(37,16).
+edge(16,41).
+edge(41,16).
+edge(16,49).
+edge(49,16).
+edge(16,67).
+edge(67,16).
+edge(16,80).
+edge(80,16).
+edge(16,90).
+edge(90,16).
+edge(16,91).
+edge(91,16).
+edge(16,98).
+edge(98,16).
+edge(16,130).
+edge(130,16).
+edge(17,25).
+edge(25,17).
+edge(17,38).
+edge(38,17).
+edge(17,49).
+edge(49,17).
+edge(17,64).
+edge(64,17).
+edge(17,85).
+edge(85,17).
+edge(17,98).
+edge(98,17).
+edge(17,124).
+edge(124,17).
+edge(17,126).
+edge(126,17).
+edge(17,131).
+edge(131,17).
+edge(17,142).
+edge(142,17).
+edge(17,145).
+edge(145,17).
+edge(18,20).
+edge(20,18).
+edge(18,25).
+edge(25,18).
+edge(18,26).
+edge(26,18).
+edge(18,32).
+edge(32,18).
+edge(18,35).
+edge(35,18).
+edge(18,56).
+edge(56,18).
+edge(18,79).
+edge(79,18).
+edge(18,87).
+edge(87,18).
+edge(18,104).
+edge(104,18).
+edge(18,112).
+edge(112,18).
+edge(18,116).
+edge(116,18).
+edge(18,123).
+edge(123,18).
+edge(18,128).
+edge(128,18).
+edge(18,132).
+edge(132,18).
+edge(19,24).
+edge(24,19).
+edge(19,27).
+edge(27,19).
+edge(19,29).
+edge(29,19).
+edge(19,39).
+edge(39,19).
+edge(19,50).
+edge(50,19).
+edge(19,61).
+edge(61,19).
+edge(19,77).
+edge(77,19).
+edge(19,103).
+edge(103,19).
+edge(19,112).
+edge(112,19).
+edge(19,143).
+edge(143,19).
+edge(20,27).
+edge(27,20).
+edge(20,35).
+edge(35,20).
+edge(20,50).
+edge(50,20).
+edge(20,60).
+edge(60,20).
+edge(20,78).
+edge(78,20).
+edge(20,80).
+edge(80,20).
+edge(20,81).
+edge(81,20).
+edge(20,103).
+edge(103,20).
+edge(20,107).
+edge(107,20).
+edge(20,112).
+edge(112,20).
+edge(20,117).
+edge(117,20).
+edge(21,22).
+edge(22,21).
+edge(21,47).
+edge(47,21).
+edge(21,49).
+edge(49,21).
+edge(21,63).
+edge(63,21).
+edge(21,75).
+edge(75,21).
+edge(21,84).
+edge(84,21).
+edge(21,90).
+edge(90,21).
+edge(21,91).
+edge(91,21).
+edge(21,98).
+edge(98,21).
+edge(21,136).
+edge(136,21).
+edge(21,137).
+edge(137,21).
+edge(22,25).
+edge(25,22).
+edge(22,44).
+edge(44,22).
+edge(22,46).
+edge(46,22).
+edge(22,47).
+edge(47,22).
+edge(22,65).
+edge(65,22).
+edge(22,73).
+edge(73,22).
+edge(22,75).
+edge(75,22).
+edge(22,94).
+edge(94,22).
+edge(22,102).
+edge(102,22).
+edge(22,108).
+edge(108,22).
+edge(22,114).
+edge(114,22).
+edge(22,119).
+edge(119,22).
+edge(22,142).
+edge(142,22).
+edge(22,145).
+edge(145,22).
+edge(23,32).
+edge(32,23).
+edge(23,48).
+edge(48,23).
+edge(23,53).
+edge(53,23).
+edge(23,60).
+edge(60,23).
+edge(23,94).
+edge(94,23).
+edge(23,96).
+edge(96,23).
+edge(23,97).
+edge(97,23).
+edge(23,99).
+edge(99,23).
+edge(23,102).
+edge(102,23).
+edge(23,107).
+edge(107,23).
+edge(23,117).
+edge(117,23).
+edge(23,123).
+edge(123,23).
+edge(23,130).
+edge(130,23).
+edge(23,134).
+edge(134,23).
+edge(23,136).
+edge(136,23).
+edge(24,46).
+edge(46,24).
+edge(24,49).
+edge(49,24).
+edge(24,67).
+edge(67,24).
+edge(24,72).
+edge(72,24).
+edge(24,80).
+edge(80,24).
+edge(24,99).
+edge(99,24).
+edge(24,100).
+edge(100,24).
+edge(24,119).
+edge(119,24).
+edge(24,139).
+edge(139,24).
+edge(24,144).
+edge(144,24).
+edge(24,145).
+edge(145,24).
+edge(25,60).
+edge(60,25).
+edge(25,69).
+edge(69,25).
+edge(25,78).
+edge(78,25).
+edge(25,86).
+edge(86,25).
+edge(25,92).
+edge(92,25).
+edge(25,106).
+edge(106,25).
+edge(25,121).
+edge(121,25).
+edge(25,124).
+edge(124,25).
+edge(25,125).
+edge(125,25).
+edge(25,145).
+edge(145,25).
+edge(26,37).
+edge(37,26).
+edge(26,46).
+edge(46,26).
+edge(26,50).
+edge(50,26).
+edge(26,55).
+edge(55,26).
+edge(26,74).
+edge(74,26).
+edge(26,84).
+edge(84,26).
+edge(26,86).
+edge(86,26).
+edge(26,93).
+edge(93,26).
+edge(26,96).
+edge(96,26).
+edge(26,99).
+edge(99,26).
+edge(26,111).
+edge(111,26).
+edge(26,133).
+edge(133,26).
+edge(26,136).
+edge(136,26).
+edge(26,138).
+edge(138,26).
+edge(27,29).
+edge(29,27).
+edge(27,30).
+edge(30,27).
+edge(27,32).
+edge(32,27).
+edge(27,53).
+edge(53,27).
+edge(27,70).
+edge(70,27).
+edge(27,73).
+edge(73,27).
+edge(27,80).
+edge(80,27).
+edge(27,88).
+edge(88,27).
+edge(27,104).
+edge(104,27).
+edge(27,107).
+edge(107,27).
+edge(27,113).
+edge(113,27).
+edge(27,118).
+edge(118,27).
+edge(27,127).
+edge(127,27).
+edge(27,129).
+edge(129,27).
+edge(27,133).
+edge(133,27).
+edge(27,144).
+edge(144,27).
+edge(28,44).
+edge(44,28).
+edge(28,52).
+edge(52,28).
+edge(28,54).
+edge(54,28).
+edge(28,71).
+edge(71,28).
+edge(28,84).
+edge(84,28).
+edge(28,88).
+edge(88,28).
+edge(28,97).
+edge(97,28).
+edge(28,98).
+edge(98,28).
+edge(28,136).
+edge(136,28).
+edge(28,138).
+edge(138,28).
+edge(29,64).
+edge(64,29).
+edge(29,65).
+edge(65,29).
+edge(29,79).
+edge(79,29).
+edge(29,82).
+edge(82,29).
+edge(29,86).
+edge(86,29).
+edge(29,87).
+edge(87,29).
+edge(29,95).
+edge(95,29).
+edge(29,108).
+edge(108,29).
+edge(29,119).
+edge(119,29).
+edge(29,123).
+edge(123,29).
+edge(29,131).
+edge(131,29).
+edge(29,144).
+edge(144,29).
+edge(30,49).
+edge(49,30).
+edge(30,65).
+edge(65,30).
+edge(30,68).
+edge(68,30).
+edge(30,123).
+edge(123,30).
+edge(30,126).
+edge(126,30).
+edge(30,136).
+edge(136,30).
+edge(31,35).
+edge(35,31).
+edge(31,36).
+edge(36,31).
+edge(31,50).
+edge(50,31).
+edge(31,60).
+edge(60,31).
+edge(31,61).
+edge(61,31).
+edge(31,65).
+edge(65,31).
+edge(31,74).
+edge(74,31).
+edge(31,75).
+edge(75,31).
+edge(31,76).
+edge(76,31).
+edge(31,119).
+edge(119,31).
+edge(31,129).
+edge(129,31).
+edge(32,38).
+edge(38,32).
+edge(32,40).
+edge(40,32).
+edge(32,53).
+edge(53,32).
+edge(32,123).
+edge(123,32).
+edge(32,129).
+edge(129,32).
+edge(32,134).
+edge(134,32).
+edge(32,137).
+edge(137,32).
+edge(32,139).
+edge(139,32).
+edge(32,143).
+edge(143,32).
+edge(32,144).
+edge(144,32).
+edge(32,145).
+edge(145,32).
+edge(33,45).
+edge(45,33).
+edge(33,57).
+edge(57,33).
+edge(33,71).
+edge(71,33).
+edge(33,87).
+edge(87,33).
+edge(33,95).
+edge(95,33).
+edge(33,96).
+edge(96,33).
+edge(33,105).
+edge(105,33).
+edge(33,109).
+edge(109,33).
+edge(33,115).
+edge(115,33).
+edge(33,116).
+edge(116,33).
+edge(33,120).
+edge(120,33).
+edge(33,133).
+edge(133,33).
+edge(33,141).
+edge(141,33).
+edge(34,35).
+edge(35,34).
+edge(34,46).
+edge(46,34).
+edge(34,82).
+edge(82,34).
+edge(34,84).
+edge(84,34).
+edge(34,88).
+edge(88,34).
+edge(34,100).
+edge(100,34).
+edge(34,113).
+edge(113,34).
+edge(35,41).
+edge(41,35).
+edge(35,48).
+edge(48,35).
+edge(35,50).
+edge(50,35).
+edge(35,61).
+edge(61,35).
+edge(35,62).
+edge(62,35).
+edge(35,88).
+edge(88,35).
+edge(35,97).
+edge(97,35).
+edge(35,116).
+edge(116,35).
+edge(35,124).
+edge(124,35).
+edge(35,133).
+edge(133,35).
+edge(35,135).
+edge(135,35).
+edge(35,140).
+edge(140,35).
+edge(36,45).
+edge(45,36).
+edge(36,51).
+edge(51,36).
+edge(36,55).
+edge(55,36).
+edge(36,59).
+edge(59,36).
+edge(36,68).
+edge(68,36).
+edge(36,75).
+edge(75,36).
+edge(36,79).
+edge(79,36).
+edge(36,87).
+edge(87,36).
+edge(36,108).
+edge(108,36).
+edge(36,110).
+edge(110,36).
+edge(36,127).
+edge(127,36).
+edge(36,129).
+edge(129,36).
+edge(36,133).
+edge(133,36).
+edge(36,138).
+edge(138,36).
+edge(36,144).
+edge(144,36).
+edge(37,42).
+edge(42,37).
+edge(37,43).
+edge(43,37).
+edge(37,49).
+edge(49,37).
+edge(37,59).
+edge(59,37).
+edge(37,67).
+edge(67,37).
+edge(37,69).
+edge(69,37).
+edge(37,82).
+edge(82,37).
+edge(37,88).
+edge(88,37).
+edge(37,137).
+edge(137,37).
+edge(37,141).
+edge(141,37).
+edge(38,48).
+edge(48,38).
+edge(38,53).
+edge(53,38).
+edge(38,59).
+edge(59,38).
+edge(38,69).
+edge(69,38).
+edge(38,75).
+edge(75,38).
+edge(38,83).
+edge(83,38).
+edge(38,92).
+edge(92,38).
+edge(38,93).
+edge(93,38).
+edge(38,98).
+edge(98,38).
+edge(38,105).
+edge(105,38).
+edge(38,128).
+edge(128,38).
+edge(38,132).
+edge(132,38).
+edge(39,42).
+edge(42,39).
+edge(39,56).
+edge(56,39).
+edge(39,83).
+edge(83,39).
+edge(39,87).
+edge(87,39).
+edge(39,90).
+edge(90,39).
+edge(39,97).
+edge(97,39).
+edge(39,115).
+edge(115,39).
+edge(39,131).
+edge(131,39).
+edge(39,138).
+edge(138,39).
+edge(40,45).
+edge(45,40).
+edge(40,63).
+edge(63,40).
+edge(40,72).
+edge(72,40).
+edge(40,87).
+edge(87,40).
+edge(40,118).
+edge(118,40).
+edge(40,121).
+edge(121,40).
+edge(40,123).
+edge(123,40).
+edge(40,131).
+edge(131,40).
+edge(40,140).
+edge(140,40).
+edge(40,142).
+edge(142,40).
+edge(41,47).
+edge(47,41).
+edge(41,48).
+edge(48,41).
+edge(41,55).
+edge(55,41).
+edge(41,62).
+edge(62,41).
+edge(41,95).
+edge(95,41).
+edge(41,100).
+edge(100,41).
+edge(41,104).
+edge(104,41).
+edge(41,105).
+edge(105,41).
+edge(41,126).
+edge(126,41).
+edge(41,133).
+edge(133,41).
+edge(42,54).
+edge(54,42).
+edge(42,57).
+edge(57,42).
+edge(42,58).
+edge(58,42).
+edge(42,72).
+edge(72,42).
+edge(42,77).
+edge(77,42).
+edge(42,101).
+edge(101,42).
+edge(42,106).
+edge(106,42).
+edge(42,113).
+edge(113,42).
+edge(42,129).
+edge(129,42).
+edge(42,134).
+edge(134,42).
+edge(43,46).
+edge(46,43).
+edge(43,49).
+edge(49,43).
+edge(43,50).
+edge(50,43).
+edge(43,58).
+edge(58,43).
+edge(43,71).
+edge(71,43).
+edge(43,74).
+edge(74,43).
+edge(43,77).
+edge(77,43).
+edge(43,78).
+edge(78,43).
+edge(43,85).
+edge(85,43).
+edge(43,93).
+edge(93,43).
+edge(43,98).
+edge(98,43).
+edge(43,99).
+edge(99,43).
+edge(43,113).
+edge(113,43).
+edge(43,123).
+edge(123,43).
+edge(43,130).
+edge(130,43).
+edge(43,139).
+edge(139,43).
+edge(44,52).
+edge(52,44).
+edge(44,62).
+edge(62,44).
+edge(44,80).
+edge(80,44).
+edge(44,85).
+edge(85,44).
+edge(44,91).
+edge(91,44).
+edge(44,94).
+edge(94,44).
+edge(44,98).
+edge(98,44).
+edge(44,118).
+edge(118,44).
+edge(44,125).
+edge(125,44).
+edge(44,126).
+edge(126,44).
+edge(44,128).
+edge(128,44).
+edge(44,135).
+edge(135,44).
+edge(44,139).
+edge(139,44).
+edge(45,57).
+edge(57,45).
+edge(45,67).
+edge(67,45).
+edge(45,70).
+edge(70,45).
+edge(45,100).
+edge(100,45).
+edge(45,103).
+edge(103,45).
+edge(45,107).
+edge(107,45).
+edge(45,116).
+edge(116,45).
+edge(45,131).
+edge(131,45).
+edge(46,49).
+edge(49,46).
+edge(46,50).
+edge(50,46).
+edge(46,60).
+edge(60,46).
+edge(46,66).
+edge(66,46).
+edge(46,73).
+edge(73,46).
+edge(46,91).
+edge(91,46).
+edge(46,96).
+edge(96,46).
+edge(46,103).
+edge(103,46).
+edge(46,105).
+edge(105,46).
+edge(46,113).
+edge(113,46).
+edge(46,126).
+edge(126,46).
+edge(46,133).
+edge(133,46).
+edge(46,135).
+edge(135,46).
+edge(46,145).
+edge(145,46).
+edge(47,61).
+edge(61,47).
+edge(47,64).
+edge(64,47).
+edge(47,71).
+edge(71,47).
+edge(47,72).
+edge(72,47).
+edge(47,75).
+edge(75,47).
+edge(47,136).
+edge(136,47).
+edge(48,50).
+edge(50,48).
+edge(48,52).
+edge(52,48).
+edge(48,57).
+edge(57,48).
+edge(48,114).
+edge(114,48).
+edge(48,115).
+edge(115,48).
+edge(48,118).
+edge(118,48).
+edge(48,121).
+edge(121,48).
+edge(48,130).
+edge(130,48).
+edge(48,131).
+edge(131,48).
+edge(49,50).
+edge(50,49).
+edge(49,55).
+edge(55,49).
+edge(49,68).
+edge(68,49).
+edge(49,73).
+edge(73,49).
+edge(49,78).
+edge(78,49).
+edge(49,85).
+edge(85,49).
+edge(49,90).
+edge(90,49).
+edge(49,96).
+edge(96,49).
+edge(49,97).
+edge(97,49).
+edge(49,100).
+edge(100,49).
+edge(49,111).
+edge(111,49).
+edge(49,129).
+edge(129,49).
+edge(49,133).
+edge(133,49).
+edge(49,142).
+edge(142,49).
+edge(50,79).
+edge(79,50).
+edge(50,94).
+edge(94,50).
+edge(50,108).
+edge(108,50).
+edge(50,110).
+edge(110,50).
+edge(50,114).
+edge(114,50).
+edge(50,122).
+edge(122,50).
+edge(50,135).
+edge(135,50).
+edge(51,70).
+edge(70,51).
+edge(51,107).
+edge(107,51).
+edge(51,108).
+edge(108,51).
+edge(51,109).
+edge(109,51).
+edge(51,114).
+edge(114,51).
+edge(51,129).
+edge(129,51).
+edge(51,141).
+edge(141,51).
+edge(52,61).
+edge(61,52).
+edge(52,65).
+edge(65,52).
+edge(52,66).
+edge(66,52).
+edge(52,76).
+edge(76,52).
+edge(52,81).
+edge(81,52).
+edge(52,89).
+edge(89,52).
+edge(52,105).
+edge(105,52).
+edge(52,106).
+edge(106,52).
+edge(52,110).
+edge(110,52).
+edge(53,56).
+edge(56,53).
+edge(53,65).
+edge(65,53).
+edge(53,75).
+edge(75,53).
+edge(53,76).
+edge(76,53).
+edge(53,81).
+edge(81,53).
+edge(53,113).
+edge(113,53).
+edge(53,122).
+edge(122,53).
+edge(53,140).
+edge(140,53).
+edge(53,143).
+edge(143,53).
+edge(54,77).
+edge(77,54).
+edge(54,95).
+edge(95,54).
+edge(54,98).
+edge(98,54).
+edge(54,115).
+edge(115,54).
+edge(54,122).
+edge(122,54).
+edge(54,128).
+edge(128,54).
+edge(54,129).
+edge(129,54).
+edge(54,132).
+edge(132,54).
+edge(54,143).
+edge(143,54).
+edge(55,68).
+edge(68,55).
+edge(55,97).
+edge(97,55).
+edge(55,102).
+edge(102,55).
+edge(55,110).
+edge(110,55).
+edge(55,113).
+edge(113,55).
+edge(55,119).
+edge(119,55).
+edge(56,66).
+edge(66,56).
+edge(56,75).
+edge(75,56).
+edge(56,94).
+edge(94,56).
+edge(56,105).
+edge(105,56).
+edge(56,108).
+edge(108,56).
+edge(56,111).
+edge(111,56).
+edge(57,71).
+edge(71,57).
+edge(57,76).
+edge(76,57).
+edge(57,78).
+edge(78,57).
+edge(57,87).
+edge(87,57).
+edge(57,97).
+edge(97,57).
+edge(57,102).
+edge(102,57).
+edge(57,110).
+edge(110,57).
+edge(57,132).
+edge(132,57).
+edge(57,141).
+edge(141,57).
+edge(58,83).
+edge(83,58).
+edge(58,104).
+edge(104,58).
+edge(58,116).
+edge(116,58).
+edge(58,141).
+edge(141,58).
+edge(59,66).
+edge(66,59).
+edge(59,97).
+edge(97,59).
+edge(59,126).
+edge(126,59).
+edge(59,139).
+edge(139,59).
+edge(60,64).
+edge(64,60).
+edge(60,79).
+edge(79,60).
+edge(60,84).
+edge(84,60).
+edge(60,90).
+edge(90,60).
+edge(60,96).
+edge(96,60).
+edge(60,100).
+edge(100,60).
+edge(60,109).
+edge(109,60).
+edge(60,112).
+edge(112,60).
+edge(60,114).
+edge(114,60).
+edge(60,119).
+edge(119,60).
+edge(60,134).
+edge(134,60).
+edge(61,63).
+edge(63,61).
+edge(61,87).
+edge(87,61).
+edge(61,102).
+edge(102,61).
+edge(61,112).
+edge(112,61).
+edge(61,115).
+edge(115,61).
+edge(61,120).
+edge(120,61).
+edge(62,77).
+edge(77,62).
+edge(62,83).
+edge(83,62).
+edge(62,91).
+edge(91,62).
+edge(62,97).
+edge(97,62).
+edge(62,99).
+edge(99,62).
+edge(62,108).
+edge(108,62).
+edge(62,119).
+edge(119,62).
+edge(62,122).
+edge(122,62).
+edge(62,132).
+edge(132,62).
+edge(63,70).
+edge(70,63).
+edge(63,85).
+edge(85,63).
+edge(63,93).
+edge(93,63).
+edge(63,104).
+edge(104,63).
+edge(63,109).
+edge(109,63).
+edge(63,110).
+edge(110,63).
+edge(63,111).
+edge(111,63).
+edge(63,115).
+edge(115,63).
+edge(63,118).
+edge(118,63).
+edge(63,120).
+edge(120,63).
+edge(63,133).
+edge(133,63).
+edge(64,70).
+edge(70,64).
+edge(64,86).
+edge(86,64).
+edge(64,88).
+edge(88,64).
+edge(64,89).
+edge(89,64).
+edge(64,96).
+edge(96,64).
+edge(64,108).
+edge(108,64).
+edge(64,110).
+edge(110,64).
+edge(64,114).
+edge(114,64).
+edge(64,118).
+edge(118,64).
+edge(64,132).
+edge(132,64).
+edge(64,133).
+edge(133,64).
+edge(64,135).
+edge(135,64).
+edge(64,138).
+edge(138,64).
+edge(64,141).
+edge(141,64).
+edge(65,69).
+edge(69,65).
+edge(65,91).
+edge(91,65).
+edge(65,92).
+edge(92,65).
+edge(65,101).
+edge(101,65).
+edge(65,109).
+edge(109,65).
+edge(65,121).
+edge(121,65).
+edge(65,122).
+edge(122,65).
+edge(65,133).
+edge(133,65).
+edge(65,143).
+edge(143,65).
+edge(66,76).
+edge(76,66).
+edge(66,77).
+edge(77,66).
+edge(66,82).
+edge(82,66).
+edge(66,91).
+edge(91,66).
+edge(66,105).
+edge(105,66).
+edge(66,109).
+edge(109,66).
+edge(66,130).
+edge(130,66).
+edge(66,139).
+edge(139,66).
+edge(66,141).
+edge(141,66).
+edge(67,71).
+edge(71,67).
+edge(67,80).
+edge(80,67).
+edge(67,88).
+edge(88,67).
+edge(67,121).
+edge(121,67).
+edge(67,129).
+edge(129,67).
+edge(67,130).
+edge(130,67).
+edge(67,131).
+edge(131,67).
+edge(67,135).
+edge(135,67).
+edge(67,144).
+edge(144,67).
+edge(68,70).
+edge(70,68).
+edge(68,96).
+edge(96,68).
+edge(68,114).
+edge(114,68).
+edge(68,125).
+edge(125,68).
+edge(68,126).
+edge(126,68).
+edge(68,144).
+edge(144,68).
+edge(69,83).
+edge(83,69).
+edge(69,88).
+edge(88,69).
+edge(69,103).
+edge(103,69).
+edge(69,104).
+edge(104,69).
+edge(69,112).
+edge(112,69).
+edge(69,119).
+edge(119,69).
+edge(69,135).
+edge(135,69).
+edge(69,144).
+edge(144,69).
+edge(70,90).
+edge(90,70).
+edge(70,101).
+edge(101,70).
+edge(70,104).
+edge(104,70).
+edge(70,105).
+edge(105,70).
+edge(70,135).
+edge(135,70).
+edge(71,90).
+edge(90,71).
+edge(71,93).
+edge(93,71).
+edge(71,101).
+edge(101,71).
+edge(71,102).
+edge(102,71).
+edge(71,109).
+edge(109,71).
+edge(71,112).
+edge(112,71).
+edge(71,114).
+edge(114,71).
+edge(71,119).
+edge(119,71).
+edge(71,122).
+edge(122,71).
+edge(71,129).
+edge(129,71).
+edge(71,135).
+edge(135,71).
+edge(72,76).
+edge(76,72).
+edge(72,99).
+edge(99,72).
+edge(72,105).
+edge(105,72).
+edge(72,126).
+edge(126,72).
+edge(72,134).
+edge(134,72).
+edge(72,139).
+edge(139,72).
+edge(72,140).
+edge(140,72).
+edge(72,144).
+edge(144,72).
+edge(73,76).
+edge(76,73).
+edge(73,99).
+edge(99,73).
+edge(73,105).
+edge(105,73).
+edge(73,106).
+edge(106,73).
+edge(73,115).
+edge(115,73).
+edge(73,121).
+edge(121,73).
+edge(73,122).
+edge(122,73).
+edge(73,137).
+edge(137,73).
+edge(73,145).
+edge(145,73).
+edge(74,83).
+edge(83,74).
+edge(74,107).
+edge(107,74).
+edge(74,109).
+edge(109,74).
+edge(74,113).
+edge(113,74).
+edge(74,119).
+edge(119,74).
+edge(75,97).
+edge(97,75).
+edge(75,101).
+edge(101,75).
+edge(75,103).
+edge(103,75).
+edge(75,126).
+edge(126,75).
+edge(75,130).
+edge(130,75).
+edge(76,88).
+edge(88,76).
+edge(76,102).
+edge(102,76).
+edge(76,118).
+edge(118,76).
+edge(76,119).
+edge(119,76).
+edge(76,126).
+edge(126,76).
+edge(76,131).
+edge(131,76).
+edge(76,142).
+edge(142,76).
+edge(76,144).
+edge(144,76).
+edge(77,81).
+edge(81,77).
+edge(77,90).
+edge(90,77).
+edge(77,93).
+edge(93,77).
+edge(77,94).
+edge(94,77).
+edge(77,106).
+edge(106,77).
+edge(77,107).
+edge(107,77).
+edge(77,110).
+edge(110,77).
+edge(77,115).
+edge(115,77).
+edge(77,136).
+edge(136,77).
+edge(77,137).
+edge(137,77).
+edge(77,143).
+edge(143,77).
+edge(78,80).
+edge(80,78).
+edge(78,86).
+edge(86,78).
+edge(78,88).
+edge(88,78).
+edge(78,94).
+edge(94,78).
+edge(78,96).
+edge(96,78).
+edge(78,120).
+edge(120,78).
+edge(78,127).
+edge(127,78).
+edge(78,130).
+edge(130,78).
+edge(78,134).
+edge(134,78).
+edge(78,143).
+edge(143,78).
+edge(79,83).
+edge(83,79).
+edge(79,98).
+edge(98,79).
+edge(79,120).
+edge(120,79).
+edge(79,136).
+edge(136,79).
+edge(79,141).
+edge(141,79).
+edge(79,143).
+edge(143,79).
+edge(80,89).
+edge(89,80).
+edge(80,93).
+edge(93,80).
+edge(80,98).
+edge(98,80).
+edge(80,137).
+edge(137,80).
+edge(80,139).
+edge(139,80).
+edge(80,142).
+edge(142,80).
+edge(81,95).
+edge(95,81).
+edge(81,97).
+edge(97,81).
+edge(81,98).
+edge(98,81).
+edge(81,102).
+edge(102,81).
+edge(81,106).
+edge(106,81).
+edge(81,117).
+edge(117,81).
+edge(81,124).
+edge(124,81).
+edge(82,91).
+edge(91,82).
+edge(82,92).
+edge(92,82).
+edge(82,100).
+edge(100,82).
+edge(82,108).
+edge(108,82).
+edge(82,109).
+edge(109,82).
+edge(82,112).
+edge(112,82).
+edge(82,145).
+edge(145,82).
+edge(83,93).
+edge(93,83).
+edge(83,97).
+edge(97,83).
+edge(83,108).
+edge(108,83).
+edge(83,125).
+edge(125,83).
+edge(83,145).
+edge(145,83).
+edge(84,89).
+edge(89,84).
+edge(84,100).
+edge(100,84).
+edge(84,115).
+edge(115,84).
+edge(84,116).
+edge(116,84).
+edge(84,117).
+edge(117,84).
+edge(84,137).
+edge(137,84).
+edge(84,142).
+edge(142,84).
+edge(85,87).
+edge(87,85).
+edge(85,105).
+edge(105,85).
+edge(85,113).
+edge(113,85).
+edge(85,121).
+edge(121,85).
+edge(85,129).
+edge(129,85).
+edge(86,104).
+edge(104,86).
+edge(86,117).
+edge(117,86).
+edge(86,118).
+edge(118,86).
+edge(86,120).
+edge(120,86).
+edge(86,126).
+edge(126,86).
+edge(86,136).
+edge(136,86).
+edge(86,141).
+edge(141,86).
+edge(87,100).
+edge(100,87).
+edge(87,103).
+edge(103,87).
+edge(87,112).
+edge(112,87).
+edge(87,118).
+edge(118,87).
+edge(87,126).
+edge(126,87).
+edge(87,137).
+edge(137,87).
+edge(88,92).
+edge(92,88).
+edge(88,98).
+edge(98,88).
+edge(88,100).
+edge(100,88).
+edge(88,106).
+edge(106,88).
+edge(88,114).
+edge(114,88).
+edge(88,122).
+edge(122,88).
+edge(88,133).
+edge(133,88).
+edge(89,103).
+edge(103,89).
+edge(89,127).
+edge(127,89).
+edge(89,139).
+edge(139,89).
+edge(89,143).
+edge(143,89).
+edge(89,145).
+edge(145,89).
+edge(90,101).
+edge(101,90).
+edge(90,106).
+edge(106,90).
+edge(90,112).
+edge(112,90).
+edge(90,127).
+edge(127,90).
+edge(90,132).
+edge(132,90).
+edge(90,145).
+edge(145,90).
+edge(91,92).
+edge(92,91).
+edge(91,109).
+edge(109,91).
+edge(91,116).
+edge(116,91).
+edge(91,119).
+edge(119,91).
+edge(91,130).
+edge(130,91).
+edge(91,134).
+edge(134,91).
+edge(91,137).
+edge(137,91).
+edge(92,93).
+edge(93,92).
+edge(92,95).
+edge(95,92).
+edge(92,97).
+edge(97,92).
+edge(92,114).
+edge(114,92).
+edge(92,116).
+edge(116,92).
+edge(92,123).
+edge(123,92).
+edge(92,130).
+edge(130,92).
+edge(92,137).
+edge(137,92).
+edge(93,101).
+edge(101,93).
+edge(93,122).
+edge(122,93).
+edge(94,100).
+edge(100,94).
+edge(94,101).
+edge(101,94).
+edge(94,107).
+edge(107,94).
+edge(94,108).
+edge(108,94).
+edge(94,111).
+edge(111,94).
+edge(94,115).
+edge(115,94).
+edge(94,126).
+edge(126,94).
+edge(95,97).
+edge(97,95).
+edge(95,107).
+edge(107,95).
+edge(95,120).
+edge(120,95).
+edge(95,127).
+edge(127,95).
+edge(95,129).
+edge(129,95).
+edge(95,140).
+edge(140,95).
+edge(96,99).
+edge(99,96).
+edge(96,105).
+edge(105,96).
+edge(96,106).
+edge(106,96).
+edge(97,120).
+edge(120,97).
+edge(97,133).
+edge(133,97).
+edge(97,136).
+edge(136,97).
+edge(98,142).
+edge(142,98).
+edge(99,101).
+edge(101,99).
+edge(99,102).
+edge(102,99).
+edge(99,112).
+edge(112,99).
+edge(99,126).
+edge(126,99).
+edge(99,141).
+edge(141,99).
+edge(100,103).
+edge(103,100).
+edge(101,110).
+edge(110,101).
+edge(101,112).
+edge(112,101).
+edge(101,114).
+edge(114,101).
+edge(101,126).
+edge(126,101).
+edge(101,144).
+edge(144,101).
+edge(102,117).
+edge(117,102).
+edge(102,124).
+edge(124,102).
+edge(102,135).
+edge(135,102).
+edge(102,138).
+edge(138,102).
+edge(102,143).
+edge(143,102).
+edge(103,137).
+edge(137,103).
+edge(104,111).
+edge(111,104).
+edge(104,114).
+edge(114,104).
+edge(104,118).
+edge(118,104).
+edge(104,122).
+edge(122,104).
+edge(104,126).
+edge(126,104).
+edge(105,113).
+edge(113,105).
+edge(105,119).
+edge(119,105).
+edge(105,131).
+edge(131,105).
+edge(106,113).
+edge(113,106).
+edge(106,115).
+edge(115,106).
+edge(106,118).
+edge(118,106).
+edge(106,135).
+edge(135,106).
+edge(106,136).
+edge(136,106).
+edge(107,110).
+edge(110,107).
+edge(107,116).
+edge(116,107).
+edge(107,117).
+edge(117,107).
+edge(107,125).
+edge(125,107).
+edge(107,126).
+edge(126,107).
+edge(107,137).
+edge(137,107).
+edge(108,119).
+edge(119,108).
+edge(108,124).
+edge(124,108).
+edge(108,126).
+edge(126,108).
+edge(108,130).
+edge(130,108).
+edge(108,135).
+edge(135,108).
+edge(108,137).
+edge(137,108).
+edge(109,111).
+edge(111,109).
+edge(109,119).
+edge(119,109).
+edge(109,122).
+edge(122,109).
+edge(109,128).
+edge(128,109).
+edge(110,121).
+edge(121,110).
+edge(110,131).
+edge(131,110).
+edge(110,134).
+edge(134,110).
+edge(110,140).
+edge(140,110).
+edge(111,117).
+edge(117,111).
+edge(111,133).
+edge(133,111).
+edge(111,139).
+edge(139,111).
+edge(111,141).
+edge(141,111).
+edge(112,119).
+edge(119,112).
+edge(112,137).
+edge(137,112).
+edge(112,139).
+edge(139,112).
+edge(112,144).
+edge(144,112).
+edge(113,114).
+edge(114,113).
+edge(113,139).
+edge(139,113).
+edge(113,144).
+edge(144,113).
+edge(115,119).
+edge(119,115).
+edge(115,132).
+edge(132,115).
+edge(115,135).
+edge(135,115).
+edge(117,131).
+edge(131,117).
+edge(117,133).
+edge(133,117).
+edge(117,134).
+edge(134,117).
+edge(117,138).
+edge(138,117).
+edge(118,121).
+edge(121,118).
+edge(118,131).
+edge(131,118).
+edge(118,137).
+edge(137,118).
+edge(118,139).
+edge(139,118).
+edge(119,125).
+edge(125,119).
+edge(119,126).
+edge(126,119).
+edge(119,127).
+edge(127,119).
+edge(119,128).
+edge(128,119).
+edge(119,137).
+edge(137,119).
+edge(120,121).
+edge(121,120).
+edge(120,131).
+edge(131,120).
+edge(120,140).
+edge(140,120).
+edge(120,145).
+edge(145,120).
+edge(122,124).
+edge(124,122).
+edge(122,132).
+edge(132,122).
+edge(123,126).
+edge(126,123).
+edge(123,133).
+edge(133,123).
+edge(123,135).
+edge(135,123).
+edge(125,142).
+edge(142,125).
+edge(125,143).
+edge(143,125).
+edge(126,127).
+edge(127,126).
+edge(126,136).
+edge(136,126).
+edge(126,139).
+edge(139,126).
+edge(127,142).
+edge(142,127).
+edge(128,130).
+edge(130,128).
+edge(129,145).
+edge(145,129).
+edge(130,135).
+edge(135,130).
+edge(132,133).
+edge(133,132).
+edge(132,145).
+edge(145,132).
+edge(133,138).
+edge(138,133).
+edge(133,145).
+edge(145,133).
+edge(134,139).
+edge(139,134).
+edge(134,143).
+edge(143,134).
+edge(136,141).
+edge(141,136).
+edge(137,139).
+edge(139,137).
+edge(137,141).
+edge(141,137).
+edge(138,141).
+edge(141,138).
+edge(139,141).
+edge(141,139).
+edge(139,144).
+edge(144,139).
+edge(139,145).
+edge(145,139).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0056-graph_colouring-150-0.lp b/examples/clingo/expansion/GraphColouring/instances/0056-graph_colouring-150-0.lp
new file mode 100644
index 0000000..680b5f7
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0056-graph_colouring-150-0.lp
@@ -0,0 +1,2252 @@
+#const n=150.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+node(146).
+node(147).
+node(148).
+node(149).
+node(150).
+edge(1,5).
+edge(5,1).
+edge(1,21).
+edge(21,1).
+edge(1,22).
+edge(22,1).
+edge(1,44).
+edge(44,1).
+edge(1,48).
+edge(48,1).
+edge(1,74).
+edge(74,1).
+edge(1,77).
+edge(77,1).
+edge(1,84).
+edge(84,1).
+edge(1,94).
+edge(94,1).
+edge(1,117).
+edge(117,1).
+edge(1,126).
+edge(126,1).
+edge(1,127).
+edge(127,1).
+edge(1,144).
+edge(144,1).
+edge(1,149).
+edge(149,1).
+edge(2,16).
+edge(16,2).
+edge(2,22).
+edge(22,2).
+edge(2,24).
+edge(24,2).
+edge(2,36).
+edge(36,2).
+edge(2,51).
+edge(51,2).
+edge(2,70).
+edge(70,2).
+edge(2,87).
+edge(87,2).
+edge(2,102).
+edge(102,2).
+edge(2,119).
+edge(119,2).
+edge(2,138).
+edge(138,2).
+edge(3,11).
+edge(11,3).
+edge(3,34).
+edge(34,3).
+edge(3,36).
+edge(36,3).
+edge(3,38).
+edge(38,3).
+edge(3,52).
+edge(52,3).
+edge(3,69).
+edge(69,3).
+edge(3,72).
+edge(72,3).
+edge(3,73).
+edge(73,3).
+edge(3,82).
+edge(82,3).
+edge(3,83).
+edge(83,3).
+edge(3,96).
+edge(96,3).
+edge(3,110).
+edge(110,3).
+edge(3,116).
+edge(116,3).
+edge(3,124).
+edge(124,3).
+edge(3,125).
+edge(125,3).
+edge(3,139).
+edge(139,3).
+edge(3,142).
+edge(142,3).
+edge(3,144).
+edge(144,3).
+edge(3,146).
+edge(146,3).
+edge(3,149).
+edge(149,3).
+edge(4,13).
+edge(13,4).
+edge(4,18).
+edge(18,4).
+edge(4,19).
+edge(19,4).
+edge(4,23).
+edge(23,4).
+edge(4,30).
+edge(30,4).
+edge(4,39).
+edge(39,4).
+edge(4,53).
+edge(53,4).
+edge(4,55).
+edge(55,4).
+edge(4,60).
+edge(60,4).
+edge(4,112).
+edge(112,4).
+edge(4,122).
+edge(122,4).
+edge(4,123).
+edge(123,4).
+edge(4,140).
+edge(140,4).
+edge(5,9).
+edge(9,5).
+edge(5,28).
+edge(28,5).
+edge(5,33).
+edge(33,5).
+edge(5,42).
+edge(42,5).
+edge(5,60).
+edge(60,5).
+edge(5,62).
+edge(62,5).
+edge(5,71).
+edge(71,5).
+edge(5,85).
+edge(85,5).
+edge(5,104).
+edge(104,5).
+edge(5,114).
+edge(114,5).
+edge(5,140).
+edge(140,5).
+edge(5,144).
+edge(144,5).
+edge(5,145).
+edge(145,5).
+edge(6,17).
+edge(17,6).
+edge(6,40).
+edge(40,6).
+edge(6,55).
+edge(55,6).
+edge(6,64).
+edge(64,6).
+edge(6,73).
+edge(73,6).
+edge(6,75).
+edge(75,6).
+edge(6,76).
+edge(76,6).
+edge(6,78).
+edge(78,6).
+edge(6,96).
+edge(96,6).
+edge(6,100).
+edge(100,6).
+edge(6,137).
+edge(137,6).
+edge(6,145).
+edge(145,6).
+edge(7,8).
+edge(8,7).
+edge(7,10).
+edge(10,7).
+edge(7,11).
+edge(11,7).
+edge(7,15).
+edge(15,7).
+edge(7,25).
+edge(25,7).
+edge(7,75).
+edge(75,7).
+edge(7,102).
+edge(102,7).
+edge(7,105).
+edge(105,7).
+edge(7,107).
+edge(107,7).
+edge(7,112).
+edge(112,7).
+edge(7,136).
+edge(136,7).
+edge(7,144).
+edge(144,7).
+edge(8,29).
+edge(29,8).
+edge(8,37).
+edge(37,8).
+edge(8,62).
+edge(62,8).
+edge(8,71).
+edge(71,8).
+edge(8,77).
+edge(77,8).
+edge(8,91).
+edge(91,8).
+edge(8,105).
+edge(105,8).
+edge(8,106).
+edge(106,8).
+edge(8,111).
+edge(111,8).
+edge(8,119).
+edge(119,8).
+edge(8,138).
+edge(138,8).
+edge(8,142).
+edge(142,8).
+edge(9,30).
+edge(30,9).
+edge(9,35).
+edge(35,9).
+edge(9,40).
+edge(40,9).
+edge(9,50).
+edge(50,9).
+edge(9,64).
+edge(64,9).
+edge(9,113).
+edge(113,9).
+edge(9,140).
+edge(140,9).
+edge(9,149).
+edge(149,9).
+edge(10,29).
+edge(29,10).
+edge(10,32).
+edge(32,10).
+edge(10,40).
+edge(40,10).
+edge(10,43).
+edge(43,10).
+edge(10,62).
+edge(62,10).
+edge(10,73).
+edge(73,10).
+edge(10,83).
+edge(83,10).
+edge(10,97).
+edge(97,10).
+edge(10,104).
+edge(104,10).
+edge(10,106).
+edge(106,10).
+edge(10,108).
+edge(108,10).
+edge(10,113).
+edge(113,10).
+edge(10,117).
+edge(117,10).
+edge(10,118).
+edge(118,10).
+edge(10,125).
+edge(125,10).
+edge(10,129).
+edge(129,10).
+edge(10,136).
+edge(136,10).
+edge(11,15).
+edge(15,11).
+edge(11,16).
+edge(16,11).
+edge(11,22).
+edge(22,11).
+edge(11,23).
+edge(23,11).
+edge(11,27).
+edge(27,11).
+edge(11,59).
+edge(59,11).
+edge(11,68).
+edge(68,11).
+edge(11,74).
+edge(74,11).
+edge(11,75).
+edge(75,11).
+edge(11,88).
+edge(88,11).
+edge(11,97).
+edge(97,11).
+edge(11,102).
+edge(102,11).
+edge(11,113).
+edge(113,11).
+edge(11,117).
+edge(117,11).
+edge(11,119).
+edge(119,11).
+edge(11,135).
+edge(135,11).
+edge(11,137).
+edge(137,11).
+edge(11,139).
+edge(139,11).
+edge(12,28).
+edge(28,12).
+edge(12,41).
+edge(41,12).
+edge(12,48).
+edge(48,12).
+edge(12,54).
+edge(54,12).
+edge(12,62).
+edge(62,12).
+edge(12,70).
+edge(70,12).
+edge(12,84).
+edge(84,12).
+edge(12,85).
+edge(85,12).
+edge(12,102).
+edge(102,12).
+edge(12,131).
+edge(131,12).
+edge(12,138).
+edge(138,12).
+edge(13,63).
+edge(63,13).
+edge(13,68).
+edge(68,13).
+edge(13,82).
+edge(82,13).
+edge(13,86).
+edge(86,13).
+edge(13,88).
+edge(88,13).
+edge(13,90).
+edge(90,13).
+edge(13,92).
+edge(92,13).
+edge(13,93).
+edge(93,13).
+edge(13,108).
+edge(108,13).
+edge(13,112).
+edge(112,13).
+edge(13,114).
+edge(114,13).
+edge(13,126).
+edge(126,13).
+edge(13,127).
+edge(127,13).
+edge(13,140).
+edge(140,13).
+edge(14,19).
+edge(19,14).
+edge(14,20).
+edge(20,14).
+edge(14,25).
+edge(25,14).
+edge(14,42).
+edge(42,14).
+edge(14,62).
+edge(62,14).
+edge(14,81).
+edge(81,14).
+edge(14,88).
+edge(88,14).
+edge(14,94).
+edge(94,14).
+edge(14,109).
+edge(109,14).
+edge(14,149).
+edge(149,14).
+edge(15,21).
+edge(21,15).
+edge(15,37).
+edge(37,15).
+edge(15,43).
+edge(43,15).
+edge(15,49).
+edge(49,15).
+edge(15,54).
+edge(54,15).
+edge(15,55).
+edge(55,15).
+edge(15,66).
+edge(66,15).
+edge(15,69).
+edge(69,15).
+edge(15,74).
+edge(74,15).
+edge(15,78).
+edge(78,15).
+edge(15,84).
+edge(84,15).
+edge(15,99).
+edge(99,15).
+edge(15,113).
+edge(113,15).
+edge(15,115).
+edge(115,15).
+edge(15,121).
+edge(121,15).
+edge(15,131).
+edge(131,15).
+edge(15,141).
+edge(141,15).
+edge(16,24).
+edge(24,16).
+edge(16,29).
+edge(29,16).
+edge(16,30).
+edge(30,16).
+edge(16,44).
+edge(44,16).
+edge(16,49).
+edge(49,16).
+edge(16,54).
+edge(54,16).
+edge(16,55).
+edge(55,16).
+edge(16,57).
+edge(57,16).
+edge(16,70).
+edge(70,16).
+edge(16,71).
+edge(71,16).
+edge(16,95).
+edge(95,16).
+edge(16,102).
+edge(102,16).
+edge(16,104).
+edge(104,16).
+edge(16,111).
+edge(111,16).
+edge(16,123).
+edge(123,16).
+edge(16,139).
+edge(139,16).
+edge(17,19).
+edge(19,17).
+edge(17,24).
+edge(24,17).
+edge(17,55).
+edge(55,17).
+edge(17,82).
+edge(82,17).
+edge(17,91).
+edge(91,17).
+edge(17,114).
+edge(114,17).
+edge(17,123).
+edge(123,17).
+edge(17,125).
+edge(125,17).
+edge(17,128).
+edge(128,17).
+edge(17,130).
+edge(130,17).
+edge(17,136).
+edge(136,17).
+edge(18,33).
+edge(33,18).
+edge(18,41).
+edge(41,18).
+edge(18,58).
+edge(58,18).
+edge(18,64).
+edge(64,18).
+edge(18,69).
+edge(69,18).
+edge(18,71).
+edge(71,18).
+edge(18,82).
+edge(82,18).
+edge(18,93).
+edge(93,18).
+edge(18,104).
+edge(104,18).
+edge(18,116).
+edge(116,18).
+edge(18,118).
+edge(118,18).
+edge(18,120).
+edge(120,18).
+edge(18,134).
+edge(134,18).
+edge(19,21).
+edge(21,19).
+edge(19,32).
+edge(32,19).
+edge(19,43).
+edge(43,19).
+edge(19,62).
+edge(62,19).
+edge(19,63).
+edge(63,19).
+edge(19,147).
+edge(147,19).
+edge(20,23).
+edge(23,20).
+edge(20,31).
+edge(31,20).
+edge(20,60).
+edge(60,20).
+edge(20,75).
+edge(75,20).
+edge(20,83).
+edge(83,20).
+edge(20,104).
+edge(104,20).
+edge(20,105).
+edge(105,20).
+edge(20,108).
+edge(108,20).
+edge(20,110).
+edge(110,20).
+edge(20,116).
+edge(116,20).
+edge(20,139).
+edge(139,20).
+edge(20,144).
+edge(144,20).
+edge(21,27).
+edge(27,21).
+edge(21,33).
+edge(33,21).
+edge(21,38).
+edge(38,21).
+edge(21,48).
+edge(48,21).
+edge(21,76).
+edge(76,21).
+edge(21,88).
+edge(88,21).
+edge(21,98).
+edge(98,21).
+edge(21,121).
+edge(121,21).
+edge(21,132).
+edge(132,21).
+edge(21,141).
+edge(141,21).
+edge(21,144).
+edge(144,21).
+edge(21,147).
+edge(147,21).
+edge(22,45).
+edge(45,22).
+edge(22,56).
+edge(56,22).
+edge(22,61).
+edge(61,22).
+edge(22,69).
+edge(69,22).
+edge(22,70).
+edge(70,22).
+edge(22,75).
+edge(75,22).
+edge(22,82).
+edge(82,22).
+edge(22,94).
+edge(94,22).
+edge(22,108).
+edge(108,22).
+edge(22,130).
+edge(130,22).
+edge(22,138).
+edge(138,22).
+edge(22,140).
+edge(140,22).
+edge(22,147).
+edge(147,22).
+edge(23,25).
+edge(25,23).
+edge(23,30).
+edge(30,23).
+edge(23,45).
+edge(45,23).
+edge(23,57).
+edge(57,23).
+edge(23,62).
+edge(62,23).
+edge(23,65).
+edge(65,23).
+edge(23,67).
+edge(67,23).
+edge(23,114).
+edge(114,23).
+edge(23,115).
+edge(115,23).
+edge(23,124).
+edge(124,23).
+edge(23,141).
+edge(141,23).
+edge(23,146).
+edge(146,23).
+edge(24,29).
+edge(29,24).
+edge(24,55).
+edge(55,24).
+edge(24,70).
+edge(70,24).
+edge(24,113).
+edge(113,24).
+edge(24,123).
+edge(123,24).
+edge(24,130).
+edge(130,24).
+edge(24,136).
+edge(136,24).
+edge(25,30).
+edge(30,25).
+edge(25,40).
+edge(40,25).
+edge(25,44).
+edge(44,25).
+edge(25,50).
+edge(50,25).
+edge(25,90).
+edge(90,25).
+edge(25,96).
+edge(96,25).
+edge(25,98).
+edge(98,25).
+edge(25,102).
+edge(102,25).
+edge(25,114).
+edge(114,25).
+edge(25,139).
+edge(139,25).
+edge(26,28).
+edge(28,26).
+edge(26,32).
+edge(32,26).
+edge(26,41).
+edge(41,26).
+edge(26,57).
+edge(57,26).
+edge(26,62).
+edge(62,26).
+edge(26,66).
+edge(66,26).
+edge(26,103).
+edge(103,26).
+edge(26,121).
+edge(121,26).
+edge(26,129).
+edge(129,26).
+edge(26,137).
+edge(137,26).
+edge(26,140).
+edge(140,26).
+edge(26,149).
+edge(149,26).
+edge(27,33).
+edge(33,27).
+edge(27,41).
+edge(41,27).
+edge(27,52).
+edge(52,27).
+edge(27,78).
+edge(78,27).
+edge(27,82).
+edge(82,27).
+edge(27,85).
+edge(85,27).
+edge(27,112).
+edge(112,27).
+edge(27,129).
+edge(129,27).
+edge(28,35).
+edge(35,28).
+edge(28,54).
+edge(54,28).
+edge(28,62).
+edge(62,28).
+edge(28,63).
+edge(63,28).
+edge(28,86).
+edge(86,28).
+edge(28,94).
+edge(94,28).
+edge(28,131).
+edge(131,28).
+edge(28,138).
+edge(138,28).
+edge(29,31).
+edge(31,29).
+edge(29,43).
+edge(43,29).
+edge(29,52).
+edge(52,29).
+edge(29,56).
+edge(56,29).
+edge(29,64).
+edge(64,29).
+edge(29,77).
+edge(77,29).
+edge(29,81).
+edge(81,29).
+edge(29,129).
+edge(129,29).
+edge(29,137).
+edge(137,29).
+edge(30,38).
+edge(38,30).
+edge(30,39).
+edge(39,30).
+edge(30,51).
+edge(51,30).
+edge(30,69).
+edge(69,30).
+edge(30,72).
+edge(72,30).
+edge(30,77).
+edge(77,30).
+edge(30,82).
+edge(82,30).
+edge(30,115).
+edge(115,30).
+edge(30,134).
+edge(134,30).
+edge(31,35).
+edge(35,31).
+edge(31,41).
+edge(41,31).
+edge(31,44).
+edge(44,31).
+edge(31,49).
+edge(49,31).
+edge(31,56).
+edge(56,31).
+edge(31,86).
+edge(86,31).
+edge(31,92).
+edge(92,31).
+edge(31,93).
+edge(93,31).
+edge(31,94).
+edge(94,31).
+edge(31,100).
+edge(100,31).
+edge(31,119).
+edge(119,31).
+edge(31,121).
+edge(121,31).
+edge(31,126).
+edge(126,31).
+edge(31,137).
+edge(137,31).
+edge(31,142).
+edge(142,31).
+edge(32,40).
+edge(40,32).
+edge(32,44).
+edge(44,32).
+edge(32,51).
+edge(51,32).
+edge(32,59).
+edge(59,32).
+edge(32,67).
+edge(67,32).
+edge(32,71).
+edge(71,32).
+edge(32,72).
+edge(72,32).
+edge(32,76).
+edge(76,32).
+edge(32,81).
+edge(81,32).
+edge(32,89).
+edge(89,32).
+edge(32,111).
+edge(111,32).
+edge(32,119).
+edge(119,32).
+edge(32,139).
+edge(139,32).
+edge(33,42).
+edge(42,33).
+edge(33,49).
+edge(49,33).
+edge(33,57).
+edge(57,33).
+edge(33,99).
+edge(99,33).
+edge(33,102).
+edge(102,33).
+edge(33,115).
+edge(115,33).
+edge(33,118).
+edge(118,33).
+edge(33,125).
+edge(125,33).
+edge(33,126).
+edge(126,33).
+edge(33,131).
+edge(131,33).
+edge(33,135).
+edge(135,33).
+edge(33,137).
+edge(137,33).
+edge(33,146).
+edge(146,33).
+edge(34,35).
+edge(35,34).
+edge(34,52).
+edge(52,34).
+edge(34,62).
+edge(62,34).
+edge(34,70).
+edge(70,34).
+edge(34,82).
+edge(82,34).
+edge(34,99).
+edge(99,34).
+edge(34,106).
+edge(106,34).
+edge(34,112).
+edge(112,34).
+edge(34,114).
+edge(114,34).
+edge(34,127).
+edge(127,34).
+edge(34,142).
+edge(142,34).
+edge(34,146).
+edge(146,34).
+edge(35,56).
+edge(56,35).
+edge(35,63).
+edge(63,35).
+edge(35,87).
+edge(87,35).
+edge(35,95).
+edge(95,35).
+edge(35,102).
+edge(102,35).
+edge(35,105).
+edge(105,35).
+edge(35,117).
+edge(117,35).
+edge(35,127).
+edge(127,35).
+edge(35,148).
+edge(148,35).
+edge(36,55).
+edge(55,36).
+edge(36,57).
+edge(57,36).
+edge(36,66).
+edge(66,36).
+edge(36,85).
+edge(85,36).
+edge(36,92).
+edge(92,36).
+edge(36,95).
+edge(95,36).
+edge(36,129).
+edge(129,36).
+edge(37,41).
+edge(41,37).
+edge(37,54).
+edge(54,37).
+edge(37,66).
+edge(66,37).
+edge(37,72).
+edge(72,37).
+edge(37,87).
+edge(87,37).
+edge(37,90).
+edge(90,37).
+edge(37,96).
+edge(96,37).
+edge(37,98).
+edge(98,37).
+edge(37,108).
+edge(108,37).
+edge(37,135).
+edge(135,37).
+edge(38,49).
+edge(49,38).
+edge(38,59).
+edge(59,38).
+edge(38,67).
+edge(67,38).
+edge(38,85).
+edge(85,38).
+edge(38,103).
+edge(103,38).
+edge(38,114).
+edge(114,38).
+edge(38,148).
+edge(148,38).
+edge(39,54).
+edge(54,39).
+edge(39,69).
+edge(69,39).
+edge(39,89).
+edge(89,39).
+edge(39,90).
+edge(90,39).
+edge(39,96).
+edge(96,39).
+edge(39,98).
+edge(98,39).
+edge(39,101).
+edge(101,39).
+edge(39,107).
+edge(107,39).
+edge(39,109).
+edge(109,39).
+edge(39,149).
+edge(149,39).
+edge(40,41).
+edge(41,40).
+edge(40,43).
+edge(43,40).
+edge(40,69).
+edge(69,40).
+edge(40,99).
+edge(99,40).
+edge(40,126).
+edge(126,40).
+edge(40,129).
+edge(129,40).
+edge(40,132).
+edge(132,40).
+edge(41,54).
+edge(54,41).
+edge(41,59).
+edge(59,41).
+edge(41,63).
+edge(63,41).
+edge(41,81).
+edge(81,41).
+edge(41,87).
+edge(87,41).
+edge(41,104).
+edge(104,41).
+edge(41,106).
+edge(106,41).
+edge(41,110).
+edge(110,41).
+edge(41,131).
+edge(131,41).
+edge(41,134).
+edge(134,41).
+edge(41,137).
+edge(137,41).
+edge(41,142).
+edge(142,41).
+edge(41,144).
+edge(144,41).
+edge(42,45).
+edge(45,42).
+edge(42,54).
+edge(54,42).
+edge(42,58).
+edge(58,42).
+edge(42,64).
+edge(64,42).
+edge(42,101).
+edge(101,42).
+edge(42,121).
+edge(121,42).
+edge(42,127).
+edge(127,42).
+edge(42,130).
+edge(130,42).
+edge(42,132).
+edge(132,42).
+edge(43,52).
+edge(52,43).
+edge(43,64).
+edge(64,43).
+edge(43,66).
+edge(66,43).
+edge(43,86).
+edge(86,43).
+edge(43,93).
+edge(93,43).
+edge(43,97).
+edge(97,43).
+edge(43,115).
+edge(115,43).
+edge(43,117).
+edge(117,43).
+edge(43,132).
+edge(132,43).
+edge(43,139).
+edge(139,43).
+edge(44,55).
+edge(55,44).
+edge(44,72).
+edge(72,44).
+edge(44,76).
+edge(76,44).
+edge(44,90).
+edge(90,44).
+edge(44,97).
+edge(97,44).
+edge(44,105).
+edge(105,44).
+edge(44,111).
+edge(111,44).
+edge(44,126).
+edge(126,44).
+edge(45,53).
+edge(53,45).
+edge(45,63).
+edge(63,45).
+edge(45,70).
+edge(70,45).
+edge(45,75).
+edge(75,45).
+edge(45,78).
+edge(78,45).
+edge(45,94).
+edge(94,45).
+edge(45,110).
+edge(110,45).
+edge(45,113).
+edge(113,45).
+edge(45,120).
+edge(120,45).
+edge(45,125).
+edge(125,45).
+edge(45,131).
+edge(131,45).
+edge(46,111).
+edge(111,46).
+edge(46,120).
+edge(120,46).
+edge(46,130).
+edge(130,46).
+edge(46,131).
+edge(131,46).
+edge(46,145).
+edge(145,46).
+edge(47,95).
+edge(95,47).
+edge(47,97).
+edge(97,47).
+edge(47,98).
+edge(98,47).
+edge(47,103).
+edge(103,47).
+edge(47,105).
+edge(105,47).
+edge(47,113).
+edge(113,47).
+edge(47,114).
+edge(114,47).
+edge(47,132).
+edge(132,47).
+edge(47,134).
+edge(134,47).
+edge(47,136).
+edge(136,47).
+edge(47,140).
+edge(140,47).
+edge(48,51).
+edge(51,48).
+edge(48,56).
+edge(56,48).
+edge(48,70).
+edge(70,48).
+edge(48,79).
+edge(79,48).
+edge(48,88).
+edge(88,48).
+edge(48,108).
+edge(108,48).
+edge(48,130).
+edge(130,48).
+edge(48,136).
+edge(136,48).
+edge(49,57).
+edge(57,49).
+edge(49,58).
+edge(58,49).
+edge(49,71).
+edge(71,49).
+edge(49,78).
+edge(78,49).
+edge(49,85).
+edge(85,49).
+edge(49,90).
+edge(90,49).
+edge(49,91).
+edge(91,49).
+edge(49,101).
+edge(101,49).
+edge(49,103).
+edge(103,49).
+edge(49,107).
+edge(107,49).
+edge(49,113).
+edge(113,49).
+edge(49,120).
+edge(120,49).
+edge(49,130).
+edge(130,49).
+edge(49,149).
+edge(149,49).
+edge(50,54).
+edge(54,50).
+edge(50,55).
+edge(55,50).
+edge(50,58).
+edge(58,50).
+edge(50,60).
+edge(60,50).
+edge(50,85).
+edge(85,50).
+edge(50,95).
+edge(95,50).
+edge(50,109).
+edge(109,50).
+edge(50,112).
+edge(112,50).
+edge(50,121).
+edge(121,50).
+edge(50,126).
+edge(126,50).
+edge(50,130).
+edge(130,50).
+edge(51,62).
+edge(62,51).
+edge(51,70).
+edge(70,51).
+edge(51,74).
+edge(74,51).
+edge(51,80).
+edge(80,51).
+edge(51,89).
+edge(89,51).
+edge(51,96).
+edge(96,51).
+edge(51,99).
+edge(99,51).
+edge(51,106).
+edge(106,51).
+edge(51,109).
+edge(109,51).
+edge(51,118).
+edge(118,51).
+edge(51,122).
+edge(122,51).
+edge(51,129).
+edge(129,51).
+edge(51,133).
+edge(133,51).
+edge(51,136).
+edge(136,51).
+edge(51,145).
+edge(145,51).
+edge(52,81).
+edge(81,52).
+edge(52,95).
+edge(95,52).
+edge(52,99).
+edge(99,52).
+edge(52,106).
+edge(106,52).
+edge(52,113).
+edge(113,52).
+edge(52,121).
+edge(121,52).
+edge(52,126).
+edge(126,52).
+edge(52,127).
+edge(127,52).
+edge(53,65).
+edge(65,53).
+edge(53,86).
+edge(86,53).
+edge(53,129).
+edge(129,53).
+edge(53,131).
+edge(131,53).
+edge(53,136).
+edge(136,53).
+edge(53,148).
+edge(148,53).
+edge(54,93).
+edge(93,54).
+edge(54,94).
+edge(94,54).
+edge(54,114).
+edge(114,54).
+edge(54,117).
+edge(117,54).
+edge(54,144).
+edge(144,54).
+edge(55,64).
+edge(64,55).
+edge(55,74).
+edge(74,55).
+edge(55,81).
+edge(81,55).
+edge(55,98).
+edge(98,55).
+edge(55,101).
+edge(101,55).
+edge(55,102).
+edge(102,55).
+edge(55,128).
+edge(128,55).
+edge(55,140).
+edge(140,55).
+edge(55,143).
+edge(143,55).
+edge(55,149).
+edge(149,55).
+edge(56,62).
+edge(62,56).
+edge(56,64).
+edge(64,56).
+edge(56,65).
+edge(65,56).
+edge(56,78).
+edge(78,56).
+edge(56,135).
+edge(135,56).
+edge(56,139).
+edge(139,56).
+edge(56,141).
+edge(141,56).
+edge(57,68).
+edge(68,57).
+edge(57,69).
+edge(69,57).
+edge(57,72).
+edge(72,57).
+edge(57,78).
+edge(78,57).
+edge(57,83).
+edge(83,57).
+edge(57,100).
+edge(100,57).
+edge(57,101).
+edge(101,57).
+edge(57,103).
+edge(103,57).
+edge(57,112).
+edge(112,57).
+edge(57,116).
+edge(116,57).
+edge(57,126).
+edge(126,57).
+edge(57,127).
+edge(127,57).
+edge(57,135).
+edge(135,57).
+edge(58,68).
+edge(68,58).
+edge(58,73).
+edge(73,58).
+edge(58,75).
+edge(75,58).
+edge(58,80).
+edge(80,58).
+edge(58,84).
+edge(84,58).
+edge(58,92).
+edge(92,58).
+edge(58,93).
+edge(93,58).
+edge(58,104).
+edge(104,58).
+edge(58,123).
+edge(123,58).
+edge(59,75).
+edge(75,59).
+edge(59,82).
+edge(82,59).
+edge(59,100).
+edge(100,59).
+edge(59,106).
+edge(106,59).
+edge(59,118).
+edge(118,59).
+edge(59,143).
+edge(143,59).
+edge(60,62).
+edge(62,60).
+edge(60,70).
+edge(70,60).
+edge(60,87).
+edge(87,60).
+edge(60,110).
+edge(110,60).
+edge(60,121).
+edge(121,60).
+edge(60,122).
+edge(122,60).
+edge(60,128).
+edge(128,60).
+edge(60,129).
+edge(129,60).
+edge(61,79).
+edge(79,61).
+edge(61,111).
+edge(111,61).
+edge(61,112).
+edge(112,61).
+edge(61,122).
+edge(122,61).
+edge(61,124).
+edge(124,61).
+edge(61,126).
+edge(126,61).
+edge(61,131).
+edge(131,61).
+edge(61,149).
+edge(149,61).
+edge(62,64).
+edge(64,62).
+edge(62,66).
+edge(66,62).
+edge(62,69).
+edge(69,62).
+edge(62,75).
+edge(75,62).
+edge(62,83).
+edge(83,62).
+edge(62,85).
+edge(85,62).
+edge(62,90).
+edge(90,62).
+edge(62,98).
+edge(98,62).
+edge(62,130).
+edge(130,62).
+edge(62,135).
+edge(135,62).
+edge(62,139).
+edge(139,62).
+edge(62,142).
+edge(142,62).
+edge(63,66).
+edge(66,63).
+edge(63,71).
+edge(71,63).
+edge(63,90).
+edge(90,63).
+edge(63,103).
+edge(103,63).
+edge(63,118).
+edge(118,63).
+edge(63,127).
+edge(127,63).
+edge(63,137).
+edge(137,63).
+edge(63,150).
+edge(150,63).
+edge(64,86).
+edge(86,64).
+edge(64,88).
+edge(88,64).
+edge(64,89).
+edge(89,64).
+edge(64,93).
+edge(93,64).
+edge(64,111).
+edge(111,64).
+edge(64,125).
+edge(125,64).
+edge(64,128).
+edge(128,64).
+edge(64,138).
+edge(138,64).
+edge(64,142).
+edge(142,64).
+edge(65,75).
+edge(75,65).
+edge(65,104).
+edge(104,65).
+edge(65,105).
+edge(105,65).
+edge(65,137).
+edge(137,65).
+edge(65,139).
+edge(139,65).
+edge(65,147).
+edge(147,65).
+edge(65,149).
+edge(149,65).
+edge(66,74).
+edge(74,66).
+edge(66,107).
+edge(107,66).
+edge(66,115).
+edge(115,66).
+edge(66,116).
+edge(116,66).
+edge(66,130).
+edge(130,66).
+edge(66,139).
+edge(139,66).
+edge(66,145).
+edge(145,66).
+edge(67,78).
+edge(78,67).
+edge(67,83).
+edge(83,67).
+edge(67,86).
+edge(86,67).
+edge(67,98).
+edge(98,67).
+edge(67,108).
+edge(108,67).
+edge(67,111).
+edge(111,67).
+edge(67,141).
+edge(141,67).
+edge(68,83).
+edge(83,68).
+edge(68,90).
+edge(90,68).
+edge(68,110).
+edge(110,68).
+edge(68,115).
+edge(115,68).
+edge(68,116).
+edge(116,68).
+edge(68,125).
+edge(125,68).
+edge(68,150).
+edge(150,68).
+edge(69,75).
+edge(75,69).
+edge(69,77).
+edge(77,69).
+edge(69,87).
+edge(87,69).
+edge(69,90).
+edge(90,69).
+edge(69,101).
+edge(101,69).
+edge(69,102).
+edge(102,69).
+edge(69,113).
+edge(113,69).
+edge(69,116).
+edge(116,69).
+edge(69,137).
+edge(137,69).
+edge(69,144).
+edge(144,69).
+edge(69,150).
+edge(150,69).
+edge(70,94).
+edge(94,70).
+edge(70,106).
+edge(106,70).
+edge(70,107).
+edge(107,70).
+edge(70,117).
+edge(117,70).
+edge(70,123).
+edge(123,70).
+edge(70,134).
+edge(134,70).
+edge(70,141).
+edge(141,70).
+edge(70,142).
+edge(142,70).
+edge(70,144).
+edge(144,70).
+edge(70,148).
+edge(148,70).
+edge(71,72).
+edge(72,71).
+edge(71,73).
+edge(73,71).
+edge(71,80).
+edge(80,71).
+edge(71,92).
+edge(92,71).
+edge(71,96).
+edge(96,71).
+edge(71,101).
+edge(101,71).
+edge(71,120).
+edge(120,71).
+edge(71,124).
+edge(124,71).
+edge(71,127).
+edge(127,71).
+edge(71,137).
+edge(137,71).
+edge(71,139).
+edge(139,71).
+edge(71,142).
+edge(142,71).
+edge(71,144).
+edge(144,71).
+edge(71,146).
+edge(146,71).
+edge(72,83).
+edge(83,72).
+edge(72,85).
+edge(85,72).
+edge(72,128).
+edge(128,72).
+edge(72,132).
+edge(132,72).
+edge(72,137).
+edge(137,72).
+edge(73,84).
+edge(84,73).
+edge(73,86).
+edge(86,73).
+edge(73,103).
+edge(103,73).
+edge(73,133).
+edge(133,73).
+edge(73,144).
+edge(144,73).
+edge(73,145).
+edge(145,73).
+edge(73,146).
+edge(146,73).
+edge(73,150).
+edge(150,73).
+edge(74,90).
+edge(90,74).
+edge(74,91).
+edge(91,74).
+edge(74,101).
+edge(101,74).
+edge(74,102).
+edge(102,74).
+edge(74,106).
+edge(106,74).
+edge(74,118).
+edge(118,74).
+edge(74,126).
+edge(126,74).
+edge(74,135).
+edge(135,74).
+edge(74,143).
+edge(143,74).
+edge(75,88).
+edge(88,75).
+edge(75,95).
+edge(95,75).
+edge(75,103).
+edge(103,75).
+edge(75,104).
+edge(104,75).
+edge(75,105).
+edge(105,75).
+edge(75,118).
+edge(118,75).
+edge(75,136).
+edge(136,75).
+edge(75,148).
+edge(148,75).
+edge(76,81).
+edge(81,76).
+edge(76,96).
+edge(96,76).
+edge(76,100).
+edge(100,76).
+edge(76,115).
+edge(115,76).
+edge(76,124).
+edge(124,76).
+edge(76,133).
+edge(133,76).
+edge(76,135).
+edge(135,76).
+edge(76,141).
+edge(141,76).
+edge(76,146).
+edge(146,76).
+edge(77,107).
+edge(107,77).
+edge(77,131).
+edge(131,77).
+edge(78,92).
+edge(92,78).
+edge(78,97).
+edge(97,78).
+edge(78,113).
+edge(113,78).
+edge(78,128).
+edge(128,78).
+edge(78,138).
+edge(138,78).
+edge(78,147).
+edge(147,78).
+edge(79,112).
+edge(112,79).
+edge(79,126).
+edge(126,79).
+edge(79,130).
+edge(130,79).
+edge(79,133).
+edge(133,79).
+edge(79,139).
+edge(139,79).
+edge(79,146).
+edge(146,79).
+edge(80,84).
+edge(84,80).
+edge(80,100).
+edge(100,80).
+edge(80,114).
+edge(114,80).
+edge(80,138).
+edge(138,80).
+edge(81,83).
+edge(83,81).
+edge(81,93).
+edge(93,81).
+edge(81,97).
+edge(97,81).
+edge(81,134).
+edge(134,81).
+edge(81,139).
+edge(139,81).
+edge(82,97).
+edge(97,82).
+edge(82,102).
+edge(102,82).
+edge(82,106).
+edge(106,82).
+edge(82,131).
+edge(131,82).
+edge(82,139).
+edge(139,82).
+edge(82,144).
+edge(144,82).
+edge(82,146).
+edge(146,82).
+edge(83,88).
+edge(88,83).
+edge(83,93).
+edge(93,83).
+edge(83,96).
+edge(96,83).
+edge(83,97).
+edge(97,83).
+edge(83,119).
+edge(119,83).
+edge(83,121).
+edge(121,83).
+edge(83,122).
+edge(122,83).
+edge(83,123).
+edge(123,83).
+edge(83,124).
+edge(124,83).
+edge(83,126).
+edge(126,83).
+edge(84,91).
+edge(91,84).
+edge(84,94).
+edge(94,84).
+edge(84,121).
+edge(121,84).
+edge(84,150).
+edge(150,84).
+edge(85,90).
+edge(90,85).
+edge(85,110).
+edge(110,85).
+edge(85,113).
+edge(113,85).
+edge(85,114).
+edge(114,85).
+edge(85,136).
+edge(136,85).
+edge(85,138).
+edge(138,85).
+edge(86,90).
+edge(90,86).
+edge(86,94).
+edge(94,86).
+edge(86,103).
+edge(103,86).
+edge(86,117).
+edge(117,86).
+edge(86,123).
+edge(123,86).
+edge(86,128).
+edge(128,86).
+edge(86,134).
+edge(134,86).
+edge(86,136).
+edge(136,86).
+edge(86,140).
+edge(140,86).
+edge(86,143).
+edge(143,86).
+edge(87,89).
+edge(89,87).
+edge(87,90).
+edge(90,87).
+edge(87,106).
+edge(106,87).
+edge(87,112).
+edge(112,87).
+edge(87,116).
+edge(116,87).
+edge(87,134).
+edge(134,87).
+edge(87,144).
+edge(144,87).
+edge(87,147).
+edge(147,87).
+edge(88,103).
+edge(103,88).
+edge(88,109).
+edge(109,88).
+edge(88,114).
+edge(114,88).
+edge(88,121).
+edge(121,88).
+edge(88,125).
+edge(125,88).
+edge(88,126).
+edge(126,88).
+edge(88,134).
+edge(134,88).
+edge(88,145).
+edge(145,88).
+edge(89,91).
+edge(91,89).
+edge(89,109).
+edge(109,89).
+edge(89,110).
+edge(110,89).
+edge(89,115).
+edge(115,89).
+edge(89,117).
+edge(117,89).
+edge(89,125).
+edge(125,89).
+edge(89,139).
+edge(139,89).
+edge(90,94).
+edge(94,90).
+edge(90,95).
+edge(95,90).
+edge(90,97).
+edge(97,90).
+edge(90,146).
+edge(146,90).
+edge(91,101).
+edge(101,91).
+edge(91,108).
+edge(108,91).
+edge(91,116).
+edge(116,91).
+edge(91,135).
+edge(135,91).
+edge(92,93).
+edge(93,92).
+edge(92,94).
+edge(94,92).
+edge(92,107).
+edge(107,92).
+edge(92,147).
+edge(147,92).
+edge(93,97).
+edge(97,93).
+edge(93,99).
+edge(99,93).
+edge(93,105).
+edge(105,93).
+edge(93,108).
+edge(108,93).
+edge(93,129).
+edge(129,93).
+edge(93,138).
+edge(138,93).
+edge(94,96).
+edge(96,94).
+edge(94,100).
+edge(100,94).
+edge(94,118).
+edge(118,94).
+edge(95,112).
+edge(112,95).
+edge(95,146).
+edge(146,95).
+edge(96,97).
+edge(97,96).
+edge(96,113).
+edge(113,96).
+edge(96,137).
+edge(137,96).
+edge(96,140).
+edge(140,96).
+edge(97,116).
+edge(116,97).
+edge(97,125).
+edge(125,97).
+edge(97,129).
+edge(129,97).
+edge(97,134).
+edge(134,97).
+edge(98,123).
+edge(123,98).
+edge(98,147).
+edge(147,98).
+edge(99,106).
+edge(106,99).
+edge(99,107).
+edge(107,99).
+edge(99,108).
+edge(108,99).
+edge(99,109).
+edge(109,99).
+edge(99,116).
+edge(116,99).
+edge(99,135).
+edge(135,99).
+edge(100,137).
+edge(137,100).
+edge(100,141).
+edge(141,100).
+edge(101,114).
+edge(114,101).
+edge(101,125).
+edge(125,101).
+edge(101,129).
+edge(129,101).
+edge(101,131).
+edge(131,101).
+edge(101,135).
+edge(135,101).
+edge(101,142).
+edge(142,101).
+edge(101,147).
+edge(147,101).
+edge(102,107).
+edge(107,102).
+edge(102,127).
+edge(127,102).
+edge(102,128).
+edge(128,102).
+edge(102,145).
+edge(145,102).
+edge(103,110).
+edge(110,103).
+edge(103,114).
+edge(114,103).
+edge(103,118).
+edge(118,103).
+edge(103,127).
+edge(127,103).
+edge(103,129).
+edge(129,103).
+edge(103,135).
+edge(135,103).
+edge(104,113).
+edge(113,104).
+edge(104,124).
+edge(124,104).
+edge(104,129).
+edge(129,104).
+edge(104,131).
+edge(131,104).
+edge(104,137).
+edge(137,104).
+edge(104,148).
+edge(148,104).
+edge(105,130).
+edge(130,105).
+edge(105,137).
+edge(137,105).
+edge(105,144).
+edge(144,105).
+edge(105,150).
+edge(150,105).
+edge(106,110).
+edge(110,106).
+edge(106,119).
+edge(119,106).
+edge(106,128).
+edge(128,106).
+edge(106,142).
+edge(142,106).
+edge(106,144).
+edge(144,106).
+edge(106,147).
+edge(147,106).
+edge(107,117).
+edge(117,107).
+edge(107,130).
+edge(130,107).
+edge(107,137).
+edge(137,107).
+edge(107,141).
+edge(141,107).
+edge(107,147).
+edge(147,107).
+edge(108,123).
+edge(123,108).
+edge(108,147).
+edge(147,108).
+edge(109,121).
+edge(121,109).
+edge(109,125).
+edge(125,109).
+edge(109,129).
+edge(129,109).
+edge(109,134).
+edge(134,109).
+edge(109,146).
+edge(146,109).
+edge(109,149).
+edge(149,109).
+edge(110,114).
+edge(114,110).
+edge(110,118).
+edge(118,110).
+edge(110,119).
+edge(119,110).
+edge(110,120).
+edge(120,110).
+edge(110,129).
+edge(129,110).
+edge(110,137).
+edge(137,110).
+edge(111,136).
+edge(136,111).
+edge(111,138).
+edge(138,111).
+edge(111,145).
+edge(145,111).
+edge(111,149).
+edge(149,111).
+edge(112,119).
+edge(119,112).
+edge(112,135).
+edge(135,112).
+edge(112,136).
+edge(136,112).
+edge(112,140).
+edge(140,112).
+edge(112,142).
+edge(142,112).
+edge(112,149).
+edge(149,112).
+edge(112,150).
+edge(150,112).
+edge(113,132).
+edge(132,113).
+edge(113,140).
+edge(140,113).
+edge(114,120).
+edge(120,114).
+edge(114,129).
+edge(129,114).
+edge(114,133).
+edge(133,114).
+edge(114,135).
+edge(135,114).
+edge(114,149).
+edge(149,114).
+edge(115,143).
+edge(143,115).
+edge(115,144).
+edge(144,115).
+edge(115,147).
+edge(147,115).
+edge(116,117).
+edge(117,116).
+edge(116,120).
+edge(120,116).
+edge(116,122).
+edge(122,116).
+edge(116,127).
+edge(127,116).
+edge(116,132).
+edge(132,116).
+edge(116,141).
+edge(141,116).
+edge(117,126).
+edge(126,117).
+edge(117,130).
+edge(130,117).
+edge(117,137).
+edge(137,117).
+edge(117,145).
+edge(145,117).
+edge(118,131).
+edge(131,118).
+edge(118,147).
+edge(147,118).
+edge(119,125).
+edge(125,119).
+edge(119,131).
+edge(131,119).
+edge(119,134).
+edge(134,119).
+edge(119,135).
+edge(135,119).
+edge(119,138).
+edge(138,119).
+edge(119,139).
+edge(139,119).
+edge(119,147).
+edge(147,119).
+edge(120,124).
+edge(124,120).
+edge(120,133).
+edge(133,120).
+edge(120,140).
+edge(140,120).
+edge(121,139).
+edge(139,121).
+edge(122,123).
+edge(123,122).
+edge(122,124).
+edge(124,122).
+edge(122,128).
+edge(128,122).
+edge(122,144).
+edge(144,122).
+edge(122,149).
+edge(149,122).
+edge(123,125).
+edge(125,123).
+edge(123,126).
+edge(126,123).
+edge(123,131).
+edge(131,123).
+edge(123,133).
+edge(133,123).
+edge(123,136).
+edge(136,123).
+edge(123,150).
+edge(150,123).
+edge(124,128).
+edge(128,124).
+edge(124,131).
+edge(131,124).
+edge(125,134).
+edge(134,125).
+edge(125,143).
+edge(143,125).
+edge(126,130).
+edge(130,126).
+edge(127,137).
+edge(137,127).
+edge(127,144).
+edge(144,127).
+edge(128,139).
+edge(139,128).
+edge(129,136).
+edge(136,129).
+edge(129,141).
+edge(141,129).
+edge(129,150).
+edge(150,129).
+edge(130,132).
+edge(132,130).
+edge(130,148).
+edge(148,130).
+edge(131,147).
+edge(147,131).
+edge(132,140).
+edge(140,132).
+edge(132,141).
+edge(141,132).
+edge(133,150).
+edge(150,133).
+edge(134,139).
+edge(139,134).
+edge(134,147).
+edge(147,134).
+edge(135,140).
+edge(140,135).
+edge(136,141).
+edge(141,136).
+edge(136,143).
+edge(143,136).
+edge(136,144).
+edge(144,136).
+edge(137,142).
+edge(142,137).
+edge(138,144).
+edge(144,138).
+edge(139,147).
+edge(147,139).
+edge(139,148).
+edge(148,139).
+edge(140,144).
+edge(144,140).
+edge(143,144).
+edge(144,143).
+edge(145,148).
+edge(148,145).
+edge(148,149).
+edge(149,148).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0059-graph_colouring-150-0.lp b/examples/clingo/expansion/GraphColouring/instances/0059-graph_colouring-150-0.lp
new file mode 100644
index 0000000..770c1b0
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0059-graph_colouring-150-0.lp
@@ -0,0 +1,2374 @@
+#const n=150.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+node(146).
+node(147).
+node(148).
+node(149).
+node(150).
+edge(1,13).
+edge(13,1).
+edge(1,15).
+edge(15,1).
+edge(1,16).
+edge(16,1).
+edge(1,23).
+edge(23,1).
+edge(1,59).
+edge(59,1).
+edge(1,66).
+edge(66,1).
+edge(1,77).
+edge(77,1).
+edge(1,78).
+edge(78,1).
+edge(1,82).
+edge(82,1).
+edge(1,91).
+edge(91,1).
+edge(1,107).
+edge(107,1).
+edge(1,113).
+edge(113,1).
+edge(1,115).
+edge(115,1).
+edge(1,124).
+edge(124,1).
+edge(1,140).
+edge(140,1).
+edge(1,144).
+edge(144,1).
+edge(1,145).
+edge(145,1).
+edge(2,5).
+edge(5,2).
+edge(2,9).
+edge(9,2).
+edge(2,45).
+edge(45,2).
+edge(2,46).
+edge(46,2).
+edge(2,70).
+edge(70,2).
+edge(2,84).
+edge(84,2).
+edge(2,86).
+edge(86,2).
+edge(2,96).
+edge(96,2).
+edge(2,112).
+edge(112,2).
+edge(2,113).
+edge(113,2).
+edge(2,118).
+edge(118,2).
+edge(2,137).
+edge(137,2).
+edge(2,150).
+edge(150,2).
+edge(3,7).
+edge(7,3).
+edge(3,11).
+edge(11,3).
+edge(3,25).
+edge(25,3).
+edge(3,30).
+edge(30,3).
+edge(3,53).
+edge(53,3).
+edge(3,61).
+edge(61,3).
+edge(3,64).
+edge(64,3).
+edge(3,67).
+edge(67,3).
+edge(3,80).
+edge(80,3).
+edge(3,81).
+edge(81,3).
+edge(3,96).
+edge(96,3).
+edge(3,110).
+edge(110,3).
+edge(3,114).
+edge(114,3).
+edge(3,118).
+edge(118,3).
+edge(3,134).
+edge(134,3).
+edge(4,7).
+edge(7,4).
+edge(4,27).
+edge(27,4).
+edge(4,31).
+edge(31,4).
+edge(4,48).
+edge(48,4).
+edge(4,59).
+edge(59,4).
+edge(4,71).
+edge(71,4).
+edge(4,77).
+edge(77,4).
+edge(4,78).
+edge(78,4).
+edge(4,84).
+edge(84,4).
+edge(4,100).
+edge(100,4).
+edge(4,121).
+edge(121,4).
+edge(4,142).
+edge(142,4).
+edge(5,8).
+edge(8,5).
+edge(5,20).
+edge(20,5).
+edge(5,41).
+edge(41,5).
+edge(5,44).
+edge(44,5).
+edge(5,57).
+edge(57,5).
+edge(5,72).
+edge(72,5).
+edge(5,82).
+edge(82,5).
+edge(5,83).
+edge(83,5).
+edge(5,85).
+edge(85,5).
+edge(5,99).
+edge(99,5).
+edge(5,109).
+edge(109,5).
+edge(5,118).
+edge(118,5).
+edge(5,125).
+edge(125,5).
+edge(5,126).
+edge(126,5).
+edge(5,128).
+edge(128,5).
+edge(5,130).
+edge(130,5).
+edge(5,131).
+edge(131,5).
+edge(5,144).
+edge(144,5).
+edge(6,7).
+edge(7,6).
+edge(6,30).
+edge(30,6).
+edge(6,41).
+edge(41,6).
+edge(6,45).
+edge(45,6).
+edge(6,74).
+edge(74,6).
+edge(6,77).
+edge(77,6).
+edge(6,95).
+edge(95,6).
+edge(6,103).
+edge(103,6).
+edge(6,108).
+edge(108,6).
+edge(6,110).
+edge(110,6).
+edge(6,111).
+edge(111,6).
+edge(6,134).
+edge(134,6).
+edge(6,141).
+edge(141,6).
+edge(6,143).
+edge(143,6).
+edge(6,147).
+edge(147,6).
+edge(6,150).
+edge(150,6).
+edge(7,17).
+edge(17,7).
+edge(7,24).
+edge(24,7).
+edge(7,26).
+edge(26,7).
+edge(7,41).
+edge(41,7).
+edge(7,53).
+edge(53,7).
+edge(7,62).
+edge(62,7).
+edge(7,68).
+edge(68,7).
+edge(7,74).
+edge(74,7).
+edge(7,95).
+edge(95,7).
+edge(7,100).
+edge(100,7).
+edge(7,120).
+edge(120,7).
+edge(7,122).
+edge(122,7).
+edge(7,135).
+edge(135,7).
+edge(7,136).
+edge(136,7).
+edge(8,10).
+edge(10,8).
+edge(8,12).
+edge(12,8).
+edge(8,14).
+edge(14,8).
+edge(8,35).
+edge(35,8).
+edge(8,47).
+edge(47,8).
+edge(8,61).
+edge(61,8).
+edge(8,63).
+edge(63,8).
+edge(8,67).
+edge(67,8).
+edge(8,71).
+edge(71,8).
+edge(8,73).
+edge(73,8).
+edge(8,107).
+edge(107,8).
+edge(8,123).
+edge(123,8).
+edge(8,137).
+edge(137,8).
+edge(9,31).
+edge(31,9).
+edge(9,36).
+edge(36,9).
+edge(9,40).
+edge(40,9).
+edge(9,41).
+edge(41,9).
+edge(9,63).
+edge(63,9).
+edge(9,96).
+edge(96,9).
+edge(9,102).
+edge(102,9).
+edge(9,103).
+edge(103,9).
+edge(9,105).
+edge(105,9).
+edge(9,124).
+edge(124,9).
+edge(9,127).
+edge(127,9).
+edge(9,150).
+edge(150,9).
+edge(10,16).
+edge(16,10).
+edge(10,24).
+edge(24,10).
+edge(10,30).
+edge(30,10).
+edge(10,31).
+edge(31,10).
+edge(10,38).
+edge(38,10).
+edge(10,39).
+edge(39,10).
+edge(10,51).
+edge(51,10).
+edge(10,58).
+edge(58,10).
+edge(10,71).
+edge(71,10).
+edge(10,118).
+edge(118,10).
+edge(11,27).
+edge(27,11).
+edge(11,52).
+edge(52,11).
+edge(11,68).
+edge(68,11).
+edge(11,91).
+edge(91,11).
+edge(11,100).
+edge(100,11).
+edge(11,108).
+edge(108,11).
+edge(11,115).
+edge(115,11).
+edge(11,124).
+edge(124,11).
+edge(11,140).
+edge(140,11).
+edge(12,14).
+edge(14,12).
+edge(12,17).
+edge(17,12).
+edge(12,19).
+edge(19,12).
+edge(12,24).
+edge(24,12).
+edge(12,25).
+edge(25,12).
+edge(12,40).
+edge(40,12).
+edge(12,48).
+edge(48,12).
+edge(12,52).
+edge(52,12).
+edge(12,58).
+edge(58,12).
+edge(12,62).
+edge(62,12).
+edge(12,65).
+edge(65,12).
+edge(12,69).
+edge(69,12).
+edge(12,81).
+edge(81,12).
+edge(12,95).
+edge(95,12).
+edge(12,99).
+edge(99,12).
+edge(12,143).
+edge(143,12).
+edge(13,16).
+edge(16,13).
+edge(13,17).
+edge(17,13).
+edge(13,24).
+edge(24,13).
+edge(13,37).
+edge(37,13).
+edge(13,47).
+edge(47,13).
+edge(13,50).
+edge(50,13).
+edge(13,59).
+edge(59,13).
+edge(13,60).
+edge(60,13).
+edge(13,67).
+edge(67,13).
+edge(13,76).
+edge(76,13).
+edge(13,86).
+edge(86,13).
+edge(13,107).
+edge(107,13).
+edge(13,112).
+edge(112,13).
+edge(13,116).
+edge(116,13).
+edge(13,118).
+edge(118,13).
+edge(13,125).
+edge(125,13).
+edge(13,136).
+edge(136,13).
+edge(14,37).
+edge(37,14).
+edge(14,61).
+edge(61,14).
+edge(14,65).
+edge(65,14).
+edge(14,78).
+edge(78,14).
+edge(14,86).
+edge(86,14).
+edge(14,102).
+edge(102,14).
+edge(14,106).
+edge(106,14).
+edge(14,113).
+edge(113,14).
+edge(14,119).
+edge(119,14).
+edge(14,128).
+edge(128,14).
+edge(14,132).
+edge(132,14).
+edge(14,136).
+edge(136,14).
+edge(14,138).
+edge(138,14).
+edge(14,148).
+edge(148,14).
+edge(15,19).
+edge(19,15).
+edge(15,45).
+edge(45,15).
+edge(15,75).
+edge(75,15).
+edge(15,80).
+edge(80,15).
+edge(15,81).
+edge(81,15).
+edge(15,95).
+edge(95,15).
+edge(15,96).
+edge(96,15).
+edge(15,97).
+edge(97,15).
+edge(15,133).
+edge(133,15).
+edge(15,136).
+edge(136,15).
+edge(16,18).
+edge(18,16).
+edge(16,20).
+edge(20,16).
+edge(16,23).
+edge(23,16).
+edge(16,24).
+edge(24,16).
+edge(16,25).
+edge(25,16).
+edge(16,67).
+edge(67,16).
+edge(16,98).
+edge(98,16).
+edge(16,111).
+edge(111,16).
+edge(16,127).
+edge(127,16).
+edge(16,136).
+edge(136,16).
+edge(16,142).
+edge(142,16).
+edge(17,18).
+edge(18,17).
+edge(17,19).
+edge(19,17).
+edge(17,32).
+edge(32,17).
+edge(17,36).
+edge(36,17).
+edge(17,37).
+edge(37,17).
+edge(17,40).
+edge(40,17).
+edge(17,41).
+edge(41,17).
+edge(17,42).
+edge(42,17).
+edge(17,65).
+edge(65,17).
+edge(17,78).
+edge(78,17).
+edge(17,91).
+edge(91,17).
+edge(17,107).
+edge(107,17).
+edge(17,123).
+edge(123,17).
+edge(17,133).
+edge(133,17).
+edge(17,134).
+edge(134,17).
+edge(17,145).
+edge(145,17).
+edge(18,22).
+edge(22,18).
+edge(18,24).
+edge(24,18).
+edge(18,35).
+edge(35,18).
+edge(18,42).
+edge(42,18).
+edge(18,56).
+edge(56,18).
+edge(18,57).
+edge(57,18).
+edge(18,64).
+edge(64,18).
+edge(18,79).
+edge(79,18).
+edge(18,83).
+edge(83,18).
+edge(18,111).
+edge(111,18).
+edge(18,122).
+edge(122,18).
+edge(18,136).
+edge(136,18).
+edge(19,20).
+edge(20,19).
+edge(19,24).
+edge(24,19).
+edge(19,25).
+edge(25,19).
+edge(19,35).
+edge(35,19).
+edge(19,37).
+edge(37,19).
+edge(19,46).
+edge(46,19).
+edge(19,48).
+edge(48,19).
+edge(19,50).
+edge(50,19).
+edge(19,54).
+edge(54,19).
+edge(19,60).
+edge(60,19).
+edge(19,88).
+edge(88,19).
+edge(19,104).
+edge(104,19).
+edge(19,116).
+edge(116,19).
+edge(19,118).
+edge(118,19).
+edge(19,126).
+edge(126,19).
+edge(19,129).
+edge(129,19).
+edge(19,135).
+edge(135,19).
+edge(19,142).
+edge(142,19).
+edge(19,145).
+edge(145,19).
+edge(19,149).
+edge(149,19).
+edge(20,42).
+edge(42,20).
+edge(20,52).
+edge(52,20).
+edge(20,66).
+edge(66,20).
+edge(20,85).
+edge(85,20).
+edge(20,88).
+edge(88,20).
+edge(20,98).
+edge(98,20).
+edge(20,113).
+edge(113,20).
+edge(20,114).
+edge(114,20).
+edge(20,115).
+edge(115,20).
+edge(20,120).
+edge(120,20).
+edge(20,125).
+edge(125,20).
+edge(20,130).
+edge(130,20).
+edge(21,57).
+edge(57,21).
+edge(21,58).
+edge(58,21).
+edge(21,59).
+edge(59,21).
+edge(21,65).
+edge(65,21).
+edge(21,66).
+edge(66,21).
+edge(21,73).
+edge(73,21).
+edge(21,77).
+edge(77,21).
+edge(21,84).
+edge(84,21).
+edge(21,99).
+edge(99,21).
+edge(21,110).
+edge(110,21).
+edge(21,124).
+edge(124,21).
+edge(21,144).
+edge(144,21).
+edge(21,150).
+edge(150,21).
+edge(22,32).
+edge(32,22).
+edge(22,52).
+edge(52,22).
+edge(22,73).
+edge(73,22).
+edge(22,74).
+edge(74,22).
+edge(22,86).
+edge(86,22).
+edge(22,123).
+edge(123,22).
+edge(22,139).
+edge(139,22).
+edge(22,143).
+edge(143,22).
+edge(23,39).
+edge(39,23).
+edge(23,53).
+edge(53,23).
+edge(23,57).
+edge(57,23).
+edge(23,78).
+edge(78,23).
+edge(23,80).
+edge(80,23).
+edge(23,88).
+edge(88,23).
+edge(23,97).
+edge(97,23).
+edge(23,99).
+edge(99,23).
+edge(23,101).
+edge(101,23).
+edge(23,134).
+edge(134,23).
+edge(23,148).
+edge(148,23).
+edge(23,150).
+edge(150,23).
+edge(24,31).
+edge(31,24).
+edge(24,32).
+edge(32,24).
+edge(24,43).
+edge(43,24).
+edge(24,48).
+edge(48,24).
+edge(24,49).
+edge(49,24).
+edge(24,50).
+edge(50,24).
+edge(24,60).
+edge(60,24).
+edge(24,64).
+edge(64,24).
+edge(24,73).
+edge(73,24).
+edge(24,86).
+edge(86,24).
+edge(24,94).
+edge(94,24).
+edge(24,109).
+edge(109,24).
+edge(24,122).
+edge(122,24).
+edge(24,126).
+edge(126,24).
+edge(24,129).
+edge(129,24).
+edge(24,137).
+edge(137,24).
+edge(25,43).
+edge(43,25).
+edge(25,60).
+edge(60,25).
+edge(25,61).
+edge(61,25).
+edge(25,69).
+edge(69,25).
+edge(25,93).
+edge(93,25).
+edge(25,109).
+edge(109,25).
+edge(25,135).
+edge(135,25).
+edge(25,138).
+edge(138,25).
+edge(25,144).
+edge(144,25).
+edge(26,28).
+edge(28,26).
+edge(26,33).
+edge(33,26).
+edge(26,50).
+edge(50,26).
+edge(26,54).
+edge(54,26).
+edge(26,58).
+edge(58,26).
+edge(26,70).
+edge(70,26).
+edge(26,73).
+edge(73,26).
+edge(26,80).
+edge(80,26).
+edge(26,82).
+edge(82,26).
+edge(26,90).
+edge(90,26).
+edge(26,93).
+edge(93,26).
+edge(26,109).
+edge(109,26).
+edge(26,110).
+edge(110,26).
+edge(26,120).
+edge(120,26).
+edge(26,150).
+edge(150,26).
+edge(27,28).
+edge(28,27).
+edge(27,47).
+edge(47,27).
+edge(27,55).
+edge(55,27).
+edge(27,60).
+edge(60,27).
+edge(27,64).
+edge(64,27).
+edge(27,67).
+edge(67,27).
+edge(27,68).
+edge(68,27).
+edge(27,75).
+edge(75,27).
+edge(27,92).
+edge(92,27).
+edge(27,104).
+edge(104,27).
+edge(27,112).
+edge(112,27).
+edge(27,119).
+edge(119,27).
+edge(27,138).
+edge(138,27).
+edge(28,37).
+edge(37,28).
+edge(28,43).
+edge(43,28).
+edge(28,48).
+edge(48,28).
+edge(28,68).
+edge(68,28).
+edge(28,69).
+edge(69,28).
+edge(28,71).
+edge(71,28).
+edge(28,76).
+edge(76,28).
+edge(28,81).
+edge(81,28).
+edge(28,89).
+edge(89,28).
+edge(28,118).
+edge(118,28).
+edge(28,119).
+edge(119,28).
+edge(28,125).
+edge(125,28).
+edge(28,128).
+edge(128,28).
+edge(28,132).
+edge(132,28).
+edge(28,136).
+edge(136,28).
+edge(28,141).
+edge(141,28).
+edge(28,143).
+edge(143,28).
+edge(28,144).
+edge(144,28).
+edge(28,147).
+edge(147,28).
+edge(29,35).
+edge(35,29).
+edge(29,37).
+edge(37,29).
+edge(29,43).
+edge(43,29).
+edge(29,44).
+edge(44,29).
+edge(29,58).
+edge(58,29).
+edge(29,63).
+edge(63,29).
+edge(29,74).
+edge(74,29).
+edge(29,89).
+edge(89,29).
+edge(29,94).
+edge(94,29).
+edge(29,99).
+edge(99,29).
+edge(29,127).
+edge(127,29).
+edge(29,148).
+edge(148,29).
+edge(29,150).
+edge(150,29).
+edge(30,44).
+edge(44,30).
+edge(30,45).
+edge(45,30).
+edge(30,61).
+edge(61,30).
+edge(30,71).
+edge(71,30).
+edge(30,88).
+edge(88,30).
+edge(30,93).
+edge(93,30).
+edge(30,106).
+edge(106,30).
+edge(30,108).
+edge(108,30).
+edge(30,114).
+edge(114,30).
+edge(30,116).
+edge(116,30).
+edge(30,119).
+edge(119,30).
+edge(30,141).
+edge(141,30).
+edge(30,149).
+edge(149,30).
+edge(31,34).
+edge(34,31).
+edge(31,43).
+edge(43,31).
+edge(31,55).
+edge(55,31).
+edge(31,61).
+edge(61,31).
+edge(31,88).
+edge(88,31).
+edge(31,90).
+edge(90,31).
+edge(31,105).
+edge(105,31).
+edge(31,118).
+edge(118,31).
+edge(32,34).
+edge(34,32).
+edge(32,43).
+edge(43,32).
+edge(32,56).
+edge(56,32).
+edge(32,58).
+edge(58,32).
+edge(32,62).
+edge(62,32).
+edge(32,74).
+edge(74,32).
+edge(32,78).
+edge(78,32).
+edge(32,82).
+edge(82,32).
+edge(32,108).
+edge(108,32).
+edge(33,45).
+edge(45,33).
+edge(33,55).
+edge(55,33).
+edge(33,60).
+edge(60,33).
+edge(33,80).
+edge(80,33).
+edge(33,85).
+edge(85,33).
+edge(33,86).
+edge(86,33).
+edge(33,96).
+edge(96,33).
+edge(33,107).
+edge(107,33).
+edge(33,125).
+edge(125,33).
+edge(33,139).
+edge(139,33).
+edge(33,145).
+edge(145,33).
+edge(33,150).
+edge(150,33).
+edge(34,53).
+edge(53,34).
+edge(34,69).
+edge(69,34).
+edge(34,75).
+edge(75,34).
+edge(34,81).
+edge(81,34).
+edge(34,90).
+edge(90,34).
+edge(34,98).
+edge(98,34).
+edge(34,101).
+edge(101,34).
+edge(34,106).
+edge(106,34).
+edge(34,112).
+edge(112,34).
+edge(34,115).
+edge(115,34).
+edge(34,116).
+edge(116,34).
+edge(34,124).
+edge(124,34).
+edge(34,128).
+edge(128,34).
+edge(34,132).
+edge(132,34).
+edge(34,134).
+edge(134,34).
+edge(34,138).
+edge(138,34).
+edge(35,46).
+edge(46,35).
+edge(35,55).
+edge(55,35).
+edge(35,72).
+edge(72,35).
+edge(35,75).
+edge(75,35).
+edge(35,85).
+edge(85,35).
+edge(35,92).
+edge(92,35).
+edge(35,107).
+edge(107,35).
+edge(35,117).
+edge(117,35).
+edge(35,118).
+edge(118,35).
+edge(35,120).
+edge(120,35).
+edge(35,127).
+edge(127,35).
+edge(35,149).
+edge(149,35).
+edge(35,150).
+edge(150,35).
+edge(36,37).
+edge(37,36).
+edge(36,39).
+edge(39,36).
+edge(36,69).
+edge(69,36).
+edge(36,70).
+edge(70,36).
+edge(36,77).
+edge(77,36).
+edge(36,81).
+edge(81,36).
+edge(36,86).
+edge(86,36).
+edge(36,90).
+edge(90,36).
+edge(36,98).
+edge(98,36).
+edge(36,112).
+edge(112,36).
+edge(36,149).
+edge(149,36).
+edge(37,52).
+edge(52,37).
+edge(37,77).
+edge(77,37).
+edge(37,84).
+edge(84,37).
+edge(37,97).
+edge(97,37).
+edge(37,102).
+edge(102,37).
+edge(37,112).
+edge(112,37).
+edge(37,118).
+edge(118,37).
+edge(37,144).
+edge(144,37).
+edge(38,45).
+edge(45,38).
+edge(38,52).
+edge(52,38).
+edge(38,93).
+edge(93,38).
+edge(38,97).
+edge(97,38).
+edge(38,116).
+edge(116,38).
+edge(38,123).
+edge(123,38).
+edge(38,124).
+edge(124,38).
+edge(38,126).
+edge(126,38).
+edge(38,127).
+edge(127,38).
+edge(38,132).
+edge(132,38).
+edge(38,135).
+edge(135,38).
+edge(38,142).
+edge(142,38).
+edge(38,144).
+edge(144,38).
+edge(39,48).
+edge(48,39).
+edge(39,52).
+edge(52,39).
+edge(39,53).
+edge(53,39).
+edge(39,67).
+edge(67,39).
+edge(39,80).
+edge(80,39).
+edge(39,87).
+edge(87,39).
+edge(39,98).
+edge(98,39).
+edge(39,102).
+edge(102,39).
+edge(39,109).
+edge(109,39).
+edge(40,43).
+edge(43,40).
+edge(40,61).
+edge(61,40).
+edge(40,89).
+edge(89,40).
+edge(40,103).
+edge(103,40).
+edge(40,104).
+edge(104,40).
+edge(40,111).
+edge(111,40).
+edge(40,119).
+edge(119,40).
+edge(40,120).
+edge(120,40).
+edge(40,122).
+edge(122,40).
+edge(40,129).
+edge(129,40).
+edge(40,148).
+edge(148,40).
+edge(41,52).
+edge(52,41).
+edge(41,61).
+edge(61,41).
+edge(41,72).
+edge(72,41).
+edge(41,77).
+edge(77,41).
+edge(41,78).
+edge(78,41).
+edge(41,81).
+edge(81,41).
+edge(41,105).
+edge(105,41).
+edge(41,122).
+edge(122,41).
+edge(41,131).
+edge(131,41).
+edge(41,138).
+edge(138,41).
+edge(41,142).
+edge(142,41).
+edge(41,145).
+edge(145,41).
+edge(41,147).
+edge(147,41).
+edge(41,150).
+edge(150,41).
+edge(42,55).
+edge(55,42).
+edge(42,61).
+edge(61,42).
+edge(42,72).
+edge(72,42).
+edge(42,73).
+edge(73,42).
+edge(42,102).
+edge(102,42).
+edge(42,110).
+edge(110,42).
+edge(42,115).
+edge(115,42).
+edge(42,127).
+edge(127,42).
+edge(42,141).
+edge(141,42).
+edge(42,148).
+edge(148,42).
+edge(43,46).
+edge(46,43).
+edge(43,50).
+edge(50,43).
+edge(43,51).
+edge(51,43).
+edge(43,122).
+edge(122,43).
+edge(43,133).
+edge(133,43).
+edge(43,136).
+edge(136,43).
+edge(43,148).
+edge(148,43).
+edge(44,46).
+edge(46,44).
+edge(44,62).
+edge(62,44).
+edge(44,89).
+edge(89,44).
+edge(44,105).
+edge(105,44).
+edge(44,109).
+edge(109,44).
+edge(44,114).
+edge(114,44).
+edge(44,122).
+edge(122,44).
+edge(44,129).
+edge(129,44).
+edge(44,139).
+edge(139,44).
+edge(44,141).
+edge(141,44).
+edge(44,143).
+edge(143,44).
+edge(44,147).
+edge(147,44).
+edge(45,47).
+edge(47,45).
+edge(45,49).
+edge(49,45).
+edge(45,51).
+edge(51,45).
+edge(45,56).
+edge(56,45).
+edge(45,72).
+edge(72,45).
+edge(45,75).
+edge(75,45).
+edge(45,77).
+edge(77,45).
+edge(45,89).
+edge(89,45).
+edge(45,109).
+edge(109,45).
+edge(45,117).
+edge(117,45).
+edge(45,121).
+edge(121,45).
+edge(45,127).
+edge(127,45).
+edge(45,133).
+edge(133,45).
+edge(45,150).
+edge(150,45).
+edge(46,62).
+edge(62,46).
+edge(46,72).
+edge(72,46).
+edge(46,81).
+edge(81,46).
+edge(46,91).
+edge(91,46).
+edge(46,101).
+edge(101,46).
+edge(46,116).
+edge(116,46).
+edge(46,117).
+edge(117,46).
+edge(46,125).
+edge(125,46).
+edge(46,126).
+edge(126,46).
+edge(46,134).
+edge(134,46).
+edge(46,136).
+edge(136,46).
+edge(46,140).
+edge(140,46).
+edge(46,141).
+edge(141,46).
+edge(46,142).
+edge(142,46).
+edge(46,150).
+edge(150,46).
+edge(47,54).
+edge(54,47).
+edge(47,63).
+edge(63,47).
+edge(47,70).
+edge(70,47).
+edge(47,77).
+edge(77,47).
+edge(47,79).
+edge(79,47).
+edge(47,88).
+edge(88,47).
+edge(47,92).
+edge(92,47).
+edge(47,103).
+edge(103,47).
+edge(47,125).
+edge(125,47).
+edge(47,128).
+edge(128,47).
+edge(47,136).
+edge(136,47).
+edge(47,140).
+edge(140,47).
+edge(48,49).
+edge(49,48).
+edge(48,97).
+edge(97,48).
+edge(48,106).
+edge(106,48).
+edge(48,114).
+edge(114,48).
+edge(48,117).
+edge(117,48).
+edge(48,130).
+edge(130,48).
+edge(49,54).
+edge(54,49).
+edge(49,91).
+edge(91,49).
+edge(49,94).
+edge(94,49).
+edge(49,100).
+edge(100,49).
+edge(49,102).
+edge(102,49).
+edge(49,106).
+edge(106,49).
+edge(49,112).
+edge(112,49).
+edge(49,116).
+edge(116,49).
+edge(49,125).
+edge(125,49).
+edge(49,128).
+edge(128,49).
+edge(50,82).
+edge(82,50).
+edge(50,85).
+edge(85,50).
+edge(50,90).
+edge(90,50).
+edge(50,100).
+edge(100,50).
+edge(50,103).
+edge(103,50).
+edge(50,121).
+edge(121,50).
+edge(50,125).
+edge(125,50).
+edge(50,137).
+edge(137,50).
+edge(50,139).
+edge(139,50).
+edge(51,76).
+edge(76,51).
+edge(51,81).
+edge(81,51).
+edge(51,84).
+edge(84,51).
+edge(51,105).
+edge(105,51).
+edge(51,106).
+edge(106,51).
+edge(51,108).
+edge(108,51).
+edge(51,112).
+edge(112,51).
+edge(51,123).
+edge(123,51).
+edge(51,125).
+edge(125,51).
+edge(51,129).
+edge(129,51).
+edge(51,131).
+edge(131,51).
+edge(51,132).
+edge(132,51).
+edge(51,145).
+edge(145,51).
+edge(52,53).
+edge(53,52).
+edge(52,63).
+edge(63,52).
+edge(52,80).
+edge(80,52).
+edge(52,103).
+edge(103,52).
+edge(52,112).
+edge(112,52).
+edge(52,120).
+edge(120,52).
+edge(52,121).
+edge(121,52).
+edge(52,126).
+edge(126,52).
+edge(52,138).
+edge(138,52).
+edge(52,139).
+edge(139,52).
+edge(53,81).
+edge(81,53).
+edge(53,82).
+edge(82,53).
+edge(53,92).
+edge(92,53).
+edge(53,93).
+edge(93,53).
+edge(53,96).
+edge(96,53).
+edge(53,111).
+edge(111,53).
+edge(53,120).
+edge(120,53).
+edge(53,134).
+edge(134,53).
+edge(53,148).
+edge(148,53).
+edge(53,149).
+edge(149,53).
+edge(54,83).
+edge(83,54).
+edge(54,85).
+edge(85,54).
+edge(54,101).
+edge(101,54).
+edge(54,119).
+edge(119,54).
+edge(54,137).
+edge(137,54).
+edge(54,138).
+edge(138,54).
+edge(54,140).
+edge(140,54).
+edge(54,143).
+edge(143,54).
+edge(54,144).
+edge(144,54).
+edge(54,146).
+edge(146,54).
+edge(55,64).
+edge(64,55).
+edge(55,105).
+edge(105,55).
+edge(55,109).
+edge(109,55).
+edge(55,111).
+edge(111,55).
+edge(55,141).
+edge(141,55).
+edge(56,57).
+edge(57,56).
+edge(56,65).
+edge(65,56).
+edge(56,71).
+edge(71,56).
+edge(56,80).
+edge(80,56).
+edge(56,82).
+edge(82,56).
+edge(56,92).
+edge(92,56).
+edge(56,96).
+edge(96,56).
+edge(56,108).
+edge(108,56).
+edge(56,137).
+edge(137,56).
+edge(57,75).
+edge(75,57).
+edge(57,80).
+edge(80,57).
+edge(57,95).
+edge(95,57).
+edge(57,96).
+edge(96,57).
+edge(57,101).
+edge(101,57).
+edge(57,102).
+edge(102,57).
+edge(57,107).
+edge(107,57).
+edge(57,115).
+edge(115,57).
+edge(57,120).
+edge(120,57).
+edge(57,123).
+edge(123,57).
+edge(57,127).
+edge(127,57).
+edge(57,136).
+edge(136,57).
+edge(57,138).
+edge(138,57).
+edge(57,147).
+edge(147,57).
+edge(58,63).
+edge(63,58).
+edge(58,65).
+edge(65,58).
+edge(58,85).
+edge(85,58).
+edge(58,102).
+edge(102,58).
+edge(58,118).
+edge(118,58).
+edge(58,124).
+edge(124,58).
+edge(58,137).
+edge(137,58).
+edge(58,146).
+edge(146,58).
+edge(58,147).
+edge(147,58).
+edge(59,76).
+edge(76,59).
+edge(59,80).
+edge(80,59).
+edge(59,82).
+edge(82,59).
+edge(59,85).
+edge(85,59).
+edge(59,86).
+edge(86,59).
+edge(59,97).
+edge(97,59).
+edge(59,100).
+edge(100,59).
+edge(59,102).
+edge(102,59).
+edge(59,107).
+edge(107,59).
+edge(59,113).
+edge(113,59).
+edge(59,117).
+edge(117,59).
+edge(59,128).
+edge(128,59).
+edge(59,139).
+edge(139,59).
+edge(60,69).
+edge(69,60).
+edge(60,80).
+edge(80,60).
+edge(60,93).
+edge(93,60).
+edge(60,96).
+edge(96,60).
+edge(60,98).
+edge(98,60).
+edge(60,104).
+edge(104,60).
+edge(60,118).
+edge(118,60).
+edge(60,120).
+edge(120,60).
+edge(60,121).
+edge(121,60).
+edge(60,131).
+edge(131,60).
+edge(60,134).
+edge(134,60).
+edge(60,138).
+edge(138,60).
+edge(61,72).
+edge(72,61).
+edge(61,74).
+edge(74,61).
+edge(61,93).
+edge(93,61).
+edge(61,101).
+edge(101,61).
+edge(61,118).
+edge(118,61).
+edge(61,122).
+edge(122,61).
+edge(61,127).
+edge(127,61).
+edge(61,131).
+edge(131,61).
+edge(62,67).
+edge(67,62).
+edge(62,109).
+edge(109,62).
+edge(62,117).
+edge(117,62).
+edge(62,121).
+edge(121,62).
+edge(62,132).
+edge(132,62).
+edge(62,145).
+edge(145,62).
+edge(63,69).
+edge(69,63).
+edge(63,87).
+edge(87,63).
+edge(63,88).
+edge(88,63).
+edge(63,103).
+edge(103,63).
+edge(63,104).
+edge(104,63).
+edge(63,127).
+edge(127,63).
+edge(63,133).
+edge(133,63).
+edge(63,138).
+edge(138,63).
+edge(63,146).
+edge(146,63).
+edge(63,147).
+edge(147,63).
+edge(64,68).
+edge(68,64).
+edge(64,87).
+edge(87,64).
+edge(64,118).
+edge(118,64).
+edge(64,130).
+edge(130,64).
+edge(64,145).
+edge(145,64).
+edge(65,87).
+edge(87,65).
+edge(65,93).
+edge(93,65).
+edge(65,98).
+edge(98,65).
+edge(65,107).
+edge(107,65).
+edge(65,135).
+edge(135,65).
+edge(65,139).
+edge(139,65).
+edge(65,141).
+edge(141,65).
+edge(66,74).
+edge(74,66).
+edge(66,81).
+edge(81,66).
+edge(66,83).
+edge(83,66).
+edge(66,84).
+edge(84,66).
+edge(66,94).
+edge(94,66).
+edge(66,95).
+edge(95,66).
+edge(66,110).
+edge(110,66).
+edge(66,111).
+edge(111,66).
+edge(66,145).
+edge(145,66).
+edge(66,148).
+edge(148,66).
+edge(67,68).
+edge(68,67).
+edge(67,82).
+edge(82,67).
+edge(67,86).
+edge(86,67).
+edge(67,88).
+edge(88,67).
+edge(67,91).
+edge(91,67).
+edge(67,97).
+edge(97,67).
+edge(67,121).
+edge(121,67).
+edge(67,133).
+edge(133,67).
+edge(67,150).
+edge(150,67).
+edge(68,96).
+edge(96,68).
+edge(68,104).
+edge(104,68).
+edge(68,106).
+edge(106,68).
+edge(68,109).
+edge(109,68).
+edge(68,117).
+edge(117,68).
+edge(68,134).
+edge(134,68).
+edge(68,138).
+edge(138,68).
+edge(69,84).
+edge(84,69).
+edge(69,85).
+edge(85,69).
+edge(69,91).
+edge(91,69).
+edge(69,110).
+edge(110,69).
+edge(69,117).
+edge(117,69).
+edge(70,71).
+edge(71,70).
+edge(70,79).
+edge(79,70).
+edge(70,126).
+edge(126,70).
+edge(70,136).
+edge(136,70).
+edge(70,142).
+edge(142,70).
+edge(70,149).
+edge(149,70).
+edge(71,73).
+edge(73,71).
+edge(71,74).
+edge(74,71).
+edge(71,76).
+edge(76,71).
+edge(71,113).
+edge(113,71).
+edge(71,117).
+edge(117,71).
+edge(71,119).
+edge(119,71).
+edge(71,138).
+edge(138,71).
+edge(71,139).
+edge(139,71).
+edge(71,140).
+edge(140,71).
+edge(71,143).
+edge(143,71).
+edge(72,76).
+edge(76,72).
+edge(72,83).
+edge(83,72).
+edge(72,91).
+edge(91,72).
+edge(72,92).
+edge(92,72).
+edge(72,93).
+edge(93,72).
+edge(72,94).
+edge(94,72).
+edge(72,99).
+edge(99,72).
+edge(72,100).
+edge(100,72).
+edge(72,113).
+edge(113,72).
+edge(72,115).
+edge(115,72).
+edge(72,126).
+edge(126,72).
+edge(72,128).
+edge(128,72).
+edge(72,146).
+edge(146,72).
+edge(72,150).
+edge(150,72).
+edge(73,78).
+edge(78,73).
+edge(73,102).
+edge(102,73).
+edge(73,110).
+edge(110,73).
+edge(73,112).
+edge(112,73).
+edge(73,113).
+edge(113,73).
+edge(73,132).
+edge(132,73).
+edge(74,75).
+edge(75,74).
+edge(74,85).
+edge(85,74).
+edge(74,101).
+edge(101,74).
+edge(74,122).
+edge(122,74).
+edge(74,125).
+edge(125,74).
+edge(74,140).
+edge(140,74).
+edge(75,85).
+edge(85,75).
+edge(75,88).
+edge(88,75).
+edge(75,89).
+edge(89,75).
+edge(75,91).
+edge(91,75).
+edge(75,97).
+edge(97,75).
+edge(75,117).
+edge(117,75).
+edge(75,120).
+edge(120,75).
+edge(75,127).
+edge(127,75).
+edge(75,134).
+edge(134,75).
+edge(75,137).
+edge(137,75).
+edge(75,143).
+edge(143,75).
+edge(75,144).
+edge(144,75).
+edge(76,77).
+edge(77,76).
+edge(76,83).
+edge(83,76).
+edge(76,116).
+edge(116,76).
+edge(76,117).
+edge(117,76).
+edge(76,121).
+edge(121,76).
+edge(76,128).
+edge(128,76).
+edge(76,136).
+edge(136,76).
+edge(76,138).
+edge(138,76).
+edge(76,140).
+edge(140,76).
+edge(76,150).
+edge(150,76).
+edge(77,87).
+edge(87,77).
+edge(77,93).
+edge(93,77).
+edge(77,96).
+edge(96,77).
+edge(77,103).
+edge(103,77).
+edge(77,114).
+edge(114,77).
+edge(77,120).
+edge(120,77).
+edge(77,122).
+edge(122,77).
+edge(78,79).
+edge(79,78).
+edge(78,80).
+edge(80,78).
+edge(78,90).
+edge(90,78).
+edge(78,101).
+edge(101,78).
+edge(78,103).
+edge(103,78).
+edge(78,105).
+edge(105,78).
+edge(78,114).
+edge(114,78).
+edge(78,117).
+edge(117,78).
+edge(78,133).
+edge(133,78).
+edge(79,91).
+edge(91,79).
+edge(79,94).
+edge(94,79).
+edge(79,101).
+edge(101,79).
+edge(79,111).
+edge(111,79).
+edge(79,120).
+edge(120,79).
+edge(79,125).
+edge(125,79).
+edge(79,127).
+edge(127,79).
+edge(80,88).
+edge(88,80).
+edge(80,100).
+edge(100,80).
+edge(80,108).
+edge(108,80).
+edge(80,130).
+edge(130,80).
+edge(80,136).
+edge(136,80).
+edge(81,90).
+edge(90,81).
+edge(81,129).
+edge(129,81).
+edge(82,116).
+edge(116,82).
+edge(82,123).
+edge(123,82).
+edge(83,84).
+edge(84,83).
+edge(83,87).
+edge(87,83).
+edge(83,89).
+edge(89,83).
+edge(83,101).
+edge(101,83).
+edge(83,108).
+edge(108,83).
+edge(83,117).
+edge(117,83).
+edge(83,130).
+edge(130,83).
+edge(83,149).
+edge(149,83).
+edge(84,91).
+edge(91,84).
+edge(84,96).
+edge(96,84).
+edge(84,107).
+edge(107,84).
+edge(84,115).
+edge(115,84).
+edge(84,127).
+edge(127,84).
+edge(84,142).
+edge(142,84).
+edge(84,144).
+edge(144,84).
+edge(84,146).
+edge(146,84).
+edge(85,108).
+edge(108,85).
+edge(85,124).
+edge(124,85).
+edge(85,131).
+edge(131,85).
+edge(85,150).
+edge(150,85).
+edge(86,88).
+edge(88,86).
+edge(86,89).
+edge(89,86).
+edge(86,97).
+edge(97,86).
+edge(86,103).
+edge(103,86).
+edge(86,104).
+edge(104,86).
+edge(86,109).
+edge(109,86).
+edge(86,112).
+edge(112,86).
+edge(86,123).
+edge(123,86).
+edge(86,134).
+edge(134,86).
+edge(87,94).
+edge(94,87).
+edge(87,101).
+edge(101,87).
+edge(87,115).
+edge(115,87).
+edge(87,116).
+edge(116,87).
+edge(87,121).
+edge(121,87).
+edge(87,126).
+edge(126,87).
+edge(87,133).
+edge(133,87).
+edge(87,138).
+edge(138,87).
+edge(87,140).
+edge(140,87).
+edge(87,144).
+edge(144,87).
+edge(87,150).
+edge(150,87).
+edge(88,89).
+edge(89,88).
+edge(88,97).
+edge(97,88).
+edge(88,133).
+edge(133,88).
+edge(88,139).
+edge(139,88).
+edge(89,92).
+edge(92,89).
+edge(89,101).
+edge(101,89).
+edge(89,116).
+edge(116,89).
+edge(89,120).
+edge(120,89).
+edge(89,122).
+edge(122,89).
+edge(89,126).
+edge(126,89).
+edge(89,129).
+edge(129,89).
+edge(89,142).
+edge(142,89).
+edge(89,149).
+edge(149,89).
+edge(89,150).
+edge(150,89).
+edge(90,91).
+edge(91,90).
+edge(90,99).
+edge(99,90).
+edge(90,139).
+edge(139,90).
+edge(90,145).
+edge(145,90).
+edge(91,123).
+edge(123,91).
+edge(91,129).
+edge(129,91).
+edge(91,134).
+edge(134,91).
+edge(91,137).
+edge(137,91).
+edge(91,142).
+edge(142,91).
+edge(92,100).
+edge(100,92).
+edge(92,105).
+edge(105,92).
+edge(92,106).
+edge(106,92).
+edge(92,113).
+edge(113,92).
+edge(92,143).
+edge(143,92).
+edge(93,100).
+edge(100,93).
+edge(93,112).
+edge(112,93).
+edge(93,123).
+edge(123,93).
+edge(93,128).
+edge(128,93).
+edge(93,139).
+edge(139,93).
+edge(93,140).
+edge(140,93).
+edge(93,149).
+edge(149,93).
+edge(94,102).
+edge(102,94).
+edge(94,112).
+edge(112,94).
+edge(94,130).
+edge(130,94).
+edge(94,150).
+edge(150,94).
+edge(95,112).
+edge(112,95).
+edge(95,119).
+edge(119,95).
+edge(95,135).
+edge(135,95).
+edge(95,142).
+edge(142,95).
+edge(96,107).
+edge(107,96).
+edge(96,108).
+edge(108,96).
+edge(96,116).
+edge(116,96).
+edge(96,117).
+edge(117,96).
+edge(96,127).
+edge(127,96).
+edge(96,132).
+edge(132,96).
+edge(96,138).
+edge(138,96).
+edge(97,126).
+edge(126,97).
+edge(97,146).
+edge(146,97).
+edge(98,117).
+edge(117,98).
+edge(98,146).
+edge(146,98).
+edge(99,115).
+edge(115,99).
+edge(100,124).
+edge(124,100).
+edge(100,126).
+edge(126,100).
+edge(100,148).
+edge(148,100).
+edge(101,112).
+edge(112,101).
+edge(101,117).
+edge(117,101).
+edge(101,126).
+edge(126,101).
+edge(101,134).
+edge(134,101).
+edge(101,145).
+edge(145,101).
+edge(102,105).
+edge(105,102).
+edge(102,131).
+edge(131,102).
+edge(102,141).
+edge(141,102).
+edge(103,107).
+edge(107,103).
+edge(103,115).
+edge(115,103).
+edge(103,120).
+edge(120,103).
+edge(103,129).
+edge(129,103).
+edge(103,141).
+edge(141,103).
+edge(104,107).
+edge(107,104).
+edge(104,109).
+edge(109,104).
+edge(104,119).
+edge(119,104).
+edge(104,132).
+edge(132,104).
+edge(104,133).
+edge(133,104).
+edge(104,136).
+edge(136,104).
+edge(104,148).
+edge(148,104).
+edge(105,115).
+edge(115,105).
+edge(105,116).
+edge(116,105).
+edge(105,118).
+edge(118,105).
+edge(105,119).
+edge(119,105).
+edge(105,135).
+edge(135,105).
+edge(105,147).
+edge(147,105).
+edge(106,116).
+edge(116,106).
+edge(106,126).
+edge(126,106).
+edge(106,134).
+edge(134,106).
+edge(106,136).
+edge(136,106).
+edge(107,116).
+edge(116,107).
+edge(107,117).
+edge(117,107).
+edge(107,125).
+edge(125,107).
+edge(107,129).
+edge(129,107).
+edge(107,130).
+edge(130,107).
+edge(108,126).
+edge(126,108).
+edge(108,129).
+edge(129,108).
+edge(108,143).
+edge(143,108).
+edge(109,120).
+edge(120,109).
+edge(109,122).
+edge(122,109).
+edge(109,128).
+edge(128,109).
+edge(109,131).
+edge(131,109).
+edge(109,145).
+edge(145,109).
+edge(109,147).
+edge(147,109).
+edge(110,113).
+edge(113,110).
+edge(110,126).
+edge(126,110).
+edge(110,136).
+edge(136,110).
+edge(110,138).
+edge(138,110).
+edge(111,117).
+edge(117,111).
+edge(111,122).
+edge(122,111).
+edge(111,126).
+edge(126,111).
+edge(111,131).
+edge(131,111).
+edge(111,133).
+edge(133,111).
+edge(112,122).
+edge(122,112).
+edge(112,125).
+edge(125,112).
+edge(112,129).
+edge(129,112).
+edge(112,130).
+edge(130,112).
+edge(113,118).
+edge(118,113).
+edge(113,125).
+edge(125,113).
+edge(113,147).
+edge(147,113).
+edge(114,117).
+edge(117,114).
+edge(114,130).
+edge(130,114).
+edge(114,139).
+edge(139,114).
+edge(114,148).
+edge(148,114).
+edge(115,117).
+edge(117,115).
+edge(115,120).
+edge(120,115).
+edge(115,127).
+edge(127,115).
+edge(115,128).
+edge(128,115).
+edge(115,133).
+edge(133,115).
+edge(115,136).
+edge(136,115).
+edge(115,141).
+edge(141,115).
+edge(116,117).
+edge(117,116).
+edge(116,125).
+edge(125,116).
+edge(116,138).
+edge(138,116).
+edge(117,145).
+edge(145,117).
+edge(118,123).
+edge(123,118).
+edge(118,144).
+edge(144,118).
+edge(119,135).
+edge(135,119).
+edge(119,142).
+edge(142,119).
+edge(120,142).
+edge(142,120).
+edge(121,123).
+edge(123,121).
+edge(121,136).
+edge(136,121).
+edge(121,138).
+edge(138,121).
+edge(121,147).
+edge(147,121).
+edge(122,127).
+edge(127,122).
+edge(122,149).
+edge(149,122).
+edge(123,126).
+edge(126,123).
+edge(123,144).
+edge(144,123).
+edge(124,145).
+edge(145,124).
+edge(124,146).
+edge(146,124).
+edge(125,142).
+edge(142,125).
+edge(125,143).
+edge(143,125).
+edge(125,145).
+edge(145,125).
+edge(125,149).
+edge(149,125).
+edge(126,138).
+edge(138,126).
+edge(128,133).
+edge(133,128).
+edge(128,136).
+edge(136,128).
+edge(128,144).
+edge(144,128).
+edge(129,132).
+edge(132,129).
+edge(129,134).
+edge(134,129).
+edge(129,142).
+edge(142,129).
+edge(130,133).
+edge(133,130).
+edge(131,140).
+edge(140,131).
+edge(132,134).
+edge(134,132).
+edge(133,140).
+edge(140,133).
+edge(133,144).
+edge(144,133).
+edge(133,146).
+edge(146,133).
+edge(134,140).
+edge(140,134).
+edge(135,136).
+edge(136,135).
+edge(135,137).
+edge(137,135).
+edge(135,149).
+edge(149,135).
+edge(136,147).
+edge(147,136).
+edge(138,144).
+edge(144,138).
+edge(140,146).
+edge(146,140).
+edge(141,149).
+edge(149,141).
+edge(142,145).
+edge(145,142).
+edge(143,147).
+edge(147,143).
+edge(146,148).
+edge(148,146).
+
diff --git a/examples/clingo/expansion/GraphColouring/instances/0060-graph_colouring-150-0.lp b/examples/clingo/expansion/GraphColouring/instances/0060-graph_colouring-150-0.lp
new file mode 100644
index 0000000..70f2206
--- /dev/null
+++ b/examples/clingo/expansion/GraphColouring/instances/0060-graph_colouring-150-0.lp
@@ -0,0 +1,2472 @@
+#const n=150.
+node(1).
+node(2).
+node(3).
+node(4).
+node(5).
+node(6).
+node(7).
+node(8).
+node(9).
+node(10).
+node(11).
+node(12).
+node(13).
+node(14).
+node(15).
+node(16).
+node(17).
+node(18).
+node(19).
+node(20).
+node(21).
+node(22).
+node(23).
+node(24).
+node(25).
+node(26).
+node(27).
+node(28).
+node(29).
+node(30).
+node(31).
+node(32).
+node(33).
+node(34).
+node(35).
+node(36).
+node(37).
+node(38).
+node(39).
+node(40).
+node(41).
+node(42).
+node(43).
+node(44).
+node(45).
+node(46).
+node(47).
+node(48).
+node(49).
+node(50).
+node(51).
+node(52).
+node(53).
+node(54).
+node(55).
+node(56).
+node(57).
+node(58).
+node(59).
+node(60).
+node(61).
+node(62).
+node(63).
+node(64).
+node(65).
+node(66).
+node(67).
+node(68).
+node(69).
+node(70).
+node(71).
+node(72).
+node(73).
+node(74).
+node(75).
+node(76).
+node(77).
+node(78).
+node(79).
+node(80).
+node(81).
+node(82).
+node(83).
+node(84).
+node(85).
+node(86).
+node(87).
+node(88).
+node(89).
+node(90).
+node(91).
+node(92).
+node(93).
+node(94).
+node(95).
+node(96).
+node(97).
+node(98).
+node(99).
+node(100).
+node(101).
+node(102).
+node(103).
+node(104).
+node(105).
+node(106).
+node(107).
+node(108).
+node(109).
+node(110).
+node(111).
+node(112).
+node(113).
+node(114).
+node(115).
+node(116).
+node(117).
+node(118).
+node(119).
+node(120).
+node(121).
+node(122).
+node(123).
+node(124).
+node(125).
+node(126).
+node(127).
+node(128).
+node(129).
+node(130).
+node(131).
+node(132).
+node(133).
+node(134).
+node(135).
+node(136).
+node(137).
+node(138).
+node(139).
+node(140).
+node(141).
+node(142).
+node(143).
+node(144).
+node(145).
+node(146).
+node(147).
+node(148).
+node(149).
+node(150).
+edge(1,8).
+edge(8,1).
+edge(1,16).
+edge(16,1).
+edge(1,29).
+edge(29,1).
+edge(1,34).
+edge(34,1).
+edge(1,54).
+edge(54,1).
+edge(1,64).
+edge(64,1).
+edge(1,112).
+edge(112,1).
+edge(1,124).
+edge(124,1).
+edge(1,150).
+edge(150,1).
+edge(2,22).
+edge(22,2).
+edge(2,29).
+edge(29,2).
+edge(2,39).
+edge(39,2).
+edge(2,50).
+edge(50,2).
+edge(2,59).
+edge(59,2).
+edge(2,62).
+edge(62,2).
+edge(2,70).
+edge(70,2).
+edge(2,71).
+edge(71,2).
+edge(2,95).
+edge(95,2).
+edge(2,97).
+edge(97,2).
+edge(2,99).
+edge(99,2).
+edge(2,121).
+edge(121,2).
+edge(2,138).
+edge(138,2).
+edge(2,142).
+edge(142,2).
+edge(2,146).
+edge(146,2).
+edge(3,7).
+edge(7,3).
+edge(3,11).
+edge(11,3).
+edge(3,30).
+edge(30,3).
+edge(3,53).
+edge(53,3).
+edge(3,61).
+edge(61,3).
+edge(3,67).
+edge(67,3).
+edge(3,69).
+edge(69,3).
+edge(3,94).
+edge(94,3).
+edge(3,103).
+edge(103,3).
+edge(3,115).
+edge(115,3).
+edge(3,140).
+edge(140,3).
+edge(3,146).
+edge(146,3).
+edge(4,8).
+edge(8,4).
+edge(4,9).
+edge(9,4).
+edge(4,33).
+edge(33,4).
+edge(4,40).
+edge(40,4).
+edge(4,60).
+edge(60,4).
+edge(4,63).
+edge(63,4).
+edge(4,69).
+edge(69,4).
+edge(4,79).
+edge(79,4).
+edge(4,82).
+edge(82,4).
+edge(4,97).
+edge(97,4).
+edge(4,101).
+edge(101,4).
+edge(4,116).
+edge(116,4).
+edge(4,122).
+edge(122,4).
+edge(4,126).
+edge(126,4).
+edge(4,137).
+edge(137,4).
+edge(5,15).
+edge(15,5).
+edge(5,21).
+edge(21,5).
+edge(5,43).
+edge(43,5).
+edge(5,57).
+edge(57,5).
+edge(5,61).
+edge(61,5).
+edge(5,63).
+edge(63,5).
+edge(5,69).
+edge(69,5).
+edge(5,74).
+edge(74,5).
+edge(5,81).
+edge(81,5).
+edge(5,83).
+edge(83,5).
+edge(5,85).
+edge(85,5).
+edge(5,90).
+edge(90,5).
+edge(5,95).
+edge(95,5).
+edge(5,99).
+edge(99,5).
+edge(5,113).
+edge(113,5).
+edge(5,116).
+edge(116,5).
+edge(5,123).
+edge(123,5).
+edge(5,125).
+edge(125,5).
+edge(5,131).
+edge(131,5).
+edge(6,8).
+edge(8,6).
+edge(6,17).
+edge(17,6).
+edge(6,26).
+edge(26,6).
+edge(6,33).
+edge(33,6).
+edge(6,42).
+edge(42,6).
+edge(6,59).
+edge(59,6).
+edge(6,65).
+edge(65,6).
+edge(6,74).
+edge(74,6).
+edge(6,90).
+edge(90,6).
+edge(6,107).
+edge(107,6).
+edge(6,108).
+edge(108,6).
+edge(6,123).
+edge(123,6).
+edge(6,133).
+edge(133,6).
+edge(6,135).
+edge(135,6).
+edge(6,138).
+edge(138,6).
+edge(6,142).
+edge(142,6).
+edge(7,8).
+edge(8,7).
+edge(7,17).
+edge(17,7).
+edge(7,32).
+edge(32,7).
+edge(7,59).
+edge(59,7).
+edge(7,66).
+edge(66,7).
+edge(7,85).
+edge(85,7).
+edge(7,87).
+edge(87,7).
+edge(7,88).
+edge(88,7).
+edge(7,123).
+edge(123,7).
+edge(7,124).
+edge(124,7).
+edge(7,146).
+edge(146,7).
+edge(8,9).
+edge(9,8).
+edge(8,12).
+edge(12,8).
+edge(8,34).
+edge(34,8).
+edge(8,37).
+edge(37,8).
+edge(8,42).
+edge(42,8).
+edge(8,58).
+edge(58,8).
+edge(8,65).
+edge(65,8).
+edge(8,73).
+edge(73,8).
+edge(8,81).
+edge(81,8).
+edge(8,83).
+edge(83,8).
+edge(8,84).
+edge(84,8).
+edge(8,87).
+edge(87,8).
+edge(8,107).
+edge(107,8).
+edge(8,116).
+edge(116,8).
+edge(8,122).
+edge(122,8).
+edge(8,129).
+edge(129,8).
+edge(8,138).
+edge(138,8).
+edge(8,139).
+edge(139,8).
+edge(9,21).
+edge(21,9).
+edge(9,29).
+edge(29,9).
+edge(9,30).
+edge(30,9).
+edge(9,36).
+edge(36,9).
+edge(9,39).
+edge(39,9).
+edge(9,48).
+edge(48,9).
+edge(9,50).
+edge(50,9).
+edge(9,58).
+edge(58,9).
+edge(9,63).
+edge(63,9).
+edge(9,69).
+edge(69,9).
+edge(9,85).
+edge(85,9).
+edge(9,91).
+edge(91,9).
+edge(9,92).
+edge(92,9).
+edge(9,118).
+edge(118,9).
+edge(9,119).
+edge(119,9).
+edge(9,128).
+edge(128,9).
+edge(9,133).
+edge(133,9).
+edge(9,142).
+edge(142,9).
+edge(10,12).
+edge(12,10).
+edge(10,20).
+edge(20,10).
+edge(10,23).
+edge(23,10).
+edge(10,27).
+edge(27,10).
+edge(10,37).
+edge(37,10).
+edge(10,52).
+edge(52,10).
+edge(10,54).
+edge(54,10).
+edge(10,56).
+edge(56,10).
+edge(10,62).
+edge(62,10).
+edge(10,63).
+edge(63,10).
+edge(10,92).
+edge(92,10).
+edge(10,105).
+edge(105,10).
+edge(10,116).
+edge(116,10).
+edge(10,137).
+edge(137,10).
+edge(10,143).
+edge(143,10).
+edge(10,146).
+edge(146,10).
+edge(10,147).
+edge(147,10).
+edge(11,13).
+edge(13,11).
+edge(11,18).
+edge(18,11).
+edge(11,21).
+edge(21,11).
+edge(11,25).
+edge(25,11).
+edge(11,35).
+edge(35,11).
+edge(11,61).
+edge(61,11).
+edge(11,64).
+edge(64,11).
+edge(11,68).
+edge(68,11).
+edge(11,89).
+edge(89,11).
+edge(11,96).
+edge(96,11).
+edge(11,101).
+edge(101,11).
+edge(11,105).
+edge(105,11).
+edge(11,107).
+edge(107,11).
+edge(11,112).
+edge(112,11).
+edge(11,118).
+edge(118,11).
+edge(11,127).
+edge(127,11).
+edge(11,132).
+edge(132,11).
+edge(11,142).
+edge(142,11).
+edge(12,13).
+edge(13,12).
+edge(12,23).
+edge(23,12).
+edge(12,32).
+edge(32,12).
+edge(12,38).
+edge(38,12).
+edge(12,52).
+edge(52,12).
+edge(12,56).
+edge(56,12).
+edge(12,58).
+edge(58,12).
+edge(12,60).
+edge(60,12).
+edge(12,63).
+edge(63,12).
+edge(12,71).
+edge(71,12).
+edge(12,94).
+edge(94,12).
+edge(12,99).
+edge(99,12).
+edge(12,100).
+edge(100,12).
+edge(12,122).
+edge(122,12).
+edge(12,130).
+edge(130,12).
+edge(12,133).
+edge(133,12).
+edge(12,135).
+edge(135,12).
+edge(12,144).
+edge(144,12).
+edge(12,147).
+edge(147,12).
+edge(13,40).
+edge(40,13).
+edge(13,57).
+edge(57,13).
+edge(13,59).
+edge(59,13).
+edge(13,60).
+edge(60,13).
+edge(13,62).
+edge(62,13).
+edge(13,66).
+edge(66,13).
+edge(13,70).
+edge(70,13).
+edge(13,75).
+edge(75,13).
+edge(13,78).
+edge(78,13).
+edge(13,79).
+edge(79,13).
+edge(13,91).
+edge(91,13).
+edge(13,95).
+edge(95,13).
+edge(13,105).
+edge(105,13).
+edge(13,128).
+edge(128,13).
+edge(13,130).
+edge(130,13).
+edge(13,132).
+edge(132,13).
+edge(13,147).
+edge(147,13).
+edge(14,17).
+edge(17,14).
+edge(14,37).
+edge(37,14).
+edge(14,40).
+edge(40,14).
+edge(14,41).
+edge(41,14).
+edge(14,52).
+edge(52,14).
+edge(14,78).
+edge(78,14).
+edge(14,105).
+edge(105,14).
+edge(15,32).
+edge(32,15).
+edge(15,41).
+edge(41,15).
+edge(15,47).
+edge(47,15).
+edge(15,50).
+edge(50,15).
+edge(15,56).
+edge(56,15).
+edge(15,65).
+edge(65,15).
+edge(15,69).
+edge(69,15).
+edge(15,73).
+edge(73,15).
+edge(15,81).
+edge(81,15).
+edge(15,82).
+edge(82,15).
+edge(15,105).
+edge(105,15).
+edge(15,111).
+edge(111,15).
+edge(15,117).
+edge(117,15).
+edge(15,120).
+edge(120,15).
+edge(15,125).
+edge(125,15).
+edge(15,148).
+edge(148,15).
+edge(16,54).
+edge(54,16).
+edge(16,66).
+edge(66,16).
+edge(16,71).
+edge(71,16).
+edge(16,82).
+edge(82,16).
+edge(16,83).
+edge(83,16).
+edge(16,95).
+edge(95,16).
+edge(16,109).
+edge(109,16).
+edge(16,113).
+edge(113,16).
+edge(16,120).
+edge(120,16).
+edge(16,139).
+edge(139,16).
+edge(17,18).
+edge(18,17).
+edge(17,26).
+edge(26,17).
+edge(17,29).
+edge(29,17).
+edge(17,30).
+edge(30,17).
+edge(17,32).
+edge(32,17).
+edge(17,34).
+edge(34,17).
+edge(17,53).
+edge(53,17).
+edge(17,72).
+edge(72,17).
+edge(17,98).
+edge(98,17).
+edge(17,105).
+edge(105,17).
+edge(17,118).
+edge(118,17).
+edge(17,150).
+edge(150,17).
+edge(18,21).
+edge(21,18).
+edge(18,46).
+edge(46,18).
+edge(18,49).
+edge(49,18).
+edge(18,53).
+edge(53,18).
+edge(18,61).
+edge(61,18).
+edge(18,63).
+edge(63,18).
+edge(18,68).
+edge(68,18).
+edge(18,69).
+edge(69,18).
+edge(18,94).
+edge(94,18).
+edge(18,108).
+edge(108,18).
+edge(18,111).
+edge(111,18).
+edge(18,118).
+edge(118,18).
+edge(18,126).
+edge(126,18).
+edge(18,128).
+edge(128,18).
+edge(19,20).
+edge(20,19).
+edge(19,21).
+edge(21,19).
+edge(19,24).
+edge(24,19).
+edge(19,27).
+edge(27,19).
+edge(19,33).
+edge(33,19).
+edge(19,45).
+edge(45,19).
+edge(19,62).
+edge(62,19).
+edge(19,72).
+edge(72,19).
+edge(19,73).
+edge(73,19).
+edge(19,80).
+edge(80,19).
+edge(19,83).
+edge(83,19).
+edge(19,87).
+edge(87,19).
+edge(19,100).
+edge(100,19).
+edge(19,108).
+edge(108,19).
+edge(19,129).
+edge(129,19).
+edge(19,135).
+edge(135,19).
+edge(19,143).
+edge(143,19).
+edge(20,36).
+edge(36,20).
+edge(20,46).
+edge(46,20).
+edge(20,74).
+edge(74,20).
+edge(20,83).
+edge(83,20).
+edge(20,88).
+edge(88,20).
+edge(20,93).
+edge(93,20).
+edge(20,122).
+edge(122,20).
+edge(20,124).
+edge(124,20).
+edge(20,125).
+edge(125,20).
+edge(20,134).
+edge(134,20).
+edge(20,150).
+edge(150,20).
+edge(21,27).
+edge(27,21).
+edge(21,29).
+edge(29,21).
+edge(21,43).
+edge(43,21).
+edge(21,72).
+edge(72,21).
+edge(21,73).
+edge(73,21).
+edge(21,78).
+edge(78,21).
+edge(21,86).
+edge(86,21).
+edge(21,95).
+edge(95,21).
+edge(21,102).
+edge(102,21).
+edge(21,103).
+edge(103,21).
+edge(21,112).
+edge(112,21).
+edge(21,126).
+edge(126,21).
+edge(21,128).
+edge(128,21).
+edge(21,147).
+edge(147,21).
+edge(22,26).
+edge(26,22).
+edge(22,34).
+edge(34,22).
+edge(22,46).
+edge(46,22).
+edge(22,62).
+edge(62,22).
+edge(22,65).
+edge(65,22).
+edge(22,76).
+edge(76,22).
+edge(22,78).
+edge(78,22).
+edge(22,99).
+edge(99,22).
+edge(22,111).
+edge(111,22).
+edge(22,112).
+edge(112,22).
+edge(22,127).
+edge(127,22).
+edge(22,134).
+edge(134,22).
+edge(22,136).
+edge(136,22).
+edge(23,29).
+edge(29,23).
+edge(23,30).
+edge(30,23).
+edge(23,32).
+edge(32,23).
+edge(23,39).
+edge(39,23).
+edge(23,41).
+edge(41,23).
+edge(23,47).
+edge(47,23).
+edge(23,49).
+edge(49,23).
+edge(23,50).
+edge(50,23).
+edge(23,51).
+edge(51,23).
+edge(23,60).
+edge(60,23).
+edge(23,64).
+edge(64,23).
+edge(23,75).
+edge(75,23).
+edge(23,85).
+edge(85,23).
+edge(23,91).
+edge(91,23).
+edge(23,94).
+edge(94,23).
+edge(23,109).
+edge(109,23).
+edge(23,116).
+edge(116,23).
+edge(23,130).
+edge(130,23).
+edge(23,134).
+edge(134,23).
+edge(24,60).
+edge(60,24).
+edge(24,64).
+edge(64,24).
+edge(24,87).
+edge(87,24).
+edge(24,90).
+edge(90,24).
+edge(24,91).
+edge(91,24).
+edge(24,106).
+edge(106,24).
+edge(24,137).
+edge(137,24).
+edge(24,138).
+edge(138,24).
+edge(24,147).
+edge(147,24).
+edge(24,148).
+edge(148,24).
+edge(25,32).
+edge(32,25).
+edge(25,44).
+edge(44,25).
+edge(25,49).
+edge(49,25).
+edge(25,58).
+edge(58,25).
+edge(25,62).
+edge(62,25).
+edge(25,68).
+edge(68,25).
+edge(25,73).
+edge(73,25).
+edge(25,82).
+edge(82,25).
+edge(25,88).
+edge(88,25).
+edge(25,99).
+edge(99,25).
+edge(25,100).
+edge(100,25).
+edge(25,125).
+edge(125,25).
+edge(25,128).
+edge(128,25).
+edge(25,133).
+edge(133,25).
+edge(25,141).
+edge(141,25).
+edge(25,142).
+edge(142,25).
+edge(25,146).
+edge(146,25).
+edge(26,28).
+edge(28,26).
+edge(26,65).
+edge(65,26).
+edge(26,88).
+edge(88,26).
+edge(26,101).
+edge(101,26).
+edge(26,105).
+edge(105,26).
+edge(26,116).
+edge(116,26).
+edge(26,120).
+edge(120,26).
+edge(26,125).
+edge(125,26).
+edge(26,133).
+edge(133,26).
+edge(26,138).
+edge(138,26).
+edge(27,41).
+edge(41,27).
+edge(27,42).
+edge(42,27).
+edge(27,52).
+edge(52,27).
+edge(27,69).
+edge(69,27).
+edge(27,72).
+edge(72,27).
+edge(27,74).
+edge(74,27).
+edge(27,76).
+edge(76,27).
+edge(27,82).
+edge(82,27).
+edge(27,92).
+edge(92,27).
+edge(27,97).
+edge(97,27).
+edge(27,101).
+edge(101,27).
+edge(27,105).
+edge(105,27).
+edge(27,112).
+edge(112,27).
+edge(27,131).
+edge(131,27).
+edge(27,142).
+edge(142,27).
+edge(28,33).
+edge(33,28).
+edge(28,34).
+edge(34,28).
+edge(28,57).
+edge(57,28).
+edge(28,67).
+edge(67,28).
+edge(28,70).
+edge(70,28).
+edge(28,90).
+edge(90,28).
+edge(28,97).
+edge(97,28).
+edge(28,98).
+edge(98,28).
+edge(28,119).
+edge(119,28).
+edge(29,46).
+edge(46,29).
+edge(29,60).
+edge(60,29).
+edge(29,66).
+edge(66,29).
+edge(29,89).
+edge(89,29).
+edge(29,100).
+edge(100,29).
+edge(29,102).
+edge(102,29).
+edge(29,114).
+edge(114,29).
+edge(29,123).
+edge(123,29).
+edge(29,150).
+edge(150,29).
+edge(30,47).
+edge(47,30).
+edge(30,49).
+edge(49,30).
+edge(30,78).
+edge(78,30).
+edge(30,94).
+edge(94,30).
+edge(30,101).
+edge(101,30).
+edge(30,103).
+edge(103,30).
+edge(30,104).
+edge(104,30).
+edge(30,111).
+edge(111,30).
+edge(30,122).
+edge(122,30).
+edge(30,138).
+edge(138,30).
+edge(30,150).
+edge(150,30).
+edge(31,33).
+edge(33,31).
+edge(31,44).
+edge(44,31).
+edge(31,47).
+edge(47,31).
+edge(31,48).
+edge(48,31).
+edge(31,55).
+edge(55,31).
+edge(31,56).
+edge(56,31).
+edge(31,58).
+edge(58,31).
+edge(31,73).
+edge(73,31).
+edge(31,81).
+edge(81,31).
+edge(31,87).
+edge(87,31).
+edge(31,92).
+edge(92,31).
+edge(31,97).
+edge(97,31).
+edge(31,99).
+edge(99,31).
+edge(31,103).
+edge(103,31).
+edge(31,105).
+edge(105,31).
+edge(31,108).
+edge(108,31).
+edge(31,114).
+edge(114,31).
+edge(31,118).
+edge(118,31).
+edge(31,123).
+edge(123,31).
+edge(31,130).
+edge(130,31).
+edge(31,136).
+edge(136,31).
+edge(31,145).
+edge(145,31).
+edge(32,43).
+edge(43,32).
+edge(32,48).
+edge(48,32).
+edge(32,52).
+edge(52,32).
+edge(32,60).
+edge(60,32).
+edge(32,65).
+edge(65,32).
+edge(32,69).
+edge(69,32).
+edge(32,75).
+edge(75,32).
+edge(32,76).
+edge(76,32).
+edge(32,83).
+edge(83,32).
+edge(32,96).
+edge(96,32).
+edge(32,108).
+edge(108,32).
+edge(32,111).
+edge(111,32).
+edge(32,134).
+edge(134,32).
+edge(32,148).
+edge(148,32).
+edge(33,60).
+edge(60,33).
+edge(33,94).
+edge(94,33).
+edge(33,116).
+edge(116,33).
+edge(33,138).
+edge(138,33).
+edge(33,142).
+edge(142,33).
+edge(33,149).
+edge(149,33).
+edge(34,45).
+edge(45,34).
+edge(34,69).
+edge(69,34).
+edge(34,77).
+edge(77,34).
+edge(34,82).
+edge(82,34).
+edge(34,84).
+edge(84,34).
+edge(34,89).
+edge(89,34).
+edge(34,101).
+edge(101,34).
+edge(34,103).
+edge(103,34).
+edge(34,124).
+edge(124,34).
+edge(34,125).
+edge(125,34).
+edge(34,143).
+edge(143,34).
+edge(34,148).
+edge(148,34).
+edge(35,48).
+edge(48,35).
+edge(35,49).
+edge(49,35).
+edge(35,60).
+edge(60,35).
+edge(35,71).
+edge(71,35).
+edge(35,93).
+edge(93,35).
+edge(35,103).
+edge(103,35).
+edge(35,104).
+edge(104,35).
+edge(35,106).
+edge(106,35).
+edge(35,107).
+edge(107,35).
+edge(35,109).
+edge(109,35).
+edge(35,119).
+edge(119,35).
+edge(35,129).
+edge(129,35).
+edge(35,133).
+edge(133,35).
+edge(35,138).
+edge(138,35).
+edge(36,39).
+edge(39,36).
+edge(36,67).
+edge(67,36).
+edge(36,77).
+edge(77,36).
+edge(36,113).
+edge(113,36).
+edge(36,126).
+edge(126,36).
+edge(36,127).
+edge(127,36).
+edge(36,129).
+edge(129,36).
+edge(36,133).
+edge(133,36).
+edge(37,39).
+edge(39,37).
+edge(37,40).
+edge(40,37).
+edge(37,55).
+edge(55,37).
+edge(37,69).
+edge(69,37).
+edge(37,70).
+edge(70,37).
+edge(37,81).
+edge(81,37).
+edge(37,89).
+edge(89,37).
+edge(37,101).
+edge(101,37).
+edge(37,115).
+edge(115,37).
+edge(37,120).
+edge(120,37).
+edge(37,123).
+edge(123,37).
+edge(37,128).
+edge(128,37).
+edge(37,130).
+edge(130,37).
+edge(38,48).
+edge(48,38).
+edge(38,63).
+edge(63,38).
+edge(38,70).
+edge(70,38).
+edge(38,72).
+edge(72,38).
+edge(38,85).
+edge(85,38).
+edge(38,112).
+edge(112,38).
+edge(38,132).
+edge(132,38).
+edge(38,143).
+edge(143,38).
+edge(39,48).
+edge(48,39).
+edge(39,73).
+edge(73,39).
+edge(39,82).
+edge(82,39).
+edge(39,90).
+edge(90,39).
+edge(39,93).
+edge(93,39).
+edge(39,101).
+edge(101,39).
+edge(39,112).
+edge(112,39).
+edge(39,115).
+edge(115,39).
+edge(39,130).
+edge(130,39).
+edge(39,135).
+edge(135,39).
+edge(39,136).
+edge(136,39).
+edge(39,137).
+edge(137,39).
+edge(40,61).
+edge(61,40).
+edge(40,78).
+edge(78,40).
+edge(40,101).
+edge(101,40).
+edge(40,104).
+edge(104,40).
+edge(40,141).
+edge(141,40).
+edge(41,43).
+edge(43,41).
+edge(41,50).
+edge(50,41).
+edge(41,52).
+edge(52,41).
+edge(41,62).
+edge(62,41).
+edge(41,68).
+edge(68,41).
+edge(41,69).
+edge(69,41).
+edge(41,70).
+edge(70,41).
+edge(41,71).
+edge(71,41).
+edge(41,102).
+edge(102,41).
+edge(41,111).
+edge(111,41).
+edge(41,131).
+edge(131,41).
+edge(42,45).
+edge(45,42).
+edge(42,58).
+edge(58,42).
+edge(42,86).
+edge(86,42).
+edge(42,88).
+edge(88,42).
+edge(42,91).
+edge(91,42).
+edge(42,92).
+edge(92,42).
+edge(42,95).
+edge(95,42).
+edge(42,105).
+edge(105,42).
+edge(42,113).
+edge(113,42).
+edge(42,119).
+edge(119,42).
+edge(42,123).
+edge(123,42).
+edge(42,128).
+edge(128,42).
+edge(42,143).
+edge(143,42).
+edge(42,147).
+edge(147,42).
+edge(43,50).
+edge(50,43).
+edge(43,55).
+edge(55,43).
+edge(43,58).
+edge(58,43).
+edge(43,65).
+edge(65,43).
+edge(43,69).
+edge(69,43).
+edge(43,78).
+edge(78,43).
+edge(43,89).
+edge(89,43).
+edge(43,90).
+edge(90,43).
+edge(43,96).
+edge(96,43).
+edge(43,116).
+edge(116,43).
+edge(43,130).
+edge(130,43).
+edge(43,133).
+edge(133,43).
+edge(43,140).
+edge(140,43).
+edge(43,142).
+edge(142,43).
+edge(43,144).
+edge(144,43).
+edge(43,147).
+edge(147,43).
+edge(44,47).
+edge(47,44).
+edge(44,54).
+edge(54,44).
+edge(44,56).
+edge(56,44).
+edge(44,58).
+edge(58,44).
+edge(44,66).
+edge(66,44).
+edge(44,77).
+edge(77,44).
+edge(44,83).
+edge(83,44).
+edge(44,84).
+edge(84,44).
+edge(44,99).
+edge(99,44).
+edge(44,101).
+edge(101,44).
+edge(44,113).
+edge(113,44).
+edge(44,114).
+edge(114,44).
+edge(44,117).
+edge(117,44).
+edge(44,131).
+edge(131,44).
+edge(44,138).
+edge(138,44).
+edge(44,150).
+edge(150,44).
+edge(45,52).
+edge(52,45).
+edge(45,57).
+edge(57,45).
+edge(45,62).
+edge(62,45).
+edge(45,74).
+edge(74,45).
+edge(45,92).
+edge(92,45).
+edge(45,109).
+edge(109,45).
+edge(45,113).
+edge(113,45).
+edge(45,120).
+edge(120,45).
+edge(45,121).
+edge(121,45).
+edge(45,127).
+edge(127,45).
+edge(45,132).
+edge(132,45).
+edge(45,141).
+edge(141,45).
+edge(45,146).
+edge(146,45).
+edge(45,147).
+edge(147,45).
+edge(45,150).
+edge(150,45).
+edge(46,49).
+edge(49,46).
+edge(46,71).
+edge(71,46).
+edge(46,78).
+edge(78,46).
+edge(46,81).
+edge(81,46).
+edge(46,89).
+edge(89,46).
+edge(46,120).
+edge(120,46).
+edge(46,122).
+edge(122,46).
+edge(46,126).
+edge(126,46).
+edge(46,129).
+edge(129,46).
+edge(46,135).
+edge(135,46).
+edge(46,149).
+edge(149,46).
+edge(47,54).
+edge(54,47).
+edge(47,57).
+edge(57,47).
+edge(47,60).
+edge(60,47).
+edge(47,69).
+edge(69,47).
+edge(47,70).
+edge(70,47).
+edge(47,81).
+edge(81,47).
+edge(47,107).
+edge(107,47).
+edge(47,116).
+edge(116,47).
+edge(47,129).
+edge(129,47).
+edge(47,130).
+edge(130,47).
+edge(47,131).
+edge(131,47).
+edge(47,149).
+edge(149,47).
+edge(48,51).
+edge(51,48).
+edge(48,78).
+edge(78,48).
+edge(48,79).
+edge(79,48).
+edge(48,89).
+edge(89,48).
+edge(48,90).
+edge(90,48).
+edge(48,91).
+edge(91,48).
+edge(48,93).
+edge(93,48).
+edge(48,111).
+edge(111,48).
+edge(48,114).
+edge(114,48).
+edge(48,125).
+edge(125,48).
+edge(48,131).
+edge(131,48).
+edge(48,141).
+edge(141,48).
+edge(48,142).
+edge(142,48).
+edge(49,79).
+edge(79,49).
+edge(49,93).
+edge(93,49).
+edge(49,97).
+edge(97,49).
+edge(49,113).
+edge(113,49).
+edge(49,115).
+edge(115,49).
+edge(49,118).
+edge(118,49).
+edge(49,139).
+edge(139,49).
+edge(49,140).
+edge(140,49).
+edge(49,143).
+edge(143,49).
+edge(49,150).
+edge(150,49).
+edge(50,58).
+edge(58,50).
+edge(50,89).
+edge(89,50).
+edge(50,96).
+edge(96,50).
+edge(50,107).
+edge(107,50).
+edge(50,115).
+edge(115,50).
+edge(50,116).
+edge(116,50).
+edge(50,126).
+edge(126,50).
+edge(50,149).
+edge(149,50).
+edge(51,93).
+edge(93,51).
+edge(51,99).
+edge(99,51).
+edge(51,108).
+edge(108,51).
+edge(51,115).
+edge(115,51).
+edge(51,134).
+edge(134,51).
+edge(51,135).
+edge(135,51).
+edge(51,140).
+edge(140,51).
+edge(52,72).
+edge(72,52).
+edge(52,74).
+edge(74,52).
+edge(52,78).
+edge(78,52).
+edge(52,104).
+edge(104,52).
+edge(52,108).
+edge(108,52).
+edge(52,111).
+edge(111,52).
+edge(52,143).
+edge(143,52).
+edge(52,145).
+edge(145,52).
+edge(52,146).
+edge(146,52).
+edge(53,67).
+edge(67,53).
+edge(53,71).
+edge(71,53).
+edge(53,88).
+edge(88,53).
+edge(53,92).
+edge(92,53).
+edge(53,93).
+edge(93,53).
+edge(53,118).
+edge(118,53).
+edge(53,123).
+edge(123,53).
+edge(53,124).
+edge(124,53).
+edge(53,131).
+edge(131,53).
+edge(53,143).
+edge(143,53).
+edge(54,71).
+edge(71,54).
+edge(54,73).
+edge(73,54).
+edge(54,83).
+edge(83,54).
+edge(54,94).
+edge(94,54).
+edge(54,97).
+edge(97,54).
+edge(54,149).
+edge(149,54).
+edge(55,58).
+edge(58,55).
+edge(55,62).
+edge(62,55).
+edge(55,63).
+edge(63,55).
+edge(55,67).
+edge(67,55).
+edge(55,80).
+edge(80,55).
+edge(55,83).
+edge(83,55).
+edge(55,91).
+edge(91,55).
+edge(55,103).
+edge(103,55).
+edge(55,122).
+edge(122,55).
+edge(55,125).
+edge(125,55).
+edge(55,138).
+edge(138,55).
+edge(55,141).
+edge(141,55).
+edge(55,146).
+edge(146,55).
+edge(56,58).
+edge(58,56).
+edge(56,81).
+edge(81,56).
+edge(56,84).
+edge(84,56).
+edge(56,106).
+edge(106,56).
+edge(56,122).
+edge(122,56).
+edge(56,126).
+edge(126,56).
+edge(57,58).
+edge(58,57).
+edge(57,61).
+edge(61,57).
+edge(57,73).
+edge(73,57).
+edge(57,75).
+edge(75,57).
+edge(57,77).
+edge(77,57).
+edge(57,95).
+edge(95,57).
+edge(57,117).
+edge(117,57).
+edge(57,121).
+edge(121,57).
+edge(57,127).
+edge(127,57).
+edge(57,131).
+edge(131,57).
+edge(57,132).
+edge(132,57).
+edge(58,73).
+edge(73,58).
+edge(58,76).
+edge(76,58).
+edge(58,83).
+edge(83,58).
+edge(58,104).
+edge(104,58).
+edge(58,118).
+edge(118,58).
+edge(58,128).
+edge(128,58).
+edge(58,133).
+edge(133,58).
+edge(58,141).
+edge(141,58).
+edge(58,142).
+edge(142,58).
+edge(59,63).
+edge(63,59).
+edge(59,70).
+edge(70,59).
+edge(59,73).
+edge(73,59).
+edge(59,80).
+edge(80,59).
+edge(59,93).
+edge(93,59).
+edge(59,102).
+edge(102,59).
+edge(59,105).
+edge(105,59).
+edge(59,137).
+edge(137,59).
+edge(59,141).
+edge(141,59).
+edge(59,143).
+edge(143,59).
+edge(59,148).
+edge(148,59).
+edge(60,76).
+edge(76,60).
+edge(60,84).
+edge(84,60).
+edge(60,100).
+edge(100,60).
+edge(60,105).
+edge(105,60).
+edge(60,110).
+edge(110,60).
+edge(60,122).
+edge(122,60).
+edge(60,126).
+edge(126,60).
+edge(60,131).
+edge(131,60).
+edge(60,134).
+edge(134,60).
+edge(60,137).
+edge(137,60).
+edge(61,73).
+edge(73,61).
+edge(61,78).
+edge(78,61).
+edge(61,101).
+edge(101,61).
+edge(61,107).
+edge(107,61).
+edge(61,118).
+edge(118,61).
+edge(61,120).
+edge(120,61).
+edge(61,121).
+edge(121,61).
+edge(61,137).
+edge(137,61).
+edge(61,138).
+edge(138,61).
+edge(62,65).
+edge(65,62).
+edge(62,66).
+edge(66,62).
+edge(62,72).
+edge(72,62).
+edge(62,94).
+edge(94,62).
+edge(62,102).
+edge(102,62).
+edge(62,111).
+edge(111,62).
+edge(62,127).
+edge(127,62).
+edge(62,133).
+edge(133,62).
+edge(62,149).
+edge(149,62).
+edge(63,72).
+edge(72,63).
+edge(63,73).
+edge(73,63).
+edge(63,81).
+edge(81,63).
+edge(63,82).
+edge(82,63).
+edge(63,90).
+edge(90,63).
+edge(63,99).
+edge(99,63).
+edge(63,103).
+edge(103,63).
+edge(63,104).
+edge(104,63).
+edge(63,105).
+edge(105,63).
+edge(63,107).
+edge(107,63).
+edge(63,110).
+edge(110,63).
+edge(63,119).
+edge(119,63).
+edge(63,120).
+edge(120,63).
+edge(63,130).
+edge(130,63).
+edge(63,140).
+edge(140,63).
+edge(63,141).
+edge(141,63).
+edge(63,142).
+edge(142,63).
+edge(64,97).
+edge(97,64).
+edge(64,115).
+edge(115,64).
+edge(64,116).
+edge(116,64).
+edge(64,117).
+edge(117,64).
+edge(64,123).
+edge(123,64).
+edge(64,133).
+edge(133,64).
+edge(64,148).
+edge(148,64).
+edge(65,73).
+edge(73,65).
+edge(65,79).
+edge(79,65).
+edge(65,86).
+edge(86,65).
+edge(65,100).
+edge(100,65).
+edge(65,112).
+edge(112,65).
+edge(65,120).
+edge(120,65).
+edge(65,123).
+edge(123,65).
+edge(65,126).
+edge(126,65).
+edge(65,127).
+edge(127,65).
+edge(66,83).
+edge(83,66).
+edge(66,93).
+edge(93,66).
+edge(66,102).
+edge(102,66).
+edge(66,119).
+edge(119,66).
+edge(66,121).
+edge(121,66).
+edge(66,143).
+edge(143,66).
+edge(66,146).
+edge(146,66).
+edge(67,76).
+edge(76,67).
+edge(67,79).
+edge(79,67).
+edge(67,85).
+edge(85,67).
+edge(67,87).
+edge(87,67).
+edge(67,98).
+edge(98,67).
+edge(67,100).
+edge(100,67).
+edge(67,111).
+edge(111,67).
+edge(67,113).
+edge(113,67).
+edge(67,135).
+edge(135,67).
+edge(67,143).
+edge(143,67).
+edge(67,144).
+edge(144,67).
+edge(67,148).
+edge(148,67).
+edge(68,87).
+edge(87,68).
+edge(68,88).
+edge(88,68).
+edge(68,91).
+edge(91,68).
+edge(68,92).
+edge(92,68).
+edge(68,94).
+edge(94,68).
+edge(68,97).
+edge(97,68).
+edge(68,113).
+edge(113,68).
+edge(68,127).
+edge(127,68).
+edge(68,140).
+edge(140,68).
+edge(68,145).
+edge(145,68).
+edge(68,147).
+edge(147,68).
+edge(68,148).
+edge(148,68).
+edge(68,149).
+edge(149,68).
+edge(68,150).
+edge(150,68).
+edge(69,73).
+edge(73,69).
+edge(69,94).
+edge(94,69).
+edge(69,98).
+edge(98,69).
+edge(69,106).
+edge(106,69).
+edge(69,119).
+edge(119,69).
+edge(69,121).
+edge(121,69).
+edge(69,126).
+edge(126,69).
+edge(70,76).
+edge(76,70).
+edge(70,96).
+edge(96,70).
+edge(70,108).
+edge(108,70).
+edge(70,111).
+edge(111,70).
+edge(70,119).
+edge(119,70).
+edge(70,142).
+edge(142,70).
+edge(70,145).
+edge(145,70).
+edge(71,73).
+edge(73,71).
+edge(71,82).
+edge(82,71).
+edge(71,86).
+edge(86,71).
+edge(71,96).
+edge(96,71).
+edge(71,126).
+edge(126,71).
+edge(71,133).
+edge(133,71).
+edge(71,146).
+edge(146,71).
+edge(71,148).
+edge(148,71).
+edge(72,84).
+edge(84,72).
+edge(72,91).
+edge(91,72).
+edge(72,98).
+edge(98,72).
+edge(72,101).
+edge(101,72).
+edge(72,117).
+edge(117,72).
+edge(72,118).
+edge(118,72).
+edge(72,119).
+edge(119,72).
+edge(72,124).
+edge(124,72).
+edge(72,135).
+edge(135,72).
+edge(72,149).
+edge(149,72).
+edge(73,80).
+edge(80,73).
+edge(73,81).
+edge(81,73).
+edge(73,89).
+edge(89,73).
+edge(73,100).
+edge(100,73).
+edge(74,81).
+edge(81,74).
+edge(74,83).
+edge(83,74).
+edge(74,107).
+edge(107,74).
+edge(74,109).
+edge(109,74).
+edge(74,122).
+edge(122,74).
+edge(74,126).
+edge(126,74).
+edge(74,129).
+edge(129,74).
+edge(74,130).
+edge(130,74).
+edge(74,131).
+edge(131,74).
+edge(74,136).
+edge(136,74).
+edge(74,139).
+edge(139,74).
+edge(74,141).
+edge(141,74).
+edge(75,89).
+edge(89,75).
+edge(75,97).
+edge(97,75).
+edge(75,101).
+edge(101,75).
+edge(75,108).
+edge(108,75).
+edge(75,110).
+edge(110,75).
+edge(75,111).
+edge(111,75).
+edge(75,118).
+edge(118,75).
+edge(75,122).
+edge(122,75).
+edge(75,142).
+edge(142,75).
+edge(76,89).
+edge(89,76).
+edge(76,96).
+edge(96,76).
+edge(76,102).
+edge(102,76).
+edge(77,94).
+edge(94,77).
+edge(77,99).
+edge(99,77).
+edge(77,120).
+edge(120,77).
+edge(77,133).
+edge(133,77).
+edge(78,104).
+edge(104,78).
+edge(78,113).
+edge(113,78).
+edge(78,124).
+edge(124,78).
+edge(78,130).
+edge(130,78).
+edge(78,136).
+edge(136,78).
+edge(78,137).
+edge(137,78).
+edge(78,144).
+edge(144,78).
+edge(78,148).
+edge(148,78).
+edge(79,86).
+edge(86,79).
+edge(79,88).
+edge(88,79).
+edge(79,95).
+edge(95,79).
+edge(79,137).
+edge(137,79).
+edge(79,138).
+edge(138,79).
+edge(79,145).
+edge(145,79).
+edge(80,82).
+edge(82,80).
+edge(80,83).
+edge(83,80).
+edge(80,110).
+edge(110,80).
+edge(80,120).
+edge(120,80).
+edge(81,86).
+edge(86,81).
+edge(81,107).
+edge(107,81).
+edge(81,121).
+edge(121,81).
+edge(81,133).
+edge(133,81).
+edge(81,138).
+edge(138,81).
+edge(81,141).
+edge(141,81).
+edge(81,143).
+edge(143,81).
+edge(82,117).
+edge(117,82).
+edge(82,118).
+edge(118,82).
+edge(82,122).
+edge(122,82).
+edge(82,131).
+edge(131,82).
+edge(82,133).
+edge(133,82).
+edge(82,146).
+edge(146,82).
+edge(83,89).
+edge(89,83).
+edge(83,97).
+edge(97,83).
+edge(83,98).
+edge(98,83).
+edge(83,105).
+edge(105,83).
+edge(83,124).
+edge(124,83).
+edge(84,85).
+edge(85,84).
+edge(84,94).
+edge(94,84).
+edge(84,99).
+edge(99,84).
+edge(84,105).
+edge(105,84).
+edge(84,109).
+edge(109,84).
+edge(84,112).
+edge(112,84).
+edge(84,122).
+edge(122,84).
+edge(84,140).
+edge(140,84).
+edge(84,150).
+edge(150,84).
+edge(85,113).
+edge(113,85).
+edge(85,114).
+edge(114,85).
+edge(85,119).
+edge(119,85).
+edge(85,122).
+edge(122,85).
+edge(85,127).
+edge(127,85).
+edge(86,111).
+edge(111,86).
+edge(86,113).
+edge(113,86).
+edge(86,128).
+edge(128,86).
+edge(86,131).
+edge(131,86).
+edge(86,133).
+edge(133,86).
+edge(86,145).
+edge(145,86).
+edge(87,88).
+edge(88,87).
+edge(87,107).
+edge(107,87).
+edge(87,111).
+edge(111,87).
+edge(87,119).
+edge(119,87).
+edge(87,139).
+edge(139,87).
+edge(87,144).
+edge(144,87).
+edge(87,148).
+edge(148,87).
+edge(88,92).
+edge(92,88).
+edge(88,95).
+edge(95,88).
+edge(88,115).
+edge(115,88).
+edge(88,118).
+edge(118,88).
+edge(88,142).
+edge(142,88).
+edge(88,143).
+edge(143,88).
+edge(88,146).
+edge(146,88).
+edge(89,99).
+edge(99,89).
+edge(89,104).
+edge(104,89).
+edge(89,109).
+edge(109,89).
+edge(89,122).
+edge(122,89).
+edge(89,125).
+edge(125,89).
+edge(89,150).
+edge(150,89).
+edge(90,96).
+edge(96,90).
+edge(90,98).
+edge(98,90).
+edge(90,102).
+edge(102,90).
+edge(90,103).
+edge(103,90).
+edge(90,105).
+edge(105,90).
+edge(90,113).
+edge(113,90).
+edge(90,138).
+edge(138,90).
+edge(91,106).
+edge(106,91).
+edge(91,113).
+edge(113,91).
+edge(91,115).
+edge(115,91).
+edge(91,118).
+edge(118,91).
+edge(91,121).
+edge(121,91).
+edge(91,125).
+edge(125,91).
+edge(91,129).
+edge(129,91).
+edge(91,144).
+edge(144,91).
+edge(92,103).
+edge(103,92).
+edge(92,106).
+edge(106,92).
+edge(92,110).
+edge(110,92).
+edge(92,112).
+edge(112,92).
+edge(92,150).
+edge(150,92).
+edge(93,96).
+edge(96,93).
+edge(93,97).
+edge(97,93).
+edge(93,103).
+edge(103,93).
+edge(93,120).
+edge(120,93).
+edge(94,105).
+edge(105,94).
+edge(94,111).
+edge(111,94).
+edge(94,120).
+edge(120,94).
+edge(94,126).
+edge(126,94).
+edge(94,141).
+edge(141,94).
+edge(94,145).
+edge(145,94).
+edge(95,109).
+edge(109,95).
+edge(95,111).
+edge(111,95).
+edge(95,128).
+edge(128,95).
+edge(95,134).
+edge(134,95).
+edge(95,141).
+edge(141,95).
+edge(95,143).
+edge(143,95).
+edge(95,150).
+edge(150,95).
+edge(96,113).
+edge(113,96).
+edge(96,139).
+edge(139,96).
+edge(96,148).
+edge(148,96).
+edge(97,100).
+edge(100,97).
+edge(97,104).
+edge(104,97).
+edge(97,105).
+edge(105,97).
+edge(97,116).
+edge(116,97).
+edge(97,120).
+edge(120,97).
+edge(97,125).
+edge(125,97).
+edge(97,140).
+edge(140,97).
+edge(98,142).
+edge(142,98).
+edge(98,145).
+edge(145,98).
+edge(99,104).
+edge(104,99).
+edge(99,136).
+edge(136,99).
+edge(99,147).
+edge(147,99).
+edge(100,105).
+edge(105,100).
+edge(100,110).
+edge(110,100).
+edge(100,119).
+edge(119,100).
+edge(100,142).
+edge(142,100).
+edge(101,117).
+edge(117,101).
+edge(101,131).
+edge(131,101).
+edge(101,132).
+edge(132,101).
+edge(101,147).
+edge(147,101).
+edge(102,106).
+edge(106,102).
+edge(102,111).
+edge(111,102).
+edge(102,114).
+edge(114,102).
+edge(102,125).
+edge(125,102).
+edge(102,130).
+edge(130,102).
+edge(102,142).
+edge(142,102).
+edge(102,148).
+edge(148,102).
+edge(102,149).
+edge(149,102).
+edge(103,104).
+edge(104,103).
+edge(103,106).
+edge(106,103).
+edge(103,110).
+edge(110,103).
+edge(103,112).
+edge(112,103).
+edge(103,119).
+edge(119,103).
+edge(103,139).
+edge(139,103).
+edge(103,147).
+edge(147,103).
+edge(104,128).
+edge(128,104).
+edge(104,143).
+edge(143,104).
+edge(105,111).
+edge(111,105).
+edge(105,124).
+edge(124,105).
+edge(105,139).
+edge(139,105).
+edge(105,141).
+edge(141,105).
+edge(106,108).
+edge(108,106).
+edge(106,117).
+edge(117,106).
+edge(106,128).
+edge(128,106).
+edge(106,129).
+edge(129,106).
+edge(106,133).
+edge(133,106).
+edge(106,135).
+edge(135,106).
+edge(106,139).
+edge(139,106).
+edge(107,109).
+edge(109,107).
+edge(107,122).
+edge(122,107).
+edge(107,129).
+edge(129,107).
+edge(107,131).
+edge(131,107).
+edge(108,111).
+edge(111,108).
+edge(108,112).
+edge(112,108).
+edge(108,113).
+edge(113,108).
+edge(108,120).
+edge(120,108).
+edge(108,122).
+edge(122,108).
+edge(109,127).
+edge(127,109).
+edge(109,140).
+edge(140,109).
+edge(109,141).
+edge(141,109).
+edge(109,149).
+edge(149,109).
+edge(110,115).
+edge(115,110).
+edge(110,118).
+edge(118,110).
+edge(110,128).
+edge(128,110).
+edge(110,131).
+edge(131,110).
+edge(110,132).
+edge(132,110).
+edge(110,136).
+edge(136,110).
+edge(110,142).
+edge(142,110).
+edge(110,149).
+edge(149,110).
+edge(111,119).
+edge(119,111).
+edge(111,143).
+edge(143,111).
+edge(112,115).
+edge(115,112).
+edge(112,122).
+edge(122,112).
+edge(112,129).
+edge(129,112).
+edge(112,144).
+edge(144,112).
+edge(113,118).
+edge(118,113).
+edge(113,124).
+edge(124,113).
+edge(113,135).
+edge(135,113).
+edge(113,138).
+edge(138,113).
+edge(113,145).
+edge(145,113).
+edge(114,123).
+edge(123,114).
+edge(114,144).
+edge(144,114).
+edge(115,119).
+edge(119,115).
+edge(115,129).
+edge(129,115).
+edge(115,132).
+edge(132,115).
+edge(115,134).
+edge(134,115).
+edge(115,137).
+edge(137,115).
+edge(115,148).
+edge(148,115).
+edge(116,117).
+edge(117,116).
+edge(116,118).
+edge(118,116).
+edge(116,125).
+edge(125,116).
+edge(116,143).
+edge(143,116).
+edge(117,118).
+edge(118,117).
+edge(117,134).
+edge(134,117).
+edge(117,143).
+edge(143,117).
+edge(118,122).
+edge(122,118).
+edge(118,138).
+edge(138,118).
+edge(118,147).
+edge(147,118).
+edge(118,148).
+edge(148,118).
+edge(119,132).
+edge(132,119).
+edge(119,135).
+edge(135,119).
+edge(120,121).
+edge(121,120).
+edge(120,122).
+edge(122,120).
+edge(120,127).
+edge(127,120).
+edge(120,130).
+edge(130,120).
+edge(121,125).
+edge(125,121).
+edge(121,134).
+edge(134,121).
+edge(122,132).
+edge(132,122).
+edge(123,125).
+edge(125,123).
+edge(123,128).
+edge(128,123).
+edge(123,132).
+edge(132,123).
+edge(123,137).
+edge(137,123).
+edge(124,125).
+edge(125,124).
+edge(124,139).
+edge(139,124).
+edge(125,129).
+edge(129,125).
+edge(125,139).
+edge(139,125).
+edge(125,142).
+edge(142,125).
+edge(126,130).
+edge(130,126).
+edge(126,145).
+edge(145,126).
+edge(126,149).
+edge(149,126).
+edge(127,133).
+edge(133,127).
+edge(127,145).
+edge(145,127).
+edge(128,130).
+edge(130,128).
+edge(128,148).
+edge(148,128).
+edge(129,147).
+edge(147,129).
+edge(129,149).
+edge(149,129).
+edge(130,132).
+edge(132,130).
+edge(130,135).
+edge(135,130).
+edge(130,138).
+edge(138,130).
+edge(130,144).
+edge(144,130).
+edge(130,148).
+edge(148,130).
+edge(131,132).
+edge(132,131).
+edge(131,135).
+edge(135,131).
+edge(131,146).
+edge(146,131).
+edge(131,149).
+edge(149,131).
+edge(132,134).
+edge(134,132).
+edge(132,141).
+edge(141,132).
+edge(133,144).
+edge(144,133).
+edge(133,145).
+edge(145,133).
+edge(135,138).
+edge(138,135).
+edge(135,145).
+edge(145,135).
+edge(141,145).
+edge(145,141).
+edge(142,148).
+edge(148,142).
+edge(142,150).
+edge(150,142).
+edge(144,147).
+edge(147,144).
+edge(147,148).
+edge(148,147).
+
diff --git a/examples/clingo/expansion/PartnerUnits/encodings/encoding.lp b/examples/clingo/expansion/PartnerUnits/encodings/encoding.lp
new file mode 100644
index 0000000..9fa907f
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/encodings/encoding.lp
@@ -0,0 +1,66 @@
+#program base.
+
+stat(T,1,1) :- object(T,1).
+
+#program object(x,k).
+#external assigned(T,x,1) : item(T,x).
+
+item(T,x) :- object(T,x).
+:- item(T,x), not assigned(T,x,1).
+
+stat(T,x,I+1) :- item(T,x), follow(T,X,T,x), stat(T,X,I).
+
+next(T,x,U,k) :- item(T,x), unit(U), U <= I : stat(T,x,I).
+
+#program horizon(u,k).
+
+unit(u).
+pair(1..u-1,u).
+
+next(u,k).
+next(T,X,u,k) :- item(T,X), u <= I : stat(T,X,I).
+
+conn(u-1,u-2,u) :- 2 < u.
+conn(u,U,U+1)   :- unit(U), U+1 < u.
+conn(U,u-1,u)   :- unit(U), U < u-1.
+
+prop(U,u-M,M,k) :- unit(U), maxPU(M), U < u-M.
+prop(U,u-N,M,k) :- unit(U), maxPU(M), N = M+1, u-M <= U, N < u.
+prop(u,U-1,M,k) :- prop(u,U,M,k), maxPU(M), 1 < U.
+prop(U,W,M-1,k) :- conn(U,V,W), prop(U,V,M,k), 1 < M.
+
+#program expand(k).
+#external assigned(T,X,U+1) : next(T,X,U,k), stat(T,X,I), U < I.
+#external assigned(T,X,U+1) : next(T,X,U,k), not stat(T,1,1).
+#external partner(U,V,k+1) : pair(U,V).
+
+{ assign(T,X,U) } :- next(T,X,U,k).
+
+assigned(T,X,U) :- assign(T,X,U), next(T,X,U,k).
+assigned(T,X,U) :- assigned(T,X,U+1), next(T,X,U,k).
+:- assign(T,X,U-1), assigned(T,X,U), next(T,X,U,k).
+
+left(T,Y,U,2) :- follow(T,X,T,Y), follow(T,Y,T,Z), assign(T,X,U), next(T,Z,U,k).
+left(T,Y,U,2) :- follow(T,X,T,Y), follow(T,Y,T,Z), left(T,X,U,2), next(T,Z,U,k).
+left(T,Y,U,1) :- follow(T,X,T,Y), left(T,X,U,2), assign(T,X,U), next(T,Y,U,k).
+left(T,Y,U,1) :- follow(T,X,T,Y), left(T,X,U,1), next(T,Y,U,k).
+:- left(T,X,U,1), assign(T,X,U), next(T,X,U,k).
+
+part(-T,Y,U) :- relate(T,X,-T,Y), assign(T,X,U), next(-T,Y,1,k).
+part(-T,Y,U) :- relate(T,X,-T,Y), assign(T,X,U), next(U,k), item(-T,Y), X < Y.
+
+partner(U,V,k) :- partner(U,V,k+1), not next(V,k).
+partner(U,V,k) :- part(T,X,U), assign(T,X,V), pair(U,V), next(T,X,1,k).
+partner(U,V,k) :- assign(T,X,U), part(T,X,V), pair(U,V), next(T,X,1,k).
+
+partner(U,V) :- partner(U,V,k+1), next(V,k).
+partner(U,V) :- part(T,X,U), assign(T,X,V), pair(U,V), next(V,k).
+partner(U,V) :- assign(T,X,U), part(T,X,V), pair(U,V), next(V,k).
+partner(V,U) :- partner(U,V), next(V,k).
+
+prop(U,W,M)   :- conn(U,V,W), partner(U,V), prop(U,V,M,k), maxPU(M).
+prop(U,W,M-1) :- conn(U,V,W), partner(U,V), prop(U,V,M-1,k), prop(U,V,M).
+prop(U,W,M)   :- conn(U,V,W), prop(U,V,M), prop(U,V,M,k).
+:- conn(U,V,W), prop(U,W,1), partner(U,W), prop(U,V,1,k).
+
+#show assign/3.
diff --git a/examples/clingo/expansion/PartnerUnits/instances/100-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/100-partner_units-100-0.lp
new file mode 100644
index 0000000..89f04a4
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/100-partner_units-100-0.lp
@@ -0,0 +1,744 @@
+maxPU(4).
+#const n=178.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(-1,7,-1,9).
+follow(-1,172,-1,173).
+follow(-1,33,-1,35).
+follow(-1,129,-1,131).
+follow(-1,176,-1,177).
+follow(-1,159,-1,160).
+follow(-1,75,-1,77).
+follow(-1,171,-1,172).
+follow(-1,63,-1,65).
+follow(-1,115,-1,117).
+follow(-1,69,-1,71).
+follow(-1,135,-1,137).
+follow(-1,168,-1,169).
+follow(-1,83,-1,85).
+follow(-1,153,-1,155).
+follow(-1,61,-1,63).
+follow(-1,125,-1,127).
+follow(-1,47,-1,49).
+follow(-1,37,-1,39).
+follow(-1,117,-1,119).
+follow(-1,151,-1,153).
+follow(-1,160,-1,161).
+follow(-1,161,-1,162).
+follow(-1,43,-1,45).
+follow(-1,105,-1,107).
+follow(-1,113,-1,115).
+follow(-1,39,-1,41).
+follow(-1,103,-1,105).
+follow(-1,21,-1,23).
+follow(-1,17,-1,19).
+follow(-1,145,-1,147).
+follow(-1,89,-1,91).
+follow(-1,93,-1,95).
+follow(-1,23,-1,25).
+follow(-1,164,-1,165).
+follow(-1,95,-1,97).
+follow(-1,87,-1,89).
+follow(-1,170,-1,171).
+follow(-1,57,-1,59).
+follow(-1,175,-1,176).
+follow(-1,157,-1,158).
+follow(-1,166,-1,167).
+follow(-1,163,-1,164).
+follow(-1,51,-1,53).
+follow(-1,35,-1,37).
+follow(-1,49,-1,51).
+follow(-1,149,-1,151).
+follow(-1,55,-1,57).
+follow(-1,141,-1,143).
+follow(-1,11,-1,13).
+follow(-1,121,-1,123).
+follow(-1,97,-1,99).
+follow(-1,29,-1,31).
+follow(-1,99,-1,101).
+follow(-1,73,-1,75).
+follow(-1,65,-1,67).
+follow(-1,107,-1,109).
+follow(-1,173,-1,174).
+follow(-1,81,-1,83).
+follow(-1,177,-1,178).
+follow(-1,25,-1,27).
+follow(-1,162,-1,163).
+follow(-1,91,-1,93).
+follow(-1,143,-1,145).
+follow(-1,5,-1,7).
+follow(-1,111,-1,113).
+follow(-1,41,-1,43).
+follow(-1,137,-1,139).
+follow(-1,13,-1,15).
+follow(-1,109,-1,111).
+follow(-1,27,-1,29).
+follow(-1,174,-1,175).
+follow(-1,169,-1,170).
+follow(-1,147,-1,149).
+follow(-1,165,-1,166).
+follow(-1,53,-1,55).
+follow(-1,77,-1,79).
+follow(-1,19,-1,21).
+follow(-1,71,-1,73).
+follow(-1,31,-1,33).
+follow(-1,45,-1,47).
+follow(-1,127,-1,129).
+follow(-1,119,-1,121).
+follow(-1,85,-1,87).
+follow(-1,15,-1,17).
+follow(-1,133,-1,135).
+follow(-1,155,-1,157).
+follow(-1,59,-1,61).
+follow(-1,167,-1,168).
+follow(-1,9,-1,11).
+follow(-1,101,-1,103).
+follow(-1,123,-1,125).
+follow(-1,67,-1,69).
+follow(-1,1,-1,3).
+follow(-1,131,-1,133).
+follow(-1,79,-1,81).
+follow(-1,139,-1,141).
+follow(-1,158,-1,159).
+follow(-1,3,-1,5).
+relate(1,2,-1,9).
+relate(1,2,-1,173).
+relate(1,2,-1,35).
+relate(1,4,-1,173).
+relate(1,4,-1,131).
+relate(1,6,-1,131).
+relate(1,6,-1,177).
+relate(1,8,-1,177).
+relate(1,8,-1,160).
+relate(1,8,-1,77).
+relate(1,10,-1,160).
+relate(1,10,-1,172).
+relate(1,10,-1,65).
+relate(1,12,-1,172).
+relate(1,12,-1,117).
+relate(1,12,-1,71).
+relate(1,14,-1,117).
+relate(1,14,-1,137).
+relate(1,16,-1,169).
+relate(1,18,-1,35).
+relate(1,18,-1,85).
+relate(1,18,-1,155).
+relate(1,20,-1,85).
+relate(1,20,-1,63).
+relate(1,22,-1,63).
+relate(1,24,-1,77).
+relate(1,24,-1,127).
+relate(1,26,-1,65).
+relate(1,26,-1,127).
+relate(1,26,-1,49).
+relate(1,26,-1,39).
+relate(1,28,-1,71).
+relate(1,28,-1,49).
+relate(1,28,-1,119).
+relate(1,28,-1,153).
+relate(1,30,-1,137).
+relate(1,30,-1,119).
+relate(1,30,-1,161).
+relate(1,32,-1,169).
+relate(1,32,-1,161).
+relate(1,34,-1,155).
+relate(1,36,-1,162).
+relate(1,36,-1,45).
+relate(1,38,-1,162).
+relate(1,38,-1,107).
+relate(1,40,-1,107).
+relate(1,40,-1,115).
+relate(1,42,-1,39).
+relate(1,42,-1,115).
+relate(1,42,-1,41).
+relate(1,42,-1,105).
+relate(1,44,-1,153).
+relate(1,44,-1,41).
+relate(1,44,-1,23).
+relate(1,46,-1,23).
+relate(1,46,-1,19).
+relate(1,48,-1,147).
+relate(1,48,-1,91).
+relate(1,50,-1,45).
+relate(1,50,-1,147).
+relate(1,50,-1,95).
+relate(1,52,-1,95).
+relate(1,52,-1,25).
+relate(1,52,-1,165).
+relate(1,54,-1,25).
+relate(1,54,-1,97).
+relate(1,54,-1,89).
+relate(1,56,-1,105).
+relate(1,56,-1,97).
+relate(1,56,-1,171).
+relate(1,58,-1,59).
+relate(1,58,-1,176).
+relate(1,60,-1,19).
+relate(1,60,-1,59).
+relate(1,62,-1,158).
+relate(1,64,-1,91).
+relate(1,64,-1,167).
+relate(1,66,-1,167).
+relate(1,66,-1,164).
+relate(1,66,-1,53).
+relate(1,68,-1,165).
+relate(1,68,-1,164).
+relate(1,68,-1,37).
+relate(1,68,-1,51).
+relate(1,70,-1,89).
+relate(1,70,-1,37).
+relate(1,70,-1,151).
+relate(1,72,-1,171).
+relate(1,74,-1,176).
+relate(1,74,-1,57).
+relate(1,74,-1,143).
+relate(1,76,-1,57).
+relate(1,76,-1,13).
+relate(1,76,-1,123).
+relate(1,78,-1,158).
+relate(1,78,-1,13).
+relate(1,80,-1,99).
+relate(1,80,-1,31).
+relate(1,82,-1,53).
+relate(1,82,-1,99).
+relate(1,82,-1,101).
+relate(1,84,-1,51).
+relate(1,84,-1,75).
+relate(1,84,-1,67).
+relate(1,86,-1,151).
+relate(1,86,-1,75).
+relate(1,86,-1,109).
+relate(1,86,-1,174).
+relate(1,88,-1,109).
+relate(1,88,-1,83).
+relate(1,88,-1,178).
+relate(1,90,-1,143).
+relate(1,90,-1,83).
+relate(1,90,-1,27).
+relate(1,92,-1,123).
+relate(1,92,-1,27).
+relate(1,92,-1,163).
+relate(1,92,-1,93).
+relate(1,94,-1,163).
+relate(1,94,-1,145).
+relate(1,96,-1,31).
+relate(1,96,-1,7).
+relate(1,96,-1,113).
+relate(1,98,-1,101).
+relate(1,98,-1,113).
+relate(1,100,-1,67).
+relate(1,100,-1,43).
+relate(1,102,-1,174).
+relate(1,102,-1,43).
+relate(1,102,-1,139).
+relate(1,102,-1,15).
+relate(1,104,-1,178).
+relate(1,104,-1,139).
+relate(1,104,-1,111).
+relate(1,106,-1,29).
+relate(1,106,-1,175).
+relate(1,108,-1,93).
+relate(1,108,-1,29).
+relate(1,108,-1,170).
+relate(1,108,-1,149).
+relate(1,110,-1,145).
+relate(1,110,-1,170).
+relate(1,112,-1,166).
+relate(1,114,-1,166).
+relate(1,114,-1,55).
+relate(1,116,-1,79).
+relate(1,118,-1,15).
+relate(1,118,-1,21).
+relate(1,120,-1,111).
+relate(1,120,-1,73).
+relate(1,122,-1,175).
+relate(1,122,-1,73).
+relate(1,122,-1,33).
+relate(1,124,-1,149).
+relate(1,124,-1,33).
+relate(1,126,-1,47).
+relate(1,128,-1,1).
+relate(1,128,-1,129).
+relate(1,128,-1,121).
+relate(1,130,-1,55).
+relate(1,130,-1,129).
+relate(1,130,-1,87).
+relate(1,132,-1,79).
+relate(1,132,-1,87).
+relate(1,132,-1,17).
+relate(1,132,-1,135).
+relate(1,134,-1,21).
+relate(1,134,-1,17).
+relate(1,134,-1,157).
+relate(1,134,-1,61).
+relate(1,136,-1,157).
+relate(1,138,-1,168).
+relate(1,140,-1,47).
+relate(1,140,-1,168).
+relate(1,140,-1,11).
+relate(1,140,-1,103).
+relate(1,142,-1,121).
+relate(1,144,-1,125).
+relate(1,146,-1,135).
+relate(1,146,-1,125).
+relate(1,146,-1,69).
+relate(1,146,-1,3).
+relate(1,148,-1,61).
+relate(1,148,-1,69).
+relate(1,148,-1,133).
+relate(1,150,-1,133).
+relate(1,150,-1,81).
+relate(1,152,-1,81).
+relate(1,152,-1,141).
+relate(1,154,-1,141).
+relate(1,154,-1,159).
+relate(1,154,-1,5).
+relate(1,156,-1,103).
+relate(1,156,-1,159).
+relate(-1,9,1,2).
+relate(-1,173,1,2).
+relate(-1,35,1,2).
+relate(-1,173,1,4).
+relate(-1,131,1,4).
+relate(-1,131,1,6).
+relate(-1,177,1,6).
+relate(-1,177,1,8).
+relate(-1,160,1,8).
+relate(-1,77,1,8).
+relate(-1,160,1,10).
+relate(-1,172,1,10).
+relate(-1,65,1,10).
+relate(-1,172,1,12).
+relate(-1,117,1,12).
+relate(-1,71,1,12).
+relate(-1,117,1,14).
+relate(-1,137,1,14).
+relate(-1,169,1,16).
+relate(-1,35,1,18).
+relate(-1,85,1,18).
+relate(-1,155,1,18).
+relate(-1,85,1,20).
+relate(-1,63,1,20).
+relate(-1,63,1,22).
+relate(-1,77,1,24).
+relate(-1,127,1,24).
+relate(-1,65,1,26).
+relate(-1,127,1,26).
+relate(-1,49,1,26).
+relate(-1,39,1,26).
+relate(-1,71,1,28).
+relate(-1,49,1,28).
+relate(-1,119,1,28).
+relate(-1,153,1,28).
+relate(-1,137,1,30).
+relate(-1,119,1,30).
+relate(-1,161,1,30).
+relate(-1,169,1,32).
+relate(-1,161,1,32).
+relate(-1,155,1,34).
+relate(-1,162,1,36).
+relate(-1,45,1,36).
+relate(-1,162,1,38).
+relate(-1,107,1,38).
+relate(-1,107,1,40).
+relate(-1,115,1,40).
+relate(-1,39,1,42).
+relate(-1,115,1,42).
+relate(-1,41,1,42).
+relate(-1,105,1,42).
+relate(-1,153,1,44).
+relate(-1,41,1,44).
+relate(-1,23,1,44).
+relate(-1,23,1,46).
+relate(-1,19,1,46).
+relate(-1,147,1,48).
+relate(-1,91,1,48).
+relate(-1,45,1,50).
+relate(-1,147,1,50).
+relate(-1,95,1,50).
+relate(-1,95,1,52).
+relate(-1,25,1,52).
+relate(-1,165,1,52).
+relate(-1,25,1,54).
+relate(-1,97,1,54).
+relate(-1,89,1,54).
+relate(-1,105,1,56).
+relate(-1,97,1,56).
+relate(-1,171,1,56).
+relate(-1,59,1,58).
+relate(-1,176,1,58).
+relate(-1,19,1,60).
+relate(-1,59,1,60).
+relate(-1,158,1,62).
+relate(-1,91,1,64).
+relate(-1,167,1,64).
+relate(-1,167,1,66).
+relate(-1,164,1,66).
+relate(-1,53,1,66).
+relate(-1,165,1,68).
+relate(-1,164,1,68).
+relate(-1,37,1,68).
+relate(-1,51,1,68).
+relate(-1,89,1,70).
+relate(-1,37,1,70).
+relate(-1,151,1,70).
+relate(-1,171,1,72).
+relate(-1,176,1,74).
+relate(-1,57,1,74).
+relate(-1,143,1,74).
+relate(-1,57,1,76).
+relate(-1,13,1,76).
+relate(-1,123,1,76).
+relate(-1,158,1,78).
+relate(-1,13,1,78).
+relate(-1,99,1,80).
+relate(-1,31,1,80).
+relate(-1,53,1,82).
+relate(-1,99,1,82).
+relate(-1,101,1,82).
+relate(-1,51,1,84).
+relate(-1,75,1,84).
+relate(-1,67,1,84).
+relate(-1,151,1,86).
+relate(-1,75,1,86).
+relate(-1,109,1,86).
+relate(-1,174,1,86).
+relate(-1,109,1,88).
+relate(-1,83,1,88).
+relate(-1,178,1,88).
+relate(-1,143,1,90).
+relate(-1,83,1,90).
+relate(-1,27,1,90).
+relate(-1,123,1,92).
+relate(-1,27,1,92).
+relate(-1,163,1,92).
+relate(-1,93,1,92).
+relate(-1,163,1,94).
+relate(-1,145,1,94).
+relate(-1,31,1,96).
+relate(-1,7,1,96).
+relate(-1,113,1,96).
+relate(-1,101,1,98).
+relate(-1,113,1,98).
+relate(-1,67,1,100).
+relate(-1,43,1,100).
+relate(-1,174,1,102).
+relate(-1,43,1,102).
+relate(-1,139,1,102).
+relate(-1,15,1,102).
+relate(-1,178,1,104).
+relate(-1,139,1,104).
+relate(-1,111,1,104).
+relate(-1,29,1,106).
+relate(-1,175,1,106).
+relate(-1,93,1,108).
+relate(-1,29,1,108).
+relate(-1,170,1,108).
+relate(-1,149,1,108).
+relate(-1,145,1,110).
+relate(-1,170,1,110).
+relate(-1,166,1,112).
+relate(-1,166,1,114).
+relate(-1,55,1,114).
+relate(-1,79,1,116).
+relate(-1,15,1,118).
+relate(-1,21,1,118).
+relate(-1,111,1,120).
+relate(-1,73,1,120).
+relate(-1,175,1,122).
+relate(-1,73,1,122).
+relate(-1,33,1,122).
+relate(-1,149,1,124).
+relate(-1,33,1,124).
+relate(-1,47,1,126).
+relate(-1,1,1,128).
+relate(-1,129,1,128).
+relate(-1,121,1,128).
+relate(-1,55,1,130).
+relate(-1,129,1,130).
+relate(-1,87,1,130).
+relate(-1,79,1,132).
+relate(-1,87,1,132).
+relate(-1,17,1,132).
+relate(-1,135,1,132).
+relate(-1,21,1,134).
+relate(-1,17,1,134).
+relate(-1,157,1,134).
+relate(-1,61,1,134).
+relate(-1,157,1,136).
+relate(-1,168,1,138).
+relate(-1,47,1,140).
+relate(-1,168,1,140).
+relate(-1,11,1,140).
+relate(-1,103,1,140).
+relate(-1,121,1,142).
+relate(-1,125,1,144).
+relate(-1,135,1,146).
+relate(-1,125,1,146).
+relate(-1,69,1,146).
+relate(-1,3,1,146).
+relate(-1,61,1,148).
+relate(-1,69,1,148).
+relate(-1,133,1,148).
+relate(-1,133,1,150).
+relate(-1,81,1,150).
+relate(-1,81,1,152).
+relate(-1,141,1,152).
+relate(-1,141,1,154).
+relate(-1,159,1,154).
+relate(-1,5,1,154).
+relate(-1,103,1,156).
+relate(-1,159,1,156).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/102-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/102-partner_units-100-0.lp
new file mode 100644
index 0000000..12a0eb6
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/102-partner_units-100-0.lp
@@ -0,0 +1,744 @@
+maxPU(4).
+#const n=178.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(-1,49,-1,51).
+follow(-1,61,-1,63).
+follow(-1,41,-1,43).
+follow(-1,7,-1,9).
+follow(-1,17,-1,19).
+follow(-1,131,-1,133).
+follow(-1,43,-1,45).
+follow(-1,157,-1,158).
+follow(-1,23,-1,25).
+follow(-1,97,-1,99).
+follow(-1,99,-1,101).
+follow(-1,163,-1,164).
+follow(-1,111,-1,113).
+follow(-1,107,-1,109).
+follow(-1,166,-1,167).
+follow(-1,167,-1,168).
+follow(-1,11,-1,13).
+follow(-1,145,-1,147).
+follow(-1,125,-1,127).
+follow(-1,129,-1,131).
+follow(-1,169,-1,170).
+follow(-1,77,-1,79).
+follow(-1,139,-1,141).
+follow(-1,21,-1,23).
+follow(-1,57,-1,59).
+follow(-1,113,-1,115).
+follow(-1,83,-1,85).
+follow(-1,33,-1,35).
+follow(-1,95,-1,97).
+follow(-1,121,-1,123).
+follow(-1,15,-1,17).
+follow(-1,85,-1,87).
+follow(-1,37,-1,39).
+follow(-1,119,-1,121).
+follow(-1,81,-1,83).
+follow(-1,160,-1,161).
+follow(-1,174,-1,175).
+follow(-1,3,-1,5).
+follow(-1,164,-1,165).
+follow(-1,155,-1,157).
+follow(-1,79,-1,81).
+follow(-1,172,-1,173).
+follow(-1,117,-1,119).
+follow(-1,170,-1,171).
+follow(-1,105,-1,107).
+follow(-1,27,-1,29).
+follow(-1,162,-1,163).
+follow(-1,127,-1,129).
+follow(-1,91,-1,93).
+follow(-1,149,-1,151).
+follow(-1,63,-1,65).
+follow(-1,158,-1,159).
+follow(-1,176,-1,177).
+follow(-1,47,-1,49).
+follow(-1,51,-1,53).
+follow(-1,65,-1,67).
+follow(-1,168,-1,169).
+follow(-1,71,-1,73).
+follow(-1,177,-1,178).
+follow(-1,67,-1,69).
+follow(-1,141,-1,143).
+follow(-1,87,-1,89).
+follow(-1,159,-1,160).
+follow(-1,143,-1,145).
+follow(-1,45,-1,47).
+follow(-1,13,-1,15).
+follow(-1,55,-1,57).
+follow(-1,73,-1,75).
+follow(-1,171,-1,172).
+follow(-1,93,-1,95).
+follow(-1,19,-1,21).
+follow(-1,133,-1,135).
+follow(-1,69,-1,71).
+follow(-1,123,-1,125).
+follow(-1,135,-1,137).
+follow(-1,53,-1,55).
+follow(-1,161,-1,162).
+follow(-1,103,-1,105).
+follow(-1,89,-1,91).
+follow(-1,1,-1,3).
+follow(-1,59,-1,61).
+follow(-1,39,-1,41).
+follow(-1,151,-1,153).
+follow(-1,29,-1,31).
+follow(-1,165,-1,166).
+follow(-1,109,-1,111).
+follow(-1,153,-1,155).
+follow(-1,147,-1,149).
+follow(-1,31,-1,33).
+follow(-1,175,-1,176).
+follow(-1,25,-1,27).
+follow(-1,5,-1,7).
+follow(-1,101,-1,103).
+follow(-1,9,-1,11).
+follow(-1,173,-1,174).
+follow(-1,35,-1,37).
+follow(-1,137,-1,139).
+follow(-1,115,-1,117).
+follow(-1,75,-1,77).
+relate(1,2,-1,51).
+relate(1,2,-1,63).
+relate(1,4,-1,51).
+relate(1,4,-1,43).
+relate(1,6,-1,9).
+relate(1,6,-1,43).
+relate(1,8,-1,19).
+relate(1,10,-1,133).
+relate(1,12,-1,133).
+relate(1,12,-1,45).
+relate(1,12,-1,158).
+relate(1,14,-1,45).
+relate(1,14,-1,25).
+relate(1,16,-1,63).
+relate(1,16,-1,99).
+relate(1,16,-1,101).
+relate(1,18,-1,99).
+relate(1,20,-1,164).
+relate(1,22,-1,19).
+relate(1,22,-1,164).
+relate(1,22,-1,113).
+relate(1,22,-1,109).
+relate(1,24,-1,113).
+relate(1,24,-1,167).
+relate(1,26,-1,168).
+relate(1,28,-1,158).
+relate(1,28,-1,13).
+relate(1,28,-1,147).
+relate(1,30,-1,25).
+relate(1,30,-1,13).
+relate(1,30,-1,127).
+relate(1,32,-1,101).
+relate(1,32,-1,131).
+relate(1,34,-1,170).
+relate(1,34,-1,79).
+relate(1,36,-1,170).
+relate(1,36,-1,141).
+relate(1,36,-1,23).
+relate(1,38,-1,109).
+relate(1,38,-1,141).
+relate(1,38,-1,59).
+relate(1,40,-1,167).
+relate(1,40,-1,115).
+relate(1,40,-1,85).
+relate(1,42,-1,168).
+relate(1,42,-1,115).
+relate(1,42,-1,35).
+relate(1,44,-1,147).
+relate(1,44,-1,35).
+relate(1,44,-1,97).
+relate(1,46,-1,127).
+relate(1,46,-1,97).
+relate(1,48,-1,131).
+relate(1,48,-1,123).
+relate(1,50,-1,79).
+relate(1,50,-1,17).
+relate(1,52,-1,23).
+relate(1,52,-1,17).
+relate(1,54,-1,59).
+relate(1,54,-1,87).
+relate(1,54,-1,39).
+relate(1,56,-1,85).
+relate(1,56,-1,87).
+relate(1,56,-1,121).
+relate(1,56,-1,83).
+relate(1,58,-1,121).
+relate(1,58,-1,161).
+relate(1,60,-1,175).
+relate(1,62,-1,123).
+relate(1,62,-1,5).
+relate(1,62,-1,165).
+relate(1,64,-1,157).
+relate(1,66,-1,157).
+relate(1,66,-1,81).
+relate(1,66,-1,173).
+relate(1,68,-1,39).
+relate(1,68,-1,81).
+relate(1,68,-1,119).
+relate(1,68,-1,171).
+relate(1,70,-1,83).
+relate(1,70,-1,119).
+relate(1,70,-1,107).
+relate(1,70,-1,29).
+relate(1,72,-1,161).
+relate(1,72,-1,107).
+relate(1,72,-1,163).
+relate(1,74,-1,175).
+relate(1,74,-1,163).
+relate(1,74,-1,129).
+relate(1,74,-1,93).
+relate(1,76,-1,129).
+relate(1,78,-1,165).
+relate(1,78,-1,151).
+relate(1,78,-1,65).
+relate(1,80,-1,151).
+relate(1,80,-1,159).
+relate(1,82,-1,173).
+relate(1,82,-1,177).
+relate(1,84,-1,171).
+relate(1,84,-1,49).
+relate(1,84,-1,53).
+relate(1,86,-1,29).
+relate(1,86,-1,49).
+relate(1,86,-1,67).
+relate(1,86,-1,169).
+relate(1,88,-1,67).
+relate(1,88,-1,73).
+relate(1,90,-1,93).
+relate(1,90,-1,73).
+relate(1,90,-1,178).
+relate(1,92,-1,69).
+relate(1,94,-1,65).
+relate(1,94,-1,143).
+relate(1,94,-1,89).
+relate(1,96,-1,159).
+relate(1,96,-1,143).
+relate(1,96,-1,160).
+relate(1,96,-1,145).
+relate(1,98,-1,177).
+relate(1,98,-1,160).
+relate(1,98,-1,47).
+relate(1,100,-1,53).
+relate(1,102,-1,169).
+relate(1,102,-1,15).
+relate(1,104,-1,57).
+relate(1,106,-1,178).
+relate(1,106,-1,75).
+relate(1,106,-1,172).
+relate(1,108,-1,69).
+relate(1,108,-1,75).
+relate(1,108,-1,95).
+relate(1,110,-1,89).
+relate(1,112,-1,145).
+relate(1,112,-1,21).
+relate(1,112,-1,135).
+relate(1,114,-1,47).
+relate(1,114,-1,21).
+relate(1,114,-1,71).
+relate(1,114,-1,125).
+relate(1,116,-1,71).
+relate(1,116,-1,137).
+relate(1,118,-1,15).
+relate(1,118,-1,55).
+relate(1,118,-1,162).
+relate(1,120,-1,57).
+relate(1,120,-1,55).
+relate(1,120,-1,105).
+relate(1,122,-1,172).
+relate(1,122,-1,105).
+relate(1,122,-1,91).
+relate(1,124,-1,95).
+relate(1,124,-1,3).
+relate(1,124,-1,61).
+relate(1,126,-1,41).
+relate(1,126,-1,153).
+relate(1,128,-1,135).
+relate(1,128,-1,41).
+relate(1,130,-1,125).
+relate(1,130,-1,31).
+relate(1,132,-1,137).
+relate(1,132,-1,166).
+relate(1,134,-1,162).
+relate(1,134,-1,111).
+relate(1,134,-1,155).
+relate(1,136,-1,111).
+relate(1,136,-1,149).
+relate(1,136,-1,33).
+relate(1,138,-1,91).
+relate(1,138,-1,149).
+relate(1,138,-1,176).
+relate(1,140,-1,61).
+relate(1,140,-1,176).
+relate(1,140,-1,27).
+relate(1,142,-1,153).
+relate(1,142,-1,7).
+relate(1,142,-1,103).
+relate(1,142,-1,11).
+relate(1,144,-1,103).
+relate(1,144,-1,174).
+relate(1,146,-1,31).
+relate(1,146,-1,174).
+relate(1,146,-1,37).
+relate(1,148,-1,166).
+relate(1,148,-1,37).
+relate(1,148,-1,139).
+relate(1,150,-1,155).
+relate(1,150,-1,139).
+relate(1,150,-1,117).
+relate(1,152,-1,33).
+relate(1,152,-1,117).
+relate(1,152,-1,77).
+relate(1,154,-1,77).
+relate(1,154,-1,1).
+relate(1,156,-1,27).
+relate(-1,51,1,2).
+relate(-1,63,1,2).
+relate(-1,51,1,4).
+relate(-1,43,1,4).
+relate(-1,9,1,6).
+relate(-1,43,1,6).
+relate(-1,19,1,8).
+relate(-1,133,1,10).
+relate(-1,133,1,12).
+relate(-1,45,1,12).
+relate(-1,158,1,12).
+relate(-1,45,1,14).
+relate(-1,25,1,14).
+relate(-1,63,1,16).
+relate(-1,99,1,16).
+relate(-1,101,1,16).
+relate(-1,99,1,18).
+relate(-1,164,1,20).
+relate(-1,19,1,22).
+relate(-1,164,1,22).
+relate(-1,113,1,22).
+relate(-1,109,1,22).
+relate(-1,113,1,24).
+relate(-1,167,1,24).
+relate(-1,168,1,26).
+relate(-1,158,1,28).
+relate(-1,13,1,28).
+relate(-1,147,1,28).
+relate(-1,25,1,30).
+relate(-1,13,1,30).
+relate(-1,127,1,30).
+relate(-1,101,1,32).
+relate(-1,131,1,32).
+relate(-1,170,1,34).
+relate(-1,79,1,34).
+relate(-1,170,1,36).
+relate(-1,141,1,36).
+relate(-1,23,1,36).
+relate(-1,109,1,38).
+relate(-1,141,1,38).
+relate(-1,59,1,38).
+relate(-1,167,1,40).
+relate(-1,115,1,40).
+relate(-1,85,1,40).
+relate(-1,168,1,42).
+relate(-1,115,1,42).
+relate(-1,35,1,42).
+relate(-1,147,1,44).
+relate(-1,35,1,44).
+relate(-1,97,1,44).
+relate(-1,127,1,46).
+relate(-1,97,1,46).
+relate(-1,131,1,48).
+relate(-1,123,1,48).
+relate(-1,79,1,50).
+relate(-1,17,1,50).
+relate(-1,23,1,52).
+relate(-1,17,1,52).
+relate(-1,59,1,54).
+relate(-1,87,1,54).
+relate(-1,39,1,54).
+relate(-1,85,1,56).
+relate(-1,87,1,56).
+relate(-1,121,1,56).
+relate(-1,83,1,56).
+relate(-1,121,1,58).
+relate(-1,161,1,58).
+relate(-1,175,1,60).
+relate(-1,123,1,62).
+relate(-1,5,1,62).
+relate(-1,165,1,62).
+relate(-1,157,1,64).
+relate(-1,157,1,66).
+relate(-1,81,1,66).
+relate(-1,173,1,66).
+relate(-1,39,1,68).
+relate(-1,81,1,68).
+relate(-1,119,1,68).
+relate(-1,171,1,68).
+relate(-1,83,1,70).
+relate(-1,119,1,70).
+relate(-1,107,1,70).
+relate(-1,29,1,70).
+relate(-1,161,1,72).
+relate(-1,107,1,72).
+relate(-1,163,1,72).
+relate(-1,175,1,74).
+relate(-1,163,1,74).
+relate(-1,129,1,74).
+relate(-1,93,1,74).
+relate(-1,129,1,76).
+relate(-1,165,1,78).
+relate(-1,151,1,78).
+relate(-1,65,1,78).
+relate(-1,151,1,80).
+relate(-1,159,1,80).
+relate(-1,173,1,82).
+relate(-1,177,1,82).
+relate(-1,171,1,84).
+relate(-1,49,1,84).
+relate(-1,53,1,84).
+relate(-1,29,1,86).
+relate(-1,49,1,86).
+relate(-1,67,1,86).
+relate(-1,169,1,86).
+relate(-1,67,1,88).
+relate(-1,73,1,88).
+relate(-1,93,1,90).
+relate(-1,73,1,90).
+relate(-1,178,1,90).
+relate(-1,69,1,92).
+relate(-1,65,1,94).
+relate(-1,143,1,94).
+relate(-1,89,1,94).
+relate(-1,159,1,96).
+relate(-1,143,1,96).
+relate(-1,160,1,96).
+relate(-1,145,1,96).
+relate(-1,177,1,98).
+relate(-1,160,1,98).
+relate(-1,47,1,98).
+relate(-1,53,1,100).
+relate(-1,169,1,102).
+relate(-1,15,1,102).
+relate(-1,57,1,104).
+relate(-1,178,1,106).
+relate(-1,75,1,106).
+relate(-1,172,1,106).
+relate(-1,69,1,108).
+relate(-1,75,1,108).
+relate(-1,95,1,108).
+relate(-1,89,1,110).
+relate(-1,145,1,112).
+relate(-1,21,1,112).
+relate(-1,135,1,112).
+relate(-1,47,1,114).
+relate(-1,21,1,114).
+relate(-1,71,1,114).
+relate(-1,125,1,114).
+relate(-1,71,1,116).
+relate(-1,137,1,116).
+relate(-1,15,1,118).
+relate(-1,55,1,118).
+relate(-1,162,1,118).
+relate(-1,57,1,120).
+relate(-1,55,1,120).
+relate(-1,105,1,120).
+relate(-1,172,1,122).
+relate(-1,105,1,122).
+relate(-1,91,1,122).
+relate(-1,95,1,124).
+relate(-1,3,1,124).
+relate(-1,61,1,124).
+relate(-1,41,1,126).
+relate(-1,153,1,126).
+relate(-1,135,1,128).
+relate(-1,41,1,128).
+relate(-1,125,1,130).
+relate(-1,31,1,130).
+relate(-1,137,1,132).
+relate(-1,166,1,132).
+relate(-1,162,1,134).
+relate(-1,111,1,134).
+relate(-1,155,1,134).
+relate(-1,111,1,136).
+relate(-1,149,1,136).
+relate(-1,33,1,136).
+relate(-1,91,1,138).
+relate(-1,149,1,138).
+relate(-1,176,1,138).
+relate(-1,61,1,140).
+relate(-1,176,1,140).
+relate(-1,27,1,140).
+relate(-1,153,1,142).
+relate(-1,7,1,142).
+relate(-1,103,1,142).
+relate(-1,11,1,142).
+relate(-1,103,1,144).
+relate(-1,174,1,144).
+relate(-1,31,1,146).
+relate(-1,174,1,146).
+relate(-1,37,1,146).
+relate(-1,166,1,148).
+relate(-1,37,1,148).
+relate(-1,139,1,148).
+relate(-1,155,1,150).
+relate(-1,139,1,150).
+relate(-1,117,1,150).
+relate(-1,33,1,152).
+relate(-1,117,1,152).
+relate(-1,77,1,152).
+relate(-1,77,1,154).
+relate(-1,1,1,154).
+relate(-1,27,1,156).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/114-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/114-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..8ee36df
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/114-partner_units_polynomial-100-0.lp
@@ -0,0 +1,746 @@
+maxPU(2).
+#const n=179.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+object(-1,179).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(1,156,1,158).
+follow(-1,168,-1,169).
+follow(-1,65,-1,67).
+follow(-1,95,-1,97).
+follow(-1,137,-1,139).
+follow(-1,115,-1,117).
+follow(-1,1,-1,3).
+follow(-1,101,-1,103).
+follow(-1,3,-1,5).
+follow(-1,63,-1,65).
+follow(-1,87,-1,89).
+follow(-1,5,-1,7).
+follow(-1,105,-1,107).
+follow(-1,81,-1,83).
+follow(-1,51,-1,53).
+follow(-1,39,-1,41).
+follow(-1,139,-1,141).
+follow(-1,31,-1,33).
+follow(-1,157,-1,159).
+follow(-1,169,-1,170).
+follow(-1,107,-1,109).
+follow(-1,170,-1,171).
+follow(-1,93,-1,95).
+follow(-1,53,-1,55).
+follow(-1,47,-1,49).
+follow(-1,127,-1,129).
+follow(-1,79,-1,81).
+follow(-1,131,-1,133).
+follow(-1,117,-1,119).
+follow(-1,99,-1,101).
+follow(-1,77,-1,79).
+follow(-1,59,-1,61).
+follow(-1,21,-1,23).
+follow(-1,129,-1,131).
+follow(-1,141,-1,143).
+follow(-1,133,-1,135).
+follow(-1,166,-1,167).
+follow(-1,171,-1,172).
+follow(-1,151,-1,153).
+follow(-1,83,-1,85).
+follow(-1,155,-1,157).
+follow(-1,176,-1,177).
+follow(-1,143,-1,145).
+follow(-1,103,-1,105).
+follow(-1,149,-1,151).
+follow(-1,33,-1,35).
+follow(-1,61,-1,63).
+follow(-1,15,-1,17).
+follow(-1,153,-1,155).
+follow(-1,172,-1,173).
+follow(-1,23,-1,25).
+follow(-1,89,-1,91).
+follow(-1,75,-1,77).
+follow(-1,165,-1,166).
+follow(-1,125,-1,127).
+follow(-1,45,-1,47).
+follow(-1,167,-1,168).
+follow(-1,57,-1,59).
+follow(-1,97,-1,99).
+follow(-1,162,-1,163).
+follow(-1,37,-1,39).
+follow(-1,19,-1,21).
+follow(-1,111,-1,113).
+follow(-1,49,-1,51).
+follow(-1,178,-1,179).
+follow(-1,163,-1,164).
+follow(-1,73,-1,75).
+follow(-1,174,-1,175).
+follow(-1,91,-1,93).
+follow(-1,85,-1,87).
+follow(-1,113,-1,115).
+follow(-1,109,-1,111).
+follow(-1,11,-1,13).
+follow(-1,67,-1,69).
+follow(-1,35,-1,37).
+follow(-1,71,-1,73).
+follow(-1,41,-1,43).
+follow(-1,160,-1,161).
+follow(-1,177,-1,178).
+follow(-1,175,-1,176).
+follow(-1,27,-1,29).
+follow(-1,17,-1,19).
+follow(-1,135,-1,137).
+follow(-1,7,-1,9).
+follow(-1,43,-1,45).
+follow(-1,161,-1,162).
+follow(-1,25,-1,27).
+follow(-1,173,-1,174).
+follow(-1,69,-1,71).
+follow(-1,119,-1,121).
+follow(-1,121,-1,123).
+follow(-1,145,-1,147).
+follow(-1,29,-1,31).
+follow(-1,123,-1,125).
+follow(-1,159,-1,160).
+follow(-1,55,-1,57).
+follow(-1,164,-1,165).
+follow(-1,9,-1,11).
+follow(-1,13,-1,15).
+follow(-1,147,-1,149).
+relate(1,2,-1,169).
+relate(1,4,-1,169).
+relate(1,4,-1,67).
+relate(1,6,-1,97).
+relate(1,8,-1,139).
+relate(1,10,-1,117).
+relate(1,12,-1,3).
+relate(1,12,-1,117).
+relate(1,12,-1,103).
+relate(1,14,-1,5).
+relate(1,14,-1,103).
+relate(1,14,-1,65).
+relate(1,16,-1,89).
+relate(1,18,-1,7).
+relate(1,18,-1,107).
+relate(1,18,-1,83).
+relate(1,20,-1,67).
+relate(1,20,-1,107).
+relate(1,22,-1,97).
+relate(1,22,-1,53).
+relate(1,22,-1,41).
+relate(1,24,-1,139).
+relate(1,24,-1,53).
+relate(1,24,-1,141).
+relate(1,26,-1,141).
+relate(1,26,-1,33).
+relate(1,26,-1,159).
+relate(1,28,-1,33).
+relate(1,28,-1,170).
+relate(1,28,-1,109).
+relate(1,30,-1,65).
+relate(1,30,-1,170).
+relate(1,30,-1,171).
+relate(1,32,-1,89).
+relate(1,32,-1,171).
+relate(1,32,-1,1).
+relate(1,32,-1,95).
+relate(1,34,-1,83).
+relate(1,34,-1,55).
+relate(1,34,-1,49).
+relate(1,36,-1,55).
+relate(1,36,-1,129).
+relate(1,38,-1,41).
+relate(1,38,-1,129).
+relate(1,38,-1,81).
+relate(1,40,-1,133).
+relate(1,42,-1,159).
+relate(1,42,-1,119).
+relate(1,42,-1,101).
+relate(1,44,-1,109).
+relate(1,44,-1,119).
+relate(1,44,-1,79).
+relate(1,44,-1,61).
+relate(1,46,-1,79).
+relate(1,46,-1,23).
+relate(1,46,-1,131).
+relate(1,48,-1,95).
+relate(1,48,-1,23).
+relate(1,48,-1,143).
+relate(1,50,-1,49).
+relate(1,50,-1,135).
+relate(1,50,-1,167).
+relate(1,52,-1,135).
+relate(1,52,-1,172).
+relate(1,52,-1,153).
+relate(1,54,-1,81).
+relate(1,54,-1,172).
+relate(1,54,-1,85).
+relate(1,56,-1,133).
+relate(1,56,-1,85).
+relate(1,56,-1,157).
+relate(1,56,-1,177).
+relate(1,58,-1,101).
+relate(1,58,-1,157).
+relate(1,58,-1,145).
+relate(1,60,-1,61).
+relate(1,60,-1,105).
+relate(1,60,-1,151).
+relate(1,62,-1,131).
+relate(1,62,-1,105).
+relate(1,62,-1,35).
+relate(1,64,-1,143).
+relate(1,64,-1,35).
+relate(1,64,-1,63).
+relate(1,66,-1,167).
+relate(1,68,-1,153).
+relate(1,68,-1,17).
+relate(1,70,-1,17).
+relate(1,70,-1,155).
+relate(1,72,-1,177).
+relate(1,72,-1,155).
+relate(1,72,-1,173).
+relate(1,72,-1,25).
+relate(1,74,-1,145).
+relate(1,74,-1,173).
+relate(1,74,-1,91).
+relate(1,76,-1,151).
+relate(1,78,-1,77).
+relate(1,80,-1,63).
+relate(1,80,-1,166).
+relate(1,82,-1,127).
+relate(1,82,-1,47).
+relate(1,84,-1,127).
+relate(1,84,-1,168).
+relate(1,86,-1,168).
+relate(1,86,-1,59).
+relate(1,86,-1,99).
+relate(1,88,-1,25).
+relate(1,88,-1,59).
+relate(1,88,-1,163).
+relate(1,88,-1,39).
+relate(1,90,-1,91).
+relate(1,90,-1,163).
+relate(1,90,-1,21).
+relate(1,90,-1,113).
+relate(1,92,-1,21).
+relate(1,92,-1,51).
+relate(1,92,-1,179).
+relate(1,94,-1,77).
+relate(1,94,-1,51).
+relate(1,94,-1,164).
+relate(1,96,-1,166).
+relate(1,96,-1,75).
+relate(1,98,-1,47).
+relate(1,98,-1,175).
+relate(1,100,-1,93).
+relate(1,102,-1,99).
+relate(1,102,-1,93).
+relate(1,102,-1,87).
+relate(1,104,-1,39).
+relate(1,104,-1,87).
+relate(1,104,-1,115).
+relate(1,104,-1,111).
+relate(1,106,-1,113).
+relate(1,106,-1,115).
+relate(1,108,-1,179).
+relate(1,108,-1,13).
+relate(1,108,-1,69).
+relate(1,110,-1,164).
+relate(1,110,-1,13).
+relate(1,110,-1,37).
+relate(1,110,-1,73).
+relate(1,112,-1,75).
+relate(1,112,-1,37).
+relate(1,112,-1,43).
+relate(1,114,-1,175).
+relate(1,116,-1,161).
+relate(1,118,-1,161).
+relate(1,118,-1,178).
+relate(1,118,-1,176).
+relate(1,120,-1,111).
+relate(1,120,-1,178).
+relate(1,120,-1,29).
+relate(1,122,-1,19).
+relate(1,124,-1,69).
+relate(1,124,-1,19).
+relate(1,126,-1,73).
+relate(1,128,-1,43).
+relate(1,128,-1,137).
+relate(1,130,-1,9).
+relate(1,130,-1,45).
+relate(1,132,-1,45).
+relate(1,132,-1,162).
+relate(1,132,-1,27).
+relate(1,134,-1,176).
+relate(1,134,-1,162).
+relate(1,134,-1,174).
+relate(1,134,-1,71).
+relate(1,136,-1,29).
+relate(1,136,-1,174).
+relate(1,136,-1,121).
+relate(1,138,-1,121).
+relate(1,138,-1,123).
+relate(1,140,-1,147).
+relate(1,140,-1,31).
+relate(1,142,-1,147).
+relate(1,142,-1,125).
+relate(1,144,-1,137).
+relate(1,144,-1,125).
+relate(1,144,-1,160).
+relate(1,146,-1,57).
+relate(1,148,-1,27).
+relate(1,148,-1,57).
+relate(1,150,-1,71).
+relate(1,152,-1,123).
+relate(1,152,-1,165).
+relate(1,152,-1,11).
+relate(1,154,-1,31).
+relate(1,154,-1,165).
+relate(1,154,-1,15).
+relate(1,156,-1,15).
+relate(1,156,-1,149).
+relate(1,158,-1,160).
+relate(1,158,-1,149).
+relate(-1,169,1,2).
+relate(-1,169,1,4).
+relate(-1,67,1,4).
+relate(-1,97,1,6).
+relate(-1,139,1,8).
+relate(-1,117,1,10).
+relate(-1,3,1,12).
+relate(-1,117,1,12).
+relate(-1,103,1,12).
+relate(-1,5,1,14).
+relate(-1,103,1,14).
+relate(-1,65,1,14).
+relate(-1,89,1,16).
+relate(-1,7,1,18).
+relate(-1,107,1,18).
+relate(-1,83,1,18).
+relate(-1,67,1,20).
+relate(-1,107,1,20).
+relate(-1,97,1,22).
+relate(-1,53,1,22).
+relate(-1,41,1,22).
+relate(-1,139,1,24).
+relate(-1,53,1,24).
+relate(-1,141,1,24).
+relate(-1,141,1,26).
+relate(-1,33,1,26).
+relate(-1,159,1,26).
+relate(-1,33,1,28).
+relate(-1,170,1,28).
+relate(-1,109,1,28).
+relate(-1,65,1,30).
+relate(-1,170,1,30).
+relate(-1,171,1,30).
+relate(-1,89,1,32).
+relate(-1,171,1,32).
+relate(-1,1,1,32).
+relate(-1,95,1,32).
+relate(-1,83,1,34).
+relate(-1,55,1,34).
+relate(-1,49,1,34).
+relate(-1,55,1,36).
+relate(-1,129,1,36).
+relate(-1,41,1,38).
+relate(-1,129,1,38).
+relate(-1,81,1,38).
+relate(-1,133,1,40).
+relate(-1,159,1,42).
+relate(-1,119,1,42).
+relate(-1,101,1,42).
+relate(-1,109,1,44).
+relate(-1,119,1,44).
+relate(-1,79,1,44).
+relate(-1,61,1,44).
+relate(-1,79,1,46).
+relate(-1,23,1,46).
+relate(-1,131,1,46).
+relate(-1,95,1,48).
+relate(-1,23,1,48).
+relate(-1,143,1,48).
+relate(-1,49,1,50).
+relate(-1,135,1,50).
+relate(-1,167,1,50).
+relate(-1,135,1,52).
+relate(-1,172,1,52).
+relate(-1,153,1,52).
+relate(-1,81,1,54).
+relate(-1,172,1,54).
+relate(-1,85,1,54).
+relate(-1,133,1,56).
+relate(-1,85,1,56).
+relate(-1,157,1,56).
+relate(-1,177,1,56).
+relate(-1,101,1,58).
+relate(-1,157,1,58).
+relate(-1,145,1,58).
+relate(-1,61,1,60).
+relate(-1,105,1,60).
+relate(-1,151,1,60).
+relate(-1,131,1,62).
+relate(-1,105,1,62).
+relate(-1,35,1,62).
+relate(-1,143,1,64).
+relate(-1,35,1,64).
+relate(-1,63,1,64).
+relate(-1,167,1,66).
+relate(-1,153,1,68).
+relate(-1,17,1,68).
+relate(-1,17,1,70).
+relate(-1,155,1,70).
+relate(-1,177,1,72).
+relate(-1,155,1,72).
+relate(-1,173,1,72).
+relate(-1,25,1,72).
+relate(-1,145,1,74).
+relate(-1,173,1,74).
+relate(-1,91,1,74).
+relate(-1,151,1,76).
+relate(-1,77,1,78).
+relate(-1,63,1,80).
+relate(-1,166,1,80).
+relate(-1,127,1,82).
+relate(-1,47,1,82).
+relate(-1,127,1,84).
+relate(-1,168,1,84).
+relate(-1,168,1,86).
+relate(-1,59,1,86).
+relate(-1,99,1,86).
+relate(-1,25,1,88).
+relate(-1,59,1,88).
+relate(-1,163,1,88).
+relate(-1,39,1,88).
+relate(-1,91,1,90).
+relate(-1,163,1,90).
+relate(-1,21,1,90).
+relate(-1,113,1,90).
+relate(-1,21,1,92).
+relate(-1,51,1,92).
+relate(-1,179,1,92).
+relate(-1,77,1,94).
+relate(-1,51,1,94).
+relate(-1,164,1,94).
+relate(-1,166,1,96).
+relate(-1,75,1,96).
+relate(-1,47,1,98).
+relate(-1,175,1,98).
+relate(-1,93,1,100).
+relate(-1,99,1,102).
+relate(-1,93,1,102).
+relate(-1,87,1,102).
+relate(-1,39,1,104).
+relate(-1,87,1,104).
+relate(-1,115,1,104).
+relate(-1,111,1,104).
+relate(-1,113,1,106).
+relate(-1,115,1,106).
+relate(-1,179,1,108).
+relate(-1,13,1,108).
+relate(-1,69,1,108).
+relate(-1,164,1,110).
+relate(-1,13,1,110).
+relate(-1,37,1,110).
+relate(-1,73,1,110).
+relate(-1,75,1,112).
+relate(-1,37,1,112).
+relate(-1,43,1,112).
+relate(-1,175,1,114).
+relate(-1,161,1,116).
+relate(-1,161,1,118).
+relate(-1,178,1,118).
+relate(-1,176,1,118).
+relate(-1,111,1,120).
+relate(-1,178,1,120).
+relate(-1,29,1,120).
+relate(-1,19,1,122).
+relate(-1,69,1,124).
+relate(-1,19,1,124).
+relate(-1,73,1,126).
+relate(-1,43,1,128).
+relate(-1,137,1,128).
+relate(-1,9,1,130).
+relate(-1,45,1,130).
+relate(-1,45,1,132).
+relate(-1,162,1,132).
+relate(-1,27,1,132).
+relate(-1,176,1,134).
+relate(-1,162,1,134).
+relate(-1,174,1,134).
+relate(-1,71,1,134).
+relate(-1,29,1,136).
+relate(-1,174,1,136).
+relate(-1,121,1,136).
+relate(-1,121,1,138).
+relate(-1,123,1,138).
+relate(-1,147,1,140).
+relate(-1,31,1,140).
+relate(-1,147,1,142).
+relate(-1,125,1,142).
+relate(-1,137,1,144).
+relate(-1,125,1,144).
+relate(-1,160,1,144).
+relate(-1,57,1,146).
+relate(-1,27,1,148).
+relate(-1,57,1,148).
+relate(-1,71,1,150).
+relate(-1,123,1,152).
+relate(-1,165,1,152).
+relate(-1,11,1,152).
+relate(-1,31,1,154).
+relate(-1,165,1,154).
+relate(-1,15,1,154).
+relate(-1,15,1,156).
+relate(-1,149,1,156).
+relate(-1,160,1,158).
+relate(-1,149,1,158).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/115-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/115-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..ab81269
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/115-partner_units_polynomial-100-0.lp
@@ -0,0 +1,746 @@
+maxPU(2).
+#const n=179.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+object(-1,179).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(1,156,1,158).
+follow(-1,5,-1,7).
+follow(-1,75,-1,77).
+follow(-1,59,-1,61).
+follow(-1,172,-1,173).
+follow(-1,41,-1,43).
+follow(-1,23,-1,25).
+follow(-1,63,-1,65).
+follow(-1,133,-1,135).
+follow(-1,57,-1,59).
+follow(-1,111,-1,113).
+follow(-1,43,-1,45).
+follow(-1,73,-1,75).
+follow(-1,85,-1,87).
+follow(-1,99,-1,101).
+follow(-1,71,-1,73).
+follow(-1,11,-1,13).
+follow(-1,65,-1,67).
+follow(-1,103,-1,105).
+follow(-1,170,-1,171).
+follow(-1,145,-1,147).
+follow(-1,87,-1,89).
+follow(-1,25,-1,27).
+follow(-1,13,-1,15).
+follow(-1,137,-1,139).
+follow(-1,69,-1,71).
+follow(-1,175,-1,176).
+follow(-1,169,-1,170).
+follow(-1,162,-1,163).
+follow(-1,27,-1,29).
+follow(-1,15,-1,17).
+follow(-1,176,-1,177).
+follow(-1,123,-1,125).
+follow(-1,55,-1,57).
+follow(-1,167,-1,168).
+follow(-1,101,-1,103).
+follow(-1,67,-1,69).
+follow(-1,159,-1,160).
+follow(-1,151,-1,153).
+follow(-1,125,-1,127).
+follow(-1,163,-1,164).
+follow(-1,164,-1,165).
+follow(-1,35,-1,37).
+follow(-1,129,-1,131).
+follow(-1,115,-1,117).
+follow(-1,53,-1,55).
+follow(-1,107,-1,109).
+follow(-1,89,-1,91).
+follow(-1,19,-1,21).
+follow(-1,149,-1,151).
+follow(-1,29,-1,31).
+follow(-1,83,-1,85).
+follow(-1,45,-1,47).
+follow(-1,177,-1,178).
+follow(-1,33,-1,35).
+follow(-1,49,-1,51).
+follow(-1,165,-1,166).
+follow(-1,81,-1,83).
+follow(-1,173,-1,174).
+follow(-1,127,-1,129).
+follow(-1,143,-1,145).
+follow(-1,160,-1,161).
+follow(-1,47,-1,49).
+follow(-1,113,-1,115).
+follow(-1,9,-1,11).
+follow(-1,31,-1,33).
+follow(-1,141,-1,143).
+follow(-1,109,-1,111).
+follow(-1,79,-1,81).
+follow(-1,17,-1,19).
+follow(-1,168,-1,169).
+follow(-1,77,-1,79).
+follow(-1,166,-1,167).
+follow(-1,91,-1,93).
+follow(-1,157,-1,159).
+follow(-1,174,-1,175).
+follow(-1,131,-1,133).
+follow(-1,37,-1,39).
+follow(-1,121,-1,123).
+follow(-1,97,-1,99).
+follow(-1,171,-1,172).
+follow(-1,135,-1,137).
+follow(-1,139,-1,141).
+follow(-1,95,-1,97).
+follow(-1,153,-1,155).
+follow(-1,21,-1,23).
+follow(-1,147,-1,149).
+follow(-1,61,-1,63).
+follow(-1,105,-1,107).
+follow(-1,155,-1,157).
+follow(-1,119,-1,121).
+follow(-1,117,-1,119).
+follow(-1,161,-1,162).
+follow(-1,3,-1,5).
+follow(-1,51,-1,53).
+follow(-1,178,-1,179).
+follow(-1,7,-1,9).
+follow(-1,39,-1,41).
+follow(-1,93,-1,95).
+follow(-1,1,-1,3).
+relate(1,2,-1,7).
+relate(1,2,-1,77).
+relate(1,4,-1,77).
+relate(1,4,-1,61).
+relate(1,6,-1,173).
+relate(1,8,-1,173).
+relate(1,8,-1,43).
+relate(1,8,-1,25).
+relate(1,10,-1,43).
+relate(1,10,-1,65).
+relate(1,12,-1,65).
+relate(1,12,-1,135).
+relate(1,12,-1,59).
+relate(1,14,-1,135).
+relate(1,14,-1,113).
+relate(1,14,-1,45).
+relate(1,16,-1,113).
+relate(1,18,-1,75).
+relate(1,20,-1,61).
+relate(1,20,-1,75).
+relate(1,20,-1,87).
+relate(1,22,-1,101).
+relate(1,22,-1,73).
+relate(1,24,-1,25).
+relate(1,24,-1,101).
+relate(1,24,-1,13).
+relate(1,24,-1,67).
+relate(1,26,-1,13).
+relate(1,26,-1,105).
+relate(1,28,-1,59).
+relate(1,28,-1,105).
+relate(1,28,-1,171).
+relate(1,30,-1,45).
+relate(1,30,-1,171).
+relate(1,30,-1,147).
+relate(1,30,-1,89).
+relate(1,32,-1,147).
+relate(1,32,-1,27).
+relate(1,34,-1,15).
+relate(1,36,-1,87).
+relate(1,36,-1,15).
+relate(1,36,-1,139).
+relate(1,38,-1,73).
+relate(1,38,-1,139).
+relate(1,38,-1,71).
+relate(1,40,-1,67).
+relate(1,40,-1,176).
+relate(1,40,-1,170).
+relate(1,42,-1,176).
+relate(1,42,-1,163).
+relate(1,44,-1,163).
+relate(1,46,-1,89).
+relate(1,46,-1,29).
+relate(1,48,-1,27).
+relate(1,48,-1,29).
+relate(1,48,-1,17).
+relate(1,50,-1,177).
+relate(1,50,-1,125).
+relate(1,52,-1,177).
+relate(1,52,-1,57).
+relate(1,54,-1,71).
+relate(1,56,-1,170).
+relate(1,56,-1,168).
+relate(1,58,-1,103).
+relate(1,60,-1,69).
+relate(1,60,-1,160).
+relate(1,62,-1,69).
+relate(1,62,-1,153).
+relate(1,62,-1,127).
+relate(1,64,-1,17).
+relate(1,64,-1,153).
+relate(1,64,-1,164).
+relate(1,66,-1,125).
+relate(1,66,-1,165).
+relate(1,66,-1,37).
+relate(1,68,-1,57).
+relate(1,68,-1,165).
+relate(1,68,-1,131).
+relate(1,68,-1,117).
+relate(1,70,-1,131).
+relate(1,70,-1,55).
+relate(1,72,-1,168).
+relate(1,72,-1,109).
+relate(1,72,-1,91).
+relate(1,74,-1,103).
+relate(1,74,-1,109).
+relate(1,74,-1,21).
+relate(1,76,-1,160).
+relate(1,76,-1,21).
+relate(1,76,-1,151).
+relate(1,76,-1,31).
+relate(1,78,-1,127).
+relate(1,78,-1,151).
+relate(1,78,-1,85).
+relate(1,78,-1,47).
+relate(1,80,-1,164).
+relate(1,80,-1,85).
+relate(1,80,-1,178).
+relate(1,82,-1,37).
+relate(1,82,-1,35).
+relate(1,82,-1,51).
+relate(1,84,-1,117).
+relate(1,84,-1,35).
+relate(1,86,-1,55).
+relate(1,86,-1,166).
+relate(1,86,-1,83).
+relate(1,88,-1,91).
+relate(1,88,-1,166).
+relate(1,90,-1,174).
+relate(1,90,-1,129).
+relate(1,92,-1,31).
+relate(1,92,-1,174).
+relate(1,92,-1,145).
+relate(1,92,-1,161).
+relate(1,94,-1,47).
+relate(1,94,-1,145).
+relate(1,94,-1,49).
+relate(1,94,-1,115).
+relate(1,96,-1,178).
+relate(1,96,-1,49).
+relate(1,96,-1,11).
+relate(1,98,-1,51).
+relate(1,98,-1,33).
+relate(1,98,-1,143).
+relate(1,100,-1,33).
+relate(1,100,-1,111).
+relate(1,102,-1,83).
+relate(1,102,-1,81).
+relate(1,104,-1,81).
+relate(1,104,-1,19).
+relate(1,104,-1,169).
+relate(1,106,-1,129).
+relate(1,106,-1,19).
+relate(1,106,-1,79).
+relate(1,106,-1,167).
+relate(1,108,-1,161).
+relate(1,108,-1,79).
+relate(1,108,-1,93).
+relate(1,110,-1,115).
+relate(1,110,-1,93).
+relate(1,110,-1,159).
+relate(1,110,-1,175).
+relate(1,112,-1,159).
+relate(1,114,-1,143).
+relate(1,114,-1,133).
+relate(1,116,-1,111).
+relate(1,116,-1,133).
+relate(1,116,-1,39).
+relate(1,118,-1,123).
+relate(1,118,-1,99).
+relate(1,120,-1,169).
+relate(1,120,-1,123).
+relate(1,122,-1,167).
+relate(1,122,-1,172).
+relate(1,124,-1,172).
+relate(1,126,-1,175).
+relate(1,126,-1,137).
+relate(1,126,-1,141).
+relate(1,128,-1,137).
+relate(1,128,-1,97).
+relate(1,130,-1,155).
+relate(1,130,-1,23).
+relate(1,132,-1,39).
+relate(1,132,-1,155).
+relate(1,132,-1,149).
+relate(1,134,-1,99).
+relate(1,134,-1,149).
+relate(1,134,-1,63).
+relate(1,134,-1,107).
+relate(1,136,-1,63).
+relate(1,138,-1,157).
+relate(1,138,-1,121).
+relate(1,140,-1,157).
+relate(1,140,-1,119).
+relate(1,142,-1,141).
+relate(1,142,-1,119).
+relate(1,144,-1,97).
+relate(1,144,-1,1).
+relate(1,146,-1,23).
+relate(1,146,-1,162).
+relate(1,146,-1,5).
+relate(1,148,-1,162).
+relate(1,148,-1,53).
+relate(1,150,-1,107).
+relate(1,150,-1,53).
+relate(1,150,-1,179).
+relate(1,150,-1,9).
+relate(1,152,-1,179).
+relate(1,154,-1,121).
+relate(1,154,-1,41).
+relate(1,156,-1,41).
+relate(1,156,-1,95).
+relate(1,156,-1,3).
+relate(1,158,-1,95).
+relate(-1,7,1,2).
+relate(-1,77,1,2).
+relate(-1,77,1,4).
+relate(-1,61,1,4).
+relate(-1,173,1,6).
+relate(-1,173,1,8).
+relate(-1,43,1,8).
+relate(-1,25,1,8).
+relate(-1,43,1,10).
+relate(-1,65,1,10).
+relate(-1,65,1,12).
+relate(-1,135,1,12).
+relate(-1,59,1,12).
+relate(-1,135,1,14).
+relate(-1,113,1,14).
+relate(-1,45,1,14).
+relate(-1,113,1,16).
+relate(-1,75,1,18).
+relate(-1,61,1,20).
+relate(-1,75,1,20).
+relate(-1,87,1,20).
+relate(-1,101,1,22).
+relate(-1,73,1,22).
+relate(-1,25,1,24).
+relate(-1,101,1,24).
+relate(-1,13,1,24).
+relate(-1,67,1,24).
+relate(-1,13,1,26).
+relate(-1,105,1,26).
+relate(-1,59,1,28).
+relate(-1,105,1,28).
+relate(-1,171,1,28).
+relate(-1,45,1,30).
+relate(-1,171,1,30).
+relate(-1,147,1,30).
+relate(-1,89,1,30).
+relate(-1,147,1,32).
+relate(-1,27,1,32).
+relate(-1,15,1,34).
+relate(-1,87,1,36).
+relate(-1,15,1,36).
+relate(-1,139,1,36).
+relate(-1,73,1,38).
+relate(-1,139,1,38).
+relate(-1,71,1,38).
+relate(-1,67,1,40).
+relate(-1,176,1,40).
+relate(-1,170,1,40).
+relate(-1,176,1,42).
+relate(-1,163,1,42).
+relate(-1,163,1,44).
+relate(-1,89,1,46).
+relate(-1,29,1,46).
+relate(-1,27,1,48).
+relate(-1,29,1,48).
+relate(-1,17,1,48).
+relate(-1,177,1,50).
+relate(-1,125,1,50).
+relate(-1,177,1,52).
+relate(-1,57,1,52).
+relate(-1,71,1,54).
+relate(-1,170,1,56).
+relate(-1,168,1,56).
+relate(-1,103,1,58).
+relate(-1,69,1,60).
+relate(-1,160,1,60).
+relate(-1,69,1,62).
+relate(-1,153,1,62).
+relate(-1,127,1,62).
+relate(-1,17,1,64).
+relate(-1,153,1,64).
+relate(-1,164,1,64).
+relate(-1,125,1,66).
+relate(-1,165,1,66).
+relate(-1,37,1,66).
+relate(-1,57,1,68).
+relate(-1,165,1,68).
+relate(-1,131,1,68).
+relate(-1,117,1,68).
+relate(-1,131,1,70).
+relate(-1,55,1,70).
+relate(-1,168,1,72).
+relate(-1,109,1,72).
+relate(-1,91,1,72).
+relate(-1,103,1,74).
+relate(-1,109,1,74).
+relate(-1,21,1,74).
+relate(-1,160,1,76).
+relate(-1,21,1,76).
+relate(-1,151,1,76).
+relate(-1,31,1,76).
+relate(-1,127,1,78).
+relate(-1,151,1,78).
+relate(-1,85,1,78).
+relate(-1,47,1,78).
+relate(-1,164,1,80).
+relate(-1,85,1,80).
+relate(-1,178,1,80).
+relate(-1,37,1,82).
+relate(-1,35,1,82).
+relate(-1,51,1,82).
+relate(-1,117,1,84).
+relate(-1,35,1,84).
+relate(-1,55,1,86).
+relate(-1,166,1,86).
+relate(-1,83,1,86).
+relate(-1,91,1,88).
+relate(-1,166,1,88).
+relate(-1,174,1,90).
+relate(-1,129,1,90).
+relate(-1,31,1,92).
+relate(-1,174,1,92).
+relate(-1,145,1,92).
+relate(-1,161,1,92).
+relate(-1,47,1,94).
+relate(-1,145,1,94).
+relate(-1,49,1,94).
+relate(-1,115,1,94).
+relate(-1,178,1,96).
+relate(-1,49,1,96).
+relate(-1,11,1,96).
+relate(-1,51,1,98).
+relate(-1,33,1,98).
+relate(-1,143,1,98).
+relate(-1,33,1,100).
+relate(-1,111,1,100).
+relate(-1,83,1,102).
+relate(-1,81,1,102).
+relate(-1,81,1,104).
+relate(-1,19,1,104).
+relate(-1,169,1,104).
+relate(-1,129,1,106).
+relate(-1,19,1,106).
+relate(-1,79,1,106).
+relate(-1,167,1,106).
+relate(-1,161,1,108).
+relate(-1,79,1,108).
+relate(-1,93,1,108).
+relate(-1,115,1,110).
+relate(-1,93,1,110).
+relate(-1,159,1,110).
+relate(-1,175,1,110).
+relate(-1,159,1,112).
+relate(-1,143,1,114).
+relate(-1,133,1,114).
+relate(-1,111,1,116).
+relate(-1,133,1,116).
+relate(-1,39,1,116).
+relate(-1,123,1,118).
+relate(-1,99,1,118).
+relate(-1,169,1,120).
+relate(-1,123,1,120).
+relate(-1,167,1,122).
+relate(-1,172,1,122).
+relate(-1,172,1,124).
+relate(-1,175,1,126).
+relate(-1,137,1,126).
+relate(-1,141,1,126).
+relate(-1,137,1,128).
+relate(-1,97,1,128).
+relate(-1,155,1,130).
+relate(-1,23,1,130).
+relate(-1,39,1,132).
+relate(-1,155,1,132).
+relate(-1,149,1,132).
+relate(-1,99,1,134).
+relate(-1,149,1,134).
+relate(-1,63,1,134).
+relate(-1,107,1,134).
+relate(-1,63,1,136).
+relate(-1,157,1,138).
+relate(-1,121,1,138).
+relate(-1,157,1,140).
+relate(-1,119,1,140).
+relate(-1,141,1,142).
+relate(-1,119,1,142).
+relate(-1,97,1,144).
+relate(-1,1,1,144).
+relate(-1,23,1,146).
+relate(-1,162,1,146).
+relate(-1,5,1,146).
+relate(-1,162,1,148).
+relate(-1,53,1,148).
+relate(-1,107,1,150).
+relate(-1,53,1,150).
+relate(-1,179,1,150).
+relate(-1,9,1,150).
+relate(-1,179,1,152).
+relate(-1,121,1,154).
+relate(-1,41,1,154).
+relate(-1,41,1,156).
+relate(-1,95,1,156).
+relate(-1,3,1,156).
+relate(-1,95,1,158).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/119-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/119-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..38d56b7
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/119-partner_units_polynomial-100-0.lp
@@ -0,0 +1,746 @@
+maxPU(2).
+#const n=179.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+object(-1,179).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(1,156,1,158).
+follow(-1,7,-1,9).
+follow(-1,143,-1,145).
+follow(-1,161,-1,162).
+follow(-1,139,-1,141).
+follow(-1,163,-1,164).
+follow(-1,172,-1,173).
+follow(-1,43,-1,45).
+follow(-1,157,-1,159).
+follow(-1,87,-1,89).
+follow(-1,115,-1,117).
+follow(-1,151,-1,153).
+follow(-1,55,-1,57).
+follow(-1,175,-1,176).
+follow(-1,127,-1,129).
+follow(-1,123,-1,125).
+follow(-1,159,-1,160).
+follow(-1,164,-1,165).
+follow(-1,95,-1,97).
+follow(-1,31,-1,33).
+follow(-1,166,-1,167).
+follow(-1,3,-1,5).
+follow(-1,113,-1,115).
+follow(-1,89,-1,91).
+follow(-1,85,-1,87).
+follow(-1,155,-1,157).
+follow(-1,165,-1,166).
+follow(-1,145,-1,147).
+follow(-1,19,-1,21).
+follow(-1,13,-1,15).
+follow(-1,103,-1,105).
+follow(-1,39,-1,41).
+follow(-1,15,-1,17).
+follow(-1,173,-1,174).
+follow(-1,49,-1,51).
+follow(-1,162,-1,163).
+follow(-1,41,-1,43).
+follow(-1,11,-1,13).
+follow(-1,93,-1,95).
+follow(-1,77,-1,79).
+follow(-1,75,-1,77).
+follow(-1,99,-1,101).
+follow(-1,135,-1,137).
+follow(-1,37,-1,39).
+follow(-1,1,-1,3).
+follow(-1,174,-1,175).
+follow(-1,67,-1,69).
+follow(-1,97,-1,99).
+follow(-1,61,-1,63).
+follow(-1,133,-1,135).
+follow(-1,69,-1,71).
+follow(-1,59,-1,61).
+follow(-1,109,-1,111).
+follow(-1,53,-1,55).
+follow(-1,119,-1,121).
+follow(-1,21,-1,23).
+follow(-1,167,-1,168).
+follow(-1,47,-1,49).
+follow(-1,160,-1,161).
+follow(-1,168,-1,169).
+follow(-1,81,-1,83).
+follow(-1,17,-1,19).
+follow(-1,91,-1,93).
+follow(-1,117,-1,119).
+follow(-1,141,-1,143).
+follow(-1,101,-1,103).
+follow(-1,178,-1,179).
+follow(-1,23,-1,25).
+follow(-1,170,-1,171).
+follow(-1,177,-1,178).
+follow(-1,51,-1,53).
+follow(-1,79,-1,81).
+follow(-1,111,-1,113).
+follow(-1,169,-1,170).
+follow(-1,131,-1,133).
+follow(-1,57,-1,59).
+follow(-1,45,-1,47).
+follow(-1,65,-1,67).
+follow(-1,35,-1,37).
+follow(-1,129,-1,131).
+follow(-1,105,-1,107).
+follow(-1,73,-1,75).
+follow(-1,137,-1,139).
+follow(-1,147,-1,149).
+follow(-1,63,-1,65).
+follow(-1,125,-1,127).
+follow(-1,83,-1,85).
+follow(-1,33,-1,35).
+follow(-1,171,-1,172).
+follow(-1,121,-1,123).
+follow(-1,176,-1,177).
+follow(-1,25,-1,27).
+follow(-1,149,-1,151).
+follow(-1,29,-1,31).
+follow(-1,9,-1,11).
+follow(-1,153,-1,155).
+follow(-1,5,-1,7).
+follow(-1,107,-1,109).
+follow(-1,71,-1,73).
+follow(-1,27,-1,29).
+relate(1,2,-1,1).
+relate(1,2,-1,9).
+relate(1,2,-1,145).
+relate(1,2,-1,162).
+relate(1,4,-1,145).
+relate(1,4,-1,141).
+relate(1,6,-1,164).
+relate(1,6,-1,173).
+relate(1,8,-1,164).
+relate(1,8,-1,45).
+relate(1,8,-1,159).
+relate(1,10,-1,45).
+relate(1,10,-1,89).
+relate(1,10,-1,117).
+relate(1,12,-1,89).
+relate(1,14,-1,153).
+relate(1,16,-1,57).
+relate(1,18,-1,162).
+relate(1,18,-1,176).
+relate(1,20,-1,141).
+relate(1,20,-1,176).
+relate(1,20,-1,129).
+relate(1,20,-1,125).
+relate(1,22,-1,173).
+relate(1,22,-1,129).
+relate(1,22,-1,160).
+relate(1,24,-1,159).
+relate(1,24,-1,165).
+relate(1,26,-1,117).
+relate(1,28,-1,97).
+relate(1,28,-1,33).
+relate(1,30,-1,153).
+relate(1,30,-1,97).
+relate(1,30,-1,167).
+relate(1,32,-1,57).
+relate(1,32,-1,167).
+relate(1,32,-1,5).
+relate(1,34,-1,115).
+relate(1,34,-1,91).
+relate(1,36,-1,125).
+relate(1,36,-1,115).
+relate(1,36,-1,87).
+relate(1,36,-1,157).
+relate(1,38,-1,160).
+relate(1,38,-1,87).
+relate(1,38,-1,166).
+relate(1,38,-1,147).
+relate(1,40,-1,165).
+relate(1,40,-1,166).
+relate(1,40,-1,21).
+relate(1,40,-1,15).
+relate(1,42,-1,21).
+relate(1,42,-1,105).
+relate(1,42,-1,41).
+relate(1,44,-1,33).
+relate(1,44,-1,105).
+relate(1,46,-1,17).
+relate(1,48,-1,17).
+relate(1,48,-1,174).
+relate(1,50,-1,91).
+relate(1,50,-1,51).
+relate(1,52,-1,157).
+relate(1,52,-1,51).
+relate(1,52,-1,163).
+relate(1,54,-1,147).
+relate(1,54,-1,163).
+relate(1,54,-1,43).
+relate(1,56,-1,15).
+relate(1,56,-1,43).
+relate(1,56,-1,13).
+relate(1,56,-1,95).
+relate(1,58,-1,41).
+relate(1,58,-1,13).
+relate(1,58,-1,79).
+relate(1,58,-1,77).
+relate(1,60,-1,79).
+relate(1,62,-1,101).
+relate(1,62,-1,137).
+relate(1,64,-1,174).
+relate(1,64,-1,101).
+relate(1,64,-1,39).
+relate(1,66,-1,3).
+relate(1,66,-1,175).
+relate(1,68,-1,175).
+relate(1,68,-1,69).
+relate(1,70,-1,99).
+relate(1,72,-1,95).
+relate(1,72,-1,99).
+relate(1,72,-1,63).
+relate(1,72,-1,135).
+relate(1,74,-1,77).
+relate(1,74,-1,63).
+relate(1,74,-1,71).
+relate(1,76,-1,137).
+relate(1,76,-1,61).
+relate(1,76,-1,111).
+relate(1,78,-1,39).
+relate(1,78,-1,61).
+relate(1,78,-1,55).
+relate(1,80,-1,121).
+relate(1,80,-1,23).
+relate(1,82,-1,69).
+relate(1,82,-1,121).
+relate(1,82,-1,168).
+relate(1,84,-1,168).
+relate(1,84,-1,49).
+relate(1,86,-1,135).
+relate(1,86,-1,161).
+relate(1,88,-1,71).
+relate(1,88,-1,161).
+relate(1,88,-1,169).
+relate(1,88,-1,83).
+relate(1,90,-1,169).
+relate(1,90,-1,19).
+relate(1,90,-1,93).
+relate(1,92,-1,111).
+relate(1,92,-1,19).
+relate(1,92,-1,119).
+relate(1,94,-1,55).
+relate(1,94,-1,119).
+relate(1,96,-1,23).
+relate(1,96,-1,143).
+relate(1,98,-1,143).
+relate(1,98,-1,103).
+relate(1,98,-1,179).
+relate(1,100,-1,49).
+relate(1,100,-1,103).
+relate(1,100,-1,25).
+relate(1,102,-1,171).
+relate(1,104,-1,83).
+relate(1,104,-1,178).
+relate(1,104,-1,53).
+relate(1,106,-1,93).
+relate(1,106,-1,178).
+relate(1,106,-1,81).
+relate(1,108,-1,113).
+relate(1,110,-1,170).
+relate(1,112,-1,133).
+relate(1,114,-1,179).
+relate(1,114,-1,133).
+relate(1,116,-1,25).
+relate(1,116,-1,59).
+relate(1,116,-1,47).
+relate(1,118,-1,171).
+relate(1,118,-1,59).
+relate(1,118,-1,67).
+relate(1,118,-1,37).
+relate(1,120,-1,53).
+relate(1,120,-1,67).
+relate(1,120,-1,131).
+relate(1,122,-1,81).
+relate(1,122,-1,131).
+relate(1,122,-1,107).
+relate(1,124,-1,113).
+relate(1,124,-1,75).
+relate(1,124,-1,139).
+relate(1,126,-1,170).
+relate(1,126,-1,75).
+relate(1,126,-1,149).
+relate(1,128,-1,65).
+relate(1,130,-1,65).
+relate(1,130,-1,127).
+relate(1,132,-1,47).
+relate(1,132,-1,85).
+relate(1,134,-1,37).
+relate(1,136,-1,35).
+relate(1,138,-1,107).
+relate(1,138,-1,172).
+relate(1,138,-1,123).
+relate(1,140,-1,139).
+relate(1,140,-1,172).
+relate(1,140,-1,177).
+relate(1,140,-1,27).
+relate(1,142,-1,149).
+relate(1,142,-1,177).
+relate(1,142,-1,151).
+relate(1,144,-1,31).
+relate(1,144,-1,11).
+relate(1,146,-1,127).
+relate(1,146,-1,31).
+relate(1,146,-1,155).
+relate(1,146,-1,7).
+relate(1,148,-1,85).
+relate(1,148,-1,155).
+relate(1,148,-1,109).
+relate(1,150,-1,109).
+relate(1,150,-1,73).
+relate(1,152,-1,35).
+relate(1,152,-1,73).
+relate(1,154,-1,123).
+relate(1,156,-1,27).
+relate(1,156,-1,29).
+relate(1,158,-1,151).
+relate(1,158,-1,29).
+relate(-1,1,1,2).
+relate(-1,9,1,2).
+relate(-1,145,1,2).
+relate(-1,162,1,2).
+relate(-1,145,1,4).
+relate(-1,141,1,4).
+relate(-1,164,1,6).
+relate(-1,173,1,6).
+relate(-1,164,1,8).
+relate(-1,45,1,8).
+relate(-1,159,1,8).
+relate(-1,45,1,10).
+relate(-1,89,1,10).
+relate(-1,117,1,10).
+relate(-1,89,1,12).
+relate(-1,153,1,14).
+relate(-1,57,1,16).
+relate(-1,162,1,18).
+relate(-1,176,1,18).
+relate(-1,141,1,20).
+relate(-1,176,1,20).
+relate(-1,129,1,20).
+relate(-1,125,1,20).
+relate(-1,173,1,22).
+relate(-1,129,1,22).
+relate(-1,160,1,22).
+relate(-1,159,1,24).
+relate(-1,165,1,24).
+relate(-1,117,1,26).
+relate(-1,97,1,28).
+relate(-1,33,1,28).
+relate(-1,153,1,30).
+relate(-1,97,1,30).
+relate(-1,167,1,30).
+relate(-1,57,1,32).
+relate(-1,167,1,32).
+relate(-1,5,1,32).
+relate(-1,115,1,34).
+relate(-1,91,1,34).
+relate(-1,125,1,36).
+relate(-1,115,1,36).
+relate(-1,87,1,36).
+relate(-1,157,1,36).
+relate(-1,160,1,38).
+relate(-1,87,1,38).
+relate(-1,166,1,38).
+relate(-1,147,1,38).
+relate(-1,165,1,40).
+relate(-1,166,1,40).
+relate(-1,21,1,40).
+relate(-1,15,1,40).
+relate(-1,21,1,42).
+relate(-1,105,1,42).
+relate(-1,41,1,42).
+relate(-1,33,1,44).
+relate(-1,105,1,44).
+relate(-1,17,1,46).
+relate(-1,17,1,48).
+relate(-1,174,1,48).
+relate(-1,91,1,50).
+relate(-1,51,1,50).
+relate(-1,157,1,52).
+relate(-1,51,1,52).
+relate(-1,163,1,52).
+relate(-1,147,1,54).
+relate(-1,163,1,54).
+relate(-1,43,1,54).
+relate(-1,15,1,56).
+relate(-1,43,1,56).
+relate(-1,13,1,56).
+relate(-1,95,1,56).
+relate(-1,41,1,58).
+relate(-1,13,1,58).
+relate(-1,79,1,58).
+relate(-1,77,1,58).
+relate(-1,79,1,60).
+relate(-1,101,1,62).
+relate(-1,137,1,62).
+relate(-1,174,1,64).
+relate(-1,101,1,64).
+relate(-1,39,1,64).
+relate(-1,3,1,66).
+relate(-1,175,1,66).
+relate(-1,175,1,68).
+relate(-1,69,1,68).
+relate(-1,99,1,70).
+relate(-1,95,1,72).
+relate(-1,99,1,72).
+relate(-1,63,1,72).
+relate(-1,135,1,72).
+relate(-1,77,1,74).
+relate(-1,63,1,74).
+relate(-1,71,1,74).
+relate(-1,137,1,76).
+relate(-1,61,1,76).
+relate(-1,111,1,76).
+relate(-1,39,1,78).
+relate(-1,61,1,78).
+relate(-1,55,1,78).
+relate(-1,121,1,80).
+relate(-1,23,1,80).
+relate(-1,69,1,82).
+relate(-1,121,1,82).
+relate(-1,168,1,82).
+relate(-1,168,1,84).
+relate(-1,49,1,84).
+relate(-1,135,1,86).
+relate(-1,161,1,86).
+relate(-1,71,1,88).
+relate(-1,161,1,88).
+relate(-1,169,1,88).
+relate(-1,83,1,88).
+relate(-1,169,1,90).
+relate(-1,19,1,90).
+relate(-1,93,1,90).
+relate(-1,111,1,92).
+relate(-1,19,1,92).
+relate(-1,119,1,92).
+relate(-1,55,1,94).
+relate(-1,119,1,94).
+relate(-1,23,1,96).
+relate(-1,143,1,96).
+relate(-1,143,1,98).
+relate(-1,103,1,98).
+relate(-1,179,1,98).
+relate(-1,49,1,100).
+relate(-1,103,1,100).
+relate(-1,25,1,100).
+relate(-1,171,1,102).
+relate(-1,83,1,104).
+relate(-1,178,1,104).
+relate(-1,53,1,104).
+relate(-1,93,1,106).
+relate(-1,178,1,106).
+relate(-1,81,1,106).
+relate(-1,113,1,108).
+relate(-1,170,1,110).
+relate(-1,133,1,112).
+relate(-1,179,1,114).
+relate(-1,133,1,114).
+relate(-1,25,1,116).
+relate(-1,59,1,116).
+relate(-1,47,1,116).
+relate(-1,171,1,118).
+relate(-1,59,1,118).
+relate(-1,67,1,118).
+relate(-1,37,1,118).
+relate(-1,53,1,120).
+relate(-1,67,1,120).
+relate(-1,131,1,120).
+relate(-1,81,1,122).
+relate(-1,131,1,122).
+relate(-1,107,1,122).
+relate(-1,113,1,124).
+relate(-1,75,1,124).
+relate(-1,139,1,124).
+relate(-1,170,1,126).
+relate(-1,75,1,126).
+relate(-1,149,1,126).
+relate(-1,65,1,128).
+relate(-1,65,1,130).
+relate(-1,127,1,130).
+relate(-1,47,1,132).
+relate(-1,85,1,132).
+relate(-1,37,1,134).
+relate(-1,35,1,136).
+relate(-1,107,1,138).
+relate(-1,172,1,138).
+relate(-1,123,1,138).
+relate(-1,139,1,140).
+relate(-1,172,1,140).
+relate(-1,177,1,140).
+relate(-1,27,1,140).
+relate(-1,149,1,142).
+relate(-1,177,1,142).
+relate(-1,151,1,142).
+relate(-1,31,1,144).
+relate(-1,11,1,144).
+relate(-1,127,1,146).
+relate(-1,31,1,146).
+relate(-1,155,1,146).
+relate(-1,7,1,146).
+relate(-1,85,1,148).
+relate(-1,155,1,148).
+relate(-1,109,1,148).
+relate(-1,109,1,150).
+relate(-1,73,1,150).
+relate(-1,35,1,152).
+relate(-1,73,1,152).
+relate(-1,123,1,154).
+relate(-1,27,1,156).
+relate(-1,29,1,156).
+relate(-1,151,1,158).
+relate(-1,29,1,158).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/127-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/127-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..d42a4cc
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/127-partner_units_polynomial-100-0.lp
@@ -0,0 +1,740 @@
+maxPU(2).
+#const n=176.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(-1,154).
+object(-1,155).
+object(-1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(-1,115,-1,117).
+follow(-1,87,-1,89).
+follow(-1,39,-1,41).
+follow(-1,153,-1,154).
+follow(-1,113,-1,115).
+follow(-1,119,-1,121).
+follow(-1,172,-1,173).
+follow(-1,9,-1,11).
+follow(-1,51,-1,53).
+follow(-1,159,-1,160).
+follow(-1,49,-1,51).
+follow(-1,93,-1,95).
+follow(-1,165,-1,166).
+follow(-1,83,-1,85).
+follow(-1,164,-1,165).
+follow(-1,77,-1,79).
+follow(-1,166,-1,167).
+follow(-1,47,-1,49).
+follow(-1,131,-1,133).
+follow(-1,23,-1,25).
+follow(-1,11,-1,13).
+follow(-1,19,-1,21).
+follow(-1,147,-1,149).
+follow(-1,73,-1,75).
+follow(-1,17,-1,19).
+follow(-1,89,-1,91).
+follow(-1,97,-1,99).
+follow(-1,95,-1,97).
+follow(-1,121,-1,123).
+follow(-1,105,-1,107).
+follow(-1,123,-1,125).
+follow(-1,137,-1,139).
+follow(-1,111,-1,113).
+follow(-1,91,-1,93).
+follow(-1,35,-1,37).
+follow(-1,61,-1,63).
+follow(-1,81,-1,83).
+follow(-1,67,-1,69).
+follow(-1,170,-1,171).
+follow(-1,37,-1,39).
+follow(-1,167,-1,168).
+follow(-1,171,-1,172).
+follow(-1,109,-1,111).
+follow(-1,85,-1,87).
+follow(-1,53,-1,55).
+follow(-1,155,-1,156).
+follow(-1,71,-1,73).
+follow(-1,103,-1,105).
+follow(-1,107,-1,109).
+follow(-1,162,-1,163).
+follow(-1,160,-1,161).
+follow(-1,13,-1,15).
+follow(-1,57,-1,59).
+follow(-1,145,-1,147).
+follow(-1,41,-1,43).
+follow(-1,129,-1,131).
+follow(-1,63,-1,65).
+follow(-1,174,-1,175).
+follow(-1,31,-1,33).
+follow(-1,154,-1,155).
+follow(-1,33,-1,35).
+follow(-1,168,-1,169).
+follow(-1,45,-1,47).
+follow(-1,99,-1,101).
+follow(-1,133,-1,135).
+follow(-1,135,-1,137).
+follow(-1,25,-1,27).
+follow(-1,173,-1,174).
+follow(-1,143,-1,145).
+follow(-1,125,-1,127).
+follow(-1,175,-1,176).
+follow(-1,101,-1,103).
+follow(-1,27,-1,29).
+follow(-1,157,-1,158).
+follow(-1,29,-1,31).
+follow(-1,151,-1,153).
+follow(-1,158,-1,159).
+follow(-1,156,-1,157).
+follow(-1,163,-1,164).
+follow(-1,69,-1,71).
+follow(-1,169,-1,170).
+follow(-1,65,-1,67).
+follow(-1,149,-1,151).
+follow(-1,55,-1,57).
+follow(-1,141,-1,143).
+follow(-1,117,-1,119).
+follow(-1,43,-1,45).
+follow(-1,21,-1,23).
+follow(-1,161,-1,162).
+follow(-1,15,-1,17).
+follow(-1,75,-1,77).
+follow(-1,7,-1,9).
+follow(-1,139,-1,141).
+follow(-1,127,-1,129).
+follow(-1,5,-1,7).
+follow(-1,59,-1,61).
+follow(-1,79,-1,81).
+follow(-1,3,-1,5).
+follow(-1,1,-1,3).
+relate(1,2,-1,117).
+relate(1,2,-1,89).
+relate(1,4,-1,117).
+relate(1,4,-1,41).
+relate(1,4,-1,154).
+relate(1,6,-1,41).
+relate(1,6,-1,115).
+relate(1,6,-1,121).
+relate(1,8,-1,115).
+relate(1,8,-1,173).
+relate(1,10,-1,11).
+relate(1,10,-1,53).
+relate(1,10,-1,160).
+relate(1,12,-1,53).
+relate(1,12,-1,51).
+relate(1,14,-1,95).
+relate(1,16,-1,95).
+relate(1,16,-1,166).
+relate(1,18,-1,89).
+relate(1,18,-1,85).
+relate(1,20,-1,154).
+relate(1,20,-1,165).
+relate(1,20,-1,79).
+relate(1,22,-1,121).
+relate(1,22,-1,165).
+relate(1,22,-1,167).
+relate(1,22,-1,49).
+relate(1,24,-1,173).
+relate(1,24,-1,167).
+relate(1,24,-1,133).
+relate(1,24,-1,25).
+relate(1,26,-1,160).
+relate(1,26,-1,133).
+relate(1,26,-1,13).
+relate(1,28,-1,51).
+relate(1,28,-1,13).
+relate(1,28,-1,21).
+relate(1,30,-1,21).
+relate(1,30,-1,149).
+relate(1,32,-1,166).
+relate(1,32,-1,149).
+relate(1,32,-1,75).
+relate(1,34,-1,85).
+relate(1,34,-1,19).
+relate(1,34,-1,91).
+relate(1,36,-1,79).
+relate(1,36,-1,19).
+relate(1,36,-1,99).
+relate(1,38,-1,49).
+relate(1,38,-1,99).
+relate(1,38,-1,97).
+relate(1,40,-1,25).
+relate(1,40,-1,97).
+relate(1,40,-1,123).
+relate(1,42,-1,123).
+relate(1,42,-1,107).
+relate(1,44,-1,125).
+relate(1,44,-1,139).
+relate(1,46,-1,125).
+relate(1,46,-1,113).
+relate(1,48,-1,75).
+relate(1,48,-1,113).
+relate(1,48,-1,93).
+relate(1,50,-1,91).
+relate(1,50,-1,1).
+relate(1,50,-1,37).
+relate(1,52,-1,37).
+relate(1,52,-1,63).
+relate(1,54,-1,107).
+relate(1,54,-1,83).
+relate(1,54,-1,69).
+relate(1,56,-1,139).
+relate(1,56,-1,83).
+relate(1,56,-1,171).
+relate(1,58,-1,93).
+relate(1,58,-1,39).
+relate(1,60,-1,168).
+relate(1,62,-1,63).
+relate(1,62,-1,172).
+relate(1,64,-1,111).
+relate(1,64,-1,87).
+relate(1,66,-1,111).
+relate(1,66,-1,55).
+relate(1,66,-1,156).
+relate(1,68,-1,69).
+relate(1,68,-1,55).
+relate(1,68,-1,73).
+relate(1,68,-1,105).
+relate(1,70,-1,171).
+relate(1,70,-1,73).
+relate(1,70,-1,109).
+relate(1,70,-1,163).
+relate(1,72,-1,109).
+relate(1,72,-1,161).
+relate(1,72,-1,15).
+relate(1,74,-1,39).
+relate(1,74,-1,161).
+relate(1,74,-1,59).
+relate(1,76,-1,168).
+relate(1,76,-1,147).
+relate(1,78,-1,172).
+relate(1,78,-1,43).
+relate(1,80,-1,87).
+relate(1,80,-1,43).
+relate(1,82,-1,156).
+relate(1,82,-1,131).
+relate(1,84,-1,105).
+relate(1,86,-1,163).
+relate(1,86,-1,65).
+relate(1,88,-1,15).
+relate(1,88,-1,65).
+relate(1,88,-1,175).
+relate(1,88,-1,33).
+relate(1,90,-1,59).
+relate(1,90,-1,175).
+relate(1,90,-1,155).
+relate(1,92,-1,147).
+relate(1,92,-1,35).
+relate(1,92,-1,169).
+relate(1,94,-1,35).
+relate(1,94,-1,47).
+relate(1,96,-1,101).
+relate(1,96,-1,135).
+relate(1,98,-1,131).
+relate(1,98,-1,101).
+relate(1,98,-1,137).
+relate(1,100,-1,137).
+relate(1,100,-1,27).
+relate(1,100,-1,174).
+relate(1,102,-1,27).
+relate(1,102,-1,145).
+relate(1,104,-1,33).
+relate(1,104,-1,145).
+relate(1,104,-1,127).
+relate(1,106,-1,155).
+relate(1,106,-1,176).
+relate(1,108,-1,169).
+relate(1,110,-1,47).
+relate(1,110,-1,103).
+relate(1,110,-1,29).
+relate(1,112,-1,135).
+relate(1,112,-1,103).
+relate(1,114,-1,158).
+relate(1,116,-1,174).
+relate(1,116,-1,31).
+relate(1,116,-1,153).
+relate(1,118,-1,31).
+relate(1,118,-1,159).
+relate(1,120,-1,127).
+relate(1,120,-1,159).
+relate(1,120,-1,157).
+relate(1,122,-1,176).
+relate(1,122,-1,164).
+relate(1,124,-1,71).
+relate(1,126,-1,29).
+relate(1,126,-1,71).
+relate(1,126,-1,170).
+relate(1,126,-1,67).
+relate(1,128,-1,170).
+relate(1,128,-1,151).
+relate(1,128,-1,57).
+relate(1,130,-1,158).
+relate(1,130,-1,151).
+relate(1,130,-1,143).
+relate(1,130,-1,119).
+relate(1,132,-1,153).
+relate(1,132,-1,143).
+relate(1,132,-1,45).
+relate(1,132,-1,23).
+relate(1,134,-1,45).
+relate(1,134,-1,162).
+relate(1,136,-1,157).
+relate(1,136,-1,162).
+relate(1,136,-1,17).
+relate(1,136,-1,77).
+relate(1,138,-1,164).
+relate(1,138,-1,17).
+relate(1,138,-1,9).
+relate(1,138,-1,141).
+relate(1,140,-1,129).
+relate(1,140,-1,7).
+relate(1,142,-1,67).
+relate(1,142,-1,129).
+relate(1,142,-1,61).
+relate(1,144,-1,57).
+relate(1,144,-1,61).
+relate(1,146,-1,119).
+relate(1,146,-1,81).
+relate(1,146,-1,5).
+relate(1,148,-1,23).
+relate(1,148,-1,81).
+relate(1,148,-1,3).
+relate(1,150,-1,77).
+relate(1,152,-1,141).
+relate(-1,117,1,2).
+relate(-1,89,1,2).
+relate(-1,117,1,4).
+relate(-1,41,1,4).
+relate(-1,154,1,4).
+relate(-1,41,1,6).
+relate(-1,115,1,6).
+relate(-1,121,1,6).
+relate(-1,115,1,8).
+relate(-1,173,1,8).
+relate(-1,11,1,10).
+relate(-1,53,1,10).
+relate(-1,160,1,10).
+relate(-1,53,1,12).
+relate(-1,51,1,12).
+relate(-1,95,1,14).
+relate(-1,95,1,16).
+relate(-1,166,1,16).
+relate(-1,89,1,18).
+relate(-1,85,1,18).
+relate(-1,154,1,20).
+relate(-1,165,1,20).
+relate(-1,79,1,20).
+relate(-1,121,1,22).
+relate(-1,165,1,22).
+relate(-1,167,1,22).
+relate(-1,49,1,22).
+relate(-1,173,1,24).
+relate(-1,167,1,24).
+relate(-1,133,1,24).
+relate(-1,25,1,24).
+relate(-1,160,1,26).
+relate(-1,133,1,26).
+relate(-1,13,1,26).
+relate(-1,51,1,28).
+relate(-1,13,1,28).
+relate(-1,21,1,28).
+relate(-1,21,1,30).
+relate(-1,149,1,30).
+relate(-1,166,1,32).
+relate(-1,149,1,32).
+relate(-1,75,1,32).
+relate(-1,85,1,34).
+relate(-1,19,1,34).
+relate(-1,91,1,34).
+relate(-1,79,1,36).
+relate(-1,19,1,36).
+relate(-1,99,1,36).
+relate(-1,49,1,38).
+relate(-1,99,1,38).
+relate(-1,97,1,38).
+relate(-1,25,1,40).
+relate(-1,97,1,40).
+relate(-1,123,1,40).
+relate(-1,123,1,42).
+relate(-1,107,1,42).
+relate(-1,125,1,44).
+relate(-1,139,1,44).
+relate(-1,125,1,46).
+relate(-1,113,1,46).
+relate(-1,75,1,48).
+relate(-1,113,1,48).
+relate(-1,93,1,48).
+relate(-1,91,1,50).
+relate(-1,1,1,50).
+relate(-1,37,1,50).
+relate(-1,37,1,52).
+relate(-1,63,1,52).
+relate(-1,107,1,54).
+relate(-1,83,1,54).
+relate(-1,69,1,54).
+relate(-1,139,1,56).
+relate(-1,83,1,56).
+relate(-1,171,1,56).
+relate(-1,93,1,58).
+relate(-1,39,1,58).
+relate(-1,168,1,60).
+relate(-1,63,1,62).
+relate(-1,172,1,62).
+relate(-1,111,1,64).
+relate(-1,87,1,64).
+relate(-1,111,1,66).
+relate(-1,55,1,66).
+relate(-1,156,1,66).
+relate(-1,69,1,68).
+relate(-1,55,1,68).
+relate(-1,73,1,68).
+relate(-1,105,1,68).
+relate(-1,171,1,70).
+relate(-1,73,1,70).
+relate(-1,109,1,70).
+relate(-1,163,1,70).
+relate(-1,109,1,72).
+relate(-1,161,1,72).
+relate(-1,15,1,72).
+relate(-1,39,1,74).
+relate(-1,161,1,74).
+relate(-1,59,1,74).
+relate(-1,168,1,76).
+relate(-1,147,1,76).
+relate(-1,172,1,78).
+relate(-1,43,1,78).
+relate(-1,87,1,80).
+relate(-1,43,1,80).
+relate(-1,156,1,82).
+relate(-1,131,1,82).
+relate(-1,105,1,84).
+relate(-1,163,1,86).
+relate(-1,65,1,86).
+relate(-1,15,1,88).
+relate(-1,65,1,88).
+relate(-1,175,1,88).
+relate(-1,33,1,88).
+relate(-1,59,1,90).
+relate(-1,175,1,90).
+relate(-1,155,1,90).
+relate(-1,147,1,92).
+relate(-1,35,1,92).
+relate(-1,169,1,92).
+relate(-1,35,1,94).
+relate(-1,47,1,94).
+relate(-1,101,1,96).
+relate(-1,135,1,96).
+relate(-1,131,1,98).
+relate(-1,101,1,98).
+relate(-1,137,1,98).
+relate(-1,137,1,100).
+relate(-1,27,1,100).
+relate(-1,174,1,100).
+relate(-1,27,1,102).
+relate(-1,145,1,102).
+relate(-1,33,1,104).
+relate(-1,145,1,104).
+relate(-1,127,1,104).
+relate(-1,155,1,106).
+relate(-1,176,1,106).
+relate(-1,169,1,108).
+relate(-1,47,1,110).
+relate(-1,103,1,110).
+relate(-1,29,1,110).
+relate(-1,135,1,112).
+relate(-1,103,1,112).
+relate(-1,158,1,114).
+relate(-1,174,1,116).
+relate(-1,31,1,116).
+relate(-1,153,1,116).
+relate(-1,31,1,118).
+relate(-1,159,1,118).
+relate(-1,127,1,120).
+relate(-1,159,1,120).
+relate(-1,157,1,120).
+relate(-1,176,1,122).
+relate(-1,164,1,122).
+relate(-1,71,1,124).
+relate(-1,29,1,126).
+relate(-1,71,1,126).
+relate(-1,170,1,126).
+relate(-1,67,1,126).
+relate(-1,170,1,128).
+relate(-1,151,1,128).
+relate(-1,57,1,128).
+relate(-1,158,1,130).
+relate(-1,151,1,130).
+relate(-1,143,1,130).
+relate(-1,119,1,130).
+relate(-1,153,1,132).
+relate(-1,143,1,132).
+relate(-1,45,1,132).
+relate(-1,23,1,132).
+relate(-1,45,1,134).
+relate(-1,162,1,134).
+relate(-1,157,1,136).
+relate(-1,162,1,136).
+relate(-1,17,1,136).
+relate(-1,77,1,136).
+relate(-1,164,1,138).
+relate(-1,17,1,138).
+relate(-1,9,1,138).
+relate(-1,141,1,138).
+relate(-1,129,1,140).
+relate(-1,7,1,140).
+relate(-1,67,1,142).
+relate(-1,129,1,142).
+relate(-1,61,1,142).
+relate(-1,57,1,144).
+relate(-1,61,1,144).
+relate(-1,119,1,146).
+relate(-1,81,1,146).
+relate(-1,5,1,146).
+relate(-1,23,1,148).
+relate(-1,81,1,148).
+relate(-1,3,1,148).
+relate(-1,77,1,150).
+relate(-1,141,1,152).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/153-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/153-partner_units-100-0.lp
new file mode 100644
index 0000000..de698e2
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/153-partner_units-100-0.lp
@@ -0,0 +1,748 @@
+maxPU(4).
+#const n=180.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(1,158).
+object(-1,159).
+object(1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+object(-1,179).
+object(-1,180).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(1,156,1,158).
+follow(1,158,1,160).
+follow(-1,3,-1,5).
+follow(-1,175,-1,176).
+follow(-1,115,-1,117).
+follow(-1,7,-1,9).
+follow(-1,59,-1,61).
+follow(-1,53,-1,55).
+follow(-1,41,-1,43).
+follow(-1,127,-1,129).
+follow(-1,161,-1,162).
+follow(-1,9,-1,11).
+follow(-1,174,-1,175).
+follow(-1,129,-1,131).
+follow(-1,5,-1,7).
+follow(-1,168,-1,169).
+follow(-1,151,-1,153).
+follow(-1,164,-1,165).
+follow(-1,57,-1,59).
+follow(-1,69,-1,71).
+follow(-1,89,-1,91).
+follow(-1,71,-1,73).
+follow(-1,125,-1,127).
+follow(-1,137,-1,139).
+follow(-1,39,-1,41).
+follow(-1,65,-1,67).
+follow(-1,51,-1,53).
+follow(-1,25,-1,27).
+follow(-1,55,-1,57).
+follow(-1,101,-1,103).
+follow(-1,139,-1,141).
+follow(-1,107,-1,109).
+follow(-1,176,-1,177).
+follow(-1,1,-1,3).
+follow(-1,15,-1,17).
+follow(-1,109,-1,111).
+follow(-1,87,-1,89).
+follow(-1,111,-1,113).
+follow(-1,37,-1,39).
+follow(-1,81,-1,83).
+follow(-1,73,-1,75).
+follow(-1,166,-1,167).
+follow(-1,123,-1,125).
+follow(-1,141,-1,143).
+follow(-1,35,-1,37).
+follow(-1,85,-1,87).
+follow(-1,149,-1,151).
+follow(-1,99,-1,101).
+follow(-1,172,-1,173).
+follow(-1,170,-1,171).
+follow(-1,133,-1,135).
+follow(-1,147,-1,149).
+follow(-1,13,-1,15).
+follow(-1,135,-1,137).
+follow(-1,153,-1,155).
+follow(-1,117,-1,119).
+follow(-1,19,-1,21).
+follow(-1,169,-1,170).
+follow(-1,29,-1,31).
+follow(-1,67,-1,69).
+follow(-1,145,-1,147).
+follow(-1,179,-1,180).
+follow(-1,93,-1,95).
+follow(-1,103,-1,105).
+follow(-1,31,-1,33).
+follow(-1,165,-1,166).
+follow(-1,75,-1,77).
+follow(-1,105,-1,107).
+follow(-1,43,-1,45).
+follow(-1,155,-1,157).
+follow(-1,113,-1,115).
+follow(-1,33,-1,35).
+follow(-1,131,-1,133).
+follow(-1,143,-1,145).
+follow(-1,79,-1,81).
+follow(-1,119,-1,121).
+follow(-1,121,-1,123).
+follow(-1,61,-1,63).
+follow(-1,97,-1,99).
+follow(-1,157,-1,159).
+follow(-1,83,-1,85).
+follow(-1,173,-1,174).
+follow(-1,95,-1,97).
+follow(-1,49,-1,51).
+follow(-1,17,-1,19).
+follow(-1,162,-1,163).
+follow(-1,177,-1,178).
+follow(-1,63,-1,65).
+follow(-1,77,-1,79).
+follow(-1,163,-1,164).
+follow(-1,21,-1,23).
+follow(-1,159,-1,161).
+follow(-1,47,-1,49).
+follow(-1,11,-1,13).
+follow(-1,45,-1,47).
+follow(-1,91,-1,93).
+follow(-1,167,-1,168).
+follow(-1,178,-1,179).
+follow(-1,27,-1,29).
+follow(-1,23,-1,25).
+follow(-1,171,-1,172).
+relate(1,2,-1,5).
+relate(1,2,-1,176).
+relate(1,4,-1,117).
+relate(1,6,-1,9).
+relate(1,6,-1,61).
+relate(1,8,-1,61).
+relate(1,8,-1,55).
+relate(1,10,-1,43).
+relate(1,12,-1,129).
+relate(1,12,-1,162).
+relate(1,14,-1,11).
+relate(1,14,-1,129).
+relate(1,14,-1,175).
+relate(1,16,-1,131).
+relate(1,18,-1,176).
+relate(1,18,-1,7).
+relate(1,18,-1,169).
+relate(1,18,-1,153).
+relate(1,20,-1,117).
+relate(1,20,-1,169).
+relate(1,20,-1,165).
+relate(1,22,-1,59).
+relate(1,24,-1,55).
+relate(1,24,-1,71).
+relate(1,26,-1,43).
+relate(1,26,-1,91).
+relate(1,28,-1,162).
+relate(1,28,-1,73).
+relate(1,30,-1,175).
+relate(1,30,-1,73).
+relate(1,30,-1,127).
+relate(1,30,-1,139).
+relate(1,32,-1,131).
+relate(1,32,-1,127).
+relate(1,34,-1,153).
+relate(1,34,-1,41).
+relate(1,36,-1,165).
+relate(1,36,-1,67).
+relate(1,36,-1,53).
+relate(1,38,-1,59).
+relate(1,38,-1,67).
+relate(1,40,-1,71).
+relate(1,40,-1,27).
+relate(1,42,-1,91).
+relate(1,42,-1,57).
+relate(1,42,-1,103).
+relate(1,44,-1,57).
+relate(1,44,-1,141).
+relate(1,46,-1,139).
+relate(1,46,-1,141).
+relate(1,46,-1,109).
+relate(1,46,-1,177).
+relate(1,48,-1,109).
+relate(1,48,-1,3).
+relate(1,48,-1,17).
+relate(1,50,-1,41).
+relate(1,50,-1,1).
+relate(1,50,-1,111).
+relate(1,52,-1,53).
+relate(1,52,-1,111).
+relate(1,52,-1,89).
+relate(1,52,-1,113).
+relate(1,54,-1,89).
+relate(1,54,-1,39).
+relate(1,56,-1,27).
+relate(1,56,-1,83).
+relate(1,58,-1,103).
+relate(1,58,-1,83).
+relate(1,58,-1,75).
+relate(1,58,-1,167).
+relate(1,60,-1,75).
+relate(1,60,-1,125).
+relate(1,62,-1,177).
+relate(1,62,-1,143).
+relate(1,64,-1,17).
+relate(1,64,-1,143).
+relate(1,64,-1,37).
+relate(1,66,-1,87).
+relate(1,68,-1,113).
+relate(1,68,-1,87).
+relate(1,68,-1,151).
+relate(1,70,-1,39).
+relate(1,70,-1,151).
+relate(1,70,-1,101).
+relate(1,70,-1,173).
+relate(1,72,-1,101).
+relate(1,72,-1,171).
+relate(1,74,-1,167).
+relate(1,74,-1,135).
+relate(1,76,-1,125).
+relate(1,76,-1,135).
+relate(1,76,-1,149).
+relate(1,76,-1,15).
+relate(1,78,-1,149).
+relate(1,78,-1,137).
+relate(1,78,-1,155).
+relate(1,80,-1,37).
+relate(1,80,-1,137).
+relate(1,80,-1,119).
+relate(1,82,-1,21).
+relate(1,84,-1,21).
+relate(1,84,-1,170).
+relate(1,86,-1,173).
+relate(1,86,-1,31).
+relate(1,88,-1,171).
+relate(1,90,-1,69).
+relate(1,90,-1,147).
+relate(1,92,-1,15).
+relate(1,92,-1,69).
+relate(1,94,-1,155).
+relate(1,94,-1,180).
+relate(1,94,-1,95).
+relate(1,96,-1,119).
+relate(1,96,-1,180).
+relate(1,96,-1,105).
+relate(1,98,-1,33).
+relate(1,100,-1,170).
+relate(1,100,-1,166).
+relate(1,100,-1,77).
+relate(1,102,-1,31).
+relate(1,102,-1,166).
+relate(1,102,-1,107).
+relate(1,104,-1,45).
+relate(1,106,-1,147).
+relate(1,106,-1,45).
+relate(1,106,-1,157).
+relate(1,108,-1,157).
+relate(1,108,-1,115).
+relate(1,108,-1,35).
+relate(1,110,-1,95).
+relate(1,110,-1,115).
+relate(1,112,-1,105).
+relate(1,112,-1,133).
+relate(1,114,-1,33).
+relate(1,114,-1,145).
+relate(1,114,-1,81).
+relate(1,116,-1,77).
+relate(1,116,-1,145).
+relate(1,116,-1,121).
+relate(1,118,-1,107).
+relate(1,118,-1,123).
+relate(1,120,-1,123).
+relate(1,120,-1,63).
+relate(1,120,-1,99).
+relate(1,122,-1,63).
+relate(1,122,-1,159).
+relate(1,122,-1,85).
+relate(1,124,-1,35).
+relate(1,124,-1,159).
+relate(1,124,-1,174).
+relate(1,124,-1,97).
+relate(1,126,-1,174).
+relate(1,126,-1,51).
+relate(1,126,-1,19).
+relate(1,128,-1,133).
+relate(1,128,-1,51).
+relate(1,128,-1,163).
+relate(1,130,-1,81).
+relate(1,130,-1,178).
+relate(1,132,-1,121).
+relate(1,134,-1,65).
+relate(1,134,-1,79).
+relate(1,136,-1,99).
+relate(1,136,-1,65).
+relate(1,136,-1,164).
+relate(1,136,-1,23).
+relate(1,138,-1,85).
+relate(1,138,-1,164).
+relate(1,138,-1,161).
+relate(1,140,-1,97).
+relate(1,140,-1,49).
+relate(1,142,-1,19).
+relate(1,142,-1,13).
+relate(1,142,-1,47).
+relate(1,144,-1,163).
+relate(1,144,-1,13).
+relate(1,144,-1,93).
+relate(1,146,-1,178).
+relate(1,146,-1,168).
+relate(1,148,-1,168).
+relate(1,148,-1,179).
+relate(1,150,-1,79).
+relate(1,150,-1,179).
+relate(1,150,-1,29).
+relate(1,152,-1,23).
+relate(1,152,-1,29).
+relate(1,152,-1,25).
+relate(1,154,-1,161).
+relate(1,154,-1,25).
+relate(1,156,-1,49).
+relate(1,156,-1,172).
+relate(1,158,-1,47).
+relate(1,158,-1,172).
+relate(1,160,-1,93).
+relate(-1,5,1,2).
+relate(-1,176,1,2).
+relate(-1,117,1,4).
+relate(-1,9,1,6).
+relate(-1,61,1,6).
+relate(-1,61,1,8).
+relate(-1,55,1,8).
+relate(-1,43,1,10).
+relate(-1,129,1,12).
+relate(-1,162,1,12).
+relate(-1,11,1,14).
+relate(-1,129,1,14).
+relate(-1,175,1,14).
+relate(-1,131,1,16).
+relate(-1,176,1,18).
+relate(-1,7,1,18).
+relate(-1,169,1,18).
+relate(-1,153,1,18).
+relate(-1,117,1,20).
+relate(-1,169,1,20).
+relate(-1,165,1,20).
+relate(-1,59,1,22).
+relate(-1,55,1,24).
+relate(-1,71,1,24).
+relate(-1,43,1,26).
+relate(-1,91,1,26).
+relate(-1,162,1,28).
+relate(-1,73,1,28).
+relate(-1,175,1,30).
+relate(-1,73,1,30).
+relate(-1,127,1,30).
+relate(-1,139,1,30).
+relate(-1,131,1,32).
+relate(-1,127,1,32).
+relate(-1,153,1,34).
+relate(-1,41,1,34).
+relate(-1,165,1,36).
+relate(-1,67,1,36).
+relate(-1,53,1,36).
+relate(-1,59,1,38).
+relate(-1,67,1,38).
+relate(-1,71,1,40).
+relate(-1,27,1,40).
+relate(-1,91,1,42).
+relate(-1,57,1,42).
+relate(-1,103,1,42).
+relate(-1,57,1,44).
+relate(-1,141,1,44).
+relate(-1,139,1,46).
+relate(-1,141,1,46).
+relate(-1,109,1,46).
+relate(-1,177,1,46).
+relate(-1,109,1,48).
+relate(-1,3,1,48).
+relate(-1,17,1,48).
+relate(-1,41,1,50).
+relate(-1,1,1,50).
+relate(-1,111,1,50).
+relate(-1,53,1,52).
+relate(-1,111,1,52).
+relate(-1,89,1,52).
+relate(-1,113,1,52).
+relate(-1,89,1,54).
+relate(-1,39,1,54).
+relate(-1,27,1,56).
+relate(-1,83,1,56).
+relate(-1,103,1,58).
+relate(-1,83,1,58).
+relate(-1,75,1,58).
+relate(-1,167,1,58).
+relate(-1,75,1,60).
+relate(-1,125,1,60).
+relate(-1,177,1,62).
+relate(-1,143,1,62).
+relate(-1,17,1,64).
+relate(-1,143,1,64).
+relate(-1,37,1,64).
+relate(-1,87,1,66).
+relate(-1,113,1,68).
+relate(-1,87,1,68).
+relate(-1,151,1,68).
+relate(-1,39,1,70).
+relate(-1,151,1,70).
+relate(-1,101,1,70).
+relate(-1,173,1,70).
+relate(-1,101,1,72).
+relate(-1,171,1,72).
+relate(-1,167,1,74).
+relate(-1,135,1,74).
+relate(-1,125,1,76).
+relate(-1,135,1,76).
+relate(-1,149,1,76).
+relate(-1,15,1,76).
+relate(-1,149,1,78).
+relate(-1,137,1,78).
+relate(-1,155,1,78).
+relate(-1,37,1,80).
+relate(-1,137,1,80).
+relate(-1,119,1,80).
+relate(-1,21,1,82).
+relate(-1,21,1,84).
+relate(-1,170,1,84).
+relate(-1,173,1,86).
+relate(-1,31,1,86).
+relate(-1,171,1,88).
+relate(-1,69,1,90).
+relate(-1,147,1,90).
+relate(-1,15,1,92).
+relate(-1,69,1,92).
+relate(-1,155,1,94).
+relate(-1,180,1,94).
+relate(-1,95,1,94).
+relate(-1,119,1,96).
+relate(-1,180,1,96).
+relate(-1,105,1,96).
+relate(-1,33,1,98).
+relate(-1,170,1,100).
+relate(-1,166,1,100).
+relate(-1,77,1,100).
+relate(-1,31,1,102).
+relate(-1,166,1,102).
+relate(-1,107,1,102).
+relate(-1,45,1,104).
+relate(-1,147,1,106).
+relate(-1,45,1,106).
+relate(-1,157,1,106).
+relate(-1,157,1,108).
+relate(-1,115,1,108).
+relate(-1,35,1,108).
+relate(-1,95,1,110).
+relate(-1,115,1,110).
+relate(-1,105,1,112).
+relate(-1,133,1,112).
+relate(-1,33,1,114).
+relate(-1,145,1,114).
+relate(-1,81,1,114).
+relate(-1,77,1,116).
+relate(-1,145,1,116).
+relate(-1,121,1,116).
+relate(-1,107,1,118).
+relate(-1,123,1,118).
+relate(-1,123,1,120).
+relate(-1,63,1,120).
+relate(-1,99,1,120).
+relate(-1,63,1,122).
+relate(-1,159,1,122).
+relate(-1,85,1,122).
+relate(-1,35,1,124).
+relate(-1,159,1,124).
+relate(-1,174,1,124).
+relate(-1,97,1,124).
+relate(-1,174,1,126).
+relate(-1,51,1,126).
+relate(-1,19,1,126).
+relate(-1,133,1,128).
+relate(-1,51,1,128).
+relate(-1,163,1,128).
+relate(-1,81,1,130).
+relate(-1,178,1,130).
+relate(-1,121,1,132).
+relate(-1,65,1,134).
+relate(-1,79,1,134).
+relate(-1,99,1,136).
+relate(-1,65,1,136).
+relate(-1,164,1,136).
+relate(-1,23,1,136).
+relate(-1,85,1,138).
+relate(-1,164,1,138).
+relate(-1,161,1,138).
+relate(-1,97,1,140).
+relate(-1,49,1,140).
+relate(-1,19,1,142).
+relate(-1,13,1,142).
+relate(-1,47,1,142).
+relate(-1,163,1,144).
+relate(-1,13,1,144).
+relate(-1,93,1,144).
+relate(-1,178,1,146).
+relate(-1,168,1,146).
+relate(-1,168,1,148).
+relate(-1,179,1,148).
+relate(-1,79,1,150).
+relate(-1,179,1,150).
+relate(-1,29,1,150).
+relate(-1,23,1,152).
+relate(-1,29,1,152).
+relate(-1,25,1,152).
+relate(-1,161,1,154).
+relate(-1,25,1,154).
+relate(-1,49,1,156).
+relate(-1,172,1,156).
+relate(-1,47,1,158).
+relate(-1,172,1,158).
+relate(-1,93,1,160).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/154-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/154-partner_units-100-0.lp
new file mode 100644
index 0000000..73ba610
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/154-partner_units-100-0.lp
@@ -0,0 +1,746 @@
+maxPU(4).
+#const n=179.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+object(-1,179).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(1,156,1,158).
+follow(-1,168,-1,169).
+follow(-1,65,-1,67).
+follow(-1,95,-1,97).
+follow(-1,137,-1,139).
+follow(-1,115,-1,117).
+follow(-1,1,-1,3).
+follow(-1,101,-1,103).
+follow(-1,3,-1,5).
+follow(-1,63,-1,65).
+follow(-1,87,-1,89).
+follow(-1,5,-1,7).
+follow(-1,105,-1,107).
+follow(-1,81,-1,83).
+follow(-1,51,-1,53).
+follow(-1,39,-1,41).
+follow(-1,139,-1,141).
+follow(-1,31,-1,33).
+follow(-1,157,-1,159).
+follow(-1,169,-1,170).
+follow(-1,107,-1,109).
+follow(-1,170,-1,171).
+follow(-1,93,-1,95).
+follow(-1,53,-1,55).
+follow(-1,47,-1,49).
+follow(-1,127,-1,129).
+follow(-1,79,-1,81).
+follow(-1,131,-1,133).
+follow(-1,117,-1,119).
+follow(-1,99,-1,101).
+follow(-1,77,-1,79).
+follow(-1,59,-1,61).
+follow(-1,21,-1,23).
+follow(-1,129,-1,131).
+follow(-1,141,-1,143).
+follow(-1,133,-1,135).
+follow(-1,166,-1,167).
+follow(-1,171,-1,172).
+follow(-1,151,-1,153).
+follow(-1,83,-1,85).
+follow(-1,155,-1,157).
+follow(-1,176,-1,177).
+follow(-1,143,-1,145).
+follow(-1,103,-1,105).
+follow(-1,149,-1,151).
+follow(-1,33,-1,35).
+follow(-1,61,-1,63).
+follow(-1,15,-1,17).
+follow(-1,153,-1,155).
+follow(-1,172,-1,173).
+follow(-1,23,-1,25).
+follow(-1,89,-1,91).
+follow(-1,75,-1,77).
+follow(-1,165,-1,166).
+follow(-1,125,-1,127).
+follow(-1,45,-1,47).
+follow(-1,167,-1,168).
+follow(-1,57,-1,59).
+follow(-1,97,-1,99).
+follow(-1,162,-1,163).
+follow(-1,37,-1,39).
+follow(-1,19,-1,21).
+follow(-1,111,-1,113).
+follow(-1,49,-1,51).
+follow(-1,178,-1,179).
+follow(-1,163,-1,164).
+follow(-1,73,-1,75).
+follow(-1,174,-1,175).
+follow(-1,91,-1,93).
+follow(-1,85,-1,87).
+follow(-1,113,-1,115).
+follow(-1,109,-1,111).
+follow(-1,11,-1,13).
+follow(-1,67,-1,69).
+follow(-1,35,-1,37).
+follow(-1,71,-1,73).
+follow(-1,41,-1,43).
+follow(-1,160,-1,161).
+follow(-1,177,-1,178).
+follow(-1,175,-1,176).
+follow(-1,27,-1,29).
+follow(-1,17,-1,19).
+follow(-1,135,-1,137).
+follow(-1,7,-1,9).
+follow(-1,43,-1,45).
+follow(-1,161,-1,162).
+follow(-1,25,-1,27).
+follow(-1,173,-1,174).
+follow(-1,69,-1,71).
+follow(-1,119,-1,121).
+follow(-1,121,-1,123).
+follow(-1,145,-1,147).
+follow(-1,29,-1,31).
+follow(-1,123,-1,125).
+follow(-1,159,-1,160).
+follow(-1,55,-1,57).
+follow(-1,164,-1,165).
+follow(-1,9,-1,11).
+follow(-1,13,-1,15).
+follow(-1,147,-1,149).
+relate(1,2,-1,169).
+relate(1,4,-1,169).
+relate(1,4,-1,67).
+relate(1,6,-1,97).
+relate(1,8,-1,139).
+relate(1,10,-1,117).
+relate(1,12,-1,3).
+relate(1,12,-1,117).
+relate(1,12,-1,103).
+relate(1,14,-1,5).
+relate(1,14,-1,103).
+relate(1,14,-1,65).
+relate(1,16,-1,89).
+relate(1,18,-1,7).
+relate(1,18,-1,107).
+relate(1,18,-1,83).
+relate(1,20,-1,67).
+relate(1,20,-1,107).
+relate(1,22,-1,97).
+relate(1,22,-1,53).
+relate(1,22,-1,41).
+relate(1,24,-1,139).
+relate(1,24,-1,53).
+relate(1,24,-1,141).
+relate(1,26,-1,141).
+relate(1,26,-1,33).
+relate(1,26,-1,159).
+relate(1,28,-1,33).
+relate(1,28,-1,170).
+relate(1,28,-1,109).
+relate(1,30,-1,65).
+relate(1,30,-1,170).
+relate(1,30,-1,171).
+relate(1,32,-1,89).
+relate(1,32,-1,171).
+relate(1,32,-1,1).
+relate(1,32,-1,95).
+relate(1,34,-1,83).
+relate(1,34,-1,55).
+relate(1,34,-1,49).
+relate(1,36,-1,55).
+relate(1,36,-1,129).
+relate(1,38,-1,41).
+relate(1,38,-1,129).
+relate(1,38,-1,81).
+relate(1,40,-1,133).
+relate(1,42,-1,159).
+relate(1,42,-1,119).
+relate(1,42,-1,101).
+relate(1,44,-1,109).
+relate(1,44,-1,119).
+relate(1,44,-1,79).
+relate(1,44,-1,61).
+relate(1,46,-1,79).
+relate(1,46,-1,23).
+relate(1,46,-1,131).
+relate(1,48,-1,95).
+relate(1,48,-1,23).
+relate(1,48,-1,143).
+relate(1,50,-1,49).
+relate(1,50,-1,135).
+relate(1,50,-1,167).
+relate(1,52,-1,135).
+relate(1,52,-1,172).
+relate(1,52,-1,153).
+relate(1,54,-1,81).
+relate(1,54,-1,172).
+relate(1,54,-1,85).
+relate(1,56,-1,133).
+relate(1,56,-1,85).
+relate(1,56,-1,157).
+relate(1,56,-1,177).
+relate(1,58,-1,101).
+relate(1,58,-1,157).
+relate(1,58,-1,145).
+relate(1,60,-1,61).
+relate(1,60,-1,105).
+relate(1,60,-1,151).
+relate(1,62,-1,131).
+relate(1,62,-1,105).
+relate(1,62,-1,35).
+relate(1,64,-1,143).
+relate(1,64,-1,35).
+relate(1,64,-1,63).
+relate(1,66,-1,167).
+relate(1,68,-1,153).
+relate(1,68,-1,17).
+relate(1,70,-1,17).
+relate(1,70,-1,155).
+relate(1,72,-1,177).
+relate(1,72,-1,155).
+relate(1,72,-1,173).
+relate(1,72,-1,25).
+relate(1,74,-1,145).
+relate(1,74,-1,173).
+relate(1,74,-1,91).
+relate(1,76,-1,151).
+relate(1,78,-1,77).
+relate(1,80,-1,63).
+relate(1,80,-1,166).
+relate(1,82,-1,127).
+relate(1,82,-1,47).
+relate(1,84,-1,127).
+relate(1,84,-1,168).
+relate(1,86,-1,168).
+relate(1,86,-1,59).
+relate(1,86,-1,99).
+relate(1,88,-1,25).
+relate(1,88,-1,59).
+relate(1,88,-1,163).
+relate(1,88,-1,39).
+relate(1,90,-1,91).
+relate(1,90,-1,163).
+relate(1,90,-1,21).
+relate(1,90,-1,113).
+relate(1,92,-1,21).
+relate(1,92,-1,51).
+relate(1,92,-1,179).
+relate(1,94,-1,77).
+relate(1,94,-1,51).
+relate(1,94,-1,164).
+relate(1,96,-1,166).
+relate(1,96,-1,75).
+relate(1,98,-1,47).
+relate(1,98,-1,175).
+relate(1,100,-1,93).
+relate(1,102,-1,99).
+relate(1,102,-1,93).
+relate(1,102,-1,87).
+relate(1,104,-1,39).
+relate(1,104,-1,87).
+relate(1,104,-1,115).
+relate(1,104,-1,111).
+relate(1,106,-1,113).
+relate(1,106,-1,115).
+relate(1,108,-1,179).
+relate(1,108,-1,13).
+relate(1,108,-1,69).
+relate(1,110,-1,164).
+relate(1,110,-1,13).
+relate(1,110,-1,37).
+relate(1,110,-1,73).
+relate(1,112,-1,75).
+relate(1,112,-1,37).
+relate(1,112,-1,43).
+relate(1,114,-1,175).
+relate(1,116,-1,161).
+relate(1,118,-1,161).
+relate(1,118,-1,178).
+relate(1,118,-1,176).
+relate(1,120,-1,111).
+relate(1,120,-1,178).
+relate(1,120,-1,29).
+relate(1,122,-1,19).
+relate(1,124,-1,69).
+relate(1,124,-1,19).
+relate(1,126,-1,73).
+relate(1,128,-1,43).
+relate(1,128,-1,137).
+relate(1,130,-1,9).
+relate(1,130,-1,45).
+relate(1,132,-1,45).
+relate(1,132,-1,162).
+relate(1,132,-1,27).
+relate(1,134,-1,176).
+relate(1,134,-1,162).
+relate(1,134,-1,174).
+relate(1,134,-1,71).
+relate(1,136,-1,29).
+relate(1,136,-1,174).
+relate(1,136,-1,121).
+relate(1,138,-1,121).
+relate(1,138,-1,123).
+relate(1,140,-1,147).
+relate(1,140,-1,31).
+relate(1,142,-1,147).
+relate(1,142,-1,125).
+relate(1,144,-1,137).
+relate(1,144,-1,125).
+relate(1,144,-1,160).
+relate(1,146,-1,57).
+relate(1,148,-1,27).
+relate(1,148,-1,57).
+relate(1,150,-1,71).
+relate(1,152,-1,123).
+relate(1,152,-1,165).
+relate(1,152,-1,11).
+relate(1,154,-1,31).
+relate(1,154,-1,165).
+relate(1,154,-1,15).
+relate(1,156,-1,15).
+relate(1,156,-1,149).
+relate(1,158,-1,160).
+relate(1,158,-1,149).
+relate(-1,169,1,2).
+relate(-1,169,1,4).
+relate(-1,67,1,4).
+relate(-1,97,1,6).
+relate(-1,139,1,8).
+relate(-1,117,1,10).
+relate(-1,3,1,12).
+relate(-1,117,1,12).
+relate(-1,103,1,12).
+relate(-1,5,1,14).
+relate(-1,103,1,14).
+relate(-1,65,1,14).
+relate(-1,89,1,16).
+relate(-1,7,1,18).
+relate(-1,107,1,18).
+relate(-1,83,1,18).
+relate(-1,67,1,20).
+relate(-1,107,1,20).
+relate(-1,97,1,22).
+relate(-1,53,1,22).
+relate(-1,41,1,22).
+relate(-1,139,1,24).
+relate(-1,53,1,24).
+relate(-1,141,1,24).
+relate(-1,141,1,26).
+relate(-1,33,1,26).
+relate(-1,159,1,26).
+relate(-1,33,1,28).
+relate(-1,170,1,28).
+relate(-1,109,1,28).
+relate(-1,65,1,30).
+relate(-1,170,1,30).
+relate(-1,171,1,30).
+relate(-1,89,1,32).
+relate(-1,171,1,32).
+relate(-1,1,1,32).
+relate(-1,95,1,32).
+relate(-1,83,1,34).
+relate(-1,55,1,34).
+relate(-1,49,1,34).
+relate(-1,55,1,36).
+relate(-1,129,1,36).
+relate(-1,41,1,38).
+relate(-1,129,1,38).
+relate(-1,81,1,38).
+relate(-1,133,1,40).
+relate(-1,159,1,42).
+relate(-1,119,1,42).
+relate(-1,101,1,42).
+relate(-1,109,1,44).
+relate(-1,119,1,44).
+relate(-1,79,1,44).
+relate(-1,61,1,44).
+relate(-1,79,1,46).
+relate(-1,23,1,46).
+relate(-1,131,1,46).
+relate(-1,95,1,48).
+relate(-1,23,1,48).
+relate(-1,143,1,48).
+relate(-1,49,1,50).
+relate(-1,135,1,50).
+relate(-1,167,1,50).
+relate(-1,135,1,52).
+relate(-1,172,1,52).
+relate(-1,153,1,52).
+relate(-1,81,1,54).
+relate(-1,172,1,54).
+relate(-1,85,1,54).
+relate(-1,133,1,56).
+relate(-1,85,1,56).
+relate(-1,157,1,56).
+relate(-1,177,1,56).
+relate(-1,101,1,58).
+relate(-1,157,1,58).
+relate(-1,145,1,58).
+relate(-1,61,1,60).
+relate(-1,105,1,60).
+relate(-1,151,1,60).
+relate(-1,131,1,62).
+relate(-1,105,1,62).
+relate(-1,35,1,62).
+relate(-1,143,1,64).
+relate(-1,35,1,64).
+relate(-1,63,1,64).
+relate(-1,167,1,66).
+relate(-1,153,1,68).
+relate(-1,17,1,68).
+relate(-1,17,1,70).
+relate(-1,155,1,70).
+relate(-1,177,1,72).
+relate(-1,155,1,72).
+relate(-1,173,1,72).
+relate(-1,25,1,72).
+relate(-1,145,1,74).
+relate(-1,173,1,74).
+relate(-1,91,1,74).
+relate(-1,151,1,76).
+relate(-1,77,1,78).
+relate(-1,63,1,80).
+relate(-1,166,1,80).
+relate(-1,127,1,82).
+relate(-1,47,1,82).
+relate(-1,127,1,84).
+relate(-1,168,1,84).
+relate(-1,168,1,86).
+relate(-1,59,1,86).
+relate(-1,99,1,86).
+relate(-1,25,1,88).
+relate(-1,59,1,88).
+relate(-1,163,1,88).
+relate(-1,39,1,88).
+relate(-1,91,1,90).
+relate(-1,163,1,90).
+relate(-1,21,1,90).
+relate(-1,113,1,90).
+relate(-1,21,1,92).
+relate(-1,51,1,92).
+relate(-1,179,1,92).
+relate(-1,77,1,94).
+relate(-1,51,1,94).
+relate(-1,164,1,94).
+relate(-1,166,1,96).
+relate(-1,75,1,96).
+relate(-1,47,1,98).
+relate(-1,175,1,98).
+relate(-1,93,1,100).
+relate(-1,99,1,102).
+relate(-1,93,1,102).
+relate(-1,87,1,102).
+relate(-1,39,1,104).
+relate(-1,87,1,104).
+relate(-1,115,1,104).
+relate(-1,111,1,104).
+relate(-1,113,1,106).
+relate(-1,115,1,106).
+relate(-1,179,1,108).
+relate(-1,13,1,108).
+relate(-1,69,1,108).
+relate(-1,164,1,110).
+relate(-1,13,1,110).
+relate(-1,37,1,110).
+relate(-1,73,1,110).
+relate(-1,75,1,112).
+relate(-1,37,1,112).
+relate(-1,43,1,112).
+relate(-1,175,1,114).
+relate(-1,161,1,116).
+relate(-1,161,1,118).
+relate(-1,178,1,118).
+relate(-1,176,1,118).
+relate(-1,111,1,120).
+relate(-1,178,1,120).
+relate(-1,29,1,120).
+relate(-1,19,1,122).
+relate(-1,69,1,124).
+relate(-1,19,1,124).
+relate(-1,73,1,126).
+relate(-1,43,1,128).
+relate(-1,137,1,128).
+relate(-1,9,1,130).
+relate(-1,45,1,130).
+relate(-1,45,1,132).
+relate(-1,162,1,132).
+relate(-1,27,1,132).
+relate(-1,176,1,134).
+relate(-1,162,1,134).
+relate(-1,174,1,134).
+relate(-1,71,1,134).
+relate(-1,29,1,136).
+relate(-1,174,1,136).
+relate(-1,121,1,136).
+relate(-1,121,1,138).
+relate(-1,123,1,138).
+relate(-1,147,1,140).
+relate(-1,31,1,140).
+relate(-1,147,1,142).
+relate(-1,125,1,142).
+relate(-1,137,1,144).
+relate(-1,125,1,144).
+relate(-1,160,1,144).
+relate(-1,57,1,146).
+relate(-1,27,1,148).
+relate(-1,57,1,148).
+relate(-1,71,1,150).
+relate(-1,123,1,152).
+relate(-1,165,1,152).
+relate(-1,11,1,152).
+relate(-1,31,1,154).
+relate(-1,165,1,154).
+relate(-1,15,1,154).
+relate(-1,15,1,156).
+relate(-1,149,1,156).
+relate(-1,160,1,158).
+relate(-1,149,1,158).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/156-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/156-partner_units-100-0.lp
new file mode 100644
index 0000000..53d99e6
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/156-partner_units-100-0.lp
@@ -0,0 +1,742 @@
+maxPU(4).
+#const n=177.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(-1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(-1,9,-1,11).
+follow(-1,168,-1,169).
+follow(-1,17,-1,19).
+follow(-1,97,-1,99).
+follow(-1,119,-1,121).
+follow(-1,5,-1,7).
+follow(-1,101,-1,103).
+follow(-1,95,-1,97).
+follow(-1,91,-1,93).
+follow(-1,167,-1,168).
+follow(-1,21,-1,23).
+follow(-1,35,-1,37).
+follow(-1,173,-1,174).
+follow(-1,151,-1,153).
+follow(-1,141,-1,143).
+follow(-1,71,-1,73).
+follow(-1,161,-1,162).
+follow(-1,156,-1,157).
+follow(-1,69,-1,71).
+follow(-1,11,-1,13).
+follow(-1,31,-1,33).
+follow(-1,163,-1,164).
+follow(-1,135,-1,137).
+follow(-1,81,-1,83).
+follow(-1,129,-1,131).
+follow(-1,147,-1,149).
+follow(-1,89,-1,91).
+follow(-1,158,-1,159).
+follow(-1,121,-1,123).
+follow(-1,127,-1,129).
+follow(-1,111,-1,113).
+follow(-1,172,-1,173).
+follow(-1,85,-1,87).
+follow(-1,49,-1,51).
+follow(-1,174,-1,175).
+follow(-1,25,-1,27).
+follow(-1,59,-1,61).
+follow(-1,123,-1,125).
+follow(-1,159,-1,160).
+follow(-1,23,-1,25).
+follow(-1,75,-1,77).
+follow(-1,113,-1,115).
+follow(-1,125,-1,127).
+follow(-1,157,-1,158).
+follow(-1,170,-1,171).
+follow(-1,65,-1,67).
+follow(-1,51,-1,53).
+follow(-1,99,-1,101).
+follow(-1,3,-1,5).
+follow(-1,145,-1,147).
+follow(-1,155,-1,156).
+follow(-1,176,-1,177).
+follow(-1,105,-1,107).
+follow(-1,41,-1,43).
+follow(-1,143,-1,145).
+follow(-1,166,-1,167).
+follow(-1,171,-1,172).
+follow(-1,57,-1,59).
+follow(-1,13,-1,15).
+follow(-1,109,-1,111).
+follow(-1,7,-1,9).
+follow(-1,43,-1,45).
+follow(-1,27,-1,29).
+follow(-1,133,-1,135).
+follow(-1,63,-1,65).
+follow(-1,77,-1,79).
+follow(-1,19,-1,21).
+follow(-1,169,-1,170).
+follow(-1,164,-1,165).
+follow(-1,162,-1,163).
+follow(-1,160,-1,161).
+follow(-1,61,-1,63).
+follow(-1,139,-1,141).
+follow(-1,53,-1,55).
+follow(-1,165,-1,166).
+follow(-1,107,-1,109).
+follow(-1,153,-1,155).
+follow(-1,115,-1,117).
+follow(-1,87,-1,89).
+follow(-1,175,-1,176).
+follow(-1,33,-1,35).
+follow(-1,79,-1,81).
+follow(-1,37,-1,39).
+follow(-1,93,-1,95).
+follow(-1,131,-1,133).
+follow(-1,83,-1,85).
+follow(-1,67,-1,69).
+follow(-1,103,-1,105).
+follow(-1,39,-1,41).
+follow(-1,149,-1,151).
+follow(-1,29,-1,31).
+follow(-1,15,-1,17).
+follow(-1,117,-1,119).
+follow(-1,47,-1,49).
+follow(-1,55,-1,57).
+follow(-1,45,-1,47).
+follow(-1,73,-1,75).
+follow(-1,137,-1,139).
+follow(-1,1,-1,3).
+relate(1,2,-1,11).
+relate(1,2,-1,169).
+relate(1,4,-1,19).
+relate(1,4,-1,99).
+relate(1,6,-1,19).
+relate(1,6,-1,121).
+relate(1,8,-1,7).
+relate(1,8,-1,103).
+relate(1,10,-1,97).
+relate(1,10,-1,93).
+relate(1,12,-1,97).
+relate(1,12,-1,168).
+relate(1,14,-1,169).
+relate(1,14,-1,23).
+relate(1,16,-1,23).
+relate(1,16,-1,37).
+relate(1,16,-1,174).
+relate(1,18,-1,37).
+relate(1,18,-1,153).
+relate(1,20,-1,99).
+relate(1,20,-1,153).
+relate(1,22,-1,121).
+relate(1,22,-1,143).
+relate(1,22,-1,73).
+relate(1,24,-1,103).
+relate(1,24,-1,143).
+relate(1,24,-1,162).
+relate(1,24,-1,157).
+relate(1,26,-1,93).
+relate(1,26,-1,162).
+relate(1,26,-1,71).
+relate(1,28,-1,168).
+relate(1,28,-1,71).
+relate(1,30,-1,13).
+relate(1,30,-1,33).
+relate(1,32,-1,174).
+relate(1,32,-1,13).
+relate(1,34,-1,164).
+relate(1,34,-1,137).
+relate(1,36,-1,164).
+relate(1,38,-1,73).
+relate(1,38,-1,83).
+relate(1,40,-1,157).
+relate(1,40,-1,131).
+relate(1,42,-1,131).
+relate(1,42,-1,149).
+relate(1,42,-1,91).
+relate(1,44,-1,149).
+relate(1,44,-1,159).
+relate(1,46,-1,33).
+relate(1,46,-1,123).
+relate(1,46,-1,129).
+relate(1,48,-1,123).
+relate(1,48,-1,113).
+relate(1,50,-1,137).
+relate(1,50,-1,113).
+relate(1,50,-1,173).
+relate(1,52,-1,173).
+relate(1,52,-1,87).
+relate(1,54,-1,83).
+relate(1,54,-1,51).
+relate(1,54,-1,175).
+relate(1,56,-1,51).
+relate(1,56,-1,27).
+relate(1,56,-1,61).
+relate(1,58,-1,91).
+relate(1,58,-1,27).
+relate(1,58,-1,125).
+relate(1,60,-1,159).
+relate(1,60,-1,125).
+relate(1,60,-1,160).
+relate(1,62,-1,129).
+relate(1,62,-1,25).
+relate(1,64,-1,77).
+relate(1,66,-1,115).
+relate(1,68,-1,87).
+relate(1,68,-1,115).
+relate(1,68,-1,127).
+relate(1,68,-1,158).
+relate(1,70,-1,175).
+relate(1,70,-1,127).
+relate(1,70,-1,171).
+relate(1,70,-1,67).
+relate(1,72,-1,61).
+relate(1,72,-1,171).
+relate(1,72,-1,53).
+relate(1,74,-1,53).
+relate(1,74,-1,101).
+relate(1,76,-1,160).
+relate(1,76,-1,5).
+relate(1,76,-1,147).
+relate(1,78,-1,25).
+relate(1,78,-1,156).
+relate(1,80,-1,77).
+relate(1,80,-1,156).
+relate(1,80,-1,177).
+relate(1,80,-1,107).
+relate(1,82,-1,177).
+relate(1,84,-1,158).
+relate(1,84,-1,43).
+relate(1,86,-1,67).
+relate(1,86,-1,43).
+relate(1,86,-1,145).
+relate(1,86,-1,167).
+relate(1,88,-1,145).
+relate(1,88,-1,172).
+relate(1,90,-1,101).
+relate(1,90,-1,59).
+relate(1,90,-1,15).
+relate(1,92,-1,147).
+relate(1,92,-1,59).
+relate(1,92,-1,111).
+relate(1,94,-1,9).
+relate(1,94,-1,45).
+relate(1,96,-1,107).
+relate(1,96,-1,45).
+relate(1,98,-1,29).
+relate(1,100,-1,29).
+relate(1,100,-1,135).
+relate(1,102,-1,167).
+relate(1,102,-1,135).
+relate(1,102,-1,65).
+relate(1,102,-1,79).
+relate(1,104,-1,172).
+relate(1,104,-1,65).
+relate(1,104,-1,21).
+relate(1,106,-1,15).
+relate(1,106,-1,170).
+relate(1,108,-1,111).
+relate(1,108,-1,170).
+relate(1,108,-1,165).
+relate(1,110,-1,163).
+relate(1,110,-1,161).
+relate(1,112,-1,163).
+relate(1,112,-1,63).
+relate(1,112,-1,141).
+relate(1,114,-1,63).
+relate(1,114,-1,55).
+relate(1,114,-1,166).
+relate(1,116,-1,55).
+relate(1,116,-1,109).
+relate(1,116,-1,155).
+relate(1,118,-1,79).
+relate(1,118,-1,109).
+relate(1,118,-1,117).
+relate(1,118,-1,89).
+relate(1,120,-1,21).
+relate(1,120,-1,117).
+relate(1,120,-1,176).
+relate(1,120,-1,35).
+relate(1,122,-1,176).
+relate(1,122,-1,81).
+relate(1,122,-1,39).
+relate(1,124,-1,165).
+relate(1,124,-1,81).
+relate(1,124,-1,95).
+relate(1,126,-1,161).
+relate(1,126,-1,133).
+relate(1,126,-1,85).
+relate(1,128,-1,141).
+relate(1,128,-1,133).
+relate(1,128,-1,69).
+relate(1,128,-1,105).
+relate(1,130,-1,166).
+relate(1,130,-1,69).
+relate(1,130,-1,41).
+relate(1,132,-1,155).
+relate(1,132,-1,41).
+relate(1,132,-1,151).
+relate(1,132,-1,31).
+relate(1,134,-1,89).
+relate(1,134,-1,151).
+relate(1,134,-1,17).
+relate(1,136,-1,35).
+relate(1,136,-1,119).
+relate(1,136,-1,49).
+relate(1,138,-1,39).
+relate(1,138,-1,119).
+relate(1,138,-1,57).
+relate(1,138,-1,47).
+relate(1,140,-1,95).
+relate(1,140,-1,57).
+relate(1,142,-1,85).
+relate(1,144,-1,105).
+relate(1,144,-1,1).
+relate(1,146,-1,31).
+relate(1,148,-1,17).
+relate(1,150,-1,49).
+relate(1,150,-1,75).
+relate(1,152,-1,47).
+relate(1,152,-1,75).
+relate(1,152,-1,139).
+relate(1,154,-1,139).
+relate(1,154,-1,3).
+relate(-1,11,1,2).
+relate(-1,169,1,2).
+relate(-1,19,1,4).
+relate(-1,99,1,4).
+relate(-1,19,1,6).
+relate(-1,121,1,6).
+relate(-1,7,1,8).
+relate(-1,103,1,8).
+relate(-1,97,1,10).
+relate(-1,93,1,10).
+relate(-1,97,1,12).
+relate(-1,168,1,12).
+relate(-1,169,1,14).
+relate(-1,23,1,14).
+relate(-1,23,1,16).
+relate(-1,37,1,16).
+relate(-1,174,1,16).
+relate(-1,37,1,18).
+relate(-1,153,1,18).
+relate(-1,99,1,20).
+relate(-1,153,1,20).
+relate(-1,121,1,22).
+relate(-1,143,1,22).
+relate(-1,73,1,22).
+relate(-1,103,1,24).
+relate(-1,143,1,24).
+relate(-1,162,1,24).
+relate(-1,157,1,24).
+relate(-1,93,1,26).
+relate(-1,162,1,26).
+relate(-1,71,1,26).
+relate(-1,168,1,28).
+relate(-1,71,1,28).
+relate(-1,13,1,30).
+relate(-1,33,1,30).
+relate(-1,174,1,32).
+relate(-1,13,1,32).
+relate(-1,164,1,34).
+relate(-1,137,1,34).
+relate(-1,164,1,36).
+relate(-1,73,1,38).
+relate(-1,83,1,38).
+relate(-1,157,1,40).
+relate(-1,131,1,40).
+relate(-1,131,1,42).
+relate(-1,149,1,42).
+relate(-1,91,1,42).
+relate(-1,149,1,44).
+relate(-1,159,1,44).
+relate(-1,33,1,46).
+relate(-1,123,1,46).
+relate(-1,129,1,46).
+relate(-1,123,1,48).
+relate(-1,113,1,48).
+relate(-1,137,1,50).
+relate(-1,113,1,50).
+relate(-1,173,1,50).
+relate(-1,173,1,52).
+relate(-1,87,1,52).
+relate(-1,83,1,54).
+relate(-1,51,1,54).
+relate(-1,175,1,54).
+relate(-1,51,1,56).
+relate(-1,27,1,56).
+relate(-1,61,1,56).
+relate(-1,91,1,58).
+relate(-1,27,1,58).
+relate(-1,125,1,58).
+relate(-1,159,1,60).
+relate(-1,125,1,60).
+relate(-1,160,1,60).
+relate(-1,129,1,62).
+relate(-1,25,1,62).
+relate(-1,77,1,64).
+relate(-1,115,1,66).
+relate(-1,87,1,68).
+relate(-1,115,1,68).
+relate(-1,127,1,68).
+relate(-1,158,1,68).
+relate(-1,175,1,70).
+relate(-1,127,1,70).
+relate(-1,171,1,70).
+relate(-1,67,1,70).
+relate(-1,61,1,72).
+relate(-1,171,1,72).
+relate(-1,53,1,72).
+relate(-1,53,1,74).
+relate(-1,101,1,74).
+relate(-1,160,1,76).
+relate(-1,5,1,76).
+relate(-1,147,1,76).
+relate(-1,25,1,78).
+relate(-1,156,1,78).
+relate(-1,77,1,80).
+relate(-1,156,1,80).
+relate(-1,177,1,80).
+relate(-1,107,1,80).
+relate(-1,177,1,82).
+relate(-1,158,1,84).
+relate(-1,43,1,84).
+relate(-1,67,1,86).
+relate(-1,43,1,86).
+relate(-1,145,1,86).
+relate(-1,167,1,86).
+relate(-1,145,1,88).
+relate(-1,172,1,88).
+relate(-1,101,1,90).
+relate(-1,59,1,90).
+relate(-1,15,1,90).
+relate(-1,147,1,92).
+relate(-1,59,1,92).
+relate(-1,111,1,92).
+relate(-1,9,1,94).
+relate(-1,45,1,94).
+relate(-1,107,1,96).
+relate(-1,45,1,96).
+relate(-1,29,1,98).
+relate(-1,29,1,100).
+relate(-1,135,1,100).
+relate(-1,167,1,102).
+relate(-1,135,1,102).
+relate(-1,65,1,102).
+relate(-1,79,1,102).
+relate(-1,172,1,104).
+relate(-1,65,1,104).
+relate(-1,21,1,104).
+relate(-1,15,1,106).
+relate(-1,170,1,106).
+relate(-1,111,1,108).
+relate(-1,170,1,108).
+relate(-1,165,1,108).
+relate(-1,163,1,110).
+relate(-1,161,1,110).
+relate(-1,163,1,112).
+relate(-1,63,1,112).
+relate(-1,141,1,112).
+relate(-1,63,1,114).
+relate(-1,55,1,114).
+relate(-1,166,1,114).
+relate(-1,55,1,116).
+relate(-1,109,1,116).
+relate(-1,155,1,116).
+relate(-1,79,1,118).
+relate(-1,109,1,118).
+relate(-1,117,1,118).
+relate(-1,89,1,118).
+relate(-1,21,1,120).
+relate(-1,117,1,120).
+relate(-1,176,1,120).
+relate(-1,35,1,120).
+relate(-1,176,1,122).
+relate(-1,81,1,122).
+relate(-1,39,1,122).
+relate(-1,165,1,124).
+relate(-1,81,1,124).
+relate(-1,95,1,124).
+relate(-1,161,1,126).
+relate(-1,133,1,126).
+relate(-1,85,1,126).
+relate(-1,141,1,128).
+relate(-1,133,1,128).
+relate(-1,69,1,128).
+relate(-1,105,1,128).
+relate(-1,166,1,130).
+relate(-1,69,1,130).
+relate(-1,41,1,130).
+relate(-1,155,1,132).
+relate(-1,41,1,132).
+relate(-1,151,1,132).
+relate(-1,31,1,132).
+relate(-1,89,1,134).
+relate(-1,151,1,134).
+relate(-1,17,1,134).
+relate(-1,35,1,136).
+relate(-1,119,1,136).
+relate(-1,49,1,136).
+relate(-1,39,1,138).
+relate(-1,119,1,138).
+relate(-1,57,1,138).
+relate(-1,47,1,138).
+relate(-1,95,1,140).
+relate(-1,57,1,140).
+relate(-1,85,1,142).
+relate(-1,105,1,144).
+relate(-1,1,1,144).
+relate(-1,31,1,146).
+relate(-1,17,1,148).
+relate(-1,49,1,150).
+relate(-1,75,1,150).
+relate(-1,47,1,152).
+relate(-1,75,1,152).
+relate(-1,139,1,152).
+relate(-1,139,1,154).
+relate(-1,3,1,154).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/161-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/161-partner_units-100-0.lp
new file mode 100644
index 0000000..16cc4d7
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/161-partner_units-100-0.lp
@@ -0,0 +1,742 @@
+maxPU(4).
+#const n=177.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(-1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(-1,167,-1,168).
+follow(-1,125,-1,127).
+follow(-1,71,-1,73).
+follow(-1,111,-1,113).
+follow(-1,39,-1,41).
+follow(-1,63,-1,65).
+follow(-1,161,-1,162).
+follow(-1,115,-1,117).
+follow(-1,156,-1,157).
+follow(-1,173,-1,174).
+follow(-1,175,-1,176).
+follow(-1,9,-1,11).
+follow(-1,7,-1,9).
+follow(-1,11,-1,13).
+follow(-1,155,-1,156).
+follow(-1,159,-1,160).
+follow(-1,79,-1,81).
+follow(-1,97,-1,99).
+follow(-1,139,-1,141).
+follow(-1,123,-1,125).
+follow(-1,101,-1,103).
+follow(-1,165,-1,166).
+follow(-1,47,-1,49).
+follow(-1,3,-1,5).
+follow(-1,65,-1,67).
+follow(-1,35,-1,37).
+follow(-1,77,-1,79).
+follow(-1,13,-1,15).
+follow(-1,166,-1,167).
+follow(-1,29,-1,31).
+follow(-1,147,-1,149).
+follow(-1,113,-1,115).
+follow(-1,160,-1,161).
+follow(-1,67,-1,69).
+follow(-1,57,-1,59).
+follow(-1,169,-1,170).
+follow(-1,135,-1,137).
+follow(-1,172,-1,173).
+follow(-1,143,-1,145).
+follow(-1,129,-1,131).
+follow(-1,41,-1,43).
+follow(-1,170,-1,171).
+follow(-1,87,-1,89).
+follow(-1,43,-1,45).
+follow(-1,23,-1,25).
+follow(-1,164,-1,165).
+follow(-1,73,-1,75).
+follow(-1,81,-1,83).
+follow(-1,83,-1,85).
+follow(-1,168,-1,169).
+follow(-1,45,-1,47).
+follow(-1,55,-1,57).
+follow(-1,163,-1,164).
+follow(-1,103,-1,105).
+follow(-1,27,-1,29).
+follow(-1,117,-1,119).
+follow(-1,174,-1,175).
+follow(-1,33,-1,35).
+follow(-1,19,-1,21).
+follow(-1,85,-1,87).
+follow(-1,5,-1,7).
+follow(-1,105,-1,107).
+follow(-1,25,-1,27).
+follow(-1,176,-1,177).
+follow(-1,157,-1,158).
+follow(-1,141,-1,143).
+follow(-1,93,-1,95).
+follow(-1,53,-1,55).
+follow(-1,75,-1,77).
+follow(-1,21,-1,23).
+follow(-1,95,-1,97).
+follow(-1,127,-1,129).
+follow(-1,145,-1,147).
+follow(-1,121,-1,123).
+follow(-1,37,-1,39).
+follow(-1,153,-1,155).
+follow(-1,131,-1,133).
+follow(-1,59,-1,61).
+follow(-1,119,-1,121).
+follow(-1,137,-1,139).
+follow(-1,149,-1,151).
+follow(-1,51,-1,53).
+follow(-1,171,-1,172).
+follow(-1,109,-1,111).
+follow(-1,91,-1,93).
+follow(-1,61,-1,63).
+follow(-1,99,-1,101).
+follow(-1,89,-1,91).
+follow(-1,49,-1,51).
+follow(-1,69,-1,71).
+follow(-1,31,-1,33).
+follow(-1,162,-1,163).
+follow(-1,17,-1,19).
+follow(-1,133,-1,135).
+follow(-1,158,-1,159).
+follow(-1,151,-1,153).
+follow(-1,15,-1,17).
+follow(-1,107,-1,109).
+follow(-1,1,-1,3).
+relate(1,2,-1,168).
+relate(1,4,-1,168).
+relate(1,4,-1,127).
+relate(1,4,-1,73).
+relate(1,6,-1,127).
+relate(1,6,-1,113).
+relate(1,6,-1,41).
+relate(1,8,-1,113).
+relate(1,8,-1,65).
+relate(1,10,-1,162).
+relate(1,12,-1,1).
+relate(1,12,-1,162).
+relate(1,12,-1,117).
+relate(1,12,-1,157).
+relate(1,14,-1,117).
+relate(1,14,-1,174).
+relate(1,14,-1,176).
+relate(1,16,-1,174).
+relate(1,16,-1,11).
+relate(1,18,-1,9).
+relate(1,18,-1,13).
+relate(1,20,-1,73).
+relate(1,20,-1,13).
+relate(1,20,-1,156).
+relate(1,20,-1,160).
+relate(1,22,-1,41).
+relate(1,22,-1,156).
+relate(1,22,-1,81).
+relate(1,22,-1,99).
+relate(1,24,-1,65).
+relate(1,24,-1,81).
+relate(1,24,-1,141).
+relate(1,26,-1,125).
+relate(1,26,-1,103).
+relate(1,28,-1,157).
+relate(1,28,-1,125).
+relate(1,30,-1,176).
+relate(1,30,-1,166).
+relate(1,30,-1,49).
+relate(1,32,-1,166).
+relate(1,32,-1,5).
+relate(1,32,-1,67).
+relate(1,34,-1,37).
+relate(1,34,-1,79).
+relate(1,36,-1,160).
+relate(1,36,-1,37).
+relate(1,36,-1,15).
+relate(1,38,-1,99).
+relate(1,38,-1,167).
+relate(1,38,-1,31).
+relate(1,40,-1,141).
+relate(1,40,-1,167).
+relate(1,40,-1,149).
+relate(1,40,-1,115).
+relate(1,42,-1,103).
+relate(1,42,-1,149).
+relate(1,42,-1,161).
+relate(1,42,-1,69).
+relate(1,44,-1,161).
+relate(1,44,-1,59).
+relate(1,46,-1,49).
+relate(1,46,-1,59).
+relate(1,48,-1,67).
+relate(1,50,-1,79).
+relate(1,50,-1,170).
+relate(1,50,-1,137).
+relate(1,52,-1,15).
+relate(1,52,-1,170).
+relate(1,52,-1,173).
+relate(1,54,-1,31).
+relate(1,54,-1,145).
+relate(1,54,-1,131).
+relate(1,56,-1,115).
+relate(1,56,-1,145).
+relate(1,58,-1,69).
+relate(1,58,-1,43).
+relate(1,60,-1,171).
+relate(1,62,-1,89).
+relate(1,64,-1,137).
+relate(1,64,-1,45).
+relate(1,66,-1,173).
+relate(1,68,-1,131).
+relate(1,68,-1,25).
+relate(1,70,-1,25).
+relate(1,70,-1,165).
+relate(1,70,-1,75).
+relate(1,72,-1,43).
+relate(1,72,-1,165).
+relate(1,72,-1,83).
+relate(1,72,-1,85).
+relate(1,74,-1,83).
+relate(1,74,-1,169).
+relate(1,76,-1,171).
+relate(1,76,-1,169).
+relate(1,76,-1,47).
+relate(1,78,-1,89).
+relate(1,78,-1,57).
+relate(1,80,-1,45).
+relate(1,80,-1,164).
+relate(1,82,-1,105).
+relate(1,84,-1,29).
+relate(1,86,-1,75).
+relate(1,86,-1,29).
+relate(1,86,-1,119).
+relate(1,88,-1,85).
+relate(1,88,-1,119).
+relate(1,88,-1,175).
+relate(1,88,-1,35).
+relate(1,90,-1,175).
+relate(1,90,-1,21).
+relate(1,92,-1,47).
+relate(1,92,-1,87).
+relate(1,94,-1,57).
+relate(1,94,-1,87).
+relate(1,94,-1,7).
+relate(1,96,-1,164).
+relate(1,96,-1,107).
+relate(1,96,-1,27).
+relate(1,98,-1,105).
+relate(1,98,-1,107).
+relate(1,98,-1,177).
+relate(1,100,-1,177).
+relate(1,100,-1,158).
+relate(1,102,-1,158).
+relate(1,102,-1,143).
+relate(1,104,-1,35).
+relate(1,104,-1,143).
+relate(1,104,-1,95).
+relate(1,104,-1,55).
+relate(1,106,-1,21).
+relate(1,106,-1,95).
+relate(1,106,-1,77).
+relate(1,108,-1,23).
+relate(1,110,-1,23).
+relate(1,110,-1,97).
+relate(1,112,-1,27).
+relate(1,112,-1,129).
+relate(1,112,-1,147).
+relate(1,114,-1,129).
+relate(1,114,-1,123).
+relate(1,116,-1,39).
+relate(1,118,-1,39).
+relate(1,118,-1,155).
+relate(1,118,-1,133).
+relate(1,120,-1,55).
+relate(1,120,-1,155).
+relate(1,120,-1,61).
+relate(1,120,-1,121).
+relate(1,122,-1,77).
+relate(1,122,-1,61).
+relate(1,124,-1,139).
+relate(1,124,-1,151).
+relate(1,126,-1,97).
+relate(1,126,-1,139).
+relate(1,126,-1,53).
+relate(1,128,-1,147).
+relate(1,128,-1,172).
+relate(1,128,-1,111).
+relate(1,130,-1,123).
+relate(1,130,-1,172).
+relate(1,130,-1,93).
+relate(1,132,-1,133).
+relate(1,132,-1,63).
+relate(1,132,-1,101).
+relate(1,134,-1,121).
+relate(1,134,-1,63).
+relate(1,134,-1,91).
+relate(1,134,-1,51).
+relate(1,136,-1,91).
+relate(1,136,-1,71).
+relate(1,136,-1,33).
+relate(1,138,-1,151).
+relate(1,138,-1,71).
+relate(1,138,-1,163).
+relate(1,140,-1,53).
+relate(1,140,-1,19).
+relate(1,142,-1,111).
+relate(1,142,-1,135).
+relate(1,144,-1,93).
+relate(1,144,-1,135).
+relate(1,146,-1,101).
+relate(1,146,-1,159).
+relate(1,148,-1,51).
+relate(1,148,-1,159).
+relate(1,148,-1,153).
+relate(1,150,-1,33).
+relate(1,150,-1,153).
+relate(1,150,-1,17).
+relate(1,152,-1,163).
+relate(1,152,-1,17).
+relate(1,152,-1,109).
+relate(1,154,-1,19).
+relate(1,154,-1,109).
+relate(1,154,-1,3).
+relate(-1,168,1,2).
+relate(-1,168,1,4).
+relate(-1,127,1,4).
+relate(-1,73,1,4).
+relate(-1,127,1,6).
+relate(-1,113,1,6).
+relate(-1,41,1,6).
+relate(-1,113,1,8).
+relate(-1,65,1,8).
+relate(-1,162,1,10).
+relate(-1,1,1,12).
+relate(-1,162,1,12).
+relate(-1,117,1,12).
+relate(-1,157,1,12).
+relate(-1,117,1,14).
+relate(-1,174,1,14).
+relate(-1,176,1,14).
+relate(-1,174,1,16).
+relate(-1,11,1,16).
+relate(-1,9,1,18).
+relate(-1,13,1,18).
+relate(-1,73,1,20).
+relate(-1,13,1,20).
+relate(-1,156,1,20).
+relate(-1,160,1,20).
+relate(-1,41,1,22).
+relate(-1,156,1,22).
+relate(-1,81,1,22).
+relate(-1,99,1,22).
+relate(-1,65,1,24).
+relate(-1,81,1,24).
+relate(-1,141,1,24).
+relate(-1,125,1,26).
+relate(-1,103,1,26).
+relate(-1,157,1,28).
+relate(-1,125,1,28).
+relate(-1,176,1,30).
+relate(-1,166,1,30).
+relate(-1,49,1,30).
+relate(-1,166,1,32).
+relate(-1,5,1,32).
+relate(-1,67,1,32).
+relate(-1,37,1,34).
+relate(-1,79,1,34).
+relate(-1,160,1,36).
+relate(-1,37,1,36).
+relate(-1,15,1,36).
+relate(-1,99,1,38).
+relate(-1,167,1,38).
+relate(-1,31,1,38).
+relate(-1,141,1,40).
+relate(-1,167,1,40).
+relate(-1,149,1,40).
+relate(-1,115,1,40).
+relate(-1,103,1,42).
+relate(-1,149,1,42).
+relate(-1,161,1,42).
+relate(-1,69,1,42).
+relate(-1,161,1,44).
+relate(-1,59,1,44).
+relate(-1,49,1,46).
+relate(-1,59,1,46).
+relate(-1,67,1,48).
+relate(-1,79,1,50).
+relate(-1,170,1,50).
+relate(-1,137,1,50).
+relate(-1,15,1,52).
+relate(-1,170,1,52).
+relate(-1,173,1,52).
+relate(-1,31,1,54).
+relate(-1,145,1,54).
+relate(-1,131,1,54).
+relate(-1,115,1,56).
+relate(-1,145,1,56).
+relate(-1,69,1,58).
+relate(-1,43,1,58).
+relate(-1,171,1,60).
+relate(-1,89,1,62).
+relate(-1,137,1,64).
+relate(-1,45,1,64).
+relate(-1,173,1,66).
+relate(-1,131,1,68).
+relate(-1,25,1,68).
+relate(-1,25,1,70).
+relate(-1,165,1,70).
+relate(-1,75,1,70).
+relate(-1,43,1,72).
+relate(-1,165,1,72).
+relate(-1,83,1,72).
+relate(-1,85,1,72).
+relate(-1,83,1,74).
+relate(-1,169,1,74).
+relate(-1,171,1,76).
+relate(-1,169,1,76).
+relate(-1,47,1,76).
+relate(-1,89,1,78).
+relate(-1,57,1,78).
+relate(-1,45,1,80).
+relate(-1,164,1,80).
+relate(-1,105,1,82).
+relate(-1,29,1,84).
+relate(-1,75,1,86).
+relate(-1,29,1,86).
+relate(-1,119,1,86).
+relate(-1,85,1,88).
+relate(-1,119,1,88).
+relate(-1,175,1,88).
+relate(-1,35,1,88).
+relate(-1,175,1,90).
+relate(-1,21,1,90).
+relate(-1,47,1,92).
+relate(-1,87,1,92).
+relate(-1,57,1,94).
+relate(-1,87,1,94).
+relate(-1,7,1,94).
+relate(-1,164,1,96).
+relate(-1,107,1,96).
+relate(-1,27,1,96).
+relate(-1,105,1,98).
+relate(-1,107,1,98).
+relate(-1,177,1,98).
+relate(-1,177,1,100).
+relate(-1,158,1,100).
+relate(-1,158,1,102).
+relate(-1,143,1,102).
+relate(-1,35,1,104).
+relate(-1,143,1,104).
+relate(-1,95,1,104).
+relate(-1,55,1,104).
+relate(-1,21,1,106).
+relate(-1,95,1,106).
+relate(-1,77,1,106).
+relate(-1,23,1,108).
+relate(-1,23,1,110).
+relate(-1,97,1,110).
+relate(-1,27,1,112).
+relate(-1,129,1,112).
+relate(-1,147,1,112).
+relate(-1,129,1,114).
+relate(-1,123,1,114).
+relate(-1,39,1,116).
+relate(-1,39,1,118).
+relate(-1,155,1,118).
+relate(-1,133,1,118).
+relate(-1,55,1,120).
+relate(-1,155,1,120).
+relate(-1,61,1,120).
+relate(-1,121,1,120).
+relate(-1,77,1,122).
+relate(-1,61,1,122).
+relate(-1,139,1,124).
+relate(-1,151,1,124).
+relate(-1,97,1,126).
+relate(-1,139,1,126).
+relate(-1,53,1,126).
+relate(-1,147,1,128).
+relate(-1,172,1,128).
+relate(-1,111,1,128).
+relate(-1,123,1,130).
+relate(-1,172,1,130).
+relate(-1,93,1,130).
+relate(-1,133,1,132).
+relate(-1,63,1,132).
+relate(-1,101,1,132).
+relate(-1,121,1,134).
+relate(-1,63,1,134).
+relate(-1,91,1,134).
+relate(-1,51,1,134).
+relate(-1,91,1,136).
+relate(-1,71,1,136).
+relate(-1,33,1,136).
+relate(-1,151,1,138).
+relate(-1,71,1,138).
+relate(-1,163,1,138).
+relate(-1,53,1,140).
+relate(-1,19,1,140).
+relate(-1,111,1,142).
+relate(-1,135,1,142).
+relate(-1,93,1,144).
+relate(-1,135,1,144).
+relate(-1,101,1,146).
+relate(-1,159,1,146).
+relate(-1,51,1,148).
+relate(-1,159,1,148).
+relate(-1,153,1,148).
+relate(-1,33,1,150).
+relate(-1,153,1,150).
+relate(-1,17,1,150).
+relate(-1,163,1,152).
+relate(-1,17,1,152).
+relate(-1,109,1,152).
+relate(-1,19,1,154).
+relate(-1,109,1,154).
+relate(-1,3,1,154).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/175-partner_units_polynomial-75-0.lp b/examples/clingo/expansion/PartnerUnits/instances/175-partner_units_polynomial-75-0.lp
new file mode 100644
index 0000000..552e9ba
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/175-partner_units_polynomial-75-0.lp
@@ -0,0 +1,780 @@
+maxPU(2).
+#const n=148.
+object(1,1).
+object(-1,2).
+object(1,3).
+object(-1,4).
+object(1,5).
+object(-1,6).
+object(1,7).
+object(-1,8).
+object(1,9).
+object(-1,10).
+object(1,11).
+object(-1,12).
+object(1,13).
+object(-1,14).
+object(1,15).
+object(-1,16).
+object(1,17).
+object(-1,18).
+object(1,19).
+object(-1,20).
+object(1,21).
+object(-1,22).
+object(1,23).
+object(-1,24).
+object(1,25).
+object(-1,26).
+object(1,27).
+object(-1,28).
+object(1,29).
+object(-1,30).
+object(1,31).
+object(-1,32).
+object(1,33).
+object(-1,34).
+object(1,35).
+object(-1,36).
+object(1,37).
+object(-1,38).
+object(1,39).
+object(-1,40).
+object(1,41).
+object(-1,42).
+object(1,43).
+object(-1,44).
+object(1,45).
+object(-1,46).
+object(1,47).
+object(-1,48).
+object(1,49).
+object(-1,50).
+object(1,51).
+object(-1,52).
+object(1,53).
+object(-1,54).
+object(1,55).
+object(-1,56).
+object(1,57).
+object(-1,58).
+object(1,59).
+object(-1,60).
+object(1,61).
+object(-1,62).
+object(1,63).
+object(-1,64).
+object(1,65).
+object(-1,66).
+object(1,67).
+object(-1,68).
+object(1,69).
+object(-1,70).
+object(1,71).
+object(-1,72).
+object(1,73).
+object(-1,74).
+object(1,75).
+object(-1,76).
+object(1,77).
+object(-1,78).
+object(1,79).
+object(-1,80).
+object(1,81).
+object(-1,82).
+object(1,83).
+object(-1,84).
+object(1,85).
+object(-1,86).
+object(1,87).
+object(-1,88).
+object(1,89).
+object(-1,90).
+object(1,91).
+object(-1,92).
+object(1,93).
+object(-1,94).
+object(1,95).
+object(-1,96).
+object(1,97).
+object(-1,98).
+object(1,99).
+object(-1,100).
+object(1,101).
+object(-1,102).
+object(1,103).
+object(-1,104).
+object(1,105).
+object(-1,106).
+object(1,107).
+object(-1,108).
+object(1,109).
+object(-1,110).
+object(1,111).
+object(-1,112).
+object(1,113).
+object(-1,114).
+object(1,115).
+object(-1,116).
+object(1,117).
+object(-1,118).
+object(1,119).
+object(-1,120).
+object(1,121).
+object(-1,122).
+object(1,123).
+object(-1,124).
+object(1,125).
+object(-1,126).
+object(1,127).
+object(-1,128).
+object(1,129).
+object(-1,130).
+object(1,131).
+object(-1,132).
+object(1,133).
+object(-1,134).
+object(1,135).
+object(-1,136).
+object(1,137).
+object(-1,138).
+object(1,139).
+object(-1,140).
+object(1,141).
+object(-1,142).
+object(1,143).
+object(-1,144).
+object(1,145).
+object(-1,146).
+object(1,147).
+object(1,148).
+follow(1,1,1,3).
+follow(1,3,1,5).
+follow(1,5,1,7).
+follow(1,7,1,9).
+follow(1,9,1,11).
+follow(1,11,1,13).
+follow(1,13,1,15).
+follow(1,15,1,17).
+follow(1,17,1,19).
+follow(1,19,1,21).
+follow(1,21,1,23).
+follow(1,23,1,25).
+follow(1,25,1,27).
+follow(1,27,1,29).
+follow(1,29,1,31).
+follow(1,31,1,33).
+follow(1,33,1,35).
+follow(1,35,1,37).
+follow(1,37,1,39).
+follow(1,39,1,41).
+follow(1,41,1,43).
+follow(1,43,1,45).
+follow(1,45,1,47).
+follow(1,47,1,49).
+follow(1,49,1,51).
+follow(1,51,1,53).
+follow(1,53,1,55).
+follow(1,55,1,57).
+follow(1,57,1,59).
+follow(1,59,1,61).
+follow(1,61,1,63).
+follow(1,63,1,65).
+follow(1,65,1,67).
+follow(1,67,1,69).
+follow(1,69,1,71).
+follow(1,71,1,73).
+follow(1,73,1,75).
+follow(1,75,1,77).
+follow(1,77,1,79).
+follow(1,79,1,81).
+follow(1,81,1,83).
+follow(1,83,1,85).
+follow(1,85,1,87).
+follow(1,87,1,89).
+follow(1,89,1,91).
+follow(1,91,1,93).
+follow(1,93,1,95).
+follow(1,95,1,97).
+follow(1,97,1,99).
+follow(1,99,1,101).
+follow(1,101,1,103).
+follow(1,103,1,105).
+follow(1,105,1,107).
+follow(1,107,1,109).
+follow(1,109,1,111).
+follow(1,111,1,113).
+follow(1,113,1,115).
+follow(1,115,1,117).
+follow(1,117,1,119).
+follow(1,119,1,121).
+follow(1,121,1,123).
+follow(1,123,1,125).
+follow(1,125,1,127).
+follow(1,127,1,129).
+follow(1,129,1,131).
+follow(1,131,1,133).
+follow(1,133,1,135).
+follow(1,135,1,137).
+follow(1,137,1,139).
+follow(1,139,1,141).
+follow(1,141,1,143).
+follow(1,143,1,145).
+follow(1,145,1,147).
+follow(1,147,1,148).
+follow(-1,2,-1,4).
+follow(-1,4,-1,6).
+follow(-1,6,-1,8).
+follow(-1,48,-1,50).
+follow(-1,50,-1,52).
+follow(-1,70,-1,72).
+follow(-1,72,-1,74).
+follow(-1,74,-1,76).
+follow(-1,76,-1,78).
+follow(-1,78,-1,80).
+follow(-1,80,-1,82).
+follow(-1,82,-1,84).
+follow(-1,84,-1,86).
+follow(-1,86,-1,88).
+follow(-1,88,-1,90).
+follow(-1,90,-1,92).
+follow(-1,92,-1,94).
+follow(-1,94,-1,96).
+follow(-1,96,-1,98).
+follow(-1,8,-1,10).
+follow(-1,10,-1,12).
+follow(-1,12,-1,14).
+follow(-1,14,-1,16).
+follow(-1,16,-1,18).
+follow(-1,18,-1,20).
+follow(-1,20,-1,22).
+follow(-1,22,-1,24).
+follow(-1,24,-1,26).
+follow(-1,26,-1,28).
+follow(-1,28,-1,30).
+follow(-1,30,-1,32).
+follow(-1,32,-1,34).
+follow(-1,34,-1,36).
+follow(-1,36,-1,38).
+follow(-1,38,-1,40).
+follow(-1,40,-1,42).
+follow(-1,42,-1,44).
+follow(-1,44,-1,46).
+follow(-1,46,-1,48).
+follow(-1,52,-1,54).
+follow(-1,54,-1,56).
+follow(-1,56,-1,58).
+follow(-1,58,-1,60).
+follow(-1,60,-1,62).
+follow(-1,62,-1,64).
+follow(-1,64,-1,66).
+follow(-1,66,-1,68).
+follow(-1,68,-1,70).
+follow(-1,98,-1,100).
+follow(-1,100,-1,102).
+follow(-1,122,-1,124).
+follow(-1,132,-1,134).
+follow(-1,134,-1,136).
+follow(-1,136,-1,138).
+follow(-1,138,-1,140).
+follow(-1,140,-1,142).
+follow(-1,142,-1,144).
+follow(-1,144,-1,146).
+follow(-1,102,-1,104).
+follow(-1,104,-1,106).
+follow(-1,106,-1,108).
+follow(-1,108,-1,110).
+follow(-1,110,-1,112).
+follow(-1,112,-1,114).
+follow(-1,114,-1,116).
+follow(-1,116,-1,118).
+follow(-1,118,-1,120).
+follow(-1,120,-1,122).
+follow(-1,124,-1,126).
+follow(-1,126,-1,128).
+follow(-1,128,-1,130).
+follow(-1,130,-1,132).
+relate(1,1,-1,2).
+relate(1,1,-1,4).
+relate(1,3,-1,2).
+relate(1,3,-1,6).
+relate(1,3,-1,8).
+relate(1,5,-1,6).
+relate(1,5,-1,50).
+relate(1,5,-1,52).
+relate(1,7,-1,50).
+relate(1,7,-1,72).
+relate(1,7,-1,74).
+relate(1,9,-1,72).
+relate(1,9,-1,76).
+relate(1,9,-1,78).
+relate(1,11,-1,76).
+relate(1,11,-1,80).
+relate(1,11,-1,82).
+relate(1,13,-1,80).
+relate(1,13,-1,84).
+relate(1,13,-1,86).
+relate(1,15,-1,84).
+relate(1,15,-1,88).
+relate(1,15,-1,90).
+relate(1,17,-1,88).
+relate(1,17,-1,92).
+relate(1,17,-1,94).
+relate(1,19,-1,92).
+relate(1,19,-1,96).
+relate(1,19,-1,98).
+relate(1,21,-1,10).
+relate(1,21,-1,12).
+relate(1,21,-1,96).
+relate(1,23,-1,10).
+relate(1,23,-1,14).
+relate(1,23,-1,16).
+relate(1,25,-1,14).
+relate(1,25,-1,18).
+relate(1,25,-1,20).
+relate(1,27,-1,18).
+relate(1,27,-1,22).
+relate(1,27,-1,24).
+relate(1,29,-1,22).
+relate(1,29,-1,26).
+relate(1,29,-1,28).
+relate(1,31,-1,26).
+relate(1,31,-1,30).
+relate(1,31,-1,32).
+relate(1,33,-1,30).
+relate(1,33,-1,34).
+relate(1,33,-1,36).
+relate(1,35,-1,34).
+relate(1,35,-1,38).
+relate(1,35,-1,40).
+relate(1,37,-1,38).
+relate(1,37,-1,42).
+relate(1,37,-1,44).
+relate(1,39,-1,42).
+relate(1,39,-1,46).
+relate(1,39,-1,48).
+relate(1,41,-1,46).
+relate(1,41,-1,54).
+relate(1,41,-1,56).
+relate(1,43,-1,54).
+relate(1,43,-1,58).
+relate(1,43,-1,60).
+relate(1,45,-1,58).
+relate(1,45,-1,62).
+relate(1,45,-1,64).
+relate(1,47,-1,62).
+relate(1,47,-1,66).
+relate(1,47,-1,68).
+relate(1,49,-1,66).
+relate(1,49,-1,70).
+relate(1,51,-1,4).
+relate(1,51,-1,100).
+relate(1,53,-1,8).
+relate(1,53,-1,100).
+relate(1,53,-1,102).
+relate(1,55,-1,52).
+relate(1,55,-1,102).
+relate(1,55,-1,124).
+relate(1,57,-1,74).
+relate(1,57,-1,124).
+relate(1,57,-1,134).
+relate(1,59,-1,78).
+relate(1,59,-1,134).
+relate(1,59,-1,136).
+relate(1,61,-1,82).
+relate(1,61,-1,136).
+relate(1,61,-1,138).
+relate(1,63,-1,86).
+relate(1,63,-1,138).
+relate(1,63,-1,140).
+relate(1,65,-1,90).
+relate(1,65,-1,140).
+relate(1,65,-1,142).
+relate(1,67,-1,94).
+relate(1,67,-1,142).
+relate(1,67,-1,144).
+relate(1,69,-1,98).
+relate(1,69,-1,144).
+relate(1,69,-1,146).
+relate(1,71,-1,12).
+relate(1,71,-1,104).
+relate(1,71,-1,146).
+relate(1,73,-1,16).
+relate(1,73,-1,104).
+relate(1,73,-1,106).
+relate(1,75,-1,20).
+relate(1,75,-1,106).
+relate(1,75,-1,108).
+relate(1,77,-1,24).
+relate(1,77,-1,108).
+relate(1,77,-1,110).
+relate(1,79,-1,28).
+relate(1,79,-1,110).
+relate(1,79,-1,112).
+relate(1,81,-1,32).
+relate(1,81,-1,112).
+relate(1,81,-1,114).
+relate(1,83,-1,36).
+relate(1,83,-1,114).
+relate(1,83,-1,116).
+relate(1,85,-1,40).
+relate(1,85,-1,116).
+relate(1,85,-1,118).
+relate(1,87,-1,44).
+relate(1,87,-1,118).
+relate(1,87,-1,120).
+relate(1,89,-1,48).
+relate(1,89,-1,120).
+relate(1,89,-1,122).
+relate(1,91,-1,56).
+relate(1,91,-1,122).
+relate(1,91,-1,126).
+relate(1,93,-1,60).
+relate(1,93,-1,126).
+relate(1,93,-1,128).
+relate(1,95,-1,64).
+relate(1,95,-1,128).
+relate(1,95,-1,130).
+relate(1,97,-1,68).
+relate(1,97,-1,130).
+relate(1,97,-1,132).
+relate(1,99,-1,70).
+relate(1,99,-1,132).
+relate(1,101,-1,2).
+relate(1,101,-1,100).
+relate(1,103,-1,2).
+relate(1,103,-1,6).
+relate(1,103,-1,100).
+relate(1,103,-1,102).
+relate(1,105,-1,6).
+relate(1,105,-1,50).
+relate(1,105,-1,102).
+relate(1,105,-1,124).
+relate(1,107,-1,50).
+relate(1,107,-1,72).
+relate(1,107,-1,124).
+relate(1,107,-1,134).
+relate(1,109,-1,72).
+relate(1,109,-1,76).
+relate(1,109,-1,134).
+relate(1,109,-1,136).
+relate(1,111,-1,76).
+relate(1,111,-1,80).
+relate(1,111,-1,136).
+relate(1,111,-1,138).
+relate(1,113,-1,80).
+relate(1,113,-1,84).
+relate(1,113,-1,138).
+relate(1,113,-1,140).
+relate(1,115,-1,84).
+relate(1,115,-1,88).
+relate(1,115,-1,140).
+relate(1,115,-1,142).
+relate(1,117,-1,88).
+relate(1,117,-1,92).
+relate(1,117,-1,142).
+relate(1,117,-1,144).
+relate(1,119,-1,92).
+relate(1,119,-1,96).
+relate(1,119,-1,144).
+relate(1,119,-1,146).
+relate(1,121,-1,10).
+relate(1,121,-1,96).
+relate(1,121,-1,104).
+relate(1,121,-1,146).
+relate(1,123,-1,10).
+relate(1,123,-1,14).
+relate(1,123,-1,104).
+relate(1,123,-1,106).
+relate(1,125,-1,14).
+relate(1,125,-1,18).
+relate(1,125,-1,106).
+relate(1,125,-1,108).
+relate(1,127,-1,18).
+relate(1,127,-1,22).
+relate(1,127,-1,108).
+relate(1,127,-1,110).
+relate(1,129,-1,22).
+relate(1,129,-1,26).
+relate(1,129,-1,110).
+relate(1,129,-1,112).
+relate(1,131,-1,26).
+relate(1,131,-1,30).
+relate(1,131,-1,112).
+relate(1,131,-1,114).
+relate(1,133,-1,30).
+relate(1,133,-1,34).
+relate(1,133,-1,114).
+relate(1,133,-1,116).
+relate(1,135,-1,34).
+relate(1,135,-1,38).
+relate(1,135,-1,116).
+relate(1,135,-1,118).
+relate(1,137,-1,38).
+relate(1,137,-1,42).
+relate(1,137,-1,118).
+relate(1,137,-1,120).
+relate(1,139,-1,42).
+relate(1,139,-1,46).
+relate(1,139,-1,120).
+relate(1,139,-1,122).
+relate(1,141,-1,46).
+relate(1,141,-1,54).
+relate(1,141,-1,122).
+relate(1,141,-1,126).
+relate(1,143,-1,54).
+relate(1,143,-1,58).
+relate(1,143,-1,126).
+relate(1,143,-1,128).
+relate(1,145,-1,58).
+relate(1,145,-1,62).
+relate(1,145,-1,128).
+relate(1,145,-1,130).
+relate(1,147,-1,62).
+relate(1,147,-1,66).
+relate(1,147,-1,130).
+relate(1,147,-1,132).
+relate(1,148,-1,66).
+relate(1,148,-1,132).
+relate(-1,2,1,1).
+relate(-1,4,1,1).
+relate(-1,2,1,3).
+relate(-1,6,1,3).
+relate(-1,8,1,3).
+relate(-1,6,1,5).
+relate(-1,50,1,5).
+relate(-1,52,1,5).
+relate(-1,50,1,7).
+relate(-1,72,1,7).
+relate(-1,74,1,7).
+relate(-1,72,1,9).
+relate(-1,76,1,9).
+relate(-1,78,1,9).
+relate(-1,76,1,11).
+relate(-1,80,1,11).
+relate(-1,82,1,11).
+relate(-1,80,1,13).
+relate(-1,84,1,13).
+relate(-1,86,1,13).
+relate(-1,84,1,15).
+relate(-1,88,1,15).
+relate(-1,90,1,15).
+relate(-1,88,1,17).
+relate(-1,92,1,17).
+relate(-1,94,1,17).
+relate(-1,92,1,19).
+relate(-1,96,1,19).
+relate(-1,98,1,19).
+relate(-1,10,1,21).
+relate(-1,12,1,21).
+relate(-1,96,1,21).
+relate(-1,10,1,23).
+relate(-1,14,1,23).
+relate(-1,16,1,23).
+relate(-1,14,1,25).
+relate(-1,18,1,25).
+relate(-1,20,1,25).
+relate(-1,18,1,27).
+relate(-1,22,1,27).
+relate(-1,24,1,27).
+relate(-1,22,1,29).
+relate(-1,26,1,29).
+relate(-1,28,1,29).
+relate(-1,26,1,31).
+relate(-1,30,1,31).
+relate(-1,32,1,31).
+relate(-1,30,1,33).
+relate(-1,34,1,33).
+relate(-1,36,1,33).
+relate(-1,34,1,35).
+relate(-1,38,1,35).
+relate(-1,40,1,35).
+relate(-1,38,1,37).
+relate(-1,42,1,37).
+relate(-1,44,1,37).
+relate(-1,42,1,39).
+relate(-1,46,1,39).
+relate(-1,48,1,39).
+relate(-1,46,1,41).
+relate(-1,54,1,41).
+relate(-1,56,1,41).
+relate(-1,54,1,43).
+relate(-1,58,1,43).
+relate(-1,60,1,43).
+relate(-1,58,1,45).
+relate(-1,62,1,45).
+relate(-1,64,1,45).
+relate(-1,62,1,47).
+relate(-1,66,1,47).
+relate(-1,68,1,47).
+relate(-1,66,1,49).
+relate(-1,70,1,49).
+relate(-1,4,1,51).
+relate(-1,100,1,51).
+relate(-1,8,1,53).
+relate(-1,100,1,53).
+relate(-1,102,1,53).
+relate(-1,52,1,55).
+relate(-1,102,1,55).
+relate(-1,124,1,55).
+relate(-1,74,1,57).
+relate(-1,124,1,57).
+relate(-1,134,1,57).
+relate(-1,78,1,59).
+relate(-1,134,1,59).
+relate(-1,136,1,59).
+relate(-1,82,1,61).
+relate(-1,136,1,61).
+relate(-1,138,1,61).
+relate(-1,86,1,63).
+relate(-1,138,1,63).
+relate(-1,140,1,63).
+relate(-1,90,1,65).
+relate(-1,140,1,65).
+relate(-1,142,1,65).
+relate(-1,94,1,67).
+relate(-1,142,1,67).
+relate(-1,144,1,67).
+relate(-1,98,1,69).
+relate(-1,144,1,69).
+relate(-1,146,1,69).
+relate(-1,12,1,71).
+relate(-1,104,1,71).
+relate(-1,146,1,71).
+relate(-1,16,1,73).
+relate(-1,104,1,73).
+relate(-1,106,1,73).
+relate(-1,20,1,75).
+relate(-1,106,1,75).
+relate(-1,108,1,75).
+relate(-1,24,1,77).
+relate(-1,108,1,77).
+relate(-1,110,1,77).
+relate(-1,28,1,79).
+relate(-1,110,1,79).
+relate(-1,112,1,79).
+relate(-1,32,1,81).
+relate(-1,112,1,81).
+relate(-1,114,1,81).
+relate(-1,36,1,83).
+relate(-1,114,1,83).
+relate(-1,116,1,83).
+relate(-1,40,1,85).
+relate(-1,116,1,85).
+relate(-1,118,1,85).
+relate(-1,44,1,87).
+relate(-1,118,1,87).
+relate(-1,120,1,87).
+relate(-1,48,1,89).
+relate(-1,120,1,89).
+relate(-1,122,1,89).
+relate(-1,56,1,91).
+relate(-1,122,1,91).
+relate(-1,126,1,91).
+relate(-1,60,1,93).
+relate(-1,126,1,93).
+relate(-1,128,1,93).
+relate(-1,64,1,95).
+relate(-1,128,1,95).
+relate(-1,130,1,95).
+relate(-1,68,1,97).
+relate(-1,130,1,97).
+relate(-1,132,1,97).
+relate(-1,70,1,99).
+relate(-1,132,1,99).
+relate(-1,2,1,101).
+relate(-1,100,1,101).
+relate(-1,2,1,103).
+relate(-1,6,1,103).
+relate(-1,100,1,103).
+relate(-1,102,1,103).
+relate(-1,6,1,105).
+relate(-1,50,1,105).
+relate(-1,102,1,105).
+relate(-1,124,1,105).
+relate(-1,50,1,107).
+relate(-1,72,1,107).
+relate(-1,124,1,107).
+relate(-1,134,1,107).
+relate(-1,72,1,109).
+relate(-1,76,1,109).
+relate(-1,134,1,109).
+relate(-1,136,1,109).
+relate(-1,76,1,111).
+relate(-1,80,1,111).
+relate(-1,136,1,111).
+relate(-1,138,1,111).
+relate(-1,80,1,113).
+relate(-1,84,1,113).
+relate(-1,138,1,113).
+relate(-1,140,1,113).
+relate(-1,84,1,115).
+relate(-1,88,1,115).
+relate(-1,140,1,115).
+relate(-1,142,1,115).
+relate(-1,88,1,117).
+relate(-1,92,1,117).
+relate(-1,142,1,117).
+relate(-1,144,1,117).
+relate(-1,92,1,119).
+relate(-1,96,1,119).
+relate(-1,144,1,119).
+relate(-1,146,1,119).
+relate(-1,10,1,121).
+relate(-1,96,1,121).
+relate(-1,104,1,121).
+relate(-1,146,1,121).
+relate(-1,10,1,123).
+relate(-1,14,1,123).
+relate(-1,104,1,123).
+relate(-1,106,1,123).
+relate(-1,14,1,125).
+relate(-1,18,1,125).
+relate(-1,106,1,125).
+relate(-1,108,1,125).
+relate(-1,18,1,127).
+relate(-1,22,1,127).
+relate(-1,108,1,127).
+relate(-1,110,1,127).
+relate(-1,22,1,129).
+relate(-1,26,1,129).
+relate(-1,110,1,129).
+relate(-1,112,1,129).
+relate(-1,26,1,131).
+relate(-1,30,1,131).
+relate(-1,112,1,131).
+relate(-1,114,1,131).
+relate(-1,30,1,133).
+relate(-1,34,1,133).
+relate(-1,114,1,133).
+relate(-1,116,1,133).
+relate(-1,34,1,135).
+relate(-1,38,1,135).
+relate(-1,116,1,135).
+relate(-1,118,1,135).
+relate(-1,38,1,137).
+relate(-1,42,1,137).
+relate(-1,118,1,137).
+relate(-1,120,1,137).
+relate(-1,42,1,139).
+relate(-1,46,1,139).
+relate(-1,120,1,139).
+relate(-1,122,1,139).
+relate(-1,46,1,141).
+relate(-1,54,1,141).
+relate(-1,122,1,141).
+relate(-1,126,1,141).
+relate(-1,54,1,143).
+relate(-1,58,1,143).
+relate(-1,126,1,143).
+relate(-1,128,1,143).
+relate(-1,58,1,145).
+relate(-1,62,1,145).
+relate(-1,128,1,145).
+relate(-1,130,1,145).
+relate(-1,62,1,147).
+relate(-1,66,1,147).
+relate(-1,130,1,147).
+relate(-1,132,1,147).
+relate(-1,66,1,148).
+relate(-1,132,1,148).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/180-partner_units_polynomial-47-0.lp b/examples/clingo/expansion/PartnerUnits/instances/180-partner_units_polynomial-47-0.lp
new file mode 100644
index 0000000..72f0ec8
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/180-partner_units_polynomial-47-0.lp
@@ -0,0 +1,366 @@
+maxPU(2).
+#const n=85.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(-1,78).
+object(-1,79).
+object(-1,80).
+object(-1,81).
+object(-1,82).
+object(-1,83).
+object(-1,84).
+object(-1,85).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(-1,1,-1,3).
+follow(-1,5,-1,7).
+follow(-1,23,-1,25).
+follow(-1,35,-1,37).
+follow(-1,37,-1,39).
+follow(-1,3,-1,5).
+follow(-1,9,-1,11).
+follow(-1,25,-1,27).
+follow(-1,39,-1,41).
+follow(-1,7,-1,9).
+follow(-1,13,-1,15).
+follow(-1,27,-1,29).
+follow(-1,41,-1,43).
+follow(-1,11,-1,13).
+follow(-1,17,-1,19).
+follow(-1,29,-1,31).
+follow(-1,43,-1,45).
+follow(-1,15,-1,17).
+follow(-1,21,-1,23).
+follow(-1,31,-1,33).
+follow(-1,45,-1,47).
+follow(-1,19,-1,21).
+follow(-1,33,-1,35).
+follow(-1,47,-1,49).
+follow(-1,51,-1,53).
+follow(-1,69,-1,71).
+follow(-1,79,-1,80).
+follow(-1,80,-1,81).
+follow(-1,49,-1,51).
+follow(-1,55,-1,57).
+follow(-1,71,-1,73).
+follow(-1,81,-1,82).
+follow(-1,53,-1,55).
+follow(-1,59,-1,61).
+follow(-1,73,-1,75).
+follow(-1,82,-1,83).
+follow(-1,57,-1,59).
+follow(-1,63,-1,65).
+follow(-1,75,-1,77).
+follow(-1,83,-1,84).
+follow(-1,61,-1,63).
+follow(-1,67,-1,69).
+follow(-1,77,-1,78).
+follow(-1,84,-1,85).
+follow(-1,65,-1,67).
+follow(-1,78,-1,79).
+relate(1,2,-1,1).
+relate(1,2,-1,3).
+relate(1,2,-1,7).
+relate(1,4,-1,3).
+relate(1,4,-1,25).
+relate(1,6,-1,25).
+relate(1,6,-1,37).
+relate(1,6,-1,39).
+relate(1,8,-1,5).
+relate(1,8,-1,7).
+relate(1,8,-1,11).
+relate(1,10,-1,5).
+relate(1,10,-1,27).
+relate(1,12,-1,27).
+relate(1,12,-1,39).
+relate(1,12,-1,41).
+relate(1,14,-1,9).
+relate(1,14,-1,11).
+relate(1,14,-1,15).
+relate(1,16,-1,9).
+relate(1,16,-1,29).
+relate(1,18,-1,29).
+relate(1,18,-1,41).
+relate(1,18,-1,43).
+relate(1,20,-1,13).
+relate(1,20,-1,15).
+relate(1,20,-1,19).
+relate(1,22,-1,13).
+relate(1,22,-1,31).
+relate(1,24,-1,31).
+relate(1,24,-1,43).
+relate(1,24,-1,45).
+relate(1,26,-1,17).
+relate(1,26,-1,19).
+relate(1,26,-1,23).
+relate(1,28,-1,17).
+relate(1,28,-1,33).
+relate(1,30,-1,33).
+relate(1,30,-1,45).
+relate(1,30,-1,47).
+relate(1,32,-1,21).
+relate(1,32,-1,23).
+relate(1,34,-1,21).
+relate(1,34,-1,35).
+relate(1,36,-1,35).
+relate(1,36,-1,47).
+relate(1,38,-1,1).
+relate(1,38,-1,7).
+relate(1,38,-1,25).
+relate(1,40,-1,37).
+relate(1,40,-1,49).
+relate(1,40,-1,53).
+relate(1,42,-1,49).
+relate(1,42,-1,71).
+relate(1,44,-1,71).
+relate(1,44,-1,80).
+relate(1,44,-1,81).
+relate(1,46,-1,51).
+relate(1,46,-1,53).
+relate(1,46,-1,57).
+relate(1,48,-1,51).
+relate(1,48,-1,73).
+relate(1,50,-1,73).
+relate(1,50,-1,81).
+relate(1,50,-1,82).
+relate(1,52,-1,55).
+relate(1,52,-1,57).
+relate(1,52,-1,61).
+relate(1,54,-1,55).
+relate(1,54,-1,75).
+relate(1,56,-1,75).
+relate(1,56,-1,82).
+relate(1,56,-1,83).
+relate(1,58,-1,59).
+relate(1,58,-1,61).
+relate(1,58,-1,65).
+relate(1,60,-1,59).
+relate(1,60,-1,77).
+relate(1,62,-1,77).
+relate(1,62,-1,83).
+relate(1,62,-1,84).
+relate(1,64,-1,63).
+relate(1,64,-1,65).
+relate(1,64,-1,69).
+relate(1,66,-1,63).
+relate(1,66,-1,78).
+relate(1,68,-1,78).
+relate(1,68,-1,84).
+relate(1,68,-1,85).
+relate(1,70,-1,67).
+relate(1,70,-1,69).
+relate(1,72,-1,67).
+relate(1,72,-1,79).
+relate(1,74,-1,79).
+relate(1,74,-1,85).
+relate(1,76,-1,37).
+relate(1,76,-1,53).
+relate(1,76,-1,71).
+relate(-1,1,1,2).
+relate(-1,3,1,2).
+relate(-1,7,1,2).
+relate(-1,3,1,4).
+relate(-1,25,1,4).
+relate(-1,25,1,6).
+relate(-1,37,1,6).
+relate(-1,39,1,6).
+relate(-1,5,1,8).
+relate(-1,7,1,8).
+relate(-1,11,1,8).
+relate(-1,5,1,10).
+relate(-1,27,1,10).
+relate(-1,27,1,12).
+relate(-1,39,1,12).
+relate(-1,41,1,12).
+relate(-1,9,1,14).
+relate(-1,11,1,14).
+relate(-1,15,1,14).
+relate(-1,9,1,16).
+relate(-1,29,1,16).
+relate(-1,29,1,18).
+relate(-1,41,1,18).
+relate(-1,43,1,18).
+relate(-1,13,1,20).
+relate(-1,15,1,20).
+relate(-1,19,1,20).
+relate(-1,13,1,22).
+relate(-1,31,1,22).
+relate(-1,31,1,24).
+relate(-1,43,1,24).
+relate(-1,45,1,24).
+relate(-1,17,1,26).
+relate(-1,19,1,26).
+relate(-1,23,1,26).
+relate(-1,17,1,28).
+relate(-1,33,1,28).
+relate(-1,33,1,30).
+relate(-1,45,1,30).
+relate(-1,47,1,30).
+relate(-1,21,1,32).
+relate(-1,23,1,32).
+relate(-1,21,1,34).
+relate(-1,35,1,34).
+relate(-1,35,1,36).
+relate(-1,47,1,36).
+relate(-1,1,1,38).
+relate(-1,7,1,38).
+relate(-1,25,1,38).
+relate(-1,37,1,40).
+relate(-1,49,1,40).
+relate(-1,53,1,40).
+relate(-1,49,1,42).
+relate(-1,71,1,42).
+relate(-1,71,1,44).
+relate(-1,80,1,44).
+relate(-1,81,1,44).
+relate(-1,51,1,46).
+relate(-1,53,1,46).
+relate(-1,57,1,46).
+relate(-1,51,1,48).
+relate(-1,73,1,48).
+relate(-1,73,1,50).
+relate(-1,81,1,50).
+relate(-1,82,1,50).
+relate(-1,55,1,52).
+relate(-1,57,1,52).
+relate(-1,61,1,52).
+relate(-1,55,1,54).
+relate(-1,75,1,54).
+relate(-1,75,1,56).
+relate(-1,82,1,56).
+relate(-1,83,1,56).
+relate(-1,59,1,58).
+relate(-1,61,1,58).
+relate(-1,65,1,58).
+relate(-1,59,1,60).
+relate(-1,77,1,60).
+relate(-1,77,1,62).
+relate(-1,83,1,62).
+relate(-1,84,1,62).
+relate(-1,63,1,64).
+relate(-1,65,1,64).
+relate(-1,69,1,64).
+relate(-1,63,1,66).
+relate(-1,78,1,66).
+relate(-1,78,1,68).
+relate(-1,84,1,68).
+relate(-1,85,1,68).
+relate(-1,67,1,70).
+relate(-1,69,1,70).
+relate(-1,67,1,72).
+relate(-1,79,1,72).
+relate(-1,79,1,74).
+relate(-1,85,1,74).
+relate(-1,37,1,76).
+relate(-1,53,1,76).
+relate(-1,71,1,76).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/188-partner_units_polynomial-57-0.lp b/examples/clingo/expansion/PartnerUnits/instances/188-partner_units_polynomial-57-0.lp
new file mode 100644
index 0000000..f180100
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/188-partner_units_polynomial-57-0.lp
@@ -0,0 +1,588 @@
+maxPU(2).
+#const n=112.
+object(1,1).
+object(-1,2).
+object(1,3).
+object(-1,4).
+object(1,5).
+object(-1,6).
+object(1,7).
+object(-1,8).
+object(1,9).
+object(-1,10).
+object(1,11).
+object(-1,12).
+object(1,13).
+object(-1,14).
+object(1,15).
+object(-1,16).
+object(1,17).
+object(-1,18).
+object(1,19).
+object(-1,20).
+object(1,21).
+object(-1,22).
+object(1,23).
+object(-1,24).
+object(1,25).
+object(-1,26).
+object(1,27).
+object(-1,28).
+object(1,29).
+object(-1,30).
+object(1,31).
+object(-1,32).
+object(1,33).
+object(-1,34).
+object(1,35).
+object(-1,36).
+object(1,37).
+object(-1,38).
+object(1,39).
+object(-1,40).
+object(1,41).
+object(-1,42).
+object(1,43).
+object(-1,44).
+object(1,45).
+object(-1,46).
+object(1,47).
+object(-1,48).
+object(1,49).
+object(-1,50).
+object(1,51).
+object(-1,52).
+object(1,53).
+object(-1,54).
+object(1,55).
+object(-1,56).
+object(1,57).
+object(-1,58).
+object(1,59).
+object(-1,60).
+object(1,61).
+object(-1,62).
+object(1,63).
+object(-1,64).
+object(1,65).
+object(-1,66).
+object(1,67).
+object(-1,68).
+object(1,69).
+object(-1,70).
+object(1,71).
+object(-1,72).
+object(1,73).
+object(-1,74).
+object(1,75).
+object(-1,76).
+object(1,77).
+object(-1,78).
+object(1,79).
+object(-1,80).
+object(1,81).
+object(-1,82).
+object(1,83).
+object(-1,84).
+object(1,85).
+object(-1,86).
+object(1,87).
+object(-1,88).
+object(1,89).
+object(-1,90).
+object(1,91).
+object(-1,92).
+object(1,93).
+object(-1,94).
+object(1,95).
+object(-1,96).
+object(1,97).
+object(-1,98).
+object(1,99).
+object(-1,100).
+object(1,101).
+object(-1,102).
+object(1,103).
+object(-1,104).
+object(1,105).
+object(-1,106).
+object(1,107).
+object(-1,108).
+object(1,109).
+object(-1,110).
+object(1,111).
+object(1,112).
+follow(1,1,1,3).
+follow(1,3,1,5).
+follow(1,5,1,7).
+follow(1,7,1,9).
+follow(1,9,1,11).
+follow(1,11,1,13).
+follow(1,13,1,15).
+follow(1,15,1,17).
+follow(1,17,1,19).
+follow(1,19,1,21).
+follow(1,21,1,23).
+follow(1,23,1,25).
+follow(1,25,1,27).
+follow(1,27,1,29).
+follow(1,29,1,31).
+follow(1,31,1,33).
+follow(1,33,1,35).
+follow(1,35,1,37).
+follow(1,37,1,39).
+follow(1,39,1,41).
+follow(1,41,1,43).
+follow(1,43,1,45).
+follow(1,45,1,47).
+follow(1,47,1,49).
+follow(1,49,1,51).
+follow(1,51,1,53).
+follow(1,53,1,55).
+follow(1,55,1,57).
+follow(1,57,1,59).
+follow(1,59,1,61).
+follow(1,61,1,63).
+follow(1,63,1,65).
+follow(1,65,1,67).
+follow(1,67,1,69).
+follow(1,69,1,71).
+follow(1,71,1,73).
+follow(1,73,1,75).
+follow(1,75,1,77).
+follow(1,77,1,79).
+follow(1,79,1,81).
+follow(1,81,1,83).
+follow(1,83,1,85).
+follow(1,85,1,87).
+follow(1,87,1,89).
+follow(1,89,1,91).
+follow(1,91,1,93).
+follow(1,93,1,95).
+follow(1,95,1,97).
+follow(1,97,1,99).
+follow(1,99,1,101).
+follow(1,101,1,103).
+follow(1,103,1,105).
+follow(1,105,1,107).
+follow(1,107,1,109).
+follow(1,109,1,111).
+follow(1,111,1,112).
+follow(-1,2,-1,4).
+follow(-1,4,-1,6).
+follow(-1,6,-1,8).
+follow(-1,42,-1,44).
+follow(-1,44,-1,46).
+follow(-1,46,-1,48).
+follow(-1,48,-1,50).
+follow(-1,50,-1,52).
+follow(-1,52,-1,54).
+follow(-1,54,-1,56).
+follow(-1,56,-1,58).
+follow(-1,58,-1,60).
+follow(-1,60,-1,62).
+follow(-1,62,-1,64).
+follow(-1,64,-1,66).
+follow(-1,66,-1,68).
+follow(-1,68,-1,70).
+follow(-1,70,-1,72).
+follow(-1,72,-1,74).
+follow(-1,8,-1,10).
+follow(-1,10,-1,12).
+follow(-1,12,-1,14).
+follow(-1,14,-1,16).
+follow(-1,16,-1,18).
+follow(-1,18,-1,20).
+follow(-1,20,-1,22).
+follow(-1,22,-1,24).
+follow(-1,24,-1,26).
+follow(-1,26,-1,28).
+follow(-1,28,-1,30).
+follow(-1,30,-1,32).
+follow(-1,32,-1,34).
+follow(-1,34,-1,36).
+follow(-1,36,-1,38).
+follow(-1,38,-1,40).
+follow(-1,40,-1,42).
+follow(-1,74,-1,76).
+follow(-1,76,-1,78).
+follow(-1,94,-1,96).
+follow(-1,96,-1,98).
+follow(-1,98,-1,100).
+follow(-1,100,-1,102).
+follow(-1,102,-1,104).
+follow(-1,104,-1,106).
+follow(-1,106,-1,108).
+follow(-1,108,-1,110).
+follow(-1,78,-1,80).
+follow(-1,80,-1,82).
+follow(-1,82,-1,84).
+follow(-1,84,-1,86).
+follow(-1,86,-1,88).
+follow(-1,88,-1,90).
+follow(-1,90,-1,92).
+follow(-1,92,-1,94).
+relate(1,1,-1,2).
+relate(1,1,-1,4).
+relate(1,3,-1,2).
+relate(1,3,-1,6).
+relate(1,3,-1,8).
+relate(1,5,-1,6).
+relate(1,5,-1,44).
+relate(1,5,-1,46).
+relate(1,7,-1,44).
+relate(1,7,-1,48).
+relate(1,7,-1,50).
+relate(1,9,-1,48).
+relate(1,9,-1,52).
+relate(1,9,-1,54).
+relate(1,11,-1,52).
+relate(1,11,-1,56).
+relate(1,11,-1,58).
+relate(1,13,-1,56).
+relate(1,13,-1,60).
+relate(1,13,-1,62).
+relate(1,15,-1,60).
+relate(1,15,-1,64).
+relate(1,15,-1,66).
+relate(1,17,-1,64).
+relate(1,17,-1,68).
+relate(1,17,-1,70).
+relate(1,19,-1,68).
+relate(1,19,-1,72).
+relate(1,19,-1,74).
+relate(1,21,-1,10).
+relate(1,21,-1,12).
+relate(1,21,-1,72).
+relate(1,23,-1,10).
+relate(1,23,-1,14).
+relate(1,23,-1,16).
+relate(1,25,-1,14).
+relate(1,25,-1,18).
+relate(1,25,-1,20).
+relate(1,27,-1,18).
+relate(1,27,-1,22).
+relate(1,27,-1,24).
+relate(1,29,-1,22).
+relate(1,29,-1,26).
+relate(1,29,-1,28).
+relate(1,31,-1,26).
+relate(1,31,-1,30).
+relate(1,31,-1,32).
+relate(1,33,-1,30).
+relate(1,33,-1,34).
+relate(1,33,-1,36).
+relate(1,35,-1,34).
+relate(1,35,-1,38).
+relate(1,35,-1,40).
+relate(1,37,-1,38).
+relate(1,37,-1,42).
+relate(1,39,-1,4).
+relate(1,39,-1,76).
+relate(1,41,-1,8).
+relate(1,41,-1,76).
+relate(1,41,-1,78).
+relate(1,43,-1,46).
+relate(1,43,-1,78).
+relate(1,43,-1,96).
+relate(1,45,-1,50).
+relate(1,45,-1,96).
+relate(1,45,-1,98).
+relate(1,47,-1,54).
+relate(1,47,-1,98).
+relate(1,47,-1,100).
+relate(1,49,-1,58).
+relate(1,49,-1,100).
+relate(1,49,-1,102).
+relate(1,51,-1,62).
+relate(1,51,-1,102).
+relate(1,51,-1,104).
+relate(1,53,-1,66).
+relate(1,53,-1,104).
+relate(1,53,-1,106).
+relate(1,55,-1,70).
+relate(1,55,-1,106).
+relate(1,55,-1,108).
+relate(1,57,-1,74).
+relate(1,57,-1,108).
+relate(1,57,-1,110).
+relate(1,59,-1,12).
+relate(1,59,-1,80).
+relate(1,59,-1,110).
+relate(1,61,-1,16).
+relate(1,61,-1,80).
+relate(1,61,-1,82).
+relate(1,63,-1,20).
+relate(1,63,-1,82).
+relate(1,63,-1,84).
+relate(1,65,-1,24).
+relate(1,65,-1,84).
+relate(1,65,-1,86).
+relate(1,67,-1,28).
+relate(1,67,-1,86).
+relate(1,67,-1,88).
+relate(1,69,-1,32).
+relate(1,69,-1,88).
+relate(1,69,-1,90).
+relate(1,71,-1,36).
+relate(1,71,-1,90).
+relate(1,71,-1,92).
+relate(1,73,-1,40).
+relate(1,73,-1,92).
+relate(1,73,-1,94).
+relate(1,75,-1,42).
+relate(1,75,-1,94).
+relate(1,77,-1,2).
+relate(1,77,-1,76).
+relate(1,79,-1,2).
+relate(1,79,-1,6).
+relate(1,79,-1,76).
+relate(1,79,-1,78).
+relate(1,81,-1,6).
+relate(1,81,-1,44).
+relate(1,81,-1,78).
+relate(1,81,-1,96).
+relate(1,83,-1,44).
+relate(1,83,-1,48).
+relate(1,83,-1,96).
+relate(1,83,-1,98).
+relate(1,85,-1,48).
+relate(1,85,-1,52).
+relate(1,85,-1,98).
+relate(1,85,-1,100).
+relate(1,87,-1,52).
+relate(1,87,-1,56).
+relate(1,87,-1,100).
+relate(1,87,-1,102).
+relate(1,89,-1,56).
+relate(1,89,-1,60).
+relate(1,89,-1,102).
+relate(1,89,-1,104).
+relate(1,91,-1,60).
+relate(1,91,-1,64).
+relate(1,91,-1,104).
+relate(1,91,-1,106).
+relate(1,93,-1,64).
+relate(1,93,-1,68).
+relate(1,93,-1,106).
+relate(1,93,-1,108).
+relate(1,95,-1,68).
+relate(1,95,-1,72).
+relate(1,95,-1,108).
+relate(1,95,-1,110).
+relate(1,97,-1,10).
+relate(1,97,-1,72).
+relate(1,97,-1,80).
+relate(1,97,-1,110).
+relate(1,99,-1,10).
+relate(1,99,-1,14).
+relate(1,99,-1,80).
+relate(1,99,-1,82).
+relate(1,101,-1,14).
+relate(1,101,-1,18).
+relate(1,101,-1,82).
+relate(1,101,-1,84).
+relate(1,103,-1,18).
+relate(1,103,-1,22).
+relate(1,103,-1,84).
+relate(1,103,-1,86).
+relate(1,105,-1,22).
+relate(1,105,-1,26).
+relate(1,105,-1,86).
+relate(1,105,-1,88).
+relate(1,107,-1,26).
+relate(1,107,-1,30).
+relate(1,107,-1,88).
+relate(1,107,-1,90).
+relate(1,109,-1,30).
+relate(1,109,-1,34).
+relate(1,109,-1,90).
+relate(1,109,-1,92).
+relate(1,111,-1,34).
+relate(1,111,-1,38).
+relate(1,111,-1,92).
+relate(1,111,-1,94).
+relate(1,112,-1,38).
+relate(1,112,-1,94).
+relate(-1,2,1,1).
+relate(-1,4,1,1).
+relate(-1,2,1,3).
+relate(-1,6,1,3).
+relate(-1,8,1,3).
+relate(-1,6,1,5).
+relate(-1,44,1,5).
+relate(-1,46,1,5).
+relate(-1,44,1,7).
+relate(-1,48,1,7).
+relate(-1,50,1,7).
+relate(-1,48,1,9).
+relate(-1,52,1,9).
+relate(-1,54,1,9).
+relate(-1,52,1,11).
+relate(-1,56,1,11).
+relate(-1,58,1,11).
+relate(-1,56,1,13).
+relate(-1,60,1,13).
+relate(-1,62,1,13).
+relate(-1,60,1,15).
+relate(-1,64,1,15).
+relate(-1,66,1,15).
+relate(-1,64,1,17).
+relate(-1,68,1,17).
+relate(-1,70,1,17).
+relate(-1,68,1,19).
+relate(-1,72,1,19).
+relate(-1,74,1,19).
+relate(-1,10,1,21).
+relate(-1,12,1,21).
+relate(-1,72,1,21).
+relate(-1,10,1,23).
+relate(-1,14,1,23).
+relate(-1,16,1,23).
+relate(-1,14,1,25).
+relate(-1,18,1,25).
+relate(-1,20,1,25).
+relate(-1,18,1,27).
+relate(-1,22,1,27).
+relate(-1,24,1,27).
+relate(-1,22,1,29).
+relate(-1,26,1,29).
+relate(-1,28,1,29).
+relate(-1,26,1,31).
+relate(-1,30,1,31).
+relate(-1,32,1,31).
+relate(-1,30,1,33).
+relate(-1,34,1,33).
+relate(-1,36,1,33).
+relate(-1,34,1,35).
+relate(-1,38,1,35).
+relate(-1,40,1,35).
+relate(-1,38,1,37).
+relate(-1,42,1,37).
+relate(-1,4,1,39).
+relate(-1,76,1,39).
+relate(-1,8,1,41).
+relate(-1,76,1,41).
+relate(-1,78,1,41).
+relate(-1,46,1,43).
+relate(-1,78,1,43).
+relate(-1,96,1,43).
+relate(-1,50,1,45).
+relate(-1,96,1,45).
+relate(-1,98,1,45).
+relate(-1,54,1,47).
+relate(-1,98,1,47).
+relate(-1,100,1,47).
+relate(-1,58,1,49).
+relate(-1,100,1,49).
+relate(-1,102,1,49).
+relate(-1,62,1,51).
+relate(-1,102,1,51).
+relate(-1,104,1,51).
+relate(-1,66,1,53).
+relate(-1,104,1,53).
+relate(-1,106,1,53).
+relate(-1,70,1,55).
+relate(-1,106,1,55).
+relate(-1,108,1,55).
+relate(-1,74,1,57).
+relate(-1,108,1,57).
+relate(-1,110,1,57).
+relate(-1,12,1,59).
+relate(-1,80,1,59).
+relate(-1,110,1,59).
+relate(-1,16,1,61).
+relate(-1,80,1,61).
+relate(-1,82,1,61).
+relate(-1,20,1,63).
+relate(-1,82,1,63).
+relate(-1,84,1,63).
+relate(-1,24,1,65).
+relate(-1,84,1,65).
+relate(-1,86,1,65).
+relate(-1,28,1,67).
+relate(-1,86,1,67).
+relate(-1,88,1,67).
+relate(-1,32,1,69).
+relate(-1,88,1,69).
+relate(-1,90,1,69).
+relate(-1,36,1,71).
+relate(-1,90,1,71).
+relate(-1,92,1,71).
+relate(-1,40,1,73).
+relate(-1,92,1,73).
+relate(-1,94,1,73).
+relate(-1,42,1,75).
+relate(-1,94,1,75).
+relate(-1,2,1,77).
+relate(-1,76,1,77).
+relate(-1,2,1,79).
+relate(-1,6,1,79).
+relate(-1,76,1,79).
+relate(-1,78,1,79).
+relate(-1,6,1,81).
+relate(-1,44,1,81).
+relate(-1,78,1,81).
+relate(-1,96,1,81).
+relate(-1,44,1,83).
+relate(-1,48,1,83).
+relate(-1,96,1,83).
+relate(-1,98,1,83).
+relate(-1,48,1,85).
+relate(-1,52,1,85).
+relate(-1,98,1,85).
+relate(-1,100,1,85).
+relate(-1,52,1,87).
+relate(-1,56,1,87).
+relate(-1,100,1,87).
+relate(-1,102,1,87).
+relate(-1,56,1,89).
+relate(-1,60,1,89).
+relate(-1,102,1,89).
+relate(-1,104,1,89).
+relate(-1,60,1,91).
+relate(-1,64,1,91).
+relate(-1,104,1,91).
+relate(-1,106,1,91).
+relate(-1,64,1,93).
+relate(-1,68,1,93).
+relate(-1,106,1,93).
+relate(-1,108,1,93).
+relate(-1,68,1,95).
+relate(-1,72,1,95).
+relate(-1,108,1,95).
+relate(-1,110,1,95).
+relate(-1,10,1,97).
+relate(-1,72,1,97).
+relate(-1,80,1,97).
+relate(-1,110,1,97).
+relate(-1,10,1,99).
+relate(-1,14,1,99).
+relate(-1,80,1,99).
+relate(-1,82,1,99).
+relate(-1,14,1,101).
+relate(-1,18,1,101).
+relate(-1,82,1,101).
+relate(-1,84,1,101).
+relate(-1,18,1,103).
+relate(-1,22,1,103).
+relate(-1,84,1,103).
+relate(-1,86,1,103).
+relate(-1,22,1,105).
+relate(-1,26,1,105).
+relate(-1,86,1,105).
+relate(-1,88,1,105).
+relate(-1,26,1,107).
+relate(-1,30,1,107).
+relate(-1,88,1,107).
+relate(-1,90,1,107).
+relate(-1,30,1,109).
+relate(-1,34,1,109).
+relate(-1,90,1,109).
+relate(-1,92,1,109).
+relate(-1,34,1,111).
+relate(-1,38,1,111).
+relate(-1,92,1,111).
+relate(-1,94,1,111).
+relate(-1,38,1,112).
+relate(-1,94,1,112).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/196-partner_units_polynomial-59-0.lp b/examples/clingo/expansion/PartnerUnits/instances/196-partner_units_polynomial-59-0.lp
new file mode 100644
index 0000000..66a682b
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/196-partner_units_polynomial-59-0.lp
@@ -0,0 +1,412 @@
+maxPU(2).
+#const n=109.
+object(1,1).
+object(-1,2).
+object(1,3).
+object(-1,4).
+object(1,5).
+object(-1,6).
+object(1,7).
+object(-1,8).
+object(1,9).
+object(-1,10).
+object(1,11).
+object(-1,12).
+object(1,13).
+object(-1,14).
+object(1,15).
+object(-1,16).
+object(1,17).
+object(-1,18).
+object(1,19).
+object(-1,20).
+object(1,21).
+object(-1,22).
+object(1,23).
+object(-1,24).
+object(1,25).
+object(-1,26).
+object(1,27).
+object(-1,28).
+object(1,29).
+object(-1,30).
+object(1,31).
+object(-1,32).
+object(1,33).
+object(-1,34).
+object(1,35).
+object(-1,36).
+object(1,37).
+object(-1,38).
+object(1,39).
+object(-1,40).
+object(1,41).
+object(-1,42).
+object(1,43).
+object(-1,44).
+object(1,45).
+object(-1,46).
+object(1,47).
+object(-1,48).
+object(1,49).
+object(-1,50).
+object(1,51).
+object(-1,52).
+object(1,53).
+object(-1,54).
+object(1,55).
+object(-1,56).
+object(1,57).
+object(-1,58).
+object(1,59).
+object(-1,60).
+object(1,61).
+object(-1,62).
+object(1,63).
+object(-1,64).
+object(1,65).
+object(-1,66).
+object(1,67).
+object(-1,68).
+object(1,69).
+object(-1,70).
+object(1,71).
+object(-1,72).
+object(1,73).
+object(-1,74).
+object(1,75).
+object(-1,76).
+object(1,77).
+object(-1,78).
+object(1,79).
+object(-1,80).
+object(1,81).
+object(-1,82).
+object(1,83).
+object(-1,84).
+object(1,85).
+object(-1,86).
+object(1,87).
+object(-1,88).
+object(1,89).
+object(-1,90).
+object(1,91).
+object(-1,92).
+object(1,93).
+object(-1,94).
+object(1,95).
+object(-1,96).
+object(1,97).
+object(-1,98).
+object(1,99).
+object(-1,100).
+object(1,101).
+object(1,102).
+object(1,103).
+object(1,104).
+object(1,105).
+object(1,106).
+object(1,107).
+object(1,108).
+object(1,109).
+follow(1,1,1,3).
+follow(1,3,1,5).
+follow(1,5,1,7).
+follow(1,7,1,9).
+follow(1,9,1,11).
+follow(1,11,1,13).
+follow(1,13,1,15).
+follow(1,15,1,17).
+follow(1,17,1,19).
+follow(1,19,1,21).
+follow(1,21,1,23).
+follow(1,23,1,25).
+follow(1,25,1,27).
+follow(1,27,1,29).
+follow(1,29,1,31).
+follow(1,31,1,33).
+follow(1,33,1,35).
+follow(1,35,1,37).
+follow(1,37,1,39).
+follow(1,39,1,41).
+follow(1,41,1,43).
+follow(1,43,1,45).
+follow(1,45,1,47).
+follow(1,47,1,49).
+follow(1,49,1,51).
+follow(1,51,1,53).
+follow(1,53,1,55).
+follow(1,55,1,57).
+follow(1,57,1,59).
+follow(1,59,1,61).
+follow(1,61,1,63).
+follow(1,63,1,65).
+follow(1,65,1,67).
+follow(1,67,1,69).
+follow(1,69,1,71).
+follow(1,71,1,73).
+follow(1,73,1,75).
+follow(1,75,1,77).
+follow(1,77,1,79).
+follow(1,79,1,81).
+follow(1,81,1,83).
+follow(1,83,1,85).
+follow(1,85,1,87).
+follow(1,87,1,89).
+follow(1,89,1,91).
+follow(1,91,1,93).
+follow(1,93,1,95).
+follow(1,95,1,97).
+follow(1,97,1,99).
+follow(1,99,1,101).
+follow(1,101,1,102).
+follow(1,102,1,103).
+follow(1,103,1,104).
+follow(1,104,1,105).
+follow(1,105,1,106).
+follow(1,106,1,107).
+follow(1,107,1,108).
+follow(1,108,1,109).
+follow(-1,38,-1,40).
+follow(-1,84,-1,86).
+follow(-1,62,-1,64).
+follow(-1,90,-1,92).
+follow(-1,6,-1,8).
+follow(-1,78,-1,80).
+follow(-1,70,-1,72).
+follow(-1,36,-1,38).
+follow(-1,92,-1,94).
+follow(-1,64,-1,66).
+follow(-1,20,-1,22).
+follow(-1,68,-1,70).
+follow(-1,40,-1,42).
+follow(-1,96,-1,98).
+follow(-1,54,-1,56).
+follow(-1,76,-1,78).
+follow(-1,44,-1,46).
+follow(-1,32,-1,34).
+follow(-1,4,-1,6).
+follow(-1,24,-1,26).
+follow(-1,10,-1,12).
+follow(-1,30,-1,32).
+follow(-1,28,-1,30).
+follow(-1,82,-1,84).
+follow(-1,74,-1,76).
+follow(-1,18,-1,20).
+follow(-1,16,-1,18).
+follow(-1,8,-1,10).
+follow(-1,50,-1,52).
+follow(-1,56,-1,58).
+follow(-1,34,-1,36).
+follow(-1,66,-1,68).
+follow(-1,86,-1,88).
+follow(-1,94,-1,96).
+follow(-1,12,-1,14).
+follow(-1,26,-1,28).
+follow(-1,22,-1,24).
+follow(-1,60,-1,62).
+follow(-1,58,-1,60).
+follow(-1,72,-1,74).
+follow(-1,98,-1,100).
+follow(-1,14,-1,16).
+follow(-1,88,-1,90).
+follow(-1,48,-1,50).
+follow(-1,46,-1,48).
+follow(-1,42,-1,44).
+follow(-1,52,-1,54).
+follow(-1,80,-1,82).
+follow(-1,2,-1,4).
+relate(1,1,-1,40).
+relate(1,1,-1,86).
+relate(1,3,-1,40).
+relate(1,3,-1,64).
+relate(1,5,-1,92).
+relate(1,7,-1,92).
+relate(1,9,-1,86).
+relate(1,9,-1,8).
+relate(1,11,-1,64).
+relate(1,11,-1,8).
+relate(1,11,-1,80).
+relate(1,13,-1,72).
+relate(1,15,-1,38).
+relate(1,17,-1,38).
+relate(1,17,-1,94).
+relate(1,19,-1,94).
+relate(1,19,-1,66).
+relate(1,19,-1,22).
+relate(1,21,-1,66).
+relate(1,23,-1,70).
+relate(1,25,-1,42).
+relate(1,27,-1,80).
+relate(1,29,-1,72).
+relate(1,31,-1,98).
+relate(1,33,-1,98).
+relate(1,33,-1,56).
+relate(1,35,-1,22).
+relate(1,35,-1,78).
+relate(1,37,-1,46).
+relate(1,39,-1,70).
+relate(1,39,-1,46).
+relate(1,41,-1,42).
+relate(1,43,-1,34).
+relate(1,45,-1,56).
+relate(1,47,-1,78).
+relate(1,49,-1,6).
+relate(1,51,-1,26).
+relate(1,51,-1,12).
+relate(1,53,-1,34).
+relate(1,53,-1,26).
+relate(1,53,-1,32).
+relate(1,53,-1,30).
+relate(1,55,-1,32).
+relate(1,57,-1,84).
+relate(1,59,-1,76).
+relate(1,59,-1,20).
+relate(1,61,-1,76).
+relate(1,63,-1,18).
+relate(1,65,-1,12).
+relate(1,65,-1,18).
+relate(1,65,-1,10).
+relate(1,67,-1,30).
+relate(1,67,-1,10).
+relate(1,69,-1,52).
+relate(1,71,-1,84).
+relate(1,71,-1,58).
+relate(1,73,-1,20).
+relate(1,73,-1,58).
+relate(1,73,-1,36).
+relate(1,75,-1,52).
+relate(1,77,-1,68).
+relate(1,77,-1,88).
+relate(1,79,-1,36).
+relate(1,79,-1,68).
+relate(1,79,-1,96).
+relate(1,79,-1,14).
+relate(1,81,-1,96).
+relate(1,83,-1,28).
+relate(1,85,-1,28).
+relate(1,85,-1,24).
+relate(1,87,-1,62).
+relate(1,89,-1,88).
+relate(1,89,-1,60).
+relate(1,89,-1,74).
+relate(1,91,-1,14).
+relate(1,91,-1,60).
+relate(1,91,-1,100).
+relate(1,93,-1,16).
+relate(1,93,-1,90).
+relate(1,95,-1,16).
+relate(1,97,-1,24).
+relate(1,97,-1,50).
+relate(1,99,-1,50).
+relate(1,101,-1,62).
+relate(1,101,-1,48).
+relate(1,102,-1,74).
+relate(1,103,-1,100).
+relate(1,103,-1,44).
+relate(1,104,-1,44).
+relate(1,104,-1,54).
+relate(1,105,-1,90).
+relate(1,106,-1,82).
+relate(1,107,-1,82).
+relate(1,107,-1,2).
+relate(1,108,-1,48).
+relate(1,109,-1,54).
+relate(1,109,-1,4).
+relate(-1,40,1,1).
+relate(-1,86,1,1).
+relate(-1,40,1,3).
+relate(-1,64,1,3).
+relate(-1,92,1,5).
+relate(-1,92,1,7).
+relate(-1,86,1,9).
+relate(-1,8,1,9).
+relate(-1,64,1,11).
+relate(-1,8,1,11).
+relate(-1,80,1,11).
+relate(-1,72,1,13).
+relate(-1,38,1,15).
+relate(-1,38,1,17).
+relate(-1,94,1,17).
+relate(-1,94,1,19).
+relate(-1,66,1,19).
+relate(-1,22,1,19).
+relate(-1,66,1,21).
+relate(-1,70,1,23).
+relate(-1,42,1,25).
+relate(-1,80,1,27).
+relate(-1,72,1,29).
+relate(-1,98,1,31).
+relate(-1,98,1,33).
+relate(-1,56,1,33).
+relate(-1,22,1,35).
+relate(-1,78,1,35).
+relate(-1,46,1,37).
+relate(-1,70,1,39).
+relate(-1,46,1,39).
+relate(-1,42,1,41).
+relate(-1,34,1,43).
+relate(-1,56,1,45).
+relate(-1,78,1,47).
+relate(-1,6,1,49).
+relate(-1,26,1,51).
+relate(-1,12,1,51).
+relate(-1,34,1,53).
+relate(-1,26,1,53).
+relate(-1,32,1,53).
+relate(-1,30,1,53).
+relate(-1,32,1,55).
+relate(-1,84,1,57).
+relate(-1,76,1,59).
+relate(-1,20,1,59).
+relate(-1,76,1,61).
+relate(-1,18,1,63).
+relate(-1,12,1,65).
+relate(-1,18,1,65).
+relate(-1,10,1,65).
+relate(-1,30,1,67).
+relate(-1,10,1,67).
+relate(-1,52,1,69).
+relate(-1,84,1,71).
+relate(-1,58,1,71).
+relate(-1,20,1,73).
+relate(-1,58,1,73).
+relate(-1,36,1,73).
+relate(-1,52,1,75).
+relate(-1,68,1,77).
+relate(-1,88,1,77).
+relate(-1,36,1,79).
+relate(-1,68,1,79).
+relate(-1,96,1,79).
+relate(-1,14,1,79).
+relate(-1,96,1,81).
+relate(-1,28,1,83).
+relate(-1,28,1,85).
+relate(-1,24,1,85).
+relate(-1,62,1,87).
+relate(-1,88,1,89).
+relate(-1,60,1,89).
+relate(-1,74,1,89).
+relate(-1,14,1,91).
+relate(-1,60,1,91).
+relate(-1,100,1,91).
+relate(-1,16,1,93).
+relate(-1,90,1,93).
+relate(-1,16,1,95).
+relate(-1,24,1,97).
+relate(-1,50,1,97).
+relate(-1,50,1,99).
+relate(-1,62,1,101).
+relate(-1,48,1,101).
+relate(-1,74,1,102).
+relate(-1,100,1,103).
+relate(-1,44,1,103).
+relate(-1,44,1,104).
+relate(-1,54,1,104).
+relate(-1,90,1,105).
+relate(-1,82,1,106).
+relate(-1,82,1,107).
+relate(-1,2,1,107).
+relate(-1,48,1,108).
+relate(-1,54,1,109).
+relate(-1,4,1,109).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/26-partner_units_polynomial-60-0.lp b/examples/clingo/expansion/PartnerUnits/instances/26-partner_units_polynomial-60-0.lp
new file mode 100644
index 0000000..07cbc7b
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/26-partner_units_polynomial-60-0.lp
@@ -0,0 +1,620 @@
+maxPU(2).
+#const n=118.
+object(1,1).
+object(-1,2).
+object(1,3).
+object(-1,4).
+object(1,5).
+object(-1,6).
+object(1,7).
+object(-1,8).
+object(1,9).
+object(-1,10).
+object(1,11).
+object(-1,12).
+object(1,13).
+object(-1,14).
+object(1,15).
+object(-1,16).
+object(1,17).
+object(-1,18).
+object(1,19).
+object(-1,20).
+object(1,21).
+object(-1,22).
+object(1,23).
+object(-1,24).
+object(1,25).
+object(-1,26).
+object(1,27).
+object(-1,28).
+object(1,29).
+object(-1,30).
+object(1,31).
+object(-1,32).
+object(1,33).
+object(-1,34).
+object(1,35).
+object(-1,36).
+object(1,37).
+object(-1,38).
+object(1,39).
+object(-1,40).
+object(1,41).
+object(-1,42).
+object(1,43).
+object(-1,44).
+object(1,45).
+object(-1,46).
+object(1,47).
+object(-1,48).
+object(1,49).
+object(-1,50).
+object(1,51).
+object(-1,52).
+object(1,53).
+object(-1,54).
+object(1,55).
+object(-1,56).
+object(1,57).
+object(-1,58).
+object(1,59).
+object(-1,60).
+object(1,61).
+object(-1,62).
+object(1,63).
+object(-1,64).
+object(1,65).
+object(-1,66).
+object(1,67).
+object(-1,68).
+object(1,69).
+object(-1,70).
+object(1,71).
+object(-1,72).
+object(1,73).
+object(-1,74).
+object(1,75).
+object(-1,76).
+object(1,77).
+object(-1,78).
+object(1,79).
+object(-1,80).
+object(1,81).
+object(-1,82).
+object(1,83).
+object(-1,84).
+object(1,85).
+object(-1,86).
+object(1,87).
+object(-1,88).
+object(1,89).
+object(-1,90).
+object(1,91).
+object(-1,92).
+object(1,93).
+object(-1,94).
+object(1,95).
+object(-1,96).
+object(1,97).
+object(-1,98).
+object(1,99).
+object(-1,100).
+object(1,101).
+object(-1,102).
+object(1,103).
+object(-1,104).
+object(1,105).
+object(-1,106).
+object(1,107).
+object(-1,108).
+object(1,109).
+object(-1,110).
+object(1,111).
+object(-1,112).
+object(1,113).
+object(-1,114).
+object(1,115).
+object(-1,116).
+object(1,117).
+object(1,118).
+follow(1,1,1,3).
+follow(1,3,1,5).
+follow(1,5,1,7).
+follow(1,7,1,9).
+follow(1,9,1,11).
+follow(1,11,1,13).
+follow(1,13,1,15).
+follow(1,15,1,17).
+follow(1,17,1,19).
+follow(1,19,1,21).
+follow(1,21,1,23).
+follow(1,23,1,25).
+follow(1,25,1,27).
+follow(1,27,1,29).
+follow(1,29,1,31).
+follow(1,31,1,33).
+follow(1,33,1,35).
+follow(1,35,1,37).
+follow(1,37,1,39).
+follow(1,39,1,41).
+follow(1,41,1,43).
+follow(1,43,1,45).
+follow(1,45,1,47).
+follow(1,47,1,49).
+follow(1,49,1,51).
+follow(1,51,1,53).
+follow(1,53,1,55).
+follow(1,55,1,57).
+follow(1,57,1,59).
+follow(1,59,1,61).
+follow(1,61,1,63).
+follow(1,63,1,65).
+follow(1,65,1,67).
+follow(1,67,1,69).
+follow(1,69,1,71).
+follow(1,71,1,73).
+follow(1,73,1,75).
+follow(1,75,1,77).
+follow(1,77,1,79).
+follow(1,79,1,81).
+follow(1,81,1,83).
+follow(1,83,1,85).
+follow(1,85,1,87).
+follow(1,87,1,89).
+follow(1,89,1,91).
+follow(1,91,1,93).
+follow(1,93,1,95).
+follow(1,95,1,97).
+follow(1,97,1,99).
+follow(1,99,1,101).
+follow(1,101,1,103).
+follow(1,103,1,105).
+follow(1,105,1,107).
+follow(1,107,1,109).
+follow(1,109,1,111).
+follow(1,111,1,113).
+follow(1,113,1,115).
+follow(1,115,1,117).
+follow(1,117,1,118).
+follow(-1,2,-1,4).
+follow(-1,4,-1,6).
+follow(-1,6,-1,8).
+follow(-1,46,-1,48).
+follow(-1,48,-1,50).
+follow(-1,50,-1,52).
+follow(-1,52,-1,54).
+follow(-1,54,-1,56).
+follow(-1,56,-1,58).
+follow(-1,58,-1,60).
+follow(-1,60,-1,62).
+follow(-1,62,-1,64).
+follow(-1,64,-1,66).
+follow(-1,66,-1,68).
+follow(-1,68,-1,70).
+follow(-1,70,-1,72).
+follow(-1,72,-1,74).
+follow(-1,74,-1,76).
+follow(-1,76,-1,78).
+follow(-1,8,-1,10).
+follow(-1,10,-1,12).
+follow(-1,12,-1,14).
+follow(-1,14,-1,16).
+follow(-1,16,-1,18).
+follow(-1,18,-1,20).
+follow(-1,20,-1,22).
+follow(-1,22,-1,24).
+follow(-1,24,-1,26).
+follow(-1,26,-1,28).
+follow(-1,28,-1,30).
+follow(-1,30,-1,32).
+follow(-1,32,-1,34).
+follow(-1,34,-1,36).
+follow(-1,36,-1,38).
+follow(-1,38,-1,40).
+follow(-1,40,-1,42).
+follow(-1,42,-1,44).
+follow(-1,44,-1,46).
+follow(-1,78,-1,80).
+follow(-1,80,-1,82).
+follow(-1,100,-1,102).
+follow(-1,102,-1,104).
+follow(-1,104,-1,106).
+follow(-1,106,-1,108).
+follow(-1,108,-1,110).
+follow(-1,110,-1,112).
+follow(-1,112,-1,114).
+follow(-1,114,-1,116).
+follow(-1,82,-1,84).
+follow(-1,84,-1,86).
+follow(-1,86,-1,88).
+follow(-1,88,-1,90).
+follow(-1,90,-1,92).
+follow(-1,92,-1,94).
+follow(-1,94,-1,96).
+follow(-1,96,-1,98).
+follow(-1,98,-1,100).
+relate(1,1,-1,2).
+relate(1,1,-1,4).
+relate(1,3,-1,2).
+relate(1,3,-1,6).
+relate(1,3,-1,8).
+relate(1,5,-1,6).
+relate(1,5,-1,48).
+relate(1,5,-1,50).
+relate(1,7,-1,48).
+relate(1,7,-1,52).
+relate(1,7,-1,54).
+relate(1,9,-1,52).
+relate(1,9,-1,56).
+relate(1,9,-1,58).
+relate(1,11,-1,56).
+relate(1,11,-1,60).
+relate(1,11,-1,62).
+relate(1,13,-1,60).
+relate(1,13,-1,64).
+relate(1,13,-1,66).
+relate(1,15,-1,64).
+relate(1,15,-1,68).
+relate(1,15,-1,70).
+relate(1,17,-1,68).
+relate(1,17,-1,72).
+relate(1,17,-1,74).
+relate(1,19,-1,72).
+relate(1,19,-1,76).
+relate(1,19,-1,78).
+relate(1,21,-1,10).
+relate(1,21,-1,12).
+relate(1,21,-1,76).
+relate(1,23,-1,10).
+relate(1,23,-1,14).
+relate(1,23,-1,16).
+relate(1,25,-1,14).
+relate(1,25,-1,18).
+relate(1,25,-1,20).
+relate(1,27,-1,18).
+relate(1,27,-1,22).
+relate(1,27,-1,24).
+relate(1,29,-1,22).
+relate(1,29,-1,26).
+relate(1,29,-1,28).
+relate(1,31,-1,26).
+relate(1,31,-1,30).
+relate(1,31,-1,32).
+relate(1,33,-1,30).
+relate(1,33,-1,34).
+relate(1,33,-1,36).
+relate(1,35,-1,34).
+relate(1,35,-1,38).
+relate(1,35,-1,40).
+relate(1,37,-1,38).
+relate(1,37,-1,42).
+relate(1,37,-1,44).
+relate(1,39,-1,42).
+relate(1,39,-1,46).
+relate(1,41,-1,4).
+relate(1,41,-1,80).
+relate(1,43,-1,8).
+relate(1,43,-1,80).
+relate(1,43,-1,82).
+relate(1,45,-1,50).
+relate(1,45,-1,82).
+relate(1,45,-1,102).
+relate(1,47,-1,54).
+relate(1,47,-1,102).
+relate(1,47,-1,104).
+relate(1,49,-1,58).
+relate(1,49,-1,104).
+relate(1,49,-1,106).
+relate(1,51,-1,62).
+relate(1,51,-1,106).
+relate(1,51,-1,108).
+relate(1,53,-1,66).
+relate(1,53,-1,108).
+relate(1,53,-1,110).
+relate(1,55,-1,70).
+relate(1,55,-1,110).
+relate(1,55,-1,112).
+relate(1,57,-1,74).
+relate(1,57,-1,112).
+relate(1,57,-1,114).
+relate(1,59,-1,78).
+relate(1,59,-1,114).
+relate(1,59,-1,116).
+relate(1,61,-1,12).
+relate(1,61,-1,84).
+relate(1,61,-1,116).
+relate(1,63,-1,16).
+relate(1,63,-1,84).
+relate(1,63,-1,86).
+relate(1,65,-1,20).
+relate(1,65,-1,86).
+relate(1,65,-1,88).
+relate(1,67,-1,24).
+relate(1,67,-1,88).
+relate(1,67,-1,90).
+relate(1,69,-1,28).
+relate(1,69,-1,90).
+relate(1,69,-1,92).
+relate(1,71,-1,32).
+relate(1,71,-1,92).
+relate(1,71,-1,94).
+relate(1,73,-1,36).
+relate(1,73,-1,94).
+relate(1,73,-1,96).
+relate(1,75,-1,40).
+relate(1,75,-1,96).
+relate(1,75,-1,98).
+relate(1,77,-1,44).
+relate(1,77,-1,98).
+relate(1,77,-1,100).
+relate(1,79,-1,46).
+relate(1,79,-1,100).
+relate(1,81,-1,2).
+relate(1,81,-1,80).
+relate(1,83,-1,2).
+relate(1,83,-1,6).
+relate(1,83,-1,80).
+relate(1,83,-1,82).
+relate(1,85,-1,6).
+relate(1,85,-1,48).
+relate(1,85,-1,82).
+relate(1,85,-1,102).
+relate(1,87,-1,48).
+relate(1,87,-1,52).
+relate(1,87,-1,102).
+relate(1,87,-1,104).
+relate(1,89,-1,52).
+relate(1,89,-1,56).
+relate(1,89,-1,104).
+relate(1,89,-1,106).
+relate(1,91,-1,56).
+relate(1,91,-1,60).
+relate(1,91,-1,106).
+relate(1,91,-1,108).
+relate(1,93,-1,60).
+relate(1,93,-1,64).
+relate(1,93,-1,108).
+relate(1,93,-1,110).
+relate(1,95,-1,64).
+relate(1,95,-1,68).
+relate(1,95,-1,110).
+relate(1,95,-1,112).
+relate(1,97,-1,68).
+relate(1,97,-1,72).
+relate(1,97,-1,112).
+relate(1,97,-1,114).
+relate(1,99,-1,72).
+relate(1,99,-1,76).
+relate(1,99,-1,114).
+relate(1,99,-1,116).
+relate(1,101,-1,10).
+relate(1,101,-1,76).
+relate(1,101,-1,84).
+relate(1,101,-1,116).
+relate(1,103,-1,10).
+relate(1,103,-1,14).
+relate(1,103,-1,84).
+relate(1,103,-1,86).
+relate(1,105,-1,14).
+relate(1,105,-1,18).
+relate(1,105,-1,86).
+relate(1,105,-1,88).
+relate(1,107,-1,18).
+relate(1,107,-1,22).
+relate(1,107,-1,88).
+relate(1,107,-1,90).
+relate(1,109,-1,22).
+relate(1,109,-1,26).
+relate(1,109,-1,90).
+relate(1,109,-1,92).
+relate(1,111,-1,26).
+relate(1,111,-1,30).
+relate(1,111,-1,92).
+relate(1,111,-1,94).
+relate(1,113,-1,30).
+relate(1,113,-1,34).
+relate(1,113,-1,94).
+relate(1,113,-1,96).
+relate(1,115,-1,34).
+relate(1,115,-1,38).
+relate(1,115,-1,96).
+relate(1,115,-1,98).
+relate(1,117,-1,38).
+relate(1,117,-1,42).
+relate(1,117,-1,98).
+relate(1,117,-1,100).
+relate(1,118,-1,42).
+relate(1,118,-1,100).
+relate(-1,2,1,1).
+relate(-1,4,1,1).
+relate(-1,2,1,3).
+relate(-1,6,1,3).
+relate(-1,8,1,3).
+relate(-1,6,1,5).
+relate(-1,48,1,5).
+relate(-1,50,1,5).
+relate(-1,48,1,7).
+relate(-1,52,1,7).
+relate(-1,54,1,7).
+relate(-1,52,1,9).
+relate(-1,56,1,9).
+relate(-1,58,1,9).
+relate(-1,56,1,11).
+relate(-1,60,1,11).
+relate(-1,62,1,11).
+relate(-1,60,1,13).
+relate(-1,64,1,13).
+relate(-1,66,1,13).
+relate(-1,64,1,15).
+relate(-1,68,1,15).
+relate(-1,70,1,15).
+relate(-1,68,1,17).
+relate(-1,72,1,17).
+relate(-1,74,1,17).
+relate(-1,72,1,19).
+relate(-1,76,1,19).
+relate(-1,78,1,19).
+relate(-1,10,1,21).
+relate(-1,12,1,21).
+relate(-1,76,1,21).
+relate(-1,10,1,23).
+relate(-1,14,1,23).
+relate(-1,16,1,23).
+relate(-1,14,1,25).
+relate(-1,18,1,25).
+relate(-1,20,1,25).
+relate(-1,18,1,27).
+relate(-1,22,1,27).
+relate(-1,24,1,27).
+relate(-1,22,1,29).
+relate(-1,26,1,29).
+relate(-1,28,1,29).
+relate(-1,26,1,31).
+relate(-1,30,1,31).
+relate(-1,32,1,31).
+relate(-1,30,1,33).
+relate(-1,34,1,33).
+relate(-1,36,1,33).
+relate(-1,34,1,35).
+relate(-1,38,1,35).
+relate(-1,40,1,35).
+relate(-1,38,1,37).
+relate(-1,42,1,37).
+relate(-1,44,1,37).
+relate(-1,42,1,39).
+relate(-1,46,1,39).
+relate(-1,4,1,41).
+relate(-1,80,1,41).
+relate(-1,8,1,43).
+relate(-1,80,1,43).
+relate(-1,82,1,43).
+relate(-1,50,1,45).
+relate(-1,82,1,45).
+relate(-1,102,1,45).
+relate(-1,54,1,47).
+relate(-1,102,1,47).
+relate(-1,104,1,47).
+relate(-1,58,1,49).
+relate(-1,104,1,49).
+relate(-1,106,1,49).
+relate(-1,62,1,51).
+relate(-1,106,1,51).
+relate(-1,108,1,51).
+relate(-1,66,1,53).
+relate(-1,108,1,53).
+relate(-1,110,1,53).
+relate(-1,70,1,55).
+relate(-1,110,1,55).
+relate(-1,112,1,55).
+relate(-1,74,1,57).
+relate(-1,112,1,57).
+relate(-1,114,1,57).
+relate(-1,78,1,59).
+relate(-1,114,1,59).
+relate(-1,116,1,59).
+relate(-1,12,1,61).
+relate(-1,84,1,61).
+relate(-1,116,1,61).
+relate(-1,16,1,63).
+relate(-1,84,1,63).
+relate(-1,86,1,63).
+relate(-1,20,1,65).
+relate(-1,86,1,65).
+relate(-1,88,1,65).
+relate(-1,24,1,67).
+relate(-1,88,1,67).
+relate(-1,90,1,67).
+relate(-1,28,1,69).
+relate(-1,90,1,69).
+relate(-1,92,1,69).
+relate(-1,32,1,71).
+relate(-1,92,1,71).
+relate(-1,94,1,71).
+relate(-1,36,1,73).
+relate(-1,94,1,73).
+relate(-1,96,1,73).
+relate(-1,40,1,75).
+relate(-1,96,1,75).
+relate(-1,98,1,75).
+relate(-1,44,1,77).
+relate(-1,98,1,77).
+relate(-1,100,1,77).
+relate(-1,46,1,79).
+relate(-1,100,1,79).
+relate(-1,2,1,81).
+relate(-1,80,1,81).
+relate(-1,2,1,83).
+relate(-1,6,1,83).
+relate(-1,80,1,83).
+relate(-1,82,1,83).
+relate(-1,6,1,85).
+relate(-1,48,1,85).
+relate(-1,82,1,85).
+relate(-1,102,1,85).
+relate(-1,48,1,87).
+relate(-1,52,1,87).
+relate(-1,102,1,87).
+relate(-1,104,1,87).
+relate(-1,52,1,89).
+relate(-1,56,1,89).
+relate(-1,104,1,89).
+relate(-1,106,1,89).
+relate(-1,56,1,91).
+relate(-1,60,1,91).
+relate(-1,106,1,91).
+relate(-1,108,1,91).
+relate(-1,60,1,93).
+relate(-1,64,1,93).
+relate(-1,108,1,93).
+relate(-1,110,1,93).
+relate(-1,64,1,95).
+relate(-1,68,1,95).
+relate(-1,110,1,95).
+relate(-1,112,1,95).
+relate(-1,68,1,97).
+relate(-1,72,1,97).
+relate(-1,112,1,97).
+relate(-1,114,1,97).
+relate(-1,72,1,99).
+relate(-1,76,1,99).
+relate(-1,114,1,99).
+relate(-1,116,1,99).
+relate(-1,10,1,101).
+relate(-1,76,1,101).
+relate(-1,84,1,101).
+relate(-1,116,1,101).
+relate(-1,10,1,103).
+relate(-1,14,1,103).
+relate(-1,84,1,103).
+relate(-1,86,1,103).
+relate(-1,14,1,105).
+relate(-1,18,1,105).
+relate(-1,86,1,105).
+relate(-1,88,1,105).
+relate(-1,18,1,107).
+relate(-1,22,1,107).
+relate(-1,88,1,107).
+relate(-1,90,1,107).
+relate(-1,22,1,109).
+relate(-1,26,1,109).
+relate(-1,90,1,109).
+relate(-1,92,1,109).
+relate(-1,26,1,111).
+relate(-1,30,1,111).
+relate(-1,92,1,111).
+relate(-1,94,1,111).
+relate(-1,30,1,113).
+relate(-1,34,1,113).
+relate(-1,94,1,113).
+relate(-1,96,1,113).
+relate(-1,34,1,115).
+relate(-1,38,1,115).
+relate(-1,96,1,115).
+relate(-1,98,1,115).
+relate(-1,38,1,117).
+relate(-1,42,1,117).
+relate(-1,98,1,117).
+relate(-1,100,1,117).
+relate(-1,42,1,118).
+relate(-1,100,1,118).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/52-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/52-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..0f9c2c9
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/52-partner_units_polynomial-100-0.lp
@@ -0,0 +1,744 @@
+maxPU(2).
+#const n=178.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(-1,75,-1,77).
+follow(-1,3,-1,5).
+follow(-1,61,-1,63).
+follow(-1,157,-1,158).
+follow(-1,171,-1,172).
+follow(-1,158,-1,159).
+follow(-1,151,-1,153).
+follow(-1,5,-1,7).
+follow(-1,155,-1,157).
+follow(-1,115,-1,117).
+follow(-1,1,-1,3).
+follow(-1,15,-1,17).
+follow(-1,39,-1,41).
+follow(-1,113,-1,115).
+follow(-1,47,-1,49).
+follow(-1,77,-1,79).
+follow(-1,168,-1,169).
+follow(-1,93,-1,95).
+follow(-1,91,-1,93).
+follow(-1,45,-1,47).
+follow(-1,143,-1,145).
+follow(-1,177,-1,178).
+follow(-1,49,-1,51).
+follow(-1,35,-1,37).
+follow(-1,164,-1,165).
+follow(-1,173,-1,174).
+follow(-1,133,-1,135).
+follow(-1,29,-1,31).
+follow(-1,119,-1,121).
+follow(-1,57,-1,59).
+follow(-1,159,-1,160).
+follow(-1,163,-1,164).
+follow(-1,109,-1,111).
+follow(-1,67,-1,69).
+follow(-1,166,-1,167).
+follow(-1,111,-1,113).
+follow(-1,41,-1,43).
+follow(-1,160,-1,161).
+follow(-1,55,-1,57).
+follow(-1,149,-1,151).
+follow(-1,89,-1,91).
+follow(-1,172,-1,173).
+follow(-1,17,-1,19).
+follow(-1,137,-1,139).
+follow(-1,169,-1,170).
+follow(-1,167,-1,168).
+follow(-1,123,-1,125).
+follow(-1,131,-1,133).
+follow(-1,162,-1,163).
+follow(-1,23,-1,25).
+follow(-1,13,-1,15).
+follow(-1,87,-1,89).
+follow(-1,121,-1,123).
+follow(-1,21,-1,23).
+follow(-1,7,-1,9).
+follow(-1,165,-1,166).
+follow(-1,153,-1,155).
+follow(-1,33,-1,35).
+follow(-1,31,-1,33).
+follow(-1,135,-1,137).
+follow(-1,99,-1,101).
+follow(-1,145,-1,147).
+follow(-1,81,-1,83).
+follow(-1,25,-1,27).
+follow(-1,117,-1,119).
+follow(-1,71,-1,73).
+follow(-1,65,-1,67).
+follow(-1,176,-1,177).
+follow(-1,175,-1,176).
+follow(-1,170,-1,171).
+follow(-1,103,-1,105).
+follow(-1,27,-1,29).
+follow(-1,83,-1,85).
+follow(-1,37,-1,39).
+follow(-1,51,-1,53).
+follow(-1,141,-1,143).
+follow(-1,11,-1,13).
+follow(-1,69,-1,71).
+follow(-1,73,-1,75).
+follow(-1,129,-1,131).
+follow(-1,79,-1,81).
+follow(-1,147,-1,149).
+follow(-1,107,-1,109).
+follow(-1,43,-1,45).
+follow(-1,19,-1,21).
+follow(-1,63,-1,65).
+follow(-1,95,-1,97).
+follow(-1,85,-1,87).
+follow(-1,161,-1,162).
+follow(-1,59,-1,61).
+follow(-1,97,-1,99).
+follow(-1,53,-1,55).
+follow(-1,101,-1,103).
+follow(-1,125,-1,127).
+follow(-1,139,-1,141).
+follow(-1,105,-1,107).
+follow(-1,127,-1,129).
+follow(-1,9,-1,11).
+follow(-1,174,-1,175).
+relate(1,2,-1,77).
+relate(1,4,-1,5).
+relate(1,4,-1,63).
+relate(1,6,-1,63).
+relate(1,6,-1,158).
+relate(1,6,-1,172).
+relate(1,8,-1,158).
+relate(1,8,-1,159).
+relate(1,10,-1,153).
+relate(1,12,-1,7).
+relate(1,12,-1,153).
+relate(1,12,-1,157).
+relate(1,12,-1,117).
+relate(1,14,-1,157).
+relate(1,14,-1,3).
+relate(1,16,-1,77).
+relate(1,16,-1,17).
+relate(1,16,-1,41).
+relate(1,18,-1,17).
+relate(1,20,-1,172).
+relate(1,22,-1,159).
+relate(1,22,-1,115).
+relate(1,22,-1,49).
+relate(1,24,-1,115).
+relate(1,24,-1,79).
+relate(1,26,-1,79).
+relate(1,26,-1,169).
+relate(1,26,-1,95).
+relate(1,28,-1,117).
+relate(1,28,-1,169).
+relate(1,28,-1,93).
+relate(1,28,-1,47).
+relate(1,30,-1,93).
+relate(1,30,-1,145).
+relate(1,32,-1,41).
+relate(1,32,-1,178).
+relate(1,32,-1,51).
+relate(1,34,-1,178).
+relate(1,34,-1,37).
+relate(1,34,-1,165).
+relate(1,36,-1,37).
+relate(1,36,-1,174).
+relate(1,36,-1,135).
+relate(1,38,-1,49).
+relate(1,38,-1,174).
+relate(1,38,-1,31).
+relate(1,40,-1,31).
+relate(1,42,-1,95).
+relate(1,42,-1,121).
+relate(1,42,-1,59).
+relate(1,44,-1,47).
+relate(1,44,-1,121).
+relate(1,44,-1,160).
+relate(1,44,-1,164).
+relate(1,46,-1,145).
+relate(1,46,-1,160).
+relate(1,46,-1,111).
+relate(1,48,-1,51).
+relate(1,48,-1,69).
+relate(1,50,-1,165).
+relate(1,50,-1,167).
+relate(1,50,-1,113).
+relate(1,52,-1,135).
+relate(1,52,-1,167).
+relate(1,52,-1,43).
+relate(1,54,-1,43).
+relate(1,54,-1,161).
+relate(1,54,-1,57).
+relate(1,56,-1,161).
+relate(1,56,-1,151).
+relate(1,58,-1,59).
+relate(1,58,-1,91).
+relate(1,58,-1,173).
+relate(1,60,-1,164).
+relate(1,60,-1,91).
+relate(1,60,-1,19).
+relate(1,60,-1,139).
+relate(1,62,-1,111).
+relate(1,62,-1,19).
+relate(1,62,-1,170).
+relate(1,64,-1,69).
+relate(1,64,-1,168).
+relate(1,66,-1,113).
+relate(1,66,-1,125).
+relate(1,68,-1,133).
+relate(1,70,-1,57).
+relate(1,70,-1,163).
+relate(1,72,-1,151).
+relate(1,72,-1,163).
+relate(1,72,-1,25).
+relate(1,72,-1,15).
+relate(1,74,-1,173).
+relate(1,74,-1,25).
+relate(1,74,-1,89).
+relate(1,74,-1,123).
+relate(1,76,-1,139).
+relate(1,76,-1,89).
+relate(1,76,-1,23).
+relate(1,78,-1,170).
+relate(1,78,-1,9).
+relate(1,78,-1,166).
+relate(1,80,-1,168).
+relate(1,80,-1,155).
+relate(1,82,-1,125).
+relate(1,82,-1,35).
+relate(1,84,-1,133).
+relate(1,84,-1,33).
+relate(1,84,-1,137).
+relate(1,86,-1,33).
+relate(1,86,-1,101).
+relate(1,88,-1,15).
+relate(1,88,-1,147).
+relate(1,88,-1,83).
+relate(1,90,-1,123).
+relate(1,90,-1,147).
+relate(1,92,-1,23).
+relate(1,92,-1,27).
+relate(1,94,-1,166).
+relate(1,94,-1,27).
+relate(1,96,-1,155).
+relate(1,96,-1,119).
+relate(1,96,-1,73).
+relate(1,98,-1,35).
+relate(1,98,-1,119).
+relate(1,98,-1,67).
+relate(1,100,-1,137).
+relate(1,100,-1,177).
+relate(1,100,-1,176).
+relate(1,102,-1,101).
+relate(1,102,-1,177).
+relate(1,102,-1,171).
+relate(1,104,-1,83).
+relate(1,104,-1,105).
+relate(1,104,-1,29).
+relate(1,106,-1,105).
+relate(1,108,-1,85).
+relate(1,110,-1,85).
+relate(1,110,-1,39).
+relate(1,112,-1,73).
+relate(1,112,-1,53).
+relate(1,112,-1,143).
+relate(1,114,-1,67).
+relate(1,114,-1,53).
+relate(1,116,-1,176).
+relate(1,116,-1,13).
+relate(1,116,-1,71).
+relate(1,118,-1,171).
+relate(1,118,-1,13).
+relate(1,118,-1,75).
+relate(1,120,-1,29).
+relate(1,120,-1,75).
+relate(1,120,-1,131).
+relate(1,120,-1,81).
+relate(1,122,-1,131).
+relate(1,122,-1,149).
+relate(1,122,-1,109).
+relate(1,124,-1,149).
+relate(1,124,-1,45).
+relate(1,126,-1,39).
+relate(1,126,-1,45).
+relate(1,126,-1,21).
+relate(1,128,-1,143).
+relate(1,128,-1,65).
+relate(1,130,-1,97).
+relate(1,132,-1,71).
+relate(1,132,-1,87).
+relate(1,134,-1,162).
+relate(1,136,-1,81).
+relate(1,136,-1,162).
+relate(1,138,-1,109).
+relate(1,138,-1,61).
+relate(1,138,-1,99).
+relate(1,140,-1,61).
+relate(1,140,-1,55).
+relate(1,140,-1,103).
+relate(1,142,-1,21).
+relate(1,142,-1,55).
+relate(1,144,-1,65).
+relate(1,144,-1,127).
+relate(1,146,-1,97).
+relate(1,146,-1,127).
+relate(1,146,-1,141).
+relate(1,148,-1,87).
+relate(1,148,-1,141).
+relate(1,148,-1,107).
+relate(1,150,-1,107).
+relate(1,150,-1,129).
+relate(1,150,-1,11).
+relate(1,152,-1,129).
+relate(1,152,-1,175).
+relate(1,154,-1,99).
+relate(1,154,-1,175).
+relate(1,156,-1,103).
+relate(1,156,-1,1).
+relate(-1,77,1,2).
+relate(-1,5,1,4).
+relate(-1,63,1,4).
+relate(-1,63,1,6).
+relate(-1,158,1,6).
+relate(-1,172,1,6).
+relate(-1,158,1,8).
+relate(-1,159,1,8).
+relate(-1,153,1,10).
+relate(-1,7,1,12).
+relate(-1,153,1,12).
+relate(-1,157,1,12).
+relate(-1,117,1,12).
+relate(-1,157,1,14).
+relate(-1,3,1,14).
+relate(-1,77,1,16).
+relate(-1,17,1,16).
+relate(-1,41,1,16).
+relate(-1,17,1,18).
+relate(-1,172,1,20).
+relate(-1,159,1,22).
+relate(-1,115,1,22).
+relate(-1,49,1,22).
+relate(-1,115,1,24).
+relate(-1,79,1,24).
+relate(-1,79,1,26).
+relate(-1,169,1,26).
+relate(-1,95,1,26).
+relate(-1,117,1,28).
+relate(-1,169,1,28).
+relate(-1,93,1,28).
+relate(-1,47,1,28).
+relate(-1,93,1,30).
+relate(-1,145,1,30).
+relate(-1,41,1,32).
+relate(-1,178,1,32).
+relate(-1,51,1,32).
+relate(-1,178,1,34).
+relate(-1,37,1,34).
+relate(-1,165,1,34).
+relate(-1,37,1,36).
+relate(-1,174,1,36).
+relate(-1,135,1,36).
+relate(-1,49,1,38).
+relate(-1,174,1,38).
+relate(-1,31,1,38).
+relate(-1,31,1,40).
+relate(-1,95,1,42).
+relate(-1,121,1,42).
+relate(-1,59,1,42).
+relate(-1,47,1,44).
+relate(-1,121,1,44).
+relate(-1,160,1,44).
+relate(-1,164,1,44).
+relate(-1,145,1,46).
+relate(-1,160,1,46).
+relate(-1,111,1,46).
+relate(-1,51,1,48).
+relate(-1,69,1,48).
+relate(-1,165,1,50).
+relate(-1,167,1,50).
+relate(-1,113,1,50).
+relate(-1,135,1,52).
+relate(-1,167,1,52).
+relate(-1,43,1,52).
+relate(-1,43,1,54).
+relate(-1,161,1,54).
+relate(-1,57,1,54).
+relate(-1,161,1,56).
+relate(-1,151,1,56).
+relate(-1,59,1,58).
+relate(-1,91,1,58).
+relate(-1,173,1,58).
+relate(-1,164,1,60).
+relate(-1,91,1,60).
+relate(-1,19,1,60).
+relate(-1,139,1,60).
+relate(-1,111,1,62).
+relate(-1,19,1,62).
+relate(-1,170,1,62).
+relate(-1,69,1,64).
+relate(-1,168,1,64).
+relate(-1,113,1,66).
+relate(-1,125,1,66).
+relate(-1,133,1,68).
+relate(-1,57,1,70).
+relate(-1,163,1,70).
+relate(-1,151,1,72).
+relate(-1,163,1,72).
+relate(-1,25,1,72).
+relate(-1,15,1,72).
+relate(-1,173,1,74).
+relate(-1,25,1,74).
+relate(-1,89,1,74).
+relate(-1,123,1,74).
+relate(-1,139,1,76).
+relate(-1,89,1,76).
+relate(-1,23,1,76).
+relate(-1,170,1,78).
+relate(-1,9,1,78).
+relate(-1,166,1,78).
+relate(-1,168,1,80).
+relate(-1,155,1,80).
+relate(-1,125,1,82).
+relate(-1,35,1,82).
+relate(-1,133,1,84).
+relate(-1,33,1,84).
+relate(-1,137,1,84).
+relate(-1,33,1,86).
+relate(-1,101,1,86).
+relate(-1,15,1,88).
+relate(-1,147,1,88).
+relate(-1,83,1,88).
+relate(-1,123,1,90).
+relate(-1,147,1,90).
+relate(-1,23,1,92).
+relate(-1,27,1,92).
+relate(-1,166,1,94).
+relate(-1,27,1,94).
+relate(-1,155,1,96).
+relate(-1,119,1,96).
+relate(-1,73,1,96).
+relate(-1,35,1,98).
+relate(-1,119,1,98).
+relate(-1,67,1,98).
+relate(-1,137,1,100).
+relate(-1,177,1,100).
+relate(-1,176,1,100).
+relate(-1,101,1,102).
+relate(-1,177,1,102).
+relate(-1,171,1,102).
+relate(-1,83,1,104).
+relate(-1,105,1,104).
+relate(-1,29,1,104).
+relate(-1,105,1,106).
+relate(-1,85,1,108).
+relate(-1,85,1,110).
+relate(-1,39,1,110).
+relate(-1,73,1,112).
+relate(-1,53,1,112).
+relate(-1,143,1,112).
+relate(-1,67,1,114).
+relate(-1,53,1,114).
+relate(-1,176,1,116).
+relate(-1,13,1,116).
+relate(-1,71,1,116).
+relate(-1,171,1,118).
+relate(-1,13,1,118).
+relate(-1,75,1,118).
+relate(-1,29,1,120).
+relate(-1,75,1,120).
+relate(-1,131,1,120).
+relate(-1,81,1,120).
+relate(-1,131,1,122).
+relate(-1,149,1,122).
+relate(-1,109,1,122).
+relate(-1,149,1,124).
+relate(-1,45,1,124).
+relate(-1,39,1,126).
+relate(-1,45,1,126).
+relate(-1,21,1,126).
+relate(-1,143,1,128).
+relate(-1,65,1,128).
+relate(-1,97,1,130).
+relate(-1,71,1,132).
+relate(-1,87,1,132).
+relate(-1,162,1,134).
+relate(-1,81,1,136).
+relate(-1,162,1,136).
+relate(-1,109,1,138).
+relate(-1,61,1,138).
+relate(-1,99,1,138).
+relate(-1,61,1,140).
+relate(-1,55,1,140).
+relate(-1,103,1,140).
+relate(-1,21,1,142).
+relate(-1,55,1,142).
+relate(-1,65,1,144).
+relate(-1,127,1,144).
+relate(-1,97,1,146).
+relate(-1,127,1,146).
+relate(-1,141,1,146).
+relate(-1,87,1,148).
+relate(-1,141,1,148).
+relate(-1,107,1,148).
+relate(-1,107,1,150).
+relate(-1,129,1,150).
+relate(-1,11,1,150).
+relate(-1,129,1,152).
+relate(-1,175,1,152).
+relate(-1,99,1,154).
+relate(-1,175,1,154).
+relate(-1,103,1,156).
+relate(-1,1,1,156).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/58-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/58-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..fcc2741
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/58-partner_units_polynomial-100-0.lp
@@ -0,0 +1,740 @@
+maxPU(2).
+#const n=176.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(-1,154).
+object(-1,155).
+object(-1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(-1,27,-1,29).
+follow(-1,15,-1,17).
+follow(-1,3,-1,5).
+follow(-1,33,-1,35).
+follow(-1,69,-1,71).
+follow(-1,153,-1,154).
+follow(-1,107,-1,109).
+follow(-1,65,-1,67).
+follow(-1,117,-1,119).
+follow(-1,164,-1,165).
+follow(-1,170,-1,171).
+follow(-1,37,-1,39).
+follow(-1,127,-1,129).
+follow(-1,79,-1,81).
+follow(-1,154,-1,155).
+follow(-1,101,-1,103).
+follow(-1,53,-1,55).
+follow(-1,147,-1,149).
+follow(-1,151,-1,153).
+follow(-1,43,-1,45).
+follow(-1,162,-1,163).
+follow(-1,51,-1,53).
+follow(-1,159,-1,160).
+follow(-1,163,-1,164).
+follow(-1,119,-1,121).
+follow(-1,125,-1,127).
+follow(-1,123,-1,125).
+follow(-1,109,-1,111).
+follow(-1,171,-1,172).
+follow(-1,35,-1,37).
+follow(-1,59,-1,61).
+follow(-1,105,-1,107).
+follow(-1,13,-1,15).
+follow(-1,115,-1,117).
+follow(-1,81,-1,83).
+follow(-1,83,-1,85).
+follow(-1,55,-1,57).
+follow(-1,172,-1,173).
+follow(-1,97,-1,99).
+follow(-1,89,-1,91).
+follow(-1,9,-1,11).
+follow(-1,77,-1,79).
+follow(-1,137,-1,139).
+follow(-1,169,-1,170).
+follow(-1,168,-1,169).
+follow(-1,85,-1,87).
+follow(-1,17,-1,19).
+follow(-1,73,-1,75).
+follow(-1,1,-1,3).
+follow(-1,166,-1,167).
+follow(-1,47,-1,49).
+follow(-1,121,-1,123).
+follow(-1,135,-1,137).
+follow(-1,167,-1,168).
+follow(-1,63,-1,65).
+follow(-1,175,-1,176).
+follow(-1,21,-1,23).
+follow(-1,143,-1,145).
+follow(-1,23,-1,25).
+follow(-1,149,-1,151).
+follow(-1,5,-1,7).
+follow(-1,113,-1,115).
+follow(-1,103,-1,105).
+follow(-1,19,-1,21).
+follow(-1,129,-1,131).
+follow(-1,61,-1,63).
+follow(-1,91,-1,93).
+follow(-1,11,-1,13).
+follow(-1,75,-1,77).
+follow(-1,174,-1,175).
+follow(-1,87,-1,89).
+follow(-1,31,-1,33).
+follow(-1,158,-1,159).
+follow(-1,95,-1,97).
+follow(-1,139,-1,141).
+follow(-1,145,-1,147).
+follow(-1,131,-1,133).
+follow(-1,29,-1,31).
+follow(-1,173,-1,174).
+follow(-1,165,-1,166).
+follow(-1,155,-1,156).
+follow(-1,141,-1,143).
+follow(-1,160,-1,161).
+follow(-1,39,-1,41).
+follow(-1,45,-1,47).
+follow(-1,156,-1,157).
+follow(-1,99,-1,101).
+follow(-1,57,-1,59).
+follow(-1,111,-1,113).
+follow(-1,157,-1,158).
+follow(-1,133,-1,135).
+follow(-1,49,-1,51).
+follow(-1,7,-1,9).
+follow(-1,67,-1,69).
+follow(-1,71,-1,73).
+follow(-1,25,-1,27).
+follow(-1,161,-1,162).
+follow(-1,93,-1,95).
+follow(-1,41,-1,43).
+relate(1,2,-1,29).
+relate(1,2,-1,17).
+relate(1,4,-1,29).
+relate(1,6,-1,5).
+relate(1,6,-1,35).
+relate(1,6,-1,71).
+relate(1,8,-1,35).
+relate(1,8,-1,154).
+relate(1,10,-1,109).
+relate(1,12,-1,17).
+relate(1,12,-1,67).
+relate(1,12,-1,119).
+relate(1,14,-1,67).
+relate(1,14,-1,165).
+relate(1,14,-1,171).
+relate(1,16,-1,71).
+relate(1,16,-1,165).
+relate(1,16,-1,39).
+relate(1,18,-1,154).
+relate(1,18,-1,39).
+relate(1,18,-1,129).
+relate(1,20,-1,81).
+relate(1,20,-1,155).
+relate(1,22,-1,109).
+relate(1,22,-1,81).
+relate(1,22,-1,103).
+relate(1,22,-1,55).
+relate(1,24,-1,103).
+relate(1,24,-1,149).
+relate(1,24,-1,153).
+relate(1,26,-1,149).
+relate(1,26,-1,45).
+relate(1,28,-1,119).
+relate(1,28,-1,163).
+relate(1,28,-1,53).
+relate(1,30,-1,171).
+relate(1,30,-1,163).
+relate(1,30,-1,160).
+relate(1,32,-1,160).
+relate(1,32,-1,164).
+relate(1,34,-1,129).
+relate(1,34,-1,121).
+relate(1,36,-1,155).
+relate(1,36,-1,127).
+relate(1,36,-1,125).
+relate(1,38,-1,55).
+relate(1,38,-1,127).
+relate(1,38,-1,111).
+relate(1,40,-1,153).
+relate(1,40,-1,172).
+relate(1,42,-1,45).
+relate(1,42,-1,172).
+relate(1,42,-1,37).
+relate(1,44,-1,53).
+relate(1,44,-1,61).
+relate(1,44,-1,107).
+relate(1,46,-1,61).
+relate(1,46,-1,15).
+relate(1,46,-1,117).
+relate(1,48,-1,164).
+relate(1,48,-1,15).
+relate(1,48,-1,83).
+relate(1,50,-1,121).
+relate(1,50,-1,85).
+relate(1,50,-1,57).
+relate(1,52,-1,125).
+relate(1,52,-1,85).
+relate(1,54,-1,111).
+relate(1,56,-1,173).
+relate(1,56,-1,99).
+relate(1,58,-1,37).
+relate(1,58,-1,173).
+relate(1,58,-1,1).
+relate(1,58,-1,91).
+relate(1,60,-1,107).
+relate(1,60,-1,11).
+relate(1,60,-1,79).
+relate(1,62,-1,117).
+relate(1,62,-1,139).
+relate(1,64,-1,83).
+relate(1,64,-1,170).
+relate(1,66,-1,57).
+relate(1,68,-1,169).
+relate(1,70,-1,169).
+relate(1,70,-1,87).
+relate(1,70,-1,19).
+relate(1,72,-1,99).
+relate(1,72,-1,87).
+relate(1,72,-1,75).
+relate(1,74,-1,91).
+relate(1,74,-1,3).
+relate(1,74,-1,167).
+relate(1,76,-1,79).
+relate(1,76,-1,49).
+relate(1,76,-1,123).
+relate(1,78,-1,139).
+relate(1,78,-1,49).
+relate(1,78,-1,137).
+relate(1,80,-1,170).
+relate(1,80,-1,137).
+relate(1,80,-1,168).
+relate(1,80,-1,65).
+relate(1,82,-1,168).
+relate(1,82,-1,176).
+relate(1,84,-1,23).
+relate(1,86,-1,19).
+relate(1,86,-1,145).
+relate(1,86,-1,25).
+relate(1,88,-1,75).
+relate(1,88,-1,145).
+relate(1,88,-1,151).
+relate(1,90,-1,167).
+relate(1,90,-1,7).
+relate(1,90,-1,115).
+relate(1,92,-1,123).
+relate(1,92,-1,105).
+relate(1,92,-1,21).
+relate(1,94,-1,105).
+relate(1,94,-1,131).
+relate(1,94,-1,63).
+relate(1,96,-1,65).
+relate(1,96,-1,131).
+relate(1,96,-1,93).
+relate(1,96,-1,13).
+relate(1,98,-1,176).
+relate(1,98,-1,93).
+relate(1,98,-1,77).
+relate(1,98,-1,175).
+relate(1,100,-1,23).
+relate(1,100,-1,77).
+relate(1,100,-1,89).
+relate(1,100,-1,33).
+relate(1,102,-1,25).
+relate(1,102,-1,89).
+relate(1,104,-1,151).
+relate(1,104,-1,159).
+relate(1,106,-1,115).
+relate(1,106,-1,159).
+relate(1,106,-1,97).
+relate(1,108,-1,21).
+relate(1,108,-1,141).
+relate(1,108,-1,147).
+relate(1,110,-1,63).
+relate(1,110,-1,141).
+relate(1,112,-1,13).
+relate(1,112,-1,133).
+relate(1,114,-1,175).
+relate(1,114,-1,31).
+relate(1,116,-1,33).
+relate(1,116,-1,31).
+relate(1,116,-1,174).
+relate(1,116,-1,166).
+relate(1,118,-1,174).
+relate(1,118,-1,156).
+relate(1,118,-1,143).
+relate(1,120,-1,156).
+relate(1,120,-1,161).
+relate(1,122,-1,97).
+relate(1,122,-1,161).
+relate(1,122,-1,41).
+relate(1,124,-1,147).
+relate(1,126,-1,47).
+relate(1,128,-1,133).
+relate(1,128,-1,47).
+relate(1,128,-1,157).
+relate(1,128,-1,101).
+relate(1,130,-1,157).
+relate(1,130,-1,59).
+relate(1,132,-1,166).
+relate(1,132,-1,59).
+relate(1,132,-1,113).
+relate(1,132,-1,158).
+relate(1,134,-1,143).
+relate(1,134,-1,113).
+relate(1,134,-1,135).
+relate(1,136,-1,51).
+relate(1,138,-1,41).
+relate(1,138,-1,51).
+relate(1,138,-1,9).
+relate(1,138,-1,69).
+relate(1,140,-1,73).
+relate(1,142,-1,101).
+relate(1,142,-1,73).
+relate(1,142,-1,27).
+relate(1,144,-1,27).
+relate(1,144,-1,162).
+relate(1,146,-1,158).
+relate(1,146,-1,162).
+relate(1,146,-1,95).
+relate(1,148,-1,135).
+relate(1,148,-1,95).
+relate(1,150,-1,43).
+relate(1,152,-1,69).
+relate(1,152,-1,43).
+relate(-1,29,1,2).
+relate(-1,17,1,2).
+relate(-1,29,1,4).
+relate(-1,5,1,6).
+relate(-1,35,1,6).
+relate(-1,71,1,6).
+relate(-1,35,1,8).
+relate(-1,154,1,8).
+relate(-1,109,1,10).
+relate(-1,17,1,12).
+relate(-1,67,1,12).
+relate(-1,119,1,12).
+relate(-1,67,1,14).
+relate(-1,165,1,14).
+relate(-1,171,1,14).
+relate(-1,71,1,16).
+relate(-1,165,1,16).
+relate(-1,39,1,16).
+relate(-1,154,1,18).
+relate(-1,39,1,18).
+relate(-1,129,1,18).
+relate(-1,81,1,20).
+relate(-1,155,1,20).
+relate(-1,109,1,22).
+relate(-1,81,1,22).
+relate(-1,103,1,22).
+relate(-1,55,1,22).
+relate(-1,103,1,24).
+relate(-1,149,1,24).
+relate(-1,153,1,24).
+relate(-1,149,1,26).
+relate(-1,45,1,26).
+relate(-1,119,1,28).
+relate(-1,163,1,28).
+relate(-1,53,1,28).
+relate(-1,171,1,30).
+relate(-1,163,1,30).
+relate(-1,160,1,30).
+relate(-1,160,1,32).
+relate(-1,164,1,32).
+relate(-1,129,1,34).
+relate(-1,121,1,34).
+relate(-1,155,1,36).
+relate(-1,127,1,36).
+relate(-1,125,1,36).
+relate(-1,55,1,38).
+relate(-1,127,1,38).
+relate(-1,111,1,38).
+relate(-1,153,1,40).
+relate(-1,172,1,40).
+relate(-1,45,1,42).
+relate(-1,172,1,42).
+relate(-1,37,1,42).
+relate(-1,53,1,44).
+relate(-1,61,1,44).
+relate(-1,107,1,44).
+relate(-1,61,1,46).
+relate(-1,15,1,46).
+relate(-1,117,1,46).
+relate(-1,164,1,48).
+relate(-1,15,1,48).
+relate(-1,83,1,48).
+relate(-1,121,1,50).
+relate(-1,85,1,50).
+relate(-1,57,1,50).
+relate(-1,125,1,52).
+relate(-1,85,1,52).
+relate(-1,111,1,54).
+relate(-1,173,1,56).
+relate(-1,99,1,56).
+relate(-1,37,1,58).
+relate(-1,173,1,58).
+relate(-1,1,1,58).
+relate(-1,91,1,58).
+relate(-1,107,1,60).
+relate(-1,11,1,60).
+relate(-1,79,1,60).
+relate(-1,117,1,62).
+relate(-1,139,1,62).
+relate(-1,83,1,64).
+relate(-1,170,1,64).
+relate(-1,57,1,66).
+relate(-1,169,1,68).
+relate(-1,169,1,70).
+relate(-1,87,1,70).
+relate(-1,19,1,70).
+relate(-1,99,1,72).
+relate(-1,87,1,72).
+relate(-1,75,1,72).
+relate(-1,91,1,74).
+relate(-1,3,1,74).
+relate(-1,167,1,74).
+relate(-1,79,1,76).
+relate(-1,49,1,76).
+relate(-1,123,1,76).
+relate(-1,139,1,78).
+relate(-1,49,1,78).
+relate(-1,137,1,78).
+relate(-1,170,1,80).
+relate(-1,137,1,80).
+relate(-1,168,1,80).
+relate(-1,65,1,80).
+relate(-1,168,1,82).
+relate(-1,176,1,82).
+relate(-1,23,1,84).
+relate(-1,19,1,86).
+relate(-1,145,1,86).
+relate(-1,25,1,86).
+relate(-1,75,1,88).
+relate(-1,145,1,88).
+relate(-1,151,1,88).
+relate(-1,167,1,90).
+relate(-1,7,1,90).
+relate(-1,115,1,90).
+relate(-1,123,1,92).
+relate(-1,105,1,92).
+relate(-1,21,1,92).
+relate(-1,105,1,94).
+relate(-1,131,1,94).
+relate(-1,63,1,94).
+relate(-1,65,1,96).
+relate(-1,131,1,96).
+relate(-1,93,1,96).
+relate(-1,13,1,96).
+relate(-1,176,1,98).
+relate(-1,93,1,98).
+relate(-1,77,1,98).
+relate(-1,175,1,98).
+relate(-1,23,1,100).
+relate(-1,77,1,100).
+relate(-1,89,1,100).
+relate(-1,33,1,100).
+relate(-1,25,1,102).
+relate(-1,89,1,102).
+relate(-1,151,1,104).
+relate(-1,159,1,104).
+relate(-1,115,1,106).
+relate(-1,159,1,106).
+relate(-1,97,1,106).
+relate(-1,21,1,108).
+relate(-1,141,1,108).
+relate(-1,147,1,108).
+relate(-1,63,1,110).
+relate(-1,141,1,110).
+relate(-1,13,1,112).
+relate(-1,133,1,112).
+relate(-1,175,1,114).
+relate(-1,31,1,114).
+relate(-1,33,1,116).
+relate(-1,31,1,116).
+relate(-1,174,1,116).
+relate(-1,166,1,116).
+relate(-1,174,1,118).
+relate(-1,156,1,118).
+relate(-1,143,1,118).
+relate(-1,156,1,120).
+relate(-1,161,1,120).
+relate(-1,97,1,122).
+relate(-1,161,1,122).
+relate(-1,41,1,122).
+relate(-1,147,1,124).
+relate(-1,47,1,126).
+relate(-1,133,1,128).
+relate(-1,47,1,128).
+relate(-1,157,1,128).
+relate(-1,101,1,128).
+relate(-1,157,1,130).
+relate(-1,59,1,130).
+relate(-1,166,1,132).
+relate(-1,59,1,132).
+relate(-1,113,1,132).
+relate(-1,158,1,132).
+relate(-1,143,1,134).
+relate(-1,113,1,134).
+relate(-1,135,1,134).
+relate(-1,51,1,136).
+relate(-1,41,1,138).
+relate(-1,51,1,138).
+relate(-1,9,1,138).
+relate(-1,69,1,138).
+relate(-1,73,1,140).
+relate(-1,101,1,142).
+relate(-1,73,1,142).
+relate(-1,27,1,142).
+relate(-1,27,1,144).
+relate(-1,162,1,144).
+relate(-1,158,1,146).
+relate(-1,162,1,146).
+relate(-1,95,1,146).
+relate(-1,135,1,148).
+relate(-1,95,1,148).
+relate(-1,43,1,150).
+relate(-1,69,1,152).
+relate(-1,43,1,152).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/69-partner_units_polynomial-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/69-partner_units_polynomial-100-0.lp
new file mode 100644
index 0000000..c982af6
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/69-partner_units_polynomial-100-0.lp
@@ -0,0 +1,744 @@
+maxPU(2).
+#const n=178.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(-1,61,-1,63).
+follow(-1,35,-1,37).
+follow(-1,115,-1,117).
+follow(-1,99,-1,101).
+follow(-1,105,-1,107).
+follow(-1,77,-1,79).
+follow(-1,19,-1,21).
+follow(-1,113,-1,115).
+follow(-1,25,-1,27).
+follow(-1,83,-1,85).
+follow(-1,159,-1,160).
+follow(-1,158,-1,159).
+follow(-1,177,-1,178).
+follow(-1,141,-1,143).
+follow(-1,95,-1,97).
+follow(-1,143,-1,145).
+follow(-1,15,-1,17).
+follow(-1,89,-1,91).
+follow(-1,157,-1,158).
+follow(-1,101,-1,103).
+follow(-1,69,-1,71).
+follow(-1,17,-1,19).
+follow(-1,173,-1,174).
+follow(-1,167,-1,168).
+follow(-1,162,-1,163).
+follow(-1,13,-1,15).
+follow(-1,168,-1,169).
+follow(-1,93,-1,95).
+follow(-1,65,-1,67).
+follow(-1,109,-1,111).
+follow(-1,176,-1,177).
+follow(-1,51,-1,53).
+follow(-1,43,-1,45).
+follow(-1,131,-1,133).
+follow(-1,149,-1,151).
+follow(-1,91,-1,93).
+follow(-1,103,-1,105).
+follow(-1,55,-1,57).
+follow(-1,151,-1,153).
+follow(-1,171,-1,172).
+follow(-1,125,-1,127).
+follow(-1,3,-1,5).
+follow(-1,31,-1,33).
+follow(-1,164,-1,165).
+follow(-1,123,-1,125).
+follow(-1,45,-1,47).
+follow(-1,175,-1,176).
+follow(-1,81,-1,83).
+follow(-1,163,-1,164).
+follow(-1,155,-1,157).
+follow(-1,107,-1,109).
+follow(-1,127,-1,129).
+follow(-1,145,-1,147).
+follow(-1,39,-1,41).
+follow(-1,79,-1,81).
+follow(-1,41,-1,43).
+follow(-1,172,-1,173).
+follow(-1,47,-1,49).
+follow(-1,133,-1,135).
+follow(-1,160,-1,161).
+follow(-1,27,-1,29).
+follow(-1,21,-1,23).
+follow(-1,29,-1,31).
+follow(-1,33,-1,35).
+follow(-1,67,-1,69).
+follow(-1,147,-1,149).
+follow(-1,5,-1,7).
+follow(-1,71,-1,73).
+follow(-1,161,-1,162).
+follow(-1,137,-1,139).
+follow(-1,59,-1,61).
+follow(-1,111,-1,113).
+follow(-1,129,-1,131).
+follow(-1,73,-1,75).
+follow(-1,7,-1,9).
+follow(-1,165,-1,166).
+follow(-1,23,-1,25).
+follow(-1,153,-1,155).
+follow(-1,49,-1,51).
+follow(-1,75,-1,77).
+follow(-1,166,-1,167).
+follow(-1,117,-1,119).
+follow(-1,87,-1,89).
+follow(-1,85,-1,87).
+follow(-1,37,-1,39).
+follow(-1,53,-1,55).
+follow(-1,135,-1,137).
+follow(-1,57,-1,59).
+follow(-1,174,-1,175).
+follow(-1,97,-1,99).
+follow(-1,9,-1,11).
+follow(-1,63,-1,65).
+follow(-1,119,-1,121).
+follow(-1,1,-1,3).
+follow(-1,169,-1,170).
+follow(-1,11,-1,13).
+follow(-1,170,-1,171).
+follow(-1,139,-1,141).
+follow(-1,121,-1,123).
+relate(1,2,-1,63).
+relate(1,4,-1,37).
+relate(1,6,-1,117).
+relate(1,8,-1,1).
+relate(1,8,-1,101).
+relate(1,8,-1,107).
+relate(1,10,-1,101).
+relate(1,10,-1,79).
+relate(1,10,-1,21).
+relate(1,12,-1,79).
+relate(1,12,-1,115).
+relate(1,14,-1,115).
+relate(1,16,-1,27).
+relate(1,18,-1,63).
+relate(1,18,-1,85).
+relate(1,18,-1,160).
+relate(1,20,-1,37).
+relate(1,20,-1,85).
+relate(1,20,-1,159).
+relate(1,20,-1,178).
+relate(1,22,-1,117).
+relate(1,22,-1,159).
+relate(1,22,-1,143).
+relate(1,22,-1,97).
+relate(1,24,-1,107).
+relate(1,24,-1,143).
+relate(1,24,-1,145).
+relate(1,24,-1,17).
+relate(1,26,-1,21).
+relate(1,26,-1,145).
+relate(1,26,-1,91).
+relate(1,26,-1,158).
+relate(1,28,-1,91).
+relate(1,28,-1,103).
+relate(1,28,-1,71).
+relate(1,30,-1,103).
+relate(1,30,-1,19).
+relate(1,30,-1,174).
+relate(1,32,-1,27).
+relate(1,32,-1,19).
+relate(1,34,-1,160).
+relate(1,34,-1,168).
+relate(1,36,-1,178).
+relate(1,36,-1,168).
+relate(1,36,-1,163).
+relate(1,36,-1,15).
+relate(1,38,-1,97).
+relate(1,38,-1,163).
+relate(1,38,-1,169).
+relate(1,40,-1,17).
+relate(1,40,-1,169).
+relate(1,40,-1,95).
+relate(1,40,-1,67).
+relate(1,42,-1,158).
+relate(1,42,-1,95).
+relate(1,42,-1,111).
+relate(1,44,-1,71).
+relate(1,46,-1,174).
+relate(1,46,-1,177).
+relate(1,46,-1,53).
+relate(1,48,-1,177).
+relate(1,48,-1,45).
+relate(1,50,-1,15).
+relate(1,50,-1,133).
+relate(1,50,-1,151).
+relate(1,52,-1,133).
+relate(1,52,-1,93).
+relate(1,54,-1,67).
+relate(1,54,-1,105).
+relate(1,54,-1,57).
+relate(1,56,-1,111).
+relate(1,56,-1,105).
+relate(1,56,-1,153).
+relate(1,58,-1,53).
+relate(1,58,-1,172).
+relate(1,58,-1,127).
+relate(1,60,-1,45).
+relate(1,60,-1,172).
+relate(1,60,-1,5).
+relate(1,60,-1,33).
+relate(1,62,-1,165).
+relate(1,64,-1,151).
+relate(1,64,-1,165).
+relate(1,64,-1,125).
+relate(1,66,-1,93).
+relate(1,68,-1,57).
+relate(1,68,-1,47).
+relate(1,68,-1,176).
+relate(1,70,-1,153).
+relate(1,70,-1,47).
+relate(1,70,-1,83).
+relate(1,70,-1,164).
+relate(1,72,-1,83).
+relate(1,72,-1,157).
+relate(1,72,-1,109).
+relate(1,74,-1,127).
+relate(1,74,-1,157).
+relate(1,74,-1,129).
+relate(1,76,-1,33).
+relate(1,78,-1,147).
+relate(1,78,-1,41).
+relate(1,80,-1,125).
+relate(1,80,-1,147).
+relate(1,80,-1,81).
+relate(1,82,-1,81).
+relate(1,82,-1,43).
+relate(1,82,-1,173).
+relate(1,84,-1,176).
+relate(1,84,-1,43).
+relate(1,84,-1,49).
+relate(1,84,-1,135).
+relate(1,86,-1,164).
+relate(1,86,-1,49).
+relate(1,86,-1,161).
+relate(1,86,-1,29).
+relate(1,88,-1,109).
+relate(1,88,-1,161).
+relate(1,88,-1,23).
+relate(1,88,-1,31).
+relate(1,90,-1,129).
+relate(1,90,-1,23).
+relate(1,90,-1,35).
+relate(1,90,-1,69).
+relate(1,92,-1,35).
+relate(1,92,-1,149).
+relate(1,94,-1,41).
+relate(1,94,-1,7).
+relate(1,94,-1,73).
+relate(1,96,-1,73).
+relate(1,96,-1,162).
+relate(1,98,-1,173).
+relate(1,98,-1,139).
+relate(1,100,-1,135).
+relate(1,100,-1,139).
+relate(1,102,-1,29).
+relate(1,102,-1,61).
+relate(1,104,-1,31).
+relate(1,104,-1,113).
+relate(1,106,-1,69).
+relate(1,106,-1,131).
+relate(1,106,-1,75).
+relate(1,108,-1,149).
+relate(1,108,-1,131).
+relate(1,108,-1,9).
+relate(1,108,-1,166).
+relate(1,110,-1,25).
+relate(1,112,-1,162).
+relate(1,112,-1,25).
+relate(1,112,-1,155).
+relate(1,114,-1,51).
+relate(1,116,-1,77).
+relate(1,116,-1,167).
+relate(1,118,-1,61).
+relate(1,118,-1,77).
+relate(1,120,-1,113).
+relate(1,120,-1,119).
+relate(1,120,-1,89).
+relate(1,122,-1,75).
+relate(1,122,-1,119).
+relate(1,122,-1,87).
+relate(1,124,-1,166).
+relate(1,124,-1,87).
+relate(1,124,-1,39).
+relate(1,126,-1,55).
+relate(1,128,-1,155).
+relate(1,130,-1,51).
+relate(1,130,-1,137).
+relate(1,132,-1,167).
+relate(1,132,-1,59).
+relate(1,134,-1,59).
+relate(1,136,-1,89).
+relate(1,136,-1,175).
+relate(1,138,-1,99).
+relate(1,140,-1,39).
+relate(1,140,-1,11).
+relate(1,142,-1,55).
+relate(1,142,-1,65).
+relate(1,144,-1,65).
+relate(1,144,-1,121).
+relate(1,144,-1,3).
+relate(1,146,-1,137).
+relate(1,146,-1,121).
+relate(1,146,-1,170).
+relate(1,148,-1,170).
+relate(1,148,-1,13).
+relate(1,150,-1,13).
+relate(1,150,-1,171).
+relate(1,152,-1,175).
+relate(1,152,-1,171).
+relate(1,152,-1,141).
+relate(1,154,-1,99).
+relate(1,154,-1,141).
+relate(1,154,-1,123).
+relate(1,156,-1,123).
+relate(-1,63,1,2).
+relate(-1,37,1,4).
+relate(-1,117,1,6).
+relate(-1,1,1,8).
+relate(-1,101,1,8).
+relate(-1,107,1,8).
+relate(-1,101,1,10).
+relate(-1,79,1,10).
+relate(-1,21,1,10).
+relate(-1,79,1,12).
+relate(-1,115,1,12).
+relate(-1,115,1,14).
+relate(-1,27,1,16).
+relate(-1,63,1,18).
+relate(-1,85,1,18).
+relate(-1,160,1,18).
+relate(-1,37,1,20).
+relate(-1,85,1,20).
+relate(-1,159,1,20).
+relate(-1,178,1,20).
+relate(-1,117,1,22).
+relate(-1,159,1,22).
+relate(-1,143,1,22).
+relate(-1,97,1,22).
+relate(-1,107,1,24).
+relate(-1,143,1,24).
+relate(-1,145,1,24).
+relate(-1,17,1,24).
+relate(-1,21,1,26).
+relate(-1,145,1,26).
+relate(-1,91,1,26).
+relate(-1,158,1,26).
+relate(-1,91,1,28).
+relate(-1,103,1,28).
+relate(-1,71,1,28).
+relate(-1,103,1,30).
+relate(-1,19,1,30).
+relate(-1,174,1,30).
+relate(-1,27,1,32).
+relate(-1,19,1,32).
+relate(-1,160,1,34).
+relate(-1,168,1,34).
+relate(-1,178,1,36).
+relate(-1,168,1,36).
+relate(-1,163,1,36).
+relate(-1,15,1,36).
+relate(-1,97,1,38).
+relate(-1,163,1,38).
+relate(-1,169,1,38).
+relate(-1,17,1,40).
+relate(-1,169,1,40).
+relate(-1,95,1,40).
+relate(-1,67,1,40).
+relate(-1,158,1,42).
+relate(-1,95,1,42).
+relate(-1,111,1,42).
+relate(-1,71,1,44).
+relate(-1,174,1,46).
+relate(-1,177,1,46).
+relate(-1,53,1,46).
+relate(-1,177,1,48).
+relate(-1,45,1,48).
+relate(-1,15,1,50).
+relate(-1,133,1,50).
+relate(-1,151,1,50).
+relate(-1,133,1,52).
+relate(-1,93,1,52).
+relate(-1,67,1,54).
+relate(-1,105,1,54).
+relate(-1,57,1,54).
+relate(-1,111,1,56).
+relate(-1,105,1,56).
+relate(-1,153,1,56).
+relate(-1,53,1,58).
+relate(-1,172,1,58).
+relate(-1,127,1,58).
+relate(-1,45,1,60).
+relate(-1,172,1,60).
+relate(-1,5,1,60).
+relate(-1,33,1,60).
+relate(-1,165,1,62).
+relate(-1,151,1,64).
+relate(-1,165,1,64).
+relate(-1,125,1,64).
+relate(-1,93,1,66).
+relate(-1,57,1,68).
+relate(-1,47,1,68).
+relate(-1,176,1,68).
+relate(-1,153,1,70).
+relate(-1,47,1,70).
+relate(-1,83,1,70).
+relate(-1,164,1,70).
+relate(-1,83,1,72).
+relate(-1,157,1,72).
+relate(-1,109,1,72).
+relate(-1,127,1,74).
+relate(-1,157,1,74).
+relate(-1,129,1,74).
+relate(-1,33,1,76).
+relate(-1,147,1,78).
+relate(-1,41,1,78).
+relate(-1,125,1,80).
+relate(-1,147,1,80).
+relate(-1,81,1,80).
+relate(-1,81,1,82).
+relate(-1,43,1,82).
+relate(-1,173,1,82).
+relate(-1,176,1,84).
+relate(-1,43,1,84).
+relate(-1,49,1,84).
+relate(-1,135,1,84).
+relate(-1,164,1,86).
+relate(-1,49,1,86).
+relate(-1,161,1,86).
+relate(-1,29,1,86).
+relate(-1,109,1,88).
+relate(-1,161,1,88).
+relate(-1,23,1,88).
+relate(-1,31,1,88).
+relate(-1,129,1,90).
+relate(-1,23,1,90).
+relate(-1,35,1,90).
+relate(-1,69,1,90).
+relate(-1,35,1,92).
+relate(-1,149,1,92).
+relate(-1,41,1,94).
+relate(-1,7,1,94).
+relate(-1,73,1,94).
+relate(-1,73,1,96).
+relate(-1,162,1,96).
+relate(-1,173,1,98).
+relate(-1,139,1,98).
+relate(-1,135,1,100).
+relate(-1,139,1,100).
+relate(-1,29,1,102).
+relate(-1,61,1,102).
+relate(-1,31,1,104).
+relate(-1,113,1,104).
+relate(-1,69,1,106).
+relate(-1,131,1,106).
+relate(-1,75,1,106).
+relate(-1,149,1,108).
+relate(-1,131,1,108).
+relate(-1,9,1,108).
+relate(-1,166,1,108).
+relate(-1,25,1,110).
+relate(-1,162,1,112).
+relate(-1,25,1,112).
+relate(-1,155,1,112).
+relate(-1,51,1,114).
+relate(-1,77,1,116).
+relate(-1,167,1,116).
+relate(-1,61,1,118).
+relate(-1,77,1,118).
+relate(-1,113,1,120).
+relate(-1,119,1,120).
+relate(-1,89,1,120).
+relate(-1,75,1,122).
+relate(-1,119,1,122).
+relate(-1,87,1,122).
+relate(-1,166,1,124).
+relate(-1,87,1,124).
+relate(-1,39,1,124).
+relate(-1,55,1,126).
+relate(-1,155,1,128).
+relate(-1,51,1,130).
+relate(-1,137,1,130).
+relate(-1,167,1,132).
+relate(-1,59,1,132).
+relate(-1,59,1,134).
+relate(-1,89,1,136).
+relate(-1,175,1,136).
+relate(-1,99,1,138).
+relate(-1,39,1,140).
+relate(-1,11,1,140).
+relate(-1,55,1,142).
+relate(-1,65,1,142).
+relate(-1,65,1,144).
+relate(-1,121,1,144).
+relate(-1,3,1,144).
+relate(-1,137,1,146).
+relate(-1,121,1,146).
+relate(-1,170,1,146).
+relate(-1,170,1,148).
+relate(-1,13,1,148).
+relate(-1,13,1,150).
+relate(-1,171,1,150).
+relate(-1,175,1,152).
+relate(-1,171,1,152).
+relate(-1,141,1,152).
+relate(-1,99,1,154).
+relate(-1,141,1,154).
+relate(-1,123,1,154).
+relate(-1,123,1,156).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/91-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/91-partner_units-100-0.lp
new file mode 100644
index 0000000..53637d0
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/91-partner_units-100-0.lp
@@ -0,0 +1,742 @@
+maxPU(4).
+#const n=177.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(-1,156).
+object(-1,157).
+object(-1,158).
+object(-1,159).
+object(-1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(-1,3,-1,5).
+follow(-1,39,-1,41).
+follow(-1,115,-1,117).
+follow(-1,21,-1,23).
+follow(-1,113,-1,115).
+follow(-1,9,-1,11).
+follow(-1,57,-1,59).
+follow(-1,135,-1,137).
+follow(-1,91,-1,93).
+follow(-1,63,-1,65).
+follow(-1,99,-1,101).
+follow(-1,89,-1,91).
+follow(-1,156,-1,157).
+follow(-1,109,-1,111).
+follow(-1,163,-1,164).
+follow(-1,13,-1,15).
+follow(-1,170,-1,171).
+follow(-1,174,-1,175).
+follow(-1,172,-1,173).
+follow(-1,157,-1,158).
+follow(-1,53,-1,55).
+follow(-1,23,-1,25).
+follow(-1,129,-1,131).
+follow(-1,33,-1,35).
+follow(-1,69,-1,71).
+follow(-1,11,-1,13).
+follow(-1,87,-1,89).
+follow(-1,167,-1,168).
+follow(-1,71,-1,73).
+follow(-1,158,-1,159).
+follow(-1,141,-1,143).
+follow(-1,41,-1,43).
+follow(-1,37,-1,39).
+follow(-1,123,-1,125).
+follow(-1,59,-1,61).
+follow(-1,65,-1,67).
+follow(-1,43,-1,45).
+follow(-1,151,-1,153).
+follow(-1,73,-1,75).
+follow(-1,143,-1,145).
+follow(-1,27,-1,29).
+follow(-1,107,-1,109).
+follow(-1,161,-1,162).
+follow(-1,35,-1,37).
+follow(-1,29,-1,31).
+follow(-1,67,-1,69).
+follow(-1,17,-1,19).
+follow(-1,7,-1,9).
+follow(-1,19,-1,21).
+follow(-1,5,-1,7).
+follow(-1,121,-1,123).
+follow(-1,147,-1,149).
+follow(-1,149,-1,151).
+follow(-1,103,-1,105).
+follow(-1,49,-1,51).
+follow(-1,169,-1,170).
+follow(-1,171,-1,172).
+follow(-1,97,-1,99).
+follow(-1,75,-1,77).
+follow(-1,127,-1,129).
+follow(-1,25,-1,27).
+follow(-1,162,-1,163).
+follow(-1,85,-1,87).
+follow(-1,165,-1,166).
+follow(-1,168,-1,169).
+follow(-1,45,-1,47).
+follow(-1,83,-1,85).
+follow(-1,160,-1,161).
+follow(-1,175,-1,176).
+follow(-1,79,-1,81).
+follow(-1,31,-1,33).
+follow(-1,139,-1,141).
+follow(-1,153,-1,155).
+follow(-1,47,-1,49).
+follow(-1,15,-1,17).
+follow(-1,176,-1,177).
+follow(-1,133,-1,135).
+follow(-1,81,-1,83).
+follow(-1,137,-1,139).
+follow(-1,77,-1,79).
+follow(-1,51,-1,53).
+follow(-1,131,-1,133).
+follow(-1,95,-1,97).
+follow(-1,1,-1,3).
+follow(-1,55,-1,57).
+follow(-1,111,-1,113).
+follow(-1,125,-1,127).
+follow(-1,93,-1,95).
+follow(-1,117,-1,119).
+follow(-1,159,-1,160).
+follow(-1,101,-1,103).
+follow(-1,61,-1,63).
+follow(-1,166,-1,167).
+follow(-1,119,-1,121).
+follow(-1,173,-1,174).
+follow(-1,145,-1,147).
+follow(-1,105,-1,107).
+follow(-1,164,-1,165).
+follow(-1,155,-1,156).
+relate(1,2,-1,5).
+relate(1,2,-1,41).
+relate(1,2,-1,117).
+relate(1,4,-1,41).
+relate(1,4,-1,23).
+relate(1,6,-1,115).
+relate(1,8,-1,11).
+relate(1,8,-1,59).
+relate(1,8,-1,137).
+relate(1,10,-1,59).
+relate(1,10,-1,93).
+relate(1,12,-1,65).
+relate(1,14,-1,65).
+relate(1,14,-1,101).
+relate(1,16,-1,117).
+relate(1,16,-1,1).
+relate(1,16,-1,91).
+relate(1,16,-1,157).
+relate(1,18,-1,23).
+relate(1,18,-1,91).
+relate(1,18,-1,111).
+relate(1,20,-1,115).
+relate(1,20,-1,164).
+relate(1,22,-1,137).
+relate(1,22,-1,164).
+relate(1,22,-1,15).
+relate(1,22,-1,171).
+relate(1,24,-1,93).
+relate(1,24,-1,15).
+relate(1,24,-1,175).
+relate(1,24,-1,173).
+relate(1,26,-1,175).
+relate(1,26,-1,158).
+relate(1,28,-1,158).
+relate(1,30,-1,101).
+relate(1,30,-1,55).
+relate(1,32,-1,157).
+relate(1,32,-1,25).
+relate(1,32,-1,131).
+relate(1,34,-1,111).
+relate(1,34,-1,25).
+relate(1,34,-1,35).
+relate(1,34,-1,71).
+relate(1,36,-1,35).
+relate(1,36,-1,13).
+relate(1,38,-1,171).
+relate(1,38,-1,13).
+relate(1,40,-1,173).
+relate(1,40,-1,89).
+relate(1,40,-1,168).
+relate(1,42,-1,89).
+relate(1,42,-1,73).
+relate(1,44,-1,55).
+relate(1,44,-1,159).
+relate(1,46,-1,131).
+relate(1,46,-1,143).
+relate(1,46,-1,43).
+relate(1,48,-1,71).
+relate(1,48,-1,143).
+relate(1,48,-1,39).
+relate(1,50,-1,39).
+relate(1,50,-1,125).
+relate(1,50,-1,61).
+relate(1,52,-1,125).
+relate(1,52,-1,67).
+relate(1,54,-1,168).
+relate(1,54,-1,67).
+relate(1,54,-1,45).
+relate(1,54,-1,153).
+relate(1,56,-1,73).
+relate(1,56,-1,45).
+relate(1,56,-1,75).
+relate(1,58,-1,75).
+relate(1,60,-1,159).
+relate(1,60,-1,145).
+relate(1,62,-1,43).
+relate(1,62,-1,29).
+relate(1,64,-1,29).
+relate(1,64,-1,109).
+relate(1,66,-1,61).
+relate(1,66,-1,162).
+relate(1,66,-1,37).
+relate(1,68,-1,162).
+relate(1,68,-1,31).
+relate(1,70,-1,153).
+relate(1,70,-1,31).
+relate(1,70,-1,69).
+relate(1,72,-1,19).
+relate(1,74,-1,145).
+relate(1,74,-1,9).
+relate(1,74,-1,21).
+relate(1,76,-1,7).
+relate(1,76,-1,123).
+relate(1,76,-1,149).
+relate(1,78,-1,109).
+relate(1,78,-1,123).
+relate(1,78,-1,151).
+relate(1,78,-1,105).
+relate(1,80,-1,37).
+relate(1,80,-1,151).
+relate(1,80,-1,51).
+relate(1,82,-1,51).
+relate(1,82,-1,170).
+relate(1,84,-1,69).
+relate(1,84,-1,172).
+relate(1,84,-1,99).
+relate(1,86,-1,172).
+relate(1,86,-1,77).
+relate(1,86,-1,129).
+relate(1,88,-1,19).
+relate(1,88,-1,77).
+relate(1,88,-1,27).
+relate(1,88,-1,163).
+relate(1,90,-1,21).
+relate(1,90,-1,27).
+relate(1,90,-1,87).
+relate(1,92,-1,149).
+relate(1,92,-1,166).
+relate(1,94,-1,105).
+relate(1,94,-1,169).
+relate(1,94,-1,47).
+relate(1,96,-1,169).
+relate(1,96,-1,85).
+relate(1,98,-1,170).
+relate(1,98,-1,85).
+relate(1,98,-1,161).
+relate(1,98,-1,176).
+relate(1,100,-1,99).
+relate(1,100,-1,161).
+relate(1,102,-1,129).
+relate(1,102,-1,81).
+relate(1,102,-1,33).
+relate(1,104,-1,163).
+relate(1,104,-1,81).
+relate(1,104,-1,141).
+relate(1,104,-1,155).
+relate(1,106,-1,87).
+relate(1,106,-1,141).
+relate(1,108,-1,166).
+relate(1,108,-1,49).
+relate(1,110,-1,47).
+relate(1,110,-1,49).
+relate(1,110,-1,17).
+relate(1,110,-1,177).
+relate(1,112,-1,17).
+relate(1,112,-1,135).
+relate(1,114,-1,176).
+relate(1,114,-1,135).
+relate(1,114,-1,83).
+relate(1,116,-1,83).
+relate(1,116,-1,139).
+relate(1,118,-1,33).
+relate(1,118,-1,79).
+relate(1,118,-1,53).
+relate(1,120,-1,155).
+relate(1,120,-1,79).
+relate(1,120,-1,133).
+relate(1,120,-1,97).
+relate(1,122,-1,133).
+relate(1,122,-1,3).
+relate(1,122,-1,57).
+relate(1,124,-1,113).
+relate(1,124,-1,127).
+relate(1,126,-1,177).
+relate(1,126,-1,113).
+relate(1,126,-1,95).
+relate(1,126,-1,119).
+relate(1,128,-1,95).
+relate(1,130,-1,160).
+relate(1,130,-1,103).
+relate(1,132,-1,139).
+relate(1,132,-1,160).
+relate(1,132,-1,63).
+relate(1,134,-1,53).
+relate(1,134,-1,167).
+relate(1,136,-1,97).
+relate(1,136,-1,167).
+relate(1,136,-1,121).
+relate(1,138,-1,57).
+relate(1,138,-1,174).
+relate(1,140,-1,127).
+relate(1,142,-1,119).
+relate(1,142,-1,147).
+relate(1,144,-1,147).
+relate(1,146,-1,103).
+relate(1,146,-1,107).
+relate(1,148,-1,63).
+relate(1,148,-1,107).
+relate(1,150,-1,165).
+relate(1,152,-1,121).
+relate(1,152,-1,165).
+relate(1,152,-1,156).
+relate(1,154,-1,174).
+relate(1,154,-1,156).
+relate(-1,5,1,2).
+relate(-1,41,1,2).
+relate(-1,117,1,2).
+relate(-1,41,1,4).
+relate(-1,23,1,4).
+relate(-1,115,1,6).
+relate(-1,11,1,8).
+relate(-1,59,1,8).
+relate(-1,137,1,8).
+relate(-1,59,1,10).
+relate(-1,93,1,10).
+relate(-1,65,1,12).
+relate(-1,65,1,14).
+relate(-1,101,1,14).
+relate(-1,117,1,16).
+relate(-1,1,1,16).
+relate(-1,91,1,16).
+relate(-1,157,1,16).
+relate(-1,23,1,18).
+relate(-1,91,1,18).
+relate(-1,111,1,18).
+relate(-1,115,1,20).
+relate(-1,164,1,20).
+relate(-1,137,1,22).
+relate(-1,164,1,22).
+relate(-1,15,1,22).
+relate(-1,171,1,22).
+relate(-1,93,1,24).
+relate(-1,15,1,24).
+relate(-1,175,1,24).
+relate(-1,173,1,24).
+relate(-1,175,1,26).
+relate(-1,158,1,26).
+relate(-1,158,1,28).
+relate(-1,101,1,30).
+relate(-1,55,1,30).
+relate(-1,157,1,32).
+relate(-1,25,1,32).
+relate(-1,131,1,32).
+relate(-1,111,1,34).
+relate(-1,25,1,34).
+relate(-1,35,1,34).
+relate(-1,71,1,34).
+relate(-1,35,1,36).
+relate(-1,13,1,36).
+relate(-1,171,1,38).
+relate(-1,13,1,38).
+relate(-1,173,1,40).
+relate(-1,89,1,40).
+relate(-1,168,1,40).
+relate(-1,89,1,42).
+relate(-1,73,1,42).
+relate(-1,55,1,44).
+relate(-1,159,1,44).
+relate(-1,131,1,46).
+relate(-1,143,1,46).
+relate(-1,43,1,46).
+relate(-1,71,1,48).
+relate(-1,143,1,48).
+relate(-1,39,1,48).
+relate(-1,39,1,50).
+relate(-1,125,1,50).
+relate(-1,61,1,50).
+relate(-1,125,1,52).
+relate(-1,67,1,52).
+relate(-1,168,1,54).
+relate(-1,67,1,54).
+relate(-1,45,1,54).
+relate(-1,153,1,54).
+relate(-1,73,1,56).
+relate(-1,45,1,56).
+relate(-1,75,1,56).
+relate(-1,75,1,58).
+relate(-1,159,1,60).
+relate(-1,145,1,60).
+relate(-1,43,1,62).
+relate(-1,29,1,62).
+relate(-1,29,1,64).
+relate(-1,109,1,64).
+relate(-1,61,1,66).
+relate(-1,162,1,66).
+relate(-1,37,1,66).
+relate(-1,162,1,68).
+relate(-1,31,1,68).
+relate(-1,153,1,70).
+relate(-1,31,1,70).
+relate(-1,69,1,70).
+relate(-1,19,1,72).
+relate(-1,145,1,74).
+relate(-1,9,1,74).
+relate(-1,21,1,74).
+relate(-1,7,1,76).
+relate(-1,123,1,76).
+relate(-1,149,1,76).
+relate(-1,109,1,78).
+relate(-1,123,1,78).
+relate(-1,151,1,78).
+relate(-1,105,1,78).
+relate(-1,37,1,80).
+relate(-1,151,1,80).
+relate(-1,51,1,80).
+relate(-1,51,1,82).
+relate(-1,170,1,82).
+relate(-1,69,1,84).
+relate(-1,172,1,84).
+relate(-1,99,1,84).
+relate(-1,172,1,86).
+relate(-1,77,1,86).
+relate(-1,129,1,86).
+relate(-1,19,1,88).
+relate(-1,77,1,88).
+relate(-1,27,1,88).
+relate(-1,163,1,88).
+relate(-1,21,1,90).
+relate(-1,27,1,90).
+relate(-1,87,1,90).
+relate(-1,149,1,92).
+relate(-1,166,1,92).
+relate(-1,105,1,94).
+relate(-1,169,1,94).
+relate(-1,47,1,94).
+relate(-1,169,1,96).
+relate(-1,85,1,96).
+relate(-1,170,1,98).
+relate(-1,85,1,98).
+relate(-1,161,1,98).
+relate(-1,176,1,98).
+relate(-1,99,1,100).
+relate(-1,161,1,100).
+relate(-1,129,1,102).
+relate(-1,81,1,102).
+relate(-1,33,1,102).
+relate(-1,163,1,104).
+relate(-1,81,1,104).
+relate(-1,141,1,104).
+relate(-1,155,1,104).
+relate(-1,87,1,106).
+relate(-1,141,1,106).
+relate(-1,166,1,108).
+relate(-1,49,1,108).
+relate(-1,47,1,110).
+relate(-1,49,1,110).
+relate(-1,17,1,110).
+relate(-1,177,1,110).
+relate(-1,17,1,112).
+relate(-1,135,1,112).
+relate(-1,176,1,114).
+relate(-1,135,1,114).
+relate(-1,83,1,114).
+relate(-1,83,1,116).
+relate(-1,139,1,116).
+relate(-1,33,1,118).
+relate(-1,79,1,118).
+relate(-1,53,1,118).
+relate(-1,155,1,120).
+relate(-1,79,1,120).
+relate(-1,133,1,120).
+relate(-1,97,1,120).
+relate(-1,133,1,122).
+relate(-1,3,1,122).
+relate(-1,57,1,122).
+relate(-1,113,1,124).
+relate(-1,127,1,124).
+relate(-1,177,1,126).
+relate(-1,113,1,126).
+relate(-1,95,1,126).
+relate(-1,119,1,126).
+relate(-1,95,1,128).
+relate(-1,160,1,130).
+relate(-1,103,1,130).
+relate(-1,139,1,132).
+relate(-1,160,1,132).
+relate(-1,63,1,132).
+relate(-1,53,1,134).
+relate(-1,167,1,134).
+relate(-1,97,1,136).
+relate(-1,167,1,136).
+relate(-1,121,1,136).
+relate(-1,57,1,138).
+relate(-1,174,1,138).
+relate(-1,127,1,140).
+relate(-1,119,1,142).
+relate(-1,147,1,142).
+relate(-1,147,1,144).
+relate(-1,103,1,146).
+relate(-1,107,1,146).
+relate(-1,63,1,148).
+relate(-1,107,1,148).
+relate(-1,165,1,150).
+relate(-1,121,1,152).
+relate(-1,165,1,152).
+relate(-1,156,1,152).
+relate(-1,174,1,154).
+relate(-1,156,1,154).
diff --git a/examples/clingo/expansion/PartnerUnits/instances/99-partner_units-100-0.lp b/examples/clingo/expansion/PartnerUnits/instances/99-partner_units-100-0.lp
new file mode 100644
index 0000000..c4710ef
--- /dev/null
+++ b/examples/clingo/expansion/PartnerUnits/instances/99-partner_units-100-0.lp
@@ -0,0 +1,748 @@
+maxPU(4).
+#const n=180.
+object(-1,1).
+object(1,2).
+object(-1,3).
+object(1,4).
+object(-1,5).
+object(1,6).
+object(-1,7).
+object(1,8).
+object(-1,9).
+object(1,10).
+object(-1,11).
+object(1,12).
+object(-1,13).
+object(1,14).
+object(-1,15).
+object(1,16).
+object(-1,17).
+object(1,18).
+object(-1,19).
+object(1,20).
+object(-1,21).
+object(1,22).
+object(-1,23).
+object(1,24).
+object(-1,25).
+object(1,26).
+object(-1,27).
+object(1,28).
+object(-1,29).
+object(1,30).
+object(-1,31).
+object(1,32).
+object(-1,33).
+object(1,34).
+object(-1,35).
+object(1,36).
+object(-1,37).
+object(1,38).
+object(-1,39).
+object(1,40).
+object(-1,41).
+object(1,42).
+object(-1,43).
+object(1,44).
+object(-1,45).
+object(1,46).
+object(-1,47).
+object(1,48).
+object(-1,49).
+object(1,50).
+object(-1,51).
+object(1,52).
+object(-1,53).
+object(1,54).
+object(-1,55).
+object(1,56).
+object(-1,57).
+object(1,58).
+object(-1,59).
+object(1,60).
+object(-1,61).
+object(1,62).
+object(-1,63).
+object(1,64).
+object(-1,65).
+object(1,66).
+object(-1,67).
+object(1,68).
+object(-1,69).
+object(1,70).
+object(-1,71).
+object(1,72).
+object(-1,73).
+object(1,74).
+object(-1,75).
+object(1,76).
+object(-1,77).
+object(1,78).
+object(-1,79).
+object(1,80).
+object(-1,81).
+object(1,82).
+object(-1,83).
+object(1,84).
+object(-1,85).
+object(1,86).
+object(-1,87).
+object(1,88).
+object(-1,89).
+object(1,90).
+object(-1,91).
+object(1,92).
+object(-1,93).
+object(1,94).
+object(-1,95).
+object(1,96).
+object(-1,97).
+object(1,98).
+object(-1,99).
+object(1,100).
+object(-1,101).
+object(1,102).
+object(-1,103).
+object(1,104).
+object(-1,105).
+object(1,106).
+object(-1,107).
+object(1,108).
+object(-1,109).
+object(1,110).
+object(-1,111).
+object(1,112).
+object(-1,113).
+object(1,114).
+object(-1,115).
+object(1,116).
+object(-1,117).
+object(1,118).
+object(-1,119).
+object(1,120).
+object(-1,121).
+object(1,122).
+object(-1,123).
+object(1,124).
+object(-1,125).
+object(1,126).
+object(-1,127).
+object(1,128).
+object(-1,129).
+object(1,130).
+object(-1,131).
+object(1,132).
+object(-1,133).
+object(1,134).
+object(-1,135).
+object(1,136).
+object(-1,137).
+object(1,138).
+object(-1,139).
+object(1,140).
+object(-1,141).
+object(1,142).
+object(-1,143).
+object(1,144).
+object(-1,145).
+object(1,146).
+object(-1,147).
+object(1,148).
+object(-1,149).
+object(1,150).
+object(-1,151).
+object(1,152).
+object(-1,153).
+object(1,154).
+object(-1,155).
+object(1,156).
+object(-1,157).
+object(1,158).
+object(-1,159).
+object(1,160).
+object(-1,161).
+object(-1,162).
+object(-1,163).
+object(-1,164).
+object(-1,165).
+object(-1,166).
+object(-1,167).
+object(-1,168).
+object(-1,169).
+object(-1,170).
+object(-1,171).
+object(-1,172).
+object(-1,173).
+object(-1,174).
+object(-1,175).
+object(-1,176).
+object(-1,177).
+object(-1,178).
+object(-1,179).
+object(-1,180).
+follow(1,2,1,4).
+follow(1,4,1,6).
+follow(1,6,1,8).
+follow(1,8,1,10).
+follow(1,10,1,12).
+follow(1,12,1,14).
+follow(1,14,1,16).
+follow(1,16,1,18).
+follow(1,18,1,20).
+follow(1,20,1,22).
+follow(1,22,1,24).
+follow(1,24,1,26).
+follow(1,26,1,28).
+follow(1,28,1,30).
+follow(1,30,1,32).
+follow(1,32,1,34).
+follow(1,34,1,36).
+follow(1,36,1,38).
+follow(1,38,1,40).
+follow(1,40,1,42).
+follow(1,42,1,44).
+follow(1,44,1,46).
+follow(1,46,1,48).
+follow(1,48,1,50).
+follow(1,50,1,52).
+follow(1,52,1,54).
+follow(1,54,1,56).
+follow(1,56,1,58).
+follow(1,58,1,60).
+follow(1,60,1,62).
+follow(1,62,1,64).
+follow(1,64,1,66).
+follow(1,66,1,68).
+follow(1,68,1,70).
+follow(1,70,1,72).
+follow(1,72,1,74).
+follow(1,74,1,76).
+follow(1,76,1,78).
+follow(1,78,1,80).
+follow(1,80,1,82).
+follow(1,82,1,84).
+follow(1,84,1,86).
+follow(1,86,1,88).
+follow(1,88,1,90).
+follow(1,90,1,92).
+follow(1,92,1,94).
+follow(1,94,1,96).
+follow(1,96,1,98).
+follow(1,98,1,100).
+follow(1,100,1,102).
+follow(1,102,1,104).
+follow(1,104,1,106).
+follow(1,106,1,108).
+follow(1,108,1,110).
+follow(1,110,1,112).
+follow(1,112,1,114).
+follow(1,114,1,116).
+follow(1,116,1,118).
+follow(1,118,1,120).
+follow(1,120,1,122).
+follow(1,122,1,124).
+follow(1,124,1,126).
+follow(1,126,1,128).
+follow(1,128,1,130).
+follow(1,130,1,132).
+follow(1,132,1,134).
+follow(1,134,1,136).
+follow(1,136,1,138).
+follow(1,138,1,140).
+follow(1,140,1,142).
+follow(1,142,1,144).
+follow(1,144,1,146).
+follow(1,146,1,148).
+follow(1,148,1,150).
+follow(1,150,1,152).
+follow(1,152,1,154).
+follow(1,154,1,156).
+follow(1,156,1,158).
+follow(1,158,1,160).
+follow(-1,119,-1,121).
+follow(-1,157,-1,159).
+follow(-1,1,-1,3).
+follow(-1,129,-1,131).
+follow(-1,61,-1,63).
+follow(-1,107,-1,109).
+follow(-1,173,-1,174).
+follow(-1,133,-1,135).
+follow(-1,165,-1,166).
+follow(-1,27,-1,29).
+follow(-1,135,-1,137).
+follow(-1,39,-1,41).
+follow(-1,7,-1,9).
+follow(-1,65,-1,67).
+follow(-1,17,-1,19).
+follow(-1,19,-1,21).
+follow(-1,162,-1,163).
+follow(-1,149,-1,151).
+follow(-1,177,-1,178).
+follow(-1,167,-1,168).
+follow(-1,115,-1,117).
+follow(-1,49,-1,51).
+follow(-1,31,-1,33).
+follow(-1,105,-1,107).
+follow(-1,163,-1,164).
+follow(-1,139,-1,141).
+follow(-1,155,-1,157).
+follow(-1,161,-1,162).
+follow(-1,153,-1,155).
+follow(-1,21,-1,23).
+follow(-1,23,-1,25).
+follow(-1,85,-1,87).
+follow(-1,47,-1,49).
+follow(-1,77,-1,79).
+follow(-1,37,-1,39).
+follow(-1,43,-1,45).
+follow(-1,51,-1,53).
+follow(-1,174,-1,175).
+follow(-1,75,-1,77).
+follow(-1,87,-1,89).
+follow(-1,103,-1,105).
+follow(-1,9,-1,11).
+follow(-1,117,-1,119).
+follow(-1,109,-1,111).
+follow(-1,41,-1,43).
+follow(-1,25,-1,27).
+follow(-1,81,-1,83).
+follow(-1,69,-1,71).
+follow(-1,169,-1,170).
+follow(-1,97,-1,99).
+follow(-1,89,-1,91).
+follow(-1,121,-1,123).
+follow(-1,159,-1,161).
+follow(-1,171,-1,172).
+follow(-1,93,-1,95).
+follow(-1,91,-1,93).
+follow(-1,178,-1,179).
+follow(-1,53,-1,55).
+follow(-1,99,-1,101).
+follow(-1,172,-1,173).
+follow(-1,164,-1,165).
+follow(-1,101,-1,103).
+follow(-1,79,-1,81).
+follow(-1,63,-1,65).
+follow(-1,125,-1,127).
+follow(-1,55,-1,57).
+follow(-1,45,-1,47).
+follow(-1,141,-1,143).
+follow(-1,168,-1,169).
+follow(-1,57,-1,59).
+follow(-1,131,-1,133).
+follow(-1,170,-1,171).
+follow(-1,151,-1,153).
+follow(-1,83,-1,85).
+follow(-1,127,-1,129).
+follow(-1,179,-1,180).
+follow(-1,123,-1,125).
+follow(-1,67,-1,69).
+follow(-1,166,-1,167).
+follow(-1,13,-1,15).
+follow(-1,29,-1,31).
+follow(-1,5,-1,7).
+follow(-1,59,-1,61).
+follow(-1,175,-1,176).
+follow(-1,95,-1,97).
+follow(-1,145,-1,147).
+follow(-1,137,-1,139).
+follow(-1,15,-1,17).
+follow(-1,73,-1,75).
+follow(-1,33,-1,35).
+follow(-1,176,-1,177).
+follow(-1,147,-1,149).
+follow(-1,35,-1,37).
+follow(-1,3,-1,5).
+follow(-1,71,-1,73).
+follow(-1,113,-1,115).
+follow(-1,143,-1,145).
+follow(-1,111,-1,113).
+follow(-1,11,-1,13).
+relate(1,2,-1,121).
+relate(1,2,-1,159).
+relate(1,4,-1,3).
+relate(1,4,-1,121).
+relate(1,4,-1,131).
+relate(1,6,-1,131).
+relate(1,6,-1,63).
+relate(1,8,-1,109).
+relate(1,8,-1,174).
+relate(1,10,-1,109).
+relate(1,10,-1,135).
+relate(1,10,-1,166).
+relate(1,12,-1,135).
+relate(1,12,-1,29).
+relate(1,14,-1,29).
+relate(1,14,-1,137).
+relate(1,14,-1,41).
+relate(1,16,-1,137).
+relate(1,16,-1,9).
+relate(1,16,-1,67).
+relate(1,18,-1,159).
+relate(1,20,-1,19).
+relate(1,20,-1,21).
+relate(1,22,-1,63).
+relate(1,22,-1,19).
+relate(1,22,-1,163).
+relate(1,22,-1,151).
+relate(1,24,-1,174).
+relate(1,24,-1,163).
+relate(1,26,-1,166).
+relate(1,26,-1,178).
+relate(1,26,-1,168).
+relate(1,28,-1,178).
+relate(1,30,-1,41).
+relate(1,30,-1,117).
+relate(1,30,-1,51).
+relate(1,32,-1,67).
+relate(1,32,-1,117).
+relate(1,32,-1,33).
+relate(1,34,-1,107).
+relate(1,36,-1,21).
+relate(1,36,-1,164).
+relate(1,36,-1,141).
+relate(1,38,-1,151).
+relate(1,38,-1,164).
+relate(1,38,-1,157).
+relate(1,38,-1,162).
+relate(1,40,-1,157).
+relate(1,40,-1,155).
+relate(1,42,-1,168).
+relate(1,42,-1,23).
+relate(1,44,-1,25).
+relate(1,46,-1,51).
+relate(1,46,-1,87).
+relate(1,48,-1,33).
+relate(1,48,-1,49).
+relate(1,50,-1,107).
+relate(1,50,-1,79).
+relate(1,50,-1,39).
+relate(1,52,-1,141).
+relate(1,52,-1,79).
+relate(1,52,-1,45).
+relate(1,54,-1,162).
+relate(1,54,-1,45).
+relate(1,54,-1,53).
+relate(1,56,-1,155).
+relate(1,56,-1,53).
+relate(1,56,-1,175).
+relate(1,58,-1,23).
+relate(1,58,-1,77).
+relate(1,60,-1,25).
+relate(1,60,-1,89).
+relate(1,62,-1,87).
+relate(1,62,-1,105).
+relate(1,64,-1,49).
+relate(1,64,-1,11).
+relate(1,64,-1,119).
+relate(1,66,-1,39).
+relate(1,66,-1,111).
+relate(1,68,-1,111).
+relate(1,68,-1,43).
+relate(1,68,-1,27).
+relate(1,70,-1,43).
+relate(1,70,-1,83).
+relate(1,72,-1,175).
+relate(1,72,-1,71).
+relate(1,74,-1,77).
+relate(1,74,-1,170).
+relate(1,76,-1,89).
+relate(1,76,-1,99).
+relate(1,78,-1,105).
+relate(1,78,-1,91).
+relate(1,80,-1,119).
+relate(1,82,-1,123).
+relate(1,84,-1,27).
+relate(1,84,-1,123).
+relate(1,84,-1,161).
+relate(1,86,-1,83).
+relate(1,86,-1,161).
+relate(1,88,-1,71).
+relate(1,88,-1,172).
+relate(1,90,-1,170).
+relate(1,90,-1,172).
+relate(1,90,-1,95).
+relate(1,90,-1,93).
+relate(1,92,-1,99).
+relate(1,92,-1,95).
+relate(1,92,-1,179).
+relate(1,92,-1,55).
+relate(1,94,-1,91).
+relate(1,94,-1,179).
+relate(1,94,-1,101).
+relate(1,96,-1,101).
+relate(1,96,-1,173).
+relate(1,98,-1,1).
+relate(1,98,-1,165).
+relate(1,100,-1,165).
+relate(1,100,-1,103).
+relate(1,100,-1,81).
+relate(1,102,-1,103).
+relate(1,102,-1,65).
+relate(1,104,-1,127).
+relate(1,104,-1,57).
+relate(1,106,-1,93).
+relate(1,106,-1,127).
+relate(1,106,-1,47).
+relate(1,106,-1,143).
+relate(1,108,-1,55).
+relate(1,108,-1,47).
+relate(1,108,-1,169).
+relate(1,110,-1,169).
+relate(1,110,-1,59).
+relate(1,110,-1,133).
+relate(1,112,-1,173).
+relate(1,112,-1,59).
+relate(1,114,-1,171).
+relate(1,116,-1,81).
+relate(1,116,-1,171).
+relate(1,116,-1,153).
+relate(1,118,-1,65).
+relate(1,118,-1,85).
+relate(1,120,-1,57).
+relate(1,120,-1,85).
+relate(1,120,-1,129).
+relate(1,120,-1,180).
+relate(1,122,-1,143).
+relate(1,122,-1,129).
+relate(1,122,-1,125).
+relate(1,122,-1,69).
+relate(1,124,-1,125).
+relate(1,124,-1,167).
+relate(1,124,-1,15).
+relate(1,126,-1,133).
+relate(1,126,-1,167).
+relate(1,126,-1,31).
+relate(1,128,-1,31).
+relate(1,128,-1,7).
+relate(1,128,-1,61).
+relate(1,130,-1,176).
+relate(1,132,-1,153).
+relate(1,132,-1,176).
+relate(1,132,-1,97).
+relate(1,132,-1,147).
+relate(1,134,-1,97).
+relate(1,134,-1,139).
+relate(1,134,-1,17).
+relate(1,136,-1,180).
+relate(1,136,-1,139).
+relate(1,136,-1,75).
+relate(1,136,-1,35).
+relate(1,138,-1,69).
+relate(1,138,-1,75).
+relate(1,140,-1,15).
+relate(1,140,-1,177).
+relate(1,140,-1,149).
+relate(1,142,-1,177).
+relate(1,144,-1,61).
+relate(1,144,-1,37).
+relate(1,146,-1,5).
+relate(1,146,-1,73).
+relate(1,148,-1,147).
+relate(1,148,-1,73).
+relate(1,148,-1,115).
+relate(1,150,-1,17).
+relate(1,150,-1,115).
+relate(1,152,-1,35).
+relate(1,152,-1,145).
+relate(1,154,-1,145).
+relate(1,156,-1,149).
+relate(1,156,-1,113).
+relate(1,158,-1,113).
+relate(1,158,-1,13).
+relate(1,160,-1,37).
+relate(1,160,-1,13).
+relate(-1,121,1,2).
+relate(-1,159,1,2).
+relate(-1,3,1,4).
+relate(-1,121,1,4).
+relate(-1,131,1,4).
+relate(-1,131,1,6).
+relate(-1,63,1,6).
+relate(-1,109,1,8).
+relate(-1,174,1,8).
+relate(-1,109,1,10).
+relate(-1,135,1,10).
+relate(-1,166,1,10).
+relate(-1,135,1,12).
+relate(-1,29,1,12).
+relate(-1,29,1,14).
+relate(-1,137,1,14).
+relate(-1,41,1,14).
+relate(-1,137,1,16).
+relate(-1,9,1,16).
+relate(-1,67,1,16).
+relate(-1,159,1,18).
+relate(-1,19,1,20).
+relate(-1,21,1,20).
+relate(-1,63,1,22).
+relate(-1,19,1,22).
+relate(-1,163,1,22).
+relate(-1,151,1,22).
+relate(-1,174,1,24).
+relate(-1,163,1,24).
+relate(-1,166,1,26).
+relate(-1,178,1,26).
+relate(-1,168,1,26).
+relate(-1,178,1,28).
+relate(-1,41,1,30).
+relate(-1,117,1,30).
+relate(-1,51,1,30).
+relate(-1,67,1,32).
+relate(-1,117,1,32).
+relate(-1,33,1,32).
+relate(-1,107,1,34).
+relate(-1,21,1,36).
+relate(-1,164,1,36).
+relate(-1,141,1,36).
+relate(-1,151,1,38).
+relate(-1,164,1,38).
+relate(-1,157,1,38).
+relate(-1,162,1,38).
+relate(-1,157,1,40).
+relate(-1,155,1,40).
+relate(-1,168,1,42).
+relate(-1,23,1,42).
+relate(-1,25,1,44).
+relate(-1,51,1,46).
+relate(-1,87,1,46).
+relate(-1,33,1,48).
+relate(-1,49,1,48).
+relate(-1,107,1,50).
+relate(-1,79,1,50).
+relate(-1,39,1,50).
+relate(-1,141,1,52).
+relate(-1,79,1,52).
+relate(-1,45,1,52).
+relate(-1,162,1,54).
+relate(-1,45,1,54).
+relate(-1,53,1,54).
+relate(-1,155,1,56).
+relate(-1,53,1,56).
+relate(-1,175,1,56).
+relate(-1,23,1,58).
+relate(-1,77,1,58).
+relate(-1,25,1,60).
+relate(-1,89,1,60).
+relate(-1,87,1,62).
+relate(-1,105,1,62).
+relate(-1,49,1,64).
+relate(-1,11,1,64).
+relate(-1,119,1,64).
+relate(-1,39,1,66).
+relate(-1,111,1,66).
+relate(-1,111,1,68).
+relate(-1,43,1,68).
+relate(-1,27,1,68).
+relate(-1,43,1,70).
+relate(-1,83,1,70).
+relate(-1,175,1,72).
+relate(-1,71,1,72).
+relate(-1,77,1,74).
+relate(-1,170,1,74).
+relate(-1,89,1,76).
+relate(-1,99,1,76).
+relate(-1,105,1,78).
+relate(-1,91,1,78).
+relate(-1,119,1,80).
+relate(-1,123,1,82).
+relate(-1,27,1,84).
+relate(-1,123,1,84).
+relate(-1,161,1,84).
+relate(-1,83,1,86).
+relate(-1,161,1,86).
+relate(-1,71,1,88).
+relate(-1,172,1,88).
+relate(-1,170,1,90).
+relate(-1,172,1,90).
+relate(-1,95,1,90).
+relate(-1,93,1,90).
+relate(-1,99,1,92).
+relate(-1,95,1,92).
+relate(-1,179,1,92).
+relate(-1,55,1,92).
+relate(-1,91,1,94).
+relate(-1,179,1,94).
+relate(-1,101,1,94).
+relate(-1,101,1,96).
+relate(-1,173,1,96).
+relate(-1,1,1,98).
+relate(-1,165,1,98).
+relate(-1,165,1,100).
+relate(-1,103,1,100).
+relate(-1,81,1,100).
+relate(-1,103,1,102).
+relate(-1,65,1,102).
+relate(-1,127,1,104).
+relate(-1,57,1,104).
+relate(-1,93,1,106).
+relate(-1,127,1,106).
+relate(-1,47,1,106).
+relate(-1,143,1,106).
+relate(-1,55,1,108).
+relate(-1,47,1,108).
+relate(-1,169,1,108).
+relate(-1,169,1,110).
+relate(-1,59,1,110).
+relate(-1,133,1,110).
+relate(-1,173,1,112).
+relate(-1,59,1,112).
+relate(-1,171,1,114).
+relate(-1,81,1,116).
+relate(-1,171,1,116).
+relate(-1,153,1,116).
+relate(-1,65,1,118).
+relate(-1,85,1,118).
+relate(-1,57,1,120).
+relate(-1,85,1,120).
+relate(-1,129,1,120).
+relate(-1,180,1,120).
+relate(-1,143,1,122).
+relate(-1,129,1,122).
+relate(-1,125,1,122).
+relate(-1,69,1,122).
+relate(-1,125,1,124).
+relate(-1,167,1,124).
+relate(-1,15,1,124).
+relate(-1,133,1,126).
+relate(-1,167,1,126).
+relate(-1,31,1,126).
+relate(-1,31,1,128).
+relate(-1,7,1,128).
+relate(-1,61,1,128).
+relate(-1,176,1,130).
+relate(-1,153,1,132).
+relate(-1,176,1,132).
+relate(-1,97,1,132).
+relate(-1,147,1,132).
+relate(-1,97,1,134).
+relate(-1,139,1,134).
+relate(-1,17,1,134).
+relate(-1,180,1,136).
+relate(-1,139,1,136).
+relate(-1,75,1,136).
+relate(-1,35,1,136).
+relate(-1,69,1,138).
+relate(-1,75,1,138).
+relate(-1,15,1,140).
+relate(-1,177,1,140).
+relate(-1,149,1,140).
+relate(-1,177,1,142).
+relate(-1,61,1,144).
+relate(-1,37,1,144).
+relate(-1,5,1,146).
+relate(-1,73,1,146).
+relate(-1,147,1,148).
+relate(-1,73,1,148).
+relate(-1,115,1,148).
+relate(-1,17,1,150).
+relate(-1,115,1,150).
+relate(-1,35,1,152).
+relate(-1,145,1,152).
+relate(-1,145,1,154).
+relate(-1,149,1,156).
+relate(-1,113,1,156).
+relate(-1,113,1,158).
+relate(-1,13,1,158).
+relate(-1,37,1,160).
+relate(-1,13,1,160).
diff --git a/examples/clingo/expansion/README b/examples/clingo/expansion/README
new file mode 100644
index 0000000..2a3cf59
--- /dev/null
+++ b/examples/clingo/expansion/README
@@ -0,0 +1,33 @@
+The script in main.py gradually expands logic programs structured into the parts:
+
+- base         : rules instantiated initially
+- object(m,k)  : rules instantiated when an m-th object is introduced at step k
+- horizon(n,k) : rules instantiated when the horizon is turned up to n at step k
+- expand(k)    : rules instantiated along with object(m,k)/horizon(n,k) at step k
+
+For example, in GraphColouring (see GraphColouring/encodings/encoding.lp) objects
+correspond to nodes of a graph and the horizon is given by colors. Both nodes and
+colors are labeled by consecutive integers starting from 1, the parts object(m,k)
+and horizon(n,k) specify auxiliary predicates controlling the instances of rules
+in expand(k) that will be generated at step k, and the base part consists of the
+facts of an instance. Then, main.py takes care of expanding objects (nodes), as
+long as there is any, and extending the number of colors on demand, whenever an
+unsatisfiable problem is encountered. The two major operation modes of main.py
+are multi-shot solving or repeated single-shot solving (via option --scratch).
+For a summary of all options, run:
+
+./main.py --help
+
+The script main.py requires the clingo Python library shipped with clingo (see
+https://potassco.org).
+
+Examples invocations:
+
+$ ./main.py --verbose --option solver.forget_on_step 1 \
+    GraphColouring/encodings/encoding.lp \
+    GraphColouring/instances/0004-graph_colouring-125-0.lp
+
+$ ./main.py --verbose --option solver.forget_on_step 1 --maxobj 40 \
+    PartnerUnits/encodings/encoding.lp \
+    PartnerUnits/instances/180-partner_units_polynomial-47-0.lp
+
diff --git a/examples/clingo/expansion/main.py b/examples/clingo/expansion/main.py
new file mode 100755
index 0000000..0ed38bf
--- /dev/null
+++ b/examples/clingo/expansion/main.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+import clingo
+import json
+import sys
+import argparse
+
+class App:
+    def __init__(self, args):
+        self.control = clingo.Control()
+        self.args = args
+        self.horizon = 0
+        self.objects = 0
+        self.end     = None
+
+    def show(self, model):
+        if not self.args.quiet:
+            print "Model:", model
+
+    def ground(self, kind):
+        count = self.objects + self.horizon + 1
+        parts = [("expand", [count])]
+
+        if self.args.scratch and count > 1:
+            self.control = clingo.Control()
+            for source in self.args.file: self.control.load(source)
+            for i in range(0, self.objects): parts.append(("object", [i + 1, count]))
+            for i in range(0, self.horizon): parts.append(("horizon", [i + 1, count]))
+
+        if self.args.scratch or count == 1:
+            for option in self.args.option:
+                setattr(self.control.configuration, option[0], option[1])
+            parts.append(("base", []))
+
+        if kind:
+            self.objects += 1
+            parts.append(("object", [self.objects, count]))
+        else:
+            self.horizon += 1
+            parts.append(("horizon", [self.horizon, count]))
+
+        if self.args.verbose:
+             print
+             print "Objects:", self.objects
+             print "Horizon:", self.horizon
+
+        self.control.ground(parts)
+
+        if self.args.verbose:
+             print "Solving:", count
+
+    def run(self):
+        for source in self.args.file:
+            self.control.load(source)
+        if self.args.maxobj is None:
+            self.end = self.control.get_const("n").number
+        else:
+            self.end = self.args.maxobj
+
+        while self.objects < self.end:
+            self.ground(True)
+            while True:
+                ret = self.control.solve(on_model=self.show)
+                if self.args.stats:
+                    args = {"sort_keys": True, "indent": 0, "separators": (',', ': ')}
+                    stats = {}
+                    for x in ["step", "enumerated", "time_cpu", "time_solve", "time_sat", "time_unsat", "time_total"]:
+                        stats[x] = self.control.statistics[x]
+                    for x in ["lp", "ctx", "solvers"]:
+                        for y in self.control.statistics[x]:
+                            stats[y] = self.control.statistics[x][y]
+                    print json.dumps(stats, *args)
+                if ret.satisfiable:
+                    break
+                self.ground(False)
+
+parser = argparse.ArgumentParser(description="Gradually expand logic programs.", epilog="""Example: main.py -x -q -s -v -m 42 -o solve.models 0 encoding.lp instance.lp""")
+
+parser.add_argument("-x", "--scratch", action='store_true', help="start each step from scratch (single-shot solving)")
+parser.add_argument("-q", "--quiet", action='store_true', help="do not print models")
+parser.add_argument("-s", "--stats", action='store_true', help="print solver statistics")
+parser.add_argument("-v", "--verbose", action='store_true', help="print progress information")
+parser.add_argument("-m", "--maxobj", type=int, metavar="NUM", default=None, help="maximum number of introduced objects")
+parser.add_argument("-o", "--option", nargs=2, metavar=("OPT", "VAL"), action="append", default=[], help="set sover options")
+parser.add_argument("file", nargs="*", default=[], help="gringo source files")
+
+args = parser.parse_args()
+if args.maxobj is not None and args.maxobj < 1:
+    parser.error("maximum number of objects must be positive")
+
+App(args).run()
+
diff --git a/examples/clingo/external/README b/examples/clingo/external/README
new file mode 100644
index 0000000..6ea3ed4
--- /dev/null
+++ b/examples/clingo/external/README
@@ -0,0 +1,3 @@
+This example shows how to use external atoms:
+    clingo external.lp external-py.lp
+    clingo external.lp external-lua.lp
diff --git a/examples/clingo/external/external-lua.lp b/examples/clingo/external/external-lua.lp
new file mode 100644
index 0000000..2c73dc7
--- /dev/null
+++ b/examples/clingo/external/external-lua.lp
@@ -0,0 +1,14 @@
+#script(lua)
+function main(prg)
+    prg:ground({{"base", {}}})
+    prg:assign_external(clingo.Function("p", {3}), true)
+    prg:solve()
+    prg:assign_external(clingo.Function("p", {3}), false)
+    prg:solve()
+    prg:ground({{"succ", {1}}, {"succ", {2}}})
+    prg:solve()
+    prg:ground({{"succ", {3}}})
+    prg:solve()
+end
+#end.
+
diff --git a/examples/clingo/external/external-py.lp b/examples/clingo/external/external-py.lp
new file mode 100644
index 0000000..64e1d9d
--- /dev/null
+++ b/examples/clingo/external/external-py.lp
@@ -0,0 +1,14 @@
+#script(python)
+import clingo
+def main(prg):
+    prg.ground([("base", [])])
+    prg.assign_external(clingo.Function("p", [3]), True)
+    prg.solve()
+    prg.assign_external(clingo.Function("p", [3]), False)
+    prg.solve()
+    prg.ground([("succ", [1]), ("succ", [2])])
+    prg.solve()
+    prg.ground([("succ", [3])])
+    prg.solve()
+#end.
+
diff --git a/examples/clingo/external/external.lp b/examples/clingo/external/external.lp
new file mode 100644
index 0000000..d0f25f6
--- /dev/null
+++ b/examples/clingo/external/external.lp
@@ -0,0 +1,8 @@
+#external p(1;2;3).
+p(0) :- p(3).
+p(0) :- not p(0).
+
+#program succ(n).
+#external p(n+3).
+p(n) :- p(n+3).
+p(n) :- not p(n+1), not p(n+2).
diff --git a/examples/clingo/iclingo/README b/examples/clingo/iclingo/README
new file mode 100644
index 0000000..aeb7e58
--- /dev/null
+++ b/examples/clingo/iclingo/README
@@ -0,0 +1,10 @@
+The new clingo does not have an inbuilt incremental solving mode anymore.
+This example shows how this mode can be simulated via scripting.  For
+convenience, the lua main function in incmode-lua.lp has been embedded into
+clingo and can be loaded with an #include statement (see example
+incmode-lua.lp).
+
+Example calls:
+    clingo incmode-int.lp example.lp
+    clingo incmode-lua.lp example.lp
+    clingo incmode-py.lp example.lp
diff --git a/examples/clingo/iclingo/example.lp b/examples/clingo/iclingo/example.lp
new file mode 100644
index 0000000..faece7c
--- /dev/null
+++ b/examples/clingo/iclingo/example.lp
@@ -0,0 +1,16 @@
+#const istop  = "SAT".
+#const imin   = 1.
+%#const imax   = 11.
+
+#program base.
+
+{a;b;c}.
+
+#program step(k).
+
+{ c(k) }.
+q(k) :- c(k).
+
+#program check(k).
+
+ :- not c(5), query(k).
diff --git a/examples/clingo/iclingo/incmode-int.lp b/examples/clingo/iclingo/incmode-int.lp
new file mode 100644
index 0000000..9e88e34
--- /dev/null
+++ b/examples/clingo/iclingo/incmode-int.lp
@@ -0,0 +1 @@
+#include .
diff --git a/examples/clingo/iclingo/incmode-lua.lp b/examples/clingo/iclingo/incmode-lua.lp
new file mode 100644
index 0000000..6e07869
--- /dev/null
+++ b/examples/clingo/iclingo/incmode-lua.lp
@@ -0,0 +1,40 @@
+#script (lua) 
+
+function get(val, default)
+    if val ~= nil then 
+        return val 
+    else 
+        return default 
+    end
+end
+
+function main(prg)
+    local imin   = get(prg:get_const("imin"), clingo.Number(0))
+    local imax   = prg:get_const("imax")
+    local istop  = get(prg:get_const("istop"), clingo.String("SAT"))
+
+    local step, ret = 0, nil
+    while (imax == nil or step < imax.number) and
+          (step == 0 or step < imin.number or (
+              (istop.string == "SAT"     and not ret.satisfiable) or
+              (istop.string == "UNSAT"   and not ret.unsatisfiable) or 
+              (istop.string == "UNKNOWN" and not ret.unknown))) do
+        local parts = {}
+        table.insert(parts, {"check", {step}})
+        if step > 0 then
+            prg:release_external(clingo.Function("query", {step-1}))
+            table.insert(parts, {"step", {step}})
+            prg:cleanup()
+        else
+            table.insert(parts, {"base", {}})
+        end
+        prg:ground(parts)
+        prg:assign_external(clingo.Function("query", {step}), true)
+        ret, step = prg:solve(), step+1
+    end
+end
+
+#end.
+
+#program check(t).
+#external query(t).
diff --git a/examples/clingo/iclingo/incmode-py.lp b/examples/clingo/iclingo/incmode-py.lp
new file mode 100644
index 0000000..71e9e24
--- /dev/null
+++ b/examples/clingo/iclingo/incmode-py.lp
@@ -0,0 +1,33 @@
+#script (python) 
+
+import clingo
+
+def get(val, default):
+    return val if val != None else default
+
+def main(prg):
+    imin   = get(prg.get_const("imin"), clingo.Number(0))
+    imax   = prg.get_const("imax")
+    istop  = get(prg.get_const("istop"), clingo.String("SAT"))
+
+    step, ret = 0, None
+    while ((imax is None or step < imax.number) and
+           (step == 0 or step < imin.number or (
+              (istop.string == "SAT"     and not ret.satisfiable) or
+              (istop.string == "UNSAT"   and not ret.unsatisfiable) or 
+              (istop.string == "UNKNOWN" and not ret.unknown)))):
+        parts = []
+        parts.append(("check", [step]))
+        if step > 0:
+            prg.release_external(clingo.Function("query", [step-1]))
+            parts.append(("step", [step]))
+            prg.cleanup()
+        else:
+            parts.append(("base", []))
+        prg.ground(parts)
+        prg.assign_external(clingo.Function("query", [step]), True)
+        ret, step = prg.solve(), step+1
+#end.
+
+#program check(t).
+#external query(t).
diff --git a/examples/clingo/include/README b/examples/clingo/include/README
new file mode 100644
index 0000000..37cb264
--- /dev/null
+++ b/examples/clingo/include/README
@@ -0,0 +1,5 @@
+This simple example show the use of the include statement.
+
+Example call:
+    clingo encoding-py.lp
+    clingo encoding-lua.lp
diff --git a/examples/clingo/include/encoding-lua.lp b/examples/clingo/include/encoding-lua.lp
new file mode 100644
index 0000000..756df69
--- /dev/null
+++ b/examples/clingo/include/encoding-lua.lp
@@ -0,0 +1,13 @@
+#script (lua)
+
+function main(prg)
+    prg:ground({{"base", {}}, {"p", {42}}})
+    prg:solve()
+end
+
+#end.
+#program p(t).
+
+a(t).
+
+#include "include.lp".
diff --git a/examples/clingo/include/encoding-py.lp b/examples/clingo/include/encoding-py.lp
new file mode 100644
index 0000000..4f52dd3
--- /dev/null
+++ b/examples/clingo/include/encoding-py.lp
@@ -0,0 +1,12 @@
+#script (python)
+
+def main(prg):
+    prg.ground([("base", []), ("p", [42])])
+    prg.solve()
+
+#end.
+#program p(t).
+
+a(t).
+
+#include "include.lp".
diff --git a/examples/clingo/include/include.lp b/examples/clingo/include/include.lp
new file mode 100644
index 0000000..7f6a7e8
--- /dev/null
+++ b/examples/clingo/include/include.lp
@@ -0,0 +1 @@
+b(t).
diff --git a/examples/clingo/incqueens/README b/examples/clingo/incqueens/README
new file mode 100644
index 0000000..d47c441
--- /dev/null
+++ b/examples/clingo/incqueens/README
@@ -0,0 +1,7 @@
+Calculates solutions for the n-Queens problem for different board sizes, which
+can be given as a list of intervals on the command line.
+
+Example calls:
+    clingo incqueens.lp incqueens-py.lp -c calls="list((1,1),(3,5),(8,9))"
+    clingo incqueens.lp incqueens-lua.lp -c calls="list((1,1),(3,5),(8,9))"
+
diff --git a/examples/clingo/incqueens/incqueens-lua.lp b/examples/clingo/incqueens/incqueens-lua.lp
new file mode 100644
index 0000000..ee2739a
--- /dev/null
+++ b/examples/clingo/incqueens/incqueens-lua.lp
@@ -0,0 +1,20 @@
+#script(lua)
+function main(prg)
+    n = 0
+    parts = {}
+    for _, rng in pairs(prg:get_const("calls").arguments) do
+        lower = rng.arguments[1].number
+        upper = rng.arguments[2].number
+        while n < upper do
+            n = n + 1
+            parts[#parts+1] = {"board", {n}}
+            if n >= lower then
+                prg:ground(parts)
+                parts = {}
+                io.write(string.format('SIZE %d\n', n))
+                prg:solve()
+            end
+        end
+    end
+end
+#end.
diff --git a/examples/clingo/incqueens/incqueens-py.lp b/examples/clingo/incqueens/incqueens-py.lp
new file mode 100644
index 0000000..0427af8
--- /dev/null
+++ b/examples/clingo/incqueens/incqueens-py.lp
@@ -0,0 +1,18 @@
+#script(python)
+
+def main(prg):
+    n = 0
+    parts = []
+    for arg in prg.get_const("calls").arguments:
+        lower = arg.arguments[0].number
+        upper = arg.arguments[1].number
+        while n < upper:
+            n += 1
+            parts.append(("board", [n]))
+            if n >= lower:
+                prg.ground(parts)
+                parts = []
+                print 'SIZE {0}'.format(n)
+                prg.solve()
+
+#end.
diff --git a/examples/clingo/incqueens/incqueens.lp b/examples/clingo/incqueens/incqueens.lp
new file mode 100644
index 0000000..b504ba8
--- /dev/null
+++ b/examples/clingo/incqueens/incqueens.lp
@@ -0,0 +1,23 @@
+#show queen/2.
+
+#program board(n).
+#external attack(n,1..n,h).
+#external attack(1..n,n,v).
+
+target(n,  X,  X,  n,  b,n) :- X = 1..n-1.              % diagonal b
+target(Y,  n-1,n,  Y-1,b,n) :- Y = 2..n-1.              % diagonal b
+target(X,  n-1,X+1,n,  f,n) :- X = 1..n-1.              % diagonal f
+target(n-1,Y,  n,  Y+1,f,n) :- Y = 1..n-2.              % diagonal f
+target(X,  n,  X-1,n,  h,n) :- X = 2..n.                % horizontal
+target(n,  Y,  n-1,Y,  h,n) :- Y = 1..n-1.              % horizontal
+target(Y,  X,  Y,  X-1,v,n) :- target(X,Y,X-1,Y,h,n).   % vertical
+
+{ queen(1..n,n); queen(n,1..n-1) }.
+
+attack(X',Y',D) :- target(X,Y,X',Y',D,n), queen(X,Y).
+attack(X',Y',D) :- target(X,Y,X',Y',D,n), attack(X,Y,D).
+
+:- target(X,Y,X',Y',D,n), attack(X',Y',D), queen(X',Y').
+
+:- not queen(1,n), not attack(1,n,h).
+:- not queen(n,1), not attack(n,1,v).
diff --git a/examples/clingo/itersolve/README b/examples/clingo/itersolve/README
new file mode 100644
index 0000000..1daeede
--- /dev/null
+++ b/examples/clingo/itersolve/README
@@ -0,0 +1,5 @@
+This example shows how iterate over all models.
+
+Example calls:
+  clingo itersolve-py.lp program.lp 0 -q
+  clingo itersolve-lua.lp program.lp 0 -q
diff --git a/examples/clingo/itersolve/itersolve-lua.lp b/examples/clingo/itersolve/itersolve-lua.lp
new file mode 100644
index 0000000..0befb44
--- /dev/null
+++ b/examples/clingo/itersolve/itersolve-lua.lp
@@ -0,0 +1,19 @@
+#script(lua)
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    local it = prg:solve_iter()
+    local ret, err = pcall(function()
+        for m in it:iter() do
+            print(m)
+        end
+        local res = it:get()
+        print (res)
+    end)
+    it:close()
+    if not ret then
+        error(err)
+    end
+end
+
+#end.
diff --git a/examples/clingo/itersolve/itersolve-py.lp b/examples/clingo/itersolve/itersolve-py.lp
new file mode 100644
index 0000000..ebe0f4b
--- /dev/null
+++ b/examples/clingo/itersolve/itersolve-py.lp
@@ -0,0 +1,9 @@
+#script(python)
+
+def main(prg):
+    prg.ground([("base", [])])
+    with prg.solve_iter() as it:
+        for m in it: print m
+        print it.get()
+
+#end.
diff --git a/examples/clingo/itersolve/program.lp b/examples/clingo/itersolve/program.lp
new file mode 100644
index 0000000..82f0758
--- /dev/null
+++ b/examples/clingo/itersolve/program.lp
@@ -0,0 +1 @@
+{a;b;c}.
diff --git a/examples/clingo/load/README b/examples/clingo/load/README
new file mode 100644
index 0000000..957ac3c
--- /dev/null
+++ b/examples/clingo/load/README
@@ -0,0 +1,7 @@
+This example shows how to extend a logic program.
+
+Example Calls:
+    clingo load-py.lp
+    clingo load-lua.lp
+    gringo -t load-py.lp
+    gringo -t load-lua.lp
diff --git a/examples/clingo/load/load-lua.lp b/examples/clingo/load/load-lua.lp
new file mode 100644
index 0000000..759f73b
--- /dev/null
+++ b/examples/clingo/load/load-lua.lp
@@ -0,0 +1,16 @@
+#script(lua)
+
+function main(prg)
+    print(string.format("#const y=%s", tostring(prg:get_const("y"))))
+    prg:load("program.lp")
+    print(string.format("#const y=%s", tostring(prg:get_const("y"))))
+    print(string.format("#const x=%s", tostring(prg:get_const("x"))))
+    prg:add("base", {}, "#const x=10. b.")
+    print(string.format("#const x=%s", tostring(prg:get_const("x"))))
+    prg:ground({{"base", {}}})
+    prg:solve()
+end
+
+#end.
+
+c.
diff --git a/examples/clingo/load/load-py.lp b/examples/clingo/load/load-py.lp
new file mode 100644
index 0000000..04ee212
--- /dev/null
+++ b/examples/clingo/load/load-py.lp
@@ -0,0 +1,15 @@
+#script(python)
+
+def main(prg):
+    print("#const y={0}".format(prg.get_const("y")))
+    prg.load("program.lp")
+    print("#const y={0}".format(prg.get_const("y")))
+    print("#const x={0}".format(prg.get_const("x")))
+    prg.add("base", [], "#const x=10. b.")
+    print("#const x={0}".format(prg.get_const("x")))
+    prg.ground([("base", [])])
+    prg.solve()
+
+#end.
+
+c.
diff --git a/examples/clingo/load/program.lp b/examples/clingo/load/program.lp
new file mode 100644
index 0000000..6918d81
--- /dev/null
+++ b/examples/clingo/load/program.lp
@@ -0,0 +1,3 @@
+#const y = 42.
+#program base.
+a.
diff --git a/examples/clingo/onmodel/README b/examples/clingo/onmodel/README
new file mode 100644
index 0000000..93c86c2
--- /dev/null
+++ b/examples/clingo/onmodel/README
@@ -0,0 +1,9 @@
+This example shows how to use the atoms method to inspect a model found by
+clasp.  You can inspect the answer set as well as the assignment that lead to
+the model.  Note that there are no guarantees regarding atoms not part of an
+answer set because due to simplifications some of them might be removed from
+the assignment altogether.
+
+Example calls:
+    clingo onmodel-py.lp
+    clingo onmodel-lua.lp
diff --git a/examples/clingo/onmodel/onmodel-lua.lp b/examples/clingo/onmodel/onmodel-lua.lp
new file mode 100644
index 0000000..4774a7d
--- /dev/null
+++ b/examples/clingo/onmodel/onmodel-lua.lp
@@ -0,0 +1,42 @@
+#script (lua)
+
+function tostringTable(t) 
+    ret   = ""
+    comma = False
+    for _, elem in pairs(t) do
+        if comma then ret = ret .. ", "
+        else          comma = true 
+        end
+        ret = ret .. tostring(elem)
+    end
+    return ret
+end
+
+function main(prg)
+    on_model = function (m)
+        print("shown")
+        print("  positive: " .. tostringTable(m:symbols{shown=true}))
+        print("  negative: " .. tostringTable(m:symbols{shown=true, complement=true}))
+        print("csp")
+        print("  positive: " .. tostringTable(m:symbols{csp=true}))
+        print("  negative: " .. tostringTable(m:symbols{csp=true, complement=true}))
+        print("atoms")
+        print("  positive: " .. tostringTable(m:symbols{atoms=true}))
+        print("  negative: " .. tostringTable(m:symbols{atoms=true, complement=true}))
+        print("terms")
+        print("  positive: " .. tostringTable(m:symbols{terms=true}))
+        print("  negative: " .. tostringTable(m:symbols{terms=true, complement=true}))
+    end
+    prg:ground({{"base", {}}})
+    prg:solve(on_model)
+end
+
+#end.
+
+{a}.
+b :- a.
+$x $= 1.
+$y $= 2.
+#show c : a.
+#show b/0.
+#show $x/0.
diff --git a/examples/clingo/onmodel/onmodel-py.lp b/examples/clingo/onmodel/onmodel-py.lp
new file mode 100644
index 0000000..5da7d16
--- /dev/null
+++ b/examples/clingo/onmodel/onmodel-py.lp
@@ -0,0 +1,31 @@
+#script (python)
+
+import clingo
+
+def main(prg):
+    def on_model(m):
+        print "shown"
+        print "  positive:", ", ".join(map(str, m.symbols(shown=True)))
+        print "  negative:", ", ".join(map(str, m.symbols(shown=True, complement=True)))
+        print "csp"
+        print "  positive:", ", ".join(map(str, m.symbols(csp=True)))
+        print "  negative:", ", ".join(map(str, m.symbols(csp=True, complement=True)))
+        print "atoms"
+        print "  positive:", ", ".join(map(str, m.symbols(atoms=True)))
+        print "  negative:", ", ".join(map(str, m.symbols(atoms=True, complement=True)))
+        print "terms"
+        print "  positive:", ", ".join(map(str, m.symbols(terms=True)))
+        print "  negative:", ", ".join(map(str, m.symbols(terms=True, complement=True)))
+
+    prg.ground([("base", [])])
+    prg.solve(on_model = on_model)
+
+#end.
+
+{a}.
+b :- a.
+$x $= 1.
+$y $= 2.
+#show c : a.
+#show b/0.
+#show $x/0.
diff --git a/examples/clingo/planning/README b/examples/clingo/planning/README
new file mode 100644
index 0000000..dd6d718
--- /dev/null
+++ b/examples/clingo/planning/README
@@ -0,0 +1,6 @@
+This example shows how to solve a conformant planning problem. Note that this
+is a disjunctive encoding.
+
+Example calls:
+    clingo planning-lua.lp encoding.lp instances/coins01.lp
+    clingo planning-lua.lp encoding.lp instances/comm02.lp
diff --git a/examples/clingo/planning/convert.lp b/examples/clingo/planning/convert.lp
new file mode 100644
index 0000000..edd658b
--- /dev/null
+++ b/examples/clingo/planning/convert.lp
@@ -0,0 +1,28 @@
+f(lit(F, 1),F)      :- fluent(F).
+f(lit(F,-1),neg(F)) :- fluent(F).
+
+_action(A)              :- action(A).
+_fluent(A)              :- fluent(A).
+_executable(A,M)        :- executable(A,L), f(M,L).
+_effect(A,M,G)          :- effect(A,L,G), f(M,L).
+_condition(A,M,N)       :- condition(A,L,N), f(M,L).
+_initially(M)           :- initially(L), f(M,L).
+_initially_oneof(G,M,B) :- initially_oneof(G,L,B), f(M,L).
+_goal(M)                :- goal(L), f(M,L).
+_goal_or(M,N)           :- goal_or(L,N,_), f(M,L).
+
+complement(F,lit(F,1),lit(F,-1)) :- fluent(F).
+
+{ _holds_initially(F) } :- complement(F,L,M), not _initially(L;M).
+  _holds_initially(F)   :- _initially(L), complement(F,L,M).
+
+holds_oneof(N,B)  :- 
+    _initially_oneof(N,_,B);
+    not _holds_initially(F) : _initially_oneof(N,M,B), complement(F,L,M);
+        _holds_initially(F) : _initially_oneof(N,L,B), complement(F,L,M).
+
+ :- _initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1.
+ % just bizarre!
+ :- not _holds_initially(F), _initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M).
+ :-     _holds_initially(F), _initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M).
+
diff --git a/examples/clingo/planning/convert.sh b/examples/clingo/planning/convert.sh
new file mode 100755
index 0000000..63dc17b
--- /dev/null
+++ b/examples/clingo/planning/convert.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+clingo --ifs="\n" "$@" convert.lp | grep "^_" | sed -e 's/$/./' -e 's/^_//'
diff --git a/examples/clingo/planning/encoding.lp b/examples/clingo/planning/encoding.lp
new file mode 100644
index 0000000..3855a1f
--- /dev/null
+++ b/examples/clingo/planning/encoding.lp
@@ -0,0 +1,90 @@
+#program warnings. % silence warnings
+
+goal_or(0,(0;neg(0))) :- #false.
+
+#program base.
+
+lit(lit(F, 1)) :- fluent(F).
+lit(lit(F,-1)) :- fluent(F).
+
+complement(F,lit(F,1),lit(F,-1)) :- fluent(F).
+complement(L,M;M,L) :- complement(F,L,M).
+
+fluent((L;M),F) :- complement(F,L,M).
+
+contradict(F)  :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2),
+                  #false : condition(A,M,N1), condition(A,L,N2), complement(L,M).
+
+holds(F,0) :- holds_initially(F).
+
+#program trans(t).
+
+1 { occurs(A,t) : action(A) } 1.
+ :- occurs(A,t), executable(A,L), not holds(F,t-1), complement(F,L,M).
+ :- occurs(A,t), executable(A,M),     holds(F,t-1), complement(F,L,M).
+
+holds(L,t) :- occurs(A,t), effect(A,L,N), holds(C,t-1) : condition(A,C,N).
+holds(L,t) :- holds(L,t-1), complement(L,M), not holds(M,t).
+ :- contradict(F), complement(F,L,M), holds((L;M),t).
+
+caused(L,t) :- occurs(A,t), effect(A,L,N), 
+               not holds(F',t-1) : condition(A,M',N), complement(F',L',M');
+                   holds(F',t-1) : condition(A,L',N), complement(F',L',M').
+holds(F,t) :- caused(L,t), complement(F,L,M).
+holds(F,t) :- holds(F,t-1), complement(F,L,M), not caused(M,t).
+ :- caused((L;M),t), contradict(F), complement(F,L,M).
+
+#program state(t).
+#external vol(t).
+
+ :- goal_or(N,_);
+    not holds(F,t) : goal_or(N,L), complement(F,L,M);
+        holds(F,t) : goal_or(N,M), complement(F,L,M);
+    vol(t).
+ :- goal(L), not holds(F,t), complement(F,L,M), vol(t).
+ :- goal(M),     holds(F,t), complement(F,L,M), vol(t).
+
+#program check(t).
+
+%%%%%%% base
+
+alt_holds(L,0,t); alt_holds(M,0,t) :- complement(F,L,M), not initially(L;M), vol(t).
+alt_holds(L,0,t) :- initially(L), vol(t).
+
+pos_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,_,B),                  alt_holds(L,0,t) : initially_oneof(N,L,B).
+not_holds_oneof(N,B,t) :- vol(t), initially_oneof(N,L,B), complement(L,M), alt_holds(M,0,t).
+
+bottom(t) :- vol(t), initially_oneof(N,_,_), 2 { pos_holds_oneof(N,B,t) : initially_oneof(N,_,B) }.
+bottom(t) :- vol(t), initially_oneof(N,_,_),     not_holds_oneof(N,B,t) : initially_oneof(N,_,B).
+bottom(t) :- alt_holds(L,0,t), initially_oneof(N,L,B), not_holds_oneof(N,B,t); vol(t).
+
+%%%%%%% transition
+
+not_condition(A,N,T,t) :- condition(A,C,N), complement(C,D), alt_holds(D,T-1,t), vol(t).
+not_caused(L,T,t)      :- occurs(A,T), lit(L), not_condition(A,N,T,t) : effect(A,L,N); vol(t).
+
+alt_holds(L,T,t) :- occurs(A,T), effect(A,L,N), alt_holds(C,T-1,t) : condition(A,C,N); vol(t).
+alt_holds(L,T,t) :- alt_holds(L,T-1,t), not_caused(M,T,t), complement(L,M), vol(t).
+
+%%%%%%% state
+
+not_contradict(F,T,t) :- contradict(F), fluent(L,F), not_caused(L,T,t), vol(t).
+pos_executable(T,t)   :- occurs(A,T), alt_holds(C,T-1,t) : executable(A,C), C != true; vol(t).
+pos_goal_or(N,t) :- goal_or(N,L), alt_holds(L,t,t), vol(t).
+pos_goal_or(N,t) :- goal_or(N,L), goal(L), vol(t).
+
+bottom(t) :- pos_goal_or(N,t)      : goal_or(N,_); 
+             alt_holds(L,t,t)      : goal(L);
+             pos_executable(R,t)   : R = 1..t; 
+             not_contradict(F,S,t) : contradict(F), S = 1..t;
+             vol(t).
+
+%%%%%%% saturation
+
+alt_holds((L;M),0,t) :- bottom(t), complement(F,L,M), not initially(L;M), vol(t).
+
+:- not bottom(t), vol(t).
+
+#show occurs/2.
+
+#program base.
diff --git a/examples/clingo/planning/instances/coins01.lp b/examples/clingo/planning/instances/coins01.lp
new file mode 100644
index 0000000..ce4261e
--- /dev/null
+++ b/examples/clingo/planning/instances/coins01.lp
@@ -0,0 +1,139 @@
+action(cpa_collect(cpa_c0,cpa_f0,cpa_p0)).
+action(cpa_collect(cpa_c0,cpa_f0,cpa_p1)).
+action(cpa_collect(cpa_c0,cpa_f1,cpa_p0)).
+action(cpa_collect(cpa_c0,cpa_f1,cpa_p1)).
+action(cpa_collect(cpa_c1,cpa_f0,cpa_p0)).
+action(cpa_collect(cpa_c1,cpa_f0,cpa_p1)).
+action(cpa_collect(cpa_c1,cpa_f1,cpa_p0)).
+action(cpa_collect(cpa_c1,cpa_f1,cpa_p1)).
+action(cpa_go_down(cpa_e0,cpa_f1,cpa_f0)).
+action(cpa_go_down(cpa_e1,cpa_f1,cpa_f0)).
+action(cpa_go_up(cpa_e0,cpa_f0,cpa_f1)).
+action(cpa_go_up(cpa_e1,cpa_f0,cpa_f1)).
+action(cpa_move_left(cpa_f0,cpa_p1,cpa_p0)).
+action(cpa_move_left(cpa_f1,cpa_p1,cpa_p0)).
+action(cpa_move_right(cpa_f0,cpa_p0,cpa_p1)).
+action(cpa_move_right(cpa_f1,cpa_p0,cpa_p1)).
+action(cpa_step_in(cpa_e0,cpa_f0,cpa_p0)).
+action(cpa_step_in(cpa_e0,cpa_f1,cpa_p0)).
+action(cpa_step_in(cpa_e1,cpa_f0,cpa_p1)).
+action(cpa_step_in(cpa_e1,cpa_f1,cpa_p1)).
+action(cpa_step_out(cpa_e0,cpa_f0,cpa_p0)).
+action(cpa_step_out(cpa_e0,cpa_f1,cpa_p0)).
+action(cpa_step_out(cpa_e1,cpa_f0,cpa_p1)).
+action(cpa_step_out(cpa_e1,cpa_f1,cpa_p1)).
+fluent(cpa_at(cpa_f1,cpa_p1)).
+fluent(cpa_inside(cpa_e1)).
+fluent(cpa_at(cpa_f1,cpa_p0)).
+fluent(cpa_have(cpa_c0)).
+fluent(cpa_have(cpa_c1)).
+fluent(cpa_at(cpa_f0,cpa_p1)).
+fluent(cpa_inside(cpa_e0)).
+fluent(cpa_at(cpa_f0,cpa_p0)).
+fluent(cpa_in(cpa_e0,cpa_f0)).
+fluent(cpa_in(cpa_e0,cpa_f1)).
+fluent(cpa_in(cpa_e1,cpa_f0)).
+fluent(cpa_in(cpa_e1,cpa_f1)).
+fluent(cpa_coin_at(cpa_c0,cpa_f1,cpa_p0)).
+fluent(cpa_coin_at(cpa_c0,cpa_f1,cpa_p1)).
+fluent(cpa_coin_at(cpa_c1,cpa_f1,cpa_p0)).
+fluent(cpa_coin_at(cpa_c1,cpa_f1,cpa_p1)).
+executable(cpa_collect(cpa_c0,cpa_f0,cpa_p0),lit(cpa_at(cpa_f0,cpa_p0),1)).
+executable(cpa_collect(cpa_c0,cpa_f0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p1),1)).
+executable(cpa_collect(cpa_c0,cpa_f1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p0),1)).
+executable(cpa_collect(cpa_c0,cpa_f1,cpa_p1),lit(cpa_at(cpa_f1,cpa_p1),1)).
+executable(cpa_collect(cpa_c1,cpa_f0,cpa_p0),lit(cpa_at(cpa_f0,cpa_p0),1)).
+executable(cpa_collect(cpa_c1,cpa_f0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p1),1)).
+executable(cpa_collect(cpa_c1,cpa_f1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p0),1)).
+executable(cpa_collect(cpa_c1,cpa_f1,cpa_p1),lit(cpa_at(cpa_f1,cpa_p1),1)).
+executable(cpa_move_left(cpa_f0,cpa_p1,cpa_p0),lit(cpa_at(cpa_f0,cpa_p1),1)).
+executable(cpa_move_left(cpa_f1,cpa_p1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p1),1)).
+executable(cpa_move_right(cpa_f0,cpa_p0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p0),1)).
+executable(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),lit(cpa_at(cpa_f1,cpa_p0),1)).
+executable(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),lit(cpa_at(cpa_f0,cpa_p0),1)).
+executable(cpa_step_in(cpa_e0,cpa_f1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p0),1)).
+executable(cpa_step_in(cpa_e1,cpa_f0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p1),1)).
+executable(cpa_step_in(cpa_e1,cpa_f1,cpa_p1),lit(cpa_at(cpa_f1,cpa_p1),1)).
+executable(cpa_step_out(cpa_e0,cpa_f0,cpa_p0),lit(cpa_inside(cpa_e0),1)).
+executable(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),lit(cpa_inside(cpa_e0),1)).
+executable(cpa_step_out(cpa_e1,cpa_f0,cpa_p1),lit(cpa_inside(cpa_e1),1)).
+executable(cpa_step_out(cpa_e1,cpa_f1,cpa_p1),lit(cpa_inside(cpa_e1),1)).
+effect(cpa_collect(cpa_c0,cpa_f1,cpa_p0),lit(cpa_have(cpa_c0),1),1).
+effect(cpa_collect(cpa_c0,cpa_f1,cpa_p0),lit(cpa_coin_at(cpa_c0,cpa_f1,cpa_p0),-1),1).
+effect(cpa_collect(cpa_c0,cpa_f1,cpa_p1),lit(cpa_have(cpa_c0),1),1).
+effect(cpa_collect(cpa_c0,cpa_f1,cpa_p1),lit(cpa_coin_at(cpa_c0,cpa_f1,cpa_p1),-1),1).
+effect(cpa_collect(cpa_c1,cpa_f1,cpa_p0),lit(cpa_have(cpa_c1),1),1).
+effect(cpa_collect(cpa_c1,cpa_f1,cpa_p0),lit(cpa_coin_at(cpa_c1,cpa_f1,cpa_p0),-1),1).
+effect(cpa_collect(cpa_c1,cpa_f1,cpa_p1),lit(cpa_have(cpa_c1),1),1).
+effect(cpa_collect(cpa_c1,cpa_f1,cpa_p1),lit(cpa_coin_at(cpa_c1,cpa_f1,cpa_p1),-1),1).
+effect(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),lit(cpa_in(cpa_e0,cpa_f0),1),1).
+effect(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),lit(cpa_in(cpa_e0,cpa_f1),-1),1).
+effect(cpa_go_down(cpa_e1,cpa_f1,cpa_f0),lit(cpa_in(cpa_e1,cpa_f0),1),1).
+effect(cpa_go_down(cpa_e1,cpa_f1,cpa_f0),lit(cpa_in(cpa_e1,cpa_f1),-1),1).
+effect(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),lit(cpa_in(cpa_e0,cpa_f1),1),1).
+effect(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),lit(cpa_in(cpa_e0,cpa_f0),-1),1).
+effect(cpa_go_up(cpa_e1,cpa_f0,cpa_f1),lit(cpa_in(cpa_e1,cpa_f1),1),1).
+effect(cpa_go_up(cpa_e1,cpa_f0,cpa_f1),lit(cpa_in(cpa_e1,cpa_f0),-1),1).
+effect(cpa_move_left(cpa_f0,cpa_p1,cpa_p0),lit(cpa_at(cpa_f0,cpa_p1),-1),1).
+effect(cpa_move_left(cpa_f0,cpa_p1,cpa_p0),lit(cpa_at(cpa_f0,cpa_p0),1),1).
+effect(cpa_move_left(cpa_f1,cpa_p1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p1),-1),1).
+effect(cpa_move_left(cpa_f1,cpa_p1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p0),1),1).
+effect(cpa_move_right(cpa_f0,cpa_p0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p0),-1),1).
+effect(cpa_move_right(cpa_f0,cpa_p0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p1),1),1).
+effect(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),lit(cpa_at(cpa_f1,cpa_p0),-1),1).
+effect(cpa_move_right(cpa_f1,cpa_p0,cpa_p1),lit(cpa_at(cpa_f1,cpa_p1),1),1).
+effect(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),lit(cpa_inside(cpa_e0),1),1).
+effect(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),lit(cpa_at(cpa_f0,cpa_p0),-1),1).
+effect(cpa_step_in(cpa_e0,cpa_f1,cpa_p0),lit(cpa_inside(cpa_e0),1),1).
+effect(cpa_step_in(cpa_e0,cpa_f1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p0),-1),1).
+effect(cpa_step_in(cpa_e1,cpa_f0,cpa_p1),lit(cpa_inside(cpa_e1),1),1).
+effect(cpa_step_in(cpa_e1,cpa_f0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p1),-1),1).
+effect(cpa_step_in(cpa_e1,cpa_f1,cpa_p1),lit(cpa_inside(cpa_e1),1),1).
+effect(cpa_step_in(cpa_e1,cpa_f1,cpa_p1),lit(cpa_at(cpa_f1,cpa_p1),-1),1).
+effect(cpa_step_out(cpa_e0,cpa_f0,cpa_p0),lit(cpa_at(cpa_f0,cpa_p0),1),1).
+effect(cpa_step_out(cpa_e0,cpa_f0,cpa_p0),lit(cpa_inside(cpa_e0),-1),1).
+effect(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),lit(cpa_at(cpa_f1,cpa_p0),1),1).
+effect(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),lit(cpa_inside(cpa_e0),-1),1).
+effect(cpa_step_out(cpa_e1,cpa_f0,cpa_p1),lit(cpa_at(cpa_f0,cpa_p1),1),1).
+effect(cpa_step_out(cpa_e1,cpa_f0,cpa_p1),lit(cpa_inside(cpa_e1),-1),1).
+effect(cpa_step_out(cpa_e1,cpa_f1,cpa_p1),lit(cpa_at(cpa_f1,cpa_p1),1),1).
+effect(cpa_step_out(cpa_e1,cpa_f1,cpa_p1),lit(cpa_inside(cpa_e1),-1),1).
+condition(cpa_collect(cpa_c0,cpa_f1,cpa_p0),lit(cpa_coin_at(cpa_c0,cpa_f1,cpa_p0),1),1).
+condition(cpa_collect(cpa_c0,cpa_f1,cpa_p1),lit(cpa_coin_at(cpa_c0,cpa_f1,cpa_p1),1),1).
+condition(cpa_collect(cpa_c1,cpa_f1,cpa_p0),lit(cpa_coin_at(cpa_c1,cpa_f1,cpa_p0),1),1).
+condition(cpa_collect(cpa_c1,cpa_f1,cpa_p1),lit(cpa_coin_at(cpa_c1,cpa_f1,cpa_p1),1),1).
+condition(cpa_go_down(cpa_e0,cpa_f1,cpa_f0),lit(cpa_in(cpa_e0,cpa_f1),1),1).
+condition(cpa_go_down(cpa_e1,cpa_f1,cpa_f0),lit(cpa_in(cpa_e1,cpa_f1),1),1).
+condition(cpa_go_up(cpa_e0,cpa_f0,cpa_f1),lit(cpa_in(cpa_e0,cpa_f0),1),1).
+condition(cpa_go_up(cpa_e1,cpa_f0,cpa_f1),lit(cpa_in(cpa_e1,cpa_f0),1),1).
+condition(cpa_step_in(cpa_e0,cpa_f0,cpa_p0),lit(cpa_in(cpa_e0,cpa_f0),1),1).
+condition(cpa_step_in(cpa_e0,cpa_f1,cpa_p0),lit(cpa_in(cpa_e0,cpa_f1),1),1).
+condition(cpa_step_in(cpa_e1,cpa_f0,cpa_p1),lit(cpa_in(cpa_e1,cpa_f0),1),1).
+condition(cpa_step_in(cpa_e1,cpa_f1,cpa_p1),lit(cpa_in(cpa_e1,cpa_f1),1),1).
+condition(cpa_step_out(cpa_e0,cpa_f0,cpa_p0),lit(cpa_in(cpa_e0,cpa_f0),1),1).
+condition(cpa_step_out(cpa_e0,cpa_f1,cpa_p0),lit(cpa_in(cpa_e0,cpa_f1),1),1).
+condition(cpa_step_out(cpa_e1,cpa_f0,cpa_p1),lit(cpa_in(cpa_e1,cpa_f0),1),1).
+condition(cpa_step_out(cpa_e1,cpa_f1,cpa_p1),lit(cpa_in(cpa_e1,cpa_f1),1),1).
+initially(lit(cpa_at(cpa_f0,cpa_p0),1)).
+initially(lit(cpa_at(cpa_f1,cpa_p1),-1)).
+initially(lit(cpa_inside(cpa_e1),-1)).
+initially(lit(cpa_at(cpa_f1,cpa_p0),-1)).
+initially(lit(cpa_have(cpa_c0),-1)).
+initially(lit(cpa_have(cpa_c1),-1)).
+initially(lit(cpa_at(cpa_f0,cpa_p1),-1)).
+initially(lit(cpa_inside(cpa_e0),-1)).
+initially_oneof(1,lit(cpa_in(cpa_e0,cpa_f0),1),1).
+initially_oneof(1,lit(cpa_in(cpa_e0,cpa_f1),1),2).
+initially_oneof(2,lit(cpa_in(cpa_e1,cpa_f0),1),1).
+initially_oneof(2,lit(cpa_in(cpa_e1,cpa_f1),1),2).
+initially_oneof(3,lit(cpa_coin_at(cpa_c0,cpa_f1,cpa_p0),1),1).
+initially_oneof(3,lit(cpa_coin_at(cpa_c1,cpa_f1,cpa_p0),1),1).
+initially_oneof(3,lit(cpa_coin_at(cpa_c0,cpa_f1,cpa_p1),1),2).
+initially_oneof(3,lit(cpa_coin_at(cpa_c1,cpa_f1,cpa_p1),1),2).
+goal(lit(cpa_have(cpa_c0),1)).
+goal(lit(cpa_have(cpa_c1),1)).
+holds_initially(cpa_at(cpa_f0,cpa_p0)).
+holds_initially(cpa_in(cpa_e0,cpa_f1)).
+holds_initially(cpa_in(cpa_e1,cpa_f1)).
+holds_initially(cpa_coin_at(cpa_c0,cpa_f1,cpa_p0)).
+holds_initially(cpa_coin_at(cpa_c1,cpa_f1,cpa_p0)).
diff --git a/examples/clingo/planning/instances/comm02.lp b/examples/clingo/planning/instances/comm02.lp
new file mode 100644
index 0000000..cc7b009
--- /dev/null
+++ b/examples/clingo/planning/instances/comm02.lp
@@ -0,0 +1,179 @@
+action(cpa_certify(cpa_p0)).
+action(cpa_certify(cpa_p1)).
+action(cpa_certify(cpa_p2)).
+action(cpa_reset(cpa_s1)).
+action(cpa_reset(cpa_s2)).
+action(cpa_reset(cpa_s3)).
+action(cpa_reset(cpa_s4)).
+action(cpa_reset(cpa_s5)).
+action(cpa_advance(cpa_s0,cpa_s1)).
+action(cpa_advance(cpa_s1,cpa_s2)).
+action(cpa_advance(cpa_s2,cpa_s3)).
+action(cpa_advance(cpa_s3,cpa_s4)).
+action(cpa_advance(cpa_s4,cpa_s5)).
+action(cpa_obtain(cpa_p0,cpa_s0)).
+action(cpa_obtain(cpa_p1,cpa_s1)).
+action(cpa_obtain(cpa_p2,cpa_s2)).
+action(cpa_request_copy(cpa_p0,cpa_s0)).
+action(cpa_request_copy(cpa_p0,cpa_s1)).
+action(cpa_request_copy(cpa_p0,cpa_s2)).
+action(cpa_request_copy(cpa_p0,cpa_s3)).
+action(cpa_request_copy(cpa_p0,cpa_s4)).
+action(cpa_request_copy(cpa_p0,cpa_s5)).
+action(cpa_request_copy(cpa_p1,cpa_s0)).
+action(cpa_request_copy(cpa_p1,cpa_s1)).
+action(cpa_request_copy(cpa_p1,cpa_s2)).
+action(cpa_request_copy(cpa_p1,cpa_s3)).
+action(cpa_request_copy(cpa_p1,cpa_s4)).
+action(cpa_request_copy(cpa_p1,cpa_s5)).
+action(cpa_request_copy(cpa_p2,cpa_s0)).
+action(cpa_request_copy(cpa_p2,cpa_s1)).
+action(cpa_request_copy(cpa_p2,cpa_s2)).
+action(cpa_request_copy(cpa_p2,cpa_s3)).
+action(cpa_request_copy(cpa_p2,cpa_s4)).
+action(cpa_request_copy(cpa_p2,cpa_s5)).
+fluent(cpa_current_stage(cpa_s5)).
+fluent(cpa_bad(cpa_p2)).
+fluent(cpa_ok(cpa_p2)).
+fluent(cpa_current_stage(cpa_s4)).
+fluent(cpa_bad(cpa_p1)).
+fluent(cpa_ok(cpa_p1)).
+fluent(cpa_current_stage(cpa_s3)).
+fluent(cpa_read(cpa_p2)).
+fluent(cpa_bad(cpa_p0)).
+fluent(cpa_ok(cpa_p0)).
+fluent(cpa_current_stage(cpa_s2)).
+fluent(cpa_read(cpa_p1)).
+fluent(cpa_current_stage(cpa_s1)).
+fluent(cpa_read(cpa_p0)).
+fluent(cpa_current_stage(cpa_s0)).
+fluent(cpa_in_channel(cpa_p0)).
+fluent(cpa_in_channel(cpa_p1)).
+fluent(cpa_in_channel(cpa_p2)).
+fluent(cpa_noisy(cpa_p0)).
+fluent(cpa_noisy(cpa_p1)).
+fluent(cpa_noisy(cpa_p2)).
+executable(cpa_certify(cpa_p0),lit(cpa_read(cpa_p0),1)).
+executable(cpa_certify(cpa_p1),lit(cpa_read(cpa_p1),1)).
+executable(cpa_certify(cpa_p2),lit(cpa_read(cpa_p2),1)).
+executable(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+effect(cpa_certify(cpa_p0),lit(cpa_bad(cpa_p0),1),1).
+effect(cpa_certify(cpa_p0),lit(cpa_ok(cpa_p0),1),2).
+effect(cpa_certify(cpa_p1),lit(cpa_bad(cpa_p1),1),1).
+effect(cpa_certify(cpa_p1),lit(cpa_ok(cpa_p1),1),2).
+effect(cpa_certify(cpa_p2),lit(cpa_bad(cpa_p2),1),1).
+effect(cpa_certify(cpa_p2),lit(cpa_ok(cpa_p2),1),2).
+effect(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s1),-1),1).
+effect(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s2),-1),1).
+effect(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s3),-1),1).
+effect(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s4),-1),1).
+effect(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s5),-1),1).
+effect(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s1),1),1).
+effect(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s0),-1),1).
+effect(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s2),1),1).
+effect(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s1),-1),1).
+effect(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s3),1),1).
+effect(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s2),-1),1).
+effect(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s4),1),1).
+effect(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s3),-1),1).
+effect(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s5),1),1).
+effect(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s4),-1),1).
+effect(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),-1),1).
+effect(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_read(cpa_p0),1),1).
+effect(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),-1),1).
+effect(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_read(cpa_p1),1),1).
+effect(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),-1),1).
+effect(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_read(cpa_p2),1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_read(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_noisy(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_bad(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_read(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_noisy(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_bad(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_read(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_noisy(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_bad(cpa_p2),-1),1).
+condition(cpa_certify(cpa_p0),lit(cpa_noisy(cpa_p0),1),1).
+condition(cpa_certify(cpa_p0),lit(cpa_noisy(cpa_p0),-1),2).
+condition(cpa_certify(cpa_p1),lit(cpa_noisy(cpa_p1),1),1).
+condition(cpa_certify(cpa_p1),lit(cpa_noisy(cpa_p1),-1),2).
+condition(cpa_certify(cpa_p2),lit(cpa_noisy(cpa_p2),1),1).
+condition(cpa_certify(cpa_p2),lit(cpa_noisy(cpa_p2),-1),2).
+condition(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),1),1).
+condition(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),1),1).
+condition(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),1),1).
+condition(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_bad(cpa_p0),1),1).
+condition(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_bad(cpa_p1),1),1).
+condition(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_bad(cpa_p2),1),1).
+initially(lit(cpa_current_stage(cpa_s0),1)).
+initially(lit(cpa_in_channel(cpa_p0),1)).
+initially(lit(cpa_in_channel(cpa_p1),1)).
+initially(lit(cpa_in_channel(cpa_p2),1)).
+initially(lit(cpa_current_stage(cpa_s5),-1)).
+initially(lit(cpa_bad(cpa_p2),-1)).
+initially(lit(cpa_ok(cpa_p2),-1)).
+initially(lit(cpa_current_stage(cpa_s4),-1)).
+initially(lit(cpa_bad(cpa_p1),-1)).
+initially(lit(cpa_ok(cpa_p1),-1)).
+initially(lit(cpa_current_stage(cpa_s3),-1)).
+initially(lit(cpa_read(cpa_p2),-1)).
+initially(lit(cpa_bad(cpa_p0),-1)).
+initially(lit(cpa_ok(cpa_p0),-1)).
+initially(lit(cpa_current_stage(cpa_s2),-1)).
+initially(lit(cpa_read(cpa_p1),-1)).
+initially(lit(cpa_current_stage(cpa_s1),-1)).
+initially(lit(cpa_read(cpa_p0),-1)).
+initially_oneof(1,lit(cpa_noisy(cpa_p0),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p2),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p1),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p0),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p2),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p1),-1),2).
+goal(lit(cpa_ok(cpa_p0),1)).
+goal(lit(cpa_ok(cpa_p1),1)).
+goal(lit(cpa_ok(cpa_p2),1)).
+holds_initially(cpa_current_stage(cpa_s0)).
+holds_initially(cpa_in_channel(cpa_p0)).
+holds_initially(cpa_in_channel(cpa_p1)).
+holds_initially(cpa_in_channel(cpa_p2)).
+holds_initially(cpa_noisy(cpa_p0)).
+holds_initially(cpa_noisy(cpa_p2)).
+holds_initially(cpa_noisy(cpa_p1)).
diff --git a/examples/clingo/planning/instances/comm03.lp b/examples/clingo/planning/instances/comm03.lp
new file mode 100644
index 0000000..fc0ea41
--- /dev/null
+++ b/examples/clingo/planning/instances/comm03.lp
@@ -0,0 +1,239 @@
+action(cpa_certify(cpa_p0)).
+action(cpa_certify(cpa_p1)).
+action(cpa_certify(cpa_p2)).
+action(cpa_certify(cpa_p3)).
+action(cpa_reset(cpa_s1)).
+action(cpa_reset(cpa_s2)).
+action(cpa_reset(cpa_s3)).
+action(cpa_reset(cpa_s4)).
+action(cpa_reset(cpa_s5)).
+action(cpa_reset(cpa_s6)).
+action(cpa_advance(cpa_s0,cpa_s1)).
+action(cpa_advance(cpa_s1,cpa_s2)).
+action(cpa_advance(cpa_s2,cpa_s3)).
+action(cpa_advance(cpa_s3,cpa_s4)).
+action(cpa_advance(cpa_s4,cpa_s5)).
+action(cpa_advance(cpa_s5,cpa_s6)).
+action(cpa_obtain(cpa_p0,cpa_s0)).
+action(cpa_obtain(cpa_p1,cpa_s1)).
+action(cpa_obtain(cpa_p2,cpa_s2)).
+action(cpa_obtain(cpa_p3,cpa_s3)).
+action(cpa_request_copy(cpa_p0,cpa_s0)).
+action(cpa_request_copy(cpa_p0,cpa_s1)).
+action(cpa_request_copy(cpa_p0,cpa_s2)).
+action(cpa_request_copy(cpa_p0,cpa_s3)).
+action(cpa_request_copy(cpa_p0,cpa_s4)).
+action(cpa_request_copy(cpa_p0,cpa_s5)).
+action(cpa_request_copy(cpa_p0,cpa_s6)).
+action(cpa_request_copy(cpa_p1,cpa_s0)).
+action(cpa_request_copy(cpa_p1,cpa_s1)).
+action(cpa_request_copy(cpa_p1,cpa_s2)).
+action(cpa_request_copy(cpa_p1,cpa_s3)).
+action(cpa_request_copy(cpa_p1,cpa_s4)).
+action(cpa_request_copy(cpa_p1,cpa_s5)).
+action(cpa_request_copy(cpa_p1,cpa_s6)).
+action(cpa_request_copy(cpa_p2,cpa_s0)).
+action(cpa_request_copy(cpa_p2,cpa_s1)).
+action(cpa_request_copy(cpa_p2,cpa_s2)).
+action(cpa_request_copy(cpa_p2,cpa_s3)).
+action(cpa_request_copy(cpa_p2,cpa_s4)).
+action(cpa_request_copy(cpa_p2,cpa_s5)).
+action(cpa_request_copy(cpa_p2,cpa_s6)).
+action(cpa_request_copy(cpa_p3,cpa_s0)).
+action(cpa_request_copy(cpa_p3,cpa_s1)).
+action(cpa_request_copy(cpa_p3,cpa_s2)).
+action(cpa_request_copy(cpa_p3,cpa_s3)).
+action(cpa_request_copy(cpa_p3,cpa_s4)).
+action(cpa_request_copy(cpa_p3,cpa_s5)).
+action(cpa_request_copy(cpa_p3,cpa_s6)).
+fluent(cpa_current_stage(cpa_s6)).
+fluent(cpa_bad(cpa_p3)).
+fluent(cpa_ok(cpa_p3)).
+fluent(cpa_current_stage(cpa_s5)).
+fluent(cpa_bad(cpa_p2)).
+fluent(cpa_ok(cpa_p2)).
+fluent(cpa_current_stage(cpa_s4)).
+fluent(cpa_read(cpa_p3)).
+fluent(cpa_bad(cpa_p1)).
+fluent(cpa_ok(cpa_p1)).
+fluent(cpa_current_stage(cpa_s3)).
+fluent(cpa_read(cpa_p2)).
+fluent(cpa_bad(cpa_p0)).
+fluent(cpa_ok(cpa_p0)).
+fluent(cpa_current_stage(cpa_s2)).
+fluent(cpa_read(cpa_p1)).
+fluent(cpa_current_stage(cpa_s1)).
+fluent(cpa_read(cpa_p0)).
+fluent(cpa_current_stage(cpa_s0)).
+fluent(cpa_in_channel(cpa_p0)).
+fluent(cpa_in_channel(cpa_p1)).
+fluent(cpa_in_channel(cpa_p2)).
+fluent(cpa_in_channel(cpa_p3)).
+fluent(cpa_noisy(cpa_p0)).
+fluent(cpa_noisy(cpa_p1)).
+fluent(cpa_noisy(cpa_p2)).
+fluent(cpa_noisy(cpa_p3)).
+executable(cpa_certify(cpa_p0),lit(cpa_read(cpa_p0),1)).
+executable(cpa_certify(cpa_p1),lit(cpa_read(cpa_p1),1)).
+executable(cpa_certify(cpa_p2),lit(cpa_read(cpa_p2),1)).
+executable(cpa_certify(cpa_p3),lit(cpa_read(cpa_p3),1)).
+executable(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_reset(cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_advance(cpa_s5,cpa_s6),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+effect(cpa_certify(cpa_p0),lit(cpa_bad(cpa_p0),1),1).
+effect(cpa_certify(cpa_p0),lit(cpa_ok(cpa_p0),1),2).
+effect(cpa_certify(cpa_p1),lit(cpa_bad(cpa_p1),1),1).
+effect(cpa_certify(cpa_p1),lit(cpa_ok(cpa_p1),1),2).
+effect(cpa_certify(cpa_p2),lit(cpa_bad(cpa_p2),1),1).
+effect(cpa_certify(cpa_p2),lit(cpa_ok(cpa_p2),1),2).
+effect(cpa_certify(cpa_p3),lit(cpa_bad(cpa_p3),1),1).
+effect(cpa_certify(cpa_p3),lit(cpa_ok(cpa_p3),1),2).
+effect(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s1),-1),1).
+effect(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s2),-1),1).
+effect(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s3),-1),1).
+effect(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s4),-1),1).
+effect(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s5),-1),1).
+effect(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s6),lit(cpa_current_stage(cpa_s6),-1),1).
+effect(cpa_reset(cpa_s6),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s1),1),1).
+effect(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s0),-1),1).
+effect(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s2),1),1).
+effect(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s1),-1),1).
+effect(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s3),1),1).
+effect(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s2),-1),1).
+effect(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s4),1),1).
+effect(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s3),-1),1).
+effect(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s5),1),1).
+effect(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s4),-1),1).
+effect(cpa_advance(cpa_s5,cpa_s6),lit(cpa_current_stage(cpa_s6),1),1).
+effect(cpa_advance(cpa_s5,cpa_s6),lit(cpa_current_stage(cpa_s5),-1),1).
+effect(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),-1),1).
+effect(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_read(cpa_p0),1),1).
+effect(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),-1),1).
+effect(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_read(cpa_p1),1),1).
+effect(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),-1),1).
+effect(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_read(cpa_p2),1),1).
+effect(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_in_channel(cpa_p3),-1),1).
+effect(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_read(cpa_p3),1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_read(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_noisy(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_bad(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_read(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_noisy(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_bad(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_read(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_noisy(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_bad(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_in_channel(cpa_p3),1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_read(cpa_p3),-1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_noisy(cpa_p3),-1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_bad(cpa_p3),-1),1).
+condition(cpa_certify(cpa_p0),lit(cpa_noisy(cpa_p0),1),1).
+condition(cpa_certify(cpa_p0),lit(cpa_noisy(cpa_p0),-1),2).
+condition(cpa_certify(cpa_p1),lit(cpa_noisy(cpa_p1),1),1).
+condition(cpa_certify(cpa_p1),lit(cpa_noisy(cpa_p1),-1),2).
+condition(cpa_certify(cpa_p2),lit(cpa_noisy(cpa_p2),1),1).
+condition(cpa_certify(cpa_p2),lit(cpa_noisy(cpa_p2),-1),2).
+condition(cpa_certify(cpa_p3),lit(cpa_noisy(cpa_p3),1),1).
+condition(cpa_certify(cpa_p3),lit(cpa_noisy(cpa_p3),-1),2).
+condition(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),1),1).
+condition(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),1),1).
+condition(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),1),1).
+condition(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_in_channel(cpa_p3),1),1).
+condition(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_bad(cpa_p0),1),1).
+condition(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_bad(cpa_p1),1),1).
+condition(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_bad(cpa_p2),1),1).
+condition(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_bad(cpa_p3),1),1).
+initially(lit(cpa_current_stage(cpa_s0),1)).
+initially(lit(cpa_in_channel(cpa_p0),1)).
+initially(lit(cpa_in_channel(cpa_p1),1)).
+initially(lit(cpa_in_channel(cpa_p2),1)).
+initially(lit(cpa_in_channel(cpa_p3),1)).
+initially(lit(cpa_current_stage(cpa_s6),-1)).
+initially(lit(cpa_bad(cpa_p3),-1)).
+initially(lit(cpa_ok(cpa_p3),-1)).
+initially(lit(cpa_current_stage(cpa_s5),-1)).
+initially(lit(cpa_bad(cpa_p2),-1)).
+initially(lit(cpa_ok(cpa_p2),-1)).
+initially(lit(cpa_current_stage(cpa_s4),-1)).
+initially(lit(cpa_read(cpa_p3),-1)).
+initially(lit(cpa_bad(cpa_p1),-1)).
+initially(lit(cpa_ok(cpa_p1),-1)).
+initially(lit(cpa_current_stage(cpa_s3),-1)).
+initially(lit(cpa_read(cpa_p2),-1)).
+initially(lit(cpa_bad(cpa_p0),-1)).
+initially(lit(cpa_ok(cpa_p0),-1)).
+initially(lit(cpa_current_stage(cpa_s2),-1)).
+initially(lit(cpa_read(cpa_p1),-1)).
+initially(lit(cpa_current_stage(cpa_s1),-1)).
+initially(lit(cpa_read(cpa_p0),-1)).
+initially_oneof(1,lit(cpa_noisy(cpa_p0),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p3),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p2),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p1),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p0),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p3),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p2),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p1),-1),2).
+goal(lit(cpa_ok(cpa_p0),1)).
+goal(lit(cpa_ok(cpa_p1),1)).
+goal(lit(cpa_ok(cpa_p2),1)).
+goal(lit(cpa_ok(cpa_p3),1)).
+holds_initially(cpa_current_stage(cpa_s0)).
+holds_initially(cpa_in_channel(cpa_p0)).
+holds_initially(cpa_in_channel(cpa_p1)).
+holds_initially(cpa_in_channel(cpa_p2)).
+holds_initially(cpa_in_channel(cpa_p3)).
+holds_initially(cpa_noisy(cpa_p0)).
+holds_initially(cpa_noisy(cpa_p3)).
+holds_initially(cpa_noisy(cpa_p2)).
+holds_initially(cpa_noisy(cpa_p1)).
diff --git a/examples/clingo/planning/instances/comm05.lp b/examples/clingo/planning/instances/comm05.lp
new file mode 100644
index 0000000..28b62f8
--- /dev/null
+++ b/examples/clingo/planning/instances/comm05.lp
@@ -0,0 +1,371 @@
+action(cpa_certify(cpa_p0)).
+action(cpa_certify(cpa_p1)).
+action(cpa_certify(cpa_p2)).
+action(cpa_certify(cpa_p3)).
+action(cpa_certify(cpa_p4)).
+action(cpa_certify(cpa_p5)).
+action(cpa_reset(cpa_s1)).
+action(cpa_reset(cpa_s2)).
+action(cpa_reset(cpa_s3)).
+action(cpa_reset(cpa_s4)).
+action(cpa_reset(cpa_s5)).
+action(cpa_reset(cpa_s6)).
+action(cpa_reset(cpa_s7)).
+action(cpa_reset(cpa_s8)).
+action(cpa_advance(cpa_s0,cpa_s1)).
+action(cpa_advance(cpa_s1,cpa_s2)).
+action(cpa_advance(cpa_s2,cpa_s3)).
+action(cpa_advance(cpa_s3,cpa_s4)).
+action(cpa_advance(cpa_s4,cpa_s5)).
+action(cpa_advance(cpa_s5,cpa_s6)).
+action(cpa_advance(cpa_s6,cpa_s7)).
+action(cpa_advance(cpa_s7,cpa_s8)).
+action(cpa_obtain(cpa_p0,cpa_s0)).
+action(cpa_obtain(cpa_p1,cpa_s1)).
+action(cpa_obtain(cpa_p2,cpa_s2)).
+action(cpa_obtain(cpa_p3,cpa_s3)).
+action(cpa_obtain(cpa_p4,cpa_s4)).
+action(cpa_obtain(cpa_p5,cpa_s5)).
+action(cpa_request_copy(cpa_p0,cpa_s0)).
+action(cpa_request_copy(cpa_p0,cpa_s1)).
+action(cpa_request_copy(cpa_p0,cpa_s2)).
+action(cpa_request_copy(cpa_p0,cpa_s3)).
+action(cpa_request_copy(cpa_p0,cpa_s4)).
+action(cpa_request_copy(cpa_p0,cpa_s5)).
+action(cpa_request_copy(cpa_p0,cpa_s6)).
+action(cpa_request_copy(cpa_p0,cpa_s7)).
+action(cpa_request_copy(cpa_p0,cpa_s8)).
+action(cpa_request_copy(cpa_p1,cpa_s0)).
+action(cpa_request_copy(cpa_p1,cpa_s1)).
+action(cpa_request_copy(cpa_p1,cpa_s2)).
+action(cpa_request_copy(cpa_p1,cpa_s3)).
+action(cpa_request_copy(cpa_p1,cpa_s4)).
+action(cpa_request_copy(cpa_p1,cpa_s5)).
+action(cpa_request_copy(cpa_p1,cpa_s6)).
+action(cpa_request_copy(cpa_p1,cpa_s7)).
+action(cpa_request_copy(cpa_p1,cpa_s8)).
+action(cpa_request_copy(cpa_p2,cpa_s0)).
+action(cpa_request_copy(cpa_p2,cpa_s1)).
+action(cpa_request_copy(cpa_p2,cpa_s2)).
+action(cpa_request_copy(cpa_p2,cpa_s3)).
+action(cpa_request_copy(cpa_p2,cpa_s4)).
+action(cpa_request_copy(cpa_p2,cpa_s5)).
+action(cpa_request_copy(cpa_p2,cpa_s6)).
+action(cpa_request_copy(cpa_p2,cpa_s7)).
+action(cpa_request_copy(cpa_p2,cpa_s8)).
+action(cpa_request_copy(cpa_p3,cpa_s0)).
+action(cpa_request_copy(cpa_p3,cpa_s1)).
+action(cpa_request_copy(cpa_p3,cpa_s2)).
+action(cpa_request_copy(cpa_p3,cpa_s3)).
+action(cpa_request_copy(cpa_p3,cpa_s4)).
+action(cpa_request_copy(cpa_p3,cpa_s5)).
+action(cpa_request_copy(cpa_p3,cpa_s6)).
+action(cpa_request_copy(cpa_p3,cpa_s7)).
+action(cpa_request_copy(cpa_p3,cpa_s8)).
+action(cpa_request_copy(cpa_p4,cpa_s0)).
+action(cpa_request_copy(cpa_p4,cpa_s1)).
+action(cpa_request_copy(cpa_p4,cpa_s2)).
+action(cpa_request_copy(cpa_p4,cpa_s3)).
+action(cpa_request_copy(cpa_p4,cpa_s4)).
+action(cpa_request_copy(cpa_p4,cpa_s5)).
+action(cpa_request_copy(cpa_p4,cpa_s6)).
+action(cpa_request_copy(cpa_p4,cpa_s7)).
+action(cpa_request_copy(cpa_p4,cpa_s8)).
+action(cpa_request_copy(cpa_p5,cpa_s0)).
+action(cpa_request_copy(cpa_p5,cpa_s1)).
+action(cpa_request_copy(cpa_p5,cpa_s2)).
+action(cpa_request_copy(cpa_p5,cpa_s3)).
+action(cpa_request_copy(cpa_p5,cpa_s4)).
+action(cpa_request_copy(cpa_p5,cpa_s5)).
+action(cpa_request_copy(cpa_p5,cpa_s6)).
+action(cpa_request_copy(cpa_p5,cpa_s7)).
+action(cpa_request_copy(cpa_p5,cpa_s8)).
+fluent(cpa_current_stage(cpa_s8)).
+fluent(cpa_bad(cpa_p5)).
+fluent(cpa_ok(cpa_p5)).
+fluent(cpa_current_stage(cpa_s7)).
+fluent(cpa_bad(cpa_p4)).
+fluent(cpa_ok(cpa_p4)).
+fluent(cpa_current_stage(cpa_s6)).
+fluent(cpa_read(cpa_p5)).
+fluent(cpa_bad(cpa_p3)).
+fluent(cpa_ok(cpa_p3)).
+fluent(cpa_current_stage(cpa_s5)).
+fluent(cpa_read(cpa_p4)).
+fluent(cpa_bad(cpa_p2)).
+fluent(cpa_ok(cpa_p2)).
+fluent(cpa_current_stage(cpa_s4)).
+fluent(cpa_read(cpa_p3)).
+fluent(cpa_bad(cpa_p1)).
+fluent(cpa_ok(cpa_p1)).
+fluent(cpa_current_stage(cpa_s3)).
+fluent(cpa_read(cpa_p2)).
+fluent(cpa_bad(cpa_p0)).
+fluent(cpa_ok(cpa_p0)).
+fluent(cpa_current_stage(cpa_s2)).
+fluent(cpa_read(cpa_p1)).
+fluent(cpa_current_stage(cpa_s1)).
+fluent(cpa_read(cpa_p0)).
+fluent(cpa_current_stage(cpa_s0)).
+fluent(cpa_in_channel(cpa_p0)).
+fluent(cpa_in_channel(cpa_p1)).
+fluent(cpa_in_channel(cpa_p2)).
+fluent(cpa_in_channel(cpa_p3)).
+fluent(cpa_in_channel(cpa_p4)).
+fluent(cpa_in_channel(cpa_p5)).
+fluent(cpa_noisy(cpa_p0)).
+fluent(cpa_noisy(cpa_p1)).
+fluent(cpa_noisy(cpa_p2)).
+fluent(cpa_noisy(cpa_p3)).
+fluent(cpa_noisy(cpa_p4)).
+fluent(cpa_noisy(cpa_p5)).
+executable(cpa_reset(cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s8),lit(cpa_current_stage(cpa_s8),1)).
+executable(cpa_reset(cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_advance(cpa_s7,cpa_s8),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s7),lit(cpa_current_stage(cpa_s7),1)).
+executable(cpa_reset(cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_advance(cpa_s6,cpa_s7),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s6),lit(cpa_current_stage(cpa_s6),1)).
+executable(cpa_certify(cpa_p5),lit(cpa_read(cpa_p5),1)).
+executable(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_advance(cpa_s5,cpa_s6),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_obtain(cpa_p5,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s5),lit(cpa_current_stage(cpa_s5),1)).
+executable(cpa_certify(cpa_p4),lit(cpa_read(cpa_p4),1)).
+executable(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_obtain(cpa_p4,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s4),lit(cpa_current_stage(cpa_s4),1)).
+executable(cpa_certify(cpa_p3),lit(cpa_read(cpa_p3),1)).
+executable(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s3),lit(cpa_current_stage(cpa_s3),1)).
+executable(cpa_certify(cpa_p2),lit(cpa_read(cpa_p2),1)).
+executable(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s2),lit(cpa_current_stage(cpa_s2),1)).
+executable(cpa_certify(cpa_p1),lit(cpa_read(cpa_p1),1)).
+executable(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s1),lit(cpa_current_stage(cpa_s1),1)).
+executable(cpa_certify(cpa_p0),lit(cpa_read(cpa_p0),1)).
+executable(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p1,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p2,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p3,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p4,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+executable(cpa_request_copy(cpa_p5,cpa_s0),lit(cpa_current_stage(cpa_s0),1)).
+effect(cpa_certify(cpa_p0),lit(cpa_bad(cpa_p0),1),1).
+effect(cpa_certify(cpa_p0),lit(cpa_ok(cpa_p0),1),2).
+effect(cpa_certify(cpa_p1),lit(cpa_bad(cpa_p1),1),1).
+effect(cpa_certify(cpa_p1),lit(cpa_ok(cpa_p1),1),2).
+effect(cpa_certify(cpa_p2),lit(cpa_bad(cpa_p2),1),1).
+effect(cpa_certify(cpa_p2),lit(cpa_ok(cpa_p2),1),2).
+effect(cpa_certify(cpa_p3),lit(cpa_bad(cpa_p3),1),1).
+effect(cpa_certify(cpa_p3),lit(cpa_ok(cpa_p3),1),2).
+effect(cpa_certify(cpa_p4),lit(cpa_bad(cpa_p4),1),1).
+effect(cpa_certify(cpa_p4),lit(cpa_ok(cpa_p4),1),2).
+effect(cpa_certify(cpa_p5),lit(cpa_bad(cpa_p5),1),1).
+effect(cpa_certify(cpa_p5),lit(cpa_ok(cpa_p5),1),2).
+effect(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s1),-1),1).
+effect(cpa_reset(cpa_s1),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s2),-1),1).
+effect(cpa_reset(cpa_s2),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s3),-1),1).
+effect(cpa_reset(cpa_s3),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s4),-1),1).
+effect(cpa_reset(cpa_s4),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s5),-1),1).
+effect(cpa_reset(cpa_s5),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s6),lit(cpa_current_stage(cpa_s6),-1),1).
+effect(cpa_reset(cpa_s6),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s7),lit(cpa_current_stage(cpa_s7),-1),1).
+effect(cpa_reset(cpa_s7),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_reset(cpa_s8),lit(cpa_current_stage(cpa_s8),-1),1).
+effect(cpa_reset(cpa_s8),lit(cpa_current_stage(cpa_s0),1),1).
+effect(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s1),1),1).
+effect(cpa_advance(cpa_s0,cpa_s1),lit(cpa_current_stage(cpa_s0),-1),1).
+effect(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s2),1),1).
+effect(cpa_advance(cpa_s1,cpa_s2),lit(cpa_current_stage(cpa_s1),-1),1).
+effect(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s3),1),1).
+effect(cpa_advance(cpa_s2,cpa_s3),lit(cpa_current_stage(cpa_s2),-1),1).
+effect(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s4),1),1).
+effect(cpa_advance(cpa_s3,cpa_s4),lit(cpa_current_stage(cpa_s3),-1),1).
+effect(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s5),1),1).
+effect(cpa_advance(cpa_s4,cpa_s5),lit(cpa_current_stage(cpa_s4),-1),1).
+effect(cpa_advance(cpa_s5,cpa_s6),lit(cpa_current_stage(cpa_s6),1),1).
+effect(cpa_advance(cpa_s5,cpa_s6),lit(cpa_current_stage(cpa_s5),-1),1).
+effect(cpa_advance(cpa_s6,cpa_s7),lit(cpa_current_stage(cpa_s7),1),1).
+effect(cpa_advance(cpa_s6,cpa_s7),lit(cpa_current_stage(cpa_s6),-1),1).
+effect(cpa_advance(cpa_s7,cpa_s8),lit(cpa_current_stage(cpa_s8),1),1).
+effect(cpa_advance(cpa_s7,cpa_s8),lit(cpa_current_stage(cpa_s7),-1),1).
+effect(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),-1),1).
+effect(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_read(cpa_p0),1),1).
+effect(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),-1),1).
+effect(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_read(cpa_p1),1),1).
+effect(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),-1),1).
+effect(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_read(cpa_p2),1),1).
+effect(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_in_channel(cpa_p3),-1),1).
+effect(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_read(cpa_p3),1),1).
+effect(cpa_obtain(cpa_p4,cpa_s4),lit(cpa_in_channel(cpa_p4),-1),1).
+effect(cpa_obtain(cpa_p4,cpa_s4),lit(cpa_read(cpa_p4),1),1).
+effect(cpa_obtain(cpa_p5,cpa_s5),lit(cpa_in_channel(cpa_p5),-1),1).
+effect(cpa_obtain(cpa_p5,cpa_s5),lit(cpa_read(cpa_p5),1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_read(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_noisy(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_bad(cpa_p0),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_read(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_noisy(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_bad(cpa_p1),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_read(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_noisy(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_bad(cpa_p2),-1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_in_channel(cpa_p3),1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_read(cpa_p3),-1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_noisy(cpa_p3),-1),1).
+effect(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_bad(cpa_p3),-1),1).
+effect(cpa_request_copy(cpa_p4,cpa_s4),lit(cpa_in_channel(cpa_p4),1),1).
+effect(cpa_request_copy(cpa_p4,cpa_s4),lit(cpa_read(cpa_p4),-1),1).
+effect(cpa_request_copy(cpa_p4,cpa_s4),lit(cpa_noisy(cpa_p4),-1),1).
+effect(cpa_request_copy(cpa_p4,cpa_s4),lit(cpa_bad(cpa_p4),-1),1).
+effect(cpa_request_copy(cpa_p5,cpa_s5),lit(cpa_in_channel(cpa_p5),1),1).
+effect(cpa_request_copy(cpa_p5,cpa_s5),lit(cpa_read(cpa_p5),-1),1).
+effect(cpa_request_copy(cpa_p5,cpa_s5),lit(cpa_noisy(cpa_p5),-1),1).
+effect(cpa_request_copy(cpa_p5,cpa_s5),lit(cpa_bad(cpa_p5),-1),1).
+condition(cpa_certify(cpa_p0),lit(cpa_noisy(cpa_p0),1),1).
+condition(cpa_certify(cpa_p0),lit(cpa_noisy(cpa_p0),-1),2).
+condition(cpa_certify(cpa_p1),lit(cpa_noisy(cpa_p1),1),1).
+condition(cpa_certify(cpa_p1),lit(cpa_noisy(cpa_p1),-1),2).
+condition(cpa_certify(cpa_p2),lit(cpa_noisy(cpa_p2),1),1).
+condition(cpa_certify(cpa_p2),lit(cpa_noisy(cpa_p2),-1),2).
+condition(cpa_certify(cpa_p3),lit(cpa_noisy(cpa_p3),1),1).
+condition(cpa_certify(cpa_p3),lit(cpa_noisy(cpa_p3),-1),2).
+condition(cpa_certify(cpa_p4),lit(cpa_noisy(cpa_p4),1),1).
+condition(cpa_certify(cpa_p4),lit(cpa_noisy(cpa_p4),-1),2).
+condition(cpa_certify(cpa_p5),lit(cpa_noisy(cpa_p5),1),1).
+condition(cpa_certify(cpa_p5),lit(cpa_noisy(cpa_p5),-1),2).
+condition(cpa_obtain(cpa_p0,cpa_s0),lit(cpa_in_channel(cpa_p0),1),1).
+condition(cpa_obtain(cpa_p1,cpa_s1),lit(cpa_in_channel(cpa_p1),1),1).
+condition(cpa_obtain(cpa_p2,cpa_s2),lit(cpa_in_channel(cpa_p2),1),1).
+condition(cpa_obtain(cpa_p3,cpa_s3),lit(cpa_in_channel(cpa_p3),1),1).
+condition(cpa_obtain(cpa_p4,cpa_s4),lit(cpa_in_channel(cpa_p4),1),1).
+condition(cpa_obtain(cpa_p5,cpa_s5),lit(cpa_in_channel(cpa_p5),1),1).
+condition(cpa_request_copy(cpa_p0,cpa_s0),lit(cpa_bad(cpa_p0),1),1).
+condition(cpa_request_copy(cpa_p1,cpa_s1),lit(cpa_bad(cpa_p1),1),1).
+condition(cpa_request_copy(cpa_p2,cpa_s2),lit(cpa_bad(cpa_p2),1),1).
+condition(cpa_request_copy(cpa_p3,cpa_s3),lit(cpa_bad(cpa_p3),1),1).
+condition(cpa_request_copy(cpa_p4,cpa_s4),lit(cpa_bad(cpa_p4),1),1).
+condition(cpa_request_copy(cpa_p5,cpa_s5),lit(cpa_bad(cpa_p5),1),1).
+initially(lit(cpa_current_stage(cpa_s0),1)).
+initially(lit(cpa_in_channel(cpa_p0),1)).
+initially(lit(cpa_in_channel(cpa_p1),1)).
+initially(lit(cpa_in_channel(cpa_p2),1)).
+initially(lit(cpa_in_channel(cpa_p3),1)).
+initially(lit(cpa_in_channel(cpa_p4),1)).
+initially(lit(cpa_in_channel(cpa_p5),1)).
+initially(lit(cpa_current_stage(cpa_s8),-1)).
+initially(lit(cpa_bad(cpa_p5),-1)).
+initially(lit(cpa_ok(cpa_p5),-1)).
+initially(lit(cpa_current_stage(cpa_s7),-1)).
+initially(lit(cpa_bad(cpa_p4),-1)).
+initially(lit(cpa_ok(cpa_p4),-1)).
+initially(lit(cpa_current_stage(cpa_s6),-1)).
+initially(lit(cpa_read(cpa_p5),-1)).
+initially(lit(cpa_bad(cpa_p3),-1)).
+initially(lit(cpa_ok(cpa_p3),-1)).
+initially(lit(cpa_current_stage(cpa_s5),-1)).
+initially(lit(cpa_read(cpa_p4),-1)).
+initially(lit(cpa_bad(cpa_p2),-1)).
+initially(lit(cpa_ok(cpa_p2),-1)).
+initially(lit(cpa_current_stage(cpa_s4),-1)).
+initially(lit(cpa_read(cpa_p3),-1)).
+initially(lit(cpa_bad(cpa_p1),-1)).
+initially(lit(cpa_ok(cpa_p1),-1)).
+initially(lit(cpa_current_stage(cpa_s3),-1)).
+initially(lit(cpa_read(cpa_p2),-1)).
+initially(lit(cpa_bad(cpa_p0),-1)).
+initially(lit(cpa_ok(cpa_p0),-1)).
+initially(lit(cpa_current_stage(cpa_s2),-1)).
+initially(lit(cpa_read(cpa_p1),-1)).
+initially(lit(cpa_current_stage(cpa_s1),-1)).
+initially(lit(cpa_read(cpa_p0),-1)).
+initially_oneof(1,lit(cpa_noisy(cpa_p0),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p5),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p4),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p3),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p2),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p1),1),1).
+initially_oneof(1,lit(cpa_noisy(cpa_p0),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p5),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p4),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p3),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p2),-1),2).
+initially_oneof(1,lit(cpa_noisy(cpa_p1),-1),2).
+goal(lit(cpa_ok(cpa_p0),1)).
+goal(lit(cpa_ok(cpa_p1),1)).
+goal(lit(cpa_ok(cpa_p2),1)).
+goal(lit(cpa_ok(cpa_p3),1)).
+goal(lit(cpa_ok(cpa_p4),1)).
+goal(lit(cpa_ok(cpa_p5),1)).
+holds_initially(cpa_current_stage(cpa_s0)).
+holds_initially(cpa_in_channel(cpa_p0)).
+holds_initially(cpa_in_channel(cpa_p1)).
+holds_initially(cpa_in_channel(cpa_p2)).
+holds_initially(cpa_in_channel(cpa_p3)).
+holds_initially(cpa_in_channel(cpa_p4)).
+holds_initially(cpa_in_channel(cpa_p5)).
+holds_initially(cpa_noisy(cpa_p0)).
+holds_initially(cpa_noisy(cpa_p5)).
+holds_initially(cpa_noisy(cpa_p4)).
+holds_initially(cpa_noisy(cpa_p3)).
+holds_initially(cpa_noisy(cpa_p2)).
+holds_initially(cpa_noisy(cpa_p1)).
diff --git a/examples/clingo/planning/instances/uts01.lp b/examples/clingo/planning/instances/uts01.lp
new file mode 100644
index 0000000..4876229
--- /dev/null
+++ b/examples/clingo/planning/instances/uts01.lp
@@ -0,0 +1,37 @@
+action(cpa_start(cpa_n1)).
+action(cpa_start(cpa_n2)).
+action(cpa_travel(cpa_n1,cpa_n1)).
+action(cpa_travel(cpa_n1,cpa_n2)).
+action(cpa_travel(cpa_n2,cpa_n1)).
+action(cpa_travel(cpa_n2,cpa_n2)).
+fluent(cpa_started).
+fluent(cpa_visited(cpa_n1)).
+fluent(cpa_visited(cpa_n2)).
+fluent(cpa_at(cpa_n1)).
+fluent(cpa_at(cpa_n2)).
+executable(cpa_travel(cpa_n1,cpa_n1),lit(cpa_started,1)).
+executable(cpa_travel(cpa_n1,cpa_n2),lit(cpa_started,1)).
+executable(cpa_travel(cpa_n2,cpa_n1),lit(cpa_started,1)).
+executable(cpa_travel(cpa_n2,cpa_n2),lit(cpa_started,1)).
+effect(cpa_start(cpa_n1),lit(cpa_started,1),1).
+effect(cpa_start(cpa_n1),lit(cpa_visited(cpa_n1),1),1).
+effect(cpa_start(cpa_n2),lit(cpa_started,1),1).
+effect(cpa_start(cpa_n2),lit(cpa_visited(cpa_n2),1),1).
+effect(cpa_travel(cpa_n1,cpa_n2),lit(cpa_visited(cpa_n2),1),1).
+effect(cpa_travel(cpa_n1,cpa_n2),lit(cpa_at(cpa_n2),1),1).
+effect(cpa_travel(cpa_n1,cpa_n2),lit(cpa_at(cpa_n1),-1),1).
+effect(cpa_travel(cpa_n2,cpa_n1),lit(cpa_visited(cpa_n1),1),1).
+effect(cpa_travel(cpa_n2,cpa_n1),lit(cpa_at(cpa_n1),1),1).
+effect(cpa_travel(cpa_n2,cpa_n1),lit(cpa_at(cpa_n2),-1),1).
+condition(cpa_start(cpa_n1),lit(cpa_at(cpa_n1),1),1).
+condition(cpa_start(cpa_n2),lit(cpa_at(cpa_n2),1),1).
+condition(cpa_travel(cpa_n1,cpa_n2),lit(cpa_at(cpa_n1),1),1).
+condition(cpa_travel(cpa_n2,cpa_n1),lit(cpa_at(cpa_n2),1),1).
+initially(lit(cpa_visited(cpa_n1),-1)).
+initially(lit(cpa_visited(cpa_n2),-1)).
+initially(lit(cpa_started,-1)).
+initially_oneof(1,lit(cpa_at(cpa_n1),1),1).
+initially_oneof(1,lit(cpa_at(cpa_n2),1),2).
+goal(lit(cpa_visited(cpa_n1),1)).
+goal(lit(cpa_visited(cpa_n2),1)).
+holds_initially(cpa_at(cpa_n2)).
diff --git a/examples/clingo/planning/planning-lua.lp b/examples/clingo/planning/planning-lua.lp
new file mode 100644
index 0000000..f954f28
--- /dev/null
+++ b/examples/clingo/planning/planning-lua.lp
@@ -0,0 +1,37 @@
+#script (lua) 
+function main(prg)
+    local step   = 0
+    local check  = false
+    while true do
+        parts = {}
+        if step > 0 then
+            parts[#parts+1] = {"trans", {step}}
+        else
+            parts[#parts+1] = {"base", {}}
+        end
+        parts[#parts+1] = {"state", {step}}
+        if check then
+            parts[#parts+1] = {"check", {step}}
+        end
+        prg:ground(parts)
+        prg:release_external(clingo.Function("vol", {step-1}))
+        prg:assign_external(clingo.Function("vol", {step}), true)
+        local ret = prg:solve()
+        if ret.satisfiable then
+            if not check and prg:get_const("nocheck") == nil then
+                check = true
+                parts = {}
+                parts[#parts+1] = {"check", {step}}
+                prg:ground(parts)
+                ret = prg:solve()
+                if ret.satisfiable then
+                    break
+                end
+            else 
+                break
+            end
+        end
+        step = step+1
+    end
+end
+#end.
diff --git a/examples/clingo/pydoc/README b/examples/clingo/pydoc/README
new file mode 100644
index 0000000..424c0c3
--- /dev/null
+++ b/examples/clingo/pydoc/README
@@ -0,0 +1,3 @@
+To generate the python API documentation for the clingo module, execute:
+    clingo pydoc.lp
+    python pydoc-lib.py
diff --git a/examples/clingo/pydoc/pydoc-lib.py b/examples/clingo/pydoc/pydoc-lib.py
new file mode 100755
index 0000000..68537ec
--- /dev/null
+++ b/examples/clingo/pydoc/pydoc-lib.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+import clingo, subprocess, pydoc
+
+for m in [clingo, clingo.ast]:
+    pydoc.writedoc(m)
+    subprocess.call(["sed", "-i",
+        "-e", r"s/\/88ff99/g",
+        "-e", r"s/\/22bb33/g",
+        "-e", r's/index<\/a>.*<\/font>/\«Potassco<\/a><\/font>/',
+        "-e", r's/[^<]*object<\/a>/object/g',
+        "-e", r's/{0}.html#/#/g',
+        "{0}.html".format(m.__name__)])
diff --git a/examples/clingo/pydoc/pydoc.lp b/examples/clingo/pydoc/pydoc.lp
new file mode 100644
index 0000000..d302d80
--- /dev/null
+++ b/examples/clingo/pydoc/pydoc.lp
@@ -0,0 +1,15 @@
+#!/usr/bin/env clingo
+#script (python)
+import clingo, pydoc, subprocess
+
+for m in [clingo, clingo.ast]:
+    pydoc.writedoc(m)
+    subprocess.call(["sed", "-i", 
+        "-e", r"s/\/88ff99/g", 
+        "-e", r"s/\/22bb33/g",
+        "-e", r's/index<\/a>.*<\/font>/\«Potassco<\/a><\/font>/',
+        "-e", r's/[^<]*object<\/a>/object/g',
+        "-e", r's/{0}.html#/#/g',
+        "{0}.html".format(m.__name__)])
+
+#end.
diff --git a/examples/clingo/robots/README b/examples/clingo/robots/README
new file mode 100644
index 0000000..42457f9
--- /dev/null
+++ b/examples/clingo/robots/README
@@ -0,0 +1,13 @@
+robots - A Ricochet Robots Solver:
+----------------------------------
+
+Alex Randolph's board game Ricochet Robots offers a rich and versatile
+benchmark for ASP. As it stands, it represents a simple multi-agent
+planning problem in which each agent, i.e., robot, has limited sensing
+capacities (that is, only bumps are detected).
+
+This little script allows you to first select a target and then move the
+robots. If you run out of ideas, you can click on solve! to get a little
+help from ASP. To start, call
+  $ python visualize.py
+
diff --git a/examples/clingo/robots/board.lp b/examples/clingo/robots/board.lp
new file mode 100644
index 0000000..af51495
--- /dev/null
+++ b/examples/clingo/robots/board.lp
@@ -0,0 +1,42 @@
+dim(1..16).
+
+barrier( 2, 1, 1,0).  barrier(13,11, 1,0).  barrier( 9, 7,0, 1).
+barrier(10, 1, 1,0).  barrier(11,12, 1,0).  barrier(11, 7,0, 1).
+barrier( 4, 2, 1,0).  barrier(14,13, 1,0).  barrier(14, 7,0, 1).
+barrier(14, 2, 1,0).  barrier( 6,14, 1,0).  barrier(16, 9,0, 1).
+barrier( 2, 3, 1,0).  barrier( 3,15, 1,0).  barrier( 2,10,0, 1).
+barrier(11, 3, 1,0).  barrier(10,15, 1,0).  barrier( 5,10,0, 1).
+barrier( 7, 4, 1,0).  barrier( 4,16, 1,0).  barrier( 8,10,0,-1).
+barrier( 3, 7, 1,0).  barrier(12,16, 1,0).  barrier( 9,10,0,-1).
+barrier(14, 7, 1,0).  barrier( 5, 1,0, 1).  barrier( 9,10,0, 1).
+barrier( 7, 8, 1,0).  barrier(15, 1,0, 1).  barrier(14,10,0, 1).
+barrier(10, 8,-1,0).  barrier( 2, 2,0, 1).  barrier( 1,12,0, 1).
+barrier(11, 8, 1,0).  barrier(12, 3,0, 1).  barrier(11,12,0, 1).
+barrier( 7, 9, 1,0).  barrier( 7, 4,0, 1).  barrier( 7,13,0, 1).
+barrier(10, 9,-1,0).  barrier(16, 4,0, 1).  barrier(15,13,0, 1).
+barrier( 4,10, 1,0).  barrier( 1, 6,0, 1).  barrier(10,14,0, 1).
+barrier( 2,11, 1,0).  barrier( 4, 7,0, 1).  barrier( 3,15,0, 1).
+barrier( 8,11, 1,0).  barrier( 8, 7,0, 1).  
+
+available_target(red   , moon  ,  5 , 2).
+available_target(red   , sun   , 15,  2).
+available_target(green , sun   ,  2,  3).
+available_target(blue  , star  , 12,  3).
+available_target(yellow, star  ,  7,  4).
+available_target(blue  , saturn,  4,  7).
+available_target(green , moon  , 14,  7).
+available_target(yellow, saturn, 11,  8).
+available_target(yellow, moon  ,  5, 10).
+available_target(green , star  ,  2, 11).
+available_target(red   , star  , 14, 11).
+available_target(green , saturn, 11, 12).
+available_target(yellow, star  , 15, 13).
+available_target(blue  , star  ,  7, 14).
+available_target(red   , saturn,  3, 15).
+available_target(blue  , moon  , 10, 15).
+
+robot(red;green;blue;yellow).
+initial_pos(red   ,1 , 1).
+initial_pos(blue  ,1 ,16).
+initial_pos(green ,16, 1).
+initial_pos(yellow,16,16).
diff --git a/examples/clingo/robots/img/arrow_blue_east.gif b/examples/clingo/robots/img/arrow_blue_east.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c41f507e8b65c7ffd8354a88548e88218f29a155
GIT binary patch
literal 680
zcmZ?wbhEHb)L_tH_{P8x92}IGn3$YgotRjgkWinNR+EuYot0ISlT#NT-w+qq7!%VR
z7uOsa*&ZL?851)tIk_z_uQflvy|567I?Bqrii&y)3;Q!Nrsw8PFDjZ+R5Z1yXj*CM
zw33n;9v-WFeOLJTt?>6>9S{ISYeGWShlQhscp%!Hld~)#VRur}?u3Lrva*+?rLW1z
zT#=Q%DldOUQu2m`#7!wFAbCq({-(6_9T}NB^740NW$)?hpEfo=V`6g7)bxV6`2|bM
zi^9SWWMv;nNIYR>{m#kxnTzWS1H%snhM!DKKN%Q)Gco;UX8z5_1{C?j$oPkW;V&cO
zUnZtM%*=lo82&LZ{AXnR-_kO>vvUpu#X#{V3nK$V7K0ARBv70%u>WhwYHDt2ZENr7
z?CS36?dzW~anj@|Q>RUzF>?~*tlkXix!n?8atk}9V?tz?wM&Ml1ut0Bk{Oql<|RIX
zUtV#ailUaP))753V`DQLjqNdM9=rN{($1Z|5_9gxt(b`IS9XZ>`K86)d-nX<)%)&3
zy^pWnymtT9y<2HcZ@b@resS&NhwUvg7rw8Rv#CPhu6XO7aKkrTO4Uvr16Q*
z$wqwrBc&dp$C5f6A7)Qr>M@w+JwsrD0AsIA+U+vkC42jrWnLCMWIDzpVOFNG*-?az
zNBofA5#>q6(`Ipn=J6^%2${gFeO@F)l;vR06qaaKQwb)sHM2NV&oUXD-nRDkcD91Y
Lr^pcXvMMYDJ
zil!A81KBg&-B*C_KL`3dMO5Tu=xG5=lQ%2^twDes$xx2Em_jPnm8ylZ7
zF*#>sbiv&Gf~Dm}Ny*2otlzn~K67(_VPN>d!0?lS;Wrc0Z)WD-Y-~X8A4bMM3=Dr6
z8UHdd{b6GI%gp?jf#Dwm!+%D`|IEz)T3TjzcFtj-04V-sVPs&)VbB4Y0g4j__6H3)
zP0cN>ZS5VMUEMvsef<+APMSQWlY?#Q1Wqq6_L;pR&M7JOO!K>h7cE{gV|m-k)vN89
z*R_cIY~1LzW$X5xJKgrom-F4f-;4Wj=&@sNC#T4tK6A|d{6y)a5pkDShlQtj2~1?n
zl9ZFm){H(Ats%xI$ScY))8_TDXzi^{=68PmHh=f`7E`kP?1sxp5=#^fu8T>rC7bko
zz3`x`bM>}68!UVmyY?*J_Tj;ayeIoaWqq$nT`YWTH|>qWzBd}1!#eu7zPB=Xwk>cJ
gxDz8$^MS={%HrTjK@&F}UT}GNz+$gfDGml}0CX4i{r~^~

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_blue_south.gif b/examples/clingo/robots/img/arrow_blue_south.gif
new file mode 100644
index 0000000000000000000000000000000000000000..b5e333c5de57c83244d18eb8058f9213a067edb4
GIT binary patch
literal 657
zcmZ?wbhEHb)L_tH_{P8x92}IGn3$ekm6%wYlvJCRR+FAylaW!CnOU2YQx_N47#rIZ
z6Vn_S*&Y|y851)tA)zrTsVzUhJwLyzprE;+puMcDtEi}_xVSGPV|sS>^pcXvMMYDJ
zil!A81KBg&-B*C_KL`3dMO5Tu=xG5=lQ%2^twDes$xx2Em_jPnm8ylZ7
zF*#>sbiv&Gf~Dm}Ny*2otlzn~K67(_VPN>d!0?lS;Wrc0Z)WD-Y-~X8A4bMM3=Dr6
z8UHdd{b6GI%gp?jf#Dwm!+%D`|IEz)T3TjzcFtj-04V-sVPs&)VbB4Y0g4j__IC|A
zP0cN>ZS5VMUEMvsef<+APMSQW#X2A)I3y%+ZlFK^)ONjurOTEpENU}|&Rn`~eS-3;
zR-@?UJ2r1=Hr~Et*{In-pe@96OpHmCP%oya+Vbm^rNr>;fcICSfp!R7l$
zbuS;eW^~!;+R~RNUca$=^(Ok$39T6>9S{ISYeGWShlQhscp%!Hld~)#VRur}?u3Lrva*+?rLW1z
zT#=Q%DldOUQu2m`#7!wFAbCq({-(6_9T}NB^740NW$)?hpEfo=V`6g7)bxV6`2|bM
zi^9SWWMv;nNIYR>{m#kxnTzWS1H%snhM!DKKN%Q)Gco;UX8z5_1{C?j$oPkW;V&cO
zUnZtM%*=lo82&LZ{AXnR-_kO>vvUpu#X#{V3nK$V7K0ARBv70%u>WhwYHDt2ZENr7
z?CS36?dzW~anj@|Q>RUzF|(UtRu7lR+%7JA-h~}pL9qhM+PGZO!uZy-Ft1Mw72Vvl
zHEnOKx|+7(A!8FuOA}iY!_)e@R((wCWA{a*#ooAb(lho@IQeYo@a(>DQ0iS6&_?<@I#K-J1Xci#58=W??OH*p-CSjo!o
zHRXEuqeUF=jI5sQxOn=Ao3NgfOUH&zWiAhysOlSUWi8eE^;A0Boo;TD)CpUo5t!84
zu~@;Srh?&R)1SD4u@urb_ZV7SG=
zaGQbQ4uiyD3HRylzB7IO=lDl9M8-G9$M(hs&J7Hj7Zfx<$a#UY&nlnbCBY#JLc$k@
zhb;;VTO1a?I6PuWMC7u_sHIU+%cEkJ#l$R+iCGa7yD~OzRb2e4`1sZF$qmVQ4SD&^
z`5Ao~xf618=H?VM7ZkP@7Pl9dw3ZZh6&Cjv7fvWFnov|Sv7~fDY0~PXgf$5*(_1=c
zbTW_v6o0ZXGB6Y}=zuhV;)H?yUqfM2b4zPmdq-zicTaC$|AdK?CQq3zmHcb=doPc*S}*hptaN*#3QAWWs_I@{a9aWUf8_*pQ@D|JlSz2kc#TH(PpFZtxLmy-@RGHw-b>hR!T2){66ODW@(yQjCWzrVkMIhc!u
G!5RR70tp)c

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_green_north.gif b/examples/clingo/robots/img/arrow_green_north.gif
new file mode 100644
index 0000000000000000000000000000000000000000..54236ed40660b66e81fe5b55fa08b0cd8fae5c3f
GIT binary patch
literal 704
zcmZ?wbhEHb)L_tH_{P8x926W|9UEU2A734xn3$Mco}5^bm{^&ZP?eBYnU-FWo>`um
zS(%wzn_Ey{AihgnWUq+Sb}8v?(lXm+BzH(k?2?e&B`LK-N_wBP%nlj3opLgJWn}ls
z%I=qy+ass5QO9_*vC&o|lg%ckTTD&2nwo7hv)FFIaGrtnJS*23F7C733>O#}E;2A&
zVqmz;z<8OF=@JvuWhUlJ%nVl;7_KrfUSVXs%E)k?f$0hp^A%>c3v3KG85nLcFx+Nf
zyv@jTn~C8LgXAGex9M)aGkyK%_(wKG#x};r_QnRz4GfwW6f{4`d4aRiPr|_|@@A4N3XU
z`T1@68GRYq{nSNtLi3v2Ni%i0oFT9}wDVO!slDrar7dCO|??K{#XtgZI$UA3D3(EQBZ
z`&OM;wT5|q_JxZlFIhNp9k`n$}aH>BQ!sX3l)Ju)4{6!nEQ~8FLpz1fF)tWG(brDRKOap`TIokRp*<@C5
zylto!zx#!7=LLGco<=#|sb<=V7O>~=YGXw6J&gL
NYg?

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_green_south.gif b/examples/clingo/robots/img/arrow_green_south.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e553da9fd1c909cf2cded6c15d077f867f286a18
GIT binary patch
literal 714
zcmZ?wbhEHb)L_tH_{P8x926W|9UEU2A734xn3$Mco}5^bm{^&ZP?eBYnU-FWo>`um
zS(%wzn_Ey{AihgnWUq+Sb}8v?(lXm+BzH(k?2?e&B`LK-N_wBP%nlj3opLgJWn}ls
z%I=qy+ass5QO9_*vC&o|lg%ckTTD&2nwo7hv)FFIaGrtnJS*23F7C733>O#}E;2A&
zVqmz;z<8OF=@JvuWhUlJ%nVl;7_KrfUSVXs%E)k?f$0hp^A%>c3v3KG85nLcFx+Nf
zyv@jTn~C8LgXAGex9M)aGkyK%_(wKG#x};r_QnRz4GfwW6f{4`d4aRiPr|_|@@A4N3XU
z`T1@68GRYq{njcFJEDAXX3QDEnMBiNPEi`OKsLrW-AGuLmy7WJhw?0>wK-uB3yeeqPjKTA@L7hg6x
z%4hRKk@>d4^7Iv=3mCS{=jTbgaMV&k@ntx#M#2>?uLTE>uaTG9cS82ag17vfeBXqk
Z6dIkF54H*!IGowB@$vBqysS(N)&Rsu64w9#

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_green_west.gif b/examples/clingo/robots/img/arrow_green_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..592999085831f13656d6e49db0971ba3954f1c50
GIT binary patch
literal 690
zcmZ?wbhEHb)L_tH_{P8x926W^9T#5}A6pxnn3$Mco}5sbkWiJ7TA7+wnU+zWky)OZ
zRhgArn=8CeSZceJ^mb{PZ89?3Wh8b;NbHi3+$AZsLrQwDwCoO9xt((IJLF~d%E<1M
zmEA8ZzeiqwqrUNGW0TD$rdv!+x0;%5Gqc!k!El~|={ytbc~;IdoLuL)7%ng{Tx4Ll
z#K3Twf$SD4u@urb_ZV7SG=
zaGQbQ4uiyD3HRylzB7IO=lDl9M8-G9$M(hs&J7Hj7Zfx<$a#UY&nlnbCBY#JLc$k@
zhb;;VTO1a?I6PuWMC7u_sHIU+%cEkJ#l$R+iCGa7yD~OzRb2e4`1sZF$qmVQ4SD&^
z`5Ao~xf618=H?VM7ZkP@7Pl9dw3ZZh6&Cjv7fvWFnov|Sv7~fDY0~PXgf$5*(_1=c
zbTW_v6o0ZXGB6Y}=zuhV;)H?yUqfM2b4zPmdq-zicTaC$|AdK?CQq3|p0Jja}BpE^M#qx~7F`y{UED<|fwl#-_$zo&lku;SmwJ$4^FtMuht$
z_3g3SXKJcud_(QVP2;<_@0lv~atPR8z4r2@)ioEVX?Noa>gs!~0_TtxH>o476
z4<27%zhIxF-7(cD2F3XY+u4P+k_-+i9_i+A*2$W1@R4gXhp5)07ateztCy0jeR<-2
ztWAYo&5`c!=h!*iQ_S{wFV~Is&$q9wt#CQ!yid}5nxQh=(#%OJ&TSl$LPt237`vsv
yX;_>sAf;dz)bi3QgLi^t)`@9f8Qk6~mf%TKbZ#>=hZA
zt3Xm-{-%V)4N1vcKvGKTj{DY0{GbiU4F0Kc{!cQb59>~g`*4IB{Y<$kd
zt;(_&&)d3dbw^Q^=J4>XAt9S1A~r`xZi$TC8WpuII(mCd%nl%mjold+
zw+o2k<9El$wCP9+>(*leq~2=pT4r}y=Tv#UA-?H-uw9K
z&1?5x-MgjC`?mZ2=NH#Le%LN0bK(11Is2-=`#dFPXt*70f3e}C@s9%yN|K-WoNUC`
zKT_%udMv5K@gcgIsmEZN_Y8pqX2xEbwA*F6OZN6L%S`l~l+rm_HSm;1w^PZ=cmvl7i*$M`;HB!2%XPFF6Z(DnNJ6plyQ%glS
G7_0$G5CMSz

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_red_north.gif b/examples/clingo/robots/img/arrow_red_north.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7efa42c5bc1d6593175fbaffd1f307c6830f06a5
GIT binary patch
literal 643
zcmZ?wbhEHb)L_tH_{P8x6datGm{eMLs*imdE)8JTPH^4I0%Z%Rnqkd(YBDS1~~`nHVBeOcMNa&q5US${Av{A6JG
z4Ma>#znPi;FfjaOVEDtx_?MCK9|OaGAYx?v!^HF#h?trGF*E;QWBbg-^@W@Jv83c_
z9i21A#^+2-E*KeIFgL$wY1tkb*&Gwo6dT(Z7uOjVH!UV+mAm^2U*8peeyjccH#Dk%M1qJN|1wBPYeZ|FHWo1)}il!A6
zO)oBJ-vPX6DCfYJf)L^ZR!M0QBn4py)gnB8oVs?yCN4YUNU2O+sf6ed70L=
z#EEU(D7t0q_MJPq_RLR~+`nJc{IK4!V_YYvq@F%=jQjk=l%u-Zmsd;aXo!YQWXy_6
zj?Q+FJtJ$MU>R;2%P=$j^)XrZtxZ99e*F%5_xII?6#3Z=muE=SC>eyetFz5C>G^u$
z!NkthRvsHId>6a+EVi2S@I>B|eaf=F*FIe=d~7%Ejl#Y+8k@!X`?$V;Waw;Ka8UM6
em&BEiOm01kjVE22ka%pt<>dj3y;`L>7_0#%0{1om

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_red_south.gif b/examples/clingo/robots/img/arrow_red_south.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4807e2a9eda3a510af468ece8e46c2a5807d92ed
GIT binary patch
literal 657
zcmZ?wbhEHb)L_tH_{P8x6datGm{eMLs*imdE)8JTPH^4I0%Z%Rnqkd(YBDS1~~`nHVBeOcMNa&q5US${Av{A6JG
z4Ma>#znPi;FfjaOVEDtx_?MCK9|OaGAYx?v!^HF#h?trGF*E;QWBbg-^@W@Jv83c_
z9i21A#^+2-E*KeIFgL$wY1tkb*&Gwo6dT(Z7uOjVH!UV+mAm^2U*8peeyjccH#Dk%M1qJN|1wBPYeZ|FHWo1)}il!A6
zO)oBJ-vPX6DCfYJf$Vgz{J?Z#Bi>mzSY!rSEZ%PmRm1s^On_Gx^BIa-Kth!
z+2uPnZ)x`1zGK<0-8p;rFLON96uR%|@e}E%_q(0QIe&ENr4y&F$=*10>zeoF`$s)5
zAGzjx+4tJgmnUAo34QfO_R|TsFX@+m-2OF{AvP=KB;zyo-MkLhG6Wa9`ZjokX>}xg
zY>ZvWryaH8ghSdTURJTfl?8#zE*+n+%wyFqMZ+cCeOp)>QqmuC8!_tEU!8Nz&7nD7
tXwwIg5QjsWoUv_uRv&_0SoOR(4cAUk$Xdw6u_o*8sjaKSof{b#tN|HD0#N_}

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_red_west.gif b/examples/clingo/robots/img/arrow_red_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..3d587aa61385828ed0c8a1ea702908f745bb2d63
GIT binary patch
literal 679
zcmZ?wbhEHb)L_tH_{P8x6datGm{^^hT$`9!pO8?KmR6mSQInNbmy>f%TKbZ#>=hZA
zt3Xm-{-%V)4N1vcKvGKTj{DY0{GbiU4F0Kc{!cQb59>~g`*4IB{Y<$kd
zt;(_&&)d3dbw^Q^=J4>XAt9S1A~r`xZi$TC8WpuII(mCd%nl%mjold+
zw+o2k<9El$wXX7!jx&+RhhG+x+YswEq`tj&~9S;JyY3-fwq@wm-RTb1|9
z+Bv)V9P;xI3Gq+&_c`t5k^16P<$7}O
z$-a;8@4fC~<9>SO(}z2sKYbIBl-T}${=Sm`2UM*LbmwiadoI^kv616oOC>A6*Ocqs
zkCe3E8CgBq@$twJw~4)yzw|5SsW~K$Pr?;)Wy`8n-u^$%;
GgEaug#Req+

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_yellow_east.gif b/examples/clingo/robots/img/arrow_yellow_east.gif
new file mode 100644
index 0000000000000000000000000000000000000000..2832a3ea7b11eb76c3350415ed80af362a96d909
GIT binary patch
literal 680
zcmZ?wbhEHb)L_tH_{P8x6cn78m{?t%TwkA1SC?2*lU7}wQB#vuU!QyHmiV=6(w8pD
zUb!N3?HZ7jzj;&Q#tq3^w}7P7-Mdn^Zpq!bBXjqz?Dy}iKYlR${K@e9H;`od{Tqmw
z|NLS2`82|iX`umsp#}Bs8pETjYhWO^@xX#Y_Y13j>t@2p8(r3jAzs;MS
z_w4amy*gmcn!vSd1J|t!TE9MQ!-kNJ8^bnl4&SydWb@{TEn9#nYU|dhZQG)^Z;#or
zBX;M`xLv#AckhmGYfElv$!l-VpFTZf`t;oP_QKB2g6{6ZuCB6)6N{!#FPt)^XxcO&
zDxEQ-WZANu-Mf?b>`9zGyJgOtP6p}$#h)yU3=HWEIv^uKal*j
zTZjG5F3#@mKE46RlkK<5Y>4dFRX%&^%q5w#*RM-#zaxCUS6^B7&XcFlt|^Oz_8MHh
za{11U7ax`RB6{9_xO)BBr(ZnmVoxWR_r*JAi7=^6`q($muIYwSUqyn$MV_KxcT$g7
zG&#C+5rG-xj-f
zPvrV_scYAyuUwJ2az*y~b(w3|!hK
zo%P2LhMzwfe*Xp{rayle{{Ch7^M~>8U&ep`82f
z%NOp)k0no^);V*=_}n>@3l|J8Trj_Q(W1RQvbi~?sVTOxF|M;SZrZe%RjWK!uJl>4
z!f*3tmpyxYR<90NvnFuu+Q4<|g4VAO+pr;I<(Wd6N6gl;m^gFI<{Ti+BDQ?dH^QFZp(Gd3p+5rG-xj-f
zPvrV_scYAyuUwJ2az*y~b(w3|!hK
zo%P2LhMzwfe*Xp{rayle{{Ch7^M~>8U&ep`82f
z%NOp)k0no^);V*=_}n>@3l|J8Trj_Q(W1RQvbi~?sVTOxF|M;SZrZe%RjWK!uJl>4
z!f*3tmpyxYR<90NvnFuu+Q4<|g4VAO+pr;IB>
zrskH`w)T$BuI`@RzWxalCrzHxl44|PVrptM*T}$nYP+ZM(q+qS7Pa}vYcE~5UfFI{
ztMBsdo3^z0%I{d_ysJ5Q?>=RhgH4Bz9y^hF>ge$kX-D?CpFO`r{@RHfJ8mDmyWR7w
z|CJs7XSW@de{o{X>)_}5j!FlGM-r?&8_#S%5a&G$HZkOQ$$LW7o8A~FX83bsnaZ;!W{GH)Pbdu
xvls;nJa;?_p1{btyiH8DMd1YpSJX72EGflRAx>;OF?UaGU44Ch8xtdgH2}_^E&Bif

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/arrow_yellow_west.gif b/examples/clingo/robots/img/arrow_yellow_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bb7bbc9d024dd14e46d26bcdb219c33edd79239f
GIT binary patch
literal 679
zcmZ?wbhEHb)L_tH_{P8x6cn78m{?t%TwkA1SC?2*lU7}wQB#vuU!QyHmiV=6(w8pD
zUb!N3?HZ7jzj;&Q#tq3^w}7P7-Mdn^Zpq!bBXjqz?Dy}iKYlR${K@e9H;`od{Tqmw
z|NLS2`82|iX`umsp#}Bs8pETjYhWO^@xX#Y_Y13j>t@2p8(r3jAzs;MS
z_w4amy*gmcn!vSd1J|t!TE9MQ!-kNJ8^bnl4&SydWb@{TEn9#nYU|dhZQG)^Z;#or
zBX;M`xLv#AckhmGYfElv$!l-VpFTZf`t;oP_QKB2g6{6ZuCB6)6N{!#FPt)^XxcO&
zDxEQ-WZANu-Mf?b>`9zGyJgOtP6p}$#h)yU3=HWEIv^uKal*j$m34SQL6ZtZ*Y_{q~N#yzau`yXDp
z`uN(1=iO|)55NDo^6tZ}&z)>s?{?m9@0WFqe<370Bdl-EzP9fPI!+1t_YRlw{q9_>
zRwy{NltrKK&i4t)$~qz@PBEJAS{LgGpGe%Wf`9fwL0!4jjThb>mq;

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/moon_blue.gif b/examples/clingo/robots/img/moon_blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0ca45e81e13458d70fd6fb44cd53e00f79626a19
GIT binary patch
literal 1121
zcmZ?wbhEHb)L_tH_|Cv!V^ibpo#yVI@8OXh5|Z!aRP5(h?Ce|{99$9^Sr8Lb92r>}
z5KvQIo>W$rQdgIimR6gdUf0l&DK9_I&aPQqeWsq?Y+c=X1_o12OlFvx&M-5ZVPZ0i
zn|r^!{8m}nJ!)!;baa;K=qy)PU$3CBO<8%ns_J$PjSYHw8+3KI>FI5=wcTQ9xZlaC
z!NsN7!J*yXzb7!TBQLKlKff(HdZmlYW^eCp)z#~=vbL3%?~sr``Xs
zyUfh@Sy}I~v)|+9zRSsZpP&D}sOWVeq5C2t_a!9mDJdOLRz9Gven>&#h?dp?4UMDP
z+Q$_X&S+_!(A7O*Xn4%n_?U^waTAj>y1F;GxgT?LKjYzf#=!83k?}1%`x_CFhoYiS
zgoIu(FnnTV{mQ`bi;?jc1H*4d#@|d#znGYQGc*5YVfoF#@Q0D{4+FzrM#jHPOn;b|
z{xUH9V_^8t$oQX$>3@9u!ML~+E-u$|at`F=oT#WcKXvNrY17vC_3fQFaqIl~n>K7%
zwQ}XY9Xqz{+_`Q0_Fa4T?mT*QT7+*UIM}U_wT-ad;aa)M}|?rz@Ye(g^___C4&wqFhF^Nf#V-T
zFsF>ih6M+kIfS)hPHb3sxLrWmYmUdpMMt|OjI-{X2ux(*4PE51aMD88=00Pm3PxSw31Sm1LiuQ`94{pkm>%h4vnCSxDKcH&3aPbsU
zu@8u`KmGHdLNcRV1&62+%LzB}>5fS`G7d?{yJTwf7Toxx+S1d<7m(1%rLN-G$|hK{
Xwzy

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/moon_green.gif b/examples/clingo/robots/img/moon_green.gif
new file mode 100644
index 0000000000000000000000000000000000000000..7b75dae460a36af42cf1e2571b68b6793fafecd4
GIT binary patch
literal 1137
zcmZ?wbhEHb)L_tH_|Cv!Q)pvXY3H8e?wsT7o#gG2>EV~_=UC+EROaMRnO2#WUX@;+T3()3UYA{0ms=-4N1l5jH}h_0<~_`;
zyII+Hv$O7F<=oB5y@#8BAHT$63CZP>a!cjpmdnYmloj13DzsNfWS@x0ei4a%5(@1K
zYOQK2Ju3RG`nuh^x_!FJ^OV(RsH@Ib)tRWHGf78twx;eJUA;MaCT%9BZKkH}rY0RG
z%1f117OJQ(QCC=@ps-#+Yq^%@YE7**S~}}=^fv10?$I?|X=t?C$as~p>1tEkg|;S}
zO&AU_Fdk=QIL*L%j+Of$H}@fKj^i9Whj|z-Ffd$XV7SDSP=4F@(H+j{Kio}u4_r!QVRb?y44>$fi4
zx_$Zf?fbXy-o1P6!L>UN?mW2u;L(jo5AHvBdjILO7tdZle*Na*n-?!%ynpxp%kwW^
zKYnExNkH)@3nK%=Mg|>_r$Kpwf#V-TGN+8kh6M+kIfS)hPHb3sxLrWmYmUdpMMt|O
zjI-{X2vlU1^X*Yc+{E12+E}7UjIC#hkW>tvU&JylpXBRb0c@f;c
zWZ|yCR++L&MB64ecz5XJibdTvt3wXX5?NY&V~(AMo`Tb<(A6PTcdDMPT-MdprOUEc
zD>Uo!WW&s$=ON52&aRwl8gn0g@f76Rb4xE%N*ea2>;$fRi*^7tm
L3T+wz4h+@+F+6ye

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/moon_red.gif b/examples/clingo/robots/img/moon_red.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e26170a2e258a93006b4491f533b94a5c043b154
GIT binary patch
literal 1121
zcmZ?wbhEHb)L_tH_|CvkV`G!=?w;oDo$cXK?BrDI>|E^Ummd;R5*%C;5Ks^qSsEEx
z91~NUmR6UZo>X3*QdX8#S2s^yem^(&R(bh7va&PP)o1JJ&C}IwwzHdRU@*hPWQM8f
zEFfuSwn$BFy}J4`9i8PmI@=T!wks=dS5@7hp|L?vZ=0^}Ha)%lhK5^gZSOKO-)CmN
z$I5z-o&7#1=Ur~@`~3U|BqWYVN*ts
zKTJ%2nV9|q6|k^86cKqMD*8%D=zx;a0cGVQ3JQnR)z2s>9MIA_s-baQTl<8T)(KtR
z8@js33=NMN8y`0@Ib&kd;N;Zq;Lz;i(&O*n5g54H#bukf_sZz#w!FNy{QPZMS?j8+
zca)c3cX2rwAAce)?m$k?iJYAC6&0Bc4SW0gR!^O}e%iFH6DMw(KY!oKm8&*v*tLE8
zmK{5`?cBL@@7_Z#EoU1W&-C`5oH66n%$esGEV#IS{gDkDHXc2?`{>bw$B&;le*Eyc
zbLY;UJ$~)liHjG{-M)SO;>D{sZd|$p0{8CUe|-J=gIl*A+_`i0!GkN0AK!cO(~_scDs~tFmeer@z3?jPp)koi;Kl
zdC!)Lb=*_>VzPnAc9~ySJVoZ7@)xz&biU{`H*jfy?jyzU!X!Qs(VT}Vt3oua>zp^U
zOj@?6#b&ux?yQt&oT7`0ykD%`ae!^H|8xV!T^F}#^00_Ap7C(e6jHH|iLtlOoT#A8
zC{@lPS|qZfg_h%f+HI{U&)dOO+02V9yANM
OX*_HZ;Sv#Gum%8P33nX;

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/moon_yellow.gif b/examples/clingo/robots/img/moon_yellow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43cdd7cfd44734ee8d8f27aebe5e5325fd0539c7
GIT binary patch
literal 1120
zcmZ?wbhEHb)L_tH_|CvkQ)82#@1BLTs(yyS5gvOSQuJU6HrhPSy~!d
zTpUwdn_gF!o|IIcl2V?PRX=Z@{QmviTer&Z-77nDruyvJ`t#=LO`U2mV}|L>nWnR5
znarGNzG#u!`t?AhzHFJ!vSqqkw<>JkuDpG_`u_dOyLPE;*`l*`tIq!YhFiAS-M!0v
z|31sTd#rcvu;0JWdG{{&{rmg}4oDn1B6aw%{L!Pb_wNhczb|tAy5zlk60cq{ynV~`
z<_-Jf$K21J0TIuqPYhqbvi|zT@cTEzuV0M6e>492#q|3(5HbJx!|>-1VfHQNtrgjLw`fX=re2ZFOvEaqZ}E@9FXH=m^-n*?HSG@0BZ~TU+y*n~S$?%UZv_
zddH56>(^Zl9*jSEGUC92oa4uH&z}c|Si|1EeXCbbUB7<%wrvwOZJNJt-`W)`Hf-6l
zW81c!yLa!{y?gheL#^k|HJv%rd-CLrQ>SL0KfmC}kqs9wZrHTx@b2A54j(>t;>7X8
zhtHooclPSl^T&^0IC0|o*|WDUUAlhp;=Q|f?>%~S?ZJcFj~?BK
zlNT?ZJ$(4`;lp>YUcG$#_WiSGU*Es~$}kF$LO}5+3nK%=G6o%x7${FLaQtKN<&^Q*
zu;5@bhp<-6i46-6w+kqH&GFc{=xDcuan_v^feV>=6Lyp^E>1kt+?VST;P`0CQehQ4
z4~`oZ%UZovEDE>P2r48uaXQ6ql9_ecvztkrHzrc~@zQ{W&U5!91Q;^0npf61)b6_K
z>}ss?@5RB7A?bnB%tZo@OlT97mrY$f@2rF2(FN}HdmLRT(iZ*J49W)D}p2Ul!#Ve+8vlQO~(q#2L>Rn4An;Y#XU&
z_c~>wf-<922@7Y`6L(+!>ADwkWDFJ^*;iT}4Gbg@yeY8Pjufrxz7XDJq&;R5Y!$bXrNt
zjIglv&d!^CeD;KeZ3++H92vPKI(l17%=Va=9kH=H;^KD3$L~r?+AS-4Nm}}vjLa2T
z*{kyMS0p8GNJ!k2k^+*q#>;`+kC
z@PmQjCj-N8CZ^xa%)i;#fZRWfj6n34iRljm!#@Uw|BQ_PTUus!cFy_#|3Aav1ByRc
z7`Yhy7!>~rIv1rTmZYXAlxLP?D7bt21~BM=+zW~*2KJ*3eof6St!?ccon75My?y-?
zCQh0>W$Lu)GiEk1&g%7%p4%;MF1xT(+SyuWS-XUttJUf?ExyjK8^q=+DXXe#XlN;H
z+itOQrlX_liIXR{Z!;C1>ALOk;q8}QO)gHqe)ryW6M;MTpKRCTnD+F^HY4__ukOEj
zH|4{9ozGvsUe{)we)Yzam@m@H*CcGtHf2fi`j~x$Lr~7HWU^txGzG51DK;B4P8?h<
p#bv=&6`*q5ZK9vlhJ=Qo2`tle=Q4D7ZeDhFwngzP9#IYkYXDjh%vJyZ

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_blue_north.gif b/examples/clingo/robots/img/move_blue_north.gif
new file mode 100644
index 0000000000000000000000000000000000000000..94ffe5d9b93aeafe94b4341466a6759523ae1424
GIT binary patch
literal 634
zcmZ?wbhEHb)L_tH_!htr92}IGn3$ekm6%wYlvJCRR+FAylaW!CnOU2YQx_N47#rIZ
z6Vn_S*&Y|ynUK(!l+>1=-=3e}RZ!4eP|#jh)>Ty0Q(WAakug0xdwNO9>l+<+@
znJcogS7cCq
zXIFPmZ(sj}iIXNznL2IyjG41$&zU=K{(^;z7B5-4Z25}i9BfNDb#>Vn3mf?OY*@J2
z$Hm1*k9EG#mOXp+GS3ya*t%=$9@As9#4UYXPaWQ4e15vL_31PB&T>zeyL05!-BYFy
zr^wknJN@*jkIAcvQdU0pw!5Ewbg{MDCg;NSfQ7l8$KQ#^`Zx1=-=3e}RZ!4eP|#jh)>Ty0Q(WAakug0xdwNO9>l+<+@
znJcogS7c8xT
zXIGa}YhV9_Cbf?4E+^HAGbgG}nd&ut*22~~^E#b07p)9XnLBm)szpj`yPdQ*EZnqo
z{*;iT}4Gbg@yeY8Pjufrxz7XDJq&;R5Y!$bXrNt
zjIglv&d!^CeD;KeZ3++H92vPKI(l17%=Va=9kH=H;^KD3$L~r?+AS-4Nm}}vjLa2T
z*{kyMS0p8GNJ!k2k^+*q#>;`+kC
z@PmQjCj-N8CZ^xa%)i;#fZRWfj6n34iRljm!#@Uw|BQ_PTUus!cFy_#|3Aav1ByRc
z7`Yhy7!>~rIv1rTmZYXAlxLP?D7bt21~BM=+zW~*2KMs}eof6St!?ccon75My?y-?
zCQh0>W$Lu)GiJ{6W0>8|BQ&p*M~8P&JCCIk|MFHIV=r62wav^rUS2jLTl|;}y_|N)
z%PA_V9M_o1w8811m;HgWmu9eTKX-1&%^lNObr0OSfAg%@G`4#Ouiw9MdkWij=UcBI
z9h}O3=FzJMZ>DhQ{rvU#MP$ZF$GEuAwu|NsBbFhD@@CkrDNLpXyD$bL|qFtDF(2ybd`
zX>Duo=Fw*EFmcl4DO0CSpE0wEWma!!;M{Hxx!{GJf%>LPm$i8+8JqgAX$>>b
zH(k#uDx`uHUt#)^)P32YwIY91;qJ*90X*HcrOdXiyQ6T^c$CpRxYKi{Fb
Jjf;iB8UVk}%KHES

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_green_north.gif b/examples/clingo/robots/img/move_green_north.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0b3fc9940bfed39bad0cd115ce0c3bbb118ddcc9
GIT binary patch
literal 639
zcmZ?wbhEHb)L_tH_!i0#926W|9UEU2A734xn3$Mco}5^bm{^&ZP?eBYnU-FWo>`um
zS(%wzn_Ey{AihgnWUq+Sb}8v?(lXm+BzH(k?2?e&B`LK-N_wBP%nlj3opLgJWn}ls
z%I=qy+at$to`Ll|E7ut=?z7ws7Z?~WGB8|bV7$!8bcu=SG86M9W`-*a3|AQ#uP`!R
zWn{X-#CCy=;U)vaEe3|$3=DS|Bo9eOHbllY#yT%>_Fd&0zA!v&aahEXh{$D;QA?wu
zmq*8}h>2Yh8@n<#epP(@>iDFFr2OXm{I>jzzKrbt?1JWk;`ZW_){^4R;^N-o;{M{I
z2}Q*di%TY!B&|+rncmVlqx1j&{|o~P6o0ZXaxsK5DE=7do*4aL%G|!#W
zFycQx!}rvl>t~OOFij7<|L~>plc|9wMlV0=7z;2@_LI|8(tPkqLqRbjU;}&Sfho!X
zeE|m#>d19Td*%qNoXFCks>yqK;faHq9@~0uSmbeiIyk?-PhoxSje{rMPgcnL<$anc
S6fNLq8Mo|r!R9~(25SKDEy>pa

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_green_south.gif b/examples/clingo/robots/img/move_green_south.gif
new file mode 100644
index 0000000000000000000000000000000000000000..58cf3bc458cd704e28661234eba864cb1cdd268e
GIT binary patch
literal 657
zcmZ?wbhEHb)L_tH_!i0#926W|9UEU2A734xn3$Mco}5^bm{^&ZP?eBYnU-FWo>`um
zS(%wzn_Ey{AihgnWUq+Sb}8v?(lXm+BzH(k?2?e&B`LK-N_wBP%nlj3opLgJWn}ls
z%I=qy+at$to`Ll|E7ut=?z7ws7Z?~WGB8|bV7$!8bcu=SG86M9W`-*a3|AQ#uP`!R
zWn{X-#CCy=;U)vaEe3|$3=DS|Bo9eOHbllY#yT%>_Fd&0zA!v&aahEXh{$D;QA?wu
zmq*8}h>2Yh8@n<#epP(@>iDFFr2OXm{I>jzzKrbt?1JWk;`ZW_){^4R;^N-o;{M{I
z2}Q*di%TY!B&|+rncmVlqx1j&{|o~P6o0ZXaxsK5DE^B=io0?l%9Q8W%v^%xsZCfWyoYZ75-`&xz-Q7QV?j*-)T{C9MJI-6)
zYP+awX792U8*CTOT%)&s!*a`M)7SI{?O0*Cb<4g36Bs;AUCg}AcW>#Ew+M0fcMoPc
z#w?2@zbXG$@Q&#
zHUbuF6xh@_6h%2W)<0-d6;zg;abUv&Hf2dw)d>m)$Bs{!EL33fk|A|DtB{6C!Ang>
k=2;fSukM`Oy!`xphh{EWuPrMsF7}wL6?^JRx&nhW0MZK0^#A|>

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_green_west.gif b/examples/clingo/robots/img/move_green_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..034fd79ab96443d435a45cb33e1b04b2fe45a43d
GIT binary patch
literal 653
zcmZ?wbhEHb)L_tH_!iC(926W^9T#5}A6pxnn3$Mco}5sbkWiJ7TA7+wnU+zWky)OZ
zRhgArn=8CeSZceJ^mb{PZ89?3Wh8b;NbHi3+$AZsLrQwDwCoO9xt((IJLF~d%E<1M
zmEA8Zzek?oJOk@_R?ah=T<5qLE-)}$WMH_=z<7y~@iHURB_^iJOw5;<8LlueTxDRq
z!pL})k@*TU+XXg;n+y!M7#MCdFx+8~I4lv_5EZF$GEuAwu|NsBbFhD@@CkrDNLpX!tKSAfB)Wnk16ovB4
zk_-iRPu~Cr9gw3y5yilMwIRHzxuvzOy`!_MyQjCWf5OB`lc!9bHhsp-S>X(`yP3V_
zbu#jsEox`u(|29o$|ho>xMpn=qlmG-g721aR^c7`suosOHa3nYX0mQq)juaMuc~_S
z(hN>Pf%TKbZ#>=hZA
zt3Xm-{-%V)4N1vcKvGKTjlV
zhmr9wBjY~?hW|js$oPke=?5FzXHL#9TwD)?g`Y@BJdl-bkBn@NiD`_BYlx3;j*IJz
zkKgR;wvM&!FjHUskyn8mAB!x?V>wpN=eC{IC*mWHX)~(vfBi(N|Q$F11{QTwXbuQNFS8qI#_#(Z0O~U4E
zA(oU|A6L8aN*N`TbQ>g0TcC7U>B9z%7e}=@bu73ZU3_@NZK7X@NeMLs*imdE)8JTPH^4I0%Z%Rnqkd(YBDS1~~`nHVBeOcMNa&q5US${Av{A6JG
z4Ma>#znPi;FfjaKWc_>Y0%KM*l8{$XPJ%f$49jqNiR*B5T?$C8rmk&(?YF-@_t
zjd5|EadDfSo%i_otPcy@6c)BQJbX)Jv`Eps|M|NjTN
zVh{nvpDc`A3;_&^{{)?jQWHy3QxwWGOEMJPJ$(ZhbU+RTMHB=3p@x8_=9bpB_Kwc3
z?w;Ph{s|K&O`bA!+VmMSXU(27ci#L33l}Y3vUJ(<70Wr;mU8m&urGENP*K^iaI=cM
zyb2%de1|Q2_UvVv>n6T+*Va8E$7Z>Ssc4)!yoc-jbPtKsXYQTVo9=Vx$f>)hL>^A@
z(SCON=~ET%R};M@RkWmbKl>;zrMa!jh3kQehmfLw3XipWl5>x;LCppQrUOBf>#n91
sTw?5(@9pKD$-A5JQta0L*?AG4mvyIj^_+>xTI84$Zz|iz#K>R`0D!*ARsaA1

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_red_south.gif b/examples/clingo/robots/img/move_red_south.gif
new file mode 100644
index 0000000000000000000000000000000000000000..375c556ee78d2fcce80667712cef9fab4ac7498f
GIT binary patch
literal 627
zcmZ?wbhEHb)L_tH_!htr6datGm{eMLs*imdE)8JTPH^4I0%Z%Rnqkd(YBDS1~~`nHVBeOcMNa&q5US${Av{A6JG
z4Ma>#znPi;FfjaKWc_>Y0%KM*l8{$XPJ%f$49jqNiR*B5T?$C8rmk&(?YF-@_t
zjd5|EadDfSo%i_otPcy@6c)BQJbX)Jv`Eps|M|NjTN
zVh{nvpDc`A3;_&^{{)?jQWHy3QxwWGOEMJPJ$(ZhbU+RTMHB=3?uLM-=9U&~S@q7Y
zE|b>2{s~PM9o=2B<`ZX5G@mk6efq40t#jse%33d48DKVd>he{KOxAYG`fgabY3clJ
z+gli1bnFb=4L46S@^|!f^kdv^%cHI-wQHJ`rn-dp-T+L0`6`Z?dJU1;lIawokRm{mvOHWTXNN(d|VXy`OeAK{0

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_red_west.gif b/examples/clingo/robots/img/move_red_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bbd9f99f260c870b4dd4329302336c6d79b26bb6
GIT binary patch
literal 647
zcmZ?wbhEHb)L_tH_~yqD6datGm{^^hT$`9!pO8?KmR6mSQInNbmy>f%TKbZ#>=hZA
zt3Xm-{-%V)4N1vcKvGKTjlV
zhmr9wBjY~?hW|js$oPke=?5FzXHL#9TwD)?g`Y@BJdl-bkBn@NiD`_BYlx3;j*IJz
zkKgR#FEq$h4Rdj3Tzl94j(6tCzIU@o0lmH2_B1B}X7
z55u27jDPaRdG&aUH
zG{iSI$8~nbZ{F;@XOGYN^4j6K6iu53M5Qxkl^(hS-n0UbGz-eycTwP$Y^*jYj;qS)m*)%#aBgkgX>%qa|_FT
z-bUNE3p>w}+J5}xAsN{tGtbCgxNurl>*(}DH*X!{wY_os!FHZ|Qy)G!BgFpn*{v6B
zuixC{diCL>EH~@@Gna4k{JejwFLkzpLU5m|xzME+5rG-xj-f
zPvrV_scYAyuUwJ2az*y~b(w3|!hK
zo%P2LhMzwfe*Xp{rayle{`_J5`f%NOp)k0smN
zBb%FJnwnx88{;}V<2G-0*|W!I{ra%Yo5QzkiP*X|YTLHx?b~B^?1gp=%?=PJ)rD*EZ;%U>0rcW=PF{5Pn?&R6C
zTjtE^{10@&U;>IiSs1w(0vHtk2|5?0CYGe8D3oWGWGJ|M`UWuQfLscSCJ-vPX6DCfYJZ0*%=`&`|nmuRky!i_jE?T@~>9XZ3mUFT%<>KY#SnMpQ
zs=8sJ%N7L%RROm74!czM>}8tkD!uja);%J}X1R->K68cp{B)0#M-JaUt3Tc6+5rG-xj-f
zPvrV_scYAyuUwJ2az*y~b(w3|!hK
zo%P2LhMzwfe*Xp{rayle{`_J5`f%NOp)k0smN
zBb%FJnwnx88{;}V<2G-0*|W!I{ra%Yo5QzkiP*X|YTLHx?b~B^?1gp=%?=PJ)rD*EZ;%U>0rcW=PF{5Pn?&R6C
zTjtE^{10@&U;>IiSs1w(0vHtk2|5?0CYGe8D3oWGWGJ|M`UWuQfLscSC(4$8hs7$490%N4+0?Wu1cDB^h_spXv@CFB
pW);?#^_Z}6@$r5I=Pnt~O-oKr)(Bn|b8^$t)6)%->$q4LtO35f<;ws7

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/move_yellow_west.gif b/examples/clingo/robots/img/move_yellow_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..130a4c10ff2460029d3bf97cb522117c88483b06
GIT binary patch
literal 643
zcmZ?wbhEHb)L_tH_~yqD6cn78m{?t%TwkA1SC?2*lU7}wQB#vuU!QyHmiV=6(w8pD
zUb!N3?HZ7jzj;&Q#tq3^w}7P7-Mdn^Zpq!bBXjqz?Dy}iKYlR${K@e9HxM!X{>}X7
z55u27jDPaRdG&aUH
zG{iSI$8~nbZ{F;@XOGYN^4j6K6iu53M5QxklHuc^7EwXMCQv#YzO
zx37P~#7UE`oM470oS9p`oGb7?PX*H@ReS>CEIsHkeNwwakrQBmAwiysTW
zqVx_!V-r*J<5n}7_Ddf;aQ6J!8LYeqc3i)4eL5@mwQCoyUzo;r_u-9mH>R>}IQQc1
zj)T%u+27oJ_Cj$Q$JGZPpI@6^Rr0x9UuKzt$R5oz(>zbKRG(F1x~#Iq$wJb*B*Vrn
zIasiJ=d2GxQ;sa+R8aO@^q@gyse-Cj-42nKmXkh?jCrr_oZP(p{CsO>Mh0sDYoGG#

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/random_robot.gif b/examples/clingo/robots/img/random_robot.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d8ab1ac6dc46adc07e1d69bcbcc22cfa34dd2053
GIT binary patch
literal 1415
zcmV;21$g>LNk%w1VJHA70QUd@dv7Rwb0mIjGkRz_dviT5dTAd#1>@N
z0BhO+bKU@Y+yZRU6HMm-SL6U&;{aLf0AuF>W9R^D-~e{$16#o$Ysf7)mqsywT{VeV
zEr4r0gK1coUSFz9TcJu?pj=0TWr~9>HwGE5T@h=tmy)`=mVtl0T%=!Vr`2p4Q1=sxm+xr6M<^=uc1O4d)
z=Jo*P{sHX%0`&a^{r&^{@&dxeF~-Y0%*Hv+&^x%6V}`tQg~vd80E2e`iF*QyX8@UW
z0FrhumRJC+S^}a)0K7^8xlsVIUN5LvGO1%MxD`#D3sadSWsDU_qYy~3JyxkSNxU~w
zw@hEBH~`Kr0M;V`-VP|u5Gu?LIm!iB0sa69{}cf602uQj0OblI;Q%D)94YKAGT|UJ;X(n$H$}=V
zMALu(f&c&jA^8LW00930EC2ui04M+`000R70RIUbNU)&6g9sBUT*$DY!-o(fN}Ncs
zqQ#3CGit<0Wd;EY4IE$?AYed7VV5!m1BT{MKV?69Jkf_JjU!){cub)PjF(SYd%DD1
zQey{_cv<++;?>I*rimMV@!G}flbdSuP)u5NqF%K(pr-QjH4z4}O`15(aZ}D&hgP;g
zI4kF-PN+|$8cC2?A<-2rYTm?=XUs$`SvHQzTa%|vn>%3yNTk5;ojrTw*ugXMh?J;D
zM&OkT7Y-b`Y!M`8fYRg`vSrPfaiFxx52X>!ymjNYZy&V15gic8f#Zga8YOJ7`tyZV
z4H6|vm@rX8hy#fZgizYGD^w^{uTK6UP;ly1DpaUy@lrM9dc+G!I^ehkiw+zF3B-vj
zR47iLSiC^u!3q~lh7K|#kWk4koqz#OJn?)3h9xu44Pb^ITf|dL
z3An)F#VMk6VFxQBG@}j|dYl2nL}cJ$fIBHbGKw6tv~o)+Y`|gz6Y_YmM3oV8fFs#polujm@o+mCp06EHRHI$LuwdeXJKLr#8(}
zoBi+?;#xYE#-=05rRmU6OG`5&Mqn~>EWsZ{QHkdMi9VdS^Kdxl=q{X7pSsL}!%ytf
z4fFsu;4#okh?k)?3dLZ0`k+eXQK_D5
zwIdZ3PQV9D1GB(eU|uSnX4yI5J+KV;qoVxL(MuxHvRM3yVHOx>Q6%!m#C+!Y37(%*
zD12F2KBaPAp;*YwTm)8tRhnJ}0)*`A8zE~HwMNqcAOw5|)`1OyU_&SjN+dys3B|{U
zq|$wBi>9}M9|$-51^fa20y~84L`3WWyM*ildxY#!)SkgGTUxqMUjDAG?rC4&q|5ao
zJjQ?L=x>?;Mx=(5!=FH~d&5|5uBolNWvOqt-FWA2Q*+BbYwP_74p
zmt|8sQEzHHUlcr&Jl))slT|owsc$v26Iawp*JtcPS$^4Tv3tAYxRtv(I
z`jNhs*!22U5yeStBM~G_dD~Q8KxD7`y+FhUC)ga=9s#T3AtwiXKQ-~{KJPr
StFv7fho61%UON#<;q*V`*VQ!u

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/robot_green.gif b/examples/clingo/robots/img/robot_green.gif
new file mode 100644
index 0000000000000000000000000000000000000000..456bf2f4d1922f3edfbd93dffae43f3e3ed99361
GIT binary patch
literal 1142
zcmZ?wbhEHb)L_tH_|Cv!+QMMk#$eXYVAjE4-o;?i#b7_1(S8nt{SpTIRSXWZnH*=c
zI4)#xS}&ut9eyBNIoGI;N0@Y%!QvyZ`dKcmkc7QekLzWZ7I_OS%)
z;0oNy9kyOFY_)9I8rh)Df+1UlL$(QrY!naOE)u#^IBbV#*k;MFIU3<}HKOKg$ILN^
znQIt3*C=+LQPg71=mpx*OSEDa>BlbCk6oq{yF@>Jg>J$s{iOB!DVy~Z78xfkHBDS)
zkiN<)ZJR;*7Nhj7##uYed=D`C9cJ)9#OQl~$?ph*KM);d@IS^7aGW9F1Vi9yhJZ5+
zfoBX5qy}_?>0m51%}{@3?V>tnIZHtL&zn@(94WrmzaaDGX!5}2))7(
zdX*vUDr4w1hS2K_Vb>YMt}+GQWC*&+5PXXvOW8WZOI5lA`IvOwPdz#b8a
z%jXsN<=B2^K1y4zXpj)KEu}f+xt~FVPQV6-tsG*@^>4axx~vFLbZT6*<4z}QSHFD&
z!{3jLtlbyc_yklM7!(x#vfLdw;G?rNf?t$7aew($W`7
zB>C9Rwn^+szWsoqjay7F=0M4Vi8hZzA7pF_KG~P(TH3QPI%LO%kIo$e3YKMCe$)xR
zoFbqUFvp_Nsii}6L+$jG$+BnbOv-j#ly=LL2x}2^jhK*-93r}OB7>lg<4vJnQ$a=s
bYr_Q(+hkrneb}zhrtzplWtvBz1A{dH0TC)L

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/robot_red.gif b/examples/clingo/robots/img/robot_red.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8eb8335cb2845bf383f5e598aa57efac9e072906
GIT binary patch
literal 687
zcmc)H-Ahw(90u^`cRac&bYYupV_Pa%Zocds-L$4%97xOvmFcD%NF)^~NP3xf<(4_E
zEbYZt%r#$F88%0jOLJp}T3VVJGJ=v(vV>Bks6?B8MPEJ_&)xID_xOq2BieEW6!;1B
z0KI?>xDWILZbIA?^&A)vWttvIOmry}<4H-+7-meRax=_CO3I7WR42*uvi0U%)0!{{j92+aZMP0K32rA-jZZhlTA@R8TBl
zlS+d!Sx_$bFw7jocv*HnJ>8p?wZO8AnVDl8=culpH5wPn%HC8|JgBet4Gg>+9>)K;
z_}?@EOi0-)-}?!8I~PrLX3ORJD-G7hrmNSkH{ZC~(t7Lmox5%Ajr^|2?uf1q3uo`^
zx0yL@p&=o`P^jew>m0h0*w_-C(`D+P9C6u`r>0c)2`;0k)MzX%%J2?y*#*UVeQ`nd
zl1(HLNo6wWXVHW?*%u^){vlB+B^w*0L#IwKV5)`pE|Cl3Cm261((2?&*E_!Nw{JyP8xSkWfR&%CjMRGVRaO_;~kbiVvaCNr(
PFnRHyJ?fbrcH)hwwP?&W^(8d!-*3Nr%o}PIm2-79K(eR
z4A-tP+`bJ&TxZWpo;V?U<%;07Yr@yBi`>2~eDkL0#fuV`E=fFi!0_l1!;>dK#Q5wP
z_5`Ih=FZ=FDnwSh954qGkt6|4JrfnOEJBs#A+SLXmw|Xv;!_GwjBAUdO_21IAo)q&`ow)R;KjdL0r=QTCYYiXU+(mJoLeO^iFx`xI@Ev*X-
z3@;fNUNJMjVP$>C!0?@c;THqLZ)WCSEG$6un}OjEBjaBtroRjf{}>tnF);jRWc<&>
z^q-meKO5U$7MB01smIdNj_2i_&CNYmRCK1e`0W1ud;9uM^!J~bH0kuki$|_qJAV1{
z)ytQ!U%h(e+O@0KuLIF7Ah>hqJ`g;5bp6@0YcF2hdGzSnqesslKYsq?$&;5aU%qhW$Lu)GiJ`3J*S0HT56&AVsU|G0{kmESXmgR$mnj|w0VoJrY^@6DP8rw
z8}}aAt9e*mmvjBrZ3=SRH*eoLdBf3-O8mxFHl|Wao3`^$5#Ox9WNGK&<>_Rhu=)Pv
zhnJaco$OuQyu(7xw;z2s>BF(23))3TPEOVcX<_&x&iQ~x-kw8h$)^<0Nm9B=TM{@t
zopc1OCJ1Q$Xn8bA*{hI;LCC^QM>qu6*s_>pUktqz9vP`nz~R|+
z&Yh3(P0H5ZFQsccxJ@fw%$V44d%c*HhT?{+ZU9+uq*ZQT+PeS?h8I25SI!K`EpF

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/saturn_green.gif b/examples/clingo/robots/img/saturn_green.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6c96685e08454267891c975333f107d059b852fc
GIT binary patch
literal 825
zcmZ?wbhEHb)L_tH_{P8xzELWCqjdO2`K0N#QEQZ=*D6P^Q;uGv61`3(X1z+xI@Q>9
zsxj+Yh}7eOXp?%}4yE`_8gV-`5;g&mX2NF8L?GIvmAFYeaf?b0xau3f!;dT`^}gPYHu+7ysl9zA*T43q)IpDc_F4A~4iAY(vr!odEoA-k!$rM0cS
zqqD2Kr?;>=NlOa~iY?>k=i=nxVq~5o?rLGXZTpUG
zF19XiOj8ssOmvUvo0*xLn;kxK#D!&woUN|@Recu~Wo30k)3drR98;t(>+2e-aC-Xs
zd&#L>)3xP#{M1m@!!Iy8E;`IdEop}GB!ydBq%q!c`YK
zE*|I<)r{EGA{flpJC*lPhs%N~6OVPO1TJgg2@c|!q37jy<;6y!Xeh;w@&7G@b+1kk6F`KbxMO644Hrw8Y?g^9Pj!SCVEVBrWyc
zui-bL$3Xo&vnuP;RTFP4c;Y!(g=>ZBW^c~Mhxvwn8P^_lu3L8s6gMwod2fvT6guhov2ba6m%J}p9_Wu6<;qmGD{PqG2
F)&S1+S9JgY

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/saturn_red.gif b/examples/clingo/robots/img/saturn_red.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8e88420050f6ef38b4f8dbcd2cf739d7fc830f9b
GIT binary patch
literal 763
zcmZ?wbhEHb)L_tH_{PAn%GUORwDd~`hF1&>Z=_{+%n
zkAdMo1H(T?#{Z0rf0>y60}(UxFBX>HEG++7SpKrH9amO9p`dV5LE#jTp`vn1MddV*
zR8>8#s(M0A?To7G88x-DK%}mI4u~`~&I6IA=2>m+b6Q&Gfk<2Xx{}gG4UG$0T6+Tm
zb|)t8NlZMJntD7f?Obl|*}S|nMMYny?y=q
z?c2BSfZ+Z6=U=|O|L}of;DF*!7Dfh!a0VTa6F_mo!2Yixys5dRwXMCQv#YzOx37P~
z#7UE`o>=d>8;>MYb)tf90_NpYo=I3vRpJ>HF*HgDnO=9QYF!z;3P%
zxetr*O0VC#jfH9Z=IuKtZ#cS)ai5ztUOq`IEXY?6uQ&m$)%Dmm1gIdNmb
z^Ci=d2JvhZTKeLmykk+$kDEn79rL*hLKbd1!XdcEHpwLWLg=ON$Vip~4$r1@?tKz(
zQnvPfDP7AbVpj2D#>U3m>)CWPGB;d(tK7JCW8TgMC5_h&lJ>R4>P@S-lyu@`is)<`
mPKO5Wl|jpe98a-wU)N12ndQ5C+uPeaieKM5YhA9uU=0Az7AZ{t

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/saturn_yellow.gif b/examples/clingo/robots/img/saturn_yellow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..909af362225c5aa8c5c19eb70751e23083b59bfe
GIT binary patch
literal 763
zcmZ?wbhEHb)L_tH_{PAnYL)G(RdyFHNWXl^@ah%An>Wnw-m!lF&hYCO!|&fflKIac
zhQEIq|NUe5|DWOCKgR$68UOxe`u`t@n1B6Z`Td*a|9_Uhf7y;7S3Yq<;p9mmsdDO+
z%IVWUQuV|MwKHc_&zw;^dlrb)&z%Dzjq~S$Nb~Gj?epig&Y#!5eqHI}MU4v=wD#@|
z*u6V(&z{6%$5PLp%{zOxc<CC;3?QO)MOpootL*Hz`bcu$xQY+}g_4-o?k)m}}4b
z$p<(OJ0u_HlXvJ-2|Se2?!d18z;ed}1vWle4pA*nCzXz#PCf>&F7pL$6M8&nC|EM3
zbo4Twba7)6T-VU6Xm7HP<&v@o?+iuFi#}@3922K_M*KR_sLXbvV{!(U^TFnmZc8o8
zF8r9lz39R^t~8TGrzh_HGFEwe3fQ<;smzMp$aUt1Vv2`=j7i)U?&l4xOL;f*&6$z7
z*sX{EPJ(Li$Emq%I9O+$jq>4i*4uWl=B>~+?Iwd`lNqd+x!!uO!oXy(z{&L$OLu^F
XOvxpL`H

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/star_blue.gif b/examples/clingo/robots/img/star_blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..014450138c2394b1d9ea5bc394f75525b08ec090
GIT binary patch
literal 721
zcmZ?wbhEHb)L_tH_{PBC>}=xfZ0hQ2?&bzW7VhpAT3Ypbdi9o;^?`wI2?>!22~kN&
z(c$4$si`SRN!7WzRa#mN`uYtfCcR=}`}Or#goZZ9#56@mx465{4G&+Cn7EUd_Ywoc
zeKE1?!oqhXC2trRT{bqpY-)OyiRl3Y!$$^&AB>DY85n*sGX7#<_|3@pn~CW+E9*}t
zraw$ff0>#8GBEsOVEE6-_@9O4kCW3yFRx2ML6^$QPj+|joICg8!iDFzZ98@3$c1y~
zE}cJr<-&!_ckf=ifB(k0bC2%de{|!_F{hY_uCaxMv95?1=WJe4RbyifYikVyV^vY!83Mxc`!tMYotp~&
z=y@>a6YN~_0;U#`8)6FtB_YAt3nrZ)N)PTvGMWo
S3CiB{e0FY1^=@Qfum%7eO5_Lt

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/star_green.gif b/examples/clingo/robots/img/star_green.gif
new file mode 100644
index 0000000000000000000000000000000000000000..86bc3c68ada6e62d8999e290b6a7fe3b6108705d
GIT binary patch
literal 757
zcmZ?wbhEHb)L_tH_{PBCR;cM#sO4UyCKsKdE+EYGjWB060-Rn=xU4L@!hT{u2oLIQ`*tWgLx1Bh57!@QpS*nj^yQmZ@7@5x+cym40>z&!j0_C93_2hKKykvr
z{;wgoskx=Kt-YhOtGlPSuYbbCNt35coi=^O%vrPN^oaQSip*^l_Ld3?lJXW_%*!ur
zuNxYwYcI{uJDX2I#mho9I!e{fMMZ&chB$|;qlJl!L_&gui;0D!EQk0sPJJ(v2QKod
zsWMm3dFgXbR%TB9Jez7@q_;@B~Y2JOdF6HkJWqV7wbTmH;q#WOuak*p9frU!9w|VdO5cs(@_4J0M
u<7PXXRJ*73NAI+nYBe?Ms)m!u91FqHU0YvY-;jKIp6~8$Z@n5B7_0$4nj{+l

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/star_red.gif b/examples/clingo/robots/img/star_red.gif
new file mode 100644
index 0000000000000000000000000000000000000000..96917b9630e3d1e104c03b34e0cf0ddfc42a5da7
GIT binary patch
literal 721
zcmZ?wbhEHb)L_tH_{P9cuccM5r&n)jY2xf`>g;Up>T2%hW&uR*?rwpBRpH^02?{KdfVn}OjMBjax%Vq*Ho!0;c47#aUCG5rN1X6B!)tbbToE*lwLHa5O$YC6~5
zy*V_rB|5q(CT2l+_|C+{i%w3Lyu2<21)VG}-`U-Laqisn3m2Z+w(Y`^BbUydyK?^g
z~H9W^Nz
z7peX78|9g%axh%c+NkI1rn~jdIR>^VY>fNVG>@3MxtV==$(@iNWF;)ClaLYU>^@1w
zDr?Ju4UKV*p1dg+P8?i(ykEg%iiV{SiwD1)WrjwE!%D}VURirN!OkU5PEIk5@RM4g
z_wY~~zp~$!2R?_6di-Gd_FFt)K_@5sJ5P!5(=EG|^q!O&M|nnfRjL^@2p?a2XQ$Vx
z8MU=yxwDLg^{;J+y>(UFwLRf*m+b8)T1*=wf9E}Y74j-%Rp?@lTCS-(HaT3ww~
zRh7GczgR?bAzkdS})4zWV|NjFKeUNZuim#j0_Ck
z3_2iZg5rdM{a=H3Q*%peTYE=mS9ecuU;l)OlO|7@I&J!lnX_ik>EYJb=bqcjr7dD&
zBBIT;m`#UQUD?!BS)EshZ8p1*q_VP%g@ufovZN6E3?4zTeKN|zPENx6_lXJeOk+GJ
zb4OX+*;#zQ%tjf;smu(IpD1g&xN2>^bB=*!3M=EjeMgL4U5$TzVbpN&Y_Q^!&{{H~
zP}y^mv{6vV0SA8uRTjO38z(k4ALm!`nj*n?DcPM*+8{<@#|@`sK3Tga3C_-zC4G|(
zqSnkYIdE`&3%9ggkHyAEd)bvcRAn!|k9UY?j@XnjbH~)x!7GDThV?3a(Y*5L
V_ylF|c|JQgJv}``mz9aZ8UWa<2j>6)

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/sun_blue.gif b/examples/clingo/robots/img/sun_blue.gif
new file mode 100644
index 0000000000000000000000000000000000000000..79f743be8c6e868a5de8c195f5057cd26a739db3
GIT binary patch
literal 1147
zcmciB`%hYT7zXg~Ip88`oRDh4+hVn@bTf{2!PvPax;T4ei@k}_c5_;dRiZYc5$7ce
z7Dr_oMir3RZQ^B>(25OOWvybJ6J@8O6+{IUG+s(N>!fy~meGG=pFDYgeSUcIo=b?2
zI-5ZTWbhgQ1WCDiH7PqgB`YiK(xr^-?Ca_2Ik~xcZcJttgHgy}6crQ{7ZsH;ndQaB
zr7TuCi&a@tQdL@7URha1q0~l3@`=O_Kfg{Np9j9as?gAZu&_Y{;U*^XX*3~?cALTA
zu~^lmrPUP`?8-`ZRh2t66%{|k#I(i6w$o^e^XL06Ummz}<#A3<_l+AWCi7ug*^s}#
zCLmzg*H?S&*f^1>Baw98-ZKC!5eNnnX~xgb5Ey6)3R(;eHAF<1!owG-)cL3=v$wa^
z+j|{@v3q!IdU|f)a2t5MjYwSf_g@JJSPcqVBM>%W_$3T)1F!?buOR5Phlc}#{smwU
z04D(Z5VViMIAM4nfCB&yA?Of>4=|Vm7(N8x4FE0(a$&It2r@>e&(P_H)KpVu=16Ad
zANlzcd3n0BvJp0$wo0&ngjx2V`HO8Bod3oB2lwMB6aKT
zmI{SxsdP{#Yi(`qkjdIRI)0PO?<*9Fp&@x!*Y7HoO06Ck9DJ2wn)>b{dRGvj(aIyd(eMGYuwM9~Gk
zetK%kU^E(LXN^lsdW*%V*PD#SrTO`Jvw7ZPu~@A$R;$5kon2iut*@Kc*DW^Nirv0!
zw_Be-U)k7L-`ZN;+FDy%+t}Q+@9w^EIR4(<-Eum&c6J<2=S!Ds+vWPl<#Mm^|2e*g
zg#a*v@VAw3e*$>E0Ry-|MEUD*jpxx1zSb&RN5030(pr!n*(jg%F~h9w$>8CG2#c+;
zD~U)=aDf>V3WK@t<(nLoscC`C=aYEubZZFyXF;tnmvK6r#7|H-ZpPug7J9yY$OzNX
z(=&fLck5kxbnp9!fO@B54{Agb>-y>a|0Wq2xms0!~v>0sb|^)mB)Tmf~&E1HA^Fslcq+!ut;$=bc6!fSSFsy
p!N^r1!+{Op3j7Z5^b(zL_NrZ|t
z8iu@dv(j*6xuTTkR3s#bmq>UbUbA^=#f=_qUES<%*8UUweExvXPoJ-1qQlRn`U8Kk
z4?qYbB&;xuoJ>x_pwh>+i03Io?C+;VJcWle;-|IXEaC+`8S|yWPDMUfv3Czh*xILI~;)3LXd!9SA+E
zJPWH~j0OY70hj==7KSDvXbOULFsz5IC#|jYR`zOpU;tnmfEfT#0HZJl#Q-A!vj8$e
z&@2Sz0BnRYMvRrw3d{qr0HApYT7Voij(8Q`L+#WiHod`B>hZ^
zk;KGH
zVO~*RDPfne*=$xBtCUm9DdUvzN_Y==d;y>TE5D9YCoC5VY6P{lwL+m#^Z~I*EEcnR
zSsaAJLwH;Tw?bJ_rL3y%s;)=sC5WWGp}kSs*d%R|N~O&$&9bL5xm@0cv?-q|ksbu;
zMHDX-1B!u%s)u|nUpOWd4T&BNKN9Ig@)5aACzFrKTc=x}k3R1m>qSP9{?Y!v@xHFv
zE@TE#sZ@jN!Qs(iokpjf(2h-vO^i?ICUknOeo{X#<4lbC${dbp)8?6P*sy-L$IC4UwC%FN$;>->ZEk%9!Hx~)_sy|
zyslqz$sBob`nMw7F(UUwbcU&$+mx6-Ui&F2{EH;hEy9T#!7UL1LqAm>q11;-s>>?c
zs{^8s;m3$uaP;|l>AAEdV&@Nph(+=f22LLpN>4c|%XWXWM)`5?TBrch5R*;?`Pkj$
z)!Nv766lI0QQc05e`%+jZ49{D6GyW7hWL2!5;2NPcahwA70ZuDBO4`t85iJ6z(~~~
zH=kev(~#)8liz;kVe9$bvu$ih0>Jr3rYd67{`C-v~0!bfC!XJ8kDp1w|g~O3@X(^Wq1;RBOI#5PMyYf%$lTV)K#q;9(;+yB2
zsK~Gr$uvL%+W^EPNZh4M$+5BVsi}!9)|J%Mw4@|XdOC;0`H9WWVzaZaUS)B)`CKk9
zD=RNMJ3lv6!OLsF
z+Z!bkb$)(5{{En0Pmba(0c$JP9bO)hTp;PuJeS)&%3+N5s9lF
z9t(bci~jygWU`4uu>=LZpwp*9LT19kiV;K{9W7xn?l2e);o%P=B2)}UTTD#H`SYC@
zFP5^|g4|p|UY@X^K*;9{3k!=13vU(_G^eF$u3h_`%kAdz`VnND$uu#UmV^X-O3I%p
zDJX|Cn3199@kBzQNF*v23QLNM#bR-FY3c3qazS;qNG6k1R#sJ2Nu^SmOmGjT;8B
z7!!*P6&0rPaGY9h@!(Niei`v!^{{qjbWJ4I50l`d~$Ns
zXf%zCn9OGL#Dv9YoHd(`v$JNab;`-ijMZu#x7kcK+l0+#SzMf1UbZeTFU-%cEG^Bg
zuiMtw7uMF6S5_7`HkLLv)>l{m-rD->&6^FUcKg=m=1aT%mBaCm!(n$g`~3envV(^J
zm;v;?$i1Hcg!iDsm4v8kdx{7Lk9}`Y*Xe(8r!Z=emik_?&*$tJL(36j5ZPnN_jo`I
zQpEiFdJ|W2xcFd(rG_vzY77V@N0zN+UN+vZERkFu{fr*(9rbwY`f2t4>6S!ICKY8S
zr5uVY`-pk6wXf_>NR40zszRdsu1vJ?8KVsuw~oqdKACPEx&7(KU)|K0?ujlml>fj=
zP}tgnsqu-yqsgAwLm=%sjy4G!fDHMQWr4UAyrxCV|5+*Oc6hSaABFp@2R_R)b5&vg%o
q#3@w)J){aSf5ylC%UT_t^cq6W9xkEHmmZa-&6m+08omn$C;tPZ(GA7`

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/sun_yellow.gif b/examples/clingo/robots/img/sun_yellow.gif
new file mode 100644
index 0000000000000000000000000000000000000000..1755e4630ebeaf1ff2d3ab0616346f9d084a2fb0
GIT binary patch
literal 1144
zcmciB`A=H~00;2bf(pbj?qd@iI}9o=D4SthqPv8GZpI-Di9_mS;TnTZCn78Km6nDA
zLRkyNnydwaVdcJI*wQ!BKHj4oZC_hjLMca|h^3n)AW$m%C;aA<@2}sVzOivJ(dWqF
zKsc}k0LjUugoG3_`NqwgcW&Lfou2+(W@cJ;c6LrqCWVrjpPxmc+@n(OlF506g$M2z
z6ntM;_@JohL2>cJ=H|ebmf-GgzusQ|!NE6~%t$u-tVD83q3}bH00aq?N{@_<9Yv5J
zjm8_pywvI-wK~{n3^5u*O(tM%jkvKvSYLOsSlld@!#M8#{5jEX2R1heo14VV%~!U!
z2|GK$?(PAXy*`}=^?d4S+>5cl_qPUk_pY;U_d9Ij@w*V2-g*&K-DUMnj{
zaXbXWPUv)}_4?Bb3lRoGl+k#O!632O*K2Fzo0={*HC+;m~?MNvmbMt^_qzyL)qk5#J^HJT)yE*XMuLr}V0o`oQ}QfVOs718N5
z5CjlB@%FCq(&m)NhE@X
zh7OUav8hSe+$?NqX>MT`
zFkFSAzi2d-FkC-1B~Yn&S}h+z+NP$&Dpjja_d5*tA;`eQ#Nfol2#OA)=!jn5sn-un
zrBVoz!SFK_l|#_v__z{5V5Jh7m_QL^QmsZc8Wh8n2E!x_tCY%FrBbg_O=H+BhG7c}
zm{zNso0~HjjPvvJGczWY%7kHNt#%2+R`hz4(YQK4zq+_+!tqs$1z%qN%WPg>TCy%L
zZ>+3rtgYcztKDkdvRZfT_J3@)Et_rEW^>x@&Yc}6@V_VQUsnPE%mEQEmtTGYaN7s^
z+}|K|J|3gH`M&eDqEiT!d7X$Ckh(88w@3;HU5^s^oWZ}XS&yZ
z@N3bZ`umD&G3n~=pU!tT{#_MN#|u;Sb@b)AC{-fMOG%1(ttcea?U*<5)svl47oWi}QlRH!j)%*=GoskQ
i+^e>W#KU=yVng5i0beXT#tb*JPVzF2Um*~H3;zM*Sx4{y

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/tile_left.gif b/examples/clingo/robots/img/tile_left.gif
new file mode 100644
index 0000000000000000000000000000000000000000..f15666773b3fe72a14ee137612af9ecd69550b2f
GIT binary patch
literal 1724
zcmd_p`BTz)9LMpmW~OYdXx`ceWr=2GW)5Z3sF?>=W}B_qw3TaPxoVTnJ8YF
zO>{^F$fA+DYK>afmf{s+h9~zW#~08*1QjFLZ~JfTYaXBH@9!TzvGFnJ-Dgn%3Rnby
z!a^(-TZ+ZvN=nK~OUt2ER^rObE1(gH4@sm)6iV%1lv*maww_Ap>Uz-DR^Qgv(A`~2
zrxRGLC!?cJ`uiyZ{gjcB=1(I{EEb8&Y2tF5v|6gw+F&v@n$3+?E2Qb`*Jg_a^0(Cr
zX|Y<{zI^F2n_pWjudUYC<}Yu|=C>BhTPwu+&!-V4k2ApI4)D1HW21xPV;?3U1tkw_#Kio_xjsQ3UX7%GSoG6X7^DkWrC4Kmc=kQ!uaAS&jJin(m+
zS1Pzl1y3&HgGwH#qQcgSR#^0#A1n9
zB85n#(-0|SS~fi`m&xRExdNh4C?QIS5>zT@G-41`s#VIF8Tsc~`RC6vEkp~Et3Xht
z0@Z4jMx&nBiw*NKr<*k`X_ieItyTy8pN2Hq{daEAw|@H*fP)2?0^w0D#O@-8wVQoWMKupX;2UGi
z8!nOi%3OEgoue)c-M@_p!1|h6SI5_EPRKQ&LeepJHlJqP;<(8AtF|X9f-dBxAAIV2
zO2NO-*CPfz6+34%)x4Q=&A)^a(_g5q%tJ(PIvOn5g;TW&=oR>c9
z>T`yx#J0jMIKAb@3dgJ#TkoDzQ!%c4*zRj%Q#;ddAxHAb3}27Sh?@>>o^Swgx*_g{
zxu>$RKkP9_voIm5GlSlraMJkiHV}!CHfYQZTiE)n;F5yur8`phItjG~nbV8Hz&7wx
zA^?}H(w-HLY|>NT0wB_*9DzgjBH}Uk9ap;{bd)NeRN%esaf}D$dm`?#ea;S*c-2Mn
z12W7W9fgakbb`Yp?$P2(HW9WCpICp#m2-j=m>&d>uu01CJa1!v<_N|g3yWW$u!$2;
zQjm`ZfJdmf2%yUCJ^XQ?C3|&^G`FH%j(X;}S6A;qlQtAOY<=So+tT_m)h`b&$dvf{
zTx+SbL%S2ZpEkS0o+G1}e%#m$Gy_&oZWMQ~asuEtY}`u4k*ho^7`VV(&$OVU#IUOe
zibKe)J@$@hF<>9u2^6h_r;{07nWzv=wvj{G?^<^=p$wJBPP!D(b47|>N0mJ*^RD!~
zbC*nX!L8_3ICgOJwX}-IfjOZ!d+U+;J_mdP^2jex;q+L+0NZ=vXmUpNT%VVJZ98`~
z;f0>j^6Z%&=7(n<{B_uWCvw31WCyauCpT-WS9;EocCWR`x7*XM2V`H$bxk_s+~<9@
zcXj|#uyodefXE-7h}(z{wM}SWNbVc;+9f7-O3zB*?(hf@xaC~^+k_h&eszw>~m=#
zdGv+rUi{fw>|E|WvOB(`sQp@8htKuXu_u2Y|GFp+cd{(W?!Q|JZ;B@G+ceXW81MI)
PuCgn{s&oCzya~BzxMwvG;kM_xb$xIp=fE_q#hLdh52-
z03ZOE2Y`YC5{X16ktoH*C1mntI8-X-^5s%EbozA$qngRAX=tcvZ?9@?ZDg@(y1H)g
zcy&WVb#Ho@Jw42K@9q!2yU*h>1QYiJf_pk$gT-=ZVWGurZn0Qk_db2PzqABWEDy2{%
z2O*UZQh{2Ha9S(Ws6`sJSgR3FYsLRei*!1%UJuUdLA_oys~5eWg}2CL5~)lglS!pA
zscaG^gH29N!lvNJC#U37Qwq6Up-?Cl3YAI)!64Plj9drPDIf?^!_<&Qt=4KZTCGMm
zGd=fSYMhfB=9GpxmC+zK8Wbjj+yu8#VKgX>2G!yMJU~W++5|JI=S`5w1h?8~(9D}O
z3m>$L3tF8{5B%@rw}AZb20@?u^P2$dmjDi^$33L8itOFjz2p^Ly7ko||5)Uj%v(_#
zQESrLw$hfNuY{vgc!e}(e>s*#KhU4B%(FBs@=4;+G9{-h@VK)3gIio5Ei_D-7?ar8
zQ;R!J+Ht+@HlZTwU=C%QTVr&vOKWDOefFB(hVUp`n-DCX<{w^I<%8FggipiL`}BVM
zqc30C(Ut6l!6w!JUHpZYTO>K2-j(MjY;s@gSQiji)dy`3WmdLEVf^+TR+g$l(%E#s
zdXm8_By(%?zWR#}RAy>(1GmN2BarZH4^1%89;PE4yA}83#o3lC(dqakLH7ms+p3D{
zQ+M0IZB5d!BW{nmZDhZY2IkT!%^pgkL8RbZW9=$>ln{08%;Hw$tLJOKKRMZ*J>2vh
z6EjFli1vEm+Gw9R$KTCfclZVoXXO+WU*H&UC%C}6tm>B(ADdTC_s4|0CagNMK5GzX
z4ImFiAbs=bEaZ_RdA7b2N$UuEcG%~TavGi$AndSL0R+O%`!vGAw=|WK8zNq9OW65s
z(;JTz6r(*JZy{^fs_j2~SF+Lx{>bcb;Vuyf
zyGZ)$vMCy_{@1-Fv+jh@PD+Ni6EYY;V$Vu506TO%ZoP_z!&3!5$-~Yi31bu+TW|dl
zCU!?e1mN_nl}=nL1c_2=qz$ha!#z5w#_hxye*&UxL>y&ZiI
zNWXlD+j5oItfUAq1OgZ&GS>sg95EM>xStxuqmjEjGJ`aoNYveUmX#Bh$Z|Lw_mmQt;gWDM3%x)j
zXGz8JHkgLQgxIy^^i~jC+wE8EeG>l~EVNtccJW+Rb?IjG@|(PzT-k~DIf3m|PoFcZ
zKZ2RDJDUtPHKD<@O}Qg6yM5O3b5F3nic!48j
ziY;vSnp#HB(dO#~Jzn*{Wj@2ij61h6^2^WKIG+pV{pgW2o|>PQXW$jDE<~r{4;7m$
zV_gX4sBS8jGHd1B^4H7?=aY&E>*Zm0-V`Mt^U02M*>vDU89MQHT^U+h!mC90{lPGM
zrjS`?&$l~u?eCK>WPcOC_i<e(GyPl5hRWYj^Xqc=mg!OsNGf6;
zsZ)l^MIXb5Ob7K>$sYUd>3|)+)9TM|BEf(4a(^1xcEeQJH(-E`Ft7;;YzBiZ
zs9@W+ZQGH+4%}cTHn0mf*u8uAUL>#&2KHkE2T%dSAOMO#S-`H)0g<3Q!NBp4!S>IE
zjjWvFBJOKK78I&=Pj44c_L{?CczULk*qk0uCDoQmnyFSx8nBzHv*7bdmieL6%}&ns-oEbc&gmgvH6LpFH868>WmJT@dK(Dv
zEBQn;tPtk3U-{_XT$`Ult8H~H&K5E_HZ=)fULoPOX2wCq0KG3;Ci(0%jSH!_OIUSz
z!RO}}QqM0FO;8tZcUT^=JFoWSl?B|Bo-i=z%qW;1m7B()dB`bHnWw?caqFqMyO#!)
zC;5d$wIqA=3+AP?Mn3Km-;#2!@8+T{&H@{zn|^-I|Mc_)ZugxohkFbTe-YxAlHRbe
li9g(gkyX+=AfZ{3FEC|ct61U^L1BLvMK?Z&3IPEIYXGF+_yzy~

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/img/wall_west.gif b/examples/clingo/robots/img/wall_west.gif
new file mode 100644
index 0000000000000000000000000000000000000000..55e73c14d89de6b11e81a490a080cf5e94c3300e
GIT binary patch
literal 1171
zcmZ?wbhEHbuvDkU$j<
zPy++CFwlw$+K2${I6wz+pc4kVkU%#KOn`x@U@!v=X3d&4d-m+PbLTDqgM|whE(U|8
zFt82`)~{c`0SRn`flWBTW-!%U-Rn?vb~_^-7#wqC
z;$`>#d3Hq)_GC;*V(Ac2bm#~;$iOOXl67g7=jLUsqP~3!CtJU8OcqmV`}E=FY4-Dq
zlHOvBLM{;k3a-AhG^ApF6g)cG%Bvi9X2yo(Qxo-_^K2?NKRq{9)t+zd%q>c4Go;n4
zCe8XF@8%W7{ps?Gwl@wPi%zg@$vByJVP<2ooa~$*AMPKsR~PS%@mOeGz3BbUV2=~i
z0w=0uP8Z3%A|{-Es&Iy6{<1SOg}FUy9$Z++%+9YWa$rGl`-KILEpN_rUQ`a5ZIIj}
z*e1QeBk{176iY$_BV)>eQ#|G~l7#)NJ}wdR);p*o?4dL7Sn4*>xNYXDlG&E5b2

literal 0
HcmV?d00001

diff --git a/examples/clingo/robots/robots.lp b/examples/clingo/robots/robots.lp
new file mode 100644
index 0000000..780eef8
--- /dev/null
+++ b/examples/clingo/robots/robots.lp
@@ -0,0 +1,35 @@
+#program base.
+dir(-1,0;1,0;0,-1;0,1).
+
+stop( DX, DY,X,   Y   ) :- barrier(X,Y,DX,DY).
+stop(-DX,-DY,X+DX,Y+DY) :- stop(DX,DY,X,Y).
+
+#external target(R,X,Y) : available_target(R,M,X,Y).
+#external pos(R,X,Y,0) : dim(X), dim(Y), robot(R).
+
+#program trans(t).
+
+1 { move(R,DX,DY,t) : robot(R), dir(DX,DY) } 1.
+
+halt(DX,DY,X-DX,Y-DY,t) :- pos(_,X,Y,t-1), dir(DX,DY), dim(X-DX), dim(Y-DY), not stop(-DX,-DY,X,Y).
+
+goto(R,DX,DY,X,Y,t) :- pos(R,X,Y,t-1), dir(DX,DY).
+goto(R,DX,DY,X+DX,Y+DY,t) :- goto(R,DX,DY,X,Y,t), dim(X+DX), dim(Y+DY), not stop(DX,DY,X,Y), not halt(DX,DY,X,Y,t).
+
+pos(R,X,Y,t) :- move(R,DX,DY,t), goto(R,DX,DY,X,Y,t), not goto(R,DX,DY,X+DX,Y+DY,t).
+pos(R,X,Y,t) :- pos(R,X,Y,t-1), not move(R,_,_,t).
+
+:- move(R,DX,DY,t-1), not goon(t-1), not move(R,DX,DY,t).
+
+#program state(t).
+
+goon(t) :- target(R,X,Y), not pos(R,X,Y,t).
+#minimize{ 1,t : goon(t) }.
+
+#program check(t).
+
+#external horizon(t).
+
+:- goon(t), horizon(t).
+
+#show move/4.
diff --git a/examples/clingo/robots/visualize.py b/examples/clingo/robots/visualize.py
new file mode 100755
index 0000000..dd8a92e
--- /dev/null
+++ b/examples/clingo/robots/visualize.py
@@ -0,0 +1,475 @@
+#!/usr/bin/env python
+import clingo
+import Tkinter
+
+# {{{1 class Board
+
+class Board:
+    def __init__(self):
+        self.size           = 1
+        self.blocked        = set()
+        self.barriers       = set()
+        self.targets        = set()
+        self.pos            = dict()
+        self.robots         = [{}]
+        self.moves          = []
+        self.current_target = None
+        self.solution       = None
+
+        ctl = clingo.Control()
+        ctl.load("board.lp")
+        ctl.ground([("base", [])])
+        ctl.solve(on_model=self.__on_model)
+
+    def __on_model(self, m):
+        for atom in m.symbols(atoms=True):
+            if atom.name == "barrier" and len(atom.arguments) == 4:
+                x, y, dx, dy = [n.number for n in atom.arguments]
+                self.blocked.add((x - 1     , y - 1     ,  dx,  dy))
+                self.blocked.add((x - 1 + dx, y - 1     , -dx,  dy))
+                self.blocked.add((x - 1     , y - 1 + dy,  dx, -dy))
+                self.blocked.add((x - 1 + dx, y - 1 + dy, -dx, -dy))
+                if dy == 0:
+                    self.barriers.add(('west', x if dx == 1 else x - 1, y - 1))
+                else:
+                    self.barriers.add(('north', x - 1, y if dy == 1 else y - 1))
+            elif atom.name == "dim" and len(atom.arguments) == 1:
+                self.size = max(self.size, atom.arguments[0].number)
+            elif atom.name == "available_target" and len(atom.arguments) == 4:
+                c, s, x, y = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                self.targets.add((c, s, x - 1, y - 1))
+            elif atom.name == "initial_pos" and len(atom.arguments) == 3:
+                c, x, y = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                self.pos[c] = (x - 1, y - 1)
+        for d in range(0, self.size):
+            self.blocked.add((d            ,             0,  0, -1))
+            self.blocked.add((d            , self.size - 1,  0,  1))
+            self.blocked.add((0            ,             d, -1,  0))
+            self.blocked.add((self.size - 1,             d,  1,  0))
+
+    def move(self, robot, dx, dy):
+        x, y = self.pos[robot]
+        while (not (x, y, dx, dy) in self.blocked and
+                not (x + dx, y + dy) in self.pos.values()):
+            x += dx
+            y += dy
+        self.pos[robot] = (x, y)
+        if (self.solution is not None and
+                len(self.solution) > 0 and
+                self.solution[0][0] == robot and
+                self.solution[0][1] == dx and
+                self.solution[0][2] == dy):
+            self.solution.pop(0)
+            if len(self.solution) == 0:
+                self.solution = None
+        else:
+            self.solution = None
+
+    def won(self):
+        r, _, x, y = self.current_target
+        return self.pos[r] == (x, y)
+
+# {{{1 class Solver
+# NOTE: it would be a nice gimmick to make the search interruptible
+
+class Solver:
+    def __init__(self, horizon=0):
+        self.__horizon = horizon
+        self.__prg = clingo.Control(['-t4'])
+        self.__future = None
+        self.__solution = None
+        self.__assign = []
+
+        self.__prg.load("board.lp")
+        self.__prg.load("robots.lp")
+        parts = [ ("base", [])
+                , ("check", [0])
+                , ("state", [0])
+                ]
+        for t in range(1, self.__horizon+1):
+            parts.extend([ ("trans", [t])
+                         , ("check", [t])
+                         , ("state", [t])
+                         ])
+        self.__prg.ground(parts)
+        self.__prg.assign_external(clingo.Function("horizon", [self.__horizon]), True)
+
+    def __next(self):
+        assert(self.__horizon < 30)
+        self.__prg.assign_external(clingo.Function("horizon", [self.__horizon]), False)
+        self.__horizon += 1
+        self.__prg.ground([ ("trans", [self.__horizon])
+                          , ("check", [self.__horizon])
+                          , ("state", [self.__horizon])
+                          ])
+        self.__prg.assign_external(clingo.Function("horizon", [self.__horizon]), True)
+
+    def start(self, board):
+        self.__assign = []
+        for robot, (x, y) in board.pos.items():
+            self.__assign.append(clingo.Function("pos", [clingo.Function(robot), x+1, y+1, 0]))
+        self.__assign.append(clingo.Function("target",
+            [ clingo.Function(board.current_target[0])
+            , board.current_target[2] + 1
+            , board.current_target[3] + 1
+            ]))
+        for x in self.__assign:
+            self.__prg.assign_external(x, True)
+        self.__solution = None
+        self.__future = self.__prg.solve_async(on_model=self.__on_model)
+
+    def busy(self):
+        if self.__future is None:
+            return False
+        if self.__future.wait(0):
+            if self.__solution is None:
+                self.__next()
+                self.__future = self.__prg.solve_async(on_model=self.__on_model)
+                return True
+            else:
+                self.__future = None
+                return False
+        return True
+
+    def stop(self):
+        if self.__future is not None:
+            self.__future.cancel()
+            self.__future.wait()
+            self.__future = None
+            self.get()
+
+    def get(self):
+        solution = self.__solution
+        self.__solution = None
+        for x in self.__assign:
+            self.__prg.assign_external(x, False)
+        self.__assign = []
+        return solution
+
+    def __on_model(self, m):
+        self.__solution = []
+        for atom in m.symbols(atoms=True):
+            if atom.name == "move" and len(atom.arguments) == 4:
+                c, x, y, t = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                self.__solution.append((c, x, y, t))
+        self.__solution.sort(key=lambda x: x[3])
+        p = None
+        i = 0
+        for x in self.__solution:
+            if p is not None and \
+               p[0] == x[0]  and \
+               p[1] == x[1]  and \
+               p[2] == x[2]:
+                break
+            p = x
+            i += 1
+        del self.__solution[i:]
+
+# {{{1 class Visualization
+
+class Visualization:
+    def __init__(self, master, board):
+        self.__margin           = 20
+        self.__tile_size        = 40
+        self.__canvas_width     = None
+        self.__canvas_height    = None
+        self.__robot_images     = {}
+        self.__target_images    = {}
+        self.__solution_images  = []
+        self.__direction_images = []
+        self.__entered          = set()
+        self.__slots            = {}
+        self.__highlights       = {}
+        self.__targets          = {}
+        self.__moves            = {}
+        self.__moves_short      = {}
+        self.__robots           = {}
+        self.__barriers         = {}
+        self.__tiles            = []
+
+        self.__canvas_width  = board.size * self.__tile_size + 2 * self.__margin
+        self.__canvas_height = (1 + board.size) * self.__tile_size + 3 * self.__margin
+
+        self.__canvas = Tkinter.Canvas(master, width=self.__canvas_width, height=self.__canvas_height)
+        self.__canvas.pack()
+
+        colors     = ['green', 'red', 'blue', 'yellow']
+        shapes     = ['moon', 'sun', 'star', 'saturn']
+        directions = [('north', 0, -1), ("east", 1, 0), ('south', 0, 1), ('west', -1, 0)]
+        for orientation in ['left', 'right']:
+            path = 'img/tile_{orientation}.gif'.format(orientation=orientation)
+            self.__tiles.append(Tkinter.PhotoImage(file=path))
+        for direction in ['north', 'west']:
+            path = 'img/wall_{direction}.gif'.format(direction=direction)
+            self.__barriers[direction] = (Tkinter.PhotoImage(file=path), -6, -6)
+        for color in colors:
+            path = 'img/robot_{color}.gif'.format(color=color)
+            self.__robots[color] = Tkinter.PhotoImage(file=path)
+            for shape in shapes:
+                path = "img/{shape}_{color}.gif".format(shape=shape, color=color)
+                self.__targets[(color, shape)] = Tkinter.PhotoImage(file=path)
+            for (direction, dx, dy) in directions:
+                path = "img/arrow_{color}_{direction}.gif".format(color=color, direction=direction)
+                self.__moves[(color, dx, dy)] = Tkinter.PhotoImage(file=path)
+                path = "img/move_{color}_{direction}.gif".format(color=color, direction=direction)
+                self.__moves_short[(color, dx, dy)] = Tkinter.PhotoImage(file=path)
+        for x in range(0, board.size):
+            for y in range(0, board.size):
+                self.__canvas.create_image(
+                    self.__margin + self.__tile_size * x,
+                    self.__margin + self.__tile_size * y,
+                    anchor=Tkinter.NW,
+                    image=self.__tiles[(x + y) % len(self.__tiles)])
+        for (t, m, x, y) in board.targets:
+            self.__target_images[(x, y)] = self.__canvas.create_image(
+                self.__margin + self.__tile_size * x,
+                self.__margin + self.__tile_size * y,
+                anchor=Tkinter.NW,
+                image=self.__targets[(t,m)])
+            self.__canvas.itemconfig(
+                self.__target_images[(x, y)],
+                state=Tkinter.HIDDEN)
+        for (r, (x, y)) in board.pos.items():
+            self.__robot_images[r] = self.__canvas.create_image(
+                self.__margin + self.__tile_size * x,
+                self.__margin + self.__tile_size * y,
+                anchor=Tkinter.NW,
+                image=self.__robots[r])
+        for (d, x, y) in board.barriers:
+            (img, dx, dy) = self.__barriers[d]
+            self.__canvas.create_image(
+                self.__margin + self.__tile_size * x + dx,
+                self.__margin + self.__tile_size * y + dy,
+                anchor=Tkinter.NW,
+                image=img)
+        self.__solve_button = self.__canvas.create_text(
+            board.size * self.__tile_size / 2 + self.__margin,
+            (0.5 + board.size) * self.__tile_size + 2 * self.__margin,
+            text="Solve!",
+            activefill="blue",
+            state=Tkinter.HIDDEN)
+        self.__solving_text = self.__canvas.create_text(
+            board.size * self.__tile_size / 2 + self.__margin,
+            (0.5 + board.size) * self.__tile_size + 2 * self.__margin,
+            text="Solving...",
+            state=Tkinter.HIDDEN)
+        self.__canvas.bind('', self.__mouse_move_event)
+        self.__canvas.bind('', self.__mouse_click_event)
+
+    def __mouse_over(self, tag, mx, my):
+        if self.__canvas.itemcget(tag, "state") == Tkinter.HIDDEN:
+            return False
+        x, y, xx, yy = self.__canvas.bbox(tag)
+        return mx >= x and mx < xx and \
+               my >= y and my < yy
+
+    def __mouse_over_triangle(self, tag, mx, my, dx, dy):
+        if self.__mouse_over(tag, mx, my):
+            px, py = self.__canvas.coords(tag)
+            px = (mx - px) / self.__tile_size
+            py = (my - py) / self.__tile_size
+            rx = px - py
+            ry = px + py - 1
+            if (dx - dy) * rx < 0 and (dx + dy) * ry < 0:
+                return True
+        return False
+
+    def __mouse_click_event(self, e):
+        clicked = set()
+        for (x, y), t in self.__target_images.items():
+            if self.__mouse_over(t, e.x, e.y):
+                clicked.add(("target", (x, y)))
+        for (t, val) in self.__direction_images:
+            r, x, y, dx, dy = val
+            if self.__mouse_over_triangle(t, e.x, e.y, dx, dy):
+                clicked.add(("robot", val))
+        if self.__mouse_over(self.__solve_button, e.x, e.y):
+            clicked.add(("solve", None))
+
+        for tag, val in clicked:
+            for slot in self.__slots.get(tag, []):
+                slot("click", val)
+
+    def __mouse_move_event(self, e):
+        entered = set()
+        for ((x, y), t) in self.__target_images.items():
+            if self.__mouse_over(t, e.x, e.y):
+                entered.add(("target", (x, y)))
+        for (t, val) in self.__direction_images:
+            r, x, y, dx, dy = val
+            if self.__mouse_over_triangle(t, e.x, e.y, dx, dy):
+                entered.add(("robot", val))
+        for (tag, val) in self.__entered - entered:
+            for slot in self.__slots.get(tag, []):
+                slot("leave", val)
+        for (tag, val) in entered - self.__entered:
+            for slot in self.__slots.get(tag, []):
+                slot("enter", val)
+        self.__entered = entered
+
+    def highlight(self, x, y, active):
+        if active and not (x, y) in self.__highlights:
+            m  = 8
+            xx = self.__margin + x * self.__tile_size + m
+            yy = self.__margin + y * self.__tile_size + m
+            self.__highlights[(x, y)] = self.__canvas.create_rectangle(
+                (xx, yy, xx + self.__tile_size - 2 * m, yy + self.__tile_size - 2 * m),
+                width=3,
+                outline="blue")
+        elif not active and (x, y) in self.__highlights:
+            self.__canvas.delete(self.__highlights[(x, y)])
+            del self.__highlights[(x, y)]
+
+    def highlight_direction(self, x, y, dx, dy, active):
+        if active and not (x, y, dx, dy) in self.__highlights:
+            m  = 8
+            xx = self.__margin + x * self.__tile_size + m
+            yy = self.__margin + y * self.__tile_size + m
+            xxx = xx + self.__tile_size - 2 * m
+            yyy = yy + self.__tile_size - 2 * m
+            cx = xx + (xxx - xx) / 2
+            cy = yy + (yyy - yy) / 2
+            if dx == -1: xx, xxx = xxx, xx
+            if dy == -1: yy, yyy = yyy, yy
+            if dy ==  0: xxx = xx
+            if dx ==  0: yyy = yy
+            self.__highlights[(x, y, dx, dy)] = self.__canvas.create_polygon(
+                (xx, yy, xxx, yyy, cx, cy),
+                width=3,
+                outline="blue",
+                fill="")
+        elif not active and (x, y, dx, dy) in self.__highlights:
+            self.__canvas.delete(self.__highlights[(x, y, dx, dy)])
+            del self.__highlights[(x, y, dx, dy)]
+
+    def clear_highlights(self):
+        for p in self.__highlights.values():
+            self.__canvas.delete(p)
+        self.__highlights = {}
+
+    def connect_target_event(self, slot):
+        self.__slots.setdefault("target", []).append(slot)
+
+    def connect_robot_event(self, slot):
+        self.__slots.setdefault("robot", []).append(slot)
+
+    def connect_solve_event(self, slot):
+        self.__slots.setdefault("solve", []).append(slot)
+
+    def update_board(self, board):
+        self.clear_directions()
+        for (r, (x, y)) in board.pos.items():
+            ox, oy = self.__canvas.coords(self.__robot_images[r])
+            self.__canvas.move(
+                self.__robot_images[r],
+                self.__margin + self.__tile_size * x - ox,
+                self.__margin + self.__tile_size * y - oy)
+            for dx, dy in [(1,0), (0,1), (-1,0), (0,-1)]:
+                xx = x + dx
+                yy = y + dy
+                if not (x, y, dx, dy) in board.blocked and not (xx, yy) in board.pos.values():
+                    self.__direction_images.append((
+                        self.__canvas.create_image(
+                            self.__margin + self.__tile_size * xx,
+                            self.__margin + self.__tile_size * yy,
+                            anchor=Tkinter.NW,
+                            image=self.__moves_short[r, dx, dy]),
+                        (r, x, y, dx, dy)))
+        for tag in self.__solution_images:
+            self.__canvas.delete(tag)
+        self.__solution_images = []
+        if board.solution is not None:
+            i = 0
+            for (r, x, y, _) in board.solution:
+                self.__solution_images.append(
+                    self.__canvas.create_image(
+                        self.__margin + i * self.__tile_size,
+                        2 * self.__margin + self.__tile_size * board.size,
+                        anchor=Tkinter.NW,
+                        image=self.__moves[(r, x, y)]))
+                i += 1
+    def enable_solve(self, board, state):
+        self.__canvas.itemconfigure(self.__solve_button, state=Tkinter.NORMAL if state == "enabled" else Tkinter.HIDDEN)
+        self.__canvas.itemconfigure(self.__solving_text, state=Tkinter.NORMAL if state == "busy" else Tkinter.HIDDEN)
+
+    def update_target(self, board):
+        for (t, m, x, y) in board.targets:
+            self.__canvas.itemconfig(self.__target_images[(x, y)], state=Tkinter.NORMAL if board.current_target is None else Tkinter.HIDDEN)
+        if board.current_target is not None:
+            self.__canvas.itemconfig(self.__target_images[board.current_target[2], board.current_target[3]], state=Tkinter.NORMAL)
+
+    def clear_directions(self):
+        for (tag, _) in self.__direction_images:
+            self.__canvas.delete(tag)
+        self.__direction_images = []
+
+# {{{1 Application
+
+class Main:
+    def __init__(self):
+        self.__master = Tkinter.Tk()
+
+        self.__board  = Board()
+        self.__solver = Solver()
+        self.__canvas = Visualization(self.__master, self.__board)
+
+        #self.__master.bind("", self.__canvas.on_previous) # would be nice to have these two bindings as an undo/redo stack
+        #self.__master.bind("", self.__canvas.on_next)
+        self.__master.bind("", lambda x: self.__master.quit())
+        self.__canvas.update_target(self.__board)
+        self.__canvas.connect_target_event(self.target_event)
+        self.__canvas.connect_robot_event(self.robot_event)
+        self.__canvas.connect_solve_event(self.solve_event)
+
+    def target_event(self, event, (x, y)):
+        if self.__board.current_target is None:
+            if event == "enter":
+                self.__canvas.highlight(x, y, True)
+            elif event == "leave":
+                self.__canvas.highlight(x, y, False)
+            elif event == "click":
+                for t in self.__board.targets:
+                    if t[2] == x and t[3] == y:
+                        self.__board.current_target = t
+                self.__canvas.update_target(self.__board)
+                self.__update_board()
+
+    def __update_board(self):
+        self.__canvas.clear_highlights()
+        self.__canvas.update_board(self.__board)
+        won = self.__board.won()
+        if won:
+            self.__board.current_target = None
+            self.__canvas.clear_directions()
+            self.__canvas.update_target(self.__board)
+        self.__canvas.enable_solve(self.__board, "enabled" if not won and self.__board.solution is None else "disabled")
+
+    def robot_event(self, event, (r, x, y, dx, dy)):
+        if event == "enter":
+            self.__canvas.highlight_direction(x+dx, y+dy, dx, dy, True)
+        elif event == "leave":
+            self.__canvas.highlight_direction(x+dx, y+dy, dx, dy, False)
+        else:
+            self.__solver.stop()
+            self.__board.move(r, dx, dy)
+            self.__update_board()
+
+    def solve_event(self, event, ignore):
+        self.__solver.start(self.__board)
+        self.__canvas.enable_solve(self.__board, "busy")
+        self.__master.after(500, self.timer_event)
+
+    def timer_event(self):
+        if self.__solver.busy():
+            self.__master.after(500, self.timer_event)
+        else:
+            self.__board.solution = self.__solver.get()
+            self.__update_board()
+
+    def run(self):
+        Tkinter.mainloop()
+
+# {{{1 main
+
+app = Main()
+app.run()
diff --git a/examples/clingo/setconf/README b/examples/clingo/setconf/README
new file mode 100644
index 0000000..5fa02cf
--- /dev/null
+++ b/examples/clingo/setconf/README
@@ -0,0 +1,5 @@
+This example shows how to change the config of the underlying solver.
+
+Example calls:
+    clingo setconf-py.lp
+    clingo setconf-lua.lp
diff --git a/examples/clingo/setconf/setconf-lua.lp b/examples/clingo/setconf/setconf-lua.lp
new file mode 100644
index 0000000..60d3f24
--- /dev/null
+++ b/examples/clingo/setconf/setconf-lua.lp
@@ -0,0 +1,52 @@
+#script (lua)
+
+function print_conf(conf, ident)
+    for _, key in ipairs(conf.keys) do
+        local subconf = conf[key]
+        if type(subconf) == type(conf) then
+            label = key
+            if #subconf >= 0 then
+                label = label .. "[0.." .. tostring(#subconf) .. "]"
+            end
+            print (ident .. label .. " - " .. conf["__desc_" .. key])
+            print_conf(subconf, "  " .. ident .. label .. ".")
+        else
+            print (ident .. key .. "[=" .. tostring(subconf) .. "] - " .. conf["__desc_" .. key])
+        end
+    end
+end
+
+function main(prg)
+    prg:ground({{"base", {}}})
+    
+    print_conf(prg.configuration, "")
+
+    print ("The heuristics of the solvers in the 'many' portfolio:")
+    prg.configuration.configuration = "many"
+    prg.configuration.solve.parallel_mode = 3 -- just use the first 3 solvers
+    for x in prg.configuration.solver:iter() do
+        print ("  " .. x.heuristic)
+    end
+
+    prg.configuration.solve.models = 0
+    print ("==================== All Models ===================")
+    prg:solve()
+
+    prg.configuration.solve.models = 1
+    print ("===================== One Model ===================")
+    prg:solve()
+
+    prg.configuration.solve.models = 0
+    prg.configuration.solve.enum_mode = "cautious"
+    print ("=============== Cautious Consequences =============")
+    prg:solve()
+
+    prg.configuration.solve.models = 0
+    prg.configuration.solve.enum_mode = "brave"
+    print ("================ Brave Consequences ===============")
+    prg:solve()
+end
+
+#end.
+
+{ a; b; c }.
diff --git a/examples/clingo/setconf/setconf-py.lp b/examples/clingo/setconf/setconf-py.lp
new file mode 100644
index 0000000..4529e9a
--- /dev/null
+++ b/examples/clingo/setconf/setconf-py.lp
@@ -0,0 +1,49 @@
+#script (python)
+
+import clingo
+
+def print_conf(conf, ident):
+    for key in conf.keys:
+        subconf = getattr(conf, key)
+        if isinstance(subconf, clingo.Configuration):
+            label = key
+            if (len(subconf) >= 0):
+                label += "[0.." + str(len(subconf)) + "]"
+            print ("{0}{1} - {2}".format(ident, label, getattr(conf, "__desc_" + key)))
+            print_conf(subconf, "  " + ident + label + ".")
+        else:
+            print ("{0}{1}[={2}] - {3}".format(ident, key, subconf, getattr(conf, "__desc_" + key)))
+
+def main(prg):
+    prg.ground([("base", [])])
+    blub = prg.configuration.solver
+
+    print_conf(prg.configuration, "")
+
+    print ("The heuristics of the solvers in the 'many' portfolio:")
+    prg.configuration.configuration = "many"
+    prg.configuration.solve.parallel_mode = 3 # just use the first 3 solvers
+    for x in prg.configuration.solver:
+        print ("  " + x.heuristic)
+
+    prg.configuration.solve.models = 0
+    print "==================== All Models ==================="
+    prg.solve()
+
+    prg.configuration.solve.models = 1
+    print "===================== One Model ==================="
+    prg.solve()
+
+    prg.configuration.solve.models = 0
+    prg.configuration.solve.enum_mode = "cautious"
+    print "=============== Cautious Consequences ============="
+    prg.solve()
+
+    prg.configuration.solve.models = 0
+    prg.configuration.solve.enum_mode = "brave"
+    print "================ Brave Consequences ==============="
+    prg.solve()
+
+#end.
+
+{ a; b; c }.
diff --git a/examples/clingo/solitaire/README b/examples/clingo/solitaire/README
new file mode 100644
index 0000000..89d3251
--- /dev/null
+++ b/examples/clingo/solitaire/README
@@ -0,0 +1,53 @@
+Peg Solitaire
+=============
+
+The Problem
+-----------
+
+Given the board below, find a solution consisting of successive moves
+such that only one peg (o) remains in the center of the board.  A move
+is an orthogonal jump of length two above an adjacent peg to a free
+position on the board.  The jumped peg has to be removed after the move.
+
+     -------
+     |o|o|o|
+     -------
+     |o|o|o|
+ ---------------
+ |o|o|o|o|o|o|o|
+ ---------------
+ |o|o|o| |o|o|o|
+ ---------------
+ |o|o|o|o|o|o|o|
+ ---------------
+     |o|o|o|
+     -------
+     |o|o|o|
+     -------
+
+Setup
+-----
+
+The visualizer requires urwid. To install under Debian it, run as root:
+
+	aptitude install python-urwid
+
+Finding a Solution
+------------------
+
+The problem can be solved using the incremental encoding in solitaire.lp.
+To find a solution, call (takes about 10s on a fast machine):
+	
+	clingo solitaire.lp instance.lp
+
+To visualize the solution, call:
+
+	./visualize.py solitaire.lp instance.lp
+
+
+Notes
+-----
+
+The encoding allows for parallel moves, i.e., moves that do not influence each
+other may occur at the same time step.  This is essential to solve the problem.
+When visualizing the solution the moves are sequentialized again.
diff --git a/examples/clingo/solitaire/instance.lp b/examples/clingo/solitaire/instance.lp
new file mode 100644
index 0000000..7e28ecc
--- /dev/null
+++ b/examples/clingo/solitaire/instance.lp
@@ -0,0 +1,37 @@
+%     -------
+%     |o|o|o|
+%     -------
+%     |o|o|o|
+% ---------------
+% |o|o|o|o|o|o|o|
+% ---------------
+% |o|o|o| |o|o|o|
+% ---------------
+% |o|o|o|o|o|o|o|
+% ---------------
+%     |o|o|o|
+%     -------
+%     |o|o|o|
+%     -------
+%
+%
+
+field(0,0).
+field(X,Y) :- stone(X,Y).
+
+stone(-1.. 1,-3..-1).
+stone(-3..-1,-1.. 1).
+stone( 1.. 3,-1.. 1).
+stone(-1.. 1, 1.. 3).
+
+dir(west;east;north;south).
+
+dir(west ,-1, 0).
+dir(east , 1, 0).
+dir(north, 0,-1).
+dir(south, 0, 1).
+
+goal(0,0).
+
+% fix the first jump to avoid symmetries
+fix_jump(0,-2,south,1).
diff --git a/examples/clingo/solitaire/solitaire.lp b/examples/clingo/solitaire/solitaire.lp
new file mode 100644
index 0000000..1ee6a0d
--- /dev/null
+++ b/examples/clingo/solitaire/solitaire.lp
@@ -0,0 +1,33 @@
+#include .
+
+#show jump/4.
+
+#program base.
+
+stone(X,Y,0) :- stone(X,Y).
+field(X,Y,D) :- field(X,Y), field(X+2*DX,Y+2*DY), dir(D,DX,DY).
+
+#program step(t).
+
+1 { jump(X,Y,D,t) : field(X,Y,D) }.
+remove(X+DX,Y+DY,t) :- jump(X,Y,D,t), dir(D,DX,DY).
+
+ :- jump(X,Y,D,t), not stone(X,Y,t-1).
+ :- jump(X,Y,D,t), stone(X+2*DX,Y+2*DY,t-1), dir(D,DX,DY).
+ :- remove(X,Y,t), not stone(X,Y,t-1), dir(D,DX,DY).
+
+ :- jump(X,Y,D,t), jump(X,Y,D',t), D != D'.
+ :- jump(X,Y,D,t), jump(X',Y',D',t), dir(D,DX,DY), dir(D',DX',DY'), X+DX == X'+DX', Y+DY == Y'+DY', D != D'.
+ :- jump(X,Y,D,t), jump(X',Y',D',t), dir(D,DX,DY), dir(D',DX',DY'), X+2*DX == X'+2*DX', Y+2*DY == Y'+2*DY', D != D'.
+ :- jump(X,Y,D,t), remove(X,Y,t).
+
+ :- fix_jump(X,Y,D,t), not jump(X,Y,D,t).
+
+stone(X+2*DX,Y+2*DY,t) :- jump(X,Y,D,t), dir(D,DX,DY).
+stone(X,Y,t)           :- stone(X,Y,t-1), not jump(X,Y,_,t), not remove(X,Y,t).
+
+#program check(t).
+
+ :- query(t), goal(X,Y), not stone(X,Y,t).
+ :- query(t), not goal(X,Y), stone(X,Y,t).
+
diff --git a/examples/clingo/solitaire/visualize.py b/examples/clingo/solitaire/visualize.py
new file mode 100755
index 0000000..99948f7
--- /dev/null
+++ b/examples/clingo/solitaire/visualize.py
@@ -0,0 +1,165 @@
+#!/usr/bin/python
+
+import urwid
+import sys
+import clingo
+
+class Board:
+
+    def __init__(self, plan):
+        self.display = urwid.Text("", align='center')
+        self.plan    = plan
+        self.current = plan.first()
+        self.update()
+
+    def next(self, button):
+        self.current = self.plan.next(self.current)
+        self.update()
+
+    def prev(self, button):
+        self.current = self.plan.prev(self.current)
+        self.update()
+
+    def update(self):
+        brd = [[" "] * (self.plan.width * 2 + 1) for _ in range(0, (self.plan.height * 2 + 1))]
+
+        for (x, y) in self.plan.field:
+            brd[2 * y + 1][2 * x + 0] = "|"
+            brd[2 * y + 1][2 * x + 2] = "|"
+
+        for (x, y) in self.plan.field:
+            brd[2 * y + 0][2 * x + 0] = "-"
+            brd[2 * y + 0][2 * x + 1] = "-"
+            brd[2 * y + 0][2 * x + 2] = "-"
+            brd[2 * y + 2][2 * x + 0] = "-"
+            brd[2 * y + 2][2 * x + 1] = "-"
+            brd[2 * y + 2][2 * x + 2] = "-"
+
+        for (x, y) in self.plan.steps(self.current):
+            brd[2 * y + 1][2 * x + 1] = "o"
+
+        j = self.plan.jumped(self.current)
+        if j != None:
+            (x, y) = j
+            brd[2 * y  + 1][2 * x  + 1] = ("blue", "o")
+
+
+        j = self.plan.jump(self.current)
+        if j != None:
+            (x, y, xx, yy) = j
+            brd[2 * y  + 1][2 * x  + 1] = ("red",   "o")
+            brd[2 * yy + 1][2 * xx + 1] = ("green", " ")
+
+        markup = []
+        for row in brd:
+            markup.extend(row)
+            markup.append("\n")
+
+        self.display.set_text(markup)
+
+class MainWindow:
+    def __init__(self):
+           self.loop = None
+
+    def exit(self, button):
+        raise urwid.ExitMainLoop()
+
+    def run(self, plan):
+
+        c = Board(plan)
+
+        ba = urwid.Button("previous")
+        bb = urwid.Button("quit")
+        bc = urwid.Button("next")
+
+        urwid.connect_signal(bb, 'click', self.exit)
+        urwid.connect_signal(bc, 'click', c.next)
+        urwid.connect_signal(ba, 'click', c.prev)
+
+        sf = urwid.Text("")
+
+        b = urwid.Columns([sf, ('fixed', len(bc.label) + 4, bc), ('fixed', len(ba.label) + 4, ba), ('fixed', len(bb.label) + 4, bb), sf], 1)
+        f = urwid.Frame(urwid.Filler(c.display), None, b, 'footer')
+
+        palette = [
+            ('red', 'black', 'light red'),
+            ('green', 'black', 'light green'),
+            ('blue', 'black', 'light blue'), ]
+
+        self.loop = urwid.MainLoop(f, palette)
+        self.loop.run()
+
+class Plan:
+    def __init__(self, field, init, jumps):
+        mx          = min([x for (x, y) in field])
+        my          = min([y for (x, y) in field])
+        self.width  = max([x for (x, y) in field]) - mx + 1
+        self.height = max([y for (x, y) in field]) - my + 1
+        self.field  = [ (x - mx, y - my) for (x, y) in field ]
+
+        pjumps = {}
+        for (t, k) in jumps.items(): pjumps[t] = [ (x - mx, y - my, xx - mx, yy - my) for (x, y, xx, yy) in k ]
+        self._jumps = []
+        self._steps = []
+        self._steps.append([ (x - mx, y - my) for (x, y) in init ])
+
+        for t in sorted(pjumps.keys()):
+            for (x, y, xx, yy) in pjumps[t]:
+                self._jumps.append((x, y, xx, yy))
+                self._steps.append(self._steps[-1][:])
+                self._steps[-1].append((xx, yy))
+                self._steps[-1].remove((x, y))
+                self._steps[-1].remove(((x + xx) // 2, (y + yy) // 2))
+
+    def jump(self, i):
+        return self._jumps[i] if i < len(self._jumps) else None
+
+    def jumped(self, i):
+        return None if i <= 0 else self.jump(i - 1)[2:]
+
+    def steps(self, i):
+        return self._steps[i]
+
+    def next(self, i):
+        return i + 1 if i + 1 < len(self._steps) else i
+
+    def prev(self, i):
+        return i - 1 if i - 1 >= 0 else i
+
+    def first(self):
+        return 0
+
+c = clingo.Control()
+c.add("check", ["k"], "#external query(k).")
+for f in sys.argv[1:]: c.load(f)
+def make_on_model(field, init, jumps):
+    sx = { "east": 2, "west": -2, "north":  0, "south": 0 }
+    sy = { "east": 0, "west":  0, "north": -2, "south": 2 }
+    def on_model(m):
+        for atom in m.symbols(atoms=True):
+            if atom.name == "field" and len(atom.arguments) == 2:
+                x, y = [n.number for n in atom.arguments]
+                field.append((x, y))
+            elif atom.name == "stone" and len(atom.arguments) == 2:
+                x, y = [n.number for n in atom.arguments]
+                init.append((x, y))
+            elif atom.name == "jump" and len(atom.arguments) == 4:
+                ox, oy, d, t = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                jumps.setdefault(t, []).append((ox, oy, ox + sx[d], oy + sy[d]))
+        return False
+    return on_model
+
+t, field, init, jumps = 0, [], [], {}
+on_model = make_on_model(field, init, jumps)
+c.ground([("base", [])])
+while True:
+    t += 1
+    c.ground([("step", [t])])
+    c.ground([("check", [t])])
+    c.release_external(clingo.Function("query", [t-1]))
+    c.assign_external(clingo.Function("query", [t]), True)
+    if c.solve(on_model).satisfiable:
+        break
+
+MainWindow().run(Plan(field, init, jumps))
+
diff --git a/examples/clingo/solve-async/README b/examples/clingo/solve-async/README
new file mode 100644
index 0000000..5465eda
--- /dev/null
+++ b/examples/clingo/solve-async/README
@@ -0,0 +1,6 @@
+This example shows how to asynchronously solve and perform some other task
+while the search runs in the background. The other task here is a crude
+approximation of Pi.
+
+Example calls:
+  clingo solve-async-py.lp program.lp
diff --git a/examples/clingo/solve-async/program.lp b/examples/clingo/solve-async/program.lp
new file mode 100644
index 0000000..f0b6fab
--- /dev/null
+++ b/examples/clingo/solve-async/program.lp
@@ -0,0 +1,5 @@
+#const n = 17.
+
+1 { p(X); q(X) } 1 :- X = 1..n.
+:- not n+1 { p(1..n); q(1..n) }.
+
diff --git a/examples/clingo/solve-async/solve-async-py.lp b/examples/clingo/solve-async/solve-async-py.lp
new file mode 100644
index 0000000..e7f40c8
--- /dev/null
+++ b/examples/clingo/solve-async/solve-async-py.lp
@@ -0,0 +1,20 @@
+#script(python)
+
+from random import random
+
+def make_on_finish(stop):
+    def on_finish(ret):
+        stop[0] = True
+    return on_finish
+
+def main(prg):
+    stop = [False]
+    prg.ground([("base", [])])
+    future, n, m = prg.solve_async(on_finish=make_on_finish(stop)), 0, 0
+    while not stop[0]:
+        x, y, m = random(), random(), m+1
+        if x * x + y * y < 1: n+= 1
+    future.wait()
+    print "approximation of pi: {0}".format(4.*n/m)
+
+#end.
diff --git a/examples/clingo/stats/README b/examples/clingo/stats/README
new file mode 100644
index 0000000..c0dd590
--- /dev/null
+++ b/examples/clingo/stats/README
@@ -0,0 +1,8 @@
+This example shows how to obtain clasp statistics from the scripting language.
+These require external python or lua libraries. The python version also prints
+the statistics in a human-readable format (such functionality is not available
+in the lua json library used).
+
+Example calls:
+    clingo example.lp stats-lua.lp
+    clingo example.lp stats-py.lp
diff --git a/examples/clingo/stats/example.lp b/examples/clingo/stats/example.lp
new file mode 100644
index 0000000..32cec74
--- /dev/null
+++ b/examples/clingo/stats/example.lp
@@ -0,0 +1,5 @@
+a | b.
+a :- b.
+b :- a.
+
+#minimize {1,a : a; 1,b : b}.
diff --git a/examples/clingo/stats/stats-lua.lp b/examples/clingo/stats/stats-lua.lp
new file mode 100644
index 0000000..087c0d5
--- /dev/null
+++ b/examples/clingo/stats/stats-lua.lp
@@ -0,0 +1,18 @@
+#script (lua)
+
+json = require("json")
+
+function main(prg)
+
+    prg:ground({{"base", {}}})
+    prg:solve()
+    print(json.encode(prg.statistics)) -- no pretty printing support
+
+    print("lp.bodies", prg.statistics["problem"]["lp"]["bodies"])
+    -- lua tables also support dot access
+    print("lp.bodies", prg.statistics.problem.lp.bodies)
+    print("optimization", prg.statistics.summary.costs[1])
+
+end
+
+#end.
diff --git a/examples/clingo/stats/stats-py.lp b/examples/clingo/stats/stats-py.lp
new file mode 100644
index 0000000..d03e5c8
--- /dev/null
+++ b/examples/clingo/stats/stats-py.lp
@@ -0,0 +1,14 @@
+#script (python)
+
+import json
+
+def main(prg):
+    prg.ground([("base", [])])
+    prg.solve()
+    print json.dumps(prg.statistics, sort_keys=True, indent=4, separators=(',', ': '))
+    print "lp.bodies", prg.statistics["problem"]["lp"]["bodies"]
+    print "optimization", prg.statistics["summary"]["costs"]
+
+#end.
+
+
diff --git a/examples/clingo/unblock/README b/examples/clingo/unblock/README
new file mode 100644
index 0000000..d04e5e4
--- /dev/null
+++ b/examples/clingo/unblock/README
@@ -0,0 +1,11 @@
+This example shows how to use the clingo module to solve and visualize a
+puzzle game.  The puzzle is about moving a car out of a parking lot that is
+blocked by other cars. Cars can only move forwards or backwards.
+
+To solve a problem, call:
+
+	clingo unblock.lp 
+
+To solve and visualize, call:
+
+	./visualize.py unblock.lp 
diff --git a/examples/clingo/unblock/inst1.lp b/examples/clingo/unblock/inst1.lp
new file mode 100644
index 0000000..8e1b560
--- /dev/null
+++ b/examples/clingo/unblock/inst1.lp
@@ -0,0 +1,15 @@
+field(1..6,1..6).
+
+stone(1, y,1,1,2).
+stone(2, x,2,1,3).
+stone(3, y,5,1,2).
+stone(4, y,6,1,3).
+stone(5, y,3,2,2).
+stone(6, x,4,3,2).
+stone(7, x,1,4,3).
+stone(8, y,4,4,2).
+stone(9, x,5,5,2).
+stone(10,x,1,6,2).
+stone(11,x,3,6,2).
+
+target(6,5,3).
diff --git a/examples/clingo/unblock/inst2.lp b/examples/clingo/unblock/inst2.lp
new file mode 100644
index 0000000..356d1c1
--- /dev/null
+++ b/examples/clingo/unblock/inst2.lp
@@ -0,0 +1,18 @@
+field(1..6,1..6).
+
+stone(1, x,1,3,2).
+stone(2, x,1,4,2).
+stone(3, x,1,5,2).
+stone(4, x,1,6,2).
+stone(5, x,4,1,2).
+stone(6, x,3,2,2).
+stone(7, x,5,4,2).
+stone(8, x,4,5,3).
+stone(9, x,4,6,3).
+stone(10,y,3,3,2).
+stone(11,y,3,5,2).
+stone(12,y,4,3,2).
+stone(13,y,5,2,2).
+stone(14,y,6,1,3).
+
+target(1,5,3).
diff --git a/examples/clingo/unblock/inst3.lp b/examples/clingo/unblock/inst3.lp
new file mode 100644
index 0000000..85a69dc
--- /dev/null
+++ b/examples/clingo/unblock/inst3.lp
@@ -0,0 +1,11 @@
+field(1..6,1..6).
+stone(1,x,2,3,2).
+stone(2,x,2,4,2).
+stone(3,x,4,5,2).
+stone(4,y,1,2,2).
+stone(5,y,2,5,2).
+stone(6,y,3,5,2).
+stone(7,y,4,2,3).
+stone(8,y,6,2,3).
+
+target(1,5,3).
diff --git a/examples/clingo/unblock/inst4.lp b/examples/clingo/unblock/inst4.lp
new file mode 100644
index 0000000..962e825
--- /dev/null
+++ b/examples/clingo/unblock/inst4.lp
@@ -0,0 +1,14 @@
+target(8,5,4).
+
+field(1..6,1..6).
+
+target(8,5,4).
+
+stone(7,x,1,6,3).
+stone(8,x,1,4,2).
+stone(5,x,5,3,2).
+stone(1,x,1,1,3).
+stone(6,y,6,4,3).
+stone(4,y,3,3,3).
+stone(3,y,1,2,2).
+stone(2,y,5,1,2).
diff --git a/examples/clingo/unblock/inst5.lp b/examples/clingo/unblock/inst5.lp
new file mode 100644
index 0000000..096433a
--- /dev/null
+++ b/examples/clingo/unblock/inst5.lp
@@ -0,0 +1,42 @@
+brick(1,1,2). %%
+brick(1,2,2).
+
+brick(2,3,2). %%
+brick(2,4,2).
+
+brick(3,6,4). %
+brick(3,6,3). %
+brick(3,6,2). %
+
+brick(4,1,3). %%
+brick(4,2,3).
+
+brick(5,3,3). %%
+brick(5,4,3).
+
+brick(6,1,6). %
+brick(6,1,5). %
+brick(6,1,4). %
+
+brick(r,2,4). %%
+brick(r,3,4).
+
+brick(7,4,4). %
+brick(7,4,5). %
+
+brick(8,3,5). %
+brick(8,3,6). %
+
+brick(9,6,6). %%%
+brick(9,5,6).
+brick(9,4,6).
+
+brick(I) :- brick(I,_,_).
+count(I,L) :- brick(I), L = { brick(I,X,Y) }.
+stone(I,x,X,Y,L) :- not brick(I,X-1,Y), brick(I,X,Y), brick(I,X+1,Y), count(I,L).
+stone(I,y,X,Y,L) :- not brick(I,X,Y-1), brick(I,X,Y), brick(I,X,Y+1), count(I,L).
+
+target(r,5,4).
+
+field(1..6,1..6).
+
diff --git a/examples/clingo/unblock/unblock.lp b/examples/clingo/unblock/unblock.lp
new file mode 100644
index 0000000..0dadefa
--- /dev/null
+++ b/examples/clingo/unblock/unblock.lp
@@ -0,0 +1,48 @@
+#include .
+
+#program base.
+% first time step
+stone(0,S,D,X,Y,L) :- stone(S,D,X,Y,L).
+
+#program step(t).
+% select possible moves
+{ move(t,S,x,X2) : field(X2,Y), field(X2+L-1,Y), X1 != X2 } 1 :- stone(t-1,S,x,X1,Y,L).
+{ move(t,S,y,Y2) : field(X,Y2), field(X,Y2+L-1), Y1 != Y2 } 1 :- stone(t-1,S,y,X,Y1,L).
+
+% transition function
+stone(t,S,x,X2,Y,L) :- stone(t-1,S,x,X1,Y,L), move(t,S,x,X2).
+stone(t,S,y,X,Y2,L) :- stone(t-1,S,y,X,Y1,L), move(t,S,y,Y2).
+
+% inertia
+stone(t,S,D,X,Y,L) :- stone(t-1,S,D,X,Y,L), not move(t,S,_,_).
+
+% field blocked by some stone
+blocked(t,X+(0..L-1),Y) :- stone(t-1,S,x,X,Y,L).
+blocked(t,X,Y+(0..L-1)) :- stone(t-1,S,y,X,Y,L).
+
+%:- 2 { move(t,_,_,_) }.
+% allow for parallel moves 
+:- 2 { move(t,S,x,X) }, field(X,_).
+:- 2 { move(t,S,y,Y) }, field(_,Y).
+:- move(t,_,x,_), move(t,_,y,_).
+
+% fail if move is blocked
+:- blocked(t,X3,Y), stone(t-1,S,x,X1,Y,L), move(t,S,x,X2), X1 < X2, X1 + L <= X3, X3 < X2 + L.
+:- blocked(t,X3,Y), stone(t-1,S,x,X1,Y,_), move(t,S,x,X2), X2 < X1, X2     <= X3, X3 < X1.
+:- blocked(t,X,Y3), stone(t-1,S,y,X,Y1,L), move(t,S,y,Y2), Y1 < Y2, Y1 + L <= Y3, Y3 < Y2 + L.
+:- blocked(t,X,Y3), stone(t-1,S,y,X,Y1,_), move(t,S,y,Y2), Y2 < Y1, Y2     <= Y3, Y3 < Y1.
+
+% some domain knowledge (redundant)
+:- stone(t,S1,x,X1,Y,N1), stone(t,S2,x,X2,Y,_), S1 != S2, X1 <= X2, X2 < X1 + N1.
+:- stone(t,S1,y,X,Y1,N1), stone(t,S2,y,X,Y2,_), S1 != S2, Y1 <= Y2, Y2 < Y1 + N1.
+:- stone(t,_,x,X1,Y1,N1), stone(t,_,y,X2,Y2,N2), X2 >= X1, X2 < X1 + N1, Y1 >= Y2, Y1 < Y2 + N2.
+
+#program check(t).
+:- target(S,X,Y), not stone(t,S,_,X,Y,_), query(t).
+
+#show move/4.
+
+% just for output
+#show field/2.
+#show stone/5.
+#show target/3.
diff --git a/examples/clingo/unblock/visualize.py b/examples/clingo/unblock/visualize.py
new file mode 100755
index 0000000..b711458
--- /dev/null
+++ b/examples/clingo/unblock/visualize.py
@@ -0,0 +1,179 @@
+#!/usr/bin/python
+
+import clingo
+import urwid
+import sys
+
+class Plan:
+    def __init__(self, field, stone, target, move):
+        mx           = min([x for (x, y) in field])
+        my           = min([y for (x, y) in field])
+        self.width   = max([x for (x, y) in field]) - mx + 1
+        self.height  = max([y for (x, y) in field]) - my + 1
+        self.field   = [ (x - mx, y - my) for (x, y) in field ]
+        self.target  = [ (s, x - mx, y - my) for (s, x, y) in target ]
+        self._stones = [ [ (s, d, x - mx, y - my, l) for (s, d, x, y, l) in stone ] ]
+        self._moves  = [ ]
+        self._locs   = [ ]
+
+        for t in sorted(move.keys()):
+            for (s, d, xy) in move[t]:
+                xy -= (mx if d == "x" else my)
+                self._moves.append((s, d, xy))
+                self._stones.append([])
+                for (ss, sd, sx, sy, sl) in self._stones[-2]:
+                    if ss == s:
+                        if d == "x": sx = xy
+                        else       : sy = xy
+                        self._locs.append((sd, sx, sy, sl))
+                    self._stones[-1].append((ss, sd, sx, sy, sl))
+        self._moves.append(None)
+        self._locs.append(None)
+
+    def loc(self, i):
+        return self._locs[i]
+
+    def move(self, i):
+        return self._moves[i]
+
+    def stones(self, i):
+        return self._stones[i]
+
+    def next(self, i):
+        return i + 1 if i + 1 < len(self._stones) else i
+
+    def prev(self, i):
+        return i - 1 if i - 1 >= 0 else i
+
+    def first(self):
+        return 0
+
+class Board:
+
+    def __init__(self, plan):
+        self.display = urwid.Text("", align='center')
+        self.plan    = plan
+        self.current = plan.first()
+        self.update()
+
+    def next(self, button):
+        self.current = self.plan.next(self.current)
+        self.update()
+
+    def prev(self, button):
+        self.current = self.plan.prev(self.current)
+        self.update()
+
+    def update(self):
+        brd = [[" "] * (self.plan.width * 2 + 1) for _ in range(0, (self.plan.height * 2 + 1))]
+
+        for (x, y) in self.plan.field:
+            brd[2 * y + 1][2 * x + 0] = "|"
+            brd[2 * y + 1][2 * x + 2] = "|"
+
+        for (x, y) in self.plan.field:
+            brd[2 * y + 0][2 * x + 0] = "-"
+            brd[2 * y + 0][2 * x + 1] = "-"
+            brd[2 * y + 0][2 * x + 2] = "-"
+            brd[2 * y + 2][2 * x + 0] = "-"
+            brd[2 * y + 2][2 * x + 1] = "-"
+            brd[2 * y + 2][2 * x + 2] = "-"
+
+        for (s, d, x, y, l) in self.plan.stones(self.current):
+            sx = 2 * x + 1
+            sy = 2 * y + 1
+            m  = self.plan.move(self.current)
+            if m != None: m = m[0]
+
+            for sd in range(0, 2 * l - 1):
+               brd[sy + (sd if d == "y" else 0)][sx + (sd if d == "x" else 0)] = ('red', d) if s == m else d
+
+        loc = self.plan.loc(self.current)
+        if loc != None:
+            (d, x, y, l) = loc
+            x = 2 * x + 1
+            y = 2 * y + 1
+            for sd in range(0, 2 * l - 1):
+                sx = x + (sd if d == "x" else 0)
+                sy = y + (sd if d == "y" else 0)
+                if brd[sy][sx] in [" ", "|", "-"]: brd[sy][sx] = ('blue', brd[sy][sx])
+
+        for (s, x, y) in self.plan.target:
+            s = brd[2 * y + 1][2 * x + 1]
+            if isinstance(s, tuple): s = s[1]
+            brd[2 * y + 1][2 * x + 1] = ("green", s)
+
+        markup = []
+        for row in brd:
+            markup.extend(row)
+            markup.append("\n")
+
+        self.display.set_text(markup)
+
+class MainWindow:
+    def __init__(self):
+           self.loop = None
+
+    def exit(self, button):
+        raise urwid.ExitMainLoop()
+
+    def run(self, plan):
+
+        c = Board(plan)
+
+        ba = urwid.Button("previous")
+        bb = urwid.Button("quit")
+        bc = urwid.Button("next")
+
+        urwid.connect_signal(bb, 'click', self.exit)
+        urwid.connect_signal(bc, 'click', c.next)
+        urwid.connect_signal(ba, 'click', c.prev)
+
+        sf = urwid.Text("")
+
+        b = urwid.Columns([sf, ('fixed', len(bc.label) + 4, bc), ('fixed', len(ba.label) + 4, ba), ('fixed', len(bb.label) + 4, bb), sf], 1)
+        f = urwid.Frame(urwid.Filler(c.display), None, b, 'footer')
+
+        palette = [
+            ('red', 'black', 'light red'),
+            ('green', 'black', 'light green'),
+            ('blue', 'black', 'light blue'), ]
+
+        self.loop = urwid.MainLoop(f, palette)
+        self.loop.run()
+
+c = clingo.Control()
+c.add("check", ["k"], "#external query(k).")
+for f in sys.argv[1:]: c.load(f)
+def make_on_model(field, stone, move, target):
+    def on_model(m):
+        for atom in m.symbols(atoms=True):
+            if atom.name == "field" and len(atom.arguments) == 2:
+                x, y = [n.number for n in atom.arguments]
+                field.append((x, y))
+            elif atom.name == "stone" and len(atom.arguments) == 5:
+                s, d, x, y, l = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                stone.append((s, d, x, y, l))
+            elif atom.name == "move" and len(atom.arguments) == 4:
+                t, s, d, xy = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                move.setdefault(t, []).append((s, d, xy))
+            elif atom.name == "target" and len(atom.arguments) == 3:
+                s, x, y = [(n.number if n.type == clingo.SymbolType.Number else str(n)) for n in atom.arguments]
+                target.append((s, x, y))
+        return False
+    return on_model
+
+t, field, stone, move, target = 0, [], [], {}, []
+on_model = make_on_model(field, stone, move, target)
+c.ground([("base", [])])
+while True:
+    t += 1
+    c.ground([("step", [t])])
+    c.ground([("check", [t])])
+    c.release_external(clingo.Function("query", [t-1]))
+    c.assign_external(clingo.Function("query", [t]), True)
+    if c.solve(on_model).satisfiable:
+        break
+
+MainWindow().run(Plan(field, stone, target, move))
+
diff --git a/examples/gringo/acyc/README b/examples/gringo/acyc/README
new file mode 100644
index 0000000..e515aa6
--- /dev/null
+++ b/examples/gringo/acyc/README
@@ -0,0 +1,5 @@
+Example showcasing the #edge directive.
+
+Example calls:
+    clingo encoding.lp instance.lp
+
diff --git a/examples/gringo/acyc/encoding.lp b/examples/gringo/acyc/encoding.lp
new file mode 100644
index 0000000..a5fd665
--- /dev/null
+++ b/examples/gringo/acyc/encoding.lp
@@ -0,0 +1,7 @@
+1 { path(X,Y) : edge(X,Y) } 1 :- node(X).
+1 { path(X,Y) : edge(X,Y) } 1 :- node(Y).
+start(X) :- X = #min { Y : node(Y) }.
+#edge (X,Y) : path(X,Y), not start(Y).
+
+#show path/2.
+
diff --git a/examples/gringo/acyc/instance.lp b/examples/gringo/acyc/instance.lp
new file mode 100644
index 0000000..5aadd40
--- /dev/null
+++ b/examples/gringo/acyc/instance.lp
@@ -0,0 +1,3 @@
+node(a;b;c;d).
+edge(a,b;b,(a;c;d);c,(a;d);d,(a;c)).
+
diff --git a/examples/gringo/ast/README b/examples/gringo/ast/README
new file mode 100644
index 0000000..50bcdba
--- /dev/null
+++ b/examples/gringo/ast/README
@@ -0,0 +1,6 @@
+This example shows how to use gringo's abstract syntax tree to append an
+additional parameter to all symbolic atoms occurring in a program.
+
+Example calls:
+    gringo --text visitor.lp
+
diff --git a/examples/gringo/ast/example.lp b/examples/gringo/ast/example.lp
new file mode 100644
index 0000000..e5f1c1d
--- /dev/null
+++ b/examples/gringo/ast/example.lp
@@ -0,0 +1,7 @@
+#show q/1.
+#show r(X) : q(X).
+
+#external z(X) : q(X).
+
+{p(a;b;c)}.
+q(X) :- p(X).
diff --git a/examples/gringo/ast/visitor.lp b/examples/gringo/ast/visitor.lp
new file mode 100644
index 0000000..2a13202
--- /dev/null
+++ b/examples/gringo/ast/visitor.lp
@@ -0,0 +1,72 @@
+#script (python)
+
+import clingo
+import clingo.ast
+
+class Transformer:
+    def visit_children(self, x, *args, **kwargs):
+        for key in x.child_keys:
+            setattr(x, key, self.visit(getattr(x, key), *args, **kwargs))
+        return x
+
+    def visit(self, x, *args, **kwargs):
+        if isinstance(x, clingo.ast.AST):
+            attr = "visit_" + str(x.type)
+            if hasattr(self, attr):
+                return getattr(self, attr)(x, *args, **kwargs)
+            else:
+                return self.visit_children(x, *args, **kwargs)
+        elif isinstance(x, list):
+            return [self.visit(y, *args, **kwargs) for y in x]
+        elif x is None:
+            return x
+        else:
+            raise TypeError("unexpected type")
+
+class TermTransformer(Transformer):
+    def __init__(self, parameter):
+        self.parameter = parameter
+
+    def visit_Function(self, term):
+        term.arguments.append(clingo.ast.Symbol(term.location, self.parameter))
+        return term
+
+    def visit_Symbol(self, term):
+        # this function is not necessary if gringo's parser is used
+        # but this case could occur in a valid AST
+        fun = term.symbol
+        assert(fun.type == clingo.SymbolType.Function)
+        term.symbol = clingo.Function(fun.name, fun.arguments + [self.parameter], fun.positive)
+        return term
+
+class ProgramTransformer(Transformer):
+    def __init__(self, parameter):
+        self.parameter = parameter
+        self.term_transformer = TermTransformer(parameter)
+
+    def visit_SymbolicAtom(self, atom):
+        atom.term = self.term_transformer.visit(atom.term)
+        return atom
+
+    def visit_Program(self, prg):
+        prg.parameters.append(clingo.ast.Id(prg.location, self.parameter.name))
+        return prg
+
+    def visit_ShowSignature(self, sig):
+        sig.arity += 1
+        return sig
+
+    def visit_ProjectSignature(self, sig):
+        sig.arity += 1
+        return sig
+
+def main(prg):
+    with prg.builder() as b:
+        t = ProgramTransformer(clingo.Function("k"))
+        clingo.parse_program(
+            open("example.lp").read(),
+            lambda stm: b.add(t.visit(stm)))
+    prg.ground([("base", [clingo.Number(i)]) for i in range(3)])
+    prg.solve()
+
+#end.
diff --git a/examples/gringo/gbie/README b/examples/gringo/gbie/README
new file mode 100644
index 0000000..c4473e8
--- /dev/null
+++ b/examples/gringo/gbie/README
@@ -0,0 +1,9 @@
+This is a benchmark that requires a grounder based on semi-naïve evaluation or
+related methods. That is, gringo prior to version three will not be able to
+instantiate this. The benchmark has been taken from the 2011 ASP-Competition:
+
+https://www.mat.unical.it/aspcomp2011/
+
+Example calls:
+    clingo gbie1.lp instances/sat_01.lp
+    clingo gbie2.lp instances/sat_01.lp
diff --git a/examples/gringo/gbie/gbie1.lp b/examples/gringo/gbie/gbie1.lp
new file mode 100644
index 0000000..7a18cab
--- /dev/null
+++ b/examples/gringo/gbie/gbie1.lp
@@ -0,0 +1,47 @@
+char_to_digit(0, 0).
+char_to_digit(1, 1).
+char_to_digit(2, 2).
+char_to_digit(3, 3).
+char_to_digit(4, 4).
+char_to_digit(5, 5).
+char_to_digit(6, 6).
+char_to_digit(7, 7).
+char_to_digit(8, 8).
+char_to_digit(9, 9).
+
+digit(X, Y, D) :- char(C, Y), char_to_digit(C, D), X = Y - 1, X >= 0.
+dig(X) :- digit(A, X, B).
+
+sign(X, 1) :- char(p, X).
+sign(X, Y) :- char(m, X), Y = 0 - 1.
+
+num_1(X, Y, Val) :- digit(X, Y, Val), not dig(X).
+num_1(X, Z, NewVal) :- num_1(X, Y, Val_1), digit(Y, Z, Val_2), NewVal_1 = 10 * Val_1, NewVal = NewVal_1 + Val_2.
+num(X, Y, Val) :- num_1(X, Y, Val), Z = Y + 1, not dig(Z).
+
+par_expr(X, W, Val) :- char(o, Y), expr(Y, Z, Val), W = Z + 1, char(c, W), X = Y - 1, X >= 0.
+
+sing_term(X, Z, Val) :- par_expr(Y, Z, Val1), sign(Y, S), Val = Val1 * S, X = Y - 1, X >= 0.
+sing_term(X, Z, Val) :- num(Y, Z, Val1), sign(Y, S), Val = Val1 * S, X = Y - 1, X >= 0.
+
+expr(X, Y, Val) :- char(o, X), num(X, Y, Val).
+expr(0, Y, Val) :- num(0, Y, Val).
+expr(X, Y, Val) :- par_expr(X, Y, Val).
+expr(X, Y, Val) :- sing_term(X, Y, Val).
+
+expr(X, Z, Val) :- expr(X, Y, Val_1), sing_term(Y, Z, Val_2), Val = Val_1 + Val_2.
+
+cmp(X, W, Val) :- char(g, Y), num(Y, W, Val), X = Y - 1, X >= 0.
+cmp(X, W, Val) :- char(g, Y), Z = Y + 1, sign(Z, S), num(Z, W, Val1), Val = S * Val1, X = Y - 1, X >= 0.
+
+sol :- expr(0, Y, Val1), cmp(Y, Z, Val2), Val1 > Val2.
+
+val1(Y, p, V) :- expr(0, Y, V), V >= 0.
+val1(Y, m, V) :- expr(0, Y, V1), V1 < 0, V = 0 - V1.
+val2(Y, p, V) :- val1(Y, A, B), cmp(Y, Z, V), V >= 0.
+val2(Y, m, V) :- val1(Y, A, B), cmp(Y, Z, V1), V1 < 0, V = 0 - V1.
+
+values(S1, V1, S2, V2) :- val1(Y, S1, V1), val2(Y, S2, V2).
+fail :- not sol, not fail.
+
+#show values/4.
diff --git a/examples/gringo/gbie/gbie2.lp b/examples/gringo/gbie/gbie2.lp
new file mode 100644
index 0000000..af011d5
--- /dev/null
+++ b/examples/gringo/gbie/gbie2.lp
@@ -0,0 +1,32 @@
+char_to_digit(X,X) :- X=0..9.
+
+digit(Y-1,Y,D) :- char(C,Y), char_to_digit(C,D), Y > 0.
+
+sign(X, 1) :- char(p,X).
+sign(X,-1) :- char(m,X).
+
+num_1(X,Y,A)      :- digit(X,Y,A), not digit(_,X,_).
+num_1(X,Z,10*A+B) :- num_1(X,Y,A), digit(Y,Z,B).
+num(X,Y,A)        :- num_1(X,Y,A), not digit(_,Y+1,_).
+
+par_expr(Y-1,Z+1,A) :- char(o,Y), expr(Y,Z,A), char(c,Z+1), Y >= 0.
+
+sign_expr(Y-1,Z,A*S) :- par_expr(Y,Z,A), sign(Y,S), Y > 0.
+sign_expr(Y-1,Z,A*S) :- num(Y,Z,A),      sign(Y,S), Y > 0.
+
+expr(0,Y,A)   :- num(0,Y,A).
+expr(X,Y,A)   :- char(o,X), num(X,Y,A).
+expr(X,Y,A)   :- par_expr(X,Y,A).
+expr(X,Y,A)   :- sign_expr(X,Y,A).
+expr(X,Z,A+B) :- expr(X,Y,A), sign_expr(Y,Z,B).
+
+cmp(Y-1,A)   :- char(g,Y), num(Y,_,A), Y > 0.
+cmp(Y-1,A*S) :- char(g,Y), sign(Y+1,S), num(Y+1,_,A), Y > 0.
+
+eq(A,A) :- expr(0,Y,A), cmp(Y,A).
+lt(A,B) :- expr(0,Y,A), cmp(Y,B), A < B.
+gt(A,B) :- expr(0,Y,A), cmp(Y,B), A > B.
+
+#show eq/2.
+#show lt/2.
+#show gt/2.
diff --git a/examples/gringo/gbie/instances/sat_01.lp b/examples/gringo/gbie/instances/sat_01.lp
new file mode 100644
index 0000000..7167d48
--- /dev/null
+++ b/examples/gringo/gbie/instances/sat_01.lp
@@ -0,0 +1,33 @@
+char(p,1).
+char(0,2).
+char(m,3).
+char(o,4).
+char(o,5).
+char(6,6).
+char(m,7).
+char(7,8).
+char(p,9).
+char(3,10).
+char(p,11).
+char(o,12).
+char(4,13).
+char(c,14).
+char(c,15).
+char(m,16).
+char(2,17).
+char(p,18).
+char(o,19).
+char(p,20).
+char(0,21).
+char(c,22).
+char(c,23).
+char(p,24).
+char(2,25).
+char(m,26).
+char(o,27).
+char(p,28).
+char(1,29).
+char(c,30).
+char(g,31).
+char(m,32).
+char(4,33).
diff --git a/examples/gringo/gbie/instances/sat_02.lp b/examples/gringo/gbie/instances/sat_02.lp
new file mode 100644
index 0000000..56e36d5
--- /dev/null
+++ b/examples/gringo/gbie/instances/sat_02.lp
@@ -0,0 +1,95144 @@
+char(m,1).
+char(4,2).
+char(4,3).
+char(7,4).
+char(4,5).
+char(p,6).
+char(o,7).
+char(6,8).
+char(1,9).
+char(8,10).
+char(6,11).
+char(m,12).
+char(o,13).
+char(m,14).
+char(o,15).
+char(p,16).
+char(1,17).
+char(6,18).
+char(3,19).
+char(4,20).
+char(m,21).
+char(2,22).
+char(0,23).
+char(7,24).
+char(3,25).
+char(p,26).
+char(2,27).
+char(9,28).
+char(3,29).
+char(c,30).
+char(m,31).
+char(o,32).
+char(p,33).
+char(o,34).
+char(p,35).
+char(o,36).
+char(m,37).
+char(6,38).
+char(5,39).
+char(9,40).
+char(6,41).
+char(p,42).
+char(5,43).
+char(2,44).
+char(5,45).
+char(m,46).
+char(o,47).
+char(p,48).
+char(o,49).
+char(o,50).
+char(m,51).
+char(8,52).
+char(6,53).
+char(2,54).
+char(7,55).
+char(m,56).
+char(o,57).
+char(p,58).
+char(o,59).
+char(p,60).
+char(o,61).
+char(o,62).
+char(o,63).
+char(p,64).
+char(8,65).
+char(4,66).
+char(8,67).
+char(0,68).
+char(c,69).
+char(c,70).
+char(m,71).
+char(6,72).
+char(8,73).
+char(8,74).
+char(0,75).
+char(p,76).
+char(o,77).
+char(m,78).
+char(o,79).
+char(p,80).
+char(8,81).
+char(5,82).
+char(9,83).
+char(p,84).
+char(o,85).
+char(9,86).
+char(2,87).
+char(8,88).
+char(5,89).
+char(c,90).
+char(c,91).
+char(c,92).
+char(c,93).
+char(c,94).
+char(c,95).
+char(p,96).
+char(4,97).
+char(8,98).
+char(9,99).
+char(7,100).
+char(c,101).
+char(c,102).
+char(c,103).
+char(c,104).
+char(c,105).
+char(m,106).
+char(1,107).
+char(2,108).
+char(4,109).
+char(8,110).
+char(m,111).
+char(6,112).
+char(1,113).
+char(1,114).
+char(4,115).
+char(m,116).
+char(o,117).
+char(p,118).
+char(4,119).
+char(8,120).
+char(6,121).
+char(5,122).
+char(c,123).
+char(m,124).
+char(6,125).
+char(1,126).
+char(3,127).
+char(7,128).
+char(c,129).
+char(p,130).
+char(o,131).
+char(o,132).
+char(2,133).
+char(6,134).
+char(5,135).
+char(0,136).
+char(c,137).
+char(p,138).
+char(2,139).
+char(7,140).
+char(0,141).
+char(3,142).
+char(c,143).
+char(c,144).
+char(m,145).
+char(6,146).
+char(1,147).
+char(2,148).
+char(4,149).
+char(m,150).
+char(o,151).
+char(o,152).
+char(p,153).
+char(o,154).
+char(o,155).
+char(o,156).
+char(p,157).
+char(o,158).
+char(m,159).
+char(o,160).
+char(p,161).
+char(1,162).
+char(4,163).
+char(6,164).
+char(4,165).
+char(m,166).
+char(1,167).
+char(4,168).
+char(2,169).
+char(4,170).
+char(m,171).
+char(5,172).
+char(6,173).
+char(5,174).
+char(7,175).
+char(m,176).
+char(1,177).
+char(5,178).
+char(6,179).
+char(6,180).
+char(m,181).
+char(o,182).
+char(p,183).
+char(7,184).
+char(7,185).
+char(9,186).
+char(4,187).
+char(c,188).
+char(p,189).
+char(o,190).
+char(7,191).
+char(6,192).
+char(1,193).
+char(9,194).
+char(m,195).
+char(8,196).
+char(0,197).
+char(4,198).
+char(8,199).
+char(c,200).
+char(c,201).
+char(c,202).
+char(c,203).
+char(c,204).
+char(p,205).
+char(4,206).
+char(3,207).
+char(9,208).
+char(4,209).
+char(p,210).
+char(3,211).
+char(3,212).
+char(6,213).
+char(4,214).
+char(c,215).
+char(p,216).
+char(o,217).
+char(o,218).
+char(o,219).
+char(p,220).
+char(o,221).
+char(o,222).
+char(m,223).
+char(6,224).
+char(0,225).
+char(6,226).
+char(5,227).
+char(c,228).
+char(p,229).
+char(o,230).
+char(p,231).
+char(o,232).
+char(m,233).
+char(4,234).
+char(7,235).
+char(7,236).
+char(7,237).
+char(m,238).
+char(o,239).
+char(o,240).
+char(o,241).
+char(m,242).
+char(o,243).
+char(2,244).
+char(9,245).
+char(0,246).
+char(3,247).
+char(p,248).
+char(o,249).
+char(o,250).
+char(m,251).
+char(o,252).
+char(p,253).
+char(o,254).
+char(m,255).
+char(o,256).
+char(5,257).
+char(0,258).
+char(2,259).
+char(0,260).
+char(m,261).
+char(3,262).
+char(1,263).
+char(9,264).
+char(8,265).
+char(c,266).
+char(c,267).
+char(p,268).
+char(4,269).
+char(9,270).
+char(3,271).
+char(1,272).
+char(m,273).
+char(o,274).
+char(m,275).
+char(o,276).
+char(m,277).
+char(4,278).
+char(0,279).
+char(4,280).
+char(2,281).
+char(p,282).
+char(3,283).
+char(7,284).
+char(4,285).
+char(8,286).
+char(c,287).
+char(c,288).
+char(c,289).
+char(c,290).
+char(c,291).
+char(p,292).
+char(2,293).
+char(3,294).
+char(7,295).
+char(0,296).
+char(c,297).
+char(m,298).
+char(o,299).
+char(m,300).
+char(7,301).
+char(0,302).
+char(2,303).
+char(1,304).
+char(c,305).
+char(m,306).
+char(8,307).
+char(5,308).
+char(6,309).
+char(0,310).
+char(c,311).
+char(p,312).
+char(o,313).
+char(p,314).
+char(o,315).
+char(p,316).
+char(o,317).
+char(p,318).
+char(6,319).
+char(1,320).
+char(0,321).
+char(m,322).
+char(4,323).
+char(2,324).
+char(8,325).
+char(9,326).
+char(c,327).
+char(c,328).
+char(c,329).
+char(m,330).
+char(2,331).
+char(0,332).
+char(8,333).
+char(3,334).
+char(c,335).
+char(p,336).
+char(2,337).
+char(3,338).
+char(0,339).
+char(0,340).
+char(c,341).
+char(m,342).
+char(4,343).
+char(1,344).
+char(1,345).
+char(8,346).
+char(m,347).
+char(3,348).
+char(5,349).
+char(8,350).
+char(9,351).
+char(c,352).
+char(c,353).
+char(m,354).
+char(7,355).
+char(4,356).
+char(9,357).
+char(9,358).
+char(c,359).
+char(c,360).
+char(m,361).
+char(8,362).
+char(1,363).
+char(8,364).
+char(6,365).
+char(c,366).
+char(c,367).
+char(p,368).
+char(o,369).
+char(1,370).
+char(1,371).
+char(9,372).
+char(1,373).
+char(p,374).
+char(9,375).
+char(4,376).
+char(9,377).
+char(7,378).
+char(m,379).
+char(o,380).
+char(p,381).
+char(o,382).
+char(p,383).
+char(o,384).
+char(m,385).
+char(o,386).
+char(p,387).
+char(7,388).
+char(7,389).
+char(7,390).
+char(8,391).
+char(c,392).
+char(p,393).
+char(o,394).
+char(m,395).
+char(o,396).
+char(m,397).
+char(9,398).
+char(2,399).
+char(0,400).
+char(2,401).
+char(m,402).
+char(o,403).
+char(m,404).
+char(7,405).
+char(9,406).
+char(6,407).
+char(p,408).
+char(3,409).
+char(8,410).
+char(6,411).
+char(1,412).
+char(p,413).
+char(o,414).
+char(7,415).
+char(9,416).
+char(5,417).
+char(8,418).
+char(c,419).
+char(m,420).
+char(o,421).
+char(o,422).
+char(m,423).
+char(7,424).
+char(5,425).
+char(8,426).
+char(8,427).
+char(c,428).
+char(m,429).
+char(o,430).
+char(p,431).
+char(o,432).
+char(p,433).
+char(o,434).
+char(o,435).
+char(o,436).
+char(p,437).
+char(1,438).
+char(8,439).
+char(7,440).
+char(5,441).
+char(c,442).
+char(p,443).
+char(o,444).
+char(o,445).
+char(m,446).
+char(o,447).
+char(m,448).
+char(3,449).
+char(5,450).
+char(5,451).
+char(6,452).
+char(m,453).
+char(9,454).
+char(7,455).
+char(4,456).
+char(6,457).
+char(m,458).
+char(o,459).
+char(p,460).
+char(o,461).
+char(o,462).
+char(o,463).
+char(p,464).
+char(o,465).
+char(m,466).
+char(o,467).
+char(m,468).
+char(8,469).
+char(5,470).
+char(0,471).
+char(1,472).
+char(p,473).
+char(5,474).
+char(3,475).
+char(2,476).
+char(p,477).
+char(o,478).
+char(p,479).
+char(5,480).
+char(4,481).
+char(8,482).
+char(5,483).
+char(c,484).
+char(p,485).
+char(7,486).
+char(9,487).
+char(9,488).
+char(3,489).
+char(c,490).
+char(c,491).
+char(c,492).
+char(c,493).
+char(p,494).
+char(9,495).
+char(2,496).
+char(1,497).
+char(7,498).
+char(c,499).
+char(m,500).
+char(o,501).
+char(m,502).
+char(3,503).
+char(6,504).
+char(2,505).
+char(2,506).
+char(p,507).
+char(1,508).
+char(9,509).
+char(9,510).
+char(c,511).
+char(p,512).
+char(6,513).
+char(6,514).
+char(6,515).
+char(1,516).
+char(p,517).
+char(o,518).
+char(m,519).
+char(o,520).
+char(p,521).
+char(6,522).
+char(3,523).
+char(6,524).
+char(6,525).
+char(m,526).
+char(8,527).
+char(6,528).
+char(1,529).
+char(m,530).
+char(o,531).
+char(p,532).
+char(o,533).
+char(p,534).
+char(6,535).
+char(4,536).
+char(7,537).
+char(5,538).
+char(p,539).
+char(4,540).
+char(3,541).
+char(9,542).
+char(3,543).
+char(c,544).
+char(c,545).
+char(c,546).
+char(p,547).
+char(8,548).
+char(4,549).
+char(1,550).
+char(4,551).
+char(c,552).
+char(m,553).
+char(9,554).
+char(4,555).
+char(5,556).
+char(0,557).
+char(p,558).
+char(3,559).
+char(0,560).
+char(9,561).
+char(4,562).
+char(m,563).
+char(o,564).
+char(p,565).
+char(5,566).
+char(5,567).
+char(7,568).
+char(8,569).
+char(p,570).
+char(5,571).
+char(8,572).
+char(1,573).
+char(8,574).
+char(p,575).
+char(6,576).
+char(4,577).
+char(2,578).
+char(2,579).
+char(c,580).
+char(c,581).
+char(c,582).
+char(c,583).
+char(c,584).
+char(c,585).
+char(m,586).
+char(3,587).
+char(9,588).
+char(3,589).
+char(9,590).
+char(m,591).
+char(o,592).
+char(p,593).
+char(o,594).
+char(m,595).
+char(o,596).
+char(m,597).
+char(9,598).
+char(0,599).
+char(3,600).
+char(1,601).
+char(p,602).
+char(o,603).
+char(o,604).
+char(p,605).
+char(o,606).
+char(p,607).
+char(5,608).
+char(5,609).
+char(8,610).
+char(5,611).
+char(c,612).
+char(c,613).
+char(c,614).
+char(c,615).
+char(p,616).
+char(o,617).
+char(o,618).
+char(m,619).
+char(5,620).
+char(4,621).
+char(6,622).
+char(5,623).
+char(m,624).
+char(1,625).
+char(6,626).
+char(2,627).
+char(7,628).
+char(m,629).
+char(o,630).
+char(o,631).
+char(p,632).
+char(o,633).
+char(p,634).
+char(o,635).
+char(m,636).
+char(o,637).
+char(9,638).
+char(7,639).
+char(7,640).
+char(7,641).
+char(p,642).
+char(o,643).
+char(p,644).
+char(8,645).
+char(6,646).
+char(1,647).
+char(7,648).
+char(m,649).
+char(4,650).
+char(3,651).
+char(3,652).
+char(4,653).
+char(c,654).
+char(m,655).
+char(o,656).
+char(p,657).
+char(1,658).
+char(4,659).
+char(4,660).
+char(1,661).
+char(m,662).
+char(3,663).
+char(2,664).
+char(8,665).
+char(5,666).
+char(m,667).
+char(4,668).
+char(4,669).
+char(1,670).
+char(c,671).
+char(m,672).
+char(3,673).
+char(2,674).
+char(1,675).
+char(0,676).
+char(m,677).
+char(o,678).
+char(m,679).
+char(9,680).
+char(9,681).
+char(0,682).
+char(1,683).
+char(c,684).
+char(p,685).
+char(o,686).
+char(p,687).
+char(o,688).
+char(o,689).
+char(1,690).
+char(6,691).
+char(5,692).
+char(3,693).
+char(c,694).
+char(p,695).
+char(7,696).
+char(2,697).
+char(4,698).
+char(2,699).
+char(c,700).
+char(c,701).
+char(p,702).
+char(8,703).
+char(1,704).
+char(7,705).
+char(5,706).
+char(c,707).
+char(c,708).
+char(c,709).
+char(c,710).
+char(c,711).
+char(m,712).
+char(o,713).
+char(p,714).
+char(o,715).
+char(m,716).
+char(o,717).
+char(p,718).
+char(8,719).
+char(1,720).
+char(3,721).
+char(p,722).
+char(o,723).
+char(p,724).
+char(o,725).
+char(5,726).
+char(3,727).
+char(m,728).
+char(9,729).
+char(4,730).
+char(1,731).
+char(7,732).
+char(m,733).
+char(o,734).
+char(m,735).
+char(o,736).
+char(m,737).
+char(o,738).
+char(2,739).
+char(3,740).
+char(7,741).
+char(0,742).
+char(m,743).
+char(o,744).
+char(m,745).
+char(3,746).
+char(8,747).
+char(6,748).
+char(7,749).
+char(p,750).
+char(o,751).
+char(3,752).
+char(5,753).
+char(2,754).
+char(0,755).
+char(c,756).
+char(p,757).
+char(o,758).
+char(p,759).
+char(6,760).
+char(3,761).
+char(5,762).
+char(0,763).
+char(p,764).
+char(5,765).
+char(8,766).
+char(6,767).
+char(9,768).
+char(c,769).
+char(m,770).
+char(1,771).
+char(6,772).
+char(2,773).
+char(3,774).
+char(c,775).
+char(c,776).
+char(p,777).
+char(8,778).
+char(9,779).
+char(4,780).
+char(9,781).
+char(c,782).
+char(c,783).
+char(c,784).
+char(c,785).
+char(c,786).
+char(c,787).
+char(p,788).
+char(5,789).
+char(6,790).
+char(9,791).
+char(5,792).
+char(c,793).
+char(c,794).
+char(c,795).
+char(c,796).
+char(c,797).
+char(m,798).
+char(3,799).
+char(5,800).
+char(5,801).
+char(0,802).
+char(c,803).
+char(c,804).
+char(c,805).
+char(c,806).
+char(p,807).
+char(2,808).
+char(3,809).
+char(4,810).
+char(8,811).
+char(c,812).
+char(m,813).
+char(o,814).
+char(p,815).
+char(o,816).
+char(m,817).
+char(o,818).
+char(m,819).
+char(o,820).
+char(m,821).
+char(7,822).
+char(0,823).
+char(1,824).
+char(3,825).
+char(c,826).
+char(c,827).
+char(p,828).
+char(3,829).
+char(2,830).
+char(2,831).
+char(3,832).
+char(c,833).
+char(p,834).
+char(8,835).
+char(5,836).
+char(6,837).
+char(2,838).
+char(c,839).
+char(c,840).
+char(c,841).
+char(p,842).
+char(9,843).
+char(7,844).
+char(3,845).
+char(7,846).
+char(m,847).
+char(o,848).
+char(p,849).
+char(8,850).
+char(9,851).
+char(8,852).
+char(m,853).
+char(o,854).
+char(p,855).
+char(7,856).
+char(1,857).
+char(3,858).
+char(7,859).
+char(c,860).
+char(p,861).
+char(7,862).
+char(5,863).
+char(4,864).
+char(5,865).
+char(m,866).
+char(o,867).
+char(m,868).
+char(5,869).
+char(1,870).
+char(6,871).
+char(1,872).
+char(p,873).
+char(5,874).
+char(6,875).
+char(6,876).
+char(3,877).
+char(p,878).
+char(o,879).
+char(m,880).
+char(o,881).
+char(3,882).
+char(9,883).
+char(2,884).
+char(c,885).
+char(c,886).
+char(m,887).
+char(6,888).
+char(2,889).
+char(1,890).
+char(9,891).
+char(p,892).
+char(4,893).
+char(8,894).
+char(9,895).
+char(7,896).
+char(c,897).
+char(c,898).
+char(m,899).
+char(1,900).
+char(7,901).
+char(0,902).
+char(1,903).
+char(c,904).
+char(m,905).
+char(o,906).
+char(o,907).
+char(m,908).
+char(o,909).
+char(p,910).
+char(o,911).
+char(p,912).
+char(7,913).
+char(8,914).
+char(7,915).
+char(3,916).
+char(m,917).
+char(4,918).
+char(7,919).
+char(1,920).
+char(0,921).
+char(c,922).
+char(m,923).
+char(9,924).
+char(6,925).
+char(3,926).
+char(8,927).
+char(c,928).
+char(c,929).
+char(p,930).
+char(2,931).
+char(8,932).
+char(3,933).
+char(1,934).
+char(c,935).
+char(c,936).
+char(p,937).
+char(o,938).
+char(p,939).
+char(o,940).
+char(5,941).
+char(1,942).
+char(6,943).
+char(7,944).
+char(c,945).
+char(c,946).
+char(m,947).
+char(2,948).
+char(4,949).
+char(1,950).
+char(6,951).
+char(c,952).
+char(c,953).
+char(p,954).
+char(o,955).
+char(6,956).
+char(7,957).
+char(9,958).
+char(7,959).
+char(c,960).
+char(m,961).
+char(o,962).
+char(m,963).
+char(7,964).
+char(9,965).
+char(4,966).
+char(p,967).
+char(o,968).
+char(1,969).
+char(1,970).
+char(1,971).
+char(p,972).
+char(o,973).
+char(p,974).
+char(4,975).
+char(1,976).
+char(3,977).
+char(6,978).
+char(p,979).
+char(1,980).
+char(3,981).
+char(3,982).
+char(5,983).
+char(c,984).
+char(m,985).
+char(o,986).
+char(p,987).
+char(6,988).
+char(3,989).
+char(9,990).
+char(5,991).
+char(p,992).
+char(1,993).
+char(0,994).
+char(6,995).
+char(7,996).
+char(p,997).
+char(o,998).
+char(3,999).
+char(5,1000).
+char(7,1001).
+char(0,1002).
+char(c,1003).
+char(p,1004).
+char(o,1005).
+char(m,1006).
+char(o,1007).
+char(p,1008).
+char(o,1009).
+char(p,1010).
+char(o,1011).
+char(p,1012).
+char(o,1013).
+char(p,1014).
+char(o,1015).
+char(p,1016).
+char(o,1017).
+char(m,1018).
+char(o,1019).
+char(m,1020).
+char(6,1021).
+char(3,1022).
+char(8,1023).
+char(7,1024).
+char(m,1025).
+char(o,1026).
+char(m,1027).
+char(o,1028).
+char(p,1029).
+char(5,1030).
+char(9,1031).
+char(1,1032).
+char(9,1033).
+char(p,1034).
+char(o,1035).
+char(m,1036).
+char(5,1037).
+char(2,1038).
+char(9,1039).
+char(2,1040).
+char(p,1041).
+char(5,1042).
+char(7,1043).
+char(9,1044).
+char(0,1045).
+char(c,1046).
+char(c,1047).
+char(c,1048).
+char(c,1049).
+char(c,1050).
+char(m,1051).
+char(9,1052).
+char(4,1053).
+char(0,1054).
+char(0,1055).
+char(c,1056).
+char(c,1057).
+char(m,1058).
+char(o,1059).
+char(m,1060).
+char(6,1061).
+char(9,1062).
+char(3,1063).
+char(3,1064).
+char(c,1065).
+char(m,1066).
+char(o,1067).
+char(p,1068).
+char(o,1069).
+char(p,1070).
+char(8,1071).
+char(5,1072).
+char(5,1073).
+char(7,1074).
+char(m,1075).
+char(o,1076).
+char(p,1077).
+char(9,1078).
+char(0,1079).
+char(3,1080).
+char(6,1081).
+char(p,1082).
+char(2,1083).
+char(2,1084).
+char(9,1085).
+char(1,1086).
+char(p,1087).
+char(7,1088).
+char(4,1089).
+char(0,1090).
+char(1,1091).
+char(c,1092).
+char(c,1093).
+char(c,1094).
+char(c,1095).
+char(c,1096).
+char(p,1097).
+char(8,1098).
+char(4,1099).
+char(5,1100).
+char(9,1101).
+char(m,1102).
+char(o,1103).
+char(o,1104).
+char(m,1105).
+char(3,1106).
+char(3,1107).
+char(1,1108).
+char(m,1109).
+char(4,1110).
+char(1,1111).
+char(5,1112).
+char(8,1113).
+char(c,1114).
+char(m,1115).
+char(8,1116).
+char(2,1117).
+char(3,1118).
+char(c,1119).
+char(p,1120).
+char(o,1121).
+char(p,1122).
+char(o,1123).
+char(o,1124).
+char(o,1125).
+char(p,1126).
+char(1,1127).
+char(3,1128).
+char(7,1129).
+char(4,1130).
+char(c,1131).
+char(c,1132).
+char(m,1133).
+char(4,1134).
+char(8,1135).
+char(9,1136).
+char(6,1137).
+char(c,1138).
+char(c,1139).
+char(m,1140).
+char(o,1141).
+char(p,1142).
+char(2,1143).
+char(6,1144).
+char(7,1145).
+char(9,1146).
+char(m,1147).
+char(8,1148).
+char(6,1149).
+char(9,1150).
+char(5,1151).
+char(m,1152).
+char(6,1153).
+char(7,1154).
+char(1,1155).
+char(2,1156).
+char(c,1157).
+char(m,1158).
+char(7,1159).
+char(5,1160).
+char(7,1161).
+char(9,1162).
+char(p,1163).
+char(9,1164).
+char(4,1165).
+char(7,1166).
+char(4,1167).
+char(c,1168).
+char(p,1169).
+char(o,1170).
+char(p,1171).
+char(o,1172).
+char(4,1173).
+char(7,1174).
+char(9,1175).
+char(p,1176).
+char(o,1177).
+char(o,1178).
+char(p,1179).
+char(o,1180).
+char(m,1181).
+char(3,1182).
+char(9,1183).
+char(8,1184).
+char(8,1185).
+char(c,1186).
+char(c,1187).
+char(c,1188).
+char(m,1189).
+char(8,1190).
+char(6,1191).
+char(5,1192).
+char(1,1193).
+char(c,1194).
+char(c,1195).
+char(c,1196).
+char(p,1197).
+char(o,1198).
+char(o,1199).
+char(p,1200).
+char(8,1201).
+char(4,1202).
+char(1,1203).
+char(4,1204).
+char(m,1205).
+char(5,1206).
+char(7,1207).
+char(8,1208).
+char(c,1209).
+char(m,1210).
+char(3,1211).
+char(c,1212).
+char(m,1213).
+char(o,1214).
+char(p,1215).
+char(o,1216).
+char(p,1217).
+char(o,1218).
+char(o,1219).
+char(m,1220).
+char(o,1221).
+char(p,1222).
+char(o,1223).
+char(m,1224).
+char(o,1225).
+char(o,1226).
+char(m,1227).
+char(3,1228).
+char(0,1229).
+char(3,1230).
+char(c,1231).
+char(c,1232).
+char(p,1233).
+char(o,1234).
+char(m,1235).
+char(o,1236).
+char(m,1237).
+char(o,1238).
+char(m,1239).
+char(7,1240).
+char(0,1241).
+char(9,1242).
+char(c,1243).
+char(m,1244).
+char(3,1245).
+char(0,1246).
+char(2,1247).
+char(5,1248).
+char(m,1249).
+char(4,1250).
+char(5,1251).
+char(9,1252).
+char(3,1253).
+char(c,1254).
+char(c,1255).
+char(c,1256).
+char(p,1257).
+char(2,1258).
+char(8,1259).
+char(5,1260).
+char(c,1261).
+char(c,1262).
+char(m,1263).
+char(o,1264).
+char(p,1265).
+char(o,1266).
+char(m,1267).
+char(5,1268).
+char(6,1269).
+char(6,1270).
+char(5,1271).
+char(c,1272).
+char(c,1273).
+char(c,1274).
+char(m,1275).
+char(o,1276).
+char(o,1277).
+char(m,1278).
+char(o,1279).
+char(4,1280).
+char(0,1281).
+char(0,1282).
+char(6,1283).
+char(m,1284).
+char(o,1285).
+char(p,1286).
+char(o,1287).
+char(o,1288).
+char(9,1289).
+char(0,1290).
+char(0,1291).
+char(3,1292).
+char(c,1293).
+char(p,1294).
+char(3,1295).
+char(5,1296).
+char(8,1297).
+char(3,1298).
+char(p,1299).
+char(o,1300).
+char(4,1301).
+char(8,1302).
+char(4,1303).
+char(c,1304).
+char(m,1305).
+char(o,1306).
+char(m,1307).
+char(8,1308).
+char(3,1309).
+char(0,1310).
+char(6,1311).
+char(m,1312).
+char(o,1313).
+char(p,1314).
+char(o,1315).
+char(o,1316).
+char(p,1317).
+char(7,1318).
+char(7,1319).
+char(8,1320).
+char(3,1321).
+char(m,1322).
+char(o,1323).
+char(m,1324).
+char(1,1325).
+char(5,1326).
+char(9,1327).
+char(2,1328).
+char(c,1329).
+char(p,1330).
+char(4,1331).
+char(5,1332).
+char(0,1333).
+char(0,1334).
+char(c,1335).
+char(p,1336).
+char(o,1337).
+char(p,1338).
+char(7,1339).
+char(5,1340).
+char(0,1341).
+char(9,1342).
+char(p,1343).
+char(o,1344).
+char(3,1345).
+char(3,1346).
+char(1,1347).
+char(1,1348).
+char(p,1349).
+char(o,1350).
+char(o,1351).
+char(m,1352).
+char(o,1353).
+char(o,1354).
+char(p,1355).
+char(5,1356).
+char(5,1357).
+char(7,1358).
+char(0,1359).
+char(m,1360).
+char(o,1361).
+char(o,1362).
+char(m,1363).
+char(o,1364).
+char(o,1365).
+char(2,1366).
+char(8,1367).
+char(2,1368).
+char(7,1369).
+char(p,1370).
+char(o,1371).
+char(o,1372).
+char(p,1373).
+char(1,1374).
+char(4,1375).
+char(0,1376).
+char(5,1377).
+char(c,1378).
+char(c,1379).
+char(c,1380).
+char(c,1381).
+char(c,1382).
+char(c,1383).
+char(p,1384).
+char(1,1385).
+char(9,1386).
+char(3,1387).
+char(3,1388).
+char(m,1389).
+char(3,1390).
+char(3,1391).
+char(3,1392).
+char(2,1393).
+char(p,1394).
+char(6,1395).
+char(4,1396).
+char(9,1397).
+char(7,1398).
+char(c,1399).
+char(p,1400).
+char(2,1401).
+char(1,1402).
+char(3,1403).
+char(5,1404).
+char(p,1405).
+char(o,1406).
+char(p,1407).
+char(7,1408).
+char(3,1409).
+char(6,1410).
+char(6,1411).
+char(c,1412).
+char(p,1413).
+char(o,1414).
+char(p,1415).
+char(6,1416).
+char(5,1417).
+char(9,1418).
+char(9,1419).
+char(p,1420).
+char(o,1421).
+char(p,1422).
+char(o,1423).
+char(p,1424).
+char(6,1425).
+char(5,1426).
+char(4,1427).
+char(6,1428).
+char(p,1429).
+char(o,1430).
+char(p,1431).
+char(6,1432).
+char(5,1433).
+char(1,1434).
+char(3,1435).
+char(c,1436).
+char(c,1437).
+char(p,1438).
+char(o,1439).
+char(o,1440).
+char(p,1441).
+char(7,1442).
+char(3,1443).
+char(2,1444).
+char(4,1445).
+char(c,1446).
+char(m,1447).
+char(o,1448).
+char(m,1449).
+char(o,1450).
+char(p,1451).
+char(o,1452).
+char(m,1453).
+char(o,1454).
+char(o,1455).
+char(m,1456).
+char(2,1457).
+char(4,1458).
+char(0,1459).
+char(0,1460).
+char(p,1461).
+char(6,1462).
+char(6,1463).
+char(7,1464).
+char(0,1465).
+char(c,1466).
+char(m,1467).
+char(o,1468).
+char(p,1469).
+char(o,1470).
+char(m,1471).
+char(o,1472).
+char(m,1473).
+char(1,1474).
+char(1,1475).
+char(1,1476).
+char(8,1477).
+char(c,1478).
+char(c,1479).
+char(c,1480).
+char(m,1481).
+char(7,1482).
+char(5,1483).
+char(4,1484).
+char(2,1485).
+char(m,1486).
+char(o,1487).
+char(o,1488).
+char(p,1489).
+char(o,1490).
+char(o,1491).
+char(4,1492).
+char(2,1493).
+char(5,1494).
+char(9,1495).
+char(c,1496).
+char(p,1497).
+char(o,1498).
+char(o,1499).
+char(p,1500).
+char(o,1501).
+char(m,1502).
+char(o,1503).
+char(p,1504).
+char(2,1505).
+char(0,1506).
+char(4,1507).
+char(5,1508).
+char(c,1509).
+char(c,1510).
+char(p,1511).
+char(4,1512).
+char(0,1513).
+char(4,1514).
+char(0,1515).
+char(m,1516).
+char(9,1517).
+char(4,1518).
+char(3,1519).
+char(5,1520).
+char(c,1521).
+char(m,1522).
+char(o,1523).
+char(p,1524).
+char(2,1525).
+char(8,1526).
+char(1,1527).
+char(3,1528).
+char(c,1529).
+char(c,1530).
+char(c,1531).
+char(c,1532).
+char(c,1533).
+char(m,1534).
+char(9,1535).
+char(4,1536).
+char(2,1537).
+char(1,1538).
+char(p,1539).
+char(1,1540).
+char(3,1541).
+char(1,1542).
+char(m,1543).
+char(o,1544).
+char(p,1545).
+char(5,1546).
+char(0,1547).
+char(7,1548).
+char(1,1549).
+char(c,1550).
+char(p,1551).
+char(9,1552).
+char(2,1553).
+char(5,1554).
+char(c,1555).
+char(p,1556).
+char(o,1557).
+char(o,1558).
+char(m,1559).
+char(1,1560).
+char(0,1561).
+char(4,1562).
+char(2,1563).
+char(m,1564).
+char(6,1565).
+char(5,1566).
+char(7,1567).
+char(1,1568).
+char(p,1569).
+char(o,1570).
+char(o,1571).
+char(o,1572).
+char(o,1573).
+char(p,1574).
+char(o,1575).
+char(m,1576).
+char(9,1577).
+char(5,1578).
+char(0,1579).
+char(7,1580).
+char(c,1581).
+char(c,1582).
+char(m,1583).
+char(5,1584).
+char(1,1585).
+char(5,1586).
+char(7,1587).
+char(c,1588).
+char(c,1589).
+char(m,1590).
+char(7,1591).
+char(3,1592).
+char(9,1593).
+char(4,1594).
+char(m,1595).
+char(5,1596).
+char(5,1597).
+char(5,1598).
+char(p,1599).
+char(o,1600).
+char(p,1601).
+char(6,1602).
+char(3,1603).
+char(6,1604).
+char(9,1605).
+char(c,1606).
+char(m,1607).
+char(o,1608).
+char(o,1609).
+char(p,1610).
+char(1,1611).
+char(1,1612).
+char(4,1613).
+char(6,1614).
+char(c,1615).
+char(m,1616).
+char(1,1617).
+char(7,1618).
+char(4,1619).
+char(6,1620).
+char(m,1621).
+char(4,1622).
+char(2,1623).
+char(1,1624).
+char(7,1625).
+char(c,1626).
+char(m,1627).
+char(o,1628).
+char(p,1629).
+char(1,1630).
+char(2,1631).
+char(3,1632).
+char(2,1633).
+char(m,1634).
+char(5,1635).
+char(9,1636).
+char(7,1637).
+char(9,1638).
+char(p,1639).
+char(o,1640).
+char(p,1641).
+char(o,1642).
+char(p,1643).
+char(o,1644).
+char(p,1645).
+char(3,1646).
+char(9,1647).
+char(6,1648).
+char(1,1649).
+char(p,1650).
+char(o,1651).
+char(o,1652).
+char(p,1653).
+char(o,1654).
+char(p,1655).
+char(7,1656).
+char(3,1657).
+char(1,1658).
+char(3,1659).
+char(c,1660).
+char(p,1661).
+char(4,1662).
+char(9,1663).
+char(8,1664).
+char(9,1665).
+char(p,1666).
+char(3,1667).
+char(1,1668).
+char(9,1669).
+char(9,1670).
+char(c,1671).
+char(m,1672).
+char(o,1673).
+char(m,1674).
+char(1,1675).
+char(4,1676).
+char(3,1677).
+char(c,1678).
+char(c,1679).
+char(p,1680).
+char(o,1681).
+char(4,1682).
+char(0,1683).
+char(6,1684).
+char(5,1685).
+char(p,1686).
+char(3,1687).
+char(8,1688).
+char(4,1689).
+char(3,1690).
+char(c,1691).
+char(c,1692).
+char(c,1693).
+char(c,1694).
+char(p,1695).
+char(1,1696).
+char(2,1697).
+char(4,1698).
+char(6,1699).
+char(m,1700).
+char(o,1701).
+char(p,1702).
+char(7,1703).
+char(7,1704).
+char(2,1705).
+char(3,1706).
+char(m,1707).
+char(6,1708).
+char(2,1709).
+char(8,1710).
+char(3,1711).
+char(p,1712).
+char(1,1713).
+char(5,1714).
+char(2,1715).
+char(6,1716).
+char(c,1717).
+char(p,1718).
+char(9,1719).
+char(5,1720).
+char(8,1721).
+char(4,1722).
+char(p,1723).
+char(o,1724).
+char(o,1725).
+char(4,1726).
+char(8,1727).
+char(1,1728).
+char(7,1729).
+char(c,1730).
+char(p,1731).
+char(5,1732).
+char(4,1733).
+char(2,1734).
+char(1,1735).
+char(c,1736).
+char(m,1737).
+char(6,1738).
+char(1,1739).
+char(2,1740).
+char(2,1741).
+char(m,1742).
+char(6,1743).
+char(6,1744).
+char(9,1745).
+char(2,1746).
+char(m,1747).
+char(8,1748).
+char(4,1749).
+char(9,1750).
+char(9,1751).
+char(c,1752).
+char(m,1753).
+char(o,1754).
+char(8,1755).
+char(6,1756).
+char(5,1757).
+char(9,1758).
+char(p,1759).
+char(4,1760).
+char(9,1761).
+char(0,1762).
+char(3,1763).
+char(p,1764).
+char(o,1765).
+char(9,1766).
+char(0,1767).
+char(2,1768).
+char(7,1769).
+char(c,1770).
+char(c,1771).
+char(c,1772).
+char(c,1773).
+char(c,1774).
+char(m,1775).
+char(7,1776).
+char(7,1777).
+char(8,1778).
+char(c,1779).
+char(c,1780).
+char(m,1781).
+char(7,1782).
+char(8,1783).
+char(9,1784).
+char(3,1785).
+char(c,1786).
+char(c,1787).
+char(c,1788).
+char(m,1789).
+char(9,1790).
+char(9,1791).
+char(4,1792).
+char(6,1793).
+char(p,1794).
+char(o,1795).
+char(o,1796).
+char(p,1797).
+char(6,1798).
+char(7,1799).
+char(8,1800).
+char(8,1801).
+char(c,1802).
+char(c,1803).
+char(c,1804).
+char(c,1805).
+char(c,1806).
+char(c,1807).
+char(c,1808).
+char(c,1809).
+char(c,1810).
+char(m,1811).
+char(8,1812).
+char(0,1813).
+char(6,1814).
+char(6,1815).
+char(c,1816).
+char(p,1817).
+char(8,1818).
+char(7,1819).
+char(8,1820).
+char(3,1821).
+char(m,1822).
+char(o,1823).
+char(p,1824).
+char(o,1825).
+char(p,1826).
+char(o,1827).
+char(o,1828).
+char(7,1829).
+char(6,1830).
+char(6,1831).
+char(5,1832).
+char(c,1833).
+char(m,1834).
+char(o,1835).
+char(p,1836).
+char(o,1837).
+char(p,1838).
+char(o,1839).
+char(m,1840).
+char(2,1841).
+char(6,1842).
+char(1,1843).
+char(8,1844).
+char(c,1845).
+char(c,1846).
+char(c,1847).
+char(c,1848).
+char(c,1849).
+char(c,1850).
+char(m,1851).
+char(1,1852).
+char(6,1853).
+char(1,1854).
+char(8,1855).
+char(c,1856).
+char(p,1857).
+char(o,1858).
+char(m,1859).
+char(7,1860).
+char(2,1861).
+char(2,1862).
+char(8,1863).
+char(c,1864).
+char(c,1865).
+char(m,1866).
+char(o,1867).
+char(p,1868).
+char(o,1869).
+char(o,1870).
+char(8,1871).
+char(7,1872).
+char(2,1873).
+char(5,1874).
+char(m,1875).
+char(o,1876).
+char(p,1877).
+char(6,1878).
+char(5,1879).
+char(2,1880).
+char(3,1881).
+char(p,1882).
+char(o,1883).
+char(p,1884).
+char(8,1885).
+char(9,1886).
+char(1,1887).
+char(4,1888).
+char(m,1889).
+char(o,1890).
+char(3,1891).
+char(0,1892).
+char(m,1893).
+char(o,1894).
+char(p,1895).
+char(3,1896).
+char(6,1897).
+char(2,1898).
+char(4,1899).
+char(p,1900).
+char(o,1901).
+char(m,1902).
+char(o,1903).
+char(o,1904).
+char(p,1905).
+char(4,1906).
+char(0,1907).
+char(8,1908).
+char(4,1909).
+char(m,1910).
+char(o,1911).
+char(3,1912).
+char(6,1913).
+char(2,1914).
+char(5,1915).
+char(p,1916).
+char(o,1917).
+char(p,1918).
+char(8,1919).
+char(5,1920).
+char(6,1921).
+char(8,1922).
+char(m,1923).
+char(8,1924).
+char(1,1925).
+char(8,1926).
+char(9,1927).
+char(c,1928).
+char(p,1929).
+char(o,1930).
+char(o,1931).
+char(m,1932).
+char(o,1933).
+char(o,1934).
+char(o,1935).
+char(2,1936).
+char(8,1937).
+char(6,1938).
+char(1,1939).
+char(m,1940).
+char(8,1941).
+char(0,1942).
+char(9,1943).
+char(1,1944).
+char(p,1945).
+char(o,1946).
+char(p,1947).
+char(o,1948).
+char(m,1949).
+char(6,1950).
+char(5,1951).
+char(1,1952).
+char(p,1953).
+char(o,1954).
+char(o,1955).
+char(m,1956).
+char(9,1957).
+char(5,1958).
+char(1,1959).
+char(3,1960).
+char(m,1961).
+char(o,1962).
+char(m,1963).
+char(2,1964).
+char(7,1965).
+char(6,1966).
+char(c,1967).
+char(p,1968).
+char(o,1969).
+char(m,1970).
+char(o,1971).
+char(o,1972).
+char(p,1973).
+char(5,1974).
+char(5,1975).
+char(4,1976).
+char(1,1977).
+char(m,1978).
+char(o,1979).
+char(p,1980).
+char(6,1981).
+char(3,1982).
+char(4,1983).
+char(5,1984).
+char(p,1985).
+char(4,1986).
+char(3,1987).
+char(7,1988).
+char(9,1989).
+char(m,1990).
+char(o,1991).
+char(m,1992).
+char(2,1993).
+char(8,1994).
+char(7,1995).
+char(1,1996).
+char(c,1997).
+char(p,1998).
+char(6,1999).
+char(9,2000).
+char(1,2001).
+char(6,2002).
+char(p,2003).
+char(o,2004).
+char(m,2005).
+char(o,2006).
+char(p,2007).
+char(4,2008).
+char(0,2009).
+char(1,2010).
+char(0,2011).
+char(m,2012).
+char(o,2013).
+char(m,2014).
+char(2,2015).
+char(0,2016).
+char(5,2017).
+char(3,2018).
+char(c,2019).
+char(m,2020).
+char(o,2021).
+char(m,2022).
+char(o,2023).
+char(p,2024).
+char(o,2025).
+char(o,2026).
+char(1,2027).
+char(0,2028).
+char(8,2029).
+char(2,2030).
+char(m,2031).
+char(o,2032).
+char(p,2033).
+char(9,2034).
+char(5,2035).
+char(9,2036).
+char(3,2037).
+char(c,2038).
+char(m,2039).
+char(4,2040).
+char(9,2041).
+char(2,2042).
+char(0,2043).
+char(m,2044).
+char(8,2045).
+char(0,2046).
+char(7,2047).
+char(3,2048).
+char(c,2049).
+char(p,2050).
+char(1,2051).
+char(4,2052).
+char(8,2053).
+char(7,2054).
+char(c,2055).
+char(c,2056).
+char(c,2057).
+char(c,2058).
+char(m,2059).
+char(o,2060).
+char(o,2061).
+char(p,2062).
+char(6,2063).
+char(4,2064).
+char(6,2065).
+char(0,2066).
+char(c,2067).
+char(c,2068).
+char(c,2069).
+char(c,2070).
+char(m,2071).
+char(o,2072).
+char(o,2073).
+char(p,2074).
+char(3,2075).
+char(2,2076).
+char(4,2077).
+char(8,2078).
+char(p,2079).
+char(o,2080).
+char(p,2081).
+char(8,2082).
+char(1,2083).
+char(8,2084).
+char(1,2085).
+char(c,2086).
+char(c,2087).
+char(c,2088).
+char(c,2089).
+char(p,2090).
+char(6,2091).
+char(2,2092).
+char(4,2093).
+char(2,2094).
+char(c,2095).
+char(m,2096).
+char(9,2097).
+char(8,2098).
+char(0,2099).
+char(3,2100).
+char(m,2101).
+char(o,2102).
+char(m,2103).
+char(o,2104).
+char(p,2105).
+char(9,2106).
+char(0,2107).
+char(4,2108).
+char(1,2109).
+char(m,2110).
+char(5,2111).
+char(5,2112).
+char(8,2113).
+char(8,2114).
+char(p,2115).
+char(1,2116).
+char(7,2117).
+char(6,2118).
+char(6,2119).
+char(c,2120).
+char(c,2121).
+char(c,2122).
+char(c,2123).
+char(p,2124).
+char(o,2125).
+char(o,2126).
+char(p,2127).
+char(o,2128).
+char(p,2129).
+char(9,2130).
+char(2,2131).
+char(8,2132).
+char(9,2133).
+char(c,2134).
+char(m,2135).
+char(o,2136).
+char(m,2137).
+char(o,2138).
+char(m,2139).
+char(2,2140).
+char(8,2141).
+char(7,2142).
+char(c,2143).
+char(p,2144).
+char(o,2145).
+char(o,2146).
+char(8,2147).
+char(8,2148).
+char(7,2149).
+char(8,2150).
+char(p,2151).
+char(o,2152).
+char(o,2153).
+char(m,2154).
+char(o,2155).
+char(m,2156).
+char(2,2157).
+char(5,2158).
+char(4,2159).
+char(1,2160).
+char(p,2161).
+char(8,2162).
+char(1,2163).
+char(4,2164).
+char(2,2165).
+char(p,2166).
+char(o,2167).
+char(m,2168).
+char(2,2169).
+char(0,2170).
+char(9,2171).
+char(9,2172).
+char(c,2173).
+char(c,2174).
+char(c,2175).
+char(c,2176).
+char(c,2177).
+char(c,2178).
+char(c,2179).
+char(p,2180).
+char(6,2181).
+char(6,2182).
+char(4,2183).
+char(9,2184).
+char(c,2185).
+char(m,2186).
+char(8,2187).
+char(7,2188).
+char(9,2189).
+char(3,2190).
+char(c,2191).
+char(c,2192).
+char(p,2193).
+char(o,2194).
+char(p,2195).
+char(2,2196).
+char(4,2197).
+char(5,2198).
+char(7,2199).
+char(c,2200).
+char(m,2201).
+char(o,2202).
+char(o,2203).
+char(m,2204).
+char(o,2205).
+char(p,2206).
+char(o,2207).
+char(m,2208).
+char(o,2209).
+char(o,2210).
+char(p,2211).
+char(o,2212).
+char(5,2213).
+char(2,2214).
+char(0,2215).
+char(6,2216).
+char(c,2217).
+char(p,2218).
+char(o,2219).
+char(o,2220).
+char(o,2221).
+char(7,2222).
+char(3,2223).
+char(2,2224).
+char(0,2225).
+char(p,2226).
+char(7,2227).
+char(1,2228).
+char(3,2229).
+char(0,2230).
+char(p,2231).
+char(o,2232).
+char(2,2233).
+char(5,2234).
+char(1,2235).
+char(1,2236).
+char(c,2237).
+char(p,2238).
+char(o,2239).
+char(p,2240).
+char(o,2241).
+char(m,2242).
+char(o,2243).
+char(p,2244).
+char(o,2245).
+char(p,2246).
+char(o,2247).
+char(p,2248).
+char(o,2249).
+char(8,2250).
+char(9,2251).
+char(6,2252).
+char(8,2253).
+char(p,2254).
+char(o,2255).
+char(p,2256).
+char(o,2257).
+char(p,2258).
+char(5,2259).
+char(2,2260).
+char(0,2261).
+char(c,2262).
+char(c,2263).
+char(c,2264).
+char(p,2265).
+char(o,2266).
+char(p,2267).
+char(9,2268).
+char(0,2269).
+char(8,2270).
+char(6,2271).
+char(c,2272).
+char(c,2273).
+char(c,2274).
+char(p,2275).
+char(1,2276).
+char(2,2277).
+char(6,2278).
+char(9,2279).
+char(c,2280).
+char(c,2281).
+char(c,2282).
+char(c,2283).
+char(c,2284).
+char(c,2285).
+char(c,2286).
+char(p,2287).
+char(o,2288).
+char(o,2289).
+char(8,2290).
+char(8,2291).
+char(4,2292).
+char(9,2293).
+char(p,2294).
+char(o,2295).
+char(o,2296).
+char(p,2297).
+char(o,2298).
+char(m,2299).
+char(2,2300).
+char(5,2301).
+char(5,2302).
+char(0,2303).
+char(c,2304).
+char(c,2305).
+char(p,2306).
+char(7,2307).
+char(0,2308).
+char(9,2309).
+char(5,2310).
+char(p,2311).
+char(1,2312).
+char(0,2313).
+char(4,2314).
+char(1,2315).
+char(c,2316).
+char(c,2317).
+char(m,2318).
+char(o,2319).
+char(4,2320).
+char(2,2321).
+char(1,2322).
+char(4,2323).
+char(c,2324).
+char(c,2325).
+char(p,2326).
+char(o,2327).
+char(p,2328).
+char(o,2329).
+char(m,2330).
+char(o,2331).
+char(p,2332).
+char(o,2333).
+char(2,2334).
+char(6,2335).
+char(9,2336).
+char(7,2337).
+char(p,2338).
+char(5,2339).
+char(4,2340).
+char(3,2341).
+char(4,2342).
+char(c,2343).
+char(c,2344).
+char(p,2345).
+char(8,2346).
+char(7,2347).
+char(1,2348).
+char(5,2349).
+char(p,2350).
+char(8,2351).
+char(6,2352).
+char(6,2353).
+char(6,2354).
+char(p,2355).
+char(3,2356).
+char(4,2357).
+char(4,2358).
+char(6,2359).
+char(p,2360).
+char(5,2361).
+char(2,2362).
+char(1,2363).
+char(4,2364).
+char(c,2365).
+char(m,2366).
+char(8,2367).
+char(2,2368).
+char(4,2369).
+char(0,2370).
+char(p,2371).
+char(6,2372).
+char(7,2373).
+char(6,2374).
+char(2,2375).
+char(c,2376).
+char(p,2377).
+char(o,2378).
+char(m,2379).
+char(o,2380).
+char(m,2381).
+char(o,2382).
+char(p,2383).
+char(2,2384).
+char(3,2385).
+char(8,2386).
+char(4,2387).
+char(m,2388).
+char(7,2389).
+char(5,2390).
+char(4,2391).
+char(8,2392).
+char(p,2393).
+char(o,2394).
+char(p,2395).
+char(o,2396).
+char(o,2397).
+char(p,2398).
+char(8,2399).
+char(0,2400).
+char(5,2401).
+char(m,2402).
+char(7,2403).
+char(8,2404).
+char(6,2405).
+char(2,2406).
+char(p,2407).
+char(9,2408).
+char(0,2409).
+char(1,2410).
+char(5,2411).
+char(c,2412).
+char(m,2413).
+char(o,2414).
+char(p,2415).
+char(o,2416).
+char(p,2417).
+char(8,2418).
+char(0,2419).
+char(3,2420).
+char(4,2421).
+char(c,2422).
+char(c,2423).
+char(m,2424).
+char(o,2425).
+char(o,2426).
+char(1,2427).
+char(2,2428).
+char(3,2429).
+char(0,2430).
+char(c,2431).
+char(p,2432).
+char(o,2433).
+char(p,2434).
+char(4,2435).
+char(4,2436).
+char(1,2437).
+char(1,2438).
+char(c,2439).
+char(c,2440).
+char(c,2441).
+char(p,2442).
+char(2,2443).
+char(2,2444).
+char(4,2445).
+char(9,2446).
+char(c,2447).
+char(p,2448).
+char(6,2449).
+char(2,2450).
+char(9,2451).
+char(7,2452).
+char(c,2453).
+char(p,2454).
+char(o,2455).
+char(o,2456).
+char(p,2457).
+char(2,2458).
+char(3,2459).
+char(5,2460).
+char(p,2461).
+char(2,2462).
+char(1,2463).
+char(3,2464).
+char(1,2465).
+char(c,2466).
+char(c,2467).
+char(c,2468).
+char(c,2469).
+char(c,2470).
+char(c,2471).
+char(c,2472).
+char(c,2473).
+char(c,2474).
+char(m,2475).
+char(o,2476).
+char(m,2477).
+char(o,2478).
+char(p,2479).
+char(9,2480).
+char(4,2481).
+char(7,2482).
+char(1,2483).
+char(p,2484).
+char(o,2485).
+char(p,2486).
+char(o,2487).
+char(o,2488).
+char(7,2489).
+char(0,2490).
+char(4,2491).
+char(0,2492).
+char(c,2493).
+char(p,2494).
+char(o,2495).
+char(p,2496).
+char(o,2497).
+char(m,2498).
+char(8,2499).
+char(8,2500).
+char(8,2501).
+char(6,2502).
+char(c,2503).
+char(m,2504).
+char(5,2505).
+char(8,2506).
+char(8,2507).
+char(4,2508).
+char(p,2509).
+char(2,2510).
+char(8,2511).
+char(9,2512).
+char(6,2513).
+char(c,2514).
+char(c,2515).
+char(m,2516).
+char(2,2517).
+char(7,2518).
+char(3,2519).
+char(2,2520).
+char(c,2521).
+char(p,2522).
+char(o,2523).
+char(m,2524).
+char(2,2525).
+char(1,2526).
+char(7,2527).
+char(2,2528).
+char(c,2529).
+char(m,2530).
+char(1,2531).
+char(9,2532).
+char(6,2533).
+char(2,2534).
+char(p,2535).
+char(6,2536).
+char(9,2537).
+char(8,2538).
+char(m,2539).
+char(9,2540).
+char(3,2541).
+char(4,2542).
+char(1,2543).
+char(p,2544).
+char(5,2545).
+char(0,2546).
+char(3,2547).
+char(0,2548).
+char(c,2549).
+char(c,2550).
+char(c,2551).
+char(m,2552).
+char(9,2553).
+char(7,2554).
+char(9,2555).
+char(1,2556).
+char(p,2557).
+char(4,2558).
+char(8,2559).
+char(8,2560).
+char(8,2561).
+char(p,2562).
+char(o,2563).
+char(o,2564).
+char(m,2565).
+char(8,2566).
+char(7,2567).
+char(9,2568).
+char(4,2569).
+char(m,2570).
+char(4,2571).
+char(8,2572).
+char(0,2573).
+char(c,2574).
+char(c,2575).
+char(p,2576).
+char(o,2577).
+char(p,2578).
+char(o,2579).
+char(4,2580).
+char(6,2581).
+char(3,2582).
+char(3,2583).
+char(c,2584).
+char(p,2585).
+char(o,2586).
+char(p,2587).
+char(6,2588).
+char(8,2589).
+char(9,2590).
+char(9,2591).
+char(c,2592).
+char(m,2593).
+char(o,2594).
+char(m,2595).
+char(5,2596).
+char(2,2597).
+char(7,2598).
+char(8,2599).
+char(m,2600).
+char(o,2601).
+char(p,2602).
+char(3,2603).
+char(4,2604).
+char(0,2605).
+char(m,2606).
+char(o,2607).
+char(9,2608).
+char(2,2609).
+char(9,2610).
+char(5,2611).
+char(c,2612).
+char(m,2613).
+char(o,2614).
+char(6,2615).
+char(4,2616).
+char(4,2617).
+char(c,2618).
+char(c,2619).
+char(c,2620).
+char(c,2621).
+char(c,2622).
+char(m,2623).
+char(9,2624).
+char(9,2625).
+char(9,2626).
+char(3,2627).
+char(c,2628).
+char(c,2629).
+char(p,2630).
+char(8,2631).
+char(1,2632).
+char(9,2633).
+char(9,2634).
+char(c,2635).
+char(p,2636).
+char(2,2637).
+char(0,2638).
+char(4,2639).
+char(2,2640).
+char(c,2641).
+char(c,2642).
+char(p,2643).
+char(o,2644).
+char(p,2645).
+char(o,2646).
+char(m,2647).
+char(o,2648).
+char(m,2649).
+char(9,2650).
+char(0,2651).
+char(0,2652).
+char(p,2653).
+char(2,2654).
+char(0,2655).
+char(8,2656).
+char(3,2657).
+char(c,2658).
+char(c,2659).
+char(p,2660).
+char(3,2661).
+char(2,2662).
+char(2,2663).
+char(8,2664).
+char(c,2665).
+char(m,2666).
+char(2,2667).
+char(1,2668).
+char(4,2669).
+char(c,2670).
+char(c,2671).
+char(c,2672).
+char(c,2673).
+char(m,2674).
+char(o,2675).
+char(o,2676).
+char(p,2677).
+char(o,2678).
+char(m,2679).
+char(o,2680).
+char(m,2681).
+char(8,2682).
+char(1,2683).
+char(7,2684).
+char(2,2685).
+char(c,2686).
+char(c,2687).
+char(c,2688).
+char(c,2689).
+char(m,2690).
+char(o,2691).
+char(p,2692).
+char(9,2693).
+char(8,2694).
+char(6,2695).
+char(3,2696).
+char(c,2697).
+char(m,2698).
+char(o,2699).
+char(1,2700).
+char(3,2701).
+char(1,2702).
+char(6,2703).
+char(p,2704).
+char(o,2705).
+char(o,2706).
+char(o,2707).
+char(m,2708).
+char(o,2709).
+char(p,2710).
+char(o,2711).
+char(m,2712).
+char(o,2713).
+char(p,2714).
+char(4,2715).
+char(3,2716).
+char(3,2717).
+char(8,2718).
+char(c,2719).
+char(c,2720).
+char(p,2721).
+char(o,2722).
+char(m,2723).
+char(o,2724).
+char(o,2725).
+char(p,2726).
+char(o,2727).
+char(m,2728).
+char(o,2729).
+char(o,2730).
+char(m,2731).
+char(3,2732).
+char(1,2733).
+char(2,2734).
+char(8,2735).
+char(m,2736).
+char(7,2737).
+char(7,2738).
+char(0,2739).
+char(5,2740).
+char(c,2741).
+char(c,2742).
+char(m,2743).
+char(o,2744).
+char(m,2745).
+char(o,2746).
+char(m,2747).
+char(o,2748).
+char(m,2749).
+char(o,2750).
+char(m,2751).
+char(o,2752).
+char(9,2753).
+char(3,2754).
+char(4,2755).
+char(p,2756).
+char(2,2757).
+char(3,2758).
+char(7,2759).
+char(4,2760).
+char(c,2761).
+char(m,2762).
+char(o,2763).
+char(m,2764).
+char(6,2765).
+char(8,2766).
+char(7,2767).
+char(2,2768).
+char(m,2769).
+char(9,2770).
+char(7,2771).
+char(2,2772).
+char(p,2773).
+char(o,2774).
+char(m,2775).
+char(o,2776).
+char(m,2777).
+char(9,2778).
+char(6,2779).
+char(3,2780).
+char(c,2781).
+char(c,2782).
+char(c,2783).
+char(c,2784).
+char(p,2785).
+char(o,2786).
+char(m,2787).
+char(3,2788).
+char(9,2789).
+char(9,2790).
+char(3,2791).
+char(c,2792).
+char(c,2793).
+char(m,2794).
+char(o,2795).
+char(o,2796).
+char(p,2797).
+char(o,2798).
+char(m,2799).
+char(2,2800).
+char(3,2801).
+char(8,2802).
+char(0,2803).
+char(m,2804).
+char(4,2805).
+char(9,2806).
+char(3,2807).
+char(8,2808).
+char(p,2809).
+char(o,2810).
+char(p,2811).
+char(3,2812).
+char(1,2813).
+char(8,2814).
+char(4,2815).
+char(c,2816).
+char(m,2817).
+char(o,2818).
+char(o,2819).
+char(p,2820).
+char(2,2821).
+char(9,2822).
+char(3,2823).
+char(3,2824).
+char(m,2825).
+char(7,2826).
+char(9,2827).
+char(3,2828).
+char(8,2829).
+char(p,2830).
+char(o,2831).
+char(m,2832).
+char(5,2833).
+char(4,2834).
+char(4,2835).
+char(9,2836).
+char(p,2837).
+char(6,2838).
+char(3,2839).
+char(0,2840).
+char(4,2841).
+char(c,2842).
+char(p,2843).
+char(o,2844).
+char(m,2845).
+char(1,2846).
+char(2,2847).
+char(3,2848).
+char(9,2849).
+char(p,2850).
+char(7,2851).
+char(0,2852).
+char(8,2853).
+char(9,2854).
+char(m,2855).
+char(3,2856).
+char(3,2857).
+char(0,2858).
+char(9,2859).
+char(c,2860).
+char(p,2861).
+char(o,2862).
+char(p,2863).
+char(o,2864).
+char(m,2865).
+char(o,2866).
+char(4,2867).
+char(6,2868).
+char(7,2869).
+char(3,2870).
+char(m,2871).
+char(7,2872).
+char(7,2873).
+char(3,2874).
+char(6,2875).
+char(m,2876).
+char(5,2877).
+char(7,2878).
+char(0,2879).
+char(p,2880).
+char(7,2881).
+char(4,2882).
+char(0,2883).
+char(7,2884).
+char(c,2885).
+char(c,2886).
+char(m,2887).
+char(o,2888).
+char(m,2889).
+char(1,2890).
+char(8,2891).
+char(6,2892).
+char(2,2893).
+char(c,2894).
+char(c,2895).
+char(c,2896).
+char(p,2897).
+char(3,2898).
+char(0,2899).
+char(7,2900).
+char(1,2901).
+char(c,2902).
+char(c,2903).
+char(c,2904).
+char(p,2905).
+char(o,2906).
+char(1,2907).
+char(8,2908).
+char(1,2909).
+char(9,2910).
+char(p,2911).
+char(3,2912).
+char(2,2913).
+char(8,2914).
+char(0,2915).
+char(c,2916).
+char(c,2917).
+char(m,2918).
+char(4,2919).
+char(5,2920).
+char(0,2921).
+char(1,2922).
+char(p,2923).
+char(o,2924).
+char(o,2925).
+char(p,2926).
+char(1,2927).
+char(9,2928).
+char(2,2929).
+char(1,2930).
+char(c,2931).
+char(p,2932).
+char(o,2933).
+char(o,2934).
+char(m,2935).
+char(o,2936).
+char(9,2937).
+char(4,2938).
+char(8,2939).
+char(2,2940).
+char(c,2941).
+char(p,2942).
+char(o,2943).
+char(m,2944).
+char(1,2945).
+char(8,2946).
+char(1,2947).
+char(5,2948).
+char(m,2949).
+char(o,2950).
+char(p,2951).
+char(3,2952).
+char(7,2953).
+char(0,2954).
+char(1,2955).
+char(c,2956).
+char(c,2957).
+char(m,2958).
+char(o,2959).
+char(p,2960).
+char(1,2961).
+char(3,2962).
+char(7,2963).
+char(7,2964).
+char(c,2965).
+char(m,2966).
+char(o,2967).
+char(m,2968).
+char(1,2969).
+char(3,2970).
+char(3,2971).
+char(6,2972).
+char(c,2973).
+char(p,2974).
+char(o,2975).
+char(m,2976).
+char(5,2977).
+char(1,2978).
+char(9,2979).
+char(2,2980).
+char(c,2981).
+char(m,2982).
+char(4,2983).
+char(0,2984).
+char(9,2985).
+char(8,2986).
+char(p,2987).
+char(o,2988).
+char(p,2989).
+char(6,2990).
+char(9,2991).
+char(8,2992).
+char(4,2993).
+char(m,2994).
+char(1,2995).
+char(8,2996).
+char(9,2997).
+char(4,2998).
+char(p,2999).
+char(o,3000).
+char(m,3001).
+char(6,3002).
+char(2,3003).
+char(2,3004).
+char(6,3005).
+char(c,3006).
+char(c,3007).
+char(p,3008).
+char(3,3009).
+char(4,3010).
+char(6,3011).
+char(1,3012).
+char(c,3013).
+char(c,3014).
+char(p,3015).
+char(o,3016).
+char(m,3017).
+char(o,3018).
+char(m,3019).
+char(1,3020).
+char(0,3021).
+char(3,3022).
+char(6,3023).
+char(c,3024).
+char(p,3025).
+char(o,3026).
+char(7,3027).
+char(9,3028).
+char(1,3029).
+char(c,3030).
+char(c,3031).
+char(m,3032).
+char(o,3033).
+char(o,3034).
+char(p,3035).
+char(8,3036).
+char(6,3037).
+char(9,3038).
+char(5,3039).
+char(c,3040).
+char(m,3041).
+char(o,3042).
+char(m,3043).
+char(5,3044).
+char(2,3045).
+char(8,3046).
+char(1,3047).
+char(p,3048).
+char(o,3049).
+char(m,3050).
+char(o,3051).
+char(p,3052).
+char(o,3053).
+char(m,3054).
+char(o,3055).
+char(p,3056).
+char(6,3057).
+char(7,3058).
+char(8,3059).
+char(1,3060).
+char(m,3061).
+char(o,3062).
+char(p,3063).
+char(o,3064).
+char(2,3065).
+char(4,3066).
+char(9,3067).
+char(1,3068).
+char(c,3069).
+char(p,3070).
+char(o,3071).
+char(p,3072).
+char(o,3073).
+char(4,3074).
+char(9,3075).
+char(3,3076).
+char(6,3077).
+char(p,3078).
+char(7,3079).
+char(8,3080).
+char(7,3081).
+char(2,3082).
+char(p,3083).
+char(3,3084).
+char(5,3085).
+char(7,3086).
+char(9,3087).
+char(m,3088).
+char(o,3089).
+char(m,3090).
+char(o,3091).
+char(o,3092).
+char(p,3093).
+char(o,3094).
+char(m,3095).
+char(o,3096).
+char(p,3097).
+char(1,3098).
+char(9,3099).
+char(3,3100).
+char(8,3101).
+char(c,3102).
+char(c,3103).
+char(m,3104).
+char(3,3105).
+char(3,3106).
+char(3,3107).
+char(7,3108).
+char(m,3109).
+char(5,3110).
+char(9,3111).
+char(5,3112).
+char(9,3113).
+char(c,3114).
+char(p,3115).
+char(2,3116).
+char(1,3117).
+char(3,3118).
+char(7,3119).
+char(c,3120).
+char(m,3121).
+char(o,3122).
+char(m,3123).
+char(7,3124).
+char(1,3125).
+char(0,3126).
+char(1,3127).
+char(c,3128).
+char(c,3129).
+char(m,3130).
+char(o,3131).
+char(p,3132).
+char(2,3133).
+char(1,3134).
+char(0,3135).
+char(6,3136).
+char(c,3137).
+char(m,3138).
+char(o,3139).
+char(9,3140).
+char(2,3141).
+char(4,3142).
+char(0,3143).
+char(c,3144).
+char(m,3145).
+char(2,3146).
+char(9,3147).
+char(5,3148).
+char(2,3149).
+char(c,3150).
+char(m,3151).
+char(7,3152).
+char(1,3153).
+char(0,3154).
+char(1,3155).
+char(p,3156).
+char(9,3157).
+char(3,3158).
+char(7,3159).
+char(1,3160).
+char(c,3161).
+char(c,3162).
+char(p,3163).
+char(2,3164).
+char(7,3165).
+char(8,3166).
+char(6,3167).
+char(c,3168).
+char(m,3169).
+char(1,3170).
+char(0,3171).
+char(9,3172).
+char(1,3173).
+char(c,3174).
+char(p,3175).
+char(8,3176).
+char(7,3177).
+char(3,3178).
+char(3,3179).
+char(m,3180).
+char(1,3181).
+char(5,3182).
+char(0,3183).
+char(1,3184).
+char(c,3185).
+char(m,3186).
+char(6,3187).
+char(4,3188).
+char(2,3189).
+char(1,3190).
+char(c,3191).
+char(c,3192).
+char(p,3193).
+char(o,3194).
+char(m,3195).
+char(o,3196).
+char(m,3197).
+char(o,3198).
+char(p,3199).
+char(o,3200).
+char(2,3201).
+char(5,3202).
+char(1,3203).
+char(0,3204).
+char(c,3205).
+char(m,3206).
+char(1,3207).
+char(3,3208).
+char(0,3209).
+char(9,3210).
+char(c,3211).
+char(c,3212).
+char(c,3213).
+char(c,3214).
+char(c,3215).
+char(p,3216).
+char(4,3217).
+char(2,3218).
+char(8,3219).
+char(6,3220).
+char(p,3221).
+char(4,3222).
+char(9,3223).
+char(3,3224).
+char(7,3225).
+char(c,3226).
+char(p,3227).
+char(o,3228).
+char(p,3229).
+char(5,3230).
+char(5,3231).
+char(0,3232).
+char(0,3233).
+char(p,3234).
+char(7,3235).
+char(4,3236).
+char(0,3237).
+char(8,3238).
+char(p,3239).
+char(o,3240).
+char(m,3241).
+char(3,3242).
+char(7,3243).
+char(4,3244).
+char(7,3245).
+char(c,3246).
+char(c,3247).
+char(c,3248).
+char(c,3249).
+char(c,3250).
+char(c,3251).
+char(c,3252).
+char(p,3253).
+char(o,3254).
+char(m,3255).
+char(o,3256).
+char(p,3257).
+char(o,3258).
+char(p,3259).
+char(o,3260).
+char(m,3261).
+char(1,3262).
+char(0,3263).
+char(4,3264).
+char(6,3265).
+char(m,3266).
+char(3,3267).
+char(3,3268).
+char(0,3269).
+char(8,3270).
+char(p,3271).
+char(o,3272).
+char(m,3273).
+char(5,3274).
+char(3,3275).
+char(9,3276).
+char(6,3277).
+char(m,3278).
+char(3,3279).
+char(5,3280).
+char(2,3281).
+char(2,3282).
+char(p,3283).
+char(9,3284).
+char(8,3285).
+char(5,3286).
+char(1,3287).
+char(c,3288).
+char(c,3289).
+char(m,3290).
+char(o,3291).
+char(m,3292).
+char(o,3293).
+char(p,3294).
+char(5,3295).
+char(0,3296).
+char(3,3297).
+char(1,3298).
+char(c,3299).
+char(p,3300).
+char(o,3301).
+char(o,3302).
+char(o,3303).
+char(m,3304).
+char(5,3305).
+char(8,3306).
+char(9,3307).
+char(6,3308).
+char(m,3309).
+char(o,3310).
+char(9,3311).
+char(1,3312).
+char(6,3313).
+char(7,3314).
+char(p,3315).
+char(o,3316).
+char(m,3317).
+char(3,3318).
+char(9,3319).
+char(6,3320).
+char(0,3321).
+char(p,3322).
+char(8,3323).
+char(4,3324).
+char(4,3325).
+char(5,3326).
+char(p,3327).
+char(8,3328).
+char(5,3329).
+char(6,3330).
+char(4,3331).
+char(c,3332).
+char(p,3333).
+char(o,3334).
+char(2,3335).
+char(6,3336).
+char(8,3337).
+char(2,3338).
+char(m,3339).
+char(o,3340).
+char(o,3341).
+char(5,3342).
+char(5,3343).
+char(9,3344).
+char(9,3345).
+char(c,3346).
+char(m,3347).
+char(2,3348).
+char(2,3349).
+char(8,3350).
+char(8,3351).
+char(p,3352).
+char(3,3353).
+char(5,3354).
+char(1,3355).
+char(0,3356).
+char(p,3357).
+char(9,3358).
+char(7,3359).
+char(0,3360).
+char(c,3361).
+char(p,3362).
+char(o,3363).
+char(m,3364).
+char(1,3365).
+char(4,3366).
+char(8,3367).
+char(4,3368).
+char(p,3369).
+char(o,3370).
+char(m,3371).
+char(2,3372).
+char(4,3373).
+char(8,3374).
+char(p,3375).
+char(o,3376).
+char(m,3377).
+char(o,3378).
+char(p,3379).
+char(9,3380).
+char(2,3381).
+char(1,3382).
+char(6,3383).
+char(m,3384).
+char(3,3385).
+char(8,3386).
+char(6,3387).
+char(0,3388).
+char(c,3389).
+char(c,3390).
+char(c,3391).
+char(c,3392).
+char(c,3393).
+char(c,3394).
+char(m,3395).
+char(6,3396).
+char(1,3397).
+char(2,3398).
+char(0,3399).
+char(p,3400).
+char(o,3401).
+char(m,3402).
+char(3,3403).
+char(3,3404).
+char(5,3405).
+char(2,3406).
+char(p,3407).
+char(o,3408).
+char(o,3409).
+char(p,3410).
+char(o,3411).
+char(m,3412).
+char(o,3413).
+char(6,3414).
+char(6,3415).
+char(0,3416).
+char(6,3417).
+char(m,3418).
+char(2,3419).
+char(0,3420).
+char(0,3421).
+char(8,3422).
+char(c,3423).
+char(c,3424).
+char(c,3425).
+char(p,3426).
+char(o,3427).
+char(p,3428).
+char(3,3429).
+char(3,3430).
+char(9,3431).
+char(2,3432).
+char(m,3433).
+char(o,3434).
+char(9,3435).
+char(6,3436).
+char(9,3437).
+char(8,3438).
+char(c,3439).
+char(c,3440).
+char(c,3441).
+char(m,3442).
+char(o,3443).
+char(m,3444).
+char(1,3445).
+char(0,3446).
+char(c,3447).
+char(p,3448).
+char(o,3449).
+char(3,3450).
+char(8,3451).
+char(8,3452).
+char(5,3453).
+char(m,3454).
+char(3,3455).
+char(0,3456).
+char(2,3457).
+char(2,3458).
+char(c,3459).
+char(p,3460).
+char(o,3461).
+char(p,3462).
+char(o,3463).
+char(p,3464).
+char(o,3465).
+char(p,3466).
+char(2,3467).
+char(1,3468).
+char(9,3469).
+char(0,3470).
+char(c,3471).
+char(p,3472).
+char(7,3473).
+char(6,3474).
+char(6,3475).
+char(8,3476).
+char(m,3477).
+char(9,3478).
+char(3,3479).
+char(6,3480).
+char(1,3481).
+char(m,3482).
+char(o,3483).
+char(p,3484).
+char(o,3485).
+char(m,3486).
+char(5,3487).
+char(0,3488).
+char(7,3489).
+char(6,3490).
+char(p,3491).
+char(o,3492).
+char(1,3493).
+char(0,3494).
+char(9,3495).
+char(3,3496).
+char(c,3497).
+char(p,3498).
+char(4,3499).
+char(0,3500).
+char(4,3501).
+char(4,3502).
+char(m,3503).
+char(o,3504).
+char(p,3505).
+char(o,3506).
+char(m,3507).
+char(5,3508).
+char(1,3509).
+char(6,3510).
+char(m,3511).
+char(o,3512).
+char(p,3513).
+char(o,3514).
+char(p,3515).
+char(5,3516).
+char(0,3517).
+char(4,3518).
+char(2,3519).
+char(m,3520).
+char(4,3521).
+char(3,3522).
+char(0,3523).
+char(3,3524).
+char(c,3525).
+char(c,3526).
+char(p,3527).
+char(o,3528).
+char(m,3529).
+char(o,3530).
+char(o,3531).
+char(o,3532).
+char(6,3533).
+char(0,3534).
+char(8,3535).
+char(0,3536).
+char(c,3537).
+char(c,3538).
+char(c,3539).
+char(c,3540).
+char(c,3541).
+char(p,3542).
+char(8,3543).
+char(2,3544).
+char(9,3545).
+char(2,3546).
+char(c,3547).
+char(m,3548).
+char(o,3549).
+char(m,3550).
+char(o,3551).
+char(m,3552).
+char(o,3553).
+char(o,3554).
+char(p,3555).
+char(2,3556).
+char(3,3557).
+char(7,3558).
+char(0,3559).
+char(c,3560).
+char(c,3561).
+char(p,3562).
+char(3,3563).
+char(3,3564).
+char(5,3565).
+char(8,3566).
+char(m,3567).
+char(6,3568).
+char(8,3569).
+char(5,3570).
+char(6,3571).
+char(c,3572).
+char(c,3573).
+char(p,3574).
+char(o,3575).
+char(p,3576).
+char(7,3577).
+char(8,3578).
+char(p,3579).
+char(8,3580).
+char(5,3581).
+char(1,3582).
+char(p,3583).
+char(o,3584).
+char(p,3585).
+char(o,3586).
+char(m,3587).
+char(2,3588).
+char(3,3589).
+char(5,3590).
+char(0,3591).
+char(m,3592).
+char(o,3593).
+char(m,3594).
+char(3,3595).
+char(9,3596).
+char(9,3597).
+char(c,3598).
+char(p,3599).
+char(1,3600).
+char(5,3601).
+char(7,3602).
+char(4,3603).
+char(c,3604).
+char(m,3605).
+char(o,3606).
+char(m,3607).
+char(3,3608).
+char(6,3609).
+char(5,3610).
+char(8,3611).
+char(c,3612).
+char(c,3613).
+char(c,3614).
+char(c,3615).
+char(p,3616).
+char(o,3617).
+char(o,3618).
+char(p,3619).
+char(1,3620).
+char(5,3621).
+char(9,3622).
+char(p,3623).
+char(2,3624).
+char(8,3625).
+char(1,3626).
+char(3,3627).
+char(m,3628).
+char(1,3629).
+char(2,3630).
+char(6,3631).
+char(7,3632).
+char(m,3633).
+char(o,3634).
+char(m,3635).
+char(1,3636).
+char(5,3637).
+char(2,3638).
+char(1,3639).
+char(p,3640).
+char(o,3641).
+char(p,3642).
+char(o,3643).
+char(p,3644).
+char(o,3645).
+char(m,3646).
+char(o,3647).
+char(m,3648).
+char(o,3649).
+char(o,3650).
+char(o,3651).
+char(m,3652).
+char(3,3653).
+char(9,3654).
+char(2,3655).
+char(3,3656).
+char(p,3657).
+char(o,3658).
+char(p,3659).
+char(4,3660).
+char(7,3661).
+char(8,3662).
+char(5,3663).
+char(c,3664).
+char(m,3665).
+char(o,3666).
+char(m,3667).
+char(5,3668).
+char(3,3669).
+char(8,3670).
+char(6,3671).
+char(c,3672).
+char(c,3673).
+char(c,3674).
+char(p,3675).
+char(o,3676).
+char(p,3677).
+char(o,3678).
+char(m,3679).
+char(o,3680).
+char(p,3681).
+char(6,3682).
+char(5,3683).
+char(1,3684).
+char(2,3685).
+char(c,3686).
+char(c,3687).
+char(c,3688).
+char(m,3689).
+char(o,3690).
+char(m,3691).
+char(2,3692).
+char(6,3693).
+char(8,3694).
+char(1,3695).
+char(p,3696).
+char(o,3697).
+char(o,3698).
+char(m,3699).
+char(8,3700).
+char(2,3701).
+char(2,3702).
+char(5,3703).
+char(p,3704).
+char(o,3705).
+char(o,3706).
+char(p,3707).
+char(o,3708).
+char(o,3709).
+char(m,3710).
+char(o,3711).
+char(m,3712).
+char(3,3713).
+char(1,3714).
+char(2,3715).
+char(1,3716).
+char(m,3717).
+char(o,3718).
+char(o,3719).
+char(p,3720).
+char(8,3721).
+char(6,3722).
+char(4,3723).
+char(m,3724).
+char(1,3725).
+char(2,3726).
+char(5,3727).
+char(2,3728).
+char(c,3729).
+char(c,3730).
+char(c,3731).
+char(m,3732).
+char(o,3733).
+char(m,3734).
+char(o,3735).
+char(o,3736).
+char(m,3737).
+char(o,3738).
+char(1,3739).
+char(8,3740).
+char(7,3741).
+char(1,3742).
+char(c,3743).
+char(c,3744).
+char(c,3745).
+char(c,3746).
+char(c,3747).
+char(p,3748).
+char(o,3749).
+char(p,3750).
+char(3,3751).
+char(6,3752).
+char(9,3753).
+char(8,3754).
+char(m,3755).
+char(1,3756).
+char(4,3757).
+char(0,3758).
+char(5,3759).
+char(c,3760).
+char(c,3761).
+char(p,3762).
+char(6,3763).
+char(6,3764).
+char(2,3765).
+char(4,3766).
+char(c,3767).
+char(c,3768).
+char(p,3769).
+char(5,3770).
+char(1,3771).
+char(3,3772).
+char(8,3773).
+char(c,3774).
+char(m,3775).
+char(o,3776).
+char(m,3777).
+char(o,3778).
+char(3,3779).
+char(0,3780).
+char(5,3781).
+char(2,3782).
+char(c,3783).
+char(m,3784).
+char(5,3785).
+char(4,3786).
+char(3,3787).
+char(0,3788).
+char(p,3789).
+char(4,3790).
+char(2,3791).
+char(2,3792).
+char(5,3793).
+char(c,3794).
+char(m,3795).
+char(o,3796).
+char(m,3797).
+char(1,3798).
+char(0,3799).
+char(7,3800).
+char(0,3801).
+char(c,3802).
+char(p,3803).
+char(6,3804).
+char(5,3805).
+char(7,3806).
+char(p,3807).
+char(o,3808).
+char(o,3809).
+char(o,3810).
+char(7,3811).
+char(9,3812).
+char(3,3813).
+char(m,3814).
+char(o,3815).
+char(8,3816).
+char(1,3817).
+char(7,3818).
+char(2,3819).
+char(c,3820).
+char(p,3821).
+char(9,3822).
+char(6,3823).
+char(2,3824).
+char(7,3825).
+char(c,3826).
+char(m,3827).
+char(o,3828).
+char(m,3829).
+char(o,3830).
+char(p,3831).
+char(o,3832).
+char(o,3833).
+char(m,3834).
+char(8,3835).
+char(9,3836).
+char(5,3837).
+char(4,3838).
+char(m,3839).
+char(6,3840).
+char(2,3841).
+char(7,3842).
+char(7,3843).
+char(m,3844).
+char(o,3845).
+char(9,3846).
+char(8,3847).
+char(1,3848).
+char(1,3849).
+char(c,3850).
+char(c,3851).
+char(c,3852).
+char(c,3853).
+char(m,3854).
+char(6,3855).
+char(3,3856).
+char(5,3857).
+char(5,3858).
+char(c,3859).
+char(p,3860).
+char(o,3861).
+char(o,3862).
+char(6,3863).
+char(9,3864).
+char(2,3865).
+char(7,3866).
+char(p,3867).
+char(o,3868).
+char(m,3869).
+char(o,3870).
+char(p,3871).
+char(o,3872).
+char(m,3873).
+char(4,3874).
+char(9,3875).
+char(8,3876).
+char(p,3877).
+char(9,3878).
+char(6,3879).
+char(0,3880).
+char(0,3881).
+char(p,3882).
+char(2,3883).
+char(7,3884).
+char(9,3885).
+char(1,3886).
+char(c,3887).
+char(c,3888).
+char(c,3889).
+char(c,3890).
+char(c,3891).
+char(c,3892).
+char(c,3893).
+char(p,3894).
+char(1,3895).
+char(7,3896).
+char(9,3897).
+char(1,3898).
+char(m,3899).
+char(1,3900).
+char(6,3901).
+char(2,3902).
+char(7,3903).
+char(m,3904).
+char(o,3905).
+char(p,3906).
+char(8,3907).
+char(8,3908).
+char(0,3909).
+char(7,3910).
+char(p,3911).
+char(9,3912).
+char(8,3913).
+char(7,3914).
+char(7,3915).
+char(p,3916).
+char(o,3917).
+char(o,3918).
+char(9,3919).
+char(3,3920).
+char(5,3921).
+char(9,3922).
+char(m,3923).
+char(7,3924).
+char(3,3925).
+char(4,3926).
+char(8,3927).
+char(p,3928).
+char(o,3929).
+char(p,3930).
+char(8,3931).
+char(8,3932).
+char(9,3933).
+char(4,3934).
+char(p,3935).
+char(o,3936).
+char(p,3937).
+char(o,3938).
+char(m,3939).
+char(8,3940).
+char(0,3941).
+char(2,3942).
+char(1,3943).
+char(c,3944).
+char(m,3945).
+char(o,3946).
+char(m,3947).
+char(5,3948).
+char(6,3949).
+char(4,3950).
+char(5,3951).
+char(c,3952).
+char(c,3953).
+char(p,3954).
+char(o,3955).
+char(5,3956).
+char(3,3957).
+char(5,3958).
+char(7,3959).
+char(c,3960).
+char(c,3961).
+char(c,3962).
+char(m,3963).
+char(2,3964).
+char(2,3965).
+char(8,3966).
+char(0,3967).
+char(c,3968).
+char(p,3969).
+char(8,3970).
+char(2,3971).
+char(9,3972).
+char(7,3973).
+char(c,3974).
+char(p,3975).
+char(o,3976).
+char(4,3977).
+char(8,3978).
+char(8,3979).
+char(3,3980).
+char(c,3981).
+char(p,3982).
+char(6,3983).
+char(4,3984).
+char(7,3985).
+char(3,3986).
+char(c,3987).
+char(c,3988).
+char(c,3989).
+char(m,3990).
+char(8,3991).
+char(8,3992).
+char(0,3993).
+char(7,3994).
+char(p,3995).
+char(4,3996).
+char(1,3997).
+char(8,3998).
+char(2,3999).
+char(p,4000).
+char(o,4001).
+char(8,4002).
+char(1,4003).
+char(6,4004).
+char(0,4005).
+char(c,4006).
+char(p,4007).
+char(o,4008).
+char(m,4009).
+char(6,4010).
+char(7,4011).
+char(9,4012).
+char(1,4013).
+char(p,4014).
+char(8,4015).
+char(0,4016).
+char(1,4017).
+char(5,4018).
+char(m,4019).
+char(o,4020).
+char(p,4021).
+char(3,4022).
+char(1,4023).
+char(2,4024).
+char(1,4025).
+char(p,4026).
+char(o,4027).
+char(p,4028).
+char(7,4029).
+char(7,4030).
+char(4,4031).
+char(1,4032).
+char(c,4033).
+char(p,4034).
+char(o,4035).
+char(p,4036).
+char(9,4037).
+char(7,4038).
+char(8,4039).
+char(3,4040).
+char(p,4041).
+char(9,4042).
+char(0,4043).
+char(8,4044).
+char(0,4045).
+char(p,4046).
+char(2,4047).
+char(7,4048).
+char(7,4049).
+char(7,4050).
+char(p,4051).
+char(o,4052).
+char(9,4053).
+char(5,4054).
+char(0,4055).
+char(1,4056).
+char(p,4057).
+char(o,4058).
+char(m,4059).
+char(5,4060).
+char(7,4061).
+char(7,4062).
+char(3,4063).
+char(m,4064).
+char(8,4065).
+char(0,4066).
+char(9,4067).
+char(6,4068).
+char(c,4069).
+char(m,4070).
+char(8,4071).
+char(1,4072).
+char(0,4073).
+char(2,4074).
+char(p,4075).
+char(o,4076).
+char(p,4077).
+char(o,4078).
+char(o,4079).
+char(p,4080).
+char(3,4081).
+char(7,4082).
+char(1,4083).
+char(0,4084).
+char(m,4085).
+char(8,4086).
+char(7,4087).
+char(8,4088).
+char(4,4089).
+char(c,4090).
+char(c,4091).
+char(p,4092).
+char(2,4093).
+char(7,4094).
+char(0,4095).
+char(p,4096).
+char(8,4097).
+char(2,4098).
+char(2,4099).
+char(9,4100).
+char(c,4101).
+char(c,4102).
+char(m,4103).
+char(o,4104).
+char(7,4105).
+char(1,4106).
+char(2,4107).
+char(4,4108).
+char(p,4109).
+char(5,4110).
+char(2,4111).
+char(6,4112).
+char(6,4113).
+char(c,4114).
+char(p,4115).
+char(o,4116).
+char(m,4117).
+char(o,4118).
+char(m,4119).
+char(o,4120).
+char(m,4121).
+char(o,4122).
+char(m,4123).
+char(o,4124).
+char(6,4125).
+char(3,4126).
+char(5,4127).
+char(c,4128).
+char(c,4129).
+char(p,4130).
+char(3,4131).
+char(6,4132).
+char(3,4133).
+char(0,4134).
+char(c,4135).
+char(m,4136).
+char(5,4137).
+char(9,4138).
+char(7,4139).
+char(c,4140).
+char(m,4141).
+char(7,4142).
+char(9,4143).
+char(7,4144).
+char(2,4145).
+char(m,4146).
+char(6,4147).
+char(2,4148).
+char(7,4149).
+char(9,4150).
+char(c,4151).
+char(p,4152).
+char(7,4153).
+char(9,4154).
+char(2,4155).
+char(2,4156).
+char(p,4157).
+char(9,4158).
+char(7,4159).
+char(8,4160).
+char(5,4161).
+char(p,4162).
+char(o,4163).
+char(m,4164).
+char(2,4165).
+char(3,4166).
+char(1,4167).
+char(7,4168).
+char(m,4169).
+char(4,4170).
+char(2,4171).
+char(5,4172).
+char(5,4173).
+char(c,4174).
+char(p,4175).
+char(o,4176).
+char(o,4177).
+char(p,4178).
+char(8,4179).
+char(4,4180).
+char(3,4181).
+char(6,4182).
+char(c,4183).
+char(c,4184).
+char(p,4185).
+char(8,4186).
+char(9,4187).
+char(2,4188).
+char(2,4189).
+char(c,4190).
+char(m,4191).
+char(o,4192).
+char(m,4193).
+char(o,4194).
+char(p,4195).
+char(6,4196).
+char(2,4197).
+char(1,4198).
+char(c,4199).
+char(m,4200).
+char(9,4201).
+char(8,4202).
+char(3,4203).
+char(0,4204).
+char(p,4205).
+char(o,4206).
+char(m,4207).
+char(2,4208).
+char(5,4209).
+char(6,4210).
+char(4,4211).
+char(p,4212).
+char(2,4213).
+char(8,4214).
+char(2,4215).
+char(m,4216).
+char(o,4217).
+char(o,4218).
+char(m,4219).
+char(o,4220).
+char(4,4221).
+char(4,4222).
+char(4,4223).
+char(6,4224).
+char(p,4225).
+char(o,4226).
+char(m,4227).
+char(7,4228).
+char(9,4229).
+char(4,4230).
+char(8,4231).
+char(c,4232).
+char(p,4233).
+char(6,4234).
+char(3,4235).
+char(3,4236).
+char(0,4237).
+char(c,4238).
+char(m,4239).
+char(o,4240).
+char(p,4241).
+char(o,4242).
+char(o,4243).
+char(p,4244).
+char(o,4245).
+char(p,4246).
+char(o,4247).
+char(p,4248).
+char(9,4249).
+char(0,4250).
+char(5,4251).
+char(5,4252).
+char(c,4253).
+char(m,4254).
+char(o,4255).
+char(m,4256).
+char(o,4257).
+char(m,4258).
+char(o,4259).
+char(4,4260).
+char(1,4261).
+char(8,4262).
+char(2,4263).
+char(c,4264).
+char(p,4265).
+char(o,4266).
+char(p,4267).
+char(o,4268).
+char(p,4269).
+char(5,4270).
+char(3,4271).
+char(4,4272).
+char(0,4273).
+char(c,4274).
+char(p,4275).
+char(o,4276).
+char(p,4277).
+char(o,4278).
+char(m,4279).
+char(o,4280).
+char(m,4281).
+char(9,4282).
+char(4,4283).
+char(6,4284).
+char(4,4285).
+char(p,4286).
+char(o,4287).
+char(m,4288).
+char(2,4289).
+char(2,4290).
+char(4,4291).
+char(2,4292).
+char(c,4293).
+char(c,4294).
+char(m,4295).
+char(8,4296).
+char(0,4297).
+char(5,4298).
+char(9,4299).
+char(c,4300).
+char(m,4301).
+char(o,4302).
+char(6,4303).
+char(2,4304).
+char(1,4305).
+char(1,4306).
+char(c,4307).
+char(c,4308).
+char(m,4309).
+char(o,4310).
+char(2,4311).
+char(6,4312).
+char(0,4313).
+char(4,4314).
+char(c,4315).
+char(m,4316).
+char(9,4317).
+char(8,4318).
+char(2,4319).
+char(5,4320).
+char(m,4321).
+char(o,4322).
+char(o,4323).
+char(o,4324).
+char(m,4325).
+char(8,4326).
+char(3,4327).
+char(9,4328).
+char(9,4329).
+char(m,4330).
+char(o,4331).
+char(m,4332).
+char(9,4333).
+char(7,4334).
+char(5,4335).
+char(3,4336).
+char(c,4337).
+char(m,4338).
+char(7,4339).
+char(7,4340).
+char(8,4341).
+char(6,4342).
+char(p,4343).
+char(9,4344).
+char(6,4345).
+char(1,4346).
+char(9,4347).
+char(c,4348).
+char(c,4349).
+char(c,4350).
+char(c,4351).
+char(c,4352).
+char(c,4353).
+char(c,4354).
+char(c,4355).
+char(c,4356).
+char(m,4357).
+char(1,4358).
+char(3,4359).
+char(5,4360).
+char(2,4361).
+char(c,4362).
+char(c,4363).
+char(c,4364).
+char(m,4365).
+char(5,4366).
+char(0,4367).
+char(4,4368).
+char(8,4369).
+char(m,4370).
+char(o,4371).
+char(o,4372).
+char(m,4373).
+char(o,4374).
+char(p,4375).
+char(o,4376).
+char(2,4377).
+char(8,4378).
+char(9,4379).
+char(9,4380).
+char(c,4381).
+char(m,4382).
+char(8,4383).
+char(0,4384).
+char(1,4385).
+char(3,4386).
+char(c,4387).
+char(m,4388).
+char(1,4389).
+char(6,4390).
+char(7,4391).
+char(3,4392).
+char(m,4393).
+char(2,4394).
+char(6,4395).
+char(6,4396).
+char(2,4397).
+char(p,4398).
+char(7,4399).
+char(0,4400).
+char(1,4401).
+char(3,4402).
+char(p,4403).
+char(o,4404).
+char(m,4405).
+char(6,4406).
+char(8,4407).
+char(0,4408).
+char(4,4409).
+char(c,4410).
+char(c,4411).
+char(m,4412).
+char(5,4413).
+char(3,4414).
+char(3,4415).
+char(8,4416).
+char(c,4417).
+char(p,4418).
+char(1,4419).
+char(5,4420).
+char(2,4421).
+char(0,4422).
+char(c,4423).
+char(c,4424).
+char(m,4425).
+char(o,4426).
+char(m,4427).
+char(2,4428).
+char(6,4429).
+char(8,4430).
+char(2,4431).
+char(p,4432).
+char(7,4433).
+char(3,4434).
+char(3,4435).
+char(3,4436).
+char(c,4437).
+char(p,4438).
+char(o,4439).
+char(8,4440).
+char(1,4441).
+char(1,4442).
+char(7,4443).
+char(p,4444).
+char(5,4445).
+char(0,4446).
+char(4,4447).
+char(c,4448).
+char(c,4449).
+char(p,4450).
+char(o,4451).
+char(m,4452).
+char(9,4453).
+char(7,4454).
+char(8,4455).
+char(7,4456).
+char(m,4457).
+char(o,4458).
+char(p,4459).
+char(3,4460).
+char(1,4461).
+char(9,4462).
+char(6,4463).
+char(p,4464).
+char(5,4465).
+char(6,4466).
+char(1,4467).
+char(4,4468).
+char(c,4469).
+char(c,4470).
+char(m,4471).
+char(2,4472).
+char(7,4473).
+char(8,4474).
+char(4,4475).
+char(c,4476).
+char(c,4477).
+char(p,4478).
+char(3,4479).
+char(5,4480).
+char(2,4481).
+char(6,4482).
+char(c,4483).
+char(c,4484).
+char(m,4485).
+char(o,4486).
+char(8,4487).
+char(6,4488).
+char(0,4489).
+char(5,4490).
+char(m,4491).
+char(o,4492).
+char(o,4493).
+char(p,4494).
+char(o,4495).
+char(m,4496).
+char(o,4497).
+char(p,4498).
+char(4,4499).
+char(5,4500).
+char(7,4501).
+char(0,4502).
+char(m,4503).
+char(5,4504).
+char(8,4505).
+char(3,4506).
+char(m,4507).
+char(1,4508).
+char(2,4509).
+char(9,4510).
+char(2,4511).
+char(p,4512).
+char(7,4513).
+char(3,4514).
+char(2,4515).
+char(3,4516).
+char(c,4517).
+char(c,4518).
+char(p,4519).
+char(o,4520).
+char(5,4521).
+char(6,4522).
+char(0,4523).
+char(p,4524).
+char(3,4525).
+char(4,4526).
+char(0,4527).
+char(4,4528).
+char(p,4529).
+char(5,4530).
+char(8,4531).
+char(2,4532).
+char(7,4533).
+char(p,4534).
+char(9,4535).
+char(7,4536).
+char(9,4537).
+char(6,4538).
+char(c,4539).
+char(m,4540).
+char(o,4541).
+char(o,4542).
+char(p,4543).
+char(o,4544).
+char(m,4545).
+char(o,4546).
+char(8,4547).
+char(6,4548).
+char(0,4549).
+char(9,4550).
+char(m,4551).
+char(o,4552).
+char(m,4553).
+char(3,4554).
+char(3,4555).
+char(4,4556).
+char(3,4557).
+char(p,4558).
+char(o,4559).
+char(o,4560).
+char(m,4561).
+char(8,4562).
+char(8,4563).
+char(3,4564).
+char(p,4565).
+char(o,4566).
+char(m,4567).
+char(o,4568).
+char(p,4569).
+char(o,4570).
+char(o,4571).
+char(m,4572).
+char(o,4573).
+char(5,4574).
+char(7,4575).
+char(6,4576).
+char(5,4577).
+char(m,4578).
+char(o,4579).
+char(m,4580).
+char(o,4581).
+char(p,4582).
+char(8,4583).
+char(9,4584).
+char(9,4585).
+char(m,4586).
+char(8,4587).
+char(1,4588).
+char(4,4589).
+char(9,4590).
+char(m,4591).
+char(9,4592).
+char(6,4593).
+char(3,4594).
+char(6,4595).
+char(c,4596).
+char(c,4597).
+char(c,4598).
+char(c,4599).
+char(c,4600).
+char(m,4601).
+char(o,4602).
+char(2,4603).
+char(8,4604).
+char(7,4605).
+char(9,4606).
+char(c,4607).
+char(p,4608).
+char(o,4609).
+char(p,4610).
+char(o,4611).
+char(m,4612).
+char(4,4613).
+char(4,4614).
+char(9,4615).
+char(1,4616).
+char(p,4617).
+char(4,4618).
+char(2,4619).
+char(5,4620).
+char(0,4621).
+char(m,4622).
+char(o,4623).
+char(p,4624).
+char(o,4625).
+char(o,4626).
+char(o,4627).
+char(6,4628).
+char(0,4629).
+char(0,4630).
+char(9,4631).
+char(c,4632).
+char(m,4633).
+char(1,4634).
+char(0,4635).
+char(1,4636).
+char(c,4637).
+char(m,4638).
+char(9,4639).
+char(7,4640).
+char(4,4641).
+char(2,4642).
+char(m,4643).
+char(7,4644).
+char(9,4645).
+char(6,4646).
+char(4,4647).
+char(c,4648).
+char(p,4649).
+char(5,4650).
+char(8,4651).
+char(6,4652).
+char(6,4653).
+char(p,4654).
+char(o,4655).
+char(m,4656).
+char(o,4657).
+char(4,4658).
+char(5,4659).
+char(8,4660).
+char(9,4661).
+char(c,4662).
+char(c,4663).
+char(p,4664).
+char(o,4665).
+char(p,4666).
+char(7,4667).
+char(3,4668).
+char(8,4669).
+char(5,4670).
+char(m,4671).
+char(o,4672).
+char(m,4673).
+char(9,4674).
+char(7,4675).
+char(4,4676).
+char(7,4677).
+char(c,4678).
+char(c,4679).
+char(c,4680).
+char(m,4681).
+char(o,4682).
+char(m,4683).
+char(2,4684).
+char(2,4685).
+char(2,4686).
+char(m,4687).
+char(o,4688).
+char(o,4689).
+char(o,4690).
+char(m,4691).
+char(5,4692).
+char(7,4693).
+char(2,4694).
+char(4,4695).
+char(c,4696).
+char(c,4697).
+char(c,4698).
+char(c,4699).
+char(c,4700).
+char(c,4701).
+char(p,4702).
+char(o,4703).
+char(p,4704).
+char(1,4705).
+char(1,4706).
+char(7,4707).
+char(9,4708).
+char(c,4709).
+char(c,4710).
+char(c,4711).
+char(m,4712).
+char(o,4713).
+char(9,4714).
+char(0,4715).
+char(4,4716).
+char(7,4717).
+char(p,4718).
+char(o,4719).
+char(6,4720).
+char(1,4721).
+char(7,4722).
+char(7,4723).
+char(p,4724).
+char(4,4725).
+char(0,4726).
+char(6,4727).
+char(6,4728).
+char(c,4729).
+char(c,4730).
+char(c,4731).
+char(m,4732).
+char(o,4733).
+char(m,4734).
+char(o,4735).
+char(o,4736).
+char(m,4737).
+char(2,4738).
+char(4,4739).
+char(1,4740).
+char(8,4741).
+char(p,4742).
+char(o,4743).
+char(o,4744).
+char(o,4745).
+char(m,4746).
+char(9,4747).
+char(0,4748).
+char(8,4749).
+char(9,4750).
+char(m,4751).
+char(1,4752).
+char(7,4753).
+char(0,4754).
+char(c,4755).
+char(p,4756).
+char(o,4757).
+char(m,4758).
+char(o,4759).
+char(m,4760).
+char(o,4761).
+char(m,4762).
+char(6,4763).
+char(2,4764).
+char(8,4765).
+char(8,4766).
+char(p,4767).
+char(6,4768).
+char(0,4769).
+char(4,4770).
+char(c,4771).
+char(c,4772).
+char(c,4773).
+char(p,4774).
+char(9,4775).
+char(8,4776).
+char(4,4777).
+char(2,4778).
+char(m,4779).
+char(6,4780).
+char(2,4781).
+char(8,4782).
+char(p,4783).
+char(o,4784).
+char(p,4785).
+char(9,4786).
+char(9,4787).
+char(5,4788).
+char(8,4789).
+char(m,4790).
+char(o,4791).
+char(m,4792).
+char(o,4793).
+char(o,4794).
+char(p,4795).
+char(9,4796).
+char(9,4797).
+char(1,4798).
+char(2,4799).
+char(c,4800).
+char(c,4801).
+char(p,4802).
+char(3,4803).
+char(3,4804).
+char(5,4805).
+char(6,4806).
+char(c,4807).
+char(p,4808).
+char(o,4809).
+char(m,4810).
+char(7,4811).
+char(1,4812).
+char(3,4813).
+char(0,4814).
+char(c,4815).
+char(m,4816).
+char(o,4817).
+char(p,4818).
+char(4,4819).
+char(8,4820).
+char(2,4821).
+char(9,4822).
+char(c,4823).
+char(m,4824).
+char(o,4825).
+char(o,4826).
+char(m,4827).
+char(1,4828).
+char(0,4829).
+char(4,4830).
+char(9,4831).
+char(p,4832).
+char(o,4833).
+char(p,4834).
+char(o,4835).
+char(m,4836).
+char(o,4837).
+char(p,4838).
+char(4,4839).
+char(8,4840).
+char(2,4841).
+char(1,4842).
+char(c,4843).
+char(m,4844).
+char(o,4845).
+char(m,4846).
+char(1,4847).
+char(7,4848).
+char(4,4849).
+char(6,4850).
+char(m,4851).
+char(o,4852).
+char(m,4853).
+char(o,4854).
+char(m,4855).
+char(7,4856).
+char(7,4857).
+char(7,4858).
+char(5,4859).
+char(c,4860).
+char(c,4861).
+char(p,4862).
+char(o,4863).
+char(p,4864).
+char(4,4865).
+char(1,4866).
+char(5,4867).
+char(4,4868).
+char(p,4869).
+char(o,4870).
+char(m,4871).
+char(3,4872).
+char(8,4873).
+char(8,4874).
+char(6,4875).
+char(p,4876).
+char(6,4877).
+char(5,4878).
+char(5,4879).
+char(7,4880).
+char(m,4881).
+char(o,4882).
+char(o,4883).
+char(o,4884).
+char(2,4885).
+char(2,4886).
+char(2,4887).
+char(2,4888).
+char(c,4889).
+char(m,4890).
+char(o,4891).
+char(p,4892).
+char(o,4893).
+char(m,4894).
+char(o,4895).
+char(m,4896).
+char(o,4897).
+char(1,4898).
+char(2,4899).
+char(6,4900).
+char(4,4901).
+char(c,4902).
+char(m,4903).
+char(o,4904).
+char(p,4905).
+char(o,4906).
+char(p,4907).
+char(2,4908).
+char(9,4909).
+char(0,4910).
+char(4,4911).
+char(c,4912).
+char(c,4913).
+char(c,4914).
+char(m,4915).
+char(o,4916).
+char(m,4917).
+char(o,4918).
+char(m,4919).
+char(o,4920).
+char(p,4921).
+char(o,4922).
+char(3,4923).
+char(1,4924).
+char(7,4925).
+char(p,4926).
+char(o,4927).
+char(p,4928).
+char(o,4929).
+char(o,4930).
+char(4,4931).
+char(9,4932).
+char(6,4933).
+char(4,4934).
+char(c,4935).
+char(c,4936).
+char(m,4937).
+char(7,4938).
+char(3,4939).
+char(3,4940).
+char(9,4941).
+char(m,4942).
+char(1,4943).
+char(9,4944).
+char(3,4945).
+char(3,4946).
+char(c,4947).
+char(c,4948).
+char(m,4949).
+char(o,4950).
+char(p,4951).
+char(o,4952).
+char(o,4953).
+char(p,4954).
+char(o,4955).
+char(o,4956).
+char(m,4957).
+char(o,4958).
+char(o,4959).
+char(o,4960).
+char(m,4961).
+char(9,4962).
+char(7,4963).
+char(5,4964).
+char(8,4965).
+char(c,4966).
+char(c,4967).
+char(p,4968).
+char(o,4969).
+char(p,4970).
+char(3,4971).
+char(0,4972).
+char(3,4973).
+char(3,4974).
+char(m,4975).
+char(9,4976).
+char(3,4977).
+char(5,4978).
+char(6,4979).
+char(m,4980).
+char(o,4981).
+char(3,4982).
+char(8,4983).
+char(2,4984).
+char(4,4985).
+char(p,4986).
+char(1,4987).
+char(8,4988).
+char(4,4989).
+char(2,4990).
+char(c,4991).
+char(c,4992).
+char(c,4993).
+char(c,4994).
+char(c,4995).
+char(m,4996).
+char(4,4997).
+char(3,4998).
+char(6,4999).
+char(3,5000).
+char(c,5001).
+char(c,5002).
+char(p,5003).
+char(5,5004).
+char(9,5005).
+char(3,5006).
+char(0,5007).
+char(c,5008).
+char(m,5009).
+char(o,5010).
+char(m,5011).
+char(o,5012).
+char(m,5013).
+char(8,5014).
+char(6,5015).
+char(4,5016).
+char(7,5017).
+char(c,5018).
+char(c,5019).
+char(p,5020).
+char(9,5021).
+char(1,5022).
+char(0,5023).
+char(2,5024).
+char(c,5025).
+char(p,5026).
+char(o,5027).
+char(m,5028).
+char(9,5029).
+char(1,5030).
+char(2,5031).
+char(8,5032).
+char(c,5033).
+char(c,5034).
+char(p,5035).
+char(7,5036).
+char(6,5037).
+char(6,5038).
+char(4,5039).
+char(c,5040).
+char(c,5041).
+char(c,5042).
+char(c,5043).
+char(c,5044).
+char(c,5045).
+char(c,5046).
+char(m,5047).
+char(1,5048).
+char(1,5049).
+char(9,5050).
+char(1,5051).
+char(c,5052).
+char(m,5053).
+char(o,5054).
+char(m,5055).
+char(5,5056).
+char(7,5057).
+char(2,5058).
+char(8,5059).
+char(p,5060).
+char(o,5061).
+char(p,5062).
+char(o,5063).
+char(m,5064).
+char(3,5065).
+char(8,5066).
+char(2,5067).
+char(9,5068).
+char(m,5069).
+char(5,5070).
+char(7,5071).
+char(6,5072).
+char(c,5073).
+char(c,5074).
+char(c,5075).
+char(c,5076).
+char(m,5077).
+char(7,5078).
+char(5,5079).
+char(8,5080).
+char(c,5081).
+char(m,5082).
+char(o,5083).
+char(m,5084).
+char(o,5085).
+char(1,5086).
+char(3,5087).
+char(4,5088).
+char(c,5089).
+char(p,5090).
+char(o,5091).
+char(o,5092).
+char(m,5093).
+char(5,5094).
+char(3,5095).
+char(7,5096).
+char(7,5097).
+char(m,5098).
+char(5,5099).
+char(4,5100).
+char(2,5101).
+char(6,5102).
+char(c,5103).
+char(c,5104).
+char(p,5105).
+char(3,5106).
+char(7,5107).
+char(6,5108).
+char(9,5109).
+char(c,5110).
+char(m,5111).
+char(4,5112).
+char(1,5113).
+char(8,5114).
+char(5,5115).
+char(m,5116).
+char(8,5117).
+char(7,5118).
+char(3,5119).
+char(2,5120).
+char(c,5121).
+char(c,5122).
+char(m,5123).
+char(8,5124).
+char(3,5125).
+char(5,5126).
+char(4,5127).
+char(p,5128).
+char(o,5129).
+char(o,5130).
+char(6,5131).
+char(1,5132).
+char(4,5133).
+char(2,5134).
+char(c,5135).
+char(p,5136).
+char(o,5137).
+char(o,5138).
+char(p,5139).
+char(5,5140).
+char(6,5141).
+char(6,5142).
+char(2,5143).
+char(m,5144).
+char(o,5145).
+char(m,5146).
+char(2,5147).
+char(2,5148).
+char(2,5149).
+char(4,5150).
+char(m,5151).
+char(8,5152).
+char(7,5153).
+char(8,5154).
+char(8,5155).
+char(p,5156).
+char(2,5157).
+char(5,5158).
+char(1,5159).
+char(4,5160).
+char(m,5161).
+char(1,5162).
+char(8,5163).
+char(0,5164).
+char(4,5165).
+char(c,5166).
+char(p,5167).
+char(o,5168).
+char(m,5169).
+char(7,5170).
+char(8,5171).
+char(0,5172).
+char(6,5173).
+char(m,5174).
+char(3,5175).
+char(0,5176).
+char(1,5177).
+char(2,5178).
+char(m,5179).
+char(o,5180).
+char(o,5181).
+char(o,5182).
+char(3,5183).
+char(0,5184).
+char(3,5185).
+char(2,5186).
+char(m,5187).
+char(2,5188).
+char(8,5189).
+char(9,5190).
+char(1,5191).
+char(p,5192).
+char(9,5193).
+char(5,5194).
+char(9,5195).
+char(3,5196).
+char(c,5197).
+char(p,5198).
+char(5,5199).
+char(9,5200).
+char(0,5201).
+char(1,5202).
+char(c,5203).
+char(m,5204).
+char(2,5205).
+char(5,5206).
+char(4,5207).
+char(0,5208).
+char(m,5209).
+char(6,5210).
+char(2,5211).
+char(9,5212).
+char(0,5213).
+char(m,5214).
+char(o,5215).
+char(p,5216).
+char(o,5217).
+char(p,5218).
+char(o,5219).
+char(o,5220).
+char(p,5221).
+char(o,5222).
+char(p,5223).
+char(9,5224).
+char(6,5225).
+char(1,5226).
+char(0,5227).
+char(m,5228).
+char(o,5229).
+char(3,5230).
+char(6,5231).
+char(3,5232).
+char(4,5233).
+char(m,5234).
+char(o,5235).
+char(p,5236).
+char(o,5237).
+char(4,5238).
+char(8,5239).
+char(9,5240).
+char(c,5241).
+char(m,5242).
+char(9,5243).
+char(7,5244).
+char(1,5245).
+char(3,5246).
+char(m,5247).
+char(o,5248).
+char(8,5249).
+char(2,5250).
+char(4,5251).
+char(3,5252).
+char(c,5253).
+char(m,5254).
+char(8,5255).
+char(2,5256).
+char(1,5257).
+char(m,5258).
+char(o,5259).
+char(m,5260).
+char(4,5261).
+char(6,5262).
+char(2,5263).
+char(1,5264).
+char(c,5265).
+char(c,5266).
+char(c,5267).
+char(m,5268).
+char(3,5269).
+char(0,5270).
+char(9,5271).
+char(3,5272).
+char(c,5273).
+char(m,5274).
+char(o,5275).
+char(m,5276).
+char(2,5277).
+char(0,5278).
+char(9,5279).
+char(2,5280).
+char(c,5281).
+char(p,5282).
+char(6,5283).
+char(0,5284).
+char(3,5285).
+char(8,5286).
+char(c,5287).
+char(c,5288).
+char(c,5289).
+char(c,5290).
+char(p,5291).
+char(o,5292).
+char(5,5293).
+char(4,5294).
+char(3,5295).
+char(1,5296).
+char(c,5297).
+char(c,5298).
+char(c,5299).
+char(p,5300).
+char(2,5301).
+char(3,5302).
+char(3,5303).
+char(9,5304).
+char(c,5305).
+char(m,5306).
+char(o,5307).
+char(8,5308).
+char(6,5309).
+char(7,5310).
+char(c,5311).
+char(p,5312).
+char(o,5313).
+char(p,5314).
+char(o,5315).
+char(p,5316).
+char(4,5317).
+char(8,5318).
+char(7,5319).
+char(5,5320).
+char(c,5321).
+char(m,5322).
+char(o,5323).
+char(m,5324).
+char(3,5325).
+char(1,5326).
+char(1,5327).
+char(8,5328).
+char(c,5329).
+char(c,5330).
+char(p,5331).
+char(o,5332).
+char(7,5333).
+char(7,5334).
+char(9,5335).
+char(3,5336).
+char(m,5337).
+char(o,5338).
+char(m,5339).
+char(3,5340).
+char(0,5341).
+char(7,5342).
+char(6,5343).
+char(c,5344).
+char(m,5345).
+char(7,5346).
+char(6,5347).
+char(6,5348).
+char(4,5349).
+char(m,5350).
+char(o,5351).
+char(m,5352).
+char(o,5353).
+char(m,5354).
+char(8,5355).
+char(3,5356).
+char(5,5357).
+char(6,5358).
+char(c,5359).
+char(p,5360).
+char(1,5361).
+char(2,5362).
+char(2,5363).
+char(7,5364).
+char(c,5365).
+char(c,5366).
+char(c,5367).
+char(c,5368).
+char(m,5369).
+char(4,5370).
+char(1,5371).
+char(3,5372).
+char(0,5373).
+char(c,5374).
+char(c,5375).
+char(m,5376).
+char(o,5377).
+char(o,5378).
+char(p,5379).
+char(o,5380).
+char(p,5381).
+char(o,5382).
+char(p,5383).
+char(8,5384).
+char(9,5385).
+char(3,5386).
+char(1,5387).
+char(m,5388).
+char(2,5389).
+char(8,5390).
+char(5,5391).
+char(0,5392).
+char(p,5393).
+char(3,5394).
+char(6,5395).
+char(3,5396).
+char(8,5397).
+char(p,5398).
+char(8,5399).
+char(7,5400).
+char(9,5401).
+char(p,5402).
+char(o,5403).
+char(9,5404).
+char(2,5405).
+char(2,5406).
+char(4,5407).
+char(m,5408).
+char(4,5409).
+char(9,5410).
+char(9,5411).
+char(6,5412).
+char(m,5413).
+char(o,5414).
+char(4,5415).
+char(7,5416).
+char(5,5417).
+char(9,5418).
+char(c,5419).
+char(m,5420).
+char(o,5421).
+char(p,5422).
+char(o,5423).
+char(5,5424).
+char(0,5425).
+char(0,5426).
+char(2,5427).
+char(m,5428).
+char(o,5429).
+char(p,5430).
+char(o,5431).
+char(o,5432).
+char(8,5433).
+char(8,5434).
+char(1,5435).
+char(c,5436).
+char(p,5437).
+char(o,5438).
+char(p,5439).
+char(2,5440).
+char(3,5441).
+char(6,5442).
+char(9,5443).
+char(m,5444).
+char(1,5445).
+char(3,5446).
+char(8,5447).
+char(5,5448).
+char(c,5449).
+char(p,5450).
+char(o,5451).
+char(p,5452).
+char(5,5453).
+char(1,5454).
+char(5,5455).
+char(7,5456).
+char(c,5457).
+char(c,5458).
+char(m,5459).
+char(o,5460).
+char(o,5461).
+char(m,5462).
+char(o,5463).
+char(o,5464).
+char(o,5465).
+char(m,5466).
+char(o,5467).
+char(m,5468).
+char(9,5469).
+char(7,5470).
+char(4,5471).
+char(1,5472).
+char(m,5473).
+char(6,5474).
+char(8,5475).
+char(3,5476).
+char(4,5477).
+char(m,5478).
+char(o,5479).
+char(9,5480).
+char(7,5481).
+char(9,5482).
+char(1,5483).
+char(p,5484).
+char(o,5485).
+char(m,5486).
+char(o,5487).
+char(m,5488).
+char(o,5489).
+char(m,5490).
+char(o,5491).
+char(o,5492).
+char(8,5493).
+char(1,5494).
+char(0,5495).
+char(2,5496).
+char(m,5497).
+char(8,5498).
+char(5,5499).
+char(9,5500).
+char(7,5501).
+char(c,5502).
+char(p,5503).
+char(o,5504).
+char(m,5505).
+char(2,5506).
+char(4,5507).
+char(0,5508).
+char(4,5509).
+char(m,5510).
+char(9,5511).
+char(0,5512).
+char(8,5513).
+char(0,5514).
+char(c,5515).
+char(c,5516).
+char(p,5517).
+char(7,5518).
+char(7,5519).
+char(6,5520).
+char(m,5521).
+char(o,5522).
+char(p,5523).
+char(o,5524).
+char(m,5525).
+char(5,5526).
+char(9,5527).
+char(8,5528).
+char(3,5529).
+char(p,5530).
+char(8,5531).
+char(7,5532).
+char(1,5533).
+char(8,5534).
+char(c,5535).
+char(p,5536).
+char(7,5537).
+char(5,5538).
+char(4,5539).
+char(7,5540).
+char(c,5541).
+char(c,5542).
+char(c,5543).
+char(c,5544).
+char(c,5545).
+char(c,5546).
+char(c,5547).
+char(c,5548).
+char(m,5549).
+char(o,5550).
+char(m,5551).
+char(o,5552).
+char(m,5553).
+char(4,5554).
+char(5,5555).
+char(2,5556).
+char(0,5557).
+char(c,5558).
+char(p,5559).
+char(3,5560).
+char(3,5561).
+char(7,5562).
+char(5,5563).
+char(p,5564).
+char(o,5565).
+char(m,5566).
+char(o,5567).
+char(9,5568).
+char(2,5569).
+char(3,5570).
+char(9,5571).
+char(c,5572).
+char(c,5573).
+char(m,5574).
+char(o,5575).
+char(p,5576).
+char(9,5577).
+char(3,5578).
+char(0,5579).
+char(4,5580).
+char(p,5581).
+char(o,5582).
+char(m,5583).
+char(o,5584).
+char(2,5585).
+char(9,5586).
+char(1,5587).
+char(8,5588).
+char(c,5589).
+char(p,5590).
+char(6,5591).
+char(0,5592).
+char(9,5593).
+char(1,5594).
+char(c,5595).
+char(c,5596).
+char(m,5597).
+char(o,5598).
+char(m,5599).
+char(o,5600).
+char(4,5601).
+char(3,5602).
+char(8,5603).
+char(1,5604).
+char(c,5605).
+char(c,5606).
+char(p,5607).
+char(4,5608).
+char(5,5609).
+char(6,5610).
+char(2,5611).
+char(c,5612).
+char(c,5613).
+char(c,5614).
+char(m,5615).
+char(o,5616).
+char(p,5617).
+char(3,5618).
+char(9,5619).
+char(0,5620).
+char(7,5621).
+char(c,5622).
+char(c,5623).
+char(p,5624).
+char(o,5625).
+char(m,5626).
+char(o,5627).
+char(m,5628).
+char(5,5629).
+char(6,5630).
+char(7,5631).
+char(2,5632).
+char(c,5633).
+char(c,5634).
+char(p,5635).
+char(2,5636).
+char(8,5637).
+char(9,5638).
+char(8,5639).
+char(m,5640).
+char(o,5641).
+char(p,5642).
+char(o,5643).
+char(m,5644).
+char(6,5645).
+char(7,5646).
+char(1,5647).
+char(3,5648).
+char(c,5649).
+char(c,5650).
+char(c,5651).
+char(c,5652).
+char(m,5653).
+char(o,5654).
+char(3,5655).
+char(4,5656).
+char(6,5657).
+char(0,5658).
+char(c,5659).
+char(m,5660).
+char(o,5661).
+char(m,5662).
+char(3,5663).
+char(4,5664).
+char(9,5665).
+char(8,5666).
+char(m,5667).
+char(o,5668).
+char(o,5669).
+char(p,5670).
+char(7,5671).
+char(9,5672).
+char(8,5673).
+char(3,5674).
+char(p,5675).
+char(7,5676).
+char(5,5677).
+char(3,5678).
+char(4,5679).
+char(c,5680).
+char(c,5681).
+char(c,5682).
+char(c,5683).
+char(c,5684).
+char(m,5685).
+char(o,5686).
+char(4,5687).
+char(7,5688).
+char(4,5689).
+char(9,5690).
+char(c,5691).
+char(c,5692).
+char(m,5693).
+char(9,5694).
+char(1,5695).
+char(8,5696).
+char(3,5697).
+char(p,5698).
+char(o,5699).
+char(m,5700).
+char(o,5701).
+char(p,5702).
+char(5,5703).
+char(0,5704).
+char(2,5705).
+char(0,5706).
+char(c,5707).
+char(c,5708).
+char(m,5709).
+char(o,5710).
+char(p,5711).
+char(o,5712).
+char(p,5713).
+char(9,5714).
+char(2,5715).
+char(6,5716).
+char(8,5717).
+char(p,5718).
+char(o,5719).
+char(p,5720).
+char(7,5721).
+char(9,5722).
+char(8,5723).
+char(7,5724).
+char(c,5725).
+char(c,5726).
+char(m,5727).
+char(3,5728).
+char(1,5729).
+char(7,5730).
+char(5,5731).
+char(m,5732).
+char(o,5733).
+char(o,5734).
+char(7,5735).
+char(8,5736).
+char(6,5737).
+char(5,5738).
+char(p,5739).
+char(2,5740).
+char(9,5741).
+char(0,5742).
+char(7,5743).
+char(m,5744).
+char(o,5745).
+char(m,5746).
+char(4,5747).
+char(4,5748).
+char(8,5749).
+char(3,5750).
+char(c,5751).
+char(m,5752).
+char(o,5753).
+char(7,5754).
+char(4,5755).
+char(9,5756).
+char(9,5757).
+char(m,5758).
+char(o,5759).
+char(m,5760).
+char(o,5761).
+char(m,5762).
+char(5,5763).
+char(1,5764).
+char(1,5765).
+char(3,5766).
+char(m,5767).
+char(o,5768).
+char(1,5769).
+char(7,5770).
+char(7,5771).
+char(5,5772).
+char(c,5773).
+char(c,5774).
+char(c,5775).
+char(m,5776).
+char(o,5777).
+char(m,5778).
+char(8,5779).
+char(8,5780).
+char(7,5781).
+char(9,5782).
+char(m,5783).
+char(o,5784).
+char(p,5785).
+char(9,5786).
+char(9,5787).
+char(9,5788).
+char(5,5789).
+char(c,5790).
+char(c,5791).
+char(c,5792).
+char(c,5793).
+char(c,5794).
+char(c,5795).
+char(c,5796).
+char(c,5797).
+char(p,5798).
+char(8,5799).
+char(1,5800).
+char(6,5801).
+char(6,5802).
+char(c,5803).
+char(m,5804).
+char(o,5805).
+char(p,5806).
+char(4,5807).
+char(6,5808).
+char(3,5809).
+char(8,5810).
+char(c,5811).
+char(m,5812).
+char(6,5813).
+char(0,5814).
+char(3,5815).
+char(9,5816).
+char(m,5817).
+char(o,5818).
+char(m,5819).
+char(o,5820).
+char(7,5821).
+char(0,5822).
+char(6,5823).
+char(2,5824).
+char(m,5825).
+char(o,5826).
+char(m,5827).
+char(3,5828).
+char(5,5829).
+char(4,5830).
+char(9,5831).
+char(c,5832).
+char(m,5833).
+char(8,5834).
+char(7,5835).
+char(9,5836).
+char(6,5837).
+char(p,5838).
+char(6,5839).
+char(4,5840).
+char(6,5841).
+char(6,5842).
+char(c,5843).
+char(p,5844).
+char(6,5845).
+char(8,5846).
+char(4,5847).
+char(7,5848).
+char(c,5849).
+char(c,5850).
+char(p,5851).
+char(3,5852).
+char(1,5853).
+char(3,5854).
+char(8,5855).
+char(m,5856).
+char(o,5857).
+char(m,5858).
+char(3,5859).
+char(2,5860).
+char(5,5861).
+char(4,5862).
+char(c,5863).
+char(p,5864).
+char(o,5865).
+char(9,5866).
+char(6,5867).
+char(6,5868).
+char(6,5869).
+char(p,5870).
+char(1,5871).
+char(5,5872).
+char(8,5873).
+char(7,5874).
+char(m,5875).
+char(4,5876).
+char(7,5877).
+char(8,5878).
+char(5,5879).
+char(c,5880).
+char(c,5881).
+char(c,5882).
+char(c,5883).
+char(c,5884).
+char(c,5885).
+char(p,5886).
+char(1,5887).
+char(7,5888).
+char(7,5889).
+char(9,5890).
+char(c,5891).
+char(p,5892).
+char(9,5893).
+char(6,5894).
+char(9,5895).
+char(4,5896).
+char(c,5897).
+char(c,5898).
+char(m,5899).
+char(5,5900).
+char(0,5901).
+char(9,5902).
+char(9,5903).
+char(p,5904).
+char(o,5905).
+char(m,5906).
+char(8,5907).
+char(2,5908).
+char(1,5909).
+char(9,5910).
+char(c,5911).
+char(c,5912).
+char(m,5913).
+char(o,5914).
+char(p,5915).
+char(7,5916).
+char(4,5917).
+char(8,5918).
+char(8,5919).
+char(c,5920).
+char(c,5921).
+char(p,5922).
+char(9,5923).
+char(2,5924).
+char(1,5925).
+char(9,5926).
+char(m,5927).
+char(o,5928).
+char(p,5929).
+char(4,5930).
+char(6,5931).
+char(6,5932).
+char(1,5933).
+char(m,5934).
+char(o,5935).
+char(p,5936).
+char(o,5937).
+char(p,5938).
+char(o,5939).
+char(p,5940).
+char(o,5941).
+char(m,5942).
+char(5,5943).
+char(3,5944).
+char(7,5945).
+char(2,5946).
+char(c,5947).
+char(c,5948).
+char(m,5949).
+char(9,5950).
+char(6,5951).
+char(6,5952).
+char(3,5953).
+char(c,5954).
+char(p,5955).
+char(o,5956).
+char(3,5957).
+char(1,5958).
+char(5,5959).
+char(2,5960).
+char(p,5961).
+char(6,5962).
+char(9,5963).
+char(8,5964).
+char(5,5965).
+char(p,5966).
+char(o,5967).
+char(9,5968).
+char(1,5969).
+char(6,5970).
+char(7,5971).
+char(m,5972).
+char(o,5973).
+char(7,5974).
+char(1,5975).
+char(2,5976).
+char(7,5977).
+char(c,5978).
+char(c,5979).
+char(c,5980).
+char(c,5981).
+char(c,5982).
+char(c,5983).
+char(m,5984).
+char(1,5985).
+char(2,5986).
+char(5,5987).
+char(7,5988).
+char(c,5989).
+char(c,5990).
+char(p,5991).
+char(9,5992).
+char(7,5993).
+char(3,5994).
+char(8,5995).
+char(c,5996).
+char(p,5997).
+char(4,5998).
+char(2,5999).
+char(8,6000).
+char(6,6001).
+char(m,6002).
+char(2,6003).
+char(0,6004).
+char(3,6005).
+char(4,6006).
+char(c,6007).
+char(c,6008).
+char(c,6009).
+char(m,6010).
+char(5,6011).
+char(4,6012).
+char(3,6013).
+char(9,6014).
+char(c,6015).
+char(m,6016).
+char(1,6017).
+char(9,6018).
+char(0,6019).
+char(4,6020).
+char(p,6021).
+char(4,6022).
+char(9,6023).
+char(6,6024).
+char(7,6025).
+char(c,6026).
+char(p,6027).
+char(o,6028).
+char(5,6029).
+char(0,6030).
+char(6,6031).
+char(5,6032).
+char(p,6033).
+char(3,6034).
+char(3,6035).
+char(0,6036).
+char(p,6037).
+char(o,6038).
+char(p,6039).
+char(o,6040).
+char(m,6041).
+char(o,6042).
+char(m,6043).
+char(o,6044).
+char(o,6045).
+char(m,6046).
+char(o,6047).
+char(p,6048).
+char(o,6049).
+char(m,6050).
+char(9,6051).
+char(0,6052).
+char(9,6053).
+char(2,6054).
+char(c,6055).
+char(c,6056).
+char(m,6057).
+char(o,6058).
+char(p,6059).
+char(o,6060).
+char(4,6061).
+char(4,6062).
+char(2,6063).
+char(8,6064).
+char(c,6065).
+char(p,6066).
+char(1,6067).
+char(4,6068).
+char(5,6069).
+char(8,6070).
+char(m,6071).
+char(6,6072).
+char(4,6073).
+char(9,6074).
+char(6,6075).
+char(p,6076).
+char(o,6077).
+char(m,6078).
+char(o,6079).
+char(p,6080).
+char(1,6081).
+char(0,6082).
+char(2,6083).
+char(m,6084).
+char(8,6085).
+char(8,6086).
+char(2,6087).
+char(5,6088).
+char(c,6089).
+char(m,6090).
+char(8,6091).
+char(4,6092).
+char(4,6093).
+char(p,6094).
+char(1,6095).
+char(8,6096).
+char(2,6097).
+char(8,6098).
+char(c,6099).
+char(m,6100).
+char(7,6101).
+char(9,6102).
+char(5,6103).
+char(0,6104).
+char(c,6105).
+char(c,6106).
+char(m,6107).
+char(o,6108).
+char(p,6109).
+char(o,6110).
+char(p,6111).
+char(8,6112).
+char(0,6113).
+char(4,6114).
+char(5,6115).
+char(c,6116).
+char(m,6117).
+char(o,6118).
+char(o,6119).
+char(7,6120).
+char(1,6121).
+char(6,6122).
+char(9,6123).
+char(c,6124).
+char(c,6125).
+char(c,6126).
+char(c,6127).
+char(p,6128).
+char(o,6129).
+char(p,6130).
+char(3,6131).
+char(5,6132).
+char(2,6133).
+char(0,6134).
+char(p,6135).
+char(5,6136).
+char(1,6137).
+char(0,6138).
+char(3,6139).
+char(c,6140).
+char(c,6141).
+char(c,6142).
+char(p,6143).
+char(9,6144).
+char(1,6145).
+char(0,6146).
+char(0,6147).
+char(c,6148).
+char(p,6149).
+char(3,6150).
+char(4,6151).
+char(5,6152).
+char(0,6153).
+char(c,6154).
+char(p,6155).
+char(o,6156).
+char(o,6157).
+char(p,6158).
+char(o,6159).
+char(m,6160).
+char(8,6161).
+char(4,6162).
+char(4,6163).
+char(8,6164).
+char(c,6165).
+char(p,6166).
+char(o,6167).
+char(m,6168).
+char(o,6169).
+char(m,6170).
+char(1,6171).
+char(2,6172).
+char(6,6173).
+char(5,6174).
+char(c,6175).
+char(m,6176).
+char(o,6177).
+char(m,6178).
+char(o,6179).
+char(2,6180).
+char(1,6181).
+char(0,6182).
+char(5,6183).
+char(m,6184).
+char(9,6185).
+char(5,6186).
+char(5,6187).
+char(0,6188).
+char(p,6189).
+char(o,6190).
+char(m,6191).
+char(o,6192).
+char(o,6193).
+char(m,6194).
+char(1,6195).
+char(9,6196).
+char(3,6197).
+char(p,6198).
+char(4,6199).
+char(5,6200).
+char(8,6201).
+char(7,6202).
+char(c,6203).
+char(c,6204).
+char(p,6205).
+char(o,6206).
+char(m,6207).
+char(4,6208).
+char(1,6209).
+char(5,6210).
+char(p,6211).
+char(3,6212).
+char(1,6213).
+char(6,6214).
+char(3,6215).
+char(c,6216).
+char(c,6217).
+char(c,6218).
+char(p,6219).
+char(o,6220).
+char(2,6221).
+char(0,6222).
+char(1,6223).
+char(7,6224).
+char(m,6225).
+char(o,6226).
+char(o,6227).
+char(p,6228).
+char(o,6229).
+char(p,6230).
+char(o,6231).
+char(m,6232).
+char(o,6233).
+char(o,6234).
+char(p,6235).
+char(o,6236).
+char(p,6237).
+char(5,6238).
+char(5,6239).
+char(2,6240).
+char(4,6241).
+char(m,6242).
+char(o,6243).
+char(p,6244).
+char(3,6245).
+char(2,6246).
+char(2,6247).
+char(6,6248).
+char(p,6249).
+char(o,6250).
+char(p,6251).
+char(8,6252).
+char(6,6253).
+char(4,6254).
+char(m,6255).
+char(o,6256).
+char(m,6257).
+char(8,6258).
+char(6,6259).
+char(1,6260).
+char(3,6261).
+char(c,6262).
+char(c,6263).
+char(p,6264).
+char(o,6265).
+char(m,6266).
+char(o,6267).
+char(m,6268).
+char(o,6269).
+char(p,6270).
+char(o,6271).
+char(p,6272).
+char(5,6273).
+char(2,6274).
+char(8,6275).
+char(c,6276).
+char(c,6277).
+char(c,6278).
+char(p,6279).
+char(o,6280).
+char(m,6281).
+char(3,6282).
+char(1,6283).
+char(4,6284).
+char(m,6285).
+char(4,6286).
+char(1,6287).
+char(8,6288).
+char(m,6289).
+char(4,6290).
+char(8,6291).
+char(7,6292).
+char(7,6293).
+char(m,6294).
+char(1,6295).
+char(9,6296).
+char(9,6297).
+char(2,6298).
+char(c,6299).
+char(m,6300).
+char(5,6301).
+char(0,6302).
+char(5,6303).
+char(8,6304).
+char(p,6305).
+char(o,6306).
+char(7,6307).
+char(8,6308).
+char(0,6309).
+char(1,6310).
+char(m,6311).
+char(3,6312).
+char(3,6313).
+char(1,6314).
+char(7,6315).
+char(c,6316).
+char(m,6317).
+char(4,6318).
+char(8,6319).
+char(0,6320).
+char(2,6321).
+char(p,6322).
+char(3,6323).
+char(7,6324).
+char(6,6325).
+char(6,6326).
+char(p,6327).
+char(6,6328).
+char(5,6329).
+char(4,6330).
+char(4,6331).
+char(p,6332).
+char(o,6333).
+char(m,6334).
+char(o,6335).
+char(p,6336).
+char(7,6337).
+char(6,6338).
+char(8,6339).
+char(9,6340).
+char(m,6341).
+char(o,6342).
+char(p,6343).
+char(o,6344).
+char(m,6345).
+char(o,6346).
+char(p,6347).
+char(o,6348).
+char(3,6349).
+char(0,6350).
+char(7,6351).
+char(6,6352).
+char(c,6353).
+char(c,6354).
+char(m,6355).
+char(o,6356).
+char(m,6357).
+char(o,6358).
+char(m,6359).
+char(o,6360).
+char(m,6361).
+char(o,6362).
+char(m,6363).
+char(o,6364).
+char(m,6365).
+char(o,6366).
+char(m,6367).
+char(8,6368).
+char(4,6369).
+char(4,6370).
+char(1,6371).
+char(c,6372).
+char(c,6373).
+char(c,6374).
+char(c,6375).
+char(p,6376).
+char(o,6377).
+char(p,6378).
+char(9,6379).
+char(4,6380).
+char(4,6381).
+char(1,6382).
+char(c,6383).
+char(c,6384).
+char(p,6385).
+char(1,6386).
+char(6,6387).
+char(5,6388).
+char(0,6389).
+char(c,6390).
+char(c,6391).
+char(m,6392).
+char(5,6393).
+char(9,6394).
+char(3,6395).
+char(6,6396).
+char(m,6397).
+char(6,6398).
+char(6,6399).
+char(2,6400).
+char(5,6401).
+char(m,6402).
+char(o,6403).
+char(o,6404).
+char(2,6405).
+char(9,6406).
+char(1,6407).
+char(1,6408).
+char(c,6409).
+char(c,6410).
+char(c,6411).
+char(m,6412).
+char(o,6413).
+char(7,6414).
+char(5,6415).
+char(9,6416).
+char(3,6417).
+char(p,6418).
+char(4,6419).
+char(7,6420).
+char(9,6421).
+char(9,6422).
+char(p,6423).
+char(3,6424).
+char(6,6425).
+char(3,6426).
+char(2,6427).
+char(m,6428).
+char(o,6429).
+char(3,6430).
+char(0,6431).
+char(3,6432).
+char(7,6433).
+char(p,6434).
+char(8,6435).
+char(7,6436).
+char(2,6437).
+char(1,6438).
+char(m,6439).
+char(o,6440).
+char(m,6441).
+char(7,6442).
+char(8,6443).
+char(2,6444).
+char(0,6445).
+char(p,6446).
+char(o,6447).
+char(p,6448).
+char(5,6449).
+char(5,6450).
+char(7,6451).
+char(1,6452).
+char(c,6453).
+char(p,6454).
+char(o,6455).
+char(m,6456).
+char(6,6457).
+char(1,6458).
+char(5,6459).
+char(0,6460).
+char(p,6461).
+char(5,6462).
+char(7,6463).
+char(9,6464).
+char(4,6465).
+char(m,6466).
+char(6,6467).
+char(4,6468).
+char(8,6469).
+char(2,6470).
+char(c,6471).
+char(m,6472).
+char(4,6473).
+char(7,6474).
+char(2,6475).
+char(9,6476).
+char(c,6477).
+char(m,6478).
+char(7,6479).
+char(4,6480).
+char(2,6481).
+char(c,6482).
+char(c,6483).
+char(p,6484).
+char(8,6485).
+char(7,6486).
+char(0,6487).
+char(4,6488).
+char(p,6489).
+char(o,6490).
+char(o,6491).
+char(o,6492).
+char(m,6493).
+char(o,6494).
+char(p,6495).
+char(7,6496).
+char(9,6497).
+char(9,6498).
+char(2,6499).
+char(m,6500).
+char(9,6501).
+char(7,6502).
+char(2,6503).
+char(9,6504).
+char(m,6505).
+char(8,6506).
+char(7,6507).
+char(0,6508).
+char(2,6509).
+char(c,6510).
+char(m,6511).
+char(o,6512).
+char(m,6513).
+char(o,6514).
+char(o,6515).
+char(p,6516).
+char(9,6517).
+char(9,6518).
+char(2,6519).
+char(c,6520).
+char(c,6521).
+char(c,6522).
+char(c,6523).
+char(c,6524).
+char(m,6525).
+char(4,6526).
+char(9,6527).
+char(5,6528).
+char(4,6529).
+char(c,6530).
+char(m,6531).
+char(9,6532).
+char(0,6533).
+char(8,6534).
+char(5,6535).
+char(m,6536).
+char(o,6537).
+char(o,6538).
+char(3,6539).
+char(4,6540).
+char(8,6541).
+char(2,6542).
+char(p,6543).
+char(o,6544).
+char(4,6545).
+char(4,6546).
+char(6,6547).
+char(0,6548).
+char(c,6549).
+char(p,6550).
+char(o,6551).
+char(3,6552).
+char(5,6553).
+char(4,6554).
+char(3,6555).
+char(m,6556).
+char(o,6557).
+char(o,6558).
+char(m,6559).
+char(o,6560).
+char(5,6561).
+char(1,6562).
+char(8,6563).
+char(9,6564).
+char(p,6565).
+char(8,6566).
+char(8,6567).
+char(8,6568).
+char(c,6569).
+char(p,6570).
+char(7,6571).
+char(6,6572).
+char(1,6573).
+char(c,6574).
+char(c,6575).
+char(p,6576).
+char(7,6577).
+char(8,6578).
+char(1,6579).
+char(c,6580).
+char(c,6581).
+char(m,6582).
+char(3,6583).
+char(2,6584).
+char(5,6585).
+char(8,6586).
+char(c,6587).
+char(m,6588).
+char(7,6589).
+char(7,6590).
+char(4,6591).
+char(9,6592).
+char(p,6593).
+char(5,6594).
+char(5,6595).
+char(2,6596).
+char(3,6597).
+char(m,6598).
+char(o,6599).
+char(p,6600).
+char(o,6601).
+char(p,6602).
+char(o,6603).
+char(p,6604).
+char(9,6605).
+char(2,6606).
+char(3,6607).
+char(1,6608).
+char(p,6609).
+char(o,6610).
+char(o,6611).
+char(o,6612).
+char(m,6613).
+char(o,6614).
+char(p,6615).
+char(5,6616).
+char(6,6617).
+char(4,6618).
+char(7,6619).
+char(p,6620).
+char(o,6621).
+char(p,6622).
+char(6,6623).
+char(3,6624).
+char(6,6625).
+char(c,6626).
+char(p,6627).
+char(6,6628).
+char(4,6629).
+char(4,6630).
+char(4,6631).
+char(c,6632).
+char(c,6633).
+char(p,6634).
+char(o,6635).
+char(o,6636).
+char(7,6637).
+char(1,6638).
+char(5,6639).
+char(8,6640).
+char(p,6641).
+char(o,6642).
+char(p,6643).
+char(o,6644).
+char(4,6645).
+char(3,6646).
+char(7,6647).
+char(5,6648).
+char(c,6649).
+char(m,6650).
+char(9,6651).
+char(2,6652).
+char(6,6653).
+char(2,6654).
+char(c,6655).
+char(p,6656).
+char(6,6657).
+char(6,6658).
+char(9,6659).
+char(8,6660).
+char(m,6661).
+char(o,6662).
+char(7,6663).
+char(8,6664).
+char(5,6665).
+char(7,6666).
+char(c,6667).
+char(c,6668).
+char(p,6669).
+char(o,6670).
+char(p,6671).
+char(4,6672).
+char(3,6673).
+char(3,6674).
+char(9,6675).
+char(c,6676).
+char(c,6677).
+char(c,6678).
+char(c,6679).
+char(c,6680).
+char(m,6681).
+char(o,6682).
+char(p,6683).
+char(3,6684).
+char(5,6685).
+char(5,6686).
+char(8,6687).
+char(c,6688).
+char(c,6689).
+char(c,6690).
+char(m,6691).
+char(3,6692).
+char(3,6693).
+char(1,6694).
+char(6,6695).
+char(p,6696).
+char(8,6697).
+char(6,6698).
+char(1,6699).
+char(7,6700).
+char(c,6701).
+char(c,6702).
+char(p,6703).
+char(8,6704).
+char(9,6705).
+char(0,6706).
+char(4,6707).
+char(c,6708).
+char(c,6709).
+char(c,6710).
+char(p,6711).
+char(3,6712).
+char(7,6713).
+char(4,6714).
+char(0,6715).
+char(c,6716).
+char(c,6717).
+char(c,6718).
+char(c,6719).
+char(c,6720).
+char(c,6721).
+char(m,6722).
+char(o,6723).
+char(m,6724).
+char(o,6725).
+char(m,6726).
+char(2,6727).
+char(0,6728).
+char(5,6729).
+char(7,6730).
+char(m,6731).
+char(9,6732).
+char(6,6733).
+char(6,6734).
+char(7,6735).
+char(p,6736).
+char(5,6737).
+char(8,6738).
+char(9,6739).
+char(2,6740).
+char(c,6741).
+char(p,6742).
+char(5,6743).
+char(4,6744).
+char(9,6745).
+char(3,6746).
+char(c,6747).
+char(m,6748).
+char(o,6749).
+char(o,6750).
+char(8,6751).
+char(3,6752).
+char(5,6753).
+char(6,6754).
+char(m,6755).
+char(o,6756).
+char(m,6757).
+char(o,6758).
+char(m,6759).
+char(8,6760).
+char(0,6761).
+char(7,6762).
+char(3,6763).
+char(m,6764).
+char(1,6765).
+char(5,6766).
+char(6,6767).
+char(1,6768).
+char(p,6769).
+char(o,6770).
+char(m,6771).
+char(2,6772).
+char(8,6773).
+char(3,6774).
+char(c,6775).
+char(m,6776).
+char(o,6777).
+char(2,6778).
+char(1,6779).
+char(5,6780).
+char(5,6781).
+char(p,6782).
+char(8,6783).
+char(9,6784).
+char(6,6785).
+char(m,6786).
+char(o,6787).
+char(p,6788).
+char(3,6789).
+char(7,6790).
+char(9,6791).
+char(c,6792).
+char(c,6793).
+char(c,6794).
+char(c,6795).
+char(c,6796).
+char(m,6797).
+char(o,6798).
+char(o,6799).
+char(p,6800).
+char(o,6801).
+char(8,6802).
+char(9,6803).
+char(1,6804).
+char(3,6805).
+char(c,6806).
+char(c,6807).
+char(c,6808).
+char(c,6809).
+char(c,6810).
+char(c,6811).
+char(m,6812).
+char(o,6813).
+char(p,6814).
+char(o,6815).
+char(p,6816).
+char(3,6817).
+char(0,6818).
+char(4,6819).
+char(1,6820).
+char(p,6821).
+char(o,6822).
+char(p,6823).
+char(7,6824).
+char(3,6825).
+char(3,6826).
+char(5,6827).
+char(c,6828).
+char(m,6829).
+char(8,6830).
+char(6,6831).
+char(8,6832).
+char(3,6833).
+char(p,6834).
+char(7,6835).
+char(1,6836).
+char(8,6837).
+char(5,6838).
+char(p,6839).
+char(o,6840).
+char(3,6841).
+char(4,6842).
+char(0,6843).
+char(9,6844).
+char(p,6845).
+char(2,6846).
+char(6,6847).
+char(4,6848).
+char(9,6849).
+char(m,6850).
+char(7,6851).
+char(5,6852).
+char(9,6853).
+char(6,6854).
+char(c,6855).
+char(m,6856).
+char(o,6857).
+char(p,6858).
+char(o,6859).
+char(p,6860).
+char(o,6861).
+char(p,6862).
+char(3,6863).
+char(8,6864).
+char(9,6865).
+char(8,6866).
+char(m,6867).
+char(8,6868).
+char(6,6869).
+char(2,6870).
+char(3,6871).
+char(p,6872).
+char(9,6873).
+char(1,6874).
+char(1,6875).
+char(8,6876).
+char(c,6877).
+char(m,6878).
+char(2,6879).
+char(6,6880).
+char(1,6881).
+char(6,6882).
+char(m,6883).
+char(o,6884).
+char(p,6885).
+char(o,6886).
+char(m,6887).
+char(o,6888).
+char(o,6889).
+char(m,6890).
+char(o,6891).
+char(3,6892).
+char(5,6893).
+char(7,6894).
+char(m,6895).
+char(o,6896).
+char(m,6897).
+char(6,6898).
+char(2,6899).
+char(1,6900).
+char(6,6901).
+char(c,6902).
+char(c,6903).
+char(c,6904).
+char(m,6905).
+char(o,6906).
+char(p,6907).
+char(o,6908).
+char(p,6909).
+char(6,6910).
+char(6,6911).
+char(1,6912).
+char(8,6913).
+char(c,6914).
+char(c,6915).
+char(m,6916).
+char(5,6917).
+char(5,6918).
+char(9,6919).
+char(8,6920).
+char(c,6921).
+char(p,6922).
+char(o,6923).
+char(p,6924).
+char(8,6925).
+char(8,6926).
+char(2,6927).
+char(2,6928).
+char(c,6929).
+char(c,6930).
+char(p,6931).
+char(o,6932).
+char(p,6933).
+char(4,6934).
+char(2,6935).
+char(0,6936).
+char(4,6937).
+char(c,6938).
+char(p,6939).
+char(6,6940).
+char(8,6941).
+char(5,6942).
+char(6,6943).
+char(m,6944).
+char(5,6945).
+char(1,6946).
+char(8,6947).
+char(2,6948).
+char(c,6949).
+char(c,6950).
+char(c,6951).
+char(m,6952).
+char(2,6953).
+char(3,6954).
+char(2,6955).
+char(4,6956).
+char(p,6957).
+char(o,6958).
+char(o,6959).
+char(9,6960).
+char(4,6961).
+char(9,6962).
+char(1,6963).
+char(c,6964).
+char(m,6965).
+char(4,6966).
+char(5,6967).
+char(4,6968).
+char(6,6969).
+char(p,6970).
+char(1,6971).
+char(5,6972).
+char(1,6973).
+char(9,6974).
+char(p,6975).
+char(o,6976).
+char(m,6977).
+char(o,6978).
+char(6,6979).
+char(7,6980).
+char(9,6981).
+char(1,6982).
+char(c,6983).
+char(c,6984).
+char(c,6985).
+char(c,6986).
+char(c,6987).
+char(c,6988).
+char(c,6989).
+char(c,6990).
+char(m,6991).
+char(7,6992).
+char(0,6993).
+char(4,6994).
+char(0,6995).
+char(c,6996).
+char(m,6997).
+char(5,6998).
+char(5,6999).
+char(4,7000).
+char(8,7001).
+char(p,7002).
+char(o,7003).
+char(m,7004).
+char(3,7005).
+char(7,7006).
+char(6,7007).
+char(7,7008).
+char(p,7009).
+char(2,7010).
+char(0,7011).
+char(6,7012).
+char(9,7013).
+char(c,7014).
+char(m,7015).
+char(o,7016).
+char(4,7017).
+char(5,7018).
+char(7,7019).
+char(9,7020).
+char(c,7021).
+char(c,7022).
+char(p,7023).
+char(8,7024).
+char(3,7025).
+char(8,7026).
+char(4,7027).
+char(c,7028).
+char(m,7029).
+char(o,7030).
+char(m,7031).
+char(8,7032).
+char(0,7033).
+char(7,7034).
+char(6,7035).
+char(c,7036).
+char(c,7037).
+char(c,7038).
+char(c,7039).
+char(c,7040).
+char(c,7041).
+char(c,7042).
+char(p,7043).
+char(o,7044).
+char(p,7045).
+char(o,7046).
+char(o,7047).
+char(p,7048).
+char(o,7049).
+char(m,7050).
+char(o,7051).
+char(p,7052).
+char(6,7053).
+char(5,7054).
+char(9,7055).
+char(0,7056).
+char(c,7057).
+char(c,7058).
+char(c,7059).
+char(m,7060).
+char(2,7061).
+char(1,7062).
+char(1,7063).
+char(9,7064).
+char(c,7065).
+char(p,7066).
+char(o,7067).
+char(m,7068).
+char(o,7069).
+char(7,7070).
+char(7,7071).
+char(0,7072).
+char(0,7073).
+char(m,7074).
+char(o,7075).
+char(m,7076).
+char(5,7077).
+char(1,7078).
+char(6,7079).
+char(1,7080).
+char(p,7081).
+char(o,7082).
+char(p,7083).
+char(6,7084).
+char(2,7085).
+char(4,7086).
+char(7,7087).
+char(c,7088).
+char(c,7089).
+char(m,7090).
+char(o,7091).
+char(m,7092).
+char(o,7093).
+char(o,7094).
+char(m,7095).
+char(3,7096).
+char(5,7097).
+char(3,7098).
+char(4,7099).
+char(p,7100).
+char(o,7101).
+char(o,7102).
+char(6,7103).
+char(0,7104).
+char(8,7105).
+char(4,7106).
+char(c,7107).
+char(c,7108).
+char(m,7109).
+char(2,7110).
+char(8,7111).
+char(4,7112).
+char(8,7113).
+char(p,7114).
+char(7,7115).
+char(8,7116).
+char(6,7117).
+char(6,7118).
+char(m,7119).
+char(4,7120).
+char(8,7121).
+char(7,7122).
+char(8,7123).
+char(c,7124).
+char(p,7125).
+char(o,7126).
+char(o,7127).
+char(m,7128).
+char(1,7129).
+char(2,7130).
+char(2,7131).
+char(7,7132).
+char(p,7133).
+char(o,7134).
+char(m,7135).
+char(o,7136).
+char(p,7137).
+char(o,7138).
+char(m,7139).
+char(o,7140).
+char(m,7141).
+char(o,7142).
+char(m,7143).
+char(1,7144).
+char(2,7145).
+char(4,7146).
+char(7,7147).
+char(m,7148).
+char(6,7149).
+char(2,7150).
+char(2,7151).
+char(7,7152).
+char(m,7153).
+char(o,7154).
+char(5,7155).
+char(3,7156).
+char(7,7157).
+char(4,7158).
+char(c,7159).
+char(p,7160).
+char(7,7161).
+char(8,7162).
+char(9,7163).
+char(1,7164).
+char(p,7165).
+char(8,7166).
+char(7,7167).
+char(9,7168).
+char(0,7169).
+char(c,7170).
+char(c,7171).
+char(c,7172).
+char(c,7173).
+char(p,7174).
+char(4,7175).
+char(3,7176).
+char(9,7177).
+char(7,7178).
+char(c,7179).
+char(m,7180).
+char(9,7181).
+char(1,7182).
+char(8,7183).
+char(7,7184).
+char(c,7185).
+char(m,7186).
+char(o,7187).
+char(p,7188).
+char(o,7189).
+char(p,7190).
+char(8,7191).
+char(0,7192).
+char(1,7193).
+char(8,7194).
+char(p,7195).
+char(o,7196).
+char(5,7197).
+char(5,7198).
+char(1,7199).
+char(1,7200).
+char(p,7201).
+char(4,7202).
+char(6,7203).
+char(8,7204).
+char(6,7205).
+char(m,7206).
+char(o,7207).
+char(o,7208).
+char(5,7209).
+char(5,7210).
+char(0,7211).
+char(4,7212).
+char(p,7213).
+char(1,7214).
+char(6,7215).
+char(2,7216).
+char(3,7217).
+char(m,7218).
+char(6,7219).
+char(0,7220).
+char(9,7221).
+char(c,7222).
+char(p,7223).
+char(8,7224).
+char(7,7225).
+char(1,7226).
+char(1,7227).
+char(m,7228).
+char(o,7229).
+char(p,7230).
+char(o,7231).
+char(p,7232).
+char(1,7233).
+char(0,7234).
+char(1,7235).
+char(8,7236).
+char(p,7237).
+char(3,7238).
+char(0,7239).
+char(6,7240).
+char(p,7241).
+char(o,7242).
+char(6,7243).
+char(1,7244).
+char(5,7245).
+char(8,7246).
+char(c,7247).
+char(p,7248).
+char(o,7249).
+char(m,7250).
+char(o,7251).
+char(p,7252).
+char(o,7253).
+char(p,7254).
+char(o,7255).
+char(m,7256).
+char(o,7257).
+char(m,7258).
+char(7,7259).
+char(2,7260).
+char(6,7261).
+char(0,7262).
+char(m,7263).
+char(o,7264).
+char(p,7265).
+char(4,7266).
+char(9,7267).
+char(6,7268).
+char(7,7269).
+char(p,7270).
+char(o,7271).
+char(p,7272).
+char(o,7273).
+char(p,7274).
+char(9,7275).
+char(9,7276).
+char(5,7277).
+char(9,7278).
+char(c,7279).
+char(m,7280).
+char(o,7281).
+char(p,7282).
+char(7,7283).
+char(6,7284).
+char(4,7285).
+char(9,7286).
+char(m,7287).
+char(4,7288).
+char(5,7289).
+char(0,7290).
+char(7,7291).
+char(m,7292).
+char(4,7293).
+char(0,7294).
+char(4,7295).
+char(9,7296).
+char(c,7297).
+char(p,7298).
+char(o,7299).
+char(o,7300).
+char(m,7301).
+char(o,7302).
+char(5,7303).
+char(9,7304).
+char(9,7305).
+char(6,7306).
+char(c,7307).
+char(c,7308).
+char(p,7309).
+char(o,7310).
+char(p,7311).
+char(2,7312).
+char(0,7313).
+char(9,7314).
+char(7,7315).
+char(p,7316).
+char(2,7317).
+char(0,7318).
+char(6,7319).
+char(4,7320).
+char(p,7321).
+char(3,7322).
+char(1,7323).
+char(8,7324).
+char(c,7325).
+char(c,7326).
+char(c,7327).
+char(c,7328).
+char(m,7329).
+char(o,7330).
+char(p,7331).
+char(o,7332).
+char(p,7333).
+char(o,7334).
+char(m,7335).
+char(o,7336).
+char(p,7337).
+char(3,7338).
+char(0,7339).
+char(4,7340).
+char(4,7341).
+char(m,7342).
+char(7,7343).
+char(8,7344).
+char(9,7345).
+char(5,7346).
+char(c,7347).
+char(p,7348).
+char(9,7349).
+char(2,7350).
+char(7,7351).
+char(6,7352).
+char(m,7353).
+char(o,7354).
+char(m,7355).
+char(o,7356).
+char(m,7357).
+char(1,7358).
+char(4,7359).
+char(2,7360).
+char(7,7361).
+char(c,7362).
+char(p,7363).
+char(o,7364).
+char(m,7365).
+char(o,7366).
+char(p,7367).
+char(o,7368).
+char(p,7369).
+char(9,7370).
+char(0,7371).
+char(6,7372).
+char(1,7373).
+char(m,7374).
+char(2,7375).
+char(6,7376).
+char(2,7377).
+char(5,7378).
+char(c,7379).
+char(m,7380).
+char(o,7381).
+char(m,7382).
+char(o,7383).
+char(m,7384).
+char(o,7385).
+char(m,7386).
+char(o,7387).
+char(m,7388).
+char(o,7389).
+char(m,7390).
+char(o,7391).
+char(p,7392).
+char(6,7393).
+char(2,7394).
+char(8,7395).
+char(1,7396).
+char(c,7397).
+char(c,7398).
+char(c,7399).
+char(m,7400).
+char(o,7401).
+char(p,7402).
+char(o,7403).
+char(p,7404).
+char(7,7405).
+char(9,7406).
+char(8,7407).
+char(7,7408).
+char(p,7409).
+char(o,7410).
+char(1,7411).
+char(7,7412).
+char(9,7413).
+char(4,7414).
+char(p,7415).
+char(o,7416).
+char(m,7417).
+char(2,7418).
+char(7,7419).
+char(1,7420).
+char(0,7421).
+char(c,7422).
+char(c,7423).
+char(m,7424).
+char(3,7425).
+char(1,7426).
+char(0,7427).
+char(8,7428).
+char(c,7429).
+char(p,7430).
+char(o,7431).
+char(m,7432).
+char(8,7433).
+char(6,7434).
+char(4,7435).
+char(7,7436).
+char(c,7437).
+char(m,7438).
+char(o,7439).
+char(o,7440).
+char(p,7441).
+char(8,7442).
+char(0,7443).
+char(2,7444).
+char(6,7445).
+char(p,7446).
+char(o,7447).
+char(m,7448).
+char(7,7449).
+char(8,7450).
+char(8,7451).
+char(6,7452).
+char(c,7453).
+char(c,7454).
+char(c,7455).
+char(c,7456).
+char(c,7457).
+char(c,7458).
+char(m,7459).
+char(o,7460).
+char(p,7461).
+char(o,7462).
+char(7,7463).
+char(5,7464).
+char(7,7465).
+char(0,7466).
+char(c,7467).
+char(c,7468).
+char(c,7469).
+char(m,7470).
+char(8,7471).
+char(9,7472).
+char(3,7473).
+char(4,7474).
+char(c,7475).
+char(m,7476).
+char(9,7477).
+char(8,7478).
+char(1,7479).
+char(6,7480).
+char(c,7481).
+char(p,7482).
+char(o,7483).
+char(m,7484).
+char(o,7485).
+char(p,7486).
+char(o,7487).
+char(m,7488).
+char(o,7489).
+char(m,7490).
+char(6,7491).
+char(1,7492).
+char(7,7493).
+char(6,7494).
+char(c,7495).
+char(p,7496).
+char(o,7497).
+char(p,7498).
+char(o,7499).
+char(1,7500).
+char(9,7501).
+char(7,7502).
+char(4,7503).
+char(c,7504).
+char(c,7505).
+char(c,7506).
+char(p,7507).
+char(8,7508).
+char(4,7509).
+char(6,7510).
+char(7,7511).
+char(c,7512).
+char(c,7513).
+char(m,7514).
+char(8,7515).
+char(1,7516).
+char(5,7517).
+char(9,7518).
+char(p,7519).
+char(o,7520).
+char(8,7521).
+char(4,7522).
+char(6,7523).
+char(7,7524).
+char(p,7525).
+char(4,7526).
+char(7,7527).
+char(7,7528).
+char(2,7529).
+char(p,7530).
+char(3,7531).
+char(9,7532).
+char(0,7533).
+char(4,7534).
+char(m,7535).
+char(7,7536).
+char(4,7537).
+char(1,7538).
+char(3,7539).
+char(p,7540).
+char(o,7541).
+char(m,7542).
+char(o,7543).
+char(m,7544).
+char(4,7545).
+char(5,7546).
+char(5,7547).
+char(7,7548).
+char(c,7549).
+char(p,7550).
+char(1,7551).
+char(4,7552).
+char(9,7553).
+char(4,7554).
+char(p,7555).
+char(o,7556).
+char(o,7557).
+char(p,7558).
+char(o,7559).
+char(3,7560).
+char(9,7561).
+char(8,7562).
+char(c,7563).
+char(c,7564).
+char(p,7565).
+char(o,7566).
+char(2,7567).
+char(3,7568).
+char(8,7569).
+char(8,7570).
+char(c,7571).
+char(c,7572).
+char(m,7573).
+char(o,7574).
+char(m,7575).
+char(o,7576).
+char(m,7577).
+char(o,7578).
+char(p,7579).
+char(o,7580).
+char(p,7581).
+char(o,7582).
+char(p,7583).
+char(o,7584).
+char(p,7585).
+char(o,7586).
+char(m,7587).
+char(o,7588).
+char(2,7589).
+char(9,7590).
+char(1,7591).
+char(3,7592).
+char(c,7593).
+char(c,7594).
+char(c,7595).
+char(p,7596).
+char(8,7597).
+char(8,7598).
+char(7,7599).
+char(5,7600).
+char(m,7601).
+char(o,7602).
+char(o,7603).
+char(p,7604).
+char(5,7605).
+char(9,7606).
+char(0,7607).
+char(5,7608).
+char(p,7609).
+char(o,7610).
+char(p,7611).
+char(8,7612).
+char(3,7613).
+char(5,7614).
+char(9,7615).
+char(c,7616).
+char(c,7617).
+char(c,7618).
+char(m,7619).
+char(2,7620).
+char(0,7621).
+char(1,7622).
+char(6,7623).
+char(c,7624).
+char(c,7625).
+char(c,7626).
+char(c,7627).
+char(c,7628).
+char(c,7629).
+char(p,7630).
+char(o,7631).
+char(o,7632).
+char(m,7633).
+char(o,7634).
+char(p,7635).
+char(o,7636).
+char(m,7637).
+char(2,7638).
+char(9,7639).
+char(4,7640).
+char(0,7641).
+char(m,7642).
+char(o,7643).
+char(m,7644).
+char(o,7645).
+char(6,7646).
+char(2,7647).
+char(5,7648).
+char(9,7649).
+char(c,7650).
+char(p,7651).
+char(o,7652).
+char(m,7653).
+char(o,7654).
+char(m,7655).
+char(3,7656).
+char(9,7657).
+char(7,7658).
+char(7,7659).
+char(c,7660).
+char(p,7661).
+char(o,7662).
+char(o,7663).
+char(m,7664).
+char(7,7665).
+char(0,7666).
+char(8,7667).
+char(4,7668).
+char(c,7669).
+char(c,7670).
+char(m,7671).
+char(6,7672).
+char(6,7673).
+char(4,7674).
+char(8,7675).
+char(m,7676).
+char(9,7677).
+char(7,7678).
+char(8,7679).
+char(6,7680).
+char(c,7681).
+char(p,7682).
+char(6,7683).
+char(2,7684).
+char(9,7685).
+char(5,7686).
+char(c,7687).
+char(c,7688).
+char(m,7689).
+char(8,7690).
+char(4,7691).
+char(7,7692).
+char(1,7693).
+char(m,7694).
+char(o,7695).
+char(m,7696).
+char(7,7697).
+char(2,7698).
+char(9,7699).
+char(6,7700).
+char(c,7701).
+char(p,7702).
+char(6,7703).
+char(9,7704).
+char(0,7705).
+char(0,7706).
+char(c,7707).
+char(p,7708).
+char(o,7709).
+char(p,7710).
+char(6,7711).
+char(7,7712).
+char(0,7713).
+char(9,7714).
+char(c,7715).
+char(c,7716).
+char(c,7717).
+char(c,7718).
+char(m,7719).
+char(o,7720).
+char(o,7721).
+char(m,7722).
+char(3,7723).
+char(2,7724).
+char(8,7725).
+char(2,7726).
+char(c,7727).
+char(p,7728).
+char(o,7729).
+char(7,7730).
+char(3,7731).
+char(2,7732).
+char(0,7733).
+char(c,7734).
+char(c,7735).
+char(c,7736).
+char(c,7737).
+char(c,7738).
+char(p,7739).
+char(o,7740).
+char(1,7741).
+char(3,7742).
+char(6,7743).
+char(3,7744).
+char(m,7745).
+char(o,7746).
+char(p,7747).
+char(o,7748).
+char(6,7749).
+char(6,7750).
+char(1,7751).
+char(2,7752).
+char(p,7753).
+char(7,7754).
+char(8,7755).
+char(0,7756).
+char(9,7757).
+char(c,7758).
+char(p,7759).
+char(7,7760).
+char(1,7761).
+char(6,7762).
+char(7,7763).
+char(p,7764).
+char(o,7765).
+char(o,7766).
+char(m,7767).
+char(o,7768).
+char(o,7769).
+char(m,7770).
+char(1,7771).
+char(9,7772).
+char(0,7773).
+char(8,7774).
+char(c,7775).
+char(c,7776).
+char(p,7777).
+char(o,7778).
+char(p,7779).
+char(8,7780).
+char(0,7781).
+char(0,7782).
+char(3,7783).
+char(p,7784).
+char(o,7785).
+char(m,7786).
+char(o,7787).
+char(m,7788).
+char(o,7789).
+char(m,7790).
+char(o,7791).
+char(m,7792).
+char(o,7793).
+char(m,7794).
+char(o,7795).
+char(o,7796).
+char(2,7797).
+char(3,7798).
+char(3,7799).
+char(7,7800).
+char(c,7801).
+char(p,7802).
+char(o,7803).
+char(5,7804).
+char(9,7805).
+char(1,7806).
+char(5,7807).
+char(c,7808).
+char(c,7809).
+char(p,7810).
+char(o,7811).
+char(o,7812).
+char(m,7813).
+char(o,7814).
+char(6,7815).
+char(4,7816).
+char(0,7817).
+char(5,7818).
+char(m,7819).
+char(8,7820).
+char(p,7821).
+char(3,7822).
+char(0,7823).
+char(8,7824).
+char(9,7825).
+char(c,7826).
+char(m,7827).
+char(o,7828).
+char(2,7829).
+char(7,7830).
+char(3,7831).
+char(7,7832).
+char(c,7833).
+char(c,7834).
+char(m,7835).
+char(o,7836).
+char(p,7837).
+char(o,7838).
+char(m,7839).
+char(4,7840).
+char(7,7841).
+char(2,7842).
+char(c,7843).
+char(m,7844).
+char(7,7845).
+char(6,7846).
+char(1,7847).
+char(0,7848).
+char(m,7849).
+char(o,7850).
+char(p,7851).
+char(4,7852).
+char(0,7853).
+char(9,7854).
+char(c,7855).
+char(c,7856).
+char(c,7857).
+char(m,7858).
+char(o,7859).
+char(o,7860).
+char(m,7861).
+char(3,7862).
+char(0,7863).
+char(7,7864).
+char(0,7865).
+char(c,7866).
+char(m,7867).
+char(o,7868).
+char(6,7869).
+char(0,7870).
+char(8,7871).
+char(4,7872).
+char(c,7873).
+char(m,7874).
+char(8,7875).
+char(2,7876).
+char(6,7877).
+char(0,7878).
+char(c,7879).
+char(c,7880).
+char(c,7881).
+char(c,7882).
+char(c,7883).
+char(c,7884).
+char(c,7885).
+char(p,7886).
+char(5,7887).
+char(7,7888).
+char(2,7889).
+char(1,7890).
+char(c,7891).
+char(c,7892).
+char(c,7893).
+char(p,7894).
+char(9,7895).
+char(7,7896).
+char(c,7897).
+char(p,7898).
+char(3,7899).
+char(4,7900).
+char(3,7901).
+char(7,7902).
+char(m,7903).
+char(o,7904).
+char(m,7905).
+char(o,7906).
+char(o,7907).
+char(m,7908).
+char(o,7909).
+char(1,7910).
+char(5,7911).
+char(5,7912).
+char(4,7913).
+char(p,7914).
+char(3,7915).
+char(9,7916).
+char(3,7917).
+char(m,7918).
+char(4,7919).
+char(5,7920).
+char(5,7921).
+char(6,7922).
+char(p,7923).
+char(o,7924).
+char(5,7925).
+char(6,7926).
+char(4,7927).
+char(1,7928).
+char(p,7929).
+char(9,7930).
+char(2,7931).
+char(1,7932).
+char(6,7933).
+char(m,7934).
+char(o,7935).
+char(m,7936).
+char(o,7937).
+char(m,7938).
+char(6,7939).
+char(6,7940).
+char(9,7941).
+char(p,7942).
+char(o,7943).
+char(p,7944).
+char(8,7945).
+char(5,7946).
+char(8,7947).
+char(2,7948).
+char(m,7949).
+char(o,7950).
+char(o,7951).
+char(o,7952).
+char(m,7953).
+char(o,7954).
+char(m,7955).
+char(1,7956).
+char(1,7957).
+char(3,7958).
+char(8,7959).
+char(m,7960).
+char(o,7961).
+char(o,7962).
+char(p,7963).
+char(8,7964).
+char(6,7965).
+char(3,7966).
+char(1,7967).
+char(p,7968).
+char(o,7969).
+char(m,7970).
+char(o,7971).
+char(5,7972).
+char(2,7973).
+char(7,7974).
+char(m,7975).
+char(o,7976).
+char(m,7977).
+char(o,7978).
+char(m,7979).
+char(3,7980).
+char(5,7981).
+char(4,7982).
+char(9,7983).
+char(c,7984).
+char(m,7985).
+char(o,7986).
+char(m,7987).
+char(2,7988).
+char(0,7989).
+char(6,7990).
+char(9,7991).
+char(p,7992).
+char(9,7993).
+char(8,7994).
+char(5,7995).
+char(8,7996).
+char(m,7997).
+char(7,7998).
+char(4,7999).
+char(1,8000).
+char(5,8001).
+char(p,8002).
+char(o,8003).
+char(m,8004).
+char(6,8005).
+char(4,8006).
+char(9,8007).
+char(6,8008).
+char(p,8009).
+char(3,8010).
+char(5,8011).
+char(4,8012).
+char(1,8013).
+char(c,8014).
+char(p,8015).
+char(o,8016).
+char(p,8017).
+char(3,8018).
+char(2,8019).
+char(4,8020).
+char(4,8021).
+char(c,8022).
+char(m,8023).
+char(o,8024).
+char(p,8025).
+char(7,8026).
+char(8,8027).
+char(6,8028).
+char(3,8029).
+char(p,8030).
+char(9,8031).
+char(9,8032).
+char(0,8033).
+char(5,8034).
+char(c,8035).
+char(m,8036).
+char(6,8037).
+char(7,8038).
+char(6,8039).
+char(9,8040).
+char(p,8041).
+char(7,8042).
+char(8,8043).
+char(0,8044).
+char(7,8045).
+char(c,8046).
+char(c,8047).
+char(c,8048).
+char(p,8049).
+char(o,8050).
+char(9,8051).
+char(1,8052).
+char(9,8053).
+char(2,8054).
+char(c,8055).
+char(c,8056).
+char(m,8057).
+char(2,8058).
+char(9,8059).
+char(0,8060).
+char(8,8061).
+char(c,8062).
+char(p,8063).
+char(o,8064).
+char(p,8065).
+char(o,8066).
+char(3,8067).
+char(6,8068).
+char(2,8069).
+char(4,8070).
+char(m,8071).
+char(9,8072).
+char(7,8073).
+char(0,8074).
+char(1,8075).
+char(p,8076).
+char(o,8077).
+char(m,8078).
+char(1,8079).
+char(8,8080).
+char(7,8081).
+char(1,8082).
+char(c,8083).
+char(c,8084).
+char(c,8085).
+char(c,8086).
+char(c,8087).
+char(c,8088).
+char(p,8089).
+char(o,8090).
+char(o,8091).
+char(m,8092).
+char(o,8093).
+char(p,8094).
+char(o,8095).
+char(p,8096).
+char(o,8097).
+char(o,8098).
+char(m,8099).
+char(5,8100).
+char(1,8101).
+char(9,8102).
+char(8,8103).
+char(m,8104).
+char(o,8105).
+char(p,8106).
+char(o,8107).
+char(m,8108).
+char(5,8109).
+char(7,8110).
+char(2,8111).
+char(0,8112).
+char(c,8113).
+char(m,8114).
+char(o,8115).
+char(4,8116).
+char(4,8117).
+char(4,8118).
+char(7,8119).
+char(c,8120).
+char(p,8121).
+char(o,8122).
+char(5,8123).
+char(7,8124).
+char(4,8125).
+char(5,8126).
+char(c,8127).
+char(c,8128).
+char(c,8129).
+char(p,8130).
+char(4,8131).
+char(8,8132).
+char(6,8133).
+char(1,8134).
+char(m,8135).
+char(o,8136).
+char(m,8137).
+char(1,8138).
+char(0,8139).
+char(3,8140).
+char(5,8141).
+char(m,8142).
+char(o,8143).
+char(m,8144).
+char(2,8145).
+char(8,8146).
+char(c,8147).
+char(c,8148).
+char(c,8149).
+char(c,8150).
+char(c,8151).
+char(c,8152).
+char(p,8153).
+char(3,8154).
+char(4,8155).
+char(4,8156).
+char(p,8157).
+char(o,8158).
+char(m,8159).
+char(o,8160).
+char(p,8161).
+char(o,8162).
+char(3,8163).
+char(1,8164).
+char(2,8165).
+char(5,8166).
+char(p,8167).
+char(o,8168).
+char(p,8169).
+char(7,8170).
+char(0,8171).
+char(1,8172).
+char(1,8173).
+char(c,8174).
+char(p,8175).
+char(o,8176).
+char(p,8177).
+char(o,8178).
+char(o,8179).
+char(3,8180).
+char(4,8181).
+char(6,8182).
+char(2,8183).
+char(c,8184).
+char(p,8185).
+char(7,8186).
+char(6,8187).
+char(0,8188).
+char(4,8189).
+char(p,8190).
+char(o,8191).
+char(m,8192).
+char(o,8193).
+char(p,8194).
+char(1,8195).
+char(5,8196).
+char(7,8197).
+char(1,8198).
+char(m,8199).
+char(4,8200).
+char(2,8201).
+char(5,8202).
+char(5,8203).
+char(c,8204).
+char(p,8205).
+char(7,8206).
+char(7,8207).
+char(0,8208).
+char(9,8209).
+char(c,8210).
+char(c,8211).
+char(p,8212).
+char(o,8213).
+char(p,8214).
+char(o,8215).
+char(p,8216).
+char(6,8217).
+char(8,8218).
+char(2,8219).
+char(8,8220).
+char(p,8221).
+char(o,8222).
+char(1,8223).
+char(8,8224).
+char(4,8225).
+char(3,8226).
+char(c,8227).
+char(m,8228).
+char(o,8229).
+char(2,8230).
+char(0,8231).
+char(5,8232).
+char(9,8233).
+char(m,8234).
+char(o,8235).
+char(p,8236).
+char(o,8237).
+char(m,8238).
+char(9,8239).
+char(9,8240).
+char(7,8241).
+char(2,8242).
+char(m,8243).
+char(o,8244).
+char(m,8245).
+char(o,8246).
+char(o,8247).
+char(7,8248).
+char(6,8249).
+char(2,8250).
+char(9,8251).
+char(c,8252).
+char(c,8253).
+char(c,8254).
+char(c,8255).
+char(c,8256).
+char(c,8257).
+char(c,8258).
+char(m,8259).
+char(9,8260).
+char(6,8261).
+char(0,8262).
+char(6,8263).
+char(c,8264).
+char(c,8265).
+char(p,8266).
+char(2,8267).
+char(8,8268).
+char(0,8269).
+char(4,8270).
+char(m,8271).
+char(o,8272).
+char(o,8273).
+char(p,8274).
+char(3,8275).
+char(2,8276).
+char(8,8277).
+char(5,8278).
+char(m,8279).
+char(5,8280).
+char(0,8281).
+char(6,8282).
+char(2,8283).
+char(p,8284).
+char(8,8285).
+char(3,8286).
+char(8,8287).
+char(8,8288).
+char(p,8289).
+char(2,8290).
+char(0,8291).
+char(9,8292).
+char(6,8293).
+char(c,8294).
+char(p,8295).
+char(5,8296).
+char(9,8297).
+char(5,8298).
+char(7,8299).
+char(p,8300).
+char(1,8301).
+char(4,8302).
+char(1,8303).
+char(3,8304).
+char(c,8305).
+char(c,8306).
+char(m,8307).
+char(4,8308).
+char(3,8309).
+char(1,8310).
+char(2,8311).
+char(c,8312).
+char(m,8313).
+char(7,8314).
+char(6,8315).
+char(3,8316).
+char(7,8317).
+char(p,8318).
+char(o,8319).
+char(m,8320).
+char(o,8321).
+char(p,8322).
+char(o,8323).
+char(m,8324).
+char(o,8325).
+char(p,8326).
+char(9,8327).
+char(9,8328).
+char(8,8329).
+char(2,8330).
+char(m,8331).
+char(o,8332).
+char(m,8333).
+char(o,8334).
+char(6,8335).
+char(7,8336).
+char(4,8337).
+char(0,8338).
+char(m,8339).
+char(2,8340).
+char(9,8341).
+char(7,8342).
+char(7,8343).
+char(c,8344).
+char(m,8345).
+char(8,8346).
+char(3,8347).
+char(0,8348).
+char(2,8349).
+char(p,8350).
+char(o,8351).
+char(p,8352).
+char(4,8353).
+char(6,8354).
+char(1,8355).
+char(p,8356).
+char(1,8357).
+char(8,8358).
+char(6,8359).
+char(m,8360).
+char(6,8361).
+char(7,8362).
+char(8,8363).
+char(6,8364).
+char(c,8365).
+char(c,8366).
+char(c,8367).
+char(c,8368).
+char(m,8369).
+char(o,8370).
+char(2,8371).
+char(1,8372).
+char(0,8373).
+char(4,8374).
+char(p,8375).
+char(4,8376).
+char(7,8377).
+char(9,8378).
+char(5,8379).
+char(c,8380).
+char(c,8381).
+char(p,8382).
+char(o,8383).
+char(m,8384).
+char(1,8385).
+char(2,8386).
+char(0,8387).
+char(0,8388).
+char(c,8389).
+char(c,8390).
+char(c,8391).
+char(c,8392).
+char(c,8393).
+char(c,8394).
+char(p,8395).
+char(o,8396).
+char(p,8397).
+char(5,8398).
+char(2,8399).
+char(1,8400).
+char(7,8401).
+char(m,8402).
+char(4,8403).
+char(5,8404).
+char(1,8405).
+char(0,8406).
+char(c,8407).
+char(p,8408).
+char(2,8409).
+char(9,8410).
+char(4,8411).
+char(c,8412).
+char(c,8413).
+char(m,8414).
+char(6,8415).
+char(7,8416).
+char(4,8417).
+char(8,8418).
+char(c,8419).
+char(c,8420).
+char(p,8421).
+char(o,8422).
+char(m,8423).
+char(7,8424).
+char(4,8425).
+char(7,8426).
+char(9,8427).
+char(c,8428).
+char(m,8429).
+char(o,8430).
+char(1,8431).
+char(8,8432).
+char(3,8433).
+char(4,8434).
+char(c,8435).
+char(m,8436).
+char(o,8437).
+char(p,8438).
+char(3,8439).
+char(8,8440).
+char(1,8441).
+char(9,8442).
+char(c,8443).
+char(c,8444).
+char(m,8445).
+char(2,8446).
+char(5,8447).
+char(8,8448).
+char(0,8449).
+char(m,8450).
+char(8,8451).
+char(3,8452).
+char(1,8453).
+char(6,8454).
+char(m,8455).
+char(o,8456).
+char(p,8457).
+char(5,8458).
+char(4,8459).
+char(4,8460).
+char(8,8461).
+char(p,8462).
+char(6,8463).
+char(1,8464).
+char(0,8465).
+char(5,8466).
+char(c,8467).
+char(c,8468).
+char(p,8469).
+char(3,8470).
+char(3,8471).
+char(8,8472).
+char(4,8473).
+char(m,8474).
+char(o,8475).
+char(o,8476).
+char(p,8477).
+char(3,8478).
+char(2,8479).
+char(9,8480).
+char(5,8481).
+char(c,8482).
+char(c,8483).
+char(c,8484).
+char(c,8485).
+char(p,8486).
+char(9,8487).
+char(4,8488).
+char(7,8489).
+char(5,8490).
+char(c,8491).
+char(c,8492).
+char(p,8493).
+char(4,8494).
+char(1,8495).
+char(5,8496).
+char(6,8497).
+char(m,8498).
+char(4,8499).
+char(9,8500).
+char(3,8501).
+char(3,8502).
+char(c,8503).
+char(m,8504).
+char(o,8505).
+char(p,8506).
+char(o,8507).
+char(o,8508).
+char(p,8509).
+char(6,8510).
+char(4,8511).
+char(4,8512).
+char(9,8513).
+char(c,8514).
+char(c,8515).
+char(p,8516).
+char(4,8517).
+char(9,8518).
+char(7,8519).
+char(8,8520).
+char(c,8521).
+char(m,8522).
+char(o,8523).
+char(m,8524).
+char(7,8525).
+char(9,8526).
+char(5,8527).
+char(c,8528).
+char(c,8529).
+char(m,8530).
+char(3,8531).
+char(9,8532).
+char(8,8533).
+char(2,8534).
+char(m,8535).
+char(6,8536).
+char(0,8537).
+char(1,8538).
+char(7,8539).
+char(m,8540).
+char(6,8541).
+char(6,8542).
+char(4,8543).
+char(3,8544).
+char(p,8545).
+char(o,8546).
+char(m,8547).
+char(o,8548).
+char(p,8549).
+char(o,8550).
+char(7,8551).
+char(6,8552).
+char(1,8553).
+char(7,8554).
+char(p,8555).
+char(8,8556).
+char(3,8557).
+char(0,8558).
+char(6,8559).
+char(c,8560).
+char(c,8561).
+char(m,8562).
+char(o,8563).
+char(5,8564).
+char(3,8565).
+char(7,8566).
+char(0,8567).
+char(p,8568).
+char(o,8569).
+char(4,8570).
+char(8,8571).
+char(1,8572).
+char(6,8573).
+char(c,8574).
+char(p,8575).
+char(o,8576).
+char(p,8577).
+char(6,8578).
+char(6,8579).
+char(5,8580).
+char(4,8581).
+char(p,8582).
+char(o,8583).
+char(m,8584).
+char(o,8585).
+char(m,8586).
+char(o,8587).
+char(m,8588).
+char(o,8589).
+char(p,8590).
+char(o,8591).
+char(m,8592).
+char(o,8593).
+char(m,8594).
+char(o,8595).
+char(m,8596).
+char(8,8597).
+char(2,8598).
+char(6,8599).
+char(0,8600).
+char(c,8601).
+char(c,8602).
+char(m,8603).
+char(5,8604).
+char(6,8605).
+char(8,8606).
+char(2,8607).
+char(c,8608).
+char(c,8609).
+char(c,8610).
+char(c,8611).
+char(c,8612).
+char(m,8613).
+char(9,8614).
+char(8,8615).
+char(7,8616).
+char(8,8617).
+char(c,8618).
+char(m,8619).
+char(3,8620).
+char(5,8621).
+char(5,8622).
+char(6,8623).
+char(c,8624).
+char(c,8625).
+char(m,8626).
+char(o,8627).
+char(o,8628).
+char(o,8629).
+char(m,8630).
+char(8,8631).
+char(3,8632).
+char(6,8633).
+char(3,8634).
+char(m,8635).
+char(6,8636).
+char(2,8637).
+char(9,8638).
+char(0,8639).
+char(p,8640).
+char(o,8641).
+char(p,8642).
+char(o,8643).
+char(p,8644).
+char(8,8645).
+char(5,8646).
+char(3,8647).
+char(3,8648).
+char(c,8649).
+char(m,8650).
+char(o,8651).
+char(p,8652).
+char(o,8653).
+char(m,8654).
+char(9,8655).
+char(2,8656).
+char(0,8657).
+char(0,8658).
+char(m,8659).
+char(o,8660).
+char(o,8661).
+char(m,8662).
+char(8,8663).
+char(8,8664).
+char(5,8665).
+char(9,8666).
+char(p,8667).
+char(5,8668).
+char(5,8669).
+char(5,8670).
+char(8,8671).
+char(c,8672).
+char(m,8673).
+char(2,8674).
+char(0,8675).
+char(2,8676).
+char(8,8677).
+char(m,8678).
+char(1,8679).
+char(6,8680).
+char(1,8681).
+char(2,8682).
+char(c,8683).
+char(m,8684).
+char(o,8685).
+char(3,8686).
+char(4,8687).
+char(5,8688).
+char(5,8689).
+char(c,8690).
+char(p,8691).
+char(o,8692).
+char(o,8693).
+char(p,8694).
+char(o,8695).
+char(o,8696).
+char(m,8697).
+char(8,8698).
+char(0,8699).
+char(8,8700).
+char(7,8701).
+char(p,8702).
+char(5,8703).
+char(0,8704).
+char(9,8705).
+char(3,8706).
+char(m,8707).
+char(7,8708).
+char(3,8709).
+char(6,8710).
+char(5,8711).
+char(p,8712).
+char(8,8713).
+char(6,8714).
+char(1,8715).
+char(0,8716).
+char(c,8717).
+char(p,8718).
+char(o,8719).
+char(m,8720).
+char(o,8721).
+char(5,8722).
+char(5,8723).
+char(5,8724).
+char(7,8725).
+char(m,8726).
+char(o,8727).
+char(m,8728).
+char(o,8729).
+char(p,8730).
+char(2,8731).
+char(2,8732).
+char(3,8733).
+char(6,8734).
+char(c,8735).
+char(c,8736).
+char(c,8737).
+char(c,8738).
+char(c,8739).
+char(m,8740).
+char(o,8741).
+char(o,8742).
+char(8,8743).
+char(4,8744).
+char(4,8745).
+char(0,8746).
+char(p,8747).
+char(4,8748).
+char(9,8749).
+char(9,8750).
+char(3,8751).
+char(p,8752).
+char(o,8753).
+char(p,8754).
+char(o,8755).
+char(9,8756).
+char(5,8757).
+char(8,8758).
+char(6,8759).
+char(c,8760).
+char(c,8761).
+char(p,8762).
+char(9,8763).
+char(2,8764).
+char(9,8765).
+char(4,8766).
+char(c,8767).
+char(c,8768).
+char(c,8769).
+char(c,8770).
+char(c,8771).
+char(p,8772).
+char(o,8773).
+char(m,8774).
+char(3,8775).
+char(5,8776).
+char(8,8777).
+char(9,8778).
+char(c,8779).
+char(m,8780).
+char(1,8781).
+char(2,8782).
+char(4,8783).
+char(0,8784).
+char(p,8785).
+char(9,8786).
+char(7,8787).
+char(3,8788).
+char(1,8789).
+char(m,8790).
+char(o,8791).
+char(m,8792).
+char(o,8793).
+char(m,8794).
+char(7,8795).
+char(9,8796).
+char(3,8797).
+char(7,8798).
+char(p,8799).
+char(o,8800).
+char(o,8801).
+char(p,8802).
+char(4,8803).
+char(3,8804).
+char(6,8805).
+char(4,8806).
+char(p,8807).
+char(5,8808).
+char(7,8809).
+char(7,8810).
+char(1,8811).
+char(c,8812).
+char(p,8813).
+char(o,8814).
+char(o,8815).
+char(p,8816).
+char(9,8817).
+char(7,8818).
+char(4,8819).
+char(8,8820).
+char(c,8821).
+char(p,8822).
+char(o,8823).
+char(3,8824).
+char(7,8825).
+char(0,8826).
+char(9,8827).
+char(m,8828).
+char(8,8829).
+char(6,8830).
+char(3,8831).
+char(1,8832).
+char(c,8833).
+char(c,8834).
+char(c,8835).
+char(c,8836).
+char(c,8837).
+char(c,8838).
+char(c,8839).
+char(p,8840).
+char(o,8841).
+char(7,8842).
+char(3,8843).
+char(0,8844).
+char(3,8845).
+char(c,8846).
+char(c,8847).
+char(c,8848).
+char(c,8849).
+char(m,8850).
+char(o,8851).
+char(p,8852).
+char(3,8853).
+char(2,8854).
+char(9,8855).
+char(0,8856).
+char(p,8857).
+char(6,8858).
+char(3,8859).
+char(5,8860).
+char(m,8861).
+char(3,8862).
+char(9,8863).
+char(6,8864).
+char(9,8865).
+char(c,8866).
+char(c,8867).
+char(m,8868).
+char(3,8869).
+char(0,8870).
+char(2,8871).
+char(8,8872).
+char(m,8873).
+char(6,8874).
+char(5,8875).
+char(9,8876).
+char(5,8877).
+char(c,8878).
+char(m,8879).
+char(9,8880).
+char(4,8881).
+char(9,8882).
+char(4,8883).
+char(m,8884).
+char(o,8885).
+char(o,8886).
+char(p,8887).
+char(o,8888).
+char(5,8889).
+char(6,8890).
+char(5,8891).
+char(4,8892).
+char(c,8893).
+char(c,8894).
+char(m,8895).
+char(o,8896).
+char(3,8897).
+char(2,8898).
+char(6,8899).
+char(8,8900).
+char(p,8901).
+char(8,8902).
+char(3,8903).
+char(2,8904).
+char(7,8905).
+char(c,8906).
+char(m,8907).
+char(o,8908).
+char(p,8909).
+char(1,8910).
+char(3,8911).
+char(1,8912).
+char(0,8913).
+char(c,8914).
+char(c,8915).
+char(m,8916).
+char(1,8917).
+char(0,8918).
+char(8,8919).
+char(5,8920).
+char(p,8921).
+char(1,8922).
+char(0,8923).
+char(8,8924).
+char(5,8925).
+char(p,8926).
+char(2,8927).
+char(9,8928).
+char(3,8929).
+char(0,8930).
+char(m,8931).
+char(o,8932).
+char(p,8933).
+char(1,8934).
+char(3,8935).
+char(2,8936).
+char(4,8937).
+char(p,8938).
+char(o,8939).
+char(p,8940).
+char(5,8941).
+char(7,8942).
+char(0,8943).
+char(6,8944).
+char(p,8945).
+char(o,8946).
+char(o,8947).
+char(o,8948).
+char(p,8949).
+char(o,8950).
+char(9,8951).
+char(7,8952).
+char(3,8953).
+char(5,8954).
+char(c,8955).
+char(p,8956).
+char(o,8957).
+char(p,8958).
+char(o,8959).
+char(o,8960).
+char(p,8961).
+char(o,8962).
+char(m,8963).
+char(5,8964).
+char(9,8965).
+char(9,8966).
+char(4,8967).
+char(c,8968).
+char(c,8969).
+char(p,8970).
+char(6,8971).
+char(4,8972).
+char(4,8973).
+char(6,8974).
+char(c,8975).
+char(m,8976).
+char(o,8977).
+char(p,8978).
+char(6,8979).
+char(6,8980).
+char(8,8981).
+char(5,8982).
+char(m,8983).
+char(o,8984).
+char(9,8985).
+char(7,8986).
+char(6,8987).
+char(8,8988).
+char(c,8989).
+char(m,8990).
+char(9,8991).
+char(7,8992).
+char(5,8993).
+char(4,8994).
+char(p,8995).
+char(8,8996).
+char(8,8997).
+char(0,8998).
+char(0,8999).
+char(p,9000).
+char(o,9001).
+char(m,9002).
+char(o,9003).
+char(p,9004).
+char(2,9005).
+char(9,9006).
+char(2,9007).
+char(7,9008).
+char(m,9009).
+char(6,9010).
+char(8,9011).
+char(9,9012).
+char(4,9013).
+char(c,9014).
+char(c,9015).
+char(m,9016).
+char(o,9017).
+char(9,9018).
+char(5,9019).
+char(9,9020).
+char(8,9021).
+char(c,9022).
+char(c,9023).
+char(c,9024).
+char(c,9025).
+char(m,9026).
+char(9,9027).
+char(2,9028).
+char(4,9029).
+char(6,9030).
+char(c,9031).
+char(m,9032).
+char(1,9033).
+char(0,9034).
+char(6,9035).
+char(3,9036).
+char(p,9037).
+char(o,9038).
+char(p,9039).
+char(6,9040).
+char(5,9041).
+char(8,9042).
+char(2,9043).
+char(c,9044).
+char(m,9045).
+char(1,9046).
+char(3,9047).
+char(2,9048).
+char(p,9049).
+char(7,9050).
+char(1,9051).
+char(8,9052).
+char(9,9053).
+char(c,9054).
+char(c,9055).
+char(c,9056).
+char(c,9057).
+char(m,9058).
+char(7,9059).
+char(6,9060).
+char(7,9061).
+char(c,9062).
+char(p,9063).
+char(3,9064).
+char(2,9065).
+char(2,9066).
+char(6,9067).
+char(p,9068).
+char(6,9069).
+char(5,9070).
+char(2,9071).
+char(1,9072).
+char(p,9073).
+char(o,9074).
+char(o,9075).
+char(m,9076).
+char(o,9077).
+char(p,9078).
+char(9,9079).
+char(6,9080).
+char(6,9081).
+char(8,9082).
+char(c,9083).
+char(c,9084).
+char(m,9085).
+char(8,9086).
+char(3,9087).
+char(1,9088).
+char(1,9089).
+char(p,9090).
+char(o,9091).
+char(m,9092).
+char(5,9093).
+char(4,9094).
+char(4,9095).
+char(5,9096).
+char(c,9097).
+char(c,9098).
+char(m,9099).
+char(8,9100).
+char(4,9101).
+char(5,9102).
+char(3,9103).
+char(m,9104).
+char(3,9105).
+char(0,9106).
+char(5,9107).
+char(8,9108).
+char(c,9109).
+char(m,9110).
+char(6,9111).
+char(6,9112).
+char(9,9113).
+char(c,9114).
+char(m,9115).
+char(o,9116).
+char(6,9117).
+char(0,9118).
+char(6,9119).
+char(8,9120).
+char(m,9121).
+char(1,9122).
+char(2,9123).
+char(6,9124).
+char(7,9125).
+char(c,9126).
+char(c,9127).
+char(c,9128).
+char(c,9129).
+char(c,9130).
+char(p,9131).
+char(o,9132).
+char(m,9133).
+char(o,9134).
+char(p,9135).
+char(o,9136).
+char(9,9137).
+char(3,9138).
+char(4,9139).
+char(2,9140).
+char(p,9141).
+char(o,9142).
+char(p,9143).
+char(5,9144).
+char(3,9145).
+char(8,9146).
+char(1,9147).
+char(c,9148).
+char(c,9149).
+char(c,9150).
+char(p,9151).
+char(5,9152).
+char(3,9153).
+char(0,9154).
+char(9,9155).
+char(p,9156).
+char(o,9157).
+char(m,9158).
+char(o,9159).
+char(3,9160).
+char(5,9161).
+char(8,9162).
+char(4,9163).
+char(p,9164).
+char(4,9165).
+char(1,9166).
+char(9,9167).
+char(p,9168).
+char(4,9169).
+char(7,9170).
+char(7,9171).
+char(3,9172).
+char(c,9173).
+char(c,9174).
+char(p,9175).
+char(9,9176).
+char(4,9177).
+char(8,9178).
+char(2,9179).
+char(m,9180).
+char(o,9181).
+char(m,9182).
+char(6,9183).
+char(0,9184).
+char(1,9185).
+char(8,9186).
+char(m,9187).
+char(o,9188).
+char(p,9189).
+char(o,9190).
+char(p,9191).
+char(3,9192).
+char(8,9193).
+char(4,9194).
+char(6,9195).
+char(c,9196).
+char(c,9197).
+char(c,9198).
+char(m,9199).
+char(o,9200).
+char(m,9201).
+char(o,9202).
+char(p,9203).
+char(o,9204).
+char(p,9205).
+char(7,9206).
+char(9,9207).
+char(1,9208).
+char(0,9209).
+char(p,9210).
+char(o,9211).
+char(p,9212).
+char(o,9213).
+char(m,9214).
+char(o,9215).
+char(o,9216).
+char(p,9217).
+char(o,9218).
+char(m,9219).
+char(2,9220).
+char(3,9221).
+char(4,9222).
+char(6,9223).
+char(m,9224).
+char(4,9225).
+char(5,9226).
+char(9,9227).
+char(7,9228).
+char(m,9229).
+char(o,9230).
+char(7,9231).
+char(0,9232).
+char(4,9233).
+char(7,9234).
+char(m,9235).
+char(o,9236).
+char(m,9237).
+char(9,9238).
+char(6,9239).
+char(2,9240).
+char(2,9241).
+char(p,9242).
+char(o,9243).
+char(p,9244).
+char(2,9245).
+char(9,9246).
+char(2,9247).
+char(4,9248).
+char(p,9249).
+char(5,9250).
+char(3,9251).
+char(8,9252).
+char(0,9253).
+char(c,9254).
+char(c,9255).
+char(p,9256).
+char(3,9257).
+char(8,9258).
+char(7,9259).
+char(1,9260).
+char(m,9261).
+char(5,9262).
+char(4,9263).
+char(8,9264).
+char(0,9265).
+char(c,9266).
+char(c,9267).
+char(p,9268).
+char(o,9269).
+char(o,9270).
+char(m,9271).
+char(o,9272).
+char(m,9273).
+char(o,9274).
+char(2,9275).
+char(4,9276).
+char(7,9277).
+char(1,9278).
+char(c,9279).
+char(c,9280).
+char(c,9281).
+char(c,9282).
+char(p,9283).
+char(6,9284).
+char(1,9285).
+char(5,9286).
+char(1,9287).
+char(m,9288).
+char(o,9289).
+char(m,9290).
+char(o,9291).
+char(o,9292).
+char(9,9293).
+char(7,9294).
+char(5,9295).
+char(p,9296).
+char(3,9297).
+char(4,9298).
+char(6,9299).
+char(3,9300).
+char(c,9301).
+char(c,9302).
+char(p,9303).
+char(7,9304).
+char(5,9305).
+char(8,9306).
+char(2,9307).
+char(c,9308).
+char(p,9309).
+char(o,9310).
+char(4,9311).
+char(3,9312).
+char(9,9313).
+char(5,9314).
+char(c,9315).
+char(m,9316).
+char(o,9317).
+char(o,9318).
+char(m,9319).
+char(o,9320).
+char(m,9321).
+char(o,9322).
+char(p,9323).
+char(o,9324).
+char(m,9325).
+char(o,9326).
+char(m,9327).
+char(o,9328).
+char(o,9329).
+char(o,9330).
+char(6,9331).
+char(5,9332).
+char(9,9333).
+char(9,9334).
+char(c,9335).
+char(p,9336).
+char(6,9337).
+char(3,9338).
+char(5,9339).
+char(8,9340).
+char(c,9341).
+char(m,9342).
+char(5,9343).
+char(9,9344).
+char(0,9345).
+char(p,9346).
+char(o,9347).
+char(m,9348).
+char(3,9349).
+char(5,9350).
+char(8,9351).
+char(3,9352).
+char(c,9353).
+char(c,9354).
+char(p,9355).
+char(7,9356).
+char(9,9357).
+char(4,9358).
+char(4,9359).
+char(p,9360).
+char(o,9361).
+char(m,9362).
+char(7,9363).
+char(7,9364).
+char(7,9365).
+char(7,9366).
+char(m,9367).
+char(2,9368).
+char(8,9369).
+char(5,9370).
+char(9,9371).
+char(c,9372).
+char(c,9373).
+char(c,9374).
+char(p,9375).
+char(o,9376).
+char(p,9377).
+char(o,9378).
+char(p,9379).
+char(o,9380).
+char(p,9381).
+char(9,9382).
+char(2,9383).
+char(2,9384).
+char(1,9385).
+char(c,9386).
+char(c,9387).
+char(c,9388).
+char(p,9389).
+char(o,9390).
+char(o,9391).
+char(m,9392).
+char(1,9393).
+char(1,9394).
+char(7,9395).
+char(8,9396).
+char(p,9397).
+char(8,9398).
+char(2,9399).
+char(0,9400).
+char(8,9401).
+char(c,9402).
+char(c,9403).
+char(p,9404).
+char(4,9405).
+char(1,9406).
+char(4,9407).
+char(0,9408).
+char(m,9409).
+char(o,9410).
+char(p,9411).
+char(o,9412).
+char(m,9413).
+char(o,9414).
+char(m,9415).
+char(o,9416).
+char(m,9417).
+char(o,9418).
+char(9,9419).
+char(8,9420).
+char(3,9421).
+char(6,9422).
+char(c,9423).
+char(p,9424).
+char(o,9425).
+char(5,9426).
+char(6,9427).
+char(6,9428).
+char(9,9429).
+char(c,9430).
+char(p,9431).
+char(4,9432).
+char(3,9433).
+char(8,9434).
+char(m,9435).
+char(5,9436).
+char(6,9437).
+char(7,9438).
+char(0,9439).
+char(p,9440).
+char(7,9441).
+char(4,9442).
+char(6,9443).
+char(6,9444).
+char(m,9445).
+char(o,9446).
+char(m,9447).
+char(o,9448).
+char(m,9449).
+char(7,9450).
+char(2,9451).
+char(7,9452).
+char(9,9453).
+char(m,9454).
+char(8,9455).
+char(4,9456).
+char(6,9457).
+char(9,9458).
+char(c,9459).
+char(c,9460).
+char(c,9461).
+char(p,9462).
+char(o,9463).
+char(m,9464).
+char(o,9465).
+char(o,9466).
+char(p,9467).
+char(6,9468).
+char(9,9469).
+char(3,9470).
+char(2,9471).
+char(p,9472).
+char(o,9473).
+char(o,9474).
+char(p,9475).
+char(4,9476).
+char(9,9477).
+char(8,9478).
+char(5,9479).
+char(p,9480).
+char(o,9481).
+char(m,9482).
+char(4,9483).
+char(0,9484).
+char(6,9485).
+char(8,9486).
+char(p,9487).
+char(o,9488).
+char(o,9489).
+char(9,9490).
+char(9,9491).
+char(7,9492).
+char(2,9493).
+char(p,9494).
+char(1,9495).
+char(4,9496).
+char(2,9497).
+char(2,9498).
+char(m,9499).
+char(o,9500).
+char(m,9501).
+char(o,9502).
+char(p,9503).
+char(4,9504).
+char(5,9505).
+char(1,9506).
+char(3,9507).
+char(m,9508).
+char(o,9509).
+char(m,9510).
+char(8,9511).
+char(4,9512).
+char(0,9513).
+char(1,9514).
+char(m,9515).
+char(o,9516).
+char(m,9517).
+char(1,9518).
+char(8,9519).
+char(4,9520).
+char(7,9521).
+char(c,9522).
+char(c,9523).
+char(c,9524).
+char(c,9525).
+char(c,9526).
+char(p,9527).
+char(2,9528).
+char(2,9529).
+char(4,9530).
+char(8,9531).
+char(p,9532).
+char(o,9533).
+char(m,9534).
+char(3,9535).
+char(8,9536).
+char(2,9537).
+char(8,9538).
+char(p,9539).
+char(4,9540).
+char(2,9541).
+char(7,9542).
+char(0,9543).
+char(c,9544).
+char(c,9545).
+char(m,9546).
+char(2,9547).
+char(8,9548).
+char(4,9549).
+char(0,9550).
+char(p,9551).
+char(3,9552).
+char(8,9553).
+char(7,9554).
+char(1,9555).
+char(c,9556).
+char(c,9557).
+char(c,9558).
+char(p,9559).
+char(o,9560).
+char(p,9561).
+char(o,9562).
+char(m,9563).
+char(o,9564).
+char(3,9565).
+char(1,9566).
+char(0,9567).
+char(3,9568).
+char(c,9569).
+char(c,9570).
+char(m,9571).
+char(o,9572).
+char(m,9573).
+char(8,9574).
+char(1,9575).
+char(5,9576).
+char(7,9577).
+char(m,9578).
+char(o,9579).
+char(p,9580).
+char(o,9581).
+char(p,9582).
+char(o,9583).
+char(p,9584).
+char(3,9585).
+char(5,9586).
+char(8,9587).
+char(7,9588).
+char(p,9589).
+char(o,9590).
+char(o,9591).
+char(p,9592).
+char(6,9593).
+char(4,9594).
+char(2,9595).
+char(1,9596).
+char(c,9597).
+char(m,9598).
+char(4,9599).
+char(1,9600).
+char(1,9601).
+char(2,9602).
+char(c,9603).
+char(m,9604).
+char(9,9605).
+char(1,9606).
+char(3,9607).
+char(8,9608).
+char(p,9609).
+char(o,9610).
+char(p,9611).
+char(o,9612).
+char(o,9613).
+char(m,9614).
+char(o,9615).
+char(p,9616).
+char(6,9617).
+char(6,9618).
+char(1,9619).
+char(7,9620).
+char(c,9621).
+char(p,9622).
+char(o,9623).
+char(o,9624).
+char(m,9625).
+char(1,9626).
+char(1,9627).
+char(0,9628).
+char(9,9629).
+char(p,9630).
+char(1,9631).
+char(0,9632).
+char(m,9633).
+char(o,9634).
+char(p,9635).
+char(o,9636).
+char(m,9637).
+char(o,9638).
+char(7,9639).
+char(4,9640).
+char(6,9641).
+char(2,9642).
+char(m,9643).
+char(3,9644).
+char(0,9645).
+char(7,9646).
+char(7,9647).
+char(c,9648).
+char(c,9649).
+char(c,9650).
+char(c,9651).
+char(m,9652).
+char(o,9653).
+char(p,9654).
+char(1,9655).
+char(7,9656).
+char(6,9657).
+char(8,9658).
+char(p,9659).
+char(o,9660).
+char(m,9661).
+char(8,9662).
+char(0,9663).
+char(8,9664).
+char(7,9665).
+char(p,9666).
+char(9,9667).
+char(6,9668).
+char(4,9669).
+char(1,9670).
+char(m,9671).
+char(6,9672).
+char(2,9673).
+char(3,9674).
+char(1,9675).
+char(c,9676).
+char(c,9677).
+char(p,9678).
+char(8,9679).
+char(7,9680).
+char(9,9681).
+char(1,9682).
+char(c,9683).
+char(p,9684).
+char(o,9685).
+char(p,9686).
+char(3,9687).
+char(0,9688).
+char(6,9689).
+char(2,9690).
+char(m,9691).
+char(o,9692).
+char(p,9693).
+char(5,9694).
+char(2,9695).
+char(4,9696).
+char(0,9697).
+char(p,9698).
+char(o,9699).
+char(p,9700).
+char(3,9701).
+char(6,9702).
+char(5,9703).
+char(4,9704).
+char(c,9705).
+char(m,9706).
+char(6,9707).
+char(2,9708).
+char(0,9709).
+char(2,9710).
+char(c,9711).
+char(m,9712).
+char(4,9713).
+char(8,9714).
+char(8,9715).
+char(0,9716).
+char(p,9717).
+char(3,9718).
+char(4,9719).
+char(2,9720).
+char(3,9721).
+char(p,9722).
+char(o,9723).
+char(p,9724).
+char(6,9725).
+char(3,9726).
+char(c,9727).
+char(c,9728).
+char(c,9729).
+char(m,9730).
+char(o,9731).
+char(m,9732).
+char(o,9733).
+char(2,9734).
+char(7,9735).
+char(0,9736).
+char(c,9737).
+char(m,9738).
+char(o,9739).
+char(m,9740).
+char(1,9741).
+char(6,9742).
+char(1,9743).
+char(0,9744).
+char(c,9745).
+char(c,9746).
+char(c,9747).
+char(p,9748).
+char(6,9749).
+char(5,9750).
+char(4,9751).
+char(4,9752).
+char(m,9753).
+char(o,9754).
+char(m,9755).
+char(3,9756).
+char(5,9757).
+char(4,9758).
+char(0,9759).
+char(c,9760).
+char(m,9761).
+char(o,9762).
+char(7,9763).
+char(1,9764).
+char(0,9765).
+char(1,9766).
+char(c,9767).
+char(c,9768).
+char(c,9769).
+char(c,9770).
+char(p,9771).
+char(o,9772).
+char(m,9773).
+char(o,9774).
+char(p,9775).
+char(o,9776).
+char(2,9777).
+char(3,9778).
+char(8,9779).
+char(0,9780).
+char(c,9781).
+char(c,9782).
+char(c,9783).
+char(c,9784).
+char(c,9785).
+char(c,9786).
+char(m,9787).
+char(9,9788).
+char(5,9789).
+char(8,9790).
+char(8,9791).
+char(p,9792).
+char(3,9793).
+char(4,9794).
+char(4,9795).
+char(9,9796).
+char(m,9797).
+char(o,9798).
+char(4,9799).
+char(7,9800).
+char(5,9801).
+char(p,9802).
+char(2,9803).
+char(5,9804).
+char(3,9805).
+char(3,9806).
+char(m,9807).
+char(4,9808).
+char(4,9809).
+char(0,9810).
+char(8,9811).
+char(c,9812).
+char(c,9813).
+char(c,9814).
+char(p,9815).
+char(o,9816).
+char(4,9817).
+char(5,9818).
+char(3,9819).
+char(7,9820).
+char(m,9821).
+char(2,9822).
+char(0,9823).
+char(5,9824).
+char(3,9825).
+char(p,9826).
+char(o,9827).
+char(m,9828).
+char(7,9829).
+char(8,9830).
+char(3,9831).
+char(p,9832).
+char(o,9833).
+char(2,9834).
+char(8,9835).
+char(1,9836).
+char(7,9837).
+char(p,9838).
+char(6,9839).
+char(7,9840).
+char(7,9841).
+char(0,9842).
+char(p,9843).
+char(9,9844).
+char(9,9845).
+char(1,9846).
+char(7,9847).
+char(c,9848).
+char(c,9849).
+char(c,9850).
+char(p,9851).
+char(5,9852).
+char(4,9853).
+char(0,9854).
+char(p,9855).
+char(o,9856).
+char(m,9857).
+char(o,9858).
+char(m,9859).
+char(3,9860).
+char(5,9861).
+char(9,9862).
+char(1,9863).
+char(c,9864).
+char(c,9865).
+char(m,9866).
+char(o,9867).
+char(m,9868).
+char(o,9869).
+char(p,9870).
+char(o,9871).
+char(o,9872).
+char(m,9873).
+char(o,9874).
+char(p,9875).
+char(6,9876).
+char(5,9877).
+char(2,9878).
+char(9,9879).
+char(p,9880).
+char(o,9881).
+char(m,9882).
+char(3,9883).
+char(6,9884).
+char(5,9885).
+char(8,9886).
+char(c,9887).
+char(p,9888).
+char(1,9889).
+char(6,9890).
+char(9,9891).
+char(4,9892).
+char(p,9893).
+char(o,9894).
+char(o,9895).
+char(m,9896).
+char(5,9897).
+char(8,9898).
+char(4,9899).
+char(6,9900).
+char(c,9901).
+char(m,9902).
+char(o,9903).
+char(m,9904).
+char(o,9905).
+char(m,9906).
+char(o,9907).
+char(m,9908).
+char(o,9909).
+char(2,9910).
+char(1,9911).
+char(5,9912).
+char(7,9913).
+char(c,9914).
+char(p,9915).
+char(o,9916).
+char(o,9917).
+char(p,9918).
+char(1,9919).
+char(8,9920).
+char(1,9921).
+char(0,9922).
+char(c,9923).
+char(c,9924).
+char(p,9925).
+char(o,9926).
+char(m,9927).
+char(o,9928).
+char(p,9929).
+char(o,9930).
+char(p,9931).
+char(o,9932).
+char(m,9933).
+char(8,9934).
+char(1,9935).
+char(8,9936).
+char(0,9937).
+char(c,9938).
+char(c,9939).
+char(p,9940).
+char(o,9941).
+char(p,9942).
+char(o,9943).
+char(p,9944).
+char(o,9945).
+char(m,9946).
+char(5,9947).
+char(1,9948).
+char(c,9949).
+char(m,9950).
+char(4,9951).
+char(8,9952).
+char(6,9953).
+char(3,9954).
+char(c,9955).
+char(c,9956).
+char(c,9957).
+char(p,9958).
+char(o,9959).
+char(o,9960).
+char(m,9961).
+char(o,9962).
+char(m,9963).
+char(o,9964).
+char(p,9965).
+char(9,9966).
+char(9,9967).
+char(9,9968).
+char(0,9969).
+char(p,9970).
+char(o,9971).
+char(7,9972).
+char(5,9973).
+char(6,9974).
+char(6,9975).
+char(m,9976).
+char(o,9977).
+char(m,9978).
+char(o,9979).
+char(6,9980).
+char(5,9981).
+char(8,9982).
+char(8,9983).
+char(c,9984).
+char(c,9985).
+char(c,9986).
+char(p,9987).
+char(7,9988).
+char(4,9989).
+char(9,9990).
+char(1,9991).
+char(c,9992).
+char(c,9993).
+char(p,9994).
+char(2,9995).
+char(9,9996).
+char(7,9997).
+char(5,9998).
+char(p,9999).
+char(o,10000).
+char(p,10001).
+char(5,10002).
+char(2,10003).
+char(2,10004).
+char(2,10005).
+char(m,10006).
+char(2,10007).
+char(9,10008).
+char(6,10009).
+char(9,10010).
+char(c,10011).
+char(c,10012).
+char(m,10013).
+char(3,10014).
+char(6,10015).
+char(1,10016).
+char(4,10017).
+char(c,10018).
+char(p,10019).
+char(o,10020).
+char(o,10021).
+char(o,10022).
+char(p,10023).
+char(o,10024).
+char(o,10025).
+char(o,10026).
+char(m,10027).
+char(8,10028).
+char(8,10029).
+char(m,10030).
+char(6,10031).
+char(4,10032).
+char(8,10033).
+char(6,10034).
+char(m,10035).
+char(o,10036).
+char(m,10037).
+char(7,10038).
+char(1,10039).
+char(4,10040).
+char(7,10041).
+char(m,10042).
+char(o,10043).
+char(p,10044).
+char(o,10045).
+char(m,10046).
+char(o,10047).
+char(p,10048).
+char(5,10049).
+char(9,10050).
+char(6,10051).
+char(6,10052).
+char(p,10053).
+char(o,10054).
+char(8,10055).
+char(1,10056).
+char(2,10057).
+char(9,10058).
+char(m,10059).
+char(o,10060).
+char(o,10061).
+char(m,10062).
+char(1,10063).
+char(7,10064).
+char(9,10065).
+char(7,10066).
+char(m,10067).
+char(o,10068).
+char(p,10069).
+char(9,10070).
+char(3,10071).
+char(9,10072).
+char(p,10073).
+char(o,10074).
+char(m,10075).
+char(7,10076).
+char(0,10077).
+char(6,10078).
+char(p,10079).
+char(6,10080).
+char(4,10081).
+char(5,10082).
+char(3,10083).
+char(c,10084).
+char(c,10085).
+char(p,10086).
+char(o,10087).
+char(o,10088).
+char(m,10089).
+char(3,10090).
+char(1,10091).
+char(2,10092).
+char(8,10093).
+char(c,10094).
+char(m,10095).
+char(8,10096).
+char(1,10097).
+char(2,10098).
+char(0,10099).
+char(c,10100).
+char(p,10101).
+char(o,10102).
+char(m,10103).
+char(2,10104).
+char(3,10105).
+char(3,10106).
+char(1,10107).
+char(c,10108).
+char(c,10109).
+char(p,10110).
+char(o,10111).
+char(o,10112).
+char(m,10113).
+char(o,10114).
+char(o,10115).
+char(m,10116).
+char(1,10117).
+char(9,10118).
+char(4,10119).
+char(6,10120).
+char(c,10121).
+char(c,10122).
+char(c,10123).
+char(c,10124).
+char(p,10125).
+char(o,10126).
+char(m,10127).
+char(1,10128).
+char(4,10129).
+char(8,10130).
+char(c,10131).
+char(c,10132).
+char(p,10133).
+char(o,10134).
+char(p,10135).
+char(6,10136).
+char(8,10137).
+char(1,10138).
+char(4,10139).
+char(c,10140).
+char(p,10141).
+char(7,10142).
+char(0,10143).
+char(7,10144).
+char(6,10145).
+char(m,10146).
+char(2,10147).
+char(8,10148).
+char(0,10149).
+char(1,10150).
+char(c,10151).
+char(c,10152).
+char(m,10153).
+char(o,10154).
+char(p,10155).
+char(7,10156).
+char(3,10157).
+char(7,10158).
+char(0,10159).
+char(c,10160).
+char(c,10161).
+char(c,10162).
+char(c,10163).
+char(p,10164).
+char(o,10165).
+char(o,10166).
+char(p,10167).
+char(o,10168).
+char(p,10169).
+char(5,10170).
+char(4,10171).
+char(2,10172).
+char(5,10173).
+char(m,10174).
+char(2,10175).
+char(6,10176).
+char(9,10177).
+char(c,10178).
+char(p,10179).
+char(2,10180).
+char(2,10181).
+char(8,10182).
+char(9,10183).
+char(m,10184).
+char(3,10185).
+char(6,10186).
+char(9,10187).
+char(1,10188).
+char(m,10189).
+char(4,10190).
+char(4,10191).
+char(5,10192).
+char(9,10193).
+char(p,10194).
+char(2,10195).
+char(1,10196).
+char(4,10197).
+char(7,10198).
+char(p,10199).
+char(2,10200).
+char(5,10201).
+char(5,10202).
+char(9,10203).
+char(c,10204).
+char(c,10205).
+char(p,10206).
+char(o,10207).
+char(5,10208).
+char(5,10209).
+char(2,10210).
+char(c,10211).
+char(m,10212).
+char(o,10213).
+char(m,10214).
+char(3,10215).
+char(5,10216).
+char(5,10217).
+char(7,10218).
+char(c,10219).
+char(c,10220).
+char(c,10221).
+char(p,10222).
+char(1,10223).
+char(8,10224).
+char(0,10225).
+char(c,10226).
+char(c,10227).
+char(p,10228).
+char(o,10229).
+char(m,10230).
+char(1,10231).
+char(1,10232).
+char(4,10233).
+char(9,10234).
+char(c,10235).
+char(m,10236).
+char(5,10237).
+char(6,10238).
+char(3,10239).
+char(3,10240).
+char(c,10241).
+char(c,10242).
+char(m,10243).
+char(2,10244).
+char(0,10245).
+char(2,10246).
+char(1,10247).
+char(c,10248).
+char(c,10249).
+char(p,10250).
+char(1,10251).
+char(4,10252).
+char(2,10253).
+char(2,10254).
+char(p,10255).
+char(1,10256).
+char(9,10257).
+char(4,10258).
+char(p,10259).
+char(o,10260).
+char(8,10261).
+char(1,10262).
+char(5,10263).
+char(7,10264).
+char(c,10265).
+char(p,10266).
+char(o,10267).
+char(3,10268).
+char(2,10269).
+char(3,10270).
+char(5,10271).
+char(p,10272).
+char(2,10273).
+char(1,10274).
+char(8,10275).
+char(7,10276).
+char(m,10277).
+char(4,10278).
+char(6,10279).
+char(2,10280).
+char(4,10281).
+char(m,10282).
+char(5,10283).
+char(4,10284).
+char(5,10285).
+char(2,10286).
+char(p,10287).
+char(6,10288).
+char(5,10289).
+char(3,10290).
+char(9,10291).
+char(p,10292).
+char(7,10293).
+char(8,10294).
+char(8,10295).
+char(9,10296).
+char(p,10297).
+char(o,10298).
+char(m,10299).
+char(6,10300).
+char(4,10301).
+char(8,10302).
+char(9,10303).
+char(m,10304).
+char(o,10305).
+char(m,10306).
+char(7,10307).
+char(7,10308).
+char(4,10309).
+char(8,10310).
+char(m,10311).
+char(9,10312).
+char(1,10313).
+char(2,10314).
+char(1,10315).
+char(m,10316).
+char(2,10317).
+char(6,10318).
+char(2,10319).
+char(4,10320).
+char(m,10321).
+char(9,10322).
+char(6,10323).
+char(6,10324).
+char(m,10325).
+char(5,10326).
+char(3,10327).
+char(2,10328).
+char(5,10329).
+char(c,10330).
+char(p,10331).
+char(o,10332).
+char(m,10333).
+char(9,10334).
+char(6,10335).
+char(3,10336).
+char(4,10337).
+char(m,10338).
+char(5,10339).
+char(1,10340).
+char(0,10341).
+char(8,10342).
+char(m,10343).
+char(o,10344).
+char(1,10345).
+char(9,10346).
+char(6,10347).
+char(6,10348).
+char(p,10349).
+char(o,10350).
+char(m,10351).
+char(6,10352).
+char(6,10353).
+char(3,10354).
+char(1,10355).
+char(c,10356).
+char(m,10357).
+char(2,10358).
+char(2,10359).
+char(6,10360).
+char(1,10361).
+char(m,10362).
+char(1,10363).
+char(1,10364).
+char(2,10365).
+char(1,10366).
+char(c,10367).
+char(p,10368).
+char(o,10369).
+char(p,10370).
+char(5,10371).
+char(7,10372).
+char(2,10373).
+char(9,10374).
+char(c,10375).
+char(c,10376).
+char(c,10377).
+char(c,10378).
+char(c,10379).
+char(p,10380).
+char(o,10381).
+char(p,10382).
+char(o,10383).
+char(p,10384).
+char(o,10385).
+char(m,10386).
+char(o,10387).
+char(9,10388).
+char(3,10389).
+char(1,10390).
+char(c,10391).
+char(c,10392).
+char(c,10393).
+char(p,10394).
+char(o,10395).
+char(p,10396).
+char(6,10397).
+char(9,10398).
+char(4,10399).
+char(0,10400).
+char(p,10401).
+char(9,10402).
+char(2,10403).
+char(0,10404).
+char(6,10405).
+char(c,10406).
+char(p,10407).
+char(1,10408).
+char(6,10409).
+char(8,10410).
+char(7,10411).
+char(p,10412).
+char(o,10413).
+char(p,10414).
+char(o,10415).
+char(p,10416).
+char(o,10417).
+char(5,10418).
+char(2,10419).
+char(2,10420).
+char(3,10421).
+char(p,10422).
+char(3,10423).
+char(8,10424).
+char(3,10425).
+char(6,10426).
+char(c,10427).
+char(c,10428).
+char(m,10429).
+char(6,10430).
+char(4,10431).
+char(0,10432).
+char(1,10433).
+char(c,10434).
+char(m,10435).
+char(1,10436).
+char(6,10437).
+char(0,10438).
+char(3,10439).
+char(c,10440).
+char(m,10441).
+char(o,10442).
+char(p,10443).
+char(3,10444).
+char(2,10445).
+char(4,10446).
+char(6,10447).
+char(c,10448).
+char(m,10449).
+char(o,10450).
+char(m,10451).
+char(o,10452).
+char(p,10453).
+char(6,10454).
+char(9,10455).
+char(2,10456).
+char(7,10457).
+char(p,10458).
+char(o,10459).
+char(9,10460).
+char(0,10461).
+char(6,10462).
+char(0,10463).
+char(p,10464).
+char(o,10465).
+char(p,10466).
+char(o,10467).
+char(p,10468).
+char(o,10469).
+char(4,10470).
+char(1,10471).
+char(3,10472).
+char(9,10473).
+char(c,10474).
+char(m,10475).
+char(o,10476).
+char(3,10477).
+char(7,10478).
+char(0,10479).
+char(5,10480).
+char(p,10481).
+char(o,10482).
+char(p,10483).
+char(o,10484).
+char(m,10485).
+char(o,10486).
+char(m,10487).
+char(7,10488).
+char(2,10489).
+char(7,10490).
+char(1,10491).
+char(p,10492).
+char(o,10493).
+char(p,10494).
+char(o,10495).
+char(o,10496).
+char(p,10497).
+char(1,10498).
+char(5,10499).
+char(3,10500).
+char(5,10501).
+char(p,10502).
+char(6,10503).
+char(8,10504).
+char(6,10505).
+char(7,10506).
+char(m,10507).
+char(1,10508).
+char(8,10509).
+char(4,10510).
+char(2,10511).
+char(c,10512).
+char(p,10513).
+char(o,10514).
+char(p,10515).
+char(7,10516).
+char(0,10517).
+char(6,10518).
+char(9,10519).
+char(p,10520).
+char(2,10521).
+char(0,10522).
+char(7,10523).
+char(2,10524).
+char(c,10525).
+char(c,10526).
+char(m,10527).
+char(o,10528).
+char(4,10529).
+char(2,10530).
+char(0,10531).
+char(2,10532).
+char(m,10533).
+char(o,10534).
+char(o,10535).
+char(p,10536).
+char(2,10537).
+char(9,10538).
+char(1,10539).
+char(0,10540).
+char(c,10541).
+char(p,10542).
+char(4,10543).
+char(8,10544).
+char(8,10545).
+char(6,10546).
+char(m,10547).
+char(2,10548).
+char(5,10549).
+char(6,10550).
+char(4,10551).
+char(c,10552).
+char(c,10553).
+char(c,10554).
+char(c,10555).
+char(p,10556).
+char(6,10557).
+char(1,10558).
+char(1,10559).
+char(9,10560).
+char(p,10561).
+char(4,10562).
+char(0,10563).
+char(0,10564).
+char(2,10565).
+char(c,10566).
+char(c,10567).
+char(c,10568).
+char(p,10569).
+char(1,10570).
+char(1,10571).
+char(0,10572).
+char(6,10573).
+char(p,10574).
+char(o,10575).
+char(m,10576).
+char(o,10577).
+char(5,10578).
+char(2,10579).
+char(3,10580).
+char(1,10581).
+char(m,10582).
+char(o,10583).
+char(o,10584).
+char(m,10585).
+char(1,10586).
+char(5,10587).
+char(5,10588).
+char(4,10589).
+char(m,10590).
+char(o,10591).
+char(p,10592).
+char(6,10593).
+char(1,10594).
+char(0,10595).
+char(9,10596).
+char(c,10597).
+char(m,10598).
+char(o,10599).
+char(6,10600).
+char(8,10601).
+char(9,10602).
+char(5,10603).
+char(m,10604).
+char(4,10605).
+char(4,10606).
+char(3,10607).
+char(2,10608).
+char(c,10609).
+char(c,10610).
+char(p,10611).
+char(7,10612).
+char(1,10613).
+char(8,10614).
+char(5,10615).
+char(p,10616).
+char(o,10617).
+char(p,10618).
+char(5,10619).
+char(4,10620).
+char(0,10621).
+char(5,10622).
+char(c,10623).
+char(m,10624).
+char(6,10625).
+char(7,10626).
+char(2,10627).
+char(c,10628).
+char(c,10629).
+char(p,10630).
+char(o,10631).
+char(m,10632).
+char(o,10633).
+char(p,10634).
+char(3,10635).
+char(4,10636).
+char(5,10637).
+char(3,10638).
+char(p,10639).
+char(o,10640).
+char(m,10641).
+char(1,10642).
+char(4,10643).
+char(5,10644).
+char(c,10645).
+char(p,10646).
+char(7,10647).
+char(4,10648).
+char(8,10649).
+char(5,10650).
+char(p,10651).
+char(o,10652).
+char(m,10653).
+char(7,10654).
+char(1,10655).
+char(1,10656).
+char(p,10657).
+char(o,10658).
+char(p,10659).
+char(o,10660).
+char(p,10661).
+char(o,10662).
+char(m,10663).
+char(o,10664).
+char(5,10665).
+char(2,10666).
+char(4,10667).
+char(2,10668).
+char(c,10669).
+char(c,10670).
+char(p,10671).
+char(8,10672).
+char(4,10673).
+char(0,10674).
+char(0,10675).
+char(p,10676).
+char(7,10677).
+char(5,10678).
+char(3,10679).
+char(6,10680).
+char(c,10681).
+char(p,10682).
+char(9,10683).
+char(9,10684).
+char(2,10685).
+char(4,10686).
+char(p,10687).
+char(9,10688).
+char(1,10689).
+char(7,10690).
+char(9,10691).
+char(c,10692).
+char(m,10693).
+char(4,10694).
+char(9,10695).
+char(7,10696).
+char(c,10697).
+char(p,10698).
+char(o,10699).
+char(m,10700).
+char(o,10701).
+char(p,10702).
+char(1,10703).
+char(8,10704).
+char(5,10705).
+char(c,10706).
+char(p,10707).
+char(o,10708).
+char(o,10709).
+char(o,10710).
+char(3,10711).
+char(4,10712).
+char(6,10713).
+char(1,10714).
+char(p,10715).
+char(o,10716).
+char(m,10717).
+char(o,10718).
+char(p,10719).
+char(o,10720).
+char(o,10721).
+char(p,10722).
+char(9,10723).
+char(1,10724).
+char(5,10725).
+char(6,10726).
+char(m,10727).
+char(8,10728).
+char(6,10729).
+char(2,10730).
+char(5,10731).
+char(p,10732).
+char(o,10733).
+char(m,10734).
+char(o,10735).
+char(p,10736).
+char(o,10737).
+char(m,10738).
+char(6,10739).
+char(0,10740).
+char(6,10741).
+char(6,10742).
+char(c,10743).
+char(c,10744).
+char(c,10745).
+char(p,10746).
+char(o,10747).
+char(m,10748).
+char(7,10749).
+char(3,10750).
+char(0,10751).
+char(1,10752).
+char(p,10753).
+char(8,10754).
+char(3,10755).
+char(2,10756).
+char(6,10757).
+char(c,10758).
+char(p,10759).
+char(8,10760).
+char(6,10761).
+char(6,10762).
+char(4,10763).
+char(p,10764).
+char(o,10765).
+char(8,10766).
+char(0,10767).
+char(5,10768).
+char(7,10769).
+char(p,10770).
+char(5,10771).
+char(4,10772).
+char(8,10773).
+char(4,10774).
+char(m,10775).
+char(o,10776).
+char(p,10777).
+char(o,10778).
+char(m,10779).
+char(7,10780).
+char(9,10781).
+char(0,10782).
+char(0,10783).
+char(p,10784).
+char(9,10785).
+char(4,10786).
+char(7,10787).
+char(2,10788).
+char(m,10789).
+char(1,10790).
+char(0,10791).
+char(0,10792).
+char(1,10793).
+char(c,10794).
+char(p,10795).
+char(6,10796).
+char(6,10797).
+char(1,10798).
+char(5,10799).
+char(c,10800).
+char(c,10801).
+char(p,10802).
+char(4,10803).
+char(6,10804).
+char(2,10805).
+char(8,10806).
+char(m,10807).
+char(o,10808).
+char(m,10809).
+char(o,10810).
+char(p,10811).
+char(o,10812).
+char(o,10813).
+char(m,10814).
+char(9,10815).
+char(5,10816).
+char(4,10817).
+char(7,10818).
+char(c,10819).
+char(m,10820).
+char(4,10821).
+char(5,10822).
+char(6,10823).
+char(0,10824).
+char(p,10825).
+char(9,10826).
+char(6,10827).
+char(1,10828).
+char(5,10829).
+char(c,10830).
+char(p,10831).
+char(o,10832).
+char(p,10833).
+char(o,10834).
+char(p,10835).
+char(o,10836).
+char(2,10837).
+char(1,10838).
+char(6,10839).
+char(8,10840).
+char(c,10841).
+char(c,10842).
+char(p,10843).
+char(o,10844).
+char(m,10845).
+char(6,10846).
+char(3,10847).
+char(5,10848).
+char(0,10849).
+char(c,10850).
+char(c,10851).
+char(m,10852).
+char(o,10853).
+char(p,10854).
+char(3,10855).
+char(7,10856).
+char(3,10857).
+char(3,10858).
+char(p,10859).
+char(o,10860).
+char(m,10861).
+char(8,10862).
+char(5,10863).
+char(8,10864).
+char(1,10865).
+char(c,10866).
+char(p,10867).
+char(o,10868).
+char(3,10869).
+char(7,10870).
+char(2,10871).
+char(9,10872).
+char(p,10873).
+char(8,10874).
+char(5,10875).
+char(4,10876).
+char(2,10877).
+char(c,10878).
+char(c,10879).
+char(c,10880).
+char(p,10881).
+char(o,10882).
+char(o,10883).
+char(p,10884).
+char(7,10885).
+char(8,10886).
+char(8,10887).
+char(4,10888).
+char(p,10889).
+char(o,10890).
+char(m,10891).
+char(o,10892).
+char(p,10893).
+char(o,10894).
+char(p,10895).
+char(2,10896).
+char(3,10897).
+char(1,10898).
+char(3,10899).
+char(c,10900).
+char(m,10901).
+char(o,10902).
+char(p,10903).
+char(o,10904).
+char(5,10905).
+char(7,10906).
+char(0,10907).
+char(5,10908).
+char(c,10909).
+char(c,10910).
+char(c,10911).
+char(p,10912).
+char(o,10913).
+char(m,10914).
+char(o,10915).
+char(p,10916).
+char(5,10917).
+char(0,10918).
+char(5,10919).
+char(7,10920).
+char(c,10921).
+char(c,10922).
+char(m,10923).
+char(o,10924).
+char(o,10925).
+char(o,10926).
+char(2,10927).
+char(8,10928).
+char(0,10929).
+char(3,10930).
+char(p,10931).
+char(8,10932).
+char(3,10933).
+char(9,10934).
+char(c,10935).
+char(p,10936).
+char(2,10937).
+char(9,10938).
+char(6,10939).
+char(5,10940).
+char(m,10941).
+char(o,10942).
+char(m,10943).
+char(o,10944).
+char(p,10945).
+char(7,10946).
+char(8,10947).
+char(1,10948).
+char(3,10949).
+char(p,10950).
+char(4,10951).
+char(9,10952).
+char(6,10953).
+char(c,10954).
+char(m,10955).
+char(o,10956).
+char(1,10957).
+char(2,10958).
+char(9,10959).
+char(4,10960).
+char(c,10961).
+char(m,10962).
+char(o,10963).
+char(m,10964).
+char(9,10965).
+char(6,10966).
+char(8,10967).
+char(4,10968).
+char(c,10969).
+char(p,10970).
+char(7,10971).
+char(4,10972).
+char(4,10973).
+char(7,10974).
+char(p,10975).
+char(o,10976).
+char(o,10977).
+char(o,10978).
+char(m,10979).
+char(o,10980).
+char(4,10981).
+char(8,10982).
+char(5,10983).
+char(5,10984).
+char(p,10985).
+char(o,10986).
+char(1,10987).
+char(1,10988).
+char(2,10989).
+char(4,10990).
+char(p,10991).
+char(4,10992).
+char(3,10993).
+char(6,10994).
+char(7,10995).
+char(m,10996).
+char(8,10997).
+char(3,10998).
+char(1,10999).
+char(6,11000).
+char(m,11001).
+char(9,11002).
+char(4,11003).
+char(6,11004).
+char(9,11005).
+char(p,11006).
+char(9,11007).
+char(2,11008).
+char(8,11009).
+char(7,11010).
+char(c,11011).
+char(c,11012).
+char(c,11013).
+char(c,11014).
+char(c,11015).
+char(p,11016).
+char(3,11017).
+char(1,11018).
+char(0,11019).
+char(1,11020).
+char(p,11021).
+char(o,11022).
+char(m,11023).
+char(o,11024).
+char(p,11025).
+char(4,11026).
+char(5,11027).
+char(7,11028).
+char(p,11029).
+char(9,11030).
+char(8,11031).
+char(6,11032).
+char(1,11033).
+char(c,11034).
+char(c,11035).
+char(p,11036).
+char(9,11037).
+char(2,11038).
+char(3,11039).
+char(5,11040).
+char(p,11041).
+char(2,11042).
+char(8,11043).
+char(2,11044).
+char(6,11045).
+char(p,11046).
+char(5,11047).
+char(1,11048).
+char(6,11049).
+char(2,11050).
+char(c,11051).
+char(p,11052).
+char(4,11053).
+char(1,11054).
+char(5,11055).
+char(5,11056).
+char(c,11057).
+char(c,11058).
+char(c,11059).
+char(c,11060).
+char(m,11061).
+char(3,11062).
+char(4,11063).
+char(2,11064).
+char(3,11065).
+char(c,11066).
+char(c,11067).
+char(c,11068).
+char(c,11069).
+char(m,11070).
+char(8,11071).
+char(2,11072).
+char(7,11073).
+char(1,11074).
+char(m,11075).
+char(9,11076).
+char(6,11077).
+char(2,11078).
+char(6,11079).
+char(m,11080).
+char(7,11081).
+char(3,11082).
+char(2,11083).
+char(0,11084).
+char(m,11085).
+char(2,11086).
+char(5,11087).
+char(0,11088).
+char(7,11089).
+char(c,11090).
+char(c,11091).
+char(m,11092).
+char(8,11093).
+char(9,11094).
+char(3,11095).
+char(1,11096).
+char(m,11097).
+char(o,11098).
+char(m,11099).
+char(o,11100).
+char(m,11101).
+char(9,11102).
+char(8,11103).
+char(8,11104).
+char(8,11105).
+char(c,11106).
+char(p,11107).
+char(o,11108).
+char(m,11109).
+char(o,11110).
+char(2,11111).
+char(6,11112).
+char(6,11113).
+char(6,11114).
+char(m,11115).
+char(5,11116).
+char(1,11117).
+char(7,11118).
+char(4,11119).
+char(m,11120).
+char(o,11121).
+char(p,11122).
+char(5,11123).
+char(4,11124).
+char(4,11125).
+char(8,11126).
+char(m,11127).
+char(o,11128).
+char(6,11129).
+char(2,11130).
+char(9,11131).
+char(8,11132).
+char(m,11133).
+char(9,11134).
+char(7,11135).
+char(7,11136).
+char(m,11137).
+char(o,11138).
+char(5,11139).
+char(7,11140).
+char(4,11141).
+char(8,11142).
+char(c,11143).
+char(m,11144).
+char(o,11145).
+char(m,11146).
+char(o,11147).
+char(m,11148).
+char(2,11149).
+char(6,11150).
+char(1,11151).
+char(8,11152).
+char(p,11153).
+char(o,11154).
+char(p,11155).
+char(o,11156).
+char(o,11157).
+char(m,11158).
+char(o,11159).
+char(p,11160).
+char(6,11161).
+char(5,11162).
+char(3,11163).
+char(0,11164).
+char(c,11165).
+char(c,11166).
+char(c,11167).
+char(c,11168).
+char(c,11169).
+char(p,11170).
+char(4,11171).
+char(9,11172).
+char(5,11173).
+char(4,11174).
+char(p,11175).
+char(9,11176).
+char(1,11177).
+char(2,11178).
+char(4,11179).
+char(c,11180).
+char(m,11181).
+char(o,11182).
+char(p,11183).
+char(5,11184).
+char(7,11185).
+char(6,11186).
+char(5,11187).
+char(c,11188).
+char(c,11189).
+char(c,11190).
+char(m,11191).
+char(o,11192).
+char(m,11193).
+char(o,11194).
+char(m,11195).
+char(o,11196).
+char(p,11197).
+char(o,11198).
+char(p,11199).
+char(o,11200).
+char(p,11201).
+char(4,11202).
+char(8,11203).
+char(1,11204).
+char(0,11205).
+char(p,11206).
+char(o,11207).
+char(p,11208).
+char(5,11209).
+char(5,11210).
+char(5,11211).
+char(9,11212).
+char(c,11213).
+char(c,11214).
+char(c,11215).
+char(c,11216).
+char(c,11217).
+char(c,11218).
+char(c,11219).
+char(c,11220).
+char(c,11221).
+char(p,11222).
+char(o,11223).
+char(p,11224).
+char(o,11225).
+char(p,11226).
+char(6,11227).
+char(2,11228).
+char(7,11229).
+char(8,11230).
+char(m,11231).
+char(7,11232).
+char(0,11233).
+char(5,11234).
+char(2,11235).
+char(m,11236).
+char(o,11237).
+char(m,11238).
+char(o,11239).
+char(p,11240).
+char(o,11241).
+char(p,11242).
+char(3,11243).
+char(6,11244).
+char(1,11245).
+char(5,11246).
+char(c,11247).
+char(m,11248).
+char(o,11249).
+char(p,11250).
+char(o,11251).
+char(m,11252).
+char(o,11253).
+char(m,11254).
+char(8,11255).
+char(5,11256).
+char(8,11257).
+char(8,11258).
+char(p,11259).
+char(o,11260).
+char(p,11261).
+char(3,11262).
+char(4,11263).
+char(9,11264).
+char(8,11265).
+char(m,11266).
+char(o,11267).
+char(p,11268).
+char(o,11269).
+char(6,11270).
+char(0,11271).
+char(8,11272).
+char(2,11273).
+char(c,11274).
+char(c,11275).
+char(c,11276).
+char(c,11277).
+char(c,11278).
+char(m,11279).
+char(4,11280).
+char(7,11281).
+char(7,11282).
+char(2,11283).
+char(p,11284).
+char(o,11285).
+char(m,11286).
+char(o,11287).
+char(o,11288).
+char(m,11289).
+char(9,11290).
+char(3,11291).
+char(6,11292).
+char(9,11293).
+char(p,11294).
+char(9,11295).
+char(2,11296).
+char(5,11297).
+char(7,11298).
+char(p,11299).
+char(o,11300).
+char(m,11301).
+char(3,11302).
+char(3,11303).
+char(5,11304).
+char(8,11305).
+char(p,11306).
+char(o,11307).
+char(m,11308).
+char(4,11309).
+char(8,11310).
+char(7,11311).
+char(3,11312).
+char(m,11313).
+char(6,11314).
+char(7,11315).
+char(2,11316).
+char(6,11317).
+char(p,11318).
+char(o,11319).
+char(4,11320).
+char(0,11321).
+char(2,11322).
+char(7,11323).
+char(c,11324).
+char(c,11325).
+char(c,11326).
+char(m,11327).
+char(o,11328).
+char(o,11329).
+char(7,11330).
+char(0,11331).
+char(8,11332).
+char(1,11333).
+char(c,11334).
+char(p,11335).
+char(o,11336).
+char(p,11337).
+char(o,11338).
+char(p,11339).
+char(o,11340).
+char(m,11341).
+char(2,11342).
+char(3,11343).
+char(7,11344).
+char(7,11345).
+char(p,11346).
+char(o,11347).
+char(6,11348).
+char(7,11349).
+char(9,11350).
+char(9,11351).
+char(p,11352).
+char(4,11353).
+char(9,11354).
+char(3,11355).
+char(0,11356).
+char(p,11357).
+char(o,11358).
+char(m,11359).
+char(6,11360).
+char(4,11361).
+char(9,11362).
+char(c,11363).
+char(c,11364).
+char(p,11365).
+char(2,11366).
+char(3,11367).
+char(2,11368).
+char(5,11369).
+char(c,11370).
+char(p,11371).
+char(1,11372).
+char(0,11373).
+char(4,11374).
+char(5,11375).
+char(p,11376).
+char(2,11377).
+char(4,11378).
+char(8,11379).
+char(p,11380).
+char(4,11381).
+char(2,11382).
+char(9,11383).
+char(6,11384).
+char(c,11385).
+char(p,11386).
+char(o,11387).
+char(m,11388).
+char(o,11389).
+char(o,11390).
+char(m,11391).
+char(9,11392).
+char(3,11393).
+char(9,11394).
+char(6,11395).
+char(c,11396).
+char(m,11397).
+char(o,11398).
+char(4,11399).
+char(4,11400).
+char(5,11401).
+char(8,11402).
+char(p,11403).
+char(6,11404).
+char(6,11405).
+char(3,11406).
+char(5,11407).
+char(c,11408).
+char(m,11409).
+char(3,11410).
+char(7,11411).
+char(2,11412).
+char(7,11413).
+char(p,11414).
+char(o,11415).
+char(m,11416).
+char(o,11417).
+char(m,11418).
+char(o,11419).
+char(6,11420).
+char(2,11421).
+char(8,11422).
+char(2,11423).
+char(c,11424).
+char(c,11425).
+char(c,11426).
+char(c,11427).
+char(c,11428).
+char(c,11429).
+char(c,11430).
+char(p,11431).
+char(o,11432).
+char(p,11433).
+char(8,11434).
+char(5,11435).
+char(9,11436).
+char(1,11437).
+char(m,11438).
+char(o,11439).
+char(o,11440).
+char(m,11441).
+char(o,11442).
+char(o,11443).
+char(p,11444).
+char(2,11445).
+char(7,11446).
+char(8,11447).
+char(2,11448).
+char(c,11449).
+char(m,11450).
+char(o,11451).
+char(p,11452).
+char(9,11453).
+char(5,11454).
+char(9,11455).
+char(1,11456).
+char(p,11457).
+char(o,11458).
+char(p,11459).
+char(2,11460).
+char(7,11461).
+char(7,11462).
+char(8,11463).
+char(c,11464).
+char(m,11465).
+char(8,11466).
+char(1,11467).
+char(0,11468).
+char(4,11469).
+char(m,11470).
+char(o,11471).
+char(p,11472).
+char(o,11473).
+char(m,11474).
+char(o,11475).
+char(p,11476).
+char(o,11477).
+char(m,11478).
+char(5,11479).
+char(8,11480).
+char(0,11481).
+char(4,11482).
+char(c,11483).
+char(m,11484).
+char(9,11485).
+char(7,11486).
+char(2,11487).
+char(8,11488).
+char(m,11489).
+char(o,11490).
+char(o,11491).
+char(m,11492).
+char(o,11493).
+char(o,11494).
+char(4,11495).
+char(9,11496).
+char(9,11497).
+char(8,11498).
+char(c,11499).
+char(c,11500).
+char(m,11501).
+char(o,11502).
+char(m,11503).
+char(5,11504).
+char(6,11505).
+char(7,11506).
+char(5,11507).
+char(m,11508).
+char(o,11509).
+char(o,11510).
+char(p,11511).
+char(9,11512).
+char(3,11513).
+char(1,11514).
+char(1,11515).
+char(p,11516).
+char(o,11517).
+char(4,11518).
+char(4,11519).
+char(5,11520).
+char(4,11521).
+char(c,11522).
+char(p,11523).
+char(o,11524).
+char(o,11525).
+char(p,11526).
+char(o,11527).
+char(o,11528).
+char(6,11529).
+char(3,11530).
+char(9,11531).
+char(3,11532).
+char(m,11533).
+char(o,11534).
+char(p,11535).
+char(3,11536).
+char(8,11537).
+char(7,11538).
+char(6,11539).
+char(m,11540).
+char(o,11541).
+char(o,11542).
+char(5,11543).
+char(0,11544).
+char(6,11545).
+char(2,11546).
+char(p,11547).
+char(o,11548).
+char(m,11549).
+char(o,11550).
+char(8,11551).
+char(1,11552).
+char(2,11553).
+char(5,11554).
+char(m,11555).
+char(o,11556).
+char(6,11557).
+char(9,11558).
+char(4,11559).
+char(1,11560).
+char(m,11561).
+char(o,11562).
+char(m,11563).
+char(o,11564).
+char(p,11565).
+char(4,11566).
+char(7,11567).
+char(1,11568).
+char(9,11569).
+char(m,11570).
+char(2,11571).
+char(5,11572).
+char(4,11573).
+char(2,11574).
+char(c,11575).
+char(m,11576).
+char(o,11577).
+char(m,11578).
+char(6,11579).
+char(4,11580).
+char(7,11581).
+char(3,11582).
+char(c,11583).
+char(m,11584).
+char(o,11585).
+char(o,11586).
+char(o,11587).
+char(p,11588).
+char(o,11589).
+char(p,11590).
+char(o,11591).
+char(8,11592).
+char(1,11593).
+char(5,11594).
+char(0,11595).
+char(p,11596).
+char(o,11597).
+char(o,11598).
+char(p,11599).
+char(6,11600).
+char(9,11601).
+char(2,11602).
+char(9,11603).
+char(m,11604).
+char(o,11605).
+char(m,11606).
+char(5,11607).
+char(0,11608).
+char(9,11609).
+char(5,11610).
+char(c,11611).
+char(m,11612).
+char(6,11613).
+char(8,11614).
+char(5,11615).
+char(1,11616).
+char(p,11617).
+char(o,11618).
+char(p,11619).
+char(o,11620).
+char(p,11621).
+char(o,11622).
+char(m,11623).
+char(2,11624).
+char(0,11625).
+char(2,11626).
+char(4,11627).
+char(c,11628).
+char(c,11629).
+char(c,11630).
+char(c,11631).
+char(p,11632).
+char(1,11633).
+char(0,11634).
+char(1,11635).
+char(4,11636).
+char(c,11637).
+char(c,11638).
+char(c,11639).
+char(m,11640).
+char(o,11641).
+char(p,11642).
+char(o,11643).
+char(p,11644).
+char(o,11645).
+char(1,11646).
+char(1,11647).
+char(6,11648).
+char(8,11649).
+char(c,11650).
+char(m,11651).
+char(3,11652).
+char(4,11653).
+char(7,11654).
+char(6,11655).
+char(p,11656).
+char(o,11657).
+char(o,11658).
+char(m,11659).
+char(o,11660).
+char(o,11661).
+char(p,11662).
+char(o,11663).
+char(m,11664).
+char(o,11665).
+char(p,11666).
+char(5,11667).
+char(6,11668).
+char(0,11669).
+char(4,11670).
+char(c,11671).
+char(m,11672).
+char(o,11673).
+char(p,11674).
+char(6,11675).
+char(7,11676).
+char(7,11677).
+char(9,11678).
+char(c,11679).
+char(c,11680).
+char(p,11681).
+char(o,11682).
+char(1,11683).
+char(5,11684).
+char(1,11685).
+char(2,11686).
+char(m,11687).
+char(o,11688).
+char(2,11689).
+char(8,11690).
+char(8,11691).
+char(9,11692).
+char(c,11693).
+char(c,11694).
+char(c,11695).
+char(c,11696).
+char(m,11697).
+char(o,11698).
+char(p,11699).
+char(5,11700).
+char(8,11701).
+char(9,11702).
+char(1,11703).
+char(m,11704).
+char(2,11705).
+char(9,11706).
+char(0,11707).
+char(6,11708).
+char(c,11709).
+char(c,11710).
+char(m,11711).
+char(6,11712).
+char(6,11713).
+char(5,11714).
+char(3,11715).
+char(p,11716).
+char(o,11717).
+char(p,11718).
+char(o,11719).
+char(4,11720).
+char(9,11721).
+char(4,11722).
+char(8,11723).
+char(c,11724).
+char(c,11725).
+char(c,11726).
+char(m,11727).
+char(o,11728).
+char(p,11729).
+char(o,11730).
+char(o,11731).
+char(o,11732).
+char(p,11733).
+char(3,11734).
+char(6,11735).
+char(1,11736).
+char(m,11737).
+char(o,11738).
+char(4,11739).
+char(2,11740).
+char(2,11741).
+char(1,11742).
+char(p,11743).
+char(o,11744).
+char(p,11745).
+char(o,11746).
+char(p,11747).
+char(1,11748).
+char(7,11749).
+char(8,11750).
+char(m,11751).
+char(o,11752).
+char(m,11753).
+char(2,11754).
+char(9,11755).
+char(5,11756).
+char(8,11757).
+char(c,11758).
+char(p,11759).
+char(o,11760).
+char(5,11761).
+char(8,11762).
+char(2,11763).
+char(8,11764).
+char(m,11765).
+char(o,11766).
+char(o,11767).
+char(p,11768).
+char(o,11769).
+char(m,11770).
+char(o,11771).
+char(o,11772).
+char(m,11773).
+char(o,11774).
+char(6,11775).
+char(2,11776).
+char(7,11777).
+char(p,11778).
+char(3,11779).
+char(0,11780).
+char(1,11781).
+char(c,11782).
+char(c,11783).
+char(c,11784).
+char(c,11785).
+char(m,11786).
+char(o,11787).
+char(m,11788).
+char(o,11789).
+char(8,11790).
+char(0,11791).
+char(2,11792).
+char(8,11793).
+char(c,11794).
+char(c,11795).
+char(m,11796).
+char(6,11797).
+char(1,11798).
+char(3,11799).
+char(c,11800).
+char(c,11801).
+char(c,11802).
+char(c,11803).
+char(m,11804).
+char(o,11805).
+char(o,11806).
+char(m,11807).
+char(4,11808).
+char(4,11809).
+char(9,11810).
+char(7,11811).
+char(p,11812).
+char(o,11813).
+char(p,11814).
+char(o,11815).
+char(o,11816).
+char(o,11817).
+char(o,11818).
+char(m,11819).
+char(7,11820).
+char(2,11821).
+char(9,11822).
+char(8,11823).
+char(p,11824).
+char(o,11825).
+char(m,11826).
+char(o,11827).
+char(4,11828).
+char(6,11829).
+char(5,11830).
+char(0,11831).
+char(c,11832).
+char(p,11833).
+char(8,11834).
+char(4,11835).
+char(4,11836).
+char(5,11837).
+char(c,11838).
+char(c,11839).
+char(c,11840).
+char(c,11841).
+char(p,11842).
+char(o,11843).
+char(m,11844).
+char(5,11845).
+char(4,11846).
+char(2,11847).
+char(7,11848).
+char(c,11849).
+char(c,11850).
+char(c,11851).
+char(c,11852).
+char(p,11853).
+char(o,11854).
+char(9,11855).
+char(6,11856).
+char(6,11857).
+char(3,11858).
+char(c,11859).
+char(p,11860).
+char(3,11861).
+char(3,11862).
+char(0,11863).
+char(4,11864).
+char(c,11865).
+char(p,11866).
+char(7,11867).
+char(7,11868).
+char(1,11869).
+char(9,11870).
+char(p,11871).
+char(9,11872).
+char(9,11873).
+char(1,11874).
+char(3,11875).
+char(c,11876).
+char(c,11877).
+char(c,11878).
+char(m,11879).
+char(9,11880).
+char(2,11881).
+char(3,11882).
+char(1,11883).
+char(m,11884).
+char(o,11885).
+char(p,11886).
+char(o,11887).
+char(p,11888).
+char(4,11889).
+char(4,11890).
+char(0,11891).
+char(2,11892).
+char(c,11893).
+char(c,11894).
+char(c,11895).
+char(p,11896).
+char(6,11897).
+char(1,11898).
+char(4,11899).
+char(6,11900).
+char(c,11901).
+char(m,11902).
+char(3,11903).
+char(1,11904).
+char(5,11905).
+char(1,11906).
+char(c,11907).
+char(m,11908).
+char(o,11909).
+char(m,11910).
+char(o,11911).
+char(o,11912).
+char(7,11913).
+char(5,11914).
+char(6,11915).
+char(3,11916).
+char(c,11917).
+char(c,11918).
+char(c,11919).
+char(m,11920).
+char(o,11921).
+char(o,11922).
+char(1,11923).
+char(3,11924).
+char(1,11925).
+char(5,11926).
+char(m,11927).
+char(o,11928).
+char(m,11929).
+char(7,11930).
+char(3,11931).
+char(7,11932).
+char(6,11933).
+char(c,11934).
+char(m,11935).
+char(o,11936).
+char(p,11937).
+char(o,11938).
+char(m,11939).
+char(2,11940).
+char(9,11941).
+char(7,11942).
+char(5,11943).
+char(c,11944).
+char(c,11945).
+char(c,11946).
+char(c,11947).
+char(c,11948).
+char(c,11949).
+char(p,11950).
+char(o,11951).
+char(m,11952).
+char(o,11953).
+char(m,11954).
+char(o,11955).
+char(p,11956).
+char(o,11957).
+char(o,11958).
+char(o,11959).
+char(p,11960).
+char(o,11961).
+char(o,11962).
+char(m,11963).
+char(2,11964).
+char(4,11965).
+char(6,11966).
+char(4,11967).
+char(p,11968).
+char(o,11969).
+char(m,11970).
+char(o,11971).
+char(p,11972).
+char(o,11973).
+char(m,11974).
+char(6,11975).
+char(0,11976).
+char(0,11977).
+char(8,11978).
+char(p,11979).
+char(o,11980).
+char(p,11981).
+char(5,11982).
+char(1,11983).
+char(0,11984).
+char(0,11985).
+char(p,11986).
+char(3,11987).
+char(3,11988).
+char(6,11989).
+char(0,11990).
+char(c,11991).
+char(c,11992).
+char(p,11993).
+char(5,11994).
+char(6,11995).
+char(7,11996).
+char(3,11997).
+char(c,11998).
+char(p,11999).
+char(o,12000).
+char(m,12001).
+char(o,12002).
+char(o,12003).
+char(m,12004).
+char(3,12005).
+char(6,12006).
+char(3,12007).
+char(4,12008).
+char(p,12009).
+char(o,12010).
+char(o,12011).
+char(3,12012).
+char(7,12013).
+char(0,12014).
+char(4,12015).
+char(c,12016).
+char(c,12017).
+char(p,12018).
+char(1,12019).
+char(9,12020).
+char(9,12021).
+char(8,12022).
+char(p,12023).
+char(7,12024).
+char(0,12025).
+char(7,12026).
+char(9,12027).
+char(m,12028).
+char(o,12029).
+char(8,12030).
+char(5,12031).
+char(1,12032).
+char(0,12033).
+char(m,12034).
+char(o,12035).
+char(m,12036).
+char(o,12037).
+char(m,12038).
+char(o,12039).
+char(m,12040).
+char(1,12041).
+char(1,12042).
+char(0,12043).
+char(1,12044).
+char(m,12045).
+char(o,12046).
+char(o,12047).
+char(p,12048).
+char(o,12049).
+char(o,12050).
+char(5,12051).
+char(2,12052).
+char(2,12053).
+char(7,12054).
+char(c,12055).
+char(p,12056).
+char(o,12057).
+char(p,12058).
+char(o,12059).
+char(o,12060).
+char(o,12061).
+char(3,12062).
+char(9,12063).
+char(9,12064).
+char(8,12065).
+char(p,12066).
+char(o,12067).
+char(m,12068).
+char(o,12069).
+char(m,12070).
+char(1,12071).
+char(5,12072).
+char(6,12073).
+char(6,12074).
+char(m,12075).
+char(9,12076).
+char(8,12077).
+char(7,12078).
+char(m,12079).
+char(o,12080).
+char(m,12081).
+char(2,12082).
+char(9,12083).
+char(3,12084).
+char(8,12085).
+char(c,12086).
+char(p,12087).
+char(3,12088).
+char(7,12089).
+char(2,12090).
+char(1,12091).
+char(p,12092).
+char(3,12093).
+char(4,12094).
+char(1,12095).
+char(0,12096).
+char(m,12097).
+char(o,12098).
+char(o,12099).
+char(p,12100).
+char(8,12101).
+char(1,12102).
+char(1,12103).
+char(c,12104).
+char(c,12105).
+char(m,12106).
+char(o,12107).
+char(p,12108).
+char(o,12109).
+char(o,12110).
+char(p,12111).
+char(o,12112).
+char(6,12113).
+char(3,12114).
+char(4,12115).
+char(0,12116).
+char(c,12117).
+char(m,12118).
+char(o,12119).
+char(p,12120).
+char(3,12121).
+char(5,12122).
+char(5,12123).
+char(1,12124).
+char(p,12125).
+char(o,12126).
+char(o,12127).
+char(m,12128).
+char(7,12129).
+char(7,12130).
+char(4,12131).
+char(0,12132).
+char(m,12133).
+char(o,12134).
+char(m,12135).
+char(6,12136).
+char(3,12137).
+char(0,12138).
+char(6,12139).
+char(m,12140).
+char(o,12141).
+char(m,12142).
+char(o,12143).
+char(m,12144).
+char(6,12145).
+char(6,12146).
+char(3,12147).
+char(7,12148).
+char(c,12149).
+char(m,12150).
+char(o,12151).
+char(m,12152).
+char(9,12153).
+char(2,12154).
+char(4,12155).
+char(5,12156).
+char(m,12157).
+char(o,12158).
+char(p,12159).
+char(9,12160).
+char(3,12161).
+char(7,12162).
+char(2,12163).
+char(c,12164).
+char(p,12165).
+char(4,12166).
+char(8,12167).
+char(6,12168).
+char(0,12169).
+char(p,12170).
+char(o,12171).
+char(m,12172).
+char(7,12173).
+char(1,12174).
+char(6,12175).
+char(0,12176).
+char(p,12177).
+char(o,12178).
+char(p,12179).
+char(o,12180).
+char(p,12181).
+char(o,12182).
+char(m,12183).
+char(o,12184).
+char(2,12185).
+char(4,12186).
+char(1,12187).
+char(9,12188).
+char(c,12189).
+char(p,12190).
+char(o,12191).
+char(m,12192).
+char(2,12193).
+char(0,12194).
+char(0,12195).
+char(5,12196).
+char(p,12197).
+char(o,12198).
+char(m,12199).
+char(9,12200).
+char(8,12201).
+char(1,12202).
+char(8,12203).
+char(c,12204).
+char(m,12205).
+char(5,12206).
+char(3,12207).
+char(6,12208).
+char(6,12209).
+char(p,12210).
+char(8,12211).
+char(6,12212).
+char(1,12213).
+char(m,12214).
+char(o,12215).
+char(o,12216).
+char(p,12217).
+char(4,12218).
+char(8,12219).
+char(9,12220).
+char(0,12221).
+char(m,12222).
+char(1,12223).
+char(0,12224).
+char(6,12225).
+char(2,12226).
+char(p,12227).
+char(9,12228).
+char(2,12229).
+char(9,12230).
+char(7,12231).
+char(c,12232).
+char(m,12233).
+char(5,12234).
+char(1,12235).
+char(8,12236).
+char(5,12237).
+char(m,12238).
+char(o,12239).
+char(p,12240).
+char(o,12241).
+char(m,12242).
+char(o,12243).
+char(o,12244).
+char(m,12245).
+char(9,12246).
+char(7,12247).
+char(9,12248).
+char(2,12249).
+char(c,12250).
+char(p,12251).
+char(o,12252).
+char(p,12253).
+char(o,12254).
+char(4,12255).
+char(9,12256).
+char(2,12257).
+char(3,12258).
+char(c,12259).
+char(m,12260).
+char(7,12261).
+char(9,12262).
+char(3,12263).
+char(4,12264).
+char(c,12265).
+char(p,12266).
+char(4,12267).
+char(7,12268).
+char(9,12269).
+char(4,12270).
+char(c,12271).
+char(m,12272).
+char(7,12273).
+char(4,12274).
+char(3,12275).
+char(5,12276).
+char(m,12277).
+char(3,12278).
+char(8,12279).
+char(8,12280).
+char(6,12281).
+char(p,12282).
+char(o,12283).
+char(p,12284).
+char(6,12285).
+char(2,12286).
+char(4,12287).
+char(9,12288).
+char(m,12289).
+char(4,12290).
+char(4,12291).
+char(0,12292).
+char(4,12293).
+char(p,12294).
+char(7,12295).
+char(2,12296).
+char(3,12297).
+char(0,12298).
+char(c,12299).
+char(p,12300).
+char(o,12301).
+char(7,12302).
+char(5,12303).
+char(4,12304).
+char(9,12305).
+char(c,12306).
+char(m,12307).
+char(o,12308).
+char(m,12309).
+char(o,12310).
+char(o,12311).
+char(p,12312).
+char(o,12313).
+char(m,12314).
+char(o,12315).
+char(o,12316).
+char(p,12317).
+char(o,12318).
+char(p,12319).
+char(o,12320).
+char(m,12321).
+char(3,12322).
+char(6,12323).
+char(6,12324).
+char(9,12325).
+char(m,12326).
+char(o,12327).
+char(p,12328).
+char(o,12329).
+char(p,12330).
+char(o,12331).
+char(o,12332).
+char(p,12333).
+char(7,12334).
+char(1,12335).
+char(7,12336).
+char(3,12337).
+char(c,12338).
+char(c,12339).
+char(m,12340).
+char(o,12341).
+char(m,12342).
+char(o,12343).
+char(p,12344).
+char(o,12345).
+char(m,12346).
+char(o,12347).
+char(9,12348).
+char(1,12349).
+char(4,12350).
+char(2,12351).
+char(m,12352).
+char(8,12353).
+char(5,12354).
+char(6,12355).
+char(6,12356).
+char(c,12357).
+char(c,12358).
+char(p,12359).
+char(9,12360).
+char(6,12361).
+char(1,12362).
+char(1,12363).
+char(c,12364).
+char(c,12365).
+char(p,12366).
+char(5,12367).
+char(2,12368).
+char(m,12369).
+char(6,12370).
+char(1,12371).
+char(4,12372).
+char(9,12373).
+char(c,12374).
+char(m,12375).
+char(9,12376).
+char(9,12377).
+char(5,12378).
+char(4,12379).
+char(c,12380).
+char(p,12381).
+char(o,12382).
+char(9,12383).
+char(0,12384).
+char(8,12385).
+char(9,12386).
+char(c,12387).
+char(c,12388).
+char(c,12389).
+char(c,12390).
+char(p,12391).
+char(o,12392).
+char(3,12393).
+char(4,12394).
+char(3,12395).
+char(8,12396).
+char(m,12397).
+char(o,12398).
+char(3,12399).
+char(7,12400).
+char(0,12401).
+char(7,12402).
+char(p,12403).
+char(4,12404).
+char(4,12405).
+char(9,12406).
+char(8,12407).
+char(p,12408).
+char(2,12409).
+char(2,12410).
+char(9,12411).
+char(9,12412).
+char(p,12413).
+char(o,12414).
+char(o,12415).
+char(4,12416).
+char(7,12417).
+char(9,12418).
+char(4,12419).
+char(c,12420).
+char(c,12421).
+char(c,12422).
+char(p,12423).
+char(o,12424).
+char(p,12425).
+char(3,12426).
+char(1,12427).
+char(1,12428).
+char(4,12429).
+char(c,12430).
+char(c,12431).
+char(m,12432).
+char(2,12433).
+char(0,12434).
+char(9,12435).
+char(3,12436).
+char(m,12437).
+char(o,12438).
+char(m,12439).
+char(o,12440).
+char(p,12441).
+char(4,12442).
+char(1,12443).
+char(3,12444).
+char(c,12445).
+char(m,12446).
+char(o,12447).
+char(p,12448).
+char(o,12449).
+char(o,12450).
+char(p,12451).
+char(o,12452).
+char(7,12453).
+char(2,12454).
+char(9,12455).
+char(8,12456).
+char(m,12457).
+char(8,12458).
+char(1,12459).
+char(2,12460).
+char(1,12461).
+char(m,12462).
+char(3,12463).
+char(4,12464).
+char(5,12465).
+char(c,12466).
+char(c,12467).
+char(c,12468).
+char(c,12469).
+char(c,12470).
+char(p,12471).
+char(6,12472).
+char(3,12473).
+char(4,12474).
+char(9,12475).
+char(c,12476).
+char(c,12477).
+char(c,12478).
+char(c,12479).
+char(c,12480).
+char(c,12481).
+char(c,12482).
+char(p,12483).
+char(o,12484).
+char(p,12485).
+char(2,12486).
+char(8,12487).
+char(9,12488).
+char(6,12489).
+char(m,12490).
+char(o,12491).
+char(o,12492).
+char(p,12493).
+char(o,12494).
+char(m,12495).
+char(7,12496).
+char(9,12497).
+char(8,12498).
+char(9,12499).
+char(m,12500).
+char(o,12501).
+char(o,12502).
+char(m,12503).
+char(o,12504).
+char(p,12505).
+char(o,12506).
+char(5,12507).
+char(9,12508).
+char(6,12509).
+char(3,12510).
+char(p,12511).
+char(3,12512).
+char(5,12513).
+char(5,12514).
+char(p,12515).
+char(o,12516).
+char(5,12517).
+char(1,12518).
+char(9,12519).
+char(5,12520).
+char(p,12521).
+char(o,12522).
+char(p,12523).
+char(9,12524).
+char(8,12525).
+char(7,12526).
+char(c,12527).
+char(p,12528).
+char(9,12529).
+char(8,12530).
+char(4,12531).
+char(p,12532).
+char(o,12533).
+char(9,12534).
+char(4,12535).
+char(7,12536).
+char(5,12537).
+char(c,12538).
+char(c,12539).
+char(c,12540).
+char(c,12541).
+char(p,12542).
+char(2,12543).
+char(4,12544).
+char(5,12545).
+char(6,12546).
+char(m,12547).
+char(o,12548).
+char(m,12549).
+char(6,12550).
+char(5,12551).
+char(7,12552).
+char(9,12553).
+char(c,12554).
+char(m,12555).
+char(9,12556).
+char(3,12557).
+char(5,12558).
+char(7,12559).
+char(p,12560).
+char(3,12561).
+char(8,12562).
+char(5,12563).
+char(6,12564).
+char(c,12565).
+char(c,12566).
+char(m,12567).
+char(o,12568).
+char(p,12569).
+char(9,12570).
+char(7,12571).
+char(3,12572).
+char(8,12573).
+char(c,12574).
+char(c,12575).
+char(c,12576).
+char(m,12577).
+char(9,12578).
+char(5,12579).
+char(0,12580).
+char(3,12581).
+char(c,12582).
+char(c,12583).
+char(p,12584).
+char(o,12585).
+char(m,12586).
+char(6,12587).
+char(0,12588).
+char(2,12589).
+char(7,12590).
+char(c,12591).
+char(c,12592).
+char(c,12593).
+char(m,12594).
+char(6,12595).
+char(1,12596).
+char(4,12597).
+char(0,12598).
+char(p,12599).
+char(6,12600).
+char(1,12601).
+char(3,12602).
+char(4,12603).
+char(p,12604).
+char(o,12605).
+char(m,12606).
+char(o,12607).
+char(m,12608).
+char(o,12609).
+char(4,12610).
+char(3,12611).
+char(5,12612).
+char(2,12613).
+char(c,12614).
+char(c,12615).
+char(m,12616).
+char(4,12617).
+char(1,12618).
+char(0,12619).
+char(1,12620).
+char(p,12621).
+char(o,12622).
+char(m,12623).
+char(2,12624).
+char(9,12625).
+char(3,12626).
+char(6,12627).
+char(c,12628).
+char(m,12629).
+char(8,12630).
+char(4,12631).
+char(5,12632).
+char(0,12633).
+char(m,12634).
+char(4,12635).
+char(6,12636).
+char(4,12637).
+char(2,12638).
+char(p,12639).
+char(o,12640).
+char(p,12641).
+char(o,12642).
+char(p,12643).
+char(1,12644).
+char(6,12645).
+char(8,12646).
+char(4,12647).
+char(p,12648).
+char(o,12649).
+char(m,12650).
+char(8,12651).
+char(0,12652).
+char(1,12653).
+char(2,12654).
+char(p,12655).
+char(o,12656).
+char(m,12657).
+char(o,12658).
+char(o,12659).
+char(p,12660).
+char(o,12661).
+char(p,12662).
+char(4,12663).
+char(8,12664).
+char(5,12665).
+char(7,12666).
+char(p,12667).
+char(o,12668).
+char(p,12669).
+char(o,12670).
+char(m,12671).
+char(6,12672).
+char(3,12673).
+char(8,12674).
+char(5,12675).
+char(p,12676).
+char(7,12677).
+char(8,12678).
+char(0,12679).
+char(c,12680).
+char(c,12681).
+char(m,12682).
+char(o,12683).
+char(m,12684).
+char(o,12685).
+char(2,12686).
+char(6,12687).
+char(5,12688).
+char(1,12689).
+char(m,12690).
+char(o,12691).
+char(m,12692).
+char(o,12693).
+char(m,12694).
+char(4,12695).
+char(9,12696).
+char(3,12697).
+char(3,12698).
+char(p,12699).
+char(7,12700).
+char(5,12701).
+char(2,12702).
+char(7,12703).
+char(p,12704).
+char(3,12705).
+char(1,12706).
+char(9,12707).
+char(6,12708).
+char(p,12709).
+char(o,12710).
+char(p,12711).
+char(5,12712).
+char(9,12713).
+char(9,12714).
+char(0,12715).
+char(c,12716).
+char(p,12717).
+char(o,12718).
+char(p,12719).
+char(3,12720).
+char(0,12721).
+char(6,12722).
+char(5,12723).
+char(m,12724).
+char(o,12725).
+char(m,12726).
+char(8,12727).
+char(7,12728).
+char(4,12729).
+char(2,12730).
+char(m,12731).
+char(o,12732).
+char(m,12733).
+char(o,12734).
+char(p,12735).
+char(o,12736).
+char(o,12737).
+char(p,12738).
+char(o,12739).
+char(p,12740).
+char(o,12741).
+char(p,12742).
+char(o,12743).
+char(p,12744).
+char(o,12745).
+char(m,12746).
+char(o,12747).
+char(p,12748).
+char(2,12749).
+char(6,12750).
+char(9,12751).
+char(0,12752).
+char(p,12753).
+char(o,12754).
+char(o,12755).
+char(m,12756).
+char(5,12757).
+char(7,12758).
+char(8,12759).
+char(5,12760).
+char(c,12761).
+char(c,12762).
+char(m,12763).
+char(8,12764).
+char(8,12765).
+char(6,12766).
+char(0,12767).
+char(p,12768).
+char(o,12769).
+char(1,12770).
+char(0,12771).
+char(7,12772).
+char(5,12773).
+char(m,12774).
+char(o,12775).
+char(p,12776).
+char(7,12777).
+char(3,12778).
+char(3,12779).
+char(0,12780).
+char(m,12781).
+char(9,12782).
+char(4,12783).
+char(5,12784).
+char(2,12785).
+char(c,12786).
+char(m,12787).
+char(o,12788).
+char(4,12789).
+char(5,12790).
+char(8,12791).
+char(5,12792).
+char(c,12793).
+char(c,12794).
+char(c,12795).
+char(c,12796).
+char(m,12797).
+char(5,12798).
+char(1,12799).
+char(0,12800).
+char(3,12801).
+char(c,12802).
+char(c,12803).
+char(p,12804).
+char(9,12805).
+char(9,12806).
+char(8,12807).
+char(6,12808).
+char(c,12809).
+char(m,12810).
+char(o,12811).
+char(p,12812).
+char(8,12813).
+char(6,12814).
+char(7,12815).
+char(0,12816).
+char(c,12817).
+char(p,12818).
+char(o,12819).
+char(p,12820).
+char(o,12821).
+char(p,12822).
+char(o,12823).
+char(2,12824).
+char(2,12825).
+char(4,12826).
+char(8,12827).
+char(c,12828).
+char(c,12829).
+char(m,12830).
+char(o,12831).
+char(p,12832).
+char(o,12833).
+char(p,12834).
+char(2,12835).
+char(3,12836).
+char(1,12837).
+char(9,12838).
+char(c,12839).
+char(m,12840).
+char(5,12841).
+char(1,12842).
+char(7,12843).
+char(c,12844).
+char(p,12845).
+char(2,12846).
+char(2,12847).
+char(8,12848).
+char(9,12849).
+char(c,12850).
+char(c,12851).
+char(p,12852).
+char(o,12853).
+char(m,12854).
+char(9,12855).
+char(3,12856).
+char(1,12857).
+char(3,12858).
+char(m,12859).
+char(8,12860).
+char(0,12861).
+char(5,12862).
+char(9,12863).
+char(p,12864).
+char(o,12865).
+char(m,12866).
+char(3,12867).
+char(1,12868).
+char(9,12869).
+char(7,12870).
+char(c,12871).
+char(c,12872).
+char(m,12873).
+char(8,12874).
+char(2,12875).
+char(6,12876).
+char(5,12877).
+char(p,12878).
+char(4,12879).
+char(4,12880).
+char(9,12881).
+char(8,12882).
+char(p,12883).
+char(7,12884).
+char(1,12885).
+char(2,12886).
+char(9,12887).
+char(c,12888).
+char(c,12889).
+char(c,12890).
+char(p,12891).
+char(3,12892).
+char(5,12893).
+char(1,12894).
+char(3,12895).
+char(c,12896).
+char(c,12897).
+char(c,12898).
+char(p,12899).
+char(o,12900).
+char(p,12901).
+char(o,12902).
+char(5,12903).
+char(7,12904).
+char(8,12905).
+char(6,12906).
+char(c,12907).
+char(p,12908).
+char(o,12909).
+char(9,12910).
+char(1,12911).
+char(4,12912).
+char(5,12913).
+char(c,12914).
+char(m,12915).
+char(o,12916).
+char(p,12917).
+char(7,12918).
+char(3,12919).
+char(1,12920).
+char(5,12921).
+char(c,12922).
+char(p,12923).
+char(o,12924).
+char(m,12925).
+char(o,12926).
+char(o,12927).
+char(o,12928).
+char(p,12929).
+char(o,12930).
+char(m,12931).
+char(o,12932).
+char(p,12933).
+char(o,12934).
+char(1,12935).
+char(8,12936).
+char(0,12937).
+char(2,12938).
+char(p,12939).
+char(9,12940).
+char(2,12941).
+char(4,12942).
+char(1,12943).
+char(c,12944).
+char(c,12945).
+char(m,12946).
+char(6,12947).
+char(8,12948).
+char(1,12949).
+char(m,12950).
+char(8,12951).
+char(9,12952).
+char(8,12953).
+char(8,12954).
+char(m,12955).
+char(o,12956).
+char(6,12957).
+char(8,12958).
+char(6,12959).
+char(6,12960).
+char(m,12961).
+char(7,12962).
+char(3,12963).
+char(2,12964).
+char(7,12965).
+char(c,12966).
+char(m,12967).
+char(o,12968).
+char(2,12969).
+char(1,12970).
+char(5,12971).
+char(3,12972).
+char(c,12973).
+char(p,12974).
+char(3,12975).
+char(7,12976).
+char(0,12977).
+char(4,12978).
+char(m,12979).
+char(o,12980).
+char(p,12981).
+char(o,12982).
+char(p,12983).
+char(o,12984).
+char(3,12985).
+char(4,12986).
+char(7,12987).
+char(6,12988).
+char(c,12989).
+char(p,12990).
+char(o,12991).
+char(p,12992).
+char(o,12993).
+char(m,12994).
+char(o,12995).
+char(8,12996).
+char(8,12997).
+char(0,12998).
+char(6,12999).
+char(c,13000).
+char(c,13001).
+char(c,13002).
+char(p,13003).
+char(1,13004).
+char(3,13005).
+char(1,13006).
+char(7,13007).
+char(c,13008).
+char(c,13009).
+char(c,13010).
+char(c,13011).
+char(c,13012).
+char(p,13013).
+char(o,13014).
+char(3,13015).
+char(3,13016).
+char(9,13017).
+char(8,13018).
+char(c,13019).
+char(c,13020).
+char(m,13021).
+char(1,13022).
+char(6,13023).
+char(2,13024).
+char(1,13025).
+char(c,13026).
+char(p,13027).
+char(o,13028).
+char(8,13029).
+char(7,13030).
+char(3,13031).
+char(5,13032).
+char(p,13033).
+char(7,13034).
+char(3,13035).
+char(6,13036).
+char(7,13037).
+char(c,13038).
+char(m,13039).
+char(o,13040).
+char(m,13041).
+char(1,13042).
+char(3,13043).
+char(0,13044).
+char(3,13045).
+char(c,13046).
+char(m,13047).
+char(o,13048).
+char(o,13049).
+char(m,13050).
+char(9,13051).
+char(5,13052).
+char(2,13053).
+char(8,13054).
+char(c,13055).
+char(p,13056).
+char(o,13057).
+char(p,13058).
+char(6,13059).
+char(6,13060).
+char(0,13061).
+char(0,13062).
+char(c,13063).
+char(c,13064).
+char(c,13065).
+char(p,13066).
+char(o,13067).
+char(p,13068).
+char(9,13069).
+char(3,13070).
+char(9,13071).
+char(2,13072).
+char(p,13073).
+char(6,13074).
+char(9,13075).
+char(8,13076).
+char(3,13077).
+char(c,13078).
+char(p,13079).
+char(1,13080).
+char(1,13081).
+char(1,13082).
+char(1,13083).
+char(c,13084).
+char(m,13085).
+char(4,13086).
+char(0,13087).
+char(7,13088).
+char(7,13089).
+char(p,13090).
+char(8,13091).
+char(3,13092).
+char(5,13093).
+char(5,13094).
+char(c,13095).
+char(p,13096).
+char(6,13097).
+char(9,13098).
+char(5,13099).
+char(6,13100).
+char(p,13101).
+char(5,13102).
+char(8,13103).
+char(5,13104).
+char(2,13105).
+char(p,13106).
+char(o,13107).
+char(p,13108).
+char(5,13109).
+char(0,13110).
+char(4,13111).
+char(3,13112).
+char(c,13113).
+char(c,13114).
+char(p,13115).
+char(8,13116).
+char(7,13117).
+char(9,13118).
+char(2,13119).
+char(c,13120).
+char(c,13121).
+char(m,13122).
+char(3,13123).
+char(4,13124).
+char(6,13125).
+char(1,13126).
+char(m,13127).
+char(4,13128).
+char(9,13129).
+char(7,13130).
+char(m,13131).
+char(o,13132).
+char(9,13133).
+char(6,13134).
+char(3,13135).
+char(c,13136).
+char(c,13137).
+char(c,13138).
+char(c,13139).
+char(m,13140).
+char(o,13141).
+char(2,13142).
+char(0,13143).
+char(5,13144).
+char(9,13145).
+char(p,13146).
+char(o,13147).
+char(p,13148).
+char(o,13149).
+char(p,13150).
+char(9,13151).
+char(6,13152).
+char(8,13153).
+char(3,13154).
+char(p,13155).
+char(5,13156).
+char(7,13157).
+char(1,13158).
+char(3,13159).
+char(c,13160).
+char(p,13161).
+char(o,13162).
+char(p,13163).
+char(1,13164).
+char(2,13165).
+char(9,13166).
+char(7,13167).
+char(c,13168).
+char(c,13169).
+char(m,13170).
+char(o,13171).
+char(6,13172).
+char(9,13173).
+char(5,13174).
+char(7,13175).
+char(c,13176).
+char(c,13177).
+char(c,13178).
+char(m,13179).
+char(5,13180).
+char(9,13181).
+char(7,13182).
+char(4,13183).
+char(c,13184).
+char(c,13185).
+char(c,13186).
+char(c,13187).
+char(m,13188).
+char(o,13189).
+char(p,13190).
+char(o,13191).
+char(p,13192).
+char(8,13193).
+char(7,13194).
+char(0,13195).
+char(2,13196).
+char(c,13197).
+char(c,13198).
+char(c,13199).
+char(p,13200).
+char(o,13201).
+char(o,13202).
+char(1,13203).
+char(2,13204).
+char(0,13205).
+char(1,13206).
+char(c,13207).
+char(p,13208).
+char(4,13209).
+char(1,13210).
+char(4,13211).
+char(9,13212).
+char(p,13213).
+char(o,13214).
+char(o,13215).
+char(p,13216).
+char(o,13217).
+char(o,13218).
+char(m,13219).
+char(3,13220).
+char(3,13221).
+char(9,13222).
+char(8,13223).
+char(c,13224).
+char(c,13225).
+char(c,13226).
+char(c,13227).
+char(c,13228).
+char(c,13229).
+char(c,13230).
+char(c,13231).
+char(p,13232).
+char(4,13233).
+char(3,13234).
+char(2,13235).
+char(6,13236).
+char(p,13237).
+char(o,13238).
+char(p,13239).
+char(o,13240).
+char(o,13241).
+char(p,13242).
+char(o,13243).
+char(m,13244).
+char(3,13245).
+char(3,13246).
+char(1,13247).
+char(8,13248).
+char(m,13249).
+char(o,13250).
+char(4,13251).
+char(7,13252).
+char(2,13253).
+char(0,13254).
+char(c,13255).
+char(p,13256).
+char(8,13257).
+char(2,13258).
+char(2,13259).
+char(6,13260).
+char(m,13261).
+char(4,13262).
+char(4,13263).
+char(9,13264).
+char(9,13265).
+char(c,13266).
+char(c,13267).
+char(m,13268).
+char(o,13269).
+char(m,13270).
+char(3,13271).
+char(1,13272).
+char(7,13273).
+char(6,13274).
+char(p,13275).
+char(o,13276).
+char(5,13277).
+char(3,13278).
+char(2,13279).
+char(1,13280).
+char(m,13281).
+char(o,13282).
+char(m,13283).
+char(1,13284).
+char(3,13285).
+char(2,13286).
+char(2,13287).
+char(c,13288).
+char(m,13289).
+char(9,13290).
+char(1,13291).
+char(4,13292).
+char(5,13293).
+char(c,13294).
+char(c,13295).
+char(m,13296).
+char(o,13297).
+char(7,13298).
+char(2,13299).
+char(9,13300).
+char(1,13301).
+char(c,13302).
+char(p,13303).
+char(o,13304).
+char(o,13305).
+char(m,13306).
+char(o,13307).
+char(m,13308).
+char(o,13309).
+char(m,13310).
+char(4,13311).
+char(2,13312).
+char(7,13313).
+char(2,13314).
+char(c,13315).
+char(p,13316).
+char(o,13317).
+char(m,13318).
+char(6,13319).
+char(3,13320).
+char(9,13321).
+char(4,13322).
+char(m,13323).
+char(9,13324).
+char(4,13325).
+char(5,13326).
+char(2,13327).
+char(p,13328).
+char(5,13329).
+char(6,13330).
+char(9,13331).
+char(6,13332).
+char(p,13333).
+char(o,13334).
+char(o,13335).
+char(p,13336).
+char(7,13337).
+char(2,13338).
+char(6,13339).
+char(5,13340).
+char(c,13341).
+char(c,13342).
+char(p,13343).
+char(9,13344).
+char(3,13345).
+char(5,13346).
+char(5,13347).
+char(p,13348).
+char(o,13349).
+char(8,13350).
+char(9,13351).
+char(2,13352).
+char(6,13353).
+char(m,13354).
+char(o,13355).
+char(p,13356).
+char(6,13357).
+char(2,13358).
+char(5,13359).
+char(6,13360).
+char(c,13361).
+char(m,13362).
+char(9,13363).
+char(7,13364).
+char(5,13365).
+char(9,13366).
+char(c,13367).
+char(c,13368).
+char(c,13369).
+char(c,13370).
+char(m,13371).
+char(4,13372).
+char(7,13373).
+char(8,13374).
+char(8,13375).
+char(c,13376).
+char(c,13377).
+char(c,13378).
+char(m,13379).
+char(o,13380).
+char(m,13381).
+char(2,13382).
+char(6,13383).
+char(0,13384).
+char(3,13385).
+char(c,13386).
+char(p,13387).
+char(2,13388).
+char(2,13389).
+char(2,13390).
+char(2,13391).
+char(m,13392).
+char(o,13393).
+char(m,13394).
+char(o,13395).
+char(m,13396).
+char(9,13397).
+char(1,13398).
+char(5,13399).
+char(9,13400).
+char(m,13401).
+char(7,13402).
+char(9,13403).
+char(8,13404).
+char(8,13405).
+char(p,13406).
+char(o,13407).
+char(p,13408).
+char(o,13409).
+char(o,13410).
+char(m,13411).
+char(o,13412).
+char(p,13413).
+char(o,13414).
+char(o,13415).
+char(p,13416).
+char(5,13417).
+char(3,13418).
+char(6,13419).
+char(0,13420).
+char(c,13421).
+char(m,13422).
+char(o,13423).
+char(8,13424).
+char(6,13425).
+char(4,13426).
+char(7,13427).
+char(m,13428).
+char(o,13429).
+char(2,13430).
+char(3,13431).
+char(6,13432).
+char(9,13433).
+char(m,13434).
+char(7,13435).
+char(0,13436).
+char(5,13437).
+char(3,13438).
+char(c,13439).
+char(c,13440).
+char(c,13441).
+char(c,13442).
+char(c,13443).
+char(p,13444).
+char(o,13445).
+char(o,13446).
+char(p,13447).
+char(o,13448).
+char(o,13449).
+char(o,13450).
+char(m,13451).
+char(4,13452).
+char(0,13453).
+char(7,13454).
+char(4,13455).
+char(c,13456).
+char(c,13457).
+char(m,13458).
+char(6,13459).
+char(0,13460).
+char(9,13461).
+char(5,13462).
+char(c,13463).
+char(c,13464).
+char(c,13465).
+char(p,13466).
+char(o,13467).
+char(m,13468).
+char(o,13469).
+char(m,13470).
+char(4,13471).
+char(8,13472).
+char(3,13473).
+char(3,13474).
+char(m,13475).
+char(o,13476).
+char(p,13477).
+char(o,13478).
+char(m,13479).
+char(6,13480).
+char(5,13481).
+char(9,13482).
+char(6,13483).
+char(c,13484).
+char(c,13485).
+char(c,13486).
+char(c,13487).
+char(p,13488).
+char(o,13489).
+char(1,13490).
+char(2,13491).
+char(3,13492).
+char(2,13493).
+char(c,13494).
+char(c,13495).
+char(p,13496).
+char(6,13497).
+char(4,13498).
+char(8,13499).
+char(3,13500).
+char(p,13501).
+char(7,13502).
+char(5,13503).
+char(3,13504).
+char(3,13505).
+char(p,13506).
+char(1,13507).
+char(4,13508).
+char(7,13509).
+char(8,13510).
+char(c,13511).
+char(p,13512).
+char(9,13513).
+char(1,13514).
+char(5,13515).
+char(3,13516).
+char(m,13517).
+char(5,13518).
+char(0,13519).
+char(3,13520).
+char(4,13521).
+char(c,13522).
+char(p,13523).
+char(9,13524).
+char(8,13525).
+char(3,13526).
+char(2,13527).
+char(c,13528).
+char(c,13529).
+char(c,13530).
+char(m,13531).
+char(2,13532).
+char(7,13533).
+char(7,13534).
+char(1,13535).
+char(c,13536).
+char(m,13537).
+char(5,13538).
+char(3,13539).
+char(3,13540).
+char(6,13541).
+char(c,13542).
+char(c,13543).
+char(p,13544).
+char(o,13545).
+char(m,13546).
+char(2,13547).
+char(4,13548).
+char(0,13549).
+char(2,13550).
+char(p,13551).
+char(o,13552).
+char(m,13553).
+char(o,13554).
+char(m,13555).
+char(5,13556).
+char(3,13557).
+char(6,13558).
+char(4,13559).
+char(c,13560).
+char(c,13561).
+char(p,13562).
+char(6,13563).
+char(3,13564).
+char(2,13565).
+char(2,13566).
+char(m,13567).
+char(5,13568).
+char(0,13569).
+char(8,13570).
+char(2,13571).
+char(p,13572).
+char(o,13573).
+char(5,13574).
+char(9,13575).
+char(5,13576).
+char(6,13577).
+char(p,13578).
+char(o,13579).
+char(o,13580).
+char(o,13581).
+char(2,13582).
+char(8,13583).
+char(0,13584).
+char(9,13585).
+char(c,13586).
+char(m,13587).
+char(o,13588).
+char(m,13589).
+char(7,13590).
+char(4,13591).
+char(4,13592).
+char(5,13593).
+char(p,13594).
+char(4,13595).
+char(7,13596).
+char(4,13597).
+char(4,13598).
+char(m,13599).
+char(9,13600).
+char(7,13601).
+char(3,13602).
+char(5,13603).
+char(p,13604).
+char(9,13605).
+char(4,13606).
+char(8,13607).
+char(4,13608).
+char(p,13609).
+char(3,13610).
+char(4,13611).
+char(0,13612).
+char(7,13613).
+char(p,13614).
+char(o,13615).
+char(o,13616).
+char(p,13617).
+char(8,13618).
+char(6,13619).
+char(5,13620).
+char(m,13621).
+char(8,13622).
+char(3,13623).
+char(1,13624).
+char(6,13625).
+char(c,13626).
+char(p,13627).
+char(5,13628).
+char(5,13629).
+char(3,13630).
+char(8,13631).
+char(c,13632).
+char(c,13633).
+char(c,13634).
+char(c,13635).
+char(m,13636).
+char(2,13637).
+char(7,13638).
+char(9,13639).
+char(5,13640).
+char(c,13641).
+char(c,13642).
+char(c,13643).
+char(c,13644).
+char(p,13645).
+char(4,13646).
+char(7,13647).
+char(3,13648).
+char(4,13649).
+char(c,13650).
+char(p,13651).
+char(6,13652).
+char(2,13653).
+char(5,13654).
+char(3,13655).
+char(c,13656).
+char(c,13657).
+char(c,13658).
+char(c,13659).
+char(m,13660).
+char(8,13661).
+char(3,13662).
+char(6,13663).
+char(0,13664).
+char(m,13665).
+char(4,13666).
+char(3,13667).
+char(8,13668).
+char(8,13669).
+char(c,13670).
+char(c,13671).
+char(c,13672).
+char(c,13673).
+char(c,13674).
+char(p,13675).
+char(8,13676).
+char(8,13677).
+char(2,13678).
+char(3,13679).
+char(c,13680).
+char(c,13681).
+char(m,13682).
+char(5,13683).
+char(2,13684).
+char(6,13685).
+char(6,13686).
+char(c,13687).
+char(c,13688).
+char(p,13689).
+char(8,13690).
+char(6,13691).
+char(2,13692).
+char(m,13693).
+char(o,13694).
+char(m,13695).
+char(6,13696).
+char(0,13697).
+char(4,13698).
+char(1,13699).
+char(m,13700).
+char(o,13701).
+char(m,13702).
+char(2,13703).
+char(7,13704).
+char(9,13705).
+char(1,13706).
+char(c,13707).
+char(m,13708).
+char(7,13709).
+char(7,13710).
+char(8,13711).
+char(5,13712).
+char(c,13713).
+char(c,13714).
+char(m,13715).
+char(9,13716).
+char(0,13717).
+char(6,13718).
+char(2,13719).
+char(c,13720).
+char(m,13721).
+char(o,13722).
+char(m,13723).
+char(o,13724).
+char(m,13725).
+char(o,13726).
+char(m,13727).
+char(3,13728).
+char(8,13729).
+char(1,13730).
+char(8,13731).
+char(m,13732).
+char(5,13733).
+char(3,13734).
+char(6,13735).
+char(6,13736).
+char(c,13737).
+char(m,13738).
+char(7,13739).
+char(5,13740).
+char(3,13741).
+char(0,13742).
+char(p,13743).
+char(o,13744).
+char(p,13745).
+char(2,13746).
+char(2,13747).
+char(1,13748).
+char(1,13749).
+char(c,13750).
+char(c,13751).
+char(p,13752).
+char(3,13753).
+char(4,13754).
+char(5,13755).
+char(4,13756).
+char(p,13757).
+char(8,13758).
+char(1,13759).
+char(0,13760).
+char(0,13761).
+char(m,13762).
+char(6,13763).
+char(8,13764).
+char(3,13765).
+char(p,13766).
+char(o,13767).
+char(p,13768).
+char(7,13769).
+char(6,13770).
+char(2,13771).
+char(0,13772).
+char(c,13773).
+char(p,13774).
+char(o,13775).
+char(m,13776).
+char(1,13777).
+char(4,13778).
+char(4,13779).
+char(5,13780).
+char(c,13781).
+char(c,13782).
+char(c,13783).
+char(p,13784).
+char(o,13785).
+char(o,13786).
+char(p,13787).
+char(7,13788).
+char(3,13789).
+char(7,13790).
+char(6,13791).
+char(c,13792).
+char(c,13793).
+char(m,13794).
+char(4,13795).
+char(0,13796).
+char(8,13797).
+char(5,13798).
+char(m,13799).
+char(o,13800).
+char(o,13801).
+char(m,13802).
+char(5,13803).
+char(0,13804).
+char(5,13805).
+char(1,13806).
+char(c,13807).
+char(m,13808).
+char(o,13809).
+char(p,13810).
+char(o,13811).
+char(m,13812).
+char(o,13813).
+char(p,13814).
+char(3,13815).
+char(2,13816).
+char(2,13817).
+char(0,13818).
+char(c,13819).
+char(c,13820).
+char(c,13821).
+char(c,13822).
+char(p,13823).
+char(4,13824).
+char(7,13825).
+char(3,13826).
+char(m,13827).
+char(1,13828).
+char(6,13829).
+char(8,13830).
+char(8,13831).
+char(c,13832).
+char(p,13833).
+char(7,13834).
+char(7,13835).
+char(2,13836).
+char(3,13837).
+char(p,13838).
+char(7,13839).
+char(0,13840).
+char(5,13841).
+char(6,13842).
+char(p,13843).
+char(o,13844).
+char(m,13845).
+char(5,13846).
+char(9,13847).
+char(5,13848).
+char(4,13849).
+char(m,13850).
+char(5,13851).
+char(0,13852).
+char(6,13853).
+char(1,13854).
+char(c,13855).
+char(m,13856).
+char(o,13857).
+char(p,13858).
+char(o,13859).
+char(p,13860).
+char(1,13861).
+char(5,13862).
+char(7,13863).
+char(1,13864).
+char(p,13865).
+char(o,13866).
+char(8,13867).
+char(2,13868).
+char(3,13869).
+char(0,13870).
+char(c,13871).
+char(c,13872).
+char(c,13873).
+char(p,13874).
+char(o,13875).
+char(p,13876).
+char(o,13877).
+char(p,13878).
+char(o,13879).
+char(8,13880).
+char(6,13881).
+char(8,13882).
+char(m,13883).
+char(o,13884).
+char(6,13885).
+char(4,13886).
+char(3,13887).
+char(4,13888).
+char(p,13889).
+char(2,13890).
+char(9,13891).
+char(3,13892).
+char(5,13893).
+char(p,13894).
+char(o,13895).
+char(m,13896).
+char(1,13897).
+char(1,13898).
+char(2,13899).
+char(9,13900).
+char(m,13901).
+char(o,13902).
+char(m,13903).
+char(4,13904).
+char(7,13905).
+char(9,13906).
+char(8,13907).
+char(c,13908).
+char(c,13909).
+char(c,13910).
+char(p,13911).
+char(9,13912).
+char(3,13913).
+char(1,13914).
+char(1,13915).
+char(c,13916).
+char(c,13917).
+char(c,13918).
+char(m,13919).
+char(6,13920).
+char(4,13921).
+char(8,13922).
+char(0,13923).
+char(c,13924).
+char(c,13925).
+char(c,13926).
+char(m,13927).
+char(o,13928).
+char(m,13929).
+char(1,13930).
+char(4,13931).
+char(1,13932).
+char(m,13933).
+char(o,13934).
+char(7,13935).
+char(1,13936).
+char(0,13937).
+char(5,13938).
+char(m,13939).
+char(o,13940).
+char(m,13941).
+char(o,13942).
+char(m,13943).
+char(8,13944).
+char(5,13945).
+char(7,13946).
+char(1,13947).
+char(p,13948).
+char(o,13949).
+char(o,13950).
+char(6,13951).
+char(5,13952).
+char(2,13953).
+char(8,13954).
+char(m,13955).
+char(o,13956).
+char(p,13957).
+char(o,13958).
+char(p,13959).
+char(1,13960).
+char(6,13961).
+char(3,13962).
+char(5,13963).
+char(m,13964).
+char(6,13965).
+char(3,13966).
+char(8,13967).
+char(9,13968).
+char(p,13969).
+char(9,13970).
+char(1,13971).
+char(2,13972).
+char(c,13973).
+char(c,13974).
+char(m,13975).
+char(o,13976).
+char(p,13977).
+char(8,13978).
+char(9,13979).
+char(6,13980).
+char(7,13981).
+char(c,13982).
+char(p,13983).
+char(o,13984).
+char(9,13985).
+char(0,13986).
+char(7,13987).
+char(9,13988).
+char(p,13989).
+char(o,13990).
+char(o,13991).
+char(o,13992).
+char(p,13993).
+char(4,13994).
+char(1,13995).
+char(9,13996).
+char(8,13997).
+char(p,13998).
+char(o,13999).
+char(2,14000).
+char(0,14001).
+char(5,14002).
+char(c,14003).
+char(c,14004).
+char(p,14005).
+char(o,14006).
+char(1,14007).
+char(5,14008).
+char(9,14009).
+char(6,14010).
+char(c,14011).
+char(p,14012).
+char(4,14013).
+char(0,14014).
+char(4,14015).
+char(6,14016).
+char(c,14017).
+char(c,14018).
+char(p,14019).
+char(5,14020).
+char(4,14021).
+char(4,14022).
+char(3,14023).
+char(c,14024).
+char(c,14025).
+char(c,14026).
+char(c,14027).
+char(c,14028).
+char(p,14029).
+char(o,14030).
+char(p,14031).
+char(o,14032).
+char(m,14033).
+char(o,14034).
+char(p,14035).
+char(9,14036).
+char(2,14037).
+char(8,14038).
+char(0,14039).
+char(m,14040).
+char(o,14041).
+char(4,14042).
+char(5,14043).
+char(2,14044).
+char(9,14045).
+char(c,14046).
+char(m,14047).
+char(o,14048).
+char(p,14049).
+char(o,14050).
+char(p,14051).
+char(4,14052).
+char(5,14053).
+char(5,14054).
+char(9,14055).
+char(m,14056).
+char(3,14057).
+char(0,14058).
+char(8,14059).
+char(5,14060).
+char(p,14061).
+char(9,14062).
+char(0,14063).
+char(3,14064).
+char(2,14065).
+char(p,14066).
+char(8,14067).
+char(3,14068).
+char(2,14069).
+char(0,14070).
+char(c,14071).
+char(p,14072).
+char(5,14073).
+char(4,14074).
+char(0,14075).
+char(9,14076).
+char(c,14077).
+char(c,14078).
+char(m,14079).
+char(o,14080).
+char(m,14081).
+char(o,14082).
+char(m,14083).
+char(o,14084).
+char(m,14085).
+char(2,14086).
+char(1,14087).
+char(2,14088).
+char(0,14089).
+char(c,14090).
+char(c,14091).
+char(m,14092).
+char(3,14093).
+char(8,14094).
+char(4,14095).
+char(0,14096).
+char(c,14097).
+char(c,14098).
+char(m,14099).
+char(o,14100).
+char(m,14101).
+char(o,14102).
+char(m,14103).
+char(2,14104).
+char(4,14105).
+char(9,14106).
+char(c,14107).
+char(c,14108).
+char(p,14109).
+char(4,14110).
+char(7,14111).
+char(2,14112).
+char(2,14113).
+char(c,14114).
+char(m,14115).
+char(8,14116).
+char(6,14117).
+char(1,14118).
+char(6,14119).
+char(c,14120).
+char(m,14121).
+char(5,14122).
+char(9,14123).
+char(7,14124).
+char(9,14125).
+char(c,14126).
+char(c,14127).
+char(p,14128).
+char(o,14129).
+char(p,14130).
+char(o,14131).
+char(m,14132).
+char(o,14133).
+char(m,14134).
+char(o,14135).
+char(3,14136).
+char(8,14137).
+char(1,14138).
+char(6,14139).
+char(p,14140).
+char(8,14141).
+char(8,14142).
+char(2,14143).
+char(0,14144).
+char(m,14145).
+char(9,14146).
+char(0,14147).
+char(0,14148).
+char(5,14149).
+char(c,14150).
+char(c,14151).
+char(c,14152).
+char(p,14153).
+char(2,14154).
+char(2,14155).
+char(5,14156).
+char(1,14157).
+char(c,14158).
+char(c,14159).
+char(c,14160).
+char(m,14161).
+char(o,14162).
+char(p,14163).
+char(9,14164).
+char(5,14165).
+char(0,14166).
+char(2,14167).
+char(m,14168).
+char(8,14169).
+char(0,14170).
+char(4,14171).
+char(6,14172).
+char(c,14173).
+char(p,14174).
+char(o,14175).
+char(m,14176).
+char(o,14177).
+char(p,14178).
+char(1,14179).
+char(5,14180).
+char(8,14181).
+char(5,14182).
+char(m,14183).
+char(8,14184).
+char(0,14185).
+char(6,14186).
+char(2,14187).
+char(m,14188).
+char(6,14189).
+char(5,14190).
+char(6,14191).
+char(c,14192).
+char(c,14193).
+char(c,14194).
+char(m,14195).
+char(4,14196).
+char(7,14197).
+char(8,14198).
+char(c,14199).
+char(c,14200).
+char(m,14201).
+char(6,14202).
+char(9,14203).
+char(5,14204).
+char(9,14205).
+char(c,14206).
+char(c,14207).
+char(c,14208).
+char(p,14209).
+char(o,14210).
+char(o,14211).
+char(m,14212).
+char(o,14213).
+char(p,14214).
+char(o,14215).
+char(o,14216).
+char(p,14217).
+char(o,14218).
+char(o,14219).
+char(m,14220).
+char(5,14221).
+char(3,14222).
+char(0,14223).
+char(4,14224).
+char(c,14225).
+char(c,14226).
+char(c,14227).
+char(m,14228).
+char(9,14229).
+char(2,14230).
+char(p,14231).
+char(o,14232).
+char(o,14233).
+char(m,14234).
+char(o,14235).
+char(1,14236).
+char(6,14237).
+char(9,14238).
+char(2,14239).
+char(m,14240).
+char(o,14241).
+char(m,14242).
+char(o,14243).
+char(o,14244).
+char(p,14245).
+char(4,14246).
+char(3,14247).
+char(4,14248).
+char(8,14249).
+char(c,14250).
+char(c,14251).
+char(p,14252).
+char(o,14253).
+char(o,14254).
+char(m,14255).
+char(3,14256).
+char(5,14257).
+char(1,14258).
+char(8,14259).
+char(m,14260).
+char(o,14261).
+char(p,14262).
+char(o,14263).
+char(m,14264).
+char(9,14265).
+char(9,14266).
+char(7,14267).
+char(9,14268).
+char(m,14269).
+char(8,14270).
+char(9,14271).
+char(2,14272).
+char(7,14273).
+char(m,14274).
+char(o,14275).
+char(1,14276).
+char(7,14277).
+char(9,14278).
+char(9,14279).
+char(c,14280).
+char(p,14281).
+char(o,14282).
+char(p,14283).
+char(3,14284).
+char(5,14285).
+char(9,14286).
+char(1,14287).
+char(c,14288).
+char(p,14289).
+char(o,14290).
+char(m,14291).
+char(5,14292).
+char(6,14293).
+char(2,14294).
+char(4,14295).
+char(c,14296).
+char(c,14297).
+char(c,14298).
+char(c,14299).
+char(p,14300).
+char(o,14301).
+char(p,14302).
+char(2,14303).
+char(5,14304).
+char(5,14305).
+char(1,14306).
+char(m,14307).
+char(o,14308).
+char(p,14309).
+char(o,14310).
+char(m,14311).
+char(3,14312).
+char(6,14313).
+char(7,14314).
+char(0,14315).
+char(p,14316).
+char(4,14317).
+char(8,14318).
+char(1,14319).
+char(2,14320).
+char(p,14321).
+char(6,14322).
+char(3,14323).
+char(0,14324).
+char(3,14325).
+char(c,14326).
+char(p,14327).
+char(o,14328).
+char(p,14329).
+char(o,14330).
+char(p,14331).
+char(o,14332).
+char(p,14333).
+char(4,14334).
+char(1,14335).
+char(9,14336).
+char(6,14337).
+char(c,14338).
+char(m,14339).
+char(7,14340).
+char(9,14341).
+char(6,14342).
+char(0,14343).
+char(m,14344).
+char(o,14345).
+char(m,14346).
+char(2,14347).
+char(2,14348).
+char(6,14349).
+char(5,14350).
+char(c,14351).
+char(p,14352).
+char(2,14353).
+char(2,14354).
+char(9,14355).
+char(3,14356).
+char(p,14357).
+char(o,14358).
+char(m,14359).
+char(9,14360).
+char(9,14361).
+char(1,14362).
+char(1,14363).
+char(c,14364).
+char(c,14365).
+char(p,14366).
+char(o,14367).
+char(m,14368).
+char(2,14369).
+char(3,14370).
+char(9,14371).
+char(1,14372).
+char(c,14373).
+char(c,14374).
+char(p,14375).
+char(o,14376).
+char(m,14377).
+char(2,14378).
+char(2,14379).
+char(9,14380).
+char(5,14381).
+char(m,14382).
+char(o,14383).
+char(p,14384).
+char(6,14385).
+char(5,14386).
+char(8,14387).
+char(3,14388).
+char(c,14389).
+char(c,14390).
+char(m,14391).
+char(2,14392).
+char(3,14393).
+char(7,14394).
+char(0,14395).
+char(c,14396).
+char(m,14397).
+char(9,14398).
+char(1,14399).
+char(5,14400).
+char(8,14401).
+char(m,14402).
+char(o,14403).
+char(o,14404).
+char(p,14405).
+char(9,14406).
+char(2,14407).
+char(0,14408).
+char(0,14409).
+char(m,14410).
+char(3,14411).
+char(1,14412).
+char(0,14413).
+char(5,14414).
+char(p,14415).
+char(6,14416).
+char(1,14417).
+char(0,14418).
+char(0,14419).
+char(p,14420).
+char(o,14421).
+char(p,14422).
+char(o,14423).
+char(o,14424).
+char(p,14425).
+char(o,14426).
+char(m,14427).
+char(2,14428).
+char(4,14429).
+char(7,14430).
+char(1,14431).
+char(c,14432).
+char(c,14433).
+char(c,14434).
+char(c,14435).
+char(p,14436).
+char(o,14437).
+char(p,14438).
+char(o,14439).
+char(m,14440).
+char(3,14441).
+char(9,14442).
+char(5,14443).
+char(3,14444).
+char(p,14445).
+char(7,14446).
+char(6,14447).
+char(6,14448).
+char(4,14449).
+char(c,14450).
+char(c,14451).
+char(c,14452).
+char(c,14453).
+char(c,14454).
+char(c,14455).
+char(c,14456).
+char(m,14457).
+char(5,14458).
+char(7,14459).
+char(2,14460).
+char(4,14461).
+char(p,14462).
+char(o,14463).
+char(o,14464).
+char(4,14465).
+char(6,14466).
+char(2,14467).
+char(8,14468).
+char(c,14469).
+char(m,14470).
+char(8,14471).
+char(1,14472).
+char(4,14473).
+char(8,14474).
+char(p,14475).
+char(3,14476).
+char(6,14477).
+char(2,14478).
+char(3,14479).
+char(c,14480).
+char(c,14481).
+char(m,14482).
+char(o,14483).
+char(m,14484).
+char(4,14485).
+char(4,14486).
+char(5,14487).
+char(9,14488).
+char(c,14489).
+char(m,14490).
+char(o,14491).
+char(p,14492).
+char(9,14493).
+char(2,14494).
+char(4,14495).
+char(3,14496).
+char(c,14497).
+char(m,14498).
+char(8,14499).
+char(1,14500).
+char(5,14501).
+char(4,14502).
+char(m,14503).
+char(9,14504).
+char(1,14505).
+char(9,14506).
+char(3,14507).
+char(c,14508).
+char(c,14509).
+char(m,14510).
+char(1,14511).
+char(3,14512).
+char(0,14513).
+char(0,14514).
+char(c,14515).
+char(c,14516).
+char(c,14517).
+char(c,14518).
+char(p,14519).
+char(o,14520).
+char(p,14521).
+char(o,14522).
+char(8,14523).
+char(6,14524).
+char(9,14525).
+char(7,14526).
+char(p,14527).
+char(1,14528).
+char(9,14529).
+char(4,14530).
+char(2,14531).
+char(m,14532).
+char(2,14533).
+char(8,14534).
+char(2,14535).
+char(c,14536).
+char(m,14537).
+char(o,14538).
+char(p,14539).
+char(o,14540).
+char(m,14541).
+char(6,14542).
+char(5,14543).
+char(5,14544).
+char(7,14545).
+char(c,14546).
+char(c,14547).
+char(m,14548).
+char(o,14549).
+char(p,14550).
+char(o,14551).
+char(m,14552).
+char(9,14553).
+char(5,14554).
+char(9,14555).
+char(6,14556).
+char(p,14557).
+char(2,14558).
+char(8,14559).
+char(4,14560).
+char(9,14561).
+char(c,14562).
+char(m,14563).
+char(4,14564).
+char(1,14565).
+char(3,14566).
+char(7,14567).
+char(c,14568).
+char(p,14569).
+char(7,14570).
+char(1,14571).
+char(6,14572).
+char(2,14573).
+char(c,14574).
+char(c,14575).
+char(m,14576).
+char(9,14577).
+char(1,14578).
+char(1,14579).
+char(9,14580).
+char(c,14581).
+char(p,14582).
+char(3,14583).
+char(9,14584).
+char(2,14585).
+char(3,14586).
+char(c,14587).
+char(c,14588).
+char(c,14589).
+char(m,14590).
+char(o,14591).
+char(m,14592).
+char(3,14593).
+char(1,14594).
+char(8,14595).
+char(4,14596).
+char(m,14597).
+char(o,14598).
+char(m,14599).
+char(o,14600).
+char(p,14601).
+char(3,14602).
+char(5,14603).
+char(4,14604).
+char(7,14605).
+char(c,14606).
+char(p,14607).
+char(o,14608).
+char(o,14609).
+char(m,14610).
+char(o,14611).
+char(p,14612).
+char(o,14613).
+char(3,14614).
+char(8,14615).
+char(m,14616).
+char(9,14617).
+char(5,14618).
+char(3,14619).
+char(1,14620).
+char(m,14621).
+char(o,14622).
+char(m,14623).
+char(o,14624).
+char(5,14625).
+char(9,14626).
+char(2,14627).
+char(5,14628).
+char(p,14629).
+char(4,14630).
+char(1,14631).
+char(3,14632).
+char(7,14633).
+char(c,14634).
+char(c,14635).
+char(p,14636).
+char(4,14637).
+char(5,14638).
+char(1,14639).
+char(8,14640).
+char(c,14641).
+char(p,14642).
+char(o,14643).
+char(m,14644).
+char(o,14645).
+char(p,14646).
+char(o,14647).
+char(p,14648).
+char(o,14649).
+char(1,14650).
+char(3,14651).
+char(7,14652).
+char(3,14653).
+char(c,14654).
+char(c,14655).
+char(c,14656).
+char(m,14657).
+char(8,14658).
+char(2,14659).
+char(2,14660).
+char(8,14661).
+char(m,14662).
+char(o,14663).
+char(m,14664).
+char(5,14665).
+char(4,14666).
+char(8,14667).
+char(3,14668).
+char(c,14669).
+char(c,14670).
+char(c,14671).
+char(c,14672).
+char(c,14673).
+char(m,14674).
+char(1,14675).
+char(9,14676).
+char(7,14677).
+char(9,14678).
+char(m,14679).
+char(o,14680).
+char(p,14681).
+char(o,14682).
+char(o,14683).
+char(m,14684).
+char(6,14685).
+char(4,14686).
+char(8,14687).
+char(3,14688).
+char(p,14689).
+char(9,14690).
+char(7,14691).
+char(0,14692).
+char(3,14693).
+char(p,14694).
+char(o,14695).
+char(p,14696).
+char(6,14697).
+char(5,14698).
+char(4,14699).
+char(1,14700).
+char(m,14701).
+char(o,14702).
+char(o,14703).
+char(m,14704).
+char(9,14705).
+char(5,14706).
+char(2,14707).
+char(9,14708).
+char(p,14709).
+char(o,14710).
+char(o,14711).
+char(o,14712).
+char(7,14713).
+char(3,14714).
+char(9,14715).
+char(4,14716).
+char(p,14717).
+char(o,14718).
+char(m,14719).
+char(8,14720).
+char(3,14721).
+char(4,14722).
+char(5,14723).
+char(c,14724).
+char(c,14725).
+char(c,14726).
+char(m,14727).
+char(1,14728).
+char(9,14729).
+char(8,14730).
+char(c,14731).
+char(m,14732).
+char(o,14733).
+char(m,14734).
+char(6,14735).
+char(7,14736).
+char(1,14737).
+char(7,14738).
+char(c,14739).
+char(m,14740).
+char(3,14741).
+char(2,14742).
+char(4,14743).
+char(4,14744).
+char(m,14745).
+char(3,14746).
+char(0,14747).
+char(5,14748).
+char(0,14749).
+char(c,14750).
+char(c,14751).
+char(m,14752).
+char(5,14753).
+char(4,14754).
+char(7,14755).
+char(c,14756).
+char(m,14757).
+char(8,14758).
+char(4,14759).
+char(0,14760).
+char(0,14761).
+char(c,14762).
+char(m,14763).
+char(o,14764).
+char(m,14765).
+char(4,14766).
+char(4,14767).
+char(5,14768).
+char(7,14769).
+char(p,14770).
+char(4,14771).
+char(9,14772).
+char(7,14773).
+char(9,14774).
+char(c,14775).
+char(c,14776).
+char(p,14777).
+char(o,14778).
+char(5,14779).
+char(8,14780).
+char(9,14781).
+char(2,14782).
+char(c,14783).
+char(p,14784).
+char(1,14785).
+char(0,14786).
+char(7,14787).
+char(c,14788).
+char(c,14789).
+char(p,14790).
+char(o,14791).
+char(m,14792).
+char(o,14793).
+char(1,14794).
+char(4,14795).
+char(7,14796).
+char(6,14797).
+char(c,14798).
+char(c,14799).
+char(p,14800).
+char(3,14801).
+char(1,14802).
+char(7,14803).
+char(3,14804).
+char(c,14805).
+char(p,14806).
+char(6,14807).
+char(3,14808).
+char(7,14809).
+char(9,14810).
+char(c,14811).
+char(c,14812).
+char(p,14813).
+char(4,14814).
+char(6,14815).
+char(1,14816).
+char(7,14817).
+char(p,14818).
+char(7,14819).
+char(1,14820).
+char(1,14821).
+char(3,14822).
+char(m,14823).
+char(6,14824).
+char(1,14825).
+char(6,14826).
+char(8,14827).
+char(p,14828).
+char(o,14829).
+char(p,14830).
+char(1,14831).
+char(8,14832).
+char(4,14833).
+char(c,14834).
+char(c,14835).
+char(c,14836).
+char(p,14837).
+char(6,14838).
+char(8,14839).
+char(6,14840).
+char(8,14841).
+char(p,14842).
+char(o,14843).
+char(m,14844).
+char(7,14845).
+char(0,14846).
+char(4,14847).
+char(5,14848).
+char(c,14849).
+char(p,14850).
+char(o,14851).
+char(p,14852).
+char(1,14853).
+char(8,14854).
+char(5,14855).
+char(3,14856).
+char(m,14857).
+char(o,14858).
+char(p,14859).
+char(o,14860).
+char(p,14861).
+char(3,14862).
+char(5,14863).
+char(1,14864).
+char(7,14865).
+char(p,14866).
+char(o,14867).
+char(o,14868).
+char(p,14869).
+char(5,14870).
+char(3,14871).
+char(5,14872).
+char(1,14873).
+char(c,14874).
+char(c,14875).
+char(c,14876).
+char(c,14877).
+char(p,14878).
+char(o,14879).
+char(p,14880).
+char(6,14881).
+char(3,14882).
+char(9,14883).
+char(0,14884).
+char(m,14885).
+char(o,14886).
+char(o,14887).
+char(p,14888).
+char(1,14889).
+char(8,14890).
+char(0,14891).
+char(0,14892).
+char(c,14893).
+char(c,14894).
+char(m,14895).
+char(1,14896).
+char(8,14897).
+char(6,14898).
+char(9,14899).
+char(c,14900).
+char(c,14901).
+char(c,14902).
+char(p,14903).
+char(4,14904).
+char(8,14905).
+char(4,14906).
+char(0,14907).
+char(c,14908).
+char(c,14909).
+char(c,14910).
+char(p,14911).
+char(3,14912).
+char(8,14913).
+char(9,14914).
+char(4,14915).
+char(m,14916).
+char(3,14917).
+char(8,14918).
+char(9,14919).
+char(5,14920).
+char(c,14921).
+char(c,14922).
+char(p,14923).
+char(o,14924).
+char(4,14925).
+char(2,14926).
+char(4,14927).
+char(4,14928).
+char(p,14929).
+char(1,14930).
+char(9,14931).
+char(4,14932).
+char(1,14933).
+char(p,14934).
+char(o,14935).
+char(p,14936).
+char(o,14937).
+char(p,14938).
+char(8,14939).
+char(4,14940).
+char(0,14941).
+char(1,14942).
+char(p,14943).
+char(3,14944).
+char(4,14945).
+char(5,14946).
+char(1,14947).
+char(c,14948).
+char(p,14949).
+char(o,14950).
+char(p,14951).
+char(6,14952).
+char(4,14953).
+char(1,14954).
+char(0,14955).
+char(c,14956).
+char(p,14957).
+char(o,14958).
+char(m,14959).
+char(2,14960).
+char(6,14961).
+char(3,14962).
+char(4,14963).
+char(c,14964).
+char(c,14965).
+char(c,14966).
+char(c,14967).
+char(m,14968).
+char(2,14969).
+char(5,14970).
+char(3,14971).
+char(2,14972).
+char(p,14973).
+char(1,14974).
+char(1,14975).
+char(7,14976).
+char(9,14977).
+char(m,14978).
+char(4,14979).
+char(5,14980).
+char(2,14981).
+char(c,14982).
+char(p,14983).
+char(o,14984).
+char(o,14985).
+char(p,14986).
+char(o,14987).
+char(1,14988).
+char(3,14989).
+char(7,14990).
+char(0,14991).
+char(p,14992).
+char(o,14993).
+char(m,14994).
+char(2,14995).
+char(2,14996).
+char(7,14997).
+char(1,14998).
+char(c,14999).
+char(m,15000).
+char(2,15001).
+char(0,15002).
+char(6,15003).
+char(8,15004).
+char(c,15005).
+char(p,15006).
+char(o,15007).
+char(p,15008).
+char(7,15009).
+char(8,15010).
+char(1,15011).
+char(0,15012).
+char(p,15013).
+char(6,15014).
+char(0,15015).
+char(2,15016).
+char(m,15017).
+char(2,15018).
+char(8,15019).
+char(2,15020).
+char(6,15021).
+char(m,15022).
+char(o,15023).
+char(m,15024).
+char(o,15025).
+char(o,15026).
+char(m,15027).
+char(o,15028).
+char(m,15029).
+char(o,15030).
+char(o,15031).
+char(3,15032).
+char(4,15033).
+char(9,15034).
+char(7,15035).
+char(m,15036).
+char(5,15037).
+char(3,15038).
+char(6,15039).
+char(4,15040).
+char(c,15041).
+char(c,15042).
+char(c,15043).
+char(c,15044).
+char(c,15045).
+char(c,15046).
+char(c,15047).
+char(p,15048).
+char(4,15049).
+char(5,15050).
+char(2,15051).
+char(8,15052).
+char(c,15053).
+char(c,15054).
+char(m,15055).
+char(9,15056).
+char(5,15057).
+char(5,15058).
+char(6,15059).
+char(c,15060).
+char(c,15061).
+char(p,15062).
+char(9,15063).
+char(0,15064).
+char(2,15065).
+char(1,15066).
+char(p,15067).
+char(2,15068).
+char(4,15069).
+char(5,15070).
+char(8,15071).
+char(c,15072).
+char(p,15073).
+char(o,15074).
+char(7,15075).
+char(1,15076).
+char(4,15077).
+char(8,15078).
+char(c,15079).
+char(c,15080).
+char(m,15081).
+char(5,15082).
+char(3,15083).
+char(0,15084).
+char(2,15085).
+char(m,15086).
+char(3,15087).
+char(8,15088).
+char(8,15089).
+char(4,15090).
+char(p,15091).
+char(4,15092).
+char(1,15093).
+char(2,15094).
+char(1,15095).
+char(p,15096).
+char(1,15097).
+char(1,15098).
+char(0,15099).
+char(5,15100).
+char(p,15101).
+char(4,15102).
+char(3,15103).
+char(0,15104).
+char(8,15105).
+char(p,15106).
+char(1,15107).
+char(7,15108).
+char(7,15109).
+char(7,15110).
+char(m,15111).
+char(3,15112).
+char(1,15113).
+char(0,15114).
+char(6,15115).
+char(m,15116).
+char(o,15117).
+char(m,15118).
+char(2,15119).
+char(4,15120).
+char(9,15121).
+char(3,15122).
+char(m,15123).
+char(o,15124).
+char(m,15125).
+char(3,15126).
+char(5,15127).
+char(0,15128).
+char(7,15129).
+char(c,15130).
+char(p,15131).
+char(o,15132).
+char(2,15133).
+char(3,15134).
+char(8,15135).
+char(c,15136).
+char(c,15137).
+char(c,15138).
+char(p,15139).
+char(5,15140).
+char(8,15141).
+char(3,15142).
+char(1,15143).
+char(c,15144).
+char(c,15145).
+char(c,15146).
+char(c,15147).
+char(m,15148).
+char(8,15149).
+char(1,15150).
+char(7,15151).
+char(9,15152).
+char(c,15153).
+char(m,15154).
+char(o,15155).
+char(m,15156).
+char(o,15157).
+char(5,15158).
+char(1,15159).
+char(5,15160).
+char(4,15161).
+char(p,15162).
+char(9,15163).
+char(8,15164).
+char(3,15165).
+char(4,15166).
+char(m,15167).
+char(4,15168).
+char(1,15169).
+char(0,15170).
+char(9,15171).
+char(m,15172).
+char(4,15173).
+char(2,15174).
+char(3,15175).
+char(3,15176).
+char(p,15177).
+char(4,15178).
+char(6,15179).
+char(9,15180).
+char(6,15181).
+char(m,15182).
+char(o,15183).
+char(p,15184).
+char(o,15185).
+char(p,15186).
+char(o,15187).
+char(m,15188).
+char(1,15189).
+char(9,15190).
+char(9,15191).
+char(3,15192).
+char(m,15193).
+char(5,15194).
+char(3,15195).
+char(5,15196).
+char(0,15197).
+char(m,15198).
+char(5,15199).
+char(1,15200).
+char(8,15201).
+char(2,15202).
+char(p,15203).
+char(1,15204).
+char(8,15205).
+char(8,15206).
+char(9,15207).
+char(c,15208).
+char(c,15209).
+char(c,15210).
+char(c,15211).
+char(p,15212).
+char(9,15213).
+char(4,15214).
+char(7,15215).
+char(8,15216).
+char(c,15217).
+char(m,15218).
+char(2,15219).
+char(5,15220).
+char(8,15221).
+char(0,15222).
+char(p,15223).
+char(8,15224).
+char(6,15225).
+char(6,15226).
+char(9,15227).
+char(p,15228).
+char(2,15229).
+char(3,15230).
+char(7,15231).
+char(5,15232).
+char(m,15233).
+char(7,15234).
+char(3,15235).
+char(6,15236).
+char(1,15237).
+char(p,15238).
+char(o,15239).
+char(o,15240).
+char(m,15241).
+char(o,15242).
+char(p,15243).
+char(o,15244).
+char(p,15245).
+char(6,15246).
+char(5,15247).
+char(3,15248).
+char(8,15249).
+char(c,15250).
+char(c,15251).
+char(m,15252).
+char(o,15253).
+char(1,15254).
+char(9,15255).
+char(1,15256).
+char(0,15257).
+char(m,15258).
+char(2,15259).
+char(0,15260).
+char(4,15261).
+char(3,15262).
+char(c,15263).
+char(p,15264).
+char(o,15265).
+char(m,15266).
+char(o,15267).
+char(7,15268).
+char(4,15269).
+char(7,15270).
+char(7,15271).
+char(p,15272).
+char(o,15273).
+char(m,15274).
+char(o,15275).
+char(o,15276).
+char(1,15277).
+char(5,15278).
+char(6,15279).
+char(7,15280).
+char(c,15281).
+char(c,15282).
+char(c,15283).
+char(c,15284).
+char(m,15285).
+char(o,15286).
+char(p,15287).
+char(o,15288).
+char(p,15289).
+char(2,15290).
+char(2,15291).
+char(c,15292).
+char(m,15293).
+char(8,15294).
+char(6,15295).
+char(3,15296).
+char(5,15297).
+char(p,15298).
+char(4,15299).
+char(2,15300).
+char(9,15301).
+char(c,15302).
+char(p,15303).
+char(o,15304).
+char(p,15305).
+char(o,15306).
+char(p,15307).
+char(o,15308).
+char(p,15309).
+char(8,15310).
+char(5,15311).
+char(8,15312).
+char(2,15313).
+char(p,15314).
+char(6,15315).
+char(9,15316).
+char(2,15317).
+char(9,15318).
+char(p,15319).
+char(5,15320).
+char(1,15321).
+char(8,15322).
+char(5,15323).
+char(m,15324).
+char(o,15325).
+char(m,15326).
+char(6,15327).
+char(3,15328).
+char(6,15329).
+char(6,15330).
+char(c,15331).
+char(p,15332).
+char(o,15333).
+char(m,15334).
+char(o,15335).
+char(7,15336).
+char(9,15337).
+char(2,15338).
+char(4,15339).
+char(c,15340).
+char(c,15341).
+char(c,15342).
+char(c,15343).
+char(p,15344).
+char(o,15345).
+char(m,15346).
+char(o,15347).
+char(2,15348).
+char(3,15349).
+char(9,15350).
+char(4,15351).
+char(m,15352).
+char(4,15353).
+char(0,15354).
+char(1,15355).
+char(3,15356).
+char(c,15357).
+char(p,15358).
+char(5,15359).
+char(4,15360).
+char(6,15361).
+char(1,15362).
+char(p,15363).
+char(o,15364).
+char(p,15365).
+char(o,15366).
+char(p,15367).
+char(o,15368).
+char(m,15369).
+char(o,15370).
+char(p,15371).
+char(o,15372).
+char(p,15373).
+char(2,15374).
+char(1,15375).
+char(1,15376).
+char(3,15377).
+char(c,15378).
+char(c,15379).
+char(c,15380).
+char(c,15381).
+char(c,15382).
+char(c,15383).
+char(c,15384).
+char(c,15385).
+char(m,15386).
+char(o,15387).
+char(p,15388).
+char(o,15389).
+char(p,15390).
+char(o,15391).
+char(p,15392).
+char(o,15393).
+char(p,15394).
+char(7,15395).
+char(0,15396).
+char(1,15397).
+char(6,15398).
+char(m,15399).
+char(5,15400).
+char(5,15401).
+char(0,15402).
+char(3,15403).
+char(c,15404).
+char(c,15405).
+char(c,15406).
+char(p,15407).
+char(o,15408).
+char(m,15409).
+char(2,15410).
+char(1,15411).
+char(2,15412).
+char(1,15413).
+char(c,15414).
+char(c,15415).
+char(c,15416).
+char(m,15417).
+char(o,15418).
+char(5,15419).
+char(3,15420).
+char(1,15421).
+char(9,15422).
+char(m,15423).
+char(5,15424).
+char(3,15425).
+char(7,15426).
+char(2,15427).
+char(m,15428).
+char(o,15429).
+char(o,15430).
+char(m,15431).
+char(o,15432).
+char(p,15433).
+char(o,15434).
+char(7,15435).
+char(8,15436).
+char(3,15437).
+char(2,15438).
+char(c,15439).
+char(c,15440).
+char(c,15441).
+char(c,15442).
+char(p,15443).
+char(7,15444).
+char(5,15445).
+char(4,15446).
+char(9,15447).
+char(m,15448).
+char(7,15449).
+char(0,15450).
+char(0,15451).
+char(0,15452).
+char(m,15453).
+char(o,15454).
+char(p,15455).
+char(o,15456).
+char(m,15457).
+char(5,15458).
+char(5,15459).
+char(2,15460).
+char(9,15461).
+char(m,15462).
+char(o,15463).
+char(p,15464).
+char(o,15465).
+char(o,15466).
+char(m,15467).
+char(2,15468).
+char(7,15469).
+char(6,15470).
+char(0,15471).
+char(c,15472).
+char(m,15473).
+char(o,15474).
+char(2,15475).
+char(4,15476).
+char(1,15477).
+char(6,15478).
+char(c,15479).
+char(m,15480).
+char(o,15481).
+char(5,15482).
+char(8,15483).
+char(8,15484).
+char(p,15485).
+char(6,15486).
+char(1,15487).
+char(6,15488).
+char(7,15489).
+char(m,15490).
+char(3,15491).
+char(2,15492).
+char(8,15493).
+char(1,15494).
+char(c,15495).
+char(c,15496).
+char(p,15497).
+char(o,15498).
+char(m,15499).
+char(o,15500).
+char(m,15501).
+char(o,15502).
+char(m,15503).
+char(o,15504).
+char(m,15505).
+char(o,15506).
+char(m,15507).
+char(o,15508).
+char(p,15509).
+char(3,15510).
+char(4,15511).
+char(3,15512).
+char(5,15513).
+char(p,15514).
+char(o,15515).
+char(p,15516).
+char(5,15517).
+char(6,15518).
+char(5,15519).
+char(4,15520).
+char(c,15521).
+char(p,15522).
+char(8,15523).
+char(6,15524).
+char(4,15525).
+char(4,15526).
+char(c,15527).
+char(c,15528).
+char(m,15529).
+char(3,15530).
+char(0,15531).
+char(9,15532).
+char(0,15533).
+char(c,15534).
+char(m,15535).
+char(2,15536).
+char(6,15537).
+char(3,15538).
+char(c,15539).
+char(m,15540).
+char(9,15541).
+char(8,15542).
+char(0,15543).
+char(0,15544).
+char(p,15545).
+char(o,15546).
+char(p,15547).
+char(5,15548).
+char(9,15549).
+char(4,15550).
+char(c,15551).
+char(m,15552).
+char(5,15553).
+char(1,15554).
+char(5,15555).
+char(3,15556).
+char(c,15557).
+char(c,15558).
+char(p,15559).
+char(o,15560).
+char(p,15561).
+char(o,15562).
+char(p,15563).
+char(o,15564).
+char(m,15565).
+char(o,15566).
+char(p,15567).
+char(o,15568).
+char(1,15569).
+char(4,15570).
+char(3,15571).
+char(9,15572).
+char(m,15573).
+char(o,15574).
+char(p,15575).
+char(5,15576).
+char(1,15577).
+char(9,15578).
+char(7,15579).
+char(c,15580).
+char(m,15581).
+char(9,15582).
+char(6,15583).
+char(5,15584).
+char(3,15585).
+char(c,15586).
+char(c,15587).
+char(c,15588).
+char(m,15589).
+char(4,15590).
+char(8,15591).
+char(0,15592).
+char(c,15593).
+char(m,15594).
+char(3,15595).
+char(0,15596).
+char(1,15597).
+char(3,15598).
+char(c,15599).
+char(c,15600).
+char(p,15601).
+char(o,15602).
+char(4,15603).
+char(5,15604).
+char(0,15605).
+char(c,15606).
+char(c,15607).
+char(c,15608).
+char(c,15609).
+char(c,15610).
+char(m,15611).
+char(o,15612).
+char(p,15613).
+char(2,15614).
+char(5,15615).
+char(7,15616).
+char(7,15617).
+char(p,15618).
+char(1,15619).
+char(6,15620).
+char(6,15621).
+char(c,15622).
+char(p,15623).
+char(o,15624).
+char(p,15625).
+char(7,15626).
+char(0,15627).
+char(9,15628).
+char(6,15629).
+char(p,15630).
+char(6,15631).
+char(6,15632).
+char(7,15633).
+char(4,15634).
+char(c,15635).
+char(m,15636).
+char(o,15637).
+char(m,15638).
+char(o,15639).
+char(m,15640).
+char(o,15641).
+char(m,15642).
+char(o,15643).
+char(m,15644).
+char(6,15645).
+char(2,15646).
+char(2,15647).
+char(9,15648).
+char(p,15649).
+char(o,15650).
+char(o,15651).
+char(o,15652).
+char(4,15653).
+char(7,15654).
+char(5,15655).
+char(6,15656).
+char(c,15657).
+char(m,15658).
+char(o,15659).
+char(p,15660).
+char(o,15661).
+char(m,15662).
+char(o,15663).
+char(9,15664).
+char(8,15665).
+char(2,15666).
+char(5,15667).
+char(c,15668).
+char(m,15669).
+char(o,15670).
+char(4,15671).
+char(1,15672).
+char(5,15673).
+char(p,15674).
+char(2,15675).
+char(4,15676).
+char(2,15677).
+char(1,15678).
+char(c,15679).
+char(m,15680).
+char(o,15681).
+char(m,15682).
+char(5,15683).
+char(6,15684).
+char(8,15685).
+char(3,15686).
+char(m,15687).
+char(o,15688).
+char(p,15689).
+char(3,15690).
+char(2,15691).
+char(5,15692).
+char(1,15693).
+char(c,15694).
+char(c,15695).
+char(p,15696).
+char(o,15697).
+char(o,15698).
+char(p,15699).
+char(o,15700).
+char(p,15701).
+char(9,15702).
+char(4,15703).
+char(5,15704).
+char(1,15705).
+char(m,15706).
+char(1,15707).
+char(2,15708).
+char(7,15709).
+char(8,15710).
+char(p,15711).
+char(2,15712).
+char(3,15713).
+char(7,15714).
+char(8,15715).
+char(p,15716).
+char(2,15717).
+char(5,15718).
+char(9,15719).
+char(7,15720).
+char(m,15721).
+char(o,15722).
+char(p,15723).
+char(o,15724).
+char(p,15725).
+char(2,15726).
+char(2,15727).
+char(4,15728).
+char(1,15729).
+char(c,15730).
+char(p,15731).
+char(9,15732).
+char(0,15733).
+char(3,15734).
+char(6,15735).
+char(c,15736).
+char(c,15737).
+char(c,15738).
+char(c,15739).
+char(c,15740).
+char(c,15741).
+char(p,15742).
+char(o,15743).
+char(o,15744).
+char(o,15745).
+char(1,15746).
+char(5,15747).
+char(4,15748).
+char(9,15749).
+char(m,15750).
+char(o,15751).
+char(1,15752).
+char(9,15753).
+char(9,15754).
+char(2,15755).
+char(c,15756).
+char(c,15757).
+char(c,15758).
+char(m,15759).
+char(o,15760).
+char(m,15761).
+char(8,15762).
+char(2,15763).
+char(8,15764).
+char(c,15765).
+char(c,15766).
+char(c,15767).
+char(m,15768).
+char(o,15769).
+char(o,15770).
+char(m,15771).
+char(4,15772).
+char(9,15773).
+char(0,15774).
+char(c,15775).
+char(p,15776).
+char(9,15777).
+char(4,15778).
+char(8,15779).
+char(7,15780).
+char(c,15781).
+char(c,15782).
+char(c,15783).
+char(m,15784).
+char(3,15785).
+char(4,15786).
+char(0,15787).
+char(1,15788).
+char(c,15789).
+char(c,15790).
+char(m,15791).
+char(o,15792).
+char(m,15793).
+char(7,15794).
+char(5,15795).
+char(3,15796).
+char(4,15797).
+char(p,15798).
+char(o,15799).
+char(o,15800).
+char(m,15801).
+char(o,15802).
+char(m,15803).
+char(o,15804).
+char(m,15805).
+char(4,15806).
+char(4,15807).
+char(2,15808).
+char(c,15809).
+char(c,15810).
+char(m,15811).
+char(o,15812).
+char(o,15813).
+char(p,15814).
+char(8,15815).
+char(7,15816).
+char(2,15817).
+char(8,15818).
+char(c,15819).
+char(m,15820).
+char(o,15821).
+char(o,15822).
+char(o,15823).
+char(p,15824).
+char(o,15825).
+char(7,15826).
+char(4,15827).
+char(8,15828).
+char(9,15829).
+char(p,15830).
+char(1,15831).
+char(3,15832).
+char(5,15833).
+char(2,15834).
+char(c,15835).
+char(m,15836).
+char(6,15837).
+char(0,15838).
+char(2,15839).
+char(3,15840).
+char(c,15841).
+char(m,15842).
+char(o,15843).
+char(p,15844).
+char(1,15845).
+char(5,15846).
+char(1,15847).
+char(2,15848).
+char(c,15849).
+char(c,15850).
+char(m,15851).
+char(o,15852).
+char(m,15853).
+char(o,15854).
+char(p,15855).
+char(3,15856).
+char(9,15857).
+char(8,15858).
+char(0,15859).
+char(c,15860).
+char(m,15861).
+char(7,15862).
+char(3,15863).
+char(0,15864).
+char(6,15865).
+char(m,15866).
+char(o,15867).
+char(p,15868).
+char(o,15869).
+char(m,15870).
+char(o,15871).
+char(m,15872).
+char(8,15873).
+char(6,15874).
+char(4,15875).
+char(2,15876).
+char(c,15877).
+char(p,15878).
+char(o,15879).
+char(m,15880).
+char(o,15881).
+char(9,15882).
+char(9,15883).
+char(5,15884).
+char(8,15885).
+char(c,15886).
+char(m,15887).
+char(5,15888).
+char(7,15889).
+char(6,15890).
+char(2,15891).
+char(m,15892).
+char(6,15893).
+char(5,15894).
+char(1,15895).
+char(6,15896).
+char(c,15897).
+char(c,15898).
+char(c,15899).
+char(c,15900).
+char(p,15901).
+char(o,15902).
+char(p,15903).
+char(8,15904).
+char(2,15905).
+char(0,15906).
+char(c,15907).
+char(m,15908).
+char(o,15909).
+char(3,15910).
+char(8,15911).
+char(4,15912).
+char(9,15913).
+char(m,15914).
+char(4,15915).
+char(6,15916).
+char(9,15917).
+char(p,15918).
+char(o,15919).
+char(o,15920).
+char(m,15921).
+char(o,15922).
+char(m,15923).
+char(o,15924).
+char(m,15925).
+char(8,15926).
+char(7,15927).
+char(4,15928).
+char(7,15929).
+char(c,15930).
+char(p,15931).
+char(3,15932).
+char(3,15933).
+char(8,15934).
+char(2,15935).
+char(c,15936).
+char(c,15937).
+char(c,15938).
+char(p,15939).
+char(2,15940).
+char(2,15941).
+char(4,15942).
+char(6,15943).
+char(c,15944).
+char(m,15945).
+char(o,15946).
+char(p,15947).
+char(o,15948).
+char(6,15949).
+char(5,15950).
+char(7,15951).
+char(3,15952).
+char(p,15953).
+char(1,15954).
+char(3,15955).
+char(9,15956).
+char(p,15957).
+char(9,15958).
+char(1,15959).
+char(6,15960).
+char(0,15961).
+char(c,15962).
+char(p,15963).
+char(8,15964).
+char(1,15965).
+char(3,15966).
+char(3,15967).
+char(c,15968).
+char(c,15969).
+char(c,15970).
+char(c,15971).
+char(c,15972).
+char(c,15973).
+char(p,15974).
+char(4,15975).
+char(8,15976).
+char(3,15977).
+char(0,15978).
+char(c,15979).
+char(m,15980).
+char(9,15981).
+char(4,15982).
+char(4,15983).
+char(9,15984).
+char(m,15985).
+char(4,15986).
+char(5,15987).
+char(0,15988).
+char(4,15989).
+char(m,15990).
+char(8,15991).
+char(4,15992).
+char(2,15993).
+char(2,15994).
+char(p,15995).
+char(o,15996).
+char(p,15997).
+char(o,15998).
+char(m,15999).
+char(5,16000).
+char(7,16001).
+char(4,16002).
+char(8,16003).
+char(c,16004).
+char(c,16005).
+char(p,16006).
+char(o,16007).
+char(p,16008).
+char(o,16009).
+char(m,16010).
+char(o,16011).
+char(o,16012).
+char(m,16013).
+char(o,16014).
+char(m,16015).
+char(7,16016).
+char(9,16017).
+char(5,16018).
+char(1,16019).
+char(p,16020).
+char(7,16021).
+char(8,16022).
+char(1,16023).
+char(1,16024).
+char(c,16025).
+char(m,16026).
+char(2,16027).
+char(4,16028).
+char(8,16029).
+char(0,16030).
+char(c,16031).
+char(p,16032).
+char(4,16033).
+char(5,16034).
+char(1,16035).
+char(6,16036).
+char(m,16037).
+char(o,16038).
+char(m,16039).
+char(6,16040).
+char(7,16041).
+char(6,16042).
+char(1,16043).
+char(c,16044).
+char(m,16045).
+char(6,16046).
+char(4,16047).
+char(0,16048).
+char(1,16049).
+char(m,16050).
+char(5,16051).
+char(5,16052).
+char(4,16053).
+char(4,16054).
+char(p,16055).
+char(4,16056).
+char(0,16057).
+char(2,16058).
+char(8,16059).
+char(p,16060).
+char(3,16061).
+char(3,16062).
+char(3,16063).
+char(9,16064).
+char(c,16065).
+char(p,16066).
+char(3,16067).
+char(1,16068).
+char(4,16069).
+char(7,16070).
+char(p,16071).
+char(9,16072).
+char(7,16073).
+char(1,16074).
+char(2,16075).
+char(m,16076).
+char(1,16077).
+char(6,16078).
+char(1,16079).
+char(1,16080).
+char(p,16081).
+char(o,16082).
+char(o,16083).
+char(p,16084).
+char(o,16085).
+char(o,16086).
+char(p,16087).
+char(2,16088).
+char(0,16089).
+char(6,16090).
+char(6,16091).
+char(c,16092).
+char(c,16093).
+char(m,16094).
+char(o,16095).
+char(p,16096).
+char(o,16097).
+char(9,16098).
+char(0,16099).
+char(0,16100).
+char(m,16101).
+char(o,16102).
+char(m,16103).
+char(2,16104).
+char(1,16105).
+char(2,16106).
+char(8,16107).
+char(c,16108).
+char(c,16109).
+char(c,16110).
+char(m,16111).
+char(4,16112).
+char(5,16113).
+char(4,16114).
+char(0,16115).
+char(p,16116).
+char(o,16117).
+char(m,16118).
+char(3,16119).
+char(4,16120).
+char(2,16121).
+char(6,16122).
+char(c,16123).
+char(c,16124).
+char(c,16125).
+char(p,16126).
+char(o,16127).
+char(3,16128).
+char(9,16129).
+char(5,16130).
+char(9,16131).
+char(p,16132).
+char(o,16133).
+char(m,16134).
+char(o,16135).
+char(p,16136).
+char(o,16137).
+char(m,16138).
+char(9,16139).
+char(2,16140).
+char(7,16141).
+char(0,16142).
+char(c,16143).
+char(c,16144).
+char(c,16145).
+char(p,16146).
+char(o,16147).
+char(9,16148).
+char(5,16149).
+char(7,16150).
+char(3,16151).
+char(m,16152).
+char(o,16153).
+char(8,16154).
+char(2,16155).
+char(0,16156).
+char(3,16157).
+char(c,16158).
+char(m,16159).
+char(8,16160).
+char(5,16161).
+char(6,16162).
+char(2,16163).
+char(c,16164).
+char(c,16165).
+char(m,16166).
+char(7,16167).
+char(6,16168).
+char(4,16169).
+char(2,16170).
+char(c,16171).
+char(c,16172).
+char(m,16173).
+char(o,16174).
+char(o,16175).
+char(p,16176).
+char(o,16177).
+char(m,16178).
+char(o,16179).
+char(p,16180).
+char(o,16181).
+char(p,16182).
+char(o,16183).
+char(p,16184).
+char(o,16185).
+char(p,16186).
+char(o,16187).
+char(p,16188).
+char(o,16189).
+char(p,16190).
+char(o,16191).
+char(6,16192).
+char(1,16193).
+char(6,16194).
+char(3,16195).
+char(c,16196).
+char(m,16197).
+char(o,16198).
+char(m,16199).
+char(7,16200).
+char(2,16201).
+char(7,16202).
+char(9,16203).
+char(p,16204).
+char(o,16205).
+char(m,16206).
+char(8,16207).
+char(6,16208).
+char(4,16209).
+char(2,16210).
+char(c,16211).
+char(p,16212).
+char(o,16213).
+char(p,16214).
+char(7,16215).
+char(4,16216).
+char(2,16217).
+char(2,16218).
+char(m,16219).
+char(o,16220).
+char(p,16221).
+char(o,16222).
+char(m,16223).
+char(o,16224).
+char(m,16225).
+char(o,16226).
+char(p,16227).
+char(o,16228).
+char(m,16229).
+char(o,16230).
+char(8,16231).
+char(0,16232).
+char(6,16233).
+char(7,16234).
+char(m,16235).
+char(o,16236).
+char(m,16237).
+char(o,16238).
+char(m,16239).
+char(6,16240).
+char(9,16241).
+char(7,16242).
+char(3,16243).
+char(m,16244).
+char(o,16245).
+char(3,16246).
+char(6,16247).
+char(2,16248).
+char(8,16249).
+char(c,16250).
+char(c,16251).
+char(p,16252).
+char(7,16253).
+char(7,16254).
+char(2,16255).
+char(3,16256).
+char(c,16257).
+char(m,16258).
+char(2,16259).
+char(2,16260).
+char(5,16261).
+char(8,16262).
+char(m,16263).
+char(o,16264).
+char(m,16265).
+char(o,16266).
+char(m,16267).
+char(9,16268).
+char(8,16269).
+char(1,16270).
+char(2,16271).
+char(c,16272).
+char(c,16273).
+char(p,16274).
+char(6,16275).
+char(2,16276).
+char(4,16277).
+char(9,16278).
+char(c,16279).
+char(p,16280).
+char(8,16281).
+char(7,16282).
+char(7,16283).
+char(3,16284).
+char(m,16285).
+char(o,16286).
+char(m,16287).
+char(o,16288).
+char(p,16289).
+char(o,16290).
+char(m,16291).
+char(1,16292).
+char(0,16293).
+char(9,16294).
+char(9,16295).
+char(c,16296).
+char(c,16297).
+char(c,16298).
+char(m,16299).
+char(9,16300).
+char(7,16301).
+char(7,16302).
+char(2,16303).
+char(c,16304).
+char(p,16305).
+char(9,16306).
+char(8,16307).
+char(4,16308).
+char(4,16309).
+char(m,16310).
+char(o,16311).
+char(p,16312).
+char(4,16313).
+char(8,16314).
+char(9,16315).
+char(0,16316).
+char(c,16317).
+char(p,16318).
+char(6,16319).
+char(9,16320).
+char(2,16321).
+char(0,16322).
+char(m,16323).
+char(o,16324).
+char(m,16325).
+char(o,16326).
+char(p,16327).
+char(o,16328).
+char(m,16329).
+char(6,16330).
+char(6,16331).
+char(8,16332).
+char(9,16333).
+char(c,16334).
+char(p,16335).
+char(o,16336).
+char(m,16337).
+char(8,16338).
+char(0,16339).
+char(9,16340).
+char(5,16341).
+char(c,16342).
+char(c,16343).
+char(c,16344).
+char(c,16345).
+char(m,16346).
+char(o,16347).
+char(m,16348).
+char(2,16349).
+char(6,16350).
+char(8,16351).
+char(7,16352).
+char(c,16353).
+char(c,16354).
+char(p,16355).
+char(6,16356).
+char(3,16357).
+char(1,16358).
+char(0,16359).
+char(c,16360).
+char(m,16361).
+char(6,16362).
+char(8,16363).
+char(5,16364).
+char(3,16365).
+char(c,16366).
+char(c,16367).
+char(m,16368).
+char(4,16369).
+char(3,16370).
+char(2,16371).
+char(0,16372).
+char(p,16373).
+char(3,16374).
+char(7,16375).
+char(7,16376).
+char(1,16377).
+char(c,16378).
+char(c,16379).
+char(c,16380).
+char(c,16381).
+char(p,16382).
+char(o,16383).
+char(o,16384).
+char(p,16385).
+char(o,16386).
+char(p,16387).
+char(o,16388).
+char(p,16389).
+char(o,16390).
+char(o,16391).
+char(p,16392).
+char(5,16393).
+char(7,16394).
+char(9,16395).
+char(6,16396).
+char(m,16397).
+char(6,16398).
+char(1,16399).
+char(5,16400).
+char(7,16401).
+char(c,16402).
+char(m,16403).
+char(9,16404).
+char(5,16405).
+char(8,16406).
+char(3,16407).
+char(c,16408).
+char(m,16409).
+char(9,16410).
+char(7,16411).
+char(3,16412).
+char(2,16413).
+char(c,16414).
+char(c,16415).
+char(c,16416).
+char(p,16417).
+char(o,16418).
+char(p,16419).
+char(2,16420).
+char(7,16421).
+char(3,16422).
+char(0,16423).
+char(m,16424).
+char(o,16425).
+char(p,16426).
+char(o,16427).
+char(9,16428).
+char(4,16429).
+char(5,16430).
+char(m,16431).
+char(o,16432).
+char(p,16433).
+char(8,16434).
+char(5,16435).
+char(9,16436).
+char(9,16437).
+char(p,16438).
+char(1,16439).
+char(3,16440).
+char(7,16441).
+char(7,16442).
+char(m,16443).
+char(3,16444).
+char(4,16445).
+char(9,16446).
+char(8,16447).
+char(c,16448).
+char(c,16449).
+char(m,16450).
+char(o,16451).
+char(5,16452).
+char(1,16453).
+char(3,16454).
+char(3,16455).
+char(p,16456).
+char(o,16457).
+char(m,16458).
+char(5,16459).
+char(5,16460).
+char(1,16461).
+char(6,16462).
+char(p,16463).
+char(o,16464).
+char(m,16465).
+char(o,16466).
+char(p,16467).
+char(6,16468).
+char(4,16469).
+char(4,16470).
+char(1,16471).
+char(c,16472).
+char(m,16473).
+char(o,16474).
+char(m,16475).
+char(o,16476).
+char(m,16477).
+char(o,16478).
+char(p,16479).
+char(o,16480).
+char(6,16481).
+char(6,16482).
+char(3,16483).
+char(6,16484).
+char(c,16485).
+char(m,16486).
+char(4,16487).
+char(2,16488).
+char(8,16489).
+char(3,16490).
+char(p,16491).
+char(2,16492).
+char(3,16493).
+char(9,16494).
+char(3,16495).
+char(m,16496).
+char(6,16497).
+char(4,16498).
+char(5,16499).
+char(c,16500).
+char(m,16501).
+char(7,16502).
+char(0,16503).
+char(5,16504).
+char(1,16505).
+char(m,16506).
+char(o,16507).
+char(o,16508).
+char(p,16509).
+char(o,16510).
+char(p,16511).
+char(8,16512).
+char(4,16513).
+char(3,16514).
+char(m,16515).
+char(o,16516).
+char(m,16517).
+char(o,16518).
+char(m,16519).
+char(o,16520).
+char(p,16521).
+char(o,16522).
+char(p,16523).
+char(o,16524).
+char(m,16525).
+char(o,16526).
+char(o,16527).
+char(p,16528).
+char(o,16529).
+char(m,16530).
+char(o,16531).
+char(p,16532).
+char(o,16533).
+char(6,16534).
+char(4,16535).
+char(8,16536).
+char(0,16537).
+char(p,16538).
+char(1,16539).
+char(0,16540).
+char(4,16541).
+char(2,16542).
+char(p,16543).
+char(o,16544).
+char(m,16545).
+char(1,16546).
+char(5,16547).
+char(2,16548).
+char(8,16549).
+char(p,16550).
+char(o,16551).
+char(p,16552).
+char(o,16553).
+char(o,16554).
+char(3,16555).
+char(4,16556).
+char(5,16557).
+char(7,16558).
+char(p,16559).
+char(o,16560).
+char(p,16561).
+char(o,16562).
+char(p,16563).
+char(9,16564).
+char(6,16565).
+char(8,16566).
+char(m,16567).
+char(o,16568).
+char(p,16569).
+char(7,16570).
+char(6,16571).
+char(5,16572).
+char(5,16573).
+char(c,16574).
+char(p,16575).
+char(9,16576).
+char(5,16577).
+char(5,16578).
+char(9,16579).
+char(p,16580).
+char(o,16581).
+char(2,16582).
+char(0,16583).
+char(8,16584).
+char(9,16585).
+char(p,16586).
+char(o,16587).
+char(p,16588).
+char(8,16589).
+char(8,16590).
+char(4,16591).
+char(1,16592).
+char(c,16593).
+char(p,16594).
+char(7,16595).
+char(9,16596).
+char(3,16597).
+char(5,16598).
+char(c,16599).
+char(c,16600).
+char(p,16601).
+char(o,16602).
+char(m,16603).
+char(o,16604).
+char(o,16605).
+char(p,16606).
+char(o,16607).
+char(m,16608).
+char(9,16609).
+char(9,16610).
+char(4,16611).
+char(4,16612).
+char(p,16613).
+char(9,16614).
+char(4,16615).
+char(1,16616).
+char(6,16617).
+char(c,16618).
+char(c,16619).
+char(m,16620).
+char(o,16621).
+char(m,16622).
+char(o,16623).
+char(p,16624).
+char(o,16625).
+char(p,16626).
+char(o,16627).
+char(m,16628).
+char(9,16629).
+char(4,16630).
+char(3,16631).
+char(9,16632).
+char(c,16633).
+char(c,16634).
+char(m,16635).
+char(9,16636).
+char(8,16637).
+char(5,16638).
+char(7,16639).
+char(m,16640).
+char(6,16641).
+char(6,16642).
+char(1,16643).
+char(4,16644).
+char(c,16645).
+char(c,16646).
+char(m,16647).
+char(o,16648).
+char(o,16649).
+char(p,16650).
+char(o,16651).
+char(m,16652).
+char(5,16653).
+char(9,16654).
+char(2,16655).
+char(0,16656).
+char(p,16657).
+char(2,16658).
+char(1,16659).
+char(8,16660).
+char(c,16661).
+char(c,16662).
+char(p,16663).
+char(o,16664).
+char(p,16665).
+char(9,16666).
+char(1,16667).
+char(2,16668).
+char(5,16669).
+char(c,16670).
+char(p,16671).
+char(o,16672).
+char(m,16673).
+char(o,16674).
+char(m,16675).
+char(5,16676).
+char(1,16677).
+char(7,16678).
+char(2,16679).
+char(m,16680).
+char(o,16681).
+char(p,16682).
+char(o,16683).
+char(o,16684).
+char(m,16685).
+char(o,16686).
+char(m,16687).
+char(o,16688).
+char(m,16689).
+char(2,16690).
+char(6,16691).
+char(3,16692).
+char(8,16693).
+char(p,16694).
+char(o,16695).
+char(m,16696).
+char(o,16697).
+char(m,16698).
+char(o,16699).
+char(m,16700).
+char(o,16701).
+char(m,16702).
+char(7,16703).
+char(6,16704).
+char(5,16705).
+char(8,16706).
+char(p,16707).
+char(2,16708).
+char(1,16709).
+char(6,16710).
+char(c,16711).
+char(p,16712).
+char(1,16713).
+char(5,16714).
+char(7,16715).
+char(4,16716).
+char(p,16717).
+char(6,16718).
+char(2,16719).
+char(8,16720).
+char(2,16721).
+char(c,16722).
+char(c,16723).
+char(c,16724).
+char(p,16725).
+char(o,16726).
+char(p,16727).
+char(o,16728).
+char(m,16729).
+char(o,16730).
+char(m,16731).
+char(o,16732).
+char(m,16733).
+char(o,16734).
+char(m,16735).
+char(o,16736).
+char(m,16737).
+char(4,16738).
+char(1,16739).
+char(8,16740).
+char(6,16741).
+char(p,16742).
+char(o,16743).
+char(p,16744).
+char(o,16745).
+char(m,16746).
+char(o,16747).
+char(m,16748).
+char(o,16749).
+char(p,16750).
+char(5,16751).
+char(1,16752).
+char(3,16753).
+char(7,16754).
+char(c,16755).
+char(c,16756).
+char(m,16757).
+char(o,16758).
+char(o,16759).
+char(m,16760).
+char(9,16761).
+char(8,16762).
+char(3,16763).
+char(5,16764).
+char(p,16765).
+char(o,16766).
+char(o,16767).
+char(1,16768).
+char(3,16769).
+char(9,16770).
+char(2,16771).
+char(p,16772).
+char(o,16773).
+char(p,16774).
+char(o,16775).
+char(o,16776).
+char(p,16777).
+char(o,16778).
+char(p,16779).
+char(7,16780).
+char(1,16781).
+char(0,16782).
+char(9,16783).
+char(c,16784).
+char(c,16785).
+char(p,16786).
+char(o,16787).
+char(m,16788).
+char(8,16789).
+char(2,16790).
+char(2,16791).
+char(0,16792).
+char(p,16793).
+char(o,16794).
+char(o,16795).
+char(p,16796).
+char(o,16797).
+char(p,16798).
+char(o,16799).
+char(o,16800).
+char(o,16801).
+char(p,16802).
+char(2,16803).
+char(3,16804).
+char(5,16805).
+char(6,16806).
+char(p,16807).
+char(8,16808).
+char(7,16809).
+char(0,16810).
+char(5,16811).
+char(c,16812).
+char(c,16813).
+char(m,16814).
+char(1,16815).
+char(1,16816).
+char(5,16817).
+char(3,16818).
+char(c,16819).
+char(m,16820).
+char(o,16821).
+char(9,16822).
+char(4,16823).
+char(6,16824).
+char(2,16825).
+char(c,16826).
+char(p,16827).
+char(2,16828).
+char(1,16829).
+char(9,16830).
+char(1,16831).
+char(p,16832).
+char(o,16833).
+char(p,16834).
+char(o,16835).
+char(m,16836).
+char(8,16837).
+char(9,16838).
+char(3,16839).
+char(1,16840).
+char(p,16841).
+char(o,16842).
+char(p,16843).
+char(9,16844).
+char(7,16845).
+char(8,16846).
+char(9,16847).
+char(c,16848).
+char(m,16849).
+char(8,16850).
+char(9,16851).
+char(6,16852).
+char(7,16853).
+char(c,16854).
+char(c,16855).
+char(c,16856).
+char(c,16857).
+char(c,16858).
+char(c,16859).
+char(p,16860).
+char(7,16861).
+char(3,16862).
+char(4,16863).
+char(6,16864).
+char(c,16865).
+char(c,16866).
+char(p,16867).
+char(7,16868).
+char(0,16869).
+char(8,16870).
+char(4,16871).
+char(p,16872).
+char(o,16873).
+char(m,16874).
+char(o,16875).
+char(m,16876).
+char(7,16877).
+char(6,16878).
+char(8,16879).
+char(c,16880).
+char(p,16881).
+char(1,16882).
+char(3,16883).
+char(3,16884).
+char(4,16885).
+char(c,16886).
+char(c,16887).
+char(m,16888).
+char(o,16889).
+char(m,16890).
+char(o,16891).
+char(5,16892).
+char(5,16893).
+char(0,16894).
+char(p,16895).
+char(4,16896).
+char(6,16897).
+char(4,16898).
+char(0,16899).
+char(c,16900).
+char(p,16901).
+char(o,16902).
+char(m,16903).
+char(o,16904).
+char(4,16905).
+char(5,16906).
+char(5,16907).
+char(7,16908).
+char(m,16909).
+char(o,16910).
+char(p,16911).
+char(o,16912).
+char(m,16913).
+char(o,16914).
+char(p,16915).
+char(5,16916).
+char(8,16917).
+char(4,16918).
+char(0,16919).
+char(c,16920).
+char(c,16921).
+char(m,16922).
+char(2,16923).
+char(2,16924).
+char(3,16925).
+char(7,16926).
+char(p,16927).
+char(o,16928).
+char(m,16929).
+char(o,16930).
+char(p,16931).
+char(o,16932).
+char(o,16933).
+char(m,16934).
+char(o,16935).
+char(9,16936).
+char(0,16937).
+char(3,16938).
+char(8,16939).
+char(c,16940).
+char(p,16941).
+char(o,16942).
+char(p,16943).
+char(o,16944).
+char(3,16945).
+char(6,16946).
+char(5,16947).
+char(1,16948).
+char(p,16949).
+char(4,16950).
+char(4,16951).
+char(9,16952).
+char(m,16953).
+char(2,16954).
+char(0,16955).
+char(2,16956).
+char(8,16957).
+char(p,16958).
+char(o,16959).
+char(p,16960).
+char(o,16961).
+char(m,16962).
+char(5,16963).
+char(2,16964).
+char(2,16965).
+char(1,16966).
+char(p,16967).
+char(o,16968).
+char(p,16969).
+char(o,16970).
+char(p,16971).
+char(o,16972).
+char(p,16973).
+char(3,16974).
+char(0,16975).
+char(2,16976).
+char(8,16977).
+char(m,16978).
+char(4,16979).
+char(0,16980).
+char(5,16981).
+char(6,16982).
+char(p,16983).
+char(4,16984).
+char(8,16985).
+char(0,16986).
+char(9,16987).
+char(c,16988).
+char(m,16989).
+char(o,16990).
+char(p,16991).
+char(o,16992).
+char(o,16993).
+char(p,16994).
+char(3,16995).
+char(6,16996).
+char(7,16997).
+char(0,16998).
+char(c,16999).
+char(p,17000).
+char(o,17001).
+char(o,17002).
+char(p,17003).
+char(o,17004).
+char(o,17005).
+char(o,17006).
+char(o,17007).
+char(m,17008).
+char(o,17009).
+char(8,17010).
+char(6,17011).
+char(6,17012).
+char(1,17013).
+char(c,17014).
+char(p,17015).
+char(7,17016).
+char(0,17017).
+char(1,17018).
+char(p,17019).
+char(o,17020).
+char(p,17021).
+char(3,17022).
+char(5,17023).
+char(8,17024).
+char(4,17025).
+char(m,17026).
+char(o,17027).
+char(7,17028).
+char(5,17029).
+char(2,17030).
+char(9,17031).
+char(c,17032).
+char(m,17033).
+char(4,17034).
+char(6,17035).
+char(4,17036).
+char(2,17037).
+char(c,17038).
+char(c,17039).
+char(p,17040).
+char(o,17041).
+char(m,17042).
+char(o,17043).
+char(o,17044).
+char(m,17045).
+char(o,17046).
+char(m,17047).
+char(o,17048).
+char(m,17049).
+char(1,17050).
+char(8,17051).
+char(1,17052).
+char(8,17053).
+char(m,17054).
+char(8,17055).
+char(8,17056).
+char(2,17057).
+char(7,17058).
+char(c,17059).
+char(p,17060).
+char(9,17061).
+char(2,17062).
+char(5,17063).
+char(c,17064).
+char(c,17065).
+char(m,17066).
+char(o,17067).
+char(m,17068).
+char(o,17069).
+char(m,17070).
+char(o,17071).
+char(m,17072).
+char(o,17073).
+char(o,17074).
+char(m,17075).
+char(1,17076).
+char(7,17077).
+char(6,17078).
+char(4,17079).
+char(c,17080).
+char(p,17081).
+char(4,17082).
+char(7,17083).
+char(8,17084).
+char(3,17085).
+char(c,17086).
+char(p,17087).
+char(o,17088).
+char(m,17089).
+char(3,17090).
+char(7,17091).
+char(0,17092).
+char(7,17093).
+char(m,17094).
+char(o,17095).
+char(p,17096).
+char(o,17097).
+char(p,17098).
+char(8,17099).
+char(3,17100).
+char(7,17101).
+char(c,17102).
+char(m,17103).
+char(o,17104).
+char(p,17105).
+char(o,17106).
+char(m,17107).
+char(3,17108).
+char(9,17109).
+char(1,17110).
+char(2,17111).
+char(m,17112).
+char(o,17113).
+char(m,17114).
+char(o,17115).
+char(p,17116).
+char(o,17117).
+char(p,17118).
+char(o,17119).
+char(6,17120).
+char(2,17121).
+char(6,17122).
+char(1,17123).
+char(c,17124).
+char(p,17125).
+char(3,17126).
+char(2,17127).
+char(9,17128).
+char(6,17129).
+char(m,17130).
+char(o,17131).
+char(m,17132).
+char(o,17133).
+char(p,17134).
+char(1,17135).
+char(0,17136).
+char(9,17137).
+char(1,17138).
+char(p,17139).
+char(4,17140).
+char(3,17141).
+char(9,17142).
+char(9,17143).
+char(m,17144).
+char(o,17145).
+char(m,17146).
+char(5,17147).
+char(9,17148).
+char(8,17149).
+char(8,17150).
+char(c,17151).
+char(c,17152).
+char(c,17153).
+char(m,17154).
+char(o,17155).
+char(p,17156).
+char(3,17157).
+char(6,17158).
+char(9,17159).
+char(4,17160).
+char(m,17161).
+char(o,17162).
+char(m,17163).
+char(o,17164).
+char(p,17165).
+char(o,17166).
+char(m,17167).
+char(5,17168).
+char(2,17169).
+char(6,17170).
+char(0,17171).
+char(c,17172).
+char(c,17173).
+char(c,17174).
+char(c,17175).
+char(m,17176).
+char(2,17177).
+char(7,17178).
+char(2,17179).
+char(c,17180).
+char(m,17181).
+char(5,17182).
+char(1,17183).
+char(2,17184).
+char(0,17185).
+char(c,17186).
+char(p,17187).
+char(o,17188).
+char(p,17189).
+char(o,17190).
+char(8,17191).
+char(7,17192).
+char(1,17193).
+char(1,17194).
+char(m,17195).
+char(o,17196).
+char(p,17197).
+char(o,17198).
+char(p,17199).
+char(o,17200).
+char(p,17201).
+char(6,17202).
+char(5,17203).
+char(6,17204).
+char(2,17205).
+char(c,17206).
+char(m,17207).
+char(4,17208).
+char(7,17209).
+char(m,17210).
+char(o,17211).
+char(m,17212).
+char(3,17213).
+char(2,17214).
+char(2,17215).
+char(2,17216).
+char(m,17217).
+char(o,17218).
+char(m,17219).
+char(5,17220).
+char(2,17221).
+char(m,17222).
+char(9,17223).
+char(9,17224).
+char(5,17225).
+char(6,17226).
+char(c,17227).
+char(m,17228).
+char(o,17229).
+char(p,17230).
+char(o,17231).
+char(p,17232).
+char(o,17233).
+char(7,17234).
+char(9,17235).
+char(2,17236).
+char(2,17237).
+char(c,17238).
+char(c,17239).
+char(c,17240).
+char(c,17241).
+char(p,17242).
+char(3,17243).
+char(3,17244).
+char(8,17245).
+char(9,17246).
+char(p,17247).
+char(8,17248).
+char(9,17249).
+char(8,17250).
+char(5,17251).
+char(m,17252).
+char(3,17253).
+char(9,17254).
+char(0,17255).
+char(6,17256).
+char(c,17257).
+char(m,17258).
+char(9,17259).
+char(1,17260).
+char(1,17261).
+char(3,17262).
+char(c,17263).
+char(c,17264).
+char(c,17265).
+char(c,17266).
+char(m,17267).
+char(o,17268).
+char(5,17269).
+char(9,17270).
+char(9,17271).
+char(3,17272).
+char(c,17273).
+char(c,17274).
+char(m,17275).
+char(2,17276).
+char(1,17277).
+char(9,17278).
+char(1,17279).
+char(c,17280).
+char(c,17281).
+char(p,17282).
+char(o,17283).
+char(o,17284).
+char(p,17285).
+char(2,17286).
+char(0,17287).
+char(3,17288).
+char(2,17289).
+char(c,17290).
+char(m,17291).
+char(o,17292).
+char(m,17293).
+char(6,17294).
+char(5,17295).
+char(3,17296).
+char(5,17297).
+char(c,17298).
+char(c,17299).
+char(c,17300).
+char(m,17301).
+char(7,17302).
+char(6,17303).
+char(7,17304).
+char(3,17305).
+char(m,17306).
+char(o,17307).
+char(3,17308).
+char(2,17309).
+char(2,17310).
+char(4,17311).
+char(c,17312).
+char(c,17313).
+char(m,17314).
+char(9,17315).
+char(3,17316).
+char(3,17317).
+char(m,17318).
+char(o,17319).
+char(m,17320).
+char(o,17321).
+char(o,17322).
+char(7,17323).
+char(9,17324).
+char(9,17325).
+char(6,17326).
+char(p,17327).
+char(o,17328).
+char(o,17329).
+char(m,17330).
+char(o,17331).
+char(m,17332).
+char(2,17333).
+char(7,17334).
+char(8,17335).
+char(8,17336).
+char(c,17337).
+char(m,17338).
+char(o,17339).
+char(o,17340).
+char(m,17341).
+char(4,17342).
+char(5,17343).
+char(7,17344).
+char(1,17345).
+char(p,17346).
+char(o,17347).
+char(p,17348).
+char(o,17349).
+char(p,17350).
+char(3,17351).
+char(1,17352).
+char(6,17353).
+char(p,17354).
+char(o,17355).
+char(m,17356).
+char(3,17357).
+char(3,17358).
+char(7,17359).
+char(3,17360).
+char(c,17361).
+char(c,17362).
+char(p,17363).
+char(1,17364).
+char(6,17365).
+char(6,17366).
+char(7,17367).
+char(p,17368).
+char(2,17369).
+char(3,17370).
+char(2,17371).
+char(p,17372).
+char(8,17373).
+char(3,17374).
+char(1,17375).
+char(4,17376).
+char(c,17377).
+char(c,17378).
+char(c,17379).
+char(c,17380).
+char(c,17381).
+char(p,17382).
+char(o,17383).
+char(m,17384).
+char(o,17385).
+char(p,17386).
+char(o,17387).
+char(1,17388).
+char(3,17389).
+char(5,17390).
+char(9,17391).
+char(c,17392).
+char(p,17393).
+char(9,17394).
+char(4,17395).
+char(6,17396).
+char(4,17397).
+char(m,17398).
+char(6,17399).
+char(5,17400).
+char(7,17401).
+char(9,17402).
+char(m,17403).
+char(o,17404).
+char(o,17405).
+char(p,17406).
+char(o,17407).
+char(2,17408).
+char(9,17409).
+char(5,17410).
+char(3,17411).
+char(c,17412).
+char(c,17413).
+char(c,17414).
+char(c,17415).
+char(c,17416).
+char(m,17417).
+char(o,17418).
+char(o,17419).
+char(1,17420).
+char(7,17421).
+char(8,17422).
+char(0,17423).
+char(c,17424).
+char(c,17425).
+char(p,17426).
+char(o,17427).
+char(m,17428).
+char(5,17429).
+char(8,17430).
+char(1,17431).
+char(7,17432).
+char(p,17433).
+char(1,17434).
+char(9,17435).
+char(3,17436).
+char(c,17437).
+char(m,17438).
+char(o,17439).
+char(o,17440).
+char(o,17441).
+char(5,17442).
+char(2,17443).
+char(6,17444).
+char(8,17445).
+char(p,17446).
+char(o,17447).
+char(p,17448).
+char(4,17449).
+char(6,17450).
+char(0,17451).
+char(8,17452).
+char(p,17453).
+char(o,17454).
+char(p,17455).
+char(7,17456).
+char(3,17457).
+char(6,17458).
+char(8,17459).
+char(c,17460).
+char(c,17461).
+char(m,17462).
+char(o,17463).
+char(4,17464).
+char(4,17465).
+char(2,17466).
+char(7,17467).
+char(c,17468).
+char(c,17469).
+char(m,17470).
+char(5,17471).
+char(1,17472).
+char(0,17473).
+char(4,17474).
+char(c,17475).
+char(m,17476).
+char(9,17477).
+char(3,17478).
+char(8,17479).
+char(6,17480).
+char(c,17481).
+char(p,17482).
+char(7,17483).
+char(5,17484).
+char(2,17485).
+char(0,17486).
+char(m,17487).
+char(7,17488).
+char(8,17489).
+char(5,17490).
+char(2,17491).
+char(m,17492).
+char(o,17493).
+char(m,17494).
+char(1,17495).
+char(1,17496).
+char(3,17497).
+char(7,17498).
+char(m,17499).
+char(8,17500).
+char(9,17501).
+char(9,17502).
+char(9,17503).
+char(c,17504).
+char(p,17505).
+char(3,17506).
+char(4,17507).
+char(2,17508).
+char(6,17509).
+char(c,17510).
+char(c,17511).
+char(c,17512).
+char(p,17513).
+char(6,17514).
+char(9,17515).
+char(6,17516).
+char(8,17517).
+char(c,17518).
+char(p,17519).
+char(o,17520).
+char(m,17521).
+char(9,17522).
+char(3,17523).
+char(2,17524).
+char(2,17525).
+char(c,17526).
+char(p,17527).
+char(5,17528).
+char(2,17529).
+char(9,17530).
+char(8,17531).
+char(m,17532).
+char(o,17533).
+char(p,17534).
+char(o,17535).
+char(m,17536).
+char(o,17537).
+char(5,17538).
+char(7,17539).
+char(9,17540).
+char(7,17541).
+char(m,17542).
+char(o,17543).
+char(p,17544).
+char(o,17545).
+char(p,17546).
+char(o,17547).
+char(m,17548).
+char(o,17549).
+char(m,17550).
+char(2,17551).
+char(2,17552).
+char(7,17553).
+char(3,17554).
+char(c,17555).
+char(c,17556).
+char(c,17557).
+char(c,17558).
+char(c,17559).
+char(p,17560).
+char(3,17561).
+char(3,17562).
+char(5,17563).
+char(3,17564).
+char(c,17565).
+char(p,17566).
+char(1,17567).
+char(2,17568).
+char(9,17569).
+char(3,17570).
+char(m,17571).
+char(9,17572).
+char(1,17573).
+char(2,17574).
+char(9,17575).
+char(m,17576).
+char(3,17577).
+char(7,17578).
+char(6,17579).
+char(0,17580).
+char(c,17581).
+char(p,17582).
+char(8,17583).
+char(4,17584).
+char(0,17585).
+char(2,17586).
+char(p,17587).
+char(o,17588).
+char(o,17589).
+char(p,17590).
+char(o,17591).
+char(p,17592).
+char(o,17593).
+char(p,17594).
+char(4,17595).
+char(3,17596).
+char(8,17597).
+char(c,17598).
+char(c,17599).
+char(p,17600).
+char(8,17601).
+char(3,17602).
+char(7,17603).
+char(9,17604).
+char(m,17605).
+char(6,17606).
+char(9,17607).
+char(8,17608).
+char(6,17609).
+char(c,17610).
+char(c,17611).
+char(c,17612).
+char(c,17613).
+char(m,17614).
+char(o,17615).
+char(o,17616).
+char(o,17617).
+char(p,17618).
+char(7,17619).
+char(0,17620).
+char(9,17621).
+char(9,17622).
+char(c,17623).
+char(c,17624).
+char(c,17625).
+char(c,17626).
+char(c,17627).
+char(c,17628).
+char(p,17629).
+char(9,17630).
+char(5,17631).
+char(7,17632).
+char(3,17633).
+char(m,17634).
+char(o,17635).
+char(m,17636).
+char(7,17637).
+char(0,17638).
+char(9,17639).
+char(5,17640).
+char(m,17641).
+char(o,17642).
+char(m,17643).
+char(o,17644).
+char(2,17645).
+char(0,17646).
+char(2,17647).
+char(4,17648).
+char(p,17649).
+char(8,17650).
+char(0,17651).
+char(9,17652).
+char(8,17653).
+char(c,17654).
+char(c,17655).
+char(m,17656).
+char(3,17657).
+char(3,17658).
+char(0,17659).
+char(c,17660).
+char(m,17661).
+char(o,17662).
+char(o,17663).
+char(p,17664).
+char(o,17665).
+char(m,17666).
+char(4,17667).
+char(0,17668).
+char(8,17669).
+char(2,17670).
+char(p,17671).
+char(5,17672).
+char(2,17673).
+char(0,17674).
+char(1,17675).
+char(m,17676).
+char(6,17677).
+char(4,17678).
+char(7,17679).
+char(5,17680).
+char(p,17681).
+char(8,17682).
+char(0,17683).
+char(2,17684).
+char(8,17685).
+char(m,17686).
+char(o,17687).
+char(9,17688).
+char(4,17689).
+char(7,17690).
+char(8,17691).
+char(c,17692).
+char(m,17693).
+char(o,17694).
+char(3,17695).
+char(0,17696).
+char(4,17697).
+char(8,17698).
+char(m,17699).
+char(o,17700).
+char(m,17701).
+char(o,17702).
+char(m,17703).
+char(3,17704).
+char(6,17705).
+char(1,17706).
+char(8,17707).
+char(c,17708).
+char(m,17709).
+char(o,17710).
+char(m,17711).
+char(o,17712).
+char(6,17713).
+char(7,17714).
+char(4,17715).
+char(6,17716).
+char(p,17717).
+char(o,17718).
+char(o,17719).
+char(m,17720).
+char(8,17721).
+char(1,17722).
+char(4,17723).
+char(8,17724).
+char(m,17725).
+char(3,17726).
+char(9,17727).
+char(5,17728).
+char(2,17729).
+char(c,17730).
+char(c,17731).
+char(c,17732).
+char(m,17733).
+char(8,17734).
+char(6,17735).
+char(9,17736).
+char(7,17737).
+char(c,17738).
+char(c,17739).
+char(c,17740).
+char(c,17741).
+char(c,17742).
+char(c,17743).
+char(p,17744).
+char(3,17745).
+char(9,17746).
+char(2,17747).
+char(6,17748).
+char(m,17749).
+char(6,17750).
+char(7,17751).
+char(9,17752).
+char(5,17753).
+char(m,17754).
+char(o,17755).
+char(m,17756).
+char(o,17757).
+char(o,17758).
+char(p,17759).
+char(2,17760).
+char(9,17761).
+char(0,17762).
+char(9,17763).
+char(c,17764).
+char(m,17765).
+char(o,17766).
+char(5,17767).
+char(4,17768).
+char(2,17769).
+char(p,17770).
+char(8,17771).
+char(9,17772).
+char(8,17773).
+char(9,17774).
+char(c,17775).
+char(c,17776).
+char(m,17777).
+char(3,17778).
+char(0,17779).
+char(6,17780).
+char(5,17781).
+char(p,17782).
+char(o,17783).
+char(o,17784).
+char(p,17785).
+char(o,17786).
+char(m,17787).
+char(5,17788).
+char(5,17789).
+char(1,17790).
+char(4,17791).
+char(m,17792).
+char(o,17793).
+char(p,17794).
+char(4,17795).
+char(3,17796).
+char(8,17797).
+char(7,17798).
+char(p,17799).
+char(7,17800).
+char(4,17801).
+char(0,17802).
+char(3,17803).
+char(p,17804).
+char(2,17805).
+char(9,17806).
+char(m,17807).
+char(o,17808).
+char(p,17809).
+char(4,17810).
+char(3,17811).
+char(7,17812).
+char(2,17813).
+char(c,17814).
+char(c,17815).
+char(c,17816).
+char(m,17817).
+char(o,17818).
+char(m,17819).
+char(o,17820).
+char(m,17821).
+char(2,17822).
+char(8,17823).
+char(5,17824).
+char(2,17825).
+char(p,17826).
+char(o,17827).
+char(m,17828).
+char(o,17829).
+char(m,17830).
+char(o,17831).
+char(m,17832).
+char(o,17833).
+char(m,17834).
+char(1,17835).
+char(2,17836).
+char(9,17837).
+char(7,17838).
+char(c,17839).
+char(p,17840).
+char(4,17841).
+char(6,17842).
+char(6,17843).
+char(6,17844).
+char(m,17845).
+char(2,17846).
+char(1,17847).
+char(2,17848).
+char(1,17849).
+char(p,17850).
+char(o,17851).
+char(m,17852).
+char(o,17853).
+char(o,17854).
+char(p,17855).
+char(o,17856).
+char(m,17857).
+char(o,17858).
+char(7,17859).
+char(4,17860).
+char(6,17861).
+char(5,17862).
+char(p,17863).
+char(o,17864).
+char(4,17865).
+char(3,17866).
+char(5,17867).
+char(6,17868).
+char(c,17869).
+char(c,17870).
+char(m,17871).
+char(o,17872).
+char(1,17873).
+char(7,17874).
+char(0,17875).
+char(m,17876).
+char(o,17877).
+char(5,17878).
+char(6,17879).
+char(8,17880).
+char(4,17881).
+char(m,17882).
+char(o,17883).
+char(m,17884).
+char(o,17885).
+char(p,17886).
+char(7,17887).
+char(1,17888).
+char(c,17889).
+char(p,17890).
+char(6,17891).
+char(8,17892).
+char(9,17893).
+char(0,17894).
+char(c,17895).
+char(p,17896).
+char(2,17897).
+char(5,17898).
+char(3,17899).
+char(7,17900).
+char(c,17901).
+char(c,17902).
+char(p,17903).
+char(o,17904).
+char(o,17905).
+char(p,17906).
+char(9,17907).
+char(9,17908).
+char(7,17909).
+char(6,17910).
+char(p,17911).
+char(o,17912).
+char(o,17913).
+char(p,17914).
+char(o,17915).
+char(p,17916).
+char(5,17917).
+char(1,17918).
+char(1,17919).
+char(6,17920).
+char(c,17921).
+char(c,17922).
+char(m,17923).
+char(5,17924).
+char(7,17925).
+char(4,17926).
+char(2,17927).
+char(m,17928).
+char(7,17929).
+char(7,17930).
+char(4,17931).
+char(3,17932).
+char(p,17933).
+char(o,17934).
+char(9,17935).
+char(7,17936).
+char(8,17937).
+char(9,17938).
+char(c,17939).
+char(p,17940).
+char(o,17941).
+char(m,17942).
+char(7,17943).
+char(2,17944).
+char(9,17945).
+char(0,17946).
+char(c,17947).
+char(m,17948).
+char(o,17949).
+char(m,17950).
+char(o,17951).
+char(m,17952).
+char(9,17953).
+char(5,17954).
+char(3,17955).
+char(8,17956).
+char(c,17957).
+char(m,17958).
+char(8,17959).
+char(7,17960).
+char(6,17961).
+char(6,17962).
+char(c,17963).
+char(m,17964).
+char(2,17965).
+char(2,17966).
+char(7,17967).
+char(2,17968).
+char(p,17969).
+char(6,17970).
+char(0,17971).
+char(5,17972).
+char(5,17973).
+char(p,17974).
+char(6,17975).
+char(6,17976).
+char(4,17977).
+char(1,17978).
+char(c,17979).
+char(m,17980).
+char(o,17981).
+char(p,17982).
+char(8,17983).
+char(5,17984).
+char(4,17985).
+char(0,17986).
+char(c,17987).
+char(c,17988).
+char(m,17989).
+char(o,17990).
+char(m,17991).
+char(o,17992).
+char(p,17993).
+char(o,17994).
+char(o,17995).
+char(m,17996).
+char(o,17997).
+char(p,17998).
+char(o,17999).
+char(m,18000).
+char(3,18001).
+char(0,18002).
+char(7,18003).
+char(5,18004).
+char(m,18005).
+char(o,18006).
+char(m,18007).
+char(1,18008).
+char(9,18009).
+char(9,18010).
+char(c,18011).
+char(m,18012).
+char(o,18013).
+char(m,18014).
+char(o,18015).
+char(p,18016).
+char(6,18017).
+char(6,18018).
+char(6,18019).
+char(6,18020).
+char(m,18021).
+char(o,18022).
+char(o,18023).
+char(p,18024).
+char(o,18025).
+char(5,18026).
+char(7,18027).
+char(9,18028).
+char(2,18029).
+char(c,18030).
+char(c,18031).
+char(c,18032).
+char(m,18033).
+char(9,18034).
+char(9,18035).
+char(4,18036).
+char(2,18037).
+char(c,18038).
+char(c,18039).
+char(p,18040).
+char(o,18041).
+char(1,18042).
+char(4,18043).
+char(0,18044).
+char(5,18045).
+char(m,18046).
+char(8,18047).
+char(7,18048).
+char(6,18049).
+char(4,18050).
+char(m,18051).
+char(o,18052).
+char(o,18053).
+char(m,18054).
+char(1,18055).
+char(5,18056).
+char(7,18057).
+char(7,18058).
+char(c,18059).
+char(m,18060).
+char(o,18061).
+char(7,18062).
+char(0,18063).
+char(6,18064).
+char(8,18065).
+char(m,18066).
+char(o,18067).
+char(3,18068).
+char(7,18069).
+char(8,18070).
+char(2,18071).
+char(c,18072).
+char(c,18073).
+char(c,18074).
+char(c,18075).
+char(m,18076).
+char(o,18077).
+char(7,18078).
+char(8,18079).
+char(0,18080).
+char(3,18081).
+char(c,18082).
+char(c,18083).
+char(p,18084).
+char(o,18085).
+char(p,18086).
+char(5,18087).
+char(8,18088).
+char(6,18089).
+char(2,18090).
+char(c,18091).
+char(p,18092).
+char(o,18093).
+char(m,18094).
+char(6,18095).
+char(7,18096).
+char(3,18097).
+char(7,18098).
+char(m,18099).
+char(o,18100).
+char(p,18101).
+char(1,18102).
+char(5,18103).
+char(3,18104).
+char(3,18105).
+char(p,18106).
+char(o,18107).
+char(o,18108).
+char(p,18109).
+char(o,18110).
+char(p,18111).
+char(o,18112).
+char(m,18113).
+char(1,18114).
+char(6,18115).
+char(7,18116).
+char(6,18117).
+char(c,18118).
+char(c,18119).
+char(m,18120).
+char(3,18121).
+char(9,18122).
+char(8,18123).
+char(0,18124).
+char(p,18125).
+char(o,18126).
+char(m,18127).
+char(4,18128).
+char(4,18129).
+char(5,18130).
+char(7,18131).
+char(c,18132).
+char(m,18133).
+char(5,18134).
+char(3,18135).
+char(3,18136).
+char(3,18137).
+char(p,18138).
+char(o,18139).
+char(o,18140).
+char(p,18141).
+char(o,18142).
+char(p,18143).
+char(o,18144).
+char(5,18145).
+char(1,18146).
+char(8,18147).
+char(4,18148).
+char(c,18149).
+char(c,18150).
+char(c,18151).
+char(p,18152).
+char(1,18153).
+char(3,18154).
+char(2,18155).
+char(9,18156).
+char(m,18157).
+char(o,18158).
+char(o,18159).
+char(m,18160).
+char(o,18161).
+char(p,18162).
+char(o,18163).
+char(o,18164).
+char(m,18165).
+char(o,18166).
+char(9,18167).
+char(3,18168).
+char(1,18169).
+char(9,18170).
+char(c,18171).
+char(p,18172).
+char(3,18173).
+char(7,18174).
+char(4,18175).
+char(5,18176).
+char(c,18177).
+char(c,18178).
+char(c,18179).
+char(m,18180).
+char(o,18181).
+char(p,18182).
+char(4,18183).
+char(5,18184).
+char(4,18185).
+char(3,18186).
+char(p,18187).
+char(o,18188).
+char(m,18189).
+char(o,18190).
+char(o,18191).
+char(o,18192).
+char(p,18193).
+char(o,18194).
+char(o,18195).
+char(p,18196).
+char(5,18197).
+char(8,18198).
+char(6,18199).
+char(1,18200).
+char(c,18201).
+char(p,18202).
+char(8,18203).
+char(0,18204).
+char(3,18205).
+char(5,18206).
+char(c,18207).
+char(m,18208).
+char(8,18209).
+char(1,18210).
+char(9,18211).
+char(2,18212).
+char(p,18213).
+char(9,18214).
+char(1,18215).
+char(8,18216).
+char(5,18217).
+char(p,18218).
+char(9,18219).
+char(1,18220).
+char(6,18221).
+char(2,18222).
+char(c,18223).
+char(c,18224).
+char(c,18225).
+char(c,18226).
+char(p,18227).
+char(2,18228).
+char(2,18229).
+char(9,18230).
+char(8,18231).
+char(c,18232).
+char(m,18233).
+char(o,18234).
+char(o,18235).
+char(p,18236).
+char(o,18237).
+char(m,18238).
+char(6,18239).
+char(8,18240).
+char(0,18241).
+char(3,18242).
+char(c,18243).
+char(c,18244).
+char(m,18245).
+char(o,18246).
+char(5,18247).
+char(2,18248).
+char(4,18249).
+char(9,18250).
+char(m,18251).
+char(o,18252).
+char(m,18253).
+char(o,18254).
+char(o,18255).
+char(p,18256).
+char(2,18257).
+char(7,18258).
+char(9,18259).
+char(3,18260).
+char(m,18261).
+char(o,18262).
+char(p,18263).
+char(6,18264).
+char(5,18265).
+char(5,18266).
+char(1,18267).
+char(m,18268).
+char(6,18269).
+char(3,18270).
+char(8,18271).
+char(4,18272).
+char(p,18273).
+char(4,18274).
+char(6,18275).
+char(3,18276).
+char(m,18277).
+char(7,18278).
+char(5,18279).
+char(4,18280).
+char(8,18281).
+char(p,18282).
+char(4,18283).
+char(9,18284).
+char(7,18285).
+char(4,18286).
+char(p,18287).
+char(o,18288).
+char(m,18289).
+char(9,18290).
+char(7,18291).
+char(6,18292).
+char(4,18293).
+char(c,18294).
+char(p,18295).
+char(7,18296).
+char(5,18297).
+char(0,18298).
+char(8,18299).
+char(c,18300).
+char(m,18301).
+char(1,18302).
+char(2,18303).
+char(9,18304).
+char(7,18305).
+char(c,18306).
+char(c,18307).
+char(p,18308).
+char(o,18309).
+char(p,18310).
+char(2,18311).
+char(0,18312).
+char(6,18313).
+char(5,18314).
+char(c,18315).
+char(c,18316).
+char(m,18317).
+char(o,18318).
+char(p,18319).
+char(o,18320).
+char(m,18321).
+char(o,18322).
+char(m,18323).
+char(1,18324).
+char(7,18325).
+char(0,18326).
+char(1,18327).
+char(c,18328).
+char(m,18329).
+char(o,18330).
+char(3,18331).
+char(5,18332).
+char(0,18333).
+char(0,18334).
+char(p,18335).
+char(6,18336).
+char(4,18337).
+char(0,18338).
+char(1,18339).
+char(c,18340).
+char(m,18341).
+char(6,18342).
+char(1,18343).
+char(7,18344).
+char(8,18345).
+char(p,18346).
+char(1,18347).
+char(0,18348).
+char(0,18349).
+char(6,18350).
+char(p,18351).
+char(3,18352).
+char(9,18353).
+char(1,18354).
+char(1,18355).
+char(c,18356).
+char(c,18357).
+char(c,18358).
+char(m,18359).
+char(o,18360).
+char(8,18361).
+char(3,18362).
+char(2,18363).
+char(8,18364).
+char(m,18365).
+char(3,18366).
+char(5,18367).
+char(1,18368).
+char(5,18369).
+char(c,18370).
+char(p,18371).
+char(o,18372).
+char(m,18373).
+char(o,18374).
+char(m,18375).
+char(5,18376).
+char(4,18377).
+char(1,18378).
+char(m,18379).
+char(5,18380).
+char(5,18381).
+char(9,18382).
+char(7,18383).
+char(m,18384).
+char(2,18385).
+char(8,18386).
+char(5,18387).
+char(9,18388).
+char(c,18389).
+char(c,18390).
+char(p,18391).
+char(2,18392).
+char(6,18393).
+char(7,18394).
+char(4,18395).
+char(p,18396).
+char(o,18397).
+char(o,18398).
+char(p,18399).
+char(o,18400).
+char(o,18401).
+char(p,18402).
+char(o,18403).
+char(7,18404).
+char(6,18405).
+char(4,18406).
+char(2,18407).
+char(c,18408).
+char(c,18409).
+char(p,18410).
+char(4,18411).
+char(6,18412).
+char(4,18413).
+char(3,18414).
+char(p,18415).
+char(2,18416).
+char(8,18417).
+char(7,18418).
+char(p,18419).
+char(o,18420).
+char(o,18421).
+char(o,18422).
+char(5,18423).
+char(2,18424).
+char(7,18425).
+char(5,18426).
+char(m,18427).
+char(2,18428).
+char(4,18429).
+char(8,18430).
+char(p,18431).
+char(o,18432).
+char(p,18433).
+char(o,18434).
+char(7,18435).
+char(1,18436).
+char(5,18437).
+char(1,18438).
+char(m,18439).
+char(7,18440).
+char(9,18441).
+char(1,18442).
+char(8,18443).
+char(c,18444).
+char(p,18445).
+char(9,18446).
+char(5,18447).
+char(3,18448).
+char(4,18449).
+char(m,18450).
+char(o,18451).
+char(p,18452).
+char(4,18453).
+char(8,18454).
+char(5,18455).
+char(4,18456).
+char(p,18457).
+char(7,18458).
+char(3,18459).
+char(2,18460).
+char(0,18461).
+char(c,18462).
+char(c,18463).
+char(c,18464).
+char(p,18465).
+char(7,18466).
+char(3,18467).
+char(7,18468).
+char(9,18469).
+char(c,18470).
+char(p,18471).
+char(o,18472).
+char(p,18473).
+char(o,18474).
+char(7,18475).
+char(3,18476).
+char(5,18477).
+char(0,18478).
+char(c,18479).
+char(m,18480).
+char(2,18481).
+char(0,18482).
+char(8,18483).
+char(c,18484).
+char(c,18485).
+char(p,18486).
+char(5,18487).
+char(2,18488).
+char(6,18489).
+char(m,18490).
+char(o,18491).
+char(m,18492).
+char(o,18493).
+char(m,18494).
+char(o,18495).
+char(p,18496).
+char(7,18497).
+char(0,18498).
+char(9,18499).
+char(5,18500).
+char(p,18501).
+char(4,18502).
+char(5,18503).
+char(6,18504).
+char(4,18505).
+char(c,18506).
+char(c,18507).
+char(c,18508).
+char(c,18509).
+char(c,18510).
+char(m,18511).
+char(9,18512).
+char(0,18513).
+char(4,18514).
+char(0,18515).
+char(c,18516).
+char(p,18517).
+char(4,18518).
+char(7,18519).
+char(c,18520).
+char(c,18521).
+char(c,18522).
+char(m,18523).
+char(4,18524).
+char(8,18525).
+char(0,18526).
+char(2,18527).
+char(c,18528).
+char(c,18529).
+char(c,18530).
+char(p,18531).
+char(4,18532).
+char(4,18533).
+char(8,18534).
+char(6,18535).
+char(m,18536).
+char(1,18537).
+char(0,18538).
+char(8,18539).
+char(0,18540).
+char(c,18541).
+char(m,18542).
+char(o,18543).
+char(m,18544).
+char(o,18545).
+char(p,18546).
+char(5,18547).
+char(2,18548).
+char(8,18549).
+char(2,18550).
+char(c,18551).
+char(c,18552).
+char(p,18553).
+char(o,18554).
+char(m,18555).
+char(o,18556).
+char(p,18557).
+char(4,18558).
+char(8,18559).
+char(1,18560).
+char(9,18561).
+char(p,18562).
+char(8,18563).
+char(3,18564).
+char(4,18565).
+char(c,18566).
+char(m,18567).
+char(9,18568).
+char(0,18569).
+char(4,18570).
+char(2,18571).
+char(p,18572).
+char(o,18573).
+char(m,18574).
+char(o,18575).
+char(p,18576).
+char(8,18577).
+char(9,18578).
+char(7,18579).
+char(7,18580).
+char(p,18581).
+char(3,18582).
+char(2,18583).
+char(7,18584).
+char(2,18585).
+char(c,18586).
+char(m,18587).
+char(3,18588).
+char(9,18589).
+char(0,18590).
+char(7,18591).
+char(c,18592).
+char(c,18593).
+char(p,18594).
+char(1,18595).
+char(1,18596).
+char(7,18597).
+char(7,18598).
+char(p,18599).
+char(9,18600).
+char(8,18601).
+char(8,18602).
+char(6,18603).
+char(c,18604).
+char(m,18605).
+char(o,18606).
+char(p,18607).
+char(6,18608).
+char(2,18609).
+char(7,18610).
+char(0,18611).
+char(p,18612).
+char(7,18613).
+char(6,18614).
+char(0,18615).
+char(5,18616).
+char(p,18617).
+char(2,18618).
+char(9,18619).
+char(9,18620).
+char(6,18621).
+char(c,18622).
+char(c,18623).
+char(m,18624).
+char(o,18625).
+char(o,18626).
+char(p,18627).
+char(o,18628).
+char(m,18629).
+char(o,18630).
+char(p,18631).
+char(2,18632).
+char(3,18633).
+char(7,18634).
+char(7,18635).
+char(c,18636).
+char(p,18637).
+char(8,18638).
+char(4,18639).
+char(5,18640).
+char(7,18641).
+char(p,18642).
+char(o,18643).
+char(p,18644).
+char(8,18645).
+char(9,18646).
+char(9,18647).
+char(7,18648).
+char(m,18649).
+char(o,18650).
+char(8,18651).
+char(0,18652).
+char(2,18653).
+char(0,18654).
+char(c,18655).
+char(m,18656).
+char(o,18657).
+char(p,18658).
+char(o,18659).
+char(o,18660).
+char(p,18661).
+char(9,18662).
+char(0,18663).
+char(0,18664).
+char(7,18665).
+char(m,18666).
+char(2,18667).
+char(1,18668).
+char(7,18669).
+char(4,18670).
+char(c,18671).
+char(m,18672).
+char(8,18673).
+char(8,18674).
+char(3,18675).
+char(7,18676).
+char(m,18677).
+char(o,18678).
+char(m,18679).
+char(o,18680).
+char(o,18681).
+char(o,18682).
+char(o,18683).
+char(m,18684).
+char(o,18685).
+char(o,18686).
+char(p,18687).
+char(5,18688).
+char(6,18689).
+char(4,18690).
+char(5,18691).
+char(c,18692).
+char(m,18693).
+char(o,18694).
+char(5,18695).
+char(7,18696).
+char(8,18697).
+char(6,18698).
+char(m,18699).
+char(o,18700).
+char(m,18701).
+char(o,18702).
+char(m,18703).
+char(o,18704).
+char(m,18705).
+char(9,18706).
+char(3,18707).
+char(3,18708).
+char(0,18709).
+char(c,18710).
+char(c,18711).
+char(m,18712).
+char(5,18713).
+char(1,18714).
+char(3,18715).
+char(4,18716).
+char(c,18717).
+char(p,18718).
+char(4,18719).
+char(9,18720).
+char(0,18721).
+char(5,18722).
+char(c,18723).
+char(p,18724).
+char(o,18725).
+char(m,18726).
+char(o,18727).
+char(o,18728).
+char(m,18729).
+char(4,18730).
+char(7,18731).
+char(0,18732).
+char(4,18733).
+char(p,18734).
+char(8,18735).
+char(9,18736).
+char(6,18737).
+char(5,18738).
+char(c,18739).
+char(c,18740).
+char(c,18741).
+char(c,18742).
+char(m,18743).
+char(o,18744).
+char(o,18745).
+char(m,18746).
+char(5,18747).
+char(8,18748).
+char(1,18749).
+char(5,18750).
+char(c,18751).
+char(p,18752).
+char(o,18753).
+char(p,18754).
+char(7,18755).
+char(6,18756).
+char(6,18757).
+char(6,18758).
+char(p,18759).
+char(o,18760).
+char(p,18761).
+char(7,18762).
+char(8,18763).
+char(5,18764).
+char(9,18765).
+char(c,18766).
+char(m,18767).
+char(o,18768).
+char(o,18769).
+char(o,18770).
+char(p,18771).
+char(6,18772).
+char(1,18773).
+char(1,18774).
+char(2,18775).
+char(c,18776).
+char(c,18777).
+char(c,18778).
+char(c,18779).
+char(p,18780).
+char(1,18781).
+char(9,18782).
+char(6,18783).
+char(7,18784).
+char(p,18785).
+char(7,18786).
+char(5,18787).
+char(9,18788).
+char(4,18789).
+char(c,18790).
+char(c,18791).
+char(m,18792).
+char(o,18793).
+char(o,18794).
+char(m,18795).
+char(o,18796).
+char(p,18797).
+char(o,18798).
+char(8,18799).
+char(4,18800).
+char(0,18801).
+char(c,18802).
+char(c,18803).
+char(c,18804).
+char(p,18805).
+char(o,18806).
+char(p,18807).
+char(9,18808).
+char(9,18809).
+char(2,18810).
+char(4,18811).
+char(c,18812).
+char(c,18813).
+char(c,18814).
+char(m,18815).
+char(2,18816).
+char(0,18817).
+char(6,18818).
+char(m,18819).
+char(8,18820).
+char(0,18821).
+char(1,18822).
+char(1,18823).
+char(m,18824).
+char(o,18825).
+char(7,18826).
+char(3,18827).
+char(8,18828).
+char(6,18829).
+char(c,18830).
+char(m,18831).
+char(o,18832).
+char(m,18833).
+char(o,18834).
+char(m,18835).
+char(4,18836).
+char(9,18837).
+char(2,18838).
+char(2,18839).
+char(c,18840).
+char(c,18841).
+char(p,18842).
+char(o,18843).
+char(p,18844).
+char(o,18845).
+char(4,18846).
+char(6,18847).
+char(3,18848).
+char(0,18849).
+char(c,18850).
+char(m,18851).
+char(o,18852).
+char(p,18853).
+char(6,18854).
+char(1,18855).
+char(2,18856).
+char(9,18857).
+char(p,18858).
+char(6,18859).
+char(8,18860).
+char(3,18861).
+char(3,18862).
+char(c,18863).
+char(m,18864).
+char(1,18865).
+char(2,18866).
+char(7,18867).
+char(6,18868).
+char(c,18869).
+char(m,18870).
+char(4,18871).
+char(2,18872).
+char(7,18873).
+char(7,18874).
+char(m,18875).
+char(o,18876).
+char(3,18877).
+char(8,18878).
+char(8,18879).
+char(8,18880).
+char(c,18881).
+char(c,18882).
+char(c,18883).
+char(p,18884).
+char(7,18885).
+char(0,18886).
+char(6,18887).
+char(8,18888).
+char(c,18889).
+char(m,18890).
+char(o,18891).
+char(p,18892).
+char(o,18893).
+char(m,18894).
+char(o,18895).
+char(p,18896).
+char(5,18897).
+char(1,18898).
+char(0,18899).
+char(7,18900).
+char(m,18901).
+char(9,18902).
+char(6,18903).
+char(8,18904).
+char(2,18905).
+char(m,18906).
+char(6,18907).
+char(2,18908).
+char(1,18909).
+char(6,18910).
+char(p,18911).
+char(o,18912).
+char(p,18913).
+char(8,18914).
+char(6,18915).
+char(7,18916).
+char(5,18917).
+char(m,18918).
+char(o,18919).
+char(p,18920).
+char(3,18921).
+char(6,18922).
+char(5,18923).
+char(6,18924).
+char(c,18925).
+char(c,18926).
+char(p,18927).
+char(8,18928).
+char(4,18929).
+char(5,18930).
+char(9,18931).
+char(c,18932).
+char(p,18933).
+char(o,18934).
+char(m,18935).
+char(5,18936).
+char(1,18937).
+char(8,18938).
+char(7,18939).
+char(m,18940).
+char(9,18941).
+char(4,18942).
+char(5,18943).
+char(c,18944).
+char(m,18945).
+char(o,18946).
+char(p,18947).
+char(o,18948).
+char(7,18949).
+char(7,18950).
+char(5,18951).
+char(6,18952).
+char(c,18953).
+char(m,18954).
+char(o,18955).
+char(p,18956).
+char(7,18957).
+char(0,18958).
+char(7,18959).
+char(9,18960).
+char(c,18961).
+char(c,18962).
+char(c,18963).
+char(m,18964).
+char(o,18965).
+char(m,18966).
+char(o,18967).
+char(m,18968).
+char(4,18969).
+char(5,18970).
+char(3,18971).
+char(6,18972).
+char(c,18973).
+char(c,18974).
+char(p,18975).
+char(7,18976).
+char(9,18977).
+char(3,18978).
+char(3,18979).
+char(p,18980).
+char(4,18981).
+char(4,18982).
+char(0,18983).
+char(3,18984).
+char(c,18985).
+char(c,18986).
+char(p,18987).
+char(5,18988).
+char(2,18989).
+char(9,18990).
+char(2,18991).
+char(m,18992).
+char(9,18993).
+char(9,18994).
+char(5,18995).
+char(4,18996).
+char(c,18997).
+char(c,18998).
+char(p,18999).
+char(o,19000).
+char(p,19001).
+char(8,19002).
+char(2,19003).
+char(9,19004).
+char(m,19005).
+char(7,19006).
+char(9,19007).
+char(1,19008).
+char(9,19009).
+char(c,19010).
+char(p,19011).
+char(o,19012).
+char(p,19013).
+char(1,19014).
+char(8,19015).
+char(0,19016).
+char(4,19017).
+char(c,19018).
+char(c,19019).
+char(c,19020).
+char(m,19021).
+char(7,19022).
+char(4,19023).
+char(0,19024).
+char(8,19025).
+char(p,19026).
+char(o,19027).
+char(9,19028).
+char(2,19029).
+char(7,19030).
+char(3,19031).
+char(c,19032).
+char(c,19033).
+char(c,19034).
+char(p,19035).
+char(o,19036).
+char(p,19037).
+char(7,19038).
+char(6,19039).
+char(9,19040).
+char(0,19041).
+char(c,19042).
+char(c,19043).
+char(c,19044).
+char(m,19045).
+char(1,19046).
+char(2,19047).
+char(6,19048).
+char(p,19049).
+char(o,19050).
+char(1,19051).
+char(7,19052).
+char(2,19053).
+char(0,19054).
+char(c,19055).
+char(m,19056).
+char(o,19057).
+char(o,19058).
+char(p,19059).
+char(3,19060).
+char(2,19061).
+char(0,19062).
+char(0,19063).
+char(c,19064).
+char(c,19065).
+char(c,19066).
+char(p,19067).
+char(o,19068).
+char(o,19069).
+char(p,19070).
+char(4,19071).
+char(7,19072).
+char(4,19073).
+char(8,19074).
+char(p,19075).
+char(8,19076).
+char(2,19077).
+char(2,19078).
+char(4,19079).
+char(c,19080).
+char(p,19081).
+char(4,19082).
+char(8,19083).
+char(0,19084).
+char(4,19085).
+char(c,19086).
+char(m,19087).
+char(o,19088).
+char(9,19089).
+char(0,19090).
+char(0,19091).
+char(1,19092).
+char(c,19093).
+char(p,19094).
+char(6,19095).
+char(9,19096).
+char(5,19097).
+char(8,19098).
+char(p,19099).
+char(6,19100).
+char(8,19101).
+char(5,19102).
+char(6,19103).
+char(c,19104).
+char(c,19105).
+char(c,19106).
+char(c,19107).
+char(c,19108).
+char(c,19109).
+char(c,19110).
+char(p,19111).
+char(o,19112).
+char(m,19113).
+char(o,19114).
+char(p,19115).
+char(5,19116).
+char(7,19117).
+char(0,19118).
+char(6,19119).
+char(p,19120).
+char(2,19121).
+char(8,19122).
+char(6,19123).
+char(0,19124).
+char(p,19125).
+char(o,19126).
+char(p,19127).
+char(o,19128).
+char(p,19129).
+char(o,19130).
+char(p,19131).
+char(o,19132).
+char(o,19133).
+char(m,19134).
+char(o,19135).
+char(p,19136).
+char(o,19137).
+char(p,19138).
+char(6,19139).
+char(5,19140).
+char(9,19141).
+char(5,19142).
+char(c,19143).
+char(p,19144).
+char(o,19145).
+char(o,19146).
+char(p,19147).
+char(8,19148).
+char(5,19149).
+char(4,19150).
+char(6,19151).
+char(m,19152).
+char(o,19153).
+char(m,19154).
+char(o,19155).
+char(m,19156).
+char(o,19157).
+char(o,19158).
+char(p,19159).
+char(o,19160).
+char(m,19161).
+char(o,19162).
+char(m,19163).
+char(o,19164).
+char(o,19165).
+char(m,19166).
+char(o,19167).
+char(m,19168).
+char(9,19169).
+char(0,19170).
+char(6,19171).
+char(8,19172).
+char(c,19173).
+char(c,19174).
+char(c,19175).
+char(c,19176).
+char(c,19177).
+char(p,19178).
+char(3,19179).
+char(6,19180).
+char(7,19181).
+char(9,19182).
+char(p,19183).
+char(o,19184).
+char(o,19185).
+char(1,19186).
+char(1,19187).
+char(1,19188).
+char(6,19189).
+char(p,19190).
+char(7,19191).
+char(6,19192).
+char(0,19193).
+char(5,19194).
+char(m,19195).
+char(o,19196).
+char(m,19197).
+char(o,19198).
+char(m,19199).
+char(2,19200).
+char(4,19201).
+char(1,19202).
+char(3,19203).
+char(c,19204).
+char(c,19205).
+char(p,19206).
+char(o,19207).
+char(p,19208).
+char(1,19209).
+char(1,19210).
+char(7,19211).
+char(9,19212).
+char(c,19213).
+char(m,19214).
+char(7,19215).
+char(3,19216).
+char(8,19217).
+char(6,19218).
+char(c,19219).
+char(c,19220).
+char(m,19221).
+char(o,19222).
+char(p,19223).
+char(5,19224).
+char(3,19225).
+char(1,19226).
+char(7,19227).
+char(p,19228).
+char(1,19229).
+char(6,19230).
+char(7,19231).
+char(9,19232).
+char(p,19233).
+char(8,19234).
+char(7,19235).
+char(9,19236).
+char(5,19237).
+char(c,19238).
+char(p,19239).
+char(1,19240).
+char(0,19241).
+char(4,19242).
+char(c,19243).
+char(p,19244).
+char(7,19245).
+char(7,19246).
+char(4,19247).
+char(5,19248).
+char(c,19249).
+char(m,19250).
+char(6,19251).
+char(3,19252).
+char(8,19253).
+char(6,19254).
+char(p,19255).
+char(o,19256).
+char(p,19257).
+char(o,19258).
+char(m,19259).
+char(o,19260).
+char(p,19261).
+char(o,19262).
+char(2,19263).
+char(4,19264).
+char(5,19265).
+char(2,19266).
+char(p,19267).
+char(5,19268).
+char(5,19269).
+char(2,19270).
+char(9,19271).
+char(c,19272).
+char(m,19273).
+char(o,19274).
+char(p,19275).
+char(o,19276).
+char(m,19277).
+char(5,19278).
+char(3,19279).
+char(3,19280).
+char(9,19281).
+char(p,19282).
+char(o,19283).
+char(1,19284).
+char(4,19285).
+char(3,19286).
+char(0,19287).
+char(c,19288).
+char(m,19289).
+char(6,19290).
+char(1,19291).
+char(5,19292).
+char(6,19293).
+char(m,19294).
+char(3,19295).
+char(1,19296).
+char(9,19297).
+char(7,19298).
+char(p,19299).
+char(6,19300).
+char(4,19301).
+char(2,19302).
+char(5,19303).
+char(m,19304).
+char(8,19305).
+char(9,19306).
+char(6,19307).
+char(c,19308).
+char(p,19309).
+char(5,19310).
+char(9,19311).
+char(8,19312).
+char(p,19313).
+char(o,19314).
+char(p,19315).
+char(o,19316).
+char(o,19317).
+char(p,19318).
+char(o,19319).
+char(m,19320).
+char(o,19321).
+char(p,19322).
+char(o,19323).
+char(p,19324).
+char(9,19325).
+char(5,19326).
+char(4,19327).
+char(0,19328).
+char(p,19329).
+char(7,19330).
+char(3,19331).
+char(9,19332).
+char(6,19333).
+char(p,19334).
+char(4,19335).
+char(7,19336).
+char(3,19337).
+char(8,19338).
+char(m,19339).
+char(o,19340).
+char(p,19341).
+char(o,19342).
+char(m,19343).
+char(o,19344).
+char(o,19345).
+char(7,19346).
+char(9,19347).
+char(1,19348).
+char(5,19349).
+char(m,19350).
+char(5,19351).
+char(7,19352).
+char(1,19353).
+char(6,19354).
+char(m,19355).
+char(1,19356).
+char(6,19357).
+char(5,19358).
+char(4,19359).
+char(m,19360).
+char(o,19361).
+char(4,19362).
+char(4,19363).
+char(5,19364).
+char(1,19365).
+char(c,19366).
+char(m,19367).
+char(o,19368).
+char(o,19369).
+char(p,19370).
+char(o,19371).
+char(o,19372).
+char(7,19373).
+char(5,19374).
+char(2,19375).
+char(7,19376).
+char(p,19377).
+char(o,19378).
+char(p,19379).
+char(4,19380).
+char(0,19381).
+char(8,19382).
+char(0,19383).
+char(c,19384).
+char(p,19385).
+char(o,19386).
+char(m,19387).
+char(5,19388).
+char(6,19389).
+char(4,19390).
+char(0,19391).
+char(m,19392).
+char(7,19393).
+char(5,19394).
+char(7,19395).
+char(7,19396).
+char(c,19397).
+char(m,19398).
+char(1,19399).
+char(6,19400).
+char(3,19401).
+char(0,19402).
+char(c,19403).
+char(m,19404).
+char(o,19405).
+char(p,19406).
+char(1,19407).
+char(9,19408).
+char(6,19409).
+char(7,19410).
+char(c,19411).
+char(p,19412).
+char(6,19413).
+char(9,19414).
+char(4,19415).
+char(2,19416).
+char(m,19417).
+char(8,19418).
+char(9,19419).
+char(7,19420).
+char(4,19421).
+char(c,19422).
+char(c,19423).
+char(m,19424).
+char(o,19425).
+char(o,19426).
+char(p,19427).
+char(5,19428).
+char(3,19429).
+char(8,19430).
+char(3,19431).
+char(m,19432).
+char(o,19433).
+char(o,19434).
+char(p,19435).
+char(6,19436).
+char(2,19437).
+char(5,19438).
+char(9,19439).
+char(c,19440).
+char(c,19441).
+char(c,19442).
+char(c,19443).
+char(m,19444).
+char(o,19445).
+char(p,19446).
+char(o,19447).
+char(p,19448).
+char(6,19449).
+char(8,19450).
+char(1,19451).
+char(2,19452).
+char(c,19453).
+char(c,19454).
+char(p,19455).
+char(o,19456).
+char(m,19457).
+char(3,19458).
+char(2,19459).
+char(7,19460).
+char(1,19461).
+char(c,19462).
+char(p,19463).
+char(o,19464).
+char(p,19465).
+char(o,19466).
+char(m,19467).
+char(o,19468).
+char(2,19469).
+char(7,19470).
+char(5,19471).
+char(9,19472).
+char(c,19473).
+char(p,19474).
+char(5,19475).
+char(9,19476).
+char(3,19477).
+char(4,19478).
+char(m,19479).
+char(o,19480).
+char(m,19481).
+char(o,19482).
+char(o,19483).
+char(p,19484).
+char(o,19485).
+char(p,19486).
+char(o,19487).
+char(o,19488).
+char(o,19489).
+char(5,19490).
+char(8,19491).
+char(7,19492).
+char(8,19493).
+char(c,19494).
+char(c,19495).
+char(c,19496).
+char(c,19497).
+char(p,19498).
+char(o,19499).
+char(o,19500).
+char(7,19501).
+char(1,19502).
+char(3,19503).
+char(6,19504).
+char(c,19505).
+char(p,19506).
+char(5,19507).
+char(1,19508).
+char(9,19509).
+char(4,19510).
+char(p,19511).
+char(o,19512).
+char(p,19513).
+char(o,19514).
+char(m,19515).
+char(4,19516).
+char(9,19517).
+char(7,19518).
+char(3,19519).
+char(c,19520).
+char(m,19521).
+char(1,19522).
+char(6,19523).
+char(5,19524).
+char(5,19525).
+char(p,19526).
+char(o,19527).
+char(m,19528).
+char(8,19529).
+char(7,19530).
+char(7,19531).
+char(6,19532).
+char(p,19533).
+char(9,19534).
+char(3,19535).
+char(0,19536).
+char(6,19537).
+char(c,19538).
+char(p,19539).
+char(o,19540).
+char(p,19541).
+char(2,19542).
+char(1,19543).
+char(1,19544).
+char(0,19545).
+char(c,19546).
+char(p,19547).
+char(o,19548).
+char(p,19549).
+char(o,19550).
+char(o,19551).
+char(o,19552).
+char(m,19553).
+char(5,19554).
+char(1,19555).
+char(7,19556).
+char(m,19557).
+char(2,19558).
+char(8,19559).
+char(4,19560).
+char(7,19561).
+char(m,19562).
+char(o,19563).
+char(o,19564).
+char(p,19565).
+char(o,19566).
+char(p,19567).
+char(o,19568).
+char(3,19569).
+char(8,19570).
+char(6,19571).
+char(6,19572).
+char(c,19573).
+char(m,19574).
+char(o,19575).
+char(m,19576).
+char(8,19577).
+char(7,19578).
+char(5,19579).
+char(0,19580).
+char(m,19581).
+char(5,19582).
+char(8,19583).
+char(0,19584).
+char(8,19585).
+char(p,19586).
+char(o,19587).
+char(o,19588).
+char(p,19589).
+char(o,19590).
+char(p,19591).
+char(o,19592).
+char(p,19593).
+char(2,19594).
+char(1,19595).
+char(5,19596).
+char(1,19597).
+char(m,19598).
+char(7,19599).
+char(6,19600).
+char(9,19601).
+char(c,19602).
+char(c,19603).
+char(c,19604).
+char(c,19605).
+char(c,19606).
+char(c,19607).
+char(c,19608).
+char(c,19609).
+char(c,19610).
+char(m,19611).
+char(3,19612).
+char(8,19613).
+char(0,19614).
+char(8,19615).
+char(c,19616).
+char(c,19617).
+char(m,19618).
+char(8,19619).
+char(9,19620).
+char(0,19621).
+char(0,19622).
+char(m,19623).
+char(o,19624).
+char(p,19625).
+char(1,19626).
+char(0,19627).
+char(2,19628).
+char(5,19629).
+char(c,19630).
+char(c,19631).
+char(p,19632).
+char(o,19633).
+char(m,19634).
+char(4,19635).
+char(0,19636).
+char(4,19637).
+char(1,19638).
+char(p,19639).
+char(o,19640).
+char(p,19641).
+char(7,19642).
+char(1,19643).
+char(6,19644).
+char(1,19645).
+char(c,19646).
+char(c,19647).
+char(c,19648).
+char(c,19649).
+char(c,19650).
+char(c,19651).
+char(c,19652).
+char(p,19653).
+char(4,19654).
+char(5,19655).
+char(8,19656).
+char(7,19657).
+char(m,19658).
+char(7,19659).
+char(4,19660).
+char(8,19661).
+char(6,19662).
+char(m,19663).
+char(8,19664).
+char(2,19665).
+char(7,19666).
+char(4,19667).
+char(p,19668).
+char(o,19669).
+char(5,19670).
+char(3,19671).
+char(9,19672).
+char(2,19673).
+char(m,19674).
+char(8,19675).
+char(7,19676).
+char(3,19677).
+char(4,19678).
+char(m,19679).
+char(5,19680).
+char(3,19681).
+char(6,19682).
+char(7,19683).
+char(c,19684).
+char(c,19685).
+char(c,19686).
+char(m,19687).
+char(o,19688).
+char(p,19689).
+char(o,19690).
+char(m,19691).
+char(9,19692).
+char(7,19693).
+char(3,19694).
+char(7,19695).
+char(c,19696).
+char(m,19697).
+char(5,19698).
+char(1,19699).
+char(0,19700).
+char(9,19701).
+char(c,19702).
+char(c,19703).
+char(m,19704).
+char(o,19705).
+char(m,19706).
+char(o,19707).
+char(p,19708).
+char(2,19709).
+char(0,19710).
+char(7,19711).
+char(7,19712).
+char(c,19713).
+char(m,19714).
+char(1,19715).
+char(8,19716).
+char(0,19717).
+char(1,19718).
+char(m,19719).
+char(4,19720).
+char(2,19721).
+char(0,19722).
+char(8,19723).
+char(c,19724).
+char(p,19725).
+char(o,19726).
+char(3,19727).
+char(4,19728).
+char(1,19729).
+char(4,19730).
+char(c,19731).
+char(m,19732).
+char(o,19733).
+char(4,19734).
+char(9,19735).
+char(5,19736).
+char(1,19737).
+char(p,19738).
+char(7,19739).
+char(6,19740).
+char(6,19741).
+char(9,19742).
+char(m,19743).
+char(8,19744).
+char(4,19745).
+char(1,19746).
+char(p,19747).
+char(o,19748).
+char(p,19749).
+char(o,19750).
+char(o,19751).
+char(m,19752).
+char(3,19753).
+char(5,19754).
+char(1,19755).
+char(1,19756).
+char(m,19757).
+char(o,19758).
+char(p,19759).
+char(7,19760).
+char(2,19761).
+char(3,19762).
+char(2,19763).
+char(c,19764).
+char(m,19765).
+char(o,19766).
+char(p,19767).
+char(o,19768).
+char(p,19769).
+char(o,19770).
+char(o,19771).
+char(m,19772).
+char(o,19773).
+char(p,19774).
+char(o,19775).
+char(p,19776).
+char(8,19777).
+char(8,19778).
+char(2,19779).
+char(0,19780).
+char(c,19781).
+char(c,19782).
+char(m,19783).
+char(o,19784).
+char(p,19785).
+char(4,19786).
+char(1,19787).
+char(8,19788).
+char(3,19789).
+char(c,19790).
+char(c,19791).
+char(c,19792).
+char(m,19793).
+char(7,19794).
+char(8,19795).
+char(9,19796).
+char(0,19797).
+char(p,19798).
+char(o,19799).
+char(o,19800).
+char(m,19801).
+char(o,19802).
+char(o,19803).
+char(p,19804).
+char(6,19805).
+char(5,19806).
+char(8,19807).
+char(5,19808).
+char(m,19809).
+char(o,19810).
+char(p,19811).
+char(1,19812).
+char(0,19813).
+char(4,19814).
+char(2,19815).
+char(p,19816).
+char(3,19817).
+char(3,19818).
+char(4,19819).
+char(0,19820).
+char(m,19821).
+char(o,19822).
+char(p,19823).
+char(o,19824).
+char(p,19825).
+char(5,19826).
+char(2,19827).
+char(3,19828).
+char(1,19829).
+char(m,19830).
+char(8,19831).
+char(1,19832).
+char(8,19833).
+char(1,19834).
+char(m,19835).
+char(7,19836).
+char(8,19837).
+char(5,19838).
+char(7,19839).
+char(c,19840).
+char(c,19841).
+char(p,19842).
+char(3,19843).
+char(6,19844).
+char(1,19845).
+char(0,19846).
+char(c,19847).
+char(p,19848).
+char(o,19849).
+char(p,19850).
+char(o,19851).
+char(m,19852).
+char(o,19853).
+char(m,19854).
+char(3,19855).
+char(2,19856).
+char(6,19857).
+char(3,19858).
+char(c,19859).
+char(p,19860).
+char(7,19861).
+char(9,19862).
+char(8,19863).
+char(3,19864).
+char(p,19865).
+char(5,19866).
+char(8,19867).
+char(4,19868).
+char(3,19869).
+char(c,19870).
+char(c,19871).
+char(p,19872).
+char(7,19873).
+char(4,19874).
+char(4,19875).
+char(6,19876).
+char(c,19877).
+char(p,19878).
+char(o,19879).
+char(8,19880).
+char(0,19881).
+char(7,19882).
+char(6,19883).
+char(p,19884).
+char(3,19885).
+char(0,19886).
+char(6,19887).
+char(8,19888).
+char(m,19889).
+char(o,19890).
+char(m,19891).
+char(o,19892).
+char(p,19893).
+char(o,19894).
+char(o,19895).
+char(7,19896).
+char(9,19897).
+char(0,19898).
+char(4,19899).
+char(p,19900).
+char(2,19901).
+char(4,19902).
+char(1,19903).
+char(6,19904).
+char(p,19905).
+char(o,19906).
+char(m,19907).
+char(o,19908).
+char(m,19909).
+char(o,19910).
+char(m,19911).
+char(o,19912).
+char(p,19913).
+char(o,19914).
+char(o,19915).
+char(p,19916).
+char(o,19917).
+char(p,19918).
+char(3,19919).
+char(8,19920).
+char(9,19921).
+char(5,19922).
+char(c,19923).
+char(c,19924).
+char(m,19925).
+char(o,19926).
+char(m,19927).
+char(o,19928).
+char(7,19929).
+char(9,19930).
+char(2,19931).
+char(0,19932).
+char(p,19933).
+char(2,19934).
+char(4,19935).
+char(5,19936).
+char(6,19937).
+char(m,19938).
+char(1,19939).
+char(9,19940).
+char(0,19941).
+char(8,19942).
+char(c,19943).
+char(c,19944).
+char(m,19945).
+char(6,19946).
+char(4,19947).
+char(4,19948).
+char(2,19949).
+char(c,19950).
+char(m,19951).
+char(o,19952).
+char(m,19953).
+char(6,19954).
+char(1,19955).
+char(8,19956).
+char(1,19957).
+char(c,19958).
+char(p,19959).
+char(o,19960).
+char(6,19961).
+char(9,19962).
+char(7,19963).
+char(6,19964).
+char(c,19965).
+char(c,19966).
+char(m,19967).
+char(9,19968).
+char(8,19969).
+char(6,19970).
+char(2,19971).
+char(c,19972).
+char(c,19973).
+char(m,19974).
+char(9,19975).
+char(7,19976).
+char(3,19977).
+char(2,19978).
+char(m,19979).
+char(8,19980).
+char(7,19981).
+char(7,19982).
+char(6,19983).
+char(c,19984).
+char(p,19985).
+char(o,19986).
+char(m,19987).
+char(2,19988).
+char(5,19989).
+char(2,19990).
+char(2,19991).
+char(c,19992).
+char(c,19993).
+char(c,19994).
+char(p,19995).
+char(6,19996).
+char(2,19997).
+char(5,19998).
+char(8,19999).
+char(c,20000).
+char(c,20001).
+char(m,20002).
+char(5,20003).
+char(7,20004).
+char(6,20005).
+char(5,20006).
+char(m,20007).
+char(o,20008).
+char(p,20009).
+char(o,20010).
+char(p,20011).
+char(o,20012).
+char(m,20013).
+char(7,20014).
+char(2,20015).
+char(0,20016).
+char(1,20017).
+char(c,20018).
+char(p,20019).
+char(o,20020).
+char(8,20021).
+char(5,20022).
+char(7,20023).
+char(8,20024).
+char(m,20025).
+char(o,20026).
+char(m,20027).
+char(o,20028).
+char(p,20029).
+char(2,20030).
+char(9,20031).
+char(3,20032).
+char(0,20033).
+char(c,20034).
+char(p,20035).
+char(o,20036).
+char(p,20037).
+char(1,20038).
+char(1,20039).
+char(2,20040).
+char(8,20041).
+char(m,20042).
+char(4,20043).
+char(7,20044).
+char(8,20045).
+char(8,20046).
+char(c,20047).
+char(p,20048).
+char(o,20049).
+char(7,20050).
+char(4,20051).
+char(3,20052).
+char(2,20053).
+char(p,20054).
+char(4,20055).
+char(7,20056).
+char(1,20057).
+char(c,20058).
+char(m,20059).
+char(2,20060).
+char(8,20061).
+char(3,20062).
+char(8,20063).
+char(m,20064).
+char(5,20065).
+char(1,20066).
+char(6,20067).
+char(5,20068).
+char(c,20069).
+char(m,20070).
+char(o,20071).
+char(p,20072).
+char(o,20073).
+char(p,20074).
+char(7,20075).
+char(2,20076).
+char(5,20077).
+char(p,20078).
+char(6,20079).
+char(6,20080).
+char(3,20081).
+char(c,20082).
+char(c,20083).
+char(c,20084).
+char(c,20085).
+char(c,20086).
+char(m,20087).
+char(2,20088).
+char(6,20089).
+char(4,20090).
+char(5,20091).
+char(m,20092).
+char(2,20093).
+char(2,20094).
+char(7,20095).
+char(6,20096).
+char(c,20097).
+char(c,20098).
+char(c,20099).
+char(c,20100).
+char(m,20101).
+char(8,20102).
+char(9,20103).
+char(5,20104).
+char(c,20105).
+char(c,20106).
+char(m,20107).
+char(o,20108).
+char(p,20109).
+char(o,20110).
+char(p,20111).
+char(9,20112).
+char(2,20113).
+char(0,20114).
+char(9,20115).
+char(c,20116).
+char(m,20117).
+char(o,20118).
+char(8,20119).
+char(7,20120).
+char(0,20121).
+char(0,20122).
+char(c,20123).
+char(p,20124).
+char(8,20125).
+char(1,20126).
+char(7,20127).
+char(3,20128).
+char(m,20129).
+char(8,20130).
+char(2,20131).
+char(2,20132).
+char(9,20133).
+char(p,20134).
+char(o,20135).
+char(9,20136).
+char(0,20137).
+char(7,20138).
+char(2,20139).
+char(c,20140).
+char(c,20141).
+char(p,20142).
+char(o,20143).
+char(m,20144).
+char(o,20145).
+char(p,20146).
+char(4,20147).
+char(9,20148).
+char(7,20149).
+char(7,20150).
+char(c,20151).
+char(c,20152).
+char(c,20153).
+char(c,20154).
+char(c,20155).
+char(p,20156).
+char(9,20157).
+char(2,20158).
+char(5,20159).
+char(3,20160).
+char(p,20161).
+char(1,20162).
+char(3,20163).
+char(7,20164).
+char(8,20165).
+char(c,20166).
+char(c,20167).
+char(p,20168).
+char(2,20169).
+char(9,20170).
+char(5,20171).
+char(5,20172).
+char(p,20173).
+char(o,20174).
+char(m,20175).
+char(o,20176).
+char(p,20177).
+char(5,20178).
+char(9,20179).
+char(2,20180).
+char(7,20181).
+char(p,20182).
+char(9,20183).
+char(6,20184).
+char(8,20185).
+char(3,20186).
+char(m,20187).
+char(o,20188).
+char(m,20189).
+char(2,20190).
+char(1,20191).
+char(4,20192).
+char(3,20193).
+char(c,20194).
+char(p,20195).
+char(o,20196).
+char(p,20197).
+char(o,20198).
+char(p,20199).
+char(8,20200).
+char(5,20201).
+char(1,20202).
+char(c,20203).
+char(c,20204).
+char(c,20205).
+char(p,20206).
+char(5,20207).
+char(4,20208).
+char(7,20209).
+char(2,20210).
+char(c,20211).
+char(m,20212).
+char(3,20213).
+char(2,20214).
+char(4,20215).
+char(2,20216).
+char(c,20217).
+char(m,20218).
+char(9,20219).
+char(9,20220).
+char(3,20221).
+char(9,20222).
+char(m,20223).
+char(o,20224).
+char(p,20225).
+char(o,20226).
+char(m,20227).
+char(o,20228).
+char(o,20229).
+char(m,20230).
+char(7,20231).
+char(6,20232).
+char(2,20233).
+char(9,20234).
+char(m,20235).
+char(o,20236).
+char(p,20237).
+char(5,20238).
+char(2,20239).
+char(5,20240).
+char(p,20241).
+char(5,20242).
+char(3,20243).
+char(7,20244).
+char(7,20245).
+char(c,20246).
+char(c,20247).
+char(c,20248).
+char(p,20249).
+char(o,20250).
+char(6,20251).
+char(9,20252).
+char(9,20253).
+char(2,20254).
+char(p,20255).
+char(o,20256).
+char(m,20257).
+char(8,20258).
+char(7,20259).
+char(0,20260).
+char(5,20261).
+char(c,20262).
+char(c,20263).
+char(c,20264).
+char(c,20265).
+char(c,20266).
+char(p,20267).
+char(5,20268).
+char(9,20269).
+char(0,20270).
+char(9,20271).
+char(m,20272).
+char(9,20273).
+char(9,20274).
+char(5,20275).
+char(8,20276).
+char(p,20277).
+char(o,20278).
+char(m,20279).
+char(o,20280).
+char(m,20281).
+char(o,20282).
+char(2,20283).
+char(7,20284).
+char(c,20285).
+char(c,20286).
+char(c,20287).
+char(c,20288).
+char(p,20289).
+char(o,20290).
+char(m,20291).
+char(o,20292).
+char(o,20293).
+char(m,20294).
+char(o,20295).
+char(p,20296).
+char(o,20297).
+char(o,20298).
+char(p,20299).
+char(1,20300).
+char(1,20301).
+char(3,20302).
+char(5,20303).
+char(p,20304).
+char(o,20305).
+char(o,20306).
+char(p,20307).
+char(8,20308).
+char(5,20309).
+char(1,20310).
+char(2,20311).
+char(p,20312).
+char(3,20313).
+char(6,20314).
+char(2,20315).
+char(2,20316).
+char(c,20317).
+char(p,20318).
+char(o,20319).
+char(m,20320).
+char(2,20321).
+char(3,20322).
+char(7,20323).
+char(0,20324).
+char(p,20325).
+char(o,20326).
+char(o,20327).
+char(4,20328).
+char(7,20329).
+char(7,20330).
+char(2,20331).
+char(c,20332).
+char(p,20333).
+char(6,20334).
+char(9,20335).
+char(2,20336).
+char(8,20337).
+char(c,20338).
+char(m,20339).
+char(o,20340).
+char(m,20341).
+char(7,20342).
+char(3,20343).
+char(8,20344).
+char(8,20345).
+char(c,20346).
+char(c,20347).
+char(c,20348).
+char(c,20349).
+char(c,20350).
+char(m,20351).
+char(o,20352).
+char(p,20353).
+char(6,20354).
+char(3,20355).
+char(3,20356).
+char(p,20357).
+char(9,20358).
+char(6,20359).
+char(6,20360).
+char(7,20361).
+char(m,20362).
+char(o,20363).
+char(p,20364).
+char(6,20365).
+char(6,20366).
+char(2,20367).
+char(0,20368).
+char(p,20369).
+char(o,20370).
+char(p,20371).
+char(4,20372).
+char(6,20373).
+char(7,20374).
+char(2,20375).
+char(p,20376).
+char(o,20377).
+char(o,20378).
+char(m,20379).
+char(o,20380).
+char(2,20381).
+char(0,20382).
+char(3,20383).
+char(7,20384).
+char(p,20385).
+char(o,20386).
+char(m,20387).
+char(o,20388).
+char(1,20389).
+char(6,20390).
+char(8,20391).
+char(2,20392).
+char(m,20393).
+char(7,20394).
+char(1,20395).
+char(3,20396).
+char(7,20397).
+char(c,20398).
+char(m,20399).
+char(o,20400).
+char(m,20401).
+char(1,20402).
+char(5,20403).
+char(1,20404).
+char(5,20405).
+char(c,20406).
+char(c,20407).
+char(p,20408).
+char(o,20409).
+char(p,20410).
+char(o,20411).
+char(m,20412).
+char(4,20413).
+char(0,20414).
+char(7,20415).
+char(8,20416).
+char(p,20417).
+char(o,20418).
+char(o,20419).
+char(m,20420).
+char(o,20421).
+char(p,20422).
+char(8,20423).
+char(1,20424).
+char(3,20425).
+char(4,20426).
+char(m,20427).
+char(5,20428).
+char(3,20429).
+char(5,20430).
+char(6,20431).
+char(m,20432).
+char(7,20433).
+char(5,20434).
+char(4,20435).
+char(8,20436).
+char(m,20437).
+char(o,20438).
+char(m,20439).
+char(2,20440).
+char(4,20441).
+char(5,20442).
+char(2,20443).
+char(c,20444).
+char(c,20445).
+char(m,20446).
+char(7,20447).
+char(3,20448).
+char(9,20449).
+char(6,20450).
+char(c,20451).
+char(p,20452).
+char(9,20453).
+char(5,20454).
+char(1,20455).
+char(8,20456).
+char(p,20457).
+char(o,20458).
+char(o,20459).
+char(p,20460).
+char(o,20461).
+char(5,20462).
+char(7,20463).
+char(3,20464).
+char(4,20465).
+char(c,20466).
+char(p,20467).
+char(o,20468).
+char(6,20469).
+char(7,20470).
+char(7,20471).
+char(9,20472).
+char(m,20473).
+char(o,20474).
+char(m,20475).
+char(7,20476).
+char(8,20477).
+char(8,20478).
+char(0,20479).
+char(p,20480).
+char(9,20481).
+char(0,20482).
+char(4,20483).
+char(8,20484).
+char(p,20485).
+char(3,20486).
+char(1,20487).
+char(4,20488).
+char(c,20489).
+char(m,20490).
+char(8,20491).
+char(4,20492).
+char(9,20493).
+char(p,20494).
+char(5,20495).
+char(3,20496).
+char(1,20497).
+char(0,20498).
+char(c,20499).
+char(p,20500).
+char(4,20501).
+char(8,20502).
+char(8,20503).
+char(2,20504).
+char(c,20505).
+char(c,20506).
+char(c,20507).
+char(c,20508).
+char(c,20509).
+char(m,20510).
+char(o,20511).
+char(4,20512).
+char(5,20513).
+char(7,20514).
+char(3,20515).
+char(p,20516).
+char(o,20517).
+char(p,20518).
+char(8,20519).
+char(7,20520).
+char(2,20521).
+char(3,20522).
+char(c,20523).
+char(c,20524).
+char(c,20525).
+char(m,20526).
+char(8,20527).
+char(8,20528).
+char(6,20529).
+char(2,20530).
+char(m,20531).
+char(3,20532).
+char(2,20533).
+char(8,20534).
+char(4,20535).
+char(p,20536).
+char(o,20537).
+char(o,20538).
+char(m,20539).
+char(4,20540).
+char(3,20541).
+char(8,20542).
+char(1,20543).
+char(c,20544).
+char(p,20545).
+char(7,20546).
+char(5,20547).
+char(1,20548).
+char(0,20549).
+char(m,20550).
+char(8,20551).
+char(6,20552).
+char(3,20553).
+char(c,20554).
+char(c,20555).
+char(c,20556).
+char(p,20557).
+char(4,20558).
+char(5,20559).
+char(7,20560).
+char(9,20561).
+char(p,20562).
+char(3,20563).
+char(1,20564).
+char(8,20565).
+char(5,20566).
+char(c,20567).
+char(m,20568).
+char(o,20569).
+char(m,20570).
+char(6,20571).
+char(5,20572).
+char(1,20573).
+char(1,20574).
+char(c,20575).
+char(c,20576).
+char(p,20577).
+char(o,20578).
+char(m,20579).
+char(o,20580).
+char(p,20581).
+char(o,20582).
+char(m,20583).
+char(1,20584).
+char(9,20585).
+char(9,20586).
+char(8,20587).
+char(p,20588).
+char(8,20589).
+char(2,20590).
+char(0,20591).
+char(3,20592).
+char(c,20593).
+char(p,20594).
+char(4,20595).
+char(3,20596).
+char(6,20597).
+char(4,20598).
+char(c,20599).
+char(c,20600).
+char(c,20601).
+char(c,20602).
+char(p,20603).
+char(3,20604).
+char(4,20605).
+char(8,20606).
+char(9,20607).
+char(c,20608).
+char(c,20609).
+char(m,20610).
+char(3,20611).
+char(3,20612).
+char(9,20613).
+char(4,20614).
+char(p,20615).
+char(o,20616).
+char(m,20617).
+char(o,20618).
+char(p,20619).
+char(o,20620).
+char(m,20621).
+char(o,20622).
+char(p,20623).
+char(7,20624).
+char(2,20625).
+char(7,20626).
+char(9,20627).
+char(c,20628).
+char(c,20629).
+char(p,20630).
+char(o,20631).
+char(o,20632).
+char(o,20633).
+char(7,20634).
+char(4,20635).
+char(0,20636).
+char(7,20637).
+char(m,20638).
+char(o,20639).
+char(o,20640).
+char(p,20641).
+char(o,20642).
+char(o,20643).
+char(p,20644).
+char(7,20645).
+char(0,20646).
+char(4,20647).
+char(9,20648).
+char(c,20649).
+char(p,20650).
+char(o,20651).
+char(m,20652).
+char(o,20653).
+char(9,20654).
+char(7,20655).
+char(0,20656).
+char(3,20657).
+char(c,20658).
+char(c,20659).
+char(m,20660).
+char(o,20661).
+char(p,20662).
+char(o,20663).
+char(p,20664).
+char(5,20665).
+char(3,20666).
+char(8,20667).
+char(0,20668).
+char(c,20669).
+char(c,20670).
+char(p,20671).
+char(1,20672).
+char(8,20673).
+char(6,20674).
+char(8,20675).
+char(p,20676).
+char(o,20677).
+char(p,20678).
+char(o,20679).
+char(m,20680).
+char(4,20681).
+char(7,20682).
+char(8,20683).
+char(3,20684).
+char(c,20685).
+char(c,20686).
+char(m,20687).
+char(o,20688).
+char(o,20689).
+char(m,20690).
+char(o,20691).
+char(o,20692).
+char(5,20693).
+char(5,20694).
+char(5,20695).
+char(8,20696).
+char(p,20697).
+char(7,20698).
+char(2,20699).
+char(2,20700).
+char(7,20701).
+char(p,20702).
+char(1,20703).
+char(6,20704).
+char(9,20705).
+char(0,20706).
+char(m,20707).
+char(o,20708).
+char(o,20709).
+char(m,20710).
+char(o,20711).
+char(m,20712).
+char(o,20713).
+char(m,20714).
+char(6,20715).
+char(8,20716).
+char(0,20717).
+char(6,20718).
+char(c,20719).
+char(c,20720).
+char(c,20721).
+char(c,20722).
+char(c,20723).
+char(p,20724).
+char(7,20725).
+char(4,20726).
+char(8,20727).
+char(c,20728).
+char(p,20729).
+char(9,20730).
+char(9,20731).
+char(2,20732).
+char(8,20733).
+char(p,20734).
+char(5,20735).
+char(8,20736).
+char(3,20737).
+char(p,20738).
+char(6,20739).
+char(8,20740).
+char(3,20741).
+char(7,20742).
+char(p,20743).
+char(o,20744).
+char(p,20745).
+char(o,20746).
+char(m,20747).
+char(7,20748).
+char(8,20749).
+char(3,20750).
+char(1,20751).
+char(m,20752).
+char(1,20753).
+char(0,20754).
+char(4,20755).
+char(4,20756).
+char(c,20757).
+char(c,20758).
+char(m,20759).
+char(2,20760).
+char(1,20761).
+char(1,20762).
+char(9,20763).
+char(c,20764).
+char(m,20765).
+char(o,20766).
+char(m,20767).
+char(o,20768).
+char(m,20769).
+char(9,20770).
+char(8,20771).
+char(4,20772).
+char(5,20773).
+char(m,20774).
+char(o,20775).
+char(p,20776).
+char(7,20777).
+char(3,20778).
+char(2,20779).
+char(7,20780).
+char(c,20781).
+char(c,20782).
+char(c,20783).
+char(p,20784).
+char(6,20785).
+char(1,20786).
+char(5,20787).
+char(3,20788).
+char(m,20789).
+char(2,20790).
+char(0,20791).
+char(7,20792).
+char(2,20793).
+char(m,20794).
+char(o,20795).
+char(m,20796).
+char(4,20797).
+char(4,20798).
+char(8,20799).
+char(1,20800).
+char(c,20801).
+char(m,20802).
+char(9,20803).
+char(8,20804).
+char(8,20805).
+char(4,20806).
+char(c,20807).
+char(p,20808).
+char(o,20809).
+char(p,20810).
+char(6,20811).
+char(2,20812).
+char(8,20813).
+char(m,20814).
+char(o,20815).
+char(o,20816).
+char(m,20817).
+char(o,20818).
+char(p,20819).
+char(9,20820).
+char(2,20821).
+char(3,20822).
+char(7,20823).
+char(m,20824).
+char(o,20825).
+char(p,20826).
+char(o,20827).
+char(m,20828).
+char(9,20829).
+char(4,20830).
+char(3,20831).
+char(8,20832).
+char(p,20833).
+char(7,20834).
+char(8,20835).
+char(3,20836).
+char(0,20837).
+char(c,20838).
+char(m,20839).
+char(7,20840).
+char(4,20841).
+char(4,20842).
+char(6,20843).
+char(m,20844).
+char(7,20845).
+char(2,20846).
+char(6,20847).
+char(0,20848).
+char(c,20849).
+char(m,20850).
+char(o,20851).
+char(p,20852).
+char(o,20853).
+char(o,20854).
+char(o,20855).
+char(m,20856).
+char(8,20857).
+char(1,20858).
+char(2,20859).
+char(7,20860).
+char(c,20861).
+char(c,20862).
+char(m,20863).
+char(1,20864).
+char(2,20865).
+char(2,20866).
+char(5,20867).
+char(p,20868).
+char(o,20869).
+char(o,20870).
+char(p,20871).
+char(o,20872).
+char(m,20873).
+char(3,20874).
+char(8,20875).
+char(2,20876).
+char(4,20877).
+char(c,20878).
+char(c,20879).
+char(p,20880).
+char(o,20881).
+char(o,20882).
+char(m,20883).
+char(o,20884).
+char(9,20885).
+char(0,20886).
+char(3,20887).
+char(3,20888).
+char(c,20889).
+char(p,20890).
+char(4,20891).
+char(3,20892).
+char(2,20893).
+char(4,20894).
+char(c,20895).
+char(p,20896).
+char(o,20897).
+char(m,20898).
+char(o,20899).
+char(p,20900).
+char(o,20901).
+char(p,20902).
+char(o,20903).
+char(m,20904).
+char(o,20905).
+char(p,20906).
+char(6,20907).
+char(7,20908).
+char(8,20909).
+char(6,20910).
+char(p,20911).
+char(o,20912).
+char(7,20913).
+char(8,20914).
+char(3,20915).
+char(6,20916).
+char(c,20917).
+char(c,20918).
+char(c,20919).
+char(p,20920).
+char(o,20921).
+char(p,20922).
+char(1,20923).
+char(8,20924).
+char(2,20925).
+char(8,20926).
+char(c,20927).
+char(c,20928).
+char(p,20929).
+char(9,20930).
+char(9,20931).
+char(8,20932).
+char(6,20933).
+char(p,20934).
+char(o,20935).
+char(m,20936).
+char(2,20937).
+char(0,20938).
+char(6,20939).
+char(5,20940).
+char(c,20941).
+char(c,20942).
+char(c,20943).
+char(p,20944).
+char(o,20945).
+char(m,20946).
+char(o,20947).
+char(m,20948).
+char(5,20949).
+char(1,20950).
+char(2,20951).
+char(1,20952).
+char(p,20953).
+char(o,20954).
+char(p,20955).
+char(1,20956).
+char(3,20957).
+char(4,20958).
+char(0,20959).
+char(p,20960).
+char(6,20961).
+char(7,20962).
+char(6,20963).
+char(8,20964).
+char(c,20965).
+char(c,20966).
+char(p,20967).
+char(8,20968).
+char(3,20969).
+char(9,20970).
+char(5,20971).
+char(p,20972).
+char(8,20973).
+char(3,20974).
+char(6,20975).
+char(7,20976).
+char(m,20977).
+char(8,20978).
+char(7,20979).
+char(6,20980).
+char(c,20981).
+char(c,20982).
+char(m,20983).
+char(7,20984).
+char(9,20985).
+char(1,20986).
+char(9,20987).
+char(m,20988).
+char(o,20989).
+char(p,20990).
+char(o,20991).
+char(o,20992).
+char(p,20993).
+char(5,20994).
+char(3,20995).
+char(8,20996).
+char(0,20997).
+char(c,20998).
+char(c,20999).
+char(m,21000).
+char(5,21001).
+char(8,21002).
+char(3,21003).
+char(c,21004).
+char(c,21005).
+char(c,21006).
+char(c,21007).
+char(c,21008).
+char(c,21009).
+char(c,21010).
+char(c,21011).
+char(c,21012).
+char(c,21013).
+char(p,21014).
+char(o,21015).
+char(m,21016).
+char(5,21017).
+char(3,21018).
+char(4,21019).
+char(m,21020).
+char(o,21021).
+char(m,21022).
+char(6,21023).
+char(9,21024).
+char(2,21025).
+char(c,21026).
+char(m,21027).
+char(o,21028).
+char(o,21029).
+char(p,21030).
+char(o,21031).
+char(p,21032).
+char(o,21033).
+char(2,21034).
+char(5,21035).
+char(0,21036).
+char(3,21037).
+char(m,21038).
+char(o,21039).
+char(o,21040).
+char(7,21041).
+char(3,21042).
+char(4,21043).
+char(8,21044).
+char(m,21045).
+char(o,21046).
+char(8,21047).
+char(4,21048).
+char(7,21049).
+char(2,21050).
+char(p,21051).
+char(9,21052).
+char(3,21053).
+char(0,21054).
+char(8,21055).
+char(c,21056).
+char(m,21057).
+char(o,21058).
+char(p,21059).
+char(o,21060).
+char(m,21061).
+char(o,21062).
+char(m,21063).
+char(o,21064).
+char(p,21065).
+char(o,21066).
+char(m,21067).
+char(o,21068).
+char(p,21069).
+char(2,21070).
+char(9,21071).
+char(8,21072).
+char(c,21073).
+char(c,21074).
+char(c,21075).
+char(c,21076).
+char(m,21077).
+char(o,21078).
+char(m,21079).
+char(2,21080).
+char(7,21081).
+char(2,21082).
+char(9,21083).
+char(c,21084).
+char(c,21085).
+char(p,21086).
+char(8,21087).
+char(8,21088).
+char(0,21089).
+char(1,21090).
+char(c,21091).
+char(p,21092).
+char(2,21093).
+char(4,21094).
+char(2,21095).
+char(1,21096).
+char(c,21097).
+char(c,21098).
+char(c,21099).
+char(c,21100).
+char(c,21101).
+char(c,21102).
+char(c,21103).
+char(p,21104).
+char(6,21105).
+char(9,21106).
+char(c,21107).
+char(c,21108).
+char(p,21109).
+char(o,21110).
+char(p,21111).
+char(7,21112).
+char(9,21113).
+char(9,21114).
+char(2,21115).
+char(c,21116).
+char(p,21117).
+char(o,21118).
+char(m,21119).
+char(o,21120).
+char(8,21121).
+char(2,21122).
+char(1,21123).
+char(9,21124).
+char(c,21125).
+char(m,21126).
+char(o,21127).
+char(m,21128).
+char(o,21129).
+char(9,21130).
+char(1,21131).
+char(9,21132).
+char(0,21133).
+char(p,21134).
+char(o,21135).
+char(p,21136).
+char(9,21137).
+char(6,21138).
+char(3,21139).
+char(0,21140).
+char(c,21141).
+char(c,21142).
+char(m,21143).
+char(3,21144).
+char(4,21145).
+char(2,21146).
+char(5,21147).
+char(c,21148).
+char(p,21149).
+char(o,21150).
+char(o,21151).
+char(m,21152).
+char(2,21153).
+char(5,21154).
+char(6,21155).
+char(9,21156).
+char(m,21157).
+char(3,21158).
+char(2,21159).
+char(8,21160).
+char(3,21161).
+char(c,21162).
+char(m,21163).
+char(5,21164).
+char(5,21165).
+char(0,21166).
+char(1,21167).
+char(c,21168).
+char(c,21169).
+char(c,21170).
+char(c,21171).
+char(c,21172).
+char(c,21173).
+char(c,21174).
+char(m,21175).
+char(1,21176).
+char(4,21177).
+char(8,21178).
+char(8,21179).
+char(c,21180).
+char(c,21181).
+char(p,21182).
+char(4,21183).
+char(9,21184).
+char(6,21185).
+char(6,21186).
+char(p,21187).
+char(o,21188).
+char(p,21189).
+char(3,21190).
+char(6,21191).
+char(0,21192).
+char(7,21193).
+char(p,21194).
+char(8,21195).
+char(6,21196).
+char(9,21197).
+char(1,21198).
+char(c,21199).
+char(c,21200).
+char(p,21201).
+char(4,21202).
+char(2,21203).
+char(0,21204).
+char(9,21205).
+char(c,21206).
+char(p,21207).
+char(7,21208).
+char(3,21209).
+char(9,21210).
+char(8,21211).
+char(c,21212).
+char(c,21213).
+char(c,21214).
+char(c,21215).
+char(p,21216).
+char(7,21217).
+char(2,21218).
+char(3,21219).
+char(8,21220).
+char(c,21221).
+char(p,21222).
+char(2,21223).
+char(2,21224).
+char(4,21225).
+char(4,21226).
+char(m,21227).
+char(o,21228).
+char(p,21229).
+char(o,21230).
+char(p,21231).
+char(o,21232).
+char(o,21233).
+char(3,21234).
+char(0,21235).
+char(1,21236).
+char(5,21237).
+char(m,21238).
+char(o,21239).
+char(m,21240).
+char(3,21241).
+char(2,21242).
+char(6,21243).
+char(3,21244).
+char(m,21245).
+char(3,21246).
+char(8,21247).
+char(4,21248).
+char(4,21249).
+char(p,21250).
+char(4,21251).
+char(3,21252).
+char(5,21253).
+char(5,21254).
+char(c,21255).
+char(p,21256).
+char(5,21257).
+char(7,21258).
+char(1,21259).
+char(0,21260).
+char(c,21261).
+char(c,21262).
+char(c,21263).
+char(p,21264).
+char(4,21265).
+char(9,21266).
+char(4,21267).
+char(5,21268).
+char(c,21269).
+char(c,21270).
+char(c,21271).
+char(c,21272).
+char(p,21273).
+char(o,21274).
+char(1,21275).
+char(2,21276).
+char(8,21277).
+char(4,21278).
+char(c,21279).
+char(p,21280).
+char(o,21281).
+char(p,21282).
+char(2,21283).
+char(8,21284).
+char(7,21285).
+char(7,21286).
+char(p,21287).
+char(o,21288).
+char(o,21289).
+char(p,21290).
+char(o,21291).
+char(o,21292).
+char(p,21293).
+char(2,21294).
+char(0,21295).
+char(0,21296).
+char(4,21297).
+char(p,21298).
+char(3,21299).
+char(9,21300).
+char(5,21301).
+char(7,21302).
+char(p,21303).
+char(o,21304).
+char(o,21305).
+char(o,21306).
+char(5,21307).
+char(8,21308).
+char(9,21309).
+char(8,21310).
+char(p,21311).
+char(o,21312).
+char(6,21313).
+char(0,21314).
+char(2,21315).
+char(5,21316).
+char(m,21317).
+char(5,21318).
+char(7,21319).
+char(6,21320).
+char(1,21321).
+char(m,21322).
+char(o,21323).
+char(m,21324).
+char(3,21325).
+char(0,21326).
+char(0,21327).
+char(3,21328).
+char(m,21329).
+char(o,21330).
+char(p,21331).
+char(8,21332).
+char(9,21333).
+char(7,21334).
+char(8,21335).
+char(m,21336).
+char(2,21337).
+char(5,21338).
+char(3,21339).
+char(6,21340).
+char(c,21341).
+char(c,21342).
+char(p,21343).
+char(o,21344).
+char(p,21345).
+char(o,21346).
+char(o,21347).
+char(1,21348).
+char(7,21349).
+char(3,21350).
+char(0,21351).
+char(p,21352).
+char(o,21353).
+char(m,21354).
+char(o,21355).
+char(p,21356).
+char(6,21357).
+char(2,21358).
+char(7,21359).
+char(3,21360).
+char(m,21361).
+char(7,21362).
+char(5,21363).
+char(5,21364).
+char(p,21365).
+char(o,21366).
+char(m,21367).
+char(1,21368).
+char(2,21369).
+char(4,21370).
+char(4,21371).
+char(c,21372).
+char(c,21373).
+char(p,21374).
+char(4,21375).
+char(0,21376).
+char(6,21377).
+char(9,21378).
+char(c,21379).
+char(c,21380).
+char(p,21381).
+char(8,21382).
+char(9,21383).
+char(9,21384).
+char(4,21385).
+char(c,21386).
+char(c,21387).
+char(c,21388).
+char(m,21389).
+char(1,21390).
+char(2,21391).
+char(1,21392).
+char(8,21393).
+char(c,21394).
+char(m,21395).
+char(o,21396).
+char(8,21397).
+char(6,21398).
+char(0,21399).
+char(8,21400).
+char(m,21401).
+char(o,21402).
+char(o,21403).
+char(9,21404).
+char(5,21405).
+char(6,21406).
+char(9,21407).
+char(p,21408).
+char(o,21409).
+char(m,21410).
+char(4,21411).
+char(7,21412).
+char(0,21413).
+char(8,21414).
+char(c,21415).
+char(m,21416).
+char(o,21417).
+char(m,21418).
+char(3,21419).
+char(4,21420).
+char(4,21421).
+char(9,21422).
+char(c,21423).
+char(c,21424).
+char(p,21425).
+char(o,21426).
+char(p,21427).
+char(7,21428).
+char(3,21429).
+char(9,21430).
+char(5,21431).
+char(c,21432).
+char(c,21433).
+char(p,21434).
+char(o,21435).
+char(3,21436).
+char(2,21437).
+char(2,21438).
+char(5,21439).
+char(m,21440).
+char(o,21441).
+char(o,21442).
+char(o,21443).
+char(m,21444).
+char(9,21445).
+char(1,21446).
+char(6,21447).
+char(8,21448).
+char(c,21449).
+char(c,21450).
+char(m,21451).
+char(o,21452).
+char(m,21453).
+char(6,21454).
+char(9,21455).
+char(4,21456).
+char(6,21457).
+char(c,21458).
+char(m,21459).
+char(4,21460).
+char(8,21461).
+char(5,21462).
+char(2,21463).
+char(c,21464).
+char(m,21465).
+char(2,21466).
+char(7,21467).
+char(7,21468).
+char(3,21469).
+char(c,21470).
+char(c,21471).
+char(c,21472).
+char(p,21473).
+char(o,21474).
+char(o,21475).
+char(m,21476).
+char(6,21477).
+char(5,21478).
+char(9,21479).
+char(2,21480).
+char(c,21481).
+char(c,21482).
+char(p,21483).
+char(o,21484).
+char(m,21485).
+char(o,21486).
+char(p,21487).
+char(o,21488).
+char(p,21489).
+char(1,21490).
+char(9,21491).
+char(9,21492).
+char(1,21493).
+char(c,21494).
+char(m,21495).
+char(9,21496).
+char(3,21497).
+char(2,21498).
+char(3,21499).
+char(m,21500).
+char(6,21501).
+char(2,21502).
+char(2,21503).
+char(7,21504).
+char(c,21505).
+char(m,21506).
+char(7,21507).
+char(1,21508).
+char(8,21509).
+char(7,21510).
+char(m,21511).
+char(o,21512).
+char(2,21513).
+char(6,21514).
+char(9,21515).
+char(c,21516).
+char(m,21517).
+char(o,21518).
+char(o,21519).
+char(m,21520).
+char(3,21521).
+char(2,21522).
+char(9,21523).
+char(5,21524).
+char(c,21525).
+char(m,21526).
+char(4,21527).
+char(5,21528).
+char(0,21529).
+char(1,21530).
+char(p,21531).
+char(o,21532).
+char(m,21533).
+char(4,21534).
+char(2,21535).
+char(6,21536).
+char(9,21537).
+char(c,21538).
+char(p,21539).
+char(o,21540).
+char(6,21541).
+char(0,21542).
+char(7,21543).
+char(6,21544).
+char(c,21545).
+char(c,21546).
+char(m,21547).
+char(6,21548).
+char(7,21549).
+char(9,21550).
+char(8,21551).
+char(p,21552).
+char(9,21553).
+char(9,21554).
+char(8,21555).
+char(1,21556).
+char(c,21557).
+char(c,21558).
+char(c,21559).
+char(c,21560).
+char(c,21561).
+char(m,21562).
+char(o,21563).
+char(p,21564).
+char(1,21565).
+char(5,21566).
+char(8,21567).
+char(7,21568).
+char(p,21569).
+char(o,21570).
+char(p,21571).
+char(o,21572).
+char(m,21573).
+char(5,21574).
+char(3,21575).
+char(0,21576).
+char(2,21577).
+char(p,21578).
+char(o,21579).
+char(o,21580).
+char(o,21581).
+char(m,21582).
+char(o,21583).
+char(p,21584).
+char(o,21585).
+char(p,21586).
+char(8,21587).
+char(3,21588).
+char(0,21589).
+char(1,21590).
+char(c,21591).
+char(m,21592).
+char(6,21593).
+char(6,21594).
+char(1,21595).
+char(8,21596).
+char(m,21597).
+char(o,21598).
+char(m,21599).
+char(6,21600).
+char(9,21601).
+char(1,21602).
+char(9,21603).
+char(m,21604).
+char(1,21605).
+char(1,21606).
+char(1,21607).
+char(3,21608).
+char(c,21609).
+char(p,21610).
+char(4,21611).
+char(3,21612).
+char(4,21613).
+char(0,21614).
+char(c,21615).
+char(p,21616).
+char(o,21617).
+char(o,21618).
+char(m,21619).
+char(o,21620).
+char(m,21621).
+char(1,21622).
+char(4,21623).
+char(1,21624).
+char(8,21625).
+char(c,21626).
+char(m,21627).
+char(o,21628).
+char(o,21629).
+char(m,21630).
+char(o,21631).
+char(m,21632).
+char(o,21633).
+char(2,21634).
+char(8,21635).
+char(4,21636).
+char(4,21637).
+char(c,21638).
+char(p,21639).
+char(1,21640).
+char(5,21641).
+char(7,21642).
+char(8,21643).
+char(c,21644).
+char(c,21645).
+char(m,21646).
+char(o,21647).
+char(o,21648).
+char(p,21649).
+char(o,21650).
+char(p,21651).
+char(5,21652).
+char(9,21653).
+char(8,21654).
+char(0,21655).
+char(c,21656).
+char(p,21657).
+char(o,21658).
+char(p,21659).
+char(4,21660).
+char(5,21661).
+char(2,21662).
+char(3,21663).
+char(c,21664).
+char(c,21665).
+char(c,21666).
+char(p,21667).
+char(o,21668).
+char(m,21669).
+char(5,21670).
+char(0,21671).
+char(1,21672).
+char(0,21673).
+char(c,21674).
+char(p,21675).
+char(2,21676).
+char(0,21677).
+char(2,21678).
+char(9,21679).
+char(m,21680).
+char(o,21681).
+char(o,21682).
+char(m,21683).
+char(o,21684).
+char(o,21685).
+char(p,21686).
+char(o,21687).
+char(p,21688).
+char(o,21689).
+char(p,21690).
+char(o,21691).
+char(m,21692).
+char(4,21693).
+char(7,21694).
+char(6,21695).
+char(7,21696).
+char(p,21697).
+char(5,21698).
+char(2,21699).
+char(4,21700).
+char(8,21701).
+char(p,21702).
+char(6,21703).
+char(0,21704).
+char(7,21705).
+char(8,21706).
+char(p,21707).
+char(7,21708).
+char(2,21709).
+char(2,21710).
+char(2,21711).
+char(p,21712).
+char(5,21713).
+char(2,21714).
+char(7,21715).
+char(7,21716).
+char(p,21717).
+char(o,21718).
+char(p,21719).
+char(o,21720).
+char(m,21721).
+char(8,21722).
+char(3,21723).
+char(6,21724).
+char(8,21725).
+char(p,21726).
+char(o,21727).
+char(m,21728).
+char(4,21729).
+char(6,21730).
+char(5,21731).
+char(9,21732).
+char(p,21733).
+char(o,21734).
+char(m,21735).
+char(3,21736).
+char(1,21737).
+char(9,21738).
+char(3,21739).
+char(c,21740).
+char(c,21741).
+char(c,21742).
+char(p,21743).
+char(7,21744).
+char(5,21745).
+char(5,21746).
+char(5,21747).
+char(c,21748).
+char(c,21749).
+char(c,21750).
+char(c,21751).
+char(m,21752).
+char(o,21753).
+char(m,21754).
+char(6,21755).
+char(8,21756).
+char(2,21757).
+char(9,21758).
+char(p,21759).
+char(3,21760).
+char(2,21761).
+char(0,21762).
+char(3,21763).
+char(c,21764).
+char(m,21765).
+char(o,21766).
+char(o,21767).
+char(p,21768).
+char(o,21769).
+char(p,21770).
+char(6,21771).
+char(6,21772).
+char(2,21773).
+char(8,21774).
+char(m,21775).
+char(6,21776).
+char(2,21777).
+char(1,21778).
+char(7,21779).
+char(c,21780).
+char(c,21781).
+char(c,21782).
+char(c,21783).
+char(p,21784).
+char(o,21785).
+char(o,21786).
+char(m,21787).
+char(o,21788).
+char(p,21789).
+char(1,21790).
+char(6,21791).
+char(5,21792).
+char(0,21793).
+char(p,21794).
+char(4,21795).
+char(9,21796).
+char(9,21797).
+char(8,21798).
+char(p,21799).
+char(o,21800).
+char(m,21801).
+char(o,21802).
+char(p,21803).
+char(1,21804).
+char(3,21805).
+char(4,21806).
+char(6,21807).
+char(m,21808).
+char(7,21809).
+char(0,21810).
+char(0,21811).
+char(0,21812).
+char(m,21813).
+char(6,21814).
+char(2,21815).
+char(9,21816).
+char(5,21817).
+char(c,21818).
+char(p,21819).
+char(o,21820).
+char(p,21821).
+char(9,21822).
+char(2,21823).
+char(1,21824).
+char(2,21825).
+char(p,21826).
+char(6,21827).
+char(4,21828).
+char(9,21829).
+char(3,21830).
+char(c,21831).
+char(c,21832).
+char(c,21833).
+char(m,21834).
+char(2,21835).
+char(1,21836).
+char(0,21837).
+char(7,21838).
+char(m,21839).
+char(o,21840).
+char(m,21841).
+char(o,21842).
+char(m,21843).
+char(8,21844).
+char(7,21845).
+char(5,21846).
+char(1,21847).
+char(c,21848).
+char(c,21849).
+char(c,21850).
+char(c,21851).
+char(p,21852).
+char(o,21853).
+char(p,21854).
+char(2,21855).
+char(3,21856).
+char(4,21857).
+char(6,21858).
+char(m,21859).
+char(6,21860).
+char(9,21861).
+char(9,21862).
+char(5,21863).
+char(c,21864).
+char(p,21865).
+char(o,21866).
+char(o,21867).
+char(p,21868).
+char(1,21869).
+char(0,21870).
+char(0,21871).
+char(9,21872).
+char(c,21873).
+char(c,21874).
+char(c,21875).
+char(c,21876).
+char(m,21877).
+char(o,21878).
+char(p,21879).
+char(1,21880).
+char(2,21881).
+char(8,21882).
+char(7,21883).
+char(c,21884).
+char(m,21885).
+char(3,21886).
+char(6,21887).
+char(0,21888).
+char(9,21889).
+char(c,21890).
+char(p,21891).
+char(o,21892).
+char(m,21893).
+char(8,21894).
+char(1,21895).
+char(2,21896).
+char(3,21897).
+char(c,21898).
+char(p,21899).
+char(5,21900).
+char(9,21901).
+char(9,21902).
+char(6,21903).
+char(c,21904).
+char(c,21905).
+char(c,21906).
+char(c,21907).
+char(m,21908).
+char(o,21909).
+char(p,21910).
+char(o,21911).
+char(m,21912).
+char(6,21913).
+char(6,21914).
+char(7,21915).
+char(2,21916).
+char(m,21917).
+char(o,21918).
+char(p,21919).
+char(o,21920).
+char(p,21921).
+char(3,21922).
+char(0,21923).
+char(0,21924).
+char(7,21925).
+char(c,21926).
+char(c,21927).
+char(p,21928).
+char(o,21929).
+char(p,21930).
+char(o,21931).
+char(o,21932).
+char(1,21933).
+char(2,21934).
+char(2,21935).
+char(8,21936).
+char(c,21937).
+char(p,21938).
+char(2,21939).
+char(3,21940).
+char(5,21941).
+char(5,21942).
+char(m,21943).
+char(6,21944).
+char(6,21945).
+char(7,21946).
+char(2,21947).
+char(p,21948).
+char(o,21949).
+char(p,21950).
+char(o,21951).
+char(p,21952).
+char(5,21953).
+char(2,21954).
+char(5,21955).
+char(0,21956).
+char(p,21957).
+char(2,21958).
+char(7,21959).
+char(7,21960).
+char(2,21961).
+char(c,21962).
+char(c,21963).
+char(m,21964).
+char(6,21965).
+char(4,21966).
+char(9,21967).
+char(1,21968).
+char(c,21969).
+char(c,21970).
+char(p,21971).
+char(3,21972).
+char(6,21973).
+char(7,21974).
+char(c,21975).
+char(p,21976).
+char(7,21977).
+char(0,21978).
+char(6,21979).
+char(3,21980).
+char(m,21981).
+char(4,21982).
+char(5,21983).
+char(9,21984).
+char(2,21985).
+char(p,21986).
+char(o,21987).
+char(p,21988).
+char(6,21989).
+char(3,21990).
+char(8,21991).
+char(m,21992).
+char(6,21993).
+char(5,21994).
+char(5,21995).
+char(8,21996).
+char(c,21997).
+char(m,21998).
+char(2,21999).
+char(7,22000).
+char(9,22001).
+char(3,22002).
+char(m,22003).
+char(o,22004).
+char(8,22005).
+char(2,22006).
+char(2,22007).
+char(c,22008).
+char(c,22009).
+char(c,22010).
+char(m,22011).
+char(o,22012).
+char(p,22013).
+char(8,22014).
+char(7,22015).
+char(0,22016).
+char(1,22017).
+char(c,22018).
+char(c,22019).
+char(m,22020).
+char(o,22021).
+char(o,22022).
+char(o,22023).
+char(m,22024).
+char(4,22025).
+char(6,22026).
+char(9,22027).
+char(0,22028).
+char(c,22029).
+char(c,22030).
+char(c,22031).
+char(c,22032).
+char(c,22033).
+char(c,22034).
+char(p,22035).
+char(8,22036).
+char(8,22037).
+char(9,22038).
+char(6,22039).
+char(m,22040).
+char(o,22041).
+char(o,22042).
+char(o,22043).
+char(p,22044).
+char(o,22045).
+char(p,22046).
+char(o,22047).
+char(3,22048).
+char(2,22049).
+char(6,22050).
+char(3,22051).
+char(c,22052).
+char(p,22053).
+char(3,22054).
+char(7,22055).
+char(3,22056).
+char(9,22057).
+char(c,22058).
+char(c,22059).
+char(m,22060).
+char(o,22061).
+char(o,22062).
+char(9,22063).
+char(4,22064).
+char(7,22065).
+char(2,22066).
+char(p,22067).
+char(7,22068).
+char(8,22069).
+char(0,22070).
+char(4,22071).
+char(c,22072).
+char(c,22073).
+char(c,22074).
+char(m,22075).
+char(o,22076).
+char(m,22077).
+char(1,22078).
+char(7,22079).
+char(2,22080).
+char(9,22081).
+char(c,22082).
+char(c,22083).
+char(c,22084).
+char(m,22085).
+char(1,22086).
+char(8,22087).
+char(2,22088).
+char(7,22089).
+char(m,22090).
+char(5,22091).
+char(7,22092).
+char(2,22093).
+char(2,22094).
+char(c,22095).
+char(m,22096).
+char(8,22097).
+char(8,22098).
+char(6,22099).
+char(2,22100).
+char(c,22101).
+char(c,22102).
+char(c,22103).
+char(c,22104).
+char(c,22105).
+char(m,22106).
+char(3,22107).
+char(9,22108).
+char(7,22109).
+char(1,22110).
+char(m,22111).
+char(o,22112).
+char(m,22113).
+char(o,22114).
+char(p,22115).
+char(9,22116).
+char(8,22117).
+char(1,22118).
+char(0,22119).
+char(m,22120).
+char(6,22121).
+char(3,22122).
+char(6,22123).
+char(7,22124).
+char(c,22125).
+char(c,22126).
+char(c,22127).
+char(c,22128).
+char(c,22129).
+char(c,22130).
+char(c,22131).
+char(p,22132).
+char(3,22133).
+char(9,22134).
+char(1,22135).
+char(4,22136).
+char(m,22137).
+char(o,22138).
+char(m,22139).
+char(o,22140).
+char(m,22141).
+char(o,22142).
+char(p,22143).
+char(o,22144).
+char(p,22145).
+char(1,22146).
+char(3,22147).
+char(0,22148).
+char(m,22149).
+char(4,22150).
+char(3,22151).
+char(0,22152).
+char(6,22153).
+char(m,22154).
+char(3,22155).
+char(6,22156).
+char(1,22157).
+char(7,22158).
+char(c,22159).
+char(c,22160).
+char(p,22161).
+char(o,22162).
+char(o,22163).
+char(p,22164).
+char(2,22165).
+char(8,22166).
+char(1,22167).
+char(2,22168).
+char(m,22169).
+char(o,22170).
+char(p,22171).
+char(8,22172).
+char(5,22173).
+char(9,22174).
+char(6,22175).
+char(c,22176).
+char(c,22177).
+char(c,22178).
+char(c,22179).
+char(p,22180).
+char(7,22181).
+char(6,22182).
+char(5,22183).
+char(0,22184).
+char(c,22185).
+char(p,22186).
+char(7,22187).
+char(7,22188).
+char(2,22189).
+char(8,22190).
+char(p,22191).
+char(o,22192).
+char(2,22193).
+char(0,22194).
+char(6,22195).
+char(2,22196).
+char(p,22197).
+char(o,22198).
+char(o,22199).
+char(m,22200).
+char(2,22201).
+char(2,22202).
+char(4,22203).
+char(5,22204).
+char(c,22205).
+char(c,22206).
+char(m,22207).
+char(o,22208).
+char(p,22209).
+char(o,22210).
+char(p,22211).
+char(o,22212).
+char(p,22213).
+char(3,22214).
+char(0,22215).
+char(7,22216).
+char(3,22217).
+char(c,22218).
+char(m,22219).
+char(3,22220).
+char(7,22221).
+char(9,22222).
+char(5,22223).
+char(p,22224).
+char(6,22225).
+char(3,22226).
+char(4,22227).
+char(0,22228).
+char(p,22229).
+char(o,22230).
+char(o,22231).
+char(m,22232).
+char(o,22233).
+char(p,22234).
+char(9,22235).
+char(1,22236).
+char(2,22237).
+char(6,22238).
+char(m,22239).
+char(6,22240).
+char(2,22241).
+char(9,22242).
+char(4,22243).
+char(p,22244).
+char(2,22245).
+char(9,22246).
+char(2,22247).
+char(3,22248).
+char(c,22249).
+char(m,22250).
+char(o,22251).
+char(o,22252).
+char(o,22253).
+char(2,22254).
+char(1,22255).
+char(2,22256).
+char(p,22257).
+char(7,22258).
+char(4,22259).
+char(4,22260).
+char(8,22261).
+char(p,22262).
+char(8,22263).
+char(4,22264).
+char(9,22265).
+char(6,22266).
+char(c,22267).
+char(c,22268).
+char(c,22269).
+char(c,22270).
+char(c,22271).
+char(m,22272).
+char(6,22273).
+char(6,22274).
+char(5,22275).
+char(2,22276).
+char(m,22277).
+char(o,22278).
+char(p,22279).
+char(o,22280).
+char(p,22281).
+char(8,22282).
+char(1,22283).
+char(0,22284).
+char(9,22285).
+char(c,22286).
+char(c,22287).
+char(p,22288).
+char(o,22289).
+char(m,22290).
+char(o,22291).
+char(o,22292).
+char(o,22293).
+char(p,22294).
+char(5,22295).
+char(7,22296).
+char(9,22297).
+char(5,22298).
+char(m,22299).
+char(1,22300).
+char(2,22301).
+char(0,22302).
+char(8,22303).
+char(c,22304).
+char(m,22305).
+char(o,22306).
+char(1,22307).
+char(1,22308).
+char(9,22309).
+char(m,22310).
+char(4,22311).
+char(9,22312).
+char(8,22313).
+char(1,22314).
+char(p,22315).
+char(1,22316).
+char(2,22317).
+char(1,22318).
+char(c,22319).
+char(c,22320).
+char(c,22321).
+char(c,22322).
+char(p,22323).
+char(5,22324).
+char(3,22325).
+char(8,22326).
+char(1,22327).
+char(c,22328).
+char(m,22329).
+char(o,22330).
+char(m,22331).
+char(9,22332).
+char(1,22333).
+char(7,22334).
+char(9,22335).
+char(p,22336).
+char(o,22337).
+char(o,22338).
+char(o,22339).
+char(p,22340).
+char(o,22341).
+char(2,22342).
+char(4,22343).
+char(2,22344).
+char(6,22345).
+char(p,22346).
+char(8,22347).
+char(8,22348).
+char(8,22349).
+char(c,22350).
+char(c,22351).
+char(c,22352).
+char(c,22353).
+char(p,22354).
+char(4,22355).
+char(6,22356).
+char(5,22357).
+char(p,22358).
+char(9,22359).
+char(3,22360).
+char(2,22361).
+char(3,22362).
+char(c,22363).
+char(m,22364).
+char(o,22365).
+char(o,22366).
+char(o,22367).
+char(m,22368).
+char(1,22369).
+char(6,22370).
+char(4,22371).
+char(m,22372).
+char(o,22373).
+char(p,22374).
+char(1,22375).
+char(3,22376).
+char(8,22377).
+char(2,22378).
+char(m,22379).
+char(o,22380).
+char(m,22381).
+char(o,22382).
+char(p,22383).
+char(o,22384).
+char(p,22385).
+char(o,22386).
+char(p,22387).
+char(3,22388).
+char(6,22389).
+char(3,22390).
+char(6,22391).
+char(m,22392).
+char(o,22393).
+char(m,22394).
+char(o,22395).
+char(4,22396).
+char(1,22397).
+char(5,22398).
+char(4,22399).
+char(c,22400).
+char(c,22401).
+char(p,22402).
+char(o,22403).
+char(m,22404).
+char(2,22405).
+char(5,22406).
+char(8,22407).
+char(1,22408).
+char(p,22409).
+char(6,22410).
+char(3,22411).
+char(4,22412).
+char(5,22413).
+char(c,22414).
+char(c,22415).
+char(p,22416).
+char(o,22417).
+char(6,22418).
+char(8,22419).
+char(6,22420).
+char(2,22421).
+char(p,22422).
+char(o,22423).
+char(m,22424).
+char(2,22425).
+char(8,22426).
+char(0,22427).
+char(9,22428).
+char(m,22429).
+char(9,22430).
+char(9,22431).
+char(3,22432).
+char(p,22433).
+char(o,22434).
+char(o,22435).
+char(p,22436).
+char(7,22437).
+char(7,22438).
+char(1,22439).
+char(p,22440).
+char(o,22441).
+char(m,22442).
+char(1,22443).
+char(4,22444).
+char(9,22445).
+char(1,22446).
+char(m,22447).
+char(7,22448).
+char(8,22449).
+char(7,22450).
+char(1,22451).
+char(p,22452).
+char(8,22453).
+char(7,22454).
+char(8,22455).
+char(0,22456).
+char(p,22457).
+char(o,22458).
+char(m,22459).
+char(1,22460).
+char(8,22461).
+char(0,22462).
+char(4,22463).
+char(p,22464).
+char(o,22465).
+char(6,22466).
+char(4,22467).
+char(9,22468).
+char(4,22469).
+char(c,22470).
+char(p,22471).
+char(o,22472).
+char(m,22473).
+char(9,22474).
+char(5,22475).
+char(3,22476).
+char(2,22477).
+char(m,22478).
+char(o,22479).
+char(p,22480).
+char(o,22481).
+char(o,22482).
+char(p,22483).
+char(o,22484).
+char(m,22485).
+char(4,22486).
+char(3,22487).
+char(2,22488).
+char(p,22489).
+char(1,22490).
+char(0,22491).
+char(8,22492).
+char(4,22493).
+char(c,22494).
+char(c,22495).
+char(p,22496).
+char(o,22497).
+char(p,22498).
+char(1,22499).
+char(1,22500).
+char(6,22501).
+char(p,22502).
+char(8,22503).
+char(4,22504).
+char(9,22505).
+char(c,22506).
+char(p,22507).
+char(1,22508).
+char(1,22509).
+char(7,22510).
+char(9,22511).
+char(c,22512).
+char(c,22513).
+char(m,22514).
+char(8,22515).
+char(8,22516).
+char(0,22517).
+char(0,22518).
+char(c,22519).
+char(c,22520).
+char(c,22521).
+char(c,22522).
+char(c,22523).
+char(m,22524).
+char(o,22525).
+char(p,22526).
+char(4,22527).
+char(6,22528).
+char(7,22529).
+char(6,22530).
+char(c,22531).
+char(p,22532).
+char(6,22533).
+char(8,22534).
+char(3,22535).
+char(7,22536).
+char(p,22537).
+char(8,22538).
+char(1,22539).
+char(5,22540).
+char(0,22541).
+char(p,22542).
+char(o,22543).
+char(4,22544).
+char(3,22545).
+char(3,22546).
+char(c,22547).
+char(c,22548).
+char(p,22549).
+char(5,22550).
+char(1,22551).
+char(1,22552).
+char(1,22553).
+char(c,22554).
+char(c,22555).
+char(m,22556).
+char(o,22557).
+char(7,22558).
+char(1,22559).
+char(7,22560).
+char(8,22561).
+char(c,22562).
+char(c,22563).
+char(p,22564).
+char(3,22565).
+char(9,22566).
+char(2,22567).
+char(5,22568).
+char(m,22569).
+char(8,22570).
+char(4,22571).
+char(6,22572).
+char(8,22573).
+char(p,22574).
+char(8,22575).
+char(3,22576).
+char(2,22577).
+char(4,22578).
+char(c,22579).
+char(c,22580).
+char(c,22581).
+char(m,22582).
+char(o,22583).
+char(2,22584).
+char(2,22585).
+char(3,22586).
+char(9,22587).
+char(c,22588).
+char(p,22589).
+char(o,22590).
+char(m,22591).
+char(o,22592).
+char(m,22593).
+char(5,22594).
+char(7,22595).
+char(4,22596).
+char(c,22597).
+char(p,22598).
+char(o,22599).
+char(o,22600).
+char(m,22601).
+char(2,22602).
+char(8,22603).
+char(7,22604).
+char(9,22605).
+char(p,22606).
+char(6,22607).
+char(1,22608).
+char(3,22609).
+char(2,22610).
+char(c,22611).
+char(c,22612).
+char(c,22613).
+char(m,22614).
+char(1,22615).
+char(6,22616).
+char(9,22617).
+char(6,22618).
+char(m,22619).
+char(3,22620).
+char(9,22621).
+char(8,22622).
+char(2,22623).
+char(c,22624).
+char(p,22625).
+char(o,22626).
+char(o,22627).
+char(m,22628).
+char(o,22629).
+char(m,22630).
+char(o,22631).
+char(p,22632).
+char(o,22633).
+char(2,22634).
+char(1,22635).
+char(7,22636).
+char(8,22637).
+char(c,22638).
+char(p,22639).
+char(o,22640).
+char(p,22641).
+char(o,22642).
+char(p,22643).
+char(4,22644).
+char(5,22645).
+char(6,22646).
+char(7,22647).
+char(c,22648).
+char(c,22649).
+char(c,22650).
+char(c,22651).
+char(p,22652).
+char(7,22653).
+char(3,22654).
+char(7,22655).
+char(2,22656).
+char(p,22657).
+char(o,22658).
+char(p,22659).
+char(o,22660).
+char(m,22661).
+char(o,22662).
+char(m,22663).
+char(o,22664).
+char(o,22665).
+char(3,22666).
+char(7,22667).
+char(0,22668).
+char(5,22669).
+char(c,22670).
+char(p,22671).
+char(o,22672).
+char(o,22673).
+char(m,22674).
+char(o,22675).
+char(p,22676).
+char(4,22677).
+char(3,22678).
+char(7,22679).
+char(4,22680).
+char(c,22681).
+char(c,22682).
+char(m,22683).
+char(8,22684).
+char(8,22685).
+char(0,22686).
+char(7,22687).
+char(c,22688).
+char(c,22689).
+char(c,22690).
+char(c,22691).
+char(m,22692).
+char(2,22693).
+char(5,22694).
+char(2,22695).
+char(3,22696).
+char(c,22697).
+char(c,22698).
+char(c,22699).
+char(c,22700).
+char(m,22701).
+char(o,22702).
+char(m,22703).
+char(o,22704).
+char(p,22705).
+char(9,22706).
+char(1,22707).
+char(7,22708).
+char(9,22709).
+char(m,22710).
+char(6,22711).
+char(1,22712).
+char(2,22713).
+char(6,22714).
+char(m,22715).
+char(o,22716).
+char(6,22717).
+char(7,22718).
+char(9,22719).
+char(9,22720).
+char(m,22721).
+char(o,22722).
+char(p,22723).
+char(o,22724).
+char(2,22725).
+char(9,22726).
+char(6,22727).
+char(1,22728).
+char(p,22729).
+char(6,22730).
+char(8,22731).
+char(8,22732).
+char(4,22733).
+char(m,22734).
+char(1,22735).
+char(6,22736).
+char(5,22737).
+char(4,22738).
+char(m,22739).
+char(8,22740).
+char(6,22741).
+char(8,22742).
+char(3,22743).
+char(c,22744).
+char(p,22745).
+char(o,22746).
+char(o,22747).
+char(m,22748).
+char(o,22749).
+char(m,22750).
+char(o,22751).
+char(7,22752).
+char(8,22753).
+char(8,22754).
+char(5,22755).
+char(p,22756).
+char(o,22757).
+char(7,22758).
+char(4,22759).
+char(1,22760).
+char(0,22761).
+char(p,22762).
+char(o,22763).
+char(p,22764).
+char(4,22765).
+char(3,22766).
+char(4,22767).
+char(0,22768).
+char(c,22769).
+char(p,22770).
+char(4,22771).
+char(3,22772).
+char(4,22773).
+char(6,22774).
+char(p,22775).
+char(2,22776).
+char(1,22777).
+char(5,22778).
+char(4,22779).
+char(p,22780).
+char(o,22781).
+char(p,22782).
+char(9,22783).
+char(4,22784).
+char(4,22785).
+char(8,22786).
+char(c,22787).
+char(c,22788).
+char(m,22789).
+char(o,22790).
+char(p,22791).
+char(1,22792).
+char(4,22793).
+char(2,22794).
+char(9,22795).
+char(c,22796).
+char(c,22797).
+char(p,22798).
+char(o,22799).
+char(p,22800).
+char(9,22801).
+char(1,22802).
+char(2,22803).
+char(3,22804).
+char(m,22805).
+char(o,22806).
+char(9,22807).
+char(9,22808).
+char(0,22809).
+char(8,22810).
+char(c,22811).
+char(m,22812).
+char(4,22813).
+char(0,22814).
+char(5,22815).
+char(6,22816).
+char(c,22817).
+char(m,22818).
+char(o,22819).
+char(m,22820).
+char(o,22821).
+char(m,22822).
+char(6,22823).
+char(0,22824).
+char(6,22825).
+char(1,22826).
+char(m,22827).
+char(6,22828).
+char(2,22829).
+char(5,22830).
+char(6,22831).
+char(p,22832).
+char(6,22833).
+char(4,22834).
+char(7,22835).
+char(3,22836).
+char(c,22837).
+char(c,22838).
+char(m,22839).
+char(1,22840).
+char(9,22841).
+char(7,22842).
+char(1,22843).
+char(c,22844).
+char(p,22845).
+char(9,22846).
+char(6,22847).
+char(1,22848).
+char(2,22849).
+char(m,22850).
+char(o,22851).
+char(p,22852).
+char(o,22853).
+char(6,22854).
+char(6,22855).
+char(5,22856).
+char(0,22857).
+char(p,22858).
+char(7,22859).
+char(0,22860).
+char(6,22861).
+char(7,22862).
+char(m,22863).
+char(o,22864).
+char(m,22865).
+char(3,22866).
+char(8,22867).
+char(2,22868).
+char(9,22869).
+char(c,22870).
+char(c,22871).
+char(c,22872).
+char(p,22873).
+char(3,22874).
+char(4,22875).
+char(1,22876).
+char(1,22877).
+char(p,22878).
+char(o,22879).
+char(9,22880).
+char(8,22881).
+char(8,22882).
+char(0,22883).
+char(m,22884).
+char(o,22885).
+char(o,22886).
+char(p,22887).
+char(o,22888).
+char(p,22889).
+char(o,22890).
+char(p,22891).
+char(o,22892).
+char(o,22893).
+char(m,22894).
+char(o,22895).
+char(m,22896).
+char(o,22897).
+char(7,22898).
+char(9,22899).
+char(4,22900).
+char(4,22901).
+char(c,22902).
+char(c,22903).
+char(c,22904).
+char(m,22905).
+char(7,22906).
+char(1,22907).
+char(8,22908).
+char(9,22909).
+char(p,22910).
+char(1,22911).
+char(1,22912).
+char(2,22913).
+char(0,22914).
+char(c,22915).
+char(p,22916).
+char(o,22917).
+char(o,22918).
+char(m,22919).
+char(9,22920).
+char(5,22921).
+char(5,22922).
+char(0,22923).
+char(c,22924).
+char(m,22925).
+char(o,22926).
+char(m,22927).
+char(o,22928).
+char(6,22929).
+char(4,22930).
+char(2,22931).
+char(8,22932).
+char(p,22933).
+char(o,22934).
+char(p,22935).
+char(o,22936).
+char(m,22937).
+char(7,22938).
+char(0,22939).
+char(1,22940).
+char(5,22941).
+char(p,22942).
+char(o,22943).
+char(p,22944).
+char(1,22945).
+char(4,22946).
+char(9,22947).
+char(1,22948).
+char(m,22949).
+char(5,22950).
+char(4,22951).
+char(3,22952).
+char(3,22953).
+char(c,22954).
+char(m,22955).
+char(o,22956).
+char(m,22957).
+char(o,22958).
+char(7,22959).
+char(0,22960).
+char(2,22961).
+char(5,22962).
+char(c,22963).
+char(c,22964).
+char(c,22965).
+char(c,22966).
+char(p,22967).
+char(o,22968).
+char(o,22969).
+char(p,22970).
+char(o,22971).
+char(m,22972).
+char(o,22973).
+char(p,22974).
+char(o,22975).
+char(p,22976).
+char(2,22977).
+char(3,22978).
+char(0,22979).
+char(m,22980).
+char(o,22981).
+char(7,22982).
+char(6,22983).
+char(0,22984).
+char(8,22985).
+char(m,22986).
+char(o,22987).
+char(o,22988).
+char(p,22989).
+char(2,22990).
+char(9,22991).
+char(6,22992).
+char(5,22993).
+char(c,22994).
+char(p,22995).
+char(7,22996).
+char(1,22997).
+char(0,22998).
+char(3,22999).
+char(c,23000).
+char(m,23001).
+char(5,23002).
+char(3,23003).
+char(4,23004).
+char(c,23005).
+char(c,23006).
+char(c,23007).
+char(m,23008).
+char(o,23009).
+char(8,23010).
+char(9,23011).
+char(0,23012).
+char(c,23013).
+char(c,23014).
+char(m,23015).
+char(3,23016).
+char(2,23017).
+char(4,23018).
+char(4,23019).
+char(m,23020).
+char(4,23021).
+char(4,23022).
+char(1,23023).
+char(7,23024).
+char(p,23025).
+char(o,23026).
+char(m,23027).
+char(6,23028).
+char(0,23029).
+char(3,23030).
+char(0,23031).
+char(p,23032).
+char(5,23033).
+char(5,23034).
+char(1,23035).
+char(2,23036).
+char(p,23037).
+char(o,23038).
+char(m,23039).
+char(3,23040).
+char(6,23041).
+char(6,23042).
+char(5,23043).
+char(c,23044).
+char(c,23045).
+char(m,23046).
+char(o,23047).
+char(m,23048).
+char(1,23049).
+char(7,23050).
+char(3,23051).
+char(9,23052).
+char(c,23053).
+char(p,23054).
+char(1,23055).
+char(5,23056).
+char(8,23057).
+char(7,23058).
+char(p,23059).
+char(o,23060).
+char(m,23061).
+char(9,23062).
+char(5,23063).
+char(7,23064).
+char(m,23065).
+char(2,23066).
+char(0,23067).
+char(1,23068).
+char(4,23069).
+char(p,23070).
+char(o,23071).
+char(m,23072).
+char(2,23073).
+char(0,23074).
+char(5,23075).
+char(5,23076).
+char(c,23077).
+char(m,23078).
+char(o,23079).
+char(o,23080).
+char(m,23081).
+char(o,23082).
+char(p,23083).
+char(1,23084).
+char(7,23085).
+char(8,23086).
+char(7,23087).
+char(c,23088).
+char(c,23089).
+char(c,23090).
+char(c,23091).
+char(m,23092).
+char(o,23093).
+char(o,23094).
+char(p,23095).
+char(o,23096).
+char(m,23097).
+char(4,23098).
+char(3,23099).
+char(8,23100).
+char(2,23101).
+char(c,23102).
+char(p,23103).
+char(o,23104).
+char(p,23105).
+char(1,23106).
+char(9,23107).
+char(2,23108).
+char(6,23109).
+char(c,23110).
+char(c,23111).
+char(c,23112).
+char(c,23113).
+char(c,23114).
+char(c,23115).
+char(m,23116).
+char(o,23117).
+char(p,23118).
+char(o,23119).
+char(p,23120).
+char(4,23121).
+char(6,23122).
+char(6,23123).
+char(4,23124).
+char(m,23125).
+char(o,23126).
+char(m,23127).
+char(3,23128).
+char(6,23129).
+char(3,23130).
+char(4,23131).
+char(p,23132).
+char(o,23133).
+char(m,23134).
+char(5,23135).
+char(7,23136).
+char(7,23137).
+char(8,23138).
+char(c,23139).
+char(m,23140).
+char(o,23141).
+char(3,23142).
+char(4,23143).
+char(4,23144).
+char(c,23145).
+char(c,23146).
+char(m,23147).
+char(1,23148).
+char(2,23149).
+char(3,23150).
+char(c,23151).
+char(m,23152).
+char(o,23153).
+char(m,23154).
+char(2,23155).
+char(8,23156).
+char(7,23157).
+char(7,23158).
+char(m,23159).
+char(4,23160).
+char(1,23161).
+char(1,23162).
+char(3,23163).
+char(c,23164).
+char(m,23165).
+char(2,23166).
+char(8,23167).
+char(4,23168).
+char(6,23169).
+char(c,23170).
+char(p,23171).
+char(3,23172).
+char(0,23173).
+char(1,23174).
+char(1,23175).
+char(m,23176).
+char(6,23177).
+char(0,23178).
+char(9,23179).
+char(3,23180).
+char(c,23181).
+char(c,23182).
+char(c,23183).
+char(c,23184).
+char(c,23185).
+char(c,23186).
+char(c,23187).
+char(m,23188).
+char(9,23189).
+char(1,23190).
+char(1,23191).
+char(m,23192).
+char(4,23193).
+char(4,23194).
+char(3,23195).
+char(p,23196).
+char(o,23197).
+char(2,23198).
+char(0,23199).
+char(4,23200).
+char(5,23201).
+char(c,23202).
+char(p,23203).
+char(3,23204).
+char(8,23205).
+char(0,23206).
+char(c,23207).
+char(m,23208).
+char(7,23209).
+char(5,23210).
+char(9,23211).
+char(1,23212).
+char(c,23213).
+char(c,23214).
+char(p,23215).
+char(o,23216).
+char(p,23217).
+char(o,23218).
+char(o,23219).
+char(m,23220).
+char(o,23221).
+char(6,23222).
+char(8,23223).
+char(8,23224).
+char(8,23225).
+char(p,23226).
+char(8,23227).
+char(7,23228).
+char(7,23229).
+char(5,23230).
+char(m,23231).
+char(o,23232).
+char(o,23233).
+char(o,23234).
+char(7,23235).
+char(2,23236).
+char(4,23237).
+char(7,23238).
+char(p,23239).
+char(9,23240).
+char(1,23241).
+char(1,23242).
+char(6,23243).
+char(c,23244).
+char(c,23245).
+char(p,23246).
+char(5,23247).
+char(2,23248).
+char(3,23249).
+char(2,23250).
+char(c,23251).
+char(c,23252).
+char(c,23253).
+char(c,23254).
+char(m,23255).
+char(9,23256).
+char(6,23257).
+char(1,23258).
+char(9,23259).
+char(p,23260).
+char(o,23261).
+char(m,23262).
+char(o,23263).
+char(o,23264).
+char(m,23265).
+char(o,23266).
+char(o,23267).
+char(o,23268).
+char(p,23269).
+char(4,23270).
+char(2,23271).
+char(7,23272).
+char(8,23273).
+char(m,23274).
+char(o,23275).
+char(o,23276).
+char(m,23277).
+char(o,23278).
+char(o,23279).
+char(3,23280).
+char(1,23281).
+char(5,23282).
+char(6,23283).
+char(m,23284).
+char(o,23285).
+char(p,23286).
+char(o,23287).
+char(m,23288).
+char(3,23289).
+char(2,23290).
+char(9,23291).
+char(7,23292).
+char(c,23293).
+char(m,23294).
+char(6,23295).
+char(0,23296).
+char(7,23297).
+char(9,23298).
+char(c,23299).
+char(m,23300).
+char(3,23301).
+char(4,23302).
+char(c,23303).
+char(p,23304).
+char(o,23305).
+char(4,23306).
+char(3,23307).
+char(6,23308).
+char(3,23309).
+char(p,23310).
+char(3,23311).
+char(3,23312).
+char(8,23313).
+char(2,23314).
+char(p,23315).
+char(o,23316).
+char(p,23317).
+char(5,23318).
+char(9,23319).
+char(2,23320).
+char(5,23321).
+char(p,23322).
+char(9,23323).
+char(7,23324).
+char(6,23325).
+char(5,23326).
+char(c,23327).
+char(p,23328).
+char(o,23329).
+char(p,23330).
+char(9,23331).
+char(9,23332).
+char(4,23333).
+char(6,23334).
+char(c,23335).
+char(c,23336).
+char(m,23337).
+char(o,23338).
+char(m,23339).
+char(o,23340).
+char(m,23341).
+char(6,23342).
+char(9,23343).
+char(2,23344).
+char(5,23345).
+char(p,23346).
+char(o,23347).
+char(o,23348).
+char(p,23349).
+char(o,23350).
+char(p,23351).
+char(o,23352).
+char(2,23353).
+char(9,23354).
+char(8,23355).
+char(6,23356).
+char(p,23357).
+char(o,23358).
+char(4,23359).
+char(6,23360).
+char(9,23361).
+char(7,23362).
+char(c,23363).
+char(m,23364).
+char(6,23365).
+char(0,23366).
+char(2,23367).
+char(3,23368).
+char(m,23369).
+char(o,23370).
+char(5,23371).
+char(1,23372).
+char(4,23373).
+char(4,23374).
+char(c,23375).
+char(c,23376).
+char(c,23377).
+char(c,23378).
+char(c,23379).
+char(c,23380).
+char(c,23381).
+char(c,23382).
+char(m,23383).
+char(5,23384).
+char(6,23385).
+char(5,23386).
+char(4,23387).
+char(c,23388).
+char(c,23389).
+char(c,23390).
+char(c,23391).
+char(c,23392).
+char(c,23393).
+char(p,23394).
+char(6,23395).
+char(3,23396).
+char(3,23397).
+char(5,23398).
+char(m,23399).
+char(o,23400).
+char(m,23401).
+char(o,23402).
+char(m,23403).
+char(8,23404).
+char(0,23405).
+char(4,23406).
+char(0,23407).
+char(p,23408).
+char(o,23409).
+char(m,23410).
+char(9,23411).
+char(9,23412).
+char(2,23413).
+char(2,23414).
+char(c,23415).
+char(m,23416).
+char(8,23417).
+char(4,23418).
+char(6,23419).
+char(5,23420).
+char(c,23421).
+char(p,23422).
+char(1,23423).
+char(2,23424).
+char(3,23425).
+char(7,23426).
+char(p,23427).
+char(4,23428).
+char(2,23429).
+char(4,23430).
+char(c,23431).
+char(m,23432).
+char(o,23433).
+char(p,23434).
+char(o,23435).
+char(o,23436).
+char(p,23437).
+char(o,23438).
+char(9,23439).
+char(8,23440).
+char(7,23441).
+char(3,23442).
+char(c,23443).
+char(c,23444).
+char(m,23445).
+char(o,23446).
+char(5,23447).
+char(9,23448).
+char(5,23449).
+char(c,23450).
+char(c,23451).
+char(p,23452).
+char(3,23453).
+char(5,23454).
+char(6,23455).
+char(7,23456).
+char(p,23457).
+char(o,23458).
+char(7,23459).
+char(8,23460).
+char(3,23461).
+char(m,23462).
+char(9,23463).
+char(9,23464).
+char(0,23465).
+char(p,23466).
+char(8,23467).
+char(3,23468).
+char(5,23469).
+char(0,23470).
+char(c,23471).
+char(p,23472).
+char(8,23473).
+char(9,23474).
+char(4,23475).
+char(6,23476).
+char(m,23477).
+char(9,23478).
+char(3,23479).
+char(0,23480).
+char(4,23481).
+char(c,23482).
+char(m,23483).
+char(7,23484).
+char(3,23485).
+char(4,23486).
+char(9,23487).
+char(p,23488).
+char(8,23489).
+char(6,23490).
+char(4,23491).
+char(5,23492).
+char(c,23493).
+char(c,23494).
+char(p,23495).
+char(3,23496).
+char(1,23497).
+char(7,23498).
+char(m,23499).
+char(o,23500).
+char(9,23501).
+char(6,23502).
+char(4,23503).
+char(3,23504).
+char(c,23505).
+char(m,23506).
+char(4,23507).
+char(3,23508).
+char(6,23509).
+char(8,23510).
+char(m,23511).
+char(o,23512).
+char(p,23513).
+char(o,23514).
+char(2,23515).
+char(2,23516).
+char(6,23517).
+char(9,23518).
+char(c,23519).
+char(c,23520).
+char(c,23521).
+char(c,23522).
+char(c,23523).
+char(m,23524).
+char(o,23525).
+char(m,23526).
+char(5,23527).
+char(9,23528).
+char(1,23529).
+char(m,23530).
+char(1,23531).
+char(6,23532).
+char(4,23533).
+char(1,23534).
+char(m,23535).
+char(o,23536).
+char(m,23537).
+char(o,23538).
+char(m,23539).
+char(9,23540).
+char(3,23541).
+char(7,23542).
+char(1,23543).
+char(c,23544).
+char(p,23545).
+char(7,23546).
+char(9,23547).
+char(5,23548).
+char(7,23549).
+char(c,23550).
+char(c,23551).
+char(p,23552).
+char(1,23553).
+char(5,23554).
+char(9,23555).
+char(1,23556).
+char(m,23557).
+char(4,23558).
+char(1,23559).
+char(5,23560).
+char(7,23561).
+char(m,23562).
+char(8,23563).
+char(5,23564).
+char(0,23565).
+char(9,23566).
+char(m,23567).
+char(o,23568).
+char(m,23569).
+char(1,23570).
+char(6,23571).
+char(6,23572).
+char(8,23573).
+char(c,23574).
+char(c,23575).
+char(c,23576).
+char(p,23577).
+char(6,23578).
+char(3,23579).
+char(5,23580).
+char(1,23581).
+char(m,23582).
+char(o,23583).
+char(m,23584).
+char(1,23585).
+char(0,23586).
+char(3,23587).
+char(1,23588).
+char(m,23589).
+char(o,23590).
+char(p,23591).
+char(o,23592).
+char(m,23593).
+char(9,23594).
+char(9,23595).
+char(9,23596).
+char(0,23597).
+char(p,23598).
+char(3,23599).
+char(3,23600).
+char(4,23601).
+char(1,23602).
+char(m,23603).
+char(o,23604).
+char(p,23605).
+char(o,23606).
+char(p,23607).
+char(3,23608).
+char(3,23609).
+char(8,23610).
+char(c,23611).
+char(m,23612).
+char(7,23613).
+char(4,23614).
+char(2,23615).
+char(0,23616).
+char(m,23617).
+char(o,23618).
+char(m,23619).
+char(7,23620).
+char(4,23621).
+char(8,23622).
+char(7,23623).
+char(p,23624).
+char(o,23625).
+char(p,23626).
+char(o,23627).
+char(p,23628).
+char(7,23629).
+char(0,23630).
+char(0,23631).
+char(6,23632).
+char(c,23633).
+char(c,23634).
+char(c,23635).
+char(c,23636).
+char(c,23637).
+char(c,23638).
+char(m,23639).
+char(3,23640).
+char(2,23641).
+char(2,23642).
+char(8,23643).
+char(p,23644).
+char(2,23645).
+char(5,23646).
+char(1,23647).
+char(7,23648).
+char(c,23649).
+char(c,23650).
+char(c,23651).
+char(p,23652).
+char(5,23653).
+char(6,23654).
+char(5,23655).
+char(8,23656).
+char(c,23657).
+char(c,23658).
+char(m,23659).
+char(6,23660).
+char(5,23661).
+char(1,23662).
+char(8,23663).
+char(p,23664).
+char(o,23665).
+char(m,23666).
+char(o,23667).
+char(1,23668).
+char(1,23669).
+char(3,23670).
+char(8,23671).
+char(c,23672).
+char(p,23673).
+char(o,23674).
+char(m,23675).
+char(3,23676).
+char(5,23677).
+char(1,23678).
+char(6,23679).
+char(c,23680).
+char(c,23681).
+char(c,23682).
+char(c,23683).
+char(m,23684).
+char(1,23685).
+char(6,23686).
+char(5,23687).
+char(2,23688).
+char(c,23689).
+char(m,23690).
+char(o,23691).
+char(p,23692).
+char(o,23693).
+char(p,23694).
+char(o,23695).
+char(4,23696).
+char(6,23697).
+char(6,23698).
+char(1,23699).
+char(c,23700).
+char(c,23701).
+char(c,23702).
+char(c,23703).
+char(c,23704).
+char(c,23705).
+char(m,23706).
+char(o,23707).
+char(p,23708).
+char(o,23709).
+char(3,23710).
+char(2,23711).
+char(5,23712).
+char(c,23713).
+char(c,23714).
+char(c,23715).
+char(c,23716).
+char(m,23717).
+char(3,23718).
+char(3,23719).
+char(1,23720).
+char(c,23721).
+char(m,23722).
+char(o,23723).
+char(p,23724).
+char(9,23725).
+char(7,23726).
+char(5,23727).
+char(4,23728).
+char(c,23729).
+char(c,23730).
+char(m,23731).
+char(o,23732).
+char(9,23733).
+char(6,23734).
+char(2,23735).
+char(9,23736).
+char(c,23737).
+char(m,23738).
+char(1,23739).
+char(6,23740).
+char(7,23741).
+char(4,23742).
+char(m,23743).
+char(o,23744).
+char(m,23745).
+char(6,23746).
+char(7,23747).
+char(8,23748).
+char(4,23749).
+char(p,23750).
+char(5,23751).
+char(8,23752).
+char(8,23753).
+char(5,23754).
+char(m,23755).
+char(o,23756).
+char(o,23757).
+char(p,23758).
+char(o,23759).
+char(m,23760).
+char(o,23761).
+char(p,23762).
+char(o,23763).
+char(6,23764).
+char(2,23765).
+char(5,23766).
+char(3,23767).
+char(c,23768).
+char(m,23769).
+char(6,23770).
+char(5,23771).
+char(5,23772).
+char(6,23773).
+char(c,23774).
+char(p,23775).
+char(o,23776).
+char(m,23777).
+char(5,23778).
+char(1,23779).
+char(3,23780).
+char(c,23781).
+char(m,23782).
+char(o,23783).
+char(3,23784).
+char(6,23785).
+char(3,23786).
+char(c,23787).
+char(c,23788).
+char(c,23789).
+char(c,23790).
+char(m,23791).
+char(o,23792).
+char(o,23793).
+char(o,23794).
+char(p,23795).
+char(1,23796).
+char(5,23797).
+char(2,23798).
+char(6,23799).
+char(p,23800).
+char(1,23801).
+char(1,23802).
+char(7,23803).
+char(5,23804).
+char(c,23805).
+char(p,23806).
+char(o,23807).
+char(m,23808).
+char(8,23809).
+char(4,23810).
+char(1,23811).
+char(6,23812).
+char(c,23813).
+char(p,23814).
+char(o,23815).
+char(p,23816).
+char(3,23817).
+char(6,23818).
+char(5,23819).
+char(6,23820).
+char(m,23821).
+char(o,23822).
+char(p,23823).
+char(o,23824).
+char(m,23825).
+char(5,23826).
+char(4,23827).
+char(6,23828).
+char(2,23829).
+char(c,23830).
+char(m,23831).
+char(3,23832).
+char(6,23833).
+char(0,23834).
+char(m,23835).
+char(o,23836).
+char(p,23837).
+char(6,23838).
+char(9,23839).
+char(0,23840).
+char(7,23841).
+char(c,23842).
+char(m,23843).
+char(1,23844).
+char(4,23845).
+char(2,23846).
+char(9,23847).
+char(m,23848).
+char(7,23849).
+char(1,23850).
+char(9,23851).
+char(5,23852).
+char(m,23853).
+char(o,23854).
+char(m,23855).
+char(2,23856).
+char(8,23857).
+char(4,23858).
+char(0,23859).
+char(m,23860).
+char(o,23861).
+char(m,23862).
+char(1,23863).
+char(9,23864).
+char(3,23865).
+char(9,23866).
+char(m,23867).
+char(o,23868).
+char(o,23869).
+char(m,23870).
+char(7,23871).
+char(2,23872).
+char(9,23873).
+char(6,23874).
+char(m,23875).
+char(o,23876).
+char(m,23877).
+char(8,23878).
+char(4,23879).
+char(0,23880).
+char(7,23881).
+char(c,23882).
+char(c,23883).
+char(m,23884).
+char(1,23885).
+char(9,23886).
+char(7,23887).
+char(3,23888).
+char(p,23889).
+char(4,23890).
+char(6,23891).
+char(8,23892).
+char(0,23893).
+char(m,23894).
+char(o,23895).
+char(2,23896).
+char(9,23897).
+char(3,23898).
+char(c,23899).
+char(c,23900).
+char(c,23901).
+char(c,23902).
+char(c,23903).
+char(c,23904).
+char(p,23905).
+char(8,23906).
+char(4,23907).
+char(7,23908).
+char(6,23909).
+char(c,23910).
+char(c,23911).
+char(m,23912).
+char(4,23913).
+char(4,23914).
+char(5,23915).
+char(5,23916).
+char(m,23917).
+char(6,23918).
+char(6,23919).
+char(8,23920).
+char(1,23921).
+char(c,23922).
+char(c,23923).
+char(c,23924).
+char(c,23925).
+char(c,23926).
+char(m,23927).
+char(o,23928).
+char(1,23929).
+char(9,23930).
+char(4,23931).
+char(9,23932).
+char(c,23933).
+char(c,23934).
+char(c,23935).
+char(c,23936).
+char(c,23937).
+char(c,23938).
+char(m,23939).
+char(o,23940).
+char(1,23941).
+char(6,23942).
+char(6,23943).
+char(c,23944).
+char(c,23945).
+char(m,23946).
+char(o,23947).
+char(m,23948).
+char(3,23949).
+char(2,23950).
+char(0,23951).
+char(c,23952).
+char(c,23953).
+char(p,23954).
+char(o,23955).
+char(p,23956).
+char(9,23957).
+char(7,23958).
+char(5,23959).
+char(3,23960).
+char(c,23961).
+char(c,23962).
+char(m,23963).
+char(o,23964).
+char(m,23965).
+char(5,23966).
+char(5,23967).
+char(0,23968).
+char(0,23969).
+char(p,23970).
+char(2,23971).
+char(5,23972).
+char(0,23973).
+char(3,23974).
+char(c,23975).
+char(c,23976).
+char(m,23977).
+char(o,23978).
+char(p,23979).
+char(o,23980).
+char(m,23981).
+char(7,23982).
+char(9,23983).
+char(4,23984).
+char(2,23985).
+char(m,23986).
+char(o,23987).
+char(p,23988).
+char(o,23989).
+char(m,23990).
+char(o,23991).
+char(m,23992).
+char(1,23993).
+char(0,23994).
+char(6,23995).
+char(7,23996).
+char(p,23997).
+char(o,23998).
+char(m,23999).
+char(2,24000).
+char(9,24001).
+char(4,24002).
+char(3,24003).
+char(c,24004).
+char(p,24005).
+char(o,24006).
+char(9,24007).
+char(6,24008).
+char(3,24009).
+char(3,24010).
+char(c,24011).
+char(m,24012).
+char(2,24013).
+char(8,24014).
+char(4,24015).
+char(0,24016).
+char(c,24017).
+char(p,24018).
+char(o,24019).
+char(m,24020).
+char(o,24021).
+char(o,24022).
+char(o,24023).
+char(p,24024).
+char(o,24025).
+char(o,24026).
+char(3,24027).
+char(2,24028).
+char(8,24029).
+char(7,24030).
+char(c,24031).
+char(p,24032).
+char(o,24033).
+char(m,24034).
+char(o,24035).
+char(o,24036).
+char(p,24037).
+char(o,24038).
+char(o,24039).
+char(m,24040).
+char(3,24041).
+char(1,24042).
+char(3,24043).
+char(5,24044).
+char(p,24045).
+char(7,24046).
+char(0,24047).
+char(3,24048).
+char(8,24049).
+char(m,24050).
+char(5,24051).
+char(0,24052).
+char(8,24053).
+char(1,24054).
+char(c,24055).
+char(c,24056).
+char(c,24057).
+char(c,24058).
+char(c,24059).
+char(m,24060).
+char(o,24061).
+char(p,24062).
+char(o,24063).
+char(m,24064).
+char(o,24065).
+char(5,24066).
+char(4,24067).
+char(6,24068).
+char(c,24069).
+char(c,24070).
+char(c,24071).
+char(c,24072).
+char(c,24073).
+char(c,24074).
+char(c,24075).
+char(c,24076).
+char(c,24077).
+char(c,24078).
+char(c,24079).
+char(p,24080).
+char(o,24081).
+char(m,24082).
+char(o,24083).
+char(p,24084).
+char(o,24085).
+char(m,24086).
+char(o,24087).
+char(p,24088).
+char(5,24089).
+char(8,24090).
+char(1,24091).
+char(0,24092).
+char(c,24093).
+char(c,24094).
+char(c,24095).
+char(c,24096).
+char(c,24097).
+char(c,24098).
+char(m,24099).
+char(o,24100).
+char(p,24101).
+char(1,24102).
+char(5,24103).
+char(8,24104).
+char(1,24105).
+char(c,24106).
+char(c,24107).
+char(c,24108).
+char(p,24109).
+char(o,24110).
+char(p,24111).
+char(2,24112).
+char(4,24113).
+char(3,24114).
+char(3,24115).
+char(m,24116).
+char(8,24117).
+char(7,24118).
+char(8,24119).
+char(7,24120).
+char(c,24121).
+char(c,24122).
+char(m,24123).
+char(o,24124).
+char(o,24125).
+char(p,24126).
+char(o,24127).
+char(m,24128).
+char(o,24129).
+char(p,24130).
+char(7,24131).
+char(3,24132).
+char(9,24133).
+char(9,24134).
+char(c,24135).
+char(m,24136).
+char(3,24137).
+char(2,24138).
+char(1,24139).
+char(3,24140).
+char(p,24141).
+char(o,24142).
+char(o,24143).
+char(p,24144).
+char(o,24145).
+char(m,24146).
+char(o,24147).
+char(m,24148).
+char(o,24149).
+char(m,24150).
+char(o,24151).
+char(m,24152).
+char(o,24153).
+char(p,24154).
+char(4,24155).
+char(3,24156).
+char(9,24157).
+char(7,24158).
+char(p,24159).
+char(o,24160).
+char(p,24161).
+char(o,24162).
+char(m,24163).
+char(o,24164).
+char(m,24165).
+char(4,24166).
+char(8,24167).
+char(1,24168).
+char(6,24169).
+char(c,24170).
+char(m,24171).
+char(4,24172).
+char(0,24173).
+char(7,24174).
+char(3,24175).
+char(c,24176).
+char(c,24177).
+char(c,24178).
+char(c,24179).
+char(c,24180).
+char(p,24181).
+char(o,24182).
+char(o,24183).
+char(o,24184).
+char(7,24185).
+char(8,24186).
+char(8,24187).
+char(7,24188).
+char(c,24189).
+char(c,24190).
+char(p,24191).
+char(o,24192).
+char(2,24193).
+char(4,24194).
+char(7,24195).
+char(6,24196).
+char(p,24197).
+char(o,24198).
+char(o,24199).
+char(p,24200).
+char(6,24201).
+char(3,24202).
+char(9,24203).
+char(6,24204).
+char(m,24205).
+char(o,24206).
+char(m,24207).
+char(o,24208).
+char(m,24209).
+char(o,24210).
+char(p,24211).
+char(o,24212).
+char(o,24213).
+char(o,24214).
+char(8,24215).
+char(8,24216).
+char(3,24217).
+char(2,24218).
+char(c,24219).
+char(c,24220).
+char(p,24221).
+char(o,24222).
+char(m,24223).
+char(o,24224).
+char(m,24225).
+char(3,24226).
+char(9,24227).
+char(8,24228).
+char(4,24229).
+char(p,24230).
+char(3,24231).
+char(2,24232).
+char(0,24233).
+char(8,24234).
+char(m,24235).
+char(4,24236).
+char(7,24237).
+char(0,24238).
+char(5,24239).
+char(m,24240).
+char(2,24241).
+char(2,24242).
+char(0,24243).
+char(5,24244).
+char(p,24245).
+char(o,24246).
+char(2,24247).
+char(1,24248).
+char(8,24249).
+char(7,24250).
+char(c,24251).
+char(p,24252).
+char(o,24253).
+char(m,24254).
+char(2,24255).
+char(4,24256).
+char(6,24257).
+char(m,24258).
+char(o,24259).
+char(p,24260).
+char(9,24261).
+char(7,24262).
+char(5,24263).
+char(6,24264).
+char(p,24265).
+char(6,24266).
+char(2,24267).
+char(6,24268).
+char(c,24269).
+char(p,24270).
+char(6,24271).
+char(6,24272).
+char(1,24273).
+char(4,24274).
+char(m,24275).
+char(o,24276).
+char(m,24277).
+char(o,24278).
+char(m,24279).
+char(7,24280).
+char(4,24281).
+char(6,24282).
+char(5,24283).
+char(c,24284).
+char(p,24285).
+char(o,24286).
+char(o,24287).
+char(p,24288).
+char(o,24289).
+char(o,24290).
+char(m,24291).
+char(7,24292).
+char(0,24293).
+char(5,24294).
+char(c,24295).
+char(c,24296).
+char(c,24297).
+char(p,24298).
+char(8,24299).
+char(7,24300).
+char(8,24301).
+char(9,24302).
+char(c,24303).
+char(c,24304).
+char(p,24305).
+char(o,24306).
+char(m,24307).
+char(o,24308).
+char(o,24309).
+char(o,24310).
+char(m,24311).
+char(o,24312).
+char(o,24313).
+char(o,24314).
+char(m,24315).
+char(1,24316).
+char(1,24317).
+char(5,24318).
+char(7,24319).
+char(c,24320).
+char(c,24321).
+char(c,24322).
+char(p,24323).
+char(o,24324).
+char(m,24325).
+char(o,24326).
+char(p,24327).
+char(6,24328).
+char(9,24329).
+char(8,24330).
+char(2,24331).
+char(c,24332).
+char(c,24333).
+char(m,24334).
+char(o,24335).
+char(p,24336).
+char(o,24337).
+char(1,24338).
+char(6,24339).
+char(2,24340).
+char(9,24341).
+char(c,24342).
+char(m,24343).
+char(6,24344).
+char(0,24345).
+char(7,24346).
+char(3,24347).
+char(c,24348).
+char(p,24349).
+char(6,24350).
+char(7,24351).
+char(0,24352).
+char(m,24353).
+char(o,24354).
+char(o,24355).
+char(m,24356).
+char(o,24357).
+char(m,24358).
+char(6,24359).
+char(6,24360).
+char(8,24361).
+char(6,24362).
+char(c,24363).
+char(p,24364).
+char(o,24365).
+char(m,24366).
+char(o,24367).
+char(o,24368).
+char(p,24369).
+char(9,24370).
+char(1,24371).
+char(5,24372).
+char(3,24373).
+char(m,24374).
+char(o,24375).
+char(p,24376).
+char(8,24377).
+char(7,24378).
+char(6,24379).
+char(6,24380).
+char(c,24381).
+char(c,24382).
+char(p,24383).
+char(7,24384).
+char(5,24385).
+char(9,24386).
+char(7,24387).
+char(m,24388).
+char(o,24389).
+char(o,24390).
+char(p,24391).
+char(4,24392).
+char(4,24393).
+char(2,24394).
+char(m,24395).
+char(6,24396).
+char(3,24397).
+char(9,24398).
+char(c,24399).
+char(c,24400).
+char(p,24401).
+char(o,24402).
+char(4,24403).
+char(3,24404).
+char(9,24405).
+char(4,24406).
+char(p,24407).
+char(5,24408).
+char(2,24409).
+char(7,24410).
+char(5,24411).
+char(c,24412).
+char(m,24413).
+char(3,24414).
+char(2,24415).
+char(7,24416).
+char(4,24417).
+char(m,24418).
+char(o,24419).
+char(m,24420).
+char(o,24421).
+char(m,24422).
+char(4,24423).
+char(7,24424).
+char(3,24425).
+char(4,24426).
+char(c,24427).
+char(c,24428).
+char(c,24429).
+char(m,24430).
+char(7,24431).
+char(0,24432).
+char(4,24433).
+char(9,24434).
+char(c,24435).
+char(m,24436).
+char(3,24437).
+char(7,24438).
+char(4,24439).
+char(7,24440).
+char(m,24441).
+char(o,24442).
+char(m,24443).
+char(1,24444).
+char(2,24445).
+char(1,24446).
+char(8,24447).
+char(p,24448).
+char(1,24449).
+char(3,24450).
+char(8,24451).
+char(3,24452).
+char(c,24453).
+char(m,24454).
+char(8,24455).
+char(0,24456).
+char(2,24457).
+char(8,24458).
+char(c,24459).
+char(p,24460).
+char(o,24461).
+char(p,24462).
+char(o,24463).
+char(p,24464).
+char(o,24465).
+char(p,24466).
+char(9,24467).
+char(1,24468).
+char(4,24469).
+char(7,24470).
+char(c,24471).
+char(m,24472).
+char(3,24473).
+char(6,24474).
+char(3,24475).
+char(0,24476).
+char(c,24477).
+char(c,24478).
+char(p,24479).
+char(9,24480).
+char(8,24481).
+char(3,24482).
+char(0,24483).
+char(m,24484).
+char(o,24485).
+char(o,24486).
+char(m,24487).
+char(o,24488).
+char(4,24489).
+char(6,24490).
+char(2,24491).
+char(5,24492).
+char(c,24493).
+char(p,24494).
+char(o,24495).
+char(p,24496).
+char(9,24497).
+char(3,24498).
+char(5,24499).
+char(3,24500).
+char(m,24501).
+char(o,24502).
+char(p,24503).
+char(6,24504).
+char(4,24505).
+char(4,24506).
+char(0,24507).
+char(c,24508).
+char(c,24509).
+char(c,24510).
+char(m,24511).
+char(5,24512).
+char(1,24513).
+char(8,24514).
+char(6,24515).
+char(c,24516).
+char(c,24517).
+char(c,24518).
+char(p,24519).
+char(6,24520).
+char(4,24521).
+char(3,24522).
+char(0,24523).
+char(m,24524).
+char(o,24525).
+char(p,24526).
+char(6,24527).
+char(6,24528).
+char(5,24529).
+char(3,24530).
+char(c,24531).
+char(c,24532).
+char(c,24533).
+char(c,24534).
+char(c,24535).
+char(p,24536).
+char(o,24537).
+char(p,24538).
+char(o,24539).
+char(2,24540).
+char(1,24541).
+char(3,24542).
+char(2,24543).
+char(p,24544).
+char(2,24545).
+char(9,24546).
+char(6,24547).
+char(7,24548).
+char(c,24549).
+char(c,24550).
+char(m,24551).
+char(o,24552).
+char(9,24553).
+char(7,24554).
+char(1,24555).
+char(7,24556).
+char(c,24557).
+char(m,24558).
+char(6,24559).
+char(1,24560).
+char(7,24561).
+char(c,24562).
+char(m,24563).
+char(5,24564).
+char(3,24565).
+char(3,24566).
+char(7,24567).
+char(c,24568).
+char(c,24569).
+char(c,24570).
+char(c,24571).
+char(c,24572).
+char(m,24573).
+char(o,24574).
+char(p,24575).
+char(7,24576).
+char(5,24577).
+char(6,24578).
+char(9,24579).
+char(c,24580).
+char(m,24581).
+char(3,24582).
+char(6,24583).
+char(0,24584).
+char(9,24585).
+char(p,24586).
+char(3,24587).
+char(7,24588).
+char(8,24589).
+char(3,24590).
+char(p,24591).
+char(7,24592).
+char(8,24593).
+char(4,24594).
+char(5,24595).
+char(p,24596).
+char(3,24597).
+char(8,24598).
+char(9,24599).
+char(7,24600).
+char(c,24601).
+char(m,24602).
+char(4,24603).
+char(1,24604).
+char(9,24605).
+char(8,24606).
+char(p,24607).
+char(4,24608).
+char(5,24609).
+char(2,24610).
+char(1,24611).
+char(c,24612).
+char(c,24613).
+char(p,24614).
+char(6,24615).
+char(0,24616).
+char(6,24617).
+char(4,24618).
+char(p,24619).
+char(8,24620).
+char(3,24621).
+char(2,24622).
+char(2,24623).
+char(c,24624).
+char(c,24625).
+char(c,24626).
+char(c,24627).
+char(p,24628).
+char(o,24629).
+char(p,24630).
+char(o,24631).
+char(p,24632).
+char(4,24633).
+char(1,24634).
+char(0,24635).
+char(1,24636).
+char(p,24637).
+char(o,24638).
+char(o,24639).
+char(m,24640).
+char(1,24641).
+char(1,24642).
+char(4,24643).
+char(8,24644).
+char(c,24645).
+char(c,24646).
+char(p,24647).
+char(o,24648).
+char(4,24649).
+char(3,24650).
+char(4,24651).
+char(6,24652).
+char(c,24653).
+char(m,24654).
+char(o,24655).
+char(m,24656).
+char(2,24657).
+char(5,24658).
+char(7,24659).
+char(8,24660).
+char(p,24661).
+char(o,24662).
+char(o,24663).
+char(o,24664).
+char(o,24665).
+char(p,24666).
+char(7,24667).
+char(1,24668).
+char(5,24669).
+char(0,24670).
+char(p,24671).
+char(o,24672).
+char(2,24673).
+char(4,24674).
+char(5,24675).
+char(6,24676).
+char(p,24677).
+char(o,24678).
+char(m,24679).
+char(o,24680).
+char(p,24681).
+char(o,24682).
+char(m,24683).
+char(4,24684).
+char(6,24685).
+char(6,24686).
+char(3,24687).
+char(c,24688).
+char(m,24689).
+char(o,24690).
+char(p,24691).
+char(o,24692).
+char(5,24693).
+char(6,24694).
+char(4,24695).
+char(5,24696).
+char(c,24697).
+char(c,24698).
+char(p,24699).
+char(o,24700).
+char(m,24701).
+char(o,24702).
+char(m,24703).
+char(1,24704).
+char(0,24705).
+char(2,24706).
+char(5,24707).
+char(c,24708).
+char(p,24709).
+char(o,24710).
+char(m,24711).
+char(o,24712).
+char(o,24713).
+char(p,24714).
+char(o,24715).
+char(m,24716).
+char(o,24717).
+char(p,24718).
+char(6,24719).
+char(2,24720).
+char(2,24721).
+char(3,24722).
+char(m,24723).
+char(o,24724).
+char(9,24725).
+char(6,24726).
+char(4,24727).
+char(1,24728).
+char(c,24729).
+char(c,24730).
+char(p,24731).
+char(o,24732).
+char(p,24733).
+char(3,24734).
+char(8,24735).
+char(7,24736).
+char(1,24737).
+char(c,24738).
+char(p,24739).
+char(o,24740).
+char(m,24741).
+char(6,24742).
+char(6,24743).
+char(1,24744).
+char(9,24745).
+char(m,24746).
+char(2,24747).
+char(6,24748).
+char(6,24749).
+char(7,24750).
+char(m,24751).
+char(8,24752).
+char(2,24753).
+char(1,24754).
+char(1,24755).
+char(m,24756).
+char(4,24757).
+char(6,24758).
+char(7,24759).
+char(1,24760).
+char(c,24761).
+char(c,24762).
+char(p,24763).
+char(4,24764).
+char(4,24765).
+char(8,24766).
+char(7,24767).
+char(c,24768).
+char(p,24769).
+char(o,24770).
+char(p,24771).
+char(6,24772).
+char(3,24773).
+char(8,24774).
+char(4,24775).
+char(p,24776).
+char(o,24777).
+char(m,24778).
+char(o,24779).
+char(9,24780).
+char(5,24781).
+char(8,24782).
+char(8,24783).
+char(c,24784).
+char(c,24785).
+char(c,24786).
+char(c,24787).
+char(c,24788).
+char(m,24789).
+char(o,24790).
+char(p,24791).
+char(8,24792).
+char(8,24793).
+char(1,24794).
+char(1,24795).
+char(m,24796).
+char(o,24797).
+char(o,24798).
+char(p,24799).
+char(o,24800).
+char(p,24801).
+char(9,24802).
+char(0,24803).
+char(8,24804).
+char(6,24805).
+char(c,24806).
+char(p,24807).
+char(o,24808).
+char(o,24809).
+char(p,24810).
+char(5,24811).
+char(0,24812).
+char(1,24813).
+char(5,24814).
+char(p,24815).
+char(o,24816).
+char(m,24817).
+char(9,24818).
+char(1,24819).
+char(3,24820).
+char(9,24821).
+char(c,24822).
+char(c,24823).
+char(m,24824).
+char(o,24825).
+char(p,24826).
+char(o,24827).
+char(m,24828).
+char(3,24829).
+char(7,24830).
+char(5,24831).
+char(5,24832).
+char(c,24833).
+char(c,24834).
+char(c,24835).
+char(m,24836).
+char(o,24837).
+char(m,24838).
+char(6,24839).
+char(1,24840).
+char(0,24841).
+char(6,24842).
+char(c,24843).
+char(m,24844).
+char(o,24845).
+char(m,24846).
+char(o,24847).
+char(p,24848).
+char(o,24849).
+char(p,24850).
+char(8,24851).
+char(5,24852).
+char(5,24853).
+char(0,24854).
+char(c,24855).
+char(c,24856).
+char(c,24857).
+char(m,24858).
+char(o,24859).
+char(p,24860).
+char(o,24861).
+char(m,24862).
+char(o,24863).
+char(o,24864).
+char(p,24865).
+char(o,24866).
+char(m,24867).
+char(7,24868).
+char(7,24869).
+char(0,24870).
+char(3,24871).
+char(c,24872).
+char(c,24873).
+char(c,24874).
+char(c,24875).
+char(c,24876).
+char(c,24877).
+char(m,24878).
+char(5,24879).
+char(7,24880).
+char(1,24881).
+char(5,24882).
+char(c,24883).
+char(m,24884).
+char(o,24885).
+char(m,24886).
+char(o,24887).
+char(p,24888).
+char(7,24889).
+char(5,24890).
+char(1,24891).
+char(m,24892).
+char(6,24893).
+char(7,24894).
+char(5,24895).
+char(p,24896).
+char(1,24897).
+char(1,24898).
+char(8,24899).
+char(5,24900).
+char(c,24901).
+char(p,24902).
+char(7,24903).
+char(7,24904).
+char(2,24905).
+char(8,24906).
+char(c,24907).
+char(c,24908).
+char(c,24909).
+char(c,24910).
+char(c,24911).
+char(c,24912).
+char(m,24913).
+char(4,24914).
+char(0,24915).
+char(5,24916).
+char(6,24917).
+char(p,24918).
+char(3,24919).
+char(7,24920).
+char(2,24921).
+char(p,24922).
+char(o,24923).
+char(7,24924).
+char(2,24925).
+char(2,24926).
+char(3,24927).
+char(c,24928).
+char(c,24929).
+char(m,24930).
+char(7,24931).
+char(2,24932).
+char(7,24933).
+char(6,24934).
+char(p,24935).
+char(o,24936).
+char(p,24937).
+char(o,24938).
+char(p,24939).
+char(o,24940).
+char(2,24941).
+char(8,24942).
+char(0,24943).
+char(2,24944).
+char(c,24945).
+char(c,24946).
+char(c,24947).
+char(m,24948).
+char(o,24949).
+char(o,24950).
+char(p,24951).
+char(6,24952).
+char(3,24953).
+char(2,24954).
+char(1,24955).
+char(c,24956).
+char(c,24957).
+char(p,24958).
+char(o,24959).
+char(p,24960).
+char(9,24961).
+char(4,24962).
+char(8,24963).
+char(6,24964).
+char(m,24965).
+char(o,24966).
+char(m,24967).
+char(1,24968).
+char(5,24969).
+char(7,24970).
+char(4,24971).
+char(p,24972).
+char(4,24973).
+char(1,24974).
+char(9,24975).
+char(8,24976).
+char(c,24977).
+char(c,24978).
+char(c,24979).
+char(m,24980).
+char(o,24981).
+char(o,24982).
+char(o,24983).
+char(m,24984).
+char(4,24985).
+char(6,24986).
+char(0,24987).
+char(7,24988).
+char(p,24989).
+char(o,24990).
+char(p,24991).
+char(o,24992).
+char(3,24993).
+char(7,24994).
+char(1,24995).
+char(5,24996).
+char(c,24997).
+char(c,24998).
+char(c,24999).
+char(m,25000).
+char(o,25001).
+char(m,25002).
+char(6,25003).
+char(0,25004).
+char(8,25005).
+char(4,25006).
+char(p,25007).
+char(3,25008).
+char(4,25009).
+char(8,25010).
+char(2,25011).
+char(c,25012).
+char(c,25013).
+char(p,25014).
+char(9,25015).
+char(8,25016).
+char(6,25017).
+char(9,25018).
+char(m,25019).
+char(7,25020).
+char(6,25021).
+char(4,25022).
+char(8,25023).
+char(p,25024).
+char(o,25025).
+char(m,25026).
+char(o,25027).
+char(p,25028).
+char(o,25029).
+char(m,25030).
+char(5,25031).
+char(5,25032).
+char(3,25033).
+char(6,25034).
+char(p,25035).
+char(7,25036).
+char(6,25037).
+char(7,25038).
+char(3,25039).
+char(c,25040).
+char(c,25041).
+char(c,25042).
+char(m,25043).
+char(o,25044).
+char(p,25045).
+char(o,25046).
+char(m,25047).
+char(9,25048).
+char(0,25049).
+char(5,25050).
+char(8,25051).
+char(p,25052).
+char(o,25053).
+char(m,25054).
+char(1,25055).
+char(1,25056).
+char(3,25057).
+char(0,25058).
+char(p,25059).
+char(o,25060).
+char(m,25061).
+char(o,25062).
+char(p,25063).
+char(o,25064).
+char(p,25065).
+char(o,25066).
+char(m,25067).
+char(o,25068).
+char(p,25069).
+char(o,25070).
+char(m,25071).
+char(o,25072).
+char(p,25073).
+char(9,25074).
+char(6,25075).
+char(8,25076).
+char(5,25077).
+char(c,25078).
+char(c,25079).
+char(m,25080).
+char(o,25081).
+char(o,25082).
+char(8,25083).
+char(3,25084).
+char(5,25085).
+char(3,25086).
+char(p,25087).
+char(o,25088).
+char(p,25089).
+char(o,25090).
+char(m,25091).
+char(o,25092).
+char(p,25093).
+char(2,25094).
+char(1,25095).
+char(1,25096).
+char(3,25097).
+char(m,25098).
+char(o,25099).
+char(3,25100).
+char(0,25101).
+char(0,25102).
+char(2,25103).
+char(c,25104).
+char(c,25105).
+char(p,25106).
+char(o,25107).
+char(m,25108).
+char(9,25109).
+char(0,25110).
+char(0,25111).
+char(5,25112).
+char(p,25113).
+char(6,25114).
+char(4,25115).
+char(9,25116).
+char(0,25117).
+char(c,25118).
+char(c,25119).
+char(p,25120).
+char(6,25121).
+char(3,25122).
+char(6,25123).
+char(3,25124).
+char(c,25125).
+char(c,25126).
+char(m,25127).
+char(7,25128).
+char(3,25129).
+char(5,25130).
+char(7,25131).
+char(m,25132).
+char(o,25133).
+char(p,25134).
+char(o,25135).
+char(p,25136).
+char(2,25137).
+char(8,25138).
+char(1,25139).
+char(8,25140).
+char(c,25141).
+char(c,25142).
+char(c,25143).
+char(c,25144).
+char(p,25145).
+char(o,25146).
+char(o,25147).
+char(o,25148).
+char(o,25149).
+char(p,25150).
+char(o,25151).
+char(p,25152).
+char(7,25153).
+char(1,25154).
+char(7,25155).
+char(2,25156).
+char(m,25157).
+char(o,25158).
+char(p,25159).
+char(8,25160).
+char(6,25161).
+char(1,25162).
+char(7,25163).
+char(c,25164).
+char(c,25165).
+char(p,25166).
+char(o,25167).
+char(p,25168).
+char(o,25169).
+char(p,25170).
+char(2,25171).
+char(2,25172).
+char(0,25173).
+char(5,25174).
+char(m,25175).
+char(o,25176).
+char(p,25177).
+char(o,25178).
+char(o,25179).
+char(o,25180).
+char(p,25181).
+char(8,25182).
+char(8,25183).
+char(9,25184).
+char(1,25185).
+char(c,25186).
+char(m,25187).
+char(1,25188).
+char(7,25189).
+char(3,25190).
+char(1,25191).
+char(c,25192).
+char(m,25193).
+char(4,25194).
+char(6,25195).
+char(0,25196).
+char(6,25197).
+char(m,25198).
+char(o,25199).
+char(m,25200).
+char(3,25201).
+char(3,25202).
+char(9,25203).
+char(0,25204).
+char(p,25205).
+char(o,25206).
+char(p,25207).
+char(o,25208).
+char(p,25209).
+char(o,25210).
+char(p,25211).
+char(o,25212).
+char(o,25213).
+char(m,25214).
+char(1,25215).
+char(8,25216).
+char(5,25217).
+char(4,25218).
+char(c,25219).
+char(m,25220).
+char(6,25221).
+char(0,25222).
+char(7,25223).
+char(9,25224).
+char(c,25225).
+char(c,25226).
+char(c,25227).
+char(c,25228).
+char(c,25229).
+char(m,25230).
+char(6,25231).
+char(6,25232).
+char(5,25233).
+char(6,25234).
+char(m,25235).
+char(7,25236).
+char(7,25237).
+char(1,25238).
+char(3,25239).
+char(p,25240).
+char(o,25241).
+char(p,25242).
+char(8,25243).
+char(8,25244).
+char(6,25245).
+char(9,25246).
+char(c,25247).
+char(p,25248).
+char(7,25249).
+char(7,25250).
+char(2,25251).
+char(1,25252).
+char(c,25253).
+char(c,25254).
+char(m,25255).
+char(o,25256).
+char(m,25257).
+char(o,25258).
+char(p,25259).
+char(3,25260).
+char(4,25261).
+char(1,25262).
+char(8,25263).
+char(c,25264).
+char(c,25265).
+char(p,25266).
+char(6,25267).
+char(3,25268).
+char(5,25269).
+char(5,25270).
+char(p,25271).
+char(o,25272).
+char(p,25273).
+char(4,25274).
+char(3,25275).
+char(3,25276).
+char(8,25277).
+char(c,25278).
+char(m,25279).
+char(o,25280).
+char(m,25281).
+char(1,25282).
+char(0,25283).
+char(6,25284).
+char(4,25285).
+char(c,25286).
+char(m,25287).
+char(5,25288).
+char(1,25289).
+char(4,25290).
+char(0,25291).
+char(p,25292).
+char(o,25293).
+char(9,25294).
+char(4,25295).
+char(8,25296).
+char(7,25297).
+char(c,25298).
+char(m,25299).
+char(9,25300).
+char(0,25301).
+char(4,25302).
+char(6,25303).
+char(p,25304).
+char(o,25305).
+char(m,25306).
+char(7,25307).
+char(3,25308).
+char(5,25309).
+char(0,25310).
+char(c,25311).
+char(c,25312).
+char(c,25313).
+char(m,25314).
+char(o,25315).
+char(m,25316).
+char(o,25317).
+char(m,25318).
+char(o,25319).
+char(m,25320).
+char(4,25321).
+char(6,25322).
+char(8,25323).
+char(0,25324).
+char(m,25325).
+char(9,25326).
+char(2,25327).
+char(0,25328).
+char(5,25329).
+char(c,25330).
+char(p,25331).
+char(o,25332).
+char(o,25333).
+char(p,25334).
+char(6,25335).
+char(0,25336).
+char(4,25337).
+char(4,25338).
+char(c,25339).
+char(c,25340).
+char(p,25341).
+char(o,25342).
+char(p,25343).
+char(5,25344).
+char(3,25345).
+char(1,25346).
+char(1,25347).
+char(m,25348).
+char(9,25349).
+char(5,25350).
+char(7,25351).
+char(5,25352).
+char(c,25353).
+char(c,25354).
+char(c,25355).
+char(m,25356).
+char(o,25357).
+char(m,25358).
+char(9,25359).
+char(8,25360).
+char(1,25361).
+char(p,25362).
+char(5,25363).
+char(8,25364).
+char(6,25365).
+char(5,25366).
+char(c,25367).
+char(p,25368).
+char(o,25369).
+char(p,25370).
+char(6,25371).
+char(1,25372).
+char(7,25373).
+char(7,25374).
+char(p,25375).
+char(5,25376).
+char(7,25377).
+char(3,25378).
+char(7,25379).
+char(c,25380).
+char(m,25381).
+char(5,25382).
+char(5,25383).
+char(2,25384).
+char(4,25385).
+char(c,25386).
+char(c,25387).
+char(c,25388).
+char(m,25389).
+char(5,25390).
+char(0,25391).
+char(2,25392).
+char(9,25393).
+char(c,25394).
+char(p,25395).
+char(o,25396).
+char(o,25397).
+char(6,25398).
+char(1,25399).
+char(4,25400).
+char(8,25401).
+char(p,25402).
+char(8,25403).
+char(7,25404).
+char(1,25405).
+char(4,25406).
+char(m,25407).
+char(o,25408).
+char(o,25409).
+char(7,25410).
+char(8,25411).
+char(8,25412).
+char(7,25413).
+char(c,25414).
+char(m,25415).
+char(9,25416).
+char(4,25417).
+char(9,25418).
+char(5,25419).
+char(c,25420).
+char(c,25421).
+char(c,25422).
+char(p,25423).
+char(2,25424).
+char(8,25425).
+char(1,25426).
+char(3,25427).
+char(c,25428).
+char(c,25429).
+char(p,25430).
+char(o,25431).
+char(m,25432).
+char(o,25433).
+char(5,25434).
+char(3,25435).
+char(9,25436).
+char(9,25437).
+char(m,25438).
+char(o,25439).
+char(m,25440).
+char(o,25441).
+char(m,25442).
+char(o,25443).
+char(m,25444).
+char(2,25445).
+char(0,25446).
+char(8,25447).
+char(9,25448).
+char(m,25449).
+char(o,25450).
+char(p,25451).
+char(7,25452).
+char(6,25453).
+char(1,25454).
+char(0,25455).
+char(p,25456).
+char(o,25457).
+char(p,25458).
+char(o,25459).
+char(m,25460).
+char(o,25461).
+char(m,25462).
+char(o,25463).
+char(o,25464).
+char(m,25465).
+char(6,25466).
+char(2,25467).
+char(3,25468).
+char(4,25469).
+char(c,25470).
+char(p,25471).
+char(o,25472).
+char(p,25473).
+char(4,25474).
+char(3,25475).
+char(4,25476).
+char(2,25477).
+char(c,25478).
+char(p,25479).
+char(o,25480).
+char(m,25481).
+char(o,25482).
+char(p,25483).
+char(o,25484).
+char(o,25485).
+char(p,25486).
+char(o,25487).
+char(8,25488).
+char(0,25489).
+char(9,25490).
+char(9,25491).
+char(c,25492).
+char(p,25493).
+char(o,25494).
+char(m,25495).
+char(1,25496).
+char(4,25497).
+char(6,25498).
+char(5,25499).
+char(c,25500).
+char(p,25501).
+char(o,25502).
+char(p,25503).
+char(o,25504).
+char(m,25505).
+char(5,25506).
+char(6,25507).
+char(0,25508).
+char(5,25509).
+char(c,25510).
+char(p,25511).
+char(9,25512).
+char(0,25513).
+char(2,25514).
+char(5,25515).
+char(p,25516).
+char(o,25517).
+char(p,25518).
+char(o,25519).
+char(2,25520).
+char(2,25521).
+char(0,25522).
+char(8,25523).
+char(c,25524).
+char(c,25525).
+char(m,25526).
+char(4,25527).
+char(4,25528).
+char(2,25529).
+char(1,25530).
+char(c,25531).
+char(p,25532).
+char(3,25533).
+char(9,25534).
+char(0,25535).
+char(8,25536).
+char(p,25537).
+char(o,25538).
+char(m,25539).
+char(o,25540).
+char(p,25541).
+char(7,25542).
+char(5,25543).
+char(5,25544).
+char(6,25545).
+char(c,25546).
+char(c,25547).
+char(c,25548).
+char(m,25549).
+char(o,25550).
+char(p,25551).
+char(o,25552).
+char(p,25553).
+char(o,25554).
+char(8,25555).
+char(7,25556).
+char(8,25557).
+char(9,25558).
+char(m,25559).
+char(6,25560).
+char(2,25561).
+char(4,25562).
+char(4,25563).
+char(p,25564).
+char(3,25565).
+char(2,25566).
+char(3,25567).
+char(9,25568).
+char(c,25569).
+char(c,25570).
+char(m,25571).
+char(o,25572).
+char(p,25573).
+char(8,25574).
+char(0,25575).
+char(2,25576).
+char(0,25577).
+char(c,25578).
+char(c,25579).
+char(m,25580).
+char(o,25581).
+char(p,25582).
+char(4,25583).
+char(0,25584).
+char(2,25585).
+char(6,25586).
+char(m,25587).
+char(5,25588).
+char(7,25589).
+char(7,25590).
+char(0,25591).
+char(c,25592).
+char(c,25593).
+char(c,25594).
+char(c,25595).
+char(m,25596).
+char(o,25597).
+char(o,25598).
+char(m,25599).
+char(o,25600).
+char(m,25601).
+char(o,25602).
+char(m,25603).
+char(5,25604).
+char(0,25605).
+char(3,25606).
+char(6,25607).
+char(m,25608).
+char(5,25609).
+char(9,25610).
+char(4,25611).
+char(2,25612).
+char(p,25613).
+char(o,25614).
+char(p,25615).
+char(o,25616).
+char(m,25617).
+char(o,25618).
+char(p,25619).
+char(7,25620).
+char(2,25621).
+char(8,25622).
+char(5,25623).
+char(m,25624).
+char(o,25625).
+char(m,25626).
+char(7,25627).
+char(6,25628).
+char(0,25629).
+char(7,25630).
+char(m,25631).
+char(4,25632).
+char(7,25633).
+char(5,25634).
+char(c,25635).
+char(c,25636).
+char(c,25637).
+char(m,25638).
+char(o,25639).
+char(p,25640).
+char(o,25641).
+char(p,25642).
+char(o,25643).
+char(6,25644).
+char(3,25645).
+char(2,25646).
+char(5,25647).
+char(c,25648).
+char(p,25649).
+char(3,25650).
+char(8,25651).
+char(5,25652).
+char(p,25653).
+char(2,25654).
+char(2,25655).
+char(7,25656).
+char(1,25657).
+char(m,25658).
+char(o,25659).
+char(9,25660).
+char(8,25661).
+char(3,25662).
+char(p,25663).
+char(4,25664).
+char(5,25665).
+char(2,25666).
+char(2,25667).
+char(c,25668).
+char(m,25669).
+char(5,25670).
+char(8,25671).
+char(0,25672).
+char(8,25673).
+char(c,25674).
+char(m,25675).
+char(o,25676).
+char(p,25677).
+char(o,25678).
+char(m,25679).
+char(5,25680).
+char(8,25681).
+char(6,25682).
+char(7,25683).
+char(c,25684).
+char(c,25685).
+char(p,25686).
+char(3,25687).
+char(1,25688).
+char(4,25689).
+char(7,25690).
+char(p,25691).
+char(2,25692).
+char(2,25693).
+char(2,25694).
+char(2,25695).
+char(p,25696).
+char(2,25697).
+char(4,25698).
+char(9,25699).
+char(1,25700).
+char(c,25701).
+char(m,25702).
+char(o,25703).
+char(1,25704).
+char(4,25705).
+char(1,25706).
+char(4,25707).
+char(p,25708).
+char(5,25709).
+char(7,25710).
+char(1,25711).
+char(6,25712).
+char(p,25713).
+char(4,25714).
+char(5,25715).
+char(8,25716).
+char(6,25717).
+char(c,25718).
+char(c,25719).
+char(m,25720).
+char(o,25721).
+char(p,25722).
+char(o,25723).
+char(m,25724).
+char(2,25725).
+char(2,25726).
+char(5,25727).
+char(5,25728).
+char(c,25729).
+char(m,25730).
+char(3,25731).
+char(1,25732).
+char(2,25733).
+char(c,25734).
+char(c,25735).
+char(p,25736).
+char(2,25737).
+char(5,25738).
+char(7,25739).
+char(5,25740).
+char(m,25741).
+char(7,25742).
+char(0,25743).
+char(0,25744).
+char(4,25745).
+char(c,25746).
+char(p,25747).
+char(o,25748).
+char(1,25749).
+char(0,25750).
+char(4,25751).
+char(9,25752).
+char(m,25753).
+char(3,25754).
+char(0,25755).
+char(8,25756).
+char(0,25757).
+char(m,25758).
+char(6,25759).
+char(3,25760).
+char(4,25761).
+char(1,25762).
+char(c,25763).
+char(c,25764).
+char(c,25765).
+char(p,25766).
+char(o,25767).
+char(m,25768).
+char(7,25769).
+char(4,25770).
+char(8,25771).
+char(2,25772).
+char(c,25773).
+char(p,25774).
+char(6,25775).
+char(5,25776).
+char(2,25777).
+char(1,25778).
+char(m,25779).
+char(o,25780).
+char(7,25781).
+char(5,25782).
+char(9,25783).
+char(1,25784).
+char(c,25785).
+char(p,25786).
+char(o,25787).
+char(o,25788).
+char(p,25789).
+char(7,25790).
+char(8,25791).
+char(8,25792).
+char(6,25793).
+char(c,25794).
+char(m,25795).
+char(o,25796).
+char(o,25797).
+char(7,25798).
+char(0,25799).
+char(5,25800).
+char(6,25801).
+char(m,25802).
+char(2,25803).
+char(9,25804).
+char(9,25805).
+char(0,25806).
+char(m,25807).
+char(8,25808).
+char(3,25809).
+char(3,25810).
+char(9,25811).
+char(m,25812).
+char(o,25813).
+char(m,25814).
+char(o,25815).
+char(p,25816).
+char(8,25817).
+char(0,25818).
+char(6,25819).
+char(p,25820).
+char(1,25821).
+char(5,25822).
+char(2,25823).
+char(9,25824).
+char(p,25825).
+char(o,25826).
+char(p,25827).
+char(o,25828).
+char(p,25829).
+char(o,25830).
+char(o,25831).
+char(8,25832).
+char(7,25833).
+char(2,25834).
+char(m,25835).
+char(o,25836).
+char(m,25837).
+char(2,25838).
+char(0,25839).
+char(2,25840).
+char(2,25841).
+char(m,25842).
+char(3,25843).
+char(9,25844).
+char(8,25845).
+char(m,25846).
+char(o,25847).
+char(o,25848).
+char(o,25849).
+char(p,25850).
+char(o,25851).
+char(m,25852).
+char(o,25853).
+char(o,25854).
+char(o,25855).
+char(p,25856).
+char(o,25857).
+char(m,25858).
+char(1,25859).
+char(8,25860).
+char(7,25861).
+char(1,25862).
+char(p,25863).
+char(9,25864).
+char(2,25865).
+char(9,25866).
+char(1,25867).
+char(c,25868).
+char(c,25869).
+char(c,25870).
+char(c,25871).
+char(c,25872).
+char(c,25873).
+char(c,25874).
+char(p,25875).
+char(5,25876).
+char(5,25877).
+char(9,25878).
+char(7,25879).
+char(c,25880).
+char(c,25881).
+char(m,25882).
+char(4,25883).
+char(8,25884).
+char(2,25885).
+char(p,25886).
+char(o,25887).
+char(p,25888).
+char(o,25889).
+char(m,25890).
+char(9,25891).
+char(7,25892).
+char(5,25893).
+char(4,25894).
+char(c,25895).
+char(c,25896).
+char(c,25897).
+char(m,25898).
+char(1,25899).
+char(9,25900).
+char(8,25901).
+char(9,25902).
+char(m,25903).
+char(o,25904).
+char(p,25905).
+char(7,25906).
+char(0,25907).
+char(2,25908).
+char(3,25909).
+char(c,25910).
+char(p,25911).
+char(o,25912).
+char(p,25913).
+char(5,25914).
+char(9,25915).
+char(1,25916).
+char(6,25917).
+char(c,25918).
+char(m,25919).
+char(o,25920).
+char(m,25921).
+char(o,25922).
+char(5,25923).
+char(6,25924).
+char(0,25925).
+char(8,25926).
+char(c,25927).
+char(m,25928).
+char(o,25929).
+char(p,25930).
+char(2,25931).
+char(1,25932).
+char(0,25933).
+char(9,25934).
+char(p,25935).
+char(o,25936).
+char(p,25937).
+char(o,25938).
+char(p,25939).
+char(o,25940).
+char(p,25941).
+char(o,25942).
+char(m,25943).
+char(1,25944).
+char(7,25945).
+char(8,25946).
+char(8,25947).
+char(c,25948).
+char(p,25949).
+char(2,25950).
+char(5,25951).
+char(0,25952).
+char(p,25953).
+char(o,25954).
+char(p,25955).
+char(o,25956).
+char(m,25957).
+char(o,25958).
+char(m,25959).
+char(6,25960).
+char(4,25961).
+char(5,25962).
+char(2,25963).
+char(c,25964).
+char(c,25965).
+char(p,25966).
+char(7,25967).
+char(9,25968).
+char(6,25969).
+char(c,25970).
+char(p,25971).
+char(6,25972).
+char(4,25973).
+char(2,25974).
+char(p,25975).
+char(o,25976).
+char(p,25977).
+char(o,25978).
+char(6,25979).
+char(1,25980).
+char(0,25981).
+char(6,25982).
+char(m,25983).
+char(o,25984).
+char(p,25985).
+char(o,25986).
+char(m,25987).
+char(8,25988).
+char(8,25989).
+char(1,25990).
+char(6,25991).
+char(c,25992).
+char(m,25993).
+char(o,25994).
+char(m,25995).
+char(o,25996).
+char(o,25997).
+char(m,25998).
+char(3,25999).
+char(3,26000).
+char(2,26001).
+char(5,26002).
+char(c,26003).
+char(p,26004).
+char(4,26005).
+char(2,26006).
+char(3,26007).
+char(6,26008).
+char(m,26009).
+char(o,26010).
+char(m,26011).
+char(o,26012).
+char(o,26013).
+char(m,26014).
+char(3,26015).
+char(8,26016).
+char(4,26017).
+char(7,26018).
+char(m,26019).
+char(o,26020).
+char(3,26021).
+char(7,26022).
+char(2,26023).
+char(5,26024).
+char(c,26025).
+char(p,26026).
+char(7,26027).
+char(0,26028).
+char(7,26029).
+char(5,26030).
+char(p,26031).
+char(8,26032).
+char(5,26033).
+char(9,26034).
+char(c,26035).
+char(p,26036).
+char(o,26037).
+char(2,26038).
+char(5,26039).
+char(7,26040).
+char(9,26041).
+char(c,26042).
+char(c,26043).
+char(p,26044).
+char(9,26045).
+char(5,26046).
+char(0,26047).
+char(0,26048).
+char(m,26049).
+char(o,26050).
+char(4,26051).
+char(6,26052).
+char(4,26053).
+char(8,26054).
+char(c,26055).
+char(p,26056).
+char(o,26057).
+char(o,26058).
+char(7,26059).
+char(7,26060).
+char(0,26061).
+char(3,26062).
+char(c,26063).
+char(m,26064).
+char(o,26065).
+char(p,26066).
+char(o,26067).
+char(p,26068).
+char(5,26069).
+char(6,26070).
+char(0,26071).
+char(8,26072).
+char(m,26073).
+char(2,26074).
+char(4,26075).
+char(4,26076).
+char(4,26077).
+char(m,26078).
+char(o,26079).
+char(7,26080).
+char(5,26081).
+char(0,26082).
+char(8,26083).
+char(m,26084).
+char(3,26085).
+char(7,26086).
+char(2,26087).
+char(9,26088).
+char(m,26089).
+char(4,26090).
+char(3,26091).
+char(5,26092).
+char(3,26093).
+char(m,26094).
+char(6,26095).
+char(3,26096).
+char(4,26097).
+char(3,26098).
+char(c,26099).
+char(p,26100).
+char(6,26101).
+char(1,26102).
+char(3,26103).
+char(1,26104).
+char(p,26105).
+char(4,26106).
+char(7,26107).
+char(8,26108).
+char(7,26109).
+char(c,26110).
+char(p,26111).
+char(1,26112).
+char(9,26113).
+char(6,26114).
+char(2,26115).
+char(m,26116).
+char(o,26117).
+char(m,26118).
+char(o,26119).
+char(p,26120).
+char(o,26121).
+char(o,26122).
+char(m,26123).
+char(o,26124).
+char(o,26125).
+char(o,26126).
+char(m,26127).
+char(4,26128).
+char(3,26129).
+char(7,26130).
+char(9,26131).
+char(c,26132).
+char(c,26133).
+char(p,26134).
+char(7,26135).
+char(1,26136).
+char(7,26137).
+char(8,26138).
+char(p,26139).
+char(o,26140).
+char(m,26141).
+char(o,26142).
+char(p,26143).
+char(7,26144).
+char(8,26145).
+char(7,26146).
+char(6,26147).
+char(c,26148).
+char(c,26149).
+char(m,26150).
+char(7,26151).
+char(2,26152).
+char(3,26153).
+char(3,26154).
+char(c,26155).
+char(c,26156).
+char(c,26157).
+char(m,26158).
+char(8,26159).
+char(3,26160).
+char(1,26161).
+char(7,26162).
+char(m,26163).
+char(o,26164).
+char(m,26165).
+char(o,26166).
+char(p,26167).
+char(o,26168).
+char(p,26169).
+char(7,26170).
+char(1,26171).
+char(2,26172).
+char(4,26173).
+char(m,26174).
+char(o,26175).
+char(p,26176).
+char(o,26177).
+char(p,26178).
+char(o,26179).
+char(p,26180).
+char(o,26181).
+char(3,26182).
+char(7,26183).
+char(2,26184).
+char(0,26185).
+char(m,26186).
+char(9,26187).
+char(9,26188).
+char(5,26189).
+char(1,26190).
+char(m,26191).
+char(o,26192).
+char(p,26193).
+char(o,26194).
+char(m,26195).
+char(o,26196).
+char(7,26197).
+char(8,26198).
+char(7,26199).
+char(0,26200).
+char(m,26201).
+char(8,26202).
+char(8,26203).
+char(2,26204).
+char(2,26205).
+char(p,26206).
+char(8,26207).
+char(2,26208).
+char(3,26209).
+char(0,26210).
+char(p,26211).
+char(3,26212).
+char(9,26213).
+char(1,26214).
+char(0,26215).
+char(p,26216).
+char(1,26217).
+char(4,26218).
+char(4,26219).
+char(8,26220).
+char(c,26221).
+char(c,26222).
+char(c,26223).
+char(m,26224).
+char(5,26225).
+char(5,26226).
+char(8,26227).
+char(6,26228).
+char(m,26229).
+char(4,26230).
+char(1,26231).
+char(2,26232).
+char(8,26233).
+char(p,26234).
+char(6,26235).
+char(8,26236).
+char(5,26237).
+char(1,26238).
+char(c,26239).
+char(m,26240).
+char(o,26241).
+char(p,26242).
+char(o,26243).
+char(p,26244).
+char(o,26245).
+char(p,26246).
+char(o,26247).
+char(m,26248).
+char(o,26249).
+char(m,26250).
+char(o,26251).
+char(m,26252).
+char(o,26253).
+char(o,26254).
+char(p,26255).
+char(8,26256).
+char(7,26257).
+char(1,26258).
+char(1,26259).
+char(m,26260).
+char(4,26261).
+char(4,26262).
+char(3,26263).
+char(8,26264).
+char(p,26265).
+char(2,26266).
+char(5,26267).
+char(4,26268).
+char(3,26269).
+char(c,26270).
+char(c,26271).
+char(c,26272).
+char(c,26273).
+char(c,26274).
+char(p,26275).
+char(7,26276).
+char(2,26277).
+char(8,26278).
+char(6,26279).
+char(c,26280).
+char(c,26281).
+char(p,26282).
+char(o,26283).
+char(7,26284).
+char(4,26285).
+char(3,26286).
+char(8,26287).
+char(p,26288).
+char(o,26289).
+char(m,26290).
+char(o,26291).
+char(p,26292).
+char(o,26293).
+char(p,26294).
+char(o,26295).
+char(p,26296).
+char(o,26297).
+char(p,26298).
+char(2,26299).
+char(3,26300).
+char(5,26301).
+char(2,26302).
+char(c,26303).
+char(p,26304).
+char(o,26305).
+char(m,26306).
+char(o,26307).
+char(m,26308).
+char(o,26309).
+char(p,26310).
+char(4,26311).
+char(3,26312).
+char(7,26313).
+char(2,26314).
+char(m,26315).
+char(o,26316).
+char(p,26317).
+char(o,26318).
+char(p,26319).
+char(3,26320).
+char(6,26321).
+char(9,26322).
+char(4,26323).
+char(c,26324).
+char(c,26325).
+char(c,26326).
+char(c,26327).
+char(m,26328).
+char(o,26329).
+char(m,26330).
+char(5,26331).
+char(4,26332).
+char(7,26333).
+char(3,26334).
+char(m,26335).
+char(7,26336).
+char(2,26337).
+char(7,26338).
+char(c,26339).
+char(p,26340).
+char(2,26341).
+char(5,26342).
+char(6,26343).
+char(c,26344).
+char(c,26345).
+char(c,26346).
+char(c,26347).
+char(c,26348).
+char(m,26349).
+char(o,26350).
+char(m,26351).
+char(o,26352).
+char(7,26353).
+char(3,26354).
+char(6,26355).
+char(3,26356).
+char(p,26357).
+char(o,26358).
+char(m,26359).
+char(o,26360).
+char(p,26361).
+char(o,26362).
+char(p,26363).
+char(3,26364).
+char(1,26365).
+char(6,26366).
+char(7,26367).
+char(c,26368).
+char(m,26369).
+char(o,26370).
+char(p,26371).
+char(o,26372).
+char(4,26373).
+char(9,26374).
+char(7,26375).
+char(6,26376).
+char(m,26377).
+char(8,26378).
+char(3,26379).
+char(6,26380).
+char(8,26381).
+char(p,26382).
+char(o,26383).
+char(p,26384).
+char(o,26385).
+char(m,26386).
+char(o,26387).
+char(o,26388).
+char(o,26389).
+char(m,26390).
+char(8,26391).
+char(9,26392).
+char(7,26393).
+char(5,26394).
+char(p,26395).
+char(o,26396).
+char(p,26397).
+char(o,26398).
+char(m,26399).
+char(o,26400).
+char(p,26401).
+char(8,26402).
+char(9,26403).
+char(5,26404).
+char(9,26405).
+char(p,26406).
+char(5,26407).
+char(0,26408).
+char(6,26409).
+char(7,26410).
+char(c,26411).
+char(p,26412).
+char(o,26413).
+char(o,26414).
+char(p,26415).
+char(o,26416).
+char(1,26417).
+char(6,26418).
+char(6,26419).
+char(1,26420).
+char(c,26421).
+char(c,26422).
+char(c,26423).
+char(c,26424).
+char(c,26425).
+char(c,26426).
+char(c,26427).
+char(c,26428).
+char(p,26429).
+char(o,26430).
+char(m,26431).
+char(8,26432).
+char(7,26433).
+char(5,26434).
+char(7,26435).
+char(c,26436).
+char(m,26437).
+char(1,26438).
+char(2,26439).
+char(8,26440).
+char(6,26441).
+char(c,26442).
+char(m,26443).
+char(o,26444).
+char(p,26445).
+char(7,26446).
+char(1,26447).
+char(2,26448).
+char(9,26449).
+char(c,26450).
+char(m,26451).
+char(2,26452).
+char(9,26453).
+char(5,26454).
+char(1,26455).
+char(c,26456).
+char(c,26457).
+char(c,26458).
+char(c,26459).
+char(c,26460).
+char(c,26461).
+char(m,26462).
+char(o,26463).
+char(o,26464).
+char(p,26465).
+char(2,26466).
+char(6,26467).
+char(4,26468).
+char(0,26469).
+char(c,26470).
+char(c,26471).
+char(m,26472).
+char(o,26473).
+char(m,26474).
+char(o,26475).
+char(9,26476).
+char(1,26477).
+char(4,26478).
+char(4,26479).
+char(p,26480).
+char(o,26481).
+char(m,26482).
+char(7,26483).
+char(2,26484).
+char(6,26485).
+char(5,26486).
+char(c,26487).
+char(m,26488).
+char(1,26489).
+char(8,26490).
+char(5,26491).
+char(8,26492).
+char(m,26493).
+char(9,26494).
+char(2,26495).
+char(8,26496).
+char(2,26497).
+char(m,26498).
+char(o,26499).
+char(p,26500).
+char(o,26501).
+char(o,26502).
+char(o,26503).
+char(p,26504).
+char(4,26505).
+char(8,26506).
+char(7,26507).
+char(p,26508).
+char(o,26509).
+char(m,26510).
+char(4,26511).
+char(1,26512).
+char(4,26513).
+char(1,26514).
+char(c,26515).
+char(p,26516).
+char(6,26517).
+char(2,26518).
+char(5,26519).
+char(c,26520).
+char(p,26521).
+char(o,26522).
+char(p,26523).
+char(3,26524).
+char(9,26525).
+char(6,26526).
+char(2,26527).
+char(p,26528).
+char(1,26529).
+char(4,26530).
+char(4,26531).
+char(0,26532).
+char(p,26533).
+char(6,26534).
+char(4,26535).
+char(4,26536).
+char(p,26537).
+char(1,26538).
+char(1,26539).
+char(0,26540).
+char(4,26541).
+char(p,26542).
+char(8,26543).
+char(4,26544).
+char(8,26545).
+char(6,26546).
+char(m,26547).
+char(9,26548).
+char(8,26549).
+char(5,26550).
+char(1,26551).
+char(c,26552).
+char(c,26553).
+char(c,26554).
+char(p,26555).
+char(4,26556).
+char(4,26557).
+char(5,26558).
+char(3,26559).
+char(c,26560).
+char(c,26561).
+char(m,26562).
+char(3,26563).
+char(9,26564).
+char(3,26565).
+char(1,26566).
+char(c,26567).
+char(p,26568).
+char(3,26569).
+char(7,26570).
+char(0,26571).
+char(8,26572).
+char(p,26573).
+char(o,26574).
+char(4,26575).
+char(3,26576).
+char(6,26577).
+char(8,26578).
+char(m,26579).
+char(6,26580).
+char(3,26581).
+char(3,26582).
+char(4,26583).
+char(c,26584).
+char(c,26585).
+char(p,26586).
+char(o,26587).
+char(p,26588).
+char(o,26589).
+char(o,26590).
+char(5,26591).
+char(0,26592).
+char(2,26593).
+char(6,26594).
+char(p,26595).
+char(o,26596).
+char(m,26597).
+char(2,26598).
+char(4,26599).
+char(9,26600).
+char(4,26601).
+char(m,26602).
+char(o,26603).
+char(o,26604).
+char(m,26605).
+char(o,26606).
+char(m,26607).
+char(o,26608).
+char(p,26609).
+char(o,26610).
+char(m,26611).
+char(7,26612).
+char(1,26613).
+char(5,26614).
+char(7,26615).
+char(m,26616).
+char(o,26617).
+char(o,26618).
+char(o,26619).
+char(o,26620).
+char(m,26621).
+char(7,26622).
+char(5,26623).
+char(8,26624).
+char(8,26625).
+char(c,26626).
+char(c,26627).
+char(c,26628).
+char(m,26629).
+char(o,26630).
+char(m,26631).
+char(o,26632).
+char(8,26633).
+char(7,26634).
+char(0,26635).
+char(p,26636).
+char(o,26637).
+char(m,26638).
+char(3,26639).
+char(0,26640).
+char(1,26641).
+char(5,26642).
+char(c,26643).
+char(p,26644).
+char(8,26645).
+char(4,26646).
+char(2,26647).
+char(6,26648).
+char(p,26649).
+char(o,26650).
+char(m,26651).
+char(o,26652).
+char(o,26653).
+char(m,26654).
+char(o,26655).
+char(m,26656).
+char(o,26657).
+char(o,26658).
+char(m,26659).
+char(6,26660).
+char(6,26661).
+char(7,26662).
+char(2,26663).
+char(p,26664).
+char(7,26665).
+char(5,26666).
+char(5,26667).
+char(3,26668).
+char(c,26669).
+char(m,26670).
+char(1,26671).
+char(8,26672).
+char(5,26673).
+char(6,26674).
+char(c,26675).
+char(m,26676).
+char(1,26677).
+char(6,26678).
+char(9,26679).
+char(9,26680).
+char(c,26681).
+char(p,26682).
+char(o,26683).
+char(m,26684).
+char(6,26685).
+char(8,26686).
+char(6,26687).
+char(9,26688).
+char(c,26689).
+char(p,26690).
+char(5,26691).
+char(2,26692).
+char(8,26693).
+char(3,26694).
+char(m,26695).
+char(7,26696).
+char(3,26697).
+char(8,26698).
+char(c,26699).
+char(p,26700).
+char(6,26701).
+char(2,26702).
+char(3,26703).
+char(0,26704).
+char(c,26705).
+char(c,26706).
+char(c,26707).
+char(c,26708).
+char(c,26709).
+char(m,26710).
+char(1,26711).
+char(1,26712).
+char(1,26713).
+char(7,26714).
+char(p,26715).
+char(o,26716).
+char(m,26717).
+char(o,26718).
+char(m,26719).
+char(o,26720).
+char(m,26721).
+char(o,26722).
+char(p,26723).
+char(7,26724).
+char(3,26725).
+char(1,26726).
+char(8,26727).
+char(p,26728).
+char(7,26729).
+char(1,26730).
+char(5,26731).
+char(1,26732).
+char(p,26733).
+char(o,26734).
+char(m,26735).
+char(5,26736).
+char(8,26737).
+char(2,26738).
+char(0,26739).
+char(m,26740).
+char(9,26741).
+char(3,26742).
+char(5,26743).
+char(p,26744).
+char(o,26745).
+char(3,26746).
+char(5,26747).
+char(4,26748).
+char(6,26749).
+char(m,26750).
+char(1,26751).
+char(5,26752).
+char(1,26753).
+char(2,26754).
+char(m,26755).
+char(o,26756).
+char(m,26757).
+char(o,26758).
+char(o,26759).
+char(o,26760).
+char(6,26761).
+char(4,26762).
+char(7,26763).
+char(6,26764).
+char(c,26765).
+char(m,26766).
+char(4,26767).
+char(8,26768).
+char(2,26769).
+char(9,26770).
+char(p,26771).
+char(o,26772).
+char(p,26773).
+char(o,26774).
+char(p,26775).
+char(o,26776).
+char(m,26777).
+char(2,26778).
+char(7,26779).
+char(1,26780).
+char(0,26781).
+char(m,26782).
+char(o,26783).
+char(o,26784).
+char(o,26785).
+char(p,26786).
+char(o,26787).
+char(m,26788).
+char(1,26789).
+char(1,26790).
+char(1,26791).
+char(5,26792).
+char(c,26793).
+char(c,26794).
+char(m,26795).
+char(o,26796).
+char(m,26797).
+char(o,26798).
+char(o,26799).
+char(p,26800).
+char(o,26801).
+char(o,26802).
+char(m,26803).
+char(o,26804).
+char(p,26805).
+char(o,26806).
+char(m,26807).
+char(3,26808).
+char(3,26809).
+char(5,26810).
+char(7,26811).
+char(m,26812).
+char(3,26813).
+char(1,26814).
+char(7,26815).
+char(3,26816).
+char(c,26817).
+char(c,26818).
+char(c,26819).
+char(c,26820).
+char(m,26821).
+char(1,26822).
+char(6,26823).
+char(5,26824).
+char(8,26825).
+char(p,26826).
+char(o,26827).
+char(o,26828).
+char(8,26829).
+char(7,26830).
+char(1,26831).
+char(4,26832).
+char(m,26833).
+char(o,26834).
+char(p,26835).
+char(9,26836).
+char(5,26837).
+char(8,26838).
+char(0,26839).
+char(p,26840).
+char(2,26841).
+char(7,26842).
+char(3,26843).
+char(6,26844).
+char(c,26845).
+char(c,26846).
+char(c,26847).
+char(c,26848).
+char(p,26849).
+char(8,26850).
+char(1,26851).
+char(8,26852).
+char(3,26853).
+char(m,26854).
+char(o,26855).
+char(9,26856).
+char(5,26857).
+char(3,26858).
+char(8,26859).
+char(p,26860).
+char(o,26861).
+char(6,26862).
+char(9,26863).
+char(7,26864).
+char(9,26865).
+char(m,26866).
+char(o,26867).
+char(p,26868).
+char(2,26869).
+char(0,26870).
+char(9,26871).
+char(9,26872).
+char(c,26873).
+char(c,26874).
+char(c,26875).
+char(m,26876).
+char(o,26877).
+char(o,26878).
+char(m,26879).
+char(o,26880).
+char(m,26881).
+char(o,26882).
+char(1,26883).
+char(8,26884).
+char(6,26885).
+char(8,26886).
+char(c,26887).
+char(m,26888).
+char(o,26889).
+char(o,26890).
+char(m,26891).
+char(o,26892).
+char(o,26893).
+char(p,26894).
+char(o,26895).
+char(p,26896).
+char(o,26897).
+char(m,26898).
+char(8,26899).
+char(3,26900).
+char(4,26901).
+char(6,26902).
+char(p,26903).
+char(o,26904).
+char(p,26905).
+char(o,26906).
+char(m,26907).
+char(1,26908).
+char(6,26909).
+char(2,26910).
+char(5,26911).
+char(p,26912).
+char(o,26913).
+char(o,26914).
+char(o,26915).
+char(m,26916).
+char(o,26917).
+char(p,26918).
+char(o,26919).
+char(m,26920).
+char(4,26921).
+char(4,26922).
+char(7,26923).
+char(1,26924).
+char(p,26925).
+char(1,26926).
+char(2,26927).
+char(5,26928).
+char(3,26929).
+char(p,26930).
+char(4,26931).
+char(3,26932).
+char(5,26933).
+char(7,26934).
+char(p,26935).
+char(1,26936).
+char(9,26937).
+char(3,26938).
+char(1,26939).
+char(m,26940).
+char(o,26941).
+char(p,26942).
+char(o,26943).
+char(m,26944).
+char(o,26945).
+char(m,26946).
+char(9,26947).
+char(1,26948).
+char(6,26949).
+char(p,26950).
+char(9,26951).
+char(2,26952).
+char(1,26953).
+char(2,26954).
+char(c,26955).
+char(p,26956).
+char(o,26957).
+char(o,26958).
+char(2,26959).
+char(8,26960).
+char(1,26961).
+char(2,26962).
+char(p,26963).
+char(o,26964).
+char(p,26965).
+char(6,26966).
+char(7,26967).
+char(3,26968).
+char(c,26969).
+char(p,26970).
+char(9,26971).
+char(7,26972).
+char(4,26973).
+char(7,26974).
+char(p,26975).
+char(2,26976).
+char(7,26977).
+char(3,26978).
+char(9,26979).
+char(m,26980).
+char(o,26981).
+char(o,26982).
+char(m,26983).
+char(1,26984).
+char(3,26985).
+char(5,26986).
+char(9,26987).
+char(c,26988).
+char(m,26989).
+char(9,26990).
+char(7,26991).
+char(2,26992).
+char(3,26993).
+char(c,26994).
+char(m,26995).
+char(o,26996).
+char(p,26997).
+char(o,26998).
+char(p,26999).
+char(o,27000).
+char(m,27001).
+char(2,27002).
+char(7,27003).
+char(7,27004).
+char(5,27005).
+char(p,27006).
+char(5,27007).
+char(3,27008).
+char(4,27009).
+char(1,27010).
+char(c,27011).
+char(p,27012).
+char(8,27013).
+char(5,27014).
+char(1,27015).
+char(9,27016).
+char(c,27017).
+char(c,27018).
+char(c,27019).
+char(c,27020).
+char(m,27021).
+char(9,27022).
+char(4,27023).
+char(4,27024).
+char(4,27025).
+char(c,27026).
+char(c,27027).
+char(p,27028).
+char(o,27029).
+char(6,27030).
+char(4,27031).
+char(6,27032).
+char(9,27033).
+char(c,27034).
+char(c,27035).
+char(p,27036).
+char(7,27037).
+char(4,27038).
+char(4,27039).
+char(4,27040).
+char(c,27041).
+char(m,27042).
+char(o,27043).
+char(m,27044).
+char(o,27045).
+char(m,27046).
+char(4,27047).
+char(6,27048).
+char(5,27049).
+char(7,27050).
+char(m,27051).
+char(o,27052).
+char(p,27053).
+char(4,27054).
+char(7,27055).
+char(7,27056).
+char(1,27057).
+char(p,27058).
+char(8,27059).
+char(0,27060).
+char(3,27061).
+char(1,27062).
+char(c,27063).
+char(c,27064).
+char(c,27065).
+char(m,27066).
+char(3,27067).
+char(3,27068).
+char(7,27069).
+char(3,27070).
+char(c,27071).
+char(c,27072).
+char(c,27073).
+char(m,27074).
+char(8,27075).
+char(2,27076).
+char(1,27077).
+char(6,27078).
+char(m,27079).
+char(o,27080).
+char(m,27081).
+char(8,27082).
+char(2,27083).
+char(2,27084).
+char(3,27085).
+char(c,27086).
+char(m,27087).
+char(o,27088).
+char(2,27089).
+char(8,27090).
+char(3,27091).
+char(3,27092).
+char(c,27093).
+char(c,27094).
+char(c,27095).
+char(c,27096).
+char(c,27097).
+char(p,27098).
+char(o,27099).
+char(o,27100).
+char(p,27101).
+char(4,27102).
+char(2,27103).
+char(0,27104).
+char(0,27105).
+char(m,27106).
+char(o,27107).
+char(p,27108).
+char(7,27109).
+char(0,27110).
+char(8,27111).
+char(7,27112).
+char(p,27113).
+char(4,27114).
+char(0,27115).
+char(1,27116).
+char(1,27117).
+char(m,27118).
+char(o,27119).
+char(p,27120).
+char(o,27121).
+char(m,27122).
+char(o,27123).
+char(m,27124).
+char(3,27125).
+char(5,27126).
+char(2,27127).
+char(2,27128).
+char(c,27129).
+char(c,27130).
+char(c,27131).
+char(c,27132).
+char(p,27133).
+char(4,27134).
+char(7,27135).
+char(2,27136).
+char(4,27137).
+char(p,27138).
+char(o,27139).
+char(p,27140).
+char(4,27141).
+char(7,27142).
+char(5,27143).
+char(5,27144).
+char(c,27145).
+char(c,27146).
+char(c,27147).
+char(c,27148).
+char(p,27149).
+char(7,27150).
+char(9,27151).
+char(6,27152).
+char(2,27153).
+char(c,27154).
+char(c,27155).
+char(m,27156).
+char(o,27157).
+char(p,27158).
+char(o,27159).
+char(o,27160).
+char(m,27161).
+char(o,27162).
+char(p,27163).
+char(7,27164).
+char(0,27165).
+char(6,27166).
+char(3,27167).
+char(p,27168).
+char(9,27169).
+char(8,27170).
+char(4,27171).
+char(6,27172).
+char(c,27173).
+char(m,27174).
+char(o,27175).
+char(o,27176).
+char(p,27177).
+char(6,27178).
+char(1,27179).
+char(1,27180).
+char(3,27181).
+char(m,27182).
+char(o,27183).
+char(m,27184).
+char(9,27185).
+char(6,27186).
+char(4,27187).
+char(4,27188).
+char(c,27189).
+char(p,27190).
+char(1,27191).
+char(1,27192).
+char(7,27193).
+char(9,27194).
+char(c,27195).
+char(c,27196).
+char(c,27197).
+char(p,27198).
+char(9,27199).
+char(4,27200).
+char(5,27201).
+char(0,27202).
+char(c,27203).
+char(c,27204).
+char(m,27205).
+char(3,27206).
+char(1,27207).
+char(0,27208).
+char(4,27209).
+char(p,27210).
+char(o,27211).
+char(p,27212).
+char(o,27213).
+char(m,27214).
+char(2,27215).
+char(6,27216).
+char(2,27217).
+char(0,27218).
+char(c,27219).
+char(m,27220).
+char(4,27221).
+char(9,27222).
+char(5,27223).
+char(0,27224).
+char(c,27225).
+char(c,27226).
+char(c,27227).
+char(c,27228).
+char(c,27229).
+char(p,27230).
+char(o,27231).
+char(o,27232).
+char(o,27233).
+char(p,27234).
+char(7,27235).
+char(7,27236).
+char(3,27237).
+char(1,27238).
+char(p,27239).
+char(6,27240).
+char(2,27241).
+char(7,27242).
+char(1,27243).
+char(c,27244).
+char(m,27245).
+char(o,27246).
+char(p,27247).
+char(8,27248).
+char(0,27249).
+char(6,27250).
+char(7,27251).
+char(m,27252).
+char(6,27253).
+char(4,27254).
+char(5,27255).
+char(2,27256).
+char(c,27257).
+char(p,27258).
+char(8,27259).
+char(6,27260).
+char(5,27261).
+char(4,27262).
+char(p,27263).
+char(4,27264).
+char(0,27265).
+char(3,27266).
+char(2,27267).
+char(m,27268).
+char(o,27269).
+char(p,27270).
+char(7,27271).
+char(0,27272).
+char(6,27273).
+char(8,27274).
+char(m,27275).
+char(7,27276).
+char(0,27277).
+char(1,27278).
+char(9,27279).
+char(c,27280).
+char(c,27281).
+char(p,27282).
+char(o,27283).
+char(p,27284).
+char(o,27285).
+char(o,27286).
+char(p,27287).
+char(1,27288).
+char(6,27289).
+char(2,27290).
+char(7,27291).
+char(c,27292).
+char(c,27293).
+char(c,27294).
+char(p,27295).
+char(o,27296).
+char(m,27297).
+char(5,27298).
+char(7,27299).
+char(6,27300).
+char(7,27301).
+char(c,27302).
+char(m,27303).
+char(o,27304).
+char(m,27305).
+char(7,27306).
+char(0,27307).
+char(8,27308).
+char(6,27309).
+char(c,27310).
+char(c,27311).
+char(c,27312).
+char(p,27313).
+char(o,27314).
+char(2,27315).
+char(4,27316).
+char(5,27317).
+char(8,27318).
+char(m,27319).
+char(6,27320).
+char(0,27321).
+char(9,27322).
+char(4,27323).
+char(c,27324).
+char(c,27325).
+char(m,27326).
+char(o,27327).
+char(p,27328).
+char(3,27329).
+char(4,27330).
+char(0,27331).
+char(c,27332).
+char(p,27333).
+char(o,27334).
+char(m,27335).
+char(5,27336).
+char(2,27337).
+char(7,27338).
+char(1,27339).
+char(p,27340).
+char(o,27341).
+char(7,27342).
+char(0,27343).
+char(0,27344).
+char(m,27345).
+char(2,27346).
+char(7,27347).
+char(9,27348).
+char(2,27349).
+char(c,27350).
+char(c,27351).
+char(c,27352).
+char(p,27353).
+char(6,27354).
+char(1,27355).
+char(4,27356).
+char(6,27357).
+char(m,27358).
+char(7,27359).
+char(6,27360).
+char(6,27361).
+char(c,27362).
+char(c,27363).
+char(c,27364).
+char(p,27365).
+char(3,27366).
+char(4,27367).
+char(4,27368).
+char(7,27369).
+char(c,27370).
+char(c,27371).
+char(c,27372).
+char(c,27373).
+char(p,27374).
+char(4,27375).
+char(2,27376).
+char(0,27377).
+char(1,27378).
+char(m,27379).
+char(o,27380).
+char(p,27381).
+char(1,27382).
+char(0,27383).
+char(3,27384).
+char(2,27385).
+char(m,27386).
+char(2,27387).
+char(7,27388).
+char(8,27389).
+char(4,27390).
+char(p,27391).
+char(6,27392).
+char(0,27393).
+char(8,27394).
+char(0,27395).
+char(c,27396).
+char(c,27397).
+char(p,27398).
+char(o,27399).
+char(m,27400).
+char(9,27401).
+char(1,27402).
+char(8,27403).
+char(3,27404).
+char(p,27405).
+char(o,27406).
+char(2,27407).
+char(3,27408).
+char(1,27409).
+char(0,27410).
+char(c,27411).
+char(c,27412).
+char(c,27413).
+char(m,27414).
+char(7,27415).
+char(9,27416).
+char(2,27417).
+char(5,27418).
+char(c,27419).
+char(p,27420).
+char(8,27421).
+char(0,27422).
+char(7,27423).
+char(7,27424).
+char(m,27425).
+char(1,27426).
+char(4,27427).
+char(7,27428).
+char(3,27429).
+char(c,27430).
+char(m,27431).
+char(5,27432).
+char(7,27433).
+char(2,27434).
+char(7,27435).
+char(m,27436).
+char(o,27437).
+char(o,27438).
+char(p,27439).
+char(1,27440).
+char(9,27441).
+char(2,27442).
+char(c,27443).
+char(c,27444).
+char(c,27445).
+char(m,27446).
+char(o,27447).
+char(p,27448).
+char(o,27449).
+char(p,27450).
+char(o,27451).
+char(p,27452).
+char(9,27453).
+char(0,27454).
+char(6,27455).
+char(c,27456).
+char(p,27457).
+char(o,27458).
+char(m,27459).
+char(4,27460).
+char(3,27461).
+char(1,27462).
+char(c,27463).
+char(m,27464).
+char(6,27465).
+char(0,27466).
+char(8,27467).
+char(5,27468).
+char(c,27469).
+char(c,27470).
+char(m,27471).
+char(o,27472).
+char(m,27473).
+char(o,27474).
+char(7,27475).
+char(1,27476).
+char(c,27477).
+char(m,27478).
+char(3,27479).
+char(4,27480).
+char(3,27481).
+char(4,27482).
+char(c,27483).
+char(c,27484).
+char(p,27485).
+char(o,27486).
+char(o,27487).
+char(m,27488).
+char(o,27489).
+char(p,27490).
+char(3,27491).
+char(6,27492).
+char(7,27493).
+char(8,27494).
+char(p,27495).
+char(4,27496).
+char(6,27497).
+char(8,27498).
+char(5,27499).
+char(m,27500).
+char(o,27501).
+char(p,27502).
+char(1,27503).
+char(8,27504).
+char(8,27505).
+char(9,27506).
+char(c,27507).
+char(m,27508).
+char(5,27509).
+char(2,27510).
+char(6,27511).
+char(3,27512).
+char(c,27513).
+char(c,27514).
+char(c,27515).
+char(m,27516).
+char(5,27517).
+char(4,27518).
+char(3,27519).
+char(8,27520).
+char(c,27521).
+char(p,27522).
+char(9,27523).
+char(6,27524).
+char(1,27525).
+char(7,27526).
+char(c,27527).
+char(m,27528).
+char(7,27529).
+char(0,27530).
+char(4,27531).
+char(6,27532).
+char(m,27533).
+char(2,27534).
+char(0,27535).
+char(1,27536).
+char(6,27537).
+char(c,27538).
+char(c,27539).
+char(p,27540).
+char(1,27541).
+char(3,27542).
+char(2,27543).
+char(c,27544).
+char(c,27545).
+char(c,27546).
+char(m,27547).
+char(o,27548).
+char(p,27549).
+char(3,27550).
+char(5,27551).
+char(5,27552).
+char(7,27553).
+char(p,27554).
+char(o,27555).
+char(o,27556).
+char(9,27557).
+char(7,27558).
+char(6,27559).
+char(c,27560).
+char(c,27561).
+char(c,27562).
+char(c,27563).
+char(m,27564).
+char(5,27565).
+char(6,27566).
+char(3,27567).
+char(6,27568).
+char(c,27569).
+char(m,27570).
+char(o,27571).
+char(o,27572).
+char(m,27573).
+char(4,27574).
+char(7,27575).
+char(4,27576).
+char(2,27577).
+char(p,27578).
+char(o,27579).
+char(p,27580).
+char(2,27581).
+char(6,27582).
+char(5,27583).
+char(5,27584).
+char(c,27585).
+char(c,27586).
+char(c,27587).
+char(c,27588).
+char(p,27589).
+char(o,27590).
+char(p,27591).
+char(o,27592).
+char(p,27593).
+char(o,27594).
+char(o,27595).
+char(p,27596).
+char(3,27597).
+char(1,27598).
+char(4,27599).
+char(7,27600).
+char(m,27601).
+char(o,27602).
+char(8,27603).
+char(1,27604).
+char(2,27605).
+char(8,27606).
+char(m,27607).
+char(o,27608).
+char(o,27609).
+char(p,27610).
+char(o,27611).
+char(4,27612).
+char(6,27613).
+char(3,27614).
+char(6,27615).
+char(c,27616).
+char(m,27617).
+char(2,27618).
+char(9,27619).
+char(8,27620).
+char(c,27621).
+char(m,27622).
+char(6,27623).
+char(3,27624).
+char(1,27625).
+char(3,27626).
+char(p,27627).
+char(o,27628).
+char(o,27629).
+char(m,27630).
+char(o,27631).
+char(3,27632).
+char(4,27633).
+char(4,27634).
+char(2,27635).
+char(p,27636).
+char(3,27637).
+char(7,27638).
+char(0,27639).
+char(8,27640).
+char(p,27641).
+char(2,27642).
+char(0,27643).
+char(4,27644).
+char(5,27645).
+char(c,27646).
+char(p,27647).
+char(2,27648).
+char(3,27649).
+char(3,27650).
+char(5,27651).
+char(c,27652).
+char(c,27653).
+char(c,27654).
+char(p,27655).
+char(4,27656).
+char(6,27657).
+char(0,27658).
+char(2,27659).
+char(c,27660).
+char(c,27661).
+char(c,27662).
+char(m,27663).
+char(1,27664).
+char(4,27665).
+char(1,27666).
+char(4,27667).
+char(c,27668).
+char(m,27669).
+char(o,27670).
+char(p,27671).
+char(o,27672).
+char(m,27673).
+char(o,27674).
+char(3,27675).
+char(5,27676).
+char(5,27677).
+char(3,27678).
+char(c,27679).
+char(c,27680).
+char(c,27681).
+char(c,27682).
+char(c,27683).
+char(m,27684).
+char(o,27685).
+char(m,27686).
+char(o,27687).
+char(m,27688).
+char(o,27689).
+char(p,27690).
+char(o,27691).
+char(m,27692).
+char(7,27693).
+char(1,27694).
+char(6,27695).
+char(0,27696).
+char(p,27697).
+char(o,27698).
+char(m,27699).
+char(9,27700).
+char(3,27701).
+char(4,27702).
+char(1,27703).
+char(c,27704).
+char(m,27705).
+char(o,27706).
+char(m,27707).
+char(6,27708).
+char(1,27709).
+char(3,27710).
+char(0,27711).
+char(p,27712).
+char(9,27713).
+char(5,27714).
+char(1,27715).
+char(2,27716).
+char(p,27717).
+char(4,27718).
+char(2,27719).
+char(6,27720).
+char(5,27721).
+char(p,27722).
+char(o,27723).
+char(o,27724).
+char(p,27725).
+char(o,27726).
+char(p,27727).
+char(4,27728).
+char(0,27729).
+char(5,27730).
+char(3,27731).
+char(p,27732).
+char(o,27733).
+char(p,27734).
+char(3,27735).
+char(1,27736).
+char(0,27737).
+char(4,27738).
+char(p,27739).
+char(7,27740).
+char(0,27741).
+char(0,27742).
+char(9,27743).
+char(p,27744).
+char(o,27745).
+char(m,27746).
+char(o,27747).
+char(p,27748).
+char(2,27749).
+char(3,27750).
+char(4,27751).
+char(4,27752).
+char(c,27753).
+char(p,27754).
+char(o,27755).
+char(p,27756).
+char(o,27757).
+char(4,27758).
+char(4,27759).
+char(3,27760).
+char(5,27761).
+char(m,27762).
+char(o,27763).
+char(m,27764).
+char(3,27765).
+char(5,27766).
+char(4,27767).
+char(c,27768).
+char(c,27769).
+char(p,27770).
+char(7,27771).
+char(7,27772).
+char(2,27773).
+char(6,27774).
+char(m,27775).
+char(o,27776).
+char(m,27777).
+char(1,27778).
+char(9,27779).
+char(3,27780).
+char(7,27781).
+char(p,27782).
+char(6,27783).
+char(2,27784).
+char(6,27785).
+char(6,27786).
+char(c,27787).
+char(c,27788).
+char(m,27789).
+char(o,27790).
+char(3,27791).
+char(5,27792).
+char(6,27793).
+char(7,27794).
+char(c,27795).
+char(p,27796).
+char(5,27797).
+char(8,27798).
+char(9,27799).
+char(4,27800).
+char(m,27801).
+char(7,27802).
+char(5,27803).
+char(6,27804).
+char(3,27805).
+char(p,27806).
+char(o,27807).
+char(m,27808).
+char(4,27809).
+char(5,27810).
+char(0,27811).
+char(1,27812).
+char(m,27813).
+char(o,27814).
+char(8,27815).
+char(2,27816).
+char(5,27817).
+char(9,27818).
+char(m,27819).
+char(5,27820).
+char(9,27821).
+char(1,27822).
+char(c,27823).
+char(m,27824).
+char(6,27825).
+char(7,27826).
+char(4,27827).
+char(1,27828).
+char(c,27829).
+char(c,27830).
+char(c,27831).
+char(c,27832).
+char(c,27833).
+char(p,27834).
+char(4,27835).
+char(4,27836).
+char(0,27837).
+char(7,27838).
+char(c,27839).
+char(c,27840).
+char(c,27841).
+char(p,27842).
+char(6,27843).
+char(0,27844).
+char(8,27845).
+char(0,27846).
+char(c,27847).
+char(p,27848).
+char(1,27849).
+char(4,27850).
+char(9,27851).
+char(2,27852).
+char(c,27853).
+char(m,27854).
+char(5,27855).
+char(3,27856).
+char(6,27857).
+char(3,27858).
+char(c,27859).
+char(p,27860).
+char(3,27861).
+char(4,27862).
+char(7,27863).
+char(2,27864).
+char(c,27865).
+char(p,27866).
+char(6,27867).
+char(1,27868).
+char(9,27869).
+char(4,27870).
+char(c,27871).
+char(c,27872).
+char(c,27873).
+char(c,27874).
+char(m,27875).
+char(6,27876).
+char(9,27877).
+char(8,27878).
+char(0,27879).
+char(c,27880).
+char(p,27881).
+char(1,27882).
+char(8,27883).
+char(1,27884).
+char(c,27885).
+char(m,27886).
+char(o,27887).
+char(m,27888).
+char(6,27889).
+char(2,27890).
+char(0,27891).
+char(2,27892).
+char(c,27893).
+char(p,27894).
+char(5,27895).
+char(2,27896).
+char(4,27897).
+char(6,27898).
+char(p,27899).
+char(6,27900).
+char(0,27901).
+char(5,27902).
+char(2,27903).
+char(c,27904).
+char(c,27905).
+char(c,27906).
+char(c,27907).
+char(m,27908).
+char(3,27909).
+char(7,27910).
+char(6,27911).
+char(9,27912).
+char(m,27913).
+char(5,27914).
+char(2,27915).
+char(0,27916).
+char(9,27917).
+char(m,27918).
+char(3,27919).
+char(2,27920).
+char(4,27921).
+char(8,27922).
+char(p,27923).
+char(o,27924).
+char(p,27925).
+char(5,27926).
+char(3,27927).
+char(5,27928).
+char(8,27929).
+char(m,27930).
+char(6,27931).
+char(0,27932).
+char(1,27933).
+char(c,27934).
+char(c,27935).
+char(c,27936).
+char(m,27937).
+char(o,27938).
+char(m,27939).
+char(8,27940).
+char(1,27941).
+char(0,27942).
+char(0,27943).
+char(c,27944).
+char(c,27945).
+char(c,27946).
+char(p,27947).
+char(o,27948).
+char(p,27949).
+char(5,27950).
+char(9,27951).
+char(0,27952).
+char(9,27953).
+char(m,27954).
+char(o,27955).
+char(p,27956).
+char(o,27957).
+char(9,27958).
+char(0,27959).
+char(2,27960).
+char(7,27961).
+char(m,27962).
+char(o,27963).
+char(p,27964).
+char(o,27965).
+char(p,27966).
+char(o,27967).
+char(o,27968).
+char(p,27969).
+char(o,27970).
+char(p,27971).
+char(o,27972).
+char(p,27973).
+char(o,27974).
+char(m,27975).
+char(o,27976).
+char(o,27977).
+char(4,27978).
+char(8,27979).
+char(0,27980).
+char(5,27981).
+char(c,27982).
+char(p,27983).
+char(1,27984).
+char(7,27985).
+char(c,27986).
+char(p,27987).
+char(o,27988).
+char(m,27989).
+char(o,27990).
+char(p,27991).
+char(o,27992).
+char(m,27993).
+char(o,27994).
+char(m,27995).
+char(1,27996).
+char(5,27997).
+char(5,27998).
+char(p,27999).
+char(9,28000).
+char(7,28001).
+char(5,28002).
+char(4,28003).
+char(c,28004).
+char(c,28005).
+char(c,28006).
+char(c,28007).
+char(m,28008).
+char(o,28009).
+char(p,28010).
+char(3,28011).
+char(0,28012).
+char(1,28013).
+char(9,28014).
+char(m,28015).
+char(3,28016).
+char(1,28017).
+char(5,28018).
+char(8,28019).
+char(c,28020).
+char(c,28021).
+char(m,28022).
+char(o,28023).
+char(p,28024).
+char(4,28025).
+char(2,28026).
+char(2,28027).
+char(4,28028).
+char(c,28029).
+char(p,28030).
+char(o,28031).
+char(p,28032).
+char(o,28033).
+char(p,28034).
+char(o,28035).
+char(o,28036).
+char(p,28037).
+char(7,28038).
+char(2,28039).
+char(5,28040).
+char(1,28041).
+char(c,28042).
+char(m,28043).
+char(9,28044).
+char(2,28045).
+char(2,28046).
+char(0,28047).
+char(m,28048).
+char(o,28049).
+char(3,28050).
+char(5,28051).
+char(4,28052).
+char(6,28053).
+char(p,28054).
+char(o,28055).
+char(m,28056).
+char(5,28057).
+char(9,28058).
+char(0,28059).
+char(2,28060).
+char(c,28061).
+char(c,28062).
+char(m,28063).
+char(3,28064).
+char(2,28065).
+char(6,28066).
+char(1,28067).
+char(m,28068).
+char(o,28069).
+char(p,28070).
+char(o,28071).
+char(m,28072).
+char(6,28073).
+char(8,28074).
+char(7,28075).
+char(1,28076).
+char(m,28077).
+char(8,28078).
+char(8,28079).
+char(9,28080).
+char(0,28081).
+char(c,28082).
+char(p,28083).
+char(3,28084).
+char(0,28085).
+char(8,28086).
+char(0,28087).
+char(m,28088).
+char(o,28089).
+char(p,28090).
+char(o,28091).
+char(m,28092).
+char(o,28093).
+char(m,28094).
+char(5,28095).
+char(3,28096).
+char(4,28097).
+char(6,28098).
+char(p,28099).
+char(7,28100).
+char(1,28101).
+char(8,28102).
+char(9,28103).
+char(c,28104).
+char(p,28105).
+char(9,28106).
+char(4,28107).
+char(0,28108).
+char(p,28109).
+char(9,28110).
+char(0,28111).
+char(4,28112).
+char(0,28113).
+char(p,28114).
+char(3,28115).
+char(3,28116).
+char(4,28117).
+char(9,28118).
+char(c,28119).
+char(c,28120).
+char(c,28121).
+char(c,28122).
+char(c,28123).
+char(c,28124).
+char(p,28125).
+char(2,28126).
+char(4,28127).
+char(8,28128).
+char(c,28129).
+char(c,28130).
+char(m,28131).
+char(o,28132).
+char(p,28133).
+char(o,28134).
+char(m,28135).
+char(o,28136).
+char(4,28137).
+char(8,28138).
+char(8,28139).
+char(1,28140).
+char(m,28141).
+char(6,28142).
+char(3,28143).
+char(5,28144).
+char(4,28145).
+char(c,28146).
+char(p,28147).
+char(8,28148).
+char(2,28149).
+char(7,28150).
+char(4,28151).
+char(p,28152).
+char(7,28153).
+char(4,28154).
+char(3,28155).
+char(8,28156).
+char(c,28157).
+char(m,28158).
+char(9,28159).
+char(4,28160).
+char(5,28161).
+char(1,28162).
+char(m,28163).
+char(2,28164).
+char(4,28165).
+char(0,28166).
+char(9,28167).
+char(p,28168).
+char(o,28169).
+char(m,28170).
+char(o,28171).
+char(m,28172).
+char(o,28173).
+char(p,28174).
+char(3,28175).
+char(6,28176).
+char(0,28177).
+char(6,28178).
+char(c,28179).
+char(m,28180).
+char(o,28181).
+char(o,28182).
+char(7,28183).
+char(2,28184).
+char(0,28185).
+char(4,28186).
+char(p,28187).
+char(o,28188).
+char(4,28189).
+char(7,28190).
+char(9,28191).
+char(2,28192).
+char(p,28193).
+char(o,28194).
+char(6,28195).
+char(8,28196).
+char(0,28197).
+char(6,28198).
+char(m,28199).
+char(9,28200).
+char(5,28201).
+char(3,28202).
+char(7,28203).
+char(m,28204).
+char(o,28205).
+char(m,28206).
+char(8,28207).
+char(6,28208).
+char(0,28209).
+char(5,28210).
+char(m,28211).
+char(o,28212).
+char(1,28213).
+char(7,28214).
+char(0,28215).
+char(4,28216).
+char(p,28217).
+char(o,28218).
+char(p,28219).
+char(9,28220).
+char(6,28221).
+char(1,28222).
+char(0,28223).
+char(c,28224).
+char(c,28225).
+char(m,28226).
+char(o,28227).
+char(p,28228).
+char(2,28229).
+char(3,28230).
+char(3,28231).
+char(c,28232).
+char(c,28233).
+char(m,28234).
+char(o,28235).
+char(p,28236).
+char(6,28237).
+char(8,28238).
+char(1,28239).
+char(4,28240).
+char(p,28241).
+char(5,28242).
+char(6,28243).
+char(6,28244).
+char(6,28245).
+char(c,28246).
+char(m,28247).
+char(3,28248).
+char(0,28249).
+char(4,28250).
+char(1,28251).
+char(c,28252).
+char(c,28253).
+char(c,28254).
+char(c,28255).
+char(p,28256).
+char(o,28257).
+char(p,28258).
+char(o,28259).
+char(m,28260).
+char(4,28261).
+char(4,28262).
+char(6,28263).
+char(3,28264).
+char(c,28265).
+char(c,28266).
+char(m,28267).
+char(o,28268).
+char(p,28269).
+char(o,28270).
+char(p,28271).
+char(1,28272).
+char(1,28273).
+char(4,28274).
+char(2,28275).
+char(c,28276).
+char(p,28277).
+char(5,28278).
+char(7,28279).
+char(8,28280).
+char(5,28281).
+char(c,28282).
+char(p,28283).
+char(o,28284).
+char(m,28285).
+char(7,28286).
+char(7,28287).
+char(7,28288).
+char(6,28289).
+char(c,28290).
+char(m,28291).
+char(8,28292).
+char(2,28293).
+char(7,28294).
+char(5,28295).
+char(c,28296).
+char(c,28297).
+char(c,28298).
+char(c,28299).
+char(p,28300).
+char(o,28301).
+char(p,28302).
+char(o,28303).
+char(7,28304).
+char(9,28305).
+char(8,28306).
+char(4,28307).
+char(c,28308).
+char(c,28309).
+char(c,28310).
+char(m,28311).
+char(o,28312).
+char(6,28313).
+char(7,28314).
+char(1,28315).
+char(1,28316).
+char(p,28317).
+char(7,28318).
+char(9,28319).
+char(7,28320).
+char(8,28321).
+char(p,28322).
+char(1,28323).
+char(6,28324).
+char(1,28325).
+char(6,28326).
+char(c,28327).
+char(c,28328).
+char(p,28329).
+char(o,28330).
+char(p,28331).
+char(o,28332).
+char(m,28333).
+char(o,28334).
+char(p,28335).
+char(3,28336).
+char(9,28337).
+char(7,28338).
+char(p,28339).
+char(8,28340).
+char(9,28341).
+char(5,28342).
+char(7,28343).
+char(m,28344).
+char(o,28345).
+char(3,28346).
+char(0,28347).
+char(7,28348).
+char(6,28349).
+char(c,28350).
+char(p,28351).
+char(3,28352).
+char(1,28353).
+char(9,28354).
+char(c,28355).
+char(p,28356).
+char(3,28357).
+char(5,28358).
+char(5,28359).
+char(9,28360).
+char(c,28361).
+char(c,28362).
+char(c,28363).
+char(m,28364).
+char(6,28365).
+char(6,28366).
+char(0,28367).
+char(1,28368).
+char(p,28369).
+char(8,28370).
+char(3,28371).
+char(3,28372).
+char(1,28373).
+char(p,28374).
+char(o,28375).
+char(p,28376).
+char(1,28377).
+char(3,28378).
+char(3,28379).
+char(8,28380).
+char(p,28381).
+char(6,28382).
+char(7,28383).
+char(5,28384).
+char(5,28385).
+char(c,28386).
+char(p,28387).
+char(o,28388).
+char(o,28389).
+char(p,28390).
+char(4,28391).
+char(6,28392).
+char(6,28393).
+char(9,28394).
+char(m,28395).
+char(5,28396).
+char(8,28397).
+char(5,28398).
+char(2,28399).
+char(c,28400).
+char(c,28401).
+char(c,28402).
+char(m,28403).
+char(o,28404).
+char(p,28405).
+char(3,28406).
+char(5,28407).
+char(6,28408).
+char(4,28409).
+char(p,28410).
+char(o,28411).
+char(m,28412).
+char(3,28413).
+char(1,28414).
+char(0,28415).
+char(6,28416).
+char(p,28417).
+char(o,28418).
+char(o,28419).
+char(p,28420).
+char(1,28421).
+char(7,28422).
+char(7,28423).
+char(2,28424).
+char(c,28425).
+char(m,28426).
+char(1,28427).
+char(6,28428).
+char(0,28429).
+char(1,28430).
+char(c,28431).
+char(c,28432).
+char(m,28433).
+char(o,28434).
+char(m,28435).
+char(o,28436).
+char(p,28437).
+char(6,28438).
+char(3,28439).
+char(9,28440).
+char(5,28441).
+char(m,28442).
+char(1,28443).
+char(0,28444).
+char(4,28445).
+char(4,28446).
+char(c,28447).
+char(m,28448).
+char(3,28449).
+char(2,28450).
+char(8,28451).
+char(3,28452).
+char(p,28453).
+char(6,28454).
+char(1,28455).
+char(5,28456).
+char(8,28457).
+char(p,28458).
+char(o,28459).
+char(o,28460).
+char(o,28461).
+char(o,28462).
+char(m,28463).
+char(o,28464).
+char(p,28465).
+char(7,28466).
+char(0,28467).
+char(6,28468).
+char(1,28469).
+char(m,28470).
+char(o,28471).
+char(m,28472).
+char(o,28473).
+char(o,28474).
+char(o,28475).
+char(m,28476).
+char(8,28477).
+char(1,28478).
+char(7,28479).
+char(p,28480).
+char(9,28481).
+char(5,28482).
+char(m,28483).
+char(o,28484).
+char(p,28485).
+char(4,28486).
+char(7,28487).
+char(5,28488).
+char(c,28489).
+char(c,28490).
+char(p,28491).
+char(o,28492).
+char(o,28493).
+char(p,28494).
+char(8,28495).
+char(9,28496).
+char(4,28497).
+char(c,28498).
+char(m,28499).
+char(7,28500).
+char(6,28501).
+char(2,28502).
+char(m,28503).
+char(o,28504).
+char(p,28505).
+char(1,28506).
+char(8,28507).
+char(6,28508).
+char(c,28509).
+char(c,28510).
+char(c,28511).
+char(c,28512).
+char(c,28513).
+char(p,28514).
+char(6,28515).
+char(0,28516).
+char(2,28517).
+char(1,28518).
+char(m,28519).
+char(7,28520).
+char(0,28521).
+char(0,28522).
+char(0,28523).
+char(c,28524).
+char(p,28525).
+char(4,28526).
+char(1,28527).
+char(5,28528).
+char(p,28529).
+char(7,28530).
+char(8,28531).
+char(9,28532).
+char(2,28533).
+char(m,28534).
+char(8,28535).
+char(4,28536).
+char(0,28537).
+char(1,28538).
+char(c,28539).
+char(m,28540).
+char(o,28541).
+char(m,28542).
+char(o,28543).
+char(m,28544).
+char(3,28545).
+char(3,28546).
+char(3,28547).
+char(c,28548).
+char(c,28549).
+char(c,28550).
+char(c,28551).
+char(c,28552).
+char(p,28553).
+char(7,28554).
+char(7,28555).
+char(8,28556).
+char(2,28557).
+char(p,28558).
+char(o,28559).
+char(m,28560).
+char(o,28561).
+char(o,28562).
+char(p,28563).
+char(3,28564).
+char(4,28565).
+char(6,28566).
+char(4,28567).
+char(c,28568).
+char(m,28569).
+char(o,28570).
+char(3,28571).
+char(7,28572).
+char(8,28573).
+char(8,28574).
+char(p,28575).
+char(o,28576).
+char(1,28577).
+char(7,28578).
+char(4,28579).
+char(5,28580).
+char(c,28581).
+char(p,28582).
+char(o,28583).
+char(5,28584).
+char(5,28585).
+char(3,28586).
+char(2,28587).
+char(m,28588).
+char(3,28589).
+char(3,28590).
+char(0,28591).
+char(9,28592).
+char(c,28593).
+char(c,28594).
+char(c,28595).
+char(p,28596).
+char(1,28597).
+char(8,28598).
+char(3,28599).
+char(7,28600).
+char(c,28601).
+char(c,28602).
+char(c,28603).
+char(p,28604).
+char(8,28605).
+char(2,28606).
+char(8,28607).
+char(5,28608).
+char(c,28609).
+char(m,28610).
+char(o,28611).
+char(p,28612).
+char(4,28613).
+char(5,28614).
+char(1,28615).
+char(9,28616).
+char(m,28617).
+char(o,28618).
+char(4,28619).
+char(3,28620).
+char(4,28621).
+char(9,28622).
+char(p,28623).
+char(o,28624).
+char(m,28625).
+char(7,28626).
+char(2,28627).
+char(0,28628).
+char(8,28629).
+char(m,28630).
+char(o,28631).
+char(p,28632).
+char(o,28633).
+char(o,28634).
+char(m,28635).
+char(6,28636).
+char(9,28637).
+char(0,28638).
+char(2,28639).
+char(p,28640).
+char(6,28641).
+char(3,28642).
+char(6,28643).
+char(7,28644).
+char(c,28645).
+char(p,28646).
+char(9,28647).
+char(7,28648).
+char(9,28649).
+char(5,28650).
+char(m,28651).
+char(o,28652).
+char(o,28653).
+char(p,28654).
+char(o,28655).
+char(p,28656).
+char(2,28657).
+char(5,28658).
+char(9,28659).
+char(0,28660).
+char(p,28661).
+char(o,28662).
+char(m,28663).
+char(4,28664).
+char(5,28665).
+char(0,28666).
+char(6,28667).
+char(m,28668).
+char(o,28669).
+char(o,28670).
+char(p,28671).
+char(3,28672).
+char(8,28673).
+char(7,28674).
+char(7,28675).
+char(c,28676).
+char(c,28677).
+char(p,28678).
+char(o,28679).
+char(m,28680).
+char(5,28681).
+char(2,28682).
+char(9,28683).
+char(0,28684).
+char(p,28685).
+char(3,28686).
+char(7,28687).
+char(2,28688).
+char(5,28689).
+char(p,28690).
+char(o,28691).
+char(m,28692).
+char(9,28693).
+char(3,28694).
+char(7,28695).
+char(4,28696).
+char(p,28697).
+char(4,28698).
+char(3,28699).
+char(1,28700).
+char(p,28701).
+char(4,28702).
+char(8,28703).
+char(3,28704).
+char(4,28705).
+char(p,28706).
+char(o,28707).
+char(7,28708).
+char(1,28709).
+char(2,28710).
+char(6,28711).
+char(c,28712).
+char(m,28713).
+char(4,28714).
+char(4,28715).
+char(2,28716).
+char(2,28717).
+char(c,28718).
+char(m,28719).
+char(7,28720).
+char(2,28721).
+char(9,28722).
+char(7,28723).
+char(c,28724).
+char(m,28725).
+char(o,28726).
+char(m,28727).
+char(o,28728).
+char(o,28729).
+char(p,28730).
+char(o,28731).
+char(m,28732).
+char(o,28733).
+char(6,28734).
+char(1,28735).
+char(5,28736).
+char(1,28737).
+char(m,28738).
+char(7,28739).
+char(2,28740).
+char(7,28741).
+char(4,28742).
+char(m,28743).
+char(2,28744).
+char(5,28745).
+char(8,28746).
+char(7,28747).
+char(c,28748).
+char(c,28749).
+char(m,28750).
+char(o,28751).
+char(m,28752).
+char(2,28753).
+char(7,28754).
+char(2,28755).
+char(c,28756).
+char(m,28757).
+char(o,28758).
+char(o,28759).
+char(p,28760).
+char(6,28761).
+char(6,28762).
+char(5,28763).
+char(p,28764).
+char(o,28765).
+char(m,28766).
+char(6,28767).
+char(4,28768).
+char(2,28769).
+char(5,28770).
+char(p,28771).
+char(o,28772).
+char(p,28773).
+char(7,28774).
+char(3,28775).
+char(2,28776).
+char(9,28777).
+char(m,28778).
+char(o,28779).
+char(m,28780).
+char(o,28781).
+char(p,28782).
+char(o,28783).
+char(o,28784).
+char(p,28785).
+char(o,28786).
+char(m,28787).
+char(9,28788).
+char(2,28789).
+char(8,28790).
+char(p,28791).
+char(7,28792).
+char(1,28793).
+char(1,28794).
+char(5,28795).
+char(m,28796).
+char(3,28797).
+char(1,28798).
+char(1,28799).
+char(0,28800).
+char(m,28801).
+char(9,28802).
+char(2,28803).
+char(2,28804).
+char(2,28805).
+char(c,28806).
+char(p,28807).
+char(o,28808).
+char(p,28809).
+char(6,28810).
+char(3,28811).
+char(2,28812).
+char(5,28813).
+char(c,28814).
+char(c,28815).
+char(c,28816).
+char(c,28817).
+char(c,28818).
+char(p,28819).
+char(o,28820).
+char(m,28821).
+char(o,28822).
+char(o,28823).
+char(m,28824).
+char(4,28825).
+char(1,28826).
+char(0,28827).
+char(1,28828).
+char(c,28829).
+char(m,28830).
+char(o,28831).
+char(p,28832).
+char(7,28833).
+char(6,28834).
+char(1,28835).
+char(0,28836).
+char(m,28837).
+char(o,28838).
+char(p,28839).
+char(o,28840).
+char(p,28841).
+char(8,28842).
+char(5,28843).
+char(9,28844).
+char(2,28845).
+char(c,28846).
+char(c,28847).
+char(c,28848).
+char(p,28849).
+char(o,28850).
+char(o,28851).
+char(o,28852).
+char(p,28853).
+char(o,28854).
+char(9,28855).
+char(5,28856).
+char(5,28857).
+char(5,28858).
+char(c,28859).
+char(p,28860).
+char(9,28861).
+char(4,28862).
+char(4,28863).
+char(3,28864).
+char(c,28865).
+char(c,28866).
+char(c,28867).
+char(p,28868).
+char(1,28869).
+char(4,28870).
+char(3,28871).
+char(0,28872).
+char(p,28873).
+char(3,28874).
+char(1,28875).
+char(2,28876).
+char(3,28877).
+char(c,28878).
+char(p,28879).
+char(o,28880).
+char(m,28881).
+char(o,28882).
+char(p,28883).
+char(9,28884).
+char(2,28885).
+char(9,28886).
+char(4,28887).
+char(m,28888).
+char(4,28889).
+char(4,28890).
+char(7,28891).
+char(7,28892).
+char(m,28893).
+char(o,28894).
+char(m,28895).
+char(o,28896).
+char(m,28897).
+char(1,28898).
+char(9,28899).
+char(5,28900).
+char(3,28901).
+char(m,28902).
+char(o,28903).
+char(p,28904).
+char(o,28905).
+char(8,28906).
+char(5,28907).
+char(4,28908).
+char(5,28909).
+char(p,28910).
+char(o,28911).
+char(p,28912).
+char(o,28913).
+char(p,28914).
+char(4,28915).
+char(7,28916).
+char(0,28917).
+char(7,28918).
+char(c,28919).
+char(c,28920).
+char(m,28921).
+char(o,28922).
+char(o,28923).
+char(p,28924).
+char(o,28925).
+char(o,28926).
+char(p,28927).
+char(5,28928).
+char(0,28929).
+char(3,28930).
+char(5,28931).
+char(c,28932).
+char(m,28933).
+char(1,28934).
+char(1,28935).
+char(9,28936).
+char(9,28937).
+char(m,28938).
+char(o,28939).
+char(2,28940).
+char(3,28941).
+char(3,28942).
+char(8,28943).
+char(c,28944).
+char(m,28945).
+char(3,28946).
+char(6,28947).
+char(9,28948).
+char(3,28949).
+char(c,28950).
+char(c,28951).
+char(c,28952).
+char(c,28953).
+char(c,28954).
+char(c,28955).
+char(m,28956).
+char(o,28957).
+char(2,28958).
+char(1,28959).
+char(4,28960).
+char(c,28961).
+char(m,28962).
+char(o,28963).
+char(m,28964).
+char(o,28965).
+char(m,28966).
+char(8,28967).
+char(6,28968).
+char(3,28969).
+char(4,28970).
+char(c,28971).
+char(p,28972).
+char(4,28973).
+char(0,28974).
+char(p,28975).
+char(o,28976).
+char(p,28977).
+char(9,28978).
+char(6,28979).
+char(3,28980).
+char(9,28981).
+char(c,28982).
+char(m,28983).
+char(o,28984).
+char(p,28985).
+char(8,28986).
+char(2,28987).
+char(9,28988).
+char(5,28989).
+char(m,28990).
+char(o,28991).
+char(2,28992).
+char(9,28993).
+char(2,28994).
+char(1,28995).
+char(c,28996).
+char(c,28997).
+char(c,28998).
+char(m,28999).
+char(o,29000).
+char(m,29001).
+char(6,29002).
+char(2,29003).
+char(5,29004).
+char(6,29005).
+char(m,29006).
+char(o,29007).
+char(m,29008).
+char(o,29009).
+char(o,29010).
+char(p,29011).
+char(3,29012).
+char(3,29013).
+char(5,29014).
+char(2,29015).
+char(c,29016).
+char(c,29017).
+char(m,29018).
+char(o,29019).
+char(p,29020).
+char(7,29021).
+char(7,29022).
+char(1,29023).
+char(2,29024).
+char(c,29025).
+char(m,29026).
+char(o,29027).
+char(m,29028).
+char(3,29029).
+char(4,29030).
+char(0,29031).
+char(5,29032).
+char(m,29033).
+char(2,29034).
+char(7,29035).
+char(6,29036).
+char(6,29037).
+char(m,29038).
+char(8,29039).
+char(0,29040).
+char(2,29041).
+char(0,29042).
+char(p,29043).
+char(o,29044).
+char(p,29045).
+char(o,29046).
+char(m,29047).
+char(o,29048).
+char(p,29049).
+char(2,29050).
+char(4,29051).
+char(0,29052).
+char(3,29053).
+char(c,29054).
+char(c,29055).
+char(p,29056).
+char(o,29057).
+char(9,29058).
+char(7,29059).
+char(1,29060).
+char(0,29061).
+char(m,29062).
+char(5,29063).
+char(0,29064).
+char(2,29065).
+char(9,29066).
+char(c,29067).
+char(c,29068).
+char(p,29069).
+char(3,29070).
+char(8,29071).
+char(c,29072).
+char(c,29073).
+char(p,29074).
+char(4,29075).
+char(0,29076).
+char(2,29077).
+char(5,29078).
+char(c,29079).
+char(c,29080).
+char(c,29081).
+char(c,29082).
+char(c,29083).
+char(c,29084).
+char(p,29085).
+char(o,29086).
+char(o,29087).
+char(9,29088).
+char(2,29089).
+char(7,29090).
+char(1,29091).
+char(c,29092).
+char(c,29093).
+char(p,29094).
+char(o,29095).
+char(p,29096).
+char(o,29097).
+char(m,29098).
+char(o,29099).
+char(p,29100).
+char(1,29101).
+char(3,29102).
+char(6,29103).
+char(m,29104).
+char(o,29105).
+char(p,29106).
+char(o,29107).
+char(8,29108).
+char(7,29109).
+char(1,29110).
+char(c,29111).
+char(c,29112).
+char(c,29113).
+char(c,29114).
+char(m,29115).
+char(3,29116).
+char(5,29117).
+char(3,29118).
+char(3,29119).
+char(m,29120).
+char(o,29121).
+char(m,29122).
+char(1,29123).
+char(6,29124).
+char(6,29125).
+char(9,29126).
+char(c,29127).
+char(c,29128).
+char(c,29129).
+char(c,29130).
+char(m,29131).
+char(o,29132).
+char(p,29133).
+char(8,29134).
+char(2,29135).
+char(3,29136).
+char(2,29137).
+char(p,29138).
+char(o,29139).
+char(m,29140).
+char(5,29141).
+char(1,29142).
+char(6,29143).
+char(9,29144).
+char(c,29145).
+char(c,29146).
+char(m,29147).
+char(2,29148).
+char(7,29149).
+char(3,29150).
+char(0,29151).
+char(m,29152).
+char(o,29153).
+char(o,29154).
+char(m,29155).
+char(7,29156).
+char(1,29157).
+char(9,29158).
+char(7,29159).
+char(c,29160).
+char(c,29161).
+char(c,29162).
+char(p,29163).
+char(7,29164).
+char(1,29165).
+char(0,29166).
+char(c,29167).
+char(c,29168).
+char(p,29169).
+char(1,29170).
+char(0,29171).
+char(1,29172).
+char(0,29173).
+char(c,29174).
+char(c,29175).
+char(c,29176).
+char(c,29177).
+char(c,29178).
+char(c,29179).
+char(p,29180).
+char(6,29181).
+char(2,29182).
+char(5,29183).
+char(7,29184).
+char(p,29185).
+char(5,29186).
+char(9,29187).
+char(6,29188).
+char(6,29189).
+char(c,29190).
+char(c,29191).
+char(c,29192).
+char(c,29193).
+char(m,29194).
+char(o,29195).
+char(m,29196).
+char(o,29197).
+char(8,29198).
+char(8,29199).
+char(9,29200).
+char(8,29201).
+char(m,29202).
+char(o,29203).
+char(7,29204).
+char(4,29205).
+char(8,29206).
+char(8,29207).
+char(p,29208).
+char(o,29209).
+char(p,29210).
+char(1,29211).
+char(6,29212).
+char(8,29213).
+char(1,29214).
+char(c,29215).
+char(c,29216).
+char(c,29217).
+char(c,29218).
+char(c,29219).
+char(c,29220).
+char(p,29221).
+char(4,29222).
+char(3,29223).
+char(0,29224).
+char(c,29225).
+char(c,29226).
+char(p,29227).
+char(o,29228).
+char(p,29229).
+char(9,29230).
+char(6,29231).
+char(2,29232).
+char(2,29233).
+char(c,29234).
+char(c,29235).
+char(c,29236).
+char(p,29237).
+char(9,29238).
+char(8,29239).
+char(2,29240).
+char(0,29241).
+char(m,29242).
+char(o,29243).
+char(m,29244).
+char(7,29245).
+char(8,29246).
+char(9,29247).
+char(9,29248).
+char(c,29249).
+char(p,29250).
+char(4,29251).
+char(2,29252).
+char(9,29253).
+char(7,29254).
+char(m,29255).
+char(o,29256).
+char(o,29257).
+char(o,29258).
+char(m,29259).
+char(8,29260).
+char(9,29261).
+char(1,29262).
+char(1,29263).
+char(c,29264).
+char(c,29265).
+char(p,29266).
+char(o,29267).
+char(m,29268).
+char(6,29269).
+char(8,29270).
+char(7,29271).
+char(4,29272).
+char(c,29273).
+char(p,29274).
+char(9,29275).
+char(7,29276).
+char(5,29277).
+char(4,29278).
+char(m,29279).
+char(o,29280).
+char(o,29281).
+char(m,29282).
+char(6,29283).
+char(7,29284).
+char(5,29285).
+char(7,29286).
+char(p,29287).
+char(6,29288).
+char(5,29289).
+char(6,29290).
+char(9,29291).
+char(c,29292).
+char(c,29293).
+char(m,29294).
+char(o,29295).
+char(o,29296).
+char(p,29297).
+char(9,29298).
+char(8,29299).
+char(7,29300).
+char(0,29301).
+char(m,29302).
+char(5,29303).
+char(2,29304).
+char(9,29305).
+char(8,29306).
+char(c,29307).
+char(m,29308).
+char(2,29309).
+char(4,29310).
+char(8,29311).
+char(7,29312).
+char(m,29313).
+char(2,29314).
+char(6,29315).
+char(5,29316).
+char(7,29317).
+char(c,29318).
+char(p,29319).
+char(6,29320).
+char(4,29321).
+char(5,29322).
+char(9,29323).
+char(m,29324).
+char(o,29325).
+char(m,29326).
+char(o,29327).
+char(o,29328).
+char(o,29329).
+char(o,29330).
+char(p,29331).
+char(2,29332).
+char(0,29333).
+char(8,29334).
+char(3,29335).
+char(c,29336).
+char(p,29337).
+char(5,29338).
+char(0,29339).
+char(0,29340).
+char(6,29341).
+char(c,29342).
+char(c,29343).
+char(c,29344).
+char(p,29345).
+char(o,29346).
+char(p,29347).
+char(3,29348).
+char(6,29349).
+char(0,29350).
+char(9,29351).
+char(c,29352).
+char(c,29353).
+char(p,29354).
+char(o,29355).
+char(p,29356).
+char(6,29357).
+char(2,29358).
+char(2,29359).
+char(7,29360).
+char(p,29361).
+char(2,29362).
+char(1,29363).
+char(6,29364).
+char(5,29365).
+char(c,29366).
+char(c,29367).
+char(c,29368).
+char(m,29369).
+char(4,29370).
+char(5,29371).
+char(9,29372).
+char(3,29373).
+char(c,29374).
+char(c,29375).
+char(c,29376).
+char(c,29377).
+char(p,29378).
+char(6,29379).
+char(3,29380).
+char(3,29381).
+char(0,29382).
+char(c,29383).
+char(m,29384).
+char(9,29385).
+char(8,29386).
+char(5,29387).
+char(5,29388).
+char(p,29389).
+char(7,29390).
+char(7,29391).
+char(5,29392).
+char(4,29393).
+char(c,29394).
+char(m,29395).
+char(1,29396).
+char(8,29397).
+char(8,29398).
+char(2,29399).
+char(p,29400).
+char(o,29401).
+char(m,29402).
+char(o,29403).
+char(m,29404).
+char(8,29405).
+char(1,29406).
+char(6,29407).
+char(0,29408).
+char(c,29409).
+char(p,29410).
+char(9,29411).
+char(1,29412).
+char(0,29413).
+char(6,29414).
+char(p,29415).
+char(9,29416).
+char(4,29417).
+char(1,29418).
+char(6,29419).
+char(m,29420).
+char(o,29421).
+char(p,29422).
+char(4,29423).
+char(9,29424).
+char(4,29425).
+char(3,29426).
+char(c,29427).
+char(c,29428).
+char(p,29429).
+char(o,29430).
+char(p,29431).
+char(3,29432).
+char(9,29433).
+char(1,29434).
+char(9,29435).
+char(m,29436).
+char(o,29437).
+char(9,29438).
+char(9,29439).
+char(9,29440).
+char(3,29441).
+char(c,29442).
+char(c,29443).
+char(p,29444).
+char(8,29445).
+char(4,29446).
+char(2,29447).
+char(3,29448).
+char(p,29449).
+char(1,29450).
+char(8,29451).
+char(1,29452).
+char(2,29453).
+char(m,29454).
+char(o,29455).
+char(m,29456).
+char(o,29457).
+char(o,29458).
+char(p,29459).
+char(o,29460).
+char(m,29461).
+char(9,29462).
+char(3,29463).
+char(1,29464).
+char(m,29465).
+char(o,29466).
+char(o,29467).
+char(m,29468).
+char(2,29469).
+char(8,29470).
+char(7,29471).
+char(6,29472).
+char(c,29473).
+char(m,29474).
+char(o,29475).
+char(3,29476).
+char(0,29477).
+char(3,29478).
+char(2,29479).
+char(c,29480).
+char(c,29481).
+char(c,29482).
+char(m,29483).
+char(o,29484).
+char(m,29485).
+char(o,29486).
+char(5,29487).
+char(7,29488).
+char(0,29489).
+char(c,29490).
+char(c,29491).
+char(m,29492).
+char(9,29493).
+char(7,29494).
+char(7,29495).
+char(6,29496).
+char(p,29497).
+char(4,29498).
+char(9,29499).
+char(1,29500).
+char(8,29501).
+char(m,29502).
+char(o,29503).
+char(m,29504).
+char(o,29505).
+char(p,29506).
+char(o,29507).
+char(o,29508).
+char(o,29509).
+char(4,29510).
+char(2,29511).
+char(1,29512).
+char(9,29513).
+char(c,29514).
+char(c,29515).
+char(m,29516).
+char(o,29517).
+char(p,29518).
+char(o,29519).
+char(6,29520).
+char(4,29521).
+char(5,29522).
+char(0,29523).
+char(m,29524).
+char(9,29525).
+char(7,29526).
+char(c,29527).
+char(c,29528).
+char(c,29529).
+char(p,29530).
+char(1,29531).
+char(1,29532).
+char(6,29533).
+char(c,29534).
+char(p,29535).
+char(2,29536).
+char(5,29537).
+char(7,29538).
+char(7,29539).
+char(p,29540).
+char(3,29541).
+char(6,29542).
+char(0,29543).
+char(0,29544).
+char(c,29545).
+char(m,29546).
+char(o,29547).
+char(m,29548).
+char(o,29549).
+char(p,29550).
+char(o,29551).
+char(p,29552).
+char(2,29553).
+char(6,29554).
+char(5,29555).
+char(7,29556).
+char(c,29557).
+char(c,29558).
+char(c,29559).
+char(c,29560).
+char(c,29561).
+char(c,29562).
+char(m,29563).
+char(o,29564).
+char(m,29565).
+char(2,29566).
+char(6,29567).
+char(7,29568).
+char(c,29569).
+char(p,29570).
+char(o,29571).
+char(m,29572).
+char(o,29573).
+char(p,29574).
+char(9,29575).
+char(1,29576).
+char(2,29577).
+char(6,29578).
+char(p,29579).
+char(o,29580).
+char(p,29581).
+char(4,29582).
+char(8,29583).
+char(4,29584).
+char(0,29585).
+char(m,29586).
+char(o,29587).
+char(m,29588).
+char(8,29589).
+char(4,29590).
+char(0,29591).
+char(1,29592).
+char(c,29593).
+char(c,29594).
+char(p,29595).
+char(o,29596).
+char(m,29597).
+char(o,29598).
+char(m,29599).
+char(2,29600).
+char(0,29601).
+char(3,29602).
+char(8,29603).
+char(m,29604).
+char(1,29605).
+char(6,29606).
+char(8,29607).
+char(0,29608).
+char(c,29609).
+char(m,29610).
+char(o,29611).
+char(5,29612).
+char(5,29613).
+char(9,29614).
+char(6,29615).
+char(c,29616).
+char(m,29617).
+char(8,29618).
+char(2,29619).
+char(2,29620).
+char(1,29621).
+char(c,29622).
+char(c,29623).
+char(m,29624).
+char(2,29625).
+char(9,29626).
+char(c,29627).
+char(p,29628).
+char(o,29629).
+char(p,29630).
+char(6,29631).
+char(0,29632).
+char(0,29633).
+char(8,29634).
+char(m,29635).
+char(3,29636).
+char(7,29637).
+char(4,29638).
+char(8,29639).
+char(p,29640).
+char(4,29641).
+char(6,29642).
+char(3,29643).
+char(4,29644).
+char(m,29645).
+char(9,29646).
+char(1,29647).
+char(9,29648).
+char(5,29649).
+char(c,29650).
+char(m,29651).
+char(o,29652).
+char(2,29653).
+char(0,29654).
+char(3,29655).
+char(5,29656).
+char(c,29657).
+char(m,29658).
+char(6,29659).
+char(9,29660).
+char(9,29661).
+char(4,29662).
+char(m,29663).
+char(o,29664).
+char(o,29665).
+char(5,29666).
+char(8,29667).
+char(9,29668).
+char(c,29669).
+char(c,29670).
+char(p,29671).
+char(4,29672).
+char(8,29673).
+char(7,29674).
+char(6,29675).
+char(m,29676).
+char(o,29677).
+char(m,29678).
+char(2,29679).
+char(9,29680).
+char(5,29681).
+char(6,29682).
+char(p,29683).
+char(o,29684).
+char(p,29685).
+char(1,29686).
+char(4,29687).
+char(8,29688).
+char(5,29689).
+char(m,29690).
+char(o,29691).
+char(9,29692).
+char(2,29693).
+char(0,29694).
+char(3,29695).
+char(m,29696).
+char(o,29697).
+char(2,29698).
+char(7,29699).
+char(9,29700).
+char(2,29701).
+char(c,29702).
+char(p,29703).
+char(8,29704).
+char(5,29705).
+char(7,29706).
+char(7,29707).
+char(c,29708).
+char(c,29709).
+char(c,29710).
+char(c,29711).
+char(p,29712).
+char(o,29713).
+char(p,29714).
+char(6,29715).
+char(4,29716).
+char(9,29717).
+char(3,29718).
+char(c,29719).
+char(c,29720).
+char(c,29721).
+char(p,29722).
+char(6,29723).
+char(2,29724).
+char(8,29725).
+char(0,29726).
+char(c,29727).
+char(c,29728).
+char(c,29729).
+char(c,29730).
+char(m,29731).
+char(6,29732).
+char(0,29733).
+char(7,29734).
+char(m,29735).
+char(6,29736).
+char(6,29737).
+char(2,29738).
+char(4,29739).
+char(c,29740).
+char(p,29741).
+char(6,29742).
+char(7,29743).
+char(6,29744).
+char(1,29745).
+char(m,29746).
+char(5,29747).
+char(6,29748).
+char(7,29749).
+char(7,29750).
+char(m,29751).
+char(6,29752).
+char(0,29753).
+char(5,29754).
+char(p,29755).
+char(2,29756).
+char(6,29757).
+char(9,29758).
+char(9,29759).
+char(c,29760).
+char(p,29761).
+char(5,29762).
+char(3,29763).
+char(2,29764).
+char(9,29765).
+char(c,29766).
+char(m,29767).
+char(6,29768).
+char(4,29769).
+char(1,29770).
+char(0,29771).
+char(c,29772).
+char(p,29773).
+char(5,29774).
+char(0,29775).
+char(6,29776).
+char(9,29777).
+char(p,29778).
+char(7,29779).
+char(9,29780).
+char(1,29781).
+char(3,29782).
+char(c,29783).
+char(p,29784).
+char(o,29785).
+char(m,29786).
+char(8,29787).
+char(1,29788).
+char(5,29789).
+char(9,29790).
+char(m,29791).
+char(o,29792).
+char(m,29793).
+char(1,29794).
+char(5,29795).
+char(8,29796).
+char(6,29797).
+char(p,29798).
+char(o,29799).
+char(m,29800).
+char(o,29801).
+char(9,29802).
+char(8,29803).
+char(0,29804).
+char(6,29805).
+char(c,29806).
+char(c,29807).
+char(p,29808).
+char(5,29809).
+char(2,29810).
+char(1,29811).
+char(1,29812).
+char(m,29813).
+char(8,29814).
+char(7,29815).
+char(1,29816).
+char(8,29817).
+char(p,29818).
+char(7,29819).
+char(9,29820).
+char(4,29821).
+char(3,29822).
+char(m,29823).
+char(7,29824).
+char(9,29825).
+char(3,29826).
+char(7,29827).
+char(c,29828).
+char(c,29829).
+char(c,29830).
+char(c,29831).
+char(c,29832).
+char(p,29833).
+char(o,29834).
+char(m,29835).
+char(o,29836).
+char(p,29837).
+char(4,29838).
+char(5,29839).
+char(8,29840).
+char(1,29841).
+char(p,29842).
+char(o,29843).
+char(p,29844).
+char(o,29845).
+char(4,29846).
+char(0,29847).
+char(9,29848).
+char(3,29849).
+char(c,29850).
+char(m,29851).
+char(4,29852).
+char(2,29853).
+char(6,29854).
+char(c,29855).
+char(c,29856).
+char(m,29857).
+char(5,29858).
+char(5,29859).
+char(2,29860).
+char(4,29861).
+char(c,29862).
+char(p,29863).
+char(o,29864).
+char(p,29865).
+char(o,29866).
+char(m,29867).
+char(3,29868).
+char(1,29869).
+char(6,29870).
+char(p,29871).
+char(5,29872).
+char(0,29873).
+char(0,29874).
+char(4,29875).
+char(c,29876).
+char(c,29877).
+char(p,29878).
+char(o,29879).
+char(m,29880).
+char(4,29881).
+char(2,29882).
+char(1,29883).
+char(8,29884).
+char(p,29885).
+char(8,29886).
+char(1,29887).
+char(9,29888).
+char(0,29889).
+char(c,29890).
+char(p,29891).
+char(5,29892).
+char(7,29893).
+char(6,29894).
+char(0,29895).
+char(c,29896).
+char(c,29897).
+char(p,29898).
+char(o,29899).
+char(8,29900).
+char(8,29901).
+char(7,29902).
+char(c,29903).
+char(c,29904).
+char(m,29905).
+char(5,29906).
+char(6,29907).
+char(9,29908).
+char(7,29909).
+char(c,29910).
+char(m,29911).
+char(o,29912).
+char(p,29913).
+char(6,29914).
+char(7,29915).
+char(c,29916).
+char(p,29917).
+char(o,29918).
+char(p,29919).
+char(2,29920).
+char(7,29921).
+char(2,29922).
+char(0,29923).
+char(c,29924).
+char(p,29925).
+char(o,29926).
+char(3,29927).
+char(3,29928).
+char(0,29929).
+char(5,29930).
+char(c,29931).
+char(m,29932).
+char(4,29933).
+char(4,29934).
+char(8,29935).
+char(7,29936).
+char(m,29937).
+char(o,29938).
+char(o,29939).
+char(o,29940).
+char(o,29941).
+char(p,29942).
+char(o,29943).
+char(m,29944).
+char(o,29945).
+char(o,29946).
+char(m,29947).
+char(o,29948).
+char(m,29949).
+char(o,29950).
+char(m,29951).
+char(o,29952).
+char(m,29953).
+char(5,29954).
+char(0,29955).
+char(4,29956).
+char(4,29957).
+char(p,29958).
+char(o,29959).
+char(6,29960).
+char(1,29961).
+char(3,29962).
+char(8,29963).
+char(c,29964).
+char(p,29965).
+char(4,29966).
+char(5,29967).
+char(7,29968).
+char(6,29969).
+char(m,29970).
+char(o,29971).
+char(p,29972).
+char(4,29973).
+char(6,29974).
+char(3,29975).
+char(7,29976).
+char(p,29977).
+char(7,29978).
+char(5,29979).
+char(2,29980).
+char(4,29981).
+char(m,29982).
+char(o,29983).
+char(m,29984).
+char(1,29985).
+char(0,29986).
+char(0,29987).
+char(0,29988).
+char(c,29989).
+char(p,29990).
+char(o,29991).
+char(m,29992).
+char(5,29993).
+char(6,29994).
+char(3,29995).
+char(4,29996).
+char(p,29997).
+char(o,29998).
+char(3,29999).
+char(2,30000).
+char(9,30001).
+char(5,30002).
+char(c,30003).
+char(p,30004).
+char(o,30005).
+char(9,30006).
+char(9,30007).
+char(8,30008).
+char(9,30009).
+char(c,30010).
+char(m,30011).
+char(2,30012).
+char(0,30013).
+char(4,30014).
+char(6,30015).
+char(p,30016).
+char(7,30017).
+char(2,30018).
+char(8,30019).
+char(5,30020).
+char(p,30021).
+char(o,30022).
+char(m,30023).
+char(o,30024).
+char(3,30025).
+char(6,30026).
+char(7,30027).
+char(4,30028).
+char(p,30029).
+char(o,30030).
+char(o,30031).
+char(m,30032).
+char(9,30033).
+char(2,30034).
+char(8,30035).
+char(8,30036).
+char(c,30037).
+char(c,30038).
+char(c,30039).
+char(m,30040).
+char(o,30041).
+char(m,30042).
+char(o,30043).
+char(p,30044).
+char(o,30045).
+char(m,30046).
+char(o,30047).
+char(p,30048).
+char(o,30049).
+char(m,30050).
+char(o,30051).
+char(m,30052).
+char(6,30053).
+char(8,30054).
+char(4,30055).
+char(4,30056).
+char(c,30057).
+char(m,30058).
+char(o,30059).
+char(o,30060).
+char(5,30061).
+char(4,30062).
+char(8,30063).
+char(1,30064).
+char(m,30065).
+char(8,30066).
+char(9,30067).
+char(9,30068).
+char(7,30069).
+char(m,30070).
+char(5,30071).
+char(7,30072).
+char(6,30073).
+char(8,30074).
+char(c,30075).
+char(m,30076).
+char(o,30077).
+char(m,30078).
+char(o,30079).
+char(m,30080).
+char(o,30081).
+char(o,30082).
+char(p,30083).
+char(9,30084).
+char(0,30085).
+char(6,30086).
+char(8,30087).
+char(c,30088).
+char(c,30089).
+char(p,30090).
+char(4,30091).
+char(4,30092).
+char(6,30093).
+char(p,30094).
+char(7,30095).
+char(6,30096).
+char(7,30097).
+char(3,30098).
+char(m,30099).
+char(9,30100).
+char(8,30101).
+char(0,30102).
+char(3,30103).
+char(m,30104).
+char(2,30105).
+char(9,30106).
+char(2,30107).
+char(8,30108).
+char(p,30109).
+char(9,30110).
+char(3,30111).
+char(8,30112).
+char(p,30113).
+char(6,30114).
+char(4,30115).
+char(0,30116).
+char(6,30117).
+char(p,30118).
+char(9,30119).
+char(3,30120).
+char(7,30121).
+char(5,30122).
+char(m,30123).
+char(2,30124).
+char(4,30125).
+char(5,30126).
+char(9,30127).
+char(p,30128).
+char(9,30129).
+char(6,30130).
+char(5,30131).
+char(5,30132).
+char(m,30133).
+char(5,30134).
+char(9,30135).
+char(5,30136).
+char(c,30137).
+char(c,30138).
+char(m,30139).
+char(o,30140).
+char(p,30141).
+char(o,30142).
+char(o,30143).
+char(o,30144).
+char(m,30145).
+char(o,30146).
+char(m,30147).
+char(6,30148).
+char(8,30149).
+char(5,30150).
+char(3,30151).
+char(c,30152).
+char(c,30153).
+char(m,30154).
+char(4,30155).
+char(0,30156).
+char(1,30157).
+char(0,30158).
+char(c,30159).
+char(m,30160).
+char(o,30161).
+char(p,30162).
+char(7,30163).
+char(8,30164).
+char(5,30165).
+char(3,30166).
+char(c,30167).
+char(p,30168).
+char(5,30169).
+char(7,30170).
+char(6,30171).
+char(2,30172).
+char(m,30173).
+char(7,30174).
+char(1,30175).
+char(8,30176).
+char(3,30177).
+char(p,30178).
+char(o,30179).
+char(o,30180).
+char(m,30181).
+char(o,30182).
+char(m,30183).
+char(5,30184).
+char(6,30185).
+char(3,30186).
+char(8,30187).
+char(c,30188).
+char(m,30189).
+char(5,30190).
+char(0,30191).
+char(3,30192).
+char(1,30193).
+char(m,30194).
+char(o,30195).
+char(m,30196).
+char(o,30197).
+char(1,30198).
+char(0,30199).
+char(5,30200).
+char(5,30201).
+char(c,30202).
+char(c,30203).
+char(c,30204).
+char(c,30205).
+char(m,30206).
+char(o,30207).
+char(o,30208).
+char(m,30209).
+char(7,30210).
+char(0,30211).
+char(4,30212).
+char(6,30213).
+char(c,30214).
+char(m,30215).
+char(o,30216).
+char(o,30217).
+char(p,30218).
+char(7,30219).
+char(2,30220).
+char(5,30221).
+char(8,30222).
+char(m,30223).
+char(o,30224).
+char(o,30225).
+char(8,30226).
+char(6,30227).
+char(9,30228).
+char(6,30229).
+char(p,30230).
+char(o,30231).
+char(m,30232).
+char(o,30233).
+char(2,30234).
+char(6,30235).
+char(6,30236).
+char(p,30237).
+char(3,30238).
+char(4,30239).
+char(6,30240).
+char(6,30241).
+char(c,30242).
+char(p,30243).
+char(o,30244).
+char(8,30245).
+char(8,30246).
+char(2,30247).
+char(8,30248).
+char(c,30249).
+char(c,30250).
+char(p,30251).
+char(o,30252).
+char(m,30253).
+char(4,30254).
+char(5,30255).
+char(8,30256).
+char(9,30257).
+char(c,30258).
+char(m,30259).
+char(3,30260).
+char(0,30261).
+char(2,30262).
+char(4,30263).
+char(p,30264).
+char(o,30265).
+char(m,30266).
+char(o,30267).
+char(p,30268).
+char(o,30269).
+char(o,30270).
+char(m,30271).
+char(8,30272).
+char(2,30273).
+char(5,30274).
+char(8,30275).
+char(c,30276).
+char(m,30277).
+char(o,30278).
+char(o,30279).
+char(m,30280).
+char(o,30281).
+char(p,30282).
+char(o,30283).
+char(m,30284).
+char(7,30285).
+char(5,30286).
+char(3,30287).
+char(2,30288).
+char(c,30289).
+char(p,30290).
+char(o,30291).
+char(m,30292).
+char(o,30293).
+char(p,30294).
+char(o,30295).
+char(o,30296).
+char(p,30297).
+char(7,30298).
+char(9,30299).
+char(5,30300).
+char(c,30301).
+char(p,30302).
+char(2,30303).
+char(4,30304).
+char(6,30305).
+char(8,30306).
+char(p,30307).
+char(1,30308).
+char(0,30309).
+char(5,30310).
+char(0,30311).
+char(m,30312).
+char(o,30313).
+char(m,30314).
+char(7,30315).
+char(3,30316).
+char(8,30317).
+char(c,30318).
+char(c,30319).
+char(c,30320).
+char(m,30321).
+char(6,30322).
+char(2,30323).
+char(4,30324).
+char(5,30325).
+char(c,30326).
+char(p,30327).
+char(3,30328).
+char(5,30329).
+char(7,30330).
+char(9,30331).
+char(c,30332).
+char(c,30333).
+char(c,30334).
+char(c,30335).
+char(p,30336).
+char(8,30337).
+char(2,30338).
+char(1,30339).
+char(6,30340).
+char(m,30341).
+char(7,30342).
+char(1,30343).
+char(3,30344).
+char(c,30345).
+char(c,30346).
+char(m,30347).
+char(o,30348).
+char(o,30349).
+char(m,30350).
+char(6,30351).
+char(4,30352).
+char(4,30353).
+char(1,30354).
+char(c,30355).
+char(c,30356).
+char(m,30357).
+char(o,30358).
+char(o,30359).
+char(p,30360).
+char(o,30361).
+char(o,30362).
+char(p,30363).
+char(3,30364).
+char(4,30365).
+char(3,30366).
+char(8,30367).
+char(c,30368).
+char(c,30369).
+char(m,30370).
+char(2,30371).
+char(6,30372).
+char(7,30373).
+char(6,30374).
+char(p,30375).
+char(o,30376).
+char(o,30377).
+char(o,30378).
+char(m,30379).
+char(6,30380).
+char(9,30381).
+char(5,30382).
+char(3,30383).
+char(c,30384).
+char(m,30385).
+char(o,30386).
+char(m,30387).
+char(o,30388).
+char(p,30389).
+char(3,30390).
+char(9,30391).
+char(3,30392).
+char(c,30393).
+char(c,30394).
+char(c,30395).
+char(c,30396).
+char(p,30397).
+char(o,30398).
+char(p,30399).
+char(o,30400).
+char(m,30401).
+char(o,30402).
+char(p,30403).
+char(5,30404).
+char(7,30405).
+char(3,30406).
+char(6,30407).
+char(m,30408).
+char(6,30409).
+char(9,30410).
+char(3,30411).
+char(9,30412).
+char(m,30413).
+char(o,30414).
+char(o,30415).
+char(p,30416).
+char(9,30417).
+char(6,30418).
+char(7,30419).
+char(3,30420).
+char(m,30421).
+char(o,30422).
+char(4,30423).
+char(8,30424).
+char(9,30425).
+char(0,30426).
+char(c,30427).
+char(m,30428).
+char(3,30429).
+char(7,30430).
+char(4,30431).
+char(8,30432).
+char(m,30433).
+char(4,30434).
+char(5,30435).
+char(0,30436).
+char(2,30437).
+char(m,30438).
+char(8,30439).
+char(0,30440).
+char(8,30441).
+char(6,30442).
+char(m,30443).
+char(3,30444).
+char(6,30445).
+char(4,30446).
+char(9,30447).
+char(p,30448).
+char(o,30449).
+char(2,30450).
+char(3,30451).
+char(2,30452).
+char(c,30453).
+char(c,30454).
+char(m,30455).
+char(o,30456).
+char(m,30457).
+char(o,30458).
+char(m,30459).
+char(1,30460).
+char(8,30461).
+char(4,30462).
+char(7,30463).
+char(c,30464).
+char(m,30465).
+char(o,30466).
+char(m,30467).
+char(o,30468).
+char(p,30469).
+char(o,30470).
+char(m,30471).
+char(1,30472).
+char(0,30473).
+char(9,30474).
+char(0,30475).
+char(c,30476).
+char(m,30477).
+char(o,30478).
+char(4,30479).
+char(5,30480).
+char(3,30481).
+char(2,30482).
+char(m,30483).
+char(o,30484).
+char(p,30485).
+char(4,30486).
+char(3,30487).
+char(0,30488).
+char(p,30489).
+char(7,30490).
+char(7,30491).
+char(3,30492).
+char(c,30493).
+char(c,30494).
+char(c,30495).
+char(c,30496).
+char(c,30497).
+char(p,30498).
+char(8,30499).
+char(6,30500).
+char(4,30501).
+char(8,30502).
+char(c,30503).
+char(m,30504).
+char(o,30505).
+char(o,30506).
+char(m,30507).
+char(o,30508).
+char(o,30509).
+char(9,30510).
+char(0,30511).
+char(5,30512).
+char(9,30513).
+char(m,30514).
+char(7,30515).
+char(0,30516).
+char(3,30517).
+char(5,30518).
+char(p,30519).
+char(3,30520).
+char(2,30521).
+char(4,30522).
+char(p,30523).
+char(o,30524).
+char(m,30525).
+char(o,30526).
+char(o,30527).
+char(o,30528).
+char(p,30529).
+char(6,30530).
+char(6,30531).
+char(7,30532).
+char(4,30533).
+char(m,30534).
+char(2,30535).
+char(9,30536).
+char(9,30537).
+char(6,30538).
+char(c,30539).
+char(m,30540).
+char(o,30541).
+char(8,30542).
+char(5,30543).
+char(3,30544).
+char(9,30545).
+char(c,30546).
+char(c,30547).
+char(p,30548).
+char(6,30549).
+char(3,30550).
+char(5,30551).
+char(1,30552).
+char(p,30553).
+char(o,30554).
+char(4,30555).
+char(8,30556).
+char(3,30557).
+char(6,30558).
+char(p,30559).
+char(8,30560).
+char(2,30561).
+char(8,30562).
+char(7,30563).
+char(c,30564).
+char(p,30565).
+char(6,30566).
+char(0,30567).
+char(9,30568).
+char(2,30569).
+char(c,30570).
+char(m,30571).
+char(7,30572).
+char(6,30573).
+char(4,30574).
+char(1,30575).
+char(c,30576).
+char(c,30577).
+char(m,30578).
+char(o,30579).
+char(o,30580).
+char(m,30581).
+char(o,30582).
+char(o,30583).
+char(m,30584).
+char(o,30585).
+char(m,30586).
+char(o,30587).
+char(p,30588).
+char(2,30589).
+char(7,30590).
+char(6,30591).
+char(1,30592).
+char(m,30593).
+char(7,30594).
+char(8,30595).
+char(4,30596).
+char(3,30597).
+char(c,30598).
+char(c,30599).
+char(p,30600).
+char(o,30601).
+char(p,30602).
+char(o,30603).
+char(m,30604).
+char(4,30605).
+char(3,30606).
+char(9,30607).
+char(c,30608).
+char(c,30609).
+char(p,30610).
+char(8,30611).
+char(0,30612).
+char(4,30613).
+char(5,30614).
+char(m,30615).
+char(2,30616).
+char(3,30617).
+char(0,30618).
+char(5,30619).
+char(c,30620).
+char(m,30621).
+char(o,30622).
+char(m,30623).
+char(5,30624).
+char(4,30625).
+char(0,30626).
+char(6,30627).
+char(c,30628).
+char(m,30629).
+char(o,30630).
+char(1,30631).
+char(1,30632).
+char(4,30633).
+char(9,30634).
+char(m,30635).
+char(o,30636).
+char(m,30637).
+char(3,30638).
+char(8,30639).
+char(5,30640).
+char(2,30641).
+char(m,30642).
+char(o,30643).
+char(m,30644).
+char(o,30645).
+char(m,30646).
+char(o,30647).
+char(p,30648).
+char(9,30649).
+char(3,30650).
+char(3,30651).
+char(1,30652).
+char(c,30653).
+char(p,30654).
+char(5,30655).
+char(8,30656).
+char(9,30657).
+char(4,30658).
+char(c,30659).
+char(c,30660).
+char(c,30661).
+char(c,30662).
+char(c,30663).
+char(c,30664).
+char(c,30665).
+char(c,30666).
+char(m,30667).
+char(o,30668).
+char(p,30669).
+char(o,30670).
+char(o,30671).
+char(m,30672).
+char(o,30673).
+char(p,30674).
+char(2,30675).
+char(6,30676).
+char(0,30677).
+char(4,30678).
+char(c,30679).
+char(m,30680).
+char(o,30681).
+char(8,30682).
+char(0,30683).
+char(3,30684).
+char(5,30685).
+char(m,30686).
+char(2,30687).
+char(8,30688).
+char(8,30689).
+char(4,30690).
+char(p,30691).
+char(4,30692).
+char(6,30693).
+char(6,30694).
+char(2,30695).
+char(m,30696).
+char(3,30697).
+char(4,30698).
+char(m,30699).
+char(3,30700).
+char(9,30701).
+char(4,30702).
+char(4,30703).
+char(c,30704).
+char(p,30705).
+char(o,30706).
+char(p,30707).
+char(o,30708).
+char(o,30709).
+char(p,30710).
+char(1,30711).
+char(0,30712).
+char(0,30713).
+char(2,30714).
+char(m,30715).
+char(6,30716).
+char(4,30717).
+char(8,30718).
+char(c,30719).
+char(c,30720).
+char(c,30721).
+char(c,30722).
+char(c,30723).
+char(p,30724).
+char(9,30725).
+char(8,30726).
+char(4,30727).
+char(c,30728).
+char(p,30729).
+char(o,30730).
+char(o,30731).
+char(m,30732).
+char(o,30733).
+char(o,30734).
+char(p,30735).
+char(o,30736).
+char(m,30737).
+char(7,30738).
+char(7,30739).
+char(1,30740).
+char(4,30741).
+char(c,30742).
+char(c,30743).
+char(p,30744).
+char(5,30745).
+char(1,30746).
+char(9,30747).
+char(0,30748).
+char(m,30749).
+char(3,30750).
+char(6,30751).
+char(5,30752).
+char(3,30753).
+char(m,30754).
+char(o,30755).
+char(m,30756).
+char(o,30757).
+char(p,30758).
+char(o,30759).
+char(o,30760).
+char(m,30761).
+char(9,30762).
+char(8,30763).
+char(2,30764).
+char(2,30765).
+char(c,30766).
+char(m,30767).
+char(o,30768).
+char(m,30769).
+char(o,30770).
+char(6,30771).
+char(5,30772).
+char(4,30773).
+char(6,30774).
+char(m,30775).
+char(o,30776).
+char(p,30777).
+char(o,30778).
+char(p,30779).
+char(3,30780).
+char(3,30781).
+char(1,30782).
+char(5,30783).
+char(c,30784).
+char(m,30785).
+char(o,30786).
+char(p,30787).
+char(o,30788).
+char(m,30789).
+char(o,30790).
+char(o,30791).
+char(6,30792).
+char(5,30793).
+char(0,30794).
+char(0,30795).
+char(c,30796).
+char(c,30797).
+char(c,30798).
+char(m,30799).
+char(4,30800).
+char(3,30801).
+char(8,30802).
+char(0,30803).
+char(c,30804).
+char(m,30805).
+char(o,30806).
+char(m,30807).
+char(o,30808).
+char(o,30809).
+char(m,30810).
+char(2,30811).
+char(0,30812).
+char(7,30813).
+char(0,30814).
+char(c,30815).
+char(c,30816).
+char(c,30817).
+char(c,30818).
+char(p,30819).
+char(1,30820).
+char(7,30821).
+char(7,30822).
+char(9,30823).
+char(m,30824).
+char(o,30825).
+char(p,30826).
+char(o,30827).
+char(1,30828).
+char(1,30829).
+char(1,30830).
+char(8,30831).
+char(c,30832).
+char(p,30833).
+char(o,30834).
+char(m,30835).
+char(o,30836).
+char(m,30837).
+char(5,30838).
+char(1,30839).
+char(7,30840).
+char(4,30841).
+char(c,30842).
+char(c,30843).
+char(c,30844).
+char(c,30845).
+char(c,30846).
+char(p,30847).
+char(8,30848).
+char(3,30849).
+char(4,30850).
+char(1,30851).
+char(m,30852).
+char(o,30853).
+char(9,30854).
+char(1,30855).
+char(7,30856).
+char(0,30857).
+char(p,30858).
+char(9,30859).
+char(2,30860).
+char(6,30861).
+char(5,30862).
+char(c,30863).
+char(m,30864).
+char(9,30865).
+char(6,30866).
+char(2,30867).
+char(7,30868).
+char(c,30869).
+char(c,30870).
+char(c,30871).
+char(c,30872).
+char(c,30873).
+char(p,30874).
+char(o,30875).
+char(p,30876).
+char(o,30877).
+char(p,30878).
+char(o,30879).
+char(p,30880).
+char(o,30881).
+char(o,30882).
+char(m,30883).
+char(o,30884).
+char(4,30885).
+char(7,30886).
+char(7,30887).
+char(1,30888).
+char(c,30889).
+char(c,30890).
+char(p,30891).
+char(1,30892).
+char(0,30893).
+char(7,30894).
+char(5,30895).
+char(p,30896).
+char(7,30897).
+char(9,30898).
+char(1,30899).
+char(1,30900).
+char(c,30901).
+char(m,30902).
+char(o,30903).
+char(m,30904).
+char(o,30905).
+char(p,30906).
+char(o,30907).
+char(m,30908).
+char(o,30909).
+char(p,30910).
+char(o,30911).
+char(m,30912).
+char(o,30913).
+char(p,30914).
+char(o,30915).
+char(p,30916).
+char(o,30917).
+char(5,30918).
+char(4,30919).
+char(7,30920).
+char(9,30921).
+char(c,30922).
+char(c,30923).
+char(p,30924).
+char(o,30925).
+char(p,30926).
+char(o,30927).
+char(p,30928).
+char(5,30929).
+char(4,30930).
+char(0,30931).
+char(2,30932).
+char(p,30933).
+char(8,30934).
+char(0,30935).
+char(7,30936).
+char(3,30937).
+char(p,30938).
+char(o,30939).
+char(m,30940).
+char(o,30941).
+char(m,30942).
+char(o,30943).
+char(7,30944).
+char(1,30945).
+char(7,30946).
+char(8,30947).
+char(m,30948).
+char(8,30949).
+char(9,30950).
+char(9,30951).
+char(9,30952).
+char(c,30953).
+char(p,30954).
+char(3,30955).
+char(4,30956).
+char(7,30957).
+char(7,30958).
+char(m,30959).
+char(7,30960).
+char(0,30961).
+char(2,30962).
+char(2,30963).
+char(c,30964).
+char(m,30965).
+char(o,30966).
+char(o,30967).
+char(m,30968).
+char(4,30969).
+char(7,30970).
+char(1,30971).
+char(0,30972).
+char(c,30973).
+char(c,30974).
+char(m,30975).
+char(9,30976).
+char(6,30977).
+char(6,30978).
+char(5,30979).
+char(c,30980).
+char(c,30981).
+char(p,30982).
+char(o,30983).
+char(m,30984).
+char(o,30985).
+char(o,30986).
+char(p,30987).
+char(o,30988).
+char(m,30989).
+char(2,30990).
+char(0,30991).
+char(2,30992).
+char(4,30993).
+char(p,30994).
+char(o,30995).
+char(9,30996).
+char(8,30997).
+char(2,30998).
+char(9,30999).
+char(p,31000).
+char(o,31001).
+char(m,31002).
+char(o,31003).
+char(m,31004).
+char(o,31005).
+char(3,31006).
+char(9,31007).
+char(0,31008).
+char(1,31009).
+char(m,31010).
+char(7,31011).
+char(4,31012).
+char(0,31013).
+char(c,31014).
+char(p,31015).
+char(5,31016).
+char(3,31017).
+char(0,31018).
+char(4,31019).
+char(m,31020).
+char(1,31021).
+char(8,31022).
+char(5,31023).
+char(p,31024).
+char(o,31025).
+char(o,31026).
+char(o,31027).
+char(m,31028).
+char(8,31029).
+char(5,31030).
+char(8,31031).
+char(1,31032).
+char(c,31033).
+char(m,31034).
+char(o,31035).
+char(o,31036).
+char(m,31037).
+char(o,31038).
+char(4,31039).
+char(9,31040).
+char(8,31041).
+char(2,31042).
+char(c,31043).
+char(c,31044).
+char(p,31045).
+char(4,31046).
+char(0,31047).
+char(7,31048).
+char(9,31049).
+char(c,31050).
+char(c,31051).
+char(c,31052).
+char(p,31053).
+char(o,31054).
+char(p,31055).
+char(o,31056).
+char(m,31057).
+char(o,31058).
+char(o,31059).
+char(p,31060).
+char(4,31061).
+char(9,31062).
+char(0,31063).
+char(5,31064).
+char(p,31065).
+char(o,31066).
+char(p,31067).
+char(o,31068).
+char(m,31069).
+char(3,31070).
+char(1,31071).
+char(8,31072).
+char(8,31073).
+char(c,31074).
+char(c,31075).
+char(c,31076).
+char(c,31077).
+char(m,31078).
+char(6,31079).
+char(0,31080).
+char(1,31081).
+char(5,31082).
+char(m,31083).
+char(3,31084).
+char(9,31085).
+char(3,31086).
+char(6,31087).
+char(c,31088).
+char(c,31089).
+char(c,31090).
+char(m,31091).
+char(o,31092).
+char(4,31093).
+char(4,31094).
+char(4,31095).
+char(8,31096).
+char(m,31097).
+char(o,31098).
+char(o,31099).
+char(m,31100).
+char(o,31101).
+char(p,31102).
+char(o,31103).
+char(p,31104).
+char(o,31105).
+char(p,31106).
+char(o,31107).
+char(p,31108).
+char(o,31109).
+char(o,31110).
+char(m,31111).
+char(o,31112).
+char(m,31113).
+char(8,31114).
+char(4,31115).
+char(4,31116).
+char(4,31117).
+char(p,31118).
+char(5,31119).
+char(6,31120).
+char(3,31121).
+char(8,31122).
+char(c,31123).
+char(c,31124).
+char(c,31125).
+char(m,31126).
+char(o,31127).
+char(m,31128).
+char(2,31129).
+char(3,31130).
+char(4,31131).
+char(8,31132).
+char(c,31133).
+char(m,31134).
+char(6,31135).
+char(6,31136).
+char(1,31137).
+char(8,31138).
+char(m,31139).
+char(o,31140).
+char(m,31141).
+char(o,31142).
+char(m,31143).
+char(3,31144).
+char(1,31145).
+char(3,31146).
+char(2,31147).
+char(c,31148).
+char(c,31149).
+char(c,31150).
+char(c,31151).
+char(m,31152).
+char(3,31153).
+char(6,31154).
+char(9,31155).
+char(9,31156).
+char(m,31157).
+char(o,31158).
+char(m,31159).
+char(o,31160).
+char(7,31161).
+char(3,31162).
+char(4,31163).
+char(7,31164).
+char(p,31165).
+char(8,31166).
+char(7,31167).
+char(8,31168).
+char(8,31169).
+char(m,31170).
+char(7,31171).
+char(3,31172).
+char(0,31173).
+char(0,31174).
+char(c,31175).
+char(p,31176).
+char(o,31177).
+char(1,31178).
+char(7,31179).
+char(8,31180).
+char(2,31181).
+char(c,31182).
+char(p,31183).
+char(o,31184).
+char(o,31185).
+char(p,31186).
+char(7,31187).
+char(0,31188).
+char(7,31189).
+char(9,31190).
+char(m,31191).
+char(4,31192).
+char(7,31193).
+char(6,31194).
+char(2,31195).
+char(p,31196).
+char(6,31197).
+char(6,31198).
+char(5,31199).
+char(5,31200).
+char(m,31201).
+char(o,31202).
+char(p,31203).
+char(3,31204).
+char(8,31205).
+char(4,31206).
+char(6,31207).
+char(c,31208).
+char(c,31209).
+char(p,31210).
+char(o,31211).
+char(o,31212).
+char(m,31213).
+char(4,31214).
+char(5,31215).
+char(7,31216).
+char(9,31217).
+char(c,31218).
+char(c,31219).
+char(c,31220).
+char(c,31221).
+char(c,31222).
+char(p,31223).
+char(o,31224).
+char(p,31225).
+char(o,31226).
+char(p,31227).
+char(o,31228).
+char(8,31229).
+char(3,31230).
+char(1,31231).
+char(5,31232).
+char(c,31233).
+char(m,31234).
+char(9,31235).
+char(3,31236).
+char(6,31237).
+char(c,31238).
+char(m,31239).
+char(o,31240).
+char(6,31241).
+char(7,31242).
+char(8,31243).
+char(8,31244).
+char(c,31245).
+char(c,31246).
+char(c,31247).
+char(m,31248).
+char(2,31249).
+char(6,31250).
+char(9,31251).
+char(3,31252).
+char(c,31253).
+char(c,31254).
+char(m,31255).
+char(o,31256).
+char(p,31257).
+char(o,31258).
+char(5,31259).
+char(8,31260).
+char(8,31261).
+char(7,31262).
+char(c,31263).
+char(c,31264).
+char(c,31265).
+char(c,31266).
+char(m,31267).
+char(o,31268).
+char(p,31269).
+char(1,31270).
+char(8,31271).
+char(6,31272).
+char(9,31273).
+char(c,31274).
+char(m,31275).
+char(o,31276).
+char(o,31277).
+char(p,31278).
+char(o,31279).
+char(o,31280).
+char(5,31281).
+char(7,31282).
+char(9,31283).
+char(1,31284).
+char(c,31285).
+char(c,31286).
+char(p,31287).
+char(9,31288).
+char(1,31289).
+char(8,31290).
+char(2,31291).
+char(c,31292).
+char(m,31293).
+char(o,31294).
+char(m,31295).
+char(o,31296).
+char(p,31297).
+char(o,31298).
+char(p,31299).
+char(9,31300).
+char(6,31301).
+char(9,31302).
+char(5,31303).
+char(m,31304).
+char(5,31305).
+char(7,31306).
+char(9,31307).
+char(8,31308).
+char(c,31309).
+char(p,31310).
+char(4,31311).
+char(2,31312).
+char(5,31313).
+char(2,31314).
+char(p,31315).
+char(3,31316).
+char(2,31317).
+char(5,31318).
+char(5,31319).
+char(c,31320).
+char(c,31321).
+char(p,31322).
+char(9,31323).
+char(8,31324).
+char(8,31325).
+char(7,31326).
+char(c,31327).
+char(c,31328).
+char(c,31329).
+char(p,31330).
+char(o,31331).
+char(p,31332).
+char(o,31333).
+char(p,31334).
+char(3,31335).
+char(6,31336).
+char(2,31337).
+char(1,31338).
+char(p,31339).
+char(o,31340).
+char(p,31341).
+char(o,31342).
+char(p,31343).
+char(o,31344).
+char(6,31345).
+char(5,31346).
+char(2,31347).
+char(0,31348).
+char(c,31349).
+char(c,31350).
+char(c,31351).
+char(c,31352).
+char(c,31353).
+char(c,31354).
+char(m,31355).
+char(o,31356).
+char(p,31357).
+char(1,31358).
+char(7,31359).
+char(8,31360).
+char(3,31361).
+char(m,31362).
+char(o,31363).
+char(p,31364).
+char(o,31365).
+char(p,31366).
+char(7,31367).
+char(2,31368).
+char(3,31369).
+char(8,31370).
+char(c,31371).
+char(c,31372).
+char(c,31373).
+char(c,31374).
+char(c,31375).
+char(m,31376).
+char(o,31377).
+char(o,31378).
+char(6,31379).
+char(5,31380).
+char(2,31381).
+char(7,31382).
+char(m,31383).
+char(o,31384).
+char(o,31385).
+char(o,31386).
+char(3,31387).
+char(3,31388).
+char(5,31389).
+char(c,31390).
+char(c,31391).
+char(m,31392).
+char(7,31393).
+char(1,31394).
+char(1,31395).
+char(5,31396).
+char(c,31397).
+char(c,31398).
+char(c,31399).
+char(c,31400).
+char(c,31401).
+char(c,31402).
+char(c,31403).
+char(c,31404).
+char(c,31405).
+char(p,31406).
+char(o,31407).
+char(2,31408).
+char(3,31409).
+char(4,31410).
+char(3,31411).
+char(m,31412).
+char(o,31413).
+char(o,31414).
+char(8,31415).
+char(4,31416).
+char(7,31417).
+char(9,31418).
+char(m,31419).
+char(o,31420).
+char(p,31421).
+char(o,31422).
+char(4,31423).
+char(9,31424).
+char(6,31425).
+char(5,31426).
+char(p,31427).
+char(o,31428).
+char(o,31429).
+char(p,31430).
+char(3,31431).
+char(7,31432).
+char(2,31433).
+char(c,31434).
+char(p,31435).
+char(9,31436).
+char(8,31437).
+char(3,31438).
+char(3,31439).
+char(c,31440).
+char(p,31441).
+char(o,31442).
+char(m,31443).
+char(o,31444).
+char(p,31445).
+char(o,31446).
+char(o,31447).
+char(6,31448).
+char(5,31449).
+char(9,31450).
+char(2,31451).
+char(m,31452).
+char(o,31453).
+char(p,31454).
+char(9,31455).
+char(2,31456).
+char(9,31457).
+char(6,31458).
+char(c,31459).
+char(p,31460).
+char(o,31461).
+char(m,31462).
+char(o,31463).
+char(6,31464).
+char(4,31465).
+char(8,31466).
+char(8,31467).
+char(c,31468).
+char(c,31469).
+char(p,31470).
+char(o,31471).
+char(m,31472).
+char(2,31473).
+char(6,31474).
+char(0,31475).
+char(4,31476).
+char(c,31477).
+char(m,31478).
+char(o,31479).
+char(m,31480).
+char(o,31481).
+char(m,31482).
+char(o,31483).
+char(m,31484).
+char(2,31485).
+char(3,31486).
+char(2,31487).
+char(1,31488).
+char(c,31489).
+char(m,31490).
+char(1,31491).
+char(8,31492).
+char(1,31493).
+char(0,31494).
+char(m,31495).
+char(o,31496).
+char(3,31497).
+char(9,31498).
+char(m,31499).
+char(9,31500).
+char(8,31501).
+char(8,31502).
+char(9,31503).
+char(c,31504).
+char(c,31505).
+char(c,31506).
+char(p,31507).
+char(5,31508).
+char(6,31509).
+char(2,31510).
+char(8,31511).
+char(m,31512).
+char(7,31513).
+char(7,31514).
+char(0,31515).
+char(2,31516).
+char(p,31517).
+char(o,31518).
+char(m,31519).
+char(7,31520).
+char(3,31521).
+char(8,31522).
+char(c,31523).
+char(p,31524).
+char(o,31525).
+char(p,31526).
+char(8,31527).
+char(8,31528).
+char(1,31529).
+char(4,31530).
+char(p,31531).
+char(3,31532).
+char(8,31533).
+char(6,31534).
+char(3,31535).
+char(m,31536).
+char(o,31537).
+char(m,31538).
+char(o,31539).
+char(p,31540).
+char(o,31541).
+char(p,31542).
+char(o,31543).
+char(2,31544).
+char(8,31545).
+char(5,31546).
+char(6,31547).
+char(m,31548).
+char(7,31549).
+char(2,31550).
+char(7,31551).
+char(6,31552).
+char(m,31553).
+char(1,31554).
+char(5,31555).
+char(5,31556).
+char(0,31557).
+char(m,31558).
+char(o,31559).
+char(m,31560).
+char(o,31561).
+char(m,31562).
+char(o,31563).
+char(p,31564).
+char(o,31565).
+char(m,31566).
+char(o,31567).
+char(o,31568).
+char(o,31569).
+char(m,31570).
+char(6,31571).
+char(2,31572).
+char(6,31573).
+char(m,31574).
+char(2,31575).
+char(4,31576).
+char(0,31577).
+char(6,31578).
+char(c,31579).
+char(c,31580).
+char(c,31581).
+char(c,31582).
+char(c,31583).
+char(c,31584).
+char(p,31585).
+char(7,31586).
+char(5,31587).
+char(7,31588).
+char(9,31589).
+char(c,31590).
+char(c,31591).
+char(c,31592).
+char(c,31593).
+char(c,31594).
+char(m,31595).
+char(o,31596).
+char(8,31597).
+char(6,31598).
+char(c,31599).
+char(p,31600).
+char(o,31601).
+char(p,31602).
+char(4,31603).
+char(7,31604).
+char(0,31605).
+char(1,31606).
+char(p,31607).
+char(7,31608).
+char(3,31609).
+char(9,31610).
+char(9,31611).
+char(c,31612).
+char(c,31613).
+char(c,31614).
+char(m,31615).
+char(8,31616).
+char(2,31617).
+char(7,31618).
+char(3,31619).
+char(c,31620).
+char(m,31621).
+char(7,31622).
+char(2,31623).
+char(8,31624).
+char(9,31625).
+char(p,31626).
+char(8,31627).
+char(7,31628).
+char(1,31629).
+char(6,31630).
+char(c,31631).
+char(c,31632).
+char(m,31633).
+char(2,31634).
+char(5,31635).
+char(4,31636).
+char(1,31637).
+char(c,31638).
+char(c,31639).
+char(m,31640).
+char(1,31641).
+char(6,31642).
+char(0,31643).
+char(4,31644).
+char(p,31645).
+char(3,31646).
+char(9,31647).
+char(2,31648).
+char(0,31649).
+char(c,31650).
+char(c,31651).
+char(m,31652).
+char(o,31653).
+char(m,31654).
+char(o,31655).
+char(m,31656).
+char(9,31657).
+char(0,31658).
+char(5,31659).
+char(4,31660).
+char(m,31661).
+char(o,31662).
+char(p,31663).
+char(8,31664).
+char(9,31665).
+char(8,31666).
+char(2,31667).
+char(c,31668).
+char(p,31669).
+char(o,31670).
+char(3,31671).
+char(2,31672).
+char(0,31673).
+char(1,31674).
+char(c,31675).
+char(m,31676).
+char(9,31677).
+char(5,31678).
+char(8,31679).
+char(6,31680).
+char(c,31681).
+char(m,31682).
+char(o,31683).
+char(9,31684).
+char(3,31685).
+char(7,31686).
+char(9,31687).
+char(c,31688).
+char(p,31689).
+char(o,31690).
+char(5,31691).
+char(0,31692).
+char(2,31693).
+char(9,31694).
+char(m,31695).
+char(o,31696).
+char(p,31697).
+char(o,31698).
+char(1,31699).
+char(0,31700).
+char(0,31701).
+char(6,31702).
+char(c,31703).
+char(p,31704).
+char(o,31705).
+char(p,31706).
+char(7,31707).
+char(8,31708).
+char(6,31709).
+char(4,31710).
+char(c,31711).
+char(c,31712).
+char(m,31713).
+char(6,31714).
+char(3,31715).
+char(0,31716).
+char(3,31717).
+char(p,31718).
+char(6,31719).
+char(3,31720).
+char(9,31721).
+char(p,31722).
+char(o,31723).
+char(o,31724).
+char(o,31725).
+char(p,31726).
+char(2,31727).
+char(1,31728).
+char(0,31729).
+char(2,31730).
+char(p,31731).
+char(o,31732).
+char(o,31733).
+char(2,31734).
+char(4,31735).
+char(3,31736).
+char(9,31737).
+char(p,31738).
+char(o,31739).
+char(o,31740).
+char(p,31741).
+char(o,31742).
+char(p,31743).
+char(3,31744).
+char(4,31745).
+char(5,31746).
+char(2,31747).
+char(m,31748).
+char(o,31749).
+char(3,31750).
+char(1,31751).
+char(6,31752).
+char(3,31753).
+char(c,31754).
+char(p,31755).
+char(o,31756).
+char(m,31757).
+char(9,31758).
+char(3,31759).
+char(7,31760).
+char(4,31761).
+char(p,31762).
+char(4,31763).
+char(2,31764).
+char(8,31765).
+char(8,31766).
+char(p,31767).
+char(8,31768).
+char(0,31769).
+char(8,31770).
+char(2,31771).
+char(c,31772).
+char(p,31773).
+char(6,31774).
+char(9,31775).
+char(5,31776).
+char(p,31777).
+char(3,31778).
+char(7,31779).
+char(4,31780).
+char(2,31781).
+char(p,31782).
+char(o,31783).
+char(p,31784).
+char(1,31785).
+char(5,31786).
+char(5,31787).
+char(0,31788).
+char(p,31789).
+char(o,31790).
+char(p,31791).
+char(4,31792).
+char(7,31793).
+char(1,31794).
+char(p,31795).
+char(7,31796).
+char(6,31797).
+char(7,31798).
+char(m,31799).
+char(o,31800).
+char(5,31801).
+char(8,31802).
+char(8,31803).
+char(2,31804).
+char(m,31805).
+char(1,31806).
+char(8,31807).
+char(3,31808).
+char(m,31809).
+char(7,31810).
+char(1,31811).
+char(1,31812).
+char(4,31813).
+char(c,31814).
+char(p,31815).
+char(o,31816).
+char(m,31817).
+char(o,31818).
+char(o,31819).
+char(m,31820).
+char(o,31821).
+char(o,31822).
+char(m,31823).
+char(o,31824).
+char(m,31825).
+char(4,31826).
+char(2,31827).
+char(6,31828).
+char(9,31829).
+char(p,31830).
+char(8,31831).
+char(2,31832).
+char(6,31833).
+char(5,31834).
+char(c,31835).
+char(c,31836).
+char(m,31837).
+char(7,31838).
+char(9,31839).
+char(8,31840).
+char(8,31841).
+char(p,31842).
+char(o,31843).
+char(p,31844).
+char(5,31845).
+char(0,31846).
+char(9,31847).
+char(8,31848).
+char(c,31849).
+char(p,31850).
+char(4,31851).
+char(4,31852).
+char(4,31853).
+char(7,31854).
+char(c,31855).
+char(c,31856).
+char(c,31857).
+char(c,31858).
+char(c,31859).
+char(c,31860).
+char(p,31861).
+char(o,31862).
+char(m,31863).
+char(5,31864).
+char(7,31865).
+char(0,31866).
+char(0,31867).
+char(c,31868).
+char(c,31869).
+char(c,31870).
+char(p,31871).
+char(1,31872).
+char(6,31873).
+char(5,31874).
+char(2,31875).
+char(c,31876).
+char(p,31877).
+char(o,31878).
+char(p,31879).
+char(o,31880).
+char(p,31881).
+char(o,31882).
+char(o,31883).
+char(4,31884).
+char(2,31885).
+char(6,31886).
+char(3,31887).
+char(c,31888).
+char(c,31889).
+char(c,31890).
+char(p,31891).
+char(4,31892).
+char(2,31893).
+char(9,31894).
+char(6,31895).
+char(c,31896).
+char(p,31897).
+char(7,31898).
+char(5,31899).
+char(8,31900).
+char(7,31901).
+char(c,31902).
+char(m,31903).
+char(o,31904).
+char(p,31905).
+char(4,31906).
+char(2,31907).
+char(0,31908).
+char(9,31909).
+char(c,31910).
+char(m,31911).
+char(7,31912).
+char(4,31913).
+char(4,31914).
+char(4,31915).
+char(c,31916).
+char(m,31917).
+char(o,31918).
+char(m,31919).
+char(o,31920).
+char(o,31921).
+char(p,31922).
+char(o,31923).
+char(m,31924).
+char(9,31925).
+char(1,31926).
+char(3,31927).
+char(c,31928).
+char(m,31929).
+char(4,31930).
+char(8,31931).
+char(2,31932).
+char(5,31933).
+char(c,31934).
+char(c,31935).
+char(c,31936).
+char(m,31937).
+char(o,31938).
+char(p,31939).
+char(6,31940).
+char(1,31941).
+char(8,31942).
+char(9,31943).
+char(c,31944).
+char(p,31945).
+char(o,31946).
+char(o,31947).
+char(m,31948).
+char(o,31949).
+char(p,31950).
+char(o,31951).
+char(p,31952).
+char(3,31953).
+char(8,31954).
+char(9,31955).
+char(2,31956).
+char(p,31957).
+char(o,31958).
+char(o,31959).
+char(p,31960).
+char(4,31961).
+char(2,31962).
+char(3,31963).
+char(4,31964).
+char(c,31965).
+char(p,31966).
+char(o,31967).
+char(1,31968).
+char(3,31969).
+char(9,31970).
+char(p,31971).
+char(o,31972).
+char(m,31973).
+char(o,31974).
+char(4,31975).
+char(4,31976).
+char(6,31977).
+char(4,31978).
+char(p,31979).
+char(8,31980).
+char(0,31981).
+char(4,31982).
+char(3,31983).
+char(m,31984).
+char(o,31985).
+char(m,31986).
+char(o,31987).
+char(m,31988).
+char(o,31989).
+char(p,31990).
+char(o,31991).
+char(p,31992).
+char(4,31993).
+char(6,31994).
+char(4,31995).
+char(6,31996).
+char(c,31997).
+char(m,31998).
+char(3,31999).
+char(2,32000).
+char(5,32001).
+char(8,32002).
+char(c,32003).
+char(c,32004).
+char(p,32005).
+char(9,32006).
+char(5,32007).
+char(9,32008).
+char(m,32009).
+char(7,32010).
+char(7,32011).
+char(7,32012).
+char(5,32013).
+char(c,32014).
+char(m,32015).
+char(2,32016).
+char(9,32017).
+char(5,32018).
+char(5,32019).
+char(m,32020).
+char(6,32021).
+char(5,32022).
+char(1,32023).
+char(0,32024).
+char(p,32025).
+char(o,32026).
+char(1,32027).
+char(8,32028).
+char(8,32029).
+char(1,32030).
+char(m,32031).
+char(o,32032).
+char(p,32033).
+char(2,32034).
+char(1,32035).
+char(8,32036).
+char(2,32037).
+char(m,32038).
+char(o,32039).
+char(o,32040).
+char(p,32041).
+char(o,32042).
+char(m,32043).
+char(1,32044).
+char(6,32045).
+char(9,32046).
+char(0,32047).
+char(m,32048).
+char(2,32049).
+char(2,32050).
+char(8,32051).
+char(6,32052).
+char(p,32053).
+char(o,32054).
+char(p,32055).
+char(o,32056).
+char(p,32057).
+char(o,32058).
+char(o,32059).
+char(p,32060).
+char(3,32061).
+char(7,32062).
+char(6,32063).
+char(5,32064).
+char(m,32065).
+char(o,32066).
+char(8,32067).
+char(2,32068).
+char(6,32069).
+char(1,32070).
+char(m,32071).
+char(5,32072).
+char(6,32073).
+char(0,32074).
+char(6,32075).
+char(c,32076).
+char(m,32077).
+char(o,32078).
+char(o,32079).
+char(p,32080).
+char(6,32081).
+char(2,32082).
+char(2,32083).
+char(3,32084).
+char(m,32085).
+char(9,32086).
+char(4,32087).
+char(2,32088).
+char(c,32089).
+char(p,32090).
+char(4,32091).
+char(2,32092).
+char(7,32093).
+char(3,32094).
+char(m,32095).
+char(o,32096).
+char(6,32097).
+char(3,32098).
+char(7,32099).
+char(7,32100).
+char(p,32101).
+char(9,32102).
+char(4,32103).
+char(6,32104).
+char(2,32105).
+char(c,32106).
+char(m,32107).
+char(7,32108).
+char(7,32109).
+char(0,32110).
+char(0,32111).
+char(p,32112).
+char(o,32113).
+char(4,32114).
+char(4,32115).
+char(0,32116).
+char(8,32117).
+char(p,32118).
+char(8,32119).
+char(2,32120).
+char(7,32121).
+char(2,32122).
+char(p,32123).
+char(o,32124).
+char(p,32125).
+char(o,32126).
+char(p,32127).
+char(o,32128).
+char(p,32129).
+char(o,32130).
+char(8,32131).
+char(7,32132).
+char(7,32133).
+char(2,32134).
+char(m,32135).
+char(4,32136).
+char(4,32137).
+char(9,32138).
+char(1,32139).
+char(c,32140).
+char(p,32141).
+char(3,32142).
+char(9,32143).
+char(0,32144).
+char(8,32145).
+char(c,32146).
+char(c,32147).
+char(p,32148).
+char(o,32149).
+char(m,32150).
+char(4,32151).
+char(2,32152).
+char(0,32153).
+char(0,32154).
+char(c,32155).
+char(p,32156).
+char(1,32157).
+char(5,32158).
+char(8,32159).
+char(p,32160).
+char(o,32161).
+char(o,32162).
+char(o,32163).
+char(1,32164).
+char(0,32165).
+char(4,32166).
+char(3,32167).
+char(c,32168).
+char(c,32169).
+char(c,32170).
+char(m,32171).
+char(o,32172).
+char(0,32173).
+char(m,32174).
+char(o,32175).
+char(o,32176).
+char(7,32177).
+char(6,32178).
+char(7,32179).
+char(5,32180).
+char(p,32181).
+char(9,32182).
+char(3,32183).
+char(8,32184).
+char(6,32185).
+char(c,32186).
+char(c,32187).
+char(p,32188).
+char(o,32189).
+char(6,32190).
+char(9,32191).
+char(7,32192).
+char(4,32193).
+char(m,32194).
+char(o,32195).
+char(m,32196).
+char(o,32197).
+char(m,32198).
+char(2,32199).
+char(6,32200).
+char(0,32201).
+char(6,32202).
+char(m,32203).
+char(6,32204).
+char(8,32205).
+char(3,32206).
+char(9,32207).
+char(c,32208).
+char(m,32209).
+char(o,32210).
+char(p,32211).
+char(6,32212).
+char(0,32213).
+char(4,32214).
+char(7,32215).
+char(c,32216).
+char(c,32217).
+char(c,32218).
+char(p,32219).
+char(o,32220).
+char(m,32221).
+char(9,32222).
+char(5,32223).
+char(5,32224).
+char(4,32225).
+char(m,32226).
+char(5,32227).
+char(4,32228).
+char(0,32229).
+char(1,32230).
+char(m,32231).
+char(o,32232).
+char(m,32233).
+char(8,32234).
+char(7,32235).
+char(6,32236).
+char(7,32237).
+char(m,32238).
+char(o,32239).
+char(o,32240).
+char(8,32241).
+char(6,32242).
+char(6,32243).
+char(1,32244).
+char(c,32245).
+char(m,32246).
+char(o,32247).
+char(m,32248).
+char(5,32249).
+char(2,32250).
+char(9,32251).
+char(3,32252).
+char(p,32253).
+char(o,32254).
+char(m,32255).
+char(7,32256).
+char(2,32257).
+char(8,32258).
+char(5,32259).
+char(c,32260).
+char(p,32261).
+char(o,32262).
+char(p,32263).
+char(3,32264).
+char(0,32265).
+char(7,32266).
+char(2,32267).
+char(m,32268).
+char(7,32269).
+char(5,32270).
+char(9,32271).
+char(1,32272).
+char(c,32273).
+char(c,32274).
+char(m,32275).
+char(5,32276).
+char(5,32277).
+char(7,32278).
+char(7,32279).
+char(c,32280).
+char(c,32281).
+char(c,32282).
+char(c,32283).
+char(m,32284).
+char(8,32285).
+char(5,32286).
+char(5,32287).
+char(9,32288).
+char(p,32289).
+char(3,32290).
+char(6,32291).
+char(7,32292).
+char(3,32293).
+char(p,32294).
+char(o,32295).
+char(o,32296).
+char(m,32297).
+char(7,32298).
+char(0,32299).
+char(9,32300).
+char(9,32301).
+char(c,32302).
+char(c,32303).
+char(m,32304).
+char(2,32305).
+char(5,32306).
+char(7,32307).
+char(0,32308).
+char(p,32309).
+char(6,32310).
+char(9,32311).
+char(0,32312).
+char(7,32313).
+char(p,32314).
+char(4,32315).
+char(2,32316).
+char(5,32317).
+char(1,32318).
+char(p,32319).
+char(6,32320).
+char(4,32321).
+char(8,32322).
+char(1,32323).
+char(m,32324).
+char(9,32325).
+char(6,32326).
+char(1,32327).
+char(2,32328).
+char(c,32329).
+char(c,32330).
+char(p,32331).
+char(3,32332).
+char(6,32333).
+char(2,32334).
+char(c,32335).
+char(p,32336).
+char(5,32337).
+char(3,32338).
+char(0,32339).
+char(5,32340).
+char(p,32341).
+char(3,32342).
+char(2,32343).
+char(0,32344).
+char(7,32345).
+char(p,32346).
+char(1,32347).
+char(7,32348).
+char(0,32349).
+char(6,32350).
+char(c,32351).
+char(p,32352).
+char(o,32353).
+char(p,32354).
+char(o,32355).
+char(5,32356).
+char(0,32357).
+char(1,32358).
+char(c,32359).
+char(p,32360).
+char(5,32361).
+char(3,32362).
+char(0,32363).
+char(6,32364).
+char(p,32365).
+char(o,32366).
+char(m,32367).
+char(o,32368).
+char(p,32369).
+char(2,32370).
+char(0,32371).
+char(5,32372).
+char(7,32373).
+char(p,32374).
+char(o,32375).
+char(p,32376).
+char(o,32377).
+char(p,32378).
+char(3,32379).
+char(6,32380).
+char(9,32381).
+char(8,32382).
+char(c,32383).
+char(m,32384).
+char(6,32385).
+char(3,32386).
+char(3,32387).
+char(7,32388).
+char(c,32389).
+char(c,32390).
+char(c,32391).
+char(c,32392).
+char(m,32393).
+char(7,32394).
+char(9,32395).
+char(7,32396).
+char(7,32397).
+char(c,32398).
+char(m,32399).
+char(2,32400).
+char(8,32401).
+char(5,32402).
+char(m,32403).
+char(o,32404).
+char(o,32405).
+char(2,32406).
+char(5,32407).
+char(0,32408).
+char(3,32409).
+char(p,32410).
+char(o,32411).
+char(m,32412).
+char(1,32413).
+char(6,32414).
+char(6,32415).
+char(5,32416).
+char(c,32417).
+char(c,32418).
+char(c,32419).
+char(c,32420).
+char(p,32421).
+char(4,32422).
+char(5,32423).
+char(3,32424).
+char(3,32425).
+char(m,32426).
+char(5,32427).
+char(1,32428).
+char(9,32429).
+char(9,32430).
+char(p,32431).
+char(8,32432).
+char(0,32433).
+char(6,32434).
+char(8,32435).
+char(p,32436).
+char(o,32437).
+char(p,32438).
+char(6,32439).
+char(1,32440).
+char(8,32441).
+char(0,32442).
+char(c,32443).
+char(m,32444).
+char(2,32445).
+char(3,32446).
+char(2,32447).
+char(3,32448).
+char(c,32449).
+char(m,32450).
+char(9,32451).
+char(9,32452).
+char(1,32453).
+char(8,32454).
+char(m,32455).
+char(o,32456).
+char(p,32457).
+char(o,32458).
+char(8,32459).
+char(4,32460).
+char(8,32461).
+char(6,32462).
+char(c,32463).
+char(m,32464).
+char(5,32465).
+char(0,32466).
+char(0,32467).
+char(1,32468).
+char(p,32469).
+char(5,32470).
+char(5,32471).
+char(8,32472).
+char(2,32473).
+char(p,32474).
+char(o,32475).
+char(p,32476).
+char(o,32477).
+char(p,32478).
+char(o,32479).
+char(o,32480).
+char(8,32481).
+char(3,32482).
+char(3,32483).
+char(6,32484).
+char(m,32485).
+char(2,32486).
+char(1,32487).
+char(1,32488).
+char(0,32489).
+char(p,32490).
+char(o,32491).
+char(4,32492).
+char(4,32493).
+char(2,32494).
+char(4,32495).
+char(c,32496).
+char(m,32497).
+char(6,32498).
+char(4,32499).
+char(8,32500).
+char(5,32501).
+char(c,32502).
+char(c,32503).
+char(p,32504).
+char(7,32505).
+char(0,32506).
+char(8,32507).
+char(6,32508).
+char(c,32509).
+char(c,32510).
+char(c,32511).
+char(m,32512).
+char(o,32513).
+char(m,32514).
+char(o,32515).
+char(o,32516).
+char(7,32517).
+char(0,32518).
+char(4,32519).
+char(c,32520).
+char(c,32521).
+char(p,32522).
+char(4,32523).
+char(6,32524).
+char(6,32525).
+char(8,32526).
+char(c,32527).
+char(m,32528).
+char(2,32529).
+char(8,32530).
+char(5,32531).
+char(3,32532).
+char(c,32533).
+char(c,32534).
+char(c,32535).
+char(c,32536).
+char(p,32537).
+char(3,32538).
+char(5,32539).
+char(4,32540).
+char(8,32541).
+char(c,32542).
+char(c,32543).
+char(c,32544).
+char(c,32545).
+char(c,32546).
+char(c,32547).
+char(p,32548).
+char(5,32549).
+char(7,32550).
+char(2,32551).
+char(c,32552).
+char(p,32553).
+char(6,32554).
+char(0,32555).
+char(1,32556).
+char(7,32557).
+char(p,32558).
+char(o,32559).
+char(m,32560).
+char(o,32561).
+char(m,32562).
+char(o,32563).
+char(4,32564).
+char(2,32565).
+char(1,32566).
+char(0,32567).
+char(c,32568).
+char(c,32569).
+char(m,32570).
+char(o,32571).
+char(m,32572).
+char(o,32573).
+char(m,32574).
+char(o,32575).
+char(o,32576).
+char(p,32577).
+char(1,32578).
+char(7,32579).
+char(1,32580).
+char(9,32581).
+char(c,32582).
+char(c,32583).
+char(c,32584).
+char(p,32585).
+char(4,32586).
+char(3,32587).
+char(9,32588).
+char(9,32589).
+char(c,32590).
+char(m,32591).
+char(o,32592).
+char(9,32593).
+char(3,32594).
+char(0,32595).
+char(3,32596).
+char(c,32597).
+char(p,32598).
+char(o,32599).
+char(m,32600).
+char(7,32601).
+char(2,32602).
+char(8,32603).
+char(3,32604).
+char(p,32605).
+char(o,32606).
+char(o,32607).
+char(p,32608).
+char(o,32609).
+char(p,32610).
+char(o,32611).
+char(m,32612).
+char(6,32613).
+char(1,32614).
+char(0,32615).
+char(2,32616).
+char(c,32617).
+char(p,32618).
+char(1,32619).
+char(3,32620).
+char(2,32621).
+char(5,32622).
+char(p,32623).
+char(1,32624).
+char(3,32625).
+char(2,32626).
+char(5,32627).
+char(m,32628).
+char(o,32629).
+char(5,32630).
+char(0,32631).
+char(7,32632).
+char(8,32633).
+char(m,32634).
+char(o,32635).
+char(8,32636).
+char(7,32637).
+char(6,32638).
+char(1,32639).
+char(m,32640).
+char(6,32641).
+char(0,32642).
+char(9,32643).
+char(5,32644).
+char(p,32645).
+char(9,32646).
+char(6,32647).
+char(9,32648).
+char(5,32649).
+char(c,32650).
+char(m,32651).
+char(6,32652).
+char(5,32653).
+char(0,32654).
+char(1,32655).
+char(m,32656).
+char(o,32657).
+char(8,32658).
+char(6,32659).
+char(5,32660).
+char(6,32661).
+char(m,32662).
+char(7,32663).
+char(7,32664).
+char(5,32665).
+char(4,32666).
+char(m,32667).
+char(9,32668).
+char(7,32669).
+char(9,32670).
+char(2,32671).
+char(c,32672).
+char(c,32673).
+char(c,32674).
+char(c,32675).
+char(p,32676).
+char(7,32677).
+char(4,32678).
+char(5,32679).
+char(c,32680).
+char(c,32681).
+char(m,32682).
+char(2,32683).
+char(8,32684).
+char(8,32685).
+char(4,32686).
+char(p,32687).
+char(o,32688).
+char(m,32689).
+char(o,32690).
+char(m,32691).
+char(1,32692).
+char(4,32693).
+char(4,32694).
+char(8,32695).
+char(m,32696).
+char(3,32697).
+char(5,32698).
+char(7,32699).
+char(7,32700).
+char(c,32701).
+char(c,32702).
+char(c,32703).
+char(c,32704).
+char(p,32705).
+char(o,32706).
+char(1,32707).
+char(2,32708).
+char(9,32709).
+char(0,32710).
+char(m,32711).
+char(4,32712).
+char(7,32713).
+char(8,32714).
+char(c,32715).
+char(p,32716).
+char(2,32717).
+char(0,32718).
+char(9,32719).
+char(5,32720).
+char(m,32721).
+char(8,32722).
+char(7,32723).
+char(1,32724).
+char(1,32725).
+char(m,32726).
+char(8,32727).
+char(9,32728).
+char(7,32729).
+char(0,32730).
+char(m,32731).
+char(o,32732).
+char(p,32733).
+char(o,32734).
+char(m,32735).
+char(o,32736).
+char(p,32737).
+char(2,32738).
+char(6,32739).
+char(2,32740).
+char(1,32741).
+char(c,32742).
+char(p,32743).
+char(7,32744).
+char(3,32745).
+char(7,32746).
+char(9,32747).
+char(c,32748).
+char(p,32749).
+char(o,32750).
+char(m,32751).
+char(o,32752).
+char(m,32753).
+char(o,32754).
+char(p,32755).
+char(1,32756).
+char(6,32757).
+char(2,32758).
+char(9,32759).
+char(c,32760).
+char(p,32761).
+char(o,32762).
+char(o,32763).
+char(1,32764).
+char(0,32765).
+char(9,32766).
+char(5,32767).
+char(m,32768).
+char(5,32769).
+char(5,32770).
+char(1,32771).
+char(8,32772).
+char(c,32773).
+char(c,32774).
+char(p,32775).
+char(o,32776).
+char(p,32777).
+char(5,32778).
+char(2,32779).
+char(9,32780).
+char(0,32781).
+char(m,32782).
+char(7,32783).
+char(1,32784).
+char(1,32785).
+char(4,32786).
+char(m,32787).
+char(6,32788).
+char(9,32789).
+char(1,32790).
+char(5,32791).
+char(c,32792).
+char(c,32793).
+char(c,32794).
+char(c,32795).
+char(p,32796).
+char(9,32797).
+char(8,32798).
+char(4,32799).
+char(m,32800).
+char(3,32801).
+char(4,32802).
+char(4,32803).
+char(5,32804).
+char(c,32805).
+char(m,32806).
+char(o,32807).
+char(8,32808).
+char(2,32809).
+char(7,32810).
+char(2,32811).
+char(c,32812).
+char(m,32813).
+char(3,32814).
+char(7,32815).
+char(0,32816).
+char(c,32817).
+char(m,32818).
+char(o,32819).
+char(1,32820).
+char(1,32821).
+char(4,32822).
+char(p,32823).
+char(o,32824).
+char(m,32825).
+char(o,32826).
+char(m,32827).
+char(3,32828).
+char(3,32829).
+char(4,32830).
+char(8,32831).
+char(c,32832).
+char(c,32833).
+char(c,32834).
+char(c,32835).
+char(p,32836).
+char(o,32837).
+char(3,32838).
+char(9,32839).
+char(9,32840).
+char(2,32841).
+char(c,32842).
+char(c,32843).
+char(c,32844).
+char(c,32845).
+char(p,32846).
+char(o,32847).
+char(p,32848).
+char(3,32849).
+char(1,32850).
+char(7,32851).
+char(0,32852).
+char(c,32853).
+char(c,32854).
+char(c,32855).
+char(m,32856).
+char(9,32857).
+char(8,32858).
+char(7,32859).
+char(7,32860).
+char(m,32861).
+char(o,32862).
+char(p,32863).
+char(o,32864).
+char(p,32865).
+char(3,32866).
+char(4,32867).
+char(7,32868).
+char(2,32869).
+char(m,32870).
+char(o,32871).
+char(7,32872).
+char(3,32873).
+char(8,32874).
+char(8,32875).
+char(c,32876).
+char(m,32877).
+char(6,32878).
+char(8,32879).
+char(8,32880).
+char(0,32881).
+char(m,32882).
+char(o,32883).
+char(p,32884).
+char(o,32885).
+char(p,32886).
+char(o,32887).
+char(p,32888).
+char(o,32889).
+char(m,32890).
+char(o,32891).
+char(m,32892).
+char(5,32893).
+char(7,32894).
+char(6,32895).
+char(8,32896).
+char(c,32897).
+char(c,32898).
+char(m,32899).
+char(4,32900).
+char(0,32901).
+char(1,32902).
+char(7,32903).
+char(p,32904).
+char(o,32905).
+char(p,32906).
+char(o,32907).
+char(m,32908).
+char(7,32909).
+char(4,32910).
+char(6,32911).
+char(m,32912).
+char(5,32913).
+char(9,32914).
+char(2,32915).
+char(6,32916).
+char(c,32917).
+char(m,32918).
+char(5,32919).
+char(1,32920).
+char(8,32921).
+char(3,32922).
+char(c,32923).
+char(p,32924).
+char(o,32925).
+char(m,32926).
+char(o,32927).
+char(p,32928).
+char(2,32929).
+char(0,32930).
+char(6,32931).
+char(3,32932).
+char(c,32933).
+char(c,32934).
+char(c,32935).
+char(c,32936).
+char(m,32937).
+char(5,32938).
+char(1,32939).
+char(8,32940).
+char(7,32941).
+char(c,32942).
+char(c,32943).
+char(p,32944).
+char(o,32945).
+char(4,32946).
+char(6,32947).
+char(0,32948).
+char(4,32949).
+char(p,32950).
+char(o,32951).
+char(m,32952).
+char(2,32953).
+char(0,32954).
+char(2,32955).
+char(9,32956).
+char(p,32957).
+char(6,32958).
+char(8,32959).
+char(5,32960).
+char(0,32961).
+char(c,32962).
+char(p,32963).
+char(5,32964).
+char(0,32965).
+char(5,32966).
+char(2,32967).
+char(m,32968).
+char(1,32969).
+char(5,32970).
+char(6,32971).
+char(7,32972).
+char(p,32973).
+char(1,32974).
+char(5,32975).
+char(6,32976).
+char(3,32977).
+char(p,32978).
+char(2,32979).
+char(0,32980).
+char(9,32981).
+char(4,32982).
+char(p,32983).
+char(o,32984).
+char(p,32985).
+char(o,32986).
+char(o,32987).
+char(o,32988).
+char(m,32989).
+char(2,32990).
+char(9,32991).
+char(7,32992).
+char(6,32993).
+char(c,32994).
+char(p,32995).
+char(3,32996).
+char(4,32997).
+char(7,32998).
+char(5,32999).
+char(c,33000).
+char(c,33001).
+char(c,33002).
+char(c,33003).
+char(p,33004).
+char(o,33005).
+char(m,33006).
+char(2,33007).
+char(5,33008).
+char(7,33009).
+char(5,33010).
+char(p,33011).
+char(7,33012).
+char(9,33013).
+char(7,33014).
+char(c,33015).
+char(c,33016).
+char(c,33017).
+char(c,33018).
+char(m,33019).
+char(o,33020).
+char(m,33021).
+char(o,33022).
+char(p,33023).
+char(o,33024).
+char(4,33025).
+char(6,33026).
+char(9,33027).
+char(6,33028).
+char(c,33029).
+char(p,33030).
+char(o,33031).
+char(m,33032).
+char(3,33033).
+char(0,33034).
+char(0,33035).
+char(2,33036).
+char(m,33037).
+char(o,33038).
+char(m,33039).
+char(1,33040).
+char(5,33041).
+char(3,33042).
+char(8,33043).
+char(m,33044).
+char(7,33045).
+char(1,33046).
+char(0,33047).
+char(0,33048).
+char(m,33049).
+char(o,33050).
+char(2,33051).
+char(6,33052).
+char(0,33053).
+char(7,33054).
+char(p,33055).
+char(o,33056).
+char(m,33057).
+char(7,33058).
+char(3,33059).
+char(2,33060).
+char(7,33061).
+char(m,33062).
+char(8,33063).
+char(5,33064).
+char(1,33065).
+char(6,33066).
+char(p,33067).
+char(o,33068).
+char(p,33069).
+char(9,33070).
+char(3,33071).
+char(8,33072).
+char(3,33073).
+char(c,33074).
+char(m,33075).
+char(1,33076).
+char(5,33077).
+char(4,33078).
+char(2,33079).
+char(m,33080).
+char(o,33081).
+char(5,33082).
+char(8,33083).
+char(5,33084).
+char(6,33085).
+char(p,33086).
+char(1,33087).
+char(9,33088).
+char(7,33089).
+char(0,33090).
+char(c,33091).
+char(m,33092).
+char(6,33093).
+char(2,33094).
+char(4,33095).
+char(7,33096).
+char(c,33097).
+char(c,33098).
+char(c,33099).
+char(m,33100).
+char(o,33101).
+char(o,33102).
+char(p,33103).
+char(o,33104).
+char(o,33105).
+char(p,33106).
+char(o,33107).
+char(p,33108).
+char(5,33109).
+char(5,33110).
+char(9,33111).
+char(7,33112).
+char(m,33113).
+char(6,33114).
+char(9,33115).
+char(4,33116).
+char(3,33117).
+char(c,33118).
+char(c,33119).
+char(p,33120).
+char(o,33121).
+char(p,33122).
+char(o,33123).
+char(m,33124).
+char(4,33125).
+char(0,33126).
+char(9,33127).
+char(6,33128).
+char(m,33129).
+char(7,33130).
+char(3,33131).
+char(1,33132).
+char(6,33133).
+char(c,33134).
+char(c,33135).
+char(p,33136).
+char(6,33137).
+char(1,33138).
+char(9,33139).
+char(7,33140).
+char(c,33141).
+char(m,33142).
+char(o,33143).
+char(m,33144).
+char(4,33145).
+char(6,33146).
+char(1,33147).
+char(1,33148).
+char(m,33149).
+char(3,33150).
+char(3,33151).
+char(3,33152).
+char(1,33153).
+char(p,33154).
+char(o,33155).
+char(7,33156).
+char(5,33157).
+char(5,33158).
+char(5,33159).
+char(m,33160).
+char(7,33161).
+char(8,33162).
+char(0,33163).
+char(2,33164).
+char(m,33165).
+char(o,33166).
+char(4,33167).
+char(3,33168).
+char(6,33169).
+char(4,33170).
+char(p,33171).
+char(5,33172).
+char(1,33173).
+char(7,33174).
+char(2,33175).
+char(c,33176).
+char(m,33177).
+char(7,33178).
+char(1,33179).
+char(2,33180).
+char(c,33181).
+char(m,33182).
+char(2,33183).
+char(5,33184).
+char(c,33185).
+char(m,33186).
+char(4,33187).
+char(2,33188).
+char(1,33189).
+char(1,33190).
+char(m,33191).
+char(8,33192).
+char(4,33193).
+char(0,33194).
+char(p,33195).
+char(o,33196).
+char(m,33197).
+char(o,33198).
+char(o,33199).
+char(p,33200).
+char(6,33201).
+char(5,33202).
+char(3,33203).
+char(9,33204).
+char(p,33205).
+char(o,33206).
+char(p,33207).
+char(o,33208).
+char(2,33209).
+char(1,33210).
+char(6,33211).
+char(4,33212).
+char(c,33213).
+char(c,33214).
+char(m,33215).
+char(o,33216).
+char(o,33217).
+char(o,33218).
+char(p,33219).
+char(o,33220).
+char(m,33221).
+char(9,33222).
+char(9,33223).
+char(1,33224).
+char(9,33225).
+char(m,33226).
+char(5,33227).
+char(0,33228).
+char(3,33229).
+char(4,33230).
+char(m,33231).
+char(8,33232).
+char(2,33233).
+char(8,33234).
+char(6,33235).
+char(m,33236).
+char(o,33237).
+char(p,33238).
+char(o,33239).
+char(m,33240).
+char(1,33241).
+char(8,33242).
+char(8,33243).
+char(2,33244).
+char(p,33245).
+char(o,33246).
+char(m,33247).
+char(4,33248).
+char(5,33249).
+char(4,33250).
+char(3,33251).
+char(c,33252).
+char(c,33253).
+char(m,33254).
+char(3,33255).
+char(4,33256).
+char(5,33257).
+char(p,33258).
+char(o,33259).
+char(8,33260).
+char(2,33261).
+char(0,33262).
+char(3,33263).
+char(c,33264).
+char(c,33265).
+char(c,33266).
+char(c,33267).
+char(p,33268).
+char(o,33269).
+char(m,33270).
+char(o,33271).
+char(4,33272).
+char(8,33273).
+char(3,33274).
+char(5,33275).
+char(c,33276).
+char(c,33277).
+char(c,33278).
+char(p,33279).
+char(o,33280).
+char(m,33281).
+char(8,33282).
+char(1,33283).
+char(5,33284).
+char(3,33285).
+char(c,33286).
+char(p,33287).
+char(o,33288).
+char(o,33289).
+char(p,33290).
+char(o,33291).
+char(o,33292).
+char(p,33293).
+char(5,33294).
+char(4,33295).
+char(3,33296).
+char(4,33297).
+char(m,33298).
+char(5,33299).
+char(9,33300).
+char(1,33301).
+char(0,33302).
+char(p,33303).
+char(o,33304).
+char(p,33305).
+char(9,33306).
+char(4,33307).
+char(8,33308).
+char(7,33309).
+char(c,33310).
+char(p,33311).
+char(2,33312).
+char(4,33313).
+char(3,33314).
+char(6,33315).
+char(p,33316).
+char(8,33317).
+char(9,33318).
+char(3,33319).
+char(m,33320).
+char(7,33321).
+char(9,33322).
+char(6,33323).
+char(7,33324).
+char(p,33325).
+char(o,33326).
+char(o,33327).
+char(p,33328).
+char(o,33329).
+char(o,33330).
+char(5,33331).
+char(0,33332).
+char(4,33333).
+char(6,33334).
+char(p,33335).
+char(o,33336).
+char(o,33337).
+char(p,33338).
+char(9,33339).
+char(8,33340).
+char(6,33341).
+char(9,33342).
+char(p,33343).
+char(8,33344).
+char(0,33345).
+char(8,33346).
+char(0,33347).
+char(m,33348).
+char(8,33349).
+char(5,33350).
+char(9,33351).
+char(9,33352).
+char(c,33353).
+char(c,33354).
+char(c,33355).
+char(c,33356).
+char(c,33357).
+char(c,33358).
+char(p,33359).
+char(o,33360).
+char(p,33361).
+char(1,33362).
+char(6,33363).
+char(5,33364).
+char(9,33365).
+char(c,33366).
+char(c,33367).
+char(c,33368).
+char(c,33369).
+char(m,33370).
+char(o,33371).
+char(m,33372).
+char(5,33373).
+char(7,33374).
+char(9,33375).
+char(6,33376).
+char(p,33377).
+char(4,33378).
+char(6,33379).
+char(5,33380).
+char(2,33381).
+char(p,33382).
+char(o,33383).
+char(m,33384).
+char(5,33385).
+char(2,33386).
+char(0,33387).
+char(5,33388).
+char(c,33389).
+char(p,33390).
+char(o,33391).
+char(p,33392).
+char(o,33393).
+char(o,33394).
+char(p,33395).
+char(9,33396).
+char(4,33397).
+char(4,33398).
+char(6,33399).
+char(m,33400).
+char(o,33401).
+char(o,33402).
+char(m,33403).
+char(2,33404).
+char(5,33405).
+char(4,33406).
+char(6,33407).
+char(c,33408).
+char(c,33409).
+char(c,33410).
+char(p,33411).
+char(3,33412).
+char(7,33413).
+char(6,33414).
+char(4,33415).
+char(m,33416).
+char(7,33417).
+char(4,33418).
+char(1,33419).
+char(3,33420).
+char(c,33421).
+char(c,33422).
+char(c,33423).
+char(c,33424).
+char(p,33425).
+char(o,33426).
+char(2,33427).
+char(1,33428).
+char(3,33429).
+char(6,33430).
+char(p,33431).
+char(o,33432).
+char(o,33433).
+char(p,33434).
+char(o,33435).
+char(p,33436).
+char(4,33437).
+char(0,33438).
+char(1,33439).
+char(5,33440).
+char(c,33441).
+char(p,33442).
+char(3,33443).
+char(1,33444).
+char(2,33445).
+char(2,33446).
+char(p,33447).
+char(2,33448).
+char(2,33449).
+char(4,33450).
+char(0,33451).
+char(m,33452).
+char(o,33453).
+char(m,33454).
+char(o,33455).
+char(o,33456).
+char(m,33457).
+char(5,33458).
+char(0,33459).
+char(7,33460).
+char(7,33461).
+char(p,33462).
+char(o,33463).
+char(o,33464).
+char(m,33465).
+char(o,33466).
+char(m,33467).
+char(1,33468).
+char(5,33469).
+char(9,33470).
+char(8,33471).
+char(c,33472).
+char(m,33473).
+char(o,33474).
+char(m,33475).
+char(2,33476).
+char(7,33477).
+char(4,33478).
+char(p,33479).
+char(7,33480).
+char(0,33481).
+char(5,33482).
+char(1,33483).
+char(c,33484).
+char(c,33485).
+char(p,33486).
+char(6,33487).
+char(1,33488).
+char(5,33489).
+char(1,33490).
+char(m,33491).
+char(o,33492).
+char(o,33493).
+char(m,33494).
+char(1,33495).
+char(5,33496).
+char(5,33497).
+char(7,33498).
+char(m,33499).
+char(o,33500).
+char(m,33501).
+char(o,33502).
+char(m,33503).
+char(o,33504).
+char(p,33505).
+char(o,33506).
+char(4,33507).
+char(6,33508).
+char(6,33509).
+char(2,33510).
+char(p,33511).
+char(3,33512).
+char(9,33513).
+char(7,33514).
+char(8,33515).
+char(c,33516).
+char(p,33517).
+char(o,33518).
+char(2,33519).
+char(9,33520).
+char(1,33521).
+char(6,33522).
+char(c,33523).
+char(c,33524).
+char(m,33525).
+char(o,33526).
+char(p,33527).
+char(2,33528).
+char(9,33529).
+char(3,33530).
+char(3,33531).
+char(c,33532).
+char(c,33533).
+char(c,33534).
+char(c,33535).
+char(m,33536).
+char(o,33537).
+char(7,33538).
+char(1,33539).
+char(1,33540).
+char(9,33541).
+char(c,33542).
+char(p,33543).
+char(9,33544).
+char(5,33545).
+char(8,33546).
+char(4,33547).
+char(c,33548).
+char(m,33549).
+char(o,33550).
+char(m,33551).
+char(o,33552).
+char(m,33553).
+char(3,33554).
+char(3,33555).
+char(7,33556).
+char(c,33557).
+char(c,33558).
+char(c,33559).
+char(p,33560).
+char(2,33561).
+char(4,33562).
+char(8,33563).
+char(7,33564).
+char(c,33565).
+char(c,33566).
+char(p,33567).
+char(8,33568).
+char(7,33569).
+char(6,33570).
+char(1,33571).
+char(c,33572).
+char(c,33573).
+char(c,33574).
+char(p,33575).
+char(o,33576).
+char(o,33577).
+char(7,33578).
+char(5,33579).
+char(2,33580).
+char(0,33581).
+char(p,33582).
+char(o,33583).
+char(m,33584).
+char(1,33585).
+char(0,33586).
+char(8,33587).
+char(1,33588).
+char(c,33589).
+char(p,33590).
+char(o,33591).
+char(m,33592).
+char(o,33593).
+char(m,33594).
+char(7,33595).
+char(5,33596).
+char(3,33597).
+char(c,33598).
+char(p,33599).
+char(5,33600).
+char(2,33601).
+char(1,33602).
+char(1,33603).
+char(c,33604).
+char(c,33605).
+char(p,33606).
+char(o,33607).
+char(9,33608).
+char(8,33609).
+char(5,33610).
+char(3,33611).
+char(p,33612).
+char(o,33613).
+char(p,33614).
+char(3,33615).
+char(6,33616).
+char(7,33617).
+char(9,33618).
+char(c,33619).
+char(p,33620).
+char(o,33621).
+char(1,33622).
+char(6,33623).
+char(7,33624).
+char(c,33625).
+char(m,33626).
+char(3,33627).
+char(5,33628).
+char(6,33629).
+char(4,33630).
+char(c,33631).
+char(m,33632).
+char(o,33633).
+char(m,33634).
+char(1,33635).
+char(2,33636).
+char(8,33637).
+char(9,33638).
+char(m,33639).
+char(o,33640).
+char(o,33641).
+char(m,33642).
+char(7,33643).
+char(2,33644).
+char(1,33645).
+char(7,33646).
+char(m,33647).
+char(3,33648).
+char(1,33649).
+char(7,33650).
+char(6,33651).
+char(p,33652).
+char(9,33653).
+char(2,33654).
+char(5,33655).
+char(7,33656).
+char(m,33657).
+char(9,33658).
+char(7,33659).
+char(6,33660).
+char(7,33661).
+char(c,33662).
+char(m,33663).
+char(o,33664).
+char(m,33665).
+char(8,33666).
+char(1,33667).
+char(4,33668).
+char(5,33669).
+char(c,33670).
+char(p,33671).
+char(8,33672).
+char(3,33673).
+char(6,33674).
+char(3,33675).
+char(c,33676).
+char(c,33677).
+char(m,33678).
+char(o,33679).
+char(o,33680).
+char(m,33681).
+char(o,33682).
+char(p,33683).
+char(o,33684).
+char(m,33685).
+char(o,33686).
+char(o,33687).
+char(m,33688).
+char(o,33689).
+char(m,33690).
+char(7,33691).
+char(8,33692).
+char(5,33693).
+char(0,33694).
+char(c,33695).
+char(c,33696).
+char(p,33697).
+char(3,33698).
+char(6,33699).
+char(7,33700).
+char(0,33701).
+char(p,33702).
+char(o,33703).
+char(p,33704).
+char(6,33705).
+char(0,33706).
+char(9,33707).
+char(8,33708).
+char(m,33709).
+char(7,33710).
+char(2,33711).
+char(5,33712).
+char(2,33713).
+char(m,33714).
+char(o,33715).
+char(m,33716).
+char(o,33717).
+char(p,33718).
+char(o,33719).
+char(3,33720).
+char(0,33721).
+char(4,33722).
+char(4,33723).
+char(m,33724).
+char(o,33725).
+char(m,33726).
+char(o,33727).
+char(1,33728).
+char(9,33729).
+char(2,33730).
+char(4,33731).
+char(p,33732).
+char(o,33733).
+char(8,33734).
+char(3,33735).
+char(4,33736).
+char(2,33737).
+char(p,33738).
+char(o,33739).
+char(p,33740).
+char(5,33741).
+char(7,33742).
+char(0,33743).
+char(7,33744).
+char(p,33745).
+char(o,33746).
+char(p,33747).
+char(4,33748).
+char(6,33749).
+char(6,33750).
+char(6,33751).
+char(c,33752).
+char(m,33753).
+char(o,33754).
+char(p,33755).
+char(4,33756).
+char(7,33757).
+char(7,33758).
+char(9,33759).
+char(c,33760).
+char(m,33761).
+char(o,33762).
+char(m,33763).
+char(o,33764).
+char(m,33765).
+char(o,33766).
+char(m,33767).
+char(2,33768).
+char(6,33769).
+char(c,33770).
+char(m,33771).
+char(9,33772).
+char(4,33773).
+char(5,33774).
+char(2,33775).
+char(c,33776).
+char(p,33777).
+char(o,33778).
+char(m,33779).
+char(2,33780).
+char(0,33781).
+char(7,33782).
+char(5,33783).
+char(p,33784).
+char(9,33785).
+char(9,33786).
+char(1,33787).
+char(9,33788).
+char(m,33789).
+char(4,33790).
+char(9,33791).
+char(8,33792).
+char(9,33793).
+char(p,33794).
+char(9,33795).
+char(5,33796).
+char(9,33797).
+char(7,33798).
+char(c,33799).
+char(p,33800).
+char(9,33801).
+char(4,33802).
+char(4,33803).
+char(8,33804).
+char(c,33805).
+char(c,33806).
+char(c,33807).
+char(p,33808).
+char(3,33809).
+char(0,33810).
+char(1,33811).
+char(2,33812).
+char(c,33813).
+char(p,33814).
+char(2,33815).
+char(8,33816).
+char(0,33817).
+char(1,33818).
+char(m,33819).
+char(4,33820).
+char(2,33821).
+char(6,33822).
+char(5,33823).
+char(m,33824).
+char(7,33825).
+char(5,33826).
+char(2,33827).
+char(0,33828).
+char(c,33829).
+char(c,33830).
+char(c,33831).
+char(c,33832).
+char(m,33833).
+char(o,33834).
+char(o,33835).
+char(m,33836).
+char(o,33837).
+char(m,33838).
+char(o,33839).
+char(p,33840).
+char(6,33841).
+char(7,33842).
+char(3,33843).
+char(6,33844).
+char(c,33845).
+char(c,33846).
+char(m,33847).
+char(4,33848).
+char(8,33849).
+char(8,33850).
+char(3,33851).
+char(c,33852).
+char(c,33853).
+char(c,33854).
+char(m,33855).
+char(o,33856).
+char(m,33857).
+char(6,33858).
+char(0,33859).
+char(7,33860).
+char(7,33861).
+char(p,33862).
+char(3,33863).
+char(3,33864).
+char(6,33865).
+char(3,33866).
+char(p,33867).
+char(o,33868).
+char(m,33869).
+char(o,33870).
+char(o,33871).
+char(m,33872).
+char(o,33873).
+char(m,33874).
+char(6,33875).
+char(6,33876).
+char(0,33877).
+char(5,33878).
+char(m,33879).
+char(8,33880).
+char(9,33881).
+char(7,33882).
+char(5,33883).
+char(p,33884).
+char(9,33885).
+char(2,33886).
+char(7,33887).
+char(7,33888).
+char(m,33889).
+char(6,33890).
+char(0,33891).
+char(7,33892).
+char(7,33893).
+char(c,33894).
+char(m,33895).
+char(6,33896).
+char(9,33897).
+char(0,33898).
+char(1,33899).
+char(m,33900).
+char(6,33901).
+char(4,33902).
+char(5,33903).
+char(5,33904).
+char(c,33905).
+char(c,33906).
+char(c,33907).
+char(m,33908).
+char(o,33909).
+char(7,33910).
+char(7,33911).
+char(1,33912).
+char(2,33913).
+char(c,33914).
+char(c,33915).
+char(c,33916).
+char(p,33917).
+char(6,33918).
+char(6,33919).
+char(0,33920).
+char(4,33921).
+char(m,33922).
+char(o,33923).
+char(m,33924).
+char(9,33925).
+char(7,33926).
+char(1,33927).
+char(0,33928).
+char(p,33929).
+char(o,33930).
+char(m,33931).
+char(o,33932).
+char(m,33933).
+char(5,33934).
+char(8,33935).
+char(4,33936).
+char(5,33937).
+char(c,33938).
+char(c,33939).
+char(p,33940).
+char(o,33941).
+char(o,33942).
+char(p,33943).
+char(7,33944).
+char(9,33945).
+char(4,33946).
+char(0,33947).
+char(c,33948).
+char(p,33949).
+char(o,33950).
+char(p,33951).
+char(o,33952).
+char(m,33953).
+char(4,33954).
+char(6,33955).
+char(7,33956).
+char(7,33957).
+char(m,33958).
+char(o,33959).
+char(m,33960).
+char(o,33961).
+char(p,33962).
+char(o,33963).
+char(m,33964).
+char(o,33965).
+char(m,33966).
+char(o,33967).
+char(o,33968).
+char(m,33969).
+char(o,33970).
+char(p,33971).
+char(o,33972).
+char(m,33973).
+char(2,33974).
+char(2,33975).
+char(4,33976).
+char(9,33977).
+char(c,33978).
+char(p,33979).
+char(8,33980).
+char(7,33981).
+char(0,33982).
+char(9,33983).
+char(c,33984).
+char(m,33985).
+char(o,33986).
+char(m,33987).
+char(o,33988).
+char(p,33989).
+char(o,33990).
+char(9,33991).
+char(5,33992).
+char(0,33993).
+char(4,33994).
+char(m,33995).
+char(o,33996).
+char(o,33997).
+char(m,33998).
+char(8,33999).
+char(9,34000).
+char(1,34001).
+char(7,34002).
+char(c,34003).
+char(c,34004).
+char(p,34005).
+char(1,34006).
+char(1,34007).
+char(5,34008).
+char(8,34009).
+char(c,34010).
+char(c,34011).
+char(c,34012).
+char(m,34013).
+char(1,34014).
+char(9,34015).
+char(2,34016).
+char(2,34017).
+char(m,34018).
+char(o,34019).
+char(m,34020).
+char(8,34021).
+char(1,34022).
+char(4,34023).
+char(6,34024).
+char(p,34025).
+char(o,34026).
+char(m,34027).
+char(7,34028).
+char(8,34029).
+char(3,34030).
+char(0,34031).
+char(c,34032).
+char(c,34033).
+char(p,34034).
+char(2,34035).
+char(5,34036).
+char(m,34037).
+char(o,34038).
+char(p,34039).
+char(o,34040).
+char(m,34041).
+char(o,34042).
+char(o,34043).
+char(p,34044).
+char(o,34045).
+char(p,34046).
+char(4,34047).
+char(4,34048).
+char(4,34049).
+char(0,34050).
+char(m,34051).
+char(o,34052).
+char(o,34053).
+char(o,34054).
+char(m,34055).
+char(o,34056).
+char(p,34057).
+char(o,34058).
+char(m,34059).
+char(o,34060).
+char(m,34061).
+char(o,34062).
+char(m,34063).
+char(o,34064).
+char(p,34065).
+char(3,34066).
+char(2,34067).
+char(1,34068).
+char(c,34069).
+char(c,34070).
+char(c,34071).
+char(c,34072).
+char(c,34073).
+char(p,34074).
+char(o,34075).
+char(o,34076).
+char(p,34077).
+char(7,34078).
+char(3,34079).
+char(0,34080).
+char(7,34081).
+char(c,34082).
+char(m,34083).
+char(3,34084).
+char(1,34085).
+char(6,34086).
+char(8,34087).
+char(c,34088).
+char(c,34089).
+char(m,34090).
+char(o,34091).
+char(m,34092).
+char(3,34093).
+char(9,34094).
+char(3,34095).
+char(0,34096).
+char(c,34097).
+char(c,34098).
+char(p,34099).
+char(o,34100).
+char(3,34101).
+char(1,34102).
+char(0,34103).
+char(1,34104).
+char(m,34105).
+char(o,34106).
+char(p,34107).
+char(7,34108).
+char(5,34109).
+char(7,34110).
+char(0,34111).
+char(c,34112).
+char(m,34113).
+char(9,34114).
+char(7,34115).
+char(7,34116).
+char(3,34117).
+char(c,34118).
+char(c,34119).
+char(c,34120).
+char(p,34121).
+char(5,34122).
+char(0,34123).
+char(8,34124).
+char(0,34125).
+char(c,34126).
+char(m,34127).
+char(o,34128).
+char(p,34129).
+char(6,34130).
+char(7,34131).
+char(7,34132).
+char(0,34133).
+char(c,34134).
+char(c,34135).
+char(m,34136).
+char(o,34137).
+char(p,34138).
+char(3,34139).
+char(3,34140).
+char(8,34141).
+char(c,34142).
+char(p,34143).
+char(o,34144).
+char(p,34145).
+char(3,34146).
+char(0,34147).
+char(2,34148).
+char(1,34149).
+char(c,34150).
+char(p,34151).
+char(o,34152).
+char(o,34153).
+char(p,34154).
+char(o,34155).
+char(o,34156).
+char(m,34157).
+char(o,34158).
+char(6,34159).
+char(7,34160).
+char(3,34161).
+char(9,34162).
+char(c,34163).
+char(p,34164).
+char(2,34165).
+char(2,34166).
+char(0,34167).
+char(3,34168).
+char(m,34169).
+char(5,34170).
+char(3,34171).
+char(4,34172).
+char(6,34173).
+char(p,34174).
+char(o,34175).
+char(p,34176).
+char(o,34177).
+char(o,34178).
+char(9,34179).
+char(0,34180).
+char(1,34181).
+char(7,34182).
+char(m,34183).
+char(3,34184).
+char(0,34185).
+char(3,34186).
+char(4,34187).
+char(p,34188).
+char(1,34189).
+char(1,34190).
+char(3,34191).
+char(9,34192).
+char(m,34193).
+char(1,34194).
+char(5,34195).
+char(4,34196).
+char(8,34197).
+char(c,34198).
+char(c,34199).
+char(c,34200).
+char(p,34201).
+char(o,34202).
+char(8,34203).
+char(6,34204).
+char(5,34205).
+char(8,34206).
+char(c,34207).
+char(c,34208).
+char(p,34209).
+char(6,34210).
+char(2,34211).
+char(0,34212).
+char(6,34213).
+char(m,34214).
+char(6,34215).
+char(1,34216).
+char(9,34217).
+char(5,34218).
+char(c,34219).
+char(c,34220).
+char(p,34221).
+char(2,34222).
+char(6,34223).
+char(7,34224).
+char(7,34225).
+char(p,34226).
+char(7,34227).
+char(2,34228).
+char(7,34229).
+char(3,34230).
+char(p,34231).
+char(o,34232).
+char(m,34233).
+char(7,34234).
+char(4,34235).
+char(1,34236).
+char(2,34237).
+char(m,34238).
+char(4,34239).
+char(5,34240).
+char(9,34241).
+char(7,34242).
+char(m,34243).
+char(o,34244).
+char(m,34245).
+char(2,34246).
+char(5,34247).
+char(8,34248).
+char(2,34249).
+char(m,34250).
+char(o,34251).
+char(m,34252).
+char(o,34253).
+char(p,34254).
+char(o,34255).
+char(m,34256).
+char(6,34257).
+char(3,34258).
+char(5,34259).
+char(2,34260).
+char(c,34261).
+char(c,34262).
+char(m,34263).
+char(o,34264).
+char(m,34265).
+char(o,34266).
+char(m,34267).
+char(o,34268).
+char(o,34269).
+char(p,34270).
+char(1,34271).
+char(0,34272).
+char(7,34273).
+char(2,34274).
+char(p,34275).
+char(o,34276).
+char(p,34277).
+char(6,34278).
+char(6,34279).
+char(4,34280).
+char(6,34281).
+char(m,34282).
+char(o,34283).
+char(m,34284).
+char(o,34285).
+char(o,34286).
+char(o,34287).
+char(9,34288).
+char(0,34289).
+char(3,34290).
+char(c,34291).
+char(c,34292).
+char(c,34293).
+char(m,34294).
+char(o,34295).
+char(p,34296).
+char(3,34297).
+char(9,34298).
+char(2,34299).
+char(2,34300).
+char(m,34301).
+char(7,34302).
+char(0,34303).
+char(1,34304).
+char(2,34305).
+char(p,34306).
+char(o,34307).
+char(6,34308).
+char(4,34309).
+char(0,34310).
+char(8,34311).
+char(c,34312).
+char(p,34313).
+char(3,34314).
+char(2,34315).
+char(7,34316).
+char(7,34317).
+char(c,34318).
+char(c,34319).
+char(p,34320).
+char(o,34321).
+char(p,34322).
+char(o,34323).
+char(o,34324).
+char(m,34325).
+char(9,34326).
+char(5,34327).
+char(5,34328).
+char(c,34329).
+char(m,34330).
+char(o,34331).
+char(m,34332).
+char(8,34333).
+char(8,34334).
+char(7,34335).
+char(9,34336).
+char(c,34337).
+char(c,34338).
+char(m,34339).
+char(7,34340).
+char(8,34341).
+char(6,34342).
+char(1,34343).
+char(c,34344).
+char(c,34345).
+char(p,34346).
+char(9,34347).
+char(0,34348).
+char(6,34349).
+char(1,34350).
+char(p,34351).
+char(o,34352).
+char(m,34353).
+char(4,34354).
+char(3,34355).
+char(2,34356).
+char(1,34357).
+char(c,34358).
+char(m,34359).
+char(8,34360).
+char(3,34361).
+char(4,34362).
+char(m,34363).
+char(o,34364).
+char(o,34365).
+char(p,34366).
+char(o,34367).
+char(m,34368).
+char(o,34369).
+char(p,34370).
+char(o,34371).
+char(p,34372).
+char(2,34373).
+char(6,34374).
+char(6,34375).
+char(8,34376).
+char(p,34377).
+char(o,34378).
+char(m,34379).
+char(o,34380).
+char(o,34381).
+char(m,34382).
+char(6,34383).
+char(5,34384).
+char(8,34385).
+char(8,34386).
+char(c,34387).
+char(p,34388).
+char(o,34389).
+char(4,34390).
+char(0,34391).
+char(4,34392).
+char(2,34393).
+char(c,34394).
+char(p,34395).
+char(6,34396).
+char(5,34397).
+char(1,34398).
+char(7,34399).
+char(m,34400).
+char(o,34401).
+char(m,34402).
+char(o,34403).
+char(m,34404).
+char(o,34405).
+char(o,34406).
+char(m,34407).
+char(o,34408).
+char(p,34409).
+char(o,34410).
+char(m,34411).
+char(o,34412).
+char(p,34413).
+char(o,34414).
+char(o,34415).
+char(2,34416).
+char(5,34417).
+char(6,34418).
+char(8,34419).
+char(c,34420).
+char(m,34421).
+char(o,34422).
+char(p,34423).
+char(7,34424).
+char(2,34425).
+char(5,34426).
+char(3,34427).
+char(c,34428).
+char(c,34429).
+char(m,34430).
+char(1,34431).
+char(1,34432).
+char(4,34433).
+char(2,34434).
+char(p,34435).
+char(9,34436).
+char(7,34437).
+char(4,34438).
+char(6,34439).
+char(c,34440).
+char(c,34441).
+char(c,34442).
+char(p,34443).
+char(9,34444).
+char(0,34445).
+char(0,34446).
+char(5,34447).
+char(c,34448).
+char(m,34449).
+char(2,34450).
+char(9,34451).
+char(6,34452).
+char(3,34453).
+char(p,34454).
+char(o,34455).
+char(o,34456).
+char(p,34457).
+char(o,34458).
+char(p,34459).
+char(9,34460).
+char(0,34461).
+char(6,34462).
+char(9,34463).
+char(m,34464).
+char(1,34465).
+char(6,34466).
+char(0,34467).
+char(4,34468).
+char(c,34469).
+char(c,34470).
+char(p,34471).
+char(2,34472).
+char(8,34473).
+char(1,34474).
+char(0,34475).
+char(c,34476).
+char(p,34477).
+char(6,34478).
+char(4,34479).
+char(9,34480).
+char(p,34481).
+char(7,34482).
+char(5,34483).
+char(8,34484).
+char(c,34485).
+char(c,34486).
+char(c,34487).
+char(c,34488).
+char(c,34489).
+char(m,34490).
+char(o,34491).
+char(m,34492).
+char(4,34493).
+char(5,34494).
+char(2,34495).
+char(0,34496).
+char(p,34497).
+char(o,34498).
+char(p,34499).
+char(8,34500).
+char(3,34501).
+char(4,34502).
+char(7,34503).
+char(c,34504).
+char(m,34505).
+char(2,34506).
+char(0,34507).
+char(6,34508).
+char(7,34509).
+char(c,34510).
+char(p,34511).
+char(4,34512).
+char(7,34513).
+char(7,34514).
+char(1,34515).
+char(m,34516).
+char(3,34517).
+char(3,34518).
+char(9,34519).
+char(5,34520).
+char(p,34521).
+char(o,34522).
+char(p,34523).
+char(7,34524).
+char(8,34525).
+char(9,34526).
+char(7,34527).
+char(c,34528).
+char(c,34529).
+char(p,34530).
+char(1,34531).
+char(9,34532).
+char(3,34533).
+char(3,34534).
+char(c,34535).
+char(c,34536).
+char(c,34537).
+char(c,34538).
+char(m,34539).
+char(o,34540).
+char(p,34541).
+char(o,34542).
+char(p,34543).
+char(9,34544).
+char(5,34545).
+char(0,34546).
+char(3,34547).
+char(p,34548).
+char(o,34549).
+char(m,34550).
+char(o,34551).
+char(6,34552).
+char(3,34553).
+char(7,34554).
+char(0,34555).
+char(c,34556).
+char(c,34557).
+char(c,34558).
+char(m,34559).
+char(o,34560).
+char(m,34561).
+char(o,34562).
+char(m,34563).
+char(o,34564).
+char(m,34565).
+char(o,34566).
+char(m,34567).
+char(1,34568).
+char(1,34569).
+char(3,34570).
+char(1,34571).
+char(c,34572).
+char(m,34573).
+char(7,34574).
+char(9,34575).
+char(9,34576).
+char(9,34577).
+char(c,34578).
+char(c,34579).
+char(m,34580).
+char(5,34581).
+char(6,34582).
+char(9,34583).
+char(9,34584).
+char(c,34585).
+char(c,34586).
+char(c,34587).
+char(c,34588).
+char(c,34589).
+char(c,34590).
+char(c,34591).
+char(c,34592).
+char(c,34593).
+char(p,34594).
+char(o,34595).
+char(p,34596).
+char(o,34597).
+char(o,34598).
+char(p,34599).
+char(3,34600).
+char(2,34601).
+char(9,34602).
+char(1,34603).
+char(c,34604).
+char(m,34605).
+char(o,34606).
+char(m,34607).
+char(o,34608).
+char(m,34609).
+char(o,34610).
+char(o,34611).
+char(9,34612).
+char(1,34613).
+char(2,34614).
+char(0,34615).
+char(c,34616).
+char(m,34617).
+char(o,34618).
+char(m,34619).
+char(4,34620).
+char(5,34621).
+char(6,34622).
+char(6,34623).
+char(c,34624).
+char(c,34625).
+char(p,34626).
+char(4,34627).
+char(6,34628).
+char(6,34629).
+char(6,34630).
+char(m,34631).
+char(o,34632).
+char(o,34633).
+char(m,34634).
+char(8,34635).
+char(0,34636).
+char(9,34637).
+char(5,34638).
+char(p,34639).
+char(o,34640).
+char(5,34641).
+char(5,34642).
+char(0,34643).
+char(5,34644).
+char(p,34645).
+char(4,34646).
+char(4,34647).
+char(2,34648).
+char(1,34649).
+char(m,34650).
+char(o,34651).
+char(p,34652).
+char(o,34653).
+char(p,34654).
+char(o,34655).
+char(m,34656).
+char(1,34657).
+char(9,34658).
+char(4,34659).
+char(6,34660).
+char(c,34661).
+char(c,34662).
+char(p,34663).
+char(1,34664).
+char(1,34665).
+char(3,34666).
+char(9,34667).
+char(m,34668).
+char(2,34669).
+char(5,34670).
+char(7,34671).
+char(0,34672).
+char(m,34673).
+char(o,34674).
+char(p,34675).
+char(o,34676).
+char(o,34677).
+char(o,34678).
+char(m,34679).
+char(o,34680).
+char(7,34681).
+char(7,34682).
+char(9,34683).
+char(6,34684).
+char(c,34685).
+char(m,34686).
+char(9,34687).
+char(0,34688).
+char(3,34689).
+char(3,34690).
+char(c,34691).
+char(c,34692).
+char(c,34693).
+char(c,34694).
+char(p,34695).
+char(o,34696).
+char(p,34697).
+char(2,34698).
+char(0,34699).
+char(6,34700).
+char(1,34701).
+char(c,34702).
+char(m,34703).
+char(9,34704).
+char(6,34705).
+char(5,34706).
+char(9,34707).
+char(c,34708).
+char(p,34709).
+char(o,34710).
+char(p,34711).
+char(o,34712).
+char(9,34713).
+char(4,34714).
+char(4,34715).
+char(2,34716).
+char(m,34717).
+char(6,34718).
+char(0,34719).
+char(6,34720).
+char(4,34721).
+char(m,34722).
+char(o,34723).
+char(9,34724).
+char(6,34725).
+char(4,34726).
+char(6,34727).
+char(c,34728).
+char(m,34729).
+char(9,34730).
+char(8,34731).
+char(1,34732).
+char(8,34733).
+char(m,34734).
+char(o,34735).
+char(p,34736).
+char(o,34737).
+char(m,34738).
+char(9,34739).
+char(5,34740).
+char(0,34741).
+char(6,34742).
+char(c,34743).
+char(c,34744).
+char(p,34745).
+char(9,34746).
+char(9,34747).
+char(4,34748).
+char(1,34749).
+char(p,34750).
+char(6,34751).
+char(5,34752).
+char(6,34753).
+char(3,34754).
+char(m,34755).
+char(9,34756).
+char(0,34757).
+char(3,34758).
+char(1,34759).
+char(p,34760).
+char(1,34761).
+char(2,34762).
+char(8,34763).
+char(2,34764).
+char(m,34765).
+char(o,34766).
+char(m,34767).
+char(6,34768).
+char(0,34769).
+char(7,34770).
+char(9,34771).
+char(c,34772).
+char(c,34773).
+char(p,34774).
+char(4,34775).
+char(3,34776).
+char(8,34777).
+char(7,34778).
+char(c,34779).
+char(p,34780).
+char(o,34781).
+char(p,34782).
+char(o,34783).
+char(p,34784).
+char(1,34785).
+char(2,34786).
+char(5,34787).
+char(6,34788).
+char(m,34789).
+char(8,34790).
+char(5,34791).
+char(3,34792).
+char(3,34793).
+char(c,34794).
+char(c,34795).
+char(c,34796).
+char(p,34797).
+char(o,34798).
+char(m,34799).
+char(o,34800).
+char(m,34801).
+char(o,34802).
+char(m,34803).
+char(5,34804).
+char(7,34805).
+char(0,34806).
+char(6,34807).
+char(p,34808).
+char(o,34809).
+char(m,34810).
+char(o,34811).
+char(7,34812).
+char(3,34813).
+char(3,34814).
+char(9,34815).
+char(c,34816).
+char(m,34817).
+char(4,34818).
+char(3,34819).
+char(6,34820).
+char(9,34821).
+char(p,34822).
+char(o,34823).
+char(m,34824).
+char(o,34825).
+char(m,34826).
+char(o,34827).
+char(m,34828).
+char(o,34829).
+char(4,34830).
+char(2,34831).
+char(7,34832).
+char(1,34833).
+char(p,34834).
+char(3,34835).
+char(6,34836).
+char(8,34837).
+char(2,34838).
+char(c,34839).
+char(p,34840).
+char(o,34841).
+char(p,34842).
+char(o,34843).
+char(1,34844).
+char(5,34845).
+char(8,34846).
+char(8,34847).
+char(m,34848).
+char(9,34849).
+char(6,34850).
+char(4,34851).
+char(1,34852).
+char(c,34853).
+char(p,34854).
+char(1,34855).
+char(5,34856).
+char(5,34857).
+char(5,34858).
+char(p,34859).
+char(o,34860).
+char(p,34861).
+char(9,34862).
+char(1,34863).
+char(8,34864).
+char(9,34865).
+char(m,34866).
+char(o,34867).
+char(p,34868).
+char(4,34869).
+char(9,34870).
+char(3,34871).
+char(1,34872).
+char(m,34873).
+char(o,34874).
+char(p,34875).
+char(4,34876).
+char(4,34877).
+char(5,34878).
+char(0,34879).
+char(c,34880).
+char(c,34881).
+char(c,34882).
+char(m,34883).
+char(o,34884).
+char(m,34885).
+char(o,34886).
+char(8,34887).
+char(9,34888).
+char(6,34889).
+char(3,34890).
+char(p,34891).
+char(9,34892).
+char(7,34893).
+char(0,34894).
+char(c,34895).
+char(m,34896).
+char(o,34897).
+char(p,34898).
+char(o,34899).
+char(m,34900).
+char(6,34901).
+char(4,34902).
+char(5,34903).
+char(6,34904).
+char(c,34905).
+char(c,34906).
+char(c,34907).
+char(m,34908).
+char(4,34909).
+char(0,34910).
+char(6,34911).
+char(7,34912).
+char(p,34913).
+char(1,34914).
+char(9,34915).
+char(4,34916).
+char(1,34917).
+char(p,34918).
+char(o,34919).
+char(p,34920).
+char(8,34921).
+char(7,34922).
+char(6,34923).
+char(6,34924).
+char(c,34925).
+char(c,34926).
+char(m,34927).
+char(9,34928).
+char(7,34929).
+char(7,34930).
+char(0,34931).
+char(c,34932).
+char(c,34933).
+char(p,34934).
+char(1,34935).
+char(6,34936).
+char(8,34937).
+char(7,34938).
+char(m,34939).
+char(5,34940).
+char(9,34941).
+char(1,34942).
+char(6,34943).
+char(m,34944).
+char(3,34945).
+char(4,34946).
+char(9,34947).
+char(1,34948).
+char(m,34949).
+char(7,34950).
+char(0,34951).
+char(3,34952).
+char(4,34953).
+char(p,34954).
+char(o,34955).
+char(m,34956).
+char(o,34957).
+char(p,34958).
+char(9,34959).
+char(8,34960).
+char(4,34961).
+char(8,34962).
+char(c,34963).
+char(c,34964).
+char(p,34965).
+char(o,34966).
+char(p,34967).
+char(4,34968).
+char(5,34969).
+char(8,34970).
+char(c,34971).
+char(c,34972).
+char(p,34973).
+char(1,34974).
+char(1,34975).
+char(8,34976).
+char(2,34977).
+char(c,34978).
+char(m,34979).
+char(3,34980).
+char(3,34981).
+char(1,34982).
+char(c,34983).
+char(p,34984).
+char(o,34985).
+char(p,34986).
+char(5,34987).
+char(6,34988).
+char(7,34989).
+char(m,34990).
+char(4,34991).
+char(2,34992).
+char(8,34993).
+char(6,34994).
+char(c,34995).
+char(c,34996).
+char(p,34997).
+char(3,34998).
+char(6,34999).
+char(7,35000).
+char(3,35001).
+char(c,35002).
+char(p,35003).
+char(o,35004).
+char(p,35005).
+char(o,35006).
+char(m,35007).
+char(o,35008).
+char(p,35009).
+char(o,35010).
+char(m,35011).
+char(9,35012).
+char(8,35013).
+char(5,35014).
+char(2,35015).
+char(p,35016).
+char(o,35017).
+char(m,35018).
+char(2,35019).
+char(6,35020).
+char(9,35021).
+char(8,35022).
+char(c,35023).
+char(m,35024).
+char(8,35025).
+char(4,35026).
+char(8,35027).
+char(3,35028).
+char(p,35029).
+char(o,35030).
+char(m,35031).
+char(2,35032).
+char(8,35033).
+char(5,35034).
+char(3,35035).
+char(p,35036).
+char(1,35037).
+char(1,35038).
+char(6,35039).
+char(3,35040).
+char(m,35041).
+char(5,35042).
+char(4,35043).
+char(0,35044).
+char(7,35045).
+char(c,35046).
+char(c,35047).
+char(p,35048).
+char(4,35049).
+char(4,35050).
+char(2,35051).
+char(4,35052).
+char(c,35053).
+char(m,35054).
+char(4,35055).
+char(6,35056).
+char(8,35057).
+char(5,35058).
+char(c,35059).
+char(p,35060).
+char(2,35061).
+char(7,35062).
+char(9,35063).
+char(1,35064).
+char(p,35065).
+char(o,35066).
+char(o,35067).
+char(p,35068).
+char(o,35069).
+char(p,35070).
+char(5,35071).
+char(3,35072).
+char(3,35073).
+char(5,35074).
+char(c,35075).
+char(p,35076).
+char(o,35077).
+char(m,35078).
+char(o,35079).
+char(o,35080).
+char(m,35081).
+char(o,35082).
+char(p,35083).
+char(3,35084).
+char(9,35085).
+char(8,35086).
+char(5,35087).
+char(p,35088).
+char(9,35089).
+char(2,35090).
+char(6,35091).
+char(9,35092).
+char(c,35093).
+char(c,35094).
+char(m,35095).
+char(1,35096).
+char(6,35097).
+char(7,35098).
+char(6,35099).
+char(p,35100).
+char(o,35101).
+char(p,35102).
+char(o,35103).
+char(o,35104).
+char(o,35105).
+char(m,35106).
+char(1,35107).
+char(7,35108).
+char(0,35109).
+char(4,35110).
+char(p,35111).
+char(6,35112).
+char(0,35113).
+char(9,35114).
+char(0,35115).
+char(c,35116).
+char(c,35117).
+char(c,35118).
+char(c,35119).
+char(c,35120).
+char(c,35121).
+char(c,35122).
+char(c,35123).
+char(p,35124).
+char(o,35125).
+char(p,35126).
+char(o,35127).
+char(6,35128).
+char(5,35129).
+char(6,35130).
+char(p,35131).
+char(5,35132).
+char(0,35133).
+char(9,35134).
+char(1,35135).
+char(m,35136).
+char(9,35137).
+char(2,35138).
+char(9,35139).
+char(8,35140).
+char(c,35141).
+char(m,35142).
+char(2,35143).
+char(0,35144).
+char(7,35145).
+char(4,35146).
+char(c,35147).
+char(m,35148).
+char(o,35149).
+char(o,35150).
+char(m,35151).
+char(o,35152).
+char(p,35153).
+char(2,35154).
+char(7,35155).
+char(6,35156).
+char(7,35157).
+char(c,35158).
+char(c,35159).
+char(c,35160).
+char(c,35161).
+char(c,35162).
+char(c,35163).
+char(m,35164).
+char(o,35165).
+char(o,35166).
+char(m,35167).
+char(8,35168).
+char(9,35169).
+char(3,35170).
+char(6,35171).
+char(c,35172).
+char(c,35173).
+char(c,35174).
+char(m,35175).
+char(1,35176).
+char(5,35177).
+char(0,35178).
+char(4,35179).
+char(m,35180).
+char(o,35181).
+char(m,35182).
+char(o,35183).
+char(o,35184).
+char(m,35185).
+char(3,35186).
+char(8,35187).
+char(0,35188).
+char(9,35189).
+char(c,35190).
+char(c,35191).
+char(c,35192).
+char(m,35193).
+char(6,35194).
+char(7,35195).
+char(0,35196).
+char(9,35197).
+char(c,35198).
+char(m,35199).
+char(o,35200).
+char(o,35201).
+char(m,35202).
+char(o,35203).
+char(m,35204).
+char(o,35205).
+char(p,35206).
+char(o,35207).
+char(p,35208).
+char(o,35209).
+char(p,35210).
+char(4,35211).
+char(0,35212).
+char(4,35213).
+char(c,35214).
+char(c,35215).
+char(c,35216).
+char(m,35217).
+char(4,35218).
+char(1,35219).
+char(4,35220).
+char(0,35221).
+char(c,35222).
+char(p,35223).
+char(3,35224).
+char(7,35225).
+char(2,35226).
+char(5,35227).
+char(c,35228).
+char(c,35229).
+char(p,35230).
+char(4,35231).
+char(9,35232).
+char(8,35233).
+char(9,35234).
+char(c,35235).
+char(m,35236).
+char(8,35237).
+char(5,35238).
+char(6,35239).
+char(7,35240).
+char(m,35241).
+char(4,35242).
+char(7,35243).
+char(4,35244).
+char(2,35245).
+char(c,35246).
+char(m,35247).
+char(o,35248).
+char(m,35249).
+char(o,35250).
+char(p,35251).
+char(4,35252).
+char(2,35253).
+char(0,35254).
+char(4,35255).
+char(c,35256).
+char(c,35257).
+char(p,35258).
+char(o,35259).
+char(o,35260).
+char(m,35261).
+char(o,35262).
+char(m,35263).
+char(o,35264).
+char(o,35265).
+char(m,35266).
+char(2,35267).
+char(0,35268).
+char(2,35269).
+char(6,35270).
+char(c,35271).
+char(m,35272).
+char(o,35273).
+char(o,35274).
+char(p,35275).
+char(o,35276).
+char(o,35277).
+char(p,35278).
+char(o,35279).
+char(m,35280).
+char(o,35281).
+char(p,35282).
+char(o,35283).
+char(3,35284).
+char(9,35285).
+char(5,35286).
+char(1,35287).
+char(m,35288).
+char(6,35289).
+char(6,35290).
+char(7,35291).
+char(9,35292).
+char(c,35293).
+char(m,35294).
+char(o,35295).
+char(p,35296).
+char(o,35297).
+char(7,35298).
+char(9,35299).
+char(6,35300).
+char(4,35301).
+char(c,35302).
+char(c,35303).
+char(c,35304).
+char(p,35305).
+char(o,35306).
+char(p,35307).
+char(1,35308).
+char(3,35309).
+char(0,35310).
+char(7,35311).
+char(m,35312).
+char(9,35313).
+char(7,35314).
+char(3,35315).
+char(2,35316).
+char(c,35317).
+char(c,35318).
+char(c,35319).
+char(c,35320).
+char(p,35321).
+char(7,35322).
+char(8,35323).
+char(5,35324).
+char(1,35325).
+char(m,35326).
+char(7,35327).
+char(0,35328).
+char(8,35329).
+char(4,35330).
+char(c,35331).
+char(c,35332).
+char(p,35333).
+char(o,35334).
+char(p,35335).
+char(7,35336).
+char(8,35337).
+char(0,35338).
+char(0,35339).
+char(c,35340).
+char(c,35341).
+char(m,35342).
+char(o,35343).
+char(1,35344).
+char(8,35345).
+char(5,35346).
+char(5,35347).
+char(p,35348).
+char(o,35349).
+char(m,35350).
+char(o,35351).
+char(9,35352).
+char(3,35353).
+char(6,35354).
+char(2,35355).
+char(c,35356).
+char(c,35357).
+char(c,35358).
+char(m,35359).
+char(9,35360).
+char(5,35361).
+char(9,35362).
+char(6,35363).
+char(c,35364).
+char(p,35365).
+char(6,35366).
+char(1,35367).
+char(7,35368).
+char(9,35369).
+char(p,35370).
+char(o,35371).
+char(9,35372).
+char(5,35373).
+char(2,35374).
+char(5,35375).
+char(c,35376).
+char(c,35377).
+char(p,35378).
+char(o,35379).
+char(o,35380).
+char(m,35381).
+char(2,35382).
+char(5,35383).
+char(7,35384).
+char(6,35385).
+char(c,35386).
+char(p,35387).
+char(7,35388).
+char(2,35389).
+char(3,35390).
+char(m,35391).
+char(o,35392).
+char(o,35393).
+char(p,35394).
+char(3,35395).
+char(8,35396).
+char(0,35397).
+char(8,35398).
+char(c,35399).
+char(c,35400).
+char(c,35401).
+char(c,35402).
+char(c,35403).
+char(p,35404).
+char(o,35405).
+char(m,35406).
+char(3,35407).
+char(4,35408).
+char(0,35409).
+char(0,35410).
+char(m,35411).
+char(5,35412).
+char(2,35413).
+char(9,35414).
+char(9,35415).
+char(p,35416).
+char(o,35417).
+char(o,35418).
+char(o,35419).
+char(m,35420).
+char(o,35421).
+char(p,35422).
+char(5,35423).
+char(1,35424).
+char(7,35425).
+char(8,35426).
+char(c,35427).
+char(m,35428).
+char(o,35429).
+char(m,35430).
+char(o,35431).
+char(p,35432).
+char(o,35433).
+char(m,35434).
+char(o,35435).
+char(m,35436).
+char(1,35437).
+char(1,35438).
+char(2,35439).
+char(4,35440).
+char(c,35441).
+char(c,35442).
+char(p,35443).
+char(6,35444).
+char(1,35445).
+char(3,35446).
+char(4,35447).
+char(m,35448).
+char(o,35449).
+char(p,35450).
+char(2,35451).
+char(4,35452).
+char(0,35453).
+char(5,35454).
+char(m,35455).
+char(o,35456).
+char(m,35457).
+char(6,35458).
+char(5,35459).
+char(6,35460).
+char(1,35461).
+char(c,35462).
+char(m,35463).
+char(5,35464).
+char(4,35465).
+char(0,35466).
+char(p,35467).
+char(o,35468).
+char(5,35469).
+char(2,35470).
+char(1,35471).
+char(8,35472).
+char(m,35473).
+char(o,35474).
+char(m,35475).
+char(o,35476).
+char(p,35477).
+char(8,35478).
+char(9,35479).
+char(0,35480).
+char(3,35481).
+char(m,35482).
+char(5,35483).
+char(4,35484).
+char(6,35485).
+char(m,35486).
+char(8,35487).
+char(0,35488).
+char(3,35489).
+char(3,35490).
+char(c,35491).
+char(c,35492).
+char(c,35493).
+char(m,35494).
+char(o,35495).
+char(m,35496).
+char(2,35497).
+char(6,35498).
+char(6,35499).
+char(9,35500).
+char(p,35501).
+char(o,35502).
+char(p,35503).
+char(o,35504).
+char(4,35505).
+char(2,35506).
+char(0,35507).
+char(3,35508).
+char(c,35509).
+char(c,35510).
+char(c,35511).
+char(c,35512).
+char(c,35513).
+char(c,35514).
+char(p,35515).
+char(7,35516).
+char(0,35517).
+char(8,35518).
+char(8,35519).
+char(m,35520).
+char(o,35521).
+char(p,35522).
+char(o,35523).
+char(p,35524).
+char(o,35525).
+char(p,35526).
+char(o,35527).
+char(9,35528).
+char(3,35529).
+char(2,35530).
+char(4,35531).
+char(m,35532).
+char(8,35533).
+char(4,35534).
+char(9,35535).
+char(2,35536).
+char(p,35537).
+char(o,35538).
+char(2,35539).
+char(2,35540).
+char(4,35541).
+char(8,35542).
+char(c,35543).
+char(c,35544).
+char(p,35545).
+char(4,35546).
+char(4,35547).
+char(3,35548).
+char(8,35549).
+char(c,35550).
+char(p,35551).
+char(o,35552).
+char(p,35553).
+char(o,35554).
+char(p,35555).
+char(5,35556).
+char(9,35557).
+char(6,35558).
+char(3,35559).
+char(c,35560).
+char(c,35561).
+char(m,35562).
+char(o,35563).
+char(o,35564).
+char(7,35565).
+char(3,35566).
+char(2,35567).
+char(3,35568).
+char(p,35569).
+char(o,35570).
+char(p,35571).
+char(o,35572).
+char(p,35573).
+char(o,35574).
+char(p,35575).
+char(3,35576).
+char(6,35577).
+char(1,35578).
+char(m,35579).
+char(7,35580).
+char(2,35581).
+char(5,35582).
+char(8,35583).
+char(c,35584).
+char(c,35585).
+char(c,35586).
+char(p,35587).
+char(o,35588).
+char(m,35589).
+char(5,35590).
+char(3,35591).
+char(0,35592).
+char(m,35593).
+char(3,35594).
+char(0,35595).
+char(1,35596).
+char(4,35597).
+char(p,35598).
+char(o,35599).
+char(m,35600).
+char(o,35601).
+char(m,35602).
+char(7,35603).
+char(4,35604).
+char(5,35605).
+char(4,35606).
+char(c,35607).
+char(m,35608).
+char(o,35609).
+char(p,35610).
+char(3,35611).
+char(0,35612).
+char(2,35613).
+char(0,35614).
+char(c,35615).
+char(m,35616).
+char(o,35617).
+char(o,35618).
+char(m,35619).
+char(o,35620).
+char(o,35621).
+char(o,35622).
+char(4,35623).
+char(6,35624).
+char(2,35625).
+char(2,35626).
+char(c,35627).
+char(m,35628).
+char(o,35629).
+char(m,35630).
+char(o,35631).
+char(m,35632).
+char(2,35633).
+char(5,35634).
+char(3,35635).
+char(6,35636).
+char(m,35637).
+char(o,35638).
+char(m,35639).
+char(7,35640).
+char(5,35641).
+char(6,35642).
+char(7,35643).
+char(m,35644).
+char(o,35645).
+char(p,35646).
+char(o,35647).
+char(p,35648).
+char(2,35649).
+char(1,35650).
+char(2,35651).
+char(4,35652).
+char(c,35653).
+char(m,35654).
+char(o,35655).
+char(7,35656).
+char(2,35657).
+char(1,35658).
+char(m,35659).
+char(o,35660).
+char(p,35661).
+char(7,35662).
+char(3,35663).
+char(2,35664).
+char(3,35665).
+char(c,35666).
+char(p,35667).
+char(o,35668).
+char(5,35669).
+char(1,35670).
+char(3,35671).
+char(5,35672).
+char(p,35673).
+char(6,35674).
+char(8,35675).
+char(0,35676).
+char(3,35677).
+char(p,35678).
+char(9,35679).
+char(0,35680).
+char(0,35681).
+char(0,35682).
+char(m,35683).
+char(8,35684).
+char(5,35685).
+char(6,35686).
+char(0,35687).
+char(m,35688).
+char(5,35689).
+char(7,35690).
+char(5,35691).
+char(5,35692).
+char(c,35693).
+char(c,35694).
+char(c,35695).
+char(m,35696).
+char(o,35697).
+char(m,35698).
+char(o,35699).
+char(o,35700).
+char(m,35701).
+char(5,35702).
+char(4,35703).
+char(4,35704).
+char(3,35705).
+char(m,35706).
+char(5,35707).
+char(1,35708).
+char(7,35709).
+char(1,35710).
+char(m,35711).
+char(o,35712).
+char(m,35713).
+char(4,35714).
+char(4,35715).
+char(1,35716).
+char(1,35717).
+char(c,35718).
+char(c,35719).
+char(c,35720).
+char(p,35721).
+char(o,35722).
+char(p,35723).
+char(o,35724).
+char(m,35725).
+char(o,35726).
+char(p,35727).
+char(o,35728).
+char(p,35729).
+char(2,35730).
+char(0,35731).
+char(5,35732).
+char(4,35733).
+char(p,35734).
+char(1,35735).
+char(6,35736).
+char(2,35737).
+char(9,35738).
+char(p,35739).
+char(5,35740).
+char(0,35741).
+char(9,35742).
+char(3,35743).
+char(c,35744).
+char(c,35745).
+char(p,35746).
+char(o,35747).
+char(m,35748).
+char(o,35749).
+char(2,35750).
+char(9,35751).
+char(8,35752).
+char(0,35753).
+char(p,35754).
+char(8,35755).
+char(2,35756).
+char(7,35757).
+char(7,35758).
+char(m,35759).
+char(o,35760).
+char(p,35761).
+char(o,35762).
+char(p,35763).
+char(o,35764).
+char(5,35765).
+char(8,35766).
+char(6,35767).
+char(1,35768).
+char(m,35769).
+char(7,35770).
+char(2,35771).
+char(4,35772).
+char(c,35773).
+char(m,35774).
+char(o,35775).
+char(9,35776).
+char(2,35777).
+char(3,35778).
+char(4,35779).
+char(p,35780).
+char(o,35781).
+char(o,35782).
+char(o,35783).
+char(p,35784).
+char(9,35785).
+char(9,35786).
+char(0,35787).
+char(0,35788).
+char(m,35789).
+char(2,35790).
+char(6,35791).
+char(5,35792).
+char(p,35793).
+char(o,35794).
+char(o,35795).
+char(p,35796).
+char(6,35797).
+char(6,35798).
+char(4,35799).
+char(5,35800).
+char(c,35801).
+char(m,35802).
+char(3,35803).
+char(5,35804).
+char(7,35805).
+char(8,35806).
+char(c,35807).
+char(c,35808).
+char(c,35809).
+char(c,35810).
+char(p,35811).
+char(2,35812).
+char(0,35813).
+char(9,35814).
+char(1,35815).
+char(m,35816).
+char(o,35817).
+char(8,35818).
+char(8,35819).
+char(1,35820).
+char(m,35821).
+char(o,35822).
+char(o,35823).
+char(p,35824).
+char(1,35825).
+char(4,35826).
+char(0,35827).
+char(8,35828).
+char(p,35829).
+char(o,35830).
+char(o,35831).
+char(p,35832).
+char(9,35833).
+char(1,35834).
+char(1,35835).
+char(1,35836).
+char(m,35837).
+char(7,35838).
+char(5,35839).
+char(3,35840).
+char(9,35841).
+char(p,35842).
+char(7,35843).
+char(2,35844).
+char(3,35845).
+char(3,35846).
+char(c,35847).
+char(c,35848).
+char(m,35849).
+char(o,35850).
+char(p,35851).
+char(9,35852).
+char(2,35853).
+char(3,35854).
+char(9,35855).
+char(m,35856).
+char(o,35857).
+char(m,35858).
+char(3,35859).
+char(9,35860).
+char(1,35861).
+char(1,35862).
+char(m,35863).
+char(o,35864).
+char(p,35865).
+char(8,35866).
+char(3,35867).
+char(5,35868).
+char(1,35869).
+char(c,35870).
+char(c,35871).
+char(m,35872).
+char(o,35873).
+char(m,35874).
+char(7,35875).
+char(1,35876).
+char(4,35877).
+char(4,35878).
+char(m,35879).
+char(o,35880).
+char(m,35881).
+char(7,35882).
+char(3,35883).
+char(7,35884).
+char(2,35885).
+char(p,35886).
+char(o,35887).
+char(p,35888).
+char(2,35889).
+char(2,35890).
+char(2,35891).
+char(4,35892).
+char(p,35893).
+char(3,35894).
+char(9,35895).
+char(6,35896).
+char(4,35897).
+char(m,35898).
+char(3,35899).
+char(6,35900).
+char(3,35901).
+char(8,35902).
+char(c,35903).
+char(c,35904).
+char(c,35905).
+char(c,35906).
+char(m,35907).
+char(o,35908).
+char(o,35909).
+char(9,35910).
+char(3,35911).
+char(2,35912).
+char(6,35913).
+char(c,35914).
+char(p,35915).
+char(8,35916).
+char(9,35917).
+char(5,35918).
+char(1,35919).
+char(m,35920).
+char(o,35921).
+char(m,35922).
+char(1,35923).
+char(3,35924).
+char(8,35925).
+char(6,35926).
+char(p,35927).
+char(3,35928).
+char(6,35929).
+char(4,35930).
+char(5,35931).
+char(m,35932).
+char(9,35933).
+char(9,35934).
+char(7,35935).
+char(0,35936).
+char(p,35937).
+char(o,35938).
+char(p,35939).
+char(o,35940).
+char(o,35941).
+char(p,35942).
+char(o,35943).
+char(6,35944).
+char(5,35945).
+char(5,35946).
+char(c,35947).
+char(p,35948).
+char(o,35949).
+char(o,35950).
+char(m,35951).
+char(o,35952).
+char(8,35953).
+char(2,35954).
+char(5,35955).
+char(9,35956).
+char(c,35957).
+char(c,35958).
+char(p,35959).
+char(o,35960).
+char(6,35961).
+char(5,35962).
+char(3,35963).
+char(2,35964).
+char(m,35965).
+char(o,35966).
+char(1,35967).
+char(4,35968).
+char(5,35969).
+char(8,35970).
+char(p,35971).
+char(o,35972).
+char(p,35973).
+char(2,35974).
+char(4,35975).
+char(1,35976).
+char(c,35977).
+char(m,35978).
+char(8,35979).
+char(9,35980).
+char(5,35981).
+char(1,35982).
+char(c,35983).
+char(m,35984).
+char(o,35985).
+char(p,35986).
+char(o,35987).
+char(2,35988).
+char(0,35989).
+char(2,35990).
+char(9,35991).
+char(m,35992).
+char(o,35993).
+char(3,35994).
+char(9,35995).
+char(9,35996).
+char(5,35997).
+char(p,35998).
+char(7,35999).
+char(7,36000).
+char(9,36001).
+char(1,36002).
+char(c,36003).
+char(c,36004).
+char(c,36005).
+char(c,36006).
+char(c,36007).
+char(p,36008).
+char(o,36009).
+char(m,36010).
+char(o,36011).
+char(3,36012).
+char(8,36013).
+char(9,36014).
+char(7,36015).
+char(p,36016).
+char(o,36017).
+char(m,36018).
+char(o,36019).
+char(p,36020).
+char(4,36021).
+char(0,36022).
+char(7,36023).
+char(5,36024).
+char(c,36025).
+char(p,36026).
+char(o,36027).
+char(o,36028).
+char(p,36029).
+char(8,36030).
+char(0,36031).
+char(2,36032).
+char(8,36033).
+char(c,36034).
+char(m,36035).
+char(o,36036).
+char(m,36037).
+char(o,36038).
+char(3,36039).
+char(0,36040).
+char(0,36041).
+char(5,36042).
+char(c,36043).
+char(c,36044).
+char(c,36045).
+char(c,36046).
+char(p,36047).
+char(o,36048).
+char(o,36049).
+char(p,36050).
+char(3,36051).
+char(6,36052).
+char(3,36053).
+char(0,36054).
+char(p,36055).
+char(o,36056).
+char(8,36057).
+char(9,36058).
+char(3,36059).
+char(8,36060).
+char(c,36061).
+char(c,36062).
+char(m,36063).
+char(o,36064).
+char(m,36065).
+char(1,36066).
+char(2,36067).
+char(9,36068).
+char(8,36069).
+char(c,36070).
+char(c,36071).
+char(c,36072).
+char(m,36073).
+char(o,36074).
+char(o,36075).
+char(p,36076).
+char(3,36077).
+char(6,36078).
+char(5,36079).
+char(9,36080).
+char(p,36081).
+char(o,36082).
+char(p,36083).
+char(7,36084).
+char(3,36085).
+char(9,36086).
+char(3,36087).
+char(p,36088).
+char(3,36089).
+char(7,36090).
+char(4,36091).
+char(6,36092).
+char(c,36093).
+char(c,36094).
+char(c,36095).
+char(m,36096).
+char(5,36097).
+char(0,36098).
+char(3,36099).
+char(8,36100).
+char(c,36101).
+char(c,36102).
+char(c,36103).
+char(m,36104).
+char(3,36105).
+char(5,36106).
+char(4,36107).
+char(1,36108).
+char(c,36109).
+char(c,36110).
+char(c,36111).
+char(c,36112).
+char(m,36113).
+char(o,36114).
+char(2,36115).
+char(2,36116).
+char(2,36117).
+char(3,36118).
+char(c,36119).
+char(c,36120).
+char(c,36121).
+char(p,36122).
+char(6,36123).
+char(4,36124).
+char(3,36125).
+char(m,36126).
+char(o,36127).
+char(3,36128).
+char(7,36129).
+char(9,36130).
+char(1,36131).
+char(m,36132).
+char(o,36133).
+char(p,36134).
+char(o,36135).
+char(p,36136).
+char(o,36137).
+char(o,36138).
+char(2,36139).
+char(4,36140).
+char(6,36141).
+char(5,36142).
+char(m,36143).
+char(o,36144).
+char(o,36145).
+char(1,36146).
+char(1,36147).
+char(2,36148).
+char(8,36149).
+char(m,36150).
+char(6,36151).
+char(7,36152).
+char(2,36153).
+char(9,36154).
+char(c,36155).
+char(c,36156).
+char(m,36157).
+char(o,36158).
+char(m,36159).
+char(o,36160).
+char(5,36161).
+char(9,36162).
+char(0,36163).
+char(c,36164).
+char(c,36165).
+char(c,36166).
+char(p,36167).
+char(2,36168).
+char(4,36169).
+char(2,36170).
+char(9,36171).
+char(p,36172).
+char(o,36173).
+char(p,36174).
+char(o,36175).
+char(m,36176).
+char(8,36177).
+char(5,36178).
+char(8,36179).
+char(5,36180).
+char(c,36181).
+char(p,36182).
+char(o,36183).
+char(m,36184).
+char(3,36185).
+char(4,36186).
+char(4,36187).
+char(3,36188).
+char(p,36189).
+char(o,36190).
+char(p,36191).
+char(2,36192).
+char(0,36193).
+char(7,36194).
+char(7,36195).
+char(c,36196).
+char(p,36197).
+char(o,36198).
+char(m,36199).
+char(o,36200).
+char(5,36201).
+char(8,36202).
+char(7,36203).
+char(8,36204).
+char(p,36205).
+char(o,36206).
+char(p,36207).
+char(3,36208).
+char(3,36209).
+char(4,36210).
+char(2,36211).
+char(c,36212).
+char(p,36213).
+char(3,36214).
+char(4,36215).
+char(6,36216).
+char(7,36217).
+char(c,36218).
+char(m,36219).
+char(o,36220).
+char(o,36221).
+char(m,36222).
+char(o,36223).
+char(m,36224).
+char(o,36225).
+char(9,36226).
+char(9,36227).
+char(8,36228).
+char(5,36229).
+char(m,36230).
+char(5,36231).
+char(3,36232).
+char(3,36233).
+char(p,36234).
+char(o,36235).
+char(m,36236).
+char(o,36237).
+char(p,36238).
+char(9,36239).
+char(8,36240).
+char(2,36241).
+char(3,36242).
+char(m,36243).
+char(o,36244).
+char(1,36245).
+char(7,36246).
+char(2,36247).
+char(p,36248).
+char(o,36249).
+char(o,36250).
+char(3,36251).
+char(6,36252).
+char(0,36253).
+char(6,36254).
+char(p,36255).
+char(1,36256).
+char(5,36257).
+char(6,36258).
+char(2,36259).
+char(p,36260).
+char(o,36261).
+char(m,36262).
+char(o,36263).
+char(p,36264).
+char(2,36265).
+char(7,36266).
+char(1,36267).
+char(5,36268).
+char(m,36269).
+char(o,36270).
+char(p,36271).
+char(o,36272).
+char(4,36273).
+char(0,36274).
+char(3,36275).
+char(9,36276).
+char(c,36277).
+char(p,36278).
+char(o,36279).
+char(p,36280).
+char(1,36281).
+char(2,36282).
+char(6,36283).
+char(2,36284).
+char(m,36285).
+char(5,36286).
+char(3,36287).
+char(6,36288).
+char(1,36289).
+char(m,36290).
+char(4,36291).
+char(8,36292).
+char(0,36293).
+char(5,36294).
+char(c,36295).
+char(c,36296).
+char(c,36297).
+char(c,36298).
+char(c,36299).
+char(m,36300).
+char(o,36301).
+char(p,36302).
+char(2,36303).
+char(7,36304).
+char(4,36305).
+char(3,36306).
+char(c,36307).
+char(p,36308).
+char(5,36309).
+char(7,36310).
+char(2,36311).
+char(9,36312).
+char(p,36313).
+char(5,36314).
+char(3,36315).
+char(8,36316).
+char(0,36317).
+char(p,36318).
+char(o,36319).
+char(o,36320).
+char(p,36321).
+char(3,36322).
+char(3,36323).
+char(9,36324).
+char(7,36325).
+char(c,36326).
+char(p,36327).
+char(8,36328).
+char(0,36329).
+char(5,36330).
+char(9,36331).
+char(m,36332).
+char(o,36333).
+char(m,36334).
+char(o,36335).
+char(p,36336).
+char(1,36337).
+char(9,36338).
+char(7,36339).
+char(5,36340).
+char(m,36341).
+char(o,36342).
+char(m,36343).
+char(2,36344).
+char(3,36345).
+char(5,36346).
+char(1,36347).
+char(p,36348).
+char(o,36349).
+char(p,36350).
+char(8,36351).
+char(8,36352).
+char(1,36353).
+char(7,36354).
+char(m,36355).
+char(o,36356).
+char(p,36357).
+char(o,36358).
+char(o,36359).
+char(m,36360).
+char(o,36361).
+char(p,36362).
+char(4,36363).
+char(8,36364).
+char(7,36365).
+char(8,36366).
+char(m,36367).
+char(6,36368).
+char(3,36369).
+char(2,36370).
+char(9,36371).
+char(c,36372).
+char(c,36373).
+char(c,36374).
+char(c,36375).
+char(c,36376).
+char(m,36377).
+char(o,36378).
+char(m,36379).
+char(5,36380).
+char(9,36381).
+char(1,36382).
+char(1,36383).
+char(c,36384).
+char(c,36385).
+char(m,36386).
+char(3,36387).
+char(9,36388).
+char(5,36389).
+char(5,36390).
+char(p,36391).
+char(o,36392).
+char(o,36393).
+char(p,36394).
+char(6,36395).
+char(7,36396).
+char(4,36397).
+char(5,36398).
+char(c,36399).
+char(p,36400).
+char(o,36401).
+char(o,36402).
+char(o,36403).
+char(p,36404).
+char(o,36405).
+char(p,36406).
+char(o,36407).
+char(m,36408).
+char(o,36409).
+char(9,36410).
+char(8,36411).
+char(1,36412).
+char(6,36413).
+char(p,36414).
+char(o,36415).
+char(p,36416).
+char(3,36417).
+char(3,36418).
+char(5,36419).
+char(1,36420).
+char(m,36421).
+char(o,36422).
+char(p,36423).
+char(o,36424).
+char(p,36425).
+char(o,36426).
+char(m,36427).
+char(o,36428).
+char(p,36429).
+char(7,36430).
+char(7,36431).
+char(8,36432).
+char(4,36433).
+char(c,36434).
+char(m,36435).
+char(9,36436).
+char(5,36437).
+char(8,36438).
+char(1,36439).
+char(m,36440).
+char(8,36441).
+char(7,36442).
+char(8,36443).
+char(7,36444).
+char(p,36445).
+char(o,36446).
+char(2,36447).
+char(0,36448).
+char(1,36449).
+char(9,36450).
+char(m,36451).
+char(3,36452).
+char(3,36453).
+char(5,36454).
+char(5,36455).
+char(p,36456).
+char(o,36457).
+char(p,36458).
+char(4,36459).
+char(7,36460).
+char(2,36461).
+char(9,36462).
+char(m,36463).
+char(o,36464).
+char(m,36465).
+char(6,36466).
+char(8,36467).
+char(1,36468).
+char(3,36469).
+char(m,36470).
+char(6,36471).
+char(1,36472).
+char(5,36473).
+char(8,36474).
+char(c,36475).
+char(c,36476).
+char(c,36477).
+char(m,36478).
+char(o,36479).
+char(4,36480).
+char(3,36481).
+char(6,36482).
+char(3,36483).
+char(m,36484).
+char(o,36485).
+char(p,36486).
+char(o,36487).
+char(p,36488).
+char(o,36489).
+char(p,36490).
+char(o,36491).
+char(o,36492).
+char(m,36493).
+char(o,36494).
+char(p,36495).
+char(o,36496).
+char(m,36497).
+char(o,36498).
+char(m,36499).
+char(2,36500).
+char(3,36501).
+char(4,36502).
+char(1,36503).
+char(m,36504).
+char(o,36505).
+char(m,36506).
+char(o,36507).
+char(9,36508).
+char(9,36509).
+char(3,36510).
+char(2,36511).
+char(c,36512).
+char(m,36513).
+char(6,36514).
+char(9,36515).
+char(3,36516).
+char(6,36517).
+char(c,36518).
+char(c,36519).
+char(c,36520).
+char(p,36521).
+char(o,36522).
+char(p,36523).
+char(2,36524).
+char(2,36525).
+char(9,36526).
+char(1,36527).
+char(c,36528).
+char(c,36529).
+char(p,36530).
+char(9,36531).
+char(3,36532).
+char(4,36533).
+char(1,36534).
+char(c,36535).
+char(p,36536).
+char(o,36537).
+char(p,36538).
+char(o,36539).
+char(o,36540).
+char(p,36541).
+char(2,36542).
+char(6,36543).
+char(8,36544).
+char(6,36545).
+char(p,36546).
+char(o,36547).
+char(o,36548).
+char(o,36549).
+char(m,36550).
+char(5,36551).
+char(6,36552).
+char(5,36553).
+char(2,36554).
+char(p,36555).
+char(o,36556).
+char(p,36557).
+char(6,36558).
+char(0,36559).
+char(0,36560).
+char(9,36561).
+char(c,36562).
+char(c,36563).
+char(p,36564).
+char(7,36565).
+char(8,36566).
+char(7,36567).
+char(8,36568).
+char(m,36569).
+char(o,36570).
+char(8,36571).
+char(1,36572).
+char(8,36573).
+char(8,36574).
+char(c,36575).
+char(c,36576).
+char(c,36577).
+char(c,36578).
+char(p,36579).
+char(1,36580).
+char(6,36581).
+char(4,36582).
+char(0,36583).
+char(p,36584).
+char(8,36585).
+char(7,36586).
+char(4,36587).
+char(0,36588).
+char(c,36589).
+char(c,36590).
+char(p,36591).
+char(7,36592).
+char(4,36593).
+char(9,36594).
+char(6,36595).
+char(p,36596).
+char(o,36597).
+char(m,36598).
+char(o,36599).
+char(m,36600).
+char(o,36601).
+char(o,36602).
+char(o,36603).
+char(m,36604).
+char(o,36605).
+char(m,36606).
+char(o,36607).
+char(o,36608).
+char(5,36609).
+char(1,36610).
+char(7,36611).
+char(1,36612).
+char(p,36613).
+char(5,36614).
+char(3,36615).
+char(1,36616).
+char(9,36617).
+char(m,36618).
+char(2,36619).
+char(6,36620).
+char(4,36621).
+char(2,36622).
+char(c,36623).
+char(c,36624).
+char(c,36625).
+char(p,36626).
+char(6,36627).
+char(9,36628).
+char(6,36629).
+char(4,36630).
+char(p,36631).
+char(o,36632).
+char(3,36633).
+char(8,36634).
+char(9,36635).
+char(8,36636).
+char(m,36637).
+char(7,36638).
+char(1,36639).
+char(1,36640).
+char(c,36641).
+char(m,36642).
+char(o,36643).
+char(m,36644).
+char(o,36645).
+char(2,36646).
+char(6,36647).
+char(7,36648).
+char(3,36649).
+char(c,36650).
+char(c,36651).
+char(m,36652).
+char(8,36653).
+char(7,36654).
+char(9,36655).
+char(c,36656).
+char(c,36657).
+char(m,36658).
+char(1,36659).
+char(7,36660).
+char(4,36661).
+char(9,36662).
+char(m,36663).
+char(9,36664).
+char(1,36665).
+char(3,36666).
+char(8,36667).
+char(c,36668).
+char(c,36669).
+char(m,36670).
+char(o,36671).
+char(p,36672).
+char(5,36673).
+char(2,36674).
+char(3,36675).
+char(7,36676).
+char(m,36677).
+char(4,36678).
+char(9,36679).
+char(1,36680).
+char(8,36681).
+char(p,36682).
+char(o,36683).
+char(m,36684).
+char(o,36685).
+char(p,36686).
+char(o,36687).
+char(p,36688).
+char(o,36689).
+char(p,36690).
+char(2,36691).
+char(8,36692).
+char(6,36693).
+char(2,36694).
+char(m,36695).
+char(7,36696).
+char(5,36697).
+char(4,36698).
+char(9,36699).
+char(c,36700).
+char(c,36701).
+char(m,36702).
+char(o,36703).
+char(p,36704).
+char(4,36705).
+char(3,36706).
+char(5,36707).
+char(1,36708).
+char(m,36709).
+char(3,36710).
+char(5,36711).
+char(9,36712).
+char(8,36713).
+char(c,36714).
+char(c,36715).
+char(c,36716).
+char(m,36717).
+char(2,36718).
+char(1,36719).
+char(1,36720).
+char(8,36721).
+char(c,36722).
+char(m,36723).
+char(5,36724).
+char(3,36725).
+char(6,36726).
+char(2,36727).
+char(m,36728).
+char(9,36729).
+char(3,36730).
+char(0,36731).
+char(9,36732).
+char(p,36733).
+char(5,36734).
+char(1,36735).
+char(5,36736).
+char(c,36737).
+char(p,36738).
+char(6,36739).
+char(3,36740).
+char(2,36741).
+char(6,36742).
+char(p,36743).
+char(6,36744).
+char(3,36745).
+char(0,36746).
+char(1,36747).
+char(c,36748).
+char(c,36749).
+char(c,36750).
+char(c,36751).
+char(c,36752).
+char(c,36753).
+char(m,36754).
+char(o,36755).
+char(m,36756).
+char(2,36757).
+char(7,36758).
+char(8,36759).
+char(7,36760).
+char(c,36761).
+char(c,36762).
+char(c,36763).
+char(c,36764).
+char(c,36765).
+char(p,36766).
+char(7,36767).
+char(8,36768).
+char(8,36769).
+char(2,36770).
+char(p,36771).
+char(o,36772).
+char(m,36773).
+char(6,36774).
+char(7,36775).
+char(8,36776).
+char(5,36777).
+char(m,36778).
+char(8,36779).
+char(7,36780).
+char(8,36781).
+char(2,36782).
+char(m,36783).
+char(o,36784).
+char(o,36785).
+char(4,36786).
+char(4,36787).
+char(5,36788).
+char(0,36789).
+char(c,36790).
+char(c,36791).
+char(m,36792).
+char(8,36793).
+char(6,36794).
+char(8,36795).
+char(1,36796).
+char(c,36797).
+char(c,36798).
+char(c,36799).
+char(p,36800).
+char(o,36801).
+char(m,36802).
+char(6,36803).
+char(5,36804).
+char(3,36805).
+char(0,36806).
+char(p,36807).
+char(o,36808).
+char(1,36809).
+char(1,36810).
+char(4,36811).
+char(2,36812).
+char(p,36813).
+char(o,36814).
+char(6,36815).
+char(1,36816).
+char(5,36817).
+char(7,36818).
+char(p,36819).
+char(o,36820).
+char(m,36821).
+char(2,36822).
+char(5,36823).
+char(6,36824).
+char(4,36825).
+char(m,36826).
+char(7,36827).
+char(5,36828).
+char(8,36829).
+char(7,36830).
+char(p,36831).
+char(8,36832).
+char(0,36833).
+char(3,36834).
+char(5,36835).
+char(c,36836).
+char(m,36837).
+char(6,36838).
+char(4,36839).
+char(4,36840).
+char(p,36841).
+char(o,36842).
+char(p,36843).
+char(o,36844).
+char(p,36845).
+char(o,36846).
+char(o,36847).
+char(m,36848).
+char(o,36849).
+char(o,36850).
+char(p,36851).
+char(3,36852).
+char(6,36853).
+char(7,36854).
+char(9,36855).
+char(p,36856).
+char(2,36857).
+char(4,36858).
+char(3,36859).
+char(5,36860).
+char(p,36861).
+char(9,36862).
+char(7,36863).
+char(4,36864).
+char(6,36865).
+char(m,36866).
+char(7,36867).
+char(0,36868).
+char(2,36869).
+char(3,36870).
+char(m,36871).
+char(o,36872).
+char(m,36873).
+char(o,36874).
+char(m,36875).
+char(3,36876).
+char(8,36877).
+char(3,36878).
+char(6,36879).
+char(c,36880).
+char(m,36881).
+char(7,36882).
+char(8,36883).
+char(6,36884).
+char(m,36885).
+char(7,36886).
+char(6,36887).
+char(1,36888).
+char(7,36889).
+char(m,36890).
+char(o,36891).
+char(p,36892).
+char(6,36893).
+char(9,36894).
+char(7,36895).
+char(9,36896).
+char(p,36897).
+char(1,36898).
+char(4,36899).
+char(9,36900).
+char(9,36901).
+char(p,36902).
+char(o,36903).
+char(p,36904).
+char(o,36905).
+char(m,36906).
+char(o,36907).
+char(o,36908).
+char(o,36909).
+char(9,36910).
+char(2,36911).
+char(3,36912).
+char(1,36913).
+char(c,36914).
+char(c,36915).
+char(c,36916).
+char(m,36917).
+char(o,36918).
+char(p,36919).
+char(o,36920).
+char(2,36921).
+char(7,36922).
+char(4,36923).
+char(6,36924).
+char(c,36925).
+char(m,36926).
+char(7,36927).
+char(0,36928).
+char(7,36929).
+char(6,36930).
+char(m,36931).
+char(o,36932).
+char(o,36933).
+char(p,36934).
+char(o,36935).
+char(m,36936).
+char(2,36937).
+char(5,36938).
+char(7,36939).
+char(0,36940).
+char(c,36941).
+char(m,36942).
+char(6,36943).
+char(0,36944).
+char(2,36945).
+char(c,36946).
+char(m,36947).
+char(1,36948).
+char(0,36949).
+char(8,36950).
+char(8,36951).
+char(c,36952).
+char(p,36953).
+char(o,36954).
+char(m,36955).
+char(3,36956).
+char(8,36957).
+char(6,36958).
+char(m,36959).
+char(9,36960).
+char(7,36961).
+char(8,36962).
+char(1,36963).
+char(p,36964).
+char(o,36965).
+char(o,36966).
+char(m,36967).
+char(o,36968).
+char(p,36969).
+char(o,36970).
+char(m,36971).
+char(3,36972).
+char(2,36973).
+char(6,36974).
+char(m,36975).
+char(o,36976).
+char(m,36977).
+char(3,36978).
+char(8,36979).
+char(5,36980).
+char(3,36981).
+char(p,36982).
+char(6,36983).
+char(3,36984).
+char(0,36985).
+char(9,36986).
+char(p,36987).
+char(o,36988).
+char(o,36989).
+char(5,36990).
+char(2,36991).
+char(4,36992).
+char(6,36993).
+char(c,36994).
+char(p,36995).
+char(o,36996).
+char(p,36997).
+char(o,36998).
+char(p,36999).
+char(o,37000).
+char(m,37001).
+char(1,37002).
+char(4,37003).
+char(9,37004).
+char(7,37005).
+char(m,37006).
+char(4,37007).
+char(5,37008).
+char(8,37009).
+char(4,37010).
+char(c,37011).
+char(p,37012).
+char(3,37013).
+char(3,37014).
+char(0,37015).
+char(5,37016).
+char(c,37017).
+char(m,37018).
+char(6,37019).
+char(0,37020).
+char(7,37021).
+char(6,37022).
+char(c,37023).
+char(c,37024).
+char(c,37025).
+char(p,37026).
+char(3,37027).
+char(1,37028).
+char(9,37029).
+char(m,37030).
+char(o,37031).
+char(p,37032).
+char(7,37033).
+char(9,37034).
+char(2,37035).
+char(0,37036).
+char(p,37037).
+char(o,37038).
+char(9,37039).
+char(2,37040).
+char(2,37041).
+char(0,37042).
+char(c,37043).
+char(p,37044).
+char(9,37045).
+char(2,37046).
+char(2,37047).
+char(3,37048).
+char(m,37049).
+char(o,37050).
+char(m,37051).
+char(o,37052).
+char(p,37053).
+char(8,37054).
+char(1,37055).
+char(9,37056).
+char(0,37057).
+char(p,37058).
+char(o,37059).
+char(o,37060).
+char(p,37061).
+char(3,37062).
+char(9,37063).
+char(8,37064).
+char(3,37065).
+char(c,37066).
+char(p,37067).
+char(4,37068).
+char(3,37069).
+char(0,37070).
+char(1,37071).
+char(p,37072).
+char(o,37073).
+char(p,37074).
+char(6,37075).
+char(4,37076).
+char(1,37077).
+char(2,37078).
+char(c,37079).
+char(c,37080).
+char(c,37081).
+char(p,37082).
+char(o,37083).
+char(p,37084).
+char(8,37085).
+char(5,37086).
+char(6,37087).
+char(0,37088).
+char(p,37089).
+char(8,37090).
+char(7,37091).
+char(3,37092).
+char(1,37093).
+char(p,37094).
+char(o,37095).
+char(o,37096).
+char(7,37097).
+char(2,37098).
+char(3,37099).
+char(2,37100).
+char(p,37101).
+char(o,37102).
+char(o,37103).
+char(m,37104).
+char(2,37105).
+char(0,37106).
+char(1,37107).
+char(5,37108).
+char(m,37109).
+char(o,37110).
+char(m,37111).
+char(o,37112).
+char(p,37113).
+char(1,37114).
+char(8,37115).
+char(7,37116).
+char(8,37117).
+char(m,37118).
+char(o,37119).
+char(p,37120).
+char(5,37121).
+char(5,37122).
+char(8,37123).
+char(6,37124).
+char(p,37125).
+char(2,37126).
+char(0,37127).
+char(7,37128).
+char(4,37129).
+char(p,37130).
+char(2,37131).
+char(2,37132).
+char(9,37133).
+char(4,37134).
+char(p,37135).
+char(3,37136).
+char(3,37137).
+char(4,37138).
+char(3,37139).
+char(c,37140).
+char(m,37141).
+char(o,37142).
+char(p,37143).
+char(1,37144).
+char(7,37145).
+char(5,37146).
+char(9,37147).
+char(c,37148).
+char(m,37149).
+char(2,37150).
+char(2,37151).
+char(1,37152).
+char(4,37153).
+char(c,37154).
+char(c,37155).
+char(c,37156).
+char(m,37157).
+char(9,37158).
+char(0,37159).
+char(6,37160).
+char(9,37161).
+char(p,37162).
+char(o,37163).
+char(m,37164).
+char(o,37165).
+char(p,37166).
+char(o,37167).
+char(p,37168).
+char(4,37169).
+char(1,37170).
+char(9,37171).
+char(7,37172).
+char(c,37173).
+char(c,37174).
+char(p,37175).
+char(o,37176).
+char(m,37177).
+char(o,37178).
+char(7,37179).
+char(0,37180).
+char(4,37181).
+char(6,37182).
+char(m,37183).
+char(7,37184).
+char(9,37185).
+char(9,37186).
+char(0,37187).
+char(p,37188).
+char(o,37189).
+char(o,37190).
+char(2,37191).
+char(0,37192).
+char(0,37193).
+char(6,37194).
+char(m,37195).
+char(o,37196).
+char(m,37197).
+char(7,37198).
+char(9,37199).
+char(0,37200).
+char(c,37201).
+char(p,37202).
+char(o,37203).
+char(m,37204).
+char(o,37205).
+char(6,37206).
+char(2,37207).
+char(8,37208).
+char(5,37209).
+char(m,37210).
+char(7,37211).
+char(0,37212).
+char(6,37213).
+char(1,37214).
+char(p,37215).
+char(5,37216).
+char(5,37217).
+char(5,37218).
+char(4,37219).
+char(c,37220).
+char(m,37221).
+char(6,37222).
+char(0,37223).
+char(8,37224).
+char(9,37225).
+char(c,37226).
+char(c,37227).
+char(c,37228).
+char(m,37229).
+char(6,37230).
+char(8,37231).
+char(6,37232).
+char(3,37233).
+char(c,37234).
+char(p,37235).
+char(o,37236).
+char(o,37237).
+char(m,37238).
+char(o,37239).
+char(m,37240).
+char(o,37241).
+char(p,37242).
+char(5,37243).
+char(9,37244).
+char(0,37245).
+char(4,37246).
+char(c,37247).
+char(c,37248).
+char(m,37249).
+char(9,37250).
+char(2,37251).
+char(8,37252).
+char(0,37253).
+char(c,37254).
+char(p,37255).
+char(5,37256).
+char(0,37257).
+char(2,37258).
+char(7,37259).
+char(p,37260).
+char(o,37261).
+char(2,37262).
+char(8,37263).
+char(3,37264).
+char(2,37265).
+char(c,37266).
+char(c,37267).
+char(c,37268).
+char(m,37269).
+char(6,37270).
+char(4,37271).
+char(9,37272).
+char(6,37273).
+char(c,37274).
+char(c,37275).
+char(c,37276).
+char(p,37277).
+char(o,37278).
+char(p,37279).
+char(o,37280).
+char(p,37281).
+char(5,37282).
+char(8,37283).
+char(9,37284).
+char(6,37285).
+char(c,37286).
+char(c,37287).
+char(c,37288).
+char(c,37289).
+char(m,37290).
+char(o,37291).
+char(7,37292).
+char(9,37293).
+char(4,37294).
+char(0,37295).
+char(c,37296).
+char(m,37297).
+char(4,37298).
+char(9,37299).
+char(9,37300).
+char(8,37301).
+char(p,37302).
+char(4,37303).
+char(2,37304).
+char(5,37305).
+char(3,37306).
+char(c,37307).
+char(m,37308).
+char(o,37309).
+char(9,37310).
+char(1,37311).
+char(7,37312).
+char(0,37313).
+char(m,37314).
+char(o,37315).
+char(o,37316).
+char(p,37317).
+char(3,37318).
+char(3,37319).
+char(4,37320).
+char(9,37321).
+char(p,37322).
+char(o,37323).
+char(p,37324).
+char(o,37325).
+char(p,37326).
+char(3,37327).
+char(2,37328).
+char(7,37329).
+char(7,37330).
+char(p,37331).
+char(9,37332).
+char(3,37333).
+char(3,37334).
+char(9,37335).
+char(c,37336).
+char(m,37337).
+char(o,37338).
+char(o,37339).
+char(p,37340).
+char(3,37341).
+char(7,37342).
+char(4,37343).
+char(4,37344).
+char(c,37345).
+char(c,37346).
+char(m,37347).
+char(o,37348).
+char(o,37349).
+char(p,37350).
+char(o,37351).
+char(p,37352).
+char(o,37353).
+char(m,37354).
+char(9,37355).
+char(7,37356).
+char(9,37357).
+char(c,37358).
+char(c,37359).
+char(c,37360).
+char(c,37361).
+char(c,37362).
+char(p,37363).
+char(4,37364).
+char(7,37365).
+char(4,37366).
+char(8,37367).
+char(p,37368).
+char(7,37369).
+char(4,37370).
+char(7,37371).
+char(5,37372).
+char(m,37373).
+char(o,37374).
+char(m,37375).
+char(2,37376).
+char(8,37377).
+char(6,37378).
+char(3,37379).
+char(c,37380).
+char(p,37381).
+char(9,37382).
+char(8,37383).
+char(2,37384).
+char(4,37385).
+char(c,37386).
+char(p,37387).
+char(5,37388).
+char(5,37389).
+char(4,37390).
+char(3,37391).
+char(c,37392).
+char(c,37393).
+char(c,37394).
+char(c,37395).
+char(c,37396).
+char(m,37397).
+char(o,37398).
+char(m,37399).
+char(o,37400).
+char(p,37401).
+char(7,37402).
+char(1,37403).
+char(9,37404).
+char(6,37405).
+char(m,37406).
+char(o,37407).
+char(m,37408).
+char(9,37409).
+char(7,37410).
+char(4,37411).
+char(0,37412).
+char(p,37413).
+char(7,37414).
+char(9,37415).
+char(7,37416).
+char(8,37417).
+char(c,37418).
+char(p,37419).
+char(1,37420).
+char(3,37421).
+char(4,37422).
+char(8,37423).
+char(m,37424).
+char(5,37425).
+char(5,37426).
+char(8,37427).
+char(2,37428).
+char(c,37429).
+char(p,37430).
+char(6,37431).
+char(0,37432).
+char(2,37433).
+char(4,37434).
+char(c,37435).
+char(c,37436).
+char(c,37437).
+char(c,37438).
+char(m,37439).
+char(7,37440).
+char(1,37441).
+char(2,37442).
+char(8,37443).
+char(m,37444).
+char(5,37445).
+char(6,37446).
+char(3,37447).
+char(6,37448).
+char(c,37449).
+char(c,37450).
+char(m,37451).
+char(o,37452).
+char(m,37453).
+char(o,37454).
+char(6,37455).
+char(3,37456).
+char(3,37457).
+char(7,37458).
+char(m,37459).
+char(2,37460).
+char(6,37461).
+char(7,37462).
+char(7,37463).
+char(m,37464).
+char(1,37465).
+char(3,37466).
+char(2,37467).
+char(1,37468).
+char(c,37469).
+char(c,37470).
+char(p,37471).
+char(7,37472).
+char(3,37473).
+char(0,37474).
+char(5,37475).
+char(p,37476).
+char(4,37477).
+char(8,37478).
+char(2,37479).
+char(0,37480).
+char(m,37481).
+char(o,37482).
+char(m,37483).
+char(8,37484).
+char(8,37485).
+char(1,37486).
+char(9,37487).
+char(c,37488).
+char(c,37489).
+char(m,37490).
+char(o,37491).
+char(m,37492).
+char(o,37493).
+char(p,37494).
+char(3,37495).
+char(2,37496).
+char(8,37497).
+char(7,37498).
+char(c,37499).
+char(c,37500).
+char(m,37501).
+char(o,37502).
+char(m,37503).
+char(o,37504).
+char(5,37505).
+char(0,37506).
+char(0,37507).
+char(2,37508).
+char(c,37509).
+char(c,37510).
+char(p,37511).
+char(1,37512).
+char(2,37513).
+char(0,37514).
+char(2,37515).
+char(c,37516).
+char(m,37517).
+char(1,37518).
+char(3,37519).
+char(6,37520).
+char(6,37521).
+char(m,37522).
+char(5,37523).
+char(8,37524).
+char(6,37525).
+char(4,37526).
+char(c,37527).
+char(m,37528).
+char(o,37529).
+char(m,37530).
+char(9,37531).
+char(0,37532).
+char(1,37533).
+char(1,37534).
+char(m,37535).
+char(o,37536).
+char(o,37537).
+char(p,37538).
+char(2,37539).
+char(5,37540).
+char(9,37541).
+char(1,37542).
+char(c,37543).
+char(m,37544).
+char(2,37545).
+char(3,37546).
+char(1,37547).
+char(5,37548).
+char(c,37549).
+char(c,37550).
+char(c,37551).
+char(c,37552).
+char(c,37553).
+char(c,37554).
+char(p,37555).
+char(3,37556).
+char(9,37557).
+char(9,37558).
+char(1,37559).
+char(p,37560).
+char(5,37561).
+char(5,37562).
+char(6,37563).
+char(0,37564).
+char(m,37565).
+char(o,37566).
+char(p,37567).
+char(o,37568).
+char(p,37569).
+char(8,37570).
+char(0,37571).
+char(7,37572).
+char(7,37573).
+char(p,37574).
+char(o,37575).
+char(m,37576).
+char(7,37577).
+char(8,37578).
+char(4,37579).
+char(2,37580).
+char(c,37581).
+char(m,37582).
+char(o,37583).
+char(p,37584).
+char(8,37585).
+char(7,37586).
+char(0,37587).
+char(3,37588).
+char(c,37589).
+char(c,37590).
+char(c,37591).
+char(p,37592).
+char(o,37593).
+char(p,37594).
+char(o,37595).
+char(p,37596).
+char(3,37597).
+char(1,37598).
+char(4,37599).
+char(2,37600).
+char(c,37601).
+char(c,37602).
+char(p,37603).
+char(o,37604).
+char(3,37605).
+char(0,37606).
+char(1,37607).
+char(4,37608).
+char(p,37609).
+char(o,37610).
+char(o,37611).
+char(8,37612).
+char(7,37613).
+char(1,37614).
+char(8,37615).
+char(m,37616).
+char(o,37617).
+char(o,37618).
+char(p,37619).
+char(4,37620).
+char(4,37621).
+char(0,37622).
+char(8,37623).
+char(c,37624).
+char(p,37625).
+char(o,37626).
+char(o,37627).
+char(m,37628).
+char(7,37629).
+char(0,37630).
+char(4,37631).
+char(c,37632).
+char(m,37633).
+char(o,37634).
+char(p,37635).
+char(7,37636).
+char(2,37637).
+char(9,37638).
+char(0,37639).
+char(p,37640).
+char(o,37641).
+char(m,37642).
+char(o,37643).
+char(m,37644).
+char(o,37645).
+char(m,37646).
+char(1,37647).
+char(4,37648).
+char(5,37649).
+char(2,37650).
+char(c,37651).
+char(p,37652).
+char(o,37653).
+char(o,37654).
+char(1,37655).
+char(5,37656).
+char(9,37657).
+char(9,37658).
+char(p,37659).
+char(o,37660).
+char(m,37661).
+char(o,37662).
+char(p,37663).
+char(8,37664).
+char(6,37665).
+char(1,37666).
+char(5,37667).
+char(c,37668).
+char(c,37669).
+char(m,37670).
+char(6,37671).
+char(5,37672).
+char(6,37673).
+char(8,37674).
+char(c,37675).
+char(c,37676).
+char(c,37677).
+char(c,37678).
+char(c,37679).
+char(p,37680).
+char(7,37681).
+char(0,37682).
+char(3,37683).
+char(5,37684).
+char(c,37685).
+char(c,37686).
+char(m,37687).
+char(3,37688).
+char(3,37689).
+char(7,37690).
+char(6,37691).
+char(c,37692).
+char(m,37693).
+char(o,37694).
+char(m,37695).
+char(o,37696).
+char(o,37697).
+char(m,37698).
+char(o,37699).
+char(p,37700).
+char(o,37701).
+char(p,37702).
+char(9,37703).
+char(9,37704).
+char(8,37705).
+char(8,37706).
+char(c,37707).
+char(c,37708).
+char(c,37709).
+char(p,37710).
+char(6,37711).
+char(3,37712).
+char(6,37713).
+char(3,37714).
+char(m,37715).
+char(o,37716).
+char(m,37717).
+char(4,37718).
+char(6,37719).
+char(9,37720).
+char(6,37721).
+char(m,37722).
+char(8,37723).
+char(3,37724).
+char(8,37725).
+char(4,37726).
+char(c,37727).
+char(m,37728).
+char(o,37729).
+char(5,37730).
+char(7,37731).
+char(9,37732).
+char(p,37733).
+char(o,37734).
+char(o,37735).
+char(p,37736).
+char(o,37737).
+char(p,37738).
+char(o,37739).
+char(5,37740).
+char(1,37741).
+char(4,37742).
+char(7,37743).
+char(c,37744).
+char(m,37745).
+char(o,37746).
+char(p,37747).
+char(1,37748).
+char(9,37749).
+char(8,37750).
+char(8,37751).
+char(p,37752).
+char(o,37753).
+char(p,37754).
+char(1,37755).
+char(4,37756).
+char(2,37757).
+char(m,37758).
+char(6,37759).
+char(7,37760).
+char(6,37761).
+char(c,37762).
+char(c,37763).
+char(m,37764).
+char(6,37765).
+char(1,37766).
+char(1,37767).
+char(0,37768).
+char(m,37769).
+char(o,37770).
+char(9,37771).
+char(7,37772).
+char(0,37773).
+char(5,37774).
+char(c,37775).
+char(c,37776).
+char(m,37777).
+char(o,37778).
+char(o,37779).
+char(m,37780).
+char(8,37781).
+char(2,37782).
+char(1,37783).
+char(6,37784).
+char(p,37785).
+char(9,37786).
+char(8,37787).
+char(5,37788).
+char(7,37789).
+char(c,37790).
+char(c,37791).
+char(c,37792).
+char(c,37793).
+char(c,37794).
+char(c,37795).
+char(c,37796).
+char(c,37797).
+char(p,37798).
+char(4,37799).
+char(7,37800).
+char(8,37801).
+char(0,37802).
+char(c,37803).
+char(m,37804).
+char(o,37805).
+char(m,37806).
+char(o,37807).
+char(p,37808).
+char(5,37809).
+char(6,37810).
+char(3,37811).
+char(9,37812).
+char(m,37813).
+char(4,37814).
+char(8,37815).
+char(0,37816).
+char(9,37817).
+char(c,37818).
+char(c,37819).
+char(m,37820).
+char(9,37821).
+char(6,37822).
+char(6,37823).
+char(3,37824).
+char(c,37825).
+char(c,37826).
+char(m,37827).
+char(1,37828).
+char(2,37829).
+char(0,37830).
+char(2,37831).
+char(p,37832).
+char(8,37833).
+char(6,37834).
+char(9,37835).
+char(m,37836).
+char(o,37837).
+char(m,37838).
+char(o,37839).
+char(1,37840).
+char(6,37841).
+char(9,37842).
+char(0,37843).
+char(c,37844).
+char(c,37845).
+char(c,37846).
+char(c,37847).
+char(c,37848).
+char(c,37849).
+char(p,37850).
+char(o,37851).
+char(p,37852).
+char(7,37853).
+char(3,37854).
+char(3,37855).
+char(3,37856).
+char(c,37857).
+char(m,37858).
+char(o,37859).
+char(m,37860).
+char(4,37861).
+char(9,37862).
+char(4,37863).
+char(5,37864).
+char(c,37865).
+char(m,37866).
+char(o,37867).
+char(m,37868).
+char(6,37869).
+char(4,37870).
+char(8,37871).
+char(1,37872).
+char(m,37873).
+char(o,37874).
+char(p,37875).
+char(o,37876).
+char(o,37877).
+char(o,37878).
+char(o,37879).
+char(m,37880).
+char(6,37881).
+char(4,37882).
+char(4,37883).
+char(c,37884).
+char(m,37885).
+char(o,37886).
+char(3,37887).
+char(3,37888).
+char(2,37889).
+char(2,37890).
+char(m,37891).
+char(o,37892).
+char(p,37893).
+char(4,37894).
+char(8,37895).
+char(6,37896).
+char(0,37897).
+char(c,37898).
+char(m,37899).
+char(o,37900).
+char(p,37901).
+char(o,37902).
+char(m,37903).
+char(5,37904).
+char(6,37905).
+char(5,37906).
+char(1,37907).
+char(p,37908).
+char(o,37909).
+char(4,37910).
+char(7,37911).
+char(5,37912).
+char(0,37913).
+char(m,37914).
+char(o,37915).
+char(m,37916).
+char(8,37917).
+char(9,37918).
+char(p,37919).
+char(2,37920).
+char(7,37921).
+char(7,37922).
+char(0,37923).
+char(c,37924).
+char(c,37925).
+char(c,37926).
+char(c,37927).
+char(m,37928).
+char(o,37929).
+char(m,37930).
+char(o,37931).
+char(m,37932).
+char(o,37933).
+char(m,37934).
+char(o,37935).
+char(m,37936).
+char(o,37937).
+char(o,37938).
+char(p,37939).
+char(o,37940).
+char(o,37941).
+char(m,37942).
+char(4,37943).
+char(8,37944).
+char(9,37945).
+char(8,37946).
+char(m,37947).
+char(1,37948).
+char(7,37949).
+char(7,37950).
+char(6,37951).
+char(c,37952).
+char(p,37953).
+char(2,37954).
+char(9,37955).
+char(4,37956).
+char(7,37957).
+char(p,37958).
+char(2,37959).
+char(0,37960).
+char(6,37961).
+char(2,37962).
+char(c,37963).
+char(m,37964).
+char(3,37965).
+char(7,37966).
+char(6,37967).
+char(1,37968).
+char(p,37969).
+char(5,37970).
+char(7,37971).
+char(4,37972).
+char(p,37973).
+char(5,37974).
+char(6,37975).
+char(9,37976).
+char(8,37977).
+char(m,37978).
+char(o,37979).
+char(7,37980).
+char(3,37981).
+char(5,37982).
+char(4,37983).
+char(p,37984).
+char(o,37985).
+char(o,37986).
+char(m,37987).
+char(o,37988).
+char(p,37989).
+char(o,37990).
+char(6,37991).
+char(5,37992).
+char(7,37993).
+char(6,37994).
+char(m,37995).
+char(1,37996).
+char(5,37997).
+char(7,37998).
+char(3,37999).
+char(m,38000).
+char(2,38001).
+char(0,38002).
+char(8,38003).
+char(7,38004).
+char(c,38005).
+char(c,38006).
+char(m,38007).
+char(o,38008).
+char(5,38009).
+char(2,38010).
+char(6,38011).
+char(5,38012).
+char(c,38013).
+char(p,38014).
+char(o,38015).
+char(p,38016).
+char(o,38017).
+char(p,38018).
+char(5,38019).
+char(1,38020).
+char(4,38021).
+char(6,38022).
+char(c,38023).
+char(c,38024).
+char(p,38025).
+char(7,38026).
+char(4,38027).
+char(8,38028).
+char(2,38029).
+char(p,38030).
+char(2,38031).
+char(9,38032).
+char(8,38033).
+char(3,38034).
+char(m,38035).
+char(o,38036).
+char(6,38037).
+char(6,38038).
+char(9,38039).
+char(0,38040).
+char(c,38041).
+char(m,38042).
+char(o,38043).
+char(p,38044).
+char(2,38045).
+char(8,38046).
+char(0,38047).
+char(5,38048).
+char(m,38049).
+char(3,38050).
+char(7,38051).
+char(3,38052).
+char(3,38053).
+char(p,38054).
+char(o,38055).
+char(m,38056).
+char(o,38057).
+char(m,38058).
+char(o,38059).
+char(m,38060).
+char(9,38061).
+char(2,38062).
+char(0,38063).
+char(5,38064).
+char(c,38065).
+char(c,38066).
+char(c,38067).
+char(c,38068).
+char(c,38069).
+char(p,38070).
+char(8,38071).
+char(6,38072).
+char(0,38073).
+char(9,38074).
+char(c,38075).
+char(p,38076).
+char(o,38077).
+char(p,38078).
+char(o,38079).
+char(3,38080).
+char(0,38081).
+char(0,38082).
+char(6,38083).
+char(c,38084).
+char(c,38085).
+char(c,38086).
+char(c,38087).
+char(c,38088).
+char(p,38089).
+char(o,38090).
+char(o,38091).
+char(o,38092).
+char(o,38093).
+char(o,38094).
+char(m,38095).
+char(6,38096).
+char(1,38097).
+char(8,38098).
+char(3,38099).
+char(c,38100).
+char(m,38101).
+char(2,38102).
+char(6,38103).
+char(8,38104).
+char(2,38105).
+char(p,38106).
+char(o,38107).
+char(p,38108).
+char(4,38109).
+char(6,38110).
+char(9,38111).
+char(c,38112).
+char(c,38113).
+char(c,38114).
+char(c,38115).
+char(c,38116).
+char(m,38117).
+char(o,38118).
+char(m,38119).
+char(8,38120).
+char(9,38121).
+char(6,38122).
+char(c,38123).
+char(c,38124).
+char(m,38125).
+char(3,38126).
+char(2,38127).
+char(8,38128).
+char(6,38129).
+char(c,38130).
+char(m,38131).
+char(8,38132).
+char(3,38133).
+char(4,38134).
+char(9,38135).
+char(c,38136).
+char(p,38137).
+char(o,38138).
+char(o,38139).
+char(p,38140).
+char(2,38141).
+char(3,38142).
+char(8,38143).
+char(9,38144).
+char(c,38145).
+char(m,38146).
+char(o,38147).
+char(9,38148).
+char(8,38149).
+char(9,38150).
+char(9,38151).
+char(c,38152).
+char(c,38153).
+char(c,38154).
+char(c,38155).
+char(m,38156).
+char(o,38157).
+char(6,38158).
+char(8,38159).
+char(4,38160).
+char(8,38161).
+char(p,38162).
+char(o,38163).
+char(m,38164).
+char(o,38165).
+char(p,38166).
+char(1,38167).
+char(5,38168).
+char(2,38169).
+char(1,38170).
+char(p,38171).
+char(7,38172).
+char(3,38173).
+char(4,38174).
+char(5,38175).
+char(p,38176).
+char(o,38177).
+char(2,38178).
+char(7,38179).
+char(0,38180).
+char(5,38181).
+char(c,38182).
+char(m,38183).
+char(o,38184).
+char(o,38185).
+char(p,38186).
+char(o,38187).
+char(o,38188).
+char(p,38189).
+char(2,38190).
+char(0,38191).
+char(0,38192).
+char(5,38193).
+char(c,38194).
+char(c,38195).
+char(c,38196).
+char(c,38197).
+char(m,38198).
+char(6,38199).
+char(4,38200).
+char(3,38201).
+char(6,38202).
+char(m,38203).
+char(o,38204).
+char(9,38205).
+char(4,38206).
+char(8,38207).
+char(9,38208).
+char(m,38209).
+char(1,38210).
+char(9,38211).
+char(8,38212).
+char(9,38213).
+char(p,38214).
+char(o,38215).
+char(m,38216).
+char(7,38217).
+char(3,38218).
+char(6,38219).
+char(7,38220).
+char(c,38221).
+char(p,38222).
+char(o,38223).
+char(6,38224).
+char(7,38225).
+char(9,38226).
+char(5,38227).
+char(c,38228).
+char(m,38229).
+char(2,38230).
+char(4,38231).
+char(0,38232).
+char(0,38233).
+char(c,38234).
+char(p,38235).
+char(8,38236).
+char(2,38237).
+char(6,38238).
+char(6,38239).
+char(p,38240).
+char(o,38241).
+char(m,38242).
+char(3,38243).
+char(9,38244).
+char(5,38245).
+char(6,38246).
+char(m,38247).
+char(o,38248).
+char(o,38249).
+char(m,38250).
+char(7,38251).
+char(4,38252).
+char(8,38253).
+char(9,38254).
+char(p,38255).
+char(4,38256).
+char(8,38257).
+char(8,38258).
+char(6,38259).
+char(c,38260).
+char(c,38261).
+char(m,38262).
+char(8,38263).
+char(5,38264).
+char(1,38265).
+char(m,38266).
+char(o,38267).
+char(o,38268).
+char(o,38269).
+char(m,38270).
+char(3,38271).
+char(2,38272).
+char(3,38273).
+char(2,38274).
+char(c,38275).
+char(m,38276).
+char(o,38277).
+char(p,38278).
+char(o,38279).
+char(o,38280).
+char(o,38281).
+char(o,38282).
+char(m,38283).
+char(4,38284).
+char(0,38285).
+char(3,38286).
+char(1,38287).
+char(c,38288).
+char(c,38289).
+char(c,38290).
+char(p,38291).
+char(7,38292).
+char(5,38293).
+char(4,38294).
+char(2,38295).
+char(p,38296).
+char(o,38297).
+char(m,38298).
+char(6,38299).
+char(4,38300).
+char(0,38301).
+char(8,38302).
+char(m,38303).
+char(1,38304).
+char(0,38305).
+char(p,38306).
+char(3,38307).
+char(6,38308).
+char(7,38309).
+char(1,38310).
+char(c,38311).
+char(c,38312).
+char(m,38313).
+char(o,38314).
+char(o,38315).
+char(1,38316).
+char(8,38317).
+char(1,38318).
+char(p,38319).
+char(o,38320).
+char(m,38321).
+char(7,38322).
+char(4,38323).
+char(9,38324).
+char(0,38325).
+char(c,38326).
+char(p,38327).
+char(o,38328).
+char(p,38329).
+char(5,38330).
+char(9,38331).
+char(4,38332).
+char(8,38333).
+char(c,38334).
+char(p,38335).
+char(o,38336).
+char(m,38337).
+char(o,38338).
+char(m,38339).
+char(4,38340).
+char(6,38341).
+char(4,38342).
+char(8,38343).
+char(m,38344).
+char(o,38345).
+char(m,38346).
+char(2,38347).
+char(3,38348).
+char(4,38349).
+char(9,38350).
+char(c,38351).
+char(c,38352).
+char(p,38353).
+char(o,38354).
+char(7,38355).
+char(7,38356).
+char(6,38357).
+char(9,38358).
+char(m,38359).
+char(o,38360).
+char(o,38361).
+char(p,38362).
+char(o,38363).
+char(4,38364).
+char(1,38365).
+char(9,38366).
+char(7,38367).
+char(p,38368).
+char(1,38369).
+char(8,38370).
+char(7,38371).
+char(8,38372).
+char(c,38373).
+char(m,38374).
+char(o,38375).
+char(p,38376).
+char(o,38377).
+char(o,38378).
+char(m,38379).
+char(o,38380).
+char(p,38381).
+char(o,38382).
+char(p,38383).
+char(2,38384).
+char(8,38385).
+char(6,38386).
+char(8,38387).
+char(c,38388).
+char(c,38389).
+char(m,38390).
+char(o,38391).
+char(m,38392).
+char(6,38393).
+char(8,38394).
+char(4,38395).
+char(1,38396).
+char(m,38397).
+char(2,38398).
+char(2,38399).
+char(3,38400).
+char(c,38401).
+char(c,38402).
+char(c,38403).
+char(m,38404).
+char(o,38405).
+char(p,38406).
+char(o,38407).
+char(m,38408).
+char(5,38409).
+char(0,38410).
+char(9,38411).
+char(2,38412).
+char(c,38413).
+char(m,38414).
+char(o,38415).
+char(6,38416).
+char(1,38417).
+char(4,38418).
+char(8,38419).
+char(c,38420).
+char(c,38421).
+char(c,38422).
+char(c,38423).
+char(m,38424).
+char(7,38425).
+char(2,38426).
+char(8,38427).
+char(1,38428).
+char(p,38429).
+char(7,38430).
+char(4,38431).
+char(3,38432).
+char(7,38433).
+char(c,38434).
+char(c,38435).
+char(c,38436).
+char(m,38437).
+char(7,38438).
+char(6,38439).
+char(7,38440).
+char(8,38441).
+char(p,38442).
+char(o,38443).
+char(4,38444).
+char(1,38445).
+char(7,38446).
+char(c,38447).
+char(c,38448).
+char(c,38449).
+char(c,38450).
+char(p,38451).
+char(o,38452).
+char(m,38453).
+char(o,38454).
+char(m,38455).
+char(o,38456).
+char(p,38457).
+char(o,38458).
+char(p,38459).
+char(4,38460).
+char(9,38461).
+char(4,38462).
+char(0,38463).
+char(m,38464).
+char(o,38465).
+char(4,38466).
+char(6,38467).
+char(0,38468).
+char(7,38469).
+char(m,38470).
+char(2,38471).
+char(4,38472).
+char(3,38473).
+char(8,38474).
+char(c,38475).
+char(p,38476).
+char(8,38477).
+char(0,38478).
+char(3,38479).
+char(5,38480).
+char(c,38481).
+char(m,38482).
+char(6,38483).
+char(3,38484).
+char(4,38485).
+char(8,38486).
+char(m,38487).
+char(o,38488).
+char(m,38489).
+char(o,38490).
+char(5,38491).
+char(3,38492).
+char(6,38493).
+char(1,38494).
+char(p,38495).
+char(7,38496).
+char(9,38497).
+char(6,38498).
+char(1,38499).
+char(m,38500).
+char(o,38501).
+char(o,38502).
+char(p,38503).
+char(1,38504).
+char(5,38505).
+char(1,38506).
+char(8,38507).
+char(c,38508).
+char(c,38509).
+char(c,38510).
+char(p,38511).
+char(o,38512).
+char(p,38513).
+char(6,38514).
+char(3,38515).
+char(1,38516).
+char(2,38517).
+char(c,38518).
+char(c,38519).
+char(p,38520).
+char(o,38521).
+char(1,38522).
+char(4,38523).
+char(4,38524).
+char(c,38525).
+char(m,38526).
+char(1,38527).
+char(6,38528).
+char(3,38529).
+char(9,38530).
+char(c,38531).
+char(m,38532).
+char(o,38533).
+char(p,38534).
+char(7,38535).
+char(7,38536).
+char(6,38537).
+char(1,38538).
+char(p,38539).
+char(o,38540).
+char(2,38541).
+char(6,38542).
+char(1,38543).
+char(2,38544).
+char(c,38545).
+char(c,38546).
+char(c,38547).
+char(p,38548).
+char(o,38549).
+char(m,38550).
+char(o,38551).
+char(m,38552).
+char(3,38553).
+char(3,38554).
+char(3,38555).
+char(3,38556).
+char(m,38557).
+char(2,38558).
+char(4,38559).
+char(8,38560).
+char(5,38561).
+char(p,38562).
+char(2,38563).
+char(1,38564).
+char(7,38565).
+char(9,38566).
+char(p,38567).
+char(6,38568).
+char(7,38569).
+char(2,38570).
+char(1,38571).
+char(c,38572).
+char(p,38573).
+char(o,38574).
+char(1,38575).
+char(8,38576).
+char(7,38577).
+char(7,38578).
+char(m,38579).
+char(o,38580).
+char(m,38581).
+char(o,38582).
+char(m,38583).
+char(5,38584).
+char(7,38585).
+char(0,38586).
+char(7,38587).
+char(p,38588).
+char(1,38589).
+char(1,38590).
+char(7,38591).
+char(7,38592).
+char(m,38593).
+char(2,38594).
+char(9,38595).
+char(1,38596).
+char(7,38597).
+char(p,38598).
+char(4,38599).
+char(1,38600).
+char(1,38601).
+char(2,38602).
+char(p,38603).
+char(5,38604).
+char(7,38605).
+char(3,38606).
+char(0,38607).
+char(m,38608).
+char(o,38609).
+char(m,38610).
+char(2,38611).
+char(9,38612).
+char(9,38613).
+char(6,38614).
+char(p,38615).
+char(o,38616).
+char(m,38617).
+char(o,38618).
+char(m,38619).
+char(8,38620).
+char(1,38621).
+char(7,38622).
+char(8,38623).
+char(m,38624).
+char(1,38625).
+char(4,38626).
+char(3,38627).
+char(2,38628).
+char(c,38629).
+char(p,38630).
+char(o,38631).
+char(m,38632).
+char(8,38633).
+char(4,38634).
+char(6,38635).
+char(c,38636).
+char(m,38637).
+char(o,38638).
+char(o,38639).
+char(p,38640).
+char(5,38641).
+char(0,38642).
+char(8,38643).
+char(9,38644).
+char(c,38645).
+char(c,38646).
+char(p,38647).
+char(7,38648).
+char(1,38649).
+char(4,38650).
+char(2,38651).
+char(p,38652).
+char(o,38653).
+char(m,38654).
+char(o,38655).
+char(m,38656).
+char(o,38657).
+char(1,38658).
+char(1,38659).
+char(3,38660).
+char(8,38661).
+char(c,38662).
+char(c,38663).
+char(m,38664).
+char(9,38665).
+char(8,38666).
+char(5,38667).
+char(6,38668).
+char(c,38669).
+char(c,38670).
+char(m,38671).
+char(o,38672).
+char(m,38673).
+char(2,38674).
+char(1,38675).
+char(0,38676).
+char(4,38677).
+char(m,38678).
+char(o,38679).
+char(m,38680).
+char(o,38681).
+char(o,38682).
+char(o,38683).
+char(p,38684).
+char(7,38685).
+char(2,38686).
+char(2,38687).
+char(4,38688).
+char(c,38689).
+char(c,38690).
+char(m,38691).
+char(2,38692).
+char(3,38693).
+char(8,38694).
+char(2,38695).
+char(c,38696).
+char(c,38697).
+char(p,38698).
+char(5,38699).
+char(3,38700).
+char(1,38701).
+char(7,38702).
+char(c,38703).
+char(c,38704).
+char(c,38705).
+char(c,38706).
+char(m,38707).
+char(o,38708).
+char(m,38709).
+char(2,38710).
+char(8,38711).
+char(8,38712).
+char(2,38713).
+char(c,38714).
+char(c,38715).
+char(c,38716).
+char(p,38717).
+char(o,38718).
+char(m,38719).
+char(o,38720).
+char(o,38721).
+char(m,38722).
+char(2,38723).
+char(7,38724).
+char(9,38725).
+char(4,38726).
+char(c,38727).
+char(p,38728).
+char(2,38729).
+char(6,38730).
+char(9,38731).
+char(8,38732).
+char(m,38733).
+char(o,38734).
+char(p,38735).
+char(2,38736).
+char(3,38737).
+char(5,38738).
+char(8,38739).
+char(c,38740).
+char(p,38741).
+char(o,38742).
+char(m,38743).
+char(6,38744).
+char(0,38745).
+char(9,38746).
+char(1,38747).
+char(c,38748).
+char(p,38749).
+char(6,38750).
+char(3,38751).
+char(0,38752).
+char(5,38753).
+char(c,38754).
+char(c,38755).
+char(c,38756).
+char(p,38757).
+char(5,38758).
+char(5,38759).
+char(0,38760).
+char(6,38761).
+char(p,38762).
+char(o,38763).
+char(p,38764).
+char(o,38765).
+char(p,38766).
+char(7,38767).
+char(2,38768).
+char(5,38769).
+char(p,38770).
+char(o,38771).
+char(m,38772).
+char(o,38773).
+char(p,38774).
+char(o,38775).
+char(m,38776).
+char(3,38777).
+char(3,38778).
+char(0,38779).
+char(4,38780).
+char(m,38781).
+char(o,38782).
+char(m,38783).
+char(5,38784).
+char(6,38785).
+char(5,38786).
+char(4,38787).
+char(p,38788).
+char(8,38789).
+char(4,38790).
+char(5,38791).
+char(7,38792).
+char(m,38793).
+char(9,38794).
+char(8,38795).
+char(5,38796).
+char(2,38797).
+char(m,38798).
+char(o,38799).
+char(p,38800).
+char(o,38801).
+char(p,38802).
+char(o,38803).
+char(o,38804).
+char(p,38805).
+char(5,38806).
+char(5,38807).
+char(5,38808).
+char(4,38809).
+char(p,38810).
+char(4,38811).
+char(6,38812).
+char(0,38813).
+char(5,38814).
+char(p,38815).
+char(o,38816).
+char(o,38817).
+char(p,38818).
+char(3,38819).
+char(0,38820).
+char(4,38821).
+char(6,38822).
+char(c,38823).
+char(m,38824).
+char(9,38825).
+char(3,38826).
+char(4,38827).
+char(3,38828).
+char(m,38829).
+char(5,38830).
+char(2,38831).
+char(3,38832).
+char(3,38833).
+char(c,38834).
+char(p,38835).
+char(o,38836).
+char(m,38837).
+char(o,38838).
+char(6,38839).
+char(8,38840).
+char(3,38841).
+char(1,38842).
+char(m,38843).
+char(7,38844).
+char(8,38845).
+char(3,38846).
+char(7,38847).
+char(p,38848).
+char(o,38849).
+char(m,38850).
+char(o,38851).
+char(2,38852).
+char(8,38853).
+char(4,38854).
+char(0,38855).
+char(p,38856).
+char(1,38857).
+char(7,38858).
+char(5,38859).
+char(8,38860).
+char(m,38861).
+char(7,38862).
+char(3,38863).
+char(6,38864).
+char(m,38865).
+char(3,38866).
+char(9,38867).
+char(8,38868).
+char(4,38869).
+char(c,38870).
+char(p,38871).
+char(o,38872).
+char(p,38873).
+char(o,38874).
+char(p,38875).
+char(o,38876).
+char(o,38877).
+char(3,38878).
+char(6,38879).
+char(9,38880).
+char(7,38881).
+char(c,38882).
+char(m,38883).
+char(1,38884).
+char(5,38885).
+char(4,38886).
+char(5,38887).
+char(c,38888).
+char(m,38889).
+char(4,38890).
+char(3,38891).
+char(c,38892).
+char(m,38893).
+char(o,38894).
+char(m,38895).
+char(6,38896).
+char(4,38897).
+char(0,38898).
+char(7,38899).
+char(p,38900).
+char(5,38901).
+char(0,38902).
+char(0,38903).
+char(6,38904).
+char(p,38905).
+char(2,38906).
+char(8,38907).
+char(8,38908).
+char(5,38909).
+char(c,38910).
+char(c,38911).
+char(c,38912).
+char(p,38913).
+char(1,38914).
+char(2,38915).
+char(2,38916).
+char(c,38917).
+char(c,38918).
+char(p,38919).
+char(9,38920).
+char(9,38921).
+char(5,38922).
+char(p,38923).
+char(o,38924).
+char(p,38925).
+char(o,38926).
+char(m,38927).
+char(1,38928).
+char(7,38929).
+char(3,38930).
+char(m,38931).
+char(2,38932).
+char(2,38933).
+char(4,38934).
+char(7,38935).
+char(m,38936).
+char(5,38937).
+char(6,38938).
+char(0,38939).
+char(5,38940).
+char(c,38941).
+char(c,38942).
+char(m,38943).
+char(2,38944).
+char(1,38945).
+char(6,38946).
+char(4,38947).
+char(m,38948).
+char(o,38949).
+char(p,38950).
+char(6,38951).
+char(0,38952).
+char(4,38953).
+char(3,38954).
+char(p,38955).
+char(o,38956).
+char(p,38957).
+char(1,38958).
+char(0,38959).
+char(2,38960).
+char(2,38961).
+char(m,38962).
+char(o,38963).
+char(m,38964).
+char(7,38965).
+char(8,38966).
+char(5,38967).
+char(7,38968).
+char(m,38969).
+char(4,38970).
+char(6,38971).
+char(0,38972).
+char(8,38973).
+char(m,38974).
+char(9,38975).
+char(1,38976).
+char(2,38977).
+char(1,38978).
+char(c,38979).
+char(c,38980).
+char(p,38981).
+char(5,38982).
+char(3,38983).
+char(1,38984).
+char(2,38985).
+char(c,38986).
+char(m,38987).
+char(o,38988).
+char(p,38989).
+char(o,38990).
+char(o,38991).
+char(o,38992).
+char(9,38993).
+char(1,38994).
+char(1,38995).
+char(2,38996).
+char(c,38997).
+char(c,38998).
+char(c,38999).
+char(c,39000).
+char(m,39001).
+char(o,39002).
+char(o,39003).
+char(p,39004).
+char(2,39005).
+char(6,39006).
+char(4,39007).
+char(3,39008).
+char(c,39009).
+char(c,39010).
+char(c,39011).
+char(c,39012).
+char(p,39013).
+char(o,39014).
+char(p,39015).
+char(o,39016).
+char(p,39017).
+char(4,39018).
+char(6,39019).
+char(1,39020).
+char(8,39021).
+char(c,39022).
+char(c,39023).
+char(p,39024).
+char(1,39025).
+char(4,39026).
+char(0,39027).
+char(6,39028).
+char(c,39029).
+char(c,39030).
+char(c,39031).
+char(m,39032).
+char(2,39033).
+char(7,39034).
+char(9,39035).
+char(3,39036).
+char(c,39037).
+char(p,39038).
+char(9,39039).
+char(9,39040).
+char(6,39041).
+char(0,39042).
+char(c,39043).
+char(m,39044).
+char(4,39045).
+char(5,39046).
+char(8,39047).
+char(8,39048).
+char(p,39049).
+char(o,39050).
+char(o,39051).
+char(p,39052).
+char(o,39053).
+char(m,39054).
+char(9,39055).
+char(8,39056).
+char(7,39057).
+char(6,39058).
+char(m,39059).
+char(o,39060).
+char(p,39061).
+char(8,39062).
+char(5,39063).
+char(6,39064).
+char(8,39065).
+char(c,39066).
+char(c,39067).
+char(c,39068).
+char(m,39069).
+char(9,39070).
+char(3,39071).
+char(7,39072).
+char(2,39073).
+char(m,39074).
+char(4,39075).
+char(7,39076).
+char(9,39077).
+char(4,39078).
+char(c,39079).
+char(m,39080).
+char(o,39081).
+char(m,39082).
+char(8,39083).
+char(3,39084).
+char(4,39085).
+char(0,39086).
+char(p,39087).
+char(8,39088).
+char(2,39089).
+char(2,39090).
+char(7,39091).
+char(m,39092).
+char(1,39093).
+char(3,39094).
+char(1,39095).
+char(3,39096).
+char(c,39097).
+char(c,39098).
+char(m,39099).
+char(o,39100).
+char(m,39101).
+char(o,39102).
+char(p,39103).
+char(2,39104).
+char(7,39105).
+char(9,39106).
+char(6,39107).
+char(m,39108).
+char(o,39109).
+char(m,39110).
+char(o,39111).
+char(p,39112).
+char(o,39113).
+char(m,39114).
+char(o,39115).
+char(p,39116).
+char(5,39117).
+char(1,39118).
+char(8,39119).
+char(p,39120).
+char(7,39121).
+char(3,39122).
+char(7,39123).
+char(3,39124).
+char(c,39125).
+char(m,39126).
+char(o,39127).
+char(p,39128).
+char(o,39129).
+char(m,39130).
+char(4,39131).
+char(8,39132).
+char(5,39133).
+char(9,39134).
+char(m,39135).
+char(3,39136).
+char(8,39137).
+char(7,39138).
+char(p,39139).
+char(o,39140).
+char(m,39141).
+char(9,39142).
+char(0,39143).
+char(3,39144).
+char(9,39145).
+char(p,39146).
+char(o,39147).
+char(m,39148).
+char(9,39149).
+char(3,39150).
+char(5,39151).
+char(3,39152).
+char(m,39153).
+char(o,39154).
+char(o,39155).
+char(p,39156).
+char(o,39157).
+char(p,39158).
+char(7,39159).
+char(4,39160).
+char(5,39161).
+char(4,39162).
+char(c,39163).
+char(c,39164).
+char(c,39165).
+char(c,39166).
+char(m,39167).
+char(o,39168).
+char(m,39169).
+char(o,39170).
+char(4,39171).
+char(5,39172).
+char(0,39173).
+char(8,39174).
+char(m,39175).
+char(o,39176).
+char(o,39177).
+char(p,39178).
+char(2,39179).
+char(9,39180).
+char(1,39181).
+char(2,39182).
+char(c,39183).
+char(c,39184).
+char(m,39185).
+char(o,39186).
+char(p,39187).
+char(6,39188).
+char(5,39189).
+char(9,39190).
+char(4,39191).
+char(c,39192).
+char(c,39193).
+char(m,39194).
+char(3,39195).
+char(8,39196).
+char(3,39197).
+char(1,39198).
+char(m,39199).
+char(1,39200).
+char(5,39201).
+char(8,39202).
+char(2,39203).
+char(c,39204).
+char(p,39205).
+char(9,39206).
+char(5,39207).
+char(9,39208).
+char(c,39209).
+char(c,39210).
+char(m,39211).
+char(o,39212).
+char(p,39213).
+char(o,39214).
+char(p,39215).
+char(9,39216).
+char(2,39217).
+char(2,39218).
+char(6,39219).
+char(c,39220).
+char(m,39221).
+char(o,39222).
+char(4,39223).
+char(1,39224).
+char(5,39225).
+char(0,39226).
+char(p,39227).
+char(4,39228).
+char(8,39229).
+char(4,39230).
+char(7,39231).
+char(c,39232).
+char(p,39233).
+char(9,39234).
+char(9,39235).
+char(4,39236).
+char(4,39237).
+char(m,39238).
+char(o,39239).
+char(m,39240).
+char(2,39241).
+char(0,39242).
+char(7,39243).
+char(p,39244).
+char(4,39245).
+char(6,39246).
+char(5,39247).
+char(2,39248).
+char(m,39249).
+char(o,39250).
+char(p,39251).
+char(8,39252).
+char(3,39253).
+char(9,39254).
+char(0,39255).
+char(p,39256).
+char(o,39257).
+char(p,39258).
+char(o,39259).
+char(m,39260).
+char(3,39261).
+char(8,39262).
+char(9,39263).
+char(7,39264).
+char(p,39265).
+char(o,39266).
+char(p,39267).
+char(8,39268).
+char(7,39269).
+char(1,39270).
+char(5,39271).
+char(p,39272).
+char(6,39273).
+char(9,39274).
+char(5,39275).
+char(6,39276).
+char(c,39277).
+char(c,39278).
+char(c,39279).
+char(c,39280).
+char(p,39281).
+char(6,39282).
+char(4,39283).
+char(4,39284).
+char(1,39285).
+char(c,39286).
+char(p,39287).
+char(5,39288).
+char(2,39289).
+char(0,39290).
+char(2,39291).
+char(c,39292).
+char(p,39293).
+char(6,39294).
+char(5,39295).
+char(6,39296).
+char(1,39297).
+char(c,39298).
+char(p,39299).
+char(3,39300).
+char(7,39301).
+char(7,39302).
+char(6,39303).
+char(c,39304).
+char(m,39305).
+char(8,39306).
+char(3,39307).
+char(0,39308).
+char(5,39309).
+char(m,39310).
+char(o,39311).
+char(p,39312).
+char(o,39313).
+char(m,39314).
+char(o,39315).
+char(9,39316).
+char(8,39317).
+char(9,39318).
+char(6,39319).
+char(c,39320).
+char(c,39321).
+char(m,39322).
+char(8,39323).
+char(9,39324).
+char(0,39325).
+char(c,39326).
+char(p,39327).
+char(o,39328).
+char(m,39329).
+char(3,39330).
+char(5,39331).
+char(0,39332).
+char(c,39333).
+char(c,39334).
+char(m,39335).
+char(2,39336).
+char(1,39337).
+char(5,39338).
+char(9,39339).
+char(m,39340).
+char(9,39341).
+char(9,39342).
+char(1,39343).
+char(9,39344).
+char(c,39345).
+char(p,39346).
+char(o,39347).
+char(p,39348).
+char(o,39349).
+char(6,39350).
+char(5,39351).
+char(8,39352).
+char(2,39353).
+char(c,39354).
+char(c,39355).
+char(c,39356).
+char(p,39357).
+char(3,39358).
+char(6,39359).
+char(4,39360).
+char(c,39361).
+char(c,39362).
+char(m,39363).
+char(7,39364).
+char(6,39365).
+char(9,39366).
+char(2,39367).
+char(c,39368).
+char(m,39369).
+char(4,39370).
+char(7,39371).
+char(3,39372).
+char(0,39373).
+char(p,39374).
+char(1,39375).
+char(1,39376).
+char(6,39377).
+char(8,39378).
+char(m,39379).
+char(5,39380).
+char(7,39381).
+char(9,39382).
+char(9,39383).
+char(p,39384).
+char(2,39385).
+char(8,39386).
+char(0,39387).
+char(6,39388).
+char(p,39389).
+char(o,39390).
+char(m,39391).
+char(o,39392).
+char(m,39393).
+char(o,39394).
+char(p,39395).
+char(2,39396).
+char(7,39397).
+char(2,39398).
+char(c,39399).
+char(m,39400).
+char(2,39401).
+char(6,39402).
+char(5,39403).
+char(6,39404).
+char(c,39405).
+char(m,39406).
+char(4,39407).
+char(0,39408).
+char(3,39409).
+char(8,39410).
+char(c,39411).
+char(p,39412).
+char(3,39413).
+char(8,39414).
+char(0,39415).
+char(3,39416).
+char(m,39417).
+char(4,39418).
+char(5,39419).
+char(9,39420).
+char(1,39421).
+char(c,39422).
+char(c,39423).
+char(m,39424).
+char(o,39425).
+char(m,39426).
+char(o,39427).
+char(o,39428).
+char(p,39429).
+char(1,39430).
+char(8,39431).
+char(0,39432).
+char(2,39433).
+char(c,39434).
+char(m,39435).
+char(2,39436).
+char(1,39437).
+char(6,39438).
+char(9,39439).
+char(c,39440).
+char(m,39441).
+char(6,39442).
+char(8,39443).
+char(2,39444).
+char(7,39445).
+char(c,39446).
+char(c,39447).
+char(p,39448).
+char(1,39449).
+char(5,39450).
+char(5,39451).
+char(6,39452).
+char(c,39453).
+char(c,39454).
+char(c,39455).
+char(p,39456).
+char(o,39457).
+char(p,39458).
+char(3,39459).
+char(9,39460).
+char(7,39461).
+char(0,39462).
+char(c,39463).
+char(p,39464).
+char(4,39465).
+char(8,39466).
+char(0,39467).
+char(2,39468).
+char(p,39469).
+char(5,39470).
+char(7,39471).
+char(7,39472).
+char(3,39473).
+char(c,39474).
+char(c,39475).
+char(c,39476).
+char(m,39477).
+char(1,39478).
+char(7,39479).
+char(7,39480).
+char(7,39481).
+char(c,39482).
+char(m,39483).
+char(o,39484).
+char(4,39485).
+char(0,39486).
+char(4,39487).
+char(6,39488).
+char(p,39489).
+char(6,39490).
+char(6,39491).
+char(0,39492).
+char(4,39493).
+char(c,39494).
+char(c,39495).
+char(c,39496).
+char(m,39497).
+char(7,39498).
+char(5,39499).
+char(3,39500).
+char(1,39501).
+char(c,39502).
+char(m,39503).
+char(o,39504).
+char(m,39505).
+char(o,39506).
+char(p,39507).
+char(6,39508).
+char(7,39509).
+char(0,39510).
+char(4,39511).
+char(c,39512).
+char(p,39513).
+char(o,39514).
+char(o,39515).
+char(o,39516).
+char(m,39517).
+char(7,39518).
+char(6,39519).
+char(2,39520).
+char(9,39521).
+char(c,39522).
+char(c,39523).
+char(p,39524).
+char(3,39525).
+char(5,39526).
+char(4,39527).
+char(3,39528).
+char(c,39529).
+char(m,39530).
+char(o,39531).
+char(o,39532).
+char(m,39533).
+char(o,39534).
+char(m,39535).
+char(8,39536).
+char(6,39537).
+char(3,39538).
+char(2,39539).
+char(m,39540).
+char(7,39541).
+char(5,39542).
+char(8,39543).
+char(6,39544).
+char(m,39545).
+char(o,39546).
+char(p,39547).
+char(o,39548).
+char(p,39549).
+char(5,39550).
+char(5,39551).
+char(7,39552).
+char(1,39553).
+char(m,39554).
+char(o,39555).
+char(p,39556).
+char(o,39557).
+char(p,39558).
+char(o,39559).
+char(m,39560).
+char(1,39561).
+char(2,39562).
+char(8,39563).
+char(0,39564).
+char(m,39565).
+char(2,39566).
+char(0,39567).
+char(4,39568).
+char(3,39569).
+char(m,39570).
+char(9,39571).
+char(5,39572).
+char(3,39573).
+char(8,39574).
+char(c,39575).
+char(m,39576).
+char(6,39577).
+char(3,39578).
+char(7,39579).
+char(3,39580).
+char(m,39581).
+char(6,39582).
+char(1,39583).
+char(9,39584).
+char(m,39585).
+char(o,39586).
+char(o,39587).
+char(p,39588).
+char(4,39589).
+char(7,39590).
+char(1,39591).
+char(4,39592).
+char(m,39593).
+char(4,39594).
+char(6,39595).
+char(9,39596).
+char(7,39597).
+char(c,39598).
+char(p,39599).
+char(1,39600).
+char(6,39601).
+char(8,39602).
+char(9,39603).
+char(p,39604).
+char(4,39605).
+char(2,39606).
+char(7,39607).
+char(3,39608).
+char(m,39609).
+char(o,39610).
+char(p,39611).
+char(1,39612).
+char(5,39613).
+char(6,39614).
+char(9,39615).
+char(c,39616).
+char(p,39617).
+char(o,39618).
+char(m,39619).
+char(o,39620).
+char(m,39621).
+char(o,39622).
+char(o,39623).
+char(m,39624).
+char(o,39625).
+char(1,39626).
+char(4,39627).
+char(5,39628).
+char(4,39629).
+char(p,39630).
+char(o,39631).
+char(m,39632).
+char(o,39633).
+char(p,39634).
+char(o,39635).
+char(p,39636).
+char(5,39637).
+char(6,39638).
+char(7,39639).
+char(2,39640).
+char(c,39641).
+char(m,39642).
+char(7,39643).
+char(9,39644).
+char(7,39645).
+char(9,39646).
+char(c,39647).
+char(m,39648).
+char(4,39649).
+char(0,39650).
+char(4,39651).
+char(7,39652).
+char(c,39653).
+char(c,39654).
+char(c,39655).
+char(m,39656).
+char(o,39657).
+char(o,39658).
+char(7,39659).
+char(5,39660).
+char(1,39661).
+char(8,39662).
+char(c,39663).
+char(c,39664).
+char(c,39665).
+char(p,39666).
+char(o,39667).
+char(m,39668).
+char(o,39669).
+char(m,39670).
+char(9,39671).
+char(9,39672).
+char(7,39673).
+char(3,39674).
+char(m,39675).
+char(7,39676).
+char(2,39677).
+char(4,39678).
+char(4,39679).
+char(p,39680).
+char(3,39681).
+char(3,39682).
+char(6,39683).
+char(0,39684).
+char(c,39685).
+char(c,39686).
+char(c,39687).
+char(c,39688).
+char(c,39689).
+char(c,39690).
+char(m,39691).
+char(o,39692).
+char(m,39693).
+char(o,39694).
+char(p,39695).
+char(2,39696).
+char(1,39697).
+char(6,39698).
+char(1,39699).
+char(c,39700).
+char(m,39701).
+char(o,39702).
+char(3,39703).
+char(8,39704).
+char(8,39705).
+char(9,39706).
+char(p,39707).
+char(3,39708).
+char(1,39709).
+char(3,39710).
+char(0,39711).
+char(c,39712).
+char(p,39713).
+char(5,39714).
+char(1,39715).
+char(0,39716).
+char(9,39717).
+char(p,39718).
+char(6,39719).
+char(2,39720).
+char(7,39721).
+char(6,39722).
+char(c,39723).
+char(c,39724).
+char(p,39725).
+char(o,39726).
+char(m,39727).
+char(o,39728).
+char(o,39729).
+char(8,39730).
+char(2,39731).
+char(6,39732).
+char(2,39733).
+char(c,39734).
+char(p,39735).
+char(5,39736).
+char(6,39737).
+char(5,39738).
+char(7,39739).
+char(c,39740).
+char(c,39741).
+char(p,39742).
+char(o,39743).
+char(o,39744).
+char(m,39745).
+char(o,39746).
+char(m,39747).
+char(5,39748).
+char(5,39749).
+char(7,39750).
+char(2,39751).
+char(p,39752).
+char(o,39753).
+char(o,39754).
+char(7,39755).
+char(5,39756).
+char(2,39757).
+char(4,39758).
+char(c,39759).
+char(p,39760).
+char(7,39761).
+char(9,39762).
+char(4,39763).
+char(5,39764).
+char(c,39765).
+char(c,39766).
+char(m,39767).
+char(2,39768).
+char(3,39769).
+char(8,39770).
+char(8,39771).
+char(p,39772).
+char(7,39773).
+char(1,39774).
+char(9,39775).
+char(2,39776).
+char(m,39777).
+char(2,39778).
+char(2,39779).
+char(2,39780).
+char(0,39781).
+char(c,39782).
+char(c,39783).
+char(c,39784).
+char(p,39785).
+char(5,39786).
+char(8,39787).
+char(4,39788).
+char(7,39789).
+char(m,39790).
+char(6,39791).
+char(3,39792).
+char(7,39793).
+char(p,39794).
+char(o,39795).
+char(o,39796).
+char(8,39797).
+char(5,39798).
+char(3,39799).
+char(0,39800).
+char(c,39801).
+char(c,39802).
+char(p,39803).
+char(5,39804).
+char(1,39805).
+char(4,39806).
+char(2,39807).
+char(c,39808).
+char(c,39809).
+char(c,39810).
+char(c,39811).
+char(c,39812).
+char(p,39813).
+char(o,39814).
+char(o,39815).
+char(m,39816).
+char(9,39817).
+char(4,39818).
+char(2,39819).
+char(8,39820).
+char(c,39821).
+char(c,39822).
+char(m,39823).
+char(o,39824).
+char(p,39825).
+char(9,39826).
+char(6,39827).
+char(4,39828).
+char(7,39829).
+char(p,39830).
+char(o,39831).
+char(p,39832).
+char(9,39833).
+char(0,39834).
+char(7,39835).
+char(3,39836).
+char(m,39837).
+char(6,39838).
+char(8,39839).
+char(9,39840).
+char(c,39841).
+char(c,39842).
+char(p,39843).
+char(3,39844).
+char(6,39845).
+char(1,39846).
+char(2,39847).
+char(m,39848).
+char(3,39849).
+char(0,39850).
+char(5,39851).
+char(4,39852).
+char(m,39853).
+char(8,39854).
+char(1,39855).
+char(6,39856).
+char(7,39857).
+char(p,39858).
+char(1,39859).
+char(5,39860).
+char(5,39861).
+char(0,39862).
+char(c,39863).
+char(m,39864).
+char(5,39865).
+char(0,39866).
+char(3,39867).
+char(4,39868).
+char(p,39869).
+char(1,39870).
+char(0,39871).
+char(1,39872).
+char(1,39873).
+char(m,39874).
+char(9,39875).
+char(7,39876).
+char(0,39877).
+char(3,39878).
+char(m,39879).
+char(o,39880).
+char(p,39881).
+char(8,39882).
+char(4,39883).
+char(4,39884).
+char(4,39885).
+char(p,39886).
+char(o,39887).
+char(m,39888).
+char(o,39889).
+char(m,39890).
+char(o,39891).
+char(m,39892).
+char(o,39893).
+char(o,39894).
+char(o,39895).
+char(p,39896).
+char(9,39897).
+char(0,39898).
+char(1,39899).
+char(9,39900).
+char(c,39901).
+char(m,39902).
+char(5,39903).
+char(0,39904).
+char(7,39905).
+char(1,39906).
+char(m,39907).
+char(1,39908).
+char(7,39909).
+char(7,39910).
+char(8,39911).
+char(p,39912).
+char(o,39913).
+char(o,39914).
+char(m,39915).
+char(o,39916).
+char(8,39917).
+char(7,39918).
+char(6,39919).
+char(0,39920).
+char(p,39921).
+char(2,39922).
+char(4,39923).
+char(2,39924).
+char(2,39925).
+char(p,39926).
+char(o,39927).
+char(3,39928).
+char(4,39929).
+char(2,39930).
+char(0,39931).
+char(p,39932).
+char(o,39933).
+char(9,39934).
+char(4,39935).
+char(3,39936).
+char(8,39937).
+char(p,39938).
+char(2,39939).
+char(6,39940).
+char(0,39941).
+char(4,39942).
+char(m,39943).
+char(o,39944).
+char(m,39945).
+char(o,39946).
+char(2,39947).
+char(5,39948).
+char(2,39949).
+char(8,39950).
+char(c,39951).
+char(m,39952).
+char(o,39953).
+char(p,39954).
+char(8,39955).
+char(5,39956).
+char(1,39957).
+char(4,39958).
+char(c,39959).
+char(c,39960).
+char(c,39961).
+char(m,39962).
+char(8,39963).
+char(6,39964).
+char(0,39965).
+char(8,39966).
+char(p,39967).
+char(8,39968).
+char(7,39969).
+char(4,39970).
+char(4,39971).
+char(p,39972).
+char(o,39973).
+char(p,39974).
+char(6,39975).
+char(0,39976).
+char(7,39977).
+char(2,39978).
+char(m,39979).
+char(8,39980).
+char(8,39981).
+char(6,39982).
+char(p,39983).
+char(o,39984).
+char(m,39985).
+char(o,39986).
+char(6,39987).
+char(5,39988).
+char(3,39989).
+char(8,39990).
+char(c,39991).
+char(c,39992).
+char(p,39993).
+char(o,39994).
+char(p,39995).
+char(o,39996).
+char(m,39997).
+char(8,39998).
+char(0,39999).
+char(1,40000).
+char(0,40001).
+char(c,40002).
+char(m,40003).
+char(o,40004).
+char(2,40005).
+char(8,40006).
+char(5,40007).
+char(6,40008).
+char(c,40009).
+char(c,40010).
+char(c,40011).
+char(m,40012).
+char(5,40013).
+char(8,40014).
+char(1,40015).
+char(8,40016).
+char(p,40017).
+char(5,40018).
+char(6,40019).
+char(7,40020).
+char(5,40021).
+char(c,40022).
+char(p,40023).
+char(7,40024).
+char(6,40025).
+char(6,40026).
+char(5,40027).
+char(m,40028).
+char(o,40029).
+char(o,40030).
+char(o,40031).
+char(p,40032).
+char(7,40033).
+char(9,40034).
+char(6,40035).
+char(8,40036).
+char(c,40037).
+char(c,40038).
+char(c,40039).
+char(c,40040).
+char(c,40041).
+char(c,40042).
+char(c,40043).
+char(c,40044).
+char(c,40045).
+char(p,40046).
+char(3,40047).
+char(6,40048).
+char(5,40049).
+char(7,40050).
+char(p,40051).
+char(o,40052).
+char(p,40053).
+char(7,40054).
+char(6,40055).
+char(5,40056).
+char(6,40057).
+char(c,40058).
+char(c,40059).
+char(c,40060).
+char(c,40061).
+char(c,40062).
+char(c,40063).
+char(p,40064).
+char(4,40065).
+char(7,40066).
+char(1,40067).
+char(0,40068).
+char(m,40069).
+char(7,40070).
+char(9,40071).
+char(9,40072).
+char(3,40073).
+char(c,40074).
+char(c,40075).
+char(c,40076).
+char(p,40077).
+char(8,40078).
+char(4,40079).
+char(5,40080).
+char(8,40081).
+char(p,40082).
+char(4,40083).
+char(0,40084).
+char(4,40085).
+char(6,40086).
+char(p,40087).
+char(8,40088).
+char(9,40089).
+char(6,40090).
+char(c,40091).
+char(c,40092).
+char(p,40093).
+char(o,40094).
+char(p,40095).
+char(o,40096).
+char(m,40097).
+char(o,40098).
+char(5,40099).
+char(5,40100).
+char(6,40101).
+char(7,40102).
+char(p,40103).
+char(o,40104).
+char(m,40105).
+char(5,40106).
+char(1,40107).
+char(6,40108).
+char(0,40109).
+char(p,40110).
+char(o,40111).
+char(m,40112).
+char(o,40113).
+char(m,40114).
+char(o,40115).
+char(m,40116).
+char(o,40117).
+char(m,40118).
+char(4,40119).
+char(8,40120).
+char(6,40121).
+char(3,40122).
+char(p,40123).
+char(o,40124).
+char(m,40125).
+char(5,40126).
+char(5,40127).
+char(5,40128).
+char(4,40129).
+char(p,40130).
+char(o,40131).
+char(p,40132).
+char(o,40133).
+char(m,40134).
+char(o,40135).
+char(p,40136).
+char(5,40137).
+char(7,40138).
+char(2,40139).
+char(4,40140).
+char(c,40141).
+char(c,40142).
+char(m,40143).
+char(9,40144).
+char(0,40145).
+char(6,40146).
+char(9,40147).
+char(c,40148).
+char(m,40149).
+char(8,40150).
+char(2,40151).
+char(8,40152).
+char(0,40153).
+char(c,40154).
+char(p,40155).
+char(o,40156).
+char(p,40157).
+char(4,40158).
+char(4,40159).
+char(5,40160).
+char(1,40161).
+char(c,40162).
+char(m,40163).
+char(8,40164).
+char(7,40165).
+char(0,40166).
+char(0,40167).
+char(c,40168).
+char(c,40169).
+char(c,40170).
+char(m,40171).
+char(7,40172).
+char(2,40173).
+char(0,40174).
+char(9,40175).
+char(p,40176).
+char(9,40177).
+char(1,40178).
+char(0,40179).
+char(7,40180).
+char(c,40181).
+char(c,40182).
+char(p,40183).
+char(o,40184).
+char(o,40185).
+char(p,40186).
+char(o,40187).
+char(o,40188).
+char(p,40189).
+char(o,40190).
+char(p,40191).
+char(o,40192).
+char(5,40193).
+char(1,40194).
+char(2,40195).
+char(0,40196).
+char(c,40197).
+char(p,40198).
+char(5,40199).
+char(6,40200).
+char(2,40201).
+char(4,40202).
+char(m,40203).
+char(4,40204).
+char(3,40205).
+char(1,40206).
+char(5,40207).
+char(c,40208).
+char(m,40209).
+char(o,40210).
+char(8,40211).
+char(9,40212).
+char(3,40213).
+char(4,40214).
+char(c,40215).
+char(c,40216).
+char(p,40217).
+char(2,40218).
+char(0,40219).
+char(3,40220).
+char(2,40221).
+char(m,40222).
+char(o,40223).
+char(p,40224).
+char(4,40225).
+char(3,40226).
+char(8,40227).
+char(1,40228).
+char(c,40229).
+char(c,40230).
+char(p,40231).
+char(o,40232).
+char(m,40233).
+char(4,40234).
+char(4,40235).
+char(6,40236).
+char(0,40237).
+char(c,40238).
+char(m,40239).
+char(9,40240).
+char(9,40241).
+char(0,40242).
+char(0,40243).
+char(p,40244).
+char(o,40245).
+char(p,40246).
+char(o,40247).
+char(m,40248).
+char(2,40249).
+char(7,40250).
+char(8,40251).
+char(1,40252).
+char(p,40253).
+char(o,40254).
+char(o,40255).
+char(p,40256).
+char(o,40257).
+char(m,40258).
+char(4,40259).
+char(6,40260).
+char(6,40261).
+char(8,40262).
+char(m,40263).
+char(o,40264).
+char(m,40265).
+char(o,40266).
+char(4,40267).
+char(0,40268).
+char(1,40269).
+char(1,40270).
+char(c,40271).
+char(c,40272).
+char(p,40273).
+char(7,40274).
+char(7,40275).
+char(0,40276).
+char(1,40277).
+char(c,40278).
+char(p,40279).
+char(6,40280).
+char(3,40281).
+char(5,40282).
+char(5,40283).
+char(m,40284).
+char(2,40285).
+char(5,40286).
+char(6,40287).
+char(6,40288).
+char(m,40289).
+char(2,40290).
+char(0,40291).
+char(0,40292).
+char(1,40293).
+char(c,40294).
+char(c,40295).
+char(m,40296).
+char(4,40297).
+char(1,40298).
+char(4,40299).
+char(7,40300).
+char(p,40301).
+char(9,40302).
+char(9,40303).
+char(8,40304).
+char(8,40305).
+char(p,40306).
+char(o,40307).
+char(o,40308).
+char(m,40309).
+char(4,40310).
+char(2,40311).
+char(8,40312).
+char(8,40313).
+char(m,40314).
+char(9,40315).
+char(9,40316).
+char(7,40317).
+char(6,40318).
+char(p,40319).
+char(o,40320).
+char(o,40321).
+char(m,40322).
+char(4,40323).
+char(1,40324).
+char(1,40325).
+char(6,40326).
+char(c,40327).
+char(p,40328).
+char(7,40329).
+char(1,40330).
+char(4,40331).
+char(2,40332).
+char(c,40333).
+char(c,40334).
+char(c,40335).
+char(c,40336).
+char(c,40337).
+char(c,40338).
+char(c,40339).
+char(p,40340).
+char(o,40341).
+char(m,40342).
+char(1,40343).
+char(1,40344).
+char(8,40345).
+char(8,40346).
+char(m,40347).
+char(o,40348).
+char(1,40349).
+char(7,40350).
+char(8,40351).
+char(7,40352).
+char(m,40353).
+char(5,40354).
+char(6,40355).
+char(8,40356).
+char(5,40357).
+char(p,40358).
+char(1,40359).
+char(8,40360).
+char(3,40361).
+char(4,40362).
+char(c,40363).
+char(c,40364).
+char(c,40365).
+char(c,40366).
+char(c,40367).
+char(p,40368).
+char(6,40369).
+char(6,40370).
+char(7,40371).
+char(m,40372).
+char(8,40373).
+char(8,40374).
+char(1,40375).
+char(c,40376).
+char(c,40377).
+char(m,40378).
+char(o,40379).
+char(4,40380).
+char(1,40381).
+char(7,40382).
+char(3,40383).
+char(m,40384).
+char(o,40385).
+char(m,40386).
+char(5,40387).
+char(7,40388).
+char(6,40389).
+char(5,40390).
+char(c,40391).
+char(c,40392).
+char(p,40393).
+char(o,40394).
+char(m,40395).
+char(o,40396).
+char(p,40397).
+char(4,40398).
+char(7,40399).
+char(9,40400).
+char(6,40401).
+char(c,40402).
+char(c,40403).
+char(c,40404).
+char(c,40405).
+char(c,40406).
+char(m,40407).
+char(6,40408).
+char(8,40409).
+char(5,40410).
+char(0,40411).
+char(m,40412).
+char(o,40413).
+char(m,40414).
+char(1,40415).
+char(8,40416).
+char(5,40417).
+char(0,40418).
+char(c,40419).
+char(m,40420).
+char(o,40421).
+char(m,40422).
+char(o,40423).
+char(o,40424).
+char(m,40425).
+char(o,40426).
+char(o,40427).
+char(m,40428).
+char(o,40429).
+char(m,40430).
+char(7,40431).
+char(1,40432).
+char(5,40433).
+char(9,40434).
+char(p,40435).
+char(9,40436).
+char(0,40437).
+char(7,40438).
+char(4,40439).
+char(m,40440).
+char(4,40441).
+char(3,40442).
+char(8,40443).
+char(5,40444).
+char(m,40445).
+char(o,40446).
+char(p,40447).
+char(9,40448).
+char(1,40449).
+char(7,40450).
+char(8,40451).
+char(c,40452).
+char(m,40453).
+char(5,40454).
+char(4,40455).
+char(6,40456).
+char(1,40457).
+char(p,40458).
+char(6,40459).
+char(6,40460).
+char(7,40461).
+char(5,40462).
+char(c,40463).
+char(c,40464).
+char(c,40465).
+char(c,40466).
+char(p,40467).
+char(o,40468).
+char(p,40469).
+char(5,40470).
+char(5,40471).
+char(3,40472).
+char(8,40473).
+char(c,40474).
+char(c,40475).
+char(c,40476).
+char(p,40477).
+char(o,40478).
+char(m,40479).
+char(o,40480).
+char(7,40481).
+char(1,40482).
+char(6,40483).
+char(8,40484).
+char(m,40485).
+char(o,40486).
+char(m,40487).
+char(o,40488).
+char(p,40489).
+char(9,40490).
+char(0,40491).
+char(5,40492).
+char(4,40493).
+char(m,40494).
+char(o,40495).
+char(p,40496).
+char(8,40497).
+char(3,40498).
+char(5,40499).
+char(8,40500).
+char(c,40501).
+char(p,40502).
+char(4,40503).
+char(9,40504).
+char(1,40505).
+char(8,40506).
+char(m,40507).
+char(1,40508).
+char(7,40509).
+char(8,40510).
+char(2,40511).
+char(c,40512).
+char(p,40513).
+char(6,40514).
+char(3,40515).
+char(0,40516).
+char(3,40517).
+char(c,40518).
+char(m,40519).
+char(o,40520).
+char(p,40521).
+char(9,40522).
+char(6,40523).
+char(1,40524).
+char(p,40525).
+char(o,40526).
+char(o,40527).
+char(9,40528).
+char(6,40529).
+char(9,40530).
+char(3,40531).
+char(m,40532).
+char(o,40533).
+char(p,40534).
+char(o,40535).
+char(o,40536).
+char(5,40537).
+char(4,40538).
+char(6,40539).
+char(5,40540).
+char(p,40541).
+char(o,40542).
+char(p,40543).
+char(o,40544).
+char(p,40545).
+char(8,40546).
+char(7,40547).
+char(3,40548).
+char(8,40549).
+char(c,40550).
+char(m,40551).
+char(2,40552).
+char(8,40553).
+char(1,40554).
+char(3,40555).
+char(c,40556).
+char(c,40557).
+char(c,40558).
+char(c,40559).
+char(c,40560).
+char(m,40561).
+char(5,40562).
+char(2,40563).
+char(5,40564).
+char(8,40565).
+char(m,40566).
+char(o,40567).
+char(p,40568).
+char(5,40569).
+char(6,40570).
+char(2,40571).
+char(c,40572).
+char(c,40573).
+char(m,40574).
+char(4,40575).
+char(2,40576).
+char(1,40577).
+char(7,40578).
+char(m,40579).
+char(o,40580).
+char(o,40581).
+char(m,40582).
+char(o,40583).
+char(o,40584).
+char(p,40585).
+char(3,40586).
+char(4,40587).
+char(6,40588).
+char(7,40589).
+char(c,40590).
+char(p,40591).
+char(o,40592).
+char(4,40593).
+char(1,40594).
+char(6,40595).
+char(3,40596).
+char(c,40597).
+char(p,40598).
+char(7,40599).
+char(0,40600).
+char(8,40601).
+char(7,40602).
+char(c,40603).
+char(c,40604).
+char(c,40605).
+char(c,40606).
+char(p,40607).
+char(o,40608).
+char(o,40609).
+char(p,40610).
+char(o,40611).
+char(o,40612).
+char(m,40613).
+char(5,40614).
+char(4,40615).
+char(4,40616).
+char(6,40617).
+char(p,40618).
+char(6,40619).
+char(3,40620).
+char(7,40621).
+char(8,40622).
+char(c,40623).
+char(p,40624).
+char(9,40625).
+char(4,40626).
+char(m,40627).
+char(8,40628).
+char(3,40629).
+char(5,40630).
+char(c,40631).
+char(c,40632).
+char(c,40633).
+char(c,40634).
+char(p,40635).
+char(o,40636).
+char(m,40637).
+char(o,40638).
+char(o,40639).
+char(m,40640).
+char(8,40641).
+char(5,40642).
+char(3,40643).
+char(4,40644).
+char(p,40645).
+char(o,40646).
+char(3,40647).
+char(7,40648).
+char(5,40649).
+char(0,40650).
+char(c,40651).
+char(m,40652).
+char(7,40653).
+char(1,40654).
+char(3,40655).
+char(0,40656).
+char(c,40657).
+char(c,40658).
+char(c,40659).
+char(m,40660).
+char(o,40661).
+char(m,40662).
+char(o,40663).
+char(p,40664).
+char(7,40665).
+char(6,40666).
+char(p,40667).
+char(2,40668).
+char(6,40669).
+char(3,40670).
+char(1,40671).
+char(c,40672).
+char(m,40673).
+char(o,40674).
+char(p,40675).
+char(6,40676).
+char(2,40677).
+char(1,40678).
+char(p,40679).
+char(1,40680).
+char(2,40681).
+char(9,40682).
+char(p,40683).
+char(7,40684).
+char(0,40685).
+char(6,40686).
+char(2,40687).
+char(p,40688).
+char(2,40689).
+char(5,40690).
+char(3,40691).
+char(4,40692).
+char(p,40693).
+char(o,40694).
+char(9,40695).
+char(2,40696).
+char(0,40697).
+char(2,40698).
+char(c,40699).
+char(m,40700).
+char(o,40701).
+char(p,40702).
+char(o,40703).
+char(o,40704).
+char(p,40705).
+char(4,40706).
+char(5,40707).
+char(8,40708).
+char(2,40709).
+char(p,40710).
+char(2,40711).
+char(7,40712).
+char(0,40713).
+char(5,40714).
+char(c,40715).
+char(m,40716).
+char(8,40717).
+char(5,40718).
+char(9,40719).
+char(9,40720).
+char(c,40721).
+char(c,40722).
+char(c,40723).
+char(c,40724).
+char(c,40725).
+char(c,40726).
+char(c,40727).
+char(c,40728).
+char(c,40729).
+char(m,40730).
+char(9,40731).
+char(9,40732).
+char(2,40733).
+char(5,40734).
+char(m,40735).
+char(9,40736).
+char(4,40737).
+char(3,40738).
+char(3,40739).
+char(m,40740).
+char(o,40741).
+char(p,40742).
+char(2,40743).
+char(6,40744).
+char(6,40745).
+char(3,40746).
+char(p,40747).
+char(7,40748).
+char(7,40749).
+char(4,40750).
+char(1,40751).
+char(p,40752).
+char(8,40753).
+char(3,40754).
+char(8,40755).
+char(8,40756).
+char(m,40757).
+char(3,40758).
+char(8,40759).
+char(2,40760).
+char(0,40761).
+char(p,40762).
+char(o,40763).
+char(p,40764).
+char(8,40765).
+char(8,40766).
+char(2,40767).
+char(0,40768).
+char(c,40769).
+char(p,40770).
+char(o,40771).
+char(7,40772).
+char(1,40773).
+char(0,40774).
+char(3,40775).
+char(m,40776).
+char(o,40777).
+char(6,40778).
+char(3,40779).
+char(6,40780).
+char(4,40781).
+char(p,40782).
+char(1,40783).
+char(5,40784).
+char(3,40785).
+char(6,40786).
+char(c,40787).
+char(p,40788).
+char(6,40789).
+char(5,40790).
+char(c,40791).
+char(p,40792).
+char(o,40793).
+char(p,40794).
+char(8,40795).
+char(6,40796).
+char(6,40797).
+char(7,40798).
+char(p,40799).
+char(1,40800).
+char(2,40801).
+char(5,40802).
+char(7,40803).
+char(m,40804).
+char(7,40805).
+char(1,40806).
+char(4,40807).
+char(6,40808).
+char(c,40809).
+char(p,40810).
+char(o,40811).
+char(m,40812).
+char(6,40813).
+char(2,40814).
+char(2,40815).
+char(8,40816).
+char(p,40817).
+char(o,40818).
+char(o,40819).
+char(o,40820).
+char(o,40821).
+char(o,40822).
+char(m,40823).
+char(o,40824).
+char(m,40825).
+char(5,40826).
+char(8,40827).
+char(0,40828).
+char(3,40829).
+char(c,40830).
+char(c,40831).
+char(m,40832).
+char(o,40833).
+char(4,40834).
+char(5,40835).
+char(9,40836).
+char(p,40837).
+char(3,40838).
+char(5,40839).
+char(2,40840).
+char(2,40841).
+char(c,40842).
+char(c,40843).
+char(m,40844).
+char(o,40845).
+char(m,40846).
+char(o,40847).
+char(m,40848).
+char(o,40849).
+char(p,40850).
+char(o,40851).
+char(o,40852).
+char(p,40853).
+char(o,40854).
+char(m,40855).
+char(1,40856).
+char(6,40857).
+char(4,40858).
+char(0,40859).
+char(p,40860).
+char(o,40861).
+char(m,40862).
+char(6,40863).
+char(7,40864).
+char(9,40865).
+char(7,40866).
+char(c,40867).
+char(c,40868).
+char(p,40869).
+char(o,40870).
+char(o,40871).
+char(p,40872).
+char(o,40873).
+char(m,40874).
+char(o,40875).
+char(p,40876).
+char(o,40877).
+char(8,40878).
+char(8,40879).
+char(4,40880).
+char(2,40881).
+char(p,40882).
+char(o,40883).
+char(9,40884).
+char(6,40885).
+char(2,40886).
+char(c,40887).
+char(p,40888).
+char(4,40889).
+char(2,40890).
+char(3,40891).
+char(8,40892).
+char(c,40893).
+char(p,40894).
+char(7,40895).
+char(5,40896).
+char(7,40897).
+char(7,40898).
+char(p,40899).
+char(o,40900).
+char(3,40901).
+char(1,40902).
+char(6,40903).
+char(7,40904).
+char(p,40905).
+char(8,40906).
+char(6,40907).
+char(1,40908).
+char(5,40909).
+char(m,40910).
+char(o,40911).
+char(m,40912).
+char(o,40913).
+char(o,40914).
+char(m,40915).
+char(3,40916).
+char(8,40917).
+char(7,40918).
+char(0,40919).
+char(p,40920).
+char(1,40921).
+char(7,40922).
+char(1,40923).
+char(9,40924).
+char(c,40925).
+char(c,40926).
+char(c,40927).
+char(p,40928).
+char(4,40929).
+char(1,40930).
+char(5,40931).
+char(2,40932).
+char(p,40933).
+char(2,40934).
+char(7,40935).
+char(4,40936).
+char(5,40937).
+char(c,40938).
+char(c,40939).
+char(c,40940).
+char(m,40941).
+char(o,40942).
+char(o,40943).
+char(p,40944).
+char(o,40945).
+char(m,40946).
+char(4,40947).
+char(2,40948).
+char(6,40949).
+char(0,40950).
+char(c,40951).
+char(m,40952).
+char(o,40953).
+char(o,40954).
+char(m,40955).
+char(5,40956).
+char(3,40957).
+char(1,40958).
+char(0,40959).
+char(c,40960).
+char(m,40961).
+char(1,40962).
+char(1,40963).
+char(6,40964).
+char(9,40965).
+char(p,40966).
+char(o,40967).
+char(m,40968).
+char(5,40969).
+char(6,40970).
+char(6,40971).
+char(5,40972).
+char(c,40973).
+char(c,40974).
+char(c,40975).
+char(c,40976).
+char(c,40977).
+char(m,40978).
+char(2,40979).
+char(8,40980).
+char(6,40981).
+char(3,40982).
+char(m,40983).
+char(2,40984).
+char(7,40985).
+char(1,40986).
+char(5,40987).
+char(p,40988).
+char(o,40989).
+char(p,40990).
+char(o,40991).
+char(p,40992).
+char(o,40993).
+char(o,40994).
+char(p,40995).
+char(9,40996).
+char(0,40997).
+char(5,40998).
+char(7,40999).
+char(c,41000).
+char(c,41001).
+char(p,41002).
+char(o,41003).
+char(p,41004).
+char(o,41005).
+char(3,41006).
+char(3,41007).
+char(4,41008).
+char(6,41009).
+char(m,41010).
+char(o,41011).
+char(p,41012).
+char(8,41013).
+char(4,41014).
+char(5,41015).
+char(5,41016).
+char(m,41017).
+char(1,41018).
+char(9,41019).
+char(9,41020).
+char(8,41021).
+char(p,41022).
+char(9,41023).
+char(4,41024).
+char(9,41025).
+char(2,41026).
+char(c,41027).
+char(m,41028).
+char(o,41029).
+char(4,41030).
+char(3,41031).
+char(5,41032).
+char(p,41033).
+char(o,41034).
+char(m,41035).
+char(o,41036).
+char(m,41037).
+char(1,41038).
+char(3,41039).
+char(9,41040).
+char(0,41041).
+char(p,41042).
+char(5,41043).
+char(0,41044).
+char(6,41045).
+char(8,41046).
+char(p,41047).
+char(8,41048).
+char(5,41049).
+char(2,41050).
+char(1,41051).
+char(c,41052).
+char(m,41053).
+char(8,41054).
+char(7,41055).
+char(3,41056).
+char(8,41057).
+char(p,41058).
+char(o,41059).
+char(o,41060).
+char(m,41061).
+char(o,41062).
+char(m,41063).
+char(o,41064).
+char(m,41065).
+char(6,41066).
+char(0,41067).
+char(5,41068).
+char(6,41069).
+char(p,41070).
+char(1,41071).
+char(2,41072).
+char(6,41073).
+char(4,41074).
+char(p,41075).
+char(o,41076).
+char(m,41077).
+char(4,41078).
+char(2,41079).
+char(4,41080).
+char(5,41081).
+char(c,41082).
+char(m,41083).
+char(o,41084).
+char(p,41085).
+char(5,41086).
+char(6,41087).
+char(8,41088).
+char(1,41089).
+char(p,41090).
+char(o,41091).
+char(m,41092).
+char(o,41093).
+char(m,41094).
+char(o,41095).
+char(m,41096).
+char(4,41097).
+char(3,41098).
+char(4,41099).
+char(8,41100).
+char(c,41101).
+char(c,41102).
+char(m,41103).
+char(o,41104).
+char(8,41105).
+char(0,41106).
+char(0,41107).
+char(5,41108).
+char(p,41109).
+char(1,41110).
+char(0,41111).
+char(7,41112).
+char(3,41113).
+char(c,41114).
+char(m,41115).
+char(o,41116).
+char(o,41117).
+char(m,41118).
+char(o,41119).
+char(p,41120).
+char(o,41121).
+char(o,41122).
+char(m,41123).
+char(1,41124).
+char(3,41125).
+char(7,41126).
+char(3,41127).
+char(c,41128).
+char(p,41129).
+char(o,41130).
+char(p,41131).
+char(1,41132).
+char(4,41133).
+char(2,41134).
+char(1,41135).
+char(p,41136).
+char(6,41137).
+char(6,41138).
+char(1,41139).
+char(1,41140).
+char(p,41141).
+char(7,41142).
+char(8,41143).
+char(4,41144).
+char(9,41145).
+char(c,41146).
+char(p,41147).
+char(o,41148).
+char(p,41149).
+char(o,41150).
+char(o,41151).
+char(m,41152).
+char(7,41153).
+char(6,41154).
+char(9,41155).
+char(2,41156).
+char(c,41157).
+char(p,41158).
+char(4,41159).
+char(0,41160).
+char(4,41161).
+char(6,41162).
+char(m,41163).
+char(9,41164).
+char(0,41165).
+char(5,41166).
+char(6,41167).
+char(p,41168).
+char(2,41169).
+char(3,41170).
+char(2,41171).
+char(6,41172).
+char(p,41173).
+char(o,41174).
+char(5,41175).
+char(8,41176).
+char(6,41177).
+char(7,41178).
+char(p,41179).
+char(8,41180).
+char(3,41181).
+char(5,41182).
+char(p,41183).
+char(2,41184).
+char(6,41185).
+char(8,41186).
+char(0,41187).
+char(p,41188).
+char(2,41189).
+char(1,41190).
+char(8,41191).
+char(4,41192).
+char(c,41193).
+char(c,41194).
+char(c,41195).
+char(c,41196).
+char(m,41197).
+char(5,41198).
+char(5,41199).
+char(5,41200).
+char(9,41201).
+char(m,41202).
+char(o,41203).
+char(8,41204).
+char(0,41205).
+char(3,41206).
+char(6,41207).
+char(p,41208).
+char(3,41209).
+char(7,41210).
+char(4,41211).
+char(1,41212).
+char(m,41213).
+char(o,41214).
+char(4,41215).
+char(1,41216).
+char(9,41217).
+char(3,41218).
+char(p,41219).
+char(o,41220).
+char(m,41221).
+char(9,41222).
+char(5,41223).
+char(6,41224).
+char(3,41225).
+char(m,41226).
+char(o,41227).
+char(p,41228).
+char(8,41229).
+char(0,41230).
+char(4,41231).
+char(6,41232).
+char(c,41233).
+char(m,41234).
+char(o,41235).
+char(1,41236).
+char(5,41237).
+char(0,41238).
+char(2,41239).
+char(m,41240).
+char(1,41241).
+char(5,41242).
+char(8,41243).
+char(7,41244).
+char(m,41245).
+char(3,41246).
+char(3,41247).
+char(7,41248).
+char(1,41249).
+char(p,41250).
+char(7,41251).
+char(7,41252).
+char(4,41253).
+char(3,41254).
+char(m,41255).
+char(o,41256).
+char(p,41257).
+char(5,41258).
+char(1,41259).
+char(8,41260).
+char(c,41261).
+char(c,41262).
+char(c,41263).
+char(m,41264).
+char(9,41265).
+char(5,41266).
+char(3,41267).
+char(m,41268).
+char(o,41269).
+char(p,41270).
+char(7,41271).
+char(7,41272).
+char(3,41273).
+char(c,41274).
+char(m,41275).
+char(1,41276).
+char(0,41277).
+char(3,41278).
+char(9,41279).
+char(m,41280).
+char(o,41281).
+char(m,41282).
+char(4,41283).
+char(2,41284).
+char(9,41285).
+char(0,41286).
+char(c,41287).
+char(p,41288).
+char(5,41289).
+char(9,41290).
+char(2,41291).
+char(2,41292).
+char(c,41293).
+char(p,41294).
+char(6,41295).
+char(4,41296).
+char(7,41297).
+char(3,41298).
+char(m,41299).
+char(o,41300).
+char(6,41301).
+char(5,41302).
+char(8,41303).
+char(5,41304).
+char(p,41305).
+char(8,41306).
+char(2,41307).
+char(7,41308).
+char(1,41309).
+char(p,41310).
+char(3,41311).
+char(8,41312).
+char(3,41313).
+char(p,41314).
+char(8,41315).
+char(8,41316).
+char(3,41317).
+char(0,41318).
+char(c,41319).
+char(m,41320).
+char(o,41321).
+char(o,41322).
+char(p,41323).
+char(8,41324).
+char(0,41325).
+char(7,41326).
+char(5,41327).
+char(p,41328).
+char(o,41329).
+char(m,41330).
+char(o,41331).
+char(8,41332).
+char(0,41333).
+char(8,41334).
+char(5,41335).
+char(p,41336).
+char(o,41337).
+char(p,41338).
+char(o,41339).
+char(m,41340).
+char(4,41341).
+char(9,41342).
+char(2,41343).
+char(2,41344).
+char(m,41345).
+char(3,41346).
+char(9,41347).
+char(7,41348).
+char(1,41349).
+char(c,41350).
+char(c,41351).
+char(p,41352).
+char(6,41353).
+char(7,41354).
+char(0,41355).
+char(3,41356).
+char(c,41357).
+char(c,41358).
+char(c,41359).
+char(p,41360).
+char(o,41361).
+char(p,41362).
+char(4,41363).
+char(6,41364).
+char(9,41365).
+char(3,41366).
+char(m,41367).
+char(o,41368).
+char(p,41369).
+char(o,41370).
+char(o,41371).
+char(p,41372).
+char(o,41373).
+char(m,41374).
+char(3,41375).
+char(0,41376).
+char(6,41377).
+char(6,41378).
+char(c,41379).
+char(c,41380).
+char(p,41381).
+char(6,41382).
+char(9,41383).
+char(2,41384).
+char(0,41385).
+char(c,41386).
+char(c,41387).
+char(m,41388).
+char(1,41389).
+char(6,41390).
+char(3,41391).
+char(0,41392).
+char(m,41393).
+char(o,41394).
+char(7,41395).
+char(5,41396).
+char(0,41397).
+char(2,41398).
+char(c,41399).
+char(m,41400).
+char(9,41401).
+char(0,41402).
+char(2,41403).
+char(0,41404).
+char(p,41405).
+char(8,41406).
+char(9,41407).
+char(2,41408).
+char(5,41409).
+char(c,41410).
+char(p,41411).
+char(8,41412).
+char(7,41413).
+char(9,41414).
+char(1,41415).
+char(c,41416).
+char(m,41417).
+char(o,41418).
+char(p,41419).
+char(o,41420).
+char(m,41421).
+char(9,41422).
+char(9,41423).
+char(6,41424).
+char(9,41425).
+char(c,41426).
+char(m,41427).
+char(o,41428).
+char(p,41429).
+char(4,41430).
+char(5,41431).
+char(3,41432).
+char(8,41433).
+char(m,41434).
+char(o,41435).
+char(p,41436).
+char(o,41437).
+char(p,41438).
+char(o,41439).
+char(m,41440).
+char(4,41441).
+char(7,41442).
+char(0,41443).
+char(6,41444).
+char(c,41445).
+char(p,41446).
+char(o,41447).
+char(p,41448).
+char(6,41449).
+char(3,41450).
+char(8,41451).
+char(p,41452).
+char(5,41453).
+char(0,41454).
+char(2,41455).
+char(7,41456).
+char(c,41457).
+char(m,41458).
+char(6,41459).
+char(7,41460).
+char(5,41461).
+char(6,41462).
+char(m,41463).
+char(o,41464).
+char(p,41465).
+char(3,41466).
+char(8,41467).
+char(8,41468).
+char(2,41469).
+char(c,41470).
+char(p,41471).
+char(2,41472).
+char(0,41473).
+char(7,41474).
+char(3,41475).
+char(p,41476).
+char(4,41477).
+char(3,41478).
+char(7,41479).
+char(1,41480).
+char(m,41481).
+char(4,41482).
+char(0,41483).
+char(3,41484).
+char(5,41485).
+char(m,41486).
+char(6,41487).
+char(2,41488).
+char(1,41489).
+char(9,41490).
+char(c,41491).
+char(c,41492).
+char(p,41493).
+char(2,41494).
+char(2,41495).
+char(5,41496).
+char(9,41497).
+char(p,41498).
+char(o,41499).
+char(p,41500).
+char(3,41501).
+char(4,41502).
+char(4,41503).
+char(5,41504).
+char(c,41505).
+char(c,41506).
+char(p,41507).
+char(2,41508).
+char(1,41509).
+char(9,41510).
+char(5,41511).
+char(c,41512).
+char(c,41513).
+char(c,41514).
+char(c,41515).
+char(c,41516).
+char(c,41517).
+char(c,41518).
+char(c,41519).
+char(c,41520).
+char(c,41521).
+char(c,41522).
+char(m,41523).
+char(o,41524).
+char(2,41525).
+char(1,41526).
+char(6,41527).
+char(3,41528).
+char(m,41529).
+char(9,41530).
+char(6,41531).
+char(3,41532).
+char(9,41533).
+char(p,41534).
+char(8,41535).
+char(9,41536).
+char(3,41537).
+char(c,41538).
+char(m,41539).
+char(6,41540).
+char(0,41541).
+char(6,41542).
+char(6,41543).
+char(c,41544).
+char(p,41545).
+char(o,41546).
+char(o,41547).
+char(p,41548).
+char(o,41549).
+char(m,41550).
+char(o,41551).
+char(p,41552).
+char(o,41553).
+char(m,41554).
+char(o,41555).
+char(m,41556).
+char(o,41557).
+char(p,41558).
+char(9,41559).
+char(3,41560).
+char(6,41561).
+char(0,41562).
+char(m,41563).
+char(o,41564).
+char(o,41565).
+char(p,41566).
+char(o,41567).
+char(m,41568).
+char(6,41569).
+char(4,41570).
+char(6,41571).
+char(5,41572).
+char(c,41573).
+char(p,41574).
+char(o,41575).
+char(m,41576).
+char(5,41577).
+char(0,41578).
+char(3,41579).
+char(c,41580).
+char(c,41581).
+char(m,41582).
+char(9,41583).
+char(2,41584).
+char(1,41585).
+char(2,41586).
+char(c,41587).
+char(m,41588).
+char(o,41589).
+char(o,41590).
+char(p,41591).
+char(o,41592).
+char(p,41593).
+char(6,41594).
+char(9,41595).
+char(4,41596).
+char(0,41597).
+char(c,41598).
+char(p,41599).
+char(o,41600).
+char(p,41601).
+char(6,41602).
+char(6,41603).
+char(6,41604).
+char(2,41605).
+char(m,41606).
+char(6,41607).
+char(7,41608).
+char(3,41609).
+char(8,41610).
+char(c,41611).
+char(c,41612).
+char(p,41613).
+char(6,41614).
+char(7,41615).
+char(1,41616).
+char(3,41617).
+char(p,41618).
+char(o,41619).
+char(m,41620).
+char(o,41621).
+char(p,41622).
+char(4,41623).
+char(8,41624).
+char(6,41625).
+char(3,41626).
+char(p,41627).
+char(8,41628).
+char(0,41629).
+char(4,41630).
+char(7,41631).
+char(p,41632).
+char(1,41633).
+char(0,41634).
+char(8,41635).
+char(5,41636).
+char(c,41637).
+char(c,41638).
+char(c,41639).
+char(c,41640).
+char(m,41641).
+char(o,41642).
+char(p,41643).
+char(o,41644).
+char(p,41645).
+char(9,41646).
+char(4,41647).
+char(4,41648).
+char(p,41649).
+char(1,41650).
+char(8,41651).
+char(1,41652).
+char(0,41653).
+char(c,41654).
+char(c,41655).
+char(m,41656).
+char(o,41657).
+char(o,41658).
+char(p,41659).
+char(o,41660).
+char(p,41661).
+char(o,41662).
+char(p,41663).
+char(7,41664).
+char(5,41665).
+char(5,41666).
+char(3,41667).
+char(p,41668).
+char(3,41669).
+char(9,41670).
+char(0,41671).
+char(3,41672).
+char(c,41673).
+char(c,41674).
+char(p,41675).
+char(o,41676).
+char(p,41677).
+char(o,41678).
+char(o,41679).
+char(m,41680).
+char(3,41681).
+char(8,41682).
+char(5,41683).
+char(8,41684).
+char(c,41685).
+char(c,41686).
+char(p,41687).
+char(9,41688).
+char(1,41689).
+char(3,41690).
+char(9,41691).
+char(c,41692).
+char(c,41693).
+char(c,41694).
+char(m,41695).
+char(o,41696).
+char(o,41697).
+char(4,41698).
+char(8,41699).
+char(3,41700).
+char(3,41701).
+char(m,41702).
+char(8,41703).
+char(4,41704).
+char(0,41705).
+char(8,41706).
+char(c,41707).
+char(c,41708).
+char(p,41709).
+char(o,41710).
+char(5,41711).
+char(2,41712).
+char(0,41713).
+char(7,41714).
+char(m,41715).
+char(6,41716).
+char(3,41717).
+char(1,41718).
+char(9,41719).
+char(c,41720).
+char(c,41721).
+char(c,41722).
+char(m,41723).
+char(6,41724).
+char(3,41725).
+char(7,41726).
+char(6,41727).
+char(c,41728).
+char(p,41729).
+char(8,41730).
+char(3,41731).
+char(1,41732).
+char(7,41733).
+char(c,41734).
+char(c,41735).
+char(c,41736).
+char(c,41737).
+char(m,41738).
+char(5,41739).
+char(4,41740).
+char(8,41741).
+char(8,41742).
+char(c,41743).
+char(p,41744).
+char(o,41745).
+char(m,41746).
+char(4,41747).
+char(1,41748).
+char(2,41749).
+char(5,41750).
+char(m,41751).
+char(3,41752).
+char(3,41753).
+char(4,41754).
+char(7,41755).
+char(c,41756).
+char(m,41757).
+char(1,41758).
+char(2,41759).
+char(8,41760).
+char(8,41761).
+char(p,41762).
+char(o,41763).
+char(p,41764).
+char(6,41765).
+char(3,41766).
+char(4,41767).
+char(4,41768).
+char(m,41769).
+char(o,41770).
+char(m,41771).
+char(3,41772).
+char(3,41773).
+char(9,41774).
+char(5,41775).
+char(c,41776).
+char(c,41777).
+char(c,41778).
+char(m,41779).
+char(o,41780).
+char(m,41781).
+char(o,41782).
+char(p,41783).
+char(o,41784).
+char(m,41785).
+char(o,41786).
+char(p,41787).
+char(o,41788).
+char(p,41789).
+char(o,41790).
+char(1,41791).
+char(0,41792).
+char(7,41793).
+char(4,41794).
+char(m,41795).
+char(o,41796).
+char(p,41797).
+char(o,41798).
+char(m,41799).
+char(o,41800).
+char(m,41801).
+char(5,41802).
+char(7,41803).
+char(2,41804).
+char(3,41805).
+char(c,41806).
+char(m,41807).
+char(4,41808).
+char(0,41809).
+char(1,41810).
+char(p,41811).
+char(o,41812).
+char(m,41813).
+char(o,41814).
+char(m,41815).
+char(2,41816).
+char(0,41817).
+char(0,41818).
+char(2,41819).
+char(p,41820).
+char(7,41821).
+char(2,41822).
+char(6,41823).
+char(9,41824).
+char(c,41825).
+char(c,41826).
+char(m,41827).
+char(8,41828).
+char(9,41829).
+char(2,41830).
+char(8,41831).
+char(m,41832).
+char(o,41833).
+char(p,41834).
+char(8,41835).
+char(1,41836).
+char(4,41837).
+char(2,41838).
+char(m,41839).
+char(6,41840).
+char(1,41841).
+char(9,41842).
+char(0,41843).
+char(c,41844).
+char(p,41845).
+char(o,41846).
+char(m,41847).
+char(4,41848).
+char(9,41849).
+char(0,41850).
+char(0,41851).
+char(m,41852).
+char(3,41853).
+char(5,41854).
+char(7,41855).
+char(2,41856).
+char(m,41857).
+char(3,41858).
+char(5,41859).
+char(0,41860).
+char(1,41861).
+char(m,41862).
+char(o,41863).
+char(m,41864).
+char(o,41865).
+char(m,41866).
+char(9,41867).
+char(0,41868).
+char(1,41869).
+char(3,41870).
+char(m,41871).
+char(o,41872).
+char(p,41873).
+char(o,41874).
+char(m,41875).
+char(5,41876).
+char(2,41877).
+char(0,41878).
+char(7,41879).
+char(p,41880).
+char(5,41881).
+char(3,41882).
+char(6,41883).
+char(1,41884).
+char(c,41885).
+char(p,41886).
+char(o,41887).
+char(6,41888).
+char(2,41889).
+char(1,41890).
+char(5,41891).
+char(p,41892).
+char(o,41893).
+char(p,41894).
+char(o,41895).
+char(p,41896).
+char(5,41897).
+char(9,41898).
+char(2,41899).
+char(1,41900).
+char(m,41901).
+char(8,41902).
+char(6,41903).
+char(3,41904).
+char(5,41905).
+char(c,41906).
+char(c,41907).
+char(p,41908).
+char(o,41909).
+char(m,41910).
+char(4,41911).
+char(1,41912).
+char(2,41913).
+char(0,41914).
+char(m,41915).
+char(9,41916).
+char(7,41917).
+char(4,41918).
+char(3,41919).
+char(m,41920).
+char(o,41921).
+char(o,41922).
+char(p,41923).
+char(o,41924).
+char(p,41925).
+char(8,41926).
+char(8,41927).
+char(9,41928).
+char(4,41929).
+char(m,41930).
+char(o,41931).
+char(8,41932).
+char(8,41933).
+char(9,41934).
+char(8,41935).
+char(p,41936).
+char(4,41937).
+char(5,41938).
+char(0,41939).
+char(1,41940).
+char(c,41941).
+char(c,41942).
+char(c,41943).
+char(c,41944).
+char(c,41945).
+char(c,41946).
+char(p,41947).
+char(o,41948).
+char(m,41949).
+char(o,41950).
+char(o,41951).
+char(4,41952).
+char(9,41953).
+char(0,41954).
+char(9,41955).
+char(c,41956).
+char(m,41957).
+char(7,41958).
+char(8,41959).
+char(5,41960).
+char(5,41961).
+char(m,41962).
+char(3,41963).
+char(8,41964).
+char(0,41965).
+char(4,41966).
+char(c,41967).
+char(c,41968).
+char(p,41969).
+char(9,41970).
+char(2,41971).
+char(0,41972).
+char(3,41973).
+char(p,41974).
+char(2,41975).
+char(4,41976).
+char(0,41977).
+char(5,41978).
+char(c,41979).
+char(p,41980).
+char(2,41981).
+char(0,41982).
+char(3,41983).
+char(3,41984).
+char(c,41985).
+char(c,41986).
+char(m,41987).
+char(7,41988).
+char(6,41989).
+char(7,41990).
+char(0,41991).
+char(c,41992).
+char(m,41993).
+char(1,41994).
+char(8,41995).
+char(0,41996).
+char(3,41997).
+char(p,41998).
+char(o,41999).
+char(o,42000).
+char(3,42001).
+char(8,42002).
+char(0,42003).
+char(9,42004).
+char(c,42005).
+char(p,42006).
+char(8,42007).
+char(6,42008).
+char(2,42009).
+char(9,42010).
+char(c,42011).
+char(m,42012).
+char(o,42013).
+char(m,42014).
+char(9,42015).
+char(6,42016).
+char(2,42017).
+char(2,42018).
+char(m,42019).
+char(o,42020).
+char(m,42021).
+char(o,42022).
+char(5,42023).
+char(4,42024).
+char(8,42025).
+char(6,42026).
+char(p,42027).
+char(7,42028).
+char(1,42029).
+char(8,42030).
+char(2,42031).
+char(c,42032).
+char(m,42033).
+char(o,42034).
+char(p,42035).
+char(8,42036).
+char(1,42037).
+char(9,42038).
+char(c,42039).
+char(c,42040).
+char(m,42041).
+char(8,42042).
+char(9,42043).
+char(9,42044).
+char(0,42045).
+char(c,42046).
+char(p,42047).
+char(o,42048).
+char(p,42049).
+char(o,42050).
+char(m,42051).
+char(4,42052).
+char(9,42053).
+char(2,42054).
+char(4,42055).
+char(c,42056).
+char(p,42057).
+char(o,42058).
+char(p,42059).
+char(6,42060).
+char(4,42061).
+char(4,42062).
+char(3,42063).
+char(m,42064).
+char(o,42065).
+char(p,42066).
+char(3,42067).
+char(6,42068).
+char(1,42069).
+char(4,42070).
+char(p,42071).
+char(4,42072).
+char(2,42073).
+char(1,42074).
+char(3,42075).
+char(c,42076).
+char(m,42077).
+char(4,42078).
+char(3,42079).
+char(7,42080).
+char(1,42081).
+char(c,42082).
+char(c,42083).
+char(c,42084).
+char(p,42085).
+char(9,42086).
+char(5,42087).
+char(7,42088).
+char(0,42089).
+char(c,42090).
+char(m,42091).
+char(o,42092).
+char(p,42093).
+char(5,42094).
+char(7,42095).
+char(0,42096).
+char(c,42097).
+char(p,42098).
+char(7,42099).
+char(5,42100).
+char(9,42101).
+char(0,42102).
+char(p,42103).
+char(5,42104).
+char(1,42105).
+char(4,42106).
+char(7,42107).
+char(m,42108).
+char(o,42109).
+char(o,42110).
+char(p,42111).
+char(5,42112).
+char(6,42113).
+char(6,42114).
+char(9,42115).
+char(p,42116).
+char(o,42117).
+char(m,42118).
+char(7,42119).
+char(3,42120).
+char(2,42121).
+char(0,42122).
+char(m,42123).
+char(o,42124).
+char(p,42125).
+char(2,42126).
+char(3,42127).
+char(5,42128).
+char(7,42129).
+char(m,42130).
+char(o,42131).
+char(p,42132).
+char(o,42133).
+char(o,42134).
+char(m,42135).
+char(o,42136).
+char(p,42137).
+char(o,42138).
+char(m,42139).
+char(o,42140).
+char(8,42141).
+char(7,42142).
+char(0,42143).
+char(0,42144).
+char(p,42145).
+char(o,42146).
+char(p,42147).
+char(o,42148).
+char(p,42149).
+char(3,42150).
+char(3,42151).
+char(1,42152).
+char(8,42153).
+char(p,42154).
+char(o,42155).
+char(o,42156).
+char(8,42157).
+char(9,42158).
+char(8,42159).
+char(6,42160).
+char(m,42161).
+char(o,42162).
+char(4,42163).
+char(7,42164).
+char(8,42165).
+char(2,42166).
+char(c,42167).
+char(m,42168).
+char(4,42169).
+char(2,42170).
+char(5,42171).
+char(4,42172).
+char(c,42173).
+char(c,42174).
+char(p,42175).
+char(6,42176).
+char(9,42177).
+char(4,42178).
+char(0,42179).
+char(m,42180).
+char(o,42181).
+char(p,42182).
+char(o,42183).
+char(6,42184).
+char(6,42185).
+char(3,42186).
+char(4,42187).
+char(c,42188).
+char(c,42189).
+char(p,42190).
+char(o,42191).
+char(m,42192).
+char(o,42193).
+char(m,42194).
+char(o,42195).
+char(m,42196).
+char(o,42197).
+char(m,42198).
+char(4,42199).
+char(5,42200).
+char(0,42201).
+char(0,42202).
+char(c,42203).
+char(p,42204).
+char(o,42205).
+char(p,42206).
+char(o,42207).
+char(p,42208).
+char(1,42209).
+char(7,42210).
+char(8,42211).
+char(8,42212).
+char(c,42213).
+char(c,42214).
+char(m,42215).
+char(4,42216).
+char(5,42217).
+char(1,42218).
+char(5,42219).
+char(m,42220).
+char(1,42221).
+char(3,42222).
+char(1,42223).
+char(5,42224).
+char(c,42225).
+char(c,42226).
+char(c,42227).
+char(c,42228).
+char(p,42229).
+char(2,42230).
+char(6,42231).
+char(1,42232).
+char(2,42233).
+char(m,42234).
+char(6,42235).
+char(8,42236).
+char(1,42237).
+char(3,42238).
+char(c,42239).
+char(m,42240).
+char(9,42241).
+char(7,42242).
+char(2,42243).
+char(7,42244).
+char(c,42245).
+char(m,42246).
+char(1,42247).
+char(2,42248).
+char(1,42249).
+char(0,42250).
+char(c,42251).
+char(c,42252).
+char(c,42253).
+char(m,42254).
+char(o,42255).
+char(p,42256).
+char(5,42257).
+char(4,42258).
+char(1,42259).
+char(0,42260).
+char(m,42261).
+char(1,42262).
+char(0,42263).
+char(4,42264).
+char(1,42265).
+char(m,42266).
+char(7,42267).
+char(8,42268).
+char(7,42269).
+char(c,42270).
+char(c,42271).
+char(p,42272).
+char(o,42273).
+char(o,42274).
+char(o,42275).
+char(o,42276).
+char(7,42277).
+char(4,42278).
+char(0,42279).
+char(6,42280).
+char(p,42281).
+char(o,42282).
+char(p,42283).
+char(3,42284).
+char(4,42285).
+char(7,42286).
+char(2,42287).
+char(m,42288).
+char(6,42289).
+char(8,42290).
+char(0,42291).
+char(7,42292).
+char(c,42293).
+char(c,42294).
+char(c,42295).
+char(c,42296).
+char(p,42297).
+char(8,42298).
+char(9,42299).
+char(7,42300).
+char(m,42301).
+char(9,42302).
+char(7,42303).
+char(1,42304).
+char(8,42305).
+char(m,42306).
+char(1,42307).
+char(7,42308).
+char(6,42309).
+char(c,42310).
+char(c,42311).
+char(m,42312).
+char(o,42313).
+char(o,42314).
+char(o,42315).
+char(m,42316).
+char(6,42317).
+char(0,42318).
+char(1,42319).
+char(0,42320).
+char(p,42321).
+char(7,42322).
+char(2,42323).
+char(6,42324).
+char(m,42325).
+char(o,42326).
+char(o,42327).
+char(o,42328).
+char(m,42329).
+char(7,42330).
+char(4,42331).
+char(6,42332).
+char(5,42333).
+char(p,42334).
+char(8,42335).
+char(5,42336).
+char(5,42337).
+char(6,42338).
+char(c,42339).
+char(m,42340).
+char(o,42341).
+char(m,42342).
+char(7,42343).
+char(1,42344).
+char(1,42345).
+char(6,42346).
+char(m,42347).
+char(9,42348).
+char(5,42349).
+char(3,42350).
+char(1,42351).
+char(m,42352).
+char(o,42353).
+char(o,42354).
+char(o,42355).
+char(m,42356).
+char(o,42357).
+char(o,42358).
+char(o,42359).
+char(2,42360).
+char(1,42361).
+char(6,42362).
+char(6,42363).
+char(c,42364).
+char(m,42365).
+char(o,42366).
+char(o,42367).
+char(m,42368).
+char(o,42369).
+char(p,42370).
+char(1,42371).
+char(6,42372).
+char(7,42373).
+char(7,42374).
+char(c,42375).
+char(p,42376).
+char(o,42377).
+char(3,42378).
+char(0,42379).
+char(1,42380).
+char(7,42381).
+char(c,42382).
+char(c,42383).
+char(c,42384).
+char(m,42385).
+char(9,42386).
+char(0,42387).
+char(4,42388).
+char(3,42389).
+char(c,42390).
+char(p,42391).
+char(o,42392).
+char(p,42393).
+char(o,42394).
+char(m,42395).
+char(4,42396).
+char(8,42397).
+char(0,42398).
+char(3,42399).
+char(c,42400).
+char(p,42401).
+char(7,42402).
+char(3,42403).
+char(0,42404).
+char(9,42405).
+char(c,42406).
+char(p,42407).
+char(o,42408).
+char(p,42409).
+char(7,42410).
+char(7,42411).
+char(7,42412).
+char(4,42413).
+char(c,42414).
+char(c,42415).
+char(m,42416).
+char(5,42417).
+char(4,42418).
+char(2,42419).
+char(8,42420).
+char(c,42421).
+char(c,42422).
+char(m,42423).
+char(o,42424).
+char(m,42425).
+char(o,42426).
+char(o,42427).
+char(p,42428).
+char(1,42429).
+char(9,42430).
+char(6,42431).
+char(5,42432).
+char(p,42433).
+char(o,42434).
+char(o,42435).
+char(m,42436).
+char(2,42437).
+char(5,42438).
+char(9,42439).
+char(6,42440).
+char(p,42441).
+char(3,42442).
+char(4,42443).
+char(3,42444).
+char(5,42445).
+char(p,42446).
+char(o,42447).
+char(p,42448).
+char(4,42449).
+char(9,42450).
+char(0,42451).
+char(6,42452).
+char(m,42453).
+char(o,42454).
+char(p,42455).
+char(o,42456).
+char(m,42457).
+char(8,42458).
+char(8,42459).
+char(0,42460).
+char(3,42461).
+char(m,42462).
+char(o,42463).
+char(p,42464).
+char(8,42465).
+char(3,42466).
+char(0,42467).
+char(1,42468).
+char(c,42469).
+char(m,42470).
+char(o,42471).
+char(p,42472).
+char(9,42473).
+char(1,42474).
+char(8,42475).
+char(4,42476).
+char(c,42477).
+char(c,42478).
+char(c,42479).
+char(p,42480).
+char(o,42481).
+char(o,42482).
+char(o,42483).
+char(m,42484).
+char(5,42485).
+char(6,42486).
+char(5,42487).
+char(0,42488).
+char(c,42489).
+char(c,42490).
+char(c,42491).
+char(c,42492).
+char(m,42493).
+char(o,42494).
+char(m,42495).
+char(o,42496).
+char(p,42497).
+char(o,42498).
+char(m,42499).
+char(o,42500).
+char(p,42501).
+char(o,42502).
+char(7,42503).
+char(0,42504).
+char(4,42505).
+char(8,42506).
+char(c,42507).
+char(c,42508).
+char(c,42509).
+char(c,42510).
+char(c,42511).
+char(p,42512).
+char(o,42513).
+char(p,42514).
+char(o,42515).
+char(3,42516).
+char(7,42517).
+char(0,42518).
+char(0,42519).
+char(m,42520).
+char(4,42521).
+char(0,42522).
+char(6,42523).
+char(c,42524).
+char(c,42525).
+char(c,42526).
+char(c,42527).
+char(c,42528).
+char(p,42529).
+char(1,42530).
+char(3,42531).
+char(6,42532).
+char(9,42533).
+char(c,42534).
+char(c,42535).
+char(m,42536).
+char(6,42537).
+char(8,42538).
+char(2,42539).
+char(5,42540).
+char(c,42541).
+char(m,42542).
+char(1,42543).
+char(2,42544).
+char(9,42545).
+char(6,42546).
+char(c,42547).
+char(c,42548).
+char(c,42549).
+char(p,42550).
+char(o,42551).
+char(p,42552).
+char(4,42553).
+char(9,42554).
+char(4,42555).
+char(1,42556).
+char(c,42557).
+char(c,42558).
+char(c,42559).
+char(c,42560).
+char(m,42561).
+char(5,42562).
+char(1,42563).
+char(1,42564).
+char(6,42565).
+char(p,42566).
+char(3,42567).
+char(7,42568).
+char(0,42569).
+char(8,42570).
+char(m,42571).
+char(3,42572).
+char(6,42573).
+char(1,42574).
+char(2,42575).
+char(c,42576).
+char(c,42577).
+char(c,42578).
+char(p,42579).
+char(o,42580).
+char(m,42581).
+char(5,42582).
+char(3,42583).
+char(5,42584).
+char(2,42585).
+char(c,42586).
+char(c,42587).
+char(p,42588).
+char(2,42589).
+char(5,42590).
+char(9,42591).
+char(m,42592).
+char(1,42593).
+char(0,42594).
+char(6,42595).
+char(0,42596).
+char(c,42597).
+char(c,42598).
+char(m,42599).
+char(o,42600).
+char(m,42601).
+char(7,42602).
+char(5,42603).
+char(7,42604).
+char(c,42605).
+char(m,42606).
+char(9,42607).
+char(1,42608).
+char(3,42609).
+char(4,42610).
+char(m,42611).
+char(3,42612).
+char(0,42613).
+char(8,42614).
+char(9,42615).
+char(m,42616).
+char(7,42617).
+char(3,42618).
+char(9,42619).
+char(9,42620).
+char(c,42621).
+char(p,42622).
+char(4,42623).
+char(0,42624).
+char(8,42625).
+char(9,42626).
+char(c,42627).
+char(c,42628).
+char(c,42629).
+char(m,42630).
+char(3,42631).
+char(7,42632).
+char(0,42633).
+char(3,42634).
+char(c,42635).
+char(c,42636).
+char(m,42637).
+char(o,42638).
+char(o,42639).
+char(p,42640).
+char(1,42641).
+char(7,42642).
+char(0,42643).
+char(5,42644).
+char(c,42645).
+char(c,42646).
+char(m,42647).
+char(o,42648).
+char(p,42649).
+char(o,42650).
+char(m,42651).
+char(3,42652).
+char(4,42653).
+char(1,42654).
+char(0,42655).
+char(c,42656).
+char(p,42657).
+char(o,42658).
+char(m,42659).
+char(o,42660).
+char(o,42661).
+char(o,42662).
+char(m,42663).
+char(o,42664).
+char(m,42665).
+char(o,42666).
+char(p,42667).
+char(o,42668).
+char(o,42669).
+char(m,42670).
+char(7,42671).
+char(4,42672).
+char(4,42673).
+char(5,42674).
+char(c,42675).
+char(c,42676).
+char(c,42677).
+char(c,42678).
+char(c,42679).
+char(c,42680).
+char(p,42681).
+char(o,42682).
+char(p,42683).
+char(9,42684).
+char(5,42685).
+char(4,42686).
+char(8,42687).
+char(c,42688).
+char(m,42689).
+char(1,42690).
+char(6,42691).
+char(9,42692).
+char(5,42693).
+char(c,42694).
+char(c,42695).
+char(m,42696).
+char(5,42697).
+char(4,42698).
+char(1,42699).
+char(4,42700).
+char(c,42701).
+char(c,42702).
+char(m,42703).
+char(o,42704).
+char(1,42705).
+char(8,42706).
+char(2,42707).
+char(8,42708).
+char(c,42709).
+char(c,42710).
+char(c,42711).
+char(c,42712).
+char(c,42713).
+char(m,42714).
+char(o,42715).
+char(m,42716).
+char(o,42717).
+char(p,42718).
+char(o,42719).
+char(o,42720).
+char(m,42721).
+char(o,42722).
+char(m,42723).
+char(o,42724).
+char(o,42725).
+char(p,42726).
+char(o,42727).
+char(o,42728).
+char(p,42729).
+char(9,42730).
+char(7,42731).
+char(8,42732).
+char(1,42733).
+char(m,42734).
+char(4,42735).
+char(6,42736).
+char(9,42737).
+char(7,42738).
+char(m,42739).
+char(o,42740).
+char(6,42741).
+char(1,42742).
+char(6,42743).
+char(0,42744).
+char(p,42745).
+char(o,42746).
+char(p,42747).
+char(7,42748).
+char(0,42749).
+char(1,42750).
+char(2,42751).
+char(m,42752).
+char(o,42753).
+char(6,42754).
+char(1,42755).
+char(1,42756).
+char(p,42757).
+char(8,42758).
+char(9,42759).
+char(3,42760).
+char(1,42761).
+char(c,42762).
+char(c,42763).
+char(c,42764).
+char(p,42765).
+char(9,42766).
+char(2,42767).
+char(8,42768).
+char(2,42769).
+char(c,42770).
+char(c,42771).
+char(p,42772).
+char(7,42773).
+char(6,42774).
+char(7,42775).
+char(4,42776).
+char(m,42777).
+char(3,42778).
+char(2,42779).
+char(3,42780).
+char(p,42781).
+char(o,42782).
+char(1,42783).
+char(6,42784).
+char(9,42785).
+char(c,42786).
+char(p,42787).
+char(7,42788).
+char(2,42789).
+char(9,42790).
+char(6,42791).
+char(c,42792).
+char(m,42793).
+char(2,42794).
+char(4,42795).
+char(6,42796).
+char(p,42797).
+char(2,42798).
+char(5,42799).
+char(4,42800).
+char(1,42801).
+char(c,42802).
+char(c,42803).
+char(m,42804).
+char(o,42805).
+char(o,42806).
+char(m,42807).
+char(o,42808).
+char(p,42809).
+char(2,42810).
+char(5,42811).
+char(3,42812).
+char(6,42813).
+char(p,42814).
+char(9,42815).
+char(8,42816).
+char(c,42817).
+char(c,42818).
+char(p,42819).
+char(o,42820).
+char(p,42821).
+char(9,42822).
+char(9,42823).
+char(3,42824).
+char(9,42825).
+char(m,42826).
+char(4,42827).
+char(4,42828).
+char(0,42829).
+char(6,42830).
+char(c,42831).
+char(c,42832).
+char(p,42833).
+char(o,42834).
+char(o,42835).
+char(o,42836).
+char(p,42837).
+char(o,42838).
+char(m,42839).
+char(o,42840).
+char(9,42841).
+char(8,42842).
+char(5,42843).
+char(c,42844).
+char(m,42845).
+char(6,42846).
+char(8,42847).
+char(9,42848).
+char(7,42849).
+char(c,42850).
+char(c,42851).
+char(c,42852).
+char(p,42853).
+char(o,42854).
+char(7,42855).
+char(1,42856).
+char(4,42857).
+char(m,42858).
+char(o,42859).
+char(8,42860).
+char(9,42861).
+char(2,42862).
+char(3,42863).
+char(c,42864).
+char(p,42865).
+char(o,42866).
+char(p,42867).
+char(o,42868).
+char(p,42869).
+char(o,42870).
+char(o,42871).
+char(p,42872).
+char(o,42873).
+char(p,42874).
+char(8,42875).
+char(5,42876).
+char(7,42877).
+char(8,42878).
+char(c,42879).
+char(c,42880).
+char(p,42881).
+char(4,42882).
+char(6,42883).
+char(5,42884).
+char(7,42885).
+char(c,42886).
+char(m,42887).
+char(o,42888).
+char(m,42889).
+char(o,42890).
+char(m,42891).
+char(5,42892).
+char(9,42893).
+char(6,42894).
+char(7,42895).
+char(p,42896).
+char(o,42897).
+char(o,42898).
+char(4,42899).
+char(0,42900).
+char(6,42901).
+char(4,42902).
+char(c,42903).
+char(p,42904).
+char(o,42905).
+char(3,42906).
+char(2,42907).
+char(2,42908).
+char(6,42909).
+char(c,42910).
+char(m,42911).
+char(4,42912).
+char(7,42913).
+char(0,42914).
+char(8,42915).
+char(c,42916).
+char(m,42917).
+char(o,42918).
+char(p,42919).
+char(o,42920).
+char(o,42921).
+char(p,42922).
+char(o,42923).
+char(p,42924).
+char(o,42925).
+char(4,42926).
+char(3,42927).
+char(5,42928).
+char(4,42929).
+char(m,42930).
+char(6,42931).
+char(8,42932).
+char(9,42933).
+char(2,42934).
+char(c,42935).
+char(c,42936).
+char(p,42937).
+char(7,42938).
+char(6,42939).
+char(2,42940).
+char(5,42941).
+char(m,42942).
+char(o,42943).
+char(m,42944).
+char(9,42945).
+char(1,42946).
+char(8,42947).
+char(0,42948).
+char(m,42949).
+char(7,42950).
+char(6,42951).
+char(3,42952).
+char(9,42953).
+char(p,42954).
+char(4,42955).
+char(0,42956).
+char(5,42957).
+char(m,42958).
+char(7,42959).
+char(9,42960).
+char(3,42961).
+char(p,42962).
+char(o,42963).
+char(m,42964).
+char(2,42965).
+char(1,42966).
+char(7,42967).
+char(5,42968).
+char(c,42969).
+char(c,42970).
+char(p,42971).
+char(4,42972).
+char(0,42973).
+char(4,42974).
+char(1,42975).
+char(m,42976).
+char(9,42977).
+char(9,42978).
+char(4,42979).
+char(7,42980).
+char(c,42981).
+char(c,42982).
+char(c,42983).
+char(c,42984).
+char(p,42985).
+char(o,42986).
+char(m,42987).
+char(9,42988).
+char(7,42989).
+char(1,42990).
+char(1,42991).
+char(p,42992).
+char(o,42993).
+char(m,42994).
+char(o,42995).
+char(p,42996).
+char(3,42997).
+char(0,42998).
+char(4,42999).
+char(1,43000).
+char(c,43001).
+char(c,43002).
+char(c,43003).
+char(p,43004).
+char(o,43005).
+char(m,43006).
+char(o,43007).
+char(m,43008).
+char(9,43009).
+char(7,43010).
+char(0,43011).
+char(9,43012).
+char(m,43013).
+char(o,43014).
+char(7,43015).
+char(3,43016).
+char(8,43017).
+char(7,43018).
+char(p,43019).
+char(6,43020).
+char(3,43021).
+char(8,43022).
+char(7,43023).
+char(m,43024).
+char(7,43025).
+char(6,43026).
+char(c,43027).
+char(c,43028).
+char(c,43029).
+char(p,43030).
+char(o,43031).
+char(p,43032).
+char(6,43033).
+char(3,43034).
+char(3,43035).
+char(9,43036).
+char(c,43037).
+char(c,43038).
+char(m,43039).
+char(o,43040).
+char(p,43041).
+char(5,43042).
+char(1,43043).
+char(6,43044).
+char(8,43045).
+char(p,43046).
+char(o,43047).
+char(p,43048).
+char(8,43049).
+char(3,43050).
+char(8,43051).
+char(4,43052).
+char(c,43053).
+char(m,43054).
+char(o,43055).
+char(p,43056).
+char(o,43057).
+char(p,43058).
+char(8,43059).
+char(2,43060).
+char(4,43061).
+char(5,43062).
+char(c,43063).
+char(c,43064).
+char(c,43065).
+char(m,43066).
+char(4,43067).
+char(1,43068).
+char(7,43069).
+char(4,43070).
+char(c,43071).
+char(m,43072).
+char(3,43073).
+char(6,43074).
+char(9,43075).
+char(p,43076).
+char(o,43077).
+char(m,43078).
+char(1,43079).
+char(5,43080).
+char(4,43081).
+char(7,43082).
+char(c,43083).
+char(m,43084).
+char(3,43085).
+char(7,43086).
+char(2,43087).
+char(2,43088).
+char(p,43089).
+char(o,43090).
+char(m,43091).
+char(8,43092).
+char(1,43093).
+char(2,43094).
+char(m,43095).
+char(8,43096).
+char(2,43097).
+char(2,43098).
+char(6,43099).
+char(p,43100).
+char(5,43101).
+char(2,43102).
+char(2,43103).
+char(5,43104).
+char(c,43105).
+char(c,43106).
+char(c,43107).
+char(m,43108).
+char(o,43109).
+char(4,43110).
+char(9,43111).
+char(6,43112).
+char(1,43113).
+char(c,43114).
+char(m,43115).
+char(o,43116).
+char(p,43117).
+char(7,43118).
+char(8,43119).
+char(1,43120).
+char(p,43121).
+char(1,43122).
+char(0,43123).
+char(5,43124).
+char(8,43125).
+char(p,43126).
+char(2,43127).
+char(2,43128).
+char(5,43129).
+char(0,43130).
+char(c,43131).
+char(c,43132).
+char(p,43133).
+char(7,43134).
+char(4,43135).
+char(3,43136).
+char(2,43137).
+char(m,43138).
+char(3,43139).
+char(6,43140).
+char(7,43141).
+char(9,43142).
+char(m,43143).
+char(o,43144).
+char(m,43145).
+char(o,43146).
+char(5,43147).
+char(2,43148).
+char(2,43149).
+char(7,43150).
+char(c,43151).
+char(c,43152).
+char(m,43153).
+char(o,43154).
+char(p,43155).
+char(o,43156).
+char(p,43157).
+char(o,43158).
+char(o,43159).
+char(o,43160).
+char(p,43161).
+char(o,43162).
+char(m,43163).
+char(5,43164).
+char(7,43165).
+char(1,43166).
+char(4,43167).
+char(p,43168).
+char(7,43169).
+char(2,43170).
+char(2,43171).
+char(3,43172).
+char(m,43173).
+char(1,43174).
+char(1,43175).
+char(1,43176).
+char(3,43177).
+char(c,43178).
+char(c,43179).
+char(p,43180).
+char(o,43181).
+char(m,43182).
+char(o,43183).
+char(p,43184).
+char(o,43185).
+char(p,43186).
+char(o,43187).
+char(7,43188).
+char(5,43189).
+char(7,43190).
+char(m,43191).
+char(9,43192).
+char(6,43193).
+char(5,43194).
+char(1,43195).
+char(c,43196).
+char(c,43197).
+char(c,43198).
+char(m,43199).
+char(3,43200).
+char(5,43201).
+char(1,43202).
+char(2,43203).
+char(p,43204).
+char(1,43205).
+char(4,43206).
+char(8,43207).
+char(c,43208).
+char(c,43209).
+char(m,43210).
+char(3,43211).
+char(2,43212).
+char(4,43213).
+char(2,43214).
+char(p,43215).
+char(o,43216).
+char(4,43217).
+char(9,43218).
+char(0,43219).
+char(8,43220).
+char(c,43221).
+char(c,43222).
+char(m,43223).
+char(8,43224).
+char(6,43225).
+char(1,43226).
+char(4,43227).
+char(m,43228).
+char(o,43229).
+char(p,43230).
+char(o,43231).
+char(o,43232).
+char(p,43233).
+char(5,43234).
+char(0,43235).
+char(8,43236).
+char(6,43237).
+char(p,43238).
+char(8,43239).
+char(8,43240).
+char(7,43241).
+char(8,43242).
+char(m,43243).
+char(2,43244).
+char(8,43245).
+char(5,43246).
+char(0,43247).
+char(c,43248).
+char(p,43249).
+char(o,43250).
+char(o,43251).
+char(7,43252).
+char(5,43253).
+char(5,43254).
+char(8,43255).
+char(m,43256).
+char(o,43257).
+char(1,43258).
+char(6,43259).
+char(0,43260).
+char(0,43261).
+char(c,43262).
+char(c,43263).
+char(m,43264).
+char(8,43265).
+char(3,43266).
+char(1,43267).
+char(7,43268).
+char(p,43269).
+char(8,43270).
+char(8,43271).
+char(4,43272).
+char(5,43273).
+char(p,43274).
+char(o,43275).
+char(o,43276).
+char(m,43277).
+char(1,43278).
+char(7,43279).
+char(2,43280).
+char(4,43281).
+char(m,43282).
+char(o,43283).
+char(p,43284).
+char(o,43285).
+char(o,43286).
+char(p,43287).
+char(o,43288).
+char(9,43289).
+char(4,43290).
+char(8,43291).
+char(p,43292).
+char(o,43293).
+char(6,43294).
+char(1,43295).
+char(0,43296).
+char(2,43297).
+char(c,43298).
+char(c,43299).
+char(m,43300).
+char(o,43301).
+char(2,43302).
+char(7,43303).
+char(6,43304).
+char(c,43305).
+char(m,43306).
+char(o,43307).
+char(m,43308).
+char(5,43309).
+char(0,43310).
+char(8,43311).
+char(7,43312).
+char(c,43313).
+char(c,43314).
+char(m,43315).
+char(o,43316).
+char(p,43317).
+char(o,43318).
+char(4,43319).
+char(0,43320).
+char(8,43321).
+char(9,43322).
+char(c,43323).
+char(m,43324).
+char(o,43325).
+char(p,43326).
+char(7,43327).
+char(1,43328).
+char(7,43329).
+char(7,43330).
+char(c,43331).
+char(c,43332).
+char(m,43333).
+char(o,43334).
+char(p,43335).
+char(6,43336).
+char(0,43337).
+char(0,43338).
+char(7,43339).
+char(c,43340).
+char(m,43341).
+char(7,43342).
+char(3,43343).
+char(7,43344).
+char(3,43345).
+char(p,43346).
+char(o,43347).
+char(4,43348).
+char(9,43349).
+char(7,43350).
+char(7,43351).
+char(m,43352).
+char(o,43353).
+char(p,43354).
+char(o,43355).
+char(m,43356).
+char(3,43357).
+char(1,43358).
+char(9,43359).
+char(p,43360).
+char(o,43361).
+char(o,43362).
+char(8,43363).
+char(8,43364).
+char(8,43365).
+char(c,43366).
+char(c,43367).
+char(p,43368).
+char(o,43369).
+char(p,43370).
+char(o,43371).
+char(m,43372).
+char(o,43373).
+char(p,43374).
+char(7,43375).
+char(0,43376).
+char(7,43377).
+char(2,43378).
+char(c,43379).
+char(c,43380).
+char(p,43381).
+char(6,43382).
+char(3,43383).
+char(6,43384).
+char(4,43385).
+char(c,43386).
+char(c,43387).
+char(c,43388).
+char(p,43389).
+char(1,43390).
+char(2,43391).
+char(6,43392).
+char(0,43393).
+char(c,43394).
+char(m,43395).
+char(o,43396).
+char(p,43397).
+char(5,43398).
+char(0,43399).
+char(7,43400).
+char(0,43401).
+char(c,43402).
+char(m,43403).
+char(7,43404).
+char(1,43405).
+char(4,43406).
+char(1,43407).
+char(p,43408).
+char(8,43409).
+char(7,43410).
+char(5,43411).
+char(9,43412).
+char(p,43413).
+char(o,43414).
+char(m,43415).
+char(o,43416).
+char(o,43417).
+char(o,43418).
+char(p,43419).
+char(3,43420).
+char(2,43421).
+char(6,43422).
+char(2,43423).
+char(c,43424).
+char(m,43425).
+char(8,43426).
+char(4,43427).
+char(0,43428).
+char(6,43429).
+char(m,43430).
+char(3,43431).
+char(6,43432).
+char(8,43433).
+char(4,43434).
+char(m,43435).
+char(o,43436).
+char(m,43437).
+char(5,43438).
+char(3,43439).
+char(3,43440).
+char(4,43441).
+char(c,43442).
+char(m,43443).
+char(4,43444).
+char(3,43445).
+char(9,43446).
+char(5,43447).
+char(c,43448).
+char(p,43449).
+char(8,43450).
+char(1,43451).
+char(8,43452).
+char(5,43453).
+char(m,43454).
+char(o,43455).
+char(5,43456).
+char(6,43457).
+char(7,43458).
+char(7,43459).
+char(c,43460).
+char(c,43461).
+char(p,43462).
+char(o,43463).
+char(m,43464).
+char(o,43465).
+char(p,43466).
+char(o,43467).
+char(m,43468).
+char(o,43469).
+char(m,43470).
+char(o,43471).
+char(o,43472).
+char(m,43473).
+char(o,43474).
+char(p,43475).
+char(o,43476).
+char(o,43477).
+char(o,43478).
+char(m,43479).
+char(8,43480).
+char(2,43481).
+char(5,43482).
+char(9,43483).
+char(p,43484).
+char(2,43485).
+char(7,43486).
+char(6,43487).
+char(7,43488).
+char(c,43489).
+char(m,43490).
+char(6,43491).
+char(6,43492).
+char(6,43493).
+char(8,43494).
+char(m,43495).
+char(8,43496).
+char(0,43497).
+char(1,43498).
+char(3,43499).
+char(c,43500).
+char(c,43501).
+char(c,43502).
+char(c,43503).
+char(m,43504).
+char(4,43505).
+char(5,43506).
+char(8,43507).
+char(4,43508).
+char(p,43509).
+char(o,43510).
+char(p,43511).
+char(o,43512).
+char(6,43513).
+char(2,43514).
+char(3,43515).
+char(9,43516).
+char(p,43517).
+char(8,43518).
+char(9,43519).
+char(0,43520).
+char(2,43521).
+char(c,43522).
+char(p,43523).
+char(o,43524).
+char(m,43525).
+char(o,43526).
+char(p,43527).
+char(o,43528).
+char(m,43529).
+char(6,43530).
+char(4,43531).
+char(7,43532).
+char(6,43533).
+char(c,43534).
+char(p,43535).
+char(o,43536).
+char(4,43537).
+char(6,43538).
+char(3,43539).
+char(p,43540).
+char(o,43541).
+char(m,43542).
+char(o,43543).
+char(9,43544).
+char(1,43545).
+char(3,43546).
+char(3,43547).
+char(m,43548).
+char(o,43549).
+char(p,43550).
+char(2,43551).
+char(3,43552).
+char(9,43553).
+char(2,43554).
+char(c,43555).
+char(m,43556).
+char(o,43557).
+char(o,43558).
+char(p,43559).
+char(2,43560).
+char(9,43561).
+char(6,43562).
+char(c,43563).
+char(c,43564).
+char(m,43565).
+char(2,43566).
+char(8,43567).
+char(9,43568).
+char(0,43569).
+char(p,43570).
+char(o,43571).
+char(o,43572).
+char(p,43573).
+char(o,43574).
+char(m,43575).
+char(o,43576).
+char(m,43577).
+char(7,43578).
+char(3,43579).
+char(0,43580).
+char(4,43581).
+char(c,43582).
+char(m,43583).
+char(o,43584).
+char(p,43585).
+char(o,43586).
+char(m,43587).
+char(9,43588).
+char(8,43589).
+char(1,43590).
+char(2,43591).
+char(m,43592).
+char(o,43593).
+char(6,43594).
+char(1,43595).
+char(7,43596).
+char(7,43597).
+char(c,43598).
+char(c,43599).
+char(p,43600).
+char(3,43601).
+char(3,43602).
+char(8,43603).
+char(1,43604).
+char(m,43605).
+char(8,43606).
+char(2,43607).
+char(7,43608).
+char(2,43609).
+char(c,43610).
+char(c,43611).
+char(c,43612).
+char(m,43613).
+char(o,43614).
+char(2,43615).
+char(3,43616).
+char(4,43617).
+char(2,43618).
+char(c,43619).
+char(c,43620).
+char(p,43621).
+char(o,43622).
+char(m,43623).
+char(o,43624).
+char(1,43625).
+char(5,43626).
+char(2,43627).
+char(2,43628).
+char(c,43629).
+char(p,43630).
+char(6,43631).
+char(9,43632).
+char(4,43633).
+char(1,43634).
+char(c,43635).
+char(c,43636).
+char(c,43637).
+char(m,43638).
+char(o,43639).
+char(p,43640).
+char(o,43641).
+char(m,43642).
+char(o,43643).
+char(m,43644).
+char(1,43645).
+char(6,43646).
+char(4,43647).
+char(8,43648).
+char(c,43649).
+char(c,43650).
+char(c,43651).
+char(p,43652).
+char(o,43653).
+char(m,43654).
+char(o,43655).
+char(p,43656).
+char(5,43657).
+char(6,43658).
+char(8,43659).
+char(1,43660).
+char(p,43661).
+char(o,43662).
+char(m,43663).
+char(3,43664).
+char(9,43665).
+char(6,43666).
+char(5,43667).
+char(c,43668).
+char(c,43669).
+char(c,43670).
+char(m,43671).
+char(3,43672).
+char(6,43673).
+char(0,43674).
+char(1,43675).
+char(c,43676).
+char(c,43677).
+char(p,43678).
+char(o,43679).
+char(o,43680).
+char(m,43681).
+char(o,43682).
+char(o,43683).
+char(m,43684).
+char(o,43685).
+char(m,43686).
+char(3,43687).
+char(8,43688).
+char(4,43689).
+char(8,43690).
+char(c,43691).
+char(c,43692).
+char(c,43693).
+char(m,43694).
+char(4,43695).
+char(7,43696).
+char(0,43697).
+char(4,43698).
+char(c,43699).
+char(p,43700).
+char(8,43701).
+char(7,43702).
+char(3,43703).
+char(2,43704).
+char(c,43705).
+char(m,43706).
+char(6,43707).
+char(7,43708).
+char(1,43709).
+char(4,43710).
+char(m,43711).
+char(o,43712).
+char(p,43713).
+char(7,43714).
+char(3,43715).
+char(0,43716).
+char(3,43717).
+char(p,43718).
+char(5,43719).
+char(6,43720).
+char(c,43721).
+char(p,43722).
+char(2,43723).
+char(1,43724).
+char(2,43725).
+char(4,43726).
+char(c,43727).
+char(c,43728).
+char(p,43729).
+char(o,43730).
+char(p,43731).
+char(o,43732).
+char(m,43733).
+char(o,43734).
+char(6,43735).
+char(7,43736).
+char(9,43737).
+char(0,43738).
+char(c,43739).
+char(p,43740).
+char(o,43741).
+char(p,43742).
+char(o,43743).
+char(p,43744).
+char(8,43745).
+char(6,43746).
+char(9,43747).
+char(6,43748).
+char(p,43749).
+char(o,43750).
+char(p,43751).
+char(o,43752).
+char(p,43753).
+char(o,43754).
+char(o,43755).
+char(6,43756).
+char(8,43757).
+char(7,43758).
+char(0,43759).
+char(m,43760).
+char(2,43761).
+char(0,43762).
+char(4,43763).
+char(4,43764).
+char(p,43765).
+char(7,43766).
+char(6,43767).
+char(7,43768).
+char(0,43769).
+char(p,43770).
+char(7,43771).
+char(0,43772).
+char(3,43773).
+char(9,43774).
+char(m,43775).
+char(6,43776).
+char(6,43777).
+char(1,43778).
+char(5,43779).
+char(m,43780).
+char(o,43781).
+char(m,43782).
+char(5,43783).
+char(4,43784).
+char(3,43785).
+char(7,43786).
+char(m,43787).
+char(o,43788).
+char(o,43789).
+char(p,43790).
+char(o,43791).
+char(o,43792).
+char(m,43793).
+char(o,43794).
+char(p,43795).
+char(4,43796).
+char(7,43797).
+char(4,43798).
+char(7,43799).
+char(c,43800).
+char(m,43801).
+char(o,43802).
+char(p,43803).
+char(o,43804).
+char(7,43805).
+char(9,43806).
+char(8,43807).
+char(4,43808).
+char(c,43809).
+char(m,43810).
+char(o,43811).
+char(p,43812).
+char(o,43813).
+char(p,43814).
+char(o,43815).
+char(m,43816).
+char(o,43817).
+char(o,43818).
+char(3,43819).
+char(9,43820).
+char(5,43821).
+char(0,43822).
+char(p,43823).
+char(o,43824).
+char(m,43825).
+char(o,43826).
+char(p,43827).
+char(4,43828).
+char(8,43829).
+char(0,43830).
+char(8,43831).
+char(m,43832).
+char(o,43833).
+char(p,43834).
+char(5,43835).
+char(9,43836).
+char(8,43837).
+char(8,43838).
+char(m,43839).
+char(3,43840).
+char(0,43841).
+char(0,43842).
+char(c,43843).
+char(c,43844).
+char(p,43845).
+char(o,43846).
+char(p,43847).
+char(o,43848).
+char(p,43849).
+char(o,43850).
+char(p,43851).
+char(o,43852).
+char(9,43853).
+char(0,43854).
+char(4,43855).
+char(7,43856).
+char(c,43857).
+char(m,43858).
+char(o,43859).
+char(p,43860).
+char(o,43861).
+char(m,43862).
+char(o,43863).
+char(p,43864).
+char(o,43865).
+char(p,43866).
+char(o,43867).
+char(m,43868).
+char(o,43869).
+char(p,43870).
+char(o,43871).
+char(m,43872).
+char(o,43873).
+char(o,43874).
+char(p,43875).
+char(3,43876).
+char(8,43877).
+char(6,43878).
+char(2,43879).
+char(c,43880).
+char(c,43881).
+char(p,43882).
+char(o,43883).
+char(4,43884).
+char(5,43885).
+char(5,43886).
+char(0,43887).
+char(m,43888).
+char(2,43889).
+char(0,43890).
+char(0,43891).
+char(1,43892).
+char(m,43893).
+char(2,43894).
+char(3,43895).
+char(3,43896).
+char(3,43897).
+char(p,43898).
+char(o,43899).
+char(p,43900).
+char(o,43901).
+char(2,43902).
+char(5,43903).
+char(0,43904).
+char(c,43905).
+char(m,43906).
+char(o,43907).
+char(o,43908).
+char(p,43909).
+char(o,43910).
+char(o,43911).
+char(6,43912).
+char(3,43913).
+char(2,43914).
+char(8,43915).
+char(p,43916).
+char(o,43917).
+char(3,43918).
+char(5,43919).
+char(6,43920).
+char(6,43921).
+char(p,43922).
+char(o,43923).
+char(p,43924).
+char(9,43925).
+char(6,43926).
+char(8,43927).
+char(5,43928).
+char(p,43929).
+char(o,43930).
+char(o,43931).
+char(p,43932).
+char(o,43933).
+char(m,43934).
+char(o,43935).
+char(p,43936).
+char(3,43937).
+char(8,43938).
+char(2,43939).
+char(5,43940).
+char(p,43941).
+char(1,43942).
+char(3,43943).
+char(6,43944).
+char(2,43945).
+char(c,43946).
+char(p,43947).
+char(1,43948).
+char(5,43949).
+char(7,43950).
+char(c,43951).
+char(c,43952).
+char(p,43953).
+char(9,43954).
+char(2,43955).
+char(1,43956).
+char(1,43957).
+char(m,43958).
+char(7,43959).
+char(5,43960).
+char(4,43961).
+char(8,43962).
+char(c,43963).
+char(c,43964).
+char(c,43965).
+char(c,43966).
+char(m,43967).
+char(1,43968).
+char(5,43969).
+char(2,43970).
+char(0,43971).
+char(p,43972).
+char(3,43973).
+char(7,43974).
+char(3,43975).
+char(7,43976).
+char(c,43977).
+char(p,43978).
+char(o,43979).
+char(p,43980).
+char(7,43981).
+char(4,43982).
+char(8,43983).
+char(9,43984).
+char(c,43985).
+char(m,43986).
+char(o,43987).
+char(p,43988).
+char(3,43989).
+char(2,43990).
+char(6,43991).
+char(8,43992).
+char(m,43993).
+char(9,43994).
+char(1,43995).
+char(2,43996).
+char(1,43997).
+char(m,43998).
+char(o,43999).
+char(o,44000).
+char(m,44001).
+char(o,44002).
+char(m,44003).
+char(7,44004).
+char(9,44005).
+char(5,44006).
+char(3,44007).
+char(c,44008).
+char(c,44009).
+char(c,44010).
+char(p,44011).
+char(2,44012).
+char(7,44013).
+char(0,44014).
+char(3,44015).
+char(m,44016).
+char(o,44017).
+char(o,44018).
+char(p,44019).
+char(6,44020).
+char(7,44021).
+char(3,44022).
+char(3,44023).
+char(c,44024).
+char(m,44025).
+char(8,44026).
+char(2,44027).
+char(8,44028).
+char(0,44029).
+char(m,44030).
+char(9,44031).
+char(4,44032).
+char(4,44033).
+char(2,44034).
+char(p,44035).
+char(3,44036).
+char(1,44037).
+char(5,44038).
+char(6,44039).
+char(c,44040).
+char(p,44041).
+char(o,44042).
+char(p,44043).
+char(1,44044).
+char(2,44045).
+char(4,44046).
+char(c,44047).
+char(c,44048).
+char(m,44049).
+char(o,44050).
+char(m,44051).
+char(7,44052).
+char(7,44053).
+char(9,44054).
+char(p,44055).
+char(o,44056).
+char(m,44057).
+char(o,44058).
+char(p,44059).
+char(o,44060).
+char(m,44061).
+char(o,44062).
+char(p,44063).
+char(o,44064).
+char(p,44065).
+char(o,44066).
+char(8,44067).
+char(3,44068).
+char(4,44069).
+char(4,44070).
+char(c,44071).
+char(p,44072).
+char(9,44073).
+char(2,44074).
+char(4,44075).
+char(3,44076).
+char(c,44077).
+char(m,44078).
+char(3,44079).
+char(1,44080).
+char(5,44081).
+char(0,44082).
+char(c,44083).
+char(m,44084).
+char(9,44085).
+char(5,44086).
+char(5,44087).
+char(8,44088).
+char(c,44089).
+char(c,44090).
+char(p,44091).
+char(o,44092).
+char(o,44093).
+char(o,44094).
+char(p,44095).
+char(1,44096).
+char(0,44097).
+char(5,44098).
+char(4,44099).
+char(c,44100).
+char(p,44101).
+char(o,44102).
+char(p,44103).
+char(o,44104).
+char(m,44105).
+char(1,44106).
+char(3,44107).
+char(7,44108).
+char(0,44109).
+char(p,44110).
+char(o,44111).
+char(o,44112).
+char(6,44113).
+char(9,44114).
+char(3,44115).
+char(0,44116).
+char(c,44117).
+char(c,44118).
+char(c,44119).
+char(c,44120).
+char(p,44121).
+char(7,44122).
+char(7,44123).
+char(2,44124).
+char(4,44125).
+char(c,44126).
+char(m,44127).
+char(7,44128).
+char(7,44129).
+char(0,44130).
+char(c,44131).
+char(p,44132).
+char(7,44133).
+char(3,44134).
+char(4,44135).
+char(3,44136).
+char(c,44137).
+char(m,44138).
+char(8,44139).
+char(2,44140).
+char(7,44141).
+char(5,44142).
+char(m,44143).
+char(3,44144).
+char(5,44145).
+char(4,44146).
+char(6,44147).
+char(c,44148).
+char(m,44149).
+char(o,44150).
+char(p,44151).
+char(o,44152).
+char(p,44153).
+char(3,44154).
+char(8,44155).
+char(0,44156).
+char(8,44157).
+char(c,44158).
+char(c,44159).
+char(m,44160).
+char(o,44161).
+char(p,44162).
+char(o,44163).
+char(p,44164).
+char(5,44165).
+char(8,44166).
+char(7,44167).
+char(4,44168).
+char(m,44169).
+char(6,44170).
+char(2,44171).
+char(5,44172).
+char(1,44173).
+char(c,44174).
+char(c,44175).
+char(p,44176).
+char(o,44177).
+char(9,44178).
+char(5,44179).
+char(7,44180).
+char(6,44181).
+char(c,44182).
+char(m,44183).
+char(o,44184).
+char(m,44185).
+char(9,44186).
+char(6,44187).
+char(8,44188).
+char(8,44189).
+char(m,44190).
+char(o,44191).
+char(p,44192).
+char(8,44193).
+char(8,44194).
+char(6,44195).
+char(6,44196).
+char(m,44197).
+char(6,44198).
+char(7,44199).
+char(3,44200).
+char(c,44201).
+char(c,44202).
+char(m,44203).
+char(o,44204).
+char(o,44205).
+char(p,44206).
+char(3,44207).
+char(3,44208).
+char(0,44209).
+char(6,44210).
+char(c,44211).
+char(c,44212).
+char(m,44213).
+char(1,44214).
+char(0,44215).
+char(7,44216).
+char(m,44217).
+char(o,44218).
+char(p,44219).
+char(7,44220).
+char(1,44221).
+char(6,44222).
+char(0,44223).
+char(m,44224).
+char(o,44225).
+char(o,44226).
+char(o,44227).
+char(1,44228).
+char(5,44229).
+char(9,44230).
+char(c,44231).
+char(c,44232).
+char(c,44233).
+char(c,44234).
+char(c,44235).
+char(c,44236).
+char(m,44237).
+char(7,44238).
+char(3,44239).
+char(5,44240).
+char(2,44241).
+char(c,44242).
+char(c,44243).
+char(m,44244).
+char(o,44245).
+char(o,44246).
+char(o,44247).
+char(p,44248).
+char(5,44249).
+char(6,44250).
+char(7,44251).
+char(2,44252).
+char(m,44253).
+char(o,44254).
+char(m,44255).
+char(o,44256).
+char(p,44257).
+char(o,44258).
+char(p,44259).
+char(o,44260).
+char(p,44261).
+char(o,44262).
+char(m,44263).
+char(6,44264).
+char(0,44265).
+char(8,44266).
+char(2,44267).
+char(c,44268).
+char(m,44269).
+char(3,44270).
+char(8,44271).
+char(0,44272).
+char(5,44273).
+char(m,44274).
+char(o,44275).
+char(p,44276).
+char(2,44277).
+char(7,44278).
+char(2,44279).
+char(4,44280).
+char(c,44281).
+char(p,44282).
+char(1,44283).
+char(6,44284).
+char(0,44285).
+char(6,44286).
+char(c,44287).
+char(p,44288).
+char(o,44289).
+char(5,44290).
+char(4,44291).
+char(1,44292).
+char(0,44293).
+char(c,44294).
+char(m,44295).
+char(5,44296).
+char(7,44297).
+char(1,44298).
+char(6,44299).
+char(c,44300).
+char(c,44301).
+char(c,44302).
+char(p,44303).
+char(o,44304).
+char(p,44305).
+char(9,44306).
+char(2,44307).
+char(1,44308).
+char(1,44309).
+char(c,44310).
+char(p,44311).
+char(o,44312).
+char(p,44313).
+char(o,44314).
+char(m,44315).
+char(o,44316).
+char(o,44317).
+char(4,44318).
+char(7,44319).
+char(6,44320).
+char(5,44321).
+char(c,44322).
+char(p,44323).
+char(o,44324).
+char(m,44325).
+char(o,44326).
+char(p,44327).
+char(1,44328).
+char(5,44329).
+char(6,44330).
+char(1,44331).
+char(m,44332).
+char(o,44333).
+char(m,44334).
+char(5,44335).
+char(2,44336).
+char(2,44337).
+char(7,44338).
+char(p,44339).
+char(2,44340).
+char(4,44341).
+char(7,44342).
+char(5,44343).
+char(m,44344).
+char(1,44345).
+char(0,44346).
+char(6,44347).
+char(5,44348).
+char(c,44349).
+char(m,44350).
+char(6,44351).
+char(7,44352).
+char(5,44353).
+char(c,44354).
+char(c,44355).
+char(c,44356).
+char(m,44357).
+char(o,44358).
+char(p,44359).
+char(2,44360).
+char(7,44361).
+char(5,44362).
+char(p,44363).
+char(o,44364).
+char(m,44365).
+char(o,44366).
+char(p,44367).
+char(o,44368).
+char(o,44369).
+char(o,44370).
+char(m,44371).
+char(5,44372).
+char(4,44373).
+char(2,44374).
+char(0,44375).
+char(p,44376).
+char(3,44377).
+char(0,44378).
+char(7,44379).
+char(c,44380).
+char(m,44381).
+char(7,44382).
+char(1,44383).
+char(9,44384).
+char(4,44385).
+char(m,44386).
+char(o,44387).
+char(p,44388).
+char(7,44389).
+char(7,44390).
+char(3,44391).
+char(8,44392).
+char(p,44393).
+char(6,44394).
+char(3,44395).
+char(6,44396).
+char(m,44397).
+char(o,44398).
+char(p,44399).
+char(o,44400).
+char(p,44401).
+char(7,44402).
+char(8,44403).
+char(4,44404).
+char(3,44405).
+char(c,44406).
+char(c,44407).
+char(c,44408).
+char(c,44409).
+char(m,44410).
+char(o,44411).
+char(6,44412).
+char(1,44413).
+char(3,44414).
+char(1,44415).
+char(m,44416).
+char(o,44417).
+char(m,44418).
+char(9,44419).
+char(3,44420).
+char(9,44421).
+char(1,44422).
+char(c,44423).
+char(c,44424).
+char(m,44425).
+char(o,44426).
+char(1,44427).
+char(6,44428).
+char(4,44429).
+char(3,44430).
+char(c,44431).
+char(c,44432).
+char(p,44433).
+char(o,44434).
+char(p,44435).
+char(2,44436).
+char(0,44437).
+char(8,44438).
+char(2,44439).
+char(c,44440).
+char(c,44441).
+char(p,44442).
+char(o,44443).
+char(m,44444).
+char(o,44445).
+char(p,44446).
+char(8,44447).
+char(5,44448).
+char(1,44449).
+char(6,44450).
+char(c,44451).
+char(p,44452).
+char(o,44453).
+char(p,44454).
+char(o,44455).
+char(p,44456).
+char(5,44457).
+char(1,44458).
+char(2,44459).
+char(6,44460).
+char(m,44461).
+char(4,44462).
+char(7,44463).
+char(4,44464).
+char(7,44465).
+char(p,44466).
+char(2,44467).
+char(2,44468).
+char(8,44469).
+char(9,44470).
+char(p,44471).
+char(5,44472).
+char(7,44473).
+char(9,44474).
+char(7,44475).
+char(m,44476).
+char(o,44477).
+char(o,44478).
+char(o,44479).
+char(1,44480).
+char(1,44481).
+char(8,44482).
+char(m,44483).
+char(9,44484).
+char(5,44485).
+char(9,44486).
+char(3,44487).
+char(m,44488).
+char(7,44489).
+char(1,44490).
+char(7,44491).
+char(c,44492).
+char(c,44493).
+char(p,44494).
+char(4,44495).
+char(2,44496).
+char(9,44497).
+char(2,44498).
+char(p,44499).
+char(o,44500).
+char(o,44501).
+char(m,44502).
+char(5,44503).
+char(9,44504).
+char(5,44505).
+char(4,44506).
+char(m,44507).
+char(7,44508).
+char(9,44509).
+char(3,44510).
+char(7,44511).
+char(c,44512).
+char(c,44513).
+char(c,44514).
+char(c,44515).
+char(p,44516).
+char(8,44517).
+char(8,44518).
+char(3,44519).
+char(9,44520).
+char(c,44521).
+char(m,44522).
+char(o,44523).
+char(p,44524).
+char(o,44525).
+char(m,44526).
+char(o,44527).
+char(o,44528).
+char(p,44529).
+char(3,44530).
+char(4,44531).
+char(2,44532).
+char(7,44533).
+char(m,44534).
+char(8,44535).
+char(8,44536).
+char(7,44537).
+char(0,44538).
+char(p,44539).
+char(7,44540).
+char(5,44541).
+char(3,44542).
+char(5,44543).
+char(m,44544).
+char(8,44545).
+char(7,44546).
+char(2,44547).
+char(4,44548).
+char(m,44549).
+char(o,44550).
+char(m,44551).
+char(3,44552).
+char(4,44553).
+char(4,44554).
+char(7,44555).
+char(p,44556).
+char(2,44557).
+char(8,44558).
+char(7,44559).
+char(5,44560).
+char(p,44561).
+char(2,44562).
+char(1,44563).
+char(7,44564).
+char(6,44565).
+char(c,44566).
+char(m,44567).
+char(o,44568).
+char(o,44569).
+char(p,44570).
+char(o,44571).
+char(p,44572).
+char(o,44573).
+char(4,44574).
+char(5,44575).
+char(2,44576).
+char(3,44577).
+char(p,44578).
+char(9,44579).
+char(8,44580).
+char(1,44581).
+char(5,44582).
+char(p,44583).
+char(2,44584).
+char(4,44585).
+char(8,44586).
+char(4,44587).
+char(c,44588).
+char(m,44589).
+char(3,44590).
+char(4,44591).
+char(4,44592).
+char(4,44593).
+char(c,44594).
+char(m,44595).
+char(2,44596).
+char(5,44597).
+char(2,44598).
+char(5,44599).
+char(p,44600).
+char(3,44601).
+char(1,44602).
+char(8,44603).
+char(9,44604).
+char(c,44605).
+char(c,44606).
+char(c,44607).
+char(m,44608).
+char(o,44609).
+char(4,44610).
+char(0,44611).
+char(9,44612).
+char(2,44613).
+char(m,44614).
+char(o,44615).
+char(3,44616).
+char(1,44617).
+char(0,44618).
+char(6,44619).
+char(m,44620).
+char(o,44621).
+char(p,44622).
+char(2,44623).
+char(9,44624).
+char(8,44625).
+char(9,44626).
+char(m,44627).
+char(4,44628).
+char(8,44629).
+char(3,44630).
+char(2,44631).
+char(p,44632).
+char(9,44633).
+char(6,44634).
+char(6,44635).
+char(4,44636).
+char(m,44637).
+char(5,44638).
+char(5,44639).
+char(7,44640).
+char(1,44641).
+char(c,44642).
+char(m,44643).
+char(o,44644).
+char(8,44645).
+char(7,44646).
+char(c,44647).
+char(p,44648).
+char(o,44649).
+char(p,44650).
+char(o,44651).
+char(o,44652).
+char(p,44653).
+char(2,44654).
+char(1,44655).
+char(4,44656).
+char(9,44657).
+char(c,44658).
+char(p,44659).
+char(9,44660).
+char(6,44661).
+char(5,44662).
+char(7,44663).
+char(m,44664).
+char(o,44665).
+char(o,44666).
+char(m,44667).
+char(7,44668).
+char(9,44669).
+char(4,44670).
+char(9,44671).
+char(p,44672).
+char(o,44673).
+char(p,44674).
+char(4,44675).
+char(6,44676).
+char(9,44677).
+char(1,44678).
+char(c,44679).
+char(p,44680).
+char(o,44681).
+char(9,44682).
+char(8,44683).
+char(2,44684).
+char(3,44685).
+char(m,44686).
+char(8,44687).
+char(5,44688).
+char(5,44689).
+char(2,44690).
+char(c,44691).
+char(m,44692).
+char(6,44693).
+char(6,44694).
+char(1,44695).
+char(c,44696).
+char(c,44697).
+char(m,44698).
+char(7,44699).
+char(6,44700).
+char(1,44701).
+char(6,44702).
+char(m,44703).
+char(o,44704).
+char(o,44705).
+char(8,44706).
+char(6,44707).
+char(4,44708).
+char(8,44709).
+char(c,44710).
+char(p,44711).
+char(o,44712).
+char(8,44713).
+char(5,44714).
+char(1,44715).
+char(9,44716).
+char(p,44717).
+char(o,44718).
+char(m,44719).
+char(o,44720).
+char(p,44721).
+char(8,44722).
+char(7,44723).
+char(8,44724).
+char(9,44725).
+char(c,44726).
+char(c,44727).
+char(c,44728).
+char(c,44729).
+char(c,44730).
+char(m,44731).
+char(3,44732).
+char(1,44733).
+char(3,44734).
+char(c,44735).
+char(c,44736).
+char(m,44737).
+char(o,44738).
+char(p,44739).
+char(o,44740).
+char(p,44741).
+char(9,44742).
+char(6,44743).
+char(4,44744).
+char(6,44745).
+char(c,44746).
+char(m,44747).
+char(o,44748).
+char(m,44749).
+char(o,44750).
+char(p,44751).
+char(4,44752).
+char(6,44753).
+char(4,44754).
+char(2,44755).
+char(c,44756).
+char(m,44757).
+char(6,44758).
+char(4,44759).
+char(6,44760).
+char(2,44761).
+char(c,44762).
+char(p,44763).
+char(8,44764).
+char(7,44765).
+char(2,44766).
+char(5,44767).
+char(c,44768).
+char(c,44769).
+char(m,44770).
+char(2,44771).
+char(9,44772).
+char(5,44773).
+char(5,44774).
+char(p,44775).
+char(o,44776).
+char(p,44777).
+char(5,44778).
+char(7,44779).
+char(4,44780).
+char(7,44781).
+char(c,44782).
+char(p,44783).
+char(o,44784).
+char(p,44785).
+char(o,44786).
+char(p,44787).
+char(o,44788).
+char(m,44789).
+char(o,44790).
+char(m,44791).
+char(2,44792).
+char(2,44793).
+char(5,44794).
+char(4,44795).
+char(c,44796).
+char(m,44797).
+char(o,44798).
+char(o,44799).
+char(2,44800).
+char(0,44801).
+char(2,44802).
+char(1,44803).
+char(m,44804).
+char(o,44805).
+char(p,44806).
+char(o,44807).
+char(p,44808).
+char(4,44809).
+char(3,44810).
+char(8,44811).
+char(3,44812).
+char(c,44813).
+char(p,44814).
+char(o,44815).
+char(p,44816).
+char(o,44817).
+char(p,44818).
+char(o,44819).
+char(o,44820).
+char(p,44821).
+char(2,44822).
+char(9,44823).
+char(7,44824).
+char(4,44825).
+char(c,44826).
+char(p,44827).
+char(o,44828).
+char(m,44829).
+char(9,44830).
+char(9,44831).
+char(6,44832).
+char(6,44833).
+char(c,44834).
+char(c,44835).
+char(c,44836).
+char(c,44837).
+char(p,44838).
+char(4,44839).
+char(9,44840).
+char(8,44841).
+char(6,44842).
+char(c,44843).
+char(p,44844).
+char(o,44845).
+char(7,44846).
+char(9,44847).
+char(9,44848).
+char(2,44849).
+char(c,44850).
+char(c,44851).
+char(c,44852).
+char(c,44853).
+char(c,44854).
+char(p,44855).
+char(o,44856).
+char(8,44857).
+char(2,44858).
+char(4,44859).
+char(c,44860).
+char(c,44861).
+char(c,44862).
+char(c,44863).
+char(c,44864).
+char(c,44865).
+char(c,44866).
+char(p,44867).
+char(6,44868).
+char(5,44869).
+char(1,44870).
+char(3,44871).
+char(c,44872).
+char(c,44873).
+char(c,44874).
+char(c,44875).
+char(p,44876).
+char(o,44877).
+char(m,44878).
+char(o,44879).
+char(p,44880).
+char(o,44881).
+char(4,44882).
+char(5,44883).
+char(7,44884).
+char(5,44885).
+char(c,44886).
+char(p,44887).
+char(6,44888).
+char(1,44889).
+char(3,44890).
+char(p,44891).
+char(o,44892).
+char(p,44893).
+char(1,44894).
+char(5,44895).
+char(6,44896).
+char(7,44897).
+char(c,44898).
+char(m,44899).
+char(o,44900).
+char(m,44901).
+char(3,44902).
+char(2,44903).
+char(3,44904).
+char(5,44905).
+char(c,44906).
+char(c,44907).
+char(c,44908).
+char(m,44909).
+char(o,44910).
+char(p,44911).
+char(3,44912).
+char(6,44913).
+char(7,44914).
+char(5,44915).
+char(m,44916).
+char(o,44917).
+char(p,44918).
+char(o,44919).
+char(9,44920).
+char(5,44921).
+char(5,44922).
+char(2,44923).
+char(p,44924).
+char(6,44925).
+char(5,44926).
+char(5,44927).
+char(1,44928).
+char(p,44929).
+char(3,44930).
+char(8,44931).
+char(8,44932).
+char(5,44933).
+char(p,44934).
+char(5,44935).
+char(9,44936).
+char(4,44937).
+char(c,44938).
+char(c,44939).
+char(m,44940).
+char(o,44941).
+char(m,44942).
+char(7,44943).
+char(0,44944).
+char(9,44945).
+char(5,44946).
+char(c,44947).
+char(c,44948).
+char(p,44949).
+char(8,44950).
+char(1,44951).
+char(9,44952).
+char(c,44953).
+char(m,44954).
+char(o,44955).
+char(p,44956).
+char(o,44957).
+char(p,44958).
+char(4,44959).
+char(9,44960).
+char(5,44961).
+char(5,44962).
+char(m,44963).
+char(o,44964).
+char(m,44965).
+char(6,44966).
+char(2,44967).
+char(2,44968).
+char(5,44969).
+char(m,44970).
+char(6,44971).
+char(0,44972).
+char(0,44973).
+char(2,44974).
+char(c,44975).
+char(c,44976).
+char(c,44977).
+char(c,44978).
+char(p,44979).
+char(7,44980).
+char(2,44981).
+char(6,44982).
+char(5,44983).
+char(p,44984).
+char(o,44985).
+char(p,44986).
+char(5,44987).
+char(7,44988).
+char(2,44989).
+char(5,44990).
+char(c,44991).
+char(m,44992).
+char(o,44993).
+char(o,44994).
+char(m,44995).
+char(o,44996).
+char(2,44997).
+char(2,44998).
+char(7,44999).
+char(9,45000).
+char(m,45001).
+char(o,45002).
+char(m,45003).
+char(3,45004).
+char(5,45005).
+char(5,45006).
+char(6,45007).
+char(c,45008).
+char(c,45009).
+char(p,45010).
+char(1,45011).
+char(0,45012).
+char(0,45013).
+char(6,45014).
+char(c,45015).
+char(c,45016).
+char(c,45017).
+char(m,45018).
+char(o,45019).
+char(4,45020).
+char(8,45021).
+char(6,45022).
+char(8,45023).
+char(c,45024).
+char(c,45025).
+char(p,45026).
+char(5,45027).
+char(0,45028).
+char(6,45029).
+char(c,45030).
+char(c,45031).
+char(m,45032).
+char(1,45033).
+char(0,45034).
+char(4,45035).
+char(3,45036).
+char(c,45037).
+char(p,45038).
+char(o,45039).
+char(m,45040).
+char(2,45041).
+char(4,45042).
+char(6,45043).
+char(8,45044).
+char(m,45045).
+char(o,45046).
+char(8,45047).
+char(1,45048).
+char(4,45049).
+char(9,45050).
+char(c,45051).
+char(m,45052).
+char(3,45053).
+char(1,45054).
+char(6,45055).
+char(3,45056).
+char(c,45057).
+char(c,45058).
+char(p,45059).
+char(o,45060).
+char(m,45061).
+char(o,45062).
+char(4,45063).
+char(1,45064).
+char(9,45065).
+char(3,45066).
+char(p,45067).
+char(4,45068).
+char(6,45069).
+char(1,45070).
+char(4,45071).
+char(c,45072).
+char(c,45073).
+char(c,45074).
+char(c,45075).
+char(p,45076).
+char(o,45077).
+char(p,45078).
+char(o,45079).
+char(o,45080).
+char(p,45081).
+char(o,45082).
+char(o,45083).
+char(o,45084).
+char(m,45085).
+char(1,45086).
+char(9,45087).
+char(7,45088).
+char(c,45089).
+char(m,45090).
+char(o,45091).
+char(m,45092).
+char(5,45093).
+char(0,45094).
+char(4,45095).
+char(4,45096).
+char(m,45097).
+char(o,45098).
+char(p,45099).
+char(o,45100).
+char(p,45101).
+char(o,45102).
+char(m,45103).
+char(o,45104).
+char(p,45105).
+char(o,45106).
+char(o,45107).
+char(p,45108).
+char(o,45109).
+char(m,45110).
+char(o,45111).
+char(p,45112).
+char(o,45113).
+char(o,45114).
+char(m,45115).
+char(3,45116).
+char(0,45117).
+char(3,45118).
+char(p,45119).
+char(2,45120).
+char(3,45121).
+char(0,45122).
+char(8,45123).
+char(m,45124).
+char(o,45125).
+char(o,45126).
+char(m,45127).
+char(3,45128).
+char(7,45129).
+char(0,45130).
+char(3,45131).
+char(c,45132).
+char(p,45133).
+char(6,45134).
+char(9,45135).
+char(0,45136).
+char(c,45137).
+char(c,45138).
+char(c,45139).
+char(m,45140).
+char(o,45141).
+char(p,45142).
+char(o,45143).
+char(m,45144).
+char(4,45145).
+char(4,45146).
+char(2,45147).
+char(3,45148).
+char(m,45149).
+char(o,45150).
+char(p,45151).
+char(7,45152).
+char(2,45153).
+char(7,45154).
+char(3,45155).
+char(c,45156).
+char(p,45157).
+char(3,45158).
+char(2,45159).
+char(6,45160).
+char(1,45161).
+char(p,45162).
+char(o,45163).
+char(5,45164).
+char(0,45165).
+char(6,45166).
+char(c,45167).
+char(c,45168).
+char(c,45169).
+char(m,45170).
+char(7,45171).
+char(3,45172).
+char(4,45173).
+char(2,45174).
+char(c,45175).
+char(c,45176).
+char(p,45177).
+char(8,45178).
+char(2,45179).
+char(6,45180).
+char(3,45181).
+char(c,45182).
+char(c,45183).
+char(c,45184).
+char(m,45185).
+char(1,45186).
+char(3,45187).
+char(9,45188).
+char(6,45189).
+char(m,45190).
+char(4,45191).
+char(7,45192).
+char(7,45193).
+char(6,45194).
+char(c,45195).
+char(m,45196).
+char(1,45197).
+char(1,45198).
+char(7,45199).
+char(1,45200).
+char(p,45201).
+char(o,45202).
+char(m,45203).
+char(8,45204).
+char(8,45205).
+char(9,45206).
+char(7,45207).
+char(c,45208).
+char(c,45209).
+char(c,45210).
+char(p,45211).
+char(o,45212).
+char(4,45213).
+char(5,45214).
+char(0,45215).
+char(3,45216).
+char(c,45217).
+char(m,45218).
+char(o,45219).
+char(4,45220).
+char(2,45221).
+char(1,45222).
+char(0,45223).
+char(c,45224).
+char(p,45225).
+char(5,45226).
+char(4,45227).
+char(9,45228).
+char(8,45229).
+char(c,45230).
+char(c,45231).
+char(c,45232).
+char(m,45233).
+char(6,45234).
+char(8,45235).
+char(7,45236).
+char(c,45237).
+char(c,45238).
+char(c,45239).
+char(c,45240).
+char(p,45241).
+char(1,45242).
+char(1,45243).
+char(6,45244).
+char(0,45245).
+char(c,45246).
+char(c,45247).
+char(p,45248).
+char(o,45249).
+char(o,45250).
+char(m,45251).
+char(o,45252).
+char(m,45253).
+char(3,45254).
+char(4,45255).
+char(9,45256).
+char(0,45257).
+char(m,45258).
+char(o,45259).
+char(p,45260).
+char(o,45261).
+char(9,45262).
+char(4,45263).
+char(2,45264).
+char(3,45265).
+char(m,45266).
+char(2,45267).
+char(3,45268).
+char(0,45269).
+char(1,45270).
+char(p,45271).
+char(o,45272).
+char(m,45273).
+char(o,45274).
+char(m,45275).
+char(o,45276).
+char(1,45277).
+char(8,45278).
+char(4,45279).
+char(6,45280).
+char(c,45281).
+char(c,45282).
+char(c,45283).
+char(p,45284).
+char(o,45285).
+char(m,45286).
+char(o,45287).
+char(p,45288).
+char(o,45289).
+char(p,45290).
+char(o,45291).
+char(p,45292).
+char(o,45293).
+char(o,45294).
+char(p,45295).
+char(o,45296).
+char(m,45297).
+char(7,45298).
+char(6,45299).
+char(0,45300).
+char(9,45301).
+char(c,45302).
+char(c,45303).
+char(m,45304).
+char(o,45305).
+char(5,45306).
+char(0,45307).
+char(5,45308).
+char(9,45309).
+char(p,45310).
+char(o,45311).
+char(7,45312).
+char(1,45313).
+char(3,45314).
+char(9,45315).
+char(c,45316).
+char(c,45317).
+char(c,45318).
+char(c,45319).
+char(p,45320).
+char(7,45321).
+char(0,45322).
+char(0,45323).
+char(3,45324).
+char(p,45325).
+char(o,45326).
+char(p,45327).
+char(o,45328).
+char(8,45329).
+char(0,45330).
+char(5,45331).
+char(1,45332).
+char(m,45333).
+char(o,45334).
+char(p,45335).
+char(o,45336).
+char(p,45337).
+char(3,45338).
+char(7,45339).
+char(1,45340).
+char(1,45341).
+char(m,45342).
+char(4,45343).
+char(4,45344).
+char(2,45345).
+char(5,45346).
+char(m,45347).
+char(1,45348).
+char(2,45349).
+char(2,45350).
+char(5,45351).
+char(m,45352).
+char(o,45353).
+char(p,45354).
+char(o,45355).
+char(m,45356).
+char(o,45357).
+char(m,45358).
+char(4,45359).
+char(3,45360).
+char(9,45361).
+char(4,45362).
+char(m,45363).
+char(o,45364).
+char(7,45365).
+char(9,45366).
+char(2,45367).
+char(4,45368).
+char(c,45369).
+char(c,45370).
+char(c,45371).
+char(p,45372).
+char(o,45373).
+char(8,45374).
+char(5,45375).
+char(0,45376).
+char(2,45377).
+char(c,45378).
+char(p,45379).
+char(1,45380).
+char(1,45381).
+char(2,45382).
+char(c,45383).
+char(c,45384).
+char(p,45385).
+char(8,45386).
+char(7,45387).
+char(2,45388).
+char(3,45389).
+char(c,45390).
+char(c,45391).
+char(c,45392).
+char(c,45393).
+char(m,45394).
+char(6,45395).
+char(1,45396).
+char(6,45397).
+char(2,45398).
+char(c,45399).
+char(c,45400).
+char(c,45401).
+char(p,45402).
+char(3,45403).
+char(2,45404).
+char(9,45405).
+char(9,45406).
+char(c,45407).
+char(c,45408).
+char(c,45409).
+char(p,45410).
+char(9,45411).
+char(1,45412).
+char(0,45413).
+char(8,45414).
+char(p,45415).
+char(4,45416).
+char(1,45417).
+char(1,45418).
+char(9,45419).
+char(c,45420).
+char(m,45421).
+char(o,45422).
+char(p,45423).
+char(o,45424).
+char(p,45425).
+char(o,45426).
+char(3,45427).
+char(3,45428).
+char(2,45429).
+char(1,45430).
+char(c,45431).
+char(p,45432).
+char(3,45433).
+char(1,45434).
+char(8,45435).
+char(c,45436).
+char(c,45437).
+char(c,45438).
+char(m,45439).
+char(o,45440).
+char(p,45441).
+char(o,45442).
+char(p,45443).
+char(o,45444).
+char(o,45445).
+char(p,45446).
+char(o,45447).
+char(m,45448).
+char(6,45449).
+char(4,45450).
+char(8,45451).
+char(6,45452).
+char(c,45453).
+char(c,45454).
+char(p,45455).
+char(o,45456).
+char(6,45457).
+char(0,45458).
+char(5,45459).
+char(5,45460).
+char(m,45461).
+char(3,45462).
+char(8,45463).
+char(5,45464).
+char(5,45465).
+char(c,45466).
+char(m,45467).
+char(6,45468).
+char(8,45469).
+char(6,45470).
+char(9,45471).
+char(c,45472).
+char(m,45473).
+char(7,45474).
+char(8,45475).
+char(5,45476).
+char(9,45477).
+char(c,45478).
+char(m,45479).
+char(1,45480).
+char(1,45481).
+char(4,45482).
+char(9,45483).
+char(c,45484).
+char(c,45485).
+char(c,45486).
+char(m,45487).
+char(o,45488).
+char(p,45489).
+char(o,45490).
+char(m,45491).
+char(5,45492).
+char(7,45493).
+char(6,45494).
+char(3,45495).
+char(m,45496).
+char(2,45497).
+char(1,45498).
+char(2,45499).
+char(2,45500).
+char(c,45501).
+char(c,45502).
+char(c,45503).
+char(p,45504).
+char(o,45505).
+char(m,45506).
+char(4,45507).
+char(5,45508).
+char(9,45509).
+char(8,45510).
+char(c,45511).
+char(m,45512).
+char(o,45513).
+char(p,45514).
+char(o,45515).
+char(o,45516).
+char(o,45517).
+char(8,45518).
+char(7,45519).
+char(4,45520).
+char(9,45521).
+char(c,45522).
+char(m,45523).
+char(7,45524).
+char(1,45525).
+char(8,45526).
+char(6,45527).
+char(p,45528).
+char(o,45529).
+char(p,45530).
+char(3,45531).
+char(3,45532).
+char(7,45533).
+char(8,45534).
+char(c,45535).
+char(m,45536).
+char(2,45537).
+char(0,45538).
+char(4,45539).
+char(6,45540).
+char(m,45541).
+char(9,45542).
+char(0,45543).
+char(1,45544).
+char(2,45545).
+char(m,45546).
+char(7,45547).
+char(9,45548).
+char(8,45549).
+char(2,45550).
+char(c,45551).
+char(p,45552).
+char(6,45553).
+char(6,45554).
+char(4,45555).
+char(2,45556).
+char(m,45557).
+char(8,45558).
+char(9,45559).
+char(3,45560).
+char(8,45561).
+char(c,45562).
+char(m,45563).
+char(8,45564).
+char(7,45565).
+char(2,45566).
+char(5,45567).
+char(c,45568).
+char(m,45569).
+char(2,45570).
+char(9,45571).
+char(4,45572).
+char(7,45573).
+char(p,45574).
+char(o,45575).
+char(p,45576).
+char(8,45577).
+char(9,45578).
+char(8,45579).
+char(0,45580).
+char(c,45581).
+char(p,45582).
+char(7,45583).
+char(0,45584).
+char(6,45585).
+char(4,45586).
+char(c,45587).
+char(c,45588).
+char(m,45589).
+char(9,45590).
+char(1,45591).
+char(9,45592).
+char(7,45593).
+char(c,45594).
+char(c,45595).
+char(p,45596).
+char(5,45597).
+char(4,45598).
+char(3,45599).
+char(2,45600).
+char(c,45601).
+char(p,45602).
+char(5,45603).
+char(0,45604).
+char(3,45605).
+char(6,45606).
+char(c,45607).
+char(c,45608).
+char(m,45609).
+char(o,45610).
+char(3,45611).
+char(0,45612).
+char(6,45613).
+char(5,45614).
+char(c,45615).
+char(m,45616).
+char(o,45617).
+char(m,45618).
+char(3,45619).
+char(3,45620).
+char(5,45621).
+char(5,45622).
+char(c,45623).
+char(c,45624).
+char(m,45625).
+char(8,45626).
+char(4,45627).
+char(7,45628).
+char(5,45629).
+char(p,45630).
+char(7,45631).
+char(3,45632).
+char(6,45633).
+char(7,45634).
+char(p,45635).
+char(o,45636).
+char(9,45637).
+char(9,45638).
+char(4,45639).
+char(4,45640).
+char(c,45641).
+char(c,45642).
+char(c,45643).
+char(c,45644).
+char(m,45645).
+char(3,45646).
+char(3,45647).
+char(0,45648).
+char(6,45649).
+char(c,45650).
+char(c,45651).
+char(p,45652).
+char(o,45653).
+char(p,45654).
+char(o,45655).
+char(p,45656).
+char(5,45657).
+char(3,45658).
+char(1,45659).
+char(1,45660).
+char(c,45661).
+char(c,45662).
+char(m,45663).
+char(7,45664).
+char(2,45665).
+char(3,45666).
+char(0,45667).
+char(c,45668).
+char(p,45669).
+char(4,45670).
+char(1,45671).
+char(5,45672).
+char(8,45673).
+char(c,45674).
+char(c,45675).
+char(c,45676).
+char(m,45677).
+char(4,45678).
+char(3,45679).
+char(0,45680).
+char(9,45681).
+char(c,45682).
+char(m,45683).
+char(o,45684).
+char(m,45685).
+char(9,45686).
+char(2,45687).
+char(0,45688).
+char(2,45689).
+char(c,45690).
+char(c,45691).
+char(c,45692).
+char(c,45693).
+char(c,45694).
+char(m,45695).
+char(o,45696).
+char(8,45697).
+char(0,45698).
+char(8,45699).
+char(6,45700).
+char(m,45701).
+char(2,45702).
+char(4,45703).
+char(8,45704).
+char(5,45705).
+char(c,45706).
+char(p,45707).
+char(o,45708).
+char(5,45709).
+char(0,45710).
+char(8,45711).
+char(7,45712).
+char(p,45713).
+char(o,45714).
+char(m,45715).
+char(4,45716).
+char(6,45717).
+char(9,45718).
+char(4,45719).
+char(p,45720).
+char(8,45721).
+char(4,45722).
+char(7,45723).
+char(6,45724).
+char(m,45725).
+char(1,45726).
+char(5,45727).
+char(4,45728).
+char(5,45729).
+char(p,45730).
+char(2,45731).
+char(9,45732).
+char(8,45733).
+char(4,45734).
+char(m,45735).
+char(6,45736).
+char(8,45737).
+char(4,45738).
+char(7,45739).
+char(m,45740).
+char(o,45741).
+char(p,45742).
+char(6,45743).
+char(9,45744).
+char(3,45745).
+char(2,45746).
+char(c,45747).
+char(m,45748).
+char(o,45749).
+char(m,45750).
+char(o,45751).
+char(o,45752).
+char(m,45753).
+char(o,45754).
+char(m,45755).
+char(6,45756).
+char(2,45757).
+char(9,45758).
+char(3,45759).
+char(c,45760).
+char(c,45761).
+char(p,45762).
+char(o,45763).
+char(o,45764).
+char(o,45765).
+char(1,45766).
+char(8,45767).
+char(0,45768).
+char(5,45769).
+char(p,45770).
+char(o,45771).
+char(m,45772).
+char(o,45773).
+char(8,45774).
+char(7,45775).
+char(3,45776).
+char(0,45777).
+char(c,45778).
+char(c,45779).
+char(p,45780).
+char(7,45781).
+char(4,45782).
+char(6,45783).
+char(9,45784).
+char(p,45785).
+char(o,45786).
+char(p,45787).
+char(o,45788).
+char(p,45789).
+char(3,45790).
+char(9,45791).
+char(0,45792).
+char(5,45793).
+char(c,45794).
+char(c,45795).
+char(c,45796).
+char(m,45797).
+char(o,45798).
+char(p,45799).
+char(8,45800).
+char(2,45801).
+char(9,45802).
+char(9,45803).
+char(c,45804).
+char(c,45805).
+char(m,45806).
+char(1,45807).
+char(0,45808).
+char(9,45809).
+char(0,45810).
+char(p,45811).
+char(o,45812).
+char(m,45813).
+char(o,45814).
+char(2,45815).
+char(4,45816).
+char(0,45817).
+char(7,45818).
+char(m,45819).
+char(o,45820).
+char(m,45821).
+char(8,45822).
+char(5,45823).
+char(9,45824).
+char(3,45825).
+char(p,45826).
+char(o,45827).
+char(o,45828).
+char(p,45829).
+char(2,45830).
+char(6,45831).
+char(0,45832).
+char(1,45833).
+char(c,45834).
+char(c,45835).
+char(m,45836).
+char(5,45837).
+char(4,45838).
+char(8,45839).
+char(2,45840).
+char(c,45841).
+char(p,45842).
+char(o,45843).
+char(2,45844).
+char(6,45845).
+char(3,45846).
+char(3,45847).
+char(c,45848).
+char(c,45849).
+char(p,45850).
+char(6,45851).
+char(3,45852).
+char(3,45853).
+char(5,45854).
+char(p,45855).
+char(o,45856).
+char(p,45857).
+char(6,45858).
+char(0,45859).
+char(9,45860).
+char(0,45861).
+char(c,45862).
+char(c,45863).
+char(c,45864).
+char(c,45865).
+char(m,45866).
+char(4,45867).
+char(5,45868).
+char(4,45869).
+char(1,45870).
+char(c,45871).
+char(p,45872).
+char(o,45873).
+char(m,45874).
+char(o,45875).
+char(o,45876).
+char(m,45877).
+char(7,45878).
+char(0,45879).
+char(6,45880).
+char(8,45881).
+char(c,45882).
+char(c,45883).
+char(c,45884).
+char(c,45885).
+char(p,45886).
+char(3,45887).
+char(1,45888).
+char(7,45889).
+char(8,45890).
+char(m,45891).
+char(8,45892).
+char(6,45893).
+char(5,45894).
+char(6,45895).
+char(c,45896).
+char(m,45897).
+char(4,45898).
+char(7,45899).
+char(2,45900).
+char(6,45901).
+char(c,45902).
+char(c,45903).
+char(m,45904).
+char(o,45905).
+char(1,45906).
+char(9,45907).
+char(1,45908).
+char(1,45909).
+char(m,45910).
+char(4,45911).
+char(2,45912).
+char(7,45913).
+char(3,45914).
+char(c,45915).
+char(p,45916).
+char(o,45917).
+char(7,45918).
+char(3,45919).
+char(9,45920).
+char(0,45921).
+char(m,45922).
+char(3,45923).
+char(6,45924).
+char(2,45925).
+char(7,45926).
+char(p,45927).
+char(4,45928).
+char(1,45929).
+char(5,45930).
+char(2,45931).
+char(p,45932).
+char(6,45933).
+char(2,45934).
+char(1,45935).
+char(p,45936).
+char(o,45937).
+char(6,45938).
+char(7,45939).
+char(5,45940).
+char(1,45941).
+char(c,45942).
+char(p,45943).
+char(o,45944).
+char(7,45945).
+char(8,45946).
+char(1,45947).
+char(0,45948).
+char(c,45949).
+char(p,45950).
+char(3,45951).
+char(0,45952).
+char(1,45953).
+char(0,45954).
+char(c,45955).
+char(c,45956).
+char(p,45957).
+char(4,45958).
+char(6,45959).
+char(0,45960).
+char(1,45961).
+char(p,45962).
+char(4,45963).
+char(9,45964).
+char(4,45965).
+char(c,45966).
+char(p,45967).
+char(o,45968).
+char(p,45969).
+char(1,45970).
+char(1,45971).
+char(2,45972).
+char(c,45973).
+char(c,45974).
+char(c,45975).
+char(m,45976).
+char(8,45977).
+char(7,45978).
+char(5,45979).
+char(3,45980).
+char(c,45981).
+char(p,45982).
+char(o,45983).
+char(p,45984).
+char(8,45985).
+char(8,45986).
+char(1,45987).
+char(5,45988).
+char(c,45989).
+char(m,45990).
+char(o,45991).
+char(p,45992).
+char(o,45993).
+char(p,45994).
+char(o,45995).
+char(9,45996).
+char(9,45997).
+char(6,45998).
+char(7,45999).
+char(c,46000).
+char(p,46001).
+char(o,46002).
+char(p,46003).
+char(o,46004).
+char(8,46005).
+char(5,46006).
+char(1,46007).
+char(9,46008).
+char(c,46009).
+char(m,46010).
+char(9,46011).
+char(5,46012).
+char(1,46013).
+char(m,46014).
+char(o,46015).
+char(p,46016).
+char(1,46017).
+char(2,46018).
+char(3,46019).
+char(8,46020).
+char(c,46021).
+char(p,46022).
+char(7,46023).
+char(4,46024).
+char(1,46025).
+char(9,46026).
+char(c,46027).
+char(p,46028).
+char(o,46029).
+char(m,46030).
+char(o,46031).
+char(o,46032).
+char(6,46033).
+char(6,46034).
+char(8,46035).
+char(m,46036).
+char(4,46037).
+char(3,46038).
+char(3,46039).
+char(2,46040).
+char(c,46041).
+char(c,46042).
+char(c,46043).
+char(p,46044).
+char(3,46045).
+char(0,46046).
+char(7,46047).
+char(7,46048).
+char(c,46049).
+char(c,46050).
+char(c,46051).
+char(c,46052).
+char(c,46053).
+char(m,46054).
+char(o,46055).
+char(m,46056).
+char(5,46057).
+char(5,46058).
+char(3,46059).
+char(0,46060).
+char(p,46061).
+char(6,46062).
+char(9,46063).
+char(6,46064).
+char(6,46065).
+char(m,46066).
+char(o,46067).
+char(m,46068).
+char(o,46069).
+char(o,46070).
+char(4,46071).
+char(9,46072).
+char(8,46073).
+char(7,46074).
+char(c,46075).
+char(c,46076).
+char(c,46077).
+char(p,46078).
+char(o,46079).
+char(o,46080).
+char(o,46081).
+char(6,46082).
+char(1,46083).
+char(3,46084).
+char(2,46085).
+char(m,46086).
+char(o,46087).
+char(p,46088).
+char(2,46089).
+char(1,46090).
+char(6,46091).
+char(8,46092).
+char(m,46093).
+char(o,46094).
+char(p,46095).
+char(9,46096).
+char(4,46097).
+char(5,46098).
+char(1,46099).
+char(c,46100).
+char(p,46101).
+char(o,46102).
+char(2,46103).
+char(6,46104).
+char(9,46105).
+char(7,46106).
+char(p,46107).
+char(7,46108).
+char(9,46109).
+char(5,46110).
+char(7,46111).
+char(c,46112).
+char(m,46113).
+char(o,46114).
+char(o,46115).
+char(1,46116).
+char(2,46117).
+char(8,46118).
+char(1,46119).
+char(p,46120).
+char(o,46121).
+char(2,46122).
+char(3,46123).
+char(8,46124).
+char(6,46125).
+char(m,46126).
+char(o,46127).
+char(7,46128).
+char(6,46129).
+char(0,46130).
+char(2,46131).
+char(c,46132).
+char(m,46133).
+char(o,46134).
+char(m,46135).
+char(o,46136).
+char(o,46137).
+char(m,46138).
+char(2,46139).
+char(5,46140).
+char(1,46141).
+char(4,46142).
+char(m,46143).
+char(o,46144).
+char(m,46145).
+char(o,46146).
+char(m,46147).
+char(6,46148).
+char(1,46149).
+char(7,46150).
+char(1,46151).
+char(p,46152).
+char(2,46153).
+char(3,46154).
+char(2,46155).
+char(0,46156).
+char(c,46157).
+char(p,46158).
+char(3,46159).
+char(6,46160).
+char(1,46161).
+char(6,46162).
+char(c,46163).
+char(c,46164).
+char(c,46165).
+char(c,46166).
+char(c,46167).
+char(m,46168).
+char(o,46169).
+char(p,46170).
+char(o,46171).
+char(o,46172).
+char(p,46173).
+char(5,46174).
+char(9,46175).
+char(4,46176).
+char(7,46177).
+char(p,46178).
+char(1,46179).
+char(7,46180).
+char(4,46181).
+char(2,46182).
+char(c,46183).
+char(p,46184).
+char(o,46185).
+char(p,46186).
+char(1,46187).
+char(3,46188).
+char(2,46189).
+char(9,46190).
+char(m,46191).
+char(1,46192).
+char(9,46193).
+char(6,46194).
+char(2,46195).
+char(m,46196).
+char(3,46197).
+char(0,46198).
+char(1,46199).
+char(c,46200).
+char(c,46201).
+char(m,46202).
+char(9,46203).
+char(2,46204).
+char(9,46205).
+char(4,46206).
+char(c,46207).
+char(m,46208).
+char(o,46209).
+char(o,46210).
+char(m,46211).
+char(o,46212).
+char(p,46213).
+char(o,46214).
+char(p,46215).
+char(o,46216).
+char(m,46217).
+char(9,46218).
+char(0,46219).
+char(5,46220).
+char(4,46221).
+char(c,46222).
+char(c,46223).
+char(c,46224).
+char(m,46225).
+char(o,46226).
+char(m,46227).
+char(o,46228).
+char(o,46229).
+char(m,46230).
+char(o,46231).
+char(m,46232).
+char(5,46233).
+char(8,46234).
+char(4,46235).
+char(4,46236).
+char(p,46237).
+char(o,46238).
+char(p,46239).
+char(3,46240).
+char(4,46241).
+char(1,46242).
+char(5,46243).
+char(c,46244).
+char(c,46245).
+char(c,46246).
+char(p,46247).
+char(o,46248).
+char(p,46249).
+char(2,46250).
+char(9,46251).
+char(4,46252).
+char(0,46253).
+char(c,46254).
+char(c,46255).
+char(c,46256).
+char(p,46257).
+char(o,46258).
+char(p,46259).
+char(o,46260).
+char(6,46261).
+char(3,46262).
+char(2,46263).
+char(2,46264).
+char(m,46265).
+char(2,46266).
+char(4,46267).
+char(7,46268).
+char(4,46269).
+char(c,46270).
+char(p,46271).
+char(o,46272).
+char(p,46273).
+char(o,46274).
+char(m,46275).
+char(5,46276).
+char(8,46277).
+char(9,46278).
+char(1,46279).
+char(m,46280).
+char(2,46281).
+char(9,46282).
+char(6,46283).
+char(5,46284).
+char(p,46285).
+char(2,46286).
+char(7,46287).
+char(4,46288).
+char(m,46289).
+char(8,46290).
+char(6,46291).
+char(9,46292).
+char(8,46293).
+char(m,46294).
+char(1,46295).
+char(5,46296).
+char(7,46297).
+char(7,46298).
+char(m,46299).
+char(3,46300).
+char(2,46301).
+char(5,46302).
+char(6,46303).
+char(c,46304).
+char(p,46305).
+char(o,46306).
+char(m,46307).
+char(o,46308).
+char(o,46309).
+char(o,46310).
+char(o,46311).
+char(m,46312).
+char(9,46313).
+char(4,46314).
+char(9,46315).
+char(7,46316).
+char(m,46317).
+char(o,46318).
+char(p,46319).
+char(3,46320).
+char(3,46321).
+char(0,46322).
+char(3,46323).
+char(c,46324).
+char(m,46325).
+char(6,46326).
+char(8,46327).
+char(9,46328).
+char(7,46329).
+char(c,46330).
+char(c,46331).
+char(c,46332).
+char(m,46333).
+char(1,46334).
+char(8,46335).
+char(0,46336).
+char(0,46337).
+char(c,46338).
+char(p,46339).
+char(5,46340).
+char(8,46341).
+char(9,46342).
+char(4,46343).
+char(p,46344).
+char(9,46345).
+char(6,46346).
+char(8,46347).
+char(9,46348).
+char(p,46349).
+char(o,46350).
+char(p,46351).
+char(o,46352).
+char(m,46353).
+char(o,46354).
+char(p,46355).
+char(o,46356).
+char(p,46357).
+char(6,46358).
+char(7,46359).
+char(6,46360).
+char(6,46361).
+char(c,46362).
+char(m,46363).
+char(o,46364).
+char(p,46365).
+char(6,46366).
+char(5,46367).
+char(1,46368).
+char(0,46369).
+char(p,46370).
+char(2,46371).
+char(1,46372).
+char(2,46373).
+char(4,46374).
+char(p,46375).
+char(2,46376).
+char(6,46377).
+char(3,46378).
+char(4,46379).
+char(c,46380).
+char(c,46381).
+char(p,46382).
+char(o,46383).
+char(p,46384).
+char(o,46385).
+char(6,46386).
+char(1,46387).
+char(8,46388).
+char(5,46389).
+char(m,46390).
+char(o,46391).
+char(7,46392).
+char(5,46393).
+char(6,46394).
+char(2,46395).
+char(p,46396).
+char(2,46397).
+char(2,46398).
+char(7,46399).
+char(4,46400).
+char(c,46401).
+char(m,46402).
+char(6,46403).
+char(1,46404).
+char(9,46405).
+char(3,46406).
+char(c,46407).
+char(p,46408).
+char(o,46409).
+char(o,46410).
+char(p,46411).
+char(6,46412).
+char(6,46413).
+char(2,46414).
+char(8,46415).
+char(m,46416).
+char(o,46417).
+char(p,46418).
+char(3,46419).
+char(5,46420).
+char(9,46421).
+char(9,46422).
+char(c,46423).
+char(p,46424).
+char(8,46425).
+char(3,46426).
+char(0,46427).
+char(8,46428).
+char(m,46429).
+char(1,46430).
+char(7,46431).
+char(2,46432).
+char(0,46433).
+char(c,46434).
+char(c,46435).
+char(c,46436).
+char(c,46437).
+char(m,46438).
+char(o,46439).
+char(o,46440).
+char(o,46441).
+char(m,46442).
+char(9,46443).
+char(4,46444).
+char(4,46445).
+char(3,46446).
+char(c,46447).
+char(p,46448).
+char(3,46449).
+char(9,46450).
+char(4,46451).
+char(8,46452).
+char(c,46453).
+char(p,46454).
+char(9,46455).
+char(5,46456).
+char(9,46457).
+char(0,46458).
+char(p,46459).
+char(5,46460).
+char(3,46461).
+char(5,46462).
+char(1,46463).
+char(c,46464).
+char(c,46465).
+char(m,46466).
+char(6,46467).
+char(9,46468).
+char(2,46469).
+char(0,46470).
+char(m,46471).
+char(5,46472).
+char(5,46473).
+char(5,46474).
+char(7,46475).
+char(c,46476).
+char(c,46477).
+char(c,46478).
+char(c,46479).
+char(c,46480).
+char(p,46481).
+char(o,46482).
+char(m,46483).
+char(2,46484).
+char(0,46485).
+char(9,46486).
+char(4,46487).
+char(c,46488).
+char(c,46489).
+char(c,46490).
+char(c,46491).
+char(c,46492).
+char(c,46493).
+char(c,46494).
+char(m,46495).
+char(o,46496).
+char(p,46497).
+char(o,46498).
+char(m,46499).
+char(6,46500).
+char(4,46501).
+char(8,46502).
+char(5,46503).
+char(m,46504).
+char(o,46505).
+char(m,46506).
+char(3,46507).
+char(3,46508).
+char(1,46509).
+char(9,46510).
+char(c,46511).
+char(c,46512).
+char(m,46513).
+char(5,46514).
+char(4,46515).
+char(0,46516).
+char(8,46517).
+char(c,46518).
+char(m,46519).
+char(8,46520).
+char(9,46521).
+char(7,46522).
+char(5,46523).
+char(c,46524).
+char(m,46525).
+char(6,46526).
+char(9,46527).
+char(5,46528).
+char(c,46529).
+char(p,46530).
+char(o,46531).
+char(o,46532).
+char(m,46533).
+char(2,46534).
+char(2,46535).
+char(8,46536).
+char(8,46537).
+char(m,46538).
+char(o,46539).
+char(p,46540).
+char(5,46541).
+char(4,46542).
+char(2,46543).
+char(0,46544).
+char(m,46545).
+char(o,46546).
+char(o,46547).
+char(o,46548).
+char(p,46549).
+char(6,46550).
+char(1,46551).
+char(0,46552).
+char(3,46553).
+char(c,46554).
+char(c,46555).
+char(m,46556).
+char(8,46557).
+char(7,46558).
+char(4,46559).
+char(6,46560).
+char(p,46561).
+char(4,46562).
+char(0,46563).
+char(5,46564).
+char(2,46565).
+char(c,46566).
+char(c,46567).
+char(p,46568).
+char(3,46569).
+char(3,46570).
+char(6,46571).
+char(4,46572).
+char(c,46573).
+char(c,46574).
+char(m,46575).
+char(2,46576).
+char(4,46577).
+char(2,46578).
+char(9,46579).
+char(c,46580).
+char(m,46581).
+char(o,46582).
+char(m,46583).
+char(2,46584).
+char(9,46585).
+char(3,46586).
+char(5,46587).
+char(c,46588).
+char(m,46589).
+char(o,46590).
+char(p,46591).
+char(2,46592).
+char(0,46593).
+char(7,46594).
+char(1,46595).
+char(p,46596).
+char(o,46597).
+char(o,46598).
+char(p,46599).
+char(3,46600).
+char(8,46601).
+char(4,46602).
+char(2,46603).
+char(p,46604).
+char(o,46605).
+char(o,46606).
+char(m,46607).
+char(9,46608).
+char(0,46609).
+char(6,46610).
+char(6,46611).
+char(c,46612).
+char(m,46613).
+char(o,46614).
+char(9,46615).
+char(9,46616).
+char(0,46617).
+char(6,46618).
+char(c,46619).
+char(p,46620).
+char(o,46621).
+char(p,46622).
+char(o,46623).
+char(m,46624).
+char(9,46625).
+char(4,46626).
+char(2,46627).
+char(4,46628).
+char(p,46629).
+char(2,46630).
+char(7,46631).
+char(6,46632).
+char(c,46633).
+char(p,46634).
+char(2,46635).
+char(3,46636).
+char(2,46637).
+char(2,46638).
+char(m,46639).
+char(o,46640).
+char(m,46641).
+char(5,46642).
+char(9,46643).
+char(4,46644).
+char(8,46645).
+char(m,46646).
+char(9,46647).
+char(2,46648).
+char(0,46649).
+char(c,46650).
+char(c,46651).
+char(c,46652).
+char(c,46653).
+char(m,46654).
+char(o,46655).
+char(p,46656).
+char(5,46657).
+char(6,46658).
+char(3,46659).
+char(9,46660).
+char(p,46661).
+char(9,46662).
+char(7,46663).
+char(0,46664).
+char(5,46665).
+char(c,46666).
+char(c,46667).
+char(p,46668).
+char(3,46669).
+char(6,46670).
+char(1,46671).
+char(3,46672).
+char(c,46673).
+char(c,46674).
+char(c,46675).
+char(c,46676).
+char(m,46677).
+char(5,46678).
+char(7,46679).
+char(7,46680).
+char(m,46681).
+char(o,46682).
+char(6,46683).
+char(5,46684).
+char(4,46685).
+char(2,46686).
+char(c,46687).
+char(c,46688).
+char(m,46689).
+char(o,46690).
+char(p,46691).
+char(o,46692).
+char(p,46693).
+char(o,46694).
+char(m,46695).
+char(o,46696).
+char(p,46697).
+char(4,46698).
+char(3,46699).
+char(2,46700).
+char(0,46701).
+char(p,46702).
+char(3,46703).
+char(6,46704).
+char(3,46705).
+char(7,46706).
+char(c,46707).
+char(m,46708).
+char(9,46709).
+char(5,46710).
+char(2,46711).
+char(9,46712).
+char(m,46713).
+char(o,46714).
+char(m,46715).
+char(3,46716).
+char(9,46717).
+char(8,46718).
+char(7,46719).
+char(c,46720).
+char(c,46721).
+char(p,46722).
+char(o,46723).
+char(p,46724).
+char(o,46725).
+char(1,46726).
+char(3,46727).
+char(7,46728).
+char(6,46729).
+char(m,46730).
+char(6,46731).
+char(8,46732).
+char(7,46733).
+char(c,46734).
+char(c,46735).
+char(c,46736).
+char(c,46737).
+char(m,46738).
+char(8,46739).
+char(5,46740).
+char(0,46741).
+char(1,46742).
+char(c,46743).
+char(c,46744).
+char(c,46745).
+char(c,46746).
+char(c,46747).
+char(m,46748).
+char(6,46749).
+char(6,46750).
+char(8,46751).
+char(0,46752).
+char(p,46753).
+char(7,46754).
+char(2,46755).
+char(4,46756).
+char(2,46757).
+char(c,46758).
+char(m,46759).
+char(8,46760).
+char(3,46761).
+char(2,46762).
+char(5,46763).
+char(m,46764).
+char(2,46765).
+char(5,46766).
+char(5,46767).
+char(2,46768).
+char(c,46769).
+char(m,46770).
+char(o,46771).
+char(m,46772).
+char(7,46773).
+char(8,46774).
+char(3,46775).
+char(5,46776).
+char(c,46777).
+char(c,46778).
+char(m,46779).
+char(5,46780).
+char(4,46781).
+char(5,46782).
+char(p,46783).
+char(o,46784).
+char(p,46785).
+char(4,46786).
+char(4,46787).
+char(6,46788).
+char(0,46789).
+char(c,46790).
+char(p,46791).
+char(8,46792).
+char(9,46793).
+char(2,46794).
+char(9,46795).
+char(c,46796).
+char(p,46797).
+char(8,46798).
+char(6,46799).
+char(3,46800).
+char(0,46801).
+char(c,46802).
+char(p,46803).
+char(o,46804).
+char(3,46805).
+char(6,46806).
+char(8,46807).
+char(5,46808).
+char(c,46809).
+char(m,46810).
+char(4,46811).
+char(8,46812).
+char(9,46813).
+char(c,46814).
+char(c,46815).
+char(c,46816).
+char(m,46817).
+char(3,46818).
+char(7,46819).
+char(8,46820).
+char(0,46821).
+char(c,46822).
+char(c,46823).
+char(p,46824).
+char(o,46825).
+char(m,46826).
+char(o,46827).
+char(p,46828).
+char(o,46829).
+char(1,46830).
+char(1,46831).
+char(0,46832).
+char(8,46833).
+char(p,46834).
+char(o,46835).
+char(m,46836).
+char(7,46837).
+char(2,46838).
+char(9,46839).
+char(c,46840).
+char(p,46841).
+char(8,46842).
+char(6,46843).
+char(8,46844).
+char(1,46845).
+char(p,46846).
+char(8,46847).
+char(7,46848).
+char(5,46849).
+char(2,46850).
+char(p,46851).
+char(8,46852).
+char(8,46853).
+char(9,46854).
+char(1,46855).
+char(c,46856).
+char(c,46857).
+char(c,46858).
+char(p,46859).
+char(8,46860).
+char(1,46861).
+char(9,46862).
+char(p,46863).
+char(o,46864).
+char(m,46865).
+char(o,46866).
+char(p,46867).
+char(o,46868).
+char(8,46869).
+char(7,46870).
+char(2,46871).
+char(1,46872).
+char(c,46873).
+char(p,46874).
+char(9,46875).
+char(8,46876).
+char(0,46877).
+char(0,46878).
+char(p,46879).
+char(9,46880).
+char(3,46881).
+char(2,46882).
+char(4,46883).
+char(p,46884).
+char(9,46885).
+char(9,46886).
+char(0,46887).
+char(8,46888).
+char(c,46889).
+char(c,46890).
+char(m,46891).
+char(2,46892).
+char(0,46893).
+char(7,46894).
+char(8,46895).
+char(p,46896).
+char(4,46897).
+char(7,46898).
+char(4,46899).
+char(2,46900).
+char(m,46901).
+char(8,46902).
+char(1,46903).
+char(9,46904).
+char(8,46905).
+char(p,46906).
+char(o,46907).
+char(p,46908).
+char(9,46909).
+char(2,46910).
+char(0,46911).
+char(8,46912).
+char(c,46913).
+char(c,46914).
+char(m,46915).
+char(o,46916).
+char(m,46917).
+char(3,46918).
+char(0,46919).
+char(1,46920).
+char(2,46921).
+char(m,46922).
+char(3,46923).
+char(9,46924).
+char(8,46925).
+char(7,46926).
+char(c,46927).
+char(m,46928).
+char(7,46929).
+char(5,46930).
+char(1,46931).
+char(2,46932).
+char(c,46933).
+char(c,46934).
+char(c,46935).
+char(p,46936).
+char(2,46937).
+char(4,46938).
+char(1,46939).
+char(5,46940).
+char(p,46941).
+char(o,46942).
+char(5,46943).
+char(4,46944).
+char(6,46945).
+char(6,46946).
+char(m,46947).
+char(7,46948).
+char(5,46949).
+char(5,46950).
+char(4,46951).
+char(p,46952).
+char(o,46953).
+char(p,46954).
+char(1,46955).
+char(2,46956).
+char(4,46957).
+char(5,46958).
+char(m,46959).
+char(o,46960).
+char(p,46961).
+char(1,46962).
+char(8,46963).
+char(9,46964).
+char(1,46965).
+char(p,46966).
+char(o,46967).
+char(m,46968).
+char(6,46969).
+char(0,46970).
+char(5,46971).
+char(c,46972).
+char(c,46973).
+char(p,46974).
+char(8,46975).
+char(6,46976).
+char(6,46977).
+char(8,46978).
+char(c,46979).
+char(p,46980).
+char(8,46981).
+char(0,46982).
+char(3,46983).
+char(8,46984).
+char(c,46985).
+char(c,46986).
+char(p,46987).
+char(7,46988).
+char(9,46989).
+char(6,46990).
+char(8,46991).
+char(c,46992).
+char(m,46993).
+char(o,46994).
+char(p,46995).
+char(8,46996).
+char(1,46997).
+char(2,46998).
+char(5,46999).
+char(m,47000).
+char(o,47001).
+char(4,47002).
+char(4,47003).
+char(5,47004).
+char(4,47005).
+char(c,47006).
+char(p,47007).
+char(o,47008).
+char(p,47009).
+char(o,47010).
+char(p,47011).
+char(o,47012).
+char(p,47013).
+char(o,47014).
+char(p,47015).
+char(7,47016).
+char(8,47017).
+char(3,47018).
+char(8,47019).
+char(p,47020).
+char(3,47021).
+char(0,47022).
+char(1,47023).
+char(8,47024).
+char(c,47025).
+char(c,47026).
+char(p,47027).
+char(1,47028).
+char(0,47029).
+char(2,47030).
+char(3,47031).
+char(p,47032).
+char(o,47033).
+char(m,47034).
+char(6,47035).
+char(7,47036).
+char(6,47037).
+char(3,47038).
+char(m,47039).
+char(3,47040).
+char(6,47041).
+char(1,47042).
+char(m,47043).
+char(7,47044).
+char(1,47045).
+char(8,47046).
+char(8,47047).
+char(c,47048).
+char(m,47049).
+char(9,47050).
+char(2,47051).
+char(0,47052).
+char(2,47053).
+char(c,47054).
+char(c,47055).
+char(m,47056).
+char(o,47057).
+char(p,47058).
+char(9,47059).
+char(1,47060).
+char(1,47061).
+char(1,47062).
+char(p,47063).
+char(2,47064).
+char(8,47065).
+char(8,47066).
+char(7,47067).
+char(c,47068).
+char(c,47069).
+char(m,47070).
+char(o,47071).
+char(m,47072).
+char(6,47073).
+char(9,47074).
+char(9,47075).
+char(5,47076).
+char(c,47077).
+char(m,47078).
+char(4,47079).
+char(9,47080).
+char(7,47081).
+char(c,47082).
+char(c,47083).
+char(c,47084).
+char(c,47085).
+char(c,47086).
+char(m,47087).
+char(o,47088).
+char(o,47089).
+char(p,47090).
+char(o,47091).
+char(p,47092).
+char(7,47093).
+char(8,47094).
+char(4,47095).
+char(2,47096).
+char(c,47097).
+char(p,47098).
+char(o,47099).
+char(o,47100).
+char(p,47101).
+char(7,47102).
+char(5,47103).
+char(1,47104).
+char(2,47105).
+char(m,47106).
+char(o,47107).
+char(m,47108).
+char(o,47109).
+char(p,47110).
+char(o,47111).
+char(3,47112).
+char(7,47113).
+char(5,47114).
+char(4,47115).
+char(c,47116).
+char(m,47117).
+char(2,47118).
+char(0,47119).
+char(2,47120).
+char(4,47121).
+char(c,47122).
+char(c,47123).
+char(c,47124).
+char(m,47125).
+char(o,47126).
+char(7,47127).
+char(3,47128).
+char(6,47129).
+char(3,47130).
+char(c,47131).
+char(m,47132).
+char(o,47133).
+char(o,47134).
+char(p,47135).
+char(1,47136).
+char(3,47137).
+char(9,47138).
+char(2,47139).
+char(m,47140).
+char(7,47141).
+char(1,47142).
+char(9,47143).
+char(1,47144).
+char(m,47145).
+char(8,47146).
+char(9,47147).
+char(4,47148).
+char(7,47149).
+char(p,47150).
+char(o,47151).
+char(m,47152).
+char(9,47153).
+char(5,47154).
+char(2,47155).
+char(9,47156).
+char(c,47157).
+char(m,47158).
+char(o,47159).
+char(m,47160).
+char(2,47161).
+char(6,47162).
+char(3,47163).
+char(3,47164).
+char(p,47165).
+char(o,47166).
+char(o,47167).
+char(p,47168).
+char(9,47169).
+char(7,47170).
+char(5,47171).
+char(5,47172).
+char(c,47173).
+char(c,47174).
+char(m,47175).
+char(o,47176).
+char(p,47177).
+char(9,47178).
+char(6,47179).
+char(9,47180).
+char(1,47181).
+char(m,47182).
+char(2,47183).
+char(4,47184).
+char(8,47185).
+char(2,47186).
+char(c,47187).
+char(p,47188).
+char(5,47189).
+char(2,47190).
+char(8,47191).
+char(6,47192).
+char(p,47193).
+char(o,47194).
+char(p,47195).
+char(o,47196).
+char(m,47197).
+char(o,47198).
+char(o,47199).
+char(p,47200).
+char(o,47201).
+char(p,47202).
+char(o,47203).
+char(p,47204).
+char(o,47205).
+char(m,47206).
+char(o,47207).
+char(m,47208).
+char(4,47209).
+char(4,47210).
+char(4,47211).
+char(1,47212).
+char(p,47213).
+char(o,47214).
+char(p,47215).
+char(5,47216).
+char(8,47217).
+char(6,47218).
+char(5,47219).
+char(c,47220).
+char(c,47221).
+char(c,47222).
+char(c,47223).
+char(p,47224).
+char(2,47225).
+char(9,47226).
+char(9,47227).
+char(1,47228).
+char(c,47229).
+char(m,47230).
+char(o,47231).
+char(o,47232).
+char(m,47233).
+char(6,47234).
+char(2,47235).
+char(1,47236).
+char(3,47237).
+char(m,47238).
+char(3,47239).
+char(7,47240).
+char(9,47241).
+char(9,47242).
+char(m,47243).
+char(o,47244).
+char(p,47245).
+char(5,47246).
+char(5,47247).
+char(0,47248).
+char(0,47249).
+char(c,47250).
+char(p,47251).
+char(o,47252).
+char(p,47253).
+char(o,47254).
+char(p,47255).
+char(o,47256).
+char(3,47257).
+char(3,47258).
+char(1,47259).
+char(9,47260).
+char(c,47261).
+char(m,47262).
+char(o,47263).
+char(6,47264).
+char(5,47265).
+char(7,47266).
+char(8,47267).
+char(m,47268).
+char(o,47269).
+char(m,47270).
+char(o,47271).
+char(m,47272).
+char(o,47273).
+char(p,47274).
+char(7,47275).
+char(7,47276).
+char(2,47277).
+char(3,47278).
+char(m,47279).
+char(5,47280).
+char(8,47281).
+char(1,47282).
+char(c,47283).
+char(c,47284).
+char(c,47285).
+char(p,47286).
+char(4,47287).
+char(3,47288).
+char(0,47289).
+char(2,47290).
+char(m,47291).
+char(4,47292).
+char(7,47293).
+char(0,47294).
+char(9,47295).
+char(m,47296).
+char(o,47297).
+char(m,47298).
+char(6,47299).
+char(0,47300).
+char(9,47301).
+char(8,47302).
+char(c,47303).
+char(m,47304).
+char(2,47305).
+char(1,47306).
+char(0,47307).
+char(2,47308).
+char(c,47309).
+char(m,47310).
+char(o,47311).
+char(p,47312).
+char(o,47313).
+char(p,47314).
+char(3,47315).
+char(4,47316).
+char(2,47317).
+char(4,47318).
+char(p,47319).
+char(o,47320).
+char(m,47321).
+char(o,47322).
+char(o,47323).
+char(m,47324).
+char(3,47325).
+char(4,47326).
+char(9,47327).
+char(p,47328).
+char(7,47329).
+char(9,47330).
+char(5,47331).
+char(2,47332).
+char(p,47333).
+char(3,47334).
+char(2,47335).
+char(5,47336).
+char(2,47337).
+char(p,47338).
+char(o,47339).
+char(m,47340).
+char(2,47341).
+char(5,47342).
+char(9,47343).
+char(5,47344).
+char(p,47345).
+char(5,47346).
+char(5,47347).
+char(5,47348).
+char(m,47349).
+char(o,47350).
+char(p,47351).
+char(o,47352).
+char(p,47353).
+char(o,47354).
+char(o,47355).
+char(2,47356).
+char(6,47357).
+char(3,47358).
+char(0,47359).
+char(p,47360).
+char(o,47361).
+char(o,47362).
+char(o,47363).
+char(m,47364).
+char(9,47365).
+char(6,47366).
+char(8,47367).
+char(2,47368).
+char(c,47369).
+char(m,47370).
+char(o,47371).
+char(m,47372).
+char(5,47373).
+char(4,47374).
+char(1,47375).
+char(7,47376).
+char(c,47377).
+char(m,47378).
+char(5,47379).
+char(9,47380).
+char(3,47381).
+char(9,47382).
+char(m,47383).
+char(o,47384).
+char(o,47385).
+char(p,47386).
+char(8,47387).
+char(2,47388).
+char(7,47389).
+char(8,47390).
+char(c,47391).
+char(c,47392).
+char(c,47393).
+char(m,47394).
+char(o,47395).
+char(m,47396).
+char(o,47397).
+char(p,47398).
+char(o,47399).
+char(p,47400).
+char(7,47401).
+char(8,47402).
+char(9,47403).
+char(0,47404).
+char(c,47405).
+char(m,47406).
+char(8,47407).
+char(7,47408).
+char(7,47409).
+char(6,47410).
+char(c,47411).
+char(c,47412).
+char(p,47413).
+char(o,47414).
+char(m,47415).
+char(2,47416).
+char(9,47417).
+char(3,47418).
+char(2,47419).
+char(p,47420).
+char(1,47421).
+char(6,47422).
+char(4,47423).
+char(5,47424).
+char(p,47425).
+char(4,47426).
+char(6,47427).
+char(8,47428).
+char(0,47429).
+char(p,47430).
+char(6,47431).
+char(8,47432).
+char(5,47433).
+char(2,47434).
+char(p,47435).
+char(o,47436).
+char(m,47437).
+char(5,47438).
+char(6,47439).
+char(6,47440).
+char(0,47441).
+char(c,47442).
+char(c,47443).
+char(p,47444).
+char(o,47445).
+char(m,47446).
+char(7,47447).
+char(3,47448).
+char(1,47449).
+char(5,47450).
+char(m,47451).
+char(o,47452).
+char(2,47453).
+char(4,47454).
+char(4,47455).
+char(4,47456).
+char(p,47457).
+char(6,47458).
+char(7,47459).
+char(2,47460).
+char(5,47461).
+char(c,47462).
+char(m,47463).
+char(5,47464).
+char(4,47465).
+char(0,47466).
+char(8,47467).
+char(c,47468).
+char(m,47469).
+char(o,47470).
+char(p,47471).
+char(o,47472).
+char(p,47473).
+char(o,47474).
+char(p,47475).
+char(6,47476).
+char(0,47477).
+char(4,47478).
+char(7,47479).
+char(m,47480).
+char(9,47481).
+char(5,47482).
+char(9,47483).
+char(2,47484).
+char(p,47485).
+char(o,47486).
+char(p,47487).
+char(1,47488).
+char(4,47489).
+char(1,47490).
+char(5,47491).
+char(c,47492).
+char(p,47493).
+char(3,47494).
+char(7,47495).
+char(2,47496).
+char(5,47497).
+char(c,47498).
+char(c,47499).
+char(m,47500).
+char(9,47501).
+char(5,47502).
+char(3,47503).
+char(5,47504).
+char(p,47505).
+char(6,47506).
+char(7,47507).
+char(8,47508).
+char(2,47509).
+char(m,47510).
+char(2,47511).
+char(5,47512).
+char(3,47513).
+char(0,47514).
+char(c,47515).
+char(c,47516).
+char(p,47517).
+char(o,47518).
+char(p,47519).
+char(o,47520).
+char(p,47521).
+char(7,47522).
+char(8,47523).
+char(7,47524).
+char(6,47525).
+char(c,47526).
+char(c,47527).
+char(p,47528).
+char(3,47529).
+char(2,47530).
+char(9,47531).
+char(3,47532).
+char(m,47533).
+char(5,47534).
+char(8,47535).
+char(7,47536).
+char(1,47537).
+char(c,47538).
+char(c,47539).
+char(c,47540).
+char(m,47541).
+char(3,47542).
+char(3,47543).
+char(0,47544).
+char(7,47545).
+char(m,47546).
+char(8,47547).
+char(5,47548).
+char(5,47549).
+char(4,47550).
+char(c,47551).
+char(p,47552).
+char(5,47553).
+char(0,47554).
+char(2,47555).
+char(2,47556).
+char(p,47557).
+char(o,47558).
+char(p,47559).
+char(o,47560).
+char(p,47561).
+char(o,47562).
+char(o,47563).
+char(o,47564).
+char(m,47565).
+char(6,47566).
+char(1,47567).
+char(7,47568).
+char(1,47569).
+char(m,47570).
+char(o,47571).
+char(m,47572).
+char(o,47573).
+char(p,47574).
+char(o,47575).
+char(p,47576).
+char(o,47577).
+char(p,47578).
+char(3,47579).
+char(2,47580).
+char(1,47581).
+char(1,47582).
+char(m,47583).
+char(6,47584).
+char(5,47585).
+char(2,47586).
+char(5,47587).
+char(p,47588).
+char(7,47589).
+char(0,47590).
+char(8,47591).
+char(1,47592).
+char(m,47593).
+char(o,47594).
+char(m,47595).
+char(o,47596).
+char(m,47597).
+char(o,47598).
+char(7,47599).
+char(5,47600).
+char(6,47601).
+char(3,47602).
+char(p,47603).
+char(o,47604).
+char(4,47605).
+char(1,47606).
+char(5,47607).
+char(7,47608).
+char(c,47609).
+char(p,47610).
+char(9,47611).
+char(6,47612).
+char(7,47613).
+char(3,47614).
+char(c,47615).
+char(c,47616).
+char(c,47617).
+char(p,47618).
+char(9,47619).
+char(6,47620).
+char(1,47621).
+char(1,47622).
+char(c,47623).
+char(c,47624).
+char(c,47625).
+char(c,47626).
+char(p,47627).
+char(o,47628).
+char(m,47629).
+char(5,47630).
+char(7,47631).
+char(1,47632).
+char(3,47633).
+char(p,47634).
+char(6,47635).
+char(9,47636).
+char(6,47637).
+char(1,47638).
+char(c,47639).
+char(p,47640).
+char(3,47641).
+char(6,47642).
+char(7,47643).
+char(0,47644).
+char(c,47645).
+char(c,47646).
+char(c,47647).
+char(c,47648).
+char(c,47649).
+char(p,47650).
+char(o,47651).
+char(p,47652).
+char(3,47653).
+char(4,47654).
+char(4,47655).
+char(0,47656).
+char(p,47657).
+char(o,47658).
+char(p,47659).
+char(o,47660).
+char(p,47661).
+char(3,47662).
+char(1,47663).
+char(9,47664).
+char(4,47665).
+char(m,47666).
+char(o,47667).
+char(7,47668).
+char(0,47669).
+char(7,47670).
+char(9,47671).
+char(m,47672).
+char(2,47673).
+char(8,47674).
+char(5,47675).
+char(2,47676).
+char(c,47677).
+char(p,47678).
+char(o,47679).
+char(o,47680).
+char(m,47681).
+char(o,47682).
+char(o,47683).
+char(p,47684).
+char(7,47685).
+char(7,47686).
+char(5,47687).
+char(8,47688).
+char(m,47689).
+char(o,47690).
+char(m,47691).
+char(o,47692).
+char(m,47693).
+char(o,47694).
+char(p,47695).
+char(9,47696).
+char(0,47697).
+char(3,47698).
+char(5,47699).
+char(p,47700).
+char(o,47701).
+char(p,47702).
+char(7,47703).
+char(7,47704).
+char(0,47705).
+char(9,47706).
+char(c,47707).
+char(p,47708).
+char(o,47709).
+char(m,47710).
+char(o,47711).
+char(m,47712).
+char(o,47713).
+char(p,47714).
+char(7,47715).
+char(3,47716).
+char(8,47717).
+char(8,47718).
+char(p,47719).
+char(6,47720).
+char(8,47721).
+char(3,47722).
+char(9,47723).
+char(c,47724).
+char(p,47725).
+char(o,47726).
+char(p,47727).
+char(5,47728).
+char(1,47729).
+char(2,47730).
+char(4,47731).
+char(m,47732).
+char(3,47733).
+char(8,47734).
+char(7,47735).
+char(6,47736).
+char(p,47737).
+char(4,47738).
+char(8,47739).
+char(9,47740).
+char(1,47741).
+char(m,47742).
+char(4,47743).
+char(1,47744).
+char(1,47745).
+char(8,47746).
+char(p,47747).
+char(9,47748).
+char(6,47749).
+char(0,47750).
+char(3,47751).
+char(p,47752).
+char(o,47753).
+char(m,47754).
+char(o,47755).
+char(p,47756).
+char(o,47757).
+char(m,47758).
+char(6,47759).
+char(7,47760).
+char(3,47761).
+char(2,47762).
+char(c,47763).
+char(c,47764).
+char(p,47765).
+char(3,47766).
+char(7,47767).
+char(9,47768).
+char(0,47769).
+char(m,47770).
+char(2,47771).
+char(0,47772).
+char(9,47773).
+char(0,47774).
+char(m,47775).
+char(8,47776).
+char(9,47777).
+char(0,47778).
+char(1,47779).
+char(c,47780).
+char(p,47781).
+char(4,47782).
+char(8,47783).
+char(1,47784).
+char(8,47785).
+char(p,47786).
+char(o,47787).
+char(m,47788).
+char(o,47789).
+char(4,47790).
+char(8,47791).
+char(5,47792).
+char(0,47793).
+char(c,47794).
+char(p,47795).
+char(o,47796).
+char(o,47797).
+char(m,47798).
+char(o,47799).
+char(m,47800).
+char(5,47801).
+char(2,47802).
+char(9,47803).
+char(2,47804).
+char(c,47805).
+char(c,47806).
+char(m,47807).
+char(4,47808).
+char(0,47809).
+char(9,47810).
+char(6,47811).
+char(c,47812).
+char(c,47813).
+char(p,47814).
+char(9,47815).
+char(2,47816).
+char(5,47817).
+char(9,47818).
+char(p,47819).
+char(8,47820).
+char(7,47821).
+char(9,47822).
+char(8,47823).
+char(c,47824).
+char(c,47825).
+char(c,47826).
+char(m,47827).
+char(2,47828).
+char(5,47829).
+char(7,47830).
+char(1,47831).
+char(c,47832).
+char(c,47833).
+char(p,47834).
+char(o,47835).
+char(m,47836).
+char(8,47837).
+char(0,47838).
+char(4,47839).
+char(6,47840).
+char(m,47841).
+char(o,47842).
+char(3,47843).
+char(1,47844).
+char(2,47845).
+char(5,47846).
+char(p,47847).
+char(8,47848).
+char(2,47849).
+char(0,47850).
+char(8,47851).
+char(p,47852).
+char(4,47853).
+char(1,47854).
+char(4,47855).
+char(7,47856).
+char(c,47857).
+char(c,47858).
+char(c,47859).
+char(m,47860).
+char(7,47861).
+char(1,47862).
+char(1,47863).
+char(5,47864).
+char(c,47865).
+char(p,47866).
+char(9,47867).
+char(8,47868).
+char(9,47869).
+char(c,47870).
+char(p,47871).
+char(o,47872).
+char(m,47873).
+char(1,47874).
+char(1,47875).
+char(9,47876).
+char(2,47877).
+char(c,47878).
+char(c,47879).
+char(c,47880).
+char(c,47881).
+char(p,47882).
+char(2,47883).
+char(4,47884).
+char(7,47885).
+char(6,47886).
+char(p,47887).
+char(2,47888).
+char(3,47889).
+char(1,47890).
+char(6,47891).
+char(c,47892).
+char(c,47893).
+char(c,47894).
+char(m,47895).
+char(o,47896).
+char(p,47897).
+char(o,47898).
+char(7,47899).
+char(0,47900).
+char(5,47901).
+char(c,47902).
+char(p,47903).
+char(3,47904).
+char(1,47905).
+char(3,47906).
+char(8,47907).
+char(m,47908).
+char(o,47909).
+char(o,47910).
+char(m,47911).
+char(2,47912).
+char(5,47913).
+char(8,47914).
+char(2,47915).
+char(c,47916).
+char(c,47917).
+char(c,47918).
+char(c,47919).
+char(c,47920).
+char(m,47921).
+char(o,47922).
+char(5,47923).
+char(5,47924).
+char(3,47925).
+char(4,47926).
+char(c,47927).
+char(p,47928).
+char(3,47929).
+char(4,47930).
+char(1,47931).
+char(c,47932).
+char(c,47933).
+char(c,47934).
+char(c,47935).
+char(m,47936).
+char(2,47937).
+char(0,47938).
+char(6,47939).
+char(5,47940).
+char(c,47941).
+char(c,47942).
+char(c,47943).
+char(p,47944).
+char(3,47945).
+char(7,47946).
+char(0,47947).
+char(c,47948).
+char(p,47949).
+char(o,47950).
+char(m,47951).
+char(8,47952).
+char(5,47953).
+char(5,47954).
+char(3,47955).
+char(c,47956).
+char(p,47957).
+char(o,47958).
+char(6,47959).
+char(3,47960).
+char(1,47961).
+char(6,47962).
+char(c,47963).
+char(m,47964).
+char(8,47965).
+char(3,47966).
+char(7,47967).
+char(7,47968).
+char(m,47969).
+char(o,47970).
+char(m,47971).
+char(5,47972).
+char(1,47973).
+char(3,47974).
+char(0,47975).
+char(c,47976).
+char(p,47977).
+char(o,47978).
+char(o,47979).
+char(o,47980).
+char(m,47981).
+char(o,47982).
+char(m,47983).
+char(1,47984).
+char(2,47985).
+char(1,47986).
+char(0,47987).
+char(p,47988).
+char(5,47989).
+char(1,47990).
+char(7,47991).
+char(9,47992).
+char(p,47993).
+char(4,47994).
+char(6,47995).
+char(8,47996).
+char(6,47997).
+char(c,47998).
+char(p,47999).
+char(2,48000).
+char(9,48001).
+char(3,48002).
+char(5,48003).
+char(c,48004).
+char(c,48005).
+char(c,48006).
+char(p,48007).
+char(2,48008).
+char(5,48009).
+char(1,48010).
+char(5,48011).
+char(p,48012).
+char(5,48013).
+char(0,48014).
+char(2,48015).
+char(c,48016).
+char(m,48017).
+char(5,48018).
+char(0,48019).
+char(5,48020).
+char(5,48021).
+char(c,48022).
+char(c,48023).
+char(m,48024).
+char(3,48025).
+char(2,48026).
+char(2,48027).
+char(5,48028).
+char(c,48029).
+char(m,48030).
+char(o,48031).
+char(o,48032).
+char(p,48033).
+char(o,48034).
+char(p,48035).
+char(o,48036).
+char(p,48037).
+char(o,48038).
+char(o,48039).
+char(m,48040).
+char(5,48041).
+char(8,48042).
+char(2,48043).
+char(3,48044).
+char(c,48045).
+char(c,48046).
+char(c,48047).
+char(p,48048).
+char(3,48049).
+char(1,48050).
+char(6,48051).
+char(4,48052).
+char(c,48053).
+char(m,48054).
+char(4,48055).
+char(8,48056).
+char(6,48057).
+char(6,48058).
+char(c,48059).
+char(m,48060).
+char(o,48061).
+char(o,48062).
+char(o,48063).
+char(o,48064).
+char(2,48065).
+char(5,48066).
+char(7,48067).
+char(3,48068).
+char(c,48069).
+char(p,48070).
+char(o,48071).
+char(p,48072).
+char(6,48073).
+char(4,48074).
+char(0,48075).
+char(3,48076).
+char(c,48077).
+char(c,48078).
+char(p,48079).
+char(o,48080).
+char(m,48081).
+char(1,48082).
+char(4,48083).
+char(2,48084).
+char(0,48085).
+char(m,48086).
+char(o,48087).
+char(o,48088).
+char(8,48089).
+char(0,48090).
+char(3,48091).
+char(m,48092).
+char(o,48093).
+char(p,48094).
+char(2,48095).
+char(3,48096).
+char(0,48097).
+char(3,48098).
+char(p,48099).
+char(o,48100).
+char(m,48101).
+char(9,48102).
+char(4,48103).
+char(1,48104).
+char(2,48105).
+char(m,48106).
+char(6,48107).
+char(6,48108).
+char(1,48109).
+char(1,48110).
+char(c,48111).
+char(c,48112).
+char(m,48113).
+char(o,48114).
+char(p,48115).
+char(o,48116).
+char(m,48117).
+char(o,48118).
+char(m,48119).
+char(3,48120).
+char(1,48121).
+char(5,48122).
+char(5,48123).
+char(p,48124).
+char(2,48125).
+char(8,48126).
+char(5,48127).
+char(5,48128).
+char(m,48129).
+char(5,48130).
+char(4,48131).
+char(7,48132).
+char(2,48133).
+char(m,48134).
+char(o,48135).
+char(m,48136).
+char(o,48137).
+char(m,48138).
+char(o,48139).
+char(p,48140).
+char(9,48141).
+char(6,48142).
+char(3,48143).
+char(3,48144).
+char(p,48145).
+char(o,48146).
+char(m,48147).
+char(o,48148).
+char(p,48149).
+char(4,48150).
+char(8,48151).
+char(6,48152).
+char(9,48153).
+char(m,48154).
+char(3,48155).
+char(6,48156).
+char(1,48157).
+char(9,48158).
+char(m,48159).
+char(o,48160).
+char(m,48161).
+char(o,48162).
+char(o,48163).
+char(8,48164).
+char(9,48165).
+char(0,48166).
+char(2,48167).
+char(p,48168).
+char(3,48169).
+char(7,48170).
+char(0,48171).
+char(0,48172).
+char(m,48173).
+char(9,48174).
+char(2,48175).
+char(9,48176).
+char(6,48177).
+char(c,48178).
+char(c,48179).
+char(m,48180).
+char(4,48181).
+char(0,48182).
+char(5,48183).
+char(9,48184).
+char(c,48185).
+char(m,48186).
+char(8,48187).
+char(7,48188).
+char(8,48189).
+char(3,48190).
+char(c,48191).
+char(c,48192).
+char(c,48193).
+char(m,48194).
+char(2,48195).
+char(3,48196).
+char(8,48197).
+char(1,48198).
+char(c,48199).
+char(p,48200).
+char(o,48201).
+char(o,48202).
+char(p,48203).
+char(6,48204).
+char(2,48205).
+char(4,48206).
+char(3,48207).
+char(c,48208).
+char(p,48209).
+char(3,48210).
+char(2,48211).
+char(9,48212).
+char(4,48213).
+char(c,48214).
+char(c,48215).
+char(c,48216).
+char(p,48217).
+char(3,48218).
+char(9,48219).
+char(7,48220).
+char(0,48221).
+char(m,48222).
+char(o,48223).
+char(o,48224).
+char(m,48225).
+char(o,48226).
+char(o,48227).
+char(o,48228).
+char(p,48229).
+char(2,48230).
+char(0,48231).
+char(0,48232).
+char(3,48233).
+char(c,48234).
+char(p,48235).
+char(8,48236).
+char(2,48237).
+char(2,48238).
+char(5,48239).
+char(p,48240).
+char(8,48241).
+char(7,48242).
+char(9,48243).
+char(5,48244).
+char(c,48245).
+char(p,48246).
+char(7,48247).
+char(9,48248).
+char(6,48249).
+char(7,48250).
+char(c,48251).
+char(c,48252).
+char(c,48253).
+char(c,48254).
+char(c,48255).
+char(p,48256).
+char(8,48257).
+char(8,48258).
+char(7,48259).
+char(4,48260).
+char(p,48261).
+char(o,48262).
+char(5,48263).
+char(0,48264).
+char(1,48265).
+char(7,48266).
+char(p,48267).
+char(o,48268).
+char(m,48269).
+char(7,48270).
+char(6,48271).
+char(9,48272).
+char(9,48273).
+char(m,48274).
+char(4,48275).
+char(4,48276).
+char(1,48277).
+char(1,48278).
+char(p,48279).
+char(2,48280).
+char(3,48281).
+char(9,48282).
+char(3,48283).
+char(c,48284).
+char(c,48285).
+char(c,48286).
+char(c,48287).
+char(m,48288).
+char(6,48289).
+char(2,48290).
+char(7,48291).
+char(c,48292).
+char(c,48293).
+char(c,48294).
+char(m,48295).
+char(o,48296).
+char(m,48297).
+char(3,48298).
+char(7,48299).
+char(7,48300).
+char(4,48301).
+char(c,48302).
+char(p,48303).
+char(o,48304).
+char(m,48305).
+char(o,48306).
+char(p,48307).
+char(1,48308).
+char(6,48309).
+char(3,48310).
+char(6,48311).
+char(m,48312).
+char(7,48313).
+char(6,48314).
+char(0,48315).
+char(1,48316).
+char(c,48317).
+char(m,48318).
+char(o,48319).
+char(o,48320).
+char(p,48321).
+char(o,48322).
+char(p,48323).
+char(o,48324).
+char(o,48325).
+char(o,48326).
+char(m,48327).
+char(o,48328).
+char(m,48329).
+char(o,48330).
+char(p,48331).
+char(1,48332).
+char(9,48333).
+char(1,48334).
+char(2,48335).
+char(c,48336).
+char(p,48337).
+char(6,48338).
+char(9,48339).
+char(4,48340).
+char(7,48341).
+char(p,48342).
+char(2,48343).
+char(7,48344).
+char(6,48345).
+char(8,48346).
+char(c,48347).
+char(c,48348).
+char(c,48349).
+char(c,48350).
+char(p,48351).
+char(6,48352).
+char(7,48353).
+char(9,48354).
+char(2,48355).
+char(p,48356).
+char(o,48357).
+char(p,48358).
+char(o,48359).
+char(p,48360).
+char(o,48361).
+char(p,48362).
+char(o,48363).
+char(m,48364).
+char(6,48365).
+char(5,48366).
+char(3,48367).
+char(2,48368).
+char(c,48369).
+char(c,48370).
+char(c,48371).
+char(c,48372).
+char(c,48373).
+char(c,48374).
+char(c,48375).
+char(c,48376).
+char(p,48377).
+char(5,48378).
+char(4,48379).
+char(1,48380).
+char(9,48381).
+char(m,48382).
+char(3,48383).
+char(0,48384).
+char(6,48385).
+char(c,48386).
+char(m,48387).
+char(1,48388).
+char(6,48389).
+char(8,48390).
+char(1,48391).
+char(c,48392).
+char(m,48393).
+char(o,48394).
+char(m,48395).
+char(5,48396).
+char(7,48397).
+char(6,48398).
+char(0,48399).
+char(c,48400).
+char(p,48401).
+char(3,48402).
+char(5,48403).
+char(9,48404).
+char(2,48405).
+char(c,48406).
+char(m,48407).
+char(o,48408).
+char(5,48409).
+char(6,48410).
+char(2,48411).
+char(0,48412).
+char(c,48413).
+char(m,48414).
+char(o,48415).
+char(p,48416).
+char(8,48417).
+char(9,48418).
+char(1,48419).
+char(4,48420).
+char(p,48421).
+char(o,48422).
+char(7,48423).
+char(8,48424).
+char(5,48425).
+char(8,48426).
+char(c,48427).
+char(c,48428).
+char(m,48429).
+char(o,48430).
+char(o,48431).
+char(p,48432).
+char(4,48433).
+char(4,48434).
+char(3,48435).
+char(5,48436).
+char(m,48437).
+char(5,48438).
+char(1,48439).
+char(0,48440).
+char(1,48441).
+char(c,48442).
+char(m,48443).
+char(2,48444).
+char(3,48445).
+char(9,48446).
+char(5,48447).
+char(c,48448).
+char(p,48449).
+char(8,48450).
+char(7,48451).
+char(8,48452).
+char(2,48453).
+char(m,48454).
+char(6,48455).
+char(1,48456).
+char(3,48457).
+char(2,48458).
+char(c,48459).
+char(c,48460).
+char(p,48461).
+char(7,48462).
+char(9,48463).
+char(3,48464).
+char(2,48465).
+char(c,48466).
+char(c,48467).
+char(p,48468).
+char(6,48469).
+char(8,48470).
+char(9,48471).
+char(c,48472).
+char(p,48473).
+char(3,48474).
+char(4,48475).
+char(5,48476).
+char(8,48477).
+char(c,48478).
+char(m,48479).
+char(5,48480).
+char(0,48481).
+char(5,48482).
+char(4,48483).
+char(p,48484).
+char(o,48485).
+char(p,48486).
+char(5,48487).
+char(8,48488).
+char(1,48489).
+char(8,48490).
+char(c,48491).
+char(m,48492).
+char(1,48493).
+char(4,48494).
+char(0,48495).
+char(c,48496).
+char(p,48497).
+char(o,48498).
+char(o,48499).
+char(p,48500).
+char(2,48501).
+char(8,48502).
+char(4,48503).
+char(9,48504).
+char(m,48505).
+char(6,48506).
+char(6,48507).
+char(5,48508).
+char(c,48509).
+char(c,48510).
+char(c,48511).
+char(c,48512).
+char(p,48513).
+char(8,48514).
+char(6,48515).
+char(7,48516).
+char(4,48517).
+char(p,48518).
+char(5,48519).
+char(3,48520).
+char(7,48521).
+char(7,48522).
+char(c,48523).
+char(p,48524).
+char(o,48525).
+char(p,48526).
+char(o,48527).
+char(m,48528).
+char(4,48529).
+char(5,48530).
+char(2,48531).
+char(0,48532).
+char(p,48533).
+char(o,48534).
+char(4,48535).
+char(2,48536).
+char(5,48537).
+char(c,48538).
+char(c,48539).
+char(m,48540).
+char(1,48541).
+char(7,48542).
+char(7,48543).
+char(6,48544).
+char(m,48545).
+char(o,48546).
+char(2,48547).
+char(8,48548).
+char(8,48549).
+char(8,48550).
+char(m,48551).
+char(9,48552).
+char(5,48553).
+char(5,48554).
+char(8,48555).
+char(p,48556).
+char(o,48557).
+char(p,48558).
+char(o,48559).
+char(m,48560).
+char(8,48561).
+char(1,48562).
+char(5,48563).
+char(3,48564).
+char(m,48565).
+char(o,48566).
+char(5,48567).
+char(9,48568).
+char(9,48569).
+char(8,48570).
+char(p,48571).
+char(7,48572).
+char(7,48573).
+char(3,48574).
+char(7,48575).
+char(p,48576).
+char(o,48577).
+char(p,48578).
+char(6,48579).
+char(0,48580).
+char(7,48581).
+char(2,48582).
+char(c,48583).
+char(p,48584).
+char(o,48585).
+char(m,48586).
+char(o,48587).
+char(m,48588).
+char(o,48589).
+char(m,48590).
+char(2,48591).
+char(8,48592).
+char(5,48593).
+char(p,48594).
+char(o,48595).
+char(o,48596).
+char(p,48597).
+char(o,48598).
+char(o,48599).
+char(m,48600).
+char(6,48601).
+char(5,48602).
+char(1,48603).
+char(7,48604).
+char(p,48605).
+char(1,48606).
+char(2,48607).
+char(4,48608).
+char(3,48609).
+char(c,48610).
+char(c,48611).
+char(c,48612).
+char(m,48613).
+char(o,48614).
+char(p,48615).
+char(6,48616).
+char(0,48617).
+char(4,48618).
+char(4,48619).
+char(c,48620).
+char(c,48621).
+char(c,48622).
+char(p,48623).
+char(5,48624).
+char(5,48625).
+char(8,48626).
+char(9,48627).
+char(c,48628).
+char(p,48629).
+char(4,48630).
+char(6,48631).
+char(6,48632).
+char(8,48633).
+char(p,48634).
+char(o,48635).
+char(p,48636).
+char(o,48637).
+char(1,48638).
+char(4,48639).
+char(3,48640).
+char(9,48641).
+char(m,48642).
+char(3,48643).
+char(2,48644).
+char(3,48645).
+char(9,48646).
+char(c,48647).
+char(c,48648).
+char(c,48649).
+char(c,48650).
+char(m,48651).
+char(7,48652).
+char(8,48653).
+char(8,48654).
+char(4,48655).
+char(c,48656).
+char(c,48657).
+char(c,48658).
+char(c,48659).
+char(c,48660).
+char(c,48661).
+char(c,48662).
+char(p,48663).
+char(5,48664).
+char(1,48665).
+char(5,48666).
+char(m,48667).
+char(3,48668).
+char(2,48669).
+char(9,48670).
+char(5,48671).
+char(p,48672).
+char(9,48673).
+char(0,48674).
+char(8,48675).
+char(7,48676).
+char(m,48677).
+char(o,48678).
+char(m,48679).
+char(9,48680).
+char(4,48681).
+char(0,48682).
+char(6,48683).
+char(m,48684).
+char(8,48685).
+char(3,48686).
+char(1,48687).
+char(4,48688).
+char(c,48689).
+char(m,48690).
+char(o,48691).
+char(p,48692).
+char(o,48693).
+char(m,48694).
+char(o,48695).
+char(m,48696).
+char(o,48697).
+char(m,48698).
+char(o,48699).
+char(m,48700).
+char(8,48701).
+char(1,48702).
+char(6,48703).
+char(7,48704).
+char(p,48705).
+char(o,48706).
+char(o,48707).
+char(p,48708).
+char(o,48709).
+char(p,48710).
+char(3,48711).
+char(9,48712).
+char(4,48713).
+char(0,48714).
+char(m,48715).
+char(o,48716).
+char(m,48717).
+char(o,48718).
+char(m,48719).
+char(o,48720).
+char(p,48721).
+char(3,48722).
+char(7,48723).
+char(7,48724).
+char(0,48725).
+char(c,48726).
+char(c,48727).
+char(c,48728).
+char(c,48729).
+char(c,48730).
+char(m,48731).
+char(o,48732).
+char(m,48733).
+char(o,48734).
+char(p,48735).
+char(1,48736).
+char(9,48737).
+char(1,48738).
+char(p,48739).
+char(o,48740).
+char(p,48741).
+char(4,48742).
+char(8,48743).
+char(3,48744).
+char(5,48745).
+char(c,48746).
+char(c,48747).
+char(c,48748).
+char(p,48749).
+char(9,48750).
+char(5,48751).
+char(4,48752).
+char(6,48753).
+char(c,48754).
+char(p,48755).
+char(2,48756).
+char(1,48757).
+char(6,48758).
+char(4,48759).
+char(c,48760).
+char(p,48761).
+char(o,48762).
+char(p,48763).
+char(o,48764).
+char(p,48765).
+char(o,48766).
+char(m,48767).
+char(3,48768).
+char(1,48769).
+char(4,48770).
+char(2,48771).
+char(p,48772).
+char(o,48773).
+char(4,48774).
+char(2,48775).
+char(1,48776).
+char(5,48777).
+char(p,48778).
+char(o,48779).
+char(p,48780).
+char(4,48781).
+char(5,48782).
+char(2,48783).
+char(7,48784).
+char(m,48785).
+char(o,48786).
+char(p,48787).
+char(o,48788).
+char(o,48789).
+char(m,48790).
+char(o,48791).
+char(m,48792).
+char(o,48793).
+char(p,48794).
+char(o,48795).
+char(o,48796).
+char(p,48797).
+char(6,48798).
+char(3,48799).
+char(3,48800).
+char(0,48801).
+char(c,48802).
+char(m,48803).
+char(3,48804).
+char(4,48805).
+char(9,48806).
+char(5,48807).
+char(c,48808).
+char(p,48809).
+char(o,48810).
+char(p,48811).
+char(o,48812).
+char(p,48813).
+char(3,48814).
+char(0,48815).
+char(0,48816).
+char(3,48817).
+char(m,48818).
+char(5,48819).
+char(5,48820).
+char(6,48821).
+char(5,48822).
+char(p,48823).
+char(4,48824).
+char(4,48825).
+char(1,48826).
+char(1,48827).
+char(m,48828).
+char(5,48829).
+char(9,48830).
+char(7,48831).
+char(8,48832).
+char(c,48833).
+char(c,48834).
+char(m,48835).
+char(o,48836).
+char(p,48837).
+char(o,48838).
+char(p,48839).
+char(o,48840).
+char(5,48841).
+char(0,48842).
+char(9,48843).
+char(0,48844).
+char(c,48845).
+char(m,48846).
+char(6,48847).
+char(0,48848).
+char(9,48849).
+char(4,48850).
+char(c,48851).
+char(c,48852).
+char(c,48853).
+char(c,48854).
+char(c,48855).
+char(c,48856).
+char(c,48857).
+char(c,48858).
+char(c,48859).
+char(c,48860).
+char(p,48861).
+char(3,48862).
+char(7,48863).
+char(0,48864).
+char(6,48865).
+char(p,48866).
+char(o,48867).
+char(p,48868).
+char(o,48869).
+char(7,48870).
+char(7,48871).
+char(9,48872).
+char(9,48873).
+char(p,48874).
+char(8,48875).
+char(5,48876).
+char(1,48877).
+char(4,48878).
+char(c,48879).
+char(c,48880).
+char(c,48881).
+char(c,48882).
+char(p,48883).
+char(o,48884).
+char(m,48885).
+char(4,48886).
+char(7,48887).
+char(8,48888).
+char(1,48889).
+char(m,48890).
+char(3,48891).
+char(9,48892).
+char(7,48893).
+char(4,48894).
+char(c,48895).
+char(m,48896).
+char(o,48897).
+char(p,48898).
+char(o,48899).
+char(8,48900).
+char(1,48901).
+char(4,48902).
+char(8,48903).
+char(m,48904).
+char(8,48905).
+char(7,48906).
+char(9,48907).
+char(5,48908).
+char(c,48909).
+char(c,48910).
+char(p,48911).
+char(o,48912).
+char(m,48913).
+char(o,48914).
+char(m,48915).
+char(8,48916).
+char(8,48917).
+char(2,48918).
+char(4,48919).
+char(p,48920).
+char(o,48921).
+char(p,48922).
+char(5,48923).
+char(9,48924).
+char(2,48925).
+char(4,48926).
+char(c,48927).
+char(c,48928).
+char(c,48929).
+char(c,48930).
+char(p,48931).
+char(1,48932).
+char(9,48933).
+char(3,48934).
+char(5,48935).
+char(c,48936).
+char(c,48937).
+char(m,48938).
+char(o,48939).
+char(m,48940).
+char(o,48941).
+char(p,48942).
+char(7,48943).
+char(4,48944).
+char(c,48945).
+char(c,48946).
+char(c,48947).
+char(c,48948).
+char(p,48949).
+char(o,48950).
+char(m,48951).
+char(o,48952).
+char(7,48953).
+char(1,48954).
+char(2,48955).
+char(3,48956).
+char(p,48957).
+char(o,48958).
+char(o,48959).
+char(m,48960).
+char(1,48961).
+char(3,48962).
+char(3,48963).
+char(8,48964).
+char(m,48965).
+char(4,48966).
+char(8,48967).
+char(6,48968).
+char(0,48969).
+char(m,48970).
+char(3,48971).
+char(6,48972).
+char(0,48973).
+char(8,48974).
+char(c,48975).
+char(p,48976).
+char(o,48977).
+char(6,48978).
+char(3,48979).
+char(8,48980).
+char(7,48981).
+char(c,48982).
+char(c,48983).
+char(p,48984).
+char(o,48985).
+char(p,48986).
+char(o,48987).
+char(p,48988).
+char(1,48989).
+char(2,48990).
+char(8,48991).
+char(6,48992).
+char(p,48993).
+char(4,48994).
+char(6,48995).
+char(4,48996).
+char(8,48997).
+char(m,48998).
+char(9,48999).
+char(7,49000).
+char(9,49001).
+char(3,49002).
+char(c,49003).
+char(c,49004).
+char(p,49005).
+char(o,49006).
+char(m,49007).
+char(1,49008).
+char(6,49009).
+char(3,49010).
+char(8,49011).
+char(p,49012).
+char(3,49013).
+char(4,49014).
+char(8,49015).
+char(4,49016).
+char(c,49017).
+char(c,49018).
+char(c,49019).
+char(m,49020).
+char(o,49021).
+char(m,49022).
+char(o,49023).
+char(p,49024).
+char(o,49025).
+char(p,49026).
+char(7,49027).
+char(7,49028).
+char(0,49029).
+char(3,49030).
+char(c,49031).
+char(c,49032).
+char(c,49033).
+char(p,49034).
+char(o,49035).
+char(p,49036).
+char(o,49037).
+char(o,49038).
+char(p,49039).
+char(7,49040).
+char(7,49041).
+char(4,49042).
+char(7,49043).
+char(m,49044).
+char(o,49045).
+char(m,49046).
+char(o,49047).
+char(p,49048).
+char(o,49049).
+char(m,49050).
+char(7,49051).
+char(8,49052).
+char(9,49053).
+char(3,49054).
+char(m,49055).
+char(o,49056).
+char(7,49057).
+char(0,49058).
+char(6,49059).
+char(6,49060).
+char(p,49061).
+char(o,49062).
+char(p,49063).
+char(9,49064).
+char(3,49065).
+char(4,49066).
+char(2,49067).
+char(p,49068).
+char(o,49069).
+char(8,49070).
+char(2,49071).
+char(9,49072).
+char(4,49073).
+char(m,49074).
+char(o,49075).
+char(p,49076).
+char(3,49077).
+char(9,49078).
+char(7,49079).
+char(6,49080).
+char(p,49081).
+char(8,49082).
+char(1,49083).
+char(9,49084).
+char(6,49085).
+char(p,49086).
+char(7,49087).
+char(8,49088).
+char(4,49089).
+char(2,49090).
+char(p,49091).
+char(o,49092).
+char(p,49093).
+char(o,49094).
+char(p,49095).
+char(o,49096).
+char(6,49097).
+char(9,49098).
+char(5,49099).
+char(2,49100).
+char(m,49101).
+char(9,49102).
+char(7,49103).
+char(9,49104).
+char(8,49105).
+char(c,49106).
+char(m,49107).
+char(o,49108).
+char(2,49109).
+char(0,49110).
+char(0,49111).
+char(2,49112).
+char(p,49113).
+char(2,49114).
+char(0,49115).
+char(8,49116).
+char(7,49117).
+char(p,49118).
+char(3,49119).
+char(6,49120).
+char(3,49121).
+char(7,49122).
+char(m,49123).
+char(8,49124).
+char(2,49125).
+char(6,49126).
+char(2,49127).
+char(p,49128).
+char(5,49129).
+char(7,49130).
+char(9,49131).
+char(7,49132).
+char(m,49133).
+char(7,49134).
+char(1,49135).
+char(0,49136).
+char(4,49137).
+char(c,49138).
+char(c,49139).
+char(c,49140).
+char(c,49141).
+char(p,49142).
+char(o,49143).
+char(o,49144).
+char(o,49145).
+char(o,49146).
+char(p,49147).
+char(9,49148).
+char(9,49149).
+char(6,49150).
+char(1,49151).
+char(p,49152).
+char(o,49153).
+char(o,49154).
+char(7,49155).
+char(6,49156).
+char(4,49157).
+char(7,49158).
+char(c,49159).
+char(p,49160).
+char(o,49161).
+char(p,49162).
+char(1,49163).
+char(7,49164).
+char(3,49165).
+char(7,49166).
+char(m,49167).
+char(o,49168).
+char(m,49169).
+char(8,49170).
+char(3,49171).
+char(0,49172).
+char(7,49173).
+char(p,49174).
+char(9,49175).
+char(7,49176).
+char(5,49177).
+char(1,49178).
+char(c,49179).
+char(p,49180).
+char(o,49181).
+char(o,49182).
+char(o,49183).
+char(7,49184).
+char(5,49185).
+char(7,49186).
+char(4,49187).
+char(m,49188).
+char(o,49189).
+char(m,49190).
+char(1,49191).
+char(2,49192).
+char(1,49193).
+char(9,49194).
+char(m,49195).
+char(2,49196).
+char(9,49197).
+char(2,49198).
+char(3,49199).
+char(c,49200).
+char(p,49201).
+char(3,49202).
+char(6,49203).
+char(0,49204).
+char(1,49205).
+char(c,49206).
+char(p,49207).
+char(2,49208).
+char(3,49209).
+char(0,49210).
+char(7,49211).
+char(m,49212).
+char(8,49213).
+char(2,49214).
+char(0,49215).
+char(0,49216).
+char(c,49217).
+char(c,49218).
+char(m,49219).
+char(8,49220).
+char(2,49221).
+char(7,49222).
+char(5,49223).
+char(m,49224).
+char(o,49225).
+char(8,49226).
+char(1,49227).
+char(1,49228).
+char(0,49229).
+char(p,49230).
+char(4,49231).
+char(3,49232).
+char(3,49233).
+char(3,49234).
+char(p,49235).
+char(4,49236).
+char(5,49237).
+char(6,49238).
+char(2,49239).
+char(c,49240).
+char(c,49241).
+char(c,49242).
+char(m,49243).
+char(7,49244).
+char(5,49245).
+char(3,49246).
+char(5,49247).
+char(c,49248).
+char(p,49249).
+char(7,49250).
+char(9,49251).
+char(9,49252).
+char(4,49253).
+char(c,49254).
+char(c,49255).
+char(p,49256).
+char(5,49257).
+char(9,49258).
+char(6,49259).
+char(1,49260).
+char(c,49261).
+char(m,49262).
+char(7,49263).
+char(3,49264).
+char(7,49265).
+char(p,49266).
+char(5,49267).
+char(9,49268).
+char(4,49269).
+char(p,49270).
+char(o,49271).
+char(p,49272).
+char(o,49273).
+char(m,49274).
+char(7,49275).
+char(3,49276).
+char(6,49277).
+char(9,49278).
+char(p,49279).
+char(3,49280).
+char(7,49281).
+char(2,49282).
+char(9,49283).
+char(c,49284).
+char(c,49285).
+char(p,49286).
+char(4,49287).
+char(5,49288).
+char(7,49289).
+char(7,49290).
+char(c,49291).
+char(c,49292).
+char(m,49293).
+char(o,49294).
+char(m,49295).
+char(o,49296).
+char(m,49297).
+char(8,49298).
+char(2,49299).
+char(6,49300).
+char(3,49301).
+char(p,49302).
+char(4,49303).
+char(5,49304).
+char(8,49305).
+char(9,49306).
+char(m,49307).
+char(o,49308).
+char(o,49309).
+char(m,49310).
+char(o,49311).
+char(p,49312).
+char(o,49313).
+char(p,49314).
+char(9,49315).
+char(1,49316).
+char(4,49317).
+char(6,49318).
+char(c,49319).
+char(c,49320).
+char(m,49321).
+char(o,49322).
+char(m,49323).
+char(7,49324).
+char(1,49325).
+char(6,49326).
+char(4,49327).
+char(c,49328).
+char(p,49329).
+char(o,49330).
+char(p,49331).
+char(o,49332).
+char(p,49333).
+char(1,49334).
+char(6,49335).
+char(6,49336).
+char(3,49337).
+char(m,49338).
+char(o,49339).
+char(p,49340).
+char(5,49341).
+char(0,49342).
+char(8,49343).
+char(7,49344).
+char(p,49345).
+char(o,49346).
+char(m,49347).
+char(o,49348).
+char(p,49349).
+char(o,49350).
+char(m,49351).
+char(9,49352).
+char(9,49353).
+char(6,49354).
+char(9,49355).
+char(m,49356).
+char(o,49357).
+char(p,49358).
+char(o,49359).
+char(p,49360).
+char(7,49361).
+char(4,49362).
+char(1,49363).
+char(1,49364).
+char(c,49365).
+char(c,49366).
+char(m,49367).
+char(o,49368).
+char(p,49369).
+char(4,49370).
+char(4,49371).
+char(4,49372).
+char(6,49373).
+char(m,49374).
+char(o,49375).
+char(m,49376).
+char(4,49377).
+char(8,49378).
+char(9,49379).
+char(2,49380).
+char(p,49381).
+char(2,49382).
+char(4,49383).
+char(1,49384).
+char(4,49385).
+char(c,49386).
+char(p,49387).
+char(o,49388).
+char(m,49389).
+char(5,49390).
+char(9,49391).
+char(5,49392).
+char(5,49393).
+char(p,49394).
+char(o,49395).
+char(2,49396).
+char(7,49397).
+char(3,49398).
+char(6,49399).
+char(c,49400).
+char(p,49401).
+char(o,49402).
+char(p,49403).
+char(o,49404).
+char(p,49405).
+char(o,49406).
+char(o,49407).
+char(m,49408).
+char(o,49409).
+char(p,49410).
+char(o,49411).
+char(o,49412).
+char(o,49413).
+char(p,49414).
+char(o,49415).
+char(2,49416).
+char(2,49417).
+char(2,49418).
+char(5,49419).
+char(c,49420).
+char(p,49421).
+char(9,49422).
+char(2,49423).
+char(0,49424).
+char(6,49425).
+char(m,49426).
+char(o,49427).
+char(o,49428).
+char(p,49429).
+char(o,49430).
+char(m,49431).
+char(o,49432).
+char(o,49433).
+char(m,49434).
+char(o,49435).
+char(p,49436).
+char(6,49437).
+char(7,49438).
+char(5,49439).
+char(9,49440).
+char(m,49441).
+char(o,49442).
+char(p,49443).
+char(2,49444).
+char(4,49445).
+char(2,49446).
+char(7,49447).
+char(p,49448).
+char(4,49449).
+char(2,49450).
+char(7,49451).
+char(4,49452).
+char(p,49453).
+char(o,49454).
+char(p,49455).
+char(9,49456).
+char(1,49457).
+char(7,49458).
+char(6,49459).
+char(m,49460).
+char(5,49461).
+char(9,49462).
+char(4,49463).
+char(5,49464).
+char(p,49465).
+char(o,49466).
+char(p,49467).
+char(o,49468).
+char(p,49469).
+char(2,49470).
+char(7,49471).
+char(2,49472).
+char(1,49473).
+char(c,49474).
+char(c,49475).
+char(c,49476).
+char(m,49477).
+char(o,49478).
+char(m,49479).
+char(o,49480).
+char(m,49481).
+char(9,49482).
+char(2,49483).
+char(8,49484).
+char(3,49485).
+char(p,49486).
+char(o,49487).
+char(p,49488).
+char(o,49489).
+char(8,49490).
+char(8,49491).
+char(1,49492).
+char(4,49493).
+char(m,49494).
+char(1,49495).
+char(1,49496).
+char(6,49497).
+char(9,49498).
+char(c,49499).
+char(c,49500).
+char(c,49501).
+char(c,49502).
+char(p,49503).
+char(6,49504).
+char(0,49505).
+char(6,49506).
+char(0,49507).
+char(c,49508).
+char(p,49509).
+char(7,49510).
+char(2,49511).
+char(1,49512).
+char(1,49513).
+char(m,49514).
+char(7,49515).
+char(1,49516).
+char(2,49517).
+char(1,49518).
+char(m,49519).
+char(o,49520).
+char(o,49521).
+char(m,49522).
+char(9,49523).
+char(0,49524).
+char(2,49525).
+char(7,49526).
+char(c,49527).
+char(p,49528).
+char(9,49529).
+char(6,49530).
+char(6,49531).
+char(5,49532).
+char(c,49533).
+char(p,49534).
+char(1,49535).
+char(6,49536).
+char(5,49537).
+char(1,49538).
+char(c,49539).
+char(c,49540).
+char(c,49541).
+char(m,49542).
+char(5,49543).
+char(9,49544).
+char(6,49545).
+char(4,49546).
+char(p,49547).
+char(o,49548).
+char(m,49549).
+char(o,49550).
+char(8,49551).
+char(3,49552).
+char(8,49553).
+char(1,49554).
+char(m,49555).
+char(4,49556).
+char(9,49557).
+char(6,49558).
+char(c,49559).
+char(c,49560).
+char(m,49561).
+char(1,49562).
+char(4,49563).
+char(7,49564).
+char(p,49565).
+char(o,49566).
+char(6,49567).
+char(8,49568).
+char(1,49569).
+char(0,49570).
+char(c,49571).
+char(m,49572).
+char(o,49573).
+char(m,49574).
+char(2,49575).
+char(1,49576).
+char(9,49577).
+char(0,49578).
+char(p,49579).
+char(8,49580).
+char(4,49581).
+char(0,49582).
+char(0,49583).
+char(c,49584).
+char(c,49585).
+char(c,49586).
+char(p,49587).
+char(7,49588).
+char(6,49589).
+char(7,49590).
+char(6,49591).
+char(p,49592).
+char(1,49593).
+char(5,49594).
+char(9,49595).
+char(p,49596).
+char(o,49597).
+char(p,49598).
+char(5,49599).
+char(2,49600).
+char(1,49601).
+char(p,49602).
+char(o,49603).
+char(p,49604).
+char(o,49605).
+char(p,49606).
+char(2,49607).
+char(8,49608).
+char(4,49609).
+char(7,49610).
+char(p,49611).
+char(2,49612).
+char(1,49613).
+char(7,49614).
+char(1,49615).
+char(m,49616).
+char(9,49617).
+char(4,49618).
+char(1,49619).
+char(9,49620).
+char(c,49621).
+char(c,49622).
+char(c,49623).
+char(p,49624).
+char(1,49625).
+char(9,49626).
+char(6,49627).
+char(1,49628).
+char(c,49629).
+char(c,49630).
+char(c,49631).
+char(c,49632).
+char(c,49633).
+char(m,49634).
+char(o,49635).
+char(p,49636).
+char(o,49637).
+char(p,49638).
+char(9,49639).
+char(5,49640).
+char(8,49641).
+char(7,49642).
+char(p,49643).
+char(o,49644).
+char(p,49645).
+char(4,49646).
+char(4,49647).
+char(6,49648).
+char(7,49649).
+char(p,49650).
+char(1,49651).
+char(2,49652).
+char(5,49653).
+char(5,49654).
+char(c,49655).
+char(p,49656).
+char(o,49657).
+char(m,49658).
+char(o,49659).
+char(o,49660).
+char(p,49661).
+char(o,49662).
+char(m,49663).
+char(o,49664).
+char(m,49665).
+char(7,49666).
+char(6,49667).
+char(1,49668).
+char(0,49669).
+char(p,49670).
+char(2,49671).
+char(1,49672).
+char(9,49673).
+char(9,49674).
+char(c,49675).
+char(m,49676).
+char(o,49677).
+char(7,49678).
+char(2,49679).
+char(9,49680).
+char(2,49681).
+char(c,49682).
+char(c,49683).
+char(p,49684).
+char(o,49685).
+char(o,49686).
+char(o,49687).
+char(o,49688).
+char(o,49689).
+char(o,49690).
+char(p,49691).
+char(o,49692).
+char(p,49693).
+char(6,49694).
+char(1,49695).
+char(6,49696).
+char(2,49697).
+char(p,49698).
+char(6,49699).
+char(9,49700).
+char(8,49701).
+char(6,49702).
+char(m,49703).
+char(3,49704).
+char(4,49705).
+char(3,49706).
+char(3,49707).
+char(p,49708).
+char(o,49709).
+char(p,49710).
+char(o,49711).
+char(m,49712).
+char(o,49713).
+char(p,49714).
+char(o,49715).
+char(p,49716).
+char(2,49717).
+char(6,49718).
+char(7,49719).
+char(6,49720).
+char(p,49721).
+char(o,49722).
+char(p,49723).
+char(9,49724).
+char(5,49725).
+char(2,49726).
+char(1,49727).
+char(c,49728).
+char(m,49729).
+char(o,49730).
+char(p,49731).
+char(o,49732).
+char(m,49733).
+char(o,49734).
+char(p,49735).
+char(9,49736).
+char(1,49737).
+char(3,49738).
+char(1,49739).
+char(c,49740).
+char(m,49741).
+char(o,49742).
+char(o,49743).
+char(6,49744).
+char(6,49745).
+char(7,49746).
+char(3,49747).
+char(c,49748).
+char(p,49749).
+char(o,49750).
+char(p,49751).
+char(o,49752).
+char(m,49753).
+char(4,49754).
+char(0,49755).
+char(3,49756).
+char(0,49757).
+char(c,49758).
+char(c,49759).
+char(p,49760).
+char(o,49761).
+char(o,49762).
+char(o,49763).
+char(m,49764).
+char(4,49765).
+char(7,49766).
+char(5,49767).
+char(5,49768).
+char(c,49769).
+char(m,49770).
+char(o,49771).
+char(o,49772).
+char(m,49773).
+char(7,49774).
+char(7,49775).
+char(7,49776).
+char(5,49777).
+char(m,49778).
+char(o,49779).
+char(7,49780).
+char(9,49781).
+char(6,49782).
+char(0,49783).
+char(p,49784).
+char(o,49785).
+char(p,49786).
+char(6,49787).
+char(1,49788).
+char(4,49789).
+char(8,49790).
+char(c,49791).
+char(c,49792).
+char(p,49793).
+char(3,49794).
+char(0,49795).
+char(0,49796).
+char(8,49797).
+char(c,49798).
+char(c,49799).
+char(m,49800).
+char(8,49801).
+char(3,49802).
+char(9,49803).
+char(4,49804).
+char(c,49805).
+char(p,49806).
+char(o,49807).
+char(2,49808).
+char(7,49809).
+char(9,49810).
+char(3,49811).
+char(p,49812).
+char(o,49813).
+char(o,49814).
+char(m,49815).
+char(1,49816).
+char(9,49817).
+char(3,49818).
+char(3,49819).
+char(p,49820).
+char(8,49821).
+char(9,49822).
+char(0,49823).
+char(9,49824).
+char(p,49825).
+char(o,49826).
+char(p,49827).
+char(o,49828).
+char(p,49829).
+char(6,49830).
+char(5,49831).
+char(8,49832).
+char(4,49833).
+char(p,49834).
+char(4,49835).
+char(6,49836).
+char(3,49837).
+char(1,49838).
+char(c,49839).
+char(p,49840).
+char(3,49841).
+char(2,49842).
+char(2,49843).
+char(0,49844).
+char(c,49845).
+char(c,49846).
+char(m,49847).
+char(1,49848).
+char(0,49849).
+char(3,49850).
+char(p,49851).
+char(o,49852).
+char(p,49853).
+char(4,49854).
+char(8,49855).
+char(7,49856).
+char(0,49857).
+char(p,49858).
+char(3,49859).
+char(5,49860).
+char(2,49861).
+char(4,49862).
+char(c,49863).
+char(c,49864).
+char(c,49865).
+char(c,49866).
+char(p,49867).
+char(o,49868).
+char(p,49869).
+char(o,49870).
+char(o,49871).
+char(p,49872).
+char(o,49873).
+char(p,49874).
+char(1,49875).
+char(3,49876).
+char(2,49877).
+char(4,49878).
+char(m,49879).
+char(7,49880).
+char(2,49881).
+char(6,49882).
+char(8,49883).
+char(c,49884).
+char(p,49885).
+char(4,49886).
+char(2,49887).
+char(1,49888).
+char(1,49889).
+char(c,49890).
+char(m,49891).
+char(6,49892).
+char(9,49893).
+char(3,49894).
+char(3,49895).
+char(c,49896).
+char(m,49897).
+char(4,49898).
+char(8,49899).
+char(6,49900).
+char(6,49901).
+char(c,49902).
+char(m,49903).
+char(2,49904).
+char(3,49905).
+char(4,49906).
+char(6,49907).
+char(c,49908).
+char(c,49909).
+char(m,49910).
+char(6,49911).
+char(6,49912).
+char(7,49913).
+char(4,49914).
+char(p,49915).
+char(2,49916).
+char(4,49917).
+char(9,49918).
+char(6,49919).
+char(c,49920).
+char(c,49921).
+char(m,49922).
+char(5,49923).
+char(7,49924).
+char(8,49925).
+char(6,49926).
+char(p,49927).
+char(o,49928).
+char(p,49929).
+char(2,49930).
+char(3,49931).
+char(0,49932).
+char(1,49933).
+char(m,49934).
+char(2,49935).
+char(4,49936).
+char(0,49937).
+char(4,49938).
+char(c,49939).
+char(c,49940).
+char(m,49941).
+char(o,49942).
+char(o,49943).
+char(m,49944).
+char(2,49945).
+char(3,49946).
+char(2,49947).
+char(2,49948).
+char(c,49949).
+char(p,49950).
+char(o,49951).
+char(p,49952).
+char(o,49953).
+char(m,49954).
+char(o,49955).
+char(3,49956).
+char(7,49957).
+char(5,49958).
+char(0,49959).
+char(p,49960).
+char(o,49961).
+char(o,49962).
+char(p,49963).
+char(o,49964).
+char(p,49965).
+char(o,49966).
+char(p,49967).
+char(o,49968).
+char(o,49969).
+char(m,49970).
+char(o,49971).
+char(o,49972).
+char(m,49973).
+char(7,49974).
+char(9,49975).
+char(6,49976).
+char(6,49977).
+char(c,49978).
+char(c,49979).
+char(p,49980).
+char(o,49981).
+char(m,49982).
+char(o,49983).
+char(p,49984).
+char(o,49985).
+char(m,49986).
+char(o,49987).
+char(m,49988).
+char(2,49989).
+char(6,49990).
+char(6,49991).
+char(2,49992).
+char(m,49993).
+char(o,49994).
+char(m,49995).
+char(o,49996).
+char(o,49997).
+char(p,49998).
+char(1,49999).
+char(6,50000).
+char(5,50001).
+char(2,50002).
+char(m,50003).
+char(8,50004).
+char(4,50005).
+char(9,50006).
+char(m,50007).
+char(o,50008).
+char(p,50009).
+char(o,50010).
+char(p,50011).
+char(4,50012).
+char(9,50013).
+char(9,50014).
+char(1,50015).
+char(c,50016).
+char(m,50017).
+char(o,50018).
+char(p,50019).
+char(o,50020).
+char(p,50021).
+char(o,50022).
+char(p,50023).
+char(3,50024).
+char(9,50025).
+char(3,50026).
+char(3,50027).
+char(p,50028).
+char(o,50029).
+char(p,50030).
+char(o,50031).
+char(m,50032).
+char(1,50033).
+char(5,50034).
+char(8,50035).
+char(2,50036).
+char(p,50037).
+char(2,50038).
+char(8,50039).
+char(0,50040).
+char(c,50041).
+char(m,50042).
+char(o,50043).
+char(o,50044).
+char(m,50045).
+char(o,50046).
+char(m,50047).
+char(2,50048).
+char(3,50049).
+char(8,50050).
+char(5,50051).
+char(m,50052).
+char(6,50053).
+char(2,50054).
+char(1,50055).
+char(4,50056).
+char(c,50057).
+char(m,50058).
+char(5,50059).
+char(6,50060).
+char(1,50061).
+char(c,50062).
+char(m,50063).
+char(o,50064).
+char(p,50065).
+char(o,50066).
+char(o,50067).
+char(p,50068).
+char(o,50069).
+char(m,50070).
+char(o,50071).
+char(m,50072).
+char(7,50073).
+char(9,50074).
+char(m,50075).
+char(4,50076).
+char(5,50077).
+char(9,50078).
+char(5,50079).
+char(c,50080).
+char(p,50081).
+char(o,50082).
+char(o,50083).
+char(2,50084).
+char(9,50085).
+char(2,50086).
+char(8,50087).
+char(m,50088).
+char(o,50089).
+char(o,50090).
+char(o,50091).
+char(m,50092).
+char(o,50093).
+char(7,50094).
+char(0,50095).
+char(2,50096).
+char(5,50097).
+char(m,50098).
+char(2,50099).
+char(7,50100).
+char(9,50101).
+char(5,50102).
+char(c,50103).
+char(p,50104).
+char(o,50105).
+char(m,50106).
+char(o,50107).
+char(8,50108).
+char(0,50109).
+char(5,50110).
+char(0,50111).
+char(c,50112).
+char(c,50113).
+char(p,50114).
+char(2,50115).
+char(3,50116).
+char(1,50117).
+char(1,50118).
+char(c,50119).
+char(c,50120).
+char(c,50121).
+char(c,50122).
+char(p,50123).
+char(9,50124).
+char(7,50125).
+char(6,50126).
+char(4,50127).
+char(c,50128).
+char(p,50129).
+char(7,50130).
+char(9,50131).
+char(1,50132).
+char(9,50133).
+char(p,50134).
+char(4,50135).
+char(5,50136).
+char(7,50137).
+char(6,50138).
+char(c,50139).
+char(c,50140).
+char(p,50141).
+char(7,50142).
+char(7,50143).
+char(1,50144).
+char(0,50145).
+char(c,50146).
+char(c,50147).
+char(p,50148).
+char(6,50149).
+char(7,50150).
+char(0,50151).
+char(4,50152).
+char(c,50153).
+char(p,50154).
+char(o,50155).
+char(m,50156).
+char(4,50157).
+char(8,50158).
+char(4,50159).
+char(7,50160).
+char(c,50161).
+char(c,50162).
+char(c,50163).
+char(m,50164).
+char(1,50165).
+char(3,50166).
+char(4,50167).
+char(0,50168).
+char(c,50169).
+char(m,50170).
+char(o,50171).
+char(p,50172).
+char(o,50173).
+char(5,50174).
+char(3,50175).
+char(8,50176).
+char(5,50177).
+char(p,50178).
+char(o,50179).
+char(8,50180).
+char(7,50181).
+char(1,50182).
+char(5,50183).
+char(p,50184).
+char(8,50185).
+char(5,50186).
+char(2,50187).
+char(2,50188).
+char(c,50189).
+char(p,50190).
+char(o,50191).
+char(o,50192).
+char(p,50193).
+char(6,50194).
+char(5,50195).
+char(9,50196).
+char(2,50197).
+char(m,50198).
+char(1,50199).
+char(8,50200).
+char(6,50201).
+char(m,50202).
+char(3,50203).
+char(9,50204).
+char(5,50205).
+char(0,50206).
+char(c,50207).
+char(c,50208).
+char(c,50209).
+char(c,50210).
+char(c,50211).
+char(c,50212).
+char(c,50213).
+char(c,50214).
+char(m,50215).
+char(3,50216).
+char(8,50217).
+char(8,50218).
+char(0,50219).
+char(m,50220).
+char(o,50221).
+char(o,50222).
+char(p,50223).
+char(4,50224).
+char(1,50225).
+char(5,50226).
+char(5,50227).
+char(p,50228).
+char(2,50229).
+char(6,50230).
+char(8,50231).
+char(1,50232).
+char(c,50233).
+char(p,50234).
+char(o,50235).
+char(m,50236).
+char(9,50237).
+char(4,50238).
+char(6,50239).
+char(8,50240).
+char(c,50241).
+char(c,50242).
+char(p,50243).
+char(3,50244).
+char(4,50245).
+char(1,50246).
+char(8,50247).
+char(p,50248).
+char(5,50249).
+char(4,50250).
+char(8,50251).
+char(3,50252).
+char(c,50253).
+char(m,50254).
+char(3,50255).
+char(0,50256).
+char(5,50257).
+char(9,50258).
+char(c,50259).
+char(p,50260).
+char(5,50261).
+char(9,50262).
+char(9,50263).
+char(5,50264).
+char(c,50265).
+char(c,50266).
+char(p,50267).
+char(6,50268).
+char(1,50269).
+char(7,50270).
+char(8,50271).
+char(c,50272).
+char(p,50273).
+char(6,50274).
+char(0,50275).
+char(7,50276).
+char(5,50277).
+char(m,50278).
+char(2,50279).
+char(3,50280).
+char(3,50281).
+char(6,50282).
+char(c,50283).
+char(c,50284).
+char(c,50285).
+char(m,50286).
+char(5,50287).
+char(0,50288).
+char(7,50289).
+char(6,50290).
+char(m,50291).
+char(o,50292).
+char(m,50293).
+char(o,50294).
+char(p,50295).
+char(1,50296).
+char(0,50297).
+char(6,50298).
+char(4,50299).
+char(m,50300).
+char(o,50301).
+char(o,50302).
+char(m,50303).
+char(o,50304).
+char(8,50305).
+char(3,50306).
+char(0,50307).
+char(6,50308).
+char(m,50309).
+char(9,50310).
+char(2,50311).
+char(0,50312).
+char(2,50313).
+char(c,50314).
+char(m,50315).
+char(6,50316).
+char(6,50317).
+char(6,50318).
+char(7,50319).
+char(p,50320).
+char(7,50321).
+char(2,50322).
+char(9,50323).
+char(5,50324).
+char(p,50325).
+char(7,50326).
+char(7,50327).
+char(2,50328).
+char(4,50329).
+char(c,50330).
+char(p,50331).
+char(2,50332).
+char(1,50333).
+char(2,50334).
+char(5,50335).
+char(m,50336).
+char(3,50337).
+char(5,50338).
+char(9,50339).
+char(2,50340).
+char(p,50341).
+char(2,50342).
+char(7,50343).
+char(1,50344).
+char(9,50345).
+char(c,50346).
+char(p,50347).
+char(o,50348).
+char(p,50349).
+char(o,50350).
+char(m,50351).
+char(9,50352).
+char(5,50353).
+char(0,50354).
+char(5,50355).
+char(p,50356).
+char(o,50357).
+char(p,50358).
+char(8,50359).
+char(9,50360).
+char(4,50361).
+char(6,50362).
+char(c,50363).
+char(c,50364).
+char(c,50365).
+char(c,50366).
+char(m,50367).
+char(5,50368).
+char(8,50369).
+char(c,50370).
+char(c,50371).
+char(c,50372).
+char(c,50373).
+char(c,50374).
+char(p,50375).
+char(o,50376).
+char(o,50377).
+char(p,50378).
+char(6,50379).
+char(7,50380).
+char(2,50381).
+char(5,50382).
+char(p,50383).
+char(o,50384).
+char(6,50385).
+char(7,50386).
+char(1,50387).
+char(7,50388).
+char(m,50389).
+char(o,50390).
+char(6,50391).
+char(1,50392).
+char(5,50393).
+char(0,50394).
+char(c,50395).
+char(c,50396).
+char(c,50397).
+char(p,50398).
+char(9,50399).
+char(4,50400).
+char(6,50401).
+char(5,50402).
+char(p,50403).
+char(7,50404).
+char(1,50405).
+char(7,50406).
+char(4,50407).
+char(m,50408).
+char(o,50409).
+char(m,50410).
+char(o,50411).
+char(o,50412).
+char(m,50413).
+char(o,50414).
+char(m,50415).
+char(o,50416).
+char(m,50417).
+char(7,50418).
+char(8,50419).
+char(9,50420).
+char(c,50421).
+char(c,50422).
+char(c,50423).
+char(p,50424).
+char(9,50425).
+char(7,50426).
+char(5,50427).
+char(1,50428).
+char(p,50429).
+char(o,50430).
+char(m,50431).
+char(9,50432).
+char(5,50433).
+char(0,50434).
+char(5,50435).
+char(p,50436).
+char(o,50437).
+char(o,50438).
+char(o,50439).
+char(1,50440).
+char(1,50441).
+char(3,50442).
+char(4,50443).
+char(c,50444).
+char(c,50445).
+char(c,50446).
+char(c,50447).
+char(p,50448).
+char(o,50449).
+char(o,50450).
+char(o,50451).
+char(m,50452).
+char(5,50453).
+char(3,50454).
+char(5,50455).
+char(9,50456).
+char(c,50457).
+char(m,50458).
+char(2,50459).
+char(7,50460).
+char(9,50461).
+char(2,50462).
+char(m,50463).
+char(1,50464).
+char(7,50465).
+char(2,50466).
+char(2,50467).
+char(c,50468).
+char(c,50469).
+char(p,50470).
+char(o,50471).
+char(p,50472).
+char(o,50473).
+char(o,50474).
+char(7,50475).
+char(5,50476).
+char(6,50477).
+char(2,50478).
+char(c,50479).
+char(c,50480).
+char(c,50481).
+char(p,50482).
+char(o,50483).
+char(6,50484).
+char(2,50485).
+char(3,50486).
+char(4,50487).
+char(m,50488).
+char(o,50489).
+char(m,50490).
+char(o,50491).
+char(9,50492).
+char(3,50493).
+char(1,50494).
+char(5,50495).
+char(c,50496).
+char(c,50497).
+char(c,50498).
+char(c,50499).
+char(c,50500).
+char(p,50501).
+char(o,50502).
+char(8,50503).
+char(8,50504).
+char(3,50505).
+char(3,50506).
+char(p,50507).
+char(o,50508).
+char(p,50509).
+char(1,50510).
+char(0,50511).
+char(8,50512).
+char(8,50513).
+char(c,50514).
+char(m,50515).
+char(2,50516).
+char(1,50517).
+char(8,50518).
+char(0,50519).
+char(p,50520).
+char(o,50521).
+char(p,50522).
+char(o,50523).
+char(m,50524).
+char(7,50525).
+char(3,50526).
+char(6,50527).
+char(5,50528).
+char(m,50529).
+char(8,50530).
+char(6,50531).
+char(5,50532).
+char(2,50533).
+char(p,50534).
+char(5,50535).
+char(8,50536).
+char(1,50537).
+char(4,50538).
+char(m,50539).
+char(9,50540).
+char(8,50541).
+char(7,50542).
+char(0,50543).
+char(m,50544).
+char(6,50545).
+char(2,50546).
+char(c,50547).
+char(m,50548).
+char(2,50549).
+char(1,50550).
+char(6,50551).
+char(m,50552).
+char(o,50553).
+char(p,50554).
+char(o,50555).
+char(m,50556).
+char(2,50557).
+char(7,50558).
+char(1,50559).
+char(2,50560).
+char(c,50561).
+char(c,50562).
+char(c,50563).
+char(p,50564).
+char(o,50565).
+char(m,50566).
+char(8,50567).
+char(1,50568).
+char(0,50569).
+char(9,50570).
+char(c,50571).
+char(p,50572).
+char(1,50573).
+char(9,50574).
+char(5,50575).
+char(3,50576).
+char(c,50577).
+char(c,50578).
+char(p,50579).
+char(4,50580).
+char(9,50581).
+char(2,50582).
+char(0,50583).
+char(c,50584).
+char(c,50585).
+char(p,50586).
+char(1,50587).
+char(9,50588).
+char(6,50589).
+char(9,50590).
+char(p,50591).
+char(o,50592).
+char(p,50593).
+char(9,50594).
+char(2,50595).
+char(2,50596).
+char(6,50597).
+char(c,50598).
+char(c,50599).
+char(c,50600).
+char(m,50601).
+char(3,50602).
+char(7,50603).
+char(5,50604).
+char(5,50605).
+char(c,50606).
+char(p,50607).
+char(o,50608).
+char(p,50609).
+char(o,50610).
+char(m,50611).
+char(9,50612).
+char(9,50613).
+char(3,50614).
+char(0,50615).
+char(c,50616).
+char(c,50617).
+char(c,50618).
+char(p,50619).
+char(o,50620).
+char(m,50621).
+char(6,50622).
+char(3,50623).
+char(9,50624).
+char(0,50625).
+char(m,50626).
+char(9,50627).
+char(4,50628).
+char(8,50629).
+char(6,50630).
+char(c,50631).
+char(p,50632).
+char(4,50633).
+char(2,50634).
+char(3,50635).
+char(2,50636).
+char(c,50637).
+char(c,50638).
+char(c,50639).
+char(m,50640).
+char(o,50641).
+char(m,50642).
+char(7,50643).
+char(1,50644).
+char(7,50645).
+char(4,50646).
+char(p,50647).
+char(7,50648).
+char(0,50649).
+char(6,50650).
+char(8,50651).
+char(p,50652).
+char(o,50653).
+char(m,50654).
+char(2,50655).
+char(7,50656).
+char(5,50657).
+char(7,50658).
+char(c,50659).
+char(c,50660).
+char(p,50661).
+char(2,50662).
+char(6,50663).
+char(1,50664).
+char(4,50665).
+char(c,50666).
+char(p,50667).
+char(o,50668).
+char(o,50669).
+char(4,50670).
+char(5,50671).
+char(8,50672).
+char(7,50673).
+char(c,50674).
+char(c,50675).
+char(c,50676).
+char(c,50677).
+char(m,50678).
+char(o,50679).
+char(m,50680).
+char(o,50681).
+char(p,50682).
+char(6,50683).
+char(6,50684).
+char(8,50685).
+char(2,50686).
+char(m,50687).
+char(o,50688).
+char(p,50689).
+char(o,50690).
+char(p,50691).
+char(4,50692).
+char(6,50693).
+char(2,50694).
+char(6,50695).
+char(p,50696).
+char(4,50697).
+char(5,50698).
+char(5,50699).
+char(9,50700).
+char(c,50701).
+char(m,50702).
+char(9,50703).
+char(3,50704).
+char(4,50705).
+char(p,50706).
+char(o,50707).
+char(m,50708).
+char(3,50709).
+char(7,50710).
+char(2,50711).
+char(7,50712).
+char(m,50713).
+char(o,50714).
+char(o,50715).
+char(4,50716).
+char(0,50717).
+char(5,50718).
+char(c,50719).
+char(c,50720).
+char(c,50721).
+char(p,50722).
+char(4,50723).
+char(0,50724).
+char(7,50725).
+char(m,50726).
+char(o,50727).
+char(p,50728).
+char(5,50729).
+char(2,50730).
+char(1,50731).
+char(6,50732).
+char(c,50733).
+char(m,50734).
+char(2,50735).
+char(8,50736).
+char(8,50737).
+char(1,50738).
+char(c,50739).
+char(c,50740).
+char(c,50741).
+char(p,50742).
+char(o,50743).
+char(m,50744).
+char(o,50745).
+char(o,50746).
+char(5,50747).
+char(1,50748).
+char(8,50749).
+char(m,50750).
+char(4,50751).
+char(1,50752).
+char(2,50753).
+char(1,50754).
+char(m,50755).
+char(8,50756).
+char(5,50757).
+char(4,50758).
+char(c,50759).
+char(p,50760).
+char(5,50761).
+char(3,50762).
+char(3,50763).
+char(4,50764).
+char(m,50765).
+char(9,50766).
+char(3,50767).
+char(7,50768).
+char(2,50769).
+char(c,50770).
+char(p,50771).
+char(5,50772).
+char(0,50773).
+char(2,50774).
+char(7,50775).
+char(c,50776).
+char(m,50777).
+char(o,50778).
+char(2,50779).
+char(2,50780).
+char(5,50781).
+char(9,50782).
+char(c,50783).
+char(c,50784).
+char(c,50785).
+char(c,50786).
+char(m,50787).
+char(2,50788).
+char(9,50789).
+char(7,50790).
+char(7,50791).
+char(c,50792).
+char(p,50793).
+char(8,50794).
+char(8,50795).
+char(3,50796).
+char(8,50797).
+char(c,50798).
+char(m,50799).
+char(5,50800).
+char(4,50801).
+char(4,50802).
+char(4,50803).
+char(c,50804).
+char(c,50805).
+char(m,50806).
+char(9,50807).
+char(2,50808).
+char(1,50809).
+char(4,50810).
+char(p,50811).
+char(7,50812).
+char(1,50813).
+char(5,50814).
+char(8,50815).
+char(p,50816).
+char(2,50817).
+char(4,50818).
+char(1,50819).
+char(8,50820).
+char(c,50821).
+char(p,50822).
+char(o,50823).
+char(m,50824).
+char(5,50825).
+char(0,50826).
+char(7,50827).
+char(6,50828).
+char(c,50829).
+char(p,50830).
+char(7,50831).
+char(9,50832).
+char(5,50833).
+char(0,50834).
+char(m,50835).
+char(6,50836).
+char(9,50837).
+char(4,50838).
+char(7,50839).
+char(c,50840).
+char(c,50841).
+char(c,50842).
+char(c,50843).
+char(p,50844).
+char(3,50845).
+char(7,50846).
+char(6,50847).
+char(m,50848).
+char(8,50849).
+char(8,50850).
+char(1,50851).
+char(8,50852).
+char(c,50853).
+char(p,50854).
+char(3,50855).
+char(4,50856).
+char(3,50857).
+char(3,50858).
+char(c,50859).
+char(p,50860).
+char(9,50861).
+char(0,50862).
+char(2,50863).
+char(p,50864).
+char(o,50865).
+char(o,50866).
+char(p,50867).
+char(o,50868).
+char(o,50869).
+char(o,50870).
+char(p,50871).
+char(5,50872).
+char(4,50873).
+char(8,50874).
+char(c,50875).
+char(p,50876).
+char(1,50877).
+char(7,50878).
+char(4,50879).
+char(7,50880).
+char(m,50881).
+char(o,50882).
+char(6,50883).
+char(8,50884).
+char(6,50885).
+char(7,50886).
+char(m,50887).
+char(o,50888).
+char(m,50889).
+char(6,50890).
+char(8,50891).
+char(3,50892).
+char(5,50893).
+char(p,50894).
+char(2,50895).
+char(7,50896).
+char(7,50897).
+char(9,50898).
+char(c,50899).
+char(m,50900).
+char(1,50901).
+char(0,50902).
+char(9,50903).
+char(1,50904).
+char(c,50905).
+char(m,50906).
+char(o,50907).
+char(o,50908).
+char(m,50909).
+char(5,50910).
+char(4,50911).
+char(8,50912).
+char(8,50913).
+char(p,50914).
+char(o,50915).
+char(5,50916).
+char(8,50917).
+char(1,50918).
+char(5,50919).
+char(c,50920).
+char(c,50921).
+char(p,50922).
+char(o,50923).
+char(o,50924).
+char(m,50925).
+char(3,50926).
+char(9,50927).
+char(9,50928).
+char(7,50929).
+char(p,50930).
+char(o,50931).
+char(p,50932).
+char(9,50933).
+char(7,50934).
+char(9,50935).
+char(9,50936).
+char(p,50937).
+char(4,50938).
+char(4,50939).
+char(9,50940).
+char(2,50941).
+char(m,50942).
+char(1,50943).
+char(6,50944).
+char(1,50945).
+char(9,50946).
+char(m,50947).
+char(8,50948).
+char(8,50949).
+char(5,50950).
+char(c,50951).
+char(c,50952).
+char(c,50953).
+char(m,50954).
+char(7,50955).
+char(6,50956).
+char(9,50957).
+char(7,50958).
+char(c,50959).
+char(c,50960).
+char(c,50961).
+char(c,50962).
+char(c,50963).
+char(m,50964).
+char(1,50965).
+char(6,50966).
+char(2,50967).
+char(5,50968).
+char(p,50969).
+char(5,50970).
+char(1,50971).
+char(5,50972).
+char(0,50973).
+char(p,50974).
+char(3,50975).
+char(7,50976).
+char(7,50977).
+char(3,50978).
+char(m,50979).
+char(o,50980).
+char(p,50981).
+char(4,50982).
+char(3,50983).
+char(2,50984).
+char(8,50985).
+char(m,50986).
+char(o,50987).
+char(o,50988).
+char(p,50989).
+char(6,50990).
+char(0,50991).
+char(8,50992).
+char(5,50993).
+char(p,50994).
+char(9,50995).
+char(7,50996).
+char(9,50997).
+char(2,50998).
+char(c,50999).
+char(p,51000).
+char(7,51001).
+char(4,51002).
+char(2,51003).
+char(1,51004).
+char(c,51005).
+char(m,51006).
+char(o,51007).
+char(2,51008).
+char(2,51009).
+char(9,51010).
+char(2,51011).
+char(c,51012).
+char(p,51013).
+char(9,51014).
+char(0,51015).
+char(7,51016).
+char(3,51017).
+char(p,51018).
+char(o,51019).
+char(p,51020).
+char(o,51021).
+char(m,51022).
+char(o,51023).
+char(o,51024).
+char(o,51025).
+char(p,51026).
+char(o,51027).
+char(p,51028).
+char(5,51029).
+char(7,51030).
+char(0,51031).
+char(3,51032).
+char(p,51033).
+char(2,51034).
+char(0,51035).
+char(3,51036).
+char(6,51037).
+char(c,51038).
+char(p,51039).
+char(o,51040).
+char(1,51041).
+char(1,51042).
+char(4,51043).
+char(0,51044).
+char(p,51045).
+char(7,51046).
+char(5,51047).
+char(1,51048).
+char(2,51049).
+char(c,51050).
+char(c,51051).
+char(c,51052).
+char(c,51053).
+char(p,51054).
+char(6,51055).
+char(9,51056).
+char(4,51057).
+char(1,51058).
+char(m,51059).
+char(8,51060).
+char(3,51061).
+char(4,51062).
+char(8,51063).
+char(c,51064).
+char(m,51065).
+char(4,51066).
+char(7,51067).
+char(0,51068).
+char(4,51069).
+char(m,51070).
+char(o,51071).
+char(m,51072).
+char(5,51073).
+char(1,51074).
+char(0,51075).
+char(5,51076).
+char(c,51077).
+char(c,51078).
+char(c,51079).
+char(c,51080).
+char(c,51081).
+char(c,51082).
+char(c,51083).
+char(c,51084).
+char(c,51085).
+char(c,51086).
+char(c,51087).
+char(m,51088).
+char(6,51089).
+char(8,51090).
+char(2,51091).
+char(9,51092).
+char(c,51093).
+char(c,51094).
+char(p,51095).
+char(1,51096).
+char(5,51097).
+char(8,51098).
+char(5,51099).
+char(p,51100).
+char(6,51101).
+char(4,51102).
+char(9,51103).
+char(c,51104).
+char(p,51105).
+char(7,51106).
+char(6,51107).
+char(3,51108).
+char(6,51109).
+char(p,51110).
+char(3,51111).
+char(3,51112).
+char(1,51113).
+char(1,51114).
+char(m,51115).
+char(o,51116).
+char(p,51117).
+char(6,51118).
+char(2,51119).
+char(4,51120).
+char(2,51121).
+char(p,51122).
+char(o,51123).
+char(p,51124).
+char(5,51125).
+char(1,51126).
+char(4,51127).
+char(6,51128).
+char(m,51129).
+char(2,51130).
+char(9,51131).
+char(1,51132).
+char(4,51133).
+char(m,51134).
+char(o,51135).
+char(m,51136).
+char(o,51137).
+char(p,51138).
+char(o,51139).
+char(p,51140).
+char(6,51141).
+char(4,51142).
+char(0,51143).
+char(1,51144).
+char(m,51145).
+char(o,51146).
+char(m,51147).
+char(o,51148).
+char(m,51149).
+char(4,51150).
+char(9,51151).
+char(8,51152).
+char(4,51153).
+char(m,51154).
+char(o,51155).
+char(6,51156).
+char(4,51157).
+char(c,51158).
+char(p,51159).
+char(o,51160).
+char(m,51161).
+char(o,51162).
+char(m,51163).
+char(o,51164).
+char(p,51165).
+char(9,51166).
+char(1,51167).
+char(6,51168).
+char(7,51169).
+char(c,51170).
+char(m,51171).
+char(o,51172).
+char(p,51173).
+char(8,51174).
+char(2,51175).
+char(6,51176).
+char(6,51177).
+char(c,51178).
+char(m,51179).
+char(o,51180).
+char(7,51181).
+char(1,51182).
+char(5,51183).
+char(4,51184).
+char(m,51185).
+char(o,51186).
+char(p,51187).
+char(o,51188).
+char(o,51189).
+char(3,51190).
+char(7,51191).
+char(9,51192).
+char(1,51193).
+char(m,51194).
+char(o,51195).
+char(o,51196).
+char(o,51197).
+char(p,51198).
+char(o,51199).
+char(o,51200).
+char(p,51201).
+char(o,51202).
+char(m,51203).
+char(4,51204).
+char(8,51205).
+char(6,51206).
+char(2,51207).
+char(p,51208).
+char(9,51209).
+char(0,51210).
+char(8,51211).
+char(1,51212).
+char(p,51213).
+char(o,51214).
+char(1,51215).
+char(5,51216).
+char(3,51217).
+char(2,51218).
+char(c,51219).
+char(c,51220).
+char(m,51221).
+char(o,51222).
+char(2,51223).
+char(9,51224).
+char(4,51225).
+char(5,51226).
+char(c,51227).
+char(c,51228).
+char(c,51229).
+char(p,51230).
+char(o,51231).
+char(o,51232).
+char(m,51233).
+char(o,51234).
+char(m,51235).
+char(9,51236).
+char(8,51237).
+char(7,51238).
+char(c,51239).
+char(c,51240).
+char(p,51241).
+char(8,51242).
+char(7,51243).
+char(2,51244).
+char(8,51245).
+char(p,51246).
+char(9,51247).
+char(0,51248).
+char(4,51249).
+char(1,51250).
+char(p,51251).
+char(1,51252).
+char(6,51253).
+char(0,51254).
+char(0,51255).
+char(c,51256).
+char(c,51257).
+char(m,51258).
+char(4,51259).
+char(9,51260).
+char(9,51261).
+char(0,51262).
+char(m,51263).
+char(5,51264).
+char(1,51265).
+char(6,51266).
+char(5,51267).
+char(m,51268).
+char(o,51269).
+char(m,51270).
+char(o,51271).
+char(p,51272).
+char(4,51273).
+char(4,51274).
+char(2,51275).
+char(7,51276).
+char(c,51277).
+char(p,51278).
+char(8,51279).
+char(7,51280).
+char(9,51281).
+char(7,51282).
+char(p,51283).
+char(o,51284).
+char(o,51285).
+char(m,51286).
+char(8,51287).
+char(3,51288).
+char(1,51289).
+char(8,51290).
+char(c,51291).
+char(c,51292).
+char(c,51293).
+char(p,51294).
+char(o,51295).
+char(6,51296).
+char(0,51297).
+char(0,51298).
+char(1,51299).
+char(m,51300).
+char(o,51301).
+char(p,51302).
+char(o,51303).
+char(p,51304).
+char(7,51305).
+char(8,51306).
+char(7,51307).
+char(8,51308).
+char(m,51309).
+char(o,51310).
+char(m,51311).
+char(9,51312).
+char(7,51313).
+char(5,51314).
+char(8,51315).
+char(m,51316).
+char(7,51317).
+char(5,51318).
+char(7,51319).
+char(6,51320).
+char(c,51321).
+char(p,51322).
+char(o,51323).
+char(m,51324).
+char(9,51325).
+char(8,51326).
+char(9,51327).
+char(0,51328).
+char(p,51329).
+char(o,51330).
+char(m,51331).
+char(3,51332).
+char(4,51333).
+char(2,51334).
+char(6,51335).
+char(p,51336).
+char(5,51337).
+char(7,51338).
+char(6,51339).
+char(6,51340).
+char(p,51341).
+char(5,51342).
+char(4,51343).
+char(9,51344).
+char(c,51345).
+char(c,51346).
+char(c,51347).
+char(c,51348).
+char(p,51349).
+char(o,51350).
+char(m,51351).
+char(o,51352).
+char(1,51353).
+char(4,51354).
+char(1,51355).
+char(8,51356).
+char(c,51357).
+char(p,51358).
+char(o,51359).
+char(p,51360).
+char(4,51361).
+char(9,51362).
+char(4,51363).
+char(0,51364).
+char(m,51365).
+char(7,51366).
+char(9,51367).
+char(2,51368).
+char(0,51369).
+char(m,51370).
+char(1,51371).
+char(0,51372).
+char(4,51373).
+char(7,51374).
+char(p,51375).
+char(o,51376).
+char(p,51377).
+char(o,51378).
+char(p,51379).
+char(o,51380).
+char(m,51381).
+char(6,51382).
+char(9,51383).
+char(6,51384).
+char(5,51385).
+char(m,51386).
+char(6,51387).
+char(2,51388).
+char(8,51389).
+char(4,51390).
+char(m,51391).
+char(2,51392).
+char(0,51393).
+char(6,51394).
+char(4,51395).
+char(c,51396).
+char(m,51397).
+char(o,51398).
+char(5,51399).
+char(2,51400).
+char(0,51401).
+char(9,51402).
+char(m,51403).
+char(o,51404).
+char(m,51405).
+char(o,51406).
+char(m,51407).
+char(o,51408).
+char(m,51409).
+char(2,51410).
+char(4,51411).
+char(0,51412).
+char(7,51413).
+char(c,51414).
+char(m,51415).
+char(o,51416).
+char(o,51417).
+char(p,51418).
+char(o,51419).
+char(p,51420).
+char(8,51421).
+char(5,51422).
+char(1,51423).
+char(5,51424).
+char(c,51425).
+char(c,51426).
+char(c,51427).
+char(p,51428).
+char(o,51429).
+char(m,51430).
+char(6,51431).
+char(2,51432).
+char(3,51433).
+char(3,51434).
+char(p,51435).
+char(o,51436).
+char(9,51437).
+char(1,51438).
+char(4,51439).
+char(4,51440).
+char(c,51441).
+char(p,51442).
+char(o,51443).
+char(p,51444).
+char(o,51445).
+char(m,51446).
+char(o,51447).
+char(m,51448).
+char(3,51449).
+char(7,51450).
+char(2,51451).
+char(7,51452).
+char(p,51453).
+char(o,51454).
+char(p,51455).
+char(o,51456).
+char(p,51457).
+char(7,51458).
+char(4,51459).
+char(8,51460).
+char(9,51461).
+char(c,51462).
+char(p,51463).
+char(1,51464).
+char(0,51465).
+char(5,51466).
+char(6,51467).
+char(c,51468).
+char(m,51469).
+char(5,51470).
+char(7,51471).
+char(6,51472).
+char(8,51473).
+char(c,51474).
+char(m,51475).
+char(6,51476).
+char(0,51477).
+char(9,51478).
+char(5,51479).
+char(c,51480).
+char(p,51481).
+char(o,51482).
+char(o,51483).
+char(m,51484).
+char(9,51485).
+char(4,51486).
+char(5,51487).
+char(0,51488).
+char(m,51489).
+char(6,51490).
+char(2,51491).
+char(2,51492).
+char(9,51493).
+char(c,51494).
+char(m,51495).
+char(2,51496).
+char(8,51497).
+char(7,51498).
+char(7,51499).
+char(c,51500).
+char(c,51501).
+char(c,51502).
+char(c,51503).
+char(c,51504).
+char(c,51505).
+char(p,51506).
+char(o,51507).
+char(m,51508).
+char(o,51509).
+char(p,51510).
+char(2,51511).
+char(7,51512).
+char(9,51513).
+char(7,51514).
+char(c,51515).
+char(c,51516).
+char(m,51517).
+char(7,51518).
+char(8,51519).
+char(4,51520).
+char(9,51521).
+char(c,51522).
+char(p,51523).
+char(1,51524).
+char(5,51525).
+char(0,51526).
+char(4,51527).
+char(c,51528).
+char(p,51529).
+char(1,51530).
+char(0,51531).
+char(1,51532).
+char(m,51533).
+char(7,51534).
+char(3,51535).
+char(1,51536).
+char(4,51537).
+char(p,51538).
+char(o,51539).
+char(o,51540).
+char(m,51541).
+char(7,51542).
+char(8,51543).
+char(8,51544).
+char(6,51545).
+char(c,51546).
+char(m,51547).
+char(6,51548).
+char(1,51549).
+char(7,51550).
+char(2,51551).
+char(m,51552).
+char(o,51553).
+char(4,51554).
+char(9,51555).
+char(6,51556).
+char(8,51557).
+char(c,51558).
+char(p,51559).
+char(4,51560).
+char(7,51561).
+char(4,51562).
+char(4,51563).
+char(c,51564).
+char(p,51565).
+char(7,51566).
+char(6,51567).
+char(4,51568).
+char(6,51569).
+char(c,51570).
+char(c,51571).
+char(c,51572).
+char(c,51573).
+char(c,51574).
+char(p,51575).
+char(5,51576).
+char(8,51577).
+char(7,51578).
+char(6,51579).
+char(c,51580).
+char(c,51581).
+char(c,51582).
+char(c,51583).
+char(c,51584).
+char(c,51585).
+char(c,51586).
+char(c,51587).
+char(m,51588).
+char(o,51589).
+char(3,51590).
+char(2,51591).
+char(9,51592).
+char(9,51593).
+char(c,51594).
+char(c,51595).
+char(p,51596).
+char(o,51597).
+char(o,51598).
+char(m,51599).
+char(4,51600).
+char(8,51601).
+char(9,51602).
+char(0,51603).
+char(c,51604).
+char(c,51605).
+char(c,51606).
+char(m,51607).
+char(o,51608).
+char(p,51609).
+char(o,51610).
+char(p,51611).
+char(3,51612).
+char(6,51613).
+char(8,51614).
+char(1,51615).
+char(c,51616).
+char(c,51617).
+char(c,51618).
+char(m,51619).
+char(2,51620).
+char(8,51621).
+char(1,51622).
+char(c,51623).
+char(c,51624).
+char(p,51625).
+char(o,51626).
+char(m,51627).
+char(8,51628).
+char(9,51629).
+char(4,51630).
+char(p,51631).
+char(4,51632).
+char(5,51633).
+char(6,51634).
+char(7,51635).
+char(c,51636).
+char(p,51637).
+char(o,51638).
+char(o,51639).
+char(9,51640).
+char(4,51641).
+char(6,51642).
+char(1,51643).
+char(p,51644).
+char(8,51645).
+char(6,51646).
+char(2,51647).
+char(0,51648).
+char(c,51649).
+char(m,51650).
+char(o,51651).
+char(o,51652).
+char(o,51653).
+char(o,51654).
+char(m,51655).
+char(o,51656).
+char(p,51657).
+char(o,51658).
+char(p,51659).
+char(6,51660).
+char(1,51661).
+char(7,51662).
+char(1,51663).
+char(c,51664).
+char(p,51665).
+char(6,51666).
+char(4,51667).
+char(2,51668).
+char(9,51669).
+char(c,51670).
+char(m,51671).
+char(3,51672).
+char(4,51673).
+char(5,51674).
+char(6,51675).
+char(p,51676).
+char(o,51677).
+char(m,51678).
+char(o,51679).
+char(m,51680).
+char(8,51681).
+char(0,51682).
+char(4,51683).
+char(5,51684).
+char(p,51685).
+char(1,51686).
+char(2,51687).
+char(2,51688).
+char(0,51689).
+char(c,51690).
+char(c,51691).
+char(c,51692).
+char(c,51693).
+char(c,51694).
+char(m,51695).
+char(3,51696).
+char(0,51697).
+char(6,51698).
+char(7,51699).
+char(c,51700).
+char(c,51701).
+char(c,51702).
+char(c,51703).
+char(m,51704).
+char(1,51705).
+char(9,51706).
+char(2,51707).
+char(7,51708).
+char(c,51709).
+char(m,51710).
+char(o,51711).
+char(9,51712).
+char(0,51713).
+char(7,51714).
+char(9,51715).
+char(p,51716).
+char(5,51717).
+char(7,51718).
+char(c,51719).
+char(m,51720).
+char(o,51721).
+char(o,51722).
+char(m,51723).
+char(1,51724).
+char(3,51725).
+char(2,51726).
+char(3,51727).
+char(m,51728).
+char(o,51729).
+char(p,51730).
+char(2,51731).
+char(8,51732).
+char(7,51733).
+char(1,51734).
+char(p,51735).
+char(o,51736).
+char(p,51737).
+char(o,51738).
+char(m,51739).
+char(8,51740).
+char(0,51741).
+char(1,51742).
+char(7,51743).
+char(c,51744).
+char(c,51745).
+char(p,51746).
+char(o,51747).
+char(1,51748).
+char(7,51749).
+char(3,51750).
+char(c,51751).
+char(m,51752).
+char(o,51753).
+char(p,51754).
+char(9,51755).
+char(4,51756).
+char(2,51757).
+char(p,51758).
+char(o,51759).
+char(m,51760).
+char(7,51761).
+char(4,51762).
+char(9,51763).
+char(8,51764).
+char(c,51765).
+char(c,51766).
+char(p,51767).
+char(o,51768).
+char(p,51769).
+char(1,51770).
+char(6,51771).
+char(0,51772).
+char(p,51773).
+char(o,51774).
+char(m,51775).
+char(o,51776).
+char(m,51777).
+char(9,51778).
+char(7,51779).
+char(1,51780).
+char(4,51781).
+char(p,51782).
+char(o,51783).
+char(m,51784).
+char(o,51785).
+char(p,51786).
+char(o,51787).
+char(m,51788).
+char(o,51789).
+char(m,51790).
+char(9,51791).
+char(0,51792).
+char(1,51793).
+char(3,51794).
+char(c,51795).
+char(c,51796).
+char(p,51797).
+char(4,51798).
+char(1,51799).
+char(5,51800).
+char(1,51801).
+char(c,51802).
+char(c,51803).
+char(m,51804).
+char(o,51805).
+char(p,51806).
+char(3,51807).
+char(7,51808).
+char(9,51809).
+char(8,51810).
+char(m,51811).
+char(o,51812).
+char(p,51813).
+char(1,51814).
+char(9,51815).
+char(7,51816).
+char(5,51817).
+char(c,51818).
+char(p,51819).
+char(8,51820).
+char(3,51821).
+char(7,51822).
+char(1,51823).
+char(m,51824).
+char(3,51825).
+char(6,51826).
+char(6,51827).
+char(9,51828).
+char(c,51829).
+char(c,51830).
+char(c,51831).
+char(p,51832).
+char(o,51833).
+char(p,51834).
+char(2,51835).
+char(7,51836).
+char(m,51837).
+char(o,51838).
+char(6,51839).
+char(3,51840).
+char(7,51841).
+char(6,51842).
+char(c,51843).
+char(c,51844).
+char(c,51845).
+char(p,51846).
+char(o,51847).
+char(o,51848).
+char(p,51849).
+char(6,51850).
+char(2,51851).
+char(m,51852).
+char(3,51853).
+char(5,51854).
+char(0,51855).
+char(m,51856).
+char(o,51857).
+char(m,51858).
+char(7,51859).
+char(6,51860).
+char(3,51861).
+char(4,51862).
+char(c,51863).
+char(c,51864).
+char(c,51865).
+char(p,51866).
+char(7,51867).
+char(0,51868).
+char(m,51869).
+char(5,51870).
+char(5,51871).
+char(6,51872).
+char(6,51873).
+char(m,51874).
+char(1,51875).
+char(1,51876).
+char(2,51877).
+char(8,51878).
+char(m,51879).
+char(o,51880).
+char(m,51881).
+char(o,51882).
+char(o,51883).
+char(3,51884).
+char(5,51885).
+char(4,51886).
+char(4,51887).
+char(c,51888).
+char(c,51889).
+char(c,51890).
+char(c,51891).
+char(c,51892).
+char(m,51893).
+char(o,51894).
+char(m,51895).
+char(o,51896).
+char(p,51897).
+char(8,51898).
+char(6,51899).
+char(2,51900).
+char(3,51901).
+char(c,51902).
+char(c,51903).
+char(c,51904).
+char(m,51905).
+char(5,51906).
+char(4,51907).
+char(5,51908).
+char(6,51909).
+char(p,51910).
+char(3,51911).
+char(1,51912).
+char(8,51913).
+char(8,51914).
+char(c,51915).
+char(c,51916).
+char(m,51917).
+char(o,51918).
+char(m,51919).
+char(9,51920).
+char(7,51921).
+char(5,51922).
+char(2,51923).
+char(c,51924).
+char(m,51925).
+char(o,51926).
+char(m,51927).
+char(o,51928).
+char(m,51929).
+char(o,51930).
+char(p,51931).
+char(2,51932).
+char(8,51933).
+char(6,51934).
+char(3,51935).
+char(c,51936).
+char(p,51937).
+char(o,51938).
+char(m,51939).
+char(1,51940).
+char(5,51941).
+char(3,51942).
+char(5,51943).
+char(p,51944).
+char(1,51945).
+char(5,51946).
+char(8,51947).
+char(1,51948).
+char(c,51949).
+char(p,51950).
+char(8,51951).
+char(8,51952).
+char(1,51953).
+char(8,51954).
+char(c,51955).
+char(c,51956).
+char(c,51957).
+char(m,51958).
+char(o,51959).
+char(m,51960).
+char(o,51961).
+char(p,51962).
+char(o,51963).
+char(m,51964).
+char(2,51965).
+char(9,51966).
+char(7,51967).
+char(1,51968).
+char(c,51969).
+char(m,51970).
+char(o,51971).
+char(9,51972).
+char(7,51973).
+char(5,51974).
+char(7,51975).
+char(m,51976).
+char(o,51977).
+char(m,51978).
+char(7,51979).
+char(6,51980).
+char(8,51981).
+char(6,51982).
+char(c,51983).
+char(c,51984).
+char(p,51985).
+char(o,51986).
+char(p,51987).
+char(o,51988).
+char(o,51989).
+char(p,51990).
+char(4,51991).
+char(3,51992).
+char(6,51993).
+char(9,51994).
+char(c,51995).
+char(c,51996).
+char(c,51997).
+char(p,51998).
+char(o,51999).
+char(m,52000).
+char(8,52001).
+char(9,52002).
+char(7,52003).
+char(7,52004).
+char(p,52005).
+char(9,52006).
+char(8,52007).
+char(1,52008).
+char(c,52009).
+char(c,52010).
+char(p,52011).
+char(o,52012).
+char(m,52013).
+char(o,52014).
+char(m,52015).
+char(2,52016).
+char(6,52017).
+char(7,52018).
+char(6,52019).
+char(c,52020).
+char(m,52021).
+char(8,52022).
+char(8,52023).
+char(7,52024).
+char(6,52025).
+char(c,52026).
+char(m,52027).
+char(6,52028).
+char(5,52029).
+char(5,52030).
+char(4,52031).
+char(p,52032).
+char(o,52033).
+char(p,52034).
+char(o,52035).
+char(1,52036).
+char(3,52037).
+char(3,52038).
+char(c,52039).
+char(p,52040).
+char(o,52041).
+char(4,52042).
+char(4,52043).
+char(2,52044).
+char(5,52045).
+char(p,52046).
+char(o,52047).
+char(p,52048).
+char(4,52049).
+char(6,52050).
+char(7,52051).
+char(7,52052).
+char(c,52053).
+char(p,52054).
+char(4,52055).
+char(5,52056).
+char(5,52057).
+char(1,52058).
+char(c,52059).
+char(m,52060).
+char(8,52061).
+char(7,52062).
+char(8,52063).
+char(4,52064).
+char(m,52065).
+char(o,52066).
+char(m,52067).
+char(o,52068).
+char(8,52069).
+char(8,52070).
+char(0,52071).
+char(0,52072).
+char(c,52073).
+char(c,52074).
+char(m,52075).
+char(3,52076).
+char(4,52077).
+char(9,52078).
+char(8,52079).
+char(c,52080).
+char(c,52081).
+char(c,52082).
+char(p,52083).
+char(5,52084).
+char(6,52085).
+char(5,52086).
+char(3,52087).
+char(m,52088).
+char(5,52089).
+char(1,52090).
+char(5,52091).
+char(3,52092).
+char(m,52093).
+char(7,52094).
+char(3,52095).
+char(6,52096).
+char(4,52097).
+char(c,52098).
+char(p,52099).
+char(1,52100).
+char(0,52101).
+char(3,52102).
+char(9,52103).
+char(c,52104).
+char(c,52105).
+char(p,52106).
+char(1,52107).
+char(0,52108).
+char(1,52109).
+char(1,52110).
+char(m,52111).
+char(o,52112).
+char(9,52113).
+char(8,52114).
+char(3,52115).
+char(5,52116).
+char(c,52117).
+char(c,52118).
+char(c,52119).
+char(m,52120).
+char(o,52121).
+char(p,52122).
+char(1,52123).
+char(5,52124).
+char(6,52125).
+char(m,52126).
+char(o,52127).
+char(p,52128).
+char(o,52129).
+char(p,52130).
+char(5,52131).
+char(7,52132).
+char(2,52133).
+char(3,52134).
+char(m,52135).
+char(6,52136).
+char(1,52137).
+char(5,52138).
+char(7,52139).
+char(p,52140).
+char(3,52141).
+char(8,52142).
+char(7,52143).
+char(8,52144).
+char(c,52145).
+char(c,52146).
+char(c,52147).
+char(c,52148).
+char(c,52149).
+char(m,52150).
+char(o,52151).
+char(o,52152).
+char(p,52153).
+char(5,52154).
+char(3,52155).
+char(3,52156).
+char(3,52157).
+char(c,52158).
+char(m,52159).
+char(6,52160).
+char(1,52161).
+char(3,52162).
+char(9,52163).
+char(c,52164).
+char(c,52165).
+char(c,52166).
+char(c,52167).
+char(c,52168).
+char(c,52169).
+char(c,52170).
+char(m,52171).
+char(3,52172).
+char(4,52173).
+char(9,52174).
+char(0,52175).
+char(p,52176).
+char(o,52177).
+char(m,52178).
+char(o,52179).
+char(o,52180).
+char(m,52181).
+char(6,52182).
+char(1,52183).
+char(1,52184).
+char(m,52185).
+char(4,52186).
+char(8,52187).
+char(3,52188).
+char(8,52189).
+char(c,52190).
+char(c,52191).
+char(c,52192).
+char(c,52193).
+char(c,52194).
+char(m,52195).
+char(6,52196).
+char(9,52197).
+char(3,52198).
+char(2,52199).
+char(c,52200).
+char(p,52201).
+char(o,52202).
+char(o,52203).
+char(p,52204).
+char(8,52205).
+char(6,52206).
+char(5,52207).
+char(3,52208).
+char(c,52209).
+char(c,52210).
+char(c,52211).
+char(c,52212).
+char(c,52213).
+char(p,52214).
+char(o,52215).
+char(8,52216).
+char(8,52217).
+char(1,52218).
+char(8,52219).
+char(m,52220).
+char(6,52221).
+char(2,52222).
+char(9,52223).
+char(1,52224).
+char(c,52225).
+char(p,52226).
+char(o,52227).
+char(p,52228).
+char(7,52229).
+char(4,52230).
+char(9,52231).
+char(7,52232).
+char(m,52233).
+char(1,52234).
+char(3,52235).
+char(2,52236).
+char(3,52237).
+char(m,52238).
+char(5,52239).
+char(5,52240).
+char(4,52241).
+char(m,52242).
+char(o,52243).
+char(o,52244).
+char(m,52245).
+char(4,52246).
+char(4,52247).
+char(0,52248).
+char(5,52249).
+char(c,52250).
+char(c,52251).
+char(c,52252).
+char(c,52253).
+char(c,52254).
+char(c,52255).
+char(m,52256).
+char(o,52257).
+char(m,52258).
+char(o,52259).
+char(m,52260).
+char(o,52261).
+char(2,52262).
+char(4,52263).
+char(0,52264).
+char(7,52265).
+char(c,52266).
+char(c,52267).
+char(c,52268).
+char(c,52269).
+char(m,52270).
+char(o,52271).
+char(p,52272).
+char(6,52273).
+char(6,52274).
+char(6,52275).
+char(7,52276).
+char(m,52277).
+char(o,52278).
+char(7,52279).
+char(0,52280).
+char(1,52281).
+char(0,52282).
+char(c,52283).
+char(p,52284).
+char(o,52285).
+char(p,52286).
+char(4,52287).
+char(2,52288).
+char(0,52289).
+char(3,52290).
+char(m,52291).
+char(8,52292).
+char(2,52293).
+char(8,52294).
+char(9,52295).
+char(c,52296).
+char(c,52297).
+char(p,52298).
+char(1,52299).
+char(2,52300).
+char(9,52301).
+char(8,52302).
+char(p,52303).
+char(8,52304).
+char(5,52305).
+char(3,52306).
+char(8,52307).
+char(c,52308).
+char(p,52309).
+char(5,52310).
+char(1,52311).
+char(1,52312).
+char(c,52313).
+char(m,52314).
+char(9,52315).
+char(8,52316).
+char(4,52317).
+char(5,52318).
+char(p,52319).
+char(o,52320).
+char(m,52321).
+char(7,52322).
+char(7,52323).
+char(2,52324).
+char(6,52325).
+char(m,52326).
+char(o,52327).
+char(p,52328).
+char(8,52329).
+char(6,52330).
+char(3,52331).
+char(2,52332).
+char(m,52333).
+char(o,52334).
+char(o,52335).
+char(p,52336).
+char(9,52337).
+char(3,52338).
+char(8,52339).
+char(4,52340).
+char(c,52341).
+char(m,52342).
+char(o,52343).
+char(o,52344).
+char(p,52345).
+char(o,52346).
+char(m,52347).
+char(o,52348).
+char(m,52349).
+char(o,52350).
+char(p,52351).
+char(1,52352).
+char(7,52353).
+char(5,52354).
+char(4,52355).
+char(c,52356).
+char(c,52357).
+char(c,52358).
+char(p,52359).
+char(o,52360).
+char(m,52361).
+char(1,52362).
+char(9,52363).
+char(8,52364).
+char(4,52365).
+char(m,52366).
+char(7,52367).
+char(0,52368).
+char(8,52369).
+char(6,52370).
+char(p,52371).
+char(o,52372).
+char(p,52373).
+char(o,52374).
+char(o,52375).
+char(o,52376).
+char(m,52377).
+char(o,52378).
+char(p,52379).
+char(2,52380).
+char(5,52381).
+char(9,52382).
+char(7,52383).
+char(p,52384).
+char(o,52385).
+char(7,52386).
+char(9,52387).
+char(4,52388).
+char(m,52389).
+char(o,52390).
+char(o,52391).
+char(o,52392).
+char(p,52393).
+char(6,52394).
+char(9,52395).
+char(2,52396).
+char(2,52397).
+char(c,52398).
+char(p,52399).
+char(o,52400).
+char(m,52401).
+char(1,52402).
+char(3,52403).
+char(5,52404).
+char(8,52405).
+char(c,52406).
+char(c,52407).
+char(c,52408).
+char(c,52409).
+char(p,52410).
+char(8,52411).
+char(3,52412).
+char(3,52413).
+char(0,52414).
+char(m,52415).
+char(2,52416).
+char(0,52417).
+char(0,52418).
+char(6,52419).
+char(p,52420).
+char(1,52421).
+char(2,52422).
+char(1,52423).
+char(8,52424).
+char(c,52425).
+char(c,52426).
+char(c,52427).
+char(c,52428).
+char(c,52429).
+char(m,52430).
+char(1,52431).
+char(8,52432).
+char(7,52433).
+char(6,52434).
+char(c,52435).
+char(p,52436).
+char(o,52437).
+char(m,52438).
+char(o,52439).
+char(m,52440).
+char(o,52441).
+char(5,52442).
+char(8,52443).
+char(0,52444).
+char(9,52445).
+char(c,52446).
+char(c,52447).
+char(m,52448).
+char(o,52449).
+char(m,52450).
+char(5,52451).
+char(2,52452).
+char(7,52453).
+char(0,52454).
+char(p,52455).
+char(o,52456).
+char(m,52457).
+char(o,52458).
+char(9,52459).
+char(2,52460).
+char(7,52461).
+char(6,52462).
+char(c,52463).
+char(c,52464).
+char(p,52465).
+char(o,52466).
+char(m,52467).
+char(3,52468).
+char(4,52469).
+char(3,52470).
+char(0,52471).
+char(c,52472).
+char(c,52473).
+char(m,52474).
+char(o,52475).
+char(8,52476).
+char(6,52477).
+char(2,52478).
+char(0,52479).
+char(p,52480).
+char(o,52481).
+char(5,52482).
+char(6,52483).
+char(3,52484).
+char(1,52485).
+char(c,52486).
+char(c,52487).
+char(m,52488).
+char(6,52489).
+char(1,52490).
+char(6,52491).
+char(5,52492).
+char(c,52493).
+char(p,52494).
+char(4,52495).
+char(7,52496).
+char(6,52497).
+char(9,52498).
+char(c,52499).
+char(m,52500).
+char(o,52501).
+char(p,52502).
+char(o,52503).
+char(m,52504).
+char(4,52505).
+char(7,52506).
+char(8,52507).
+char(8,52508).
+char(p,52509).
+char(1,52510).
+char(1,52511).
+char(9,52512).
+char(2,52513).
+char(c,52514).
+char(c,52515).
+char(c,52516).
+char(c,52517).
+char(c,52518).
+char(p,52519).
+char(o,52520).
+char(3,52521).
+char(0,52522).
+char(1,52523).
+char(4,52524).
+char(p,52525).
+char(o,52526).
+char(p,52527).
+char(o,52528).
+char(p,52529).
+char(o,52530).
+char(4,52531).
+char(3,52532).
+char(9,52533).
+char(7,52534).
+char(c,52535).
+char(p,52536).
+char(o,52537).
+char(p,52538).
+char(o,52539).
+char(m,52540).
+char(1,52541).
+char(9,52542).
+char(0,52543).
+char(4,52544).
+char(c,52545).
+char(p,52546).
+char(o,52547).
+char(p,52548).
+char(6,52549).
+char(2,52550).
+char(2,52551).
+char(5,52552).
+char(m,52553).
+char(2,52554).
+char(7,52555).
+char(0,52556).
+char(2,52557).
+char(c,52558).
+char(c,52559).
+char(c,52560).
+char(p,52561).
+char(8,52562).
+char(7,52563).
+char(0,52564).
+char(5,52565).
+char(c,52566).
+char(c,52567).
+char(m,52568).
+char(7,52569).
+char(4,52570).
+char(9,52571).
+char(7,52572).
+char(c,52573).
+char(m,52574).
+char(o,52575).
+char(m,52576).
+char(o,52577).
+char(o,52578).
+char(o,52579).
+char(p,52580).
+char(o,52581).
+char(p,52582).
+char(o,52583).
+char(o,52584).
+char(m,52585).
+char(o,52586).
+char(p,52587).
+char(7,52588).
+char(9,52589).
+char(9,52590).
+char(2,52591).
+char(c,52592).
+char(c,52593).
+char(c,52594).
+char(c,52595).
+char(m,52596).
+char(o,52597).
+char(7,52598).
+char(2,52599).
+char(6,52600).
+char(2,52601).
+char(c,52602).
+char(p,52603).
+char(o,52604).
+char(p,52605).
+char(o,52606).
+char(o,52607).
+char(m,52608).
+char(5,52609).
+char(1,52610).
+char(5,52611).
+char(2,52612).
+char(c,52613).
+char(c,52614).
+char(c,52615).
+char(c,52616).
+char(c,52617).
+char(c,52618).
+char(c,52619).
+char(c,52620).
+char(c,52621).
+char(c,52622).
+char(p,52623).
+char(2,52624).
+char(6,52625).
+char(5,52626).
+char(5,52627).
+char(c,52628).
+char(m,52629).
+char(o,52630).
+char(7,52631).
+char(8,52632).
+char(6,52633).
+char(2,52634).
+char(p,52635).
+char(4,52636).
+char(0,52637).
+char(3,52638).
+char(2,52639).
+char(p,52640).
+char(o,52641).
+char(m,52642).
+char(o,52643).
+char(o,52644).
+char(m,52645).
+char(o,52646).
+char(p,52647).
+char(o,52648).
+char(o,52649).
+char(p,52650).
+char(2,52651).
+char(1,52652).
+char(1,52653).
+char(9,52654).
+char(m,52655).
+char(3,52656).
+char(7,52657).
+char(7,52658).
+char(7,52659).
+char(p,52660).
+char(5,52661).
+char(6,52662).
+char(2,52663).
+char(1,52664).
+char(p,52665).
+char(o,52666).
+char(o,52667).
+char(p,52668).
+char(1,52669).
+char(9,52670).
+char(1,52671).
+char(8,52672).
+char(c,52673).
+char(c,52674).
+char(p,52675).
+char(o,52676).
+char(m,52677).
+char(o,52678).
+char(m,52679).
+char(6,52680).
+char(7,52681).
+char(8,52682).
+char(6,52683).
+char(c,52684).
+char(m,52685).
+char(8,52686).
+char(5,52687).
+char(8,52688).
+char(1,52689).
+char(c,52690).
+char(c,52691).
+char(m,52692).
+char(o,52693).
+char(3,52694).
+char(3,52695).
+char(9,52696).
+char(5,52697).
+char(c,52698).
+char(c,52699).
+char(c,52700).
+char(c,52701).
+char(p,52702).
+char(5,52703).
+char(7,52704).
+char(7,52705).
+char(7,52706).
+char(c,52707).
+char(m,52708).
+char(7,52709).
+char(5,52710).
+char(4,52711).
+char(5,52712).
+char(m,52713).
+char(5,52714).
+char(2,52715).
+char(9,52716).
+char(1,52717).
+char(m,52718).
+char(o,52719).
+char(p,52720).
+char(o,52721).
+char(m,52722).
+char(o,52723).
+char(m,52724).
+char(6,52725).
+char(4,52726).
+char(2,52727).
+char(9,52728).
+char(m,52729).
+char(o,52730).
+char(m,52731).
+char(9,52732).
+char(2,52733).
+char(9,52734).
+char(c,52735).
+char(c,52736).
+char(c,52737).
+char(m,52738).
+char(2,52739).
+char(1,52740).
+char(8,52741).
+char(9,52742).
+char(m,52743).
+char(8,52744).
+char(2,52745).
+char(3,52746).
+char(1,52747).
+char(p,52748).
+char(9,52749).
+char(8,52750).
+char(7,52751).
+char(0,52752).
+char(p,52753).
+char(o,52754).
+char(m,52755).
+char(7,52756).
+char(5,52757).
+char(3,52758).
+char(6,52759).
+char(c,52760).
+char(c,52761).
+char(p,52762).
+char(o,52763).
+char(p,52764).
+char(3,52765).
+char(5,52766).
+char(7,52767).
+char(1,52768).
+char(m,52769).
+char(9,52770).
+char(5,52771).
+char(0,52772).
+char(8,52773).
+char(c,52774).
+char(m,52775).
+char(o,52776).
+char(9,52777).
+char(2,52778).
+char(3,52779).
+char(0,52780).
+char(m,52781).
+char(3,52782).
+char(1,52783).
+char(5,52784).
+char(6,52785).
+char(p,52786).
+char(o,52787).
+char(8,52788).
+char(7,52789).
+char(1,52790).
+char(5,52791).
+char(m,52792).
+char(3,52793).
+char(9,52794).
+char(7,52795).
+char(c,52796).
+char(p,52797).
+char(8,52798).
+char(5,52799).
+char(1,52800).
+char(2,52801).
+char(m,52802).
+char(o,52803).
+char(3,52804).
+char(0,52805).
+char(1,52806).
+char(4,52807).
+char(p,52808).
+char(o,52809).
+char(m,52810).
+char(5,52811).
+char(6,52812).
+char(9,52813).
+char(1,52814).
+char(c,52815).
+char(p,52816).
+char(7,52817).
+char(7,52818).
+char(0,52819).
+char(2,52820).
+char(c,52821).
+char(c,52822).
+char(c,52823).
+char(c,52824).
+char(c,52825).
+char(c,52826).
+char(p,52827).
+char(5,52828).
+char(4,52829).
+char(9,52830).
+char(8,52831).
+char(m,52832).
+char(o,52833).
+char(m,52834).
+char(o,52835).
+char(m,52836).
+char(4,52837).
+char(7,52838).
+char(8,52839).
+char(7,52840).
+char(c,52841).
+char(c,52842).
+char(c,52843).
+char(c,52844).
+char(c,52845).
+char(m,52846).
+char(o,52847).
+char(o,52848).
+char(p,52849).
+char(9,52850).
+char(1,52851).
+char(0,52852).
+char(1,52853).
+char(c,52854).
+char(p,52855).
+char(3,52856).
+char(2,52857).
+char(0,52858).
+char(7,52859).
+char(c,52860).
+char(c,52861).
+char(c,52862).
+char(m,52863).
+char(o,52864).
+char(o,52865).
+char(o,52866).
+char(p,52867).
+char(2,52868).
+char(7,52869).
+char(6,52870).
+char(9,52871).
+char(c,52872).
+char(c,52873).
+char(m,52874).
+char(o,52875).
+char(o,52876).
+char(o,52877).
+char(9,52878).
+char(2,52879).
+char(7,52880).
+char(2,52881).
+char(p,52882).
+char(o,52883).
+char(m,52884).
+char(1,52885).
+char(4,52886).
+char(6,52887).
+char(5,52888).
+char(c,52889).
+char(c,52890).
+char(m,52891).
+char(1,52892).
+char(9,52893).
+char(7,52894).
+char(6,52895).
+char(c,52896).
+char(p,52897).
+char(o,52898).
+char(m,52899).
+char(2,52900).
+char(2,52901).
+char(0,52902).
+char(1,52903).
+char(p,52904).
+char(o,52905).
+char(m,52906).
+char(o,52907).
+char(o,52908).
+char(o,52909).
+char(o,52910).
+char(p,52911).
+char(8,52912).
+char(3,52913).
+char(7,52914).
+char(9,52915).
+char(c,52916).
+char(m,52917).
+char(o,52918).
+char(m,52919).
+char(o,52920).
+char(m,52921).
+char(1,52922).
+char(0,52923).
+char(0,52924).
+char(5,52925).
+char(p,52926).
+char(o,52927).
+char(o,52928).
+char(7,52929).
+char(8,52930).
+char(3,52931).
+char(2,52932).
+char(c,52933).
+char(p,52934).
+char(1,52935).
+char(0,52936).
+char(9,52937).
+char(7,52938).
+char(m,52939).
+char(1,52940).
+char(0,52941).
+char(8,52942).
+char(5,52943).
+char(m,52944).
+char(5,52945).
+char(8,52946).
+char(3,52947).
+char(3,52948).
+char(m,52949).
+char(o,52950).
+char(m,52951).
+char(o,52952).
+char(m,52953).
+char(3,52954).
+char(2,52955).
+char(7,52956).
+char(0,52957).
+char(m,52958).
+char(5,52959).
+char(0,52960).
+char(2,52961).
+char(6,52962).
+char(c,52963).
+char(c,52964).
+char(m,52965).
+char(3,52966).
+char(0,52967).
+char(0,52968).
+char(9,52969).
+char(c,52970).
+char(c,52971).
+char(c,52972).
+char(m,52973).
+char(o,52974).
+char(o,52975).
+char(o,52976).
+char(p,52977).
+char(o,52978).
+char(6,52979).
+char(2,52980).
+char(6,52981).
+char(0,52982).
+char(c,52983).
+char(m,52984).
+char(3,52985).
+char(5,52986).
+char(1,52987).
+char(7,52988).
+char(p,52989).
+char(5,52990).
+char(7,52991).
+char(4,52992).
+char(8,52993).
+char(m,52994).
+char(o,52995).
+char(o,52996).
+char(o,52997).
+char(o,52998).
+char(p,52999).
+char(8,53000).
+char(8,53001).
+char(0,53002).
+char(1,53003).
+char(c,53004).
+char(c,53005).
+char(p,53006).
+char(o,53007).
+char(p,53008).
+char(o,53009).
+char(p,53010).
+char(5,53011).
+char(5,53012).
+char(9,53013).
+char(0,53014).
+char(c,53015).
+char(c,53016).
+char(m,53017).
+char(o,53018).
+char(o,53019).
+char(p,53020).
+char(2,53021).
+char(8,53022).
+char(7,53023).
+char(1,53024).
+char(p,53025).
+char(o,53026).
+char(m,53027).
+char(9,53028).
+char(1,53029).
+char(8,53030).
+char(c,53031).
+char(m,53032).
+char(o,53033).
+char(2,53034).
+char(1,53035).
+char(4,53036).
+char(1,53037).
+char(c,53038).
+char(m,53039).
+char(6,53040).
+char(5,53041).
+char(9,53042).
+char(3,53043).
+char(c,53044).
+char(c,53045).
+char(c,53046).
+char(p,53047).
+char(o,53048).
+char(m,53049).
+char(4,53050).
+char(5,53051).
+char(7,53052).
+char(2,53053).
+char(m,53054).
+char(o,53055).
+char(3,53056).
+char(3,53057).
+char(7,53058).
+char(4,53059).
+char(c,53060).
+char(c,53061).
+char(c,53062).
+char(c,53063).
+char(c,53064).
+char(p,53065).
+char(7,53066).
+char(0,53067).
+char(4,53068).
+char(2,53069).
+char(c,53070).
+char(p,53071).
+char(4,53072).
+char(5,53073).
+char(4,53074).
+char(5,53075).
+char(c,53076).
+char(c,53077).
+char(c,53078).
+char(m,53079).
+char(o,53080).
+char(p,53081).
+char(o,53082).
+char(m,53083).
+char(o,53084).
+char(p,53085).
+char(o,53086).
+char(m,53087).
+char(o,53088).
+char(p,53089).
+char(o,53090).
+char(m,53091).
+char(o,53092).
+char(p,53093).
+char(8,53094).
+char(7,53095).
+char(7,53096).
+char(8,53097).
+char(m,53098).
+char(o,53099).
+char(o,53100).
+char(6,53101).
+char(7,53102).
+char(6,53103).
+char(0,53104).
+char(c,53105).
+char(p,53106).
+char(6,53107).
+char(2,53108).
+char(8,53109).
+char(6,53110).
+char(c,53111).
+char(p,53112).
+char(o,53113).
+char(p,53114).
+char(o,53115).
+char(p,53116).
+char(o,53117).
+char(o,53118).
+char(3,53119).
+char(0,53120).
+char(1,53121).
+char(3,53122).
+char(c,53123).
+char(c,53124).
+char(p,53125).
+char(o,53126).
+char(o,53127).
+char(4,53128).
+char(9,53129).
+char(6,53130).
+char(5,53131).
+char(c,53132).
+char(c,53133).
+char(p,53134).
+char(o,53135).
+char(p,53136).
+char(o,53137).
+char(6,53138).
+char(7,53139).
+char(7,53140).
+char(8,53141).
+char(m,53142).
+char(o,53143).
+char(p,53144).
+char(8,53145).
+char(9,53146).
+char(1,53147).
+char(8,53148).
+char(m,53149).
+char(o,53150).
+char(m,53151).
+char(o,53152).
+char(4,53153).
+char(0,53154).
+char(1,53155).
+char(1,53156).
+char(m,53157).
+char(o,53158).
+char(p,53159).
+char(5,53160).
+char(6,53161).
+char(9,53162).
+char(7,53163).
+char(c,53164).
+char(c,53165).
+char(c,53166).
+char(c,53167).
+char(m,53168).
+char(2,53169).
+char(5,53170).
+char(1,53171).
+char(6,53172).
+char(c,53173).
+char(c,53174).
+char(m,53175).
+char(4,53176).
+char(5,53177).
+char(1,53178).
+char(4,53179).
+char(p,53180).
+char(o,53181).
+char(m,53182).
+char(o,53183).
+char(p,53184).
+char(8,53185).
+char(3,53186).
+char(2,53187).
+char(6,53188).
+char(c,53189).
+char(p,53190).
+char(8,53191).
+char(6,53192).
+char(8,53193).
+char(2,53194).
+char(m,53195).
+char(o,53196).
+char(o,53197).
+char(1,53198).
+char(3,53199).
+char(3,53200).
+char(5,53201).
+char(p,53202).
+char(o,53203).
+char(7,53204).
+char(7,53205).
+char(2,53206).
+char(0,53207).
+char(p,53208).
+char(4,53209).
+char(0,53210).
+char(5,53211).
+char(0,53212).
+char(c,53213).
+char(c,53214).
+char(c,53215).
+char(p,53216).
+char(o,53217).
+char(o,53218).
+char(m,53219).
+char(o,53220).
+char(m,53221).
+char(o,53222).
+char(5,53223).
+char(9,53224).
+char(6,53225).
+char(4,53226).
+char(m,53227).
+char(o,53228).
+char(o,53229).
+char(m,53230).
+char(5,53231).
+char(8,53232).
+char(1,53233).
+char(5,53234).
+char(c,53235).
+char(c,53236).
+char(c,53237).
+char(m,53238).
+char(4,53239).
+char(0,53240).
+char(7,53241).
+char(4,53242).
+char(m,53243).
+char(o,53244).
+char(m,53245).
+char(6,53246).
+char(5,53247).
+char(9,53248).
+char(1,53249).
+char(c,53250).
+char(c,53251).
+char(c,53252).
+char(c,53253).
+char(p,53254).
+char(7,53255).
+char(1,53256).
+char(7,53257).
+char(8,53258).
+char(m,53259).
+char(o,53260).
+char(p,53261).
+char(o,53262).
+char(1,53263).
+char(9,53264).
+char(0,53265).
+char(p,53266).
+char(2,53267).
+char(8,53268).
+char(5,53269).
+char(7,53270).
+char(p,53271).
+char(2,53272).
+char(6,53273).
+char(4,53274).
+char(6,53275).
+char(p,53276).
+char(1,53277).
+char(3,53278).
+char(2,53279).
+char(5,53280).
+char(c,53281).
+char(m,53282).
+char(o,53283).
+char(m,53284).
+char(o,53285).
+char(p,53286).
+char(o,53287).
+char(6,53288).
+char(2,53289).
+char(8,53290).
+char(4,53291).
+char(c,53292).
+char(c,53293).
+char(p,53294).
+char(o,53295).
+char(p,53296).
+char(2,53297).
+char(7,53298).
+char(9,53299).
+char(8,53300).
+char(c,53301).
+char(c,53302).
+char(c,53303).
+char(m,53304).
+char(o,53305).
+char(m,53306).
+char(o,53307).
+char(m,53308).
+char(o,53309).
+char(p,53310).
+char(2,53311).
+char(3,53312).
+char(8,53313).
+char(4,53314).
+char(m,53315).
+char(o,53316).
+char(o,53317).
+char(o,53318).
+char(o,53319).
+char(o,53320).
+char(8,53321).
+char(2,53322).
+char(3,53323).
+char(0,53324).
+char(c,53325).
+char(c,53326).
+char(c,53327).
+char(p,53328).
+char(o,53329).
+char(m,53330).
+char(o,53331).
+char(p,53332).
+char(o,53333).
+char(5,53334).
+char(8,53335).
+char(5,53336).
+char(6,53337).
+char(c,53338).
+char(c,53339).
+char(c,53340).
+char(c,53341).
+char(p,53342).
+char(o,53343).
+char(p,53344).
+char(7,53345).
+char(5,53346).
+char(9,53347).
+char(8,53348).
+char(m,53349).
+char(o,53350).
+char(p,53351).
+char(7,53352).
+char(0,53353).
+char(1,53354).
+char(8,53355).
+char(p,53356).
+char(o,53357).
+char(m,53358).
+char(o,53359).
+char(m,53360).
+char(o,53361).
+char(p,53362).
+char(o,53363).
+char(3,53364).
+char(0,53365).
+char(2,53366).
+char(3,53367).
+char(p,53368).
+char(6,53369).
+char(8,53370).
+char(0,53371).
+char(4,53372).
+char(c,53373).
+char(p,53374).
+char(9,53375).
+char(7,53376).
+char(0,53377).
+char(6,53378).
+char(c,53379).
+char(c,53380).
+char(p,53381).
+char(5,53382).
+char(9,53383).
+char(7,53384).
+char(2,53385).
+char(p,53386).
+char(o,53387).
+char(m,53388).
+char(8,53389).
+char(1,53390).
+char(9,53391).
+char(4,53392).
+char(m,53393).
+char(o,53394).
+char(p,53395).
+char(o,53396).
+char(m,53397).
+char(o,53398).
+char(p,53399).
+char(1,53400).
+char(3,53401).
+char(3,53402).
+char(3,53403).
+char(c,53404).
+char(c,53405).
+char(p,53406).
+char(o,53407).
+char(p,53408).
+char(6,53409).
+char(3,53410).
+char(7,53411).
+char(m,53412).
+char(o,53413).
+char(m,53414).
+char(2,53415).
+char(2,53416).
+char(9,53417).
+char(6,53418).
+char(c,53419).
+char(c,53420).
+char(c,53421).
+char(c,53422).
+char(c,53423).
+char(p,53424).
+char(8,53425).
+char(8,53426).
+char(9,53427).
+char(8,53428).
+char(p,53429).
+char(o,53430).
+char(o,53431).
+char(6,53432).
+char(8,53433).
+char(9,53434).
+char(2,53435).
+char(p,53436).
+char(o,53437).
+char(3,53438).
+char(2,53439).
+char(8,53440).
+char(0,53441).
+char(m,53442).
+char(o,53443).
+char(p,53444).
+char(o,53445).
+char(m,53446).
+char(o,53447).
+char(p,53448).
+char(o,53449).
+char(p,53450).
+char(o,53451).
+char(m,53452).
+char(8,53453).
+char(0,53454).
+char(7,53455).
+char(5,53456).
+char(c,53457).
+char(m,53458).
+char(2,53459).
+char(9,53460).
+char(8,53461).
+char(9,53462).
+char(p,53463).
+char(9,53464).
+char(9,53465).
+char(8,53466).
+char(3,53467).
+char(c,53468).
+char(c,53469).
+char(c,53470).
+char(c,53471).
+char(m,53472).
+char(7,53473).
+char(7,53474).
+char(6,53475).
+char(5,53476).
+char(p,53477).
+char(6,53478).
+char(6,53479).
+char(9,53480).
+char(7,53481).
+char(c,53482).
+char(p,53483).
+char(o,53484).
+char(p,53485).
+char(o,53486).
+char(p,53487).
+char(5,53488).
+char(2,53489).
+char(3,53490).
+char(5,53491).
+char(c,53492).
+char(m,53493).
+char(1,53494).
+char(4,53495).
+char(1,53496).
+char(6,53497).
+char(c,53498).
+char(c,53499).
+char(c,53500).
+char(m,53501).
+char(o,53502).
+char(p,53503).
+char(2,53504).
+char(8,53505).
+char(5,53506).
+char(4,53507).
+char(c,53508).
+char(m,53509).
+char(o,53510).
+char(6,53511).
+char(6,53512).
+char(3,53513).
+char(m,53514).
+char(o,53515).
+char(p,53516).
+char(4,53517).
+char(7,53518).
+char(6,53519).
+char(6,53520).
+char(p,53521).
+char(o,53522).
+char(p,53523).
+char(6,53524).
+char(3,53525).
+char(2,53526).
+char(6,53527).
+char(m,53528).
+char(o,53529).
+char(p,53530).
+char(o,53531).
+char(p,53532).
+char(7,53533).
+char(9,53534).
+char(2,53535).
+char(2,53536).
+char(p,53537).
+char(1,53538).
+char(2,53539).
+char(3,53540).
+char(2,53541).
+char(c,53542).
+char(c,53543).
+char(c,53544).
+char(p,53545).
+char(9,53546).
+char(7,53547).
+char(0,53548).
+char(6,53549).
+char(m,53550).
+char(7,53551).
+char(7,53552).
+char(8,53553).
+char(9,53554).
+char(c,53555).
+char(c,53556).
+char(c,53557).
+char(m,53558).
+char(o,53559).
+char(o,53560).
+char(m,53561).
+char(4,53562).
+char(4,53563).
+char(5,53564).
+char(2,53565).
+char(p,53566).
+char(9,53567).
+char(4,53568).
+char(2,53569).
+char(7,53570).
+char(m,53571).
+char(1,53572).
+char(6,53573).
+char(8,53574).
+char(m,53575).
+char(8,53576).
+char(0,53577).
+char(5,53578).
+char(9,53579).
+char(c,53580).
+char(m,53581).
+char(o,53582).
+char(m,53583).
+char(7,53584).
+char(8,53585).
+char(8,53586).
+char(7,53587).
+char(p,53588).
+char(o,53589).
+char(p,53590).
+char(o,53591).
+char(4,53592).
+char(3,53593).
+char(4,53594).
+char(5,53595).
+char(c,53596).
+char(p,53597).
+char(7,53598).
+char(2,53599).
+char(9,53600).
+char(2,53601).
+char(p,53602).
+char(3,53603).
+char(3,53604).
+char(6,53605).
+char(6,53606).
+char(m,53607).
+char(o,53608).
+char(m,53609).
+char(2,53610).
+char(2,53611).
+char(6,53612).
+char(8,53613).
+char(c,53614).
+char(c,53615).
+char(m,53616).
+char(o,53617).
+char(p,53618).
+char(o,53619).
+char(m,53620).
+char(o,53621).
+char(m,53622).
+char(o,53623).
+char(o,53624).
+char(3,53625).
+char(5,53626).
+char(1,53627).
+char(2,53628).
+char(c,53629).
+char(p,53630).
+char(7,53631).
+char(2,53632).
+char(2,53633).
+char(1,53634).
+char(m,53635).
+char(1,53636).
+char(9,53637).
+char(1,53638).
+char(6,53639).
+char(c,53640).
+char(c,53641).
+char(m,53642).
+char(o,53643).
+char(o,53644).
+char(4,53645).
+char(4,53646).
+char(6,53647).
+char(5,53648).
+char(c,53649).
+char(c,53650).
+char(p,53651).
+char(o,53652).
+char(p,53653).
+char(o,53654).
+char(p,53655).
+char(o,53656).
+char(p,53657).
+char(6,53658).
+char(5,53659).
+char(1,53660).
+char(6,53661).
+char(m,53662).
+char(9,53663).
+char(2,53664).
+char(9,53665).
+char(4,53666).
+char(m,53667).
+char(o,53668).
+char(m,53669).
+char(o,53670).
+char(o,53671).
+char(p,53672).
+char(o,53673).
+char(m,53674).
+char(o,53675).
+char(p,53676).
+char(o,53677).
+char(p,53678).
+char(6,53679).
+char(5,53680).
+char(9,53681).
+char(3,53682).
+char(m,53683).
+char(o,53684).
+char(p,53685).
+char(o,53686).
+char(m,53687).
+char(o,53688).
+char(o,53689).
+char(p,53690).
+char(2,53691).
+char(5,53692).
+char(3,53693).
+char(m,53694).
+char(9,53695).
+char(5,53696).
+char(1,53697).
+char(2,53698).
+char(p,53699).
+char(7,53700).
+char(7,53701).
+char(6,53702).
+char(9,53703).
+char(p,53704).
+char(2,53705).
+char(9,53706).
+char(4,53707).
+char(4,53708).
+char(c,53709).
+char(c,53710).
+char(p,53711).
+char(9,53712).
+char(1,53713).
+char(6,53714).
+char(7,53715).
+char(p,53716).
+char(4,53717).
+char(6,53718).
+char(7,53719).
+char(4,53720).
+char(c,53721).
+char(m,53722).
+char(7,53723).
+char(5,53724).
+char(0,53725).
+char(1,53726).
+char(m,53727).
+char(2,53728).
+char(0,53729).
+char(5,53730).
+char(8,53731).
+char(c,53732).
+char(m,53733).
+char(o,53734).
+char(5,53735).
+char(9,53736).
+char(9,53737).
+char(0,53738).
+char(p,53739).
+char(o,53740).
+char(m,53741).
+char(o,53742).
+char(m,53743).
+char(o,53744).
+char(m,53745).
+char(4,53746).
+char(4,53747).
+char(2,53748).
+char(3,53749).
+char(p,53750).
+char(o,53751).
+char(2,53752).
+char(5,53753).
+char(2,53754).
+char(m,53755).
+char(4,53756).
+char(2,53757).
+char(1,53758).
+char(3,53759).
+char(m,53760).
+char(5,53761).
+char(7,53762).
+char(2,53763).
+char(1,53764).
+char(p,53765).
+char(o,53766).
+char(o,53767).
+char(p,53768).
+char(o,53769).
+char(1,53770).
+char(8,53771).
+char(9,53772).
+char(6,53773).
+char(c,53774).
+char(c,53775).
+char(m,53776).
+char(o,53777).
+char(m,53778).
+char(8,53779).
+char(8,53780).
+char(p,53781).
+char(o,53782).
+char(p,53783).
+char(o,53784).
+char(9,53785).
+char(5,53786).
+char(2,53787).
+char(6,53788).
+char(m,53789).
+char(o,53790).
+char(m,53791).
+char(o,53792).
+char(o,53793).
+char(4,53794).
+char(5,53795).
+char(0,53796).
+char(8,53797).
+char(c,53798).
+char(m,53799).
+char(6,53800).
+char(8,53801).
+char(0,53802).
+char(9,53803).
+char(m,53804).
+char(8,53805).
+char(9,53806).
+char(1,53807).
+char(2,53808).
+char(m,53809).
+char(o,53810).
+char(5,53811).
+char(7,53812).
+char(7,53813).
+char(3,53814).
+char(p,53815).
+char(8,53816).
+char(8,53817).
+char(0,53818).
+char(2,53819).
+char(m,53820).
+char(o,53821).
+char(m,53822).
+char(o,53823).
+char(4,53824).
+char(4,53825).
+char(1,53826).
+char(6,53827).
+char(p,53828).
+char(9,53829).
+char(8,53830).
+char(0,53831).
+char(8,53832).
+char(m,53833).
+char(o,53834).
+char(p,53835).
+char(8,53836).
+char(7,53837).
+char(5,53838).
+char(7,53839).
+char(c,53840).
+char(c,53841).
+char(c,53842).
+char(m,53843).
+char(o,53844).
+char(p,53845).
+char(5,53846).
+char(6,53847).
+char(5,53848).
+char(7,53849).
+char(p,53850).
+char(o,53851).
+char(6,53852).
+char(6,53853).
+char(3,53854).
+char(9,53855).
+char(p,53856).
+char(5,53857).
+char(0,53858).
+char(2,53859).
+char(m,53860).
+char(2,53861).
+char(7,53862).
+char(1,53863).
+char(9,53864).
+char(p,53865).
+char(6,53866).
+char(0,53867).
+char(0,53868).
+char(0,53869).
+char(p,53870).
+char(o,53871).
+char(m,53872).
+char(4,53873).
+char(5,53874).
+char(1,53875).
+char(7,53876).
+char(c,53877).
+char(m,53878).
+char(o,53879).
+char(o,53880).
+char(o,53881).
+char(4,53882).
+char(9,53883).
+char(9,53884).
+char(6,53885).
+char(p,53886).
+char(o,53887).
+char(p,53888).
+char(4,53889).
+char(3,53890).
+char(1,53891).
+char(0,53892).
+char(c,53893).
+char(m,53894).
+char(8,53895).
+char(8,53896).
+char(7,53897).
+char(8,53898).
+char(c,53899).
+char(p,53900).
+char(7,53901).
+char(4,53902).
+char(6,53903).
+char(3,53904).
+char(c,53905).
+char(p,53906).
+char(6,53907).
+char(1,53908).
+char(2,53909).
+char(6,53910).
+char(m,53911).
+char(6,53912).
+char(1,53913).
+char(0,53914).
+char(4,53915).
+char(p,53916).
+char(o,53917).
+char(m,53918).
+char(o,53919).
+char(p,53920).
+char(2,53921).
+char(3,53922).
+char(2,53923).
+char(0,53924).
+char(c,53925).
+char(c,53926).
+char(m,53927).
+char(o,53928).
+char(p,53929).
+char(9,53930).
+char(6,53931).
+char(2,53932).
+char(5,53933).
+char(c,53934).
+char(c,53935).
+char(m,53936).
+char(9,53937).
+char(5,53938).
+char(9,53939).
+char(6,53940).
+char(m,53941).
+char(2,53942).
+char(5,53943).
+char(3,53944).
+char(5,53945).
+char(c,53946).
+char(c,53947).
+char(p,53948).
+char(o,53949).
+char(p,53950).
+char(o,53951).
+char(p,53952).
+char(7,53953).
+char(0,53954).
+char(2,53955).
+char(0,53956).
+char(c,53957).
+char(c,53958).
+char(m,53959).
+char(o,53960).
+char(p,53961).
+char(1,53962).
+char(5,53963).
+char(0,53964).
+char(1,53965).
+char(m,53966).
+char(o,53967).
+char(m,53968).
+char(o,53969).
+char(p,53970).
+char(o,53971).
+char(3,53972).
+char(7,53973).
+char(1,53974).
+char(2,53975).
+char(c,53976).
+char(c,53977).
+char(c,53978).
+char(p,53979).
+char(o,53980).
+char(o,53981).
+char(4,53982).
+char(8,53983).
+char(2,53984).
+char(p,53985).
+char(9,53986).
+char(5,53987).
+char(4,53988).
+char(0,53989).
+char(c,53990).
+char(m,53991).
+char(4,53992).
+char(1,53993).
+char(5,53994).
+char(c,53995).
+char(p,53996).
+char(o,53997).
+char(m,53998).
+char(9,53999).
+char(8,54000).
+char(4,54001).
+char(6,54002).
+char(c,54003).
+char(m,54004).
+char(7,54005).
+char(0,54006).
+char(3,54007).
+char(0,54008).
+char(c,54009).
+char(m,54010).
+char(4,54011).
+char(9,54012).
+char(1,54013).
+char(9,54014).
+char(m,54015).
+char(o,54016).
+char(5,54017).
+char(1,54018).
+char(2,54019).
+char(9,54020).
+char(m,54021).
+char(2,54022).
+char(8,54023).
+char(m,54024).
+char(o,54025).
+char(p,54026).
+char(o,54027).
+char(m,54028).
+char(o,54029).
+char(o,54030).
+char(o,54031).
+char(p,54032).
+char(7,54033).
+char(7,54034).
+char(9,54035).
+char(7,54036).
+char(m,54037).
+char(o,54038).
+char(m,54039).
+char(6,54040).
+char(4,54041).
+char(5,54042).
+char(7,54043).
+char(m,54044).
+char(1,54045).
+char(7,54046).
+char(3,54047).
+char(0,54048).
+char(p,54049).
+char(o,54050).
+char(p,54051).
+char(5,54052).
+char(7,54053).
+char(5,54054).
+char(5,54055).
+char(c,54056).
+char(c,54057).
+char(c,54058).
+char(c,54059).
+char(c,54060).
+char(c,54061).
+char(c,54062).
+char(c,54063).
+char(c,54064).
+char(m,54065).
+char(o,54066).
+char(4,54067).
+char(9,54068).
+char(3,54069).
+char(9,54070).
+char(m,54071).
+char(o,54072).
+char(4,54073).
+char(3,54074).
+char(1,54075).
+char(8,54076).
+char(c,54077).
+char(c,54078).
+char(c,54079).
+char(m,54080).
+char(o,54081).
+char(m,54082).
+char(9,54083).
+char(7,54084).
+char(0,54085).
+char(1,54086).
+char(p,54087).
+char(o,54088).
+char(m,54089).
+char(6,54090).
+char(9,54091).
+char(0,54092).
+char(9,54093).
+char(c,54094).
+char(m,54095).
+char(4,54096).
+char(7,54097).
+char(7,54098).
+char(4,54099).
+char(p,54100).
+char(7,54101).
+char(0,54102).
+char(9,54103).
+char(c,54104).
+char(c,54105).
+char(c,54106).
+char(c,54107).
+char(c,54108).
+char(p,54109).
+char(o,54110).
+char(o,54111).
+char(m,54112).
+char(o,54113).
+char(p,54114).
+char(3,54115).
+char(8,54116).
+char(9,54117).
+char(c,54118).
+char(c,54119).
+char(p,54120).
+char(o,54121).
+char(m,54122).
+char(o,54123).
+char(m,54124).
+char(o,54125).
+char(m,54126).
+char(o,54127).
+char(m,54128).
+char(9,54129).
+char(7,54130).
+char(5,54131).
+char(9,54132).
+char(c,54133).
+char(m,54134).
+char(o,54135).
+char(m,54136).
+char(o,54137).
+char(p,54138).
+char(4,54139).
+char(8,54140).
+char(4,54141).
+char(4,54142).
+char(m,54143).
+char(6,54144).
+char(0,54145).
+char(5,54146).
+char(5,54147).
+char(m,54148).
+char(o,54149).
+char(4,54150).
+char(3,54151).
+char(0,54152).
+char(m,54153).
+char(o,54154).
+char(p,54155).
+char(5,54156).
+char(2,54157).
+char(1,54158).
+char(8,54159).
+char(c,54160).
+char(p,54161).
+char(1,54162).
+char(7,54163).
+char(0,54164).
+char(7,54165).
+char(c,54166).
+char(c,54167).
+char(c,54168).
+char(c,54169).
+char(p,54170).
+char(1,54171).
+char(0,54172).
+char(7,54173).
+char(7,54174).
+char(m,54175).
+char(9,54176).
+char(4,54177).
+char(5,54178).
+char(0,54179).
+char(c,54180).
+char(m,54181).
+char(8,54182).
+char(7,54183).
+char(7,54184).
+char(9,54185).
+char(p,54186).
+char(8,54187).
+char(2,54188).
+char(3,54189).
+char(5,54190).
+char(c,54191).
+char(c,54192).
+char(m,54193).
+char(o,54194).
+char(p,54195).
+char(3,54196).
+char(7,54197).
+char(2,54198).
+char(c,54199).
+char(c,54200).
+char(m,54201).
+char(o,54202).
+char(m,54203).
+char(5,54204).
+char(1,54205).
+char(0,54206).
+char(8,54207).
+char(p,54208).
+char(o,54209).
+char(p,54210).
+char(1,54211).
+char(2,54212).
+char(4,54213).
+char(7,54214).
+char(c,54215).
+char(p,54216).
+char(7,54217).
+char(4,54218).
+char(5,54219).
+char(7,54220).
+char(c,54221).
+char(p,54222).
+char(1,54223).
+char(3,54224).
+char(9,54225).
+char(4,54226).
+char(c,54227).
+char(c,54228).
+char(c,54229).
+char(c,54230).
+char(c,54231).
+char(c,54232).
+char(c,54233).
+char(c,54234).
+char(p,54235).
+char(o,54236).
+char(p,54237).
+char(8,54238).
+char(1,54239).
+char(9,54240).
+char(1,54241).
+char(p,54242).
+char(o,54243).
+char(m,54244).
+char(o,54245).
+char(p,54246).
+char(3,54247).
+char(5,54248).
+char(5,54249).
+char(9,54250).
+char(p,54251).
+char(7,54252).
+char(4,54253).
+char(1,54254).
+char(0,54255).
+char(p,54256).
+char(6,54257).
+char(0,54258).
+char(3,54259).
+char(1,54260).
+char(m,54261).
+char(1,54262).
+char(1,54263).
+char(7,54264).
+char(0,54265).
+char(m,54266).
+char(6,54267).
+char(9,54268).
+char(9,54269).
+char(6,54270).
+char(p,54271).
+char(2,54272).
+char(5,54273).
+char(1,54274).
+char(6,54275).
+char(c,54276).
+char(c,54277).
+char(c,54278).
+char(c,54279).
+char(c,54280).
+char(c,54281).
+char(c,54282).
+char(c,54283).
+char(c,54284).
+char(c,54285).
+char(c,54286).
+char(m,54287).
+char(o,54288).
+char(m,54289).
+char(o,54290).
+char(m,54291).
+char(o,54292).
+char(m,54293).
+char(7,54294).
+char(3,54295).
+char(3,54296).
+char(c,54297).
+char(p,54298).
+char(5,54299).
+char(4,54300).
+char(9,54301).
+char(2,54302).
+char(c,54303).
+char(c,54304).
+char(p,54305).
+char(7,54306).
+char(1,54307).
+char(5,54308).
+char(3,54309).
+char(c,54310).
+char(c,54311).
+char(c,54312).
+char(c,54313).
+char(m,54314).
+char(o,54315).
+char(5,54316).
+char(4,54317).
+char(3,54318).
+char(6,54319).
+char(c,54320).
+char(c,54321).
+char(m,54322).
+char(4,54323).
+char(1,54324).
+char(3,54325).
+char(5,54326).
+char(c,54327).
+char(m,54328).
+char(6,54329).
+char(3,54330).
+char(5,54331).
+char(4,54332).
+char(m,54333).
+char(8,54334).
+char(6,54335).
+char(1,54336).
+char(5,54337).
+char(p,54338).
+char(4,54339).
+char(4,54340).
+char(4,54341).
+char(3,54342).
+char(p,54343).
+char(o,54344).
+char(p,54345).
+char(2,54346).
+char(6,54347).
+char(7,54348).
+char(4,54349).
+char(p,54350).
+char(o,54351).
+char(o,54352).
+char(m,54353).
+char(o,54354).
+char(m,54355).
+char(9,54356).
+char(3,54357).
+char(8,54358).
+char(3,54359).
+char(m,54360).
+char(4,54361).
+char(8,54362).
+char(3,54363).
+char(9,54364).
+char(p,54365).
+char(1,54366).
+char(0,54367).
+char(0,54368).
+char(7,54369).
+char(m,54370).
+char(o,54371).
+char(p,54372).
+char(9,54373).
+char(0,54374).
+char(7,54375).
+char(7,54376).
+char(m,54377).
+char(5,54378).
+char(1,54379).
+char(5,54380).
+char(7,54381).
+char(m,54382).
+char(o,54383).
+char(p,54384).
+char(o,54385).
+char(o,54386).
+char(2,54387).
+char(9,54388).
+char(4,54389).
+char(7,54390).
+char(c,54391).
+char(m,54392).
+char(o,54393).
+char(p,54394).
+char(2,54395).
+char(6,54396).
+char(4,54397).
+char(5,54398).
+char(c,54399).
+char(c,54400).
+char(c,54401).
+char(p,54402).
+char(4,54403).
+char(4,54404).
+char(5,54405).
+char(8,54406).
+char(c,54407).
+char(m,54408).
+char(9,54409).
+char(7,54410).
+char(4,54411).
+char(2,54412).
+char(c,54413).
+char(c,54414).
+char(p,54415).
+char(5,54416).
+char(0,54417).
+char(0,54418).
+char(8,54419).
+char(m,54420).
+char(2,54421).
+char(9,54422).
+char(4,54423).
+char(6,54424).
+char(c,54425).
+char(c,54426).
+char(m,54427).
+char(7,54428).
+char(7,54429).
+char(7,54430).
+char(1,54431).
+char(c,54432).
+char(p,54433).
+char(o,54434).
+char(o,54435).
+char(p,54436).
+char(8,54437).
+char(4,54438).
+char(8,54439).
+char(4,54440).
+char(p,54441).
+char(o,54442).
+char(m,54443).
+char(o,54444).
+char(6,54445).
+char(5,54446).
+char(8,54447).
+char(5,54448).
+char(m,54449).
+char(6,54450).
+char(4,54451).
+char(4,54452).
+char(m,54453).
+char(o,54454).
+char(p,54455).
+char(7,54456).
+char(1,54457).
+char(2,54458).
+char(p,54459).
+char(o,54460).
+char(o,54461).
+char(p,54462).
+char(o,54463).
+char(m,54464).
+char(3,54465).
+char(1,54466).
+char(7,54467).
+char(9,54468).
+char(p,54469).
+char(o,54470).
+char(p,54471).
+char(o,54472).
+char(p,54473).
+char(5,54474).
+char(0,54475).
+char(4,54476).
+char(2,54477).
+char(c,54478).
+char(m,54479).
+char(o,54480).
+char(m,54481).
+char(1,54482).
+char(2,54483).
+char(3,54484).
+char(c,54485).
+char(p,54486).
+char(3,54487).
+char(0,54488).
+char(7,54489).
+char(p,54490).
+char(1,54491).
+char(7,54492).
+char(6,54493).
+char(c,54494).
+char(c,54495).
+char(p,54496).
+char(9,54497).
+char(4,54498).
+char(0,54499).
+char(2,54500).
+char(p,54501).
+char(o,54502).
+char(m,54503).
+char(7,54504).
+char(4,54505).
+char(6,54506).
+char(6,54507).
+char(m,54508).
+char(o,54509).
+char(p,54510).
+char(7,54511).
+char(5,54512).
+char(0,54513).
+char(0,54514).
+char(c,54515).
+char(c,54516).
+char(c,54517).
+char(c,54518).
+char(c,54519).
+char(c,54520).
+char(c,54521).
+char(m,54522).
+char(2,54523).
+char(5,54524).
+char(8,54525).
+char(7,54526).
+char(m,54527).
+char(o,54528).
+char(o,54529).
+char(9,54530).
+char(4,54531).
+char(9,54532).
+char(8,54533).
+char(m,54534).
+char(o,54535).
+char(p,54536).
+char(o,54537).
+char(p,54538).
+char(o,54539).
+char(o,54540).
+char(9,54541).
+char(9,54542).
+char(8,54543).
+char(1,54544).
+char(c,54545).
+char(p,54546).
+char(9,54547).
+char(2,54548).
+char(2,54549).
+char(0,54550).
+char(c,54551).
+char(m,54552).
+char(o,54553).
+char(m,54554).
+char(2,54555).
+char(7,54556).
+char(0,54557).
+char(5,54558).
+char(c,54559).
+char(c,54560).
+char(p,54561).
+char(o,54562).
+char(p,54563).
+char(o,54564).
+char(o,54565).
+char(p,54566).
+char(o,54567).
+char(m,54568).
+char(4,54569).
+char(7,54570).
+char(8,54571).
+char(8,54572).
+char(m,54573).
+char(1,54574).
+char(1,54575).
+char(3,54576).
+char(3,54577).
+char(c,54578).
+char(m,54579).
+char(o,54580).
+char(o,54581).
+char(9,54582).
+char(2,54583).
+char(8,54584).
+char(5,54585).
+char(m,54586).
+char(o,54587).
+char(o,54588).
+char(m,54589).
+char(o,54590).
+char(9,54591).
+char(8,54592).
+char(7,54593).
+char(0,54594).
+char(c,54595).
+char(p,54596).
+char(9,54597).
+char(3,54598).
+char(2,54599).
+char(8,54600).
+char(c,54601).
+char(m,54602).
+char(7,54603).
+char(4,54604).
+char(5,54605).
+char(1,54606).
+char(m,54607).
+char(4,54608).
+char(4,54609).
+char(9,54610).
+char(3,54611).
+char(c,54612).
+char(m,54613).
+char(3,54614).
+char(2,54615).
+char(4,54616).
+char(8,54617).
+char(c,54618).
+char(c,54619).
+char(m,54620).
+char(o,54621).
+char(m,54622).
+char(6,54623).
+char(7,54624).
+char(6,54625).
+char(6,54626).
+char(m,54627).
+char(o,54628).
+char(p,54629).
+char(o,54630).
+char(m,54631).
+char(o,54632).
+char(1,54633).
+char(5,54634).
+char(4,54635).
+char(0,54636).
+char(c,54637).
+char(m,54638).
+char(5,54639).
+char(8,54640).
+char(3,54641).
+char(5,54642).
+char(c,54643).
+char(m,54644).
+char(o,54645).
+char(p,54646).
+char(o,54647).
+char(p,54648).
+char(o,54649).
+char(5,54650).
+char(5,54651).
+char(5,54652).
+char(0,54653).
+char(m,54654).
+char(2,54655).
+char(1,54656).
+char(3,54657).
+char(9,54658).
+char(m,54659).
+char(o,54660).
+char(o,54661).
+char(o,54662).
+char(m,54663).
+char(3,54664).
+char(7,54665).
+char(4,54666).
+char(8,54667).
+char(p,54668).
+char(o,54669).
+char(2,54670).
+char(6,54671).
+char(0,54672).
+char(4,54673).
+char(c,54674).
+char(p,54675).
+char(o,54676).
+char(m,54677).
+char(o,54678).
+char(m,54679).
+char(1,54680).
+char(8,54681).
+char(5,54682).
+char(6,54683).
+char(p,54684).
+char(3,54685).
+char(2,54686).
+char(9,54687).
+char(6,54688).
+char(m,54689).
+char(7,54690).
+char(8,54691).
+char(2,54692).
+char(7,54693).
+char(p,54694).
+char(3,54695).
+char(3,54696).
+char(8,54697).
+char(0,54698).
+char(c,54699).
+char(m,54700).
+char(o,54701).
+char(7,54702).
+char(5,54703).
+char(6,54704).
+char(3,54705).
+char(c,54706).
+char(m,54707).
+char(o,54708).
+char(4,54709).
+char(8,54710).
+char(1,54711).
+char(9,54712).
+char(m,54713).
+char(9,54714).
+char(4,54715).
+char(8,54716).
+char(1,54717).
+char(c,54718).
+char(c,54719).
+char(c,54720).
+char(c,54721).
+char(c,54722).
+char(c,54723).
+char(m,54724).
+char(o,54725).
+char(m,54726).
+char(6,54727).
+char(9,54728).
+char(2,54729).
+char(3,54730).
+char(p,54731).
+char(8,54732).
+char(3,54733).
+char(9,54734).
+char(5,54735).
+char(m,54736).
+char(5,54737).
+char(5,54738).
+char(0,54739).
+char(5,54740).
+char(m,54741).
+char(o,54742).
+char(5,54743).
+char(5,54744).
+char(3,54745).
+char(4,54746).
+char(c,54747).
+char(m,54748).
+char(4,54749).
+char(6,54750).
+char(4,54751).
+char(2,54752).
+char(m,54753).
+char(9,54754).
+char(1,54755).
+char(5,54756).
+char(p,54757).
+char(3,54758).
+char(1,54759).
+char(2,54760).
+char(0,54761).
+char(c,54762).
+char(p,54763).
+char(o,54764).
+char(4,54765).
+char(3,54766).
+char(9,54767).
+char(7,54768).
+char(c,54769).
+char(p,54770).
+char(o,54771).
+char(o,54772).
+char(m,54773).
+char(o,54774).
+char(o,54775).
+char(m,54776).
+char(2,54777).
+char(8,54778).
+char(3,54779).
+char(4,54780).
+char(c,54781).
+char(c,54782).
+char(m,54783).
+char(3,54784).
+char(9,54785).
+char(9,54786).
+char(5,54787).
+char(c,54788).
+char(p,54789).
+char(1,54790).
+char(4,54791).
+char(9,54792).
+char(m,54793).
+char(6,54794).
+char(1,54795).
+char(0,54796).
+char(3,54797).
+char(c,54798).
+char(c,54799).
+char(m,54800).
+char(o,54801).
+char(p,54802).
+char(1,54803).
+char(8,54804).
+char(6,54805).
+char(1,54806).
+char(c,54807).
+char(c,54808).
+char(c,54809).
+char(c,54810).
+char(p,54811).
+char(o,54812).
+char(5,54813).
+char(2,54814).
+char(4,54815).
+char(1,54816).
+char(c,54817).
+char(c,54818).
+char(p,54819).
+char(4,54820).
+char(7,54821).
+char(7,54822).
+char(m,54823).
+char(o,54824).
+char(m,54825).
+char(3,54826).
+char(8,54827).
+char(3,54828).
+char(0,54829).
+char(m,54830).
+char(o,54831).
+char(p,54832).
+char(o,54833).
+char(o,54834).
+char(p,54835).
+char(3,54836).
+char(0,54837).
+char(4,54838).
+char(7,54839).
+char(c,54840).
+char(c,54841).
+char(c,54842).
+char(c,54843).
+char(c,54844).
+char(c,54845).
+char(c,54846).
+char(p,54847).
+char(7,54848).
+char(2,54849).
+char(9,54850).
+char(5,54851).
+char(p,54852).
+char(9,54853).
+char(6,54854).
+char(2,54855).
+char(5,54856).
+char(m,54857).
+char(4,54858).
+char(2,54859).
+char(4,54860).
+char(4,54861).
+char(m,54862).
+char(7,54863).
+char(3,54864).
+char(4,54865).
+char(6,54866).
+char(p,54867).
+char(o,54868).
+char(m,54869).
+char(o,54870).
+char(m,54871).
+char(o,54872).
+char(m,54873).
+char(9,54874).
+char(4,54875).
+char(3,54876).
+char(2,54877).
+char(c,54878).
+char(c,54879).
+char(c,54880).
+char(p,54881).
+char(o,54882).
+char(m,54883).
+char(3,54884).
+char(5,54885).
+char(6,54886).
+char(7,54887).
+char(m,54888).
+char(9,54889).
+char(0,54890).
+char(0,54891).
+char(8,54892).
+char(p,54893).
+char(2,54894).
+char(4,54895).
+char(3,54896).
+char(0,54897).
+char(c,54898).
+char(c,54899).
+char(m,54900).
+char(8,54901).
+char(7,54902).
+char(6,54903).
+char(2,54904).
+char(c,54905).
+char(c,54906).
+char(m,54907).
+char(o,54908).
+char(m,54909).
+char(o,54910).
+char(6,54911).
+char(6,54912).
+char(4,54913).
+char(5,54914).
+char(c,54915).
+char(c,54916).
+char(m,54917).
+char(o,54918).
+char(m,54919).
+char(o,54920).
+char(m,54921).
+char(o,54922).
+char(3,54923).
+char(3,54924).
+char(3,54925).
+char(4,54926).
+char(c,54927).
+char(c,54928).
+char(c,54929).
+char(c,54930).
+char(c,54931).
+char(c,54932).
+char(p,54933).
+char(8,54934).
+char(2,54935).
+char(8,54936).
+char(8,54937).
+char(p,54938).
+char(o,54939).
+char(p,54940).
+char(8,54941).
+char(5,54942).
+char(4,54943).
+char(9,54944).
+char(m,54945).
+char(o,54946).
+char(m,54947).
+char(o,54948).
+char(m,54949).
+char(o,54950).
+char(p,54951).
+char(o,54952).
+char(m,54953).
+char(2,54954).
+char(7,54955).
+char(9,54956).
+char(9,54957).
+char(m,54958).
+char(4,54959).
+char(4,54960).
+char(9,54961).
+char(5,54962).
+char(m,54963).
+char(o,54964).
+char(p,54965).
+char(2,54966).
+char(5,54967).
+char(7,54968).
+char(5,54969).
+char(c,54970).
+char(m,54971).
+char(o,54972).
+char(o,54973).
+char(o,54974).
+char(4,54975).
+char(5,54976).
+char(5,54977).
+char(6,54978).
+char(c,54979).
+char(c,54980).
+char(c,54981).
+char(p,54982).
+char(3,54983).
+char(5,54984).
+char(3,54985).
+char(5,54986).
+char(c,54987).
+char(c,54988).
+char(c,54989).
+char(c,54990).
+char(m,54991).
+char(o,54992).
+char(o,54993).
+char(p,54994).
+char(o,54995).
+char(m,54996).
+char(4,54997).
+char(7,54998).
+char(8,54999).
+char(2,55000).
+char(c,55001).
+char(c,55002).
+char(c,55003).
+char(m,55004).
+char(o,55005).
+char(m,55006).
+char(1,55007).
+char(c,55008).
+char(c,55009).
+char(p,55010).
+char(2,55011).
+char(9,55012).
+char(2,55013).
+char(9,55014).
+char(c,55015).
+char(c,55016).
+char(p,55017).
+char(o,55018).
+char(o,55019).
+char(p,55020).
+char(o,55021).
+char(o,55022).
+char(o,55023).
+char(9,55024).
+char(4,55025).
+char(0,55026).
+char(2,55027).
+char(m,55028).
+char(o,55029).
+char(p,55030).
+char(5,55031).
+char(3,55032).
+char(9,55033).
+char(3,55034).
+char(m,55035).
+char(o,55036).
+char(m,55037).
+char(1,55038).
+char(2,55039).
+char(p,55040).
+char(o,55041).
+char(p,55042).
+char(o,55043).
+char(p,55044).
+char(o,55045).
+char(p,55046).
+char(6,55047).
+char(5,55048).
+char(5,55049).
+char(0,55050).
+char(c,55051).
+char(p,55052).
+char(5,55053).
+char(9,55054).
+char(1,55055).
+char(6,55056).
+char(m,55057).
+char(o,55058).
+char(m,55059).
+char(o,55060).
+char(m,55061).
+char(o,55062).
+char(p,55063).
+char(o,55064).
+char(m,55065).
+char(o,55066).
+char(m,55067).
+char(7,55068).
+char(4,55069).
+char(7,55070).
+char(5,55071).
+char(c,55072).
+char(m,55073).
+char(o,55074).
+char(m,55075).
+char(1,55076).
+char(2,55077).
+char(4,55078).
+char(9,55079).
+char(m,55080).
+char(o,55081).
+char(p,55082).
+char(o,55083).
+char(p,55084).
+char(9,55085).
+char(9,55086).
+char(4,55087).
+char(p,55088).
+char(3,55089).
+char(5,55090).
+char(9,55091).
+char(c,55092).
+char(m,55093).
+char(1,55094).
+char(1,55095).
+char(7,55096).
+char(0,55097).
+char(c,55098).
+char(c,55099).
+char(c,55100).
+char(c,55101).
+char(c,55102).
+char(m,55103).
+char(8,55104).
+char(0,55105).
+char(2,55106).
+char(6,55107).
+char(p,55108).
+char(3,55109).
+char(9,55110).
+char(2,55111).
+char(6,55112).
+char(m,55113).
+char(1,55114).
+char(7,55115).
+char(4,55116).
+char(3,55117).
+char(p,55118).
+char(o,55119).
+char(4,55120).
+char(1,55121).
+char(7,55122).
+char(4,55123).
+char(c,55124).
+char(m,55125).
+char(8,55126).
+char(2,55127).
+char(7,55128).
+char(5,55129).
+char(m,55130).
+char(o,55131).
+char(o,55132).
+char(m,55133).
+char(o,55134).
+char(m,55135).
+char(9,55136).
+char(6,55137).
+char(7,55138).
+char(1,55139).
+char(c,55140).
+char(c,55141).
+char(p,55142).
+char(3,55143).
+char(5,55144).
+char(6,55145).
+char(m,55146).
+char(o,55147).
+char(p,55148).
+char(2,55149).
+char(9,55150).
+char(7,55151).
+char(7,55152).
+char(m,55153).
+char(1,55154).
+char(0,55155).
+char(8,55156).
+char(6,55157).
+char(m,55158).
+char(4,55159).
+char(1,55160).
+char(1,55161).
+char(7,55162).
+char(c,55163).
+char(c,55164).
+char(c,55165).
+char(c,55166).
+char(c,55167).
+char(c,55168).
+char(m,55169).
+char(o,55170).
+char(m,55171).
+char(o,55172).
+char(m,55173).
+char(o,55174).
+char(6,55175).
+char(9,55176).
+char(4,55177).
+char(0,55178).
+char(c,55179).
+char(c,55180).
+char(c,55181).
+char(p,55182).
+char(8,55183).
+char(3,55184).
+char(6,55185).
+char(7,55186).
+char(m,55187).
+char(4,55188).
+char(2,55189).
+char(0,55190).
+char(4,55191).
+char(p,55192).
+char(o,55193).
+char(3,55194).
+char(1,55195).
+char(5,55196).
+char(8,55197).
+char(c,55198).
+char(c,55199).
+char(p,55200).
+char(o,55201).
+char(1,55202).
+char(7,55203).
+char(3,55204).
+char(7,55205).
+char(c,55206).
+char(c,55207).
+char(c,55208).
+char(p,55209).
+char(o,55210).
+char(m,55211).
+char(7,55212).
+char(8,55213).
+char(3,55214).
+char(3,55215).
+char(c,55216).
+char(p,55217).
+char(7,55218).
+char(5,55219).
+char(1,55220).
+char(1,55221).
+char(m,55222).
+char(7,55223).
+char(4,55224).
+char(5,55225).
+char(2,55226).
+char(c,55227).
+char(m,55228).
+char(o,55229).
+char(o,55230).
+char(o,55231).
+char(p,55232).
+char(o,55233).
+char(p,55234).
+char(4,55235).
+char(9,55236).
+char(5,55237).
+char(8,55238).
+char(c,55239).
+char(c,55240).
+char(p,55241).
+char(o,55242).
+char(p,55243).
+char(9,55244).
+char(1,55245).
+char(9,55246).
+char(3,55247).
+char(c,55248).
+char(c,55249).
+char(m,55250).
+char(4,55251).
+char(7,55252).
+char(1,55253).
+char(2,55254).
+char(m,55255).
+char(7,55256).
+char(3,55257).
+char(7,55258).
+char(6,55259).
+char(c,55260).
+char(c,55261).
+char(p,55262).
+char(o,55263).
+char(p,55264).
+char(o,55265).
+char(m,55266).
+char(o,55267).
+char(m,55268).
+char(6,55269).
+char(0,55270).
+char(7,55271).
+char(3,55272).
+char(m,55273).
+char(7,55274).
+char(9,55275).
+char(6,55276).
+char(c,55277).
+char(c,55278).
+char(p,55279).
+char(9,55280).
+char(4,55281).
+char(3,55282).
+char(7,55283).
+char(p,55284).
+char(8,55285).
+char(2,55286).
+char(7,55287).
+char(3,55288).
+char(c,55289).
+char(c,55290).
+char(p,55291).
+char(2,55292).
+char(1,55293).
+char(1,55294).
+char(2,55295).
+char(m,55296).
+char(8,55297).
+char(4,55298).
+char(7,55299).
+char(4,55300).
+char(p,55301).
+char(8,55302).
+char(7,55303).
+char(3,55304).
+char(5,55305).
+char(c,55306).
+char(c,55307).
+char(m,55308).
+char(1,55309).
+char(1,55310).
+char(0,55311).
+char(3,55312).
+char(c,55313).
+char(c,55314).
+char(m,55315).
+char(o,55316).
+char(m,55317).
+char(o,55318).
+char(p,55319).
+char(o,55320).
+char(m,55321).
+char(4,55322).
+char(7,55323).
+char(7,55324).
+char(1,55325).
+char(m,55326).
+char(8,55327).
+char(6,55328).
+char(3,55329).
+char(3,55330).
+char(m,55331).
+char(o,55332).
+char(m,55333).
+char(4,55334).
+char(0,55335).
+char(2,55336).
+char(5,55337).
+char(c,55338).
+char(c,55339).
+char(p,55340).
+char(o,55341).
+char(m,55342).
+char(8,55343).
+char(3,55344).
+char(4,55345).
+char(p,55346).
+char(6,55347).
+char(2,55348).
+char(8,55349).
+char(4,55350).
+char(c,55351).
+char(c,55352).
+char(c,55353).
+char(c,55354).
+char(m,55355).
+char(8,55356).
+char(6,55357).
+char(0,55358).
+char(6,55359).
+char(c,55360).
+char(p,55361).
+char(4,55362).
+char(0,55363).
+char(9,55364).
+char(5,55365).
+char(c,55366).
+char(c,55367).
+char(p,55368).
+char(o,55369).
+char(p,55370).
+char(3,55371).
+char(0,55372).
+char(8,55373).
+char(3,55374).
+char(p,55375).
+char(o,55376).
+char(o,55377).
+char(p,55378).
+char(o,55379).
+char(p,55380).
+char(o,55381).
+char(1,55382).
+char(3,55383).
+char(3,55384).
+char(c,55385).
+char(c,55386).
+char(m,55387).
+char(o,55388).
+char(6,55389).
+char(5,55390).
+char(2,55391).
+char(0,55392).
+char(m,55393).
+char(o,55394).
+char(m,55395).
+char(o,55396).
+char(p,55397).
+char(o,55398).
+char(m,55399).
+char(8,55400).
+char(4,55401).
+char(7,55402).
+char(9,55403).
+char(c,55404).
+char(p,55405).
+char(o,55406).
+char(6,55407).
+char(3,55408).
+char(5,55409).
+char(4,55410).
+char(p,55411).
+char(o,55412).
+char(p,55413).
+char(o,55414).
+char(o,55415).
+char(p,55416).
+char(o,55417).
+char(p,55418).
+char(6,55419).
+char(2,55420).
+char(5,55421).
+char(4,55422).
+char(p,55423).
+char(o,55424).
+char(p,55425).
+char(o,55426).
+char(p,55427).
+char(8,55428).
+char(5,55429).
+char(8,55430).
+char(9,55431).
+char(c,55432).
+char(c,55433).
+char(p,55434).
+char(2,55435).
+char(8,55436).
+char(2,55437).
+char(7,55438).
+char(p,55439).
+char(o,55440).
+char(p,55441).
+char(9,55442).
+char(1,55443).
+char(1,55444).
+char(5,55445).
+char(c,55446).
+char(p,55447).
+char(4,55448).
+char(9,55449).
+char(9,55450).
+char(7,55451).
+char(c,55452).
+char(c,55453).
+char(m,55454).
+char(2,55455).
+char(6,55456).
+char(0,55457).
+char(5,55458).
+char(c,55459).
+char(c,55460).
+char(p,55461).
+char(9,55462).
+char(0,55463).
+char(7,55464).
+char(3,55465).
+char(p,55466).
+char(2,55467).
+char(3,55468).
+char(0,55469).
+char(3,55470).
+char(c,55471).
+char(p,55472).
+char(4,55473).
+char(4,55474).
+char(5,55475).
+char(3,55476).
+char(c,55477).
+char(c,55478).
+char(c,55479).
+char(c,55480).
+char(p,55481).
+char(o,55482).
+char(m,55483).
+char(7,55484).
+char(6,55485).
+char(6,55486).
+char(8,55487).
+char(p,55488).
+char(9,55489).
+char(6,55490).
+char(7,55491).
+char(8,55492).
+char(c,55493).
+char(c,55494).
+char(m,55495).
+char(1,55496).
+char(4,55497).
+char(8,55498).
+char(2,55499).
+char(c,55500).
+char(m,55501).
+char(o,55502).
+char(m,55503).
+char(1,55504).
+char(0,55505).
+char(0,55506).
+char(2,55507).
+char(p,55508).
+char(o,55509).
+char(m,55510).
+char(5,55511).
+char(8,55512).
+char(2,55513).
+char(0,55514).
+char(p,55515).
+char(9,55516).
+char(3,55517).
+char(7,55518).
+char(c,55519).
+char(m,55520).
+char(o,55521).
+char(m,55522).
+char(o,55523).
+char(o,55524).
+char(9,55525).
+char(7,55526).
+char(8,55527).
+char(3,55528).
+char(c,55529).
+char(c,55530).
+char(m,55531).
+char(o,55532).
+char(m,55533).
+char(o,55534).
+char(p,55535).
+char(8,55536).
+char(0,55537).
+char(1,55538).
+char(7,55539).
+char(p,55540).
+char(5,55541).
+char(9,55542).
+char(1,55543).
+char(5,55544).
+char(p,55545).
+char(o,55546).
+char(m,55547).
+char(7,55548).
+char(1,55549).
+char(7,55550).
+char(p,55551).
+char(9,55552).
+char(7,55553).
+char(0,55554).
+char(0,55555).
+char(m,55556).
+char(9,55557).
+char(1,55558).
+char(0,55559).
+char(3,55560).
+char(c,55561).
+char(p,55562).
+char(8,55563).
+char(9,55564).
+char(8,55565).
+char(6,55566).
+char(p,55567).
+char(o,55568).
+char(p,55569).
+char(o,55570).
+char(p,55571).
+char(o,55572).
+char(7,55573).
+char(0,55574).
+char(1,55575).
+char(7,55576).
+char(m,55577).
+char(8,55578).
+char(1,55579).
+char(9,55580).
+char(p,55581).
+char(7,55582).
+char(0,55583).
+char(2,55584).
+char(1,55585).
+char(c,55586).
+char(c,55587).
+char(p,55588).
+char(o,55589).
+char(m,55590).
+char(6,55591).
+char(7,55592).
+char(5,55593).
+char(m,55594).
+char(3,55595).
+char(1,55596).
+char(1,55597).
+char(3,55598).
+char(p,55599).
+char(o,55600).
+char(p,55601).
+char(o,55602).
+char(o,55603).
+char(1,55604).
+char(0,55605).
+char(3,55606).
+char(0,55607).
+char(m,55608).
+char(o,55609).
+char(o,55610).
+char(m,55611).
+char(7,55612).
+char(9,55613).
+char(6,55614).
+char(0,55615).
+char(p,55616).
+char(o,55617).
+char(7,55618).
+char(8,55619).
+char(1,55620).
+char(8,55621).
+char(p,55622).
+char(7,55623).
+char(3,55624).
+char(6,55625).
+char(9,55626).
+char(c,55627).
+char(c,55628).
+char(m,55629).
+char(6,55630).
+char(5,55631).
+char(7,55632).
+char(6,55633).
+char(m,55634).
+char(4,55635).
+char(8,55636).
+char(6,55637).
+char(3,55638).
+char(m,55639).
+char(o,55640).
+char(m,55641).
+char(6,55642).
+char(3,55643).
+char(6,55644).
+char(7,55645).
+char(c,55646).
+char(p,55647).
+char(o,55648).
+char(m,55649).
+char(9,55650).
+char(3,55651).
+char(9,55652).
+char(2,55653).
+char(c,55654).
+char(m,55655).
+char(2,55656).
+char(6,55657).
+char(1,55658).
+char(0,55659).
+char(p,55660).
+char(o,55661).
+char(m,55662).
+char(o,55663).
+char(p,55664).
+char(o,55665).
+char(p,55666).
+char(5,55667).
+char(1,55668).
+char(0,55669).
+char(3,55670).
+char(m,55671).
+char(6,55672).
+char(5,55673).
+char(4,55674).
+char(0,55675).
+char(c,55676).
+char(c,55677).
+char(c,55678).
+char(p,55679).
+char(1,55680).
+char(7,55681).
+char(1,55682).
+char(0,55683).
+char(m,55684).
+char(o,55685).
+char(p,55686).
+char(5,55687).
+char(1,55688).
+char(9,55689).
+char(0,55690).
+char(c,55691).
+char(m,55692).
+char(6,55693).
+char(2,55694).
+char(5,55695).
+char(5,55696).
+char(m,55697).
+char(7,55698).
+char(2,55699).
+char(8,55700).
+char(7,55701).
+char(m,55702).
+char(1,55703).
+char(9,55704).
+char(8,55705).
+char(c,55706).
+char(c,55707).
+char(m,55708).
+char(o,55709).
+char(m,55710).
+char(o,55711).
+char(o,55712).
+char(o,55713).
+char(p,55714).
+char(3,55715).
+char(2,55716).
+char(8,55717).
+char(5,55718).
+char(c,55719).
+char(p,55720).
+char(o,55721).
+char(p,55722).
+char(o,55723).
+char(p,55724).
+char(o,55725).
+char(m,55726).
+char(4,55727).
+char(6,55728).
+char(1,55729).
+char(7,55730).
+char(c,55731).
+char(m,55732).
+char(9,55733).
+char(6,55734).
+char(5,55735).
+char(6,55736).
+char(m,55737).
+char(6,55738).
+char(2,55739).
+char(0,55740).
+char(4,55741).
+char(m,55742).
+char(o,55743).
+char(p,55744).
+char(o,55745).
+char(p,55746).
+char(o,55747).
+char(p,55748).
+char(o,55749).
+char(m,55750).
+char(4,55751).
+char(7,55752).
+char(6,55753).
+char(2,55754).
+char(c,55755).
+char(m,55756).
+char(o,55757).
+char(o,55758).
+char(3,55759).
+char(7,55760).
+char(6,55761).
+char(8,55762).
+char(m,55763).
+char(o,55764).
+char(m,55765).
+char(6,55766).
+char(3,55767).
+char(2,55768).
+char(p,55769).
+char(o,55770).
+char(2,55771).
+char(2,55772).
+char(2,55773).
+char(3,55774).
+char(p,55775).
+char(o,55776).
+char(m,55777).
+char(o,55778).
+char(p,55779).
+char(o,55780).
+char(p,55781).
+char(o,55782).
+char(o,55783).
+char(m,55784).
+char(o,55785).
+char(o,55786).
+char(p,55787).
+char(7,55788).
+char(5,55789).
+char(9,55790).
+char(5,55791).
+char(p,55792).
+char(1,55793).
+char(4,55794).
+char(9,55795).
+char(6,55796).
+char(c,55797).
+char(m,55798).
+char(1,55799).
+char(0,55800).
+char(1,55801).
+char(2,55802).
+char(c,55803).
+char(m,55804).
+char(o,55805).
+char(m,55806).
+char(o,55807).
+char(p,55808).
+char(2,55809).
+char(3,55810).
+char(4,55811).
+char(2,55812).
+char(c,55813).
+char(p,55814).
+char(3,55815).
+char(1,55816).
+char(8,55817).
+char(p,55818).
+char(4,55819).
+char(2,55820).
+char(c,55821).
+char(p,55822).
+char(9,55823).
+char(8,55824).
+char(2,55825).
+char(2,55826).
+char(c,55827).
+char(m,55828).
+char(4,55829).
+char(0,55830).
+char(2,55831).
+char(5,55832).
+char(c,55833).
+char(c,55834).
+char(c,55835).
+char(m,55836).
+char(o,55837).
+char(p,55838).
+char(2,55839).
+char(2,55840).
+char(5,55841).
+char(3,55842).
+char(c,55843).
+char(c,55844).
+char(c,55845).
+char(c,55846).
+char(c,55847).
+char(c,55848).
+char(p,55849).
+char(o,55850).
+char(6,55851).
+char(3,55852).
+char(9,55853).
+char(2,55854).
+char(p,55855).
+char(4,55856).
+char(5,55857).
+char(6,55858).
+char(9,55859).
+char(c,55860).
+char(c,55861).
+char(m,55862).
+char(7,55863).
+char(1,55864).
+char(5,55865).
+char(1,55866).
+char(p,55867).
+char(o,55868).
+char(p,55869).
+char(3,55870).
+char(8,55871).
+char(7,55872).
+char(9,55873).
+char(c,55874).
+char(m,55875).
+char(o,55876).
+char(m,55877).
+char(o,55878).
+char(o,55879).
+char(2,55880).
+char(5,55881).
+char(7,55882).
+char(7,55883).
+char(c,55884).
+char(p,55885).
+char(o,55886).
+char(o,55887).
+char(m,55888).
+char(4,55889).
+char(0,55890).
+char(3,55891).
+char(7,55892).
+char(c,55893).
+char(c,55894).
+char(c,55895).
+char(p,55896).
+char(6,55897).
+char(8,55898).
+char(1,55899).
+char(0,55900).
+char(c,55901).
+char(c,55902).
+char(c,55903).
+char(m,55904).
+char(o,55905).
+char(m,55906).
+char(2,55907).
+char(7,55908).
+char(4,55909).
+char(3,55910).
+char(p,55911).
+char(o,55912).
+char(o,55913).
+char(m,55914).
+char(8,55915).
+char(5,55916).
+char(2,55917).
+char(2,55918).
+char(c,55919).
+char(c,55920).
+char(c,55921).
+char(c,55922).
+char(p,55923).
+char(o,55924).
+char(p,55925).
+char(8,55926).
+char(5,55927).
+char(4,55928).
+char(p,55929).
+char(5,55930).
+char(1,55931).
+char(9,55932).
+char(p,55933).
+char(o,55934).
+char(p,55935).
+char(9,55936).
+char(4,55937).
+char(3,55938).
+char(0,55939).
+char(m,55940).
+char(6,55941).
+char(5,55942).
+char(3,55943).
+char(4,55944).
+char(c,55945).
+char(c,55946).
+char(c,55947).
+char(p,55948).
+char(1,55949).
+char(7,55950).
+char(7,55951).
+char(5,55952).
+char(p,55953).
+char(o,55954).
+char(p,55955).
+char(6,55956).
+char(2,55957).
+char(5,55958).
+char(4,55959).
+char(c,55960).
+char(m,55961).
+char(o,55962).
+char(o,55963).
+char(p,55964).
+char(o,55965).
+char(3,55966).
+char(9,55967).
+char(4,55968).
+char(0,55969).
+char(p,55970).
+char(o,55971).
+char(p,55972).
+char(4,55973).
+char(5,55974).
+char(4,55975).
+char(2,55976).
+char(c,55977).
+char(p,55978).
+char(o,55979).
+char(o,55980).
+char(p,55981).
+char(3,55982).
+char(8,55983).
+char(9,55984).
+char(3,55985).
+char(c,55986).
+char(c,55987).
+char(c,55988).
+char(c,55989).
+char(c,55990).
+char(p,55991).
+char(6,55992).
+char(8,55993).
+char(3,55994).
+char(2,55995).
+char(c,55996).
+char(c,55997).
+char(c,55998).
+char(c,55999).
+char(c,56000).
+char(m,56001).
+char(o,56002).
+char(p,56003).
+char(1,56004).
+char(6,56005).
+char(2,56006).
+char(2,56007).
+char(m,56008).
+char(3,56009).
+char(9,56010).
+char(9,56011).
+char(2,56012).
+char(c,56013).
+char(c,56014).
+char(m,56015).
+char(o,56016).
+char(p,56017).
+char(o,56018).
+char(m,56019).
+char(o,56020).
+char(p,56021).
+char(5,56022).
+char(6,56023).
+char(8,56024).
+char(1,56025).
+char(c,56026).
+char(m,56027).
+char(5,56028).
+char(6,56029).
+char(5,56030).
+char(3,56031).
+char(m,56032).
+char(o,56033).
+char(p,56034).
+char(o,56035).
+char(m,56036).
+char(6,56037).
+char(6,56038).
+char(1,56039).
+char(8,56040).
+char(c,56041).
+char(m,56042).
+char(6,56043).
+char(6,56044).
+char(6,56045).
+char(5,56046).
+char(p,56047).
+char(3,56048).
+char(0,56049).
+char(3,56050).
+char(5,56051).
+char(p,56052).
+char(o,56053).
+char(m,56054).
+char(o,56055).
+char(m,56056).
+char(8,56057).
+char(3,56058).
+char(6,56059).
+char(1,56060).
+char(c,56061).
+char(c,56062).
+char(c,56063).
+char(c,56064).
+char(m,56065).
+char(4,56066).
+char(0,56067).
+char(0,56068).
+char(6,56069).
+char(c,56070).
+char(p,56071).
+char(6,56072).
+char(9,56073).
+char(3,56074).
+char(4,56075).
+char(c,56076).
+char(c,56077).
+char(c,56078).
+char(c,56079).
+char(c,56080).
+char(p,56081).
+char(1,56082).
+char(7,56083).
+char(4,56084).
+char(0,56085).
+char(p,56086).
+char(8,56087).
+char(8,56088).
+char(8,56089).
+char(5,56090).
+char(c,56091).
+char(c,56092).
+char(m,56093).
+char(o,56094).
+char(p,56095).
+char(o,56096).
+char(8,56097).
+char(5,56098).
+char(9,56099).
+char(9,56100).
+char(m,56101).
+char(6,56102).
+char(3,56103).
+char(0,56104).
+char(1,56105).
+char(c,56106).
+char(m,56107).
+char(8,56108).
+char(1,56109).
+char(0,56110).
+char(c,56111).
+char(c,56112).
+char(m,56113).
+char(3,56114).
+char(6,56115).
+char(6,56116).
+char(4,56117).
+char(c,56118).
+char(m,56119).
+char(4,56120).
+char(7,56121).
+char(6,56122).
+char(0,56123).
+char(m,56124).
+char(4,56125).
+char(4,56126).
+char(6,56127).
+char(7,56128).
+char(m,56129).
+char(o,56130).
+char(p,56131).
+char(6,56132).
+char(6,56133).
+char(6,56134).
+char(3,56135).
+char(c,56136).
+char(c,56137).
+char(m,56138).
+char(o,56139).
+char(m,56140).
+char(5,56141).
+char(5,56142).
+char(0,56143).
+char(9,56144).
+char(c,56145).
+char(c,56146).
+char(m,56147).
+char(o,56148).
+char(p,56149).
+char(8,56150).
+char(1,56151).
+char(8,56152).
+char(8,56153).
+char(c,56154).
+char(c,56155).
+char(c,56156).
+char(p,56157).
+char(o,56158).
+char(o,56159).
+char(p,56160).
+char(6,56161).
+char(5,56162).
+char(5,56163).
+char(3,56164).
+char(c,56165).
+char(p,56166).
+char(o,56167).
+char(5,56168).
+char(9,56169).
+char(7,56170).
+char(1,56171).
+char(c,56172).
+char(m,56173).
+char(o,56174).
+char(m,56175).
+char(o,56176).
+char(m,56177).
+char(o,56178).
+char(m,56179).
+char(o,56180).
+char(p,56181).
+char(o,56182).
+char(p,56183).
+char(o,56184).
+char(m,56185).
+char(o,56186).
+char(p,56187).
+char(o,56188).
+char(5,56189).
+char(4,56190).
+char(1,56191).
+char(9,56192).
+char(m,56193).
+char(o,56194).
+char(o,56195).
+char(p,56196).
+char(o,56197).
+char(m,56198).
+char(9,56199).
+char(3,56200).
+char(2,56201).
+char(4,56202).
+char(m,56203).
+char(o,56204).
+char(m,56205).
+char(o,56206).
+char(m,56207).
+char(o,56208).
+char(8,56209).
+char(4,56210).
+char(6,56211).
+char(4,56212).
+char(c,56213).
+char(c,56214).
+char(m,56215).
+char(o,56216).
+char(p,56217).
+char(o,56218).
+char(o,56219).
+char(m,56220).
+char(1,56221).
+char(4,56222).
+char(9,56223).
+char(0,56224).
+char(p,56225).
+char(9,56226).
+char(9,56227).
+char(6,56228).
+char(0,56229).
+char(p,56230).
+char(1,56231).
+char(2,56232).
+char(3,56233).
+char(3,56234).
+char(c,56235).
+char(m,56236).
+char(o,56237).
+char(o,56238).
+char(m,56239).
+char(6,56240).
+char(7,56241).
+char(6,56242).
+char(9,56243).
+char(c,56244).
+char(c,56245).
+char(c,56246).
+char(p,56247).
+char(o,56248).
+char(m,56249).
+char(o,56250).
+char(p,56251).
+char(o,56252).
+char(m,56253).
+char(6,56254).
+char(9,56255).
+char(5,56256).
+char(m,56257).
+char(1,56258).
+char(4,56259).
+char(9,56260).
+char(6,56261).
+char(c,56262).
+char(c,56263).
+char(m,56264).
+char(9,56265).
+char(9,56266).
+char(1,56267).
+char(0,56268).
+char(c,56269).
+char(p,56270).
+char(1,56271).
+char(0,56272).
+char(c,56273).
+char(m,56274).
+char(8,56275).
+char(8,56276).
+char(0,56277).
+char(5,56278).
+char(m,56279).
+char(o,56280).
+char(p,56281).
+char(o,56282).
+char(8,56283).
+char(3,56284).
+char(9,56285).
+char(3,56286).
+char(c,56287).
+char(m,56288).
+char(7,56289).
+char(6,56290).
+char(5,56291).
+char(3,56292).
+char(c,56293).
+char(c,56294).
+char(c,56295).
+char(m,56296).
+char(o,56297).
+char(4,56298).
+char(7,56299).
+char(5,56300).
+char(8,56301).
+char(c,56302).
+char(c,56303).
+char(c,56304).
+char(c,56305).
+char(p,56306).
+char(o,56307).
+char(2,56308).
+char(0,56309).
+char(9,56310).
+char(3,56311).
+char(m,56312).
+char(6,56313).
+char(7,56314).
+char(6,56315).
+char(7,56316).
+char(p,56317).
+char(4,56318).
+char(3,56319).
+char(5,56320).
+char(m,56321).
+char(o,56322).
+char(4,56323).
+char(7,56324).
+char(8,56325).
+char(4,56326).
+char(c,56327).
+char(m,56328).
+char(o,56329).
+char(3,56330).
+char(8,56331).
+char(6,56332).
+char(5,56333).
+char(c,56334).
+char(m,56335).
+char(2,56336).
+char(5,56337).
+char(3,56338).
+char(0,56339).
+char(c,56340).
+char(c,56341).
+char(p,56342).
+char(o,56343).
+char(p,56344).
+char(8,56345).
+char(7,56346).
+char(6,56347).
+char(1,56348).
+char(m,56349).
+char(o,56350).
+char(p,56351).
+char(o,56352).
+char(o,56353).
+char(o,56354).
+char(6,56355).
+char(8,56356).
+char(9,56357).
+char(8,56358).
+char(m,56359).
+char(5,56360).
+char(2,56361).
+char(1,56362).
+char(9,56363).
+char(c,56364).
+char(m,56365).
+char(o,56366).
+char(p,56367).
+char(4,56368).
+char(7,56369).
+char(1,56370).
+char(2,56371).
+char(c,56372).
+char(c,56373).
+char(p,56374).
+char(o,56375).
+char(9,56376).
+char(3,56377).
+char(5,56378).
+char(5,56379).
+char(c,56380).
+char(m,56381).
+char(o,56382).
+char(p,56383).
+char(o,56384).
+char(1,56385).
+char(7,56386).
+char(5,56387).
+char(c,56388).
+char(p,56389).
+char(7,56390).
+char(6,56391).
+char(7,56392).
+char(0,56393).
+char(c,56394).
+char(c,56395).
+char(m,56396).
+char(1,56397).
+char(2,56398).
+char(3,56399).
+char(8,56400).
+char(c,56401).
+char(c,56402).
+char(c,56403).
+char(c,56404).
+char(c,56405).
+char(p,56406).
+char(4,56407).
+char(2,56408).
+char(7,56409).
+char(6,56410).
+char(m,56411).
+char(o,56412).
+char(m,56413).
+char(2,56414).
+char(8,56415).
+char(4,56416).
+char(0,56417).
+char(c,56418).
+char(m,56419).
+char(o,56420).
+char(p,56421).
+char(o,56422).
+char(m,56423).
+char(o,56424).
+char(o,56425).
+char(p,56426).
+char(3,56427).
+char(0,56428).
+char(9,56429).
+char(9,56430).
+char(p,56431).
+char(o,56432).
+char(p,56433).
+char(1,56434).
+char(6,56435).
+char(7,56436).
+char(c,56437).
+char(m,56438).
+char(o,56439).
+char(p,56440).
+char(3,56441).
+char(5,56442).
+char(9,56443).
+char(9,56444).
+char(c,56445).
+char(p,56446).
+char(6,56447).
+char(5,56448).
+char(3,56449).
+char(1,56450).
+char(m,56451).
+char(o,56452).
+char(p,56453).
+char(o,56454).
+char(m,56455).
+char(8,56456).
+char(7,56457).
+char(1,56458).
+char(2,56459).
+char(c,56460).
+char(m,56461).
+char(6,56462).
+char(1,56463).
+char(6,56464).
+char(5,56465).
+char(c,56466).
+char(p,56467).
+char(o,56468).
+char(m,56469).
+char(2,56470).
+char(9,56471).
+char(c,56472).
+char(m,56473).
+char(4,56474).
+char(9,56475).
+char(3,56476).
+char(c,56477).
+char(c,56478).
+char(p,56479).
+char(o,56480).
+char(1,56481).
+char(2,56482).
+char(8,56483).
+char(7,56484).
+char(p,56485).
+char(o,56486).
+char(3,56487).
+char(8,56488).
+char(5,56489).
+char(7,56490).
+char(c,56491).
+char(c,56492).
+char(c,56493).
+char(m,56494).
+char(o,56495).
+char(6,56496).
+char(1,56497).
+char(8,56498).
+char(3,56499).
+char(c,56500).
+char(c,56501).
+char(p,56502).
+char(o,56503).
+char(o,56504).
+char(m,56505).
+char(3,56506).
+char(4,56507).
+char(9,56508).
+char(2,56509).
+char(m,56510).
+char(o,56511).
+char(p,56512).
+char(1,56513).
+char(2,56514).
+char(9,56515).
+char(c,56516).
+char(c,56517).
+char(c,56518).
+char(m,56519).
+char(o,56520).
+char(p,56521).
+char(o,56522).
+char(o,56523).
+char(m,56524).
+char(o,56525).
+char(o,56526).
+char(m,56527).
+char(5,56528).
+char(5,56529).
+char(7,56530).
+char(4,56531).
+char(m,56532).
+char(5,56533).
+char(3,56534).
+char(1,56535).
+char(0,56536).
+char(m,56537).
+char(1,56538).
+char(1,56539).
+char(9,56540).
+char(9,56541).
+char(c,56542).
+char(p,56543).
+char(o,56544).
+char(p,56545).
+char(o,56546).
+char(9,56547).
+char(5,56548).
+char(6,56549).
+char(8,56550).
+char(p,56551).
+char(o,56552).
+char(p,56553).
+char(o,56554).
+char(6,56555).
+char(8,56556).
+char(3,56557).
+char(7,56558).
+char(p,56559).
+char(7,56560).
+char(1,56561).
+char(7,56562).
+char(1,56563).
+char(m,56564).
+char(4,56565).
+char(1,56566).
+char(6,56567).
+char(8,56568).
+char(p,56569).
+char(o,56570).
+char(o,56571).
+char(8,56572).
+char(3,56573).
+char(5,56574).
+char(8,56575).
+char(c,56576).
+char(m,56577).
+char(8,56578).
+char(7,56579).
+char(9,56580).
+char(2,56581).
+char(p,56582).
+char(1,56583).
+char(7,56584).
+char(1,56585).
+char(7,56586).
+char(c,56587).
+char(p,56588).
+char(8,56589).
+char(9,56590).
+char(6,56591).
+char(6,56592).
+char(c,56593).
+char(p,56594).
+char(o,56595).
+char(m,56596).
+char(o,56597).
+char(p,56598).
+char(6,56599).
+char(5,56600).
+char(2,56601).
+char(5,56602).
+char(c,56603).
+char(c,56604).
+char(c,56605).
+char(p,56606).
+char(2,56607).
+char(0,56608).
+char(5,56609).
+char(5,56610).
+char(c,56611).
+char(m,56612).
+char(9,56613).
+char(0,56614).
+char(4,56615).
+char(3,56616).
+char(p,56617).
+char(7,56618).
+char(1,56619).
+char(0,56620).
+char(m,56621).
+char(9,56622).
+char(5,56623).
+char(8,56624).
+char(6,56625).
+char(c,56626).
+char(m,56627).
+char(8,56628).
+char(2,56629).
+char(4,56630).
+char(1,56631).
+char(p,56632).
+char(9,56633).
+char(5,56634).
+char(3,56635).
+char(1,56636).
+char(m,56637).
+char(8,56638).
+char(7,56639).
+char(6,56640).
+char(8,56641).
+char(m,56642).
+char(o,56643).
+char(8,56644).
+char(1,56645).
+char(4,56646).
+char(8,56647).
+char(c,56648).
+char(p,56649).
+char(o,56650).
+char(o,56651).
+char(m,56652).
+char(o,56653).
+char(8,56654).
+char(8,56655).
+char(2,56656).
+char(3,56657).
+char(p,56658).
+char(o,56659).
+char(m,56660).
+char(2,56661).
+char(9,56662).
+char(9,56663).
+char(5,56664).
+char(c,56665).
+char(m,56666).
+char(o,56667).
+char(9,56668).
+char(8,56669).
+char(1,56670).
+char(4,56671).
+char(m,56672).
+char(o,56673).
+char(9,56674).
+char(8,56675).
+char(2,56676).
+char(4,56677).
+char(c,56678).
+char(c,56679).
+char(c,56680).
+char(p,56681).
+char(6,56682).
+char(2,56683).
+char(9,56684).
+char(p,56685).
+char(3,56686).
+char(7,56687).
+char(7,56688).
+char(5,56689).
+char(c,56690).
+char(m,56691).
+char(o,56692).
+char(m,56693).
+char(o,56694).
+char(p,56695).
+char(1,56696).
+char(9,56697).
+char(8,56698).
+char(6,56699).
+char(c,56700).
+char(p,56701).
+char(o,56702).
+char(m,56703).
+char(2,56704).
+char(3,56705).
+char(0,56706).
+char(1,56707).
+char(c,56708).
+char(p,56709).
+char(8,56710).
+char(3,56711).
+char(0,56712).
+char(3,56713).
+char(c,56714).
+char(c,56715).
+char(c,56716).
+char(p,56717).
+char(o,56718).
+char(o,56719).
+char(p,56720).
+char(4,56721).
+char(9,56722).
+char(7,56723).
+char(5,56724).
+char(c,56725).
+char(p,56726).
+char(4,56727).
+char(6,56728).
+char(8,56729).
+char(2,56730).
+char(p,56731).
+char(o,56732).
+char(o,56733).
+char(p,56734).
+char(5,56735).
+char(9,56736).
+char(9,56737).
+char(5,56738).
+char(p,56739).
+char(2,56740).
+char(2,56741).
+char(2,56742).
+char(0,56743).
+char(c,56744).
+char(p,56745).
+char(o,56746).
+char(p,56747).
+char(o,56748).
+char(p,56749).
+char(5,56750).
+char(3,56751).
+char(1,56752).
+char(9,56753).
+char(c,56754).
+char(m,56755).
+char(7,56756).
+char(4,56757).
+char(4,56758).
+char(4,56759).
+char(c,56760).
+char(p,56761).
+char(o,56762).
+char(p,56763).
+char(o,56764).
+char(o,56765).
+char(m,56766).
+char(4,56767).
+char(3,56768).
+char(9,56769).
+char(6,56770).
+char(m,56771).
+char(o,56772).
+char(3,56773).
+char(4,56774).
+char(2,56775).
+char(9,56776).
+char(c,56777).
+char(m,56778).
+char(2,56779).
+char(1,56780).
+char(4,56781).
+char(9,56782).
+char(c,56783).
+char(c,56784).
+char(p,56785).
+char(1,56786).
+char(2,56787).
+char(3,56788).
+char(6,56789).
+char(c,56790).
+char(c,56791).
+char(c,56792).
+char(c,56793).
+char(m,56794).
+char(3,56795).
+char(7,56796).
+char(7,56797).
+char(9,56798).
+char(c,56799).
+char(c,56800).
+char(c,56801).
+char(m,56802).
+char(5,56803).
+char(0,56804).
+char(2,56805).
+char(c,56806).
+char(c,56807).
+char(c,56808).
+char(m,56809).
+char(o,56810).
+char(7,56811).
+char(0,56812).
+char(2,56813).
+char(8,56814).
+char(c,56815).
+char(m,56816).
+char(8,56817).
+char(4,56818).
+char(3,56819).
+char(6,56820).
+char(c,56821).
+char(p,56822).
+char(o,56823).
+char(m,56824).
+char(o,56825).
+char(m,56826).
+char(6,56827).
+char(7,56828).
+char(6,56829).
+char(0,56830).
+char(c,56831).
+char(c,56832).
+char(c,56833).
+char(m,56834).
+char(o,56835).
+char(m,56836).
+char(6,56837).
+char(6,56838).
+char(7,56839).
+char(9,56840).
+char(c,56841).
+char(p,56842).
+char(o,56843).
+char(p,56844).
+char(o,56845).
+char(p,56846).
+char(o,56847).
+char(m,56848).
+char(o,56849).
+char(p,56850).
+char(o,56851).
+char(o,56852).
+char(6,56853).
+char(3,56854).
+char(9,56855).
+char(8,56856).
+char(p,56857).
+char(o,56858).
+char(m,56859).
+char(o,56860).
+char(m,56861).
+char(5,56862).
+char(0,56863).
+char(2,56864).
+char(c,56865).
+char(m,56866).
+char(1,56867).
+char(3,56868).
+char(4,56869).
+char(7,56870).
+char(c,56871).
+char(m,56872).
+char(9,56873).
+char(7,56874).
+char(1,56875).
+char(2,56876).
+char(c,56877).
+char(c,56878).
+char(p,56879).
+char(o,56880).
+char(m,56881).
+char(1,56882).
+char(1,56883).
+char(4,56884).
+char(8,56885).
+char(c,56886).
+char(m,56887).
+char(o,56888).
+char(4,56889).
+char(1,56890).
+char(6,56891).
+char(c,56892).
+char(p,56893).
+char(5,56894).
+char(3,56895).
+char(8,56896).
+char(m,56897).
+char(5,56898).
+char(9,56899).
+char(8,56900).
+char(4,56901).
+char(c,56902).
+char(m,56903).
+char(6,56904).
+char(9,56905).
+char(9,56906).
+char(1,56907).
+char(m,56908).
+char(o,56909).
+char(m,56910).
+char(o,56911).
+char(p,56912).
+char(o,56913).
+char(m,56914).
+char(4,56915).
+char(0,56916).
+char(7,56917).
+char(1,56918).
+char(p,56919).
+char(o,56920).
+char(m,56921).
+char(7,56922).
+char(6,56923).
+char(0,56924).
+char(0,56925).
+char(c,56926).
+char(m,56927).
+char(3,56928).
+char(8,56929).
+char(5,56930).
+char(0,56931).
+char(c,56932).
+char(p,56933).
+char(4,56934).
+char(7,56935).
+char(1,56936).
+char(6,56937).
+char(p,56938).
+char(o,56939).
+char(o,56940).
+char(4,56941).
+char(6,56942).
+char(5,56943).
+char(4,56944).
+char(m,56945).
+char(o,56946).
+char(o,56947).
+char(m,56948).
+char(6,56949).
+char(9,56950).
+char(8,56951).
+char(2,56952).
+char(p,56953).
+char(3,56954).
+char(6,56955).
+char(6,56956).
+char(9,56957).
+char(c,56958).
+char(c,56959).
+char(c,56960).
+char(m,56961).
+char(1,56962).
+char(0,56963).
+char(3,56964).
+char(4,56965).
+char(c,56966).
+char(c,56967).
+char(m,56968).
+char(2,56969).
+char(2,56970).
+char(5,56971).
+char(1,56972).
+char(m,56973).
+char(o,56974).
+char(m,56975).
+char(o,56976).
+char(p,56977).
+char(7,56978).
+char(6,56979).
+char(1,56980).
+char(2,56981).
+char(c,56982).
+char(c,56983).
+char(c,56984).
+char(c,56985).
+char(p,56986).
+char(o,56987).
+char(1,56988).
+char(1,56989).
+char(6,56990).
+char(m,56991).
+char(6,56992).
+char(6,56993).
+char(7,56994).
+char(5,56995).
+char(p,56996).
+char(8,56997).
+char(8,56998).
+char(8,56999).
+char(6,57000).
+char(m,57001).
+char(o,57002).
+char(m,57003).
+char(o,57004).
+char(p,57005).
+char(5,57006).
+char(4,57007).
+char(2,57008).
+char(1,57009).
+char(c,57010).
+char(p,57011).
+char(o,57012).
+char(8,57013).
+char(0,57014).
+char(2,57015).
+char(p,57016).
+char(9,57017).
+char(8,57018).
+char(0,57019).
+char(8,57020).
+char(m,57021).
+char(o,57022).
+char(p,57023).
+char(o,57024).
+char(p,57025).
+char(o,57026).
+char(o,57027).
+char(m,57028).
+char(o,57029).
+char(4,57030).
+char(9,57031).
+char(8,57032).
+char(1,57033).
+char(c,57034).
+char(c,57035).
+char(m,57036).
+char(o,57037).
+char(p,57038).
+char(7,57039).
+char(0,57040).
+char(7,57041).
+char(8,57042).
+char(c,57043).
+char(m,57044).
+char(o,57045).
+char(o,57046).
+char(p,57047).
+char(o,57048).
+char(m,57049).
+char(8,57050).
+char(7,57051).
+char(9,57052).
+char(4,57053).
+char(m,57054).
+char(o,57055).
+char(4,57056).
+char(7,57057).
+char(7,57058).
+char(7,57059).
+char(c,57060).
+char(p,57061).
+char(o,57062).
+char(6,57063).
+char(4,57064).
+char(4,57065).
+char(3,57066).
+char(c,57067).
+char(c,57068).
+char(m,57069).
+char(4,57070).
+char(3,57071).
+char(4,57072).
+char(6,57073).
+char(m,57074).
+char(9,57075).
+char(0,57076).
+char(1,57077).
+char(3,57078).
+char(c,57079).
+char(m,57080).
+char(5,57081).
+char(0,57082).
+char(6,57083).
+char(8,57084).
+char(c,57085).
+char(c,57086).
+char(p,57087).
+char(o,57088).
+char(m,57089).
+char(o,57090).
+char(7,57091).
+char(1,57092).
+char(5,57093).
+char(5,57094).
+char(c,57095).
+char(c,57096).
+char(c,57097).
+char(c,57098).
+char(c,57099).
+char(p,57100).
+char(o,57101).
+char(m,57102).
+char(o,57103).
+char(m,57104).
+char(o,57105).
+char(m,57106).
+char(4,57107).
+char(7,57108).
+char(7,57109).
+char(0,57110).
+char(c,57111).
+char(c,57112).
+char(c,57113).
+char(c,57114).
+char(p,57115).
+char(8,57116).
+char(7,57117).
+char(1,57118).
+char(5,57119).
+char(c,57120).
+char(c,57121).
+char(c,57122).
+char(p,57123).
+char(o,57124).
+char(7,57125).
+char(9,57126).
+char(4,57127).
+char(2,57128).
+char(p,57129).
+char(2,57130).
+char(2,57131).
+char(7,57132).
+char(p,57133).
+char(8,57134).
+char(0,57135).
+char(9,57136).
+char(2,57137).
+char(p,57138).
+char(o,57139).
+char(o,57140).
+char(p,57141).
+char(o,57142).
+char(o,57143).
+char(m,57144).
+char(8,57145).
+char(9,57146).
+char(5,57147).
+char(1,57148).
+char(c,57149).
+char(c,57150).
+char(m,57151).
+char(4,57152).
+char(6,57153).
+char(1,57154).
+char(3,57155).
+char(m,57156).
+char(o,57157).
+char(p,57158).
+char(o,57159).
+char(p,57160).
+char(o,57161).
+char(p,57162).
+char(o,57163).
+char(o,57164).
+char(p,57165).
+char(o,57166).
+char(7,57167).
+char(0,57168).
+char(6,57169).
+char(9,57170).
+char(c,57171).
+char(c,57172).
+char(c,57173).
+char(p,57174).
+char(6,57175).
+char(4,57176).
+char(4,57177).
+char(0,57178).
+char(m,57179).
+char(o,57180).
+char(m,57181).
+char(5,57182).
+char(4,57183).
+char(3,57184).
+char(5,57185).
+char(m,57186).
+char(o,57187).
+char(m,57188).
+char(o,57189).
+char(p,57190).
+char(o,57191).
+char(3,57192).
+char(2,57193).
+char(7,57194).
+char(4,57195).
+char(c,57196).
+char(m,57197).
+char(1,57198).
+char(3,57199).
+char(1,57200).
+char(p,57201).
+char(o,57202).
+char(m,57203).
+char(9,57204).
+char(9,57205).
+char(6,57206).
+char(5,57207).
+char(c,57208).
+char(c,57209).
+char(c,57210).
+char(c,57211).
+char(c,57212).
+char(c,57213).
+char(p,57214).
+char(o,57215).
+char(p,57216).
+char(3,57217).
+char(3,57218).
+char(1,57219).
+char(2,57220).
+char(m,57221).
+char(3,57222).
+char(8,57223).
+char(4,57224).
+char(6,57225).
+char(m,57226).
+char(o,57227).
+char(m,57228).
+char(o,57229).
+char(m,57230).
+char(o,57231).
+char(6,57232).
+char(4,57233).
+char(5,57234).
+char(5,57235).
+char(m,57236).
+char(o,57237).
+char(2,57238).
+char(1,57239).
+char(3,57240).
+char(0,57241).
+char(c,57242).
+char(c,57243).
+char(p,57244).
+char(4,57245).
+char(3,57246).
+char(4,57247).
+char(8,57248).
+char(c,57249).
+char(p,57250).
+char(3,57251).
+char(6,57252).
+char(0,57253).
+char(8,57254).
+char(p,57255).
+char(7,57256).
+char(0,57257).
+char(3,57258).
+char(c,57259).
+char(c,57260).
+char(c,57261).
+char(p,57262).
+char(o,57263).
+char(o,57264).
+char(o,57265).
+char(o,57266).
+char(m,57267).
+char(o,57268).
+char(p,57269).
+char(3,57270).
+char(7,57271).
+char(9,57272).
+char(2,57273).
+char(c,57274).
+char(p,57275).
+char(o,57276).
+char(o,57277).
+char(p,57278).
+char(o,57279).
+char(4,57280).
+char(6,57281).
+char(4,57282).
+char(m,57283).
+char(5,57284).
+char(6,57285).
+char(8,57286).
+char(7,57287).
+char(c,57288).
+char(c,57289).
+char(m,57290).
+char(8,57291).
+char(4,57292).
+char(1,57293).
+char(0,57294).
+char(c,57295).
+char(c,57296).
+char(m,57297).
+char(o,57298).
+char(m,57299).
+char(o,57300).
+char(3,57301).
+char(8,57302).
+char(6,57303).
+char(3,57304).
+char(m,57305).
+char(9,57306).
+char(6,57307).
+char(c,57308).
+char(p,57309).
+char(4,57310).
+char(4,57311).
+char(7,57312).
+char(9,57313).
+char(m,57314).
+char(1,57315).
+char(9,57316).
+char(6,57317).
+char(7,57318).
+char(c,57319).
+char(p,57320).
+char(7,57321).
+char(3,57322).
+char(7,57323).
+char(3,57324).
+char(p,57325).
+char(o,57326).
+char(p,57327).
+char(8,57328).
+char(3,57329).
+char(4,57330).
+char(9,57331).
+char(p,57332).
+char(o,57333).
+char(p,57334).
+char(3,57335).
+char(1,57336).
+char(7,57337).
+char(5,57338).
+char(m,57339).
+char(o,57340).
+char(m,57341).
+char(o,57342).
+char(o,57343).
+char(p,57344).
+char(6,57345).
+char(3,57346).
+char(5,57347).
+char(6,57348).
+char(c,57349).
+char(m,57350).
+char(9,57351).
+char(7,57352).
+char(0,57353).
+char(4,57354).
+char(m,57355).
+char(o,57356).
+char(m,57357).
+char(o,57358).
+char(p,57359).
+char(3,57360).
+char(3,57361).
+char(2,57362).
+char(0,57363).
+char(p,57364).
+char(o,57365).
+char(o,57366).
+char(m,57367).
+char(o,57368).
+char(m,57369).
+char(o,57370).
+char(m,57371).
+char(2,57372).
+char(3,57373).
+char(8,57374).
+char(8,57375).
+char(p,57376).
+char(6,57377).
+char(0,57378).
+char(3,57379).
+char(3,57380).
+char(p,57381).
+char(o,57382).
+char(m,57383).
+char(3,57384).
+char(3,57385).
+char(4,57386).
+char(7,57387).
+char(m,57388).
+char(o,57389).
+char(o,57390).
+char(o,57391).
+char(m,57392).
+char(1,57393).
+char(6,57394).
+char(3,57395).
+char(7,57396).
+char(c,57397).
+char(p,57398).
+char(o,57399).
+char(p,57400).
+char(o,57401).
+char(m,57402).
+char(4,57403).
+char(2,57404).
+char(1,57405).
+char(4,57406).
+char(c,57407).
+char(p,57408).
+char(9,57409).
+char(8,57410).
+char(0,57411).
+char(5,57412).
+char(c,57413).
+char(c,57414).
+char(p,57415).
+char(1,57416).
+char(9,57417).
+char(9,57418).
+char(0,57419).
+char(m,57420).
+char(o,57421).
+char(o,57422).
+char(p,57423).
+char(o,57424).
+char(6,57425).
+char(7,57426).
+char(0,57427).
+char(p,57428).
+char(5,57429).
+char(8,57430).
+char(9,57431).
+char(0,57432).
+char(p,57433).
+char(o,57434).
+char(p,57435).
+char(o,57436).
+char(m,57437).
+char(8,57438).
+char(0,57439).
+char(0,57440).
+char(2,57441).
+char(m,57442).
+char(6,57443).
+char(0,57444).
+char(7,57445).
+char(0,57446).
+char(c,57447).
+char(c,57448).
+char(m,57449).
+char(o,57450).
+char(m,57451).
+char(6,57452).
+char(9,57453).
+char(6,57454).
+char(9,57455).
+char(c,57456).
+char(m,57457).
+char(5,57458).
+char(7,57459).
+char(4,57460).
+char(9,57461).
+char(c,57462).
+char(c,57463).
+char(c,57464).
+char(m,57465).
+char(o,57466).
+char(m,57467).
+char(o,57468).
+char(p,57469).
+char(o,57470).
+char(m,57471).
+char(o,57472).
+char(p,57473).
+char(o,57474).
+char(m,57475).
+char(8,57476).
+char(3,57477).
+char(3,57478).
+char(7,57479).
+char(c,57480).
+char(m,57481).
+char(2,57482).
+char(2,57483).
+char(1,57484).
+char(7,57485).
+char(c,57486).
+char(m,57487).
+char(o,57488).
+char(m,57489).
+char(o,57490).
+char(p,57491).
+char(7,57492).
+char(2,57493).
+char(6,57494).
+char(6,57495).
+char(m,57496).
+char(4,57497).
+char(7,57498).
+char(3,57499).
+char(7,57500).
+char(c,57501).
+char(c,57502).
+char(m,57503).
+char(o,57504).
+char(p,57505).
+char(o,57506).
+char(p,57507).
+char(o,57508).
+char(p,57509).
+char(4,57510).
+char(6,57511).
+char(3,57512).
+char(4,57513).
+char(m,57514).
+char(o,57515).
+char(o,57516).
+char(p,57517).
+char(1,57518).
+char(9,57519).
+char(3,57520).
+char(6,57521).
+char(m,57522).
+char(o,57523).
+char(o,57524).
+char(m,57525).
+char(o,57526).
+char(2,57527).
+char(3,57528).
+char(8,57529).
+char(8,57530).
+char(c,57531).
+char(p,57532).
+char(4,57533).
+char(6,57534).
+char(3,57535).
+char(0,57536).
+char(p,57537).
+char(5,57538).
+char(5,57539).
+char(7,57540).
+char(m,57541).
+char(4,57542).
+char(1,57543).
+char(2,57544).
+char(0,57545).
+char(m,57546).
+char(o,57547).
+char(p,57548).
+char(o,57549).
+char(p,57550).
+char(o,57551).
+char(p,57552).
+char(2,57553).
+char(8,57554).
+char(4,57555).
+char(5,57556).
+char(m,57557).
+char(1,57558).
+char(1,57559).
+char(0,57560).
+char(6,57561).
+char(c,57562).
+char(c,57563).
+char(p,57564).
+char(4,57565).
+char(7,57566).
+char(1,57567).
+char(7,57568).
+char(m,57569).
+char(o,57570).
+char(m,57571).
+char(1,57572).
+char(0,57573).
+char(2,57574).
+char(8,57575).
+char(c,57576).
+char(p,57577).
+char(6,57578).
+char(8,57579).
+char(0,57580).
+char(9,57581).
+char(c,57582).
+char(m,57583).
+char(o,57584).
+char(m,57585).
+char(5,57586).
+char(0,57587).
+char(6,57588).
+char(4,57589).
+char(c,57590).
+char(c,57591).
+char(c,57592).
+char(p,57593).
+char(8,57594).
+char(9,57595).
+char(9,57596).
+char(1,57597).
+char(p,57598).
+char(o,57599).
+char(m,57600).
+char(2,57601).
+char(0,57602).
+char(5,57603).
+char(1,57604).
+char(m,57605).
+char(o,57606).
+char(m,57607).
+char(o,57608).
+char(o,57609).
+char(m,57610).
+char(o,57611).
+char(m,57612).
+char(7,57613).
+char(1,57614).
+char(3,57615).
+char(p,57616).
+char(o,57617).
+char(p,57618).
+char(2,57619).
+char(4,57620).
+char(3,57621).
+char(c,57622).
+char(p,57623).
+char(o,57624).
+char(8,57625).
+char(7,57626).
+char(8,57627).
+char(3,57628).
+char(p,57629).
+char(4,57630).
+char(5,57631).
+char(3,57632).
+char(3,57633).
+char(c,57634).
+char(p,57635).
+char(o,57636).
+char(m,57637).
+char(1,57638).
+char(8,57639).
+char(7,57640).
+char(4,57641).
+char(c,57642).
+char(m,57643).
+char(4,57644).
+char(8,57645).
+char(4,57646).
+char(7,57647).
+char(c,57648).
+char(p,57649).
+char(7,57650).
+char(1,57651).
+char(9,57652).
+char(1,57653).
+char(c,57654).
+char(p,57655).
+char(5,57656).
+char(5,57657).
+char(5,57658).
+char(5,57659).
+char(m,57660).
+char(3,57661).
+char(6,57662).
+char(5,57663).
+char(8,57664).
+char(c,57665).
+char(c,57666).
+char(p,57667).
+char(1,57668).
+char(1,57669).
+char(8,57670).
+char(8,57671).
+char(c,57672).
+char(c,57673).
+char(c,57674).
+char(p,57675).
+char(4,57676).
+char(5,57677).
+char(4,57678).
+char(6,57679).
+char(c,57680).
+char(p,57681).
+char(6,57682).
+char(7,57683).
+char(8,57684).
+char(5,57685).
+char(p,57686).
+char(o,57687).
+char(m,57688).
+char(2,57689).
+char(1,57690).
+char(5,57691).
+char(6,57692).
+char(m,57693).
+char(o,57694).
+char(p,57695).
+char(o,57696).
+char(p,57697).
+char(3,57698).
+char(8,57699).
+char(8,57700).
+char(6,57701).
+char(p,57702).
+char(o,57703).
+char(m,57704).
+char(o,57705).
+char(o,57706).
+char(p,57707).
+char(o,57708).
+char(m,57709).
+char(8,57710).
+char(7,57711).
+char(c,57712).
+char(c,57713).
+char(m,57714).
+char(2,57715).
+char(2,57716).
+char(6,57717).
+char(2,57718).
+char(c,57719).
+char(m,57720).
+char(o,57721).
+char(m,57722).
+char(6,57723).
+char(3,57724).
+char(7,57725).
+char(3,57726).
+char(p,57727).
+char(o,57728).
+char(o,57729).
+char(7,57730).
+char(7,57731).
+char(2,57732).
+char(7,57733).
+char(c,57734).
+char(c,57735).
+char(p,57736).
+char(3,57737).
+char(1,57738).
+char(7,57739).
+char(3,57740).
+char(m,57741).
+char(o,57742).
+char(o,57743).
+char(m,57744).
+char(o,57745).
+char(m,57746).
+char(o,57747).
+char(p,57748).
+char(o,57749).
+char(2,57750).
+char(1,57751).
+char(6,57752).
+char(7,57753).
+char(c,57754).
+char(p,57755).
+char(8,57756).
+char(1,57757).
+char(0,57758).
+char(1,57759).
+char(c,57760).
+char(c,57761).
+char(m,57762).
+char(7,57763).
+char(2,57764).
+char(5,57765).
+char(3,57766).
+char(c,57767).
+char(c,57768).
+char(c,57769).
+char(c,57770).
+char(p,57771).
+char(4,57772).
+char(1,57773).
+char(4,57774).
+char(7,57775).
+char(m,57776).
+char(o,57777).
+char(o,57778).
+char(7,57779).
+char(9,57780).
+char(8,57781).
+char(8,57782).
+char(c,57783).
+char(p,57784).
+char(o,57785).
+char(o,57786).
+char(m,57787).
+char(o,57788).
+char(p,57789).
+char(3,57790).
+char(9,57791).
+char(7,57792).
+char(8,57793).
+char(m,57794).
+char(5,57795).
+char(6,57796).
+char(0,57797).
+char(6,57798).
+char(c,57799).
+char(c,57800).
+char(m,57801).
+char(o,57802).
+char(1,57803).
+char(1,57804).
+char(m,57805).
+char(o,57806).
+char(o,57807).
+char(m,57808).
+char(o,57809).
+char(p,57810).
+char(6,57811).
+char(3,57812).
+char(6,57813).
+char(3,57814).
+char(p,57815).
+char(1,57816).
+char(9,57817).
+char(0,57818).
+char(1,57819).
+char(c,57820).
+char(p,57821).
+char(2,57822).
+char(4,57823).
+char(7,57824).
+char(1,57825).
+char(m,57826).
+char(1,57827).
+char(8,57828).
+char(7,57829).
+char(0,57830).
+char(m,57831).
+char(o,57832).
+char(6,57833).
+char(9,57834).
+char(8,57835).
+char(3,57836).
+char(m,57837).
+char(o,57838).
+char(m,57839).
+char(o,57840).
+char(o,57841).
+char(m,57842).
+char(5,57843).
+char(4,57844).
+char(3,57845).
+char(1,57846).
+char(c,57847).
+char(c,57848).
+char(m,57849).
+char(7,57850).
+char(9,57851).
+char(4,57852).
+char(9,57853).
+char(m,57854).
+char(o,57855).
+char(m,57856).
+char(o,57857).
+char(m,57858).
+char(o,57859).
+char(o,57860).
+char(p,57861).
+char(3,57862).
+char(0,57863).
+char(2,57864).
+char(2,57865).
+char(c,57866).
+char(m,57867).
+char(4,57868).
+char(8,57869).
+char(9,57870).
+char(9,57871).
+char(m,57872).
+char(o,57873).
+char(p,57874).
+char(9,57875).
+char(4,57876).
+char(8,57877).
+char(2,57878).
+char(p,57879).
+char(o,57880).
+char(p,57881).
+char(o,57882).
+char(m,57883).
+char(o,57884).
+char(p,57885).
+char(6,57886).
+char(8,57887).
+char(4,57888).
+char(4,57889).
+char(c,57890).
+char(c,57891).
+char(c,57892).
+char(m,57893).
+char(3,57894).
+char(4,57895).
+char(0,57896).
+char(8,57897).
+char(p,57898).
+char(5,57899).
+char(0,57900).
+char(7,57901).
+char(0,57902).
+char(c,57903).
+char(m,57904).
+char(3,57905).
+char(0,57906).
+char(3,57907).
+char(0,57908).
+char(m,57909).
+char(9,57910).
+char(5,57911).
+char(5,57912).
+char(3,57913).
+char(c,57914).
+char(c,57915).
+char(p,57916).
+char(o,57917).
+char(6,57918).
+char(9,57919).
+char(0,57920).
+char(6,57921).
+char(p,57922).
+char(1,57923).
+char(7,57924).
+char(1,57925).
+char(0,57926).
+char(p,57927).
+char(o,57928).
+char(m,57929).
+char(o,57930).
+char(p,57931).
+char(o,57932).
+char(o,57933).
+char(m,57934).
+char(6,57935).
+char(9,57936).
+char(4,57937).
+char(4,57938).
+char(c,57939).
+char(m,57940).
+char(o,57941).
+char(m,57942).
+char(3,57943).
+char(0,57944).
+char(5,57945).
+char(1,57946).
+char(m,57947).
+char(o,57948).
+char(p,57949).
+char(o,57950).
+char(m,57951).
+char(4,57952).
+char(2,57953).
+char(0,57954).
+char(5,57955).
+char(p,57956).
+char(o,57957).
+char(p,57958).
+char(2,57959).
+char(8,57960).
+char(6,57961).
+char(4,57962).
+char(c,57963).
+char(p,57964).
+char(o,57965).
+char(m,57966).
+char(o,57967).
+char(m,57968).
+char(3,57969).
+char(6,57970).
+char(3,57971).
+char(8,57972).
+char(c,57973).
+char(c,57974).
+char(m,57975).
+char(o,57976).
+char(m,57977).
+char(6,57978).
+char(6,57979).
+char(2,57980).
+char(3,57981).
+char(c,57982).
+char(c,57983).
+char(m,57984).
+char(1,57985).
+char(6,57986).
+char(8,57987).
+char(m,57988).
+char(9,57989).
+char(5,57990).
+char(4,57991).
+char(9,57992).
+char(p,57993).
+char(7,57994).
+char(7,57995).
+char(1,57996).
+char(1,57997).
+char(p,57998).
+char(3,57999).
+char(7,58000).
+char(8,58001).
+char(3,58002).
+char(p,58003).
+char(5,58004).
+char(8,58005).
+char(8,58006).
+char(4,58007).
+char(c,58008).
+char(c,58009).
+char(c,58010).
+char(c,58011).
+char(m,58012).
+char(2,58013).
+char(4,58014).
+char(0,58015).
+char(4,58016).
+char(c,58017).
+char(c,58018).
+char(c,58019).
+char(c,58020).
+char(c,58021).
+char(m,58022).
+char(o,58023).
+char(o,58024).
+char(9,58025).
+char(0,58026).
+char(1,58027).
+char(9,58028).
+char(c,58029).
+char(c,58030).
+char(c,58031).
+char(c,58032).
+char(c,58033).
+char(p,58034).
+char(o,58035).
+char(o,58036).
+char(p,58037).
+char(o,58038).
+char(m,58039).
+char(9,58040).
+char(1,58041).
+char(7,58042).
+char(2,58043).
+char(c,58044).
+char(c,58045).
+char(c,58046).
+char(m,58047).
+char(2,58048).
+char(9,58049).
+char(9,58050).
+char(3,58051).
+char(c,58052).
+char(c,58053).
+char(c,58054).
+char(m,58055).
+char(6,58056).
+char(4,58057).
+char(4,58058).
+char(8,58059).
+char(m,58060).
+char(5,58061).
+char(9,58062).
+char(2,58063).
+char(0,58064).
+char(c,58065).
+char(m,58066).
+char(7,58067).
+char(5,58068).
+char(2,58069).
+char(9,58070).
+char(m,58071).
+char(2,58072).
+char(6,58073).
+char(9,58074).
+char(0,58075).
+char(c,58076).
+char(p,58077).
+char(o,58078).
+char(m,58079).
+char(o,58080).
+char(m,58081).
+char(o,58082).
+char(m,58083).
+char(o,58084).
+char(p,58085).
+char(o,58086).
+char(m,58087).
+char(o,58088).
+char(m,58089).
+char(o,58090).
+char(p,58091).
+char(o,58092).
+char(m,58093).
+char(5,58094).
+char(6,58095).
+char(8,58096).
+char(8,58097).
+char(m,58098).
+char(9,58099).
+char(6,58100).
+char(4,58101).
+char(2,58102).
+char(p,58103).
+char(7,58104).
+char(0,58105).
+char(9,58106).
+char(6,58107).
+char(m,58108).
+char(1,58109).
+char(9,58110).
+char(9,58111).
+char(9,58112).
+char(c,58113).
+char(p,58114).
+char(5,58115).
+char(3,58116).
+char(5,58117).
+char(2,58118).
+char(c,58119).
+char(c,58120).
+char(m,58121).
+char(4,58122).
+char(8,58123).
+char(7,58124).
+char(5,58125).
+char(p,58126).
+char(8,58127).
+char(0,58128).
+char(9,58129).
+char(9,58130).
+char(p,58131).
+char(3,58132).
+char(5,58133).
+char(6,58134).
+char(0,58135).
+char(c,58136).
+char(p,58137).
+char(o,58138).
+char(m,58139).
+char(2,58140).
+char(6,58141).
+char(9,58142).
+char(3,58143).
+char(p,58144).
+char(5,58145).
+char(2,58146).
+char(0,58147).
+char(7,58148).
+char(c,58149).
+char(m,58150).
+char(1,58151).
+char(5,58152).
+char(8,58153).
+char(4,58154).
+char(p,58155).
+char(7,58156).
+char(0,58157).
+char(1,58158).
+char(3,58159).
+char(p,58160).
+char(4,58161).
+char(1,58162).
+char(9,58163).
+char(7,58164).
+char(p,58165).
+char(2,58166).
+char(2,58167).
+char(0,58168).
+char(7,58169).
+char(c,58170).
+char(m,58171).
+char(2,58172).
+char(1,58173).
+char(1,58174).
+char(5,58175).
+char(c,58176).
+char(m,58177).
+char(o,58178).
+char(p,58179).
+char(4,58180).
+char(6,58181).
+char(2,58182).
+char(9,58183).
+char(c,58184).
+char(c,58185).
+char(c,58186).
+char(c,58187).
+char(m,58188).
+char(o,58189).
+char(p,58190).
+char(5,58191).
+char(0,58192).
+char(2,58193).
+char(4,58194).
+char(c,58195).
+char(c,58196).
+char(m,58197).
+char(o,58198).
+char(m,58199).
+char(o,58200).
+char(m,58201).
+char(6,58202).
+char(8,58203).
+char(4,58204).
+char(2,58205).
+char(c,58206).
+char(c,58207).
+char(m,58208).
+char(o,58209).
+char(p,58210).
+char(o,58211).
+char(8,58212).
+char(9,58213).
+char(2,58214).
+char(3,58215).
+char(c,58216).
+char(c,58217).
+char(c,58218).
+char(c,58219).
+char(p,58220).
+char(4,58221).
+char(4,58222).
+char(0,58223).
+char(0,58224).
+char(p,58225).
+char(o,58226).
+char(p,58227).
+char(7,58228).
+char(5,58229).
+char(6,58230).
+char(8,58231).
+char(p,58232).
+char(o,58233).
+char(p,58234).
+char(o,58235).
+char(m,58236).
+char(6,58237).
+char(4,58238).
+char(3,58239).
+char(0,58240).
+char(c,58241).
+char(c,58242).
+char(c,58243).
+char(c,58244).
+char(m,58245).
+char(o,58246).
+char(m,58247).
+char(2,58248).
+char(1,58249).
+char(0,58250).
+char(7,58251).
+char(c,58252).
+char(c,58253).
+char(m,58254).
+char(1,58255).
+char(8,58256).
+char(9,58257).
+char(4,58258).
+char(m,58259).
+char(5,58260).
+char(0,58261).
+char(1,58262).
+char(4,58263).
+char(c,58264).
+char(c,58265).
+char(m,58266).
+char(9,58267).
+char(2,58268).
+char(0,58269).
+char(0,58270).
+char(c,58271).
+char(p,58272).
+char(o,58273).
+char(o,58274).
+char(p,58275).
+char(o,58276).
+char(p,58277).
+char(5,58278).
+char(6,58279).
+char(3,58280).
+char(3,58281).
+char(c,58282).
+char(m,58283).
+char(3,58284).
+char(1,58285).
+char(5,58286).
+char(c,58287).
+char(p,58288).
+char(4,58289).
+char(p,58290).
+char(9,58291).
+char(3,58292).
+char(8,58293).
+char(6,58294).
+char(c,58295).
+char(c,58296).
+char(p,58297).
+char(8,58298).
+char(9,58299).
+char(3,58300).
+char(1,58301).
+char(m,58302).
+char(6,58303).
+char(0,58304).
+char(2,58305).
+char(5,58306).
+char(c,58307).
+char(c,58308).
+char(c,58309).
+char(m,58310).
+char(6,58311).
+char(3,58312).
+char(4,58313).
+char(4,58314).
+char(p,58315).
+char(2,58316).
+char(4,58317).
+char(6,58318).
+char(1,58319).
+char(m,58320).
+char(9,58321).
+char(3,58322).
+char(1,58323).
+char(7,58324).
+char(c,58325).
+char(m,58326).
+char(9,58327).
+char(6,58328).
+char(3,58329).
+char(0,58330).
+char(p,58331).
+char(o,58332).
+char(p,58333).
+char(8,58334).
+char(5,58335).
+char(2,58336).
+char(4,58337).
+char(c,58338).
+char(p,58339).
+char(2,58340).
+char(6,58341).
+char(4,58342).
+char(3,58343).
+char(m,58344).
+char(9,58345).
+char(5,58346).
+char(8,58347).
+char(9,58348).
+char(p,58349).
+char(1,58350).
+char(7,58351).
+char(4,58352).
+char(3,58353).
+char(c,58354).
+char(c,58355).
+char(c,58356).
+char(c,58357).
+char(m,58358).
+char(4,58359).
+char(1,58360).
+char(1,58361).
+char(0,58362).
+char(m,58363).
+char(1,58364).
+char(4,58365).
+char(3,58366).
+char(9,58367).
+char(m,58368).
+char(6,58369).
+char(2,58370).
+char(7,58371).
+char(2,58372).
+char(m,58373).
+char(1,58374).
+char(0,58375).
+char(9,58376).
+char(8,58377).
+char(c,58378).
+char(c,58379).
+char(c,58380).
+char(m,58381).
+char(o,58382).
+char(p,58383).
+char(6,58384).
+char(5,58385).
+char(8,58386).
+char(6,58387).
+char(c,58388).
+char(m,58389).
+char(1,58390).
+char(3,58391).
+char(5,58392).
+char(5,58393).
+char(c,58394).
+char(c,58395).
+char(p,58396).
+char(o,58397).
+char(m,58398).
+char(2,58399).
+char(8,58400).
+char(4,58401).
+char(9,58402).
+char(c,58403).
+char(c,58404).
+char(c,58405).
+char(c,58406).
+char(p,58407).
+char(o,58408).
+char(p,58409).
+char(o,58410).
+char(m,58411).
+char(2,58412).
+char(6,58413).
+char(9,58414).
+char(0,58415).
+char(m,58416).
+char(5,58417).
+char(2,58418).
+char(0,58419).
+char(0,58420).
+char(c,58421).
+char(p,58422).
+char(6,58423).
+char(1,58424).
+char(2,58425).
+char(5,58426).
+char(c,58427).
+char(p,58428).
+char(o,58429).
+char(p,58430).
+char(o,58431).
+char(o,58432).
+char(m,58433).
+char(o,58434).
+char(6,58435).
+char(1,58436).
+char(6,58437).
+char(4,58438).
+char(c,58439).
+char(p,58440).
+char(o,58441).
+char(m,58442).
+char(o,58443).
+char(p,58444).
+char(3,58445).
+char(4,58446).
+char(4,58447).
+char(7,58448).
+char(c,58449).
+char(m,58450).
+char(o,58451).
+char(3,58452).
+char(2,58453).
+char(9,58454).
+char(3,58455).
+char(p,58456).
+char(4,58457).
+char(9,58458).
+char(5,58459).
+char(6,58460).
+char(m,58461).
+char(o,58462).
+char(p,58463).
+char(7,58464).
+char(7,58465).
+char(7,58466).
+char(6,58467).
+char(c,58468).
+char(p,58469).
+char(6,58470).
+char(0,58471).
+char(6,58472).
+char(8,58473).
+char(c,58474).
+char(m,58475).
+char(4,58476).
+char(8,58477).
+char(9,58478).
+char(9,58479).
+char(c,58480).
+char(p,58481).
+char(6,58482).
+char(1,58483).
+char(9,58484).
+char(2,58485).
+char(c,58486).
+char(p,58487).
+char(1,58488).
+char(1,58489).
+char(6,58490).
+char(6,58491).
+char(m,58492).
+char(o,58493).
+char(p,58494).
+char(o,58495).
+char(p,58496).
+char(o,58497).
+char(m,58498).
+char(o,58499).
+char(2,58500).
+char(5,58501).
+char(8,58502).
+char(9,58503).
+char(c,58504).
+char(c,58505).
+char(c,58506).
+char(p,58507).
+char(2,58508).
+char(8,58509).
+char(7,58510).
+char(9,58511).
+char(c,58512).
+char(p,58513).
+char(2,58514).
+char(3,58515).
+char(7,58516).
+char(2,58517).
+char(c,58518).
+char(p,58519).
+char(o,58520).
+char(p,58521).
+char(o,58522).
+char(p,58523).
+char(9,58524).
+char(1,58525).
+char(6,58526).
+char(1,58527).
+char(p,58528).
+char(o,58529).
+char(m,58530).
+char(9,58531).
+char(7,58532).
+char(7,58533).
+char(5,58534).
+char(p,58535).
+char(6,58536).
+char(7,58537).
+char(7,58538).
+char(c,58539).
+char(p,58540).
+char(3,58541).
+char(4,58542).
+char(0,58543).
+char(9,58544).
+char(m,58545).
+char(1,58546).
+char(6,58547).
+char(9,58548).
+char(2,58549).
+char(c,58550).
+char(c,58551).
+char(c,58552).
+char(m,58553).
+char(o,58554).
+char(p,58555).
+char(o,58556).
+char(m,58557).
+char(o,58558).
+char(p,58559).
+char(o,58560).
+char(m,58561).
+char(8,58562).
+char(1,58563).
+char(0,58564).
+char(4,58565).
+char(p,58566).
+char(o,58567).
+char(p,58568).
+char(o,58569).
+char(4,58570).
+char(9,58571).
+char(7,58572).
+char(3,58573).
+char(m,58574).
+char(o,58575).
+char(6,58576).
+char(5,58577).
+char(5,58578).
+char(1,58579).
+char(m,58580).
+char(2,58581).
+char(8,58582).
+char(4,58583).
+char(5,58584).
+char(c,58585).
+char(p,58586).
+char(o,58587).
+char(o,58588).
+char(m,58589).
+char(6,58590).
+char(6,58591).
+char(9,58592).
+char(8,58593).
+char(p,58594).
+char(2,58595).
+char(4,58596).
+char(2,58597).
+char(6,58598).
+char(p,58599).
+char(o,58600).
+char(m,58601).
+char(3,58602).
+char(2,58603).
+char(7,58604).
+char(7,58605).
+char(m,58606).
+char(o,58607).
+char(p,58608).
+char(o,58609).
+char(p,58610).
+char(o,58611).
+char(1,58612).
+char(1,58613).
+char(9,58614).
+char(8,58615).
+char(c,58616).
+char(c,58617).
+char(c,58618).
+char(c,58619).
+char(c,58620).
+char(m,58621).
+char(1,58622).
+char(9,58623).
+char(5,58624).
+char(m,58625).
+char(4,58626).
+char(3,58627).
+char(6,58628).
+char(7,58629).
+char(c,58630).
+char(m,58631).
+char(5,58632).
+char(2,58633).
+char(3,58634).
+char(0,58635).
+char(p,58636).
+char(8,58637).
+char(4,58638).
+char(2,58639).
+char(9,58640).
+char(c,58641).
+char(c,58642).
+char(p,58643).
+char(5,58644).
+char(7,58645).
+char(7,58646).
+char(8,58647).
+char(m,58648).
+char(o,58649).
+char(m,58650).
+char(o,58651).
+char(p,58652).
+char(1,58653).
+char(8,58654).
+char(7,58655).
+char(m,58656).
+char(o,58657).
+char(p,58658).
+char(1,58659).
+char(0,58660).
+char(0,58661).
+char(9,58662).
+char(c,58663).
+char(m,58664).
+char(1,58665).
+char(1,58666).
+char(5,58667).
+char(c,58668).
+char(c,58669).
+char(c,58670).
+char(c,58671).
+char(p,58672).
+char(3,58673).
+char(8,58674).
+char(7,58675).
+char(3,58676).
+char(m,58677).
+char(1,58678).
+char(6,58679).
+char(9,58680).
+char(7,58681).
+char(c,58682).
+char(c,58683).
+char(c,58684).
+char(c,58685).
+char(p,58686).
+char(8,58687).
+char(3,58688).
+char(5,58689).
+char(1,58690).
+char(m,58691).
+char(8,58692).
+char(5,58693).
+char(9,58694).
+char(5,58695).
+char(p,58696).
+char(o,58697).
+char(p,58698).
+char(o,58699).
+char(o,58700).
+char(m,58701).
+char(o,58702).
+char(o,58703).
+char(p,58704).
+char(o,58705).
+char(m,58706).
+char(3,58707).
+char(6,58708).
+char(8,58709).
+char(5,58710).
+char(m,58711).
+char(o,58712).
+char(2,58713).
+char(0,58714).
+char(6,58715).
+char(5,58716).
+char(c,58717).
+char(m,58718).
+char(3,58719).
+char(2,58720).
+char(4,58721).
+char(p,58722).
+char(o,58723).
+char(o,58724).
+char(1,58725).
+char(6,58726).
+char(4,58727).
+char(5,58728).
+char(c,58729).
+char(p,58730).
+char(o,58731).
+char(m,58732).
+char(o,58733).
+char(o,58734).
+char(m,58735).
+char(6,58736).
+char(0,58737).
+char(5,58738).
+char(8,58739).
+char(p,58740).
+char(o,58741).
+char(o,58742).
+char(m,58743).
+char(4,58744).
+char(2,58745).
+char(8,58746).
+char(c,58747).
+char(c,58748).
+char(p,58749).
+char(2,58750).
+char(6,58751).
+char(7,58752).
+char(1,58753).
+char(p,58754).
+char(o,58755).
+char(m,58756).
+char(8,58757).
+char(3,58758).
+char(3,58759).
+char(5,58760).
+char(c,58761).
+char(c,58762).
+char(p,58763).
+char(9,58764).
+char(3,58765).
+char(8,58766).
+char(3,58767).
+char(p,58768).
+char(o,58769).
+char(p,58770).
+char(5,58771).
+char(5,58772).
+char(1,58773).
+char(9,58774).
+char(c,58775).
+char(c,58776).
+char(c,58777).
+char(m,58778).
+char(3,58779).
+char(3,58780).
+char(9,58781).
+char(6,58782).
+char(m,58783).
+char(o,58784).
+char(m,58785).
+char(6,58786).
+char(9,58787).
+char(5,58788).
+char(2,58789).
+char(c,58790).
+char(m,58791).
+char(4,58792).
+char(2,58793).
+char(6,58794).
+char(6,58795).
+char(m,58796).
+char(4,58797).
+char(0,58798).
+char(7,58799).
+char(5,58800).
+char(c,58801).
+char(c,58802).
+char(c,58803).
+char(c,58804).
+char(p,58805).
+char(o,58806).
+char(p,58807).
+char(6,58808).
+char(9,58809).
+char(2,58810).
+char(2,58811).
+char(p,58812).
+char(o,58813).
+char(m,58814).
+char(2,58815).
+char(0,58816).
+char(4,58817).
+char(3,58818).
+char(c,58819).
+char(m,58820).
+char(o,58821).
+char(o,58822).
+char(m,58823).
+char(2,58824).
+char(7,58825).
+char(8,58826).
+char(5,58827).
+char(p,58828).
+char(4,58829).
+char(3,58830).
+char(4,58831).
+char(6,58832).
+char(m,58833).
+char(o,58834).
+char(2,58835).
+char(3,58836).
+char(7,58837).
+char(0,58838).
+char(p,58839).
+char(o,58840).
+char(p,58841).
+char(8,58842).
+char(6,58843).
+char(8,58844).
+char(4,58845).
+char(m,58846).
+char(2,58847).
+char(1,58848).
+char(6,58849).
+char(7,58850).
+char(c,58851).
+char(c,58852).
+char(p,58853).
+char(o,58854).
+char(p,58855).
+char(8,58856).
+char(7,58857).
+char(9,58858).
+char(1,58859).
+char(p,58860).
+char(7,58861).
+char(8,58862).
+char(3,58863).
+char(5,58864).
+char(p,58865).
+char(3,58866).
+char(9,58867).
+char(2,58868).
+char(7,58869).
+char(p,58870).
+char(o,58871).
+char(p,58872).
+char(o,58873).
+char(m,58874).
+char(2,58875).
+char(1,58876).
+char(4,58877).
+char(2,58878).
+char(m,58879).
+char(8,58880).
+char(2,58881).
+char(1,58882).
+char(1,58883).
+char(p,58884).
+char(o,58885).
+char(o,58886).
+char(p,58887).
+char(o,58888).
+char(p,58889).
+char(o,58890).
+char(o,58891).
+char(p,58892).
+char(o,58893).
+char(m,58894).
+char(o,58895).
+char(p,58896).
+char(o,58897).
+char(m,58898).
+char(3,58899).
+char(3,58900).
+char(7,58901).
+char(c,58902).
+char(m,58903).
+char(o,58904).
+char(7,58905).
+char(7,58906).
+char(3,58907).
+char(7,58908).
+char(p,58909).
+char(o,58910).
+char(m,58911).
+char(6,58912).
+char(1,58913).
+char(7,58914).
+char(8,58915).
+char(c,58916).
+char(c,58917).
+char(p,58918).
+char(o,58919).
+char(m,58920).
+char(o,58921).
+char(p,58922).
+char(8,58923).
+char(0,58924).
+char(2,58925).
+char(c,58926).
+char(p,58927).
+char(8,58928).
+char(6,58929).
+char(4,58930).
+char(0,58931).
+char(c,58932).
+char(p,58933).
+char(8,58934).
+char(9,58935).
+char(5,58936).
+char(8,58937).
+char(c,58938).
+char(p,58939).
+char(6,58940).
+char(7,58941).
+char(5,58942).
+char(0,58943).
+char(m,58944).
+char(6,58945).
+char(9,58946).
+char(6,58947).
+char(7,58948).
+char(m,58949).
+char(o,58950).
+char(m,58951).
+char(5,58952).
+char(4,58953).
+char(8,58954).
+char(9,58955).
+char(m,58956).
+char(3,58957).
+char(9,58958).
+char(6,58959).
+char(m,58960).
+char(o,58961).
+char(m,58962).
+char(7,58963).
+char(8,58964).
+char(6,58965).
+char(c,58966).
+char(p,58967).
+char(o,58968).
+char(m,58969).
+char(o,58970).
+char(3,58971).
+char(6,58972).
+char(5,58973).
+char(2,58974).
+char(m,58975).
+char(5,58976).
+char(3,58977).
+char(6,58978).
+char(3,58979).
+char(c,58980).
+char(c,58981).
+char(m,58982).
+char(o,58983).
+char(o,58984).
+char(p,58985).
+char(8,58986).
+char(7,58987).
+char(0,58988).
+char(p,58989).
+char(o,58990).
+char(m,58991).
+char(o,58992).
+char(m,58993).
+char(6,58994).
+char(4,58995).
+char(4,58996).
+char(6,58997).
+char(c,58998).
+char(c,58999).
+char(p,59000).
+char(5,59001).
+char(7,59002).
+char(0,59003).
+char(2,59004).
+char(c,59005).
+char(c,59006).
+char(p,59007).
+char(1,59008).
+char(9,59009).
+char(3,59010).
+char(3,59011).
+char(m,59012).
+char(4,59013).
+char(4,59014).
+char(7,59015).
+char(9,59016).
+char(c,59017).
+char(m,59018).
+char(7,59019).
+char(0,59020).
+char(9,59021).
+char(1,59022).
+char(c,59023).
+char(c,59024).
+char(m,59025).
+char(1,59026).
+char(6,59027).
+char(2,59028).
+char(1,59029).
+char(c,59030).
+char(c,59031).
+char(m,59032).
+char(o,59033).
+char(m,59034).
+char(7,59035).
+char(7,59036).
+char(8,59037).
+char(m,59038).
+char(o,59039).
+char(m,59040).
+char(o,59041).
+char(p,59042).
+char(9,59043).
+char(0,59044).
+char(8,59045).
+char(2,59046).
+char(p,59047).
+char(7,59048).
+char(8,59049).
+char(5,59050).
+char(3,59051).
+char(p,59052).
+char(o,59053).
+char(m,59054).
+char(7,59055).
+char(6,59056).
+char(5,59057).
+char(7,59058).
+char(c,59059).
+char(c,59060).
+char(m,59061).
+char(1,59062).
+char(2,59063).
+char(2,59064).
+char(3,59065).
+char(c,59066).
+char(m,59067).
+char(o,59068).
+char(o,59069).
+char(o,59070).
+char(p,59071).
+char(o,59072).
+char(p,59073).
+char(o,59074).
+char(o,59075).
+char(p,59076).
+char(o,59077).
+char(p,59078).
+char(o,59079).
+char(o,59080).
+char(3,59081).
+char(1,59082).
+char(0,59083).
+char(2,59084).
+char(c,59085).
+char(p,59086).
+char(2,59087).
+char(4,59088).
+char(8,59089).
+char(9,59090).
+char(m,59091).
+char(9,59092).
+char(6,59093).
+char(2,59094).
+char(2,59095).
+char(c,59096).
+char(c,59097).
+char(p,59098).
+char(o,59099).
+char(p,59100).
+char(9,59101).
+char(4,59102).
+char(9,59103).
+char(8,59104).
+char(c,59105).
+char(c,59106).
+char(m,59107).
+char(7,59108).
+char(9,59109).
+char(6,59110).
+char(7,59111).
+char(p,59112).
+char(4,59113).
+char(2,59114).
+char(1,59115).
+char(0,59116).
+char(m,59117).
+char(o,59118).
+char(p,59119).
+char(o,59120).
+char(p,59121).
+char(8,59122).
+char(6,59123).
+char(7,59124).
+char(6,59125).
+char(m,59126).
+char(4,59127).
+char(7,59128).
+char(0,59129).
+char(7,59130).
+char(c,59131).
+char(c,59132).
+char(m,59133).
+char(1,59134).
+char(0,59135).
+char(7,59136).
+char(0,59137).
+char(c,59138).
+char(c,59139).
+char(c,59140).
+char(m,59141).
+char(2,59142).
+char(9,59143).
+char(4,59144).
+char(8,59145).
+char(m,59146).
+char(o,59147).
+char(m,59148).
+char(9,59149).
+char(5,59150).
+char(9,59151).
+char(0,59152).
+char(p,59153).
+char(o,59154).
+char(m,59155).
+char(o,59156).
+char(m,59157).
+char(o,59158).
+char(p,59159).
+char(8,59160).
+char(2,59161).
+char(8,59162).
+char(m,59163).
+char(o,59164).
+char(m,59165).
+char(o,59166).
+char(p,59167).
+char(o,59168).
+char(7,59169).
+char(4,59170).
+char(4,59171).
+char(7,59172).
+char(m,59173).
+char(1,59174).
+char(6,59175).
+char(1,59176).
+char(3,59177).
+char(m,59178).
+char(o,59179).
+char(m,59180).
+char(5,59181).
+char(4,59182).
+char(3,59183).
+char(0,59184).
+char(c,59185).
+char(p,59186).
+char(8,59187).
+char(8,59188).
+char(0,59189).
+char(4,59190).
+char(c,59191).
+char(c,59192).
+char(m,59193).
+char(5,59194).
+char(3,59195).
+char(9,59196).
+char(4,59197).
+char(p,59198).
+char(2,59199).
+char(8,59200).
+char(5,59201).
+char(4,59202).
+char(c,59203).
+char(m,59204).
+char(5,59205).
+char(0,59206).
+char(5,59207).
+char(5,59208).
+char(p,59209).
+char(o,59210).
+char(4,59211).
+char(8,59212).
+char(3,59213).
+char(7,59214).
+char(p,59215).
+char(o,59216).
+char(o,59217).
+char(o,59218).
+char(p,59219).
+char(8,59220).
+char(2,59221).
+char(9,59222).
+char(8,59223).
+char(m,59224).
+char(9,59225).
+char(0,59226).
+char(2,59227).
+char(m,59228).
+char(9,59229).
+char(7,59230).
+char(0,59231).
+char(1,59232).
+char(c,59233).
+char(m,59234).
+char(o,59235).
+char(3,59236).
+char(7,59237).
+char(2,59238).
+char(6,59239).
+char(c,59240).
+char(c,59241).
+char(m,59242).
+char(o,59243).
+char(p,59244).
+char(4,59245).
+char(3,59246).
+char(7,59247).
+char(3,59248).
+char(c,59249).
+char(c,59250).
+char(c,59251).
+char(m,59252).
+char(o,59253).
+char(m,59254).
+char(5,59255).
+char(4,59256).
+char(9,59257).
+char(0,59258).
+char(c,59259).
+char(p,59260).
+char(6,59261).
+char(6,59262).
+char(5,59263).
+char(8,59264).
+char(m,59265).
+char(o,59266).
+char(o,59267).
+char(m,59268).
+char(o,59269).
+char(2,59270).
+char(0,59271).
+char(1,59272).
+char(0,59273).
+char(c,59274).
+char(m,59275).
+char(o,59276).
+char(p,59277).
+char(9,59278).
+char(8,59279).
+char(9,59280).
+char(7,59281).
+char(m,59282).
+char(4,59283).
+char(6,59284).
+char(9,59285).
+char(2,59286).
+char(c,59287).
+char(m,59288).
+char(o,59289).
+char(p,59290).
+char(1,59291).
+char(7,59292).
+char(1,59293).
+char(0,59294).
+char(p,59295).
+char(2,59296).
+char(1,59297).
+char(7,59298).
+char(0,59299).
+char(c,59300).
+char(c,59301).
+char(c,59302).
+char(p,59303).
+char(o,59304).
+char(p,59305).
+char(o,59306).
+char(o,59307).
+char(p,59308).
+char(9,59309).
+char(9,59310).
+char(5,59311).
+char(1,59312).
+char(c,59313).
+char(c,59314).
+char(c,59315).
+char(p,59316).
+char(3,59317).
+char(7,59318).
+char(9,59319).
+char(8,59320).
+char(m,59321).
+char(1,59322).
+char(2,59323).
+char(0,59324).
+char(6,59325).
+char(m,59326).
+char(6,59327).
+char(1,59328).
+char(4,59329).
+char(5,59330).
+char(c,59331).
+char(m,59332).
+char(o,59333).
+char(m,59334).
+char(8,59335).
+char(8,59336).
+char(5,59337).
+char(p,59338).
+char(6,59339).
+char(9,59340).
+char(2,59341).
+char(6,59342).
+char(m,59343).
+char(o,59344).
+char(o,59345).
+char(p,59346).
+char(5,59347).
+char(7,59348).
+char(5,59349).
+char(c,59350).
+char(m,59351).
+char(o,59352).
+char(m,59353).
+char(o,59354).
+char(p,59355).
+char(4,59356).
+char(7,59357).
+char(9,59358).
+char(2,59359).
+char(p,59360).
+char(o,59361).
+char(p,59362).
+char(o,59363).
+char(p,59364).
+char(o,59365).
+char(7,59366).
+char(8,59367).
+char(2,59368).
+char(8,59369).
+char(c,59370).
+char(c,59371).
+char(c,59372).
+char(p,59373).
+char(6,59374).
+char(4,59375).
+char(7,59376).
+char(0,59377).
+char(c,59378).
+char(m,59379).
+char(5,59380).
+char(6,59381).
+char(0,59382).
+char(5,59383).
+char(m,59384).
+char(6,59385).
+char(6,59386).
+char(9,59387).
+char(4,59388).
+char(m,59389).
+char(3,59390).
+char(4,59391).
+char(7,59392).
+char(1,59393).
+char(m,59394).
+char(o,59395).
+char(p,59396).
+char(2,59397).
+char(9,59398).
+char(3,59399).
+char(6,59400).
+char(c,59401).
+char(c,59402).
+char(m,59403).
+char(7,59404).
+char(5,59405).
+char(5,59406).
+char(6,59407).
+char(p,59408).
+char(o,59409).
+char(p,59410).
+char(8,59411).
+char(9,59412).
+char(6,59413).
+char(2,59414).
+char(m,59415).
+char(o,59416).
+char(p,59417).
+char(o,59418).
+char(p,59419).
+char(3,59420).
+char(4,59421).
+char(4,59422).
+char(0,59423).
+char(c,59424).
+char(m,59425).
+char(9,59426).
+char(8,59427).
+char(1,59428).
+char(9,59429).
+char(c,59430).
+char(m,59431).
+char(o,59432).
+char(m,59433).
+char(4,59434).
+char(2,59435).
+char(6,59436).
+char(3,59437).
+char(c,59438).
+char(p,59439).
+char(o,59440).
+char(p,59441).
+char(8,59442).
+char(8,59443).
+char(7,59444).
+char(0,59445).
+char(c,59446).
+char(c,59447).
+char(c,59448).
+char(c,59449).
+char(c,59450).
+char(c,59451).
+char(m,59452).
+char(9,59453).
+char(4,59454).
+char(3,59455).
+char(0,59456).
+char(p,59457).
+char(2,59458).
+char(3,59459).
+char(8,59460).
+char(4,59461).
+char(m,59462).
+char(o,59463).
+char(3,59464).
+char(1,59465).
+char(2,59466).
+char(3,59467).
+char(c,59468).
+char(c,59469).
+char(c,59470).
+char(c,59471).
+char(p,59472).
+char(9,59473).
+char(4,59474).
+char(7,59475).
+char(2,59476).
+char(p,59477).
+char(2,59478).
+char(0,59479).
+char(6,59480).
+char(4,59481).
+char(c,59482).
+char(c,59483).
+char(c,59484).
+char(c,59485).
+char(c,59486).
+char(c,59487).
+char(m,59488).
+char(1,59489).
+char(6,59490).
+char(6,59491).
+char(1,59492).
+char(m,59493).
+char(3,59494).
+char(1,59495).
+char(9,59496).
+char(c,59497).
+char(m,59498).
+char(o,59499).
+char(p,59500).
+char(1,59501).
+char(3,59502).
+char(1,59503).
+char(0,59504).
+char(c,59505).
+char(p,59506).
+char(o,59507).
+char(p,59508).
+char(o,59509).
+char(7,59510).
+char(5,59511).
+char(6,59512).
+char(2,59513).
+char(c,59514).
+char(c,59515).
+char(c,59516).
+char(c,59517).
+char(c,59518).
+char(m,59519).
+char(3,59520).
+char(0,59521).
+char(1,59522).
+char(5,59523).
+char(c,59524).
+char(c,59525).
+char(c,59526).
+char(c,59527).
+char(c,59528).
+char(c,59529).
+char(m,59530).
+char(2,59531).
+char(0,59532).
+char(5,59533).
+char(7,59534).
+char(c,59535).
+char(p,59536).
+char(o,59537).
+char(o,59538).
+char(2,59539).
+char(2,59540).
+char(9,59541).
+char(7,59542).
+char(m,59543).
+char(o,59544).
+char(p,59545).
+char(o,59546).
+char(o,59547).
+char(m,59548).
+char(o,59549).
+char(p,59550).
+char(2,59551).
+char(6,59552).
+char(5,59553).
+char(7,59554).
+char(c,59555).
+char(p,59556).
+char(o,59557).
+char(m,59558).
+char(o,59559).
+char(p,59560).
+char(o,59561).
+char(o,59562).
+char(p,59563).
+char(o,59564).
+char(3,59565).
+char(1,59566).
+char(8,59567).
+char(2,59568).
+char(m,59569).
+char(o,59570).
+char(m,59571).
+char(o,59572).
+char(m,59573).
+char(5,59574).
+char(6,59575).
+char(p,59576).
+char(2,59577).
+char(2,59578).
+char(2,59579).
+char(9,59580).
+char(c,59581).
+char(m,59582).
+char(9,59583).
+char(8,59584).
+char(3,59585).
+char(8,59586).
+char(m,59587).
+char(o,59588).
+char(m,59589).
+char(7,59590).
+char(2,59591).
+char(2,59592).
+char(1,59593).
+char(p,59594).
+char(o,59595).
+char(m,59596).
+char(7,59597).
+char(1,59598).
+char(9,59599).
+char(0,59600).
+char(c,59601).
+char(c,59602).
+char(m,59603).
+char(o,59604).
+char(9,59605).
+char(7,59606).
+char(5,59607).
+char(0,59608).
+char(c,59609).
+char(m,59610).
+char(5,59611).
+char(0,59612).
+char(3,59613).
+char(9,59614).
+char(c,59615).
+char(m,59616).
+char(4,59617).
+char(0,59618).
+char(1,59619).
+char(3,59620).
+char(p,59621).
+char(4,59622).
+char(1,59623).
+char(3,59624).
+char(1,59625).
+char(m,59626).
+char(7,59627).
+char(6,59628).
+char(3,59629).
+char(7,59630).
+char(m,59631).
+char(o,59632).
+char(m,59633).
+char(8,59634).
+char(7,59635).
+char(2,59636).
+char(7,59637).
+char(c,59638).
+char(c,59639).
+char(c,59640).
+char(c,59641).
+char(c,59642).
+char(p,59643).
+char(4,59644).
+char(5,59645).
+char(7,59646).
+char(5,59647).
+char(c,59648).
+char(c,59649).
+char(c,59650).
+char(c,59651).
+char(c,59652).
+char(p,59653).
+char(3,59654).
+char(0,59655).
+char(2,59656).
+char(6,59657).
+char(c,59658).
+char(c,59659).
+char(m,59660).
+char(o,59661).
+char(4,59662).
+char(0,59663).
+char(7,59664).
+char(3,59665).
+char(p,59666).
+char(o,59667).
+char(m,59668).
+char(3,59669).
+char(8,59670).
+char(1,59671).
+char(6,59672).
+char(m,59673).
+char(o,59674).
+char(m,59675).
+char(o,59676).
+char(m,59677).
+char(o,59678).
+char(p,59679).
+char(o,59680).
+char(6,59681).
+char(4,59682).
+char(0,59683).
+char(1,59684).
+char(p,59685).
+char(5,59686).
+char(6,59687).
+char(2,59688).
+char(6,59689).
+char(c,59690).
+char(c,59691).
+char(p,59692).
+char(o,59693).
+char(p,59694).
+char(o,59695).
+char(p,59696).
+char(o,59697).
+char(m,59698).
+char(5,59699).
+char(2,59700).
+char(3,59701).
+char(0,59702).
+char(p,59703).
+char(7,59704).
+char(7,59705).
+char(7,59706).
+char(0,59707).
+char(c,59708).
+char(p,59709).
+char(o,59710).
+char(p,59711).
+char(o,59712).
+char(m,59713).
+char(9,59714).
+char(9,59715).
+char(3,59716).
+char(6,59717).
+char(m,59718).
+char(2,59719).
+char(3,59720).
+char(1,59721).
+char(3,59722).
+char(p,59723).
+char(6,59724).
+char(7,59725).
+char(6,59726).
+char(8,59727).
+char(m,59728).
+char(9,59729).
+char(8,59730).
+char(2,59731).
+char(1,59732).
+char(p,59733).
+char(7,59734).
+char(9,59735).
+char(6,59736).
+char(8,59737).
+char(p,59738).
+char(3,59739).
+char(8,59740).
+char(7,59741).
+char(2,59742).
+char(c,59743).
+char(p,59744).
+char(o,59745).
+char(p,59746).
+char(8,59747).
+char(6,59748).
+char(6,59749).
+char(2,59750).
+char(p,59751).
+char(o,59752).
+char(p,59753).
+char(4,59754).
+char(0,59755).
+char(2,59756).
+char(5,59757).
+char(p,59758).
+char(o,59759).
+char(m,59760).
+char(o,59761).
+char(m,59762).
+char(o,59763).
+char(m,59764).
+char(6,59765).
+char(8,59766).
+char(7,59767).
+char(p,59768).
+char(o,59769).
+char(o,59770).
+char(m,59771).
+char(4,59772).
+char(8,59773).
+char(8,59774).
+char(0,59775).
+char(m,59776).
+char(7,59777).
+char(9,59778).
+char(9,59779).
+char(9,59780).
+char(m,59781).
+char(o,59782).
+char(m,59783).
+char(o,59784).
+char(p,59785).
+char(4,59786).
+char(3,59787).
+char(6,59788).
+char(5,59789).
+char(c,59790).
+char(c,59791).
+char(c,59792).
+char(m,59793).
+char(o,59794).
+char(m,59795).
+char(5,59796).
+char(9,59797).
+char(3,59798).
+char(7,59799).
+char(p,59800).
+char(4,59801).
+char(7,59802).
+char(4,59803).
+char(8,59804).
+char(m,59805).
+char(1,59806).
+char(4,59807).
+char(1,59808).
+char(5,59809).
+char(m,59810).
+char(3,59811).
+char(0,59812).
+char(6,59813).
+char(4,59814).
+char(c,59815).
+char(c,59816).
+char(m,59817).
+char(o,59818).
+char(p,59819).
+char(o,59820).
+char(m,59821).
+char(o,59822).
+char(o,59823).
+char(m,59824).
+char(o,59825).
+char(m,59826).
+char(o,59827).
+char(p,59828).
+char(1,59829).
+char(4,59830).
+char(6,59831).
+char(5,59832).
+char(c,59833).
+char(c,59834).
+char(m,59835).
+char(1,59836).
+char(5,59837).
+char(3,59838).
+char(9,59839).
+char(c,59840).
+char(m,59841).
+char(o,59842).
+char(p,59843).
+char(o,59844).
+char(m,59845).
+char(7,59846).
+char(2,59847).
+char(7,59848).
+char(1,59849).
+char(m,59850).
+char(4,59851).
+char(9,59852).
+char(8,59853).
+char(7,59854).
+char(c,59855).
+char(c,59856).
+char(m,59857).
+char(9,59858).
+char(3,59859).
+char(7,59860).
+char(2,59861).
+char(p,59862).
+char(o,59863).
+char(p,59864).
+char(o,59865).
+char(m,59866).
+char(o,59867).
+char(2,59868).
+char(3,59869).
+char(1,59870).
+char(8,59871).
+char(p,59872).
+char(o,59873).
+char(4,59874).
+char(5,59875).
+char(3,59876).
+char(3,59877).
+char(m,59878).
+char(1,59879).
+char(6,59880).
+char(7,59881).
+char(6,59882).
+char(m,59883).
+char(2,59884).
+char(5,59885).
+char(0,59886).
+char(9,59887).
+char(p,59888).
+char(7,59889).
+char(8,59890).
+char(5,59891).
+char(1,59892).
+char(p,59893).
+char(o,59894).
+char(p,59895).
+char(o,59896).
+char(m,59897).
+char(9,59898).
+char(2,59899).
+char(7,59900).
+char(c,59901).
+char(c,59902).
+char(p,59903).
+char(o,59904).
+char(8,59905).
+char(3,59906).
+char(1,59907).
+char(6,59908).
+char(m,59909).
+char(2,59910).
+char(5,59911).
+char(1,59912).
+char(7,59913).
+char(p,59914).
+char(9,59915).
+char(0,59916).
+char(3,59917).
+char(8,59918).
+char(c,59919).
+char(c,59920).
+char(c,59921).
+char(c,59922).
+char(c,59923).
+char(c,59924).
+char(p,59925).
+char(6,59926).
+char(8,59927).
+char(0,59928).
+char(5,59929).
+char(m,59930).
+char(o,59931).
+char(m,59932).
+char(o,59933).
+char(p,59934).
+char(o,59935).
+char(p,59936).
+char(o,59937).
+char(p,59938).
+char(o,59939).
+char(5,59940).
+char(2,59941).
+char(8,59942).
+char(9,59943).
+char(c,59944).
+char(c,59945).
+char(m,59946).
+char(5,59947).
+char(9,59948).
+char(8,59949).
+char(8,59950).
+char(c,59951).
+char(c,59952).
+char(c,59953).
+char(p,59954).
+char(1,59955).
+char(1,59956).
+char(4,59957).
+char(c,59958).
+char(m,59959).
+char(o,59960).
+char(p,59961).
+char(o,59962).
+char(m,59963).
+char(1,59964).
+char(6,59965).
+char(2,59966).
+char(3,59967).
+char(m,59968).
+char(o,59969).
+char(o,59970).
+char(m,59971).
+char(4,59972).
+char(6,59973).
+char(7,59974).
+char(c,59975).
+char(c,59976).
+char(c,59977).
+char(p,59978).
+char(1,59979).
+char(9,59980).
+char(5,59981).
+char(1,59982).
+char(c,59983).
+char(m,59984).
+char(o,59985).
+char(5,59986).
+char(1,59987).
+char(7,59988).
+char(0,59989).
+char(c,59990).
+char(c,59991).
+char(p,59992).
+char(o,59993).
+char(m,59994).
+char(o,59995).
+char(m,59996).
+char(o,59997).
+char(o,59998).
+char(o,59999).
+char(m,60000).
+char(o,60001).
+char(o,60002).
+char(p,60003).
+char(5,60004).
+char(7,60005).
+char(4,60006).
+char(0,60007).
+char(p,60008).
+char(8,60009).
+char(7,60010).
+char(5,60011).
+char(4,60012).
+char(c,60013).
+char(p,60014).
+char(6,60015).
+char(3,60016).
+char(9,60017).
+char(0,60018).
+char(p,60019).
+char(5,60020).
+char(5,60021).
+char(8,60022).
+char(7,60023).
+char(p,60024).
+char(o,60025).
+char(m,60026).
+char(4,60027).
+char(0,60028).
+char(7,60029).
+char(7,60030).
+char(m,60031).
+char(5,60032).
+char(8,60033).
+char(3,60034).
+char(7,60035).
+char(p,60036).
+char(6,60037).
+char(1,60038).
+char(8,60039).
+char(7,60040).
+char(p,60041).
+char(o,60042).
+char(m,60043).
+char(o,60044).
+char(m,60045).
+char(1,60046).
+char(3,60047).
+char(9,60048).
+char(4,60049).
+char(c,60050).
+char(c,60051).
+char(p,60052).
+char(o,60053).
+char(o,60054).
+char(p,60055).
+char(o,60056).
+char(m,60057).
+char(7,60058).
+char(0,60059).
+char(4,60060).
+char(0,60061).
+char(p,60062).
+char(1,60063).
+char(4,60064).
+char(3,60065).
+char(3,60066).
+char(m,60067).
+char(7,60068).
+char(2,60069).
+char(0,60070).
+char(8,60071).
+char(c,60072).
+char(c,60073).
+char(m,60074).
+char(8,60075).
+char(2,60076).
+char(0,60077).
+char(c,60078).
+char(p,60079).
+char(4,60080).
+char(0,60081).
+char(4,60082).
+char(6,60083).
+char(m,60084).
+char(o,60085).
+char(p,60086).
+char(3,60087).
+char(8,60088).
+char(5,60089).
+char(6,60090).
+char(m,60091).
+char(8,60092).
+char(7,60093).
+char(9,60094).
+char(2,60095).
+char(c,60096).
+char(c,60097).
+char(c,60098).
+char(c,60099).
+char(c,60100).
+char(p,60101).
+char(o,60102).
+char(p,60103).
+char(o,60104).
+char(m,60105).
+char(o,60106).
+char(p,60107).
+char(3,60108).
+char(9,60109).
+char(0,60110).
+char(8,60111).
+char(m,60112).
+char(2,60113).
+char(8,60114).
+char(3,60115).
+char(5,60116).
+char(p,60117).
+char(2,60118).
+char(9,60119).
+char(2,60120).
+char(2,60121).
+char(c,60122).
+char(p,60123).
+char(6,60124).
+char(0,60125).
+char(5,60126).
+char(c,60127).
+char(c,60128).
+char(c,60129).
+char(c,60130).
+char(p,60131).
+char(5,60132).
+char(9,60133).
+char(5,60134).
+char(8,60135).
+char(p,60136).
+char(o,60137).
+char(m,60138).
+char(6,60139).
+char(8,60140).
+char(3,60141).
+char(0,60142).
+char(m,60143).
+char(7,60144).
+char(4,60145).
+char(9,60146).
+char(p,60147).
+char(5,60148).
+char(0,60149).
+char(5,60150).
+char(1,60151).
+char(m,60152).
+char(o,60153).
+char(p,60154).
+char(o,60155).
+char(p,60156).
+char(5,60157).
+char(3,60158).
+char(3,60159).
+char(8,60160).
+char(c,60161).
+char(c,60162).
+char(m,60163).
+char(o,60164).
+char(m,60165).
+char(o,60166).
+char(o,60167).
+char(o,60168).
+char(m,60169).
+char(2,60170).
+char(6,60171).
+char(4,60172).
+char(7,60173).
+char(c,60174).
+char(c,60175).
+char(p,60176).
+char(7,60177).
+char(2,60178).
+char(3,60179).
+char(c,60180).
+char(m,60181).
+char(o,60182).
+char(8,60183).
+char(4,60184).
+char(7,60185).
+char(3,60186).
+char(p,60187).
+char(o,60188).
+char(5,60189).
+char(3,60190).
+char(7,60191).
+char(0,60192).
+char(m,60193).
+char(o,60194).
+char(p,60195).
+char(9,60196).
+char(7,60197).
+char(3,60198).
+char(0,60199).
+char(c,60200).
+char(c,60201).
+char(p,60202).
+char(o,60203).
+char(p,60204).
+char(5,60205).
+char(7,60206).
+char(8,60207).
+char(6,60208).
+char(p,60209).
+char(o,60210).
+char(o,60211).
+char(p,60212).
+char(9,60213).
+char(9,60214).
+char(7,60215).
+char(0,60216).
+char(c,60217).
+char(c,60218).
+char(m,60219).
+char(o,60220).
+char(p,60221).
+char(9,60222).
+char(8,60223).
+char(4,60224).
+char(m,60225).
+char(o,60226).
+char(m,60227).
+char(o,60228).
+char(o,60229).
+char(p,60230).
+char(8,60231).
+char(2,60232).
+char(8,60233).
+char(9,60234).
+char(c,60235).
+char(c,60236).
+char(c,60237).
+char(m,60238).
+char(o,60239).
+char(o,60240).
+char(m,60241).
+char(o,60242).
+char(p,60243).
+char(o,60244).
+char(o,60245).
+char(p,60246).
+char(2,60247).
+char(7,60248).
+char(4,60249).
+char(3,60250).
+char(m,60251).
+char(o,60252).
+char(m,60253).
+char(o,60254).
+char(m,60255).
+char(o,60256).
+char(p,60257).
+char(o,60258).
+char(1,60259).
+char(8,60260).
+char(3,60261).
+char(0,60262).
+char(c,60263).
+char(c,60264).
+char(p,60265).
+char(o,60266).
+char(p,60267).
+char(4,60268).
+char(2,60269).
+char(1,60270).
+char(2,60271).
+char(c,60272).
+char(c,60273).
+char(m,60274).
+char(o,60275).
+char(p,60276).
+char(3,60277).
+char(4,60278).
+char(5,60279).
+char(9,60280).
+char(m,60281).
+char(3,60282).
+char(0,60283).
+char(5,60284).
+char(0,60285).
+char(m,60286).
+char(o,60287).
+char(p,60288).
+char(o,60289).
+char(m,60290).
+char(o,60291).
+char(m,60292).
+char(o,60293).
+char(m,60294).
+char(o,60295).
+char(o,60296).
+char(p,60297).
+char(5,60298).
+char(2,60299).
+char(9,60300).
+char(8,60301).
+char(p,60302).
+char(6,60303).
+char(4,60304).
+char(7,60305).
+char(4,60306).
+char(m,60307).
+char(3,60308).
+char(0,60309).
+char(4,60310).
+char(4,60311).
+char(m,60312).
+char(o,60313).
+char(m,60314).
+char(o,60315).
+char(p,60316).
+char(6,60317).
+char(6,60318).
+char(3,60319).
+char(6,60320).
+char(p,60321).
+char(8,60322).
+char(8,60323).
+char(9,60324).
+char(p,60325).
+char(4,60326).
+char(0,60327).
+char(1,60328).
+char(8,60329).
+char(m,60330).
+char(5,60331).
+char(4,60332).
+char(6,60333).
+char(4,60334).
+char(c,60335).
+char(c,60336).
+char(c,60337).
+char(c,60338).
+char(c,60339).
+char(c,60340).
+char(c,60341).
+char(c,60342).
+char(c,60343).
+char(p,60344).
+char(o,60345).
+char(p,60346).
+char(o,60347).
+char(m,60348).
+char(o,60349).
+char(m,60350).
+char(8,60351).
+char(9,60352).
+char(0,60353).
+char(6,60354).
+char(m,60355).
+char(3,60356).
+char(4,60357).
+char(2,60358).
+char(4,60359).
+char(c,60360).
+char(m,60361).
+char(o,60362).
+char(p,60363).
+char(o,60364).
+char(m,60365).
+char(o,60366).
+char(m,60367).
+char(o,60368).
+char(m,60369).
+char(3,60370).
+char(9,60371).
+char(7,60372).
+char(0,60373).
+char(c,60374).
+char(c,60375).
+char(c,60376).
+char(p,60377).
+char(6,60378).
+char(0,60379).
+char(8,60380).
+char(1,60381).
+char(c,60382).
+char(p,60383).
+char(9,60384).
+char(8,60385).
+char(5,60386).
+char(5,60387).
+char(c,60388).
+char(c,60389).
+char(c,60390).
+char(c,60391).
+char(c,60392).
+char(c,60393).
+char(c,60394).
+char(c,60395).
+char(p,60396).
+char(o,60397).
+char(m,60398).
+char(4,60399).
+char(8,60400).
+char(5,60401).
+char(5,60402).
+char(p,60403).
+char(o,60404).
+char(p,60405).
+char(o,60406).
+char(m,60407).
+char(2,60408).
+char(6,60409).
+char(6,60410).
+char(m,60411).
+char(o,60412).
+char(p,60413).
+char(o,60414).
+char(p,60415).
+char(7,60416).
+char(4,60417).
+char(2,60418).
+char(1,60419).
+char(p,60420).
+char(2,60421).
+char(3,60422).
+char(1,60423).
+char(4,60424).
+char(m,60425).
+char(o,60426).
+char(p,60427).
+char(o,60428).
+char(m,60429).
+char(o,60430).
+char(p,60431).
+char(o,60432).
+char(p,60433).
+char(o,60434).
+char(m,60435).
+char(o,60436).
+char(m,60437).
+char(o,60438).
+char(p,60439).
+char(o,60440).
+char(o,60441).
+char(o,60442).
+char(o,60443).
+char(3,60444).
+char(3,60445).
+char(8,60446).
+char(0,60447).
+char(m,60448).
+char(2,60449).
+char(9,60450).
+char(9,60451).
+char(8,60452).
+char(c,60453).
+char(c,60454).
+char(p,60455).
+char(1,60456).
+char(7,60457).
+char(8,60458).
+char(7,60459).
+char(c,60460).
+char(p,60461).
+char(5,60462).
+char(5,60463).
+char(5,60464).
+char(2,60465).
+char(m,60466).
+char(o,60467).
+char(p,60468).
+char(o,60469).
+char(o,60470).
+char(o,60471).
+char(p,60472).
+char(o,60473).
+char(p,60474).
+char(8,60475).
+char(3,60476).
+char(3,60477).
+char(7,60478).
+char(c,60479).
+char(m,60480).
+char(1,60481).
+char(4,60482).
+char(8,60483).
+char(4,60484).
+char(m,60485).
+char(8,60486).
+char(1,60487).
+char(7,60488).
+char(7,60489).
+char(c,60490).
+char(c,60491).
+char(p,60492).
+char(7,60493).
+char(2,60494).
+char(0,60495).
+char(7,60496).
+char(m,60497).
+char(o,60498).
+char(m,60499).
+char(o,60500).
+char(m,60501).
+char(o,60502).
+char(6,60503).
+char(3,60504).
+char(9,60505).
+char(6,60506).
+char(c,60507).
+char(m,60508).
+char(2,60509).
+char(4,60510).
+char(9,60511).
+char(0,60512).
+char(p,60513).
+char(2,60514).
+char(8,60515).
+char(7,60516).
+char(5,60517).
+char(p,60518).
+char(o,60519).
+char(p,60520).
+char(o,60521).
+char(p,60522).
+char(6,60523).
+char(3,60524).
+char(5,60525).
+char(p,60526).
+char(1,60527).
+char(2,60528).
+char(3,60529).
+char(6,60530).
+char(c,60531).
+char(m,60532).
+char(o,60533).
+char(p,60534).
+char(5,60535).
+char(2,60536).
+char(6,60537).
+char(3,60538).
+char(c,60539).
+char(p,60540).
+char(o,60541).
+char(m,60542).
+char(o,60543).
+char(m,60544).
+char(o,60545).
+char(m,60546).
+char(o,60547).
+char(p,60548).
+char(o,60549).
+char(m,60550).
+char(o,60551).
+char(1,60552).
+char(1,60553).
+char(3,60554).
+char(2,60555).
+char(m,60556).
+char(o,60557).
+char(p,60558).
+char(o,60559).
+char(p,60560).
+char(o,60561).
+char(o,60562).
+char(m,60563).
+char(1,60564).
+char(p,60565).
+char(9,60566).
+char(3,60567).
+char(4,60568).
+char(8,60569).
+char(p,60570).
+char(2,60571).
+char(3,60572).
+char(8,60573).
+char(0,60574).
+char(m,60575).
+char(6,60576).
+char(8,60577).
+char(0,60578).
+char(3,60579).
+char(p,60580).
+char(6,60581).
+char(8,60582).
+char(5,60583).
+char(9,60584).
+char(c,60585).
+char(p,60586).
+char(o,60587).
+char(m,60588).
+char(o,60589).
+char(7,60590).
+char(9,60591).
+char(6,60592).
+char(8,60593).
+char(c,60594).
+char(c,60595).
+char(c,60596).
+char(c,60597).
+char(m,60598).
+char(5,60599).
+char(2,60600).
+char(9,60601).
+char(9,60602).
+char(c,60603).
+char(p,60604).
+char(o,60605).
+char(p,60606).
+char(6,60607).
+char(2,60608).
+char(5,60609).
+char(4,60610).
+char(m,60611).
+char(4,60612).
+char(9,60613).
+char(5,60614).
+char(8,60615).
+char(c,60616).
+char(c,60617).
+char(c,60618).
+char(c,60619).
+char(c,60620).
+char(m,60621).
+char(o,60622).
+char(o,60623).
+char(6,60624).
+char(5,60625).
+char(4,60626).
+char(6,60627).
+char(c,60628).
+char(m,60629).
+char(5,60630).
+char(7,60631).
+char(6,60632).
+char(m,60633).
+char(8,60634).
+char(0,60635).
+char(2,60636).
+char(0,60637).
+char(c,60638).
+char(m,60639).
+char(1,60640).
+char(9,60641).
+char(2,60642).
+char(8,60643).
+char(c,60644).
+char(m,60645).
+char(o,60646).
+char(2,60647).
+char(1,60648).
+char(3,60649).
+char(0,60650).
+char(c,60651).
+char(m,60652).
+char(o,60653).
+char(m,60654).
+char(4,60655).
+char(1,60656).
+char(0,60657).
+char(6,60658).
+char(m,60659).
+char(o,60660).
+char(m,60661).
+char(3,60662).
+char(9,60663).
+char(1,60664).
+char(5,60665).
+char(c,60666).
+char(m,60667).
+char(7,60668).
+char(7,60669).
+char(1,60670).
+char(0,60671).
+char(c,60672).
+char(c,60673).
+char(c,60674).
+char(p,60675).
+char(o,60676).
+char(m,60677).
+char(o,60678).
+char(p,60679).
+char(2,60680).
+char(8,60681).
+char(2,60682).
+char(3,60683).
+char(p,60684).
+char(o,60685).
+char(p,60686).
+char(3,60687).
+char(1,60688).
+char(1,60689).
+char(9,60690).
+char(p,60691).
+char(o,60692).
+char(7,60693).
+char(1,60694).
+char(7,60695).
+char(0,60696).
+char(c,60697).
+char(c,60698).
+char(p,60699).
+char(o,60700).
+char(o,60701).
+char(m,60702).
+char(o,60703).
+char(m,60704).
+char(o,60705).
+char(m,60706).
+char(o,60707).
+char(m,60708).
+char(9,60709).
+char(0,60710).
+char(6,60711).
+char(4,60712).
+char(m,60713).
+char(o,60714).
+char(7,60715).
+char(5,60716).
+char(7,60717).
+char(9,60718).
+char(c,60719).
+char(c,60720).
+char(c,60721).
+char(c,60722).
+char(c,60723).
+char(c,60724).
+char(c,60725).
+char(m,60726).
+char(7,60727).
+char(9,60728).
+char(5,60729).
+char(7,60730).
+char(c,60731).
+char(c,60732).
+char(m,60733).
+char(o,60734).
+char(p,60735).
+char(1,60736).
+char(9,60737).
+char(3,60738).
+char(9,60739).
+char(c,60740).
+char(m,60741).
+char(o,60742).
+char(p,60743).
+char(6,60744).
+char(6,60745).
+char(2,60746).
+char(2,60747).
+char(c,60748).
+char(c,60749).
+char(c,60750).
+char(m,60751).
+char(8,60752).
+char(7,60753).
+char(7,60754).
+char(9,60755).
+char(c,60756).
+char(c,60757).
+char(c,60758).
+char(p,60759).
+char(o,60760).
+char(p,60761).
+char(9,60762).
+char(2,60763).
+char(7,60764).
+char(8,60765).
+char(p,60766).
+char(9,60767).
+char(3,60768).
+char(8,60769).
+char(2,60770).
+char(c,60771).
+char(p,60772).
+char(o,60773).
+char(p,60774).
+char(o,60775).
+char(o,60776).
+char(p,60777).
+char(7,60778).
+char(3,60779).
+char(9,60780).
+char(5,60781).
+char(c,60782).
+char(p,60783).
+char(4,60784).
+char(7,60785).
+char(3,60786).
+char(4,60787).
+char(p,60788).
+char(9,60789).
+char(5,60790).
+char(5,60791).
+char(5,60792).
+char(p,60793).
+char(5,60794).
+char(7,60795).
+char(7,60796).
+char(5,60797).
+char(c,60798).
+char(p,60799).
+char(o,60800).
+char(4,60801).
+char(8,60802).
+char(5,60803).
+char(c,60804).
+char(m,60805).
+char(o,60806).
+char(p,60807).
+char(o,60808).
+char(p,60809).
+char(1,60810).
+char(1,60811).
+char(8,60812).
+char(1,60813).
+char(m,60814).
+char(1,60815).
+char(4,60816).
+char(8,60817).
+char(6,60818).
+char(c,60819).
+char(c,60820).
+char(p,60821).
+char(9,60822).
+char(5,60823).
+char(6,60824).
+char(2,60825).
+char(c,60826).
+char(c,60827).
+char(c,60828).
+char(c,60829).
+char(p,60830).
+char(6,60831).
+char(7,60832).
+char(8,60833).
+char(0,60834).
+char(c,60835).
+char(m,60836).
+char(4,60837).
+char(6,60838).
+char(7,60839).
+char(4,60840).
+char(c,60841).
+char(c,60842).
+char(c,60843).
+char(m,60844).
+char(1,60845).
+char(5,60846).
+char(2,60847).
+char(7,60848).
+char(p,60849).
+char(o,60850).
+char(o,60851).
+char(m,60852).
+char(o,60853).
+char(o,60854).
+char(m,60855).
+char(8,60856).
+char(7,60857).
+char(6,60858).
+char(8,60859).
+char(c,60860).
+char(c,60861).
+char(c,60862).
+char(c,60863).
+char(c,60864).
+char(c,60865).
+char(m,60866).
+char(3,60867).
+char(1,60868).
+char(3,60869).
+char(3,60870).
+char(m,60871).
+char(9,60872).
+char(0,60873).
+char(2,60874).
+char(1,60875).
+char(p,60876).
+char(1,60877).
+char(5,60878).
+char(6,60879).
+char(2,60880).
+char(p,60881).
+char(o,60882).
+char(8,60883).
+char(7,60884).
+char(5,60885).
+char(0,60886).
+char(c,60887).
+char(p,60888).
+char(o,60889).
+char(m,60890).
+char(o,60891).
+char(m,60892).
+char(7,60893).
+char(0,60894).
+char(2,60895).
+char(c,60896).
+char(p,60897).
+char(o,60898).
+char(7,60899).
+char(6,60900).
+char(1,60901).
+char(3,60902).
+char(p,60903).
+char(9,60904).
+char(4,60905).
+char(6,60906).
+char(2,60907).
+char(c,60908).
+char(c,60909).
+char(m,60910).
+char(1,60911).
+char(1,60912).
+char(4,60913).
+char(9,60914).
+char(c,60915).
+char(m,60916).
+char(o,60917).
+char(p,60918).
+char(7,60919).
+char(4,60920).
+char(9,60921).
+char(6,60922).
+char(p,60923).
+char(4,60924).
+char(3,60925).
+char(3,60926).
+char(7,60927).
+char(m,60928).
+char(8,60929).
+char(7,60930).
+char(0,60931).
+char(2,60932).
+char(c,60933).
+char(c,60934).
+char(p,60935).
+char(7,60936).
+char(8,60937).
+char(5,60938).
+char(1,60939).
+char(p,60940).
+char(o,60941).
+char(m,60942).
+char(o,60943).
+char(o,60944).
+char(p,60945).
+char(o,60946).
+char(m,60947).
+char(o,60948).
+char(m,60949).
+char(1,60950).
+char(6,60951).
+char(4,60952).
+char(1,60953).
+char(c,60954).
+char(p,60955).
+char(5,60956).
+char(7,60957).
+char(9,60958).
+char(3,60959).
+char(c,60960).
+char(m,60961).
+char(3,60962).
+char(6,60963).
+char(1,60964).
+char(0,60965).
+char(c,60966).
+char(p,60967).
+char(o,60968).
+char(o,60969).
+char(m,60970).
+char(9,60971).
+char(4,60972).
+char(7,60973).
+char(0,60974).
+char(m,60975).
+char(o,60976).
+char(p,60977).
+char(4,60978).
+char(8,60979).
+char(2,60980).
+char(c,60981).
+char(p,60982).
+char(7,60983).
+char(5,60984).
+char(9,60985).
+char(0,60986).
+char(m,60987).
+char(o,60988).
+char(m,60989).
+char(7,60990).
+char(9,60991).
+char(3,60992).
+char(6,60993).
+char(m,60994).
+char(o,60995).
+char(5,60996).
+char(5,60997).
+char(4,60998).
+char(2,60999).
+char(m,61000).
+char(7,61001).
+char(8,61002).
+char(1,61003).
+char(8,61004).
+char(c,61005).
+char(c,61006).
+char(p,61007).
+char(7,61008).
+char(5,61009).
+char(3,61010).
+char(3,61011).
+char(c,61012).
+char(c,61013).
+char(c,61014).
+char(p,61015).
+char(1,61016).
+char(2,61017).
+char(9,61018).
+char(1,61019).
+char(p,61020).
+char(o,61021).
+char(o,61022).
+char(p,61023).
+char(o,61024).
+char(m,61025).
+char(o,61026).
+char(p,61027).
+char(1,61028).
+char(7,61029).
+char(0,61030).
+char(6,61031).
+char(c,61032).
+char(m,61033).
+char(o,61034).
+char(o,61035).
+char(o,61036).
+char(m,61037).
+char(o,61038).
+char(p,61039).
+char(o,61040).
+char(m,61041).
+char(o,61042).
+char(p,61043).
+char(7,61044).
+char(3,61045).
+char(7,61046).
+char(c,61047).
+char(p,61048).
+char(o,61049).
+char(p,61050).
+char(o,61051).
+char(p,61052).
+char(o,61053).
+char(o,61054).
+char(p,61055).
+char(1,61056).
+char(5,61057).
+char(8,61058).
+char(2,61059).
+char(m,61060).
+char(o,61061).
+char(6,61062).
+char(7,61063).
+char(2,61064).
+char(1,61065).
+char(c,61066).
+char(c,61067).
+char(m,61068).
+char(8,61069).
+char(5,61070).
+char(1,61071).
+char(6,61072).
+char(p,61073).
+char(o,61074).
+char(p,61075).
+char(o,61076).
+char(9,61077).
+char(9,61078).
+char(9,61079).
+char(6,61080).
+char(m,61081).
+char(o,61082).
+char(p,61083).
+char(o,61084).
+char(p,61085).
+char(o,61086).
+char(p,61087).
+char(o,61088).
+char(p,61089).
+char(o,61090).
+char(p,61091).
+char(2,61092).
+char(6,61093).
+char(6,61094).
+char(c,61095).
+char(m,61096).
+char(1,61097).
+char(4,61098).
+char(3,61099).
+char(c,61100).
+char(c,61101).
+char(c,61102).
+char(m,61103).
+char(5,61104).
+char(0,61105).
+char(0,61106).
+char(1,61107).
+char(m,61108).
+char(o,61109).
+char(2,61110).
+char(3,61111).
+char(5,61112).
+char(9,61113).
+char(m,61114).
+char(3,61115).
+char(1,61116).
+char(9,61117).
+char(m,61118).
+char(3,61119).
+char(8,61120).
+char(c,61121).
+char(c,61122).
+char(m,61123).
+char(8,61124).
+char(9,61125).
+char(7,61126).
+char(4,61127).
+char(m,61128).
+char(o,61129).
+char(p,61130).
+char(o,61131).
+char(o,61132).
+char(p,61133).
+char(o,61134).
+char(o,61135).
+char(o,61136).
+char(p,61137).
+char(o,61138).
+char(p,61139).
+char(o,61140).
+char(o,61141).
+char(m,61142).
+char(3,61143).
+char(4,61144).
+char(1,61145).
+char(5,61146).
+char(c,61147).
+char(m,61148).
+char(o,61149).
+char(p,61150).
+char(o,61151).
+char(p,61152).
+char(o,61153).
+char(o,61154).
+char(o,61155).
+char(m,61156).
+char(o,61157).
+char(p,61158).
+char(7,61159).
+char(0,61160).
+char(6,61161).
+char(m,61162).
+char(7,61163).
+char(1,61164).
+char(0,61165).
+char(7,61166).
+char(m,61167).
+char(o,61168).
+char(o,61169).
+char(m,61170).
+char(o,61171).
+char(1,61172).
+char(7,61173).
+char(9,61174).
+char(9,61175).
+char(c,61176).
+char(c,61177).
+char(p,61178).
+char(8,61179).
+char(0,61180).
+char(3,61181).
+char(7,61182).
+char(m,61183).
+char(6,61184).
+char(6,61185).
+char(8,61186).
+char(1,61187).
+char(c,61188).
+char(c,61189).
+char(p,61190).
+char(o,61191).
+char(m,61192).
+char(o,61193).
+char(o,61194).
+char(p,61195).
+char(o,61196).
+char(p,61197).
+char(o,61198).
+char(p,61199).
+char(6,61200).
+char(0,61201).
+char(5,61202).
+char(8,61203).
+char(p,61204).
+char(o,61205).
+char(o,61206).
+char(m,61207).
+char(o,61208).
+char(p,61209).
+char(5,61210).
+char(1,61211).
+char(7,61212).
+char(9,61213).
+char(p,61214).
+char(8,61215).
+char(5,61216).
+char(9,61217).
+char(0,61218).
+char(c,61219).
+char(c,61220).
+char(m,61221).
+char(2,61222).
+char(3,61223).
+char(8,61224).
+char(2,61225).
+char(m,61226).
+char(o,61227).
+char(6,61228).
+char(6,61229).
+char(4,61230).
+char(7,61231).
+char(c,61232).
+char(c,61233).
+char(c,61234).
+char(m,61235).
+char(o,61236).
+char(m,61237).
+char(o,61238).
+char(m,61239).
+char(o,61240).
+char(m,61241).
+char(4,61242).
+char(3,61243).
+char(8,61244).
+char(1,61245).
+char(c,61246).
+char(m,61247).
+char(9,61248).
+char(8,61249).
+char(3,61250).
+char(9,61251).
+char(m,61252).
+char(2,61253).
+char(0,61254).
+char(4,61255).
+char(1,61256).
+char(m,61257).
+char(8,61258).
+char(5,61259).
+char(4,61260).
+char(8,61261).
+char(c,61262).
+char(p,61263).
+char(5,61264).
+char(9,61265).
+char(3,61266).
+char(0,61267).
+char(m,61268).
+char(2,61269).
+char(9,61270).
+char(7,61271).
+char(7,61272).
+char(c,61273).
+char(m,61274).
+char(o,61275).
+char(o,61276).
+char(o,61277).
+char(m,61278).
+char(5,61279).
+char(3,61280).
+char(8,61281).
+char(7,61282).
+char(p,61283).
+char(o,61284).
+char(p,61285).
+char(8,61286).
+char(6,61287).
+char(2,61288).
+char(8,61289).
+char(p,61290).
+char(o,61291).
+char(m,61292).
+char(o,61293).
+char(o,61294).
+char(p,61295).
+char(o,61296).
+char(6,61297).
+char(8,61298).
+char(7,61299).
+char(1,61300).
+char(p,61301).
+char(8,61302).
+char(0,61303).
+char(1,61304).
+char(3,61305).
+char(c,61306).
+char(m,61307).
+char(o,61308).
+char(o,61309).
+char(p,61310).
+char(o,61311).
+char(o,61312).
+char(m,61313).
+char(2,61314).
+char(0,61315).
+char(1,61316).
+char(6,61317).
+char(c,61318).
+char(p,61319).
+char(9,61320).
+char(0,61321).
+char(1,61322).
+char(2,61323).
+char(c,61324).
+char(m,61325).
+char(1,61326).
+char(5,61327).
+char(8,61328).
+char(5,61329).
+char(c,61330).
+char(c,61331).
+char(c,61332).
+char(p,61333).
+char(4,61334).
+char(2,61335).
+char(6,61336).
+char(6,61337).
+char(c,61338).
+char(c,61339).
+char(c,61340).
+char(c,61341).
+char(c,61342).
+char(c,61343).
+char(c,61344).
+char(c,61345).
+char(c,61346).
+char(m,61347).
+char(9,61348).
+char(8,61349).
+char(1,61350).
+char(1,61351).
+char(p,61352).
+char(o,61353).
+char(p,61354).
+char(o,61355).
+char(p,61356).
+char(o,61357).
+char(p,61358).
+char(5,61359).
+char(8,61360).
+char(9,61361).
+char(6,61362).
+char(m,61363).
+char(o,61364).
+char(6,61365).
+char(6,61366).
+char(0,61367).
+char(m,61368).
+char(1,61369).
+char(7,61370).
+char(7,61371).
+char(4,61372).
+char(p,61373).
+char(o,61374).
+char(p,61375).
+char(1,61376).
+char(4,61377).
+char(2,61378).
+char(6,61379).
+char(c,61380).
+char(c,61381).
+char(m,61382).
+char(4,61383).
+char(1,61384).
+char(9,61385).
+char(1,61386).
+char(c,61387).
+char(m,61388).
+char(1,61389).
+char(6,61390).
+char(3,61391).
+char(8,61392).
+char(c,61393).
+char(m,61394).
+char(o,61395).
+char(o,61396).
+char(p,61397).
+char(1,61398).
+char(5,61399).
+char(9,61400).
+char(8,61401).
+char(c,61402).
+char(c,61403).
+char(m,61404).
+char(o,61405).
+char(p,61406).
+char(7,61407).
+char(3,61408).
+char(9,61409).
+char(0,61410).
+char(c,61411).
+char(m,61412).
+char(o,61413).
+char(p,61414).
+char(9,61415).
+char(3,61416).
+char(1,61417).
+char(1,61418).
+char(c,61419).
+char(c,61420).
+char(c,61421).
+char(m,61422).
+char(o,61423).
+char(p,61424).
+char(o,61425).
+char(m,61426).
+char(8,61427).
+char(7,61428).
+char(3,61429).
+char(8,61430).
+char(c,61431).
+char(c,61432).
+char(m,61433).
+char(o,61434).
+char(m,61435).
+char(o,61436).
+char(m,61437).
+char(o,61438).
+char(p,61439).
+char(1,61440).
+char(5,61441).
+char(0,61442).
+char(6,61443).
+char(m,61444).
+char(o,61445).
+char(p,61446).
+char(7,61447).
+char(7,61448).
+char(6,61449).
+char(6,61450).
+char(c,61451).
+char(p,61452).
+char(o,61453).
+char(o,61454).
+char(o,61455).
+char(p,61456).
+char(o,61457).
+char(o,61458).
+char(p,61459).
+char(o,61460).
+char(m,61461).
+char(5,61462).
+char(0,61463).
+char(2,61464).
+char(6,61465).
+char(c,61466).
+char(c,61467).
+char(m,61468).
+char(o,61469).
+char(m,61470).
+char(1,61471).
+char(6,61472).
+char(5,61473).
+char(3,61474).
+char(p,61475).
+char(4,61476).
+char(8,61477).
+char(4,61478).
+char(9,61479).
+char(c,61480).
+char(c,61481).
+char(c,61482).
+char(c,61483).
+char(p,61484).
+char(4,61485).
+char(6,61486).
+char(1,61487).
+char(2,61488).
+char(p,61489).
+char(6,61490).
+char(4,61491).
+char(6,61492).
+char(8,61493).
+char(m,61494).
+char(o,61495).
+char(p,61496).
+char(2,61497).
+char(0,61498).
+char(0,61499).
+char(6,61500).
+char(c,61501).
+char(c,61502).
+char(p,61503).
+char(o,61504).
+char(m,61505).
+char(8,61506).
+char(6,61507).
+char(0,61508).
+char(1,61509).
+char(c,61510).
+char(c,61511).
+char(c,61512).
+char(c,61513).
+char(c,61514).
+char(p,61515).
+char(o,61516).
+char(p,61517).
+char(4,61518).
+char(1,61519).
+char(9,61520).
+char(4,61521).
+char(c,61522).
+char(p,61523).
+char(o,61524).
+char(m,61525).
+char(1,61526).
+char(4,61527).
+char(5,61528).
+char(7,61529).
+char(c,61530).
+char(c,61531).
+char(c,61532).
+char(c,61533).
+char(p,61534).
+char(o,61535).
+char(p,61536).
+char(2,61537).
+char(5,61538).
+char(3,61539).
+char(2,61540).
+char(p,61541).
+char(7,61542).
+char(2,61543).
+char(8,61544).
+char(6,61545).
+char(p,61546).
+char(o,61547).
+char(m,61548).
+char(o,61549).
+char(p,61550).
+char(6,61551).
+char(0,61552).
+char(5,61553).
+char(2,61554).
+char(m,61555).
+char(o,61556).
+char(o,61557).
+char(8,61558).
+char(8,61559).
+char(8,61560).
+char(8,61561).
+char(p,61562).
+char(o,61563).
+char(o,61564).
+char(6,61565).
+char(2,61566).
+char(5,61567).
+char(3,61568).
+char(c,61569).
+char(m,61570).
+char(o,61571).
+char(p,61572).
+char(2,61573).
+char(0,61574).
+char(7,61575).
+char(9,61576).
+char(p,61577).
+char(4,61578).
+char(4,61579).
+char(2,61580).
+char(7,61581).
+char(c,61582).
+char(c,61583).
+char(c,61584).
+char(c,61585).
+char(p,61586).
+char(o,61587).
+char(p,61588).
+char(3,61589).
+char(7,61590).
+char(7,61591).
+char(9,61592).
+char(c,61593).
+char(c,61594).
+char(m,61595).
+char(6,61596).
+char(0,61597).
+char(8,61598).
+char(9,61599).
+char(c,61600).
+char(m,61601).
+char(5,61602).
+char(4,61603).
+char(2,61604).
+char(c,61605).
+char(m,61606).
+char(4,61607).
+char(8,61608).
+char(3,61609).
+char(2,61610).
+char(m,61611).
+char(o,61612).
+char(1,61613).
+char(0,61614).
+char(1,61615).
+char(3,61616).
+char(m,61617).
+char(9,61618).
+char(8,61619).
+char(1,61620).
+char(8,61621).
+char(c,61622).
+char(m,61623).
+char(9,61624).
+char(5,61625).
+char(1,61626).
+char(6,61627).
+char(m,61628).
+char(o,61629).
+char(o,61630).
+char(o,61631).
+char(p,61632).
+char(o,61633).
+char(o,61634).
+char(m,61635).
+char(8,61636).
+char(5,61637).
+char(1,61638).
+char(4,61639).
+char(c,61640).
+char(m,61641).
+char(o,61642).
+char(o,61643).
+char(m,61644).
+char(o,61645).
+char(p,61646).
+char(6,61647).
+char(9,61648).
+char(3,61649).
+char(1,61650).
+char(p,61651).
+char(6,61652).
+char(9,61653).
+char(8,61654).
+char(6,61655).
+char(c,61656).
+char(c,61657).
+char(m,61658).
+char(2,61659).
+char(6,61660).
+char(1,61661).
+char(2,61662).
+char(m,61663).
+char(8,61664).
+char(9,61665).
+char(2,61666).
+char(6,61667).
+char(p,61668).
+char(o,61669).
+char(p,61670).
+char(o,61671).
+char(p,61672).
+char(o,61673).
+char(m,61674).
+char(4,61675).
+char(8,61676).
+char(6,61677).
+char(9,61678).
+char(p,61679).
+char(o,61680).
+char(p,61681).
+char(o,61682).
+char(o,61683).
+char(m,61684).
+char(o,61685).
+char(p,61686).
+char(5,61687).
+char(0,61688).
+char(4,61689).
+char(3,61690).
+char(p,61691).
+char(7,61692).
+char(5,61693).
+char(3,61694).
+char(6,61695).
+char(m,61696).
+char(6,61697).
+char(2,61698).
+char(7,61699).
+char(7,61700).
+char(p,61701).
+char(o,61702).
+char(p,61703).
+char(o,61704).
+char(m,61705).
+char(o,61706).
+char(m,61707).
+char(o,61708).
+char(m,61709).
+char(o,61710).
+char(p,61711).
+char(o,61712).
+char(m,61713).
+char(o,61714).
+char(o,61715).
+char(p,61716).
+char(o,61717).
+char(p,61718).
+char(7,61719).
+char(4,61720).
+char(0,61721).
+char(8,61722).
+char(p,61723).
+char(4,61724).
+char(0,61725).
+char(8,61726).
+char(9,61727).
+char(c,61728).
+char(m,61729).
+char(3,61730).
+char(3,61731).
+char(8,61732).
+char(4,61733).
+char(p,61734).
+char(4,61735).
+char(7,61736).
+char(5,61737).
+char(7,61738).
+char(m,61739).
+char(9,61740).
+char(7,61741).
+char(0,61742).
+char(p,61743).
+char(o,61744).
+char(p,61745).
+char(8,61746).
+char(6,61747).
+char(3,61748).
+char(9,61749).
+char(c,61750).
+char(c,61751).
+char(c,61752).
+char(m,61753).
+char(o,61754).
+char(m,61755).
+char(1,61756).
+char(1,61757).
+char(0,61758).
+char(8,61759).
+char(c,61760).
+char(c,61761).
+char(c,61762).
+char(c,61763).
+char(c,61764).
+char(p,61765).
+char(o,61766).
+char(o,61767).
+char(m,61768).
+char(o,61769).
+char(m,61770).
+char(2,61771).
+char(7,61772).
+char(1,61773).
+char(3,61774).
+char(c,61775).
+char(p,61776).
+char(8,61777).
+char(9,61778).
+char(6,61779).
+char(3,61780).
+char(m,61781).
+char(5,61782).
+char(6,61783).
+char(1,61784).
+char(5,61785).
+char(m,61786).
+char(o,61787).
+char(4,61788).
+char(1,61789).
+char(1,61790).
+char(1,61791).
+char(p,61792).
+char(2,61793).
+char(7,61794).
+char(5,61795).
+char(1,61796).
+char(m,61797).
+char(9,61798).
+char(6,61799).
+char(2,61800).
+char(7,61801).
+char(m,61802).
+char(9,61803).
+char(3,61804).
+char(0,61805).
+char(2,61806).
+char(c,61807).
+char(p,61808).
+char(o,61809).
+char(o,61810).
+char(m,61811).
+char(2,61812).
+char(7,61813).
+char(p,61814).
+char(7,61815).
+char(2,61816).
+char(7,61817).
+char(0,61818).
+char(c,61819).
+char(p,61820).
+char(3,61821).
+char(9,61822).
+char(8,61823).
+char(9,61824).
+char(c,61825).
+char(c,61826).
+char(c,61827).
+char(m,61828).
+char(2,61829).
+char(8,61830).
+char(6,61831).
+char(2,61832).
+char(m,61833).
+char(o,61834).
+char(p,61835).
+char(o,61836).
+char(p,61837).
+char(8,61838).
+char(4,61839).
+char(4,61840).
+char(3,61841).
+char(c,61842).
+char(c,61843).
+char(m,61844).
+char(8,61845).
+char(7,61846).
+char(0,61847).
+char(3,61848).
+char(c,61849).
+char(c,61850).
+char(m,61851).
+char(3,61852).
+char(6,61853).
+char(2,61854).
+char(0,61855).
+char(c,61856).
+char(c,61857).
+char(p,61858).
+char(3,61859).
+char(5,61860).
+char(8,61861).
+char(2,61862).
+char(m,61863).
+char(5,61864).
+char(0,61865).
+char(6,61866).
+char(4,61867).
+char(c,61868).
+char(c,61869).
+char(c,61870).
+char(c,61871).
+char(c,61872).
+char(c,61873).
+char(m,61874).
+char(o,61875).
+char(p,61876).
+char(o,61877).
+char(p,61878).
+char(o,61879).
+char(o,61880).
+char(4,61881).
+char(9,61882).
+char(8,61883).
+char(1,61884).
+char(c,61885).
+char(m,61886).
+char(9,61887).
+char(5,61888).
+char(8,61889).
+char(1,61890).
+char(c,61891).
+char(p,61892).
+char(8,61893).
+char(1,61894).
+char(1,61895).
+char(7,61896).
+char(c,61897).
+char(c,61898).
+char(c,61899).
+char(c,61900).
+char(c,61901).
+char(m,61902).
+char(o,61903).
+char(m,61904).
+char(1,61905).
+char(8,61906).
+char(7,61907).
+char(2,61908).
+char(c,61909).
+char(c,61910).
+char(c,61911).
+char(m,61912).
+char(o,61913).
+char(4,61914).
+char(4,61915).
+char(8,61916).
+char(9,61917).
+char(m,61918).
+char(5,61919).
+char(3,61920).
+char(4,61921).
+char(6,61922).
+char(c,61923).
+char(m,61924).
+char(o,61925).
+char(m,61926).
+char(o,61927).
+char(o,61928).
+char(p,61929).
+char(o,61930).
+char(p,61931).
+char(o,61932).
+char(3,61933).
+char(0,61934).
+char(5,61935).
+char(c,61936).
+char(c,61937).
+char(c,61938).
+char(p,61939).
+char(o,61940).
+char(m,61941).
+char(o,61942).
+char(m,61943).
+char(2,61944).
+char(5,61945).
+char(3,61946).
+char(6,61947).
+char(m,61948).
+char(o,61949).
+char(o,61950).
+char(m,61951).
+char(4,61952).
+char(4,61953).
+char(8,61954).
+char(2,61955).
+char(c,61956).
+char(c,61957).
+char(p,61958).
+char(5,61959).
+char(7,61960).
+char(5,61961).
+char(6,61962).
+char(m,61963).
+char(7,61964).
+char(7,61965).
+char(7,61966).
+char(3,61967).
+char(p,61968).
+char(o,61969).
+char(m,61970).
+char(o,61971).
+char(m,61972).
+char(o,61973).
+char(m,61974).
+char(o,61975).
+char(m,61976).
+char(o,61977).
+char(m,61978).
+char(9,61979).
+char(8,61980).
+char(3,61981).
+char(0,61982).
+char(c,61983).
+char(p,61984).
+char(9,61985).
+char(5,61986).
+char(7,61987).
+char(2,61988).
+char(p,61989).
+char(o,61990).
+char(2,61991).
+char(5,61992).
+char(1,61993).
+char(3,61994).
+char(c,61995).
+char(p,61996).
+char(7,61997).
+char(4,61998).
+char(7,61999).
+char(8,62000).
+char(p,62001).
+char(2,62002).
+char(1,62003).
+char(8,62004).
+char(2,62005).
+char(c,62006).
+char(c,62007).
+char(m,62008).
+char(o,62009).
+char(m,62010).
+char(o,62011).
+char(m,62012).
+char(3,62013).
+char(9,62014).
+char(9,62015).
+char(8,62016).
+char(c,62017).
+char(c,62018).
+char(p,62019).
+char(o,62020).
+char(p,62021).
+char(o,62022).
+char(o,62023).
+char(p,62024).
+char(o,62025).
+char(m,62026).
+char(o,62027).
+char(p,62028).
+char(o,62029).
+char(o,62030).
+char(p,62031).
+char(4,62032).
+char(3,62033).
+char(3,62034).
+char(2,62035).
+char(c,62036).
+char(p,62037).
+char(5,62038).
+char(1,62039).
+char(5,62040).
+char(5,62041).
+char(m,62042).
+char(7,62043).
+char(7,62044).
+char(8,62045).
+char(c,62046).
+char(p,62047).
+char(o,62048).
+char(o,62049).
+char(o,62050).
+char(m,62051).
+char(o,62052).
+char(p,62053).
+char(o,62054).
+char(p,62055).
+char(1,62056).
+char(7,62057).
+char(1,62058).
+char(1,62059).
+char(c,62060).
+char(c,62061).
+char(p,62062).
+char(o,62063).
+char(p,62064).
+char(o,62065).
+char(o,62066).
+char(m,62067).
+char(o,62068).
+char(p,62069).
+char(4,62070).
+char(8,62071).
+char(1,62072).
+char(0,62073).
+char(m,62074).
+char(9,62075).
+char(2,62076).
+char(5,62077).
+char(6,62078).
+char(m,62079).
+char(9,62080).
+char(5,62081).
+char(2,62082).
+char(1,62083).
+char(c,62084).
+char(c,62085).
+char(m,62086).
+char(1,62087).
+char(1,62088).
+char(0,62089).
+char(6,62090).
+char(c,62091).
+char(m,62092).
+char(o,62093).
+char(m,62094).
+char(o,62095).
+char(o,62096).
+char(p,62097).
+char(4,62098).
+char(9,62099).
+char(0,62100).
+char(8,62101).
+char(c,62102).
+char(p,62103).
+char(7,62104).
+char(9,62105).
+char(5,62106).
+char(9,62107).
+char(c,62108).
+char(c,62109).
+char(c,62110).
+char(c,62111).
+char(c,62112).
+char(m,62113).
+char(o,62114).
+char(9,62115).
+char(1,62116).
+char(1,62117).
+char(0,62118).
+char(c,62119).
+char(p,62120).
+char(1,62121).
+char(2,62122).
+char(8,62123).
+char(1,62124).
+char(p,62125).
+char(o,62126).
+char(8,62127).
+char(0,62128).
+char(4,62129).
+char(m,62130).
+char(o,62131).
+char(p,62132).
+char(o,62133).
+char(5,62134).
+char(1,62135).
+char(3,62136).
+char(7,62137).
+char(c,62138).
+char(p,62139).
+char(o,62140).
+char(8,62141).
+char(9,62142).
+char(4,62143).
+char(9,62144).
+char(c,62145).
+char(c,62146).
+char(c,62147).
+char(c,62148).
+char(c,62149).
+char(c,62150).
+char(m,62151).
+char(5,62152).
+char(7,62153).
+char(2,62154).
+char(2,62155).
+char(p,62156).
+char(2,62157).
+char(4,62158).
+char(6,62159).
+char(2,62160).
+char(c,62161).
+char(c,62162).
+char(c,62163).
+char(m,62164).
+char(o,62165).
+char(p,62166).
+char(o,62167).
+char(7,62168).
+char(2,62169).
+char(c,62170).
+char(p,62171).
+char(o,62172).
+char(m,62173).
+char(9,62174).
+char(9,62175).
+char(7,62176).
+char(9,62177).
+char(p,62178).
+char(o,62179).
+char(m,62180).
+char(o,62181).
+char(9,62182).
+char(9,62183).
+char(7,62184).
+char(p,62185).
+char(5,62186).
+char(0,62187).
+char(0,62188).
+char(9,62189).
+char(c,62190).
+char(p,62191).
+char(o,62192).
+char(2,62193).
+char(4,62194).
+char(0,62195).
+char(1,62196).
+char(c,62197).
+char(p,62198).
+char(o,62199).
+char(m,62200).
+char(o,62201).
+char(6,62202).
+char(9,62203).
+char(1,62204).
+char(0,62205).
+char(c,62206).
+char(c,62207).
+char(c,62208).
+char(c,62209).
+char(c,62210).
+char(c,62211).
+char(p,62212).
+char(6,62213).
+char(7,62214).
+char(6,62215).
+char(1,62216).
+char(c,62217).
+char(c,62218).
+char(m,62219).
+char(o,62220).
+char(p,62221).
+char(3,62222).
+char(7,62223).
+char(p,62224).
+char(5,62225).
+char(1,62226).
+char(3,62227).
+char(8,62228).
+char(p,62229).
+char(8,62230).
+char(2,62231).
+char(5,62232).
+char(8,62233).
+char(c,62234).
+char(c,62235).
+char(c,62236).
+char(m,62237).
+char(o,62238).
+char(1,62239).
+char(2,62240).
+char(3,62241).
+char(p,62242).
+char(6,62243).
+char(0,62244).
+char(8,62245).
+char(9,62246).
+char(m,62247).
+char(o,62248).
+char(o,62249).
+char(m,62250).
+char(o,62251).
+char(p,62252).
+char(o,62253).
+char(o,62254).
+char(m,62255).
+char(7,62256).
+char(4,62257).
+char(6,62258).
+char(c,62259).
+char(c,62260).
+char(c,62261).
+char(c,62262).
+char(c,62263).
+char(m,62264).
+char(6,62265).
+char(7,62266).
+char(7,62267).
+char(0,62268).
+char(c,62269).
+char(c,62270).
+char(p,62271).
+char(6,62272).
+char(2,62273).
+char(9,62274).
+char(0,62275).
+char(p,62276).
+char(o,62277).
+char(p,62278).
+char(o,62279).
+char(m,62280).
+char(o,62281).
+char(1,62282).
+char(2,62283).
+char(9,62284).
+char(6,62285).
+char(m,62286).
+char(o,62287).
+char(p,62288).
+char(8,62289).
+char(3,62290).
+char(7,62291).
+char(6,62292).
+char(m,62293).
+char(o,62294).
+char(m,62295).
+char(5,62296).
+char(2,62297).
+char(5,62298).
+char(m,62299).
+char(3,62300).
+char(0,62301).
+char(2,62302).
+char(9,62303).
+char(p,62304).
+char(o,62305).
+char(m,62306).
+char(o,62307).
+char(p,62308).
+char(o,62309).
+char(m,62310).
+char(o,62311).
+char(m,62312).
+char(o,62313).
+char(p,62314).
+char(o,62315).
+char(p,62316).
+char(o,62317).
+char(m,62318).
+char(3,62319).
+char(6,62320).
+char(0,62321).
+char(3,62322).
+char(c,62323).
+char(m,62324).
+char(o,62325).
+char(m,62326).
+char(9,62327).
+char(2,62328).
+char(1,62329).
+char(6,62330).
+char(c,62331).
+char(p,62332).
+char(o,62333).
+char(m,62334).
+char(3,62335).
+char(6,62336).
+char(4,62337).
+char(8,62338).
+char(c,62339).
+char(c,62340).
+char(m,62341).
+char(7,62342).
+char(6,62343).
+char(3,62344).
+char(2,62345).
+char(p,62346).
+char(o,62347).
+char(p,62348).
+char(o,62349).
+char(o,62350).
+char(o,62351).
+char(p,62352).
+char(1,62353).
+char(2,62354).
+char(1,62355).
+char(7,62356).
+char(c,62357).
+char(c,62358).
+char(m,62359).
+char(9,62360).
+char(2,62361).
+char(6,62362).
+char(9,62363).
+char(c,62364).
+char(m,62365).
+char(o,62366).
+char(p,62367).
+char(o,62368).
+char(p,62369).
+char(o,62370).
+char(p,62371).
+char(o,62372).
+char(p,62373).
+char(9,62374).
+char(1,62375).
+char(1,62376).
+char(1,62377).
+char(c,62378).
+char(c,62379).
+char(c,62380).
+char(m,62381).
+char(2,62382).
+char(0,62383).
+char(c,62384).
+char(c,62385).
+char(m,62386).
+char(o,62387).
+char(p,62388).
+char(o,62389).
+char(m,62390).
+char(o,62391).
+char(m,62392).
+char(o,62393).
+char(m,62394).
+char(9,62395).
+char(5,62396).
+char(1,62397).
+char(6,62398).
+char(c,62399).
+char(c,62400).
+char(p,62401).
+char(o,62402).
+char(p,62403).
+char(o,62404).
+char(o,62405).
+char(7,62406).
+char(3,62407).
+char(2,62408).
+char(2,62409).
+char(m,62410).
+char(o,62411).
+char(m,62412).
+char(o,62413).
+char(p,62414).
+char(o,62415).
+char(p,62416).
+char(1,62417).
+char(0,62418).
+char(6,62419).
+char(0,62420).
+char(c,62421).
+char(c,62422).
+char(c,62423).
+char(p,62424).
+char(3,62425).
+char(4,62426).
+char(3,62427).
+char(3,62428).
+char(c,62429).
+char(p,62430).
+char(1,62431).
+char(7,62432).
+char(3,62433).
+char(1,62434).
+char(c,62435).
+char(c,62436).
+char(c,62437).
+char(c,62438).
+char(c,62439).
+char(c,62440).
+char(p,62441).
+char(9,62442).
+char(2,62443).
+char(2,62444).
+char(6,62445).
+char(p,62446).
+char(2,62447).
+char(4,62448).
+char(2,62449).
+char(9,62450).
+char(c,62451).
+char(c,62452).
+char(p,62453).
+char(o,62454).
+char(m,62455).
+char(7,62456).
+char(6,62457).
+char(8,62458).
+char(3,62459).
+char(p,62460).
+char(o,62461).
+char(p,62462).
+char(o,62463).
+char(o,62464).
+char(2,62465).
+char(5,62466).
+char(5,62467).
+char(1,62468).
+char(p,62469).
+char(o,62470).
+char(5,62471).
+char(7,62472).
+char(8,62473).
+char(0,62474).
+char(m,62475).
+char(o,62476).
+char(o,62477).
+char(m,62478).
+char(7,62479).
+char(7,62480).
+char(1,62481).
+char(1,62482).
+char(c,62483).
+char(c,62484).
+char(c,62485).
+char(c,62486).
+char(c,62487).
+char(m,62488).
+char(4,62489).
+char(4,62490).
+char(0,62491).
+char(1,62492).
+char(p,62493).
+char(6,62494).
+char(5,62495).
+char(8,62496).
+char(p,62497).
+char(o,62498).
+char(m,62499).
+char(3,62500).
+char(4,62501).
+char(8,62502).
+char(4,62503).
+char(p,62504).
+char(7,62505).
+char(9,62506).
+char(9,62507).
+char(9,62508).
+char(c,62509).
+char(p,62510).
+char(6,62511).
+char(6,62512).
+char(2,62513).
+char(7,62514).
+char(c,62515).
+char(c,62516).
+char(c,62517).
+char(c,62518).
+char(m,62519).
+char(6,62520).
+char(1,62521).
+char(5,62522).
+char(5,62523).
+char(c,62524).
+char(c,62525).
+char(p,62526).
+char(2,62527).
+char(0,62528).
+char(9,62529).
+char(8,62530).
+char(c,62531).
+char(c,62532).
+char(c,62533).
+char(p,62534).
+char(9,62535).
+char(5,62536).
+char(2,62537).
+char(2,62538).
+char(c,62539).
+char(c,62540).
+char(c,62541).
+char(c,62542).
+char(c,62543).
+char(m,62544).
+char(o,62545).
+char(4,62546).
+char(4,62547).
+char(3,62548).
+char(2,62549).
+char(c,62550).
+char(c,62551).
+char(p,62552).
+char(8,62553).
+char(0,62554).
+char(2,62555).
+char(3,62556).
+char(m,62557).
+char(o,62558).
+char(m,62559).
+char(8,62560).
+char(9,62561).
+char(9,62562).
+char(2,62563).
+char(m,62564).
+char(4,62565).
+char(0,62566).
+char(3,62567).
+char(6,62568).
+char(p,62569).
+char(o,62570).
+char(p,62571).
+char(o,62572).
+char(p,62573).
+char(4,62574).
+char(1,62575).
+char(2,62576).
+char(4,62577).
+char(c,62578).
+char(c,62579).
+char(p,62580).
+char(o,62581).
+char(m,62582).
+char(o,62583).
+char(m,62584).
+char(7,62585).
+char(1,62586).
+char(3,62587).
+char(2,62588).
+char(c,62589).
+char(c,62590).
+char(c,62591).
+char(p,62592).
+char(9,62593).
+char(4,62594).
+char(8,62595).
+char(7,62596).
+char(c,62597).
+char(p,62598).
+char(9,62599).
+char(2,62600).
+char(2,62601).
+char(7,62602).
+char(c,62603).
+char(p,62604).
+char(o,62605).
+char(m,62606).
+char(o,62607).
+char(m,62608).
+char(o,62609).
+char(m,62610).
+char(o,62611).
+char(4,62612).
+char(8,62613).
+char(8,62614).
+char(1,62615).
+char(c,62616).
+char(m,62617).
+char(6,62618).
+char(0,62619).
+char(5,62620).
+char(0,62621).
+char(c,62622).
+char(p,62623).
+char(9,62624).
+char(7,62625).
+char(6,62626).
+char(p,62627).
+char(o,62628).
+char(p,62629).
+char(o,62630).
+char(m,62631).
+char(o,62632).
+char(o,62633).
+char(o,62634).
+char(p,62635).
+char(1,62636).
+char(5,62637).
+char(7,62638).
+char(2,62639).
+char(m,62640).
+char(o,62641).
+char(m,62642).
+char(o,62643).
+char(p,62644).
+char(9,62645).
+char(5,62646).
+char(6,62647).
+char(4,62648).
+char(p,62649).
+char(o,62650).
+char(p,62651).
+char(2,62652).
+char(5,62653).
+char(1,62654).
+char(7,62655).
+char(c,62656).
+char(c,62657).
+char(m,62658).
+char(o,62659).
+char(m,62660).
+char(5,62661).
+char(3,62662).
+char(4,62663).
+char(6,62664).
+char(c,62665).
+char(c,62666).
+char(m,62667).
+char(o,62668).
+char(o,62669).
+char(2,62670).
+char(2,62671).
+char(8,62672).
+char(3,62673).
+char(c,62674).
+char(m,62675).
+char(4,62676).
+char(0,62677).
+char(3,62678).
+char(8,62679).
+char(c,62680).
+char(c,62681).
+char(p,62682).
+char(8,62683).
+char(2,62684).
+char(4,62685).
+char(6,62686).
+char(c,62687).
+char(c,62688).
+char(c,62689).
+char(m,62690).
+char(o,62691).
+char(m,62692).
+char(o,62693).
+char(p,62694).
+char(o,62695).
+char(p,62696).
+char(2,62697).
+char(5,62698).
+char(4,62699).
+char(1,62700).
+char(c,62701).
+char(p,62702).
+char(2,62703).
+char(3,62704).
+char(8,62705).
+char(2,62706).
+char(c,62707).
+char(p,62708).
+char(o,62709).
+char(m,62710).
+char(8,62711).
+char(7,62712).
+char(9,62713).
+char(9,62714).
+char(m,62715).
+char(o,62716).
+char(p,62717).
+char(o,62718).
+char(o,62719).
+char(p,62720).
+char(4,62721).
+char(0,62722).
+char(3,62723).
+char(6,62724).
+char(c,62725).
+char(p,62726).
+char(o,62727).
+char(m,62728).
+char(o,62729).
+char(p,62730).
+char(7,62731).
+char(5,62732).
+char(1,62733).
+char(0,62734).
+char(c,62735).
+char(m,62736).
+char(2,62737).
+char(8,62738).
+char(7,62739).
+char(0,62740).
+char(c,62741).
+char(p,62742).
+char(o,62743).
+char(p,62744).
+char(4,62745).
+char(3,62746).
+char(5,62747).
+char(6,62748).
+char(p,62749).
+char(1,62750).
+char(1,62751).
+char(9,62752).
+char(1,62753).
+char(p,62754).
+char(9,62755).
+char(4,62756).
+char(7,62757).
+char(7,62758).
+char(p,62759).
+char(o,62760).
+char(m,62761).
+char(o,62762).
+char(m,62763).
+char(7,62764).
+char(7,62765).
+char(3,62766).
+char(1,62767).
+char(c,62768).
+char(m,62769).
+char(3,62770).
+char(4,62771).
+char(3,62772).
+char(2,62773).
+char(p,62774).
+char(2,62775).
+char(4,62776).
+char(0,62777).
+char(6,62778).
+char(m,62779).
+char(1,62780).
+char(8,62781).
+char(9,62782).
+char(2,62783).
+char(m,62784).
+char(8,62785).
+char(3,62786).
+char(8,62787).
+char(7,62788).
+char(m,62789).
+char(7,62790).
+char(4,62791).
+char(6,62792).
+char(5,62793).
+char(p,62794).
+char(o,62795).
+char(m,62796).
+char(o,62797).
+char(9,62798).
+char(7,62799).
+char(4,62800).
+char(5,62801).
+char(p,62802).
+char(7,62803).
+char(5,62804).
+char(6,62805).
+char(9,62806).
+char(m,62807).
+char(o,62808).
+char(1,62809).
+char(9,62810).
+char(6,62811).
+char(1,62812).
+char(c,62813).
+char(p,62814).
+char(3,62815).
+char(9,62816).
+char(0,62817).
+char(6,62818).
+char(p,62819).
+char(2,62820).
+char(8,62821).
+char(6,62822).
+char(1,62823).
+char(c,62824).
+char(p,62825).
+char(1,62826).
+char(3,62827).
+char(9,62828).
+char(1,62829).
+char(c,62830).
+char(m,62831).
+char(o,62832).
+char(m,62833).
+char(4,62834).
+char(9,62835).
+char(6,62836).
+char(2,62837).
+char(p,62838).
+char(3,62839).
+char(4,62840).
+char(0,62841).
+char(6,62842).
+char(c,62843).
+char(p,62844).
+char(o,62845).
+char(4,62846).
+char(2,62847).
+char(0,62848).
+char(9,62849).
+char(m,62850).
+char(2,62851).
+char(1,62852).
+char(8,62853).
+char(5,62854).
+char(m,62855).
+char(8,62856).
+char(5,62857).
+char(8,62858).
+char(6,62859).
+char(m,62860).
+char(1,62861).
+char(0,62862).
+char(5,62863).
+char(8,62864).
+char(p,62865).
+char(3,62866).
+char(9,62867).
+char(9,62868).
+char(5,62869).
+char(p,62870).
+char(5,62871).
+char(6,62872).
+char(2,62873).
+char(p,62874).
+char(o,62875).
+char(o,62876).
+char(p,62877).
+char(6,62878).
+char(5,62879).
+char(8,62880).
+char(3,62881).
+char(m,62882).
+char(9,62883).
+char(8,62884).
+char(7,62885).
+char(1,62886).
+char(p,62887).
+char(9,62888).
+char(2,62889).
+char(4,62890).
+char(8,62891).
+char(c,62892).
+char(c,62893).
+char(p,62894).
+char(8,62895).
+char(2,62896).
+char(0,62897).
+char(6,62898).
+char(c,62899).
+char(p,62900).
+char(o,62901).
+char(p,62902).
+char(o,62903).
+char(p,62904).
+char(o,62905).
+char(m,62906).
+char(3,62907).
+char(6,62908).
+char(1,62909).
+char(7,62910).
+char(m,62911).
+char(8,62912).
+char(7,62913).
+char(0,62914).
+char(1,62915).
+char(m,62916).
+char(3,62917).
+char(2,62918).
+char(6,62919).
+char(c,62920).
+char(c,62921).
+char(m,62922).
+char(o,62923).
+char(4,62924).
+char(8,62925).
+char(2,62926).
+char(5,62927).
+char(c,62928).
+char(p,62929).
+char(o,62930).
+char(p,62931).
+char(3,62932).
+char(6,62933).
+char(2,62934).
+char(3,62935).
+char(c,62936).
+char(c,62937).
+char(p,62938).
+char(1,62939).
+char(7,62940).
+char(1,62941).
+char(0,62942).
+char(m,62943).
+char(3,62944).
+char(0,62945).
+char(0,62946).
+char(3,62947).
+char(m,62948).
+char(4,62949).
+char(4,62950).
+char(2,62951).
+char(3,62952).
+char(c,62953).
+char(c,62954).
+char(c,62955).
+char(m,62956).
+char(o,62957).
+char(p,62958).
+char(o,62959).
+char(p,62960).
+char(o,62961).
+char(2,62962).
+char(3,62963).
+char(3,62964).
+char(2,62965).
+char(c,62966).
+char(m,62967).
+char(5,62968).
+char(4,62969).
+char(6,62970).
+char(3,62971).
+char(m,62972).
+char(8,62973).
+char(1,62974).
+char(3,62975).
+char(8,62976).
+char(c,62977).
+char(m,62978).
+char(o,62979).
+char(m,62980).
+char(o,62981).
+char(o,62982).
+char(p,62983).
+char(3,62984).
+char(8,62985).
+char(5,62986).
+char(0,62987).
+char(p,62988).
+char(1,62989).
+char(7,62990).
+char(1,62991).
+char(c,62992).
+char(c,62993).
+char(m,62994).
+char(o,62995).
+char(o,62996).
+char(m,62997).
+char(o,62998).
+char(m,62999).
+char(5,63000).
+char(8,63001).
+char(2,63002).
+char(4,63003).
+char(c,63004).
+char(p,63005).
+char(o,63006).
+char(p,63007).
+char(o,63008).
+char(m,63009).
+char(6,63010).
+char(3,63011).
+char(8,63012).
+char(c,63013).
+char(m,63014).
+char(o,63015).
+char(o,63016).
+char(m,63017).
+char(o,63018).
+char(m,63019).
+char(5,63020).
+char(5,63021).
+char(6,63022).
+char(4,63023).
+char(c,63024).
+char(c,63025).
+char(m,63026).
+char(9,63027).
+char(2,63028).
+char(1,63029).
+char(3,63030).
+char(p,63031).
+char(o,63032).
+char(o,63033).
+char(m,63034).
+char(8,63035).
+char(8,63036).
+char(8,63037).
+char(1,63038).
+char(c,63039).
+char(p,63040).
+char(9,63041).
+char(7,63042).
+char(5,63043).
+char(9,63044).
+char(p,63045).
+char(3,63046).
+char(4,63047).
+char(7,63048).
+char(2,63049).
+char(c,63050).
+char(p,63051).
+char(6,63052).
+char(5,63053).
+char(9,63054).
+char(0,63055).
+char(m,63056).
+char(o,63057).
+char(m,63058).
+char(7,63059).
+char(1,63060).
+char(8,63061).
+char(4,63062).
+char(c,63063).
+char(p,63064).
+char(o,63065).
+char(p,63066).
+char(9,63067).
+char(9,63068).
+char(4,63069).
+char(3,63070).
+char(p,63071).
+char(2,63072).
+char(9,63073).
+char(7,63074).
+char(m,63075).
+char(7,63076).
+char(3,63077).
+char(0,63078).
+char(6,63079).
+char(c,63080).
+char(c,63081).
+char(m,63082).
+char(o,63083).
+char(p,63084).
+char(o,63085).
+char(p,63086).
+char(3,63087).
+char(9,63088).
+char(0,63089).
+char(1,63090).
+char(c,63091).
+char(m,63092).
+char(o,63093).
+char(m,63094).
+char(o,63095).
+char(o,63096).
+char(p,63097).
+char(o,63098).
+char(m,63099).
+char(o,63100).
+char(o,63101).
+char(p,63102).
+char(o,63103).
+char(6,63104).
+char(0,63105).
+char(4,63106).
+char(1,63107).
+char(m,63108).
+char(o,63109).
+char(o,63110).
+char(m,63111).
+char(o,63112).
+char(p,63113).
+char(o,63114).
+char(p,63115).
+char(o,63116).
+char(7,63117).
+char(0,63118).
+char(3,63119).
+char(3,63120).
+char(c,63121).
+char(c,63122).
+char(p,63123).
+char(1,63124).
+char(6,63125).
+char(7,63126).
+char(3,63127).
+char(p,63128).
+char(3,63129).
+char(2,63130).
+char(3,63131).
+char(5,63132).
+char(p,63133).
+char(o,63134).
+char(p,63135).
+char(9,63136).
+char(0,63137).
+char(4,63138).
+char(c,63139).
+char(c,63140).
+char(c,63141).
+char(m,63142).
+char(o,63143).
+char(p,63144).
+char(o,63145).
+char(m,63146).
+char(2,63147).
+char(0,63148).
+char(6,63149).
+char(5,63150).
+char(c,63151).
+char(p,63152).
+char(o,63153).
+char(m,63154).
+char(o,63155).
+char(o,63156).
+char(1,63157).
+char(2,63158).
+char(8,63159).
+char(5,63160).
+char(p,63161).
+char(6,63162).
+char(8,63163).
+char(6,63164).
+char(4,63165).
+char(c,63166).
+char(c,63167).
+char(m,63168).
+char(o,63169).
+char(p,63170).
+char(o,63171).
+char(m,63172).
+char(o,63173).
+char(m,63174).
+char(o,63175).
+char(m,63176).
+char(o,63177).
+char(m,63178).
+char(o,63179).
+char(p,63180).
+char(o,63181).
+char(6,63182).
+char(2,63183).
+char(3,63184).
+char(4,63185).
+char(c,63186).
+char(c,63187).
+char(c,63188).
+char(m,63189).
+char(9,63190).
+char(3,63191).
+char(7,63192).
+char(0,63193).
+char(m,63194).
+char(9,63195).
+char(1,63196).
+char(1,63197).
+char(4,63198).
+char(c,63199).
+char(m,63200).
+char(8,63201).
+char(9,63202).
+char(4,63203).
+char(8,63204).
+char(p,63205).
+char(8,63206).
+char(7,63207).
+char(7,63208).
+char(3,63209).
+char(p,63210).
+char(7,63211).
+char(4,63212).
+char(6,63213).
+char(4,63214).
+char(p,63215).
+char(2,63216).
+char(2,63217).
+char(1,63218).
+char(7,63219).
+char(m,63220).
+char(4,63221).
+char(8,63222).
+char(2,63223).
+char(6,63224).
+char(c,63225).
+char(c,63226).
+char(m,63227).
+char(o,63228).
+char(m,63229).
+char(3,63230).
+char(3,63231).
+char(6,63232).
+char(5,63233).
+char(m,63234).
+char(1,63235).
+char(4,63236).
+char(8,63237).
+char(0,63238).
+char(m,63239).
+char(o,63240).
+char(m,63241).
+char(4,63242).
+char(4,63243).
+char(9,63244).
+char(1,63245).
+char(c,63246).
+char(m,63247).
+char(o,63248).
+char(p,63249).
+char(o,63250).
+char(m,63251).
+char(o,63252).
+char(p,63253).
+char(o,63254).
+char(p,63255).
+char(o,63256).
+char(o,63257).
+char(p,63258).
+char(8,63259).
+char(1,63260).
+char(9,63261).
+char(5,63262).
+char(p,63263).
+char(o,63264).
+char(p,63265).
+char(8,63266).
+char(5,63267).
+char(3,63268).
+char(5,63269).
+char(p,63270).
+char(1,63271).
+char(6,63272).
+char(6,63273).
+char(3,63274).
+char(p,63275).
+char(o,63276).
+char(m,63277).
+char(9,63278).
+char(3,63279).
+char(3,63280).
+char(p,63281).
+char(o,63282).
+char(3,63283).
+char(5,63284).
+char(8,63285).
+char(5,63286).
+char(m,63287).
+char(5,63288).
+char(3,63289).
+char(7,63290).
+char(2,63291).
+char(m,63292).
+char(o,63293).
+char(8,63294).
+char(7,63295).
+char(3,63296).
+char(8,63297).
+char(m,63298).
+char(7,63299).
+char(5,63300).
+char(1,63301).
+char(7,63302).
+char(c,63303).
+char(c,63304).
+char(m,63305).
+char(o,63306).
+char(1,63307).
+char(9,63308).
+char(7,63309).
+char(8,63310).
+char(p,63311).
+char(o,63312).
+char(m,63313).
+char(5,63314).
+char(2,63315).
+char(8,63316).
+char(7,63317).
+char(m,63318).
+char(o,63319).
+char(1,63320).
+char(2,63321).
+char(3,63322).
+char(7,63323).
+char(m,63324).
+char(2,63325).
+char(1,63326).
+char(0,63327).
+char(9,63328).
+char(c,63329).
+char(m,63330).
+char(o,63331).
+char(m,63332).
+char(1,63333).
+char(0,63334).
+char(2,63335).
+char(3,63336).
+char(c,63337).
+char(c,63338).
+char(c,63339).
+char(c,63340).
+char(m,63341).
+char(o,63342).
+char(m,63343).
+char(o,63344).
+char(m,63345).
+char(o,63346).
+char(p,63347).
+char(o,63348).
+char(5,63349).
+char(1,63350).
+char(4,63351).
+char(m,63352).
+char(9,63353).
+char(0,63354).
+char(1,63355).
+char(5,63356).
+char(p,63357).
+char(o,63358).
+char(p,63359).
+char(7,63360).
+char(9,63361).
+char(7,63362).
+char(3,63363).
+char(m,63364).
+char(o,63365).
+char(m,63366).
+char(o,63367).
+char(m,63368).
+char(o,63369).
+char(5,63370).
+char(3,63371).
+char(6,63372).
+char(5,63373).
+char(c,63374).
+char(c,63375).
+char(m,63376).
+char(6,63377).
+char(6,63378).
+char(6,63379).
+char(5,63380).
+char(c,63381).
+char(c,63382).
+char(m,63383).
+char(4,63384).
+char(2,63385).
+char(3,63386).
+char(3,63387).
+char(p,63388).
+char(o,63389).
+char(m,63390).
+char(o,63391).
+char(m,63392).
+char(o,63393).
+char(p,63394).
+char(9,63395).
+char(0,63396).
+char(7,63397).
+char(2,63398).
+char(p,63399).
+char(7,63400).
+char(7,63401).
+char(1,63402).
+char(4,63403).
+char(m,63404).
+char(o,63405).
+char(1,63406).
+char(0,63407).
+char(4,63408).
+char(p,63409).
+char(o,63410).
+char(o,63411).
+char(m,63412).
+char(2,63413).
+char(7,63414).
+char(0,63415).
+char(c,63416).
+char(c,63417).
+char(c,63418).
+char(c,63419).
+char(c,63420).
+char(p,63421).
+char(2,63422).
+char(0,63423).
+char(9,63424).
+char(2,63425).
+char(p,63426).
+char(4,63427).
+char(6,63428).
+char(3,63429).
+char(9,63430).
+char(c,63431).
+char(m,63432).
+char(2,63433).
+char(1,63434).
+char(1,63435).
+char(4,63436).
+char(m,63437).
+char(4,63438).
+char(6,63439).
+char(4,63440).
+char(9,63441).
+char(m,63442).
+char(9,63443).
+char(1,63444).
+char(2,63445).
+char(5,63446).
+char(c,63447).
+char(c,63448).
+char(c,63449).
+char(c,63450).
+char(m,63451).
+char(o,63452).
+char(p,63453).
+char(o,63454).
+char(m,63455).
+char(o,63456).
+char(8,63457).
+char(2,63458).
+char(9,63459).
+char(7,63460).
+char(p,63461).
+char(3,63462).
+char(2,63463).
+char(7,63464).
+char(9,63465).
+char(c,63466).
+char(c,63467).
+char(c,63468).
+char(c,63469).
+char(c,63470).
+char(c,63471).
+char(c,63472).
+char(c,63473).
+char(c,63474).
+char(c,63475).
+char(m,63476).
+char(6,63477).
+char(4,63478).
+char(7,63479).
+char(5,63480).
+char(c,63481).
+char(p,63482).
+char(o,63483).
+char(o,63484).
+char(o,63485).
+char(p,63486).
+char(o,63487).
+char(p,63488).
+char(o,63489).
+char(o,63490).
+char(1,63491).
+char(3,63492).
+char(4,63493).
+char(4,63494).
+char(p,63495).
+char(o,63496).
+char(p,63497).
+char(o,63498).
+char(p,63499).
+char(o,63500).
+char(8,63501).
+char(5,63502).
+char(7,63503).
+char(4,63504).
+char(c,63505).
+char(c,63506).
+char(p,63507).
+char(9,63508).
+char(6,63509).
+char(5,63510).
+char(0,63511).
+char(m,63512).
+char(9,63513).
+char(2,63514).
+char(2,63515).
+char(6,63516).
+char(p,63517).
+char(2,63518).
+char(3,63519).
+char(1,63520).
+char(3,63521).
+char(c,63522).
+char(p,63523).
+char(6,63524).
+char(5,63525).
+char(9,63526).
+char(7,63527).
+char(p,63528).
+char(5,63529).
+char(2,63530).
+char(0,63531).
+char(9,63532).
+char(c,63533).
+char(c,63534).
+char(p,63535).
+char(o,63536).
+char(o,63537).
+char(p,63538).
+char(o,63539).
+char(o,63540).
+char(p,63541).
+char(1,63542).
+char(7,63543).
+char(9,63544).
+char(6,63545).
+char(p,63546).
+char(o,63547).
+char(m,63548).
+char(o,63549).
+char(m,63550).
+char(5,63551).
+char(2,63552).
+char(5,63553).
+char(5,63554).
+char(m,63555).
+char(o,63556).
+char(m,63557).
+char(o,63558).
+char(4,63559).
+char(8,63560).
+char(5,63561).
+char(p,63562).
+char(9,63563).
+char(7,63564).
+char(2,63565).
+char(0,63566).
+char(c,63567).
+char(p,63568).
+char(o,63569).
+char(3,63570).
+char(8,63571).
+char(2,63572).
+char(8,63573).
+char(m,63574).
+char(o,63575).
+char(m,63576).
+char(1,63577).
+char(7,63578).
+char(5,63579).
+char(1,63580).
+char(c,63581).
+char(p,63582).
+char(2,63583).
+char(9,63584).
+char(0,63585).
+char(5,63586).
+char(m,63587).
+char(o,63588).
+char(m,63589).
+char(o,63590).
+char(m,63591).
+char(o,63592).
+char(p,63593).
+char(o,63594).
+char(p,63595).
+char(o,63596).
+char(p,63597).
+char(2,63598).
+char(0,63599).
+char(8,63600).
+char(6,63601).
+char(c,63602).
+char(c,63603).
+char(m,63604).
+char(1,63605).
+char(3,63606).
+char(1,63607).
+char(7,63608).
+char(c,63609).
+char(c,63610).
+char(p,63611).
+char(o,63612).
+char(m,63613).
+char(7,63614).
+char(1,63615).
+char(6,63616).
+char(1,63617).
+char(m,63618).
+char(o,63619).
+char(m,63620).
+char(9,63621).
+char(7,63622).
+char(1,63623).
+char(9,63624).
+char(c,63625).
+char(c,63626).
+char(p,63627).
+char(1,63628).
+char(5,63629).
+char(7,63630).
+char(2,63631).
+char(c,63632).
+char(c,63633).
+char(c,63634).
+char(m,63635).
+char(4,63636).
+char(8,63637).
+char(4,63638).
+char(5,63639).
+char(c,63640).
+char(m,63641).
+char(4,63642).
+char(3,63643).
+char(8,63644).
+char(6,63645).
+char(c,63646).
+char(c,63647).
+char(p,63648).
+char(9,63649).
+char(8,63650).
+char(4,63651).
+char(8,63652).
+char(c,63653).
+char(m,63654).
+char(o,63655).
+char(p,63656).
+char(1,63657).
+char(6,63658).
+char(0,63659).
+char(8,63660).
+char(c,63661).
+char(c,63662).
+char(c,63663).
+char(c,63664).
+char(c,63665).
+char(c,63666).
+char(m,63667).
+char(o,63668).
+char(m,63669).
+char(o,63670).
+char(o,63671).
+char(p,63672).
+char(1,63673).
+char(0,63674).
+char(5,63675).
+char(7,63676).
+char(m,63677).
+char(9,63678).
+char(6,63679).
+char(7,63680).
+char(m,63681).
+char(o,63682).
+char(p,63683).
+char(4,63684).
+char(2,63685).
+char(1,63686).
+char(c,63687).
+char(p,63688).
+char(o,63689).
+char(o,63690).
+char(p,63691).
+char(9,63692).
+char(1,63693).
+char(2,63694).
+char(2,63695).
+char(c,63696).
+char(c,63697).
+char(p,63698).
+char(7,63699).
+char(8,63700).
+char(3,63701).
+char(5,63702).
+char(p,63703).
+char(7,63704).
+char(1,63705).
+char(2,63706).
+char(5,63707).
+char(c,63708).
+char(m,63709).
+char(o,63710).
+char(m,63711).
+char(3,63712).
+char(7,63713).
+char(4,63714).
+char(8,63715).
+char(c,63716).
+char(c,63717).
+char(p,63718).
+char(2,63719).
+char(6,63720).
+char(4,63721).
+char(0,63722).
+char(c,63723).
+char(c,63724).
+char(c,63725).
+char(m,63726).
+char(o,63727).
+char(1,63728).
+char(1,63729).
+char(6,63730).
+char(3,63731).
+char(c,63732).
+char(c,63733).
+char(c,63734).
+char(c,63735).
+char(p,63736).
+char(4,63737).
+char(2,63738).
+char(5,63739).
+char(1,63740).
+char(c,63741).
+char(p,63742).
+char(o,63743).
+char(p,63744).
+char(o,63745).
+char(o,63746).
+char(p,63747).
+char(6,63748).
+char(3,63749).
+char(1,63750).
+char(8,63751).
+char(m,63752).
+char(o,63753).
+char(p,63754).
+char(o,63755).
+char(p,63756).
+char(9,63757).
+char(8,63758).
+char(3,63759).
+char(c,63760).
+char(c,63761).
+char(m,63762).
+char(5,63763).
+char(5,63764).
+char(1,63765).
+char(7,63766).
+char(p,63767).
+char(o,63768).
+char(m,63769).
+char(3,63770).
+char(4,63771).
+char(8,63772).
+char(c,63773).
+char(c,63774).
+char(p,63775).
+char(2,63776).
+char(5,63777).
+char(1,63778).
+char(2,63779).
+char(p,63780).
+char(o,63781).
+char(3,63782).
+char(1,63783).
+char(9,63784).
+char(3,63785).
+char(c,63786).
+char(c,63787).
+char(c,63788).
+char(p,63789).
+char(4,63790).
+char(1,63791).
+char(3,63792).
+char(6,63793).
+char(m,63794).
+char(o,63795).
+char(m,63796).
+char(o,63797).
+char(m,63798).
+char(1,63799).
+char(3,63800).
+char(2,63801).
+char(2,63802).
+char(p,63803).
+char(1,63804).
+char(3,63805).
+char(7,63806).
+char(2,63807).
+char(m,63808).
+char(6,63809).
+char(3,63810).
+char(4,63811).
+char(7,63812).
+char(m,63813).
+char(o,63814).
+char(p,63815).
+char(2,63816).
+char(7,63817).
+char(9,63818).
+char(2,63819).
+char(c,63820).
+char(p,63821).
+char(2,63822).
+char(1,63823).
+char(6,63824).
+char(9,63825).
+char(c,63826).
+char(p,63827).
+char(6,63828).
+char(0,63829).
+char(4,63830).
+char(5,63831).
+char(c,63832).
+char(m,63833).
+char(o,63834).
+char(p,63835).
+char(o,63836).
+char(m,63837).
+char(9,63838).
+char(8,63839).
+char(5,63840).
+char(3,63841).
+char(p,63842).
+char(3,63843).
+char(0,63844).
+char(2,63845).
+char(1,63846).
+char(c,63847).
+char(c,63848).
+char(c,63849).
+char(p,63850).
+char(o,63851).
+char(m,63852).
+char(o,63853).
+char(6,63854).
+char(4,63855).
+char(2,63856).
+char(0,63857).
+char(c,63858).
+char(m,63859).
+char(8,63860).
+char(6,63861).
+char(4,63862).
+char(1,63863).
+char(m,63864).
+char(o,63865).
+char(p,63866).
+char(4,63867).
+char(9,63868).
+char(2,63869).
+char(5,63870).
+char(p,63871).
+char(o,63872).
+char(p,63873).
+char(6,63874).
+char(7,63875).
+char(5,63876).
+char(2,63877).
+char(c,63878).
+char(m,63879).
+char(2,63880).
+char(5,63881).
+char(0,63882).
+char(6,63883).
+char(m,63884).
+char(6,63885).
+char(7,63886).
+char(7,63887).
+char(2,63888).
+char(p,63889).
+char(5,63890).
+char(5,63891).
+char(4,63892).
+char(8,63893).
+char(c,63894).
+char(m,63895).
+char(o,63896).
+char(p,63897).
+char(o,63898).
+char(p,63899).
+char(3,63900).
+char(9,63901).
+char(6,63902).
+char(5,63903).
+char(m,63904).
+char(6,63905).
+char(7,63906).
+char(3,63907).
+char(4,63908).
+char(c,63909).
+char(c,63910).
+char(m,63911).
+char(6,63912).
+char(7,63913).
+char(9,63914).
+char(2,63915).
+char(m,63916).
+char(o,63917).
+char(m,63918).
+char(o,63919).
+char(m,63920).
+char(6,63921).
+char(0,63922).
+char(9,63923).
+char(7,63924).
+char(c,63925).
+char(c,63926).
+char(c,63927).
+char(m,63928).
+char(9,63929).
+char(8,63930).
+char(5,63931).
+char(2,63932).
+char(c,63933).
+char(p,63934).
+char(1,63935).
+char(0,63936).
+char(8,63937).
+char(3,63938).
+char(m,63939).
+char(o,63940).
+char(p,63941).
+char(o,63942).
+char(p,63943).
+char(o,63944).
+char(o,63945).
+char(m,63946).
+char(o,63947).
+char(p,63948).
+char(3,63949).
+char(1,63950).
+char(1,63951).
+char(9,63952).
+char(c,63953).
+char(c,63954).
+char(m,63955).
+char(o,63956).
+char(6,63957).
+char(8,63958).
+char(3,63959).
+char(5,63960).
+char(m,63961).
+char(9,63962).
+char(3,63963).
+char(7,63964).
+char(6,63965).
+char(p,63966).
+char(1,63967).
+char(9,63968).
+char(1,63969).
+char(3,63970).
+char(p,63971).
+char(2,63972).
+char(0,63973).
+char(5,63974).
+char(7,63975).
+char(c,63976).
+char(c,63977).
+char(c,63978).
+char(p,63979).
+char(o,63980).
+char(p,63981).
+char(o,63982).
+char(o,63983).
+char(m,63984).
+char(o,63985).
+char(p,63986).
+char(1,63987).
+char(2,63988).
+char(1,63989).
+char(6,63990).
+char(c,63991).
+char(c,63992).
+char(c,63993).
+char(c,63994).
+char(c,63995).
+char(c,63996).
+char(c,63997).
+char(c,63998).
+char(c,63999).
+char(c,64000).
+char(c,64001).
+char(c,64002).
+char(c,64003).
+char(p,64004).
+char(1,64005).
+char(4,64006).
+char(2,64007).
+char(0,64008).
+char(m,64009).
+char(7,64010).
+char(9,64011).
+char(1,64012).
+char(5,64013).
+char(p,64014).
+char(o,64015).
+char(p,64016).
+char(o,64017).
+char(p,64018).
+char(o,64019).
+char(o,64020).
+char(m,64021).
+char(7,64022).
+char(3,64023).
+char(4,64024).
+char(9,64025).
+char(p,64026).
+char(5,64027).
+char(8,64028).
+char(7,64029).
+char(9,64030).
+char(p,64031).
+char(9,64032).
+char(3,64033).
+char(5,64034).
+char(1,64035).
+char(c,64036).
+char(c,64037).
+char(c,64038).
+char(c,64039).
+char(m,64040).
+char(o,64041).
+char(6,64042).
+char(7,64043).
+char(4,64044).
+char(5,64045).
+char(p,64046).
+char(1,64047).
+char(2,64048).
+char(0,64049).
+char(6,64050).
+char(c,64051).
+char(c,64052).
+char(c,64053).
+char(p,64054).
+char(o,64055).
+char(p,64056).
+char(1,64057).
+char(1,64058).
+char(5,64059).
+char(4,64060).
+char(m,64061).
+char(6,64062).
+char(4,64063).
+char(4,64064).
+char(6,64065).
+char(m,64066).
+char(6,64067).
+char(0,64068).
+char(4,64069).
+char(4,64070).
+char(m,64071).
+char(o,64072).
+char(5,64073).
+char(4,64074).
+char(c,64075).
+char(m,64076).
+char(9,64077).
+char(3,64078).
+char(6,64079).
+char(8,64080).
+char(p,64081).
+char(9,64082).
+char(5,64083).
+char(9,64084).
+char(5,64085).
+char(c,64086).
+char(c,64087).
+char(c,64088).
+char(p,64089).
+char(o,64090).
+char(m,64091).
+char(o,64092).
+char(o,64093).
+char(m,64094).
+char(9,64095).
+char(0,64096).
+char(9,64097).
+char(0,64098).
+char(p,64099).
+char(o,64100).
+char(m,64101).
+char(3,64102).
+char(6,64103).
+char(4,64104).
+char(7,64105).
+char(c,64106).
+char(c,64107).
+char(p,64108).
+char(2,64109).
+char(5,64110).
+char(2,64111).
+char(0,64112).
+char(m,64113).
+char(1,64114).
+char(0,64115).
+char(0,64116).
+char(3,64117).
+char(c,64118).
+char(m,64119).
+char(o,64120).
+char(p,64121).
+char(7,64122).
+char(4,64123).
+char(6,64124).
+char(0,64125).
+char(m,64126).
+char(o,64127).
+char(m,64128).
+char(o,64129).
+char(m,64130).
+char(o,64131).
+char(o,64132).
+char(o,64133).
+char(p,64134).
+char(o,64135).
+char(o,64136).
+char(m,64137).
+char(6,64138).
+char(7,64139).
+char(4,64140).
+char(0,64141).
+char(c,64142).
+char(m,64143).
+char(o,64144).
+char(9,64145).
+char(7,64146).
+char(6,64147).
+char(0,64148).
+char(c,64149).
+char(p,64150).
+char(o,64151).
+char(p,64152).
+char(8,64153).
+char(7,64154).
+char(5,64155).
+char(3,64156).
+char(c,64157).
+char(m,64158).
+char(3,64159).
+char(4,64160).
+char(2,64161).
+char(9,64162).
+char(c,64163).
+char(m,64164).
+char(o,64165).
+char(m,64166).
+char(o,64167).
+char(4,64168).
+char(1,64169).
+char(8,64170).
+char(3,64171).
+char(p,64172).
+char(o,64173).
+char(p,64174).
+char(5,64175).
+char(3,64176).
+char(5,64177).
+char(4,64178).
+char(m,64179).
+char(o,64180).
+char(p,64181).
+char(o,64182).
+char(p,64183).
+char(8,64184).
+char(5,64185).
+char(8,64186).
+char(7,64187).
+char(c,64188).
+char(c,64189).
+char(c,64190).
+char(p,64191).
+char(o,64192).
+char(m,64193).
+char(o,64194).
+char(o,64195).
+char(o,64196).
+char(m,64197).
+char(3,64198).
+char(4,64199).
+char(8,64200).
+char(3,64201).
+char(c,64202).
+char(p,64203).
+char(2,64204).
+char(8,64205).
+char(1,64206).
+char(3,64207).
+char(c,64208).
+char(p,64209).
+char(6,64210).
+char(4,64211).
+char(0,64212).
+char(5,64213).
+char(m,64214).
+char(o,64215).
+char(6,64216).
+char(6,64217).
+char(1,64218).
+char(8,64219).
+char(c,64220).
+char(c,64221).
+char(c,64222).
+char(c,64223).
+char(p,64224).
+char(5,64225).
+char(8,64226).
+char(0,64227).
+char(2,64228).
+char(c,64229).
+char(m,64230).
+char(1,64231).
+char(1,64232).
+char(4,64233).
+char(9,64234).
+char(c,64235).
+char(p,64236).
+char(8,64237).
+char(2,64238).
+char(2,64239).
+char(7,64240).
+char(p,64241).
+char(o,64242).
+char(p,64243).
+char(o,64244).
+char(m,64245).
+char(6,64246).
+char(1,64247).
+char(6,64248).
+char(6,64249).
+char(c,64250).
+char(m,64251).
+char(2,64252).
+char(5,64253).
+char(2,64254).
+char(5,64255).
+char(m,64256).
+char(2,64257).
+char(7,64258).
+char(4,64259).
+char(c,64260).
+char(c,64261).
+char(p,64262).
+char(3,64263).
+char(4,64264).
+char(9,64265).
+char(2,64266).
+char(c,64267).
+char(p,64268).
+char(o,64269).
+char(7,64270).
+char(6,64271).
+char(3,64272).
+char(8,64273).
+char(c,64274).
+char(m,64275).
+char(5,64276).
+char(7,64277).
+char(8,64278).
+char(4,64279).
+char(c,64280).
+char(c,64281).
+char(c,64282).
+char(c,64283).
+char(m,64284).
+char(o,64285).
+char(p,64286).
+char(o,64287).
+char(o,64288).
+char(m,64289).
+char(o,64290).
+char(m,64291).
+char(4,64292).
+char(6,64293).
+char(1,64294).
+char(7,64295).
+char(m,64296).
+char(3,64297).
+char(9,64298).
+char(3,64299).
+char(2,64300).
+char(c,64301).
+char(c,64302).
+char(c,64303).
+char(c,64304).
+char(m,64305).
+char(o,64306).
+char(3,64307).
+char(5,64308).
+char(2,64309).
+char(m,64310).
+char(3,64311).
+char(9,64312).
+char(7,64313).
+char(7,64314).
+char(p,64315).
+char(o,64316).
+char(o,64317).
+char(p,64318).
+char(o,64319).
+char(m,64320).
+char(8,64321).
+char(6,64322).
+char(1,64323).
+char(2,64324).
+char(m,64325).
+char(o,64326).
+char(m,64327).
+char(4,64328).
+char(2,64329).
+char(3,64330).
+char(1,64331).
+char(m,64332).
+char(9,64333).
+char(4,64334).
+char(2,64335).
+char(4,64336).
+char(c,64337).
+char(c,64338).
+char(m,64339).
+char(2,64340).
+char(7,64341).
+char(2,64342).
+char(8,64343).
+char(m,64344).
+char(7,64345).
+char(7,64346).
+char(6,64347).
+char(0,64348).
+char(c,64349).
+char(c,64350).
+char(p,64351).
+char(3,64352).
+char(4,64353).
+char(4,64354).
+char(5,64355).
+char(m,64356).
+char(o,64357).
+char(p,64358).
+char(1,64359).
+char(6,64360).
+char(4,64361).
+char(c,64362).
+char(c,64363).
+char(c,64364).
+char(c,64365).
+char(p,64366).
+char(4,64367).
+char(6,64368).
+char(3,64369).
+char(0,64370).
+char(c,64371).
+char(m,64372).
+char(o,64373).
+char(p,64374).
+char(7,64375).
+char(8,64376).
+char(1,64377).
+char(2,64378).
+char(c,64379).
+char(c,64380).
+char(m,64381).
+char(o,64382).
+char(p,64383).
+char(2,64384).
+char(8,64385).
+char(3,64386).
+char(m,64387).
+char(o,64388).
+char(p,64389).
+char(o,64390).
+char(p,64391).
+char(o,64392).
+char(m,64393).
+char(o,64394).
+char(p,64395).
+char(o,64396).
+char(m,64397).
+char(o,64398).
+char(5,64399).
+char(2,64400).
+char(3,64401).
+char(4,64402).
+char(c,64403).
+char(c,64404).
+char(m,64405).
+char(o,64406).
+char(o,64407).
+char(m,64408).
+char(9,64409).
+char(4,64410).
+char(9,64411).
+char(5,64412).
+char(c,64413).
+char(c,64414).
+char(p,64415).
+char(7,64416).
+char(6,64417).
+char(0,64418).
+char(9,64419).
+char(c,64420).
+char(p,64421).
+char(o,64422).
+char(8,64423).
+char(5,64424).
+char(7,64425).
+char(3,64426).
+char(m,64427).
+char(o,64428).
+char(p,64429).
+char(o,64430).
+char(m,64431).
+char(o,64432).
+char(m,64433).
+char(7,64434).
+char(8,64435).
+char(5,64436).
+char(c,64437).
+char(c,64438).
+char(c,64439).
+char(m,64440).
+char(6,64441).
+char(1,64442).
+char(0,64443).
+char(9,64444).
+char(m,64445).
+char(4,64446).
+char(3,64447).
+char(9,64448).
+char(6,64449).
+char(c,64450).
+char(m,64451).
+char(3,64452).
+char(6,64453).
+char(4,64454).
+char(6,64455).
+char(m,64456).
+char(o,64457).
+char(p,64458).
+char(9,64459).
+char(6,64460).
+char(6,64461).
+char(2,64462).
+char(c,64463).
+char(m,64464).
+char(3,64465).
+char(2,64466).
+char(0,64467).
+char(9,64468).
+char(p,64469).
+char(o,64470).
+char(m,64471).
+char(o,64472).
+char(o,64473).
+char(m,64474).
+char(o,64475).
+char(o,64476).
+char(m,64477).
+char(7,64478).
+char(4,64479).
+char(8,64480).
+char(4,64481).
+char(m,64482).
+char(4,64483).
+char(1,64484).
+char(5,64485).
+char(5,64486).
+char(c,64487).
+char(c,64488).
+char(p,64489).
+char(7,64490).
+char(5,64491).
+char(6,64492).
+char(8,64493).
+char(c,64494).
+char(p,64495).
+char(6,64496).
+char(7,64497).
+char(7,64498).
+char(9,64499).
+char(p,64500).
+char(o,64501).
+char(p,64502).
+char(7,64503).
+char(7,64504).
+char(7,64505).
+char(p,64506).
+char(2,64507).
+char(1,64508).
+char(3,64509).
+char(5,64510).
+char(c,64511).
+char(p,64512).
+char(o,64513).
+char(o,64514).
+char(o,64515).
+char(p,64516).
+char(7,64517).
+char(8,64518).
+char(5,64519).
+char(6,64520).
+char(p,64521).
+char(6,64522).
+char(0,64523).
+char(7,64524).
+char(4,64525).
+char(c,64526).
+char(p,64527).
+char(o,64528).
+char(p,64529).
+char(o,64530).
+char(3,64531).
+char(8,64532).
+char(1,64533).
+char(4,64534).
+char(c,64535).
+char(c,64536).
+char(m,64537).
+char(1,64538).
+char(4,64539).
+char(5,64540).
+char(4,64541).
+char(c,64542).
+char(m,64543).
+char(6,64544).
+char(2,64545).
+char(6,64546).
+char(0,64547).
+char(m,64548).
+char(o,64549).
+char(p,64550).
+char(o,64551).
+char(p,64552).
+char(o,64553).
+char(p,64554).
+char(6,64555).
+char(7,64556).
+char(1,64557).
+char(9,64558).
+char(c,64559).
+char(c,64560).
+char(c,64561).
+char(c,64562).
+char(c,64563).
+char(c,64564).
+char(c,64565).
+char(m,64566).
+char(4,64567).
+char(4,64568).
+char(6,64569).
+char(8,64570).
+char(c,64571).
+char(c,64572).
+char(c,64573).
+char(m,64574).
+char(3,64575).
+char(9,64576).
+char(4,64577).
+char(6,64578).
+char(m,64579).
+char(1,64580).
+char(3,64581).
+char(2,64582).
+char(2,64583).
+char(c,64584).
+char(p,64585).
+char(o,64586).
+char(o,64587).
+char(p,64588).
+char(4,64589).
+char(9,64590).
+char(8,64591).
+char(c,64592).
+char(p,64593).
+char(4,64594).
+char(6,64595).
+char(5,64596).
+char(6,64597).
+char(m,64598).
+char(4,64599).
+char(4,64600).
+char(0,64601).
+char(7,64602).
+char(c,64603).
+char(m,64604).
+char(o,64605).
+char(m,64606).
+char(o,64607).
+char(m,64608).
+char(4,64609).
+char(2,64610).
+char(5,64611).
+char(9,64612).
+char(c,64613).
+char(c,64614).
+char(c,64615).
+char(p,64616).
+char(o,64617).
+char(p,64618).
+char(9,64619).
+char(4,64620).
+char(6,64621).
+char(6,64622).
+char(c,64623).
+char(c,64624).
+char(c,64625).
+char(c,64626).
+char(c,64627).
+char(m,64628).
+char(8,64629).
+char(7,64630).
+char(1,64631).
+char(9,64632).
+char(c,64633).
+char(m,64634).
+char(4,64635).
+char(1,64636).
+char(9,64637).
+char(4,64638).
+char(c,64639).
+char(m,64640).
+char(o,64641).
+char(o,64642).
+char(3,64643).
+char(4,64644).
+char(4,64645).
+char(5,64646).
+char(m,64647).
+char(o,64648).
+char(o,64649).
+char(p,64650).
+char(7,64651).
+char(6,64652).
+char(0,64653).
+char(9,64654).
+char(m,64655).
+char(7,64656).
+char(3,64657).
+char(5,64658).
+char(9,64659).
+char(c,64660).
+char(p,64661).
+char(7,64662).
+char(6,64663).
+char(1,64664).
+char(3,64665).
+char(m,64666).
+char(3,64667).
+char(5,64668).
+char(7,64669).
+char(0,64670).
+char(c,64671).
+char(c,64672).
+char(p,64673).
+char(3,64674).
+char(1,64675).
+char(c,64676).
+char(m,64677).
+char(o,64678).
+char(8,64679).
+char(2,64680).
+char(1,64681).
+char(6,64682).
+char(m,64683).
+char(3,64684).
+char(0,64685).
+char(3,64686).
+char(c,64687).
+char(m,64688).
+char(o,64689).
+char(o,64690).
+char(p,64691).
+char(o,64692).
+char(m,64693).
+char(1,64694).
+char(1,64695).
+char(5,64696).
+char(6,64697).
+char(c,64698).
+char(c,64699).
+char(c,64700).
+char(m,64701).
+char(o,64702).
+char(p,64703).
+char(o,64704).
+char(p,64705).
+char(o,64706).
+char(o,64707).
+char(p,64708).
+char(o,64709).
+char(m,64710).
+char(o,64711).
+char(m,64712).
+char(8,64713).
+char(1,64714).
+char(1,64715).
+char(2,64716).
+char(m,64717).
+char(o,64718).
+char(m,64719).
+char(1,64720).
+char(3,64721).
+char(6,64722).
+char(3,64723).
+char(c,64724).
+char(c,64725).
+char(c,64726).
+char(m,64727).
+char(o,64728).
+char(o,64729).
+char(5,64730).
+char(0,64731).
+char(8,64732).
+char(2,64733).
+char(c,64734).
+char(m,64735).
+char(3,64736).
+char(5,64737).
+char(5,64738).
+char(9,64739).
+char(c,64740).
+char(c,64741).
+char(m,64742).
+char(4,64743).
+char(2,64744).
+char(2,64745).
+char(8,64746).
+char(c,64747).
+char(c,64748).
+char(c,64749).
+char(c,64750).
+char(c,64751).
+char(c,64752).
+char(c,64753).
+char(m,64754).
+char(o,64755).
+char(p,64756).
+char(4,64757).
+char(4,64758).
+char(0,64759).
+char(0,64760).
+char(m,64761).
+char(6,64762).
+char(3,64763).
+char(m,64764).
+char(3,64765).
+char(7,64766).
+char(5,64767).
+char(p,64768).
+char(o,64769).
+char(2,64770).
+char(4,64771).
+char(7,64772).
+char(5,64773).
+char(m,64774).
+char(3,64775).
+char(3,64776).
+char(5,64777).
+char(3,64778).
+char(c,64779).
+char(m,64780).
+char(1,64781).
+char(1,64782).
+char(8,64783).
+char(3,64784).
+char(p,64785).
+char(7,64786).
+char(6,64787).
+char(9,64788).
+char(1,64789).
+char(c,64790).
+char(c,64791).
+char(c,64792).
+char(c,64793).
+char(m,64794).
+char(9,64795).
+char(9,64796).
+char(8,64797).
+char(2,64798).
+char(m,64799).
+char(5,64800).
+char(8,64801).
+char(0,64802).
+char(3,64803).
+char(m,64804).
+char(o,64805).
+char(5,64806).
+char(3,64807).
+char(3,64808).
+char(9,64809).
+char(c,64810).
+char(m,64811).
+char(2,64812).
+char(8,64813).
+char(0,64814).
+char(9,64815).
+char(p,64816).
+char(1,64817).
+char(1,64818).
+char(2,64819).
+char(6,64820).
+char(p,64821).
+char(o,64822).
+char(p,64823).
+char(o,64824).
+char(o,64825).
+char(o,64826).
+char(o,64827).
+char(p,64828).
+char(o,64829).
+char(m,64830).
+char(2,64831).
+char(8,64832).
+char(4,64833).
+char(9,64834).
+char(c,64835).
+char(c,64836).
+char(c,64837).
+char(c,64838).
+char(m,64839).
+char(2,64840).
+char(5,64841).
+char(9,64842).
+char(9,64843).
+char(m,64844).
+char(6,64845).
+char(5,64846).
+char(6,64847).
+char(5,64848).
+char(m,64849).
+char(3,64850).
+char(4,64851).
+char(8,64852).
+char(7,64853).
+char(c,64854).
+char(c,64855).
+char(p,64856).
+char(o,64857).
+char(o,64858).
+char(m,64859).
+char(o,64860).
+char(m,64861).
+char(o,64862).
+char(p,64863).
+char(o,64864).
+char(3,64865).
+char(5,64866).
+char(8,64867).
+char(6,64868).
+char(c,64869).
+char(p,64870).
+char(o,64871).
+char(m,64872).
+char(o,64873).
+char(p,64874).
+char(o,64875).
+char(4,64876).
+char(9,64877).
+char(8,64878).
+char(2,64879).
+char(m,64880).
+char(o,64881).
+char(m,64882).
+char(2,64883).
+char(4,64884).
+char(8,64885).
+char(7,64886).
+char(m,64887).
+char(7,64888).
+char(2,64889).
+char(p,64890).
+char(o,64891).
+char(8,64892).
+char(6,64893).
+char(9,64894).
+char(3,64895).
+char(m,64896).
+char(9,64897).
+char(8,64898).
+char(9,64899).
+char(3,64900).
+char(c,64901).
+char(c,64902).
+char(c,64903).
+char(p,64904).
+char(o,64905).
+char(9,64906).
+char(8,64907).
+char(8,64908).
+char(2,64909).
+char(p,64910).
+char(o,64911).
+char(o,64912).
+char(p,64913).
+char(o,64914).
+char(m,64915).
+char(o,64916).
+char(8,64917).
+char(0,64918).
+char(6,64919).
+char(6,64920).
+char(c,64921).
+char(c,64922).
+char(m,64923).
+char(o,64924).
+char(m,64925).
+char(4,64926).
+char(6,64927).
+char(5,64928).
+char(1,64929).
+char(p,64930).
+char(9,64931).
+char(9,64932).
+char(2,64933).
+char(4,64934).
+char(m,64935).
+char(o,64936).
+char(5,64937).
+char(2,64938).
+char(8,64939).
+char(m,64940).
+char(6,64941).
+char(8,64942).
+char(0,64943).
+char(m,64944).
+char(o,64945).
+char(o,64946).
+char(m,64947).
+char(o,64948).
+char(m,64949).
+char(6,64950).
+char(0,64951).
+char(8,64952).
+char(3,64953).
+char(m,64954).
+char(1,64955).
+char(7,64956).
+char(3,64957).
+char(p,64958).
+char(6,64959).
+char(1,64960).
+char(0,64961).
+char(6,64962).
+char(c,64963).
+char(c,64964).
+char(p,64965).
+char(o,64966).
+char(m,64967).
+char(8,64968).
+char(7,64969).
+char(2,64970).
+char(3,64971).
+char(p,64972).
+char(o,64973).
+char(p,64974).
+char(o,64975).
+char(p,64976).
+char(4,64977).
+char(1,64978).
+char(2,64979).
+char(7,64980).
+char(c,64981).
+char(p,64982).
+char(5,64983).
+char(5,64984).
+char(6,64985).
+char(2,64986).
+char(p,64987).
+char(o,64988).
+char(p,64989).
+char(8,64990).
+char(4,64991).
+char(7,64992).
+char(9,64993).
+char(c,64994).
+char(m,64995).
+char(4,64996).
+char(6,64997).
+char(1,64998).
+char(9,64999).
+char(m,65000).
+char(o,65001).
+char(7,65002).
+char(7,65003).
+char(2,65004).
+char(2,65005).
+char(c,65006).
+char(c,65007).
+char(c,65008).
+char(c,65009).
+char(m,65010).
+char(o,65011).
+char(m,65012).
+char(8,65013).
+char(4,65014).
+char(2,65015).
+char(c,65016).
+char(p,65017).
+char(4,65018).
+char(8,65019).
+char(4,65020).
+char(8,65021).
+char(p,65022).
+char(o,65023).
+char(1,65024).
+char(6,65025).
+char(9,65026).
+char(1,65027).
+char(p,65028).
+char(o,65029).
+char(o,65030).
+char(o,65031).
+char(m,65032).
+char(1,65033).
+char(9,65034).
+char(2,65035).
+char(9,65036).
+char(m,65037).
+char(o,65038).
+char(p,65039).
+char(o,65040).
+char(p,65041).
+char(o,65042).
+char(o,65043).
+char(2,65044).
+char(9,65045).
+char(9,65046).
+char(1,65047).
+char(p,65048).
+char(o,65049).
+char(p,65050).
+char(4,65051).
+char(6,65052).
+char(9,65053).
+char(5,65054).
+char(m,65055).
+char(o,65056).
+char(p,65057).
+char(o,65058).
+char(p,65059).
+char(6,65060).
+char(1,65061).
+char(4,65062).
+char(6,65063).
+char(c,65064).
+char(c,65065).
+char(p,65066).
+char(o,65067).
+char(p,65068).
+char(3,65069).
+char(1,65070).
+char(8,65071).
+char(6,65072).
+char(m,65073).
+char(8,65074).
+char(3,65075).
+char(6,65076).
+char(0,65077).
+char(c,65078).
+char(p,65079).
+char(3,65080).
+char(9,65081).
+char(1,65082).
+char(6,65083).
+char(c,65084).
+char(c,65085).
+char(p,65086).
+char(o,65087).
+char(m,65088).
+char(o,65089).
+char(p,65090).
+char(4,65091).
+char(1,65092).
+char(2,65093).
+char(5,65094).
+char(p,65095).
+char(o,65096).
+char(p,65097).
+char(3,65098).
+char(2,65099).
+char(6,65100).
+char(c,65101).
+char(c,65102).
+char(c,65103).
+char(m,65104).
+char(2,65105).
+char(1,65106).
+char(3,65107).
+char(1,65108).
+char(p,65109).
+char(7,65110).
+char(0,65111).
+char(6,65112).
+char(2,65113).
+char(p,65114).
+char(o,65115).
+char(m,65116).
+char(8,65117).
+char(4,65118).
+char(4,65119).
+char(2,65120).
+char(c,65121).
+char(m,65122).
+char(6,65123).
+char(4,65124).
+char(2,65125).
+char(5,65126).
+char(c,65127).
+char(p,65128).
+char(o,65129).
+char(o,65130).
+char(p,65131).
+char(5,65132).
+char(7,65133).
+char(1,65134).
+char(3,65135).
+char(m,65136).
+char(o,65137).
+char(o,65138).
+char(4,65139).
+char(5,65140).
+char(1,65141).
+char(9,65142).
+char(c,65143).
+char(c,65144).
+char(c,65145).
+char(m,65146).
+char(o,65147).
+char(p,65148).
+char(o,65149).
+char(m,65150).
+char(4,65151).
+char(4,65152).
+char(2,65153).
+char(4,65154).
+char(c,65155).
+char(p,65156).
+char(o,65157).
+char(o,65158).
+char(o,65159).
+char(m,65160).
+char(5,65161).
+char(8,65162).
+char(3,65163).
+char(5,65164).
+char(m,65165).
+char(4,65166).
+char(3,65167).
+char(3,65168).
+char(3,65169).
+char(p,65170).
+char(5,65171).
+char(2,65172).
+char(5,65173).
+char(2,65174).
+char(c,65175).
+char(m,65176).
+char(o,65177).
+char(m,65178).
+char(o,65179).
+char(o,65180).
+char(m,65181).
+char(o,65182).
+char(m,65183).
+char(o,65184).
+char(m,65185).
+char(7,65186).
+char(6,65187).
+char(3,65188).
+char(2,65189).
+char(p,65190).
+char(o,65191).
+char(p,65192).
+char(5,65193).
+char(0,65194).
+char(6,65195).
+char(7,65196).
+char(c,65197).
+char(p,65198).
+char(o,65199).
+char(o,65200).
+char(p,65201).
+char(o,65202).
+char(p,65203).
+char(o,65204).
+char(p,65205).
+char(o,65206).
+char(p,65207).
+char(o,65208).
+char(m,65209).
+char(o,65210).
+char(o,65211).
+char(p,65212).
+char(o,65213).
+char(m,65214).
+char(o,65215).
+char(m,65216).
+char(2,65217).
+char(4,65218).
+char(2,65219).
+char(5,65220).
+char(c,65221).
+char(p,65222).
+char(o,65223).
+char(p,65224).
+char(6,65225).
+char(0,65226).
+char(0,65227).
+char(2,65228).
+char(c,65229).
+char(c,65230).
+char(c,65231).
+char(p,65232).
+char(9,65233).
+char(3,65234).
+char(4,65235).
+char(8,65236).
+char(m,65237).
+char(o,65238).
+char(m,65239).
+char(3,65240).
+char(3,65241).
+char(9,65242).
+char(2,65243).
+char(m,65244).
+char(o,65245).
+char(p,65246).
+char(9,65247).
+char(0,65248).
+char(9,65249).
+char(3,65250).
+char(c,65251).
+char(c,65252).
+char(c,65253).
+char(c,65254).
+char(c,65255).
+char(c,65256).
+char(m,65257).
+char(3,65258).
+char(6,65259).
+char(8,65260).
+char(9,65261).
+char(c,65262).
+char(c,65263).
+char(c,65264).
+char(m,65265).
+char(2,65266).
+char(9,65267).
+char(4,65268).
+char(0,65269).
+char(c,65270).
+char(m,65271).
+char(o,65272).
+char(o,65273).
+char(9,65274).
+char(9,65275).
+char(1,65276).
+char(5,65277).
+char(m,65278).
+char(o,65279).
+char(o,65280).
+char(m,65281).
+char(o,65282).
+char(p,65283).
+char(o,65284).
+char(p,65285).
+char(o,65286).
+char(2,65287).
+char(3,65288).
+char(3,65289).
+char(6,65290).
+char(p,65291).
+char(8,65292).
+char(6,65293).
+char(6,65294).
+char(3,65295).
+char(m,65296).
+char(o,65297).
+char(m,65298).
+char(5,65299).
+char(5,65300).
+char(0,65301).
+char(0,65302).
+char(m,65303).
+char(8,65304).
+char(3,65305).
+char(2,65306).
+char(c,65307).
+char(p,65308).
+char(o,65309).
+char(1,65310).
+char(1,65311).
+char(4,65312).
+char(3,65313).
+char(m,65314).
+char(8,65315).
+char(6,65316).
+char(0,65317).
+char(5,65318).
+char(c,65319).
+char(m,65320).
+char(7,65321).
+char(4,65322).
+char(1,65323).
+char(c,65324).
+char(m,65325).
+char(2,65326).
+char(4,65327).
+char(0,65328).
+char(8,65329).
+char(p,65330).
+char(o,65331).
+char(m,65332).
+char(o,65333).
+char(m,65334).
+char(7,65335).
+char(8,65336).
+char(5,65337).
+char(7,65338).
+char(m,65339).
+char(o,65340).
+char(m,65341).
+char(3,65342).
+char(2,65343).
+char(0,65344).
+char(2,65345).
+char(c,65346).
+char(c,65347).
+char(m,65348).
+char(o,65349).
+char(p,65350).
+char(o,65351).
+char(p,65352).
+char(o,65353).
+char(o,65354).
+char(4,65355).
+char(0,65356).
+char(9,65357).
+char(5,65358).
+char(m,65359).
+char(8,65360).
+char(6,65361).
+char(4,65362).
+char(8,65363).
+char(c,65364).
+char(p,65365).
+char(o,65366).
+char(4,65367).
+char(0,65368).
+char(0,65369).
+char(c,65370).
+char(c,65371).
+char(c,65372).
+char(c,65373).
+char(c,65374).
+char(m,65375).
+char(o,65376).
+char(p,65377).
+char(o,65378).
+char(p,65379).
+char(8,65380).
+char(7,65381).
+char(5,65382).
+char(1,65383).
+char(m,65384).
+char(o,65385).
+char(m,65386).
+char(4,65387).
+char(1,65388).
+char(9,65389).
+char(9,65390).
+char(c,65391).
+char(c,65392).
+char(c,65393).
+char(m,65394).
+char(3,65395).
+char(8,65396).
+char(1,65397).
+char(4,65398).
+char(c,65399).
+char(c,65400).
+char(m,65401).
+char(2,65402).
+char(2,65403).
+char(c,65404).
+char(c,65405).
+char(p,65406).
+char(1,65407).
+char(2,65408).
+char(3,65409).
+char(c,65410).
+char(c,65411).
+char(c,65412).
+char(p,65413).
+char(3,65414).
+char(6,65415).
+char(6,65416).
+char(5,65417).
+char(c,65418).
+char(c,65419).
+char(c,65420).
+char(c,65421).
+char(c,65422).
+char(m,65423).
+char(o,65424).
+char(o,65425).
+char(m,65426).
+char(o,65427).
+char(p,65428).
+char(o,65429).
+char(m,65430).
+char(o,65431).
+char(m,65432).
+char(8,65433).
+char(8,65434).
+char(8,65435).
+char(4,65436).
+char(c,65437).
+char(p,65438).
+char(o,65439).
+char(m,65440).
+char(o,65441).
+char(o,65442).
+char(o,65443).
+char(6,65444).
+char(4,65445).
+char(1,65446).
+char(c,65447).
+char(p,65448).
+char(o,65449).
+char(o,65450).
+char(4,65451).
+char(3,65452).
+char(8,65453).
+char(4,65454).
+char(p,65455).
+char(8,65456).
+char(4,65457).
+char(2,65458).
+char(6,65459).
+char(c,65460).
+char(p,65461).
+char(8,65462).
+char(4,65463).
+char(8,65464).
+char(7,65465).
+char(c,65466).
+char(c,65467).
+char(m,65468).
+char(o,65469).
+char(m,65470).
+char(o,65471).
+char(o,65472).
+char(p,65473).
+char(o,65474).
+char(m,65475).
+char(8,65476).
+char(5,65477).
+char(3,65478).
+char(3,65479).
+char(c,65480).
+char(p,65481).
+char(9,65482).
+char(5,65483).
+char(0,65484).
+char(4,65485).
+char(p,65486).
+char(o,65487).
+char(m,65488).
+char(7,65489).
+char(3,65490).
+char(5,65491).
+char(c,65492).
+char(c,65493).
+char(c,65494).
+char(p,65495).
+char(o,65496).
+char(p,65497).
+char(o,65498).
+char(3,65499).
+char(6,65500).
+char(0,65501).
+char(7,65502).
+char(p,65503).
+char(o,65504).
+char(p,65505).
+char(o,65506).
+char(p,65507).
+char(o,65508).
+char(m,65509).
+char(o,65510).
+char(m,65511).
+char(o,65512).
+char(m,65513).
+char(5,65514).
+char(0,65515).
+char(4,65516).
+char(9,65517).
+char(p,65518).
+char(o,65519).
+char(o,65520).
+char(m,65521).
+char(1,65522).
+char(7,65523).
+char(5,65524).
+char(8,65525).
+char(m,65526).
+char(o,65527).
+char(o,65528).
+char(8,65529).
+char(9,65530).
+char(2,65531).
+char(1,65532).
+char(c,65533).
+char(c,65534).
+char(p,65535).
+char(o,65536).
+char(m,65537).
+char(o,65538).
+char(m,65539).
+char(4,65540).
+char(8,65541).
+char(6,65542).
+char(4,65543).
+char(c,65544).
+char(p,65545).
+char(o,65546).
+char(7,65547).
+char(0,65548).
+char(4,65549).
+char(8,65550).
+char(p,65551).
+char(5,65552).
+char(4,65553).
+char(8,65554).
+char(7,65555).
+char(m,65556).
+char(o,65557).
+char(m,65558).
+char(o,65559).
+char(8,65560).
+char(5,65561).
+char(0,65562).
+char(7,65563).
+char(c,65564).
+char(p,65565).
+char(6,65566).
+char(0,65567).
+char(0,65568).
+char(0,65569).
+char(c,65570).
+char(c,65571).
+char(p,65572).
+char(4,65573).
+char(3,65574).
+char(0,65575).
+char(9,65576).
+char(m,65577).
+char(o,65578).
+char(p,65579).
+char(o,65580).
+char(p,65581).
+char(o,65582).
+char(o,65583).
+char(o,65584).
+char(3,65585).
+char(0,65586).
+char(4,65587).
+char(6,65588).
+char(m,65589).
+char(4,65590).
+char(p,65591).
+char(4,65592).
+char(1,65593).
+char(7,65594).
+char(7,65595).
+char(c,65596).
+char(p,65597).
+char(4,65598).
+char(9,65599).
+char(3,65600).
+char(2,65601).
+char(m,65602).
+char(o,65603).
+char(m,65604).
+char(8,65605).
+char(6,65606).
+char(6,65607).
+char(2,65608).
+char(c,65609).
+char(c,65610).
+char(p,65611).
+char(1,65612).
+char(2,65613).
+char(3,65614).
+char(3,65615).
+char(c,65616).
+char(m,65617).
+char(o,65618).
+char(p,65619).
+char(8,65620).
+char(3,65621).
+char(9,65622).
+char(m,65623).
+char(8,65624).
+char(9,65625).
+char(1,65626).
+char(0,65627).
+char(c,65628).
+char(p,65629).
+char(o,65630).
+char(p,65631).
+char(9,65632).
+char(9,65633).
+char(9,65634).
+char(3,65635).
+char(c,65636).
+char(c,65637).
+char(m,65638).
+char(o,65639).
+char(m,65640).
+char(5,65641).
+char(9,65642).
+char(4,65643).
+char(5,65644).
+char(p,65645).
+char(o,65646).
+char(o,65647).
+char(m,65648).
+char(8,65649).
+char(7,65650).
+char(3,65651).
+char(6,65652).
+char(p,65653).
+char(2,65654).
+char(6,65655).
+char(7,65656).
+char(4,65657).
+char(c,65658).
+char(c,65659).
+char(p,65660).
+char(7,65661).
+char(9,65662).
+char(4,65663).
+char(5,65664).
+char(m,65665).
+char(o,65666).
+char(7,65667).
+char(5,65668).
+char(9,65669).
+char(6,65670).
+char(m,65671).
+char(8,65672).
+char(8,65673).
+char(1,65674).
+char(6,65675).
+char(m,65676).
+char(9,65677).
+char(7,65678).
+char(4,65679).
+char(8,65680).
+char(m,65681).
+char(o,65682).
+char(o,65683).
+char(m,65684).
+char(5,65685).
+char(2,65686).
+char(7,65687).
+char(2,65688).
+char(c,65689).
+char(c,65690).
+char(c,65691).
+char(c,65692).
+char(m,65693).
+char(o,65694).
+char(m,65695).
+char(o,65696).
+char(8,65697).
+char(6,65698).
+char(5,65699).
+char(2,65700).
+char(c,65701).
+char(c,65702).
+char(c,65703).
+char(p,65704).
+char(o,65705).
+char(4,65706).
+char(1,65707).
+char(3,65708).
+char(2,65709).
+char(p,65710).
+char(o,65711).
+char(p,65712).
+char(1,65713).
+char(2,65714).
+char(6,65715).
+char(3,65716).
+char(m,65717).
+char(o,65718).
+char(7,65719).
+char(8,65720).
+char(2,65721).
+char(c,65722).
+char(c,65723).
+char(c,65724).
+char(m,65725).
+char(o,65726).
+char(5,65727).
+char(6,65728).
+char(7,65729).
+char(3,65730).
+char(m,65731).
+char(2,65732).
+char(1,65733).
+char(4,65734).
+char(2,65735).
+char(p,65736).
+char(o,65737).
+char(6,65738).
+char(3,65739).
+char(m,65740).
+char(o,65741).
+char(o,65742).
+char(5,65743).
+char(2,65744).
+char(0,65745).
+char(1,65746).
+char(m,65747).
+char(9,65748).
+char(4,65749).
+char(3,65750).
+char(2,65751).
+char(c,65752).
+char(c,65753).
+char(p,65754).
+char(2,65755).
+char(1,65756).
+char(6,65757).
+char(2,65758).
+char(c,65759).
+char(m,65760).
+char(9,65761).
+char(7,65762).
+char(3,65763).
+char(8,65764).
+char(m,65765).
+char(5,65766).
+char(2,65767).
+char(8,65768).
+char(4,65769).
+char(m,65770).
+char(o,65771).
+char(p,65772).
+char(o,65773).
+char(p,65774).
+char(2,65775).
+char(4,65776).
+char(5,65777).
+char(7,65778).
+char(m,65779).
+char(o,65780).
+char(m,65781).
+char(9,65782).
+char(2,65783).
+char(7,65784).
+char(0,65785).
+char(p,65786).
+char(7,65787).
+char(3,65788).
+char(3,65789).
+char(1,65790).
+char(c,65791).
+char(c,65792).
+char(m,65793).
+char(8,65794).
+char(4,65795).
+char(0,65796).
+char(8,65797).
+char(c,65798).
+char(m,65799).
+char(o,65800).
+char(5,65801).
+char(1,65802).
+char(2,65803).
+char(6,65804).
+char(m,65805).
+char(4,65806).
+char(4,65807).
+char(2,65808).
+char(0,65809).
+char(m,65810).
+char(4,65811).
+char(3,65812).
+char(2,65813).
+char(2,65814).
+char(m,65815).
+char(5,65816).
+char(9,65817).
+char(3,65818).
+char(9,65819).
+char(p,65820).
+char(8,65821).
+char(1,65822).
+char(0,65823).
+char(c,65824).
+char(c,65825).
+char(m,65826).
+char(o,65827).
+char(m,65828).
+char(6,65829).
+char(5,65830).
+char(8,65831).
+char(5,65832).
+char(p,65833).
+char(o,65834).
+char(p,65835).
+char(o,65836).
+char(m,65837).
+char(8,65838).
+char(8,65839).
+char(4,65840).
+char(6,65841).
+char(c,65842).
+char(c,65843).
+char(c,65844).
+char(c,65845).
+char(m,65846).
+char(o,65847).
+char(1,65848).
+char(6,65849).
+char(8,65850).
+char(c,65851).
+char(c,65852).
+char(c,65853).
+char(m,65854).
+char(o,65855).
+char(m,65856).
+char(9,65857).
+char(1,65858).
+char(1,65859).
+char(3,65860).
+char(c,65861).
+char(c,65862).
+char(p,65863).
+char(2,65864).
+char(5,65865).
+char(3,65866).
+char(4,65867).
+char(c,65868).
+char(m,65869).
+char(o,65870).
+char(p,65871).
+char(o,65872).
+char(p,65873).
+char(o,65874).
+char(p,65875).
+char(5,65876).
+char(1,65877).
+char(1,65878).
+char(1,65879).
+char(m,65880).
+char(2,65881).
+char(3,65882).
+char(6,65883).
+char(2,65884).
+char(m,65885).
+char(5,65886).
+char(7,65887).
+char(8,65888).
+char(7,65889).
+char(m,65890).
+char(o,65891).
+char(p,65892).
+char(o,65893).
+char(p,65894).
+char(3,65895).
+char(1,65896).
+char(7,65897).
+char(4,65898).
+char(p,65899).
+char(2,65900).
+char(8,65901).
+char(1,65902).
+char(p,65903).
+char(2,65904).
+char(3,65905).
+char(2,65906).
+char(5,65907).
+char(m,65908).
+char(o,65909).
+char(p,65910).
+char(4,65911).
+char(9,65912).
+char(5,65913).
+char(1,65914).
+char(p,65915).
+char(o,65916).
+char(m,65917).
+char(o,65918).
+char(p,65919).
+char(o,65920).
+char(m,65921).
+char(9,65922).
+char(2,65923).
+char(7,65924).
+char(4,65925).
+char(p,65926).
+char(7,65927).
+char(4,65928).
+char(3,65929).
+char(5,65930).
+char(p,65931).
+char(8,65932).
+char(5,65933).
+char(4,65934).
+char(4,65935).
+char(p,65936).
+char(5,65937).
+char(8,65938).
+char(8,65939).
+char(0,65940).
+char(m,65941).
+char(o,65942).
+char(p,65943).
+char(o,65944).
+char(o,65945).
+char(p,65946).
+char(9,65947).
+char(3,65948).
+char(2,65949).
+char(4,65950).
+char(c,65951).
+char(c,65952).
+char(m,65953).
+char(o,65954).
+char(o,65955).
+char(1,65956).
+char(3,65957).
+char(6,65958).
+char(0,65959).
+char(c,65960).
+char(c,65961).
+char(c,65962).
+char(m,65963).
+char(o,65964).
+char(2,65965).
+char(6,65966).
+char(7,65967).
+char(5,65968).
+char(c,65969).
+char(c,65970).
+char(c,65971).
+char(p,65972).
+char(o,65973).
+char(p,65974).
+char(o,65975).
+char(p,65976).
+char(4,65977).
+char(6,65978).
+char(2,65979).
+char(1,65980).
+char(m,65981).
+char(7,65982).
+char(7,65983).
+char(0,65984).
+char(7,65985).
+char(c,65986).
+char(c,65987).
+char(c,65988).
+char(m,65989).
+char(2,65990).
+char(9,65991).
+char(5,65992).
+char(2,65993).
+char(c,65994).
+char(p,65995).
+char(o,65996).
+char(m,65997).
+char(o,65998).
+char(m,65999).
+char(o,66000).
+char(p,66001).
+char(6,66002).
+char(3,66003).
+char(7,66004).
+char(8,66005).
+char(p,66006).
+char(4,66007).
+char(4,66008).
+char(9,66009).
+char(8,66010).
+char(m,66011).
+char(o,66012).
+char(p,66013).
+char(9,66014).
+char(4,66015).
+char(0,66016).
+char(1,66017).
+char(p,66018).
+char(o,66019).
+char(p,66020).
+char(8,66021).
+char(8,66022).
+char(5,66023).
+char(0,66024).
+char(m,66025).
+char(o,66026).
+char(3,66027).
+char(2,66028).
+char(0,66029).
+char(c,66030).
+char(p,66031).
+char(1,66032).
+char(9,66033).
+char(4,66034).
+char(9,66035).
+char(p,66036).
+char(9,66037).
+char(4,66038).
+char(4,66039).
+char(4,66040).
+char(p,66041).
+char(o,66042).
+char(m,66043).
+char(6,66044).
+char(7,66045).
+char(6,66046).
+char(2,66047).
+char(m,66048).
+char(o,66049).
+char(p,66050).
+char(o,66051).
+char(m,66052).
+char(o,66053).
+char(m,66054).
+char(5,66055).
+char(3,66056).
+char(8,66057).
+char(6,66058).
+char(c,66059).
+char(p,66060).
+char(8,66061).
+char(0,66062).
+char(6,66063).
+char(4,66064).
+char(p,66065).
+char(7,66066).
+char(8,66067).
+char(5,66068).
+char(9,66069).
+char(c,66070).
+char(c,66071).
+char(p,66072).
+char(o,66073).
+char(6,66074).
+char(8,66075).
+char(7,66076).
+char(2,66077).
+char(c,66078).
+char(m,66079).
+char(o,66080).
+char(2,66081).
+char(2,66082).
+char(6,66083).
+char(6,66084).
+char(c,66085).
+char(c,66086).
+char(c,66087).
+char(m,66088).
+char(o,66089).
+char(o,66090).
+char(3,66091).
+char(3,66092).
+char(3,66093).
+char(4,66094).
+char(c,66095).
+char(c,66096).
+char(m,66097).
+char(2,66098).
+char(1,66099).
+char(3,66100).
+char(6,66101).
+char(m,66102).
+char(8,66103).
+char(2,66104).
+char(6,66105).
+char(c,66106).
+char(c,66107).
+char(p,66108).
+char(o,66109).
+char(o,66110).
+char(3,66111).
+char(5,66112).
+char(6,66113).
+char(8,66114).
+char(p,66115).
+char(8,66116).
+char(4,66117).
+char(8,66118).
+char(2,66119).
+char(c,66120).
+char(c,66121).
+char(m,66122).
+char(o,66123).
+char(m,66124).
+char(o,66125).
+char(5,66126).
+char(2,66127).
+char(1,66128).
+char(0,66129).
+char(m,66130).
+char(1,66131).
+char(7,66132).
+char(2,66133).
+char(5,66134).
+char(c,66135).
+char(p,66136).
+char(o,66137).
+char(p,66138).
+char(o,66139).
+char(6,66140).
+char(7,66141).
+char(8,66142).
+char(3,66143).
+char(m,66144).
+char(o,66145).
+char(m,66146).
+char(o,66147).
+char(p,66148).
+char(6,66149).
+char(2,66150).
+char(6,66151).
+char(0,66152).
+char(c,66153).
+char(p,66154).
+char(5,66155).
+char(0,66156).
+char(5,66157).
+char(5,66158).
+char(c,66159).
+char(p,66160).
+char(o,66161).
+char(p,66162).
+char(o,66163).
+char(1,66164).
+char(9,66165).
+char(6,66166).
+char(c,66167).
+char(c,66168).
+char(m,66169).
+char(o,66170).
+char(p,66171).
+char(8,66172).
+char(7,66173).
+char(1,66174).
+char(9,66175).
+char(c,66176).
+char(c,66177).
+char(c,66178).
+char(c,66179).
+char(c,66180).
+char(c,66181).
+char(m,66182).
+char(9,66183).
+char(5,66184).
+char(6,66185).
+char(6,66186).
+char(c,66187).
+char(p,66188).
+char(o,66189).
+char(o,66190).
+char(p,66191).
+char(o,66192).
+char(m,66193).
+char(3,66194).
+char(1,66195).
+char(4,66196).
+char(2,66197).
+char(c,66198).
+char(p,66199).
+char(2,66200).
+char(0,66201).
+char(4,66202).
+char(6,66203).
+char(m,66204).
+char(o,66205).
+char(7,66206).
+char(1,66207).
+char(7,66208).
+char(8,66209).
+char(c,66210).
+char(c,66211).
+char(c,66212).
+char(m,66213).
+char(5,66214).
+char(5,66215).
+char(2,66216).
+char(9,66217).
+char(c,66218).
+char(p,66219).
+char(o,66220).
+char(m,66221).
+char(9,66222).
+char(4,66223).
+char(8,66224).
+char(6,66225).
+char(c,66226).
+char(m,66227).
+char(7,66228).
+char(0,66229).
+char(0,66230).
+char(1,66231).
+char(c,66232).
+char(c,66233).
+char(c,66234).
+char(c,66235).
+char(p,66236).
+char(o,66237).
+char(p,66238).
+char(5,66239).
+char(3,66240).
+char(3,66241).
+char(p,66242).
+char(o,66243).
+char(m,66244).
+char(o,66245).
+char(p,66246).
+char(o,66247).
+char(o,66248).
+char(m,66249).
+char(1,66250).
+char(6,66251).
+char(9,66252).
+char(0,66253).
+char(c,66254).
+char(p,66255).
+char(4,66256).
+char(0,66257).
+char(8,66258).
+char(3,66259).
+char(p,66260).
+char(o,66261).
+char(p,66262).
+char(6,66263).
+char(2,66264).
+char(5,66265).
+char(3,66266).
+char(m,66267).
+char(o,66268).
+char(m,66269).
+char(2,66270).
+char(0,66271).
+char(6,66272).
+char(2,66273).
+char(c,66274).
+char(p,66275).
+char(3,66276).
+char(2,66277).
+char(1,66278).
+char(5,66279).
+char(m,66280).
+char(8,66281).
+char(9,66282).
+char(1,66283).
+char(5,66284).
+char(p,66285).
+char(2,66286).
+char(2,66287).
+char(8,66288).
+char(8,66289).
+char(c,66290).
+char(c,66291).
+char(c,66292).
+char(m,66293).
+char(o,66294).
+char(1,66295).
+char(8,66296).
+char(8,66297).
+char(1,66298).
+char(c,66299).
+char(c,66300).
+char(c,66301).
+char(c,66302).
+char(c,66303).
+char(m,66304).
+char(5,66305).
+char(2,66306).
+char(4,66307).
+char(9,66308).
+char(m,66309).
+char(o,66310).
+char(o,66311).
+char(m,66312).
+char(3,66313).
+char(2,66314).
+char(9,66315).
+char(7,66316).
+char(m,66317).
+char(o,66318).
+char(o,66319).
+char(m,66320).
+char(o,66321).
+char(p,66322).
+char(o,66323).
+char(m,66324).
+char(o,66325).
+char(1,66326).
+char(2,66327).
+char(0,66328).
+char(9,66329).
+char(p,66330).
+char(o,66331).
+char(m,66332).
+char(o,66333).
+char(8,66334).
+char(5,66335).
+char(4,66336).
+char(p,66337).
+char(o,66338).
+char(p,66339).
+char(o,66340).
+char(p,66341).
+char(5,66342).
+char(3,66343).
+char(9,66344).
+char(5,66345).
+char(m,66346).
+char(7,66347).
+char(2,66348).
+char(6,66349).
+char(4,66350).
+char(c,66351).
+char(m,66352).
+char(o,66353).
+char(o,66354).
+char(6,66355).
+char(8,66356).
+char(2,66357).
+char(6,66358).
+char(c,66359).
+char(c,66360).
+char(p,66361).
+char(o,66362).
+char(2,66363).
+char(9,66364).
+char(8,66365).
+char(4,66366).
+char(p,66367).
+char(o,66368).
+char(m,66369).
+char(3,66370).
+char(0,66371).
+char(9,66372).
+char(m,66373).
+char(5,66374).
+char(3,66375).
+char(6,66376).
+char(3,66377).
+char(p,66378).
+char(o,66379).
+char(p,66380).
+char(o,66381).
+char(m,66382).
+char(8,66383).
+char(7,66384).
+char(8,66385).
+char(8,66386).
+char(m,66387).
+char(3,66388).
+char(8,66389).
+char(3,66390).
+char(1,66391).
+char(c,66392).
+char(p,66393).
+char(o,66394).
+char(m,66395).
+char(o,66396).
+char(m,66397).
+char(3,66398).
+char(8,66399).
+char(9,66400).
+char(1,66401).
+char(m,66402).
+char(5,66403).
+char(0,66404).
+char(8,66405).
+char(3,66406).
+char(m,66407).
+char(o,66408).
+char(p,66409).
+char(7,66410).
+char(3,66411).
+char(5,66412).
+char(1,66413).
+char(p,66414).
+char(o,66415).
+char(p,66416).
+char(o,66417).
+char(p,66418).
+char(o,66419).
+char(m,66420).
+char(1,66421).
+char(6,66422).
+char(1,66423).
+char(8,66424).
+char(c,66425).
+char(c,66426).
+char(m,66427).
+char(o,66428).
+char(p,66429).
+char(o,66430).
+char(p,66431).
+char(o,66432).
+char(m,66433).
+char(o,66434).
+char(m,66435).
+char(o,66436).
+char(m,66437).
+char(o,66438).
+char(6,66439).
+char(0,66440).
+char(6,66441).
+char(1,66442).
+char(c,66443).
+char(c,66444).
+char(c,66445).
+char(p,66446).
+char(3,66447).
+char(0,66448).
+char(2,66449).
+char(4,66450).
+char(c,66451).
+char(m,66452).
+char(o,66453).
+char(3,66454).
+char(4,66455).
+char(5,66456).
+char(1,66457).
+char(m,66458).
+char(9,66459).
+char(4,66460).
+char(4,66461).
+char(8,66462).
+char(c,66463).
+char(p,66464).
+char(6,66465).
+char(7,66466).
+char(5,66467).
+char(1,66468).
+char(p,66469).
+char(o,66470).
+char(p,66471).
+char(o,66472).
+char(m,66473).
+char(o,66474).
+char(m,66475).
+char(o,66476).
+char(o,66477).
+char(o,66478).
+char(8,66479).
+char(5,66480).
+char(0,66481).
+char(1,66482).
+char(c,66483).
+char(p,66484).
+char(o,66485).
+char(m,66486).
+char(o,66487).
+char(m,66488).
+char(4,66489).
+char(8,66490).
+char(3,66491).
+char(9,66492).
+char(c,66493).
+char(c,66494).
+char(c,66495).
+char(m,66496).
+char(o,66497).
+char(o,66498).
+char(p,66499).
+char(9,66500).
+char(5,66501).
+char(6,66502).
+char(4,66503).
+char(m,66504).
+char(9,66505).
+char(1,66506).
+char(1,66507).
+char(5,66508).
+char(c,66509).
+char(m,66510).
+char(8,66511).
+char(0,66512).
+char(4,66513).
+char(2,66514).
+char(c,66515).
+char(m,66516).
+char(o,66517).
+char(p,66518).
+char(o,66519).
+char(3,66520).
+char(7,66521).
+char(7,66522).
+char(c,66523).
+char(c,66524).
+char(m,66525).
+char(9,66526).
+char(3,66527).
+char(6,66528).
+char(8,66529).
+char(m,66530).
+char(o,66531).
+char(p,66532).
+char(o,66533).
+char(p,66534).
+char(o,66535).
+char(o,66536).
+char(7,66537).
+char(0,66538).
+char(5,66539).
+char(3,66540).
+char(c,66541).
+char(p,66542).
+char(o,66543).
+char(o,66544).
+char(o,66545).
+char(o,66546).
+char(p,66547).
+char(o,66548).
+char(p,66549).
+char(o,66550).
+char(m,66551).
+char(8,66552).
+char(5,66553).
+char(4,66554).
+char(7,66555).
+char(c,66556).
+char(m,66557).
+char(5,66558).
+char(2,66559).
+char(9,66560).
+char(5,66561).
+char(c,66562).
+char(c,66563).
+char(c,66564).
+char(c,66565).
+char(p,66566).
+char(o,66567).
+char(o,66568).
+char(6,66569).
+char(4,66570).
+char(7,66571).
+char(3,66572).
+char(c,66573).
+char(p,66574).
+char(o,66575).
+char(p,66576).
+char(o,66577).
+char(o,66578).
+char(p,66579).
+char(o,66580).
+char(m,66581).
+char(o,66582).
+char(m,66583).
+char(o,66584).
+char(m,66585).
+char(o,66586).
+char(5,66587).
+char(3,66588).
+char(0,66589).
+char(0,66590).
+char(p,66591).
+char(o,66592).
+char(m,66593).
+char(o,66594).
+char(p,66595).
+char(o,66596).
+char(1,66597).
+char(3,66598).
+char(7,66599).
+char(3,66600).
+char(c,66601).
+char(m,66602).
+char(o,66603).
+char(p,66604).
+char(3,66605).
+char(2,66606).
+char(9,66607).
+char(1,66608).
+char(c,66609).
+char(p,66610).
+char(6,66611).
+char(1,66612).
+char(3,66613).
+char(9,66614).
+char(m,66615).
+char(o,66616).
+char(5,66617).
+char(8,66618).
+char(5,66619).
+char(4,66620).
+char(m,66621).
+char(5,66622).
+char(6,66623).
+char(9,66624).
+char(3,66625).
+char(c,66626).
+char(m,66627).
+char(9,66628).
+char(4,66629).
+char(4,66630).
+char(6,66631).
+char(c,66632).
+char(c,66633).
+char(c,66634).
+char(m,66635).
+char(2,66636).
+char(0,66637).
+char(1,66638).
+char(4,66639).
+char(p,66640).
+char(o,66641).
+char(p,66642).
+char(o,66643).
+char(m,66644).
+char(o,66645).
+char(m,66646).
+char(o,66647).
+char(m,66648).
+char(3,66649).
+char(2,66650).
+char(5,66651).
+char(2,66652).
+char(c,66653).
+char(c,66654).
+char(c,66655).
+char(p,66656).
+char(6,66657).
+char(1,66658).
+char(9,66659).
+char(8,66660).
+char(c,66661).
+char(c,66662).
+char(c,66663).
+char(m,66664).
+char(o,66665).
+char(m,66666).
+char(7,66667).
+char(2,66668).
+char(0,66669).
+char(2,66670).
+char(m,66671).
+char(o,66672).
+char(m,66673).
+char(2,66674).
+char(1,66675).
+char(6,66676).
+char(0,66677).
+char(c,66678).
+char(c,66679).
+char(c,66680).
+char(m,66681).
+char(o,66682).
+char(p,66683).
+char(8,66684).
+char(7,66685).
+char(7,66686).
+char(2,66687).
+char(c,66688).
+char(m,66689).
+char(o,66690).
+char(p,66691).
+char(o,66692).
+char(p,66693).
+char(o,66694).
+char(m,66695).
+char(6,66696).
+char(2,66697).
+char(0,66698).
+char(7,66699).
+char(c,66700).
+char(c,66701).
+char(c,66702).
+char(p,66703).
+char(1,66704).
+char(6,66705).
+char(6,66706).
+char(m,66707).
+char(o,66708).
+char(p,66709).
+char(o,66710).
+char(p,66711).
+char(1,66712).
+char(8,66713).
+char(4,66714).
+char(m,66715).
+char(o,66716).
+char(6,66717).
+char(1,66718).
+char(9,66719).
+char(4,66720).
+char(c,66721).
+char(c,66722).
+char(m,66723).
+char(o,66724).
+char(p,66725).
+char(1,66726).
+char(1,66727).
+char(4,66728).
+char(c,66729).
+char(p,66730).
+char(8,66731).
+char(7,66732).
+char(8,66733).
+char(6,66734).
+char(c,66735).
+char(m,66736).
+char(o,66737).
+char(4,66738).
+char(1,66739).
+char(9,66740).
+char(4,66741).
+char(p,66742).
+char(3,66743).
+char(1,66744).
+char(2,66745).
+char(p,66746).
+char(o,66747).
+char(6,66748).
+char(5,66749).
+char(7,66750).
+char(9,66751).
+char(c,66752).
+char(p,66753).
+char(o,66754).
+char(3,66755).
+char(0,66756).
+char(6,66757).
+char(0,66758).
+char(c,66759).
+char(c,66760).
+char(c,66761).
+char(p,66762).
+char(4,66763).
+char(7,66764).
+char(6,66765).
+char(1,66766).
+char(c,66767).
+char(m,66768).
+char(o,66769).
+char(m,66770).
+char(o,66771).
+char(m,66772).
+char(7,66773).
+char(3,66774).
+char(6,66775).
+char(4,66776).
+char(c,66777).
+char(p,66778).
+char(5,66779).
+char(1,66780).
+char(2,66781).
+char(6,66782).
+char(p,66783).
+char(6,66784).
+char(9,66785).
+char(4,66786).
+char(2,66787).
+char(c,66788).
+char(p,66789).
+char(o,66790).
+char(m,66791).
+char(8,66792).
+char(1,66793).
+char(9,66794).
+char(0,66795).
+char(p,66796).
+char(5,66797).
+char(4,66798).
+char(3,66799).
+char(8,66800).
+char(c,66801).
+char(c,66802).
+char(m,66803).
+char(1,66804).
+char(8,66805).
+char(5,66806).
+char(4,66807).
+char(m,66808).
+char(o,66809).
+char(o,66810).
+char(m,66811).
+char(1,66812).
+char(6,66813).
+char(1,66814).
+char(3,66815).
+char(c,66816).
+char(m,66817).
+char(o,66818).
+char(7,66819).
+char(5,66820).
+char(8,66821).
+char(8,66822).
+char(p,66823).
+char(o,66824).
+char(p,66825).
+char(o,66826).
+char(o,66827).
+char(8,66828).
+char(8,66829).
+char(1,66830).
+char(4,66831).
+char(m,66832).
+char(9,66833).
+char(3,66834).
+char(2,66835).
+char(7,66836).
+char(m,66837).
+char(o,66838).
+char(p,66839).
+char(o,66840).
+char(4,66841).
+char(9,66842).
+char(0,66843).
+char(5,66844).
+char(c,66845).
+char(c,66846).
+char(m,66847).
+char(o,66848).
+char(p,66849).
+char(2,66850).
+char(6,66851).
+char(6,66852).
+char(m,66853).
+char(7,66854).
+char(7,66855).
+char(2,66856).
+char(5,66857).
+char(m,66858).
+char(2,66859).
+char(1,66860).
+char(7,66861).
+char(6,66862).
+char(m,66863).
+char(o,66864).
+char(o,66865).
+char(m,66866).
+char(2,66867).
+char(0,66868).
+char(3,66869).
+char(6,66870).
+char(c,66871).
+char(p,66872).
+char(2,66873).
+char(9,66874).
+char(8,66875).
+char(3,66876).
+char(c,66877).
+char(c,66878).
+char(c,66879).
+char(c,66880).
+char(m,66881).
+char(3,66882).
+char(7,66883).
+char(3,66884).
+char(1,66885).
+char(p,66886).
+char(o,66887).
+char(6,66888).
+char(8,66889).
+char(3,66890).
+char(3,66891).
+char(m,66892).
+char(o,66893).
+char(8,66894).
+char(8,66895).
+char(2,66896).
+char(1,66897).
+char(m,66898).
+char(o,66899).
+char(o,66900).
+char(m,66901).
+char(o,66902).
+char(p,66903).
+char(o,66904).
+char(p,66905).
+char(o,66906).
+char(p,66907).
+char(9,66908).
+char(7,66909).
+char(0,66910).
+char(7,66911).
+char(p,66912).
+char(7,66913).
+char(5,66914).
+char(2,66915).
+char(c,66916).
+char(c,66917).
+char(m,66918).
+char(o,66919).
+char(p,66920).
+char(7,66921).
+char(6,66922).
+char(5,66923).
+char(4,66924).
+char(p,66925).
+char(o,66926).
+char(8,66927).
+char(8,66928).
+char(0,66929).
+char(c,66930).
+char(m,66931).
+char(7,66932).
+char(4,66933).
+char(8,66934).
+char(0,66935).
+char(p,66936).
+char(4,66937).
+char(7,66938).
+char(0,66939).
+char(5,66940).
+char(m,66941).
+char(o,66942).
+char(3,66943).
+char(1,66944).
+char(0,66945).
+char(8,66946).
+char(c,66947).
+char(c,66948).
+char(c,66949).
+char(p,66950).
+char(6,66951).
+char(1,66952).
+char(6,66953).
+char(5,66954).
+char(p,66955).
+char(8,66956).
+char(3,66957).
+char(6,66958).
+char(8,66959).
+char(p,66960).
+char(o,66961).
+char(o,66962).
+char(p,66963).
+char(o,66964).
+char(m,66965).
+char(o,66966).
+char(m,66967).
+char(4,66968).
+char(9,66969).
+char(2,66970).
+char(4,66971).
+char(c,66972).
+char(m,66973).
+char(o,66974).
+char(m,66975).
+char(2,66976).
+char(7,66977).
+char(6,66978).
+char(9,66979).
+char(p,66980).
+char(1,66981).
+char(1,66982).
+char(6,66983).
+char(2,66984).
+char(p,66985).
+char(o,66986).
+char(m,66987).
+char(7,66988).
+char(7,66989).
+char(9,66990).
+char(8,66991).
+char(c,66992).
+char(m,66993).
+char(o,66994).
+char(o,66995).
+char(m,66996).
+char(o,66997).
+char(m,66998).
+char(o,66999).
+char(m,67000).
+char(o,67001).
+char(m,67002).
+char(3,67003).
+char(9,67004).
+char(6,67005).
+char(4,67006).
+char(m,67007).
+char(o,67008).
+char(m,67009).
+char(o,67010).
+char(p,67011).
+char(o,67012).
+char(3,67013).
+char(4,67014).
+char(6,67015).
+char(7,67016).
+char(c,67017).
+char(c,67018).
+char(m,67019).
+char(1,67020).
+char(4,67021).
+char(0,67022).
+char(0,67023).
+char(m,67024).
+char(6,67025).
+char(7,67026).
+char(4,67027).
+char(0,67028).
+char(c,67029).
+char(c,67030).
+char(m,67031).
+char(4,67032).
+char(1,67033).
+char(0,67034).
+char(6,67035).
+char(p,67036).
+char(5,67037).
+char(2,67038).
+char(2,67039).
+char(7,67040).
+char(m,67041).
+char(2,67042).
+char(5,67043).
+char(8,67044).
+char(p,67045).
+char(o,67046).
+char(m,67047).
+char(1,67048).
+char(2,67049).
+char(6,67050).
+char(5,67051).
+char(c,67052).
+char(c,67053).
+char(c,67054).
+char(c,67055).
+char(c,67056).
+char(c,67057).
+char(c,67058).
+char(p,67059).
+char(o,67060).
+char(o,67061).
+char(p,67062).
+char(2,67063).
+char(1,67064).
+char(9,67065).
+char(1,67066).
+char(c,67067).
+char(p,67068).
+char(o,67069).
+char(2,67070).
+char(4,67071).
+char(6,67072).
+char(4,67073).
+char(p,67074).
+char(3,67075).
+char(5,67076).
+char(4,67077).
+char(7,67078).
+char(c,67079).
+char(p,67080).
+char(o,67081).
+char(o,67082).
+char(p,67083).
+char(o,67084).
+char(p,67085).
+char(9,67086).
+char(4,67087).
+char(8,67088).
+char(8,67089).
+char(p,67090).
+char(o,67091).
+char(m,67092).
+char(o,67093).
+char(m,67094).
+char(6,67095).
+char(9,67096).
+char(0,67097).
+char(4,67098).
+char(m,67099).
+char(5,67100).
+char(4,67101).
+char(3,67102).
+char(1,67103).
+char(p,67104).
+char(o,67105).
+char(5,67106).
+char(5,67107).
+char(3,67108).
+char(8,67109).
+char(m,67110).
+char(o,67111).
+char(p,67112).
+char(o,67113).
+char(p,67114).
+char(6,67115).
+char(6,67116).
+char(2,67117).
+char(4,67118).
+char(p,67119).
+char(o,67120).
+char(o,67121).
+char(m,67122).
+char(o,67123).
+char(p,67124).
+char(9,67125).
+char(0,67126).
+char(2,67127).
+char(9,67128).
+char(c,67129).
+char(p,67130).
+char(4,67131).
+char(9,67132).
+char(7,67133).
+char(6,67134).
+char(c,67135).
+char(c,67136).
+char(c,67137).
+char(c,67138).
+char(m,67139).
+char(9,67140).
+char(0,67141).
+char(2,67142).
+char(9,67143).
+char(m,67144).
+char(o,67145).
+char(p,67146).
+char(o,67147).
+char(p,67148).
+char(o,67149).
+char(p,67150).
+char(o,67151).
+char(p,67152).
+char(6,67153).
+char(9,67154).
+char(7,67155).
+char(c,67156).
+char(p,67157).
+char(o,67158).
+char(p,67159).
+char(o,67160).
+char(p,67161).
+char(o,67162).
+char(o,67163).
+char(p,67164).
+char(o,67165).
+char(m,67166).
+char(7,67167).
+char(6,67168).
+char(3,67169).
+char(5,67170).
+char(p,67171).
+char(o,67172).
+char(5,67173).
+char(5,67174).
+char(0,67175).
+char(9,67176).
+char(c,67177).
+char(m,67178).
+char(4,67179).
+char(3,67180).
+char(6,67181).
+char(6,67182).
+char(c,67183).
+char(p,67184).
+char(o,67185).
+char(m,67186).
+char(5,67187).
+char(0,67188).
+char(3,67189).
+char(5,67190).
+char(p,67191).
+char(o,67192).
+char(o,67193).
+char(p,67194).
+char(o,67195).
+char(m,67196).
+char(o,67197).
+char(m,67198).
+char(o,67199).
+char(o,67200).
+char(7,67201).
+char(7,67202).
+char(9,67203).
+char(7,67204).
+char(m,67205).
+char(o,67206).
+char(m,67207).
+char(o,67208).
+char(o,67209).
+char(m,67210).
+char(o,67211).
+char(p,67212).
+char(o,67213).
+char(o,67214).
+char(p,67215).
+char(1,67216).
+char(7,67217).
+char(0,67218).
+char(7,67219).
+char(c,67220).
+char(c,67221).
+char(p,67222).
+char(4,67223).
+char(2,67224).
+char(5,67225).
+char(0,67226).
+char(p,67227).
+char(o,67228).
+char(m,67229).
+char(3,67230).
+char(6,67231).
+char(6,67232).
+char(5,67233).
+char(c,67234).
+char(c,67235).
+char(p,67236).
+char(1,67237).
+char(1,67238).
+char(9,67239).
+char(8,67240).
+char(c,67241).
+char(c,67242).
+char(c,67243).
+char(c,67244).
+char(c,67245).
+char(c,67246).
+char(p,67247).
+char(o,67248).
+char(p,67249).
+char(8,67250).
+char(3,67251).
+char(5,67252).
+char(6,67253).
+char(m,67254).
+char(o,67255).
+char(p,67256).
+char(o,67257).
+char(8,67258).
+char(4,67259).
+char(6,67260).
+char(9,67261).
+char(c,67262).
+char(p,67263).
+char(o,67264).
+char(m,67265).
+char(6,67266).
+char(7,67267).
+char(9,67268).
+char(1,67269).
+char(c,67270).
+char(c,67271).
+char(m,67272).
+char(o,67273).
+char(m,67274).
+char(o,67275).
+char(o,67276).
+char(5,67277).
+char(2,67278).
+char(0,67279).
+char(3,67280).
+char(c,67281).
+char(m,67282).
+char(o,67283).
+char(4,67284).
+char(7,67285).
+char(0,67286).
+char(0,67287).
+char(m,67288).
+char(2,67289).
+char(8,67290).
+char(8,67291).
+char(4,67292).
+char(p,67293).
+char(o,67294).
+char(m,67295).
+char(5,67296).
+char(4,67297).
+char(7,67298).
+char(7,67299).
+char(p,67300).
+char(5,67301).
+char(1,67302).
+char(7,67303).
+char(6,67304).
+char(c,67305).
+char(c,67306).
+char(c,67307).
+char(c,67308).
+char(m,67309).
+char(o,67310).
+char(o,67311).
+char(m,67312).
+char(2,67313).
+char(9,67314).
+char(6,67315).
+char(3,67316).
+char(m,67317).
+char(1,67318).
+char(6,67319).
+char(0,67320).
+char(0,67321).
+char(p,67322).
+char(o,67323).
+char(m,67324).
+char(3,67325).
+char(3,67326).
+char(8,67327).
+char(6,67328).
+char(c,67329).
+char(m,67330).
+char(o,67331).
+char(p,67332).
+char(2,67333).
+char(2,67334).
+char(4,67335).
+char(7,67336).
+char(c,67337).
+char(p,67338).
+char(o,67339).
+char(9,67340).
+char(9,67341).
+char(0,67342).
+char(5,67343).
+char(m,67344).
+char(9,67345).
+char(3,67346).
+char(2,67347).
+char(1,67348).
+char(c,67349).
+char(c,67350).
+char(p,67351).
+char(3,67352).
+char(8,67353).
+char(2,67354).
+char(9,67355).
+char(c,67356).
+char(p,67357).
+char(o,67358).
+char(o,67359).
+char(p,67360).
+char(o,67361).
+char(m,67362).
+char(9,67363).
+char(2,67364).
+char(5,67365).
+char(c,67366).
+char(c,67367).
+char(c,67368).
+char(c,67369).
+char(c,67370).
+char(c,67371).
+char(m,67372).
+char(9,67373).
+char(1,67374).
+char(4,67375).
+char(1,67376).
+char(m,67377).
+char(5,67378).
+char(0,67379).
+char(8,67380).
+char(6,67381).
+char(m,67382).
+char(o,67383).
+char(m,67384).
+char(o,67385).
+char(p,67386).
+char(o,67387).
+char(p,67388).
+char(5,67389).
+char(8,67390).
+char(7,67391).
+char(2,67392).
+char(c,67393).
+char(m,67394).
+char(1,67395).
+char(7,67396).
+char(7,67397).
+char(4,67398).
+char(m,67399).
+char(6,67400).
+char(1,67401).
+char(0,67402).
+char(3,67403).
+char(c,67404).
+char(c,67405).
+char(c,67406).
+char(c,67407).
+char(c,67408).
+char(m,67409).
+char(7,67410).
+char(1,67411).
+char(p,67412).
+char(7,67413).
+char(6,67414).
+char(6,67415).
+char(9,67416).
+char(c,67417).
+char(c,67418).
+char(m,67419).
+char(2,67420).
+char(9,67421).
+char(2,67422).
+char(4,67423).
+char(c,67424).
+char(m,67425).
+char(o,67426).
+char(p,67427).
+char(o,67428).
+char(p,67429).
+char(o,67430).
+char(o,67431).
+char(p,67432).
+char(o,67433).
+char(p,67434).
+char(o,67435).
+char(3,67436).
+char(0,67437).
+char(0,67438).
+char(7,67439).
+char(c,67440).
+char(m,67441).
+char(o,67442).
+char(o,67443).
+char(p,67444).
+char(o,67445).
+char(p,67446).
+char(5,67447).
+char(1,67448).
+char(3,67449).
+char(9,67450).
+char(p,67451).
+char(o,67452).
+char(m,67453).
+char(3,67454).
+char(3,67455).
+char(8,67456).
+char(m,67457).
+char(5,67458).
+char(2,67459).
+char(2,67460).
+char(4,67461).
+char(c,67462).
+char(c,67463).
+char(m,67464).
+char(4,67465).
+char(7,67466).
+char(7,67467).
+char(8,67468).
+char(m,67469).
+char(o,67470).
+char(8,67471).
+char(1,67472).
+char(6,67473).
+char(6,67474).
+char(p,67475).
+char(5,67476).
+char(5,67477).
+char(2,67478).
+char(8,67479).
+char(p,67480).
+char(9,67481).
+char(7,67482).
+char(4,67483).
+char(0,67484).
+char(p,67485).
+char(o,67486).
+char(6,67487).
+char(4,67488).
+char(6,67489).
+char(7,67490).
+char(c,67491).
+char(p,67492).
+char(1,67493).
+char(0,67494).
+char(2,67495).
+char(5,67496).
+char(c,67497).
+char(m,67498).
+char(o,67499).
+char(m,67500).
+char(o,67501).
+char(o,67502).
+char(m,67503).
+char(3,67504).
+char(8,67505).
+char(7,67506).
+char(8,67507).
+char(m,67508).
+char(2,67509).
+char(5,67510).
+char(8,67511).
+char(4,67512).
+char(c,67513).
+char(c,67514).
+char(p,67515).
+char(2,67516).
+char(2,67517).
+char(1,67518).
+char(6,67519).
+char(p,67520).
+char(o,67521).
+char(p,67522).
+char(o,67523).
+char(m,67524).
+char(o,67525).
+char(o,67526).
+char(3,67527).
+char(3,67528).
+char(7,67529).
+char(5,67530).
+char(p,67531).
+char(o,67532).
+char(5,67533).
+char(8,67534).
+char(0,67535).
+char(9,67536).
+char(m,67537).
+char(4,67538).
+char(5,67539).
+char(5,67540).
+char(4,67541).
+char(p,67542).
+char(9,67543).
+char(6,67544).
+char(6,67545).
+char(1,67546).
+char(m,67547).
+char(o,67548).
+char(p,67549).
+char(1,67550).
+char(3,67551).
+char(0,67552).
+char(c,67553).
+char(m,67554).
+char(1,67555).
+char(9,67556).
+char(6,67557).
+char(7,67558).
+char(p,67559).
+char(9,67560).
+char(6,67561).
+char(4,67562).
+char(5,67563).
+char(m,67564).
+char(o,67565).
+char(p,67566).
+char(9,67567).
+char(5,67568).
+char(0,67569).
+char(1,67570).
+char(m,67571).
+char(o,67572).
+char(m,67573).
+char(2,67574).
+char(7,67575).
+char(0,67576).
+char(3,67577).
+char(c,67578).
+char(c,67579).
+char(m,67580).
+char(3,67581).
+char(1,67582).
+char(1,67583).
+char(7,67584).
+char(c,67585).
+char(c,67586).
+char(m,67587).
+char(3,67588).
+char(9,67589).
+char(2,67590).
+char(7,67591).
+char(c,67592).
+char(p,67593).
+char(1,67594).
+char(5,67595).
+char(9,67596).
+char(7,67597).
+char(m,67598).
+char(o,67599).
+char(p,67600).
+char(o,67601).
+char(p,67602).
+char(7,67603).
+char(4,67604).
+char(1,67605).
+char(6,67606).
+char(m,67607).
+char(8,67608).
+char(8,67609).
+char(7,67610).
+char(m,67611).
+char(4,67612).
+char(5,67613).
+char(8,67614).
+char(3,67615).
+char(c,67616).
+char(c,67617).
+char(c,67618).
+char(p,67619).
+char(o,67620).
+char(4,67621).
+char(5,67622).
+char(5,67623).
+char(5,67624).
+char(p,67625).
+char(o,67626).
+char(m,67627).
+char(o,67628).
+char(p,67629).
+char(8,67630).
+char(2,67631).
+char(2,67632).
+char(6,67633).
+char(p,67634).
+char(o,67635).
+char(m,67636).
+char(o,67637).
+char(p,67638).
+char(1,67639).
+char(0,67640).
+char(7,67641).
+char(2,67642).
+char(c,67643).
+char(m,67644).
+char(o,67645).
+char(m,67646).
+char(1,67647).
+char(7,67648).
+char(6,67649).
+char(8,67650).
+char(c,67651).
+char(p,67652).
+char(o,67653).
+char(m,67654).
+char(5,67655).
+char(6,67656).
+char(8,67657).
+char(1,67658).
+char(p,67659).
+char(4,67660).
+char(0,67661).
+char(3,67662).
+char(3,67663).
+char(m,67664).
+char(4,67665).
+char(9,67666).
+char(0,67667).
+char(0,67668).
+char(m,67669).
+char(7,67670).
+char(8,67671).
+char(8,67672).
+char(4,67673).
+char(c,67674).
+char(m,67675).
+char(o,67676).
+char(m,67677).
+char(o,67678).
+char(p,67679).
+char(o,67680).
+char(p,67681).
+char(o,67682).
+char(6,67683).
+char(6,67684).
+char(8,67685).
+char(m,67686).
+char(9,67687).
+char(9,67688).
+char(4,67689).
+char(0,67690).
+char(m,67691).
+char(7,67692).
+char(2,67693).
+char(3,67694).
+char(7,67695).
+char(p,67696).
+char(4,67697).
+char(4,67698).
+char(4,67699).
+char(5,67700).
+char(c,67701).
+char(c,67702).
+char(c,67703).
+char(c,67704).
+char(p,67705).
+char(o,67706).
+char(3,67707).
+char(3,67708).
+char(2,67709).
+char(1,67710).
+char(c,67711).
+char(p,67712).
+char(5,67713).
+char(8,67714).
+char(0,67715).
+char(7,67716).
+char(m,67717).
+char(o,67718).
+char(m,67719).
+char(o,67720).
+char(p,67721).
+char(7,67722).
+char(2,67723).
+char(4,67724).
+char(7,67725).
+char(c,67726).
+char(c,67727).
+char(p,67728).
+char(9,67729).
+char(4,67730).
+char(7,67731).
+char(7,67732).
+char(p,67733).
+char(7,67734).
+char(0,67735).
+char(8,67736).
+char(8,67737).
+char(c,67738).
+char(c,67739).
+char(c,67740).
+char(c,67741).
+char(c,67742).
+char(c,67743).
+char(c,67744).
+char(m,67745).
+char(o,67746).
+char(m,67747).
+char(o,67748).
+char(m,67749).
+char(4,67750).
+char(5,67751).
+char(9,67752).
+char(5,67753).
+char(c,67754).
+char(m,67755).
+char(2,67756).
+char(1,67757).
+char(9,67758).
+char(4,67759).
+char(m,67760).
+char(o,67761).
+char(p,67762).
+char(o,67763).
+char(p,67764).
+char(o,67765).
+char(p,67766).
+char(7,67767).
+char(5,67768).
+char(3,67769).
+char(0,67770).
+char(p,67771).
+char(9,67772).
+char(1,67773).
+char(4,67774).
+char(8,67775).
+char(p,67776).
+char(o,67777).
+char(m,67778).
+char(6,67779).
+char(2,67780).
+char(9,67781).
+char(8,67782).
+char(c,67783).
+char(m,67784).
+char(8,67785).
+char(8,67786).
+char(8,67787).
+char(4,67788).
+char(c,67789).
+char(c,67790).
+char(m,67791).
+char(6,67792).
+char(9,67793).
+char(2,67794).
+char(9,67795).
+char(c,67796).
+char(p,67797).
+char(5,67798).
+char(9,67799).
+char(2,67800).
+char(1,67801).
+char(c,67802).
+char(m,67803).
+char(4,67804).
+char(3,67805).
+char(4,67806).
+char(3,67807).
+char(m,67808).
+char(2,67809).
+char(8,67810).
+char(0,67811).
+char(9,67812).
+char(p,67813).
+char(5,67814).
+char(8,67815).
+char(4,67816).
+char(9,67817).
+char(c,67818).
+char(c,67819).
+char(c,67820).
+char(m,67821).
+char(6,67822).
+char(9,67823).
+char(8,67824).
+char(7,67825).
+char(m,67826).
+char(o,67827).
+char(o,67828).
+char(m,67829).
+char(7,67830).
+char(1,67831).
+char(5,67832).
+char(m,67833).
+char(9,67834).
+char(5,67835).
+char(4,67836).
+char(4,67837).
+char(p,67838).
+char(6,67839).
+char(4,67840).
+char(5,67841).
+char(1,67842).
+char(p,67843).
+char(4,67844).
+char(3,67845).
+char(0,67846).
+char(9,67847).
+char(m,67848).
+char(o,67849).
+char(4,67850).
+char(1,67851).
+char(0,67852).
+char(8,67853).
+char(m,67854).
+char(o,67855).
+char(o,67856).
+char(p,67857).
+char(6,67858).
+char(8,67859).
+char(3,67860).
+char(8,67861).
+char(c,67862).
+char(m,67863).
+char(o,67864).
+char(m,67865).
+char(o,67866).
+char(o,67867).
+char(p,67868).
+char(o,67869).
+char(m,67870).
+char(8,67871).
+char(1,67872).
+char(9,67873).
+char(9,67874).
+char(p,67875).
+char(5,67876).
+char(3,67877).
+char(1,67878).
+char(c,67879).
+char(c,67880).
+char(m,67881).
+char(o,67882).
+char(p,67883).
+char(4,67884).
+char(3,67885).
+char(8,67886).
+char(2,67887).
+char(m,67888).
+char(o,67889).
+char(m,67890).
+char(o,67891).
+char(m,67892).
+char(o,67893).
+char(7,67894).
+char(5,67895).
+char(2,67896).
+char(9,67897).
+char(p,67898).
+char(o,67899).
+char(7,67900).
+char(4,67901).
+char(5,67902).
+char(9,67903).
+char(c,67904).
+char(c,67905).
+char(c,67906).
+char(c,67907).
+char(m,67908).
+char(o,67909).
+char(o,67910).
+char(m,67911).
+char(o,67912).
+char(p,67913).
+char(o,67914).
+char(p,67915).
+char(o,67916).
+char(o,67917).
+char(6,67918).
+char(9,67919).
+char(9,67920).
+char(1,67921).
+char(p,67922).
+char(3,67923).
+char(0,67924).
+char(1,67925).
+char(2,67926).
+char(p,67927).
+char(o,67928).
+char(o,67929).
+char(3,67930).
+char(0,67931).
+char(4,67932).
+char(7,67933).
+char(c,67934).
+char(p,67935).
+char(o,67936).
+char(m,67937).
+char(o,67938).
+char(m,67939).
+char(9,67940).
+char(0,67941).
+char(0,67942).
+char(6,67943).
+char(m,67944).
+char(5,67945).
+char(4,67946).
+char(3,67947).
+char(3,67948).
+char(c,67949).
+char(m,67950).
+char(7,67951).
+char(0,67952).
+char(1,67953).
+char(7,67954).
+char(m,67955).
+char(o,67956).
+char(m,67957).
+char(1,67958).
+char(8,67959).
+char(7,67960).
+char(8,67961).
+char(p,67962).
+char(o,67963).
+char(p,67964).
+char(o,67965).
+char(p,67966).
+char(o,67967).
+char(o,67968).
+char(o,67969).
+char(m,67970).
+char(o,67971).
+char(p,67972).
+char(o,67973).
+char(m,67974).
+char(2,67975).
+char(0,67976).
+char(0,67977).
+char(4,67978).
+char(p,67979).
+char(o,67980).
+char(p,67981).
+char(o,67982).
+char(p,67983).
+char(o,67984).
+char(p,67985).
+char(o,67986).
+char(p,67987).
+char(o,67988).
+char(o,67989).
+char(1,67990).
+char(0,67991).
+char(6,67992).
+char(9,67993).
+char(p,67994).
+char(o,67995).
+char(3,67996).
+char(p,67997).
+char(7,67998).
+char(7,67999).
+char(8,68000).
+char(6,68001).
+char(c,68002).
+char(m,68003).
+char(8,68004).
+char(1,68005).
+char(2,68006).
+char(1,68007).
+char(c,68008).
+char(c,68009).
+char(p,68010).
+char(8,68011).
+char(3,68012).
+char(6,68013).
+char(2,68014).
+char(p,68015).
+char(o,68016).
+char(7,68017).
+char(2,68018).
+char(5,68019).
+char(1,68020).
+char(p,68021).
+char(3,68022).
+char(7,68023).
+char(9,68024).
+char(2,68025).
+char(p,68026).
+char(5,68027).
+char(0,68028).
+char(p,68029).
+char(2,68030).
+char(6,68031).
+char(7,68032).
+char(4,68033).
+char(c,68034).
+char(m,68035).
+char(o,68036).
+char(p,68037).
+char(3,68038).
+char(6,68039).
+char(9,68040).
+char(3,68041).
+char(m,68042).
+char(4,68043).
+char(6,68044).
+char(1,68045).
+char(2,68046).
+char(c,68047).
+char(m,68048).
+char(o,68049).
+char(o,68050).
+char(m,68051).
+char(o,68052).
+char(m,68053).
+char(o,68054).
+char(p,68055).
+char(o,68056).
+char(m,68057).
+char(3,68058).
+char(5,68059).
+char(2,68060).
+char(6,68061).
+char(c,68062).
+char(c,68063).
+char(c,68064).
+char(c,68065).
+char(p,68066).
+char(5,68067).
+char(4,68068).
+char(9,68069).
+char(9,68070).
+char(c,68071).
+char(c,68072).
+char(m,68073).
+char(6,68074).
+char(2,68075).
+char(6,68076).
+char(3,68077).
+char(m,68078).
+char(6,68079).
+char(4,68080).
+char(1,68081).
+char(4,68082).
+char(c,68083).
+char(c,68084).
+char(c,68085).
+char(p,68086).
+char(3,68087).
+char(3,68088).
+char(5,68089).
+char(8,68090).
+char(p,68091).
+char(o,68092).
+char(p,68093).
+char(9,68094).
+char(7,68095).
+char(4,68096).
+char(m,68097).
+char(1,68098).
+char(3,68099).
+char(9,68100).
+char(1,68101).
+char(m,68102).
+char(o,68103).
+char(p,68104).
+char(o,68105).
+char(o,68106).
+char(o,68107).
+char(p,68108).
+char(o,68109).
+char(6,68110).
+char(6,68111).
+char(1,68112).
+char(3,68113).
+char(p,68114).
+char(o,68115).
+char(m,68116).
+char(o,68117).
+char(m,68118).
+char(o,68119).
+char(o,68120).
+char(3,68121).
+char(8,68122).
+char(0,68123).
+char(9,68124).
+char(c,68125).
+char(p,68126).
+char(3,68127).
+char(4,68128).
+char(9,68129).
+char(0,68130).
+char(c,68131).
+char(p,68132).
+char(9,68133).
+char(5,68134).
+char(9,68135).
+char(3,68136).
+char(c,68137).
+char(m,68138).
+char(o,68139).
+char(m,68140).
+char(o,68141).
+char(m,68142).
+char(o,68143).
+char(m,68144).
+char(1,68145).
+char(3,68146).
+char(4,68147).
+char(5,68148).
+char(c,68149).
+char(m,68150).
+char(3,68151).
+char(3,68152).
+char(5,68153).
+char(8,68154).
+char(m,68155).
+char(o,68156).
+char(o,68157).
+char(m,68158).
+char(o,68159).
+char(m,68160).
+char(o,68161).
+char(m,68162).
+char(o,68163).
+char(m,68164).
+char(6,68165).
+char(8,68166).
+char(6,68167).
+char(9,68168).
+char(c,68169).
+char(m,68170).
+char(o,68171).
+char(5,68172).
+char(4,68173).
+char(1,68174).
+char(0,68175).
+char(m,68176).
+char(o,68177).
+char(o,68178).
+char(9,68179).
+char(7,68180).
+char(3,68181).
+char(p,68182).
+char(2,68183).
+char(1,68184).
+char(5,68185).
+char(6,68186).
+char(m,68187).
+char(6,68188).
+char(6,68189).
+char(3,68190).
+char(4,68191).
+char(c,68192).
+char(c,68193).
+char(m,68194).
+char(o,68195).
+char(p,68196).
+char(o,68197).
+char(3,68198).
+char(8,68199).
+char(9,68200).
+char(c,68201).
+char(c,68202).
+char(m,68203).
+char(o,68204).
+char(4,68205).
+char(9,68206).
+char(5,68207).
+char(7,68208).
+char(p,68209).
+char(1,68210).
+char(2,68211).
+char(4,68212).
+char(5,68213).
+char(m,68214).
+char(1,68215).
+char(1,68216).
+char(9,68217).
+char(5,68218).
+char(m,68219).
+char(4,68220).
+char(8,68221).
+char(3,68222).
+char(2,68223).
+char(c,68224).
+char(c,68225).
+char(c,68226).
+char(m,68227).
+char(o,68228).
+char(p,68229).
+char(o,68230).
+char(p,68231).
+char(o,68232).
+char(2,68233).
+char(7,68234).
+char(5,68235).
+char(7,68236).
+char(c,68237).
+char(p,68238).
+char(9,68239).
+char(3,68240).
+char(9,68241).
+char(0,68242).
+char(p,68243).
+char(2,68244).
+char(5,68245).
+char(8,68246).
+char(2,68247).
+char(p,68248).
+char(o,68249).
+char(p,68250).
+char(o,68251).
+char(9,68252).
+char(2,68253).
+char(4,68254).
+char(c,68255).
+char(m,68256).
+char(2,68257).
+char(0,68258).
+char(9,68259).
+char(4,68260).
+char(c,68261).
+char(p,68262).
+char(o,68263).
+char(o,68264).
+char(o,68265).
+char(m,68266).
+char(o,68267).
+char(m,68268).
+char(o,68269).
+char(p,68270).
+char(o,68271).
+char(p,68272).
+char(o,68273).
+char(m,68274).
+char(o,68275).
+char(m,68276).
+char(o,68277).
+char(m,68278).
+char(4,68279).
+char(7,68280).
+char(9,68281).
+char(5,68282).
+char(m,68283).
+char(8,68284).
+char(4,68285).
+char(4,68286).
+char(6,68287).
+char(c,68288).
+char(p,68289).
+char(o,68290).
+char(8,68291).
+char(5,68292).
+char(5,68293).
+char(4,68294).
+char(c,68295).
+char(m,68296).
+char(o,68297).
+char(m,68298).
+char(2,68299).
+char(2,68300).
+char(3,68301).
+char(p,68302).
+char(5,68303).
+char(8,68304).
+char(3,68305).
+char(0,68306).
+char(c,68307).
+char(c,68308).
+char(c,68309).
+char(p,68310).
+char(1,68311).
+char(8,68312).
+char(6,68313).
+char(8,68314).
+char(m,68315).
+char(1,68316).
+char(2,68317).
+char(6,68318).
+char(3,68319).
+char(c,68320).
+char(c,68321).
+char(c,68322).
+char(c,68323).
+char(p,68324).
+char(4,68325).
+char(6,68326).
+char(5,68327).
+char(9,68328).
+char(p,68329).
+char(8,68330).
+char(6,68331).
+char(4,68332).
+char(4,68333).
+char(p,68334).
+char(o,68335).
+char(7,68336).
+char(0,68337).
+char(1,68338).
+char(4,68339).
+char(c,68340).
+char(c,68341).
+char(m,68342).
+char(1,68343).
+char(9,68344).
+char(9,68345).
+char(8,68346).
+char(m,68347).
+char(3,68348).
+char(8,68349).
+char(1,68350).
+char(0,68351).
+char(m,68352).
+char(9,68353).
+char(1,68354).
+char(0,68355).
+char(5,68356).
+char(c,68357).
+char(p,68358).
+char(o,68359).
+char(m,68360).
+char(o,68361).
+char(2,68362).
+char(6,68363).
+char(7,68364).
+char(2,68365).
+char(m,68366).
+char(o,68367).
+char(o,68368).
+char(2,68369).
+char(4,68370).
+char(7,68371).
+char(1,68372).
+char(c,68373).
+char(c,68374).
+char(p,68375).
+char(4,68376).
+char(4,68377).
+char(4,68378).
+char(1,68379).
+char(p,68380).
+char(o,68381).
+char(6,68382).
+char(4,68383).
+char(4,68384).
+char(7,68385).
+char(c,68386).
+char(m,68387).
+char(1,68388).
+char(9,68389).
+char(4,68390).
+char(6,68391).
+char(p,68392).
+char(5,68393).
+char(7,68394).
+char(1,68395).
+char(1,68396).
+char(p,68397).
+char(o,68398).
+char(o,68399).
+char(p,68400).
+char(5,68401).
+char(5,68402).
+char(6,68403).
+char(7,68404).
+char(m,68405).
+char(o,68406).
+char(m,68407).
+char(o,68408).
+char(p,68409).
+char(1,68410).
+char(7,68411).
+char(4,68412).
+char(8,68413).
+char(m,68414).
+char(8,68415).
+char(6,68416).
+char(6,68417).
+char(2,68418).
+char(c,68419).
+char(m,68420).
+char(6,68421).
+char(8,68422).
+char(6,68423).
+char(6,68424).
+char(p,68425).
+char(1,68426).
+char(8,68427).
+char(9,68428).
+char(2,68429).
+char(p,68430).
+char(2,68431).
+char(6,68432).
+char(8,68433).
+char(0,68434).
+char(c,68435).
+char(m,68436).
+char(o,68437).
+char(9,68438).
+char(8,68439).
+char(7,68440).
+char(5,68441).
+char(p,68442).
+char(o,68443).
+char(o,68444).
+char(m,68445).
+char(2,68446).
+char(8,68447).
+char(3,68448).
+char(1,68449).
+char(c,68450).
+char(c,68451).
+char(m,68452).
+char(4,68453).
+char(9,68454).
+char(7,68455).
+char(3,68456).
+char(m,68457).
+char(o,68458).
+char(m,68459).
+char(5,68460).
+char(4,68461).
+char(7,68462).
+char(5,68463).
+char(p,68464).
+char(6,68465).
+char(9,68466).
+char(4,68467).
+char(5,68468).
+char(c,68469).
+char(c,68470).
+char(c,68471).
+char(c,68472).
+char(c,68473).
+char(p,68474).
+char(4,68475).
+char(4,68476).
+char(7,68477).
+char(2,68478).
+char(c,68479).
+char(m,68480).
+char(5,68481).
+char(6,68482).
+char(4,68483).
+char(9,68484).
+char(c,68485).
+char(c,68486).
+char(m,68487).
+char(9,68488).
+char(5,68489).
+char(5,68490).
+char(6,68491).
+char(p,68492).
+char(o,68493).
+char(o,68494).
+char(m,68495).
+char(o,68496).
+char(m,68497).
+char(o,68498).
+char(1,68499).
+char(3,68500).
+char(3,68501).
+char(2,68502).
+char(p,68503).
+char(o,68504).
+char(o,68505).
+char(m,68506).
+char(o,68507).
+char(m,68508).
+char(6,68509).
+char(6,68510).
+char(6,68511).
+char(0,68512).
+char(m,68513).
+char(6,68514).
+char(4,68515).
+char(9,68516).
+char(3,68517).
+char(c,68518).
+char(c,68519).
+char(c,68520).
+char(c,68521).
+char(m,68522).
+char(o,68523).
+char(p,68524).
+char(4,68525).
+char(9,68526).
+char(1,68527).
+char(2,68528).
+char(c,68529).
+char(c,68530).
+char(p,68531).
+char(o,68532).
+char(9,68533).
+char(5,68534).
+char(8,68535).
+char(7,68536).
+char(m,68537).
+char(1,68538).
+char(4,68539).
+char(2,68540).
+char(0,68541).
+char(p,68542).
+char(8,68543).
+char(6,68544).
+char(4,68545).
+char(p,68546).
+char(9,68547).
+char(9,68548).
+char(0,68549).
+char(2,68550).
+char(c,68551).
+char(c,68552).
+char(c,68553).
+char(c,68554).
+char(c,68555).
+char(c,68556).
+char(c,68557).
+char(m,68558).
+char(2,68559).
+char(0,68560).
+char(5,68561).
+char(3,68562).
+char(m,68563).
+char(o,68564).
+char(p,68565).
+char(o,68566).
+char(8,68567).
+char(9,68568).
+char(5,68569).
+char(3,68570).
+char(m,68571).
+char(o,68572).
+char(m,68573).
+char(8,68574).
+char(5,68575).
+char(5,68576).
+char(4,68577).
+char(c,68578).
+char(m,68579).
+char(1,68580).
+char(6,68581).
+char(1,68582).
+char(8,68583).
+char(m,68584).
+char(3,68585).
+char(4,68586).
+char(1,68587).
+char(7,68588).
+char(c,68589).
+char(c,68590).
+char(c,68591).
+char(m,68592).
+char(9,68593).
+char(6,68594).
+char(3,68595).
+char(8,68596).
+char(m,68597).
+char(o,68598).
+char(m,68599).
+char(o,68600).
+char(p,68601).
+char(o,68602).
+char(p,68603).
+char(o,68604).
+char(7,68605).
+char(7,68606).
+char(7,68607).
+char(5,68608).
+char(m,68609).
+char(8,68610).
+char(8,68611).
+char(5,68612).
+char(4,68613).
+char(p,68614).
+char(o,68615).
+char(m,68616).
+char(o,68617).
+char(m,68618).
+char(1,68619).
+char(9,68620).
+char(3,68621).
+char(2,68622).
+char(m,68623).
+char(9,68624).
+char(2,68625).
+char(7,68626).
+char(6,68627).
+char(c,68628).
+char(m,68629).
+char(7,68630).
+char(8,68631).
+char(9,68632).
+char(9,68633).
+char(c,68634).
+char(c,68635).
+char(c,68636).
+char(c,68637).
+char(m,68638).
+char(o,68639).
+char(7,68640).
+char(8,68641).
+char(0,68642).
+char(7,68643).
+char(p,68644).
+char(4,68645).
+char(0,68646).
+char(8,68647).
+char(m,68648).
+char(2,68649).
+char(9,68650).
+char(0,68651).
+char(5,68652).
+char(p,68653).
+char(3,68654).
+char(6,68655).
+char(5,68656).
+char(6,68657).
+char(m,68658).
+char(2,68659).
+char(6,68660).
+char(3,68661).
+char(3,68662).
+char(c,68663).
+char(p,68664).
+char(4,68665).
+char(8,68666).
+char(3,68667).
+char(4,68668).
+char(c,68669).
+char(m,68670).
+char(6,68671).
+char(1,68672).
+char(2,68673).
+char(8,68674).
+char(m,68675).
+char(o,68676).
+char(o,68677).
+char(p,68678).
+char(1,68679).
+char(7,68680).
+char(4,68681).
+char(7,68682).
+char(c,68683).
+char(c,68684).
+char(p,68685).
+char(o,68686).
+char(p,68687).
+char(o,68688).
+char(o,68689).
+char(o,68690).
+char(p,68691).
+char(7,68692).
+char(4,68693).
+char(5,68694).
+char(1,68695).
+char(m,68696).
+char(3,68697).
+char(1,68698).
+char(3,68699).
+char(8,68700).
+char(c,68701).
+char(m,68702).
+char(5,68703).
+char(2,68704).
+char(5,68705).
+char(7,68706).
+char(c,68707).
+char(c,68708).
+char(c,68709).
+char(m,68710).
+char(1,68711).
+char(2,68712).
+char(3,68713).
+char(2,68714).
+char(p,68715).
+char(3,68716).
+char(7,68717).
+char(4,68718).
+char(2,68719).
+char(c,68720).
+char(c,68721).
+char(p,68722).
+char(o,68723).
+char(m,68724).
+char(o,68725).
+char(p,68726).
+char(4,68727).
+char(8,68728).
+char(9,68729).
+char(2,68730).
+char(c,68731).
+char(c,68732).
+char(m,68733).
+char(o,68734).
+char(p,68735).
+char(o,68736).
+char(p,68737).
+char(o,68738).
+char(p,68739).
+char(9,68740).
+char(2,68741).
+char(2,68742).
+char(3,68743).
+char(m,68744).
+char(o,68745).
+char(m,68746).
+char(o,68747).
+char(p,68748).
+char(2,68749).
+char(5,68750).
+char(0,68751).
+char(3,68752).
+char(m,68753).
+char(6,68754).
+char(4,68755).
+char(1,68756).
+char(4,68757).
+char(c,68758).
+char(m,68759).
+char(1,68760).
+char(2,68761).
+char(7,68762).
+char(4,68763).
+char(c,68764).
+char(m,68765).
+char(o,68766).
+char(m,68767).
+char(7,68768).
+char(7,68769).
+char(1,68770).
+char(2,68771).
+char(c,68772).
+char(m,68773).
+char(o,68774).
+char(p,68775).
+char(6,68776).
+char(5,68777).
+char(1,68778).
+char(9,68779).
+char(p,68780).
+char(1,68781).
+char(6,68782).
+char(1,68783).
+char(6,68784).
+char(p,68785).
+char(8,68786).
+char(7,68787).
+char(3,68788).
+char(8,68789).
+char(m,68790).
+char(o,68791).
+char(m,68792).
+char(1,68793).
+char(0,68794).
+char(9,68795).
+char(8,68796).
+char(p,68797).
+char(9,68798).
+char(4,68799).
+char(3,68800).
+char(5,68801).
+char(p,68802).
+char(3,68803).
+char(4,68804).
+char(9,68805).
+char(2,68806).
+char(p,68807).
+char(o,68808).
+char(p,68809).
+char(3,68810).
+char(5,68811).
+char(9,68812).
+char(8,68813).
+char(c,68814).
+char(c,68815).
+char(c,68816).
+char(m,68817).
+char(o,68818).
+char(m,68819).
+char(1,68820).
+char(1,68821).
+char(9,68822).
+char(6,68823).
+char(c,68824).
+char(c,68825).
+char(p,68826).
+char(4,68827).
+char(3,68828).
+char(8,68829).
+char(3,68830).
+char(c,68831).
+char(p,68832).
+char(7,68833).
+char(2,68834).
+char(0,68835).
+char(2,68836).
+char(c,68837).
+char(p,68838).
+char(o,68839).
+char(o,68840).
+char(p,68841).
+char(2,68842).
+char(4,68843).
+char(8,68844).
+char(3,68845).
+char(p,68846).
+char(o,68847).
+char(o,68848).
+char(p,68849).
+char(o,68850).
+char(p,68851).
+char(4,68852).
+char(9,68853).
+char(2,68854).
+char(6,68855).
+char(m,68856).
+char(o,68857).
+char(m,68858).
+char(o,68859).
+char(m,68860).
+char(o,68861).
+char(m,68862).
+char(o,68863).
+char(p,68864).
+char(o,68865).
+char(m,68866).
+char(o,68867).
+char(3,68868).
+char(2,68869).
+char(0,68870).
+char(5,68871).
+char(c,68872).
+char(p,68873).
+char(6,68874).
+char(3,68875).
+char(1,68876).
+char(4,68877).
+char(c,68878).
+char(m,68879).
+char(o,68880).
+char(p,68881).
+char(o,68882).
+char(m,68883).
+char(4,68884).
+char(5,68885).
+char(7,68886).
+char(9,68887).
+char(c,68888).
+char(p,68889).
+char(6,68890).
+char(3,68891).
+char(7,68892).
+char(9,68893).
+char(m,68894).
+char(o,68895).
+char(p,68896).
+char(o,68897).
+char(m,68898).
+char(o,68899).
+char(8,68900).
+char(8,68901).
+char(6,68902).
+char(9,68903).
+char(c,68904).
+char(p,68905).
+char(8,68906).
+char(7,68907).
+char(1,68908).
+char(1,68909).
+char(p,68910).
+char(o,68911).
+char(o,68912).
+char(5,68913).
+char(3,68914).
+char(2,68915).
+char(5,68916).
+char(m,68917).
+char(7,68918).
+char(1,68919).
+char(2,68920).
+char(5,68921).
+char(p,68922).
+char(o,68923).
+char(o,68924).
+char(m,68925).
+char(3,68926).
+char(9,68927).
+char(6,68928).
+char(p,68929).
+char(o,68930).
+char(p,68931).
+char(4,68932).
+char(1,68933).
+char(c,68934).
+char(c,68935).
+char(p,68936).
+char(6,68937).
+char(4,68938).
+char(c,68939).
+char(c,68940).
+char(m,68941).
+char(4,68942).
+char(9,68943).
+char(8,68944).
+char(8,68945).
+char(m,68946).
+char(o,68947).
+char(3,68948).
+char(7,68949).
+char(2,68950).
+char(3,68951).
+char(c,68952).
+char(c,68953).
+char(m,68954).
+char(1,68955).
+char(0,68956).
+char(2,68957).
+char(0,68958).
+char(c,68959).
+char(p,68960).
+char(9,68961).
+char(2,68962).
+char(4,68963).
+char(0,68964).
+char(c,68965).
+char(c,68966).
+char(p,68967).
+char(6,68968).
+char(0,68969).
+char(3,68970).
+char(3,68971).
+char(c,68972).
+char(c,68973).
+char(p,68974).
+char(o,68975).
+char(o,68976).
+char(m,68977).
+char(o,68978).
+char(p,68979).
+char(3,68980).
+char(1,68981).
+char(3,68982).
+char(3,68983).
+char(m,68984).
+char(1,68985).
+char(0,68986).
+char(7,68987).
+char(9,68988).
+char(p,68989).
+char(o,68990).
+char(m,68991).
+char(o,68992).
+char(m,68993).
+char(o,68994).
+char(p,68995).
+char(o,68996).
+char(p,68997).
+char(1,68998).
+char(0,68999).
+char(8,69000).
+char(3,69001).
+char(c,69002).
+char(p,69003).
+char(5,69004).
+char(7,69005).
+char(3,69006).
+char(6,69007).
+char(m,69008).
+char(o,69009).
+char(o,69010).
+char(7,69011).
+char(1,69012).
+char(6,69013).
+char(7,69014).
+char(m,69015).
+char(1,69016).
+char(5,69017).
+char(7,69018).
+char(4,69019).
+char(c,69020).
+char(c,69021).
+char(m,69022).
+char(3,69023).
+char(8,69024).
+char(5,69025).
+char(6,69026).
+char(p,69027).
+char(o,69028).
+char(p,69029).
+char(o,69030).
+char(m,69031).
+char(8,69032).
+char(9,69033).
+char(7,69034).
+char(6,69035).
+char(p,69036).
+char(2,69037).
+char(0,69038).
+char(6,69039).
+char(6,69040).
+char(p,69041).
+char(o,69042).
+char(p,69043).
+char(4,69044).
+char(0,69045).
+char(7,69046).
+char(7,69047).
+char(c,69048).
+char(c,69049).
+char(c,69050).
+char(c,69051).
+char(c,69052).
+char(c,69053).
+char(p,69054).
+char(o,69055).
+char(o,69056).
+char(m,69057).
+char(o,69058).
+char(m,69059).
+char(o,69060).
+char(m,69061).
+char(8,69062).
+char(5,69063).
+char(1,69064).
+char(5,69065).
+char(m,69066).
+char(o,69067).
+char(p,69068).
+char(2,69069).
+char(1,69070).
+char(8,69071).
+char(6,69072).
+char(c,69073).
+char(c,69074).
+char(c,69075).
+char(c,69076).
+char(c,69077).
+char(m,69078).
+char(o,69079).
+char(o,69080).
+char(o,69081).
+char(p,69082).
+char(3,69083).
+char(3,69084).
+char(4,69085).
+char(5,69086).
+char(c,69087).
+char(c,69088).
+char(m,69089).
+char(o,69090).
+char(1,69091).
+char(8,69092).
+char(p,69093).
+char(o,69094).
+char(o,69095).
+char(1,69096).
+char(6,69097).
+char(4,69098).
+char(c,69099).
+char(c,69100).
+char(m,69101).
+char(o,69102).
+char(o,69103).
+char(m,69104).
+char(6,69105).
+char(9,69106).
+char(4,69107).
+char(1,69108).
+char(m,69109).
+char(o,69110).
+char(o,69111).
+char(9,69112).
+char(7,69113).
+char(p,69114).
+char(9,69115).
+char(7,69116).
+char(3,69117).
+char(4,69118).
+char(m,69119).
+char(8,69120).
+char(8,69121).
+char(8,69122).
+char(2,69123).
+char(p,69124).
+char(1,69125).
+char(9,69126).
+char(3,69127).
+char(3,69128).
+char(c,69129).
+char(p,69130).
+char(2,69131).
+char(9,69132).
+char(7,69133).
+char(9,69134).
+char(m,69135).
+char(9,69136).
+char(5,69137).
+char(3,69138).
+char(6,69139).
+char(c,69140).
+char(m,69141).
+char(o,69142).
+char(p,69143).
+char(o,69144).
+char(p,69145).
+char(o,69146).
+char(m,69147).
+char(7,69148).
+char(1,69149).
+char(2,69150).
+char(0,69151).
+char(c,69152).
+char(m,69153).
+char(o,69154).
+char(p,69155).
+char(6,69156).
+char(0,69157).
+char(0,69158).
+char(6,69159).
+char(m,69160).
+char(3,69161).
+char(6,69162).
+char(2,69163).
+char(3,69164).
+char(c,69165).
+char(m,69166).
+char(o,69167).
+char(p,69168).
+char(o,69169).
+char(8,69170).
+char(8,69171).
+char(8,69172).
+char(0,69173).
+char(p,69174).
+char(o,69175).
+char(3,69176).
+char(1,69177).
+char(3,69178).
+char(2,69179).
+char(m,69180).
+char(o,69181).
+char(o,69182).
+char(p,69183).
+char(7,69184).
+char(6,69185).
+char(1,69186).
+char(m,69187).
+char(3,69188).
+char(2,69189).
+char(1,69190).
+char(1,69191).
+char(c,69192).
+char(c,69193).
+char(m,69194).
+char(5,69195).
+char(8,69196).
+char(2,69197).
+char(7,69198).
+char(p,69199).
+char(o,69200).
+char(o,69201).
+char(5,69202).
+char(5,69203).
+char(9,69204).
+char(9,69205).
+char(p,69206).
+char(6,69207).
+char(6,69208).
+char(7,69209).
+char(4,69210).
+char(p,69211).
+char(7,69212).
+char(2,69213).
+char(7,69214).
+char(0,69215).
+char(m,69216).
+char(o,69217).
+char(p,69218).
+char(2,69219).
+char(6,69220).
+char(5,69221).
+char(5,69222).
+char(p,69223).
+char(o,69224).
+char(p,69225).
+char(o,69226).
+char(p,69227).
+char(8,69228).
+char(6,69229).
+char(0,69230).
+char(2,69231).
+char(p,69232).
+char(4,69233).
+char(0,69234).
+char(3,69235).
+char(8,69236).
+char(p,69237).
+char(o,69238).
+char(m,69239).
+char(o,69240).
+char(m,69241).
+char(o,69242).
+char(o,69243).
+char(m,69244).
+char(5,69245).
+char(8,69246).
+char(6,69247).
+char(6,69248).
+char(p,69249).
+char(o,69250).
+char(9,69251).
+char(8,69252).
+char(7,69253).
+char(c,69254).
+char(p,69255).
+char(o,69256).
+char(m,69257).
+char(o,69258).
+char(o,69259).
+char(p,69260).
+char(o,69261).
+char(p,69262).
+char(o,69263).
+char(m,69264).
+char(o,69265).
+char(m,69266).
+char(o,69267).
+char(p,69268).
+char(1,69269).
+char(3,69270).
+char(8,69271).
+char(4,69272).
+char(m,69273).
+char(o,69274).
+char(o,69275).
+char(3,69276).
+char(3,69277).
+char(0,69278).
+char(c,69279).
+char(p,69280).
+char(5,69281).
+char(7,69282).
+char(0,69283).
+char(2,69284).
+char(c,69285).
+char(m,69286).
+char(1,69287).
+char(7,69288).
+char(3,69289).
+char(9,69290).
+char(m,69291).
+char(9,69292).
+char(4,69293).
+char(6,69294).
+char(3,69295).
+char(c,69296).
+char(c,69297).
+char(m,69298).
+char(o,69299).
+char(m,69300).
+char(7,69301).
+char(1,69302).
+char(3,69303).
+char(8,69304).
+char(c,69305).
+char(c,69306).
+char(c,69307).
+char(p,69308).
+char(2,69309).
+char(3,69310).
+char(0,69311).
+char(p,69312).
+char(o,69313).
+char(p,69314).
+char(o,69315).
+char(m,69316).
+char(o,69317).
+char(m,69318).
+char(o,69319).
+char(p,69320).
+char(o,69321).
+char(m,69322).
+char(o,69323).
+char(m,69324).
+char(1,69325).
+char(3,69326).
+char(7,69327).
+char(0,69328).
+char(m,69329).
+char(5,69330).
+char(2,69331).
+char(3,69332).
+char(7,69333).
+char(p,69334).
+char(o,69335).
+char(o,69336).
+char(4,69337).
+char(5,69338).
+char(9,69339).
+char(1,69340).
+char(c,69341).
+char(c,69342).
+char(p,69343).
+char(o,69344).
+char(m,69345).
+char(7,69346).
+char(1,69347).
+char(2,69348).
+char(7,69349).
+char(p,69350).
+char(4,69351).
+char(8,69352).
+char(3,69353).
+char(4,69354).
+char(p,69355).
+char(o,69356).
+char(p,69357).
+char(o,69358).
+char(m,69359).
+char(o,69360).
+char(p,69361).
+char(o,69362).
+char(p,69363).
+char(o,69364).
+char(o,69365).
+char(p,69366).
+char(o,69367).
+char(4,69368).
+char(4,69369).
+char(3,69370).
+char(7,69371).
+char(c,69372).
+char(p,69373).
+char(8,69374).
+char(4,69375).
+char(7,69376).
+char(3,69377).
+char(c,69378).
+char(c,69379).
+char(p,69380).
+char(9,69381).
+char(1,69382).
+char(7,69383).
+char(0,69384).
+char(p,69385).
+char(o,69386).
+char(o,69387).
+char(o,69388).
+char(o,69389).
+char(p,69390).
+char(o,69391).
+char(m,69392).
+char(6,69393).
+char(3,69394).
+char(0,69395).
+char(6,69396).
+char(p,69397).
+char(7,69398).
+char(2,69399).
+char(2,69400).
+char(2,69401).
+char(c,69402).
+char(c,69403).
+char(m,69404).
+char(5,69405).
+char(7,69406).
+char(0,69407).
+char(c,69408).
+char(c,69409).
+char(m,69410).
+char(o,69411).
+char(o,69412).
+char(m,69413).
+char(o,69414).
+char(p,69415).
+char(9,69416).
+char(2,69417).
+char(1,69418).
+char(7,69419).
+char(m,69420).
+char(o,69421).
+char(p,69422).
+char(6,69423).
+char(4,69424).
+char(0,69425).
+char(1,69426).
+char(p,69427).
+char(4,69428).
+char(0,69429).
+char(2,69430).
+char(2,69431).
+char(c,69432).
+char(p,69433).
+char(o,69434).
+char(o,69435).
+char(p,69436).
+char(7,69437).
+char(9,69438).
+char(0,69439).
+char(7,69440).
+char(p,69441).
+char(7,69442).
+char(8,69443).
+char(7,69444).
+char(2,69445).
+char(c,69446).
+char(c,69447).
+char(c,69448).
+char(c,69449).
+char(c,69450).
+char(m,69451).
+char(9,69452).
+char(2,69453).
+char(6,69454).
+char(6,69455).
+char(p,69456).
+char(3,69457).
+char(0,69458).
+char(5,69459).
+char(4,69460).
+char(c,69461).
+char(c,69462).
+char(p,69463).
+char(7,69464).
+char(4,69465).
+char(2,69466).
+char(5,69467).
+char(m,69468).
+char(o,69469).
+char(p,69470).
+char(5,69471).
+char(2,69472).
+char(3,69473).
+char(4,69474).
+char(m,69475).
+char(o,69476).
+char(p,69477).
+char(3,69478).
+char(7,69479).
+char(2,69480).
+char(3,69481).
+char(c,69482).
+char(m,69483).
+char(2,69484).
+char(1,69485).
+char(1,69486).
+char(1,69487).
+char(c,69488).
+char(c,69489).
+char(c,69490).
+char(c,69491).
+char(p,69492).
+char(5,69493).
+char(1,69494).
+char(0,69495).
+char(3,69496).
+char(p,69497).
+char(o,69498).
+char(p,69499).
+char(o,69500).
+char(m,69501).
+char(o,69502).
+char(p,69503).
+char(8,69504).
+char(1,69505).
+char(1,69506).
+char(2,69507).
+char(m,69508).
+char(o,69509).
+char(p,69510).
+char(o,69511).
+char(m,69512).
+char(1,69513).
+char(2,69514).
+char(1,69515).
+char(7,69516).
+char(p,69517).
+char(o,69518).
+char(m,69519).
+char(o,69520).
+char(1,69521).
+char(3,69522).
+char(6,69523).
+char(0,69524).
+char(c,69525).
+char(c,69526).
+char(m,69527).
+char(o,69528).
+char(4,69529).
+char(7,69530).
+char(9,69531).
+char(9,69532).
+char(p,69533).
+char(o,69534).
+char(p,69535).
+char(o,69536).
+char(p,69537).
+char(o,69538).
+char(6,69539).
+char(9,69540).
+char(9,69541).
+char(6,69542).
+char(c,69543).
+char(c,69544).
+char(m,69545).
+char(o,69546).
+char(3,69547).
+char(3,69548).
+char(4,69549).
+char(8,69550).
+char(c,69551).
+char(c,69552).
+char(m,69553).
+char(o,69554).
+char(9,69555).
+char(9,69556).
+char(4,69557).
+char(6,69558).
+char(m,69559).
+char(o,69560).
+char(p,69561).
+char(1,69562).
+char(2,69563).
+char(3,69564).
+char(0,69565).
+char(c,69566).
+char(m,69567).
+char(7,69568).
+char(7,69569).
+char(7,69570).
+char(6,69571).
+char(c,69572).
+char(c,69573).
+char(m,69574).
+char(1,69575).
+char(7,69576).
+char(3,69577).
+char(3,69578).
+char(p,69579).
+char(o,69580).
+char(o,69581).
+char(p,69582).
+char(o,69583).
+char(o,69584).
+char(2,69585).
+char(7,69586).
+char(5,69587).
+char(2,69588).
+char(c,69589).
+char(c,69590).
+char(p,69591).
+char(1,69592).
+char(2,69593).
+char(4,69594).
+char(7,69595).
+char(c,69596).
+char(c,69597).
+char(c,69598).
+char(c,69599).
+char(c,69600).
+char(c,69601).
+char(m,69602).
+char(o,69603).
+char(8,69604).
+char(1,69605).
+char(5,69606).
+char(5,69607).
+char(c,69608).
+char(c,69609).
+char(c,69610).
+char(c,69611).
+char(c,69612).
+char(c,69613).
+char(m,69614).
+char(o,69615).
+char(p,69616).
+char(o,69617).
+char(o,69618).
+char(m,69619).
+char(2,69620).
+char(6,69621).
+char(6,69622).
+char(2,69623).
+char(p,69624).
+char(8,69625).
+char(6,69626).
+char(4,69627).
+char(7,69628).
+char(c,69629).
+char(c,69630).
+char(c,69631).
+char(c,69632).
+char(p,69633).
+char(o,69634).
+char(m,69635).
+char(o,69636).
+char(p,69637).
+char(o,69638).
+char(m,69639).
+char(3,69640).
+char(3,69641).
+char(9,69642).
+char(7,69643).
+char(m,69644).
+char(o,69645).
+char(m,69646).
+char(o,69647).
+char(p,69648).
+char(o,69649).
+char(8,69650).
+char(9,69651).
+char(8,69652).
+char(6,69653).
+char(p,69654).
+char(o,69655).
+char(m,69656).
+char(2,69657).
+char(3,69658).
+char(1,69659).
+char(4,69660).
+char(c,69661).
+char(c,69662).
+char(m,69663).
+char(6,69664).
+char(4,69665).
+char(3,69666).
+char(2,69667).
+char(p,69668).
+char(6,69669).
+char(3,69670).
+char(7,69671).
+char(4,69672).
+char(m,69673).
+char(2,69674).
+char(0,69675).
+char(3,69676).
+char(2,69677).
+char(c,69678).
+char(p,69679).
+char(o,69680).
+char(o,69681).
+char(m,69682).
+char(o,69683).
+char(p,69684).
+char(2,69685).
+char(5,69686).
+char(7,69687).
+char(0,69688).
+char(c,69689).
+char(c,69690).
+char(c,69691).
+char(m,69692).
+char(o,69693).
+char(m,69694).
+char(o,69695).
+char(m,69696).
+char(1,69697).
+char(5,69698).
+char(0,69699).
+char(6,69700).
+char(p,69701).
+char(o,69702).
+char(p,69703).
+char(o,69704).
+char(m,69705).
+char(7,69706).
+char(0,69707).
+char(2,69708).
+char(9,69709).
+char(p,69710).
+char(o,69711).
+char(m,69712).
+char(6,69713).
+char(7,69714).
+char(6,69715).
+char(7,69716).
+char(c,69717).
+char(p,69718).
+char(o,69719).
+char(7,69720).
+char(1,69721).
+char(7,69722).
+char(3,69723).
+char(p,69724).
+char(4,69725).
+char(4,69726).
+char(3,69727).
+char(7,69728).
+char(c,69729).
+char(m,69730).
+char(1,69731).
+char(6,69732).
+char(2,69733).
+char(9,69734).
+char(p,69735).
+char(o,69736).
+char(m,69737).
+char(7,69738).
+char(2,69739).
+char(6,69740).
+char(2,69741).
+char(c,69742).
+char(p,69743).
+char(6,69744).
+char(4,69745).
+char(3,69746).
+char(c,69747).
+char(m,69748).
+char(6,69749).
+char(4,69750).
+char(9,69751).
+char(9,69752).
+char(c,69753).
+char(m,69754).
+char(8,69755).
+char(1,69756).
+char(9,69757).
+char(4,69758).
+char(m,69759).
+char(o,69760).
+char(m,69761).
+char(8,69762).
+char(6,69763).
+char(9,69764).
+char(3,69765).
+char(c,69766).
+char(c,69767).
+char(c,69768).
+char(p,69769).
+char(9,69770).
+char(7,69771).
+char(4,69772).
+char(9,69773).
+char(p,69774).
+char(6,69775).
+char(1,69776).
+char(6,69777).
+char(6,69778).
+char(m,69779).
+char(6,69780).
+char(5,69781).
+char(0,69782).
+char(3,69783).
+char(m,69784).
+char(1,69785).
+char(2,69786).
+char(7,69787).
+char(5,69788).
+char(m,69789).
+char(o,69790).
+char(o,69791).
+char(7,69792).
+char(1,69793).
+char(9,69794).
+char(4,69795).
+char(m,69796).
+char(4,69797).
+char(9,69798).
+char(9,69799).
+char(1,69800).
+char(p,69801).
+char(6,69802).
+char(8,69803).
+char(4,69804).
+char(7,69805).
+char(m,69806).
+char(o,69807).
+char(1,69808).
+char(3,69809).
+char(8,69810).
+char(8,69811).
+char(m,69812).
+char(4,69813).
+char(7,69814).
+char(3,69815).
+char(3,69816).
+char(c,69817).
+char(c,69818).
+char(p,69819).
+char(7,69820).
+char(1,69821).
+char(2,69822).
+char(5,69823).
+char(c,69824).
+char(c,69825).
+char(m,69826).
+char(o,69827).
+char(m,69828).
+char(o,69829).
+char(m,69830).
+char(o,69831).
+char(p,69832).
+char(o,69833).
+char(o,69834).
+char(m,69835).
+char(o,69836).
+char(o,69837).
+char(7,69838).
+char(2,69839).
+char(6,69840).
+char(3,69841).
+char(c,69842).
+char(c,69843).
+char(m,69844).
+char(o,69845).
+char(m,69846).
+char(o,69847).
+char(m,69848).
+char(7,69849).
+char(9,69850).
+char(6,69851).
+char(5,69852).
+char(c,69853).
+char(c,69854).
+char(c,69855).
+char(m,69856).
+char(o,69857).
+char(3,69858).
+char(8,69859).
+char(8,69860).
+char(1,69861).
+char(m,69862).
+char(o,69863).
+char(m,69864).
+char(4,69865).
+char(2,69866).
+char(6,69867).
+char(5,69868).
+char(c,69869).
+char(c,69870).
+char(p,69871).
+char(9,69872).
+char(4,69873).
+char(4,69874).
+char(2,69875).
+char(p,69876).
+char(8,69877).
+char(1,69878).
+char(0,69879).
+char(9,69880).
+char(c,69881).
+char(m,69882).
+char(5,69883).
+char(5,69884).
+char(3,69885).
+char(p,69886).
+char(5,69887).
+char(9,69888).
+char(6,69889).
+char(3,69890).
+char(p,69891).
+char(9,69892).
+char(7,69893).
+char(1,69894).
+char(3,69895).
+char(p,69896).
+char(o,69897).
+char(7,69898).
+char(1,69899).
+char(4,69900).
+char(8,69901).
+char(c,69902).
+char(c,69903).
+char(p,69904).
+char(o,69905).
+char(o,69906).
+char(p,69907).
+char(5,69908).
+char(4,69909).
+char(5,69910).
+char(7,69911).
+char(m,69912).
+char(o,69913).
+char(6,69914).
+char(3,69915).
+char(2,69916).
+char(2,69917).
+char(p,69918).
+char(o,69919).
+char(6,69920).
+char(6,69921).
+char(2,69922).
+char(c,69923).
+char(c,69924).
+char(m,69925).
+char(6,69926).
+char(7,69927).
+char(4,69928).
+char(6,69929).
+char(c,69930).
+char(c,69931).
+char(c,69932).
+char(p,69933).
+char(4,69934).
+char(6,69935).
+char(3,69936).
+char(0,69937).
+char(c,69938).
+char(p,69939).
+char(o,69940).
+char(m,69941).
+char(o,69942).
+char(2,69943).
+char(4,69944).
+char(6,69945).
+char(3,69946).
+char(p,69947).
+char(2,69948).
+char(2,69949).
+char(1,69950).
+char(6,69951).
+char(c,69952).
+char(p,69953).
+char(3,69954).
+char(3,69955).
+char(3,69956).
+char(1,69957).
+char(c,69958).
+char(p,69959).
+char(1,69960).
+char(3,69961).
+char(7,69962).
+char(5,69963).
+char(c,69964).
+char(m,69965).
+char(o,69966).
+char(p,69967).
+char(o,69968).
+char(o,69969).
+char(p,69970).
+char(3,69971).
+char(7,69972).
+char(4,69973).
+char(1,69974).
+char(c,69975).
+char(m,69976).
+char(2,69977).
+char(0,69978).
+char(9,69979).
+char(6,69980).
+char(m,69981).
+char(8,69982).
+char(9,69983).
+char(8,69984).
+char(p,69985).
+char(1,69986).
+char(5,69987).
+char(9,69988).
+char(7,69989).
+char(c,69990).
+char(c,69991).
+char(p,69992).
+char(o,69993).
+char(p,69994).
+char(1,69995).
+char(5,69996).
+char(5,69997).
+char(0,69998).
+char(c,69999).
+char(m,70000).
+char(2,70001).
+char(9,70002).
+char(7,70003).
+char(1,70004).
+char(c,70005).
+char(c,70006).
+char(c,70007).
+char(c,70008).
+char(p,70009).
+char(o,70010).
+char(m,70011).
+char(2,70012).
+char(1,70013).
+char(9,70014).
+char(6,70015).
+char(p,70016).
+char(7,70017).
+char(7,70018).
+char(6,70019).
+char(7,70020).
+char(c,70021).
+char(c,70022).
+char(p,70023).
+char(4,70024).
+char(8,70025).
+char(3,70026).
+char(2,70027).
+char(c,70028).
+char(m,70029).
+char(o,70030).
+char(m,70031).
+char(7,70032).
+char(4,70033).
+char(4,70034).
+char(3,70035).
+char(c,70036).
+char(m,70037).
+char(9,70038).
+char(5,70039).
+char(4,70040).
+char(4,70041).
+char(c,70042).
+char(c,70043).
+char(c,70044).
+char(c,70045).
+char(c,70046).
+char(c,70047).
+char(p,70048).
+char(o,70049).
+char(m,70050).
+char(o,70051).
+char(4,70052).
+char(1,70053).
+char(6,70054).
+char(1,70055).
+char(c,70056).
+char(p,70057).
+char(9,70058).
+char(9,70059).
+char(4,70060).
+char(c,70061).
+char(c,70062).
+char(c,70063).
+char(p,70064).
+char(o,70065).
+char(p,70066).
+char(o,70067).
+char(p,70068).
+char(2,70069).
+char(4,70070).
+char(6,70071).
+char(1,70072).
+char(c,70073).
+char(c,70074).
+char(p,70075).
+char(o,70076).
+char(p,70077).
+char(o,70078).
+char(m,70079).
+char(o,70080).
+char(m,70081).
+char(3,70082).
+char(4,70083).
+char(0,70084).
+char(5,70085).
+char(c,70086).
+char(p,70087).
+char(3,70088).
+char(7,70089).
+char(1,70090).
+char(5,70091).
+char(c,70092).
+char(p,70093).
+char(8,70094).
+char(7,70095).
+char(8,70096).
+char(3,70097).
+char(c,70098).
+char(c,70099).
+char(c,70100).
+char(c,70101).
+char(m,70102).
+char(o,70103).
+char(m,70104).
+char(2,70105).
+char(4,70106).
+char(2,70107).
+char(3,70108).
+char(c,70109).
+char(p,70110).
+char(o,70111).
+char(o,70112).
+char(m,70113).
+char(o,70114).
+char(p,70115).
+char(o,70116).
+char(m,70117).
+char(o,70118).
+char(p,70119).
+char(o,70120).
+char(1,70121).
+char(7,70122).
+char(0,70123).
+char(m,70124).
+char(o,70125).
+char(m,70126).
+char(2,70127).
+char(0,70128).
+char(9,70129).
+char(8,70130).
+char(p,70131).
+char(8,70132).
+char(8,70133).
+char(5,70134).
+char(8,70135).
+char(c,70136).
+char(m,70137).
+char(o,70138).
+char(3,70139).
+char(2,70140).
+char(4,70141).
+char(4,70142).
+char(m,70143).
+char(o,70144).
+char(p,70145).
+char(o,70146).
+char(5,70147).
+char(5,70148).
+char(2,70149).
+char(m,70150).
+char(o,70151).
+char(m,70152).
+char(o,70153).
+char(p,70154).
+char(1,70155).
+char(6,70156).
+char(0,70157).
+char(6,70158).
+char(p,70159).
+char(3,70160).
+char(5,70161).
+char(7,70162).
+char(6,70163).
+char(c,70164).
+char(m,70165).
+char(o,70166).
+char(p,70167).
+char(1,70168).
+char(5,70169).
+char(1,70170).
+char(2,70171).
+char(p,70172).
+char(o,70173).
+char(o,70174).
+char(p,70175).
+char(o,70176).
+char(m,70177).
+char(o,70178).
+char(p,70179).
+char(9,70180).
+char(8,70181).
+char(4,70182).
+char(c,70183).
+char(c,70184).
+char(c,70185).
+char(c,70186).
+char(m,70187).
+char(o,70188).
+char(o,70189).
+char(p,70190).
+char(3,70191).
+char(2,70192).
+char(3,70193).
+char(9,70194).
+char(m,70195).
+char(o,70196).
+char(m,70197).
+char(o,70198).
+char(o,70199).
+char(p,70200).
+char(4,70201).
+char(4,70202).
+char(5,70203).
+char(6,70204).
+char(p,70205).
+char(o,70206).
+char(p,70207).
+char(o,70208).
+char(p,70209).
+char(o,70210).
+char(m,70211).
+char(4,70212).
+char(8,70213).
+char(7,70214).
+char(1,70215).
+char(c,70216).
+char(c,70217).
+char(c,70218).
+char(c,70219).
+char(m,70220).
+char(o,70221).
+char(m,70222).
+char(o,70223).
+char(m,70224).
+char(2,70225).
+char(1,70226).
+char(9,70227).
+char(2,70228).
+char(c,70229).
+char(m,70230).
+char(9,70231).
+char(4,70232).
+char(8,70233).
+char(c,70234).
+char(c,70235).
+char(m,70236).
+char(o,70237).
+char(2,70238).
+char(7,70239).
+char(2,70240).
+char(5,70241).
+char(m,70242).
+char(o,70243).
+char(m,70244).
+char(4,70245).
+char(3,70246).
+char(3,70247).
+char(2,70248).
+char(c,70249).
+char(p,70250).
+char(o,70251).
+char(m,70252).
+char(o,70253).
+char(1,70254).
+char(5,70255).
+char(9,70256).
+char(7,70257).
+char(p,70258).
+char(o,70259).
+char(p,70260).
+char(8,70261).
+char(7,70262).
+char(4,70263).
+char(3,70264).
+char(m,70265).
+char(5,70266).
+char(6,70267).
+char(7,70268).
+char(8,70269).
+char(m,70270).
+char(5,70271).
+char(8,70272).
+char(7,70273).
+char(4,70274).
+char(c,70275).
+char(c,70276).
+char(p,70277).
+char(o,70278).
+char(m,70279).
+char(o,70280).
+char(p,70281).
+char(6,70282).
+char(1,70283).
+char(5,70284).
+char(2,70285).
+char(c,70286).
+char(p,70287).
+char(5,70288).
+char(0,70289).
+char(3,70290).
+char(3,70291).
+char(p,70292).
+char(5,70293).
+char(1,70294).
+char(4,70295).
+char(0,70296).
+char(c,70297).
+char(c,70298).
+char(m,70299).
+char(o,70300).
+char(p,70301).
+char(o,70302).
+char(o,70303).
+char(o,70304).
+char(p,70305).
+char(o,70306).
+char(m,70307).
+char(o,70308).
+char(p,70309).
+char(2,70310).
+char(3,70311).
+char(4,70312).
+char(4,70313).
+char(c,70314).
+char(c,70315).
+char(p,70316).
+char(7,70317).
+char(0,70318).
+char(4,70319).
+char(4,70320).
+char(p,70321).
+char(o,70322).
+char(p,70323).
+char(9,70324).
+char(7,70325).
+char(4,70326).
+char(2,70327).
+char(c,70328).
+char(c,70329).
+char(p,70330).
+char(8,70331).
+char(6,70332).
+char(1,70333).
+char(9,70334).
+char(m,70335).
+char(7,70336).
+char(7,70337).
+char(2,70338).
+char(9,70339).
+char(c,70340).
+char(c,70341).
+char(c,70342).
+char(p,70343).
+char(2,70344).
+char(9,70345).
+char(1,70346).
+char(3,70347).
+char(p,70348).
+char(1,70349).
+char(2,70350).
+char(6,70351).
+char(7,70352).
+char(c,70353).
+char(p,70354).
+char(o,70355).
+char(m,70356).
+char(o,70357).
+char(o,70358).
+char(m,70359).
+char(o,70360).
+char(p,70361).
+char(o,70362).
+char(p,70363).
+char(9,70364).
+char(4,70365).
+char(2,70366).
+char(5,70367).
+char(c,70368).
+char(c,70369).
+char(p,70370).
+char(o,70371).
+char(p,70372).
+char(7,70373).
+char(6,70374).
+char(9,70375).
+char(5,70376).
+char(p,70377).
+char(3,70378).
+char(1,70379).
+char(8,70380).
+char(1,70381).
+char(c,70382).
+char(p,70383).
+char(o,70384).
+char(p,70385).
+char(1,70386).
+char(2,70387).
+char(8,70388).
+char(6,70389).
+char(c,70390).
+char(c,70391).
+char(p,70392).
+char(4,70393).
+char(4,70394).
+char(6,70395).
+char(1,70396).
+char(c,70397).
+char(c,70398).
+char(c,70399).
+char(c,70400).
+char(p,70401).
+char(o,70402).
+char(m,70403).
+char(o,70404).
+char(p,70405).
+char(6,70406).
+char(6,70407).
+char(8,70408).
+char(3,70409).
+char(p,70410).
+char(o,70411).
+char(p,70412).
+char(5,70413).
+char(2,70414).
+char(0,70415).
+char(2,70416).
+char(c,70417).
+char(p,70418).
+char(o,70419).
+char(m,70420).
+char(o,70421).
+char(m,70422).
+char(9,70423).
+char(3,70424).
+char(1,70425).
+char(0,70426).
+char(m,70427).
+char(o,70428).
+char(9,70429).
+char(5,70430).
+char(0,70431).
+char(6,70432).
+char(m,70433).
+char(1,70434).
+char(7,70435).
+char(1,70436).
+char(9,70437).
+char(c,70438).
+char(m,70439).
+char(1,70440).
+char(3,70441).
+char(5,70442).
+char(1,70443).
+char(p,70444).
+char(o,70445).
+char(m,70446).
+char(o,70447).
+char(m,70448).
+char(4,70449).
+char(4,70450).
+char(9,70451).
+char(2,70452).
+char(c,70453).
+char(c,70454).
+char(p,70455).
+char(4,70456).
+char(5,70457).
+char(6,70458).
+char(c,70459).
+char(c,70460).
+char(c,70461).
+char(c,70462).
+char(c,70463).
+char(p,70464).
+char(o,70465).
+char(o,70466).
+char(m,70467).
+char(o,70468).
+char(p,70469).
+char(8,70470).
+char(8,70471).
+char(5,70472).
+char(1,70473).
+char(p,70474).
+char(4,70475).
+char(9,70476).
+char(4,70477).
+char(4,70478).
+char(c,70479).
+char(c,70480).
+char(c,70481).
+char(m,70482).
+char(o,70483).
+char(m,70484).
+char(o,70485).
+char(o,70486).
+char(o,70487).
+char(p,70488).
+char(5,70489).
+char(3,70490).
+char(2,70491).
+char(2,70492).
+char(c,70493).
+char(c,70494).
+char(c,70495).
+char(c,70496).
+char(c,70497).
+char(p,70498).
+char(9,70499).
+char(5,70500).
+char(0,70501).
+char(9,70502).
+char(c,70503).
+char(p,70504).
+char(8,70505).
+char(2,70506).
+char(4,70507).
+char(3,70508).
+char(c,70509).
+char(c,70510).
+char(c,70511).
+char(c,70512).
+char(p,70513).
+char(o,70514).
+char(m,70515).
+char(o,70516).
+char(p,70517).
+char(9,70518).
+char(9,70519).
+char(7,70520).
+char(6,70521).
+char(m,70522).
+char(o,70523).
+char(p,70524).
+char(2,70525).
+char(1,70526).
+char(8,70527).
+char(8,70528).
+char(c,70529).
+char(c,70530).
+char(c,70531).
+char(c,70532).
+char(c,70533).
+char(m,70534).
+char(5,70535).
+char(0,70536).
+char(4,70537).
+char(1,70538).
+char(p,70539).
+char(o,70540).
+char(o,70541).
+char(p,70542).
+char(o,70543).
+char(4,70544).
+char(1,70545).
+char(1,70546).
+char(9,70547).
+char(m,70548).
+char(o,70549).
+char(m,70550).
+char(o,70551).
+char(1,70552).
+char(4,70553).
+char(9,70554).
+char(0,70555).
+char(p,70556).
+char(o,70557).
+char(p,70558).
+char(9,70559).
+char(9,70560).
+char(0,70561).
+char(c,70562).
+char(p,70563).
+char(o,70564).
+char(m,70565).
+char(3,70566).
+char(0,70567).
+char(1,70568).
+char(8,70569).
+char(p,70570).
+char(o,70571).
+char(p,70572).
+char(6,70573).
+char(6,70574).
+char(0,70575).
+char(4,70576).
+char(p,70577).
+char(5,70578).
+char(1,70579).
+char(0,70580).
+char(5,70581).
+char(m,70582).
+char(o,70583).
+char(o,70584).
+char(p,70585).
+char(o,70586).
+char(m,70587).
+char(2,70588).
+char(6,70589).
+char(4,70590).
+char(7,70591).
+char(p,70592).
+char(4,70593).
+char(9,70594).
+char(1,70595).
+char(3,70596).
+char(m,70597).
+char(2,70598).
+char(4,70599).
+char(1,70600).
+char(4,70601).
+char(p,70602).
+char(7,70603).
+char(1,70604).
+char(3,70605).
+char(7,70606).
+char(c,70607).
+char(c,70608).
+char(c,70609).
+char(c,70610).
+char(c,70611).
+char(c,70612).
+char(p,70613).
+char(o,70614).
+char(o,70615).
+char(p,70616).
+char(1,70617).
+char(0,70618).
+char(4,70619).
+char(7,70620).
+char(c,70621).
+char(m,70622).
+char(2,70623).
+char(3,70624).
+char(0,70625).
+char(4,70626).
+char(c,70627).
+char(m,70628).
+char(o,70629).
+char(m,70630).
+char(9,70631).
+char(5,70632).
+char(9,70633).
+char(5,70634).
+char(c,70635).
+char(p,70636).
+char(9,70637).
+char(4,70638).
+char(8,70639).
+char(3,70640).
+char(c,70641).
+char(p,70642).
+char(o,70643).
+char(p,70644).
+char(o,70645).
+char(4,70646).
+char(1,70647).
+char(8,70648).
+char(7,70649).
+char(c,70650).
+char(c,70651).
+char(c,70652).
+char(c,70653).
+char(p,70654).
+char(1,70655).
+char(2,70656).
+char(7,70657).
+char(0,70658).
+char(m,70659).
+char(7,70660).
+char(7,70661).
+char(2,70662).
+char(6,70663).
+char(c,70664).
+char(m,70665).
+char(3,70666).
+char(6,70667).
+char(6,70668).
+char(6,70669).
+char(p,70670).
+char(4,70671).
+char(3,70672).
+char(9,70673).
+char(8,70674).
+char(p,70675).
+char(1,70676).
+char(2,70677).
+char(1,70678).
+char(1,70679).
+char(p,70680).
+char(6,70681).
+char(6,70682).
+char(2,70683).
+char(3,70684).
+char(p,70685).
+char(o,70686).
+char(p,70687).
+char(o,70688).
+char(p,70689).
+char(7,70690).
+char(7,70691).
+char(1,70692).
+char(8,70693).
+char(m,70694).
+char(o,70695).
+char(6,70696).
+char(3,70697).
+char(3,70698).
+char(8,70699).
+char(c,70700).
+char(m,70701).
+char(8,70702).
+char(6,70703).
+char(8,70704).
+char(5,70705).
+char(p,70706).
+char(4,70707).
+char(8,70708).
+char(1,70709).
+char(2,70710).
+char(c,70711).
+char(p,70712).
+char(1,70713).
+char(8,70714).
+char(0,70715).
+char(2,70716).
+char(c,70717).
+char(c,70718).
+char(m,70719).
+char(o,70720).
+char(o,70721).
+char(m,70722).
+char(o,70723).
+char(o,70724).
+char(o,70725).
+char(p,70726).
+char(9,70727).
+char(1,70728).
+char(1,70729).
+char(7,70730).
+char(p,70731).
+char(9,70732).
+char(2,70733).
+char(4,70734).
+char(5,70735).
+char(c,70736).
+char(c,70737).
+char(p,70738).
+char(3,70739).
+char(2,70740).
+char(0,70741).
+char(1,70742).
+char(m,70743).
+char(2,70744).
+char(9,70745).
+char(5,70746).
+char(9,70747).
+char(m,70748).
+char(4,70749).
+char(7,70750).
+char(9,70751).
+char(9,70752).
+char(c,70753).
+char(c,70754).
+char(c,70755).
+char(c,70756).
+char(p,70757).
+char(o,70758).
+char(7,70759).
+char(3,70760).
+char(2,70761).
+char(7,70762).
+char(c,70763).
+char(c,70764).
+char(p,70765).
+char(8,70766).
+char(5,70767).
+char(2,70768).
+char(5,70769).
+char(p,70770).
+char(4,70771).
+char(7,70772).
+char(8,70773).
+char(2,70774).
+char(m,70775).
+char(1,70776).
+char(7,70777).
+char(8,70778).
+char(9,70779).
+char(c,70780).
+char(p,70781).
+char(7,70782).
+char(4,70783).
+char(9,70784).
+char(4,70785).
+char(c,70786).
+char(m,70787).
+char(o,70788).
+char(p,70789).
+char(o,70790).
+char(p,70791).
+char(o,70792).
+char(3,70793).
+char(3,70794).
+char(3,70795).
+char(1,70796).
+char(m,70797).
+char(o,70798).
+char(m,70799).
+char(2,70800).
+char(7,70801).
+char(9,70802).
+char(2,70803).
+char(p,70804).
+char(8,70805).
+char(9,70806).
+char(3,70807).
+char(0,70808).
+char(c,70809).
+char(c,70810).
+char(m,70811).
+char(7,70812).
+char(9,70813).
+char(1,70814).
+char(1,70815).
+char(p,70816).
+char(o,70817).
+char(m,70818).
+char(o,70819).
+char(m,70820).
+char(8,70821).
+char(5,70822).
+char(2,70823).
+char(9,70824).
+char(c,70825).
+char(p,70826).
+char(o,70827).
+char(m,70828).
+char(o,70829).
+char(m,70830).
+char(o,70831).
+char(p,70832).
+char(8,70833).
+char(0,70834).
+char(0,70835).
+char(p,70836).
+char(o,70837).
+char(m,70838).
+char(7,70839).
+char(2,70840).
+char(2,70841).
+char(4,70842).
+char(p,70843).
+char(3,70844).
+char(2,70845).
+char(8,70846).
+char(m,70847).
+char(8,70848).
+char(9,70849).
+char(4,70850).
+char(8,70851).
+char(p,70852).
+char(o,70853).
+char(p,70854).
+char(o,70855).
+char(m,70856).
+char(o,70857).
+char(m,70858).
+char(8,70859).
+char(2,70860).
+char(6,70861).
+char(5,70862).
+char(m,70863).
+char(o,70864).
+char(p,70865).
+char(o,70866).
+char(2,70867).
+char(0,70868).
+char(2,70869).
+char(c,70870).
+char(c,70871).
+char(m,70872).
+char(3,70873).
+char(7,70874).
+char(1,70875).
+char(0,70876).
+char(c,70877).
+char(c,70878).
+char(c,70879).
+char(m,70880).
+char(o,70881).
+char(o,70882).
+char(m,70883).
+char(o,70884).
+char(p,70885).
+char(3,70886).
+char(5,70887).
+char(2,70888).
+char(7,70889).
+char(p,70890).
+char(1,70891).
+char(3,70892).
+char(5,70893).
+char(2,70894).
+char(c,70895).
+char(p,70896).
+char(o,70897).
+char(p,70898).
+char(o,70899).
+char(m,70900).
+char(o,70901).
+char(p,70902).
+char(o,70903).
+char(8,70904).
+char(0,70905).
+char(7,70906).
+char(0,70907).
+char(c,70908).
+char(c,70909).
+char(p,70910).
+char(o,70911).
+char(m,70912).
+char(o,70913).
+char(o,70914).
+char(o,70915).
+char(p,70916).
+char(o,70917).
+char(p,70918).
+char(3,70919).
+char(4,70920).
+char(8,70921).
+char(1,70922).
+char(p,70923).
+char(o,70924).
+char(1,70925).
+char(2,70926).
+char(4,70927).
+char(6,70928).
+char(p,70929).
+char(o,70930).
+char(p,70931).
+char(6,70932).
+char(0,70933).
+char(6,70934).
+char(9,70935).
+char(p,70936).
+char(1,70937).
+char(5,70938).
+char(5,70939).
+char(8,70940).
+char(c,70941).
+char(p,70942).
+char(o,70943).
+char(m,70944).
+char(1,70945).
+char(6,70946).
+char(4,70947).
+char(7,70948).
+char(c,70949).
+char(p,70950).
+char(o,70951).
+char(m,70952).
+char(o,70953).
+char(m,70954).
+char(6,70955).
+char(5,70956).
+char(9,70957).
+char(0,70958).
+char(p,70959).
+char(7,70960).
+char(2,70961).
+char(3,70962).
+char(m,70963).
+char(2,70964).
+char(0,70965).
+char(7,70966).
+char(4,70967).
+char(p,70968).
+char(5,70969).
+char(9,70970).
+char(8,70971).
+char(5,70972).
+char(c,70973).
+char(c,70974).
+char(c,70975).
+char(m,70976).
+char(o,70977).
+char(o,70978).
+char(o,70979).
+char(3,70980).
+char(3,70981).
+char(0,70982).
+char(1,70983).
+char(c,70984).
+char(c,70985).
+char(p,70986).
+char(o,70987).
+char(o,70988).
+char(p,70989).
+char(6,70990).
+char(1,70991).
+char(6,70992).
+char(c,70993).
+char(c,70994).
+char(p,70995).
+char(1,70996).
+char(5,70997).
+char(6,70998).
+char(9,70999).
+char(c,71000).
+char(p,71001).
+char(o,71002).
+char(3,71003).
+char(0,71004).
+char(4,71005).
+char(3,71006).
+char(c,71007).
+char(m,71008).
+char(2,71009).
+char(9,71010).
+char(4,71011).
+char(0,71012).
+char(c,71013).
+char(c,71014).
+char(c,71015).
+char(c,71016).
+char(c,71017).
+char(c,71018).
+char(m,71019).
+char(o,71020).
+char(o,71021).
+char(m,71022).
+char(o,71023).
+char(m,71024).
+char(o,71025).
+char(m,71026).
+char(o,71027).
+char(p,71028).
+char(1,71029).
+char(0,71030).
+char(8,71031).
+char(4,71032).
+char(m,71033).
+char(9,71034).
+char(7,71035).
+char(0,71036).
+char(7,71037).
+char(p,71038).
+char(1,71039).
+char(0,71040).
+char(2,71041).
+char(3,71042).
+char(c,71043).
+char(c,71044).
+char(p,71045).
+char(o,71046).
+char(m,71047).
+char(2,71048).
+char(9,71049).
+char(2,71050).
+char(7,71051).
+char(p,71052).
+char(7,71053).
+char(9,71054).
+char(0,71055).
+char(0,71056).
+char(p,71057).
+char(o,71058).
+char(m,71059).
+char(3,71060).
+char(7,71061).
+char(0,71062).
+char(2,71063).
+char(p,71064).
+char(1,71065).
+char(9,71066).
+char(6,71067).
+char(5,71068).
+char(m,71069).
+char(o,71070).
+char(m,71071).
+char(2,71072).
+char(2,71073).
+char(6,71074).
+char(2,71075).
+char(p,71076).
+char(4,71077).
+char(2,71078).
+char(6,71079).
+char(1,71080).
+char(m,71081).
+char(6,71082).
+char(8,71083).
+char(6,71084).
+char(8,71085).
+char(p,71086).
+char(5,71087).
+char(8,71088).
+char(8,71089).
+char(8,71090).
+char(c,71091).
+char(m,71092).
+char(7,71093).
+char(2,71094).
+char(6,71095).
+char(0,71096).
+char(c,71097).
+char(p,71098).
+char(5,71099).
+char(7,71100).
+char(1,71101).
+char(1,71102).
+char(p,71103).
+char(5,71104).
+char(6,71105).
+char(1,71106).
+char(3,71107).
+char(m,71108).
+char(o,71109).
+char(o,71110).
+char(p,71111).
+char(o,71112).
+char(p,71113).
+char(o,71114).
+char(m,71115).
+char(o,71116).
+char(p,71117).
+char(6,71118).
+char(0,71119).
+char(8,71120).
+char(3,71121).
+char(m,71122).
+char(2,71123).
+char(m,71124).
+char(3,71125).
+char(0,71126).
+char(9,71127).
+char(p,71128).
+char(5,71129).
+char(5,71130).
+char(0,71131).
+char(9,71132).
+char(c,71133).
+char(m,71134).
+char(9,71135).
+char(8,71136).
+char(4,71137).
+char(0,71138).
+char(c,71139).
+char(p,71140).
+char(3,71141).
+char(3,71142).
+char(8,71143).
+char(0,71144).
+char(m,71145).
+char(o,71146).
+char(o,71147).
+char(p,71148).
+char(o,71149).
+char(p,71150).
+char(3,71151).
+char(1,71152).
+char(0,71153).
+char(2,71154).
+char(c,71155).
+char(c,71156).
+char(m,71157).
+char(o,71158).
+char(o,71159).
+char(5,71160).
+char(5,71161).
+char(3,71162).
+char(4,71163).
+char(m,71164).
+char(3,71165).
+char(9,71166).
+char(9,71167).
+char(5,71168).
+char(c,71169).
+char(c,71170).
+char(c,71171).
+char(c,71172).
+char(m,71173).
+char(o,71174).
+char(1,71175).
+char(2,71176).
+char(5,71177).
+char(c,71178).
+char(c,71179).
+char(c,71180).
+char(p,71181).
+char(o,71182).
+char(o,71183).
+char(2,71184).
+char(0,71185).
+char(0,71186).
+char(4,71187).
+char(m,71188).
+char(9,71189).
+char(8,71190).
+char(3,71191).
+char(c,71192).
+char(m,71193).
+char(7,71194).
+char(6,71195).
+char(0,71196).
+char(9,71197).
+char(c,71198).
+char(m,71199).
+char(o,71200).
+char(m,71201).
+char(o,71202).
+char(m,71203).
+char(o,71204).
+char(o,71205).
+char(o,71206).
+char(o,71207).
+char(p,71208).
+char(7,71209).
+char(5,71210).
+char(5,71211).
+char(4,71212).
+char(c,71213).
+char(m,71214).
+char(o,71215).
+char(o,71216).
+char(m,71217).
+char(9,71218).
+char(3,71219).
+char(9,71220).
+char(9,71221).
+char(p,71222).
+char(o,71223).
+char(o,71224).
+char(m,71225).
+char(4,71226).
+char(2,71227).
+char(8,71228).
+char(6,71229).
+char(p,71230).
+char(9,71231).
+char(3,71232).
+char(3,71233).
+char(1,71234).
+char(c,71235).
+char(m,71236).
+char(3,71237).
+char(3,71238).
+char(1,71239).
+char(8,71240).
+char(c,71241).
+char(c,71242).
+char(c,71243).
+char(c,71244).
+char(c,71245).
+char(c,71246).
+char(m,71247).
+char(o,71248).
+char(4,71249).
+char(2,71250).
+char(0,71251).
+char(m,71252).
+char(o,71253).
+char(p,71254).
+char(o,71255).
+char(p,71256).
+char(6,71257).
+char(3,71258).
+char(7,71259).
+char(6,71260).
+char(c,71261).
+char(c,71262).
+char(c,71263).
+char(m,71264).
+char(o,71265).
+char(7,71266).
+char(4,71267).
+char(5,71268).
+char(6,71269).
+char(p,71270).
+char(o,71271).
+char(o,71272).
+char(p,71273).
+char(o,71274).
+char(p,71275).
+char(1,71276).
+char(7,71277).
+char(4,71278).
+char(5,71279).
+char(p,71280).
+char(o,71281).
+char(o,71282).
+char(m,71283).
+char(4,71284).
+char(0,71285).
+char(0,71286).
+char(0,71287).
+char(c,71288).
+char(c,71289).
+char(c,71290).
+char(c,71291).
+char(m,71292).
+char(1,71293).
+char(9,71294).
+char(2,71295).
+char(2,71296).
+char(c,71297).
+char(p,71298).
+char(o,71299).
+char(m,71300).
+char(o,71301).
+char(m,71302).
+char(o,71303).
+char(m,71304).
+char(5,71305).
+char(8,71306).
+char(9,71307).
+char(1,71308).
+char(c,71309).
+char(p,71310).
+char(5,71311).
+char(6,71312).
+char(3,71313).
+char(6,71314).
+char(m,71315).
+char(o,71316).
+char(m,71317).
+char(7,71318).
+char(3,71319).
+char(1,71320).
+char(4,71321).
+char(c,71322).
+char(c,71323).
+char(c,71324).
+char(p,71325).
+char(6,71326).
+char(4,71327).
+char(5,71328).
+char(4,71329).
+char(p,71330).
+char(o,71331).
+char(p,71332).
+char(7,71333).
+char(9,71334).
+char(2,71335).
+char(6,71336).
+char(c,71337).
+char(c,71338).
+char(m,71339).
+char(3,71340).
+char(3,71341).
+char(3,71342).
+char(9,71343).
+char(p,71344).
+char(o,71345).
+char(8,71346).
+char(7,71347).
+char(2,71348).
+char(5,71349).
+char(m,71350).
+char(o,71351).
+char(o,71352).
+char(m,71353).
+char(o,71354).
+char(p,71355).
+char(3,71356).
+char(3,71357).
+char(5,71358).
+char(7,71359).
+char(p,71360).
+char(3,71361).
+char(9,71362).
+char(7,71363).
+char(p,71364).
+char(o,71365).
+char(o,71366).
+char(9,71367).
+char(2,71368).
+char(7,71369).
+char(4,71370).
+char(p,71371).
+char(1,71372).
+char(3,71373).
+char(3,71374).
+char(7,71375).
+char(c,71376).
+char(p,71377).
+char(o,71378).
+char(p,71379).
+char(7,71380).
+char(8,71381).
+char(7,71382).
+char(2,71383).
+char(c,71384).
+char(p,71385).
+char(o,71386).
+char(1,71387).
+char(1,71388).
+char(5,71389).
+char(1,71390).
+char(p,71391).
+char(o,71392).
+char(p,71393).
+char(9,71394).
+char(8,71395).
+char(2,71396).
+char(2,71397).
+char(p,71398).
+char(6,71399).
+char(8,71400).
+char(2,71401).
+char(2,71402).
+char(p,71403).
+char(6,71404).
+char(3,71405).
+char(9,71406).
+char(6,71407).
+char(p,71408).
+char(2,71409).
+char(0,71410).
+char(7,71411).
+char(7,71412).
+char(c,71413).
+char(c,71414).
+char(c,71415).
+char(m,71416).
+char(o,71417).
+char(m,71418).
+char(7,71419).
+char(9,71420).
+char(1,71421).
+char(1,71422).
+char(m,71423).
+char(8,71424).
+char(4,71425).
+char(4,71426).
+char(6,71427).
+char(m,71428).
+char(o,71429).
+char(m,71430).
+char(3,71431).
+char(2,71432).
+char(8,71433).
+char(5,71434).
+char(c,71435).
+char(c,71436).
+char(m,71437).
+char(5,71438).
+char(3,71439).
+char(4,71440).
+char(7,71441).
+char(p,71442).
+char(o,71443).
+char(p,71444).
+char(o,71445).
+char(m,71446).
+char(o,71447).
+char(p,71448).
+char(8,71449).
+char(7,71450).
+char(0,71451).
+char(1,71452).
+char(c,71453).
+char(p,71454).
+char(o,71455).
+char(p,71456).
+char(o,71457).
+char(m,71458).
+char(o,71459).
+char(o,71460).
+char(o,71461).
+char(p,71462).
+char(2,71463).
+char(0,71464).
+char(8,71465).
+char(0,71466).
+char(m,71467).
+char(o,71468).
+char(m,71469).
+char(o,71470).
+char(o,71471).
+char(4,71472).
+char(8,71473).
+char(1,71474).
+char(1,71475).
+char(c,71476).
+char(c,71477).
+char(p,71478).
+char(o,71479).
+char(p,71480).
+char(8,71481).
+char(4,71482).
+char(3,71483).
+char(7,71484).
+char(c,71485).
+char(p,71486).
+char(8,71487).
+char(0,71488).
+char(9,71489).
+char(8,71490).
+char(m,71491).
+char(o,71492).
+char(p,71493).
+char(8,71494).
+char(1,71495).
+char(4,71496).
+char(p,71497).
+char(o,71498).
+char(m,71499).
+char(9,71500).
+char(3,71501).
+char(7,71502).
+char(5,71503).
+char(c,71504).
+char(c,71505).
+char(c,71506).
+char(c,71507).
+char(c,71508).
+char(p,71509).
+char(4,71510).
+char(9,71511).
+char(5,71512).
+char(2,71513).
+char(c,71514).
+char(c,71515).
+char(c,71516).
+char(p,71517).
+char(o,71518).
+char(m,71519).
+char(o,71520).
+char(o,71521).
+char(m,71522).
+char(o,71523).
+char(4,71524).
+char(5,71525).
+char(1,71526).
+char(2,71527).
+char(m,71528).
+char(o,71529).
+char(m,71530).
+char(o,71531).
+char(p,71532).
+char(6,71533).
+char(7,71534).
+char(8,71535).
+char(8,71536).
+char(c,71537).
+char(c,71538).
+char(c,71539).
+char(p,71540).
+char(o,71541).
+char(m,71542).
+char(o,71543).
+char(p,71544).
+char(4,71545).
+char(8,71546).
+char(6,71547).
+char(9,71548).
+char(m,71549).
+char(2,71550).
+char(0,71551).
+char(5,71552).
+char(m,71553).
+char(o,71554).
+char(o,71555).
+char(p,71556).
+char(4,71557).
+char(3,71558).
+char(2,71559).
+char(5,71560).
+char(c,71561).
+char(c,71562).
+char(c,71563).
+char(p,71564).
+char(o,71565).
+char(p,71566).
+char(7,71567).
+char(6,71568).
+char(3,71569).
+char(0,71570).
+char(c,71571).
+char(m,71572).
+char(o,71573).
+char(p,71574).
+char(5,71575).
+char(4,71576).
+char(6,71577).
+char(6,71578).
+char(c,71579).
+char(p,71580).
+char(9,71581).
+char(6,71582).
+char(9,71583).
+char(1,71584).
+char(c,71585).
+char(c,71586).
+char(c,71587).
+char(c,71588).
+char(c,71589).
+char(m,71590).
+char(o,71591).
+char(m,71592).
+char(4,71593).
+char(3,71594).
+char(7,71595).
+char(1,71596).
+char(c,71597).
+char(c,71598).
+char(m,71599).
+char(o,71600).
+char(m,71601).
+char(6,71602).
+char(4,71603).
+char(7,71604).
+char(p,71605).
+char(7,71606).
+char(2,71607).
+char(0,71608).
+char(5,71609).
+char(m,71610).
+char(6,71611).
+char(8,71612).
+char(2,71613).
+char(4,71614).
+char(c,71615).
+char(c,71616).
+char(p,71617).
+char(o,71618).
+char(p,71619).
+char(o,71620).
+char(6,71621).
+char(1,71622).
+char(0,71623).
+char(6,71624).
+char(c,71625).
+char(c,71626).
+char(c,71627).
+char(m,71628).
+char(o,71629).
+char(o,71630).
+char(m,71631).
+char(o,71632).
+char(p,71633).
+char(9,71634).
+char(7,71635).
+char(2,71636).
+char(4,71637).
+char(p,71638).
+char(o,71639).
+char(o,71640).
+char(p,71641).
+char(4,71642).
+char(1,71643).
+char(5,71644).
+char(4,71645).
+char(m,71646).
+char(9,71647).
+char(5,71648).
+char(1,71649).
+char(7,71650).
+char(c,71651).
+char(c,71652).
+char(p,71653).
+char(5,71654).
+char(3,71655).
+char(2,71656).
+char(0,71657).
+char(c,71658).
+char(c,71659).
+char(c,71660).
+char(c,71661).
+char(p,71662).
+char(o,71663).
+char(m,71664).
+char(o,71665).
+char(p,71666).
+char(o,71667).
+char(o,71668).
+char(p,71669).
+char(6,71670).
+char(9,71671).
+char(4,71672).
+char(5,71673).
+char(c,71674).
+char(c,71675).
+char(m,71676).
+char(o,71677).
+char(m,71678).
+char(1,71679).
+char(8,71680).
+char(2,71681).
+char(3,71682).
+char(c,71683).
+char(c,71684).
+char(c,71685).
+char(c,71686).
+char(c,71687).
+char(c,71688).
+char(c,71689).
+char(p,71690).
+char(3,71691).
+char(4,71692).
+char(9,71693).
+char(4,71694).
+char(m,71695).
+char(2,71696).
+char(1,71697).
+char(5,71698).
+char(2,71699).
+char(p,71700).
+char(o,71701).
+char(m,71702).
+char(o,71703).
+char(5,71704).
+char(9,71705).
+char(0,71706).
+char(9,71707).
+char(c,71708).
+char(c,71709).
+char(c,71710).
+char(c,71711).
+char(p,71712).
+char(6,71713).
+char(3,71714).
+char(5,71715).
+char(8,71716).
+char(c,71717).
+char(c,71718).
+char(p,71719).
+char(5,71720).
+char(2,71721).
+char(0,71722).
+char(5,71723).
+char(p,71724).
+char(o,71725).
+char(4,71726).
+char(8,71727).
+char(7,71728).
+char(7,71729).
+char(c,71730).
+char(p,71731).
+char(6,71732).
+char(6,71733).
+char(6,71734).
+char(5,71735).
+char(c,71736).
+char(c,71737).
+char(m,71738).
+char(o,71739).
+char(m,71740).
+char(o,71741).
+char(m,71742).
+char(o,71743).
+char(6,71744).
+char(1,71745).
+char(3,71746).
+char(0,71747).
+char(c,71748).
+char(p,71749).
+char(6,71750).
+char(7,71751).
+char(3,71752).
+char(2,71753).
+char(c,71754).
+char(c,71755).
+char(p,71756).
+char(9,71757).
+char(9,71758).
+char(7,71759).
+char(4,71760).
+char(c,71761).
+char(p,71762).
+char(8,71763).
+char(7,71764).
+char(1,71765).
+char(0,71766).
+char(m,71767).
+char(5,71768).
+char(7,71769).
+char(2,71770).
+char(5,71771).
+char(c,71772).
+char(c,71773).
+char(c,71774).
+char(p,71775).
+char(2,71776).
+char(5,71777).
+char(7,71778).
+char(3,71779).
+char(c,71780).
+char(c,71781).
+char(p,71782).
+char(o,71783).
+char(o,71784).
+char(p,71785).
+char(7,71786).
+char(4,71787).
+char(5,71788).
+char(3,71789).
+char(p,71790).
+char(5,71791).
+char(7,71792).
+char(8,71793).
+char(3,71794).
+char(c,71795).
+char(c,71796).
+char(c,71797).
+char(c,71798).
+char(c,71799).
+char(p,71800).
+char(o,71801).
+char(2,71802).
+char(4,71803).
+char(0,71804).
+char(3,71805).
+char(p,71806).
+char(5,71807).
+char(6,71808).
+char(4,71809).
+char(8,71810).
+char(c,71811).
+char(m,71812).
+char(4,71813).
+char(2,71814).
+char(7,71815).
+char(3,71816).
+char(c,71817).
+char(c,71818).
+char(c,71819).
+char(c,71820).
+char(c,71821).
+char(m,71822).
+char(4,71823).
+char(6,71824).
+char(6,71825).
+char(m,71826).
+char(6,71827).
+char(0,71828).
+char(6,71829).
+char(0,71830).
+char(c,71831).
+char(p,71832).
+char(o,71833).
+char(m,71834).
+char(o,71835).
+char(m,71836).
+char(9,71837).
+char(2,71838).
+char(1,71839).
+char(0,71840).
+char(m,71841).
+char(o,71842).
+char(p,71843).
+char(3,71844).
+char(5,71845).
+char(9,71846).
+char(0,71847).
+char(c,71848).
+char(c,71849).
+char(c,71850).
+char(c,71851).
+char(c,71852).
+char(m,71853).
+char(o,71854).
+char(p,71855).
+char(3,71856).
+char(9,71857).
+char(4,71858).
+char(7,71859).
+char(c,71860).
+char(c,71861).
+char(c,71862).
+char(c,71863).
+char(c,71864).
+char(c,71865).
+char(c,71866).
+char(p,71867).
+char(4,71868).
+char(9,71869).
+char(0,71870).
+char(9,71871).
+char(c,71872).
+char(p,71873).
+char(o,71874).
+char(o,71875).
+char(p,71876).
+char(7,71877).
+char(5,71878).
+char(2,71879).
+char(5,71880).
+char(p,71881).
+char(o,71882).
+char(o,71883).
+char(m,71884).
+char(o,71885).
+char(m,71886).
+char(o,71887).
+char(7,71888).
+char(5,71889).
+char(1,71890).
+char(m,71891).
+char(o,71892).
+char(o,71893).
+char(p,71894).
+char(o,71895).
+char(m,71896).
+char(4,71897).
+char(4,71898).
+char(3,71899).
+char(8,71900).
+char(c,71901).
+char(m,71902).
+char(o,71903).
+char(m,71904).
+char(6,71905).
+char(7,71906).
+char(7,71907).
+char(4,71908).
+char(c,71909).
+char(p,71910).
+char(o,71911).
+char(m,71912).
+char(o,71913).
+char(p,71914).
+char(o,71915).
+char(p,71916).
+char(6,71917).
+char(5,71918).
+char(1,71919).
+char(0,71920).
+char(c,71921).
+char(m,71922).
+char(o,71923).
+char(6,71924).
+char(5,71925).
+char(9,71926).
+char(9,71927).
+char(c,71928).
+char(p,71929).
+char(o,71930).
+char(o,71931).
+char(m,71932).
+char(o,71933).
+char(p,71934).
+char(9,71935).
+char(5,71936).
+char(2,71937).
+char(7,71938).
+char(m,71939).
+char(o,71940).
+char(5,71941).
+char(2,71942).
+char(3,71943).
+char(m,71944).
+char(2,71945).
+char(8,71946).
+char(2,71947).
+char(6,71948).
+char(p,71949).
+char(3,71950).
+char(9,71951).
+char(3,71952).
+char(c,71953).
+char(c,71954).
+char(c,71955).
+char(m,71956).
+char(1,71957).
+char(0,71958).
+char(5,71959).
+char(6,71960).
+char(c,71961).
+char(m,71962).
+char(o,71963).
+char(p,71964).
+char(o,71965).
+char(o,71966).
+char(m,71967).
+char(o,71968).
+char(m,71969).
+char(3,71970).
+char(0,71971).
+char(2,71972).
+char(0,71973).
+char(m,71974).
+char(o,71975).
+char(p,71976).
+char(1,71977).
+char(6,71978).
+char(8,71979).
+char(6,71980).
+char(p,71981).
+char(o,71982).
+char(p,71983).
+char(1,71984).
+char(0,71985).
+char(9,71986).
+char(4,71987).
+char(m,71988).
+char(o,71989).
+char(3,71990).
+char(4,71991).
+char(9,71992).
+char(2,71993).
+char(m,71994).
+char(6,71995).
+char(4,71996).
+char(7,71997).
+char(4,71998).
+char(c,71999).
+char(c,72000).
+char(c,72001).
+char(c,72002).
+char(c,72003).
+char(c,72004).
+char(m,72005).
+char(5,72006).
+char(2,72007).
+char(1,72008).
+char(2,72009).
+char(c,72010).
+char(p,72011).
+char(9,72012).
+char(2,72013).
+char(3,72014).
+char(2,72015).
+char(c,72016).
+char(c,72017).
+char(m,72018).
+char(2,72019).
+char(9,72020).
+char(8,72021).
+char(4,72022).
+char(m,72023).
+char(o,72024).
+char(m,72025).
+char(o,72026).
+char(o,72027).
+char(3,72028).
+char(7,72029).
+char(3,72030).
+char(m,72031).
+char(o,72032).
+char(m,72033).
+char(o,72034).
+char(m,72035).
+char(o,72036).
+char(p,72037).
+char(1,72038).
+char(1,72039).
+char(6,72040).
+char(1,72041).
+char(m,72042).
+char(2,72043).
+char(4,72044).
+char(9,72045).
+char(6,72046).
+char(c,72047).
+char(c,72048).
+char(c,72049).
+char(p,72050).
+char(o,72051).
+char(p,72052).
+char(4,72053).
+char(3,72054).
+char(4,72055).
+char(2,72056).
+char(c,72057).
+char(m,72058).
+char(5,72059).
+char(7,72060).
+char(2,72061).
+char(8,72062).
+char(c,72063).
+char(c,72064).
+char(m,72065).
+char(o,72066).
+char(m,72067).
+char(o,72068).
+char(m,72069).
+char(o,72070).
+char(m,72071).
+char(5,72072).
+char(9,72073).
+char(0,72074).
+char(9,72075).
+char(c,72076).
+char(m,72077).
+char(o,72078).
+char(6,72079).
+char(8,72080).
+char(9,72081).
+char(3,72082).
+char(c,72083).
+char(m,72084).
+char(o,72085).
+char(m,72086).
+char(o,72087).
+char(p,72088).
+char(o,72089).
+char(m,72090).
+char(1,72091).
+char(6,72092).
+char(3,72093).
+char(3,72094).
+char(c,72095).
+char(c,72096).
+char(c,72097).
+char(c,72098).
+char(c,72099).
+char(c,72100).
+char(c,72101).
+char(m,72102).
+char(o,72103).
+char(m,72104).
+char(o,72105).
+char(m,72106).
+char(o,72107).
+char(p,72108).
+char(7,72109).
+char(5,72110).
+char(1,72111).
+char(5,72112).
+char(m,72113).
+char(o,72114).
+char(o,72115).
+char(m,72116).
+char(7,72117).
+char(4,72118).
+char(3,72119).
+char(9,72120).
+char(p,72121).
+char(o,72122).
+char(m,72123).
+char(5,72124).
+char(6,72125).
+char(8,72126).
+char(6,72127).
+char(p,72128).
+char(3,72129).
+char(9,72130).
+char(0,72131).
+char(7,72132).
+char(p,72133).
+char(9,72134).
+char(7,72135).
+char(4,72136).
+char(1,72137).
+char(c,72138).
+char(c,72139).
+char(c,72140).
+char(m,72141).
+char(o,72142).
+char(8,72143).
+char(3,72144).
+char(3,72145).
+char(0,72146).
+char(m,72147).
+char(8,72148).
+char(6,72149).
+char(6,72150).
+char(2,72151).
+char(c,72152).
+char(c,72153).
+char(c,72154).
+char(c,72155).
+char(c,72156).
+char(c,72157).
+char(m,72158).
+char(5,72159).
+char(0,72160).
+char(1,72161).
+char(4,72162).
+char(c,72163).
+char(c,72164).
+char(c,72165).
+char(m,72166).
+char(5,72167).
+char(0,72168).
+char(4,72169).
+char(8,72170).
+char(p,72171).
+char(o,72172).
+char(m,72173).
+char(o,72174).
+char(p,72175).
+char(2,72176).
+char(1,72177).
+char(6,72178).
+char(0,72179).
+char(m,72180).
+char(6,72181).
+char(6,72182).
+char(7,72183).
+char(5,72184).
+char(c,72185).
+char(c,72186).
+char(m,72187).
+char(o,72188).
+char(p,72189).
+char(o,72190).
+char(m,72191).
+char(o,72192).
+char(p,72193).
+char(9,72194).
+char(3,72195).
+char(8,72196).
+char(0,72197).
+char(m,72198).
+char(9,72199).
+char(8,72200).
+char(4,72201).
+char(m,72202).
+char(o,72203).
+char(2,72204).
+char(6,72205).
+char(4,72206).
+char(7,72207).
+char(p,72208).
+char(4,72209).
+char(8,72210).
+char(8,72211).
+char(9,72212).
+char(m,72213).
+char(1,72214).
+char(4,72215).
+char(6,72216).
+char(1,72217).
+char(p,72218).
+char(o,72219).
+char(m,72220).
+char(5,72221).
+char(5,72222).
+char(5,72223).
+char(m,72224).
+char(3,72225).
+char(8,72226).
+char(6,72227).
+char(9,72228).
+char(m,72229).
+char(o,72230).
+char(m,72231).
+char(o,72232).
+char(p,72233).
+char(4,72234).
+char(7,72235).
+char(9,72236).
+char(9,72237).
+char(m,72238).
+char(o,72239).
+char(m,72240).
+char(o,72241).
+char(m,72242).
+char(5,72243).
+char(1,72244).
+char(2,72245).
+char(0,72246).
+char(p,72247).
+char(o,72248).
+char(m,72249).
+char(o,72250).
+char(p,72251).
+char(o,72252).
+char(m,72253).
+char(o,72254).
+char(p,72255).
+char(o,72256).
+char(m,72257).
+char(9,72258).
+char(2,72259).
+char(8,72260).
+char(2,72261).
+char(c,72262).
+char(c,72263).
+char(p,72264).
+char(2,72265).
+char(0,72266).
+char(5,72267).
+char(3,72268).
+char(m,72269).
+char(2,72270).
+char(7,72271).
+char(7,72272).
+char(2,72273).
+char(c,72274).
+char(p,72275).
+char(o,72276).
+char(p,72277).
+char(o,72278).
+char(p,72279).
+char(6,72280).
+char(6,72281).
+char(5,72282).
+char(1,72283).
+char(p,72284).
+char(4,72285).
+char(0,72286).
+char(7,72287).
+char(3,72288).
+char(p,72289).
+char(o,72290).
+char(m,72291).
+char(o,72292).
+char(p,72293).
+char(7,72294).
+char(3,72295).
+char(0,72296).
+char(3,72297).
+char(p,72298).
+char(o,72299).
+char(m,72300).
+char(o,72301).
+char(p,72302).
+char(o,72303).
+char(m,72304).
+char(o,72305).
+char(6,72306).
+char(9,72307).
+char(4,72308).
+char(3,72309).
+char(c,72310).
+char(c,72311).
+char(m,72312).
+char(1,72313).
+char(p,72314).
+char(o,72315).
+char(3,72316).
+char(3,72317).
+char(0,72318).
+char(9,72319).
+char(p,72320).
+char(o,72321).
+char(m,72322).
+char(7,72323).
+char(2,72324).
+char(0,72325).
+char(7,72326).
+char(c,72327).
+char(p,72328).
+char(5,72329).
+char(1,72330).
+char(3,72331).
+char(8,72332).
+char(c,72333).
+char(c,72334).
+char(p,72335).
+char(5,72336).
+char(6,72337).
+char(2,72338).
+char(1,72339).
+char(c,72340).
+char(m,72341).
+char(2,72342).
+char(2,72343).
+char(0,72344).
+char(3,72345).
+char(m,72346).
+char(2,72347).
+char(4,72348).
+char(9,72349).
+char(8,72350).
+char(c,72351).
+char(c,72352).
+char(p,72353).
+char(o,72354).
+char(p,72355).
+char(o,72356).
+char(m,72357).
+char(8,72358).
+char(6,72359).
+char(4,72360).
+char(4,72361).
+char(c,72362).
+char(m,72363).
+char(o,72364).
+char(m,72365).
+char(o,72366).
+char(1,72367).
+char(4,72368).
+char(3,72369).
+char(3,72370).
+char(p,72371).
+char(8,72372).
+char(1,72373).
+char(4,72374).
+char(c,72375).
+char(c,72376).
+char(m,72377).
+char(7,72378).
+char(2,72379).
+char(0,72380).
+char(8,72381).
+char(c,72382).
+char(p,72383).
+char(3,72384).
+char(6,72385).
+char(8,72386).
+char(c,72387).
+char(m,72388).
+char(4,72389).
+char(4,72390).
+char(0,72391).
+char(3,72392).
+char(c,72393).
+char(p,72394).
+char(4,72395).
+char(4,72396).
+char(5,72397).
+char(1,72398).
+char(m,72399).
+char(9,72400).
+char(4,72401).
+char(7,72402).
+char(5,72403).
+char(m,72404).
+char(6,72405).
+char(3,72406).
+char(4,72407).
+char(0,72408).
+char(c,72409).
+char(c,72410).
+char(p,72411).
+char(o,72412).
+char(m,72413).
+char(o,72414).
+char(2,72415).
+char(9,72416).
+char(p,72417).
+char(6,72418).
+char(1,72419).
+char(6,72420).
+char(2,72421).
+char(c,72422).
+char(m,72423).
+char(9,72424).
+char(1,72425).
+char(1,72426).
+char(6,72427).
+char(m,72428).
+char(4,72429).
+char(2,72430).
+char(5,72431).
+char(2,72432).
+char(m,72433).
+char(o,72434).
+char(m,72435).
+char(1,72436).
+char(9,72437).
+char(1,72438).
+char(p,72439).
+char(o,72440).
+char(m,72441).
+char(o,72442).
+char(m,72443).
+char(2,72444).
+char(8,72445).
+char(2,72446).
+char(5,72447).
+char(m,72448).
+char(o,72449).
+char(m,72450).
+char(5,72451).
+char(5,72452).
+char(0,72453).
+char(m,72454).
+char(o,72455).
+char(o,72456).
+char(m,72457).
+char(1,72458).
+char(0,72459).
+char(8,72460).
+char(1,72461).
+char(c,72462).
+char(p,72463).
+char(o,72464).
+char(p,72465).
+char(o,72466).
+char(p,72467).
+char(6,72468).
+char(1,72469).
+char(8,72470).
+char(1,72471).
+char(c,72472).
+char(c,72473).
+char(c,72474).
+char(c,72475).
+char(p,72476).
+char(5,72477).
+char(9,72478).
+char(5,72479).
+char(7,72480).
+char(c,72481).
+char(m,72482).
+char(7,72483).
+char(0,72484).
+char(5,72485).
+char(4,72486).
+char(p,72487).
+char(2,72488).
+char(7,72489).
+char(6,72490).
+char(9,72491).
+char(p,72492).
+char(5,72493).
+char(6,72494).
+char(7,72495).
+char(4,72496).
+char(c,72497).
+char(p,72498).
+char(o,72499).
+char(p,72500).
+char(3,72501).
+char(1,72502).
+char(0,72503).
+char(6,72504).
+char(c,72505).
+char(m,72506).
+char(9,72507).
+char(9,72508).
+char(1,72509).
+char(8,72510).
+char(c,72511).
+char(p,72512).
+char(3,72513).
+char(2,72514).
+char(8,72515).
+char(7,72516).
+char(c,72517).
+char(c,72518).
+char(p,72519).
+char(o,72520).
+char(2,72521).
+char(3,72522).
+char(1,72523).
+char(8,72524).
+char(c,72525).
+char(m,72526).
+char(o,72527).
+char(m,72528).
+char(o,72529).
+char(p,72530).
+char(o,72531).
+char(o,72532).
+char(p,72533).
+char(4,72534).
+char(2,72535).
+char(5,72536).
+char(3,72537).
+char(c,72538).
+char(m,72539).
+char(7,72540).
+char(0,72541).
+char(0,72542).
+char(7,72543).
+char(c,72544).
+char(c,72545).
+char(c,72546).
+char(c,72547).
+char(p,72548).
+char(o,72549).
+char(p,72550).
+char(9,72551).
+char(4,72552).
+char(8,72553).
+char(8,72554).
+char(c,72555).
+char(m,72556).
+char(o,72557).
+char(o,72558).
+char(m,72559).
+char(o,72560).
+char(m,72561).
+char(2,72562).
+char(9,72563).
+char(8,72564).
+char(1,72565).
+char(c,72566).
+char(c,72567).
+char(m,72568).
+char(4,72569).
+char(7,72570).
+char(8,72571).
+char(6,72572).
+char(c,72573).
+char(p,72574).
+char(o,72575).
+char(3,72576).
+char(1,72577).
+char(7,72578).
+char(7,72579).
+char(p,72580).
+char(6,72581).
+char(7,72582).
+char(4,72583).
+char(6,72584).
+char(c,72585).
+char(c,72586).
+char(c,72587).
+char(c,72588).
+char(c,72589).
+char(m,72590).
+char(o,72591).
+char(p,72592).
+char(9,72593).
+char(1,72594).
+char(9,72595).
+char(m,72596).
+char(8,72597).
+char(8,72598).
+char(0,72599).
+char(5,72600).
+char(c,72601).
+char(c,72602).
+char(c,72603).
+char(p,72604).
+char(3,72605).
+char(4,72606).
+char(2,72607).
+char(0,72608).
+char(m,72609).
+char(5,72610).
+char(6,72611).
+char(5,72612).
+char(8,72613).
+char(c,72614).
+char(p,72615).
+char(o,72616).
+char(p,72617).
+char(5,72618).
+char(5,72619).
+char(9,72620).
+char(1,72621).
+char(p,72622).
+char(o,72623).
+char(p,72624).
+char(o,72625).
+char(o,72626).
+char(m,72627).
+char(2,72628).
+char(5,72629).
+char(9,72630).
+char(m,72631).
+char(7,72632).
+char(4,72633).
+char(2,72634).
+char(8,72635).
+char(c,72636).
+char(c,72637).
+char(p,72638).
+char(o,72639).
+char(2,72640).
+char(2,72641).
+char(7,72642).
+char(c,72643).
+char(p,72644).
+char(o,72645).
+char(m,72646).
+char(o,72647).
+char(m,72648).
+char(8,72649).
+char(8,72650).
+char(6,72651).
+char(8,72652).
+char(c,72653).
+char(c,72654).
+char(c,72655).
+char(p,72656).
+char(4,72657).
+char(9,72658).
+char(c,72659).
+char(p,72660).
+char(5,72661).
+char(4,72662).
+char(5,72663).
+char(0,72664).
+char(c,72665).
+char(c,72666).
+char(p,72667).
+char(2,72668).
+char(7,72669).
+char(4,72670).
+char(1,72671).
+char(c,72672).
+char(c,72673).
+char(m,72674).
+char(o,72675).
+char(m,72676).
+char(4,72677).
+char(9,72678).
+char(4,72679).
+char(0,72680).
+char(p,72681).
+char(6,72682).
+char(6,72683).
+char(8,72684).
+char(7,72685).
+char(m,72686).
+char(9,72687).
+char(7,72688).
+char(3,72689).
+char(4,72690).
+char(m,72691).
+char(o,72692).
+char(7,72693).
+char(7,72694).
+char(8,72695).
+char(c,72696).
+char(c,72697).
+char(p,72698).
+char(o,72699).
+char(m,72700).
+char(o,72701).
+char(p,72702).
+char(9,72703).
+char(4,72704).
+char(9,72705).
+char(2,72706).
+char(p,72707).
+char(1,72708).
+char(3,72709).
+char(9,72710).
+char(m,72711).
+char(o,72712).
+char(p,72713).
+char(o,72714).
+char(m,72715).
+char(2,72716).
+char(4,72717).
+char(4,72718).
+char(9,72719).
+char(p,72720).
+char(6,72721).
+char(9,72722).
+char(5,72723).
+char(2,72724).
+char(p,72725).
+char(9,72726).
+char(7,72727).
+char(8,72728).
+char(8,72729).
+char(p,72730).
+char(3,72731).
+char(5,72732).
+char(4,72733).
+char(1,72734).
+char(m,72735).
+char(o,72736).
+char(o,72737).
+char(o,72738).
+char(7,72739).
+char(3,72740).
+char(8,72741).
+char(7,72742).
+char(m,72743).
+char(o,72744).
+char(7,72745).
+char(0,72746).
+char(6,72747).
+char(6,72748).
+char(m,72749).
+char(4,72750).
+char(1,72751).
+char(3,72752).
+char(1,72753).
+char(m,72754).
+char(2,72755).
+char(0,72756).
+char(5,72757).
+char(c,72758).
+char(m,72759).
+char(9,72760).
+char(4,72761).
+char(8,72762).
+char(6,72763).
+char(c,72764).
+char(p,72765).
+char(o,72766).
+char(m,72767).
+char(o,72768).
+char(p,72769).
+char(o,72770).
+char(p,72771).
+char(6,72772).
+char(1,72773).
+char(6,72774).
+char(0,72775).
+char(c,72776).
+char(p,72777).
+char(6,72778).
+char(8,72779).
+char(7,72780).
+char(5,72781).
+char(c,72782).
+char(m,72783).
+char(2,72784).
+char(7,72785).
+char(5,72786).
+char(5,72787).
+char(c,72788).
+char(m,72789).
+char(6,72790).
+char(8,72791).
+char(8,72792).
+char(7,72793).
+char(c,72794).
+char(c,72795).
+char(p,72796).
+char(o,72797).
+char(6,72798).
+char(7,72799).
+char(5,72800).
+char(c,72801).
+char(c,72802).
+char(p,72803).
+char(o,72804).
+char(m,72805).
+char(5,72806).
+char(6,72807).
+char(0,72808).
+char(9,72809).
+char(p,72810).
+char(3,72811).
+char(1,72812).
+char(7,72813).
+char(0,72814).
+char(p,72815).
+char(1,72816).
+char(2,72817).
+char(1,72818).
+char(0,72819).
+char(c,72820).
+char(p,72821).
+char(o,72822).
+char(o,72823).
+char(m,72824).
+char(8,72825).
+char(9,72826).
+char(6,72827).
+char(4,72828).
+char(c,72829).
+char(m,72830).
+char(7,72831).
+char(4,72832).
+char(4,72833).
+char(5,72834).
+char(c,72835).
+char(c,72836).
+char(p,72837).
+char(o,72838).
+char(o,72839).
+char(p,72840).
+char(o,72841).
+char(o,72842).
+char(o,72843).
+char(p,72844).
+char(o,72845).
+char(p,72846).
+char(o,72847).
+char(9,72848).
+char(2,72849).
+char(2,72850).
+char(1,72851).
+char(m,72852).
+char(9,72853).
+char(3,72854).
+char(3,72855).
+char(0,72856).
+char(m,72857).
+char(9,72858).
+char(9,72859).
+char(8,72860).
+char(8,72861).
+char(m,72862).
+char(1,72863).
+char(2,72864).
+char(1,72865).
+char(5,72866).
+char(c,72867).
+char(p,72868).
+char(8,72869).
+char(2,72870).
+char(8,72871).
+char(2,72872).
+char(c,72873).
+char(m,72874).
+char(9,72875).
+char(2,72876).
+char(1,72877).
+char(3,72878).
+char(p,72879).
+char(o,72880).
+char(4,72881).
+char(5,72882).
+char(7,72883).
+char(3,72884).
+char(c,72885).
+char(c,72886).
+char(c,72887).
+char(p,72888).
+char(o,72889).
+char(m,72890).
+char(1,72891).
+char(3,72892).
+char(2,72893).
+char(2,72894).
+char(p,72895).
+char(o,72896).
+char(m,72897).
+char(3,72898).
+char(7,72899).
+char(4,72900).
+char(6,72901).
+char(p,72902).
+char(1,72903).
+char(3,72904).
+char(5,72905).
+char(5,72906).
+char(p,72907).
+char(3,72908).
+char(7,72909).
+char(9,72910).
+char(6,72911).
+char(c,72912).
+char(c,72913).
+char(p,72914).
+char(o,72915).
+char(o,72916).
+char(m,72917).
+char(7,72918).
+char(2,72919).
+char(7,72920).
+char(9,72921).
+char(c,72922).
+char(m,72923).
+char(o,72924).
+char(p,72925).
+char(o,72926).
+char(o,72927).
+char(p,72928).
+char(o,72929).
+char(m,72930).
+char(o,72931).
+char(p,72932).
+char(o,72933).
+char(p,72934).
+char(7,72935).
+char(0,72936).
+char(1,72937).
+char(m,72938).
+char(o,72939).
+char(m,72940).
+char(o,72941).
+char(p,72942).
+char(o,72943).
+char(o,72944).
+char(p,72945).
+char(o,72946).
+char(o,72947).
+char(o,72948).
+char(m,72949).
+char(o,72950).
+char(m,72951).
+char(9,72952).
+char(2,72953).
+char(1,72954).
+char(9,72955).
+char(m,72956).
+char(o,72957).
+char(m,72958).
+char(9,72959).
+char(8,72960).
+char(0,72961).
+char(3,72962).
+char(c,72963).
+char(c,72964).
+char(c,72965).
+char(m,72966).
+char(o,72967).
+char(o,72968).
+char(p,72969).
+char(o,72970).
+char(o,72971).
+char(o,72972).
+char(m,72973).
+char(o,72974).
+char(m,72975).
+char(o,72976).
+char(2,72977).
+char(5,72978).
+char(5,72979).
+char(5,72980).
+char(c,72981).
+char(m,72982).
+char(4,72983).
+char(7,72984).
+char(9,72985).
+char(6,72986).
+char(c,72987).
+char(m,72988).
+char(o,72989).
+char(p,72990).
+char(4,72991).
+char(4,72992).
+char(0,72993).
+char(9,72994).
+char(c,72995).
+char(c,72996).
+char(m,72997).
+char(o,72998).
+char(m,72999).
+char(2,73000).
+char(0,73001).
+char(0,73002).
+char(9,73003).
+char(m,73004).
+char(3,73005).
+char(9,73006).
+char(8,73007).
+char(2,73008).
+char(c,73009).
+char(c,73010).
+char(c,73011).
+char(p,73012).
+char(8,73013).
+char(5,73014).
+char(2,73015).
+char(4,73016).
+char(c,73017).
+char(m,73018).
+char(8,73019).
+char(6,73020).
+char(8,73021).
+char(3,73022).
+char(c,73023).
+char(p,73024).
+char(6,73025).
+char(6,73026).
+char(5,73027).
+char(c,73028).
+char(p,73029).
+char(o,73030).
+char(m,73031).
+char(o,73032).
+char(m,73033).
+char(4,73034).
+char(3,73035).
+char(1,73036).
+char(m,73037).
+char(o,73038).
+char(4,73039).
+char(4,73040).
+char(0,73041).
+char(2,73042).
+char(c,73043).
+char(c,73044).
+char(m,73045).
+char(5,73046).
+char(2,73047).
+char(7,73048).
+char(m,73049).
+char(o,73050).
+char(o,73051).
+char(o,73052).
+char(p,73053).
+char(1,73054).
+char(7,73055).
+char(5,73056).
+char(4,73057).
+char(c,73058).
+char(p,73059).
+char(9,73060).
+char(3,73061).
+char(8,73062).
+char(8,73063).
+char(p,73064).
+char(3,73065).
+char(7,73066).
+char(0,73067).
+char(c,73068).
+char(m,73069).
+char(o,73070).
+char(o,73071).
+char(9,73072).
+char(6,73073).
+char(6,73074).
+char(0,73075).
+char(c,73076).
+char(c,73077).
+char(m,73078).
+char(6,73079).
+char(9,73080).
+char(5,73081).
+char(3,73082).
+char(c,73083).
+char(p,73084).
+char(1,73085).
+char(5,73086).
+char(6,73087).
+char(5,73088).
+char(c,73089).
+char(c,73090).
+char(p,73091).
+char(1,73092).
+char(6,73093).
+char(8,73094).
+char(0,73095).
+char(c,73096).
+char(m,73097).
+char(o,73098).
+char(m,73099).
+char(2,73100).
+char(9,73101).
+char(5,73102).
+char(8,73103).
+char(m,73104).
+char(o,73105).
+char(9,73106).
+char(8,73107).
+char(7,73108).
+char(4,73109).
+char(c,73110).
+char(m,73111).
+char(3,73112).
+char(9,73113).
+char(2,73114).
+char(4,73115).
+char(c,73116).
+char(c,73117).
+char(p,73118).
+char(o,73119).
+char(o,73120).
+char(m,73121).
+char(5,73122).
+char(1,73123).
+char(7,73124).
+char(0,73125).
+char(p,73126).
+char(o,73127).
+char(m,73128).
+char(o,73129).
+char(p,73130).
+char(2,73131).
+char(3,73132).
+char(6,73133).
+char(8,73134).
+char(p,73135).
+char(o,73136).
+char(o,73137).
+char(m,73138).
+char(o,73139).
+char(m,73140).
+char(5,73141).
+char(9,73142).
+char(5,73143).
+char(4,73144).
+char(p,73145).
+char(2,73146).
+char(4,73147).
+char(9,73148).
+char(2,73149).
+char(p,73150).
+char(o,73151).
+char(m,73152).
+char(o,73153).
+char(o,73154).
+char(m,73155).
+char(o,73156).
+char(p,73157).
+char(8,73158).
+char(8,73159).
+char(7,73160).
+char(4,73161).
+char(c,73162).
+char(p,73163).
+char(8,73164).
+char(3,73165).
+char(8,73166).
+char(8,73167).
+char(c,73168).
+char(p,73169).
+char(o,73170).
+char(p,73171).
+char(o,73172).
+char(p,73173).
+char(8,73174).
+char(3,73175).
+char(9,73176).
+char(6,73177).
+char(m,73178).
+char(6,73179).
+char(6,73180).
+char(9,73181).
+char(9,73182).
+char(c,73183).
+char(m,73184).
+char(o,73185).
+char(p,73186).
+char(o,73187).
+char(m,73188).
+char(o,73189).
+char(o,73190).
+char(4,73191).
+char(3,73192).
+char(4,73193).
+char(5,73194).
+char(m,73195).
+char(o,73196).
+char(m,73197).
+char(2,73198).
+char(5,73199).
+char(1,73200).
+char(6,73201).
+char(p,73202).
+char(7,73203).
+char(9,73204).
+char(2,73205).
+char(1,73206).
+char(p,73207).
+char(o,73208).
+char(p,73209).
+char(3,73210).
+char(6,73211).
+char(5,73212).
+char(0,73213).
+char(c,73214).
+char(c,73215).
+char(p,73216).
+char(o,73217).
+char(p,73218).
+char(o,73219).
+char(p,73220).
+char(2,73221).
+char(3,73222).
+char(4,73223).
+char(2,73224).
+char(c,73225).
+char(m,73226).
+char(6,73227).
+char(9,73228).
+char(2,73229).
+char(4,73230).
+char(p,73231).
+char(o,73232).
+char(o,73233).
+char(p,73234).
+char(9,73235).
+char(2,73236).
+char(5,73237).
+char(1,73238).
+char(p,73239).
+char(o,73240).
+char(p,73241).
+char(7,73242).
+char(0,73243).
+char(2,73244).
+char(9,73245).
+char(c,73246).
+char(c,73247).
+char(c,73248).
+char(m,73249).
+char(3,73250).
+char(7,73251).
+char(7,73252).
+char(5,73253).
+char(c,73254).
+char(p,73255).
+char(o,73256).
+char(7,73257).
+char(2,73258).
+char(2,73259).
+char(2,73260).
+char(c,73261).
+char(m,73262).
+char(9,73263).
+char(7,73264).
+char(8,73265).
+char(9,73266).
+char(p,73267).
+char(o,73268).
+char(m,73269).
+char(4,73270).
+char(6,73271).
+char(6,73272).
+char(4,73273).
+char(c,73274).
+char(p,73275).
+char(o,73276).
+char(o,73277).
+char(o,73278).
+char(p,73279).
+char(o,73280).
+char(o,73281).
+char(p,73282).
+char(6,73283).
+char(4,73284).
+char(6,73285).
+char(6,73286).
+char(p,73287).
+char(o,73288).
+char(o,73289).
+char(m,73290).
+char(1,73291).
+char(8,73292).
+char(8,73293).
+char(7,73294).
+char(c,73295).
+char(c,73296).
+char(c,73297).
+char(p,73298).
+char(6,73299).
+char(4,73300).
+char(4,73301).
+char(7,73302).
+char(m,73303).
+char(o,73304).
+char(p,73305).
+char(8,73306).
+char(4,73307).
+char(5,73308).
+char(7,73309).
+char(c,73310).
+char(c,73311).
+char(c,73312).
+char(m,73313).
+char(8,73314).
+char(9,73315).
+char(5,73316).
+char(2,73317).
+char(m,73318).
+char(o,73319).
+char(m,73320).
+char(3,73321).
+char(5,73322).
+char(9,73323).
+char(0,73324).
+char(p,73325).
+char(o,73326).
+char(p,73327).
+char(o,73328).
+char(p,73329).
+char(8,73330).
+char(1,73331).
+char(9,73332).
+char(2,73333).
+char(m,73334).
+char(7,73335).
+char(0,73336).
+char(8,73337).
+char(8,73338).
+char(c,73339).
+char(p,73340).
+char(o,73341).
+char(p,73342).
+char(8,73343).
+char(8,73344).
+char(4,73345).
+char(3,73346).
+char(p,73347).
+char(o,73348).
+char(2,73349).
+char(5,73350).
+char(1,73351).
+char(1,73352).
+char(c,73353).
+char(p,73354).
+char(o,73355).
+char(p,73356).
+char(o,73357).
+char(m,73358).
+char(1,73359).
+char(8,73360).
+char(2,73361).
+char(9,73362).
+char(c,73363).
+char(p,73364).
+char(o,73365).
+char(o,73366).
+char(p,73367).
+char(o,73368).
+char(o,73369).
+char(o,73370).
+char(o,73371).
+char(1,73372).
+char(3,73373).
+char(5,73374).
+char(3,73375).
+char(p,73376).
+char(2,73377).
+char(3,73378).
+char(6,73379).
+char(1,73380).
+char(p,73381).
+char(7,73382).
+char(0,73383).
+char(9,73384).
+char(7,73385).
+char(m,73386).
+char(o,73387).
+char(p,73388).
+char(7,73389).
+char(2,73390).
+char(0,73391).
+char(1,73392).
+char(c,73393).
+char(c,73394).
+char(c,73395).
+char(c,73396).
+char(m,73397).
+char(1,73398).
+char(9,73399).
+char(2,73400).
+char(7,73401).
+char(m,73402).
+char(o,73403).
+char(p,73404).
+char(o,73405).
+char(m,73406).
+char(2,73407).
+char(7,73408).
+char(7,73409).
+char(8,73410).
+char(c,73411).
+char(c,73412).
+char(p,73413).
+char(o,73414).
+char(o,73415).
+char(o,73416).
+char(7,73417).
+char(3,73418).
+char(3,73419).
+char(9,73420).
+char(c,73421).
+char(c,73422).
+char(p,73423).
+char(o,73424).
+char(7,73425).
+char(7,73426).
+char(6,73427).
+char(2,73428).
+char(c,73429).
+char(c,73430).
+char(m,73431).
+char(o,73432).
+char(p,73433).
+char(5,73434).
+char(1,73435).
+char(8,73436).
+char(7,73437).
+char(p,73438).
+char(9,73439).
+char(3,73440).
+char(3,73441).
+char(6,73442).
+char(c,73443).
+char(c,73444).
+char(c,73445).
+char(p,73446).
+char(4,73447).
+char(4,73448).
+char(m,73449).
+char(o,73450).
+char(1,73451).
+char(1,73452).
+char(4,73453).
+char(8,73454).
+char(c,73455).
+char(p,73456).
+char(9,73457).
+char(3,73458).
+char(3,73459).
+char(4,73460).
+char(c,73461).
+char(c,73462).
+char(c,73463).
+char(c,73464).
+char(c,73465).
+char(p,73466).
+char(4,73467).
+char(0,73468).
+char(6,73469).
+char(6,73470).
+char(p,73471).
+char(5,73472).
+char(9,73473).
+char(6,73474).
+char(2,73475).
+char(c,73476).
+char(c,73477).
+char(p,73478).
+char(o,73479).
+char(7,73480).
+char(5,73481).
+char(0,73482).
+char(p,73483).
+char(6,73484).
+char(8,73485).
+char(0,73486).
+char(7,73487).
+char(c,73488).
+char(c,73489).
+char(m,73490).
+char(5,73491).
+char(0,73492).
+char(2,73493).
+char(6,73494).
+char(m,73495).
+char(6,73496).
+char(1,73497).
+char(5,73498).
+char(6,73499).
+char(p,73500).
+char(1,73501).
+char(0,73502).
+char(7,73503).
+char(9,73504).
+char(c,73505).
+char(m,73506).
+char(o,73507).
+char(p,73508).
+char(3,73509).
+char(4,73510).
+char(0,73511).
+char(4,73512).
+char(p,73513).
+char(8,73514).
+char(3,73515).
+char(6,73516).
+char(4,73517).
+char(p,73518).
+char(5,73519).
+char(4,73520).
+char(9,73521).
+char(8,73522).
+char(c,73523).
+char(m,73524).
+char(o,73525).
+char(9,73526).
+char(4,73527).
+char(4,73528).
+char(3,73529).
+char(c,73530).
+char(m,73531).
+char(1,73532).
+char(8,73533).
+char(1,73534).
+char(4,73535).
+char(c,73536).
+char(c,73537).
+char(c,73538).
+char(c,73539).
+char(c,73540).
+char(m,73541).
+char(o,73542).
+char(m,73543).
+char(o,73544).
+char(p,73545).
+char(o,73546).
+char(p,73547).
+char(o,73548).
+char(m,73549).
+char(6,73550).
+char(5,73551).
+char(3,73552).
+char(4,73553).
+char(c,73554).
+char(c,73555).
+char(c,73556).
+char(p,73557).
+char(o,73558).
+char(p,73559).
+char(o,73560).
+char(1,73561).
+char(8,73562).
+char(5,73563).
+char(4,73564).
+char(m,73565).
+char(3,73566).
+char(2,73567).
+char(9,73568).
+char(5,73569).
+char(c,73570).
+char(c,73571).
+char(c,73572).
+char(c,73573).
+char(p,73574).
+char(o,73575).
+char(o,73576).
+char(m,73577).
+char(2,73578).
+char(4,73579).
+char(1,73580).
+char(3,73581).
+char(p,73582).
+char(8,73583).
+char(3,73584).
+char(7,73585).
+char(2,73586).
+char(m,73587).
+char(o,73588).
+char(2,73589).
+char(7,73590).
+char(6,73591).
+char(6,73592).
+char(c,73593).
+char(c,73594).
+char(p,73595).
+char(o,73596).
+char(o,73597).
+char(m,73598).
+char(o,73599).
+char(1,73600).
+char(8,73601).
+char(0,73602).
+char(2,73603).
+char(p,73604).
+char(1,73605).
+char(8,73606).
+char(8,73607).
+char(3,73608).
+char(c,73609).
+char(c,73610).
+char(c,73611).
+char(c,73612).
+char(p,73613).
+char(o,73614).
+char(p,73615).
+char(2,73616).
+char(8,73617).
+char(9,73618).
+char(m,73619).
+char(o,73620).
+char(o,73621).
+char(8,73622).
+char(2,73623).
+char(3,73624).
+char(3,73625).
+char(p,73626).
+char(4,73627).
+char(8,73628).
+char(5,73629).
+char(0,73630).
+char(m,73631).
+char(o,73632).
+char(m,73633).
+char(o,73634).
+char(1,73635).
+char(0,73636).
+char(4,73637).
+char(0,73638).
+char(c,73639).
+char(m,73640).
+char(9,73641).
+char(4,73642).
+char(9,73643).
+char(7,73644).
+char(m,73645).
+char(4,73646).
+char(9,73647).
+char(6,73648).
+char(0,73649).
+char(m,73650).
+char(o,73651).
+char(p,73652).
+char(2,73653).
+char(1,73654).
+char(1,73655).
+char(7,73656).
+char(c,73657).
+char(p,73658).
+char(8,73659).
+char(2,73660).
+char(5,73661).
+char(9,73662).
+char(c,73663).
+char(p,73664).
+char(o,73665).
+char(m,73666).
+char(o,73667).
+char(o,73668).
+char(p,73669).
+char(o,73670).
+char(p,73671).
+char(o,73672).
+char(m,73673).
+char(5,73674).
+char(4,73675).
+char(4,73676).
+char(8,73677).
+char(c,73678).
+char(c,73679).
+char(m,73680).
+char(7,73681).
+char(6,73682).
+char(3,73683).
+char(9,73684).
+char(m,73685).
+char(o,73686).
+char(m,73687).
+char(o,73688).
+char(m,73689).
+char(o,73690).
+char(o,73691).
+char(p,73692).
+char(o,73693).
+char(m,73694).
+char(o,73695).
+char(8,73696).
+char(2,73697).
+char(9,73698).
+char(8,73699).
+char(c,73700).
+char(m,73701).
+char(o,73702).
+char(3,73703).
+char(0,73704).
+char(0,73705).
+char(0,73706).
+char(c,73707).
+char(p,73708).
+char(o,73709).
+char(m,73710).
+char(9,73711).
+char(5,73712).
+char(1,73713).
+char(4,73714).
+char(c,73715).
+char(m,73716).
+char(o,73717).
+char(m,73718).
+char(8,73719).
+char(9,73720).
+char(9,73721).
+char(5,73722).
+char(m,73723).
+char(o,73724).
+char(p,73725).
+char(6,73726).
+char(8,73727).
+char(4,73728).
+char(6,73729).
+char(c,73730).
+char(c,73731).
+char(m,73732).
+char(o,73733).
+char(m,73734).
+char(3,73735).
+char(4,73736).
+char(1,73737).
+char(0,73738).
+char(m,73739).
+char(o,73740).
+char(p,73741).
+char(o,73742).
+char(p,73743).
+char(o,73744).
+char(m,73745).
+char(6,73746).
+char(0,73747).
+char(8,73748).
+char(9,73749).
+char(c,73750).
+char(c,73751).
+char(c,73752).
+char(c,73753).
+char(p,73754).
+char(o,73755).
+char(p,73756).
+char(3,73757).
+char(0,73758).
+char(8,73759).
+char(0,73760).
+char(m,73761).
+char(6,73762).
+char(3,73763).
+char(9,73764).
+char(4,73765).
+char(m,73766).
+char(o,73767).
+char(1,73768).
+char(5,73769).
+char(5,73770).
+char(3,73771).
+char(c,73772).
+char(c,73773).
+char(c,73774).
+char(c,73775).
+char(p,73776).
+char(o,73777).
+char(5,73778).
+char(9,73779).
+char(2,73780).
+char(6,73781).
+char(c,73782).
+char(p,73783).
+char(o,73784).
+char(o,73785).
+char(p,73786).
+char(9,73787).
+char(1,73788).
+char(0,73789).
+char(6,73790).
+char(c,73791).
+char(c,73792).
+char(c,73793).
+char(p,73794).
+char(o,73795).
+char(p,73796).
+char(2,73797).
+char(0,73798).
+char(2,73799).
+char(8,73800).
+char(c,73801).
+char(c,73802).
+char(c,73803).
+char(m,73804).
+char(o,73805).
+char(o,73806).
+char(o,73807).
+char(o,73808).
+char(p,73809).
+char(6,73810).
+char(8,73811).
+char(0,73812).
+char(7,73813).
+char(m,73814).
+char(o,73815).
+char(p,73816).
+char(3,73817).
+char(3,73818).
+char(6,73819).
+char(2,73820).
+char(c,73821).
+char(p,73822).
+char(7,73823).
+char(4,73824).
+char(5,73825).
+char(7,73826).
+char(m,73827).
+char(o,73828).
+char(7,73829).
+char(4,73830).
+char(8,73831).
+char(9,73832).
+char(p,73833).
+char(7,73834).
+char(8,73835).
+char(6,73836).
+char(1,73837).
+char(c,73838).
+char(m,73839).
+char(4,73840).
+char(5,73841).
+char(6,73842).
+char(9,73843).
+char(c,73844).
+char(c,73845).
+char(c,73846).
+char(c,73847).
+char(c,73848).
+char(p,73849).
+char(2,73850).
+char(5,73851).
+char(9,73852).
+char(7,73853).
+char(c,73854).
+char(p,73855).
+char(o,73856).
+char(p,73857).
+char(2,73858).
+char(5,73859).
+char(9,73860).
+char(4,73861).
+char(c,73862).
+char(m,73863).
+char(7,73864).
+char(2,73865).
+char(9,73866).
+char(6,73867).
+char(p,73868).
+char(o,73869).
+char(p,73870).
+char(o,73871).
+char(m,73872).
+char(5,73873).
+char(4,73874).
+char(9,73875).
+char(1,73876).
+char(c,73877).
+char(p,73878).
+char(3,73879).
+char(3,73880).
+char(0,73881).
+char(5,73882).
+char(p,73883).
+char(o,73884).
+char(m,73885).
+char(o,73886).
+char(m,73887).
+char(o,73888).
+char(8,73889).
+char(1,73890).
+char(4,73891).
+char(7,73892).
+char(c,73893).
+char(c,73894).
+char(c,73895).
+char(c,73896).
+char(c,73897).
+char(c,73898).
+char(m,73899).
+char(8,73900).
+char(3,73901).
+char(9,73902).
+char(m,73903).
+char(o,73904).
+char(m,73905).
+char(8,73906).
+char(2,73907).
+char(2,73908).
+char(1,73909).
+char(p,73910).
+char(o,73911).
+char(p,73912).
+char(6,73913).
+char(4,73914).
+char(9,73915).
+char(9,73916).
+char(c,73917).
+char(c,73918).
+char(p,73919).
+char(2,73920).
+char(2,73921).
+char(6,73922).
+char(4,73923).
+char(c,73924).
+char(m,73925).
+char(8,73926).
+char(5,73927).
+char(7,73928).
+char(0,73929).
+char(p,73930).
+char(o,73931).
+char(m,73932).
+char(7,73933).
+char(0,73934).
+char(5,73935).
+char(9,73936).
+char(p,73937).
+char(o,73938).
+char(4,73939).
+char(7,73940).
+char(3,73941).
+char(c,73942).
+char(p,73943).
+char(8,73944).
+char(9,73945).
+char(3,73946).
+char(c,73947).
+char(c,73948).
+char(c,73949).
+char(c,73950).
+char(m,73951).
+char(o,73952).
+char(o,73953).
+char(m,73954).
+char(4,73955).
+char(2,73956).
+char(9,73957).
+char(2,73958).
+char(c,73959).
+char(m,73960).
+char(o,73961).
+char(p,73962).
+char(o,73963).
+char(5,73964).
+char(8,73965).
+char(5,73966).
+char(5,73967).
+char(c,73968).
+char(c,73969).
+char(c,73970).
+char(m,73971).
+char(4,73972).
+char(5,73973).
+char(4,73974).
+char(3,73975).
+char(c,73976).
+char(c,73977).
+char(c,73978).
+char(m,73979).
+char(4,73980).
+char(5,73981).
+char(1,73982).
+char(2,73983).
+char(c,73984).
+char(m,73985).
+char(o,73986).
+char(m,73987).
+char(o,73988).
+char(o,73989).
+char(p,73990).
+char(o,73991).
+char(5,73992).
+char(9,73993).
+char(1,73994).
+char(8,73995).
+char(c,73996).
+char(c,73997).
+char(m,73998).
+char(1,73999).
+char(2,74000).
+char(9,74001).
+char(1,74002).
+char(c,74003).
+char(c,74004).
+char(p,74005).
+char(1,74006).
+char(0,74007).
+char(2,74008).
+char(8,74009).
+char(p,74010).
+char(o,74011).
+char(p,74012).
+char(5,74013).
+char(4,74014).
+char(4,74015).
+char(2,74016).
+char(m,74017).
+char(o,74018).
+char(p,74019).
+char(o,74020).
+char(p,74021).
+char(o,74022).
+char(p,74023).
+char(o,74024).
+char(p,74025).
+char(o,74026).
+char(3,74027).
+char(0,74028).
+char(6,74029).
+char(2,74030).
+char(c,74031).
+char(m,74032).
+char(o,74033).
+char(m,74034).
+char(3,74035).
+char(1,74036).
+char(6,74037).
+char(4,74038).
+char(c,74039).
+char(c,74040).
+char(p,74041).
+char(o,74042).
+char(p,74043).
+char(o,74044).
+char(m,74045).
+char(5,74046).
+char(1,74047).
+char(8,74048).
+char(6,74049).
+char(c,74050).
+char(c,74051).
+char(c,74052).
+char(m,74053).
+char(8,74054).
+char(5,74055).
+char(9,74056).
+char(c,74057).
+char(c,74058).
+char(c,74059).
+char(c,74060).
+char(m,74061).
+char(1,74062).
+char(1,74063).
+char(1,74064).
+char(2,74065).
+char(m,74066).
+char(2,74067).
+char(7,74068).
+char(2,74069).
+char(6,74070).
+char(m,74071).
+char(9,74072).
+char(3,74073).
+char(0,74074).
+char(8,74075).
+char(m,74076).
+char(5,74077).
+char(0,74078).
+char(6,74079).
+char(9,74080).
+char(m,74081).
+char(o,74082).
+char(o,74083).
+char(o,74084).
+char(o,74085).
+char(m,74086).
+char(o,74087).
+char(m,74088).
+char(1,74089).
+char(1,74090).
+char(5,74091).
+char(3,74092).
+char(p,74093).
+char(5,74094).
+char(7,74095).
+char(4,74096).
+char(6,74097).
+char(p,74098).
+char(8,74099).
+char(3,74100).
+char(5,74101).
+char(9,74102).
+char(c,74103).
+char(c,74104).
+char(p,74105).
+char(2,74106).
+char(9,74107).
+char(3,74108).
+char(9,74109).
+char(c,74110).
+char(p,74111).
+char(9,74112).
+char(1,74113).
+char(0,74114).
+char(1,74115).
+char(m,74116).
+char(o,74117).
+char(o,74118).
+char(m,74119).
+char(o,74120).
+char(m,74121).
+char(o,74122).
+char(m,74123).
+char(6,74124).
+char(8,74125).
+char(1,74126).
+char(3,74127).
+char(c,74128).
+char(c,74129).
+char(c,74130).
+char(p,74131).
+char(o,74132).
+char(o,74133).
+char(p,74134).
+char(o,74135).
+char(m,74136).
+char(o,74137).
+char(7,74138).
+char(2,74139).
+char(2,74140).
+char(2,74141).
+char(c,74142).
+char(c,74143).
+char(c,74144).
+char(p,74145).
+char(o,74146).
+char(p,74147).
+char(o,74148).
+char(2,74149).
+char(5,74150).
+char(8,74151).
+char(m,74152).
+char(o,74153).
+char(m,74154).
+char(o,74155).
+char(p,74156).
+char(o,74157).
+char(3,74158).
+char(1,74159).
+char(9,74160).
+char(2,74161).
+char(c,74162).
+char(p,74163).
+char(o,74164).
+char(5,74165).
+char(4,74166).
+char(2,74167).
+char(4,74168).
+char(c,74169).
+char(p,74170).
+char(1,74171).
+char(4,74172).
+char(5,74173).
+char(0,74174).
+char(m,74175).
+char(6,74176).
+char(3,74177).
+char(0,74178).
+char(1,74179).
+char(p,74180).
+char(o,74181).
+char(o,74182).
+char(p,74183).
+char(o,74184).
+char(p,74185).
+char(o,74186).
+char(m,74187).
+char(o,74188).
+char(1,74189).
+char(1,74190).
+char(8,74191).
+char(3,74192).
+char(m,74193).
+char(6,74194).
+char(2,74195).
+char(2,74196).
+char(1,74197).
+char(c,74198).
+char(p,74199).
+char(3,74200).
+char(3,74201).
+char(1,74202).
+char(1,74203).
+char(c,74204).
+char(m,74205).
+char(o,74206).
+char(p,74207).
+char(5,74208).
+char(7,74209).
+char(2,74210).
+char(3,74211).
+char(c,74212).
+char(c,74213).
+char(m,74214).
+char(4,74215).
+char(5,74216).
+char(5,74217).
+char(3,74218).
+char(p,74219).
+char(8,74220).
+char(7,74221).
+char(4,74222).
+char(7,74223).
+char(c,74224).
+char(p,74225).
+char(9,74226).
+char(5,74227).
+char(5,74228).
+char(9,74229).
+char(c,74230).
+char(c,74231).
+char(c,74232).
+char(c,74233).
+char(m,74234).
+char(2,74235).
+char(1,74236).
+char(2,74237).
+char(3,74238).
+char(c,74239).
+char(c,74240).
+char(m,74241).
+char(7,74242).
+char(6,74243).
+char(1,74244).
+char(c,74245).
+char(c,74246).
+char(p,74247).
+char(o,74248).
+char(3,74249).
+char(1,74250).
+char(3,74251).
+char(0,74252).
+char(m,74253).
+char(o,74254).
+char(m,74255).
+char(8,74256).
+char(9,74257).
+char(3,74258).
+char(m,74259).
+char(2,74260).
+char(7,74261).
+char(0,74262).
+char(0,74263).
+char(p,74264).
+char(o,74265).
+char(o,74266).
+char(p,74267).
+char(o,74268).
+char(p,74269).
+char(7,74270).
+char(6,74271).
+char(4,74272).
+char(4,74273).
+char(c,74274).
+char(c,74275).
+char(c,74276).
+char(m,74277).
+char(7,74278).
+char(4,74279).
+char(3,74280).
+char(7,74281).
+char(m,74282).
+char(3,74283).
+char(6,74284).
+char(3,74285).
+char(1,74286).
+char(c,74287).
+char(c,74288).
+char(m,74289).
+char(9,74290).
+char(3,74291).
+char(7,74292).
+char(3,74293).
+char(m,74294).
+char(4,74295).
+char(9,74296).
+char(1,74297).
+char(4,74298).
+char(c,74299).
+char(m,74300).
+char(3,74301).
+char(1,74302).
+char(2,74303).
+char(1,74304).
+char(m,74305).
+char(o,74306).
+char(p,74307).
+char(o,74308).
+char(m,74309).
+char(o,74310).
+char(p,74311).
+char(o,74312).
+char(o,74313).
+char(p,74314).
+char(3,74315).
+char(6,74316).
+char(6,74317).
+char(7,74318).
+char(c,74319).
+char(m,74320).
+char(o,74321).
+char(p,74322).
+char(o,74323).
+char(m,74324).
+char(1,74325).
+char(8,74326).
+char(9,74327).
+char(5,74328).
+char(p,74329).
+char(2,74330).
+char(6,74331).
+char(8,74332).
+char(4,74333).
+char(p,74334).
+char(o,74335).
+char(m,74336).
+char(5,74337).
+char(8,74338).
+char(4,74339).
+char(6,74340).
+char(c,74341).
+char(c,74342).
+char(c,74343).
+char(m,74344).
+char(5,74345).
+char(9,74346).
+char(8,74347).
+char(3,74348).
+char(c,74349).
+char(c,74350).
+char(c,74351).
+char(p,74352).
+char(o,74353).
+char(p,74354).
+char(o,74355).
+char(m,74356).
+char(o,74357).
+char(p,74358).
+char(3,74359).
+char(9,74360).
+char(5,74361).
+char(0,74362).
+char(p,74363).
+char(o,74364).
+char(p,74365).
+char(2,74366).
+char(3,74367).
+char(5,74368).
+char(1,74369).
+char(c,74370).
+char(p,74371).
+char(o,74372).
+char(p,74373).
+char(o,74374).
+char(o,74375).
+char(m,74376).
+char(7,74377).
+char(8,74378).
+char(m,74379).
+char(8,74380).
+char(4,74381).
+char(0,74382).
+char(7,74383).
+char(m,74384).
+char(5,74385).
+char(3,74386).
+char(7,74387).
+char(2,74388).
+char(c,74389).
+char(p,74390).
+char(5,74391).
+char(6,74392).
+char(9,74393).
+char(1,74394).
+char(m,74395).
+char(3,74396).
+char(1,74397).
+char(1,74398).
+char(3,74399).
+char(p,74400).
+char(o,74401).
+char(o,74402).
+char(m,74403).
+char(o,74404).
+char(m,74405).
+char(9,74406).
+char(6,74407).
+char(9,74408).
+char(3,74409).
+char(m,74410).
+char(3,74411).
+char(1,74412).
+char(0,74413).
+char(6,74414).
+char(c,74415).
+char(m,74416).
+char(o,74417).
+char(2,74418).
+char(6,74419).
+char(7,74420).
+char(c,74421).
+char(c,74422).
+char(m,74423).
+char(7,74424).
+char(3,74425).
+char(7,74426).
+char(6,74427).
+char(p,74428).
+char(o,74429).
+char(o,74430).
+char(6,74431).
+char(0,74432).
+char(5,74433).
+char(6,74434).
+char(m,74435).
+char(o,74436).
+char(6,74437).
+char(3,74438).
+char(1,74439).
+char(4,74440).
+char(m,74441).
+char(5,74442).
+char(6,74443).
+char(3,74444).
+char(8,74445).
+char(m,74446).
+char(5,74447).
+char(0,74448).
+char(9,74449).
+char(4,74450).
+char(c,74451).
+char(c,74452).
+char(p,74453).
+char(6,74454).
+char(9,74455).
+char(8,74456).
+char(6,74457).
+char(m,74458).
+char(o,74459).
+char(m,74460).
+char(o,74461).
+char(m,74462).
+char(4,74463).
+char(7,74464).
+char(5,74465).
+char(8,74466).
+char(c,74467).
+char(p,74468).
+char(8,74469).
+char(5,74470).
+char(1,74471).
+char(4,74472).
+char(m,74473).
+char(7,74474).
+char(5,74475).
+char(5,74476).
+char(0,74477).
+char(p,74478).
+char(o,74479).
+char(p,74480).
+char(2,74481).
+char(0,74482).
+char(9,74483).
+char(m,74484).
+char(o,74485).
+char(m,74486).
+char(9,74487).
+char(7,74488).
+char(9,74489).
+char(c,74490).
+char(c,74491).
+char(m,74492).
+char(o,74493).
+char(m,74494).
+char(o,74495).
+char(o,74496).
+char(o,74497).
+char(p,74498).
+char(3,74499).
+char(9,74500).
+char(5,74501).
+char(4,74502).
+char(c,74503).
+char(m,74504).
+char(9,74505).
+char(1,74506).
+char(5,74507).
+char(3,74508).
+char(p,74509).
+char(3,74510).
+char(6,74511).
+char(6,74512).
+char(4,74513).
+char(c,74514).
+char(p,74515).
+char(6,74516).
+char(8,74517).
+char(7,74518).
+char(5,74519).
+char(p,74520).
+char(5,74521).
+char(5,74522).
+char(2,74523).
+char(c,74524).
+char(c,74525).
+char(m,74526).
+char(4,74527).
+char(2,74528).
+char(2,74529).
+char(2,74530).
+char(p,74531).
+char(7,74532).
+char(1,74533).
+char(m,74534).
+char(o,74535).
+char(m,74536).
+char(o,74537).
+char(o,74538).
+char(m,74539).
+char(o,74540).
+char(m,74541).
+char(1,74542).
+char(0,74543).
+char(6,74544).
+char(7,74545).
+char(p,74546).
+char(4,74547).
+char(9,74548).
+char(8,74549).
+char(8,74550).
+char(c,74551).
+char(c,74552).
+char(p,74553).
+char(9,74554).
+char(9,74555).
+char(5,74556).
+char(1,74557).
+char(m,74558).
+char(o,74559).
+char(p,74560).
+char(o,74561).
+char(o,74562).
+char(p,74563).
+char(o,74564).
+char(o,74565).
+char(p,74566).
+char(7,74567).
+char(2,74568).
+char(0,74569).
+char(1,74570).
+char(p,74571).
+char(2,74572).
+char(4,74573).
+char(7,74574).
+char(5,74575).
+char(c,74576).
+char(m,74577).
+char(o,74578).
+char(p,74579).
+char(o,74580).
+char(o,74581).
+char(p,74582).
+char(o,74583).
+char(o,74584).
+char(m,74585).
+char(o,74586).
+char(p,74587).
+char(o,74588).
+char(m,74589).
+char(o,74590).
+char(o,74591).
+char(m,74592).
+char(o,74593).
+char(o,74594).
+char(p,74595).
+char(6,74596).
+char(4,74597).
+char(2,74598).
+char(2,74599).
+char(c,74600).
+char(p,74601).
+char(2,74602).
+char(3,74603).
+char(2,74604).
+char(8,74605).
+char(c,74606).
+char(p,74607).
+char(4,74608).
+char(0,74609).
+char(3,74610).
+char(5,74611).
+char(c,74612).
+char(c,74613).
+char(c,74614).
+char(c,74615).
+char(p,74616).
+char(o,74617).
+char(p,74618).
+char(o,74619).
+char(o,74620).
+char(m,74621).
+char(6,74622).
+char(4,74623).
+char(5,74624).
+char(6,74625).
+char(c,74626).
+char(c,74627).
+char(c,74628).
+char(p,74629).
+char(4,74630).
+char(0,74631).
+char(6,74632).
+char(1,74633).
+char(c,74634).
+char(m,74635).
+char(o,74636).
+char(m,74637).
+char(o,74638).
+char(p,74639).
+char(4,74640).
+char(5,74641).
+char(3,74642).
+char(7,74643).
+char(p,74644).
+char(o,74645).
+char(o,74646).
+char(9,74647).
+char(8,74648).
+char(3,74649).
+char(1,74650).
+char(c,74651).
+char(m,74652).
+char(8,74653).
+char(9,74654).
+char(9,74655).
+char(4,74656).
+char(m,74657).
+char(6,74658).
+char(6,74659).
+char(7,74660).
+char(8,74661).
+char(m,74662).
+char(o,74663).
+char(o,74664).
+char(o,74665).
+char(2,74666).
+char(0,74667).
+char(7,74668).
+char(5,74669).
+char(c,74670).
+char(c,74671).
+char(p,74672).
+char(6,74673).
+char(6,74674).
+char(5,74675).
+char(6,74676).
+char(c,74677).
+char(c,74678).
+char(p,74679).
+char(o,74680).
+char(m,74681).
+char(6,74682).
+char(6,74683).
+char(8,74684).
+char(0,74685).
+char(m,74686).
+char(1,74687).
+char(8,74688).
+char(9,74689).
+char(2,74690).
+char(p,74691).
+char(o,74692).
+char(2,74693).
+char(5,74694).
+char(4,74695).
+char(6,74696).
+char(c,74697).
+char(c,74698).
+char(c,74699).
+char(p,74700).
+char(o,74701).
+char(p,74702).
+char(2,74703).
+char(0,74704).
+char(8,74705).
+char(0,74706).
+char(m,74707).
+char(6,74708).
+char(0,74709).
+char(9,74710).
+char(0,74711).
+char(m,74712).
+char(6,74713).
+char(3,74714).
+char(7,74715).
+char(9,74716).
+char(m,74717).
+char(9,74718).
+char(6,74719).
+char(3,74720).
+char(5,74721).
+char(c,74722).
+char(c,74723).
+char(c,74724).
+char(m,74725).
+char(o,74726).
+char(p,74727).
+char(1,74728).
+char(8,74729).
+char(5,74730).
+char(3,74731).
+char(c,74732).
+char(m,74733).
+char(o,74734).
+char(m,74735).
+char(4,74736).
+char(5,74737).
+char(1,74738).
+char(0,74739).
+char(c,74740).
+char(c,74741).
+char(p,74742).
+char(o,74743).
+char(p,74744).
+char(o,74745).
+char(4,74746).
+char(9,74747).
+char(9,74748).
+char(3,74749).
+char(c,74750).
+char(c,74751).
+char(c,74752).
+char(c,74753).
+char(c,74754).
+char(m,74755).
+char(8,74756).
+char(7,74757).
+char(1,74758).
+char(1,74759).
+char(c,74760).
+char(c,74761).
+char(p,74762).
+char(7,74763).
+char(5,74764).
+char(5,74765).
+char(1,74766).
+char(p,74767).
+char(5,74768).
+char(5,74769).
+char(8,74770).
+char(2,74771).
+char(p,74772).
+char(o,74773).
+char(m,74774).
+char(o,74775).
+char(m,74776).
+char(9,74777).
+char(9,74778).
+char(7,74779).
+char(9,74780).
+char(m,74781).
+char(3,74782).
+char(4,74783).
+char(8,74784).
+char(4,74785).
+char(c,74786).
+char(m,74787).
+char(9,74788).
+char(8,74789).
+char(0,74790).
+char(6,74791).
+char(p,74792).
+char(7,74793).
+char(3,74794).
+char(7,74795).
+char(4,74796).
+char(c,74797).
+char(m,74798).
+char(8,74799).
+char(9,74800).
+char(6,74801).
+char(8,74802).
+char(m,74803).
+char(7,74804).
+char(6,74805).
+char(4,74806).
+char(5,74807).
+char(p,74808).
+char(o,74809).
+char(p,74810).
+char(o,74811).
+char(6,74812).
+char(5,74813).
+char(5,74814).
+char(2,74815).
+char(c,74816).
+char(c,74817).
+char(m,74818).
+char(2,74819).
+char(5,74820).
+char(3,74821).
+char(6,74822).
+char(m,74823).
+char(o,74824).
+char(p,74825).
+char(5,74826).
+char(7,74827).
+char(3,74828).
+char(8,74829).
+char(c,74830).
+char(c,74831).
+char(p,74832).
+char(o,74833).
+char(p,74834).
+char(8,74835).
+char(9,74836).
+char(7,74837).
+char(3,74838).
+char(m,74839).
+char(o,74840).
+char(4,74841).
+char(7,74842).
+char(8,74843).
+char(3,74844).
+char(c,74845).
+char(c,74846).
+char(p,74847).
+char(1,74848).
+char(4,74849).
+char(7,74850).
+char(9,74851).
+char(m,74852).
+char(1,74853).
+char(3,74854).
+char(2,74855).
+char(3,74856).
+char(c,74857).
+char(m,74858).
+char(o,74859).
+char(p,74860).
+char(o,74861).
+char(m,74862).
+char(o,74863).
+char(m,74864).
+char(o,74865).
+char(m,74866).
+char(o,74867).
+char(m,74868).
+char(3,74869).
+char(4,74870).
+char(7,74871).
+char(1,74872).
+char(m,74873).
+char(o,74874).
+char(m,74875).
+char(8,74876).
+char(1,74877).
+char(4,74878).
+char(c,74879).
+char(p,74880).
+char(2,74881).
+char(9,74882).
+char(7,74883).
+char(6,74884).
+char(c,74885).
+char(c,74886).
+char(c,74887).
+char(p,74888).
+char(9,74889).
+char(9,74890).
+char(1,74891).
+char(8,74892).
+char(m,74893).
+char(o,74894).
+char(m,74895).
+char(1,74896).
+char(7,74897).
+char(6,74898).
+char(2,74899).
+char(c,74900).
+char(m,74901).
+char(1,74902).
+char(8,74903).
+char(9,74904).
+char(5,74905).
+char(p,74906).
+char(o,74907).
+char(p,74908).
+char(o,74909).
+char(m,74910).
+char(5,74911).
+char(2,74912).
+char(1,74913).
+char(6,74914).
+char(m,74915).
+char(9,74916).
+char(4,74917).
+char(5,74918).
+char(5,74919).
+char(c,74920).
+char(m,74921).
+char(o,74922).
+char(m,74923).
+char(o,74924).
+char(o,74925).
+char(m,74926).
+char(4,74927).
+char(6,74928).
+char(4,74929).
+char(4,74930).
+char(m,74931).
+char(7,74932).
+char(8,74933).
+char(5,74934).
+char(0,74935).
+char(p,74936).
+char(o,74937).
+char(o,74938).
+char(p,74939).
+char(o,74940).
+char(m,74941).
+char(o,74942).
+char(p,74943).
+char(o,74944).
+char(p,74945).
+char(o,74946).
+char(p,74947).
+char(1,74948).
+char(8,74949).
+char(4,74950).
+char(9,74951).
+char(c,74952).
+char(p,74953).
+char(o,74954).
+char(m,74955).
+char(o,74956).
+char(p,74957).
+char(o,74958).
+char(m,74959).
+char(4,74960).
+char(9,74961).
+char(7,74962).
+char(2,74963).
+char(c,74964).
+char(m,74965).
+char(o,74966).
+char(m,74967).
+char(6,74968).
+char(5,74969).
+char(5,74970).
+char(9,74971).
+char(c,74972).
+char(p,74973).
+char(o,74974).
+char(p,74975).
+char(o,74976).
+char(1,74977).
+char(1,74978).
+char(9,74979).
+char(3,74980).
+char(c,74981).
+char(m,74982).
+char(5,74983).
+char(4,74984).
+char(6,74985).
+char(3,74986).
+char(c,74987).
+char(p,74988).
+char(8,74989).
+char(6,74990).
+char(6,74991).
+char(9,74992).
+char(p,74993).
+char(1,74994).
+char(7,74995).
+char(5,74996).
+char(9,74997).
+char(c,74998).
+char(m,74999).
+char(o,75000).
+char(o,75001).
+char(p,75002).
+char(o,75003).
+char(p,75004).
+char(o,75005).
+char(o,75006).
+char(m,75007).
+char(9,75008).
+char(2,75009).
+char(3,75010).
+char(9,75011).
+char(m,75012).
+char(5,75013).
+char(1,75014).
+char(9,75015).
+char(8,75016).
+char(c,75017).
+char(p,75018).
+char(5,75019).
+char(3,75020).
+char(4,75021).
+char(p,75022).
+char(o,75023).
+char(p,75024).
+char(o,75025).
+char(p,75026).
+char(o,75027).
+char(m,75028).
+char(1,75029).
+char(4,75030).
+char(1,75031).
+char(c,75032).
+char(c,75033).
+char(p,75034).
+char(o,75035).
+char(p,75036).
+char(o,75037).
+char(m,75038).
+char(8,75039).
+char(8,75040).
+char(6,75041).
+char(5,75042).
+char(m,75043).
+char(o,75044).
+char(o,75045).
+char(m,75046).
+char(2,75047).
+char(5,75048).
+char(8,75049).
+char(4,75050).
+char(c,75051).
+char(c,75052).
+char(c,75053).
+char(m,75054).
+char(o,75055).
+char(m,75056).
+char(o,75057).
+char(m,75058).
+char(o,75059).
+char(o,75060).
+char(p,75061).
+char(o,75062).
+char(m,75063).
+char(o,75064).
+char(p,75065).
+char(o,75066).
+char(p,75067).
+char(o,75068).
+char(o,75069).
+char(5,75070).
+char(0,75071).
+char(0,75072).
+char(7,75073).
+char(c,75074).
+char(m,75075).
+char(1,75076).
+char(8,75077).
+char(0,75078).
+char(1,75079).
+char(p,75080).
+char(o,75081).
+char(3,75082).
+char(3,75083).
+char(0,75084).
+char(4,75085).
+char(c,75086).
+char(p,75087).
+char(o,75088).
+char(p,75089).
+char(2,75090).
+char(4,75091).
+char(8,75092).
+char(9,75093).
+char(p,75094).
+char(o,75095).
+char(p,75096).
+char(o,75097).
+char(p,75098).
+char(3,75099).
+char(3,75100).
+char(6,75101).
+char(c,75102).
+char(c,75103).
+char(c,75104).
+char(c,75105).
+char(m,75106).
+char(5,75107).
+char(3,75108).
+char(8,75109).
+char(5,75110).
+char(c,75111).
+char(p,75112).
+char(o,75113).
+char(p,75114).
+char(o,75115).
+char(6,75116).
+char(2,75117).
+char(1,75118).
+char(7,75119).
+char(c,75120).
+char(m,75121).
+char(4,75122).
+char(0,75123).
+char(9,75124).
+char(8,75125).
+char(m,75126).
+char(o,75127).
+char(p,75128).
+char(8,75129).
+char(3,75130).
+char(8,75131).
+char(2,75132).
+char(p,75133).
+char(o,75134).
+char(5,75135).
+char(1,75136).
+char(0,75137).
+char(6,75138).
+char(m,75139).
+char(o,75140).
+char(m,75141).
+char(2,75142).
+char(6,75143).
+char(6,75144).
+char(1,75145).
+char(c,75146).
+char(c,75147).
+char(m,75148).
+char(7,75149).
+char(1,75150).
+char(9,75151).
+char(9,75152).
+char(c,75153).
+char(p,75154).
+char(4,75155).
+char(0,75156).
+char(1,75157).
+char(6,75158).
+char(m,75159).
+char(9,75160).
+char(9,75161).
+char(4,75162).
+char(8,75163).
+char(c,75164).
+char(c,75165).
+char(c,75166).
+char(c,75167).
+char(c,75168).
+char(c,75169).
+char(c,75170).
+char(p,75171).
+char(3,75172).
+char(8,75173).
+char(7,75174).
+char(0,75175).
+char(c,75176).
+char(c,75177).
+char(p,75178).
+char(8,75179).
+char(6,75180).
+char(0,75181).
+char(0,75182).
+char(p,75183).
+char(7,75184).
+char(6,75185).
+char(1,75186).
+char(8,75187).
+char(c,75188).
+char(p,75189).
+char(9,75190).
+char(3,75191).
+char(1,75192).
+char(6,75193).
+char(m,75194).
+char(o,75195).
+char(m,75196).
+char(o,75197).
+char(p,75198).
+char(8,75199).
+char(6,75200).
+char(6,75201).
+char(5,75202).
+char(m,75203).
+char(o,75204).
+char(m,75205).
+char(o,75206).
+char(p,75207).
+char(o,75208).
+char(5,75209).
+char(7,75210).
+char(3,75211).
+char(7,75212).
+char(c,75213).
+char(c,75214).
+char(p,75215).
+char(1,75216).
+char(1,75217).
+char(4,75218).
+char(6,75219).
+char(p,75220).
+char(o,75221).
+char(4,75222).
+char(5,75223).
+char(1,75224).
+char(6,75225).
+char(c,75226).
+char(m,75227).
+char(2,75228).
+char(9,75229).
+char(6,75230).
+char(2,75231).
+char(c,75232).
+char(p,75233).
+char(o,75234).
+char(m,75235).
+char(o,75236).
+char(o,75237).
+char(p,75238).
+char(o,75239).
+char(o,75240).
+char(m,75241).
+char(4,75242).
+char(3,75243).
+char(0,75244).
+char(7,75245).
+char(p,75246).
+char(o,75247).
+char(m,75248).
+char(5,75249).
+char(6,75250).
+char(5,75251).
+char(1,75252).
+char(p,75253).
+char(2,75254).
+char(0,75255).
+char(5,75256).
+char(1,75257).
+char(c,75258).
+char(p,75259).
+char(7,75260).
+char(1,75261).
+char(6,75262).
+char(0,75263).
+char(p,75264).
+char(4,75265).
+char(9,75266).
+char(c,75267).
+char(c,75268).
+char(m,75269).
+char(o,75270).
+char(o,75271).
+char(m,75272).
+char(2,75273).
+char(8,75274).
+char(4,75275).
+char(2,75276).
+char(c,75277).
+char(p,75278).
+char(2,75279).
+char(2,75280).
+char(7,75281).
+char(6,75282).
+char(c,75283).
+char(m,75284).
+char(o,75285).
+char(m,75286).
+char(o,75287).
+char(p,75288).
+char(3,75289).
+char(0,75290).
+char(4,75291).
+char(5,75292).
+char(p,75293).
+char(6,75294).
+char(5,75295).
+char(2,75296).
+char(6,75297).
+char(c,75298).
+char(m,75299).
+char(o,75300).
+char(p,75301).
+char(o,75302).
+char(3,75303).
+char(7,75304).
+char(7,75305).
+char(7,75306).
+char(c,75307).
+char(m,75308).
+char(o,75309).
+char(o,75310).
+char(5,75311).
+char(4,75312).
+char(5,75313).
+char(0,75314).
+char(m,75315).
+char(6,75316).
+char(0,75317).
+char(9,75318).
+char(7,75319).
+char(c,75320).
+char(c,75321).
+char(c,75322).
+char(m,75323).
+char(7,75324).
+char(9,75325).
+char(0,75326).
+char(6,75327).
+char(c,75328).
+char(m,75329).
+char(o,75330).
+char(8,75331).
+char(5,75332).
+char(1,75333).
+char(9,75334).
+char(c,75335).
+char(c,75336).
+char(m,75337).
+char(o,75338).
+char(m,75339).
+char(1,75340).
+char(5,75341).
+char(5,75342).
+char(8,75343).
+char(p,75344).
+char(o,75345).
+char(o,75346).
+char(o,75347).
+char(m,75348).
+char(9,75349).
+char(3,75350).
+char(9,75351).
+char(5,75352).
+char(p,75353).
+char(o,75354).
+char(m,75355).
+char(8,75356).
+char(9,75357).
+char(5,75358).
+char(3,75359).
+char(m,75360).
+char(8,75361).
+char(1,75362).
+char(2,75363).
+char(3,75364).
+char(c,75365).
+char(c,75366).
+char(m,75367).
+char(o,75368).
+char(o,75369).
+char(m,75370).
+char(8,75371).
+char(7,75372).
+char(3,75373).
+char(1,75374).
+char(c,75375).
+char(c,75376).
+char(c,75377).
+char(p,75378).
+char(9,75379).
+char(7,75380).
+char(7,75381).
+char(0,75382).
+char(p,75383).
+char(o,75384).
+char(p,75385).
+char(o,75386).
+char(o,75387).
+char(2,75388).
+char(6,75389).
+char(5,75390).
+char(5,75391).
+char(m,75392).
+char(1,75393).
+char(0,75394).
+char(9,75395).
+char(1,75396).
+char(p,75397).
+char(5,75398).
+char(6,75399).
+char(0,75400).
+char(6,75401).
+char(c,75402).
+char(c,75403).
+char(m,75404).
+char(o,75405).
+char(m,75406).
+char(o,75407).
+char(o,75408).
+char(m,75409).
+char(4,75410).
+char(4,75411).
+char(1,75412).
+char(6,75413).
+char(c,75414).
+char(c,75415).
+char(c,75416).
+char(p,75417).
+char(8,75418).
+char(1,75419).
+char(2,75420).
+char(5,75421).
+char(c,75422).
+char(c,75423).
+char(p,75424).
+char(o,75425).
+char(p,75426).
+char(3,75427).
+char(5,75428).
+char(7,75429).
+char(6,75430).
+char(c,75431).
+char(m,75432).
+char(o,75433).
+char(p,75434).
+char(8,75435).
+char(6,75436).
+char(4,75437).
+char(1,75438).
+char(m,75439).
+char(o,75440).
+char(4,75441).
+char(6,75442).
+char(4,75443).
+char(c,75444).
+char(m,75445).
+char(o,75446).
+char(m,75447).
+char(4,75448).
+char(3,75449).
+char(6,75450).
+char(9,75451).
+char(c,75452).
+char(c,75453).
+char(c,75454).
+char(c,75455).
+char(c,75456).
+char(c,75457).
+char(m,75458).
+char(8,75459).
+char(4,75460).
+char(7,75461).
+char(6,75462).
+char(c,75463).
+char(c,75464).
+char(c,75465).
+char(c,75466).
+char(c,75467).
+char(m,75468).
+char(o,75469).
+char(p,75470).
+char(1,75471).
+char(3,75472).
+char(5,75473).
+char(c,75474).
+char(m,75475).
+char(9,75476).
+char(5,75477).
+char(7,75478).
+char(0,75479).
+char(c,75480).
+char(p,75481).
+char(o,75482).
+char(5,75483).
+char(2,75484).
+char(7,75485).
+char(4,75486).
+char(p,75487).
+char(2,75488).
+char(3,75489).
+char(9,75490).
+char(2,75491).
+char(c,75492).
+char(p,75493).
+char(o,75494).
+char(p,75495).
+char(8,75496).
+char(4,75497).
+char(6,75498).
+char(c,75499).
+char(p,75500).
+char(8,75501).
+char(7,75502).
+char(5,75503).
+char(2,75504).
+char(p,75505).
+char(9,75506).
+char(1,75507).
+char(9,75508).
+char(6,75509).
+char(m,75510).
+char(o,75511).
+char(p,75512).
+char(9,75513).
+char(9,75514).
+char(9,75515).
+char(1,75516).
+char(c,75517).
+char(c,75518).
+char(c,75519).
+char(c,75520).
+char(c,75521).
+char(p,75522).
+char(o,75523).
+char(o,75524).
+char(p,75525).
+char(o,75526).
+char(o,75527).
+char(m,75528).
+char(4,75529).
+char(2,75530).
+char(1,75531).
+char(7,75532).
+char(c,75533).
+char(m,75534).
+char(o,75535).
+char(m,75536).
+char(o,75537).
+char(p,75538).
+char(1,75539).
+char(5,75540).
+char(7,75541).
+char(7,75542).
+char(m,75543).
+char(2,75544).
+char(0,75545).
+char(0,75546).
+char(4,75547).
+char(c,75548).
+char(p,75549).
+char(o,75550).
+char(o,75551).
+char(m,75552).
+char(1,75553).
+char(3,75554).
+char(7,75555).
+char(3,75556).
+char(p,75557).
+char(3,75558).
+char(1,75559).
+char(5,75560).
+char(2,75561).
+char(c,75562).
+char(c,75563).
+char(p,75564).
+char(o,75565).
+char(m,75566).
+char(5,75567).
+char(7,75568).
+char(3,75569).
+char(2,75570).
+char(p,75571).
+char(1,75572).
+char(9,75573).
+char(6,75574).
+char(c,75575).
+char(p,75576).
+char(6,75577).
+char(1,75578).
+char(1,75579).
+char(8,75580).
+char(p,75581).
+char(o,75582).
+char(p,75583).
+char(5,75584).
+char(3,75585).
+char(8,75586).
+char(4,75587).
+char(c,75588).
+char(p,75589).
+char(o,75590).
+char(m,75591).
+char(3,75592).
+char(6,75593).
+char(4,75594).
+char(5,75595).
+char(c,75596).
+char(c,75597).
+char(c,75598).
+char(m,75599).
+char(o,75600).
+char(p,75601).
+char(o,75602).
+char(p,75603).
+char(4,75604).
+char(8,75605).
+char(0,75606).
+char(7,75607).
+char(m,75608).
+char(o,75609).
+char(m,75610).
+char(o,75611).
+char(m,75612).
+char(o,75613).
+char(o,75614).
+char(p,75615).
+char(o,75616).
+char(p,75617).
+char(8,75618).
+char(4,75619).
+char(4,75620).
+char(9,75621).
+char(p,75622).
+char(o,75623).
+char(m,75624).
+char(o,75625).
+char(9,75626).
+char(7,75627).
+char(0,75628).
+char(8,75629).
+char(c,75630).
+char(c,75631).
+char(c,75632).
+char(m,75633).
+char(o,75634).
+char(1,75635).
+char(9,75636).
+char(5,75637).
+char(7,75638).
+char(p,75639).
+char(7,75640).
+char(8,75641).
+char(5,75642).
+char(5,75643).
+char(c,75644).
+char(c,75645).
+char(p,75646).
+char(3,75647).
+char(2,75648).
+char(8,75649).
+char(5,75650).
+char(c,75651).
+char(c,75652).
+char(m,75653).
+char(6,75654).
+char(9,75655).
+char(0,75656).
+char(6,75657).
+char(m,75658).
+char(o,75659).
+char(m,75660).
+char(8,75661).
+char(3,75662).
+char(8,75663).
+char(4,75664).
+char(m,75665).
+char(8,75666).
+char(3,75667).
+char(7,75668).
+char(2,75669).
+char(c,75670).
+char(c,75671).
+char(c,75672).
+char(c,75673).
+char(m,75674).
+char(o,75675).
+char(p,75676).
+char(7,75677).
+char(2,75678).
+char(8,75679).
+char(4,75680).
+char(m,75681).
+char(5,75682).
+char(4,75683).
+char(4,75684).
+char(0,75685).
+char(m,75686).
+char(8,75687).
+char(7,75688).
+char(7,75689).
+char(0,75690).
+char(p,75691).
+char(o,75692).
+char(m,75693).
+char(o,75694).
+char(p,75695).
+char(3,75696).
+char(4,75697).
+char(4,75698).
+char(2,75699).
+char(m,75700).
+char(o,75701).
+char(m,75702).
+char(1,75703).
+char(6,75704).
+char(1,75705).
+char(3,75706).
+char(p,75707).
+char(o,75708).
+char(7,75709).
+char(2,75710).
+char(5,75711).
+char(4,75712).
+char(c,75713).
+char(c,75714).
+char(c,75715).
+char(p,75716).
+char(o,75717).
+char(p,75718).
+char(o,75719).
+char(p,75720).
+char(3,75721).
+char(4,75722).
+char(1,75723).
+char(0,75724).
+char(p,75725).
+char(o,75726).
+char(p,75727).
+char(4,75728).
+char(4,75729).
+char(7,75730).
+char(8,75731).
+char(m,75732).
+char(o,75733).
+char(1,75734).
+char(4,75735).
+char(6,75736).
+char(5,75737).
+char(m,75738).
+char(3,75739).
+char(9,75740).
+char(9,75741).
+char(8,75742).
+char(p,75743).
+char(o,75744).
+char(5,75745).
+char(1,75746).
+char(6,75747).
+char(1,75748).
+char(c,75749).
+char(p,75750).
+char(o,75751).
+char(p,75752).
+char(o,75753).
+char(o,75754).
+char(m,75755).
+char(3,75756).
+char(8,75757).
+char(3,75758).
+char(7,75759).
+char(c,75760).
+char(c,75761).
+char(p,75762).
+char(o,75763).
+char(p,75764).
+char(o,75765).
+char(p,75766).
+char(2,75767).
+char(6,75768).
+char(7,75769).
+char(7,75770).
+char(p,75771).
+char(7,75772).
+char(9,75773).
+char(0,75774).
+char(0,75775).
+char(c,75776).
+char(c,75777).
+char(c,75778).
+char(c,75779).
+char(c,75780).
+char(c,75781).
+char(p,75782).
+char(o,75783).
+char(p,75784).
+char(8,75785).
+char(8,75786).
+char(4,75787).
+char(9,75788).
+char(p,75789).
+char(o,75790).
+char(p,75791).
+char(o,75792).
+char(m,75793).
+char(4,75794).
+char(4,75795).
+char(1,75796).
+char(0,75797).
+char(c,75798).
+char(p,75799).
+char(9,75800).
+char(2,75801).
+char(8,75802).
+char(4,75803).
+char(p,75804).
+char(4,75805).
+char(0,75806).
+char(2,75807).
+char(9,75808).
+char(c,75809).
+char(p,75810).
+char(3,75811).
+char(5,75812).
+char(8,75813).
+char(4,75814).
+char(c,75815).
+char(c,75816).
+char(c,75817).
+char(m,75818).
+char(5,75819).
+char(4,75820).
+char(2,75821).
+char(8,75822).
+char(c,75823).
+char(m,75824).
+char(o,75825).
+char(m,75826).
+char(o,75827).
+char(3,75828).
+char(5,75829).
+char(0,75830).
+char(0,75831).
+char(m,75832).
+char(9,75833).
+char(7,75834).
+char(6,75835).
+char(5,75836).
+char(p,75837).
+char(3,75838).
+char(6,75839).
+char(9,75840).
+char(7,75841).
+char(p,75842).
+char(o,75843).
+char(p,75844).
+char(o,75845).
+char(p,75846).
+char(o,75847).
+char(m,75848).
+char(7,75849).
+char(3,75850).
+char(2,75851).
+char(8,75852).
+char(c,75853).
+char(c,75854).
+char(p,75855).
+char(1,75856).
+char(2,75857).
+char(4,75858).
+char(5,75859).
+char(p,75860).
+char(o,75861).
+char(p,75862).
+char(o,75863).
+char(1,75864).
+char(5,75865).
+char(8,75866).
+char(9,75867).
+char(m,75868).
+char(o,75869).
+char(p,75870).
+char(o,75871).
+char(m,75872).
+char(6,75873).
+char(5,75874).
+char(5,75875).
+char(9,75876).
+char(m,75877).
+char(o,75878).
+char(m,75879).
+char(o,75880).
+char(p,75881).
+char(o,75882).
+char(p,75883).
+char(o,75884).
+char(5,75885).
+char(5,75886).
+char(3,75887).
+char(7,75888).
+char(m,75889).
+char(o,75890).
+char(m,75891).
+char(o,75892).
+char(p,75893).
+char(9,75894).
+char(9,75895).
+char(1,75896).
+char(9,75897).
+char(m,75898).
+char(o,75899).
+char(m,75900).
+char(9,75901).
+char(1,75902).
+char(8,75903).
+char(4,75904).
+char(c,75905).
+char(p,75906).
+char(1,75907).
+char(4,75908).
+char(9,75909).
+char(1,75910).
+char(m,75911).
+char(o,75912).
+char(1,75913).
+char(2,75914).
+char(0,75915).
+char(8,75916).
+char(p,75917).
+char(8,75918).
+char(5,75919).
+char(0,75920).
+char(1,75921).
+char(p,75922).
+char(4,75923).
+char(4,75924).
+char(8,75925).
+char(c,75926).
+char(m,75927).
+char(9,75928).
+char(7,75929).
+char(8,75930).
+char(9,75931).
+char(c,75932).
+char(p,75933).
+char(3,75934).
+char(6,75935).
+char(6,75936).
+char(2,75937).
+char(c,75938).
+char(c,75939).
+char(m,75940).
+char(3,75941).
+char(5,75942).
+char(4,75943).
+char(6,75944).
+char(m,75945).
+char(o,75946).
+char(m,75947).
+char(o,75948).
+char(m,75949).
+char(9,75950).
+char(4,75951).
+char(5,75952).
+char(1,75953).
+char(c,75954).
+char(p,75955).
+char(6,75956).
+char(1,75957).
+char(5,75958).
+char(p,75959).
+char(o,75960).
+char(p,75961).
+char(8,75962).
+char(7,75963).
+char(3,75964).
+char(0,75965).
+char(m,75966).
+char(o,75967).
+char(p,75968).
+char(o,75969).
+char(m,75970).
+char(o,75971).
+char(m,75972).
+char(5,75973).
+char(5,75974).
+char(3,75975).
+char(1,75976).
+char(p,75977).
+char(o,75978).
+char(6,75979).
+char(1,75980).
+char(6,75981).
+char(c,75982).
+char(c,75983).
+char(c,75984).
+char(c,75985).
+char(m,75986).
+char(3,75987).
+char(1,75988).
+char(3,75989).
+char(4,75990).
+char(m,75991).
+char(6,75992).
+char(4,75993).
+char(4,75994).
+char(1,75995).
+char(m,75996).
+char(5,75997).
+char(9,75998).
+char(8,75999).
+char(6,76000).
+char(m,76001).
+char(8,76002).
+char(4,76003).
+char(6,76004).
+char(7,76005).
+char(m,76006).
+char(o,76007).
+char(p,76008).
+char(o,76009).
+char(1,76010).
+char(1,76011).
+char(9,76012).
+char(6,76013).
+char(c,76014).
+char(p,76015).
+char(o,76016).
+char(6,76017).
+char(2,76018).
+char(4,76019).
+char(c,76020).
+char(m,76021).
+char(9,76022).
+char(7,76023).
+char(8,76024).
+char(7,76025).
+char(c,76026).
+char(c,76027).
+char(m,76028).
+char(o,76029).
+char(5,76030).
+char(0,76031).
+char(2,76032).
+char(1,76033).
+char(c,76034).
+char(c,76035).
+char(m,76036).
+char(o,76037).
+char(6,76038).
+char(6,76039).
+char(9,76040).
+char(6,76041).
+char(p,76042).
+char(o,76043).
+char(m,76044).
+char(o,76045).
+char(m,76046).
+char(o,76047).
+char(p,76048).
+char(4,76049).
+char(9,76050).
+char(2,76051).
+char(7,76052).
+char(c,76053).
+char(c,76054).
+char(m,76055).
+char(4,76056).
+char(9,76057).
+char(1,76058).
+char(0,76059).
+char(c,76060).
+char(c,76061).
+char(m,76062).
+char(4,76063).
+char(0,76064).
+char(8,76065).
+char(3,76066).
+char(c,76067).
+char(m,76068).
+char(o,76069).
+char(6,76070).
+char(4,76071).
+char(8,76072).
+char(6,76073).
+char(c,76074).
+char(c,76075).
+char(p,76076).
+char(4,76077).
+char(5,76078).
+char(9,76079).
+char(4,76080).
+char(c,76081).
+char(c,76082).
+char(p,76083).
+char(1,76084).
+char(5,76085).
+char(6,76086).
+char(5,76087).
+char(p,76088).
+char(2,76089).
+char(4,76090).
+char(1,76091).
+char(1,76092).
+char(c,76093).
+char(c,76094).
+char(p,76095).
+char(7,76096).
+char(3,76097).
+char(9,76098).
+char(7,76099).
+char(c,76100).
+char(c,76101).
+char(m,76102).
+char(o,76103).
+char(p,76104).
+char(1,76105).
+char(1,76106).
+char(6,76107).
+char(6,76108).
+char(c,76109).
+char(m,76110).
+char(o,76111).
+char(o,76112).
+char(4,76113).
+char(1,76114).
+char(5,76115).
+char(0,76116).
+char(c,76117).
+char(c,76118).
+char(c,76119).
+char(c,76120).
+char(m,76121).
+char(o,76122).
+char(m,76123).
+char(o,76124).
+char(p,76125).
+char(o,76126).
+char(p,76127).
+char(o,76128).
+char(7,76129).
+char(3,76130).
+char(4,76131).
+char(0,76132).
+char(p,76133).
+char(4,76134).
+char(9,76135).
+char(6,76136).
+char(p,76137).
+char(o,76138).
+char(2,76139).
+char(8,76140).
+char(6,76141).
+char(1,76142).
+char(c,76143).
+char(m,76144).
+char(8,76145).
+char(1,76146).
+char(4,76147).
+char(8,76148).
+char(m,76149).
+char(o,76150).
+char(p,76151).
+char(9,76152).
+char(8,76153).
+char(1,76154).
+char(3,76155).
+char(c,76156).
+char(m,76157).
+char(o,76158).
+char(8,76159).
+char(7,76160).
+char(7,76161).
+char(c,76162).
+char(c,76163).
+char(p,76164).
+char(3,76165).
+char(7,76166).
+char(1,76167).
+char(3,76168).
+char(c,76169).
+char(c,76170).
+char(c,76171).
+char(p,76172).
+char(o,76173).
+char(m,76174).
+char(6,76175).
+char(0,76176).
+char(7,76177).
+char(5,76178).
+char(c,76179).
+char(p,76180).
+char(o,76181).
+char(m,76182).
+char(o,76183).
+char(p,76184).
+char(3,76185).
+char(4,76186).
+char(7,76187).
+char(4,76188).
+char(m,76189).
+char(4,76190).
+char(6,76191).
+char(5,76192).
+char(2,76193).
+char(c,76194).
+char(m,76195).
+char(1,76196).
+char(2,76197).
+char(6,76198).
+char(5,76199).
+char(c,76200).
+char(p,76201).
+char(6,76202).
+char(7,76203).
+char(9,76204).
+char(8,76205).
+char(m,76206).
+char(3,76207).
+char(2,76208).
+char(4,76209).
+char(1,76210).
+char(p,76211).
+char(4,76212).
+char(3,76213).
+char(9,76214).
+char(0,76215).
+char(c,76216).
+char(c,76217).
+char(p,76218).
+char(3,76219).
+char(2,76220).
+char(4,76221).
+char(4,76222).
+char(c,76223).
+char(m,76224).
+char(o,76225).
+char(1,76226).
+char(0,76227).
+char(7,76228).
+char(5,76229).
+char(m,76230).
+char(o,76231).
+char(p,76232).
+char(8,76233).
+char(5,76234).
+char(1,76235).
+char(1,76236).
+char(p,76237).
+char(o,76238).
+char(m,76239).
+char(o,76240).
+char(p,76241).
+char(3,76242).
+char(9,76243).
+char(5,76244).
+char(4,76245).
+char(c,76246).
+char(c,76247).
+char(p,76248).
+char(o,76249).
+char(p,76250).
+char(5,76251).
+char(9,76252).
+char(2,76253).
+char(7,76254).
+char(p,76255).
+char(4,76256).
+char(7,76257).
+char(7,76258).
+char(5,76259).
+char(c,76260).
+char(m,76261).
+char(o,76262).
+char(o,76263).
+char(m,76264).
+char(2,76265).
+char(7,76266).
+char(7,76267).
+char(7,76268).
+char(m,76269).
+char(6,76270).
+char(5,76271).
+char(1,76272).
+char(3,76273).
+char(m,76274).
+char(o,76275).
+char(o,76276).
+char(4,76277).
+char(1,76278).
+char(6,76279).
+char(8,76280).
+char(m,76281).
+char(2,76282).
+char(9,76283).
+char(6,76284).
+char(5,76285).
+char(c,76286).
+char(c,76287).
+char(p,76288).
+char(2,76289).
+char(7,76290).
+char(6,76291).
+char(8,76292).
+char(m,76293).
+char(8,76294).
+char(3,76295).
+char(3,76296).
+char(0,76297).
+char(c,76298).
+char(m,76299).
+char(o,76300).
+char(p,76301).
+char(o,76302).
+char(p,76303).
+char(9,76304).
+char(4,76305).
+char(6,76306).
+char(1,76307).
+char(c,76308).
+char(c,76309).
+char(p,76310).
+char(8,76311).
+char(4,76312).
+char(8,76313).
+char(7,76314).
+char(p,76315).
+char(1,76316).
+char(2,76317).
+char(3,76318).
+char(3,76319).
+char(c,76320).
+char(p,76321).
+char(9,76322).
+char(1,76323).
+char(8,76324).
+char(6,76325).
+char(m,76326).
+char(4,76327).
+char(0,76328).
+char(2,76329).
+char(0,76330).
+char(c,76331).
+char(c,76332).
+char(m,76333).
+char(o,76334).
+char(m,76335).
+char(o,76336).
+char(p,76337).
+char(5,76338).
+char(9,76339).
+char(4,76340).
+char(m,76341).
+char(4,76342).
+char(9,76343).
+char(3,76344).
+char(c,76345).
+char(m,76346).
+char(o,76347).
+char(8,76348).
+char(6,76349).
+char(3,76350).
+char(6,76351).
+char(c,76352).
+char(c,76353).
+char(p,76354).
+char(1,76355).
+char(3,76356).
+char(0,76357).
+char(1,76358).
+char(p,76359).
+char(7,76360).
+char(5,76361).
+char(8,76362).
+char(3,76363).
+char(m,76364).
+char(o,76365).
+char(m,76366).
+char(3,76367).
+char(4,76368).
+char(8,76369).
+char(6,76370).
+char(m,76371).
+char(o,76372).
+char(p,76373).
+char(5,76374).
+char(8,76375).
+char(2,76376).
+char(2,76377).
+char(c,76378).
+char(p,76379).
+char(o,76380).
+char(m,76381).
+char(5,76382).
+char(5,76383).
+char(1,76384).
+char(4,76385).
+char(c,76386).
+char(c,76387).
+char(c,76388).
+char(m,76389).
+char(o,76390).
+char(8,76391).
+char(1,76392).
+char(1,76393).
+char(8,76394).
+char(c,76395).
+char(c,76396).
+char(c,76397).
+char(c,76398).
+char(c,76399).
+char(m,76400).
+char(2,76401).
+char(9,76402).
+char(3,76403).
+char(9,76404).
+char(c,76405).
+char(c,76406).
+char(m,76407).
+char(o,76408).
+char(p,76409).
+char(7,76410).
+char(0,76411).
+char(1,76412).
+char(5,76413).
+char(m,76414).
+char(7,76415).
+char(2,76416).
+char(0,76417).
+char(0,76418).
+char(m,76419).
+char(2,76420).
+char(0,76421).
+char(4,76422).
+char(1,76423).
+char(c,76424).
+char(m,76425).
+char(6,76426).
+char(8,76427).
+char(7,76428).
+char(2,76429).
+char(p,76430).
+char(o,76431).
+char(p,76432).
+char(o,76433).
+char(m,76434).
+char(o,76435).
+char(m,76436).
+char(o,76437).
+char(m,76438).
+char(o,76439).
+char(m,76440).
+char(6,76441).
+char(5,76442).
+char(8,76443).
+char(4,76444).
+char(c,76445).
+char(c,76446).
+char(c,76447).
+char(c,76448).
+char(m,76449).
+char(7,76450).
+char(4,76451).
+char(7,76452).
+char(1,76453).
+char(c,76454).
+char(c,76455).
+char(m,76456).
+char(9,76457).
+char(8,76458).
+char(4,76459).
+char(1,76460).
+char(c,76461).
+char(c,76462).
+char(p,76463).
+char(6,76464).
+char(8,76465).
+char(0,76466).
+char(3,76467).
+char(p,76468).
+char(o,76469).
+char(2,76470).
+char(2,76471).
+char(7,76472).
+char(7,76473).
+char(c,76474).
+char(c,76475).
+char(p,76476).
+char(o,76477).
+char(o,76478).
+char(p,76479).
+char(2,76480).
+char(4,76481).
+char(1,76482).
+char(c,76483).
+char(c,76484).
+char(m,76485).
+char(3,76486).
+char(6,76487).
+char(7,76488).
+char(3,76489).
+char(m,76490).
+char(9,76491).
+char(0,76492).
+char(3,76493).
+char(4,76494).
+char(c,76495).
+char(c,76496).
+char(c,76497).
+char(c,76498).
+char(m,76499).
+char(o,76500).
+char(o,76501).
+char(p,76502).
+char(2,76503).
+char(6,76504).
+char(6,76505).
+char(c,76506).
+char(c,76507).
+char(c,76508).
+char(c,76509).
+char(c,76510).
+char(p,76511).
+char(o,76512).
+char(o,76513).
+char(p,76514).
+char(4,76515).
+char(5,76516).
+char(8,76517).
+char(c,76518).
+char(c,76519).
+char(p,76520).
+char(4,76521).
+char(3,76522).
+char(5,76523).
+char(8,76524).
+char(m,76525).
+char(2,76526).
+char(5,76527).
+char(0,76528).
+char(3,76529).
+char(c,76530).
+char(c,76531).
+char(c,76532).
+char(p,76533).
+char(o,76534).
+char(o,76535).
+char(p,76536).
+char(5,76537).
+char(7,76538).
+char(5,76539).
+char(8,76540).
+char(m,76541).
+char(2,76542).
+char(4,76543).
+char(7,76544).
+char(4,76545).
+char(c,76546).
+char(c,76547).
+char(c,76548).
+char(c,76549).
+char(c,76550).
+char(c,76551).
+char(c,76552).
+char(p,76553).
+char(2,76554).
+char(1,76555).
+char(4,76556).
+char(3,76557).
+char(c,76558).
+char(m,76559).
+char(5,76560).
+char(1,76561).
+char(7,76562).
+char(8,76563).
+char(c,76564).
+char(c,76565).
+char(c,76566).
+char(c,76567).
+char(c,76568).
+char(m,76569).
+char(6,76570).
+char(2,76571).
+char(6,76572).
+char(6,76573).
+char(c,76574).
+char(p,76575).
+char(7,76576).
+char(9,76577).
+char(3,76578).
+char(8,76579).
+char(m,76580).
+char(o,76581).
+char(p,76582).
+char(o,76583).
+char(o,76584).
+char(p,76585).
+char(6,76586).
+char(7,76587).
+char(1,76588).
+char(6,76589).
+char(p,76590).
+char(5,76591).
+char(5,76592).
+char(8,76593).
+char(1,76594).
+char(c,76595).
+char(p,76596).
+char(o,76597).
+char(p,76598).
+char(2,76599).
+char(3,76600).
+char(8,76601).
+char(6,76602).
+char(c,76603).
+char(m,76604).
+char(o,76605).
+char(o,76606).
+char(p,76607).
+char(o,76608).
+char(6,76609).
+char(0,76610).
+char(4,76611).
+char(2,76612).
+char(p,76613).
+char(9,76614).
+char(0,76615).
+char(3,76616).
+char(5,76617).
+char(p,76618).
+char(o,76619).
+char(m,76620).
+char(6,76621).
+char(1,76622).
+char(2,76623).
+char(3,76624).
+char(p,76625).
+char(o,76626).
+char(o,76627).
+char(m,76628).
+char(6,76629).
+char(5,76630).
+char(9,76631).
+char(0,76632).
+char(p,76633).
+char(o,76634).
+char(m,76635).
+char(o,76636).
+char(m,76637).
+char(o,76638).
+char(m,76639).
+char(8,76640).
+char(5,76641).
+char(2,76642).
+char(7,76643).
+char(p,76644).
+char(o,76645).
+char(8,76646).
+char(4,76647).
+char(6,76648).
+char(5,76649).
+char(c,76650).
+char(c,76651).
+char(m,76652).
+char(2,76653).
+char(0,76654).
+char(4,76655).
+char(5,76656).
+char(m,76657).
+char(9,76658).
+char(2,76659).
+char(5,76660).
+char(7,76661).
+char(p,76662).
+char(o,76663).
+char(p,76664).
+char(o,76665).
+char(o,76666).
+char(m,76667).
+char(o,76668).
+char(p,76669).
+char(o,76670).
+char(7,76671).
+char(9,76672).
+char(2,76673).
+char(9,76674).
+char(m,76675).
+char(o,76676).
+char(m,76677).
+char(6,76678).
+char(8,76679).
+char(8,76680).
+char(7,76681).
+char(c,76682).
+char(m,76683).
+char(o,76684).
+char(o,76685).
+char(m,76686).
+char(o,76687).
+char(o,76688).
+char(p,76689).
+char(o,76690).
+char(6,76691).
+char(9,76692).
+char(2,76693).
+char(5,76694).
+char(c,76695).
+char(c,76696).
+char(p,76697).
+char(o,76698).
+char(m,76699).
+char(4,76700).
+char(9,76701).
+char(8,76702).
+char(0,76703).
+char(m,76704).
+char(8,76705).
+char(0,76706).
+char(8,76707).
+char(8,76708).
+char(c,76709).
+char(m,76710).
+char(1,76711).
+char(6,76712).
+char(7,76713).
+char(7,76714).
+char(p,76715).
+char(o,76716).
+char(p,76717).
+char(5,76718).
+char(2,76719).
+char(8,76720).
+char(3,76721).
+char(c,76722).
+char(c,76723).
+char(m,76724).
+char(2,76725).
+char(4,76726).
+char(8,76727).
+char(8,76728).
+char(p,76729).
+char(o,76730).
+char(m,76731).
+char(1,76732).
+char(3,76733).
+char(3,76734).
+char(m,76735).
+char(o,76736).
+char(m,76737).
+char(7,76738).
+char(2,76739).
+char(4,76740).
+char(1,76741).
+char(c,76742).
+char(c,76743).
+char(m,76744).
+char(5,76745).
+char(6,76746).
+char(3,76747).
+char(6,76748).
+char(c,76749).
+char(m,76750).
+char(o,76751).
+char(6,76752).
+char(8,76753).
+char(4,76754).
+char(3,76755).
+char(c,76756).
+char(p,76757).
+char(o,76758).
+char(p,76759).
+char(o,76760).
+char(m,76761).
+char(o,76762).
+char(o,76763).
+char(o,76764).
+char(p,76765).
+char(5,76766).
+char(0,76767).
+char(5,76768).
+char(8,76769).
+char(p,76770).
+char(7,76771).
+char(5,76772).
+char(9,76773).
+char(3,76774).
+char(c,76775).
+char(m,76776).
+char(7,76777).
+char(4,76778).
+char(9,76779).
+char(2,76780).
+char(p,76781).
+char(4,76782).
+char(4,76783).
+char(5,76784).
+char(3,76785).
+char(c,76786).
+char(c,76787).
+char(c,76788).
+char(p,76789).
+char(o,76790).
+char(p,76791).
+char(5,76792).
+char(2,76793).
+char(4,76794).
+char(c,76795).
+char(c,76796).
+char(p,76797).
+char(o,76798).
+char(p,76799).
+char(o,76800).
+char(m,76801).
+char(o,76802).
+char(p,76803).
+char(o,76804).
+char(m,76805).
+char(o,76806).
+char(o,76807).
+char(p,76808).
+char(4,76809).
+char(1,76810).
+char(2,76811).
+char(1,76812).
+char(p,76813).
+char(6,76814).
+char(4,76815).
+char(3,76816).
+char(4,76817).
+char(c,76818).
+char(c,76819).
+char(m,76820).
+char(o,76821).
+char(o,76822).
+char(o,76823).
+char(6,76824).
+char(9,76825).
+char(4,76826).
+char(2,76827).
+char(c,76828).
+char(c,76829).
+char(p,76830).
+char(7,76831).
+char(5,76832).
+char(4,76833).
+char(4,76834).
+char(p,76835).
+char(o,76836).
+char(m,76837).
+char(o,76838).
+char(m,76839).
+char(8,76840).
+char(8,76841).
+char(9,76842).
+char(8,76843).
+char(p,76844).
+char(o,76845).
+char(8,76846).
+char(9,76847).
+char(6,76848).
+char(2,76849).
+char(c,76850).
+char(c,76851).
+char(m,76852).
+char(7,76853).
+char(9,76854).
+char(1,76855).
+char(0,76856).
+char(m,76857).
+char(o,76858).
+char(m,76859).
+char(o,76860).
+char(m,76861).
+char(o,76862).
+char(p,76863).
+char(o,76864).
+char(m,76865).
+char(3,76866).
+char(8,76867).
+char(8,76868).
+char(m,76869).
+char(4,76870).
+char(5,76871).
+char(0,76872).
+char(3,76873).
+char(p,76874).
+char(5,76875).
+char(7,76876).
+char(2,76877).
+char(7,76878).
+char(c,76879).
+char(c,76880).
+char(c,76881).
+char(c,76882).
+char(c,76883).
+char(p,76884).
+char(o,76885).
+char(4,76886).
+char(7,76887).
+char(4,76888).
+char(7,76889).
+char(p,76890).
+char(4,76891).
+char(3,76892).
+char(1,76893).
+char(5,76894).
+char(p,76895).
+char(o,76896).
+char(p,76897).
+char(o,76898).
+char(p,76899).
+char(8,76900).
+char(0,76901).
+char(9,76902).
+char(4,76903).
+char(m,76904).
+char(9,76905).
+char(7,76906).
+char(1,76907).
+char(6,76908).
+char(m,76909).
+char(o,76910).
+char(3,76911).
+char(8,76912).
+char(6,76913).
+char(5,76914).
+char(c,76915).
+char(m,76916).
+char(7,76917).
+char(7,76918).
+char(5,76919).
+char(3,76920).
+char(m,76921).
+char(o,76922).
+char(p,76923).
+char(5,76924).
+char(2,76925).
+char(9,76926).
+char(8,76927).
+char(c,76928).
+char(p,76929).
+char(4,76930).
+char(1,76931).
+char(4,76932).
+char(3,76933).
+char(c,76934).
+char(p,76935).
+char(o,76936).
+char(m,76937).
+char(o,76938).
+char(m,76939).
+char(4,76940).
+char(9,76941).
+char(3,76942).
+char(m,76943).
+char(o,76944).
+char(p,76945).
+char(o,76946).
+char(p,76947).
+char(o,76948).
+char(m,76949).
+char(2,76950).
+char(7,76951).
+char(3,76952).
+char(3,76953).
+char(c,76954).
+char(m,76955).
+char(4,76956).
+char(7,76957).
+char(4,76958).
+char(4,76959).
+char(c,76960).
+char(p,76961).
+char(1,76962).
+char(9,76963).
+char(3,76964).
+char(9,76965).
+char(m,76966).
+char(o,76967).
+char(m,76968).
+char(o,76969).
+char(m,76970).
+char(7,76971).
+char(5,76972).
+char(9,76973).
+char(9,76974).
+char(p,76975).
+char(o,76976).
+char(o,76977).
+char(5,76978).
+char(2,76979).
+char(7,76980).
+char(7,76981).
+char(c,76982).
+char(p,76983).
+char(6,76984).
+char(8,76985).
+char(7,76986).
+char(2,76987).
+char(c,76988).
+char(c,76989).
+char(p,76990).
+char(o,76991).
+char(m,76992).
+char(3,76993).
+char(8,76994).
+char(9,76995).
+char(2,76996).
+char(c,76997).
+char(c,76998).
+char(c,76999).
+char(m,77000).
+char(3,77001).
+char(8,77002).
+char(3,77003).
+char(0,77004).
+char(p,77005).
+char(3,77006).
+char(7,77007).
+char(9,77008).
+char(9,77009).
+char(c,77010).
+char(m,77011).
+char(6,77012).
+char(0,77013).
+char(9,77014).
+char(4,77015).
+char(m,77016).
+char(o,77017).
+char(p,77018).
+char(5,77019).
+char(2,77020).
+char(3,77021).
+char(7,77022).
+char(c,77023).
+char(c,77024).
+char(c,77025).
+char(p,77026).
+char(7,77027).
+char(3,77028).
+char(1,77029).
+char(1,77030).
+char(c,77031).
+char(p,77032).
+char(o,77033).
+char(o,77034).
+char(m,77035).
+char(o,77036).
+char(m,77037).
+char(o,77038).
+char(p,77039).
+char(o,77040).
+char(m,77041).
+char(5,77042).
+char(0,77043).
+char(2,77044).
+char(8,77045).
+char(c,77046).
+char(c,77047).
+char(p,77048).
+char(o,77049).
+char(m,77050).
+char(o,77051).
+char(p,77052).
+char(4,77053).
+char(8,77054).
+char(7,77055).
+char(2,77056).
+char(p,77057).
+char(o,77058).
+char(m,77059).
+char(o,77060).
+char(p,77061).
+char(4,77062).
+char(9,77063).
+char(5,77064).
+char(9,77065).
+char(c,77066).
+char(m,77067).
+char(5,77068).
+char(8,77069).
+char(9,77070).
+char(0,77071).
+char(p,77072).
+char(9,77073).
+char(1,77074).
+char(9,77075).
+char(8,77076).
+char(m,77077).
+char(o,77078).
+char(m,77079).
+char(2,77080).
+char(2,77081).
+char(3,77082).
+char(1,77083).
+char(c,77084).
+char(c,77085).
+char(c,77086).
+char(p,77087).
+char(o,77088).
+char(m,77089).
+char(9,77090).
+char(6,77091).
+char(2,77092).
+char(0,77093).
+char(c,77094).
+char(m,77095).
+char(4,77096).
+char(5,77097).
+char(9,77098).
+char(7,77099).
+char(c,77100).
+char(c,77101).
+char(m,77102).
+char(o,77103).
+char(m,77104).
+char(8,77105).
+char(1,77106).
+char(0,77107).
+char(4,77108).
+char(m,77109).
+char(o,77110).
+char(p,77111).
+char(8,77112).
+char(4,77113).
+char(3,77114).
+char(0,77115).
+char(c,77116).
+char(p,77117).
+char(5,77118).
+char(7,77119).
+char(2,77120).
+char(1,77121).
+char(m,77122).
+char(1,77123).
+char(1,77124).
+char(6,77125).
+char(2,77126).
+char(p,77127).
+char(o,77128).
+char(p,77129).
+char(o,77130).
+char(m,77131).
+char(2,77132).
+char(4,77133).
+char(6,77134).
+char(6,77135).
+char(c,77136).
+char(c,77137).
+char(p,77138).
+char(4,77139).
+char(0,77140).
+char(6,77141).
+char(4,77142).
+char(m,77143).
+char(o,77144).
+char(m,77145).
+char(o,77146).
+char(p,77147).
+char(6,77148).
+char(9,77149).
+char(8,77150).
+char(9,77151).
+char(c,77152).
+char(c,77153).
+char(c,77154).
+char(p,77155).
+char(o,77156).
+char(4,77157).
+char(8,77158).
+char(6,77159).
+char(7,77160).
+char(c,77161).
+char(p,77162).
+char(1,77163).
+char(9,77164).
+char(8,77165).
+char(7,77166).
+char(m,77167).
+char(o,77168).
+char(o,77169).
+char(6,77170).
+char(7,77171).
+char(5,77172).
+char(7,77173).
+char(p,77174).
+char(8,77175).
+char(1,77176).
+char(5,77177).
+char(0,77178).
+char(c,77179).
+char(p,77180).
+char(o,77181).
+char(p,77182).
+char(o,77183).
+char(p,77184).
+char(3,77185).
+char(8,77186).
+char(0,77187).
+char(7,77188).
+char(c,77189).
+char(p,77190).
+char(2,77191).
+char(5,77192).
+char(0,77193).
+char(2,77194).
+char(c,77195).
+char(p,77196).
+char(o,77197).
+char(p,77198).
+char(2,77199).
+char(6,77200).
+char(9,77201).
+char(c,77202).
+char(c,77203).
+char(p,77204).
+char(o,77205).
+char(p,77206).
+char(o,77207).
+char(m,77208).
+char(2,77209).
+char(3,77210).
+char(3,77211).
+char(8,77212).
+char(m,77213).
+char(2,77214).
+char(4,77215).
+char(0,77216).
+char(1,77217).
+char(m,77218).
+char(5,77219).
+char(9,77220).
+char(5,77221).
+char(0,77222).
+char(p,77223).
+char(o,77224).
+char(m,77225).
+char(o,77226).
+char(2,77227).
+char(4,77228).
+char(2,77229).
+char(0,77230).
+char(p,77231).
+char(o,77232).
+char(6,77233).
+char(0,77234).
+char(3,77235).
+char(5,77236).
+char(m,77237).
+char(o,77238).
+char(m,77239).
+char(4,77240).
+char(3,77241).
+char(6,77242).
+char(3,77243).
+char(m,77244).
+char(1,77245).
+char(5,77246).
+char(5,77247).
+char(8,77248).
+char(m,77249).
+char(o,77250).
+char(m,77251).
+char(2,77252).
+char(2,77253).
+char(7,77254).
+char(6,77255).
+char(m,77256).
+char(3,77257).
+char(9,77258).
+char(9,77259).
+char(1,77260).
+char(c,77261).
+char(c,77262).
+char(p,77263).
+char(o,77264).
+char(o,77265).
+char(1,77266).
+char(1,77267).
+char(2,77268).
+char(6,77269).
+char(c,77270).
+char(c,77271).
+char(m,77272).
+char(o,77273).
+char(m,77274).
+char(1,77275).
+char(1,77276).
+char(1,77277).
+char(8,77278).
+char(c,77279).
+char(m,77280).
+char(o,77281).
+char(p,77282).
+char(5,77283).
+char(2,77284).
+char(5,77285).
+char(8,77286).
+char(m,77287).
+char(o,77288).
+char(p,77289).
+char(o,77290).
+char(p,77291).
+char(o,77292).
+char(3,77293).
+char(2,77294).
+char(9,77295).
+char(8,77296).
+char(c,77297).
+char(c,77298).
+char(c,77299).
+char(c,77300).
+char(m,77301).
+char(2,77302).
+char(4,77303).
+char(2,77304).
+char(1,77305).
+char(m,77306).
+char(6,77307).
+char(1,77308).
+char(5,77309).
+char(4,77310).
+char(c,77311).
+char(m,77312).
+char(o,77313).
+char(1,77314).
+char(9,77315).
+char(p,77316).
+char(7,77317).
+char(0,77318).
+char(3,77319).
+char(2,77320).
+char(c,77321).
+char(c,77322).
+char(c,77323).
+char(c,77324).
+char(p,77325).
+char(6,77326).
+char(5,77327).
+char(3,77328).
+char(p,77329).
+char(3,77330).
+char(4,77331).
+char(0,77332).
+char(5,77333).
+char(c,77334).
+char(m,77335).
+char(o,77336).
+char(p,77337).
+char(o,77338).
+char(m,77339).
+char(7,77340).
+char(0,77341).
+char(1,77342).
+char(4,77343).
+char(c,77344).
+char(c,77345).
+char(m,77346).
+char(7,77347).
+char(9,77348).
+char(8,77349).
+char(p,77350).
+char(8,77351).
+char(5,77352).
+char(0,77353).
+char(1,77354).
+char(p,77355).
+char(o,77356).
+char(o,77357).
+char(o,77358).
+char(m,77359).
+char(5,77360).
+char(0,77361).
+char(0,77362).
+char(7,77363).
+char(m,77364).
+char(o,77365).
+char(6,77366).
+char(4,77367).
+char(0,77368).
+char(7,77369).
+char(p,77370).
+char(o,77371).
+char(m,77372).
+char(o,77373).
+char(m,77374).
+char(o,77375).
+char(p,77376).
+char(o,77377).
+char(p,77378).
+char(o,77379).
+char(m,77380).
+char(3,77381).
+char(4,77382).
+char(2,77383).
+char(3,77384).
+char(p,77385).
+char(o,77386).
+char(p,77387).
+char(9,77388).
+char(5,77389).
+char(7,77390).
+char(5,77391).
+char(m,77392).
+char(o,77393).
+char(4,77394).
+char(5,77395).
+char(2,77396).
+char(p,77397).
+char(o,77398).
+char(2,77399).
+char(0,77400).
+char(7,77401).
+char(5,77402).
+char(m,77403).
+char(3,77404).
+char(8,77405).
+char(0,77406).
+char(5,77407).
+char(p,77408).
+char(o,77409).
+char(4,77410).
+char(1,77411).
+char(9,77412).
+char(p,77413).
+char(2,77414).
+char(3,77415).
+char(4,77416).
+char(3,77417).
+char(c,77418).
+char(m,77419).
+char(1,77420).
+char(8,77421).
+char(3,77422).
+char(8,77423).
+char(m,77424).
+char(o,77425).
+char(m,77426).
+char(6,77427).
+char(5,77428).
+char(5,77429).
+char(8,77430).
+char(p,77431).
+char(o,77432).
+char(p,77433).
+char(o,77434).
+char(7,77435).
+char(6,77436).
+char(4,77437).
+char(0,77438).
+char(p,77439).
+char(7,77440).
+char(4,77441).
+char(9,77442).
+char(4,77443).
+char(m,77444).
+char(4,77445).
+char(5,77446).
+char(6,77447).
+char(4,77448).
+char(c,77449).
+char(c,77450).
+char(c,77451).
+char(p,77452).
+char(o,77453).
+char(o,77454).
+char(o,77455).
+char(o,77456).
+char(p,77457).
+char(8,77458).
+char(9,77459).
+char(5,77460).
+char(7,77461).
+char(c,77462).
+char(m,77463).
+char(6,77464).
+char(7,77465).
+char(4,77466).
+char(5,77467).
+char(c,77468).
+char(c,77469).
+char(c,77470).
+char(c,77471).
+char(c,77472).
+char(m,77473).
+char(6,77474).
+char(7,77475).
+char(0,77476).
+char(8,77477).
+char(c,77478).
+char(c,77479).
+char(c,77480).
+char(p,77481).
+char(2,77482).
+char(8,77483).
+char(3,77484).
+char(4,77485).
+char(c,77486).
+char(c,77487).
+char(c,77488).
+char(c,77489).
+char(m,77490).
+char(7,77491).
+char(3,77492).
+char(c,77493).
+char(c,77494).
+char(p,77495).
+char(o,77496).
+char(m,77497).
+char(4,77498).
+char(2,77499).
+char(3,77500).
+char(p,77501).
+char(3,77502).
+char(3,77503).
+char(3,77504).
+char(p,77505).
+char(4,77506).
+char(6,77507).
+char(1,77508).
+char(4,77509).
+char(m,77510).
+char(o,77511).
+char(p,77512).
+char(5,77513).
+char(6,77514).
+char(8,77515).
+char(0,77516).
+char(p,77517).
+char(1,77518).
+char(2,77519).
+char(7,77520).
+char(4,77521).
+char(p,77522).
+char(2,77523).
+char(0,77524).
+char(1,77525).
+char(3,77526).
+char(c,77527).
+char(m,77528).
+char(o,77529).
+char(p,77530).
+char(o,77531).
+char(m,77532).
+char(o,77533).
+char(m,77534).
+char(o,77535).
+char(p,77536).
+char(o,77537).
+char(6,77538).
+char(2,77539).
+char(7,77540).
+char(3,77541).
+char(c,77542).
+char(c,77543).
+char(c,77544).
+char(m,77545).
+char(3,77546).
+char(6,77547).
+char(4,77548).
+char(0,77549).
+char(c,77550).
+char(m,77551).
+char(6,77552).
+char(1,77553).
+char(3,77554).
+char(9,77555).
+char(c,77556).
+char(c,77557).
+char(c,77558).
+char(p,77559).
+char(6,77560).
+char(5,77561).
+char(0,77562).
+char(7,77563).
+char(c,77564).
+char(c,77565).
+char(p,77566).
+char(4,77567).
+char(9,77568).
+char(2,77569).
+char(3,77570).
+char(p,77571).
+char(6,77572).
+char(2,77573).
+char(9,77574).
+char(6,77575).
+char(c,77576).
+char(p,77577).
+char(5,77578).
+char(7,77579).
+char(4,77580).
+char(6,77581).
+char(c,77582).
+char(c,77583).
+char(p,77584).
+char(9,77585).
+char(1,77586).
+char(c,77587).
+char(m,77588).
+char(o,77589).
+char(o,77590).
+char(m,77591).
+char(9,77592).
+char(0,77593).
+char(2,77594).
+char(7,77595).
+char(c,77596).
+char(c,77597).
+char(c,77598).
+char(c,77599).
+char(c,77600).
+char(m,77601).
+char(o,77602).
+char(m,77603).
+char(4,77604).
+char(5,77605).
+char(1,77606).
+char(m,77607).
+char(6,77608).
+char(9,77609).
+char(6,77610).
+char(2,77611).
+char(p,77612).
+char(6,77613).
+char(0,77614).
+char(3,77615).
+char(1,77616).
+char(p,77617).
+char(o,77618).
+char(p,77619).
+char(o,77620).
+char(m,77621).
+char(6,77622).
+char(1,77623).
+char(5,77624).
+char(3,77625).
+char(c,77626).
+char(p,77627).
+char(9,77628).
+char(8,77629).
+char(0,77630).
+char(8,77631).
+char(p,77632).
+char(4,77633).
+char(2,77634).
+char(5,77635).
+char(8,77636).
+char(c,77637).
+char(c,77638).
+char(c,77639).
+char(p,77640).
+char(o,77641).
+char(o,77642).
+char(m,77643).
+char(o,77644).
+char(o,77645).
+char(o,77646).
+char(p,77647).
+char(1,77648).
+char(0,77649).
+char(4,77650).
+char(c,77651).
+char(p,77652).
+char(o,77653).
+char(p,77654).
+char(6,77655).
+char(1,77656).
+char(4,77657).
+char(0,77658).
+char(m,77659).
+char(o,77660).
+char(m,77661).
+char(6,77662).
+char(9,77663).
+char(5,77664).
+char(2,77665).
+char(m,77666).
+char(1,77667).
+char(8,77668).
+char(0,77669).
+char(2,77670).
+char(p,77671).
+char(o,77672).
+char(m,77673).
+char(o,77674).
+char(m,77675).
+char(3,77676).
+char(2,77677).
+char(7,77678).
+char(4,77679).
+char(m,77680).
+char(o,77681).
+char(m,77682).
+char(o,77683).
+char(p,77684).
+char(3,77685).
+char(2,77686).
+char(2,77687).
+char(0,77688).
+char(p,77689).
+char(o,77690).
+char(p,77691).
+char(o,77692).
+char(p,77693).
+char(o,77694).
+char(5,77695).
+char(5,77696).
+char(9,77697).
+char(3,77698).
+char(c,77699).
+char(c,77700).
+char(c,77701).
+char(c,77702).
+char(p,77703).
+char(o,77704).
+char(m,77705).
+char(o,77706).
+char(p,77707).
+char(8,77708).
+char(0,77709).
+char(3,77710).
+char(3,77711).
+char(c,77712).
+char(c,77713).
+char(c,77714).
+char(c,77715).
+char(c,77716).
+char(p,77717).
+char(o,77718).
+char(o,77719).
+char(p,77720).
+char(o,77721).
+char(o,77722).
+char(m,77723).
+char(o,77724).
+char(m,77725).
+char(o,77726).
+char(m,77727).
+char(9,77728).
+char(3,77729).
+char(2,77730).
+char(1,77731).
+char(p,77732).
+char(o,77733).
+char(p,77734).
+char(o,77735).
+char(o,77736).
+char(p,77737).
+char(8,77738).
+char(3,77739).
+char(1,77740).
+char(9,77741).
+char(p,77742).
+char(1,77743).
+char(2,77744).
+char(9,77745).
+char(p,77746).
+char(8,77747).
+char(4,77748).
+char(8,77749).
+char(1,77750).
+char(c,77751).
+char(c,77752).
+char(m,77753).
+char(1,77754).
+char(5,77755).
+char(7,77756).
+char(5,77757).
+char(c,77758).
+char(p,77759).
+char(o,77760).
+char(m,77761).
+char(o,77762).
+char(p,77763).
+char(o,77764).
+char(o,77765).
+char(3,77766).
+char(2,77767).
+char(6,77768).
+char(3,77769).
+char(c,77770).
+char(c,77771).
+char(c,77772).
+char(p,77773).
+char(o,77774).
+char(6,77775).
+char(6,77776).
+char(6,77777).
+char(m,77778).
+char(4,77779).
+char(9,77780).
+char(7,77781).
+char(0,77782).
+char(c,77783).
+char(m,77784).
+char(7,77785).
+char(9,77786).
+char(1,77787).
+char(5,77788).
+char(c,77789).
+char(c,77790).
+char(c,77791).
+char(c,77792).
+char(c,77793).
+char(c,77794).
+char(c,77795).
+char(m,77796).
+char(6,77797).
+char(1,77798).
+char(9,77799).
+char(0,77800).
+char(c,77801).
+char(c,77802).
+char(m,77803).
+char(3,77804).
+char(7,77805).
+char(7,77806).
+char(p,77807).
+char(8,77808).
+char(0,77809).
+char(3,77810).
+char(9,77811).
+char(c,77812).
+char(c,77813).
+char(p,77814).
+char(3,77815).
+char(9,77816).
+char(8,77817).
+char(0,77818).
+char(c,77819).
+char(p,77820).
+char(9,77821).
+char(4,77822).
+char(8,77823).
+char(1,77824).
+char(c,77825).
+char(c,77826).
+char(c,77827).
+char(c,77828).
+char(c,77829).
+char(c,77830).
+char(c,77831).
+char(p,77832).
+char(o,77833).
+char(m,77834).
+char(3,77835).
+char(6,77836).
+char(9,77837).
+char(4,77838).
+char(m,77839).
+char(o,77840).
+char(7,77841).
+char(6,77842).
+char(9,77843).
+char(4,77844).
+char(p,77845).
+char(o,77846).
+char(p,77847).
+char(3,77848).
+char(7,77849).
+char(0,77850).
+char(1,77851).
+char(m,77852).
+char(7,77853).
+char(5,77854).
+char(3,77855).
+char(7,77856).
+char(c,77857).
+char(p,77858).
+char(o,77859).
+char(p,77860).
+char(1,77861).
+char(9,77862).
+char(4,77863).
+char(4,77864).
+char(p,77865).
+char(o,77866).
+char(p,77867).
+char(1,77868).
+char(7,77869).
+char(0,77870).
+char(4,77871).
+char(m,77872).
+char(o,77873).
+char(p,77874).
+char(o,77875).
+char(o,77876).
+char(m,77877).
+char(9,77878).
+char(9,77879).
+char(5,77880).
+char(1,77881).
+char(c,77882).
+char(c,77883).
+char(c,77884).
+char(c,77885).
+char(c,77886).
+char(m,77887).
+char(o,77888).
+char(m,77889).
+char(o,77890).
+char(m,77891).
+char(6,77892).
+char(9,77893).
+char(4,77894).
+char(4,77895).
+char(c,77896).
+char(p,77897).
+char(o,77898).
+char(3,77899).
+char(3,77900).
+char(7,77901).
+char(1,77902).
+char(c,77903).
+char(c,77904).
+char(p,77905).
+char(9,77906).
+char(1,77907).
+char(1,77908).
+char(c,77909).
+char(c,77910).
+char(c,77911).
+char(c,77912).
+char(c,77913).
+char(c,77914).
+char(c,77915).
+char(m,77916).
+char(o,77917).
+char(m,77918).
+char(o,77919).
+char(9,77920).
+char(7,77921).
+char(0,77922).
+char(1,77923).
+char(p,77924).
+char(o,77925).
+char(p,77926).
+char(o,77927).
+char(p,77928).
+char(o,77929).
+char(p,77930).
+char(o,77931).
+char(m,77932).
+char(o,77933).
+char(o,77934).
+char(p,77935).
+char(o,77936).
+char(m,77937).
+char(o,77938).
+char(m,77939).
+char(o,77940).
+char(p,77941).
+char(3,77942).
+char(1,77943).
+char(2,77944).
+char(2,77945).
+char(c,77946).
+char(c,77947).
+char(m,77948).
+char(1,77949).
+char(5,77950).
+char(2,77951).
+char(5,77952).
+char(p,77953).
+char(o,77954).
+char(4,77955).
+char(2,77956).
+char(8,77957).
+char(3,77958).
+char(c,77959).
+char(c,77960).
+char(c,77961).
+char(p,77962).
+char(o,77963).
+char(p,77964).
+char(o,77965).
+char(p,77966).
+char(o,77967).
+char(o,77968).
+char(o,77969).
+char(m,77970).
+char(o,77971).
+char(5,77972).
+char(3,77973).
+char(9,77974).
+char(m,77975).
+char(o,77976).
+char(m,77977).
+char(o,77978).
+char(p,77979).
+char(6,77980).
+char(2,77981).
+char(7,77982).
+char(6,77983).
+char(c,77984).
+char(m,77985).
+char(o,77986).
+char(o,77987).
+char(m,77988).
+char(9,77989).
+char(4,77990).
+char(2,77991).
+char(5,77992).
+char(p,77993).
+char(1,77994).
+char(4,77995).
+char(3,77996).
+char(2,77997).
+char(c,77998).
+char(c,77999).
+char(p,78000).
+char(o,78001).
+char(m,78002).
+char(o,78003).
+char(m,78004).
+char(6,78005).
+char(0,78006).
+char(0,78007).
+char(3,78008).
+char(p,78009).
+char(1,78010).
+char(7,78011).
+char(0,78012).
+char(6,78013).
+char(c,78014).
+char(c,78015).
+char(c,78016).
+char(m,78017).
+char(o,78018).
+char(p,78019).
+char(o,78020).
+char(o,78021).
+char(p,78022).
+char(o,78023).
+char(p,78024).
+char(o,78025).
+char(m,78026).
+char(o,78027).
+char(m,78028).
+char(o,78029).
+char(p,78030).
+char(1,78031).
+char(4,78032).
+char(2,78033).
+char(3,78034).
+char(p,78035).
+char(o,78036).
+char(7,78037).
+char(9,78038).
+char(2,78039).
+char(9,78040).
+char(m,78041).
+char(o,78042).
+char(8,78043).
+char(1,78044).
+char(3,78045).
+char(9,78046).
+char(p,78047).
+char(o,78048).
+char(2,78049).
+char(1,78050).
+char(4,78051).
+char(5,78052).
+char(c,78053).
+char(c,78054).
+char(c,78055).
+char(m,78056).
+char(o,78057).
+char(m,78058).
+char(o,78059).
+char(p,78060).
+char(3,78061).
+char(1,78062).
+char(7,78063).
+char(7,78064).
+char(m,78065).
+char(5,78066).
+char(3,78067).
+char(5,78068).
+char(9,78069).
+char(m,78070).
+char(4,78071).
+char(3,78072).
+char(1,78073).
+char(6,78074).
+char(m,78075).
+char(3,78076).
+char(0,78077).
+char(2,78078).
+char(1,78079).
+char(c,78080).
+char(c,78081).
+char(m,78082).
+char(1,78083).
+char(5,78084).
+char(1,78085).
+char(0,78086).
+char(c,78087).
+char(p,78088).
+char(o,78089).
+char(p,78090).
+char(7,78091).
+char(0,78092).
+char(6,78093).
+char(5,78094).
+char(c,78095).
+char(c,78096).
+char(c,78097).
+char(c,78098).
+char(c,78099).
+char(p,78100).
+char(6,78101).
+char(5,78102).
+char(3,78103).
+char(3,78104).
+char(c,78105).
+char(m,78106).
+char(o,78107).
+char(p,78108).
+char(o,78109).
+char(4,78110).
+char(4,78111).
+char(1,78112).
+char(2,78113).
+char(c,78114).
+char(p,78115).
+char(5,78116).
+char(5,78117).
+char(3,78118).
+char(4,78119).
+char(c,78120).
+char(c,78121).
+char(c,78122).
+char(p,78123).
+char(o,78124).
+char(p,78125).
+char(9,78126).
+char(6,78127).
+char(0,78128).
+char(1,78129).
+char(c,78130).
+char(m,78131).
+char(4,78132).
+char(3,78133).
+char(4,78134).
+char(2,78135).
+char(c,78136).
+char(c,78137).
+char(c,78138).
+char(p,78139).
+char(9,78140).
+char(6,78141).
+char(9,78142).
+char(7,78143).
+char(c,78144).
+char(c,78145).
+char(p,78146).
+char(o,78147).
+char(m,78148).
+char(6,78149).
+char(4,78150).
+char(7,78151).
+char(5,78152).
+char(c,78153).
+char(c,78154).
+char(c,78155).
+char(c,78156).
+char(m,78157).
+char(8,78158).
+char(1,78159).
+char(0,78160).
+char(3,78161).
+char(m,78162).
+char(o,78163).
+char(m,78164).
+char(o,78165).
+char(m,78166).
+char(o,78167).
+char(8,78168).
+char(6,78169).
+char(2,78170).
+char(1,78171).
+char(p,78172).
+char(o,78173).
+char(4,78174).
+char(5,78175).
+char(2,78176).
+char(1,78177).
+char(c,78178).
+char(p,78179).
+char(1,78180).
+char(2,78181).
+char(7,78182).
+char(0,78183).
+char(p,78184).
+char(o,78185).
+char(m,78186).
+char(o,78187).
+char(m,78188).
+char(o,78189).
+char(1,78190).
+char(9,78191).
+char(1,78192).
+char(1,78193).
+char(p,78194).
+char(o,78195).
+char(o,78196).
+char(m,78197).
+char(4,78198).
+char(9,78199).
+char(5,78200).
+char(4,78201).
+char(c,78202).
+char(p,78203).
+char(o,78204).
+char(m,78205).
+char(o,78206).
+char(o,78207).
+char(p,78208).
+char(o,78209).
+char(m,78210).
+char(o,78211).
+char(p,78212).
+char(2,78213).
+char(5,78214).
+char(6,78215).
+char(8,78216).
+char(m,78217).
+char(o,78218).
+char(m,78219).
+char(5,78220).
+char(1,78221).
+char(4,78222).
+char(p,78223).
+char(4,78224).
+char(8,78225).
+char(3,78226).
+char(5,78227).
+char(c,78228).
+char(p,78229).
+char(1,78230).
+char(0,78231).
+char(8,78232).
+char(5,78233).
+char(p,78234).
+char(6,78235).
+char(6,78236).
+char(0,78237).
+char(p,78238).
+char(3,78239).
+char(9,78240).
+char(3,78241).
+char(9,78242).
+char(c,78243).
+char(c,78244).
+char(m,78245).
+char(2,78246).
+char(7,78247).
+char(5,78248).
+char(8,78249).
+char(c,78250).
+char(c,78251).
+char(c,78252).
+char(p,78253).
+char(7,78254).
+char(5,78255).
+char(9,78256).
+char(1,78257).
+char(c,78258).
+char(m,78259).
+char(3,78260).
+char(3,78261).
+char(6,78262).
+char(9,78263).
+char(c,78264).
+char(m,78265).
+char(8,78266).
+char(3,78267).
+char(2,78268).
+char(p,78269).
+char(o,78270).
+char(m,78271).
+char(o,78272).
+char(p,78273).
+char(o,78274).
+char(3,78275).
+char(4,78276).
+char(7,78277).
+char(3,78278).
+char(p,78279).
+char(o,78280).
+char(p,78281).
+char(o,78282).
+char(m,78283).
+char(o,78284).
+char(m,78285).
+char(o,78286).
+char(o,78287).
+char(p,78288).
+char(2,78289).
+char(4,78290).
+char(2,78291).
+char(3,78292).
+char(p,78293).
+char(5,78294).
+char(1,78295).
+char(6,78296).
+char(7,78297).
+char(p,78298).
+char(2,78299).
+char(2,78300).
+char(6,78301).
+char(2,78302).
+char(c,78303).
+char(m,78304).
+char(4,78305).
+char(6,78306).
+char(0,78307).
+char(7,78308).
+char(m,78309).
+char(5,78310).
+char(8,78311).
+char(4,78312).
+char(5,78313).
+char(c,78314).
+char(c,78315).
+char(p,78316).
+char(o,78317).
+char(o,78318).
+char(m,78319).
+char(1,78320).
+char(4,78321).
+char(4,78322).
+char(m,78323).
+char(6,78324).
+char(3,78325).
+char(1,78326).
+char(m,78327).
+char(4,78328).
+char(8,78329).
+char(2,78330).
+char(9,78331).
+char(m,78332).
+char(8,78333).
+char(5,78334).
+char(6,78335).
+char(7,78336).
+char(c,78337).
+char(c,78338).
+char(m,78339).
+char(o,78340).
+char(m,78341).
+char(5,78342).
+char(1,78343).
+char(1,78344).
+char(2,78345).
+char(c,78346).
+char(c,78347).
+char(p,78348).
+char(o,78349).
+char(m,78350).
+char(o,78351).
+char(p,78352).
+char(8,78353).
+char(5,78354).
+char(7,78355).
+char(0,78356).
+char(m,78357).
+char(o,78358).
+char(o,78359).
+char(m,78360).
+char(o,78361).
+char(o,78362).
+char(m,78363).
+char(o,78364).
+char(p,78365).
+char(o,78366).
+char(p,78367).
+char(2,78368).
+char(2,78369).
+char(4,78370).
+char(9,78371).
+char(c,78372).
+char(c,78373).
+char(m,78374).
+char(8,78375).
+char(0,78376).
+char(5,78377).
+char(1,78378).
+char(p,78379).
+char(o,78380).
+char(5,78381).
+char(0,78382).
+char(5,78383).
+char(9,78384).
+char(p,78385).
+char(o,78386).
+char(p,78387).
+char(8,78388).
+char(5,78389).
+char(1,78390).
+char(7,78391).
+char(c,78392).
+char(c,78393).
+char(p,78394).
+char(4,78395).
+char(8,78396).
+char(7,78397).
+char(9,78398).
+char(m,78399).
+char(o,78400).
+char(o,78401).
+char(m,78402).
+char(o,78403).
+char(p,78404).
+char(6,78405).
+char(5,78406).
+char(8,78407).
+char(m,78408).
+char(o,78409).
+char(9,78410).
+char(7,78411).
+char(8,78412).
+char(2,78413).
+char(m,78414).
+char(4,78415).
+char(7,78416).
+char(8,78417).
+char(4,78418).
+char(p,78419).
+char(5,78420).
+char(0,78421).
+char(5,78422).
+char(1,78423).
+char(c,78424).
+char(p,78425).
+char(7,78426).
+char(5,78427).
+char(8,78428).
+char(2,78429).
+char(m,78430).
+char(o,78431).
+char(p,78432).
+char(o,78433).
+char(p,78434).
+char(o,78435).
+char(m,78436).
+char(o,78437).
+char(p,78438).
+char(8,78439).
+char(8,78440).
+char(2,78441).
+char(1,78442).
+char(m,78443).
+char(o,78444).
+char(9,78445).
+char(9,78446).
+char(5,78447).
+char(8,78448).
+char(p,78449).
+char(o,78450).
+char(7,78451).
+char(8,78452).
+char(5,78453).
+char(6,78454).
+char(m,78455).
+char(4,78456).
+char(9,78457).
+char(5,78458).
+char(4,78459).
+char(m,78460).
+char(1,78461).
+char(4,78462).
+char(5,78463).
+char(4,78464).
+char(m,78465).
+char(o,78466).
+char(m,78467).
+char(o,78468).
+char(m,78469).
+char(o,78470).
+char(o,78471).
+char(4,78472).
+char(3,78473).
+char(9,78474).
+char(m,78475).
+char(3,78476).
+char(5,78477).
+char(0,78478).
+char(4,78479).
+char(c,78480).
+char(m,78481).
+char(o,78482).
+char(m,78483).
+char(o,78484).
+char(m,78485).
+char(o,78486).
+char(o,78487).
+char(p,78488).
+char(o,78489).
+char(o,78490).
+char(p,78491).
+char(o,78492).
+char(m,78493).
+char(2,78494).
+char(9,78495).
+char(4,78496).
+char(0,78497).
+char(c,78498).
+char(p,78499).
+char(o,78500).
+char(2,78501).
+char(9,78502).
+char(8,78503).
+char(9,78504).
+char(c,78505).
+char(c,78506).
+char(c,78507).
+char(c,78508).
+char(c,78509).
+char(p,78510).
+char(o,78511).
+char(o,78512).
+char(m,78513).
+char(o,78514).
+char(p,78515).
+char(o,78516).
+char(o,78517).
+char(7,78518).
+char(0,78519).
+char(1,78520).
+char(1,78521).
+char(c,78522).
+char(c,78523).
+char(p,78524).
+char(2,78525).
+char(6,78526).
+char(9,78527).
+char(0,78528).
+char(c,78529).
+char(c,78530).
+char(m,78531).
+char(4,78532).
+char(0,78533).
+char(4,78534).
+char(1,78535).
+char(c,78536).
+char(p,78537).
+char(o,78538).
+char(m,78539).
+char(o,78540).
+char(p,78541).
+char(o,78542).
+char(o,78543).
+char(p,78544).
+char(o,78545).
+char(o,78546).
+char(m,78547).
+char(o,78548).
+char(p,78549).
+char(8,78550).
+char(2,78551).
+char(1,78552).
+char(8,78553).
+char(m,78554).
+char(9,78555).
+char(7,78556).
+char(0,78557).
+char(7,78558).
+char(c,78559).
+char(c,78560).
+char(m,78561).
+char(3,78562).
+char(4,78563).
+char(6,78564).
+char(0,78565).
+char(c,78566).
+char(c,78567).
+char(m,78568).
+char(o,78569).
+char(m,78570).
+char(o,78571).
+char(p,78572).
+char(o,78573).
+char(o,78574).
+char(m,78575).
+char(6,78576).
+char(2,78577).
+char(0,78578).
+char(9,78579).
+char(c,78580).
+char(c,78581).
+char(p,78582).
+char(o,78583).
+char(m,78584).
+char(o,78585).
+char(p,78586).
+char(5,78587).
+char(5,78588).
+char(6,78589).
+char(2,78590).
+char(c,78591).
+char(c,78592).
+char(p,78593).
+char(o,78594).
+char(1,78595).
+char(9,78596).
+char(9,78597).
+char(5,78598).
+char(m,78599).
+char(o,78600).
+char(m,78601).
+char(5,78602).
+char(1,78603).
+char(0,78604).
+char(8,78605).
+char(p,78606).
+char(8,78607).
+char(9,78608).
+char(2,78609).
+char(7,78610).
+char(c,78611).
+char(c,78612).
+char(c,78613).
+char(c,78614).
+char(c,78615).
+char(c,78616).
+char(c,78617).
+char(p,78618).
+char(o,78619).
+char(o,78620).
+char(m,78621).
+char(o,78622).
+char(p,78623).
+char(4,78624).
+char(9,78625).
+char(8,78626).
+char(7,78627).
+char(c,78628).
+char(c,78629).
+char(c,78630).
+char(m,78631).
+char(5,78632).
+char(8,78633).
+char(1,78634).
+char(7,78635).
+char(c,78636).
+char(p,78637).
+char(9,78638).
+char(2,78639).
+char(0,78640).
+char(0,78641).
+char(m,78642).
+char(8,78643).
+char(0,78644).
+char(6,78645).
+char(0,78646).
+char(c,78647).
+char(c,78648).
+char(c,78649).
+char(c,78650).
+char(c,78651).
+char(c,78652).
+char(c,78653).
+char(c,78654).
+char(c,78655).
+char(m,78656).
+char(o,78657).
+char(m,78658).
+char(o,78659).
+char(m,78660).
+char(o,78661).
+char(m,78662).
+char(o,78663).
+char(5,78664).
+char(9,78665).
+char(9,78666).
+char(1,78667).
+char(c,78668).
+char(c,78669).
+char(p,78670).
+char(2,78671).
+char(5,78672).
+char(4,78673).
+char(9,78674).
+char(c,78675).
+char(m,78676).
+char(o,78677).
+char(m,78678).
+char(1,78679).
+char(9,78680).
+char(4,78681).
+char(6,78682).
+char(c,78683).
+char(p,78684).
+char(1,78685).
+char(6,78686).
+char(8,78687).
+char(7,78688).
+char(m,78689).
+char(1,78690).
+char(1,78691).
+char(1,78692).
+char(0,78693).
+char(c,78694).
+char(c,78695).
+char(c,78696).
+char(p,78697).
+char(o,78698).
+char(4,78699).
+char(7,78700).
+char(5,78701).
+char(9,78702).
+char(m,78703).
+char(o,78704).
+char(p,78705).
+char(o,78706).
+char(m,78707).
+char(3,78708).
+char(9,78709).
+char(1,78710).
+char(8,78711).
+char(p,78712).
+char(7,78713).
+char(6,78714).
+char(9,78715).
+char(3,78716).
+char(p,78717).
+char(2,78718).
+char(7,78719).
+char(4,78720).
+char(4,78721).
+char(c,78722).
+char(c,78723).
+char(c,78724).
+char(c,78725).
+char(c,78726).
+char(c,78727).
+char(p,78728).
+char(o,78729).
+char(m,78730).
+char(o,78731).
+char(m,78732).
+char(5,78733).
+char(4,78734).
+char(2,78735).
+char(7,78736).
+char(m,78737).
+char(o,78738).
+char(p,78739).
+char(7,78740).
+char(7,78741).
+char(2,78742).
+char(2,78743).
+char(c,78744).
+char(p,78745).
+char(9,78746).
+char(9,78747).
+char(9,78748).
+char(7,78749).
+char(m,78750).
+char(5,78751).
+char(3,78752).
+char(9,78753).
+char(0,78754).
+char(c,78755).
+char(m,78756).
+char(7,78757).
+char(1,78758).
+char(2,78759).
+char(5,78760).
+char(m,78761).
+char(7,78762).
+char(0,78763).
+char(3,78764).
+char(9,78765).
+char(p,78766).
+char(o,78767).
+char(p,78768).
+char(5,78769).
+char(3,78770).
+char(4,78771).
+char(2,78772).
+char(c,78773).
+char(m,78774).
+char(o,78775).
+char(8,78776).
+char(3,78777).
+char(5,78778).
+char(7,78779).
+char(m,78780).
+char(o,78781).
+char(9,78782).
+char(7,78783).
+char(5,78784).
+char(5,78785).
+char(p,78786).
+char(3,78787).
+char(7,78788).
+char(1,78789).
+char(3,78790).
+char(c,78791).
+char(p,78792).
+char(o,78793).
+char(m,78794).
+char(o,78795).
+char(5,78796).
+char(5,78797).
+char(7,78798).
+char(1,78799).
+char(m,78800).
+char(3,78801).
+char(0,78802).
+char(9,78803).
+char(1,78804).
+char(c,78805).
+char(m,78806).
+char(o,78807).
+char(8,78808).
+char(1,78809).
+char(2,78810).
+char(8,78811).
+char(p,78812).
+char(9,78813).
+char(3,78814).
+char(0,78815).
+char(4,78816).
+char(c,78817).
+char(p,78818).
+char(4,78819).
+char(9,78820).
+char(2,78821).
+char(3,78822).
+char(c,78823).
+char(c,78824).
+char(p,78825).
+char(9,78826).
+char(3,78827).
+char(5,78828).
+char(7,78829).
+char(m,78830).
+char(o,78831).
+char(6,78832).
+char(4,78833).
+char(2,78834).
+char(5,78835).
+char(c,78836).
+char(m,78837).
+char(3,78838).
+char(7,78839).
+char(4,78840).
+char(9,78841).
+char(m,78842).
+char(o,78843).
+char(o,78844).
+char(7,78845).
+char(4,78846).
+char(5,78847).
+char(4,78848).
+char(c,78849).
+char(c,78850).
+char(m,78851).
+char(o,78852).
+char(m,78853).
+char(o,78854).
+char(p,78855).
+char(6,78856).
+char(6,78857).
+char(1,78858).
+char(7,78859).
+char(m,78860).
+char(3,78861).
+char(7,78862).
+char(7,78863).
+char(0,78864).
+char(c,78865).
+char(p,78866).
+char(5,78867).
+char(6,78868).
+char(0,78869).
+char(8,78870).
+char(c,78871).
+char(p,78872).
+char(o,78873).
+char(p,78874).
+char(1,78875).
+char(2,78876).
+char(8,78877).
+char(2,78878).
+char(m,78879).
+char(8,78880).
+char(1,78881).
+char(2,78882).
+char(9,78883).
+char(c,78884).
+char(p,78885).
+char(6,78886).
+char(1,78887).
+char(1,78888).
+char(7,78889).
+char(p,78890).
+char(o,78891).
+char(9,78892).
+char(3,78893).
+char(5,78894).
+char(p,78895).
+char(o,78896).
+char(p,78897).
+char(o,78898).
+char(6,78899).
+char(8,78900).
+char(0,78901).
+char(m,78902).
+char(4,78903).
+char(2,78904).
+char(0,78905).
+char(1,78906).
+char(p,78907).
+char(7,78908).
+char(3,78909).
+char(2,78910).
+char(9,78911).
+char(m,78912).
+char(o,78913).
+char(m,78914).
+char(3,78915).
+char(9,78916).
+char(9,78917).
+char(6,78918).
+char(c,78919).
+char(p,78920).
+char(2,78921).
+char(5,78922).
+char(4,78923).
+char(6,78924).
+char(p,78925).
+char(1,78926).
+char(7,78927).
+char(2,78928).
+char(6,78929).
+char(c,78930).
+char(p,78931).
+char(o,78932).
+char(m,78933).
+char(o,78934).
+char(m,78935).
+char(o,78936).
+char(p,78937).
+char(2,78938).
+char(5,78939).
+char(6,78940).
+char(6,78941).
+char(m,78942).
+char(o,78943).
+char(o,78944).
+char(m,78945).
+char(o,78946).
+char(p,78947).
+char(2,78948).
+char(9,78949).
+char(0,78950).
+char(5,78951).
+char(m,78952).
+char(6,78953).
+char(7,78954).
+char(9,78955).
+char(2,78956).
+char(c,78957).
+char(p,78958).
+char(2,78959).
+char(7,78960).
+char(9,78961).
+char(4,78962).
+char(p,78963).
+char(9,78964).
+char(1,78965).
+char(1,78966).
+char(0,78967).
+char(c,78968).
+char(m,78969).
+char(2,78970).
+char(6,78971).
+char(4,78972).
+char(6,78973).
+char(c,78974).
+char(c,78975).
+char(c,78976).
+char(c,78977).
+char(p,78978).
+char(o,78979).
+char(3,78980).
+char(2,78981).
+char(4,78982).
+char(0,78983).
+char(c,78984).
+char(p,78985).
+char(o,78986).
+char(m,78987).
+char(5,78988).
+char(4,78989).
+char(0,78990).
+char(2,78991).
+char(c,78992).
+char(m,78993).
+char(o,78994).
+char(p,78995).
+char(9,78996).
+char(5,78997).
+char(5,78998).
+char(8,78999).
+char(m,79000).
+char(4,79001).
+char(0,79002).
+char(9,79003).
+char(5,79004).
+char(c,79005).
+char(c,79006).
+char(c,79007).
+char(c,79008).
+char(p,79009).
+char(7,79010).
+char(7,79011).
+char(3,79012).
+char(1,79013).
+char(c,79014).
+char(c,79015).
+char(c,79016).
+char(c,79017).
+char(c,79018).
+char(p,79019).
+char(6,79020).
+char(3,79021).
+char(3,79022).
+char(2,79023).
+char(p,79024).
+char(o,79025).
+char(p,79026).
+char(5,79027).
+char(1,79028).
+char(1,79029).
+char(7,79030).
+char(c,79031).
+char(p,79032).
+char(5,79033).
+char(4,79034).
+char(5,79035).
+char(c,79036).
+char(c,79037).
+char(c,79038).
+char(c,79039).
+char(c,79040).
+char(c,79041).
+char(c,79042).
+char(m,79043).
+char(o,79044).
+char(m,79045).
+char(9,79046).
+char(7,79047).
+char(0,79048).
+char(5,79049).
+char(c,79050).
+char(c,79051).
+char(m,79052).
+char(2,79053).
+char(1,79054).
+char(9,79055).
+char(1,79056).
+char(c,79057).
+char(c,79058).
+char(c,79059).
+char(c,79060).
+char(c,79061).
+char(c,79062).
+char(m,79063).
+char(o,79064).
+char(m,79065).
+char(o,79066).
+char(o,79067).
+char(7,79068).
+char(6,79069).
+char(5,79070).
+char(7,79071).
+char(m,79072).
+char(8,79073).
+char(5,79074).
+char(9,79075).
+char(6,79076).
+char(c,79077).
+char(m,79078).
+char(o,79079).
+char(7,79080).
+char(1,79081).
+char(3,79082).
+char(0,79083).
+char(m,79084).
+char(7,79085).
+char(1,79086).
+char(2,79087).
+char(9,79088).
+char(c,79089).
+char(c,79090).
+char(c,79091).
+char(p,79092).
+char(o,79093).
+char(p,79094).
+char(o,79095).
+char(o,79096).
+char(m,79097).
+char(o,79098).
+char(m,79099).
+char(3,79100).
+char(8,79101).
+char(8,79102).
+char(0,79103).
+char(c,79104).
+char(p,79105).
+char(1,79106).
+char(1,79107).
+char(0,79108).
+char(3,79109).
+char(m,79110).
+char(7,79111).
+char(2,79112).
+char(7,79113).
+char(7,79114).
+char(c,79115).
+char(p,79116).
+char(o,79117).
+char(m,79118).
+char(o,79119).
+char(o,79120).
+char(p,79121).
+char(1,79122).
+char(4,79123).
+char(6,79124).
+char(6,79125).
+char(m,79126).
+char(6,79127).
+char(6,79128).
+char(0,79129).
+char(p,79130).
+char(o,79131).
+char(p,79132).
+char(o,79133).
+char(p,79134).
+char(o,79135).
+char(m,79136).
+char(o,79137).
+char(p,79138).
+char(4,79139).
+char(7,79140).
+char(6,79141).
+char(2,79142).
+char(c,79143).
+char(p,79144).
+char(2,79145).
+char(0,79146).
+char(9,79147).
+char(2,79148).
+char(c,79149).
+char(c,79150).
+char(c,79151).
+char(c,79152).
+char(c,79153).
+char(c,79154).
+char(c,79155).
+char(p,79156).
+char(o,79157).
+char(m,79158).
+char(o,79159).
+char(o,79160).
+char(o,79161).
+char(p,79162).
+char(o,79163).
+char(p,79164).
+char(o,79165).
+char(m,79166).
+char(2,79167).
+char(5,79168).
+char(5,79169).
+char(m,79170).
+char(o,79171).
+char(o,79172).
+char(o,79173).
+char(3,79174).
+char(9,79175).
+char(8,79176).
+char(9,79177).
+char(c,79178).
+char(c,79179).
+char(p,79180).
+char(7,79181).
+char(0,79182).
+char(1,79183).
+char(1,79184).
+char(c,79185).
+char(c,79186).
+char(p,79187).
+char(o,79188).
+char(m,79189).
+char(o,79190).
+char(m,79191).
+char(o,79192).
+char(p,79193).
+char(2,79194).
+char(7,79195).
+char(6,79196).
+char(2,79197).
+char(c,79198).
+char(m,79199).
+char(o,79200).
+char(m,79201).
+char(o,79202).
+char(m,79203).
+char(8,79204).
+char(5,79205).
+char(1,79206).
+char(6,79207).
+char(c,79208).
+char(c,79209).
+char(c,79210).
+char(c,79211).
+char(m,79212).
+char(4,79213).
+char(4,79214).
+char(4,79215).
+char(5,79216).
+char(c,79217).
+char(m,79218).
+char(7,79219).
+char(7,79220).
+char(4,79221).
+char(6,79222).
+char(p,79223).
+char(o,79224).
+char(m,79225).
+char(4,79226).
+char(6,79227).
+char(3,79228).
+char(p,79229).
+char(o,79230).
+char(p,79231).
+char(9,79232).
+char(8,79233).
+char(5,79234).
+char(1,79235).
+char(m,79236).
+char(o,79237).
+char(p,79238).
+char(8,79239).
+char(8,79240).
+char(6,79241).
+char(3,79242).
+char(c,79243).
+char(p,79244).
+char(o,79245).
+char(o,79246).
+char(p,79247).
+char(4,79248).
+char(0,79249).
+char(8,79250).
+char(9,79251).
+char(c,79252).
+char(c,79253).
+char(p,79254).
+char(o,79255).
+char(m,79256).
+char(7,79257).
+char(4,79258).
+char(1,79259).
+char(7,79260).
+char(p,79261).
+char(o,79262).
+char(5,79263).
+char(5,79264).
+char(6,79265).
+char(7,79266).
+char(c,79267).
+char(p,79268).
+char(5,79269).
+char(0,79270).
+char(3,79271).
+char(6,79272).
+char(c,79273).
+char(c,79274).
+char(m,79275).
+char(o,79276).
+char(m,79277).
+char(5,79278).
+char(6,79279).
+char(7,79280).
+char(p,79281).
+char(o,79282).
+char(m,79283).
+char(o,79284).
+char(m,79285).
+char(o,79286).
+char(o,79287).
+char(p,79288).
+char(5,79289).
+char(0,79290).
+char(8,79291).
+char(1,79292).
+char(p,79293).
+char(8,79294).
+char(5,79295).
+char(6,79296).
+char(8,79297).
+char(m,79298).
+char(o,79299).
+char(p,79300).
+char(o,79301).
+char(o,79302).
+char(m,79303).
+char(o,79304).
+char(m,79305).
+char(8,79306).
+char(5,79307).
+char(8,79308).
+char(5,79309).
+char(c,79310).
+char(c,79311).
+char(c,79312).
+char(m,79313).
+char(o,79314).
+char(6,79315).
+char(2,79316).
+char(2,79317).
+char(6,79318).
+char(c,79319).
+char(c,79320).
+char(p,79321).
+char(o,79322).
+char(o,79323).
+char(m,79324).
+char(9,79325).
+char(8,79326).
+char(3,79327).
+char(4,79328).
+char(m,79329).
+char(o,79330).
+char(1,79331).
+char(0,79332).
+char(9,79333).
+char(0,79334).
+char(p,79335).
+char(o,79336).
+char(2,79337).
+char(5,79338).
+char(2,79339).
+char(m,79340).
+char(9,79341).
+char(8,79342).
+char(7,79343).
+char(1,79344).
+char(c,79345).
+char(m,79346).
+char(5,79347).
+char(6,79348).
+char(1,79349).
+char(p,79350).
+char(6,79351).
+char(1,79352).
+char(5,79353).
+char(1,79354).
+char(m,79355).
+char(8,79356).
+char(0,79357).
+char(1,79358).
+char(1,79359).
+char(p,79360).
+char(1,79361).
+char(7,79362).
+char(3,79363).
+char(0,79364).
+char(m,79365).
+char(o,79366).
+char(m,79367).
+char(o,79368).
+char(p,79369).
+char(4,79370).
+char(7,79371).
+char(8,79372).
+char(6,79373).
+char(c,79374).
+char(c,79375).
+char(m,79376).
+char(o,79377).
+char(o,79378).
+char(m,79379).
+char(9,79380).
+char(3,79381).
+char(9,79382).
+char(0,79383).
+char(m,79384).
+char(2,79385).
+char(4,79386).
+char(8,79387).
+char(7,79388).
+char(p,79389).
+char(o,79390).
+char(p,79391).
+char(2,79392).
+char(4,79393).
+char(7,79394).
+char(4,79395).
+char(m,79396).
+char(8,79397).
+char(6,79398).
+char(8,79399).
+char(9,79400).
+char(c,79401).
+char(c,79402).
+char(m,79403).
+char(9,79404).
+char(2,79405).
+char(6,79406).
+char(m,79407).
+char(7,79408).
+char(0,79409).
+char(8,79410).
+char(m,79411).
+char(o,79412).
+char(p,79413).
+char(6,79414).
+char(2,79415).
+char(1,79416).
+char(6,79417).
+char(c,79418).
+char(p,79419).
+char(o,79420).
+char(p,79421).
+char(o,79422).
+char(5,79423).
+char(1,79424).
+char(6,79425).
+char(3,79426).
+char(p,79427).
+char(1,79428).
+char(4,79429).
+char(7,79430).
+char(0,79431).
+char(p,79432).
+char(4,79433).
+char(9,79434).
+char(4,79435).
+char(8,79436).
+char(m,79437).
+char(3,79438).
+char(0,79439).
+char(1,79440).
+char(3,79441).
+char(p,79442).
+char(o,79443).
+char(m,79444).
+char(8,79445).
+char(5,79446).
+char(5,79447).
+char(c,79448).
+char(m,79449).
+char(o,79450).
+char(m,79451).
+char(7,79452).
+char(7,79453).
+char(6,79454).
+char(7,79455).
+char(c,79456).
+char(c,79457).
+char(c,79458).
+char(c,79459).
+char(c,79460).
+char(m,79461).
+char(o,79462).
+char(7,79463).
+char(7,79464).
+char(0,79465).
+char(1,79466).
+char(c,79467).
+char(c,79468).
+char(m,79469).
+char(1,79470).
+char(2,79471).
+char(0,79472).
+char(9,79473).
+char(p,79474).
+char(5,79475).
+char(9,79476).
+char(6,79477).
+char(4,79478).
+char(m,79479).
+char(3,79480).
+char(9,79481).
+char(9,79482).
+char(6,79483).
+char(c,79484).
+char(c,79485).
+char(c,79486).
+char(c,79487).
+char(m,79488).
+char(1,79489).
+char(2,79490).
+char(9,79491).
+char(4,79492).
+char(m,79493).
+char(7,79494).
+char(2,79495).
+char(5,79496).
+char(c,79497).
+char(c,79498).
+char(c,79499).
+char(p,79500).
+char(o,79501).
+char(m,79502).
+char(o,79503).
+char(p,79504).
+char(1,79505).
+char(0,79506).
+char(1,79507).
+char(0,79508).
+char(m,79509).
+char(9,79510).
+char(6,79511).
+char(6,79512).
+char(3,79513).
+char(m,79514).
+char(o,79515).
+char(m,79516).
+char(1,79517).
+char(8,79518).
+char(0,79519).
+char(3,79520).
+char(p,79521).
+char(o,79522).
+char(m,79523).
+char(o,79524).
+char(m,79525).
+char(o,79526).
+char(m,79527).
+char(1,79528).
+char(6,79529).
+char(9,79530).
+char(2,79531).
+char(c,79532).
+char(p,79533).
+char(5,79534).
+char(5,79535).
+char(9,79536).
+char(2,79537).
+char(p,79538).
+char(7,79539).
+char(6,79540).
+char(0,79541).
+char(4,79542).
+char(p,79543).
+char(7,79544).
+char(4,79545).
+char(7,79546).
+char(0,79547).
+char(m,79548).
+char(2,79549).
+char(7,79550).
+char(5,79551).
+char(6,79552).
+char(p,79553).
+char(8,79554).
+char(4,79555).
+char(6,79556).
+char(p,79557).
+char(o,79558).
+char(3,79559).
+char(2,79560).
+char(7,79561).
+char(1,79562).
+char(c,79563).
+char(p,79564).
+char(3,79565).
+char(2,79566).
+char(4,79567).
+char(c,79568).
+char(c,79569).
+char(m,79570).
+char(o,79571).
+char(m,79572).
+char(7,79573).
+char(3,79574).
+char(9,79575).
+char(2,79576).
+char(m,79577).
+char(3,79578).
+char(8,79579).
+char(9,79580).
+char(8,79581).
+char(c,79582).
+char(c,79583).
+char(p,79584).
+char(o,79585).
+char(p,79586).
+char(o,79587).
+char(p,79588).
+char(o,79589).
+char(m,79590).
+char(o,79591).
+char(p,79592).
+char(9,79593).
+char(9,79594).
+char(0,79595).
+char(9,79596).
+char(c,79597).
+char(m,79598).
+char(o,79599).
+char(m,79600).
+char(6,79601).
+char(4,79602).
+char(7,79603).
+char(3,79604).
+char(c,79605).
+char(m,79606).
+char(9,79607).
+char(5,79608).
+char(2,79609).
+char(6,79610).
+char(p,79611).
+char(o,79612).
+char(p,79613).
+char(2,79614).
+char(8,79615).
+char(9,79616).
+char(4,79617).
+char(p,79618).
+char(6,79619).
+char(4,79620).
+char(3,79621).
+char(9,79622).
+char(m,79623).
+char(1,79624).
+char(8,79625).
+char(8,79626).
+char(4,79627).
+char(c,79628).
+char(p,79629).
+char(7,79630).
+char(7,79631).
+char(8,79632).
+char(8,79633).
+char(c,79634).
+char(c,79635).
+char(c,79636).
+char(c,79637).
+char(m,79638).
+char(o,79639).
+char(7,79640).
+char(3,79641).
+char(8,79642).
+char(0,79643).
+char(m,79644).
+char(o,79645).
+char(8,79646).
+char(6,79647).
+char(0,79648).
+char(3,79649).
+char(p,79650).
+char(o,79651).
+char(m,79652).
+char(8,79653).
+char(5,79654).
+char(3,79655).
+char(0,79656).
+char(c,79657).
+char(c,79658).
+char(m,79659).
+char(6,79660).
+char(1,79661).
+char(5,79662).
+char(7,79663).
+char(c,79664).
+char(m,79665).
+char(o,79666).
+char(m,79667).
+char(7,79668).
+char(6,79669).
+char(1,79670).
+char(c,79671).
+char(c,79672).
+char(c,79673).
+char(c,79674).
+char(m,79675).
+char(o,79676).
+char(2,79677).
+char(4,79678).
+char(7,79679).
+char(5,79680).
+char(c,79681).
+char(p,79682).
+char(7,79683).
+char(8,79684).
+char(4,79685).
+char(7,79686).
+char(p,79687).
+char(4,79688).
+char(7,79689).
+char(5,79690).
+char(c,79691).
+char(c,79692).
+char(c,79693).
+char(c,79694).
+char(c,79695).
+char(m,79696).
+char(o,79697).
+char(o,79698).
+char(p,79699).
+char(o,79700).
+char(m,79701).
+char(o,79702).
+char(m,79703).
+char(4,79704).
+char(4,79705).
+char(1,79706).
+char(7,79707).
+char(m,79708).
+char(o,79709).
+char(p,79710).
+char(o,79711).
+char(p,79712).
+char(1,79713).
+char(0,79714).
+char(0,79715).
+char(9,79716).
+char(p,79717).
+char(o,79718).
+char(m,79719).
+char(8,79720).
+char(1,79721).
+char(5,79722).
+char(3,79723).
+char(m,79724).
+char(o,79725).
+char(m,79726).
+char(4,79727).
+char(5,79728).
+char(7,79729).
+char(7,79730).
+char(m,79731).
+char(o,79732).
+char(p,79733).
+char(o,79734).
+char(m,79735).
+char(o,79736).
+char(p,79737).
+char(o,79738).
+char(m,79739).
+char(o,79740).
+char(o,79741).
+char(3,79742).
+char(6,79743).
+char(5,79744).
+char(3,79745).
+char(c,79746).
+char(c,79747).
+char(c,79748).
+char(m,79749).
+char(o,79750).
+char(p,79751).
+char(o,79752).
+char(2,79753).
+char(2,79754).
+char(3,79755).
+char(1,79756).
+char(c,79757).
+char(m,79758).
+char(o,79759).
+char(m,79760).
+char(o,79761).
+char(1,79762).
+char(5,79763).
+char(8,79764).
+char(7,79765).
+char(c,79766).
+char(c,79767).
+char(p,79768).
+char(9,79769).
+char(1,79770).
+char(5,79771).
+char(c,79772).
+char(c,79773).
+char(m,79774).
+char(3,79775).
+char(7,79776).
+char(0,79777).
+char(5,79778).
+char(c,79779).
+char(c,79780).
+char(m,79781).
+char(o,79782).
+char(o,79783).
+char(m,79784).
+char(9,79785).
+char(4,79786).
+char(1,79787).
+char(7,79788).
+char(c,79789).
+char(c,79790).
+char(c,79791).
+char(c,79792).
+char(c,79793).
+char(c,79794).
+char(c,79795).
+char(c,79796).
+char(c,79797).
+char(c,79798).
+char(m,79799).
+char(o,79800).
+char(o,79801).
+char(m,79802).
+char(8,79803).
+char(5,79804).
+char(4,79805).
+char(3,79806).
+char(c,79807).
+char(c,79808).
+char(c,79809).
+char(p,79810).
+char(2,79811).
+char(8,79812).
+char(5,79813).
+char(6,79814).
+char(p,79815).
+char(4,79816).
+char(2,79817).
+char(3,79818).
+char(c,79819).
+char(c,79820).
+char(c,79821).
+char(c,79822).
+char(m,79823).
+char(1,79824).
+char(9,79825).
+char(4,79826).
+char(0,79827).
+char(c,79828).
+char(m,79829).
+char(o,79830).
+char(3,79831).
+char(7,79832).
+char(8,79833).
+char(2,79834).
+char(m,79835).
+char(o,79836).
+char(m,79837).
+char(6,79838).
+char(2,79839).
+char(8,79840).
+char(5,79841).
+char(p,79842).
+char(o,79843).
+char(m,79844).
+char(9,79845).
+char(1,79846).
+char(3,79847).
+char(5,79848).
+char(c,79849).
+char(p,79850).
+char(8,79851).
+char(2,79852).
+char(7,79853).
+char(7,79854).
+char(p,79855).
+char(o,79856).
+char(1,79857).
+char(2,79858).
+char(1,79859).
+char(4,79860).
+char(c,79861).
+char(c,79862).
+char(m,79863).
+char(1,79864).
+char(0,79865).
+char(1,79866).
+char(0,79867).
+char(p,79868).
+char(o,79869).
+char(5,79870).
+char(0,79871).
+char(7,79872).
+char(6,79873).
+char(p,79874).
+char(5,79875).
+char(3,79876).
+char(6,79877).
+char(0,79878).
+char(c,79879).
+char(p,79880).
+char(7,79881).
+char(0,79882).
+char(0,79883).
+char(9,79884).
+char(p,79885).
+char(1,79886).
+char(1,79887).
+char(8,79888).
+char(0,79889).
+char(p,79890).
+char(5,79891).
+char(5,79892).
+char(9,79893).
+char(4,79894).
+char(m,79895).
+char(o,79896).
+char(p,79897).
+char(o,79898).
+char(m,79899).
+char(o,79900).
+char(m,79901).
+char(5,79902).
+char(1,79903).
+char(5,79904).
+char(4,79905).
+char(c,79906).
+char(c,79907).
+char(m,79908).
+char(o,79909).
+char(o,79910).
+char(p,79911).
+char(7,79912).
+char(0,79913).
+char(6,79914).
+char(0,79915).
+char(p,79916).
+char(7,79917).
+char(6,79918).
+char(6,79919).
+char(6,79920).
+char(c,79921).
+char(c,79922).
+char(m,79923).
+char(o,79924).
+char(p,79925).
+char(o,79926).
+char(m,79927).
+char(8,79928).
+char(8,79929).
+char(3,79930).
+char(2,79931).
+char(c,79932).
+char(p,79933).
+char(7,79934).
+char(0,79935).
+char(0,79936).
+char(2,79937).
+char(m,79938).
+char(6,79939).
+char(8,79940).
+char(0,79941).
+char(4,79942).
+char(c,79943).
+char(c,79944).
+char(p,79945).
+char(o,79946).
+char(p,79947).
+char(3,79948).
+char(7,79949).
+char(2,79950).
+char(1,79951).
+char(c,79952).
+char(m,79953).
+char(o,79954).
+char(p,79955).
+char(6,79956).
+char(6,79957).
+char(8,79958).
+char(c,79959).
+char(c,79960).
+char(c,79961).
+char(c,79962).
+char(p,79963).
+char(o,79964).
+char(m,79965).
+char(o,79966).
+char(o,79967).
+char(m,79968).
+char(o,79969).
+char(m,79970).
+char(o,79971).
+char(p,79972).
+char(o,79973).
+char(m,79974).
+char(8,79975).
+char(8,79976).
+char(4,79977).
+char(m,79978).
+char(7,79979).
+char(3,79980).
+char(1,79981).
+char(7,79982).
+char(p,79983).
+char(8,79984).
+char(7,79985).
+char(7,79986).
+char(2,79987).
+char(m,79988).
+char(o,79989).
+char(3,79990).
+char(8,79991).
+char(4,79992).
+char(5,79993).
+char(c,79994).
+char(p,79995).
+char(o,79996).
+char(p,79997).
+char(o,79998).
+char(9,79999).
+char(4,80000).
+char(8,80001).
+char(0,80002).
+char(m,80003).
+char(o,80004).
+char(m,80005).
+char(o,80006).
+char(8,80007).
+char(8,80008).
+char(9,80009).
+char(0,80010).
+char(c,80011).
+char(c,80012).
+char(m,80013).
+char(9,80014).
+char(9,80015).
+char(3,80016).
+char(4,80017).
+char(c,80018).
+char(c,80019).
+char(c,80020).
+char(c,80021).
+char(c,80022).
+char(p,80023).
+char(o,80024).
+char(p,80025).
+char(4,80026).
+char(9,80027).
+char(0,80028).
+char(4,80029).
+char(c,80030).
+char(c,80031).
+char(c,80032).
+char(m,80033).
+char(o,80034).
+char(m,80035).
+char(6,80036).
+char(7,80037).
+char(5,80038).
+char(3,80039).
+char(c,80040).
+char(c,80041).
+char(m,80042).
+char(o,80043).
+char(p,80044).
+char(o,80045).
+char(7,80046).
+char(2,80047).
+char(1,80048).
+char(6,80049).
+char(c,80050).
+char(m,80051).
+char(o,80052).
+char(m,80053).
+char(o,80054).
+char(m,80055).
+char(o,80056).
+char(o,80057).
+char(m,80058).
+char(o,80059).
+char(m,80060).
+char(9,80061).
+char(2,80062).
+char(2,80063).
+char(4,80064).
+char(m,80065).
+char(o,80066).
+char(m,80067).
+char(o,80068).
+char(o,80069).
+char(o,80070).
+char(m,80071).
+char(o,80072).
+char(p,80073).
+char(7,80074).
+char(9,80075).
+char(5,80076).
+char(p,80077).
+char(4,80078).
+char(1,80079).
+char(5,80080).
+char(0,80081).
+char(c,80082).
+char(c,80083).
+char(p,80084).
+char(3,80085).
+char(0,80086).
+char(7,80087).
+char(1,80088).
+char(c,80089).
+char(m,80090).
+char(6,80091).
+char(3,80092).
+char(6,80093).
+char(1,80094).
+char(c,80095).
+char(c,80096).
+char(c,80097).
+char(m,80098).
+char(8,80099).
+char(0,80100).
+char(0,80101).
+char(6,80102).
+char(p,80103).
+char(o,80104).
+char(p,80105).
+char(o,80106).
+char(o,80107).
+char(p,80108).
+char(9,80109).
+char(2,80110).
+char(7,80111).
+char(0,80112).
+char(c,80113).
+char(c,80114).
+char(c,80115).
+char(c,80116).
+char(c,80117).
+char(m,80118).
+char(o,80119).
+char(5,80120).
+char(6,80121).
+char(3,80122).
+char(3,80123).
+char(c,80124).
+char(m,80125).
+char(3,80126).
+char(3,80127).
+char(1,80128).
+char(4,80129).
+char(c,80130).
+char(p,80131).
+char(o,80132).
+char(p,80133).
+char(o,80134).
+char(m,80135).
+char(8,80136).
+char(1,80137).
+char(p,80138).
+char(7,80139).
+char(4,80140).
+char(8,80141).
+char(4,80142).
+char(c,80143).
+char(p,80144).
+char(5,80145).
+char(6,80146).
+char(0,80147).
+char(2,80148).
+char(p,80149).
+char(o,80150).
+char(9,80151).
+char(2,80152).
+char(2,80153).
+char(7,80154).
+char(c,80155).
+char(m,80156).
+char(7,80157).
+char(9,80158).
+char(4,80159).
+char(9,80160).
+char(p,80161).
+char(1,80162).
+char(8,80163).
+char(2,80164).
+char(0,80165).
+char(p,80166).
+char(o,80167).
+char(m,80168).
+char(3,80169).
+char(4,80170).
+char(8,80171).
+char(6,80172).
+char(m,80173).
+char(o,80174).
+char(2,80175).
+char(9,80176).
+char(5,80177).
+char(8,80178).
+char(c,80179).
+char(p,80180).
+char(o,80181).
+char(p,80182).
+char(7,80183).
+char(5,80184).
+char(5,80185).
+char(9,80186).
+char(p,80187).
+char(8,80188).
+char(0,80189).
+char(8,80190).
+char(1,80191).
+char(p,80192).
+char(o,80193).
+char(p,80194).
+char(2,80195).
+char(6,80196).
+char(3,80197).
+char(6,80198).
+char(c,80199).
+char(m,80200).
+char(o,80201).
+char(5,80202).
+char(2,80203).
+char(6,80204).
+char(1,80205).
+char(c,80206).
+char(m,80207).
+char(o,80208).
+char(3,80209).
+char(3,80210).
+char(2,80211).
+char(5,80212).
+char(c,80213).
+char(m,80214).
+char(o,80215).
+char(5,80216).
+char(5,80217).
+char(6,80218).
+char(2,80219).
+char(c,80220).
+char(c,80221).
+char(c,80222).
+char(m,80223).
+char(o,80224).
+char(m,80225).
+char(o,80226).
+char(o,80227).
+char(3,80228).
+char(4,80229).
+char(3,80230).
+char(5,80231).
+char(p,80232).
+char(o,80233).
+char(p,80234).
+char(o,80235).
+char(m,80236).
+char(o,80237).
+char(o,80238).
+char(8,80239).
+char(3,80240).
+char(1,80241).
+char(4,80242).
+char(p,80243).
+char(o,80244).
+char(p,80245).
+char(6,80246).
+char(0,80247).
+char(9,80248).
+char(2,80249).
+char(c,80250).
+char(p,80251).
+char(7,80252).
+char(7,80253).
+char(9,80254).
+char(4,80255).
+char(m,80256).
+char(o,80257).
+char(9,80258).
+char(2,80259).
+char(8,80260).
+char(5,80261).
+char(c,80262).
+char(m,80263).
+char(1,80264).
+char(5,80265).
+char(8,80266).
+char(c,80267).
+char(p,80268).
+char(3,80269).
+char(3,80270).
+char(9,80271).
+char(8,80272).
+char(c,80273).
+char(c,80274).
+char(c,80275).
+char(m,80276).
+char(4,80277).
+char(9,80278).
+char(2,80279).
+char(6,80280).
+char(m,80281).
+char(o,80282).
+char(m,80283).
+char(o,80284).
+char(m,80285).
+char(o,80286).
+char(m,80287).
+char(o,80288).
+char(p,80289).
+char(o,80290).
+char(m,80291).
+char(2,80292).
+char(1,80293).
+char(0,80294).
+char(6,80295).
+char(c,80296).
+char(c,80297).
+char(m,80298).
+char(o,80299).
+char(m,80300).
+char(3,80301).
+char(9,80302).
+char(9,80303).
+char(1,80304).
+char(c,80305).
+char(c,80306).
+char(m,80307).
+char(7,80308).
+char(2,80309).
+char(0,80310).
+char(6,80311).
+char(c,80312).
+char(c,80313).
+char(p,80314).
+char(8,80315).
+char(5,80316).
+char(1,80317).
+char(1,80318).
+char(c,80319).
+char(c,80320).
+char(c,80321).
+char(c,80322).
+char(c,80323).
+char(c,80324).
+char(p,80325).
+char(4,80326).
+char(8,80327).
+char(7,80328).
+char(4,80329).
+char(c,80330).
+char(m,80331).
+char(o,80332).
+char(m,80333).
+char(1,80334).
+char(9,80335).
+char(3,80336).
+char(2,80337).
+char(c,80338).
+char(c,80339).
+char(p,80340).
+char(o,80341).
+char(p,80342).
+char(o,80343).
+char(5,80344).
+char(4,80345).
+char(5,80346).
+char(7,80347).
+char(c,80348).
+char(c,80349).
+char(c,80350).
+char(p,80351).
+char(o,80352).
+char(p,80353).
+char(1,80354).
+char(2,80355).
+char(0,80356).
+char(5,80357).
+char(p,80358).
+char(o,80359).
+char(p,80360).
+char(o,80361).
+char(m,80362).
+char(6,80363).
+char(8,80364).
+char(8,80365).
+char(1,80366).
+char(c,80367).
+char(c,80368).
+char(p,80369).
+char(3,80370).
+char(3,80371).
+char(6,80372).
+char(5,80373).
+char(c,80374).
+char(m,80375).
+char(o,80376).
+char(p,80377).
+char(o,80378).
+char(m,80379).
+char(1,80380).
+char(5,80381).
+char(4,80382).
+char(3,80383).
+char(c,80384).
+char(p,80385).
+char(2,80386).
+char(5,80387).
+char(9,80388).
+char(8,80389).
+char(c,80390).
+char(p,80391).
+char(o,80392).
+char(6,80393).
+char(5,80394).
+char(7,80395).
+char(4,80396).
+char(c,80397).
+char(c,80398).
+char(c,80399).
+char(c,80400).
+char(c,80401).
+char(c,80402).
+char(c,80403).
+char(m,80404).
+char(o,80405).
+char(p,80406).
+char(o,80407).
+char(m,80408).
+char(o,80409).
+char(o,80410).
+char(p,80411).
+char(o,80412).
+char(m,80413).
+char(6,80414).
+char(9,80415).
+char(7,80416).
+char(7,80417).
+char(p,80418).
+char(4,80419).
+char(7,80420).
+char(0,80421).
+char(c,80422).
+char(c,80423).
+char(m,80424).
+char(2,80425).
+char(1,80426).
+char(3,80427).
+char(c,80428).
+char(p,80429).
+char(o,80430).
+char(4,80431).
+char(0,80432).
+char(6,80433).
+char(8,80434).
+char(m,80435).
+char(4,80436).
+char(8,80437).
+char(0,80438).
+char(9,80439).
+char(c,80440).
+char(m,80441).
+char(o,80442).
+char(m,80443).
+char(o,80444).
+char(p,80445).
+char(o,80446).
+char(m,80447).
+char(o,80448).
+char(m,80449).
+char(o,80450).
+char(m,80451).
+char(7,80452).
+char(8,80453).
+char(7,80454).
+char(2,80455).
+char(c,80456).
+char(p,80457).
+char(6,80458).
+char(0,80459).
+char(8,80460).
+char(2,80461).
+char(p,80462).
+char(o,80463).
+char(p,80464).
+char(o,80465).
+char(1,80466).
+char(9,80467).
+char(2,80468).
+char(4,80469).
+char(c,80470).
+char(m,80471).
+char(o,80472).
+char(m,80473).
+char(5,80474).
+char(0,80475).
+char(4,80476).
+char(7,80477).
+char(c,80478).
+char(p,80479).
+char(3,80480).
+char(9,80481).
+char(2,80482).
+char(5,80483).
+char(m,80484).
+char(2,80485).
+char(4,80486).
+char(3,80487).
+char(3,80488).
+char(p,80489).
+char(8,80490).
+char(6,80491).
+char(1,80492).
+char(9,80493).
+char(p,80494).
+char(o,80495).
+char(m,80496).
+char(5,80497).
+char(7,80498).
+char(6,80499).
+char(5,80500).
+char(m,80501).
+char(o,80502).
+char(m,80503).
+char(4,80504).
+char(9,80505).
+char(1,80506).
+char(5,80507).
+char(c,80508).
+char(m,80509).
+char(o,80510).
+char(7,80511).
+char(5,80512).
+char(5,80513).
+char(5,80514).
+char(m,80515).
+char(2,80516).
+char(4,80517).
+char(8,80518).
+char(2,80519).
+char(p,80520).
+char(o,80521).
+char(p,80522).
+char(5,80523).
+char(9,80524).
+char(9,80525).
+char(0,80526).
+char(m,80527).
+char(4,80528).
+char(5,80529).
+char(2,80530).
+char(1,80531).
+char(c,80532).
+char(p,80533).
+char(o,80534).
+char(m,80535).
+char(7,80536).
+char(1,80537).
+char(5,80538).
+char(6,80539).
+char(m,80540).
+char(o,80541).
+char(p,80542).
+char(2,80543).
+char(4,80544).
+char(8,80545).
+char(8,80546).
+char(m,80547).
+char(9,80548).
+char(5,80549).
+char(6,80550).
+char(m,80551).
+char(4,80552).
+char(8,80553).
+char(7,80554).
+char(4,80555).
+char(p,80556).
+char(2,80557).
+char(0,80558).
+char(7,80559).
+char(0,80560).
+char(c,80561).
+char(c,80562).
+char(c,80563).
+char(c,80564).
+char(p,80565).
+char(o,80566).
+char(m,80567).
+char(o,80568).
+char(2,80569).
+char(1,80570).
+char(2,80571).
+char(4,80572).
+char(c,80573).
+char(c,80574).
+char(p,80575).
+char(8,80576).
+char(9,80577).
+char(2,80578).
+char(2,80579).
+char(c,80580).
+char(c,80581).
+char(c,80582).
+char(m,80583).
+char(o,80584).
+char(p,80585).
+char(2,80586).
+char(3,80587).
+char(5,80588).
+char(3,80589).
+char(p,80590).
+char(o,80591).
+char(6,80592).
+char(8,80593).
+char(0,80594).
+char(c,80595).
+char(c,80596).
+char(c,80597).
+char(p,80598).
+char(6,80599).
+char(3,80600).
+char(5,80601).
+char(c,80602).
+char(c,80603).
+char(m,80604).
+char(o,80605).
+char(p,80606).
+char(o,80607).
+char(p,80608).
+char(5,80609).
+char(6,80610).
+char(3,80611).
+char(0,80612).
+char(m,80613).
+char(o,80614).
+char(p,80615).
+char(5,80616).
+char(8,80617).
+char(8,80618).
+char(1,80619).
+char(c,80620).
+char(c,80621).
+char(m,80622).
+char(o,80623).
+char(p,80624).
+char(o,80625).
+char(o,80626).
+char(m,80627).
+char(o,80628).
+char(p,80629).
+char(4,80630).
+char(7,80631).
+char(8,80632).
+char(8,80633).
+char(m,80634).
+char(5,80635).
+char(8,80636).
+char(8,80637).
+char(0,80638).
+char(c,80639).
+char(m,80640).
+char(9,80641).
+char(2,80642).
+char(6,80643).
+char(2,80644).
+char(m,80645).
+char(o,80646).
+char(p,80647).
+char(6,80648).
+char(9,80649).
+char(2,80650).
+char(0,80651).
+char(p,80652).
+char(o,80653).
+char(o,80654).
+char(p,80655).
+char(8,80656).
+char(2,80657).
+char(2,80658).
+char(7,80659).
+char(p,80660).
+char(9,80661).
+char(4,80662).
+char(2,80663).
+char(9,80664).
+char(p,80665).
+char(6,80666).
+char(1,80667).
+char(0,80668).
+char(7,80669).
+char(m,80670).
+char(2,80671).
+char(7,80672).
+char(0,80673).
+char(8,80674).
+char(p,80675).
+char(o,80676).
+char(m,80677).
+char(o,80678).
+char(p,80679).
+char(o,80680).
+char(p,80681).
+char(9,80682).
+char(9,80683).
+char(3,80684).
+char(6,80685).
+char(c,80686).
+char(p,80687).
+char(o,80688).
+char(p,80689).
+char(o,80690).
+char(o,80691).
+char(m,80692).
+char(5,80693).
+char(1,80694).
+char(6,80695).
+char(m,80696).
+char(8,80697).
+char(3,80698).
+char(8,80699).
+char(3,80700).
+char(m,80701).
+char(2,80702).
+char(9,80703).
+char(0,80704).
+char(6,80705).
+char(c,80706).
+char(p,80707).
+char(6,80708).
+char(4,80709).
+char(9,80710).
+char(3,80711).
+char(m,80712).
+char(o,80713).
+char(m,80714).
+char(o,80715).
+char(p,80716).
+char(9,80717).
+char(3,80718).
+char(9,80719).
+char(2,80720).
+char(p,80721).
+char(2,80722).
+char(8,80723).
+char(5,80724).
+char(7,80725).
+char(m,80726).
+char(o,80727).
+char(p,80728).
+char(4,80729).
+char(7,80730).
+char(7,80731).
+char(0,80732).
+char(c,80733).
+char(c,80734).
+char(c,80735).
+char(c,80736).
+char(c,80737).
+char(m,80738).
+char(o,80739).
+char(p,80740).
+char(o,80741).
+char(p,80742).
+char(6,80743).
+char(3,80744).
+char(8,80745).
+char(3,80746).
+char(c,80747).
+char(m,80748).
+char(4,80749).
+char(7,80750).
+char(2,80751).
+char(4,80752).
+char(p,80753).
+char(o,80754).
+char(o,80755).
+char(4,80756).
+char(9,80757).
+char(4,80758).
+char(8,80759).
+char(c,80760).
+char(m,80761).
+char(o,80762).
+char(m,80763).
+char(2,80764).
+char(5,80765).
+char(8,80766).
+char(2,80767).
+char(p,80768).
+char(4,80769).
+char(1,80770).
+char(0,80771).
+char(1,80772).
+char(c,80773).
+char(m,80774).
+char(7,80775).
+char(7,80776).
+char(6,80777).
+char(0,80778).
+char(m,80779).
+char(9,80780).
+char(7,80781).
+char(1,80782).
+char(6,80783).
+char(p,80784).
+char(o,80785).
+char(p,80786).
+char(7,80787).
+char(8,80788).
+char(3,80789).
+char(3,80790).
+char(c,80791).
+char(m,80792).
+char(5,80793).
+char(3,80794).
+char(4,80795).
+char(1,80796).
+char(c,80797).
+char(m,80798).
+char(8,80799).
+char(5,80800).
+char(1,80801).
+char(9,80802).
+char(c,80803).
+char(p,80804).
+char(o,80805).
+char(p,80806).
+char(1,80807).
+char(6,80808).
+char(3,80809).
+char(2,80810).
+char(c,80811).
+char(c,80812).
+char(c,80813).
+char(p,80814).
+char(o,80815).
+char(9,80816).
+char(3,80817).
+char(5,80818).
+char(1,80819).
+char(m,80820).
+char(o,80821).
+char(o,80822).
+char(p,80823).
+char(o,80824).
+char(9,80825).
+char(0,80826).
+char(8,80827).
+char(3,80828).
+char(m,80829).
+char(o,80830).
+char(m,80831).
+char(o,80832).
+char(o,80833).
+char(m,80834).
+char(o,80835).
+char(p,80836).
+char(9,80837).
+char(9,80838).
+char(9,80839).
+char(4,80840).
+char(c,80841).
+char(p,80842).
+char(1,80843).
+char(5,80844).
+char(4,80845).
+char(3,80846).
+char(m,80847).
+char(2,80848).
+char(3,80849).
+char(5,80850).
+char(1,80851).
+char(p,80852).
+char(o,80853).
+char(o,80854).
+char(p,80855).
+char(o,80856).
+char(p,80857).
+char(o,80858).
+char(p,80859).
+char(o,80860).
+char(m,80861).
+char(3,80862).
+char(2,80863).
+char(2,80864).
+char(8,80865).
+char(m,80866).
+char(4,80867).
+char(2,80868).
+char(5,80869).
+char(m,80870).
+char(2,80871).
+char(0,80872).
+char(2,80873).
+char(0,80874).
+char(m,80875).
+char(o,80876).
+char(m,80877).
+char(o,80878).
+char(m,80879).
+char(o,80880).
+char(m,80881).
+char(o,80882).
+char(7,80883).
+char(7,80884).
+char(0,80885).
+char(7,80886).
+char(p,80887).
+char(o,80888).
+char(m,80889).
+char(o,80890).
+char(o,80891).
+char(o,80892).
+char(p,80893).
+char(1,80894).
+char(0,80895).
+char(6,80896).
+char(2,80897).
+char(m,80898).
+char(3,80899).
+char(6,80900).
+char(4,80901).
+char(8,80902).
+char(p,80903).
+char(1,80904).
+char(1,80905).
+char(9,80906).
+char(p,80907).
+char(o,80908).
+char(1,80909).
+char(5,80910).
+char(4,80911).
+char(8,80912).
+char(m,80913).
+char(o,80914).
+char(o,80915).
+char(o,80916).
+char(p,80917).
+char(o,80918).
+char(o,80919).
+char(p,80920).
+char(o,80921).
+char(m,80922).
+char(2,80923).
+char(9,80924).
+char(5,80925).
+char(4,80926).
+char(c,80927).
+char(c,80928).
+char(c,80929).
+char(m,80930).
+char(o,80931).
+char(m,80932).
+char(o,80933).
+char(m,80934).
+char(o,80935).
+char(m,80936).
+char(7,80937).
+char(2,80938).
+char(9,80939).
+char(4,80940).
+char(c,80941).
+char(c,80942).
+char(c,80943).
+char(c,80944).
+char(p,80945).
+char(o,80946).
+char(p,80947).
+char(7,80948).
+char(4,80949).
+char(6,80950).
+char(7,80951).
+char(m,80952).
+char(6,80953).
+char(5,80954).
+char(2,80955).
+char(1,80956).
+char(p,80957).
+char(4,80958).
+char(1,80959).
+char(6,80960).
+char(4,80961).
+char(c,80962).
+char(m,80963).
+char(1,80964).
+char(5,80965).
+char(4,80966).
+char(0,80967).
+char(m,80968).
+char(1,80969).
+char(2,80970).
+char(6,80971).
+char(1,80972).
+char(c,80973).
+char(p,80974).
+char(2,80975).
+char(4,80976).
+char(8,80977).
+char(9,80978).
+char(c,80979).
+char(c,80980).
+char(p,80981).
+char(3,80982).
+char(8,80983).
+char(2,80984).
+char(7,80985).
+char(p,80986).
+char(o,80987).
+char(m,80988).
+char(3,80989).
+char(0,80990).
+char(1,80991).
+char(m,80992).
+char(9,80993).
+char(7,80994).
+char(0,80995).
+char(2,80996).
+char(c,80997).
+char(c,80998).
+char(p,80999).
+char(o,81000).
+char(6,81001).
+char(3,81002).
+char(7,81003).
+char(5,81004).
+char(m,81005).
+char(o,81006).
+char(m,81007).
+char(6,81008).
+char(8,81009).
+char(4,81010).
+char(4,81011).
+char(m,81012).
+char(3,81013).
+char(0,81014).
+char(5,81015).
+char(5,81016).
+char(p,81017).
+char(7,81018).
+char(7,81019).
+char(8,81020).
+char(4,81021).
+char(c,81022).
+char(c,81023).
+char(c,81024).
+char(m,81025).
+char(7,81026).
+char(3,81027).
+char(3,81028).
+char(p,81029).
+char(o,81030).
+char(m,81031).
+char(o,81032).
+char(p,81033).
+char(5,81034).
+char(8,81035).
+char(2,81036).
+char(c,81037).
+char(m,81038).
+char(3,81039).
+char(0,81040).
+char(7,81041).
+char(3,81042).
+char(p,81043).
+char(o,81044).
+char(o,81045).
+char(m,81046).
+char(9,81047).
+char(1,81048).
+char(9,81049).
+char(0,81050).
+char(c,81051).
+char(c,81052).
+char(c,81053).
+char(c,81054).
+char(p,81055).
+char(o,81056).
+char(p,81057).
+char(o,81058).
+char(p,81059).
+char(1,81060).
+char(8,81061).
+char(6,81062).
+char(1,81063).
+char(c,81064).
+char(p,81065).
+char(o,81066).
+char(m,81067).
+char(5,81068).
+char(6,81069).
+char(7,81070).
+char(c,81071).
+char(c,81072).
+char(p,81073).
+char(o,81074).
+char(m,81075).
+char(o,81076).
+char(m,81077).
+char(9,81078).
+char(6,81079).
+char(7,81080).
+char(3,81081).
+char(c,81082).
+char(m,81083).
+char(9,81084).
+char(3,81085).
+char(5,81086).
+char(4,81087).
+char(c,81088).
+char(c,81089).
+char(p,81090).
+char(8,81091).
+char(3,81092).
+char(8,81093).
+char(0,81094).
+char(p,81095).
+char(5,81096).
+char(5,81097).
+char(6,81098).
+char(7,81099).
+char(m,81100).
+char(o,81101).
+char(o,81102).
+char(5,81103).
+char(7,81104).
+char(9,81105).
+char(3,81106).
+char(p,81107).
+char(9,81108).
+char(4,81109).
+char(9,81110).
+char(3,81111).
+char(m,81112).
+char(9,81113).
+char(9,81114).
+char(3,81115).
+char(4,81116).
+char(c,81117).
+char(c,81118).
+char(c,81119).
+char(p,81120).
+char(o,81121).
+char(8,81122).
+char(9,81123).
+char(9,81124).
+char(6,81125).
+char(c,81126).
+char(c,81127).
+char(c,81128).
+char(p,81129).
+char(6,81130).
+char(6,81131).
+char(6,81132).
+char(0,81133).
+char(c,81134).
+char(c,81135).
+char(m,81136).
+char(o,81137).
+char(m,81138).
+char(3,81139).
+char(8,81140).
+char(7,81141).
+char(3,81142).
+char(c,81143).
+char(c,81144).
+char(p,81145).
+char(3,81146).
+char(0,81147).
+char(9,81148).
+char(1,81149).
+char(c,81150).
+char(c,81151).
+char(c,81152).
+char(p,81153).
+char(7,81154).
+char(7,81155).
+char(8,81156).
+char(3,81157).
+char(m,81158).
+char(9,81159).
+char(2,81160).
+char(5,81161).
+char(1,81162).
+char(c,81163).
+char(c,81164).
+char(c,81165).
+char(m,81166).
+char(7,81167).
+char(4,81168).
+char(5,81169).
+char(8,81170).
+char(c,81171).
+char(c,81172).
+char(m,81173).
+char(3,81174).
+char(1,81175).
+char(9,81176).
+char(1,81177).
+char(c,81178).
+char(m,81179).
+char(o,81180).
+char(m,81181).
+char(o,81182).
+char(o,81183).
+char(p,81184).
+char(5,81185).
+char(7,81186).
+char(8,81187).
+char(m,81188).
+char(9,81189).
+char(1,81190).
+char(5,81191).
+char(8,81192).
+char(c,81193).
+char(p,81194).
+char(o,81195).
+char(m,81196).
+char(8,81197).
+char(5,81198).
+char(2,81199).
+char(c,81200).
+char(m,81201).
+char(9,81202).
+char(0,81203).
+char(7,81204).
+char(4,81205).
+char(m,81206).
+char(o,81207).
+char(m,81208).
+char(7,81209).
+char(3,81210).
+char(4,81211).
+char(p,81212).
+char(o,81213).
+char(6,81214).
+char(7,81215).
+char(0,81216).
+char(2,81217).
+char(p,81218).
+char(8,81219).
+char(3,81220).
+char(3,81221).
+char(8,81222).
+char(p,81223).
+char(o,81224).
+char(p,81225).
+char(o,81226).
+char(o,81227).
+char(p,81228).
+char(2,81229).
+char(3,81230).
+char(7,81231).
+char(8,81232).
+char(m,81233).
+char(1,81234).
+char(1,81235).
+char(8,81236).
+char(2,81237).
+char(c,81238).
+char(c,81239).
+char(m,81240).
+char(o,81241).
+char(9,81242).
+char(1,81243).
+char(0,81244).
+char(9,81245).
+char(c,81246).
+char(p,81247).
+char(o,81248).
+char(p,81249).
+char(2,81250).
+char(5,81251).
+char(4,81252).
+char(c,81253).
+char(c,81254).
+char(m,81255).
+char(o,81256).
+char(m,81257).
+char(4,81258).
+char(0,81259).
+char(8,81260).
+char(0,81261).
+char(c,81262).
+char(c,81263).
+char(p,81264).
+char(o,81265).
+char(p,81266).
+char(3,81267).
+char(2,81268).
+char(3,81269).
+char(p,81270).
+char(o,81271).
+char(m,81272).
+char(o,81273).
+char(o,81274).
+char(p,81275).
+char(3,81276).
+char(5,81277).
+char(3,81278).
+char(c,81279).
+char(c,81280).
+char(c,81281).
+char(c,81282).
+char(m,81283).
+char(o,81284).
+char(o,81285).
+char(7,81286).
+char(0,81287).
+char(1,81288).
+char(8,81289).
+char(c,81290).
+char(c,81291).
+char(c,81292).
+char(p,81293).
+char(3,81294).
+char(5,81295).
+char(8,81296).
+char(0,81297).
+char(m,81298).
+char(7,81299).
+char(0,81300).
+char(8,81301).
+char(7,81302).
+char(c,81303).
+char(m,81304).
+char(6,81305).
+char(7,81306).
+char(0,81307).
+char(1,81308).
+char(p,81309).
+char(4,81310).
+char(4,81311).
+char(9,81312).
+char(5,81313).
+char(c,81314).
+char(p,81315).
+char(o,81316).
+char(p,81317).
+char(6,81318).
+char(3,81319).
+char(2,81320).
+char(5,81321).
+char(c,81322).
+char(p,81323).
+char(5,81324).
+char(2,81325).
+char(7,81326).
+char(5,81327).
+char(m,81328).
+char(5,81329).
+char(2,81330).
+char(9,81331).
+char(0,81332).
+char(p,81333).
+char(4,81334).
+char(1,81335).
+char(5,81336).
+char(1,81337).
+char(c,81338).
+char(c,81339).
+char(p,81340).
+char(o,81341).
+char(o,81342).
+char(p,81343).
+char(6,81344).
+char(0,81345).
+char(1,81346).
+char(1,81347).
+char(m,81348).
+char(4,81349).
+char(0,81350).
+char(6,81351).
+char(0,81352).
+char(m,81353).
+char(o,81354).
+char(p,81355).
+char(o,81356).
+char(o,81357).
+char(m,81358).
+char(6,81359).
+char(8,81360).
+char(1,81361).
+char(7,81362).
+char(c,81363).
+char(m,81364).
+char(o,81365).
+char(m,81366).
+char(o,81367).
+char(m,81368).
+char(o,81369).
+char(4,81370).
+char(2,81371).
+char(2,81372).
+char(5,81373).
+char(m,81374).
+char(o,81375).
+char(m,81376).
+char(3,81377).
+char(1,81378).
+char(3,81379).
+char(2,81380).
+char(c,81381).
+char(p,81382).
+char(o,81383).
+char(7,81384).
+char(6,81385).
+char(3,81386).
+char(5,81387).
+char(c,81388).
+char(c,81389).
+char(p,81390).
+char(o,81391).
+char(m,81392).
+char(o,81393).
+char(5,81394).
+char(3,81395).
+char(8,81396).
+char(2,81397).
+char(m,81398).
+char(o,81399).
+char(1,81400).
+char(7,81401).
+char(9,81402).
+char(6,81403).
+char(c,81404).
+char(m,81405).
+char(o,81406).
+char(p,81407).
+char(o,81408).
+char(p,81409).
+char(o,81410).
+char(o,81411).
+char(m,81412).
+char(8,81413).
+char(3,81414).
+char(9,81415).
+char(8,81416).
+char(c,81417).
+char(c,81418).
+char(m,81419).
+char(o,81420).
+char(m,81421).
+char(o,81422).
+char(m,81423).
+char(1,81424).
+char(7,81425).
+char(5,81426).
+char(3,81427).
+char(m,81428).
+char(9,81429).
+char(8,81430).
+char(1,81431).
+char(7,81432).
+char(c,81433).
+char(c,81434).
+char(m,81435).
+char(o,81436).
+char(m,81437).
+char(o,81438).
+char(o,81439).
+char(p,81440).
+char(6,81441).
+char(8,81442).
+char(1,81443).
+char(3,81444).
+char(p,81445).
+char(7,81446).
+char(3,81447).
+char(8,81448).
+char(9,81449).
+char(c,81450).
+char(m,81451).
+char(4,81452).
+char(1,81453).
+char(8,81454).
+char(4,81455).
+char(c,81456).
+char(p,81457).
+char(1,81458).
+char(4,81459).
+char(2,81460).
+char(1,81461).
+char(c,81462).
+char(m,81463).
+char(7,81464).
+char(1,81465).
+char(0,81466).
+char(2,81467).
+char(p,81468).
+char(o,81469).
+char(o,81470).
+char(p,81471).
+char(o,81472).
+char(p,81473).
+char(1,81474).
+char(9,81475).
+char(5,81476).
+char(c,81477).
+char(p,81478).
+char(1,81479).
+char(2,81480).
+char(8,81481).
+char(3,81482).
+char(m,81483).
+char(o,81484).
+char(m,81485).
+char(4,81486).
+char(2,81487).
+char(8,81488).
+char(4,81489).
+char(c,81490).
+char(m,81491).
+char(o,81492).
+char(p,81493).
+char(o,81494).
+char(m,81495).
+char(o,81496).
+char(p,81497).
+char(9,81498).
+char(1,81499).
+char(3,81500).
+char(5,81501).
+char(c,81502).
+char(m,81503).
+char(o,81504).
+char(p,81505).
+char(2,81506).
+char(8,81507).
+char(0,81508).
+char(c,81509).
+char(c,81510).
+char(c,81511).
+char(p,81512).
+char(o,81513).
+char(5,81514).
+char(3,81515).
+char(4,81516).
+char(8,81517).
+char(p,81518).
+char(4,81519).
+char(6,81520).
+char(0,81521).
+char(c,81522).
+char(m,81523).
+char(o,81524).
+char(2,81525).
+char(9,81526).
+char(5,81527).
+char(5,81528).
+char(m,81529).
+char(o,81530).
+char(o,81531).
+char(p,81532).
+char(8,81533).
+char(0,81534).
+char(5,81535).
+char(2,81536).
+char(p,81537).
+char(o,81538).
+char(m,81539).
+char(1,81540).
+char(2,81541).
+char(9,81542).
+char(2,81543).
+char(p,81544).
+char(2,81545).
+char(1,81546).
+char(4,81547).
+char(8,81548).
+char(c,81549).
+char(c,81550).
+char(p,81551).
+char(o,81552).
+char(2,81553).
+char(8,81554).
+char(1,81555).
+char(4,81556).
+char(m,81557).
+char(5,81558).
+char(1,81559).
+char(3,81560).
+char(8,81561).
+char(c,81562).
+char(p,81563).
+char(7,81564).
+char(0,81565).
+char(2,81566).
+char(2,81567).
+char(m,81568).
+char(6,81569).
+char(5,81570).
+char(3,81571).
+char(3,81572).
+char(m,81573).
+char(o,81574).
+char(m,81575).
+char(3,81576).
+char(8,81577).
+char(6,81578).
+char(7,81579).
+char(m,81580).
+char(8,81581).
+char(7,81582).
+char(6,81583).
+char(m,81584).
+char(5,81585).
+char(0,81586).
+char(7,81587).
+char(4,81588).
+char(c,81589).
+char(c,81590).
+char(c,81591).
+char(c,81592).
+char(c,81593).
+char(c,81594).
+char(c,81595).
+char(c,81596).
+char(m,81597).
+char(7,81598).
+char(2,81599).
+char(8,81600).
+char(0,81601).
+char(p,81602).
+char(o,81603).
+char(p,81604).
+char(5,81605).
+char(3,81606).
+char(3,81607).
+char(9,81608).
+char(p,81609).
+char(o,81610).
+char(p,81611).
+char(5,81612).
+char(0,81613).
+char(1,81614).
+char(1,81615).
+char(c,81616).
+char(c,81617).
+char(p,81618).
+char(5,81619).
+char(0,81620).
+char(3,81621).
+char(6,81622).
+char(c,81623).
+char(m,81624).
+char(1,81625).
+char(8,81626).
+char(1,81627).
+char(c,81628).
+char(p,81629).
+char(4,81630).
+char(2,81631).
+char(4,81632).
+char(2,81633).
+char(m,81634).
+char(9,81635).
+char(3,81636).
+char(1,81637).
+char(p,81638).
+char(o,81639).
+char(o,81640).
+char(5,81641).
+char(7,81642).
+char(9,81643).
+char(0,81644).
+char(c,81645).
+char(c,81646).
+char(c,81647).
+char(c,81648).
+char(c,81649).
+char(p,81650).
+char(9,81651).
+char(3,81652).
+char(9,81653).
+char(7,81654).
+char(m,81655).
+char(1,81656).
+char(9,81657).
+char(3,81658).
+char(0,81659).
+char(c,81660).
+char(c,81661).
+char(c,81662).
+char(c,81663).
+char(c,81664).
+char(c,81665).
+char(c,81666).
+char(c,81667).
+char(m,81668).
+char(6,81669).
+char(2,81670).
+char(0,81671).
+char(9,81672).
+char(p,81673).
+char(1,81674).
+char(7,81675).
+char(1,81676).
+char(6,81677).
+char(p,81678).
+char(o,81679).
+char(o,81680).
+char(m,81681).
+char(1,81682).
+char(3,81683).
+char(6,81684).
+char(0,81685).
+char(p,81686).
+char(9,81687).
+char(7,81688).
+char(4,81689).
+char(6,81690).
+char(c,81691).
+char(p,81692).
+char(o,81693).
+char(m,81694).
+char(1,81695).
+char(3,81696).
+char(4,81697).
+char(0,81698).
+char(c,81699).
+char(m,81700).
+char(7,81701).
+char(0,81702).
+char(9,81703).
+char(5,81704).
+char(c,81705).
+char(p,81706).
+char(3,81707).
+char(5,81708).
+char(1,81709).
+char(3,81710).
+char(p,81711).
+char(2,81712).
+char(3,81713).
+char(9,81714).
+char(3,81715).
+char(c,81716).
+char(p,81717).
+char(o,81718).
+char(p,81719).
+char(4,81720).
+char(2,81721).
+char(0,81722).
+char(5,81723).
+char(c,81724).
+char(c,81725).
+char(p,81726).
+char(o,81727).
+char(m,81728).
+char(5,81729).
+char(2,81730).
+char(8,81731).
+char(8,81732).
+char(m,81733).
+char(3,81734).
+char(5,81735).
+char(7,81736).
+char(c,81737).
+char(m,81738).
+char(o,81739).
+char(1,81740).
+char(4,81741).
+char(5,81742).
+char(3,81743).
+char(p,81744).
+char(o,81745).
+char(m,81746).
+char(o,81747).
+char(o,81748).
+char(m,81749).
+char(o,81750).
+char(3,81751).
+char(1,81752).
+char(4,81753).
+char(m,81754).
+char(6,81755).
+char(3,81756).
+char(8,81757).
+char(9,81758).
+char(m,81759).
+char(1,81760).
+char(4,81761).
+char(6,81762).
+char(0,81763).
+char(p,81764).
+char(9,81765).
+char(6,81766).
+char(1,81767).
+char(4,81768).
+char(c,81769).
+char(m,81770).
+char(o,81771).
+char(o,81772).
+char(m,81773).
+char(5,81774).
+char(3,81775).
+char(0,81776).
+char(5,81777).
+char(c,81778).
+char(c,81779).
+char(c,81780).
+char(c,81781).
+char(p,81782).
+char(o,81783).
+char(m,81784).
+char(o,81785).
+char(1,81786).
+char(6,81787).
+char(8,81788).
+char(5,81789).
+char(c,81790).
+char(c,81791).
+char(p,81792).
+char(o,81793).
+char(o,81794).
+char(o,81795).
+char(8,81796).
+char(4,81797).
+char(3,81798).
+char(6,81799).
+char(p,81800).
+char(1,81801).
+char(0,81802).
+char(5,81803).
+char(6,81804).
+char(c,81805).
+char(c,81806).
+char(m,81807).
+char(o,81808).
+char(6,81809).
+char(0,81810).
+char(9,81811).
+char(m,81812).
+char(o,81813).
+char(o,81814).
+char(p,81815).
+char(o,81816).
+char(m,81817).
+char(o,81818).
+char(m,81819).
+char(o,81820).
+char(m,81821).
+char(1,81822).
+char(2,81823).
+char(2,81824).
+char(5,81825).
+char(c,81826).
+char(c,81827).
+char(c,81828).
+char(m,81829).
+char(8,81830).
+char(3,81831).
+char(7,81832).
+char(9,81833).
+char(c,81834).
+char(p,81835).
+char(o,81836).
+char(m,81837).
+char(9,81838).
+char(5,81839).
+char(5,81840).
+char(9,81841).
+char(c,81842).
+char(c,81843).
+char(p,81844).
+char(o,81845).
+char(p,81846).
+char(4,81847).
+char(9,81848).
+char(0,81849).
+char(8,81850).
+char(p,81851).
+char(4,81852).
+char(1,81853).
+char(4,81854).
+char(0,81855).
+char(c,81856).
+char(p,81857).
+char(o,81858).
+char(p,81859).
+char(8,81860).
+char(7,81861).
+char(3,81862).
+char(6,81863).
+char(c,81864).
+char(p,81865).
+char(7,81866).
+char(9,81867).
+char(4,81868).
+char(9,81869).
+char(p,81870).
+char(5,81871).
+char(6,81872).
+char(1,81873).
+char(m,81874).
+char(9,81875).
+char(8,81876).
+char(5,81877).
+char(7,81878).
+char(m,81879).
+char(2,81880).
+char(2,81881).
+char(7,81882).
+char(3,81883).
+char(p,81884).
+char(o,81885).
+char(m,81886).
+char(7,81887).
+char(6,81888).
+char(3,81889).
+char(1,81890).
+char(c,81891).
+char(c,81892).
+char(c,81893).
+char(c,81894).
+char(c,81895).
+char(m,81896).
+char(o,81897).
+char(m,81898).
+char(3,81899).
+char(3,81900).
+char(2,81901).
+char(0,81902).
+char(m,81903).
+char(8,81904).
+char(2,81905).
+char(4,81906).
+char(6,81907).
+char(c,81908).
+char(c,81909).
+char(p,81910).
+char(o,81911).
+char(m,81912).
+char(o,81913).
+char(p,81914).
+char(9,81915).
+char(5,81916).
+char(7,81917).
+char(0,81918).
+char(p,81919).
+char(1,81920).
+char(7,81921).
+char(2,81922).
+char(7,81923).
+char(c,81924).
+char(m,81925).
+char(4,81926).
+char(3,81927).
+char(2,81928).
+char(2,81929).
+char(c,81930).
+char(p,81931).
+char(4,81932).
+char(9,81933).
+char(3,81934).
+char(5,81935).
+char(c,81936).
+char(c,81937).
+char(m,81938).
+char(o,81939).
+char(o,81940).
+char(4,81941).
+char(5,81942).
+char(1,81943).
+char(3,81944).
+char(m,81945).
+char(3,81946).
+char(5,81947).
+char(8,81948).
+char(c,81949).
+char(c,81950).
+char(c,81951).
+char(c,81952).
+char(p,81953).
+char(o,81954).
+char(m,81955).
+char(9,81956).
+char(9,81957).
+char(8,81958).
+char(6,81959).
+char(c,81960).
+char(c,81961).
+char(p,81962).
+char(9,81963).
+char(7,81964).
+char(0,81965).
+char(6,81966).
+char(c,81967).
+char(p,81968).
+char(o,81969).
+char(2,81970).
+char(6,81971).
+char(0,81972).
+char(5,81973).
+char(p,81974).
+char(8,81975).
+char(7,81976).
+char(8,81977).
+char(1,81978).
+char(m,81979).
+char(o,81980).
+char(o,81981).
+char(1,81982).
+char(5,81983).
+char(2,81984).
+char(4,81985).
+char(m,81986).
+char(3,81987).
+char(0,81988).
+char(8,81989).
+char(3,81990).
+char(m,81991).
+char(3,81992).
+char(7,81993).
+char(8,81994).
+char(7,81995).
+char(c,81996).
+char(c,81997).
+char(c,81998).
+char(m,81999).
+char(o,82000).
+char(p,82001).
+char(7,82002).
+char(1,82003).
+char(5,82004).
+char(9,82005).
+char(c,82006).
+char(c,82007).
+char(c,82008).
+char(p,82009).
+char(o,82010).
+char(m,82011).
+char(1,82012).
+char(5,82013).
+char(4,82014).
+char(5,82015).
+char(p,82016).
+char(o,82017).
+char(m,82018).
+char(8,82019).
+char(2,82020).
+char(7,82021).
+char(4,82022).
+char(p,82023).
+char(9,82024).
+char(7,82025).
+char(3,82026).
+char(2,82027).
+char(p,82028).
+char(2,82029).
+char(9,82030).
+char(7,82031).
+char(6,82032).
+char(c,82033).
+char(m,82034).
+char(3,82035).
+char(7,82036).
+char(4,82037).
+char(4,82038).
+char(c,82039).
+char(c,82040).
+char(p,82041).
+char(o,82042).
+char(p,82043).
+char(9,82044).
+char(5,82045).
+char(8,82046).
+char(0,82047).
+char(m,82048).
+char(1,82049).
+char(7,82050).
+char(2,82051).
+char(2,82052).
+char(p,82053).
+char(o,82054).
+char(p,82055).
+char(9,82056).
+char(4,82057).
+char(0,82058).
+char(7,82059).
+char(p,82060).
+char(1,82061).
+char(6,82062).
+char(4,82063).
+char(0,82064).
+char(p,82065).
+char(o,82066).
+char(p,82067).
+char(o,82068).
+char(p,82069).
+char(o,82070).
+char(p,82071).
+char(8,82072).
+char(0,82073).
+char(7,82074).
+char(0,82075).
+char(p,82076).
+char(o,82077).
+char(m,82078).
+char(4,82079).
+char(3,82080).
+char(2,82081).
+char(0,82082).
+char(m,82083).
+char(9,82084).
+char(8,82085).
+char(6,82086).
+char(0,82087).
+char(c,82088).
+char(m,82089).
+char(2,82090).
+char(0,82091).
+char(9,82092).
+char(1,82093).
+char(m,82094).
+char(o,82095).
+char(7,82096).
+char(1,82097).
+char(2,82098).
+char(1,82099).
+char(p,82100).
+char(9,82101).
+char(1,82102).
+char(8,82103).
+char(m,82104).
+char(o,82105).
+char(m,82106).
+char(o,82107).
+char(o,82108).
+char(o,82109).
+char(4,82110).
+char(0,82111).
+char(3,82112).
+char(6,82113).
+char(p,82114).
+char(1,82115).
+char(5,82116).
+char(1,82117).
+char(6,82118).
+char(c,82119).
+char(c,82120).
+char(p,82121).
+char(o,82122).
+char(p,82123).
+char(7,82124).
+char(7,82125).
+char(5,82126).
+char(0,82127).
+char(c,82128).
+char(p,82129).
+char(o,82130).
+char(9,82131).
+char(6,82132).
+char(7,82133).
+char(9,82134).
+char(c,82135).
+char(p,82136).
+char(o,82137).
+char(m,82138).
+char(8,82139).
+char(2,82140).
+char(9,82141).
+char(p,82142).
+char(5,82143).
+char(8,82144).
+char(7,82145).
+char(7,82146).
+char(p,82147).
+char(o,82148).
+char(p,82149).
+char(o,82150).
+char(p,82151).
+char(7,82152).
+char(9,82153).
+char(0,82154).
+char(6,82155).
+char(p,82156).
+char(o,82157).
+char(7,82158).
+char(1,82159).
+char(0,82160).
+char(3,82161).
+char(m,82162).
+char(o,82163).
+char(m,82164).
+char(7,82165).
+char(9,82166).
+char(8,82167).
+char(2,82168).
+char(p,82169).
+char(o,82170).
+char(m,82171).
+char(6,82172).
+char(8,82173).
+char(8,82174).
+char(0,82175).
+char(c,82176).
+char(m,82177).
+char(o,82178).
+char(o,82179).
+char(p,82180).
+char(7,82181).
+char(4,82182).
+char(3,82183).
+char(1,82184).
+char(c,82185).
+char(m,82186).
+char(o,82187).
+char(5,82188).
+char(5,82189).
+char(5,82190).
+char(0,82191).
+char(m,82192).
+char(o,82193).
+char(m,82194).
+char(o,82195).
+char(p,82196).
+char(o,82197).
+char(7,82198).
+char(3,82199).
+char(9,82200).
+char(7,82201).
+char(m,82202).
+char(7,82203).
+char(3,82204).
+char(4,82205).
+char(6,82206).
+char(m,82207).
+char(o,82208).
+char(m,82209).
+char(3,82210).
+char(2,82211).
+char(5,82212).
+char(2,82213).
+char(c,82214).
+char(c,82215).
+char(c,82216).
+char(m,82217).
+char(o,82218).
+char(1,82219).
+char(6,82220).
+char(7,82221).
+char(3,82222).
+char(c,82223).
+char(p,82224).
+char(o,82225).
+char(p,82226).
+char(1,82227).
+char(7,82228).
+char(2,82229).
+char(8,82230).
+char(p,82231).
+char(9,82232).
+char(6,82233).
+char(5,82234).
+char(8,82235).
+char(m,82236).
+char(2,82237).
+char(3,82238).
+char(1,82239).
+char(6,82240).
+char(c,82241).
+char(p,82242).
+char(9,82243).
+char(9,82244).
+char(9,82245).
+char(c,82246).
+char(c,82247).
+char(p,82248).
+char(o,82249).
+char(m,82250).
+char(3,82251).
+char(8,82252).
+char(2,82253).
+char(c,82254).
+char(p,82255).
+char(4,82256).
+char(8,82257).
+char(9,82258).
+char(3,82259).
+char(m,82260).
+char(5,82261).
+char(0,82262).
+char(1,82263).
+char(2,82264).
+char(m,82265).
+char(1,82266).
+char(1,82267).
+char(1,82268).
+char(3,82269).
+char(c,82270).
+char(c,82271).
+char(c,82272).
+char(p,82273).
+char(4,82274).
+char(9,82275).
+char(7,82276).
+char(5,82277).
+char(p,82278).
+char(o,82279).
+char(1,82280).
+char(6,82281).
+char(8,82282).
+char(1,82283).
+char(c,82284).
+char(c,82285).
+char(m,82286).
+char(o,82287).
+char(o,82288).
+char(p,82289).
+char(o,82290).
+char(p,82291).
+char(1,82292).
+char(5,82293).
+char(6,82294).
+char(4,82295).
+char(c,82296).
+char(c,82297).
+char(p,82298).
+char(7,82299).
+char(7,82300).
+char(5,82301).
+char(5,82302).
+char(m,82303).
+char(o,82304).
+char(p,82305).
+char(5,82306).
+char(2,82307).
+char(9,82308).
+char(2,82309).
+char(c,82310).
+char(m,82311).
+char(5,82312).
+char(5,82313).
+char(3,82314).
+char(p,82315).
+char(o,82316).
+char(p,82317).
+char(3,82318).
+char(2,82319).
+char(9,82320).
+char(3,82321).
+char(m,82322).
+char(1,82323).
+char(1,82324).
+char(2,82325).
+char(9,82326).
+char(c,82327).
+char(m,82328).
+char(7,82329).
+char(0,82330).
+char(6,82331).
+char(3,82332).
+char(p,82333).
+char(4,82334).
+char(9,82335).
+char(1,82336).
+char(8,82337).
+char(p,82338).
+char(o,82339).
+char(2,82340).
+char(8,82341).
+char(3,82342).
+char(8,82343).
+char(c,82344).
+char(c,82345).
+char(p,82346).
+char(o,82347).
+char(o,82348).
+char(2,82349).
+char(2,82350).
+char(5,82351).
+char(8,82352).
+char(c,82353).
+char(m,82354).
+char(3,82355).
+char(1,82356).
+char(4,82357).
+char(5,82358).
+char(m,82359).
+char(o,82360).
+char(5,82361).
+char(3,82362).
+char(2,82363).
+char(6,82364).
+char(p,82365).
+char(o,82366).
+char(p,82367).
+char(o,82368).
+char(m,82369).
+char(3,82370).
+char(9,82371).
+char(1,82372).
+char(6,82373).
+char(p,82374).
+char(1,82375).
+char(4,82376).
+char(1,82377).
+char(4,82378).
+char(p,82379).
+char(o,82380).
+char(m,82381).
+char(9,82382).
+char(8,82383).
+char(0,82384).
+char(2,82385).
+char(c,82386).
+char(p,82387).
+char(o,82388).
+char(p,82389).
+char(7,82390).
+char(9,82391).
+char(0,82392).
+char(8,82393).
+char(c,82394).
+char(m,82395).
+char(8,82396).
+char(0,82397).
+char(4,82398).
+char(4,82399).
+char(m,82400).
+char(2,82401).
+char(0,82402).
+char(0,82403).
+char(6,82404).
+char(p,82405).
+char(3,82406).
+char(2,82407).
+char(2,82408).
+char(3,82409).
+char(p,82410).
+char(6,82411).
+char(2,82412).
+char(4,82413).
+char(8,82414).
+char(p,82415).
+char(6,82416).
+char(4,82417).
+char(4,82418).
+char(p,82419).
+char(o,82420).
+char(m,82421).
+char(o,82422).
+char(m,82423).
+char(o,82424).
+char(4,82425).
+char(0,82426).
+char(5,82427).
+char(6,82428).
+char(p,82429).
+char(o,82430).
+char(o,82431).
+char(m,82432).
+char(o,82433).
+char(2,82434).
+char(9,82435).
+char(6,82436).
+char(3,82437).
+char(m,82438).
+char(o,82439).
+char(5,82440).
+char(3,82441).
+char(5,82442).
+char(9,82443).
+char(m,82444).
+char(o,82445).
+char(p,82446).
+char(o,82447).
+char(m,82448).
+char(3,82449).
+char(3,82450).
+char(1,82451).
+char(0,82452).
+char(c,82453).
+char(c,82454).
+char(m,82455).
+char(6,82456).
+char(5,82457).
+char(2,82458).
+char(3,82459).
+char(c,82460).
+char(c,82461).
+char(c,82462).
+char(m,82463).
+char(o,82464).
+char(p,82465).
+char(o,82466).
+char(p,82467).
+char(o,82468).
+char(7,82469).
+char(6,82470).
+char(1,82471).
+char(0,82472).
+char(c,82473).
+char(p,82474).
+char(8,82475).
+char(0,82476).
+char(2,82477).
+char(4,82478).
+char(m,82479).
+char(8,82480).
+char(6,82481).
+char(8,82482).
+char(9,82483).
+char(c,82484).
+char(c,82485).
+char(m,82486).
+char(o,82487).
+char(m,82488).
+char(8,82489).
+char(7,82490).
+char(4,82491).
+char(0,82492).
+char(c,82493).
+char(c,82494).
+char(c,82495).
+char(p,82496).
+char(o,82497).
+char(p,82498).
+char(o,82499).
+char(p,82500).
+char(9,82501).
+char(8,82502).
+char(1,82503).
+char(8,82504).
+char(m,82505).
+char(3,82506).
+char(6,82507).
+char(7,82508).
+char(c,82509).
+char(p,82510).
+char(7,82511).
+char(1,82512).
+char(9,82513).
+char(6,82514).
+char(c,82515).
+char(c,82516).
+char(m,82517).
+char(o,82518).
+char(p,82519).
+char(7,82520).
+char(0,82521).
+char(6,82522).
+char(7,82523).
+char(c,82524).
+char(c,82525).
+char(m,82526).
+char(o,82527).
+char(o,82528).
+char(o,82529).
+char(m,82530).
+char(o,82531).
+char(p,82532).
+char(o,82533).
+char(o,82534).
+char(5,82535).
+char(1,82536).
+char(0,82537).
+char(6,82538).
+char(c,82539).
+char(p,82540).
+char(o,82541).
+char(m,82542).
+char(o,82543).
+char(o,82544).
+char(3,82545).
+char(4,82546).
+char(6,82547).
+char(5,82548).
+char(p,82549).
+char(8,82550).
+char(0,82551).
+char(1,82552).
+char(7,82553).
+char(p,82554).
+char(4,82555).
+char(9,82556).
+char(3,82557).
+char(9,82558).
+char(p,82559).
+char(o,82560).
+char(5,82561).
+char(3,82562).
+char(0,82563).
+char(9,82564).
+char(p,82565).
+char(o,82566).
+char(m,82567).
+char(o,82568).
+char(m,82569).
+char(o,82570).
+char(m,82571).
+char(o,82572).
+char(7,82573).
+char(8,82574).
+char(1,82575).
+char(5,82576).
+char(c,82577).
+char(c,82578).
+char(c,82579).
+char(c,82580).
+char(c,82581).
+char(c,82582).
+char(c,82583).
+char(c,82584).
+char(c,82585).
+char(m,82586).
+char(2,82587).
+char(8,82588).
+char(9,82589).
+char(2,82590).
+char(p,82591).
+char(5,82592).
+char(8,82593).
+char(3,82594).
+char(7,82595).
+char(c,82596).
+char(c,82597).
+char(m,82598).
+char(o,82599).
+char(p,82600).
+char(9,82601).
+char(1,82602).
+char(4,82603).
+char(9,82604).
+char(p,82605).
+char(o,82606).
+char(m,82607).
+char(5,82608).
+char(4,82609).
+char(7,82610).
+char(7,82611).
+char(c,82612).
+char(c,82613).
+char(p,82614).
+char(o,82615).
+char(7,82616).
+char(9,82617).
+char(2,82618).
+char(4,82619).
+char(c,82620).
+char(c,82621).
+char(c,82622).
+char(c,82623).
+char(c,82624).
+char(p,82625).
+char(o,82626).
+char(p,82627).
+char(o,82628).
+char(p,82629).
+char(3,82630).
+char(7,82631).
+char(9,82632).
+char(p,82633).
+char(5,82634).
+char(2,82635).
+char(9,82636).
+char(c,82637).
+char(c,82638).
+char(c,82639).
+char(m,82640).
+char(o,82641).
+char(m,82642).
+char(o,82643).
+char(p,82644).
+char(o,82645).
+char(o,82646).
+char(m,82647).
+char(1,82648).
+char(8,82649).
+char(1,82650).
+char(9,82651).
+char(c,82652).
+char(p,82653).
+char(4,82654).
+char(9,82655).
+char(6,82656).
+char(6,82657).
+char(c,82658).
+char(m,82659).
+char(6,82660).
+char(1,82661).
+char(3,82662).
+char(3,82663).
+char(c,82664).
+char(c,82665).
+char(m,82666).
+char(o,82667).
+char(9,82668).
+char(5,82669).
+char(7,82670).
+char(6,82671).
+char(c,82672).
+char(c,82673).
+char(c,82674).
+char(c,82675).
+char(m,82676).
+char(4,82677).
+char(0,82678).
+char(0,82679).
+char(2,82680).
+char(p,82681).
+char(3,82682).
+char(0,82683).
+char(2,82684).
+char(9,82685).
+char(c,82686).
+char(c,82687).
+char(p,82688).
+char(o,82689).
+char(p,82690).
+char(o,82691).
+char(p,82692).
+char(9,82693).
+char(5,82694).
+char(9,82695).
+char(1,82696).
+char(p,82697).
+char(o,82698).
+char(p,82699).
+char(o,82700).
+char(m,82701).
+char(7,82702).
+char(1,82703).
+char(6,82704).
+char(5,82705).
+char(c,82706).
+char(m,82707).
+char(9,82708).
+char(8,82709).
+char(3,82710).
+char(3,82711).
+char(p,82712).
+char(o,82713).
+char(p,82714).
+char(o,82715).
+char(2,82716).
+char(3,82717).
+char(8,82718).
+char(4,82719).
+char(c,82720).
+char(p,82721).
+char(o,82722).
+char(p,82723).
+char(o,82724).
+char(m,82725).
+char(5,82726).
+char(4,82727).
+char(7,82728).
+char(1,82729).
+char(c,82730).
+char(c,82731).
+char(m,82732).
+char(o,82733).
+char(1,82734).
+char(0,82735).
+char(7,82736).
+char(6,82737).
+char(p,82738).
+char(1,82739).
+char(7,82740).
+char(6,82741).
+char(3,82742).
+char(c,82743).
+char(p,82744).
+char(9,82745).
+char(9,82746).
+char(5,82747).
+char(8,82748).
+char(m,82749).
+char(4,82750).
+char(3,82751).
+char(5,82752).
+char(2,82753).
+char(c,82754).
+char(c,82755).
+char(m,82756).
+char(o,82757).
+char(p,82758).
+char(o,82759).
+char(p,82760).
+char(9,82761).
+char(5,82762).
+char(8,82763).
+char(9,82764).
+char(c,82765).
+char(m,82766).
+char(4,82767).
+char(5,82768).
+char(2,82769).
+char(4,82770).
+char(p,82771).
+char(o,82772).
+char(o,82773).
+char(p,82774).
+char(2,82775).
+char(1,82776).
+char(7,82777).
+char(8,82778).
+char(c,82779).
+char(c,82780).
+char(p,82781).
+char(o,82782).
+char(o,82783).
+char(8,82784).
+char(1,82785).
+char(5,82786).
+char(0,82787).
+char(m,82788).
+char(1,82789).
+char(4,82790).
+char(9,82791).
+char(p,82792).
+char(7,82793).
+char(5,82794).
+char(4,82795).
+char(9,82796).
+char(c,82797).
+char(m,82798).
+char(o,82799).
+char(m,82800).
+char(7,82801).
+char(0,82802).
+char(7,82803).
+char(7,82804).
+char(m,82805).
+char(6,82806).
+char(2,82807).
+char(3,82808).
+char(p,82809).
+char(6,82810).
+char(4,82811).
+char(0,82812).
+char(9,82813).
+char(m,82814).
+char(5,82815).
+char(4,82816).
+char(7,82817).
+char(c,82818).
+char(m,82819).
+char(3,82820).
+char(1,82821).
+char(6,82822).
+char(4,82823).
+char(c,82824).
+char(c,82825).
+char(p,82826).
+char(o,82827).
+char(5,82828).
+char(6,82829).
+char(1,82830).
+char(5,82831).
+char(m,82832).
+char(3,82833).
+char(4,82834).
+char(1,82835).
+char(8,82836).
+char(c,82837).
+char(p,82838).
+char(o,82839).
+char(m,82840).
+char(o,82841).
+char(m,82842).
+char(o,82843).
+char(m,82844).
+char(3,82845).
+char(9,82846).
+char(6,82847).
+char(9,82848).
+char(m,82849).
+char(o,82850).
+char(o,82851).
+char(4,82852).
+char(7,82853).
+char(8,82854).
+char(0,82855).
+char(c,82856).
+char(p,82857).
+char(o,82858).
+char(p,82859).
+char(o,82860).
+char(p,82861).
+char(5,82862).
+char(4,82863).
+char(8,82864).
+char(c,82865).
+char(c,82866).
+char(m,82867).
+char(o,82868).
+char(m,82869).
+char(7,82870).
+char(7,82871).
+char(1,82872).
+char(9,82873).
+char(p,82874).
+char(9,82875).
+char(5,82876).
+char(6,82877).
+char(6,82878).
+char(m,82879).
+char(o,82880).
+char(o,82881).
+char(m,82882).
+char(o,82883).
+char(m,82884).
+char(o,82885).
+char(p,82886).
+char(o,82887).
+char(p,82888).
+char(o,82889).
+char(m,82890).
+char(o,82891).
+char(o,82892).
+char(p,82893).
+char(6,82894).
+char(4,82895).
+char(0,82896).
+char(9,82897).
+char(c,82898).
+char(c,82899).
+char(c,82900).
+char(c,82901).
+char(p,82902).
+char(8,82903).
+char(0,82904).
+char(5,82905).
+char(8,82906).
+char(c,82907).
+char(c,82908).
+char(m,82909).
+char(3,82910).
+char(5,82911).
+char(1,82912).
+char(1,82913).
+char(m,82914).
+char(8,82915).
+char(6,82916).
+char(2,82917).
+char(3,82918).
+char(p,82919).
+char(9,82920).
+char(2,82921).
+char(7,82922).
+char(7,82923).
+char(c,82924).
+char(m,82925).
+char(9,82926).
+char(1,82927).
+char(6,82928).
+char(8,82929).
+char(c,82930).
+char(m,82931).
+char(o,82932).
+char(o,82933).
+char(o,82934).
+char(p,82935).
+char(6,82936).
+char(8,82937).
+char(4,82938).
+char(1,82939).
+char(p,82940).
+char(o,82941).
+char(m,82942).
+char(1,82943).
+char(1,82944).
+char(1,82945).
+char(6,82946).
+char(p,82947).
+char(o,82948).
+char(2,82949).
+char(9,82950).
+char(2,82951).
+char(8,82952).
+char(c,82953).
+char(p,82954).
+char(o,82955).
+char(p,82956).
+char(5,82957).
+char(0,82958).
+char(8,82959).
+char(2,82960).
+char(c,82961).
+char(c,82962).
+char(c,82963).
+char(c,82964).
+char(m,82965).
+char(o,82966).
+char(m,82967).
+char(3,82968).
+char(6,82969).
+char(6,82970).
+char(4,82971).
+char(c,82972).
+char(p,82973).
+char(o,82974).
+char(o,82975).
+char(p,82976).
+char(6,82977).
+char(8,82978).
+char(9,82979).
+char(0,82980).
+char(p,82981).
+char(o,82982).
+char(p,82983).
+char(1,82984).
+char(4,82985).
+char(6,82986).
+char(3,82987).
+char(m,82988).
+char(o,82989).
+char(o,82990).
+char(m,82991).
+char(o,82992).
+char(p,82993).
+char(o,82994).
+char(o,82995).
+char(m,82996).
+char(3,82997).
+char(8,82998).
+char(2,82999).
+char(m,83000).
+char(o,83001).
+char(5,83002).
+char(3,83003).
+char(3,83004).
+char(4,83005).
+char(m,83006).
+char(o,83007).
+char(4,83008).
+char(1,83009).
+char(0,83010).
+char(6,83011).
+char(m,83012).
+char(o,83013).
+char(m,83014).
+char(5,83015).
+char(2,83016).
+char(4,83017).
+char(3,83018).
+char(p,83019).
+char(6,83020).
+char(7,83021).
+char(2,83022).
+char(9,83023).
+char(c,83024).
+char(p,83025).
+char(o,83026).
+char(p,83027).
+char(8,83028).
+char(6,83029).
+char(5,83030).
+char(8,83031).
+char(m,83032).
+char(5,83033).
+char(4,83034).
+char(9,83035).
+char(7,83036).
+char(m,83037).
+char(o,83038).
+char(o,83039).
+char(p,83040).
+char(5,83041).
+char(7,83042).
+char(2,83043).
+char(6,83044).
+char(c,83045).
+char(p,83046).
+char(o,83047).
+char(m,83048).
+char(o,83049).
+char(3,83050).
+char(1,83051).
+char(7,83052).
+char(0,83053).
+char(p,83054).
+char(1,83055).
+char(2,83056).
+char(2,83057).
+char(3,83058).
+char(c,83059).
+char(c,83060).
+char(c,83061).
+char(p,83062).
+char(o,83063).
+char(o,83064).
+char(o,83065).
+char(p,83066).
+char(6,83067).
+char(6,83068).
+char(6,83069).
+char(m,83070).
+char(5,83071).
+char(1,83072).
+char(3,83073).
+char(1,83074).
+char(m,83075).
+char(2,83076).
+char(8,83077).
+char(3,83078).
+char(6,83079).
+char(p,83080).
+char(2,83081).
+char(8,83082).
+char(5,83083).
+char(1,83084).
+char(c,83085).
+char(m,83086).
+char(o,83087).
+char(m,83088).
+char(o,83089).
+char(m,83090).
+char(4,83091).
+char(4,83092).
+char(7,83093).
+char(7,83094).
+char(p,83095).
+char(6,83096).
+char(5,83097).
+char(0,83098).
+char(7,83099).
+char(m,83100).
+char(o,83101).
+char(p,83102).
+char(o,83103).
+char(p,83104).
+char(3,83105).
+char(1,83106).
+char(2,83107).
+char(3,83108).
+char(p,83109).
+char(o,83110).
+char(m,83111).
+char(o,83112).
+char(p,83113).
+char(5,83114).
+char(6,83115).
+char(2,83116).
+char(0,83117).
+char(m,83118).
+char(1,83119).
+char(5,83120).
+char(7,83121).
+char(3,83122).
+char(c,83123).
+char(m,83124).
+char(o,83125).
+char(m,83126).
+char(o,83127).
+char(6,83128).
+char(7,83129).
+char(9,83130).
+char(p,83131).
+char(4,83132).
+char(8,83133).
+char(2,83134).
+char(7,83135).
+char(m,83136).
+char(9,83137).
+char(7,83138).
+char(9,83139).
+char(8,83140).
+char(p,83141).
+char(o,83142).
+char(p,83143).
+char(2,83144).
+char(9,83145).
+char(3,83146).
+char(c,83147).
+char(p,83148).
+char(7,83149).
+char(6,83150).
+char(0,83151).
+char(3,83152).
+char(c,83153).
+char(c,83154).
+char(p,83155).
+char(6,83156).
+char(4,83157).
+char(6,83158).
+char(5,83159).
+char(c,83160).
+char(m,83161).
+char(o,83162).
+char(m,83163).
+char(1,83164).
+char(1,83165).
+char(6,83166).
+char(4,83167).
+char(c,83168).
+char(c,83169).
+char(p,83170).
+char(6,83171).
+char(8,83172).
+char(2,83173).
+char(c,83174).
+char(c,83175).
+char(m,83176).
+char(2,83177).
+char(9,83178).
+char(7,83179).
+char(5,83180).
+char(c,83181).
+char(m,83182).
+char(2,83183).
+char(3,83184).
+char(3,83185).
+char(7,83186).
+char(m,83187).
+char(o,83188).
+char(9,83189).
+char(8,83190).
+char(4,83191).
+char(5,83192).
+char(p,83193).
+char(9,83194).
+char(3,83195).
+char(5,83196).
+char(8,83197).
+char(p,83198).
+char(o,83199).
+char(o,83200).
+char(m,83201).
+char(1,83202).
+char(3,83203).
+char(4,83204).
+char(5,83205).
+char(p,83206).
+char(o,83207).
+char(m,83208).
+char(8,83209).
+char(6,83210).
+char(6,83211).
+char(6,83212).
+char(m,83213).
+char(8,83214).
+char(9,83215).
+char(0,83216).
+char(3,83217).
+char(p,83218).
+char(o,83219).
+char(m,83220).
+char(4,83221).
+char(7,83222).
+char(8,83223).
+char(1,83224).
+char(c,83225).
+char(p,83226).
+char(5,83227).
+char(6,83228).
+char(0,83229).
+char(6,83230).
+char(c,83231).
+char(p,83232).
+char(o,83233).
+char(7,83234).
+char(3,83235).
+char(2,83236).
+char(8,83237).
+char(c,83238).
+char(p,83239).
+char(2,83240).
+char(3,83241).
+char(9,83242).
+char(2,83243).
+char(c,83244).
+char(c,83245).
+char(c,83246).
+char(c,83247).
+char(m,83248).
+char(o,83249).
+char(o,83250).
+char(p,83251).
+char(o,83252).
+char(p,83253).
+char(5,83254).
+char(1,83255).
+char(3,83256).
+char(6,83257).
+char(c,83258).
+char(m,83259).
+char(1,83260).
+char(1,83261).
+char(9,83262).
+char(1,83263).
+char(c,83264).
+char(c,83265).
+char(p,83266).
+char(o,83267).
+char(p,83268).
+char(o,83269).
+char(2,83270).
+char(8,83271).
+char(2,83272).
+char(1,83273).
+char(m,83274).
+char(o,83275).
+char(o,83276).
+char(m,83277).
+char(o,83278).
+char(p,83279).
+char(1,83280).
+char(1,83281).
+char(2,83282).
+char(3,83283).
+char(c,83284).
+char(m,83285).
+char(o,83286).
+char(p,83287).
+char(o,83288).
+char(p,83289).
+char(o,83290).
+char(9,83291).
+char(2,83292).
+char(0,83293).
+char(0,83294).
+char(m,83295).
+char(o,83296).
+char(o,83297).
+char(m,83298).
+char(7,83299).
+char(9,83300).
+char(0,83301).
+char(6,83302).
+char(m,83303).
+char(o,83304).
+char(p,83305).
+char(o,83306).
+char(p,83307).
+char(o,83308).
+char(o,83309).
+char(3,83310).
+char(0,83311).
+char(6,83312).
+char(0,83313).
+char(m,83314).
+char(o,83315).
+char(m,83316).
+char(8,83317).
+char(0,83318).
+char(8,83319).
+char(7,83320).
+char(p,83321).
+char(5,83322).
+char(7,83323).
+char(0,83324).
+char(2,83325).
+char(m,83326).
+char(o,83327).
+char(m,83328).
+char(4,83329).
+char(6,83330).
+char(2,83331).
+char(9,83332).
+char(c,83333).
+char(c,83334).
+char(c,83335).
+char(m,83336).
+char(o,83337).
+char(m,83338).
+char(o,83339).
+char(m,83340).
+char(o,83341).
+char(9,83342).
+char(9,83343).
+char(2,83344).
+char(4,83345).
+char(c,83346).
+char(c,83347).
+char(p,83348).
+char(o,83349).
+char(m,83350).
+char(o,83351).
+char(o,83352).
+char(m,83353).
+char(o,83354).
+char(m,83355).
+char(8,83356).
+char(9,83357).
+char(0,83358).
+char(8,83359).
+char(m,83360).
+char(9,83361).
+char(5,83362).
+char(0,83363).
+char(7,83364).
+char(p,83365).
+char(o,83366).
+char(4,83367).
+char(3,83368).
+char(5,83369).
+char(3,83370).
+char(p,83371).
+char(9,83372).
+char(7,83373).
+char(6,83374).
+char(2,83375).
+char(p,83376).
+char(7,83377).
+char(4,83378).
+char(5,83379).
+char(3,83380).
+char(p,83381).
+char(o,83382).
+char(m,83383).
+char(1,83384).
+char(4,83385).
+char(8,83386).
+char(p,83387).
+char(o,83388).
+char(p,83389).
+char(1,83390).
+char(5,83391).
+char(9,83392).
+char(3,83393).
+char(p,83394).
+char(5,83395).
+char(9,83396).
+char(1,83397).
+char(c,83398).
+char(p,83399).
+char(o,83400).
+char(4,83401).
+char(7,83402).
+char(2,83403).
+char(8,83404).
+char(c,83405).
+char(c,83406).
+char(c,83407).
+char(p,83408).
+char(o,83409).
+char(p,83410).
+char(5,83411).
+char(9,83412).
+char(2,83413).
+char(4,83414).
+char(c,83415).
+char(m,83416).
+char(o,83417).
+char(o,83418).
+char(m,83419).
+char(o,83420).
+char(m,83421).
+char(o,83422).
+char(m,83423).
+char(4,83424).
+char(7,83425).
+char(8,83426).
+char(1,83427).
+char(c,83428).
+char(c,83429).
+char(c,83430).
+char(c,83431).
+char(p,83432).
+char(9,83433).
+char(0,83434).
+char(c,83435).
+char(m,83436).
+char(2,83437).
+char(2,83438).
+char(2,83439).
+char(0,83440).
+char(p,83441).
+char(4,83442).
+char(8,83443).
+char(9,83444).
+char(2,83445).
+char(c,83446).
+char(m,83447).
+char(3,83448).
+char(0,83449).
+char(5,83450).
+char(2,83451).
+char(m,83452).
+char(9,83453).
+char(4,83454).
+char(2,83455).
+char(1,83456).
+char(c,83457).
+char(c,83458).
+char(c,83459).
+char(m,83460).
+char(o,83461).
+char(4,83462).
+char(9,83463).
+char(9,83464).
+char(9,83465).
+char(p,83466).
+char(4,83467).
+char(9,83468).
+char(1,83469).
+char(4,83470).
+char(c,83471).
+char(m,83472).
+char(o,83473).
+char(p,83474).
+char(8,83475).
+char(6,83476).
+char(7,83477).
+char(6,83478).
+char(c,83479).
+char(c,83480).
+char(c,83481).
+char(c,83482).
+char(c,83483).
+char(m,83484).
+char(8,83485).
+char(2,83486).
+char(9,83487).
+char(4,83488).
+char(c,83489).
+char(p,83490).
+char(o,83491).
+char(o,83492).
+char(m,83493).
+char(o,83494).
+char(o,83495).
+char(m,83496).
+char(o,83497).
+char(o,83498).
+char(p,83499).
+char(o,83500).
+char(p,83501).
+char(o,83502).
+char(m,83503).
+char(o,83504).
+char(p,83505).
+char(o,83506).
+char(m,83507).
+char(1,83508).
+char(7,83509).
+char(2,83510).
+char(9,83511).
+char(c,83512).
+char(p,83513).
+char(o,83514).
+char(o,83515).
+char(o,83516).
+char(1,83517).
+char(2,83518).
+char(3,83519).
+char(3,83520).
+char(c,83521).
+char(c,83522).
+char(c,83523).
+char(c,83524).
+char(p,83525).
+char(2,83526).
+char(9,83527).
+char(3,83528).
+char(3,83529).
+char(p,83530).
+char(9,83531).
+char(8,83532).
+char(2,83533).
+char(3,83534).
+char(c,83535).
+char(p,83536).
+char(9,83537).
+char(6,83538).
+char(1,83539).
+char(3,83540).
+char(m,83541).
+char(o,83542).
+char(m,83543).
+char(o,83544).
+char(m,83545).
+char(o,83546).
+char(m,83547).
+char(o,83548).
+char(o,83549).
+char(m,83550).
+char(7,83551).
+char(3,83552).
+char(1,83553).
+char(8,83554).
+char(m,83555).
+char(6,83556).
+char(9,83557).
+char(7,83558).
+char(c,83559).
+char(m,83560).
+char(o,83561).
+char(p,83562).
+char(o,83563).
+char(p,83564).
+char(8,83565).
+char(6,83566).
+char(9,83567).
+char(0,83568).
+char(c,83569).
+char(c,83570).
+char(c,83571).
+char(m,83572).
+char(o,83573).
+char(2,83574).
+char(1,83575).
+char(0,83576).
+char(4,83577).
+char(c,83578).
+char(p,83579).
+char(5,83580).
+char(2,83581).
+char(3,83582).
+char(m,83583).
+char(9,83584).
+char(3,83585).
+char(4,83586).
+char(3,83587).
+char(p,83588).
+char(7,83589).
+char(1,83590).
+char(9,83591).
+char(4,83592).
+char(m,83593).
+char(4,83594).
+char(5,83595).
+char(7,83596).
+char(2,83597).
+char(c,83598).
+char(p,83599).
+char(o,83600).
+char(o,83601).
+char(p,83602).
+char(o,83603).
+char(p,83604).
+char(3,83605).
+char(7,83606).
+char(9,83607).
+char(2,83608).
+char(m,83609).
+char(o,83610).
+char(o,83611).
+char(p,83612).
+char(4,83613).
+char(2,83614).
+char(1,83615).
+char(6,83616).
+char(c,83617).
+char(c,83618).
+char(m,83619).
+char(8,83620).
+char(8,83621).
+char(0,83622).
+char(0,83623).
+char(c,83624).
+char(c,83625).
+char(c,83626).
+char(c,83627).
+char(c,83628).
+char(m,83629).
+char(5,83630).
+char(9,83631).
+char(0,83632).
+char(8,83633).
+char(m,83634).
+char(6,83635).
+char(2,83636).
+char(m,83637).
+char(9,83638).
+char(9,83639).
+char(4,83640).
+char(1,83641).
+char(c,83642).
+char(p,83643).
+char(8,83644).
+char(2,83645).
+char(4,83646).
+char(9,83647).
+char(p,83648).
+char(2,83649).
+char(8,83650).
+char(3,83651).
+char(4,83652).
+char(c,83653).
+char(p,83654).
+char(9,83655).
+char(5,83656).
+char(5,83657).
+char(8,83658).
+char(c,83659).
+char(m,83660).
+char(o,83661).
+char(m,83662).
+char(o,83663).
+char(9,83664).
+char(9,83665).
+char(5,83666).
+char(c,83667).
+char(m,83668).
+char(o,83669).
+char(m,83670).
+char(9,83671).
+char(0,83672).
+char(5,83673).
+char(p,83674).
+char(o,83675).
+char(p,83676).
+char(o,83677).
+char(p,83678).
+char(5,83679).
+char(5,83680).
+char(3,83681).
+char(2,83682).
+char(m,83683).
+char(2,83684).
+char(1,83685).
+char(8,83686).
+char(m,83687).
+char(5,83688).
+char(8,83689).
+char(0,83690).
+char(3,83691).
+char(c,83692).
+char(c,83693).
+char(c,83694).
+char(m,83695).
+char(o,83696).
+char(m,83697).
+char(o,83698).
+char(o,83699).
+char(1,83700).
+char(9,83701).
+char(0,83702).
+char(7,83703).
+char(p,83704).
+char(o,83705).
+char(m,83706).
+char(9,83707).
+char(2,83708).
+char(6,83709).
+char(2,83710).
+char(p,83711).
+char(o,83712).
+char(o,83713).
+char(p,83714).
+char(6,83715).
+char(0,83716).
+char(9,83717).
+char(2,83718).
+char(c,83719).
+char(c,83720).
+char(m,83721).
+char(o,83722).
+char(p,83723).
+char(o,83724).
+char(m,83725).
+char(8,83726).
+char(1,83727).
+char(1,83728).
+char(6,83729).
+char(p,83730).
+char(2,83731).
+char(2,83732).
+char(3,83733).
+char(0,83734).
+char(c,83735).
+char(m,83736).
+char(5,83737).
+char(3,83738).
+char(1,83739).
+char(7,83740).
+char(m,83741).
+char(3,83742).
+char(0,83743).
+char(0,83744).
+char(1,83745).
+char(c,83746).
+char(c,83747).
+char(m,83748).
+char(6,83749).
+char(6,83750).
+char(0,83751).
+char(9,83752).
+char(c,83753).
+char(m,83754).
+char(o,83755).
+char(m,83756).
+char(o,83757).
+char(o,83758).
+char(o,83759).
+char(p,83760).
+char(o,83761).
+char(o,83762).
+char(p,83763).
+char(9,83764).
+char(4,83765).
+char(9,83766).
+char(5,83767).
+char(c,83768).
+char(c,83769).
+char(m,83770).
+char(3,83771).
+char(6,83772).
+char(0,83773).
+char(6,83774).
+char(p,83775).
+char(o,83776).
+char(m,83777).
+char(o,83778).
+char(m,83779).
+char(o,83780).
+char(8,83781).
+char(3,83782).
+char(4,83783).
+char(6,83784).
+char(c,83785).
+char(c,83786).
+char(m,83787).
+char(o,83788).
+char(p,83789).
+char(o,83790).
+char(m,83791).
+char(6,83792).
+char(9,83793).
+char(4,83794).
+char(3,83795).
+char(p,83796).
+char(5,83797).
+char(5,83798).
+char(3,83799).
+char(5,83800).
+char(c,83801).
+char(c,83802).
+char(c,83803).
+char(p,83804).
+char(o,83805).
+char(m,83806).
+char(8,83807).
+char(2,83808).
+char(1,83809).
+char(7,83810).
+char(c,83811).
+char(c,83812).
+char(p,83813).
+char(o,83814).
+char(9,83815).
+char(7,83816).
+char(5,83817).
+char(7,83818).
+char(c,83819).
+char(c,83820).
+char(c,83821).
+char(p,83822).
+char(6,83823).
+char(4,83824).
+char(4,83825).
+char(9,83826).
+char(p,83827).
+char(9,83828).
+char(0,83829).
+char(9,83830).
+char(1,83831).
+char(c,83832).
+char(p,83833).
+char(o,83834).
+char(m,83835).
+char(o,83836).
+char(o,83837).
+char(p,83838).
+char(6,83839).
+char(1,83840).
+char(6,83841).
+char(3,83842).
+char(c,83843).
+char(c,83844).
+char(p,83845).
+char(o,83846).
+char(p,83847).
+char(4,83848).
+char(9,83849).
+char(8,83850).
+char(4,83851).
+char(c,83852).
+char(c,83853).
+char(p,83854).
+char(o,83855).
+char(p,83856).
+char(3,83857).
+char(2,83858).
+char(8,83859).
+char(9,83860).
+char(m,83861).
+char(o,83862).
+char(2,83863).
+char(5,83864).
+char(2,83865).
+char(2,83866).
+char(c,83867).
+char(m,83868).
+char(1,83869).
+char(9,83870).
+char(8,83871).
+char(4,83872).
+char(p,83873).
+char(o,83874).
+char(m,83875).
+char(9,83876).
+char(3,83877).
+char(1,83878).
+char(4,83879).
+char(p,83880).
+char(o,83881).
+char(p,83882).
+char(8,83883).
+char(5,83884).
+char(9,83885).
+char(6,83886).
+char(c,83887).
+char(c,83888).
+char(c,83889).
+char(p,83890).
+char(o,83891).
+char(p,83892).
+char(o,83893).
+char(p,83894).
+char(8,83895).
+char(9,83896).
+char(1,83897).
+char(3,83898).
+char(m,83899).
+char(2,83900).
+char(4,83901).
+char(4,83902).
+char(m,83903).
+char(3,83904).
+char(6,83905).
+char(2,83906).
+char(0,83907).
+char(m,83908).
+char(3,83909).
+char(7,83910).
+char(4,83911).
+char(4,83912).
+char(p,83913).
+char(7,83914).
+char(0,83915).
+char(0,83916).
+char(6,83917).
+char(m,83918).
+char(4,83919).
+char(9,83920).
+char(3,83921).
+char(1,83922).
+char(p,83923).
+char(o,83924).
+char(5,83925).
+char(2,83926).
+char(3,83927).
+char(3,83928).
+char(c,83929).
+char(c,83930).
+char(c,83931).
+char(p,83932).
+char(6,83933).
+char(8,83934).
+char(2,83935).
+char(4,83936).
+char(m,83937).
+char(6,83938).
+char(6,83939).
+char(9,83940).
+char(2,83941).
+char(c,83942).
+char(p,83943).
+char(1,83944).
+char(8,83945).
+char(3,83946).
+char(3,83947).
+char(m,83948).
+char(5,83949).
+char(4,83950).
+char(8,83951).
+char(7,83952).
+char(c,83953).
+char(c,83954).
+char(c,83955).
+char(m,83956).
+char(2,83957).
+char(1,83958).
+char(9,83959).
+char(c,83960).
+char(p,83961).
+char(o,83962).
+char(p,83963).
+char(9,83964).
+char(4,83965).
+char(7,83966).
+char(6,83967).
+char(c,83968).
+char(p,83969).
+char(8,83970).
+char(7,83971).
+char(6,83972).
+char(5,83973).
+char(c,83974).
+char(p,83975).
+char(1,83976).
+char(0,83977).
+char(5,83978).
+char(8,83979).
+char(m,83980).
+char(3,83981).
+char(4,83982).
+char(1,83983).
+char(2,83984).
+char(c,83985).
+char(p,83986).
+char(o,83987).
+char(2,83988).
+char(6,83989).
+char(2,83990).
+char(1,83991).
+char(c,83992).
+char(c,83993).
+char(c,83994).
+char(p,83995).
+char(5,83996).
+char(0,83997).
+char(3,83998).
+char(c,83999).
+char(c,84000).
+char(p,84001).
+char(o,84002).
+char(o,84003).
+char(m,84004).
+char(o,84005).
+char(p,84006).
+char(2,84007).
+char(2,84008).
+char(9,84009).
+char(2,84010).
+char(c,84011).
+char(m,84012).
+char(4,84013).
+char(1,84014).
+char(3,84015).
+char(2,84016).
+char(c,84017).
+char(c,84018).
+char(c,84019).
+char(c,84020).
+char(p,84021).
+char(o,84022).
+char(m,84023).
+char(o,84024).
+char(6,84025).
+char(7,84026).
+char(0,84027).
+char(1,84028).
+char(c,84029).
+char(c,84030).
+char(m,84031).
+char(o,84032).
+char(p,84033).
+char(6,84034).
+char(2,84035).
+char(6,84036).
+char(9,84037).
+char(c,84038).
+char(m,84039).
+char(9,84040).
+char(7,84041).
+char(4,84042).
+char(0,84043).
+char(c,84044).
+char(m,84045).
+char(8,84046).
+char(3,84047).
+char(0,84048).
+char(c,84049).
+char(p,84050).
+char(o,84051).
+char(o,84052).
+char(m,84053).
+char(o,84054).
+char(p,84055).
+char(o,84056).
+char(p,84057).
+char(o,84058).
+char(p,84059).
+char(o,84060).
+char(p,84061).
+char(o,84062).
+char(m,84063).
+char(5,84064).
+char(2,84065).
+char(8,84066).
+char(5,84067).
+char(p,84068).
+char(2,84069).
+char(4,84070).
+char(7,84071).
+char(c,84072).
+char(c,84073).
+char(p,84074).
+char(9,84075).
+char(8,84076).
+char(3,84077).
+char(7,84078).
+char(p,84079).
+char(o,84080).
+char(m,84081).
+char(o,84082).
+char(m,84083).
+char(o,84084).
+char(p,84085).
+char(7,84086).
+char(7,84087).
+char(3,84088).
+char(2,84089).
+char(p,84090).
+char(o,84091).
+char(m,84092).
+char(o,84093).
+char(o,84094).
+char(p,84095).
+char(6,84096).
+char(5,84097).
+char(0,84098).
+char(6,84099).
+char(p,84100).
+char(o,84101).
+char(m,84102).
+char(2,84103).
+char(9,84104).
+char(9,84105).
+char(6,84106).
+char(m,84107).
+char(2,84108).
+char(3,84109).
+char(2,84110).
+char(7,84111).
+char(c,84112).
+char(m,84113).
+char(5,84114).
+char(7,84115).
+char(4,84116).
+char(2,84117).
+char(c,84118).
+char(c,84119).
+char(p,84120).
+char(o,84121).
+char(p,84122).
+char(8,84123).
+char(4,84124).
+char(3,84125).
+char(c,84126).
+char(c,84127).
+char(m,84128).
+char(1,84129).
+char(1,84130).
+char(2,84131).
+char(7,84132).
+char(p,84133).
+char(9,84134).
+char(0,84135).
+char(3,84136).
+char(7,84137).
+char(c,84138).
+char(c,84139).
+char(m,84140).
+char(8,84141).
+char(0,84142).
+char(3,84143).
+char(4,84144).
+char(c,84145).
+char(m,84146).
+char(o,84147).
+char(o,84148).
+char(p,84149).
+char(1,84150).
+char(9,84151).
+char(5,84152).
+char(9,84153).
+char(p,84154).
+char(o,84155).
+char(m,84156).
+char(o,84157).
+char(m,84158).
+char(1,84159).
+char(2,84160).
+char(6,84161).
+char(7,84162).
+char(p,84163).
+char(7,84164).
+char(6,84165).
+char(4,84166).
+char(2,84167).
+char(c,84168).
+char(p,84169).
+char(o,84170).
+char(p,84171).
+char(8,84172).
+char(0,84173).
+char(6,84174).
+char(0,84175).
+char(c,84176).
+char(c,84177).
+char(p,84178).
+char(2,84179).
+char(9,84180).
+char(6,84181).
+char(9,84182).
+char(p,84183).
+char(8,84184).
+char(0,84185).
+char(4,84186).
+char(c,84187).
+char(c,84188).
+char(p,84189).
+char(5,84190).
+char(2,84191).
+char(9,84192).
+char(5,84193).
+char(c,84194).
+char(m,84195).
+char(3,84196).
+char(6,84197).
+char(0,84198).
+char(1,84199).
+char(m,84200).
+char(9,84201).
+char(3,84202).
+char(0,84203).
+char(c,84204).
+char(m,84205).
+char(4,84206).
+char(4,84207).
+char(8,84208).
+char(4,84209).
+char(p,84210).
+char(o,84211).
+char(p,84212).
+char(o,84213).
+char(p,84214).
+char(o,84215).
+char(p,84216).
+char(8,84217).
+char(4,84218).
+char(5,84219).
+char(9,84220).
+char(c,84221).
+char(c,84222).
+char(m,84223).
+char(o,84224).
+char(m,84225).
+char(o,84226).
+char(m,84227).
+char(o,84228).
+char(p,84229).
+char(8,84230).
+char(2,84231).
+char(3,84232).
+char(6,84233).
+char(m,84234).
+char(2,84235).
+char(1,84236).
+char(9,84237).
+char(4,84238).
+char(c,84239).
+char(c,84240).
+char(c,84241).
+char(c,84242).
+char(m,84243).
+char(2,84244).
+char(3,84245).
+char(8,84246).
+char(2,84247).
+char(p,84248).
+char(o,84249).
+char(p,84250).
+char(o,84251).
+char(o,84252).
+char(m,84253).
+char(3,84254).
+char(7,84255).
+char(7,84256).
+char(9,84257).
+char(c,84258).
+char(m,84259).
+char(4,84260).
+char(1,84261).
+char(1,84262).
+char(3,84263).
+char(p,84264).
+char(8,84265).
+char(1,84266).
+char(0,84267).
+char(c,84268).
+char(p,84269).
+char(7,84270).
+char(2,84271).
+char(9,84272).
+char(4,84273).
+char(p,84274).
+char(o,84275).
+char(m,84276).
+char(o,84277).
+char(o,84278).
+char(m,84279).
+char(o,84280).
+char(p,84281).
+char(1,84282).
+char(1,84283).
+char(9,84284).
+char(4,84285).
+char(p,84286).
+char(o,84287).
+char(m,84288).
+char(5,84289).
+char(2,84290).
+char(4,84291).
+char(7,84292).
+char(c,84293).
+char(m,84294).
+char(4,84295).
+char(3,84296).
+char(8,84297).
+char(7,84298).
+char(c,84299).
+char(c,84300).
+char(c,84301).
+char(c,84302).
+char(c,84303).
+char(c,84304).
+char(p,84305).
+char(o,84306).
+char(m,84307).
+char(o,84308).
+char(o,84309).
+char(o,84310).
+char(1,84311).
+char(5,84312).
+char(9,84313).
+char(6,84314).
+char(c,84315).
+char(c,84316).
+char(c,84317).
+char(m,84318).
+char(4,84319).
+char(8,84320).
+char(0,84321).
+char(5,84322).
+char(p,84323).
+char(o,84324).
+char(m,84325).
+char(2,84326).
+char(8,84327).
+char(8,84328).
+char(c,84329).
+char(p,84330).
+char(4,84331).
+char(9,84332).
+char(8,84333).
+char(2,84334).
+char(p,84335).
+char(o,84336).
+char(m,84337).
+char(o,84338).
+char(5,84339).
+char(5,84340).
+char(7,84341).
+char(6,84342).
+char(c,84343).
+char(c,84344).
+char(c,84345).
+char(p,84346).
+char(3,84347).
+char(0,84348).
+char(9,84349).
+char(6,84350).
+char(m,84351).
+char(9,84352).
+char(9,84353).
+char(3,84354).
+char(4,84355).
+char(c,84356).
+char(p,84357).
+char(8,84358).
+char(2,84359).
+char(5,84360).
+char(8,84361).
+char(p,84362).
+char(1,84363).
+char(2,84364).
+char(1,84365).
+char(1,84366).
+char(p,84367).
+char(8,84368).
+char(6,84369).
+char(3,84370).
+char(9,84371).
+char(c,84372).
+char(c,84373).
+char(p,84374).
+char(6,84375).
+char(6,84376).
+char(6,84377).
+char(8,84378).
+char(p,84379).
+char(2,84380).
+char(9,84381).
+char(0,84382).
+char(9,84383).
+char(c,84384).
+char(p,84385).
+char(4,84386).
+char(0,84387).
+char(1,84388).
+char(7,84389).
+char(m,84390).
+char(o,84391).
+char(8,84392).
+char(1,84393).
+char(1,84394).
+char(7,84395).
+char(c,84396).
+char(c,84397).
+char(c,84398).
+char(m,84399).
+char(9,84400).
+char(0,84401).
+char(5,84402).
+char(0,84403).
+char(c,84404).
+char(m,84405).
+char(9,84406).
+char(3,84407).
+char(m,84408).
+char(1,84409).
+char(3,84410).
+char(7,84411).
+char(4,84412).
+char(c,84413).
+char(c,84414).
+char(p,84415).
+char(1,84416).
+char(3,84417).
+char(4,84418).
+char(1,84419).
+char(m,84420).
+char(3,84421).
+char(9,84422).
+char(1,84423).
+char(3,84424).
+char(p,84425).
+char(o,84426).
+char(p,84427).
+char(4,84428).
+char(6,84429).
+char(7,84430).
+char(c,84431).
+char(c,84432).
+char(c,84433).
+char(c,84434).
+char(c,84435).
+char(c,84436).
+char(c,84437).
+char(p,84438).
+char(o,84439).
+char(m,84440).
+char(2,84441).
+char(7,84442).
+char(3,84443).
+char(4,84444).
+char(p,84445).
+char(o,84446).
+char(p,84447).
+char(5,84448).
+char(7,84449).
+char(9,84450).
+char(7,84451).
+char(m,84452).
+char(o,84453).
+char(1,84454).
+char(4,84455).
+char(4,84456).
+char(5,84457).
+char(p,84458).
+char(9,84459).
+char(7,84460).
+char(1,84461).
+char(9,84462).
+char(c,84463).
+char(c,84464).
+char(c,84465).
+char(m,84466).
+char(4,84467).
+char(9,84468).
+char(7,84469).
+char(4,84470).
+char(c,84471).
+char(m,84472).
+char(9,84473).
+char(5,84474).
+char(8,84475).
+char(2,84476).
+char(c,84477).
+char(c,84478).
+char(m,84479).
+char(o,84480).
+char(m,84481).
+char(8,84482).
+char(8,84483).
+char(4,84484).
+char(7,84485).
+char(c,84486).
+char(c,84487).
+char(c,84488).
+char(m,84489).
+char(5,84490).
+char(7,84491).
+char(7,84492).
+char(8,84493).
+char(c,84494).
+char(m,84495).
+char(4,84496).
+char(4,84497).
+char(2,84498).
+char(0,84499).
+char(m,84500).
+char(o,84501).
+char(p,84502).
+char(7,84503).
+char(3,84504).
+char(6,84505).
+char(5,84506).
+char(c,84507).
+char(c,84508).
+char(m,84509).
+char(o,84510).
+char(o,84511).
+char(p,84512).
+char(o,84513).
+char(9,84514).
+char(8,84515).
+char(4,84516).
+char(c,84517).
+char(p,84518).
+char(o,84519).
+char(m,84520).
+char(1,84521).
+char(3,84522).
+char(4,84523).
+char(1,84524).
+char(m,84525).
+char(3,84526).
+char(2,84527).
+char(2,84528).
+char(9,84529).
+char(c,84530).
+char(m,84531).
+char(o,84532).
+char(m,84533).
+char(o,84534).
+char(p,84535).
+char(9,84536).
+char(7,84537).
+char(4,84538).
+char(4,84539).
+char(m,84540).
+char(5,84541).
+char(5,84542).
+char(4,84543).
+char(7,84544).
+char(c,84545).
+char(c,84546).
+char(c,84547).
+char(p,84548).
+char(7,84549).
+char(2,84550).
+char(0,84551).
+char(6,84552).
+char(m,84553).
+char(o,84554).
+char(p,84555).
+char(o,84556).
+char(p,84557).
+char(4,84558).
+char(3,84559).
+char(1,84560).
+char(9,84561).
+char(c,84562).
+char(c,84563).
+char(c,84564).
+char(c,84565).
+char(c,84566).
+char(c,84567).
+char(m,84568).
+char(3,84569).
+char(6,84570).
+char(1,84571).
+char(4,84572).
+char(c,84573).
+char(c,84574).
+char(p,84575).
+char(o,84576).
+char(o,84577).
+char(o,84578).
+char(o,84579).
+char(m,84580).
+char(6,84581).
+char(5,84582).
+char(3,84583).
+char(4,84584).
+char(m,84585).
+char(o,84586).
+char(o,84587).
+char(m,84588).
+char(o,84589).
+char(o,84590).
+char(m,84591).
+char(3,84592).
+char(0,84593).
+char(2,84594).
+char(2,84595).
+char(c,84596).
+char(c,84597).
+char(m,84598).
+char(8,84599).
+char(5,84600).
+char(0,84601).
+char(6,84602).
+char(c,84603).
+char(p,84604).
+char(3,84605).
+char(2,84606).
+char(8,84607).
+char(4,84608).
+char(m,84609).
+char(o,84610).
+char(p,84611).
+char(o,84612).
+char(o,84613).
+char(7,84614).
+char(3,84615).
+char(9,84616).
+char(1,84617).
+char(p,84618).
+char(5,84619).
+char(2,84620).
+char(8,84621).
+char(5,84622).
+char(p,84623).
+char(9,84624).
+char(1,84625).
+char(0,84626).
+char(3,84627).
+char(p,84628).
+char(9,84629).
+char(7,84630).
+char(5,84631).
+char(9,84632).
+char(c,84633).
+char(c,84634).
+char(p,84635).
+char(o,84636).
+char(p,84637).
+char(2,84638).
+char(4,84639).
+char(1,84640).
+char(8,84641).
+char(c,84642).
+char(c,84643).
+char(c,84644).
+char(p,84645).
+char(9,84646).
+char(5,84647).
+char(5,84648).
+char(3,84649).
+char(c,84650).
+char(c,84651).
+char(c,84652).
+char(c,84653).
+char(m,84654).
+char(o,84655).
+char(p,84656).
+char(8,84657).
+char(4,84658).
+char(8,84659).
+char(1,84660).
+char(c,84661).
+char(m,84662).
+char(7,84663).
+char(9,84664).
+char(4,84665).
+char(0,84666).
+char(c,84667).
+char(c,84668).
+char(c,84669).
+char(m,84670).
+char(9,84671).
+char(1,84672).
+char(4,84673).
+char(8,84674).
+char(m,84675).
+char(o,84676).
+char(p,84677).
+char(2,84678).
+char(4,84679).
+char(2,84680).
+char(0,84681).
+char(c,84682).
+char(c,84683).
+char(p,84684).
+char(o,84685).
+char(m,84686).
+char(6,84687).
+char(9,84688).
+char(1,84689).
+char(1,84690).
+char(p,84691).
+char(o,84692).
+char(m,84693).
+char(o,84694).
+char(p,84695).
+char(o,84696).
+char(o,84697).
+char(p,84698).
+char(o,84699).
+char(p,84700).
+char(5,84701).
+char(6,84702).
+char(2,84703).
+char(1,84704).
+char(m,84705).
+char(9,84706).
+char(9,84707).
+char(4,84708).
+char(9,84709).
+char(c,84710).
+char(m,84711).
+char(o,84712).
+char(6,84713).
+char(9,84714).
+char(7,84715).
+char(9,84716).
+char(m,84717).
+char(9,84718).
+char(8,84719).
+char(8,84720).
+char(c,84721).
+char(m,84722).
+char(4,84723).
+char(5,84724).
+char(4,84725).
+char(5,84726).
+char(c,84727).
+char(p,84728).
+char(3,84729).
+char(5,84730).
+char(8,84731).
+char(1,84732).
+char(c,84733).
+char(c,84734).
+char(p,84735).
+char(o,84736).
+char(p,84737).
+char(o,84738).
+char(p,84739).
+char(o,84740).
+char(m,84741).
+char(o,84742).
+char(m,84743).
+char(5,84744).
+char(6,84745).
+char(8,84746).
+char(1,84747).
+char(c,84748).
+char(p,84749).
+char(1,84750).
+char(9,84751).
+char(7,84752).
+char(2,84753).
+char(c,84754).
+char(c,84755).
+char(p,84756).
+char(2,84757).
+char(5,84758).
+char(1,84759).
+char(7,84760).
+char(c,84761).
+char(m,84762).
+char(5,84763).
+char(8,84764).
+char(2,84765).
+char(5,84766).
+char(c,84767).
+char(c,84768).
+char(c,84769).
+char(c,84770).
+char(p,84771).
+char(7,84772).
+char(0,84773).
+char(3,84774).
+char(2,84775).
+char(p,84776).
+char(5,84777).
+char(9,84778).
+char(9,84779).
+char(4,84780).
+char(m,84781).
+char(o,84782).
+char(p,84783).
+char(8,84784).
+char(7,84785).
+char(3,84786).
+char(p,84787).
+char(5,84788).
+char(8,84789).
+char(4,84790).
+char(7,84791).
+char(c,84792).
+char(c,84793).
+char(m,84794).
+char(o,84795).
+char(p,84796).
+char(8,84797).
+char(6,84798).
+char(3,84799).
+char(4,84800).
+char(p,84801).
+char(3,84802).
+char(5,84803).
+char(2,84804).
+char(5,84805).
+char(c,84806).
+char(c,84807).
+char(c,84808).
+char(p,84809).
+char(7,84810).
+char(4,84811).
+char(4,84812).
+char(1,84813).
+char(c,84814).
+char(p,84815).
+char(1,84816).
+char(6,84817).
+char(4,84818).
+char(7,84819).
+char(p,84820).
+char(7,84821).
+char(8,84822).
+char(3,84823).
+char(8,84824).
+char(c,84825).
+char(c,84826).
+char(c,84827).
+char(m,84828).
+char(7,84829).
+char(4,84830).
+char(6,84831).
+char(c,84832).
+char(p,84833).
+char(7,84834).
+char(9,84835).
+char(4,84836).
+char(c,84837).
+char(m,84838).
+char(3,84839).
+char(8,84840).
+char(5,84841).
+char(m,84842).
+char(3,84843).
+char(1,84844).
+char(7,84845).
+char(4,84846).
+char(m,84847).
+char(o,84848).
+char(o,84849).
+char(o,84850).
+char(o,84851).
+char(m,84852).
+char(o,84853).
+char(o,84854).
+char(m,84855).
+char(o,84856).
+char(m,84857).
+char(6,84858).
+char(1,84859).
+char(0,84860).
+char(6,84861).
+char(m,84862).
+char(8,84863).
+char(9,84864).
+char(8,84865).
+char(0,84866).
+char(c,84867).
+char(m,84868).
+char(o,84869).
+char(p,84870).
+char(o,84871).
+char(8,84872).
+char(1,84873).
+char(1,84874).
+char(9,84875).
+char(c,84876).
+char(p,84877).
+char(7,84878).
+char(6,84879).
+char(6,84880).
+char(1,84881).
+char(p,84882).
+char(6,84883).
+char(7,84884).
+char(4,84885).
+char(3,84886).
+char(c,84887).
+char(m,84888).
+char(3,84889).
+char(0,84890).
+char(7,84891).
+char(4,84892).
+char(c,84893).
+char(m,84894).
+char(4,84895).
+char(2,84896).
+char(0,84897).
+char(0,84898).
+char(c,84899).
+char(c,84900).
+char(c,84901).
+char(p,84902).
+char(4,84903).
+char(6,84904).
+char(1,84905).
+char(1,84906).
+char(c,84907).
+char(c,84908).
+char(c,84909).
+char(c,84910).
+char(c,84911).
+char(c,84912).
+char(c,84913).
+char(m,84914).
+char(o,84915).
+char(2,84916).
+char(6,84917).
+char(4,84918).
+char(c,84919).
+char(c,84920).
+char(c,84921).
+char(c,84922).
+char(m,84923).
+char(6,84924).
+char(9,84925).
+char(8,84926).
+char(1,84927).
+char(c,84928).
+char(p,84929).
+char(o,84930).
+char(o,84931).
+char(p,84932).
+char(o,84933).
+char(o,84934).
+char(m,84935).
+char(o,84936).
+char(2,84937).
+char(9,84938).
+char(0,84939).
+char(9,84940).
+char(p,84941).
+char(o,84942).
+char(m,84943).
+char(7,84944).
+char(6,84945).
+char(7,84946).
+char(4,84947).
+char(m,84948).
+char(7,84949).
+char(9,84950).
+char(8,84951).
+char(8,84952).
+char(c,84953).
+char(p,84954).
+char(o,84955).
+char(p,84956).
+char(o,84957).
+char(m,84958).
+char(o,84959).
+char(m,84960).
+char(8,84961).
+char(6,84962).
+char(6,84963).
+char(9,84964).
+char(c,84965).
+char(p,84966).
+char(o,84967).
+char(1,84968).
+char(7,84969).
+char(9,84970).
+char(6,84971).
+char(c,84972).
+char(c,84973).
+char(c,84974).
+char(m,84975).
+char(o,84976).
+char(m,84977).
+char(9,84978).
+char(4,84979).
+char(1,84980).
+char(5,84981).
+char(m,84982).
+char(4,84983).
+char(8,84984).
+char(0,84985).
+char(2,84986).
+char(c,84987).
+char(c,84988).
+char(p,84989).
+char(4,84990).
+char(6,84991).
+char(7,84992).
+char(m,84993).
+char(o,84994).
+char(p,84995).
+char(o,84996).
+char(m,84997).
+char(o,84998).
+char(p,84999).
+char(o,85000).
+char(p,85001).
+char(1,85002).
+char(0,85003).
+char(3,85004).
+char(9,85005).
+char(c,85006).
+char(p,85007).
+char(5,85008).
+char(1,85009).
+char(c,85010).
+char(c,85011).
+char(p,85012).
+char(o,85013).
+char(m,85014).
+char(o,85015).
+char(o,85016).
+char(p,85017).
+char(o,85018).
+char(p,85019).
+char(3,85020).
+char(1,85021).
+char(4,85022).
+char(8,85023).
+char(m,85024).
+char(o,85025).
+char(m,85026).
+char(1,85027).
+char(8,85028).
+char(9,85029).
+char(3,85030).
+char(c,85031).
+char(c,85032).
+char(c,85033).
+char(c,85034).
+char(m,85035).
+char(o,85036).
+char(o,85037).
+char(4,85038).
+char(3,85039).
+char(3,85040).
+char(0,85041).
+char(m,85042).
+char(o,85043).
+char(m,85044).
+char(o,85045).
+char(1,85046).
+char(6,85047).
+char(1,85048).
+char(2,85049).
+char(p,85050).
+char(4,85051).
+char(7,85052).
+char(1,85053).
+char(3,85054).
+char(c,85055).
+char(c,85056).
+char(c,85057).
+char(c,85058).
+char(c,85059).
+char(m,85060).
+char(8,85061).
+char(6,85062).
+char(5,85063).
+char(4,85064).
+char(c,85065).
+char(c,85066).
+char(c,85067).
+char(m,85068).
+char(5,85069).
+char(8,85070).
+char(4,85071).
+char(7,85072).
+char(p,85073).
+char(o,85074).
+char(m,85075).
+char(o,85076).
+char(p,85077).
+char(4,85078).
+char(7,85079).
+char(8,85080).
+char(7,85081).
+char(c,85082).
+char(p,85083).
+char(o,85084).
+char(m,85085).
+char(o,85086).
+char(o,85087).
+char(m,85088).
+char(o,85089).
+char(p,85090).
+char(o,85091).
+char(p,85092).
+char(5,85093).
+char(4,85094).
+char(5,85095).
+char(0,85096).
+char(p,85097).
+char(3,85098).
+char(9,85099).
+char(5,85100).
+char(6,85101).
+char(c,85102).
+char(m,85103).
+char(o,85104).
+char(o,85105).
+char(m,85106).
+char(3,85107).
+char(0,85108).
+char(2,85109).
+char(2,85110).
+char(m,85111).
+char(o,85112).
+char(o,85113).
+char(p,85114).
+char(6,85115).
+char(9,85116).
+char(5,85117).
+char(7,85118).
+char(c,85119).
+char(c,85120).
+char(p,85121).
+char(9,85122).
+char(9,85123).
+char(6,85124).
+char(7,85125).
+char(c,85126).
+char(c,85127).
+char(c,85128).
+char(p,85129).
+char(5,85130).
+char(9,85131).
+char(3,85132).
+char(1,85133).
+char(c,85134).
+char(m,85135).
+char(o,85136).
+char(2,85137).
+char(0,85138).
+char(1,85139).
+char(2,85140).
+char(m,85141).
+char(2,85142).
+char(6,85143).
+char(5,85144).
+char(c,85145).
+char(p,85146).
+char(o,85147).
+char(p,85148).
+char(o,85149).
+char(p,85150).
+char(1,85151).
+char(9,85152).
+char(2,85153).
+char(5,85154).
+char(m,85155).
+char(o,85156).
+char(o,85157).
+char(p,85158).
+char(o,85159).
+char(m,85160).
+char(8,85161).
+char(2,85162).
+char(p,85163).
+char(5,85164).
+char(1,85165).
+char(8,85166).
+char(7,85167).
+char(p,85168).
+char(o,85169).
+char(p,85170).
+char(7,85171).
+char(1,85172).
+char(1,85173).
+char(9,85174).
+char(p,85175).
+char(6,85176).
+char(0,85177).
+char(3,85178).
+char(8,85179).
+char(m,85180).
+char(7,85181).
+char(4,85182).
+char(2,85183).
+char(8,85184).
+char(c,85185).
+char(p,85186).
+char(o,85187).
+char(m,85188).
+char(4,85189).
+char(3,85190).
+char(4,85191).
+char(9,85192).
+char(m,85193).
+char(3,85194).
+char(2,85195).
+char(6,85196).
+char(7,85197).
+char(m,85198).
+char(1,85199).
+char(9,85200).
+char(0,85201).
+char(5,85202).
+char(m,85203).
+char(9,85204).
+char(8,85205).
+char(5,85206).
+char(2,85207).
+char(c,85208).
+char(c,85209).
+char(p,85210).
+char(o,85211).
+char(o,85212).
+char(m,85213).
+char(o,85214).
+char(p,85215).
+char(3,85216).
+char(7,85217).
+char(1,85218).
+char(9,85219).
+char(c,85220).
+char(m,85221).
+char(o,85222).
+char(p,85223).
+char(o,85224).
+char(p,85225).
+char(o,85226).
+char(m,85227).
+char(o,85228).
+char(o,85229).
+char(7,85230).
+char(1,85231).
+char(1,85232).
+char(0,85233).
+char(c,85234).
+char(m,85235).
+char(9,85236).
+char(6,85237).
+char(7,85238).
+char(8,85239).
+char(p,85240).
+char(2,85241).
+char(9,85242).
+char(0,85243).
+char(0,85244).
+char(m,85245).
+char(9,85246).
+char(0,85247).
+char(1,85248).
+char(2,85249).
+char(m,85250).
+char(o,85251).
+char(m,85252).
+char(3,85253).
+char(7,85254).
+char(0,85255).
+char(9,85256).
+char(p,85257).
+char(4,85258).
+char(9,85259).
+char(7,85260).
+char(5,85261).
+char(m,85262).
+char(6,85263).
+char(2,85264).
+char(0,85265).
+char(9,85266).
+char(p,85267).
+char(o,85268).
+char(m,85269).
+char(o,85270).
+char(o,85271).
+char(p,85272).
+char(o,85273).
+char(m,85274).
+char(1,85275).
+char(0,85276).
+char(3,85277).
+char(2,85278).
+char(p,85279).
+char(3,85280).
+char(0,85281).
+char(8,85282).
+char(7,85283).
+char(c,85284).
+char(p,85285).
+char(5,85286).
+char(1,85287).
+char(9,85288).
+char(9,85289).
+char(m,85290).
+char(o,85291).
+char(m,85292).
+char(3,85293).
+char(5,85294).
+char(9,85295).
+char(7,85296).
+char(m,85297).
+char(4,85298).
+char(2,85299).
+char(7,85300).
+char(4,85301).
+char(c,85302).
+char(c,85303).
+char(p,85304).
+char(4,85305).
+char(6,85306).
+char(5,85307).
+char(8,85308).
+char(c,85309).
+char(c,85310).
+char(m,85311).
+char(8,85312).
+char(1,85313).
+char(1,85314).
+char(1,85315).
+char(p,85316).
+char(o,85317).
+char(p,85318).
+char(o,85319).
+char(6,85320).
+char(9,85321).
+char(8,85322).
+char(4,85323).
+char(c,85324).
+char(c,85325).
+char(p,85326).
+char(o,85327).
+char(p,85328).
+char(8,85329).
+char(2,85330).
+char(8,85331).
+char(2,85332).
+char(m,85333).
+char(o,85334).
+char(o,85335).
+char(6,85336).
+char(2,85337).
+char(6,85338).
+char(9,85339).
+char(m,85340).
+char(3,85341).
+char(7,85342).
+char(2,85343).
+char(3,85344).
+char(m,85345).
+char(o,85346).
+char(8,85347).
+char(9,85348).
+char(0,85349).
+char(6,85350).
+char(m,85351).
+char(1,85352).
+char(4,85353).
+char(7,85354).
+char(1,85355).
+char(p,85356).
+char(o,85357).
+char(o,85358).
+char(p,85359).
+char(o,85360).
+char(m,85361).
+char(2,85362).
+char(0,85363).
+char(8,85364).
+char(6,85365).
+char(m,85366).
+char(8,85367).
+char(7,85368).
+char(8,85369).
+char(c,85370).
+char(p,85371).
+char(o,85372).
+char(p,85373).
+char(6,85374).
+char(8,85375).
+char(9,85376).
+char(4,85377).
+char(p,85378).
+char(o,85379).
+char(p,85380).
+char(5,85381).
+char(6,85382).
+char(1,85383).
+char(5,85384).
+char(p,85385).
+char(o,85386).
+char(m,85387).
+char(2,85388).
+char(5,85389).
+char(5,85390).
+char(1,85391).
+char(m,85392).
+char(o,85393).
+char(m,85394).
+char(9,85395).
+char(2,85396).
+char(6,85397).
+char(5,85398).
+char(m,85399).
+char(o,85400).
+char(o,85401).
+char(m,85402).
+char(o,85403).
+char(o,85404).
+char(o,85405).
+char(m,85406).
+char(o,85407).
+char(o,85408).
+char(m,85409).
+char(o,85410).
+char(p,85411).
+char(3,85412).
+char(3,85413).
+char(1,85414).
+char(c,85415).
+char(c,85416).
+char(c,85417).
+char(c,85418).
+char(m,85419).
+char(1,85420).
+char(9,85421).
+char(9,85422).
+char(1,85423).
+char(p,85424).
+char(5,85425).
+char(9,85426).
+char(4,85427).
+char(4,85428).
+char(c,85429).
+char(c,85430).
+char(c,85431).
+char(p,85432).
+char(o,85433).
+char(m,85434).
+char(o,85435).
+char(m,85436).
+char(4,85437).
+char(8,85438).
+char(8,85439).
+char(0,85440).
+char(m,85441).
+char(8,85442).
+char(0,85443).
+char(9,85444).
+char(7,85445).
+char(c,85446).
+char(c,85447).
+char(c,85448).
+char(m,85449).
+char(o,85450).
+char(o,85451).
+char(o,85452).
+char(6,85453).
+char(9,85454).
+char(6,85455).
+char(0,85456).
+char(c,85457).
+char(m,85458).
+char(9,85459).
+char(3,85460).
+char(2,85461).
+char(2,85462).
+char(p,85463).
+char(1,85464).
+char(3,85465).
+char(3,85466).
+char(7,85467).
+char(m,85468).
+char(o,85469).
+char(o,85470).
+char(5,85471).
+char(0,85472).
+char(7,85473).
+char(9,85474).
+char(p,85475).
+char(4,85476).
+char(3,85477).
+char(5,85478).
+char(0,85479).
+char(m,85480).
+char(9,85481).
+char(1,85482).
+char(3,85483).
+char(6,85484).
+char(c,85485).
+char(c,85486).
+char(c,85487).
+char(p,85488).
+char(2,85489).
+char(9,85490).
+char(8,85491).
+char(p,85492).
+char(1,85493).
+char(2,85494).
+char(0,85495).
+char(5,85496).
+char(c,85497).
+char(p,85498).
+char(5,85499).
+char(3,85500).
+char(7,85501).
+char(0,85502).
+char(p,85503).
+char(8,85504).
+char(3,85505).
+char(1,85506).
+char(1,85507).
+char(m,85508).
+char(o,85509).
+char(m,85510).
+char(2,85511).
+char(3,85512).
+char(4,85513).
+char(0,85514).
+char(m,85515).
+char(o,85516).
+char(p,85517).
+char(7,85518).
+char(4,85519).
+char(8,85520).
+char(c,85521).
+char(m,85522).
+char(3,85523).
+char(4,85524).
+char(7,85525).
+char(7,85526).
+char(c,85527).
+char(c,85528).
+char(c,85529).
+char(c,85530).
+char(m,85531).
+char(o,85532).
+char(p,85533).
+char(6,85534).
+char(0,85535).
+char(1,85536).
+char(2,85537).
+char(c,85538).
+char(m,85539).
+char(7,85540).
+char(2,85541).
+char(6,85542).
+char(4,85543).
+char(c,85544).
+char(p,85545).
+char(9,85546).
+char(1,85547).
+char(0,85548).
+char(5,85549).
+char(c,85550).
+char(c,85551).
+char(m,85552).
+char(o,85553).
+char(m,85554).
+char(o,85555).
+char(1,85556).
+char(1,85557).
+char(4,85558).
+char(4,85559).
+char(c,85560).
+char(c,85561).
+char(c,85562).
+char(c,85563).
+char(c,85564).
+char(c,85565).
+char(p,85566).
+char(3,85567).
+char(9,85568).
+char(4,85569).
+char(2,85570).
+char(c,85571).
+char(c,85572).
+char(c,85573).
+char(p,85574).
+char(1,85575).
+char(8,85576).
+char(1,85577).
+char(8,85578).
+char(m,85579).
+char(8,85580).
+char(9,85581).
+char(5,85582).
+char(1,85583).
+char(c,85584).
+char(c,85585).
+char(m,85586).
+char(o,85587).
+char(m,85588).
+char(6,85589).
+char(6,85590).
+char(5,85591).
+char(4,85592).
+char(c,85593).
+char(p,85594).
+char(o,85595).
+char(2,85596).
+char(4,85597).
+char(0,85598).
+char(7,85599).
+char(c,85600).
+char(c,85601).
+char(c,85602).
+char(p,85603).
+char(8,85604).
+char(9,85605).
+char(8,85606).
+char(5,85607).
+char(c,85608).
+char(c,85609).
+char(p,85610).
+char(6,85611).
+char(8,85612).
+char(7,85613).
+char(2,85614).
+char(m,85615).
+char(o,85616).
+char(m,85617).
+char(o,85618).
+char(3,85619).
+char(2,85620).
+char(1,85621).
+char(8,85622).
+char(p,85623).
+char(o,85624).
+char(m,85625).
+char(3,85626).
+char(1,85627).
+char(6,85628).
+char(3,85629).
+char(p,85630).
+char(o,85631).
+char(o,85632).
+char(p,85633).
+char(8,85634).
+char(9,85635).
+char(6,85636).
+char(6,85637).
+char(m,85638).
+char(8,85639).
+char(7,85640).
+char(4,85641).
+char(4,85642).
+char(c,85643).
+char(m,85644).
+char(o,85645).
+char(o,85646).
+char(o,85647).
+char(p,85648).
+char(9,85649).
+char(1,85650).
+char(4,85651).
+char(m,85652).
+char(4,85653).
+char(5,85654).
+char(0,85655).
+char(8,85656).
+char(c,85657).
+char(p,85658).
+char(o,85659).
+char(o,85660).
+char(3,85661).
+char(4,85662).
+char(1,85663).
+char(c,85664).
+char(c,85665).
+char(c,85666).
+char(c,85667).
+char(p,85668).
+char(o,85669).
+char(o,85670).
+char(m,85671).
+char(9,85672).
+char(0,85673).
+char(1,85674).
+char(1,85675).
+char(p,85676).
+char(o,85677).
+char(p,85678).
+char(2,85679).
+char(5,85680).
+char(1,85681).
+char(7,85682).
+char(c,85683).
+char(c,85684).
+char(p,85685).
+char(o,85686).
+char(m,85687).
+char(7,85688).
+char(2,85689).
+char(1,85690).
+char(c,85691).
+char(c,85692).
+char(p,85693).
+char(o,85694).
+char(m,85695).
+char(o,85696).
+char(o,85697).
+char(m,85698).
+char(4,85699).
+char(4,85700).
+char(1,85701).
+char(1,85702).
+char(p,85703).
+char(4,85704).
+char(1,85705).
+char(8,85706).
+char(0,85707).
+char(c,85708).
+char(c,85709).
+char(c,85710).
+char(c,85711).
+char(m,85712).
+char(6,85713).
+char(8,85714).
+char(4,85715).
+char(8,85716).
+char(c,85717).
+char(p,85718).
+char(o,85719).
+char(m,85720).
+char(5,85721).
+char(0,85722).
+char(3,85723).
+char(m,85724).
+char(o,85725).
+char(m,85726).
+char(o,85727).
+char(6,85728).
+char(7,85729).
+char(2,85730).
+char(5,85731).
+char(p,85732).
+char(1,85733).
+char(6,85734).
+char(0,85735).
+char(9,85736).
+char(m,85737).
+char(5,85738).
+char(9,85739).
+char(5,85740).
+char(0,85741).
+char(c,85742).
+char(p,85743).
+char(8,85744).
+char(7,85745).
+char(4,85746).
+char(3,85747).
+char(m,85748).
+char(o,85749).
+char(9,85750).
+char(6,85751).
+char(5,85752).
+char(p,85753).
+char(8,85754).
+char(5,85755).
+char(3,85756).
+char(2,85757).
+char(c,85758).
+char(p,85759).
+char(o,85760).
+char(p,85761).
+char(7,85762).
+char(3,85763).
+char(8,85764).
+char(3,85765).
+char(c,85766).
+char(c,85767).
+char(c,85768).
+char(p,85769).
+char(o,85770).
+char(m,85771).
+char(5,85772).
+char(4,85773).
+char(6,85774).
+char(9,85775).
+char(m,85776).
+char(o,85777).
+char(p,85778).
+char(o,85779).
+char(m,85780).
+char(3,85781).
+char(5,85782).
+char(4,85783).
+char(1,85784).
+char(c,85785).
+char(m,85786).
+char(7,85787).
+char(8,85788).
+char(7,85789).
+char(7,85790).
+char(c,85791).
+char(c,85792).
+char(c,85793).
+char(c,85794).
+char(c,85795).
+char(m,85796).
+char(o,85797).
+char(o,85798).
+char(m,85799).
+char(5,85800).
+char(4,85801).
+char(8,85802).
+char(2,85803).
+char(p,85804).
+char(3,85805).
+char(3,85806).
+char(8,85807).
+char(9,85808).
+char(m,85809).
+char(9,85810).
+char(9,85811).
+char(3,85812).
+char(4,85813).
+char(p,85814).
+char(o,85815).
+char(p,85816).
+char(3,85817).
+char(2,85818).
+char(7,85819).
+char(6,85820).
+char(c,85821).
+char(c,85822).
+char(c,85823).
+char(c,85824).
+char(p,85825).
+char(2,85826).
+char(3,85827).
+char(8,85828).
+char(c,85829).
+char(c,85830).
+char(c,85831).
+char(c,85832).
+char(m,85833).
+char(o,85834).
+char(p,85835).
+char(7,85836).
+char(5,85837).
+char(5,85838).
+char(0,85839).
+char(m,85840).
+char(3,85841).
+char(7,85842).
+char(2,85843).
+char(8,85844).
+char(c,85845).
+char(p,85846).
+char(9,85847).
+char(6,85848).
+char(4,85849).
+char(9,85850).
+char(m,85851).
+char(3,85852).
+char(0,85853).
+char(8,85854).
+char(9,85855).
+char(c,85856).
+char(c,85857).
+char(m,85858).
+char(o,85859).
+char(o,85860).
+char(p,85861).
+char(o,85862).
+char(o,85863).
+char(p,85864).
+char(1,85865).
+char(1,85866).
+char(8,85867).
+char(7,85868).
+char(c,85869).
+char(c,85870).
+char(p,85871).
+char(o,85872).
+char(o,85873).
+char(o,85874).
+char(m,85875).
+char(9,85876).
+char(8,85877).
+char(9,85878).
+char(6,85879).
+char(c,85880).
+char(p,85881).
+char(9,85882).
+char(8,85883).
+char(9,85884).
+char(6,85885).
+char(p,85886).
+char(o,85887).
+char(7,85888).
+char(7,85889).
+char(5,85890).
+char(5,85891).
+char(c,85892).
+char(m,85893).
+char(7,85894).
+char(3,85895).
+char(7,85896).
+char(6,85897).
+char(c,85898).
+char(p,85899).
+char(o,85900).
+char(p,85901).
+char(o,85902).
+char(o,85903).
+char(m,85904).
+char(o,85905).
+char(m,85906).
+char(3,85907).
+char(8,85908).
+char(3,85909).
+char(c,85910).
+char(c,85911).
+char(m,85912).
+char(9,85913).
+char(4,85914).
+char(5,85915).
+char(9,85916).
+char(m,85917).
+char(o,85918).
+char(m,85919).
+char(7,85920).
+char(1,85921).
+char(6,85922).
+char(0,85923).
+char(p,85924).
+char(o,85925).
+char(m,85926).
+char(1,85927).
+char(5,85928).
+char(8,85929).
+char(4,85930).
+char(c,85931).
+char(p,85932).
+char(o,85933).
+char(m,85934).
+char(9,85935).
+char(3,85936).
+char(5,85937).
+char(0,85938).
+char(p,85939).
+char(3,85940).
+char(9,85941).
+char(0,85942).
+char(6,85943).
+char(c,85944).
+char(c,85945).
+char(c,85946).
+char(c,85947).
+char(c,85948).
+char(c,85949).
+char(c,85950).
+char(p,85951).
+char(o,85952).
+char(m,85953).
+char(1,85954).
+char(0,85955).
+char(0,85956).
+char(4,85957).
+char(p,85958).
+char(o,85959).
+char(p,85960).
+char(o,85961).
+char(p,85962).
+char(o,85963).
+char(m,85964).
+char(4,85965).
+char(3,85966).
+char(1,85967).
+char(0,85968).
+char(c,85969).
+char(m,85970).
+char(o,85971).
+char(o,85972).
+char(m,85973).
+char(o,85974).
+char(p,85975).
+char(1,85976).
+char(0,85977).
+char(5,85978).
+char(1,85979).
+char(p,85980).
+char(7,85981).
+char(3,85982).
+char(8,85983).
+char(c,85984).
+char(m,85985).
+char(o,85986).
+char(m,85987).
+char(o,85988).
+char(m,85989).
+char(o,85990).
+char(p,85991).
+char(1,85992).
+char(2,85993).
+char(6,85994).
+char(4,85995).
+char(c,85996).
+char(p,85997).
+char(o,85998).
+char(o,85999).
+char(o,86000).
+char(1,86001).
+char(9,86002).
+char(7,86003).
+char(4,86004).
+char(p,86005).
+char(o,86006).
+char(p,86007).
+char(1,86008).
+char(8,86009).
+char(8,86010).
+char(c,86011).
+char(c,86012).
+char(c,86013).
+char(c,86014).
+char(p,86015).
+char(5,86016).
+char(5,86017).
+char(2,86018).
+char(3,86019).
+char(c,86020).
+char(c,86021).
+char(p,86022).
+char(o,86023).
+char(o,86024).
+char(m,86025).
+char(o,86026).
+char(p,86027).
+char(2,86028).
+char(0,86029).
+char(5,86030).
+char(0,86031).
+char(c,86032).
+char(c,86033).
+char(c,86034).
+char(m,86035).
+char(o,86036).
+char(p,86037).
+char(o,86038).
+char(p,86039).
+char(o,86040).
+char(m,86041).
+char(o,86042).
+char(4,86043).
+char(0,86044).
+char(5,86045).
+char(7,86046).
+char(c,86047).
+char(m,86048).
+char(8,86049).
+char(0,86050).
+char(2,86051).
+char(9,86052).
+char(c,86053).
+char(c,86054).
+char(p,86055).
+char(o,86056).
+char(o,86057).
+char(p,86058).
+char(1,86059).
+char(6,86060).
+char(2,86061).
+char(9,86062).
+char(m,86063).
+char(7,86064).
+char(5,86065).
+char(7,86066).
+char(c,86067).
+char(p,86068).
+char(4,86069).
+char(6,86070).
+char(0,86071).
+char(6,86072).
+char(p,86073).
+char(7,86074).
+char(4,86075).
+char(2,86076).
+char(5,86077).
+char(c,86078).
+char(m,86079).
+char(o,86080).
+char(4,86081).
+char(4,86082).
+char(1,86083).
+char(1,86084).
+char(p,86085).
+char(3,86086).
+char(9,86087).
+char(8,86088).
+char(7,86089).
+char(c,86090).
+char(p,86091).
+char(o,86092).
+char(m,86093).
+char(o,86094).
+char(2,86095).
+char(5,86096).
+char(6,86097).
+char(8,86098).
+char(m,86099).
+char(o,86100).
+char(m,86101).
+char(2,86102).
+char(2,86103).
+char(5,86104).
+char(5,86105).
+char(c,86106).
+char(c,86107).
+char(m,86108).
+char(1,86109).
+char(5,86110).
+char(5,86111).
+char(3,86112).
+char(p,86113).
+char(o,86114).
+char(p,86115).
+char(o,86116).
+char(p,86117).
+char(9,86118).
+char(1,86119).
+char(3,86120).
+char(m,86121).
+char(9,86122).
+char(1,86123).
+char(3,86124).
+char(p,86125).
+char(o,86126).
+char(m,86127).
+char(4,86128).
+char(6,86129).
+char(7,86130).
+char(3,86131).
+char(c,86132).
+char(p,86133).
+char(o,86134).
+char(m,86135).
+char(6,86136).
+char(2,86137).
+char(4,86138).
+char(4,86139).
+char(m,86140).
+char(2,86141).
+char(3,86142).
+char(0,86143).
+char(4,86144).
+char(p,86145).
+char(3,86146).
+char(7,86147).
+char(3,86148).
+char(2,86149).
+char(c,86150).
+char(c,86151).
+char(p,86152).
+char(o,86153).
+char(m,86154).
+char(o,86155).
+char(p,86156).
+char(o,86157).
+char(o,86158).
+char(1,86159).
+char(6,86160).
+char(3,86161).
+char(0,86162).
+char(p,86163).
+char(8,86164).
+char(4,86165).
+char(7,86166).
+char(3,86167).
+char(c,86168).
+char(c,86169).
+char(m,86170).
+char(2,86171).
+char(3,86172).
+char(6,86173).
+char(9,86174).
+char(c,86175).
+char(c,86176).
+char(c,86177).
+char(c,86178).
+char(m,86179).
+char(6,86180).
+char(4,86181).
+char(4,86182).
+char(3,86183).
+char(c,86184).
+char(c,86185).
+char(m,86186).
+char(o,86187).
+char(6,86188).
+char(4,86189).
+char(0,86190).
+char(7,86191).
+char(p,86192).
+char(2,86193).
+char(9,86194).
+char(3,86195).
+char(9,86196).
+char(p,86197).
+char(o,86198).
+char(p,86199).
+char(o,86200).
+char(9,86201).
+char(0,86202).
+char(3,86203).
+char(8,86204).
+char(c,86205).
+char(c,86206).
+char(c,86207).
+char(m,86208).
+char(o,86209).
+char(p,86210).
+char(o,86211).
+char(p,86212).
+char(7,86213).
+char(7,86214).
+char(9,86215).
+char(4,86216).
+char(c,86217).
+char(m,86218).
+char(9,86219).
+char(2,86220).
+char(4,86221).
+char(c,86222).
+char(m,86223).
+char(5,86224).
+char(6,86225).
+char(8,86226).
+char(8,86227).
+char(m,86228).
+char(o,86229).
+char(p,86230).
+char(5,86231).
+char(6,86232).
+char(8,86233).
+char(5,86234).
+char(c,86235).
+char(m,86236).
+char(o,86237).
+char(m,86238).
+char(o,86239).
+char(m,86240).
+char(o,86241).
+char(m,86242).
+char(o,86243).
+char(p,86244).
+char(8,86245).
+char(6,86246).
+char(3,86247).
+char(p,86248).
+char(o,86249).
+char(o,86250).
+char(p,86251).
+char(o,86252).
+char(p,86253).
+char(9,86254).
+char(8,86255).
+char(7,86256).
+char(3,86257).
+char(c,86258).
+char(c,86259).
+char(c,86260).
+char(c,86261).
+char(c,86262).
+char(c,86263).
+char(p,86264).
+char(4,86265).
+char(7,86266).
+char(6,86267).
+char(5,86268).
+char(m,86269).
+char(6,86270).
+char(4,86271).
+char(6,86272).
+char(6,86273).
+char(p,86274).
+char(o,86275).
+char(p,86276).
+char(9,86277).
+char(0,86278).
+char(2,86279).
+char(2,86280).
+char(c,86281).
+char(m,86282).
+char(4,86283).
+char(2,86284).
+char(7,86285).
+char(8,86286).
+char(m,86287).
+char(o,86288).
+char(m,86289).
+char(5,86290).
+char(9,86291).
+char(2,86292).
+char(0,86293).
+char(c,86294).
+char(m,86295).
+char(o,86296).
+char(m,86297).
+char(o,86298).
+char(5,86299).
+char(8,86300).
+char(7,86301).
+char(0,86302).
+char(c,86303).
+char(m,86304).
+char(o,86305).
+char(m,86306).
+char(o,86307).
+char(m,86308).
+char(o,86309).
+char(9,86310).
+char(2,86311).
+char(1,86312).
+char(2,86313).
+char(m,86314).
+char(4,86315).
+char(2,86316).
+char(3,86317).
+char(5,86318).
+char(m,86319).
+char(o,86320).
+char(o,86321).
+char(2,86322).
+char(8,86323).
+char(6,86324).
+char(7,86325).
+char(m,86326).
+char(6,86327).
+char(2,86328).
+char(5,86329).
+char(3,86330).
+char(c,86331).
+char(p,86332).
+char(o,86333).
+char(p,86334).
+char(8,86335).
+char(7,86336).
+char(9,86337).
+char(0,86338).
+char(m,86339).
+char(6,86340).
+char(6,86341).
+char(2,86342).
+char(6,86343).
+char(c,86344).
+char(c,86345).
+char(c,86346).
+char(c,86347).
+char(m,86348).
+char(1,86349).
+char(3,86350).
+char(4,86351).
+char(c,86352).
+char(c,86353).
+char(p,86354).
+char(o,86355).
+char(p,86356).
+char(o,86357).
+char(m,86358).
+char(o,86359).
+char(m,86360).
+char(2,86361).
+char(8,86362).
+char(8,86363).
+char(3,86364).
+char(m,86365).
+char(3,86366).
+char(7,86367).
+char(9,86368).
+char(2,86369).
+char(c,86370).
+char(c,86371).
+char(c,86372).
+char(c,86373).
+char(c,86374).
+char(c,86375).
+char(c,86376).
+char(c,86377).
+char(p,86378).
+char(o,86379).
+char(p,86380).
+char(1,86381).
+char(9,86382).
+char(0,86383).
+char(7,86384).
+char(p,86385).
+char(8,86386).
+char(9,86387).
+char(2,86388).
+char(3,86389).
+char(c,86390).
+char(m,86391).
+char(o,86392).
+char(7,86393).
+char(7,86394).
+char(4,86395).
+char(5,86396).
+char(p,86397).
+char(8,86398).
+char(9,86399).
+char(3,86400).
+char(4,86401).
+char(c,86402).
+char(p,86403).
+char(o,86404).
+char(m,86405).
+char(o,86406).
+char(m,86407).
+char(8,86408).
+char(9,86409).
+char(3,86410).
+char(0,86411).
+char(c,86412).
+char(m,86413).
+char(9,86414).
+char(9,86415).
+char(2,86416).
+char(7,86417).
+char(m,86418).
+char(o,86419).
+char(p,86420).
+char(1,86421).
+char(9,86422).
+char(5,86423).
+char(5,86424).
+char(m,86425).
+char(o,86426).
+char(m,86427).
+char(2,86428).
+char(5,86429).
+char(9,86430).
+char(4,86431).
+char(m,86432).
+char(o,86433).
+char(p,86434).
+char(7,86435).
+char(0,86436).
+char(3,86437).
+char(8,86438).
+char(m,86439).
+char(2,86440).
+char(4,86441).
+char(5,86442).
+char(5,86443).
+char(m,86444).
+char(1,86445).
+char(5,86446).
+char(2,86447).
+char(6,86448).
+char(c,86449).
+char(c,86450).
+char(c,86451).
+char(p,86452).
+char(7,86453).
+char(8,86454).
+char(3,86455).
+char(8,86456).
+char(m,86457).
+char(9,86458).
+char(0,86459).
+char(6,86460).
+char(8,86461).
+char(p,86462).
+char(8,86463).
+char(8,86464).
+char(2,86465).
+char(5,86466).
+char(c,86467).
+char(c,86468).
+char(c,86469).
+char(p,86470).
+char(o,86471).
+char(6,86472).
+char(2,86473).
+char(0,86474).
+char(8,86475).
+char(c,86476).
+char(p,86477).
+char(8,86478).
+char(1,86479).
+char(5,86480).
+char(9,86481).
+char(m,86482).
+char(o,86483).
+char(p,86484).
+char(o,86485).
+char(p,86486).
+char(4,86487).
+char(2,86488).
+char(2,86489).
+char(4,86490).
+char(m,86491).
+char(2,86492).
+char(9,86493).
+char(6,86494).
+char(6,86495).
+char(c,86496).
+char(m,86497).
+char(8,86498).
+char(6,86499).
+char(0,86500).
+char(m,86501).
+char(o,86502).
+char(p,86503).
+char(o,86504).
+char(p,86505).
+char(o,86506).
+char(m,86507).
+char(o,86508).
+char(p,86509).
+char(3,86510).
+char(1,86511).
+char(9,86512).
+char(c,86513).
+char(c,86514).
+char(m,86515).
+char(o,86516).
+char(o,86517).
+char(m,86518).
+char(o,86519).
+char(o,86520).
+char(m,86521).
+char(o,86522).
+char(p,86523).
+char(o,86524).
+char(m,86525).
+char(o,86526).
+char(o,86527).
+char(m,86528).
+char(o,86529).
+char(p,86530).
+char(o,86531).
+char(m,86532).
+char(5,86533).
+char(1,86534).
+char(6,86535).
+char(6,86536).
+char(c,86537).
+char(m,86538).
+char(7,86539).
+char(5,86540).
+char(6,86541).
+char(8,86542).
+char(c,86543).
+char(c,86544).
+char(c,86545).
+char(c,86546).
+char(c,86547).
+char(c,86548).
+char(m,86549).
+char(3,86550).
+char(4,86551).
+char(0,86552).
+char(2,86553).
+char(c,86554).
+char(c,86555).
+char(c,86556).
+char(p,86557).
+char(o,86558).
+char(m,86559).
+char(o,86560).
+char(7,86561).
+char(8,86562).
+char(5,86563).
+char(9,86564).
+char(c,86565).
+char(c,86566).
+char(m,86567).
+char(3,86568).
+char(3,86569).
+char(2,86570).
+char(4,86571).
+char(p,86572).
+char(o,86573).
+char(p,86574).
+char(o,86575).
+char(p,86576).
+char(8,86577).
+char(8,86578).
+char(5,86579).
+char(2,86580).
+char(p,86581).
+char(o,86582).
+char(p,86583).
+char(2,86584).
+char(0,86585).
+char(0,86586).
+char(8,86587).
+char(p,86588).
+char(o,86589).
+char(4,86590).
+char(8,86591).
+char(1,86592).
+char(6,86593).
+char(p,86594).
+char(7,86595).
+char(2,86596).
+char(7,86597).
+char(6,86598).
+char(m,86599).
+char(1,86600).
+char(8,86601).
+char(9,86602).
+char(6,86603).
+char(c,86604).
+char(p,86605).
+char(o,86606).
+char(4,86607).
+char(8,86608).
+char(2,86609).
+char(5,86610).
+char(c,86611).
+char(p,86612).
+char(o,86613).
+char(m,86614).
+char(4,86615).
+char(1,86616).
+char(1,86617).
+char(8,86618).
+char(p,86619).
+char(2,86620).
+char(0,86621).
+char(5,86622).
+char(6,86623).
+char(p,86624).
+char(o,86625).
+char(o,86626).
+char(p,86627).
+char(o,86628).
+char(5,86629).
+char(7,86630).
+char(0,86631).
+char(0,86632).
+char(m,86633).
+char(o,86634).
+char(o,86635).
+char(p,86636).
+char(3,86637).
+char(7,86638).
+char(2,86639).
+char(6,86640).
+char(c,86641).
+char(c,86642).
+char(c,86643).
+char(c,86644).
+char(m,86645).
+char(o,86646).
+char(m,86647).
+char(8,86648).
+char(9,86649).
+char(7,86650).
+char(4,86651).
+char(c,86652).
+char(c,86653).
+char(c,86654).
+char(c,86655).
+char(c,86656).
+char(c,86657).
+char(c,86658).
+char(c,86659).
+char(m,86660).
+char(9,86661).
+char(8,86662).
+char(8,86663).
+char(6,86664).
+char(c,86665).
+char(m,86666).
+char(2,86667).
+char(8,86668).
+char(5,86669).
+char(7,86670).
+char(p,86671).
+char(7,86672).
+char(9,86673).
+char(2,86674).
+char(1,86675).
+char(c,86676).
+char(c,86677).
+char(p,86678).
+char(o,86679).
+char(p,86680).
+char(1,86681).
+char(3,86682).
+char(4,86683).
+char(3,86684).
+char(c,86685).
+char(c,86686).
+char(c,86687).
+char(p,86688).
+char(5,86689).
+char(2,86690).
+char(0,86691).
+char(4,86692).
+char(c,86693).
+char(m,86694).
+char(8,86695).
+char(3,86696).
+char(9,86697).
+char(0,86698).
+char(m,86699).
+char(o,86700).
+char(1,86701).
+char(9,86702).
+char(4,86703).
+char(7,86704).
+char(c,86705).
+char(c,86706).
+char(p,86707).
+char(3,86708).
+char(9,86709).
+char(7,86710).
+char(3,86711).
+char(c,86712).
+char(p,86713).
+char(3,86714).
+char(2,86715).
+char(7,86716).
+char(1,86717).
+char(p,86718).
+char(o,86719).
+char(p,86720).
+char(o,86721).
+char(m,86722).
+char(2,86723).
+char(2,86724).
+char(1,86725).
+char(8,86726).
+char(c,86727).
+char(c,86728).
+char(c,86729).
+char(p,86730).
+char(9,86731).
+char(6,86732).
+char(8,86733).
+char(6,86734).
+char(m,86735).
+char(o,86736).
+char(o,86737).
+char(o,86738).
+char(o,86739).
+char(4,86740).
+char(1,86741).
+char(5,86742).
+char(3,86743).
+char(c,86744).
+char(p,86745).
+char(6,86746).
+char(7,86747).
+char(2,86748).
+char(7,86749).
+char(c,86750).
+char(c,86751).
+char(c,86752).
+char(m,86753).
+char(1,86754).
+char(7,86755).
+char(1,86756).
+char(3,86757).
+char(m,86758).
+char(2,86759).
+char(7,86760).
+char(7,86761).
+char(9,86762).
+char(c,86763).
+char(c,86764).
+char(m,86765).
+char(1,86766).
+char(3,86767).
+char(6,86768).
+char(0,86769).
+char(c,86770).
+char(p,86771).
+char(o,86772).
+char(m,86773).
+char(o,86774).
+char(o,86775).
+char(m,86776).
+char(o,86777).
+char(p,86778).
+char(o,86779).
+char(1,86780).
+char(1,86781).
+char(7,86782).
+char(2,86783).
+char(c,86784).
+char(m,86785).
+char(7,86786).
+char(7,86787).
+char(4,86788).
+char(8,86789).
+char(m,86790).
+char(o,86791).
+char(o,86792).
+char(m,86793).
+char(1,86794).
+char(9,86795).
+char(7,86796).
+char(3,86797).
+char(m,86798).
+char(1,86799).
+char(7,86800).
+char(6,86801).
+char(9,86802).
+char(p,86803).
+char(o,86804).
+char(p,86805).
+char(9,86806).
+char(9,86807).
+char(5,86808).
+char(7,86809).
+char(c,86810).
+char(c,86811).
+char(c,86812).
+char(m,86813).
+char(9,86814).
+char(0,86815).
+char(7,86816).
+char(2,86817).
+char(m,86818).
+char(o,86819).
+char(p,86820).
+char(8,86821).
+char(4,86822).
+char(5,86823).
+char(0,86824).
+char(c,86825).
+char(c,86826).
+char(c,86827).
+char(m,86828).
+char(o,86829).
+char(m,86830).
+char(7,86831).
+char(8,86832).
+char(5,86833).
+char(0,86834).
+char(p,86835).
+char(1,86836).
+char(9,86837).
+char(7,86838).
+char(4,86839).
+char(c,86840).
+char(m,86841).
+char(2,86842).
+char(2,86843).
+char(5,86844).
+char(c,86845).
+char(m,86846).
+char(1,86847).
+char(3,86848).
+char(2,86849).
+char(4,86850).
+char(c,86851).
+char(c,86852).
+char(p,86853).
+char(o,86854).
+char(p,86855).
+char(o,86856).
+char(m,86857).
+char(5,86858).
+char(4,86859).
+char(0,86860).
+char(8,86861).
+char(p,86862).
+char(6,86863).
+char(7,86864).
+char(5,86865).
+char(7,86866).
+char(m,86867).
+char(o,86868).
+char(m,86869).
+char(9,86870).
+char(4,86871).
+char(3,86872).
+char(1,86873).
+char(m,86874).
+char(o,86875).
+char(p,86876).
+char(7,86877).
+char(4,86878).
+char(8,86879).
+char(0,86880).
+char(c,86881).
+char(p,86882).
+char(1,86883).
+char(7,86884).
+char(7,86885).
+char(3,86886).
+char(m,86887).
+char(o,86888).
+char(m,86889).
+char(o,86890).
+char(m,86891).
+char(7,86892).
+char(8,86893).
+char(9,86894).
+char(1,86895).
+char(m,86896).
+char(o,86897).
+char(o,86898).
+char(p,86899).
+char(8,86900).
+char(9,86901).
+char(7,86902).
+char(9,86903).
+char(c,86904).
+char(c,86905).
+char(m,86906).
+char(o,86907).
+char(m,86908).
+char(o,86909).
+char(7,86910).
+char(2,86911).
+char(4,86912).
+char(5,86913).
+char(m,86914).
+char(o,86915).
+char(m,86916).
+char(4,86917).
+char(0,86918).
+char(0,86919).
+char(9,86920).
+char(c,86921).
+char(c,86922).
+char(m,86923).
+char(7,86924).
+char(3,86925).
+char(4,86926).
+char(0,86927).
+char(m,86928).
+char(9,86929).
+char(5,86930).
+char(2,86931).
+char(7,86932).
+char(p,86933).
+char(1,86934).
+char(9,86935).
+char(6,86936).
+char(7,86937).
+char(c,86938).
+char(p,86939).
+char(o,86940).
+char(o,86941).
+char(p,86942).
+char(o,86943).
+char(m,86944).
+char(o,86945).
+char(m,86946).
+char(9,86947).
+char(8,86948).
+char(0,86949).
+char(4,86950).
+char(c,86951).
+char(c,86952).
+char(c,86953).
+char(m,86954).
+char(8,86955).
+char(4,86956).
+char(3,86957).
+char(8,86958).
+char(p,86959).
+char(o,86960).
+char(o,86961).
+char(p,86962).
+char(3,86963).
+char(9,86964).
+char(2,86965).
+char(2,86966).
+char(p,86967).
+char(o,86968).
+char(1,86969).
+char(0,86970).
+char(0,86971).
+char(2,86972).
+char(c,86973).
+char(p,86974).
+char(5,86975).
+char(9,86976).
+char(2,86977).
+char(3,86978).
+char(c,86979).
+char(m,86980).
+char(o,86981).
+char(p,86982).
+char(o,86983).
+char(p,86984).
+char(o,86985).
+char(m,86986).
+char(3,86987).
+char(1,86988).
+char(4,86989).
+char(7,86990).
+char(c,86991).
+char(c,86992).
+char(p,86993).
+char(9,86994).
+char(7,86995).
+char(7,86996).
+char(9,86997).
+char(m,86998).
+char(o,86999).
+char(m,87000).
+char(1,87001).
+char(0,87002).
+char(5,87003).
+char(5,87004).
+char(c,87005).
+char(c,87006).
+char(c,87007).
+char(c,87008).
+char(p,87009).
+char(o,87010).
+char(m,87011).
+char(o,87012).
+char(o,87013).
+char(m,87014).
+char(9,87015).
+char(5,87016).
+char(2,87017).
+char(6,87018).
+char(c,87019).
+char(p,87020).
+char(o,87021).
+char(p,87022).
+char(o,87023).
+char(m,87024).
+char(1,87025).
+char(0,87026).
+char(7,87027).
+char(4,87028).
+char(m,87029).
+char(5,87030).
+char(6,87031).
+char(6,87032).
+char(3,87033).
+char(c,87034).
+char(m,87035).
+char(6,87036).
+char(6,87037).
+char(7,87038).
+char(1,87039).
+char(p,87040).
+char(o,87041).
+char(3,87042).
+char(8,87043).
+char(6,87044).
+char(7,87045).
+char(p,87046).
+char(o,87047).
+char(p,87048).
+char(3,87049).
+char(8,87050).
+char(6,87051).
+char(5,87052).
+char(p,87053).
+char(1,87054).
+char(8,87055).
+char(2,87056).
+char(7,87057).
+char(c,87058).
+char(c,87059).
+char(p,87060).
+char(o,87061).
+char(o,87062).
+char(p,87063).
+char(2,87064).
+char(2,87065).
+char(3,87066).
+char(8,87067).
+char(m,87068).
+char(o,87069).
+char(9,87070).
+char(8,87071).
+char(0,87072).
+char(4,87073).
+char(c,87074).
+char(c,87075).
+char(c,87076).
+char(c,87077).
+char(m,87078).
+char(o,87079).
+char(8,87080).
+char(4,87081).
+char(c,87082).
+char(c,87083).
+char(p,87084).
+char(2,87085).
+char(1,87086).
+char(3,87087).
+char(0,87088).
+char(c,87089).
+char(p,87090).
+char(o,87091).
+char(m,87092).
+char(8,87093).
+char(2,87094).
+char(5,87095).
+char(8,87096).
+char(m,87097).
+char(8,87098).
+char(5,87099).
+char(3,87100).
+char(3,87101).
+char(m,87102).
+char(o,87103).
+char(m,87104).
+char(o,87105).
+char(p,87106).
+char(2,87107).
+char(3,87108).
+char(4,87109).
+char(1,87110).
+char(c,87111).
+char(c,87112).
+char(m,87113).
+char(o,87114).
+char(1,87115).
+char(7,87116).
+char(9,87117).
+char(9,87118).
+char(c,87119).
+char(c,87120).
+char(c,87121).
+char(p,87122).
+char(5,87123).
+char(8,87124).
+char(4,87125).
+char(7,87126).
+char(m,87127).
+char(o,87128).
+char(p,87129).
+char(7,87130).
+char(5,87131).
+char(5,87132).
+char(4,87133).
+char(c,87134).
+char(p,87135).
+char(o,87136).
+char(o,87137).
+char(p,87138).
+char(o,87139).
+char(3,87140).
+char(1,87141).
+char(3,87142).
+char(3,87143).
+char(c,87144).
+char(p,87145).
+char(o,87146).
+char(m,87147).
+char(9,87148).
+char(0,87149).
+char(1,87150).
+char(2,87151).
+char(c,87152).
+char(p,87153).
+char(4,87154).
+char(4,87155).
+char(7,87156).
+char(2,87157).
+char(c,87158).
+char(m,87159).
+char(o,87160).
+char(o,87161).
+char(2,87162).
+char(5,87163).
+char(2,87164).
+char(8,87165).
+char(c,87166).
+char(m,87167).
+char(7,87168).
+char(9,87169).
+char(8,87170).
+char(2,87171).
+char(p,87172).
+char(7,87173).
+char(4,87174).
+char(9,87175).
+char(0,87176).
+char(c,87177).
+char(c,87178).
+char(m,87179).
+char(3,87180).
+char(8,87181).
+char(4,87182).
+char(0,87183).
+char(c,87184).
+char(m,87185).
+char(o,87186).
+char(o,87187).
+char(m,87188).
+char(3,87189).
+char(9,87190).
+char(4,87191).
+char(8,87192).
+char(c,87193).
+char(c,87194).
+char(p,87195).
+char(o,87196).
+char(o,87197).
+char(p,87198).
+char(9,87199).
+char(3,87200).
+char(3,87201).
+char(9,87202).
+char(c,87203).
+char(p,87204).
+char(2,87205).
+char(7,87206).
+char(0,87207).
+char(3,87208).
+char(m,87209).
+char(7,87210).
+char(8,87211).
+char(0,87212).
+char(0,87213).
+char(c,87214).
+char(m,87215).
+char(o,87216).
+char(1,87217).
+char(2,87218).
+char(9,87219).
+char(7,87220).
+char(c,87221).
+char(p,87222).
+char(o,87223).
+char(m,87224).
+char(6,87225).
+char(4,87226).
+char(7,87227).
+char(9,87228).
+char(p,87229).
+char(1,87230).
+char(0,87231).
+char(2,87232).
+char(0,87233).
+char(c,87234).
+char(c,87235).
+char(c,87236).
+char(c,87237).
+char(c,87238).
+char(c,87239).
+char(c,87240).
+char(c,87241).
+char(p,87242).
+char(o,87243).
+char(5,87244).
+char(2,87245).
+char(0,87246).
+char(1,87247).
+char(c,87248).
+char(m,87249).
+char(7,87250).
+char(9,87251).
+char(4,87252).
+char(8,87253).
+char(c,87254).
+char(m,87255).
+char(o,87256).
+char(p,87257).
+char(8,87258).
+char(7,87259).
+char(8,87260).
+char(8,87261).
+char(c,87262).
+char(c,87263).
+char(c,87264).
+char(m,87265).
+char(o,87266).
+char(m,87267).
+char(o,87268).
+char(o,87269).
+char(o,87270).
+char(p,87271).
+char(o,87272).
+char(m,87273).
+char(2,87274).
+char(0,87275).
+char(9,87276).
+char(2,87277).
+char(c,87278).
+char(c,87279).
+char(c,87280).
+char(c,87281).
+char(c,87282).
+char(m,87283).
+char(5,87284).
+char(9,87285).
+char(2,87286).
+char(7,87287).
+char(m,87288).
+char(o,87289).
+char(7,87290).
+char(0,87291).
+char(0,87292).
+char(7,87293).
+char(c,87294).
+char(m,87295).
+char(o,87296).
+char(p,87297).
+char(5,87298).
+char(1,87299).
+char(7,87300).
+char(6,87301).
+char(m,87302).
+char(o,87303).
+char(m,87304).
+char(5,87305).
+char(3,87306).
+char(4,87307).
+char(0,87308).
+char(c,87309).
+char(c,87310).
+char(p,87311).
+char(o,87312).
+char(m,87313).
+char(o,87314).
+char(m,87315).
+char(o,87316).
+char(p,87317).
+char(3,87318).
+char(8,87319).
+char(4,87320).
+char(7,87321).
+char(c,87322).
+char(c,87323).
+char(m,87324).
+char(5,87325).
+char(3,87326).
+char(3,87327).
+char(1,87328).
+char(c,87329).
+char(m,87330).
+char(o,87331).
+char(o,87332).
+char(p,87333).
+char(5,87334).
+char(0,87335).
+char(4,87336).
+char(c,87337).
+char(c,87338).
+char(m,87339).
+char(o,87340).
+char(4,87341).
+char(3,87342).
+char(7,87343).
+char(7,87344).
+char(m,87345).
+char(o,87346).
+char(p,87347).
+char(o,87348).
+char(o,87349).
+char(p,87350).
+char(o,87351).
+char(m,87352).
+char(5,87353).
+char(9,87354).
+char(7,87355).
+char(0,87356).
+char(m,87357).
+char(9,87358).
+char(4,87359).
+char(8,87360).
+char(9,87361).
+char(m,87362).
+char(o,87363).
+char(m,87364).
+char(o,87365).
+char(p,87366).
+char(6,87367).
+char(9,87368).
+char(0,87369).
+char(8,87370).
+char(p,87371).
+char(5,87372).
+char(6,87373).
+char(2,87374).
+char(1,87375).
+char(c,87376).
+char(c,87377).
+char(c,87378).
+char(p,87379).
+char(o,87380).
+char(m,87381).
+char(2,87382).
+char(1,87383).
+char(4,87384).
+char(2,87385).
+char(c,87386).
+char(m,87387).
+char(o,87388).
+char(p,87389).
+char(o,87390).
+char(m,87391).
+char(o,87392).
+char(m,87393).
+char(3,87394).
+char(8,87395).
+char(2,87396).
+char(2,87397).
+char(m,87398).
+char(2,87399).
+char(2,87400).
+char(8,87401).
+char(5,87402).
+char(p,87403).
+char(o,87404).
+char(8,87405).
+char(3,87406).
+char(5,87407).
+char(1,87408).
+char(p,87409).
+char(4,87410).
+char(3,87411).
+char(2,87412).
+char(7,87413).
+char(m,87414).
+char(2,87415).
+char(8,87416).
+char(1,87417).
+char(1,87418).
+char(p,87419).
+char(7,87420).
+char(2,87421).
+char(7,87422).
+char(3,87423).
+char(c,87424).
+char(p,87425).
+char(4,87426).
+char(8,87427).
+char(2,87428).
+char(1,87429).
+char(c,87430).
+char(c,87431).
+char(p,87432).
+char(o,87433).
+char(m,87434).
+char(7,87435).
+char(6,87436).
+char(8,87437).
+char(8,87438).
+char(p,87439).
+char(9,87440).
+char(5,87441).
+char(5,87442).
+char(4,87443).
+char(c,87444).
+char(m,87445).
+char(o,87446).
+char(m,87447).
+char(o,87448).
+char(p,87449).
+char(5,87450).
+char(3,87451).
+char(8,87452).
+char(2,87453).
+char(c,87454).
+char(p,87455).
+char(o,87456).
+char(m,87457).
+char(o,87458).
+char(o,87459).
+char(m,87460).
+char(o,87461).
+char(m,87462).
+char(o,87463).
+char(m,87464).
+char(o,87465).
+char(m,87466).
+char(o,87467).
+char(o,87468).
+char(m,87469).
+char(7,87470).
+char(9,87471).
+char(4,87472).
+char(5,87473).
+char(m,87474).
+char(8,87475).
+char(3,87476).
+char(0,87477).
+char(5,87478).
+char(m,87479).
+char(o,87480).
+char(m,87481).
+char(5,87482).
+char(7,87483).
+char(0,87484).
+char(2,87485).
+char(c,87486).
+char(c,87487).
+char(m,87488).
+char(o,87489).
+char(m,87490).
+char(o,87491).
+char(p,87492).
+char(2,87493).
+char(4,87494).
+char(9,87495).
+char(2,87496).
+char(c,87497).
+char(m,87498).
+char(o,87499).
+char(6,87500).
+char(1,87501).
+char(5,87502).
+char(4,87503).
+char(p,87504).
+char(o,87505).
+char(p,87506).
+char(8,87507).
+char(5,87508).
+char(4,87509).
+char(3,87510).
+char(p,87511).
+char(o,87512).
+char(o,87513).
+char(m,87514).
+char(1,87515).
+char(8,87516).
+char(0,87517).
+char(9,87518).
+char(c,87519).
+char(p,87520).
+char(4,87521).
+char(3,87522).
+char(0,87523).
+char(8,87524).
+char(c,87525).
+char(m,87526).
+char(8,87527).
+char(9,87528).
+char(8,87529).
+char(0,87530).
+char(c,87531).
+char(c,87532).
+char(m,87533).
+char(5,87534).
+char(1,87535).
+char(0,87536).
+char(2,87537).
+char(m,87538).
+char(o,87539).
+char(p,87540).
+char(6,87541).
+char(7,87542).
+char(6,87543).
+char(3,87544).
+char(m,87545).
+char(3,87546).
+char(1,87547).
+char(4,87548).
+char(6,87549).
+char(m,87550).
+char(8,87551).
+char(7,87552).
+char(5,87553).
+char(3,87554).
+char(p,87555).
+char(o,87556).
+char(m,87557).
+char(3,87558).
+char(9,87559).
+char(0,87560).
+char(p,87561).
+char(8,87562).
+char(1,87563).
+char(9,87564).
+char(0,87565).
+char(m,87566).
+char(o,87567).
+char(m,87568).
+char(o,87569).
+char(m,87570).
+char(o,87571).
+char(p,87572).
+char(o,87573).
+char(o,87574).
+char(m,87575).
+char(8,87576).
+char(1,87577).
+char(7,87578).
+char(0,87579).
+char(m,87580).
+char(8,87581).
+char(1,87582).
+char(3,87583).
+char(9,87584).
+char(m,87585).
+char(o,87586).
+char(p,87587).
+char(8,87588).
+char(1,87589).
+char(3,87590).
+char(0,87591).
+char(p,87592).
+char(o,87593).
+char(m,87594).
+char(o,87595).
+char(p,87596).
+char(9,87597).
+char(5,87598).
+char(8,87599).
+char(7,87600).
+char(c,87601).
+char(p,87602).
+char(5,87603).
+char(4,87604).
+char(m,87605).
+char(o,87606).
+char(m,87607).
+char(6,87608).
+char(5,87609).
+char(9,87610).
+char(7,87611).
+char(c,87612).
+char(m,87613).
+char(8,87614).
+char(6,87615).
+char(3,87616).
+char(8,87617).
+char(m,87618).
+char(6,87619).
+char(3,87620).
+char(1,87621).
+char(1,87622).
+char(m,87623).
+char(o,87624).
+char(m,87625).
+char(7,87626).
+char(0,87627).
+char(0,87628).
+char(4,87629).
+char(c,87630).
+char(m,87631).
+char(2,87632).
+char(2,87633).
+char(2,87634).
+char(1,87635).
+char(c,87636).
+char(p,87637).
+char(1,87638).
+char(1,87639).
+char(2,87640).
+char(6,87641).
+char(p,87642).
+char(4,87643).
+char(6,87644).
+char(5,87645).
+char(2,87646).
+char(c,87647).
+char(c,87648).
+char(m,87649).
+char(6,87650).
+char(5,87651).
+char(2,87652).
+char(5,87653).
+char(c,87654).
+char(m,87655).
+char(1,87656).
+char(4,87657).
+char(4,87658).
+char(p,87659).
+char(8,87660).
+char(2,87661).
+char(7,87662).
+char(c,87663).
+char(m,87664).
+char(8,87665).
+char(4,87666).
+char(0,87667).
+char(c,87668).
+char(c,87669).
+char(m,87670).
+char(o,87671).
+char(2,87672).
+char(2,87673).
+char(2,87674).
+char(6,87675).
+char(c,87676).
+char(c,87677).
+char(p,87678).
+char(4,87679).
+char(4,87680).
+char(6,87681).
+char(3,87682).
+char(m,87683).
+char(o,87684).
+char(p,87685).
+char(5,87686).
+char(4,87687).
+char(9,87688).
+char(9,87689).
+char(c,87690).
+char(c,87691).
+char(c,87692).
+char(c,87693).
+char(p,87694).
+char(o,87695).
+char(m,87696).
+char(5,87697).
+char(7,87698).
+char(4,87699).
+char(m,87700).
+char(7,87701).
+char(1,87702).
+char(7,87703).
+char(m,87704).
+char(o,87705).
+char(o,87706).
+char(p,87707).
+char(7,87708).
+char(5,87709).
+char(3,87710).
+char(2,87711).
+char(m,87712).
+char(4,87713).
+char(9,87714).
+char(8,87715).
+char(9,87716).
+char(m,87717).
+char(o,87718).
+char(7,87719).
+char(9,87720).
+char(9,87721).
+char(0,87722).
+char(m,87723).
+char(6,87724).
+char(0,87725).
+char(7,87726).
+char(4,87727).
+char(c,87728).
+char(p,87729).
+char(3,87730).
+char(5,87731).
+char(0,87732).
+char(4,87733).
+char(p,87734).
+char(o,87735).
+char(2,87736).
+char(7,87737).
+char(4,87738).
+char(7,87739).
+char(p,87740).
+char(1,87741).
+char(1,87742).
+char(5,87743).
+char(8,87744).
+char(m,87745).
+char(5,87746).
+char(2,87747).
+char(5,87748).
+char(9,87749).
+char(p,87750).
+char(1,87751).
+char(7,87752).
+char(6,87753).
+char(3,87754).
+char(c,87755).
+char(c,87756).
+char(p,87757).
+char(2,87758).
+char(3,87759).
+char(0,87760).
+char(2,87761).
+char(m,87762).
+char(1,87763).
+char(2,87764).
+char(5,87765).
+char(6,87766).
+char(c,87767).
+char(m,87768).
+char(9,87769).
+char(4,87770).
+char(1,87771).
+char(4,87772).
+char(p,87773).
+char(o,87774).
+char(p,87775).
+char(o,87776).
+char(m,87777).
+char(o,87778).
+char(m,87779).
+char(o,87780).
+char(8,87781).
+char(6,87782).
+char(4,87783).
+char(3,87784).
+char(m,87785).
+char(9,87786).
+char(9,87787).
+char(0,87788).
+char(p,87789).
+char(o,87790).
+char(m,87791).
+char(o,87792).
+char(m,87793).
+char(o,87794).
+char(o,87795).
+char(m,87796).
+char(o,87797).
+char(m,87798).
+char(o,87799).
+char(o,87800).
+char(m,87801).
+char(8,87802).
+char(5,87803).
+char(3,87804).
+char(4,87805).
+char(p,87806).
+char(3,87807).
+char(0,87808).
+char(2,87809).
+char(8,87810).
+char(c,87811).
+char(c,87812).
+char(c,87813).
+char(p,87814).
+char(1,87815).
+char(3,87816).
+char(5,87817).
+char(9,87818).
+char(c,87819).
+char(c,87820).
+char(c,87821).
+char(m,87822).
+char(o,87823).
+char(p,87824).
+char(5,87825).
+char(4,87826).
+char(0,87827).
+char(3,87828).
+char(c,87829).
+char(p,87830).
+char(4,87831).
+char(1,87832).
+char(4,87833).
+char(9,87834).
+char(m,87835).
+char(o,87836).
+char(2,87837).
+char(2,87838).
+char(2,87839).
+char(6,87840).
+char(p,87841).
+char(9,87842).
+char(0,87843).
+char(4,87844).
+char(9,87845).
+char(m,87846).
+char(o,87847).
+char(m,87848).
+char(9,87849).
+char(2,87850).
+char(2,87851).
+char(9,87852).
+char(c,87853).
+char(p,87854).
+char(2,87855).
+char(7,87856).
+char(7,87857).
+char(2,87858).
+char(m,87859).
+char(o,87860).
+char(p,87861).
+char(o,87862).
+char(p,87863).
+char(o,87864).
+char(o,87865).
+char(8,87866).
+char(4,87867).
+char(7,87868).
+char(1,87869).
+char(c,87870).
+char(c,87871).
+char(c,87872).
+char(m,87873).
+char(2,87874).
+char(9,87875).
+char(1,87876).
+char(6,87877).
+char(c,87878).
+char(m,87879).
+char(o,87880).
+char(m,87881).
+char(8,87882).
+char(0,87883).
+char(4,87884).
+char(1,87885).
+char(c,87886).
+char(p,87887).
+char(o,87888).
+char(p,87889).
+char(o,87890).
+char(p,87891).
+char(o,87892).
+char(p,87893).
+char(3,87894).
+char(0,87895).
+char(8,87896).
+char(2,87897).
+char(m,87898).
+char(o,87899).
+char(9,87900).
+char(3,87901).
+char(9,87902).
+char(6,87903).
+char(c,87904).
+char(c,87905).
+char(p,87906).
+char(4,87907).
+char(3,87908).
+char(5,87909).
+char(5,87910).
+char(c,87911).
+char(p,87912).
+char(1,87913).
+char(5,87914).
+char(7,87915).
+char(6,87916).
+char(c,87917).
+char(p,87918).
+char(o,87919).
+char(m,87920).
+char(4,87921).
+char(9,87922).
+char(8,87923).
+char(7,87924).
+char(m,87925).
+char(o,87926).
+char(m,87927).
+char(o,87928).
+char(p,87929).
+char(o,87930).
+char(5,87931).
+char(4,87932).
+char(3,87933).
+char(4,87934).
+char(c,87935).
+char(c,87936).
+char(c,87937).
+char(c,87938).
+char(m,87939).
+char(o,87940).
+char(m,87941).
+char(9,87942).
+char(9,87943).
+char(1,87944).
+char(9,87945).
+char(c,87946).
+char(p,87947).
+char(o,87948).
+char(p,87949).
+char(o,87950).
+char(m,87951).
+char(8,87952).
+char(4,87953).
+char(2,87954).
+char(4,87955).
+char(p,87956).
+char(o,87957).
+char(1,87958).
+char(6,87959).
+char(9,87960).
+char(m,87961).
+char(o,87962).
+char(o,87963).
+char(m,87964).
+char(o,87965).
+char(m,87966).
+char(o,87967).
+char(o,87968).
+char(p,87969).
+char(o,87970).
+char(9,87971).
+char(3,87972).
+char(7,87973).
+char(1,87974).
+char(p,87975).
+char(9,87976).
+char(8,87977).
+char(3,87978).
+char(c,87979).
+char(c,87980).
+char(m,87981).
+char(9,87982).
+char(8,87983).
+char(9,87984).
+char(9,87985).
+char(c,87986).
+char(m,87987).
+char(1,87988).
+char(4,87989).
+char(6,87990).
+char(9,87991).
+char(c,87992).
+char(p,87993).
+char(2,87994).
+char(2,87995).
+char(7,87996).
+char(5,87997).
+char(p,87998).
+char(o,87999).
+char(p,88000).
+char(6,88001).
+char(4,88002).
+char(2,88003).
+char(5,88004).
+char(c,88005).
+char(m,88006).
+char(4,88007).
+char(0,88008).
+char(2,88009).
+char(0,88010).
+char(c,88011).
+char(c,88012).
+char(c,88013).
+char(c,88014).
+char(m,88015).
+char(o,88016).
+char(p,88017).
+char(6,88018).
+char(2,88019).
+char(5,88020).
+char(3,88021).
+char(p,88022).
+char(6,88023).
+char(4,88024).
+char(8,88025).
+char(3,88026).
+char(c,88027).
+char(c,88028).
+char(c,88029).
+char(c,88030).
+char(m,88031).
+char(o,88032).
+char(p,88033).
+char(9,88034).
+char(7,88035).
+char(1,88036).
+char(8,88037).
+char(c,88038).
+char(c,88039).
+char(p,88040).
+char(o,88041).
+char(m,88042).
+char(o,88043).
+char(o,88044).
+char(m,88045).
+char(o,88046).
+char(m,88047).
+char(6,88048).
+char(6,88049).
+char(9,88050).
+char(7,88051).
+char(c,88052).
+char(c,88053).
+char(c,88054).
+char(c,88055).
+char(m,88056).
+char(8,88057).
+char(6,88058).
+char(8,88059).
+char(5,88060).
+char(m,88061).
+char(6,88062).
+char(9,88063).
+char(8,88064).
+char(2,88065).
+char(c,88066).
+char(c,88067).
+char(p,88068).
+char(o,88069).
+char(p,88070).
+char(7,88071).
+char(9,88072).
+char(5,88073).
+char(0,88074).
+char(c,88075).
+char(p,88076).
+char(9,88077).
+char(5,88078).
+char(4,88079).
+char(5,88080).
+char(m,88081).
+char(6,88082).
+char(3,88083).
+char(1,88084).
+char(0,88085).
+char(c,88086).
+char(c,88087).
+char(p,88088).
+char(o,88089).
+char(m,88090).
+char(9,88091).
+char(1,88092).
+char(4,88093).
+char(9,88094).
+char(m,88095).
+char(3,88096).
+char(1,88097).
+char(5,88098).
+char(0,88099).
+char(c,88100).
+char(c,88101).
+char(c,88102).
+char(c,88103).
+char(p,88104).
+char(o,88105).
+char(o,88106).
+char(p,88107).
+char(o,88108).
+char(6,88109).
+char(1,88110).
+char(2,88111).
+char(6,88112).
+char(m,88113).
+char(9,88114).
+char(0,88115).
+char(3,88116).
+char(c,88117).
+char(c,88118).
+char(p,88119).
+char(o,88120).
+char(m,88121).
+char(o,88122).
+char(o,88123).
+char(m,88124).
+char(1,88125).
+char(6,88126).
+char(5,88127).
+char(9,88128).
+char(p,88129).
+char(6,88130).
+char(6,88131).
+char(9,88132).
+char(1,88133).
+char(c,88134).
+char(m,88135).
+char(6,88136).
+char(2,88137).
+char(8,88138).
+char(7,88139).
+char(c,88140).
+char(c,88141).
+char(c,88142).
+char(c,88143).
+char(c,88144).
+char(c,88145).
+char(p,88146).
+char(2,88147).
+char(4,88148).
+char(2,88149).
+char(1,88150).
+char(c,88151).
+char(m,88152).
+char(4,88153).
+char(4,88154).
+char(3,88155).
+char(8,88156).
+char(c,88157).
+char(c,88158).
+char(c,88159).
+char(c,88160).
+char(c,88161).
+char(m,88162).
+char(o,88163).
+char(m,88164).
+char(o,88165).
+char(p,88166).
+char(o,88167).
+char(1,88168).
+char(8,88169).
+char(7,88170).
+char(8,88171).
+char(c,88172).
+char(c,88173).
+char(c,88174).
+char(c,88175).
+char(m,88176).
+char(o,88177).
+char(6,88178).
+char(5,88179).
+char(3,88180).
+char(5,88181).
+char(c,88182).
+char(c,88183).
+char(c,88184).
+char(m,88185).
+char(o,88186).
+char(m,88187).
+char(2,88188).
+char(0,88189).
+char(2,88190).
+char(6,88191).
+char(c,88192).
+char(c,88193).
+char(c,88194).
+char(c,88195).
+char(c,88196).
+char(c,88197).
+char(c,88198).
+char(c,88199).
+char(p,88200).
+char(o,88201).
+char(p,88202).
+char(8,88203).
+char(9,88204).
+char(6,88205).
+char(1,88206).
+char(c,88207).
+char(p,88208).
+char(4,88209).
+char(8,88210).
+char(2,88211).
+char(6,88212).
+char(c,88213).
+char(m,88214).
+char(o,88215).
+char(m,88216).
+char(1,88217).
+char(0,88218).
+char(8,88219).
+char(7,88220).
+char(c,88221).
+char(c,88222).
+char(m,88223).
+char(4,88224).
+char(2,88225).
+char(2,88226).
+char(0,88227).
+char(p,88228).
+char(o,88229).
+char(p,88230).
+char(o,88231).
+char(m,88232).
+char(o,88233).
+char(p,88234).
+char(1,88235).
+char(8,88236).
+char(1,88237).
+char(0,88238).
+char(p,88239).
+char(6,88240).
+char(4,88241).
+char(5,88242).
+char(6,88243).
+char(m,88244).
+char(o,88245).
+char(p,88246).
+char(1,88247).
+char(9,88248).
+char(1,88249).
+char(8,88250).
+char(c,88251).
+char(c,88252).
+char(p,88253).
+char(o,88254).
+char(m,88255).
+char(7,88256).
+char(1,88257).
+char(8,88258).
+char(8,88259).
+char(m,88260).
+char(2,88261).
+char(8,88262).
+char(4,88263).
+char(3,88264).
+char(p,88265).
+char(o,88266).
+char(p,88267).
+char(1,88268).
+char(8,88269).
+char(3,88270).
+char(5,88271).
+char(c,88272).
+char(p,88273).
+char(9,88274).
+char(1,88275).
+char(9,88276).
+char(5,88277).
+char(c,88278).
+char(p,88279).
+char(o,88280).
+char(m,88281).
+char(3,88282).
+char(5,88283).
+char(7,88284).
+char(8,88285).
+char(c,88286).
+char(c,88287).
+char(c,88288).
+char(p,88289).
+char(6,88290).
+char(5,88291).
+char(0,88292).
+char(2,88293).
+char(c,88294).
+char(p,88295).
+char(7,88296).
+char(5,88297).
+char(7,88298).
+char(4,88299).
+char(m,88300).
+char(4,88301).
+char(2,88302).
+char(6,88303).
+char(3,88304).
+char(p,88305).
+char(6,88306).
+char(4,88307).
+char(4,88308).
+char(7,88309).
+char(p,88310).
+char(o,88311).
+char(o,88312).
+char(p,88313).
+char(8,88314).
+char(1,88315).
+char(4,88316).
+char(9,88317).
+char(c,88318).
+char(c,88319).
+char(p,88320).
+char(9,88321).
+char(1,88322).
+char(3,88323).
+char(7,88324).
+char(m,88325).
+char(o,88326).
+char(p,88327).
+char(o,88328).
+char(4,88329).
+char(3,88330).
+char(9,88331).
+char(9,88332).
+char(c,88333).
+char(p,88334).
+char(o,88335).
+char(m,88336).
+char(o,88337).
+char(p,88338).
+char(o,88339).
+char(p,88340).
+char(4,88341).
+char(8,88342).
+char(6,88343).
+char(0,88344).
+char(p,88345).
+char(5,88346).
+char(6,88347).
+char(9,88348).
+char(9,88349).
+char(p,88350).
+char(4,88351).
+char(4,88352).
+char(5,88353).
+char(2,88354).
+char(p,88355).
+char(o,88356).
+char(m,88357).
+char(7,88358).
+char(7,88359).
+char(1,88360).
+char(2,88361).
+char(m,88362).
+char(o,88363).
+char(4,88364).
+char(2,88365).
+char(9,88366).
+char(1,88367).
+char(m,88368).
+char(o,88369).
+char(p,88370).
+char(o,88371).
+char(p,88372).
+char(o,88373).
+char(4,88374).
+char(5,88375).
+char(3,88376).
+char(3,88377).
+char(m,88378).
+char(o,88379).
+char(o,88380).
+char(p,88381).
+char(o,88382).
+char(p,88383).
+char(o,88384).
+char(p,88385).
+char(7,88386).
+char(9,88387).
+char(5,88388).
+char(1,88389).
+char(p,88390).
+char(5,88391).
+char(6,88392).
+char(8,88393).
+char(0,88394).
+char(m,88395).
+char(9,88396).
+char(5,88397).
+char(5,88398).
+char(2,88399).
+char(c,88400).
+char(c,88401).
+char(p,88402).
+char(1,88403).
+char(3,88404).
+char(0,88405).
+char(6,88406).
+char(c,88407).
+char(c,88408).
+char(p,88409).
+char(o,88410).
+char(m,88411).
+char(8,88412).
+char(4,88413).
+char(9,88414).
+char(6,88415).
+char(p,88416).
+char(o,88417).
+char(m,88418).
+char(o,88419).
+char(1,88420).
+char(3,88421).
+char(1,88422).
+char(7,88423).
+char(c,88424).
+char(p,88425).
+char(o,88426).
+char(1,88427).
+char(8,88428).
+char(7,88429).
+char(3,88430).
+char(p,88431).
+char(8,88432).
+char(1,88433).
+char(6,88434).
+char(5,88435).
+char(p,88436).
+char(6,88437).
+char(0,88438).
+char(0,88439).
+char(8,88440).
+char(c,88441).
+char(c,88442).
+char(m,88443).
+char(7,88444).
+char(0,88445).
+char(2,88446).
+char(9,88447).
+char(c,88448).
+char(c,88449).
+char(c,88450).
+char(m,88451).
+char(o,88452).
+char(3,88453).
+char(3,88454).
+char(9,88455).
+char(0,88456).
+char(c,88457).
+char(c,88458).
+char(c,88459).
+char(m,88460).
+char(o,88461).
+char(p,88462).
+char(6,88463).
+char(2,88464).
+char(6,88465).
+char(c,88466).
+char(m,88467).
+char(7,88468).
+char(6,88469).
+char(5,88470).
+char(1,88471).
+char(m,88472).
+char(4,88473).
+char(9,88474).
+char(2,88475).
+char(1,88476).
+char(c,88477).
+char(p,88478).
+char(7,88479).
+char(4,88480).
+char(7,88481).
+char(c,88482).
+char(c,88483).
+char(c,88484).
+char(m,88485).
+char(o,88486).
+char(p,88487).
+char(o,88488).
+char(m,88489).
+char(o,88490).
+char(o,88491).
+char(p,88492).
+char(4,88493).
+char(5,88494).
+char(7,88495).
+char(4,88496).
+char(c,88497).
+char(m,88498).
+char(o,88499).
+char(o,88500).
+char(m,88501).
+char(4,88502).
+char(5,88503).
+char(0,88504).
+char(3,88505).
+char(c,88506).
+char(m,88507).
+char(2,88508).
+char(5,88509).
+char(2,88510).
+char(3,88511).
+char(c,88512).
+char(p,88513).
+char(o,88514).
+char(m,88515).
+char(o,88516).
+char(m,88517).
+char(6,88518).
+char(4,88519).
+char(5,88520).
+char(3,88521).
+char(c,88522).
+char(c,88523).
+char(c,88524).
+char(p,88525).
+char(3,88526).
+char(3,88527).
+char(0,88528).
+char(4,88529).
+char(m,88530).
+char(2,88531).
+char(9,88532).
+char(0,88533).
+char(0,88534).
+char(p,88535).
+char(5,88536).
+char(0,88537).
+char(9,88538).
+char(2,88539).
+char(p,88540).
+char(1,88541).
+char(9,88542).
+char(7,88543).
+char(8,88544).
+char(c,88545).
+char(m,88546).
+char(3,88547).
+char(1,88548).
+char(7,88549).
+char(2,88550).
+char(c,88551).
+char(c,88552).
+char(p,88553).
+char(o,88554).
+char(m,88555).
+char(o,88556).
+char(m,88557).
+char(8,88558).
+char(5,88559).
+char(7,88560).
+char(8,88561).
+char(p,88562).
+char(9,88563).
+char(5,88564).
+char(7,88565).
+char(7,88566).
+char(c,88567).
+char(c,88568).
+char(c,88569).
+char(c,88570).
+char(c,88571).
+char(c,88572).
+char(c,88573).
+char(m,88574).
+char(8,88575).
+char(5,88576).
+char(8,88577).
+char(2,88578).
+char(p,88579).
+char(o,88580).
+char(o,88581).
+char(p,88582).
+char(7,88583).
+char(7,88584).
+char(9,88585).
+char(8,88586).
+char(m,88587).
+char(6,88588).
+char(9,88589).
+char(5,88590).
+char(0,88591).
+char(c,88592).
+char(p,88593).
+char(4,88594).
+char(6,88595).
+char(8,88596).
+char(8,88597).
+char(p,88598).
+char(o,88599).
+char(p,88600).
+char(1,88601).
+char(5,88602).
+char(4,88603).
+char(5,88604).
+char(c,88605).
+char(m,88606).
+char(6,88607).
+char(1,88608).
+char(1,88609).
+char(4,88610).
+char(c,88611).
+char(m,88612).
+char(o,88613).
+char(p,88614).
+char(5,88615).
+char(5,88616).
+char(c,88617).
+char(m,88618).
+char(o,88619).
+char(5,88620).
+char(0,88621).
+char(4,88622).
+char(5,88623).
+char(c,88624).
+char(m,88625).
+char(o,88626).
+char(p,88627).
+char(o,88628).
+char(m,88629).
+char(o,88630).
+char(m,88631).
+char(o,88632).
+char(2,88633).
+char(5,88634).
+char(6,88635).
+char(6,88636).
+char(c,88637).
+char(m,88638).
+char(5,88639).
+char(6,88640).
+char(4,88641).
+char(3,88642).
+char(p,88643).
+char(3,88644).
+char(7,88645).
+char(6,88646).
+char(0,88647).
+char(c,88648).
+char(m,88649).
+char(7,88650).
+char(7,88651).
+char(8,88652).
+char(9,88653).
+char(c,88654).
+char(m,88655).
+char(6,88656).
+char(9,88657).
+char(2,88658).
+char(6,88659).
+char(c,88660).
+char(c,88661).
+char(p,88662).
+char(2,88663).
+char(6,88664).
+char(8,88665).
+char(5,88666).
+char(c,88667).
+char(c,88668).
+char(c,88669).
+char(c,88670).
+char(p,88671).
+char(o,88672).
+char(6,88673).
+char(9,88674).
+char(0,88675).
+char(p,88676).
+char(4,88677).
+char(5,88678).
+char(9,88679).
+char(6,88680).
+char(p,88681).
+char(o,88682).
+char(m,88683).
+char(7,88684).
+char(0,88685).
+char(7,88686).
+char(9,88687).
+char(c,88688).
+char(c,88689).
+char(p,88690).
+char(o,88691).
+char(m,88692).
+char(6,88693).
+char(6,88694).
+char(1,88695).
+char(c,88696).
+char(c,88697).
+char(c,88698).
+char(p,88699).
+char(2,88700).
+char(2,88701).
+char(2,88702).
+char(0,88703).
+char(c,88704).
+char(c,88705).
+char(m,88706).
+char(4,88707).
+char(1,88708).
+char(3,88709).
+char(1,88710).
+char(c,88711).
+char(c,88712).
+char(p,88713).
+char(4,88714).
+char(9,88715).
+char(8,88716).
+char(9,88717).
+char(c,88718).
+char(m,88719).
+char(o,88720).
+char(m,88721).
+char(o,88722).
+char(p,88723).
+char(o,88724).
+char(p,88725).
+char(5,88726).
+char(2,88727).
+char(4,88728).
+char(5,88729).
+char(p,88730).
+char(o,88731).
+char(6,88732).
+char(0,88733).
+char(5,88734).
+char(2,88735).
+char(c,88736).
+char(m,88737).
+char(8,88738).
+char(6,88739).
+char(5,88740).
+char(c,88741).
+char(c,88742).
+char(c,88743).
+char(c,88744).
+char(c,88745).
+char(p,88746).
+char(6,88747).
+char(0,88748).
+char(4,88749).
+char(6,88750).
+char(m,88751).
+char(o,88752).
+char(9,88753).
+char(4,88754).
+char(8,88755).
+char(4,88756).
+char(c,88757).
+char(c,88758).
+char(c,88759).
+char(p,88760).
+char(3,88761).
+char(1,88762).
+char(8,88763).
+char(c,88764).
+char(m,88765).
+char(2,88766).
+char(9,88767).
+char(2,88768).
+char(5,88769).
+char(c,88770).
+char(c,88771).
+char(p,88772).
+char(3,88773).
+char(9,88774).
+char(4,88775).
+char(4,88776).
+char(p,88777).
+char(o,88778).
+char(m,88779).
+char(9,88780).
+char(7,88781).
+char(6,88782).
+char(2,88783).
+char(p,88784).
+char(o,88785).
+char(m,88786).
+char(o,88787).
+char(7,88788).
+char(6,88789).
+char(3,88790).
+char(9,88791).
+char(c,88792).
+char(c,88793).
+char(m,88794).
+char(5,88795).
+char(5,88796).
+char(9,88797).
+char(m,88798).
+char(1,88799).
+char(7,88800).
+char(5,88801).
+char(7,88802).
+char(p,88803).
+char(o,88804).
+char(2,88805).
+char(6,88806).
+char(4,88807).
+char(9,88808).
+char(c,88809).
+char(c,88810).
+char(c,88811).
+char(c,88812).
+char(p,88813).
+char(2,88814).
+char(8,88815).
+char(3,88816).
+char(8,88817).
+char(c,88818).
+char(c,88819).
+char(c,88820).
+char(c,88821).
+char(c,88822).
+char(p,88823).
+char(4,88824).
+char(1,88825).
+char(2,88826).
+char(5,88827).
+char(p,88828).
+char(1,88829).
+char(2,88830).
+char(0,88831).
+char(2,88832).
+char(p,88833).
+char(9,88834).
+char(9,88835).
+char(3,88836).
+char(4,88837).
+char(m,88838).
+char(2,88839).
+char(5,88840).
+char(1,88841).
+char(1,88842).
+char(m,88843).
+char(6,88844).
+char(4,88845).
+char(6,88846).
+char(8,88847).
+char(c,88848).
+char(p,88849).
+char(o,88850).
+char(m,88851).
+char(7,88852).
+char(1,88853).
+char(3,88854).
+char(6,88855).
+char(c,88856).
+char(m,88857).
+char(o,88858).
+char(m,88859).
+char(2,88860).
+char(0,88861).
+char(9,88862).
+char(5,88863).
+char(m,88864).
+char(9,88865).
+char(9,88866).
+char(3,88867).
+char(c,88868).
+char(c,88869).
+char(m,88870).
+char(o,88871).
+char(m,88872).
+char(o,88873).
+char(p,88874).
+char(7,88875).
+char(6,88876).
+char(5,88877).
+char(4,88878).
+char(p,88879).
+char(o,88880).
+char(m,88881).
+char(o,88882).
+char(o,88883).
+char(o,88884).
+char(m,88885).
+char(o,88886).
+char(m,88887).
+char(o,88888).
+char(p,88889).
+char(1,88890).
+char(1,88891).
+char(0,88892).
+char(8,88893).
+char(m,88894).
+char(o,88895).
+char(m,88896).
+char(o,88897).
+char(p,88898).
+char(5,88899).
+char(6,88900).
+char(3,88901).
+char(5,88902).
+char(p,88903).
+char(6,88904).
+char(6,88905).
+char(0,88906).
+char(5,88907).
+char(m,88908).
+char(1,88909).
+char(4,88910).
+char(8,88911).
+char(9,88912).
+char(m,88913).
+char(o,88914).
+char(p,88915).
+char(o,88916).
+char(8,88917).
+char(2,88918).
+char(8,88919).
+char(5,88920).
+char(m,88921).
+char(o,88922).
+char(o,88923).
+char(p,88924).
+char(1,88925).
+char(3,88926).
+char(2,88927).
+char(5,88928).
+char(c,88929).
+char(c,88930).
+char(p,88931).
+char(o,88932).
+char(p,88933).
+char(7,88934).
+char(5,88935).
+char(0,88936).
+char(0,88937).
+char(p,88938).
+char(o,88939).
+char(p,88940).
+char(o,88941).
+char(p,88942).
+char(o,88943).
+char(m,88944).
+char(o,88945).
+char(m,88946).
+char(o,88947).
+char(p,88948).
+char(8,88949).
+char(4,88950).
+char(5,88951).
+char(7,88952).
+char(c,88953).
+char(c,88954).
+char(c,88955).
+char(c,88956).
+char(c,88957).
+char(p,88958).
+char(7,88959).
+char(4,88960).
+char(8,88961).
+char(4,88962).
+char(m,88963).
+char(o,88964).
+char(m,88965).
+char(6,88966).
+char(3,88967).
+char(0,88968).
+char(1,88969).
+char(c,88970).
+char(m,88971).
+char(4,88972).
+char(1,88973).
+char(0,88974).
+char(2,88975).
+char(c,88976).
+char(c,88977).
+char(c,88978).
+char(p,88979).
+char(8,88980).
+char(1,88981).
+char(9,88982).
+char(8,88983).
+char(c,88984).
+char(c,88985).
+char(c,88986).
+char(p,88987).
+char(o,88988).
+char(p,88989).
+char(9,88990).
+char(4,88991).
+char(9,88992).
+char(5,88993).
+char(c,88994).
+char(c,88995).
+char(p,88996).
+char(o,88997).
+char(p,88998).
+char(3,88999).
+char(4,89000).
+char(3,89001).
+char(8,89002).
+char(c,89003).
+char(m,89004).
+char(o,89005).
+char(6,89006).
+char(9,89007).
+char(1,89008).
+char(0,89009).
+char(m,89010).
+char(1,89011).
+char(0,89012).
+char(9,89013).
+char(3,89014).
+char(c,89015).
+char(m,89016).
+char(3,89017).
+char(3,89018).
+char(9,89019).
+char(7,89020).
+char(c,89021).
+char(c,89022).
+char(c,89023).
+char(m,89024).
+char(o,89025).
+char(m,89026).
+char(6,89027).
+char(2,89028).
+char(4,89029).
+char(6,89030).
+char(m,89031).
+char(1,89032).
+char(3,89033).
+char(8,89034).
+char(6,89035).
+char(c,89036).
+char(m,89037).
+char(5,89038).
+char(8,89039).
+char(0,89040).
+char(2,89041).
+char(p,89042).
+char(o,89043).
+char(p,89044).
+char(3,89045).
+char(6,89046).
+char(7,89047).
+char(p,89048).
+char(o,89049).
+char(o,89050).
+char(7,89051).
+char(5,89052).
+char(1,89053).
+char(7,89054).
+char(c,89055).
+char(p,89056).
+char(5,89057).
+char(2,89058).
+char(0,89059).
+char(9,89060).
+char(p,89061).
+char(o,89062).
+char(m,89063).
+char(5,89064).
+char(3,89065).
+char(1,89066).
+char(5,89067).
+char(m,89068).
+char(3,89069).
+char(4,89070).
+char(9,89071).
+char(2,89072).
+char(c,89073).
+char(m,89074).
+char(2,89075).
+char(7,89076).
+char(6,89077).
+char(8,89078).
+char(c,89079).
+char(c,89080).
+char(c,89081).
+char(m,89082).
+char(o,89083).
+char(m,89084).
+char(3,89085).
+char(1,89086).
+char(2,89087).
+char(9,89088).
+char(c,89089).
+char(c,89090).
+char(m,89091).
+char(o,89092).
+char(p,89093).
+char(o,89094).
+char(p,89095).
+char(o,89096).
+char(p,89097).
+char(2,89098).
+char(2,89099).
+char(3,89100).
+char(4,89101).
+char(c,89102).
+char(c,89103).
+char(c,89104).
+char(m,89105).
+char(4,89106).
+char(1,89107).
+char(2,89108).
+char(5,89109).
+char(c,89110).
+char(p,89111).
+char(5,89112).
+char(5,89113).
+char(6,89114).
+char(6,89115).
+char(p,89116).
+char(o,89117).
+char(o,89118).
+char(p,89119).
+char(9,89120).
+char(9,89121).
+char(9,89122).
+char(7,89123).
+char(c,89124).
+char(m,89125).
+char(3,89126).
+char(7,89127).
+char(1,89128).
+char(2,89129).
+char(c,89130).
+char(p,89131).
+char(o,89132).
+char(m,89133).
+char(6,89134).
+char(5,89135).
+char(1,89136).
+char(0,89137).
+char(p,89138).
+char(o,89139).
+char(p,89140).
+char(2,89141).
+char(6,89142).
+char(9,89143).
+char(4,89144).
+char(c,89145).
+char(p,89146).
+char(7,89147).
+char(8,89148).
+char(6,89149).
+char(4,89150).
+char(m,89151).
+char(5,89152).
+char(5,89153).
+char(2,89154).
+char(7,89155).
+char(m,89156).
+char(o,89157).
+char(o,89158).
+char(4,89159).
+char(5,89160).
+char(4,89161).
+char(p,89162).
+char(2,89163).
+char(2,89164).
+char(2,89165).
+char(9,89166).
+char(p,89167).
+char(o,89168).
+char(p,89169).
+char(2,89170).
+char(3,89171).
+char(1,89172).
+char(9,89173).
+char(c,89174).
+char(c,89175).
+char(p,89176).
+char(5,89177).
+char(7,89178).
+char(5,89179).
+char(p,89180).
+char(3,89181).
+char(9,89182).
+char(4,89183).
+char(9,89184).
+char(p,89185).
+char(3,89186).
+char(5,89187).
+char(6,89188).
+char(0,89189).
+char(c,89190).
+char(c,89191).
+char(c,89192).
+char(c,89193).
+char(p,89194).
+char(o,89195).
+char(p,89196).
+char(o,89197).
+char(o,89198).
+char(o,89199).
+char(m,89200).
+char(o,89201).
+char(p,89202).
+char(1,89203).
+char(0,89204).
+char(3,89205).
+char(9,89206).
+char(c,89207).
+char(p,89208).
+char(o,89209).
+char(p,89210).
+char(o,89211).
+char(o,89212).
+char(o,89213).
+char(p,89214).
+char(o,89215).
+char(4,89216).
+char(3,89217).
+char(0,89218).
+char(8,89219).
+char(c,89220).
+char(p,89221).
+char(o,89222).
+char(p,89223).
+char(2,89224).
+char(1,89225).
+char(7,89226).
+char(1,89227).
+char(c,89228).
+char(c,89229).
+char(c,89230).
+char(p,89231).
+char(6,89232).
+char(3,89233).
+char(c,89234).
+char(c,89235).
+char(c,89236).
+char(c,89237).
+char(c,89238).
+char(m,89239).
+char(9,89240).
+char(5,89241).
+char(5,89242).
+char(5,89243).
+char(c,89244).
+char(p,89245).
+char(o,89246).
+char(m,89247).
+char(8,89248).
+char(0,89249).
+char(5,89250).
+char(0,89251).
+char(p,89252).
+char(8,89253).
+char(0,89254).
+char(7,89255).
+char(0,89256).
+char(m,89257).
+char(4,89258).
+char(7,89259).
+char(5,89260).
+char(7,89261).
+char(m,89262).
+char(2,89263).
+char(7,89264).
+char(5,89265).
+char(3,89266).
+char(m,89267).
+char(2,89268).
+char(8,89269).
+char(7,89270).
+char(2,89271).
+char(p,89272).
+char(4,89273).
+char(1,89274).
+char(3,89275).
+char(c,89276).
+char(p,89277).
+char(o,89278).
+char(m,89279).
+char(o,89280).
+char(o,89281).
+char(m,89282).
+char(2,89283).
+char(0,89284).
+char(9,89285).
+char(1,89286).
+char(p,89287).
+char(o,89288).
+char(o,89289).
+char(m,89290).
+char(6,89291).
+char(1,89292).
+char(2,89293).
+char(8,89294).
+char(c,89295).
+char(c,89296).
+char(m,89297).
+char(o,89298).
+char(p,89299).
+char(o,89300).
+char(p,89301).
+char(5,89302).
+char(2,89303).
+char(4,89304).
+char(7,89305).
+char(c,89306).
+char(p,89307).
+char(o,89308).
+char(m,89309).
+char(5,89310).
+char(5,89311).
+char(6,89312).
+char(8,89313).
+char(c,89314).
+char(m,89315).
+char(8,89316).
+char(8,89317).
+char(6,89318).
+char(1,89319).
+char(p,89320).
+char(3,89321).
+char(4,89322).
+char(8,89323).
+char(3,89324).
+char(m,89325).
+char(6,89326).
+char(5,89327).
+char(5,89328).
+char(p,89329).
+char(3,89330).
+char(9,89331).
+char(1,89332).
+char(1,89333).
+char(p,89334).
+char(8,89335).
+char(7,89336).
+char(4,89337).
+char(c,89338).
+char(c,89339).
+char(p,89340).
+char(o,89341).
+char(m,89342).
+char(o,89343).
+char(m,89344).
+char(9,89345).
+char(7,89346).
+char(5,89347).
+char(2,89348).
+char(c,89349).
+char(c,89350).
+char(p,89351).
+char(o,89352).
+char(p,89353).
+char(6,89354).
+char(7,89355).
+char(8,89356).
+char(8,89357).
+char(p,89358).
+char(o,89359).
+char(p,89360).
+char(o,89361).
+char(o,89362).
+char(m,89363).
+char(1,89364).
+char(4,89365).
+char(8,89366).
+char(7,89367).
+char(p,89368).
+char(o,89369).
+char(m,89370).
+char(o,89371).
+char(p,89372).
+char(o,89373).
+char(p,89374).
+char(4,89375).
+char(6,89376).
+char(7,89377).
+char(7,89378).
+char(m,89379).
+char(o,89380).
+char(o,89381).
+char(m,89382).
+char(6,89383).
+char(8,89384).
+char(1,89385).
+char(5,89386).
+char(c,89387).
+char(p,89388).
+char(7,89389).
+char(1,89390).
+char(p,89391).
+char(5,89392).
+char(1,89393).
+char(1,89394).
+char(3,89395).
+char(c,89396).
+char(c,89397).
+char(c,89398).
+char(c,89399).
+char(c,89400).
+char(m,89401).
+char(o,89402).
+char(p,89403).
+char(o,89404).
+char(9,89405).
+char(9,89406).
+char(9,89407).
+char(5,89408).
+char(c,89409).
+char(m,89410).
+char(1,89411).
+char(1,89412).
+char(5,89413).
+char(9,89414).
+char(p,89415).
+char(6,89416).
+char(7,89417).
+char(9,89418).
+char(6,89419).
+char(p,89420).
+char(o,89421).
+char(1,89422).
+char(3,89423).
+char(4,89424).
+char(c,89425).
+char(c,89426).
+char(c,89427).
+char(p,89428).
+char(o,89429).
+char(m,89430).
+char(1,89431).
+char(8,89432).
+char(1,89433).
+char(8,89434).
+char(c,89435).
+char(c,89436).
+char(p,89437).
+char(5,89438).
+char(7,89439).
+char(0,89440).
+char(7,89441).
+char(c,89442).
+char(p,89443).
+char(o,89444).
+char(5,89445).
+char(1,89446).
+char(0,89447).
+char(5,89448).
+char(p,89449).
+char(8,89450).
+char(9,89451).
+char(2,89452).
+char(4,89453).
+char(c,89454).
+char(p,89455).
+char(o,89456).
+char(3,89457).
+char(3,89458).
+char(2,89459).
+char(7,89460).
+char(p,89461).
+char(o,89462).
+char(p,89463).
+char(1,89464).
+char(5,89465).
+char(4,89466).
+char(1,89467).
+char(c,89468).
+char(p,89469).
+char(o,89470).
+char(m,89471).
+char(8,89472).
+char(3,89473).
+char(1,89474).
+char(3,89475).
+char(c,89476).
+char(c,89477).
+char(c,89478).
+char(p,89479).
+char(7,89480).
+char(3,89481).
+char(1,89482).
+char(3,89483).
+char(p,89484).
+char(o,89485).
+char(m,89486).
+char(o,89487).
+char(m,89488).
+char(o,89489).
+char(p,89490).
+char(7,89491).
+char(7,89492).
+char(0,89493).
+char(p,89494).
+char(7,89495).
+char(7,89496).
+char(1,89497).
+char(1,89498).
+char(p,89499).
+char(2,89500).
+char(5,89501).
+char(3,89502).
+char(9,89503).
+char(p,89504).
+char(7,89505).
+char(5,89506).
+char(7,89507).
+char(2,89508).
+char(m,89509).
+char(7,89510).
+char(8,89511).
+char(7,89512).
+char(m,89513).
+char(1,89514).
+char(7,89515).
+char(7,89516).
+char(c,89517).
+char(c,89518).
+char(c,89519).
+char(c,89520).
+char(c,89521).
+char(c,89522).
+char(c,89523).
+char(c,89524).
+char(c,89525).
+char(c,89526).
+char(c,89527).
+char(c,89528).
+char(c,89529).
+char(m,89530).
+char(1,89531).
+char(9,89532).
+char(2,89533).
+char(4,89534).
+char(m,89535).
+char(1,89536).
+char(4,89537).
+char(1,89538).
+char(8,89539).
+char(c,89540).
+char(c,89541).
+char(c,89542).
+char(p,89543).
+char(o,89544).
+char(m,89545).
+char(5,89546).
+char(6,89547).
+char(8,89548).
+char(8,89549).
+char(c,89550).
+char(p,89551).
+char(o,89552).
+char(m,89553).
+char(o,89554).
+char(m,89555).
+char(1,89556).
+char(5,89557).
+char(3,89558).
+char(9,89559).
+char(c,89560).
+char(m,89561).
+char(1,89562).
+char(8,89563).
+char(4,89564).
+char(c,89565).
+char(m,89566).
+char(o,89567).
+char(9,89568).
+char(8,89569).
+char(5,89570).
+char(6,89571).
+char(c,89572).
+char(c,89573).
+char(m,89574).
+char(8,89575).
+char(3,89576).
+char(1,89577).
+char(8,89578).
+char(m,89579).
+char(2,89580).
+char(4,89581).
+char(9,89582).
+char(6,89583).
+char(m,89584).
+char(4,89585).
+char(7,89586).
+char(4,89587).
+char(p,89588).
+char(3,89589).
+char(6,89590).
+char(5,89591).
+char(7,89592).
+char(m,89593).
+char(1,89594).
+char(4,89595).
+char(7,89596).
+char(5,89597).
+char(c,89598).
+char(c,89599).
+char(m,89600).
+char(o,89601).
+char(7,89602).
+char(0,89603).
+char(6,89604).
+char(4,89605).
+char(c,89606).
+char(p,89607).
+char(o,89608).
+char(m,89609).
+char(o,89610).
+char(3,89611).
+char(0,89612).
+char(1,89613).
+char(6,89614).
+char(m,89615).
+char(o,89616).
+char(m,89617).
+char(3,89618).
+char(9,89619).
+char(3,89620).
+char(1,89621).
+char(p,89622).
+char(o,89623).
+char(m,89624).
+char(3,89625).
+char(0,89626).
+char(5,89627).
+char(p,89628).
+char(5,89629).
+char(8,89630).
+char(8,89631).
+char(9,89632).
+char(c,89633).
+char(m,89634).
+char(o,89635).
+char(p,89636).
+char(4,89637).
+char(5,89638).
+char(5,89639).
+char(6,89640).
+char(p,89641).
+char(5,89642).
+char(7,89643).
+char(4,89644).
+char(6,89645).
+char(m,89646).
+char(9,89647).
+char(7,89648).
+char(3,89649).
+char(5,89650).
+char(m,89651).
+char(8,89652).
+char(1,89653).
+char(8,89654).
+char(6,89655).
+char(p,89656).
+char(3,89657).
+char(7,89658).
+char(4,89659).
+char(2,89660).
+char(c,89661).
+char(m,89662).
+char(o,89663).
+char(m,89664).
+char(o,89665).
+char(o,89666).
+char(o,89667).
+char(p,89668).
+char(o,89669).
+char(m,89670).
+char(1,89671).
+char(5,89672).
+char(6,89673).
+char(8,89674).
+char(c,89675).
+char(c,89676).
+char(p,89677).
+char(o,89678).
+char(m,89679).
+char(o,89680).
+char(p,89681).
+char(o,89682).
+char(p,89683).
+char(o,89684).
+char(o,89685).
+char(o,89686).
+char(p,89687).
+char(o,89688).
+char(p,89689).
+char(4,89690).
+char(4,89691).
+char(9,89692).
+char(9,89693).
+char(c,89694).
+char(c,89695).
+char(m,89696).
+char(o,89697).
+char(p,89698).
+char(o,89699).
+char(p,89700).
+char(o,89701).
+char(o,89702).
+char(p,89703).
+char(o,89704).
+char(p,89705).
+char(4,89706).
+char(7,89707).
+char(9,89708).
+char(8,89709).
+char(c,89710).
+char(c,89711).
+char(c,89712).
+char(m,89713).
+char(4,89714).
+char(7,89715).
+char(0,89716).
+char(3,89717).
+char(c,89718).
+char(c,89719).
+char(c,89720).
+char(c,89721).
+char(m,89722).
+char(o,89723).
+char(p,89724).
+char(o,89725).
+char(p,89726).
+char(o,89727).
+char(m,89728).
+char(3,89729).
+char(9,89730).
+char(4,89731).
+char(4,89732).
+char(c,89733).
+char(c,89734).
+char(c,89735).
+char(p,89736).
+char(5,89737).
+char(3,89738).
+char(3,89739).
+char(9,89740).
+char(c,89741).
+char(c,89742).
+char(p,89743).
+char(o,89744).
+char(p,89745).
+char(6,89746).
+char(9,89747).
+char(7,89748).
+char(5,89749).
+char(p,89750).
+char(3,89751).
+char(3,89752).
+char(8,89753).
+char(c,89754).
+char(c,89755).
+char(m,89756).
+char(5,89757).
+char(3,89758).
+char(9,89759).
+char(0,89760).
+char(c,89761).
+char(c,89762).
+char(c,89763).
+char(p,89764).
+char(o,89765).
+char(m,89766).
+char(o,89767).
+char(p,89768).
+char(8,89769).
+char(3,89770).
+char(0,89771).
+char(2,89772).
+char(c,89773).
+char(m,89774).
+char(o,89775).
+char(p,89776).
+char(2,89777).
+char(7,89778).
+char(4,89779).
+char(3,89780).
+char(c,89781).
+char(c,89782).
+char(c,89783).
+char(c,89784).
+char(m,89785).
+char(o,89786).
+char(p,89787).
+char(o,89788).
+char(p,89789).
+char(6,89790).
+char(8,89791).
+char(2,89792).
+char(9,89793).
+char(c,89794).
+char(p,89795).
+char(o,89796).
+char(m,89797).
+char(3,89798).
+char(5,89799).
+char(9,89800).
+char(8,89801).
+char(p,89802).
+char(2,89803).
+char(7,89804).
+char(2,89805).
+char(5,89806).
+char(m,89807).
+char(5,89808).
+char(4,89809).
+char(9,89810).
+char(6,89811).
+char(c,89812).
+char(p,89813).
+char(o,89814).
+char(5,89815).
+char(9,89816).
+char(9,89817).
+char(6,89818).
+char(m,89819).
+char(5,89820).
+char(4,89821).
+char(6,89822).
+char(9,89823).
+char(c,89824).
+char(c,89825).
+char(c,89826).
+char(p,89827).
+char(5,89828).
+char(3,89829).
+char(7,89830).
+char(2,89831).
+char(c,89832).
+char(c,89833).
+char(c,89834).
+char(c,89835).
+char(p,89836).
+char(7,89837).
+char(7,89838).
+char(c,89839).
+char(c,89840).
+char(p,89841).
+char(o,89842).
+char(m,89843).
+char(7,89844).
+char(7,89845).
+char(4,89846).
+char(4,89847).
+char(c,89848).
+char(m,89849).
+char(5,89850).
+char(8,89851).
+char(7,89852).
+char(3,89853).
+char(c,89854).
+char(p,89855).
+char(1,89856).
+char(1,89857).
+char(3,89858).
+char(9,89859).
+char(c,89860).
+char(c,89861).
+char(m,89862).
+char(8,89863).
+char(7,89864).
+char(6,89865).
+char(7,89866).
+char(p,89867).
+char(7,89868).
+char(3,89869).
+char(5,89870).
+char(0,89871).
+char(c,89872).
+char(p,89873).
+char(3,89874).
+char(4,89875).
+char(3,89876).
+char(6,89877).
+char(p,89878).
+char(o,89879).
+char(3,89880).
+char(4,89881).
+char(6,89882).
+char(9,89883).
+char(p,89884).
+char(o,89885).
+char(3,89886).
+char(5,89887).
+char(5,89888).
+char(4,89889).
+char(c,89890).
+char(p,89891).
+char(o,89892).
+char(m,89893).
+char(o,89894).
+char(m,89895).
+char(1,89896).
+char(4,89897).
+char(7,89898).
+char(9,89899).
+char(c,89900).
+char(m,89901).
+char(9,89902).
+char(0,89903).
+char(9,89904).
+char(p,89905).
+char(1,89906).
+char(3,89907).
+char(8,89908).
+char(4,89909).
+char(c,89910).
+char(c,89911).
+char(p,89912).
+char(o,89913).
+char(p,89914).
+char(8,89915).
+char(0,89916).
+char(6,89917).
+char(0,89918).
+char(c,89919).
+char(c,89920).
+char(m,89921).
+char(o,89922).
+char(7,89923).
+char(9,89924).
+char(8,89925).
+char(1,89926).
+char(c,89927).
+char(c,89928).
+char(p,89929).
+char(7,89930).
+char(6,89931).
+char(1,89932).
+char(6,89933).
+char(c,89934).
+char(c,89935).
+char(c,89936).
+char(c,89937).
+char(c,89938).
+char(c,89939).
+char(c,89940).
+char(c,89941).
+char(c,89942).
+char(c,89943).
+char(p,89944).
+char(o,89945).
+char(9,89946).
+char(2,89947).
+char(4,89948).
+char(4,89949).
+char(c,89950).
+char(c,89951).
+char(m,89952).
+char(o,89953).
+char(p,89954).
+char(o,89955).
+char(p,89956).
+char(7,89957).
+char(9,89958).
+char(1,89959).
+char(2,89960).
+char(c,89961).
+char(m,89962).
+char(o,89963).
+char(m,89964).
+char(o,89965).
+char(o,89966).
+char(m,89967).
+char(o,89968).
+char(p,89969).
+char(4,89970).
+char(5,89971).
+char(4,89972).
+char(p,89973).
+char(5,89974).
+char(7,89975).
+char(3,89976).
+char(8,89977).
+char(p,89978).
+char(5,89979).
+char(4,89980).
+char(5,89981).
+char(2,89982).
+char(p,89983).
+char(6,89984).
+char(5,89985).
+char(0,89986).
+char(5,89987).
+char(p,89988).
+char(o,89989).
+char(3,89990).
+char(8,89991).
+char(7,89992).
+char(0,89993).
+char(p,89994).
+char(o,89995).
+char(p,89996).
+char(o,89997).
+char(m,89998).
+char(o,89999).
+char(m,90000).
+char(4,90001).
+char(0,90002).
+char(5,90003).
+char(0,90004).
+char(c,90005).
+char(p,90006).
+char(5,90007).
+char(2,90008).
+char(2,90009).
+char(p,90010).
+char(o,90011).
+char(p,90012).
+char(2,90013).
+char(6,90014).
+char(7,90015).
+char(2,90016).
+char(c,90017).
+char(c,90018).
+char(c,90019).
+char(m,90020).
+char(o,90021).
+char(m,90022).
+char(9,90023).
+char(6,90024).
+char(5,90025).
+char(0,90026).
+char(c,90027).
+char(c,90028).
+char(m,90029).
+char(o,90030).
+char(p,90031).
+char(o,90032).
+char(o,90033).
+char(m,90034).
+char(1,90035).
+char(6,90036).
+char(4,90037).
+char(c,90038).
+char(p,90039).
+char(9,90040).
+char(9,90041).
+char(5,90042).
+char(0,90043).
+char(m,90044).
+char(1,90045).
+char(4,90046).
+char(9,90047).
+char(c,90048).
+char(c,90049).
+char(p,90050).
+char(1,90051).
+char(3,90052).
+char(2,90053).
+char(5,90054).
+char(c,90055).
+char(p,90056).
+char(6,90057).
+char(8,90058).
+char(8,90059).
+char(2,90060).
+char(m,90061).
+char(1,90062).
+char(1,90063).
+char(5,90064).
+char(6,90065).
+char(c,90066).
+char(m,90067).
+char(o,90068).
+char(m,90069).
+char(o,90070).
+char(p,90071).
+char(o,90072).
+char(p,90073).
+char(2,90074).
+char(9,90075).
+char(1,90076).
+char(m,90077).
+char(o,90078).
+char(p,90079).
+char(1,90080).
+char(8,90081).
+char(6,90082).
+char(0,90083).
+char(c,90084).
+char(p,90085).
+char(3,90086).
+char(6,90087).
+char(8,90088).
+char(0,90089).
+char(p,90090).
+char(7,90091).
+char(4,90092).
+char(1,90093).
+char(5,90094).
+char(c,90095).
+char(c,90096).
+char(c,90097).
+char(c,90098).
+char(m,90099).
+char(o,90100).
+char(m,90101).
+char(o,90102).
+char(p,90103).
+char(o,90104).
+char(o,90105).
+char(p,90106).
+char(2,90107).
+char(9,90108).
+char(0,90109).
+char(1,90110).
+char(m,90111).
+char(o,90112).
+char(o,90113).
+char(m,90114).
+char(o,90115).
+char(o,90116).
+char(9,90117).
+char(6,90118).
+char(0,90119).
+char(8,90120).
+char(c,90121).
+char(p,90122).
+char(6,90123).
+char(6,90124).
+char(4,90125).
+char(9,90126).
+char(m,90127).
+char(o,90128).
+char(5,90129).
+char(5,90130).
+char(3,90131).
+char(5,90132).
+char(c,90133).
+char(m,90134).
+char(o,90135).
+char(p,90136).
+char(o,90137).
+char(1,90138).
+char(6,90139).
+char(2,90140).
+char(9,90141).
+char(m,90142).
+char(9,90143).
+char(8,90144).
+char(0,90145).
+char(3,90146).
+char(c,90147).
+char(m,90148).
+char(1,90149).
+char(4,90150).
+char(3,90151).
+char(0,90152).
+char(p,90153).
+char(o,90154).
+char(o,90155).
+char(o,90156).
+char(m,90157).
+char(3,90158).
+char(8,90159).
+char(9,90160).
+char(1,90161).
+char(p,90162).
+char(o,90163).
+char(p,90164).
+char(o,90165).
+char(p,90166).
+char(o,90167).
+char(4,90168).
+char(4,90169).
+char(2,90170).
+char(4,90171).
+char(c,90172).
+char(m,90173).
+char(o,90174).
+char(o,90175).
+char(p,90176).
+char(2,90177).
+char(7,90178).
+char(6,90179).
+char(9,90180).
+char(c,90181).
+char(m,90182).
+char(o,90183).
+char(m,90184).
+char(o,90185).
+char(m,90186).
+char(o,90187).
+char(p,90188).
+char(5,90189).
+char(2,90190).
+char(0,90191).
+char(7,90192).
+char(p,90193).
+char(o,90194).
+char(8,90195).
+char(5,90196).
+char(9,90197).
+char(9,90198).
+char(p,90199).
+char(7,90200).
+char(8,90201).
+char(9,90202).
+char(4,90203).
+char(p,90204).
+char(1,90205).
+char(9,90206).
+char(0,90207).
+char(1,90208).
+char(m,90209).
+char(o,90210).
+char(9,90211).
+char(8,90212).
+char(0,90213).
+char(3,90214).
+char(p,90215).
+char(o,90216).
+char(p,90217).
+char(o,90218).
+char(5,90219).
+char(6,90220).
+char(3,90221).
+char(c,90222).
+char(c,90223).
+char(p,90224).
+char(o,90225).
+char(m,90226).
+char(6,90227).
+char(5,90228).
+char(8,90229).
+char(m,90230).
+char(6,90231).
+char(8,90232).
+char(8,90233).
+char(c,90234).
+char(m,90235).
+char(5,90236).
+char(3,90237).
+char(8,90238).
+char(0,90239).
+char(c,90240).
+char(p,90241).
+char(5,90242).
+char(5,90243).
+char(0,90244).
+char(4,90245).
+char(m,90246).
+char(o,90247).
+char(m,90248).
+char(6,90249).
+char(8,90250).
+char(2,90251).
+char(3,90252).
+char(c,90253).
+char(c,90254).
+char(c,90255).
+char(m,90256).
+char(o,90257).
+char(p,90258).
+char(5,90259).
+char(6,90260).
+char(9,90261).
+char(8,90262).
+char(p,90263).
+char(o,90264).
+char(p,90265).
+char(4,90266).
+char(1,90267).
+char(7,90268).
+char(2,90269).
+char(c,90270).
+char(c,90271).
+char(c,90272).
+char(m,90273).
+char(1,90274).
+char(8,90275).
+char(2,90276).
+char(8,90277).
+char(p,90278).
+char(5,90279).
+char(9,90280).
+char(5,90281).
+char(6,90282).
+char(m,90283).
+char(9,90284).
+char(8,90285).
+char(1,90286).
+char(0,90287).
+char(c,90288).
+char(p,90289).
+char(3,90290).
+char(1,90291).
+char(9,90292).
+char(9,90293).
+char(m,90294).
+char(o,90295).
+char(5,90296).
+char(0,90297).
+char(4,90298).
+char(6,90299).
+char(c,90300).
+char(m,90301).
+char(o,90302).
+char(o,90303).
+char(p,90304).
+char(9,90305).
+char(9,90306).
+char(0,90307).
+char(6,90308).
+char(c,90309).
+char(m,90310).
+char(6,90311).
+char(4,90312).
+char(4,90313).
+char(m,90314).
+char(o,90315).
+char(m,90316).
+char(o,90317).
+char(m,90318).
+char(o,90319).
+char(m,90320).
+char(6,90321).
+char(3,90322).
+char(1,90323).
+char(0,90324).
+char(c,90325).
+char(p,90326).
+char(2,90327).
+char(0,90328).
+char(6,90329).
+char(c,90330).
+char(m,90331).
+char(o,90332).
+char(o,90333).
+char(m,90334).
+char(4,90335).
+char(7,90336).
+char(5,90337).
+char(8,90338).
+char(c,90339).
+char(c,90340).
+char(m,90341).
+char(o,90342).
+char(p,90343).
+char(3,90344).
+char(0,90345).
+char(4,90346).
+char(5,90347).
+char(m,90348).
+char(o,90349).
+char(m,90350).
+char(5,90351).
+char(9,90352).
+char(8,90353).
+char(3,90354).
+char(c,90355).
+char(c,90356).
+char(m,90357).
+char(2,90358).
+char(4,90359).
+char(4,90360).
+char(6,90361).
+char(p,90362).
+char(o,90363).
+char(o,90364).
+char(6,90365).
+char(2,90366).
+char(4,90367).
+char(4,90368).
+char(c,90369).
+char(m,90370).
+char(4,90371).
+char(7,90372).
+char(8,90373).
+char(1,90374).
+char(c,90375).
+char(m,90376).
+char(7,90377).
+char(0,90378).
+char(6,90379).
+char(0,90380).
+char(m,90381).
+char(2,90382).
+char(7,90383).
+char(3,90384).
+char(7,90385).
+char(p,90386).
+char(o,90387).
+char(m,90388).
+char(7,90389).
+char(1,90390).
+char(4,90391).
+char(7,90392).
+char(c,90393).
+char(m,90394).
+char(7,90395).
+char(5,90396).
+char(1,90397).
+char(1,90398).
+char(p,90399).
+char(o,90400).
+char(m,90401).
+char(4,90402).
+char(7,90403).
+char(6,90404).
+char(5,90405).
+char(p,90406).
+char(o,90407).
+char(m,90408).
+char(6,90409).
+char(8,90410).
+char(0,90411).
+char(5,90412).
+char(c,90413).
+char(p,90414).
+char(4,90415).
+char(1,90416).
+char(2,90417).
+char(7,90418).
+char(m,90419).
+char(o,90420).
+char(o,90421).
+char(o,90422).
+char(m,90423).
+char(3,90424).
+char(0,90425).
+char(5,90426).
+char(2,90427).
+char(p,90428).
+char(4,90429).
+char(2,90430).
+char(1,90431).
+char(6,90432).
+char(c,90433).
+char(c,90434).
+char(c,90435).
+char(m,90436).
+char(1,90437).
+char(8,90438).
+char(1,90439).
+char(2,90440).
+char(c,90441).
+char(p,90442).
+char(2,90443).
+char(2,90444).
+char(5,90445).
+char(3,90446).
+char(c,90447).
+char(p,90448).
+char(o,90449).
+char(p,90450).
+char(2,90451).
+char(9,90452).
+char(6,90453).
+char(6,90454).
+char(c,90455).
+char(m,90456).
+char(o,90457).
+char(o,90458).
+char(m,90459).
+char(1,90460).
+char(6,90461).
+char(9,90462).
+char(1,90463).
+char(m,90464).
+char(9,90465).
+char(5,90466).
+char(1,90467).
+char(6,90468).
+char(p,90469).
+char(o,90470).
+char(p,90471).
+char(6,90472).
+char(3,90473).
+char(3,90474).
+char(2,90475).
+char(p,90476).
+char(o,90477).
+char(m,90478).
+char(2,90479).
+char(3,90480).
+char(3,90481).
+char(9,90482).
+char(c,90483).
+char(c,90484).
+char(m,90485).
+char(9,90486).
+char(7,90487).
+char(2,90488).
+char(6,90489).
+char(c,90490).
+char(m,90491).
+char(o,90492).
+char(o,90493).
+char(p,90494).
+char(o,90495).
+char(p,90496).
+char(4,90497).
+char(7,90498).
+char(6,90499).
+char(0,90500).
+char(c,90501).
+char(c,90502).
+char(m,90503).
+char(1,90504).
+char(2,90505).
+char(8,90506).
+char(6,90507).
+char(p,90508).
+char(o,90509).
+char(6,90510).
+char(1,90511).
+char(5,90512).
+char(4,90513).
+char(c,90514).
+char(p,90515).
+char(9,90516).
+char(8,90517).
+char(7,90518).
+char(3,90519).
+char(p,90520).
+char(o,90521).
+char(p,90522).
+char(o,90523).
+char(p,90524).
+char(1,90525).
+char(8,90526).
+char(4,90527).
+char(2,90528).
+char(c,90529).
+char(c,90530).
+char(p,90531).
+char(o,90532).
+char(p,90533).
+char(o,90534).
+char(p,90535).
+char(o,90536).
+char(p,90537).
+char(o,90538).
+char(m,90539).
+char(o,90540).
+char(p,90541).
+char(o,90542).
+char(o,90543).
+char(m,90544).
+char(1,90545).
+char(2,90546).
+char(7,90547).
+char(0,90548).
+char(c,90549).
+char(p,90550).
+char(o,90551).
+char(p,90552).
+char(o,90553).
+char(o,90554).
+char(5,90555).
+char(6,90556).
+char(8,90557).
+char(8,90558).
+char(c,90559).
+char(p,90560).
+char(8,90561).
+char(1,90562).
+char(9,90563).
+char(9,90564).
+char(p,90565).
+char(o,90566).
+char(p,90567).
+char(o,90568).
+char(m,90569).
+char(o,90570).
+char(m,90571).
+char(o,90572).
+char(p,90573).
+char(4,90574).
+char(7,90575).
+char(4,90576).
+char(3,90577).
+char(p,90578).
+char(3,90579).
+char(4,90580).
+char(4,90581).
+char(1,90582).
+char(m,90583).
+char(7,90584).
+char(9,90585).
+char(8,90586).
+char(m,90587).
+char(o,90588).
+char(m,90589).
+char(1,90590).
+char(0,90591).
+char(3,90592).
+char(3,90593).
+char(m,90594).
+char(2,90595).
+char(3,90596).
+char(7,90597).
+char(8,90598).
+char(m,90599).
+char(o,90600).
+char(7,90601).
+char(9,90602).
+char(1,90603).
+char(1,90604).
+char(c,90605).
+char(m,90606).
+char(3,90607).
+char(7,90608).
+char(1,90609).
+char(3,90610).
+char(c,90611).
+char(c,90612).
+char(c,90613).
+char(p,90614).
+char(1,90615).
+char(9,90616).
+char(5,90617).
+char(c,90618).
+char(c,90619).
+char(m,90620).
+char(o,90621).
+char(p,90622).
+char(5,90623).
+char(6,90624).
+char(8,90625).
+char(2,90626).
+char(c,90627).
+char(m,90628).
+char(o,90629).
+char(o,90630).
+char(8,90631).
+char(4,90632).
+char(2,90633).
+char(m,90634).
+char(3,90635).
+char(1,90636).
+char(6,90637).
+char(3,90638).
+char(c,90639).
+char(c,90640).
+char(c,90641).
+char(p,90642).
+char(o,90643).
+char(m,90644).
+char(9,90645).
+char(3,90646).
+char(4,90647).
+char(9,90648).
+char(c,90649).
+char(m,90650).
+char(o,90651).
+char(p,90652).
+char(5,90653).
+char(3,90654).
+char(3,90655).
+char(0,90656).
+char(p,90657).
+char(o,90658).
+char(m,90659).
+char(8,90660).
+char(7,90661).
+char(7,90662).
+char(3,90663).
+char(c,90664).
+char(c,90665).
+char(c,90666).
+char(p,90667).
+char(3,90668).
+char(2,90669).
+char(8,90670).
+char(0,90671).
+char(m,90672).
+char(5,90673).
+char(4,90674).
+char(9,90675).
+char(4,90676).
+char(c,90677).
+char(p,90678).
+char(o,90679).
+char(p,90680).
+char(o,90681).
+char(p,90682).
+char(3,90683).
+char(7,90684).
+char(8,90685).
+char(4,90686).
+char(m,90687).
+char(o,90688).
+char(o,90689).
+char(p,90690).
+char(9,90691).
+char(2,90692).
+char(2,90693).
+char(1,90694).
+char(c,90695).
+char(c,90696).
+char(c,90697).
+char(p,90698).
+char(4,90699).
+char(0,90700).
+char(9,90701).
+char(8,90702).
+char(c,90703).
+char(c,90704).
+char(p,90705).
+char(o,90706).
+char(p,90707).
+char(o,90708).
+char(o,90709).
+char(p,90710).
+char(o,90711).
+char(p,90712).
+char(3,90713).
+char(4,90714).
+char(1,90715).
+char(1,90716).
+char(c,90717).
+char(c,90718).
+char(m,90719).
+char(o,90720).
+char(m,90721).
+char(2,90722).
+char(4,90723).
+char(8,90724).
+char(6,90725).
+char(c,90726).
+char(c,90727).
+char(c,90728).
+char(p,90729).
+char(o,90730).
+char(5,90731).
+char(3,90732).
+char(1,90733).
+char(1,90734).
+char(c,90735).
+char(c,90736).
+char(p,90737).
+char(7,90738).
+char(9,90739).
+char(9,90740).
+char(3,90741).
+char(p,90742).
+char(2,90743).
+char(0,90744).
+char(3,90745).
+char(1,90746).
+char(p,90747).
+char(2,90748).
+char(7,90749).
+char(7,90750).
+char(8,90751).
+char(p,90752).
+char(4,90753).
+char(0,90754).
+char(1,90755).
+char(6,90756).
+char(c,90757).
+char(c,90758).
+char(c,90759).
+char(c,90760).
+char(p,90761).
+char(9,90762).
+char(4,90763).
+char(9,90764).
+char(2,90765).
+char(c,90766).
+char(m,90767).
+char(o,90768).
+char(p,90769).
+char(o,90770).
+char(p,90771).
+char(6,90772).
+char(4,90773).
+char(8,90774).
+char(6,90775).
+char(c,90776).
+char(m,90777).
+char(3,90778).
+char(4,90779).
+char(9,90780).
+char(3,90781).
+char(c,90782).
+char(m,90783).
+char(1,90784).
+char(8,90785).
+char(2,90786).
+char(7,90787).
+char(c,90788).
+char(p,90789).
+char(o,90790).
+char(m,90791).
+char(o,90792).
+char(p,90793).
+char(o,90794).
+char(p,90795).
+char(1,90796).
+char(2,90797).
+char(4,90798).
+char(7,90799).
+char(p,90800).
+char(2,90801).
+char(3,90802).
+char(7,90803).
+char(9,90804).
+char(p,90805).
+char(5,90806).
+char(7,90807).
+char(2,90808).
+char(6,90809).
+char(m,90810).
+char(o,90811).
+char(m,90812).
+char(o,90813).
+char(p,90814).
+char(o,90815).
+char(4,90816).
+char(8,90817).
+char(1,90818).
+char(1,90819).
+char(c,90820).
+char(p,90821).
+char(7,90822).
+char(7,90823).
+char(6,90824).
+char(1,90825).
+char(c,90826).
+char(c,90827).
+char(c,90828).
+char(c,90829).
+char(p,90830).
+char(o,90831).
+char(m,90832).
+char(o,90833).
+char(6,90834).
+char(2,90835).
+char(8,90836).
+char(0,90837).
+char(p,90838).
+char(o,90839).
+char(p,90840).
+char(o,90841).
+char(m,90842).
+char(2,90843).
+char(6,90844).
+char(7,90845).
+char(c,90846).
+char(p,90847).
+char(2,90848).
+char(4,90849).
+char(2,90850).
+char(5,90851).
+char(c,90852).
+char(p,90853).
+char(2,90854).
+char(4,90855).
+char(9,90856).
+char(c,90857).
+char(c,90858).
+char(m,90859).
+char(o,90860).
+char(1,90861).
+char(7,90862).
+char(1,90863).
+char(p,90864).
+char(6,90865).
+char(5,90866).
+char(6,90867).
+char(5,90868).
+char(c,90869).
+char(c,90870).
+char(c,90871).
+char(c,90872).
+char(p,90873).
+char(8,90874).
+char(0,90875).
+char(0,90876).
+char(7,90877).
+char(p,90878).
+char(o,90879).
+char(8,90880).
+char(8,90881).
+char(3,90882).
+char(6,90883).
+char(c,90884).
+char(p,90885).
+char(7,90886).
+char(0,90887).
+char(3,90888).
+char(9,90889).
+char(p,90890).
+char(o,90891).
+char(p,90892).
+char(o,90893).
+char(m,90894).
+char(6,90895).
+char(5,90896).
+char(1,90897).
+char(4,90898).
+char(c,90899).
+char(m,90900).
+char(4,90901).
+char(2,90902).
+char(2,90903).
+char(3,90904).
+char(c,90905).
+char(m,90906).
+char(o,90907).
+char(p,90908).
+char(o,90909).
+char(2,90910).
+char(8,90911).
+char(1,90912).
+char(p,90913).
+char(o,90914).
+char(p,90915).
+char(8,90916).
+char(3,90917).
+char(6,90918).
+char(5,90919).
+char(c,90920).
+char(m,90921).
+char(o,90922).
+char(o,90923).
+char(p,90924).
+char(5,90925).
+char(1,90926).
+char(9,90927).
+char(9,90928).
+char(p,90929).
+char(o,90930).
+char(3,90931).
+char(7,90932).
+char(1,90933).
+char(c,90934).
+char(m,90935).
+char(o,90936).
+char(p,90937).
+char(o,90938).
+char(5,90939).
+char(3,90940).
+char(2,90941).
+char(6,90942).
+char(p,90943).
+char(o,90944).
+char(p,90945).
+char(o,90946).
+char(m,90947).
+char(4,90948).
+char(3,90949).
+char(0,90950).
+char(1,90951).
+char(m,90952).
+char(o,90953).
+char(m,90954).
+char(4,90955).
+char(0,90956).
+char(0,90957).
+char(6,90958).
+char(p,90959).
+char(o,90960).
+char(p,90961).
+char(3,90962).
+char(8,90963).
+char(9,90964).
+char(2,90965).
+char(m,90966).
+char(3,90967).
+char(4,90968).
+char(3,90969).
+char(1,90970).
+char(m,90971).
+char(7,90972).
+char(9,90973).
+char(3,90974).
+char(4,90975).
+char(p,90976).
+char(3,90977).
+char(1,90978).
+char(4,90979).
+char(2,90980).
+char(c,90981).
+char(c,90982).
+char(c,90983).
+char(c,90984).
+char(p,90985).
+char(1,90986).
+char(8,90987).
+char(8,90988).
+char(8,90989).
+char(p,90990).
+char(o,90991).
+char(6,90992).
+char(7,90993).
+char(2,90994).
+char(p,90995).
+char(6,90996).
+char(9,90997).
+char(6,90998).
+char(3,90999).
+char(c,91000).
+char(c,91001).
+char(c,91002).
+char(c,91003).
+char(c,91004).
+char(m,91005).
+char(o,91006).
+char(o,91007).
+char(p,91008).
+char(9,91009).
+char(7,91010).
+char(9,91011).
+char(7,91012).
+char(m,91013).
+char(o,91014).
+char(p,91015).
+char(1,91016).
+char(9,91017).
+char(3,91018).
+char(4,91019).
+char(c,91020).
+char(p,91021).
+char(6,91022).
+char(4,91023).
+char(1,91024).
+char(4,91025).
+char(c,91026).
+char(m,91027).
+char(o,91028).
+char(o,91029).
+char(o,91030).
+char(m,91031).
+char(o,91032).
+char(o,91033).
+char(m,91034).
+char(1,91035).
+char(2,91036).
+char(3,91037).
+char(1,91038).
+char(c,91039).
+char(p,91040).
+char(o,91041).
+char(o,91042).
+char(p,91043).
+char(5,91044).
+char(4,91045).
+char(8,91046).
+char(8,91047).
+char(c,91048).
+char(c,91049).
+char(p,91050).
+char(4,91051).
+char(4,91052).
+char(2,91053).
+char(3,91054).
+char(c,91055).
+char(c,91056).
+char(m,91057).
+char(o,91058).
+char(7,91059).
+char(0,91060).
+char(0,91061).
+char(4,91062).
+char(c,91063).
+char(c,91064).
+char(c,91065).
+char(c,91066).
+char(c,91067).
+char(c,91068).
+char(c,91069).
+char(m,91070).
+char(8,91071).
+char(2,91072).
+char(2,91073).
+char(2,91074).
+char(m,91075).
+char(1,91076).
+char(7,91077).
+char(4,91078).
+char(p,91079).
+char(o,91080).
+char(p,91081).
+char(o,91082).
+char(m,91083).
+char(o,91084).
+char(p,91085).
+char(3,91086).
+char(5,91087).
+char(8,91088).
+char(m,91089).
+char(o,91090).
+char(p,91091).
+char(8,91092).
+char(5,91093).
+char(7,91094).
+char(9,91095).
+char(c,91096).
+char(m,91097).
+char(5,91098).
+char(3,91099).
+char(6,91100).
+char(0,91101).
+char(p,91102).
+char(6,91103).
+char(5,91104).
+char(9,91105).
+char(5,91106).
+char(c,91107).
+char(c,91108).
+char(c,91109).
+char(c,91110).
+char(p,91111).
+char(o,91112).
+char(m,91113).
+char(2,91114).
+char(2,91115).
+char(7,91116).
+char(5,91117).
+char(m,91118).
+char(2,91119).
+char(1,91120).
+char(7,91121).
+char(9,91122).
+char(c,91123).
+char(p,91124).
+char(o,91125).
+char(m,91126).
+char(o,91127).
+char(m,91128).
+char(o,91129).
+char(p,91130).
+char(9,91131).
+char(0,91132).
+char(6,91133).
+char(6,91134).
+char(c,91135).
+char(p,91136).
+char(7,91137).
+char(5,91138).
+char(0,91139).
+char(4,91140).
+char(p,91141).
+char(o,91142).
+char(5,91143).
+char(7,91144).
+char(9,91145).
+char(6,91146).
+char(p,91147).
+char(o,91148).
+char(o,91149).
+char(m,91150).
+char(o,91151).
+char(p,91152).
+char(2,91153).
+char(9,91154).
+char(2,91155).
+char(4,91156).
+char(c,91157).
+char(c,91158).
+char(m,91159).
+char(o,91160).
+char(4,91161).
+char(5,91162).
+char(3,91163).
+char(c,91164).
+char(c,91165).
+char(p,91166).
+char(o,91167).
+char(p,91168).
+char(o,91169).
+char(m,91170).
+char(o,91171).
+char(m,91172).
+char(o,91173).
+char(p,91174).
+char(o,91175).
+char(p,91176).
+char(2,91177).
+char(5,91178).
+char(3,91179).
+char(6,91180).
+char(m,91181).
+char(o,91182).
+char(o,91183).
+char(m,91184).
+char(1,91185).
+char(7,91186).
+char(3,91187).
+char(6,91188).
+char(p,91189).
+char(o,91190).
+char(p,91191).
+char(o,91192).
+char(m,91193).
+char(3,91194).
+char(2,91195).
+char(9,91196).
+char(0,91197).
+char(m,91198).
+char(o,91199).
+char(p,91200).
+char(o,91201).
+char(p,91202).
+char(o,91203).
+char(8,91204).
+char(5,91205).
+char(2,91206).
+char(0,91207).
+char(m,91208).
+char(o,91209).
+char(p,91210).
+char(5,91211).
+char(4,91212).
+char(2,91213).
+char(m,91214).
+char(4,91215).
+char(5,91216).
+char(p,91217).
+char(o,91218).
+char(3,91219).
+char(0,91220).
+char(1,91221).
+char(8,91222).
+char(m,91223).
+char(2,91224).
+char(5,91225).
+char(1,91226).
+char(6,91227).
+char(c,91228).
+char(p,91229).
+char(o,91230).
+char(4,91231).
+char(1,91232).
+char(6,91233).
+char(9,91234).
+char(c,91235).
+char(c,91236).
+char(m,91237).
+char(5,91238).
+char(8,91239).
+char(6,91240).
+char(m,91241).
+char(8,91242).
+char(7,91243).
+char(7,91244).
+char(6,91245).
+char(m,91246).
+char(9,91247).
+char(4,91248).
+char(4,91249).
+char(7,91250).
+char(c,91251).
+char(c,91252).
+char(p,91253).
+char(o,91254).
+char(p,91255).
+char(o,91256).
+char(4,91257).
+char(9,91258).
+char(c,91259).
+char(p,91260).
+char(o,91261).
+char(m,91262).
+char(o,91263).
+char(m,91264).
+char(1,91265).
+char(8,91266).
+char(2,91267).
+char(0,91268).
+char(c,91269).
+char(c,91270).
+char(c,91271).
+char(c,91272).
+char(m,91273).
+char(o,91274).
+char(m,91275).
+char(7,91276).
+char(6,91277).
+char(7,91278).
+char(3,91279).
+char(c,91280).
+char(c,91281).
+char(m,91282).
+char(3,91283).
+char(8,91284).
+char(2,91285).
+char(2,91286).
+char(p,91287).
+char(5,91288).
+char(5,91289).
+char(m,91290).
+char(o,91291).
+char(8,91292).
+char(2,91293).
+char(5,91294).
+char(4,91295).
+char(c,91296).
+char(c,91297).
+char(c,91298).
+char(m,91299).
+char(9,91300).
+char(2,91301).
+char(8,91302).
+char(1,91303).
+char(m,91304).
+char(o,91305).
+char(o,91306).
+char(9,91307).
+char(4,91308).
+char(2,91309).
+char(5,91310).
+char(c,91311).
+char(c,91312).
+char(c,91313).
+char(c,91314).
+char(m,91315).
+char(8,91316).
+char(0,91317).
+char(5,91318).
+char(3,91319).
+char(c,91320).
+char(c,91321).
+char(m,91322).
+char(8,91323).
+char(4,91324).
+char(7,91325).
+char(5,91326).
+char(p,91327).
+char(6,91328).
+char(9,91329).
+char(4,91330).
+char(2,91331).
+char(c,91332).
+char(p,91333).
+char(6,91334).
+char(7,91335).
+char(1,91336).
+char(8,91337).
+char(m,91338).
+char(o,91339).
+char(p,91340).
+char(2,91341).
+char(4,91342).
+char(0,91343).
+char(7,91344).
+char(c,91345).
+char(p,91346).
+char(7,91347).
+char(7,91348).
+char(1,91349).
+char(4,91350).
+char(p,91351).
+char(4,91352).
+char(9,91353).
+char(6,91354).
+char(9,91355).
+char(c,91356).
+char(c,91357).
+char(c,91358).
+char(c,91359).
+char(m,91360).
+char(o,91361).
+char(p,91362).
+char(o,91363).
+char(m,91364).
+char(o,91365).
+char(p,91366).
+char(8,91367).
+char(2,91368).
+char(1,91369).
+char(4,91370).
+char(m,91371).
+char(o,91372).
+char(p,91373).
+char(9,91374).
+char(3,91375).
+char(8,91376).
+char(8,91377).
+char(p,91378).
+char(o,91379).
+char(p,91380).
+char(6,91381).
+char(3,91382).
+char(6,91383).
+char(7,91384).
+char(c,91385).
+char(c,91386).
+char(m,91387).
+char(o,91388).
+char(o,91389).
+char(p,91390).
+char(o,91391).
+char(p,91392).
+char(9,91393).
+char(5,91394).
+char(9,91395).
+char(m,91396).
+char(o,91397).
+char(p,91398).
+char(o,91399).
+char(o,91400).
+char(m,91401).
+char(7,91402).
+char(6,91403).
+char(5,91404).
+char(0,91405).
+char(p,91406).
+char(3,91407).
+char(5,91408).
+char(3,91409).
+char(1,91410).
+char(c,91411).
+char(c,91412).
+char(c,91413).
+char(c,91414).
+char(c,91415).
+char(p,91416).
+char(o,91417).
+char(p,91418).
+char(o,91419).
+char(p,91420).
+char(o,91421).
+char(m,91422).
+char(o,91423).
+char(o,91424).
+char(p,91425).
+char(2,91426).
+char(7,91427).
+char(9,91428).
+char(6,91429).
+char(m,91430).
+char(o,91431).
+char(m,91432).
+char(o,91433).
+char(o,91434).
+char(3,91435).
+char(5,91436).
+char(4,91437).
+char(7,91438).
+char(p,91439).
+char(o,91440).
+char(o,91441).
+char(8,91442).
+char(9,91443).
+char(7,91444).
+char(4,91445).
+char(m,91446).
+char(o,91447).
+char(p,91448).
+char(o,91449).
+char(m,91450).
+char(o,91451).
+char(m,91452).
+char(o,91453).
+char(1,91454).
+char(4,91455).
+char(0,91456).
+char(1,91457).
+char(m,91458).
+char(3,91459).
+char(4,91460).
+char(8,91461).
+char(c,91462).
+char(m,91463).
+char(4,91464).
+char(8,91465).
+char(4,91466).
+char(2,91467).
+char(c,91468).
+char(c,91469).
+char(p,91470).
+char(6,91471).
+char(7,91472).
+char(6,91473).
+char(5,91474).
+char(c,91475).
+char(c,91476).
+char(m,91477).
+char(o,91478).
+char(p,91479).
+char(8,91480).
+char(8,91481).
+char(6,91482).
+char(0,91483).
+char(c,91484).
+char(p,91485).
+char(o,91486).
+char(o,91487).
+char(o,91488).
+char(m,91489).
+char(2,91490).
+char(2,91491).
+char(1,91492).
+char(c,91493).
+char(p,91494).
+char(o,91495).
+char(7,91496).
+char(3,91497).
+char(9,91498).
+char(0,91499).
+char(p,91500).
+char(1,91501).
+char(8,91502).
+char(0,91503).
+char(0,91504).
+char(c,91505).
+char(c,91506).
+char(p,91507).
+char(7,91508).
+char(3,91509).
+char(0,91510).
+char(4,91511).
+char(c,91512).
+char(c,91513).
+char(c,91514).
+char(p,91515).
+char(6,91516).
+char(1,91517).
+char(1,91518).
+char(0,91519).
+char(c,91520).
+char(p,91521).
+char(4,91522).
+char(7,91523).
+char(7,91524).
+char(9,91525).
+char(m,91526).
+char(o,91527).
+char(p,91528).
+char(8,91529).
+char(6,91530).
+char(2,91531).
+char(8,91532).
+char(c,91533).
+char(p,91534).
+char(o,91535).
+char(p,91536).
+char(o,91537).
+char(m,91538).
+char(o,91539).
+char(m,91540).
+char(4,91541).
+char(7,91542).
+char(8,91543).
+char(3,91544).
+char(c,91545).
+char(m,91546).
+char(5,91547).
+char(2,91548).
+char(0,91549).
+char(3,91550).
+char(c,91551).
+char(c,91552).
+char(c,91553).
+char(p,91554).
+char(o,91555).
+char(m,91556).
+char(o,91557).
+char(p,91558).
+char(1,91559).
+char(5,91560).
+char(8,91561).
+char(6,91562).
+char(c,91563).
+char(m,91564).
+char(o,91565).
+char(o,91566).
+char(o,91567).
+char(p,91568).
+char(7,91569).
+char(6,91570).
+char(3,91571).
+char(4,91572).
+char(c,91573).
+char(c,91574).
+char(p,91575).
+char(8,91576).
+char(8,91577).
+char(0,91578).
+char(1,91579).
+char(m,91580).
+char(o,91581).
+char(p,91582).
+char(6,91583).
+char(6,91584).
+char(5,91585).
+char(6,91586).
+char(m,91587).
+char(7,91588).
+char(0,91589).
+char(0,91590).
+char(7,91591).
+char(c,91592).
+char(c,91593).
+char(c,91594).
+char(c,91595).
+char(p,91596).
+char(6,91597).
+char(5,91598).
+char(6,91599).
+char(5,91600).
+char(p,91601).
+char(o,91602).
+char(4,91603).
+char(4,91604).
+char(4,91605).
+char(6,91606).
+char(m,91607).
+char(1,91608).
+char(7,91609).
+char(7,91610).
+char(8,91611).
+char(p,91612).
+char(7,91613).
+char(7,91614).
+char(4,91615).
+char(1,91616).
+char(c,91617).
+char(m,91618).
+char(6,91619).
+char(7,91620).
+char(m,91621).
+char(5,91622).
+char(7,91623).
+char(7,91624).
+char(5,91625).
+char(m,91626).
+char(6,91627).
+char(1,91628).
+char(0,91629).
+char(7,91630).
+char(m,91631).
+char(o,91632).
+char(p,91633).
+char(o,91634).
+char(2,91635).
+char(7,91636).
+char(9,91637).
+char(6,91638).
+char(c,91639).
+char(m,91640).
+char(o,91641).
+char(m,91642).
+char(o,91643).
+char(m,91644).
+char(o,91645).
+char(o,91646).
+char(2,91647).
+char(7,91648).
+char(0,91649).
+char(4,91650).
+char(m,91651).
+char(o,91652).
+char(m,91653).
+char(2,91654).
+char(0,91655).
+char(6,91656).
+char(4,91657).
+char(c,91658).
+char(p,91659).
+char(o,91660).
+char(m,91661).
+char(o,91662).
+char(m,91663).
+char(7,91664).
+char(3,91665).
+char(8,91666).
+char(4,91667).
+char(p,91668).
+char(o,91669).
+char(m,91670).
+char(7,91671).
+char(2,91672).
+char(0,91673).
+char(6,91674).
+char(c,91675).
+char(m,91676).
+char(o,91677).
+char(m,91678).
+char(o,91679).
+char(m,91680).
+char(5,91681).
+char(9,91682).
+char(6,91683).
+char(2,91684).
+char(c,91685).
+char(p,91686).
+char(o,91687).
+char(p,91688).
+char(o,91689).
+char(9,91690).
+char(9,91691).
+char(4,91692).
+char(7,91693).
+char(c,91694).
+char(p,91695).
+char(3,91696).
+char(8,91697).
+char(9,91698).
+char(2,91699).
+char(p,91700).
+char(3,91701).
+char(3,91702).
+char(5,91703).
+char(p,91704).
+char(o,91705).
+char(o,91706).
+char(m,91707).
+char(o,91708).
+char(m,91709).
+char(o,91710).
+char(6,91711).
+char(9,91712).
+char(4,91713).
+char(2,91714).
+char(c,91715).
+char(c,91716).
+char(c,91717).
+char(c,91718).
+char(c,91719).
+char(m,91720).
+char(o,91721).
+char(m,91722).
+char(3,91723).
+char(0,91724).
+char(5,91725).
+char(9,91726).
+char(m,91727).
+char(3,91728).
+char(4,91729).
+char(1,91730).
+char(0,91731).
+char(p,91732).
+char(1,91733).
+char(8,91734).
+char(1,91735).
+char(c,91736).
+char(p,91737).
+char(4,91738).
+char(0,91739).
+char(7,91740).
+char(8,91741).
+char(c,91742).
+char(m,91743).
+char(o,91744).
+char(m,91745).
+char(o,91746).
+char(m,91747).
+char(2,91748).
+char(9,91749).
+char(5,91750).
+char(3,91751).
+char(p,91752).
+char(8,91753).
+char(9,91754).
+char(0,91755).
+char(3,91756).
+char(p,91757).
+char(1,91758).
+char(9,91759).
+char(1,91760).
+char(3,91761).
+char(c,91762).
+char(m,91763).
+char(5,91764).
+char(5,91765).
+char(5,91766).
+char(9,91767).
+char(m,91768).
+char(o,91769).
+char(p,91770).
+char(o,91771).
+char(p,91772).
+char(o,91773).
+char(p,91774).
+char(o,91775).
+char(8,91776).
+char(5,91777).
+char(4,91778).
+char(0,91779).
+char(p,91780).
+char(2,91781).
+char(8,91782).
+char(3,91783).
+char(3,91784).
+char(p,91785).
+char(o,91786).
+char(m,91787).
+char(o,91788).
+char(p,91789).
+char(o,91790).
+char(m,91791).
+char(o,91792).
+char(p,91793).
+char(6,91794).
+char(2,91795).
+char(5,91796).
+char(5,91797).
+char(p,91798).
+char(o,91799).
+char(m,91800).
+char(2,91801).
+char(8,91802).
+char(4,91803).
+char(c,91804).
+char(c,91805).
+char(c,91806).
+char(c,91807).
+char(p,91808).
+char(o,91809).
+char(p,91810).
+char(6,91811).
+char(3,91812).
+char(5,91813).
+char(6,91814).
+char(p,91815).
+char(o,91816).
+char(p,91817).
+char(o,91818).
+char(p,91819).
+char(o,91820).
+char(m,91821).
+char(6,91822).
+char(2,91823).
+char(7,91824).
+char(4,91825).
+char(p,91826).
+char(o,91827).
+char(5,91828).
+char(5,91829).
+char(3,91830).
+char(c,91831).
+char(c,91832).
+char(c,91833).
+char(m,91834).
+char(4,91835).
+char(3,91836).
+char(5,91837).
+char(4,91838).
+char(c,91839).
+char(m,91840).
+char(o,91841).
+char(p,91842).
+char(8,91843).
+char(9,91844).
+char(0,91845).
+char(4,91846).
+char(c,91847).
+char(p,91848).
+char(7,91849).
+char(7,91850).
+char(4,91851).
+char(4,91852).
+char(c,91853).
+char(m,91854).
+char(1,91855).
+char(5,91856).
+char(2,91857).
+char(c,91858).
+char(c,91859).
+char(p,91860).
+char(7,91861).
+char(8,91862).
+char(6,91863).
+char(8,91864).
+char(c,91865).
+char(c,91866).
+char(c,91867).
+char(c,91868).
+char(c,91869).
+char(p,91870).
+char(o,91871).
+char(p,91872).
+char(o,91873).
+char(m,91874).
+char(o,91875).
+char(m,91876).
+char(o,91877).
+char(7,91878).
+char(8,91879).
+char(1,91880).
+char(0,91881).
+char(c,91882).
+char(c,91883).
+char(p,91884).
+char(8,91885).
+char(8,91886).
+char(7,91887).
+char(1,91888).
+char(c,91889).
+char(m,91890).
+char(o,91891).
+char(o,91892).
+char(p,91893).
+char(o,91894).
+char(o,91895).
+char(o,91896).
+char(p,91897).
+char(o,91898).
+char(5,91899).
+char(7,91900).
+char(2,91901).
+char(1,91902).
+char(p,91903).
+char(o,91904).
+char(m,91905).
+char(8,91906).
+char(7,91907).
+char(3,91908).
+char(0,91909).
+char(m,91910).
+char(o,91911).
+char(6,91912).
+char(0,91913).
+char(2,91914).
+char(9,91915).
+char(p,91916).
+char(7,91917).
+char(5,91918).
+char(6,91919).
+char(9,91920).
+char(c,91921).
+char(c,91922).
+char(c,91923).
+char(p,91924).
+char(o,91925).
+char(4,91926).
+char(7,91927).
+char(7,91928).
+char(3,91929).
+char(c,91930).
+char(c,91931).
+char(c,91932).
+char(c,91933).
+char(m,91934).
+char(o,91935).
+char(3,91936).
+char(5,91937).
+char(3,91938).
+char(6,91939).
+char(p,91940).
+char(o,91941).
+char(7,91942).
+char(0,91943).
+char(2,91944).
+char(1,91945).
+char(c,91946).
+char(p,91947).
+char(o,91948).
+char(p,91949).
+char(o,91950).
+char(p,91951).
+char(2,91952).
+char(3,91953).
+char(2,91954).
+char(6,91955).
+char(c,91956).
+char(c,91957).
+char(c,91958).
+char(c,91959).
+char(m,91960).
+char(5,91961).
+char(1,91962).
+char(8,91963).
+char(6,91964).
+char(c,91965).
+char(p,91966).
+char(6,91967).
+char(1,91968).
+char(0,91969).
+char(8,91970).
+char(c,91971).
+char(c,91972).
+char(m,91973).
+char(o,91974).
+char(m,91975).
+char(o,91976).
+char(m,91977).
+char(o,91978).
+char(5,91979).
+char(0,91980).
+char(7,91981).
+char(9,91982).
+char(c,91983).
+char(p,91984).
+char(8,91985).
+char(8,91986).
+char(5,91987).
+char(5,91988).
+char(c,91989).
+char(c,91990).
+char(m,91991).
+char(7,91992).
+char(6,91993).
+char(3,91994).
+char(0,91995).
+char(c,91996).
+char(c,91997).
+char(c,91998).
+char(p,91999).
+char(o,92000).
+char(p,92001).
+char(4,92002).
+char(0,92003).
+char(3,92004).
+char(3,92005).
+char(m,92006).
+char(o,92007).
+char(o,92008).
+char(2,92009).
+char(1,92010).
+char(7,92011).
+char(1,92012).
+char(p,92013).
+char(o,92014).
+char(m,92015).
+char(o,92016).
+char(o,92017).
+char(p,92018).
+char(o,92019).
+char(p,92020).
+char(o,92021).
+char(p,92022).
+char(8,92023).
+char(7,92024).
+char(0,92025).
+char(7,92026).
+char(m,92027).
+char(3,92028).
+char(1,92029).
+char(3,92030).
+char(2,92031).
+char(m,92032).
+char(4,92033).
+char(1,92034).
+char(7,92035).
+char(0,92036).
+char(p,92037).
+char(9,92038).
+char(7,92039).
+char(6,92040).
+char(m,92041).
+char(o,92042).
+char(p,92043).
+char(8,92044).
+char(9,92045).
+char(8,92046).
+char(7,92047).
+char(m,92048).
+char(3,92049).
+char(7,92050).
+char(9,92051).
+char(3,92052).
+char(c,92053).
+char(m,92054).
+char(3,92055).
+char(2,92056).
+char(4,92057).
+char(5,92058).
+char(c,92059).
+char(c,92060).
+char(p,92061).
+char(o,92062).
+char(p,92063).
+char(6,92064).
+char(3,92065).
+char(3,92066).
+char(c,92067).
+char(p,92068).
+char(o,92069).
+char(4,92070).
+char(9,92071).
+char(6,92072).
+char(1,92073).
+char(p,92074).
+char(8,92075).
+char(2,92076).
+char(2,92077).
+char(3,92078).
+char(c,92079).
+char(c,92080).
+char(p,92081).
+char(3,92082).
+char(7,92083).
+char(4,92084).
+char(7,92085).
+char(p,92086).
+char(4,92087).
+char(6,92088).
+char(9,92089).
+char(4,92090).
+char(c,92091).
+char(c,92092).
+char(m,92093).
+char(2,92094).
+char(0,92095).
+char(4,92096).
+char(8,92097).
+char(c,92098).
+char(c,92099).
+char(c,92100).
+char(p,92101).
+char(9,92102).
+char(0,92103).
+char(8,92104).
+char(3,92105).
+char(c,92106).
+char(p,92107).
+char(o,92108).
+char(p,92109).
+char(o,92110).
+char(2,92111).
+char(6,92112).
+char(8,92113).
+char(9,92114).
+char(c,92115).
+char(c,92116).
+char(p,92117).
+char(o,92118).
+char(m,92119).
+char(8,92120).
+char(1,92121).
+char(0,92122).
+char(4,92123).
+char(m,92124).
+char(8,92125).
+char(0,92126).
+char(7,92127).
+char(1,92128).
+char(p,92129).
+char(1,92130).
+char(7,92131).
+char(5,92132).
+char(9,92133).
+char(c,92134).
+char(m,92135).
+char(o,92136).
+char(p,92137).
+char(o,92138).
+char(p,92139).
+char(o,92140).
+char(3,92141).
+char(5,92142).
+char(2,92143).
+char(3,92144).
+char(c,92145).
+char(c,92146).
+char(p,92147).
+char(2,92148).
+char(8,92149).
+char(9,92150).
+char(4,92151).
+char(c,92152).
+char(p,92153).
+char(6,92154).
+char(0,92155).
+char(6,92156).
+char(1,92157).
+char(c,92158).
+char(m,92159).
+char(5,92160).
+char(0,92161).
+char(4,92162).
+char(2,92163).
+char(m,92164).
+char(9,92165).
+char(4,92166).
+char(7,92167).
+char(8,92168).
+char(p,92169).
+char(4,92170).
+char(6,92171).
+char(2,92172).
+char(0,92173).
+char(c,92174).
+char(c,92175).
+char(c,92176).
+char(c,92177).
+char(m,92178).
+char(9,92179).
+char(3,92180).
+char(0,92181).
+char(7,92182).
+char(c,92183).
+char(m,92184).
+char(2,92185).
+char(7,92186).
+char(9,92187).
+char(c,92188).
+char(p,92189).
+char(4,92190).
+char(2,92191).
+char(7,92192).
+char(8,92193).
+char(p,92194).
+char(1,92195).
+char(7,92196).
+char(1,92197).
+char(8,92198).
+char(p,92199).
+char(8,92200).
+char(4,92201).
+char(0,92202).
+char(3,92203).
+char(c,92204).
+char(c,92205).
+char(c,92206).
+char(c,92207).
+char(c,92208).
+char(p,92209).
+char(o,92210).
+char(p,92211).
+char(7,92212).
+char(9,92213).
+char(0,92214).
+char(6,92215).
+char(c,92216).
+char(p,92217).
+char(8,92218).
+char(2,92219).
+char(6,92220).
+char(8,92221).
+char(p,92222).
+char(9,92223).
+char(3,92224).
+char(5,92225).
+char(8,92226).
+char(m,92227).
+char(o,92228).
+char(9,92229).
+char(9,92230).
+char(0,92231).
+char(9,92232).
+char(m,92233).
+char(o,92234).
+char(p,92235).
+char(1,92236).
+char(3,92237).
+char(1,92238).
+char(8,92239).
+char(p,92240).
+char(6,92241).
+char(0,92242).
+char(9,92243).
+char(8,92244).
+char(c,92245).
+char(p,92246).
+char(3,92247).
+char(0,92248).
+char(6,92249).
+char(2,92250).
+char(c,92251).
+char(p,92252).
+char(9,92253).
+char(4,92254).
+char(4,92255).
+char(5,92256).
+char(p,92257).
+char(8,92258).
+char(4,92259).
+char(1,92260).
+char(0,92261).
+char(p,92262).
+char(o,92263).
+char(o,92264).
+char(o,92265).
+char(p,92266).
+char(o,92267).
+char(p,92268).
+char(o,92269).
+char(8,92270).
+char(2,92271).
+char(2,92272).
+char(7,92273).
+char(c,92274).
+char(c,92275).
+char(m,92276).
+char(o,92277).
+char(m,92278).
+char(o,92279).
+char(2,92280).
+char(0,92281).
+char(4,92282).
+char(5,92283).
+char(c,92284).
+char(c,92285).
+char(m,92286).
+char(o,92287).
+char(p,92288).
+char(4,92289).
+char(4,92290).
+char(3,92291).
+char(0,92292).
+char(c,92293).
+char(c,92294).
+char(p,92295).
+char(o,92296).
+char(o,92297).
+char(p,92298).
+char(2,92299).
+char(8,92300).
+char(3,92301).
+char(2,92302).
+char(c,92303).
+char(c,92304).
+char(m,92305).
+char(o,92306).
+char(2,92307).
+char(5,92308).
+char(0,92309).
+char(4,92310).
+char(c,92311).
+char(c,92312).
+char(c,92313).
+char(c,92314).
+char(p,92315).
+char(o,92316).
+char(o,92317).
+char(m,92318).
+char(o,92319).
+char(m,92320).
+char(1,92321).
+char(4,92322).
+char(1,92323).
+char(9,92324).
+char(c,92325).
+char(m,92326).
+char(5,92327).
+char(1,92328).
+char(2,92329).
+char(5,92330).
+char(c,92331).
+char(c,92332).
+char(p,92333).
+char(o,92334).
+char(p,92335).
+char(6,92336).
+char(1,92337).
+char(5,92338).
+char(2,92339).
+char(c,92340).
+char(p,92341).
+char(7,92342).
+char(4,92343).
+char(8,92344).
+char(3,92345).
+char(c,92346).
+char(c,92347).
+char(p,92348).
+char(9,92349).
+char(0,92350).
+char(1,92351).
+char(7,92352).
+char(p,92353).
+char(3,92354).
+char(9,92355).
+char(9,92356).
+char(2,92357).
+char(m,92358).
+char(o,92359).
+char(o,92360).
+char(p,92361).
+char(o,92362).
+char(p,92363).
+char(2,92364).
+char(6,92365).
+char(1,92366).
+char(7,92367).
+char(p,92368).
+char(8,92369).
+char(6,92370).
+char(5,92371).
+char(6,92372).
+char(c,92373).
+char(p,92374).
+char(o,92375).
+char(p,92376).
+char(1,92377).
+char(0,92378).
+char(1,92379).
+char(8,92380).
+char(p,92381).
+char(o,92382).
+char(o,92383).
+char(m,92384).
+char(5,92385).
+char(0,92386).
+char(9,92387).
+char(8,92388).
+char(c,92389).
+char(p,92390).
+char(o,92391).
+char(p,92392).
+char(o,92393).
+char(8,92394).
+char(6,92395).
+char(4,92396).
+char(7,92397).
+char(p,92398).
+char(5,92399).
+char(8,92400).
+char(2,92401).
+char(4,92402).
+char(p,92403).
+char(6,92404).
+char(7,92405).
+char(9,92406).
+char(7,92407).
+char(p,92408).
+char(o,92409).
+char(8,92410).
+char(4,92411).
+char(1,92412).
+char(9,92413).
+char(c,92414).
+char(p,92415).
+char(7,92416).
+char(8,92417).
+char(3,92418).
+char(9,92419).
+char(c,92420).
+char(c,92421).
+char(p,92422).
+char(1,92423).
+char(8,92424).
+char(4,92425).
+char(0,92426).
+char(m,92427).
+char(o,92428).
+char(4,92429).
+char(4,92430).
+char(1,92431).
+char(c,92432).
+char(c,92433).
+char(p,92434).
+char(o,92435).
+char(m,92436).
+char(2,92437).
+char(1,92438).
+char(5,92439).
+char(9,92440).
+char(m,92441).
+char(4,92442).
+char(8,92443).
+char(4,92444).
+char(8,92445).
+char(p,92446).
+char(o,92447).
+char(7,92448).
+char(7,92449).
+char(8,92450).
+char(3,92451).
+char(p,92452).
+char(1,92453).
+char(2,92454).
+char(4,92455).
+char(3,92456).
+char(m,92457).
+char(o,92458).
+char(p,92459).
+char(o,92460).
+char(p,92461).
+char(1,92462).
+char(7,92463).
+char(0,92464).
+char(2,92465).
+char(p,92466).
+char(8,92467).
+char(5,92468).
+char(0,92469).
+char(1,92470).
+char(p,92471).
+char(o,92472).
+char(p,92473).
+char(o,92474).
+char(p,92475).
+char(o,92476).
+char(m,92477).
+char(o,92478).
+char(3,92479).
+char(2,92480).
+char(6,92481).
+char(3,92482).
+char(p,92483).
+char(6,92484).
+char(5,92485).
+char(9,92486).
+char(9,92487).
+char(p,92488).
+char(o,92489).
+char(p,92490).
+char(3,92491).
+char(5,92492).
+char(7,92493).
+char(6,92494).
+char(c,92495).
+char(p,92496).
+char(3,92497).
+char(5,92498).
+char(3,92499).
+char(c,92500).
+char(p,92501).
+char(6,92502).
+char(5,92503).
+char(1,92504).
+char(c,92505).
+char(m,92506).
+char(o,92507).
+char(m,92508).
+char(o,92509).
+char(p,92510).
+char(7,92511).
+char(5,92512).
+char(2,92513).
+char(4,92514).
+char(m,92515).
+char(o,92516).
+char(p,92517).
+char(8,92518).
+char(4,92519).
+char(9,92520).
+char(8,92521).
+char(c,92522).
+char(p,92523).
+char(o,92524).
+char(1,92525).
+char(7,92526).
+char(0,92527).
+char(6,92528).
+char(c,92529).
+char(m,92530).
+char(o,92531).
+char(p,92532).
+char(6,92533).
+char(7,92534).
+char(4,92535).
+char(2,92536).
+char(m,92537).
+char(o,92538).
+char(4,92539).
+char(3,92540).
+char(2,92541).
+char(4,92542).
+char(c,92543).
+char(c,92544).
+char(m,92545).
+char(o,92546).
+char(7,92547).
+char(3,92548).
+char(4,92549).
+char(6,92550).
+char(p,92551).
+char(o,92552).
+char(m,92553).
+char(3,92554).
+char(7,92555).
+char(1,92556).
+char(5,92557).
+char(c,92558).
+char(c,92559).
+char(c,92560).
+char(c,92561).
+char(p,92562).
+char(o,92563).
+char(m,92564).
+char(o,92565).
+char(p,92566).
+char(5,92567).
+char(1,92568).
+char(9,92569).
+char(5,92570).
+char(c,92571).
+char(p,92572).
+char(o,92573).
+char(p,92574).
+char(o,92575).
+char(m,92576).
+char(o,92577).
+char(4,92578).
+char(0,92579).
+char(8,92580).
+char(4,92581).
+char(c,92582).
+char(p,92583).
+char(3,92584).
+char(6,92585).
+char(0,92586).
+char(5,92587).
+char(c,92588).
+char(c,92589).
+char(c,92590).
+char(m,92591).
+char(8,92592).
+char(8,92593).
+char(2,92594).
+char(4,92595).
+char(p,92596).
+char(9,92597).
+char(3,92598).
+char(7,92599).
+char(3,92600).
+char(p,92601).
+char(o,92602).
+char(m,92603).
+char(8,92604).
+char(2,92605).
+char(9,92606).
+char(9,92607).
+char(m,92608).
+char(6,92609).
+char(5,92610).
+char(9,92611).
+char(9,92612).
+char(c,92613).
+char(p,92614).
+char(o,92615).
+char(p,92616).
+char(o,92617).
+char(p,92618).
+char(6,92619).
+char(3,92620).
+char(6,92621).
+char(6,92622).
+char(p,92623).
+char(6,92624).
+char(7,92625).
+char(8,92626).
+char(3,92627).
+char(c,92628).
+char(m,92629).
+char(o,92630).
+char(o,92631).
+char(p,92632).
+char(9,92633).
+char(0,92634).
+char(6,92635).
+char(6,92636).
+char(c,92637).
+char(c,92638).
+char(m,92639).
+char(o,92640).
+char(p,92641).
+char(5,92642).
+char(8,92643).
+char(3,92644).
+char(4,92645).
+char(c,92646).
+char(c,92647).
+char(c,92648).
+char(c,92649).
+char(c,92650).
+char(p,92651).
+char(o,92652).
+char(p,92653).
+char(8,92654).
+char(0,92655).
+char(1,92656).
+char(1,92657).
+char(c,92658).
+char(c,92659).
+char(m,92660).
+char(3,92661).
+char(4,92662).
+char(1,92663).
+char(8,92664).
+char(c,92665).
+char(m,92666).
+char(o,92667).
+char(m,92668).
+char(o,92669).
+char(1,92670).
+char(0,92671).
+char(2,92672).
+char(2,92673).
+char(p,92674).
+char(o,92675).
+char(p,92676).
+char(3,92677).
+char(8,92678).
+char(6,92679).
+char(c,92680).
+char(c,92681).
+char(c,92682).
+char(c,92683).
+char(c,92684).
+char(c,92685).
+char(c,92686).
+char(p,92687).
+char(o,92688).
+char(p,92689).
+char(o,92690).
+char(1,92691).
+char(5,92692).
+char(4,92693).
+char(0,92694).
+char(c,92695).
+char(c,92696).
+char(p,92697).
+char(6,92698).
+char(7,92699).
+char(0,92700).
+char(6,92701).
+char(c,92702).
+char(c,92703).
+char(c,92704).
+char(p,92705).
+char(o,92706).
+char(p,92707).
+char(o,92708).
+char(9,92709).
+char(6,92710).
+char(0,92711).
+char(7,92712).
+char(c,92713).
+char(p,92714).
+char(o,92715).
+char(o,92716).
+char(p,92717).
+char(o,92718).
+char(p,92719).
+char(o,92720).
+char(m,92721).
+char(4,92722).
+char(8,92723).
+char(7,92724).
+char(9,92725).
+char(c,92726).
+char(p,92727).
+char(1,92728).
+char(4,92729).
+char(5,92730).
+char(6,92731).
+char(c,92732).
+char(m,92733).
+char(1,92734).
+char(4,92735).
+char(2,92736).
+char(1,92737).
+char(c,92738).
+char(p,92739).
+char(3,92740).
+char(0,92741).
+char(1,92742).
+char(3,92743).
+char(p,92744).
+char(o,92745).
+char(o,92746).
+char(p,92747).
+char(5,92748).
+char(8,92749).
+char(7,92750).
+char(m,92751).
+char(1,92752).
+char(1,92753).
+char(2,92754).
+char(9,92755).
+char(c,92756).
+char(p,92757).
+char(9,92758).
+char(8,92759).
+char(9,92760).
+char(3,92761).
+char(c,92762).
+char(p,92763).
+char(8,92764).
+char(4,92765).
+char(7,92766).
+char(8,92767).
+char(p,92768).
+char(7,92769).
+char(3,92770).
+char(1,92771).
+char(5,92772).
+char(p,92773).
+char(8,92774).
+char(0,92775).
+char(8,92776).
+char(4,92777).
+char(p,92778).
+char(o,92779).
+char(o,92780).
+char(m,92781).
+char(o,92782).
+char(p,92783).
+char(3,92784).
+char(3,92785).
+char(0,92786).
+char(c,92787).
+char(m,92788).
+char(o,92789).
+char(p,92790).
+char(1,92791).
+char(6,92792).
+char(5,92793).
+char(9,92794).
+char(c,92795).
+char(p,92796).
+char(5,92797).
+char(9,92798).
+char(9,92799).
+char(2,92800).
+char(c,92801).
+char(p,92802).
+char(6,92803).
+char(7,92804).
+char(9,92805).
+char(3,92806).
+char(p,92807).
+char(o,92808).
+char(p,92809).
+char(1,92810).
+char(7,92811).
+char(3,92812).
+char(2,92813).
+char(p,92814).
+char(o,92815).
+char(p,92816).
+char(5,92817).
+char(0,92818).
+char(6,92819).
+char(p,92820).
+char(4,92821).
+char(5,92822).
+char(3,92823).
+char(5,92824).
+char(c,92825).
+char(m,92826).
+char(o,92827).
+char(m,92828).
+char(o,92829).
+char(p,92830).
+char(2,92831).
+char(8,92832).
+char(8,92833).
+char(2,92834).
+char(c,92835).
+char(m,92836).
+char(6,92837).
+char(6,92838).
+char(6,92839).
+char(1,92840).
+char(c,92841).
+char(p,92842).
+char(1,92843).
+char(1,92844).
+char(9,92845).
+char(7,92846).
+char(c,92847).
+char(c,92848).
+char(c,92849).
+char(m,92850).
+char(o,92851).
+char(o,92852).
+char(1,92853).
+char(3,92854).
+char(9,92855).
+char(9,92856).
+char(c,92857).
+char(c,92858).
+char(p,92859).
+char(o,92860).
+char(m,92861).
+char(o,92862).
+char(m,92863).
+char(o,92864).
+char(o,92865).
+char(p,92866).
+char(o,92867).
+char(3,92868).
+char(6,92869).
+char(3,92870).
+char(5,92871).
+char(c,92872).
+char(p,92873).
+char(o,92874).
+char(p,92875).
+char(o,92876).
+char(p,92877).
+char(o,92878).
+char(m,92879).
+char(o,92880).
+char(p,92881).
+char(3,92882).
+char(3,92883).
+char(1,92884).
+char(4,92885).
+char(c,92886).
+char(c,92887).
+char(c,92888).
+char(p,92889).
+char(7,92890).
+char(8,92891).
+char(5,92892).
+char(2,92893).
+char(c,92894).
+char(c,92895).
+char(m,92896).
+char(8,92897).
+char(3,92898).
+char(9,92899).
+char(8,92900).
+char(m,92901).
+char(o,92902).
+char(5,92903).
+char(9,92904).
+char(1,92905).
+char(3,92906).
+char(p,92907).
+char(8,92908).
+char(7,92909).
+char(4,92910).
+char(1,92911).
+char(c,92912).
+char(m,92913).
+char(o,92914).
+char(p,92915).
+char(1,92916).
+char(6,92917).
+char(4,92918).
+char(0,92919).
+char(m,92920).
+char(4,92921).
+char(0,92922).
+char(3,92923).
+char(2,92924).
+char(p,92925).
+char(5,92926).
+char(1,92927).
+char(4,92928).
+char(9,92929).
+char(m,92930).
+char(o,92931).
+char(m,92932).
+char(4,92933).
+char(4,92934).
+char(2,92935).
+char(3,92936).
+char(c,92937).
+char(c,92938).
+char(p,92939).
+char(o,92940).
+char(3,92941).
+char(9,92942).
+char(1,92943).
+char(0,92944).
+char(c,92945).
+char(p,92946).
+char(6,92947).
+char(2,92948).
+char(9,92949).
+char(3,92950).
+char(c,92951).
+char(c,92952).
+char(m,92953).
+char(6,92954).
+char(6,92955).
+char(1,92956).
+char(8,92957).
+char(c,92958).
+char(c,92959).
+char(c,92960).
+char(c,92961).
+char(m,92962).
+char(o,92963).
+char(p,92964).
+char(o,92965).
+char(p,92966).
+char(o,92967).
+char(o,92968).
+char(m,92969).
+char(3,92970).
+char(4,92971).
+char(1,92972).
+char(5,92973).
+char(m,92974).
+char(1,92975).
+char(6,92976).
+char(6,92977).
+char(5,92978).
+char(c,92979).
+char(c,92980).
+char(p,92981).
+char(6,92982).
+char(3,92983).
+char(0,92984).
+char(1,92985).
+char(p,92986).
+char(o,92987).
+char(1,92988).
+char(3,92989).
+char(2,92990).
+char(7,92991).
+char(p,92992).
+char(o,92993).
+char(m,92994).
+char(o,92995).
+char(m,92996).
+char(o,92997).
+char(o,92998).
+char(o,92999).
+char(o,93000).
+char(m,93001).
+char(o,93002).
+char(7,93003).
+char(7,93004).
+char(1,93005).
+char(2,93006).
+char(c,93007).
+char(c,93008).
+char(c,93009).
+char(m,93010).
+char(o,93011).
+char(m,93012).
+char(o,93013).
+char(6,93014).
+char(7,93015).
+char(3,93016).
+char(3,93017).
+char(p,93018).
+char(5,93019).
+char(3,93020).
+char(7,93021).
+char(6,93022).
+char(p,93023).
+char(9,93024).
+char(3,93025).
+char(5,93026).
+char(1,93027).
+char(c,93028).
+char(p,93029).
+char(o,93030).
+char(o,93031).
+char(2,93032).
+char(8,93033).
+char(6,93034).
+char(2,93035).
+char(c,93036).
+char(c,93037).
+char(p,93038).
+char(8,93039).
+char(7,93040).
+char(6,93041).
+char(2,93042).
+char(p,93043).
+char(o,93044).
+char(7,93045).
+char(4,93046).
+char(4,93047).
+char(1,93048).
+char(c,93049).
+char(c,93050).
+char(m,93051).
+char(4,93052).
+char(0,93053).
+char(0,93054).
+char(6,93055).
+char(c,93056).
+char(m,93057).
+char(8,93058).
+char(4,93059).
+char(3,93060).
+char(9,93061).
+char(c,93062).
+char(c,93063).
+char(p,93064).
+char(1,93065).
+char(6,93066).
+char(5,93067).
+char(2,93068).
+char(c,93069).
+char(c,93070).
+char(c,93071).
+char(c,93072).
+char(m,93073).
+char(o,93074).
+char(p,93075).
+char(5,93076).
+char(8,93077).
+char(9,93078).
+char(p,93079).
+char(o,93080).
+char(m,93081).
+char(o,93082).
+char(m,93083).
+char(o,93084).
+char(8,93085).
+char(2,93086).
+char(5,93087).
+char(p,93088).
+char(o,93089).
+char(m,93090).
+char(8,93091).
+char(3,93092).
+char(1,93093).
+char(8,93094).
+char(c,93095).
+char(p,93096).
+char(9,93097).
+char(1,93098).
+char(7,93099).
+char(0,93100).
+char(m,93101).
+char(o,93102).
+char(4,93103).
+char(6,93104).
+char(6,93105).
+char(5,93106).
+char(c,93107).
+char(c,93108).
+char(m,93109).
+char(7,93110).
+char(8,93111).
+char(1,93112).
+char(6,93113).
+char(c,93114).
+char(p,93115).
+char(o,93116).
+char(o,93117).
+char(m,93118).
+char(3,93119).
+char(1,93120).
+char(2,93121).
+char(2,93122).
+char(p,93123).
+char(o,93124).
+char(m,93125).
+char(2,93126).
+char(0,93127).
+char(4,93128).
+char(2,93129).
+char(p,93130).
+char(9,93131).
+char(0,93132).
+char(1,93133).
+char(5,93134).
+char(m,93135).
+char(o,93136).
+char(m,93137).
+char(3,93138).
+char(2,93139).
+char(8,93140).
+char(9,93141).
+char(p,93142).
+char(o,93143).
+char(o,93144).
+char(m,93145).
+char(o,93146).
+char(m,93147).
+char(7,93148).
+char(5,93149).
+char(1,93150).
+char(6,93151).
+char(p,93152).
+char(2,93153).
+char(5,93154).
+char(9,93155).
+char(m,93156).
+char(o,93157).
+char(m,93158).
+char(4,93159).
+char(4,93160).
+char(1,93161).
+char(3,93162).
+char(p,93163).
+char(o,93164).
+char(p,93165).
+char(o,93166).
+char(3,93167).
+char(8,93168).
+char(6,93169).
+char(6,93170).
+char(c,93171).
+char(c,93172).
+char(p,93173).
+char(5,93174).
+char(1,93175).
+char(2,93176).
+char(7,93177).
+char(m,93178).
+char(6,93179).
+char(0,93180).
+char(0,93181).
+char(3,93182).
+char(m,93183).
+char(8,93184).
+char(9,93185).
+char(1,93186).
+char(7,93187).
+char(c,93188).
+char(p,93189).
+char(o,93190).
+char(m,93191).
+char(o,93192).
+char(m,93193).
+char(o,93194).
+char(o,93195).
+char(o,93196).
+char(p,93197).
+char(4,93198).
+char(6,93199).
+char(2,93200).
+char(0,93201).
+char(c,93202).
+char(c,93203).
+char(m,93204).
+char(o,93205).
+char(o,93206).
+char(p,93207).
+char(8,93208).
+char(0,93209).
+char(2,93210).
+char(1,93211).
+char(c,93212).
+char(c,93213).
+char(p,93214).
+char(3,93215).
+char(4,93216).
+char(8,93217).
+char(9,93218).
+char(c,93219).
+char(c,93220).
+char(m,93221).
+char(o,93222).
+char(2,93223).
+char(3,93224).
+char(0,93225).
+char(6,93226).
+char(m,93227).
+char(1,93228).
+char(7,93229).
+char(4,93230).
+char(1,93231).
+char(m,93232).
+char(o,93233).
+char(m,93234).
+char(6,93235).
+char(4,93236).
+char(1,93237).
+char(5,93238).
+char(p,93239).
+char(1,93240).
+char(9,93241).
+char(1,93242).
+char(3,93243).
+char(c,93244).
+char(c,93245).
+char(p,93246).
+char(o,93247).
+char(m,93248).
+char(o,93249).
+char(o,93250).
+char(p,93251).
+char(7,93252).
+char(6,93253).
+char(7,93254).
+char(4,93255).
+char(c,93256).
+char(p,93257).
+char(2,93258).
+char(0,93259).
+char(5,93260).
+char(6,93261).
+char(c,93262).
+char(m,93263).
+char(3,93264).
+char(6,93265).
+char(8,93266).
+char(3,93267).
+char(p,93268).
+char(o,93269).
+char(o,93270).
+char(m,93271).
+char(5,93272).
+char(3,93273).
+char(3,93274).
+char(7,93275).
+char(c,93276).
+char(m,93277).
+char(2,93278).
+char(4,93279).
+char(8,93280).
+char(4,93281).
+char(m,93282).
+char(3,93283).
+char(2,93284).
+char(0,93285).
+char(7,93286).
+char(c,93287).
+char(c,93288).
+char(m,93289).
+char(4,93290).
+char(3,93291).
+char(0,93292).
+char(1,93293).
+char(c,93294).
+char(c,93295).
+char(p,93296).
+char(1,93297).
+char(8,93298).
+char(5,93299).
+char(7,93300).
+char(c,93301).
+char(c,93302).
+char(c,93303).
+char(c,93304).
+char(c,93305).
+char(c,93306).
+char(c,93307).
+char(m,93308).
+char(o,93309).
+char(m,93310).
+char(4,93311).
+char(6,93312).
+char(2,93313).
+char(4,93314).
+char(c,93315).
+char(p,93316).
+char(o,93317).
+char(p,93318).
+char(o,93319).
+char(o,93320).
+char(m,93321).
+char(3,93322).
+char(4,93323).
+char(7,93324).
+char(1,93325).
+char(c,93326).
+char(m,93327).
+char(2,93328).
+char(9,93329).
+char(4,93330).
+char(6,93331).
+char(p,93332).
+char(5,93333).
+char(6,93334).
+char(4,93335).
+char(2,93336).
+char(c,93337).
+char(c,93338).
+char(c,93339).
+char(m,93340).
+char(o,93341).
+char(o,93342).
+char(2,93343).
+char(0,93344).
+char(4,93345).
+char(8,93346).
+char(m,93347).
+char(2,93348).
+char(4,93349).
+char(1,93350).
+char(5,93351).
+char(c,93352).
+char(c,93353).
+char(c,93354).
+char(p,93355).
+char(7,93356).
+char(2,93357).
+char(7,93358).
+char(7,93359).
+char(p,93360).
+char(9,93361).
+char(7,93362).
+char(0,93363).
+char(9,93364).
+char(c,93365).
+char(p,93366).
+char(6,93367).
+char(6,93368).
+char(8,93369).
+char(6,93370).
+char(p,93371).
+char(7,93372).
+char(1,93373).
+char(6,93374).
+char(7,93375).
+char(p,93376).
+char(8,93377).
+char(6,93378).
+char(8,93379).
+char(5,93380).
+char(c,93381).
+char(p,93382).
+char(8,93383).
+char(8,93384).
+char(6,93385).
+char(7,93386).
+char(p,93387).
+char(4,93388).
+char(9,93389).
+char(8,93390).
+char(3,93391).
+char(c,93392).
+char(c,93393).
+char(c,93394).
+char(p,93395).
+char(o,93396).
+char(m,93397).
+char(6,93398).
+char(3,93399).
+char(0,93400).
+char(2,93401).
+char(m,93402).
+char(2,93403).
+char(5,93404).
+char(4,93405).
+char(9,93406).
+char(c,93407).
+char(c,93408).
+char(c,93409).
+char(p,93410).
+char(o,93411).
+char(o,93412).
+char(5,93413).
+char(6,93414).
+char(1,93415).
+char(3,93416).
+char(m,93417).
+char(1,93418).
+char(1,93419).
+char(1,93420).
+char(7,93421).
+char(c,93422).
+char(m,93423).
+char(2,93424).
+char(1,93425).
+char(5,93426).
+char(9,93427).
+char(c,93428).
+char(c,93429).
+char(m,93430).
+char(o,93431).
+char(p,93432).
+char(o,93433).
+char(o,93434).
+char(m,93435).
+char(o,93436).
+char(m,93437).
+char(o,93438).
+char(p,93439).
+char(3,93440).
+char(6,93441).
+char(4,93442).
+char(0,93443).
+char(p,93444).
+char(o,93445).
+char(8,93446).
+char(5,93447).
+char(9,93448).
+char(7,93449).
+char(c,93450).
+char(m,93451).
+char(o,93452).
+char(p,93453).
+char(8,93454).
+char(8,93455).
+char(8,93456).
+char(8,93457).
+char(m,93458).
+char(o,93459).
+char(m,93460).
+char(o,93461).
+char(o,93462).
+char(o,93463).
+char(m,93464).
+char(o,93465).
+char(p,93466).
+char(4,93467).
+char(2,93468).
+char(1,93469).
+char(5,93470).
+char(m,93471).
+char(3,93472).
+char(7,93473).
+char(9,93474).
+char(3,93475).
+char(c,93476).
+char(c,93477).
+char(c,93478).
+char(c,93479).
+char(p,93480).
+char(o,93481).
+char(m,93482).
+char(4,93483).
+char(3,93484).
+char(1,93485).
+char(6,93486).
+char(c,93487).
+char(c,93488).
+char(m,93489).
+char(1,93490).
+char(5,93491).
+char(8,93492).
+char(8,93493).
+char(c,93494).
+char(c,93495).
+char(m,93496).
+char(o,93497).
+char(m,93498).
+char(2,93499).
+char(5,93500).
+char(5,93501).
+char(1,93502).
+char(c,93503).
+char(p,93504).
+char(o,93505).
+char(m,93506).
+char(o,93507).
+char(m,93508).
+char(4,93509).
+char(5,93510).
+char(6,93511).
+char(9,93512).
+char(c,93513).
+char(c,93514).
+char(p,93515).
+char(2,93516).
+char(6,93517).
+char(6,93518).
+char(1,93519).
+char(m,93520).
+char(o,93521).
+char(p,93522).
+char(7,93523).
+char(3,93524).
+char(1,93525).
+char(m,93526).
+char(7,93527).
+char(3,93528).
+char(6,93529).
+char(3,93530).
+char(p,93531).
+char(o,93532).
+char(p,93533).
+char(o,93534).
+char(o,93535).
+char(m,93536).
+char(7,93537).
+char(6,93538).
+char(7,93539).
+char(7,93540).
+char(c,93541).
+char(c,93542).
+char(c,93543).
+char(m,93544).
+char(o,93545).
+char(o,93546).
+char(m,93547).
+char(5,93548).
+char(8,93549).
+char(9,93550).
+char(5,93551).
+char(c,93552).
+char(c,93553).
+char(c,93554).
+char(c,93555).
+char(m,93556).
+char(4,93557).
+char(2,93558).
+char(7,93559).
+char(c,93560).
+char(p,93561).
+char(8,93562).
+char(5,93563).
+char(6,93564).
+char(0,93565).
+char(m,93566).
+char(o,93567).
+char(m,93568).
+char(o,93569).
+char(p,93570).
+char(o,93571).
+char(p,93572).
+char(1,93573).
+char(5,93574).
+char(3,93575).
+char(5,93576).
+char(c,93577).
+char(c,93578).
+char(m,93579).
+char(2,93580).
+char(7,93581).
+char(9,93582).
+char(1,93583).
+char(p,93584).
+char(o,93585).
+char(o,93586).
+char(7,93587).
+char(8,93588).
+char(6,93589).
+char(9,93590).
+char(m,93591).
+char(4,93592).
+char(2,93593).
+char(8,93594).
+char(4,93595).
+char(c,93596).
+char(m,93597).
+char(o,93598).
+char(p,93599).
+char(1,93600).
+char(4,93601).
+char(0,93602).
+char(9,93603).
+char(c,93604).
+char(c,93605).
+char(c,93606).
+char(p,93607).
+char(1,93608).
+char(8,93609).
+char(6,93610).
+char(2,93611).
+char(c,93612).
+char(p,93613).
+char(5,93614).
+char(m,93615).
+char(2,93616).
+char(5,93617).
+char(8,93618).
+char(9,93619).
+char(m,93620).
+char(4,93621).
+char(3,93622).
+char(4,93623).
+char(8,93624).
+char(p,93625).
+char(2,93626).
+char(9,93627).
+char(1,93628).
+char(8,93629).
+char(c,93630).
+char(c,93631).
+char(c,93632).
+char(c,93633).
+char(c,93634).
+char(c,93635).
+char(c,93636).
+char(m,93637).
+char(o,93638).
+char(p,93639).
+char(o,93640).
+char(p,93641).
+char(o,93642).
+char(m,93643).
+char(8,93644).
+char(9,93645).
+char(5,93646).
+char(7,93647).
+char(p,93648).
+char(o,93649).
+char(9,93650).
+char(9,93651).
+char(6,93652).
+char(c,93653).
+char(m,93654).
+char(o,93655).
+char(p,93656).
+char(o,93657).
+char(p,93658).
+char(5,93659).
+char(8,93660).
+char(5,93661).
+char(7,93662).
+char(c,93663).
+char(c,93664).
+char(c,93665).
+char(m,93666).
+char(o,93667).
+char(m,93668).
+char(o,93669).
+char(m,93670).
+char(4,93671).
+char(5,93672).
+char(7,93673).
+char(0,93674).
+char(m,93675).
+char(o,93676).
+char(m,93677).
+char(3,93678).
+char(5,93679).
+char(0,93680).
+char(3,93681).
+char(c,93682).
+char(c,93683).
+char(c,93684).
+char(c,93685).
+char(m,93686).
+char(o,93687).
+char(6,93688).
+char(8,93689).
+char(5,93690).
+char(3,93691).
+char(c,93692).
+char(c,93693).
+char(c,93694).
+char(c,93695).
+char(c,93696).
+char(p,93697).
+char(o,93698).
+char(4,93699).
+char(5,93700).
+char(9,93701).
+char(7,93702).
+char(p,93703).
+char(6,93704).
+char(3,93705).
+char(9,93706).
+char(6,93707).
+char(p,93708).
+char(o,93709).
+char(3,93710).
+char(1,93711).
+char(3,93712).
+char(5,93713).
+char(p,93714).
+char(9,93715).
+char(7,93716).
+char(7,93717).
+char(2,93718).
+char(c,93719).
+char(p,93720).
+char(6,93721).
+char(1,93722).
+char(3,93723).
+char(6,93724).
+char(p,93725).
+char(4,93726).
+char(4,93727).
+char(1,93728).
+char(5,93729).
+char(p,93730).
+char(o,93731).
+char(o,93732).
+char(7,93733).
+char(4,93734).
+char(3,93735).
+char(4,93736).
+char(p,93737).
+char(o,93738).
+char(8,93739).
+char(5,93740).
+char(1,93741).
+char(3,93742).
+char(c,93743).
+char(p,93744).
+char(o,93745).
+char(p,93746).
+char(o,93747).
+char(m,93748).
+char(1,93749).
+char(8,93750).
+char(8,93751).
+char(3,93752).
+char(c,93753).
+char(m,93754).
+char(o,93755).
+char(m,93756).
+char(7,93757).
+char(7,93758).
+char(1,93759).
+char(3,93760).
+char(c,93761).
+char(c,93762).
+char(c,93763).
+char(p,93764).
+char(o,93765).
+char(m,93766).
+char(7,93767).
+char(4,93768).
+char(8,93769).
+char(c,93770).
+char(c,93771).
+char(c,93772).
+char(p,93773).
+char(8,93774).
+char(4,93775).
+char(1,93776).
+char(4,93777).
+char(c,93778).
+char(p,93779).
+char(o,93780).
+char(p,93781).
+char(5,93782).
+char(6,93783).
+char(7,93784).
+char(7,93785).
+char(c,93786).
+char(c,93787).
+char(m,93788).
+char(o,93789).
+char(m,93790).
+char(8,93791).
+char(7,93792).
+char(1,93793).
+char(4,93794).
+char(c,93795).
+char(m,93796).
+char(o,93797).
+char(m,93798).
+char(6,93799).
+char(2,93800).
+char(9,93801).
+char(8,93802).
+char(m,93803).
+char(o,93804).
+char(m,93805).
+char(3,93806).
+char(5,93807).
+char(0,93808).
+char(9,93809).
+char(c,93810).
+char(c,93811).
+char(p,93812).
+char(3,93813).
+char(1,93814).
+char(5,93815).
+char(1,93816).
+char(c,93817).
+char(m,93818).
+char(7,93819).
+char(2,93820).
+char(3,93821).
+char(3,93822).
+char(c,93823).
+char(c,93824).
+char(p,93825).
+char(7,93826).
+char(2,93827).
+char(5,93828).
+char(3,93829).
+char(p,93830).
+char(o,93831).
+char(p,93832).
+char(o,93833).
+char(m,93834).
+char(5,93835).
+char(4,93836).
+char(6,93837).
+char(2,93838).
+char(p,93839).
+char(o,93840).
+char(3,93841).
+char(9,93842).
+char(1,93843).
+char(7,93844).
+char(p,93845).
+char(o,93846).
+char(1,93847).
+char(7,93848).
+char(2,93849).
+char(0,93850).
+char(c,93851).
+char(m,93852).
+char(o,93853).
+char(p,93854).
+char(o,93855).
+char(m,93856).
+char(1,93857).
+char(3,93858).
+char(3,93859).
+char(0,93860).
+char(m,93861).
+char(9,93862).
+char(9,93863).
+char(4,93864).
+char(8,93865).
+char(c,93866).
+char(p,93867).
+char(8,93868).
+char(8,93869).
+char(9,93870).
+char(0,93871).
+char(c,93872).
+char(p,93873).
+char(o,93874).
+char(p,93875).
+char(o,93876).
+char(8,93877).
+char(5,93878).
+char(8,93879).
+char(9,93880).
+char(c,93881).
+char(c,93882).
+char(p,93883).
+char(3,93884).
+char(5,93885).
+char(6,93886).
+char(5,93887).
+char(c,93888).
+char(c,93889).
+char(p,93890).
+char(o,93891).
+char(o,93892).
+char(m,93893).
+char(o,93894).
+char(m,93895).
+char(4,93896).
+char(6,93897).
+char(2,93898).
+char(9,93899).
+char(m,93900).
+char(o,93901).
+char(p,93902).
+char(o,93903).
+char(5,93904).
+char(7,93905).
+char(8,93906).
+char(2,93907).
+char(c,93908).
+char(c,93909).
+char(m,93910).
+char(5,93911).
+char(3,93912).
+char(9,93913).
+char(6,93914).
+char(p,93915).
+char(o,93916).
+char(p,93917).
+char(o,93918).
+char(p,93919).
+char(9,93920).
+char(7,93921).
+char(5,93922).
+char(8,93923).
+char(p,93924).
+char(2,93925).
+char(7,93926).
+char(3,93927).
+char(5,93928).
+char(c,93929).
+char(p,93930).
+char(o,93931).
+char(p,93932).
+char(5,93933).
+char(8,93934).
+char(3,93935).
+char(5,93936).
+char(c,93937).
+char(m,93938).
+char(2,93939).
+char(6,93940).
+char(4,93941).
+char(0,93942).
+char(c,93943).
+char(p,93944).
+char(1,93945).
+char(7,93946).
+char(1,93947).
+char(8,93948).
+char(m,93949).
+char(o,93950).
+char(o,93951).
+char(3,93952).
+char(1,93953).
+char(8,93954).
+char(7,93955).
+char(c,93956).
+char(m,93957).
+char(o,93958).
+char(p,93959).
+char(o,93960).
+char(m,93961).
+char(o,93962).
+char(m,93963).
+char(2,93964).
+char(1,93965).
+char(5,93966).
+char(p,93967).
+char(o,93968).
+char(o,93969).
+char(p,93970).
+char(o,93971).
+char(m,93972).
+char(1,93973).
+char(1,93974).
+char(2,93975).
+char(3,93976).
+char(c,93977).
+char(p,93978).
+char(5,93979).
+char(0,93980).
+char(1,93981).
+char(5,93982).
+char(p,93983).
+char(6,93984).
+char(8,93985).
+char(4,93986).
+char(p,93987).
+char(o,93988).
+char(p,93989).
+char(3,93990).
+char(2,93991).
+char(4,93992).
+char(1,93993).
+char(c,93994).
+char(m,93995).
+char(o,93996).
+char(7,93997).
+char(2,93998).
+char(3,93999).
+char(3,94000).
+char(c,94001).
+char(c,94002).
+char(c,94003).
+char(m,94004).
+char(5,94005).
+char(6,94006).
+char(9,94007).
+char(c,94008).
+char(m,94009).
+char(2,94010).
+char(4,94011).
+char(7,94012).
+char(9,94013).
+char(c,94014).
+char(c,94015).
+char(c,94016).
+char(p,94017).
+char(8,94018).
+char(5,94019).
+char(0,94020).
+char(8,94021).
+char(m,94022).
+char(7,94023).
+char(7,94024).
+char(3,94025).
+char(5,94026).
+char(c,94027).
+char(p,94028).
+char(o,94029).
+char(o,94030).
+char(m,94031).
+char(4,94032).
+char(2,94033).
+char(6,94034).
+char(3,94035).
+char(c,94036).
+char(c,94037).
+char(c,94038).
+char(c,94039).
+char(c,94040).
+char(c,94041).
+char(c,94042).
+char(p,94043).
+char(2,94044).
+char(7,94045).
+char(3,94046).
+char(c,94047).
+char(c,94048).
+char(c,94049).
+char(c,94050).
+char(m,94051).
+char(o,94052).
+char(7,94053).
+char(1,94054).
+char(3,94055).
+char(8,94056).
+char(p,94057).
+char(3,94058).
+char(3,94059).
+char(7,94060).
+char(3,94061).
+char(p,94062).
+char(o,94063).
+char(o,94064).
+char(p,94065).
+char(o,94066).
+char(p,94067).
+char(1,94068).
+char(8,94069).
+char(2,94070).
+char(8,94071).
+char(c,94072).
+char(c,94073).
+char(p,94074).
+char(o,94075).
+char(6,94076).
+char(2,94077).
+char(6,94078).
+char(8,94079).
+char(c,94080).
+char(c,94081).
+char(c,94082).
+char(p,94083).
+char(6,94084).
+char(2,94085).
+char(6,94086).
+char(7,94087).
+char(c,94088).
+char(c,94089).
+char(m,94090).
+char(6,94091).
+char(8,94092).
+char(0,94093).
+char(0,94094).
+char(m,94095).
+char(6,94096).
+char(3,94097).
+char(0,94098).
+char(5,94099).
+char(p,94100).
+char(2,94101).
+char(4,94102).
+char(9,94103).
+char(1,94104).
+char(c,94105).
+char(p,94106).
+char(o,94107).
+char(p,94108).
+char(o,94109).
+char(p,94110).
+char(o,94111).
+char(o,94112).
+char(6,94113).
+char(6,94114).
+char(1,94115).
+char(8,94116).
+char(m,94117).
+char(7,94118).
+char(4,94119).
+char(1,94120).
+char(4,94121).
+char(p,94122).
+char(8,94123).
+char(0,94124).
+char(4,94125).
+char(7,94126).
+char(c,94127).
+char(c,94128).
+char(c,94129).
+char(m,94130).
+char(o,94131).
+char(m,94132).
+char(9,94133).
+char(7,94134).
+char(7,94135).
+char(c,94136).
+char(c,94137).
+char(p,94138).
+char(5,94139).
+char(3,94140).
+char(5,94141).
+char(3,94142).
+char(p,94143).
+char(8,94144).
+char(5,94145).
+char(4,94146).
+char(4,94147).
+char(p,94148).
+char(o,94149).
+char(o,94150).
+char(p,94151).
+char(4,94152).
+char(3,94153).
+char(2,94154).
+char(8,94155).
+char(p,94156).
+char(o,94157).
+char(m,94158).
+char(o,94159).
+char(m,94160).
+char(8,94161).
+char(0,94162).
+char(8,94163).
+char(0,94164).
+char(p,94165).
+char(o,94166).
+char(p,94167).
+char(8,94168).
+char(1,94169).
+char(6,94170).
+char(2,94171).
+char(p,94172).
+char(o,94173).
+char(m,94174).
+char(o,94175).
+char(m,94176).
+char(7,94177).
+char(8,94178).
+char(1,94179).
+char(2,94180).
+char(c,94181).
+char(c,94182).
+char(p,94183).
+char(7,94184).
+char(3,94185).
+char(5,94186).
+char(8,94187).
+char(c,94188).
+char(p,94189).
+char(4,94190).
+char(3,94191).
+char(2,94192).
+char(3,94193).
+char(c,94194).
+char(c,94195).
+char(m,94196).
+char(1,94197).
+char(5,94198).
+char(1,94199).
+char(0,94200).
+char(c,94201).
+char(p,94202).
+char(o,94203).
+char(m,94204).
+char(7,94205).
+char(0,94206).
+char(5,94207).
+char(1,94208).
+char(c,94209).
+char(c,94210).
+char(c,94211).
+char(p,94212).
+char(o,94213).
+char(m,94214).
+char(2,94215).
+char(1,94216).
+char(0,94217).
+char(4,94218).
+char(c,94219).
+char(c,94220).
+char(m,94221).
+char(o,94222).
+char(o,94223).
+char(p,94224).
+char(5,94225).
+char(7,94226).
+char(4,94227).
+char(1,94228).
+char(m,94229).
+char(2,94230).
+char(3,94231).
+char(4,94232).
+char(9,94233).
+char(m,94234).
+char(o,94235).
+char(m,94236).
+char(o,94237).
+char(o,94238).
+char(7,94239).
+char(5,94240).
+char(5,94241).
+char(3,94242).
+char(m,94243).
+char(o,94244).
+char(p,94245).
+char(3,94246).
+char(9,94247).
+char(9,94248).
+char(7,94249).
+char(c,94250).
+char(c,94251).
+char(p,94252).
+char(o,94253).
+char(p,94254).
+char(1,94255).
+char(8,94256).
+char(1,94257).
+char(0,94258).
+char(c,94259).
+char(c,94260).
+char(p,94261).
+char(o,94262).
+char(p,94263).
+char(6,94264).
+char(3,94265).
+char(7,94266).
+char(8,94267).
+char(p,94268).
+char(1,94269).
+char(8,94270).
+char(5,94271).
+char(9,94272).
+char(m,94273).
+char(7,94274).
+char(7,94275).
+char(0,94276).
+char(9,94277).
+char(p,94278).
+char(7,94279).
+char(5,94280).
+char(4,94281).
+char(7,94282).
+char(p,94283).
+char(3,94284).
+char(0,94285).
+char(4,94286).
+char(7,94287).
+char(c,94288).
+char(c,94289).
+char(c,94290).
+char(p,94291).
+char(9,94292).
+char(6,94293).
+char(6,94294).
+char(8,94295).
+char(m,94296).
+char(o,94297).
+char(m,94298).
+char(1,94299).
+char(0,94300).
+char(2,94301).
+char(4,94302).
+char(p,94303).
+char(o,94304).
+char(m,94305).
+char(9,94306).
+char(4,94307).
+char(5,94308).
+char(4,94309).
+char(m,94310).
+char(o,94311).
+char(o,94312).
+char(m,94313).
+char(o,94314).
+char(p,94315).
+char(6,94316).
+char(6,94317).
+char(4,94318).
+char(9,94319).
+char(c,94320).
+char(m,94321).
+char(1,94322).
+char(2,94323).
+char(0,94324).
+char(6,94325).
+char(p,94326).
+char(5,94327).
+char(3,94328).
+char(3,94329).
+char(c,94330).
+char(c,94331).
+char(p,94332).
+char(o,94333).
+char(p,94334).
+char(o,94335).
+char(m,94336).
+char(3,94337).
+char(3,94338).
+char(7,94339).
+char(c,94340).
+char(m,94341).
+char(1,94342).
+char(4,94343).
+char(7,94344).
+char(0,94345).
+char(p,94346).
+char(8,94347).
+char(7,94348).
+char(1,94349).
+char(8,94350).
+char(p,94351).
+char(o,94352).
+char(m,94353).
+char(9,94354).
+char(1,94355).
+char(6,94356).
+char(4,94357).
+char(m,94358).
+char(o,94359).
+char(m,94360).
+char(8,94361).
+char(9,94362).
+char(5,94363).
+char(9,94364).
+char(c,94365).
+char(p,94366).
+char(4,94367).
+char(8,94368).
+char(2,94369).
+char(5,94370).
+char(c,94371).
+char(m,94372).
+char(4,94373).
+char(4,94374).
+char(0,94375).
+char(6,94376).
+char(c,94377).
+char(c,94378).
+char(c,94379).
+char(c,94380).
+char(c,94381).
+char(c,94382).
+char(p,94383).
+char(4,94384).
+char(1,94385).
+char(9,94386).
+char(5,94387).
+char(c,94388).
+char(m,94389).
+char(2,94390).
+char(3,94391).
+char(3,94392).
+char(1,94393).
+char(p,94394).
+char(o,94395).
+char(p,94396).
+char(o,94397).
+char(p,94398).
+char(7,94399).
+char(2,94400).
+char(2,94401).
+char(4,94402).
+char(m,94403).
+char(o,94404).
+char(m,94405).
+char(3,94406).
+char(3,94407).
+char(3,94408).
+char(5,94409).
+char(c,94410).
+char(c,94411).
+char(m,94412).
+char(o,94413).
+char(m,94414).
+char(o,94415).
+char(m,94416).
+char(o,94417).
+char(p,94418).
+char(o,94419).
+char(o,94420).
+char(o,94421).
+char(m,94422).
+char(4,94423).
+char(1,94424).
+char(0,94425).
+char(8,94426).
+char(c,94427).
+char(m,94428).
+char(8,94429).
+char(8,94430).
+char(0,94431).
+char(2,94432).
+char(c,94433).
+char(m,94434).
+char(o,94435).
+char(p,94436).
+char(7,94437).
+char(9,94438).
+char(2,94439).
+char(1,94440).
+char(m,94441).
+char(o,94442).
+char(7,94443).
+char(6,94444).
+char(2,94445).
+char(3,94446).
+char(p,94447).
+char(o,94448).
+char(7,94449).
+char(4,94450).
+char(0,94451).
+char(7,94452).
+char(c,94453).
+char(c,94454).
+char(p,94455).
+char(o,94456).
+char(3,94457).
+char(7,94458).
+char(8,94459).
+char(9,94460).
+char(c,94461).
+char(c,94462).
+char(c,94463).
+char(c,94464).
+char(c,94465).
+char(m,94466).
+char(o,94467).
+char(m,94468).
+char(4,94469).
+char(9,94470).
+char(7,94471).
+char(4,94472).
+char(p,94473).
+char(o,94474).
+char(p,94475).
+char(7,94476).
+char(6,94477).
+char(1,94478).
+char(6,94479).
+char(c,94480).
+char(p,94481).
+char(o,94482).
+char(o,94483).
+char(o,94484).
+char(p,94485).
+char(o,94486).
+char(m,94487).
+char(2,94488).
+char(1,94489).
+char(8,94490).
+char(0,94491).
+char(p,94492).
+char(8,94493).
+char(1,94494).
+char(5,94495).
+char(8,94496).
+char(c,94497).
+char(c,94498).
+char(p,94499).
+char(o,94500).
+char(m,94501).
+char(o,94502).
+char(o,94503).
+char(p,94504).
+char(3,94505).
+char(8,94506).
+char(9,94507).
+char(1,94508).
+char(c,94509).
+char(p,94510).
+char(2,94511).
+char(3,94512).
+char(0,94513).
+char(3,94514).
+char(c,94515).
+char(c,94516).
+char(m,94517).
+char(o,94518).
+char(p,94519).
+char(o,94520).
+char(p,94521).
+char(6,94522).
+char(9,94523).
+char(3,94524).
+char(8,94525).
+char(p,94526).
+char(7,94527).
+char(2,94528).
+char(3,94529).
+char(6,94530).
+char(c,94531).
+char(c,94532).
+char(p,94533).
+char(o,94534).
+char(p,94535).
+char(o,94536).
+char(m,94537).
+char(o,94538).
+char(p,94539).
+char(o,94540).
+char(5,94541).
+char(9,94542).
+char(6,94543).
+char(8,94544).
+char(c,94545).
+char(c,94546).
+char(m,94547).
+char(o,94548).
+char(p,94549).
+char(3,94550).
+char(8,94551).
+char(4,94552).
+char(1,94553).
+char(c,94554).
+char(p,94555).
+char(4,94556).
+char(8,94557).
+char(1,94558).
+char(1,94559).
+char(c,94560).
+char(m,94561).
+char(5,94562).
+char(1,94563).
+char(5,94564).
+char(9,94565).
+char(c,94566).
+char(c,94567).
+char(m,94568).
+char(5,94569).
+char(7,94570).
+char(6,94571).
+char(9,94572).
+char(p,94573).
+char(4,94574).
+char(8,94575).
+char(2,94576).
+char(7,94577).
+char(c,94578).
+char(c,94579).
+char(c,94580).
+char(c,94581).
+char(c,94582).
+char(c,94583).
+char(m,94584).
+char(6,94585).
+char(9,94586).
+char(8,94587).
+char(1,94588).
+char(c,94589).
+char(m,94590).
+char(1,94591).
+char(8,94592).
+char(8,94593).
+char(6,94594).
+char(c,94595).
+char(p,94596).
+char(4,94597).
+char(6,94598).
+char(9,94599).
+char(8,94600).
+char(m,94601).
+char(1,94602).
+char(6,94603).
+char(8,94604).
+char(1,94605).
+char(m,94606).
+char(o,94607).
+char(7,94608).
+char(8,94609).
+char(1,94610).
+char(7,94611).
+char(p,94612).
+char(1,94613).
+char(9,94614).
+char(4,94615).
+char(0,94616).
+char(c,94617).
+char(c,94618).
+char(m,94619).
+char(o,94620).
+char(p,94621).
+char(o,94622).
+char(m,94623).
+char(o,94624).
+char(1,94625).
+char(3,94626).
+char(4,94627).
+char(0,94628).
+char(p,94629).
+char(3,94630).
+char(0,94631).
+char(6,94632).
+char(5,94633).
+char(c,94634).
+char(p,94635).
+char(8,94636).
+char(4,94637).
+char(2,94638).
+char(7,94639).
+char(p,94640).
+char(o,94641).
+char(4,94642).
+char(0,94643).
+char(6,94644).
+char(1,94645).
+char(c,94646).
+char(c,94647).
+char(c,94648).
+char(m,94649).
+char(o,94650).
+char(o,94651).
+char(p,94652).
+char(3,94653).
+char(1,94654).
+char(6,94655).
+char(6,94656).
+char(c,94657).
+char(c,94658).
+char(c,94659).
+char(c,94660).
+char(p,94661).
+char(o,94662).
+char(m,94663).
+char(o,94664).
+char(p,94665).
+char(o,94666).
+char(3,94667).
+char(9,94668).
+char(7,94669).
+char(0,94670).
+char(m,94671).
+char(9,94672).
+char(8,94673).
+char(7,94674).
+char(5,94675).
+char(m,94676).
+char(7,94677).
+char(5,94678).
+char(9,94679).
+char(0,94680).
+char(c,94681).
+char(c,94682).
+char(p,94683).
+char(3,94684).
+char(9,94685).
+char(2,94686).
+char(7,94687).
+char(m,94688).
+char(8,94689).
+char(2,94690).
+char(6,94691).
+char(7,94692).
+char(c,94693).
+char(p,94694).
+char(3,94695).
+char(0,94696).
+char(6,94697).
+char(8,94698).
+char(m,94699).
+char(7,94700).
+char(0,94701).
+char(1,94702).
+char(3,94703).
+char(c,94704).
+char(p,94705).
+char(o,94706).
+char(m,94707).
+char(o,94708).
+char(4,94709).
+char(4,94710).
+char(4,94711).
+char(8,94712).
+char(p,94713).
+char(o,94714).
+char(o,94715).
+char(4,94716).
+char(8,94717).
+char(7,94718).
+char(c,94719).
+char(c,94720).
+char(c,94721).
+char(c,94722).
+char(p,94723).
+char(o,94724).
+char(m,94725).
+char(3,94726).
+char(7,94727).
+char(5,94728).
+char(7,94729).
+char(m,94730).
+char(o,94731).
+char(1,94732).
+char(2,94733).
+char(1,94734).
+char(0,94735).
+char(m,94736).
+char(o,94737).
+char(1,94738).
+char(3,94739).
+char(0,94740).
+char(9,94741).
+char(c,94742).
+char(m,94743).
+char(o,94744).
+char(m,94745).
+char(1,94746).
+char(8,94747).
+char(7,94748).
+char(c,94749).
+char(c,94750).
+char(m,94751).
+char(9,94752).
+char(5,94753).
+char(5,94754).
+char(1,94755).
+char(p,94756).
+char(o,94757).
+char(o,94758).
+char(p,94759).
+char(o,94760).
+char(p,94761).
+char(o,94762).
+char(m,94763).
+char(5,94764).
+char(2,94765).
+char(7,94766).
+char(m,94767).
+char(9,94768).
+char(5,94769).
+char(1,94770).
+char(1,94771).
+char(m,94772).
+char(5,94773).
+char(3,94774).
+char(9,94775).
+char(2,94776).
+char(c,94777).
+char(c,94778).
+char(m,94779).
+char(o,94780).
+char(m,94781).
+char(9,94782).
+char(9,94783).
+char(8,94784).
+char(6,94785).
+char(p,94786).
+char(o,94787).
+char(m,94788).
+char(6,94789).
+char(3,94790).
+char(1,94791).
+char(5,94792).
+char(c,94793).
+char(c,94794).
+char(m,94795).
+char(7,94796).
+char(7,94797).
+char(7,94798).
+char(0,94799).
+char(m,94800).
+char(o,94801).
+char(m,94802).
+char(2,94803).
+char(6,94804).
+char(8,94805).
+char(c,94806).
+char(c,94807).
+char(p,94808).
+char(o,94809).
+char(2,94810).
+char(7,94811).
+char(6,94812).
+char(2,94813).
+char(c,94814).
+char(c,94815).
+char(m,94816).
+char(1,94817).
+char(3,94818).
+char(4,94819).
+char(5,94820).
+char(m,94821).
+char(5,94822).
+char(5,94823).
+char(2,94824).
+char(0,94825).
+char(c,94826).
+char(c,94827).
+char(c,94828).
+char(c,94829).
+char(c,94830).
+char(c,94831).
+char(c,94832).
+char(c,94833).
+char(p,94834).
+char(o,94835).
+char(p,94836).
+char(o,94837).
+char(m,94838).
+char(o,94839).
+char(m,94840).
+char(1,94841).
+char(5,94842).
+char(8,94843).
+char(m,94844).
+char(3,94845).
+char(8,94846).
+char(0,94847).
+char(5,94848).
+char(c,94849).
+char(p,94850).
+char(o,94851).
+char(o,94852).
+char(p,94853).
+char(o,94854).
+char(p,94855).
+char(9,94856).
+char(3,94857).
+char(9,94858).
+char(9,94859).
+char(m,94860).
+char(o,94861).
+char(p,94862).
+char(o,94863).
+char(p,94864).
+char(3,94865).
+char(5,94866).
+char(6,94867).
+char(4,94868).
+char(c,94869).
+char(m,94870).
+char(7,94871).
+char(7,94872).
+char(9,94873).
+char(3,94874).
+char(c,94875).
+char(m,94876).
+char(o,94877).
+char(p,94878).
+char(5,94879).
+char(1,94880).
+char(1,94881).
+char(2,94882).
+char(c,94883).
+char(p,94884).
+char(o,94885).
+char(1,94886).
+char(9,94887).
+char(7,94888).
+char(3,94889).
+char(c,94890).
+char(c,94891).
+char(c,94892).
+char(p,94893).
+char(o,94894).
+char(m,94895).
+char(6,94896).
+char(6,94897).
+char(3,94898).
+char(1,94899).
+char(c,94900).
+char(c,94901).
+char(c,94902).
+char(p,94903).
+char(2,94904).
+char(1,94905).
+char(8,94906).
+char(1,94907).
+char(m,94908).
+char(o,94909).
+char(p,94910).
+char(1,94911).
+char(7,94912).
+char(9,94913).
+char(3,94914).
+char(c,94915).
+char(c,94916).
+char(p,94917).
+char(8,94918).
+char(2,94919).
+char(9,94920).
+char(9,94921).
+char(c,94922).
+char(c,94923).
+char(c,94924).
+char(m,94925).
+char(o,94926).
+char(5,94927).
+char(2,94928).
+char(0,94929).
+char(4,94930).
+char(c,94931).
+char(p,94932).
+char(o,94933).
+char(m,94934).
+char(6,94935).
+char(9,94936).
+char(8,94937).
+char(8,94938).
+char(p,94939).
+char(o,94940).
+char(p,94941).
+char(o,94942).
+char(m,94943).
+char(o,94944).
+char(9,94945).
+char(1,94946).
+char(9,94947).
+char(8,94948).
+char(m,94949).
+char(o,94950).
+char(m,94951).
+char(o,94952).
+char(p,94953).
+char(3,94954).
+char(6,94955).
+char(3,94956).
+char(8,94957).
+char(p,94958).
+char(2,94959).
+char(1,94960).
+char(2,94961).
+char(4,94962).
+char(c,94963).
+char(c,94964).
+char(c,94965).
+char(c,94966).
+char(c,94967).
+char(c,94968).
+char(c,94969).
+char(p,94970).
+char(6,94971).
+char(0,94972).
+char(7,94973).
+char(5,94974).
+char(p,94975).
+char(6,94976).
+char(1,94977).
+char(2,94978).
+char(7,94979).
+char(c,94980).
+char(c,94981).
+char(c,94982).
+char(c,94983).
+char(p,94984).
+char(o,94985).
+char(p,94986).
+char(o,94987).
+char(o,94988).
+char(7,94989).
+char(7,94990).
+char(9,94991).
+char(c,94992).
+char(m,94993).
+char(2,94994).
+char(5,94995).
+char(9,94996).
+char(1,94997).
+char(c,94998).
+char(c,94999).
+char(c,95000).
+char(c,95001).
+char(c,95002).
+char(m,95003).
+char(4,95004).
+char(1,95005).
+char(0,95006).
+char(6,95007).
+char(c,95008).
+char(p,95009).
+char(o,95010).
+char(m,95011).
+char(o,95012).
+char(o,95013).
+char(m,95014).
+char(o,95015).
+char(2,95016).
+char(7,95017).
+char(7,95018).
+char(6,95019).
+char(c,95020).
+char(c,95021).
+char(c,95022).
+char(c,95023).
+char(c,95024).
+char(m,95025).
+char(o,95026).
+char(p,95027).
+char(3,95028).
+char(6,95029).
+char(3,95030).
+char(6,95031).
+char(c,95032).
+char(p,95033).
+char(o,95034).
+char(m,95035).
+char(9,95036).
+char(0,95037).
+char(5,95038).
+char(9,95039).
+char(c,95040).
+char(c,95041).
+char(c,95042).
+char(c,95043).
+char(p,95044).
+char(1,95045).
+char(4,95046).
+char(0,95047).
+char(1,95048).
+char(p,95049).
+char(o,95050).
+char(p,95051).
+char(9,95052).
+char(5,95053).
+char(8,95054).
+char(5,95055).
+char(c,95056).
+char(p,95057).
+char(o,95058).
+char(m,95059).
+char(o,95060).
+char(m,95061).
+char(2,95062).
+char(5,95063).
+char(0,95064).
+char(4,95065).
+char(p,95066).
+char(o,95067).
+char(p,95068).
+char(o,95069).
+char(p,95070).
+char(2,95071).
+char(2,95072).
+char(3,95073).
+char(c,95074).
+char(m,95075).
+char(2,95076).
+char(3,95077).
+char(6,95078).
+char(9,95079).
+char(c,95080).
+char(c,95081).
+char(p,95082).
+char(3,95083).
+char(3,95084).
+char(3,95085).
+char(8,95086).
+char(c,95087).
+char(c,95088).
+char(p,95089).
+char(4,95090).
+char(0,95091).
+char(7,95092).
+char(7,95093).
+char(p,95094).
+char(o,95095).
+char(1,95096).
+char(5,95097).
+char(1,95098).
+char(6,95099).
+char(p,95100).
+char(o,95101).
+char(5,95102).
+char(0,95103).
+char(2,95104).
+char(7,95105).
+char(p,95106).
+char(o,95107).
+char(p,95108).
+char(o,95109).
+char(p,95110).
+char(5,95111).
+char(1,95112).
+char(4,95113).
+char(7,95114).
+char(c,95115).
+char(c,95116).
+char(c,95117).
+char(m,95118).
+char(2,95119).
+char(9,95120).
+char(1,95121).
+char(6,95122).
+char(c,95123).
+char(c,95124).
+char(m,95125).
+char(o,95126).
+char(m,95127).
+char(2,95128).
+char(9,95129).
+char(9,95130).
+char(4,95131).
+char(p,95132).
+char(6,95133).
+char(0,95134).
+char(0,95135).
+char(5,95136).
+char(c,95137).
+char(g,95138).
+char(m,95139).
+char(1,95140).
+char(3,95141).
+char(0,95142).
+char(8,95143).
+char(8,95144).
diff --git a/examples/gringo/gbie/instances/sat_03.lp b/examples/gringo/gbie/instances/sat_03.lp
new file mode 100644
index 0000000..3c4b21a
--- /dev/null
+++ b/examples/gringo/gbie/instances/sat_03.lp
@@ -0,0 +1,81956 @@
+char(o,1).
+char(p,2).
+char(o,3).
+char(m,4).
+char(o,5).
+char(p,6).
+char(o,7).
+char(m,8).
+char(4,9).
+char(7,10).
+char(1,11).
+char(m,12).
+char(8,13).
+char(0,14).
+char(4,15).
+char(3,16).
+char(c,17).
+char(m,18).
+char(o,19).
+char(m,20).
+char(o,21).
+char(o,22).
+char(m,23).
+char(5,24).
+char(2,25).
+char(4,26).
+char(4,27).
+char(c,28).
+char(c,29).
+char(m,30).
+char(o,31).
+char(7,32).
+char(2,33).
+char(1,34).
+char(8,35).
+char(c,36).
+char(p,37).
+char(o,38).
+char(o,39).
+char(p,40).
+char(o,41).
+char(m,42).
+char(o,43).
+char(p,44).
+char(2,45).
+char(3,46).
+char(8,47).
+char(2,48).
+char(m,49).
+char(o,50).
+char(m,51).
+char(o,52).
+char(p,53).
+char(6,54).
+char(7,55).
+char(4,56).
+char(6,57).
+char(c,58).
+char(c,59).
+char(c,60).
+char(c,61).
+char(m,62).
+char(o,63).
+char(o,64).
+char(p,65).
+char(o,66).
+char(p,67).
+char(9,68).
+char(1,69).
+char(2,70).
+char(6,71).
+char(c,72).
+char(c,73).
+char(c,74).
+char(c,75).
+char(c,76).
+char(m,77).
+char(o,78).
+char(m,79).
+char(o,80).
+char(o,81).
+char(p,82).
+char(1,83).
+char(8,84).
+char(2,85).
+char(p,86).
+char(2,87).
+char(7,88).
+char(9,89).
+char(0,90).
+char(p,91).
+char(o,92).
+char(o,93).
+char(m,94).
+char(o,95).
+char(m,96).
+char(3,97).
+char(6,98).
+char(3,99).
+char(c,100).
+char(m,101).
+char(4,102).
+char(3,103).
+char(5,104).
+char(3,105).
+char(p,106).
+char(o,107).
+char(m,108).
+char(o,109).
+char(p,110).
+char(3,111).
+char(3,112).
+char(9,113).
+char(7,114).
+char(p,115).
+char(o,116).
+char(m,117).
+char(5,118).
+char(6,119).
+char(6,120).
+char(7,121).
+char(m,122).
+char(o,123).
+char(m,124).
+char(o,125).
+char(m,126).
+char(o,127).
+char(m,128).
+char(4,129).
+char(7,130).
+char(9,131).
+char(p,132).
+char(o,133).
+char(o,134).
+char(4,135).
+char(4,136).
+char(2,137).
+char(7,138).
+char(c,139).
+char(m,140).
+char(2,141).
+char(1,142).
+char(4,143).
+char(8,144).
+char(c,145).
+char(p,146).
+char(o,147).
+char(1,148).
+char(5,149).
+char(5,150).
+char(2,151).
+char(p,152).
+char(o,153).
+char(p,154).
+char(5,155).
+char(1,156).
+char(6,157).
+char(3,158).
+char(c,159).
+char(m,160).
+char(o,161).
+char(6,162).
+char(9,163).
+char(9,164).
+char(7,165).
+char(p,166).
+char(o,167).
+char(o,168).
+char(p,169).
+char(o,170).
+char(p,171).
+char(9,172).
+char(4,173).
+char(5,174).
+char(4,175).
+char(p,176).
+char(5,177).
+char(5,178).
+char(4,179).
+char(8,180).
+char(m,181).
+char(8,182).
+char(6,183).
+char(7,184).
+char(0,185).
+char(m,186).
+char(o,187).
+char(m,188).
+char(9,189).
+char(3,190).
+char(6,191).
+char(3,192).
+char(p,193).
+char(o,194).
+char(m,195).
+char(o,196).
+char(8,197).
+char(2,198).
+char(4,199).
+char(9,200).
+char(c,201).
+char(c,202).
+char(m,203).
+char(7,204).
+char(7,205).
+char(4,206).
+char(8,207).
+char(m,208).
+char(1,209).
+char(0,210).
+char(0,211).
+char(5,212).
+char(p,213).
+char(o,214).
+char(p,215).
+char(o,216).
+char(o,217).
+char(o,218).
+char(9,219).
+char(4,220).
+char(7,221).
+char(9,222).
+char(c,223).
+char(m,224).
+char(o,225).
+char(5,226).
+char(6,227).
+char(5,228).
+char(9,229).
+char(m,230).
+char(o,231).
+char(m,232).
+char(o,233).
+char(m,234).
+char(o,235).
+char(o,236).
+char(1,237).
+char(6,238).
+char(8,239).
+char(6,240).
+char(p,241).
+char(3,242).
+char(6,243).
+char(1,244).
+char(5,245).
+char(m,246).
+char(9,247).
+char(3,248).
+char(6,249).
+char(9,250).
+char(p,251).
+char(o,252).
+char(5,253).
+char(7,254).
+char(8,255).
+char(6,256).
+char(p,257).
+char(5,258).
+char(3,259).
+char(1,260).
+char(6,261).
+char(c,262).
+char(p,263).
+char(o,264).
+char(p,265).
+char(o,266).
+char(o,267).
+char(p,268).
+char(o,269).
+char(m,270).
+char(8,271).
+char(6,272).
+char(6,273).
+char(3,274).
+char(m,275).
+char(3,276).
+char(0,277).
+char(6,278).
+char(7,279).
+char(m,280).
+char(o,281).
+char(o,282).
+char(p,283).
+char(o,284).
+char(m,285).
+char(3,286).
+char(6,287).
+char(m,288).
+char(5,289).
+char(4,290).
+char(7,291).
+char(8,292).
+char(c,293).
+char(c,294).
+char(c,295).
+char(c,296).
+char(p,297).
+char(o,298).
+char(o,299).
+char(m,300).
+char(o,301).
+char(m,302).
+char(o,303).
+char(p,304).
+char(2,305).
+char(0,306).
+char(2,307).
+char(4,308).
+char(m,309).
+char(o,310).
+char(o,311).
+char(m,312).
+char(o,313).
+char(o,314).
+char(o,315).
+char(m,316).
+char(2,317).
+char(4,318).
+char(8,319).
+char(8,320).
+char(c,321).
+char(p,322).
+char(o,323).
+char(7,324).
+char(6,325).
+char(7,326).
+char(3,327).
+char(c,328).
+char(p,329).
+char(o,330).
+char(m,331).
+char(o,332).
+char(p,333).
+char(o,334).
+char(p,335).
+char(8,336).
+char(2,337).
+char(6,338).
+char(4,339).
+char(m,340).
+char(7,341).
+char(3,342).
+char(9,343).
+char(0,344).
+char(m,345).
+char(3,346).
+char(8,347).
+char(0,348).
+char(p,349).
+char(o,350).
+char(p,351).
+char(8,352).
+char(6,353).
+char(9,354).
+char(4,355).
+char(m,356).
+char(o,357).
+char(p,358).
+char(5,359).
+char(5,360).
+char(9,361).
+char(1,362).
+char(p,363).
+char(o,364).
+char(o,365).
+char(m,366).
+char(o,367).
+char(o,368).
+char(p,369).
+char(1,370).
+char(8,371).
+char(6,372).
+char(2,373).
+char(p,374).
+char(o,375).
+char(o,376).
+char(9,377).
+char(9,378).
+char(6,379).
+char(0,380).
+char(c,381).
+char(c,382).
+char(m,383).
+char(o,384).
+char(p,385).
+char(o,386).
+char(m,387).
+char(3,388).
+char(9,389).
+char(7,390).
+char(c,391).
+char(m,392).
+char(7,393).
+char(5,394).
+char(0,395).
+char(c,396).
+char(p,397).
+char(5,398).
+char(2,399).
+char(1,400).
+char(5,401).
+char(c,402).
+char(p,403).
+char(1,404).
+char(0,405).
+char(9,406).
+char(3,407).
+char(m,408).
+char(o,409).
+char(m,410).
+char(o,411).
+char(o,412).
+char(p,413).
+char(o,414).
+char(p,415).
+char(3,416).
+char(7,417).
+char(8,418).
+char(0,419).
+char(c,420).
+char(m,421).
+char(o,422).
+char(6,423).
+char(5,424).
+char(0,425).
+char(0,426).
+char(m,427).
+char(o,428).
+char(m,429).
+char(6,430).
+char(8,431).
+char(2,432).
+char(7,433).
+char(c,434).
+char(c,435).
+char(c,436).
+char(c,437).
+char(m,438).
+char(o,439).
+char(m,440).
+char(9,441).
+char(8,442).
+char(5,443).
+char(5,444).
+char(c,445).
+char(m,446).
+char(4,447).
+char(8,448).
+char(4,449).
+char(3,450).
+char(m,451).
+char(o,452).
+char(p,453).
+char(8,454).
+char(8,455).
+char(0,456).
+char(3,457).
+char(c,458).
+char(p,459).
+char(6,460).
+char(7,461).
+char(7,462).
+char(9,463).
+char(c,464).
+char(c,465).
+char(p,466).
+char(o,467).
+char(p,468).
+char(5,469).
+char(2,470).
+char(8,471).
+char(9,472).
+char(c,473).
+char(c,474).
+char(c,475).
+char(c,476).
+char(p,477).
+char(o,478).
+char(p,479).
+char(1,480).
+char(7,481).
+char(4,482).
+char(m,483).
+char(2,484).
+char(2,485).
+char(4,486).
+char(9,487).
+char(c,488).
+char(m,489).
+char(7,490).
+char(1,491).
+char(5,492).
+char(9,493).
+char(m,494).
+char(4,495).
+char(7,496).
+char(3,497).
+char(5,498).
+char(c,499).
+char(p,500).
+char(7,501).
+char(9,502).
+char(0,503).
+char(6,504).
+char(m,505).
+char(o,506).
+char(5,507).
+char(3,508).
+char(5,509).
+char(3,510).
+char(c,511).
+char(c,512).
+char(c,513).
+char(c,514).
+char(c,515).
+char(p,516).
+char(9,517).
+char(3,518).
+char(1,519).
+char(9,520).
+char(m,521).
+char(4,522).
+char(0,523).
+char(3,524).
+char(2,525).
+char(p,526).
+char(5,527).
+char(1,528).
+char(9,529).
+char(7,530).
+char(m,531).
+char(o,532).
+char(m,533).
+char(6,534).
+char(7,535).
+char(7,536).
+char(7,537).
+char(c,538).
+char(m,539).
+char(1,540).
+char(6,541).
+char(3,542).
+char(3,543).
+char(c,544).
+char(p,545).
+char(8,546).
+char(5,547).
+char(5,548).
+char(c,549).
+char(c,550).
+char(c,551).
+char(m,552).
+char(9,553).
+char(1,554).
+char(6,555).
+char(6,556).
+char(c,557).
+char(m,558).
+char(o,559).
+char(p,560).
+char(3,561).
+char(7,562).
+char(0,563).
+char(4,564).
+char(m,565).
+char(o,566).
+char(m,567).
+char(2,568).
+char(9,569).
+char(8,570).
+char(3,571).
+char(m,572).
+char(6,573).
+char(4,574).
+char(1,575).
+char(9,576).
+char(c,577).
+char(p,578).
+char(o,579).
+char(m,580).
+char(o,581).
+char(m,582).
+char(7,583).
+char(1,584).
+char(2,585).
+char(2,586).
+char(p,587).
+char(o,588).
+char(p,589).
+char(o,590).
+char(p,591).
+char(2,592).
+char(0,593).
+char(1,594).
+char(3,595).
+char(c,596).
+char(c,597).
+char(m,598).
+char(9,599).
+char(5,600).
+char(6,601).
+char(2,602).
+char(c,603).
+char(m,604).
+char(o,605).
+char(m,606).
+char(o,607).
+char(p,608).
+char(o,609).
+char(8,610).
+char(0,611).
+char(3,612).
+char(3,613).
+char(p,614).
+char(o,615).
+char(m,616).
+char(o,617).
+char(4,618).
+char(1,619).
+char(8,620).
+char(2,621).
+char(m,622).
+char(o,623).
+char(m,624).
+char(o,625).
+char(m,626).
+char(o,627).
+char(p,628).
+char(o,629).
+char(o,630).
+char(5,631).
+char(9,632).
+char(2,633).
+char(3,634).
+char(m,635).
+char(5,636).
+char(7,637).
+char(1,638).
+char(5,639).
+char(p,640).
+char(4,641).
+char(5,642).
+char(0,643).
+char(p,644).
+char(2,645).
+char(9,646).
+char(9,647).
+char(3,648).
+char(c,649).
+char(m,650).
+char(8,651).
+char(2,652).
+char(7,653).
+char(7,654).
+char(c,655).
+char(p,656).
+char(9,657).
+char(7,658).
+char(7,659).
+char(0,660).
+char(c,661).
+char(p,662).
+char(2,663).
+char(4,664).
+char(0,665).
+char(p,666).
+char(o,667).
+char(p,668).
+char(7,669).
+char(1,670).
+char(0,671).
+char(9,672).
+char(c,673).
+char(p,674).
+char(9,675).
+char(8,676).
+char(4,677).
+char(9,678).
+char(p,679).
+char(o,680).
+char(5,681).
+char(3,682).
+char(3,683).
+char(1,684).
+char(m,685).
+char(o,686).
+char(9,687).
+char(6,688).
+char(1,689).
+char(0,690).
+char(p,691).
+char(o,692).
+char(m,693).
+char(o,694).
+char(o,695).
+char(7,696).
+char(7,697).
+char(c,698).
+char(c,699).
+char(m,700).
+char(o,701).
+char(m,702).
+char(3,703).
+char(9,704).
+char(2,705).
+char(0,706).
+char(c,707).
+char(p,708).
+char(1,709).
+char(6,710).
+char(7,711).
+char(6,712).
+char(c,713).
+char(m,714).
+char(7,715).
+char(2,716).
+char(9,717).
+char(0,718).
+char(c,719).
+char(c,720).
+char(c,721).
+char(p,722).
+char(o,723).
+char(m,724).
+char(5,725).
+char(8,726).
+char(3,727).
+char(8,728).
+char(c,729).
+char(c,730).
+char(c,731).
+char(p,732).
+char(5,733).
+char(7,734).
+char(3,735).
+char(1,736).
+char(m,737).
+char(6,738).
+char(8,739).
+char(6,740).
+char(1,741).
+char(m,742).
+char(o,743).
+char(p,744).
+char(6,745).
+char(4,746).
+char(6,747).
+char(0,748).
+char(c,749).
+char(c,750).
+char(m,751).
+char(o,752).
+char(p,753).
+char(o,754).
+char(m,755).
+char(2,756).
+char(9,757).
+char(5,758).
+char(m,759).
+char(o,760).
+char(m,761).
+char(o,762).
+char(m,763).
+char(o,764).
+char(o,765).
+char(o,766).
+char(m,767).
+char(o,768).
+char(o,769).
+char(o,770).
+char(p,771).
+char(1,772).
+char(4,773).
+char(1,774).
+char(9,775).
+char(c,776).
+char(m,777).
+char(8,778).
+char(4,779).
+char(0,780).
+char(5,781).
+char(c,782).
+char(c,783).
+char(p,784).
+char(o,785).
+char(m,786).
+char(6,787).
+char(9,788).
+char(6,789).
+char(1,790).
+char(m,791).
+char(o,792).
+char(m,793).
+char(9,794).
+char(0,795).
+char(3,796).
+char(p,797).
+char(o,798).
+char(m,799).
+char(1,800).
+char(0,801).
+char(1,802).
+char(3,803).
+char(m,804).
+char(4,805).
+char(6,806).
+char(9,807).
+char(m,808).
+char(o,809).
+char(m,810).
+char(o,811).
+char(8,812).
+char(6,813).
+char(1,814).
+char(3,815).
+char(c,816).
+char(c,817).
+char(c,818).
+char(m,819).
+char(9,820).
+char(9,821).
+char(2,822).
+char(9,823).
+char(m,824).
+char(4,825).
+char(8,826).
+char(2,827).
+char(6,828).
+char(p,829).
+char(1,830).
+char(1,831).
+char(8,832).
+char(p,833).
+char(8,834).
+char(1,835).
+char(7,836).
+char(5,837).
+char(c,838).
+char(m,839).
+char(o,840).
+char(p,841).
+char(o,842).
+char(m,843).
+char(6,844).
+char(6,845).
+char(0,846).
+char(7,847).
+char(c,848).
+char(c,849).
+char(m,850).
+char(7,851).
+char(2,852).
+char(1,853).
+char(8,854).
+char(p,855).
+char(o,856).
+char(p,857).
+char(9,858).
+char(2,859).
+char(7,860).
+char(0,861).
+char(c,862).
+char(c,863).
+char(c,864).
+char(c,865).
+char(p,866).
+char(2,867).
+char(4,868).
+char(4,869).
+char(7,870).
+char(c,871).
+char(m,872).
+char(o,873).
+char(p,874).
+char(o,875).
+char(p,876).
+char(o,877).
+char(m,878).
+char(o,879).
+char(m,880).
+char(o,881).
+char(p,882).
+char(7,883).
+char(4,884).
+char(3,885).
+char(9,886).
+char(m,887).
+char(o,888).
+char(m,889).
+char(7,890).
+char(8,891).
+char(6,892).
+char(0,893).
+char(c,894).
+char(m,895).
+char(o,896).
+char(o,897).
+char(p,898).
+char(4,899).
+char(1,900).
+char(5,901).
+char(7,902).
+char(c,903).
+char(c,904).
+char(c,905).
+char(p,906).
+char(o,907).
+char(m,908).
+char(7,909).
+char(2,910).
+char(6,911).
+char(7,912).
+char(p,913).
+char(o,914).
+char(o,915).
+char(m,916).
+char(4,917).
+char(0,918).
+char(9,919).
+char(7,920).
+char(c,921).
+char(c,922).
+char(c,923).
+char(p,924).
+char(1,925).
+char(4,926).
+char(2,927).
+char(9,928).
+char(c,929).
+char(c,930).
+char(p,931).
+char(7,932).
+char(6,933).
+char(2,934).
+char(9,935).
+char(p,936).
+char(4,937).
+char(6,938).
+char(4,939).
+char(6,940).
+char(m,941).
+char(o,942).
+char(o,943).
+char(m,944).
+char(8,945).
+char(3,946).
+char(0,947).
+char(6,948).
+char(c,949).
+char(p,950).
+char(8,951).
+char(8,952).
+char(5,953).
+char(4,954).
+char(c,955).
+char(c,956).
+char(p,957).
+char(6,958).
+char(2,959).
+char(8,960).
+char(0,961).
+char(c,962).
+char(c,963).
+char(c,964).
+char(c,965).
+char(m,966).
+char(1,967).
+char(0,968).
+char(1,969).
+char(0,970).
+char(m,971).
+char(3,972).
+char(5,973).
+char(7,974).
+char(8,975).
+char(m,976).
+char(3,977).
+char(4,978).
+char(2,979).
+char(0,980).
+char(m,981).
+char(o,982).
+char(m,983).
+char(o,984).
+char(m,985).
+char(o,986).
+char(p,987).
+char(3,988).
+char(5,989).
+char(2,990).
+char(9,991).
+char(m,992).
+char(2,993).
+char(5,994).
+char(4,995).
+char(4,996).
+char(c,997).
+char(m,998).
+char(o,999).
+char(m,1000).
+char(9,1001).
+char(2,1002).
+char(4,1003).
+char(6,1004).
+char(c,1005).
+char(m,1006).
+char(o,1007).
+char(m,1008).
+char(o,1009).
+char(o,1010).
+char(p,1011).
+char(9,1012).
+char(5,1013).
+char(3,1014).
+char(5,1015).
+char(c,1016).
+char(p,1017).
+char(o,1018).
+char(p,1019).
+char(o,1020).
+char(9,1021).
+char(1,1022).
+char(1,1023).
+char(6,1024).
+char(p,1025).
+char(4,1026).
+char(4,1027).
+char(9,1028).
+char(5,1029).
+char(c,1030).
+char(m,1031).
+char(o,1032).
+char(m,1033).
+char(o,1034).
+char(p,1035).
+char(o,1036).
+char(5,1037).
+char(0,1038).
+char(7,1039).
+char(0,1040).
+char(p,1041).
+char(o,1042).
+char(m,1043).
+char(o,1044).
+char(o,1045).
+char(m,1046).
+char(o,1047).
+char(o,1048).
+char(o,1049).
+char(o,1050).
+char(m,1051).
+char(o,1052).
+char(p,1053).
+char(o,1054).
+char(8,1055).
+char(9,1056).
+char(7,1057).
+char(8,1058).
+char(c,1059).
+char(m,1060).
+char(5,1061).
+char(9,1062).
+char(7,1063).
+char(3,1064).
+char(p,1065).
+char(5,1066).
+char(2,1067).
+char(8,1068).
+char(8,1069).
+char(c,1070).
+char(m,1071).
+char(6,1072).
+char(2,1073).
+char(6,1074).
+char(0,1075).
+char(c,1076).
+char(p,1077).
+char(o,1078).
+char(m,1079).
+char(4,1080).
+char(7,1081).
+char(0,1082).
+char(9,1083).
+char(c,1084).
+char(c,1085).
+char(c,1086).
+char(c,1087).
+char(c,1088).
+char(c,1089).
+char(c,1090).
+char(m,1091).
+char(9,1092).
+char(8,1093).
+char(5,1094).
+char(2,1095).
+char(m,1096).
+char(9,1097).
+char(4,1098).
+char(5,1099).
+char(3,1100).
+char(c,1101).
+char(m,1102).
+char(o,1103).
+char(m,1104).
+char(o,1105).
+char(o,1106).
+char(p,1107).
+char(3,1108).
+char(9,1109).
+char(7,1110).
+char(8,1111).
+char(p,1112).
+char(6,1113).
+char(5,1114).
+char(6,1115).
+char(7,1116).
+char(c,1117).
+char(m,1118).
+char(3,1119).
+char(2,1120).
+char(7,1121).
+char(5,1122).
+char(c,1123).
+char(p,1124).
+char(2,1125).
+char(1,1126).
+char(7,1127).
+char(4,1128).
+char(c,1129).
+char(c,1130).
+char(p,1131).
+char(o,1132).
+char(p,1133).
+char(7,1134).
+char(2,1135).
+char(0,1136).
+char(7,1137).
+char(c,1138).
+char(c,1139).
+char(p,1140).
+char(o,1141).
+char(p,1142).
+char(8,1143).
+char(4,1144).
+char(0,1145).
+char(5,1146).
+char(m,1147).
+char(o,1148).
+char(p,1149).
+char(5,1150).
+char(2,1151).
+char(4,1152).
+char(c,1153).
+char(c,1154).
+char(m,1155).
+char(4,1156).
+char(0,1157).
+char(5,1158).
+char(6,1159).
+char(c,1160).
+char(m,1161).
+char(8,1162).
+char(3,1163).
+char(7,1164).
+char(9,1165).
+char(c,1166).
+char(c,1167).
+char(c,1168).
+char(c,1169).
+char(c,1170).
+char(c,1171).
+char(c,1172).
+char(p,1173).
+char(o,1174).
+char(p,1175).
+char(6,1176).
+char(7,1177).
+char(0,1178).
+char(2,1179).
+char(p,1180).
+char(5,1181).
+char(8,1182).
+char(5,1183).
+char(6,1184).
+char(c,1185).
+char(m,1186).
+char(4,1187).
+char(9,1188).
+char(2,1189).
+char(4,1190).
+char(p,1191).
+char(5,1192).
+char(0,1193).
+char(9,1194).
+char(1,1195).
+char(c,1196).
+char(c,1197).
+char(c,1198).
+char(c,1199).
+char(c,1200).
+char(m,1201).
+char(o,1202).
+char(o,1203).
+char(m,1204).
+char(o,1205).
+char(1,1206).
+char(4,1207).
+char(3,1208).
+char(1,1209).
+char(m,1210).
+char(o,1211).
+char(o,1212).
+char(o,1213).
+char(p,1214).
+char(o,1215).
+char(m,1216).
+char(o,1217).
+char(p,1218).
+char(o,1219).
+char(m,1220).
+char(o,1221).
+char(m,1222).
+char(5,1223).
+char(8,1224).
+char(3,1225).
+char(1,1226).
+char(p,1227).
+char(o,1228).
+char(m,1229).
+char(4,1230).
+char(8,1231).
+char(0,1232).
+char(1,1233).
+char(m,1234).
+char(o,1235).
+char(m,1236).
+char(5,1237).
+char(0,1238).
+char(3,1239).
+char(9,1240).
+char(c,1241).
+char(c,1242).
+char(p,1243).
+char(1,1244).
+char(3,1245).
+char(p,1246).
+char(o,1247).
+char(p,1248).
+char(o,1249).
+char(m,1250).
+char(o,1251).
+char(p,1252).
+char(7,1253).
+char(4,1254).
+char(8,1255).
+char(1,1256).
+char(p,1257).
+char(o,1258).
+char(p,1259).
+char(6,1260).
+char(1,1261).
+char(0,1262).
+char(9,1263).
+char(c,1264).
+char(c,1265).
+char(c,1266).
+char(m,1267).
+char(o,1268).
+char(2,1269).
+char(4,1270).
+char(4,1271).
+char(0,1272).
+char(p,1273).
+char(o,1274).
+char(7,1275).
+char(1,1276).
+char(2,1277).
+char(2,1278).
+char(m,1279).
+char(8,1280).
+char(6,1281).
+char(3,1282).
+char(6,1283).
+char(c,1284).
+char(p,1285).
+char(8,1286).
+char(3,1287).
+char(2,1288).
+char(6,1289).
+char(m,1290).
+char(o,1291).
+char(m,1292).
+char(o,1293).
+char(m,1294).
+char(o,1295).
+char(p,1296).
+char(4,1297).
+char(7,1298).
+char(7,1299).
+char(3,1300).
+char(c,1301).
+char(c,1302).
+char(c,1303).
+char(m,1304).
+char(o,1305).
+char(m,1306).
+char(o,1307).
+char(o,1308).
+char(m,1309).
+char(2,1310).
+char(7,1311).
+char(1,1312).
+char(0,1313).
+char(p,1314).
+char(o,1315).
+char(p,1316).
+char(7,1317).
+char(8,1318).
+char(7,1319).
+char(3,1320).
+char(c,1321).
+char(m,1322).
+char(7,1323).
+char(4,1324).
+char(3,1325).
+char(5,1326).
+char(c,1327).
+char(c,1328).
+char(c,1329).
+char(p,1330).
+char(o,1331).
+char(m,1332).
+char(4,1333).
+char(5,1334).
+char(0,1335).
+char(8,1336).
+char(m,1337).
+char(o,1338).
+char(p,1339).
+char(8,1340).
+char(6,1341).
+char(8,1342).
+char(c,1343).
+char(p,1344).
+char(2,1345).
+char(0,1346).
+char(9,1347).
+char(6,1348).
+char(m,1349).
+char(o,1350).
+char(m,1351).
+char(o,1352).
+char(p,1353).
+char(1,1354).
+char(4,1355).
+char(2,1356).
+char(3,1357).
+char(c,1358).
+char(c,1359).
+char(p,1360).
+char(o,1361).
+char(6,1362).
+char(5,1363).
+char(7,1364).
+char(8,1365).
+char(c,1366).
+char(c,1367).
+char(m,1368).
+char(6,1369).
+char(6,1370).
+char(6,1371).
+char(9,1372).
+char(p,1373).
+char(5,1374).
+char(6,1375).
+char(2,1376).
+char(5,1377).
+char(c,1378).
+char(c,1379).
+char(c,1380).
+char(c,1381).
+char(p,1382).
+char(3,1383).
+char(2,1384).
+char(3,1385).
+char(6,1386).
+char(c,1387).
+char(c,1388).
+char(c,1389).
+char(m,1390).
+char(o,1391).
+char(1,1392).
+char(1,1393).
+char(0,1394).
+char(0,1395).
+char(p,1396).
+char(3,1397).
+char(9,1398).
+char(9,1399).
+char(4,1400).
+char(c,1401).
+char(m,1402).
+char(6,1403).
+char(9,1404).
+char(9,1405).
+char(0,1406).
+char(p,1407).
+char(o,1408).
+char(p,1409).
+char(7,1410).
+char(2,1411).
+char(5,1412).
+char(4,1413).
+char(c,1414).
+char(c,1415).
+char(c,1416).
+char(c,1417).
+char(m,1418).
+char(6,1419).
+char(3,1420).
+char(7,1421).
+char(9,1422).
+char(c,1423).
+char(m,1424).
+char(o,1425).
+char(p,1426).
+char(5,1427).
+char(9,1428).
+char(7,1429).
+char(5,1430).
+char(p,1431).
+char(9,1432).
+char(8,1433).
+char(5,1434).
+char(7,1435).
+char(m,1436).
+char(1,1437).
+char(3,1438).
+char(1,1439).
+char(2,1440).
+char(m,1441).
+char(o,1442).
+char(p,1443).
+char(o,1444).
+char(m,1445).
+char(o,1446).
+char(m,1447).
+char(6,1448).
+char(2,1449).
+char(6,1450).
+char(9,1451).
+char(p,1452).
+char(1,1453).
+char(2,1454).
+char(2,1455).
+char(5,1456).
+char(m,1457).
+char(3,1458).
+char(5,1459).
+char(5,1460).
+char(3,1461).
+char(c,1462).
+char(m,1463).
+char(o,1464).
+char(9,1465).
+char(6,1466).
+char(8,1467).
+char(8,1468).
+char(c,1469).
+char(c,1470).
+char(c,1471).
+char(p,1472).
+char(5,1473).
+char(1,1474).
+char(7,1475).
+char(4,1476).
+char(p,1477).
+char(o,1478).
+char(m,1479).
+char(o,1480).
+char(m,1481).
+char(o,1482).
+char(o,1483).
+char(m,1484).
+char(o,1485).
+char(p,1486).
+char(9,1487).
+char(9,1488).
+char(0,1489).
+char(5,1490).
+char(m,1491).
+char(o,1492).
+char(m,1493).
+char(6,1494).
+char(9,1495).
+char(1,1496).
+char(9,1497).
+char(m,1498).
+char(3,1499).
+char(5,1500).
+char(8,1501).
+char(6,1502).
+char(m,1503).
+char(9,1504).
+char(0,1505).
+char(5,1506).
+char(m,1507).
+char(6,1508).
+char(9,1509).
+char(2,1510).
+char(5,1511).
+char(c,1512).
+char(m,1513).
+char(5,1514).
+char(5,1515).
+char(5,1516).
+char(0,1517).
+char(c,1518).
+char(c,1519).
+char(c,1520).
+char(c,1521).
+char(m,1522).
+char(o,1523).
+char(m,1524).
+char(o,1525).
+char(p,1526).
+char(6,1527).
+char(7,1528).
+char(0,1529).
+char(1,1530).
+char(c,1531).
+char(m,1532).
+char(6,1533).
+char(6,1534).
+char(5,1535).
+char(4,1536).
+char(c,1537).
+char(c,1538).
+char(p,1539).
+char(o,1540).
+char(3,1541).
+char(0,1542).
+char(9,1543).
+char(p,1544).
+char(o,1545).
+char(m,1546).
+char(o,1547).
+char(p,1548).
+char(o,1549).
+char(o,1550).
+char(m,1551).
+char(o,1552).
+char(p,1553).
+char(6,1554).
+char(5,1555).
+char(0,1556).
+char(5,1557).
+char(m,1558).
+char(5,1559).
+char(8,1560).
+char(1,1561).
+char(1,1562).
+char(m,1563).
+char(9,1564).
+char(5,1565).
+char(5,1566).
+char(8,1567).
+char(p,1568).
+char(9,1569).
+char(4,1570).
+char(c,1571).
+char(c,1572).
+char(c,1573).
+char(c,1574).
+char(c,1575).
+char(p,1576).
+char(o,1577).
+char(m,1578).
+char(o,1579).
+char(p,1580).
+char(o,1581).
+char(p,1582).
+char(o,1583).
+char(m,1584).
+char(o,1585).
+char(o,1586).
+char(p,1587).
+char(o,1588).
+char(m,1589).
+char(o,1590).
+char(p,1591).
+char(3,1592).
+char(9,1593).
+char(3,1594).
+char(2,1595).
+char(p,1596).
+char(o,1597).
+char(p,1598).
+char(4,1599).
+char(5,1600).
+char(3,1601).
+char(9,1602).
+char(c,1603).
+char(c,1604).
+char(c,1605).
+char(p,1606).
+char(1,1607).
+char(6,1608).
+char(7,1609).
+char(5,1610).
+char(c,1611).
+char(m,1612).
+char(o,1613).
+char(2,1614).
+char(8,1615).
+char(2,1616).
+char(8,1617).
+char(c,1618).
+char(m,1619).
+char(4,1620).
+char(5,1621).
+char(0,1622).
+char(1,1623).
+char(c,1624).
+char(c,1625).
+char(c,1626).
+char(m,1627).
+char(9,1628).
+char(6,1629).
+char(4,1630).
+char(7,1631).
+char(c,1632).
+char(c,1633).
+char(c,1634).
+char(c,1635).
+char(c,1636).
+char(c,1637).
+char(p,1638).
+char(o,1639).
+char(m,1640).
+char(o,1641).
+char(m,1642).
+char(o,1643).
+char(p,1644).
+char(o,1645).
+char(p,1646).
+char(o,1647).
+char(m,1648).
+char(o,1649).
+char(p,1650).
+char(o,1651).
+char(o,1652).
+char(m,1653).
+char(o,1654).
+char(p,1655).
+char(3,1656).
+char(5,1657).
+char(5,1658).
+char(1,1659).
+char(c,1660).
+char(m,1661).
+char(o,1662).
+char(m,1663).
+char(3,1664).
+char(0,1665).
+char(0,1666).
+char(4,1667).
+char(c,1668).
+char(c,1669).
+char(p,1670).
+char(o,1671).
+char(3,1672).
+char(9,1673).
+char(5,1674).
+char(5,1675).
+char(p,1676).
+char(o,1677).
+char(o,1678).
+char(m,1679).
+char(o,1680).
+char(m,1681).
+char(o,1682).
+char(m,1683).
+char(2,1684).
+char(7,1685).
+char(5,1686).
+char(5,1687).
+char(m,1688).
+char(o,1689).
+char(o,1690).
+char(o,1691).
+char(4,1692).
+char(9,1693).
+char(8,1694).
+char(6,1695).
+char(c,1696).
+char(p,1697).
+char(7,1698).
+char(9,1699).
+char(1,1700).
+char(7,1701).
+char(m,1702).
+char(o,1703).
+char(p,1704).
+char(o,1705).
+char(1,1706).
+char(7,1707).
+char(7,1708).
+char(9,1709).
+char(m,1710).
+char(o,1711).
+char(m,1712).
+char(o,1713).
+char(o,1714).
+char(o,1715).
+char(3,1716).
+char(0,1717).
+char(2,1718).
+char(5,1719).
+char(p,1720).
+char(o,1721).
+char(o,1722).
+char(p,1723).
+char(8,1724).
+char(9,1725).
+char(3,1726).
+char(3,1727).
+char(c,1728).
+char(p,1729).
+char(o,1730).
+char(1,1731).
+char(4,1732).
+char(0,1733).
+char(1,1734).
+char(p,1735).
+char(o,1736).
+char(p,1737).
+char(o,1738).
+char(p,1739).
+char(o,1740).
+char(p,1741).
+char(8,1742).
+char(1,1743).
+char(0,1744).
+char(1,1745).
+char(p,1746).
+char(3,1747).
+char(3,1748).
+char(5,1749).
+char(3,1750).
+char(p,1751).
+char(o,1752).
+char(m,1753).
+char(8,1754).
+char(8,1755).
+char(4,1756).
+char(3,1757).
+char(c,1758).
+char(m,1759).
+char(3,1760).
+char(1,1761).
+char(0,1762).
+char(8,1763).
+char(c,1764).
+char(m,1765).
+char(o,1766).
+char(m,1767).
+char(7,1768).
+char(1,1769).
+char(8,1770).
+char(5,1771).
+char(p,1772).
+char(9,1773).
+char(8,1774).
+char(3,1775).
+char(6,1776).
+char(m,1777).
+char(o,1778).
+char(o,1779).
+char(9,1780).
+char(5,1781).
+char(8,1782).
+char(c,1783).
+char(m,1784).
+char(o,1785).
+char(m,1786).
+char(o,1787).
+char(o,1788).
+char(m,1789).
+char(o,1790).
+char(m,1791).
+char(o,1792).
+char(p,1793).
+char(3,1794).
+char(7,1795).
+char(3,1796).
+char(6,1797).
+char(c,1798).
+char(c,1799).
+char(m,1800).
+char(o,1801).
+char(p,1802).
+char(o,1803).
+char(o,1804).
+char(p,1805).
+char(3,1806).
+char(2,1807).
+char(0,1808).
+char(8,1809).
+char(m,1810).
+char(2,1811).
+char(3,1812).
+char(2,1813).
+char(9,1814).
+char(c,1815).
+char(m,1816).
+char(3,1817).
+char(8,1818).
+char(5,1819).
+char(c,1820).
+char(c,1821).
+char(c,1822).
+char(c,1823).
+char(p,1824).
+char(o,1825).
+char(p,1826).
+char(8,1827).
+char(9,1828).
+char(1,1829).
+char(5,1830).
+char(c,1831).
+char(c,1832).
+char(c,1833).
+char(c,1834).
+char(p,1835).
+char(2,1836).
+char(4,1837).
+char(0,1838).
+char(7,1839).
+char(c,1840).
+char(p,1841).
+char(4,1842).
+char(1,1843).
+char(8,1844).
+char(4,1845).
+char(c,1846).
+char(p,1847).
+char(o,1848).
+char(p,1849).
+char(7,1850).
+char(9,1851).
+char(9,1852).
+char(1,1853).
+char(c,1854).
+char(m,1855).
+char(o,1856).
+char(m,1857).
+char(7,1858).
+char(3,1859).
+char(5,1860).
+char(7,1861).
+char(m,1862).
+char(o,1863).
+char(p,1864).
+char(6,1865).
+char(4,1866).
+char(0,1867).
+char(8,1868).
+char(c,1869).
+char(p,1870).
+char(4,1871).
+char(4,1872).
+char(3,1873).
+char(m,1874).
+char(6,1875).
+char(1,1876).
+char(7,1877).
+char(4,1878).
+char(c,1879).
+char(m,1880).
+char(o,1881).
+char(p,1882).
+char(8,1883).
+char(7,1884).
+char(0,1885).
+char(8,1886).
+char(p,1887).
+char(o,1888).
+char(p,1889).
+char(2,1890).
+char(3,1891).
+char(4,1892).
+char(1,1893).
+char(p,1894).
+char(1,1895).
+char(4,1896).
+char(3,1897).
+char(4,1898).
+char(m,1899).
+char(3,1900).
+char(7,1901).
+char(2,1902).
+char(2,1903).
+char(m,1904).
+char(1,1905).
+char(5,1906).
+char(4,1907).
+char(9,1908).
+char(p,1909).
+char(o,1910).
+char(o,1911).
+char(m,1912).
+char(o,1913).
+char(p,1914).
+char(2,1915).
+char(8,1916).
+char(4,1917).
+char(9,1918).
+char(c,1919).
+char(p,1920).
+char(4,1921).
+char(0,1922).
+char(4,1923).
+char(3,1924).
+char(m,1925).
+char(o,1926).
+char(m,1927).
+char(o,1928).
+char(p,1929).
+char(2,1930).
+char(0,1931).
+char(1,1932).
+char(5,1933).
+char(c,1934).
+char(c,1935).
+char(p,1936).
+char(4,1937).
+char(3,1938).
+char(4,1939).
+char(7,1940).
+char(c,1941).
+char(c,1942).
+char(p,1943).
+char(o,1944).
+char(m,1945).
+char(o,1946).
+char(o,1947).
+char(5,1948).
+char(7,1949).
+char(5,1950).
+char(2,1951).
+char(p,1952).
+char(5,1953).
+char(6,1954).
+char(0,1955).
+char(4,1956).
+char(m,1957).
+char(4,1958).
+char(4,1959).
+char(5,1960).
+char(7,1961).
+char(c,1962).
+char(p,1963).
+char(7,1964).
+char(0,1965).
+char(8,1966).
+char(m,1967).
+char(3,1968).
+char(2,1969).
+char(4,1970).
+char(2,1971).
+char(p,1972).
+char(4,1973).
+char(0,1974).
+char(2,1975).
+char(3,1976).
+char(c,1977).
+char(m,1978).
+char(8,1979).
+char(4,1980).
+char(1,1981).
+char(6,1982).
+char(c,1983).
+char(m,1984).
+char(o,1985).
+char(o,1986).
+char(p,1987).
+char(o,1988).
+char(p,1989).
+char(o,1990).
+char(p,1991).
+char(1,1992).
+char(0,1993).
+char(1,1994).
+char(6,1995).
+char(p,1996).
+char(o,1997).
+char(m,1998).
+char(2,1999).
+char(0,2000).
+char(5,2001).
+char(4,2002).
+char(p,2003).
+char(o,2004).
+char(2,2005).
+char(8,2006).
+char(8,2007).
+char(5,2008).
+char(p,2009).
+char(o,2010).
+char(9,2011).
+char(9,2012).
+char(9,2013).
+char(1,2014).
+char(c,2015).
+char(m,2016).
+char(8,2017).
+char(4,2018).
+char(4,2019).
+char(2,2020).
+char(c,2021).
+char(p,2022).
+char(7,2023).
+char(2,2024).
+char(5,2025).
+char(2,2026).
+char(c,2027).
+char(p,2028).
+char(o,2029).
+char(o,2030).
+char(8,2031).
+char(7,2032).
+char(6,2033).
+char(c,2034).
+char(p,2035).
+char(6,2036).
+char(6,2037).
+char(6,2038).
+char(5,2039).
+char(c,2040).
+char(m,2041).
+char(9,2042).
+char(1,2043).
+char(5,2044).
+char(2,2045).
+char(p,2046).
+char(7,2047).
+char(7,2048).
+char(0,2049).
+char(2,2050).
+char(m,2051).
+char(o,2052).
+char(p,2053).
+char(o,2054).
+char(m,2055).
+char(6,2056).
+char(2,2057).
+char(5,2058).
+char(8,2059).
+char(c,2060).
+char(c,2061).
+char(c,2062).
+char(c,2063).
+char(c,2064).
+char(c,2065).
+char(m,2066).
+char(o,2067).
+char(m,2068).
+char(o,2069).
+char(p,2070).
+char(8,2071).
+char(3,2072).
+char(3,2073).
+char(2,2074).
+char(m,2075).
+char(3,2076).
+char(3,2077).
+char(9,2078).
+char(c,2079).
+char(c,2080).
+char(c,2081).
+char(c,2082).
+char(c,2083).
+char(c,2084).
+char(c,2085).
+char(c,2086).
+char(m,2087).
+char(8,2088).
+char(2,2089).
+char(9,2090).
+char(6,2091).
+char(c,2092).
+char(c,2093).
+char(m,2094).
+char(8,2095).
+char(9,2096).
+char(0,2097).
+char(8,2098).
+char(p,2099).
+char(3,2100).
+char(6,2101).
+char(6,2102).
+char(2,2103).
+char(m,2104).
+char(7,2105).
+char(7,2106).
+char(9,2107).
+char(3,2108).
+char(p,2109).
+char(o,2110).
+char(p,2111).
+char(8,2112).
+char(2,2113).
+char(1,2114).
+char(2,2115).
+char(m,2116).
+char(6,2117).
+char(6,2118).
+char(4,2119).
+char(5,2120).
+char(c,2121).
+char(c,2122).
+char(c,2123).
+char(c,2124).
+char(p,2125).
+char(4,2126).
+char(4,2127).
+char(1,2128).
+char(8,2129).
+char(c,2130).
+char(c,2131).
+char(c,2132).
+char(c,2133).
+char(p,2134).
+char(o,2135).
+char(m,2136).
+char(2,2137).
+char(1,2138).
+char(2,2139).
+char(6,2140).
+char(p,2141).
+char(4,2142).
+char(5,2143).
+char(1,2144).
+char(3,2145).
+char(p,2146).
+char(3,2147).
+char(8,2148).
+char(9,2149).
+char(9,2150).
+char(p,2151).
+char(6,2152).
+char(1,2153).
+char(8,2154).
+char(5,2155).
+char(c,2156).
+char(c,2157).
+char(c,2158).
+char(c,2159).
+char(p,2160).
+char(o,2161).
+char(p,2162).
+char(o,2163).
+char(p,2164).
+char(o,2165).
+char(m,2166).
+char(4,2167).
+char(5,2168).
+char(8,2169).
+char(1,2170).
+char(p,2171).
+char(o,2172).
+char(p,2173).
+char(o,2174).
+char(m,2175).
+char(7,2176).
+char(6,2177).
+char(6,2178).
+char(c,2179).
+char(c,2180).
+char(c,2181).
+char(m,2182).
+char(9,2183).
+char(7,2184).
+char(0,2185).
+char(8,2186).
+char(p,2187).
+char(o,2188).
+char(m,2189).
+char(o,2190).
+char(7,2191).
+char(1,2192).
+char(0,2193).
+char(2,2194).
+char(m,2195).
+char(o,2196).
+char(o,2197).
+char(m,2198).
+char(4,2199).
+char(2,2200).
+char(1,2201).
+char(1,2202).
+char(c,2203).
+char(m,2204).
+char(7,2205).
+char(6,2206).
+char(5,2207).
+char(3,2208).
+char(p,2209).
+char(6,2210).
+char(6,2211).
+char(5,2212).
+char(7,2213).
+char(m,2214).
+char(3,2215).
+char(3,2216).
+char(3,2217).
+char(7,2218).
+char(p,2219).
+char(9,2220).
+char(3,2221).
+char(2,2222).
+char(4,2223).
+char(c,2224).
+char(c,2225).
+char(c,2226).
+char(p,2227).
+char(o,2228).
+char(p,2229).
+char(5,2230).
+char(0,2231).
+char(8,2232).
+char(3,2233).
+char(c,2234).
+char(p,2235).
+char(o,2236).
+char(9,2237).
+char(5,2238).
+char(5,2239).
+char(8,2240).
+char(p,2241).
+char(6,2242).
+char(9,2243).
+char(2,2244).
+char(6,2245).
+char(p,2246).
+char(o,2247).
+char(m,2248).
+char(3,2249).
+char(2,2250).
+char(8,2251).
+char(6,2252).
+char(c,2253).
+char(c,2254).
+char(c,2255).
+char(m,2256).
+char(o,2257).
+char(m,2258).
+char(o,2259).
+char(o,2260).
+char(p,2261).
+char(o,2262).
+char(p,2263).
+char(3,2264).
+char(8,2265).
+char(4,2266).
+char(7,2267).
+char(c,2268).
+char(p,2269).
+char(o,2270).
+char(o,2271).
+char(p,2272).
+char(o,2273).
+char(p,2274).
+char(o,2275).
+char(p,2276).
+char(2,2277).
+char(6,2278).
+char(7,2279).
+char(6,2280).
+char(m,2281).
+char(3,2282).
+char(8,2283).
+char(5,2284).
+char(9,2285).
+char(m,2286).
+char(4,2287).
+char(0,2288).
+char(3,2289).
+char(1,2290).
+char(m,2291).
+char(o,2292).
+char(p,2293).
+char(5,2294).
+char(7,2295).
+char(9,2296).
+char(1,2297).
+char(c,2298).
+char(c,2299).
+char(p,2300).
+char(1,2301).
+char(1,2302).
+char(7,2303).
+char(9,2304).
+char(m,2305).
+char(o,2306).
+char(3,2307).
+char(5,2308).
+char(5,2309).
+char(9,2310).
+char(m,2311).
+char(o,2312).
+char(o,2313).
+char(m,2314).
+char(3,2315).
+char(2,2316).
+char(4,2317).
+char(3,2318).
+char(c,2319).
+char(p,2320).
+char(o,2321).
+char(m,2322).
+char(6,2323).
+char(0,2324).
+char(7,2325).
+char(0,2326).
+char(m,2327).
+char(4,2328).
+char(0,2329).
+char(5,2330).
+char(3,2331).
+char(c,2332).
+char(p,2333).
+char(o,2334).
+char(m,2335).
+char(o,2336).
+char(o,2337).
+char(m,2338).
+char(o,2339).
+char(o,2340).
+char(m,2341).
+char(6,2342).
+char(6,2343).
+char(9,2344).
+char(1,2345).
+char(p,2346).
+char(9,2347).
+char(0,2348).
+char(6,2349).
+char(7,2350).
+char(m,2351).
+char(5,2352).
+char(4,2353).
+char(4,2354).
+char(1,2355).
+char(m,2356).
+char(o,2357).
+char(p,2358).
+char(o,2359).
+char(p,2360).
+char(1,2361).
+char(0,2362).
+char(0,2363).
+char(9,2364).
+char(p,2365).
+char(o,2366).
+char(o,2367).
+char(p,2368).
+char(o,2369).
+char(m,2370).
+char(5,2371).
+char(1,2372).
+char(7,2373).
+char(2,2374).
+char(c,2375).
+char(c,2376).
+char(p,2377).
+char(3,2378).
+char(2,2379).
+char(0,2380).
+char(1,2381).
+char(m,2382).
+char(o,2383).
+char(o,2384).
+char(m,2385).
+char(8,2386).
+char(9,2387).
+char(3,2388).
+char(4,2389).
+char(c,2390).
+char(c,2391).
+char(c,2392).
+char(c,2393).
+char(p,2394).
+char(3,2395).
+char(8,2396).
+char(7,2397).
+char(m,2398).
+char(o,2399).
+char(m,2400).
+char(7,2401).
+char(8,2402).
+char(7,2403).
+char(0,2404).
+char(m,2405).
+char(o,2406).
+char(m,2407).
+char(o,2408).
+char(o,2409).
+char(o,2410).
+char(m,2411).
+char(5,2412).
+char(1,2413).
+char(7,2414).
+char(8,2415).
+char(c,2416).
+char(c,2417).
+char(m,2418).
+char(o,2419).
+char(m,2420).
+char(o,2421).
+char(2,2422).
+char(7,2423).
+char(2,2424).
+char(m,2425).
+char(o,2426).
+char(6,2427).
+char(6,2428).
+char(4,2429).
+char(5,2430).
+char(p,2431).
+char(5,2432).
+char(6,2433).
+char(1,2434).
+char(5,2435).
+char(c,2436).
+char(p,2437).
+char(5,2438).
+char(8,2439).
+char(2,2440).
+char(3,2441).
+char(p,2442).
+char(o,2443).
+char(m,2444).
+char(o,2445).
+char(m,2446).
+char(o,2447).
+char(m,2448).
+char(o,2449).
+char(4,2450).
+char(9,2451).
+char(0,2452).
+char(5,2453).
+char(c,2454).
+char(m,2455).
+char(o,2456).
+char(p,2457).
+char(o,2458).
+char(p,2459).
+char(o,2460).
+char(m,2461).
+char(8,2462).
+char(2,2463).
+char(1,2464).
+char(9,2465).
+char(m,2466).
+char(2,2467).
+char(1,2468).
+char(7,2469).
+char(8,2470).
+char(c,2471).
+char(m,2472).
+char(o,2473).
+char(o,2474).
+char(o,2475).
+char(p,2476).
+char(3,2477).
+char(0,2478).
+char(6,2479).
+char(c,2480).
+char(c,2481).
+char(c,2482).
+char(c,2483).
+char(p,2484).
+char(5,2485).
+char(3,2486).
+char(0,2487).
+char(1,2488).
+char(m,2489).
+char(o,2490).
+char(7,2491).
+char(9,2492).
+char(9,2493).
+char(8,2494).
+char(c,2495).
+char(p,2496).
+char(1,2497).
+char(1,2498).
+char(7,2499).
+char(3,2500).
+char(p,2501).
+char(o,2502).
+char(p,2503).
+char(6,2504).
+char(3,2505).
+char(0,2506).
+char(5,2507).
+char(c,2508).
+char(p,2509).
+char(8,2510).
+char(8,2511).
+char(6,2512).
+char(7,2513).
+char(c,2514).
+char(c,2515).
+char(p,2516).
+char(o,2517).
+char(o,2518).
+char(m,2519).
+char(1,2520).
+char(2,2521).
+char(4,2522).
+char(7,2523).
+char(c,2524).
+char(m,2525).
+char(o,2526).
+char(3,2527).
+char(8,2528).
+char(7,2529).
+char(9,2530).
+char(c,2531).
+char(p,2532).
+char(o,2533).
+char(6,2534).
+char(4,2535).
+char(7,2536).
+char(c,2537).
+char(p,2538).
+char(9,2539).
+char(4,2540).
+char(4,2541).
+char(0,2542).
+char(c,2543).
+char(m,2544).
+char(o,2545).
+char(m,2546).
+char(o,2547).
+char(1,2548).
+char(6,2549).
+char(0,2550).
+char(0,2551).
+char(c,2552).
+char(m,2553).
+char(o,2554).
+char(5,2555).
+char(1,2556).
+char(3,2557).
+char(6,2558).
+char(c,2559).
+char(m,2560).
+char(3,2561).
+char(5,2562).
+char(3,2563).
+char(1,2564).
+char(c,2565).
+char(c,2566).
+char(p,2567).
+char(9,2568).
+char(9,2569).
+char(2,2570).
+char(2,2571).
+char(c,2572).
+char(m,2573).
+char(o,2574).
+char(p,2575).
+char(o,2576).
+char(p,2577).
+char(o,2578).
+char(p,2579).
+char(8,2580).
+char(2,2581).
+char(1,2582).
+char(c,2583).
+char(p,2584).
+char(o,2585).
+char(o,2586).
+char(o,2587).
+char(m,2588).
+char(8,2589).
+char(6,2590).
+char(5,2591).
+char(8,2592).
+char(c,2593).
+char(p,2594).
+char(o,2595).
+char(m,2596).
+char(o,2597).
+char(m,2598).
+char(o,2599).
+char(p,2600).
+char(o,2601).
+char(m,2602).
+char(8,2603).
+char(0,2604).
+char(6,2605).
+char(7,2606).
+char(p,2607).
+char(o,2608).
+char(1,2609).
+char(3,2610).
+char(9,2611).
+char(7,2612).
+char(c,2613).
+char(p,2614).
+char(o,2615).
+char(p,2616).
+char(5,2617).
+char(6,2618).
+char(3,2619).
+char(5,2620).
+char(p,2621).
+char(o,2622).
+char(p,2623).
+char(o,2624).
+char(o,2625).
+char(o,2626).
+char(7,2627).
+char(2,2628).
+char(6,2629).
+char(3,2630).
+char(c,2631).
+char(m,2632).
+char(o,2633).
+char(p,2634).
+char(9,2635).
+char(5,2636).
+char(7,2637).
+char(2,2638).
+char(c,2639).
+char(c,2640).
+char(c,2641).
+char(c,2642).
+char(c,2643).
+char(c,2644).
+char(c,2645).
+char(p,2646).
+char(o,2647).
+char(p,2648).
+char(7,2649).
+char(0,2650).
+char(5,2651).
+char(c,2652).
+char(m,2653).
+char(3,2654).
+char(0,2655).
+char(0,2656).
+char(8,2657).
+char(m,2658).
+char(3,2659).
+char(7,2660).
+char(2,2661).
+char(1,2662).
+char(p,2663).
+char(o,2664).
+char(p,2665).
+char(2,2666).
+char(8,2667).
+char(1,2668).
+char(4,2669).
+char(p,2670).
+char(o,2671).
+char(1,2672).
+char(5,2673).
+char(7,2674).
+char(8,2675).
+char(m,2676).
+char(o,2677).
+char(o,2678).
+char(m,2679).
+char(8,2680).
+char(9,2681).
+char(3,2682).
+char(2,2683).
+char(c,2684).
+char(m,2685).
+char(o,2686).
+char(m,2687).
+char(3,2688).
+char(9,2689).
+char(6,2690).
+char(7,2691).
+char(c,2692).
+char(c,2693).
+char(m,2694).
+char(o,2695).
+char(p,2696).
+char(2,2697).
+char(3,2698).
+char(3,2699).
+char(6,2700).
+char(c,2701).
+char(m,2702).
+char(o,2703).
+char(o,2704).
+char(1,2705).
+char(4,2706).
+char(4,2707).
+char(3,2708).
+char(c,2709).
+char(p,2710).
+char(3,2711).
+char(6,2712).
+char(8,2713).
+char(0,2714).
+char(p,2715).
+char(o,2716).
+char(o,2717).
+char(m,2718).
+char(7,2719).
+char(7,2720).
+char(2,2721).
+char(4,2722).
+char(m,2723).
+char(o,2724).
+char(m,2725).
+char(o,2726).
+char(p,2727).
+char(3,2728).
+char(1,2729).
+char(0,2730).
+char(2,2731).
+char(c,2732).
+char(c,2733).
+char(p,2734).
+char(o,2735).
+char(6,2736).
+char(8,2737).
+char(0,2738).
+char(3,2739).
+char(c,2740).
+char(p,2741).
+char(o,2742).
+char(p,2743).
+char(8,2744).
+char(5,2745).
+char(6,2746).
+char(5,2747).
+char(m,2748).
+char(o,2749).
+char(m,2750).
+char(o,2751).
+char(m,2752).
+char(o,2753).
+char(2,2754).
+char(6,2755).
+char(6,2756).
+char(7,2757).
+char(c,2758).
+char(c,2759).
+char(c,2760).
+char(p,2761).
+char(o,2762).
+char(m,2763).
+char(o,2764).
+char(m,2765).
+char(o,2766).
+char(p,2767).
+char(4,2768).
+char(4,2769).
+char(7,2770).
+char(5,2771).
+char(p,2772).
+char(4,2773).
+char(6,2774).
+char(1,2775).
+char(2,2776).
+char(p,2777).
+char(8,2778).
+char(5,2779).
+char(0,2780).
+char(7,2781).
+char(m,2782).
+char(o,2783).
+char(m,2784).
+char(1,2785).
+char(1,2786).
+char(3,2787).
+char(3,2788).
+char(c,2789).
+char(p,2790).
+char(6,2791).
+char(0,2792).
+char(1,2793).
+char(2,2794).
+char(c,2795).
+char(c,2796).
+char(c,2797).
+char(m,2798).
+char(o,2799).
+char(p,2800).
+char(o,2801).
+char(o,2802).
+char(p,2803).
+char(3,2804).
+char(2,2805).
+char(8,2806).
+char(2,2807).
+char(p,2808).
+char(3,2809).
+char(8,2810).
+char(0,2811).
+char(9,2812).
+char(m,2813).
+char(7,2814).
+char(7,2815).
+char(6,2816).
+char(6,2817).
+char(m,2818).
+char(o,2819).
+char(3,2820).
+char(7,2821).
+char(2,2822).
+char(6,2823).
+char(p,2824).
+char(6,2825).
+char(5,2826).
+char(3,2827).
+char(2,2828).
+char(p,2829).
+char(o,2830).
+char(p,2831).
+char(o,2832).
+char(p,2833).
+char(3,2834).
+char(0,2835).
+char(3,2836).
+char(c,2837).
+char(c,2838).
+char(p,2839).
+char(o,2840).
+char(7,2841).
+char(5,2842).
+char(7,2843).
+char(7,2844).
+char(m,2845).
+char(o,2846).
+char(p,2847).
+char(9,2848).
+char(7,2849).
+char(4,2850).
+char(1,2851).
+char(c,2852).
+char(p,2853).
+char(7,2854).
+char(2,2855).
+char(0,2856).
+char(2,2857).
+char(m,2858).
+char(1,2859).
+char(6,2860).
+char(8,2861).
+char(1,2862).
+char(p,2863).
+char(o,2864).
+char(o,2865).
+char(p,2866).
+char(o,2867).
+char(3,2868).
+char(7,2869).
+char(4,2870).
+char(4,2871).
+char(m,2872).
+char(8,2873).
+char(8,2874).
+char(1,2875).
+char(4,2876).
+char(c,2877).
+char(p,2878).
+char(o,2879).
+char(m,2880).
+char(9,2881).
+char(7,2882).
+char(7,2883).
+char(0,2884).
+char(m,2885).
+char(o,2886).
+char(2,2887).
+char(5,2888).
+char(5,2889).
+char(9,2890).
+char(m,2891).
+char(o,2892).
+char(o,2893).
+char(m,2894).
+char(4,2895).
+char(3,2896).
+char(7,2897).
+char(8,2898).
+char(c,2899).
+char(m,2900).
+char(o,2901).
+char(2,2902).
+char(1,2903).
+char(1,2904).
+char(0,2905).
+char(p,2906).
+char(o,2907).
+char(4,2908).
+char(7,2909).
+char(3,2910).
+char(2,2911).
+char(c,2912).
+char(c,2913).
+char(c,2914).
+char(c,2915).
+char(c,2916).
+char(m,2917).
+char(o,2918).
+char(m,2919).
+char(6,2920).
+char(2,2921).
+char(2,2922).
+char(7,2923).
+char(p,2924).
+char(o,2925).
+char(6,2926).
+char(3,2927).
+char(9,2928).
+char(4,2929).
+char(p,2930).
+char(o,2931).
+char(p,2932).
+char(o,2933).
+char(p,2934).
+char(o,2935).
+char(p,2936).
+char(1,2937).
+char(5,2938).
+char(4,2939).
+char(4,2940).
+char(c,2941).
+char(c,2942).
+char(c,2943).
+char(m,2944).
+char(o,2945).
+char(o,2946).
+char(m,2947).
+char(o,2948).
+char(p,2949).
+char(1,2950).
+char(5,2951).
+char(9,2952).
+char(1,2953).
+char(c,2954).
+char(c,2955).
+char(c,2956).
+char(m,2957).
+char(o,2958).
+char(m,2959).
+char(9,2960).
+char(2,2961).
+char(0,2962).
+char(2,2963).
+char(c,2964).
+char(p,2965).
+char(1,2966).
+char(7,2967).
+char(0,2968).
+char(p,2969).
+char(o,2970).
+char(m,2971).
+char(2,2972).
+char(9,2973).
+char(8,2974).
+char(0,2975).
+char(c,2976).
+char(c,2977).
+char(c,2978).
+char(m,2979).
+char(3,2980).
+char(2,2981).
+char(8,2982).
+char(7,2983).
+char(c,2984).
+char(c,2985).
+char(c,2986).
+char(c,2987).
+char(c,2988).
+char(p,2989).
+char(o,2990).
+char(m,2991).
+char(o,2992).
+char(p,2993).
+char(o,2994).
+char(2,2995).
+char(0,2996).
+char(9,2997).
+char(2,2998).
+char(p,2999).
+char(o,3000).
+char(p,3001).
+char(o,3002).
+char(9,3003).
+char(8,3004).
+char(6,3005).
+char(7,3006).
+char(c,3007).
+char(c,3008).
+char(c,3009).
+char(m,3010).
+char(o,3011).
+char(p,3012).
+char(8,3013).
+char(7,3014).
+char(2,3015).
+char(6,3016).
+char(p,3017).
+char(o,3018).
+char(p,3019).
+char(7,3020).
+char(4,3021).
+char(7,3022).
+char(4,3023).
+char(c,3024).
+char(c,3025).
+char(p,3026).
+char(4,3027).
+char(8,3028).
+char(6,3029).
+char(7,3030).
+char(m,3031).
+char(o,3032).
+char(8,3033).
+char(4,3034).
+char(3,3035).
+char(2,3036).
+char(m,3037).
+char(2,3038).
+char(8,3039).
+char(4,3040).
+char(2,3041).
+char(c,3042).
+char(c,3043).
+char(p,3044).
+char(o,3045).
+char(6,3046).
+char(6,3047).
+char(9,3048).
+char(9,3049).
+char(c,3050).
+char(c,3051).
+char(c,3052).
+char(m,3053).
+char(o,3054).
+char(p,3055).
+char(o,3056).
+char(p,3057).
+char(o,3058).
+char(m,3059).
+char(8,3060).
+char(1,3061).
+char(1,3062).
+char(9,3063).
+char(c,3064).
+char(p,3065).
+char(o,3066).
+char(1,3067).
+char(3,3068).
+char(2,3069).
+char(c,3070).
+char(p,3071).
+char(o,3072).
+char(o,3073).
+char(o,3074).
+char(m,3075).
+char(3,3076).
+char(1,3077).
+char(4,3078).
+char(1,3079).
+char(m,3080).
+char(o,3081).
+char(o,3082).
+char(p,3083).
+char(4,3084).
+char(8,3085).
+char(1,3086).
+char(7,3087).
+char(c,3088).
+char(p,3089).
+char(9,3090).
+char(5,3091).
+char(6,3092).
+char(c,3093).
+char(c,3094).
+char(c,3095).
+char(c,3096).
+char(c,3097).
+char(c,3098).
+char(c,3099).
+char(m,3100).
+char(o,3101).
+char(m,3102).
+char(o,3103).
+char(p,3104).
+char(o,3105).
+char(m,3106).
+char(o,3107).
+char(m,3108).
+char(5,3109).
+char(3,3110).
+char(5,3111).
+char(c,3112).
+char(m,3113).
+char(o,3114).
+char(m,3115).
+char(o,3116).
+char(p,3117).
+char(2,3118).
+char(4,3119).
+char(5,3120).
+char(6,3121).
+char(c,3122).
+char(c,3123).
+char(p,3124).
+char(o,3125).
+char(9,3126).
+char(1,3127).
+char(1,3128).
+char(9,3129).
+char(c,3130).
+char(m,3131).
+char(3,3132).
+char(5,3133).
+char(5,3134).
+char(5,3135).
+char(c,3136).
+char(c,3137).
+char(c,3138).
+char(p,3139).
+char(o,3140).
+char(p,3141).
+char(o,3142).
+char(m,3143).
+char(o,3144).
+char(m,3145).
+char(1,3146).
+char(2,3147).
+char(7,3148).
+char(c,3149).
+char(c,3150).
+char(c,3151).
+char(m,3152).
+char(o,3153).
+char(o,3154).
+char(m,3155).
+char(7,3156).
+char(9,3157).
+char(7,3158).
+char(4,3159).
+char(m,3160).
+char(o,3161).
+char(8,3162).
+char(3,3163).
+char(3,3164).
+char(p,3165).
+char(o,3166).
+char(p,3167).
+char(o,3168).
+char(m,3169).
+char(7,3170).
+char(3,3171).
+char(2,3172).
+char(0,3173).
+char(c,3174).
+char(m,3175).
+char(o,3176).
+char(7,3177).
+char(3,3178).
+char(0,3179).
+char(6,3180).
+char(c,3181).
+char(p,3182).
+char(7,3183).
+char(1,3184).
+char(5,3185).
+char(1,3186).
+char(c,3187).
+char(c,3188).
+char(c,3189).
+char(c,3190).
+char(c,3191).
+char(c,3192).
+char(m,3193).
+char(1,3194).
+char(2,3195).
+char(9,3196).
+char(p,3197).
+char(o,3198).
+char(m,3199).
+char(7,3200).
+char(9,3201).
+char(6,3202).
+char(0,3203).
+char(p,3204).
+char(o,3205).
+char(m,3206).
+char(o,3207).
+char(p,3208).
+char(o,3209).
+char(p,3210).
+char(9,3211).
+char(2,3212).
+char(1,3213).
+char(2,3214).
+char(c,3215).
+char(p,3216).
+char(o,3217).
+char(o,3218).
+char(o,3219).
+char(m,3220).
+char(3,3221).
+char(6,3222).
+char(7,3223).
+char(m,3224).
+char(o,3225).
+char(m,3226).
+char(o,3227).
+char(o,3228).
+char(m,3229).
+char(8,3230).
+char(2,3231).
+char(2,3232).
+char(7,3233).
+char(c,3234).
+char(c,3235).
+char(p,3236).
+char(9,3237).
+char(5,3238).
+char(9,3239).
+char(p,3240).
+char(2,3241).
+char(5,3242).
+char(3,3243).
+char(2,3244).
+char(p,3245).
+char(o,3246).
+char(m,3247).
+char(5,3248).
+char(8,3249).
+char(1,3250).
+char(8,3251).
+char(m,3252).
+char(8,3253).
+char(6,3254).
+char(3,3255).
+char(7,3256).
+char(c,3257).
+char(c,3258).
+char(m,3259).
+char(2,3260).
+char(2,3261).
+char(7,3262).
+char(1,3263).
+char(c,3264).
+char(m,3265).
+char(9,3266).
+char(9,3267).
+char(8,3268).
+char(9,3269).
+char(c,3270).
+char(c,3271).
+char(c,3272).
+char(m,3273).
+char(o,3274).
+char(p,3275).
+char(6,3276).
+char(5,3277).
+char(4,3278).
+char(3,3279).
+char(m,3280).
+char(o,3281).
+char(m,3282).
+char(7,3283).
+char(7,3284).
+char(5,3285).
+char(2,3286).
+char(p,3287).
+char(1,3288).
+char(1,3289).
+char(7,3290).
+char(8,3291).
+char(c,3292).
+char(p,3293).
+char(o,3294).
+char(p,3295).
+char(5,3296).
+char(5,3297).
+char(2,3298).
+char(0,3299).
+char(c,3300).
+char(m,3301).
+char(o,3302).
+char(m,3303).
+char(2,3304).
+char(7,3305).
+char(3,3306).
+char(3,3307).
+char(c,3308).
+char(m,3309).
+char(o,3310).
+char(m,3311).
+char(o,3312).
+char(4,3313).
+char(1,3314).
+char(1,3315).
+char(6,3316).
+char(c,3317).
+char(p,3318).
+char(1,3319).
+char(5,3320).
+char(4,3321).
+char(m,3322).
+char(3,3323).
+char(3,3324).
+char(0,3325).
+char(1,3326).
+char(c,3327).
+char(m,3328).
+char(8,3329).
+char(6,3330).
+char(2,3331).
+char(9,3332).
+char(p,3333).
+char(o,3334).
+char(m,3335).
+char(7,3336).
+char(4,3337).
+char(0,3338).
+char(8,3339).
+char(c,3340).
+char(c,3341).
+char(p,3342).
+char(o,3343).
+char(o,3344).
+char(8,3345).
+char(9,3346).
+char(3,3347).
+char(1,3348).
+char(c,3349).
+char(c,3350).
+char(c,3351).
+char(c,3352).
+char(c,3353).
+char(p,3354).
+char(o,3355).
+char(p,3356).
+char(o,3357).
+char(p,3358).
+char(6,3359).
+char(2,3360).
+char(7,3361).
+char(7,3362).
+char(c,3363).
+char(m,3364).
+char(o,3365).
+char(4,3366).
+char(6,3367).
+char(4,3368).
+char(8,3369).
+char(m,3370).
+char(9,3371).
+char(9,3372).
+char(1,3373).
+char(2,3374).
+char(m,3375).
+char(o,3376).
+char(p,3377).
+char(o,3378).
+char(p,3379).
+char(1,3380).
+char(8,3381).
+char(1,3382).
+char(0,3383).
+char(c,3384).
+char(p,3385).
+char(6,3386).
+char(9,3387).
+char(4,3388).
+char(7,3389).
+char(c,3390).
+char(p,3391).
+char(o,3392).
+char(o,3393).
+char(o,3394).
+char(m,3395).
+char(5,3396).
+char(8,3397).
+char(3,3398).
+char(m,3399).
+char(1,3400).
+char(4,3401).
+char(9,3402).
+char(6,3403).
+char(p,3404).
+char(7,3405).
+char(8,3406).
+char(1,3407).
+char(8,3408).
+char(c,3409).
+char(c,3410).
+char(c,3411).
+char(p,3412).
+char(2,3413).
+char(4,3414).
+char(4,3415).
+char(4,3416).
+char(c,3417).
+char(p,3418).
+char(o,3419).
+char(p,3420).
+char(4,3421).
+char(6,3422).
+char(2,3423).
+char(9,3424).
+char(p,3425).
+char(4,3426).
+char(3,3427).
+char(7,3428).
+char(7,3429).
+char(c,3430).
+char(m,3431).
+char(1,3432).
+char(8,3433).
+char(5,3434).
+char(1,3435).
+char(c,3436).
+char(c,3437).
+char(p,3438).
+char(6,3439).
+char(6,3440).
+char(4,3441).
+char(3,3442).
+char(m,3443).
+char(o,3444).
+char(p,3445).
+char(3,3446).
+char(1,3447).
+char(1,3448).
+char(5,3449).
+char(c,3450).
+char(m,3451).
+char(2,3452).
+char(6,3453).
+char(1,3454).
+char(c,3455).
+char(m,3456).
+char(o,3457).
+char(1,3458).
+char(3,3459).
+char(1,3460).
+char(8,3461).
+char(c,3462).
+char(p,3463).
+char(o,3464).
+char(p,3465).
+char(8,3466).
+char(4,3467).
+char(5,3468).
+char(6,3469).
+char(p,3470).
+char(o,3471).
+char(m,3472).
+char(7,3473).
+char(8,3474).
+char(7,3475).
+char(5,3476).
+char(c,3477).
+char(c,3478).
+char(c,3479).
+char(m,3480).
+char(2,3481).
+char(2,3482).
+char(9,3483).
+char(c,3484).
+char(p,3485).
+char(7,3486).
+char(8,3487).
+char(6,3488).
+char(4,3489).
+char(c,3490).
+char(c,3491).
+char(p,3492).
+char(7,3493).
+char(0,3494).
+char(4,3495).
+char(3,3496).
+char(p,3497).
+char(4,3498).
+char(5,3499).
+char(3,3500).
+char(5,3501).
+char(m,3502).
+char(9,3503).
+char(3,3504).
+char(5,3505).
+char(9,3506).
+char(p,3507).
+char(5,3508).
+char(2,3509).
+char(1,3510).
+char(3,3511).
+char(c,3512).
+char(c,3513).
+char(c,3514).
+char(m,3515).
+char(o,3516).
+char(p,3517).
+char(5,3518).
+char(8,3519).
+char(9,3520).
+char(2,3521).
+char(c,3522).
+char(c,3523).
+char(c,3524).
+char(p,3525).
+char(o,3526).
+char(m,3527).
+char(o,3528).
+char(m,3529).
+char(2,3530).
+char(7,3531).
+char(4,3532).
+char(7,3533).
+char(m,3534).
+char(6,3535).
+char(3,3536).
+char(7,3537).
+char(9,3538).
+char(c,3539).
+char(c,3540).
+char(m,3541).
+char(7,3542).
+char(2,3543).
+char(7,3544).
+char(p,3545).
+char(o,3546).
+char(p,3547).
+char(o,3548).
+char(2,3549).
+char(4,3550).
+char(1,3551).
+char(1,3552).
+char(c,3553).
+char(c,3554).
+char(c,3555).
+char(p,3556).
+char(o,3557).
+char(o,3558).
+char(o,3559).
+char(m,3560).
+char(o,3561).
+char(o,3562).
+char(m,3563).
+char(9,3564).
+char(4,3565).
+char(0,3566).
+char(c,3567).
+char(c,3568).
+char(c,3569).
+char(m,3570).
+char(o,3571).
+char(o,3572).
+char(m,3573).
+char(1,3574).
+char(9,3575).
+char(4,3576).
+char(7,3577).
+char(c,3578).
+char(m,3579).
+char(9,3580).
+char(6,3581).
+char(5,3582).
+char(6,3583).
+char(c,3584).
+char(m,3585).
+char(6,3586).
+char(4,3587).
+char(1,3588).
+char(c,3589).
+char(p,3590).
+char(5,3591).
+char(1,3592).
+char(4,3593).
+char(5,3594).
+char(c,3595).
+char(c,3596).
+char(m,3597).
+char(o,3598).
+char(p,3599).
+char(4,3600).
+char(2,3601).
+char(8,3602).
+char(4,3603).
+char(m,3604).
+char(o,3605).
+char(8,3606).
+char(1,3607).
+char(8,3608).
+char(1,3609).
+char(p,3610).
+char(7,3611).
+char(7,3612).
+char(4,3613).
+char(7,3614).
+char(c,3615).
+char(m,3616).
+char(6,3617).
+char(5,3618).
+char(7,3619).
+char(9,3620).
+char(c,3621).
+char(c,3622).
+char(c,3623).
+char(p,3624).
+char(o,3625).
+char(2,3626).
+char(1,3627).
+char(0,3628).
+char(m,3629).
+char(4,3630).
+char(3,3631).
+char(3,3632).
+char(1,3633).
+char(c,3634).
+char(c,3635).
+char(c,3636).
+char(c,3637).
+char(c,3638).
+char(m,3639).
+char(o,3640).
+char(m,3641).
+char(o,3642).
+char(p,3643).
+char(o,3644).
+char(m,3645).
+char(o,3646).
+char(m,3647).
+char(o,3648).
+char(p,3649).
+char(1,3650).
+char(7,3651).
+char(2,3652).
+char(0,3653).
+char(c,3654).
+char(m,3655).
+char(o,3656).
+char(m,3657).
+char(5,3658).
+char(4,3659).
+char(8,3660).
+char(0,3661).
+char(p,3662).
+char(5,3663).
+char(2,3664).
+char(9,3665).
+char(m,3666).
+char(7,3667).
+char(2,3668).
+char(2,3669).
+char(1,3670).
+char(c,3671).
+char(c,3672).
+char(m,3673).
+char(3,3674).
+char(8,3675).
+char(4,3676).
+char(p,3677).
+char(o,3678).
+char(m,3679).
+char(o,3680).
+char(m,3681).
+char(o,3682).
+char(m,3683).
+char(7,3684).
+char(3,3685).
+char(1,3686).
+char(6,3687).
+char(m,3688).
+char(o,3689).
+char(p,3690).
+char(3,3691).
+char(9,3692).
+char(1,3693).
+char(9,3694).
+char(m,3695).
+char(9,3696).
+char(1,3697).
+char(1,3698).
+char(4,3699).
+char(c,3700).
+char(p,3701).
+char(4,3702).
+char(2,3703).
+char(5,3704).
+char(5,3705).
+char(p,3706).
+char(o,3707).
+char(o,3708).
+char(o,3709).
+char(o,3710).
+char(m,3711).
+char(2,3712).
+char(4,3713).
+char(7,3714).
+char(8,3715).
+char(p,3716).
+char(o,3717).
+char(p,3718).
+char(5,3719).
+char(1,3720).
+char(4,3721).
+char(3,3722).
+char(m,3723).
+char(4,3724).
+char(3,3725).
+char(8,3726).
+char(2,3727).
+char(m,3728).
+char(o,3729).
+char(o,3730).
+char(5,3731).
+char(2,3732).
+char(8,3733).
+char(1,3734).
+char(m,3735).
+char(o,3736).
+char(m,3737).
+char(6,3738).
+char(1,3739).
+char(6,3740).
+char(6,3741).
+char(m,3742).
+char(8,3743).
+char(2,3744).
+char(1,3745).
+char(8,3746).
+char(m,3747).
+char(4,3748).
+char(7,3749).
+char(9,3750).
+char(5,3751).
+char(p,3752).
+char(9,3753).
+char(0,3754).
+char(3,3755).
+char(8,3756).
+char(c,3757).
+char(p,3758).
+char(2,3759).
+char(5,3760).
+char(6,3761).
+char(5,3762).
+char(c,3763).
+char(p,3764).
+char(o,3765).
+char(o,3766).
+char(o,3767).
+char(p,3768).
+char(o,3769).
+char(9,3770).
+char(9,3771).
+char(2,3772).
+char(7,3773).
+char(c,3774).
+char(p,3775).
+char(o,3776).
+char(p,3777).
+char(8,3778).
+char(8,3779).
+char(5,3780).
+char(1,3781).
+char(c,3782).
+char(p,3783).
+char(o,3784).
+char(o,3785).
+char(o,3786).
+char(p,3787).
+char(2,3788).
+char(8,3789).
+char(9,3790).
+char(2,3791).
+char(m,3792).
+char(7,3793).
+char(6,3794).
+char(6,3795).
+char(3,3796).
+char(p,3797).
+char(o,3798).
+char(8,3799).
+char(4,3800).
+char(6,3801).
+char(7,3802).
+char(c,3803).
+char(c,3804).
+char(p,3805).
+char(o,3806).
+char(o,3807).
+char(p,3808).
+char(2,3809).
+char(5,3810).
+char(8,3811).
+char(5,3812).
+char(p,3813).
+char(o,3814).
+char(o,3815).
+char(m,3816).
+char(4,3817).
+char(4,3818).
+char(4,3819).
+char(2,3820).
+char(p,3821).
+char(2,3822).
+char(7,3823).
+char(1,3824).
+char(4,3825).
+char(c,3826).
+char(p,3827).
+char(o,3828).
+char(o,3829).
+char(m,3830).
+char(o,3831).
+char(p,3832).
+char(o,3833).
+char(o,3834).
+char(m,3835).
+char(o,3836).
+char(o,3837).
+char(3,3838).
+char(1,3839).
+char(0,3840).
+char(3,3841).
+char(p,3842).
+char(2,3843).
+char(6,3844).
+char(6,3845).
+char(p,3846).
+char(9,3847).
+char(5,3848).
+char(8,3849).
+char(3,3850).
+char(m,3851).
+char(o,3852).
+char(o,3853).
+char(m,3854).
+char(4,3855).
+char(5,3856).
+char(4,3857).
+char(8,3858).
+char(c,3859).
+char(p,3860).
+char(1,3861).
+char(3,3862).
+char(4,3863).
+char(2,3864).
+char(c,3865).
+char(m,3866).
+char(o,3867).
+char(p,3868).
+char(o,3869).
+char(m,3870).
+char(9,3871).
+char(0,3872).
+char(5,3873).
+char(3,3874).
+char(p,3875).
+char(4,3876).
+char(0,3877).
+char(4,3878).
+char(8,3879).
+char(p,3880).
+char(1,3881).
+char(2,3882).
+char(7,3883).
+char(2,3884).
+char(c,3885).
+char(c,3886).
+char(c,3887).
+char(c,3888).
+char(p,3889).
+char(o,3890).
+char(p,3891).
+char(o,3892).
+char(m,3893).
+char(o,3894).
+char(2,3895).
+char(5,3896).
+char(3,3897).
+char(6,3898).
+char(m,3899).
+char(2,3900).
+char(8,3901).
+char(9,3902).
+char(7,3903).
+char(c,3904).
+char(m,3905).
+char(7,3906).
+char(8,3907).
+char(9,3908).
+char(2,3909).
+char(c,3910).
+char(c,3911).
+char(m,3912).
+char(o,3913).
+char(o,3914).
+char(o,3915).
+char(o,3916).
+char(p,3917).
+char(o,3918).
+char(m,3919).
+char(o,3920).
+char(o,3921).
+char(p,3922).
+char(o,3923).
+char(o,3924).
+char(m,3925).
+char(o,3926).
+char(m,3927).
+char(o,3928).
+char(p,3929).
+char(o,3930).
+char(4,3931).
+char(3,3932).
+char(2,3933).
+char(4,3934).
+char(c,3935).
+char(c,3936).
+char(m,3937).
+char(3,3938).
+char(2,3939).
+char(2,3940).
+char(3,3941).
+char(c,3942).
+char(m,3943).
+char(6,3944).
+char(0,3945).
+char(2,3946).
+char(3,3947).
+char(c,3948).
+char(c,3949).
+char(p,3950).
+char(o,3951).
+char(p,3952).
+char(8,3953).
+char(9,3954).
+char(3,3955).
+char(0,3956).
+char(c,3957).
+char(c,3958).
+char(p,3959).
+char(6,3960).
+char(9,3961).
+char(3,3962).
+char(7,3963).
+char(m,3964).
+char(o,3965).
+char(o,3966).
+char(3,3967).
+char(8,3968).
+char(3,3969).
+char(5,3970).
+char(c,3971).
+char(c,3972).
+char(c,3973).
+char(c,3974).
+char(c,3975).
+char(p,3976).
+char(7,3977).
+char(0,3978).
+char(2,3979).
+char(5,3980).
+char(m,3981).
+char(o,3982).
+char(o,3983).
+char(p,3984).
+char(o,3985).
+char(m,3986).
+char(o,3987).
+char(7,3988).
+char(0,3989).
+char(2,3990).
+char(6,3991).
+char(m,3992).
+char(o,3993).
+char(7,3994).
+char(0,3995).
+char(8,3996).
+char(7,3997).
+char(p,3998).
+char(o,3999).
+char(p,4000).
+char(9,4001).
+char(4,4002).
+char(0,4003).
+char(m,4004).
+char(o,4005).
+char(m,4006).
+char(o,4007).
+char(m,4008).
+char(o,4009).
+char(p,4010).
+char(4,4011).
+char(3,4012).
+char(8,4013).
+char(5,4014).
+char(p,4015).
+char(o,4016).
+char(m,4017).
+char(o,4018).
+char(1,4019).
+char(1,4020).
+char(6,4021).
+char(0,4022).
+char(m,4023).
+char(1,4024).
+char(9,4025).
+char(4,4026).
+char(9,4027).
+char(m,4028).
+char(o,4029).
+char(7,4030).
+char(0,4031).
+char(9,4032).
+char(9,4033).
+char(m,4034).
+char(1,4035).
+char(4,4036).
+char(3,4037).
+char(7,4038).
+char(p,4039).
+char(o,4040).
+char(p,4041).
+char(5,4042).
+char(4,4043).
+char(9,4044).
+char(2,4045).
+char(m,4046).
+char(o,4047).
+char(o,4048).
+char(o,4049).
+char(p,4050).
+char(o,4051).
+char(m,4052).
+char(o,4053).
+char(4,4054).
+char(1,4055).
+char(8,4056).
+char(9,4057).
+char(c,4058).
+char(c,4059).
+char(m,4060).
+char(o,4061).
+char(m,4062).
+char(o,4063).
+char(p,4064).
+char(o,4065).
+char(m,4066).
+char(1,4067).
+char(5,4068).
+char(5,4069).
+char(0,4070).
+char(c,4071).
+char(c,4072).
+char(c,4073).
+char(c,4074).
+char(c,4075).
+char(c,4076).
+char(p,4077).
+char(8,4078).
+char(2,4079).
+char(3,4080).
+char(9,4081).
+char(c,4082).
+char(c,4083).
+char(c,4084).
+char(c,4085).
+char(c,4086).
+char(m,4087).
+char(3,4088).
+char(9,4089).
+char(0,4090).
+char(m,4091).
+char(6,4092).
+char(2,4093).
+char(8,4094).
+char(8,4095).
+char(c,4096).
+char(c,4097).
+char(c,4098).
+char(c,4099).
+char(c,4100).
+char(c,4101).
+char(c,4102).
+char(p,4103).
+char(o,4104).
+char(p,4105).
+char(o,4106).
+char(p,4107).
+char(o,4108).
+char(m,4109).
+char(o,4110).
+char(o,4111).
+char(p,4112).
+char(o,4113).
+char(9,4114).
+char(1,4115).
+char(8,4116).
+char(8,4117).
+char(p,4118).
+char(6,4119).
+char(6,4120).
+char(2,4121).
+char(4,4122).
+char(c,4123).
+char(m,4124).
+char(o,4125).
+char(2,4126).
+char(3,4127).
+char(3,4128).
+char(3,4129).
+char(c,4130).
+char(c,4131).
+char(c,4132).
+char(c,4133).
+char(m,4134).
+char(o,4135).
+char(4,4136).
+char(7,4137).
+char(4,4138).
+char(3,4139).
+char(c,4140).
+char(c,4141).
+char(c,4142).
+char(m,4143).
+char(o,4144).
+char(p,4145).
+char(o,4146).
+char(p,4147).
+char(3,4148).
+char(0,4149).
+char(5,4150).
+char(5,4151).
+char(p,4152).
+char(o,4153).
+char(m,4154).
+char(6,4155).
+char(2,4156).
+char(6,4157).
+char(6,4158).
+char(p,4159).
+char(o,4160).
+char(m,4161).
+char(4,4162).
+char(9,4163).
+char(6,4164).
+char(9,4165).
+char(c,4166).
+char(m,4167).
+char(o,4168).
+char(6,4169).
+char(1,4170).
+char(5,4171).
+char(7,4172).
+char(c,4173).
+char(c,4174).
+char(c,4175).
+char(c,4176).
+char(p,4177).
+char(8,4178).
+char(1,4179).
+char(5,4180).
+char(4,4181).
+char(c,4182).
+char(c,4183).
+char(c,4184).
+char(c,4185).
+char(c,4186).
+char(c,4187).
+char(c,4188).
+char(c,4189).
+char(p,4190).
+char(1,4191).
+char(7,4192).
+char(5,4193).
+char(m,4194).
+char(7,4195).
+char(5,4196).
+char(4,4197).
+char(5,4198).
+char(p,4199).
+char(o,4200).
+char(m,4201).
+char(o,4202).
+char(2,4203).
+char(0,4204).
+char(8,4205).
+char(5,4206).
+char(c,4207).
+char(m,4208).
+char(o,4209).
+char(o,4210).
+char(6,4211).
+char(6,4212).
+char(0,4213).
+char(8,4214).
+char(m,4215).
+char(9,4216).
+char(3,4217).
+char(5,4218).
+char(2,4219).
+char(c,4220).
+char(p,4221).
+char(o,4222).
+char(p,4223).
+char(4,4224).
+char(3,4225).
+char(4,4226).
+char(2,4227).
+char(m,4228).
+char(1,4229).
+char(1,4230).
+char(6,4231).
+char(1,4232).
+char(c,4233).
+char(c,4234).
+char(c,4235).
+char(m,4236).
+char(6,4237).
+char(2,4238).
+char(4,4239).
+char(4,4240).
+char(m,4241).
+char(5,4242).
+char(9,4243).
+char(6,4244).
+char(1,4245).
+char(p,4246).
+char(o,4247).
+char(o,4248).
+char(m,4249).
+char(o,4250).
+char(m,4251).
+char(o,4252).
+char(p,4253).
+char(o,4254).
+char(m,4255).
+char(5,4256).
+char(8,4257).
+char(0,4258).
+char(1,4259).
+char(p,4260).
+char(4,4261).
+char(1,4262).
+char(2,4263).
+char(6,4264).
+char(c,4265).
+char(c,4266).
+char(c,4267).
+char(p,4268).
+char(o,4269).
+char(o,4270).
+char(p,4271).
+char(6,4272).
+char(3,4273).
+char(5,4274).
+char(5,4275).
+char(m,4276).
+char(o,4277).
+char(5,4278).
+char(6,4279).
+char(4,4280).
+char(6,4281).
+char(c,4282).
+char(p,4283).
+char(4,4284).
+char(1,4285).
+char(1,4286).
+char(7,4287).
+char(p,4288).
+char(o,4289).
+char(4,4290).
+char(4,4291).
+char(4,4292).
+char(3,4293).
+char(p,4294).
+char(3,4295).
+char(0,4296).
+char(4,4297).
+char(6,4298).
+char(c,4299).
+char(p,4300).
+char(o,4301).
+char(m,4302).
+char(3,4303).
+char(9,4304).
+char(6,4305).
+char(1,4306).
+char(p,4307).
+char(o,4308).
+char(o,4309).
+char(2,4310).
+char(8,4311).
+char(0,4312).
+char(0,4313).
+char(c,4314).
+char(p,4315).
+char(7,4316).
+char(8,4317).
+char(5,4318).
+char(4,4319).
+char(c,4320).
+char(m,4321).
+char(9,4322).
+char(7,4323).
+char(8,4324).
+char(p,4325).
+char(5,4326).
+char(1,4327).
+char(7,4328).
+char(8,4329).
+char(c,4330).
+char(c,4331).
+char(m,4332).
+char(o,4333).
+char(3,4334).
+char(6,4335).
+char(9,4336).
+char(4,4337).
+char(c,4338).
+char(c,4339).
+char(m,4340).
+char(o,4341).
+char(m,4342).
+char(5,4343).
+char(6,4344).
+char(5,4345).
+char(9,4346).
+char(c,4347).
+char(m,4348).
+char(3,4349).
+char(0,4350).
+char(6,4351).
+char(1,4352).
+char(p,4353).
+char(o,4354).
+char(p,4355).
+char(2,4356).
+char(2,4357).
+char(4,4358).
+char(9,4359).
+char(m,4360).
+char(o,4361).
+char(p,4362).
+char(o,4363).
+char(1,4364).
+char(2,4365).
+char(4,4366).
+char(4,4367).
+char(c,4368).
+char(c,4369).
+char(c,4370).
+char(c,4371).
+char(p,4372).
+char(5,4373).
+char(5,4374).
+char(3,4375).
+char(m,4376).
+char(o,4377).
+char(m,4378).
+char(4,4379).
+char(0,4380).
+char(4,4381).
+char(2,4382).
+char(p,4383).
+char(1,4384).
+char(7,4385).
+char(6,4386).
+char(5,4387).
+char(m,4388).
+char(o,4389).
+char(p,4390).
+char(1,4391).
+char(2,4392).
+char(0,4393).
+char(1,4394).
+char(c,4395).
+char(c,4396).
+char(p,4397).
+char(8,4398).
+char(5,4399).
+char(8,4400).
+char(1,4401).
+char(m,4402).
+char(o,4403).
+char(p,4404).
+char(o,4405).
+char(p,4406).
+char(o,4407).
+char(o,4408).
+char(p,4409).
+char(7,4410).
+char(1,4411).
+char(7,4412).
+char(4,4413).
+char(m,4414).
+char(o,4415).
+char(p,4416).
+char(9,4417).
+char(6,4418).
+char(6,4419).
+char(5,4420).
+char(c,4421).
+char(c,4422).
+char(c,4423).
+char(p,4424).
+char(6,4425).
+char(5,4426).
+char(1,4427).
+char(5,4428).
+char(m,4429).
+char(o,4430).
+char(p,4431).
+char(o,4432).
+char(m,4433).
+char(4,4434).
+char(9,4435).
+char(9,4436).
+char(2,4437).
+char(m,4438).
+char(o,4439).
+char(p,4440).
+char(o,4441).
+char(m,4442).
+char(o,4443).
+char(p,4444).
+char(8,4445).
+char(3,4446).
+char(9,4447).
+char(p,4448).
+char(6,4449).
+char(9,4450).
+char(6,4451).
+char(5,4452).
+char(m,4453).
+char(7,4454).
+char(8,4455).
+char(8,4456).
+char(3,4457).
+char(c,4458).
+char(c,4459).
+char(c,4460).
+char(m,4461).
+char(o,4462).
+char(2,4463).
+char(5,4464).
+char(6,4465).
+char(9,4466).
+char(c,4467).
+char(c,4468).
+char(m,4469).
+char(o,4470).
+char(p,4471).
+char(o,4472).
+char(m,4473).
+char(1,4474).
+char(6,4475).
+char(2,4476).
+char(c,4477).
+char(m,4478).
+char(o,4479).
+char(p,4480).
+char(o,4481).
+char(m,4482).
+char(o,4483).
+char(o,4484).
+char(m,4485).
+char(o,4486).
+char(m,4487).
+char(o,4488).
+char(9,4489).
+char(3,4490).
+char(3,4491).
+char(0,4492).
+char(p,4493).
+char(3,4494).
+char(2,4495).
+char(9,4496).
+char(5,4497).
+char(c,4498).
+char(m,4499).
+char(o,4500).
+char(p,4501).
+char(6,4502).
+char(6,4503).
+char(5,4504).
+char(0,4505).
+char(m,4506).
+char(1,4507).
+char(8,4508).
+char(4,4509).
+char(1,4510).
+char(c,4511).
+char(p,4512).
+char(o,4513).
+char(o,4514).
+char(m,4515).
+char(o,4516).
+char(p,4517).
+char(o,4518).
+char(m,4519).
+char(o,4520).
+char(p,4521).
+char(o,4522).
+char(m,4523).
+char(o,4524).
+char(7,4525).
+char(4,4526).
+char(9,4527).
+char(9,4528).
+char(c,4529).
+char(c,4530).
+char(m,4531).
+char(2,4532).
+char(5,4533).
+char(2,4534).
+char(5,4535).
+char(c,4536).
+char(c,4537).
+char(m,4538).
+char(o,4539).
+char(5,4540).
+char(7,4541).
+char(5,4542).
+char(8,4543).
+char(c,4544).
+char(c,4545).
+char(c,4546).
+char(c,4547).
+char(p,4548).
+char(o,4549).
+char(m,4550).
+char(2,4551).
+char(4,4552).
+char(1,4553).
+char(9,4554).
+char(m,4555).
+char(o,4556).
+char(m,4557).
+char(3,4558).
+char(0,4559).
+char(8,4560).
+char(9,4561).
+char(p,4562).
+char(8,4563).
+char(9,4564).
+char(0,4565).
+char(3,4566).
+char(c,4567).
+char(m,4568).
+char(9,4569).
+char(7,4570).
+char(7,4571).
+char(4,4572).
+char(c,4573).
+char(m,4574).
+char(o,4575).
+char(4,4576).
+char(6,4577).
+char(8,4578).
+char(8,4579).
+char(m,4580).
+char(o,4581).
+char(p,4582).
+char(6,4583).
+char(5,4584).
+char(6,4585).
+char(5,4586).
+char(p,4587).
+char(o,4588).
+char(p,4589).
+char(3,4590).
+char(3,4591).
+char(8,4592).
+char(9,4593).
+char(c,4594).
+char(c,4595).
+char(p,4596).
+char(o,4597).
+char(o,4598).
+char(p,4599).
+char(5,4600).
+char(4,4601).
+char(8,4602).
+char(m,4603).
+char(8,4604).
+char(8,4605).
+char(7,4606).
+char(0,4607).
+char(m,4608).
+char(o,4609).
+char(p,4610).
+char(9,4611).
+char(2,4612).
+char(7,4613).
+char(2,4614).
+char(p,4615).
+char(4,4616).
+char(8,4617).
+char(4,4618).
+char(5,4619).
+char(m,4620).
+char(5,4621).
+char(6,4622).
+char(4,4623).
+char(2,4624).
+char(p,4625).
+char(2,4626).
+char(8,4627).
+char(0,4628).
+char(8,4629).
+char(c,4630).
+char(m,4631).
+char(o,4632).
+char(m,4633).
+char(o,4634).
+char(6,4635).
+char(6,4636).
+char(1,4637).
+char(3,4638).
+char(c,4639).
+char(c,4640).
+char(m,4641).
+char(9,4642).
+char(6,4643).
+char(9,4644).
+char(8,4645).
+char(m,4646).
+char(7,4647).
+char(8,4648).
+char(3,4649).
+char(3,4650).
+char(p,4651).
+char(5,4652).
+char(5,4653).
+char(3,4654).
+char(9,4655).
+char(p,4656).
+char(o,4657).
+char(2,4658).
+char(5,4659).
+char(0,4660).
+char(m,4661).
+char(o,4662).
+char(p,4663).
+char(o,4664).
+char(m,4665).
+char(o,4666).
+char(m,4667).
+char(o,4668).
+char(p,4669).
+char(5,4670).
+char(2,4671).
+char(9,4672).
+char(3,4673).
+char(m,4674).
+char(o,4675).
+char(p,4676).
+char(o,4677).
+char(9,4678).
+char(3,4679).
+char(2,4680).
+char(8,4681).
+char(c,4682).
+char(c,4683).
+char(m,4684).
+char(7,4685).
+char(9,4686).
+char(3,4687).
+char(3,4688).
+char(m,4689).
+char(8,4690).
+char(2,4691).
+char(1,4692).
+char(1,4693).
+char(c,4694).
+char(p,4695).
+char(o,4696).
+char(p,4697).
+char(8,4698).
+char(2,4699).
+char(5,4700).
+char(6,4701).
+char(c,4702).
+char(p,4703).
+char(o,4704).
+char(m,4705).
+char(o,4706).
+char(o,4707).
+char(p,4708).
+char(3,4709).
+char(2,4710).
+char(2,4711).
+char(p,4712).
+char(7,4713).
+char(6,4714).
+char(4,4715).
+char(9,4716).
+char(m,4717).
+char(4,4718).
+char(1,4719).
+char(4,4720).
+char(9,4721).
+char(p,4722).
+char(o,4723).
+char(p,4724).
+char(6,4725).
+char(7,4726).
+char(1,4727).
+char(5,4728).
+char(c,4729).
+char(m,4730).
+char(o,4731).
+char(5,4732).
+char(8,4733).
+char(3,4734).
+char(9,4735).
+char(c,4736).
+char(m,4737).
+char(1,4738).
+char(3,4739).
+char(1,4740).
+char(9,4741).
+char(m,4742).
+char(2,4743).
+char(2,4744).
+char(5,4745).
+char(3,4746).
+char(c,4747).
+char(p,4748).
+char(4,4749).
+char(7,4750).
+char(7,4751).
+char(0,4752).
+char(c,4753).
+char(c,4754).
+char(m,4755).
+char(o,4756).
+char(m,4757).
+char(7,4758).
+char(9,4759).
+char(6,4760).
+char(0,4761).
+char(p,4762).
+char(2,4763).
+char(1,4764).
+char(5,4765).
+char(9,4766).
+char(p,4767).
+char(o,4768).
+char(p,4769).
+char(8,4770).
+char(9,4771).
+char(5,4772).
+char(2,4773).
+char(p,4774).
+char(7,4775).
+char(9,4776).
+char(1,4777).
+char(5,4778).
+char(c,4779).
+char(m,4780).
+char(2,4781).
+char(9,4782).
+char(7,4783).
+char(2,4784).
+char(c,4785).
+char(p,4786).
+char(2,4787).
+char(9,4788).
+char(7,4789).
+char(0,4790).
+char(c,4791).
+char(p,4792).
+char(9,4793).
+char(7,4794).
+char(9,4795).
+char(4,4796).
+char(c,4797).
+char(c,4798).
+char(c,4799).
+char(c,4800).
+char(m,4801).
+char(o,4802).
+char(p,4803).
+char(o,4804).
+char(p,4805).
+char(o,4806).
+char(6,4807).
+char(6,4808).
+char(2,4809).
+char(4,4810).
+char(m,4811).
+char(o,4812).
+char(o,4813).
+char(p,4814).
+char(2,4815).
+char(9,4816).
+char(8,4817).
+char(2,4818).
+char(p,4819).
+char(o,4820).
+char(3,4821).
+char(8,4822).
+char(7,4823).
+char(6,4824).
+char(c,4825).
+char(c,4826).
+char(m,4827).
+char(6,4828).
+char(1,4829).
+char(1,4830).
+char(1,4831).
+char(p,4832).
+char(o,4833).
+char(p,4834).
+char(6,4835).
+char(4,4836).
+char(1,4837).
+char(m,4838).
+char(o,4839).
+char(o,4840).
+char(p,4841).
+char(6,4842).
+char(0,4843).
+char(9,4844).
+char(2,4845).
+char(c,4846).
+char(c,4847).
+char(c,4848).
+char(c,4849).
+char(p,4850).
+char(9,4851).
+char(3,4852).
+char(8,4853).
+char(8,4854).
+char(m,4855).
+char(o,4856).
+char(m,4857).
+char(2,4858).
+char(8,4859).
+char(5,4860).
+char(5,4861).
+char(m,4862).
+char(6,4863).
+char(6,4864).
+char(0,4865).
+char(7,4866).
+char(p,4867).
+char(5,4868).
+char(5,4869).
+char(5,4870).
+char(4,4871).
+char(c,4872).
+char(p,4873).
+char(o,4874).
+char(3,4875).
+char(5,4876).
+char(5,4877).
+char(9,4878).
+char(m,4879).
+char(o,4880).
+char(p,4881).
+char(5,4882).
+char(5,4883).
+char(8,4884).
+char(4,4885).
+char(c,4886).
+char(c,4887).
+char(c,4888).
+char(c,4889).
+char(c,4890).
+char(c,4891).
+char(c,4892).
+char(m,4893).
+char(9,4894).
+char(5,4895).
+char(2,4896).
+char(3,4897).
+char(p,4898).
+char(7,4899).
+char(1,4900).
+char(3,4901).
+char(5,4902).
+char(m,4903).
+char(o,4904).
+char(o,4905).
+char(m,4906).
+char(8,4907).
+char(4,4908).
+char(3,4909).
+char(2,4910).
+char(m,4911).
+char(o,4912).
+char(m,4913).
+char(o,4914).
+char(p,4915).
+char(o,4916).
+char(m,4917).
+char(o,4918).
+char(o,4919).
+char(p,4920).
+char(o,4921).
+char(m,4922).
+char(o,4923).
+char(8,4924).
+char(9,4925).
+char(5,4926).
+char(0,4927).
+char(c,4928).
+char(c,4929).
+char(m,4930).
+char(8,4931).
+char(7,4932).
+char(8,4933).
+char(0,4934).
+char(c,4935).
+char(p,4936).
+char(o,4937).
+char(m,4938).
+char(o,4939).
+char(m,4940).
+char(6,4941).
+char(3,4942).
+char(5,4943).
+char(4,4944).
+char(c,4945).
+char(c,4946).
+char(p,4947).
+char(o,4948).
+char(o,4949).
+char(m,4950).
+char(4,4951).
+char(9,4952).
+char(2,4953).
+char(9,4954).
+char(c,4955).
+char(c,4956).
+char(p,4957).
+char(o,4958).
+char(2,4959).
+char(6,4960).
+char(4,4961).
+char(6,4962).
+char(p,4963).
+char(3,4964).
+char(0,4965).
+char(6,4966).
+char(c,4967).
+char(c,4968).
+char(c,4969).
+char(c,4970).
+char(p,4971).
+char(o,4972).
+char(8,4973).
+char(0,4974).
+char(6,4975).
+char(2,4976).
+char(m,4977).
+char(1,4978).
+char(8,4979).
+char(2,4980).
+char(4,4981).
+char(c,4982).
+char(p,4983).
+char(2,4984).
+char(4,4985).
+char(1,4986).
+char(8,4987).
+char(p,4988).
+char(o,4989).
+char(m,4990).
+char(o,4991).
+char(7,4992).
+char(0,4993).
+char(4,4994).
+char(7,4995).
+char(c,4996).
+char(c,4997).
+char(c,4998).
+char(m,4999).
+char(8,5000).
+char(6,5001).
+char(7,5002).
+char(9,5003).
+char(c,5004).
+char(c,5005).
+char(c,5006).
+char(c,5007).
+char(p,5008).
+char(8,5009).
+char(2,5010).
+char(8,5011).
+char(4,5012).
+char(p,5013).
+char(o,5014).
+char(p,5015).
+char(o,5016).
+char(m,5017).
+char(9,5018).
+char(6,5019).
+char(4,5020).
+char(0,5021).
+char(m,5022).
+char(o,5023).
+char(1,5024).
+char(3,5025).
+char(6,5026).
+char(9,5027).
+char(p,5028).
+char(4,5029).
+char(3,5030).
+char(0,5031).
+char(2,5032).
+char(c,5033).
+char(m,5034).
+char(o,5035).
+char(p,5036).
+char(o,5037).
+char(m,5038).
+char(o,5039).
+char(m,5040).
+char(4,5041).
+char(3,5042).
+char(0,5043).
+char(1,5044).
+char(c,5045).
+char(c,5046).
+char(c,5047).
+char(p,5048).
+char(o,5049).
+char(p,5050).
+char(o,5051).
+char(o,5052).
+char(m,5053).
+char(o,5054).
+char(7,5055).
+char(2,5056).
+char(5,5057).
+char(4,5058).
+char(m,5059).
+char(o,5060).
+char(m,5061).
+char(o,5062).
+char(8,5063).
+char(5,5064).
+char(7,5065).
+char(3,5066).
+char(c,5067).
+char(c,5068).
+char(m,5069).
+char(5,5070).
+char(1,5071).
+char(3,5072).
+char(5,5073).
+char(c,5074).
+char(p,5075).
+char(o,5076).
+char(p,5077).
+char(o,5078).
+char(p,5079).
+char(o,5080).
+char(p,5081).
+char(o,5082).
+char(7,5083).
+char(1,5084).
+char(2,5085).
+char(7,5086).
+char(m,5087).
+char(o,5088).
+char(m,5089).
+char(3,5090).
+char(4,5091).
+char(9,5092).
+char(1,5093).
+char(c,5094).
+char(m,5095).
+char(1,5096).
+char(0,5097).
+char(c,5098).
+char(m,5099).
+char(o,5100).
+char(p,5101).
+char(9,5102).
+char(5,5103).
+char(1,5104).
+char(8,5105).
+char(c,5106).
+char(c,5107).
+char(c,5108).
+char(m,5109).
+char(o,5110).
+char(7,5111).
+char(8,5112).
+char(8,5113).
+char(6,5114).
+char(c,5115).
+char(p,5116).
+char(4,5117).
+char(3,5118).
+char(7,5119).
+char(3,5120).
+char(p,5121).
+char(9,5122).
+char(9,5123).
+char(3,5124).
+char(4,5125).
+char(m,5126).
+char(2,5127).
+char(1,5128).
+char(5,5129).
+char(0,5130).
+char(p,5131).
+char(o,5132).
+char(p,5133).
+char(1,5134).
+char(7,5135).
+char(4,5136).
+char(6,5137).
+char(c,5138).
+char(p,5139).
+char(o,5140).
+char(p,5141).
+char(1,5142).
+char(8,5143).
+char(4,5144).
+char(5,5145).
+char(p,5146).
+char(9,5147).
+char(3,5148).
+char(6,5149).
+char(9,5150).
+char(c,5151).
+char(m,5152).
+char(4,5153).
+char(3,5154).
+char(3,5155).
+char(5,5156).
+char(m,5157).
+char(6,5158).
+char(8,5159).
+char(4,5160).
+char(7,5161).
+char(c,5162).
+char(m,5163).
+char(o,5164).
+char(o,5165).
+char(m,5166).
+char(o,5167).
+char(o,5168).
+char(m,5169).
+char(3,5170).
+char(0,5171).
+char(4,5172).
+char(5,5173).
+char(p,5174).
+char(o,5175).
+char(m,5176).
+char(6,5177).
+char(9,5178).
+char(3,5179).
+char(6,5180).
+char(c,5181).
+char(m,5182).
+char(o,5183).
+char(o,5184).
+char(m,5185).
+char(o,5186).
+char(p,5187).
+char(o,5188).
+char(p,5189).
+char(3,5190).
+char(1,5191).
+char(8,5192).
+char(c,5193).
+char(c,5194).
+char(p,5195).
+char(2,5196).
+char(8,5197).
+char(5,5198).
+char(4,5199).
+char(m,5200).
+char(o,5201).
+char(p,5202).
+char(5,5203).
+char(0,5204).
+char(1,5205).
+char(c,5206).
+char(m,5207).
+char(4,5208).
+char(1,5209).
+char(2,5210).
+char(9,5211).
+char(c,5212).
+char(p,5213).
+char(o,5214).
+char(m,5215).
+char(o,5216).
+char(p,5217).
+char(7,5218).
+char(7,5219).
+char(1,5220).
+char(4,5221).
+char(m,5222).
+char(o,5223).
+char(m,5224).
+char(3,5225).
+char(7,5226).
+char(4,5227).
+char(9,5228).
+char(c,5229).
+char(m,5230).
+char(o,5231).
+char(9,5232).
+char(5,5233).
+char(6,5234).
+char(8,5235).
+char(c,5236).
+char(p,5237).
+char(o,5238).
+char(p,5239).
+char(o,5240).
+char(p,5241).
+char(o,5242).
+char(p,5243).
+char(o,5244).
+char(m,5245).
+char(1,5246).
+char(7,5247).
+char(1,5248).
+char(c,5249).
+char(p,5250).
+char(o,5251).
+char(m,5252).
+char(o,5253).
+char(6,5254).
+char(9,5255).
+char(8,5256).
+char(4,5257).
+char(c,5258).
+char(p,5259).
+char(o,5260).
+char(p,5261).
+char(o,5262).
+char(m,5263).
+char(3,5264).
+char(9,5265).
+char(3,5266).
+char(5,5267).
+char(p,5268).
+char(o,5269).
+char(8,5270).
+char(7,5271).
+char(0,5272).
+char(0,5273).
+char(m,5274).
+char(9,5275).
+char(6,5276).
+char(6,5277).
+char(8,5278).
+char(c,5279).
+char(c,5280).
+char(p,5281).
+char(o,5282).
+char(m,5283).
+char(o,5284).
+char(m,5285).
+char(9,5286).
+char(7,5287).
+char(4,5288).
+char(4,5289).
+char(m,5290).
+char(5,5291).
+char(0,5292).
+char(8,5293).
+char(m,5294).
+char(3,5295).
+char(9,5296).
+char(0,5297).
+char(c,5298).
+char(p,5299).
+char(o,5300).
+char(o,5301).
+char(p,5302).
+char(5,5303).
+char(8,5304).
+char(6,5305).
+char(6,5306).
+char(m,5307).
+char(9,5308).
+char(1,5309).
+char(8,5310).
+char(4,5311).
+char(p,5312).
+char(o,5313).
+char(p,5314).
+char(o,5315).
+char(m,5316).
+char(o,5317).
+char(p,5318).
+char(o,5319).
+char(m,5320).
+char(o,5321).
+char(p,5322).
+char(o,5323).
+char(p,5324).
+char(5,5325).
+char(6,5326).
+char(0,5327).
+char(2,5328).
+char(m,5329).
+char(8,5330).
+char(5,5331).
+char(0,5332).
+char(8,5333).
+char(c,5334).
+char(c,5335).
+char(m,5336).
+char(2,5337).
+char(3,5338).
+char(7,5339).
+char(8,5340).
+char(c,5341).
+char(p,5342).
+char(9,5343).
+char(2,5344).
+char(0,5345).
+char(5,5346).
+char(p,5347).
+char(8,5348).
+char(3,5349).
+char(1,5350).
+char(4,5351).
+char(c,5352).
+char(m,5353).
+char(3,5354).
+char(6,5355).
+char(2,5356).
+char(2,5357).
+char(p,5358).
+char(o,5359).
+char(p,5360).
+char(3,5361).
+char(2,5362).
+char(8,5363).
+char(7,5364).
+char(c,5365).
+char(c,5366).
+char(c,5367).
+char(c,5368).
+char(p,5369).
+char(o,5370).
+char(m,5371).
+char(2,5372).
+char(9,5373).
+char(9,5374).
+char(4,5375).
+char(p,5376).
+char(1,5377).
+char(4,5378).
+char(3,5379).
+char(9,5380).
+char(c,5381).
+char(c,5382).
+char(m,5383).
+char(o,5384).
+char(o,5385).
+char(3,5386).
+char(1,5387).
+char(9,5388).
+char(6,5389).
+char(p,5390).
+char(o,5391).
+char(m,5392).
+char(5,5393).
+char(9,5394).
+char(0,5395).
+char(7,5396).
+char(c,5397).
+char(c,5398).
+char(p,5399).
+char(o,5400).
+char(o,5401).
+char(o,5402).
+char(m,5403).
+char(9,5404).
+char(5,5405).
+char(0,5406).
+char(c,5407).
+char(c,5408).
+char(c,5409).
+char(m,5410).
+char(7,5411).
+char(6,5412).
+char(8,5413).
+char(9,5414).
+char(m,5415).
+char(o,5416).
+char(2,5417).
+char(4,5418).
+char(4,5419).
+char(6,5420).
+char(p,5421).
+char(2,5422).
+char(2,5423).
+char(8,5424).
+char(4,5425).
+char(m,5426).
+char(o,5427).
+char(p,5428).
+char(8,5429).
+char(8,5430).
+char(2,5431).
+char(7,5432).
+char(p,5433).
+char(3,5434).
+char(7,5435).
+char(1,5436).
+char(2,5437).
+char(p,5438).
+char(o,5439).
+char(m,5440).
+char(o,5441).
+char(7,5442).
+char(7,5443).
+char(0,5444).
+char(9,5445).
+char(c,5446).
+char(p,5447).
+char(o,5448).
+char(p,5449).
+char(o,5450).
+char(p,5451).
+char(o,5452).
+char(p,5453).
+char(7,5454).
+char(5,5455).
+char(2,5456).
+char(3,5457).
+char(m,5458).
+char(1,5459).
+char(1,5460).
+char(p,5461).
+char(o,5462).
+char(o,5463).
+char(o,5464).
+char(m,5465).
+char(o,5466).
+char(m,5467).
+char(3,5468).
+char(9,5469).
+char(1,5470).
+char(9,5471).
+char(p,5472).
+char(o,5473).
+char(p,5474).
+char(9,5475).
+char(9,5476).
+char(8,5477).
+char(9,5478).
+char(p,5479).
+char(o,5480).
+char(m,5481).
+char(2,5482).
+char(3,5483).
+char(8,5484).
+char(6,5485).
+char(c,5486).
+char(m,5487).
+char(4,5488).
+char(1,5489).
+char(3,5490).
+char(c,5491).
+char(m,5492).
+char(o,5493).
+char(p,5494).
+char(5,5495).
+char(9,5496).
+char(2,5497).
+char(5,5498).
+char(c,5499).
+char(c,5500).
+char(c,5501).
+char(p,5502).
+char(3,5503).
+char(9,5504).
+char(6,5505).
+char(5,5506).
+char(c,5507).
+char(c,5508).
+char(m,5509).
+char(2,5510).
+char(9,5511).
+char(3,5512).
+char(7,5513).
+char(c,5514).
+char(p,5515).
+char(o,5516).
+char(p,5517).
+char(7,5518).
+char(8,5519).
+char(8,5520).
+char(8,5521).
+char(c,5522).
+char(c,5523).
+char(m,5524).
+char(o,5525).
+char(m,5526).
+char(o,5527).
+char(m,5528).
+char(o,5529).
+char(m,5530).
+char(4,5531).
+char(0,5532).
+char(7,5533).
+char(3,5534).
+char(m,5535).
+char(o,5536).
+char(m,5537).
+char(6,5538).
+char(9,5539).
+char(0,5540).
+char(5,5541).
+char(c,5542).
+char(p,5543).
+char(7,5544).
+char(5,5545).
+char(1,5546).
+char(8,5547).
+char(p,5548).
+char(o,5549).
+char(m,5550).
+char(o,5551).
+char(p,5552).
+char(1,5553).
+char(1,5554).
+char(4,5555).
+char(6,5556).
+char(c,5557).
+char(c,5558).
+char(c,5559).
+char(p,5560).
+char(2,5561).
+char(6,5562).
+char(6,5563).
+char(c,5564).
+char(m,5565).
+char(9,5566).
+char(6,5567).
+char(2,5568).
+char(8,5569).
+char(p,5570).
+char(o,5571).
+char(p,5572).
+char(2,5573).
+char(7,5574).
+char(8,5575).
+char(4,5576).
+char(p,5577).
+char(o,5578).
+char(p,5579).
+char(o,5580).
+char(p,5581).
+char(1,5582).
+char(9,5583).
+char(2,5584).
+char(1,5585).
+char(m,5586).
+char(o,5587).
+char(o,5588).
+char(p,5589).
+char(o,5590).
+char(m,5591).
+char(4,5592).
+char(6,5593).
+char(7,5594).
+char(c,5595).
+char(c,5596).
+char(c,5597).
+char(m,5598).
+char(2,5599).
+char(2,5600).
+char(5,5601).
+char(9,5602).
+char(m,5603).
+char(6,5604).
+char(1,5605).
+char(5,5606).
+char(4,5607).
+char(c,5608).
+char(p,5609).
+char(1,5610).
+char(3,5611).
+char(4,5612).
+char(0,5613).
+char(c,5614).
+char(m,5615).
+char(o,5616).
+char(p,5617).
+char(5,5618).
+char(3,5619).
+char(2,5620).
+char(4,5621).
+char(m,5622).
+char(o,5623).
+char(p,5624).
+char(5,5625).
+char(8,5626).
+char(5,5627).
+char(0,5628).
+char(m,5629).
+char(o,5630).
+char(o,5631).
+char(p,5632).
+char(o,5633).
+char(m,5634).
+char(5,5635).
+char(1,5636).
+char(2,5637).
+char(2,5638).
+char(c,5639).
+char(c,5640).
+char(m,5641).
+char(o,5642).
+char(p,5643).
+char(o,5644).
+char(5,5645).
+char(3,5646).
+char(2,5647).
+char(1,5648).
+char(c,5649).
+char(m,5650).
+char(o,5651).
+char(p,5652).
+char(o,5653).
+char(m,5654).
+char(o,5655).
+char(p,5656).
+char(o,5657).
+char(m,5658).
+char(3,5659).
+char(2,5660).
+char(0,5661).
+char(0,5662).
+char(p,5663).
+char(1,5664).
+char(7,5665).
+char(7,5666).
+char(7,5667).
+char(m,5668).
+char(o,5669).
+char(p,5670).
+char(9,5671).
+char(9,5672).
+char(6,5673).
+char(3,5674).
+char(p,5675).
+char(o,5676).
+char(p,5677).
+char(o,5678).
+char(m,5679).
+char(1,5680).
+char(3,5681).
+char(4,5682).
+char(0,5683).
+char(c,5684).
+char(m,5685).
+char(3,5686).
+char(7,5687).
+char(7,5688).
+char(3,5689).
+char(c,5690).
+char(p,5691).
+char(o,5692).
+char(p,5693).
+char(o,5694).
+char(o,5695).
+char(8,5696).
+char(3,5697).
+char(2,5698).
+char(4,5699).
+char(p,5700).
+char(o,5701).
+char(p,5702).
+char(7,5703).
+char(8,5704).
+char(9,5705).
+char(0,5706).
+char(c,5707).
+char(c,5708).
+char(m,5709).
+char(4,5710).
+char(7,5711).
+char(4,5712).
+char(3,5713).
+char(c,5714).
+char(c,5715).
+char(c,5716).
+char(p,5717).
+char(o,5718).
+char(8,5719).
+char(1,5720).
+char(7,5721).
+char(5,5722).
+char(c,5723).
+char(c,5724).
+char(m,5725).
+char(4,5726).
+char(4,5727).
+char(3,5728).
+char(1,5729).
+char(m,5730).
+char(o,5731).
+char(p,5732).
+char(1,5733).
+char(3,5734).
+char(2,5735).
+char(2,5736).
+char(c,5737).
+char(m,5738).
+char(o,5739).
+char(2,5740).
+char(8,5741).
+char(3,5742).
+char(5,5743).
+char(c,5744).
+char(c,5745).
+char(p,5746).
+char(o,5747).
+char(m,5748).
+char(5,5749).
+char(5,5750).
+char(8,5751).
+char(7,5752).
+char(c,5753).
+char(p,5754).
+char(o,5755).
+char(m,5756).
+char(o,5757).
+char(m,5758).
+char(o,5759).
+char(p,5760).
+char(5,5761).
+char(7,5762).
+char(2,5763).
+char(4,5764).
+char(c,5765).
+char(m,5766).
+char(7,5767).
+char(5,5768).
+char(4,5769).
+char(0,5770).
+char(p,5771).
+char(o,5772).
+char(m,5773).
+char(o,5774).
+char(m,5775).
+char(5,5776).
+char(5,5777).
+char(7,5778).
+char(9,5779).
+char(c,5780).
+char(c,5781).
+char(p,5782).
+char(o,5783).
+char(o,5784).
+char(m,5785).
+char(o,5786).
+char(p,5787).
+char(o,5788).
+char(m,5789).
+char(o,5790).
+char(m,5791).
+char(5,5792).
+char(4,5793).
+char(3,5794).
+char(3,5795).
+char(c,5796).
+char(p,5797).
+char(7,5798).
+char(7,5799).
+char(0,5800).
+char(7,5801).
+char(c,5802).
+char(p,5803).
+char(7,5804).
+char(0,5805).
+char(4,5806).
+char(4,5807).
+char(m,5808).
+char(o,5809).
+char(8,5810).
+char(8,5811).
+char(3,5812).
+char(p,5813).
+char(1,5814).
+char(9,5815).
+char(4,5816).
+char(6,5817).
+char(c,5818).
+char(p,5819).
+char(o,5820).
+char(m,5821).
+char(o,5822).
+char(m,5823).
+char(3,5824).
+char(4,5825).
+char(4,5826).
+char(c,5827).
+char(c,5828).
+char(c,5829).
+char(c,5830).
+char(c,5831).
+char(c,5832).
+char(c,5833).
+char(m,5834).
+char(o,5835).
+char(p,5836).
+char(o,5837).
+char(p,5838).
+char(o,5839).
+char(o,5840).
+char(o,5841).
+char(p,5842).
+char(3,5843).
+char(4,5844).
+char(7,5845).
+char(2,5846).
+char(c,5847).
+char(c,5848).
+char(m,5849).
+char(o,5850).
+char(p,5851).
+char(o,5852).
+char(m,5853).
+char(o,5854).
+char(2,5855).
+char(3,5856).
+char(3,5857).
+char(3,5858).
+char(c,5859).
+char(c,5860).
+char(c,5861).
+char(p,5862).
+char(5,5863).
+char(1,5864).
+char(7,5865).
+char(9,5866).
+char(p,5867).
+char(o,5868).
+char(m,5869).
+char(o,5870).
+char(o,5871).
+char(m,5872).
+char(4,5873).
+char(1,5874).
+char(8,5875).
+char(4,5876).
+char(p,5877).
+char(3,5878).
+char(1,5879).
+char(5,5880).
+char(9,5881).
+char(m,5882).
+char(o,5883).
+char(m,5884).
+char(o,5885).
+char(p,5886).
+char(o,5887).
+char(m,5888).
+char(o,5889).
+char(m,5890).
+char(8,5891).
+char(2,5892).
+char(1,5893).
+char(6,5894).
+char(m,5895).
+char(7,5896).
+char(5,5897).
+char(3,5898).
+char(0,5899).
+char(m,5900).
+char(o,5901).
+char(m,5902).
+char(o,5903).
+char(m,5904).
+char(o,5905).
+char(o,5906).
+char(p,5907).
+char(7,5908).
+char(4,5909).
+char(9,5910).
+char(6,5911).
+char(p,5912).
+char(o,5913).
+char(7,5914).
+char(5,5915).
+char(5,5916).
+char(m,5917).
+char(9,5918).
+char(1,5919).
+char(6,5920).
+char(5,5921).
+char(m,5922).
+char(o,5923).
+char(m,5924).
+char(o,5925).
+char(o,5926).
+char(8,5927).
+char(2,5928).
+char(9,5929).
+char(4,5930).
+char(p,5931).
+char(o,5932).
+char(p,5933).
+char(9,5934).
+char(4,5935).
+char(3,5936).
+char(3,5937).
+char(m,5938).
+char(o,5939).
+char(m,5940).
+char(9,5941).
+char(2,5942).
+char(9,5943).
+char(5,5944).
+char(p,5945).
+char(o,5946).
+char(p,5947).
+char(o,5948).
+char(o,5949).
+char(o,5950).
+char(m,5951).
+char(6,5952).
+char(8,5953).
+char(5,5954).
+char(2,5955).
+char(c,5956).
+char(m,5957).
+char(1,5958).
+char(5,5959).
+char(0,5960).
+char(5,5961).
+char(c,5962).
+char(m,5963).
+char(6,5964).
+char(0,5965).
+char(5,5966).
+char(4,5967).
+char(m,5968).
+char(o,5969).
+char(o,5970).
+char(6,5971).
+char(1,5972).
+char(5,5973).
+char(9,5974).
+char(m,5975).
+char(1,5976).
+char(8,5977).
+char(p,5978).
+char(2,5979).
+char(5,5980).
+char(0,5981).
+char(9,5982).
+char(p,5983).
+char(o,5984).
+char(o,5985).
+char(p,5986).
+char(o,5987).
+char(m,5988).
+char(7,5989).
+char(0,5990).
+char(2,5991).
+char(m,5992).
+char(o,5993).
+char(m,5994).
+char(o,5995).
+char(p,5996).
+char(o,5997).
+char(p,5998).
+char(6,5999).
+char(8,6000).
+char(2,6001).
+char(7,6002).
+char(c,6003).
+char(c,6004).
+char(c,6005).
+char(p,6006).
+char(4,6007).
+char(1,6008).
+char(3,6009).
+char(0,6010).
+char(c,6011).
+char(c,6012).
+char(c,6013).
+char(p,6014).
+char(5,6015).
+char(8,6016).
+char(3,6017).
+char(8,6018).
+char(c,6019).
+char(c,6020).
+char(c,6021).
+char(c,6022).
+char(p,6023).
+char(o,6024).
+char(1,6025).
+char(3,6026).
+char(1,6027).
+char(9,6028).
+char(m,6029).
+char(o,6030).
+char(m,6031).
+char(o,6032).
+char(p,6033).
+char(5,6034).
+char(9,6035).
+char(8,6036).
+char(p,6037).
+char(8,6038).
+char(1,6039).
+char(3,6040).
+char(0,6041).
+char(c,6042).
+char(p,6043).
+char(1,6044).
+char(6,6045).
+char(5,6046).
+char(4,6047).
+char(c,6048).
+char(m,6049).
+char(7,6050).
+char(1,6051).
+char(4,6052).
+char(5,6053).
+char(m,6054).
+char(5,6055).
+char(4,6056).
+char(1,6057).
+char(0,6058).
+char(p,6059).
+char(o,6060).
+char(o,6061).
+char(9,6062).
+char(3,6063).
+char(8,6064).
+char(6,6065).
+char(c,6066).
+char(m,6067).
+char(o,6068).
+char(p,6069).
+char(9,6070).
+char(5,6071).
+char(0,6072).
+char(7,6073).
+char(m,6074).
+char(1,6075).
+char(9,6076).
+char(9,6077).
+char(7,6078).
+char(c,6079).
+char(m,6080).
+char(5,6081).
+char(1,6082).
+char(8,6083).
+char(c,6084).
+char(p,6085).
+char(o,6086).
+char(m,6087).
+char(3,6088).
+char(3,6089).
+char(7,6090).
+char(6,6091).
+char(c,6092).
+char(p,6093).
+char(o,6094).
+char(p,6095).
+char(7,6096).
+char(9,6097).
+char(8,6098).
+char(0,6099).
+char(c,6100).
+char(c,6101).
+char(c,6102).
+char(c,6103).
+char(c,6104).
+char(p,6105).
+char(5,6106).
+char(9,6107).
+char(5,6108).
+char(0,6109).
+char(c,6110).
+char(c,6111).
+char(m,6112).
+char(8,6113).
+char(9,6114).
+char(4,6115).
+char(5,6116).
+char(c,6117).
+char(c,6118).
+char(m,6119).
+char(6,6120).
+char(3,6121).
+char(6,6122).
+char(0,6123).
+char(c,6124).
+char(c,6125).
+char(p,6126).
+char(7,6127).
+char(4,6128).
+char(4,6129).
+char(0,6130).
+char(c,6131).
+char(c,6132).
+char(p,6133).
+char(o,6134).
+char(p,6135).
+char(9,6136).
+char(3,6137).
+char(0,6138).
+char(1,6139).
+char(m,6140).
+char(6,6141).
+char(2,6142).
+char(6,6143).
+char(6,6144).
+char(m,6145).
+char(o,6146).
+char(5,6147).
+char(4,6148).
+char(6,6149).
+char(0,6150).
+char(c,6151).
+char(p,6152).
+char(o,6153).
+char(m,6154).
+char(8,6155).
+char(2,6156).
+char(0,6157).
+char(5,6158).
+char(c,6159).
+char(m,6160).
+char(2,6161).
+char(4,6162).
+char(4,6163).
+char(c,6164).
+char(m,6165).
+char(o,6166).
+char(p,6167).
+char(o,6168).
+char(o,6169).
+char(m,6170).
+char(o,6171).
+char(m,6172).
+char(2,6173).
+char(8,6174).
+char(9,6175).
+char(p,6176).
+char(o,6177).
+char(m,6178).
+char(o,6179).
+char(p,6180).
+char(5,6181).
+char(2,6182).
+char(8,6183).
+char(1,6184).
+char(p,6185).
+char(1,6186).
+char(5,6187).
+char(6,6188).
+char(2,6189).
+char(c,6190).
+char(m,6191).
+char(2,6192).
+char(1,6193).
+char(8,6194).
+char(8,6195).
+char(p,6196).
+char(o,6197).
+char(p,6198).
+char(3,6199).
+char(1,6200).
+char(4,6201).
+char(2,6202).
+char(p,6203).
+char(o,6204).
+char(2,6205).
+char(0,6206).
+char(0,6207).
+char(0,6208).
+char(p,6209).
+char(o,6210).
+char(2,6211).
+char(7,6212).
+char(8,6213).
+char(3,6214).
+char(m,6215).
+char(9,6216).
+char(0,6217).
+char(6,6218).
+char(9,6219).
+char(m,6220).
+char(o,6221).
+char(m,6222).
+char(o,6223).
+char(m,6224).
+char(8,6225).
+char(6,6226).
+char(6,6227).
+char(6,6228).
+char(c,6229).
+char(p,6230).
+char(5,6231).
+char(7,6232).
+char(1,6233).
+char(2,6234).
+char(p,6235).
+char(o,6236).
+char(m,6237).
+char(o,6238).
+char(4,6239).
+char(4,6240).
+char(1,6241).
+char(c,6242).
+char(c,6243).
+char(p,6244).
+char(o,6245).
+char(o,6246).
+char(p,6247).
+char(6,6248).
+char(5,6249).
+char(3,6250).
+char(5,6251).
+char(p,6252).
+char(9,6253).
+char(3,6254).
+char(7,6255).
+char(4,6256).
+char(m,6257).
+char(2,6258).
+char(5,6259).
+char(0,6260).
+char(7,6261).
+char(c,6262).
+char(c,6263).
+char(c,6264).
+char(c,6265).
+char(c,6266).
+char(c,6267).
+char(p,6268).
+char(3,6269).
+char(9,6270).
+char(4,6271).
+char(5,6272).
+char(m,6273).
+char(3,6274).
+char(2,6275).
+char(5,6276).
+char(1,6277).
+char(m,6278).
+char(o,6279).
+char(m,6280).
+char(8,6281).
+char(0,6282).
+char(7,6283).
+char(1,6284).
+char(c,6285).
+char(c,6286).
+char(c,6287).
+char(c,6288).
+char(m,6289).
+char(6,6290).
+char(4,6291).
+char(6,6292).
+char(4,6293).
+char(m,6294).
+char(o,6295).
+char(m,6296).
+char(o,6297).
+char(o,6298).
+char(m,6299).
+char(o,6300).
+char(p,6301).
+char(4,6302).
+char(4,6303).
+char(1,6304).
+char(8,6305).
+char(p,6306).
+char(o,6307).
+char(5,6308).
+char(1,6309).
+char(8,6310).
+char(6,6311).
+char(m,6312).
+char(o,6313).
+char(m,6314).
+char(o,6315).
+char(p,6316).
+char(6,6317).
+char(6,6318).
+char(2,6319).
+char(4,6320).
+char(c,6321).
+char(m,6322).
+char(o,6323).
+char(p,6324).
+char(5,6325).
+char(0,6326).
+char(2,6327).
+char(6,6328).
+char(c,6329).
+char(p,6330).
+char(o,6331).
+char(o,6332).
+char(m,6333).
+char(o,6334).
+char(8,6335).
+char(8,6336).
+char(0,6337).
+char(3,6338).
+char(m,6339).
+char(o,6340).
+char(m,6341).
+char(9,6342).
+char(9,6343).
+char(3,6344).
+char(7,6345).
+char(c,6346).
+char(c,6347).
+char(c,6348).
+char(c,6349).
+char(c,6350).
+char(p,6351).
+char(o,6352).
+char(o,6353).
+char(p,6354).
+char(9,6355).
+char(7,6356).
+char(3,6357).
+char(0,6358).
+char(c,6359).
+char(m,6360).
+char(7,6361).
+char(4,6362).
+char(1,6363).
+char(0,6364).
+char(m,6365).
+char(o,6366).
+char(m,6367).
+char(o,6368).
+char(p,6369).
+char(5,6370).
+char(8,6371).
+char(3,6372).
+char(7,6373).
+char(c,6374).
+char(p,6375).
+char(8,6376).
+char(9,6377).
+char(8,6378).
+char(1,6379).
+char(m,6380).
+char(o,6381).
+char(o,6382).
+char(p,6383).
+char(3,6384).
+char(6,6385).
+char(9,6386).
+char(7,6387).
+char(m,6388).
+char(o,6389).
+char(m,6390).
+char(1,6391).
+char(8,6392).
+char(3,6393).
+char(7,6394).
+char(c,6395).
+char(m,6396).
+char(o,6397).
+char(p,6398).
+char(4,6399).
+char(3,6400).
+char(6,6401).
+char(8,6402).
+char(m,6403).
+char(5,6404).
+char(6,6405).
+char(4,6406).
+char(c,6407).
+char(m,6408).
+char(3,6409).
+char(5,6410).
+char(9,6411).
+char(0,6412).
+char(c,6413).
+char(m,6414).
+char(o,6415).
+char(o,6416).
+char(o,6417).
+char(o,6418).
+char(6,6419).
+char(7,6420).
+char(8,6421).
+char(2,6422).
+char(c,6423).
+char(p,6424).
+char(5,6425).
+char(5,6426).
+char(2,6427).
+char(7,6428).
+char(p,6429).
+char(3,6430).
+char(5,6431).
+char(6,6432).
+char(6,6433).
+char(c,6434).
+char(c,6435).
+char(p,6436).
+char(o,6437).
+char(p,6438).
+char(9,6439).
+char(4,6440).
+char(5,6441).
+char(5,6442).
+char(p,6443).
+char(6,6444).
+char(0,6445).
+char(4,6446).
+char(3,6447).
+char(c,6448).
+char(c,6449).
+char(m,6450).
+char(8,6451).
+char(3,6452).
+char(6,6453).
+char(9,6454).
+char(c,6455).
+char(c,6456).
+char(p,6457).
+char(9,6458).
+char(6,6459).
+char(6,6460).
+char(3,6461).
+char(c,6462).
+char(c,6463).
+char(c,6464).
+char(m,6465).
+char(6,6466).
+char(9,6467).
+char(9,6468).
+char(0,6469).
+char(p,6470).
+char(o,6471).
+char(p,6472).
+char(7,6473).
+char(6,6474).
+char(8,6475).
+char(1,6476).
+char(c,6477).
+char(p,6478).
+char(o,6479).
+char(m,6480).
+char(7,6481).
+char(6,6482).
+char(7,6483).
+char(3,6484).
+char(m,6485).
+char(o,6486).
+char(o,6487).
+char(p,6488).
+char(6,6489).
+char(0,6490).
+char(0,6491).
+char(6,6492).
+char(c,6493).
+char(m,6494).
+char(5,6495).
+char(7,6496).
+char(9,6497).
+char(5,6498).
+char(c,6499).
+char(m,6500).
+char(o,6501).
+char(p,6502).
+char(o,6503).
+char(p,6504).
+char(6,6505).
+char(1,6506).
+char(1,6507).
+char(0,6508).
+char(c,6509).
+char(m,6510).
+char(o,6511).
+char(m,6512).
+char(8,6513).
+char(3,6514).
+char(9,6515).
+char(7,6516).
+char(m,6517).
+char(o,6518).
+char(o,6519).
+char(o,6520).
+char(m,6521).
+char(6,6522).
+char(7,6523).
+char(7,6524).
+char(4,6525).
+char(c,6526).
+char(c,6527).
+char(c,6528).
+char(m,6529).
+char(o,6530).
+char(p,6531).
+char(3,6532).
+char(5,6533).
+char(5,6534).
+char(3,6535).
+char(c,6536).
+char(m,6537).
+char(o,6538).
+char(p,6539).
+char(o,6540).
+char(m,6541).
+char(7,6542).
+char(1,6543).
+char(6,6544).
+char(4,6545).
+char(c,6546).
+char(p,6547).
+char(2,6548).
+char(0,6549).
+char(0,6550).
+char(2,6551).
+char(c,6552).
+char(c,6553).
+char(m,6554).
+char(5,6555).
+char(9,6556).
+char(6,6557).
+char(c,6558).
+char(m,6559).
+char(2,6560).
+char(0,6561).
+char(0,6562).
+char(c,6563).
+char(p,6564).
+char(5,6565).
+char(0,6566).
+char(9,6567).
+char(7,6568).
+char(p,6569).
+char(8,6570).
+char(0,6571).
+char(4,6572).
+char(2,6573).
+char(c,6574).
+char(c,6575).
+char(c,6576).
+char(c,6577).
+char(c,6578).
+char(m,6579).
+char(o,6580).
+char(m,6581).
+char(o,6582).
+char(o,6583).
+char(p,6584).
+char(o,6585).
+char(p,6586).
+char(2,6587).
+char(7,6588).
+char(4,6589).
+char(5,6590).
+char(c,6591).
+char(c,6592).
+char(c,6593).
+char(c,6594).
+char(c,6595).
+char(c,6596).
+char(p,6597).
+char(o,6598).
+char(m,6599).
+char(o,6600).
+char(p,6601).
+char(o,6602).
+char(o,6603).
+char(8,6604).
+char(6,6605).
+char(3,6606).
+char(0,6607).
+char(m,6608).
+char(o,6609).
+char(m,6610).
+char(4,6611).
+char(4,6612).
+char(4,6613).
+char(p,6614).
+char(o,6615).
+char(m,6616).
+char(6,6617).
+char(3,6618).
+char(p,6619).
+char(o,6620).
+char(o,6621).
+char(p,6622).
+char(o,6623).
+char(m,6624).
+char(4,6625).
+char(8,6626).
+char(3,6627).
+char(5,6628).
+char(c,6629).
+char(m,6630).
+char(o,6631).
+char(o,6632).
+char(m,6633).
+char(7,6634).
+char(0,6635).
+char(4,6636).
+char(6,6637).
+char(c,6638).
+char(c,6639).
+char(c,6640).
+char(c,6641).
+char(c,6642).
+char(m,6643).
+char(o,6644).
+char(p,6645).
+char(7,6646).
+char(9,6647).
+char(4,6648).
+char(c,6649).
+char(c,6650).
+char(c,6651).
+char(p,6652).
+char(1,6653).
+char(3,6654).
+char(8,6655).
+char(5,6656).
+char(c,6657).
+char(p,6658).
+char(o,6659).
+char(m,6660).
+char(o,6661).
+char(p,6662).
+char(5,6663).
+char(8,6664).
+char(2,6665).
+char(0,6666).
+char(c,6667).
+char(p,6668).
+char(4,6669).
+char(2,6670).
+char(5,6671).
+char(2,6672).
+char(c,6673).
+char(m,6674).
+char(o,6675).
+char(m,6676).
+char(1,6677).
+char(6,6678).
+char(4,6679).
+char(5,6680).
+char(c,6681).
+char(p,6682).
+char(o,6683).
+char(m,6684).
+char(5,6685).
+char(6,6686).
+char(5,6687).
+char(3,6688).
+char(c,6689).
+char(c,6690).
+char(c,6691).
+char(c,6692).
+char(p,6693).
+char(5,6694).
+char(9,6695).
+char(8,6696).
+char(9,6697).
+char(c,6698).
+char(m,6699).
+char(o,6700).
+char(7,6701).
+char(3,6702).
+char(5,6703).
+char(0,6704).
+char(c,6705).
+char(m,6706).
+char(o,6707).
+char(o,6708).
+char(1,6709).
+char(3,6710).
+char(p,6711).
+char(4,6712).
+char(7,6713).
+char(4,6714).
+char(0,6715).
+char(m,6716).
+char(o,6717).
+char(o,6718).
+char(o,6719).
+char(o,6720).
+char(m,6721).
+char(o,6722).
+char(1,6723).
+char(1,6724).
+char(0,6725).
+char(6,6726).
+char(p,6727).
+char(o,6728).
+char(m,6729).
+char(o,6730).
+char(p,6731).
+char(2,6732).
+char(9,6733).
+char(5,6734).
+char(2,6735).
+char(p,6736).
+char(2,6737).
+char(0,6738).
+char(3,6739).
+char(m,6740).
+char(2,6741).
+char(7,6742).
+char(7,6743).
+char(6,6744).
+char(c,6745).
+char(p,6746).
+char(6,6747).
+char(8,6748).
+char(0,6749).
+char(5,6750).
+char(c,6751).
+char(c,6752).
+char(c,6753).
+char(m,6754).
+char(9,6755).
+char(8,6756).
+char(9,6757).
+char(5,6758).
+char(m,6759).
+char(o,6760).
+char(p,6761).
+char(o,6762).
+char(o,6763).
+char(7,6764).
+char(0,6765).
+char(7,6766).
+char(6,6767).
+char(m,6768).
+char(7,6769).
+char(7,6770).
+char(5,6771).
+char(9,6772).
+char(m,6773).
+char(o,6774).
+char(p,6775).
+char(1,6776).
+char(3,6777).
+char(2,6778).
+char(0,6779).
+char(c,6780).
+char(c,6781).
+char(c,6782).
+char(m,6783).
+char(1,6784).
+char(0,6785).
+char(5,6786).
+char(1,6787).
+char(c,6788).
+char(p,6789).
+char(o,6790).
+char(p,6791).
+char(o,6792).
+char(m,6793).
+char(2,6794).
+char(7,6795).
+char(7,6796).
+char(7,6797).
+char(p,6798).
+char(5,6799).
+char(6,6800).
+char(1,6801).
+char(c,6802).
+char(p,6803).
+char(o,6804).
+char(m,6805).
+char(4,6806).
+char(2,6807).
+char(9,6808).
+char(1,6809).
+char(p,6810).
+char(2,6811).
+char(2,6812).
+char(3,6813).
+char(5,6814).
+char(c,6815).
+char(p,6816).
+char(5,6817).
+char(4,6818).
+char(2,6819).
+char(9,6820).
+char(c,6821).
+char(c,6822).
+char(c,6823).
+char(c,6824).
+char(m,6825).
+char(5,6826).
+char(4,6827).
+char(6,6828).
+char(c,6829).
+char(p,6830).
+char(9,6831).
+char(4,6832).
+char(9,6833).
+char(1,6834).
+char(c,6835).
+char(c,6836).
+char(c,6837).
+char(c,6838).
+char(p,6839).
+char(9,6840).
+char(4,6841).
+char(2,6842).
+char(2,6843).
+char(m,6844).
+char(o,6845).
+char(6,6846).
+char(3,6847).
+char(9,6848).
+char(8,6849).
+char(c,6850).
+char(m,6851).
+char(6,6852).
+char(9,6853).
+char(6,6854).
+char(1,6855).
+char(c,6856).
+char(m,6857).
+char(o,6858).
+char(m,6859).
+char(3,6860).
+char(4,6861).
+char(2,6862).
+char(1,6863).
+char(m,6864).
+char(6,6865).
+char(1,6866).
+char(7,6867).
+char(8,6868).
+char(p,6869).
+char(o,6870).
+char(p,6871).
+char(o,6872).
+char(p,6873).
+char(o,6874).
+char(6,6875).
+char(3,6876).
+char(6,6877).
+char(3,6878).
+char(p,6879).
+char(o,6880).
+char(p,6881).
+char(4,6882).
+char(7,6883).
+char(5,6884).
+char(c,6885).
+char(c,6886).
+char(p,6887).
+char(7,6888).
+char(7,6889).
+char(2,6890).
+char(7,6891).
+char(m,6892).
+char(o,6893).
+char(m,6894).
+char(o,6895).
+char(o,6896).
+char(m,6897).
+char(4,6898).
+char(1,6899).
+char(1,6900).
+char(9,6901).
+char(p,6902).
+char(5,6903).
+char(4,6904).
+char(9,6905).
+char(4,6906).
+char(c,6907).
+char(c,6908).
+char(m,6909).
+char(4,6910).
+char(6,6911).
+char(9,6912).
+char(9,6913).
+char(c,6914).
+char(p,6915).
+char(o,6916).
+char(o,6917).
+char(3,6918).
+char(0,6919).
+char(0,6920).
+char(8,6921).
+char(m,6922).
+char(o,6923).
+char(m,6924).
+char(o,6925).
+char(p,6926).
+char(9,6927).
+char(0,6928).
+char(8,6929).
+char(c,6930).
+char(c,6931).
+char(m,6932).
+char(8,6933).
+char(9,6934).
+char(4,6935).
+char(c,6936).
+char(c,6937).
+char(c,6938).
+char(c,6939).
+char(m,6940).
+char(3,6941).
+char(6,6942).
+char(1,6943).
+char(6,6944).
+char(c,6945).
+char(m,6946).
+char(o,6947).
+char(m,6948).
+char(o,6949).
+char(o,6950).
+char(o,6951).
+char(o,6952).
+char(m,6953).
+char(4,6954).
+char(4,6955).
+char(5,6956).
+char(p,6957).
+char(o,6958).
+char(o,6959).
+char(p,6960).
+char(o,6961).
+char(6,6962).
+char(8,6963).
+char(1,6964).
+char(7,6965).
+char(c,6966).
+char(c,6967).
+char(p,6968).
+char(o,6969).
+char(p,6970).
+char(2,6971).
+char(6,6972).
+char(7,6973).
+char(p,6974).
+char(3,6975).
+char(7,6976).
+char(4,6977).
+char(5,6978).
+char(c,6979).
+char(c,6980).
+char(p,6981).
+char(8,6982).
+char(8,6983).
+char(1,6984).
+char(6,6985).
+char(p,6986).
+char(6,6987).
+char(9,6988).
+char(3,6989).
+char(2,6990).
+char(m,6991).
+char(o,6992).
+char(5,6993).
+char(6,6994).
+char(8,6995).
+char(4,6996).
+char(m,6997).
+char(7,6998).
+char(2,6999).
+char(1,7000).
+char(8,7001).
+char(m,7002).
+char(2,7003).
+char(3,7004).
+char(2,7005).
+char(2,7006).
+char(c,7007).
+char(c,7008).
+char(m,7009).
+char(9,7010).
+char(0,7011).
+char(3,7012).
+char(4,7013).
+char(m,7014).
+char(5,7015).
+char(8,7016).
+char(4,7017).
+char(0,7018).
+char(p,7019).
+char(o,7020).
+char(p,7021).
+char(4,7022).
+char(4,7023).
+char(3,7024).
+char(5,7025).
+char(c,7026).
+char(c,7027).
+char(p,7028).
+char(o,7029).
+char(9,7030).
+char(1,7031).
+char(7,7032).
+char(9,7033).
+char(c,7034).
+char(p,7035).
+char(3,7036).
+char(3,7037).
+char(4,7038).
+char(9,7039).
+char(m,7040).
+char(7,7041).
+char(2,7042).
+char(9,7043).
+char(1,7044).
+char(p,7045).
+char(2,7046).
+char(2,7047).
+char(9,7048).
+char(0,7049).
+char(p,7050).
+char(7,7051).
+char(0,7052).
+char(7,7053).
+char(1,7054).
+char(m,7055).
+char(9,7056).
+char(3,7057).
+char(4,7058).
+char(2,7059).
+char(m,7060).
+char(o,7061).
+char(p,7062).
+char(4,7063).
+char(0,7064).
+char(2,7065).
+char(5,7066).
+char(c,7067).
+char(m,7068).
+char(o,7069).
+char(m,7070).
+char(o,7071).
+char(o,7072).
+char(p,7073).
+char(6,7074).
+char(6,7075).
+char(9,7076).
+char(3,7077).
+char(c,7078).
+char(p,7079).
+char(3,7080).
+char(7,7081).
+char(1,7082).
+char(3,7083).
+char(c,7084).
+char(p,7085).
+char(8,7086).
+char(9,7087).
+char(6,7088).
+char(6,7089).
+char(m,7090).
+char(o,7091).
+char(m,7092).
+char(o,7093).
+char(5,7094).
+char(4,7095).
+char(2,7096).
+char(1,7097).
+char(c,7098).
+char(p,7099).
+char(6,7100).
+char(7,7101).
+char(9,7102).
+char(7,7103).
+char(p,7104).
+char(7,7105).
+char(5,7106).
+char(0,7107).
+char(8,7108).
+char(m,7109).
+char(o,7110).
+char(m,7111).
+char(8,7112).
+char(1,7113).
+char(7,7114).
+char(m,7115).
+char(o,7116).
+char(3,7117).
+char(6,7118).
+char(6,7119).
+char(9,7120).
+char(m,7121).
+char(9,7122).
+char(5,7123).
+char(1,7124).
+char(5,7125).
+char(c,7126).
+char(p,7127).
+char(8,7128).
+char(0,7129).
+char(8,7130).
+char(5,7131).
+char(p,7132).
+char(o,7133).
+char(o,7134).
+char(p,7135).
+char(5,7136).
+char(1,7137).
+char(0,7138).
+char(7,7139).
+char(c,7140).
+char(c,7141).
+char(m,7142).
+char(1,7143).
+char(2,7144).
+char(2,7145).
+char(9,7146).
+char(c,7147).
+char(p,7148).
+char(o,7149).
+char(m,7150).
+char(7,7151).
+char(9,7152).
+char(5,7153).
+char(2,7154).
+char(p,7155).
+char(o,7156).
+char(p,7157).
+char(9,7158).
+char(0,7159).
+char(3,7160).
+char(2,7161).
+char(p,7162).
+char(o,7163).
+char(o,7164).
+char(m,7165).
+char(8,7166).
+char(7,7167).
+char(8,7168).
+char(2,7169).
+char(c,7170).
+char(c,7171).
+char(c,7172).
+char(m,7173).
+char(o,7174).
+char(m,7175).
+char(o,7176).
+char(3,7177).
+char(7,7178).
+char(3,7179).
+char(5,7180).
+char(c,7181).
+char(m,7182).
+char(o,7183).
+char(5,7184).
+char(8,7185).
+char(2,7186).
+char(8,7187).
+char(c,7188).
+char(m,7189).
+char(8,7190).
+char(7,7191).
+char(3,7192).
+char(9,7193).
+char(c,7194).
+char(c,7195).
+char(m,7196).
+char(6,7197).
+char(2,7198).
+char(3,7199).
+char(3,7200).
+char(p,7201).
+char(6,7202).
+char(4,7203).
+char(5,7204).
+char(3,7205).
+char(c,7206).
+char(m,7207).
+char(7,7208).
+char(2,7209).
+char(4,7210).
+char(1,7211).
+char(m,7212).
+char(9,7213).
+char(4,7214).
+char(9,7215).
+char(5,7216).
+char(c,7217).
+char(c,7218).
+char(m,7219).
+char(9,7220).
+char(3,7221).
+char(7,7222).
+char(7,7223).
+char(c,7224).
+char(m,7225).
+char(o,7226).
+char(m,7227).
+char(o,7228).
+char(p,7229).
+char(7,7230).
+char(1,7231).
+char(7,7232).
+char(5,7233).
+char(c,7234).
+char(c,7235).
+char(c,7236).
+char(m,7237).
+char(o,7238).
+char(p,7239).
+char(o,7240).
+char(m,7241).
+char(3,7242).
+char(8,7243).
+char(9,7244).
+char(c,7245).
+char(c,7246).
+char(p,7247).
+char(2,7248).
+char(6,7249).
+char(9,7250).
+char(7,7251).
+char(c,7252).
+char(c,7253).
+char(p,7254).
+char(4,7255).
+char(5,7256).
+char(1,7257).
+char(3,7258).
+char(p,7259).
+char(5,7260).
+char(7,7261).
+char(9,7262).
+char(m,7263).
+char(4,7264).
+char(2,7265).
+char(6,7266).
+char(0,7267).
+char(c,7268).
+char(m,7269).
+char(1,7270).
+char(7,7271).
+char(9,7272).
+char(6,7273).
+char(m,7274).
+char(1,7275).
+char(8,7276).
+char(5,7277).
+char(0,7278).
+char(p,7279).
+char(4,7280).
+char(8,7281).
+char(8,7282).
+char(2,7283).
+char(c,7284).
+char(c,7285).
+char(p,7286).
+char(o,7287).
+char(p,7288).
+char(o,7289).
+char(m,7290).
+char(8,7291).
+char(0,7292).
+char(1,7293).
+char(4,7294).
+char(c,7295).
+char(c,7296).
+char(m,7297).
+char(4,7298).
+char(6,7299).
+char(2,7300).
+char(6,7301).
+char(c,7302).
+char(p,7303).
+char(5,7304).
+char(6,7305).
+char(5,7306).
+char(6,7307).
+char(c,7308).
+char(m,7309).
+char(o,7310).
+char(o,7311).
+char(m,7312).
+char(5,7313).
+char(8,7314).
+char(5,7315).
+char(5,7316).
+char(c,7317).
+char(c,7318).
+char(m,7319).
+char(6,7320).
+char(3,7321).
+char(7,7322).
+char(0,7323).
+char(c,7324).
+char(c,7325).
+char(m,7326).
+char(8,7327).
+char(3,7328).
+char(4,7329).
+char(9,7330).
+char(c,7331).
+char(c,7332).
+char(p,7333).
+char(o,7334).
+char(m,7335).
+char(o,7336).
+char(p,7337).
+char(o,7338).
+char(p,7339).
+char(o,7340).
+char(p,7341).
+char(9,7342).
+char(5,7343).
+char(8,7344).
+char(3,7345).
+char(p,7346).
+char(o,7347).
+char(o,7348).
+char(o,7349).
+char(p,7350).
+char(o,7351).
+char(p,7352).
+char(2,7353).
+char(1,7354).
+char(2,7355).
+char(7,7356).
+char(c,7357).
+char(p,7358).
+char(5,7359).
+char(1,7360).
+char(8,7361).
+char(2,7362).
+char(m,7363).
+char(6,7364).
+char(1,7365).
+char(2,7366).
+char(4,7367).
+char(c,7368).
+char(c,7369).
+char(p,7370).
+char(o,7371).
+char(o,7372).
+char(p,7373).
+char(4,7374).
+char(9,7375).
+char(3,7376).
+char(8,7377).
+char(c,7378).
+char(c,7379).
+char(c,7380).
+char(m,7381).
+char(o,7382).
+char(m,7383).
+char(8,7384).
+char(0,7385).
+char(3,7386).
+char(0,7387).
+char(c,7388).
+char(c,7389).
+char(p,7390).
+char(o,7391).
+char(m,7392).
+char(2,7393).
+char(0,7394).
+char(2,7395).
+char(5,7396).
+char(c,7397).
+char(p,7398).
+char(o,7399).
+char(p,7400).
+char(o,7401).
+char(p,7402).
+char(2,7403).
+char(2,7404).
+char(0,7405).
+char(4,7406).
+char(c,7407).
+char(c,7408).
+char(c,7409).
+char(c,7410).
+char(c,7411).
+char(c,7412).
+char(m,7413).
+char(2,7414).
+char(4,7415).
+char(8,7416).
+char(2,7417).
+char(c,7418).
+char(p,7419).
+char(4,7420).
+char(7,7421).
+char(8,7422).
+char(5,7423).
+char(c,7424).
+char(m,7425).
+char(o,7426).
+char(m,7427).
+char(o,7428).
+char(m,7429).
+char(1,7430).
+char(4,7431).
+char(1,7432).
+char(9,7433).
+char(p,7434).
+char(o,7435).
+char(8,7436).
+char(4,7437).
+char(4,7438).
+char(0,7439).
+char(c,7440).
+char(c,7441).
+char(c,7442).
+char(p,7443).
+char(4,7444).
+char(5,7445).
+char(0,7446).
+char(9,7447).
+char(c,7448).
+char(c,7449).
+char(c,7450).
+char(c,7451).
+char(c,7452).
+char(c,7453).
+char(c,7454).
+char(p,7455).
+char(o,7456).
+char(o,7457).
+char(m,7458).
+char(8,7459).
+char(8,7460).
+char(8,7461).
+char(1,7462).
+char(p,7463).
+char(o,7464).
+char(o,7465).
+char(m,7466).
+char(9,7467).
+char(3,7468).
+char(6,7469).
+char(2,7470).
+char(c,7471).
+char(p,7472).
+char(o,7473).
+char(3,7474).
+char(9,7475).
+char(7,7476).
+char(1,7477).
+char(p,7478).
+char(o,7479).
+char(m,7480).
+char(7,7481).
+char(7,7482).
+char(3,7483).
+char(0,7484).
+char(m,7485).
+char(3,7486).
+char(4,7487).
+char(7,7488).
+char(2,7489).
+char(p,7490).
+char(o,7491).
+char(8,7492).
+char(7,7493).
+char(6,7494).
+char(4,7495).
+char(m,7496).
+char(o,7497).
+char(o,7498).
+char(p,7499).
+char(8,7500).
+char(6,7501).
+char(0,7502).
+char(4,7503).
+char(p,7504).
+char(o,7505).
+char(p,7506).
+char(3,7507).
+char(1,7508).
+char(2,7509).
+char(7,7510).
+char(p,7511).
+char(o,7512).
+char(1,7513).
+char(2,7514).
+char(4,7515).
+char(5,7516).
+char(c,7517).
+char(c,7518).
+char(p,7519).
+char(2,7520).
+char(5,7521).
+char(6,7522).
+char(6,7523).
+char(m,7524).
+char(o,7525).
+char(2,7526).
+char(2,7527).
+char(0,7528).
+char(8,7529).
+char(m,7530).
+char(o,7531).
+char(p,7532).
+char(o,7533).
+char(o,7534).
+char(p,7535).
+char(5,7536).
+char(6,7537).
+char(3,7538).
+char(5,7539).
+char(c,7540).
+char(c,7541).
+char(c,7542).
+char(m,7543).
+char(8,7544).
+char(1,7545).
+char(1,7546).
+char(4,7547).
+char(p,7548).
+char(7,7549).
+char(8,7550).
+char(0,7551).
+char(2,7552).
+char(c,7553).
+char(p,7554).
+char(o,7555).
+char(p,7556).
+char(5,7557).
+char(2,7558).
+char(4,7559).
+char(2,7560).
+char(m,7561).
+char(o,7562).
+char(m,7563).
+char(1,7564).
+char(7,7565).
+char(2,7566).
+char(6,7567).
+char(c,7568).
+char(c,7569).
+char(c,7570).
+char(c,7571).
+char(c,7572).
+char(p,7573).
+char(3,7574).
+char(7,7575).
+char(2,7576).
+char(0,7577).
+char(c,7578).
+char(m,7579).
+char(8,7580).
+char(3,7581).
+char(0,7582).
+char(9,7583).
+char(p,7584).
+char(o,7585).
+char(p,7586).
+char(o,7587).
+char(p,7588).
+char(6,7589).
+char(0,7590).
+char(4,7591).
+char(1,7592).
+char(c,7593).
+char(p,7594).
+char(o,7595).
+char(o,7596).
+char(m,7597).
+char(o,7598).
+char(o,7599).
+char(7,7600).
+char(1,7601).
+char(3,7602).
+char(7,7603).
+char(c,7604).
+char(m,7605).
+char(7,7606).
+char(6,7607).
+char(6,7608).
+char(0,7609).
+char(p,7610).
+char(6,7611).
+char(4,7612).
+char(9,7613).
+char(2,7614).
+char(c,7615).
+char(m,7616).
+char(8,7617).
+char(8,7618).
+char(8,7619).
+char(3,7620).
+char(p,7621).
+char(o,7622).
+char(m,7623).
+char(5,7624).
+char(0,7625).
+char(9,7626).
+char(9,7627).
+char(c,7628).
+char(c,7629).
+char(c,7630).
+char(m,7631).
+char(9,7632).
+char(4,7633).
+char(4,7634).
+char(3,7635).
+char(m,7636).
+char(o,7637).
+char(8,7638).
+char(7,7639).
+char(8,7640).
+char(4,7641).
+char(m,7642).
+char(o,7643).
+char(o,7644).
+char(m,7645).
+char(9,7646).
+char(5,7647).
+char(3,7648).
+char(9,7649).
+char(c,7650).
+char(c,7651).
+char(c,7652).
+char(c,7653).
+char(m,7654).
+char(o,7655).
+char(m,7656).
+char(o,7657).
+char(p,7658).
+char(o,7659).
+char(p,7660).
+char(o,7661).
+char(5,7662).
+char(6,7663).
+char(2,7664).
+char(7,7665).
+char(c,7666).
+char(c,7667).
+char(c,7668).
+char(m,7669).
+char(o,7670).
+char(p,7671).
+char(8,7672).
+char(7,7673).
+char(5,7674).
+char(8,7675).
+char(m,7676).
+char(o,7677).
+char(m,7678).
+char(o,7679).
+char(p,7680).
+char(8,7681).
+char(6,7682).
+char(9,7683).
+char(4,7684).
+char(m,7685).
+char(o,7686).
+char(o,7687).
+char(m,7688).
+char(4,7689).
+char(5,7690).
+char(1,7691).
+char(3,7692).
+char(c,7693).
+char(m,7694).
+char(o,7695).
+char(p,7696).
+char(o,7697).
+char(o,7698).
+char(7,7699).
+char(2,7700).
+char(2,7701).
+char(2,7702).
+char(c,7703).
+char(c,7704).
+char(c,7705).
+char(c,7706).
+char(p,7707).
+char(3,7708).
+char(1,7709).
+char(3,7710).
+char(0,7711).
+char(p,7712).
+char(6,7713).
+char(2,7714).
+char(7,7715).
+char(c,7716).
+char(c,7717).
+char(c,7718).
+char(c,7719).
+char(c,7720).
+char(p,7721).
+char(o,7722).
+char(4,7723).
+char(1,7724).
+char(7,7725).
+char(5,7726).
+char(p,7727).
+char(7,7728).
+char(9,7729).
+char(3,7730).
+char(m,7731).
+char(9,7732).
+char(0,7733).
+char(4,7734).
+char(4,7735).
+char(c,7736).
+char(c,7737).
+char(c,7738).
+char(c,7739).
+char(c,7740).
+char(c,7741).
+char(m,7742).
+char(o,7743).
+char(p,7744).
+char(o,7745).
+char(6,7746).
+char(0,7747).
+char(0,7748).
+char(p,7749).
+char(1,7750).
+char(8,7751).
+char(3,7752).
+char(4,7753).
+char(p,7754).
+char(o,7755).
+char(p,7756).
+char(o,7757).
+char(o,7758).
+char(o,7759).
+char(p,7760).
+char(4,7761).
+char(9,7762).
+char(7,7763).
+char(3,7764).
+char(m,7765).
+char(2,7766).
+char(5,7767).
+char(3,7768).
+char(6,7769).
+char(c,7770).
+char(p,7771).
+char(2,7772).
+char(1,7773).
+char(8,7774).
+char(0,7775).
+char(c,7776).
+char(p,7777).
+char(o,7778).
+char(m,7779).
+char(o,7780).
+char(p,7781).
+char(9,7782).
+char(7,7783).
+char(9,7784).
+char(4,7785).
+char(m,7786).
+char(9,7787).
+char(0,7788).
+char(4,7789).
+char(8,7790).
+char(c,7791).
+char(m,7792).
+char(4,7793).
+char(1,7794).
+char(4,7795).
+char(1,7796).
+char(m,7797).
+char(1,7798).
+char(3,7799).
+char(6,7800).
+char(p,7801).
+char(o,7802).
+char(o,7803).
+char(p,7804).
+char(o,7805).
+char(p,7806).
+char(o,7807).
+char(p,7808).
+char(7,7809).
+char(4,7810).
+char(0,7811).
+char(4,7812).
+char(c,7813).
+char(m,7814).
+char(o,7815).
+char(p,7816).
+char(o,7817).
+char(p,7818).
+char(9,7819).
+char(0,7820).
+char(3,7821).
+char(5,7822).
+char(c,7823).
+char(c,7824).
+char(c,7825).
+char(m,7826).
+char(4,7827).
+char(6,7828).
+char(6,7829).
+char(c,7830).
+char(c,7831).
+char(c,7832).
+char(m,7833).
+char(o,7834).
+char(9,7835).
+char(1,7836).
+char(7,7837).
+char(8,7838).
+char(c,7839).
+char(c,7840).
+char(p,7841).
+char(2,7842).
+char(2,7843).
+char(1,7844).
+char(9,7845).
+char(c,7846).
+char(c,7847).
+char(c,7848).
+char(p,7849).
+char(o,7850).
+char(m,7851).
+char(6,7852).
+char(8,7853).
+char(6,7854).
+char(3,7855).
+char(m,7856).
+char(2,7857).
+char(7,7858).
+char(2,7859).
+char(4,7860).
+char(m,7861).
+char(4,7862).
+char(8,7863).
+char(8,7864).
+char(8,7865).
+char(p,7866).
+char(o,7867).
+char(p,7868).
+char(o,7869).
+char(p,7870).
+char(6,7871).
+char(1,7872).
+char(6,7873).
+char(3,7874).
+char(c,7875).
+char(c,7876).
+char(p,7877).
+char(o,7878).
+char(p,7879).
+char(o,7880).
+char(p,7881).
+char(o,7882).
+char(p,7883).
+char(3,7884).
+char(6,7885).
+char(1,7886).
+char(c,7887).
+char(m,7888).
+char(5,7889).
+char(3,7890).
+char(7,7891).
+char(8,7892).
+char(p,7893).
+char(o,7894).
+char(o,7895).
+char(m,7896).
+char(4,7897).
+char(4,7898).
+char(6,7899).
+char(5,7900).
+char(c,7901).
+char(c,7902).
+char(c,7903).
+char(m,7904).
+char(3,7905).
+char(1,7906).
+char(2,7907).
+char(4,7908).
+char(m,7909).
+char(o,7910).
+char(o,7911).
+char(p,7912).
+char(3,7913).
+char(0,7914).
+char(0,7915).
+char(9,7916).
+char(m,7917).
+char(9,7918).
+char(4,7919).
+char(3,7920).
+char(1,7921).
+char(c,7922).
+char(p,7923).
+char(o,7924).
+char(o,7925).
+char(p,7926).
+char(o,7927).
+char(m,7928).
+char(o,7929).
+char(m,7930).
+char(4,7931).
+char(5,7932).
+char(0,7933).
+char(4,7934).
+char(c,7935).
+char(p,7936).
+char(o,7937).
+char(1,7938).
+char(8,7939).
+char(6,7940).
+char(5,7941).
+char(c,7942).
+char(p,7943).
+char(o,7944).
+char(p,7945).
+char(5,7946).
+char(2,7947).
+char(6,7948).
+char(6,7949).
+char(c,7950).
+char(c,7951).
+char(p,7952).
+char(o,7953).
+char(o,7954).
+char(m,7955).
+char(5,7956).
+char(8,7957).
+char(3,7958).
+char(5,7959).
+char(c,7960).
+char(c,7961).
+char(p,7962).
+char(3,7963).
+char(4,7964).
+char(2,7965).
+char(6,7966).
+char(p,7967).
+char(2,7968).
+char(1,7969).
+char(2,7970).
+char(6,7971).
+char(c,7972).
+char(c,7973).
+char(p,7974).
+char(o,7975).
+char(o,7976).
+char(p,7977).
+char(o,7978).
+char(p,7979).
+char(o,7980).
+char(m,7981).
+char(8,7982).
+char(6,7983).
+char(3,7984).
+char(5,7985).
+char(m,7986).
+char(9,7987).
+char(3,7988).
+char(7,7989).
+char(2,7990).
+char(p,7991).
+char(o,7992).
+char(p,7993).
+char(o,7994).
+char(p,7995).
+char(o,7996).
+char(p,7997).
+char(o,7998).
+char(m,7999).
+char(8,8000).
+char(5,8001).
+char(2,8002).
+char(7,8003).
+char(c,8004).
+char(c,8005).
+char(m,8006).
+char(4,8007).
+char(5,8008).
+char(1,8009).
+char(c,8010).
+char(m,8011).
+char(7,8012).
+char(2,8013).
+char(0,8014).
+char(9,8015).
+char(c,8016).
+char(c,8017).
+char(p,8018).
+char(6,8019).
+char(8,8020).
+char(7,8021).
+char(4,8022).
+char(c,8023).
+char(m,8024).
+char(3,8025).
+char(8,8026).
+char(5,8027).
+char(8,8028).
+char(c,8029).
+char(c,8030).
+char(p,8031).
+char(5,8032).
+char(8,8033).
+char(4,8034).
+char(1,8035).
+char(p,8036).
+char(2,8037).
+char(1,8038).
+char(1,8039).
+char(9,8040).
+char(p,8041).
+char(8,8042).
+char(0,8043).
+char(1,8044).
+char(4,8045).
+char(p,8046).
+char(3,8047).
+char(6,8048).
+char(2,8049).
+char(1,8050).
+char(c,8051).
+char(c,8052).
+char(p,8053).
+char(o,8054).
+char(m,8055).
+char(o,8056).
+char(p,8057).
+char(7,8058).
+char(9,8059).
+char(4,8060).
+char(3,8061).
+char(c,8062).
+char(c,8063).
+char(m,8064).
+char(6,8065).
+char(4,8066).
+char(8,8067).
+char(4,8068).
+char(c,8069).
+char(p,8070).
+char(o,8071).
+char(7,8072).
+char(5,8073).
+char(4,8074).
+char(6,8075).
+char(p,8076).
+char(o,8077).
+char(5,8078).
+char(7,8079).
+char(3,8080).
+char(8,8081).
+char(c,8082).
+char(c,8083).
+char(p,8084).
+char(5,8085).
+char(6,8086).
+char(8,8087).
+char(4,8088).
+char(p,8089).
+char(7,8090).
+char(8,8091).
+char(4,8092).
+char(7,8093).
+char(c,8094).
+char(p,8095).
+char(2,8096).
+char(4,8097).
+char(1,8098).
+char(6,8099).
+char(c,8100).
+char(c,8101).
+char(c,8102).
+char(p,8103).
+char(o,8104).
+char(o,8105).
+char(6,8106).
+char(6,8107).
+char(5,8108).
+char(1,8109).
+char(p,8110).
+char(o,8111).
+char(o,8112).
+char(p,8113).
+char(o,8114).
+char(m,8115).
+char(o,8116).
+char(m,8117).
+char(o,8118).
+char(p,8119).
+char(o,8120).
+char(9,8121).
+char(5,8122).
+char(2,8123).
+char(0,8124).
+char(c,8125).
+char(p,8126).
+char(6,8127).
+char(5,8128).
+char(4,8129).
+char(3,8130).
+char(p,8131).
+char(5,8132).
+char(5,8133).
+char(9,8134).
+char(6,8135).
+char(c,8136).
+char(p,8137).
+char(o,8138).
+char(4,8139).
+char(4,8140).
+char(0,8141).
+char(3,8142).
+char(p,8143).
+char(o,8144).
+char(m,8145).
+char(o,8146).
+char(p,8147).
+char(7,8148).
+char(0,8149).
+char(1,8150).
+char(8,8151).
+char(m,8152).
+char(o,8153).
+char(m,8154).
+char(8,8155).
+char(4,8156).
+char(0,8157).
+char(0,8158).
+char(c,8159).
+char(p,8160).
+char(1,8161).
+char(9,8162).
+char(8,8163).
+char(7,8164).
+char(m,8165).
+char(1,8166).
+char(9,8167).
+char(5,8168).
+char(5,8169).
+char(p,8170).
+char(o,8171).
+char(m,8172).
+char(3,8173).
+char(4,8174).
+char(8,8175).
+char(3,8176).
+char(p,8177).
+char(7,8178).
+char(6,8179).
+char(1,8180).
+char(8,8181).
+char(m,8182).
+char(o,8183).
+char(p,8184).
+char(o,8185).
+char(1,8186).
+char(8,8187).
+char(1,8188).
+char(3,8189).
+char(c,8190).
+char(m,8191).
+char(5,8192).
+char(7,8193).
+char(2,8194).
+char(3,8195).
+char(c,8196).
+char(p,8197).
+char(o,8198).
+char(m,8199).
+char(9,8200).
+char(4,8201).
+char(5,8202).
+char(9,8203).
+char(c,8204).
+char(p,8205).
+char(2,8206).
+char(8,8207).
+char(6,8208).
+char(p,8209).
+char(o,8210).
+char(p,8211).
+char(3,8212).
+char(4,8213).
+char(5,8214).
+char(7,8215).
+char(m,8216).
+char(o,8217).
+char(m,8218).
+char(5,8219).
+char(0,8220).
+char(9,8221).
+char(c,8222).
+char(c,8223).
+char(c,8224).
+char(p,8225).
+char(8,8226).
+char(8,8227).
+char(1,8228).
+char(6,8229).
+char(m,8230).
+char(9,8231).
+char(1,8232).
+char(1,8233).
+char(4,8234).
+char(c,8235).
+char(c,8236).
+char(p,8237).
+char(o,8238).
+char(m,8239).
+char(o,8240).
+char(5,8241).
+char(7,8242).
+char(3,8243).
+char(5,8244).
+char(m,8245).
+char(o,8246).
+char(m,8247).
+char(6,8248).
+char(6,8249).
+char(8,8250).
+char(7,8251).
+char(p,8252).
+char(4,8253).
+char(3,8254).
+char(5,8255).
+char(p,8256).
+char(9,8257).
+char(6,8258).
+char(3,8259).
+char(6,8260).
+char(c,8261).
+char(c,8262).
+char(m,8263).
+char(1,8264).
+char(0,8265).
+char(4,8266).
+char(3,8267).
+char(c,8268).
+char(c,8269).
+char(c,8270).
+char(c,8271).
+char(c,8272).
+char(p,8273).
+char(o,8274).
+char(m,8275).
+char(5,8276).
+char(9,8277).
+char(8,8278).
+char(1,8279).
+char(p,8280).
+char(1,8281).
+char(4,8282).
+char(7,8283).
+char(0,8284).
+char(c,8285).
+char(m,8286).
+char(o,8287).
+char(m,8288).
+char(5,8289).
+char(3,8290).
+char(5,8291).
+char(6,8292).
+char(c,8293).
+char(p,8294).
+char(1,8295).
+char(9,8296).
+char(1,8297).
+char(6,8298).
+char(c,8299).
+char(c,8300).
+char(p,8301).
+char(4,8302).
+char(4,8303).
+char(4,8304).
+char(m,8305).
+char(o,8306).
+char(m,8307).
+char(o,8308).
+char(m,8309).
+char(5,8310).
+char(2,8311).
+char(1,8312).
+char(c,8313).
+char(p,8314).
+char(o,8315).
+char(m,8316).
+char(o,8317).
+char(p,8318).
+char(5,8319).
+char(4,8320).
+char(9,8321).
+char(0,8322).
+char(m,8323).
+char(o,8324).
+char(m,8325).
+char(o,8326).
+char(p,8327).
+char(o,8328).
+char(m,8329).
+char(o,8330).
+char(o,8331).
+char(m,8332).
+char(1,8333).
+char(5,8334).
+char(2,8335).
+char(6,8336).
+char(p,8337).
+char(o,8338).
+char(m,8339).
+char(3,8340).
+char(5,8341).
+char(5,8342).
+char(4,8343).
+char(c,8344).
+char(c,8345).
+char(p,8346).
+char(o,8347).
+char(p,8348).
+char(o,8349).
+char(o,8350).
+char(p,8351).
+char(3,8352).
+char(1,8353).
+char(9,8354).
+char(9,8355).
+char(m,8356).
+char(9,8357).
+char(7,8358).
+char(8,8359).
+char(8,8360).
+char(m,8361).
+char(1,8362).
+char(3,8363).
+char(7,8364).
+char(5,8365).
+char(m,8366).
+char(3,8367).
+char(9,8368).
+char(3,8369).
+char(m,8370).
+char(o,8371).
+char(m,8372).
+char(o,8373).
+char(o,8374).
+char(5,8375).
+char(8,8376).
+char(2,8377).
+char(4,8378).
+char(m,8379).
+char(2,8380).
+char(7,8381).
+char(4,8382).
+char(5,8383).
+char(m,8384).
+char(o,8385).
+char(p,8386).
+char(6,8387).
+char(9,8388).
+char(2,8389).
+char(4,8390).
+char(c,8391).
+char(m,8392).
+char(o,8393).
+char(9,8394).
+char(5,8395).
+char(4,8396).
+char(0,8397).
+char(c,8398).
+char(p,8399).
+char(7,8400).
+char(2,8401).
+char(6,8402).
+char(7,8403).
+char(m,8404).
+char(o,8405).
+char(o,8406).
+char(m,8407).
+char(o,8408).
+char(m,8409).
+char(5,8410).
+char(1,8411).
+char(9,8412).
+char(9,8413).
+char(m,8414).
+char(o,8415).
+char(m,8416).
+char(o,8417).
+char(p,8418).
+char(4,8419).
+char(5,8420).
+char(3,8421).
+char(8,8422).
+char(m,8423).
+char(1,8424).
+char(3,8425).
+char(0,8426).
+char(7,8427).
+char(c,8428).
+char(c,8429).
+char(c,8430).
+char(p,8431).
+char(3,8432).
+char(8,8433).
+char(3,8434).
+char(4,8435).
+char(p,8436).
+char(5,8437).
+char(1,8438).
+char(5,8439).
+char(1,8440).
+char(c,8441).
+char(p,8442).
+char(8,8443).
+char(0,8444).
+char(2,8445).
+char(4,8446).
+char(c,8447).
+char(m,8448).
+char(4,8449).
+char(5,8450).
+char(8,8451).
+char(4,8452).
+char(p,8453).
+char(8,8454).
+char(9,8455).
+char(2,8456).
+char(8,8457).
+char(p,8458).
+char(o,8459).
+char(p,8460).
+char(5,8461).
+char(9,8462).
+char(0,8463).
+char(5,8464).
+char(p,8465).
+char(3,8466).
+char(6,8467).
+char(3,8468).
+char(9,8469).
+char(c,8470).
+char(p,8471).
+char(8,8472).
+char(5,8473).
+char(7,8474).
+char(9,8475).
+char(c,8476).
+char(m,8477).
+char(o,8478).
+char(m,8479).
+char(o,8480).
+char(m,8481).
+char(o,8482).
+char(o,8483).
+char(7,8484).
+char(8,8485).
+char(8,8486).
+char(7,8487).
+char(p,8488).
+char(o,8489).
+char(m,8490).
+char(o,8491).
+char(p,8492).
+char(o,8493).
+char(p,8494).
+char(o,8495).
+char(m,8496).
+char(7,8497).
+char(0,8498).
+char(9,8499).
+char(5,8500).
+char(c,8501).
+char(m,8502).
+char(6,8503).
+char(8,8504).
+char(8,8505).
+char(8,8506).
+char(p,8507).
+char(9,8508).
+char(4,8509).
+char(4,8510).
+char(3,8511).
+char(p,8512).
+char(2,8513).
+char(8,8514).
+char(4,8515).
+char(4,8516).
+char(p,8517).
+char(5,8518).
+char(8,8519).
+char(7,8520).
+char(1,8521).
+char(m,8522).
+char(o,8523).
+char(4,8524).
+char(3,8525).
+char(3,8526).
+char(1,8527).
+char(c,8528).
+char(c,8529).
+char(c,8530).
+char(c,8531).
+char(p,8532).
+char(o,8533).
+char(p,8534).
+char(o,8535).
+char(p,8536).
+char(1,8537).
+char(2,8538).
+char(4,8539).
+char(6,8540).
+char(p,8541).
+char(o,8542).
+char(m,8543).
+char(6,8544).
+char(2,8545).
+char(6,8546).
+char(3,8547).
+char(c,8548).
+char(p,8549).
+char(3,8550).
+char(9,8551).
+char(3,8552).
+char(7,8553).
+char(c,8554).
+char(m,8555).
+char(o,8556).
+char(o,8557).
+char(m,8558).
+char(9,8559).
+char(9,8560).
+char(3,8561).
+char(0,8562).
+char(c,8563).
+char(p,8564).
+char(o,8565).
+char(p,8566).
+char(8,8567).
+char(2,8568).
+char(5,8569).
+char(3,8570).
+char(c,8571).
+char(m,8572).
+char(7,8573).
+char(3,8574).
+char(7,8575).
+char(3,8576).
+char(c,8577).
+char(p,8578).
+char(o,8579).
+char(m,8580).
+char(1,8581).
+char(6,8582).
+char(5,8583).
+char(9,8584).
+char(c,8585).
+char(m,8586).
+char(o,8587).
+char(o,8588).
+char(4,8589).
+char(8,8590).
+char(6,8591).
+char(8,8592).
+char(m,8593).
+char(5,8594).
+char(3,8595).
+char(1,8596).
+char(2,8597).
+char(c,8598).
+char(c,8599).
+char(m,8600).
+char(6,8601).
+char(5,8602).
+char(5,8603).
+char(0,8604).
+char(p,8605).
+char(o,8606).
+char(p,8607).
+char(8,8608).
+char(7,8609).
+char(1,8610).
+char(p,8611).
+char(8,8612).
+char(6,8613).
+char(1,8614).
+char(8,8615).
+char(p,8616).
+char(2,8617).
+char(1,8618).
+char(1,8619).
+char(8,8620).
+char(c,8621).
+char(p,8622).
+char(o,8623).
+char(m,8624).
+char(6,8625).
+char(6,8626).
+char(0,8627).
+char(6,8628).
+char(c,8629).
+char(m,8630).
+char(o,8631).
+char(1,8632).
+char(2,8633).
+char(5,8634).
+char(4,8635).
+char(p,8636).
+char(3,8637).
+char(6,8638).
+char(2,8639).
+char(0,8640).
+char(c,8641).
+char(p,8642).
+char(9,8643).
+char(6,8644).
+char(5,8645).
+char(9,8646).
+char(p,8647).
+char(o,8648).
+char(p,8649).
+char(o,8650).
+char(p,8651).
+char(5,8652).
+char(0,8653).
+char(1,8654).
+char(6,8655).
+char(p,8656).
+char(8,8657).
+char(6,8658).
+char(7,8659).
+char(1,8660).
+char(c,8661).
+char(c,8662).
+char(p,8663).
+char(3,8664).
+char(5,8665).
+char(1,8666).
+char(3,8667).
+char(c,8668).
+char(c,8669).
+char(p,8670).
+char(o,8671).
+char(1,8672).
+char(6,8673).
+char(9,8674).
+char(6,8675).
+char(c,8676).
+char(p,8677).
+char(6,8678).
+char(0,8679).
+char(5,8680).
+char(4,8681).
+char(p,8682).
+char(8,8683).
+char(6,8684).
+char(1,8685).
+char(3,8686).
+char(m,8687).
+char(o,8688).
+char(p,8689).
+char(o,8690).
+char(m,8691).
+char(o,8692).
+char(o,8693).
+char(o,8694).
+char(m,8695).
+char(o,8696).
+char(7,8697).
+char(c,8698).
+char(c,8699).
+char(c,8700).
+char(c,8701).
+char(c,8702).
+char(p,8703).
+char(o,8704).
+char(p,8705).
+char(o,8706).
+char(5,8707).
+char(8,8708).
+char(3,8709).
+char(5,8710).
+char(p,8711).
+char(3,8712).
+char(3,8713).
+char(6,8714).
+char(5,8715).
+char(c,8716).
+char(c,8717).
+char(c,8718).
+char(c,8719).
+char(p,8720).
+char(3,8721).
+char(7,8722).
+char(4,8723).
+char(7,8724).
+char(p,8725).
+char(o,8726).
+char(m,8727).
+char(9,8728).
+char(6,8729).
+char(0,8730).
+char(0,8731).
+char(c,8732).
+char(m,8733).
+char(o,8734).
+char(p,8735).
+char(4,8736).
+char(3,8737).
+char(7,8738).
+char(1,8739).
+char(p,8740).
+char(4,8741).
+char(0,8742).
+char(2,8743).
+char(0,8744).
+char(p,8745).
+char(o,8746).
+char(6,8747).
+char(2,8748).
+char(7,8749).
+char(5,8750).
+char(p,8751).
+char(9,8752).
+char(4,8753).
+char(5,8754).
+char(3,8755).
+char(c,8756).
+char(c,8757).
+char(c,8758).
+char(m,8759).
+char(5,8760).
+char(1,8761).
+char(0,8762).
+char(6,8763).
+char(m,8764).
+char(8,8765).
+char(1,8766).
+char(1,8767).
+char(7,8768).
+char(c,8769).
+char(c,8770).
+char(p,8771).
+char(2,8772).
+char(6,8773).
+char(6,8774).
+char(3,8775).
+char(m,8776).
+char(o,8777).
+char(m,8778).
+char(o,8779).
+char(p,8780).
+char(6,8781).
+char(3,8782).
+char(1,8783).
+char(4,8784).
+char(c,8785).
+char(c,8786).
+char(c,8787).
+char(c,8788).
+char(p,8789).
+char(o,8790).
+char(m,8791).
+char(o,8792).
+char(m,8793).
+char(3,8794).
+char(4,8795).
+char(7,8796).
+char(3,8797).
+char(c,8798).
+char(c,8799).
+char(p,8800).
+char(o,8801).
+char(m,8802).
+char(o,8803).
+char(p,8804).
+char(o,8805).
+char(m,8806).
+char(o,8807).
+char(p,8808).
+char(o,8809).
+char(p,8810).
+char(o,8811).
+char(6,8812).
+char(0,8813).
+char(2,8814).
+char(3,8815).
+char(c,8816).
+char(m,8817).
+char(6,8818).
+char(2,8819).
+char(5,8820).
+char(5,8821).
+char(c,8822).
+char(p,8823).
+char(o,8824).
+char(p,8825).
+char(5,8826).
+char(2,8827).
+char(8,8828).
+char(0,8829).
+char(p,8830).
+char(5,8831).
+char(1,8832).
+char(2,8833).
+char(8,8834).
+char(c,8835).
+char(c,8836).
+char(c,8837).
+char(c,8838).
+char(p,8839).
+char(o,8840).
+char(m,8841).
+char(o,8842).
+char(m,8843).
+char(o,8844).
+char(6,8845).
+char(4,8846).
+char(2,8847).
+char(5,8848).
+char(p,8849).
+char(3,8850).
+char(3,8851).
+char(3,8852).
+char(0,8853).
+char(p,8854).
+char(o,8855).
+char(p,8856).
+char(4,8857).
+char(6,8858).
+char(2,8859).
+char(m,8860).
+char(o,8861).
+char(m,8862).
+char(o,8863).
+char(p,8864).
+char(1,8865).
+char(5,8866).
+char(c,8867).
+char(c,8868).
+char(m,8869).
+char(4,8870).
+char(5,8871).
+char(5,8872).
+char(6,8873).
+char(c,8874).
+char(m,8875).
+char(o,8876).
+char(o,8877).
+char(m,8878).
+char(5,8879).
+char(2,8880).
+char(7,8881).
+char(6,8882).
+char(m,8883).
+char(6,8884).
+char(0,8885).
+char(1,8886).
+char(3,8887).
+char(p,8888).
+char(2,8889).
+char(7,8890).
+char(9,8891).
+char(9,8892).
+char(m,8893).
+char(4,8894).
+char(9,8895).
+char(9,8896).
+char(4,8897).
+char(c,8898).
+char(c,8899).
+char(c,8900).
+char(c,8901).
+char(c,8902).
+char(p,8903).
+char(2,8904).
+char(9,8905).
+char(0,8906).
+char(2,8907).
+char(c,8908).
+char(m,8909).
+char(6,8910).
+char(9,8911).
+char(1,8912).
+char(1,8913).
+char(c,8914).
+char(c,8915).
+char(c,8916).
+char(m,8917).
+char(7,8918).
+char(4,8919).
+char(6,8920).
+char(4,8921).
+char(m,8922).
+char(1,8923).
+char(4,8924).
+char(0,8925).
+char(6,8926).
+char(m,8927).
+char(8,8928).
+char(5,8929).
+char(6,8930).
+char(6,8931).
+char(c,8932).
+char(c,8933).
+char(p,8934).
+char(o,8935).
+char(m,8936).
+char(o,8937).
+char(p,8938).
+char(6,8939).
+char(2,8940).
+char(9,8941).
+char(5,8942).
+char(m,8943).
+char(o,8944).
+char(p,8945).
+char(o,8946).
+char(m,8947).
+char(4,8948).
+char(8,8949).
+char(3,8950).
+char(5,8951).
+char(c,8952).
+char(p,8953).
+char(o,8954).
+char(p,8955).
+char(1,8956).
+char(0,8957).
+char(0,8958).
+char(3,8959).
+char(c,8960).
+char(c,8961).
+char(p,8962).
+char(o,8963).
+char(m,8964).
+char(o,8965).
+char(o,8966).
+char(o,8967).
+char(m,8968).
+char(o,8969).
+char(m,8970).
+char(o,8971).
+char(m,8972).
+char(o,8973).
+char(m,8974).
+char(5,8975).
+char(3,8976).
+char(0,8977).
+char(1,8978).
+char(p,8979).
+char(4,8980).
+char(0,8981).
+char(8,8982).
+char(2,8983).
+char(c,8984).
+char(p,8985).
+char(o,8986).
+char(m,8987).
+char(3,8988).
+char(2,8989).
+char(9,8990).
+char(8,8991).
+char(m,8992).
+char(o,8993).
+char(o,8994).
+char(p,8995).
+char(2,8996).
+char(3,8997).
+char(1,8998).
+char(6,8999).
+char(m,9000).
+char(7,9001).
+char(5,9002).
+char(0,9003).
+char(9,9004).
+char(c,9005).
+char(p,9006).
+char(8,9007).
+char(8,9008).
+char(2,9009).
+char(0,9010).
+char(c,9011).
+char(p,9012).
+char(o,9013).
+char(4,9014).
+char(7,9015).
+char(2,9016).
+char(4,9017).
+char(c,9018).
+char(c,9019).
+char(c,9020).
+char(c,9021).
+char(c,9022).
+char(c,9023).
+char(m,9024).
+char(6,9025).
+char(5,9026).
+char(1,9027).
+char(1,9028).
+char(p,9029).
+char(o,9030).
+char(p,9031).
+char(o,9032).
+char(o,9033).
+char(p,9034).
+char(o,9035).
+char(m,9036).
+char(8,9037).
+char(8,9038).
+char(9,9039).
+char(9,9040).
+char(m,9041).
+char(o,9042).
+char(o,9043).
+char(7,9044).
+char(4,9045).
+char(6,9046).
+char(3,9047).
+char(c,9048).
+char(m,9049).
+char(o,9050).
+char(p,9051).
+char(1,9052).
+char(8,9053).
+char(7,9054).
+char(0,9055).
+char(p,9056).
+char(3,9057).
+char(9,9058).
+char(3,9059).
+char(4,9060).
+char(c,9061).
+char(p,9062).
+char(o,9063).
+char(3,9064).
+char(9,9065).
+char(1,9066).
+char(4,9067).
+char(m,9068).
+char(4,9069).
+char(5,9070).
+char(5,9071).
+char(9,9072).
+char(m,9073).
+char(o,9074).
+char(m,9075).
+char(o,9076).
+char(p,9077).
+char(8,9078).
+char(0,9079).
+char(3,9080).
+char(7,9081).
+char(c,9082).
+char(m,9083).
+char(8,9084).
+char(4,9085).
+char(7,9086).
+char(9,9087).
+char(c,9088).
+char(p,9089).
+char(9,9090).
+char(3,9091).
+char(2,9092).
+char(c,9093).
+char(p,9094).
+char(3,9095).
+char(2,9096).
+char(9,9097).
+char(2,9098).
+char(c,9099).
+char(m,9100).
+char(2,9101).
+char(7,9102).
+char(7,9103).
+char(3,9104).
+char(c,9105).
+char(c,9106).
+char(c,9107).
+char(p,9108).
+char(o,9109).
+char(m,9110).
+char(o,9111).
+char(m,9112).
+char(o,9113).
+char(m,9114).
+char(9,9115).
+char(2,9116).
+char(9,9117).
+char(1,9118).
+char(c,9119).
+char(c,9120).
+char(m,9121).
+char(o,9122).
+char(2,9123).
+char(4,9124).
+char(2,9125).
+char(2,9126).
+char(c,9127).
+char(c,9128).
+char(p,9129).
+char(9,9130).
+char(0,9131).
+char(8,9132).
+char(p,9133).
+char(o,9134).
+char(1,9135).
+char(4,9136).
+char(4,9137).
+char(2,9138).
+char(p,9139).
+char(3,9140).
+char(6,9141).
+char(7,9142).
+char(5,9143).
+char(m,9144).
+char(2,9145).
+char(8,9146).
+char(7,9147).
+char(7,9148).
+char(m,9149).
+char(9,9150).
+char(7,9151).
+char(1,9152).
+char(8,9153).
+char(c,9154).
+char(m,9155).
+char(o,9156).
+char(7,9157).
+char(2,9158).
+char(4,9159).
+char(3,9160).
+char(c,9161).
+char(p,9162).
+char(4,9163).
+char(8,9164).
+char(5,9165).
+char(4,9166).
+char(p,9167).
+char(o,9168).
+char(m,9169).
+char(2,9170).
+char(7,9171).
+char(4,9172).
+char(5,9173).
+char(c,9174).
+char(m,9175).
+char(o,9176).
+char(p,9177).
+char(5,9178).
+char(4,9179).
+char(1,9180).
+char(7,9181).
+char(m,9182).
+char(4,9183).
+char(7,9184).
+char(8,9185).
+char(c,9186).
+char(c,9187).
+char(p,9188).
+char(7,9189).
+char(3,9190).
+char(5,9191).
+char(6,9192).
+char(m,9193).
+char(o,9194).
+char(m,9195).
+char(7,9196).
+char(0,9197).
+char(9,9198).
+char(2,9199).
+char(p,9200).
+char(1,9201).
+char(5,9202).
+char(5,9203).
+char(2,9204).
+char(p,9205).
+char(8,9206).
+char(0,9207).
+char(2,9208).
+char(3,9209).
+char(p,9210).
+char(o,9211).
+char(m,9212).
+char(8,9213).
+char(1,9214).
+char(9,9215).
+char(2,9216).
+char(c,9217).
+char(m,9218).
+char(8,9219).
+char(1,9220).
+char(2,9221).
+char(3,9222).
+char(c,9223).
+char(c,9224).
+char(c,9225).
+char(c,9226).
+char(c,9227).
+char(c,9228).
+char(m,9229).
+char(o,9230).
+char(p,9231).
+char(7,9232).
+char(3,9233).
+char(3,9234).
+char(2,9235).
+char(c,9236).
+char(p,9237).
+char(o,9238).
+char(m,9239).
+char(o,9240).
+char(m,9241).
+char(8,9242).
+char(9,9243).
+char(5,9244).
+char(0,9245).
+char(c,9246).
+char(p,9247).
+char(1,9248).
+char(0,9249).
+char(3,9250).
+char(2,9251).
+char(p,9252).
+char(7,9253).
+char(6,9254).
+char(6,9255).
+char(1,9256).
+char(m,9257).
+char(9,9258).
+char(4,9259).
+char(6,9260).
+char(9,9261).
+char(m,9262).
+char(5,9263).
+char(2,9264).
+char(0,9265).
+char(1,9266).
+char(m,9267).
+char(2,9268).
+char(8,9269).
+char(2,9270).
+char(6,9271).
+char(c,9272).
+char(c,9273).
+char(c,9274).
+char(m,9275).
+char(o,9276).
+char(o,9277).
+char(p,9278).
+char(o,9279).
+char(p,9280).
+char(6,9281).
+char(8,9282).
+char(1,9283).
+char(1,9284).
+char(p,9285).
+char(o,9286).
+char(p,9287).
+char(6,9288).
+char(3,9289).
+char(7,9290).
+char(5,9291).
+char(c,9292).
+char(m,9293).
+char(o,9294).
+char(o,9295).
+char(p,9296).
+char(1,9297).
+char(9,9298).
+char(5,9299).
+char(1,9300).
+char(c,9301).
+char(m,9302).
+char(o,9303).
+char(m,9304).
+char(o,9305).
+char(m,9306).
+char(2,9307).
+char(6,9308).
+char(5,9309).
+char(3,9310).
+char(p,9311).
+char(4,9312).
+char(9,9313).
+char(0,9314).
+char(7,9315).
+char(m,9316).
+char(8,9317).
+char(8,9318).
+char(1,9319).
+char(8,9320).
+char(c,9321).
+char(c,9322).
+char(p,9323).
+char(1,9324).
+char(8,9325).
+char(1,9326).
+char(7,9327).
+char(c,9328).
+char(c,9329).
+char(m,9330).
+char(8,9331).
+char(1,9332).
+char(7,9333).
+char(7,9334).
+char(m,9335).
+char(1,9336).
+char(3,9337).
+char(0,9338).
+char(7,9339).
+char(p,9340).
+char(o,9341).
+char(3,9342).
+char(4,9343).
+char(8,9344).
+char(1,9345).
+char(m,9346).
+char(2,9347).
+char(0,9348).
+char(5,9349).
+char(7,9350).
+char(c,9351).
+char(p,9352).
+char(o,9353).
+char(p,9354).
+char(8,9355).
+char(6,9356).
+char(5,9357).
+char(3,9358).
+char(p,9359).
+char(o,9360).
+char(m,9361).
+char(4,9362).
+char(7,9363).
+char(3,9364).
+char(9,9365).
+char(c,9366).
+char(p,9367).
+char(o,9368).
+char(m,9369).
+char(o,9370).
+char(9,9371).
+char(0,9372).
+char(9,9373).
+char(7,9374).
+char(p,9375).
+char(o,9376).
+char(p,9377).
+char(o,9378).
+char(p,9379).
+char(3,9380).
+char(5,9381).
+char(6,9382).
+char(4,9383).
+char(m,9384).
+char(7,9385).
+char(9,9386).
+char(8,9387).
+char(6,9388).
+char(c,9389).
+char(m,9390).
+char(o,9391).
+char(o,9392).
+char(5,9393).
+char(7,9394).
+char(0,9395).
+char(0,9396).
+char(m,9397).
+char(o,9398).
+char(o,9399).
+char(m,9400).
+char(9,9401).
+char(2,9402).
+char(1,9403).
+char(1,9404).
+char(p,9405).
+char(o,9406).
+char(p,9407).
+char(8,9408).
+char(8,9409).
+char(9,9410).
+char(9,9411).
+char(c,9412).
+char(c,9413).
+char(c,9414).
+char(m,9415).
+char(7,9416).
+char(6,9417).
+char(4,9418).
+char(m,9419).
+char(o,9420).
+char(7,9421).
+char(5,9422).
+char(3,9423).
+char(c,9424).
+char(p,9425).
+char(o,9426).
+char(p,9427).
+char(o,9428).
+char(m,9429).
+char(o,9430).
+char(o,9431).
+char(m,9432).
+char(2,9433).
+char(8,9434).
+char(7,9435).
+char(6,9436).
+char(c,9437).
+char(c,9438).
+char(m,9439).
+char(9,9440).
+char(2,9441).
+char(5,9442).
+char(5,9443).
+char(c,9444).
+char(c,9445).
+char(c,9446).
+char(c,9447).
+char(m,9448).
+char(o,9449).
+char(p,9450).
+char(3,9451).
+char(1,9452).
+char(7,9453).
+char(3,9454).
+char(c,9455).
+char(p,9456).
+char(3,9457).
+char(6,9458).
+char(6,9459).
+char(5,9460).
+char(c,9461).
+char(c,9462).
+char(c,9463).
+char(p,9464).
+char(3,9465).
+char(7,9466).
+char(7,9467).
+char(m,9468).
+char(4,9469).
+char(5,9470).
+char(8,9471).
+char(9,9472).
+char(p,9473).
+char(o,9474).
+char(o,9475).
+char(3,9476).
+char(4,9477).
+char(6,9478).
+char(3,9479).
+char(m,9480).
+char(o,9481).
+char(p,9482).
+char(5,9483).
+char(7,9484).
+char(1,9485).
+char(5,9486).
+char(p,9487).
+char(9,9488).
+char(8,9489).
+char(8,9490).
+char(0,9491).
+char(c,9492).
+char(c,9493).
+char(m,9494).
+char(5,9495).
+char(6,9496).
+char(4,9497).
+char(c,9498).
+char(p,9499).
+char(5,9500).
+char(3,9501).
+char(8,9502).
+char(0,9503).
+char(p,9504).
+char(3,9505).
+char(7,9506).
+char(2,9507).
+char(3,9508).
+char(m,9509).
+char(1,9510).
+char(5,9511).
+char(4,9512).
+char(3,9513).
+char(c,9514).
+char(c,9515).
+char(c,9516).
+char(c,9517).
+char(c,9518).
+char(p,9519).
+char(1,9520).
+char(9,9521).
+char(9,9522).
+char(c,9523).
+char(c,9524).
+char(m,9525).
+char(o,9526).
+char(p,9527).
+char(8,9528).
+char(6,9529).
+char(8,9530).
+char(0,9531).
+char(c,9532).
+char(p,9533).
+char(o,9534).
+char(p,9535).
+char(2,9536).
+char(6,9537).
+char(7,9538).
+char(1,9539).
+char(p,9540).
+char(2,9541).
+char(6,9542).
+char(7,9543).
+char(2,9544).
+char(p,9545).
+char(o,9546).
+char(p,9547).
+char(o,9548).
+char(o,9549).
+char(6,9550).
+char(1,9551).
+char(6,9552).
+char(6,9553).
+char(p,9554).
+char(5,9555).
+char(9,9556).
+char(0,9557).
+char(3,9558).
+char(m,9559).
+char(3,9560).
+char(4,9561).
+char(2,9562).
+char(7,9563).
+char(c,9564).
+char(m,9565).
+char(1,9566).
+char(7,9567).
+char(4,9568).
+char(3,9569).
+char(c,9570).
+char(p,9571).
+char(1,9572).
+char(2,9573).
+char(6,9574).
+char(7,9575).
+char(c,9576).
+char(c,9577).
+char(m,9578).
+char(o,9579).
+char(1,9580).
+char(3,9581).
+char(6,9582).
+char(6,9583).
+char(m,9584).
+char(1,9585).
+char(1,9586).
+char(5,9587).
+char(5,9588).
+char(c,9589).
+char(c,9590).
+char(c,9591).
+char(c,9592).
+char(c,9593).
+char(m,9594).
+char(9,9595).
+char(0,9596).
+char(5,9597).
+char(9,9598).
+char(m,9599).
+char(o,9600).
+char(m,9601).
+char(7,9602).
+char(1,9603).
+char(2,9604).
+char(3,9605).
+char(c,9606).
+char(c,9607).
+char(c,9608).
+char(m,9609).
+char(o,9610).
+char(m,9611).
+char(2,9612).
+char(9,9613).
+char(4,9614).
+char(5,9615).
+char(m,9616).
+char(1,9617).
+char(2,9618).
+char(9,9619).
+char(7,9620).
+char(p,9621).
+char(7,9622).
+char(9,9623).
+char(m,9624).
+char(5,9625).
+char(3,9626).
+char(0,9627).
+char(c,9628).
+char(c,9629).
+char(m,9630).
+char(1,9631).
+char(5,9632).
+char(0,9633).
+char(1,9634).
+char(c,9635).
+char(m,9636).
+char(o,9637).
+char(p,9638).
+char(o,9639).
+char(p,9640).
+char(9,9641).
+char(1,9642).
+char(4,9643).
+char(8,9644).
+char(c,9645).
+char(c,9646).
+char(c,9647).
+char(c,9648).
+char(m,9649).
+char(3,9650).
+char(1,9651).
+char(4,9652).
+char(2,9653).
+char(m,9654).
+char(o,9655).
+char(p,9656).
+char(o,9657).
+char(p,9658).
+char(8,9659).
+char(6,9660).
+char(9,9661).
+char(8,9662).
+char(p,9663).
+char(o,9664).
+char(p,9665).
+char(6,9666).
+char(3,9667).
+char(9,9668).
+char(0,9669).
+char(c,9670).
+char(c,9671).
+char(m,9672).
+char(o,9673).
+char(m,9674).
+char(6,9675).
+char(3,9676).
+char(4,9677).
+char(2,9678).
+char(p,9679).
+char(o,9680).
+char(8,9681).
+char(4,9682).
+char(3,9683).
+char(2,9684).
+char(m,9685).
+char(o,9686).
+char(p,9687).
+char(5,9688).
+char(7,9689).
+char(3,9690).
+char(8,9691).
+char(p,9692).
+char(o,9693).
+char(m,9694).
+char(o,9695).
+char(m,9696).
+char(9,9697).
+char(9,9698).
+char(6,9699).
+char(6,9700).
+char(m,9701).
+char(o,9702).
+char(p,9703).
+char(6,9704).
+char(1,9705).
+char(0,9706).
+char(9,9707).
+char(p,9708).
+char(2,9709).
+char(5,9710).
+char(2,9711).
+char(4,9712).
+char(p,9713).
+char(o,9714).
+char(p,9715).
+char(o,9716).
+char(m,9717).
+char(o,9718).
+char(p,9719).
+char(4,9720).
+char(3,9721).
+char(9,9722).
+char(5,9723).
+char(c,9724).
+char(p,9725).
+char(o,9726).
+char(o,9727).
+char(m,9728).
+char(3,9729).
+char(6,9730).
+char(0,9731).
+char(7,9732).
+char(p,9733).
+char(o,9734).
+char(p,9735).
+char(2,9736).
+char(0,9737).
+char(2,9738).
+char(7,9739).
+char(m,9740).
+char(1,9741).
+char(2,9742).
+char(4,9743).
+char(0,9744).
+char(p,9745).
+char(8,9746).
+char(2,9747).
+char(4,9748).
+char(2,9749).
+char(c,9750).
+char(c,9751).
+char(c,9752).
+char(p,9753).
+char(o,9754).
+char(m,9755).
+char(7,9756).
+char(7,9757).
+char(4,9758).
+char(7,9759).
+char(c,9760).
+char(p,9761).
+char(8,9762).
+char(6,9763).
+char(8,9764).
+char(4,9765).
+char(c,9766).
+char(p,9767).
+char(o,9768).
+char(o,9769).
+char(o,9770).
+char(5,9771).
+char(9,9772).
+char(9,9773).
+char(5,9774).
+char(m,9775).
+char(2,9776).
+char(7,9777).
+char(8,9778).
+char(p,9779).
+char(8,9780).
+char(8,9781).
+char(7,9782).
+char(2,9783).
+char(p,9784).
+char(4,9785).
+char(8,9786).
+char(4,9787).
+char(2,9788).
+char(p,9789).
+char(o,9790).
+char(p,9791).
+char(4,9792).
+char(2,9793).
+char(9,9794).
+char(c,9795).
+char(c,9796).
+char(m,9797).
+char(2,9798).
+char(6,9799).
+char(5,9800).
+char(4,9801).
+char(m,9802).
+char(o,9803).
+char(m,9804).
+char(1,9805).
+char(9,9806).
+char(9,9807).
+char(3,9808).
+char(c,9809).
+char(p,9810).
+char(5,9811).
+char(5,9812).
+char(0,9813).
+char(5,9814).
+char(c,9815).
+char(m,9816).
+char(2,9817).
+char(0,9818).
+char(5,9819).
+char(2,9820).
+char(m,9821).
+char(1,9822).
+char(4,9823).
+char(8,9824).
+char(m,9825).
+char(o,9826).
+char(p,9827).
+char(9,9828).
+char(1,9829).
+char(4,9830).
+char(1,9831).
+char(c,9832).
+char(p,9833).
+char(8,9834).
+char(4,9835).
+char(5,9836).
+char(p,9837).
+char(2,9838).
+char(9,9839).
+char(6,9840).
+char(6,9841).
+char(p,9842).
+char(5,9843).
+char(5,9844).
+char(8,9845).
+char(1,9846).
+char(p,9847).
+char(9,9848).
+char(0,9849).
+char(5,9850).
+char(6,9851).
+char(c,9852).
+char(c,9853).
+char(c,9854).
+char(m,9855).
+char(1,9856).
+char(6,9857).
+char(4,9858).
+char(2,9859).
+char(c,9860).
+char(p,9861).
+char(3,9862).
+char(4,9863).
+char(0,9864).
+char(m,9865).
+char(o,9866).
+char(m,9867).
+char(o,9868).
+char(o,9869).
+char(o,9870).
+char(1,9871).
+char(3,9872).
+char(5,9873).
+char(9,9874).
+char(m,9875).
+char(o,9876).
+char(p,9877).
+char(7,9878).
+char(6,9879).
+char(2,9880).
+char(2,9881).
+char(p,9882).
+char(o,9883).
+char(3,9884).
+char(2,9885).
+char(0,9886).
+char(2,9887).
+char(m,9888).
+char(6,9889).
+char(2,9890).
+char(9,9891).
+char(4,9892).
+char(c,9893).
+char(c,9894).
+char(c,9895).
+char(c,9896).
+char(c,9897).
+char(c,9898).
+char(p,9899).
+char(5,9900).
+char(6,9901).
+char(2,9902).
+char(0,9903).
+char(c,9904).
+char(m,9905).
+char(o,9906).
+char(p,9907).
+char(7,9908).
+char(9,9909).
+char(8,9910).
+char(c,9911).
+char(c,9912).
+char(m,9913).
+char(1,9914).
+char(3,9915).
+char(7,9916).
+char(8,9917).
+char(c,9918).
+char(c,9919).
+char(m,9920).
+char(8,9921).
+char(9,9922).
+char(8,9923).
+char(9,9924).
+char(c,9925).
+char(c,9926).
+char(c,9927).
+char(m,9928).
+char(o,9929).
+char(p,9930).
+char(o,9931).
+char(p,9932).
+char(o,9933).
+char(m,9934).
+char(9,9935).
+char(8,9936).
+char(7,9937).
+char(2,9938).
+char(c,9939).
+char(m,9940).
+char(4,9941).
+char(9,9942).
+char(3,9943).
+char(7,9944).
+char(c,9945).
+char(p,9946).
+char(8,9947).
+char(5,9948).
+char(5,9949).
+char(7,9950).
+char(c,9951).
+char(p,9952).
+char(7,9953).
+char(5,9954).
+char(3,9955).
+char(4,9956).
+char(c,9957).
+char(m,9958).
+char(o,9959).
+char(m,9960).
+char(3,9961).
+char(6,9962).
+char(7,9963).
+char(9,9964).
+char(m,9965).
+char(o,9966).
+char(m,9967).
+char(o,9968).
+char(7,9969).
+char(2,9970).
+char(0,9971).
+char(8,9972).
+char(c,9973).
+char(m,9974).
+char(6,9975).
+char(0,9976).
+char(0,9977).
+char(p,9978).
+char(3,9979).
+char(2,9980).
+char(8,9981).
+char(m,9982).
+char(o,9983).
+char(m,9984).
+char(8,9985).
+char(0,9986).
+char(9,9987).
+char(m,9988).
+char(o,9989).
+char(m,9990).
+char(3,9991).
+char(5,9992).
+char(2,9993).
+char(5,9994).
+char(m,9995).
+char(3,9996).
+char(6,9997).
+char(2,9998).
+char(3,9999).
+char(c,10000).
+char(m,10001).
+char(2,10002).
+char(4,10003).
+char(7,10004).
+char(p,10005).
+char(8,10006).
+char(7,10007).
+char(8,10008).
+char(3,10009).
+char(p,10010).
+char(4,10011).
+char(2,10012).
+char(2,10013).
+char(c,10014).
+char(c,10015).
+char(m,10016).
+char(o,10017).
+char(m,10018).
+char(o,10019).
+char(o,10020).
+char(o,10021).
+char(p,10022).
+char(o,10023).
+char(p,10024).
+char(4,10025).
+char(2,10026).
+char(1,10027).
+char(8,10028).
+char(p,10029).
+char(9,10030).
+char(7,10031).
+char(2,10032).
+char(9,10033).
+char(p,10034).
+char(7,10035).
+char(8,10036).
+char(4,10037).
+char(8,10038).
+char(c,10039).
+char(m,10040).
+char(o,10041).
+char(m,10042).
+char(o,10043).
+char(p,10044).
+char(o,10045).
+char(o,10046).
+char(p,10047).
+char(6,10048).
+char(0,10049).
+char(4,10050).
+char(6,10051).
+char(c,10052).
+char(m,10053).
+char(6,10054).
+char(3,10055).
+char(8,10056).
+char(4,10057).
+char(m,10058).
+char(o,10059).
+char(p,10060).
+char(o,10061).
+char(m,10062).
+char(1,10063).
+char(5,10064).
+char(4,10065).
+char(7,10066).
+char(m,10067).
+char(o,10068).
+char(p,10069).
+char(3,10070).
+char(0,10071).
+char(3,10072).
+char(9,10073).
+char(m,10074).
+char(2,10075).
+char(5,10076).
+char(8,10077).
+char(8,10078).
+char(m,10079).
+char(9,10080).
+char(9,10081).
+char(6,10082).
+char(c,10083).
+char(c,10084).
+char(m,10085).
+char(o,10086).
+char(p,10087).
+char(o,10088).
+char(o,10089).
+char(p,10090).
+char(o,10091).
+char(p,10092).
+char(o,10093).
+char(o,10094).
+char(m,10095).
+char(o,10096).
+char(o,10097).
+char(p,10098).
+char(7,10099).
+char(2,10100).
+char(6,10101).
+char(7,10102).
+char(m,10103).
+char(o,10104).
+char(o,10105).
+char(p,10106).
+char(9,10107).
+char(7,10108).
+char(8,10109).
+char(1,10110).
+char(m,10111).
+char(o,10112).
+char(p,10113).
+char(1,10114).
+char(7,10115).
+char(7,10116).
+char(1,10117).
+char(c,10118).
+char(m,10119).
+char(5,10120).
+char(9,10121).
+char(6,10122).
+char(0,10123).
+char(p,10124).
+char(4,10125).
+char(2,10126).
+char(0,10127).
+char(8,10128).
+char(c,10129).
+char(c,10130).
+char(p,10131).
+char(9,10132).
+char(0,10133).
+char(1,10134).
+char(5,10135).
+char(m,10136).
+char(6,10137).
+char(5,10138).
+char(8,10139).
+char(1,10140).
+char(p,10141).
+char(o,10142).
+char(p,10143).
+char(4,10144).
+char(3,10145).
+char(8,10146).
+char(3,10147).
+char(c,10148).
+char(p,10149).
+char(o,10150).
+char(p,10151).
+char(o,10152).
+char(7,10153).
+char(2,10154).
+char(9,10155).
+char(0,10156).
+char(m,10157).
+char(8,10158).
+char(0,10159).
+char(4,10160).
+char(1,10161).
+char(p,10162).
+char(o,10163).
+char(p,10164).
+char(5,10165).
+char(4,10166).
+char(2,10167).
+char(7,10168).
+char(c,10169).
+char(c,10170).
+char(c,10171).
+char(c,10172).
+char(c,10173).
+char(p,10174).
+char(o,10175).
+char(p,10176).
+char(o,10177).
+char(m,10178).
+char(3,10179).
+char(3,10180).
+char(5,10181).
+char(2,10182).
+char(p,10183).
+char(o,10184).
+char(o,10185).
+char(p,10186).
+char(6,10187).
+char(1,10188).
+char(8,10189).
+char(2,10190).
+char(c,10191).
+char(p,10192).
+char(o,10193).
+char(m,10194).
+char(9,10195).
+char(9,10196).
+char(7,10197).
+char(0,10198).
+char(p,10199).
+char(o,10200).
+char(m,10201).
+char(o,10202).
+char(3,10203).
+char(9,10204).
+char(3,10205).
+char(8,10206).
+char(c,10207).
+char(p,10208).
+char(o,10209).
+char(p,10210).
+char(o,10211).
+char(o,10212).
+char(p,10213).
+char(9,10214).
+char(8,10215).
+char(5,10216).
+char(6,10217).
+char(c,10218).
+char(m,10219).
+char(6,10220).
+char(1,10221).
+char(5,10222).
+char(4,10223).
+char(c,10224).
+char(p,10225).
+char(4,10226).
+char(3,10227).
+char(4,10228).
+char(9,10229).
+char(c,10230).
+char(c,10231).
+char(c,10232).
+char(p,10233).
+char(6,10234).
+char(0,10235).
+char(2,10236).
+char(6,10237).
+char(c,10238).
+char(m,10239).
+char(4,10240).
+char(3,10241).
+char(1,10242).
+char(4,10243).
+char(m,10244).
+char(o,10245).
+char(8,10246).
+char(0,10247).
+char(0,10248).
+char(0,10249).
+char(c,10250).
+char(m,10251).
+char(o,10252).
+char(o,10253).
+char(4,10254).
+char(6,10255).
+char(8,10256).
+char(4,10257).
+char(c,10258).
+char(p,10259).
+char(o,10260).
+char(m,10261).
+char(o,10262).
+char(m,10263).
+char(7,10264).
+char(2,10265).
+char(1,10266).
+char(8,10267).
+char(c,10268).
+char(c,10269).
+char(m,10270).
+char(o,10271).
+char(6,10272).
+char(3,10273).
+char(0,10274).
+char(1,10275).
+char(m,10276).
+char(o,10277).
+char(p,10278).
+char(o,10279).
+char(p,10280).
+char(1,10281).
+char(7,10282).
+char(2,10283).
+char(1,10284).
+char(c,10285).
+char(c,10286).
+char(m,10287).
+char(o,10288).
+char(p,10289).
+char(5,10290).
+char(1,10291).
+char(4,10292).
+char(4,10293).
+char(p,10294).
+char(4,10295).
+char(3,10296).
+char(9,10297).
+char(3,10298).
+char(c,10299).
+char(c,10300).
+char(m,10301).
+char(o,10302).
+char(1,10303).
+char(5,10304).
+char(4,10305).
+char(6,10306).
+char(c,10307).
+char(c,10308).
+char(p,10309).
+char(o,10310).
+char(p,10311).
+char(o,10312).
+char(p,10313).
+char(6,10314).
+char(4,10315).
+char(2,10316).
+char(0,10317).
+char(p,10318).
+char(o,10319).
+char(p,10320).
+char(5,10321).
+char(1,10322).
+char(8,10323).
+char(1,10324).
+char(p,10325).
+char(6,10326).
+char(6,10327).
+char(4,10328).
+char(2,10329).
+char(m,10330).
+char(o,10331).
+char(9,10332).
+char(9,10333).
+char(7,10334).
+char(9,10335).
+char(c,10336).
+char(c,10337).
+char(c,10338).
+char(m,10339).
+char(o,10340).
+char(p,10341).
+char(o,10342).
+char(p,10343).
+char(o,10344).
+char(m,10345).
+char(5,10346).
+char(3,10347).
+char(4,10348).
+char(0,10349).
+char(c,10350).
+char(c,10351).
+char(m,10352).
+char(1,10353).
+char(4,10354).
+char(0,10355).
+char(0,10356).
+char(m,10357).
+char(o,10358).
+char(o,10359).
+char(m,10360).
+char(2,10361).
+char(0,10362).
+char(8,10363).
+char(c,10364).
+char(c,10365).
+char(c,10366).
+char(c,10367).
+char(m,10368).
+char(o,10369).
+char(p,10370).
+char(2,10371).
+char(6,10372).
+char(8,10373).
+char(8,10374).
+char(c,10375).
+char(c,10376).
+char(p,10377).
+char(o,10378).
+char(p,10379).
+char(1,10380).
+char(1,10381).
+char(8,10382).
+char(c,10383).
+char(c,10384).
+char(p,10385).
+char(o,10386).
+char(p,10387).
+char(o,10388).
+char(o,10389).
+char(o,10390).
+char(p,10391).
+char(o,10392).
+char(o,10393).
+char(m,10394).
+char(2,10395).
+char(2,10396).
+char(5,10397).
+char(c,10398).
+char(c,10399).
+char(m,10400).
+char(3,10401).
+char(7,10402).
+char(7,10403).
+char(8,10404).
+char(p,10405).
+char(6,10406).
+char(2,10407).
+char(7,10408).
+char(8,10409).
+char(m,10410).
+char(2,10411).
+char(6,10412).
+char(9,10413).
+char(7,10414).
+char(m,10415).
+char(o,10416).
+char(m,10417).
+char(7,10418).
+char(9,10419).
+char(2,10420).
+char(9,10421).
+char(m,10422).
+char(o,10423).
+char(m,10424).
+char(o,10425).
+char(p,10426).
+char(7,10427).
+char(4,10428).
+char(7,10429).
+char(0,10430).
+char(c,10431).
+char(m,10432).
+char(6,10433).
+char(5,10434).
+char(8,10435).
+char(6,10436).
+char(p,10437).
+char(8,10438).
+char(0,10439).
+char(m,10440).
+char(o,10441).
+char(m,10442).
+char(2,10443).
+char(8,10444).
+char(7,10445).
+char(p,10446).
+char(3,10447).
+char(2,10448).
+char(4,10449).
+char(4,10450).
+char(m,10451).
+char(6,10452).
+char(3,10453).
+char(7,10454).
+char(6,10455).
+char(c,10456).
+char(c,10457).
+char(c,10458).
+char(c,10459).
+char(p,10460).
+char(5,10461).
+char(0,10462).
+char(3,10463).
+char(2,10464).
+char(p,10465).
+char(o,10466).
+char(m,10467).
+char(o,10468).
+char(p,10469).
+char(4,10470).
+char(5,10471).
+char(2,10472).
+char(3,10473).
+char(m,10474).
+char(o,10475).
+char(m,10476).
+char(o,10477).
+char(m,10478).
+char(6,10479).
+char(8,10480).
+char(8,10481).
+char(1,10482).
+char(p,10483).
+char(o,10484).
+char(9,10485).
+char(1,10486).
+char(6,10487).
+char(3,10488).
+char(m,10489).
+char(o,10490).
+char(p,10491).
+char(4,10492).
+char(0,10493).
+char(5,10494).
+char(0,10495).
+char(c,10496).
+char(c,10497).
+char(c,10498).
+char(c,10499).
+char(c,10500).
+char(c,10501).
+char(c,10502).
+char(p,10503).
+char(1,10504).
+char(7,10505).
+char(2,10506).
+char(3,10507).
+char(m,10508).
+char(9,10509).
+char(5,10510).
+char(4,10511).
+char(6,10512).
+char(m,10513).
+char(o,10514).
+char(p,10515).
+char(2,10516).
+char(9,10517).
+char(6,10518).
+char(9,10519).
+char(c,10520).
+char(p,10521).
+char(o,10522).
+char(6,10523).
+char(8,10524).
+char(3,10525).
+char(2,10526).
+char(p,10527).
+char(o,10528).
+char(m,10529).
+char(7,10530).
+char(1,10531).
+char(1,10532).
+char(8,10533).
+char(m,10534).
+char(2,10535).
+char(0,10536).
+char(1,10537).
+char(1,10538).
+char(c,10539).
+char(c,10540).
+char(p,10541).
+char(2,10542).
+char(3,10543).
+char(8,10544).
+char(4,10545).
+char(p,10546).
+char(o,10547).
+char(p,10548).
+char(o,10549).
+char(o,10550).
+char(m,10551).
+char(1,10552).
+char(9,10553).
+char(1,10554).
+char(8,10555).
+char(c,10556).
+char(p,10557).
+char(o,10558).
+char(p,10559).
+char(o,10560).
+char(p,10561).
+char(1,10562).
+char(2,10563).
+char(0,10564).
+char(1,10565).
+char(c,10566).
+char(c,10567).
+char(m,10568).
+char(o,10569).
+char(9,10570).
+char(5,10571).
+char(0,10572).
+char(c,10573).
+char(p,10574).
+char(1,10575).
+char(9,10576).
+char(8,10577).
+char(6,10578).
+char(m,10579).
+char(o,10580).
+char(p,10581).
+char(3,10582).
+char(8,10583).
+char(6,10584).
+char(6,10585).
+char(c,10586).
+char(c,10587).
+char(m,10588).
+char(o,10589).
+char(p,10590).
+char(o,10591).
+char(o,10592).
+char(m,10593).
+char(6,10594).
+char(2,10595).
+char(7,10596).
+char(5,10597).
+char(c,10598).
+char(m,10599).
+char(2,10600).
+char(4,10601).
+char(3,10602).
+char(0,10603).
+char(c,10604).
+char(c,10605).
+char(m,10606).
+char(o,10607).
+char(m,10608).
+char(o,10609).
+char(m,10610).
+char(6,10611).
+char(5,10612).
+char(2,10613).
+char(0,10614).
+char(c,10615).
+char(p,10616).
+char(o,10617).
+char(m,10618).
+char(o,10619).
+char(o,10620).
+char(o,10621).
+char(p,10622).
+char(o,10623).
+char(5,10624).
+char(0,10625).
+char(0,10626).
+char(9,10627).
+char(c,10628).
+char(m,10629).
+char(o,10630).
+char(o,10631).
+char(1,10632).
+char(9,10633).
+char(2,10634).
+char(c,10635).
+char(c,10636).
+char(m,10637).
+char(o,10638).
+char(o,10639).
+char(o,10640).
+char(p,10641).
+char(2,10642).
+char(9,10643).
+char(8,10644).
+char(2,10645).
+char(p,10646).
+char(o,10647).
+char(p,10648).
+char(3,10649).
+char(9,10650).
+char(0,10651).
+char(9,10652).
+char(c,10653).
+char(c,10654).
+char(m,10655).
+char(1,10656).
+char(9,10657).
+char(0,10658).
+char(1,10659).
+char(c,10660).
+char(m,10661).
+char(o,10662).
+char(p,10663).
+char(o,10664).
+char(m,10665).
+char(1,10666).
+char(7,10667).
+char(3,10668).
+char(2,10669).
+char(c,10670).
+char(c,10671).
+char(m,10672).
+char(o,10673).
+char(m,10674).
+char(2,10675).
+char(4,10676).
+char(9,10677).
+char(2,10678).
+char(c,10679).
+char(c,10680).
+char(c,10681).
+char(m,10682).
+char(8,10683).
+char(1,10684).
+char(9,10685).
+char(2,10686).
+char(c,10687).
+char(c,10688).
+char(p,10689).
+char(5,10690).
+char(0,10691).
+char(2,10692).
+char(9,10693).
+char(c,10694).
+char(c,10695).
+char(m,10696).
+char(2,10697).
+char(1,10698).
+char(2,10699).
+char(2,10700).
+char(c,10701).
+char(c,10702).
+char(c,10703).
+char(p,10704).
+char(o,10705).
+char(o,10706).
+char(9,10707).
+char(2,10708).
+char(8,10709).
+char(8,10710).
+char(c,10711).
+char(c,10712).
+char(c,10713).
+char(c,10714).
+char(c,10715).
+char(c,10716).
+char(c,10717).
+char(p,10718).
+char(4,10719).
+char(3,10720).
+char(3,10721).
+char(0,10722).
+char(m,10723).
+char(o,10724).
+char(o,10725).
+char(m,10726).
+char(o,10727).
+char(2,10728).
+char(3,10729).
+char(1,10730).
+char(6,10731).
+char(c,10732).
+char(p,10733).
+char(5,10734).
+char(4,10735).
+char(4,10736).
+char(0,10737).
+char(p,10738).
+char(o,10739).
+char(p,10740).
+char(o,10741).
+char(3,10742).
+char(7,10743).
+char(8,10744).
+char(3,10745).
+char(c,10746).
+char(c,10747).
+char(p,10748).
+char(1,10749).
+char(4,10750).
+char(9,10751).
+char(3,10752).
+char(p,10753).
+char(o,10754).
+char(p,10755).
+char(o,10756).
+char(m,10757).
+char(3,10758).
+char(7,10759).
+char(4,10760).
+char(5,10761).
+char(c,10762).
+char(m,10763).
+char(o,10764).
+char(p,10765).
+char(o,10766).
+char(m,10767).
+char(o,10768).
+char(p,10769).
+char(5,10770).
+char(9,10771).
+char(3,10772).
+char(1,10773).
+char(c,10774).
+char(p,10775).
+char(o,10776).
+char(6,10777).
+char(9,10778).
+char(5,10779).
+char(3,10780).
+char(m,10781).
+char(o,10782).
+char(o,10783).
+char(p,10784).
+char(4,10785).
+char(1,10786).
+char(4,10787).
+char(5,10788).
+char(m,10789).
+char(o,10790).
+char(o,10791).
+char(o,10792).
+char(p,10793).
+char(o,10794).
+char(m,10795).
+char(7,10796).
+char(9,10797).
+char(3,10798).
+char(5,10799).
+char(c,10800).
+char(m,10801).
+char(o,10802).
+char(2,10803).
+char(0,10804).
+char(3,10805).
+char(1,10806).
+char(c,10807).
+char(m,10808).
+char(o,10809).
+char(p,10810).
+char(4,10811).
+char(1,10812).
+char(6,10813).
+char(7,10814).
+char(c,10815).
+char(p,10816).
+char(4,10817).
+char(9,10818).
+char(9,10819).
+char(6,10820).
+char(p,10821).
+char(o,10822).
+char(p,10823).
+char(o,10824).
+char(p,10825).
+char(o,10826).
+char(o,10827).
+char(p,10828).
+char(8,10829).
+char(3,10830).
+char(7,10831).
+char(9,10832).
+char(c,10833).
+char(c,10834).
+char(p,10835).
+char(3,10836).
+char(2,10837).
+char(0,10838).
+char(8,10839).
+char(c,10840).
+char(c,10841).
+char(m,10842).
+char(o,10843).
+char(p,10844).
+char(5,10845).
+char(5,10846).
+char(6,10847).
+char(0,10848).
+char(c,10849).
+char(m,10850).
+char(7,10851).
+char(4,10852).
+char(6,10853).
+char(6,10854).
+char(c,10855).
+char(m,10856).
+char(3,10857).
+char(9,10858).
+char(8,10859).
+char(c,10860).
+char(c,10861).
+char(c,10862).
+char(p,10863).
+char(o,10864).
+char(9,10865).
+char(7,10866).
+char(8,10867).
+char(3,10868).
+char(c,10869).
+char(m,10870).
+char(o,10871).
+char(m,10872).
+char(7,10873).
+char(3,10874).
+char(4,10875).
+char(5,10876).
+char(p,10877).
+char(5,10878).
+char(2,10879).
+char(5,10880).
+char(p,10881).
+char(o,10882).
+char(o,10883).
+char(2,10884).
+char(4,10885).
+char(8,10886).
+char(0,10887).
+char(c,10888).
+char(m,10889).
+char(1,10890).
+char(2,10891).
+char(2,10892).
+char(0,10893).
+char(c,10894).
+char(c,10895).
+char(c,10896).
+char(c,10897).
+char(c,10898).
+char(c,10899).
+char(m,10900).
+char(o,10901).
+char(p,10902).
+char(3,10903).
+char(3,10904).
+char(7,10905).
+char(4,10906).
+char(c,10907).
+char(c,10908).
+char(p,10909).
+char(5,10910).
+char(3,10911).
+char(8,10912).
+char(5,10913).
+char(m,10914).
+char(o,10915).
+char(o,10916).
+char(m,10917).
+char(7,10918).
+char(4,10919).
+char(4,10920).
+char(1,10921).
+char(c,10922).
+char(p,10923).
+char(1,10924).
+char(2,10925).
+char(2,10926).
+char(8,10927).
+char(m,10928).
+char(5,10929).
+char(6,10930).
+char(5,10931).
+char(6,10932).
+char(c,10933).
+char(c,10934).
+char(c,10935).
+char(c,10936).
+char(m,10937).
+char(4,10938).
+char(9,10939).
+char(9,10940).
+char(6,10941).
+char(m,10942).
+char(3,10943).
+char(9,10944).
+char(9,10945).
+char(5,10946).
+char(c,10947).
+char(c,10948).
+char(c,10949).
+char(c,10950).
+char(m,10951).
+char(5,10952).
+char(8,10953).
+char(9,10954).
+char(6,10955).
+char(m,10956).
+char(o,10957).
+char(7,10958).
+char(8,10959).
+char(0,10960).
+char(7,10961).
+char(m,10962).
+char(o,10963).
+char(o,10964).
+char(m,10965).
+char(3,10966).
+char(5,10967).
+char(4,10968).
+char(7,10969).
+char(p,10970).
+char(9,10971).
+char(7,10972).
+char(3,10973).
+char(2,10974).
+char(p,10975).
+char(9,10976).
+char(0,10977).
+char(4,10978).
+char(1,10979).
+char(c,10980).
+char(c,10981).
+char(m,10982).
+char(8,10983).
+char(5,10984).
+char(0,10985).
+char(7,10986).
+char(m,10987).
+char(o,10988).
+char(p,10989).
+char(o,10990).
+char(p,10991).
+char(o,10992).
+char(m,10993).
+char(o,10994).
+char(p,10995).
+char(2,10996).
+char(9,10997).
+char(2,10998).
+char(9,10999).
+char(c,11000).
+char(m,11001).
+char(8,11002).
+char(9,11003).
+char(5,11004).
+char(3,11005).
+char(p,11006).
+char(o,11007).
+char(p,11008).
+char(3,11009).
+char(6,11010).
+char(6,11011).
+char(m,11012).
+char(o,11013).
+char(1,11014).
+char(2,11015).
+char(7,11016).
+char(c,11017).
+char(c,11018).
+char(c,11019).
+char(c,11020).
+char(c,11021).
+char(p,11022).
+char(3,11023).
+char(7,11024).
+char(3,11025).
+char(6,11026).
+char(c,11027).
+char(p,11028).
+char(2,11029).
+char(5,11030).
+char(8,11031).
+char(c,11032).
+char(m,11033).
+char(o,11034).
+char(o,11035).
+char(m,11036).
+char(o,11037).
+char(o,11038).
+char(m,11039).
+char(9,11040).
+char(9,11041).
+char(3,11042).
+char(2,11043).
+char(m,11044).
+char(o,11045).
+char(m,11046).
+char(8,11047).
+char(3,11048).
+char(3,11049).
+char(9,11050).
+char(m,11051).
+char(9,11052).
+char(5,11053).
+char(2,11054).
+char(6,11055).
+char(c,11056).
+char(c,11057).
+char(c,11058).
+char(c,11059).
+char(c,11060).
+char(c,11061).
+char(p,11062).
+char(8,11063).
+char(9,11064).
+char(9,11065).
+char(6,11066).
+char(c,11067).
+char(c,11068).
+char(p,11069).
+char(o,11070).
+char(p,11071).
+char(5,11072).
+char(6,11073).
+char(5,11074).
+char(3,11075).
+char(p,11076).
+char(o,11077).
+char(p,11078).
+char(5,11079).
+char(5,11080).
+char(2,11081).
+char(8,11082).
+char(m,11083).
+char(2,11084).
+char(1,11085).
+char(0,11086).
+char(5,11087).
+char(m,11088).
+char(o,11089).
+char(m,11090).
+char(o,11091).
+char(m,11092).
+char(4,11093).
+char(3,11094).
+char(7,11095).
+char(m,11096).
+char(7,11097).
+char(6,11098).
+char(3,11099).
+char(6,11100).
+char(c,11101).
+char(c,11102).
+char(p,11103).
+char(o,11104).
+char(p,11105).
+char(o,11106).
+char(m,11107).
+char(1,11108).
+char(9,11109).
+char(8,11110).
+char(5,11111).
+char(c,11112).
+char(p,11113).
+char(o,11114).
+char(7,11115).
+char(6,11116).
+char(4,11117).
+char(1,11118).
+char(m,11119).
+char(3,11120).
+char(2,11121).
+char(1,11122).
+char(7,11123).
+char(c,11124).
+char(m,11125).
+char(o,11126).
+char(m,11127).
+char(7,11128).
+char(0,11129).
+char(1,11130).
+char(5,11131).
+char(p,11132).
+char(o,11133).
+char(4,11134).
+char(2,11135).
+char(7,11136).
+char(8,11137).
+char(c,11138).
+char(p,11139).
+char(5,11140).
+char(6,11141).
+char(4,11142).
+char(8,11143).
+char(p,11144).
+char(6,11145).
+char(4,11146).
+char(2,11147).
+char(c,11148).
+char(m,11149).
+char(o,11150).
+char(m,11151).
+char(6,11152).
+char(9,11153).
+char(4,11154).
+char(5,11155).
+char(p,11156).
+char(o,11157).
+char(p,11158).
+char(5,11159).
+char(9,11160).
+char(5,11161).
+char(2,11162).
+char(p,11163).
+char(6,11164).
+char(5,11165).
+char(6,11166).
+char(c,11167).
+char(p,11168).
+char(6,11169).
+char(7,11170).
+char(3,11171).
+char(m,11172).
+char(5,11173).
+char(6,11174).
+char(6,11175).
+char(5,11176).
+char(c,11177).
+char(c,11178).
+char(p,11179).
+char(o,11180).
+char(o,11181).
+char(p,11182).
+char(o,11183).
+char(m,11184).
+char(o,11185).
+char(m,11186).
+char(8,11187).
+char(6,11188).
+char(5,11189).
+char(8,11190).
+char(c,11191).
+char(m,11192).
+char(4,11193).
+char(3,11194).
+char(2,11195).
+char(7,11196).
+char(p,11197).
+char(5,11198).
+char(3,11199).
+char(6,11200).
+char(5,11201).
+char(c,11202).
+char(p,11203).
+char(8,11204).
+char(0,11205).
+char(3,11206).
+char(0,11207).
+char(p,11208).
+char(o,11209).
+char(6,11210).
+char(1,11211).
+char(6,11212).
+char(5,11213).
+char(c,11214).
+char(p,11215).
+char(o,11216).
+char(p,11217).
+char(o,11218).
+char(p,11219).
+char(2,11220).
+char(0,11221).
+char(8,11222).
+char(3,11223).
+char(c,11224).
+char(p,11225).
+char(o,11226).
+char(m,11227).
+char(o,11228).
+char(5,11229).
+char(5,11230).
+char(0,11231).
+char(2,11232).
+char(c,11233).
+char(m,11234).
+char(8,11235).
+char(9,11236).
+char(4,11237).
+char(6,11238).
+char(m,11239).
+char(4,11240).
+char(8,11241).
+char(5,11242).
+char(3,11243).
+char(m,11244).
+char(o,11245).
+char(m,11246).
+char(5,11247).
+char(7,11248).
+char(8,11249).
+char(p,11250).
+char(o,11251).
+char(o,11252).
+char(o,11253).
+char(9,11254).
+char(5,11255).
+char(0,11256).
+char(2,11257).
+char(p,11258).
+char(o,11259).
+char(p,11260).
+char(1,11261).
+char(5,11262).
+char(7,11263).
+char(5,11264).
+char(p,11265).
+char(8,11266).
+char(3,11267).
+char(9,11268).
+char(5,11269).
+char(p,11270).
+char(o,11271).
+char(m,11272).
+char(2,11273).
+char(5,11274).
+char(5,11275).
+char(8,11276).
+char(c,11277).
+char(m,11278).
+char(4,11279).
+char(7,11280).
+char(7,11281).
+char(3,11282).
+char(m,11283).
+char(8,11284).
+char(2,11285).
+char(1,11286).
+char(c,11287).
+char(c,11288).
+char(p,11289).
+char(1,11290).
+char(9,11291).
+char(9,11292).
+char(5,11293).
+char(c,11294).
+char(m,11295).
+char(1,11296).
+char(1,11297).
+char(3,11298).
+char(1,11299).
+char(p,11300).
+char(1,11301).
+char(4,11302).
+char(7,11303).
+char(6,11304).
+char(m,11305).
+char(o,11306).
+char(p,11307).
+char(5,11308).
+char(1,11309).
+char(1,11310).
+char(7,11311).
+char(c,11312).
+char(c,11313).
+char(c,11314).
+char(m,11315).
+char(1,11316).
+char(2,11317).
+char(0,11318).
+char(6,11319).
+char(c,11320).
+char(m,11321).
+char(o,11322).
+char(m,11323).
+char(o,11324).
+char(m,11325).
+char(o,11326).
+char(p,11327).
+char(3,11328).
+char(0,11329).
+char(4,11330).
+char(9,11331).
+char(c,11332).
+char(c,11333).
+char(p,11334).
+char(o,11335).
+char(p,11336).
+char(o,11337).
+char(p,11338).
+char(8,11339).
+char(9,11340).
+char(7,11341).
+char(2,11342).
+char(p,11343).
+char(8,11344).
+char(4,11345).
+char(1,11346).
+char(1,11347).
+char(c,11348).
+char(c,11349).
+char(m,11350).
+char(7,11351).
+char(7,11352).
+char(5,11353).
+char(9,11354).
+char(p,11355).
+char(2,11356).
+char(1,11357).
+char(4,11358).
+char(6,11359).
+char(p,11360).
+char(7,11361).
+char(6,11362).
+char(9,11363).
+char(2,11364).
+char(m,11365).
+char(o,11366).
+char(m,11367).
+char(o,11368).
+char(p,11369).
+char(7,11370).
+char(8,11371).
+char(6,11372).
+char(1,11373).
+char(p,11374).
+char(o,11375).
+char(m,11376).
+char(o,11377).
+char(p,11378).
+char(3,11379).
+char(9,11380).
+char(0,11381).
+char(7,11382).
+char(c,11383).
+char(c,11384).
+char(c,11385).
+char(c,11386).
+char(p,11387).
+char(3,11388).
+char(6,11389).
+char(0,11390).
+char(0,11391).
+char(p,11392).
+char(o,11393).
+char(m,11394).
+char(o,11395).
+char(m,11396).
+char(7,11397).
+char(1,11398).
+char(6,11399).
+char(5,11400).
+char(p,11401).
+char(2,11402).
+char(7,11403).
+char(9,11404).
+char(7,11405).
+char(p,11406).
+char(1,11407).
+char(3,11408).
+char(6,11409).
+char(2,11410).
+char(c,11411).
+char(m,11412).
+char(o,11413).
+char(p,11414).
+char(o,11415).
+char(m,11416).
+char(o,11417).
+char(o,11418).
+char(o,11419).
+char(o,11420).
+char(m,11421).
+char(o,11422).
+char(m,11423).
+char(8,11424).
+char(7,11425).
+char(4,11426).
+char(8,11427).
+char(c,11428).
+char(p,11429).
+char(o,11430).
+char(m,11431).
+char(o,11432).
+char(p,11433).
+char(o,11434).
+char(7,11435).
+char(1,11436).
+char(7,11437).
+char(c,11438).
+char(c,11439).
+char(m,11440).
+char(o,11441).
+char(p,11442).
+char(o,11443).
+char(p,11444).
+char(3,11445).
+char(7,11446).
+char(8,11447).
+char(1,11448).
+char(m,11449).
+char(o,11450).
+char(p,11451).
+char(7,11452).
+char(1,11453).
+char(1,11454).
+char(8,11455).
+char(c,11456).
+char(c,11457).
+char(m,11458).
+char(o,11459).
+char(o,11460).
+char(m,11461).
+char(o,11462).
+char(8,11463).
+char(3,11464).
+char(0,11465).
+char(5,11466).
+char(p,11467).
+char(o,11468).
+char(m,11469).
+char(o,11470).
+char(4,11471).
+char(7,11472).
+char(1,11473).
+char(7,11474).
+char(c,11475).
+char(c,11476).
+char(m,11477).
+char(8,11478).
+char(7,11479).
+char(2,11480).
+char(4,11481).
+char(c,11482).
+char(c,11483).
+char(c,11484).
+char(c,11485).
+char(m,11486).
+char(o,11487).
+char(m,11488).
+char(5,11489).
+char(3,11490).
+char(9,11491).
+char(6,11492).
+char(c,11493).
+char(m,11494).
+char(o,11495).
+char(m,11496).
+char(3,11497).
+char(7,11498).
+char(6,11499).
+char(m,11500).
+char(o,11501).
+char(p,11502).
+char(o,11503).
+char(8,11504).
+char(3,11505).
+char(7,11506).
+char(7,11507).
+char(c,11508).
+char(c,11509).
+char(c,11510).
+char(c,11511).
+char(c,11512).
+char(p,11513).
+char(3,11514).
+char(1,11515).
+char(7,11516).
+char(8,11517).
+char(c,11518).
+char(m,11519).
+char(o,11520).
+char(m,11521).
+char(o,11522).
+char(1,11523).
+char(2,11524).
+char(7,11525).
+char(p,11526).
+char(o,11527).
+char(m,11528).
+char(2,11529).
+char(9,11530).
+char(1,11531).
+char(c,11532).
+char(c,11533).
+char(c,11534).
+char(m,11535).
+char(o,11536).
+char(p,11537).
+char(o,11538).
+char(p,11539).
+char(o,11540).
+char(m,11541).
+char(o,11542).
+char(m,11543).
+char(o,11544).
+char(p,11545).
+char(o,11546).
+char(p,11547).
+char(1,11548).
+char(0,11549).
+char(1,11550).
+char(1,11551).
+char(c,11552).
+char(c,11553).
+char(c,11554).
+char(m,11555).
+char(8,11556).
+char(1,11557).
+char(2,11558).
+char(7,11559).
+char(c,11560).
+char(c,11561).
+char(c,11562).
+char(m,11563).
+char(o,11564).
+char(p,11565).
+char(9,11566).
+char(7,11567).
+char(6,11568).
+char(7,11569).
+char(c,11570).
+char(p,11571).
+char(4,11572).
+char(9,11573).
+char(8,11574).
+char(7,11575).
+char(p,11576).
+char(o,11577).
+char(o,11578).
+char(o,11579).
+char(5,11580).
+char(6,11581).
+char(3,11582).
+char(5,11583).
+char(c,11584).
+char(c,11585).
+char(p,11586).
+char(9,11587).
+char(7,11588).
+char(2,11589).
+char(5,11590).
+char(c,11591).
+char(m,11592).
+char(3,11593).
+char(1,11594).
+char(1,11595).
+char(2,11596).
+char(m,11597).
+char(o,11598).
+char(o,11599).
+char(2,11600).
+char(0,11601).
+char(8,11602).
+char(7,11603).
+char(c,11604).
+char(c,11605).
+char(c,11606).
+char(c,11607).
+char(c,11608).
+char(m,11609).
+char(2,11610).
+char(2,11611).
+char(9,11612).
+char(5,11613).
+char(c,11614).
+char(c,11615).
+char(c,11616).
+char(p,11617).
+char(6,11618).
+char(5,11619).
+char(4,11620).
+char(6,11621).
+char(m,11622).
+char(o,11623).
+char(o,11624).
+char(p,11625).
+char(6,11626).
+char(1,11627).
+char(0,11628).
+char(8,11629).
+char(p,11630).
+char(o,11631).
+char(p,11632).
+char(4,11633).
+char(1,11634).
+char(6,11635).
+char(0,11636).
+char(p,11637).
+char(7,11638).
+char(8,11639).
+char(9,11640).
+char(4,11641).
+char(c,11642).
+char(c,11643).
+char(c,11644).
+char(m,11645).
+char(o,11646).
+char(m,11647).
+char(o,11648).
+char(3,11649).
+char(8,11650).
+char(3,11651).
+char(1,11652).
+char(c,11653).
+char(c,11654).
+char(m,11655).
+char(2,11656).
+char(1,11657).
+char(0,11658).
+char(1,11659).
+char(c,11660).
+char(m,11661).
+char(1,11662).
+char(3,11663).
+char(5,11664).
+char(3,11665).
+char(m,11666).
+char(6,11667).
+char(7,11668).
+char(8,11669).
+char(c,11670).
+char(c,11671).
+char(p,11672).
+char(8,11673).
+char(2,11674).
+char(8,11675).
+char(4,11676).
+char(c,11677).
+char(c,11678).
+char(m,11679).
+char(o,11680).
+char(m,11681).
+char(1,11682).
+char(7,11683).
+char(2,11684).
+char(6,11685).
+char(c,11686).
+char(m,11687).
+char(6,11688).
+char(9,11689).
+char(1,11690).
+char(1,11691).
+char(m,11692).
+char(4,11693).
+char(8,11694).
+char(1,11695).
+char(m,11696).
+char(8,11697).
+char(5,11698).
+char(2,11699).
+char(7,11700).
+char(c,11701).
+char(m,11702).
+char(9,11703).
+char(5,11704).
+char(5,11705).
+char(5,11706).
+char(c,11707).
+char(p,11708).
+char(1,11709).
+char(7,11710).
+char(2,11711).
+char(1,11712).
+char(p,11713).
+char(7,11714).
+char(4,11715).
+char(6,11716).
+char(9,11717).
+char(c,11718).
+char(c,11719).
+char(m,11720).
+char(o,11721).
+char(p,11722).
+char(o,11723).
+char(m,11724).
+char(o,11725).
+char(o,11726).
+char(o,11727).
+char(o,11728).
+char(7,11729).
+char(1,11730).
+char(9,11731).
+char(6,11732).
+char(p,11733).
+char(8,11734).
+char(5,11735).
+char(8,11736).
+char(1,11737).
+char(p,11738).
+char(o,11739).
+char(m,11740).
+char(1,11741).
+char(6,11742).
+char(2,11743).
+char(4,11744).
+char(m,11745).
+char(7,11746).
+char(7,11747).
+char(5,11748).
+char(3,11749).
+char(c,11750).
+char(m,11751).
+char(o,11752).
+char(4,11753).
+char(7,11754).
+char(8,11755).
+char(3,11756).
+char(c,11757).
+char(m,11758).
+char(o,11759).
+char(p,11760).
+char(o,11761).
+char(m,11762).
+char(1,11763).
+char(0,11764).
+char(2,11765).
+char(1,11766).
+char(p,11767).
+char(o,11768).
+char(m,11769).
+char(o,11770).
+char(p,11771).
+char(o,11772).
+char(p,11773).
+char(o,11774).
+char(m,11775).
+char(o,11776).
+char(o,11777).
+char(p,11778).
+char(o,11779).
+char(p,11780).
+char(4,11781).
+char(6,11782).
+char(3,11783).
+char(1,11784).
+char(m,11785).
+char(8,11786).
+char(2,11787).
+char(1,11788).
+char(6,11789).
+char(c,11790).
+char(m,11791).
+char(3,11792).
+char(3,11793).
+char(9,11794).
+char(7,11795).
+char(c,11796).
+char(p,11797).
+char(3,11798).
+char(2,11799).
+char(3,11800).
+char(3,11801).
+char(c,11802).
+char(m,11803).
+char(o,11804).
+char(m,11805).
+char(o,11806).
+char(p,11807).
+char(o,11808).
+char(8,11809).
+char(8,11810).
+char(3,11811).
+char(6,11812).
+char(m,11813).
+char(9,11814).
+char(9,11815).
+char(8,11816).
+char(1,11817).
+char(p,11818).
+char(o,11819).
+char(o,11820).
+char(p,11821).
+char(o,11822).
+char(m,11823).
+char(2,11824).
+char(7,11825).
+char(8,11826).
+char(c,11827).
+char(p,11828).
+char(o,11829).
+char(p,11830).
+char(o,11831).
+char(p,11832).
+char(o,11833).
+char(m,11834).
+char(3,11835).
+char(2,11836).
+char(3,11837).
+char(3,11838).
+char(m,11839).
+char(o,11840).
+char(m,11841).
+char(o,11842).
+char(o,11843).
+char(o,11844).
+char(m,11845).
+char(2,11846).
+char(1,11847).
+char(1,11848).
+char(6,11849).
+char(p,11850).
+char(o,11851).
+char(p,11852).
+char(o,11853).
+char(p,11854).
+char(7,11855).
+char(8,11856).
+char(5,11857).
+char(9,11858).
+char(c,11859).
+char(c,11860).
+char(m,11861).
+char(o,11862).
+char(o,11863).
+char(o,11864).
+char(p,11865).
+char(8,11866).
+char(6,11867).
+char(2,11868).
+char(0,11869).
+char(p,11870).
+char(o,11871).
+char(p,11872).
+char(1,11873).
+char(8,11874).
+char(5,11875).
+char(0,11876).
+char(p,11877).
+char(o,11878).
+char(p,11879).
+char(5,11880).
+char(9,11881).
+char(1,11882).
+char(3,11883).
+char(p,11884).
+char(8,11885).
+char(3,11886).
+char(5,11887).
+char(6,11888).
+char(p,11889).
+char(8,11890).
+char(1,11891).
+char(2,11892).
+char(8,11893).
+char(m,11894).
+char(o,11895).
+char(p,11896).
+char(o,11897).
+char(3,11898).
+char(1,11899).
+char(0,11900).
+char(p,11901).
+char(o,11902).
+char(6,11903).
+char(3,11904).
+char(5,11905).
+char(2,11906).
+char(c,11907).
+char(p,11908).
+char(o,11909).
+char(m,11910).
+char(6,11911).
+char(2,11912).
+char(3,11913).
+char(5,11914).
+char(c,11915).
+char(c,11916).
+char(c,11917).
+char(c,11918).
+char(m,11919).
+char(o,11920).
+char(m,11921).
+char(1,11922).
+char(9,11923).
+char(8,11924).
+char(2,11925).
+char(c,11926).
+char(p,11927).
+char(o,11928).
+char(p,11929).
+char(o,11930).
+char(p,11931).
+char(2,11932).
+char(3,11933).
+char(4,11934).
+char(1,11935).
+char(c,11936).
+char(p,11937).
+char(6,11938).
+char(1,11939).
+char(m,11940).
+char(4,11941).
+char(2,11942).
+char(0,11943).
+char(7,11944).
+char(c,11945).
+char(p,11946).
+char(6,11947).
+char(7,11948).
+char(4,11949).
+char(3,11950).
+char(c,11951).
+char(p,11952).
+char(o,11953).
+char(o,11954).
+char(o,11955).
+char(p,11956).
+char(o,11957).
+char(9,11958).
+char(0,11959).
+char(9,11960).
+char(7,11961).
+char(c,11962).
+char(c,11963).
+char(m,11964).
+char(8,11965).
+char(1,11966).
+char(3,11967).
+char(0,11968).
+char(p,11969).
+char(7,11970).
+char(1,11971).
+char(3,11972).
+char(4,11973).
+char(m,11974).
+char(4,11975).
+char(9,11976).
+char(1,11977).
+char(3,11978).
+char(p,11979).
+char(o,11980).
+char(m,11981).
+char(4,11982).
+char(7,11983).
+char(9,11984).
+char(p,11985).
+char(7,11986).
+char(0,11987).
+char(2,11988).
+char(5,11989).
+char(m,11990).
+char(o,11991).
+char(5,11992).
+char(2,11993).
+char(0,11994).
+char(5,11995).
+char(c,11996).
+char(m,11997).
+char(9,11998).
+char(3,11999).
+char(9,12000).
+char(6,12001).
+char(c,12002).
+char(m,12003).
+char(o,12004).
+char(o,12005).
+char(m,12006).
+char(o,12007).
+char(p,12008).
+char(o,12009).
+char(p,12010).
+char(9,12011).
+char(1,12012).
+char(c,12013).
+char(m,12014).
+char(o,12015).
+char(m,12016).
+char(o,12017).
+char(p,12018).
+char(1,12019).
+char(7,12020).
+char(7,12021).
+char(5,12022).
+char(c,12023).
+char(c,12024).
+char(m,12025).
+char(o,12026).
+char(o,12027).
+char(4,12028).
+char(3,12029).
+char(2,12030).
+char(0,12031).
+char(c,12032).
+char(p,12033).
+char(o,12034).
+char(p,12035).
+char(1,12036).
+char(3,12037).
+char(3,12038).
+char(5,12039).
+char(p,12040).
+char(6,12041).
+char(2,12042).
+char(5,12043).
+char(0,12044).
+char(c,12045).
+char(c,12046).
+char(c,12047).
+char(p,12048).
+char(o,12049).
+char(p,12050).
+char(o,12051).
+char(m,12052).
+char(o,12053).
+char(o,12054).
+char(p,12055).
+char(4,12056).
+char(6,12057).
+char(4,12058).
+char(9,12059).
+char(p,12060).
+char(8,12061).
+char(4,12062).
+char(4,12063).
+char(0,12064).
+char(m,12065).
+char(o,12066).
+char(m,12067).
+char(9,12068).
+char(4,12069).
+char(0,12070).
+char(6,12071).
+char(m,12072).
+char(o,12073).
+char(5,12074).
+char(1,12075).
+char(2,12076).
+char(7,12077).
+char(m,12078).
+char(2,12079).
+char(0,12080).
+char(2,12081).
+char(1,12082).
+char(c,12083).
+char(c,12084).
+char(m,12085).
+char(o,12086).
+char(4,12087).
+char(1,12088).
+char(4,12089).
+char(1,12090).
+char(p,12091).
+char(3,12092).
+char(1,12093).
+char(4,12094).
+char(2,12095).
+char(p,12096).
+char(5,12097).
+char(0,12098).
+char(5,12099).
+char(8,12100).
+char(p,12101).
+char(o,12102).
+char(p,12103).
+char(o,12104).
+char(o,12105).
+char(p,12106).
+char(o,12107).
+char(4,12108).
+char(7,12109).
+char(2,12110).
+char(1,12111).
+char(m,12112).
+char(3,12113).
+char(9,12114).
+char(7,12115).
+char(0,12116).
+char(c,12117).
+char(c,12118).
+char(m,12119).
+char(o,12120).
+char(p,12121).
+char(2,12122).
+char(6,12123).
+char(4,12124).
+char(4,12125).
+char(c,12126).
+char(c,12127).
+char(c,12128).
+char(c,12129).
+char(m,12130).
+char(o,12131).
+char(o,12132).
+char(6,12133).
+char(4,12134).
+char(6,12135).
+char(8,12136).
+char(m,12137).
+char(6,12138).
+char(7,12139).
+char(m,12140).
+char(2,12141).
+char(1,12142).
+char(1,12143).
+char(7,12144).
+char(m,12145).
+char(o,12146).
+char(p,12147).
+char(o,12148).
+char(m,12149).
+char(o,12150).
+char(m,12151).
+char(o,12152).
+char(m,12153).
+char(6,12154).
+char(4,12155).
+char(9,12156).
+char(9,12157).
+char(c,12158).
+char(c,12159).
+char(c,12160).
+char(p,12161).
+char(o,12162).
+char(o,12163).
+char(o,12164).
+char(m,12165).
+char(5,12166).
+char(7,12167).
+char(1,12168).
+char(0,12169).
+char(c,12170).
+char(m,12171).
+char(1,12172).
+char(8,12173).
+char(0,12174).
+char(5,12175).
+char(m,12176).
+char(5,12177).
+char(7,12178).
+char(2,12179).
+char(6,12180).
+char(m,12181).
+char(9,12182).
+char(3,12183).
+char(9,12184).
+char(1,12185).
+char(p,12186).
+char(3,12187).
+char(8,12188).
+char(4,12189).
+char(1,12190).
+char(p,12191).
+char(8,12192).
+char(9,12193).
+char(3,12194).
+char(2,12195).
+char(c,12196).
+char(p,12197).
+char(6,12198).
+char(1,12199).
+char(7,12200).
+char(m,12201).
+char(5,12202).
+char(2,12203).
+char(2,12204).
+char(1,12205).
+char(m,12206).
+char(o,12207).
+char(o,12208).
+char(o,12209).
+char(o,12210).
+char(o,12211).
+char(o,12212).
+char(m,12213).
+char(9,12214).
+char(5,12215).
+char(3,12216).
+char(9,12217).
+char(c,12218).
+char(c,12219).
+char(c,12220).
+char(m,12221).
+char(5,12222).
+char(2,12223).
+char(1,12224).
+char(4,12225).
+char(m,12226).
+char(5,12227).
+char(1,12228).
+char(2,12229).
+char(c,12230).
+char(c,12231).
+char(m,12232).
+char(3,12233).
+char(4,12234).
+char(5,12235).
+char(4,12236).
+char(m,12237).
+char(o,12238).
+char(m,12239).
+char(6,12240).
+char(9,12241).
+char(7,12242).
+char(4,12243).
+char(m,12244).
+char(o,12245).
+char(p,12246).
+char(o,12247).
+char(m,12248).
+char(o,12249).
+char(1,12250).
+char(6,12251).
+char(9,12252).
+char(1,12253).
+char(c,12254).
+char(p,12255).
+char(o,12256).
+char(m,12257).
+char(o,12258).
+char(m,12259).
+char(8,12260).
+char(6,12261).
+char(5,12262).
+char(8,12263).
+char(c,12264).
+char(p,12265).
+char(o,12266).
+char(o,12267).
+char(m,12268).
+char(6,12269).
+char(6,12270).
+char(5,12271).
+char(6,12272).
+char(c,12273).
+char(p,12274).
+char(o,12275).
+char(p,12276).
+char(1,12277).
+char(5,12278).
+char(7,12279).
+char(7,12280).
+char(c,12281).
+char(m,12282).
+char(o,12283).
+char(o,12284).
+char(m,12285).
+char(3,12286).
+char(9,12287).
+char(3,12288).
+char(4,12289).
+char(m,12290).
+char(1,12291).
+char(6,12292).
+char(4,12293).
+char(5,12294).
+char(c,12295).
+char(m,12296).
+char(o,12297).
+char(o,12298).
+char(p,12299).
+char(o,12300).
+char(p,12301).
+char(6,12302).
+char(1,12303).
+char(5,12304).
+char(5,12305).
+char(c,12306).
+char(c,12307).
+char(c,12308).
+char(m,12309).
+char(o,12310).
+char(o,12311).
+char(9,12312).
+char(6,12313).
+char(1,12314).
+char(3,12315).
+char(m,12316).
+char(o,12317).
+char(m,12318).
+char(o,12319).
+char(p,12320).
+char(7,12321).
+char(2,12322).
+char(3,12323).
+char(0,12324).
+char(c,12325).
+char(c,12326).
+char(c,12327).
+char(c,12328).
+char(p,12329).
+char(o,12330).
+char(1,12331).
+char(6,12332).
+char(6,12333).
+char(4,12334).
+char(p,12335).
+char(o,12336).
+char(p,12337).
+char(1,12338).
+char(9,12339).
+char(1,12340).
+char(m,12341).
+char(4,12342).
+char(7,12343).
+char(5,12344).
+char(2,12345).
+char(c,12346).
+char(p,12347).
+char(8,12348).
+char(1,12349).
+char(2,12350).
+char(4,12351).
+char(c,12352).
+char(p,12353).
+char(o,12354).
+char(p,12355).
+char(9,12356).
+char(9,12357).
+char(9,12358).
+char(1,12359).
+char(m,12360).
+char(o,12361).
+char(m,12362).
+char(6,12363).
+char(3,12364).
+char(9,12365).
+char(1,12366).
+char(m,12367).
+char(o,12368).
+char(o,12369).
+char(o,12370).
+char(m,12371).
+char(4,12372).
+char(1,12373).
+char(5,12374).
+char(4,12375).
+char(m,12376).
+char(7,12377).
+char(7,12378).
+char(6,12379).
+char(1,12380).
+char(c,12381).
+char(m,12382).
+char(7,12383).
+char(1,12384).
+char(1,12385).
+char(4,12386).
+char(c,12387).
+char(c,12388).
+char(m,12389).
+char(o,12390).
+char(m,12391).
+char(o,12392).
+char(p,12393).
+char(9,12394).
+char(3,12395).
+char(0,12396).
+char(7,12397).
+char(c,12398).
+char(c,12399).
+char(m,12400).
+char(2,12401).
+char(4,12402).
+char(1,12403).
+char(1,12404).
+char(c,12405).
+char(c,12406).
+char(c,12407).
+char(c,12408).
+char(c,12409).
+char(m,12410).
+char(o,12411).
+char(m,12412).
+char(o,12413).
+char(o,12414).
+char(6,12415).
+char(8,12416).
+char(9,12417).
+char(1,12418).
+char(c,12419).
+char(c,12420).
+char(m,12421).
+char(o,12422).
+char(p,12423).
+char(o,12424).
+char(p,12425).
+char(3,12426).
+char(3,12427).
+char(6,12428).
+char(1,12429).
+char(p,12430).
+char(o,12431).
+char(m,12432).
+char(o,12433).
+char(m,12434).
+char(o,12435).
+char(o,12436).
+char(m,12437).
+char(o,12438).
+char(4,12439).
+char(0,12440).
+char(0,12441).
+char(m,12442).
+char(o,12443).
+char(6,12444).
+char(6,12445).
+char(8,12446).
+char(0,12447).
+char(p,12448).
+char(o,12449).
+char(m,12450).
+char(o,12451).
+char(m,12452).
+char(o,12453).
+char(p,12454).
+char(6,12455).
+char(5,12456).
+char(4,12457).
+char(4,12458).
+char(p,12459).
+char(8,12460).
+char(8,12461).
+char(9,12462).
+char(1,12463).
+char(p,12464).
+char(o,12465).
+char(p,12466).
+char(1,12467).
+char(4,12468).
+char(9,12469).
+char(1,12470).
+char(c,12471).
+char(c,12472).
+char(p,12473).
+char(o,12474).
+char(m,12475).
+char(o,12476).
+char(m,12477).
+char(1,12478).
+char(7,12479).
+char(6,12480).
+char(3,12481).
+char(m,12482).
+char(o,12483).
+char(o,12484).
+char(5,12485).
+char(1,12486).
+char(3,12487).
+char(5,12488).
+char(c,12489).
+char(m,12490).
+char(1,12491).
+char(8,12492).
+char(6,12493).
+char(4,12494).
+char(p,12495).
+char(3,12496).
+char(5,12497).
+char(4,12498).
+char(0,12499).
+char(c,12500).
+char(m,12501).
+char(5,12502).
+char(6,12503).
+char(1,12504).
+char(6,12505).
+char(c,12506).
+char(c,12507).
+char(m,12508).
+char(2,12509).
+char(0,12510).
+char(3,12511).
+char(0,12512).
+char(c,12513).
+char(c,12514).
+char(c,12515).
+char(c,12516).
+char(m,12517).
+char(o,12518).
+char(m,12519).
+char(4,12520).
+char(5,12521).
+char(6,12522).
+char(2,12523).
+char(c,12524).
+char(c,12525).
+char(p,12526).
+char(o,12527).
+char(p,12528).
+char(1,12529).
+char(9,12530).
+char(3,12531).
+char(8,12532).
+char(c,12533).
+char(c,12534).
+char(m,12535).
+char(o,12536).
+char(p,12537).
+char(o,12538).
+char(p,12539).
+char(8,12540).
+char(4,12541).
+char(9,12542).
+char(7,12543).
+char(m,12544).
+char(8,12545).
+char(5,12546).
+char(1,12547).
+char(5,12548).
+char(p,12549).
+char(7,12550).
+char(5,12551).
+char(0,12552).
+char(7,12553).
+char(m,12554).
+char(o,12555).
+char(p,12556).
+char(9,12557).
+char(7,12558).
+char(1,12559).
+char(4,12560).
+char(p,12561).
+char(o,12562).
+char(8,12563).
+char(9,12564).
+char(5,12565).
+char(m,12566).
+char(o,12567).
+char(m,12568).
+char(6,12569).
+char(2,12570).
+char(7,12571).
+char(0,12572).
+char(m,12573).
+char(6,12574).
+char(4,12575).
+char(8,12576).
+char(5,12577).
+char(c,12578).
+char(m,12579).
+char(o,12580).
+char(o,12581).
+char(m,12582).
+char(2,12583).
+char(9,12584).
+char(2,12585).
+char(8,12586).
+char(c,12587).
+char(c,12588).
+char(m,12589).
+char(6,12590).
+char(4,12591).
+char(8,12592).
+char(9,12593).
+char(p,12594).
+char(o,12595).
+char(o,12596).
+char(m,12597).
+char(o,12598).
+char(m,12599).
+char(o,12600).
+char(p,12601).
+char(8,12602).
+char(7,12603).
+char(8,12604).
+char(0,12605).
+char(c,12606).
+char(c,12607).
+char(c,12608).
+char(c,12609).
+char(c,12610).
+char(m,12611).
+char(o,12612).
+char(p,12613).
+char(1,12614).
+char(7,12615).
+char(m,12616).
+char(o,12617).
+char(p,12618).
+char(4,12619).
+char(1,12620).
+char(5,12621).
+char(1,12622).
+char(c,12623).
+char(c,12624).
+char(m,12625).
+char(o,12626).
+char(o,12627).
+char(o,12628).
+char(p,12629).
+char(3,12630).
+char(0,12631).
+char(4,12632).
+char(6,12633).
+char(c,12634).
+char(c,12635).
+char(p,12636).
+char(o,12637).
+char(o,12638).
+char(m,12639).
+char(4,12640).
+char(7,12641).
+char(4,12642).
+char(7,12643).
+char(m,12644).
+char(o,12645).
+char(m,12646).
+char(o,12647).
+char(1,12648).
+char(0,12649).
+char(9,12650).
+char(c,12651).
+char(c,12652).
+char(c,12653).
+char(c,12654).
+char(p,12655).
+char(4,12656).
+char(0,12657).
+char(8,12658).
+char(7,12659).
+char(c,12660).
+char(c,12661).
+char(c,12662).
+char(c,12663).
+char(p,12664).
+char(7,12665).
+char(8,12666).
+char(0,12667).
+char(7,12668).
+char(p,12669).
+char(7,12670).
+char(4,12671).
+char(9,12672).
+char(1,12673).
+char(c,12674).
+char(c,12675).
+char(p,12676).
+char(o,12677).
+char(m,12678).
+char(2,12679).
+char(2,12680).
+char(6,12681).
+char(8,12682).
+char(c,12683).
+char(c,12684).
+char(p,12685).
+char(8,12686).
+char(7,12687).
+char(4,12688).
+char(4,12689).
+char(c,12690).
+char(c,12691).
+char(c,12692).
+char(m,12693).
+char(o,12694).
+char(m,12695).
+char(o,12696).
+char(7,12697).
+char(6,12698).
+char(7,12699).
+char(7,12700).
+char(m,12701).
+char(9,12702).
+char(3,12703).
+char(6,12704).
+char(5,12705).
+char(c,12706).
+char(p,12707).
+char(o,12708).
+char(m,12709).
+char(2,12710).
+char(8,12711).
+char(1,12712).
+char(8,12713).
+char(c,12714).
+char(c,12715).
+char(m,12716).
+char(4,12717).
+char(4,12718).
+char(9,12719).
+char(1,12720).
+char(c,12721).
+char(c,12722).
+char(c,12723).
+char(c,12724).
+char(m,12725).
+char(o,12726).
+char(p,12727).
+char(6,12728).
+char(8,12729).
+char(2,12730).
+char(0,12731).
+char(m,12732).
+char(o,12733).
+char(o,12734).
+char(o,12735).
+char(p,12736).
+char(7,12737).
+char(1,12738).
+char(1,12739).
+char(1,12740).
+char(c,12741).
+char(m,12742).
+char(o,12743).
+char(6,12744).
+char(0,12745).
+char(1,12746).
+char(5,12747).
+char(c,12748).
+char(c,12749).
+char(c,12750).
+char(c,12751).
+char(p,12752).
+char(8,12753).
+char(1,12754).
+char(9,12755).
+char(2,12756).
+char(m,12757).
+char(9,12758).
+char(8,12759).
+char(0,12760).
+char(1,12761).
+char(p,12762).
+char(2,12763).
+char(8,12764).
+char(1,12765).
+char(0,12766).
+char(c,12767).
+char(c,12768).
+char(c,12769).
+char(c,12770).
+char(m,12771).
+char(o,12772).
+char(m,12773).
+char(4,12774).
+char(7,12775).
+char(0,12776).
+char(5,12777).
+char(p,12778).
+char(o,12779).
+char(p,12780).
+char(4,12781).
+char(3,12782).
+char(1,12783).
+char(1,12784).
+char(p,12785).
+char(5,12786).
+char(9,12787).
+char(1,12788).
+char(1,12789).
+char(c,12790).
+char(c,12791).
+char(c,12792).
+char(c,12793).
+char(p,12794).
+char(4,12795).
+char(1,12796).
+char(6,12797).
+char(8,12798).
+char(c,12799).
+char(c,12800).
+char(c,12801).
+char(c,12802).
+char(c,12803).
+char(p,12804).
+char(6,12805).
+char(4,12806).
+char(1,12807).
+char(2,12808).
+char(p,12809).
+char(o,12810).
+char(o,12811).
+char(p,12812).
+char(o,12813).
+char(p,12814).
+char(o,12815).
+char(4,12816).
+char(2,12817).
+char(2,12818).
+char(0,12819).
+char(c,12820).
+char(c,12821).
+char(c,12822).
+char(m,12823).
+char(o,12824).
+char(o,12825).
+char(p,12826).
+char(o,12827).
+char(8,12828).
+char(9,12829).
+char(3,12830).
+char(5,12831).
+char(c,12832).
+char(m,12833).
+char(6,12834).
+char(0,12835).
+char(5,12836).
+char(2,12837).
+char(p,12838).
+char(3,12839).
+char(6,12840).
+char(1,12841).
+char(c,12842).
+char(c,12843).
+char(c,12844).
+char(c,12845).
+char(p,12846).
+char(o,12847).
+char(m,12848).
+char(7,12849).
+char(0,12850).
+char(9,12851).
+char(7,12852).
+char(m,12853).
+char(3,12854).
+char(8,12855).
+char(1,12856).
+char(8,12857).
+char(c,12858).
+char(p,12859).
+char(4,12860).
+char(6,12861).
+char(6,12862).
+char(1,12863).
+char(m,12864).
+char(o,12865).
+char(m,12866).
+char(4,12867).
+char(3,12868).
+char(5,12869).
+char(8,12870).
+char(m,12871).
+char(o,12872).
+char(o,12873).
+char(o,12874).
+char(m,12875).
+char(4,12876).
+char(4,12877).
+char(1,12878).
+char(6,12879).
+char(c,12880).
+char(c,12881).
+char(m,12882).
+char(9,12883).
+char(0,12884).
+char(7,12885).
+char(4,12886).
+char(m,12887).
+char(5,12888).
+char(6,12889).
+char(2,12890).
+char(9,12891).
+char(c,12892).
+char(p,12893).
+char(o,12894).
+char(p,12895).
+char(o,12896).
+char(7,12897).
+char(5,12898).
+char(8,12899).
+char(6,12900).
+char(c,12901).
+char(c,12902).
+char(c,12903).
+char(c,12904).
+char(c,12905).
+char(p,12906).
+char(o,12907).
+char(p,12908).
+char(o,12909).
+char(p,12910).
+char(o,12911).
+char(o,12912).
+char(p,12913).
+char(7,12914).
+char(6,12915).
+char(2,12916).
+char(5,12917).
+char(p,12918).
+char(2,12919).
+char(3,12920).
+char(8,12921).
+char(2,12922).
+char(m,12923).
+char(o,12924).
+char(6,12925).
+char(8,12926).
+char(7,12927).
+char(m,12928).
+char(o,12929).
+char(o,12930).
+char(m,12931).
+char(4,12932).
+char(0,12933).
+char(4,12934).
+char(3,12935).
+char(p,12936).
+char(o,12937).
+char(o,12938).
+char(m,12939).
+char(8,12940).
+char(6,12941).
+char(4,12942).
+char(1,12943).
+char(m,12944).
+char(2,12945).
+char(1,12946).
+char(9,12947).
+char(2,12948).
+char(c,12949).
+char(p,12950).
+char(o,12951).
+char(6,12952).
+char(2,12953).
+char(3,12954).
+char(4,12955).
+char(p,12956).
+char(o,12957).
+char(m,12958).
+char(5,12959).
+char(1,12960).
+char(0,12961).
+char(3,12962).
+char(c,12963).
+char(p,12964).
+char(o,12965).
+char(m,12966).
+char(o,12967).
+char(o,12968).
+char(o,12969).
+char(o,12970).
+char(p,12971).
+char(5,12972).
+char(9,12973).
+char(7,12974).
+char(0,12975).
+char(p,12976).
+char(7,12977).
+char(1,12978).
+char(4,12979).
+char(c,12980).
+char(c,12981).
+char(m,12982).
+char(o,12983).
+char(9,12984).
+char(4,12985).
+char(8,12986).
+char(3,12987).
+char(m,12988).
+char(o,12989).
+char(p,12990).
+char(1,12991).
+char(5,12992).
+char(5,12993).
+char(5,12994).
+char(c,12995).
+char(m,12996).
+char(o,12997).
+char(p,12998).
+char(3,12999).
+char(3,13000).
+char(8,13001).
+char(c,13002).
+char(c,13003).
+char(m,13004).
+char(o,13005).
+char(m,13006).
+char(o,13007).
+char(5,13008).
+char(1,13009).
+char(1,13010).
+char(5,13011).
+char(c,13012).
+char(c,13013).
+char(c,13014).
+char(c,13015).
+char(m,13016).
+char(8,13017).
+char(2,13018).
+char(4,13019).
+char(7,13020).
+char(c,13021).
+char(p,13022).
+char(o,13023).
+char(m,13024).
+char(8,13025).
+char(2,13026).
+char(8,13027).
+char(3,13028).
+char(c,13029).
+char(c,13030).
+char(c,13031).
+char(c,13032).
+char(c,13033).
+char(m,13034).
+char(o,13035).
+char(7,13036).
+char(0,13037).
+char(2,13038).
+char(1,13039).
+char(c,13040).
+char(p,13041).
+char(1,13042).
+char(8,13043).
+char(4,13044).
+char(9,13045).
+char(c,13046).
+char(m,13047).
+char(3,13048).
+char(7,13049).
+char(3,13050).
+char(3,13051).
+char(c,13052).
+char(c,13053).
+char(c,13054).
+char(m,13055).
+char(6,13056).
+char(3,13057).
+char(8,13058).
+char(6,13059).
+char(c,13060).
+char(m,13061).
+char(1,13062).
+char(4,13063).
+char(6,13064).
+char(7,13065).
+char(c,13066).
+char(p,13067).
+char(o,13068).
+char(p,13069).
+char(o,13070).
+char(o,13071).
+char(m,13072).
+char(4,13073).
+char(1,13074).
+char(7,13075).
+char(c,13076).
+char(m,13077).
+char(o,13078).
+char(3,13079).
+char(8,13080).
+char(0,13081).
+char(9,13082).
+char(m,13083).
+char(o,13084).
+char(1,13085).
+char(0,13086).
+char(2,13087).
+char(6,13088).
+char(c,13089).
+char(m,13090).
+char(o,13091).
+char(m,13092).
+char(4,13093).
+char(0,13094).
+char(2,13095).
+char(0,13096).
+char(p,13097).
+char(o,13098).
+char(5,13099).
+char(7,13100).
+char(2,13101).
+char(6,13102).
+char(c,13103).
+char(c,13104).
+char(m,13105).
+char(3,13106).
+char(8,13107).
+char(0,13108).
+char(7,13109).
+char(m,13110).
+char(o,13111).
+char(5,13112).
+char(9,13113).
+char(8,13114).
+char(5,13115).
+char(c,13116).
+char(p,13117).
+char(o,13118).
+char(o,13119).
+char(p,13120).
+char(o,13121).
+char(o,13122).
+char(p,13123).
+char(o,13124).
+char(m,13125).
+char(o,13126).
+char(p,13127).
+char(o,13128).
+char(8,13129).
+char(8,13130).
+char(5,13131).
+char(3,13132).
+char(c,13133).
+char(p,13134).
+char(9,13135).
+char(0,13136).
+char(7,13137).
+char(1,13138).
+char(p,13139).
+char(o,13140).
+char(p,13141).
+char(o,13142).
+char(p,13143).
+char(o,13144).
+char(7,13145).
+char(2,13146).
+char(5,13147).
+char(1,13148).
+char(c,13149).
+char(m,13150).
+char(o,13151).
+char(p,13152).
+char(o,13153).
+char(p,13154).
+char(8,13155).
+char(1,13156).
+char(9,13157).
+char(4,13158).
+char(p,13159).
+char(o,13160).
+char(3,13161).
+char(0,13162).
+char(8,13163).
+char(1,13164).
+char(m,13165).
+char(2,13166).
+char(1,13167).
+char(1,13168).
+char(9,13169).
+char(p,13170).
+char(3,13171).
+char(8,13172).
+char(1,13173).
+char(4,13174).
+char(m,13175).
+char(1,13176).
+char(1,13177).
+char(6,13178).
+char(4,13179).
+char(m,13180).
+char(2,13181).
+char(1,13182).
+char(1,13183).
+char(8,13184).
+char(p,13185).
+char(2,13186).
+char(9,13187).
+char(2,13188).
+char(6,13189).
+char(c,13190).
+char(m,13191).
+char(7,13192).
+char(0,13193).
+char(2,13194).
+char(3,13195).
+char(m,13196).
+char(o,13197).
+char(p,13198).
+char(o,13199).
+char(5,13200).
+char(4,13201).
+char(0,13202).
+char(9,13203).
+char(c,13204).
+char(m,13205).
+char(1,13206).
+char(4,13207).
+char(2,13208).
+char(c,13209).
+char(p,13210).
+char(o,13211).
+char(p,13212).
+char(o,13213).
+char(p,13214).
+char(o,13215).
+char(o,13216).
+char(m,13217).
+char(o,13218).
+char(m,13219).
+char(o,13220).
+char(6,13221).
+char(8,13222).
+char(3,13223).
+char(8,13224).
+char(p,13225).
+char(o,13226).
+char(m,13227).
+char(8,13228).
+char(9,13229).
+char(4,13230).
+char(0,13231).
+char(c,13232).
+char(p,13233).
+char(3,13234).
+char(3,13235).
+char(c,13236).
+char(c,13237).
+char(c,13238).
+char(p,13239).
+char(6,13240).
+char(2,13241).
+char(8,13242).
+char(4,13243).
+char(m,13244).
+char(4,13245).
+char(9,13246).
+char(1,13247).
+char(0,13248).
+char(m,13249).
+char(o,13250).
+char(2,13251).
+char(1,13252).
+char(1,13253).
+char(1,13254).
+char(c,13255).
+char(p,13256).
+char(1,13257).
+char(2,13258).
+char(1,13259).
+char(6,13260).
+char(c,13261).
+char(c,13262).
+char(p,13263).
+char(o,13264).
+char(o,13265).
+char(o,13266).
+char(o,13267).
+char(o,13268).
+char(m,13269).
+char(o,13270).
+char(p,13271).
+char(o,13272).
+char(o,13273).
+char(m,13274).
+char(3,13275).
+char(3,13276).
+char(6,13277).
+char(6,13278).
+char(m,13279).
+char(5,13280).
+char(1,13281).
+char(2,13282).
+char(c,13283).
+char(m,13284).
+char(8,13285).
+char(1,13286).
+char(7,13287).
+char(0,13288).
+char(m,13289).
+char(o,13290).
+char(p,13291).
+char(2,13292).
+char(0,13293).
+char(2,13294).
+char(1,13295).
+char(c,13296).
+char(m,13297).
+char(o,13298).
+char(m,13299).
+char(5,13300).
+char(8,13301).
+char(2,13302).
+char(2,13303).
+char(m,13304).
+char(5,13305).
+char(1,13306).
+char(5,13307).
+char(7,13308).
+char(c,13309).
+char(p,13310).
+char(o,13311).
+char(m,13312).
+char(1,13313).
+char(6,13314).
+char(0,13315).
+char(6,13316).
+char(c,13317).
+char(p,13318).
+char(5,13319).
+char(5,13320).
+char(8,13321).
+char(1,13322).
+char(m,13323).
+char(o,13324).
+char(4,13325).
+char(6,13326).
+char(2,13327).
+char(2,13328).
+char(c,13329).
+char(m,13330).
+char(2,13331).
+char(9,13332).
+char(9,13333).
+char(0,13334).
+char(p,13335).
+char(o,13336).
+char(p,13337).
+char(o,13338).
+char(o,13339).
+char(o,13340).
+char(p,13341).
+char(3,13342).
+char(1,13343).
+char(1,13344).
+char(5,13345).
+char(c,13346).
+char(c,13347).
+char(m,13348).
+char(o,13349).
+char(m,13350).
+char(o,13351).
+char(o,13352).
+char(m,13353).
+char(o,13354).
+char(p,13355).
+char(o,13356).
+char(m,13357).
+char(o,13358).
+char(p,13359).
+char(8,13360).
+char(5,13361).
+char(7,13362).
+char(4,13363).
+char(m,13364).
+char(2,13365).
+char(7,13366).
+char(7,13367).
+char(2,13368).
+char(c,13369).
+char(c,13370).
+char(c,13371).
+char(m,13372).
+char(2,13373).
+char(8,13374).
+char(4,13375).
+char(1,13376).
+char(c,13377).
+char(p,13378).
+char(o,13379).
+char(m,13380).
+char(o,13381).
+char(p,13382).
+char(o,13383).
+char(o,13384).
+char(p,13385).
+char(o,13386).
+char(p,13387).
+char(6,13388).
+char(4,13389).
+char(1,13390).
+char(9,13391).
+char(p,13392).
+char(o,13393).
+char(p,13394).
+char(8,13395).
+char(1,13396).
+char(7,13397).
+char(1,13398).
+char(p,13399).
+char(o,13400).
+char(5,13401).
+char(9,13402).
+char(9,13403).
+char(m,13404).
+char(3,13405).
+char(7,13406).
+char(7,13407).
+char(8,13408).
+char(c,13409).
+char(m,13410).
+char(2,13411).
+char(2,13412).
+char(5,13413).
+char(0,13414).
+char(m,13415).
+char(o,13416).
+char(m,13417).
+char(1,13418).
+char(4,13419).
+char(8,13420).
+char(9,13421).
+char(m,13422).
+char(o,13423).
+char(m,13424).
+char(8,13425).
+char(8,13426).
+char(9,13427).
+char(8,13428).
+char(m,13429).
+char(3,13430).
+char(2,13431).
+char(3,13432).
+char(4,13433).
+char(m,13434).
+char(9,13435).
+char(2,13436).
+char(1,13437).
+char(1,13438).
+char(m,13439).
+char(o,13440).
+char(m,13441).
+char(o,13442).
+char(9,13443).
+char(6,13444).
+char(8,13445).
+char(2,13446).
+char(c,13447).
+char(p,13448).
+char(7,13449).
+char(9,13450).
+char(6,13451).
+char(9,13452).
+char(m,13453).
+char(o,13454).
+char(p,13455).
+char(o,13456).
+char(p,13457).
+char(1,13458).
+char(5,13459).
+char(0,13460).
+char(0,13461).
+char(c,13462).
+char(c,13463).
+char(c,13464).
+char(m,13465).
+char(7,13466).
+char(5,13467).
+char(9,13468).
+char(5,13469).
+char(p,13470).
+char(o,13471).
+char(p,13472).
+char(1,13473).
+char(7,13474).
+char(6,13475).
+char(c,13476).
+char(c,13477).
+char(c,13478).
+char(p,13479).
+char(1,13480).
+char(5,13481).
+char(1,13482).
+char(8,13483).
+char(c,13484).
+char(m,13485).
+char(3,13486).
+char(6,13487).
+char(5,13488).
+char(3,13489).
+char(c,13490).
+char(m,13491).
+char(o,13492).
+char(p,13493).
+char(o,13494).
+char(p,13495).
+char(o,13496).
+char(3,13497).
+char(9,13498).
+char(1,13499).
+char(6,13500).
+char(p,13501).
+char(o,13502).
+char(p,13503).
+char(7,13504).
+char(5,13505).
+char(6,13506).
+char(6,13507).
+char(c,13508).
+char(m,13509).
+char(5,13510).
+char(6,13511).
+char(5,13512).
+char(8,13513).
+char(p,13514).
+char(4,13515).
+char(3,13516).
+char(2,13517).
+char(8,13518).
+char(p,13519).
+char(7,13520).
+char(2,13521).
+char(0,13522).
+char(p,13523).
+char(1,13524).
+char(7,13525).
+char(2,13526).
+char(9,13527).
+char(m,13528).
+char(4,13529).
+char(8,13530).
+char(6,13531).
+char(3,13532).
+char(c,13533).
+char(m,13534).
+char(4,13535).
+char(0,13536).
+char(9,13537).
+char(m,13538).
+char(5,13539).
+char(5,13540).
+char(2,13541).
+char(2,13542).
+char(c,13543).
+char(c,13544).
+char(p,13545).
+char(7,13546).
+char(1,13547).
+char(6,13548).
+char(5,13549).
+char(c,13550).
+char(p,13551).
+char(o,13552).
+char(o,13553).
+char(p,13554).
+char(3,13555).
+char(0,13556).
+char(4,13557).
+char(7,13558).
+char(c,13559).
+char(c,13560).
+char(c,13561).
+char(c,13562).
+char(m,13563).
+char(2,13564).
+char(8,13565).
+char(4,13566).
+char(5,13567).
+char(c,13568).
+char(m,13569).
+char(o,13570).
+char(m,13571).
+char(o,13572).
+char(m,13573).
+char(o,13574).
+char(p,13575).
+char(o,13576).
+char(p,13577).
+char(o,13578).
+char(4,13579).
+char(3,13580).
+char(4,13581).
+char(2,13582).
+char(c,13583).
+char(p,13584).
+char(9,13585).
+char(3,13586).
+char(8,13587).
+char(7,13588).
+char(m,13589).
+char(5,13590).
+char(9,13591).
+char(5,13592).
+char(p,13593).
+char(3,13594).
+char(8,13595).
+char(4,13596).
+char(9,13597).
+char(c,13598).
+char(p,13599).
+char(o,13600).
+char(m,13601).
+char(o,13602).
+char(p,13603).
+char(7,13604).
+char(4,13605).
+char(2,13606).
+char(1,13607).
+char(p,13608).
+char(9,13609).
+char(0,13610).
+char(6,13611).
+char(5,13612).
+char(p,13613).
+char(2,13614).
+char(1,13615).
+char(3,13616).
+char(5,13617).
+char(c,13618).
+char(c,13619).
+char(c,13620).
+char(c,13621).
+char(c,13622).
+char(c,13623).
+char(c,13624).
+char(m,13625).
+char(4,13626).
+char(2,13627).
+char(3,13628).
+char(8,13629).
+char(m,13630).
+char(4,13631).
+char(5,13632).
+char(0,13633).
+char(7,13634).
+char(p,13635).
+char(7,13636).
+char(6,13637).
+char(4,13638).
+char(4,13639).
+char(p,13640).
+char(5,13641).
+char(5,13642).
+char(7,13643).
+char(9,13644).
+char(c,13645).
+char(p,13646).
+char(o,13647).
+char(m,13648).
+char(8,13649).
+char(9,13650).
+char(4,13651).
+char(m,13652).
+char(o,13653).
+char(m,13654).
+char(3,13655).
+char(8,13656).
+char(6,13657).
+char(1,13658).
+char(c,13659).
+char(m,13660).
+char(7,13661).
+char(8,13662).
+char(2,13663).
+char(0,13664).
+char(c,13665).
+char(c,13666).
+char(c,13667).
+char(c,13668).
+char(c,13669).
+char(c,13670).
+char(c,13671).
+char(c,13672).
+char(p,13673).
+char(1,13674).
+char(6,13675).
+char(6,13676).
+char(3,13677).
+char(p,13678).
+char(o,13679).
+char(m,13680).
+char(o,13681).
+char(m,13682).
+char(o,13683).
+char(1,13684).
+char(0,13685).
+char(4,13686).
+char(6,13687).
+char(p,13688).
+char(o,13689).
+char(o,13690).
+char(o,13691).
+char(m,13692).
+char(o,13693).
+char(p,13694).
+char(6,13695).
+char(5,13696).
+char(1,13697).
+char(m,13698).
+char(9,13699).
+char(8,13700).
+char(1,13701).
+char(9,13702).
+char(c,13703).
+char(m,13704).
+char(o,13705).
+char(m,13706).
+char(7,13707).
+char(1,13708).
+char(2,13709).
+char(0,13710).
+char(p,13711).
+char(7,13712).
+char(5,13713).
+char(2,13714).
+char(7,13715).
+char(m,13716).
+char(3,13717).
+char(1,13718).
+char(1,13719).
+char(1,13720).
+char(p,13721).
+char(8,13722).
+char(8,13723).
+char(4,13724).
+char(8,13725).
+char(m,13726).
+char(o,13727).
+char(o,13728).
+char(o,13729).
+char(m,13730).
+char(o,13731).
+char(m,13732).
+char(7,13733).
+char(5,13734).
+char(6,13735).
+char(9,13736).
+char(p,13737).
+char(o,13738).
+char(p,13739).
+char(o,13740).
+char(m,13741).
+char(6,13742).
+char(3,13743).
+char(5,13744).
+char(9,13745).
+char(p,13746).
+char(o,13747).
+char(p,13748).
+char(o,13749).
+char(7,13750).
+char(2,13751).
+char(6,13752).
+char(0,13753).
+char(m,13754).
+char(1,13755).
+char(2,13756).
+char(6,13757).
+char(3,13758).
+char(c,13759).
+char(p,13760).
+char(o,13761).
+char(9,13762).
+char(8,13763).
+char(3,13764).
+char(7,13765).
+char(m,13766).
+char(4,13767).
+char(5,13768).
+char(1,13769).
+char(1,13770).
+char(c,13771).
+char(c,13772).
+char(p,13773).
+char(o,13774).
+char(m,13775).
+char(8,13776).
+char(5,13777).
+char(5,13778).
+char(1,13779).
+char(c,13780).
+char(c,13781).
+char(c,13782).
+char(p,13783).
+char(4,13784).
+char(8,13785).
+char(1,13786).
+char(3,13787).
+char(p,13788).
+char(9,13789).
+char(4,13790).
+char(8,13791).
+char(p,13792).
+char(o,13793).
+char(p,13794).
+char(1,13795).
+char(6,13796).
+char(9,13797).
+char(c,13798).
+char(m,13799).
+char(o,13800).
+char(m,13801).
+char(o,13802).
+char(3,13803).
+char(0,13804).
+char(9,13805).
+char(4,13806).
+char(c,13807).
+char(c,13808).
+char(c,13809).
+char(c,13810).
+char(c,13811).
+char(c,13812).
+char(m,13813).
+char(2,13814).
+char(0,13815).
+char(5,13816).
+char(7,13817).
+char(p,13818).
+char(6,13819).
+char(3,13820).
+char(4,13821).
+char(5,13822).
+char(c,13823).
+char(m,13824).
+char(8,13825).
+char(2,13826).
+char(6,13827).
+char(m,13828).
+char(9,13829).
+char(4,13830).
+char(0,13831).
+char(5,13832).
+char(p,13833).
+char(o,13834).
+char(p,13835).
+char(6,13836).
+char(1,13837).
+char(1,13838).
+char(7,13839).
+char(c,13840).
+char(m,13841).
+char(2,13842).
+char(2,13843).
+char(3,13844).
+char(9,13845).
+char(c,13846).
+char(m,13847).
+char(o,13848).
+char(p,13849).
+char(o,13850).
+char(p,13851).
+char(o,13852).
+char(p,13853).
+char(o,13854).
+char(m,13855).
+char(o,13856).
+char(m,13857).
+char(o,13858).
+char(m,13859).
+char(o,13860).
+char(m,13861).
+char(o,13862).
+char(p,13863).
+char(o,13864).
+char(o,13865).
+char(p,13866).
+char(o,13867).
+char(m,13868).
+char(5,13869).
+char(6,13870).
+char(0,13871).
+char(8,13872).
+char(m,13873).
+char(1,13874).
+char(4,13875).
+char(6,13876).
+char(3,13877).
+char(p,13878).
+char(6,13879).
+char(9,13880).
+char(6,13881).
+char(9,13882).
+char(p,13883).
+char(1,13884).
+char(6,13885).
+char(8,13886).
+char(9,13887).
+char(c,13888).
+char(m,13889).
+char(o,13890).
+char(m,13891).
+char(o,13892).
+char(o,13893).
+char(m,13894).
+char(7,13895).
+char(2,13896).
+char(6,13897).
+char(3,13898).
+char(c,13899).
+char(p,13900).
+char(o,13901).
+char(m,13902).
+char(9,13903).
+char(0,13904).
+char(6,13905).
+char(9,13906).
+char(c,13907).
+char(p,13908).
+char(3,13909).
+char(8,13910).
+char(2,13911).
+char(9,13912).
+char(c,13913).
+char(m,13914).
+char(4,13915).
+char(5,13916).
+char(7,13917).
+char(c,13918).
+char(m,13919).
+char(o,13920).
+char(p,13921).
+char(3,13922).
+char(8,13923).
+char(6,13924).
+char(4,13925).
+char(m,13926).
+char(6,13927).
+char(1,13928).
+char(3,13929).
+char(3,13930).
+char(c,13931).
+char(m,13932).
+char(8,13933).
+char(1,13934).
+char(5,13935).
+char(8,13936).
+char(m,13937).
+char(o,13938).
+char(m,13939).
+char(o,13940).
+char(p,13941).
+char(3,13942).
+char(2,13943).
+char(8,13944).
+char(1,13945).
+char(p,13946).
+char(4,13947).
+char(6,13948).
+char(2,13949).
+char(8,13950).
+char(c,13951).
+char(p,13952).
+char(6,13953).
+char(7,13954).
+char(7,13955).
+char(8,13956).
+char(c,13957).
+char(c,13958).
+char(p,13959).
+char(o,13960).
+char(p,13961).
+char(8,13962).
+char(5,13963).
+char(3,13964).
+char(1,13965).
+char(c,13966).
+char(c,13967).
+char(c,13968).
+char(c,13969).
+char(c,13970).
+char(c,13971).
+char(c,13972).
+char(c,13973).
+char(p,13974).
+char(7,13975).
+char(3,13976).
+char(0,13977).
+char(4,13978).
+char(c,13979).
+char(c,13980).
+char(c,13981).
+char(c,13982).
+char(c,13983).
+char(c,13984).
+char(m,13985).
+char(o,13986).
+char(m,13987).
+char(1,13988).
+char(2,13989).
+char(5,13990).
+char(3,13991).
+char(p,13992).
+char(4,13993).
+char(5,13994).
+char(8,13995).
+char(2,13996).
+char(m,13997).
+char(3,13998).
+char(1,13999).
+char(6,14000).
+char(7,14001).
+char(m,14002).
+char(o,14003).
+char(m,14004).
+char(o,14005).
+char(2,14006).
+char(5,14007).
+char(8,14008).
+char(5,14009).
+char(c,14010).
+char(c,14011).
+char(p,14012).
+char(1,14013).
+char(9,14014).
+char(8,14015).
+char(7,14016).
+char(m,14017).
+char(o,14018).
+char(2,14019).
+char(8,14020).
+char(3,14021).
+char(9,14022).
+char(p,14023).
+char(o,14024).
+char(p,14025).
+char(5,14026).
+char(9,14027).
+char(3,14028).
+char(m,14029).
+char(8,14030).
+char(3,14031).
+char(8,14032).
+char(9,14033).
+char(p,14034).
+char(4,14035).
+char(1,14036).
+char(4,14037).
+char(5,14038).
+char(c,14039).
+char(c,14040).
+char(p,14041).
+char(o,14042).
+char(p,14043).
+char(o,14044).
+char(o,14045).
+char(p,14046).
+char(o,14047).
+char(3,14048).
+char(9,14049).
+char(4,14050).
+char(4,14051).
+char(c,14052).
+char(c,14053).
+char(m,14054).
+char(1,14055).
+char(5,14056).
+char(3,14057).
+char(0,14058).
+char(p,14059).
+char(4,14060).
+char(8,14061).
+char(0,14062).
+char(1,14063).
+char(c,14064).
+char(c,14065).
+char(p,14066).
+char(o,14067).
+char(5,14068).
+char(6,14069).
+char(1,14070).
+char(4,14071).
+char(c,14072).
+char(c,14073).
+char(p,14074).
+char(2,14075).
+char(0,14076).
+char(8,14077).
+char(0,14078).
+char(c,14079).
+char(c,14080).
+char(p,14081).
+char(o,14082).
+char(p,14083).
+char(o,14084).
+char(p,14085).
+char(o,14086).
+char(m,14087).
+char(o,14088).
+char(p,14089).
+char(o,14090).
+char(p,14091).
+char(o,14092).
+char(p,14093).
+char(3,14094).
+char(3,14095).
+char(7,14096).
+char(8,14097).
+char(p,14098).
+char(o,14099).
+char(p,14100).
+char(o,14101).
+char(o,14102).
+char(m,14103).
+char(o,14104).
+char(p,14105).
+char(o,14106).
+char(p,14107).
+char(o,14108).
+char(5,14109).
+char(2,14110).
+char(0,14111).
+char(9,14112).
+char(p,14113).
+char(o,14114).
+char(m,14115).
+char(o,14116).
+char(m,14117).
+char(5,14118).
+char(3,14119).
+char(8,14120).
+char(3,14121).
+char(p,14122).
+char(o,14123).
+char(m,14124).
+char(1,14125).
+char(3,14126).
+char(5,14127).
+char(4,14128).
+char(c,14129).
+char(c,14130).
+char(m,14131).
+char(3,14132).
+char(0,14133).
+char(1,14134).
+char(5,14135).
+char(m,14136).
+char(o,14137).
+char(p,14138).
+char(2,14139).
+char(9,14140).
+char(7,14141).
+char(0,14142).
+char(c,14143).
+char(p,14144).
+char(o,14145).
+char(o,14146).
+char(p,14147).
+char(o,14148).
+char(m,14149).
+char(8,14150).
+char(7,14151).
+char(9,14152).
+char(3,14153).
+char(m,14154).
+char(o,14155).
+char(o,14156).
+char(m,14157).
+char(o,14158).
+char(2,14159).
+char(2,14160).
+char(0,14161).
+char(2,14162).
+char(p,14163).
+char(o,14164).
+char(m,14165).
+char(3,14166).
+char(0,14167).
+char(5,14168).
+char(7,14169).
+char(p,14170).
+char(6,14171).
+char(2,14172).
+char(1,14173).
+char(9,14174).
+char(c,14175).
+char(m,14176).
+char(3,14177).
+char(4,14178).
+char(1,14179).
+char(8,14180).
+char(m,14181).
+char(6,14182).
+char(4,14183).
+char(4,14184).
+char(3,14185).
+char(m,14186).
+char(4,14187).
+char(0,14188).
+char(6,14189).
+char(6,14190).
+char(m,14191).
+char(6,14192).
+char(4,14193).
+char(1,14194).
+char(6,14195).
+char(m,14196).
+char(6,14197).
+char(7,14198).
+char(7,14199).
+char(1,14200).
+char(c,14201).
+char(c,14202).
+char(c,14203).
+char(m,14204).
+char(o,14205).
+char(p,14206).
+char(3,14207).
+char(1,14208).
+char(1,14209).
+char(6,14210).
+char(m,14211).
+char(o,14212).
+char(p,14213).
+char(o,14214).
+char(m,14215).
+char(o,14216).
+char(6,14217).
+char(9,14218).
+char(6,14219).
+char(8,14220).
+char(p,14221).
+char(o,14222).
+char(p,14223).
+char(6,14224).
+char(3,14225).
+char(9,14226).
+char(2,14227).
+char(c,14228).
+char(m,14229).
+char(9,14230).
+char(0,14231).
+char(1,14232).
+char(0,14233).
+char(c,14234).
+char(m,14235).
+char(5,14236).
+char(8,14237).
+char(5,14238).
+char(5,14239).
+char(m,14240).
+char(3,14241).
+char(9,14242).
+char(9,14243).
+char(3,14244).
+char(c,14245).
+char(c,14246).
+char(p,14247).
+char(o,14248).
+char(o,14249).
+char(m,14250).
+char(4,14251).
+char(7,14252).
+char(7,14253).
+char(0,14254).
+char(c,14255).
+char(p,14256).
+char(4,14257).
+char(1,14258).
+char(5,14259).
+char(5,14260).
+char(c,14261).
+char(c,14262).
+char(p,14263).
+char(8,14264).
+char(2,14265).
+char(9,14266).
+char(p,14267).
+char(3,14268).
+char(1,14269).
+char(1,14270).
+char(9,14271).
+char(c,14272).
+char(c,14273).
+char(c,14274).
+char(m,14275).
+char(5,14276).
+char(6,14277).
+char(1,14278).
+char(1,14279).
+char(p,14280).
+char(3,14281).
+char(0,14282).
+char(5,14283).
+char(9,14284).
+char(m,14285).
+char(o,14286).
+char(p,14287).
+char(o,14288).
+char(3,14289).
+char(3,14290).
+char(2,14291).
+char(4,14292).
+char(c,14293).
+char(m,14294).
+char(o,14295).
+char(m,14296).
+char(3,14297).
+char(2,14298).
+char(9,14299).
+char(4,14300).
+char(c,14301).
+char(m,14302).
+char(o,14303).
+char(m,14304).
+char(3,14305).
+char(9,14306).
+char(0,14307).
+char(7,14308).
+char(c,14309).
+char(p,14310).
+char(o,14311).
+char(o,14312).
+char(p,14313).
+char(3,14314).
+char(2,14315).
+char(3,14316).
+char(1,14317).
+char(p,14318).
+char(1,14319).
+char(4,14320).
+char(0,14321).
+char(6,14322).
+char(c,14323).
+char(c,14324).
+char(c,14325).
+char(c,14326).
+char(p,14327).
+char(3,14328).
+char(3,14329).
+char(0,14330).
+char(8,14331).
+char(c,14332).
+char(p,14333).
+char(o,14334).
+char(4,14335).
+char(8,14336).
+char(4,14337).
+char(8,14338).
+char(c,14339).
+char(c,14340).
+char(c,14341).
+char(p,14342).
+char(o,14343).
+char(m,14344).
+char(o,14345).
+char(m,14346).
+char(4,14347).
+char(7,14348).
+char(3,14349).
+char(4,14350).
+char(m,14351).
+char(o,14352).
+char(p,14353).
+char(o,14354).
+char(p,14355).
+char(o,14356).
+char(p,14357).
+char(o,14358).
+char(p,14359).
+char(8,14360).
+char(0,14361).
+char(5,14362).
+char(1,14363).
+char(m,14364).
+char(o,14365).
+char(2,14366).
+char(5,14367).
+char(2,14368).
+char(3,14369).
+char(c,14370).
+char(c,14371).
+char(c,14372).
+char(p,14373).
+char(o,14374).
+char(p,14375).
+char(o,14376).
+char(p,14377).
+char(3,14378).
+char(8,14379).
+char(8,14380).
+char(2,14381).
+char(p,14382).
+char(9,14383).
+char(5,14384).
+char(4,14385).
+char(p,14386).
+char(1,14387).
+char(8,14388).
+char(0,14389).
+char(2,14390).
+char(c,14391).
+char(c,14392).
+char(c,14393).
+char(m,14394).
+char(o,14395).
+char(p,14396).
+char(o,14397).
+char(p,14398).
+char(o,14399).
+char(p,14400).
+char(1,14401).
+char(2,14402).
+char(2,14403).
+char(3,14404).
+char(m,14405).
+char(o,14406).
+char(m,14407).
+char(2,14408).
+char(8,14409).
+char(1,14410).
+char(1,14411).
+char(m,14412).
+char(o,14413).
+char(p,14414).
+char(o,14415).
+char(p,14416).
+char(3,14417).
+char(0,14418).
+char(3,14419).
+char(7,14420).
+char(c,14421).
+char(p,14422).
+char(1,14423).
+char(7,14424).
+char(5,14425).
+char(2,14426).
+char(c,14427).
+char(m,14428).
+char(9,14429).
+char(9,14430).
+char(5,14431).
+char(9,14432).
+char(c,14433).
+char(c,14434).
+char(c,14435).
+char(m,14436).
+char(o,14437).
+char(3,14438).
+char(8,14439).
+char(7,14440).
+char(8,14441).
+char(c,14442).
+char(c,14443).
+char(c,14444).
+char(p,14445).
+char(o,14446).
+char(p,14447).
+char(o,14448).
+char(p,14449).
+char(o,14450).
+char(9,14451).
+char(5,14452).
+char(2,14453).
+char(4,14454).
+char(c,14455).
+char(p,14456).
+char(8,14457).
+char(6,14458).
+char(3,14459).
+char(0,14460).
+char(m,14461).
+char(o,14462).
+char(p,14463).
+char(5,14464).
+char(6,14465).
+char(2,14466).
+char(c,14467).
+char(c,14468).
+char(p,14469).
+char(o,14470).
+char(m,14471).
+char(8,14472).
+char(9,14473).
+char(8,14474).
+char(0,14475).
+char(m,14476).
+char(o,14477).
+char(p,14478).
+char(5,14479).
+char(1,14480).
+char(2,14481).
+char(c,14482).
+char(c,14483).
+char(m,14484).
+char(o,14485).
+char(p,14486).
+char(3,14487).
+char(7,14488).
+char(9,14489).
+char(3,14490).
+char(c,14491).
+char(c,14492).
+char(c,14493).
+char(p,14494).
+char(o,14495).
+char(p,14496).
+char(o,14497).
+char(p,14498).
+char(o,14499).
+char(m,14500).
+char(4,14501).
+char(7,14502).
+char(c,14503).
+char(m,14504).
+char(5,14505).
+char(0,14506).
+char(2,14507).
+char(3,14508).
+char(m,14509).
+char(o,14510).
+char(p,14511).
+char(3,14512).
+char(3,14513).
+char(0,14514).
+char(9,14515).
+char(c,14516).
+char(m,14517).
+char(2,14518).
+char(7,14519).
+char(3,14520).
+char(3,14521).
+char(m,14522).
+char(o,14523).
+char(o,14524).
+char(p,14525).
+char(o,14526).
+char(p,14527).
+char(o,14528).
+char(m,14529).
+char(8,14530).
+char(4,14531).
+char(7,14532).
+char(8,14533).
+char(c,14534).
+char(p,14535).
+char(o,14536).
+char(m,14537).
+char(o,14538).
+char(o,14539).
+char(p,14540).
+char(o,14541).
+char(m,14542).
+char(o,14543).
+char(4,14544).
+char(6,14545).
+char(7,14546).
+char(3,14547).
+char(c,14548).
+char(c,14549).
+char(c,14550).
+char(m,14551).
+char(4,14552).
+char(7,14553).
+char(0,14554).
+char(1,14555).
+char(c,14556).
+char(c,14557).
+char(m,14558).
+char(3,14559).
+char(0,14560).
+char(4,14561).
+char(8,14562).
+char(p,14563).
+char(o,14564).
+char(m,14565).
+char(2,14566).
+char(3,14567).
+char(9,14568).
+char(7,14569).
+char(c,14570).
+char(p,14571).
+char(6,14572).
+char(5,14573).
+char(2,14574).
+char(0,14575).
+char(c,14576).
+char(c,14577).
+char(p,14578).
+char(o,14579).
+char(p,14580).
+char(2,14581).
+char(9,14582).
+char(2,14583).
+char(6,14584).
+char(c,14585).
+char(p,14586).
+char(7,14587).
+char(5,14588).
+char(5,14589).
+char(3,14590).
+char(c,14591).
+char(c,14592).
+char(p,14593).
+char(5,14594).
+char(6,14595).
+char(8,14596).
+char(9,14597).
+char(c,14598).
+char(p,14599).
+char(o,14600).
+char(m,14601).
+char(3,14602).
+char(2,14603).
+char(6,14604).
+char(4,14605).
+char(p,14606).
+char(o,14607).
+char(o,14608).
+char(o,14609).
+char(m,14610).
+char(o,14611).
+char(p,14612).
+char(o,14613).
+char(m,14614).
+char(5,14615).
+char(3,14616).
+char(9,14617).
+char(9,14618).
+char(m,14619).
+char(5,14620).
+char(7,14621).
+char(9,14622).
+char(0,14623).
+char(c,14624).
+char(c,14625).
+char(c,14626).
+char(m,14627).
+char(3,14628).
+char(4,14629).
+char(2,14630).
+char(1,14631).
+char(m,14632).
+char(o,14633).
+char(m,14634).
+char(o,14635).
+char(8,14636).
+char(7,14637).
+char(3,14638).
+char(1,14639).
+char(m,14640).
+char(o,14641).
+char(p,14642).
+char(o,14643).
+char(m,14644).
+char(3,14645).
+char(8,14646).
+char(2,14647).
+char(1,14648).
+char(c,14649).
+char(m,14650).
+char(6,14651).
+char(0,14652).
+char(6,14653).
+char(3,14654).
+char(m,14655).
+char(o,14656).
+char(3,14657).
+char(2,14658).
+char(9,14659).
+char(6,14660).
+char(c,14661).
+char(p,14662).
+char(o,14663).
+char(m,14664).
+char(o,14665).
+char(p,14666).
+char(o,14667).
+char(4,14668).
+char(9,14669).
+char(5,14670).
+char(6,14671).
+char(p,14672).
+char(9,14673).
+char(3,14674).
+char(8,14675).
+char(6,14676).
+char(p,14677).
+char(o,14678).
+char(m,14679).
+char(o,14680).
+char(m,14681).
+char(o,14682).
+char(p,14683).
+char(7,14684).
+char(8,14685).
+char(6,14686).
+char(c,14687).
+char(p,14688).
+char(o,14689).
+char(p,14690).
+char(o,14691).
+char(m,14692).
+char(8,14693).
+char(9,14694).
+char(8,14695).
+char(9,14696).
+char(c,14697).
+char(c,14698).
+char(c,14699).
+char(c,14700).
+char(m,14701).
+char(2,14702).
+char(9,14703).
+char(9,14704).
+char(2,14705).
+char(c,14706).
+char(c,14707).
+char(m,14708).
+char(o,14709).
+char(p,14710).
+char(1,14711).
+char(6,14712).
+char(6,14713).
+char(4,14714).
+char(p,14715).
+char(4,14716).
+char(8,14717).
+char(4,14718).
+char(p,14719).
+char(6,14720).
+char(8,14721).
+char(0,14722).
+char(1,14723).
+char(p,14724).
+char(o,14725).
+char(p,14726).
+char(7,14727).
+char(2,14728).
+char(4,14729).
+char(9,14730).
+char(p,14731).
+char(8,14732).
+char(7,14733).
+char(2,14734).
+char(9,14735).
+char(c,14736).
+char(m,14737).
+char(3,14738).
+char(3,14739).
+char(3,14740).
+char(1,14741).
+char(c,14742).
+char(m,14743).
+char(6,14744).
+char(3,14745).
+char(8,14746).
+char(3,14747).
+char(c,14748).
+char(c,14749).
+char(c,14750).
+char(m,14751).
+char(6,14752).
+char(2,14753).
+char(4,14754).
+char(7,14755).
+char(c,14756).
+char(p,14757).
+char(9,14758).
+char(4,14759).
+char(5,14760).
+char(4,14761).
+char(c,14762).
+char(c,14763).
+char(c,14764).
+char(p,14765).
+char(7,14766).
+char(9,14767).
+char(4,14768).
+char(1,14769).
+char(m,14770).
+char(9,14771).
+char(5,14772).
+char(1,14773).
+char(3,14774).
+char(c,14775).
+char(m,14776).
+char(o,14777).
+char(1,14778).
+char(9,14779).
+char(3,14780).
+char(6,14781).
+char(m,14782).
+char(o,14783).
+char(p,14784).
+char(1,14785).
+char(8,14786).
+char(8,14787).
+char(7,14788).
+char(m,14789).
+char(o,14790).
+char(p,14791).
+char(o,14792).
+char(p,14793).
+char(o,14794).
+char(m,14795).
+char(o,14796).
+char(m,14797).
+char(8,14798).
+char(1,14799).
+char(3,14800).
+char(4,14801).
+char(c,14802).
+char(p,14803).
+char(o,14804).
+char(o,14805).
+char(m,14806).
+char(o,14807).
+char(o,14808).
+char(o,14809).
+char(p,14810).
+char(2,14811).
+char(3,14812).
+char(1,14813).
+char(1,14814).
+char(p,14815).
+char(o,14816).
+char(3,14817).
+char(8,14818).
+char(2,14819).
+char(4,14820).
+char(c,14821).
+char(p,14822).
+char(1,14823).
+char(5,14824).
+char(1,14825).
+char(6,14826).
+char(c,14827).
+char(m,14828).
+char(5,14829).
+char(3,14830).
+char(9,14831).
+char(9,14832).
+char(c,14833).
+char(c,14834).
+char(p,14835).
+char(2,14836).
+char(6,14837).
+char(5,14838).
+char(0,14839).
+char(m,14840).
+char(5,14841).
+char(3,14842).
+char(9,14843).
+char(5,14844).
+char(c,14845).
+char(p,14846).
+char(o,14847).
+char(p,14848).
+char(6,14849).
+char(4,14850).
+char(4,14851).
+char(8,14852).
+char(c,14853).
+char(p,14854).
+char(4,14855).
+char(3,14856).
+char(8,14857).
+char(1,14858).
+char(m,14859).
+char(o,14860).
+char(p,14861).
+char(3,14862).
+char(2,14863).
+char(2,14864).
+char(6,14865).
+char(c,14866).
+char(m,14867).
+char(3,14868).
+char(7,14869).
+char(0,14870).
+char(0,14871).
+char(c,14872).
+char(m,14873).
+char(2,14874).
+char(3,14875).
+char(7,14876).
+char(p,14877).
+char(o,14878).
+char(p,14879).
+char(6,14880).
+char(8,14881).
+char(5,14882).
+char(9,14883).
+char(m,14884).
+char(7,14885).
+char(6,14886).
+char(2,14887).
+char(8,14888).
+char(m,14889).
+char(o,14890).
+char(p,14891).
+char(o,14892).
+char(p,14893).
+char(3,14894).
+char(8,14895).
+char(1,14896).
+char(7,14897).
+char(p,14898).
+char(3,14899).
+char(1,14900).
+char(4,14901).
+char(p,14902).
+char(o,14903).
+char(m,14904).
+char(8,14905).
+char(4,14906).
+char(4,14907).
+char(5,14908).
+char(p,14909).
+char(9,14910).
+char(8,14911).
+char(2,14912).
+char(1,14913).
+char(m,14914).
+char(o,14915).
+char(m,14916).
+char(o,14917).
+char(p,14918).
+char(o,14919).
+char(5,14920).
+char(5,14921).
+char(9,14922).
+char(3,14923).
+char(c,14924).
+char(p,14925).
+char(2,14926).
+char(0,14927).
+char(4,14928).
+char(0,14929).
+char(c,14930).
+char(c,14931).
+char(m,14932).
+char(3,14933).
+char(0,14934).
+char(6,14935).
+char(8,14936).
+char(m,14937).
+char(6,14938).
+char(m,14939).
+char(5,14940).
+char(8,14941).
+char(8,14942).
+char(0,14943).
+char(p,14944).
+char(o,14945).
+char(p,14946).
+char(o,14947).
+char(p,14948).
+char(1,14949).
+char(9,14950).
+char(7,14951).
+char(4,14952).
+char(m,14953).
+char(o,14954).
+char(p,14955).
+char(6,14956).
+char(8,14957).
+char(5,14958).
+char(8,14959).
+char(m,14960).
+char(4,14961).
+char(9,14962).
+char(9,14963).
+char(4,14964).
+char(c,14965).
+char(m,14966).
+char(o,14967).
+char(p,14968).
+char(8,14969).
+char(0,14970).
+char(4,14971).
+char(0,14972).
+char(c,14973).
+char(c,14974).
+char(p,14975).
+char(o,14976).
+char(m,14977).
+char(3,14978).
+char(3,14979).
+char(2,14980).
+char(0,14981).
+char(c,14982).
+char(m,14983).
+char(3,14984).
+char(9,14985).
+char(5,14986).
+char(5,14987).
+char(c,14988).
+char(c,14989).
+char(p,14990).
+char(o,14991).
+char(o,14992).
+char(p,14993).
+char(o,14994).
+char(p,14995).
+char(o,14996).
+char(m,14997).
+char(5,14998).
+char(9,14999).
+char(7,15000).
+char(3,15001).
+char(m,15002).
+char(o,15003).
+char(m,15004).
+char(5,15005).
+char(5,15006).
+char(4,15007).
+char(7,15008).
+char(p,15009).
+char(1,15010).
+char(5,15011).
+char(7,15012).
+char(c,15013).
+char(p,15014).
+char(o,15015).
+char(7,15016).
+char(2,15017).
+char(1,15018).
+char(9,15019).
+char(p,15020).
+char(6,15021).
+char(6,15022).
+char(4,15023).
+char(0,15024).
+char(c,15025).
+char(m,15026).
+char(3,15027).
+char(1,15028).
+char(4,15029).
+char(8,15030).
+char(c,15031).
+char(m,15032).
+char(o,15033).
+char(1,15034).
+char(1,15035).
+char(5,15036).
+char(1,15037).
+char(m,15038).
+char(2,15039).
+char(0,15040).
+char(6,15041).
+char(9,15042).
+char(c,15043).
+char(m,15044).
+char(1,15045).
+char(7,15046).
+char(0,15047).
+char(4,15048).
+char(m,15049).
+char(o,15050).
+char(m,15051).
+char(5,15052).
+char(4,15053).
+char(2,15054).
+char(0,15055).
+char(m,15056).
+char(7,15057).
+char(3,15058).
+char(9,15059).
+char(6,15060).
+char(c,15061).
+char(p,15062).
+char(6,15063).
+char(2,15064).
+char(5,15065).
+char(1,15066).
+char(p,15067).
+char(8,15068).
+char(5,15069).
+char(4,15070).
+char(c,15071).
+char(c,15072).
+char(m,15073).
+char(2,15074).
+char(6,15075).
+char(2,15076).
+char(m,15077).
+char(1,15078).
+char(1,15079).
+char(7,15080).
+char(7,15081).
+char(c,15082).
+char(m,15083).
+char(o,15084).
+char(4,15085).
+char(3,15086).
+char(9,15087).
+char(7,15088).
+char(c,15089).
+char(p,15090).
+char(8,15091).
+char(1,15092).
+char(6,15093).
+char(4,15094).
+char(c,15095).
+char(c,15096).
+char(c,15097).
+char(p,15098).
+char(o,15099).
+char(1,15100).
+char(9,15101).
+char(6,15102).
+char(9,15103).
+char(c,15104).
+char(m,15105).
+char(5,15106).
+char(8,15107).
+char(2,15108).
+char(3,15109).
+char(c,15110).
+char(c,15111).
+char(p,15112).
+char(o,15113).
+char(1,15114).
+char(4,15115).
+char(2,15116).
+char(1,15117).
+char(c,15118).
+char(c,15119).
+char(m,15120).
+char(1,15121).
+char(1,15122).
+char(8,15123).
+char(7,15124).
+char(c,15125).
+char(c,15126).
+char(p,15127).
+char(o,15128).
+char(m,15129).
+char(o,15130).
+char(m,15131).
+char(2,15132).
+char(0,15133).
+char(9,15134).
+char(c,15135).
+char(m,15136).
+char(o,15137).
+char(o,15138).
+char(m,15139).
+char(o,15140).
+char(o,15141).
+char(m,15142).
+char(3,15143).
+char(3,15144).
+char(7,15145).
+char(1,15146).
+char(m,15147).
+char(9,15148).
+char(0,15149).
+char(5,15150).
+char(3,15151).
+char(p,15152).
+char(9,15153).
+char(7,15154).
+char(5,15155).
+char(7,15156).
+char(c,15157).
+char(p,15158).
+char(8,15159).
+char(6,15160).
+char(5,15161).
+char(4,15162).
+char(p,15163).
+char(7,15164).
+char(8,15165).
+char(1,15166).
+char(1,15167).
+char(c,15168).
+char(m,15169).
+char(7,15170).
+char(5,15171).
+char(4,15172).
+char(p,15173).
+char(8,15174).
+char(8,15175).
+char(2,15176).
+char(0,15177).
+char(p,15178).
+char(o,15179).
+char(p,15180).
+char(o,15181).
+char(m,15182).
+char(1,15183).
+char(1,15184).
+char(5,15185).
+char(8,15186).
+char(p,15187).
+char(o,15188).
+char(m,15189).
+char(o,15190).
+char(m,15191).
+char(o,15192).
+char(p,15193).
+char(7,15194).
+char(9,15195).
+char(3,15196).
+char(0,15197).
+char(c,15198).
+char(c,15199).
+char(m,15200).
+char(2,15201).
+char(3,15202).
+char(7,15203).
+char(6,15204).
+char(c,15205).
+char(c,15206).
+char(c,15207).
+char(c,15208).
+char(c,15209).
+char(c,15210).
+char(m,15211).
+char(3,15212).
+char(9,15213).
+char(6,15214).
+char(7,15215).
+char(c,15216).
+char(c,15217).
+char(c,15218).
+char(m,15219).
+char(o,15220).
+char(p,15221).
+char(5,15222).
+char(5,15223).
+char(1,15224).
+char(0,15225).
+char(c,15226).
+char(c,15227).
+char(c,15228).
+char(p,15229).
+char(6,15230).
+char(9,15231).
+char(2,15232).
+char(6,15233).
+char(p,15234).
+char(o,15235).
+char(m,15236).
+char(7,15237).
+char(6,15238).
+char(0,15239).
+char(p,15240).
+char(o,15241).
+char(o,15242).
+char(p,15243).
+char(o,15244).
+char(m,15245).
+char(2,15246).
+char(8,15247).
+char(6,15248).
+char(4,15249).
+char(c,15250).
+char(p,15251).
+char(6,15252).
+char(0,15253).
+char(5,15254).
+char(0,15255).
+char(p,15256).
+char(o,15257).
+char(m,15258).
+char(7,15259).
+char(4,15260).
+char(7,15261).
+char(p,15262).
+char(5,15263).
+char(4,15264).
+char(7,15265).
+char(5,15266).
+char(p,15267).
+char(2,15268).
+char(1,15269).
+char(6,15270).
+char(1,15271).
+char(c,15272).
+char(c,15273).
+char(p,15274).
+char(3,15275).
+char(1,15276).
+char(4,15277).
+char(3,15278).
+char(m,15279).
+char(o,15280).
+char(o,15281).
+char(m,15282).
+char(6,15283).
+char(3,15284).
+char(0,15285).
+char(1,15286).
+char(m,15287).
+char(1,15288).
+char(9,15289).
+char(8,15290).
+char(3,15291).
+char(c,15292).
+char(m,15293).
+char(o,15294).
+char(4,15295).
+char(3,15296).
+char(5,15297).
+char(1,15298).
+char(c,15299).
+char(c,15300).
+char(p,15301).
+char(5,15302).
+char(0,15303).
+char(6,15304).
+char(3,15305).
+char(c,15306).
+char(m,15307).
+char(o,15308).
+char(p,15309).
+char(o,15310).
+char(p,15311).
+char(o,15312).
+char(o,15313).
+char(o,15314).
+char(p,15315).
+char(o,15316).
+char(p,15317).
+char(o,15318).
+char(o,15319).
+char(m,15320).
+char(7,15321).
+char(4,15322).
+char(5,15323).
+char(4,15324).
+char(c,15325).
+char(p,15326).
+char(2,15327).
+char(1,15328).
+char(c,15329).
+char(c,15330).
+char(c,15331).
+char(m,15332).
+char(o,15333).
+char(p,15334).
+char(8,15335).
+char(3,15336).
+char(2,15337).
+char(5,15338).
+char(c,15339).
+char(m,15340).
+char(8,15341).
+char(7,15342).
+char(5,15343).
+char(0,15344).
+char(m,15345).
+char(2,15346).
+char(3,15347).
+char(2,15348).
+char(m,15349).
+char(7,15350).
+char(1,15351).
+char(7,15352).
+char(8,15353).
+char(m,15354).
+char(o,15355).
+char(o,15356).
+char(m,15357).
+char(6,15358).
+char(4,15359).
+char(9,15360).
+char(1,15361).
+char(c,15362).
+char(m,15363).
+char(6,15364).
+char(5,15365).
+char(5,15366).
+char(1,15367).
+char(m,15368).
+char(4,15369).
+char(0,15370).
+char(7,15371).
+char(7,15372).
+char(c,15373).
+char(c,15374).
+char(c,15375).
+char(c,15376).
+char(c,15377).
+char(p,15378).
+char(o,15379).
+char(p,15380).
+char(7,15381).
+char(2,15382).
+char(2,15383).
+char(1,15384).
+char(c,15385).
+char(c,15386).
+char(m,15387).
+char(3,15388).
+char(6,15389).
+char(6,15390).
+char(9,15391).
+char(m,15392).
+char(o,15393).
+char(6,15394).
+char(0,15395).
+char(1,15396).
+char(8,15397).
+char(c,15398).
+char(c,15399).
+char(m,15400).
+char(o,15401).
+char(m,15402).
+char(o,15403).
+char(p,15404).
+char(o,15405).
+char(p,15406).
+char(5,15407).
+char(2,15408).
+char(3,15409).
+char(4,15410).
+char(p,15411).
+char(o,15412).
+char(4,15413).
+char(1,15414).
+char(8,15415).
+char(4,15416).
+char(m,15417).
+char(9,15418).
+char(3,15419).
+char(4,15420).
+char(7,15421).
+char(c,15422).
+char(c,15423).
+char(c,15424).
+char(m,15425).
+char(1,15426).
+char(5,15427).
+char(1,15428).
+char(2,15429).
+char(m,15430).
+char(4,15431).
+char(0,15432).
+char(6,15433).
+char(9,15434).
+char(c,15435).
+char(p,15436).
+char(1,15437).
+char(7,15438).
+char(5,15439).
+char(6,15440).
+char(c,15441).
+char(c,15442).
+char(c,15443).
+char(p,15444).
+char(o,15445).
+char(p,15446).
+char(o,15447).
+char(o,15448).
+char(5,15449).
+char(1,15450).
+char(1,15451).
+char(3,15452).
+char(c,15453).
+char(p,15454).
+char(1,15455).
+char(9,15456).
+char(7,15457).
+char(p,15458).
+char(2,15459).
+char(5,15460).
+char(2,15461).
+char(7,15462).
+char(m,15463).
+char(o,15464).
+char(o,15465).
+char(5,15466).
+char(2,15467).
+char(8,15468).
+char(0,15469).
+char(m,15470).
+char(o,15471).
+char(m,15472).
+char(o,15473).
+char(o,15474).
+char(p,15475).
+char(2,15476).
+char(1,15477).
+char(8,15478).
+char(9,15479).
+char(p,15480).
+char(o,15481).
+char(m,15482).
+char(9,15483).
+char(6,15484).
+char(7,15485).
+char(m,15486).
+char(8,15487).
+char(4,15488).
+char(1,15489).
+char(7,15490).
+char(c,15491).
+char(c,15492).
+char(m,15493).
+char(o,15494).
+char(o,15495).
+char(m,15496).
+char(o,15497).
+char(m,15498).
+char(3,15499).
+char(6,15500).
+char(3,15501).
+char(8,15502).
+char(p,15503).
+char(o,15504).
+char(p,15505).
+char(5,15506).
+char(7,15507).
+char(8,15508).
+char(6,15509).
+char(c,15510).
+char(m,15511).
+char(o,15512).
+char(m,15513).
+char(o,15514).
+char(2,15515).
+char(5,15516).
+char(3,15517).
+char(4,15518).
+char(c,15519).
+char(p,15520).
+char(1,15521).
+char(4,15522).
+char(p,15523).
+char(3,15524).
+char(4,15525).
+char(4,15526).
+char(1,15527).
+char(p,15528).
+char(o,15529).
+char(m,15530).
+char(o,15531).
+char(9,15532).
+char(6,15533).
+char(1,15534).
+char(2,15535).
+char(c,15536).
+char(c,15537).
+char(c,15538).
+char(c,15539).
+char(p,15540).
+char(o,15541).
+char(p,15542).
+char(o,15543).
+char(4,15544).
+char(7,15545).
+char(0,15546).
+char(6,15547).
+char(m,15548).
+char(9,15549).
+char(7,15550).
+char(3,15551).
+char(p,15552).
+char(2,15553).
+char(8,15554).
+char(4,15555).
+char(7,15556).
+char(c,15557).
+char(p,15558).
+char(1,15559).
+char(5,15560).
+char(2,15561).
+char(9,15562).
+char(c,15563).
+char(p,15564).
+char(o,15565).
+char(o,15566).
+char(o,15567).
+char(2,15568).
+char(6,15569).
+char(4,15570).
+char(p,15571).
+char(7,15572).
+char(8,15573).
+char(8,15574).
+char(4,15575).
+char(p,15576).
+char(o,15577).
+char(p,15578).
+char(o,15579).
+char(m,15580).
+char(o,15581).
+char(m,15582).
+char(6,15583).
+char(7,15584).
+char(9,15585).
+char(3,15586).
+char(m,15587).
+char(1,15588).
+char(3,15589).
+char(3,15590).
+char(8,15591).
+char(c,15592).
+char(m,15593).
+char(3,15594).
+char(9,15595).
+char(1,15596).
+char(p,15597).
+char(o,15598).
+char(m,15599).
+char(o,15600).
+char(m,15601).
+char(o,15602).
+char(p,15603).
+char(o,15604).
+char(p,15605).
+char(o,15606).
+char(m,15607).
+char(o,15608).
+char(p,15609).
+char(o,15610).
+char(p,15611).
+char(6,15612).
+char(2,15613).
+char(6,15614).
+char(3,15615).
+char(c,15616).
+char(p,15617).
+char(9,15618).
+char(8,15619).
+char(2,15620).
+char(9,15621).
+char(c,15622).
+char(m,15623).
+char(o,15624).
+char(m,15625).
+char(1,15626).
+char(2,15627).
+char(8,15628).
+char(0,15629).
+char(c,15630).
+char(m,15631).
+char(o,15632).
+char(o,15633).
+char(m,15634).
+char(o,15635).
+char(p,15636).
+char(o,15637).
+char(8,15638).
+char(1,15639).
+char(9,15640).
+char(1,15641).
+char(m,15642).
+char(o,15643).
+char(m,15644).
+char(o,15645).
+char(9,15646).
+char(6,15647).
+char(1,15648).
+char(4,15649).
+char(m,15650).
+char(2,15651).
+char(2,15652).
+char(5,15653).
+char(9,15654).
+char(c,15655).
+char(p,15656).
+char(o,15657).
+char(o,15658).
+char(p,15659).
+char(o,15660).
+char(m,15661).
+char(8,15662).
+char(2,15663).
+char(6,15664).
+char(7,15665).
+char(p,15666).
+char(o,15667).
+char(p,15668).
+char(5,15669).
+char(6,15670).
+char(8,15671).
+char(6,15672).
+char(p,15673).
+char(o,15674).
+char(p,15675).
+char(7,15676).
+char(p,15677).
+char(3,15678).
+char(3,15679).
+char(5,15680).
+char(m,15681).
+char(o,15682).
+char(m,15683).
+char(9,15684).
+char(6,15685).
+char(2,15686).
+char(2,15687).
+char(p,15688).
+char(o,15689).
+char(o,15690).
+char(m,15691).
+char(9,15692).
+char(5,15693).
+char(4,15694).
+char(5,15695).
+char(c,15696).
+char(m,15697).
+char(2,15698).
+char(9,15699).
+char(8,15700).
+char(9,15701).
+char(c,15702).
+char(c,15703).
+char(p,15704).
+char(9,15705).
+char(1,15706).
+char(5,15707).
+char(1,15708).
+char(c,15709).
+char(m,15710).
+char(o,15711).
+char(p,15712).
+char(o,15713).
+char(o,15714).
+char(m,15715).
+char(5,15716).
+char(6,15717).
+char(2,15718).
+char(7,15719).
+char(c,15720).
+char(c,15721).
+char(c,15722).
+char(p,15723).
+char(o,15724).
+char(p,15725).
+char(o,15726).
+char(m,15727).
+char(9,15728).
+char(7,15729).
+char(7,15730).
+char(6,15731).
+char(c,15732).
+char(c,15733).
+char(p,15734).
+char(4,15735).
+char(3,15736).
+char(2,15737).
+char(5,15738).
+char(m,15739).
+char(o,15740).
+char(p,15741).
+char(o,15742).
+char(m,15743).
+char(2,15744).
+char(1,15745).
+char(9,15746).
+char(6,15747).
+char(p,15748).
+char(o,15749).
+char(3,15750).
+char(8,15751).
+char(4,15752).
+char(0,15753).
+char(m,15754).
+char(o,15755).
+char(m,15756).
+char(7,15757).
+char(0,15758).
+char(1,15759).
+char(9,15760).
+char(c,15761).
+char(m,15762).
+char(o,15763).
+char(4,15764).
+char(0,15765).
+char(4,15766).
+char(2,15767).
+char(c,15768).
+char(c,15769).
+char(c,15770).
+char(p,15771).
+char(o,15772).
+char(m,15773).
+char(8,15774).
+char(9,15775).
+char(7,15776).
+char(4,15777).
+char(m,15778).
+char(o,15779).
+char(p,15780).
+char(o,15781).
+char(8,15782).
+char(6,15783).
+char(6,15784).
+char(3,15785).
+char(c,15786).
+char(m,15787).
+char(o,15788).
+char(p,15789).
+char(6,15790).
+char(6,15791).
+char(9,15792).
+char(9,15793).
+char(m,15794).
+char(o,15795).
+char(p,15796).
+char(2,15797).
+char(7,15798).
+char(0,15799).
+char(2,15800).
+char(m,15801).
+char(o,15802).
+char(o,15803).
+char(3,15804).
+char(3,15805).
+char(8,15806).
+char(8,15807).
+char(c,15808).
+char(p,15809).
+char(o,15810).
+char(m,15811).
+char(o,15812).
+char(1,15813).
+char(3,15814).
+char(9,15815).
+char(3,15816).
+char(m,15817).
+char(o,15818).
+char(2,15819).
+char(9,15820).
+char(2,15821).
+char(1,15822).
+char(c,15823).
+char(m,15824).
+char(2,15825).
+char(4,15826).
+char(9,15827).
+char(8,15828).
+char(p,15829).
+char(o,15830).
+char(p,15831).
+char(3,15832).
+char(7,15833).
+char(9,15834).
+char(3,15835).
+char(m,15836).
+char(2,15837).
+char(1,15838).
+char(6,15839).
+char(8,15840).
+char(c,15841).
+char(c,15842).
+char(c,15843).
+char(m,15844).
+char(5,15845).
+char(3,15846).
+char(5,15847).
+char(2,15848).
+char(c,15849).
+char(c,15850).
+char(p,15851).
+char(5,15852).
+char(8,15853).
+char(8,15854).
+char(5,15855).
+char(m,15856).
+char(o,15857).
+char(m,15858).
+char(6,15859).
+char(4,15860).
+char(8,15861).
+char(2,15862).
+char(p,15863).
+char(o,15864).
+char(p,15865).
+char(o,15866).
+char(m,15867).
+char(o,15868).
+char(6,15869).
+char(0,15870).
+char(7,15871).
+char(5,15872).
+char(c,15873).
+char(p,15874).
+char(9,15875).
+char(4,15876).
+char(3,15877).
+char(9,15878).
+char(p,15879).
+char(2,15880).
+char(4,15881).
+char(6,15882).
+char(1,15883).
+char(m,15884).
+char(o,15885).
+char(7,15886).
+char(7,15887).
+char(2,15888).
+char(1,15889).
+char(c,15890).
+char(c,15891).
+char(m,15892).
+char(o,15893).
+char(m,15894).
+char(o,15895).
+char(o,15896).
+char(o,15897).
+char(3,15898).
+char(4,15899).
+char(8,15900).
+char(2,15901).
+char(c,15902).
+char(m,15903).
+char(6,15904).
+char(0,15905).
+char(0,15906).
+char(4,15907).
+char(c,15908).
+char(c,15909).
+char(m,15910).
+char(o,15911).
+char(5,15912).
+char(3,15913).
+char(5,15914).
+char(2,15915).
+char(c,15916).
+char(p,15917).
+char(o,15918).
+char(m,15919).
+char(o,15920).
+char(m,15921).
+char(5,15922).
+char(9,15923).
+char(6,15924).
+char(1,15925).
+char(m,15926).
+char(o,15927).
+char(p,15928).
+char(o,15929).
+char(o,15930).
+char(4,15931).
+char(5,15932).
+char(0,15933).
+char(4,15934).
+char(c,15935).
+char(m,15936).
+char(2,15937).
+char(5,15938).
+char(7,15939).
+char(9,15940).
+char(c,15941).
+char(m,15942).
+char(5,15943).
+char(4,15944).
+char(5,15945).
+char(9,15946).
+char(c,15947).
+char(c,15948).
+char(p,15949).
+char(8,15950).
+char(8,15951).
+char(8,15952).
+char(6,15953).
+char(c,15954).
+char(p,15955).
+char(o,15956).
+char(m,15957).
+char(o,15958).
+char(p,15959).
+char(o,15960).
+char(o,15961).
+char(m,15962).
+char(o,15963).
+char(p,15964).
+char(o,15965).
+char(o,15966).
+char(p,15967).
+char(4,15968).
+char(7,15969).
+char(6,15970).
+char(4,15971).
+char(p,15972).
+char(2,15973).
+char(7,15974).
+char(7,15975).
+char(6,15976).
+char(c,15977).
+char(m,15978).
+char(7,15979).
+char(4,15980).
+char(1,15981).
+char(7,15982).
+char(p,15983).
+char(o,15984).
+char(p,15985).
+char(4,15986).
+char(3,15987).
+char(0,15988).
+char(3,15989).
+char(c,15990).
+char(p,15991).
+char(o,15992).
+char(2,15993).
+char(8,15994).
+char(5,15995).
+char(1,15996).
+char(c,15997).
+char(c,15998).
+char(c,15999).
+char(c,16000).
+char(c,16001).
+char(c,16002).
+char(p,16003).
+char(o,16004).
+char(p,16005).
+char(4,16006).
+char(7,16007).
+char(8,16008).
+char(6,16009).
+char(c,16010).
+char(c,16011).
+char(m,16012).
+char(7,16013).
+char(2,16014).
+char(8,16015).
+char(9,16016).
+char(c,16017).
+char(c,16018).
+char(c,16019).
+char(m,16020).
+char(o,16021).
+char(5,16022).
+char(2,16023).
+char(0,16024).
+char(3,16025).
+char(p,16026).
+char(o,16027).
+char(p,16028).
+char(7,16029).
+char(4,16030).
+char(2,16031).
+char(6,16032).
+char(m,16033).
+char(o,16034).
+char(p,16035).
+char(4,16036).
+char(8,16037).
+char(1,16038).
+char(c,16039).
+char(c,16040).
+char(c,16041).
+char(p,16042).
+char(o,16043).
+char(p,16044).
+char(8,16045).
+char(4,16046).
+char(2,16047).
+char(2,16048).
+char(c,16049).
+char(m,16050).
+char(o,16051).
+char(m,16052).
+char(5,16053).
+char(0,16054).
+char(2,16055).
+char(7,16056).
+char(p,16057).
+char(2,16058).
+char(8,16059).
+char(3,16060).
+char(8,16061).
+char(c,16062).
+char(c,16063).
+char(m,16064).
+char(o,16065).
+char(7,16066).
+char(6,16067).
+char(9,16068).
+char(1,16069).
+char(p,16070).
+char(o,16071).
+char(o,16072).
+char(m,16073).
+char(8,16074).
+char(6,16075).
+char(7,16076).
+char(5,16077).
+char(m,16078).
+char(5,16079).
+char(6,16080).
+char(2,16081).
+char(6,16082).
+char(m,16083).
+char(o,16084).
+char(m,16085).
+char(4,16086).
+char(8,16087).
+char(9,16088).
+char(9,16089).
+char(c,16090).
+char(c,16091).
+char(c,16092).
+char(p,16093).
+char(o,16094).
+char(9,16095).
+char(4,16096).
+char(6,16097).
+char(0,16098).
+char(c,16099).
+char(c,16100).
+char(m,16101).
+char(o,16102).
+char(o,16103).
+char(o,16104).
+char(o,16105).
+char(m,16106).
+char(7,16107).
+char(5,16108).
+char(1,16109).
+char(6,16110).
+char(c,16111).
+char(m,16112).
+char(4,16113).
+char(4,16114).
+char(3,16115).
+char(2,16116).
+char(c,16117).
+char(c,16118).
+char(m,16119).
+char(4,16120).
+char(8,16121).
+char(4,16122).
+char(4,16123).
+char(c,16124).
+char(m,16125).
+char(o,16126).
+char(p,16127).
+char(o,16128).
+char(o,16129).
+char(p,16130).
+char(o,16131).
+char(o,16132).
+char(p,16133).
+char(5,16134).
+char(5,16135).
+char(3,16136).
+char(5,16137).
+char(p,16138).
+char(o,16139).
+char(p,16140).
+char(o,16141).
+char(m,16142).
+char(6,16143).
+char(3,16144).
+char(9,16145).
+char(6,16146).
+char(m,16147).
+char(o,16148).
+char(6,16149).
+char(4,16150).
+char(2,16151).
+char(2,16152).
+char(c,16153).
+char(p,16154).
+char(o,16155).
+char(o,16156).
+char(p,16157).
+char(o,16158).
+char(m,16159).
+char(3,16160).
+char(5,16161).
+char(7,16162).
+char(4,16163).
+char(c,16164).
+char(p,16165).
+char(o,16166).
+char(m,16167).
+char(o,16168).
+char(p,16169).
+char(7,16170).
+char(2,16171).
+char(9,16172).
+char(0,16173).
+char(m,16174).
+char(5,16175).
+char(1,16176).
+char(9,16177).
+char(9,16178).
+char(c,16179).
+char(c,16180).
+char(p,16181).
+char(o,16182).
+char(p,16183).
+char(o,16184).
+char(p,16185).
+char(1,16186).
+char(4,16187).
+char(1,16188).
+char(6,16189).
+char(c,16190).
+char(c,16191).
+char(c,16192).
+char(c,16193).
+char(p,16194).
+char(o,16195).
+char(m,16196).
+char(o,16197).
+char(9,16198).
+char(3,16199).
+char(4,16200).
+char(4,16201).
+char(m,16202).
+char(o,16203).
+char(m,16204).
+char(o,16205).
+char(m,16206).
+char(7,16207).
+char(5,16208).
+char(9,16209).
+char(5,16210).
+char(c,16211).
+char(m,16212).
+char(7,16213).
+char(6,16214).
+char(4,16215).
+char(9,16216).
+char(c,16217).
+char(c,16218).
+char(m,16219).
+char(o,16220).
+char(p,16221).
+char(2,16222).
+char(6,16223).
+char(0,16224).
+char(0,16225).
+char(c,16226).
+char(p,16227).
+char(1,16228).
+char(8,16229).
+char(0,16230).
+char(3,16231).
+char(m,16232).
+char(o,16233).
+char(m,16234).
+char(o,16235).
+char(m,16236).
+char(9,16237).
+char(9,16238).
+char(1,16239).
+char(4,16240).
+char(p,16241).
+char(2,16242).
+char(8,16243).
+char(7,16244).
+char(3,16245).
+char(m,16246).
+char(1,16247).
+char(4,16248).
+char(1,16249).
+char(9,16250).
+char(p,16251).
+char(o,16252).
+char(p,16253).
+char(o,16254).
+char(m,16255).
+char(o,16256).
+char(m,16257).
+char(6,16258).
+char(1,16259).
+char(8,16260).
+char(7,16261).
+char(m,16262).
+char(1,16263).
+char(4,16264).
+char(7,16265).
+char(9,16266).
+char(c,16267).
+char(p,16268).
+char(o,16269).
+char(6,16270).
+char(2,16271).
+char(7,16272).
+char(3,16273).
+char(c,16274).
+char(p,16275).
+char(o,16276).
+char(1,16277).
+char(1,16278).
+char(7,16279).
+char(4,16280).
+char(c,16281).
+char(c,16282).
+char(c,16283).
+char(c,16284).
+char(p,16285).
+char(o,16286).
+char(p,16287).
+char(6,16288).
+char(2,16289).
+char(7,16290).
+char(9,16291).
+char(c,16292).
+char(m,16293).
+char(o,16294).
+char(m,16295).
+char(5,16296).
+char(4,16297).
+char(0,16298).
+char(2,16299).
+char(c,16300).
+char(c,16301).
+char(c,16302).
+char(c,16303).
+char(m,16304).
+char(o,16305).
+char(m,16306).
+char(5,16307).
+char(4,16308).
+char(5,16309).
+char(5,16310).
+char(p,16311).
+char(o,16312).
+char(p,16313).
+char(o,16314).
+char(o,16315).
+char(p,16316).
+char(o,16317).
+char(p,16318).
+char(4,16319).
+char(8,16320).
+char(7,16321).
+char(6,16322).
+char(c,16323).
+char(c,16324).
+char(c,16325).
+char(m,16326).
+char(9,16327).
+char(6,16328).
+char(0,16329).
+char(0,16330).
+char(m,16331).
+char(o,16332).
+char(p,16333).
+char(9,16334).
+char(8,16335).
+char(9,16336).
+char(0,16337).
+char(c,16338).
+char(c,16339).
+char(c,16340).
+char(m,16341).
+char(4,16342).
+char(9,16343).
+char(9,16344).
+char(5,16345).
+char(m,16346).
+char(o,16347).
+char(o,16348).
+char(m,16349).
+char(9,16350).
+char(0,16351).
+char(3,16352).
+char(4,16353).
+char(c,16354).
+char(m,16355).
+char(7,16356).
+char(6,16357).
+char(0,16358).
+char(4,16359).
+char(m,16360).
+char(o,16361).
+char(m,16362).
+char(o,16363).
+char(p,16364).
+char(o,16365).
+char(o,16366).
+char(m,16367).
+char(o,16368).
+char(p,16369).
+char(o,16370).
+char(m,16371).
+char(9,16372).
+char(8,16373).
+char(0,16374).
+char(4,16375).
+char(p,16376).
+char(2,16377).
+char(0,16378).
+char(3,16379).
+char(0,16380).
+char(c,16381).
+char(c,16382).
+char(c,16383).
+char(p,16384).
+char(7,16385).
+char(0,16386).
+char(6,16387).
+char(6,16388).
+char(p,16389).
+char(3,16390).
+char(3,16391).
+char(4,16392).
+char(9,16393).
+char(p,16394).
+char(o,16395).
+char(p,16396).
+char(1,16397).
+char(7,16398).
+char(6,16399).
+char(6,16400).
+char(c,16401).
+char(m,16402).
+char(o,16403).
+char(p,16404).
+char(1,16405).
+char(7,16406).
+char(2,16407).
+char(9,16408).
+char(c,16409).
+char(c,16410).
+char(m,16411).
+char(4,16412).
+char(m,16413).
+char(o,16414).
+char(m,16415).
+char(7,16416).
+char(1,16417).
+char(2,16418).
+char(2,16419).
+char(c,16420).
+char(m,16421).
+char(o,16422).
+char(o,16423).
+char(7,16424).
+char(3,16425).
+char(8,16426).
+char(8,16427).
+char(c,16428).
+char(p,16429).
+char(o,16430).
+char(m,16431).
+char(o,16432).
+char(m,16433).
+char(o,16434).
+char(p,16435).
+char(8,16436).
+char(6,16437).
+char(5,16438).
+char(4,16439).
+char(p,16440).
+char(o,16441).
+char(m,16442).
+char(3,16443).
+char(8,16444).
+char(0,16445).
+char(3,16446).
+char(c,16447).
+char(p,16448).
+char(o,16449).
+char(4,16450).
+char(7,16451).
+char(9,16452).
+char(7,16453).
+char(c,16454).
+char(c,16455).
+char(m,16456).
+char(9,16457).
+char(8,16458).
+char(0,16459).
+char(5,16460).
+char(c,16461).
+char(c,16462).
+char(p,16463).
+char(o,16464).
+char(m,16465).
+char(o,16466).
+char(8,16467).
+char(6,16468).
+char(2,16469).
+char(8,16470).
+char(c,16471).
+char(c,16472).
+char(m,16473).
+char(o,16474).
+char(m,16475).
+char(o,16476).
+char(p,16477).
+char(8,16478).
+char(6,16479).
+char(2,16480).
+char(3,16481).
+char(m,16482).
+char(o,16483).
+char(o,16484).
+char(p,16485).
+char(3,16486).
+char(1,16487).
+char(0,16488).
+char(4,16489).
+char(c,16490).
+char(p,16491).
+char(o,16492).
+char(m,16493).
+char(o,16494).
+char(o,16495).
+char(m,16496).
+char(8,16497).
+char(6,16498).
+char(5,16499).
+char(6,16500).
+char(c,16501).
+char(c,16502).
+char(c,16503).
+char(p,16504).
+char(o,16505).
+char(p,16506).
+char(1,16507).
+char(4,16508).
+char(1,16509).
+char(6,16510).
+char(c,16511).
+char(m,16512).
+char(6,16513).
+char(1,16514).
+char(0,16515).
+char(5,16516).
+char(c,16517).
+char(p,16518).
+char(7,16519).
+char(7,16520).
+char(9,16521).
+char(4,16522).
+char(p,16523).
+char(6,16524).
+char(7,16525).
+char(5,16526).
+char(3,16527).
+char(m,16528).
+char(o,16529).
+char(6,16530).
+char(1,16531).
+char(8,16532).
+char(5,16533).
+char(m,16534).
+char(9,16535).
+char(9,16536).
+char(4,16537).
+char(3,16538).
+char(p,16539).
+char(1,16540).
+char(1,16541).
+char(7,16542).
+char(m,16543).
+char(8,16544).
+char(9,16545).
+char(5,16546).
+char(c,16547).
+char(c,16548).
+char(m,16549).
+char(o,16550).
+char(7,16551).
+char(6,16552).
+char(7,16553).
+char(c,16554).
+char(c,16555).
+char(p,16556).
+char(o,16557).
+char(p,16558).
+char(4,16559).
+char(4,16560).
+char(6,16561).
+char(1,16562).
+char(p,16563).
+char(o,16564).
+char(m,16565).
+char(o,16566).
+char(8,16567).
+char(1,16568).
+char(4,16569).
+char(8,16570).
+char(p,16571).
+char(o,16572).
+char(8,16573).
+char(1,16574).
+char(7,16575).
+char(5,16576).
+char(c,16577).
+char(c,16578).
+char(p,16579).
+char(8,16580).
+char(7,16581).
+char(6,16582).
+char(5,16583).
+char(c,16584).
+char(m,16585).
+char(o,16586).
+char(p,16587).
+char(o,16588).
+char(m,16589).
+char(3,16590).
+char(4,16591).
+char(2,16592).
+char(6,16593).
+char(c,16594).
+char(c,16595).
+char(c,16596).
+char(c,16597).
+char(p,16598).
+char(3,16599).
+char(0,16600).
+char(8,16601).
+char(8,16602).
+char(p,16603).
+char(6,16604).
+char(8,16605).
+char(3,16606).
+char(1,16607).
+char(m,16608).
+char(6,16609).
+char(9,16610).
+char(0,16611).
+char(m,16612).
+char(8,16613).
+char(0,16614).
+char(3,16615).
+char(7,16616).
+char(p,16617).
+char(6,16618).
+char(7,16619).
+char(2,16620).
+char(6,16621).
+char(m,16622).
+char(2,16623).
+char(3,16624).
+char(6,16625).
+char(7,16626).
+char(c,16627).
+char(p,16628).
+char(1,16629).
+char(3,16630).
+char(4,16631).
+char(5,16632).
+char(c,16633).
+char(c,16634).
+char(m,16635).
+char(o,16636).
+char(m,16637).
+char(o,16638).
+char(9,16639).
+char(6,16640).
+char(4,16641).
+char(4,16642).
+char(p,16643).
+char(o,16644).
+char(p,16645).
+char(o,16646).
+char(2,16647).
+char(3,16648).
+char(3,16649).
+char(1,16650).
+char(c,16651).
+char(p,16652).
+char(o,16653).
+char(p,16654).
+char(1,16655).
+char(1,16656).
+char(2,16657).
+char(7,16658).
+char(m,16659).
+char(4,16660).
+char(5,16661).
+char(5,16662).
+char(0,16663).
+char(m,16664).
+char(7,16665).
+char(5,16666).
+char(5,16667).
+char(5,16668).
+char(c,16669).
+char(m,16670).
+char(o,16671).
+char(6,16672).
+char(9,16673).
+char(0,16674).
+char(9,16675).
+char(c,16676).
+char(p,16677).
+char(6,16678).
+char(5,16679).
+char(8,16680).
+char(4,16681).
+char(c,16682).
+char(c,16683).
+char(p,16684).
+char(6,16685).
+char(5,16686).
+char(6,16687).
+char(5,16688).
+char(c,16689).
+char(c,16690).
+char(m,16691).
+char(1,16692).
+char(5,16693).
+char(3,16694).
+char(9,16695).
+char(m,16696).
+char(6,16697).
+char(2,16698).
+char(8,16699).
+char(5,16700).
+char(p,16701).
+char(o,16702).
+char(2,16703).
+char(4,16704).
+char(7,16705).
+char(4,16706).
+char(p,16707).
+char(8,16708).
+char(3,16709).
+char(2,16710).
+char(2,16711).
+char(c,16712).
+char(p,16713).
+char(1,16714).
+char(6,16715).
+char(5,16716).
+char(3,16717).
+char(c,16718).
+char(c,16719).
+char(c,16720).
+char(p,16721).
+char(2,16722).
+char(3,16723).
+char(8,16724).
+char(2,16725).
+char(p,16726).
+char(5,16727).
+char(5,16728).
+char(c,16729).
+char(p,16730).
+char(o,16731).
+char(m,16732).
+char(8,16733).
+char(8,16734).
+char(6,16735).
+char(5,16736).
+char(c,16737).
+char(m,16738).
+char(o,16739).
+char(p,16740).
+char(3,16741).
+char(1,16742).
+char(0,16743).
+char(1,16744).
+char(c,16745).
+char(m,16746).
+char(9,16747).
+char(1,16748).
+char(1,16749).
+char(7,16750).
+char(p,16751).
+char(o,16752).
+char(p,16753).
+char(o,16754).
+char(o,16755).
+char(o,16756).
+char(p,16757).
+char(5,16758).
+char(6,16759).
+char(9,16760).
+char(8,16761).
+char(c,16762).
+char(p,16763).
+char(o,16764).
+char(m,16765).
+char(5,16766).
+char(8,16767).
+char(5,16768).
+char(5,16769).
+char(c,16770).
+char(p,16771).
+char(4,16772).
+char(5,16773).
+char(4,16774).
+char(9,16775).
+char(c,16776).
+char(m,16777).
+char(2,16778).
+char(3,16779).
+char(3,16780).
+char(8,16781).
+char(c,16782).
+char(c,16783).
+char(p,16784).
+char(o,16785).
+char(1,16786).
+char(8,16787).
+char(0,16788).
+char(4,16789).
+char(c,16790).
+char(m,16791).
+char(2,16792).
+char(8,16793).
+char(8,16794).
+char(c,16795).
+char(c,16796).
+char(p,16797).
+char(o,16798).
+char(o,16799).
+char(p,16800).
+char(o,16801).
+char(o,16802).
+char(m,16803).
+char(o,16804).
+char(1,16805).
+char(4,16806).
+char(5,16807).
+char(1,16808).
+char(c,16809).
+char(c,16810).
+char(c,16811).
+char(p,16812).
+char(o,16813).
+char(4,16814).
+char(2,16815).
+char(8,16816).
+char(p,16817).
+char(3,16818).
+char(1,16819).
+char(8,16820).
+char(m,16821).
+char(o,16822).
+char(m,16823).
+char(o,16824).
+char(9,16825).
+char(9,16826).
+char(6,16827).
+char(7,16828).
+char(c,16829).
+char(c,16830).
+char(c,16831).
+char(p,16832).
+char(9,16833).
+char(9,16834).
+char(2,16835).
+char(9,16836).
+char(p,16837).
+char(7,16838).
+char(5,16839).
+char(7,16840).
+char(4,16841).
+char(c,16842).
+char(c,16843).
+char(c,16844).
+char(m,16845).
+char(1,16846).
+char(3,16847).
+char(2,16848).
+char(m,16849).
+char(9,16850).
+char(4,16851).
+char(2,16852).
+char(0,16853).
+char(c,16854).
+char(p,16855).
+char(o,16856).
+char(5,16857).
+char(0,16858).
+char(6,16859).
+char(6,16860).
+char(c,16861).
+char(c,16862).
+char(c,16863).
+char(p,16864).
+char(8,16865).
+char(7,16866).
+char(0,16867).
+char(0,16868).
+char(m,16869).
+char(8,16870).
+char(2,16871).
+char(3,16872).
+char(8,16873).
+char(c,16874).
+char(p,16875).
+char(o,16876).
+char(o,16877).
+char(m,16878).
+char(4,16879).
+char(8,16880).
+char(6,16881).
+char(7,16882).
+char(m,16883).
+char(o,16884).
+char(p,16885).
+char(o,16886).
+char(o,16887).
+char(4,16888).
+char(7,16889).
+char(2,16890).
+char(7,16891).
+char(p,16892).
+char(6,16893).
+char(5,16894).
+char(0,16895).
+char(7,16896).
+char(p,16897).
+char(o,16898).
+char(1,16899).
+char(2,16900).
+char(1,16901).
+char(0,16902).
+char(m,16903).
+char(o,16904).
+char(m,16905).
+char(o,16906).
+char(p,16907).
+char(9,16908).
+char(3,16909).
+char(3,16910).
+char(2,16911).
+char(c,16912).
+char(c,16913).
+char(c,16914).
+char(m,16915).
+char(3,16916).
+char(9,16917).
+char(6,16918).
+char(2,16919).
+char(c,16920).
+char(p,16921).
+char(o,16922).
+char(p,16923).
+char(o,16924).
+char(m,16925).
+char(o,16926).
+char(o,16927).
+char(m,16928).
+char(9,16929).
+char(7,16930).
+char(7,16931).
+char(9,16932).
+char(m,16933).
+char(5,16934).
+char(9,16935).
+char(9,16936).
+char(0,16937).
+char(p,16938).
+char(3,16939).
+char(0,16940).
+char(1,16941).
+char(4,16942).
+char(p,16943).
+char(o,16944).
+char(m,16945).
+char(4,16946).
+char(4,16947).
+char(9,16948).
+char(5,16949).
+char(m,16950).
+char(2,16951).
+char(0,16952).
+char(4,16953).
+char(m,16954).
+char(8,16955).
+char(7,16956).
+char(5,16957).
+char(9,16958).
+char(c,16959).
+char(c,16960).
+char(c,16961).
+char(c,16962).
+char(c,16963).
+char(c,16964).
+char(p,16965).
+char(7,16966).
+char(5,16967).
+char(0,16968).
+char(1,16969).
+char(c,16970).
+char(p,16971).
+char(6,16972).
+char(1,16973).
+char(7,16974).
+char(1,16975).
+char(c,16976).
+char(c,16977).
+char(p,16978).
+char(1,16979).
+char(3,16980).
+char(0,16981).
+char(8,16982).
+char(c,16983).
+char(p,16984).
+char(3,16985).
+char(0,16986).
+char(6,16987).
+char(8,16988).
+char(m,16989).
+char(6,16990).
+char(7,16991).
+char(5,16992).
+char(8,16993).
+char(m,16994).
+char(8,16995).
+char(6,16996).
+char(4,16997).
+char(5,16998).
+char(m,16999).
+char(1,17000).
+char(9,17001).
+char(7,17002).
+char(8,17003).
+char(c,17004).
+char(p,17005).
+char(5,17006).
+char(7,17007).
+char(1,17008).
+char(9,17009).
+char(c,17010).
+char(c,17011).
+char(c,17012).
+char(p,17013).
+char(o,17014).
+char(p,17015).
+char(7,17016).
+char(5,17017).
+char(2,17018).
+char(0,17019).
+char(c,17020).
+char(c,17021).
+char(m,17022).
+char(4,17023).
+char(5,17024).
+char(7,17025).
+char(1,17026).
+char(m,17027).
+char(5,17028).
+char(7,17029).
+char(2,17030).
+char(5,17031).
+char(c,17032).
+char(c,17033).
+char(c,17034).
+char(c,17035).
+char(c,17036).
+char(m,17037).
+char(o,17038).
+char(o,17039).
+char(m,17040).
+char(o,17041).
+char(m,17042).
+char(9,17043).
+char(6,17044).
+char(9,17045).
+char(8,17046).
+char(m,17047).
+char(o,17048).
+char(p,17049).
+char(4,17050).
+char(2,17051).
+char(3,17052).
+char(7,17053).
+char(c,17054).
+char(c,17055).
+char(c,17056).
+char(m,17057).
+char(2,17058).
+char(8,17059).
+char(0,17060).
+char(1,17061).
+char(c,17062).
+char(p,17063).
+char(3,17064).
+char(5,17065).
+char(9,17066).
+char(6,17067).
+char(m,17068).
+char(o,17069).
+char(m,17070).
+char(o,17071).
+char(2,17072).
+char(2,17073).
+char(3,17074).
+char(9,17075).
+char(c,17076).
+char(c,17077).
+char(p,17078).
+char(5,17079).
+char(9,17080).
+char(2,17081).
+char(7,17082).
+char(c,17083).
+char(m,17084).
+char(5,17085).
+char(2,17086).
+char(3,17087).
+char(2,17088).
+char(p,17089).
+char(4,17090).
+char(9,17091).
+char(6,17092).
+char(c,17093).
+char(c,17094).
+char(m,17095).
+char(2,17096).
+char(9,17097).
+char(1,17098).
+char(6,17099).
+char(c,17100).
+char(c,17101).
+char(c,17102).
+char(c,17103).
+char(c,17104).
+char(c,17105).
+char(c,17106).
+char(m,17107).
+char(2,17108).
+char(4,17109).
+char(5,17110).
+char(9,17111).
+char(c,17112).
+char(m,17113).
+char(5,17114).
+char(6,17115).
+char(4,17116).
+char(9,17117).
+char(p,17118).
+char(o,17119).
+char(p,17120).
+char(5,17121).
+char(5,17122).
+char(7,17123).
+char(3,17124).
+char(c,17125).
+char(c,17126).
+char(p,17127).
+char(2,17128).
+char(0,17129).
+char(8,17130).
+char(c,17131).
+char(c,17132).
+char(c,17133).
+char(c,17134).
+char(m,17135).
+char(o,17136).
+char(p,17137).
+char(o,17138).
+char(3,17139).
+char(0,17140).
+char(2,17141).
+char(9,17142).
+char(c,17143).
+char(c,17144).
+char(m,17145).
+char(1,17146).
+char(4,17147).
+char(4,17148).
+char(2,17149).
+char(p,17150).
+char(5,17151).
+char(5,17152).
+char(6,17153).
+char(4,17154).
+char(c,17155).
+char(c,17156).
+char(p,17157).
+char(1,17158).
+char(8,17159).
+char(8,17160).
+char(9,17161).
+char(c,17162).
+char(p,17163).
+char(3,17164).
+char(2,17165).
+char(6,17166).
+char(c,17167).
+char(c,17168).
+char(c,17169).
+char(m,17170).
+char(o,17171).
+char(o,17172).
+char(o,17173).
+char(o,17174).
+char(m,17175).
+char(2,17176).
+char(0,17177).
+char(1,17178).
+char(7,17179).
+char(p,17180).
+char(9,17181).
+char(9,17182).
+char(8,17183).
+char(1,17184).
+char(m,17185).
+char(o,17186).
+char(m,17187).
+char(4,17188).
+char(7,17189).
+char(6,17190).
+char(6,17191).
+char(c,17192).
+char(c,17193).
+char(c,17194).
+char(c,17195).
+char(c,17196).
+char(p,17197).
+char(2,17198).
+char(7,17199).
+char(4,17200).
+char(0,17201).
+char(c,17202).
+char(p,17203).
+char(o,17204).
+char(p,17205).
+char(o,17206).
+char(p,17207).
+char(o,17208).
+char(8,17209).
+char(0,17210).
+char(9,17211).
+char(5,17212).
+char(c,17213).
+char(m,17214).
+char(6,17215).
+char(6,17216).
+char(5,17217).
+char(c,17218).
+char(m,17219).
+char(o,17220).
+char(o,17221).
+char(o,17222).
+char(m,17223).
+char(5,17224).
+char(3,17225).
+char(5,17226).
+char(2,17227).
+char(c,17228).
+char(c,17229).
+char(c,17230).
+char(c,17231).
+char(c,17232).
+char(c,17233).
+char(c,17234).
+char(c,17235).
+char(p,17236).
+char(8,17237).
+char(4,17238).
+char(0,17239).
+char(1,17240).
+char(c,17241).
+char(p,17242).
+char(3,17243).
+char(7,17244).
+char(1,17245).
+char(4,17246).
+char(c,17247).
+char(m,17248).
+char(o,17249).
+char(p,17250).
+char(o,17251).
+char(m,17252).
+char(o,17253).
+char(m,17254).
+char(o,17255).
+char(p,17256).
+char(o,17257).
+char(o,17258).
+char(p,17259).
+char(o,17260).
+char(p,17261).
+char(1,17262).
+char(4,17263).
+char(2,17264).
+char(6,17265).
+char(m,17266).
+char(o,17267).
+char(m,17268).
+char(o,17269).
+char(m,17270).
+char(4,17271).
+char(7,17272).
+char(6,17273).
+char(5,17274).
+char(p,17275).
+char(6,17276).
+char(6,17277).
+char(3,17278).
+char(2,17279).
+char(c,17280).
+char(c,17281).
+char(m,17282).
+char(o,17283).
+char(o,17284).
+char(4,17285).
+char(5,17286).
+char(7,17287).
+char(c,17288).
+char(p,17289).
+char(8,17290).
+char(6,17291).
+char(5,17292).
+char(0,17293).
+char(c,17294).
+char(c,17295).
+char(c,17296).
+char(m,17297).
+char(7,17298).
+char(0,17299).
+char(6,17300).
+char(8,17301).
+char(p,17302).
+char(3,17303).
+char(8,17304).
+char(0,17305).
+char(5,17306).
+char(c,17307).
+char(c,17308).
+char(c,17309).
+char(m,17310).
+char(9,17311).
+char(1,17312).
+char(0,17313).
+char(8,17314).
+char(m,17315).
+char(5,17316).
+char(1,17317).
+char(3,17318).
+char(0,17319).
+char(c,17320).
+char(p,17321).
+char(6,17322).
+char(6,17323).
+char(8,17324).
+char(6,17325).
+char(m,17326).
+char(o,17327).
+char(m,17328).
+char(1,17329).
+char(7,17330).
+char(9,17331).
+char(7,17332).
+char(c,17333).
+char(c,17334).
+char(c,17335).
+char(m,17336).
+char(o,17337).
+char(o,17338).
+char(p,17339).
+char(6,17340).
+char(0,17341).
+char(4,17342).
+char(p,17343).
+char(o,17344).
+char(o,17345).
+char(o,17346).
+char(o,17347).
+char(3,17348).
+char(1,17349).
+char(6,17350).
+char(c,17351).
+char(c,17352).
+char(m,17353).
+char(5,17354).
+char(8,17355).
+char(7,17356).
+char(7,17357).
+char(c,17358).
+char(c,17359).
+char(c,17360).
+char(c,17361).
+char(c,17362).
+char(m,17363).
+char(3,17364).
+char(3,17365).
+char(8,17366).
+char(3,17367).
+char(m,17368).
+char(2,17369).
+char(0,17370).
+char(0,17371).
+char(c,17372).
+char(p,17373).
+char(2,17374).
+char(1,17375).
+char(1,17376).
+char(0,17377).
+char(c,17378).
+char(p,17379).
+char(o,17380).
+char(2,17381).
+char(0,17382).
+char(9,17383).
+char(4,17384).
+char(c,17385).
+char(p,17386).
+char(4,17387).
+char(3,17388).
+char(1,17389).
+char(1,17390).
+char(c,17391).
+char(c,17392).
+char(m,17393).
+char(9,17394).
+char(0,17395).
+char(2,17396).
+char(1,17397).
+char(c,17398).
+char(m,17399).
+char(o,17400).
+char(p,17401).
+char(6,17402).
+char(8,17403).
+char(4,17404).
+char(5,17405).
+char(c,17406).
+char(p,17407).
+char(o,17408).
+char(6,17409).
+char(8,17410).
+char(6,17411).
+char(4,17412).
+char(c,17413).
+char(c,17414).
+char(c,17415).
+char(m,17416).
+char(o,17417).
+char(p,17418).
+char(o,17419).
+char(5,17420).
+char(6,17421).
+char(2,17422).
+char(1,17423).
+char(p,17424).
+char(o,17425).
+char(p,17426).
+char(o,17427).
+char(p,17428).
+char(o,17429).
+char(6,17430).
+char(0,17431).
+char(7,17432).
+char(4,17433).
+char(c,17434).
+char(p,17435).
+char(o,17436).
+char(9,17437).
+char(5,17438).
+char(2,17439).
+char(0,17440).
+char(p,17441).
+char(9,17442).
+char(8,17443).
+char(3,17444).
+char(9,17445).
+char(p,17446).
+char(o,17447).
+char(p,17448).
+char(5,17449).
+char(0,17450).
+char(9,17451).
+char(8,17452).
+char(c,17453).
+char(m,17454).
+char(o,17455).
+char(m,17456).
+char(9,17457).
+char(9,17458).
+char(6,17459).
+char(6,17460).
+char(c,17461).
+char(p,17462).
+char(7,17463).
+char(7,17464).
+char(3,17465).
+char(0,17466).
+char(m,17467).
+char(6,17468).
+char(1,17469).
+char(5,17470).
+char(9,17471).
+char(c,17472).
+char(c,17473).
+char(c,17474).
+char(m,17475).
+char(7,17476).
+char(3,17477).
+char(4,17478).
+char(0,17479).
+char(c,17480).
+char(c,17481).
+char(c,17482).
+char(m,17483).
+char(2,17484).
+char(3,17485).
+char(3,17486).
+char(m,17487).
+char(o,17488).
+char(m,17489).
+char(3,17490).
+char(4,17491).
+char(4,17492).
+char(0,17493).
+char(c,17494).
+char(p,17495).
+char(o,17496).
+char(o,17497).
+char(p,17498).
+char(5,17499).
+char(5,17500).
+char(9,17501).
+char(8,17502).
+char(c,17503).
+char(m,17504).
+char(9,17505).
+char(3,17506).
+char(6,17507).
+char(5,17508).
+char(m,17509).
+char(4,17510).
+char(1,17511).
+char(8,17512).
+char(3,17513).
+char(m,17514).
+char(o,17515).
+char(m,17516).
+char(o,17517).
+char(9,17518).
+char(6,17519).
+char(8,17520).
+char(3,17521).
+char(c,17522).
+char(c,17523).
+char(m,17524).
+char(o,17525).
+char(m,17526).
+char(8,17527).
+char(0,17528).
+char(5,17529).
+char(c,17530).
+char(c,17531).
+char(c,17532).
+char(p,17533).
+char(1,17534).
+char(5,17535).
+char(0,17536).
+char(4,17537).
+char(c,17538).
+char(c,17539).
+char(c,17540).
+char(c,17541).
+char(c,17542).
+char(m,17543).
+char(o,17544).
+char(p,17545).
+char(4,17546).
+char(1,17547).
+char(1,17548).
+char(p,17549).
+char(o,17550).
+char(p,17551).
+char(5,17552).
+char(4,17553).
+char(1,17554).
+char(9,17555).
+char(c,17556).
+char(m,17557).
+char(o,17558).
+char(m,17559).
+char(o,17560).
+char(o,17561).
+char(m,17562).
+char(6,17563).
+char(7,17564).
+char(9,17565).
+char(4,17566).
+char(m,17567).
+char(o,17568).
+char(m,17569).
+char(7,17570).
+char(2,17571).
+char(7,17572).
+char(c,17573).
+char(m,17574).
+char(o,17575).
+char(p,17576).
+char(o,17577).
+char(m,17578).
+char(9,17579).
+char(3,17580).
+char(0,17581).
+char(2,17582).
+char(c,17583).
+char(p,17584).
+char(2,17585).
+char(2,17586).
+char(0,17587).
+char(6,17588).
+char(c,17589).
+char(c,17590).
+char(c,17591).
+char(p,17592).
+char(6,17593).
+char(8,17594).
+char(0,17595).
+char(6,17596).
+char(p,17597).
+char(5,17598).
+char(0,17599).
+char(7,17600).
+char(8,17601).
+char(p,17602).
+char(o,17603).
+char(9,17604).
+char(9,17605).
+char(1,17606).
+char(8,17607).
+char(p,17608).
+char(o,17609).
+char(m,17610).
+char(8,17611).
+char(4,17612).
+char(7,17613).
+char(8,17614).
+char(c,17615).
+char(c,17616).
+char(m,17617).
+char(5,17618).
+char(6,17619).
+char(8,17620).
+char(6,17621).
+char(m,17622).
+char(1,17623).
+char(7,17624).
+char(0,17625).
+char(8,17626).
+char(m,17627).
+char(o,17628).
+char(m,17629).
+char(o,17630).
+char(m,17631).
+char(8,17632).
+char(6,17633).
+char(7,17634).
+char(1,17635).
+char(p,17636).
+char(o,17637).
+char(m,17638).
+char(o,17639).
+char(p,17640).
+char(7,17641).
+char(6,17642).
+char(3,17643).
+char(4,17644).
+char(p,17645).
+char(9,17646).
+char(9,17647).
+char(1,17648).
+char(1,17649).
+char(c,17650).
+char(c,17651).
+char(m,17652).
+char(o,17653).
+char(p,17654).
+char(3,17655).
+char(8,17656).
+char(1,17657).
+char(9,17658).
+char(p,17659).
+char(5,17660).
+char(1,17661).
+char(7,17662).
+char(2,17663).
+char(p,17664).
+char(o,17665).
+char(5,17666).
+char(6,17667).
+char(3,17668).
+char(8,17669).
+char(m,17670).
+char(1,17671).
+char(8,17672).
+char(7,17673).
+char(5,17674).
+char(p,17675).
+char(8,17676).
+char(6,17677).
+char(4,17678).
+char(c,17679).
+char(p,17680).
+char(o,17681).
+char(m,17682).
+char(1,17683).
+char(5,17684).
+char(7,17685).
+char(9,17686).
+char(c,17687).
+char(m,17688).
+char(1,17689).
+char(4,17690).
+char(0,17691).
+char(9,17692).
+char(m,17693).
+char(o,17694).
+char(m,17695).
+char(9,17696).
+char(6,17697).
+char(9,17698).
+char(p,17699).
+char(7,17700).
+char(1,17701).
+char(0,17702).
+char(5,17703).
+char(m,17704).
+char(4,17705).
+char(0,17706).
+char(9,17707).
+char(3,17708).
+char(p,17709).
+char(3,17710).
+char(4,17711).
+char(1,17712).
+char(0,17713).
+char(c,17714).
+char(m,17715).
+char(o,17716).
+char(m,17717).
+char(3,17718).
+char(0,17719).
+char(2,17720).
+char(6,17721).
+char(p,17722).
+char(5,17723).
+char(8,17724).
+char(9,17725).
+char(3,17726).
+char(p,17727).
+char(o,17728).
+char(m,17729).
+char(7,17730).
+char(2,17731).
+char(9,17732).
+char(5,17733).
+char(c,17734).
+char(p,17735).
+char(o,17736).
+char(m,17737).
+char(7,17738).
+char(5,17739).
+char(0,17740).
+char(0,17741).
+char(c,17742).
+char(m,17743).
+char(3,17744).
+char(6,17745).
+char(0,17746).
+char(5,17747).
+char(p,17748).
+char(o,17749).
+char(1,17750).
+char(1,17751).
+char(0,17752).
+char(c,17753).
+char(m,17754).
+char(o,17755).
+char(p,17756).
+char(7,17757).
+char(2,17758).
+char(9,17759).
+char(0,17760).
+char(c,17761).
+char(c,17762).
+char(m,17763).
+char(7,17764).
+char(5,17765).
+char(9,17766).
+char(7,17767).
+char(m,17768).
+char(5,17769).
+char(6,17770).
+char(8,17771).
+char(2,17772).
+char(m,17773).
+char(8,17774).
+char(9,17775).
+char(8,17776).
+char(1,17777).
+char(p,17778).
+char(8,17779).
+char(6,17780).
+char(8,17781).
+char(8,17782).
+char(m,17783).
+char(o,17784).
+char(2,17785).
+char(5,17786).
+char(7,17787).
+char(3,17788).
+char(p,17789).
+char(o,17790).
+char(p,17791).
+char(o,17792).
+char(m,17793).
+char(6,17794).
+char(0,17795).
+char(9,17796).
+char(0,17797).
+char(p,17798).
+char(7,17799).
+char(1,17800).
+char(4,17801).
+char(6,17802).
+char(p,17803).
+char(o,17804).
+char(m,17805).
+char(5,17806).
+char(0,17807).
+char(8,17808).
+char(8,17809).
+char(c,17810).
+char(p,17811).
+char(o,17812).
+char(p,17813).
+char(5,17814).
+char(6,17815).
+char(5,17816).
+char(7,17817).
+char(m,17818).
+char(o,17819).
+char(m,17820).
+char(o,17821).
+char(m,17822).
+char(7,17823).
+char(2,17824).
+char(7,17825).
+char(4,17826).
+char(m,17827).
+char(2,17828).
+char(2,17829).
+char(3,17830).
+char(3,17831).
+char(p,17832).
+char(o,17833).
+char(p,17834).
+char(o,17835).
+char(7,17836).
+char(2,17837).
+char(3,17838).
+char(1,17839).
+char(m,17840).
+char(o,17841).
+char(2,17842).
+char(2,17843).
+char(2,17844).
+char(5,17845).
+char(m,17846).
+char(o,17847).
+char(o,17848).
+char(p,17849).
+char(3,17850).
+char(9,17851).
+char(6,17852).
+char(8,17853).
+char(c,17854).
+char(c,17855).
+char(c,17856).
+char(p,17857).
+char(8,17858).
+char(5,17859).
+char(0,17860).
+char(6,17861).
+char(m,17862).
+char(1,17863).
+char(3,17864).
+char(3,17865).
+char(9,17866).
+char(c,17867).
+char(c,17868).
+char(c,17869).
+char(m,17870).
+char(o,17871).
+char(m,17872).
+char(o,17873).
+char(p,17874).
+char(o,17875).
+char(m,17876).
+char(1,17877).
+char(3,17878).
+char(1,17879).
+char(9,17880).
+char(c,17881).
+char(c,17882).
+char(p,17883).
+char(6,17884).
+char(1,17885).
+char(0,17886).
+char(c,17887).
+char(p,17888).
+char(1,17889).
+char(8,17890).
+char(0,17891).
+char(0,17892).
+char(c,17893).
+char(c,17894).
+char(m,17895).
+char(o,17896).
+char(m,17897).
+char(o,17898).
+char(o,17899).
+char(p,17900).
+char(8,17901).
+char(9,17902).
+char(4,17903).
+char(7,17904).
+char(m,17905).
+char(o,17906).
+char(o,17907).
+char(o,17908).
+char(4,17909).
+char(0,17910).
+char(6,17911).
+char(8,17912).
+char(c,17913).
+char(c,17914).
+char(p,17915).
+char(3,17916).
+char(8,17917).
+char(1,17918).
+char(m,17919).
+char(1,17920).
+char(8,17921).
+char(7,17922).
+char(c,17923).
+char(m,17924).
+char(9,17925).
+char(6,17926).
+char(5,17927).
+char(2,17928).
+char(c,17929).
+char(m,17930).
+char(4,17931).
+char(2,17932).
+char(7,17933).
+char(7,17934).
+char(c,17935).
+char(m,17936).
+char(o,17937).
+char(p,17938).
+char(o,17939).
+char(p,17940).
+char(o,17941).
+char(p,17942).
+char(o,17943).
+char(o,17944).
+char(o,17945).
+char(p,17946).
+char(o,17947).
+char(4,17948).
+char(5,17949).
+char(0,17950).
+char(8,17951).
+char(m,17952).
+char(7,17953).
+char(4,17954).
+char(1,17955).
+char(3,17956).
+char(c,17957).
+char(p,17958).
+char(o,17959).
+char(4,17960).
+char(6,17961).
+char(7,17962).
+char(c,17963).
+char(m,17964).
+char(o,17965).
+char(4,17966).
+char(8,17967).
+char(8,17968).
+char(3,17969).
+char(c,17970).
+char(p,17971).
+char(o,17972).
+char(o,17973).
+char(o,17974).
+char(p,17975).
+char(o,17976).
+char(p,17977).
+char(o,17978).
+char(p,17979).
+char(5,17980).
+char(9,17981).
+char(p,17982).
+char(1,17983).
+char(7,17984).
+char(9,17985).
+char(5,17986).
+char(c,17987).
+char(c,17988).
+char(c,17989).
+char(p,17990).
+char(5,17991).
+char(8,17992).
+char(3,17993).
+char(4,17994).
+char(c,17995).
+char(m,17996).
+char(2,17997).
+char(4,17998).
+char(3,17999).
+char(9,18000).
+char(c,18001).
+char(c,18002).
+char(m,18003).
+char(o,18004).
+char(m,18005).
+char(o,18006).
+char(o,18007).
+char(m,18008).
+char(o,18009).
+char(p,18010).
+char(6,18011).
+char(7,18012).
+char(9,18013).
+char(2,18014).
+char(m,18015).
+char(4,18016).
+char(7,18017).
+char(9,18018).
+char(7,18019).
+char(c,18020).
+char(m,18021).
+char(1,18022).
+char(7,18023).
+char(0,18024).
+char(5,18025).
+char(m,18026).
+char(5,18027).
+char(7,18028).
+char(8,18029).
+char(1,18030).
+char(p,18031).
+char(o,18032).
+char(m,18033).
+char(o,18034).
+char(o,18035).
+char(m,18036).
+char(o,18037).
+char(m,18038).
+char(8,18039).
+char(7,18040).
+char(6,18041).
+char(1,18042).
+char(m,18043).
+char(3,18044).
+char(6,18045).
+char(5,18046).
+char(9,18047).
+char(m,18048).
+char(o,18049).
+char(6,18050).
+char(6,18051).
+char(2,18052).
+char(c,18053).
+char(c,18054).
+char(m,18055).
+char(4,18056).
+char(1,18057).
+char(6,18058).
+char(1,18059).
+char(c,18060).
+char(p,18061).
+char(o,18062).
+char(m,18063).
+char(8,18064).
+char(1,18065).
+char(9,18066).
+char(1,18067).
+char(c,18068).
+char(c,18069).
+char(p,18070).
+char(4,18071).
+char(0,18072).
+char(3,18073).
+char(9,18074).
+char(c,18075).
+char(c,18076).
+char(c,18077).
+char(p,18078).
+char(5,18079).
+char(5,18080).
+char(1,18081).
+char(6,18082).
+char(m,18083).
+char(o,18084).
+char(o,18085).
+char(1,18086).
+char(9,18087).
+char(1,18088).
+char(8,18089).
+char(m,18090).
+char(o,18091).
+char(m,18092).
+char(2,18093).
+char(1,18094).
+char(9,18095).
+char(0,18096).
+char(c,18097).
+char(m,18098).
+char(o,18099).
+char(o,18100).
+char(m,18101).
+char(o,18102).
+char(m,18103).
+char(o,18104).
+char(2,18105).
+char(4,18106).
+char(2,18107).
+char(4,18108).
+char(p,18109).
+char(o,18110).
+char(p,18111).
+char(o,18112).
+char(1,18113).
+char(2,18114).
+char(6,18115).
+char(6,18116).
+char(c,18117).
+char(c,18118).
+char(c,18119).
+char(c,18120).
+char(p,18121).
+char(9,18122).
+char(3,18123).
+char(6,18124).
+char(3,18125).
+char(c,18126).
+char(p,18127).
+char(o,18128).
+char(o,18129).
+char(m,18130).
+char(o,18131).
+char(m,18132).
+char(3,18133).
+char(5,18134).
+char(7,18135).
+char(8,18136).
+char(c,18137).
+char(c,18138).
+char(p,18139).
+char(o,18140).
+char(p,18141).
+char(5,18142).
+char(0,18143).
+char(2,18144).
+char(6,18145).
+char(c,18146).
+char(p,18147).
+char(o,18148).
+char(o,18149).
+char(p,18150).
+char(o,18151).
+char(p,18152).
+char(o,18153).
+char(p,18154).
+char(6,18155).
+char(7,18156).
+char(2,18157).
+char(2,18158).
+char(c,18159).
+char(p,18160).
+char(8,18161).
+char(8,18162).
+char(7,18163).
+char(8,18164).
+char(c,18165).
+char(c,18166).
+char(p,18167).
+char(o,18168).
+char(m,18169).
+char(6,18170).
+char(3,18171).
+char(5,18172).
+char(p,18173).
+char(1,18174).
+char(6,18175).
+char(4,18176).
+char(m,18177).
+char(7,18178).
+char(0,18179).
+char(3,18180).
+char(9,18181).
+char(c,18182).
+char(p,18183).
+char(o,18184).
+char(m,18185).
+char(5,18186).
+char(4,18187).
+char(2,18188).
+char(6,18189).
+char(m,18190).
+char(6,18191).
+char(0,18192).
+char(4,18193).
+char(5,18194).
+char(m,18195).
+char(9,18196).
+char(9,18197).
+char(7,18198).
+char(4,18199).
+char(m,18200).
+char(2,18201).
+char(4,18202).
+char(3,18203).
+char(7,18204).
+char(m,18205).
+char(6,18206).
+char(0,18207).
+char(4,18208).
+char(7,18209).
+char(c,18210).
+char(c,18211).
+char(c,18212).
+char(c,18213).
+char(p,18214).
+char(8,18215).
+char(4,18216).
+char(9,18217).
+char(8,18218).
+char(c,18219).
+char(p,18220).
+char(o,18221).
+char(p,18222).
+char(o,18223).
+char(p,18224).
+char(o,18225).
+char(p,18226).
+char(o,18227).
+char(m,18228).
+char(9,18229).
+char(1,18230).
+char(2,18231).
+char(m,18232).
+char(o,18233).
+char(m,18234).
+char(4,18235).
+char(6,18236).
+char(0,18237).
+char(8,18238).
+char(m,18239).
+char(8,18240).
+char(1,18241).
+char(5,18242).
+char(6,18243).
+char(c,18244).
+char(m,18245).
+char(o,18246).
+char(2,18247).
+char(2,18248).
+char(7,18249).
+char(5,18250).
+char(c,18251).
+char(p,18252).
+char(3,18253).
+char(2,18254).
+char(2,18255).
+char(9,18256).
+char(c,18257).
+char(m,18258).
+char(7,18259).
+char(1,18260).
+char(8,18261).
+char(3,18262).
+char(p,18263).
+char(o,18264).
+char(p,18265).
+char(o,18266).
+char(m,18267).
+char(6,18268).
+char(8,18269).
+char(2,18270).
+char(7,18271).
+char(c,18272).
+char(c,18273).
+char(c,18274).
+char(c,18275).
+char(m,18276).
+char(8,18277).
+char(6,18278).
+char(9,18279).
+char(9,18280).
+char(p,18281).
+char(o,18282).
+char(p,18283).
+char(o,18284).
+char(p,18285).
+char(4,18286).
+char(7,18287).
+char(1,18288).
+char(6,18289).
+char(m,18290).
+char(o,18291).
+char(m,18292).
+char(9,18293).
+char(5,18294).
+char(5,18295).
+char(7,18296).
+char(m,18297).
+char(o,18298).
+char(o,18299).
+char(m,18300).
+char(o,18301).
+char(o,18302).
+char(m,18303).
+char(o,18304).
+char(m,18305).
+char(5,18306).
+char(3,18307).
+char(1,18308).
+char(3,18309).
+char(c,18310).
+char(p,18311).
+char(6,18312).
+char(4,18313).
+char(4,18314).
+char(2,18315).
+char(c,18316).
+char(m,18317).
+char(4,18318).
+char(7,18319).
+char(5,18320).
+char(1,18321).
+char(m,18322).
+char(o,18323).
+char(o,18324).
+char(m,18325).
+char(4,18326).
+char(6,18327).
+char(6,18328).
+char(p,18329).
+char(8,18330).
+char(0,18331).
+char(7,18332).
+char(3,18333).
+char(c,18334).
+char(c,18335).
+char(c,18336).
+char(p,18337).
+char(o,18338).
+char(p,18339).
+char(o,18340).
+char(2,18341).
+char(8,18342).
+char(6,18343).
+char(0,18344).
+char(c,18345).
+char(m,18346).
+char(2,18347).
+char(3,18348).
+char(8,18349).
+char(2,18350).
+char(p,18351).
+char(3,18352).
+char(3,18353).
+char(6,18354).
+char(6,18355).
+char(c,18356).
+char(m,18357).
+char(o,18358).
+char(o,18359).
+char(m,18360).
+char(o,18361).
+char(m,18362).
+char(o,18363).
+char(p,18364).
+char(o,18365).
+char(4,18366).
+char(6,18367).
+char(9,18368).
+char(7,18369).
+char(p,18370).
+char(8,18371).
+char(5,18372).
+char(4,18373).
+char(4,18374).
+char(c,18375).
+char(c,18376).
+char(m,18377).
+char(2,18378).
+char(8,18379).
+char(1,18380).
+char(9,18381).
+char(c,18382).
+char(c,18383).
+char(m,18384).
+char(o,18385).
+char(p,18386).
+char(1,18387).
+char(7,18388).
+char(2,18389).
+char(2,18390).
+char(c,18391).
+char(m,18392).
+char(o,18393).
+char(4,18394).
+char(0,18395).
+char(6,18396).
+char(5,18397).
+char(c,18398).
+char(c,18399).
+char(m,18400).
+char(o,18401).
+char(o,18402).
+char(9,18403).
+char(2,18404).
+char(1,18405).
+char(0,18406).
+char(m,18407).
+char(4,18408).
+char(5,18409).
+char(4,18410).
+char(9,18411).
+char(p,18412).
+char(o,18413).
+char(m,18414).
+char(3,18415).
+char(3,18416).
+char(3,18417).
+char(4,18418).
+char(p,18419).
+char(2,18420).
+char(4,18421).
+char(3,18422).
+char(8,18423).
+char(c,18424).
+char(p,18425).
+char(9,18426).
+char(4,18427).
+char(1,18428).
+char(2,18429).
+char(p,18430).
+char(o,18431).
+char(p,18432).
+char(o,18433).
+char(p,18434).
+char(2,18435).
+char(3,18436).
+char(3,18437).
+char(5,18438).
+char(m,18439).
+char(o,18440).
+char(3,18441).
+char(8,18442).
+char(5,18443).
+char(0,18444).
+char(c,18445).
+char(m,18446).
+char(6,18447).
+char(8,18448).
+char(5,18449).
+char(4,18450).
+char(m,18451).
+char(3,18452).
+char(8,18453).
+char(9,18454).
+char(5,18455).
+char(m,18456).
+char(5,18457).
+char(2,18458).
+char(5,18459).
+char(2,18460).
+char(m,18461).
+char(o,18462).
+char(o,18463).
+char(m,18464).
+char(4,18465).
+char(1,18466).
+char(4,18467).
+char(6,18468).
+char(c,18469).
+char(m,18470).
+char(5,18471).
+char(3,18472).
+char(6,18473).
+char(3,18474).
+char(c,18475).
+char(m,18476).
+char(o,18477).
+char(m,18478).
+char(o,18479).
+char(m,18480).
+char(8,18481).
+char(2,18482).
+char(5,18483).
+char(9,18484).
+char(m,18485).
+char(o,18486).
+char(o,18487).
+char(m,18488).
+char(4,18489).
+char(4,18490).
+char(2,18491).
+char(9,18492).
+char(c,18493).
+char(c,18494).
+char(p,18495).
+char(o,18496).
+char(p,18497).
+char(3,18498).
+char(6,18499).
+char(7,18500).
+char(3,18501).
+char(m,18502).
+char(4,18503).
+char(6,18504).
+char(m,18505).
+char(o,18506).
+char(m,18507).
+char(o,18508).
+char(p,18509).
+char(o,18510).
+char(p,18511).
+char(8,18512).
+char(8,18513).
+char(1,18514).
+char(0,18515).
+char(p,18516).
+char(6,18517).
+char(1,18518).
+char(6,18519).
+char(0,18520).
+char(c,18521).
+char(m,18522).
+char(o,18523).
+char(m,18524).
+char(8,18525).
+char(3,18526).
+char(5,18527).
+char(3,18528).
+char(m,18529).
+char(o,18530).
+char(o,18531).
+char(9,18532).
+char(1,18533).
+char(6,18534).
+char(m,18535).
+char(9,18536).
+char(9,18537).
+char(9,18538).
+char(4,18539).
+char(m,18540).
+char(o,18541).
+char(p,18542).
+char(o,18543).
+char(p,18544).
+char(6,18545).
+char(3,18546).
+char(1,18547).
+char(6,18548).
+char(p,18549).
+char(8,18550).
+char(6,18551).
+char(0,18552).
+char(1,18553).
+char(c,18554).
+char(c,18555).
+char(c,18556).
+char(c,18557).
+char(p,18558).
+char(o,18559).
+char(m,18560).
+char(9,18561).
+char(2,18562).
+char(8,18563).
+char(0,18564).
+char(p,18565).
+char(2,18566).
+char(2,18567).
+char(6,18568).
+char(4,18569).
+char(c,18570).
+char(p,18571).
+char(o,18572).
+char(p,18573).
+char(7,18574).
+char(7,18575).
+char(2,18576).
+char(1,18577).
+char(c,18578).
+char(m,18579).
+char(2,18580).
+char(3,18581).
+char(3,18582).
+char(5,18583).
+char(p,18584).
+char(o,18585).
+char(m,18586).
+char(6,18587).
+char(1,18588).
+char(7,18589).
+char(3,18590).
+char(c,18591).
+char(c,18592).
+char(m,18593).
+char(o,18594).
+char(m,18595).
+char(o,18596).
+char(m,18597).
+char(3,18598).
+char(3,18599).
+char(7,18600).
+char(8,18601).
+char(m,18602).
+char(o,18603).
+char(7,18604).
+char(8,18605).
+char(7,18606).
+char(7,18607).
+char(m,18608).
+char(4,18609).
+char(5,18610).
+char(3,18611).
+char(p,18612).
+char(8,18613).
+char(3,18614).
+char(4,18615).
+char(9,18616).
+char(c,18617).
+char(c,18618).
+char(p,18619).
+char(o,18620).
+char(o,18621).
+char(p,18622).
+char(o,18623).
+char(m,18624).
+char(7,18625).
+char(6,18626).
+char(4,18627).
+char(3,18628).
+char(c,18629).
+char(m,18630).
+char(o,18631).
+char(p,18632).
+char(2,18633).
+char(1,18634).
+char(7,18635).
+char(0,18636).
+char(m,18637).
+char(o,18638).
+char(p,18639).
+char(3,18640).
+char(5,18641).
+char(8,18642).
+char(8,18643).
+char(m,18644).
+char(o,18645).
+char(p,18646).
+char(1,18647).
+char(3,18648).
+char(5,18649).
+char(m,18650).
+char(o,18651).
+char(p,18652).
+char(o,18653).
+char(m,18654).
+char(o,18655).
+char(m,18656).
+char(7,18657).
+char(7,18658).
+char(5,18659).
+char(5,18660).
+char(c,18661).
+char(m,18662).
+char(o,18663).
+char(m,18664).
+char(o,18665).
+char(o,18666).
+char(o,18667).
+char(m,18668).
+char(1,18669).
+char(1,18670).
+char(9,18671).
+char(3,18672).
+char(c,18673).
+char(c,18674).
+char(c,18675).
+char(c,18676).
+char(c,18677).
+char(c,18678).
+char(p,18679).
+char(8,18680).
+char(8,18681).
+char(7,18682).
+char(1,18683).
+char(m,18684).
+char(o,18685).
+char(m,18686).
+char(o,18687).
+char(m,18688).
+char(o,18689).
+char(p,18690).
+char(5,18691).
+char(9,18692).
+char(9,18693).
+char(p,18694).
+char(7,18695).
+char(1,18696).
+char(6,18697).
+char(1,18698).
+char(p,18699).
+char(o,18700).
+char(m,18701).
+char(o,18702).
+char(8,18703).
+char(3,18704).
+char(2,18705).
+char(0,18706).
+char(p,18707).
+char(8,18708).
+char(6,18709).
+char(6,18710).
+char(7,18711).
+char(c,18712).
+char(m,18713).
+char(o,18714).
+char(2,18715).
+char(2,18716).
+char(6,18717).
+char(8,18718).
+char(c,18719).
+char(c,18720).
+char(p,18721).
+char(o,18722).
+char(m,18723).
+char(o,18724).
+char(o,18725).
+char(m,18726).
+char(1,18727).
+char(3,18728).
+char(9,18729).
+char(3,18730).
+char(c,18731).
+char(c,18732).
+char(c,18733).
+char(c,18734).
+char(c,18735).
+char(c,18736).
+char(p,18737).
+char(7,18738).
+char(0,18739).
+char(1,18740).
+char(9,18741).
+char(c,18742).
+char(p,18743).
+char(1,18744).
+char(6,18745).
+char(3,18746).
+char(1,18747).
+char(c,18748).
+char(c,18749).
+char(c,18750).
+char(m,18751).
+char(o,18752).
+char(o,18753).
+char(o,18754).
+char(m,18755).
+char(o,18756).
+char(m,18757).
+char(o,18758).
+char(m,18759).
+char(o,18760).
+char(p,18761).
+char(o,18762).
+char(p,18763).
+char(3,18764).
+char(2,18765).
+char(4,18766).
+char(7,18767).
+char(c,18768).
+char(c,18769).
+char(c,18770).
+char(m,18771).
+char(o,18772).
+char(p,18773).
+char(9,18774).
+char(0,18775).
+char(7,18776).
+char(8,18777).
+char(c,18778).
+char(c,18779).
+char(c,18780).
+char(c,18781).
+char(m,18782).
+char(o,18783).
+char(p,18784).
+char(7,18785).
+char(6,18786).
+char(7,18787).
+char(6,18788).
+char(m,18789).
+char(4,18790).
+char(8,18791).
+char(5,18792).
+char(9,18793).
+char(c,18794).
+char(c,18795).
+char(m,18796).
+char(o,18797).
+char(m,18798).
+char(o,18799).
+char(m,18800).
+char(o,18801).
+char(m,18802).
+char(o,18803).
+char(p,18804).
+char(o,18805).
+char(p,18806).
+char(o,18807).
+char(m,18808).
+char(o,18809).
+char(m,18810).
+char(o,18811).
+char(m,18812).
+char(9,18813).
+char(1,18814).
+char(7,18815).
+char(p,18816).
+char(5,18817).
+char(8,18818).
+char(8,18819).
+char(6,18820).
+char(c,18821).
+char(c,18822).
+char(c,18823).
+char(c,18824).
+char(c,18825).
+char(c,18826).
+char(c,18827).
+char(m,18828).
+char(3,18829).
+char(0,18830).
+char(6,18831).
+char(6,18832).
+char(p,18833).
+char(5,18834).
+char(5,18835).
+char(6,18836).
+char(m,18837).
+char(9,18838).
+char(9,18839).
+char(5,18840).
+char(5,18841).
+char(p,18842).
+char(4,18843).
+char(5,18844).
+char(4,18845).
+char(8,18846).
+char(m,18847).
+char(2,18848).
+char(5,18849).
+char(1,18850).
+char(5,18851).
+char(c,18852).
+char(p,18853).
+char(2,18854).
+char(8,18855).
+char(8,18856).
+char(p,18857).
+char(4,18858).
+char(7,18859).
+char(4,18860).
+char(6,18861).
+char(c,18862).
+char(p,18863).
+char(o,18864).
+char(m,18865).
+char(5,18866).
+char(4,18867).
+char(3,18868).
+char(c,18869).
+char(c,18870).
+char(p,18871).
+char(o,18872).
+char(m,18873).
+char(o,18874).
+char(p,18875).
+char(o,18876).
+char(m,18877).
+char(o,18878).
+char(p,18879).
+char(o,18880).
+char(o,18881).
+char(m,18882).
+char(4,18883).
+char(7,18884).
+char(6,18885).
+char(3,18886).
+char(c,18887).
+char(p,18888).
+char(4,18889).
+char(5,18890).
+char(7,18891).
+char(m,18892).
+char(3,18893).
+char(7,18894).
+char(4,18895).
+char(0,18896).
+char(p,18897).
+char(2,18898).
+char(6,18899).
+char(9,18900).
+char(9,18901).
+char(m,18902).
+char(o,18903).
+char(m,18904).
+char(o,18905).
+char(m,18906).
+char(o,18907).
+char(o,18908).
+char(o,18909).
+char(p,18910).
+char(1,18911).
+char(9,18912).
+char(3,18913).
+char(m,18914).
+char(5,18915).
+char(5,18916).
+char(3,18917).
+char(9,18918).
+char(c,18919).
+char(c,18920).
+char(m,18921).
+char(8,18922).
+char(1,18923).
+char(7,18924).
+char(5,18925).
+char(m,18926).
+char(1,18927).
+char(5,18928).
+char(7,18929).
+char(0,18930).
+char(c,18931).
+char(m,18932).
+char(o,18933).
+char(p,18934).
+char(1,18935).
+char(9,18936).
+char(4,18937).
+char(0,18938).
+char(m,18939).
+char(o,18940).
+char(2,18941).
+char(4,18942).
+char(2,18943).
+char(8,18944).
+char(c,18945).
+char(m,18946).
+char(o,18947).
+char(5,18948).
+char(4,18949).
+char(1,18950).
+char(9,18951).
+char(p,18952).
+char(3,18953).
+char(7,18954).
+char(6,18955).
+char(9,18956).
+char(p,18957).
+char(9,18958).
+char(0,18959).
+char(2,18960).
+char(3,18961).
+char(p,18962).
+char(o,18963).
+char(p,18964).
+char(o,18965).
+char(7,18966).
+char(9,18967).
+char(9,18968).
+char(7,18969).
+char(c,18970).
+char(p,18971).
+char(6,18972).
+char(5,18973).
+char(7,18974).
+char(4,18975).
+char(c,18976).
+char(c,18977).
+char(c,18978).
+char(p,18979).
+char(o,18980).
+char(m,18981).
+char(o,18982).
+char(m,18983).
+char(8,18984).
+char(9,18985).
+char(0,18986).
+char(p,18987).
+char(o,18988).
+char(p,18989).
+char(4,18990).
+char(8,18991).
+char(0,18992).
+char(9,18993).
+char(p,18994).
+char(o,18995).
+char(p,18996).
+char(4,18997).
+char(8,18998).
+char(3,18999).
+char(3,19000).
+char(c,19001).
+char(c,19002).
+char(c,19003).
+char(c,19004).
+char(p,19005).
+char(o,19006).
+char(m,19007).
+char(5,19008).
+char(1,19009).
+char(5,19010).
+char(9,19011).
+char(c,19012).
+char(c,19013).
+char(c,19014).
+char(p,19015).
+char(o,19016).
+char(p,19017).
+char(o,19018).
+char(m,19019).
+char(5,19020).
+char(7,19021).
+char(9,19022).
+char(2,19023).
+char(m,19024).
+char(o,19025).
+char(m,19026).
+char(5,19027).
+char(2,19028).
+char(m,19029).
+char(4,19030).
+char(8,19031).
+char(4,19032).
+char(7,19033).
+char(m,19034).
+char(o,19035).
+char(o,19036).
+char(o,19037).
+char(6,19038).
+char(6,19039).
+char(8,19040).
+char(9,19041).
+char(m,19042).
+char(4,19043).
+char(6,19044).
+char(1,19045).
+char(4,19046).
+char(c,19047).
+char(c,19048).
+char(c,19049).
+char(c,19050).
+char(c,19051).
+char(p,19052).
+char(o,19053).
+char(p,19054).
+char(o,19055).
+char(m,19056).
+char(o,19057).
+char(1,19058).
+char(9,19059).
+char(3,19060).
+char(2,19061).
+char(m,19062).
+char(9,19063).
+char(4,19064).
+char(8,19065).
+char(5,19066).
+char(c,19067).
+char(c,19068).
+char(p,19069).
+char(o,19070).
+char(m,19071).
+char(8,19072).
+char(5,19073).
+char(2,19074).
+char(6,19075).
+char(c,19076).
+char(c,19077).
+char(m,19078).
+char(o,19079).
+char(2,19080).
+char(9,19081).
+char(1,19082).
+char(5,19083).
+char(p,19084).
+char(8,19085).
+char(9,19086).
+char(1,19087).
+char(1,19088).
+char(c,19089).
+char(c,19090).
+char(c,19091).
+char(c,19092).
+char(c,19093).
+char(c,19094).
+char(c,19095).
+char(m,19096).
+char(2,19097).
+char(1,19098).
+char(2,19099).
+char(3,19100).
+char(p,19101).
+char(8,19102).
+char(0,19103).
+char(6,19104).
+char(1,19105).
+char(m,19106).
+char(1,19107).
+char(2,19108).
+char(1,19109).
+char(5,19110).
+char(c,19111).
+char(p,19112).
+char(o,19113).
+char(o,19114).
+char(m,19115).
+char(4,19116).
+char(4,19117).
+char(9,19118).
+char(1,19119).
+char(p,19120).
+char(3,19121).
+char(4,19122).
+char(0,19123).
+char(8,19124).
+char(c,19125).
+char(c,19126).
+char(p,19127).
+char(6,19128).
+char(4,19129).
+char(6,19130).
+char(6,19131).
+char(c,19132).
+char(m,19133).
+char(o,19134).
+char(p,19135).
+char(o,19136).
+char(p,19137).
+char(o,19138).
+char(p,19139).
+char(o,19140).
+char(p,19141).
+char(o,19142).
+char(m,19143).
+char(o,19144).
+char(p,19145).
+char(o,19146).
+char(m,19147).
+char(1,19148).
+char(4,19149).
+char(1,19150).
+char(2,19151).
+char(c,19152).
+char(c,19153).
+char(c,19154).
+char(c,19155).
+char(c,19156).
+char(m,19157).
+char(2,19158).
+char(4,19159).
+char(2,19160).
+char(6,19161).
+char(c,19162).
+char(p,19163).
+char(5,19164).
+char(0,19165).
+char(1,19166).
+char(3,19167).
+char(c,19168).
+char(c,19169).
+char(m,19170).
+char(2,19171).
+char(1,19172).
+char(9,19173).
+char(1,19174).
+char(p,19175).
+char(o,19176).
+char(p,19177).
+char(o,19178).
+char(o,19179).
+char(p,19180).
+char(o,19181).
+char(m,19182).
+char(o,19183).
+char(m,19184).
+char(5,19185).
+char(4,19186).
+char(4,19187).
+char(3,19188).
+char(m,19189).
+char(o,19190).
+char(m,19191).
+char(2,19192).
+char(2,19193).
+char(6,19194).
+char(2,19195).
+char(c,19196).
+char(c,19197).
+char(p,19198).
+char(5,19199).
+char(2,19200).
+char(9,19201).
+char(0,19202).
+char(p,19203).
+char(o,19204).
+char(2,19205).
+char(4,19206).
+char(1,19207).
+char(7,19208).
+char(c,19209).
+char(p,19210).
+char(6,19211).
+char(6,19212).
+char(1,19213).
+char(2,19214).
+char(p,19215).
+char(5,19216).
+char(0,19217).
+char(8,19218).
+char(2,19219).
+char(c,19220).
+char(m,19221).
+char(o,19222).
+char(m,19223).
+char(o,19224).
+char(4,19225).
+char(0,19226).
+char(4,19227).
+char(5,19228).
+char(p,19229).
+char(5,19230).
+char(4,19231).
+char(1,19232).
+char(1,19233).
+char(c,19234).
+char(m,19235).
+char(5,19236).
+char(0,19237).
+char(9,19238).
+char(4,19239).
+char(p,19240).
+char(o,19241).
+char(p,19242).
+char(o,19243).
+char(8,19244).
+char(8,19245).
+char(1,19246).
+char(4,19247).
+char(c,19248).
+char(p,19249).
+char(9,19250).
+char(4,19251).
+char(9,19252).
+char(c,19253).
+char(c,19254).
+char(m,19255).
+char(o,19256).
+char(m,19257).
+char(2,19258).
+char(0,19259).
+char(7,19260).
+char(m,19261).
+char(o,19262).
+char(m,19263).
+char(o,19264).
+char(p,19265).
+char(3,19266).
+char(6,19267).
+char(0,19268).
+char(6,19269).
+char(p,19270).
+char(9,19271).
+char(0,19272).
+char(8,19273).
+char(4,19274).
+char(p,19275).
+char(o,19276).
+char(p,19277).
+char(1,19278).
+char(0,19279).
+char(1,19280).
+char(5,19281).
+char(m,19282).
+char(6,19283).
+char(6,19284).
+char(8,19285).
+char(6,19286).
+char(p,19287).
+char(o,19288).
+char(m,19289).
+char(o,19290).
+char(o,19291).
+char(m,19292).
+char(o,19293).
+char(p,19294).
+char(o,19295).
+char(p,19296).
+char(o,19297).
+char(o,19298).
+char(p,19299).
+char(4,19300).
+char(8,19301).
+char(6,19302).
+char(1,19303).
+char(c,19304).
+char(m,19305).
+char(o,19306).
+char(o,19307).
+char(p,19308).
+char(o,19309).
+char(o,19310).
+char(m,19311).
+char(6,19312).
+char(1,19313).
+char(9,19314).
+char(5,19315).
+char(p,19316).
+char(o,19317).
+char(4,19318).
+char(6,19319).
+char(4,19320).
+char(0,19321).
+char(c,19322).
+char(p,19323).
+char(4,19324).
+char(0,19325).
+char(5,19326).
+char(c,19327).
+char(m,19328).
+char(o,19329).
+char(4,19330).
+char(8,19331).
+char(2,19332).
+char(7,19333).
+char(c,19334).
+char(c,19335).
+char(p,19336).
+char(o,19337).
+char(m,19338).
+char(8,19339).
+char(2,19340).
+char(5,19341).
+char(6,19342).
+char(c,19343).
+char(c,19344).
+char(c,19345).
+char(c,19346).
+char(p,19347).
+char(o,19348).
+char(7,19349).
+char(6,19350).
+char(7,19351).
+char(3,19352).
+char(c,19353).
+char(m,19354).
+char(o,19355).
+char(o,19356).
+char(m,19357).
+char(o,19358).
+char(m,19359).
+char(o,19360).
+char(p,19361).
+char(o,19362).
+char(m,19363).
+char(o,19364).
+char(6,19365).
+char(1,19366).
+char(5,19367).
+char(7,19368).
+char(p,19369).
+char(5,19370).
+char(8,19371).
+char(0,19372).
+char(8,19373).
+char(c,19374).
+char(c,19375).
+char(c,19376).
+char(c,19377).
+char(m,19378).
+char(2,19379).
+char(5,19380).
+char(9,19381).
+char(1,19382).
+char(c,19383).
+char(m,19384).
+char(o,19385).
+char(p,19386).
+char(8,19387).
+char(6,19388).
+char(8,19389).
+char(9,19390).
+char(c,19391).
+char(c,19392).
+char(m,19393).
+char(o,19394).
+char(o,19395).
+char(8,19396).
+char(5,19397).
+char(8,19398).
+char(0,19399).
+char(c,19400).
+char(p,19401).
+char(5,19402).
+char(2,19403).
+char(2,19404).
+char(2,19405).
+char(c,19406).
+char(m,19407).
+char(o,19408).
+char(p,19409).
+char(o,19410).
+char(m,19411).
+char(6,19412).
+char(6,19413).
+char(4,19414).
+char(9,19415).
+char(p,19416).
+char(o,19417).
+char(o,19418).
+char(m,19419).
+char(8,19420).
+char(6,19421).
+char(8,19422).
+char(6,19423).
+char(c,19424).
+char(c,19425).
+char(c,19426).
+char(p,19427).
+char(6,19428).
+char(2,19429).
+char(8,19430).
+char(5,19431).
+char(p,19432).
+char(7,19433).
+char(5,19434).
+char(1,19435).
+char(6,19436).
+char(p,19437).
+char(4,19438).
+char(6,19439).
+char(7,19440).
+char(3,19441).
+char(p,19442).
+char(1,19443).
+char(1,19444).
+char(8,19445).
+char(c,19446).
+char(c,19447).
+char(p,19448).
+char(5,19449).
+char(6,19450).
+char(2,19451).
+char(2,19452).
+char(c,19453).
+char(p,19454).
+char(5,19455).
+char(7,19456).
+char(1,19457).
+char(3,19458).
+char(c,19459).
+char(p,19460).
+char(o,19461).
+char(o,19462).
+char(2,19463).
+char(6,19464).
+char(9,19465).
+char(c,19466).
+char(c,19467).
+char(m,19468).
+char(o,19469).
+char(m,19470).
+char(o,19471).
+char(p,19472).
+char(o,19473).
+char(1,19474).
+char(2,19475).
+char(2,19476).
+char(9,19477).
+char(p,19478).
+char(o,19479).
+char(o,19480).
+char(p,19481).
+char(5,19482).
+char(7,19483).
+char(7,19484).
+char(0,19485).
+char(m,19486).
+char(o,19487).
+char(1,19488).
+char(4,19489).
+char(1,19490).
+char(7,19491).
+char(c,19492).
+char(c,19493).
+char(p,19494).
+char(o,19495).
+char(m,19496).
+char(o,19497).
+char(m,19498).
+char(o,19499).
+char(p,19500).
+char(o,19501).
+char(p,19502).
+char(9,19503).
+char(2,19504).
+char(7,19505).
+char(8,19506).
+char(c,19507).
+char(c,19508).
+char(c,19509).
+char(p,19510).
+char(o,19511).
+char(o,19512).
+char(p,19513).
+char(o,19514).
+char(m,19515).
+char(o,19516).
+char(m,19517).
+char(7,19518).
+char(2,19519).
+char(4,19520).
+char(5,19521).
+char(m,19522).
+char(o,19523).
+char(o,19524).
+char(m,19525).
+char(9,19526).
+char(2,19527).
+char(5,19528).
+char(6,19529).
+char(c,19530).
+char(p,19531).
+char(8,19532).
+char(1,19533).
+char(3,19534).
+char(5,19535).
+char(m,19536).
+char(2,19537).
+char(1,19538).
+char(0,19539).
+char(8,19540).
+char(m,19541).
+char(o,19542).
+char(o,19543).
+char(p,19544).
+char(o,19545).
+char(8,19546).
+char(3,19547).
+char(6,19548).
+char(8,19549).
+char(p,19550).
+char(5,19551).
+char(0,19552).
+char(2,19553).
+char(m,19554).
+char(o,19555).
+char(p,19556).
+char(1,19557).
+char(7,19558).
+char(7,19559).
+char(2,19560).
+char(c,19561).
+char(m,19562).
+char(1,19563).
+char(5,19564).
+char(0,19565).
+char(4,19566).
+char(p,19567).
+char(3,19568).
+char(5,19569).
+char(3,19570).
+char(8,19571).
+char(m,19572).
+char(o,19573).
+char(m,19574).
+char(4,19575).
+char(8,19576).
+char(1,19577).
+char(9,19578).
+char(c,19579).
+char(c,19580).
+char(p,19581).
+char(o,19582).
+char(p,19583).
+char(o,19584).
+char(p,19585).
+char(o,19586).
+char(p,19587).
+char(o,19588).
+char(m,19589).
+char(o,19590).
+char(m,19591).
+char(o,19592).
+char(o,19593).
+char(p,19594).
+char(o,19595).
+char(p,19596).
+char(5,19597).
+char(7,19598).
+char(2,19599).
+char(4,19600).
+char(c,19601).
+char(c,19602).
+char(c,19603).
+char(c,19604).
+char(p,19605).
+char(o,19606).
+char(o,19607).
+char(m,19608).
+char(o,19609).
+char(5,19610).
+char(6,19611).
+char(5,19612).
+char(9,19613).
+char(m,19614).
+char(5,19615).
+char(9,19616).
+char(5,19617).
+char(3,19618).
+char(c,19619).
+char(c,19620).
+char(c,19621).
+char(c,19622).
+char(p,19623).
+char(6,19624).
+char(8,19625).
+char(6,19626).
+char(9,19627).
+char(c,19628).
+char(p,19629).
+char(o,19630).
+char(o,19631).
+char(o,19632).
+char(m,19633).
+char(o,19634).
+char(p,19635).
+char(o,19636).
+char(m,19637).
+char(o,19638).
+char(o,19639).
+char(p,19640).
+char(o,19641).
+char(o,19642).
+char(p,19643).
+char(1,19644).
+char(9,19645).
+char(1,19646).
+char(2,19647).
+char(p,19648).
+char(o,19649).
+char(m,19650).
+char(1,19651).
+char(1,19652).
+char(4,19653).
+char(1,19654).
+char(p,19655).
+char(1,19656).
+char(7,19657).
+char(9,19658).
+char(1,19659).
+char(c,19660).
+char(m,19661).
+char(9,19662).
+char(5,19663).
+char(5,19664).
+char(7,19665).
+char(c,19666).
+char(c,19667).
+char(c,19668).
+char(m,19669).
+char(o,19670).
+char(p,19671).
+char(o,19672).
+char(p,19673).
+char(o,19674).
+char(p,19675).
+char(2,19676).
+char(0,19677).
+char(7,19678).
+char(3,19679).
+char(c,19680).
+char(c,19681).
+char(c,19682).
+char(c,19683).
+char(p,19684).
+char(6,19685).
+char(8,19686).
+char(0,19687).
+char(c,19688).
+char(c,19689).
+char(m,19690).
+char(o,19691).
+char(p,19692).
+char(3,19693).
+char(0,19694).
+char(6,19695).
+char(2,19696).
+char(m,19697).
+char(5,19698).
+char(9,19699).
+char(0,19700).
+char(3,19701).
+char(c,19702).
+char(c,19703).
+char(c,19704).
+char(p,19705).
+char(1,19706).
+char(4,19707).
+char(8,19708).
+char(2,19709).
+char(c,19710).
+char(m,19711).
+char(o,19712).
+char(p,19713).
+char(8,19714).
+char(6,19715).
+char(5,19716).
+char(6,19717).
+char(p,19718).
+char(o,19719).
+char(m,19720).
+char(5,19721).
+char(5,19722).
+char(6,19723).
+char(9,19724).
+char(c,19725).
+char(p,19726).
+char(o,19727).
+char(m,19728).
+char(o,19729).
+char(m,19730).
+char(o,19731).
+char(4,19732).
+char(9,19733).
+char(4,19734).
+char(7,19735).
+char(c,19736).
+char(p,19737).
+char(5,19738).
+char(2,19739).
+char(0,19740).
+char(3,19741).
+char(m,19742).
+char(7,19743).
+char(6,19744).
+char(0,19745).
+char(5,19746).
+char(c,19747).
+char(m,19748).
+char(o,19749).
+char(o,19750).
+char(p,19751).
+char(2,19752).
+char(2,19753).
+char(3,19754).
+char(5,19755).
+char(c,19756).
+char(m,19757).
+char(3,19758).
+char(5,19759).
+char(6,19760).
+char(c,19761).
+char(c,19762).
+char(m,19763).
+char(o,19764).
+char(o,19765).
+char(m,19766).
+char(o,19767).
+char(o,19768).
+char(p,19769).
+char(2,19770).
+char(6,19771).
+char(3,19772).
+char(6,19773).
+char(c,19774).
+char(m,19775).
+char(5,19776).
+char(8,19777).
+char(8,19778).
+char(9,19779).
+char(p,19780).
+char(o,19781).
+char(5,19782).
+char(5,19783).
+char(2,19784).
+char(0,19785).
+char(c,19786).
+char(m,19787).
+char(o,19788).
+char(p,19789).
+char(5,19790).
+char(6,19791).
+char(8,19792).
+char(p,19793).
+char(8,19794).
+char(7,19795).
+char(5,19796).
+char(3,19797).
+char(m,19798).
+char(o,19799).
+char(p,19800).
+char(6,19801).
+char(9,19802).
+char(7,19803).
+char(9,19804).
+char(c,19805).
+char(m,19806).
+char(9,19807).
+char(1,19808).
+char(2,19809).
+char(5,19810).
+char(c,19811).
+char(c,19812).
+char(c,19813).
+char(c,19814).
+char(c,19815).
+char(m,19816).
+char(o,19817).
+char(m,19818).
+char(5,19819).
+char(3,19820).
+char(6,19821).
+char(4,19822).
+char(p,19823).
+char(o,19824).
+char(m,19825).
+char(o,19826).
+char(o,19827).
+char(p,19828).
+char(o,19829).
+char(m,19830).
+char(o,19831).
+char(m,19832).
+char(3,19833).
+char(1,19834).
+char(4,19835).
+char(2,19836).
+char(c,19837).
+char(c,19838).
+char(c,19839).
+char(c,19840).
+char(m,19841).
+char(9,19842).
+char(7,19843).
+char(6,19844).
+char(6,19845).
+char(m,19846).
+char(1,19847).
+char(3,19848).
+char(1,19849).
+char(0,19850).
+char(m,19851).
+char(8,19852).
+char(7,19853).
+char(2,19854).
+char(8,19855).
+char(c,19856).
+char(c,19857).
+char(p,19858).
+char(o,19859).
+char(m,19860).
+char(9,19861).
+char(1,19862).
+char(4,19863).
+char(3,19864).
+char(m,19865).
+char(o,19866).
+char(p,19867).
+char(o,19868).
+char(o,19869).
+char(m,19870).
+char(o,19871).
+char(o,19872).
+char(m,19873).
+char(o,19874).
+char(3,19875).
+char(1,19876).
+char(8,19877).
+char(8,19878).
+char(c,19879).
+char(c,19880).
+char(c,19881).
+char(p,19882).
+char(1,19883).
+char(1,19884).
+char(3,19885).
+char(5,19886).
+char(p,19887).
+char(o,19888).
+char(m,19889).
+char(o,19890).
+char(p,19891).
+char(o,19892).
+char(m,19893).
+char(o,19894).
+char(o,19895).
+char(m,19896).
+char(o,19897).
+char(p,19898).
+char(9,19899).
+char(5,19900).
+char(8,19901).
+char(c,19902).
+char(m,19903).
+char(o,19904).
+char(m,19905).
+char(o,19906).
+char(p,19907).
+char(o,19908).
+char(o,19909).
+char(m,19910).
+char(o,19911).
+char(m,19912).
+char(o,19913).
+char(o,19914).
+char(5,19915).
+char(1,19916).
+char(0,19917).
+char(2,19918).
+char(m,19919).
+char(9,19920).
+char(3,19921).
+char(7,19922).
+char(2,19923).
+char(p,19924).
+char(o,19925).
+char(p,19926).
+char(o,19927).
+char(o,19928).
+char(p,19929).
+char(4,19930).
+char(7,19931).
+char(5,19932).
+char(3,19933).
+char(c,19934).
+char(p,19935).
+char(3,19936).
+char(8,19937).
+char(5,19938).
+char(8,19939).
+char(c,19940).
+char(c,19941).
+char(c,19942).
+char(c,19943).
+char(p,19944).
+char(o,19945).
+char(p,19946).
+char(2,19947).
+char(0,19948).
+char(7,19949).
+char(2,19950).
+char(c,19951).
+char(c,19952).
+char(p,19953).
+char(o,19954).
+char(p,19955).
+char(o,19956).
+char(m,19957).
+char(o,19958).
+char(m,19959).
+char(o,19960).
+char(o,19961).
+char(6,19962).
+char(7,19963).
+char(6,19964).
+char(2,19965).
+char(p,19966).
+char(1,19967).
+char(4,19968).
+char(4,19969).
+char(3,19970).
+char(m,19971).
+char(1,19972).
+char(2,19973).
+char(3,19974).
+char(6,19975).
+char(m,19976).
+char(o,19977).
+char(p,19978).
+char(7,19979).
+char(3,19980).
+char(7,19981).
+char(5,19982).
+char(p,19983).
+char(6,19984).
+char(0,19985).
+char(5,19986).
+char(9,19987).
+char(m,19988).
+char(o,19989).
+char(o,19990).
+char(p,19991).
+char(o,19992).
+char(6,19993).
+char(0,19994).
+char(6,19995).
+char(2,19996).
+char(c,19997).
+char(c,19998).
+char(p,19999).
+char(o,20000).
+char(p,20001).
+char(o,20002).
+char(p,20003).
+char(o,20004).
+char(9,20005).
+char(1,20006).
+char(3,20007).
+char(c,20008).
+char(m,20009).
+char(o,20010).
+char(p,20011).
+char(o,20012).
+char(m,20013).
+char(o,20014).
+char(p,20015).
+char(1,20016).
+char(1,20017).
+char(9,20018).
+char(0,20019).
+char(p,20020).
+char(o,20021).
+char(m,20022).
+char(o,20023).
+char(m,20024).
+char(o,20025).
+char(p,20026).
+char(o,20027).
+char(p,20028).
+char(o,20029).
+char(o,20030).
+char(p,20031).
+char(5,20032).
+char(6,20033).
+char(2,20034).
+char(3,20035).
+char(p,20036).
+char(5,20037).
+char(6,20038).
+char(8,20039).
+char(3,20040).
+char(m,20041).
+char(o,20042).
+char(p,20043).
+char(o,20044).
+char(o,20045).
+char(m,20046).
+char(6,20047).
+char(0,20048).
+char(0,20049).
+char(p,20050).
+char(o,20051).
+char(p,20052).
+char(o,20053).
+char(3,20054).
+char(0,20055).
+char(9,20056).
+char(5,20057).
+char(p,20058).
+char(3,20059).
+char(0,20060).
+char(0,20061).
+char(2,20062).
+char(c,20063).
+char(m,20064).
+char(o,20065).
+char(m,20066).
+char(3,20067).
+char(2,20068).
+char(9,20069).
+char(9,20070).
+char(m,20071).
+char(9,20072).
+char(4,20073).
+char(6,20074).
+char(4,20075).
+char(c,20076).
+char(p,20077).
+char(6,20078).
+char(9,20079).
+char(6,20080).
+char(9,20081).
+char(p,20082).
+char(o,20083).
+char(7,20084).
+char(8,20085).
+char(8,20086).
+char(2,20087).
+char(p,20088).
+char(o,20089).
+char(p,20090).
+char(7,20091).
+char(7,20092).
+char(4,20093).
+char(2,20094).
+char(p,20095).
+char(o,20096).
+char(p,20097).
+char(o,20098).
+char(p,20099).
+char(9,20100).
+char(8,20101).
+char(5,20102).
+char(4,20103).
+char(c,20104).
+char(m,20105).
+char(o,20106).
+char(o,20107).
+char(m,20108).
+char(o,20109).
+char(p,20110).
+char(o,20111).
+char(p,20112).
+char(8,20113).
+char(9,20114).
+char(6,20115).
+char(4,20116).
+char(c,20117).
+char(m,20118).
+char(7,20119).
+char(5,20120).
+char(9,20121).
+char(p,20122).
+char(o,20123).
+char(m,20124).
+char(5,20125).
+char(9,20126).
+char(4,20127).
+char(3,20128).
+char(p,20129).
+char(o,20130).
+char(p,20131).
+char(1,20132).
+char(7,20133).
+char(8,20134).
+char(p,20135).
+char(8,20136).
+char(0,20137).
+char(1,20138).
+char(4,20139).
+char(c,20140).
+char(p,20141).
+char(o,20142).
+char(m,20143).
+char(o,20144).
+char(1,20145).
+char(2,20146).
+char(2,20147).
+char(4,20148).
+char(c,20149).
+char(m,20150).
+char(o,20151).
+char(m,20152).
+char(o,20153).
+char(p,20154).
+char(6,20155).
+char(0,20156).
+char(7,20157).
+char(8,20158).
+char(c,20159).
+char(c,20160).
+char(c,20161).
+char(c,20162).
+char(m,20163).
+char(8,20164).
+char(9,20165).
+char(1,20166).
+char(6,20167).
+char(m,20168).
+char(o,20169).
+char(p,20170).
+char(o,20171).
+char(m,20172).
+char(1,20173).
+char(9,20174).
+char(1,20175).
+char(5,20176).
+char(c,20177).
+char(c,20178).
+char(p,20179).
+char(o,20180).
+char(o,20181).
+char(p,20182).
+char(4,20183).
+char(9,20184).
+char(0,20185).
+char(5,20186).
+char(c,20187).
+char(p,20188).
+char(o,20189).
+char(m,20190).
+char(9,20191).
+char(7,20192).
+char(2,20193).
+char(6,20194).
+char(c,20195).
+char(c,20196).
+char(p,20197).
+char(o,20198).
+char(o,20199).
+char(m,20200).
+char(o,20201).
+char(m,20202).
+char(8,20203).
+char(7,20204).
+char(8,20205).
+char(9,20206).
+char(c,20207).
+char(c,20208).
+char(m,20209).
+char(o,20210).
+char(p,20211).
+char(7,20212).
+char(8,20213).
+char(2,20214).
+char(6,20215).
+char(p,20216).
+char(7,20217).
+char(5,20218).
+char(5,20219).
+char(1,20220).
+char(p,20221).
+char(o,20222).
+char(p,20223).
+char(o,20224).
+char(m,20225).
+char(o,20226).
+char(o,20227).
+char(p,20228).
+char(9,20229).
+char(2,20230).
+char(4,20231).
+char(8,20232).
+char(c,20233).
+char(c,20234).
+char(m,20235).
+char(o,20236).
+char(3,20237).
+char(3,20238).
+char(9,20239).
+char(2,20240).
+char(p,20241).
+char(o,20242).
+char(o,20243).
+char(o,20244).
+char(p,20245).
+char(o,20246).
+char(p,20247).
+char(7,20248).
+char(0,20249).
+char(3,20250).
+char(c,20251).
+char(c,20252).
+char(c,20253).
+char(c,20254).
+char(c,20255).
+char(c,20256).
+char(p,20257).
+char(3,20258).
+char(8,20259).
+char(3,20260).
+char(5,20261).
+char(c,20262).
+char(c,20263).
+char(p,20264).
+char(5,20265).
+char(8,20266).
+char(4,20267).
+char(c,20268).
+char(p,20269).
+char(o,20270).
+char(p,20271).
+char(o,20272).
+char(m,20273).
+char(o,20274).
+char(m,20275).
+char(o,20276).
+char(o,20277).
+char(m,20278).
+char(o,20279).
+char(7,20280).
+char(6,20281).
+char(2,20282).
+char(7,20283).
+char(c,20284).
+char(p,20285).
+char(7,20286).
+char(0,20287).
+char(7,20288).
+char(m,20289).
+char(o,20290).
+char(m,20291).
+char(o,20292).
+char(m,20293).
+char(2,20294).
+char(5,20295).
+char(6,20296).
+char(3,20297).
+char(m,20298).
+char(o,20299).
+char(m,20300).
+char(4,20301).
+char(2,20302).
+char(9,20303).
+char(3,20304).
+char(m,20305).
+char(4,20306).
+char(5,20307).
+char(4,20308).
+char(8,20309).
+char(c,20310).
+char(c,20311).
+char(c,20312).
+char(p,20313).
+char(o,20314).
+char(p,20315).
+char(5,20316).
+char(3,20317).
+char(2,20318).
+char(c,20319).
+char(m,20320).
+char(o,20321).
+char(m,20322).
+char(o,20323).
+char(p,20324).
+char(5,20325).
+char(1,20326).
+char(8,20327).
+char(5,20328).
+char(p,20329).
+char(9,20330).
+char(8,20331).
+char(5,20332).
+char(2,20333).
+char(p,20334).
+char(o,20335).
+char(8,20336).
+char(1,20337).
+char(7,20338).
+char(4,20339).
+char(p,20340).
+char(2,20341).
+char(8,20342).
+char(7,20343).
+char(8,20344).
+char(c,20345).
+char(c,20346).
+char(p,20347).
+char(o,20348).
+char(m,20349).
+char(1,20350).
+char(0,20351).
+char(0,20352).
+char(2,20353).
+char(p,20354).
+char(o,20355).
+char(m,20356).
+char(o,20357).
+char(4,20358).
+char(9,20359).
+char(2,20360).
+char(6,20361).
+char(c,20362).
+char(m,20363).
+char(8,20364).
+char(0,20365).
+char(1,20366).
+char(0,20367).
+char(c,20368).
+char(p,20369).
+char(6,20370).
+char(4,20371).
+char(9,20372).
+char(7,20373).
+char(p,20374).
+char(9,20375).
+char(5,20376).
+char(4,20377).
+char(5,20378).
+char(c,20379).
+char(c,20380).
+char(c,20381).
+char(c,20382).
+char(p,20383).
+char(o,20384).
+char(4,20385).
+char(9,20386).
+char(2,20387).
+char(6,20388).
+char(p,20389).
+char(o,20390).
+char(m,20391).
+char(6,20392).
+char(5,20393).
+char(0,20394).
+char(7,20395).
+char(c,20396).
+char(c,20397).
+char(m,20398).
+char(o,20399).
+char(o,20400).
+char(m,20401).
+char(o,20402).
+char(p,20403).
+char(9,20404).
+char(7,20405).
+char(8,20406).
+char(6,20407).
+char(p,20408).
+char(o,20409).
+char(p,20410).
+char(o,20411).
+char(p,20412).
+char(o,20413).
+char(m,20414).
+char(6,20415).
+char(6,20416).
+char(1,20417).
+char(3,20418).
+char(c,20419).
+char(m,20420).
+char(2,20421).
+char(7,20422).
+char(6,20423).
+char(5,20424).
+char(p,20425).
+char(o,20426).
+char(m,20427).
+char(o,20428).
+char(m,20429).
+char(5,20430).
+char(9,20431).
+char(7,20432).
+char(1,20433).
+char(c,20434).
+char(m,20435).
+char(1,20436).
+char(2,20437).
+char(5,20438).
+char(c,20439).
+char(p,20440).
+char(o,20441).
+char(m,20442).
+char(3,20443).
+char(3,20444).
+char(8,20445).
+char(3,20446).
+char(c,20447).
+char(m,20448).
+char(1,20449).
+char(7,20450).
+char(7,20451).
+char(7,20452).
+char(c,20453).
+char(c,20454).
+char(m,20455).
+char(9,20456).
+char(4,20457).
+char(3,20458).
+char(2,20459).
+char(m,20460).
+char(2,20461).
+char(1,20462).
+char(9,20463).
+char(1,20464).
+char(p,20465).
+char(o,20466).
+char(2,20467).
+char(1,20468).
+char(0,20469).
+char(7,20470).
+char(c,20471).
+char(p,20472).
+char(o,20473).
+char(p,20474).
+char(o,20475).
+char(p,20476).
+char(3,20477).
+char(0,20478).
+char(2,20479).
+char(5,20480).
+char(c,20481).
+char(c,20482).
+char(c,20483).
+char(c,20484).
+char(p,20485).
+char(8,20486).
+char(5,20487).
+char(7,20488).
+char(5,20489).
+char(p,20490).
+char(7,20491).
+char(0,20492).
+char(1,20493).
+char(7,20494).
+char(c,20495).
+char(c,20496).
+char(p,20497).
+char(o,20498).
+char(o,20499).
+char(p,20500).
+char(o,20501).
+char(o,20502).
+char(3,20503).
+char(3,20504).
+char(7,20505).
+char(5,20506).
+char(c,20507).
+char(m,20508).
+char(o,20509).
+char(m,20510).
+char(7,20511).
+char(8,20512).
+char(1,20513).
+char(6,20514).
+char(c,20515).
+char(m,20516).
+char(3,20517).
+char(6,20518).
+char(7,20519).
+char(6,20520).
+char(m,20521).
+char(o,20522).
+char(5,20523).
+char(2,20524).
+char(5,20525).
+char(0,20526).
+char(m,20527).
+char(o,20528).
+char(p,20529).
+char(5,20530).
+char(9,20531).
+char(2,20532).
+char(0,20533).
+char(c,20534).
+char(c,20535).
+char(p,20536).
+char(8,20537).
+char(0,20538).
+char(0,20539).
+char(3,20540).
+char(m,20541).
+char(o,20542).
+char(m,20543).
+char(o,20544).
+char(m,20545).
+char(o,20546).
+char(9,20547).
+char(8,20548).
+char(6,20549).
+char(1,20550).
+char(p,20551).
+char(1,20552).
+char(2,20553).
+char(1,20554).
+char(0,20555).
+char(m,20556).
+char(9,20557).
+char(2,20558).
+char(5,20559).
+char(0,20560).
+char(p,20561).
+char(o,20562).
+char(o,20563).
+char(m,20564).
+char(7,20565).
+char(8,20566).
+char(7,20567).
+char(1,20568).
+char(p,20569).
+char(o,20570).
+char(8,20571).
+char(9,20572).
+char(8,20573).
+char(6,20574).
+char(c,20575).
+char(m,20576).
+char(5,20577).
+char(6,20578).
+char(7,20579).
+char(c,20580).
+char(c,20581).
+char(m,20582).
+char(1,20583).
+char(1,20584).
+char(6,20585).
+char(7,20586).
+char(c,20587).
+char(c,20588).
+char(c,20589).
+char(p,20590).
+char(5,20591).
+char(4,20592).
+char(6,20593).
+char(1,20594).
+char(m,20595).
+char(2,20596).
+char(3,20597).
+char(5,20598).
+char(c,20599).
+char(c,20600).
+char(m,20601).
+char(3,20602).
+char(3,20603).
+char(9,20604).
+char(1,20605).
+char(m,20606).
+char(5,20607).
+char(0,20608).
+char(1,20609).
+char(6,20610).
+char(p,20611).
+char(3,20612).
+char(9,20613).
+char(7,20614).
+char(4,20615).
+char(m,20616).
+char(o,20617).
+char(m,20618).
+char(o,20619).
+char(p,20620).
+char(8,20621).
+char(3,20622).
+char(9,20623).
+char(2,20624).
+char(m,20625).
+char(o,20626).
+char(m,20627).
+char(6,20628).
+char(2,20629).
+char(1,20630).
+char(8,20631).
+char(c,20632).
+char(c,20633).
+char(c,20634).
+char(c,20635).
+char(c,20636).
+char(p,20637).
+char(5,20638).
+char(7,20639).
+char(8,20640).
+char(5,20641).
+char(m,20642).
+char(6,20643).
+char(9,20644).
+char(7,20645).
+char(m,20646).
+char(o,20647).
+char(9,20648).
+char(5,20649).
+char(8,20650).
+char(3,20651).
+char(p,20652).
+char(2,20653).
+char(1,20654).
+char(8,20655).
+char(c,20656).
+char(p,20657).
+char(1,20658).
+char(5,20659).
+char(0,20660).
+char(6,20661).
+char(m,20662).
+char(o,20663).
+char(m,20664).
+char(o,20665).
+char(p,20666).
+char(o,20667).
+char(p,20668).
+char(o,20669).
+char(2,20670).
+char(1,20671).
+char(8,20672).
+char(9,20673).
+char(c,20674).
+char(p,20675).
+char(o,20676).
+char(9,20677).
+char(8,20678).
+char(5,20679).
+char(0,20680).
+char(c,20681).
+char(m,20682).
+char(4,20683).
+char(8,20684).
+char(5,20685).
+char(7,20686).
+char(m,20687).
+char(o,20688).
+char(p,20689).
+char(8,20690).
+char(5,20691).
+char(2,20692).
+char(5,20693).
+char(c,20694).
+char(c,20695).
+char(m,20696).
+char(o,20697).
+char(p,20698).
+char(o,20699).
+char(5,20700).
+char(8,20701).
+char(9,20702).
+char(9,20703).
+char(c,20704).
+char(p,20705).
+char(o,20706).
+char(p,20707).
+char(6,20708).
+char(1,20709).
+char(2,20710).
+char(2,20711).
+char(p,20712).
+char(o,20713).
+char(m,20714).
+char(6,20715).
+char(8,20716).
+char(7,20717).
+char(9,20718).
+char(p,20719).
+char(o,20720).
+char(o,20721).
+char(m,20722).
+char(7,20723).
+char(9,20724).
+char(1,20725).
+char(m,20726).
+char(o,20727).
+char(p,20728).
+char(o,20729).
+char(p,20730).
+char(o,20731).
+char(o,20732).
+char(m,20733).
+char(8,20734).
+char(1,20735).
+char(8,20736).
+char(3,20737).
+char(c,20738).
+char(m,20739).
+char(o,20740).
+char(m,20741).
+char(o,20742).
+char(5,20743).
+char(0,20744).
+char(0,20745).
+char(4,20746).
+char(p,20747).
+char(4,20748).
+char(3,20749).
+char(4,20750).
+char(9,20751).
+char(c,20752).
+char(c,20753).
+char(c,20754).
+char(p,20755).
+char(9,20756).
+char(6,20757).
+char(1,20758).
+char(4,20759).
+char(m,20760).
+char(o,20761).
+char(p,20762).
+char(o,20763).
+char(m,20764).
+char(o,20765).
+char(m,20766).
+char(o,20767).
+char(m,20768).
+char(2,20769).
+char(3,20770).
+char(9,20771).
+char(c,20772).
+char(m,20773).
+char(9,20774).
+char(3,20775).
+char(7,20776).
+char(c,20777).
+char(c,20778).
+char(c,20779).
+char(p,20780).
+char(4,20781).
+char(7,20782).
+char(6,20783).
+char(c,20784).
+char(c,20785).
+char(c,20786).
+char(p,20787).
+char(8,20788).
+char(5,20789).
+char(6,20790).
+char(8,20791).
+char(m,20792).
+char(5,20793).
+char(5,20794).
+char(0,20795).
+char(m,20796).
+char(8,20797).
+char(6,20798).
+char(8,20799).
+char(7,20800).
+char(c,20801).
+char(c,20802).
+char(c,20803).
+char(m,20804).
+char(8,20805).
+char(5,20806).
+char(3,20807).
+char(9,20808).
+char(p,20809).
+char(2,20810).
+char(9,20811).
+char(7,20812).
+char(3,20813).
+char(c,20814).
+char(m,20815).
+char(5,20816).
+char(0,20817).
+char(8,20818).
+char(2,20819).
+char(m,20820).
+char(3,20821).
+char(3,20822).
+char(5,20823).
+char(6,20824).
+char(m,20825).
+char(o,20826).
+char(m,20827).
+char(9,20828).
+char(5,20829).
+char(3,20830).
+char(8,20831).
+char(c,20832).
+char(c,20833).
+char(p,20834).
+char(o,20835).
+char(p,20836).
+char(o,20837).
+char(p,20838).
+char(4,20839).
+char(2,20840).
+char(6,20841).
+char(9,20842).
+char(p,20843).
+char(o,20844).
+char(o,20845).
+char(m,20846).
+char(o,20847).
+char(p,20848).
+char(o,20849).
+char(o,20850).
+char(8,20851).
+char(1,20852).
+char(2,20853).
+char(7,20854).
+char(m,20855).
+char(o,20856).
+char(o,20857).
+char(p,20858).
+char(8,20859).
+char(6,20860).
+char(3,20861).
+char(4,20862).
+char(c,20863).
+char(c,20864).
+char(m,20865).
+char(7,20866).
+char(6,20867).
+char(2,20868).
+char(0,20869).
+char(c,20870).
+char(c,20871).
+char(m,20872).
+char(4,20873).
+char(1,20874).
+char(9,20875).
+char(p,20876).
+char(6,20877).
+char(6,20878).
+char(0,20879).
+char(7,20880).
+char(c,20881).
+char(c,20882).
+char(c,20883).
+char(c,20884).
+char(m,20885).
+char(1,20886).
+char(0,20887).
+char(4,20888).
+char(p,20889).
+char(8,20890).
+char(2,20891).
+char(9,20892).
+char(6,20893).
+char(c,20894).
+char(p,20895).
+char(8,20896).
+char(8,20897).
+char(2,20898).
+char(3,20899).
+char(m,20900).
+char(8,20901).
+char(9,20902).
+char(9,20903).
+char(7,20904).
+char(m,20905).
+char(9,20906).
+char(0,20907).
+char(3,20908).
+char(2,20909).
+char(c,20910).
+char(p,20911).
+char(9,20912).
+char(0,20913).
+char(2,20914).
+char(9,20915).
+char(p,20916).
+char(o,20917).
+char(p,20918).
+char(5,20919).
+char(9,20920).
+char(2,20921).
+char(2,20922).
+char(c,20923).
+char(m,20924).
+char(o,20925).
+char(p,20926).
+char(o,20927).
+char(2,20928).
+char(0,20929).
+char(4,20930).
+char(0,20931).
+char(p,20932).
+char(o,20933).
+char(m,20934).
+char(3,20935).
+char(5,20936).
+char(5,20937).
+char(5,20938).
+char(c,20939).
+char(c,20940).
+char(p,20941).
+char(3,20942).
+char(3,20943).
+char(8,20944).
+char(3,20945).
+char(m,20946).
+char(o,20947).
+char(m,20948).
+char(8,20949).
+char(4,20950).
+char(7,20951).
+char(2,20952).
+char(c,20953).
+char(c,20954).
+char(c,20955).
+char(m,20956).
+char(o,20957).
+char(p,20958).
+char(7,20959).
+char(9,20960).
+char(3,20961).
+char(5,20962).
+char(p,20963).
+char(9,20964).
+char(7,20965).
+char(1,20966).
+char(9,20967).
+char(c,20968).
+char(m,20969).
+char(o,20970).
+char(m,20971).
+char(o,20972).
+char(o,20973).
+char(m,20974).
+char(1,20975).
+char(7,20976).
+char(6,20977).
+char(7,20978).
+char(c,20979).
+char(p,20980).
+char(9,20981).
+char(1,20982).
+char(6,20983).
+char(4,20984).
+char(c,20985).
+char(p,20986).
+char(o,20987).
+char(m,20988).
+char(6,20989).
+char(3,20990).
+char(3,20991).
+char(0,20992).
+char(c,20993).
+char(c,20994).
+char(p,20995).
+char(o,20996).
+char(p,20997).
+char(o,20998).
+char(9,20999).
+char(7,21000).
+char(5,21001).
+char(0,21002).
+char(c,21003).
+char(c,21004).
+char(m,21005).
+char(8,21006).
+char(2,21007).
+char(2,21008).
+char(5,21009).
+char(c,21010).
+char(c,21011).
+char(m,21012).
+char(o,21013).
+char(p,21014).
+char(o,21015).
+char(p,21016).
+char(o,21017).
+char(5,21018).
+char(0,21019).
+char(5,21020).
+char(1,21021).
+char(m,21022).
+char(2,21023).
+char(5,21024).
+char(4,21025).
+char(9,21026).
+char(m,21027).
+char(o,21028).
+char(m,21029).
+char(o,21030).
+char(o,21031).
+char(p,21032).
+char(o,21033).
+char(p,21034).
+char(o,21035).
+char(m,21036).
+char(3,21037).
+char(4,21038).
+char(7,21039).
+char(8,21040).
+char(p,21041).
+char(o,21042).
+char(1,21043).
+char(5,21044).
+char(2,21045).
+char(9,21046).
+char(c,21047).
+char(p,21048).
+char(o,21049).
+char(7,21050).
+char(0,21051).
+char(7,21052).
+char(3,21053).
+char(c,21054).
+char(p,21055).
+char(o,21056).
+char(m,21057).
+char(6,21058).
+char(3,21059).
+char(9,21060).
+char(4,21061).
+char(m,21062).
+char(o,21063).
+char(m,21064).
+char(o,21065).
+char(o,21066).
+char(m,21067).
+char(o,21068).
+char(o,21069).
+char(1,21070).
+char(3,21071).
+char(7,21072).
+char(7,21073).
+char(c,21074).
+char(c,21075).
+char(m,21076).
+char(o,21077).
+char(p,21078).
+char(o,21079).
+char(p,21080).
+char(3,21081).
+char(2,21082).
+char(0,21083).
+char(0,21084).
+char(m,21085).
+char(5,21086).
+char(4,21087).
+char(2,21088).
+char(9,21089).
+char(c,21090).
+char(c,21091).
+char(c,21092).
+char(c,21093).
+char(c,21094).
+char(m,21095).
+char(o,21096).
+char(p,21097).
+char(o,21098).
+char(p,21099).
+char(o,21100).
+char(o,21101).
+char(p,21102).
+char(1,21103).
+char(6,21104).
+char(1,21105).
+char(6,21106).
+char(m,21107).
+char(o,21108).
+char(m,21109).
+char(o,21110).
+char(2,21111).
+char(7,21112).
+char(0,21113).
+char(c,21114).
+char(p,21115).
+char(1,21116).
+char(9,21117).
+char(6,21118).
+char(5,21119).
+char(c,21120).
+char(p,21121).
+char(o,21122).
+char(p,21123).
+char(4,21124).
+char(4,21125).
+char(9,21126).
+char(c,21127).
+char(c,21128).
+char(c,21129).
+char(m,21130).
+char(5,21131).
+char(2,21132).
+char(6,21133).
+char(1,21134).
+char(p,21135).
+char(o,21136).
+char(m,21137).
+char(2,21138).
+char(8,21139).
+char(5,21140).
+char(3,21141).
+char(c,21142).
+char(p,21143).
+char(o,21144).
+char(6,21145).
+char(8,21146).
+char(9,21147).
+char(5,21148).
+char(p,21149).
+char(2,21150).
+char(6,21151).
+char(6,21152).
+char(5,21153).
+char(c,21154).
+char(c,21155).
+char(p,21156).
+char(o,21157).
+char(p,21158).
+char(2,21159).
+char(0,21160).
+char(4,21161).
+char(2,21162).
+char(c,21163).
+char(c,21164).
+char(p,21165).
+char(8,21166).
+char(7,21167).
+char(9,21168).
+char(6,21169).
+char(p,21170).
+char(o,21171).
+char(9,21172).
+char(3,21173).
+char(9,21174).
+char(1,21175).
+char(c,21176).
+char(m,21177).
+char(o,21178).
+char(p,21179).
+char(3,21180).
+char(6,21181).
+char(3,21182).
+char(0,21183).
+char(p,21184).
+char(5,21185).
+char(5,21186).
+char(0,21187).
+char(8,21188).
+char(c,21189).
+char(p,21190).
+char(8,21191).
+char(9,21192).
+char(2,21193).
+char(7,21194).
+char(p,21195).
+char(8,21196).
+char(3,21197).
+char(0,21198).
+char(5,21199).
+char(c,21200).
+char(c,21201).
+char(c,21202).
+char(m,21203).
+char(o,21204).
+char(p,21205).
+char(o,21206).
+char(m,21207).
+char(o,21208).
+char(8,21209).
+char(7,21210).
+char(4,21211).
+char(0,21212).
+char(c,21213).
+char(p,21214).
+char(o,21215).
+char(p,21216).
+char(6,21217).
+char(8,21218).
+char(0,21219).
+char(3,21220).
+char(c,21221).
+char(p,21222).
+char(9,21223).
+char(8,21224).
+char(8,21225).
+char(0,21226).
+char(c,21227).
+char(p,21228).
+char(o,21229).
+char(p,21230).
+char(1,21231).
+char(0,21232).
+char(3,21233).
+char(1,21234).
+char(c,21235).
+char(c,21236).
+char(c,21237).
+char(c,21238).
+char(c,21239).
+char(c,21240).
+char(c,21241).
+char(c,21242).
+char(m,21243).
+char(4,21244).
+char(0,21245).
+char(6,21246).
+char(7,21247).
+char(c,21248).
+char(c,21249).
+char(p,21250).
+char(1,21251).
+char(8,21252).
+char(1,21253).
+char(m,21254).
+char(o,21255).
+char(m,21256).
+char(o,21257).
+char(o,21258).
+char(5,21259).
+char(9,21260).
+char(1,21261).
+char(6,21262).
+char(c,21263).
+char(c,21264).
+char(p,21265).
+char(7,21266).
+char(3,21267).
+char(3,21268).
+char(7,21269).
+char(p,21270).
+char(7,21271).
+char(6,21272).
+char(7,21273).
+char(9,21274).
+char(m,21275).
+char(o,21276).
+char(o,21277).
+char(p,21278).
+char(o,21279).
+char(p,21280).
+char(o,21281).
+char(o,21282).
+char(m,21283).
+char(2,21284).
+char(1,21285).
+char(9,21286).
+char(9,21287).
+char(c,21288).
+char(m,21289).
+char(8,21290).
+char(9,21291).
+char(0,21292).
+char(7,21293).
+char(c,21294).
+char(p,21295).
+char(o,21296).
+char(o,21297).
+char(p,21298).
+char(o,21299).
+char(p,21300).
+char(7,21301).
+char(8,21302).
+char(1,21303).
+char(p,21304).
+char(7,21305).
+char(4,21306).
+char(4,21307).
+char(9,21308).
+char(m,21309).
+char(o,21310).
+char(m,21311).
+char(6,21312).
+char(1,21313).
+char(8,21314).
+char(6,21315).
+char(c,21316).
+char(p,21317).
+char(5,21318).
+char(6,21319).
+char(9,21320).
+char(4,21321).
+char(p,21322).
+char(o,21323).
+char(p,21324).
+char(8,21325).
+char(4,21326).
+char(1,21327).
+char(3,21328).
+char(m,21329).
+char(8,21330).
+char(7,21331).
+char(3,21332).
+char(9,21333).
+char(p,21334).
+char(o,21335).
+char(o,21336).
+char(m,21337).
+char(1,21338).
+char(5,21339).
+char(3,21340).
+char(2,21341).
+char(m,21342).
+char(6,21343).
+char(9,21344).
+char(8,21345).
+char(2,21346).
+char(m,21347).
+char(o,21348).
+char(p,21349).
+char(1,21350).
+char(0,21351).
+char(2,21352).
+char(5,21353).
+char(c,21354).
+char(c,21355).
+char(m,21356).
+char(o,21357).
+char(m,21358).
+char(o,21359).
+char(m,21360).
+char(o,21361).
+char(3,21362).
+char(8,21363).
+char(0,21364).
+char(3,21365).
+char(c,21366).
+char(c,21367).
+char(c,21368).
+char(c,21369).
+char(c,21370).
+char(c,21371).
+char(c,21372).
+char(p,21373).
+char(o,21374).
+char(m,21375).
+char(9,21376).
+char(7,21377).
+char(5,21378).
+char(2,21379).
+char(c,21380).
+char(c,21381).
+char(c,21382).
+char(p,21383).
+char(3,21384).
+char(0,21385).
+char(4,21386).
+char(4,21387).
+char(m,21388).
+char(1,21389).
+char(0,21390).
+char(6,21391).
+char(8,21392).
+char(c,21393).
+char(p,21394).
+char(2,21395).
+char(6,21396).
+char(0,21397).
+char(2,21398).
+char(p,21399).
+char(1,21400).
+char(9,21401).
+char(8,21402).
+char(3,21403).
+char(c,21404).
+char(p,21405).
+char(o,21406).
+char(p,21407).
+char(o,21408).
+char(p,21409).
+char(3,21410).
+char(3,21411).
+char(6,21412).
+char(4,21413).
+char(p,21414).
+char(3,21415).
+char(1,21416).
+char(5,21417).
+char(2,21418).
+char(m,21419).
+char(5,21420).
+char(6,21421).
+char(6,21422).
+char(2,21423).
+char(m,21424).
+char(9,21425).
+char(3,21426).
+char(2,21427).
+char(1,21428).
+char(c,21429).
+char(p,21430).
+char(5,21431).
+char(1,21432).
+char(5,21433).
+char(5,21434).
+char(m,21435).
+char(5,21436).
+char(0,21437).
+char(1,21438).
+char(7,21439).
+char(p,21440).
+char(o,21441).
+char(m,21442).
+char(3,21443).
+char(2,21444).
+char(2,21445).
+char(5,21446).
+char(p,21447).
+char(o,21448).
+char(p,21449).
+char(1,21450).
+char(5,21451).
+char(8,21452).
+char(2,21453).
+char(c,21454).
+char(c,21455).
+char(p,21456).
+char(o,21457).
+char(2,21458).
+char(6,21459).
+char(0,21460).
+char(1,21461).
+char(m,21462).
+char(o,21463).
+char(p,21464).
+char(o,21465).
+char(m,21466).
+char(9,21467).
+char(0,21468).
+char(8,21469).
+char(p,21470).
+char(1,21471).
+char(5,21472).
+char(5,21473).
+char(2,21474).
+char(c,21475).
+char(c,21476).
+char(m,21477).
+char(5,21478).
+char(0,21479).
+char(0,21480).
+char(5,21481).
+char(p,21482).
+char(8,21483).
+char(7,21484).
+char(8,21485).
+char(4,21486).
+char(c,21487).
+char(m,21488).
+char(o,21489).
+char(m,21490).
+char(5,21491).
+char(8,21492).
+char(6,21493).
+char(3,21494).
+char(m,21495).
+char(o,21496).
+char(p,21497).
+char(1,21498).
+char(7,21499).
+char(9,21500).
+char(5,21501).
+char(m,21502).
+char(9,21503).
+char(2,21504).
+char(6,21505).
+char(3,21506).
+char(c,21507).
+char(c,21508).
+char(p,21509).
+char(1,21510).
+char(3,21511).
+char(6,21512).
+char(7,21513).
+char(p,21514).
+char(o,21515).
+char(2,21516).
+char(1,21517).
+char(4,21518).
+char(4,21519).
+char(c,21520).
+char(p,21521).
+char(7,21522).
+char(3,21523).
+char(6,21524).
+char(5,21525).
+char(c,21526).
+char(c,21527).
+char(c,21528).
+char(p,21529).
+char(7,21530).
+char(8,21531).
+char(7,21532).
+char(9,21533).
+char(m,21534).
+char(o,21535).
+char(o,21536).
+char(5,21537).
+char(6,21538).
+char(2,21539).
+char(4,21540).
+char(c,21541).
+char(p,21542).
+char(3,21543).
+char(2,21544).
+char(1,21545).
+char(2,21546).
+char(c,21547).
+char(p,21548).
+char(o,21549).
+char(m,21550).
+char(7,21551).
+char(4,21552).
+char(6,21553).
+char(9,21554).
+char(c,21555).
+char(c,21556).
+char(p,21557).
+char(o,21558).
+char(m,21559).
+char(o,21560).
+char(m,21561).
+char(o,21562).
+char(o,21563).
+char(m,21564).
+char(2,21565).
+char(7,21566).
+char(1,21567).
+char(5,21568).
+char(p,21569).
+char(2,21570).
+char(3,21571).
+char(0,21572).
+char(0,21573).
+char(m,21574).
+char(8,21575).
+char(6,21576).
+char(8,21577).
+char(8,21578).
+char(m,21579).
+char(1,21580).
+char(0,21581).
+char(2,21582).
+char(4,21583).
+char(c,21584).
+char(p,21585).
+char(1,21586).
+char(2,21587).
+char(4,21588).
+char(4,21589).
+char(m,21590).
+char(1,21591).
+char(1,21592).
+char(8,21593).
+char(2,21594).
+char(c,21595).
+char(m,21596).
+char(o,21597).
+char(m,21598).
+char(1,21599).
+char(2,21600).
+char(1,21601).
+char(3,21602).
+char(c,21603).
+char(p,21604).
+char(4,21605).
+char(4,21606).
+char(0,21607).
+char(6,21608).
+char(c,21609).
+char(c,21610).
+char(c,21611).
+char(c,21612).
+char(p,21613).
+char(o,21614).
+char(m,21615).
+char(o,21616).
+char(6,21617).
+char(3,21618).
+char(7,21619).
+char(8,21620).
+char(m,21621).
+char(o,21622).
+char(o,21623).
+char(m,21624).
+char(6,21625).
+char(0,21626).
+char(1,21627).
+char(0,21628).
+char(c,21629).
+char(c,21630).
+char(m,21631).
+char(6,21632).
+char(3,21633).
+char(0,21634).
+char(9,21635).
+char(c,21636).
+char(m,21637).
+char(8,21638).
+char(2,21639).
+char(5,21640).
+char(4,21641).
+char(m,21642).
+char(5,21643).
+char(7,21644).
+char(0,21645).
+char(3,21646).
+char(c,21647).
+char(m,21648).
+char(o,21649).
+char(m,21650).
+char(6,21651).
+char(0,21652).
+char(1,21653).
+char(0,21654).
+char(c,21655).
+char(c,21656).
+char(c,21657).
+char(c,21658).
+char(m,21659).
+char(o,21660).
+char(m,21661).
+char(o,21662).
+char(p,21663).
+char(1,21664).
+char(9,21665).
+char(9,21666).
+char(6,21667).
+char(c,21668).
+char(p,21669).
+char(o,21670).
+char(m,21671).
+char(o,21672).
+char(7,21673).
+char(6,21674).
+char(5,21675).
+char(9,21676).
+char(c,21677).
+char(c,21678).
+char(p,21679).
+char(8,21680).
+char(2,21681).
+char(2,21682).
+char(9,21683).
+char(c,21684).
+char(p,21685).
+char(o,21686).
+char(p,21687).
+char(7,21688).
+char(0,21689).
+char(1,21690).
+char(0,21691).
+char(p,21692).
+char(4,21693).
+char(3,21694).
+char(9,21695).
+char(8,21696).
+char(c,21697).
+char(p,21698).
+char(o,21699).
+char(p,21700).
+char(o,21701).
+char(p,21702).
+char(o,21703).
+char(p,21704).
+char(5,21705).
+char(3,21706).
+char(4,21707).
+char(5,21708).
+char(c,21709).
+char(c,21710).
+char(c,21711).
+char(c,21712).
+char(p,21713).
+char(o,21714).
+char(m,21715).
+char(5,21716).
+char(2,21717).
+char(7,21718).
+char(8,21719).
+char(p,21720).
+char(o,21721).
+char(m,21722).
+char(5,21723).
+char(0,21724).
+char(2,21725).
+char(9,21726).
+char(p,21727).
+char(8,21728).
+char(5,21729).
+char(2,21730).
+char(4,21731).
+char(p,21732).
+char(o,21733).
+char(2,21734).
+char(9,21735).
+char(0,21736).
+char(5,21737).
+char(c,21738).
+char(m,21739).
+char(9,21740).
+char(7,21741).
+char(6,21742).
+char(9,21743).
+char(c,21744).
+char(c,21745).
+char(c,21746).
+char(c,21747).
+char(c,21748).
+char(p,21749).
+char(o,21750).
+char(1,21751).
+char(8,21752).
+char(7,21753).
+char(1,21754).
+char(c,21755).
+char(c,21756).
+char(c,21757).
+char(c,21758).
+char(c,21759).
+char(c,21760).
+char(c,21761).
+char(m,21762).
+char(3,21763).
+char(5,21764).
+char(3,21765).
+char(4,21766).
+char(c,21767).
+char(m,21768).
+char(o,21769).
+char(p,21770).
+char(9,21771).
+char(8,21772).
+char(2,21773).
+char(8,21774).
+char(c,21775).
+char(c,21776).
+char(c,21777).
+char(p,21778).
+char(5,21779).
+char(4,21780).
+char(9,21781).
+char(5,21782).
+char(c,21783).
+char(c,21784).
+char(m,21785).
+char(8,21786).
+char(5,21787).
+char(0,21788).
+char(p,21789).
+char(1,21790).
+char(5,21791).
+char(1,21792).
+char(1,21793).
+char(p,21794).
+char(o,21795).
+char(p,21796).
+char(o,21797).
+char(2,21798).
+char(6,21799).
+char(5,21800).
+char(7,21801).
+char(m,21802).
+char(o,21803).
+char(p,21804).
+char(o,21805).
+char(m,21806).
+char(o,21807).
+char(5,21808).
+char(2,21809).
+char(8,21810).
+char(0,21811).
+char(m,21812).
+char(o,21813).
+char(m,21814).
+char(2,21815).
+char(3,21816).
+char(5,21817).
+char(6,21818).
+char(c,21819).
+char(c,21820).
+char(p,21821).
+char(3,21822).
+char(7,21823).
+char(5,21824).
+char(5,21825).
+char(m,21826).
+char(8,21827).
+char(4,21828).
+char(4,21829).
+char(1,21830).
+char(c,21831).
+char(c,21832).
+char(c,21833).
+char(p,21834).
+char(o,21835).
+char(m,21836).
+char(1,21837).
+char(1,21838).
+char(1,21839).
+char(8,21840).
+char(c,21841).
+char(m,21842).
+char(9,21843).
+char(0,21844).
+char(2,21845).
+char(c,21846).
+char(c,21847).
+char(p,21848).
+char(7,21849).
+char(2,21850).
+char(5,21851).
+char(9,21852).
+char(p,21853).
+char(9,21854).
+char(2,21855).
+char(8,21856).
+char(3,21857).
+char(p,21858).
+char(2,21859).
+char(3,21860).
+char(4,21861).
+char(9,21862).
+char(c,21863).
+char(p,21864).
+char(8,21865).
+char(4,21866).
+char(4,21867).
+char(7,21868).
+char(c,21869).
+char(p,21870).
+char(o,21871).
+char(o,21872).
+char(2,21873).
+char(6,21874).
+char(8,21875).
+char(7,21876).
+char(p,21877).
+char(9,21878).
+char(4,21879).
+char(5,21880).
+char(3,21881).
+char(m,21882).
+char(8,21883).
+char(1,21884).
+char(2,21885).
+char(9,21886).
+char(m,21887).
+char(3,21888).
+char(9,21889).
+char(0,21890).
+char(0,21891).
+char(m,21892).
+char(o,21893).
+char(p,21894).
+char(o,21895).
+char(p,21896).
+char(o,21897).
+char(m,21898).
+char(o,21899).
+char(m,21900).
+char(o,21901).
+char(m,21902).
+char(3,21903).
+char(4,21904).
+char(4,21905).
+char(6,21906).
+char(p,21907).
+char(o,21908).
+char(p,21909).
+char(8,21910).
+char(3,21911).
+char(9,21912).
+char(1,21913).
+char(c,21914).
+char(p,21915).
+char(o,21916).
+char(p,21917).
+char(o,21918).
+char(3,21919).
+char(9,21920).
+char(6,21921).
+char(3,21922).
+char(p,21923).
+char(1,21924).
+char(4,21925).
+char(7,21926).
+char(4,21927).
+char(c,21928).
+char(c,21929).
+char(p,21930).
+char(o,21931).
+char(p,21932).
+char(o,21933).
+char(m,21934).
+char(o,21935).
+char(p,21936).
+char(5,21937).
+char(8,21938).
+char(3,21939).
+char(5,21940).
+char(c,21941).
+char(c,21942).
+char(p,21943).
+char(4,21944).
+char(1,21945).
+char(7,21946).
+char(8,21947).
+char(p,21948).
+char(3,21949).
+char(0,21950).
+char(8,21951).
+char(8,21952).
+char(c,21953).
+char(m,21954).
+char(o,21955).
+char(8,21956).
+char(6,21957).
+char(9,21958).
+char(9,21959).
+char(c,21960).
+char(c,21961).
+char(m,21962).
+char(3,21963).
+char(2,21964).
+char(8,21965).
+char(8,21966).
+char(c,21967).
+char(c,21968).
+char(c,21969).
+char(c,21970).
+char(c,21971).
+char(m,21972).
+char(5,21973).
+char(4,21974).
+char(5,21975).
+char(4,21976).
+char(c,21977).
+char(c,21978).
+char(c,21979).
+char(c,21980).
+char(c,21981).
+char(m,21982).
+char(1,21983).
+char(9,21984).
+char(1,21985).
+char(9,21986).
+char(p,21987).
+char(9,21988).
+char(0,21989).
+char(8,21990).
+char(0,21991).
+char(p,21992).
+char(o,21993).
+char(m,21994).
+char(9,21995).
+char(8,21996).
+char(3,21997).
+char(2,21998).
+char(p,21999).
+char(2,22000).
+char(3,22001).
+char(8,22002).
+char(c,22003).
+char(p,22004).
+char(1,22005).
+char(0,22006).
+char(5,22007).
+char(8,22008).
+char(p,22009).
+char(o,22010).
+char(m,22011).
+char(1,22012).
+char(3,22013).
+char(3,22014).
+char(6,22015).
+char(p,22016).
+char(9,22017).
+char(5,22018).
+char(8,22019).
+char(4,22020).
+char(c,22021).
+char(m,22022).
+char(1,22023).
+char(7,22024).
+char(7,22025).
+char(c,22026).
+char(p,22027).
+char(7,22028).
+char(3,22029).
+char(0,22030).
+char(0,22031).
+char(m,22032).
+char(3,22033).
+char(6,22034).
+char(1,22035).
+char(8,22036).
+char(c,22037).
+char(m,22038).
+char(o,22039).
+char(m,22040).
+char(o,22041).
+char(8,22042).
+char(6,22043).
+char(2,22044).
+char(8,22045).
+char(p,22046).
+char(o,22047).
+char(4,22048).
+char(8,22049).
+char(0,22050).
+char(6,22051).
+char(m,22052).
+char(o,22053).
+char(p,22054).
+char(8,22055).
+char(7,22056).
+char(8,22057).
+char(8,22058).
+char(p,22059).
+char(6,22060).
+char(3,22061).
+char(0,22062).
+char(4,22063).
+char(c,22064).
+char(c,22065).
+char(c,22066).
+char(c,22067).
+char(c,22068).
+char(c,22069).
+char(p,22070).
+char(o,22071).
+char(p,22072).
+char(o,22073).
+char(p,22074).
+char(1,22075).
+char(4,22076).
+char(1,22077).
+char(1,22078).
+char(c,22079).
+char(c,22080).
+char(m,22081).
+char(1,22082).
+char(6,22083).
+char(5,22084).
+char(1,22085).
+char(m,22086).
+char(9,22087).
+char(6,22088).
+char(6,22089).
+char(9,22090).
+char(c,22091).
+char(m,22092).
+char(9,22093).
+char(8,22094).
+char(9,22095).
+char(5,22096).
+char(p,22097).
+char(1,22098).
+char(2,22099).
+char(9,22100).
+char(2,22101).
+char(c,22102).
+char(p,22103).
+char(1,22104).
+char(6,22105).
+char(8,22106).
+char(c,22107).
+char(c,22108).
+char(c,22109).
+char(m,22110).
+char(o,22111).
+char(o,22112).
+char(p,22113).
+char(o,22114).
+char(m,22115).
+char(o,22116).
+char(p,22117).
+char(o,22118).
+char(m,22119).
+char(9,22120).
+char(9,22121).
+char(6,22122).
+char(6,22123).
+char(c,22124).
+char(c,22125).
+char(c,22126).
+char(c,22127).
+char(c,22128).
+char(p,22129).
+char(2,22130).
+char(6,22131).
+char(4,22132).
+char(0,22133).
+char(m,22134).
+char(4,22135).
+char(4,22136).
+char(0,22137).
+char(5,22138).
+char(c,22139).
+char(c,22140).
+char(c,22141).
+char(p,22142).
+char(o,22143).
+char(m,22144).
+char(8,22145).
+char(0,22146).
+char(1,22147).
+char(5,22148).
+char(c,22149).
+char(c,22150).
+char(p,22151).
+char(o,22152).
+char(m,22153).
+char(5,22154).
+char(6,22155).
+char(5,22156).
+char(m,22157).
+char(o,22158).
+char(p,22159).
+char(o,22160).
+char(m,22161).
+char(o,22162).
+char(m,22163).
+char(o,22164).
+char(m,22165).
+char(1,22166).
+char(9,22167).
+char(1,22168).
+char(4,22169).
+char(c,22170).
+char(m,22171).
+char(o,22172).
+char(o,22173).
+char(p,22174).
+char(4,22175).
+char(4,22176).
+char(6,22177).
+char(4,22178).
+char(p,22179).
+char(o,22180).
+char(p,22181).
+char(o,22182).
+char(o,22183).
+char(o,22184).
+char(p,22185).
+char(o,22186).
+char(m,22187).
+char(7,22188).
+char(3,22189).
+char(7,22190).
+char(1,22191).
+char(p,22192).
+char(5,22193).
+char(7,22194).
+char(8,22195).
+char(3,22196).
+char(c,22197).
+char(p,22198).
+char(3,22199).
+char(9,22200).
+char(9,22201).
+char(c,22202).
+char(c,22203).
+char(m,22204).
+char(7,22205).
+char(1,22206).
+char(2,22207).
+char(5,22208).
+char(c,22209).
+char(m,22210).
+char(4,22211).
+char(3,22212).
+char(4,22213).
+char(6,22214).
+char(c,22215).
+char(c,22216).
+char(m,22217).
+char(6,22218).
+char(3,22219).
+char(5,22220).
+char(6,22221).
+char(c,22222).
+char(c,22223).
+char(m,22224).
+char(o,22225).
+char(o,22226).
+char(o,22227).
+char(p,22228).
+char(o,22229).
+char(m,22230).
+char(7,22231).
+char(3,22232).
+char(3,22233).
+char(m,22234).
+char(6,22235).
+char(9,22236).
+char(5,22237).
+char(9,22238).
+char(m,22239).
+char(o,22240).
+char(m,22241).
+char(6,22242).
+char(9,22243).
+char(6,22244).
+char(5,22245).
+char(c,22246).
+char(c,22247).
+char(m,22248).
+char(8,22249).
+char(8,22250).
+char(3,22251).
+char(4,22252).
+char(c,22253).
+char(c,22254).
+char(c,22255).
+char(p,22256).
+char(1,22257).
+char(1,22258).
+char(9,22259).
+char(4,22260).
+char(c,22261).
+char(p,22262).
+char(8,22263).
+char(4,22264).
+char(0,22265).
+char(5,22266).
+char(p,22267).
+char(2,22268).
+char(2,22269).
+char(3,22270).
+char(0,22271).
+char(c,22272).
+char(c,22273).
+char(c,22274).
+char(c,22275).
+char(p,22276).
+char(o,22277).
+char(p,22278).
+char(3,22279).
+char(2,22280).
+char(3,22281).
+char(9,22282).
+char(m,22283).
+char(o,22284).
+char(p,22285).
+char(o,22286).
+char(m,22287).
+char(4,22288).
+char(7,22289).
+char(5,22290).
+char(2,22291).
+char(p,22292).
+char(7,22293).
+char(3,22294).
+char(7,22295).
+char(6,22296).
+char(c,22297).
+char(m,22298).
+char(8,22299).
+char(6,22300).
+char(7,22301).
+char(6,22302).
+char(c,22303).
+char(c,22304).
+char(p,22305).
+char(o,22306).
+char(m,22307).
+char(7,22308).
+char(5,22309).
+char(0,22310).
+char(2,22311).
+char(p,22312).
+char(6,22313).
+char(6,22314).
+char(5,22315).
+char(p,22316).
+char(1,22317).
+char(7,22318).
+char(2,22319).
+char(0,22320).
+char(c,22321).
+char(m,22322).
+char(2,22323).
+char(0,22324).
+char(7,22325).
+char(7,22326).
+char(m,22327).
+char(o,22328).
+char(4,22329).
+char(6,22330).
+char(3,22331).
+char(0,22332).
+char(c,22333).
+char(m,22334).
+char(4,22335).
+char(2,22336).
+char(2,22337).
+char(7,22338).
+char(m,22339).
+char(4,22340).
+char(9,22341).
+char(2,22342).
+char(6,22343).
+char(p,22344).
+char(6,22345).
+char(9,22346).
+char(0,22347).
+char(6,22348).
+char(p,22349).
+char(o,22350).
+char(o,22351).
+char(m,22352).
+char(o,22353).
+char(p,22354).
+char(3,22355).
+char(8,22356).
+char(3,22357).
+char(2,22358).
+char(m,22359).
+char(1,22360).
+char(0,22361).
+char(1,22362).
+char(2,22363).
+char(p,22364).
+char(o,22365).
+char(9,22366).
+char(1,22367).
+char(1,22368).
+char(0,22369).
+char(c,22370).
+char(c,22371).
+char(m,22372).
+char(o,22373).
+char(p,22374).
+char(7,22375).
+char(6,22376).
+char(1,22377).
+char(2,22378).
+char(p,22379).
+char(o,22380).
+char(m,22381).
+char(3,22382).
+char(7,22383).
+char(3,22384).
+char(1,22385).
+char(c,22386).
+char(c,22387).
+char(c,22388).
+char(c,22389).
+char(c,22390).
+char(c,22391).
+char(p,22392).
+char(o,22393).
+char(p,22394).
+char(o,22395).
+char(p,22396).
+char(o,22397).
+char(p,22398).
+char(8,22399).
+char(5,22400).
+char(6,22401).
+char(1,22402).
+char(c,22403).
+char(c,22404).
+char(c,22405).
+char(c,22406).
+char(m,22407).
+char(o,22408).
+char(p,22409).
+char(1,22410).
+char(3,22411).
+char(8,22412).
+char(6,22413).
+char(p,22414).
+char(o,22415).
+char(p,22416).
+char(2,22417).
+char(5,22418).
+char(1,22419).
+char(5,22420).
+char(m,22421).
+char(1,22422).
+char(9,22423).
+char(0,22424).
+char(c,22425).
+char(c,22426).
+char(c,22427).
+char(p,22428).
+char(o,22429).
+char(p,22430).
+char(1,22431).
+char(0,22432).
+char(4,22433).
+char(c,22434).
+char(p,22435).
+char(o,22436).
+char(m,22437).
+char(3,22438).
+char(2,22439).
+char(5,22440).
+char(3,22441).
+char(m,22442).
+char(o,22443).
+char(p,22444).
+char(o,22445).
+char(m,22446).
+char(9,22447).
+char(4,22448).
+char(9,22449).
+char(1,22450).
+char(m,22451).
+char(o,22452).
+char(m,22453).
+char(8,22454).
+char(8,22455).
+char(3,22456).
+char(6,22457).
+char(c,22458).
+char(c,22459).
+char(c,22460).
+char(p,22461).
+char(7,22462).
+char(0,22463).
+char(1,22464).
+char(2,22465).
+char(p,22466).
+char(9,22467).
+char(9,22468).
+char(7,22469).
+char(2,22470).
+char(p,22471).
+char(9,22472).
+char(1,22473).
+char(1,22474).
+char(1,22475).
+char(c,22476).
+char(c,22477).
+char(c,22478).
+char(p,22479).
+char(8,22480).
+char(1,22481).
+char(9,22482).
+char(3,22483).
+char(p,22484).
+char(5,22485).
+char(1,22486).
+char(9,22487).
+char(c,22488).
+char(p,22489).
+char(7,22490).
+char(7,22491).
+char(4,22492).
+char(3,22493).
+char(p,22494).
+char(o,22495).
+char(p,22496).
+char(9,22497).
+char(3,22498).
+char(2,22499).
+char(7,22500).
+char(c,22501).
+char(c,22502).
+char(p,22503).
+char(9,22504).
+char(9,22505).
+char(3,22506).
+char(p,22507).
+char(o,22508).
+char(9,22509).
+char(1,22510).
+char(7,22511).
+char(9,22512).
+char(c,22513).
+char(p,22514).
+char(o,22515).
+char(o,22516).
+char(2,22517).
+char(6,22518).
+char(7,22519).
+char(8,22520).
+char(c,22521).
+char(p,22522).
+char(o,22523).
+char(p,22524).
+char(o,22525).
+char(p,22526).
+char(o,22527).
+char(4,22528).
+char(5,22529).
+char(6,22530).
+char(4,22531).
+char(p,22532).
+char(7,22533).
+char(7,22534).
+char(1,22535).
+char(4,22536).
+char(m,22537).
+char(8,22538).
+char(5,22539).
+char(0,22540).
+char(5,22541).
+char(c,22542).
+char(c,22543).
+char(c,22544).
+char(c,22545).
+char(m,22546).
+char(4,22547).
+char(3,22548).
+char(1,22549).
+char(4,22550).
+char(m,22551).
+char(o,22552).
+char(8,22553).
+char(1,22554).
+char(2,22555).
+char(6,22556).
+char(p,22557).
+char(o,22558).
+char(p,22559).
+char(3,22560).
+char(3,22561).
+char(8,22562).
+char(7,22563).
+char(p,22564).
+char(6,22565).
+char(8,22566).
+char(4,22567).
+char(3,22568).
+char(m,22569).
+char(5,22570).
+char(5,22571).
+char(2,22572).
+char(5,22573).
+char(p,22574).
+char(o,22575).
+char(m,22576).
+char(5,22577).
+char(8,22578).
+char(3,22579).
+char(2,22580).
+char(m,22581).
+char(6,22582).
+char(5,22583).
+char(0,22584).
+char(0,22585).
+char(c,22586).
+char(c,22587).
+char(c,22588).
+char(p,22589).
+char(1,22590).
+char(9,22591).
+char(6,22592).
+char(3,22593).
+char(p,22594).
+char(4,22595).
+char(6,22596).
+char(9,22597).
+char(0,22598).
+char(c,22599).
+char(c,22600).
+char(p,22601).
+char(o,22602).
+char(m,22603).
+char(o,22604).
+char(p,22605).
+char(o,22606).
+char(p,22607).
+char(6,22608).
+char(3,22609).
+char(6,22610).
+char(2,22611).
+char(p,22612).
+char(o,22613).
+char(p,22614).
+char(o,22615).
+char(m,22616).
+char(o,22617).
+char(p,22618).
+char(o,22619).
+char(8,22620).
+char(9,22621).
+char(0,22622).
+char(2,22623).
+char(m,22624).
+char(o,22625).
+char(p,22626).
+char(4,22627).
+char(7,22628).
+char(2,22629).
+char(5,22630).
+char(p,22631).
+char(8,22632).
+char(1,22633).
+char(6,22634).
+char(5,22635).
+char(c,22636).
+char(p,22637).
+char(o,22638).
+char(4,22639).
+char(8,22640).
+char(6,22641).
+char(9,22642).
+char(c,22643).
+char(p,22644).
+char(o,22645).
+char(o,22646).
+char(p,22647).
+char(o,22648).
+char(5,22649).
+char(6,22650).
+char(9,22651).
+char(c,22652).
+char(p,22653).
+char(o,22654).
+char(m,22655).
+char(5,22656).
+char(2,22657).
+char(0,22658).
+char(0,22659).
+char(c,22660).
+char(c,22661).
+char(m,22662).
+char(3,22663).
+char(2,22664).
+char(3,22665).
+char(9,22666).
+char(m,22667).
+char(2,22668).
+char(7,22669).
+char(6,22670).
+char(5,22671).
+char(m,22672).
+char(o,22673).
+char(p,22674).
+char(o,22675).
+char(p,22676).
+char(o,22677).
+char(m,22678).
+char(5,22679).
+char(4,22680).
+char(3,22681).
+char(5,22682).
+char(c,22683).
+char(c,22684).
+char(c,22685).
+char(m,22686).
+char(o,22687).
+char(m,22688).
+char(4,22689).
+char(6,22690).
+char(6,22691).
+char(4,22692).
+char(c,22693).
+char(c,22694).
+char(c,22695).
+char(c,22696).
+char(m,22697).
+char(o,22698).
+char(o,22699).
+char(m,22700).
+char(8,22701).
+char(2,22702).
+char(5,22703).
+char(8,22704).
+char(c,22705).
+char(c,22706).
+char(m,22707).
+char(9,22708).
+char(8,22709).
+char(5,22710).
+char(3,22711).
+char(p,22712).
+char(o,22713).
+char(m,22714).
+char(8,22715).
+char(1,22716).
+char(7,22717).
+char(m,22718).
+char(4,22719).
+char(1,22720).
+char(5,22721).
+char(7,22722).
+char(p,22723).
+char(o,22724).
+char(m,22725).
+char(o,22726).
+char(p,22727).
+char(o,22728).
+char(m,22729).
+char(8,22730).
+char(7,22731).
+char(6,22732).
+char(1,22733).
+char(p,22734).
+char(o,22735).
+char(o,22736).
+char(p,22737).
+char(4,22738).
+char(1,22739).
+char(0,22740).
+char(5,22741).
+char(c,22742).
+char(c,22743).
+char(m,22744).
+char(1,22745).
+char(5,22746).
+char(5,22747).
+char(4,22748).
+char(m,22749).
+char(o,22750).
+char(p,22751).
+char(o,22752).
+char(o,22753).
+char(p,22754).
+char(8,22755).
+char(1,22756).
+char(3,22757).
+char(5,22758).
+char(p,22759).
+char(2,22760).
+char(1,22761).
+char(2,22762).
+char(8,22763).
+char(p,22764).
+char(1,22765).
+char(0,22766).
+char(8,22767).
+char(7,22768).
+char(c,22769).
+char(c,22770).
+char(c,22771).
+char(m,22772).
+char(o,22773).
+char(m,22774).
+char(o,22775).
+char(6,22776).
+char(0,22777).
+char(3,22778).
+char(1,22779).
+char(c,22780).
+char(p,22781).
+char(o,22782).
+char(m,22783).
+char(o,22784).
+char(p,22785).
+char(o,22786).
+char(m,22787).
+char(o,22788).
+char(p,22789).
+char(o,22790).
+char(p,22791).
+char(7,22792).
+char(3,22793).
+char(0,22794).
+char(4,22795).
+char(p,22796).
+char(o,22797).
+char(o,22798).
+char(6,22799).
+char(8,22800).
+char(3,22801).
+char(1,22802).
+char(p,22803).
+char(o,22804).
+char(5,22805).
+char(1,22806).
+char(9,22807).
+char(c,22808).
+char(p,22809).
+char(o,22810).
+char(p,22811).
+char(o,22812).
+char(m,22813).
+char(7,22814).
+char(4,22815).
+char(2,22816).
+char(8,22817).
+char(c,22818).
+char(m,22819).
+char(4,22820).
+char(7,22821).
+char(8,22822).
+char(5,22823).
+char(p,22824).
+char(o,22825).
+char(m,22826).
+char(o,22827).
+char(p,22828).
+char(o,22829).
+char(p,22830).
+char(4,22831).
+char(5,22832).
+char(4,22833).
+char(0,22834).
+char(c,22835).
+char(c,22836).
+char(m,22837).
+char(o,22838).
+char(p,22839).
+char(9,22840).
+char(5,22841).
+char(1,22842).
+char(p,22843).
+char(7,22844).
+char(1,22845).
+char(0,22846).
+char(6,22847).
+char(c,22848).
+char(c,22849).
+char(m,22850).
+char(3,22851).
+char(9,22852).
+char(7,22853).
+char(6,22854).
+char(c,22855).
+char(m,22856).
+char(1,22857).
+char(8,22858).
+char(8,22859).
+char(0,22860).
+char(c,22861).
+char(c,22862).
+char(c,22863).
+char(m,22864).
+char(o,22865).
+char(p,22866).
+char(8,22867).
+char(3,22868).
+char(3,22869).
+char(5,22870).
+char(m,22871).
+char(o,22872).
+char(o,22873).
+char(m,22874).
+char(o,22875).
+char(m,22876).
+char(2,22877).
+char(9,22878).
+char(6,22879).
+char(3,22880).
+char(c,22881).
+char(c,22882).
+char(c,22883).
+char(c,22884).
+char(p,22885).
+char(4,22886).
+char(2,22887).
+char(7,22888).
+char(1,22889).
+char(c,22890).
+char(c,22891).
+char(p,22892).
+char(o,22893).
+char(m,22894).
+char(6,22895).
+char(7,22896).
+char(2,22897).
+char(8,22898).
+char(c,22899).
+char(c,22900).
+char(m,22901).
+char(o,22902).
+char(p,22903).
+char(o,22904).
+char(m,22905).
+char(o,22906).
+char(p,22907).
+char(1,22908).
+char(8,22909).
+char(8,22910).
+char(m,22911).
+char(o,22912).
+char(p,22913).
+char(o,22914).
+char(p,22915).
+char(o,22916).
+char(o,22917).
+char(8,22918).
+char(2,22919).
+char(5,22920).
+char(9,22921).
+char(p,22922).
+char(o,22923).
+char(p,22924).
+char(o,22925).
+char(m,22926).
+char(o,22927).
+char(o,22928).
+char(m,22929).
+char(9,22930).
+char(4,22931).
+char(6,22932).
+char(7,22933).
+char(c,22934).
+char(m,22935).
+char(o,22936).
+char(p,22937).
+char(5,22938).
+char(9,22939).
+char(5,22940).
+char(5,22941).
+char(c,22942).
+char(p,22943).
+char(o,22944).
+char(m,22945).
+char(2,22946).
+char(1,22947).
+char(4,22948).
+char(6,22949).
+char(c,22950).
+char(p,22951).
+char(9,22952).
+char(5,22953).
+char(5,22954).
+char(6,22955).
+char(c,22956).
+char(p,22957).
+char(o,22958).
+char(p,22959).
+char(6,22960).
+char(3,22961).
+char(5,22962).
+char(8,22963).
+char(p,22964).
+char(o,22965).
+char(o,22966).
+char(p,22967).
+char(8,22968).
+char(5,22969).
+char(4,22970).
+char(p,22971).
+char(4,22972).
+char(1,22973).
+char(2,22974).
+char(0,22975).
+char(c,22976).
+char(m,22977).
+char(o,22978).
+char(m,22979).
+char(o,22980).
+char(p,22981).
+char(o,22982).
+char(m,22983).
+char(1,22984).
+char(1,22985).
+char(4,22986).
+char(1,22987).
+char(p,22988).
+char(4,22989).
+char(6,22990).
+char(5,22991).
+char(4,22992).
+char(c,22993).
+char(c,22994).
+char(p,22995).
+char(3,22996).
+char(4,22997).
+char(4,22998).
+char(6,22999).
+char(p,23000).
+char(7,23001).
+char(9,23002).
+char(0,23003).
+char(6,23004).
+char(m,23005).
+char(4,23006).
+char(6,23007).
+char(9,23008).
+char(6,23009).
+char(c,23010).
+char(m,23011).
+char(o,23012).
+char(p,23013).
+char(6,23014).
+char(6,23015).
+char(0,23016).
+char(5,23017).
+char(m,23018).
+char(o,23019).
+char(o,23020).
+char(o,23021).
+char(m,23022).
+char(o,23023).
+char(m,23024).
+char(o,23025).
+char(p,23026).
+char(8,23027).
+char(2,23028).
+char(3,23029).
+char(9,23030).
+char(c,23031).
+char(c,23032).
+char(p,23033).
+char(o,23034).
+char(o,23035).
+char(p,23036).
+char(6,23037).
+char(9,23038).
+char(1,23039).
+char(9,23040).
+char(m,23041).
+char(6,23042).
+char(3,23043).
+char(3,23044).
+char(7,23045).
+char(m,23046).
+char(7,23047).
+char(7,23048).
+char(9,23049).
+char(8,23050).
+char(c,23051).
+char(m,23052).
+char(3,23053).
+char(0,23054).
+char(0,23055).
+char(5,23056).
+char(c,23057).
+char(p,23058).
+char(o,23059).
+char(m,23060).
+char(1,23061).
+char(0,23062).
+char(4,23063).
+char(3,23064).
+char(c,23065).
+char(c,23066).
+char(m,23067).
+char(7,23068).
+char(1,23069).
+char(2,23070).
+char(2,23071).
+char(c,23072).
+char(c,23073).
+char(c,23074).
+char(p,23075).
+char(o,23076).
+char(p,23077).
+char(2,23078).
+char(6,23079).
+char(0,23080).
+char(4,23081).
+char(p,23082).
+char(5,23083).
+char(3,23084).
+char(5,23085).
+char(1,23086).
+char(m,23087).
+char(3,23088).
+char(5,23089).
+char(4,23090).
+char(8,23091).
+char(c,23092).
+char(p,23093).
+char(o,23094).
+char(o,23095).
+char(p,23096).
+char(6,23097).
+char(1,23098).
+char(8,23099).
+char(0,23100).
+char(c,23101).
+char(p,23102).
+char(9,23103).
+char(6,23104).
+char(8,23105).
+char(2,23106).
+char(c,23107).
+char(p,23108).
+char(o,23109).
+char(p,23110).
+char(1,23111).
+char(2,23112).
+char(8,23113).
+char(0,23114).
+char(m,23115).
+char(o,23116).
+char(m,23117).
+char(o,23118).
+char(p,23119).
+char(o,23120).
+char(o,23121).
+char(m,23122).
+char(o,23123).
+char(2,23124).
+char(3,23125).
+char(5,23126).
+char(5,23127).
+char(m,23128).
+char(o,23129).
+char(m,23130).
+char(o,23131).
+char(p,23132).
+char(5,23133).
+char(6,23134).
+char(2,23135).
+char(4,23136).
+char(p,23137).
+char(3,23138).
+char(5,23139).
+char(4,23140).
+char(5,23141).
+char(m,23142).
+char(o,23143).
+char(o,23144).
+char(m,23145).
+char(o,23146).
+char(p,23147).
+char(o,23148).
+char(p,23149).
+char(3,23150).
+char(8,23151).
+char(7,23152).
+char(8,23153).
+char(c,23154).
+char(m,23155).
+char(o,23156).
+char(o,23157).
+char(m,23158).
+char(o,23159).
+char(o,23160).
+char(o,23161).
+char(m,23162).
+char(o,23163).
+char(8,23164).
+char(7,23165).
+char(3,23166).
+char(7,23167).
+char(c,23168).
+char(c,23169).
+char(p,23170).
+char(o,23171).
+char(m,23172).
+char(o,23173).
+char(7,23174).
+char(8,23175).
+char(7,23176).
+char(1,23177).
+char(m,23178).
+char(4,23179).
+char(4,23180).
+char(6,23181).
+char(m,23182).
+char(o,23183).
+char(p,23184).
+char(o,23185).
+char(1,23186).
+char(2,23187).
+char(8,23188).
+char(6,23189).
+char(c,23190).
+char(c,23191).
+char(p,23192).
+char(9,23193).
+char(1,23194).
+char(3,23195).
+char(4,23196).
+char(c,23197).
+char(p,23198).
+char(9,23199).
+char(2,23200).
+char(7,23201).
+char(0,23202).
+char(c,23203).
+char(m,23204).
+char(o,23205).
+char(6,23206).
+char(7,23207).
+char(6,23208).
+char(m,23209).
+char(3,23210).
+char(8,23211).
+char(3,23212).
+char(1,23213).
+char(m,23214).
+char(2,23215).
+char(0,23216).
+char(4,23217).
+char(7,23218).
+char(m,23219).
+char(o,23220).
+char(p,23221).
+char(o,23222).
+char(p,23223).
+char(5,23224).
+char(7,23225).
+char(8,23226).
+char(5,23227).
+char(c,23228).
+char(m,23229).
+char(o,23230).
+char(m,23231).
+char(o,23232).
+char(p,23233).
+char(o,23234).
+char(m,23235).
+char(o,23236).
+char(p,23237).
+char(o,23238).
+char(3,23239).
+char(2,23240).
+char(6,23241).
+char(m,23242).
+char(5,23243).
+char(4,23244).
+char(8,23245).
+char(3,23246).
+char(c,23247).
+char(m,23248).
+char(7,23249).
+char(0,23250).
+char(8,23251).
+char(0,23252).
+char(c,23253).
+char(p,23254).
+char(8,23255).
+char(5,23256).
+char(8,23257).
+char(7,23258).
+char(c,23259).
+char(c,23260).
+char(m,23261).
+char(4,23262).
+char(7,23263).
+char(3,23264).
+char(8,23265).
+char(c,23266).
+char(p,23267).
+char(o,23268).
+char(m,23269).
+char(o,23270).
+char(p,23271).
+char(o,23272).
+char(1,23273).
+char(4,23274).
+char(6,23275).
+char(p,23276).
+char(4,23277).
+char(1,23278).
+char(2,23279).
+char(4,23280).
+char(c,23281).
+char(c,23282).
+char(c,23283).
+char(m,23284).
+char(1,23285).
+char(8,23286).
+char(0,23287).
+char(3,23288).
+char(c,23289).
+char(c,23290).
+char(p,23291).
+char(o,23292).
+char(p,23293).
+char(5,23294).
+char(4,23295).
+char(3,23296).
+char(8,23297).
+char(c,23298).
+char(m,23299).
+char(o,23300).
+char(m,23301).
+char(8,23302).
+char(6,23303).
+char(0,23304).
+char(6,23305).
+char(c,23306).
+char(p,23307).
+char(o,23308).
+char(p,23309).
+char(1,23310).
+char(0,23311).
+char(0,23312).
+char(0,23313).
+char(c,23314).
+char(p,23315).
+char(9,23316).
+char(2,23317).
+char(9,23318).
+char(2,23319).
+char(p,23320).
+char(4,23321).
+char(6,23322).
+char(4,23323).
+char(8,23324).
+char(m,23325).
+char(4,23326).
+char(2,23327).
+char(3,23328).
+char(9,23329).
+char(p,23330).
+char(o,23331).
+char(o,23332).
+char(p,23333).
+char(o,23334).
+char(p,23335).
+char(2,23336).
+char(2,23337).
+char(6,23338).
+char(6,23339).
+char(c,23340).
+char(c,23341).
+char(m,23342).
+char(7,23343).
+char(1,23344).
+char(8,23345).
+char(2,23346).
+char(p,23347).
+char(o,23348).
+char(m,23349).
+char(o,23350).
+char(m,23351).
+char(5,23352).
+char(9,23353).
+char(7,23354).
+char(7,23355).
+char(c,23356).
+char(c,23357).
+char(c,23358).
+char(p,23359).
+char(8,23360).
+char(6,23361).
+char(8,23362).
+char(8,23363).
+char(c,23364).
+char(p,23365).
+char(o,23366).
+char(o,23367).
+char(m,23368).
+char(9,23369).
+char(7,23370).
+char(7,23371).
+char(5,23372).
+char(p,23373).
+char(8,23374).
+char(3,23375).
+char(8,23376).
+char(1,23377).
+char(m,23378).
+char(o,23379).
+char(m,23380).
+char(2,23381).
+char(8,23382).
+char(2,23383).
+char(5,23384).
+char(p,23385).
+char(2,23386).
+char(5,23387).
+char(1,23388).
+char(2,23389).
+char(c,23390).
+char(p,23391).
+char(7,23392).
+char(4,23393).
+char(9,23394).
+char(6,23395).
+char(c,23396).
+char(p,23397).
+char(o,23398).
+char(4,23399).
+char(6,23400).
+char(2,23401).
+char(2,23402).
+char(c,23403).
+char(c,23404).
+char(m,23405).
+char(8,23406).
+char(1,23407).
+char(1,23408).
+char(3,23409).
+char(c,23410).
+char(c,23411).
+char(p,23412).
+char(o,23413).
+char(o,23414).
+char(m,23415).
+char(4,23416).
+char(6,23417).
+char(2,23418).
+char(8,23419).
+char(c,23420).
+char(c,23421).
+char(p,23422).
+char(o,23423).
+char(p,23424).
+char(5,23425).
+char(5,23426).
+char(8,23427).
+char(3,23428).
+char(m,23429).
+char(o,23430).
+char(m,23431).
+char(2,23432).
+char(1,23433).
+char(3,23434).
+char(0,23435).
+char(c,23436).
+char(m,23437).
+char(o,23438).
+char(o,23439).
+char(o,23440).
+char(o,23441).
+char(8,23442).
+char(1,23443).
+char(1,23444).
+char(5,23445).
+char(p,23446).
+char(o,23447).
+char(p,23448).
+char(o,23449).
+char(m,23450).
+char(o,23451).
+char(3,23452).
+char(0,23453).
+char(9,23454).
+char(7,23455).
+char(m,23456).
+char(1,23457).
+char(1,23458).
+char(8,23459).
+char(3,23460).
+char(m,23461).
+char(9,23462).
+char(4,23463).
+char(6,23464).
+char(4,23465).
+char(p,23466).
+char(5,23467).
+char(2,23468).
+char(8,23469).
+char(7,23470).
+char(c,23471).
+char(c,23472).
+char(c,23473).
+char(c,23474).
+char(p,23475).
+char(7,23476).
+char(3,23477).
+char(5,23478).
+char(8,23479).
+char(c,23480).
+char(p,23481).
+char(o,23482).
+char(o,23483).
+char(m,23484).
+char(7,23485).
+char(2,23486).
+char(6,23487).
+char(3,23488).
+char(c,23489).
+char(c,23490).
+char(p,23491).
+char(9,23492).
+char(5,23493).
+char(3,23494).
+char(2,23495).
+char(p,23496).
+char(o,23497).
+char(1,23498).
+char(1,23499).
+char(2,23500).
+char(2,23501).
+char(p,23502).
+char(o,23503).
+char(p,23504).
+char(o,23505).
+char(o,23506).
+char(p,23507).
+char(9,23508).
+char(7,23509).
+char(9,23510).
+char(6,23511).
+char(c,23512).
+char(c,23513).
+char(c,23514).
+char(c,23515).
+char(c,23516).
+char(p,23517).
+char(o,23518).
+char(m,23519).
+char(o,23520).
+char(p,23521).
+char(4,23522).
+char(0,23523).
+char(0,23524).
+char(9,23525).
+char(p,23526).
+char(o,23527).
+char(5,23528).
+char(5,23529).
+char(5,23530).
+char(3,23531).
+char(p,23532).
+char(o,23533).
+char(p,23534).
+char(1,23535).
+char(4,23536).
+char(0,23537).
+char(c,23538).
+char(m,23539).
+char(o,23540).
+char(o,23541).
+char(o,23542).
+char(m,23543).
+char(3,23544).
+char(0,23545).
+char(1,23546).
+char(4,23547).
+char(c,23548).
+char(c,23549).
+char(m,23550).
+char(6,23551).
+char(8,23552).
+char(9,23553).
+char(1,23554).
+char(c,23555).
+char(m,23556).
+char(9,23557).
+char(3,23558).
+char(4,23559).
+char(6,23560).
+char(c,23561).
+char(c,23562).
+char(c,23563).
+char(m,23564).
+char(o,23565).
+char(m,23566).
+char(o,23567).
+char(o,23568).
+char(o,23569).
+char(p,23570).
+char(5,23571).
+char(3,23572).
+char(5,23573).
+char(3,23574).
+char(c,23575).
+char(c,23576).
+char(c,23577).
+char(p,23578).
+char(5,23579).
+char(7,23580).
+char(4,23581).
+char(3,23582).
+char(m,23583).
+char(o,23584).
+char(p,23585).
+char(o,23586).
+char(m,23587).
+char(2,23588).
+char(5,23589).
+char(c,23590).
+char(p,23591).
+char(6,23592).
+char(5,23593).
+char(1,23594).
+char(8,23595).
+char(p,23596).
+char(6,23597).
+char(2,23598).
+char(7,23599).
+char(0,23600).
+char(c,23601).
+char(c,23602).
+char(c,23603).
+char(m,23604).
+char(o,23605).
+char(m,23606).
+char(4,23607).
+char(9,23608).
+char(7,23609).
+char(5,23610).
+char(c,23611).
+char(m,23612).
+char(4,23613).
+char(5,23614).
+char(1,23615).
+char(9,23616).
+char(c,23617).
+char(p,23618).
+char(5,23619).
+char(4,23620).
+char(3,23621).
+char(1,23622).
+char(c,23623).
+char(m,23624).
+char(o,23625).
+char(9,23626).
+char(8,23627).
+char(9,23628).
+char(1,23629).
+char(c,23630).
+char(c,23631).
+char(p,23632).
+char(3,23633).
+char(9,23634).
+char(3,23635).
+char(8,23636).
+char(p,23637).
+char(5,23638).
+char(9,23639).
+char(8,23640).
+char(3,23641).
+char(c,23642).
+char(c,23643).
+char(c,23644).
+char(c,23645).
+char(p,23646).
+char(o,23647).
+char(p,23648).
+char(o,23649).
+char(p,23650).
+char(o,23651).
+char(o,23652).
+char(m,23653).
+char(o,23654).
+char(o,23655).
+char(1,23656).
+char(6,23657).
+char(7,23658).
+char(0,23659).
+char(p,23660).
+char(o,23661).
+char(8,23662).
+char(2,23663).
+char(0,23664).
+char(0,23665).
+char(c,23666).
+char(c,23667).
+char(p,23668).
+char(o,23669).
+char(p,23670).
+char(1,23671).
+char(7,23672).
+char(3,23673).
+char(7,23674).
+char(c,23675).
+char(p,23676).
+char(9,23677).
+char(8,23678).
+char(0,23679).
+char(0,23680).
+char(p,23681).
+char(o,23682).
+char(2,23683).
+char(2,23684).
+char(3,23685).
+char(2,23686).
+char(c,23687).
+char(c,23688).
+char(p,23689).
+char(9,23690).
+char(9,23691).
+char(5,23692).
+char(2,23693).
+char(c,23694).
+char(p,23695).
+char(o,23696).
+char(m,23697).
+char(o,23698).
+char(p,23699).
+char(3,23700).
+char(3,23701).
+char(0,23702).
+char(0,23703).
+char(p,23704).
+char(o,23705).
+char(p,23706).
+char(9,23707).
+char(1,23708).
+char(5,23709).
+char(5,23710).
+char(m,23711).
+char(o,23712).
+char(o,23713).
+char(m,23714).
+char(8,23715).
+char(6,23716).
+char(8,23717).
+char(9,23718).
+char(c,23719).
+char(c,23720).
+char(c,23721).
+char(c,23722).
+char(m,23723).
+char(7,23724).
+char(9,23725).
+char(6,23726).
+char(9,23727).
+char(c,23728).
+char(c,23729).
+char(c,23730).
+char(m,23731).
+char(o,23732).
+char(p,23733).
+char(o,23734).
+char(m,23735).
+char(7,23736).
+char(3,23737).
+char(4,23738).
+char(4,23739).
+char(p,23740).
+char(9,23741).
+char(1,23742).
+char(2,23743).
+char(3,23744).
+char(c,23745).
+char(c,23746).
+char(c,23747).
+char(m,23748).
+char(o,23749).
+char(m,23750).
+char(o,23751).
+char(m,23752).
+char(o,23753).
+char(p,23754).
+char(o,23755).
+char(9,23756).
+char(2,23757).
+char(8,23758).
+char(c,23759).
+char(p,23760).
+char(o,23761).
+char(m,23762).
+char(7,23763).
+char(1,23764).
+char(4,23765).
+char(5,23766).
+char(m,23767).
+char(6,23768).
+char(3,23769).
+char(6,23770).
+char(0,23771).
+char(p,23772).
+char(3,23773).
+char(6,23774).
+char(1,23775).
+char(0,23776).
+char(c,23777).
+char(c,23778).
+char(p,23779).
+char(o,23780).
+char(m,23781).
+char(o,23782).
+char(7,23783).
+char(4,23784).
+char(7,23785).
+char(7,23786).
+char(p,23787).
+char(2,23788).
+char(4,23789).
+char(2,23790).
+char(9,23791).
+char(c,23792).
+char(p,23793).
+char(o,23794).
+char(p,23795).
+char(o,23796).
+char(m,23797).
+char(o,23798).
+char(p,23799).
+char(o,23800).
+char(p,23801).
+char(9,23802).
+char(2,23803).
+char(8,23804).
+char(c,23805).
+char(c,23806).
+char(c,23807).
+char(c,23808).
+char(p,23809).
+char(o,23810).
+char(p,23811).
+char(o,23812).
+char(p,23813).
+char(o,23814).
+char(6,23815).
+char(0,23816).
+char(3,23817).
+char(3,23818).
+char(m,23819).
+char(o,23820).
+char(1,23821).
+char(2,23822).
+char(9,23823).
+char(7,23824).
+char(p,23825).
+char(8,23826).
+char(8,23827).
+char(2,23828).
+char(3,23829).
+char(p,23830).
+char(o,23831).
+char(1,23832).
+char(6,23833).
+char(9,23834).
+char(6,23835).
+char(p,23836).
+char(1,23837).
+char(0,23838).
+char(0,23839).
+char(0,23840).
+char(c,23841).
+char(p,23842).
+char(2,23843).
+char(3,23844).
+char(5,23845).
+char(6,23846).
+char(m,23847).
+char(o,23848).
+char(p,23849).
+char(9,23850).
+char(5,23851).
+char(6,23852).
+char(3,23853).
+char(m,23854).
+char(7,23855).
+char(9,23856).
+char(3,23857).
+char(4,23858).
+char(m,23859).
+char(1,23860).
+char(3,23861).
+char(6,23862).
+char(9,23863).
+char(c,23864).
+char(m,23865).
+char(9,23866).
+char(2,23867).
+char(8,23868).
+char(p,23869).
+char(o,23870).
+char(2,23871).
+char(9,23872).
+char(4,23873).
+char(7,23874).
+char(m,23875).
+char(7,23876).
+char(7,23877).
+char(2,23878).
+char(3,23879).
+char(c,23880).
+char(c,23881).
+char(p,23882).
+char(o,23883).
+char(m,23884).
+char(o,23885).
+char(m,23886).
+char(o,23887).
+char(o,23888).
+char(p,23889).
+char(o,23890).
+char(m,23891).
+char(5,23892).
+char(0,23893).
+char(4,23894).
+char(4,23895).
+char(c,23896).
+char(m,23897).
+char(2,23898).
+char(7,23899).
+char(3,23900).
+char(c,23901).
+char(p,23902).
+char(o,23903).
+char(o,23904).
+char(p,23905).
+char(o,23906).
+char(m,23907).
+char(o,23908).
+char(1,23909).
+char(4,23910).
+char(9,23911).
+char(1,23912).
+char(m,23913).
+char(o,23914).
+char(p,23915).
+char(5,23916).
+char(3,23917).
+char(4,23918).
+char(4,23919).
+char(p,23920).
+char(o,23921).
+char(p,23922).
+char(o,23923).
+char(8,23924).
+char(1,23925).
+char(2,23926).
+char(1,23927).
+char(c,23928).
+char(c,23929).
+char(c,23930).
+char(p,23931).
+char(8,23932).
+char(9,23933).
+char(5,23934).
+char(7,23935).
+char(c,23936).
+char(m,23937).
+char(6,23938).
+char(8,23939).
+char(1,23940).
+char(4,23941).
+char(c,23942).
+char(c,23943).
+char(p,23944).
+char(4,23945).
+char(1,23946).
+char(9,23947).
+char(0,23948).
+char(c,23949).
+char(c,23950).
+char(m,23951).
+char(8,23952).
+char(0,23953).
+char(4,23954).
+char(3,23955).
+char(p,23956).
+char(o,23957).
+char(m,23958).
+char(o,23959).
+char(m,23960).
+char(o,23961).
+char(o,23962).
+char(m,23963).
+char(6,23964).
+char(9,23965).
+char(7,23966).
+char(0,23967).
+char(c,23968).
+char(c,23969).
+char(m,23970).
+char(o,23971).
+char(p,23972).
+char(o,23973).
+char(o,23974).
+char(p,23975).
+char(1,23976).
+char(4,23977).
+char(4,23978).
+char(6,23979).
+char(c,23980).
+char(m,23981).
+char(7,23982).
+char(1,23983).
+char(5,23984).
+char(4,23985).
+char(m,23986).
+char(1,23987).
+char(5,23988).
+char(1,23989).
+char(0,23990).
+char(p,23991).
+char(9,23992).
+char(8,23993).
+char(6,23994).
+char(4,23995).
+char(c,23996).
+char(c,23997).
+char(c,23998).
+char(c,23999).
+char(p,24000).
+char(1,24001).
+char(2,24002).
+char(1,24003).
+char(m,24004).
+char(o,24005).
+char(p,24006).
+char(o,24007).
+char(p,24008).
+char(o,24009).
+char(p,24010).
+char(o,24011).
+char(o,24012).
+char(p,24013).
+char(o,24014).
+char(m,24015).
+char(2,24016).
+char(8,24017).
+char(2,24018).
+char(3,24019).
+char(m,24020).
+char(9,24021).
+char(8,24022).
+char(7,24023).
+char(4,24024).
+char(m,24025).
+char(8,24026).
+char(2,24027).
+char(9,24028).
+char(3,24029).
+char(m,24030).
+char(7,24031).
+char(8,24032).
+char(8,24033).
+char(m,24034).
+char(6,24035).
+char(5,24036).
+char(8,24037).
+char(9,24038).
+char(c,24039).
+char(c,24040).
+char(m,24041).
+char(4,24042).
+char(1,24043).
+char(7,24044).
+char(1,24045).
+char(c,24046).
+char(c,24047).
+char(c,24048).
+char(p,24049).
+char(6,24050).
+char(2,24051).
+char(7,24052).
+char(0,24053).
+char(m,24054).
+char(5,24055).
+char(5,24056).
+char(2,24057).
+char(7,24058).
+char(m,24059).
+char(o,24060).
+char(9,24061).
+char(3,24062).
+char(1,24063).
+char(2,24064).
+char(c,24065).
+char(m,24066).
+char(1,24067).
+char(7,24068).
+char(2,24069).
+char(7,24070).
+char(m,24071).
+char(o,24072).
+char(p,24073).
+char(o,24074).
+char(p,24075).
+char(o,24076).
+char(m,24077).
+char(3,24078).
+char(9,24079).
+char(0,24080).
+char(7,24081).
+char(m,24082).
+char(7,24083).
+char(1,24084).
+char(6,24085).
+char(6,24086).
+char(c,24087).
+char(p,24088).
+char(o,24089).
+char(p,24090).
+char(4,24091).
+char(2,24092).
+char(7,24093).
+char(6,24094).
+char(c,24095).
+char(c,24096).
+char(c,24097).
+char(p,24098).
+char(3,24099).
+char(9,24100).
+char(5,24101).
+char(8,24102).
+char(c,24103).
+char(c,24104).
+char(m,24105).
+char(9,24106).
+char(1,24107).
+char(1,24108).
+char(1,24109).
+char(c,24110).
+char(c,24111).
+char(m,24112).
+char(7,24113).
+char(6,24114).
+char(9,24115).
+char(4,24116).
+char(p,24117).
+char(o,24118).
+char(o,24119).
+char(m,24120).
+char(o,24121).
+char(m,24122).
+char(6,24123).
+char(6,24124).
+char(8,24125).
+char(2,24126).
+char(m,24127).
+char(o,24128).
+char(o,24129).
+char(m,24130).
+char(o,24131).
+char(p,24132).
+char(o,24133).
+char(m,24134).
+char(o,24135).
+char(p,24136).
+char(5,24137).
+char(6,24138).
+char(0,24139).
+char(6,24140).
+char(c,24141).
+char(m,24142).
+char(3,24143).
+char(8,24144).
+char(6,24145).
+char(0,24146).
+char(p,24147).
+char(o,24148).
+char(p,24149).
+char(o,24150).
+char(p,24151).
+char(4,24152).
+char(6,24153).
+char(1,24154).
+char(2,24155).
+char(c,24156).
+char(m,24157).
+char(8,24158).
+char(3,24159).
+char(0,24160).
+char(2,24161).
+char(m,24162).
+char(5,24163).
+char(3,24164).
+char(7,24165).
+char(8,24166).
+char(m,24167).
+char(7,24168).
+char(7,24169).
+char(1,24170).
+char(7,24171).
+char(m,24172).
+char(o,24173).
+char(6,24174).
+char(1,24175).
+char(1,24176).
+char(8,24177).
+char(c,24178).
+char(c,24179).
+char(p,24180).
+char(6,24181).
+char(0,24182).
+char(2,24183).
+char(4,24184).
+char(c,24185).
+char(c,24186).
+char(c,24187).
+char(c,24188).
+char(c,24189).
+char(c,24190).
+char(c,24191).
+char(m,24192).
+char(6,24193).
+char(6,24194).
+char(9,24195).
+char(8,24196).
+char(c,24197).
+char(p,24198).
+char(3,24199).
+char(5,24200).
+char(5,24201).
+char(4,24202).
+char(c,24203).
+char(c,24204).
+char(p,24205).
+char(o,24206).
+char(o,24207).
+char(o,24208).
+char(o,24209).
+char(m,24210).
+char(4,24211).
+char(2,24212).
+char(9,24213).
+char(4,24214).
+char(c,24215).
+char(p,24216).
+char(8,24217).
+char(3,24218).
+char(8,24219).
+char(6,24220).
+char(p,24221).
+char(9,24222).
+char(9,24223).
+char(4,24224).
+char(1,24225).
+char(c,24226).
+char(m,24227).
+char(7,24228).
+char(2,24229).
+char(5,24230).
+char(7,24231).
+char(p,24232).
+char(7,24233).
+char(5,24234).
+char(6,24235).
+char(1,24236).
+char(c,24237).
+char(c,24238).
+char(m,24239).
+char(o,24240).
+char(m,24241).
+char(o,24242).
+char(p,24243).
+char(o,24244).
+char(p,24245).
+char(5,24246).
+char(8,24247).
+char(0,24248).
+char(8,24249).
+char(m,24250).
+char(o,24251).
+char(o,24252).
+char(p,24253).
+char(8,24254).
+char(8,24255).
+char(0,24256).
+char(7,24257).
+char(c,24258).
+char(c,24259).
+char(m,24260).
+char(o,24261).
+char(p,24262).
+char(7,24263).
+char(5,24264).
+char(6,24265).
+char(6,24266).
+char(c,24267).
+char(p,24268).
+char(o,24269).
+char(4,24270).
+char(9,24271).
+char(7,24272).
+char(2,24273).
+char(c,24274).
+char(m,24275).
+char(o,24276).
+char(m,24277).
+char(9,24278).
+char(7,24279).
+char(3,24280).
+char(3,24281).
+char(c,24282).
+char(c,24283).
+char(m,24284).
+char(5,24285).
+char(7,24286).
+char(0,24287).
+char(7,24288).
+char(m,24289).
+char(8,24290).
+char(6,24291).
+char(3,24292).
+char(m,24293).
+char(o,24294).
+char(o,24295).
+char(1,24296).
+char(9,24297).
+char(8,24298).
+char(9,24299).
+char(c,24300).
+char(c,24301).
+char(c,24302).
+char(m,24303).
+char(5,24304).
+char(2,24305).
+char(1,24306).
+char(6,24307).
+char(p,24308).
+char(o,24309).
+char(p,24310).
+char(4,24311).
+char(6,24312).
+char(0,24313).
+char(8,24314).
+char(m,24315).
+char(o,24316).
+char(o,24317).
+char(m,24318).
+char(o,24319).
+char(p,24320).
+char(6,24321).
+char(1,24322).
+char(9,24323).
+char(6,24324).
+char(p,24325).
+char(o,24326).
+char(m,24327).
+char(2,24328).
+char(6,24329).
+char(0,24330).
+char(c,24331).
+char(c,24332).
+char(c,24333).
+char(m,24334).
+char(2,24335).
+char(3,24336).
+char(6,24337).
+char(8,24338).
+char(m,24339).
+char(o,24340).
+char(p,24341).
+char(7,24342).
+char(0,24343).
+char(9,24344).
+char(2,24345).
+char(m,24346).
+char(o,24347).
+char(p,24348).
+char(o,24349).
+char(p,24350).
+char(4,24351).
+char(2,24352).
+char(0,24353).
+char(9,24354).
+char(c,24355).
+char(c,24356).
+char(m,24357).
+char(o,24358).
+char(9,24359).
+char(0,24360).
+char(8,24361).
+char(6,24362).
+char(p,24363).
+char(o,24364).
+char(p,24365).
+char(1,24366).
+char(5,24367).
+char(4,24368).
+char(9,24369).
+char(p,24370).
+char(7,24371).
+char(1,24372).
+char(3,24373).
+char(3,24374).
+char(c,24375).
+char(m,24376).
+char(3,24377).
+char(5,24378).
+char(3,24379).
+char(1,24380).
+char(c,24381).
+char(c,24382).
+char(c,24383).
+char(m,24384).
+char(5,24385).
+char(1,24386).
+char(6,24387).
+char(5,24388).
+char(m,24389).
+char(1,24390).
+char(8,24391).
+char(4,24392).
+char(9,24393).
+char(c,24394).
+char(m,24395).
+char(o,24396).
+char(p,24397).
+char(7,24398).
+char(2,24399).
+char(7,24400).
+char(9,24401).
+char(m,24402).
+char(o,24403).
+char(1,24404).
+char(2,24405).
+char(5,24406).
+char(7,24407).
+char(p,24408).
+char(2,24409).
+char(8,24410).
+char(3,24411).
+char(1,24412).
+char(p,24413).
+char(5,24414).
+char(8,24415).
+char(2,24416).
+char(3,24417).
+char(c,24418).
+char(c,24419).
+char(c,24420).
+char(c,24421).
+char(p,24422).
+char(o,24423).
+char(m,24424).
+char(1,24425).
+char(8,24426).
+char(7,24427).
+char(c,24428).
+char(c,24429).
+char(c,24430).
+char(p,24431).
+char(o,24432).
+char(o,24433).
+char(p,24434).
+char(o,24435).
+char(m,24436).
+char(5,24437).
+char(9,24438).
+char(9,24439).
+char(0,24440).
+char(c,24441).
+char(p,24442).
+char(9,24443).
+char(6,24444).
+char(0,24445).
+char(p,24446).
+char(o,24447).
+char(m,24448).
+char(o,24449).
+char(m,24450).
+char(7,24451).
+char(3,24452).
+char(9,24453).
+char(7,24454).
+char(c,24455).
+char(p,24456).
+char(o,24457).
+char(p,24458).
+char(4,24459).
+char(2,24460).
+char(0,24461).
+char(0,24462).
+char(c,24463).
+char(c,24464).
+char(c,24465).
+char(c,24466).
+char(c,24467).
+char(c,24468).
+char(c,24469).
+char(c,24470).
+char(p,24471).
+char(5,24472).
+char(9,24473).
+char(3,24474).
+char(5,24475).
+char(m,24476).
+char(o,24477).
+char(o,24478).
+char(m,24479).
+char(1,24480).
+char(9,24481).
+char(2,24482).
+char(p,24483).
+char(5,24484).
+char(2,24485).
+char(4,24486).
+char(8,24487).
+char(m,24488).
+char(o,24489).
+char(m,24490).
+char(o,24491).
+char(o,24492).
+char(o,24493).
+char(6,24494).
+char(0,24495).
+char(8,24496).
+char(7,24497).
+char(c,24498).
+char(m,24499).
+char(1,24500).
+char(4,24501).
+char(4,24502).
+char(4,24503).
+char(c,24504).
+char(c,24505).
+char(p,24506).
+char(o,24507).
+char(p,24508).
+char(3,24509).
+char(4,24510).
+char(4,24511).
+char(3,24512).
+char(p,24513).
+char(o,24514).
+char(o,24515).
+char(o,24516).
+char(o,24517).
+char(p,24518).
+char(1,24519).
+char(3,24520).
+char(8,24521).
+char(2,24522).
+char(c,24523).
+char(p,24524).
+char(2,24525).
+char(3,24526).
+char(0,24527).
+char(7,24528).
+char(c,24529).
+char(c,24530).
+char(c,24531).
+char(c,24532).
+char(c,24533).
+char(p,24534).
+char(6,24535).
+char(4,24536).
+char(6,24537).
+char(5,24538).
+char(m,24539).
+char(o,24540).
+char(o,24541).
+char(p,24542).
+char(o,24543).
+char(p,24544).
+char(o,24545).
+char(p,24546).
+char(o,24547).
+char(m,24548).
+char(o,24549).
+char(m,24550).
+char(2,24551).
+char(3,24552).
+char(1,24553).
+char(9,24554).
+char(p,24555).
+char(5,24556).
+char(2,24557).
+char(6,24558).
+char(8,24559).
+char(p,24560).
+char(7,24561).
+char(9,24562).
+char(2,24563).
+char(4,24564).
+char(p,24565).
+char(o,24566).
+char(2,24567).
+char(4,24568).
+char(3,24569).
+char(9,24570).
+char(p,24571).
+char(o,24572).
+char(m,24573).
+char(8,24574).
+char(2,24575).
+char(7,24576).
+char(4,24577).
+char(m,24578).
+char(7,24579).
+char(3,24580).
+char(2,24581).
+char(7,24582).
+char(c,24583).
+char(c,24584).
+char(p,24585).
+char(9,24586).
+char(8,24587).
+char(5,24588).
+char(1,24589).
+char(m,24590).
+char(o,24591).
+char(m,24592).
+char(6,24593).
+char(3,24594).
+char(1,24595).
+char(8,24596).
+char(m,24597).
+char(o,24598).
+char(m,24599).
+char(o,24600).
+char(9,24601).
+char(9,24602).
+char(5,24603).
+char(5,24604).
+char(p,24605).
+char(o,24606).
+char(m,24607).
+char(2,24608).
+char(1,24609).
+char(2,24610).
+char(8,24611).
+char(c,24612).
+char(p,24613).
+char(o,24614).
+char(4,24615).
+char(1,24616).
+char(5,24617).
+char(c,24618).
+char(p,24619).
+char(3,24620).
+char(6,24621).
+char(9,24622).
+char(6,24623).
+char(m,24624).
+char(o,24625).
+char(m,24626).
+char(o,24627).
+char(o,24628).
+char(m,24629).
+char(7,24630).
+char(4,24631).
+char(3,24632).
+char(0,24633).
+char(p,24634).
+char(o,24635).
+char(p,24636).
+char(o,24637).
+char(p,24638).
+char(o,24639).
+char(7,24640).
+char(3,24641).
+char(2,24642).
+char(7,24643).
+char(p,24644).
+char(6,24645).
+char(9,24646).
+char(7,24647).
+char(7,24648).
+char(m,24649).
+char(o,24650).
+char(o,24651).
+char(6,24652).
+char(6,24653).
+char(5,24654).
+char(9,24655).
+char(c,24656).
+char(c,24657).
+char(c,24658).
+char(c,24659).
+char(p,24660).
+char(o,24661).
+char(m,24662).
+char(4,24663).
+char(9,24664).
+char(1,24665).
+char(6,24666).
+char(m,24667).
+char(o,24668).
+char(p,24669).
+char(o,24670).
+char(m,24671).
+char(5,24672).
+char(5,24673).
+char(1,24674).
+char(7,24675).
+char(p,24676).
+char(1,24677).
+char(8,24678).
+char(2,24679).
+char(0,24680).
+char(p,24681).
+char(o,24682).
+char(p,24683).
+char(o,24684).
+char(m,24685).
+char(2,24686).
+char(9,24687).
+char(8,24688).
+char(2,24689).
+char(m,24690).
+char(o,24691).
+char(m,24692).
+char(1,24693).
+char(5,24694).
+char(7,24695).
+char(5,24696).
+char(p,24697).
+char(5,24698).
+char(5,24699).
+char(5,24700).
+char(6,24701).
+char(c,24702).
+char(p,24703).
+char(8,24704).
+char(5,24705).
+char(2,24706).
+char(8,24707).
+char(p,24708).
+char(o,24709).
+char(o,24710).
+char(o,24711).
+char(o,24712).
+char(o,24713).
+char(p,24714).
+char(6,24715).
+char(7,24716).
+char(2,24717).
+char(5,24718).
+char(c,24719).
+char(m,24720).
+char(4,24721).
+char(7,24722).
+char(3,24723).
+char(7,24724).
+char(c,24725).
+char(c,24726).
+char(c,24727).
+char(p,24728).
+char(o,24729).
+char(p,24730).
+char(9,24731).
+char(3,24732).
+char(9,24733).
+char(p,24734).
+char(9,24735).
+char(2,24736).
+char(0,24737).
+char(2,24738).
+char(m,24739).
+char(o,24740).
+char(4,24741).
+char(6,24742).
+char(6,24743).
+char(p,24744).
+char(o,24745).
+char(6,24746).
+char(9,24747).
+char(8,24748).
+char(5,24749).
+char(p,24750).
+char(7,24751).
+char(3,24752).
+char(5,24753).
+char(5,24754).
+char(c,24755).
+char(c,24756).
+char(p,24757).
+char(8,24758).
+char(6,24759).
+char(8,24760).
+char(9,24761).
+char(c,24762).
+char(p,24763).
+char(6,24764).
+char(5,24765).
+char(4,24766).
+char(4,24767).
+char(m,24768).
+char(o,24769).
+char(o,24770).
+char(p,24771).
+char(1,24772).
+char(1,24773).
+char(2,24774).
+char(7,24775).
+char(c,24776).
+char(c,24777).
+char(c,24778).
+char(c,24779).
+char(c,24780).
+char(m,24781).
+char(o,24782).
+char(p,24783).
+char(8,24784).
+char(7,24785).
+char(7,24786).
+char(3,24787).
+char(p,24788).
+char(o,24789).
+char(o,24790).
+char(m,24791).
+char(o,24792).
+char(m,24793).
+char(o,24794).
+char(p,24795).
+char(o,24796).
+char(m,24797).
+char(o,24798).
+char(p,24799).
+char(9,24800).
+char(2,24801).
+char(7,24802).
+char(9,24803).
+char(m,24804).
+char(o,24805).
+char(p,24806).
+char(o,24807).
+char(m,24808).
+char(o,24809).
+char(m,24810).
+char(o,24811).
+char(8,24812).
+char(2,24813).
+char(0,24814).
+char(5,24815).
+char(m,24816).
+char(o,24817).
+char(p,24818).
+char(o,24819).
+char(m,24820).
+char(4,24821).
+char(8,24822).
+char(0,24823).
+char(7,24824).
+char(m,24825).
+char(o,24826).
+char(m,24827).
+char(o,24828).
+char(4,24829).
+char(5,24830).
+char(7,24831).
+char(3,24832).
+char(c,24833).
+char(m,24834).
+char(6,24835).
+char(4,24836).
+char(7,24837).
+char(7,24838).
+char(c,24839).
+char(p,24840).
+char(8,24841).
+char(4,24842).
+char(0,24843).
+char(0,24844).
+char(m,24845).
+char(o,24846).
+char(m,24847).
+char(o,24848).
+char(1,24849).
+char(7,24850).
+char(4,24851).
+char(0,24852).
+char(c,24853).
+char(m,24854).
+char(7,24855).
+char(8,24856).
+char(0,24857).
+char(3,24858).
+char(m,24859).
+char(o,24860).
+char(5,24861).
+char(3,24862).
+char(4,24863).
+char(4,24864).
+char(c,24865).
+char(p,24866).
+char(6,24867).
+char(3,24868).
+char(7,24869).
+char(p,24870).
+char(7,24871).
+char(8,24872).
+char(4,24873).
+char(4,24874).
+char(m,24875).
+char(1,24876).
+char(9,24877).
+char(6,24878).
+char(7,24879).
+char(p,24880).
+char(o,24881).
+char(o,24882).
+char(m,24883).
+char(o,24884).
+char(4,24885).
+char(7,24886).
+char(8,24887).
+char(2,24888).
+char(c,24889).
+char(m,24890).
+char(7,24891).
+char(3,24892).
+char(4,24893).
+char(c,24894).
+char(p,24895).
+char(7,24896).
+char(1,24897).
+char(7,24898).
+char(5,24899).
+char(p,24900).
+char(o,24901).
+char(p,24902).
+char(o,24903).
+char(m,24904).
+char(o,24905).
+char(3,24906).
+char(3,24907).
+char(5,24908).
+char(7,24909).
+char(p,24910).
+char(6,24911).
+char(2,24912).
+char(3,24913).
+char(9,24914).
+char(c,24915).
+char(c,24916).
+char(c,24917).
+char(c,24918).
+char(m,24919).
+char(o,24920).
+char(o,24921).
+char(p,24922).
+char(5,24923).
+char(9,24924).
+char(7,24925).
+char(1,24926).
+char(m,24927).
+char(5,24928).
+char(5,24929).
+char(1,24930).
+char(8,24931).
+char(p,24932).
+char(o,24933).
+char(5,24934).
+char(9,24935).
+char(0,24936).
+char(p,24937).
+char(5,24938).
+char(7,24939).
+char(1,24940).
+char(7,24941).
+char(m,24942).
+char(o,24943).
+char(o,24944).
+char(p,24945).
+char(o,24946).
+char(p,24947).
+char(o,24948).
+char(o,24949).
+char(p,24950).
+char(o,24951).
+char(p,24952).
+char(o,24953).
+char(o,24954).
+char(5,24955).
+char(6,24956).
+char(8,24957).
+char(p,24958).
+char(o,24959).
+char(m,24960).
+char(7,24961).
+char(6,24962).
+char(7,24963).
+char(2,24964).
+char(p,24965).
+char(1,24966).
+char(5,24967).
+char(c,24968).
+char(p,24969).
+char(o,24970).
+char(o,24971).
+char(p,24972).
+char(o,24973).
+char(o,24974).
+char(2,24975).
+char(9,24976).
+char(2,24977).
+char(6,24978).
+char(c,24979).
+char(p,24980).
+char(5,24981).
+char(6,24982).
+char(3,24983).
+char(5,24984).
+char(p,24985).
+char(6,24986).
+char(1,24987).
+char(2,24988).
+char(4,24989).
+char(c,24990).
+char(c,24991).
+char(c,24992).
+char(c,24993).
+char(p,24994).
+char(o,24995).
+char(p,24996).
+char(o,24997).
+char(m,24998).
+char(o,24999).
+char(m,25000).
+char(3,25001).
+char(4,25002).
+char(5,25003).
+char(6,25004).
+char(m,25005).
+char(7,25006).
+char(1,25007).
+char(8,25008).
+char(9,25009).
+char(c,25010).
+char(p,25011).
+char(3,25012).
+char(7,25013).
+char(3,25014).
+char(4,25015).
+char(c,25016).
+char(c,25017).
+char(c,25018).
+char(p,25019).
+char(6,25020).
+char(9,25021).
+char(2,25022).
+char(2,25023).
+char(p,25024).
+char(o,25025).
+char(p,25026).
+char(9,25027).
+char(6,25028).
+char(6,25029).
+char(m,25030).
+char(6,25031).
+char(0,25032).
+char(4,25033).
+char(8,25034).
+char(m,25035).
+char(o,25036).
+char(m,25037).
+char(o,25038).
+char(p,25039).
+char(o,25040).
+char(p,25041).
+char(8,25042).
+char(7,25043).
+char(4,25044).
+char(c,25045).
+char(c,25046).
+char(p,25047).
+char(8,25048).
+char(3,25049).
+char(3,25050).
+char(4,25051).
+char(m,25052).
+char(o,25053).
+char(o,25054).
+char(o,25055).
+char(p,25056).
+char(7,25057).
+char(4,25058).
+char(2,25059).
+char(3,25060).
+char(p,25061).
+char(o,25062).
+char(m,25063).
+char(o,25064).
+char(m,25065).
+char(6,25066).
+char(4,25067).
+char(m,25068).
+char(o,25069).
+char(m,25070).
+char(3,25071).
+char(4,25072).
+char(8,25073).
+char(7,25074).
+char(p,25075).
+char(7,25076).
+char(0,25077).
+char(9,25078).
+char(4,25079).
+char(p,25080).
+char(6,25081).
+char(4,25082).
+char(7,25083).
+char(8,25084).
+char(p,25085).
+char(o,25086).
+char(4,25087).
+char(1,25088).
+char(p,25089).
+char(o,25090).
+char(m,25091).
+char(4,25092).
+char(8,25093).
+char(2,25094).
+char(4,25095).
+char(c,25096).
+char(c,25097).
+char(c,25098).
+char(c,25099).
+char(c,25100).
+char(c,25101).
+char(m,25102).
+char(o,25103).
+char(m,25104).
+char(o,25105).
+char(o,25106).
+char(7,25107).
+char(3,25108).
+char(1,25109).
+char(1,25110).
+char(c,25111).
+char(c,25112).
+char(p,25113).
+char(7,25114).
+char(2,25115).
+char(8,25116).
+char(8,25117).
+char(p,25118).
+char(8,25119).
+char(8,25120).
+char(5,25121).
+char(2,25122).
+char(c,25123).
+char(m,25124).
+char(9,25125).
+char(5,25126).
+char(8,25127).
+char(9,25128).
+char(p,25129).
+char(8,25130).
+char(5,25131).
+char(1,25132).
+char(7,25133).
+char(c,25134).
+char(p,25135).
+char(o,25136).
+char(1,25137).
+char(4,25138).
+char(2,25139).
+char(6,25140).
+char(c,25141).
+char(c,25142).
+char(c,25143).
+char(c,25144).
+char(m,25145).
+char(o,25146).
+char(m,25147).
+char(o,25148).
+char(p,25149).
+char(o,25150).
+char(6,25151).
+char(7,25152).
+char(0,25153).
+char(3,25154).
+char(c,25155).
+char(c,25156).
+char(c,25157).
+char(c,25158).
+char(c,25159).
+char(c,25160).
+char(m,25161).
+char(5,25162).
+char(4,25163).
+char(7,25164).
+char(3,25165).
+char(c,25166).
+char(p,25167).
+char(o,25168).
+char(p,25169).
+char(o,25170).
+char(p,25171).
+char(o,25172).
+char(p,25173).
+char(o,25174).
+char(p,25175).
+char(2,25176).
+char(5,25177).
+char(5,25178).
+char(1,25179).
+char(m,25180).
+char(6,25181).
+char(6,25182).
+char(6,25183).
+char(7,25184).
+char(m,25185).
+char(7,25186).
+char(7,25187).
+char(1,25188).
+char(1,25189).
+char(m,25190).
+char(o,25191).
+char(4,25192).
+char(1,25193).
+char(6,25194).
+char(0,25195).
+char(c,25196).
+char(p,25197).
+char(o,25198).
+char(m,25199).
+char(4,25200).
+char(9,25201).
+char(5,25202).
+char(5,25203).
+char(m,25204).
+char(o,25205).
+char(o,25206).
+char(o,25207).
+char(m,25208).
+char(o,25209).
+char(p,25210).
+char(4,25211).
+char(5,25212).
+char(3,25213).
+char(2,25214).
+char(m,25215).
+char(o,25216).
+char(m,25217).
+char(6,25218).
+char(8,25219).
+char(0,25220).
+char(3,25221).
+char(p,25222).
+char(o,25223).
+char(m,25224).
+char(6,25225).
+char(2,25226).
+char(1,25227).
+char(5,25228).
+char(m,25229).
+char(o,25230).
+char(9,25231).
+char(1,25232).
+char(3,25233).
+char(7,25234).
+char(c,25235).
+char(c,25236).
+char(c,25237).
+char(c,25238).
+char(p,25239).
+char(o,25240).
+char(1,25241).
+char(5,25242).
+char(0,25243).
+char(3,25244).
+char(c,25245).
+char(m,25246).
+char(3,25247).
+char(5,25248).
+char(2,25249).
+char(4,25250).
+char(c,25251).
+char(c,25252).
+char(c,25253).
+char(c,25254).
+char(p,25255).
+char(o,25256).
+char(o,25257).
+char(m,25258).
+char(9,25259).
+char(7,25260).
+char(3,25261).
+char(1,25262).
+char(m,25263).
+char(o,25264).
+char(p,25265).
+char(2,25266).
+char(2,25267).
+char(3,25268).
+char(0,25269).
+char(c,25270).
+char(c,25271).
+char(p,25272).
+char(8,25273).
+char(8,25274).
+char(4,25275).
+char(2,25276).
+char(c,25277).
+char(c,25278).
+char(c,25279).
+char(c,25280).
+char(m,25281).
+char(5,25282).
+char(0,25283).
+char(6,25284).
+char(0,25285).
+char(m,25286).
+char(1,25287).
+char(9,25288).
+char(7,25289).
+char(7,25290).
+char(c,25291).
+char(c,25292).
+char(c,25293).
+char(p,25294).
+char(o,25295).
+char(o,25296).
+char(p,25297).
+char(o,25298).
+char(o,25299).
+char(p,25300).
+char(o,25301).
+char(m,25302).
+char(o,25303).
+char(p,25304).
+char(6,25305).
+char(8,25306).
+char(9,25307).
+char(5,25308).
+char(p,25309).
+char(6,25310).
+char(2,25311).
+char(1,25312).
+char(2,25313).
+char(m,25314).
+char(7,25315).
+char(7,25316).
+char(7,25317).
+char(6,25318).
+char(p,25319).
+char(8,25320).
+char(0,25321).
+char(0,25322).
+char(8,25323).
+char(c,25324).
+char(m,25325).
+char(o,25326).
+char(1,25327).
+char(9,25328).
+char(6,25329).
+char(5,25330).
+char(c,25331).
+char(m,25332).
+char(o,25333).
+char(o,25334).
+char(p,25335).
+char(4,25336).
+char(9,25337).
+char(5,25338).
+char(6,25339).
+char(m,25340).
+char(8,25341).
+char(1,25342).
+char(4,25343).
+char(0,25344).
+char(m,25345).
+char(o,25346).
+char(1,25347).
+char(7,25348).
+char(2,25349).
+char(3,25350).
+char(m,25351).
+char(1,25352).
+char(0,25353).
+char(0,25354).
+char(9,25355).
+char(p,25356).
+char(9,25357).
+char(8,25358).
+char(8,25359).
+char(1,25360).
+char(m,25361).
+char(o,25362).
+char(m,25363).
+char(8,25364).
+char(9,25365).
+char(6,25366).
+char(6,25367).
+char(m,25368).
+char(o,25369).
+char(7,25370).
+char(1,25371).
+char(4,25372).
+char(2,25373).
+char(m,25374).
+char(3,25375).
+char(2,25376).
+char(1,25377).
+char(5,25378).
+char(c,25379).
+char(m,25380).
+char(o,25381).
+char(m,25382).
+char(o,25383).
+char(o,25384).
+char(2,25385).
+char(7,25386).
+char(6,25387).
+char(3,25388).
+char(m,25389).
+char(4,25390).
+char(6,25391).
+char(7,25392).
+char(7,25393).
+char(m,25394).
+char(o,25395).
+char(p,25396).
+char(o,25397).
+char(p,25398).
+char(9,25399).
+char(0,25400).
+char(4,25401).
+char(8,25402).
+char(p,25403).
+char(o,25404).
+char(o,25405).
+char(9,25406).
+char(7,25407).
+char(8,25408).
+char(p,25409).
+char(8,25410).
+char(3,25411).
+char(4,25412).
+char(3,25413).
+char(c,25414).
+char(p,25415).
+char(o,25416).
+char(3,25417).
+char(6,25418).
+char(0,25419).
+char(0,25420).
+char(c,25421).
+char(c,25422).
+char(m,25423).
+char(o,25424).
+char(p,25425).
+char(3,25426).
+char(2,25427).
+char(3,25428).
+char(5,25429).
+char(m,25430).
+char(o,25431).
+char(m,25432).
+char(9,25433).
+char(9,25434).
+char(3,25435).
+char(9,25436).
+char(m,25437).
+char(o,25438).
+char(m,25439).
+char(o,25440).
+char(m,25441).
+char(9,25442).
+char(3,25443).
+char(6,25444).
+char(c,25445).
+char(c,25446).
+char(c,25447).
+char(c,25448).
+char(c,25449).
+char(c,25450).
+char(m,25451).
+char(o,25452).
+char(m,25453).
+char(1,25454).
+char(4,25455).
+char(6,25456).
+char(5,25457).
+char(p,25458).
+char(o,25459).
+char(7,25460).
+char(7,25461).
+char(4,25462).
+char(c,25463).
+char(m,25464).
+char(8,25465).
+char(2,25466).
+char(6,25467).
+char(1,25468).
+char(c,25469).
+char(m,25470).
+char(o,25471).
+char(3,25472).
+char(7,25473).
+char(3,25474).
+char(1,25475).
+char(m,25476).
+char(8,25477).
+char(2,25478).
+char(4,25479).
+char(4,25480).
+char(c,25481).
+char(m,25482).
+char(o,25483).
+char(9,25484).
+char(6,25485).
+char(0,25486).
+char(8,25487).
+char(c,25488).
+char(c,25489).
+char(m,25490).
+char(7,25491).
+char(0,25492).
+char(8,25493).
+char(7,25494).
+char(c,25495).
+char(c,25496).
+char(c,25497).
+char(p,25498).
+char(o,25499).
+char(o,25500).
+char(4,25501).
+char(3,25502).
+char(8,25503).
+char(0,25504).
+char(m,25505).
+char(o,25506).
+char(p,25507).
+char(o,25508).
+char(m,25509).
+char(o,25510).
+char(m,25511).
+char(o,25512).
+char(2,25513).
+char(0,25514).
+char(2,25515).
+char(p,25516).
+char(8,25517).
+char(0,25518).
+char(4,25519).
+char(7,25520).
+char(p,25521).
+char(o,25522).
+char(m,25523).
+char(o,25524).
+char(p,25525).
+char(2,25526).
+char(4,25527).
+char(5,25528).
+char(3,25529).
+char(p,25530).
+char(o,25531).
+char(m,25532).
+char(1,25533).
+char(1,25534).
+char(7,25535).
+char(5,25536).
+char(c,25537).
+char(p,25538).
+char(7,25539).
+char(3,25540).
+char(8,25541).
+char(m,25542).
+char(o,25543).
+char(p,25544).
+char(o,25545).
+char(m,25546).
+char(o,25547).
+char(m,25548).
+char(o,25549).
+char(p,25550).
+char(8,25551).
+char(8,25552).
+char(7,25553).
+char(0,25554).
+char(c,25555).
+char(c,25556).
+char(c,25557).
+char(c,25558).
+char(m,25559).
+char(o,25560).
+char(o,25561).
+char(p,25562).
+char(1,25563).
+char(2,25564).
+char(7,25565).
+char(2,25566).
+char(c,25567).
+char(p,25568).
+char(o,25569).
+char(m,25570).
+char(3,25571).
+char(3,25572).
+char(9,25573).
+char(8,25574).
+char(m,25575).
+char(8,25576).
+char(1,25577).
+char(0,25578).
+char(9,25579).
+char(m,25580).
+char(4,25581).
+char(5,25582).
+char(9,25583).
+char(7,25584).
+char(p,25585).
+char(o,25586).
+char(p,25587).
+char(o,25588).
+char(p,25589).
+char(o,25590).
+char(5,25591).
+char(2,25592).
+char(1,25593).
+char(4,25594).
+char(c,25595).
+char(c,25596).
+char(m,25597).
+char(o,25598).
+char(m,25599).
+char(o,25600).
+char(m,25601).
+char(5,25602).
+char(7,25603).
+char(0,25604).
+char(6,25605).
+char(m,25606).
+char(7,25607).
+char(4,25608).
+char(2,25609).
+char(6,25610).
+char(m,25611).
+char(o,25612).
+char(m,25613).
+char(1,25614).
+char(7,25615).
+char(3,25616).
+char(6,25617).
+char(c,25618).
+char(m,25619).
+char(o,25620).
+char(p,25621).
+char(o,25622).
+char(p,25623).
+char(o,25624).
+char(8,25625).
+char(5,25626).
+char(8,25627).
+char(0,25628).
+char(c,25629).
+char(c,25630).
+char(c,25631).
+char(m,25632).
+char(2,25633).
+char(9,25634).
+char(1,25635).
+char(4,25636).
+char(c,25637).
+char(c,25638).
+char(c,25639).
+char(c,25640).
+char(c,25641).
+char(c,25642).
+char(c,25643).
+char(m,25644).
+char(o,25645).
+char(o,25646).
+char(p,25647).
+char(o,25648).
+char(m,25649).
+char(o,25650).
+char(p,25651).
+char(7,25652).
+char(1,25653).
+char(2,25654).
+char(4,25655).
+char(c,25656).
+char(p,25657).
+char(o,25658).
+char(2,25659).
+char(4,25660).
+char(6,25661).
+char(8,25662).
+char(p,25663).
+char(4,25664).
+char(9,25665).
+char(6,25666).
+char(7,25667).
+char(p,25668).
+char(o,25669).
+char(9,25670).
+char(3,25671).
+char(8,25672).
+char(8,25673).
+char(c,25674).
+char(m,25675).
+char(4,25676).
+char(6,25677).
+char(2,25678).
+char(m,25679).
+char(9,25680).
+char(7,25681).
+char(7,25682).
+char(4,25683).
+char(m,25684).
+char(o,25685).
+char(m,25686).
+char(5,25687).
+char(4,25688).
+char(0,25689).
+char(8,25690).
+char(p,25691).
+char(9,25692).
+char(6,25693).
+char(0,25694).
+char(3,25695).
+char(m,25696).
+char(5,25697).
+char(2,25698).
+char(2,25699).
+char(7,25700).
+char(c,25701).
+char(c,25702).
+char(c,25703).
+char(p,25704).
+char(o,25705).
+char(p,25706).
+char(2,25707).
+char(0,25708).
+char(2,25709).
+char(5,25710).
+char(c,25711).
+char(c,25712).
+char(p,25713).
+char(2,25714).
+char(0,25715).
+char(0,25716).
+char(7,25717).
+char(c,25718).
+char(c,25719).
+char(m,25720).
+char(9,25721).
+char(2,25722).
+char(6,25723).
+char(1,25724).
+char(m,25725).
+char(4,25726).
+char(4,25727).
+char(5,25728).
+char(1,25729).
+char(m,25730).
+char(o,25731).
+char(o,25732).
+char(o,25733).
+char(p,25734).
+char(8,25735).
+char(8,25736).
+char(1,25737).
+char(3,25738).
+char(p,25739).
+char(o,25740).
+char(p,25741).
+char(7,25742).
+char(0,25743).
+char(8,25744).
+char(4,25745).
+char(c,25746).
+char(p,25747).
+char(o,25748).
+char(m,25749).
+char(o,25750).
+char(m,25751).
+char(1,25752).
+char(1,25753).
+char(8,25754).
+char(1,25755).
+char(p,25756).
+char(1,25757).
+char(2,25758).
+char(p,25759).
+char(o,25760).
+char(2,25761).
+char(0,25762).
+char(9,25763).
+char(0,25764).
+char(c,25765).
+char(m,25766).
+char(o,25767).
+char(p,25768).
+char(1,25769).
+char(5,25770).
+char(0,25771).
+char(3,25772).
+char(m,25773).
+char(4,25774).
+char(2,25775).
+char(5,25776).
+char(1,25777).
+char(m,25778).
+char(5,25779).
+char(0,25780).
+char(6,25781).
+char(m,25782).
+char(9,25783).
+char(9,25784).
+char(3,25785).
+char(8,25786).
+char(p,25787).
+char(5,25788).
+char(2,25789).
+char(8,25790).
+char(7,25791).
+char(p,25792).
+char(o,25793).
+char(p,25794).
+char(4,25795).
+char(6,25796).
+char(2,25797).
+char(m,25798).
+char(1,25799).
+char(3,25800).
+char(7,25801).
+char(p,25802).
+char(o,25803).
+char(m,25804).
+char(5,25805).
+char(1,25806).
+char(7,25807).
+char(3,25808).
+char(c,25809).
+char(m,25810).
+char(6,25811).
+char(8,25812).
+char(9,25813).
+char(6,25814).
+char(c,25815).
+char(c,25816).
+char(c,25817).
+char(c,25818).
+char(m,25819).
+char(5,25820).
+char(9,25821).
+char(6,25822).
+char(9,25823).
+char(c,25824).
+char(c,25825).
+char(m,25826).
+char(o,25827).
+char(p,25828).
+char(8,25829).
+char(5,25830).
+char(8,25831).
+char(5,25832).
+char(m,25833).
+char(o,25834).
+char(m,25835).
+char(4,25836).
+char(7,25837).
+char(2,25838).
+char(9,25839).
+char(m,25840).
+char(6,25841).
+char(4,25842).
+char(3,25843).
+char(9,25844).
+char(c,25845).
+char(c,25846).
+char(m,25847).
+char(o,25848).
+char(o,25849).
+char(m,25850).
+char(2,25851).
+char(9,25852).
+char(2,25853).
+char(6,25854).
+char(c,25855).
+char(c,25856).
+char(c,25857).
+char(c,25858).
+char(p,25859).
+char(o,25860).
+char(3,25861).
+char(0,25862).
+char(6,25863).
+char(7,25864).
+char(c,25865).
+char(m,25866).
+char(o,25867).
+char(p,25868).
+char(o,25869).
+char(p,25870).
+char(9,25871).
+char(0,25872).
+char(2,25873).
+char(7,25874).
+char(p,25875).
+char(8,25876).
+char(2,25877).
+char(8,25878).
+char(9,25879).
+char(c,25880).
+char(p,25881).
+char(o,25882).
+char(m,25883).
+char(o,25884).
+char(m,25885).
+char(o,25886).
+char(5,25887).
+char(2,25888).
+char(9,25889).
+char(3,25890).
+char(p,25891).
+char(6,25892).
+char(1,25893).
+char(4,25894).
+char(3,25895).
+char(c,25896).
+char(c,25897).
+char(m,25898).
+char(6,25899).
+char(9,25900).
+char(6,25901).
+char(1,25902).
+char(p,25903).
+char(4,25904).
+char(2,25905).
+char(5,25906).
+char(0,25907).
+char(c,25908).
+char(c,25909).
+char(c,25910).
+char(m,25911).
+char(8,25912).
+char(0,25913).
+char(7,25914).
+char(p,25915).
+char(o,25916).
+char(m,25917).
+char(8,25918).
+char(4,25919).
+char(4,25920).
+char(8,25921).
+char(m,25922).
+char(3,25923).
+char(6,25924).
+char(6,25925).
+char(8,25926).
+char(c,25927).
+char(m,25928).
+char(o,25929).
+char(p,25930).
+char(2,25931).
+char(0,25932).
+char(9,25933).
+char(0,25934).
+char(c,25935).
+char(p,25936).
+char(3,25937).
+char(0,25938).
+char(6,25939).
+char(6,25940).
+char(m,25941).
+char(o,25942).
+char(o,25943).
+char(m,25944).
+char(o,25945).
+char(p,25946).
+char(o,25947).
+char(m,25948).
+char(o,25949).
+char(p,25950).
+char(o,25951).
+char(m,25952).
+char(o,25953).
+char(2,25954).
+char(2,25955).
+char(4,25956).
+char(4,25957).
+char(c,25958).
+char(c,25959).
+char(c,25960).
+char(m,25961).
+char(6,25962).
+char(2,25963).
+char(1,25964).
+char(1,25965).
+char(c,25966).
+char(c,25967).
+char(c,25968).
+char(c,25969).
+char(c,25970).
+char(m,25971).
+char(o,25972).
+char(p,25973).
+char(8,25974).
+char(4,25975).
+char(0,25976).
+char(c,25977).
+char(p,25978).
+char(o,25979).
+char(o,25980).
+char(o,25981).
+char(m,25982).
+char(o,25983).
+char(4,25984).
+char(4,25985).
+char(3,25986).
+char(5,25987).
+char(p,25988).
+char(7,25989).
+char(0,25990).
+char(1,25991).
+char(0,25992).
+char(m,25993).
+char(8,25994).
+char(3,25995).
+char(7,25996).
+char(1,25997).
+char(m,25998).
+char(o,25999).
+char(m,26000).
+char(2,26001).
+char(2,26002).
+char(2,26003).
+char(5,26004).
+char(p,26005).
+char(1,26006).
+char(2,26007).
+char(0,26008).
+char(6,26009).
+char(p,26010).
+char(6,26011).
+char(2,26012).
+char(0,26013).
+char(0,26014).
+char(c,26015).
+char(c,26016).
+char(c,26017).
+char(m,26018).
+char(9,26019).
+char(3,26020).
+char(4,26021).
+char(7,26022).
+char(c,26023).
+char(m,26024).
+char(o,26025).
+char(m,26026).
+char(o,26027).
+char(o,26028).
+char(m,26029).
+char(o,26030).
+char(p,26031).
+char(5,26032).
+char(2,26033).
+char(0,26034).
+char(2,26035).
+char(p,26036).
+char(6,26037).
+char(5,26038).
+char(8,26039).
+char(4,26040).
+char(c,26041).
+char(p,26042).
+char(o,26043).
+char(m,26044).
+char(3,26045).
+char(4,26046).
+char(8,26047).
+char(9,26048).
+char(c,26049).
+char(p,26050).
+char(7,26051).
+char(0,26052).
+char(7,26053).
+char(6,26054).
+char(c,26055).
+char(p,26056).
+char(5,26057).
+char(8,26058).
+char(9,26059).
+char(p,26060).
+char(o,26061).
+char(p,26062).
+char(5,26063).
+char(7,26064).
+char(3,26065).
+char(7,26066).
+char(c,26067).
+char(c,26068).
+char(m,26069).
+char(7,26070).
+char(6,26071).
+char(9,26072).
+char(1,26073).
+char(m,26074).
+char(o,26075).
+char(p,26076).
+char(1,26077).
+char(5,26078).
+char(9,26079).
+char(4,26080).
+char(p,26081).
+char(8,26082).
+char(5,26083).
+char(4,26084).
+char(6,26085).
+char(m,26086).
+char(o,26087).
+char(m,26088).
+char(8,26089).
+char(3,26090).
+char(7,26091).
+char(6,26092).
+char(p,26093).
+char(o,26094).
+char(p,26095).
+char(5,26096).
+char(0,26097).
+char(6,26098).
+char(5,26099).
+char(c,26100).
+char(c,26101).
+char(c,26102).
+char(m,26103).
+char(5,26104).
+char(0,26105).
+char(5,26106).
+char(1,26107).
+char(c,26108).
+char(p,26109).
+char(o,26110).
+char(4,26111).
+char(1,26112).
+char(4,26113).
+char(6,26114).
+char(c,26115).
+char(c,26116).
+char(p,26117).
+char(o,26118).
+char(p,26119).
+char(8,26120).
+char(0,26121).
+char(9,26122).
+char(c,26123).
+char(p,26124).
+char(4,26125).
+char(6,26126).
+char(9,26127).
+char(2,26128).
+char(c,26129).
+char(c,26130).
+char(p,26131).
+char(3,26132).
+char(4,26133).
+char(1,26134).
+char(6,26135).
+char(c,26136).
+char(c,26137).
+char(c,26138).
+char(m,26139).
+char(o,26140).
+char(p,26141).
+char(o,26142).
+char(m,26143).
+char(o,26144).
+char(7,26145).
+char(8,26146).
+char(7,26147).
+char(7,26148).
+char(p,26149).
+char(5,26150).
+char(7,26151).
+char(0,26152).
+char(4,26153).
+char(c,26154).
+char(m,26155).
+char(o,26156).
+char(p,26157).
+char(o,26158).
+char(p,26159).
+char(o,26160).
+char(o,26161).
+char(m,26162).
+char(4,26163).
+char(5,26164).
+char(1,26165).
+char(5,26166).
+char(c,26167).
+char(p,26168).
+char(2,26169).
+char(1,26170).
+char(8,26171).
+char(1,26172).
+char(c,26173).
+char(m,26174).
+char(o,26175).
+char(p,26176).
+char(6,26177).
+char(6,26178).
+char(0,26179).
+char(2,26180).
+char(c,26181).
+char(c,26182).
+char(p,26183).
+char(5,26184).
+char(4,26185).
+char(8,26186).
+char(4,26187).
+char(m,26188).
+char(o,26189).
+char(m,26190).
+char(6,26191).
+char(2,26192).
+char(7,26193).
+char(0,26194).
+char(m,26195).
+char(o,26196).
+char(m,26197).
+char(o,26198).
+char(o,26199).
+char(m,26200).
+char(8,26201).
+char(0,26202).
+char(7,26203).
+char(5,26204).
+char(c,26205).
+char(p,26206).
+char(o,26207).
+char(o,26208).
+char(m,26209).
+char(7,26210).
+char(6,26211).
+char(0,26212).
+char(7,26213).
+char(c,26214).
+char(m,26215).
+char(o,26216).
+char(6,26217).
+char(0,26218).
+char(5,26219).
+char(5,26220).
+char(c,26221).
+char(p,26222).
+char(o,26223).
+char(p,26224).
+char(o,26225).
+char(p,26226).
+char(o,26227).
+char(m,26228).
+char(5,26229).
+char(1,26230).
+char(8,26231).
+char(7,26232).
+char(c,26233).
+char(c,26234).
+char(c,26235).
+char(m,26236).
+char(o,26237).
+char(m,26238).
+char(o,26239).
+char(p,26240).
+char(o,26241).
+char(o,26242).
+char(p,26243).
+char(3,26244).
+char(3,26245).
+char(4,26246).
+char(7,26247).
+char(c,26248).
+char(c,26249).
+char(c,26250).
+char(c,26251).
+char(m,26252).
+char(5,26253).
+char(4,26254).
+char(4,26255).
+char(0,26256).
+char(m,26257).
+char(1,26258).
+char(1,26259).
+char(8,26260).
+char(9,26261).
+char(p,26262).
+char(o,26263).
+char(m,26264).
+char(9,26265).
+char(4,26266).
+char(9,26267).
+char(6,26268).
+char(p,26269).
+char(2,26270).
+char(1,26271).
+char(3,26272).
+char(m,26273).
+char(o,26274).
+char(m,26275).
+char(5,26276).
+char(6,26277).
+char(6,26278).
+char(c,26279).
+char(c,26280).
+char(m,26281).
+char(o,26282).
+char(p,26283).
+char(o,26284).
+char(m,26285).
+char(3,26286).
+char(6,26287).
+char(4,26288).
+char(0,26289).
+char(c,26290).
+char(c,26291).
+char(p,26292).
+char(o,26293).
+char(p,26294).
+char(3,26295).
+char(5,26296).
+char(7,26297).
+char(6,26298).
+char(c,26299).
+char(c,26300).
+char(p,26301).
+char(o,26302).
+char(o,26303).
+char(p,26304).
+char(o,26305).
+char(m,26306).
+char(8,26307).
+char(3,26308).
+char(9,26309).
+char(9,26310).
+char(m,26311).
+char(2,26312).
+char(7,26313).
+char(1,26314).
+char(8,26315).
+char(m,26316).
+char(o,26317).
+char(p,26318).
+char(8,26319).
+char(6,26320).
+char(6,26321).
+char(4,26322).
+char(c,26323).
+char(m,26324).
+char(2,26325).
+char(7,26326).
+char(9,26327).
+char(8,26328).
+char(p,26329).
+char(o,26330).
+char(m,26331).
+char(1,26332).
+char(5,26333).
+char(4,26334).
+char(1,26335).
+char(p,26336).
+char(o,26337).
+char(m,26338).
+char(9,26339).
+char(1,26340).
+char(4,26341).
+char(9,26342).
+char(m,26343).
+char(o,26344).
+char(m,26345).
+char(1,26346).
+char(4,26347).
+char(8,26348).
+char(0,26349).
+char(c,26350).
+char(c,26351).
+char(m,26352).
+char(7,26353).
+char(7,26354).
+char(p,26355).
+char(o,26356).
+char(m,26357).
+char(7,26358).
+char(0,26359).
+char(0,26360).
+char(1,26361).
+char(p,26362).
+char(6,26363).
+char(2,26364).
+char(0,26365).
+char(4,26366).
+char(m,26367).
+char(o,26368).
+char(7,26369).
+char(2,26370).
+char(0,26371).
+char(4,26372).
+char(c,26373).
+char(c,26374).
+char(c,26375).
+char(p,26376).
+char(o,26377).
+char(p,26378).
+char(o,26379).
+char(m,26380).
+char(o,26381).
+char(o,26382).
+char(m,26383).
+char(9,26384).
+char(9,26385).
+char(5,26386).
+char(6,26387).
+char(p,26388).
+char(6,26389).
+char(2,26390).
+char(4,26391).
+char(8,26392).
+char(c,26393).
+char(m,26394).
+char(o,26395).
+char(m,26396).
+char(2,26397).
+char(6,26398).
+char(3,26399).
+char(9,26400).
+char(m,26401).
+char(3,26402).
+char(6,26403).
+char(7,26404).
+char(4,26405).
+char(c,26406).
+char(m,26407).
+char(o,26408).
+char(o,26409).
+char(p,26410).
+char(7,26411).
+char(3,26412).
+char(4,26413).
+char(5,26414).
+char(c,26415).
+char(m,26416).
+char(o,26417).
+char(p,26418).
+char(1,26419).
+char(8,26420).
+char(3,26421).
+char(0,26422).
+char(p,26423).
+char(2,26424).
+char(8,26425).
+char(c,26426).
+char(c,26427).
+char(c,26428).
+char(m,26429).
+char(1,26430).
+char(2,26431).
+char(7,26432).
+char(8,26433).
+char(c,26434).
+char(p,26435).
+char(o,26436).
+char(o,26437).
+char(o,26438).
+char(o,26439).
+char(p,26440).
+char(o,26441).
+char(o,26442).
+char(4,26443).
+char(3,26444).
+char(4,26445).
+char(2,26446).
+char(m,26447).
+char(o,26448).
+char(9,26449).
+char(1,26450).
+char(4,26451).
+char(1,26452).
+char(p,26453).
+char(o,26454).
+char(m,26455).
+char(o,26456).
+char(p,26457).
+char(9,26458).
+char(0,26459).
+char(6,26460).
+char(4,26461).
+char(p,26462).
+char(8,26463).
+char(8,26464).
+char(5,26465).
+char(3,26466).
+char(c,26467).
+char(m,26468).
+char(8,26469).
+char(3,26470).
+char(7,26471).
+char(9,26472).
+char(m,26473).
+char(5,26474).
+char(7,26475).
+char(9,26476).
+char(9,26477).
+char(m,26478).
+char(o,26479).
+char(p,26480).
+char(o,26481).
+char(m,26482).
+char(o,26483).
+char(o,26484).
+char(1,26485).
+char(9,26486).
+char(6,26487).
+char(5,26488).
+char(c,26489).
+char(p,26490).
+char(9,26491).
+char(9,26492).
+char(9,26493).
+char(2,26494).
+char(c,26495).
+char(m,26496).
+char(o,26497).
+char(p,26498).
+char(o,26499).
+char(p,26500).
+char(7,26501).
+char(2,26502).
+char(3,26503).
+char(3,26504).
+char(c,26505).
+char(c,26506).
+char(c,26507).
+char(c,26508).
+char(m,26509).
+char(o,26510).
+char(p,26511).
+char(7,26512).
+char(3,26513).
+char(9,26514).
+char(4,26515).
+char(m,26516).
+char(8,26517).
+char(8,26518).
+char(3,26519).
+char(6,26520).
+char(p,26521).
+char(6,26522).
+char(7,26523).
+char(0,26524).
+char(7,26525).
+char(c,26526).
+char(c,26527).
+char(p,26528).
+char(3,26529).
+char(4,26530).
+char(9,26531).
+char(c,26532).
+char(p,26533).
+char(3,26534).
+char(3,26535).
+char(9,26536).
+char(6,26537).
+char(c,26538).
+char(p,26539).
+char(o,26540).
+char(m,26541).
+char(o,26542).
+char(p,26543).
+char(o,26544).
+char(m,26545).
+char(7,26546).
+char(2,26547).
+char(9,26548).
+char(7,26549).
+char(c,26550).
+char(c,26551).
+char(p,26552).
+char(o,26553).
+char(p,26554).
+char(o,26555).
+char(o,26556).
+char(p,26557).
+char(8,26558).
+char(7,26559).
+char(7,26560).
+char(8,26561).
+char(m,26562).
+char(o,26563).
+char(p,26564).
+char(2,26565).
+char(1,26566).
+char(8,26567).
+char(3,26568).
+char(c,26569).
+char(c,26570).
+char(c,26571).
+char(c,26572).
+char(m,26573).
+char(1,26574).
+char(0,26575).
+char(1,26576).
+char(2,26577).
+char(m,26578).
+char(o,26579).
+char(p,26580).
+char(o,26581).
+char(p,26582).
+char(6,26583).
+char(8,26584).
+char(6,26585).
+char(9,26586).
+char(c,26587).
+char(c,26588).
+char(c,26589).
+char(p,26590).
+char(7,26591).
+char(3,26592).
+char(3,26593).
+char(1,26594).
+char(c,26595).
+char(m,26596).
+char(o,26597).
+char(m,26598).
+char(8,26599).
+char(9,26600).
+char(8,26601).
+char(c,26602).
+char(c,26603).
+char(c,26604).
+char(c,26605).
+char(p,26606).
+char(7,26607).
+char(0,26608).
+char(4,26609).
+char(6,26610).
+char(m,26611).
+char(3,26612).
+char(7,26613).
+char(1,26614).
+char(2,26615).
+char(m,26616).
+char(o,26617).
+char(m,26618).
+char(o,26619).
+char(p,26620).
+char(2,26621).
+char(6,26622).
+char(p,26623).
+char(o,26624).
+char(m,26625).
+char(o,26626).
+char(o,26627).
+char(m,26628).
+char(o,26629).
+char(p,26630).
+char(5,26631).
+char(0,26632).
+char(0,26633).
+char(2,26634).
+char(c,26635).
+char(m,26636).
+char(2,26637).
+char(0,26638).
+char(7,26639).
+char(1,26640).
+char(c,26641).
+char(m,26642).
+char(o,26643).
+char(p,26644).
+char(o,26645).
+char(6,26646).
+char(0,26647).
+char(6,26648).
+char(5,26649).
+char(m,26650).
+char(o,26651).
+char(p,26652).
+char(5,26653).
+char(2,26654).
+char(6,26655).
+char(1,26656).
+char(p,26657).
+char(o,26658).
+char(o,26659).
+char(6,26660).
+char(5,26661).
+char(6,26662).
+char(4,26663).
+char(p,26664).
+char(4,26665).
+char(5,26666).
+char(1,26667).
+char(3,26668).
+char(p,26669).
+char(9,26670).
+char(8,26671).
+char(4,26672).
+char(p,26673).
+char(o,26674).
+char(o,26675).
+char(9,26676).
+char(4,26677).
+char(2,26678).
+char(8,26679).
+char(m,26680).
+char(o,26681).
+char(p,26682).
+char(4,26683).
+char(4,26684).
+char(4,26685).
+char(2,26686).
+char(m,26687).
+char(o,26688).
+char(8,26689).
+char(9,26690).
+char(2,26691).
+char(m,26692).
+char(o,26693).
+char(m,26694).
+char(4,26695).
+char(4,26696).
+char(6,26697).
+char(2,26698).
+char(c,26699).
+char(p,26700).
+char(2,26701).
+char(6,26702).
+char(2,26703).
+char(1,26704).
+char(p,26705).
+char(8,26706).
+char(c,26707).
+char(c,26708).
+char(c,26709).
+char(m,26710).
+char(o,26711).
+char(m,26712).
+char(3,26713).
+char(4,26714).
+char(8,26715).
+char(2,26716).
+char(m,26717).
+char(o,26718).
+char(p,26719).
+char(o,26720).
+char(m,26721).
+char(2,26722).
+char(4,26723).
+char(4,26724).
+char(4,26725).
+char(p,26726).
+char(6,26727).
+char(9,26728).
+char(9,26729).
+char(9,26730).
+char(m,26731).
+char(o,26732).
+char(m,26733).
+char(o,26734).
+char(3,26735).
+char(5,26736).
+char(3,26737).
+char(5,26738).
+char(c,26739).
+char(p,26740).
+char(o,26741).
+char(o,26742).
+char(p,26743).
+char(o,26744).
+char(o,26745).
+char(6,26746).
+char(1,26747).
+char(8,26748).
+char(3,26749).
+char(p,26750).
+char(8,26751).
+char(8,26752).
+char(0,26753).
+char(4,26754).
+char(c,26755).
+char(c,26756).
+char(c,26757).
+char(m,26758).
+char(o,26759).
+char(m,26760).
+char(5,26761).
+char(9,26762).
+char(3,26763).
+char(8,26764).
+char(p,26765).
+char(6,26766).
+char(7,26767).
+char(0,26768).
+char(2,26769).
+char(p,26770).
+char(o,26771).
+char(p,26772).
+char(o,26773).
+char(p,26774).
+char(4,26775).
+char(3,26776).
+char(0,26777).
+char(3,26778).
+char(c,26779).
+char(c,26780).
+char(c,26781).
+char(p,26782).
+char(o,26783).
+char(8,26784).
+char(6,26785).
+char(6,26786).
+char(m,26787).
+char(7,26788).
+char(0,26789).
+char(7,26790).
+char(2,26791).
+char(c,26792).
+char(c,26793).
+char(c,26794).
+char(p,26795).
+char(5,26796).
+char(4,26797).
+char(6,26798).
+char(9,26799).
+char(m,26800).
+char(1,26801).
+char(5,26802).
+char(0,26803).
+char(0,26804).
+char(c,26805).
+char(m,26806).
+char(o,26807).
+char(p,26808).
+char(o,26809).
+char(p,26810).
+char(o,26811).
+char(p,26812).
+char(o,26813).
+char(o,26814).
+char(m,26815).
+char(2,26816).
+char(5,26817).
+char(9,26818).
+char(c,26819).
+char(p,26820).
+char(o,26821).
+char(m,26822).
+char(6,26823).
+char(0,26824).
+char(4,26825).
+char(0,26826).
+char(p,26827).
+char(5,26828).
+char(9,26829).
+char(0,26830).
+char(2,26831).
+char(p,26832).
+char(o,26833).
+char(m,26834).
+char(o,26835).
+char(m,26836).
+char(o,26837).
+char(1,26838).
+char(6,26839).
+char(7,26840).
+char(6,26841).
+char(p,26842).
+char(o,26843).
+char(o,26844).
+char(p,26845).
+char(o,26846).
+char(5,26847).
+char(9,26848).
+char(1,26849).
+char(8,26850).
+char(c,26851).
+char(p,26852).
+char(9,26853).
+char(4,26854).
+char(6,26855).
+char(5,26856).
+char(m,26857).
+char(1,26858).
+char(2,26859).
+char(6,26860).
+char(2,26861).
+char(m,26862).
+char(4,26863).
+char(7,26864).
+char(1,26865).
+char(8,26866).
+char(c,26867).
+char(m,26868).
+char(2,26869).
+char(0,26870).
+char(1,26871).
+char(4,26872).
+char(m,26873).
+char(o,26874).
+char(o,26875).
+char(p,26876).
+char(3,26877).
+char(6,26878).
+char(4,26879).
+char(7,26880).
+char(c,26881).
+char(m,26882).
+char(1,26883).
+char(4,26884).
+char(0,26885).
+char(3,26886).
+char(m,26887).
+char(4,26888).
+char(7,26889).
+char(1,26890).
+char(6,26891).
+char(m,26892).
+char(1,26893).
+char(1,26894).
+char(6,26895).
+char(6,26896).
+char(m,26897).
+char(o,26898).
+char(m,26899).
+char(6,26900).
+char(1,26901).
+char(3,26902).
+char(7,26903).
+char(p,26904).
+char(o,26905).
+char(m,26906).
+char(o,26907).
+char(o,26908).
+char(p,26909).
+char(o,26910).
+char(5,26911).
+char(1,26912).
+char(5,26913).
+char(5,26914).
+char(c,26915).
+char(p,26916).
+char(9,26917).
+char(2,26918).
+char(7,26919).
+char(5,26920).
+char(m,26921).
+char(o,26922).
+char(8,26923).
+char(1,26924).
+char(4,26925).
+char(0,26926).
+char(p,26927).
+char(5,26928).
+char(0,26929).
+char(2,26930).
+char(0,26931).
+char(m,26932).
+char(o,26933).
+char(m,26934).
+char(5,26935).
+char(5,26936).
+char(8,26937).
+char(2,26938).
+char(c,26939).
+char(c,26940).
+char(c,26941).
+char(c,26942).
+char(c,26943).
+char(c,26944).
+char(c,26945).
+char(c,26946).
+char(c,26947).
+char(c,26948).
+char(m,26949).
+char(6,26950).
+char(3,26951).
+char(3,26952).
+char(2,26953).
+char(c,26954).
+char(p,26955).
+char(4,26956).
+char(3,26957).
+char(5,26958).
+char(5,26959).
+char(c,26960).
+char(m,26961).
+char(4,26962).
+char(9,26963).
+char(8,26964).
+char(8,26965).
+char(m,26966).
+char(1,26967).
+char(6,26968).
+char(3,26969).
+char(0,26970).
+char(c,26971).
+char(p,26972).
+char(o,26973).
+char(2,26974).
+char(2,26975).
+char(8,26976).
+char(6,26977).
+char(c,26978).
+char(p,26979).
+char(2,26980).
+char(8,26981).
+char(8,26982).
+char(c,26983).
+char(m,26984).
+char(5,26985).
+char(8,26986).
+char(9,26987).
+char(2,26988).
+char(c,26989).
+char(c,26990).
+char(c,26991).
+char(p,26992).
+char(5,26993).
+char(6,26994).
+char(8,26995).
+char(7,26996).
+char(c,26997).
+char(p,26998).
+char(4,26999).
+char(1,27000).
+char(2,27001).
+char(5,27002).
+char(p,27003).
+char(8,27004).
+char(1,27005).
+char(9,27006).
+char(6,27007).
+char(m,27008).
+char(4,27009).
+char(1,27010).
+char(0,27011).
+char(5,27012).
+char(c,27013).
+char(c,27014).
+char(c,27015).
+char(c,27016).
+char(c,27017).
+char(c,27018).
+char(c,27019).
+char(c,27020).
+char(m,27021).
+char(o,27022).
+char(m,27023).
+char(o,27024).
+char(o,27025).
+char(o,27026).
+char(1,27027).
+char(8,27028).
+char(5,27029).
+char(2,27030).
+char(m,27031).
+char(o,27032).
+char(m,27033).
+char(3,27034).
+char(0,27035).
+char(2,27036).
+char(8,27037).
+char(c,27038).
+char(m,27039).
+char(3,27040).
+char(8,27041).
+char(9,27042).
+char(2,27043).
+char(c,27044).
+char(p,27045).
+char(9,27046).
+char(2,27047).
+char(6,27048).
+char(3,27049).
+char(p,27050).
+char(4,27051).
+char(3,27052).
+char(8,27053).
+char(3,27054).
+char(c,27055).
+char(p,27056).
+char(2,27057).
+char(0,27058).
+char(6,27059).
+char(8,27060).
+char(m,27061).
+char(o,27062).
+char(3,27063).
+char(8,27064).
+char(2,27065).
+char(5,27066).
+char(c,27067).
+char(c,27068).
+char(c,27069).
+char(c,27070).
+char(p,27071).
+char(2,27072).
+char(9,27073).
+char(0,27074).
+char(1,27075).
+char(c,27076).
+char(c,27077).
+char(c,27078).
+char(c,27079).
+char(c,27080).
+char(c,27081).
+char(m,27082).
+char(2,27083).
+char(6,27084).
+char(9,27085).
+char(3,27086).
+char(m,27087).
+char(o,27088).
+char(m,27089).
+char(o,27090).
+char(p,27091).
+char(o,27092).
+char(o,27093).
+char(o,27094).
+char(o,27095).
+char(1,27096).
+char(7,27097).
+char(2,27098).
+char(9,27099).
+char(c,27100).
+char(c,27101).
+char(c,27102).
+char(c,27103).
+char(p,27104).
+char(o,27105).
+char(5,27106).
+char(7,27107).
+char(8,27108).
+char(8,27109).
+char(c,27110).
+char(p,27111).
+char(3,27112).
+char(8,27113).
+char(4,27114).
+char(8,27115).
+char(p,27116).
+char(2,27117).
+char(5,27118).
+char(1,27119).
+char(0,27120).
+char(m,27121).
+char(o,27122).
+char(m,27123).
+char(4,27124).
+char(9,27125).
+char(8,27126).
+char(0,27127).
+char(c,27128).
+char(p,27129).
+char(o,27130).
+char(p,27131).
+char(7,27132).
+char(3,27133).
+char(2,27134).
+char(6,27135).
+char(p,27136).
+char(7,27137).
+char(8,27138).
+char(5,27139).
+char(4,27140).
+char(m,27141).
+char(3,27142).
+char(1,27143).
+char(8,27144).
+char(6,27145).
+char(c,27146).
+char(c,27147).
+char(m,27148).
+char(o,27149).
+char(m,27150).
+char(o,27151).
+char(p,27152).
+char(1,27153).
+char(7,27154).
+char(0,27155).
+char(5,27156).
+char(m,27157).
+char(o,27158).
+char(p,27159).
+char(3,27160).
+char(9,27161).
+char(0,27162).
+char(3,27163).
+char(c,27164).
+char(c,27165).
+char(p,27166).
+char(7,27167).
+char(2,27168).
+char(7,27169).
+char(8,27170).
+char(c,27171).
+char(c,27172).
+char(p,27173).
+char(3,27174).
+char(5,27175).
+char(8,27176).
+char(5,27177).
+char(p,27178).
+char(1,27179).
+char(1,27180).
+char(3,27181).
+char(2,27182).
+char(p,27183).
+char(o,27184).
+char(p,27185).
+char(o,27186).
+char(m,27187).
+char(2,27188).
+char(0,27189).
+char(6,27190).
+char(9,27191).
+char(p,27192).
+char(3,27193).
+char(9,27194).
+char(0,27195).
+char(8,27196).
+char(p,27197).
+char(o,27198).
+char(p,27199).
+char(o,27200).
+char(m,27201).
+char(1,27202).
+char(1,27203).
+char(7,27204).
+char(7,27205).
+char(c,27206).
+char(m,27207).
+char(o,27208).
+char(m,27209).
+char(3,27210).
+char(9,27211).
+char(6,27212).
+char(1,27213).
+char(c,27214).
+char(p,27215).
+char(o,27216).
+char(m,27217).
+char(o,27218).
+char(o,27219).
+char(6,27220).
+char(1,27221).
+char(9,27222).
+char(m,27223).
+char(o,27224).
+char(p,27225).
+char(7,27226).
+char(3,27227).
+char(2,27228).
+char(7,27229).
+char(p,27230).
+char(8,27231).
+char(1,27232).
+char(8,27233).
+char(9,27234).
+char(m,27235).
+char(o,27236).
+char(p,27237).
+char(3,27238).
+char(5,27239).
+char(4,27240).
+char(2,27241).
+char(m,27242).
+char(3,27243).
+char(7,27244).
+char(6,27245).
+char(3,27246).
+char(c,27247).
+char(p,27248).
+char(o,27249).
+char(m,27250).
+char(o,27251).
+char(m,27252).
+char(9,27253).
+char(3,27254).
+char(5,27255).
+char(9,27256).
+char(m,27257).
+char(1,27258).
+char(6,27259).
+char(6,27260).
+char(5,27261).
+char(p,27262).
+char(o,27263).
+char(p,27264).
+char(o,27265).
+char(m,27266).
+char(o,27267).
+char(o,27268).
+char(m,27269).
+char(5,27270).
+char(9,27271).
+char(3,27272).
+char(7,27273).
+char(c,27274).
+char(c,27275).
+char(p,27276).
+char(o,27277).
+char(p,27278).
+char(1,27279).
+char(7,27280).
+char(0,27281).
+char(3,27282).
+char(p,27283).
+char(o,27284).
+char(p,27285).
+char(9,27286).
+char(5,27287).
+char(2,27288).
+char(1,27289).
+char(c,27290).
+char(c,27291).
+char(p,27292).
+char(2,27293).
+char(9,27294).
+char(8,27295).
+char(5,27296).
+char(c,27297).
+char(m,27298).
+char(1,27299).
+char(5,27300).
+char(5,27301).
+char(9,27302).
+char(p,27303).
+char(9,27304).
+char(9,27305).
+char(1,27306).
+char(1,27307).
+char(c,27308).
+char(m,27309).
+char(6,27310).
+char(2,27311).
+char(5,27312).
+char(2,27313).
+char(p,27314).
+char(7,27315).
+char(0,27316).
+char(3,27317).
+char(9,27318).
+char(p,27319).
+char(6,27320).
+char(0,27321).
+char(9,27322).
+char(p,27323).
+char(o,27324).
+char(o,27325).
+char(p,27326).
+char(8,27327).
+char(1,27328).
+char(9,27329).
+char(2,27330).
+char(p,27331).
+char(6,27332).
+char(4,27333).
+char(3,27334).
+char(1,27335).
+char(c,27336).
+char(c,27337).
+char(c,27338).
+char(p,27339).
+char(o,27340).
+char(3,27341).
+char(9,27342).
+char(6,27343).
+char(c,27344).
+char(p,27345).
+char(o,27346).
+char(m,27347).
+char(o,27348).
+char(2,27349).
+char(2,27350).
+char(3,27351).
+char(9,27352).
+char(m,27353).
+char(o,27354).
+char(8,27355).
+char(0,27356).
+char(5,27357).
+char(5,27358).
+char(c,27359).
+char(m,27360).
+char(o,27361).
+char(o,27362).
+char(p,27363).
+char(9,27364).
+char(8,27365).
+char(7,27366).
+char(3,27367).
+char(m,27368).
+char(o,27369).
+char(o,27370).
+char(p,27371).
+char(o,27372).
+char(p,27373).
+char(o,27374).
+char(7,27375).
+char(0,27376).
+char(6,27377).
+char(7,27378).
+char(m,27379).
+char(o,27380).
+char(p,27381).
+char(3,27382).
+char(9,27383).
+char(3,27384).
+char(5,27385).
+char(c,27386).
+char(p,27387).
+char(5,27388).
+char(2,27389).
+char(0,27390).
+char(3,27391).
+char(p,27392).
+char(6,27393).
+char(7,27394).
+char(8,27395).
+char(1,27396).
+char(c,27397).
+char(c,27398).
+char(c,27399).
+char(c,27400).
+char(c,27401).
+char(c,27402).
+char(m,27403).
+char(7,27404).
+char(9,27405).
+char(4,27406).
+char(0,27407).
+char(m,27408).
+char(1,27409).
+char(8,27410).
+char(2,27411).
+char(5,27412).
+char(c,27413).
+char(c,27414).
+char(p,27415).
+char(o,27416).
+char(m,27417).
+char(o,27418).
+char(o,27419).
+char(m,27420).
+char(o,27421).
+char(p,27422).
+char(o,27423).
+char(m,27424).
+char(6,27425).
+char(9,27426).
+char(0,27427).
+char(8,27428).
+char(m,27429).
+char(6,27430).
+char(0,27431).
+char(6,27432).
+char(3,27433).
+char(c,27434).
+char(m,27435).
+char(4,27436).
+char(5,27437).
+char(0,27438).
+char(3,27439).
+char(c,27440).
+char(c,27441).
+char(c,27442).
+char(c,27443).
+char(p,27444).
+char(1,27445).
+char(0,27446).
+char(c,27447).
+char(c,27448).
+char(p,27449).
+char(3,27450).
+char(8,27451).
+char(1,27452).
+char(9,27453).
+char(c,27454).
+char(m,27455).
+char(o,27456).
+char(p,27457).
+char(8,27458).
+char(9,27459).
+char(1,27460).
+char(0,27461).
+char(m,27462).
+char(o,27463).
+char(m,27464).
+char(o,27465).
+char(p,27466).
+char(o,27467).
+char(5,27468).
+char(7,27469).
+char(5,27470).
+char(2,27471).
+char(p,27472).
+char(6,27473).
+char(4,27474).
+char(3,27475).
+char(8,27476).
+char(m,27477).
+char(o,27478).
+char(m,27479).
+char(3,27480).
+char(4,27481).
+char(c,27482).
+char(m,27483).
+char(6,27484).
+char(5,27485).
+char(4,27486).
+char(0,27487).
+char(c,27488).
+char(m,27489).
+char(o,27490).
+char(o,27491).
+char(o,27492).
+char(p,27493).
+char(4,27494).
+char(3,27495).
+char(5,27496).
+char(4,27497).
+char(c,27498).
+char(p,27499).
+char(o,27500).
+char(m,27501).
+char(9,27502).
+char(1,27503).
+char(8,27504).
+char(4,27505).
+char(m,27506).
+char(9,27507).
+char(3,27508).
+char(0,27509).
+char(1,27510).
+char(c,27511).
+char(c,27512).
+char(m,27513).
+char(o,27514).
+char(9,27515).
+char(2,27516).
+char(8,27517).
+char(9,27518).
+char(c,27519).
+char(c,27520).
+char(m,27521).
+char(o,27522).
+char(m,27523).
+char(o,27524).
+char(p,27525).
+char(1,27526).
+char(3,27527).
+char(8,27528).
+char(6,27529).
+char(p,27530).
+char(o,27531).
+char(m,27532).
+char(8,27533).
+char(7,27534).
+char(3,27535).
+char(0,27536).
+char(c,27537).
+char(m,27538).
+char(o,27539).
+char(m,27540).
+char(o,27541).
+char(m,27542).
+char(o,27543).
+char(m,27544).
+char(3,27545).
+char(9,27546).
+char(1,27547).
+char(4,27548).
+char(m,27549).
+char(o,27550).
+char(p,27551).
+char(o,27552).
+char(9,27553).
+char(5,27554).
+char(1,27555).
+char(6,27556).
+char(c,27557).
+char(m,27558).
+char(o,27559).
+char(2,27560).
+char(5,27561).
+char(0,27562).
+char(7,27563).
+char(c,27564).
+char(p,27565).
+char(o,27566).
+char(p,27567).
+char(5,27568).
+char(9,27569).
+char(7,27570).
+char(4,27571).
+char(c,27572).
+char(p,27573).
+char(o,27574).
+char(m,27575).
+char(o,27576).
+char(p,27577).
+char(o,27578).
+char(p,27579).
+char(8,27580).
+char(7,27581).
+char(2,27582).
+char(4,27583).
+char(c,27584).
+char(c,27585).
+char(m,27586).
+char(o,27587).
+char(o,27588).
+char(m,27589).
+char(1,27590).
+char(3,27591).
+char(7,27592).
+char(7,27593).
+char(m,27594).
+char(3,27595).
+char(1,27596).
+char(8,27597).
+char(3,27598).
+char(c,27599).
+char(c,27600).
+char(c,27601).
+char(p,27602).
+char(o,27603).
+char(o,27604).
+char(p,27605).
+char(9,27606).
+char(7,27607).
+char(1,27608).
+char(6,27609).
+char(p,27610).
+char(3,27611).
+char(7,27612).
+char(2,27613).
+char(0,27614).
+char(c,27615).
+char(p,27616).
+char(1,27617).
+char(8,27618).
+char(4,27619).
+char(3,27620).
+char(c,27621).
+char(p,27622).
+char(4,27623).
+char(9,27624).
+char(7,27625).
+char(4,27626).
+char(c,27627).
+char(p,27628).
+char(3,27629).
+char(7,27630).
+char(0,27631).
+char(c,27632).
+char(c,27633).
+char(c,27634).
+char(p,27635).
+char(3,27636).
+char(2,27637).
+char(9,27638).
+char(3,27639).
+char(c,27640).
+char(c,27641).
+char(p,27642).
+char(o,27643).
+char(m,27644).
+char(1,27645).
+char(2,27646).
+char(2,27647).
+char(9,27648).
+char(c,27649).
+char(c,27650).
+char(c,27651).
+char(c,27652).
+char(c,27653).
+char(c,27654).
+char(c,27655).
+char(c,27656).
+char(m,27657).
+char(7,27658).
+char(9,27659).
+char(8,27660).
+char(0,27661).
+char(c,27662).
+char(c,27663).
+char(c,27664).
+char(c,27665).
+char(c,27666).
+char(p,27667).
+char(1,27668).
+char(2,27669).
+char(6,27670).
+char(4,27671).
+char(m,27672).
+char(o,27673).
+char(5,27674).
+char(7,27675).
+char(7,27676).
+char(6,27677).
+char(c,27678).
+char(c,27679).
+char(c,27680).
+char(c,27681).
+char(c,27682).
+char(c,27683).
+char(c,27684).
+char(m,27685).
+char(2,27686).
+char(9,27687).
+char(1,27688).
+char(8,27689).
+char(p,27690).
+char(2,27691).
+char(1,27692).
+char(0,27693).
+char(4,27694).
+char(c,27695).
+char(c,27696).
+char(m,27697).
+char(o,27698).
+char(p,27699).
+char(o,27700).
+char(p,27701).
+char(o,27702).
+char(o,27703).
+char(6,27704).
+char(8,27705).
+char(6,27706).
+char(4,27707).
+char(p,27708).
+char(o,27709).
+char(m,27710).
+char(o,27711).
+char(o,27712).
+char(5,27713).
+char(9,27714).
+char(7,27715).
+char(8,27716).
+char(c,27717).
+char(m,27718).
+char(o,27719).
+char(p,27720).
+char(o,27721).
+char(p,27722).
+char(o,27723).
+char(m,27724).
+char(6,27725).
+char(1,27726).
+char(3,27727).
+char(c,27728).
+char(m,27729).
+char(o,27730).
+char(8,27731).
+char(6,27732).
+char(2,27733).
+char(m,27734).
+char(o,27735).
+char(o,27736).
+char(p,27737).
+char(o,27738).
+char(7,27739).
+char(4,27740).
+char(0,27741).
+char(1,27742).
+char(m,27743).
+char(o,27744).
+char(m,27745).
+char(o,27746).
+char(8,27747).
+char(0,27748).
+char(0,27749).
+char(0,27750).
+char(m,27751).
+char(9,27752).
+char(3,27753).
+char(4,27754).
+char(8,27755).
+char(c,27756).
+char(p,27757).
+char(o,27758).
+char(6,27759).
+char(0,27760).
+char(2,27761).
+char(3,27762).
+char(m,27763).
+char(1,27764).
+char(6,27765).
+char(6,27766).
+char(1,27767).
+char(c,27768).
+char(c,27769).
+char(c,27770).
+char(c,27771).
+char(c,27772).
+char(c,27773).
+char(c,27774).
+char(c,27775).
+char(p,27776).
+char(o,27777).
+char(6,27778).
+char(8,27779).
+char(0,27780).
+char(3,27781).
+char(c,27782).
+char(p,27783).
+char(3,27784).
+char(4,27785).
+char(0,27786).
+char(1,27787).
+char(p,27788).
+char(o,27789).
+char(p,27790).
+char(5,27791).
+char(7,27792).
+char(9,27793).
+char(6,27794).
+char(m,27795).
+char(o,27796).
+char(p,27797).
+char(o,27798).
+char(7,27799).
+char(7,27800).
+char(2,27801).
+char(2,27802).
+char(c,27803).
+char(c,27804).
+char(p,27805).
+char(o,27806).
+char(m,27807).
+char(o,27808).
+char(8,27809).
+char(8,27810).
+char(5,27811).
+char(9,27812).
+char(m,27813).
+char(o,27814).
+char(m,27815).
+char(o,27816).
+char(o,27817).
+char(m,27818).
+char(6,27819).
+char(3,27820).
+char(8,27821).
+char(9,27822).
+char(c,27823).
+char(c,27824).
+char(c,27825).
+char(p,27826).
+char(9,27827).
+char(1,27828).
+char(7,27829).
+char(7,27830).
+char(m,27831).
+char(9,27832).
+char(6,27833).
+char(8,27834).
+char(7,27835).
+char(m,27836).
+char(o,27837).
+char(p,27838).
+char(o,27839).
+char(o,27840).
+char(p,27841).
+char(o,27842).
+char(p,27843).
+char(3,27844).
+char(1,27845).
+char(1,27846).
+char(7,27847).
+char(c,27848).
+char(c,27849).
+char(m,27850).
+char(7,27851).
+char(5,27852).
+char(8,27853).
+char(6,27854).
+char(c,27855).
+char(m,27856).
+char(1,27857).
+char(3,27858).
+char(2,27859).
+char(4,27860).
+char(c,27861).
+char(p,27862).
+char(7,27863).
+char(0,27864).
+char(1,27865).
+char(0,27866).
+char(c,27867).
+char(m,27868).
+char(3,27869).
+char(4,27870).
+char(4,27871).
+char(8,27872).
+char(p,27873).
+char(1,27874).
+char(8,27875).
+char(9,27876).
+char(1,27877).
+char(c,27878).
+char(c,27879).
+char(p,27880).
+char(o,27881).
+char(m,27882).
+char(9,27883).
+char(6,27884).
+char(1,27885).
+char(6,27886).
+char(m,27887).
+char(o,27888).
+char(p,27889).
+char(7,27890).
+char(8,27891).
+char(m,27892).
+char(o,27893).
+char(p,27894).
+char(8,27895).
+char(6,27896).
+char(0,27897).
+char(9,27898).
+char(m,27899).
+char(o,27900).
+char(o,27901).
+char(p,27902).
+char(o,27903).
+char(p,27904).
+char(o,27905).
+char(p,27906).
+char(4,27907).
+char(2,27908).
+char(5,27909).
+char(1,27910).
+char(m,27911).
+char(2,27912).
+char(1,27913).
+char(8,27914).
+char(2,27915).
+char(p,27916).
+char(o,27917).
+char(m,27918).
+char(o,27919).
+char(m,27920).
+char(3,27921).
+char(4,27922).
+char(5,27923).
+char(m,27924).
+char(o,27925).
+char(o,27926).
+char(p,27927).
+char(4,27928).
+char(3,27929).
+char(1,27930).
+char(1,27931).
+char(c,27932).
+char(c,27933).
+char(m,27934).
+char(o,27935).
+char(m,27936).
+char(6,27937).
+char(2,27938).
+char(4,27939).
+char(c,27940).
+char(c,27941).
+char(m,27942).
+char(7,27943).
+char(8,27944).
+char(5,27945).
+char(2,27946).
+char(c,27947).
+char(c,27948).
+char(m,27949).
+char(7,27950).
+char(5,27951).
+char(7,27952).
+char(0,27953).
+char(c,27954).
+char(m,27955).
+char(9,27956).
+char(5,27957).
+char(9,27958).
+char(3,27959).
+char(p,27960).
+char(o,27961).
+char(p,27962).
+char(o,27963).
+char(o,27964).
+char(p,27965).
+char(1,27966).
+char(7,27967).
+char(5,27968).
+char(8,27969).
+char(p,27970).
+char(o,27971).
+char(p,27972).
+char(o,27973).
+char(p,27974).
+char(2,27975).
+char(0,27976).
+char(2,27977).
+char(2,27978).
+char(c,27979).
+char(m,27980).
+char(o,27981).
+char(1,27982).
+char(1,27983).
+char(1,27984).
+char(4,27985).
+char(p,27986).
+char(o,27987).
+char(m,27988).
+char(7,27989).
+char(4,27990).
+char(5,27991).
+char(9,27992).
+char(c,27993).
+char(p,27994).
+char(5,27995).
+char(3,27996).
+char(7,27997).
+char(9,27998).
+char(m,27999).
+char(o,28000).
+char(5,28001).
+char(7,28002).
+char(5,28003).
+char(8,28004).
+char(m,28005).
+char(9,28006).
+char(2,28007).
+char(5,28008).
+char(8,28009).
+char(c,28010).
+char(c,28011).
+char(p,28012).
+char(8,28013).
+char(6,28014).
+char(4,28015).
+char(0,28016).
+char(c,28017).
+char(p,28018).
+char(6,28019).
+char(3,28020).
+char(9,28021).
+char(6,28022).
+char(c,28023).
+char(p,28024).
+char(o,28025).
+char(o,28026).
+char(o,28027).
+char(m,28028).
+char(3,28029).
+char(9,28030).
+char(4,28031).
+char(1,28032).
+char(c,28033).
+char(c,28034).
+char(m,28035).
+char(o,28036).
+char(m,28037).
+char(o,28038).
+char(m,28039).
+char(9,28040).
+char(4,28041).
+char(5,28042).
+char(3,28043).
+char(p,28044).
+char(1,28045).
+char(1,28046).
+char(2,28047).
+char(5,28048).
+char(m,28049).
+char(o,28050).
+char(o,28051).
+char(m,28052).
+char(7,28053).
+char(8,28054).
+char(6,28055).
+char(1,28056).
+char(c,28057).
+char(m,28058).
+char(o,28059).
+char(o,28060).
+char(m,28061).
+char(6,28062).
+char(1,28063).
+char(7,28064).
+char(1,28065).
+char(c,28066).
+char(c,28067).
+char(m,28068).
+char(4,28069).
+char(7,28070).
+char(5,28071).
+char(0,28072).
+char(m,28073).
+char(8,28074).
+char(2,28075).
+char(6,28076).
+char(4,28077).
+char(c,28078).
+char(c,28079).
+char(c,28080).
+char(c,28081).
+char(c,28082).
+char(p,28083).
+char(o,28084).
+char(p,28085).
+char(o,28086).
+char(p,28087).
+char(o,28088).
+char(p,28089).
+char(7,28090).
+char(0,28091).
+char(5,28092).
+char(c,28093).
+char(c,28094).
+char(c,28095).
+char(c,28096).
+char(c,28097).
+char(c,28098).
+char(p,28099).
+char(o,28100).
+char(m,28101).
+char(7,28102).
+char(5,28103).
+char(4,28104).
+char(6,28105).
+char(p,28106).
+char(1,28107).
+char(7,28108).
+char(4,28109).
+char(5,28110).
+char(c,28111).
+char(c,28112).
+char(m,28113).
+char(1,28114).
+char(1,28115).
+char(9,28116).
+char(5,28117).
+char(m,28118).
+char(o,28119).
+char(p,28120).
+char(5,28121).
+char(1,28122).
+char(3,28123).
+char(6,28124).
+char(p,28125).
+char(3,28126).
+char(3,28127).
+char(8,28128).
+char(2,28129).
+char(m,28130).
+char(2,28131).
+char(3,28132).
+char(6,28133).
+char(7,28134).
+char(p,28135).
+char(7,28136).
+char(2,28137).
+char(5,28138).
+char(9,28139).
+char(p,28140).
+char(o,28141).
+char(m,28142).
+char(4,28143).
+char(2,28144).
+char(6,28145).
+char(8,28146).
+char(p,28147).
+char(9,28148).
+char(1,28149).
+char(9,28150).
+char(9,28151).
+char(p,28152).
+char(o,28153).
+char(m,28154).
+char(9,28155).
+char(5,28156).
+char(6,28157).
+char(4,28158).
+char(m,28159).
+char(o,28160).
+char(p,28161).
+char(o,28162).
+char(9,28163).
+char(3,28164).
+char(2,28165).
+char(4,28166).
+char(c,28167).
+char(c,28168).
+char(p,28169).
+char(9,28170).
+char(0,28171).
+char(6,28172).
+char(m,28173).
+char(o,28174).
+char(p,28175).
+char(5,28176).
+char(6,28177).
+char(8,28178).
+char(4,28179).
+char(c,28180).
+char(c,28181).
+char(c,28182).
+char(m,28183).
+char(7,28184).
+char(1,28185).
+char(9,28186).
+char(5,28187).
+char(p,28188).
+char(o,28189).
+char(p,28190).
+char(9,28191).
+char(7,28192).
+char(5,28193).
+char(8,28194).
+char(c,28195).
+char(m,28196).
+char(7,28197).
+char(3,28198).
+char(7,28199).
+char(7,28200).
+char(p,28201).
+char(7,28202).
+char(3,28203).
+char(8,28204).
+char(1,28205).
+char(m,28206).
+char(o,28207).
+char(6,28208).
+char(1,28209).
+char(0,28210).
+char(1,28211).
+char(m,28212).
+char(7,28213).
+char(9,28214).
+char(8,28215).
+char(3,28216).
+char(c,28217).
+char(c,28218).
+char(c,28219).
+char(c,28220).
+char(m,28221).
+char(2,28222).
+char(2,28223).
+char(1,28224).
+char(7,28225).
+char(p,28226).
+char(o,28227).
+char(o,28228).
+char(6,28229).
+char(3,28230).
+char(8,28231).
+char(4,28232).
+char(c,28233).
+char(c,28234).
+char(c,28235).
+char(c,28236).
+char(m,28237).
+char(8,28238).
+char(0,28239).
+char(2,28240).
+char(m,28241).
+char(2,28242).
+char(0,28243).
+char(2,28244).
+char(c,28245).
+char(m,28246).
+char(o,28247).
+char(5,28248).
+char(1,28249).
+char(3,28250).
+char(2,28251).
+char(c,28252).
+char(p,28253).
+char(8,28254).
+char(3,28255).
+char(2,28256).
+char(p,28257).
+char(o,28258).
+char(m,28259).
+char(6,28260).
+char(7,28261).
+char(2,28262).
+char(2,28263).
+char(m,28264).
+char(8,28265).
+char(2,28266).
+char(5,28267).
+char(7,28268).
+char(c,28269).
+char(m,28270).
+char(o,28271).
+char(m,28272).
+char(6,28273).
+char(4,28274).
+char(5,28275).
+char(5,28276).
+char(c,28277).
+char(p,28278).
+char(o,28279).
+char(p,28280).
+char(9,28281).
+char(4,28282).
+char(2,28283).
+char(4,28284).
+char(c,28285).
+char(p,28286).
+char(5,28287).
+char(0,28288).
+char(7,28289).
+char(3,28290).
+char(p,28291).
+char(3,28292).
+char(3,28293).
+char(9,28294).
+char(1,28295).
+char(c,28296).
+char(c,28297).
+char(m,28298).
+char(o,28299).
+char(m,28300).
+char(2,28301).
+char(5,28302).
+char(3,28303).
+char(4,28304).
+char(m,28305).
+char(o,28306).
+char(1,28307).
+char(0,28308).
+char(4,28309).
+char(2,28310).
+char(c,28311).
+char(p,28312).
+char(9,28313).
+char(5,28314).
+char(5,28315).
+char(1,28316).
+char(c,28317).
+char(p,28318).
+char(4,28319).
+char(5,28320).
+char(6,28321).
+char(4,28322).
+char(p,28323).
+char(6,28324).
+char(9,28325).
+char(6,28326).
+char(7,28327).
+char(c,28328).
+char(m,28329).
+char(7,28330).
+char(0,28331).
+char(9,28332).
+char(3,28333).
+char(p,28334).
+char(o,28335).
+char(2,28336).
+char(1,28337).
+char(4,28338).
+char(8,28339).
+char(c,28340).
+char(c,28341).
+char(m,28342).
+char(o,28343).
+char(m,28344).
+char(6,28345).
+char(4,28346).
+char(7,28347).
+char(8,28348).
+char(p,28349).
+char(o,28350).
+char(3,28351).
+char(3,28352).
+char(0,28353).
+char(p,28354).
+char(9,28355).
+char(1,28356).
+char(7,28357).
+char(5,28358).
+char(m,28359).
+char(o,28360).
+char(2,28361).
+char(9,28362).
+char(2,28363).
+char(8,28364).
+char(p,28365).
+char(5,28366).
+char(0,28367).
+char(7,28368).
+char(5,28369).
+char(c,28370).
+char(c,28371).
+char(p,28372).
+char(o,28373).
+char(m,28374).
+char(2,28375).
+char(6,28376).
+char(8,28377).
+char(9,28378).
+char(p,28379).
+char(9,28380).
+char(5,28381).
+char(5,28382).
+char(9,28383).
+char(p,28384).
+char(o,28385).
+char(o,28386).
+char(o,28387).
+char(m,28388).
+char(6,28389).
+char(3,28390).
+char(2,28391).
+char(m,28392).
+char(6,28393).
+char(7,28394).
+char(4,28395).
+char(9,28396).
+char(p,28397).
+char(o,28398).
+char(2,28399).
+char(5,28400).
+char(4,28401).
+char(6,28402).
+char(p,28403).
+char(o,28404).
+char(p,28405).
+char(o,28406).
+char(p,28407).
+char(2,28408).
+char(3,28409).
+char(2,28410).
+char(6,28411).
+char(m,28412).
+char(8,28413).
+char(0,28414).
+char(3,28415).
+char(p,28416).
+char(1,28417).
+char(7,28418).
+char(1,28419).
+char(7,28420).
+char(m,28421).
+char(o,28422).
+char(m,28423).
+char(o,28424).
+char(m,28425).
+char(5,28426).
+char(5,28427).
+char(7,28428).
+char(0,28429).
+char(m,28430).
+char(o,28431).
+char(m,28432).
+char(o,28433).
+char(3,28434).
+char(9,28435).
+char(9,28436).
+char(7,28437).
+char(m,28438).
+char(o,28439).
+char(o,28440).
+char(m,28441).
+char(o,28442).
+char(9,28443).
+char(9,28444).
+char(5,28445).
+char(7,28446).
+char(c,28447).
+char(c,28448).
+char(m,28449).
+char(9,28450).
+char(0,28451).
+char(5,28452).
+char(c,28453).
+char(m,28454).
+char(4,28455).
+char(5,28456).
+char(4,28457).
+char(4,28458).
+char(c,28459).
+char(c,28460).
+char(c,28461).
+char(c,28462).
+char(m,28463).
+char(o,28464).
+char(4,28465).
+char(6,28466).
+char(9,28467).
+char(9,28468).
+char(c,28469).
+char(m,28470).
+char(o,28471).
+char(p,28472).
+char(4,28473).
+char(1,28474).
+char(1,28475).
+char(8,28476).
+char(m,28477).
+char(1,28478).
+char(5,28479).
+char(1,28480).
+char(1,28481).
+char(c,28482).
+char(p,28483).
+char(3,28484).
+char(4,28485).
+char(0,28486).
+char(4,28487).
+char(c,28488).
+char(m,28489).
+char(4,28490).
+char(3,28491).
+char(5,28492).
+char(0,28493).
+char(c,28494).
+char(m,28495).
+char(o,28496).
+char(1,28497).
+char(2,28498).
+char(7,28499).
+char(2,28500).
+char(c,28501).
+char(c,28502).
+char(c,28503).
+char(c,28504).
+char(c,28505).
+char(c,28506).
+char(p,28507).
+char(o,28508).
+char(p,28509).
+char(o,28510).
+char(o,28511).
+char(m,28512).
+char(5,28513).
+char(7,28514).
+char(4,28515).
+char(3,28516).
+char(c,28517).
+char(c,28518).
+char(m,28519).
+char(4,28520).
+char(6,28521).
+char(9,28522).
+char(1,28523).
+char(c,28524).
+char(c,28525).
+char(p,28526).
+char(8,28527).
+char(3,28528).
+char(4,28529).
+char(4,28530).
+char(c,28531).
+char(c,28532).
+char(m,28533).
+char(o,28534).
+char(p,28535).
+char(o,28536).
+char(o,28537).
+char(p,28538).
+char(o,28539).
+char(p,28540).
+char(o,28541).
+char(7,28542).
+char(4,28543).
+char(0,28544).
+char(8,28545).
+char(p,28546).
+char(3,28547).
+char(2,28548).
+char(1,28549).
+char(0,28550).
+char(p,28551).
+char(2,28552).
+char(4,28553).
+char(3,28554).
+char(2,28555).
+char(c,28556).
+char(p,28557).
+char(3,28558).
+char(2,28559).
+char(3,28560).
+char(5,28561).
+char(p,28562).
+char(1,28563).
+char(6,28564).
+char(1,28565).
+char(0,28566).
+char(c,28567).
+char(m,28568).
+char(o,28569).
+char(o,28570).
+char(o,28571).
+char(5,28572).
+char(2,28573).
+char(6,28574).
+char(1,28575).
+char(c,28576).
+char(m,28577).
+char(4,28578).
+char(0,28579).
+char(6,28580).
+char(9,28581).
+char(c,28582).
+char(c,28583).
+char(p,28584).
+char(o,28585).
+char(o,28586).
+char(5,28587).
+char(7,28588).
+char(2,28589).
+char(7,28590).
+char(m,28591).
+char(o,28592).
+char(p,28593).
+char(1,28594).
+char(1,28595).
+char(3,28596).
+char(0,28597).
+char(m,28598).
+char(7,28599).
+char(2,28600).
+char(1,28601).
+char(8,28602).
+char(m,28603).
+char(9,28604).
+char(7,28605).
+char(2,28606).
+char(2,28607).
+char(p,28608).
+char(o,28609).
+char(2,28610).
+char(8,28611).
+char(7,28612).
+char(0,28613).
+char(p,28614).
+char(o,28615).
+char(5,28616).
+char(0,28617).
+char(6,28618).
+char(5,28619).
+char(m,28620).
+char(o,28621).
+char(p,28622).
+char(o,28623).
+char(o,28624).
+char(8,28625).
+char(2,28626).
+char(3,28627).
+char(4,28628).
+char(m,28629).
+char(o,28630).
+char(m,28631).
+char(o,28632).
+char(o,28633).
+char(m,28634).
+char(4,28635).
+char(5,28636).
+char(6,28637).
+char(6,28638).
+char(m,28639).
+char(o,28640).
+char(5,28641).
+char(9,28642).
+char(3,28643).
+char(1,28644).
+char(m,28645).
+char(8,28646).
+char(5,28647).
+char(7,28648).
+char(3,28649).
+char(m,28650).
+char(o,28651).
+char(2,28652).
+char(7,28653).
+char(5,28654).
+char(7,28655).
+char(m,28656).
+char(o,28657).
+char(o,28658).
+char(p,28659).
+char(7,28660).
+char(4,28661).
+char(8,28662).
+char(9,28663).
+char(c,28664).
+char(m,28665).
+char(o,28666).
+char(p,28667).
+char(9,28668).
+char(9,28669).
+char(9,28670).
+char(0,28671).
+char(c,28672).
+char(p,28673).
+char(o,28674).
+char(7,28675).
+char(3,28676).
+char(1,28677).
+char(3,28678).
+char(p,28679).
+char(3,28680).
+char(3,28681).
+char(3,28682).
+char(3,28683).
+char(p,28684).
+char(5,28685).
+char(2,28686).
+char(2,28687).
+char(2,28688).
+char(m,28689).
+char(o,28690).
+char(p,28691).
+char(o,28692).
+char(o,28693).
+char(7,28694).
+char(0,28695).
+char(8,28696).
+char(0,28697).
+char(p,28698).
+char(o,28699).
+char(o,28700).
+char(p,28701).
+char(9,28702).
+char(0,28703).
+char(8,28704).
+char(5,28705).
+char(m,28706).
+char(6,28707).
+char(4,28708).
+char(9,28709).
+char(1,28710).
+char(m,28711).
+char(9,28712).
+char(3,28713).
+char(0,28714).
+char(2,28715).
+char(p,28716).
+char(o,28717).
+char(8,28718).
+char(1,28719).
+char(6,28720).
+char(7,28721).
+char(c,28722).
+char(c,28723).
+char(m,28724).
+char(o,28725).
+char(p,28726).
+char(o,28727).
+char(p,28728).
+char(o,28729).
+char(6,28730).
+char(9,28731).
+char(8,28732).
+char(c,28733).
+char(m,28734).
+char(o,28735).
+char(m,28736).
+char(7,28737).
+char(6,28738).
+char(2,28739).
+char(5,28740).
+char(c,28741).
+char(c,28742).
+char(m,28743).
+char(5,28744).
+char(1,28745).
+char(8,28746).
+char(c,28747).
+char(p,28748).
+char(o,28749).
+char(m,28750).
+char(o,28751).
+char(8,28752).
+char(5,28753).
+char(6,28754).
+char(5,28755).
+char(c,28756).
+char(p,28757).
+char(o,28758).
+char(m,28759).
+char(o,28760).
+char(p,28761).
+char(o,28762).
+char(p,28763).
+char(6,28764).
+char(5,28765).
+char(6,28766).
+char(p,28767).
+char(6,28768).
+char(8,28769).
+char(7,28770).
+char(6,28771).
+char(c,28772).
+char(m,28773).
+char(8,28774).
+char(4,28775).
+char(4,28776).
+char(2,28777).
+char(m,28778).
+char(6,28779).
+char(1,28780).
+char(3,28781).
+char(p,28782).
+char(o,28783).
+char(2,28784).
+char(8,28785).
+char(1,28786).
+char(3,28787).
+char(p,28788).
+char(o,28789).
+char(2,28790).
+char(4,28791).
+char(3,28792).
+char(0,28793).
+char(p,28794).
+char(o,28795).
+char(m,28796).
+char(o,28797).
+char(4,28798).
+char(8,28799).
+char(3,28800).
+char(7,28801).
+char(c,28802).
+char(p,28803).
+char(o,28804).
+char(9,28805).
+char(7,28806).
+char(7,28807).
+char(8,28808).
+char(c,28809).
+char(p,28810).
+char(o,28811).
+char(m,28812).
+char(o,28813).
+char(p,28814).
+char(7,28815).
+char(3,28816).
+char(3,28817).
+char(m,28818).
+char(o,28819).
+char(4,28820).
+char(5,28821).
+char(5,28822).
+char(7,28823).
+char(c,28824).
+char(m,28825).
+char(o,28826).
+char(p,28827).
+char(8,28828).
+char(7,28829).
+char(5,28830).
+char(0,28831).
+char(c,28832).
+char(m,28833).
+char(2,28834).
+char(8,28835).
+char(6,28836).
+char(9,28837).
+char(p,28838).
+char(o,28839).
+char(m,28840).
+char(8,28841).
+char(8,28842).
+char(3,28843).
+char(9,28844).
+char(c,28845).
+char(c,28846).
+char(m,28847).
+char(8,28848).
+char(5,28849).
+char(0,28850).
+char(6,28851).
+char(c,28852).
+char(c,28853).
+char(p,28854).
+char(o,28855).
+char(m,28856).
+char(o,28857).
+char(6,28858).
+char(6,28859).
+char(0,28860).
+char(3,28861).
+char(p,28862).
+char(o,28863).
+char(o,28864).
+char(p,28865).
+char(5,28866).
+char(6,28867).
+char(1,28868).
+char(0,28869).
+char(p,28870).
+char(o,28871).
+char(o,28872).
+char(p,28873).
+char(o,28874).
+char(m,28875).
+char(o,28876).
+char(p,28877).
+char(o,28878).
+char(6,28879).
+char(8,28880).
+char(1,28881).
+char(m,28882).
+char(2,28883).
+char(7,28884).
+char(0,28885).
+char(3,28886).
+char(c,28887).
+char(m,28888).
+char(o,28889).
+char(p,28890).
+char(7,28891).
+char(5,28892).
+char(6,28893).
+char(0,28894).
+char(m,28895).
+char(9,28896).
+char(6,28897).
+char(7,28898).
+char(p,28899).
+char(5,28900).
+char(2,28901).
+char(3,28902).
+char(0,28903).
+char(p,28904).
+char(o,28905).
+char(m,28906).
+char(8,28907).
+char(2,28908).
+char(7,28909).
+char(6,28910).
+char(c,28911).
+char(c,28912).
+char(m,28913).
+char(9,28914).
+char(5,28915).
+char(6,28916).
+char(p,28917).
+char(7,28918).
+char(0,28919).
+char(1,28920).
+char(2,28921).
+char(p,28922).
+char(o,28923).
+char(3,28924).
+char(3,28925).
+char(2,28926).
+char(2,28927).
+char(c,28928).
+char(c,28929).
+char(p,28930).
+char(o,28931).
+char(p,28932).
+char(1,28933).
+char(7,28934).
+char(2,28935).
+char(2,28936).
+char(p,28937).
+char(1,28938).
+char(9,28939).
+char(4,28940).
+char(5,28941).
+char(c,28942).
+char(c,28943).
+char(c,28944).
+char(c,28945).
+char(c,28946).
+char(p,28947).
+char(o,28948).
+char(p,28949).
+char(1,28950).
+char(9,28951).
+char(9,28952).
+char(5,28953).
+char(p,28954).
+char(o,28955).
+char(p,28956).
+char(4,28957).
+char(2,28958).
+char(9,28959).
+char(3,28960).
+char(c,28961).
+char(c,28962).
+char(m,28963).
+char(5,28964).
+char(8,28965).
+char(9,28966).
+char(p,28967).
+char(9,28968).
+char(0,28969).
+char(8,28970).
+char(5,28971).
+char(c,28972).
+char(p,28973).
+char(o,28974).
+char(m,28975).
+char(o,28976).
+char(m,28977).
+char(7,28978).
+char(2,28979).
+char(0,28980).
+char(p,28981).
+char(o,28982).
+char(p,28983).
+char(o,28984).
+char(p,28985).
+char(o,28986).
+char(m,28987).
+char(o,28988).
+char(7,28989).
+char(0,28990).
+char(4,28991).
+char(7,28992).
+char(m,28993).
+char(7,28994).
+char(3,28995).
+char(6,28996).
+char(5,28997).
+char(m,28998).
+char(6,28999).
+char(2,29000).
+char(2,29001).
+char(1,29002).
+char(c,29003).
+char(c,29004).
+char(m,29005).
+char(o,29006).
+char(m,29007).
+char(1,29008).
+char(2,29009).
+char(1,29010).
+char(7,29011).
+char(p,29012).
+char(5,29013).
+char(4,29014).
+char(5,29015).
+char(3,29016).
+char(c,29017).
+char(c,29018).
+char(p,29019).
+char(o,29020).
+char(m,29021).
+char(o,29022).
+char(m,29023).
+char(o,29024).
+char(o,29025).
+char(o,29026).
+char(p,29027).
+char(o,29028).
+char(p,29029).
+char(9,29030).
+char(6,29031).
+char(6,29032).
+char(4,29033).
+char(m,29034).
+char(1,29035).
+char(2,29036).
+char(1,29037).
+char(8,29038).
+char(c,29039).
+char(c,29040).
+char(c,29041).
+char(c,29042).
+char(c,29043).
+char(c,29044).
+char(c,29045).
+char(p,29046).
+char(o,29047).
+char(o,29048).
+char(m,29049).
+char(o,29050).
+char(m,29051).
+char(o,29052).
+char(p,29053).
+char(7,29054).
+char(3,29055).
+char(2,29056).
+char(8,29057).
+char(c,29058).
+char(m,29059).
+char(7,29060).
+char(5,29061).
+char(6,29062).
+char(8,29063).
+char(m,29064).
+char(2,29065).
+char(1,29066).
+char(9,29067).
+char(9,29068).
+char(p,29069).
+char(9,29070).
+char(8,29071).
+char(m,29072).
+char(7,29073).
+char(9,29074).
+char(7,29075).
+char(0,29076).
+char(p,29077).
+char(o,29078).
+char(p,29079).
+char(7,29080).
+char(0,29081).
+char(1,29082).
+char(3,29083).
+char(c,29084).
+char(m,29085).
+char(o,29086).
+char(m,29087).
+char(7,29088).
+char(5,29089).
+char(9,29090).
+char(5,29091).
+char(m,29092).
+char(8,29093).
+char(7,29094).
+char(5,29095).
+char(8,29096).
+char(c,29097).
+char(c,29098).
+char(c,29099).
+char(c,29100).
+char(c,29101).
+char(c,29102).
+char(c,29103).
+char(c,29104).
+char(p,29105).
+char(7,29106).
+char(3,29107).
+char(6,29108).
+char(7,29109).
+char(c,29110).
+char(p,29111).
+char(1,29112).
+char(5,29113).
+char(6,29114).
+char(9,29115).
+char(p,29116).
+char(4,29117).
+char(4,29118).
+char(4,29119).
+char(9,29120).
+char(m,29121).
+char(8,29122).
+char(0,29123).
+char(2,29124).
+char(5,29125).
+char(m,29126).
+char(1,29127).
+char(4,29128).
+char(2,29129).
+char(8,29130).
+char(p,29131).
+char(o,29132).
+char(p,29133).
+char(o,29134).
+char(o,29135).
+char(m,29136).
+char(1,29137).
+char(5,29138).
+char(6,29139).
+char(0,29140).
+char(c,29141).
+char(c,29142).
+char(c,29143).
+char(c,29144).
+char(c,29145).
+char(p,29146).
+char(2,29147).
+char(6,29148).
+char(0,29149).
+char(6,29150).
+char(c,29151).
+char(c,29152).
+char(c,29153).
+char(c,29154).
+char(m,29155).
+char(o,29156).
+char(5,29157).
+char(6,29158).
+char(0,29159).
+char(c,29160).
+char(m,29161).
+char(7,29162).
+char(6,29163).
+char(7,29164).
+char(9,29165).
+char(p,29166).
+char(o,29167).
+char(p,29168).
+char(3,29169).
+char(9,29170).
+char(8,29171).
+char(5,29172).
+char(c,29173).
+char(m,29174).
+char(6,29175).
+char(9,29176).
+char(4,29177).
+char(9,29178).
+char(c,29179).
+char(c,29180).
+char(c,29181).
+char(c,29182).
+char(m,29183).
+char(6,29184).
+char(1,29185).
+char(7,29186).
+char(0,29187).
+char(c,29188).
+char(p,29189).
+char(o,29190).
+char(m,29191).
+char(7,29192).
+char(2,29193).
+char(4,29194).
+char(6,29195).
+char(c,29196).
+char(p,29197).
+char(o,29198).
+char(m,29199).
+char(2,29200).
+char(0,29201).
+char(3,29202).
+char(9,29203).
+char(p,29204).
+char(o,29205).
+char(p,29206).
+char(3,29207).
+char(3,29208).
+char(2,29209).
+char(1,29210).
+char(c,29211).
+char(c,29212).
+char(m,29213).
+char(9,29214).
+char(5,29215).
+char(5,29216).
+char(9,29217).
+char(p,29218).
+char(4,29219).
+char(9,29220).
+char(6,29221).
+char(3,29222).
+char(p,29223).
+char(9,29224).
+char(1,29225).
+char(8,29226).
+char(4,29227).
+char(c,29228).
+char(c,29229).
+char(m,29230).
+char(8,29231).
+char(8,29232).
+char(9,29233).
+char(1,29234).
+char(c,29235).
+char(p,29236).
+char(o,29237).
+char(m,29238).
+char(1,29239).
+char(8,29240).
+char(c,29241).
+char(m,29242).
+char(1,29243).
+char(9,29244).
+char(5,29245).
+char(6,29246).
+char(c,29247).
+char(p,29248).
+char(o,29249).
+char(6,29250).
+char(9,29251).
+char(8,29252).
+char(0,29253).
+char(p,29254).
+char(2,29255).
+char(2,29256).
+char(9,29257).
+char(c,29258).
+char(c,29259).
+char(m,29260).
+char(9,29261).
+char(4,29262).
+char(2,29263).
+char(6,29264).
+char(p,29265).
+char(o,29266).
+char(p,29267).
+char(o,29268).
+char(5,29269).
+char(1,29270).
+char(5,29271).
+char(c,29272).
+char(c,29273).
+char(p,29274).
+char(o,29275).
+char(m,29276).
+char(o,29277).
+char(3,29278).
+char(7,29279).
+char(9,29280).
+char(0,29281).
+char(c,29282).
+char(m,29283).
+char(o,29284).
+char(p,29285).
+char(7,29286).
+char(8,29287).
+char(7,29288).
+char(8,29289).
+char(m,29290).
+char(9,29291).
+char(4,29292).
+char(6,29293).
+char(1,29294).
+char(p,29295).
+char(6,29296).
+char(5,29297).
+char(5,29298).
+char(9,29299).
+char(c,29300).
+char(c,29301).
+char(c,29302).
+char(m,29303).
+char(o,29304).
+char(p,29305).
+char(4,29306).
+char(9,29307).
+char(3,29308).
+char(c,29309).
+char(c,29310).
+char(p,29311).
+char(3,29312).
+char(1,29313).
+char(4,29314).
+char(0,29315).
+char(p,29316).
+char(o,29317).
+char(p,29318).
+char(7,29319).
+char(4,29320).
+char(1,29321).
+char(7,29322).
+char(m,29323).
+char(o,29324).
+char(p,29325).
+char(o,29326).
+char(p,29327).
+char(1,29328).
+char(8,29329).
+char(4,29330).
+char(5,29331).
+char(p,29332).
+char(o,29333).
+char(m,29334).
+char(o,29335).
+char(m,29336).
+char(9,29337).
+char(8,29338).
+char(7,29339).
+char(7,29340).
+char(c,29341).
+char(c,29342).
+char(c,29343).
+char(c,29344).
+char(m,29345).
+char(4,29346).
+char(9,29347).
+char(2,29348).
+char(1,29349).
+char(m,29350).
+char(o,29351).
+char(m,29352).
+char(5,29353).
+char(3,29354).
+char(6,29355).
+char(3,29356).
+char(c,29357).
+char(c,29358).
+char(m,29359).
+char(5,29360).
+char(6,29361).
+char(2,29362).
+char(2,29363).
+char(p,29364).
+char(o,29365).
+char(m,29366).
+char(o,29367).
+char(m,29368).
+char(o,29369).
+char(m,29370).
+char(o,29371).
+char(5,29372).
+char(9,29373).
+char(0,29374).
+char(5,29375).
+char(m,29376).
+char(9,29377).
+char(0,29378).
+char(9,29379).
+char(7,29380).
+char(p,29381).
+char(o,29382).
+char(o,29383).
+char(o,29384).
+char(o,29385).
+char(m,29386).
+char(5,29387).
+char(1,29388).
+char(9,29389).
+char(8,29390).
+char(c,29391).
+char(p,29392).
+char(o,29393).
+char(p,29394).
+char(8,29395).
+char(0,29396).
+char(9,29397).
+char(0,29398).
+char(m,29399).
+char(2,29400).
+char(0,29401).
+char(7,29402).
+char(0,29403).
+char(p,29404).
+char(o,29405).
+char(p,29406).
+char(2,29407).
+char(9,29408).
+char(1,29409).
+char(2,29410).
+char(p,29411).
+char(o,29412).
+char(o,29413).
+char(p,29414).
+char(5,29415).
+char(9,29416).
+char(4,29417).
+char(5,29418).
+char(c,29419).
+char(c,29420).
+char(m,29421).
+char(o,29422).
+char(m,29423).
+char(1,29424).
+char(8,29425).
+char(0,29426).
+char(4,29427).
+char(m,29428).
+char(o,29429).
+char(o,29430).
+char(m,29431).
+char(o,29432).
+char(4,29433).
+char(2,29434).
+char(8,29435).
+char(0,29436).
+char(c,29437).
+char(c,29438).
+char(m,29439).
+char(9,29440).
+char(3,29441).
+char(1,29442).
+char(6,29443).
+char(c,29444).
+char(m,29445).
+char(8,29446).
+char(2,29447).
+char(5,29448).
+char(c,29449).
+char(c,29450).
+char(m,29451).
+char(6,29452).
+char(8,29453).
+char(7,29454).
+char(6,29455).
+char(c,29456).
+char(c,29457).
+char(c,29458).
+char(p,29459).
+char(8,29460).
+char(1,29461).
+char(0,29462).
+char(9,29463).
+char(c,29464).
+char(c,29465).
+char(p,29466).
+char(7,29467).
+char(4,29468).
+char(7,29469).
+char(9,29470).
+char(c,29471).
+char(p,29472).
+char(3,29473).
+char(7,29474).
+char(4,29475).
+char(2,29476).
+char(p,29477).
+char(8,29478).
+char(6,29479).
+char(5,29480).
+char(p,29481).
+char(o,29482).
+char(p,29483).
+char(o,29484).
+char(p,29485).
+char(o,29486).
+char(m,29487).
+char(6,29488).
+char(5,29489).
+char(6,29490).
+char(8,29491).
+char(c,29492).
+char(m,29493).
+char(o,29494).
+char(p,29495).
+char(o,29496).
+char(m,29497).
+char(o,29498).
+char(m,29499).
+char(3,29500).
+char(2,29501).
+char(5,29502).
+char(9,29503).
+char(c,29504).
+char(p,29505).
+char(o,29506).
+char(m,29507).
+char(o,29508).
+char(m,29509).
+char(o,29510).
+char(p,29511).
+char(o,29512).
+char(p,29513).
+char(7,29514).
+char(3,29515).
+char(0,29516).
+char(7,29517).
+char(c,29518).
+char(m,29519).
+char(4,29520).
+char(5,29521).
+char(2,29522).
+char(6,29523).
+char(m,29524).
+char(o,29525).
+char(p,29526).
+char(o,29527).
+char(p,29528).
+char(o,29529).
+char(p,29530).
+char(o,29531).
+char(o,29532).
+char(8,29533).
+char(9,29534).
+char(9,29535).
+char(7,29536).
+char(c,29537).
+char(c,29538).
+char(p,29539).
+char(o,29540).
+char(p,29541).
+char(o,29542).
+char(m,29543).
+char(7,29544).
+char(7,29545).
+char(1,29546).
+char(2,29547).
+char(c,29548).
+char(m,29549).
+char(7,29550).
+char(1,29551).
+char(2,29552).
+char(9,29553).
+char(m,29554).
+char(o,29555).
+char(m,29556).
+char(7,29557).
+char(9,29558).
+char(6,29559).
+char(5,29560).
+char(p,29561).
+char(2,29562).
+char(4,29563).
+char(5,29564).
+char(m,29565).
+char(o,29566).
+char(m,29567).
+char(4,29568).
+char(8,29569).
+char(7,29570).
+char(4,29571).
+char(m,29572).
+char(o,29573).
+char(8,29574).
+char(4,29575).
+char(6,29576).
+char(3,29577).
+char(c,29578).
+char(p,29579).
+char(8,29580).
+char(0,29581).
+char(8,29582).
+char(3,29583).
+char(m,29584).
+char(5,29585).
+char(c,29586).
+char(c,29587).
+char(c,29588).
+char(c,29589).
+char(p,29590).
+char(o,29591).
+char(m,29592).
+char(o,29593).
+char(m,29594).
+char(6,29595).
+char(9,29596).
+char(6,29597).
+char(6,29598).
+char(c,29599).
+char(c,29600).
+char(p,29601).
+char(o,29602).
+char(p,29603).
+char(4,29604).
+char(9,29605).
+char(5,29606).
+char(4,29607).
+char(c,29608).
+char(c,29609).
+char(c,29610).
+char(p,29611).
+char(4,29612).
+char(4,29613).
+char(9,29614).
+char(8,29615).
+char(m,29616).
+char(7,29617).
+char(8,29618).
+char(3,29619).
+char(4,29620).
+char(c,29621).
+char(p,29622).
+char(7,29623).
+char(3,29624).
+char(3,29625).
+char(7,29626).
+char(c,29627).
+char(p,29628).
+char(6,29629).
+char(3,29630).
+char(3,29631).
+char(2,29632).
+char(p,29633).
+char(4,29634).
+char(9,29635).
+char(4,29636).
+char(5,29637).
+char(m,29638).
+char(o,29639).
+char(o,29640).
+char(m,29641).
+char(4,29642).
+char(4,29643).
+char(4,29644).
+char(5,29645).
+char(p,29646).
+char(o,29647).
+char(p,29648).
+char(7,29649).
+char(7,29650).
+char(2,29651).
+char(5,29652).
+char(m,29653).
+char(o,29654).
+char(m,29655).
+char(6,29656).
+char(8,29657).
+char(8,29658).
+char(7,29659).
+char(c,29660).
+char(c,29661).
+char(m,29662).
+char(o,29663).
+char(p,29664).
+char(8,29665).
+char(4,29666).
+char(3,29667).
+char(p,29668).
+char(o,29669).
+char(m,29670).
+char(4,29671).
+char(7,29672).
+char(6,29673).
+char(1,29674).
+char(m,29675).
+char(6,29676).
+char(4,29677).
+char(1,29678).
+char(1,29679).
+char(c,29680).
+char(c,29681).
+char(c,29682).
+char(c,29683).
+char(c,29684).
+char(p,29685).
+char(7,29686).
+char(4,29687).
+char(0,29688).
+char(2,29689).
+char(c,29690).
+char(m,29691).
+char(o,29692).
+char(8,29693).
+char(5,29694).
+char(8,29695).
+char(8,29696).
+char(p,29697).
+char(7,29698).
+char(4,29699).
+char(7,29700).
+char(3,29701).
+char(p,29702).
+char(o,29703).
+char(p,29704).
+char(o,29705).
+char(p,29706).
+char(5,29707).
+char(3,29708).
+char(3,29709).
+char(3,29710).
+char(m,29711).
+char(o,29712).
+char(m,29713).
+char(o,29714).
+char(m,29715).
+char(o,29716).
+char(m,29717).
+char(o,29718).
+char(m,29719).
+char(9,29720).
+char(1,29721).
+char(4,29722).
+char(9,29723).
+char(c,29724).
+char(c,29725).
+char(p,29726).
+char(o,29727).
+char(o,29728).
+char(m,29729).
+char(9,29730).
+char(3,29731).
+char(6,29732).
+char(0,29733).
+char(c,29734).
+char(c,29735).
+char(m,29736).
+char(o,29737).
+char(m,29738).
+char(3,29739).
+char(6,29740).
+char(7,29741).
+char(8,29742).
+char(c,29743).
+char(p,29744).
+char(2,29745).
+char(1,29746).
+char(3,29747).
+char(0,29748).
+char(p,29749).
+char(o,29750).
+char(2,29751).
+char(1,29752).
+char(7,29753).
+char(7,29754).
+char(c,29755).
+char(c,29756).
+char(m,29757).
+char(2,29758).
+char(6,29759).
+char(8,29760).
+char(5,29761).
+char(c,29762).
+char(c,29763).
+char(m,29764).
+char(o,29765).
+char(p,29766).
+char(o,29767).
+char(m,29768).
+char(o,29769).
+char(p,29770).
+char(o,29771).
+char(p,29772).
+char(8,29773).
+char(3,29774).
+char(9,29775).
+char(2,29776).
+char(p,29777).
+char(7,29778).
+char(6,29779).
+char(9,29780).
+char(3,29781).
+char(c,29782).
+char(m,29783).
+char(o,29784).
+char(o,29785).
+char(p,29786).
+char(o,29787).
+char(9,29788).
+char(9,29789).
+char(0,29790).
+char(3,29791).
+char(c,29792).
+char(p,29793).
+char(7,29794).
+char(6,29795).
+char(9,29796).
+char(4,29797).
+char(p,29798).
+char(1,29799).
+char(7,29800).
+char(6,29801).
+char(1,29802).
+char(c,29803).
+char(p,29804).
+char(6,29805).
+char(0,29806).
+char(7,29807).
+char(c,29808).
+char(m,29809).
+char(9,29810).
+char(3,29811).
+char(6,29812).
+char(8,29813).
+char(c,29814).
+char(p,29815).
+char(8,29816).
+char(2,29817).
+char(1,29818).
+char(5,29819).
+char(c,29820).
+char(p,29821).
+char(9,29822).
+char(9,29823).
+char(3,29824).
+char(2,29825).
+char(m,29826).
+char(o,29827).
+char(p,29828).
+char(o,29829).
+char(m,29830).
+char(o,29831).
+char(1,29832).
+char(0,29833).
+char(4,29834).
+char(4,29835).
+char(c,29836).
+char(m,29837).
+char(8,29838).
+char(1,29839).
+char(9,29840).
+char(7,29841).
+char(c,29842).
+char(c,29843).
+char(p,29844).
+char(4,29845).
+char(8,29846).
+char(0,29847).
+char(6,29848).
+char(m,29849).
+char(3,29850).
+char(7,29851).
+char(1,29852).
+char(7,29853).
+char(m,29854).
+char(o,29855).
+char(o,29856).
+char(p,29857).
+char(3,29858).
+char(1,29859).
+char(7,29860).
+char(6,29861).
+char(m,29862).
+char(2,29863).
+char(9,29864).
+char(7,29865).
+char(3,29866).
+char(m,29867).
+char(3,29868).
+char(5,29869).
+char(6,29870).
+char(9,29871).
+char(m,29872).
+char(2,29873).
+char(0,29874).
+char(4,29875).
+char(9,29876).
+char(c,29877).
+char(p,29878).
+char(o,29879).
+char(m,29880).
+char(o,29881).
+char(m,29882).
+char(4,29883).
+char(0,29884).
+char(3,29885).
+char(0,29886).
+char(c,29887).
+char(p,29888).
+char(6,29889).
+char(4,29890).
+char(5,29891).
+char(4,29892).
+char(m,29893).
+char(o,29894).
+char(m,29895).
+char(o,29896).
+char(p,29897).
+char(o,29898).
+char(m,29899).
+char(8,29900).
+char(6,29901).
+char(0,29902).
+char(6,29903).
+char(p,29904).
+char(o,29905).
+char(m,29906).
+char(o,29907).
+char(m,29908).
+char(o,29909).
+char(p,29910).
+char(5,29911).
+char(8,29912).
+char(8,29913).
+char(7,29914).
+char(c,29915).
+char(c,29916).
+char(c,29917).
+char(c,29918).
+char(m,29919).
+char(o,29920).
+char(o,29921).
+char(m,29922).
+char(o,29923).
+char(m,29924).
+char(o,29925).
+char(o,29926).
+char(m,29927).
+char(o,29928).
+char(p,29929).
+char(o,29930).
+char(m,29931).
+char(o,29932).
+char(p,29933).
+char(o,29934).
+char(o,29935).
+char(m,29936).
+char(1,29937).
+char(5,29938).
+char(7,29939).
+char(c,29940).
+char(m,29941).
+char(o,29942).
+char(6,29943).
+char(2,29944).
+char(3,29945).
+char(3,29946).
+char(c,29947).
+char(m,29948).
+char(6,29949).
+char(0,29950).
+char(9,29951).
+char(9,29952).
+char(c,29953).
+char(m,29954).
+char(9,29955).
+char(0,29956).
+char(8,29957).
+char(5,29958).
+char(p,29959).
+char(o,29960).
+char(5,29961).
+char(6,29962).
+char(0,29963).
+char(c,29964).
+char(c,29965).
+char(p,29966).
+char(9,29967).
+char(7,29968).
+char(5,29969).
+char(8,29970).
+char(p,29971).
+char(7,29972).
+char(1,29973).
+char(1,29974).
+char(9,29975).
+char(p,29976).
+char(1,29977).
+char(2,29978).
+char(3,29979).
+char(3,29980).
+char(c,29981).
+char(m,29982).
+char(o,29983).
+char(m,29984).
+char(o,29985).
+char(p,29986).
+char(o,29987).
+char(o,29988).
+char(m,29989).
+char(7,29990).
+char(9,29991).
+char(2,29992).
+char(8,29993).
+char(c,29994).
+char(p,29995).
+char(8,29996).
+char(0,29997).
+char(6,29998).
+char(2,29999).
+char(c,30000).
+char(p,30001).
+char(5,30002).
+char(4,30003).
+char(5,30004).
+char(2,30005).
+char(p,30006).
+char(3,30007).
+char(9,30008).
+char(8,30009).
+char(1,30010).
+char(c,30011).
+char(c,30012).
+char(p,30013).
+char(3,30014).
+char(0,30015).
+char(5,30016).
+char(8,30017).
+char(c,30018).
+char(m,30019).
+char(o,30020).
+char(o,30021).
+char(p,30022).
+char(2,30023).
+char(0,30024).
+char(9,30025).
+char(8,30026).
+char(p,30027).
+char(9,30028).
+char(8,30029).
+char(8,30030).
+char(6,30031).
+char(p,30032).
+char(3,30033).
+char(0,30034).
+char(7,30035).
+char(8,30036).
+char(c,30037).
+char(c,30038).
+char(m,30039).
+char(6,30040).
+char(4,30041).
+char(8,30042).
+char(8,30043).
+char(m,30044).
+char(2,30045).
+char(7,30046).
+char(9,30047).
+char(2,30048).
+char(c,30049).
+char(c,30050).
+char(m,30051).
+char(o,30052).
+char(6,30053).
+char(1,30054).
+char(9,30055).
+char(8,30056).
+char(m,30057).
+char(9,30058).
+char(3,30059).
+char(0,30060).
+char(1,30061).
+char(c,30062).
+char(p,30063).
+char(4,30064).
+char(3,30065).
+char(6,30066).
+char(7,30067).
+char(c,30068).
+char(p,30069).
+char(o,30070).
+char(p,30071).
+char(o,30072).
+char(3,30073).
+char(0,30074).
+char(8,30075).
+char(0,30076).
+char(c,30077).
+char(c,30078).
+char(c,30079).
+char(p,30080).
+char(1,30081).
+char(6,30082).
+char(0,30083).
+char(2,30084).
+char(c,30085).
+char(c,30086).
+char(c,30087).
+char(p,30088).
+char(5,30089).
+char(0,30090).
+char(6,30091).
+char(3,30092).
+char(c,30093).
+char(c,30094).
+char(c,30095).
+char(m,30096).
+char(5,30097).
+char(5,30098).
+char(5,30099).
+char(1,30100).
+char(c,30101).
+char(p,30102).
+char(o,30103).
+char(p,30104).
+char(o,30105).
+char(m,30106).
+char(o,30107).
+char(p,30108).
+char(o,30109).
+char(1,30110).
+char(3,30111).
+char(0,30112).
+char(8,30113).
+char(c,30114).
+char(c,30115).
+char(m,30116).
+char(o,30117).
+char(m,30118).
+char(6,30119).
+char(0,30120).
+char(6,30121).
+char(p,30122).
+char(5,30123).
+char(2,30124).
+char(2,30125).
+char(4,30126).
+char(p,30127).
+char(o,30128).
+char(p,30129).
+char(o,30130).
+char(2,30131).
+char(0,30132).
+char(2,30133).
+char(6,30134).
+char(p,30135).
+char(o,30136).
+char(m,30137).
+char(4,30138).
+char(2,30139).
+char(9,30140).
+char(5,30141).
+char(c,30142).
+char(p,30143).
+char(2,30144).
+char(1,30145).
+char(2,30146).
+char(6,30147).
+char(m,30148).
+char(6,30149).
+char(3,30150).
+char(2,30151).
+char(m,30152).
+char(o,30153).
+char(p,30154).
+char(2,30155).
+char(6,30156).
+char(0,30157).
+char(c,30158).
+char(c,30159).
+char(p,30160).
+char(4,30161).
+char(3,30162).
+char(7,30163).
+char(0,30164).
+char(c,30165).
+char(p,30166).
+char(o,30167).
+char(o,30168).
+char(p,30169).
+char(o,30170).
+char(m,30171).
+char(o,30172).
+char(m,30173).
+char(o,30174).
+char(m,30175).
+char(5,30176).
+char(8,30177).
+char(9,30178).
+char(0,30179).
+char(p,30180).
+char(2,30181).
+char(2,30182).
+char(8,30183).
+char(p,30184).
+char(7,30185).
+char(1,30186).
+char(9,30187).
+char(7,30188).
+char(c,30189).
+char(c,30190).
+char(c,30191).
+char(c,30192).
+char(p,30193).
+char(2,30194).
+char(5,30195).
+char(4,30196).
+char(8,30197).
+char(m,30198).
+char(o,30199).
+char(o,30200).
+char(p,30201).
+char(o,30202).
+char(p,30203).
+char(o,30204).
+char(m,30205).
+char(1,30206).
+char(5,30207).
+char(9,30208).
+char(6,30209).
+char(p,30210).
+char(o,30211).
+char(o,30212).
+char(p,30213).
+char(9,30214).
+char(3,30215).
+char(3,30216).
+char(6,30217).
+char(c,30218).
+char(p,30219).
+char(2,30220).
+char(9,30221).
+char(5,30222).
+char(3,30223).
+char(c,30224).
+char(p,30225).
+char(9,30226).
+char(5,30227).
+char(7,30228).
+char(2,30229).
+char(m,30230).
+char(1,30231).
+char(8,30232).
+char(2,30233).
+char(6,30234).
+char(m,30235).
+char(2,30236).
+char(8,30237).
+char(4,30238).
+char(0,30239).
+char(c,30240).
+char(m,30241).
+char(o,30242).
+char(m,30243).
+char(8,30244).
+char(0,30245).
+char(2,30246).
+char(9,30247).
+char(p,30248).
+char(3,30249).
+char(6,30250).
+char(3,30251).
+char(4,30252).
+char(m,30253).
+char(7,30254).
+char(8,30255).
+char(3,30256).
+char(6,30257).
+char(m,30258).
+char(o,30259).
+char(o,30260).
+char(o,30261).
+char(m,30262).
+char(o,30263).
+char(m,30264).
+char(7,30265).
+char(0,30266).
+char(6,30267).
+char(5,30268).
+char(c,30269).
+char(c,30270).
+char(m,30271).
+char(o,30272).
+char(m,30273).
+char(o,30274).
+char(o,30275).
+char(m,30276).
+char(6,30277).
+char(9,30278).
+char(6,30279).
+char(3,30280).
+char(p,30281).
+char(1,30282).
+char(0,30283).
+char(2,30284).
+char(7,30285).
+char(p,30286).
+char(8,30287).
+char(1,30288).
+char(9,30289).
+char(c,30290).
+char(p,30291).
+char(o,30292).
+char(m,30293).
+char(o,30294).
+char(p,30295).
+char(7,30296).
+char(4,30297).
+char(3,30298).
+char(7,30299).
+char(c,30300).
+char(c,30301).
+char(m,30302).
+char(o,30303).
+char(m,30304).
+char(o,30305).
+char(p,30306).
+char(o,30307).
+char(p,30308).
+char(o,30309).
+char(m,30310).
+char(o,30311).
+char(m,30312).
+char(o,30313).
+char(o,30314).
+char(p,30315).
+char(8,30316).
+char(9,30317).
+char(9,30318).
+char(4,30319).
+char(p,30320).
+char(o,30321).
+char(m,30322).
+char(o,30323).
+char(p,30324).
+char(o,30325).
+char(m,30326).
+char(5,30327).
+char(8,30328).
+char(7,30329).
+char(6,30330).
+char(p,30331).
+char(o,30332).
+char(m,30333).
+char(o,30334).
+char(p,30335).
+char(2,30336).
+char(4,30337).
+char(4,30338).
+char(c,30339).
+char(c,30340).
+char(p,30341).
+char(o,30342).
+char(2,30343).
+char(9,30344).
+char(1,30345).
+char(4,30346).
+char(c,30347).
+char(c,30348).
+char(p,30349).
+char(9,30350).
+char(7,30351).
+char(9,30352).
+char(0,30353).
+char(c,30354).
+char(p,30355).
+char(2,30356).
+char(3,30357).
+char(7,30358).
+char(6,30359).
+char(c,30360).
+char(c,30361).
+char(p,30362).
+char(3,30363).
+char(1,30364).
+char(3,30365).
+char(2,30366).
+char(c,30367).
+char(c,30368).
+char(c,30369).
+char(m,30370).
+char(2,30371).
+char(4,30372).
+char(5,30373).
+char(6,30374).
+char(c,30375).
+char(c,30376).
+char(m,30377).
+char(5,30378).
+char(3,30379).
+char(4,30380).
+char(c,30381).
+char(c,30382).
+char(p,30383).
+char(o,30384).
+char(p,30385).
+char(o,30386).
+char(p,30387).
+char(o,30388).
+char(1,30389).
+char(1,30390).
+char(2,30391).
+char(4,30392).
+char(p,30393).
+char(7,30394).
+char(8,30395).
+char(7,30396).
+char(1,30397).
+char(c,30398).
+char(p,30399).
+char(3,30400).
+char(2,30401).
+char(8,30402).
+char(4,30403).
+char(c,30404).
+char(c,30405).
+char(p,30406).
+char(2,30407).
+char(8,30408).
+char(7,30409).
+char(7,30410).
+char(p,30411).
+char(o,30412).
+char(p,30413).
+char(o,30414).
+char(p,30415).
+char(o,30416).
+char(p,30417).
+char(7,30418).
+char(9,30419).
+char(7,30420).
+char(0,30421).
+char(p,30422).
+char(o,30423).
+char(o,30424).
+char(p,30425).
+char(o,30426).
+char(p,30427).
+char(o,30428).
+char(5,30429).
+char(7,30430).
+char(3,30431).
+char(2,30432).
+char(c,30433).
+char(c,30434).
+char(c,30435).
+char(c,30436).
+char(c,30437).
+char(c,30438).
+char(c,30439).
+char(m,30440).
+char(6,30441).
+char(9,30442).
+char(0,30443).
+char(4,30444).
+char(c,30445).
+char(m,30446).
+char(3,30447).
+char(7,30448).
+char(5,30449).
+char(0,30450).
+char(m,30451).
+char(5,30452).
+char(0,30453).
+char(4,30454).
+char(4,30455).
+char(m,30456).
+char(4,30457).
+char(5,30458).
+char(5,30459).
+char(0,30460).
+char(c,30461).
+char(m,30462).
+char(o,30463).
+char(m,30464).
+char(o,30465).
+char(m,30466).
+char(o,30467).
+char(o,30468).
+char(o,30469).
+char(p,30470).
+char(o,30471).
+char(o,30472).
+char(p,30473).
+char(o,30474).
+char(m,30475).
+char(6,30476).
+char(4,30477).
+char(7,30478).
+char(9,30479).
+char(m,30480).
+char(o,30481).
+char(m,30482).
+char(4,30483).
+char(6,30484).
+char(2,30485).
+char(3,30486).
+char(p,30487).
+char(7,30488).
+char(2,30489).
+char(5,30490).
+char(p,30491).
+char(o,30492).
+char(m,30493).
+char(3,30494).
+char(7,30495).
+char(0,30496).
+char(1,30497).
+char(m,30498).
+char(3,30499).
+char(9,30500).
+char(1,30501).
+char(6,30502).
+char(m,30503).
+char(o,30504).
+char(m,30505).
+char(1,30506).
+char(1,30507).
+char(9,30508).
+char(6,30509).
+char(c,30510).
+char(c,30511).
+char(m,30512).
+char(o,30513).
+char(m,30514).
+char(o,30515).
+char(m,30516).
+char(o,30517).
+char(2,30518).
+char(9,30519).
+char(7,30520).
+char(5,30521).
+char(c,30522).
+char(c,30523).
+char(m,30524).
+char(5,30525).
+char(6,30526).
+char(9,30527).
+char(0,30528).
+char(p,30529).
+char(6,30530).
+char(4,30531).
+char(2,30532).
+char(5,30533).
+char(m,30534).
+char(o,30535).
+char(p,30536).
+char(5,30537).
+char(8,30538).
+char(4,30539).
+char(7,30540).
+char(m,30541).
+char(o,30542).
+char(9,30543).
+char(9,30544).
+char(6,30545).
+char(3,30546).
+char(m,30547).
+char(6,30548).
+char(4,30549).
+char(1,30550).
+char(8,30551).
+char(c,30552).
+char(c,30553).
+char(c,30554).
+char(c,30555).
+char(m,30556).
+char(o,30557).
+char(p,30558).
+char(o,30559).
+char(p,30560).
+char(o,30561).
+char(m,30562).
+char(9,30563).
+char(1,30564).
+char(3,30565).
+char(2,30566).
+char(c,30567).
+char(p,30568).
+char(6,30569).
+char(0,30570).
+char(1,30571).
+char(5,30572).
+char(c,30573).
+char(c,30574).
+char(c,30575).
+char(c,30576).
+char(m,30577).
+char(o,30578).
+char(p,30579).
+char(o,30580).
+char(m,30581).
+char(3,30582).
+char(2,30583).
+char(1,30584).
+char(1,30585).
+char(m,30586).
+char(3,30587).
+char(1,30588).
+char(6,30589).
+char(2,30590).
+char(c,30591).
+char(c,30592).
+char(c,30593).
+char(m,30594).
+char(o,30595).
+char(p,30596).
+char(3,30597).
+char(6,30598).
+char(8,30599).
+char(1,30600).
+char(p,30601).
+char(6,30602).
+char(5,30603).
+char(8,30604).
+char(3,30605).
+char(m,30606).
+char(4,30607).
+char(2,30608).
+char(9,30609).
+char(4,30610).
+char(m,30611).
+char(2,30612).
+char(1,30613).
+char(9,30614).
+char(6,30615).
+char(c,30616).
+char(m,30617).
+char(o,30618).
+char(7,30619).
+char(8,30620).
+char(1,30621).
+char(9,30622).
+char(p,30623).
+char(4,30624).
+char(7,30625).
+char(5,30626).
+char(2,30627).
+char(c,30628).
+char(m,30629).
+char(o,30630).
+char(9,30631).
+char(7,30632).
+char(4,30633).
+char(2,30634).
+char(c,30635).
+char(c,30636).
+char(c,30637).
+char(c,30638).
+char(c,30639).
+char(m,30640).
+char(5,30641).
+char(9,30642).
+char(9,30643).
+char(7,30644).
+char(m,30645).
+char(o,30646).
+char(o,30647).
+char(m,30648).
+char(o,30649).
+char(m,30650).
+char(o,30651).
+char(m,30652).
+char(4,30653).
+char(1,30654).
+char(8,30655).
+char(8,30656).
+char(p,30657).
+char(3,30658).
+char(0,30659).
+char(2,30660).
+char(3,30661).
+char(m,30662).
+char(o,30663).
+char(m,30664).
+char(7,30665).
+char(4,30666).
+char(7,30667).
+char(9,30668).
+char(p,30669).
+char(o,30670).
+char(p,30671).
+char(3,30672).
+char(0,30673).
+char(4,30674).
+char(7,30675).
+char(c,30676).
+char(m,30677).
+char(8,30678).
+char(4,30679).
+char(7,30680).
+char(0,30681).
+char(c,30682).
+char(c,30683).
+char(c,30684).
+char(m,30685).
+char(o,30686).
+char(m,30687).
+char(o,30688).
+char(m,30689).
+char(9,30690).
+char(4,30691).
+char(1,30692).
+char(5,30693).
+char(c,30694).
+char(m,30695).
+char(8,30696).
+char(6,30697).
+char(0,30698).
+char(7,30699).
+char(c,30700).
+char(c,30701).
+char(c,30702).
+char(m,30703).
+char(7,30704).
+char(1,30705).
+char(2,30706).
+char(c,30707).
+char(p,30708).
+char(o,30709).
+char(p,30710).
+char(o,30711).
+char(p,30712).
+char(7,30713).
+char(4,30714).
+char(4,30715).
+char(9,30716).
+char(p,30717).
+char(8,30718).
+char(3,30719).
+char(3,30720).
+char(8,30721).
+char(c,30722).
+char(c,30723).
+char(c,30724).
+char(c,30725).
+char(m,30726).
+char(6,30727).
+char(9,30728).
+char(1,30729).
+char(9,30730).
+char(c,30731).
+char(c,30732).
+char(c,30733).
+char(c,30734).
+char(p,30735).
+char(8,30736).
+char(4,30737).
+char(0,30738).
+char(5,30739).
+char(c,30740).
+char(m,30741).
+char(2,30742).
+char(7,30743).
+char(8,30744).
+char(0,30745).
+char(c,30746).
+char(m,30747).
+char(2,30748).
+char(8,30749).
+char(9,30750).
+char(1,30751).
+char(c,30752).
+char(c,30753).
+char(c,30754).
+char(m,30755).
+char(5,30756).
+char(7,30757).
+char(4,30758).
+char(6,30759).
+char(m,30760).
+char(1,30761).
+char(4,30762).
+char(6,30763).
+char(2,30764).
+char(p,30765).
+char(o,30766).
+char(1,30767).
+char(2,30768).
+char(4,30769).
+char(9,30770).
+char(m,30771).
+char(o,30772).
+char(m,30773).
+char(1,30774).
+char(6,30775).
+char(1,30776).
+char(6,30777).
+char(c,30778).
+char(c,30779).
+char(c,30780).
+char(c,30781).
+char(c,30782).
+char(p,30783).
+char(7,30784).
+char(5,30785).
+char(7,30786).
+char(8,30787).
+char(c,30788).
+char(c,30789).
+char(c,30790).
+char(m,30791).
+char(o,30792).
+char(8,30793).
+char(5,30794).
+char(1,30795).
+char(4,30796).
+char(c,30797).
+char(m,30798).
+char(6,30799).
+char(5,30800).
+char(9,30801).
+char(0,30802).
+char(c,30803).
+char(c,30804).
+char(c,30805).
+char(c,30806).
+char(p,30807).
+char(9,30808).
+char(6,30809).
+char(2,30810).
+char(c,30811).
+char(c,30812).
+char(p,30813).
+char(9,30814).
+char(0,30815).
+char(4,30816).
+char(2,30817).
+char(p,30818).
+char(o,30819).
+char(8,30820).
+char(6,30821).
+char(3,30822).
+char(1,30823).
+char(m,30824).
+char(9,30825).
+char(9,30826).
+char(3,30827).
+char(7,30828).
+char(m,30829).
+char(o,30830).
+char(m,30831).
+char(o,30832).
+char(p,30833).
+char(9,30834).
+char(6,30835).
+char(0,30836).
+char(2,30837).
+char(c,30838).
+char(c,30839).
+char(p,30840).
+char(8,30841).
+char(8,30842).
+char(5,30843).
+char(9,30844).
+char(c,30845).
+char(c,30846).
+char(m,30847).
+char(o,30848).
+char(5,30849).
+char(4,30850).
+char(9,30851).
+char(6,30852).
+char(c,30853).
+char(p,30854).
+char(9,30855).
+char(0,30856).
+char(4,30857).
+char(5,30858).
+char(p,30859).
+char(3,30860).
+char(3,30861).
+char(1,30862).
+char(9,30863).
+char(c,30864).
+char(c,30865).
+char(c,30866).
+char(c,30867).
+char(m,30868).
+char(o,30869).
+char(p,30870).
+char(o,30871).
+char(m,30872).
+char(4,30873).
+char(0,30874).
+char(0,30875).
+char(3,30876).
+char(c,30877).
+char(c,30878).
+char(m,30879).
+char(7,30880).
+char(8,30881).
+char(3,30882).
+char(2,30883).
+char(m,30884).
+char(2,30885).
+char(4,30886).
+char(9,30887).
+char(7,30888).
+char(c,30889).
+char(p,30890).
+char(4,30891).
+char(4,30892).
+char(4,30893).
+char(7,30894).
+char(c,30895).
+char(p,30896).
+char(o,30897).
+char(o,30898).
+char(m,30899).
+char(o,30900).
+char(m,30901).
+char(o,30902).
+char(p,30903).
+char(o,30904).
+char(5,30905).
+char(5,30906).
+char(3,30907).
+char(1,30908).
+char(p,30909).
+char(o,30910).
+char(p,30911).
+char(1,30912).
+char(0,30913).
+char(2,30914).
+char(4,30915).
+char(c,30916).
+char(m,30917).
+char(2,30918).
+char(8,30919).
+char(7,30920).
+char(8,30921).
+char(c,30922).
+char(c,30923).
+char(c,30924).
+char(c,30925).
+char(c,30926).
+char(c,30927).
+char(p,30928).
+char(6,30929).
+char(4,30930).
+char(0,30931).
+char(8,30932).
+char(c,30933).
+char(c,30934).
+char(p,30935).
+char(1,30936).
+char(4,30937).
+char(9,30938).
+char(8,30939).
+char(c,30940).
+char(p,30941).
+char(3,30942).
+char(0,30943).
+char(0,30944).
+char(c,30945).
+char(c,30946).
+char(p,30947).
+char(o,30948).
+char(o,30949).
+char(4,30950).
+char(9,30951).
+char(5,30952).
+char(4,30953).
+char(c,30954).
+char(c,30955).
+char(c,30956).
+char(c,30957).
+char(m,30958).
+char(o,30959).
+char(2,30960).
+char(3,30961).
+char(1,30962).
+char(9,30963).
+char(c,30964).
+char(m,30965).
+char(9,30966).
+char(5,30967).
+char(2,30968).
+char(7,30969).
+char(m,30970).
+char(o,30971).
+char(m,30972).
+char(o,30973).
+char(1,30974).
+char(8,30975).
+char(9,30976).
+char(9,30977).
+char(m,30978).
+char(o,30979).
+char(7,30980).
+char(2,30981).
+char(0,30982).
+char(8,30983).
+char(c,30984).
+char(c,30985).
+char(m,30986).
+char(7,30987).
+char(3,30988).
+char(4,30989).
+char(6,30990).
+char(c,30991).
+char(c,30992).
+char(m,30993).
+char(3,30994).
+char(6,30995).
+char(4,30996).
+char(6,30997).
+char(c,30998).
+char(m,30999).
+char(o,31000).
+char(p,31001).
+char(o,31002).
+char(m,31003).
+char(7,31004).
+char(2,31005).
+char(9,31006).
+char(0,31007).
+char(m,31008).
+char(o,31009).
+char(1,31010).
+char(6,31011).
+char(0,31012).
+char(6,31013).
+char(p,31014).
+char(o,31015).
+char(m,31016).
+char(o,31017).
+char(p,31018).
+char(3,31019).
+char(4,31020).
+char(0,31021).
+char(c,31022).
+char(c,31023).
+char(p,31024).
+char(o,31025).
+char(9,31026).
+char(1,31027).
+char(4,31028).
+char(1,31029).
+char(m,31030).
+char(3,31031).
+char(2,31032).
+char(7,31033).
+char(3,31034).
+char(p,31035).
+char(o,31036).
+char(p,31037).
+char(5,31038).
+char(0,31039).
+char(9,31040).
+char(5,31041).
+char(p,31042).
+char(o,31043).
+char(p,31044).
+char(o,31045).
+char(m,31046).
+char(o,31047).
+char(9,31048).
+char(6,31049).
+char(4,31050).
+char(6,31051).
+char(m,31052).
+char(o,31053).
+char(8,31054).
+char(3,31055).
+char(6,31056).
+char(8,31057).
+char(m,31058).
+char(1,31059).
+char(9,31060).
+char(5,31061).
+char(8,31062).
+char(c,31063).
+char(m,31064).
+char(7,31065).
+char(0,31066).
+char(5,31067).
+char(5,31068).
+char(c,31069).
+char(c,31070).
+char(p,31071).
+char(5,31072).
+char(6,31073).
+char(3,31074).
+char(7,31075).
+char(c,31076).
+char(p,31077).
+char(1,31078).
+char(7,31079).
+char(9,31080).
+char(3,31081).
+char(c,31082).
+char(c,31083).
+char(m,31084).
+char(o,31085).
+char(m,31086).
+char(o,31087).
+char(m,31088).
+char(o,31089).
+char(p,31090).
+char(o,31091).
+char(m,31092).
+char(o,31093).
+char(p,31094).
+char(8,31095).
+char(8,31096).
+char(6,31097).
+char(0,31098).
+char(c,31099).
+char(c,31100).
+char(p,31101).
+char(2,31102).
+char(3,31103).
+char(2,31104).
+char(5,31105).
+char(p,31106).
+char(o,31107).
+char(o,31108).
+char(p,31109).
+char(8,31110).
+char(4,31111).
+char(1,31112).
+char(1,31113).
+char(c,31114).
+char(c,31115).
+char(p,31116).
+char(6,31117).
+char(8,31118).
+char(0,31119).
+char(7,31120).
+char(c,31121).
+char(c,31122).
+char(m,31123).
+char(3,31124).
+char(7,31125).
+char(1,31126).
+char(3,31127).
+char(m,31128).
+char(o,31129).
+char(m,31130).
+char(2,31131).
+char(5,31132).
+char(3,31133).
+char(4,31134).
+char(m,31135).
+char(9,31136).
+char(0,31137).
+char(6,31138).
+char(c,31139).
+char(c,31140).
+char(c,31141).
+char(c,31142).
+char(p,31143).
+char(3,31144).
+char(9,31145).
+char(2,31146).
+char(8,31147).
+char(m,31148).
+char(4,31149).
+char(2,31150).
+char(3,31151).
+char(3,31152).
+char(c,31153).
+char(p,31154).
+char(6,31155).
+char(5,31156).
+char(1,31157).
+char(2,31158).
+char(c,31159).
+char(c,31160).
+char(c,31161).
+char(m,31162).
+char(o,31163).
+char(o,31164).
+char(m,31165).
+char(o,31166).
+char(m,31167).
+char(2,31168).
+char(2,31169).
+char(2,31170).
+char(2,31171).
+char(m,31172).
+char(1,31173).
+char(3,31174).
+char(5,31175).
+char(c,31176).
+char(c,31177).
+char(c,31178).
+char(c,31179).
+char(m,31180).
+char(o,31181).
+char(p,31182).
+char(o,31183).
+char(p,31184).
+char(2,31185).
+char(9,31186).
+char(3,31187).
+char(1,31188).
+char(c,31189).
+char(p,31190).
+char(1,31191).
+char(7,31192).
+char(2,31193).
+char(5,31194).
+char(m,31195).
+char(9,31196).
+char(7,31197).
+char(6,31198).
+char(9,31199).
+char(p,31200).
+char(6,31201).
+char(7,31202).
+char(2,31203).
+char(6,31204).
+char(c,31205).
+char(c,31206).
+char(c,31207).
+char(c,31208).
+char(c,31209).
+char(c,31210).
+char(c,31211).
+char(p,31212).
+char(7,31213).
+char(0,31214).
+char(1,31215).
+char(5,31216).
+char(m,31217).
+char(5,31218).
+char(0,31219).
+char(6,31220).
+char(6,31221).
+char(c,31222).
+char(p,31223).
+char(1,31224).
+char(9,31225).
+char(0,31226).
+char(6,31227).
+char(c,31228).
+char(c,31229).
+char(p,31230).
+char(o,31231).
+char(m,31232).
+char(8,31233).
+char(2,31234).
+char(3,31235).
+char(7,31236).
+char(p,31237).
+char(1,31238).
+char(2,31239).
+char(6,31240).
+char(4,31241).
+char(m,31242).
+char(5,31243).
+char(3,31244).
+char(4,31245).
+char(9,31246).
+char(c,31247).
+char(m,31248).
+char(7,31249).
+char(7,31250).
+char(4,31251).
+char(9,31252).
+char(c,31253).
+char(c,31254).
+char(m,31255).
+char(o,31256).
+char(m,31257).
+char(8,31258).
+char(9,31259).
+char(7,31260).
+char(p,31261).
+char(6,31262).
+char(9,31263).
+char(8,31264).
+char(5,31265).
+char(p,31266).
+char(6,31267).
+char(0,31268).
+char(9,31269).
+char(6,31270).
+char(m,31271).
+char(o,31272).
+char(1,31273).
+char(5,31274).
+char(2,31275).
+char(m,31276).
+char(o,31277).
+char(m,31278).
+char(2,31279).
+char(6,31280).
+char(8,31281).
+char(2,31282).
+char(c,31283).
+char(p,31284).
+char(1,31285).
+char(7,31286).
+char(8,31287).
+char(9,31288).
+char(p,31289).
+char(o,31290).
+char(o,31291).
+char(p,31292).
+char(o,31293).
+char(o,31294).
+char(m,31295).
+char(1,31296).
+char(5,31297).
+char(3,31298).
+char(8,31299).
+char(p,31300).
+char(o,31301).
+char(p,31302).
+char(8,31303).
+char(8,31304).
+char(8,31305).
+char(3,31306).
+char(p,31307).
+char(o,31308).
+char(p,31309).
+char(o,31310).
+char(p,31311).
+char(o,31312).
+char(p,31313).
+char(9,31314).
+char(5,31315).
+char(6,31316).
+char(9,31317).
+char(c,31318).
+char(c,31319).
+char(c,31320).
+char(c,31321).
+char(m,31322).
+char(o,31323).
+char(m,31324).
+char(7,31325).
+char(4,31326).
+char(4,31327).
+char(5,31328).
+char(p,31329).
+char(o,31330).
+char(m,31331).
+char(o,31332).
+char(m,31333).
+char(o,31334).
+char(p,31335).
+char(4,31336).
+char(0,31337).
+char(0,31338).
+char(0,31339).
+char(p,31340).
+char(4,31341).
+char(3,31342).
+char(7,31343).
+char(1,31344).
+char(m,31345).
+char(2,31346).
+char(6,31347).
+char(2,31348).
+char(4,31349).
+char(m,31350).
+char(o,31351).
+char(p,31352).
+char(5,31353).
+char(2,31354).
+char(0,31355).
+char(6,31356).
+char(c,31357).
+char(p,31358).
+char(7,31359).
+char(4,31360).
+char(0,31361).
+char(5,31362).
+char(p,31363).
+char(o,31364).
+char(o,31365).
+char(m,31366).
+char(o,31367).
+char(m,31368).
+char(o,31369).
+char(o,31370).
+char(p,31371).
+char(3,31372).
+char(7,31373).
+char(4,31374).
+char(7,31375).
+char(c,31376).
+char(c,31377).
+char(p,31378).
+char(o,31379).
+char(m,31380).
+char(o,31381).
+char(p,31382).
+char(o,31383).
+char(m,31384).
+char(8,31385).
+char(3,31386).
+char(8,31387).
+char(4,31388).
+char(c,31389).
+char(m,31390).
+char(7,31391).
+char(9,31392).
+char(9,31393).
+char(2,31394).
+char(m,31395).
+char(9,31396).
+char(1,31397).
+char(6,31398).
+char(4,31399).
+char(c,31400).
+char(c,31401).
+char(m,31402).
+char(o,31403).
+char(4,31404).
+char(2,31405).
+char(7,31406).
+char(0,31407).
+char(p,31408).
+char(2,31409).
+char(8,31410).
+char(0,31411).
+char(1,31412).
+char(c,31413).
+char(m,31414).
+char(o,31415).
+char(p,31416).
+char(4,31417).
+char(6,31418).
+char(4,31419).
+char(1,31420).
+char(p,31421).
+char(o,31422).
+char(p,31423).
+char(7,31424).
+char(5,31425).
+char(2,31426).
+char(9,31427).
+char(p,31428).
+char(o,31429).
+char(o,31430).
+char(o,31431).
+char(7,31432).
+char(5,31433).
+char(4,31434).
+char(4,31435).
+char(p,31436).
+char(2,31437).
+char(5,31438).
+char(6,31439).
+char(1,31440).
+char(p,31441).
+char(7,31442).
+char(8,31443).
+char(2,31444).
+char(8,31445).
+char(c,31446).
+char(c,31447).
+char(p,31448).
+char(o,31449).
+char(o,31450).
+char(m,31451).
+char(5,31452).
+char(5,31453).
+char(7,31454).
+char(4,31455).
+char(c,31456).
+char(c,31457).
+char(c,31458).
+char(c,31459).
+char(m,31460).
+char(6,31461).
+char(6,31462).
+char(5,31463).
+char(5,31464).
+char(c,31465).
+char(c,31466).
+char(c,31467).
+char(p,31468).
+char(6,31469).
+char(0,31470).
+char(4,31471).
+char(2,31472).
+char(m,31473).
+char(6,31474).
+char(3,31475).
+char(3,31476).
+char(2,31477).
+char(c,31478).
+char(p,31479).
+char(o,31480).
+char(m,31481).
+char(o,31482).
+char(3,31483).
+char(9,31484).
+char(3,31485).
+char(1,31486).
+char(p,31487).
+char(4,31488).
+char(8,31489).
+char(5,31490).
+char(9,31491).
+char(c,31492).
+char(c,31493).
+char(c,31494).
+char(m,31495).
+char(o,31496).
+char(7,31497).
+char(0,31498).
+char(6,31499).
+char(5,31500).
+char(c,31501).
+char(c,31502).
+char(c,31503).
+char(p,31504).
+char(o,31505).
+char(m,31506).
+char(o,31507).
+char(p,31508).
+char(7,31509).
+char(3,31510).
+char(5,31511).
+char(3,31512).
+char(p,31513).
+char(o,31514).
+char(o,31515).
+char(m,31516).
+char(o,31517).
+char(p,31518).
+char(7,31519).
+char(7,31520).
+char(2,31521).
+char(0,31522).
+char(c,31523).
+char(c,31524).
+char(c,31525).
+char(c,31526).
+char(c,31527).
+char(p,31528).
+char(o,31529).
+char(p,31530).
+char(o,31531).
+char(m,31532).
+char(o,31533).
+char(p,31534).
+char(o,31535).
+char(m,31536).
+char(o,31537).
+char(p,31538).
+char(9,31539).
+char(0,31540).
+char(6,31541).
+char(0,31542).
+char(c,31543).
+char(m,31544).
+char(4,31545).
+char(3,31546).
+char(1,31547).
+char(2,31548).
+char(p,31549).
+char(6,31550).
+char(0,31551).
+char(3,31552).
+char(0,31553).
+char(m,31554).
+char(o,31555).
+char(8,31556).
+char(7,31557).
+char(8,31558).
+char(3,31559).
+char(m,31560).
+char(3,31561).
+char(6,31562).
+char(9,31563).
+char(1,31564).
+char(p,31565).
+char(o,31566).
+char(m,31567).
+char(o,31568).
+char(m,31569).
+char(2,31570).
+char(7,31571).
+char(5,31572).
+char(3,31573).
+char(c,31574).
+char(c,31575).
+char(m,31576).
+char(1,31577).
+char(4,31578).
+char(8,31579).
+char(8,31580).
+char(c,31581).
+char(p,31582).
+char(5,31583).
+char(9,31584).
+char(7,31585).
+char(1,31586).
+char(p,31587).
+char(7,31588).
+char(5,31589).
+char(7,31590).
+char(9,31591).
+char(p,31592).
+char(o,31593).
+char(p,31594).
+char(3,31595).
+char(6,31596).
+char(6,31597).
+char(5,31598).
+char(c,31599).
+char(c,31600).
+char(c,31601).
+char(c,31602).
+char(p,31603).
+char(o,31604).
+char(m,31605).
+char(6,31606).
+char(0,31607).
+char(2,31608).
+char(6,31609).
+char(m,31610).
+char(2,31611).
+char(8,31612).
+char(7,31613).
+char(3,31614).
+char(c,31615).
+char(c,31616).
+char(c,31617).
+char(m,31618).
+char(2,31619).
+char(8,31620).
+char(2,31621).
+char(4,31622).
+char(c,31623).
+char(m,31624).
+char(3,31625).
+char(3,31626).
+char(2,31627).
+char(9,31628).
+char(p,31629).
+char(o,31630).
+char(p,31631).
+char(8,31632).
+char(9,31633).
+char(4,31634).
+char(6,31635).
+char(m,31636).
+char(5,31637).
+char(7,31638).
+char(7,31639).
+char(4,31640).
+char(c,31641).
+char(c,31642).
+char(c,31643).
+char(m,31644).
+char(7,31645).
+char(8,31646).
+char(7,31647).
+char(6,31648).
+char(c,31649).
+char(c,31650).
+char(c,31651).
+char(p,31652).
+char(o,31653).
+char(p,31654).
+char(5,31655).
+char(2,31656).
+char(6,31657).
+char(1,31658).
+char(c,31659).
+char(p,31660).
+char(o,31661).
+char(m,31662).
+char(o,31663).
+char(1,31664).
+char(5,31665).
+char(2,31666).
+char(5,31667).
+char(p,31668).
+char(4,31669).
+char(4,31670).
+char(7,31671).
+char(9,31672).
+char(p,31673).
+char(o,31674).
+char(m,31675).
+char(9,31676).
+char(7,31677).
+char(3,31678).
+char(6,31679).
+char(p,31680).
+char(o,31681).
+char(p,31682).
+char(1,31683).
+char(2,31684).
+char(1,31685).
+char(8,31686).
+char(c,31687).
+char(c,31688).
+char(p,31689).
+char(o,31690).
+char(p,31691).
+char(o,31692).
+char(p,31693).
+char(5,31694).
+char(5,31695).
+char(6,31696).
+char(9,31697).
+char(c,31698).
+char(c,31699).
+char(c,31700).
+char(c,31701).
+char(p,31702).
+char(o,31703).
+char(p,31704).
+char(o,31705).
+char(m,31706).
+char(o,31707).
+char(5,31708).
+char(7,31709).
+char(2,31710).
+char(9,31711).
+char(c,31712).
+char(c,31713).
+char(c,31714).
+char(c,31715).
+char(c,31716).
+char(c,31717).
+char(p,31718).
+char(o,31719).
+char(p,31720).
+char(o,31721).
+char(p,31722).
+char(4,31723).
+char(7,31724).
+char(9,31725).
+char(5,31726).
+char(c,31727).
+char(m,31728).
+char(7,31729).
+char(6,31730).
+char(6,31731).
+char(7,31732).
+char(c,31733).
+char(c,31734).
+char(c,31735).
+char(p,31736).
+char(1,31737).
+char(0,31738).
+char(9,31739).
+char(p,31740).
+char(3,31741).
+char(5,31742).
+char(1,31743).
+char(7,31744).
+char(m,31745).
+char(4,31746).
+char(3,31747).
+char(5,31748).
+char(2,31749).
+char(m,31750).
+char(7,31751).
+char(6,31752).
+char(9,31753).
+char(1,31754).
+char(c,31755).
+char(c,31756).
+char(c,31757).
+char(m,31758).
+char(o,31759).
+char(m,31760).
+char(8,31761).
+char(5,31762).
+char(9,31763).
+char(0,31764).
+char(m,31765).
+char(o,31766).
+char(p,31767).
+char(o,31768).
+char(p,31769).
+char(o,31770).
+char(p,31771).
+char(4,31772).
+char(9,31773).
+char(9,31774).
+char(1,31775).
+char(p,31776).
+char(o,31777).
+char(m,31778).
+char(7,31779).
+char(0,31780).
+char(3,31781).
+char(0,31782).
+char(p,31783).
+char(o,31784).
+char(o,31785).
+char(p,31786).
+char(8,31787).
+char(6,31788).
+char(6,31789).
+char(6,31790).
+char(c,31791).
+char(p,31792).
+char(2,31793).
+char(9,31794).
+char(6,31795).
+char(3,31796).
+char(m,31797).
+char(o,31798).
+char(p,31799).
+char(2,31800).
+char(7,31801).
+char(7,31802).
+char(0,31803).
+char(m,31804).
+char(7,31805).
+char(6,31806).
+char(5,31807).
+char(p,31808).
+char(o,31809).
+char(m,31810).
+char(o,31811).
+char(o,31812).
+char(o,31813).
+char(1,31814).
+char(1,31815).
+char(4,31816).
+char(1,31817).
+char(m,31818).
+char(o,31819).
+char(m,31820).
+char(5,31821).
+char(2,31822).
+char(9,31823).
+char(9,31824).
+char(c,31825).
+char(c,31826).
+char(c,31827).
+char(m,31828).
+char(9,31829).
+char(6,31830).
+char(0,31831).
+char(3,31832).
+char(m,31833).
+char(2,31834).
+char(8,31835).
+char(5,31836).
+char(c,31837).
+char(p,31838).
+char(4,31839).
+char(7,31840).
+char(6,31841).
+char(2,31842).
+char(p,31843).
+char(3,31844).
+char(6,31845).
+char(3,31846).
+char(6,31847).
+char(p,31848).
+char(5,31849).
+char(4,31850).
+char(c,31851).
+char(c,31852).
+char(c,31853).
+char(c,31854).
+char(c,31855).
+char(c,31856).
+char(c,31857).
+char(m,31858).
+char(o,31859).
+char(m,31860).
+char(4,31861).
+char(7,31862).
+char(2,31863).
+char(7,31864).
+char(p,31865).
+char(7,31866).
+char(1,31867).
+char(5,31868).
+char(8,31869).
+char(c,31870).
+char(m,31871).
+char(o,31872).
+char(p,31873).
+char(9,31874).
+char(5,31875).
+char(1,31876).
+char(7,31877).
+char(p,31878).
+char(o,31879).
+char(o,31880).
+char(p,31881).
+char(4,31882).
+char(2,31883).
+char(1,31884).
+char(9,31885).
+char(p,31886).
+char(3,31887).
+char(1,31888).
+char(5,31889).
+char(8,31890).
+char(c,31891).
+char(c,31892).
+char(c,31893).
+char(c,31894).
+char(m,31895).
+char(o,31896).
+char(p,31897).
+char(9,31898).
+char(1,31899).
+char(3,31900).
+char(5,31901).
+char(p,31902).
+char(5,31903).
+char(6,31904).
+char(3,31905).
+char(9,31906).
+char(m,31907).
+char(o,31908).
+char(p,31909).
+char(o,31910).
+char(p,31911).
+char(o,31912).
+char(m,31913).
+char(o,31914).
+char(o,31915).
+char(m,31916).
+char(1,31917).
+char(7,31918).
+char(7,31919).
+char(1,31920).
+char(c,31921).
+char(c,31922).
+char(m,31923).
+char(2,31924).
+char(5,31925).
+char(1,31926).
+char(0,31927).
+char(p,31928).
+char(7,31929).
+char(1,31930).
+char(9,31931).
+char(6,31932).
+char(c,31933).
+char(m,31934).
+char(8,31935).
+char(1,31936).
+char(7,31937).
+char(5,31938).
+char(m,31939).
+char(o,31940).
+char(p,31941).
+char(o,31942).
+char(m,31943).
+char(7,31944).
+char(8,31945).
+char(4,31946).
+char(5,31947).
+char(m,31948).
+char(2,31949).
+char(9,31950).
+char(4,31951).
+char(8,31952).
+char(c,31953).
+char(c,31954).
+char(c,31955).
+char(c,31956).
+char(m,31957).
+char(o,31958).
+char(m,31959).
+char(7,31960).
+char(7,31961).
+char(4,31962).
+char(2,31963).
+char(p,31964).
+char(2,31965).
+char(6,31966).
+char(1,31967).
+char(8,31968).
+char(c,31969).
+char(c,31970).
+char(c,31971).
+char(c,31972).
+char(c,31973).
+char(c,31974).
+char(m,31975).
+char(8,31976).
+char(6,31977).
+char(7,31978).
+char(4,31979).
+char(p,31980).
+char(o,31981).
+char(o,31982).
+char(o,31983).
+char(m,31984).
+char(o,31985).
+char(2,31986).
+char(3,31987).
+char(3,31988).
+char(9,31989).
+char(m,31990).
+char(5,31991).
+char(0,31992).
+char(1,31993).
+char(7,31994).
+char(c,31995).
+char(c,31996).
+char(p,31997).
+char(o,31998).
+char(p,31999).
+char(o,32000).
+char(o,32001).
+char(p,32002).
+char(4,32003).
+char(5,32004).
+char(9,32005).
+char(8,32006).
+char(c,32007).
+char(m,32008).
+char(9,32009).
+char(2,32010).
+char(6,32011).
+char(9,32012).
+char(c,32013).
+char(c,32014).
+char(p,32015).
+char(o,32016).
+char(m,32017).
+char(4,32018).
+char(2,32019).
+char(6,32020).
+char(8,32021).
+char(c,32022).
+char(m,32023).
+char(2,32024).
+char(2,32025).
+char(9,32026).
+char(2,32027).
+char(m,32028).
+char(o,32029).
+char(m,32030).
+char(1,32031).
+char(9,32032).
+char(3,32033).
+char(4,32034).
+char(p,32035).
+char(5,32036).
+char(1,32037).
+char(6,32038).
+char(9,32039).
+char(p,32040).
+char(5,32041).
+char(6,32042).
+char(7,32043).
+char(4,32044).
+char(p,32045).
+char(4,32046).
+char(6,32047).
+char(3,32048).
+char(1,32049).
+char(m,32050).
+char(o,32051).
+char(1,32052).
+char(9,32053).
+char(2,32054).
+char(8,32055).
+char(c,32056).
+char(m,32057).
+char(o,32058).
+char(m,32059).
+char(3,32060).
+char(0,32061).
+char(7,32062).
+char(8,32063).
+char(c,32064).
+char(c,32065).
+char(m,32066).
+char(o,32067).
+char(p,32068).
+char(2,32069).
+char(9,32070).
+char(1,32071).
+char(2,32072).
+char(c,32073).
+char(c,32074).
+char(p,32075).
+char(3,32076).
+char(6,32077).
+char(1,32078).
+char(4,32079).
+char(p,32080).
+char(8,32081).
+char(8,32082).
+char(3,32083).
+char(8,32084).
+char(c,32085).
+char(c,32086).
+char(p,32087).
+char(o,32088).
+char(m,32089).
+char(o,32090).
+char(m,32091).
+char(o,32092).
+char(m,32093).
+char(6,32094).
+char(7,32095).
+char(1,32096).
+char(m,32097).
+char(1,32098).
+char(6,32099).
+char(0,32100).
+char(2,32101).
+char(p,32102).
+char(o,32103).
+char(7,32104).
+char(6,32105).
+char(8,32106).
+char(c,32107).
+char(p,32108).
+char(o,32109).
+char(m,32110).
+char(o,32111).
+char(o,32112).
+char(o,32113).
+char(p,32114).
+char(o,32115).
+char(8,32116).
+char(0,32117).
+char(5,32118).
+char(9,32119).
+char(p,32120).
+char(o,32121).
+char(m,32122).
+char(7,32123).
+char(0,32124).
+char(7,32125).
+char(5,32126).
+char(p,32127).
+char(o,32128).
+char(6,32129).
+char(3,32130).
+char(4,32131).
+char(c,32132).
+char(c,32133).
+char(p,32134).
+char(1,32135).
+char(2,32136).
+char(2,32137).
+char(0,32138).
+char(m,32139).
+char(2,32140).
+char(8,32141).
+char(4,32142).
+char(m,32143).
+char(o,32144).
+char(8,32145).
+char(6,32146).
+char(9,32147).
+char(5,32148).
+char(c,32149).
+char(c,32150).
+char(c,32151).
+char(c,32152).
+char(c,32153).
+char(c,32154).
+char(p,32155).
+char(o,32156).
+char(p,32157).
+char(8,32158).
+char(4,32159).
+char(3,32160).
+char(c,32161).
+char(c,32162).
+char(p,32163).
+char(o,32164).
+char(m,32165).
+char(9,32166).
+char(7,32167).
+char(9,32168).
+char(0,32169).
+char(c,32170).
+char(m,32171).
+char(o,32172).
+char(p,32173).
+char(o,32174).
+char(p,32175).
+char(o,32176).
+char(m,32177).
+char(1,32178).
+char(9,32179).
+char(1,32180).
+char(9,32181).
+char(m,32182).
+char(2,32183).
+char(6,32184).
+char(4,32185).
+char(0,32186).
+char(c,32187).
+char(m,32188).
+char(o,32189).
+char(3,32190).
+char(5,32191).
+char(0,32192).
+char(8,32193).
+char(m,32194).
+char(6,32195).
+char(4,32196).
+char(7,32197).
+char(3,32198).
+char(c,32199).
+char(c,32200).
+char(p,32201).
+char(o,32202).
+char(6,32203).
+char(3,32204).
+char(7,32205).
+char(1,32206).
+char(m,32207).
+char(o,32208).
+char(p,32209).
+char(o,32210).
+char(m,32211).
+char(3,32212).
+char(3,32213).
+char(1,32214).
+char(3,32215).
+char(c,32216).
+char(c,32217).
+char(m,32218).
+char(o,32219).
+char(m,32220).
+char(o,32221).
+char(m,32222).
+char(o,32223).
+char(9,32224).
+char(5,32225).
+char(8,32226).
+char(3,32227).
+char(c,32228).
+char(m,32229).
+char(5,32230).
+char(7,32231).
+char(8,32232).
+char(1,32233).
+char(c,32234).
+char(p,32235).
+char(4,32236).
+char(1,32237).
+char(8,32238).
+char(9,32239).
+char(c,32240).
+char(m,32241).
+char(2,32242).
+char(8,32243).
+char(9,32244).
+char(4,32245).
+char(m,32246).
+char(o,32247).
+char(p,32248).
+char(o,32249).
+char(9,32250).
+char(4,32251).
+char(4,32252).
+char(7,32253).
+char(m,32254).
+char(o,32255).
+char(p,32256).
+char(o,32257).
+char(m,32258).
+char(o,32259).
+char(4,32260).
+char(1,32261).
+char(9,32262).
+char(7,32263).
+char(c,32264).
+char(c,32265).
+char(c,32266).
+char(m,32267).
+char(o,32268).
+char(6,32269).
+char(0,32270).
+char(9,32271).
+char(3,32272).
+char(p,32273).
+char(o,32274).
+char(o,32275).
+char(4,32276).
+char(5,32277).
+char(9,32278).
+char(m,32279).
+char(o,32280).
+char(p,32281).
+char(2,32282).
+char(0,32283).
+char(7,32284).
+char(9,32285).
+char(c,32286).
+char(m,32287).
+char(7,32288).
+char(8,32289).
+char(0,32290).
+char(6,32291).
+char(c,32292).
+char(c,32293).
+char(c,32294).
+char(c,32295).
+char(c,32296).
+char(c,32297).
+char(m,32298).
+char(o,32299).
+char(m,32300).
+char(o,32301).
+char(p,32302).
+char(4,32303).
+char(1,32304).
+char(2,32305).
+char(8,32306).
+char(c,32307).
+char(c,32308).
+char(p,32309).
+char(3,32310).
+char(8,32311).
+char(8,32312).
+char(4,32313).
+char(c,32314).
+char(m,32315).
+char(o,32316).
+char(m,32317).
+char(o,32318).
+char(p,32319).
+char(2,32320).
+char(9,32321).
+char(2,32322).
+char(9,32323).
+char(m,32324).
+char(o,32325).
+char(p,32326).
+char(o,32327).
+char(p,32328).
+char(o,32329).
+char(m,32330).
+char(o,32331).
+char(m,32332).
+char(o,32333).
+char(m,32334).
+char(o,32335).
+char(p,32336).
+char(4,32337).
+char(1,32338).
+char(6,32339).
+char(5,32340).
+char(m,32341).
+char(8,32342).
+char(3,32343).
+char(0,32344).
+char(7,32345).
+char(p,32346).
+char(8,32347).
+char(9,32348).
+char(2,32349).
+char(9,32350).
+char(c,32351).
+char(c,32352).
+char(c,32353).
+char(c,32354).
+char(p,32355).
+char(9,32356).
+char(1,32357).
+char(7,32358).
+char(3,32359).
+char(m,32360).
+char(3,32361).
+char(0,32362).
+char(9,32363).
+char(0,32364).
+char(p,32365).
+char(3,32366).
+char(1,32367).
+char(2,32368).
+char(7,32369).
+char(m,32370).
+char(o,32371).
+char(o,32372).
+char(p,32373).
+char(5,32374).
+char(6,32375).
+char(2,32376).
+char(4,32377).
+char(c,32378).
+char(m,32379).
+char(9,32380).
+char(5,32381).
+char(7,32382).
+char(2,32383).
+char(c,32384).
+char(p,32385).
+char(o,32386).
+char(p,32387).
+char(9,32388).
+char(8,32389).
+char(8,32390).
+char(1,32391).
+char(m,32392).
+char(o,32393).
+char(p,32394).
+char(o,32395).
+char(5,32396).
+char(1,32397).
+char(9,32398).
+char(c,32399).
+char(c,32400).
+char(c,32401).
+char(c,32402).
+char(c,32403).
+char(c,32404).
+char(c,32405).
+char(p,32406).
+char(o,32407).
+char(p,32408).
+char(3,32409).
+char(2,32410).
+char(8,32411).
+char(1,32412).
+char(m,32413).
+char(4,32414).
+char(7,32415).
+char(7,32416).
+char(6,32417).
+char(c,32418).
+char(c,32419).
+char(p,32420).
+char(9,32421).
+char(4,32422).
+char(1,32423).
+char(3,32424).
+char(c,32425).
+char(c,32426).
+char(p,32427).
+char(o,32428).
+char(p,32429).
+char(1,32430).
+char(2,32431).
+char(5,32432).
+char(5,32433).
+char(p,32434).
+char(9,32435).
+char(9,32436).
+char(3,32437).
+char(2,32438).
+char(c,32439).
+char(m,32440).
+char(6,32441).
+char(6,32442).
+char(1,32443).
+char(4,32444).
+char(m,32445).
+char(7,32446).
+char(1,32447).
+char(4,32448).
+char(0,32449).
+char(p,32450).
+char(o,32451).
+char(m,32452).
+char(o,32453).
+char(p,32454).
+char(3,32455).
+char(3,32456).
+char(8,32457).
+char(0,32458).
+char(m,32459).
+char(o,32460).
+char(m,32461).
+char(o,32462).
+char(m,32463).
+char(4,32464).
+char(9,32465).
+char(3,32466).
+char(3,32467).
+char(c,32468).
+char(p,32469).
+char(o,32470).
+char(m,32471).
+char(o,32472).
+char(m,32473).
+char(7,32474).
+char(4,32475).
+char(8,32476).
+char(4,32477).
+char(m,32478).
+char(o,32479).
+char(m,32480).
+char(o,32481).
+char(m,32482).
+char(o,32483).
+char(2,32484).
+char(0,32485).
+char(5,32486).
+char(0,32487).
+char(p,32488).
+char(o,32489).
+char(m,32490).
+char(1,32491).
+char(6,32492).
+char(2,32493).
+char(0,32494).
+char(c,32495).
+char(m,32496).
+char(4,32497).
+char(9,32498).
+char(3,32499).
+char(6,32500).
+char(p,32501).
+char(3,32502).
+char(1,32503).
+char(9,32504).
+char(m,32505).
+char(o,32506).
+char(o,32507).
+char(o,32508).
+char(p,32509).
+char(8,32510).
+char(1,32511).
+char(8,32512).
+char(3,32513).
+char(c,32514).
+char(c,32515).
+char(c,32516).
+char(c,32517).
+char(c,32518).
+char(m,32519).
+char(5,32520).
+char(0,32521).
+char(8,32522).
+char(7,32523).
+char(c,32524).
+char(c,32525).
+char(c,32526).
+char(m,32527).
+char(6,32528).
+char(9,32529).
+char(4,32530).
+char(c,32531).
+char(m,32532).
+char(o,32533).
+char(7,32534).
+char(5,32535).
+char(7,32536).
+char(4,32537).
+char(p,32538).
+char(o,32539).
+char(o,32540).
+char(3,32541).
+char(0,32542).
+char(8,32543).
+char(8,32544).
+char(m,32545).
+char(1,32546).
+char(0,32547).
+char(7,32548).
+char(3,32549).
+char(c,32550).
+char(p,32551).
+char(5,32552).
+char(8,32553).
+char(9,32554).
+char(4,32555).
+char(c,32556).
+char(m,32557).
+char(6,32558).
+char(1,32559).
+char(5,32560).
+char(6,32561).
+char(m,32562).
+char(5,32563).
+char(5,32564).
+char(0,32565).
+char(4,32566).
+char(p,32567).
+char(o,32568).
+char(p,32569).
+char(o,32570).
+char(o,32571).
+char(m,32572).
+char(8,32573).
+char(7,32574).
+char(p,32575).
+char(6,32576).
+char(4,32577).
+char(6,32578).
+char(0,32579).
+char(c,32580).
+char(c,32581).
+char(c,32582).
+char(c,32583).
+char(m,32584).
+char(o,32585).
+char(m,32586).
+char(o,32587).
+char(m,32588).
+char(o,32589).
+char(m,32590).
+char(o,32591).
+char(p,32592).
+char(4,32593).
+char(7,32594).
+char(1,32595).
+char(6,32596).
+char(p,32597).
+char(o,32598).
+char(m,32599).
+char(7,32600).
+char(7,32601).
+char(9,32602).
+char(4,32603).
+char(c,32604).
+char(c,32605).
+char(c,32606).
+char(c,32607).
+char(p,32608).
+char(o,32609).
+char(p,32610).
+char(o,32611).
+char(5,32612).
+char(9,32613).
+char(0,32614).
+char(8,32615).
+char(c,32616).
+char(c,32617).
+char(p,32618).
+char(2,32619).
+char(4,32620).
+char(2,32621).
+char(1,32622).
+char(c,32623).
+char(c,32624).
+char(c,32625).
+char(c,32626).
+char(p,32627).
+char(o,32628).
+char(m,32629).
+char(o,32630).
+char(p,32631).
+char(3,32632).
+char(9,32633).
+char(9,32634).
+char(c,32635).
+char(m,32636).
+char(1,32637).
+char(2,32638).
+char(6,32639).
+char(7,32640).
+char(c,32641).
+char(m,32642).
+char(9,32643).
+char(2,32644).
+char(7,32645).
+char(c,32646).
+char(p,32647).
+char(4,32648).
+char(8,32649).
+char(3,32650).
+char(3,32651).
+char(p,32652).
+char(8,32653).
+char(7,32654).
+char(8,32655).
+char(3,32656).
+char(c,32657).
+char(p,32658).
+char(3,32659).
+char(8,32660).
+char(2,32661).
+char(0,32662).
+char(p,32663).
+char(o,32664).
+char(p,32665).
+char(o,32666).
+char(3,32667).
+char(5,32668).
+char(8,32669).
+char(2,32670).
+char(c,32671).
+char(c,32672).
+char(c,32673).
+char(c,32674).
+char(p,32675).
+char(o,32676).
+char(4,32677).
+char(2,32678).
+char(6,32679).
+char(2,32680).
+char(c,32681).
+char(c,32682).
+char(p,32683).
+char(o,32684).
+char(o,32685).
+char(m,32686).
+char(o,32687).
+char(m,32688).
+char(7,32689).
+char(7,32690).
+char(3,32691).
+char(5,32692).
+char(c,32693).
+char(c,32694).
+char(p,32695).
+char(3,32696).
+char(4,32697).
+char(9,32698).
+char(1,32699).
+char(p,32700).
+char(o,32701).
+char(o,32702).
+char(p,32703).
+char(o,32704).
+char(p,32705).
+char(o,32706).
+char(p,32707).
+char(8,32708).
+char(6,32709).
+char(1,32710).
+char(6,32711).
+char(c,32712).
+char(c,32713).
+char(c,32714).
+char(c,32715).
+char(c,32716).
+char(p,32717).
+char(4,32718).
+char(8,32719).
+char(2,32720).
+char(9,32721).
+char(c,32722).
+char(m,32723).
+char(3,32724).
+char(5,32725).
+char(7,32726).
+char(9,32727).
+char(p,32728).
+char(2,32729).
+char(6,32730).
+char(2,32731).
+char(8,32732).
+char(p,32733).
+char(o,32734).
+char(o,32735).
+char(p,32736).
+char(o,32737).
+char(m,32738).
+char(o,32739).
+char(m,32740).
+char(o,32741).
+char(p,32742).
+char(o,32743).
+char(2,32744).
+char(9,32745).
+char(6,32746).
+char(9,32747).
+char(c,32748).
+char(p,32749).
+char(9,32750).
+char(6,32751).
+char(5,32752).
+char(4,32753).
+char(c,32754).
+char(c,32755).
+char(p,32756).
+char(o,32757).
+char(m,32758).
+char(4,32759).
+char(5,32760).
+char(6,32761).
+char(1,32762).
+char(m,32763).
+char(o,32764).
+char(o,32765).
+char(3,32766).
+char(5,32767).
+char(3,32768).
+char(0,32769).
+char(c,32770).
+char(c,32771).
+char(p,32772).
+char(o,32773).
+char(m,32774).
+char(o,32775).
+char(p,32776).
+char(8,32777).
+char(4,32778).
+char(0,32779).
+char(9,32780).
+char(c,32781).
+char(p,32782).
+char(o,32783).
+char(o,32784).
+char(p,32785).
+char(o,32786).
+char(p,32787).
+char(o,32788).
+char(p,32789).
+char(o,32790).
+char(o,32791).
+char(o,32792).
+char(8,32793).
+char(2,32794).
+char(4,32795).
+char(1,32796).
+char(m,32797).
+char(o,32798).
+char(p,32799).
+char(1,32800).
+char(6,32801).
+char(8,32802).
+char(p,32803).
+char(5,32804).
+char(5,32805).
+char(3,32806).
+char(6,32807).
+char(m,32808).
+char(2,32809).
+char(2,32810).
+char(2,32811).
+char(8,32812).
+char(c,32813).
+char(c,32814).
+char(p,32815).
+char(o,32816).
+char(o,32817).
+char(6,32818).
+char(4,32819).
+char(0,32820).
+char(2,32821).
+char(c,32822).
+char(c,32823).
+char(c,32824).
+char(p,32825).
+char(4,32826).
+char(6,32827).
+char(7,32828).
+char(4,32829).
+char(p,32830).
+char(1,32831).
+char(6,32832).
+char(5,32833).
+char(2,32834).
+char(m,32835).
+char(o,32836).
+char(m,32837).
+char(5,32838).
+char(6,32839).
+char(0,32840).
+char(m,32841).
+char(o,32842).
+char(1,32843).
+char(9,32844).
+char(2,32845).
+char(0,32846).
+char(p,32847).
+char(o,32848).
+char(2,32849).
+char(2,32850).
+char(7,32851).
+char(p,32852).
+char(8,32853).
+char(9,32854).
+char(7,32855).
+char(1,32856).
+char(c,32857).
+char(m,32858).
+char(o,32859).
+char(o,32860).
+char(p,32861).
+char(o,32862).
+char(o,32863).
+char(2,32864).
+char(6,32865).
+char(c,32866).
+char(c,32867).
+char(p,32868).
+char(5,32869).
+char(2,32870).
+char(4,32871).
+char(1,32872).
+char(p,32873).
+char(o,32874).
+char(p,32875).
+char(5,32876).
+char(3,32877).
+char(5,32878).
+char(3,32879).
+char(p,32880).
+char(8,32881).
+char(1,32882).
+char(4,32883).
+char(8,32884).
+char(m,32885).
+char(o,32886).
+char(m,32887).
+char(5,32888).
+char(4,32889).
+char(2,32890).
+char(3,32891).
+char(c,32892).
+char(c,32893).
+char(c,32894).
+char(p,32895).
+char(8,32896).
+char(0,32897).
+char(9,32898).
+char(c,32899).
+char(m,32900).
+char(o,32901).
+char(o,32902).
+char(m,32903).
+char(o,32904).
+char(o,32905).
+char(m,32906).
+char(1,32907).
+char(9,32908).
+char(0,32909).
+char(6,32910).
+char(c,32911).
+char(m,32912).
+char(o,32913).
+char(m,32914).
+char(o,32915).
+char(p,32916).
+char(7,32917).
+char(9,32918).
+char(2,32919).
+char(6,32920).
+char(m,32921).
+char(9,32922).
+char(7,32923).
+char(4,32924).
+char(8,32925).
+char(m,32926).
+char(3,32927).
+char(2,32928).
+char(4,32929).
+char(9,32930).
+char(c,32931).
+char(p,32932).
+char(5,32933).
+char(3,32934).
+char(6,32935).
+char(3,32936).
+char(m,32937).
+char(3,32938).
+char(8,32939).
+char(2,32940).
+char(5,32941).
+char(c,32942).
+char(c,32943).
+char(c,32944).
+char(c,32945).
+char(p,32946).
+char(o,32947).
+char(p,32948).
+char(1,32949).
+char(0,32950).
+char(2,32951).
+char(3,32952).
+char(m,32953).
+char(o,32954).
+char(p,32955).
+char(o,32956).
+char(m,32957).
+char(6,32958).
+char(7,32959).
+char(7,32960).
+char(2,32961).
+char(p,32962).
+char(6,32963).
+char(6,32964).
+char(0,32965).
+char(m,32966).
+char(o,32967).
+char(o,32968).
+char(p,32969).
+char(6,32970).
+char(3,32971).
+char(7,32972).
+char(8,32973).
+char(c,32974).
+char(m,32975).
+char(9,32976).
+char(1,32977).
+char(7,32978).
+char(6,32979).
+char(c,32980).
+char(m,32981).
+char(8,32982).
+char(8,32983).
+char(2,32984).
+char(5,32985).
+char(p,32986).
+char(3,32987).
+char(7,32988).
+char(9,32989).
+char(3,32990).
+char(c,32991).
+char(p,32992).
+char(2,32993).
+char(4,32994).
+char(3,32995).
+char(1,32996).
+char(m,32997).
+char(o,32998).
+char(m,32999).
+char(5,33000).
+char(0,33001).
+char(6,33002).
+char(4,33003).
+char(c,33004).
+char(c,33005).
+char(c,33006).
+char(p,33007).
+char(o,33008).
+char(o,33009).
+char(m,33010).
+char(3,33011).
+char(7,33012).
+char(3,33013).
+char(3,33014).
+char(c,33015).
+char(p,33016).
+char(4,33017).
+char(2,33018).
+char(7,33019).
+char(5,33020).
+char(c,33021).
+char(c,33022).
+char(m,33023).
+char(o,33024).
+char(m,33025).
+char(o,33026).
+char(p,33027).
+char(1,33028).
+char(3,33029).
+char(0,33030).
+char(9,33031).
+char(c,33032).
+char(p,33033).
+char(o,33034).
+char(6,33035).
+char(3,33036).
+char(1,33037).
+char(4,33038).
+char(c,33039).
+char(p,33040).
+char(o,33041).
+char(o,33042).
+char(p,33043).
+char(4,33044).
+char(6,33045).
+char(9,33046).
+char(c,33047).
+char(c,33048).
+char(c,33049).
+char(c,33050).
+char(m,33051).
+char(o,33052).
+char(o,33053).
+char(o,33054).
+char(p,33055).
+char(8,33056).
+char(2,33057).
+char(0,33058).
+char(8,33059).
+char(c,33060).
+char(p,33061).
+char(o,33062).
+char(o,33063).
+char(o,33064).
+char(m,33065).
+char(o,33066).
+char(7,33067).
+char(8,33068).
+char(4,33069).
+char(7,33070).
+char(m,33071).
+char(o,33072).
+char(o,33073).
+char(p,33074).
+char(o,33075).
+char(p,33076).
+char(o,33077).
+char(m,33078).
+char(o,33079).
+char(m,33080).
+char(o,33081).
+char(p,33082).
+char(o,33083).
+char(o,33084).
+char(o,33085).
+char(4,33086).
+char(0,33087).
+char(5,33088).
+char(1,33089).
+char(p,33090).
+char(6,33091).
+char(1,33092).
+char(1,33093).
+char(6,33094).
+char(m,33095).
+char(o,33096).
+char(p,33097).
+char(o,33098).
+char(p,33099).
+char(o,33100).
+char(4,33101).
+char(8,33102).
+char(3,33103).
+char(1,33104).
+char(c,33105).
+char(c,33106).
+char(c,33107).
+char(m,33108).
+char(5,33109).
+char(0,33110).
+char(2,33111).
+char(2,33112).
+char(c,33113).
+char(p,33114).
+char(2,33115).
+char(7,33116).
+char(2,33117).
+char(7,33118).
+char(p,33119).
+char(o,33120).
+char(p,33121).
+char(o,33122).
+char(o,33123).
+char(m,33124).
+char(o,33125).
+char(o,33126).
+char(8,33127).
+char(9,33128).
+char(6,33129).
+char(0,33130).
+char(c,33131).
+char(c,33132).
+char(p,33133).
+char(4,33134).
+char(2,33135).
+char(c,33136).
+char(c,33137).
+char(c,33138).
+char(c,33139).
+char(c,33140).
+char(m,33141).
+char(o,33142).
+char(o,33143).
+char(p,33144).
+char(8,33145).
+char(5,33146).
+char(8,33147).
+char(0,33148).
+char(c,33149).
+char(m,33150).
+char(3,33151).
+char(3,33152).
+char(2,33153).
+char(p,33154).
+char(3,33155).
+char(1,33156).
+char(4,33157).
+char(m,33158).
+char(o,33159).
+char(o,33160).
+char(o,33161).
+char(p,33162).
+char(3,33163).
+char(4,33164).
+char(3,33165).
+char(0,33166).
+char(p,33167).
+char(o,33168).
+char(p,33169).
+char(4,33170).
+char(9,33171).
+char(2,33172).
+char(6,33173).
+char(c,33174).
+char(c,33175).
+char(c,33176).
+char(m,33177).
+char(3,33178).
+char(2,33179).
+char(8,33180).
+char(9,33181).
+char(m,33182).
+char(o,33183).
+char(m,33184).
+char(5,33185).
+char(6,33186).
+char(0,33187).
+char(1,33188).
+char(m,33189).
+char(5,33190).
+char(2,33191).
+char(9,33192).
+char(0,33193).
+char(c,33194).
+char(m,33195).
+char(8,33196).
+char(4,33197).
+char(3,33198).
+char(4,33199).
+char(p,33200).
+char(3,33201).
+char(5,33202).
+char(6,33203).
+char(4,33204).
+char(m,33205).
+char(o,33206).
+char(p,33207).
+char(4,33208).
+char(6,33209).
+char(9,33210).
+char(2,33211).
+char(c,33212).
+char(p,33213).
+char(9,33214).
+char(5,33215).
+char(2,33216).
+char(1,33217).
+char(c,33218).
+char(m,33219).
+char(9,33220).
+char(8,33221).
+char(6,33222).
+char(5,33223).
+char(m,33224).
+char(8,33225).
+char(0,33226).
+char(9,33227).
+char(2,33228).
+char(c,33229).
+char(c,33230).
+char(m,33231).
+char(o,33232).
+char(o,33233).
+char(o,33234).
+char(4,33235).
+char(8,33236).
+char(7,33237).
+char(9,33238).
+char(c,33239).
+char(m,33240).
+char(1,33241).
+char(5,33242).
+char(4,33243).
+char(1,33244).
+char(p,33245).
+char(1,33246).
+char(7,33247).
+char(7,33248).
+char(7,33249).
+char(m,33250).
+char(5,33251).
+char(2,33252).
+char(6,33253).
+char(1,33254).
+char(c,33255).
+char(p,33256).
+char(o,33257).
+char(1,33258).
+char(0,33259).
+char(3,33260).
+char(6,33261).
+char(m,33262).
+char(4,33263).
+char(3,33264).
+char(8,33265).
+char(6,33266).
+char(p,33267).
+char(o,33268).
+char(m,33269).
+char(o,33270).
+char(o,33271).
+char(m,33272).
+char(9,33273).
+char(1,33274).
+char(4,33275).
+char(5,33276).
+char(p,33277).
+char(o,33278).
+char(m,33279).
+char(4,33280).
+char(0,33281).
+char(7,33282).
+char(1,33283).
+char(p,33284).
+char(o,33285).
+char(p,33286).
+char(1,33287).
+char(3,33288).
+char(0,33289).
+char(5,33290).
+char(m,33291).
+char(5,33292).
+char(8,33293).
+char(3,33294).
+char(3,33295).
+char(p,33296).
+char(o,33297).
+char(6,33298).
+char(3,33299).
+char(9,33300).
+char(5,33301).
+char(m,33302).
+char(7,33303).
+char(3,33304).
+char(0,33305).
+char(4,33306).
+char(p,33307).
+char(3,33308).
+char(8,33309).
+char(0,33310).
+char(3,33311).
+char(p,33312).
+char(o,33313).
+char(p,33314).
+char(o,33315).
+char(p,33316).
+char(9,33317).
+char(9,33318).
+char(1,33319).
+char(6,33320).
+char(c,33321).
+char(p,33322).
+char(2,33323).
+char(5,33324).
+char(9,33325).
+char(p,33326).
+char(3,33327).
+char(4,33328).
+char(4,33329).
+char(4,33330).
+char(c,33331).
+char(p,33332).
+char(6,33333).
+char(2,33334).
+char(6,33335).
+char(c,33336).
+char(p,33337).
+char(o,33338).
+char(p,33339).
+char(5,33340).
+char(2,33341).
+char(0,33342).
+char(7,33343).
+char(p,33344).
+char(o,33345).
+char(4,33346).
+char(4,33347).
+char(0,33348).
+char(1,33349).
+char(c,33350).
+char(c,33351).
+char(m,33352).
+char(8,33353).
+char(8,33354).
+char(1,33355).
+char(7,33356).
+char(p,33357).
+char(o,33358).
+char(m,33359).
+char(3,33360).
+char(0,33361).
+char(3,33362).
+char(1,33363).
+char(p,33364).
+char(5,33365).
+char(3,33366).
+char(6,33367).
+char(p,33368).
+char(o,33369).
+char(2,33370).
+char(9,33371).
+char(9,33372).
+char(5,33373).
+char(c,33374).
+char(c,33375).
+char(p,33376).
+char(o,33377).
+char(p,33378).
+char(o,33379).
+char(m,33380).
+char(o,33381).
+char(p,33382).
+char(o,33383).
+char(m,33384).
+char(3,33385).
+char(8,33386).
+char(2,33387).
+char(9,33388).
+char(c,33389).
+char(c,33390).
+char(c,33391).
+char(m,33392).
+char(o,33393).
+char(m,33394).
+char(4,33395).
+char(8,33396).
+char(6,33397).
+char(0,33398).
+char(c,33399).
+char(c,33400).
+char(m,33401).
+char(o,33402).
+char(7,33403).
+char(3,33404).
+char(3,33405).
+char(7,33406).
+char(c,33407).
+char(c,33408).
+char(c,33409).
+char(c,33410).
+char(p,33411).
+char(o,33412).
+char(p,33413).
+char(o,33414).
+char(p,33415).
+char(o,33416).
+char(m,33417).
+char(5,33418).
+char(8,33419).
+char(6,33420).
+char(0,33421).
+char(m,33422).
+char(7,33423).
+char(3,33424).
+char(7,33425).
+char(7,33426).
+char(c,33427).
+char(m,33428).
+char(1,33429).
+char(7,33430).
+char(3,33431).
+char(5,33432).
+char(c,33433).
+char(p,33434).
+char(9,33435).
+char(8,33436).
+char(9,33437).
+char(3,33438).
+char(p,33439).
+char(9,33440).
+char(1,33441).
+char(9,33442).
+char(6,33443).
+char(c,33444).
+char(p,33445).
+char(7,33446).
+char(9,33447).
+char(7,33448).
+char(0,33449).
+char(c,33450).
+char(p,33451).
+char(o,33452).
+char(1,33453).
+char(4,33454).
+char(6,33455).
+char(0,33456).
+char(c,33457).
+char(p,33458).
+char(o,33459).
+char(p,33460).
+char(o,33461).
+char(p,33462).
+char(o,33463).
+char(o,33464).
+char(p,33465).
+char(1,33466).
+char(4,33467).
+char(7,33468).
+char(5,33469).
+char(c,33470).
+char(c,33471).
+char(m,33472).
+char(o,33473).
+char(p,33474).
+char(4,33475).
+char(9,33476).
+char(1,33477).
+char(8,33478).
+char(c,33479).
+char(c,33480).
+char(m,33481).
+char(o,33482).
+char(o,33483).
+char(m,33484).
+char(o,33485).
+char(p,33486).
+char(6,33487).
+char(0,33488).
+char(4,33489).
+char(9,33490).
+char(c,33491).
+char(c,33492).
+char(m,33493).
+char(o,33494).
+char(p,33495).
+char(o,33496).
+char(6,33497).
+char(3,33498).
+char(9,33499).
+char(c,33500).
+char(c,33501).
+char(c,33502).
+char(p,33503).
+char(6,33504).
+char(0,33505).
+char(3,33506).
+char(2,33507).
+char(c,33508).
+char(c,33509).
+char(c,33510).
+char(m,33511).
+char(8,33512).
+char(3,33513).
+char(4,33514).
+char(8,33515).
+char(c,33516).
+char(p,33517).
+char(o,33518).
+char(p,33519).
+char(o,33520).
+char(m,33521).
+char(o,33522).
+char(p,33523).
+char(2,33524).
+char(8,33525).
+char(1,33526).
+char(1,33527).
+char(p,33528).
+char(o,33529).
+char(m,33530).
+char(8,33531).
+char(6,33532).
+char(6,33533).
+char(0,33534).
+char(c,33535).
+char(p,33536).
+char(o,33537).
+char(m,33538).
+char(2,33539).
+char(9,33540).
+char(4,33541).
+char(3,33542).
+char(m,33543).
+char(o,33544).
+char(p,33545).
+char(1,33546).
+char(4,33547).
+char(3,33548).
+char(5,33549).
+char(m,33550).
+char(5,33551).
+char(8,33552).
+char(0,33553).
+char(5,33554).
+char(p,33555).
+char(2,33556).
+char(3,33557).
+char(0,33558).
+char(2,33559).
+char(m,33560).
+char(o,33561).
+char(3,33562).
+char(8,33563).
+char(4,33564).
+char(c,33565).
+char(m,33566).
+char(6,33567).
+char(6,33568).
+char(5,33569).
+char(3,33570).
+char(p,33571).
+char(1,33572).
+char(7,33573).
+char(7,33574).
+char(5,33575).
+char(p,33576).
+char(o,33577).
+char(p,33578).
+char(1,33579).
+char(9,33580).
+char(4,33581).
+char(8,33582).
+char(c,33583).
+char(c,33584).
+char(p,33585).
+char(9,33586).
+char(2,33587).
+char(0,33588).
+char(9,33589).
+char(m,33590).
+char(o,33591).
+char(7,33592).
+char(0,33593).
+char(4,33594).
+char(5,33595).
+char(c,33596).
+char(p,33597).
+char(o,33598).
+char(p,33599).
+char(o,33600).
+char(o,33601).
+char(p,33602).
+char(9,33603).
+char(8,33604).
+char(4,33605).
+char(3,33606).
+char(c,33607).
+char(m,33608).
+char(o,33609).
+char(p,33610).
+char(7,33611).
+char(1,33612).
+char(6,33613).
+char(c,33614).
+char(c,33615).
+char(c,33616).
+char(c,33617).
+char(c,33618).
+char(p,33619).
+char(4,33620).
+char(6,33621).
+char(8,33622).
+char(9,33623).
+char(p,33624).
+char(5,33625).
+char(8,33626).
+char(3,33627).
+char(5,33628).
+char(p,33629).
+char(o,33630).
+char(p,33631).
+char(5,33632).
+char(3,33633).
+char(8,33634).
+char(9,33635).
+char(c,33636).
+char(c,33637).
+char(m,33638).
+char(o,33639).
+char(o,33640).
+char(p,33641).
+char(o,33642).
+char(m,33643).
+char(o,33644).
+char(m,33645).
+char(o,33646).
+char(m,33647).
+char(8,33648).
+char(4,33649).
+char(9,33650).
+char(0,33651).
+char(m,33652).
+char(6,33653).
+char(1,33654).
+char(4,33655).
+char(2,33656).
+char(p,33657).
+char(o,33658).
+char(p,33659).
+char(6,33660).
+char(3,33661).
+char(2,33662).
+char(9,33663).
+char(m,33664).
+char(8,33665).
+char(3,33666).
+char(6,33667).
+char(5,33668).
+char(c,33669).
+char(p,33670).
+char(5,33671).
+char(2,33672).
+char(5,33673).
+char(4,33674).
+char(m,33675).
+char(6,33676).
+char(1,33677).
+char(9,33678).
+char(2,33679).
+char(m,33680).
+char(3,33681).
+char(2,33682).
+char(3,33683).
+char(2,33684).
+char(c,33685).
+char(p,33686).
+char(o,33687).
+char(p,33688).
+char(o,33689).
+char(m,33690).
+char(o,33691).
+char(p,33692).
+char(7,33693).
+char(2,33694).
+char(6,33695).
+char(6,33696).
+char(c,33697).
+char(c,33698).
+char(p,33699).
+char(7,33700).
+char(8,33701).
+char(1,33702).
+char(6,33703).
+char(m,33704).
+char(4,33705).
+char(5,33706).
+char(9,33707).
+char(7,33708).
+char(c,33709).
+char(m,33710).
+char(1,33711).
+char(5,33712).
+char(5,33713).
+char(0,33714).
+char(c,33715).
+char(p,33716).
+char(8,33717).
+char(8,33718).
+char(6,33719).
+char(6,33720).
+char(m,33721).
+char(o,33722).
+char(1,33723).
+char(4,33724).
+char(5,33725).
+char(0,33726).
+char(m,33727).
+char(o,33728).
+char(m,33729).
+char(7,33730).
+char(9,33731).
+char(7,33732).
+char(5,33733).
+char(c,33734).
+char(p,33735).
+char(2,33736).
+char(8,33737).
+char(0,33738).
+char(8,33739).
+char(m,33740).
+char(o,33741).
+char(6,33742).
+char(5,33743).
+char(5,33744).
+char(3,33745).
+char(c,33746).
+char(c,33747).
+char(m,33748).
+char(8,33749).
+char(7,33750).
+char(0,33751).
+char(0,33752).
+char(p,33753).
+char(o,33754).
+char(1,33755).
+char(1,33756).
+char(4,33757).
+char(c,33758).
+char(p,33759).
+char(6,33760).
+char(3,33761).
+char(7,33762).
+char(5,33763).
+char(c,33764).
+char(c,33765).
+char(m,33766).
+char(9,33767).
+char(3,33768).
+char(9,33769).
+char(6,33770).
+char(m,33771).
+char(5,33772).
+char(2,33773).
+char(6,33774).
+char(6,33775).
+char(c,33776).
+char(c,33777).
+char(c,33778).
+char(m,33779).
+char(o,33780).
+char(4,33781).
+char(6,33782).
+char(8,33783).
+char(2,33784).
+char(m,33785).
+char(7,33786).
+char(8,33787).
+char(4,33788).
+char(1,33789).
+char(c,33790).
+char(c,33791).
+char(c,33792).
+char(m,33793).
+char(o,33794).
+char(9,33795).
+char(7,33796).
+char(5,33797).
+char(8,33798).
+char(c,33799).
+char(c,33800).
+char(m,33801).
+char(o,33802).
+char(m,33803).
+char(o,33804).
+char(o,33805).
+char(o,33806).
+char(m,33807).
+char(o,33808).
+char(m,33809).
+char(7,33810).
+char(9,33811).
+char(0,33812).
+char(5,33813).
+char(c,33814).
+char(p,33815).
+char(5,33816).
+char(3,33817).
+char(6,33818).
+char(3,33819).
+char(p,33820).
+char(2,33821).
+char(3,33822).
+char(4,33823).
+char(4,33824).
+char(c,33825).
+char(p,33826).
+char(o,33827).
+char(m,33828).
+char(o,33829).
+char(m,33830).
+char(8,33831).
+char(3,33832).
+char(6,33833).
+char(5,33834).
+char(c,33835).
+char(p,33836).
+char(8,33837).
+char(3,33838).
+char(3,33839).
+char(2,33840).
+char(c,33841).
+char(c,33842).
+char(c,33843).
+char(m,33844).
+char(9,33845).
+char(2,33846).
+char(9,33847).
+char(2,33848).
+char(c,33849).
+char(m,33850).
+char(4,33851).
+char(5,33852).
+char(0,33853).
+char(0,33854).
+char(p,33855).
+char(1,33856).
+char(4,33857).
+char(9,33858).
+char(2,33859).
+char(p,33860).
+char(5,33861).
+char(8,33862).
+char(4,33863).
+char(c,33864).
+char(c,33865).
+char(p,33866).
+char(o,33867).
+char(6,33868).
+char(1,33869).
+char(5,33870).
+char(8,33871).
+char(c,33872).
+char(p,33873).
+char(9,33874).
+char(2,33875).
+char(0,33876).
+char(2,33877).
+char(c,33878).
+char(p,33879).
+char(4,33880).
+char(6,33881).
+char(9,33882).
+char(c,33883).
+char(m,33884).
+char(o,33885).
+char(o,33886).
+char(p,33887).
+char(o,33888).
+char(m,33889).
+char(6,33890).
+char(1,33891).
+char(9,33892).
+char(2,33893).
+char(c,33894).
+char(m,33895).
+char(o,33896).
+char(m,33897).
+char(o,33898).
+char(7,33899).
+char(2,33900).
+char(1,33901).
+char(6,33902).
+char(c,33903).
+char(c,33904).
+char(c,33905).
+char(p,33906).
+char(1,33907).
+char(8,33908).
+char(2,33909).
+char(2,33910).
+char(p,33911).
+char(9,33912).
+char(2,33913).
+char(1,33914).
+char(9,33915).
+char(c,33916).
+char(p,33917).
+char(o,33918).
+char(p,33919).
+char(9,33920).
+char(7,33921).
+char(p,33922).
+char(o,33923).
+char(1,33924).
+char(7,33925).
+char(4,33926).
+char(c,33927).
+char(p,33928).
+char(o,33929).
+char(p,33930).
+char(1,33931).
+char(8,33932).
+char(4,33933).
+char(1,33934).
+char(c,33935).
+char(c,33936).
+char(c,33937).
+char(c,33938).
+char(c,33939).
+char(c,33940).
+char(m,33941).
+char(o,33942).
+char(o,33943).
+char(p,33944).
+char(3,33945).
+char(5,33946).
+char(0,33947).
+char(7,33948).
+char(p,33949).
+char(o,33950).
+char(m,33951).
+char(o,33952).
+char(1,33953).
+char(9,33954).
+char(1,33955).
+char(1,33956).
+char(m,33957).
+char(o,33958).
+char(m,33959).
+char(o,33960).
+char(p,33961).
+char(o,33962).
+char(o,33963).
+char(7,33964).
+char(0,33965).
+char(9,33966).
+char(p,33967).
+char(1,33968).
+char(4,33969).
+char(1,33970).
+char(4,33971).
+char(c,33972).
+char(m,33973).
+char(o,33974).
+char(3,33975).
+char(3,33976).
+char(7,33977).
+char(8,33978).
+char(c,33979).
+char(c,33980).
+char(p,33981).
+char(o,33982).
+char(o,33983).
+char(m,33984).
+char(1,33985).
+char(1,33986).
+char(9,33987).
+char(3,33988).
+char(c,33989).
+char(m,33990).
+char(o,33991).
+char(p,33992).
+char(6,33993).
+char(1,33994).
+char(1,33995).
+char(6,33996).
+char(m,33997).
+char(3,33998).
+char(1,33999).
+char(9,34000).
+char(0,34001).
+char(m,34002).
+char(o,34003).
+char(p,34004).
+char(o,34005).
+char(1,34006).
+char(4,34007).
+char(3,34008).
+char(0,34009).
+char(c,34010).
+char(m,34011).
+char(o,34012).
+char(o,34013).
+char(m,34014).
+char(8,34015).
+char(0,34016).
+char(2,34017).
+char(4,34018).
+char(c,34019).
+char(m,34020).
+char(1,34021).
+char(0,34022).
+char(9,34023).
+char(2,34024).
+char(m,34025).
+char(o,34026).
+char(2,34027).
+char(9,34028).
+char(8,34029).
+char(7,34030).
+char(m,34031).
+char(2,34032).
+char(0,34033).
+char(3,34034).
+char(c,34035).
+char(m,34036).
+char(o,34037).
+char(m,34038).
+char(3,34039).
+char(7,34040).
+char(8,34041).
+char(3,34042).
+char(p,34043).
+char(o,34044).
+char(m,34045).
+char(o,34046).
+char(o,34047).
+char(p,34048).
+char(4,34049).
+char(3,34050).
+char(6,34051).
+char(6,34052).
+char(c,34053).
+char(m,34054).
+char(o,34055).
+char(p,34056).
+char(6,34057).
+char(0,34058).
+char(1,34059).
+char(0,34060).
+char(c,34061).
+char(m,34062).
+char(8,34063).
+char(5,34064).
+char(9,34065).
+char(8,34066).
+char(c,34067).
+char(p,34068).
+char(o,34069).
+char(p,34070).
+char(o,34071).
+char(6,34072).
+char(4,34073).
+char(5,34074).
+char(4,34075).
+char(m,34076).
+char(1,34077).
+char(8,34078).
+char(7,34079).
+char(1,34080).
+char(c,34081).
+char(p,34082).
+char(5,34083).
+char(1,34084).
+char(0,34085).
+char(9,34086).
+char(c,34087).
+char(c,34088).
+char(c,34089).
+char(p,34090).
+char(o,34091).
+char(p,34092).
+char(o,34093).
+char(m,34094).
+char(o,34095).
+char(p,34096).
+char(8,34097).
+char(7,34098).
+char(3,34099).
+char(5,34100).
+char(c,34101).
+char(c,34102).
+char(m,34103).
+char(o,34104).
+char(p,34105).
+char(o,34106).
+char(m,34107).
+char(o,34108).
+char(m,34109).
+char(o,34110).
+char(o,34111).
+char(m,34112).
+char(6,34113).
+char(9,34114).
+char(1,34115).
+char(6,34116).
+char(c,34117).
+char(p,34118).
+char(o,34119).
+char(m,34120).
+char(8,34121).
+char(4,34122).
+char(7,34123).
+char(6,34124).
+char(c,34125).
+char(m,34126).
+char(o,34127).
+char(o,34128).
+char(p,34129).
+char(o,34130).
+char(m,34131).
+char(1,34132).
+char(3,34133).
+char(9,34134).
+char(0,34135).
+char(c,34136).
+char(m,34137).
+char(2,34138).
+char(1,34139).
+char(8,34140).
+char(5,34141).
+char(c,34142).
+char(c,34143).
+char(c,34144).
+char(m,34145).
+char(8,34146).
+char(0,34147).
+char(0,34148).
+char(9,34149).
+char(c,34150).
+char(m,34151).
+char(8,34152).
+char(0,34153).
+char(3,34154).
+char(4,34155).
+char(c,34156).
+char(p,34157).
+char(1,34158).
+char(0,34159).
+char(2,34160).
+char(3,34161).
+char(c,34162).
+char(m,34163).
+char(o,34164).
+char(p,34165).
+char(4,34166).
+char(2,34167).
+char(6,34168).
+char(0,34169).
+char(m,34170).
+char(o,34171).
+char(p,34172).
+char(o,34173).
+char(m,34174).
+char(9,34175).
+char(0,34176).
+char(0,34177).
+char(2,34178).
+char(c,34179).
+char(p,34180).
+char(o,34181).
+char(p,34182).
+char(5,34183).
+char(3,34184).
+char(8,34185).
+char(1,34186).
+char(c,34187).
+char(p,34188).
+char(o,34189).
+char(o,34190).
+char(p,34191).
+char(7,34192).
+char(2,34193).
+char(7,34194).
+char(1,34195).
+char(c,34196).
+char(c,34197).
+char(p,34198).
+char(9,34199).
+char(1,34200).
+char(9,34201).
+char(5,34202).
+char(m,34203).
+char(3,34204).
+char(1,34205).
+char(1,34206).
+char(m,34207).
+char(o,34208).
+char(p,34209).
+char(o,34210).
+char(m,34211).
+char(o,34212).
+char(m,34213).
+char(o,34214).
+char(m,34215).
+char(o,34216).
+char(m,34217).
+char(2,34218).
+char(9,34219).
+char(3,34220).
+char(1,34221).
+char(c,34222).
+char(p,34223).
+char(6,34224).
+char(5,34225).
+char(4,34226).
+char(7,34227).
+char(p,34228).
+char(9,34229).
+char(1,34230).
+char(5,34231).
+char(6,34232).
+char(m,34233).
+char(o,34234).
+char(m,34235).
+char(7,34236).
+char(3,34237).
+char(8,34238).
+char(4,34239).
+char(p,34240).
+char(7,34241).
+char(4,34242).
+char(4,34243).
+char(5,34244).
+char(c,34245).
+char(c,34246).
+char(c,34247).
+char(p,34248).
+char(1,34249).
+char(0,34250).
+char(1,34251).
+char(6,34252).
+char(c,34253).
+char(c,34254).
+char(m,34255).
+char(9,34256).
+char(1,34257).
+char(4,34258).
+char(3,34259).
+char(p,34260).
+char(6,34261).
+char(9,34262).
+char(6,34263).
+char(3,34264).
+char(c,34265).
+char(c,34266).
+char(p,34267).
+char(o,34268).
+char(p,34269).
+char(1,34270).
+char(1,34271).
+char(7,34272).
+char(0,34273).
+char(m,34274).
+char(o,34275).
+char(p,34276).
+char(4,34277).
+char(0,34278).
+char(2,34279).
+char(4,34280).
+char(m,34281).
+char(4,34282).
+char(8,34283).
+char(5,34284).
+char(3,34285).
+char(c,34286).
+char(m,34287).
+char(o,34288).
+char(p,34289).
+char(5,34290).
+char(5,34291).
+char(8,34292).
+char(2,34293).
+char(c,34294).
+char(m,34295).
+char(8,34296).
+char(7,34297).
+char(6,34298).
+char(2,34299).
+char(p,34300).
+char(5,34301).
+char(8,34302).
+char(2,34303).
+char(8,34304).
+char(m,34305).
+char(4,34306).
+char(1,34307).
+char(9,34308).
+char(1,34309).
+char(c,34310).
+char(c,34311).
+char(c,34312).
+char(c,34313).
+char(c,34314).
+char(p,34315).
+char(4,34316).
+char(9,34317).
+char(5,34318).
+char(3,34319).
+char(m,34320).
+char(7,34321).
+char(7,34322).
+char(4,34323).
+char(6,34324).
+char(c,34325).
+char(m,34326).
+char(o,34327).
+char(p,34328).
+char(o,34329).
+char(o,34330).
+char(m,34331).
+char(o,34332).
+char(p,34333).
+char(o,34334).
+char(o,34335).
+char(o,34336).
+char(p,34337).
+char(o,34338).
+char(p,34339).
+char(o,34340).
+char(p,34341).
+char(o,34342).
+char(m,34343).
+char(6,34344).
+char(3,34345).
+char(8,34346).
+char(m,34347).
+char(7,34348).
+char(0,34349).
+char(6,34350).
+char(3,34351).
+char(c,34352).
+char(m,34353).
+char(3,34354).
+char(9,34355).
+char(4,34356).
+char(5,34357).
+char(c,34358).
+char(c,34359).
+char(p,34360).
+char(o,34361).
+char(m,34362).
+char(4,34363).
+char(0,34364).
+char(8,34365).
+char(9,34366).
+char(m,34367).
+char(o,34368).
+char(p,34369).
+char(8,34370).
+char(7,34371).
+char(5,34372).
+char(6,34373).
+char(c,34374).
+char(c,34375).
+char(c,34376).
+char(m,34377).
+char(o,34378).
+char(m,34379).
+char(7,34380).
+char(7,34381).
+char(9,34382).
+char(9,34383).
+char(p,34384).
+char(8,34385).
+char(3,34386).
+char(1,34387).
+char(2,34388).
+char(m,34389).
+char(9,34390).
+char(3,34391).
+char(7,34392).
+char(9,34393).
+char(m,34394).
+char(9,34395).
+char(9,34396).
+char(7,34397).
+char(8,34398).
+char(c,34399).
+char(m,34400).
+char(o,34401).
+char(p,34402).
+char(o,34403).
+char(9,34404).
+char(4,34405).
+char(0,34406).
+char(6,34407).
+char(p,34408).
+char(o,34409).
+char(m,34410).
+char(o,34411).
+char(m,34412).
+char(o,34413).
+char(p,34414).
+char(2,34415).
+char(3,34416).
+char(0,34417).
+char(7,34418).
+char(c,34419).
+char(c,34420).
+char(c,34421).
+char(c,34422).
+char(p,34423).
+char(2,34424).
+char(7,34425).
+char(9,34426).
+char(4,34427).
+char(m,34428).
+char(o,34429).
+char(o,34430).
+char(m,34431).
+char(o,34432).
+char(4,34433).
+char(5,34434).
+char(5,34435).
+char(1,34436).
+char(m,34437).
+char(o,34438).
+char(p,34439).
+char(o,34440).
+char(p,34441).
+char(9,34442).
+char(2,34443).
+char(5,34444).
+char(8,34445).
+char(c,34446).
+char(c,34447).
+char(c,34448).
+char(c,34449).
+char(c,34450).
+char(p,34451).
+char(3,34452).
+char(9,34453).
+char(1,34454).
+char(3,34455).
+char(c,34456).
+char(c,34457).
+char(p,34458).
+char(o,34459).
+char(m,34460).
+char(9,34461).
+char(8,34462).
+char(9,34463).
+char(6,34464).
+char(m,34465).
+char(9,34466).
+char(0,34467).
+char(1,34468).
+char(1,34469).
+char(c,34470).
+char(p,34471).
+char(5,34472).
+char(8,34473).
+char(6,34474).
+char(2,34475).
+char(c,34476).
+char(c,34477).
+char(p,34478).
+char(o,34479).
+char(p,34480).
+char(9,34481).
+char(2,34482).
+char(1,34483).
+char(5,34484).
+char(c,34485).
+char(p,34486).
+char(7,34487).
+char(8,34488).
+char(7,34489).
+char(3,34490).
+char(m,34491).
+char(o,34492).
+char(m,34493).
+char(5,34494).
+char(5,34495).
+char(9,34496).
+char(c,34497).
+char(c,34498).
+char(p,34499).
+char(o,34500).
+char(p,34501).
+char(o,34502).
+char(m,34503).
+char(o,34504).
+char(p,34505).
+char(o,34506).
+char(m,34507).
+char(7,34508).
+char(2,34509).
+char(6,34510).
+char(9,34511).
+char(c,34512).
+char(m,34513).
+char(o,34514).
+char(m,34515).
+char(o,34516).
+char(o,34517).
+char(m,34518).
+char(o,34519).
+char(m,34520).
+char(o,34521).
+char(2,34522).
+char(2,34523).
+char(8,34524).
+char(7,34525).
+char(c,34526).
+char(m,34527).
+char(o,34528).
+char(4,34529).
+char(5,34530).
+char(4,34531).
+char(5,34532).
+char(p,34533).
+char(7,34534).
+char(8,34535).
+char(1,34536).
+char(0,34537).
+char(c,34538).
+char(p,34539).
+char(o,34540).
+char(m,34541).
+char(3,34542).
+char(0,34543).
+char(6,34544).
+char(4,34545).
+char(m,34546).
+char(o,34547).
+char(o,34548).
+char(m,34549).
+char(o,34550).
+char(o,34551).
+char(o,34552).
+char(6,34553).
+char(9,34554).
+char(8,34555).
+char(m,34556).
+char(o,34557).
+char(p,34558).
+char(7,34559).
+char(3,34560).
+char(3,34561).
+char(7,34562).
+char(m,34563).
+char(4,34564).
+char(1,34565).
+char(6,34566).
+char(5,34567).
+char(m,34568).
+char(2,34569).
+char(2,34570).
+char(4,34571).
+char(2,34572).
+char(m,34573).
+char(o,34574).
+char(m,34575).
+char(o,34576).
+char(4,34577).
+char(7,34578).
+char(3,34579).
+char(0,34580).
+char(c,34581).
+char(p,34582).
+char(o,34583).
+char(m,34584).
+char(5,34585).
+char(6,34586).
+char(6,34587).
+char(2,34588).
+char(c,34589).
+char(c,34590).
+char(c,34591).
+char(p,34592).
+char(o,34593).
+char(m,34594).
+char(o,34595).
+char(m,34596).
+char(6,34597).
+char(4,34598).
+char(5,34599).
+char(c,34600).
+char(p,34601).
+char(2,34602).
+char(8,34603).
+char(2,34604).
+char(8,34605).
+char(c,34606).
+char(c,34607).
+char(c,34608).
+char(c,34609).
+char(m,34610).
+char(o,34611).
+char(p,34612).
+char(o,34613).
+char(p,34614).
+char(o,34615).
+char(1,34616).
+char(2,34617).
+char(8,34618).
+char(7,34619).
+char(m,34620).
+char(6,34621).
+char(9,34622).
+char(7,34623).
+char(p,34624).
+char(o,34625).
+char(m,34626).
+char(3,34627).
+char(7,34628).
+char(2,34629).
+char(2,34630).
+char(p,34631).
+char(o,34632).
+char(p,34633).
+char(o,34634).
+char(5,34635).
+char(8,34636).
+char(0,34637).
+char(7,34638).
+char(c,34639).
+char(m,34640).
+char(4,34641).
+char(7,34642).
+char(9,34643).
+char(1,34644).
+char(c,34645).
+char(c,34646).
+char(m,34647).
+char(5,34648).
+char(3,34649).
+char(0,34650).
+char(8,34651).
+char(c,34652).
+char(c,34653).
+char(c,34654).
+char(c,34655).
+char(c,34656).
+char(c,34657).
+char(c,34658).
+char(c,34659).
+char(p,34660).
+char(o,34661).
+char(p,34662).
+char(6,34663).
+char(0,34664).
+char(1,34665).
+char(9,34666).
+char(m,34667).
+char(2,34668).
+char(6,34669).
+char(9,34670).
+char(0,34671).
+char(m,34672).
+char(4,34673).
+char(3,34674).
+char(5,34675).
+char(5,34676).
+char(m,34677).
+char(6,34678).
+char(6,34679).
+char(8,34680).
+char(4,34681).
+char(m,34682).
+char(o,34683).
+char(2,34684).
+char(0,34685).
+char(8,34686).
+char(p,34687).
+char(o,34688).
+char(m,34689).
+char(o,34690).
+char(p,34691).
+char(o,34692).
+char(7,34693).
+char(0,34694).
+char(8,34695).
+char(c,34696).
+char(m,34697).
+char(5,34698).
+char(3,34699).
+char(7,34700).
+char(7,34701).
+char(c,34702).
+char(p,34703).
+char(o,34704).
+char(p,34705).
+char(1,34706).
+char(1,34707).
+char(6,34708).
+char(1,34709).
+char(c,34710).
+char(m,34711).
+char(o,34712).
+char(4,34713).
+char(2,34714).
+char(3,34715).
+char(4,34716).
+char(c,34717).
+char(c,34718).
+char(c,34719).
+char(p,34720).
+char(3,34721).
+char(5,34722).
+char(1,34723).
+char(3,34724).
+char(p,34725).
+char(1,34726).
+char(4,34727).
+char(5,34728).
+char(3,34729).
+char(c,34730).
+char(p,34731).
+char(7,34732).
+char(7,34733).
+char(0,34734).
+char(c,34735).
+char(m,34736).
+char(9,34737).
+char(5,34738).
+char(1,34739).
+char(6,34740).
+char(c,34741).
+char(c,34742).
+char(p,34743).
+char(o,34744).
+char(o,34745).
+char(o,34746).
+char(5,34747).
+char(1,34748).
+char(4,34749).
+char(4,34750).
+char(c,34751).
+char(c,34752).
+char(c,34753).
+char(c,34754).
+char(c,34755).
+char(m,34756).
+char(o,34757).
+char(5,34758).
+char(5,34759).
+char(6,34760).
+char(0,34761).
+char(m,34762).
+char(9,34763).
+char(5,34764).
+char(8,34765).
+char(8,34766).
+char(m,34767).
+char(o,34768).
+char(m,34769).
+char(8,34770).
+char(8,34771).
+char(3,34772).
+char(0,34773).
+char(c,34774).
+char(c,34775).
+char(c,34776).
+char(c,34777).
+char(m,34778).
+char(o,34779).
+char(p,34780).
+char(5,34781).
+char(8,34782).
+char(9,34783).
+char(8,34784).
+char(m,34785).
+char(o,34786).
+char(o,34787).
+char(m,34788).
+char(9,34789).
+char(1,34790).
+char(0,34791).
+char(1,34792).
+char(m,34793).
+char(o,34794).
+char(m,34795).
+char(9,34796).
+char(5,34797).
+char(7,34798).
+char(m,34799).
+char(o,34800).
+char(m,34801).
+char(o,34802).
+char(m,34803).
+char(o,34804).
+char(o,34805).
+char(9,34806).
+char(1,34807).
+char(0,34808).
+char(4,34809).
+char(c,34810).
+char(c,34811).
+char(c,34812).
+char(m,34813).
+char(8,34814).
+char(3,34815).
+char(5,34816).
+char(4,34817).
+char(c,34818).
+char(c,34819).
+char(c,34820).
+char(c,34821).
+char(p,34822).
+char(o,34823).
+char(p,34824).
+char(9,34825).
+char(3,34826).
+char(9,34827).
+char(2,34828).
+char(m,34829).
+char(4,34830).
+char(8,34831).
+char(7,34832).
+char(2,34833).
+char(c,34834).
+char(c,34835).
+char(c,34836).
+char(p,34837).
+char(o,34838).
+char(o,34839).
+char(o,34840).
+char(2,34841).
+char(1,34842).
+char(1,34843).
+char(7,34844).
+char(c,34845).
+char(p,34846).
+char(o,34847).
+char(1,34848).
+char(4,34849).
+char(9,34850).
+char(2,34851).
+char(m,34852).
+char(6,34853).
+char(0,34854).
+char(1,34855).
+char(7,34856).
+char(m,34857).
+char(o,34858).
+char(4,34859).
+char(8,34860).
+char(6,34861).
+char(5,34862).
+char(c,34863).
+char(m,34864).
+char(1,34865).
+char(7,34866).
+char(1,34867).
+char(1,34868).
+char(c,34869).
+char(m,34870).
+char(o,34871).
+char(m,34872).
+char(2,34873).
+char(8,34874).
+char(1,34875).
+char(0,34876).
+char(c,34877).
+char(c,34878).
+char(p,34879).
+char(o,34880).
+char(p,34881).
+char(2,34882).
+char(1,34883).
+char(0,34884).
+char(m,34885).
+char(7,34886).
+char(5,34887).
+char(7,34888).
+char(4,34889).
+char(m,34890).
+char(4,34891).
+char(8,34892).
+char(0,34893).
+char(4,34894).
+char(p,34895).
+char(9,34896).
+char(9,34897).
+char(0,34898).
+char(9,34899).
+char(m,34900).
+char(7,34901).
+char(0,34902).
+char(4,34903).
+char(8,34904).
+char(c,34905).
+char(c,34906).
+char(p,34907).
+char(o,34908).
+char(p,34909).
+char(4,34910).
+char(4,34911).
+char(9,34912).
+char(5,34913).
+char(c,34914).
+char(c,34915).
+char(c,34916).
+char(c,34917).
+char(c,34918).
+char(m,34919).
+char(o,34920).
+char(m,34921).
+char(o,34922).
+char(m,34923).
+char(o,34924).
+char(m,34925).
+char(o,34926).
+char(m,34927).
+char(o,34928).
+char(4,34929).
+char(1,34930).
+char(9,34931).
+char(8,34932).
+char(c,34933).
+char(m,34934).
+char(o,34935).
+char(p,34936).
+char(6,34937).
+char(6,34938).
+char(8,34939).
+char(6,34940).
+char(m,34941).
+char(o,34942).
+char(m,34943).
+char(8,34944).
+char(4,34945).
+char(5,34946).
+char(5,34947).
+char(p,34948).
+char(o,34949).
+char(6,34950).
+char(5,34951).
+char(8,34952).
+char(0,34953).
+char(p,34954).
+char(5,34955).
+char(1,34956).
+char(9,34957).
+char(c,34958).
+char(c,34959).
+char(c,34960).
+char(c,34961).
+char(m,34962).
+char(o,34963).
+char(p,34964).
+char(o,34965).
+char(o,34966).
+char(p,34967).
+char(o,34968).
+char(m,34969).
+char(o,34970).
+char(p,34971).
+char(4,34972).
+char(1,34973).
+char(3,34974).
+char(9,34975).
+char(c,34976).
+char(c,34977).
+char(c,34978).
+char(c,34979).
+char(c,34980).
+char(m,34981).
+char(o,34982).
+char(p,34983).
+char(o,34984).
+char(o,34985).
+char(m,34986).
+char(o,34987).
+char(9,34988).
+char(7,34989).
+char(8,34990).
+char(8,34991).
+char(p,34992).
+char(o,34993).
+char(p,34994).
+char(o,34995).
+char(7,34996).
+char(3,34997).
+char(0,34998).
+char(1,34999).
+char(m,35000).
+char(o,35001).
+char(m,35002).
+char(o,35003).
+char(o,35004).
+char(1,35005).
+char(6,35006).
+char(2,35007).
+char(5,35008).
+char(c,35009).
+char(p,35010).
+char(5,35011).
+char(4,35012).
+char(8,35013).
+char(0,35014).
+char(m,35015).
+char(o,35016).
+char(7,35017).
+char(5,35018).
+char(7,35019).
+char(1,35020).
+char(c,35021).
+char(p,35022).
+char(3,35023).
+char(2,35024).
+char(4,35025).
+char(7,35026).
+char(p,35027).
+char(5,35028).
+char(3,35029).
+char(2,35030).
+char(m,35031).
+char(o,35032).
+char(p,35033).
+char(o,35034).
+char(o,35035).
+char(o,35036).
+char(p,35037).
+char(4,35038).
+char(9,35039).
+char(2,35040).
+char(7,35041).
+char(p,35042).
+char(o,35043).
+char(o,35044).
+char(m,35045).
+char(o,35046).
+char(m,35047).
+char(2,35048).
+char(5,35049).
+char(8,35050).
+char(1,35051).
+char(c,35052).
+char(m,35053).
+char(o,35054).
+char(p,35055).
+char(4,35056).
+char(3,35057).
+char(1,35058).
+char(0,35059).
+char(c,35060).
+char(c,35061).
+char(c,35062).
+char(c,35063).
+char(c,35064).
+char(c,35065).
+char(p,35066).
+char(o,35067).
+char(o,35068).
+char(9,35069).
+char(0,35070).
+char(9,35071).
+char(3,35072).
+char(c,35073).
+char(m,35074).
+char(o,35075).
+char(3,35076).
+char(2,35077).
+char(1,35078).
+char(8,35079).
+char(p,35080).
+char(2,35081).
+char(7,35082).
+char(1,35083).
+char(0,35084).
+char(c,35085).
+char(m,35086).
+char(6,35087).
+char(6,35088).
+char(0,35089).
+char(9,35090).
+char(p,35091).
+char(o,35092).
+char(o,35093).
+char(p,35094).
+char(8,35095).
+char(0,35096).
+char(8,35097).
+char(c,35098).
+char(m,35099).
+char(7,35100).
+char(0,35101).
+char(8,35102).
+char(c,35103).
+char(m,35104).
+char(2,35105).
+char(3,35106).
+char(4,35107).
+char(9,35108).
+char(c,35109).
+char(c,35110).
+char(p,35111).
+char(o,35112).
+char(m,35113).
+char(4,35114).
+char(5,35115).
+char(5,35116).
+char(0,35117).
+char(m,35118).
+char(1,35119).
+char(8,35120).
+char(7,35121).
+char(3,35122).
+char(c,35123).
+char(c,35124).
+char(c,35125).
+char(c,35126).
+char(c,35127).
+char(c,35128).
+char(p,35129).
+char(o,35130).
+char(p,35131).
+char(5,35132).
+char(8,35133).
+char(5,35134).
+char(2,35135).
+char(c,35136).
+char(c,35137).
+char(p,35138).
+char(o,35139).
+char(m,35140).
+char(4,35141).
+char(0,35142).
+char(3,35143).
+char(5,35144).
+char(p,35145).
+char(o,35146).
+char(p,35147).
+char(7,35148).
+char(8,35149).
+char(7,35150).
+char(5,35151).
+char(m,35152).
+char(6,35153).
+char(8,35154).
+char(2,35155).
+char(7,35156).
+char(m,35157).
+char(o,35158).
+char(p,35159).
+char(o,35160).
+char(m,35161).
+char(o,35162).
+char(p,35163).
+char(8,35164).
+char(1,35165).
+char(2,35166).
+char(7,35167).
+char(p,35168).
+char(o,35169).
+char(m,35170).
+char(4,35171).
+char(5,35172).
+char(3,35173).
+char(8,35174).
+char(p,35175).
+char(o,35176).
+char(m,35177).
+char(6,35178).
+char(1,35179).
+char(4,35180).
+char(5,35181).
+char(m,35182).
+char(8,35183).
+char(9,35184).
+char(8,35185).
+char(7,35186).
+char(c,35187).
+char(m,35188).
+char(6,35189).
+char(8,35190).
+char(5,35191).
+char(0,35192).
+char(m,35193).
+char(o,35194).
+char(m,35195).
+char(o,35196).
+char(m,35197).
+char(7,35198).
+char(1,35199).
+char(7,35200).
+char(7,35201).
+char(m,35202).
+char(o,35203).
+char(m,35204).
+char(7,35205).
+char(3,35206).
+char(6,35207).
+char(p,35208).
+char(3,35209).
+char(0,35210).
+char(0,35211).
+char(6,35212).
+char(m,35213).
+char(9,35214).
+char(2,35215).
+char(8,35216).
+char(9,35217).
+char(p,35218).
+char(6,35219).
+char(1,35220).
+char(c,35221).
+char(c,35222).
+char(c,35223).
+char(m,35224).
+char(9,35225).
+char(5,35226).
+char(3,35227).
+char(3,35228).
+char(m,35229).
+char(7,35230).
+char(4,35231).
+char(5,35232).
+char(7,35233).
+char(m,35234).
+char(o,35235).
+char(m,35236).
+char(3,35237).
+char(3,35238).
+char(2,35239).
+char(5,35240).
+char(m,35241).
+char(4,35242).
+char(4,35243).
+char(8,35244).
+char(c,35245).
+char(m,35246).
+char(5,35247).
+char(1,35248).
+char(2,35249).
+char(8,35250).
+char(p,35251).
+char(o,35252).
+char(m,35253).
+char(o,35254).
+char(p,35255).
+char(4,35256).
+char(2,35257).
+char(1,35258).
+char(4,35259).
+char(m,35260).
+char(o,35261).
+char(m,35262).
+char(o,35263).
+char(m,35264).
+char(4,35265).
+char(6,35266).
+char(1,35267).
+char(9,35268).
+char(m,35269).
+char(o,35270).
+char(p,35271).
+char(o,35272).
+char(p,35273).
+char(o,35274).
+char(p,35275).
+char(o,35276).
+char(m,35277).
+char(9,35278).
+char(9,35279).
+char(1,35280).
+char(2,35281).
+char(p,35282).
+char(2,35283).
+char(3,35284).
+char(7,35285).
+char(0,35286).
+char(p,35287).
+char(5,35288).
+char(7,35289).
+char(5,35290).
+char(8,35291).
+char(c,35292).
+char(m,35293).
+char(o,35294).
+char(o,35295).
+char(p,35296).
+char(4,35297).
+char(7,35298).
+char(4,35299).
+char(1,35300).
+char(c,35301).
+char(c,35302).
+char(m,35303).
+char(o,35304).
+char(p,35305).
+char(o,35306).
+char(m,35307).
+char(o,35308).
+char(2,35309).
+char(5,35310).
+char(5,35311).
+char(m,35312).
+char(2,35313).
+char(4,35314).
+char(6,35315).
+char(7,35316).
+char(c,35317).
+char(c,35318).
+char(c,35319).
+char(c,35320).
+char(c,35321).
+char(m,35322).
+char(o,35323).
+char(p,35324).
+char(o,35325).
+char(m,35326).
+char(o,35327).
+char(p,35328).
+char(7,35329).
+char(0,35330).
+char(0,35331).
+char(2,35332).
+char(c,35333).
+char(m,35334).
+char(7,35335).
+char(6,35336).
+char(0,35337).
+char(2,35338).
+char(c,35339).
+char(p,35340).
+char(o,35341).
+char(m,35342).
+char(6,35343).
+char(1,35344).
+char(3,35345).
+char(6,35346).
+char(p,35347).
+char(o,35348).
+char(m,35349).
+char(9,35350).
+char(0,35351).
+char(2,35352).
+char(6,35353).
+char(m,35354).
+char(1,35355).
+char(9,35356).
+char(c,35357).
+char(p,35358).
+char(o,35359).
+char(m,35360).
+char(8,35361).
+char(7,35362).
+char(9,35363).
+char(6,35364).
+char(p,35365).
+char(2,35366).
+char(4,35367).
+char(2,35368).
+char(7,35369).
+char(c,35370).
+char(c,35371).
+char(p,35372).
+char(o,35373).
+char(1,35374).
+char(0,35375).
+char(8,35376).
+char(m,35377).
+char(o,35378).
+char(m,35379).
+char(3,35380).
+char(7,35381).
+char(9,35382).
+char(1,35383).
+char(c,35384).
+char(c,35385).
+char(p,35386).
+char(3,35387).
+char(4,35388).
+char(3,35389).
+char(8,35390).
+char(c,35391).
+char(c,35392).
+char(c,35393).
+char(p,35394).
+char(o,35395).
+char(p,35396).
+char(6,35397).
+char(9,35398).
+char(1,35399).
+char(1,35400).
+char(m,35401).
+char(o,35402).
+char(p,35403).
+char(2,35404).
+char(2,35405).
+char(7,35406).
+char(0,35407).
+char(m,35408).
+char(2,35409).
+char(6,35410).
+char(1,35411).
+char(6,35412).
+char(p,35413).
+char(9,35414).
+char(0,35415).
+char(7,35416).
+char(p,35417).
+char(o,35418).
+char(3,35419).
+char(1,35420).
+char(3,35421).
+char(7,35422).
+char(c,35423).
+char(c,35424).
+char(p,35425).
+char(o,35426).
+char(m,35427).
+char(1,35428).
+char(0,35429).
+char(7,35430).
+char(6,35431).
+char(c,35432).
+char(c,35433).
+char(p,35434).
+char(o,35435).
+char(o,35436).
+char(o,35437).
+char(m,35438).
+char(1,35439).
+char(8,35440).
+char(3,35441).
+char(6,35442).
+char(p,35443).
+char(o,35444).
+char(m,35445).
+char(2,35446).
+char(5,35447).
+char(1,35448).
+char(1,35449).
+char(p,35450).
+char(o,35451).
+char(p,35452).
+char(9,35453).
+char(6,35454).
+char(4,35455).
+char(c,35456).
+char(c,35457).
+char(c,35458).
+char(m,35459).
+char(2,35460).
+char(8,35461).
+char(4,35462).
+char(5,35463).
+char(c,35464).
+char(p,35465).
+char(o,35466).
+char(p,35467).
+char(9,35468).
+char(0,35469).
+char(6,35470).
+char(c,35471).
+char(p,35472).
+char(o,35473).
+char(o,35474).
+char(o,35475).
+char(m,35476).
+char(o,35477).
+char(p,35478).
+char(o,35479).
+char(p,35480).
+char(2,35481).
+char(0,35482).
+char(5,35483).
+char(9,35484).
+char(m,35485).
+char(8,35486).
+char(4,35487).
+char(1,35488).
+char(7,35489).
+char(p,35490).
+char(o,35491).
+char(m,35492).
+char(7,35493).
+char(5,35494).
+char(9,35495).
+char(1,35496).
+char(c,35497).
+char(c,35498).
+char(p,35499).
+char(1,35500).
+char(7,35501).
+char(9,35502).
+char(8,35503).
+char(c,35504).
+char(c,35505).
+char(p,35506).
+char(8,35507).
+char(7,35508).
+char(8,35509).
+char(4,35510).
+char(c,35511).
+char(m,35512).
+char(o,35513).
+char(m,35514).
+char(o,35515).
+char(p,35516).
+char(5,35517).
+char(6,35518).
+char(3,35519).
+char(8,35520).
+char(p,35521).
+char(o,35522).
+char(p,35523).
+char(3,35524).
+char(9,35525).
+char(1,35526).
+char(4,35527).
+char(p,35528).
+char(o,35529).
+char(p,35530).
+char(4,35531).
+char(7,35532).
+char(6,35533).
+char(6,35534).
+char(p,35535).
+char(3,35536).
+char(4,35537).
+char(9,35538).
+char(5,35539).
+char(p,35540).
+char(o,35541).
+char(o,35542).
+char(m,35543).
+char(6,35544).
+char(9,35545).
+char(7,35546).
+char(6,35547).
+char(c,35548).
+char(m,35549).
+char(o,35550).
+char(m,35551).
+char(o,35552).
+char(m,35553).
+char(o,35554).
+char(o,35555).
+char(o,35556).
+char(m,35557).
+char(o,35558).
+char(1,35559).
+char(9,35560).
+char(5,35561).
+char(8,35562).
+char(c,35563).
+char(c,35564).
+char(c,35565).
+char(c,35566).
+char(c,35567).
+char(c,35568).
+char(m,35569).
+char(o,35570).
+char(p,35571).
+char(5,35572).
+char(1,35573).
+char(7,35574).
+char(9,35575).
+char(c,35576).
+char(c,35577).
+char(c,35578).
+char(p,35579).
+char(8,35580).
+char(0,35581).
+char(0,35582).
+char(0,35583).
+char(p,35584).
+char(o,35585).
+char(o,35586).
+char(m,35587).
+char(3,35588).
+char(4,35589).
+char(3,35590).
+char(0,35591).
+char(m,35592).
+char(5,35593).
+char(8,35594).
+char(1,35595).
+char(8,35596).
+char(c,35597).
+char(c,35598).
+char(p,35599).
+char(9,35600).
+char(3,35601).
+char(3,35602).
+char(7,35603).
+char(m,35604).
+char(o,35605).
+char(4,35606).
+char(4,35607).
+char(3,35608).
+char(1,35609).
+char(m,35610).
+char(o,35611).
+char(1,35612).
+char(9,35613).
+char(7,35614).
+char(7,35615).
+char(m,35616).
+char(8,35617).
+char(4,35618).
+char(4,35619).
+char(0,35620).
+char(c,35621).
+char(c,35622).
+char(c,35623).
+char(c,35624).
+char(c,35625).
+char(c,35626).
+char(p,35627).
+char(o,35628).
+char(p,35629).
+char(3,35630).
+char(4,35631).
+char(5,35632).
+char(5,35633).
+char(c,35634).
+char(c,35635).
+char(c,35636).
+char(c,35637).
+char(c,35638).
+char(m,35639).
+char(2,35640).
+char(6,35641).
+char(2,35642).
+char(2,35643).
+char(c,35644).
+char(c,35645).
+char(m,35646).
+char(o,35647).
+char(m,35648).
+char(o,35649).
+char(m,35650).
+char(1,35651).
+char(4,35652).
+char(8,35653).
+char(2,35654).
+char(c,35655).
+char(m,35656).
+char(o,35657).
+char(m,35658).
+char(6,35659).
+char(3,35660).
+char(8,35661).
+char(c,35662).
+char(p,35663).
+char(5,35664).
+char(8,35665).
+char(2,35666).
+char(c,35667).
+char(c,35668).
+char(c,35669).
+char(p,35670).
+char(4,35671).
+char(8,35672).
+char(8,35673).
+char(8,35674).
+char(p,35675).
+char(o,35676).
+char(p,35677).
+char(9,35678).
+char(6,35679).
+char(4,35680).
+char(m,35681).
+char(o,35682).
+char(m,35683).
+char(o,35684).
+char(p,35685).
+char(o,35686).
+char(3,35687).
+char(7,35688).
+char(5,35689).
+char(0,35690).
+char(c,35691).
+char(c,35692).
+char(m,35693).
+char(o,35694).
+char(m,35695).
+char(o,35696).
+char(m,35697).
+char(o,35698).
+char(p,35699).
+char(o,35700).
+char(p,35701).
+char(5,35702).
+char(9,35703).
+char(1,35704).
+char(2,35705).
+char(c,35706).
+char(p,35707).
+char(o,35708).
+char(7,35709).
+char(1,35710).
+char(2,35711).
+char(9,35712).
+char(c,35713).
+char(c,35714).
+char(m,35715).
+char(o,35716).
+char(p,35717).
+char(8,35718).
+char(9,35719).
+char(0,35720).
+char(8,35721).
+char(c,35722).
+char(c,35723).
+char(m,35724).
+char(3,35725).
+char(1,35726).
+char(0,35727).
+char(5,35728).
+char(p,35729).
+char(o,35730).
+char(p,35731).
+char(7,35732).
+char(8,35733).
+char(9,35734).
+char(1,35735).
+char(c,35736).
+char(m,35737).
+char(9,35738).
+char(7,35739).
+char(3,35740).
+char(4,35741).
+char(c,35742).
+char(m,35743).
+char(4,35744).
+char(7,35745).
+char(7,35746).
+char(9,35747).
+char(c,35748).
+char(c,35749).
+char(c,35750).
+char(c,35751).
+char(p,35752).
+char(o,35753).
+char(p,35754).
+char(o,35755).
+char(p,35756).
+char(o,35757).
+char(p,35758).
+char(o,35759).
+char(p,35760).
+char(o,35761).
+char(p,35762).
+char(o,35763).
+char(m,35764).
+char(o,35765).
+char(m,35766).
+char(7,35767).
+char(1,35768).
+char(5,35769).
+char(3,35770).
+char(m,35771).
+char(2,35772).
+char(9,35773).
+char(6,35774).
+char(3,35775).
+char(m,35776).
+char(o,35777).
+char(o,35778).
+char(5,35779).
+char(2,35780).
+char(1,35781).
+char(c,35782).
+char(p,35783).
+char(o,35784).
+char(p,35785).
+char(2,35786).
+char(3,35787).
+char(6,35788).
+char(c,35789).
+char(c,35790).
+char(c,35791).
+char(c,35792).
+char(c,35793).
+char(c,35794).
+char(p,35795).
+char(9,35796).
+char(2,35797).
+char(9,35798).
+char(2,35799).
+char(p,35800).
+char(2,35801).
+char(6,35802).
+char(8,35803).
+char(3,35804).
+char(m,35805).
+char(3,35806).
+char(3,35807).
+char(2,35808).
+char(4,35809).
+char(m,35810).
+char(2,35811).
+char(0,35812).
+char(4,35813).
+char(4,35814).
+char(m,35815).
+char(o,35816).
+char(7,35817).
+char(0,35818).
+char(1,35819).
+char(5,35820).
+char(p,35821).
+char(o,35822).
+char(7,35823).
+char(1,35824).
+char(1,35825).
+char(9,35826).
+char(c,35827).
+char(c,35828).
+char(c,35829).
+char(p,35830).
+char(3,35831).
+char(2,35832).
+char(8,35833).
+char(5,35834).
+char(p,35835).
+char(o,35836).
+char(m,35837).
+char(o,35838).
+char(m,35839).
+char(9,35840).
+char(4,35841).
+char(7,35842).
+char(8,35843).
+char(c,35844).
+char(p,35845).
+char(5,35846).
+char(5,35847).
+char(9,35848).
+char(7,35849).
+char(m,35850).
+char(7,35851).
+char(7,35852).
+char(7,35853).
+char(1,35854).
+char(p,35855).
+char(6,35856).
+char(2,35857).
+char(0,35858).
+char(7,35859).
+char(p,35860).
+char(o,35861).
+char(o,35862).
+char(4,35863).
+char(8,35864).
+char(3,35865).
+char(7,35866).
+char(p,35867).
+char(2,35868).
+char(8,35869).
+char(5,35870).
+char(1,35871).
+char(m,35872).
+char(3,35873).
+char(2,35874).
+char(6,35875).
+char(m,35876).
+char(o,35877).
+char(m,35878).
+char(6,35879).
+char(6,35880).
+char(8,35881).
+char(7,35882).
+char(p,35883).
+char(o,35884).
+char(o,35885).
+char(m,35886).
+char(2,35887).
+char(6,35888).
+char(7,35889).
+char(2,35890).
+char(m,35891).
+char(7,35892).
+char(9,35893).
+char(1,35894).
+char(6,35895).
+char(c,35896).
+char(m,35897).
+char(o,35898).
+char(6,35899).
+char(6,35900).
+char(5,35901).
+char(6,35902).
+char(c,35903).
+char(m,35904).
+char(9,35905).
+char(5,35906).
+char(6,35907).
+char(p,35908).
+char(o,35909).
+char(8,35910).
+char(4,35911).
+char(4,35912).
+char(9,35913).
+char(c,35914).
+char(c,35915).
+char(c,35916).
+char(c,35917).
+char(p,35918).
+char(8,35919).
+char(9,35920).
+char(1,35921).
+char(8,35922).
+char(c,35923).
+char(c,35924).
+char(c,35925).
+char(m,35926).
+char(o,35927).
+char(m,35928).
+char(9,35929).
+char(5,35930).
+char(7,35931).
+char(5,35932).
+char(p,35933).
+char(o,35934).
+char(o,35935).
+char(9,35936).
+char(1,35937).
+char(1,35938).
+char(0,35939).
+char(m,35940).
+char(o,35941).
+char(m,35942).
+char(o,35943).
+char(m,35944).
+char(o,35945).
+char(9,35946).
+char(8,35947).
+char(8,35948).
+char(7,35949).
+char(c,35950).
+char(c,35951).
+char(m,35952).
+char(3,35953).
+char(2,35954).
+char(4,35955).
+char(6,35956).
+char(c,35957).
+char(p,35958).
+char(5,35959).
+char(3,35960).
+char(4,35961).
+char(5,35962).
+char(c,35963).
+char(p,35964).
+char(1,35965).
+char(7,35966).
+char(3,35967).
+char(7,35968).
+char(c,35969).
+char(m,35970).
+char(9,35971).
+char(5,35972).
+char(2,35973).
+char(p,35974).
+char(9,35975).
+char(8,35976).
+char(9,35977).
+char(3,35978).
+char(p,35979).
+char(6,35980).
+char(8,35981).
+char(6,35982).
+char(1,35983).
+char(c,35984).
+char(c,35985).
+char(c,35986).
+char(p,35987).
+char(5,35988).
+char(3,35989).
+char(5,35990).
+char(4,35991).
+char(c,35992).
+char(c,35993).
+char(p,35994).
+char(4,35995).
+char(5,35996).
+char(6,35997).
+char(2,35998).
+char(p,35999).
+char(o,36000).
+char(7,36001).
+char(0,36002).
+char(5,36003).
+char(4,36004).
+char(c,36005).
+char(m,36006).
+char(o,36007).
+char(9,36008).
+char(1,36009).
+char(5,36010).
+char(4,36011).
+char(m,36012).
+char(o,36013).
+char(o,36014).
+char(m,36015).
+char(o,36016).
+char(m,36017).
+char(o,36018).
+char(p,36019).
+char(o,36020).
+char(p,36021).
+char(4,36022).
+char(6,36023).
+char(3,36024).
+char(4,36025).
+char(m,36026).
+char(o,36027).
+char(m,36028).
+char(o,36029).
+char(p,36030).
+char(o,36031).
+char(m,36032).
+char(o,36033).
+char(m,36034).
+char(o,36035).
+char(8,36036).
+char(2,36037).
+char(3,36038).
+char(7,36039).
+char(p,36040).
+char(5,36041).
+char(0,36042).
+char(9,36043).
+char(8,36044).
+char(p,36045).
+char(5,36046).
+char(0,36047).
+char(9,36048).
+char(0,36049).
+char(c,36050).
+char(m,36051).
+char(o,36052).
+char(6,36053).
+char(9,36054).
+char(1,36055).
+char(9,36056).
+char(m,36057).
+char(o,36058).
+char(o,36059).
+char(4,36060).
+char(3,36061).
+char(6,36062).
+char(3,36063).
+char(p,36064).
+char(o,36065).
+char(p,36066).
+char(o,36067).
+char(p,36068).
+char(7,36069).
+char(4,36070).
+char(8,36071).
+char(m,36072).
+char(4,36073).
+char(8,36074).
+char(4,36075).
+char(8,36076).
+char(m,36077).
+char(5,36078).
+char(8,36079).
+char(6,36080).
+char(c,36081).
+char(m,36082).
+char(o,36083).
+char(m,36084).
+char(o,36085).
+char(4,36086).
+char(8,36087).
+char(3,36088).
+char(7,36089).
+char(p,36090).
+char(o,36091).
+char(p,36092).
+char(o,36093).
+char(8,36094).
+char(5,36095).
+char(6,36096).
+char(0,36097).
+char(c,36098).
+char(c,36099).
+char(m,36100).
+char(3,36101).
+char(3,36102).
+char(6,36103).
+char(2,36104).
+char(c,36105).
+char(p,36106).
+char(5,36107).
+char(3,36108).
+char(2,36109).
+char(9,36110).
+char(p,36111).
+char(8,36112).
+char(6,36113).
+char(1,36114).
+char(m,36115).
+char(3,36116).
+char(1,36117).
+char(5,36118).
+char(9,36119).
+char(c,36120).
+char(m,36121).
+char(4,36122).
+char(7,36123).
+char(4,36124).
+char(2,36125).
+char(c,36126).
+char(m,36127).
+char(5,36128).
+char(7,36129).
+char(9,36130).
+char(0,36131).
+char(p,36132).
+char(8,36133).
+char(3,36134).
+char(7,36135).
+char(6,36136).
+char(c,36137).
+char(p,36138).
+char(o,36139).
+char(m,36140).
+char(4,36141).
+char(2,36142).
+char(7,36143).
+char(p,36144).
+char(o,36145).
+char(m,36146).
+char(o,36147).
+char(m,36148).
+char(2,36149).
+char(7,36150).
+char(9,36151).
+char(0,36152).
+char(c,36153).
+char(m,36154).
+char(o,36155).
+char(p,36156).
+char(o,36157).
+char(p,36158).
+char(o,36159).
+char(p,36160).
+char(o,36161).
+char(6,36162).
+char(9,36163).
+char(6,36164).
+char(7,36165).
+char(c,36166).
+char(m,36167).
+char(o,36168).
+char(p,36169).
+char(o,36170).
+char(8,36171).
+char(5,36172).
+char(9,36173).
+char(1,36174).
+char(m,36175).
+char(o,36176).
+char(m,36177).
+char(o,36178).
+char(m,36179).
+char(o,36180).
+char(m,36181).
+char(9,36182).
+char(0,36183).
+char(6,36184).
+char(9,36185).
+char(p,36186).
+char(o,36187).
+char(m,36188).
+char(6,36189).
+char(4,36190).
+char(2,36191).
+char(9,36192).
+char(m,36193).
+char(8,36194).
+char(8,36195).
+char(3,36196).
+char(5,36197).
+char(m,36198).
+char(o,36199).
+char(6,36200).
+char(5,36201).
+char(4,36202).
+char(c,36203).
+char(m,36204).
+char(o,36205).
+char(m,36206).
+char(o,36207).
+char(m,36208).
+char(7,36209).
+char(2,36210).
+char(1,36211).
+char(3,36212).
+char(c,36213).
+char(m,36214).
+char(o,36215).
+char(p,36216).
+char(3,36217).
+char(3,36218).
+char(3,36219).
+char(8,36220).
+char(m,36221).
+char(7,36222).
+char(9,36223).
+char(2,36224).
+char(0,36225).
+char(m,36226).
+char(7,36227).
+char(3,36228).
+char(4,36229).
+char(m,36230).
+char(4,36231).
+char(1,36232).
+char(2,36233).
+char(4,36234).
+char(c,36235).
+char(c,36236).
+char(c,36237).
+char(c,36238).
+char(m,36239).
+char(o,36240).
+char(3,36241).
+char(4,36242).
+char(0,36243).
+char(9,36244).
+char(p,36245).
+char(o,36246).
+char(m,36247).
+char(5,36248).
+char(1,36249).
+char(9,36250).
+char(1,36251).
+char(p,36252).
+char(o,36253).
+char(o,36254).
+char(o,36255).
+char(p,36256).
+char(o,36257).
+char(m,36258).
+char(2,36259).
+char(0,36260).
+char(3,36261).
+char(6,36262).
+char(m,36263).
+char(o,36264).
+char(o,36265).
+char(m,36266).
+char(1,36267).
+char(3,36268).
+char(8,36269).
+char(9,36270).
+char(m,36271).
+char(3,36272).
+char(8,36273).
+char(3,36274).
+char(8,36275).
+char(m,36276).
+char(4,36277).
+char(6,36278).
+char(6,36279).
+char(3,36280).
+char(c,36281).
+char(c,36282).
+char(c,36283).
+char(p,36284).
+char(o,36285).
+char(p,36286).
+char(o,36287).
+char(p,36288).
+char(4,36289).
+char(6,36290).
+char(6,36291).
+char(4,36292).
+char(m,36293).
+char(o,36294).
+char(o,36295).
+char(p,36296).
+char(5,36297).
+char(1,36298).
+char(6,36299).
+char(1,36300).
+char(c,36301).
+char(p,36302).
+char(2,36303).
+char(6,36304).
+char(5,36305).
+char(4,36306).
+char(m,36307).
+char(9,36308).
+char(1,36309).
+char(7,36310).
+char(6,36311).
+char(p,36312).
+char(9,36313).
+char(5,36314).
+char(0,36315).
+char(7,36316).
+char(p,36317).
+char(o,36318).
+char(3,36319).
+char(9,36320).
+char(5,36321).
+char(7,36322).
+char(m,36323).
+char(3,36324).
+char(5,36325).
+char(5,36326).
+char(4,36327).
+char(c,36328).
+char(m,36329).
+char(2,36330).
+char(5,36331).
+char(1,36332).
+char(4,36333).
+char(c,36334).
+char(c,36335).
+char(c,36336).
+char(m,36337).
+char(5,36338).
+char(9,36339).
+char(5,36340).
+char(p,36341).
+char(4,36342).
+char(1,36343).
+char(3,36344).
+char(m,36345).
+char(3,36346).
+char(5,36347).
+char(7,36348).
+char(0,36349).
+char(c,36350).
+char(c,36351).
+char(c,36352).
+char(c,36353).
+char(c,36354).
+char(p,36355).
+char(5,36356).
+char(5,36357).
+char(1,36358).
+char(7,36359).
+char(c,36360).
+char(m,36361).
+char(o,36362).
+char(o,36363).
+char(p,36364).
+char(4,36365).
+char(9,36366).
+char(1,36367).
+char(7,36368).
+char(p,36369).
+char(4,36370).
+char(5,36371).
+char(4,36372).
+char(6,36373).
+char(c,36374).
+char(p,36375).
+char(7,36376).
+char(7,36377).
+char(8,36378).
+char(6,36379).
+char(p,36380).
+char(o,36381).
+char(p,36382).
+char(3,36383).
+char(2,36384).
+char(9,36385).
+char(6,36386).
+char(p,36387).
+char(4,36388).
+char(2,36389).
+char(8,36390).
+char(0,36391).
+char(p,36392).
+char(o,36393).
+char(3,36394).
+char(8,36395).
+char(6,36396).
+char(4,36397).
+char(c,36398).
+char(c,36399).
+char(p,36400).
+char(2,36401).
+char(1,36402).
+char(4,36403).
+char(3,36404).
+char(c,36405).
+char(m,36406).
+char(o,36407).
+char(o,36408).
+char(o,36409).
+char(8,36410).
+char(6,36411).
+char(6,36412).
+char(1,36413).
+char(c,36414).
+char(p,36415).
+char(o,36416).
+char(m,36417).
+char(o,36418).
+char(o,36419).
+char(m,36420).
+char(o,36421).
+char(o,36422).
+char(3,36423).
+char(8,36424).
+char(4,36425).
+char(2,36426).
+char(m,36427).
+char(4,36428).
+char(6,36429).
+char(7,36430).
+char(8,36431).
+char(m,36432).
+char(o,36433).
+char(p,36434).
+char(o,36435).
+char(p,36436).
+char(o,36437).
+char(m,36438).
+char(o,36439).
+char(p,36440).
+char(o,36441).
+char(p,36442).
+char(o,36443).
+char(m,36444).
+char(6,36445).
+char(3,36446).
+char(2,36447).
+char(4,36448).
+char(m,36449).
+char(o,36450).
+char(o,36451).
+char(3,36452).
+char(9,36453).
+char(7,36454).
+char(2,36455).
+char(p,36456).
+char(7,36457).
+char(9,36458).
+char(3,36459).
+char(3,36460).
+char(m,36461).
+char(7,36462).
+char(6,36463).
+char(0,36464).
+char(4,36465).
+char(p,36466).
+char(o,36467).
+char(9,36468).
+char(5,36469).
+char(5,36470).
+char(4,36471).
+char(c,36472).
+char(c,36473).
+char(c,36474).
+char(c,36475).
+char(c,36476).
+char(c,36477).
+char(p,36478).
+char(5,36479).
+char(6,36480).
+char(8,36481).
+char(5,36482).
+char(m,36483).
+char(o,36484).
+char(m,36485).
+char(2,36486).
+char(7,36487).
+char(5,36488).
+char(6,36489).
+char(m,36490).
+char(o,36491).
+char(p,36492).
+char(o,36493).
+char(m,36494).
+char(9,36495).
+char(7,36496).
+char(1,36497).
+char(8,36498).
+char(m,36499).
+char(9,36500).
+char(0,36501).
+char(8,36502).
+char(6,36503).
+char(p,36504).
+char(o,36505).
+char(p,36506).
+char(2,36507).
+char(4,36508).
+char(6,36509).
+char(2,36510).
+char(m,36511).
+char(7,36512).
+char(6,36513).
+char(2,36514).
+char(9,36515).
+char(c,36516).
+char(m,36517).
+char(o,36518).
+char(m,36519).
+char(o,36520).
+char(m,36521).
+char(1,36522).
+char(6,36523).
+char(1,36524).
+char(7,36525).
+char(m,36526).
+char(o,36527).
+char(m,36528).
+char(o,36529).
+char(5,36530).
+char(4,36531).
+char(0,36532).
+char(1,36533).
+char(c,36534).
+char(c,36535).
+char(p,36536).
+char(o,36537).
+char(3,36538).
+char(6,36539).
+char(4,36540).
+char(8,36541).
+char(p,36542).
+char(o,36543).
+char(p,36544).
+char(o,36545).
+char(o,36546).
+char(p,36547).
+char(5,36548).
+char(4,36549).
+char(4,36550).
+char(4,36551).
+char(c,36552).
+char(m,36553).
+char(4,36554).
+char(2,36555).
+char(3,36556).
+char(1,36557).
+char(c,36558).
+char(c,36559).
+char(c,36560).
+char(c,36561).
+char(c,36562).
+char(p,36563).
+char(9,36564).
+char(3,36565).
+char(8,36566).
+char(3,36567).
+char(p,36568).
+char(o,36569).
+char(p,36570).
+char(3,36571).
+char(2,36572).
+char(6,36573).
+char(4,36574).
+char(c,36575).
+char(c,36576).
+char(p,36577).
+char(7,36578).
+char(8,36579).
+char(2,36580).
+char(6,36581).
+char(c,36582).
+char(p,36583).
+char(o,36584).
+char(p,36585).
+char(o,36586).
+char(p,36587).
+char(6,36588).
+char(3,36589).
+char(9,36590).
+char(m,36591).
+char(o,36592).
+char(m,36593).
+char(9,36594).
+char(9,36595).
+char(6,36596).
+char(c,36597).
+char(c,36598).
+char(c,36599).
+char(c,36600).
+char(c,36601).
+char(m,36602).
+char(8,36603).
+char(3,36604).
+char(9,36605).
+char(9,36606).
+char(c,36607).
+char(c,36608).
+char(p,36609).
+char(o,36610).
+char(p,36611).
+char(4,36612).
+char(5,36613).
+char(4,36614).
+char(8,36615).
+char(c,36616).
+char(c,36617).
+char(c,36618).
+char(c,36619).
+char(c,36620).
+char(c,36621).
+char(c,36622).
+char(c,36623).
+char(c,36624).
+char(c,36625).
+char(c,36626).
+char(c,36627).
+char(c,36628).
+char(p,36629).
+char(o,36630).
+char(9,36631).
+char(7,36632).
+char(3,36633).
+char(0,36634).
+char(c,36635).
+char(m,36636).
+char(3,36637).
+char(8,36638).
+char(3,36639).
+char(9,36640).
+char(c,36641).
+char(c,36642).
+char(c,36643).
+char(p,36644).
+char(o,36645).
+char(p,36646).
+char(o,36647).
+char(p,36648).
+char(1,36649).
+char(5,36650).
+char(6,36651).
+char(6,36652).
+char(c,36653).
+char(c,36654).
+char(c,36655).
+char(p,36656).
+char(3,36657).
+char(0,36658).
+char(3,36659).
+char(7,36660).
+char(m,36661).
+char(7,36662).
+char(3,36663).
+char(7,36664).
+char(6,36665).
+char(p,36666).
+char(o,36667).
+char(p,36668).
+char(4,36669).
+char(1,36670).
+char(8,36671).
+char(9,36672).
+char(c,36673).
+char(p,36674).
+char(o,36675).
+char(p,36676).
+char(o,36677).
+char(m,36678).
+char(o,36679).
+char(m,36680).
+char(8,36681).
+char(4,36682).
+char(7,36683).
+char(9,36684).
+char(c,36685).
+char(c,36686).
+char(c,36687).
+char(c,36688).
+char(m,36689).
+char(5,36690).
+char(4,36691).
+char(6,36692).
+char(0,36693).
+char(p,36694).
+char(5,36695).
+char(9,36696).
+char(5,36697).
+char(2,36698).
+char(c,36699).
+char(c,36700).
+char(p,36701).
+char(o,36702).
+char(4,36703).
+char(6,36704).
+char(0,36705).
+char(7,36706).
+char(p,36707).
+char(6,36708).
+char(0,36709).
+char(1,36710).
+char(4,36711).
+char(c,36712).
+char(c,36713).
+char(c,36714).
+char(m,36715).
+char(o,36716).
+char(p,36717).
+char(o,36718).
+char(m,36719).
+char(o,36720).
+char(2,36721).
+char(8,36722).
+char(4,36723).
+char(6,36724).
+char(p,36725).
+char(8,36726).
+char(2,36727).
+char(3,36728).
+char(4,36729).
+char(p,36730).
+char(4,36731).
+char(1,36732).
+char(6,36733).
+char(1,36734).
+char(m,36735).
+char(2,36736).
+char(3,36737).
+char(8,36738).
+char(4,36739).
+char(p,36740).
+char(8,36741).
+char(6,36742).
+char(8,36743).
+char(4,36744).
+char(c,36745).
+char(c,36746).
+char(p,36747).
+char(o,36748).
+char(m,36749).
+char(o,36750).
+char(m,36751).
+char(o,36752).
+char(m,36753).
+char(o,36754).
+char(m,36755).
+char(9,36756).
+char(2,36757).
+char(9,36758).
+char(6,36759).
+char(p,36760).
+char(8,36761).
+char(5,36762).
+char(6,36763).
+char(2,36764).
+char(p,36765).
+char(o,36766).
+char(m,36767).
+char(9,36768).
+char(0,36769).
+char(0,36770).
+char(0,36771).
+char(p,36772).
+char(5,36773).
+char(1,36774).
+char(7,36775).
+char(9,36776).
+char(p,36777).
+char(o,36778).
+char(p,36779).
+char(o,36780).
+char(p,36781).
+char(o,36782).
+char(m,36783).
+char(6,36784).
+char(1,36785).
+char(8,36786).
+char(7,36787).
+char(c,36788).
+char(m,36789).
+char(2,36790).
+char(4,36791).
+char(4,36792).
+char(6,36793).
+char(m,36794).
+char(3,36795).
+char(5,36796).
+char(0,36797).
+char(7,36798).
+char(c,36799).
+char(c,36800).
+char(p,36801).
+char(1,36802).
+char(9,36803).
+char(0,36804).
+char(3,36805).
+char(c,36806).
+char(c,36807).
+char(m,36808).
+char(o,36809).
+char(o,36810).
+char(8,36811).
+char(7,36812).
+char(3,36813).
+char(1,36814).
+char(c,36815).
+char(c,36816).
+char(c,36817).
+char(c,36818).
+char(m,36819).
+char(1,36820).
+char(4,36821).
+char(1,36822).
+char(5,36823).
+char(p,36824).
+char(o,36825).
+char(p,36826).
+char(2,36827).
+char(7,36828).
+char(5,36829).
+char(2,36830).
+char(c,36831).
+char(c,36832).
+char(c,36833).
+char(c,36834).
+char(m,36835).
+char(6,36836).
+char(7,36837).
+char(2,36838).
+char(8,36839).
+char(p,36840).
+char(3,36841).
+char(4,36842).
+char(8,36843).
+char(8,36844).
+char(c,36845).
+char(c,36846).
+char(p,36847).
+char(9,36848).
+char(2,36849).
+char(c,36850).
+char(m,36851).
+char(7,36852).
+char(7,36853).
+char(8,36854).
+char(9,36855).
+char(p,36856).
+char(o,36857).
+char(2,36858).
+char(9,36859).
+char(5,36860).
+char(6,36861).
+char(p,36862).
+char(o,36863).
+char(m,36864).
+char(o,36865).
+char(p,36866).
+char(o,36867).
+char(o,36868).
+char(p,36869).
+char(o,36870).
+char(o,36871).
+char(p,36872).
+char(6,36873).
+char(1,36874).
+char(4,36875).
+char(2,36876).
+char(p,36877).
+char(1,36878).
+char(4,36879).
+char(3,36880).
+char(0,36881).
+char(c,36882).
+char(c,36883).
+char(c,36884).
+char(m,36885).
+char(2,36886).
+char(6,36887).
+char(5,36888).
+char(8,36889).
+char(c,36890).
+char(c,36891).
+char(m,36892).
+char(2,36893).
+char(5,36894).
+char(0,36895).
+char(8,36896).
+char(p,36897).
+char(8,36898).
+char(6,36899).
+char(6,36900).
+char(p,36901).
+char(6,36902).
+char(5,36903).
+char(4,36904).
+char(8,36905).
+char(c,36906).
+char(c,36907).
+char(c,36908).
+char(c,36909).
+char(c,36910).
+char(c,36911).
+char(c,36912).
+char(p,36913).
+char(3,36914).
+char(9,36915).
+char(1,36916).
+char(8,36917).
+char(p,36918).
+char(3,36919).
+char(6,36920).
+char(4,36921).
+char(3,36922).
+char(c,36923).
+char(c,36924).
+char(c,36925).
+char(m,36926).
+char(9,36927).
+char(2,36928).
+char(8,36929).
+char(c,36930).
+char(c,36931).
+char(c,36932).
+char(c,36933).
+char(c,36934).
+char(p,36935).
+char(7,36936).
+char(9,36937).
+char(8,36938).
+char(1,36939).
+char(c,36940).
+char(m,36941).
+char(3,36942).
+char(0,36943).
+char(4,36944).
+char(5,36945).
+char(c,36946).
+char(c,36947).
+char(c,36948).
+char(m,36949).
+char(3,36950).
+char(7,36951).
+char(1,36952).
+char(2,36953).
+char(c,36954).
+char(m,36955).
+char(3,36956).
+char(9,36957).
+char(5,36958).
+char(9,36959).
+char(m,36960).
+char(o,36961).
+char(p,36962).
+char(8,36963).
+char(6,36964).
+char(5,36965).
+char(3,36966).
+char(c,36967).
+char(c,36968).
+char(m,36969).
+char(o,36970).
+char(p,36971).
+char(o,36972).
+char(m,36973).
+char(4,36974).
+char(5,36975).
+char(5,36976).
+char(9,36977).
+char(c,36978).
+char(p,36979).
+char(6,36980).
+char(7,36981).
+char(5,36982).
+char(6,36983).
+char(m,36984).
+char(3,36985).
+char(1,36986).
+char(5,36987).
+char(5,36988).
+char(c,36989).
+char(p,36990).
+char(o,36991).
+char(p,36992).
+char(6,36993).
+char(1,36994).
+char(5,36995).
+char(6,36996).
+char(c,36997).
+char(m,36998).
+char(o,36999).
+char(9,37000).
+char(9,37001).
+char(6,37002).
+char(c,37003).
+char(c,37004).
+char(c,37005).
+char(p,37006).
+char(3,37007).
+char(3,37008).
+char(9,37009).
+char(2,37010).
+char(c,37011).
+char(c,37012).
+char(p,37013).
+char(7,37014).
+char(8,37015).
+char(4,37016).
+char(7,37017).
+char(m,37018).
+char(3,37019).
+char(2,37020).
+char(2,37021).
+char(2,37022).
+char(c,37023).
+char(p,37024).
+char(o,37025).
+char(m,37026).
+char(o,37027).
+char(m,37028).
+char(o,37029).
+char(3,37030).
+char(1,37031).
+char(5,37032).
+char(3,37033).
+char(c,37034).
+char(c,37035).
+char(p,37036).
+char(o,37037).
+char(m,37038).
+char(o,37039).
+char(2,37040).
+char(7,37041).
+char(4,37042).
+char(6,37043).
+char(c,37044).
+char(c,37045).
+char(c,37046).
+char(c,37047).
+char(c,37048).
+char(p,37049).
+char(8,37050).
+char(3,37051).
+char(3,37052).
+char(6,37053).
+char(m,37054).
+char(o,37055).
+char(m,37056).
+char(o,37057).
+char(o,37058).
+char(m,37059).
+char(o,37060).
+char(m,37061).
+char(o,37062).
+char(p,37063).
+char(7,37064).
+char(7,37065).
+char(1,37066).
+char(6,37067).
+char(c,37068).
+char(m,37069).
+char(7,37070).
+char(3,37071).
+char(6,37072).
+char(3,37073).
+char(c,37074).
+char(m,37075).
+char(8,37076).
+char(6,37077).
+char(4,37078).
+char(0,37079).
+char(c,37080).
+char(c,37081).
+char(c,37082).
+char(p,37083).
+char(1,37084).
+char(1,37085).
+char(2,37086).
+char(1,37087).
+char(m,37088).
+char(7,37089).
+char(5,37090).
+char(6,37091).
+char(3,37092).
+char(c,37093).
+char(c,37094).
+char(p,37095).
+char(1,37096).
+char(8,37097).
+char(9,37098).
+char(0,37099).
+char(c,37100).
+char(p,37101).
+char(9,37102).
+char(6,37103).
+char(5,37104).
+char(0,37105).
+char(c,37106).
+char(c,37107).
+char(p,37108).
+char(4,37109).
+char(2,37110).
+char(3,37111).
+char(0,37112).
+char(p,37113).
+char(o,37114).
+char(o,37115).
+char(m,37116).
+char(o,37117).
+char(o,37118).
+char(m,37119).
+char(7,37120).
+char(2,37121).
+char(5,37122).
+char(7,37123).
+char(p,37124).
+char(o,37125).
+char(8,37126).
+char(0,37127).
+char(2,37128).
+char(3,37129).
+char(c,37130).
+char(m,37131).
+char(o,37132).
+char(m,37133).
+char(o,37134).
+char(p,37135).
+char(1,37136).
+char(5,37137).
+char(7,37138).
+char(9,37139).
+char(c,37140).
+char(p,37141).
+char(9,37142).
+char(8,37143).
+char(8,37144).
+char(2,37145).
+char(c,37146).
+char(c,37147).
+char(c,37148).
+char(c,37149).
+char(p,37150).
+char(4,37151).
+char(2,37152).
+char(4,37153).
+char(9,37154).
+char(p,37155).
+char(1,37156).
+char(6,37157).
+char(7,37158).
+char(6,37159).
+char(m,37160).
+char(o,37161).
+char(o,37162).
+char(3,37163).
+char(9,37164).
+char(1,37165).
+char(1,37166).
+char(p,37167).
+char(5,37168).
+char(0,37169).
+char(6,37170).
+char(7,37171).
+char(c,37172).
+char(m,37173).
+char(2,37174).
+char(8,37175).
+char(9,37176).
+char(3,37177).
+char(p,37178).
+char(o,37179).
+char(p,37180).
+char(1,37181).
+char(6,37182).
+char(7,37183).
+char(5,37184).
+char(c,37185).
+char(m,37186).
+char(o,37187).
+char(o,37188).
+char(o,37189).
+char(p,37190).
+char(o,37191).
+char(m,37192).
+char(o,37193).
+char(p,37194).
+char(o,37195).
+char(m,37196).
+char(6,37197).
+char(2,37198).
+char(6,37199).
+char(p,37200).
+char(9,37201).
+char(3,37202).
+char(4,37203).
+char(5,37204).
+char(p,37205).
+char(o,37206).
+char(m,37207).
+char(o,37208).
+char(p,37209).
+char(o,37210).
+char(m,37211).
+char(6,37212).
+char(6,37213).
+char(7,37214).
+char(8,37215).
+char(c,37216).
+char(c,37217).
+char(m,37218).
+char(o,37219).
+char(m,37220).
+char(o,37221).
+char(m,37222).
+char(o,37223).
+char(p,37224).
+char(o,37225).
+char(o,37226).
+char(m,37227).
+char(8,37228).
+char(9,37229).
+char(2,37230).
+char(2,37231).
+char(m,37232).
+char(8,37233).
+char(5,37234).
+char(9,37235).
+char(7,37236).
+char(c,37237).
+char(c,37238).
+char(c,37239).
+char(c,37240).
+char(c,37241).
+char(p,37242).
+char(4,37243).
+char(2,37244).
+char(7,37245).
+char(6,37246).
+char(m,37247).
+char(o,37248).
+char(m,37249).
+char(o,37250).
+char(m,37251).
+char(7,37252).
+char(9,37253).
+char(9,37254).
+char(c,37255).
+char(m,37256).
+char(8,37257).
+char(9,37258).
+char(7,37259).
+char(5,37260).
+char(c,37261).
+char(c,37262).
+char(c,37263).
+char(c,37264).
+char(p,37265).
+char(o,37266).
+char(m,37267).
+char(5,37268).
+char(5,37269).
+char(9,37270).
+char(2,37271).
+char(c,37272).
+char(p,37273).
+char(o,37274).
+char(p,37275).
+char(o,37276).
+char(p,37277).
+char(o,37278).
+char(8,37279).
+char(5,37280).
+char(8,37281).
+char(9,37282).
+char(c,37283).
+char(p,37284).
+char(2,37285).
+char(5,37286).
+char(6,37287).
+char(1,37288).
+char(c,37289).
+char(c,37290).
+char(c,37291).
+char(m,37292).
+char(o,37293).
+char(m,37294).
+char(8,37295).
+char(1,37296).
+char(9,37297).
+char(1,37298).
+char(m,37299).
+char(o,37300).
+char(m,37301).
+char(o,37302).
+char(p,37303).
+char(7,37304).
+char(0,37305).
+char(3,37306).
+char(m,37307).
+char(o,37308).
+char(m,37309).
+char(o,37310).
+char(p,37311).
+char(o,37312).
+char(o,37313).
+char(p,37314).
+char(o,37315).
+char(p,37316).
+char(5,37317).
+char(4,37318).
+char(3,37319).
+char(3,37320).
+char(p,37321).
+char(4,37322).
+char(9,37323).
+char(0,37324).
+char(1,37325).
+char(c,37326).
+char(c,37327).
+char(c,37328).
+char(m,37329).
+char(3,37330).
+char(4,37331).
+char(3,37332).
+char(4,37333).
+char(c,37334).
+char(m,37335).
+char(6,37336).
+char(1,37337).
+char(5,37338).
+char(5,37339).
+char(c,37340).
+char(c,37341).
+char(p,37342).
+char(3,37343).
+char(1,37344).
+char(6,37345).
+char(9,37346).
+char(c,37347).
+char(m,37348).
+char(o,37349).
+char(1,37350).
+char(2,37351).
+char(6,37352).
+char(1,37353).
+char(c,37354).
+char(m,37355).
+char(5,37356).
+char(9,37357).
+char(5,37358).
+char(8,37359).
+char(m,37360).
+char(2,37361).
+char(1,37362).
+char(8,37363).
+char(2,37364).
+char(c,37365).
+char(m,37366).
+char(5,37367).
+char(7,37368).
+char(6,37369).
+char(9,37370).
+char(m,37371).
+char(o,37372).
+char(4,37373).
+char(9,37374).
+char(7,37375).
+char(6,37376).
+char(c,37377).
+char(m,37378).
+char(o,37379).
+char(p,37380).
+char(3,37381).
+char(5,37382).
+char(6,37383).
+char(p,37384).
+char(o,37385).
+char(p,37386).
+char(1,37387).
+char(7,37388).
+char(p,37389).
+char(o,37390).
+char(m,37391).
+char(o,37392).
+char(p,37393).
+char(o,37394).
+char(m,37395).
+char(7,37396).
+char(6,37397).
+char(8,37398).
+char(7,37399).
+char(c,37400).
+char(c,37401).
+char(c,37402).
+char(m,37403).
+char(8,37404).
+char(2,37405).
+char(3,37406).
+char(2,37407).
+char(c,37408).
+char(p,37409).
+char(6,37410).
+char(9,37411).
+char(8,37412).
+char(9,37413).
+char(c,37414).
+char(p,37415).
+char(9,37416).
+char(4,37417).
+char(1,37418).
+char(4,37419).
+char(p,37420).
+char(o,37421).
+char(m,37422).
+char(6,37423).
+char(0,37424).
+char(6,37425).
+char(8,37426).
+char(p,37427).
+char(7,37428).
+char(4,37429).
+char(6,37430).
+char(p,37431).
+char(o,37432).
+char(m,37433).
+char(o,37434).
+char(m,37435).
+char(o,37436).
+char(p,37437).
+char(o,37438).
+char(p,37439).
+char(o,37440).
+char(p,37441).
+char(o,37442).
+char(m,37443).
+char(o,37444).
+char(p,37445).
+char(7,37446).
+char(5,37447).
+char(1,37448).
+char(4,37449).
+char(c,37450).
+char(c,37451).
+char(c,37452).
+char(c,37453).
+char(c,37454).
+char(m,37455).
+char(o,37456).
+char(m,37457).
+char(o,37458).
+char(p,37459).
+char(5,37460).
+char(6,37461).
+char(5,37462).
+char(0,37463).
+char(c,37464).
+char(m,37465).
+char(7,37466).
+char(5,37467).
+char(4,37468).
+char(2,37469).
+char(m,37470).
+char(o,37471).
+char(m,37472).
+char(4,37473).
+char(3,37474).
+char(9,37475).
+char(8,37476).
+char(c,37477).
+char(m,37478).
+char(o,37479).
+char(p,37480).
+char(o,37481).
+char(p,37482).
+char(o,37483).
+char(p,37484).
+char(o,37485).
+char(p,37486).
+char(2,37487).
+char(5,37488).
+char(5,37489).
+char(7,37490).
+char(c,37491).
+char(c,37492).
+char(c,37493).
+char(c,37494).
+char(c,37495).
+char(c,37496).
+char(p,37497).
+char(2,37498).
+char(7,37499).
+char(0,37500).
+char(9,37501).
+char(c,37502).
+char(m,37503).
+char(o,37504).
+char(p,37505).
+char(o,37506).
+char(p,37507).
+char(7,37508).
+char(7,37509).
+char(8,37510).
+char(4,37511).
+char(m,37512).
+char(o,37513).
+char(p,37514).
+char(o,37515).
+char(p,37516).
+char(4,37517).
+char(6,37518).
+char(4,37519).
+char(9,37520).
+char(c,37521).
+char(c,37522).
+char(c,37523).
+char(c,37524).
+char(c,37525).
+char(m,37526).
+char(1,37527).
+char(5,37528).
+char(6,37529).
+char(1,37530).
+char(c,37531).
+char(m,37532).
+char(o,37533).
+char(p,37534).
+char(o,37535).
+char(o,37536).
+char(m,37537).
+char(5,37538).
+char(5,37539).
+char(2,37540).
+char(5,37541).
+char(m,37542).
+char(o,37543).
+char(o,37544).
+char(m,37545).
+char(3,37546).
+char(6,37547).
+char(3,37548).
+char(1,37549).
+char(c,37550).
+char(c,37551).
+char(c,37552).
+char(c,37553).
+char(c,37554).
+char(p,37555).
+char(7,37556).
+char(1,37557).
+char(4,37558).
+char(1,37559).
+char(c,37560).
+char(p,37561).
+char(o,37562).
+char(p,37563).
+char(o,37564).
+char(p,37565).
+char(o,37566).
+char(m,37567).
+char(o,37568).
+char(m,37569).
+char(o,37570).
+char(m,37571).
+char(7,37572).
+char(5,37573).
+char(8,37574).
+char(2,37575).
+char(p,37576).
+char(5,37577).
+char(3,37578).
+char(5,37579).
+char(9,37580).
+char(c,37581).
+char(c,37582).
+char(c,37583).
+char(p,37584).
+char(o,37585).
+char(o,37586).
+char(p,37587).
+char(o,37588).
+char(m,37589).
+char(o,37590).
+char(m,37591).
+char(2,37592).
+char(3,37593).
+char(2,37594).
+char(1,37595).
+char(c,37596).
+char(c,37597).
+char(c,37598).
+char(p,37599).
+char(4,37600).
+char(9,37601).
+char(5,37602).
+char(1,37603).
+char(c,37604).
+char(c,37605).
+char(c,37606).
+char(m,37607).
+char(5,37608).
+char(9,37609).
+char(2,37610).
+char(1,37611).
+char(p,37612).
+char(5,37613).
+char(6,37614).
+char(1,37615).
+char(2,37616).
+char(p,37617).
+char(o,37618).
+char(p,37619).
+char(9,37620).
+char(9,37621).
+char(5,37622).
+char(5,37623).
+char(c,37624).
+char(p,37625).
+char(4,37626).
+char(6,37627).
+char(4,37628).
+char(0,37629).
+char(m,37630).
+char(o,37631).
+char(m,37632).
+char(1,37633).
+char(6,37634).
+char(7,37635).
+char(9,37636).
+char(c,37637).
+char(c,37638).
+char(c,37639).
+char(c,37640).
+char(p,37641).
+char(1,37642).
+char(8,37643).
+char(9,37644).
+char(2,37645).
+char(c,37646).
+char(m,37647).
+char(4,37648).
+char(0,37649).
+char(1,37650).
+char(5,37651).
+char(c,37652).
+char(m,37653).
+char(o,37654).
+char(2,37655).
+char(6,37656).
+char(5,37657).
+char(7,37658).
+char(m,37659).
+char(7,37660).
+char(8,37661).
+char(4,37662).
+char(1,37663).
+char(c,37664).
+char(c,37665).
+char(m,37666).
+char(o,37667).
+char(m,37668).
+char(o,37669).
+char(m,37670).
+char(o,37671).
+char(p,37672).
+char(o,37673).
+char(o,37674).
+char(p,37675).
+char(o,37676).
+char(m,37677).
+char(9,37678).
+char(4,37679).
+char(6,37680).
+char(1,37681).
+char(c,37682).
+char(c,37683).
+char(c,37684).
+char(c,37685).
+char(c,37686).
+char(c,37687).
+char(c,37688).
+char(c,37689).
+char(c,37690).
+char(c,37691).
+char(p,37692).
+char(o,37693).
+char(5,37694).
+char(6,37695).
+char(8,37696).
+char(0,37697).
+char(c,37698).
+char(c,37699).
+char(c,37700).
+char(p,37701).
+char(5,37702).
+char(6,37703).
+char(0,37704).
+char(1,37705).
+char(m,37706).
+char(o,37707).
+char(p,37708).
+char(5,37709).
+char(3,37710).
+char(2,37711).
+char(3,37712).
+char(c,37713).
+char(p,37714).
+char(5,37715).
+char(8,37716).
+char(8,37717).
+char(2,37718).
+char(p,37719).
+char(o,37720).
+char(m,37721).
+char(4,37722).
+char(9,37723).
+char(1,37724).
+char(5,37725).
+char(p,37726).
+char(4,37727).
+char(1,37728).
+char(8,37729).
+char(8,37730).
+char(c,37731).
+char(p,37732).
+char(7,37733).
+char(7,37734).
+char(8,37735).
+char(4,37736).
+char(c,37737).
+char(c,37738).
+char(c,37739).
+char(c,37740).
+char(p,37741).
+char(o,37742).
+char(p,37743).
+char(4,37744).
+char(1,37745).
+char(7,37746).
+char(2,37747).
+char(c,37748).
+char(c,37749).
+char(c,37750).
+char(p,37751).
+char(o,37752).
+char(m,37753).
+char(9,37754).
+char(0,37755).
+char(1,37756).
+char(0,37757).
+char(m,37758).
+char(8,37759).
+char(7,37760).
+char(2,37761).
+char(5,37762).
+char(c,37763).
+char(c,37764).
+char(c,37765).
+char(c,37766).
+char(c,37767).
+char(p,37768).
+char(o,37769).
+char(3,37770).
+char(4,37771).
+char(3,37772).
+char(6,37773).
+char(p,37774).
+char(6,37775).
+char(6,37776).
+char(8,37777).
+char(3,37778).
+char(c,37779).
+char(c,37780).
+char(m,37781).
+char(o,37782).
+char(o,37783).
+char(m,37784).
+char(o,37785).
+char(m,37786).
+char(o,37787).
+char(4,37788).
+char(7,37789).
+char(1,37790).
+char(3,37791).
+char(p,37792).
+char(9,37793).
+char(4,37794).
+char(3,37795).
+char(4,37796).
+char(c,37797).
+char(p,37798).
+char(1,37799).
+char(1,37800).
+char(6,37801).
+char(9,37802).
+char(p,37803).
+char(o,37804).
+char(4,37805).
+char(2,37806).
+char(6,37807).
+char(4,37808).
+char(c,37809).
+char(p,37810).
+char(o,37811).
+char(1,37812).
+char(0,37813).
+char(6,37814).
+char(3,37815).
+char(m,37816).
+char(o,37817).
+char(m,37818).
+char(o,37819).
+char(m,37820).
+char(5,37821).
+char(3,37822).
+char(8,37823).
+char(6,37824).
+char(c,37825).
+char(m,37826).
+char(o,37827).
+char(o,37828).
+char(o,37829).
+char(p,37830).
+char(o,37831).
+char(p,37832).
+char(o,37833).
+char(p,37834).
+char(o,37835).
+char(p,37836).
+char(4,37837).
+char(9,37838).
+char(9,37839).
+char(7,37840).
+char(c,37841).
+char(m,37842).
+char(o,37843).
+char(2,37844).
+char(9,37845).
+char(2,37846).
+char(1,37847).
+char(m,37848).
+char(o,37849).
+char(p,37850).
+char(4,37851).
+char(9,37852).
+char(6,37853).
+char(7,37854).
+char(c,37855).
+char(c,37856).
+char(c,37857).
+char(p,37858).
+char(1,37859).
+char(8,37860).
+char(2,37861).
+char(0,37862).
+char(m,37863).
+char(5,37864).
+char(6,37865).
+char(7,37866).
+char(0,37867).
+char(p,37868).
+char(8,37869).
+char(6,37870).
+char(4,37871).
+char(7,37872).
+char(c,37873).
+char(m,37874).
+char(o,37875).
+char(m,37876).
+char(3,37877).
+char(5,37878).
+char(1,37879).
+char(2,37880).
+char(p,37881).
+char(o,37882).
+char(p,37883).
+char(6,37884).
+char(7,37885).
+char(7,37886).
+char(8,37887).
+char(m,37888).
+char(3,37889).
+char(7,37890).
+char(5,37891).
+char(6,37892).
+char(c,37893).
+char(c,37894).
+char(p,37895).
+char(7,37896).
+char(4,37897).
+char(7,37898).
+char(0,37899).
+char(c,37900).
+char(p,37901).
+char(1,37902).
+char(8,37903).
+char(5,37904).
+char(7,37905).
+char(m,37906).
+char(4,37907).
+char(4,37908).
+char(6,37909).
+char(1,37910).
+char(m,37911).
+char(8,37912).
+char(0,37913).
+char(2,37914).
+char(3,37915).
+char(c,37916).
+char(c,37917).
+char(m,37918).
+char(8,37919).
+char(3,37920).
+char(1,37921).
+char(6,37922).
+char(c,37923).
+char(p,37924).
+char(9,37925).
+char(3,37926).
+char(5,37927).
+char(4,37928).
+char(c,37929).
+char(c,37930).
+char(c,37931).
+char(c,37932).
+char(c,37933).
+char(c,37934).
+char(c,37935).
+char(c,37936).
+char(m,37937).
+char(3,37938).
+char(6,37939).
+char(7,37940).
+char(8,37941).
+char(c,37942).
+char(p,37943).
+char(o,37944).
+char(p,37945).
+char(o,37946).
+char(o,37947).
+char(8,37948).
+char(2,37949).
+char(5,37950).
+char(9,37951).
+char(p,37952).
+char(o,37953).
+char(m,37954).
+char(o,37955).
+char(o,37956).
+char(p,37957).
+char(2,37958).
+char(7,37959).
+char(1,37960).
+char(1,37961).
+char(c,37962).
+char(c,37963).
+char(c,37964).
+char(p,37965).
+char(o,37966).
+char(p,37967).
+char(o,37968).
+char(m,37969).
+char(o,37970).
+char(7,37971).
+char(7,37972).
+char(5,37973).
+char(1,37974).
+char(m,37975).
+char(o,37976).
+char(p,37977).
+char(o,37978).
+char(o,37979).
+char(o,37980).
+char(m,37981).
+char(8,37982).
+char(2,37983).
+char(8,37984).
+char(p,37985).
+char(o,37986).
+char(p,37987).
+char(3,37988).
+char(0,37989).
+char(9,37990).
+char(p,37991).
+char(o,37992).
+char(m,37993).
+char(o,37994).
+char(p,37995).
+char(o,37996).
+char(o,37997).
+char(9,37998).
+char(1,37999).
+char(5,38000).
+char(3,38001).
+char(m,38002).
+char(o,38003).
+char(p,38004).
+char(o,38005).
+char(8,38006).
+char(6,38007).
+char(6,38008).
+char(4,38009).
+char(m,38010).
+char(5,38011).
+char(2,38012).
+char(6,38013).
+char(5,38014).
+char(m,38015).
+char(4,38016).
+char(5,38017).
+char(3,38018).
+char(5,38019).
+char(p,38020).
+char(8,38021).
+char(3,38022).
+char(6,38023).
+char(6,38024).
+char(m,38025).
+char(3,38026).
+char(5,38027).
+char(0,38028).
+char(6,38029).
+char(c,38030).
+char(p,38031).
+char(2,38032).
+char(2,38033).
+char(3,38034).
+char(0,38035).
+char(p,38036).
+char(5,38037).
+char(0,38038).
+char(2,38039).
+char(1,38040).
+char(p,38041).
+char(o,38042).
+char(m,38043).
+char(1,38044).
+char(3,38045).
+char(2,38046).
+char(3,38047).
+char(p,38048).
+char(o,38049).
+char(o,38050).
+char(m,38051).
+char(5,38052).
+char(4,38053).
+char(1,38054).
+char(0,38055).
+char(m,38056).
+char(o,38057).
+char(m,38058).
+char(o,38059).
+char(p,38060).
+char(o,38061).
+char(o,38062).
+char(6,38063).
+char(7,38064).
+char(5,38065).
+char(6,38066).
+char(m,38067).
+char(4,38068).
+char(7,38069).
+char(3,38070).
+char(4,38071).
+char(c,38072).
+char(m,38073).
+char(o,38074).
+char(m,38075).
+char(4,38076).
+char(2,38077).
+char(5,38078).
+char(1,38079).
+char(c,38080).
+char(m,38081).
+char(9,38082).
+char(7,38083).
+char(3,38084).
+char(5,38085).
+char(c,38086).
+char(m,38087).
+char(1,38088).
+char(1,38089).
+char(1,38090).
+char(7,38091).
+char(m,38092).
+char(3,38093).
+char(8,38094).
+char(6,38095).
+char(0,38096).
+char(c,38097).
+char(p,38098).
+char(o,38099).
+char(p,38100).
+char(o,38101).
+char(m,38102).
+char(3,38103).
+char(4,38104).
+char(0,38105).
+char(4,38106).
+char(m,38107).
+char(o,38108).
+char(p,38109).
+char(8,38110).
+char(2,38111).
+char(7,38112).
+char(c,38113).
+char(c,38114).
+char(m,38115).
+char(1,38116).
+char(7,38117).
+char(2,38118).
+char(7,38119).
+char(c,38120).
+char(c,38121).
+char(m,38122).
+char(o,38123).
+char(p,38124).
+char(9,38125).
+char(5,38126).
+char(5,38127).
+char(9,38128).
+char(p,38129).
+char(8,38130).
+char(9,38131).
+char(4,38132).
+char(0,38133).
+char(p,38134).
+char(9,38135).
+char(9,38136).
+char(1,38137).
+char(0,38138).
+char(c,38139).
+char(m,38140).
+char(1,38141).
+char(7,38142).
+char(6,38143).
+char(5,38144).
+char(c,38145).
+char(p,38146).
+char(9,38147).
+char(0,38148).
+char(3,38149).
+char(m,38150).
+char(4,38151).
+char(1,38152).
+char(0,38153).
+char(2,38154).
+char(c,38155).
+char(p,38156).
+char(5,38157).
+char(4,38158).
+char(9,38159).
+char(8,38160).
+char(m,38161).
+char(7,38162).
+char(1,38163).
+char(2,38164).
+char(6,38165).
+char(p,38166).
+char(7,38167).
+char(0,38168).
+char(7,38169).
+char(9,38170).
+char(m,38171).
+char(5,38172).
+char(2,38173).
+char(3,38174).
+char(3,38175).
+char(c,38176).
+char(c,38177).
+char(m,38178).
+char(1,38179).
+char(6,38180).
+char(6,38181).
+char(2,38182).
+char(m,38183).
+char(o,38184).
+char(m,38185).
+char(4,38186).
+char(4,38187).
+char(5,38188).
+char(8,38189).
+char(c,38190).
+char(c,38191).
+char(c,38192).
+char(p,38193).
+char(o,38194).
+char(p,38195).
+char(o,38196).
+char(p,38197).
+char(o,38198).
+char(5,38199).
+char(0,38200).
+char(8,38201).
+char(m,38202).
+char(o,38203).
+char(p,38204).
+char(o,38205).
+char(o,38206).
+char(m,38207).
+char(1,38208).
+char(1,38209).
+char(3,38210).
+char(0,38211).
+char(m,38212).
+char(2,38213).
+char(2,38214).
+char(7,38215).
+char(2,38216).
+char(m,38217).
+char(3,38218).
+char(8,38219).
+char(6,38220).
+char(9,38221).
+char(c,38222).
+char(c,38223).
+char(p,38224).
+char(o,38225).
+char(o,38226).
+char(p,38227).
+char(o,38228).
+char(p,38229).
+char(o,38230).
+char(o,38231).
+char(m,38232).
+char(9,38233).
+char(5,38234).
+char(4,38235).
+char(2,38236).
+char(c,38237).
+char(m,38238).
+char(5,38239).
+char(7,38240).
+char(8,38241).
+char(5,38242).
+char(c,38243).
+char(c,38244).
+char(c,38245).
+char(m,38246).
+char(o,38247).
+char(m,38248).
+char(2,38249).
+char(1,38250).
+char(6,38251).
+char(6,38252).
+char(c,38253).
+char(c,38254).
+char(p,38255).
+char(o,38256).
+char(m,38257).
+char(7,38258).
+char(0,38259).
+char(1,38260).
+char(5,38261).
+char(m,38262).
+char(o,38263).
+char(m,38264).
+char(o,38265).
+char(o,38266).
+char(m,38267).
+char(o,38268).
+char(p,38269).
+char(o,38270).
+char(m,38271).
+char(3,38272).
+char(4,38273).
+char(4,38274).
+char(5,38275).
+char(p,38276).
+char(o,38277).
+char(p,38278).
+char(o,38279).
+char(7,38280).
+char(8,38281).
+char(2,38282).
+char(9,38283).
+char(m,38284).
+char(8,38285).
+char(5,38286).
+char(0,38287).
+char(1,38288).
+char(c,38289).
+char(m,38290).
+char(o,38291).
+char(m,38292).
+char(1,38293).
+char(1,38294).
+char(6,38295).
+char(c,38296).
+char(c,38297).
+char(c,38298).
+char(c,38299).
+char(m,38300).
+char(o,38301).
+char(m,38302).
+char(o,38303).
+char(m,38304).
+char(3,38305).
+char(4,38306).
+char(0,38307).
+char(8,38308).
+char(p,38309).
+char(4,38310).
+char(4,38311).
+char(7,38312).
+char(3,38313).
+char(c,38314).
+char(m,38315).
+char(o,38316).
+char(p,38317).
+char(o,38318).
+char(p,38319).
+char(9,38320).
+char(8,38321).
+char(4,38322).
+char(5,38323).
+char(p,38324).
+char(9,38325).
+char(0,38326).
+char(4,38327).
+char(3,38328).
+char(p,38329).
+char(o,38330).
+char(7,38331).
+char(1,38332).
+char(3,38333).
+char(c,38334).
+char(c,38335).
+char(c,38336).
+char(c,38337).
+char(c,38338).
+char(c,38339).
+char(c,38340).
+char(m,38341).
+char(o,38342).
+char(p,38343).
+char(1,38344).
+char(4,38345).
+char(5,38346).
+char(c,38347).
+char(p,38348).
+char(o,38349).
+char(m,38350).
+char(1,38351).
+char(9,38352).
+char(0,38353).
+char(2,38354).
+char(m,38355).
+char(o,38356).
+char(m,38357).
+char(9,38358).
+char(0,38359).
+char(6,38360).
+char(5,38361).
+char(c,38362).
+char(m,38363).
+char(5,38364).
+char(1,38365).
+char(0,38366).
+char(1,38367).
+char(m,38368).
+char(9,38369).
+char(3,38370).
+char(1,38371).
+char(1,38372).
+char(m,38373).
+char(5,38374).
+char(4,38375).
+char(1,38376).
+char(7,38377).
+char(c,38378).
+char(c,38379).
+char(c,38380).
+char(c,38381).
+char(m,38382).
+char(o,38383).
+char(p,38384).
+char(5,38385).
+char(1,38386).
+char(9,38387).
+char(2,38388).
+char(c,38389).
+char(c,38390).
+char(c,38391).
+char(m,38392).
+char(o,38393).
+char(m,38394).
+char(o,38395).
+char(m,38396).
+char(3,38397).
+char(6,38398).
+char(5,38399).
+char(9,38400).
+char(c,38401).
+char(p,38402).
+char(7,38403).
+char(3,38404).
+char(2,38405).
+char(m,38406).
+char(4,38407).
+char(6,38408).
+char(0,38409).
+char(8,38410).
+char(c,38411).
+char(p,38412).
+char(7,38413).
+char(8,38414).
+char(8,38415).
+char(8,38416).
+char(p,38417).
+char(8,38418).
+char(8,38419).
+char(8,38420).
+char(6,38421).
+char(c,38422).
+char(c,38423).
+char(c,38424).
+char(m,38425).
+char(o,38426).
+char(p,38427).
+char(4,38428).
+char(3,38429).
+char(2,38430).
+char(5,38431).
+char(m,38432).
+char(3,38433).
+char(8,38434).
+char(9,38435).
+char(7,38436).
+char(c,38437).
+char(c,38438).
+char(c,38439).
+char(c,38440).
+char(c,38441).
+char(c,38442).
+char(m,38443).
+char(9,38444).
+char(9,38445).
+char(8,38446).
+char(5,38447).
+char(c,38448).
+char(m,38449).
+char(9,38450).
+char(2,38451).
+char(4,38452).
+char(6,38453).
+char(c,38454).
+char(c,38455).
+char(c,38456).
+char(c,38457).
+char(c,38458).
+char(m,38459).
+char(o,38460).
+char(p,38461).
+char(o,38462).
+char(o,38463).
+char(p,38464).
+char(o,38465).
+char(m,38466).
+char(4,38467).
+char(8,38468).
+char(5,38469).
+char(7,38470).
+char(m,38471).
+char(o,38472).
+char(m,38473).
+char(8,38474).
+char(6,38475).
+char(3,38476).
+char(5,38477).
+char(m,38478).
+char(o,38479).
+char(p,38480).
+char(9,38481).
+char(7,38482).
+char(4,38483).
+char(9,38484).
+char(m,38485).
+char(4,38486).
+char(8,38487).
+char(7,38488).
+char(2,38489).
+char(c,38490).
+char(c,38491).
+char(m,38492).
+char(o,38493).
+char(p,38494).
+char(5,38495).
+char(6,38496).
+char(4,38497).
+char(6,38498).
+char(c,38499).
+char(m,38500).
+char(2,38501).
+char(8,38502).
+char(8,38503).
+char(3,38504).
+char(m,38505).
+char(o,38506).
+char(p,38507).
+char(9,38508).
+char(5,38509).
+char(4,38510).
+char(1,38511).
+char(c,38512).
+char(m,38513).
+char(o,38514).
+char(o,38515).
+char(o,38516).
+char(p,38517).
+char(o,38518).
+char(m,38519).
+char(o,38520).
+char(o,38521).
+char(m,38522).
+char(1,38523).
+char(4,38524).
+char(9,38525).
+char(m,38526).
+char(o,38527).
+char(p,38528).
+char(o,38529).
+char(m,38530).
+char(3,38531).
+char(8,38532).
+char(7,38533).
+char(2,38534).
+char(c,38535).
+char(c,38536).
+char(c,38537).
+char(p,38538).
+char(5,38539).
+char(3,38540).
+char(7,38541).
+char(5,38542).
+char(m,38543).
+char(8,38544).
+char(9,38545).
+char(9,38546).
+char(2,38547).
+char(p,38548).
+char(4,38549).
+char(9,38550).
+char(6,38551).
+char(4,38552).
+char(c,38553).
+char(c,38554).
+char(c,38555).
+char(m,38556).
+char(5,38557).
+char(7,38558).
+char(0,38559).
+char(2,38560).
+char(c,38561).
+char(m,38562).
+char(o,38563).
+char(m,38564).
+char(6,38565).
+char(4,38566).
+char(4,38567).
+char(6,38568).
+char(m,38569).
+char(9,38570).
+char(8,38571).
+char(0,38572).
+char(5,38573).
+char(c,38574).
+char(c,38575).
+char(c,38576).
+char(c,38577).
+char(m,38578).
+char(3,38579).
+char(1,38580).
+char(9,38581).
+char(8,38582).
+char(c,38583).
+char(c,38584).
+char(m,38585).
+char(2,38586).
+char(6,38587).
+char(9,38588).
+char(3,38589).
+char(c,38590).
+char(m,38591).
+char(o,38592).
+char(p,38593).
+char(o,38594).
+char(p,38595).
+char(3,38596).
+char(1,38597).
+char(4,38598).
+char(1,38599).
+char(p,38600).
+char(o,38601).
+char(o,38602).
+char(p,38603).
+char(o,38604).
+char(5,38605).
+char(1,38606).
+char(1,38607).
+char(0,38608).
+char(c,38609).
+char(c,38610).
+char(p,38611).
+char(o,38612).
+char(p,38613).
+char(4,38614).
+char(3,38615).
+char(1,38616).
+char(8,38617).
+char(c,38618).
+char(c,38619).
+char(m,38620).
+char(o,38621).
+char(p,38622).
+char(o,38623).
+char(p,38624).
+char(o,38625).
+char(m,38626).
+char(7,38627).
+char(2,38628).
+char(8,38629).
+char(8,38630).
+char(c,38631).
+char(p,38632).
+char(3,38633).
+char(9,38634).
+char(7,38635).
+char(3,38636).
+char(c,38637).
+char(c,38638).
+char(p,38639).
+char(o,38640).
+char(5,38641).
+char(9,38642).
+char(9,38643).
+char(4,38644).
+char(m,38645).
+char(9,38646).
+char(3,38647).
+char(4,38648).
+char(4,38649).
+char(c,38650).
+char(p,38651).
+char(o,38652).
+char(o,38653).
+char(m,38654).
+char(o,38655).
+char(p,38656).
+char(1,38657).
+char(6,38658).
+char(3,38659).
+char(p,38660).
+char(o,38661).
+char(p,38662).
+char(5,38663).
+char(7,38664).
+char(7,38665).
+char(2,38666).
+char(c,38667).
+char(c,38668).
+char(c,38669).
+char(c,38670).
+char(c,38671).
+char(m,38672).
+char(6,38673).
+char(4,38674).
+char(4,38675).
+char(0,38676).
+char(m,38677).
+char(o,38678).
+char(p,38679).
+char(7,38680).
+char(8,38681).
+char(2,38682).
+char(9,38683).
+char(c,38684).
+char(c,38685).
+char(m,38686).
+char(o,38687).
+char(2,38688).
+char(3,38689).
+char(1,38690).
+char(6,38691).
+char(m,38692).
+char(o,38693).
+char(7,38694).
+char(2,38695).
+char(4,38696).
+char(9,38697).
+char(m,38698).
+char(8,38699).
+char(6,38700).
+char(9,38701).
+char(6,38702).
+char(m,38703).
+char(o,38704).
+char(o,38705).
+char(o,38706).
+char(o,38707).
+char(m,38708).
+char(6,38709).
+char(7,38710).
+char(4,38711).
+char(1,38712).
+char(c,38713).
+char(c,38714).
+char(c,38715).
+char(p,38716).
+char(8,38717).
+char(1,38718).
+char(5,38719).
+char(2,38720).
+char(c,38721).
+char(m,38722).
+char(o,38723).
+char(2,38724).
+char(4,38725).
+char(1,38726).
+char(0,38727).
+char(p,38728).
+char(4,38729).
+char(4,38730).
+char(9,38731).
+char(0,38732).
+char(p,38733).
+char(o,38734).
+char(m,38735).
+char(o,38736).
+char(p,38737).
+char(7,38738).
+char(8,38739).
+char(1,38740).
+char(0,38741).
+char(c,38742).
+char(c,38743).
+char(p,38744).
+char(o,38745).
+char(m,38746).
+char(o,38747).
+char(p,38748).
+char(6,38749).
+char(5,38750).
+char(4,38751).
+char(1,38752).
+char(m,38753).
+char(o,38754).
+char(m,38755).
+char(o,38756).
+char(5,38757).
+char(8,38758).
+char(1,38759).
+char(6,38760).
+char(c,38761).
+char(m,38762).
+char(o,38763).
+char(p,38764).
+char(o,38765).
+char(p,38766).
+char(6,38767).
+char(7,38768).
+char(0,38769).
+char(6,38770).
+char(c,38771).
+char(p,38772).
+char(o,38773).
+char(p,38774).
+char(o,38775).
+char(m,38776).
+char(7,38777).
+char(5,38778).
+char(7,38779).
+char(4,38780).
+char(p,38781).
+char(o,38782).
+char(o,38783).
+char(1,38784).
+char(6,38785).
+char(0,38786).
+char(4,38787).
+char(m,38788).
+char(3,38789).
+char(5,38790).
+char(3,38791).
+char(3,38792).
+char(c,38793).
+char(c,38794).
+char(c,38795).
+char(m,38796).
+char(o,38797).
+char(m,38798).
+char(9,38799).
+char(1,38800).
+char(9,38801).
+char(4,38802).
+char(c,38803).
+char(c,38804).
+char(p,38805).
+char(8,38806).
+char(6,38807).
+char(7,38808).
+char(8,38809).
+char(m,38810).
+char(o,38811).
+char(m,38812).
+char(9,38813).
+char(2,38814).
+char(0,38815).
+char(0,38816).
+char(m,38817).
+char(o,38818).
+char(o,38819).
+char(2,38820).
+char(3,38821).
+char(2,38822).
+char(6,38823).
+char(c,38824).
+char(c,38825).
+char(c,38826).
+char(m,38827).
+char(3,38828).
+char(2,38829).
+char(0,38830).
+char(5,38831).
+char(c,38832).
+char(p,38833).
+char(o,38834).
+char(m,38835).
+char(3,38836).
+char(7,38837).
+char(3,38838).
+char(7,38839).
+char(c,38840).
+char(m,38841).
+char(7,38842).
+char(0,38843).
+char(9,38844).
+char(1,38845).
+char(p,38846).
+char(o,38847).
+char(m,38848).
+char(1,38849).
+char(0,38850).
+char(2,38851).
+char(4,38852).
+char(c,38853).
+char(m,38854).
+char(5,38855).
+char(3,38856).
+char(3,38857).
+char(1,38858).
+char(m,38859).
+char(4,38860).
+char(5,38861).
+char(2,38862).
+char(1,38863).
+char(m,38864).
+char(4,38865).
+char(2,38866).
+char(7,38867).
+char(8,38868).
+char(p,38869).
+char(o,38870).
+char(p,38871).
+char(6,38872).
+char(3,38873).
+char(4,38874).
+char(1,38875).
+char(p,38876).
+char(2,38877).
+char(1,38878).
+char(0,38879).
+char(p,38880).
+char(o,38881).
+char(o,38882).
+char(p,38883).
+char(o,38884).
+char(m,38885).
+char(o,38886).
+char(m,38887).
+char(o,38888).
+char(p,38889).
+char(7,38890).
+char(3,38891).
+char(0,38892).
+char(9,38893).
+char(c,38894).
+char(m,38895).
+char(o,38896).
+char(o,38897).
+char(8,38898).
+char(8,38899).
+char(1,38900).
+char(1,38901).
+char(c,38902).
+char(c,38903).
+char(c,38904).
+char(p,38905).
+char(3,38906).
+char(2,38907).
+char(4,38908).
+char(0,38909).
+char(c,38910).
+char(c,38911).
+char(p,38912).
+char(o,38913).
+char(p,38914).
+char(o,38915).
+char(p,38916).
+char(2,38917).
+char(2,38918).
+char(0,38919).
+char(9,38920).
+char(c,38921).
+char(c,38922).
+char(m,38923).
+char(o,38924).
+char(p,38925).
+char(o,38926).
+char(m,38927).
+char(6,38928).
+char(5,38929).
+char(7,38930).
+char(8,38931).
+char(c,38932).
+char(p,38933).
+char(o,38934).
+char(m,38935).
+char(o,38936).
+char(o,38937).
+char(m,38938).
+char(o,38939).
+char(p,38940).
+char(o,38941).
+char(m,38942).
+char(o,38943).
+char(o,38944).
+char(p,38945).
+char(o,38946).
+char(m,38947).
+char(o,38948).
+char(m,38949).
+char(o,38950).
+char(p,38951).
+char(2,38952).
+char(0,38953).
+char(3,38954).
+char(7,38955).
+char(c,38956).
+char(c,38957).
+char(p,38958).
+char(o,38959).
+char(m,38960).
+char(2,38961).
+char(8,38962).
+char(2,38963).
+char(9,38964).
+char(p,38965).
+char(o,38966).
+char(m,38967).
+char(o,38968).
+char(p,38969).
+char(o,38970).
+char(m,38971).
+char(3,38972).
+char(0,38973).
+char(0,38974).
+char(0,38975).
+char(p,38976).
+char(6,38977).
+char(6,38978).
+char(7,38979).
+char(2,38980).
+char(c,38981).
+char(c,38982).
+char(c,38983).
+char(m,38984).
+char(9,38985).
+char(5,38986).
+char(4,38987).
+char(0,38988).
+char(c,38989).
+char(m,38990).
+char(2,38991).
+char(5,38992).
+char(7,38993).
+char(6,38994).
+char(p,38995).
+char(9,38996).
+char(7,38997).
+char(6,38998).
+char(8,38999).
+char(p,39000).
+char(o,39001).
+char(m,39002).
+char(o,39003).
+char(o,39004).
+char(p,39005).
+char(o,39006).
+char(p,39007).
+char(5,39008).
+char(8,39009).
+char(7,39010).
+char(1,39011).
+char(m,39012).
+char(o,39013).
+char(m,39014).
+char(2,39015).
+char(1,39016).
+char(0,39017).
+char(2,39018).
+char(c,39019).
+char(m,39020).
+char(o,39021).
+char(8,39022).
+char(3,39023).
+char(9,39024).
+char(2,39025).
+char(m,39026).
+char(9,39027).
+char(2,39028).
+char(0,39029).
+char(1,39030).
+char(c,39031).
+char(c,39032).
+char(p,39033).
+char(1,39034).
+char(0,39035).
+char(3,39036).
+char(8,39037).
+char(p,39038).
+char(o,39039).
+char(m,39040).
+char(o,39041).
+char(o,39042).
+char(m,39043).
+char(o,39044).
+char(5,39045).
+char(2,39046).
+char(4,39047).
+char(1,39048).
+char(p,39049).
+char(o,39050).
+char(p,39051).
+char(5,39052).
+char(5,39053).
+char(1,39054).
+char(7,39055).
+char(p,39056).
+char(o,39057).
+char(6,39058).
+char(8,39059).
+char(4,39060).
+char(6,39061).
+char(c,39062).
+char(c,39063).
+char(m,39064).
+char(6,39065).
+char(6,39066).
+char(5,39067).
+char(3,39068).
+char(c,39069).
+char(p,39070).
+char(2,39071).
+char(1,39072).
+char(2,39073).
+char(c,39074).
+char(m,39075).
+char(7,39076).
+char(6,39077).
+char(9,39078).
+char(c,39079).
+char(c,39080).
+char(p,39081).
+char(o,39082).
+char(m,39083).
+char(2,39084).
+char(0,39085).
+char(4,39086).
+char(3,39087).
+char(m,39088).
+char(3,39089).
+char(3,39090).
+char(4,39091).
+char(4,39092).
+char(m,39093).
+char(7,39094).
+char(5,39095).
+char(1,39096).
+char(0,39097).
+char(p,39098).
+char(2,39099).
+char(5,39100).
+char(8,39101).
+char(8,39102).
+char(c,39103).
+char(p,39104).
+char(8,39105).
+char(1,39106).
+char(2,39107).
+char(0,39108).
+char(c,39109).
+char(c,39110).
+char(c,39111).
+char(m,39112).
+char(o,39113).
+char(p,39114).
+char(o,39115).
+char(m,39116).
+char(o,39117).
+char(o,39118).
+char(p,39119).
+char(9,39120).
+char(1,39121).
+char(2,39122).
+char(3,39123).
+char(m,39124).
+char(7,39125).
+char(7,39126).
+char(8,39127).
+char(3,39128).
+char(c,39129).
+char(m,39130).
+char(8,39131).
+char(9,39132).
+char(6,39133).
+char(9,39134).
+char(p,39135).
+char(4,39136).
+char(7,39137).
+char(4,39138).
+char(5,39139).
+char(p,39140).
+char(o,39141).
+char(p,39142).
+char(o,39143).
+char(1,39144).
+char(7,39145).
+char(2,39146).
+char(6,39147).
+char(m,39148).
+char(o,39149).
+char(m,39150).
+char(o,39151).
+char(m,39152).
+char(5,39153).
+char(5,39154).
+char(4,39155).
+char(6,39156).
+char(m,39157).
+char(6,39158).
+char(7,39159).
+char(4,39160).
+char(7,39161).
+char(c,39162).
+char(c,39163).
+char(c,39164).
+char(c,39165).
+char(m,39166).
+char(2,39167).
+char(3,39168).
+char(6,39169).
+char(1,39170).
+char(c,39171).
+char(m,39172).
+char(o,39173).
+char(1,39174).
+char(2,39175).
+char(7,39176).
+char(1,39177).
+char(c,39178).
+char(c,39179).
+char(m,39180).
+char(o,39181).
+char(m,39182).
+char(o,39183).
+char(m,39184).
+char(o,39185).
+char(p,39186).
+char(o,39187).
+char(o,39188).
+char(6,39189).
+char(7,39190).
+char(8,39191).
+char(5,39192).
+char(m,39193).
+char(o,39194).
+char(p,39195).
+char(3,39196).
+char(3,39197).
+char(1,39198).
+char(9,39199).
+char(c,39200).
+char(m,39201).
+char(o,39202).
+char(p,39203).
+char(4,39204).
+char(9,39205).
+char(9,39206).
+char(4,39207).
+char(c,39208).
+char(c,39209).
+char(p,39210).
+char(o,39211).
+char(m,39212).
+char(o,39213).
+char(m,39214).
+char(1,39215).
+char(0,39216).
+char(0,39217).
+char(2,39218).
+char(c,39219).
+char(m,39220).
+char(5,39221).
+char(5,39222).
+char(7,39223).
+char(3,39224).
+char(p,39225).
+char(5,39226).
+char(6,39227).
+char(8,39228).
+char(1,39229).
+char(m,39230).
+char(1,39231).
+char(8,39232).
+char(8,39233).
+char(2,39234).
+char(m,39235).
+char(4,39236).
+char(3,39237).
+char(9,39238).
+char(c,39239).
+char(p,39240).
+char(o,39241).
+char(4,39242).
+char(0,39243).
+char(9,39244).
+char(8,39245).
+char(c,39246).
+char(m,39247).
+char(o,39248).
+char(p,39249).
+char(o,39250).
+char(p,39251).
+char(4,39252).
+char(1,39253).
+char(9,39254).
+char(1,39255).
+char(c,39256).
+char(c,39257).
+char(c,39258).
+char(m,39259).
+char(1,39260).
+char(1,39261).
+char(1,39262).
+char(0,39263).
+char(c,39264).
+char(c,39265).
+char(c,39266).
+char(m,39267).
+char(5,39268).
+char(4,39269).
+char(5,39270).
+char(m,39271).
+char(o,39272).
+char(m,39273).
+char(7,39274).
+char(3,39275).
+char(3,39276).
+char(7,39277).
+char(m,39278).
+char(o,39279).
+char(o,39280).
+char(m,39281).
+char(o,39282).
+char(o,39283).
+char(7,39284).
+char(5,39285).
+char(6,39286).
+char(6,39287).
+char(p,39288).
+char(o,39289).
+char(p,39290).
+char(2,39291).
+char(4,39292).
+char(8,39293).
+char(1,39294).
+char(c,39295).
+char(m,39296).
+char(3,39297).
+char(8,39298).
+char(6,39299).
+char(4,39300).
+char(c,39301).
+char(c,39302).
+char(p,39303).
+char(o,39304).
+char(m,39305).
+char(4,39306).
+char(6,39307).
+char(1,39308).
+char(2,39309).
+char(p,39310).
+char(7,39311).
+char(0,39312).
+char(4,39313).
+char(c,39314).
+char(m,39315).
+char(6,39316).
+char(2,39317).
+char(6,39318).
+char(8,39319).
+char(p,39320).
+char(o,39321).
+char(o,39322).
+char(o,39323).
+char(p,39324).
+char(o,39325).
+char(p,39326).
+char(6,39327).
+char(9,39328).
+char(8,39329).
+char(4,39330).
+char(c,39331).
+char(p,39332).
+char(o,39333).
+char(p,39334).
+char(5,39335).
+char(2,39336).
+char(7,39337).
+char(8,39338).
+char(p,39339).
+char(o,39340).
+char(m,39341).
+char(o,39342).
+char(o,39343).
+char(p,39344).
+char(o,39345).
+char(p,39346).
+char(o,39347).
+char(p,39348).
+char(2,39349).
+char(4,39350).
+char(3,39351).
+char(3,39352).
+char(m,39353).
+char(1,39354).
+char(8,39355).
+char(1,39356).
+char(0,39357).
+char(m,39358).
+char(9,39359).
+char(2,39360).
+char(2,39361).
+char(9,39362).
+char(p,39363).
+char(o,39364).
+char(p,39365).
+char(o,39366).
+char(2,39367).
+char(0,39368).
+char(9,39369).
+char(8,39370).
+char(p,39371).
+char(o,39372).
+char(p,39373).
+char(o,39374).
+char(p,39375).
+char(o,39376).
+char(5,39377).
+char(2,39378).
+char(3,39379).
+char(8,39380).
+char(c,39381).
+char(p,39382).
+char(o,39383).
+char(p,39384).
+char(o,39385).
+char(m,39386).
+char(o,39387).
+char(p,39388).
+char(o,39389).
+char(p,39390).
+char(8,39391).
+char(6,39392).
+char(3,39393).
+char(1,39394).
+char(c,39395).
+char(c,39396).
+char(c,39397).
+char(c,39398).
+char(c,39399).
+char(c,39400).
+char(c,39401).
+char(c,39402).
+char(c,39403).
+char(m,39404).
+char(o,39405).
+char(p,39406).
+char(o,39407).
+char(m,39408).
+char(o,39409).
+char(6,39410).
+char(2,39411).
+char(2,39412).
+char(5,39413).
+char(c,39414).
+char(c,39415).
+char(c,39416).
+char(c,39417).
+char(m,39418).
+char(o,39419).
+char(o,39420).
+char(o,39421).
+char(p,39422).
+char(2,39423).
+char(6,39424).
+char(2,39425).
+char(0,39426).
+char(c,39427).
+char(c,39428).
+char(p,39429).
+char(4,39430).
+char(5,39431).
+char(2,39432).
+char(0,39433).
+char(c,39434).
+char(p,39435).
+char(o,39436).
+char(1,39437).
+char(2,39438).
+char(9,39439).
+char(4,39440).
+char(c,39441).
+char(c,39442).
+char(p,39443).
+char(2,39444).
+char(8,39445).
+char(7,39446).
+char(9,39447).
+char(c,39448).
+char(c,39449).
+char(c,39450).
+char(p,39451).
+char(o,39452).
+char(m,39453).
+char(o,39454).
+char(m,39455).
+char(o,39456).
+char(o,39457).
+char(9,39458).
+char(7,39459).
+char(7,39460).
+char(7,39461).
+char(c,39462).
+char(m,39463).
+char(o,39464).
+char(p,39465).
+char(4,39466).
+char(6,39467).
+char(3,39468).
+char(6,39469).
+char(p,39470).
+char(o,39471).
+char(m,39472).
+char(2,39473).
+char(3,39474).
+char(0,39475).
+char(6,39476).
+char(c,39477).
+char(p,39478).
+char(4,39479).
+char(3,39480).
+char(5,39481).
+char(7,39482).
+char(m,39483).
+char(o,39484).
+char(o,39485).
+char(m,39486).
+char(1,39487).
+char(1,39488).
+char(8,39489).
+char(2,39490).
+char(p,39491).
+char(2,39492).
+char(9,39493).
+char(4,39494).
+char(9,39495).
+char(p,39496).
+char(o,39497).
+char(p,39498).
+char(o,39499).
+char(m,39500).
+char(1,39501).
+char(5,39502).
+char(4,39503).
+char(7,39504).
+char(c,39505).
+char(c,39506).
+char(c,39507).
+char(c,39508).
+char(c,39509).
+char(p,39510).
+char(o,39511).
+char(m,39512).
+char(o,39513).
+char(p,39514).
+char(o,39515).
+char(p,39516).
+char(o,39517).
+char(o,39518).
+char(3,39519).
+char(6,39520).
+char(7,39521).
+char(3,39522).
+char(c,39523).
+char(c,39524).
+char(c,39525).
+char(p,39526).
+char(o,39527).
+char(o,39528).
+char(m,39529).
+char(o,39530).
+char(m,39531).
+char(o,39532).
+char(p,39533).
+char(3,39534).
+char(2,39535).
+char(5,39536).
+char(6,39537).
+char(p,39538).
+char(o,39539).
+char(p,39540).
+char(9,39541).
+char(8,39542).
+char(4,39543).
+char(8,39544).
+char(p,39545).
+char(8,39546).
+char(4,39547).
+char(5,39548).
+char(6,39549).
+char(p,39550).
+char(7,39551).
+char(8,39552).
+char(2,39553).
+char(9,39554).
+char(p,39555).
+char(1,39556).
+char(4,39557).
+char(0,39558).
+char(3,39559).
+char(c,39560).
+char(m,39561).
+char(o,39562).
+char(m,39563).
+char(6,39564).
+char(2,39565).
+char(5,39566).
+char(5,39567).
+char(p,39568).
+char(o,39569).
+char(8,39570).
+char(2,39571).
+char(5,39572).
+char(6,39573).
+char(p,39574).
+char(7,39575).
+char(4,39576).
+char(3,39577).
+char(8,39578).
+char(m,39579).
+char(6,39580).
+char(3,39581).
+char(2,39582).
+char(0,39583).
+char(c,39584).
+char(p,39585).
+char(o,39586).
+char(6,39587).
+char(9,39588).
+char(1,39589).
+char(7,39590).
+char(c,39591).
+char(c,39592).
+char(c,39593).
+char(c,39594).
+char(m,39595).
+char(o,39596).
+char(p,39597).
+char(o,39598).
+char(m,39599).
+char(6,39600).
+char(9,39601).
+char(1,39602).
+char(9,39603).
+char(c,39604).
+char(c,39605).
+char(p,39606).
+char(6,39607).
+char(2,39608).
+char(3,39609).
+char(4,39610).
+char(m,39611).
+char(7,39612).
+char(7,39613).
+char(5,39614).
+char(3,39615).
+char(c,39616).
+char(p,39617).
+char(o,39618).
+char(m,39619).
+char(o,39620).
+char(7,39621).
+char(1,39622).
+char(4,39623).
+char(0,39624).
+char(m,39625).
+char(5,39626).
+char(3,39627).
+char(5,39628).
+char(8,39629).
+char(m,39630).
+char(1,39631).
+char(1,39632).
+char(0,39633).
+char(p,39634).
+char(1,39635).
+char(2,39636).
+char(0,39637).
+char(1,39638).
+char(c,39639).
+char(m,39640).
+char(o,39641).
+char(m,39642).
+char(o,39643).
+char(o,39644).
+char(p,39645).
+char(o,39646).
+char(m,39647).
+char(4,39648).
+char(0,39649).
+char(8,39650).
+char(9,39651).
+char(c,39652).
+char(c,39653).
+char(c,39654).
+char(c,39655).
+char(c,39656).
+char(c,39657).
+char(p,39658).
+char(5,39659).
+char(8,39660).
+char(5,39661).
+char(1,39662).
+char(c,39663).
+char(m,39664).
+char(o,39665).
+char(m,39666).
+char(9,39667).
+char(0,39668).
+char(4,39669).
+char(5,39670).
+char(c,39671).
+char(m,39672).
+char(o,39673).
+char(m,39674).
+char(o,39675).
+char(4,39676).
+char(8,39677).
+char(7,39678).
+char(0,39679).
+char(m,39680).
+char(1,39681).
+char(9,39682).
+char(9,39683).
+char(4,39684).
+char(c,39685).
+char(c,39686).
+char(p,39687).
+char(3,39688).
+char(8,39689).
+char(4,39690).
+char(2,39691).
+char(c,39692).
+char(p,39693).
+char(o,39694).
+char(m,39695).
+char(8,39696).
+char(1,39697).
+char(0,39698).
+char(5,39699).
+char(c,39700).
+char(m,39701).
+char(7,39702).
+char(0,39703).
+char(8,39704).
+char(9,39705).
+char(m,39706).
+char(9,39707).
+char(4,39708).
+char(2,39709).
+char(5,39710).
+char(m,39711).
+char(2,39712).
+char(6,39713).
+char(7,39714).
+char(3,39715).
+char(p,39716).
+char(o,39717).
+char(p,39718).
+char(9,39719).
+char(9,39720).
+char(3,39721).
+char(9,39722).
+char(c,39723).
+char(m,39724).
+char(o,39725).
+char(m,39726).
+char(5,39727).
+char(5,39728).
+char(1,39729).
+char(3,39730).
+char(c,39731).
+char(p,39732).
+char(4,39733).
+char(7,39734).
+char(2,39735).
+char(0,39736).
+char(p,39737).
+char(o,39738).
+char(p,39739).
+char(1,39740).
+char(9,39741).
+char(7,39742).
+char(9,39743).
+char(c,39744).
+char(c,39745).
+char(p,39746).
+char(1,39747).
+char(6,39748).
+char(2,39749).
+char(1,39750).
+char(m,39751).
+char(o,39752).
+char(o,39753).
+char(m,39754).
+char(o,39755).
+char(o,39756).
+char(m,39757).
+char(o,39758).
+char(m,39759).
+char(8,39760).
+char(7,39761).
+char(3,39762).
+char(9,39763).
+char(p,39764).
+char(o,39765).
+char(p,39766).
+char(o,39767).
+char(m,39768).
+char(o,39769).
+char(m,39770).
+char(o,39771).
+char(p,39772).
+char(o,39773).
+char(m,39774).
+char(5,39775).
+char(9,39776).
+char(9,39777).
+char(0,39778).
+char(p,39779).
+char(2,39780).
+char(6,39781).
+char(2,39782).
+char(3,39783).
+char(m,39784).
+char(o,39785).
+char(9,39786).
+char(4,39787).
+char(2,39788).
+char(0,39789).
+char(c,39790).
+char(c,39791).
+char(p,39792).
+char(5,39793).
+char(2,39794).
+char(8,39795).
+char(4,39796).
+char(c,39797).
+char(p,39798).
+char(o,39799).
+char(p,39800).
+char(o,39801).
+char(m,39802).
+char(3,39803).
+char(5,39804).
+char(1,39805).
+char(5,39806).
+char(c,39807).
+char(c,39808).
+char(c,39809).
+char(m,39810).
+char(o,39811).
+char(1,39812).
+char(8,39813).
+char(3,39814).
+char(7,39815).
+char(c,39816).
+char(c,39817).
+char(c,39818).
+char(m,39819).
+char(o,39820).
+char(p,39821).
+char(o,39822).
+char(m,39823).
+char(o,39824).
+char(p,39825).
+char(3,39826).
+char(0,39827).
+char(1,39828).
+char(3,39829).
+char(c,39830).
+char(c,39831).
+char(c,39832).
+char(m,39833).
+char(o,39834).
+char(o,39835).
+char(m,39836).
+char(o,39837).
+char(o,39838).
+char(p,39839).
+char(9,39840).
+char(8,39841).
+char(0,39842).
+char(3,39843).
+char(m,39844).
+char(7,39845).
+char(9,39846).
+char(4,39847).
+char(7,39848).
+char(c,39849).
+char(m,39850).
+char(1,39851).
+char(8,39852).
+char(5,39853).
+char(5,39854).
+char(c,39855).
+char(c,39856).
+char(c,39857).
+char(p,39858).
+char(o,39859).
+char(2,39860).
+char(3,39861).
+char(7,39862).
+char(8,39863).
+char(c,39864).
+char(p,39865).
+char(o,39866).
+char(p,39867).
+char(7,39868).
+char(3,39869).
+char(5,39870).
+char(6,39871).
+char(m,39872).
+char(7,39873).
+char(7,39874).
+char(0,39875).
+char(8,39876).
+char(c,39877).
+char(p,39878).
+char(o,39879).
+char(o,39880).
+char(m,39881).
+char(o,39882).
+char(m,39883).
+char(7,39884).
+char(7,39885).
+char(0,39886).
+char(8,39887).
+char(p,39888).
+char(5,39889).
+char(3,39890).
+char(7,39891).
+char(5,39892).
+char(m,39893).
+char(5,39894).
+char(0,39895).
+char(0,39896).
+char(7,39897).
+char(m,39898).
+char(o,39899).
+char(m,39900).
+char(o,39901).
+char(o,39902).
+char(m,39903).
+char(1,39904).
+char(1,39905).
+char(2,39906).
+char(6,39907).
+char(p,39908).
+char(2,39909).
+char(8,39910).
+char(9,39911).
+char(8,39912).
+char(m,39913).
+char(5,39914).
+char(2,39915).
+char(6,39916).
+char(0,39917).
+char(m,39918).
+char(4,39919).
+char(5,39920).
+char(1,39921).
+char(7,39922).
+char(m,39923).
+char(o,39924).
+char(m,39925).
+char(o,39926).
+char(m,39927).
+char(5,39928).
+char(3,39929).
+char(1,39930).
+char(7,39931).
+char(p,39932).
+char(1,39933).
+char(1,39934).
+char(1,39935).
+char(0,39936).
+char(m,39937).
+char(8,39938).
+char(2,39939).
+char(8,39940).
+char(p,39941).
+char(o,39942).
+char(m,39943).
+char(1,39944).
+char(0,39945).
+char(8,39946).
+char(5,39947).
+char(p,39948).
+char(o,39949).
+char(o,39950).
+char(o,39951).
+char(p,39952).
+char(o,39953).
+char(p,39954).
+char(1,39955).
+char(2,39956).
+char(1,39957).
+char(4,39958).
+char(p,39959).
+char(4,39960).
+char(0,39961).
+char(1,39962).
+char(0,39963).
+char(m,39964).
+char(o,39965).
+char(p,39966).
+char(8,39967).
+char(3,39968).
+char(3,39969).
+char(2,39970).
+char(c,39971).
+char(m,39972).
+char(o,39973).
+char(9,39974).
+char(7,39975).
+char(7,39976).
+char(4,39977).
+char(c,39978).
+char(p,39979).
+char(o,39980).
+char(p,39981).
+char(o,39982).
+char(o,39983).
+char(p,39984).
+char(o,39985).
+char(m,39986).
+char(9,39987).
+char(5,39988).
+char(8,39989).
+char(0,39990).
+char(m,39991).
+char(1,39992).
+char(1,39993).
+char(1,39994).
+char(1,39995).
+char(c,39996).
+char(c,39997).
+char(c,39998).
+char(c,39999).
+char(p,40000).
+char(o,40001).
+char(m,40002).
+char(o,40003).
+char(8,40004).
+char(5,40005).
+char(4,40006).
+char(0,40007).
+char(m,40008).
+char(7,40009).
+char(7,40010).
+char(5,40011).
+char(2,40012).
+char(m,40013).
+char(8,40014).
+char(5,40015).
+char(1,40016).
+char(6,40017).
+char(c,40018).
+char(p,40019).
+char(o,40020).
+char(o,40021).
+char(p,40022).
+char(7,40023).
+char(6,40024).
+char(c,40025).
+char(m,40026).
+char(1,40027).
+char(0,40028).
+char(3,40029).
+char(2,40030).
+char(c,40031).
+char(c,40032).
+char(m,40033).
+char(o,40034).
+char(m,40035).
+char(8,40036).
+char(0,40037).
+char(9,40038).
+char(8,40039).
+char(c,40040).
+char(c,40041).
+char(c,40042).
+char(p,40043).
+char(2,40044).
+char(0,40045).
+char(5,40046).
+char(5,40047).
+char(c,40048).
+char(p,40049).
+char(o,40050).
+char(7,40051).
+char(9,40052).
+char(4,40053).
+char(4,40054).
+char(p,40055).
+char(o,40056).
+char(m,40057).
+char(5,40058).
+char(4,40059).
+char(1,40060).
+char(6,40061).
+char(m,40062).
+char(o,40063).
+char(m,40064).
+char(4,40065).
+char(4,40066).
+char(3,40067).
+char(3,40068).
+char(m,40069).
+char(3,40070).
+char(0,40071).
+char(6,40072).
+char(2,40073).
+char(c,40074).
+char(p,40075).
+char(2,40076).
+char(5,40077).
+char(2,40078).
+char(2,40079).
+char(c,40080).
+char(m,40081).
+char(7,40082).
+char(1,40083).
+char(2,40084).
+char(6,40085).
+char(c,40086).
+char(c,40087).
+char(c,40088).
+char(m,40089).
+char(o,40090).
+char(o,40091).
+char(p,40092).
+char(3,40093).
+char(3,40094).
+char(4,40095).
+char(1,40096).
+char(c,40097).
+char(c,40098).
+char(m,40099).
+char(o,40100).
+char(m,40101).
+char(3,40102).
+char(3,40103).
+char(9,40104).
+char(2,40105).
+char(m,40106).
+char(o,40107).
+char(o,40108).
+char(3,40109).
+char(2,40110).
+char(0,40111).
+char(3,40112).
+char(p,40113).
+char(o,40114).
+char(8,40115).
+char(3,40116).
+char(2,40117).
+char(7,40118).
+char(c,40119).
+char(m,40120).
+char(8,40121).
+char(2,40122).
+char(9,40123).
+char(4,40124).
+char(m,40125).
+char(o,40126).
+char(m,40127).
+char(o,40128).
+char(p,40129).
+char(o,40130).
+char(m,40131).
+char(3,40132).
+char(3,40133).
+char(1,40134).
+char(8,40135).
+char(m,40136).
+char(o,40137).
+char(p,40138).
+char(o,40139).
+char(m,40140).
+char(3,40141).
+char(6,40142).
+char(5,40143).
+char(7,40144).
+char(m,40145).
+char(5,40146).
+char(1,40147).
+char(4,40148).
+char(3,40149).
+char(c,40150).
+char(p,40151).
+char(o,40152).
+char(m,40153).
+char(o,40154).
+char(p,40155).
+char(o,40156).
+char(m,40157).
+char(o,40158).
+char(p,40159).
+char(o,40160).
+char(m,40161).
+char(6,40162).
+char(5,40163).
+char(5,40164).
+char(5,40165).
+char(c,40166).
+char(c,40167).
+char(c,40168).
+char(p,40169).
+char(3,40170).
+char(9,40171).
+char(8,40172).
+char(5,40173).
+char(p,40174).
+char(1,40175).
+char(3,40176).
+char(7,40177).
+char(8,40178).
+char(m,40179).
+char(1,40180).
+char(1,40181).
+char(2,40182).
+char(8,40183).
+char(m,40184).
+char(o,40185).
+char(m,40186).
+char(5,40187).
+char(6,40188).
+char(5,40189).
+char(6,40190).
+char(p,40191).
+char(1,40192).
+char(7,40193).
+char(6,40194).
+char(2,40195).
+char(m,40196).
+char(4,40197).
+char(7,40198).
+char(3,40199).
+char(4,40200).
+char(m,40201).
+char(o,40202).
+char(m,40203).
+char(9,40204).
+char(9,40205).
+char(1,40206).
+char(5,40207).
+char(m,40208).
+char(o,40209).
+char(p,40210).
+char(2,40211).
+char(0,40212).
+char(5,40213).
+char(3,40214).
+char(m,40215).
+char(7,40216).
+char(5,40217).
+char(9,40218).
+char(3,40219).
+char(p,40220).
+char(9,40221).
+char(7,40222).
+char(3,40223).
+char(8,40224).
+char(c,40225).
+char(c,40226).
+char(c,40227).
+char(p,40228).
+char(o,40229).
+char(m,40230).
+char(o,40231).
+char(o,40232).
+char(m,40233).
+char(o,40234).
+char(p,40235).
+char(1,40236).
+char(0,40237).
+char(5,40238).
+char(6,40239).
+char(m,40240).
+char(o,40241).
+char(m,40242).
+char(o,40243).
+char(o,40244).
+char(m,40245).
+char(3,40246).
+char(3,40247).
+char(9,40248).
+char(6,40249).
+char(m,40250).
+char(8,40251).
+char(5,40252).
+char(2,40253).
+char(9,40254).
+char(p,40255).
+char(2,40256).
+char(9,40257).
+char(1,40258).
+char(0,40259).
+char(m,40260).
+char(5,40261).
+char(7,40262).
+char(0,40263).
+char(4,40264).
+char(p,40265).
+char(7,40266).
+char(3,40267).
+char(8,40268).
+char(3,40269).
+char(m,40270).
+char(9,40271).
+char(5,40272).
+char(3,40273).
+char(c,40274).
+char(c,40275).
+char(c,40276).
+char(c,40277).
+char(m,40278).
+char(4,40279).
+char(4,40280).
+char(2,40281).
+char(2,40282).
+char(m,40283).
+char(1,40284).
+char(8,40285).
+char(4,40286).
+char(4,40287).
+char(c,40288).
+char(m,40289).
+char(4,40290).
+char(9,40291).
+char(0,40292).
+char(8,40293).
+char(c,40294).
+char(m,40295).
+char(1,40296).
+char(5,40297).
+char(9,40298).
+char(1,40299).
+char(c,40300).
+char(m,40301).
+char(4,40302).
+char(1,40303).
+char(5,40304).
+char(3,40305).
+char(p,40306).
+char(o,40307).
+char(o,40308).
+char(o,40309).
+char(5,40310).
+char(8,40311).
+char(0,40312).
+char(6,40313).
+char(p,40314).
+char(o,40315).
+char(o,40316).
+char(o,40317).
+char(p,40318).
+char(4,40319).
+char(2,40320).
+char(5,40321).
+char(6,40322).
+char(p,40323).
+char(o,40324).
+char(m,40325).
+char(3,40326).
+char(8,40327).
+char(1,40328).
+char(2,40329).
+char(c,40330).
+char(c,40331).
+char(c,40332).
+char(c,40333).
+char(p,40334).
+char(2,40335).
+char(8,40336).
+char(1,40337).
+char(1,40338).
+char(p,40339).
+char(o,40340).
+char(m,40341).
+char(2,40342).
+char(3,40343).
+char(4,40344).
+char(4,40345).
+char(p,40346).
+char(o,40347).
+char(o,40348).
+char(p,40349).
+char(8,40350).
+char(3,40351).
+char(4,40352).
+char(p,40353).
+char(3,40354).
+char(4,40355).
+char(6,40356).
+char(2,40357).
+char(m,40358).
+char(6,40359).
+char(0,40360).
+char(2,40361).
+char(1,40362).
+char(c,40363).
+char(c,40364).
+char(c,40365).
+char(c,40366).
+char(c,40367).
+char(p,40368).
+char(o,40369).
+char(p,40370).
+char(9,40371).
+char(5,40372).
+char(3,40373).
+char(0,40374).
+char(c,40375).
+char(m,40376).
+char(2,40377).
+char(5,40378).
+char(5,40379).
+char(5,40380).
+char(c,40381).
+char(c,40382).
+char(p,40383).
+char(2,40384).
+char(4,40385).
+char(5,40386).
+char(4,40387).
+char(c,40388).
+char(m,40389).
+char(7,40390).
+char(7,40391).
+char(4,40392).
+char(c,40393).
+char(c,40394).
+char(m,40395).
+char(o,40396).
+char(4,40397).
+char(4,40398).
+char(4,40399).
+char(2,40400).
+char(c,40401).
+char(c,40402).
+char(p,40403).
+char(4,40404).
+char(6,40405).
+char(7,40406).
+char(4,40407).
+char(m,40408).
+char(4,40409).
+char(0,40410).
+char(2,40411).
+char(p,40412).
+char(2,40413).
+char(1,40414).
+char(0,40415).
+char(5,40416).
+char(p,40417).
+char(2,40418).
+char(4,40419).
+char(5,40420).
+char(3,40421).
+char(m,40422).
+char(8,40423).
+char(2,40424).
+char(8,40425).
+char(2,40426).
+char(c,40427).
+char(p,40428).
+char(o,40429).
+char(p,40430).
+char(o,40431).
+char(o,40432).
+char(p,40433).
+char(9,40434).
+char(5,40435).
+char(1,40436).
+char(1,40437).
+char(c,40438).
+char(c,40439).
+char(c,40440).
+char(p,40441).
+char(7,40442).
+char(2,40443).
+char(3,40444).
+char(6,40445).
+char(c,40446).
+char(p,40447).
+char(o,40448).
+char(p,40449).
+char(6,40450).
+char(0,40451).
+char(9,40452).
+char(2,40453).
+char(m,40454).
+char(1,40455).
+char(7,40456).
+char(1,40457).
+char(4,40458).
+char(c,40459).
+char(c,40460).
+char(c,40461).
+char(c,40462).
+char(m,40463).
+char(o,40464).
+char(p,40465).
+char(9,40466).
+char(5,40467).
+char(1,40468).
+char(6,40469).
+char(p,40470).
+char(o,40471).
+char(7,40472).
+char(3,40473).
+char(3,40474).
+char(3,40475).
+char(m,40476).
+char(7,40477).
+char(0,40478).
+char(6,40479).
+char(5,40480).
+char(m,40481).
+char(o,40482).
+char(m,40483).
+char(o,40484).
+char(o,40485).
+char(m,40486).
+char(o,40487).
+char(m,40488).
+char(o,40489).
+char(m,40490).
+char(o,40491).
+char(o,40492).
+char(9,40493).
+char(3,40494).
+char(9,40495).
+char(1,40496).
+char(m,40497).
+char(8,40498).
+char(6,40499).
+char(1,40500).
+char(3,40501).
+char(c,40502).
+char(c,40503).
+char(c,40504).
+char(c,40505).
+char(m,40506).
+char(o,40507).
+char(m,40508).
+char(6,40509).
+char(2,40510).
+char(8,40511).
+char(4,40512).
+char(c,40513).
+char(c,40514).
+char(m,40515).
+char(o,40516).
+char(o,40517).
+char(p,40518).
+char(o,40519).
+char(m,40520).
+char(4,40521).
+char(4,40522).
+char(7,40523).
+char(2,40524).
+char(c,40525).
+char(c,40526).
+char(p,40527).
+char(3,40528).
+char(8,40529).
+char(3,40530).
+char(6,40531).
+char(c,40532).
+char(p,40533).
+char(o,40534).
+char(p,40535).
+char(2,40536).
+char(0,40537).
+char(3,40538).
+char(7,40539).
+char(m,40540).
+char(o,40541).
+char(p,40542).
+char(o,40543).
+char(m,40544).
+char(o,40545).
+char(o,40546).
+char(p,40547).
+char(o,40548).
+char(m,40549).
+char(o,40550).
+char(m,40551).
+char(o,40552).
+char(2,40553).
+char(8,40554).
+char(9,40555).
+char(3,40556).
+char(p,40557).
+char(o,40558).
+char(p,40559).
+char(o,40560).
+char(p,40561).
+char(5,40562).
+char(0,40563).
+char(4,40564).
+char(0,40565).
+char(p,40566).
+char(2,40567).
+char(7,40568).
+char(4,40569).
+char(8,40570).
+char(c,40571).
+char(m,40572).
+char(7,40573).
+char(0,40574).
+char(4,40575).
+char(1,40576).
+char(c,40577).
+char(m,40578).
+char(6,40579).
+char(8,40580).
+char(2,40581).
+char(6,40582).
+char(c,40583).
+char(p,40584).
+char(o,40585).
+char(6,40586).
+char(3,40587).
+char(5,40588).
+char(8,40589).
+char(c,40590).
+char(p,40591).
+char(o,40592).
+char(m,40593).
+char(o,40594).
+char(o,40595).
+char(p,40596).
+char(8,40597).
+char(2,40598).
+char(1,40599).
+char(0,40600).
+char(m,40601).
+char(8,40602).
+char(3,40603).
+char(6,40604).
+char(4,40605).
+char(m,40606).
+char(o,40607).
+char(7,40608).
+char(8,40609).
+char(9,40610).
+char(9,40611).
+char(m,40612).
+char(7,40613).
+char(0,40614).
+char(4,40615).
+char(5,40616).
+char(c,40617).
+char(c,40618).
+char(c,40619).
+char(p,40620).
+char(o,40621).
+char(p,40622).
+char(o,40623).
+char(m,40624).
+char(7,40625).
+char(8,40626).
+char(1,40627).
+char(0,40628).
+char(c,40629).
+char(c,40630).
+char(p,40631).
+char(8,40632).
+char(6,40633).
+char(1,40634).
+char(0,40635).
+char(p,40636).
+char(5,40637).
+char(1,40638).
+char(8,40639).
+char(7,40640).
+char(p,40641).
+char(8,40642).
+char(5,40643).
+char(2,40644).
+char(4,40645).
+char(p,40646).
+char(o,40647).
+char(m,40648).
+char(o,40649).
+char(m,40650).
+char(9,40651).
+char(4,40652).
+char(9,40653).
+char(6,40654).
+char(p,40655).
+char(o,40656).
+char(o,40657).
+char(p,40658).
+char(o,40659).
+char(m,40660).
+char(4,40661).
+char(7,40662).
+char(3,40663).
+char(4,40664).
+char(c,40665).
+char(c,40666).
+char(c,40667).
+char(p,40668).
+char(o,40669).
+char(9,40670).
+char(6,40671).
+char(5,40672).
+char(3,40673).
+char(p,40674).
+char(o,40675).
+char(m,40676).
+char(7,40677).
+char(6,40678).
+char(3,40679).
+char(5,40680).
+char(p,40681).
+char(o,40682).
+char(m,40683).
+char(1,40684).
+char(2,40685).
+char(5,40686).
+char(7,40687).
+char(m,40688).
+char(o,40689).
+char(o,40690).
+char(o,40691).
+char(o,40692).
+char(o,40693).
+char(p,40694).
+char(3,40695).
+char(5,40696).
+char(5,40697).
+char(8,40698).
+char(m,40699).
+char(9,40700).
+char(9,40701).
+char(0,40702).
+char(8,40703).
+char(p,40704).
+char(o,40705).
+char(m,40706).
+char(o,40707).
+char(m,40708).
+char(2,40709).
+char(8,40710).
+char(9,40711).
+char(3,40712).
+char(c,40713).
+char(p,40714).
+char(o,40715).
+char(o,40716).
+char(p,40717).
+char(o,40718).
+char(m,40719).
+char(5,40720).
+char(7,40721).
+char(4,40722).
+char(6,40723).
+char(c,40724).
+char(c,40725).
+char(p,40726).
+char(o,40727).
+char(m,40728).
+char(o,40729).
+char(p,40730).
+char(o,40731).
+char(p,40732).
+char(o,40733).
+char(m,40734).
+char(1,40735).
+char(9,40736).
+char(2,40737).
+char(4,40738).
+char(c,40739).
+char(m,40740).
+char(o,40741).
+char(4,40742).
+char(3,40743).
+char(4,40744).
+char(0,40745).
+char(c,40746).
+char(p,40747).
+char(o,40748).
+char(m,40749).
+char(9,40750).
+char(9,40751).
+char(1,40752).
+char(2,40753).
+char(p,40754).
+char(o,40755).
+char(7,40756).
+char(9,40757).
+char(4,40758).
+char(4,40759).
+char(p,40760).
+char(4,40761).
+char(2,40762).
+char(0,40763).
+char(1,40764).
+char(c,40765).
+char(m,40766).
+char(7,40767).
+char(4,40768).
+char(5,40769).
+char(0,40770).
+char(c,40771).
+char(m,40772).
+char(o,40773).
+char(o,40774).
+char(p,40775).
+char(o,40776).
+char(o,40777).
+char(m,40778).
+char(9,40779).
+char(6,40780).
+char(2,40781).
+char(c,40782).
+char(m,40783).
+char(o,40784).
+char(4,40785).
+char(5,40786).
+char(0,40787).
+char(6,40788).
+char(p,40789).
+char(o,40790).
+char(p,40791).
+char(6,40792).
+char(2,40793).
+char(9,40794).
+char(9,40795).
+char(p,40796).
+char(9,40797).
+char(8,40798).
+char(1,40799).
+char(6,40800).
+char(c,40801).
+char(m,40802).
+char(8,40803).
+char(4,40804).
+char(4,40805).
+char(7,40806).
+char(m,40807).
+char(5,40808).
+char(2,40809).
+char(2,40810).
+char(1,40811).
+char(c,40812).
+char(p,40813).
+char(o,40814).
+char(p,40815).
+char(8,40816).
+char(5,40817).
+char(8,40818).
+char(5,40819).
+char(m,40820).
+char(o,40821).
+char(p,40822).
+char(6,40823).
+char(9,40824).
+char(7,40825).
+char(5,40826).
+char(m,40827).
+char(9,40828).
+char(9,40829).
+char(8,40830).
+char(9,40831).
+char(p,40832).
+char(4,40833).
+char(0,40834).
+char(0,40835).
+char(3,40836).
+char(p,40837).
+char(o,40838).
+char(7,40839).
+char(6,40840).
+char(2,40841).
+char(4,40842).
+char(c,40843).
+char(m,40844).
+char(o,40845).
+char(m,40846).
+char(3,40847).
+char(8,40848).
+char(5,40849).
+char(5,40850).
+char(m,40851).
+char(o,40852).
+char(m,40853).
+char(3,40854).
+char(4,40855).
+char(2,40856).
+char(4,40857).
+char(p,40858).
+char(2,40859).
+char(5,40860).
+char(0,40861).
+char(9,40862).
+char(p,40863).
+char(o,40864).
+char(p,40865).
+char(o,40866).
+char(p,40867).
+char(6,40868).
+char(1,40869).
+char(0,40870).
+char(0,40871).
+char(p,40872).
+char(3,40873).
+char(5,40874).
+char(3,40875).
+char(m,40876).
+char(o,40877).
+char(o,40878).
+char(p,40879).
+char(9,40880).
+char(6,40881).
+char(6,40882).
+char(p,40883).
+char(o,40884).
+char(m,40885).
+char(o,40886).
+char(m,40887).
+char(2,40888).
+char(8,40889).
+char(1,40890).
+char(4,40891).
+char(c,40892).
+char(m,40893).
+char(o,40894).
+char(m,40895).
+char(6,40896).
+char(7,40897).
+char(9,40898).
+char(6,40899).
+char(c,40900).
+char(c,40901).
+char(m,40902).
+char(o,40903).
+char(p,40904).
+char(1,40905).
+char(4,40906).
+char(6,40907).
+char(2,40908).
+char(p,40909).
+char(4,40910).
+char(6,40911).
+char(5,40912).
+char(5,40913).
+char(c,40914).
+char(m,40915).
+char(4,40916).
+char(8,40917).
+char(0,40918).
+char(0,40919).
+char(c,40920).
+char(c,40921).
+char(m,40922).
+char(4,40923).
+char(2,40924).
+char(7,40925).
+char(9,40926).
+char(m,40927).
+char(o,40928).
+char(p,40929).
+char(2,40930).
+char(3,40931).
+char(7,40932).
+char(3,40933).
+char(c,40934).
+char(m,40935).
+char(2,40936).
+char(1,40937).
+char(0,40938).
+char(1,40939).
+char(p,40940).
+char(1,40941).
+char(5,40942).
+char(3,40943).
+char(1,40944).
+char(c,40945).
+char(m,40946).
+char(6,40947).
+char(9,40948).
+char(0,40949).
+char(3,40950).
+char(p,40951).
+char(o,40952).
+char(p,40953).
+char(8,40954).
+char(2,40955).
+char(8,40956).
+char(5,40957).
+char(c,40958).
+char(c,40959).
+char(c,40960).
+char(c,40961).
+char(p,40962).
+char(7,40963).
+char(4,40964).
+char(1,40965).
+char(2,40966).
+char(p,40967).
+char(5,40968).
+char(1,40969).
+char(6,40970).
+char(4,40971).
+char(c,40972).
+char(c,40973).
+char(c,40974).
+char(c,40975).
+char(p,40976).
+char(7,40977).
+char(9,40978).
+char(1,40979).
+char(5,40980).
+char(m,40981).
+char(o,40982).
+char(m,40983).
+char(o,40984).
+char(m,40985).
+char(2,40986).
+char(1,40987).
+char(1,40988).
+char(2,40989).
+char(c,40990).
+char(p,40991).
+char(o,40992).
+char(m,40993).
+char(o,40994).
+char(m,40995).
+char(9,40996).
+char(5,40997).
+char(6,40998).
+char(1,40999).
+char(m,41000).
+char(8,41001).
+char(9,41002).
+char(6,41003).
+char(6,41004).
+char(p,41005).
+char(o,41006).
+char(p,41007).
+char(6,41008).
+char(0,41009).
+char(0,41010).
+char(8,41011).
+char(c,41012).
+char(p,41013).
+char(1,41014).
+char(5,41015).
+char(8,41016).
+char(7,41017).
+char(p,41018).
+char(2,41019).
+char(1,41020).
+char(9,41021).
+char(1,41022).
+char(c,41023).
+char(c,41024).
+char(c,41025).
+char(p,41026).
+char(o,41027).
+char(4,41028).
+char(2,41029).
+char(8,41030).
+char(2,41031).
+char(c,41032).
+char(c,41033).
+char(p,41034).
+char(8,41035).
+char(6,41036).
+char(2,41037).
+char(8,41038).
+char(m,41039).
+char(1,41040).
+char(8,41041).
+char(1,41042).
+char(3,41043).
+char(c,41044).
+char(p,41045).
+char(o,41046).
+char(p,41047).
+char(3,41048).
+char(8,41049).
+char(3,41050).
+char(5,41051).
+char(c,41052).
+char(c,41053).
+char(p,41054).
+char(o,41055).
+char(m,41056).
+char(9,41057).
+char(0,41058).
+char(1,41059).
+char(4,41060).
+char(m,41061).
+char(4,41062).
+char(6,41063).
+char(9,41064).
+char(c,41065).
+char(c,41066).
+char(p,41067).
+char(4,41068).
+char(1,41069).
+char(5,41070).
+char(1,41071).
+char(c,41072).
+char(c,41073).
+char(c,41074).
+char(c,41075).
+char(p,41076).
+char(4,41077).
+char(7,41078).
+char(5,41079).
+char(2,41080).
+char(p,41081).
+char(o,41082).
+char(o,41083).
+char(m,41084).
+char(o,41085).
+char(2,41086).
+char(4,41087).
+char(2,41088).
+char(5,41089).
+char(m,41090).
+char(o,41091).
+char(m,41092).
+char(8,41093).
+char(0,41094).
+char(0,41095).
+char(0,41096).
+char(p,41097).
+char(o,41098).
+char(o,41099).
+char(p,41100).
+char(o,41101).
+char(m,41102).
+char(3,41103).
+char(8,41104).
+char(3,41105).
+char(9,41106).
+char(c,41107).
+char(c,41108).
+char(c,41109).
+char(c,41110).
+char(p,41111).
+char(o,41112).
+char(m,41113).
+char(8,41114).
+char(2,41115).
+char(0,41116).
+char(2,41117).
+char(p,41118).
+char(o,41119).
+char(m,41120).
+char(o,41121).
+char(p,41122).
+char(o,41123).
+char(p,41124).
+char(o,41125).
+char(m,41126).
+char(8,41127).
+char(9,41128).
+char(3,41129).
+char(8,41130).
+char(c,41131).
+char(c,41132).
+char(c,41133).
+char(c,41134).
+char(m,41135).
+char(6,41136).
+char(1,41137).
+char(7,41138).
+char(7,41139).
+char(p,41140).
+char(o,41141).
+char(o,41142).
+char(6,41143).
+char(4,41144).
+char(9,41145).
+char(9,41146).
+char(m,41147).
+char(o,41148).
+char(4,41149).
+char(1,41150).
+char(2,41151).
+char(0,41152).
+char(p,41153).
+char(4,41154).
+char(3,41155).
+char(3,41156).
+char(7,41157).
+char(c,41158).
+char(c,41159).
+char(c,41160).
+char(c,41161).
+char(m,41162).
+char(o,41163).
+char(p,41164).
+char(8,41165).
+char(4,41166).
+char(2,41167).
+char(9,41168).
+char(p,41169).
+char(o,41170).
+char(3,41171).
+char(4,41172).
+char(1,41173).
+char(9,41174).
+char(c,41175).
+char(m,41176).
+char(o,41177).
+char(o,41178).
+char(p,41179).
+char(o,41180).
+char(p,41181).
+char(7,41182).
+char(8,41183).
+char(5,41184).
+char(0,41185).
+char(c,41186).
+char(c,41187).
+char(c,41188).
+char(m,41189).
+char(o,41190).
+char(m,41191).
+char(6,41192).
+char(3,41193).
+char(3,41194).
+char(p,41195).
+char(9,41196).
+char(5,41197).
+char(6,41198).
+char(7,41199).
+char(p,41200).
+char(o,41201).
+char(p,41202).
+char(9,41203).
+char(0,41204).
+char(4,41205).
+char(2,41206).
+char(c,41207).
+char(c,41208).
+char(p,41209).
+char(o,41210).
+char(o,41211).
+char(m,41212).
+char(o,41213).
+char(m,41214).
+char(o,41215).
+char(m,41216).
+char(3,41217).
+char(6,41218).
+char(0,41219).
+char(1,41220).
+char(p,41221).
+char(o,41222).
+char(p,41223).
+char(o,41224).
+char(o,41225).
+char(p,41226).
+char(o,41227).
+char(m,41228).
+char(7,41229).
+char(1,41230).
+char(8,41231).
+char(4,41232).
+char(m,41233).
+char(2,41234).
+char(8,41235).
+char(4,41236).
+char(9,41237).
+char(c,41238).
+char(c,41239).
+char(c,41240).
+char(c,41241).
+char(c,41242).
+char(c,41243).
+char(m,41244).
+char(9,41245).
+char(6,41246).
+char(9,41247).
+char(1,41248).
+char(m,41249).
+char(8,41250).
+char(7,41251).
+char(5,41252).
+char(6,41253).
+char(m,41254).
+char(5,41255).
+char(4,41256).
+char(5,41257).
+char(5,41258).
+char(p,41259).
+char(9,41260).
+char(2,41261).
+char(1,41262).
+char(5,41263).
+char(m,41264).
+char(4,41265).
+char(6,41266).
+char(9,41267).
+char(0,41268).
+char(c,41269).
+char(c,41270).
+char(c,41271).
+char(p,41272).
+char(1,41273).
+char(6,41274).
+char(4,41275).
+char(0,41276).
+char(p,41277).
+char(o,41278).
+char(o,41279).
+char(p,41280).
+char(7,41281).
+char(6,41282).
+char(7,41283).
+char(7,41284).
+char(c,41285).
+char(c,41286).
+char(m,41287).
+char(o,41288).
+char(3,41289).
+char(1,41290).
+char(2,41291).
+char(c,41292).
+char(m,41293).
+char(o,41294).
+char(m,41295).
+char(2,41296).
+char(8,41297).
+char(9,41298).
+char(3,41299).
+char(p,41300).
+char(7,41301).
+char(2,41302).
+char(5,41303).
+char(8,41304).
+char(m,41305).
+char(o,41306).
+char(m,41307).
+char(1,41308).
+char(2,41309).
+char(3,41310).
+char(4,41311).
+char(m,41312).
+char(7,41313).
+char(4,41314).
+char(0,41315).
+char(4,41316).
+char(c,41317).
+char(c,41318).
+char(c,41319).
+char(c,41320).
+char(p,41321).
+char(9,41322).
+char(5,41323).
+char(3,41324).
+char(1,41325).
+char(m,41326).
+char(7,41327).
+char(2,41328).
+char(9,41329).
+char(6,41330).
+char(c,41331).
+char(c,41332).
+char(m,41333).
+char(o,41334).
+char(p,41335).
+char(2,41336).
+char(9,41337).
+char(6,41338).
+char(9,41339).
+char(m,41340).
+char(4,41341).
+char(6,41342).
+char(2,41343).
+char(8,41344).
+char(p,41345).
+char(7,41346).
+char(9,41347).
+char(7,41348).
+char(c,41349).
+char(c,41350).
+char(m,41351).
+char(1,41352).
+char(9,41353).
+char(7,41354).
+char(9,41355).
+char(c,41356).
+char(p,41357).
+char(9,41358).
+char(4,41359).
+char(7,41360).
+char(c,41361).
+char(p,41362).
+char(6,41363).
+char(3,41364).
+char(9,41365).
+char(2,41366).
+char(c,41367).
+char(c,41368).
+char(p,41369).
+char(7,41370).
+char(5,41371).
+char(9,41372).
+char(9,41373).
+char(c,41374).
+char(p,41375).
+char(7,41376).
+char(5,41377).
+char(0,41378).
+char(0,41379).
+char(m,41380).
+char(8,41381).
+char(0,41382).
+char(5,41383).
+char(1,41384).
+char(c,41385).
+char(c,41386).
+char(c,41387).
+char(c,41388).
+char(m,41389).
+char(1,41390).
+char(2,41391).
+char(2,41392).
+char(1,41393).
+char(c,41394).
+char(c,41395).
+char(m,41396).
+char(o,41397).
+char(p,41398).
+char(o,41399).
+char(m,41400).
+char(o,41401).
+char(p,41402).
+char(8,41403).
+char(2,41404).
+char(0,41405).
+char(9,41406).
+char(c,41407).
+char(c,41408).
+char(c,41409).
+char(c,41410).
+char(m,41411).
+char(o,41412).
+char(o,41413).
+char(m,41414).
+char(o,41415).
+char(p,41416).
+char(9,41417).
+char(1,41418).
+char(9,41419).
+char(3,41420).
+char(m,41421).
+char(5,41422).
+char(8,41423).
+char(8,41424).
+char(8,41425).
+char(m,41426).
+char(4,41427).
+char(0,41428).
+char(6,41429).
+char(5,41430).
+char(p,41431).
+char(8,41432).
+char(0,41433).
+char(8,41434).
+char(9,41435).
+char(c,41436).
+char(m,41437).
+char(o,41438).
+char(p,41439).
+char(5,41440).
+char(5,41441).
+char(5,41442).
+char(6,41443).
+char(p,41444).
+char(8,41445).
+char(7,41446).
+char(2,41447).
+char(8,41448).
+char(c,41449).
+char(c,41450).
+char(m,41451).
+char(o,41452).
+char(o,41453).
+char(m,41454).
+char(o,41455).
+char(1,41456).
+char(1,41457).
+char(1,41458).
+char(0,41459).
+char(c,41460).
+char(p,41461).
+char(5,41462).
+char(5,41463).
+char(2,41464).
+char(0,41465).
+char(m,41466).
+char(o,41467).
+char(m,41468).
+char(5,41469).
+char(9,41470).
+char(9,41471).
+char(6,41472).
+char(c,41473).
+char(p,41474).
+char(o,41475).
+char(7,41476).
+char(7,41477).
+char(7,41478).
+char(5,41479).
+char(p,41480).
+char(o,41481).
+char(p,41482).
+char(1,41483).
+char(7,41484).
+char(3,41485).
+char(c,41486).
+char(c,41487).
+char(p,41488).
+char(8,41489).
+char(9,41490).
+char(8,41491).
+char(4,41492).
+char(m,41493).
+char(o,41494).
+char(m,41495).
+char(1,41496).
+char(7,41497).
+char(4,41498).
+char(2,41499).
+char(m,41500).
+char(4,41501).
+char(6,41502).
+char(2,41503).
+char(p,41504).
+char(1,41505).
+char(8,41506).
+char(7,41507).
+char(9,41508).
+char(m,41509).
+char(1,41510).
+char(3,41511).
+char(9,41512).
+char(1,41513).
+char(p,41514).
+char(4,41515).
+char(5,41516).
+char(4,41517).
+char(8,41518).
+char(m,41519).
+char(8,41520).
+char(4,41521).
+char(2,41522).
+char(c,41523).
+char(c,41524).
+char(p,41525).
+char(8,41526).
+char(2,41527).
+char(3,41528).
+char(5,41529).
+char(c,41530).
+char(c,41531).
+char(m,41532).
+char(o,41533).
+char(o,41534).
+char(m,41535).
+char(o,41536).
+char(m,41537).
+char(o,41538).
+char(p,41539).
+char(1,41540).
+char(3,41541).
+char(1,41542).
+char(2,41543).
+char(m,41544).
+char(2,41545).
+char(1,41546).
+char(0,41547).
+char(5,41548).
+char(c,41549).
+char(p,41550).
+char(o,41551).
+char(m,41552).
+char(o,41553).
+char(o,41554).
+char(m,41555).
+char(o,41556).
+char(o,41557).
+char(p,41558).
+char(o,41559).
+char(o,41560).
+char(m,41561).
+char(o,41562).
+char(p,41563).
+char(o,41564).
+char(p,41565).
+char(6,41566).
+char(9,41567).
+char(0,41568).
+char(7,41569).
+char(p,41570).
+char(o,41571).
+char(m,41572).
+char(6,41573).
+char(8,41574).
+char(5,41575).
+char(5,41576).
+char(c,41577).
+char(c,41578).
+char(c,41579).
+char(m,41580).
+char(o,41581).
+char(m,41582).
+char(4,41583).
+char(9,41584).
+char(9,41585).
+char(3,41586).
+char(m,41587).
+char(o,41588).
+char(m,41589).
+char(o,41590).
+char(m,41591).
+char(7,41592).
+char(4,41593).
+char(2,41594).
+char(1,41595).
+char(m,41596).
+char(2,41597).
+char(6,41598).
+char(3,41599).
+char(9,41600).
+char(c,41601).
+char(m,41602).
+char(o,41603).
+char(o,41604).
+char(m,41605).
+char(7,41606).
+char(1,41607).
+char(1,41608).
+char(7,41609).
+char(p,41610).
+char(o,41611).
+char(p,41612).
+char(1,41613).
+char(0,41614).
+char(2,41615).
+char(4,41616).
+char(c,41617).
+char(p,41618).
+char(o,41619).
+char(m,41620).
+char(o,41621).
+char(m,41622).
+char(4,41623).
+char(0,41624).
+char(2,41625).
+char(c,41626).
+char(p,41627).
+char(o,41628).
+char(m,41629).
+char(8,41630).
+char(5,41631).
+char(0,41632).
+char(8,41633).
+char(p,41634).
+char(8,41635).
+char(6,41636).
+char(6,41637).
+char(7,41638).
+char(c,41639).
+char(c,41640).
+char(p,41641).
+char(o,41642).
+char(p,41643).
+char(4,41644).
+char(1,41645).
+char(5,41646).
+char(8,41647).
+char(c,41648).
+char(c,41649).
+char(c,41650).
+char(c,41651).
+char(p,41652).
+char(o,41653).
+char(p,41654).
+char(7,41655).
+char(3,41656).
+char(8,41657).
+char(3,41658).
+char(c,41659).
+char(p,41660).
+char(8,41661).
+char(9,41662).
+char(8,41663).
+char(2,41664).
+char(c,41665).
+char(c,41666).
+char(p,41667).
+char(3,41668).
+char(5,41669).
+char(0,41670).
+char(9,41671).
+char(c,41672).
+char(m,41673).
+char(o,41674).
+char(p,41675).
+char(o,41676).
+char(4,41677).
+char(5,41678).
+char(7,41679).
+char(5,41680).
+char(c,41681).
+char(m,41682).
+char(o,41683).
+char(o,41684).
+char(p,41685).
+char(o,41686).
+char(p,41687).
+char(o,41688).
+char(m,41689).
+char(o,41690).
+char(p,41691).
+char(o,41692).
+char(p,41693).
+char(o,41694).
+char(8,41695).
+char(4,41696).
+char(5,41697).
+char(0,41698).
+char(p,41699).
+char(7,41700).
+char(2,41701).
+char(2,41702).
+char(2,41703).
+char(m,41704).
+char(o,41705).
+char(o,41706).
+char(o,41707).
+char(p,41708).
+char(6,41709).
+char(6,41710).
+char(5,41711).
+char(9,41712).
+char(c,41713).
+char(p,41714).
+char(o,41715).
+char(1,41716).
+char(7,41717).
+char(8,41718).
+char(7,41719).
+char(m,41720).
+char(4,41721).
+char(6,41722).
+char(1,41723).
+char(0,41724).
+char(m,41725).
+char(o,41726).
+char(m,41727).
+char(6,41728).
+char(4,41729).
+char(8,41730).
+char(5,41731).
+char(c,41732).
+char(p,41733).
+char(4,41734).
+char(5,41735).
+char(9,41736).
+char(5,41737).
+char(c,41738).
+char(c,41739).
+char(p,41740).
+char(4,41741).
+char(9,41742).
+char(1,41743).
+char(0,41744).
+char(c,41745).
+char(m,41746).
+char(2,41747).
+char(0,41748).
+char(9,41749).
+char(0,41750).
+char(m,41751).
+char(o,41752).
+char(p,41753).
+char(o,41754).
+char(m,41755).
+char(8,41756).
+char(7,41757).
+char(4,41758).
+char(2,41759).
+char(m,41760).
+char(o,41761).
+char(9,41762).
+char(1,41763).
+char(6,41764).
+char(8,41765).
+char(p,41766).
+char(7,41767).
+char(1,41768).
+char(6,41769).
+char(0,41770).
+char(m,41771).
+char(9,41772).
+char(8,41773).
+char(1,41774).
+char(8,41775).
+char(m,41776).
+char(1,41777).
+char(7,41778).
+char(1,41779).
+char(9,41780).
+char(c,41781).
+char(c,41782).
+char(p,41783).
+char(o,41784).
+char(m,41785).
+char(8,41786).
+char(8,41787).
+char(4,41788).
+char(4,41789).
+char(m,41790).
+char(o,41791).
+char(o,41792).
+char(p,41793).
+char(o,41794).
+char(m,41795).
+char(o,41796).
+char(4,41797).
+char(4,41798).
+char(9,41799).
+char(1,41800).
+char(c,41801).
+char(p,41802).
+char(o,41803).
+char(o,41804).
+char(p,41805).
+char(o,41806).
+char(p,41807).
+char(o,41808).
+char(m,41809).
+char(9,41810).
+char(3,41811).
+char(2,41812).
+char(0,41813).
+char(c,41814).
+char(m,41815).
+char(1,41816).
+char(2,41817).
+char(1,41818).
+char(4,41819).
+char(m,41820).
+char(9,41821).
+char(0,41822).
+char(1,41823).
+char(2,41824).
+char(c,41825).
+char(p,41826).
+char(o,41827).
+char(p,41828).
+char(o,41829).
+char(m,41830).
+char(o,41831).
+char(p,41832).
+char(1,41833).
+char(6,41834).
+char(9,41835).
+char(8,41836).
+char(c,41837).
+char(m,41838).
+char(o,41839).
+char(p,41840).
+char(2,41841).
+char(5,41842).
+char(4,41843).
+char(2,41844).
+char(c,41845).
+char(p,41846).
+char(1,41847).
+char(1,41848).
+char(6,41849).
+char(4,41850).
+char(m,41851).
+char(o,41852).
+char(m,41853).
+char(1,41854).
+char(6,41855).
+char(3,41856).
+char(9,41857).
+char(c,41858).
+char(m,41859).
+char(6,41860).
+char(1,41861).
+char(7,41862).
+char(5,41863).
+char(p,41864).
+char(o,41865).
+char(m,41866).
+char(7,41867).
+char(7,41868).
+char(8,41869).
+char(0,41870).
+char(m,41871).
+char(o,41872).
+char(o,41873).
+char(p,41874).
+char(o,41875).
+char(m,41876).
+char(o,41877).
+char(m,41878).
+char(5,41879).
+char(4,41880).
+char(8,41881).
+char(5,41882).
+char(p,41883).
+char(o,41884).
+char(o,41885).
+char(m,41886).
+char(o,41887).
+char(m,41888).
+char(8,41889).
+char(1,41890).
+char(8,41891).
+char(m,41892).
+char(2,41893).
+char(2,41894).
+char(7,41895).
+char(3,41896).
+char(p,41897).
+char(o,41898).
+char(p,41899).
+char(o,41900).
+char(m,41901).
+char(1,41902).
+char(3,41903).
+char(4,41904).
+char(2,41905).
+char(c,41906).
+char(c,41907).
+char(c,41908).
+char(c,41909).
+char(c,41910).
+char(m,41911).
+char(o,41912).
+char(1,41913).
+char(5,41914).
+char(0,41915).
+char(5,41916).
+char(c,41917).
+char(c,41918).
+char(m,41919).
+char(o,41920).
+char(m,41921).
+char(8,41922).
+char(2,41923).
+char(8,41924).
+char(2,41925).
+char(c,41926).
+char(m,41927).
+char(5,41928).
+char(6,41929).
+char(5,41930).
+char(9,41931).
+char(c,41932).
+char(c,41933).
+char(m,41934).
+char(o,41935).
+char(p,41936).
+char(3,41937).
+char(5,41938).
+char(7,41939).
+char(1,41940).
+char(c,41941).
+char(c,41942).
+char(p,41943).
+char(o,41944).
+char(3,41945).
+char(8,41946).
+char(6,41947).
+char(6,41948).
+char(m,41949).
+char(o,41950).
+char(4,41951).
+char(0,41952).
+char(2,41953).
+char(3,41954).
+char(p,41955).
+char(o,41956).
+char(o,41957).
+char(m,41958).
+char(o,41959).
+char(p,41960).
+char(o,41961).
+char(p,41962).
+char(o,41963).
+char(m,41964).
+char(1,41965).
+char(9,41966).
+char(8,41967).
+char(9,41968).
+char(c,41969).
+char(m,41970).
+char(8,41971).
+char(6,41972).
+char(6,41973).
+char(3,41974).
+char(m,41975).
+char(o,41976).
+char(o,41977).
+char(7,41978).
+char(1,41979).
+char(3,41980).
+char(9,41981).
+char(c,41982).
+char(c,41983).
+char(m,41984).
+char(o,41985).
+char(p,41986).
+char(o,41987).
+char(6,41988).
+char(2,41989).
+char(0,41990).
+char(8,41991).
+char(c,41992).
+char(c,41993).
+char(m,41994).
+char(o,41995).
+char(p,41996).
+char(o,41997).
+char(m,41998).
+char(4,41999).
+char(1,42000).
+char(2,42001).
+char(1,42002).
+char(c,42003).
+char(m,42004).
+char(o,42005).
+char(4,42006).
+char(5,42007).
+char(0,42008).
+char(6,42009).
+char(c,42010).
+char(p,42011).
+char(4,42012).
+char(3,42013).
+char(3,42014).
+char(5,42015).
+char(m,42016).
+char(o,42017).
+char(2,42018).
+char(4,42019).
+char(2,42020).
+char(1,42021).
+char(p,42022).
+char(6,42023).
+char(7,42024).
+char(4,42025).
+char(3,42026).
+char(c,42027).
+char(m,42028).
+char(7,42029).
+char(3,42030).
+char(3,42031).
+char(1,42032).
+char(c,42033).
+char(p,42034).
+char(5,42035).
+char(8,42036).
+char(5,42037).
+char(7,42038).
+char(m,42039).
+char(4,42040).
+char(0,42041).
+char(5,42042).
+char(m,42043).
+char(o,42044).
+char(1,42045).
+char(8,42046).
+char(8,42047).
+char(7,42048).
+char(m,42049).
+char(o,42050).
+char(o,42051).
+char(o,42052).
+char(m,42053).
+char(o,42054).
+char(m,42055).
+char(2,42056).
+char(2,42057).
+char(7,42058).
+char(7,42059).
+char(c,42060).
+char(m,42061).
+char(1,42062).
+char(3,42063).
+char(2,42064).
+char(0,42065).
+char(p,42066).
+char(6,42067).
+char(0,42068).
+char(9,42069).
+char(8,42070).
+char(c,42071).
+char(m,42072).
+char(o,42073).
+char(m,42074).
+char(9,42075).
+char(5,42076).
+char(3,42077).
+char(9,42078).
+char(c,42079).
+char(c,42080).
+char(c,42081).
+char(p,42082).
+char(o,42083).
+char(m,42084).
+char(7,42085).
+char(9,42086).
+char(5,42087).
+char(p,42088).
+char(o,42089).
+char(p,42090).
+char(o,42091).
+char(m,42092).
+char(8,42093).
+char(9,42094).
+char(8,42095).
+char(1,42096).
+char(p,42097).
+char(o,42098).
+char(o,42099).
+char(p,42100).
+char(o,42101).
+char(p,42102).
+char(o,42103).
+char(p,42104).
+char(o,42105).
+char(p,42106).
+char(o,42107).
+char(8,42108).
+char(4,42109).
+char(4,42110).
+char(1,42111).
+char(c,42112).
+char(m,42113).
+char(1,42114).
+char(1,42115).
+char(5,42116).
+char(7,42117).
+char(c,42118).
+char(p,42119).
+char(9,42120).
+char(2,42121).
+char(3,42122).
+char(4,42123).
+char(p,42124).
+char(o,42125).
+char(2,42126).
+char(2,42127).
+char(4,42128).
+char(5,42129).
+char(m,42130).
+char(o,42131).
+char(m,42132).
+char(3,42133).
+char(7,42134).
+char(8,42135).
+char(8,42136).
+char(c,42137).
+char(m,42138).
+char(o,42139).
+char(p,42140).
+char(6,42141).
+char(5,42142).
+char(8,42143).
+char(6,42144).
+char(c,42145).
+char(c,42146).
+char(c,42147).
+char(p,42148).
+char(o,42149).
+char(p,42150).
+char(o,42151).
+char(o,42152).
+char(o,42153).
+char(m,42154).
+char(2,42155).
+char(9,42156).
+char(7,42157).
+char(7,42158).
+char(m,42159).
+char(o,42160).
+char(o,42161).
+char(m,42162).
+char(o,42163).
+char(3,42164).
+char(1,42165).
+char(0,42166).
+char(5,42167).
+char(c,42168).
+char(c,42169).
+char(c,42170).
+char(c,42171).
+char(c,42172).
+char(c,42173).
+char(c,42174).
+char(c,42175).
+char(c,42176).
+char(c,42177).
+char(c,42178).
+char(c,42179).
+char(c,42180).
+char(p,42181).
+char(o,42182).
+char(o,42183).
+char(p,42184).
+char(o,42185).
+char(m,42186).
+char(o,42187).
+char(p,42188).
+char(o,42189).
+char(p,42190).
+char(o,42191).
+char(m,42192).
+char(o,42193).
+char(m,42194).
+char(1,42195).
+char(3,42196).
+char(9,42197).
+char(5,42198).
+char(p,42199).
+char(o,42200).
+char(m,42201).
+char(o,42202).
+char(m,42203).
+char(7,42204).
+char(3,42205).
+char(7,42206).
+char(2,42207).
+char(p,42208).
+char(o,42209).
+char(p,42210).
+char(o,42211).
+char(4,42212).
+char(7,42213).
+char(3,42214).
+char(2,42215).
+char(c,42216).
+char(c,42217).
+char(m,42218).
+char(7,42219).
+char(0,42220).
+char(8,42221).
+char(0,42222).
+char(m,42223).
+char(4,42224).
+char(8,42225).
+char(5,42226).
+char(9,42227).
+char(c,42228).
+char(c,42229).
+char(m,42230).
+char(o,42231).
+char(p,42232).
+char(3,42233).
+char(4,42234).
+char(0,42235).
+char(c,42236).
+char(m,42237).
+char(o,42238).
+char(2,42239).
+char(3,42240).
+char(0,42241).
+char(6,42242).
+char(m,42243).
+char(6,42244).
+char(5,42245).
+char(5,42246).
+char(6,42247).
+char(c,42248).
+char(c,42249).
+char(m,42250).
+char(8,42251).
+char(2,42252).
+char(3,42253).
+char(9,42254).
+char(c,42255).
+char(p,42256).
+char(4,42257).
+char(0,42258).
+char(8,42259).
+char(8,42260).
+char(m,42261).
+char(4,42262).
+char(0,42263).
+char(5,42264).
+char(2,42265).
+char(m,42266).
+char(2,42267).
+char(4,42268).
+char(9,42269).
+char(9,42270).
+char(p,42271).
+char(o,42272).
+char(5,42273).
+char(8,42274).
+char(3,42275).
+char(6,42276).
+char(m,42277).
+char(o,42278).
+char(1,42279).
+char(5,42280).
+char(6,42281).
+char(m,42282).
+char(o,42283).
+char(p,42284).
+char(1,42285).
+char(9,42286).
+char(0,42287).
+char(3,42288).
+char(c,42289).
+char(m,42290).
+char(o,42291).
+char(p,42292).
+char(8,42293).
+char(2,42294).
+char(8,42295).
+char(7,42296).
+char(p,42297).
+char(9,42298).
+char(1,42299).
+char(c,42300).
+char(c,42301).
+char(p,42302).
+char(o,42303).
+char(p,42304).
+char(o,42305).
+char(o,42306).
+char(m,42307).
+char(5,42308).
+char(4,42309).
+char(9,42310).
+char(1,42311).
+char(m,42312).
+char(1,42313).
+char(6,42314).
+char(2,42315).
+char(8,42316).
+char(c,42317).
+char(p,42318).
+char(o,42319).
+char(m,42320).
+char(4,42321).
+char(1,42322).
+char(9,42323).
+char(p,42324).
+char(o,42325).
+char(m,42326).
+char(8,42327).
+char(2,42328).
+char(3,42329).
+char(5,42330).
+char(c,42331).
+char(c,42332).
+char(m,42333).
+char(o,42334).
+char(m,42335).
+char(6,42336).
+char(1,42337).
+char(4,42338).
+char(8,42339).
+char(p,42340).
+char(o,42341).
+char(3,42342).
+char(8,42343).
+char(0,42344).
+char(2,42345).
+char(c,42346).
+char(c,42347).
+char(m,42348).
+char(o,42349).
+char(9,42350).
+char(1,42351).
+char(2,42352).
+char(5,42353).
+char(c,42354).
+char(c,42355).
+char(m,42356).
+char(o,42357).
+char(m,42358).
+char(8,42359).
+char(4,42360).
+char(1,42361).
+char(2,42362).
+char(c,42363).
+char(m,42364).
+char(4,42365).
+char(4,42366).
+char(1,42367).
+char(4,42368).
+char(c,42369).
+char(c,42370).
+char(m,42371).
+char(o,42372).
+char(7,42373).
+char(5,42374).
+char(8,42375).
+char(0,42376).
+char(c,42377).
+char(c,42378).
+char(m,42379).
+char(6,42380).
+char(7,42381).
+char(5,42382).
+char(4,42383).
+char(c,42384).
+char(c,42385).
+char(m,42386).
+char(3,42387).
+char(4,42388).
+char(2,42389).
+char(c,42390).
+char(p,42391).
+char(o,42392).
+char(o,42393).
+char(m,42394).
+char(o,42395).
+char(p,42396).
+char(8,42397).
+char(8,42398).
+char(0,42399).
+char(1,42400).
+char(p,42401).
+char(o,42402).
+char(p,42403).
+char(o,42404).
+char(o,42405).
+char(p,42406).
+char(3,42407).
+char(6,42408).
+char(8,42409).
+char(1,42410).
+char(c,42411).
+char(p,42412).
+char(8,42413).
+char(0,42414).
+char(2,42415).
+char(4,42416).
+char(c,42417).
+char(p,42418).
+char(o,42419).
+char(p,42420).
+char(3,42421).
+char(0,42422).
+char(5,42423).
+char(5,42424).
+char(p,42425).
+char(5,42426).
+char(9,42427).
+char(3,42428).
+char(1,42429).
+char(m,42430).
+char(o,42431).
+char(o,42432).
+char(6,42433).
+char(6,42434).
+char(2,42435).
+char(2,42436).
+char(m,42437).
+char(1,42438).
+char(8,42439).
+char(7,42440).
+char(8,42441).
+char(m,42442).
+char(o,42443).
+char(4,42444).
+char(9,42445).
+char(7,42446).
+char(3,42447).
+char(p,42448).
+char(3,42449).
+char(2,42450).
+char(1,42451).
+char(0,42452).
+char(m,42453).
+char(6,42454).
+char(8,42455).
+char(9,42456).
+char(4,42457).
+char(c,42458).
+char(m,42459).
+char(7,42460).
+char(5,42461).
+char(p,42462).
+char(o,42463).
+char(o,42464).
+char(p,42465).
+char(o,42466).
+char(p,42467).
+char(o,42468).
+char(m,42469).
+char(5,42470).
+char(1,42471).
+char(p,42472).
+char(9,42473).
+char(8,42474).
+char(2,42475).
+char(3,42476).
+char(c,42477).
+char(c,42478).
+char(p,42479).
+char(o,42480).
+char(m,42481).
+char(3,42482).
+char(8,42483).
+char(1,42484).
+char(9,42485).
+char(p,42486).
+char(4,42487).
+char(5,42488).
+char(3,42489).
+char(m,42490).
+char(o,42491).
+char(o,42492).
+char(3,42493).
+char(1,42494).
+char(7,42495).
+char(1,42496).
+char(c,42497).
+char(p,42498).
+char(1,42499).
+char(3,42500).
+char(8,42501).
+char(0,42502).
+char(c,42503).
+char(p,42504).
+char(8,42505).
+char(7,42506).
+char(5,42507).
+char(4,42508).
+char(m,42509).
+char(o,42510).
+char(o,42511).
+char(o,42512).
+char(m,42513).
+char(o,42514).
+char(p,42515).
+char(9,42516).
+char(3,42517).
+char(5,42518).
+char(c,42519).
+char(p,42520).
+char(o,42521).
+char(m,42522).
+char(o,42523).
+char(p,42524).
+char(3,42525).
+char(6,42526).
+char(5,42527).
+char(2,42528).
+char(c,42529).
+char(c,42530).
+char(c,42531).
+char(c,42532).
+char(c,42533).
+char(c,42534).
+char(c,42535).
+char(m,42536).
+char(o,42537).
+char(m,42538).
+char(o,42539).
+char(m,42540).
+char(o,42541).
+char(m,42542).
+char(o,42543).
+char(p,42544).
+char(o,42545).
+char(p,42546).
+char(o,42547).
+char(m,42548).
+char(o,42549).
+char(m,42550).
+char(o,42551).
+char(o,42552).
+char(m,42553).
+char(3,42554).
+char(6,42555).
+char(2,42556).
+char(1,42557).
+char(p,42558).
+char(o,42559).
+char(p,42560).
+char(7,42561).
+char(9,42562).
+char(8,42563).
+char(5,42564).
+char(c,42565).
+char(m,42566).
+char(4,42567).
+char(0,42568).
+char(2,42569).
+char(1,42570).
+char(m,42571).
+char(o,42572).
+char(o,42573).
+char(p,42574).
+char(o,42575).
+char(p,42576).
+char(o,42577).
+char(p,42578).
+char(4,42579).
+char(8,42580).
+char(9,42581).
+char(1,42582).
+char(c,42583).
+char(c,42584).
+char(m,42585).
+char(o,42586).
+char(m,42587).
+char(o,42588).
+char(p,42589).
+char(8,42590).
+char(4,42591).
+char(7,42592).
+char(2,42593).
+char(c,42594).
+char(c,42595).
+char(c,42596).
+char(c,42597).
+char(c,42598).
+char(c,42599).
+char(c,42600).
+char(c,42601).
+char(c,42602).
+char(m,42603).
+char(o,42604).
+char(4,42605).
+char(7,42606).
+char(8,42607).
+char(7,42608).
+char(m,42609).
+char(o,42610).
+char(m,42611).
+char(8,42612).
+char(1,42613).
+char(4,42614).
+char(8,42615).
+char(c,42616).
+char(c,42617).
+char(p,42618).
+char(o,42619).
+char(p,42620).
+char(o,42621).
+char(9,42622).
+char(5,42623).
+char(9,42624).
+char(1,42625).
+char(p,42626).
+char(o,42627).
+char(p,42628).
+char(o,42629).
+char(m,42630).
+char(o,42631).
+char(m,42632).
+char(4,42633).
+char(3,42634).
+char(7,42635).
+char(1,42636).
+char(c,42637).
+char(p,42638).
+char(o,42639).
+char(p,42640).
+char(1,42641).
+char(4,42642).
+char(9,42643).
+char(2,42644).
+char(c,42645).
+char(m,42646).
+char(4,42647).
+char(8,42648).
+char(1,42649).
+char(4,42650).
+char(m,42651).
+char(o,42652).
+char(4,42653).
+char(3,42654).
+char(5,42655).
+char(5,42656).
+char(c,42657).
+char(c,42658).
+char(m,42659).
+char(o,42660).
+char(o,42661).
+char(1,42662).
+char(7,42663).
+char(7,42664).
+char(7,42665).
+char(p,42666).
+char(6,42667).
+char(3,42668).
+char(5,42669).
+char(5,42670).
+char(p,42671).
+char(o,42672).
+char(m,42673).
+char(o,42674).
+char(p,42675).
+char(o,42676).
+char(5,42677).
+char(8,42678).
+char(7,42679).
+char(8,42680).
+char(c,42681).
+char(m,42682).
+char(o,42683).
+char(p,42684).
+char(6,42685).
+char(6,42686).
+char(6,42687).
+char(0,42688).
+char(c,42689).
+char(m,42690).
+char(6,42691).
+char(0,42692).
+char(7,42693).
+char(0,42694).
+char(m,42695).
+char(5,42696).
+char(5,42697).
+char(8,42698).
+char(2,42699).
+char(c,42700).
+char(p,42701).
+char(o,42702).
+char(o,42703).
+char(m,42704).
+char(o,42705).
+char(p,42706).
+char(2,42707).
+char(2,42708).
+char(8,42709).
+char(3,42710).
+char(m,42711).
+char(8,42712).
+char(2,42713).
+char(2,42714).
+char(5,42715).
+char(c,42716).
+char(m,42717).
+char(5,42718).
+char(5,42719).
+char(4,42720).
+char(1,42721).
+char(p,42722).
+char(o,42723).
+char(p,42724).
+char(o,42725).
+char(o,42726).
+char(p,42727).
+char(o,42728).
+char(m,42729).
+char(o,42730).
+char(p,42731).
+char(7,42732).
+char(9,42733).
+char(6,42734).
+char(0,42735).
+char(c,42736).
+char(p,42737).
+char(o,42738).
+char(m,42739).
+char(o,42740).
+char(2,42741).
+char(0,42742).
+char(5,42743).
+char(p,42744).
+char(4,42745).
+char(0,42746).
+char(5,42747).
+char(2,42748).
+char(c,42749).
+char(c,42750).
+char(c,42751).
+char(p,42752).
+char(o,42753).
+char(o,42754).
+char(m,42755).
+char(3,42756).
+char(6,42757).
+char(3,42758).
+char(7,42759).
+char(m,42760).
+char(5,42761).
+char(3,42762).
+char(5,42763).
+char(0,42764).
+char(c,42765).
+char(c,42766).
+char(m,42767).
+char(o,42768).
+char(p,42769).
+char(6,42770).
+char(9,42771).
+char(1,42772).
+char(1,42773).
+char(p,42774).
+char(7,42775).
+char(5,42776).
+char(0,42777).
+char(3,42778).
+char(p,42779).
+char(o,42780).
+char(m,42781).
+char(9,42782).
+char(3,42783).
+char(0,42784).
+char(0,42785).
+char(p,42786).
+char(9,42787).
+char(6,42788).
+char(3,42789).
+char(1,42790).
+char(m,42791).
+char(6,42792).
+char(4,42793).
+char(9,42794).
+char(2,42795).
+char(m,42796).
+char(o,42797).
+char(m,42798).
+char(2,42799).
+char(4,42800).
+char(1,42801).
+char(1,42802).
+char(c,42803).
+char(m,42804).
+char(3,42805).
+char(0,42806).
+char(8,42807).
+char(5,42808).
+char(p,42809).
+char(8,42810).
+char(2,42811).
+char(5,42812).
+char(7,42813).
+char(c,42814).
+char(p,42815).
+char(4,42816).
+char(5,42817).
+char(6,42818).
+char(5,42819).
+char(p,42820).
+char(6,42821).
+char(3,42822).
+char(2,42823).
+char(7,42824).
+char(p,42825).
+char(o,42826).
+char(5,42827).
+char(7,42828).
+char(5,42829).
+char(0,42830).
+char(c,42831).
+char(c,42832).
+char(c,42833).
+char(c,42834).
+char(c,42835).
+char(c,42836).
+char(m,42837).
+char(4,42838).
+char(1,42839).
+char(3,42840).
+char(1,42841).
+char(c,42842).
+char(p,42843).
+char(o,42844).
+char(o,42845).
+char(o,42846).
+char(p,42847).
+char(8,42848).
+char(2,42849).
+char(7,42850).
+char(7,42851).
+char(c,42852).
+char(p,42853).
+char(o,42854).
+char(p,42855).
+char(3,42856).
+char(0,42857).
+char(1,42858).
+char(6,42859).
+char(c,42860).
+char(p,42861).
+char(o,42862).
+char(p,42863).
+char(o,42864).
+char(p,42865).
+char(o,42866).
+char(m,42867).
+char(o,42868).
+char(o,42869).
+char(m,42870).
+char(o,42871).
+char(p,42872).
+char(3,42873).
+char(0,42874).
+char(2,42875).
+char(8,42876).
+char(c,42877).
+char(m,42878).
+char(o,42879).
+char(o,42880).
+char(m,42881).
+char(6,42882).
+char(3,42883).
+char(1,42884).
+char(c,42885).
+char(p,42886).
+char(8,42887).
+char(4,42888).
+char(7,42889).
+char(7,42890).
+char(c,42891).
+char(c,42892).
+char(p,42893).
+char(4,42894).
+char(9,42895).
+char(8,42896).
+char(9,42897).
+char(m,42898).
+char(o,42899).
+char(m,42900).
+char(o,42901).
+char(p,42902).
+char(6,42903).
+char(9,42904).
+char(9,42905).
+char(1,42906).
+char(c,42907).
+char(c,42908).
+char(m,42909).
+char(o,42910).
+char(p,42911).
+char(o,42912).
+char(6,42913).
+char(2,42914).
+char(0,42915).
+char(p,42916).
+char(4,42917).
+char(2,42918).
+char(9,42919).
+char(7,42920).
+char(c,42921).
+char(m,42922).
+char(o,42923).
+char(m,42924).
+char(o,42925).
+char(m,42926).
+char(o,42927).
+char(m,42928).
+char(o,42929).
+char(9,42930).
+char(4,42931).
+char(1,42932).
+char(8,42933).
+char(c,42934).
+char(p,42935).
+char(6,42936).
+char(1,42937).
+char(0,42938).
+char(5,42939).
+char(p,42940).
+char(o,42941).
+char(p,42942).
+char(5,42943).
+char(1,42944).
+char(1,42945).
+char(0,42946).
+char(c,42947).
+char(c,42948).
+char(c,42949).
+char(p,42950).
+char(7,42951).
+char(5,42952).
+char(4,42953).
+char(5,42954).
+char(c,42955).
+char(m,42956).
+char(6,42957).
+char(2,42958).
+char(9,42959).
+char(2,42960).
+char(c,42961).
+char(c,42962).
+char(c,42963).
+char(p,42964).
+char(o,42965).
+char(6,42966).
+char(1,42967).
+char(8,42968).
+char(0,42969).
+char(c,42970).
+char(p,42971).
+char(8,42972).
+char(4,42973).
+char(1,42974).
+char(8,42975).
+char(c,42976).
+char(c,42977).
+char(m,42978).
+char(8,42979).
+char(7,42980).
+char(6,42981).
+char(7,42982).
+char(c,42983).
+char(p,42984).
+char(5,42985).
+char(7,42986).
+char(c,42987).
+char(c,42988).
+char(c,42989).
+char(c,42990).
+char(c,42991).
+char(c,42992).
+char(c,42993).
+char(p,42994).
+char(6,42995).
+char(1,42996).
+char(2,42997).
+char(6,42998).
+char(m,42999).
+char(8,43000).
+char(6,43001).
+char(9,43002).
+char(1,43003).
+char(c,43004).
+char(p,43005).
+char(9,43006).
+char(7,43007).
+char(2,43008).
+char(m,43009).
+char(1,43010).
+char(2,43011).
+char(4,43012).
+char(8,43013).
+char(c,43014).
+char(c,43015).
+char(m,43016).
+char(o,43017).
+char(m,43018).
+char(o,43019).
+char(m,43020).
+char(7,43021).
+char(0,43022).
+char(7,43023).
+char(6,43024).
+char(c,43025).
+char(p,43026).
+char(3,43027).
+char(5,43028).
+char(9,43029).
+char(3,43030).
+char(c,43031).
+char(c,43032).
+char(c,43033).
+char(c,43034).
+char(p,43035).
+char(4,43036).
+char(0,43037).
+char(5,43038).
+char(1,43039).
+char(m,43040).
+char(o,43041).
+char(p,43042).
+char(8,43043).
+char(1,43044).
+char(4,43045).
+char(1,43046).
+char(c,43047).
+char(c,43048).
+char(c,43049).
+char(m,43050).
+char(3,43051).
+char(9,43052).
+char(1,43053).
+char(7,43054).
+char(c,43055).
+char(p,43056).
+char(8,43057).
+char(1,43058).
+char(3,43059).
+char(7,43060).
+char(c,43061).
+char(p,43062).
+char(o,43063).
+char(o,43064).
+char(p,43065).
+char(7,43066).
+char(5,43067).
+char(5,43068).
+char(7,43069).
+char(m,43070).
+char(4,43071).
+char(8,43072).
+char(4,43073).
+char(m,43074).
+char(o,43075).
+char(o,43076).
+char(2,43077).
+char(7,43078).
+char(1,43079).
+char(5,43080).
+char(c,43081).
+char(m,43082).
+char(8,43083).
+char(8,43084).
+char(2,43085).
+char(7,43086).
+char(m,43087).
+char(o,43088).
+char(p,43089).
+char(7,43090).
+char(9,43091).
+char(4,43092).
+char(2,43093).
+char(c,43094).
+char(m,43095).
+char(3,43096).
+char(9,43097).
+char(6,43098).
+char(0,43099).
+char(m,43100).
+char(1,43101).
+char(5,43102).
+char(3,43103).
+char(9,43104).
+char(m,43105).
+char(4,43106).
+char(7,43107).
+char(5,43108).
+char(4,43109).
+char(c,43110).
+char(c,43111).
+char(c,43112).
+char(m,43113).
+char(o,43114).
+char(p,43115).
+char(o,43116).
+char(m,43117).
+char(1,43118).
+char(7,43119).
+char(7,43120).
+char(c,43121).
+char(p,43122).
+char(6,43123).
+char(6,43124).
+char(8,43125).
+char(8,43126).
+char(p,43127).
+char(4,43128).
+char(1,43129).
+char(1,43130).
+char(4,43131).
+char(c,43132).
+char(p,43133).
+char(6,43134).
+char(0,43135).
+char(9,43136).
+char(9,43137).
+char(m,43138).
+char(o,43139).
+char(m,43140).
+char(1,43141).
+char(7,43142).
+char(3,43143).
+char(2,43144).
+char(p,43145).
+char(5,43146).
+char(4,43147).
+char(1,43148).
+char(c,43149).
+char(c,43150).
+char(m,43151).
+char(o,43152).
+char(o,43153).
+char(6,43154).
+char(7,43155).
+char(6,43156).
+char(6,43157).
+char(p,43158).
+char(o,43159).
+char(m,43160).
+char(4,43161).
+char(2,43162).
+char(2,43163).
+char(5,43164).
+char(p,43165).
+char(5,43166).
+char(7,43167).
+char(6,43168).
+char(p,43169).
+char(1,43170).
+char(6,43171).
+char(3,43172).
+char(4,43173).
+char(m,43174).
+char(3,43175).
+char(4,43176).
+char(3,43177).
+char(2,43178).
+char(c,43179).
+char(m,43180).
+char(o,43181).
+char(o,43182).
+char(o,43183).
+char(m,43184).
+char(o,43185).
+char(o,43186).
+char(4,43187).
+char(6,43188).
+char(7,43189).
+char(7,43190).
+char(p,43191).
+char(o,43192).
+char(m,43193).
+char(7,43194).
+char(4,43195).
+char(4,43196).
+char(9,43197).
+char(c,43198).
+char(c,43199).
+char(m,43200).
+char(o,43201).
+char(o,43202).
+char(p,43203).
+char(7,43204).
+char(9,43205).
+char(0,43206).
+char(2,43207).
+char(c,43208).
+char(m,43209).
+char(o,43210).
+char(o,43211).
+char(7,43212).
+char(9,43213).
+char(1,43214).
+char(7,43215).
+char(p,43216).
+char(o,43217).
+char(m,43218).
+char(o,43219).
+char(o,43220).
+char(o,43221).
+char(6,43222).
+char(1,43223).
+char(8,43224).
+char(6,43225).
+char(p,43226).
+char(o,43227).
+char(p,43228).
+char(2,43229).
+char(5,43230).
+char(7,43231).
+char(9,43232).
+char(p,43233).
+char(2,43234).
+char(6,43235).
+char(7,43236).
+char(4,43237).
+char(c,43238).
+char(c,43239).
+char(c,43240).
+char(c,43241).
+char(p,43242).
+char(o,43243).
+char(p,43244).
+char(5,43245).
+char(3,43246).
+char(8,43247).
+char(3,43248).
+char(c,43249).
+char(c,43250).
+char(p,43251).
+char(o,43252).
+char(m,43253).
+char(4,43254).
+char(5,43255).
+char(2,43256).
+char(6,43257).
+char(c,43258).
+char(c,43259).
+char(c,43260).
+char(c,43261).
+char(p,43262).
+char(3,43263).
+char(0,43264).
+char(1,43265).
+char(1,43266).
+char(p,43267).
+char(2,43268).
+char(9,43269).
+char(1,43270).
+char(9,43271).
+char(p,43272).
+char(o,43273).
+char(o,43274).
+char(4,43275).
+char(2,43276).
+char(2,43277).
+char(3,43278).
+char(p,43279).
+char(o,43280).
+char(m,43281).
+char(2,43282).
+char(5,43283).
+char(9,43284).
+char(7,43285).
+char(c,43286).
+char(p,43287).
+char(7,43288).
+char(8,43289).
+char(4,43290).
+char(8,43291).
+char(m,43292).
+char(o,43293).
+char(8,43294).
+char(0,43295).
+char(2,43296).
+char(9,43297).
+char(c,43298).
+char(c,43299).
+char(c,43300).
+char(p,43301).
+char(o,43302).
+char(p,43303).
+char(9,43304).
+char(6,43305).
+char(2,43306).
+char(8,43307).
+char(m,43308).
+char(3,43309).
+char(5,43310).
+char(0,43311).
+char(7,43312).
+char(c,43313).
+char(c,43314).
+char(m,43315).
+char(6,43316).
+char(6,43317).
+char(2,43318).
+char(9,43319).
+char(m,43320).
+char(o,43321).
+char(m,43322).
+char(7,43323).
+char(2,43324).
+char(5,43325).
+char(8,43326).
+char(p,43327).
+char(o,43328).
+char(4,43329).
+char(9,43330).
+char(0,43331).
+char(0,43332).
+char(m,43333).
+char(o,43334).
+char(m,43335).
+char(o,43336).
+char(2,43337).
+char(0,43338).
+char(0,43339).
+char(c,43340).
+char(c,43341).
+char(c,43342).
+char(m,43343).
+char(o,43344).
+char(p,43345).
+char(o,43346).
+char(m,43347).
+char(5,43348).
+char(2,43349).
+char(9,43350).
+char(4,43351).
+char(c,43352).
+char(c,43353).
+char(c,43354).
+char(c,43355).
+char(c,43356).
+char(c,43357).
+char(c,43358).
+char(c,43359).
+char(p,43360).
+char(5,43361).
+char(7,43362).
+char(4,43363).
+char(0,43364).
+char(p,43365).
+char(3,43366).
+char(0,43367).
+char(7,43368).
+char(2,43369).
+char(p,43370).
+char(4,43371).
+char(8,43372).
+char(4,43373).
+char(5,43374).
+char(c,43375).
+char(m,43376).
+char(o,43377).
+char(8,43378).
+char(2,43379).
+char(8,43380).
+char(8,43381).
+char(m,43382).
+char(o,43383).
+char(p,43384).
+char(o,43385).
+char(m,43386).
+char(8,43387).
+char(6,43388).
+char(0,43389).
+char(7,43390).
+char(m,43391).
+char(o,43392).
+char(m,43393).
+char(o,43394).
+char(5,43395).
+char(5,43396).
+char(0,43397).
+char(8,43398).
+char(c,43399).
+char(c,43400).
+char(p,43401).
+char(3,43402).
+char(4,43403).
+char(3,43404).
+char(6,43405).
+char(m,43406).
+char(6,43407).
+char(2,43408).
+char(1,43409).
+char(5,43410).
+char(p,43411).
+char(o,43412).
+char(m,43413).
+char(o,43414).
+char(p,43415).
+char(6,43416).
+char(2,43417).
+char(9,43418).
+char(1,43419).
+char(p,43420).
+char(3,43421).
+char(3,43422).
+char(8,43423).
+char(9,43424).
+char(p,43425).
+char(6,43426).
+char(1,43427).
+char(8,43428).
+char(p,43429).
+char(3,43430).
+char(1,43431).
+char(8,43432).
+char(6,43433).
+char(m,43434).
+char(o,43435).
+char(o,43436).
+char(m,43437).
+char(3,43438).
+char(5,43439).
+char(4,43440).
+char(6,43441).
+char(p,43442).
+char(o,43443).
+char(m,43444).
+char(8,43445).
+char(6,43446).
+char(8,43447).
+char(3,43448).
+char(m,43449).
+char(5,43450).
+char(7,43451).
+char(0,43452).
+char(3,43453).
+char(c,43454).
+char(c,43455).
+char(c,43456).
+char(m,43457).
+char(1,43458).
+char(1,43459).
+char(6,43460).
+char(7,43461).
+char(c,43462).
+char(p,43463).
+char(5,43464).
+char(4,43465).
+char(4,43466).
+char(3,43467).
+char(m,43468).
+char(9,43469).
+char(4,43470).
+char(1,43471).
+char(1,43472).
+char(c,43473).
+char(m,43474).
+char(2,43475).
+char(2,43476).
+char(2,43477).
+char(4,43478).
+char(p,43479).
+char(o,43480).
+char(p,43481).
+char(o,43482).
+char(p,43483).
+char(9,43484).
+char(1,43485).
+char(1,43486).
+char(4,43487).
+char(c,43488).
+char(m,43489).
+char(6,43490).
+char(5,43491).
+char(3,43492).
+char(0,43493).
+char(m,43494).
+char(o,43495).
+char(p,43496).
+char(3,43497).
+char(1,43498).
+char(3,43499).
+char(8,43500).
+char(p,43501).
+char(7,43502).
+char(8,43503).
+char(2,43504).
+char(7,43505).
+char(m,43506).
+char(o,43507).
+char(6,43508).
+char(4,43509).
+char(1,43510).
+char(0,43511).
+char(m,43512).
+char(o,43513).
+char(o,43514).
+char(m,43515).
+char(1,43516).
+char(4,43517).
+char(9,43518).
+char(3,43519).
+char(p,43520).
+char(8,43521).
+char(1,43522).
+char(6,43523).
+char(8,43524).
+char(p,43525).
+char(9,43526).
+char(8,43527).
+char(3,43528).
+char(5,43529).
+char(m,43530).
+char(2,43531).
+char(9,43532).
+char(6,43533).
+char(8,43534).
+char(c,43535).
+char(p,43536).
+char(1,43537).
+char(1,43538).
+char(8,43539).
+char(m,43540).
+char(o,43541).
+char(p,43542).
+char(3,43543).
+char(3,43544).
+char(9,43545).
+char(7,43546).
+char(m,43547).
+char(o,43548).
+char(m,43549).
+char(o,43550).
+char(1,43551).
+char(8,43552).
+char(9,43553).
+char(3,43554).
+char(m,43555).
+char(o,43556).
+char(p,43557).
+char(o,43558).
+char(p,43559).
+char(o,43560).
+char(m,43561).
+char(3,43562).
+char(9,43563).
+char(4,43564).
+char(1,43565).
+char(m,43566).
+char(o,43567).
+char(p,43568).
+char(o,43569).
+char(m,43570).
+char(8,43571).
+char(7,43572).
+char(0,43573).
+char(6,43574).
+char(p,43575).
+char(o,43576).
+char(m,43577).
+char(5,43578).
+char(1,43579).
+char(9,43580).
+char(1,43581).
+char(p,43582).
+char(o,43583).
+char(p,43584).
+char(o,43585).
+char(p,43586).
+char(8,43587).
+char(6,43588).
+char(3,43589).
+char(5,43590).
+char(c,43591).
+char(m,43592).
+char(o,43593).
+char(5,43594).
+char(7,43595).
+char(5,43596).
+char(1,43597).
+char(p,43598).
+char(o,43599).
+char(p,43600).
+char(6,43601).
+char(5,43602).
+char(6,43603).
+char(4,43604).
+char(c,43605).
+char(p,43606).
+char(6,43607).
+char(8,43608).
+char(7,43609).
+char(3,43610).
+char(c,43611).
+char(c,43612).
+char(c,43613).
+char(m,43614).
+char(6,43615).
+char(3,43616).
+char(7,43617).
+char(m,43618).
+char(o,43619).
+char(o,43620).
+char(p,43621).
+char(o,43622).
+char(m,43623).
+char(2,43624).
+char(8,43625).
+char(6,43626).
+char(4,43627).
+char(c,43628).
+char(c,43629).
+char(m,43630).
+char(o,43631).
+char(p,43632).
+char(6,43633).
+char(4,43634).
+char(8,43635).
+char(m,43636).
+char(3,43637).
+char(6,43638).
+char(5,43639).
+char(3,43640).
+char(c,43641).
+char(p,43642).
+char(o,43643).
+char(m,43644).
+char(o,43645).
+char(m,43646).
+char(o,43647).
+char(5,43648).
+char(7,43649).
+char(6,43650).
+char(7,43651).
+char(c,43652).
+char(m,43653).
+char(8,43654).
+char(3,43655).
+char(6,43656).
+char(0,43657).
+char(m,43658).
+char(o,43659).
+char(p,43660).
+char(7,43661).
+char(5,43662).
+char(6,43663).
+char(5,43664).
+char(c,43665).
+char(c,43666).
+char(p,43667).
+char(o,43668).
+char(p,43669).
+char(4,43670).
+char(0,43671).
+char(7,43672).
+char(4,43673).
+char(c,43674).
+char(p,43675).
+char(o,43676).
+char(5,43677).
+char(1,43678).
+char(4,43679).
+char(9,43680).
+char(m,43681).
+char(4,43682).
+char(6,43683).
+char(2,43684).
+char(7,43685).
+char(c,43686).
+char(m,43687).
+char(o,43688).
+char(4,43689).
+char(9,43690).
+char(3,43691).
+char(5,43692).
+char(c,43693).
+char(c,43694).
+char(c,43695).
+char(m,43696).
+char(o,43697).
+char(m,43698).
+char(3,43699).
+char(9,43700).
+char(9,43701).
+char(2,43702).
+char(p,43703).
+char(9,43704).
+char(6,43705).
+char(5,43706).
+char(2,43707).
+char(c,43708).
+char(c,43709).
+char(p,43710).
+char(7,43711).
+char(8,43712).
+char(9,43713).
+char(7,43714).
+char(c,43715).
+char(c,43716).
+char(p,43717).
+char(o,43718).
+char(3,43719).
+char(2,43720).
+char(1,43721).
+char(9,43722).
+char(c,43723).
+char(p,43724).
+char(o,43725).
+char(m,43726).
+char(5,43727).
+char(1,43728).
+char(6,43729).
+char(3,43730).
+char(c,43731).
+char(p,43732).
+char(o,43733).
+char(m,43734).
+char(o,43735).
+char(m,43736).
+char(1,43737).
+char(0,43738).
+char(3,43739).
+char(7,43740).
+char(c,43741).
+char(c,43742).
+char(c,43743).
+char(c,43744).
+char(p,43745).
+char(o,43746).
+char(m,43747).
+char(6,43748).
+char(6,43749).
+char(2,43750).
+char(4,43751).
+char(c,43752).
+char(c,43753).
+char(m,43754).
+char(o,43755).
+char(p,43756).
+char(o,43757).
+char(3,43758).
+char(9,43759).
+char(3,43760).
+char(6,43761).
+char(p,43762).
+char(o,43763).
+char(o,43764).
+char(8,43765).
+char(6,43766).
+char(9,43767).
+char(0,43768).
+char(m,43769).
+char(o,43770).
+char(m,43771).
+char(2,43772).
+char(8,43773).
+char(5,43774).
+char(3,43775).
+char(p,43776).
+char(o,43777).
+char(m,43778).
+char(1,43779).
+char(9,43780).
+char(1,43781).
+char(2,43782).
+char(p,43783).
+char(4,43784).
+char(0,43785).
+char(0,43786).
+char(5,43787).
+char(c,43788).
+char(c,43789).
+char(c,43790).
+char(c,43791).
+char(p,43792).
+char(o,43793).
+char(1,43794).
+char(0,43795).
+char(7,43796).
+char(8,43797).
+char(c,43798).
+char(m,43799).
+char(o,43800).
+char(m,43801).
+char(o,43802).
+char(m,43803).
+char(1,43804).
+char(7,43805).
+char(4,43806).
+char(6,43807).
+char(p,43808).
+char(6,43809).
+char(5,43810).
+char(8,43811).
+char(4,43812).
+char(c,43813).
+char(c,43814).
+char(p,43815).
+char(o,43816).
+char(p,43817).
+char(1,43818).
+char(9,43819).
+char(1,43820).
+char(9,43821).
+char(p,43822).
+char(o,43823).
+char(p,43824).
+char(6,43825).
+char(2,43826).
+char(3,43827).
+char(2,43828).
+char(m,43829).
+char(o,43830).
+char(m,43831).
+char(o,43832).
+char(p,43833).
+char(3,43834).
+char(5,43835).
+char(1,43836).
+char(8,43837).
+char(m,43838).
+char(1,43839).
+char(4,43840).
+char(4,43841).
+char(6,43842).
+char(c,43843).
+char(c,43844).
+char(c,43845).
+char(c,43846).
+char(c,43847).
+char(c,43848).
+char(c,43849).
+char(c,43850).
+char(m,43851).
+char(o,43852).
+char(o,43853).
+char(p,43854).
+char(4,43855).
+char(1,43856).
+char(1,43857).
+char(1,43858).
+char(c,43859).
+char(c,43860).
+char(c,43861).
+char(p,43862).
+char(9,43863).
+char(6,43864).
+char(9,43865).
+char(2,43866).
+char(c,43867).
+char(p,43868).
+char(3,43869).
+char(4,43870).
+char(6,43871).
+char(6,43872).
+char(c,43873).
+char(p,43874).
+char(9,43875).
+char(9,43876).
+char(7,43877).
+char(1,43878).
+char(c,43879).
+char(c,43880).
+char(m,43881).
+char(o,43882).
+char(p,43883).
+char(o,43884).
+char(m,43885).
+char(o,43886).
+char(m,43887).
+char(3,43888).
+char(1,43889).
+char(7,43890).
+char(4,43891).
+char(m,43892).
+char(o,43893).
+char(p,43894).
+char(o,43895).
+char(p,43896).
+char(1,43897).
+char(7,43898).
+char(3,43899).
+char(8,43900).
+char(c,43901).
+char(p,43902).
+char(7,43903).
+char(9,43904).
+char(4,43905).
+char(1,43906).
+char(m,43907).
+char(8,43908).
+char(0,43909).
+char(8,43910).
+char(5,43911).
+char(m,43912).
+char(4,43913).
+char(2,43914).
+char(9,43915).
+char(2,43916).
+char(p,43917).
+char(8,43918).
+char(5,43919).
+char(0,43920).
+char(2,43921).
+char(c,43922).
+char(p,43923).
+char(6,43924).
+char(9,43925).
+char(3,43926).
+char(2,43927).
+char(c,43928).
+char(p,43929).
+char(7,43930).
+char(1,43931).
+char(0,43932).
+char(4,43933).
+char(p,43934).
+char(1,43935).
+char(6,43936).
+char(5,43937).
+char(c,43938).
+char(c,43939).
+char(p,43940).
+char(3,43941).
+char(2,43942).
+char(5,43943).
+char(2,43944).
+char(c,43945).
+char(m,43946).
+char(o,43947).
+char(m,43948).
+char(o,43949).
+char(p,43950).
+char(1,43951).
+char(9,43952).
+char(6,43953).
+char(1,43954).
+char(c,43955).
+char(m,43956).
+char(4,43957).
+char(5,43958).
+char(m,43959).
+char(o,43960).
+char(p,43961).
+char(o,43962).
+char(p,43963).
+char(o,43964).
+char(7,43965).
+char(8,43966).
+char(7,43967).
+char(m,43968).
+char(o,43969).
+char(m,43970).
+char(o,43971).
+char(m,43972).
+char(o,43973).
+char(p,43974).
+char(1,43975).
+char(9,43976).
+char(0,43977).
+char(2,43978).
+char(m,43979).
+char(o,43980).
+char(m,43981).
+char(9,43982).
+char(1,43983).
+char(3,43984).
+char(9,43985).
+char(p,43986).
+char(o,43987).
+char(p,43988).
+char(5,43989).
+char(9,43990).
+char(7,43991).
+char(9,43992).
+char(p,43993).
+char(o,43994).
+char(m,43995).
+char(2,43996).
+char(5,43997).
+char(8,43998).
+char(6,43999).
+char(c,44000).
+char(c,44001).
+char(m,44002).
+char(o,44003).
+char(p,44004).
+char(6,44005).
+char(1,44006).
+char(2,44007).
+char(3,44008).
+char(p,44009).
+char(7,44010).
+char(3,44011).
+char(2,44012).
+char(9,44013).
+char(c,44014).
+char(p,44015).
+char(7,44016).
+char(1,44017).
+char(0,44018).
+char(8,44019).
+char(c,44020).
+char(m,44021).
+char(o,44022).
+char(m,44023).
+char(o,44024).
+char(p,44025).
+char(o,44026).
+char(p,44027).
+char(8,44028).
+char(7,44029).
+char(5,44030).
+char(7,44031).
+char(c,44032).
+char(c,44033).
+char(c,44034).
+char(p,44035).
+char(1,44036).
+char(2,44037).
+char(8,44038).
+char(5,44039).
+char(c,44040).
+char(p,44041).
+char(o,44042).
+char(p,44043).
+char(o,44044).
+char(m,44045).
+char(3,44046).
+char(7,44047).
+char(3,44048).
+char(1,44049).
+char(c,44050).
+char(p,44051).
+char(o,44052).
+char(p,44053).
+char(o,44054).
+char(m,44055).
+char(3,44056).
+char(5,44057).
+char(6,44058).
+char(2,44059).
+char(c,44060).
+char(c,44061).
+char(p,44062).
+char(o,44063).
+char(2,44064).
+char(5,44065).
+char(7,44066).
+char(9,44067).
+char(c,44068).
+char(c,44069).
+char(m,44070).
+char(o,44071).
+char(m,44072).
+char(8,44073).
+char(0,44074).
+char(3,44075).
+char(5,44076).
+char(m,44077).
+char(8,44078).
+char(0,44079).
+char(0,44080).
+char(9,44081).
+char(c,44082).
+char(m,44083).
+char(3,44084).
+char(2,44085).
+char(9,44086).
+char(0,44087).
+char(c,44088).
+char(m,44089).
+char(9,44090).
+char(8,44091).
+char(7,44092).
+char(3,44093).
+char(c,44094).
+char(p,44095).
+char(6,44096).
+char(1,44097).
+char(8,44098).
+char(6,44099).
+char(p,44100).
+char(o,44101).
+char(p,44102).
+char(o,44103).
+char(6,44104).
+char(1,44105).
+char(8,44106).
+char(2,44107).
+char(c,44108).
+char(p,44109).
+char(o,44110).
+char(p,44111).
+char(9,44112).
+char(8,44113).
+char(1,44114).
+char(9,44115).
+char(m,44116).
+char(o,44117).
+char(4,44118).
+char(7,44119).
+char(6,44120).
+char(3,44121).
+char(p,44122).
+char(o,44123).
+char(4,44124).
+char(6,44125).
+char(1,44126).
+char(2,44127).
+char(c,44128).
+char(m,44129).
+char(1,44130).
+char(5,44131).
+char(2,44132).
+char(7,44133).
+char(p,44134).
+char(o,44135).
+char(p,44136).
+char(o,44137).
+char(o,44138).
+char(p,44139).
+char(o,44140).
+char(m,44141).
+char(4,44142).
+char(0,44143).
+char(5,44144).
+char(6,44145).
+char(p,44146).
+char(o,44147).
+char(2,44148).
+char(4,44149).
+char(1,44150).
+char(0,44151).
+char(m,44152).
+char(3,44153).
+char(4,44154).
+char(2,44155).
+char(6,44156).
+char(m,44157).
+char(o,44158).
+char(p,44159).
+char(o,44160).
+char(o,44161).
+char(p,44162).
+char(9,44163).
+char(6,44164).
+char(2,44165).
+char(4,44166).
+char(c,44167).
+char(m,44168).
+char(7,44169).
+char(4,44170).
+char(0,44171).
+char(3,44172).
+char(c,44173).
+char(p,44174).
+char(o,44175).
+char(p,44176).
+char(o,44177).
+char(m,44178).
+char(o,44179).
+char(p,44180).
+char(o,44181).
+char(m,44182).
+char(o,44183).
+char(5,44184).
+char(4,44185).
+char(c,44186).
+char(m,44187).
+char(1,44188).
+char(8,44189).
+char(6,44190).
+char(p,44191).
+char(1,44192).
+char(5,44193).
+char(3,44194).
+char(2,44195).
+char(c,44196).
+char(m,44197).
+char(o,44198).
+char(m,44199).
+char(5,44200).
+char(8,44201).
+char(9,44202).
+char(8,44203).
+char(m,44204).
+char(6,44205).
+char(9,44206).
+char(6,44207).
+char(1,44208).
+char(c,44209).
+char(m,44210).
+char(o,44211).
+char(m,44212).
+char(o,44213).
+char(3,44214).
+char(0,44215).
+char(6,44216).
+char(c,44217).
+char(c,44218).
+char(p,44219).
+char(o,44220).
+char(p,44221).
+char(o,44222).
+char(1,44223).
+char(4,44224).
+char(4,44225).
+char(2,44226).
+char(m,44227).
+char(o,44228).
+char(p,44229).
+char(o,44230).
+char(m,44231).
+char(6,44232).
+char(0,44233).
+char(1,44234).
+char(0,44235).
+char(c,44236).
+char(m,44237).
+char(9,44238).
+char(4,44239).
+char(4,44240).
+char(9,44241).
+char(c,44242).
+char(c,44243).
+char(m,44244).
+char(4,44245).
+char(3,44246).
+char(4,44247).
+char(6,44248).
+char(m,44249).
+char(2,44250).
+char(7,44251).
+char(7,44252).
+char(7,44253).
+char(c,44254).
+char(c,44255).
+char(c,44256).
+char(c,44257).
+char(c,44258).
+char(m,44259).
+char(2,44260).
+char(7,44261).
+char(7,44262).
+char(4,44263).
+char(m,44264).
+char(o,44265).
+char(p,44266).
+char(2,44267).
+char(7,44268).
+char(1,44269).
+char(c,44270).
+char(m,44271).
+char(5,44272).
+char(2,44273).
+char(3,44274).
+char(6,44275).
+char(p,44276).
+char(o,44277).
+char(6,44278).
+char(3,44279).
+char(1,44280).
+char(m,44281).
+char(o,44282).
+char(m,44283).
+char(1,44284).
+char(3,44285).
+char(8,44286).
+char(4,44287).
+char(p,44288).
+char(o,44289).
+char(p,44290).
+char(2,44291).
+char(4,44292).
+char(9,44293).
+char(m,44294).
+char(o,44295).
+char(p,44296).
+char(2,44297).
+char(5,44298).
+char(9,44299).
+char(6,44300).
+char(c,44301).
+char(m,44302).
+char(5,44303).
+char(3,44304).
+char(0,44305).
+char(m,44306).
+char(o,44307).
+char(m,44308).
+char(3,44309).
+char(8,44310).
+char(7,44311).
+char(m,44312).
+char(o,44313).
+char(p,44314).
+char(o,44315).
+char(m,44316).
+char(7,44317).
+char(1,44318).
+char(5,44319).
+char(8,44320).
+char(m,44321).
+char(7,44322).
+char(5,44323).
+char(5,44324).
+char(5,44325).
+char(c,44326).
+char(c,44327).
+char(p,44328).
+char(o,44329).
+char(m,44330).
+char(o,44331).
+char(m,44332).
+char(o,44333).
+char(7,44334).
+char(8,44335).
+char(4,44336).
+char(3,44337).
+char(m,44338).
+char(7,44339).
+char(4,44340).
+char(5,44341).
+char(9,44342).
+char(m,44343).
+char(9,44344).
+char(9,44345).
+char(4,44346).
+char(4,44347).
+char(m,44348).
+char(o,44349).
+char(o,44350).
+char(p,44351).
+char(o,44352).
+char(p,44353).
+char(2,44354).
+char(6,44355).
+char(2,44356).
+char(4,44357).
+char(c,44358).
+char(p,44359).
+char(9,44360).
+char(1,44361).
+char(7,44362).
+char(7,44363).
+char(c,44364).
+char(p,44365).
+char(7,44366).
+char(0,44367).
+char(7,44368).
+char(3,44369).
+char(c,44370).
+char(c,44371).
+char(c,44372).
+char(m,44373).
+char(3,44374).
+char(7,44375).
+char(2,44376).
+char(5,44377).
+char(c,44378).
+char(p,44379).
+char(9,44380).
+char(1,44381).
+char(3,44382).
+char(p,44383).
+char(6,44384).
+char(4,44385).
+char(8,44386).
+char(6,44387).
+char(c,44388).
+char(p,44389).
+char(o,44390).
+char(o,44391).
+char(7,44392).
+char(2,44393).
+char(1,44394).
+char(1,44395).
+char(c,44396).
+char(c,44397).
+char(p,44398).
+char(2,44399).
+char(9,44400).
+char(6,44401).
+char(7,44402).
+char(p,44403).
+char(1,44404).
+char(9,44405).
+char(3,44406).
+char(8,44407).
+char(m,44408).
+char(o,44409).
+char(p,44410).
+char(o,44411).
+char(6,44412).
+char(6,44413).
+char(0,44414).
+char(1,44415).
+char(p,44416).
+char(o,44417).
+char(p,44418).
+char(4,44419).
+char(4,44420).
+char(2,44421).
+char(4,44422).
+char(c,44423).
+char(c,44424).
+char(m,44425).
+char(4,44426).
+char(1,44427).
+char(8,44428).
+char(6,44429).
+char(c,44430).
+char(c,44431).
+char(c,44432).
+char(p,44433).
+char(9,44434).
+char(8,44435).
+char(5,44436).
+char(7,44437).
+char(p,44438).
+char(7,44439).
+char(8,44440).
+char(6,44441).
+char(m,44442).
+char(1,44443).
+char(4,44444).
+char(9,44445).
+char(c,44446).
+char(c,44447).
+char(m,44448).
+char(7,44449).
+char(3,44450).
+char(5,44451).
+char(p,44452).
+char(5,44453).
+char(6,44454).
+char(2,44455).
+char(5,44456).
+char(c,44457).
+char(c,44458).
+char(p,44459).
+char(o,44460).
+char(p,44461).
+char(o,44462).
+char(p,44463).
+char(o,44464).
+char(m,44465).
+char(6,44466).
+char(3,44467).
+char(9,44468).
+char(5,44469).
+char(m,44470).
+char(6,44471).
+char(7,44472).
+char(1,44473).
+char(9,44474).
+char(c,44475).
+char(c,44476).
+char(c,44477).
+char(c,44478).
+char(c,44479).
+char(p,44480).
+char(7,44481).
+char(4,44482).
+char(8,44483).
+char(4,44484).
+char(m,44485).
+char(9,44486).
+char(3,44487).
+char(0,44488).
+char(6,44489).
+char(c,44490).
+char(c,44491).
+char(c,44492).
+char(m,44493).
+char(1,44494).
+char(7,44495).
+char(5,44496).
+char(2,44497).
+char(m,44498).
+char(5,44499).
+char(9,44500).
+char(6,44501).
+char(9,44502).
+char(c,44503).
+char(m,44504).
+char(3,44505).
+char(1,44506).
+char(3,44507).
+char(9,44508).
+char(m,44509).
+char(9,44510).
+char(6,44511).
+char(4,44512).
+char(7,44513).
+char(p,44514).
+char(8,44515).
+char(6,44516).
+char(6,44517).
+char(c,44518).
+char(c,44519).
+char(m,44520).
+char(o,44521).
+char(p,44522).
+char(o,44523).
+char(o,44524).
+char(m,44525).
+char(9,44526).
+char(7,44527).
+char(7,44528).
+char(8,44529).
+char(c,44530).
+char(p,44531).
+char(o,44532).
+char(p,44533).
+char(o,44534).
+char(m,44535).
+char(o,44536).
+char(m,44537).
+char(6,44538).
+char(8,44539).
+char(5,44540).
+char(5,44541).
+char(c,44542).
+char(m,44543).
+char(8,44544).
+char(3,44545).
+char(0,44546).
+char(5,44547).
+char(p,44548).
+char(o,44549).
+char(m,44550).
+char(7,44551).
+char(1,44552).
+char(1,44553).
+char(c,44554).
+char(c,44555).
+char(p,44556).
+char(4,44557).
+char(5,44558).
+char(5,44559).
+char(9,44560).
+char(c,44561).
+char(m,44562).
+char(9,44563).
+char(7,44564).
+char(5,44565).
+char(0,44566).
+char(c,44567).
+char(c,44568).
+char(c,44569).
+char(p,44570).
+char(o,44571).
+char(o,44572).
+char(m,44573).
+char(3,44574).
+char(0,44575).
+char(7,44576).
+char(1,44577).
+char(c,44578).
+char(m,44579).
+char(3,44580).
+char(7,44581).
+char(1,44582).
+char(2,44583).
+char(m,44584).
+char(8,44585).
+char(3,44586).
+char(6,44587).
+char(6,44588).
+char(c,44589).
+char(m,44590).
+char(o,44591).
+char(p,44592).
+char(4,44593).
+char(9,44594).
+char(4,44595).
+char(8,44596).
+char(c,44597).
+char(p,44598).
+char(1,44599).
+char(8,44600).
+char(4,44601).
+char(8,44602).
+char(p,44603).
+char(8,44604).
+char(3,44605).
+char(5,44606).
+char(4,44607).
+char(p,44608).
+char(4,44609).
+char(1,44610).
+char(1,44611).
+char(8,44612).
+char(m,44613).
+char(1,44614).
+char(p,44615).
+char(o,44616).
+char(o,44617).
+char(p,44618).
+char(o,44619).
+char(1,44620).
+char(3,44621).
+char(0,44622).
+char(9,44623).
+char(c,44624).
+char(c,44625).
+char(p,44626).
+char(o,44627).
+char(p,44628).
+char(9,44629).
+char(1,44630).
+char(5,44631).
+char(3,44632).
+char(c,44633).
+char(m,44634).
+char(6,44635).
+char(1,44636).
+char(2,44637).
+char(6,44638).
+char(p,44639).
+char(3,44640).
+char(3,44641).
+char(6,44642).
+char(9,44643).
+char(c,44644).
+char(c,44645).
+char(c,44646).
+char(p,44647).
+char(o,44648).
+char(p,44649).
+char(o,44650).
+char(8,44651).
+char(9,44652).
+char(6,44653).
+char(9,44654).
+char(m,44655).
+char(o,44656).
+char(m,44657).
+char(4,44658).
+char(8,44659).
+char(1,44660).
+char(4,44661).
+char(c,44662).
+char(p,44663).
+char(4,44664).
+char(6,44665).
+char(2,44666).
+char(1,44667).
+char(p,44668).
+char(3,44669).
+char(7,44670).
+char(8,44671).
+char(0,44672).
+char(c,44673).
+char(c,44674).
+char(m,44675).
+char(o,44676).
+char(4,44677).
+char(1,44678).
+char(4,44679).
+char(7,44680).
+char(m,44681).
+char(7,44682).
+char(8,44683).
+char(4,44684).
+char(9,44685).
+char(m,44686).
+char(8,44687).
+char(5,44688).
+char(c,44689).
+char(p,44690).
+char(o,44691).
+char(o,44692).
+char(m,44693).
+char(o,44694).
+char(m,44695).
+char(o,44696).
+char(m,44697).
+char(o,44698).
+char(o,44699).
+char(6,44700).
+char(1,44701).
+char(6,44702).
+char(3,44703).
+char(p,44704).
+char(9,44705).
+char(8,44706).
+char(5,44707).
+char(m,44708).
+char(o,44709).
+char(m,44710).
+char(o,44711).
+char(m,44712).
+char(o,44713).
+char(m,44714).
+char(o,44715).
+char(p,44716).
+char(2,44717).
+char(8,44718).
+char(8,44719).
+char(3,44720).
+char(c,44721).
+char(c,44722).
+char(c,44723).
+char(p,44724).
+char(o,44725).
+char(m,44726).
+char(8,44727).
+char(2,44728).
+char(2,44729).
+char(9,44730).
+char(p,44731).
+char(5,44732).
+char(8,44733).
+char(3,44734).
+char(0,44735).
+char(m,44736).
+char(4,44737).
+char(5,44738).
+char(9,44739).
+char(4,44740).
+char(c,44741).
+char(p,44742).
+char(8,44743).
+char(5,44744).
+char(8,44745).
+char(6,44746).
+char(c,44747).
+char(c,44748).
+char(m,44749).
+char(o,44750).
+char(p,44751).
+char(o,44752).
+char(m,44753).
+char(o,44754).
+char(2,44755).
+char(3,44756).
+char(6,44757).
+char(5,44758).
+char(p,44759).
+char(9,44760).
+char(0,44761).
+char(7,44762).
+char(c,44763).
+char(c,44764).
+char(m,44765).
+char(2,44766).
+char(4,44767).
+char(4,44768).
+char(0,44769).
+char(p,44770).
+char(o,44771).
+char(8,44772).
+char(8,44773).
+char(4,44774).
+char(0,44775).
+char(p,44776).
+char(9,44777).
+char(7,44778).
+char(0,44779).
+char(8,44780).
+char(c,44781).
+char(c,44782).
+char(p,44783).
+char(2,44784).
+char(5,44785).
+char(7,44786).
+char(p,44787).
+char(o,44788).
+char(p,44789).
+char(8,44790).
+char(0,44791).
+char(1,44792).
+char(m,44793).
+char(7,44794).
+char(0,44795).
+char(0,44796).
+char(9,44797).
+char(m,44798).
+char(5,44799).
+char(2,44800).
+char(0,44801).
+char(5,44802).
+char(c,44803).
+char(m,44804).
+char(5,44805).
+char(1,44806).
+char(1,44807).
+char(5,44808).
+char(c,44809).
+char(m,44810).
+char(5,44811).
+char(3,44812).
+char(7,44813).
+char(7,44814).
+char(p,44815).
+char(6,44816).
+char(5,44817).
+char(6,44818).
+char(3,44819).
+char(c,44820).
+char(c,44821).
+char(c,44822).
+char(c,44823).
+char(p,44824).
+char(6,44825).
+char(9,44826).
+char(6,44827).
+char(c,44828).
+char(p,44829).
+char(4,44830).
+char(1,44831).
+char(5,44832).
+char(0,44833).
+char(c,44834).
+char(c,44835).
+char(m,44836).
+char(o,44837).
+char(p,44838).
+char(o,44839).
+char(m,44840).
+char(4,44841).
+char(2,44842).
+char(0,44843).
+char(4,44844).
+char(c,44845).
+char(c,44846).
+char(p,44847).
+char(o,44848).
+char(o,44849).
+char(m,44850).
+char(2,44851).
+char(8,44852).
+char(6,44853).
+char(8,44854).
+char(c,44855).
+char(c,44856).
+char(c,44857).
+char(c,44858).
+char(m,44859).
+char(2,44860).
+char(0,44861).
+char(5,44862).
+char(0,44863).
+char(c,44864).
+char(p,44865).
+char(o,44866).
+char(p,44867).
+char(o,44868).
+char(p,44869).
+char(2,44870).
+char(5,44871).
+char(7,44872).
+char(7,44873).
+char(p,44874).
+char(o,44875).
+char(p,44876).
+char(o,44877).
+char(p,44878).
+char(2,44879).
+char(3,44880).
+char(0,44881).
+char(1,44882).
+char(m,44883).
+char(7,44884).
+char(1,44885).
+char(1,44886).
+char(8,44887).
+char(c,44888).
+char(c,44889).
+char(p,44890).
+char(o,44891).
+char(m,44892).
+char(2,44893).
+char(4,44894).
+char(2,44895).
+char(4,44896).
+char(m,44897).
+char(8,44898).
+char(9,44899).
+char(4,44900).
+char(3,44901).
+char(c,44902).
+char(p,44903).
+char(o,44904).
+char(m,44905).
+char(6,44906).
+char(7,44907).
+char(6,44908).
+char(6,44909).
+char(c,44910).
+char(c,44911).
+char(c,44912).
+char(m,44913).
+char(o,44914).
+char(5,44915).
+char(3,44916).
+char(9,44917).
+char(m,44918).
+char(4,44919).
+char(6,44920).
+char(1,44921).
+char(0,44922).
+char(c,44923).
+char(m,44924).
+char(5,44925).
+char(2,44926).
+char(4,44927).
+char(7,44928).
+char(c,44929).
+char(p,44930).
+char(6,44931).
+char(3,44932).
+char(5,44933).
+char(c,44934).
+char(c,44935).
+char(c,44936).
+char(p,44937).
+char(o,44938).
+char(p,44939).
+char(7,44940).
+char(6,44941).
+char(1,44942).
+char(2,44943).
+char(m,44944).
+char(o,44945).
+char(p,44946).
+char(3,44947).
+char(1,44948).
+char(7,44949).
+char(c,44950).
+char(p,44951).
+char(o,44952).
+char(p,44953).
+char(5,44954).
+char(6,44955).
+char(0,44956).
+char(m,44957).
+char(8,44958).
+char(6,44959).
+char(3,44960).
+char(m,44961).
+char(4,44962).
+char(3,44963).
+char(6,44964).
+char(c,44965).
+char(p,44966).
+char(6,44967).
+char(6,44968).
+char(6,44969).
+char(0,44970).
+char(c,44971).
+char(p,44972).
+char(3,44973).
+char(8,44974).
+char(1,44975).
+char(6,44976).
+char(c,44977).
+char(m,44978).
+char(o,44979).
+char(o,44980).
+char(1,44981).
+char(0,44982).
+char(4,44983).
+char(4,44984).
+char(c,44985).
+char(c,44986).
+char(c,44987).
+char(c,44988).
+char(p,44989).
+char(2,44990).
+char(4,44991).
+char(0,44992).
+char(3,44993).
+char(c,44994).
+char(c,44995).
+char(c,44996).
+char(p,44997).
+char(9,44998).
+char(0,44999).
+char(0,45000).
+char(8,45001).
+char(m,45002).
+char(o,45003).
+char(m,45004).
+char(4,45005).
+char(0,45006).
+char(3,45007).
+char(7,45008).
+char(p,45009).
+char(o,45010).
+char(o,45011).
+char(o,45012).
+char(o,45013).
+char(p,45014).
+char(o,45015).
+char(p,45016).
+char(6,45017).
+char(2,45018).
+char(4,45019).
+char(9,45020).
+char(c,45021).
+char(c,45022).
+char(c,45023).
+char(c,45024).
+char(c,45025).
+char(c,45026).
+char(c,45027).
+char(c,45028).
+char(p,45029).
+char(o,45030).
+char(m,45031).
+char(o,45032).
+char(o,45033).
+char(m,45034).
+char(6,45035).
+char(3,45036).
+char(9,45037).
+char(8,45038).
+char(c,45039).
+char(c,45040).
+char(c,45041).
+char(p,45042).
+char(6,45043).
+char(5,45044).
+char(4,45045).
+char(9,45046).
+char(p,45047).
+char(o,45048).
+char(p,45049).
+char(7,45050).
+char(1,45051).
+char(0,45052).
+char(1,45053).
+char(m,45054).
+char(7,45055).
+char(6,45056).
+char(0,45057).
+char(2,45058).
+char(m,45059).
+char(o,45060).
+char(p,45061).
+char(9,45062).
+char(0,45063).
+char(7,45064).
+char(7,45065).
+char(m,45066).
+char(o,45067).
+char(5,45068).
+char(3,45069).
+char(2,45070).
+char(1,45071).
+char(c,45072).
+char(c,45073).
+char(p,45074).
+char(8,45075).
+char(8,45076).
+char(6,45077).
+char(7,45078).
+char(c,45079).
+char(p,45080).
+char(o,45081).
+char(m,45082).
+char(o,45083).
+char(p,45084).
+char(o,45085).
+char(o,45086).
+char(p,45087).
+char(o,45088).
+char(p,45089).
+char(o,45090).
+char(o,45091).
+char(m,45092).
+char(o,45093).
+char(m,45094).
+char(o,45095).
+char(p,45096).
+char(o,45097).
+char(p,45098).
+char(o,45099).
+char(p,45100).
+char(o,45101).
+char(p,45102).
+char(7,45103).
+char(5,45104).
+char(4,45105).
+char(9,45106).
+char(c,45107).
+char(p,45108).
+char(5,45109).
+char(7,45110).
+char(7,45111).
+char(8,45112).
+char(c,45113).
+char(m,45114).
+char(7,45115).
+char(0,45116).
+char(3,45117).
+char(6,45118).
+char(c,45119).
+char(m,45120).
+char(o,45121).
+char(p,45122).
+char(5,45123).
+char(5,45124).
+char(7,45125).
+char(c,45126).
+char(c,45127).
+char(m,45128).
+char(6,45129).
+char(3,45130).
+char(8,45131).
+char(0,45132).
+char(c,45133).
+char(p,45134).
+char(2,45135).
+char(1,45136).
+char(7,45137).
+char(7,45138).
+char(m,45139).
+char(2,45140).
+char(1,45141).
+char(9,45142).
+char(8,45143).
+char(c,45144).
+char(p,45145).
+char(o,45146).
+char(m,45147).
+char(5,45148).
+char(3,45149).
+char(3,45150).
+char(5,45151).
+char(p,45152).
+char(o,45153).
+char(p,45154).
+char(o,45155).
+char(m,45156).
+char(5,45157).
+char(4,45158).
+char(8,45159).
+char(0,45160).
+char(m,45161).
+char(o,45162).
+char(p,45163).
+char(6,45164).
+char(8,45165).
+char(7,45166).
+char(3,45167).
+char(p,45168).
+char(1,45169).
+char(4,45170).
+char(2,45171).
+char(7,45172).
+char(c,45173).
+char(c,45174).
+char(p,45175).
+char(4,45176).
+char(5,45177).
+char(2,45178).
+char(0,45179).
+char(p,45180).
+char(9,45181).
+char(3,45182).
+char(9,45183).
+char(7,45184).
+char(p,45185).
+char(o,45186).
+char(p,45187).
+char(o,45188).
+char(p,45189).
+char(o,45190).
+char(p,45191).
+char(o,45192).
+char(p,45193).
+char(2,45194).
+char(6,45195).
+char(9,45196).
+char(9,45197).
+char(p,45198).
+char(8,45199).
+char(0,45200).
+char(9,45201).
+char(9,45202).
+char(c,45203).
+char(c,45204).
+char(c,45205).
+char(p,45206).
+char(o,45207).
+char(p,45208).
+char(o,45209).
+char(m,45210).
+char(o,45211).
+char(m,45212).
+char(3,45213).
+char(2,45214).
+char(1,45215).
+char(7,45216).
+char(m,45217).
+char(9,45218).
+char(2,45219).
+char(2,45220).
+char(2,45221).
+char(c,45222).
+char(m,45223).
+char(8,45224).
+char(6,45225).
+char(6,45226).
+char(1,45227).
+char(c,45228).
+char(c,45229).
+char(m,45230).
+char(o,45231).
+char(p,45232).
+char(o,45233).
+char(m,45234).
+char(o,45235).
+char(m,45236).
+char(7,45237).
+char(7,45238).
+char(4,45239).
+char(6,45240).
+char(p,45241).
+char(o,45242).
+char(m,45243).
+char(7,45244).
+char(0,45245).
+char(7,45246).
+char(0,45247).
+char(p,45248).
+char(o,45249).
+char(p,45250).
+char(o,45251).
+char(o,45252).
+char(p,45253).
+char(o,45254).
+char(m,45255).
+char(o,45256).
+char(2,45257).
+char(3,45258).
+char(9,45259).
+char(4,45260).
+char(p,45261).
+char(4,45262).
+char(6,45263).
+char(2,45264).
+char(1,45265).
+char(c,45266).
+char(p,45267).
+char(o,45268).
+char(2,45269).
+char(9,45270).
+char(4,45271).
+char(0,45272).
+char(m,45273).
+char(5,45274).
+char(1,45275).
+char(8,45276).
+char(c,45277).
+char(c,45278).
+char(m,45279).
+char(o,45280).
+char(m,45281).
+char(1,45282).
+char(8,45283).
+char(1,45284).
+char(2,45285).
+char(c,45286).
+char(c,45287).
+char(p,45288).
+char(1,45289).
+char(2,45290).
+char(6,45291).
+char(1,45292).
+char(m,45293).
+char(2,45294).
+char(3,45295).
+char(3,45296).
+char(1,45297).
+char(c,45298).
+char(m,45299).
+char(8,45300).
+char(0,45301).
+char(2,45302).
+char(6,45303).
+char(c,45304).
+char(m,45305).
+char(9,45306).
+char(7,45307).
+char(9,45308).
+char(9,45309).
+char(c,45310).
+char(c,45311).
+char(m,45312).
+char(o,45313).
+char(m,45314).
+char(3,45315).
+char(5,45316).
+char(7,45317).
+char(6,45318).
+char(p,45319).
+char(4,45320).
+char(3,45321).
+char(9,45322).
+char(c,45323).
+char(p,45324).
+char(o,45325).
+char(m,45326).
+char(o,45327).
+char(p,45328).
+char(o,45329).
+char(m,45330).
+char(4,45331).
+char(6,45332).
+char(8,45333).
+char(1,45334).
+char(p,45335).
+char(4,45336).
+char(0,45337).
+char(9,45338).
+char(6,45339).
+char(p,45340).
+char(o,45341).
+char(p,45342).
+char(o,45343).
+char(p,45344).
+char(3,45345).
+char(7,45346).
+char(6,45347).
+char(2,45348).
+char(c,45349).
+char(p,45350).
+char(4,45351).
+char(8,45352).
+char(0,45353).
+char(2,45354).
+char(c,45355).
+char(c,45356).
+char(p,45357).
+char(o,45358).
+char(9,45359).
+char(6,45360).
+char(9,45361).
+char(6,45362).
+char(p,45363).
+char(o,45364).
+char(p,45365).
+char(3,45366).
+char(3,45367).
+char(5,45368).
+char(9,45369).
+char(m,45370).
+char(o,45371).
+char(4,45372).
+char(5,45373).
+char(9,45374).
+char(3,45375).
+char(c,45376).
+char(c,45377).
+char(p,45378).
+char(o,45379).
+char(p,45380).
+char(8,45381).
+char(5,45382).
+char(2,45383).
+char(c,45384).
+char(p,45385).
+char(o,45386).
+char(4,45387).
+char(1,45388).
+char(2,45389).
+char(3,45390).
+char(c,45391).
+char(c,45392).
+char(p,45393).
+char(7,45394).
+char(0,45395).
+char(5,45396).
+char(4,45397).
+char(p,45398).
+char(2,45399).
+char(2,45400).
+char(3,45401).
+char(6,45402).
+char(c,45403).
+char(c,45404).
+char(c,45405).
+char(m,45406).
+char(o,45407).
+char(m,45408).
+char(o,45409).
+char(o,45410).
+char(m,45411).
+char(o,45412).
+char(m,45413).
+char(6,45414).
+char(6,45415).
+char(0,45416).
+char(2,45417).
+char(p,45418).
+char(o,45419).
+char(m,45420).
+char(o,45421).
+char(m,45422).
+char(o,45423).
+char(8,45424).
+char(9,45425).
+char(2,45426).
+char(9,45427).
+char(c,45428).
+char(c,45429).
+char(m,45430).
+char(o,45431).
+char(o,45432).
+char(m,45433).
+char(7,45434).
+char(1,45435).
+char(2,45436).
+char(m,45437).
+char(7,45438).
+char(4,45439).
+char(7,45440).
+char(3,45441).
+char(m,45442).
+char(o,45443).
+char(m,45444).
+char(9,45445).
+char(7,45446).
+char(1,45447).
+char(9,45448).
+char(c,45449).
+char(m,45450).
+char(o,45451).
+char(m,45452).
+char(5,45453).
+char(4,45454).
+char(2,45455).
+char(2,45456).
+char(p,45457).
+char(9,45458).
+char(3,45459).
+char(3,45460).
+char(3,45461).
+char(m,45462).
+char(9,45463).
+char(4,45464).
+char(3,45465).
+char(0,45466).
+char(m,45467).
+char(2,45468).
+char(5,45469).
+char(3,45470).
+char(5,45471).
+char(p,45472).
+char(8,45473).
+char(5,45474).
+char(1,45475).
+char(8,45476).
+char(p,45477).
+char(5,45478).
+char(6,45479).
+char(3,45480).
+char(4,45481).
+char(p,45482).
+char(o,45483).
+char(m,45484).
+char(9,45485).
+char(0,45486).
+char(8,45487).
+char(1,45488).
+char(p,45489).
+char(o,45490).
+char(m,45491).
+char(o,45492).
+char(m,45493).
+char(2,45494).
+char(4,45495).
+char(8,45496).
+char(2,45497).
+char(c,45498).
+char(m,45499).
+char(o,45500).
+char(p,45501).
+char(o,45502).
+char(p,45503).
+char(1,45504).
+char(3,45505).
+char(7,45506).
+char(6,45507).
+char(c,45508).
+char(m,45509).
+char(o,45510).
+char(p,45511).
+char(4,45512).
+char(5,45513).
+char(3,45514).
+char(0,45515).
+char(c,45516).
+char(c,45517).
+char(c,45518).
+char(p,45519).
+char(2,45520).
+char(7,45521).
+char(0,45522).
+char(2,45523).
+char(c,45524).
+char(c,45525).
+char(c,45526).
+char(c,45527).
+char(m,45528).
+char(4,45529).
+char(5,45530).
+char(3,45531).
+char(9,45532).
+char(p,45533).
+char(o,45534).
+char(p,45535).
+char(o,45536).
+char(o,45537).
+char(o,45538).
+char(4,45539).
+char(9,45540).
+char(8,45541).
+char(8,45542).
+char(m,45543).
+char(o,45544).
+char(m,45545).
+char(o,45546).
+char(m,45547).
+char(4,45548).
+char(0,45549).
+char(c,45550).
+char(p,45551).
+char(1,45552).
+char(8,45553).
+char(1,45554).
+char(5,45555).
+char(p,45556).
+char(o,45557).
+char(p,45558).
+char(1,45559).
+char(5,45560).
+char(8,45561).
+char(4,45562).
+char(m,45563).
+char(o,45564).
+char(p,45565).
+char(o,45566).
+char(m,45567).
+char(o,45568).
+char(8,45569).
+char(6,45570).
+char(3,45571).
+char(9,45572).
+char(p,45573).
+char(9,45574).
+char(6,45575).
+char(9,45576).
+char(2,45577).
+char(p,45578).
+char(o,45579).
+char(p,45580).
+char(9,45581).
+char(2,45582).
+char(2,45583).
+char(6,45584).
+char(c,45585).
+char(c,45586).
+char(m,45587).
+char(9,45588).
+char(6,45589).
+char(3,45590).
+char(9,45591).
+char(c,45592).
+char(m,45593).
+char(o,45594).
+char(m,45595).
+char(o,45596).
+char(p,45597).
+char(o,45598).
+char(m,45599).
+char(o,45600).
+char(m,45601).
+char(8,45602).
+char(4,45603).
+char(2,45604).
+char(3,45605).
+char(c,45606).
+char(c,45607).
+char(m,45608).
+char(o,45609).
+char(m,45610).
+char(9,45611).
+char(7,45612).
+char(7,45613).
+char(2,45614).
+char(p,45615).
+char(o,45616).
+char(m,45617).
+char(6,45618).
+char(9,45619).
+char(9,45620).
+char(8,45621).
+char(p,45622).
+char(o,45623).
+char(o,45624).
+char(o,45625).
+char(p,45626).
+char(o,45627).
+char(o,45628).
+char(6,45629).
+char(1,45630).
+char(6,45631).
+char(5,45632).
+char(c,45633).
+char(p,45634).
+char(3,45635).
+char(2,45636).
+char(2,45637).
+char(7,45638).
+char(m,45639).
+char(1,45640).
+char(0,45641).
+char(1,45642).
+char(6,45643).
+char(c,45644).
+char(c,45645).
+char(c,45646).
+char(c,45647).
+char(m,45648).
+char(o,45649).
+char(m,45650).
+char(2,45651).
+char(1,45652).
+char(4,45653).
+char(5,45654).
+char(c,45655).
+char(p,45656).
+char(2,45657).
+char(3,45658).
+char(6,45659).
+char(4,45660).
+char(p,45661).
+char(1,45662).
+char(7,45663).
+char(8,45664).
+char(2,45665).
+char(c,45666).
+char(c,45667).
+char(c,45668).
+char(p,45669).
+char(2,45670).
+char(6,45671).
+char(0,45672).
+char(4,45673).
+char(m,45674).
+char(6,45675).
+char(4,45676).
+char(8,45677).
+char(2,45678).
+char(c,45679).
+char(m,45680).
+char(3,45681).
+char(5,45682).
+char(2,45683).
+char(9,45684).
+char(c,45685).
+char(c,45686).
+char(p,45687).
+char(o,45688).
+char(o,45689).
+char(p,45690).
+char(9,45691).
+char(4,45692).
+char(1,45693).
+char(3,45694).
+char(c,45695).
+char(p,45696).
+char(1,45697).
+char(9,45698).
+char(8,45699).
+char(5,45700).
+char(c,45701).
+char(c,45702).
+char(m,45703).
+char(o,45704).
+char(m,45705).
+char(o,45706).
+char(m,45707).
+char(o,45708).
+char(3,45709).
+char(6,45710).
+char(4,45711).
+char(0,45712).
+char(m,45713).
+char(6,45714).
+char(1,45715).
+char(6,45716).
+char(7,45717).
+char(c,45718).
+char(p,45719).
+char(o,45720).
+char(o,45721).
+char(p,45722).
+char(5,45723).
+char(4,45724).
+char(7,45725).
+char(4,45726).
+char(m,45727).
+char(5,45728).
+char(6,45729).
+char(6,45730).
+char(3,45731).
+char(c,45732).
+char(p,45733).
+char(8,45734).
+char(3,45735).
+char(2,45736).
+char(6,45737).
+char(c,45738).
+char(p,45739).
+char(o,45740).
+char(m,45741).
+char(o,45742).
+char(6,45743).
+char(7,45744).
+char(8,45745).
+char(9,45746).
+char(c,45747).
+char(m,45748).
+char(6,45749).
+char(1,45750).
+char(9,45751).
+char(4,45752).
+char(c,45753).
+char(c,45754).
+char(c,45755).
+char(c,45756).
+char(m,45757).
+char(o,45758).
+char(m,45759).
+char(2,45760).
+char(4,45761).
+char(2,45762).
+char(4,45763).
+char(p,45764).
+char(6,45765).
+char(9,45766).
+char(4,45767).
+char(2,45768).
+char(c,45769).
+char(c,45770).
+char(m,45771).
+char(o,45772).
+char(o,45773).
+char(1,45774).
+char(1,45775).
+char(2,45776).
+char(1,45777).
+char(m,45778).
+char(o,45779).
+char(m,45780).
+char(6,45781).
+char(4,45782).
+char(1,45783).
+char(4,45784).
+char(p,45785).
+char(o,45786).
+char(m,45787).
+char(5,45788).
+char(8,45789).
+char(6,45790).
+char(9,45791).
+char(c,45792).
+char(c,45793).
+char(m,45794).
+char(5,45795).
+char(3,45796).
+char(8,45797).
+char(p,45798).
+char(o,45799).
+char(m,45800).
+char(2,45801).
+char(4,45802).
+char(3,45803).
+char(9,45804).
+char(p,45805).
+char(7,45806).
+char(3,45807).
+char(1,45808).
+char(8,45809).
+char(m,45810).
+char(o,45811).
+char(o,45812).
+char(p,45813).
+char(7,45814).
+char(0,45815).
+char(7,45816).
+char(c,45817).
+char(c,45818).
+char(m,45819).
+char(o,45820).
+char(p,45821).
+char(o,45822).
+char(m,45823).
+char(o,45824).
+char(p,45825).
+char(o,45826).
+char(m,45827).
+char(o,45828).
+char(p,45829).
+char(5,45830).
+char(8,45831).
+char(1,45832).
+char(9,45833).
+char(m,45834).
+char(8,45835).
+char(9,45836).
+char(7,45837).
+char(c,45838).
+char(c,45839).
+char(c,45840).
+char(p,45841).
+char(o,45842).
+char(p,45843).
+char(o,45844).
+char(p,45845).
+char(o,45846).
+char(m,45847).
+char(4,45848).
+char(6,45849).
+char(9,45850).
+char(1,45851).
+char(m,45852).
+char(o,45853).
+char(o,45854).
+char(o,45855).
+char(o,45856).
+char(o,45857).
+char(p,45858).
+char(o,45859).
+char(7,45860).
+char(9,45861).
+char(2,45862).
+char(2,45863).
+char(p,45864).
+char(9,45865).
+char(2,45866).
+char(9,45867).
+char(3,45868).
+char(p,45869).
+char(7,45870).
+char(2,45871).
+char(8,45872).
+char(5,45873).
+char(c,45874).
+char(p,45875).
+char(3,45876).
+char(1,45877).
+char(2,45878).
+char(4,45879).
+char(p,45880).
+char(5,45881).
+char(8,45882).
+char(6,45883).
+char(3,45884).
+char(m,45885).
+char(o,45886).
+char(m,45887).
+char(o,45888).
+char(o,45889).
+char(o,45890).
+char(p,45891).
+char(1,45892).
+char(0,45893).
+char(4,45894).
+char(2,45895).
+char(p,45896).
+char(9,45897).
+char(4,45898).
+char(6,45899).
+char(3,45900).
+char(p,45901).
+char(o,45902).
+char(o,45903).
+char(m,45904).
+char(o,45905).
+char(5,45906).
+char(3,45907).
+char(3,45908).
+char(0,45909).
+char(c,45910).
+char(c,45911).
+char(m,45912).
+char(o,45913).
+char(p,45914).
+char(8,45915).
+char(3,45916).
+char(5,45917).
+char(3,45918).
+char(c,45919).
+char(m,45920).
+char(o,45921).
+char(o,45922).
+char(p,45923).
+char(o,45924).
+char(p,45925).
+char(2,45926).
+char(4,45927).
+char(6,45928).
+char(7,45929).
+char(c,45930).
+char(m,45931).
+char(o,45932).
+char(6,45933).
+char(4,45934).
+char(3,45935).
+char(3,45936).
+char(m,45937).
+char(8,45938).
+char(8,45939).
+char(7,45940).
+char(5,45941).
+char(m,45942).
+char(8,45943).
+char(1,45944).
+char(2,45945).
+char(5,45946).
+char(c,45947).
+char(c,45948).
+char(m,45949).
+char(o,45950).
+char(5,45951).
+char(4,45952).
+char(5,45953).
+char(8,45954).
+char(c,45955).
+char(c,45956).
+char(p,45957).
+char(5,45958).
+char(7,45959).
+char(6,45960).
+char(m,45961).
+char(6,45962).
+char(9,45963).
+char(6,45964).
+char(5,45965).
+char(m,45966).
+char(2,45967).
+char(5,45968).
+char(0,45969).
+char(8,45970).
+char(c,45971).
+char(m,45972).
+char(2,45973).
+char(8,45974).
+char(2,45975).
+char(1,45976).
+char(m,45977).
+char(o,45978).
+char(p,45979).
+char(1,45980).
+char(3,45981).
+char(2,45982).
+char(1,45983).
+char(m,45984).
+char(8,45985).
+char(2,45986).
+char(4,45987).
+char(7,45988).
+char(c,45989).
+char(p,45990).
+char(1,45991).
+char(1,45992).
+char(3,45993).
+char(0,45994).
+char(m,45995).
+char(7,45996).
+char(4,45997).
+char(1,45998).
+char(9,45999).
+char(m,46000).
+char(o,46001).
+char(m,46002).
+char(1,46003).
+char(5,46004).
+char(3,46005).
+char(3,46006).
+char(c,46007).
+char(c,46008).
+char(c,46009).
+char(c,46010).
+char(c,46011).
+char(m,46012).
+char(o,46013).
+char(1,46014).
+char(7,46015).
+char(2,46016).
+char(1,46017).
+char(m,46018).
+char(o,46019).
+char(m,46020).
+char(9,46021).
+char(7,46022).
+char(3,46023).
+char(4,46024).
+char(p,46025).
+char(o,46026).
+char(o,46027).
+char(o,46028).
+char(p,46029).
+char(o,46030).
+char(m,46031).
+char(o,46032).
+char(p,46033).
+char(o,46034).
+char(o,46035).
+char(p,46036).
+char(o,46037).
+char(o,46038).
+char(p,46039).
+char(2,46040).
+char(3,46041).
+char(7,46042).
+char(8,46043).
+char(c,46044).
+char(m,46045).
+char(7,46046).
+char(2,46047).
+char(1,46048).
+char(9,46049).
+char(c,46050).
+char(c,46051).
+char(m,46052).
+char(4,46053).
+char(5,46054).
+char(6,46055).
+char(0,46056).
+char(c,46057).
+char(m,46058).
+char(o,46059).
+char(p,46060).
+char(2,46061).
+char(6,46062).
+char(8,46063).
+char(5,46064).
+char(m,46065).
+char(8,46066).
+char(8,46067).
+char(1,46068).
+char(4,46069).
+char(c,46070).
+char(m,46071).
+char(5,46072).
+char(5,46073).
+char(0,46074).
+char(1,46075).
+char(p,46076).
+char(o,46077).
+char(p,46078).
+char(2,46079).
+char(5,46080).
+char(3,46081).
+char(4,46082).
+char(c,46083).
+char(c,46084).
+char(m,46085).
+char(o,46086).
+char(m,46087).
+char(7,46088).
+char(6,46089).
+char(7,46090).
+char(0,46091).
+char(m,46092).
+char(9,46093).
+char(7,46094).
+char(9,46095).
+char(9,46096).
+char(p,46097).
+char(9,46098).
+char(1,46099).
+char(3,46100).
+char(7,46101).
+char(c,46102).
+char(m,46103).
+char(1,46104).
+char(5,46105).
+char(3,46106).
+char(2,46107).
+char(m,46108).
+char(o,46109).
+char(p,46110).
+char(2,46111).
+char(2,46112).
+char(5,46113).
+char(1,46114).
+char(p,46115).
+char(6,46116).
+char(6,46117).
+char(1,46118).
+char(7,46119).
+char(c,46120).
+char(c,46121).
+char(c,46122).
+char(c,46123).
+char(p,46124).
+char(8,46125).
+char(0,46126).
+char(6,46127).
+char(8,46128).
+char(c,46129).
+char(m,46130).
+char(o,46131).
+char(m,46132).
+char(9,46133).
+char(7,46134).
+char(0,46135).
+char(4,46136).
+char(c,46137).
+char(c,46138).
+char(m,46139).
+char(o,46140).
+char(o,46141).
+char(m,46142).
+char(1,46143).
+char(5,46144).
+char(7,46145).
+char(5,46146).
+char(p,46147).
+char(7,46148).
+char(3,46149).
+char(1,46150).
+char(0,46151).
+char(c,46152).
+char(p,46153).
+char(2,46154).
+char(3,46155).
+char(4,46156).
+char(p,46157).
+char(1,46158).
+char(5,46159).
+char(9,46160).
+char(0,46161).
+char(c,46162).
+char(p,46163).
+char(3,46164).
+char(6,46165).
+char(7,46166).
+char(8,46167).
+char(c,46168).
+char(c,46169).
+char(p,46170).
+char(o,46171).
+char(9,46172).
+char(0,46173).
+char(1,46174).
+char(5,46175).
+char(p,46176).
+char(8,46177).
+char(2,46178).
+char(1,46179).
+char(c,46180).
+char(p,46181).
+char(7,46182).
+char(9,46183).
+char(8,46184).
+char(0,46185).
+char(c,46186).
+char(c,46187).
+char(c,46188).
+char(c,46189).
+char(m,46190).
+char(7,46191).
+char(4,46192).
+char(3,46193).
+char(4,46194).
+char(p,46195).
+char(5,46196).
+char(9,46197).
+char(0,46198).
+char(7,46199).
+char(m,46200).
+char(7,46201).
+char(5,46202).
+char(4,46203).
+char(0,46204).
+char(p,46205).
+char(1,46206).
+char(3,46207).
+char(2,46208).
+char(8,46209).
+char(c,46210).
+char(c,46211).
+char(p,46212).
+char(o,46213).
+char(7,46214).
+char(7,46215).
+char(7,46216).
+char(3,46217).
+char(m,46218).
+char(3,46219).
+char(4,46220).
+char(0,46221).
+char(2,46222).
+char(c,46223).
+char(p,46224).
+char(1,46225).
+char(0,46226).
+char(3,46227).
+char(4,46228).
+char(c,46229).
+char(c,46230).
+char(p,46231).
+char(2,46232).
+char(7,46233).
+char(6,46234).
+char(5,46235).
+char(m,46236).
+char(o,46237).
+char(o,46238).
+char(p,46239).
+char(9,46240).
+char(1,46241).
+char(7,46242).
+char(0,46243).
+char(m,46244).
+char(o,46245).
+char(m,46246).
+char(o,46247).
+char(m,46248).
+char(o,46249).
+char(p,46250).
+char(7,46251).
+char(7,46252).
+char(7,46253).
+char(9,46254).
+char(m,46255).
+char(o,46256).
+char(5,46257).
+char(7,46258).
+char(2,46259).
+char(1,46260).
+char(p,46261).
+char(5,46262).
+char(0,46263).
+char(2,46264).
+char(5,46265).
+char(c,46266).
+char(c,46267).
+char(c,46268).
+char(c,46269).
+char(c,46270).
+char(m,46271).
+char(9,46272).
+char(1,46273).
+char(8,46274).
+char(4,46275).
+char(p,46276).
+char(6,46277).
+char(4,46278).
+char(4,46279).
+char(9,46280).
+char(c,46281).
+char(c,46282).
+char(p,46283).
+char(8,46284).
+char(7,46285).
+char(9,46286).
+char(7,46287).
+char(m,46288).
+char(o,46289).
+char(p,46290).
+char(5,46291).
+char(4,46292).
+char(3,46293).
+char(6,46294).
+char(c,46295).
+char(p,46296).
+char(o,46297).
+char(m,46298).
+char(7,46299).
+char(1,46300).
+char(6,46301).
+char(3,46302).
+char(m,46303).
+char(1,46304).
+char(5,46305).
+char(4,46306).
+char(0,46307).
+char(c,46308).
+char(c,46309).
+char(c,46310).
+char(c,46311).
+char(c,46312).
+char(c,46313).
+char(c,46314).
+char(c,46315).
+char(m,46316).
+char(o,46317).
+char(o,46318).
+char(p,46319).
+char(o,46320).
+char(o,46321).
+char(o,46322).
+char(p,46323).
+char(o,46324).
+char(o,46325).
+char(o,46326).
+char(m,46327).
+char(1,46328).
+char(6,46329).
+char(7,46330).
+char(5,46331).
+char(m,46332).
+char(6,46333).
+char(4,46334).
+char(3,46335).
+char(9,46336).
+char(m,46337).
+char(o,46338).
+char(o,46339).
+char(m,46340).
+char(o,46341).
+char(o,46342).
+char(p,46343).
+char(o,46344).
+char(o,46345).
+char(o,46346).
+char(m,46347).
+char(o,46348).
+char(p,46349).
+char(9,46350).
+char(5,46351).
+char(2,46352).
+char(0,46353).
+char(c,46354).
+char(m,46355).
+char(o,46356).
+char(o,46357).
+char(m,46358).
+char(o,46359).
+char(p,46360).
+char(4,46361).
+char(1,46362).
+char(0,46363).
+char(6,46364).
+char(p,46365).
+char(o,46366).
+char(7,46367).
+char(9,46368).
+char(6,46369).
+char(c,46370).
+char(p,46371).
+char(o,46372).
+char(m,46373).
+char(o,46374).
+char(7,46375).
+char(9,46376).
+char(2,46377).
+char(4,46378).
+char(c,46379).
+char(c,46380).
+char(p,46381).
+char(3,46382).
+char(0,46383).
+char(1,46384).
+char(7,46385).
+char(c,46386).
+char(p,46387).
+char(o,46388).
+char(p,46389).
+char(6,46390).
+char(8,46391).
+char(2,46392).
+char(8,46393).
+char(m,46394).
+char(o,46395).
+char(p,46396).
+char(o,46397).
+char(o,46398).
+char(p,46399).
+char(o,46400).
+char(m,46401).
+char(1,46402).
+char(1,46403).
+char(3,46404).
+char(0,46405).
+char(c,46406).
+char(m,46407).
+char(o,46408).
+char(m,46409).
+char(o,46410).
+char(p,46411).
+char(7,46412).
+char(0,46413).
+char(7,46414).
+char(6,46415).
+char(c,46416).
+char(m,46417).
+char(2,46418).
+char(8,46419).
+char(0,46420).
+char(0,46421).
+char(c,46422).
+char(c,46423).
+char(m,46424).
+char(8,46425).
+char(6,46426).
+char(0,46427).
+char(9,46428).
+char(c,46429).
+char(c,46430).
+char(m,46431).
+char(2,46432).
+char(4,46433).
+char(m,46434).
+char(o,46435).
+char(p,46436).
+char(4,46437).
+char(4,46438).
+char(6,46439).
+char(4,46440).
+char(m,46441).
+char(5,46442).
+char(6,46443).
+char(1,46444).
+char(9,46445).
+char(m,46446).
+char(o,46447).
+char(o,46448).
+char(p,46449).
+char(3,46450).
+char(5,46451).
+char(7,46452).
+char(4,46453).
+char(m,46454).
+char(o,46455).
+char(m,46456).
+char(o,46457).
+char(m,46458).
+char(4,46459).
+char(1,46460).
+char(9,46461).
+char(7,46462).
+char(c,46463).
+char(m,46464).
+char(3,46465).
+char(7,46466).
+char(1,46467).
+char(9,46468).
+char(c,46469).
+char(c,46470).
+char(m,46471).
+char(7,46472).
+char(7,46473).
+char(6,46474).
+char(3,46475).
+char(c,46476).
+char(p,46477).
+char(o,46478).
+char(o,46479).
+char(p,46480).
+char(4,46481).
+char(5,46482).
+char(0,46483).
+char(5,46484).
+char(c,46485).
+char(c,46486).
+char(m,46487).
+char(o,46488).
+char(o,46489).
+char(p,46490).
+char(o,46491).
+char(5,46492).
+char(4,46493).
+char(0,46494).
+char(1,46495).
+char(c,46496).
+char(p,46497).
+char(5,46498).
+char(9,46499).
+char(3,46500).
+char(0,46501).
+char(m,46502).
+char(9,46503).
+char(2,46504).
+char(7,46505).
+char(2,46506).
+char(m,46507).
+char(o,46508).
+char(o,46509).
+char(m,46510).
+char(o,46511).
+char(p,46512).
+char(o,46513).
+char(o,46514).
+char(o,46515).
+char(4,46516).
+char(9,46517).
+char(6,46518).
+char(c,46519).
+char(c,46520).
+char(p,46521).
+char(4,46522).
+char(7,46523).
+char(7,46524).
+char(3,46525).
+char(p,46526).
+char(6,46527).
+char(4,46528).
+char(1,46529).
+char(2,46530).
+char(p,46531).
+char(2,46532).
+char(7,46533).
+char(2,46534).
+char(2,46535).
+char(c,46536).
+char(c,46537).
+char(p,46538).
+char(3,46539).
+char(1,46540).
+char(c,46541).
+char(m,46542).
+char(7,46543).
+char(8,46544).
+char(7,46545).
+char(7,46546).
+char(c,46547).
+char(p,46548).
+char(1,46549).
+char(4,46550).
+char(9,46551).
+char(7,46552).
+char(c,46553).
+char(p,46554).
+char(3,46555).
+char(6,46556).
+char(5,46557).
+char(4,46558).
+char(c,46559).
+char(c,46560).
+char(p,46561).
+char(o,46562).
+char(m,46563).
+char(o,46564).
+char(p,46565).
+char(7,46566).
+char(5,46567).
+char(0,46568).
+char(1,46569).
+char(m,46570).
+char(o,46571).
+char(8,46572).
+char(3,46573).
+char(7,46574).
+char(9,46575).
+char(c,46576).
+char(m,46577).
+char(o,46578).
+char(o,46579).
+char(o,46580).
+char(m,46581).
+char(o,46582).
+char(m,46583).
+char(3,46584).
+char(1,46585).
+char(1,46586).
+char(5,46587).
+char(c,46588).
+char(m,46589).
+char(o,46590).
+char(o,46591).
+char(o,46592).
+char(o,46593).
+char(o,46594).
+char(5,46595).
+char(2,46596).
+char(3,46597).
+char(6,46598).
+char(m,46599).
+char(1,46600).
+char(5,46601).
+char(4,46602).
+char(p,46603).
+char(o,46604).
+char(m,46605).
+char(7,46606).
+char(9,46607).
+char(2,46608).
+char(5,46609).
+char(c,46610).
+char(m,46611).
+char(2,46612).
+char(1,46613).
+char(6,46614).
+char(0,46615).
+char(p,46616).
+char(o,46617).
+char(o,46618).
+char(p,46619).
+char(o,46620).
+char(p,46621).
+char(o,46622).
+char(m,46623).
+char(o,46624).
+char(m,46625).
+char(o,46626).
+char(m,46627).
+char(4,46628).
+char(1,46629).
+char(0,46630).
+char(9,46631).
+char(c,46632).
+char(p,46633).
+char(1,46634).
+char(7,46635).
+char(2,46636).
+char(2,46637).
+char(p,46638).
+char(5,46639).
+char(3,46640).
+char(3,46641).
+char(5,46642).
+char(c,46643).
+char(c,46644).
+char(c,46645).
+char(c,46646).
+char(c,46647).
+char(m,46648).
+char(7,46649).
+char(2,46650).
+char(9,46651).
+char(0,46652).
+char(c,46653).
+char(p,46654).
+char(3,46655).
+char(0,46656).
+char(6,46657).
+char(p,46658).
+char(o,46659).
+char(p,46660).
+char(o,46661).
+char(p,46662).
+char(9,46663).
+char(3,46664).
+char(3,46665).
+char(7,46666).
+char(p,46667).
+char(o,46668).
+char(p,46669).
+char(o,46670).
+char(m,46671).
+char(o,46672).
+char(m,46673).
+char(o,46674).
+char(m,46675).
+char(o,46676).
+char(m,46677).
+char(5,46678).
+char(5,46679).
+char(8,46680).
+char(5,46681).
+char(c,46682).
+char(p,46683).
+char(3,46684).
+char(6,46685).
+char(2,46686).
+char(9,46687).
+char(m,46688).
+char(o,46689).
+char(m,46690).
+char(3,46691).
+char(9,46692).
+char(3,46693).
+char(0,46694).
+char(p,46695).
+char(o,46696).
+char(o,46697).
+char(5,46698).
+char(7,46699).
+char(1,46700).
+char(9,46701).
+char(m,46702).
+char(o,46703).
+char(p,46704).
+char(9,46705).
+char(8,46706).
+char(6,46707).
+char(9,46708).
+char(c,46709).
+char(c,46710).
+char(m,46711).
+char(o,46712).
+char(p,46713).
+char(5,46714).
+char(6,46715).
+char(9,46716).
+char(7,46717).
+char(c,46718).
+char(p,46719).
+char(9,46720).
+char(1,46721).
+char(7,46722).
+char(9,46723).
+char(c,46724).
+char(p,46725).
+char(o,46726).
+char(m,46727).
+char(o,46728).
+char(5,46729).
+char(2,46730).
+char(4,46731).
+char(7,46732).
+char(c,46733).
+char(c,46734).
+char(m,46735).
+char(7,46736).
+char(8,46737).
+char(8,46738).
+char(8,46739).
+char(m,46740).
+char(o,46741).
+char(p,46742).
+char(o,46743).
+char(o,46744).
+char(m,46745).
+char(7,46746).
+char(6,46747).
+char(1,46748).
+char(9,46749).
+char(m,46750).
+char(o,46751).
+char(4,46752).
+char(2,46753).
+char(9,46754).
+char(1,46755).
+char(m,46756).
+char(2,46757).
+char(6,46758).
+char(2,46759).
+char(1,46760).
+char(c,46761).
+char(c,46762).
+char(c,46763).
+char(c,46764).
+char(c,46765).
+char(c,46766).
+char(c,46767).
+char(c,46768).
+char(c,46769).
+char(m,46770).
+char(o,46771).
+char(p,46772).
+char(o,46773).
+char(p,46774).
+char(o,46775).
+char(m,46776).
+char(o,46777).
+char(5,46778).
+char(5,46779).
+char(1,46780).
+char(9,46781).
+char(c,46782).
+char(p,46783).
+char(o,46784).
+char(m,46785).
+char(o,46786).
+char(m,46787).
+char(o,46788).
+char(4,46789).
+char(0,46790).
+char(2,46791).
+char(2,46792).
+char(m,46793).
+char(5,46794).
+char(2,46795).
+char(2,46796).
+char(2,46797).
+char(c,46798).
+char(c,46799).
+char(c,46800).
+char(c,46801).
+char(p,46802).
+char(8,46803).
+char(4,46804).
+char(9,46805).
+char(4,46806).
+char(c,46807).
+char(m,46808).
+char(o,46809).
+char(m,46810).
+char(3,46811).
+char(8,46812).
+char(9,46813).
+char(2,46814).
+char(p,46815).
+char(o,46816).
+char(p,46817).
+char(o,46818).
+char(m,46819).
+char(6,46820).
+char(3,46821).
+char(2,46822).
+char(m,46823).
+char(o,46824).
+char(p,46825).
+char(1,46826).
+char(3,46827).
+char(3,46828).
+char(0,46829).
+char(c,46830).
+char(m,46831).
+char(2,46832).
+char(6,46833).
+char(6,46834).
+char(0,46835).
+char(m,46836).
+char(6,46837).
+char(9,46838).
+char(8,46839).
+char(0,46840).
+char(c,46841).
+char(m,46842).
+char(7,46843).
+char(5,46844).
+char(8,46845).
+char(2,46846).
+char(c,46847).
+char(c,46848).
+char(c,46849).
+char(c,46850).
+char(c,46851).
+char(c,46852).
+char(m,46853).
+char(o,46854).
+char(m,46855).
+char(o,46856).
+char(9,46857).
+char(8,46858).
+char(2,46859).
+char(7,46860).
+char(m,46861).
+char(4,46862).
+char(9,46863).
+char(1,46864).
+char(6,46865).
+char(m,46866).
+char(6,46867).
+char(0,46868).
+char(0,46869).
+char(1,46870).
+char(p,46871).
+char(4,46872).
+char(7,46873).
+char(7,46874).
+char(0,46875).
+char(c,46876).
+char(p,46877).
+char(o,46878).
+char(m,46879).
+char(1,46880).
+char(7,46881).
+char(7,46882).
+char(3,46883).
+char(c,46884).
+char(m,46885).
+char(o,46886).
+char(5,46887).
+char(9,46888).
+char(2,46889).
+char(4,46890).
+char(c,46891).
+char(c,46892).
+char(c,46893).
+char(p,46894).
+char(4,46895).
+char(2,46896).
+char(4,46897).
+char(0,46898).
+char(m,46899).
+char(9,46900).
+char(4,46901).
+char(5,46902).
+char(p,46903).
+char(2,46904).
+char(4,46905).
+char(6,46906).
+char(c,46907).
+char(p,46908).
+char(o,46909).
+char(p,46910).
+char(o,46911).
+char(3,46912).
+char(8,46913).
+char(5,46914).
+char(3,46915).
+char(c,46916).
+char(c,46917).
+char(m,46918).
+char(8,46919).
+char(4,46920).
+char(4,46921).
+char(5,46922).
+char(m,46923).
+char(1,46924).
+char(9,46925).
+char(3,46926).
+char(0,46927).
+char(p,46928).
+char(4,46929).
+char(7,46930).
+char(7,46931).
+char(0,46932).
+char(c,46933).
+char(c,46934).
+char(c,46935).
+char(c,46936).
+char(c,46937).
+char(m,46938).
+char(o,46939).
+char(p,46940).
+char(5,46941).
+char(4,46942).
+char(8,46943).
+char(8,46944).
+char(c,46945).
+char(c,46946).
+char(m,46947).
+char(o,46948).
+char(m,46949).
+char(3,46950).
+char(6,46951).
+char(6,46952).
+char(3,46953).
+char(c,46954).
+char(c,46955).
+char(p,46956).
+char(o,46957).
+char(m,46958).
+char(3,46959).
+char(5,46960).
+char(7,46961).
+char(c,46962).
+char(m,46963).
+char(o,46964).
+char(m,46965).
+char(5,46966).
+char(8,46967).
+char(4,46968).
+char(1,46969).
+char(c,46970).
+char(c,46971).
+char(c,46972).
+char(c,46973).
+char(c,46974).
+char(m,46975).
+char(o,46976).
+char(m,46977).
+char(o,46978).
+char(p,46979).
+char(o,46980).
+char(m,46981).
+char(o,46982).
+char(p,46983).
+char(8,46984).
+char(7,46985).
+char(8,46986).
+char(7,46987).
+char(m,46988).
+char(7,46989).
+char(1,46990).
+char(8,46991).
+char(8,46992).
+char(m,46993).
+char(7,46994).
+char(6,46995).
+char(6,46996).
+char(2,46997).
+char(p,46998).
+char(o,46999).
+char(o,47000).
+char(6,47001).
+char(2,47002).
+char(1,47003).
+char(1,47004).
+char(m,47005).
+char(o,47006).
+char(o,47007).
+char(p,47008).
+char(o,47009).
+char(o,47010).
+char(m,47011).
+char(o,47012).
+char(2,47013).
+char(5,47014).
+char(7,47015).
+char(4,47016).
+char(c,47017).
+char(p,47018).
+char(5,47019).
+char(1,47020).
+char(5,47021).
+char(0,47022).
+char(p,47023).
+char(9,47024).
+char(9,47025).
+char(3,47026).
+char(3,47027).
+char(p,47028).
+char(7,47029).
+char(9,47030).
+char(1,47031).
+char(2,47032).
+char(c,47033).
+char(c,47034).
+char(c,47035).
+char(p,47036).
+char(o,47037).
+char(5,47038).
+char(4,47039).
+char(3,47040).
+char(c,47041).
+char(c,47042).
+char(p,47043).
+char(8,47044).
+char(4,47045).
+char(7,47046).
+char(4,47047).
+char(c,47048).
+char(c,47049).
+char(c,47050).
+char(c,47051).
+char(m,47052).
+char(9,47053).
+char(9,47054).
+char(0,47055).
+char(8,47056).
+char(m,47057).
+char(8,47058).
+char(5,47059).
+char(1,47060).
+char(8,47061).
+char(m,47062).
+char(o,47063).
+char(m,47064).
+char(o,47065).
+char(o,47066).
+char(7,47067).
+char(1,47068).
+char(2,47069).
+char(5,47070).
+char(m,47071).
+char(o,47072).
+char(5,47073).
+char(0,47074).
+char(0,47075).
+char(6,47076).
+char(m,47077).
+char(o,47078).
+char(p,47079).
+char(4,47080).
+char(3,47081).
+char(c,47082).
+char(p,47083).
+char(9,47084).
+char(7,47085).
+char(0,47086).
+char(0,47087).
+char(c,47088).
+char(m,47089).
+char(o,47090).
+char(m,47091).
+char(o,47092).
+char(7,47093).
+char(4,47094).
+char(1,47095).
+char(7,47096).
+char(p,47097).
+char(o,47098).
+char(m,47099).
+char(o,47100).
+char(m,47101).
+char(o,47102).
+char(m,47103).
+char(o,47104).
+char(m,47105).
+char(5,47106).
+char(6,47107).
+char(2,47108).
+char(8,47109).
+char(c,47110).
+char(c,47111).
+char(c,47112).
+char(c,47113).
+char(m,47114).
+char(3,47115).
+char(7,47116).
+char(7,47117).
+char(2,47118).
+char(m,47119).
+char(3,47120).
+char(1,47121).
+char(8,47122).
+char(2,47123).
+char(p,47124).
+char(o,47125).
+char(2,47126).
+char(0,47127).
+char(7,47128).
+char(7,47129).
+char(c,47130).
+char(p,47131).
+char(o,47132).
+char(m,47133).
+char(o,47134).
+char(p,47135).
+char(o,47136).
+char(2,47137).
+char(1,47138).
+char(2,47139).
+char(3,47140).
+char(c,47141).
+char(p,47142).
+char(o,47143).
+char(o,47144).
+char(o,47145).
+char(4,47146).
+char(3,47147).
+char(5,47148).
+char(1,47149).
+char(c,47150).
+char(p,47151).
+char(7,47152).
+char(0,47153).
+char(5,47154).
+char(1,47155).
+char(c,47156).
+char(p,47157).
+char(o,47158).
+char(o,47159).
+char(p,47160).
+char(9,47161).
+char(9,47162).
+char(3,47163).
+char(3,47164).
+char(m,47165).
+char(o,47166).
+char(p,47167).
+char(5,47168).
+char(8,47169).
+char(7,47170).
+char(8,47171).
+char(m,47172).
+char(8,47173).
+char(5,47174).
+char(8,47175).
+char(2,47176).
+char(c,47177).
+char(p,47178).
+char(4,47179).
+char(5,47180).
+char(3,47181).
+char(7,47182).
+char(m,47183).
+char(5,47184).
+char(3,47185).
+char(7,47186).
+char(7,47187).
+char(c,47188).
+char(c,47189).
+char(p,47190).
+char(o,47191).
+char(m,47192).
+char(o,47193).
+char(p,47194).
+char(7,47195).
+char(4,47196).
+char(2,47197).
+char(c,47198).
+char(p,47199).
+char(o,47200).
+char(o,47201).
+char(m,47202).
+char(5,47203).
+char(6,47204).
+char(5,47205).
+char(3,47206).
+char(p,47207).
+char(o,47208).
+char(7,47209).
+char(6,47210).
+char(3,47211).
+char(4,47212).
+char(c,47213).
+char(m,47214).
+char(3,47215).
+char(0,47216).
+char(1,47217).
+char(c,47218).
+char(c,47219).
+char(p,47220).
+char(o,47221).
+char(m,47222).
+char(6,47223).
+char(2,47224).
+char(1,47225).
+char(2,47226).
+char(c,47227).
+char(p,47228).
+char(o,47229).
+char(o,47230).
+char(m,47231).
+char(o,47232).
+char(m,47233).
+char(5,47234).
+char(6,47235).
+char(5,47236).
+char(8,47237).
+char(c,47238).
+char(p,47239).
+char(6,47240).
+char(0,47241).
+char(9,47242).
+char(1,47243).
+char(c,47244).
+char(p,47245).
+char(5,47246).
+char(9,47247).
+char(4,47248).
+char(4,47249).
+char(c,47250).
+char(c,47251).
+char(p,47252).
+char(1,47253).
+char(9,47254).
+char(1,47255).
+char(9,47256).
+char(m,47257).
+char(o,47258).
+char(2,47259).
+char(4,47260).
+char(7,47261).
+char(4,47262).
+char(c,47263).
+char(p,47264).
+char(o,47265).
+char(p,47266).
+char(1,47267).
+char(8,47268).
+char(5,47269).
+char(9,47270).
+char(m,47271).
+char(3,47272).
+char(0,47273).
+char(1,47274).
+char(c,47275).
+char(c,47276).
+char(c,47277).
+char(c,47278).
+char(c,47279).
+char(c,47280).
+char(p,47281).
+char(o,47282).
+char(8,47283).
+char(2,47284).
+char(0,47285).
+char(8,47286).
+char(c,47287).
+char(m,47288).
+char(3,47289).
+char(0,47290).
+char(6,47291).
+char(8,47292).
+char(p,47293).
+char(6,47294).
+char(9,47295).
+char(9,47296).
+char(p,47297).
+char(o,47298).
+char(p,47299).
+char(o,47300).
+char(o,47301).
+char(9,47302).
+char(8,47303).
+char(5,47304).
+char(5,47305).
+char(c,47306).
+char(p,47307).
+char(6,47308).
+char(7,47309).
+char(5,47310).
+char(4,47311).
+char(c,47312).
+char(m,47313).
+char(8,47314).
+char(5,47315).
+char(0,47316).
+char(9,47317).
+char(m,47318).
+char(o,47319).
+char(p,47320).
+char(o,47321).
+char(m,47322).
+char(9,47323).
+char(0,47324).
+char(3,47325).
+char(7,47326).
+char(p,47327).
+char(o,47328).
+char(p,47329).
+char(2,47330).
+char(2,47331).
+char(0,47332).
+char(5,47333).
+char(c,47334).
+char(c,47335).
+char(m,47336).
+char(o,47337).
+char(p,47338).
+char(o,47339).
+char(m,47340).
+char(8,47341).
+char(1,47342).
+char(7,47343).
+char(9,47344).
+char(p,47345).
+char(1,47346).
+char(9,47347).
+char(9,47348).
+char(9,47349).
+char(m,47350).
+char(o,47351).
+char(p,47352).
+char(5,47353).
+char(3,47354).
+char(2,47355).
+char(5,47356).
+char(c,47357).
+char(p,47358).
+char(7,47359).
+char(4,47360).
+char(5,47361).
+char(5,47362).
+char(p,47363).
+char(5,47364).
+char(6,47365).
+char(3,47366).
+char(4,47367).
+char(p,47368).
+char(o,47369).
+char(m,47370).
+char(1,47371).
+char(7,47372).
+char(3,47373).
+char(6,47374).
+char(c,47375).
+char(c,47376).
+char(m,47377).
+char(2,47378).
+char(2,47379).
+char(7,47380).
+char(0,47381).
+char(p,47382).
+char(6,47383).
+char(3,47384).
+char(3,47385).
+char(1,47386).
+char(c,47387).
+char(p,47388).
+char(o,47389).
+char(7,47390).
+char(4,47391).
+char(1,47392).
+char(9,47393).
+char(c,47394).
+char(c,47395).
+char(c,47396).
+char(m,47397).
+char(1,47398).
+char(7,47399).
+char(3,47400).
+char(8,47401).
+char(p,47402).
+char(7,47403).
+char(6,47404).
+char(3,47405).
+char(7,47406).
+char(m,47407).
+char(4,47408).
+char(3,47409).
+char(1,47410).
+char(7,47411).
+char(p,47412).
+char(o,47413).
+char(o,47414).
+char(o,47415).
+char(o,47416).
+char(o,47417).
+char(o,47418).
+char(p,47419).
+char(3,47420).
+char(4,47421).
+char(5,47422).
+char(1,47423).
+char(m,47424).
+char(5,47425).
+char(8,47426).
+char(0,47427).
+char(7,47428).
+char(m,47429).
+char(8,47430).
+char(3,47431).
+char(7,47432).
+char(1,47433).
+char(m,47434).
+char(3,47435).
+char(2,47436).
+char(2,47437).
+char(9,47438).
+char(c,47439).
+char(p,47440).
+char(o,47441).
+char(m,47442).
+char(9,47443).
+char(7,47444).
+char(2,47445).
+char(0,47446).
+char(c,47447).
+char(p,47448).
+char(o,47449).
+char(2,47450).
+char(6,47451).
+char(8,47452).
+char(0,47453).
+char(m,47454).
+char(o,47455).
+char(o,47456).
+char(2,47457).
+char(1,47458).
+char(7,47459).
+char(3,47460).
+char(m,47461).
+char(o,47462).
+char(8,47463).
+char(7,47464).
+char(8,47465).
+char(4,47466).
+char(c,47467).
+char(m,47468).
+char(4,47469).
+char(6,47470).
+char(9,47471).
+char(9,47472).
+char(c,47473).
+char(c,47474).
+char(c,47475).
+char(c,47476).
+char(c,47477).
+char(p,47478).
+char(o,47479).
+char(8,47480).
+char(6,47481).
+char(5,47482).
+char(0,47483).
+char(c,47484).
+char(p,47485).
+char(o,47486).
+char(7,47487).
+char(0,47488).
+char(4,47489).
+char(8,47490).
+char(p,47491).
+char(o,47492).
+char(o,47493).
+char(p,47494).
+char(o,47495).
+char(p,47496).
+char(o,47497).
+char(m,47498).
+char(1,47499).
+char(7,47500).
+char(3,47501).
+char(1,47502).
+char(p,47503).
+char(5,47504).
+char(1,47505).
+char(2,47506).
+char(9,47507).
+char(c,47508).
+char(c,47509).
+char(c,47510).
+char(p,47511).
+char(3,47512).
+char(2,47513).
+char(3,47514).
+char(3,47515).
+char(c,47516).
+char(p,47517).
+char(o,47518).
+char(p,47519).
+char(7,47520).
+char(3,47521).
+char(8,47522).
+char(5,47523).
+char(c,47524).
+char(c,47525).
+char(m,47526).
+char(o,47527).
+char(p,47528).
+char(o,47529).
+char(m,47530).
+char(2,47531).
+char(8,47532).
+char(0,47533).
+char(p,47534).
+char(1,47535).
+char(2,47536).
+char(7,47537).
+char(m,47538).
+char(o,47539).
+char(p,47540).
+char(o,47541).
+char(p,47542).
+char(o,47543).
+char(p,47544).
+char(6,47545).
+char(4,47546).
+char(7,47547).
+char(0,47548).
+char(c,47549).
+char(p,47550).
+char(o,47551).
+char(8,47552).
+char(0,47553).
+char(8,47554).
+char(3,47555).
+char(c,47556).
+char(m,47557).
+char(o,47558).
+char(m,47559).
+char(7,47560).
+char(0,47561).
+char(1,47562).
+char(4,47563).
+char(p,47564).
+char(o,47565).
+char(p,47566).
+char(5,47567).
+char(0,47568).
+char(7,47569).
+char(7,47570).
+char(c,47571).
+char(c,47572).
+char(c,47573).
+char(c,47574).
+char(c,47575).
+char(m,47576).
+char(3,47577).
+char(2,47578).
+char(9,47579).
+char(3,47580).
+char(p,47581).
+char(6,47582).
+char(1,47583).
+char(2,47584).
+char(2,47585).
+char(p,47586).
+char(5,47587).
+char(1,47588).
+char(0,47589).
+char(2,47590).
+char(c,47591).
+char(c,47592).
+char(c,47593).
+char(c,47594).
+char(c,47595).
+char(c,47596).
+char(m,47597).
+char(o,47598).
+char(o,47599).
+char(4,47600).
+char(3,47601).
+char(6,47602).
+char(8,47603).
+char(m,47604).
+char(o,47605).
+char(p,47606).
+char(5,47607).
+char(6,47608).
+char(6,47609).
+char(2,47610).
+char(c,47611).
+char(m,47612).
+char(2,47613).
+char(9,47614).
+char(7,47615).
+char(2,47616).
+char(p,47617).
+char(9,47618).
+char(6,47619).
+char(9,47620).
+char(2,47621).
+char(p,47622).
+char(4,47623).
+char(9,47624).
+char(5,47625).
+char(7,47626).
+char(c,47627).
+char(c,47628).
+char(m,47629).
+char(1,47630).
+char(3,47631).
+char(2,47632).
+char(4,47633).
+char(c,47634).
+char(c,47635).
+char(c,47636).
+char(c,47637).
+char(m,47638).
+char(6,47639).
+char(0,47640).
+char(c,47641).
+char(c,47642).
+char(c,47643).
+char(m,47644).
+char(o,47645).
+char(m,47646).
+char(9,47647).
+char(2,47648).
+char(0,47649).
+char(3,47650).
+char(c,47651).
+char(p,47652).
+char(o,47653).
+char(m,47654).
+char(o,47655).
+char(p,47656).
+char(1,47657).
+char(6,47658).
+char(7,47659).
+char(5,47660).
+char(m,47661).
+char(5,47662).
+char(7,47663).
+char(3,47664).
+char(0,47665).
+char(p,47666).
+char(o,47667).
+char(m,47668).
+char(1,47669).
+char(2,47670).
+char(4,47671).
+char(5,47672).
+char(c,47673).
+char(m,47674).
+char(5,47675).
+char(0,47676).
+char(6,47677).
+char(6,47678).
+char(p,47679).
+char(o,47680).
+char(1,47681).
+char(7,47682).
+char(0,47683).
+char(9,47684).
+char(c,47685).
+char(c,47686).
+char(m,47687).
+char(o,47688).
+char(p,47689).
+char(o,47690).
+char(o,47691).
+char(7,47692).
+char(8,47693).
+char(9,47694).
+char(5,47695).
+char(c,47696).
+char(m,47697).
+char(7,47698).
+char(0,47699).
+char(6,47700).
+char(2,47701).
+char(m,47702).
+char(o,47703).
+char(o,47704).
+char(o,47705).
+char(p,47706).
+char(o,47707).
+char(m,47708).
+char(o,47709).
+char(m,47710).
+char(o,47711).
+char(4,47712).
+char(8,47713).
+char(3,47714).
+char(2,47715).
+char(c,47716).
+char(c,47717).
+char(p,47718).
+char(o,47719).
+char(o,47720).
+char(m,47721).
+char(o,47722).
+char(p,47723).
+char(o,47724).
+char(m,47725).
+char(9,47726).
+char(3,47727).
+char(2,47728).
+char(3,47729).
+char(c,47730).
+char(p,47731).
+char(o,47732).
+char(p,47733).
+char(o,47734).
+char(m,47735).
+char(o,47736).
+char(m,47737).
+char(9,47738).
+char(0,47739).
+char(6,47740).
+char(9,47741).
+char(c,47742).
+char(p,47743).
+char(o,47744).
+char(p,47745).
+char(o,47746).
+char(p,47747).
+char(o,47748).
+char(m,47749).
+char(o,47750).
+char(o,47751).
+char(o,47752).
+char(2,47753).
+char(2,47754).
+char(7,47755).
+char(c,47756).
+char(m,47757).
+char(o,47758).
+char(9,47759).
+char(2,47760).
+char(8,47761).
+char(1,47762).
+char(c,47763).
+char(m,47764).
+char(6,47765).
+char(8,47766).
+char(6,47767).
+char(2,47768).
+char(m,47769).
+char(o,47770).
+char(m,47771).
+char(o,47772).
+char(p,47773).
+char(o,47774).
+char(p,47775).
+char(o,47776).
+char(m,47777).
+char(o,47778).
+char(p,47779).
+char(6,47780).
+char(9,47781).
+char(8,47782).
+char(0,47783).
+char(p,47784).
+char(o,47785).
+char(o,47786).
+char(m,47787).
+char(o,47788).
+char(p,47789).
+char(o,47790).
+char(9,47791).
+char(8,47792).
+char(3,47793).
+char(2,47794).
+char(c,47795).
+char(p,47796).
+char(o,47797).
+char(m,47798).
+char(8,47799).
+char(7,47800).
+char(6,47801).
+char(9,47802).
+char(p,47803).
+char(7,47804).
+char(8,47805).
+char(0,47806).
+char(0,47807).
+char(p,47808).
+char(2,47809).
+char(4,47810).
+char(3,47811).
+char(3,47812).
+char(c,47813).
+char(p,47814).
+char(o,47815).
+char(m,47816).
+char(6,47817).
+char(1,47818).
+char(7,47819).
+char(2,47820).
+char(c,47821).
+char(c,47822).
+char(c,47823).
+char(c,47824).
+char(c,47825).
+char(m,47826).
+char(o,47827).
+char(o,47828).
+char(m,47829).
+char(9,47830).
+char(2,47831).
+char(7,47832).
+char(1,47833).
+char(m,47834).
+char(7,47835).
+char(0,47836).
+char(6,47837).
+char(0,47838).
+char(c,47839).
+char(c,47840).
+char(c,47841).
+char(m,47842).
+char(8,47843).
+char(7,47844).
+char(0,47845).
+char(5,47846).
+char(c,47847).
+char(m,47848).
+char(6,47849).
+char(8,47850).
+char(8,47851).
+char(8,47852).
+char(p,47853).
+char(o,47854).
+char(9,47855).
+char(7,47856).
+char(3,47857).
+char(5,47858).
+char(c,47859).
+char(m,47860).
+char(7,47861).
+char(2,47862).
+char(5,47863).
+char(7,47864).
+char(c,47865).
+char(c,47866).
+char(c,47867).
+char(c,47868).
+char(c,47869).
+char(c,47870).
+char(c,47871).
+char(c,47872).
+char(m,47873).
+char(7,47874).
+char(8,47875).
+char(5,47876).
+char(8,47877).
+char(m,47878).
+char(9,47879).
+char(0,47880).
+char(3,47881).
+char(4,47882).
+char(p,47883).
+char(o,47884).
+char(m,47885).
+char(o,47886).
+char(p,47887).
+char(4,47888).
+char(7,47889).
+char(7,47890).
+char(9,47891).
+char(p,47892).
+char(4,47893).
+char(9,47894).
+char(4,47895).
+char(9,47896).
+char(p,47897).
+char(2,47898).
+char(8,47899).
+char(3,47900).
+char(p,47901).
+char(o,47902).
+char(m,47903).
+char(6,47904).
+char(4,47905).
+char(1,47906).
+char(6,47907).
+char(c,47908).
+char(m,47909).
+char(6,47910).
+char(2,47911).
+char(9,47912).
+char(9,47913).
+char(c,47914).
+char(c,47915).
+char(p,47916).
+char(9,47917).
+char(9,47918).
+char(6,47919).
+char(4,47920).
+char(m,47921).
+char(7,47922).
+char(3,47923).
+char(3,47924).
+char(7,47925).
+char(m,47926).
+char(o,47927).
+char(o,47928).
+char(o,47929).
+char(9,47930).
+char(7,47931).
+char(0,47932).
+char(6,47933).
+char(c,47934).
+char(m,47935).
+char(3,47936).
+char(5,47937).
+char(5,47938).
+char(9,47939).
+char(c,47940).
+char(m,47941).
+char(o,47942).
+char(p,47943).
+char(8,47944).
+char(4,47945).
+char(1,47946).
+char(2,47947).
+char(c,47948).
+char(c,47949).
+char(c,47950).
+char(m,47951).
+char(4,47952).
+char(3,47953).
+char(3,47954).
+char(9,47955).
+char(p,47956).
+char(o,47957).
+char(5,47958).
+char(2,47959).
+char(9,47960).
+char(1,47961).
+char(c,47962).
+char(c,47963).
+char(c,47964).
+char(p,47965).
+char(o,47966).
+char(1,47967).
+char(8,47968).
+char(3,47969).
+char(1,47970).
+char(m,47971).
+char(2,47972).
+char(2,47973).
+char(5,47974).
+char(0,47975).
+char(p,47976).
+char(7,47977).
+char(4,47978).
+char(2,47979).
+char(5,47980).
+char(c,47981).
+char(m,47982).
+char(5,47983).
+char(0,47984).
+char(0,47985).
+char(9,47986).
+char(m,47987).
+char(6,47988).
+char(2,47989).
+char(3,47990).
+char(2,47991).
+char(c,47992).
+char(c,47993).
+char(p,47994).
+char(7,47995).
+char(9,47996).
+char(1,47997).
+char(8,47998).
+char(p,47999).
+char(4,48000).
+char(4,48001).
+char(2,48002).
+char(7,48003).
+char(m,48004).
+char(3,48005).
+char(0,48006).
+char(7,48007).
+char(3,48008).
+char(c,48009).
+char(m,48010).
+char(o,48011).
+char(p,48012).
+char(3,48013).
+char(2,48014).
+char(6,48015).
+char(c,48016).
+char(c,48017).
+char(c,48018).
+char(c,48019).
+char(c,48020).
+char(c,48021).
+char(c,48022).
+char(p,48023).
+char(8,48024).
+char(8,48025).
+char(4,48026).
+char(3,48027).
+char(c,48028).
+char(c,48029).
+char(m,48030).
+char(o,48031).
+char(p,48032).
+char(5,48033).
+char(2,48034).
+char(8,48035).
+char(2,48036).
+char(c,48037).
+char(p,48038).
+char(o,48039).
+char(m,48040).
+char(o,48041).
+char(o,48042).
+char(m,48043).
+char(o,48044).
+char(m,48045).
+char(o,48046).
+char(o,48047).
+char(m,48048).
+char(8,48049).
+char(3,48050).
+char(8,48051).
+char(0,48052).
+char(c,48053).
+char(p,48054).
+char(o,48055).
+char(p,48056).
+char(6,48057).
+char(3,48058).
+char(5,48059).
+char(0,48060).
+char(p,48061).
+char(9,48062).
+char(4,48063).
+char(2,48064).
+char(9,48065).
+char(c,48066).
+char(c,48067).
+char(p,48068).
+char(2,48069).
+char(4,48070).
+char(4,48071).
+char(6,48072).
+char(c,48073).
+char(c,48074).
+char(p,48075).
+char(5,48076).
+char(6,48077).
+char(0,48078).
+char(5,48079).
+char(p,48080).
+char(o,48081).
+char(m,48082).
+char(4,48083).
+char(5,48084).
+char(2,48085).
+char(1,48086).
+char(c,48087).
+char(m,48088).
+char(4,48089).
+char(5,48090).
+char(6,48091).
+char(3,48092).
+char(m,48093).
+char(o,48094).
+char(7,48095).
+char(3,48096).
+char(4,48097).
+char(p,48098).
+char(7,48099).
+char(9,48100).
+char(6,48101).
+char(5,48102).
+char(m,48103).
+char(o,48104).
+char(o,48105).
+char(p,48106).
+char(o,48107).
+char(m,48108).
+char(4,48109).
+char(5,48110).
+char(5,48111).
+char(4,48112).
+char(c,48113).
+char(c,48114).
+char(p,48115).
+char(6,48116).
+char(4,48117).
+char(2,48118).
+char(0,48119).
+char(c,48120).
+char(c,48121).
+char(c,48122).
+char(c,48123).
+char(m,48124).
+char(3,48125).
+char(3,48126).
+char(2,48127).
+char(2,48128).
+char(c,48129).
+char(m,48130).
+char(o,48131).
+char(p,48132).
+char(o,48133).
+char(p,48134).
+char(9,48135).
+char(4,48136).
+char(3,48137).
+char(m,48138).
+char(o,48139).
+char(p,48140).
+char(8,48141).
+char(5,48142).
+char(0,48143).
+char(9,48144).
+char(c,48145).
+char(c,48146).
+char(c,48147).
+char(c,48148).
+char(c,48149).
+char(c,48150).
+char(c,48151).
+char(c,48152).
+char(m,48153).
+char(5,48154).
+char(6,48155).
+char(6,48156).
+char(5,48157).
+char(p,48158).
+char(8,48159).
+char(4,48160).
+char(4,48161).
+char(1,48162).
+char(p,48163).
+char(o,48164).
+char(6,48165).
+char(9,48166).
+char(7,48167).
+char(p,48168).
+char(6,48169).
+char(4,48170).
+char(9,48171).
+char(8,48172).
+char(c,48173).
+char(c,48174).
+char(p,48175).
+char(6,48176).
+char(4,48177).
+char(3,48178).
+char(4,48179).
+char(c,48180).
+char(c,48181).
+char(p,48182).
+char(3,48183).
+char(1,48184).
+char(7,48185).
+char(8,48186).
+char(m,48187).
+char(4,48188).
+char(3,48189).
+char(7,48190).
+char(6,48191).
+char(p,48192).
+char(o,48193).
+char(2,48194).
+char(5,48195).
+char(1,48196).
+char(6,48197).
+char(c,48198).
+char(m,48199).
+char(4,48200).
+char(4,48201).
+char(1,48202).
+char(0,48203).
+char(p,48204).
+char(2,48205).
+char(5,48206).
+char(8,48207).
+char(5,48208).
+char(p,48209).
+char(o,48210).
+char(p,48211).
+char(o,48212).
+char(o,48213).
+char(p,48214).
+char(o,48215).
+char(p,48216).
+char(o,48217).
+char(p,48218).
+char(o,48219).
+char(p,48220).
+char(5,48221).
+char(9,48222).
+char(5,48223).
+char(7,48224).
+char(c,48225).
+char(m,48226).
+char(o,48227).
+char(p,48228).
+char(o,48229).
+char(m,48230).
+char(o,48231).
+char(m,48232).
+char(6,48233).
+char(5,48234).
+char(5,48235).
+char(8,48236).
+char(m,48237).
+char(1,48238).
+char(6,48239).
+char(2,48240).
+char(8,48241).
+char(m,48242).
+char(6,48243).
+char(3,48244).
+char(7,48245).
+char(2,48246).
+char(m,48247).
+char(o,48248).
+char(6,48249).
+char(9,48250).
+char(4,48251).
+char(8,48252).
+char(m,48253).
+char(o,48254).
+char(m,48255).
+char(7,48256).
+char(7,48257).
+char(6,48258).
+char(1,48259).
+char(m,48260).
+char(o,48261).
+char(o,48262).
+char(8,48263).
+char(8,48264).
+char(1,48265).
+char(1,48266).
+char(p,48267).
+char(o,48268).
+char(3,48269).
+char(8,48270).
+char(1,48271).
+char(7,48272).
+char(c,48273).
+char(m,48274).
+char(1,48275).
+char(6,48276).
+char(8,48277).
+char(0,48278).
+char(c,48279).
+char(m,48280).
+char(o,48281).
+char(o,48282).
+char(p,48283).
+char(o,48284).
+char(o,48285).
+char(m,48286).
+char(9,48287).
+char(5,48288).
+char(9,48289).
+char(1,48290).
+char(p,48291).
+char(3,48292).
+char(6,48293).
+char(7,48294).
+char(4,48295).
+char(m,48296).
+char(9,48297).
+char(0,48298).
+char(0,48299).
+char(7,48300).
+char(c,48301).
+char(c,48302).
+char(c,48303).
+char(m,48304).
+char(4,48305).
+char(1,48306).
+char(9,48307).
+char(5,48308).
+char(c,48309).
+char(c,48310).
+char(c,48311).
+char(c,48312).
+char(m,48313).
+char(o,48314).
+char(m,48315).
+char(o,48316).
+char(m,48317).
+char(3,48318).
+char(4,48319).
+char(4,48320).
+char(9,48321).
+char(p,48322).
+char(o,48323).
+char(2,48324).
+char(2,48325).
+char(8,48326).
+char(1,48327).
+char(m,48328).
+char(5,48329).
+char(5,48330).
+char(2,48331).
+char(7,48332).
+char(c,48333).
+char(m,48334).
+char(6,48335).
+char(8,48336).
+char(5,48337).
+char(2,48338).
+char(c,48339).
+char(m,48340).
+char(o,48341).
+char(9,48342).
+char(2,48343).
+char(6,48344).
+char(1,48345).
+char(c,48346).
+char(c,48347).
+char(c,48348).
+char(c,48349).
+char(c,48350).
+char(m,48351).
+char(o,48352).
+char(o,48353).
+char(m,48354).
+char(4,48355).
+char(0,48356).
+char(1,48357).
+char(8,48358).
+char(c,48359).
+char(c,48360).
+char(m,48361).
+char(o,48362).
+char(p,48363).
+char(7,48364).
+char(2,48365).
+char(1,48366).
+char(6,48367).
+char(c,48368).
+char(p,48369).
+char(6,48370).
+char(9,48371).
+char(9,48372).
+char(4,48373).
+char(p,48374).
+char(1,48375).
+char(5,48376).
+char(2,48377).
+char(1,48378).
+char(c,48379).
+char(p,48380).
+char(o,48381).
+char(o,48382).
+char(p,48383).
+char(1,48384).
+char(5,48385).
+char(3,48386).
+char(0,48387).
+char(p,48388).
+char(o,48389).
+char(p,48390).
+char(o,48391).
+char(8,48392).
+char(0,48393).
+char(3,48394).
+char(5,48395).
+char(c,48396).
+char(m,48397).
+char(o,48398).
+char(9,48399).
+char(0,48400).
+char(5,48401).
+char(6,48402).
+char(c,48403).
+char(c,48404).
+char(c,48405).
+char(m,48406).
+char(8,48407).
+char(6,48408).
+char(7,48409).
+char(c,48410).
+char(c,48411).
+char(m,48412).
+char(o,48413).
+char(p,48414).
+char(o,48415).
+char(p,48416).
+char(1,48417).
+char(8,48418).
+char(0,48419).
+char(6,48420).
+char(m,48421).
+char(o,48422).
+char(p,48423).
+char(o,48424).
+char(m,48425).
+char(o,48426).
+char(p,48427).
+char(o,48428).
+char(p,48429).
+char(4,48430).
+char(8,48431).
+char(3,48432).
+char(0,48433).
+char(m,48434).
+char(o,48435).
+char(m,48436).
+char(6,48437).
+char(5,48438).
+char(8,48439).
+char(7,48440).
+char(p,48441).
+char(6,48442).
+char(1,48443).
+char(3,48444).
+char(c,48445).
+char(m,48446).
+char(o,48447).
+char(4,48448).
+char(5,48449).
+char(3,48450).
+char(9,48451).
+char(c,48452).
+char(p,48453).
+char(o,48454).
+char(p,48455).
+char(o,48456).
+char(o,48457).
+char(p,48458).
+char(o,48459).
+char(p,48460).
+char(o,48461).
+char(m,48462).
+char(5,48463).
+char(3,48464).
+char(1,48465).
+char(5,48466).
+char(p,48467).
+char(o,48468).
+char(p,48469).
+char(5,48470).
+char(5,48471).
+char(3,48472).
+char(1,48473).
+char(c,48474).
+char(p,48475).
+char(8,48476).
+char(8,48477).
+char(4,48478).
+char(7,48479).
+char(c,48480).
+char(c,48481).
+char(m,48482).
+char(o,48483).
+char(p,48484).
+char(6,48485).
+char(1,48486).
+char(8,48487).
+char(4,48488).
+char(c,48489).
+char(m,48490).
+char(8,48491).
+char(4,48492).
+char(5,48493).
+char(3,48494).
+char(c,48495).
+char(c,48496).
+char(c,48497).
+char(p,48498).
+char(3,48499).
+char(8,48500).
+char(6,48501).
+char(0,48502).
+char(c,48503).
+char(c,48504).
+char(p,48505).
+char(7,48506).
+char(2,48507).
+char(7,48508).
+char(8,48509).
+char(m,48510).
+char(7,48511).
+char(7,48512).
+char(6,48513).
+char(7,48514).
+char(p,48515).
+char(1,48516).
+char(5,48517).
+char(9,48518).
+char(9,48519).
+char(m,48520).
+char(o,48521).
+char(o,48522).
+char(p,48523).
+char(o,48524).
+char(m,48525).
+char(o,48526).
+char(p,48527).
+char(o,48528).
+char(m,48529).
+char(o,48530).
+char(p,48531).
+char(o,48532).
+char(o,48533).
+char(m,48534).
+char(o,48535).
+char(p,48536).
+char(5,48537).
+char(4,48538).
+char(7,48539).
+char(2,48540).
+char(p,48541).
+char(o,48542).
+char(m,48543).
+char(8,48544).
+char(7,48545).
+char(7,48546).
+char(7,48547).
+char(c,48548).
+char(c,48549).
+char(m,48550).
+char(o,48551).
+char(m,48552).
+char(o,48553).
+char(m,48554).
+char(6,48555).
+char(5,48556).
+char(7,48557).
+char(1,48558).
+char(m,48559).
+char(o,48560).
+char(p,48561).
+char(o,48562).
+char(o,48563).
+char(p,48564).
+char(1,48565).
+char(0,48566).
+char(4,48567).
+char(c,48568).
+char(m,48569).
+char(1,48570).
+char(7,48571).
+char(2,48572).
+char(2,48573).
+char(p,48574).
+char(4,48575).
+char(0,48576).
+char(9,48577).
+char(6,48578).
+char(c,48579).
+char(c,48580).
+char(c,48581).
+char(c,48582).
+char(m,48583).
+char(o,48584).
+char(p,48585).
+char(o,48586).
+char(m,48587).
+char(o,48588).
+char(m,48589).
+char(o,48590).
+char(m,48591).
+char(8,48592).
+char(1,48593).
+char(c,48594).
+char(c,48595).
+char(m,48596).
+char(o,48597).
+char(6,48598).
+char(5,48599).
+char(4,48600).
+char(9,48601).
+char(m,48602).
+char(o,48603).
+char(p,48604).
+char(o,48605).
+char(m,48606).
+char(o,48607).
+char(m,48608).
+char(o,48609).
+char(o,48610).
+char(6,48611).
+char(9,48612).
+char(9,48613).
+char(9,48614).
+char(m,48615).
+char(1,48616).
+char(1,48617).
+char(0,48618).
+char(c,48619).
+char(c,48620).
+char(p,48621).
+char(1,48622).
+char(8,48623).
+char(2,48624).
+char(6,48625).
+char(p,48626).
+char(o,48627).
+char(2,48628).
+char(6,48629).
+char(1,48630).
+char(7,48631).
+char(m,48632).
+char(o,48633).
+char(9,48634).
+char(2,48635).
+char(8,48636).
+char(7,48637).
+char(c,48638).
+char(m,48639).
+char(4,48640).
+char(4,48641).
+char(5,48642).
+char(1,48643).
+char(c,48644).
+char(c,48645).
+char(p,48646).
+char(o,48647).
+char(o,48648).
+char(m,48649).
+char(4,48650).
+char(7,48651).
+char(1,48652).
+char(9,48653).
+char(m,48654).
+char(o,48655).
+char(8,48656).
+char(1,48657).
+char(1,48658).
+char(p,48659).
+char(8,48660).
+char(4,48661).
+char(0,48662).
+char(4,48663).
+char(c,48664).
+char(c,48665).
+char(c,48666).
+char(c,48667).
+char(c,48668).
+char(c,48669).
+char(c,48670).
+char(c,48671).
+char(c,48672).
+char(m,48673).
+char(7,48674).
+char(5,48675).
+char(5,48676).
+char(2,48677).
+char(p,48678).
+char(o,48679).
+char(m,48680).
+char(7,48681).
+char(3,48682).
+char(0,48683).
+char(9,48684).
+char(p,48685).
+char(6,48686).
+char(2,48687).
+char(4,48688).
+char(9,48689).
+char(c,48690).
+char(c,48691).
+char(c,48692).
+char(m,48693).
+char(o,48694).
+char(6,48695).
+char(0,48696).
+char(3,48697).
+char(9,48698).
+char(c,48699).
+char(c,48700).
+char(p,48701).
+char(o,48702).
+char(m,48703).
+char(o,48704).
+char(p,48705).
+char(2,48706).
+char(6,48707).
+char(4,48708).
+char(8,48709).
+char(m,48710).
+char(o,48711).
+char(m,48712).
+char(7,48713).
+char(7,48714).
+char(8,48715).
+char(4,48716).
+char(c,48717).
+char(p,48718).
+char(o,48719).
+char(p,48720).
+char(o,48721).
+char(p,48722).
+char(o,48723).
+char(m,48724).
+char(8,48725).
+char(3,48726).
+char(0,48727).
+char(2,48728).
+char(c,48729).
+char(c,48730).
+char(m,48731).
+char(o,48732).
+char(m,48733).
+char(7,48734).
+char(3,48735).
+char(1,48736).
+char(2,48737).
+char(c,48738).
+char(m,48739).
+char(4,48740).
+char(9,48741).
+char(0,48742).
+char(9,48743).
+char(c,48744).
+char(m,48745).
+char(2,48746).
+char(5,48747).
+char(1,48748).
+char(p,48749).
+char(o,48750).
+char(m,48751).
+char(4,48752).
+char(2,48753).
+char(5,48754).
+char(6,48755).
+char(m,48756).
+char(o,48757).
+char(m,48758).
+char(o,48759).
+char(o,48760).
+char(p,48761).
+char(o,48762).
+char(m,48763).
+char(o,48764).
+char(m,48765).
+char(3,48766).
+char(7,48767).
+char(5,48768).
+char(4,48769).
+char(c,48770).
+char(c,48771).
+char(m,48772).
+char(o,48773).
+char(p,48774).
+char(8,48775).
+char(9,48776).
+char(1,48777).
+char(3,48778).
+char(c,48779).
+char(c,48780).
+char(p,48781).
+char(7,48782).
+char(0,48783).
+char(6,48784).
+char(7,48785).
+char(c,48786).
+char(c,48787).
+char(p,48788).
+char(o,48789).
+char(p,48790).
+char(o,48791).
+char(o,48792).
+char(7,48793).
+char(0,48794).
+char(3,48795).
+char(8,48796).
+char(c,48797).
+char(m,48798).
+char(8,48799).
+char(2,48800).
+char(c,48801).
+char(p,48802).
+char(5,48803).
+char(3,48804).
+char(5,48805).
+char(3,48806).
+char(c,48807).
+char(p,48808).
+char(o,48809).
+char(8,48810).
+char(3,48811).
+char(8,48812).
+char(3,48813).
+char(p,48814).
+char(7,48815).
+char(9,48816).
+char(1,48817).
+char(c,48818).
+char(c,48819).
+char(p,48820).
+char(4,48821).
+char(3,48822).
+char(4,48823).
+char(2,48824).
+char(c,48825).
+char(c,48826).
+char(m,48827).
+char(8,48828).
+char(8,48829).
+char(7,48830).
+char(5,48831).
+char(m,48832).
+char(o,48833).
+char(7,48834).
+char(0,48835).
+char(0,48836).
+char(9,48837).
+char(p,48838).
+char(o,48839).
+char(3,48840).
+char(0,48841).
+char(0,48842).
+char(2,48843).
+char(c,48844).
+char(c,48845).
+char(c,48846).
+char(c,48847).
+char(c,48848).
+char(c,48849).
+char(p,48850).
+char(o,48851).
+char(p,48852).
+char(9,48853).
+char(7,48854).
+char(0,48855).
+char(0,48856).
+char(c,48857).
+char(c,48858).
+char(p,48859).
+char(o,48860).
+char(p,48861).
+char(o,48862).
+char(m,48863).
+char(o,48864).
+char(3,48865).
+char(9,48866).
+char(0,48867).
+char(3,48868).
+char(c,48869).
+char(m,48870).
+char(o,48871).
+char(m,48872).
+char(1,48873).
+char(8,48874).
+char(4,48875).
+char(2,48876).
+char(p,48877).
+char(6,48878).
+char(9,48879).
+char(1,48880).
+char(2,48881).
+char(m,48882).
+char(o,48883).
+char(p,48884).
+char(1,48885).
+char(5,48886).
+char(8,48887).
+char(2,48888).
+char(c,48889).
+char(p,48890).
+char(o,48891).
+char(m,48892).
+char(4,48893).
+char(0,48894).
+char(3,48895).
+char(3,48896).
+char(c,48897).
+char(c,48898).
+char(c,48899).
+char(c,48900).
+char(c,48901).
+char(c,48902).
+char(c,48903).
+char(m,48904).
+char(o,48905).
+char(m,48906).
+char(3,48907).
+char(1,48908).
+char(7,48909).
+char(p,48910).
+char(3,48911).
+char(9,48912).
+char(5,48913).
+char(9,48914).
+char(c,48915).
+char(m,48916).
+char(o,48917).
+char(p,48918).
+char(8,48919).
+char(9,48920).
+char(5,48921).
+char(1,48922).
+char(c,48923).
+char(p,48924).
+char(4,48925).
+char(4,48926).
+char(5,48927).
+char(7,48928).
+char(p,48929).
+char(o,48930).
+char(o,48931).
+char(o,48932).
+char(o,48933).
+char(m,48934).
+char(5,48935).
+char(7,48936).
+char(1,48937).
+char(1,48938).
+char(c,48939).
+char(m,48940).
+char(o,48941).
+char(p,48942).
+char(1,48943).
+char(4,48944).
+char(4,48945).
+char(2,48946).
+char(c,48947).
+char(c,48948).
+char(p,48949).
+char(o,48950).
+char(7,48951).
+char(9,48952).
+char(7,48953).
+char(3,48954).
+char(c,48955).
+char(c,48956).
+char(c,48957).
+char(p,48958).
+char(o,48959).
+char(m,48960).
+char(5,48961).
+char(6,48962).
+char(9,48963).
+char(2,48964).
+char(m,48965).
+char(8,48966).
+char(4,48967).
+char(9,48968).
+char(0,48969).
+char(c,48970).
+char(c,48971).
+char(m,48972).
+char(6,48973).
+char(3,48974).
+char(6,48975).
+char(1,48976).
+char(c,48977).
+char(p,48978).
+char(o,48979).
+char(p,48980).
+char(8,48981).
+char(6,48982).
+char(1,48983).
+char(7,48984).
+char(c,48985).
+char(c,48986).
+char(c,48987).
+char(c,48988).
+char(p,48989).
+char(o,48990).
+char(p,48991).
+char(2,48992).
+char(3,48993).
+char(4,48994).
+char(4,48995).
+char(p,48996).
+char(o,48997).
+char(p,48998).
+char(o,48999).
+char(2,49000).
+char(8,49001).
+char(4,49002).
+char(c,49003).
+char(p,49004).
+char(5,49005).
+char(4,49006).
+char(6,49007).
+char(9,49008).
+char(c,49009).
+char(p,49010).
+char(o,49011).
+char(o,49012).
+char(p,49013).
+char(o,49014).
+char(p,49015).
+char(o,49016).
+char(p,49017).
+char(2,49018).
+char(9,49019).
+char(0,49020).
+char(3,49021).
+char(m,49022).
+char(o,49023).
+char(o,49024).
+char(p,49025).
+char(8,49026).
+char(6,49027).
+char(9,49028).
+char(1,49029).
+char(m,49030).
+char(o,49031).
+char(m,49032).
+char(3,49033).
+char(9,49034).
+char(5,49035).
+char(8,49036).
+char(m,49037).
+char(2,49038).
+char(6,49039).
+char(2,49040).
+char(8,49041).
+char(c,49042).
+char(c,49043).
+char(p,49044).
+char(o,49045).
+char(p,49046).
+char(2,49047).
+char(6,49048).
+char(0,49049).
+char(8,49050).
+char(c,49051).
+char(c,49052).
+char(c,49053).
+char(c,49054).
+char(c,49055).
+char(m,49056).
+char(1,49057).
+char(5,49058).
+char(5,49059).
+char(0,49060).
+char(c,49061).
+char(c,49062).
+char(c,49063).
+char(p,49064).
+char(5,49065).
+char(4,49066).
+char(6,49067).
+char(6,49068).
+char(m,49069).
+char(8,49070).
+char(7,49071).
+char(2,49072).
+char(1,49073).
+char(c,49074).
+char(m,49075).
+char(9,49076).
+char(0,49077).
+char(6,49078).
+char(4,49079).
+char(m,49080).
+char(o,49081).
+char(p,49082).
+char(8,49083).
+char(0,49084).
+char(1,49085).
+char(6,49086).
+char(m,49087).
+char(8,49088).
+char(8,49089).
+char(9,49090).
+char(9,49091).
+char(m,49092).
+char(o,49093).
+char(p,49094).
+char(o,49095).
+char(3,49096).
+char(6,49097).
+char(9,49098).
+char(7,49099).
+char(c,49100).
+char(p,49101).
+char(o,49102).
+char(m,49103).
+char(o,49104).
+char(p,49105).
+char(o,49106).
+char(p,49107).
+char(o,49108).
+char(m,49109).
+char(2,49110).
+char(5,49111).
+char(0,49112).
+char(0,49113).
+char(p,49114).
+char(9,49115).
+char(3,49116).
+char(5,49117).
+char(c,49118).
+char(c,49119).
+char(c,49120).
+char(c,49121).
+char(p,49122).
+char(o,49123).
+char(m,49124).
+char(9,49125).
+char(6,49126).
+char(8,49127).
+char(9,49128).
+char(m,49129).
+char(o,49130).
+char(p,49131).
+char(o,49132).
+char(o,49133).
+char(o,49134).
+char(m,49135).
+char(o,49136).
+char(7,49137).
+char(9,49138).
+char(1,49139).
+char(9,49140).
+char(m,49141).
+char(o,49142).
+char(o,49143).
+char(m,49144).
+char(5,49145).
+char(8,49146).
+char(5,49147).
+char(2,49148).
+char(c,49149).
+char(p,49150).
+char(6,49151).
+char(8,49152).
+char(7,49153).
+char(4,49154).
+char(c,49155).
+char(p,49156).
+char(8,49157).
+char(5,49158).
+char(m,49159).
+char(7,49160).
+char(9,49161).
+char(5,49162).
+char(0,49163).
+char(p,49164).
+char(8,49165).
+char(6,49166).
+char(1,49167).
+char(4,49168).
+char(p,49169).
+char(4,49170).
+char(8,49171).
+char(6,49172).
+char(2,49173).
+char(m,49174).
+char(7,49175).
+char(1,49176).
+char(2,49177).
+char(2,49178).
+char(c,49179).
+char(c,49180).
+char(c,49181).
+char(m,49182).
+char(6,49183).
+char(4,49184).
+char(7,49185).
+char(7,49186).
+char(c,49187).
+char(c,49188).
+char(p,49189).
+char(3,49190).
+char(9,49191).
+char(2,49192).
+char(1,49193).
+char(c,49194).
+char(m,49195).
+char(o,49196).
+char(5,49197).
+char(5,49198).
+char(7,49199).
+char(5,49200).
+char(p,49201).
+char(o,49202).
+char(p,49203).
+char(7,49204).
+char(3,49205).
+char(0,49206).
+char(9,49207).
+char(m,49208).
+char(8,49209).
+char(0,49210).
+char(3,49211).
+char(6,49212).
+char(m,49213).
+char(9,49214).
+char(5,49215).
+char(2,49216).
+char(7,49217).
+char(m,49218).
+char(5,49219).
+char(8,49220).
+char(3,49221).
+char(8,49222).
+char(c,49223).
+char(m,49224).
+char(1,49225).
+char(6,49226).
+char(6,49227).
+char(9,49228).
+char(m,49229).
+char(3,49230).
+char(1,49231).
+char(8,49232).
+char(1,49233).
+char(p,49234).
+char(o,49235).
+char(p,49236).
+char(2,49237).
+char(4,49238).
+char(2,49239).
+char(9,49240).
+char(p,49241).
+char(2,49242).
+char(6,49243).
+char(6,49244).
+char(5,49245).
+char(c,49246).
+char(c,49247).
+char(c,49248).
+char(m,49249).
+char(o,49250).
+char(m,49251).
+char(1,49252).
+char(0,49253).
+char(1,49254).
+char(8,49255).
+char(c,49256).
+char(c,49257).
+char(p,49258).
+char(6,49259).
+char(3,49260).
+char(2,49261).
+char(0,49262).
+char(m,49263).
+char(o,49264).
+char(p,49265).
+char(1,49266).
+char(1,49267).
+char(2,49268).
+char(7,49269).
+char(m,49270).
+char(o,49271).
+char(6,49272).
+char(7,49273).
+char(9,49274).
+char(0,49275).
+char(m,49276).
+char(8,49277).
+char(6,49278).
+char(1,49279).
+char(0,49280).
+char(c,49281).
+char(p,49282).
+char(o,49283).
+char(4,49284).
+char(7,49285).
+char(4,49286).
+char(1,49287).
+char(p,49288).
+char(o,49289).
+char(o,49290).
+char(p,49291).
+char(3,49292).
+char(1,49293).
+char(1,49294).
+char(4,49295).
+char(m,49296).
+char(o,49297).
+char(m,49298).
+char(o,49299).
+char(3,49300).
+char(6,49301).
+char(6,49302).
+char(8,49303).
+char(m,49304).
+char(5,49305).
+char(9,49306).
+char(3,49307).
+char(7,49308).
+char(c,49309).
+char(m,49310).
+char(o,49311).
+char(m,49312).
+char(4,49313).
+char(2,49314).
+char(7,49315).
+char(8,49316).
+char(c,49317).
+char(m,49318).
+char(2,49319).
+char(2,49320).
+char(0,49321).
+char(2,49322).
+char(c,49323).
+char(p,49324).
+char(o,49325).
+char(m,49326).
+char(o,49327).
+char(m,49328).
+char(1,49329).
+char(9,49330).
+char(5,49331).
+char(5,49332).
+char(c,49333).
+char(c,49334).
+char(c,49335).
+char(c,49336).
+char(m,49337).
+char(7,49338).
+char(4,49339).
+char(7,49340).
+char(3,49341).
+char(c,49342).
+char(c,49343).
+char(c,49344).
+char(m,49345).
+char(8,49346).
+char(7,49347).
+char(5,49348).
+char(4,49349).
+char(c,49350).
+char(c,49351).
+char(c,49352).
+char(c,49353).
+char(c,49354).
+char(m,49355).
+char(1,49356).
+char(6,49357).
+char(9,49358).
+char(m,49359).
+char(4,49360).
+char(4,49361).
+char(3,49362).
+char(2,49363).
+char(p,49364).
+char(4,49365).
+char(0,49366).
+char(0,49367).
+char(0,49368).
+char(m,49369).
+char(o,49370).
+char(m,49371).
+char(9,49372).
+char(6,49373).
+char(2,49374).
+char(6,49375).
+char(p,49376).
+char(8,49377).
+char(9,49378).
+char(9,49379).
+char(8,49380).
+char(c,49381).
+char(m,49382).
+char(o,49383).
+char(o,49384).
+char(o,49385).
+char(o,49386).
+char(o,49387).
+char(m,49388).
+char(3,49389).
+char(2,49390).
+char(5,49391).
+char(c,49392).
+char(m,49393).
+char(o,49394).
+char(6,49395).
+char(9,49396).
+char(9,49397).
+char(6,49398).
+char(m,49399).
+char(3,49400).
+char(2,49401).
+char(9,49402).
+char(5,49403).
+char(c,49404).
+char(c,49405).
+char(c,49406).
+char(p,49407).
+char(o,49408).
+char(8,49409).
+char(7,49410).
+char(4,49411).
+char(5,49412).
+char(p,49413).
+char(o,49414).
+char(1,49415).
+char(4,49416).
+char(7,49417).
+char(8,49418).
+char(m,49419).
+char(8,49420).
+char(7,49421).
+char(5,49422).
+char(6,49423).
+char(c,49424).
+char(p,49425).
+char(o,49426).
+char(m,49427).
+char(o,49428).
+char(o,49429).
+char(3,49430).
+char(5,49431).
+char(7,49432).
+char(4,49433).
+char(p,49434).
+char(1,49435).
+char(9,49436).
+char(2,49437).
+char(7,49438).
+char(m,49439).
+char(o,49440).
+char(p,49441).
+char(4,49442).
+char(7,49443).
+char(7,49444).
+char(0,49445).
+char(c,49446).
+char(p,49447).
+char(o,49448).
+char(m,49449).
+char(7,49450).
+char(0,49451).
+char(0,49452).
+char(9,49453).
+char(c,49454).
+char(c,49455).
+char(c,49456).
+char(c,49457).
+char(m,49458).
+char(7,49459).
+char(7,49460).
+char(9,49461).
+char(8,49462).
+char(c,49463).
+char(p,49464).
+char(7,49465).
+char(6,49466).
+char(5,49467).
+char(7,49468).
+char(c,49469).
+char(c,49470).
+char(p,49471).
+char(o,49472).
+char(p,49473).
+char(7,49474).
+char(9,49475).
+char(9,49476).
+char(7,49477).
+char(c,49478).
+char(m,49479).
+char(8,49480).
+char(7,49481).
+char(3,49482).
+char(5,49483).
+char(c,49484).
+char(m,49485).
+char(o,49486).
+char(p,49487).
+char(o,49488).
+char(m,49489).
+char(o,49490).
+char(2,49491).
+char(3,49492).
+char(3,49493).
+char(6,49494).
+char(c,49495).
+char(m,49496).
+char(o,49497).
+char(p,49498).
+char(o,49499).
+char(4,49500).
+char(5,49501).
+char(1,49502).
+char(9,49503).
+char(m,49504).
+char(3,49505).
+char(1,49506).
+char(0,49507).
+char(7,49508).
+char(m,49509).
+char(6,49510).
+char(2,49511).
+char(3,49512).
+char(1,49513).
+char(c,49514).
+char(c,49515).
+char(m,49516).
+char(o,49517).
+char(2,49518).
+char(5,49519).
+char(5,49520).
+char(1,49521).
+char(c,49522).
+char(c,49523).
+char(m,49524).
+char(o,49525).
+char(p,49526).
+char(o,49527).
+char(2,49528).
+char(9,49529).
+char(8,49530).
+char(6,49531).
+char(p,49532).
+char(1,49533).
+char(5,49534).
+char(9,49535).
+char(7,49536).
+char(c,49537).
+char(m,49538).
+char(8,49539).
+char(3,49540).
+char(1,49541).
+char(4,49542).
+char(c,49543).
+char(p,49544).
+char(o,49545).
+char(m,49546).
+char(o,49547).
+char(m,49548).
+char(o,49549).
+char(m,49550).
+char(o,49551).
+char(9,49552).
+char(5,49553).
+char(4,49554).
+char(0,49555).
+char(p,49556).
+char(1,49557).
+char(6,49558).
+char(2,49559).
+char(1,49560).
+char(c,49561).
+char(p,49562).
+char(6,49563).
+char(5,49564).
+char(6,49565).
+char(6,49566).
+char(c,49567).
+char(c,49568).
+char(m,49569).
+char(7,49570).
+char(6,49571).
+char(p,49572).
+char(o,49573).
+char(5,49574).
+char(0,49575).
+char(8,49576).
+char(0,49577).
+char(m,49578).
+char(7,49579).
+char(0,49580).
+char(5,49581).
+char(0,49582).
+char(c,49583).
+char(p,49584).
+char(4,49585).
+char(4,49586).
+char(3,49587).
+char(0,49588).
+char(c,49589).
+char(c,49590).
+char(m,49591).
+char(o,49592).
+char(o,49593).
+char(o,49594).
+char(p,49595).
+char(1,49596).
+char(6,49597).
+char(5,49598).
+char(0,49599).
+char(p,49600).
+char(3,49601).
+char(0,49602).
+char(6,49603).
+char(3,49604).
+char(p,49605).
+char(o,49606).
+char(5,49607).
+char(6,49608).
+char(4,49609).
+char(1,49610).
+char(c,49611).
+char(m,49612).
+char(8,49613).
+char(9,49614).
+char(8,49615).
+char(3,49616).
+char(c,49617).
+char(m,49618).
+char(2,49619).
+char(1,49620).
+char(0,49621).
+char(7,49622).
+char(c,49623).
+char(c,49624).
+char(c,49625).
+char(c,49626).
+char(c,49627).
+char(p,49628).
+char(9,49629).
+char(9,49630).
+char(9,49631).
+char(6,49632).
+char(c,49633).
+char(p,49634).
+char(o,49635).
+char(9,49636).
+char(1,49637).
+char(7,49638).
+char(0,49639).
+char(m,49640).
+char(o,49641).
+char(4,49642).
+char(5,49643).
+char(2,49644).
+char(7,49645).
+char(p,49646).
+char(4,49647).
+char(4,49648).
+char(8,49649).
+char(5,49650).
+char(c,49651).
+char(p,49652).
+char(o,49653).
+char(m,49654).
+char(o,49655).
+char(m,49656).
+char(o,49657).
+char(p,49658).
+char(o,49659).
+char(p,49660).
+char(o,49661).
+char(6,49662).
+char(8,49663).
+char(6,49664).
+char(1,49665).
+char(m,49666).
+char(5,49667).
+char(7,49668).
+char(9,49669).
+char(8,49670).
+char(p,49671).
+char(8,49672).
+char(2,49673).
+char(0,49674).
+char(9,49675).
+char(c,49676).
+char(c,49677).
+char(m,49678).
+char(3,49679).
+char(0,49680).
+char(4,49681).
+char(4,49682).
+char(c,49683).
+char(m,49684).
+char(o,49685).
+char(m,49686).
+char(o,49687).
+char(o,49688).
+char(9,49689).
+char(0,49690).
+char(6,49691).
+char(4,49692).
+char(m,49693).
+char(8,49694).
+char(1,49695).
+char(0,49696).
+char(8,49697).
+char(c,49698).
+char(c,49699).
+char(c,49700).
+char(p,49701).
+char(9,49702).
+char(7,49703).
+char(0,49704).
+char(1,49705).
+char(c,49706).
+char(p,49707).
+char(o,49708).
+char(4,49709).
+char(1,49710).
+char(8,49711).
+char(3,49712).
+char(m,49713).
+char(o,49714).
+char(p,49715).
+char(2,49716).
+char(8,49717).
+char(4,49718).
+char(m,49719).
+char(7,49720).
+char(2,49721).
+char(4,49722).
+char(7,49723).
+char(p,49724).
+char(1,49725).
+char(3,49726).
+char(3,49727).
+char(8,49728).
+char(c,49729).
+char(m,49730).
+char(2,49731).
+char(7,49732).
+char(7,49733).
+char(2,49734).
+char(c,49735).
+char(m,49736).
+char(3,49737).
+char(8,49738).
+char(7,49739).
+char(2,49740).
+char(p,49741).
+char(o,49742).
+char(p,49743).
+char(6,49744).
+char(9,49745).
+char(2,49746).
+char(6,49747).
+char(c,49748).
+char(p,49749).
+char(o,49750).
+char(p,49751).
+char(5,49752).
+char(5,49753).
+char(5,49754).
+char(0,49755).
+char(m,49756).
+char(o,49757).
+char(m,49758).
+char(o,49759).
+char(p,49760).
+char(o,49761).
+char(p,49762).
+char(1,49763).
+char(0,49764).
+char(9,49765).
+char(3,49766).
+char(c,49767).
+char(m,49768).
+char(4,49769).
+char(7,49770).
+char(4,49771).
+char(5,49772).
+char(p,49773).
+char(3,49774).
+char(5,49775).
+char(2,49776).
+char(9,49777).
+char(p,49778).
+char(3,49779).
+char(6,49780).
+char(7,49781).
+char(5,49782).
+char(p,49783).
+char(4,49784).
+char(3,49785).
+char(0,49786).
+char(4,49787).
+char(m,49788).
+char(o,49789).
+char(p,49790).
+char(3,49791).
+char(2,49792).
+char(7,49793).
+char(2,49794).
+char(m,49795).
+char(5,49796).
+char(8,49797).
+char(1,49798).
+char(0,49799).
+char(c,49800).
+char(c,49801).
+char(c,49802).
+char(c,49803).
+char(c,49804).
+char(m,49805).
+char(o,49806).
+char(m,49807).
+char(4,49808).
+char(7,49809).
+char(1,49810).
+char(8,49811).
+char(c,49812).
+char(m,49813).
+char(o,49814).
+char(m,49815).
+char(o,49816).
+char(o,49817).
+char(p,49818).
+char(2,49819).
+char(1,49820).
+char(6,49821).
+char(1,49822).
+char(c,49823).
+char(m,49824).
+char(o,49825).
+char(o,49826).
+char(p,49827).
+char(9,49828).
+char(6,49829).
+char(4,49830).
+char(9,49831).
+char(p,49832).
+char(o,49833).
+char(9,49834).
+char(5,49835).
+char(3,49836).
+char(2,49837).
+char(m,49838).
+char(o,49839).
+char(p,49840).
+char(3,49841).
+char(9,49842).
+char(3,49843).
+char(6,49844).
+char(c,49845).
+char(c,49846).
+char(p,49847).
+char(o,49848).
+char(m,49849).
+char(o,49850).
+char(m,49851).
+char(7,49852).
+char(7,49853).
+char(2,49854).
+char(7,49855).
+char(c,49856).
+char(c,49857).
+char(p,49858).
+char(o,49859).
+char(o,49860).
+char(m,49861).
+char(3,49862).
+char(9,49863).
+char(0,49864).
+char(5,49865).
+char(c,49866).
+char(c,49867).
+char(c,49868).
+char(m,49869).
+char(o,49870).
+char(p,49871).
+char(3,49872).
+char(8,49873).
+char(4,49874).
+char(8,49875).
+char(m,49876).
+char(4,49877).
+char(2,49878).
+char(4,49879).
+char(8,49880).
+char(c,49881).
+char(p,49882).
+char(o,49883).
+char(p,49884).
+char(6,49885).
+char(2,49886).
+char(3,49887).
+char(6,49888).
+char(p,49889).
+char(o,49890).
+char(3,49891).
+char(7,49892).
+char(5,49893).
+char(9,49894).
+char(c,49895).
+char(m,49896).
+char(4,49897).
+char(6,49898).
+char(7,49899).
+char(6,49900).
+char(c,49901).
+char(c,49902).
+char(c,49903).
+char(p,49904).
+char(4,49905).
+char(6,49906).
+char(4,49907).
+char(9,49908).
+char(c,49909).
+char(c,49910).
+char(m,49911).
+char(o,49912).
+char(o,49913).
+char(p,49914).
+char(3,49915).
+char(0,49916).
+char(7,49917).
+char(5,49918).
+char(p,49919).
+char(5,49920).
+char(4,49921).
+char(6,49922).
+char(7,49923).
+char(p,49924).
+char(9,49925).
+char(7,49926).
+char(8,49927).
+char(c,49928).
+char(c,49929).
+char(c,49930).
+char(m,49931).
+char(9,49932).
+char(2,49933).
+char(3,49934).
+char(p,49935).
+char(o,49936).
+char(8,49937).
+char(2,49938).
+char(2,49939).
+char(9,49940).
+char(m,49941).
+char(1,49942).
+char(1,49943).
+char(0,49944).
+char(5,49945).
+char(p,49946).
+char(o,49947).
+char(m,49948).
+char(9,49949).
+char(8,49950).
+char(8,49951).
+char(0,49952).
+char(p,49953).
+char(1,49954).
+char(4,49955).
+char(3,49956).
+char(6,49957).
+char(c,49958).
+char(m,49959).
+char(1,49960).
+char(4,49961).
+char(4,49962).
+char(4,49963).
+char(c,49964).
+char(p,49965).
+char(o,49966).
+char(p,49967).
+char(o,49968).
+char(m,49969).
+char(o,49970).
+char(m,49971).
+char(o,49972).
+char(m,49973).
+char(o,49974).
+char(m,49975).
+char(4,49976).
+char(7,49977).
+char(2,49978).
+char(6,49979).
+char(p,49980).
+char(6,49981).
+char(8,49982).
+char(3,49983).
+char(2,49984).
+char(p,49985).
+char(o,49986).
+char(p,49987).
+char(o,49988).
+char(m,49989).
+char(o,49990).
+char(m,49991).
+char(o,49992).
+char(1,49993).
+char(9,49994).
+char(6,49995).
+char(3,49996).
+char(c,49997).
+char(p,49998).
+char(7,49999).
+char(3,50000).
+char(0,50001).
+char(2,50002).
+char(p,50003).
+char(5,50004).
+char(8,50005).
+char(5,50006).
+char(8,50007).
+char(p,50008).
+char(7,50009).
+char(7,50010).
+char(1,50011).
+char(8,50012).
+char(m,50013).
+char(o,50014).
+char(p,50015).
+char(o,50016).
+char(m,50017).
+char(o,50018).
+char(m,50019).
+char(o,50020).
+char(m,50021).
+char(1,50022).
+char(5,50023).
+char(8,50024).
+char(2,50025).
+char(c,50026).
+char(c,50027).
+char(c,50028).
+char(c,50029).
+char(c,50030).
+char(p,50031).
+char(o,50032).
+char(m,50033).
+char(o,50034).
+char(p,50035).
+char(o,50036).
+char(o,50037).
+char(m,50038).
+char(9,50039).
+char(0,50040).
+char(8,50041).
+char(5,50042).
+char(p,50043).
+char(o,50044).
+char(m,50045).
+char(4,50046).
+char(0,50047).
+char(7,50048).
+char(2,50049).
+char(m,50050).
+char(3,50051).
+char(3,50052).
+char(8,50053).
+char(2,50054).
+char(m,50055).
+char(o,50056).
+char(o,50057).
+char(m,50058).
+char(2,50059).
+char(9,50060).
+char(0,50061).
+char(5,50062).
+char(p,50063).
+char(o,50064).
+char(m,50065).
+char(6,50066).
+char(3,50067).
+char(2,50068).
+char(4,50069).
+char(c,50070).
+char(p,50071).
+char(o,50072).
+char(p,50073).
+char(o,50074).
+char(5,50075).
+char(8,50076).
+char(5,50077).
+char(2,50078).
+char(p,50079).
+char(1,50080).
+char(4,50081).
+char(9,50082).
+char(8,50083).
+char(c,50084).
+char(m,50085).
+char(4,50086).
+char(0,50087).
+char(7,50088).
+char(7,50089).
+char(p,50090).
+char(4,50091).
+char(2,50092).
+char(9,50093).
+char(3,50094).
+char(p,50095).
+char(5,50096).
+char(1,50097).
+char(3,50098).
+char(8,50099).
+char(c,50100).
+char(c,50101).
+char(c,50102).
+char(p,50103).
+char(o,50104).
+char(o,50105).
+char(3,50106).
+char(9,50107).
+char(2,50108).
+char(8,50109).
+char(m,50110).
+char(o,50111).
+char(8,50112).
+char(7,50113).
+char(3,50114).
+char(3,50115).
+char(m,50116).
+char(7,50117).
+char(9,50118).
+char(6,50119).
+char(3,50120).
+char(c,50121).
+char(c,50122).
+char(c,50123).
+char(p,50124).
+char(o,50125).
+char(p,50126).
+char(7,50127).
+char(7,50128).
+char(7,50129).
+char(4,50130).
+char(p,50131).
+char(o,50132).
+char(m,50133).
+char(7,50134).
+char(1,50135).
+char(6,50136).
+char(c,50137).
+char(c,50138).
+char(c,50139).
+char(c,50140).
+char(c,50141).
+char(c,50142).
+char(m,50143).
+char(5,50144).
+char(3,50145).
+char(9,50146).
+char(8,50147).
+char(p,50148).
+char(o,50149).
+char(p,50150).
+char(o,50151).
+char(m,50152).
+char(o,50153).
+char(m,50154).
+char(o,50155).
+char(p,50156).
+char(2,50157).
+char(3,50158).
+char(2,50159).
+char(8,50160).
+char(p,50161).
+char(2,50162).
+char(4,50163).
+char(4,50164).
+char(1,50165).
+char(c,50166).
+char(p,50167).
+char(o,50168).
+char(o,50169).
+char(6,50170).
+char(0,50171).
+char(1,50172).
+char(1,50173).
+char(p,50174).
+char(o,50175).
+char(8,50176).
+char(1,50177).
+char(4,50178).
+char(c,50179).
+char(c,50180).
+char(c,50181).
+char(c,50182).
+char(c,50183).
+char(p,50184).
+char(2,50185).
+char(2,50186).
+char(5,50187).
+char(5,50188).
+char(m,50189).
+char(o,50190).
+char(9,50191).
+char(4,50192).
+char(4,50193).
+char(3,50194).
+char(p,50195).
+char(o,50196).
+char(m,50197).
+char(o,50198).
+char(m,50199).
+char(o,50200).
+char(o,50201).
+char(p,50202).
+char(o,50203).
+char(m,50204).
+char(o,50205).
+char(p,50206).
+char(o,50207).
+char(m,50208).
+char(9,50209).
+char(4,50210).
+char(9,50211).
+char(8,50212).
+char(m,50213).
+char(o,50214).
+char(m,50215).
+char(5,50216).
+char(6,50217).
+char(6,50218).
+char(2,50219).
+char(c,50220).
+char(p,50221).
+char(9,50222).
+char(7,50223).
+char(4,50224).
+char(4,50225).
+char(c,50226).
+char(c,50227).
+char(m,50228).
+char(o,50229).
+char(5,50230).
+char(8,50231).
+char(4,50232).
+char(3,50233).
+char(m,50234).
+char(o,50235).
+char(p,50236).
+char(o,50237).
+char(3,50238).
+char(6,50239).
+char(5,50240).
+char(3,50241).
+char(p,50242).
+char(2,50243).
+char(7,50244).
+char(5,50245).
+char(1,50246).
+char(m,50247).
+char(9,50248).
+char(7,50249).
+char(4,50250).
+char(9,50251).
+char(m,50252).
+char(9,50253).
+char(5,50254).
+char(6,50255).
+char(2,50256).
+char(c,50257).
+char(c,50258).
+char(c,50259).
+char(m,50260).
+char(o,50261).
+char(m,50262).
+char(8,50263).
+char(9,50264).
+char(1,50265).
+char(4,50266).
+char(m,50267).
+char(6,50268).
+char(5,50269).
+char(2,50270).
+char(2,50271).
+char(c,50272).
+char(m,50273).
+char(o,50274).
+char(6,50275).
+char(4,50276).
+char(7,50277).
+char(4,50278).
+char(c,50279).
+char(p,50280).
+char(o,50281).
+char(m,50282).
+char(3,50283).
+char(8,50284).
+char(6,50285).
+char(8,50286).
+char(p,50287).
+char(o,50288).
+char(p,50289).
+char(4,50290).
+char(0,50291).
+char(3,50292).
+char(5,50293).
+char(c,50294).
+char(c,50295).
+char(c,50296).
+char(c,50297).
+char(p,50298).
+char(o,50299).
+char(p,50300).
+char(4,50301).
+char(0,50302).
+char(8,50303).
+char(0,50304).
+char(p,50305).
+char(o,50306).
+char(m,50307).
+char(o,50308).
+char(p,50309).
+char(o,50310).
+char(p,50311).
+char(1,50312).
+char(0,50313).
+char(8,50314).
+char(1,50315).
+char(c,50316).
+char(c,50317).
+char(c,50318).
+char(p,50319).
+char(4,50320).
+char(3,50321).
+char(4,50322).
+char(3,50323).
+char(m,50324).
+char(o,50325).
+char(m,50326).
+char(1,50327).
+char(9,50328).
+char(8,50329).
+char(2,50330).
+char(c,50331).
+char(c,50332).
+char(p,50333).
+char(o,50334).
+char(o,50335).
+char(p,50336).
+char(4,50337).
+char(4,50338).
+char(1,50339).
+char(5,50340).
+char(c,50341).
+char(p,50342).
+char(o,50343).
+char(p,50344).
+char(8,50345).
+char(9,50346).
+char(4,50347).
+char(2,50348).
+char(c,50349).
+char(c,50350).
+char(m,50351).
+char(3,50352).
+char(5,50353).
+char(1,50354).
+char(3,50355).
+char(m,50356).
+char(9,50357).
+char(1,50358).
+char(8,50359).
+char(5,50360).
+char(m,50361).
+char(7,50362).
+char(4,50363).
+char(6,50364).
+char(4,50365).
+char(c,50366).
+char(m,50367).
+char(4,50368).
+char(1,50369).
+char(3,50370).
+char(0,50371).
+char(m,50372).
+char(o,50373).
+char(p,50374).
+char(o,50375).
+char(9,50376).
+char(2,50377).
+char(3,50378).
+char(8,50379).
+char(p,50380).
+char(o,50381).
+char(m,50382).
+char(o,50383).
+char(m,50384).
+char(o,50385).
+char(p,50386).
+char(o,50387).
+char(p,50388).
+char(o,50389).
+char(m,50390).
+char(o,50391).
+char(p,50392).
+char(7,50393).
+char(0,50394).
+char(7,50395).
+char(3,50396).
+char(m,50397).
+char(o,50398).
+char(p,50399).
+char(9,50400).
+char(6,50401).
+char(4,50402).
+char(4,50403).
+char(m,50404).
+char(o,50405).
+char(p,50406).
+char(o,50407).
+char(m,50408).
+char(7,50409).
+char(8,50410).
+char(0,50411).
+char(7,50412).
+char(p,50413).
+char(4,50414).
+char(7,50415).
+char(9,50416).
+char(2,50417).
+char(c,50418).
+char(c,50419).
+char(p,50420).
+char(8,50421).
+char(9,50422).
+char(4,50423).
+char(1,50424).
+char(c,50425).
+char(p,50426).
+char(o,50427).
+char(p,50428).
+char(o,50429).
+char(p,50430).
+char(o,50431).
+char(p,50432).
+char(4,50433).
+char(9,50434).
+char(6,50435).
+char(4,50436).
+char(m,50437).
+char(o,50438).
+char(m,50439).
+char(o,50440).
+char(p,50441).
+char(3,50442).
+char(5,50443).
+char(9,50444).
+char(2,50445).
+char(c,50446).
+char(m,50447).
+char(2,50448).
+char(1,50449).
+char(0,50450).
+char(8,50451).
+char(c,50452).
+char(c,50453).
+char(c,50454).
+char(m,50455).
+char(1,50456).
+char(7,50457).
+char(8,50458).
+char(2,50459).
+char(c,50460).
+char(p,50461).
+char(o,50462).
+char(o,50463).
+char(o,50464).
+char(m,50465).
+char(o,50466).
+char(o,50467).
+char(m,50468).
+char(8,50469).
+char(6,50470).
+char(5,50471).
+char(0,50472).
+char(c,50473).
+char(p,50474).
+char(9,50475).
+char(4,50476).
+char(4,50477).
+char(7,50478).
+char(m,50479).
+char(o,50480).
+char(7,50481).
+char(6,50482).
+char(6,50483).
+char(1,50484).
+char(p,50485).
+char(7,50486).
+char(1,50487).
+char(7,50488).
+char(2,50489).
+char(c,50490).
+char(m,50491).
+char(7,50492).
+char(3,50493).
+char(9,50494).
+char(9,50495).
+char(p,50496).
+char(o,50497).
+char(m,50498).
+char(o,50499).
+char(p,50500).
+char(o,50501).
+char(p,50502).
+char(o,50503).
+char(p,50504).
+char(o,50505).
+char(o,50506).
+char(o,50507).
+char(m,50508).
+char(8,50509).
+char(0,50510).
+char(9,50511).
+char(c,50512).
+char(c,50513).
+char(c,50514).
+char(c,50515).
+char(c,50516).
+char(p,50517).
+char(o,50518).
+char(p,50519).
+char(1,50520).
+char(4,50521).
+char(6,50522).
+char(2,50523).
+char(p,50524).
+char(5,50525).
+char(1,50526).
+char(6,50527).
+char(4,50528).
+char(p,50529).
+char(o,50530).
+char(p,50531).
+char(o,50532).
+char(o,50533).
+char(5,50534).
+char(3,50535).
+char(8,50536).
+char(8,50537).
+char(p,50538).
+char(o,50539).
+char(p,50540).
+char(6,50541).
+char(9,50542).
+char(3,50543).
+char(1,50544).
+char(p,50545).
+char(o,50546).
+char(7,50547).
+char(2,50548).
+char(7,50549).
+char(7,50550).
+char(m,50551).
+char(4,50552).
+char(7,50553).
+char(5,50554).
+char(4,50555).
+char(c,50556).
+char(c,50557).
+char(c,50558).
+char(m,50559).
+char(o,50560).
+char(3,50561).
+char(4,50562).
+char(1,50563).
+char(5,50564).
+char(p,50565).
+char(o,50566).
+char(p,50567).
+char(o,50568).
+char(1,50569).
+char(8,50570).
+char(6,50571).
+char(8,50572).
+char(c,50573).
+char(c,50574).
+char(c,50575).
+char(c,50576).
+char(p,50577).
+char(o,50578).
+char(p,50579).
+char(o,50580).
+char(p,50581).
+char(o,50582).
+char(p,50583).
+char(o,50584).
+char(p,50585).
+char(o,50586).
+char(m,50587).
+char(o,50588).
+char(9,50589).
+char(3,50590).
+char(2,50591).
+char(7,50592).
+char(c,50593).
+char(p,50594).
+char(8,50595).
+char(6,50596).
+char(0,50597).
+char(5,50598).
+char(c,50599).
+char(c,50600).
+char(p,50601).
+char(o,50602).
+char(p,50603).
+char(o,50604).
+char(p,50605).
+char(o,50606).
+char(4,50607).
+char(3,50608).
+char(1,50609).
+char(1,50610).
+char(c,50611).
+char(c,50612).
+char(c,50613).
+char(m,50614).
+char(7,50615).
+char(0,50616).
+char(7,50617).
+char(p,50618).
+char(o,50619).
+char(p,50620).
+char(1,50621).
+char(2,50622).
+char(4,50623).
+char(8,50624).
+char(c,50625).
+char(p,50626).
+char(6,50627).
+char(9,50628).
+char(2,50629).
+char(3,50630).
+char(c,50631).
+char(c,50632).
+char(c,50633).
+char(m,50634).
+char(9,50635).
+char(4,50636).
+char(8,50637).
+char(8,50638).
+char(p,50639).
+char(5,50640).
+char(1,50641).
+char(1,50642).
+char(4,50643).
+char(p,50644).
+char(o,50645).
+char(m,50646).
+char(3,50647).
+char(2,50648).
+char(2,50649).
+char(3,50650).
+char(c,50651).
+char(c,50652).
+char(m,50653).
+char(o,50654).
+char(7,50655).
+char(6,50656).
+char(9,50657).
+char(1,50658).
+char(c,50659).
+char(m,50660).
+char(1,50661).
+char(0,50662).
+char(3,50663).
+char(5,50664).
+char(c,50665).
+char(c,50666).
+char(c,50667).
+char(p,50668).
+char(3,50669).
+char(0,50670).
+char(4,50671).
+char(8,50672).
+char(m,50673).
+char(8,50674).
+char(4,50675).
+char(c,50676).
+char(p,50677).
+char(o,50678).
+char(m,50679).
+char(6,50680).
+char(5,50681).
+char(3,50682).
+char(0,50683).
+char(m,50684).
+char(o,50685).
+char(p,50686).
+char(o,50687).
+char(2,50688).
+char(9,50689).
+char(7,50690).
+char(7,50691).
+char(m,50692).
+char(o,50693).
+char(p,50694).
+char(o,50695).
+char(m,50696).
+char(6,50697).
+char(8,50698).
+char(1,50699).
+char(4,50700).
+char(p,50701).
+char(o,50702).
+char(p,50703).
+char(4,50704).
+char(8,50705).
+char(2,50706).
+char(1,50707).
+char(m,50708).
+char(8,50709).
+char(1,50710).
+char(1,50711).
+char(3,50712).
+char(m,50713).
+char(o,50714).
+char(o,50715).
+char(o,50716).
+char(p,50717).
+char(o,50718).
+char(p,50719).
+char(o,50720).
+char(m,50721).
+char(o,50722).
+char(p,50723).
+char(1,50724).
+char(6,50725).
+char(2,50726).
+char(8,50727).
+char(p,50728).
+char(o,50729).
+char(p,50730).
+char(5,50731).
+char(6,50732).
+char(8,50733).
+char(c,50734).
+char(m,50735).
+char(o,50736).
+char(m,50737).
+char(o,50738).
+char(o,50739).
+char(p,50740).
+char(o,50741).
+char(o,50742).
+char(m,50743).
+char(o,50744).
+char(m,50745).
+char(3,50746).
+char(2,50747).
+char(9,50748).
+char(c,50749).
+char(m,50750).
+char(o,50751).
+char(o,50752).
+char(m,50753).
+char(o,50754).
+char(p,50755).
+char(o,50756).
+char(1,50757).
+char(9,50758).
+char(5,50759).
+char(5,50760).
+char(p,50761).
+char(o,50762).
+char(m,50763).
+char(2,50764).
+char(7,50765).
+char(5,50766).
+char(2,50767).
+char(p,50768).
+char(1,50769).
+char(3,50770).
+char(9,50771).
+char(8,50772).
+char(m,50773).
+char(8,50774).
+char(7,50775).
+char(6,50776).
+char(2,50777).
+char(p,50778).
+char(3,50779).
+char(1,50780).
+char(4,50781).
+char(1,50782).
+char(c,50783).
+char(c,50784).
+char(p,50785).
+char(o,50786).
+char(m,50787).
+char(5,50788).
+char(0,50789).
+char(2,50790).
+char(5,50791).
+char(c,50792).
+char(c,50793).
+char(c,50794).
+char(p,50795).
+char(o,50796).
+char(2,50797).
+char(7,50798).
+char(6,50799).
+char(0,50800).
+char(p,50801).
+char(8,50802).
+char(9,50803).
+char(8,50804).
+char(8,50805).
+char(p,50806).
+char(o,50807).
+char(p,50808).
+char(7,50809).
+char(8,50810).
+char(5,50811).
+char(9,50812).
+char(p,50813).
+char(o,50814).
+char(m,50815).
+char(7,50816).
+char(1,50817).
+char(1,50818).
+char(6,50819).
+char(c,50820).
+char(c,50821).
+char(c,50822).
+char(c,50823).
+char(c,50824).
+char(p,50825).
+char(6,50826).
+char(2,50827).
+char(6,50828).
+char(6,50829).
+char(p,50830).
+char(6,50831).
+char(3,50832).
+char(6,50833).
+char(7,50834).
+char(c,50835).
+char(m,50836).
+char(9,50837).
+char(9,50838).
+char(4,50839).
+char(0,50840).
+char(p,50841).
+char(7,50842).
+char(5,50843).
+char(6,50844).
+char(1,50845).
+char(m,50846).
+char(o,50847).
+char(7,50848).
+char(4,50849).
+char(1,50850).
+char(3,50851).
+char(c,50852).
+char(c,50853).
+char(c,50854).
+char(m,50855).
+char(2,50856).
+char(3,50857).
+char(5,50858).
+char(6,50859).
+char(m,50860).
+char(5,50861).
+char(5,50862).
+char(6,50863).
+char(4,50864).
+char(c,50865).
+char(m,50866).
+char(4,50867).
+char(4,50868).
+char(1,50869).
+char(8,50870).
+char(c,50871).
+char(c,50872).
+char(p,50873).
+char(2,50874).
+char(9,50875).
+char(0,50876).
+char(3,50877).
+char(m,50878).
+char(3,50879).
+char(3,50880).
+char(9,50881).
+char(3,50882).
+char(c,50883).
+char(c,50884).
+char(c,50885).
+char(c,50886).
+char(c,50887).
+char(m,50888).
+char(7,50889).
+char(5,50890).
+char(8,50891).
+char(7,50892).
+char(c,50893).
+char(p,50894).
+char(5,50895).
+char(9,50896).
+char(1,50897).
+char(9,50898).
+char(p,50899).
+char(7,50900).
+char(1,50901).
+char(2,50902).
+char(9,50903).
+char(c,50904).
+char(p,50905).
+char(o,50906).
+char(3,50907).
+char(1,50908).
+char(1,50909).
+char(c,50910).
+char(c,50911).
+char(m,50912).
+char(o,50913).
+char(p,50914).
+char(o,50915).
+char(p,50916).
+char(7,50917).
+char(3,50918).
+char(6,50919).
+char(3,50920).
+char(c,50921).
+char(m,50922).
+char(o,50923).
+char(o,50924).
+char(p,50925).
+char(9,50926).
+char(7,50927).
+char(1,50928).
+char(0,50929).
+char(p,50930).
+char(o,50931).
+char(p,50932).
+char(6,50933).
+char(5,50934).
+char(3,50935).
+char(5,50936).
+char(m,50937).
+char(o,50938).
+char(m,50939).
+char(o,50940).
+char(p,50941).
+char(5,50942).
+char(4,50943).
+char(4,50944).
+char(5,50945).
+char(m,50946).
+char(o,50947).
+char(m,50948).
+char(4,50949).
+char(5,50950).
+char(0,50951).
+char(6,50952).
+char(m,50953).
+char(3,50954).
+char(5,50955).
+char(3,50956).
+char(0,50957).
+char(m,50958).
+char(o,50959).
+char(1,50960).
+char(3,50961).
+char(8,50962).
+char(2,50963).
+char(m,50964).
+char(o,50965).
+char(p,50966).
+char(o,50967).
+char(m,50968).
+char(4,50969).
+char(1,50970).
+char(4,50971).
+char(5,50972).
+char(m,50973).
+char(8,50974).
+char(7,50975).
+char(2,50976).
+char(8,50977).
+char(c,50978).
+char(m,50979).
+char(o,50980).
+char(6,50981).
+char(2,50982).
+char(8,50983).
+char(7,50984).
+char(c,50985).
+char(c,50986).
+char(p,50987).
+char(4,50988).
+char(3,50989).
+char(1,50990).
+char(1,50991).
+char(p,50992).
+char(o,50993).
+char(m,50994).
+char(5,50995).
+char(0,50996).
+char(7,50997).
+char(1,50998).
+char(c,50999).
+char(c,51000).
+char(p,51001).
+char(2,51002).
+char(4,51003).
+char(4,51004).
+char(0,51005).
+char(p,51006).
+char(2,51007).
+char(5,51008).
+char(5,51009).
+char(0,51010).
+char(p,51011).
+char(o,51012).
+char(p,51013).
+char(o,51014).
+char(o,51015).
+char(o,51016).
+char(m,51017).
+char(o,51018).
+char(p,51019).
+char(o,51020).
+char(m,51021).
+char(8,51022).
+char(8,51023).
+char(8,51024).
+char(4,51025).
+char(p,51026).
+char(1,51027).
+char(2,51028).
+char(6,51029).
+char(1,51030).
+char(p,51031).
+char(o,51032).
+char(o,51033).
+char(m,51034).
+char(o,51035).
+char(p,51036).
+char(o,51037).
+char(m,51038).
+char(o,51039).
+char(o,51040).
+char(m,51041).
+char(o,51042).
+char(p,51043).
+char(5,51044).
+char(4,51045).
+char(4,51046).
+char(3,51047).
+char(c,51048).
+char(c,51049).
+char(c,51050).
+char(m,51051).
+char(7,51052).
+char(4,51053).
+char(8,51054).
+char(2,51055).
+char(c,51056).
+char(p,51057).
+char(o,51058).
+char(3,51059).
+char(1,51060).
+char(4,51061).
+char(9,51062).
+char(m,51063).
+char(9,51064).
+char(6,51065).
+char(3,51066).
+char(6,51067).
+char(p,51068).
+char(o,51069).
+char(p,51070).
+char(3,51071).
+char(2,51072).
+char(8,51073).
+char(8,51074).
+char(p,51075).
+char(7,51076).
+char(7,51077).
+char(9,51078).
+char(2,51079).
+char(c,51080).
+char(c,51081).
+char(p,51082).
+char(o,51083).
+char(m,51084).
+char(8,51085).
+char(6,51086).
+char(6,51087).
+char(2,51088).
+char(c,51089).
+char(p,51090).
+char(7,51091).
+char(9,51092).
+char(1,51093).
+char(3,51094).
+char(c,51095).
+char(m,51096).
+char(4,51097).
+char(8,51098).
+char(7,51099).
+char(1,51100).
+char(c,51101).
+char(c,51102).
+char(c,51103).
+char(m,51104).
+char(o,51105).
+char(o,51106).
+char(p,51107).
+char(1,51108).
+char(1,51109).
+char(0,51110).
+char(3,51111).
+char(c,51112).
+char(p,51113).
+char(3,51114).
+char(3,51115).
+char(2,51116).
+char(5,51117).
+char(m,51118).
+char(1,51119).
+char(8,51120).
+char(4,51121).
+char(p,51122).
+char(5,51123).
+char(9,51124).
+char(2,51125).
+char(8,51126).
+char(p,51127).
+char(9,51128).
+char(8,51129).
+char(2,51130).
+char(5,51131).
+char(m,51132).
+char(o,51133).
+char(m,51134).
+char(o,51135).
+char(p,51136).
+char(6,51137).
+char(3,51138).
+char(3,51139).
+char(3,51140).
+char(c,51141).
+char(c,51142).
+char(m,51143).
+char(o,51144).
+char(5,51145).
+char(1,51146).
+char(2,51147).
+char(0,51148).
+char(m,51149).
+char(5,51150).
+char(2,51151).
+char(1,51152).
+char(9,51153).
+char(c,51154).
+char(m,51155).
+char(1,51156).
+char(6,51157).
+char(3,51158).
+char(4,51159).
+char(p,51160).
+char(o,51161).
+char(p,51162).
+char(2,51163).
+char(3,51164).
+char(9,51165).
+char(1,51166).
+char(p,51167).
+char(3,51168).
+char(2,51169).
+char(2,51170).
+char(0,51171).
+char(p,51172).
+char(7,51173).
+char(9,51174).
+char(2,51175).
+char(7,51176).
+char(c,51177).
+char(c,51178).
+char(m,51179).
+char(3,51180).
+char(4,51181).
+char(7,51182).
+char(7,51183).
+char(c,51184).
+char(m,51185).
+char(3,51186).
+char(3,51187).
+char(9,51188).
+char(0,51189).
+char(c,51190).
+char(c,51191).
+char(c,51192).
+char(c,51193).
+char(p,51194).
+char(o,51195).
+char(m,51196).
+char(7,51197).
+char(5,51198).
+char(3,51199).
+char(9,51200).
+char(c,51201).
+char(c,51202).
+char(c,51203).
+char(m,51204).
+char(o,51205).
+char(4,51206).
+char(1,51207).
+char(4,51208).
+char(7,51209).
+char(c,51210).
+char(p,51211).
+char(o,51212).
+char(1,51213).
+char(2,51214).
+char(7,51215).
+char(1,51216).
+char(m,51217).
+char(o,51218).
+char(m,51219).
+char(9,51220).
+char(2,51221).
+char(0,51222).
+char(2,51223).
+char(c,51224).
+char(c,51225).
+char(c,51226).
+char(p,51227).
+char(6,51228).
+char(0,51229).
+char(0,51230).
+char(0,51231).
+char(p,51232).
+char(4,51233).
+char(8,51234).
+char(7,51235).
+char(6,51236).
+char(c,51237).
+char(c,51238).
+char(p,51239).
+char(2,51240).
+char(8,51241).
+char(5,51242).
+char(4,51243).
+char(c,51244).
+char(c,51245).
+char(p,51246).
+char(5,51247).
+char(1,51248).
+char(3,51249).
+char(9,51250).
+char(p,51251).
+char(5,51252).
+char(8,51253).
+char(0,51254).
+char(4,51255).
+char(c,51256).
+char(p,51257).
+char(7,51258).
+char(7,51259).
+char(8,51260).
+char(4,51261).
+char(c,51262).
+char(m,51263).
+char(7,51264).
+char(3,51265).
+char(2,51266).
+char(8,51267).
+char(m,51268).
+char(o,51269).
+char(p,51270).
+char(8,51271).
+char(0,51272).
+char(8,51273).
+char(4,51274).
+char(p,51275).
+char(o,51276).
+char(p,51277).
+char(8,51278).
+char(7,51279).
+char(4,51280).
+char(9,51281).
+char(c,51282).
+char(p,51283).
+char(o,51284).
+char(m,51285).
+char(8,51286).
+char(7,51287).
+char(7,51288).
+char(7,51289).
+char(p,51290).
+char(o,51291).
+char(o,51292).
+char(m,51293).
+char(o,51294).
+char(m,51295).
+char(2,51296).
+char(8,51297).
+char(8,51298).
+char(8,51299).
+char(c,51300).
+char(p,51301).
+char(8,51302).
+char(2,51303).
+char(1,51304).
+char(2,51305).
+char(p,51306).
+char(9,51307).
+char(0,51308).
+char(0,51309).
+char(8,51310).
+char(c,51311).
+char(m,51312).
+char(5,51313).
+char(5,51314).
+char(3,51315).
+char(c,51316).
+char(c,51317).
+char(m,51318).
+char(o,51319).
+char(p,51320).
+char(3,51321).
+char(8,51322).
+char(5,51323).
+char(3,51324).
+char(c,51325).
+char(p,51326).
+char(4,51327).
+char(4,51328).
+char(1,51329).
+char(3,51330).
+char(c,51331).
+char(c,51332).
+char(m,51333).
+char(o,51334).
+char(o,51335).
+char(m,51336).
+char(4,51337).
+char(6,51338).
+char(9,51339).
+char(6,51340).
+char(c,51341).
+char(m,51342).
+char(7,51343).
+char(5,51344).
+char(9,51345).
+char(2,51346).
+char(c,51347).
+char(c,51348).
+char(c,51349).
+char(c,51350).
+char(p,51351).
+char(7,51352).
+char(1,51353).
+char(3,51354).
+char(0,51355).
+char(m,51356).
+char(o,51357).
+char(p,51358).
+char(o,51359).
+char(p,51360).
+char(o,51361).
+char(p,51362).
+char(o,51363).
+char(m,51364).
+char(2,51365).
+char(3,51366).
+char(0,51367).
+char(5,51368).
+char(c,51369).
+char(m,51370).
+char(o,51371).
+char(o,51372).
+char(m,51373).
+char(6,51374).
+char(2,51375).
+char(2,51376).
+char(8,51377).
+char(m,51378).
+char(o,51379).
+char(o,51380).
+char(m,51381).
+char(5,51382).
+char(0,51383).
+char(3,51384).
+char(2,51385).
+char(p,51386).
+char(3,51387).
+char(6,51388).
+char(0,51389).
+char(7,51390).
+char(c,51391).
+char(m,51392).
+char(2,51393).
+char(7,51394).
+char(6,51395).
+char(9,51396).
+char(c,51397).
+char(p,51398).
+char(o,51399).
+char(p,51400).
+char(1,51401).
+char(9,51402).
+char(1,51403).
+char(7,51404).
+char(p,51405).
+char(o,51406).
+char(o,51407).
+char(p,51408).
+char(o,51409).
+char(p,51410).
+char(o,51411).
+char(6,51412).
+char(5,51413).
+char(6,51414).
+char(0,51415).
+char(m,51416).
+char(o,51417).
+char(m,51418).
+char(o,51419).
+char(m,51420).
+char(o,51421).
+char(p,51422).
+char(7,51423).
+char(6,51424).
+char(4,51425).
+char(7,51426).
+char(c,51427).
+char(c,51428).
+char(m,51429).
+char(o,51430).
+char(p,51431).
+char(4,51432).
+char(6,51433).
+char(9,51434).
+char(8,51435).
+char(m,51436).
+char(o,51437).
+char(p,51438).
+char(5,51439).
+char(1,51440).
+char(8,51441).
+char(0,51442).
+char(c,51443).
+char(m,51444).
+char(9,51445).
+char(8,51446).
+char(2,51447).
+char(c,51448).
+char(c,51449).
+char(m,51450).
+char(8,51451).
+char(6,51452).
+char(1,51453).
+char(3,51454).
+char(c,51455).
+char(m,51456).
+char(2,51457).
+char(6,51458).
+char(3,51459).
+char(m,51460).
+char(o,51461).
+char(m,51462).
+char(5,51463).
+char(8,51464).
+char(4,51465).
+char(0,51466).
+char(p,51467).
+char(8,51468).
+char(3,51469).
+char(1,51470).
+char(1,51471).
+char(p,51472).
+char(o,51473).
+char(4,51474).
+char(9,51475).
+char(3,51476).
+char(6,51477).
+char(c,51478).
+char(m,51479).
+char(7,51480).
+char(4,51481).
+char(1,51482).
+char(c,51483).
+char(c,51484).
+char(p,51485).
+char(7,51486).
+char(9,51487).
+char(2,51488).
+char(9,51489).
+char(c,51490).
+char(p,51491).
+char(o,51492).
+char(8,51493).
+char(4,51494).
+char(3,51495).
+char(4,51496).
+char(m,51497).
+char(o,51498).
+char(p,51499).
+char(o,51500).
+char(o,51501).
+char(7,51502).
+char(0,51503).
+char(3,51504).
+char(4,51505).
+char(c,51506).
+char(c,51507).
+char(p,51508).
+char(8,51509).
+char(6,51510).
+char(1,51511).
+char(8,51512).
+char(m,51513).
+char(o,51514).
+char(7,51515).
+char(8,51516).
+char(4,51517).
+char(9,51518).
+char(m,51519).
+char(6,51520).
+char(3,51521).
+char(8,51522).
+char(4,51523).
+char(c,51524).
+char(c,51525).
+char(p,51526).
+char(o,51527).
+char(m,51528).
+char(o,51529).
+char(p,51530).
+char(8,51531).
+char(9,51532).
+char(0,51533).
+char(7,51534).
+char(c,51535).
+char(c,51536).
+char(c,51537).
+char(m,51538).
+char(o,51539).
+char(o,51540).
+char(p,51541).
+char(5,51542).
+char(9,51543).
+char(6,51544).
+char(3,51545).
+char(m,51546).
+char(o,51547).
+char(o,51548).
+char(p,51549).
+char(9,51550).
+char(6,51551).
+char(3,51552).
+char(8,51553).
+char(m,51554).
+char(9,51555).
+char(9,51556).
+char(6,51557).
+char(4,51558).
+char(c,51559).
+char(c,51560).
+char(m,51561).
+char(8,51562).
+char(3,51563).
+char(4,51564).
+char(0,51565).
+char(c,51566).
+char(m,51567).
+char(7,51568).
+char(9,51569).
+char(3,51570).
+char(2,51571).
+char(c,51572).
+char(c,51573).
+char(m,51574).
+char(o,51575).
+char(m,51576).
+char(2,51577).
+char(0,51578).
+char(1,51579).
+char(7,51580).
+char(c,51581).
+char(m,51582).
+char(o,51583).
+char(m,51584).
+char(o,51585).
+char(o,51586).
+char(o,51587).
+char(p,51588).
+char(o,51589).
+char(p,51590).
+char(o,51591).
+char(p,51592).
+char(o,51593).
+char(4,51594).
+char(8,51595).
+char(9,51596).
+char(1,51597).
+char(c,51598).
+char(c,51599).
+char(c,51600).
+char(c,51601).
+char(m,51602).
+char(o,51603).
+char(p,51604).
+char(9,51605).
+char(5,51606).
+char(9,51607).
+char(c,51608).
+char(c,51609).
+char(c,51610).
+char(m,51611).
+char(5,51612).
+char(8,51613).
+char(2,51614).
+char(5,51615).
+char(p,51616).
+char(o,51617).
+char(o,51618).
+char(m,51619).
+char(7,51620).
+char(6,51621).
+char(2,51622).
+char(2,51623).
+char(m,51624).
+char(o,51625).
+char(p,51626).
+char(7,51627).
+char(0,51628).
+char(6,51629).
+char(1,51630).
+char(m,51631).
+char(4,51632).
+char(8,51633).
+char(3,51634).
+char(c,51635).
+char(p,51636).
+char(o,51637).
+char(p,51638).
+char(o,51639).
+char(m,51640).
+char(o,51641).
+char(o,51642).
+char(o,51643).
+char(3,51644).
+char(1,51645).
+char(2,51646).
+char(1,51647).
+char(c,51648).
+char(p,51649).
+char(9,51650).
+char(8,51651).
+char(7,51652).
+char(6,51653).
+char(m,51654).
+char(1,51655).
+char(7,51656).
+char(5,51657).
+char(5,51658).
+char(c,51659).
+char(c,51660).
+char(m,51661).
+char(o,51662).
+char(o,51663).
+char(m,51664).
+char(4,51665).
+char(4,51666).
+char(1,51667).
+char(c,51668).
+char(p,51669).
+char(o,51670).
+char(o,51671).
+char(o,51672).
+char(o,51673).
+char(p,51674).
+char(o,51675).
+char(o,51676).
+char(p,51677).
+char(o,51678).
+char(p,51679).
+char(o,51680).
+char(m,51681).
+char(7,51682).
+char(3,51683).
+char(5,51684).
+char(6,51685).
+char(c,51686).
+char(c,51687).
+char(m,51688).
+char(9,51689).
+char(7,51690).
+char(5,51691).
+char(c,51692).
+char(c,51693).
+char(c,51694).
+char(m,51695).
+char(5,51696).
+char(7,51697).
+char(4,51698).
+char(9,51699).
+char(m,51700).
+char(o,51701).
+char(m,51702).
+char(o,51703).
+char(5,51704).
+char(2,51705).
+char(1,51706).
+char(2,51707).
+char(m,51708).
+char(o,51709).
+char(p,51710).
+char(9,51711).
+char(8,51712).
+char(0,51713).
+char(9,51714).
+char(c,51715).
+char(m,51716).
+char(o,51717).
+char(m,51718).
+char(o,51719).
+char(m,51720).
+char(7,51721).
+char(8,51722).
+char(4,51723).
+char(7,51724).
+char(c,51725).
+char(c,51726).
+char(p,51727).
+char(1,51728).
+char(1,51729).
+char(7,51730).
+char(3,51731).
+char(p,51732).
+char(o,51733).
+char(p,51734).
+char(3,51735).
+char(7,51736).
+char(9,51737).
+char(0,51738).
+char(c,51739).
+char(m,51740).
+char(o,51741).
+char(p,51742).
+char(o,51743).
+char(m,51744).
+char(o,51745).
+char(m,51746).
+char(o,51747).
+char(m,51748).
+char(9,51749).
+char(8,51750).
+char(4,51751).
+char(3,51752).
+char(c,51753).
+char(p,51754).
+char(o,51755).
+char(m,51756).
+char(5,51757).
+char(2,51758).
+char(4,51759).
+char(7,51760).
+char(c,51761).
+char(c,51762).
+char(m,51763).
+char(9,51764).
+char(8,51765).
+char(7,51766).
+char(5,51767).
+char(c,51768).
+char(c,51769).
+char(c,51770).
+char(m,51771).
+char(8,51772).
+char(4,51773).
+char(4,51774).
+char(4,51775).
+char(c,51776).
+char(m,51777).
+char(o,51778).
+char(m,51779).
+char(5,51780).
+char(4,51781).
+char(3,51782).
+char(7,51783).
+char(p,51784).
+char(o,51785).
+char(m,51786).
+char(o,51787).
+char(p,51788).
+char(1,51789).
+char(5,51790).
+char(5,51791).
+char(9,51792).
+char(p,51793).
+char(5,51794).
+char(8,51795).
+char(5,51796).
+char(p,51797).
+char(4,51798).
+char(7,51799).
+char(6,51800).
+char(5,51801).
+char(c,51802).
+char(c,51803).
+char(p,51804).
+char(9,51805).
+char(9,51806).
+char(5,51807).
+char(7,51808).
+char(m,51809).
+char(9,51810).
+char(7,51811).
+char(6,51812).
+char(7,51813).
+char(c,51814).
+char(c,51815).
+char(m,51816).
+char(1,51817).
+char(6,51818).
+char(7,51819).
+char(5,51820).
+char(c,51821).
+char(c,51822).
+char(p,51823).
+char(4,51824).
+char(2,51825).
+char(1,51826).
+char(2,51827).
+char(p,51828).
+char(1,51829).
+char(0,51830).
+char(3,51831).
+char(1,51832).
+char(c,51833).
+char(c,51834).
+char(c,51835).
+char(c,51836).
+char(c,51837).
+char(c,51838).
+char(c,51839).
+char(c,51840).
+char(c,51841).
+char(p,51842).
+char(o,51843).
+char(m,51844).
+char(2,51845).
+char(1,51846).
+char(6,51847).
+char(4,51848).
+char(c,51849).
+char(p,51850).
+char(6,51851).
+char(7,51852).
+char(7,51853).
+char(1,51854).
+char(c,51855).
+char(c,51856).
+char(m,51857).
+char(o,51858).
+char(m,51859).
+char(o,51860).
+char(9,51861).
+char(3,51862).
+char(3,51863).
+char(7,51864).
+char(c,51865).
+char(c,51866).
+char(p,51867).
+char(o,51868).
+char(o,51869).
+char(p,51870).
+char(4,51871).
+char(2,51872).
+char(3,51873).
+char(8,51874).
+char(c,51875).
+char(c,51876).
+char(p,51877).
+char(5,51878).
+char(8,51879).
+char(8,51880).
+char(9,51881).
+char(p,51882).
+char(8,51883).
+char(4,51884).
+char(8,51885).
+char(2,51886).
+char(p,51887).
+char(o,51888).
+char(3,51889).
+char(3,51890).
+char(8,51891).
+char(5,51892).
+char(c,51893).
+char(p,51894).
+char(o,51895).
+char(5,51896).
+char(4,51897).
+char(0,51898).
+char(0,51899).
+char(m,51900).
+char(8,51901).
+char(6,51902).
+char(8,51903).
+char(9,51904).
+char(p,51905).
+char(7,51906).
+char(6,51907).
+char(2,51908).
+char(1,51909).
+char(c,51910).
+char(p,51911).
+char(7,51912).
+char(7,51913).
+char(1,51914).
+char(5,51915).
+char(m,51916).
+char(o,51917).
+char(p,51918).
+char(2,51919).
+char(7,51920).
+char(5,51921).
+char(9,51922).
+char(p,51923).
+char(4,51924).
+char(0,51925).
+char(7,51926).
+char(m,51927).
+char(4,51928).
+char(4,51929).
+char(9,51930).
+char(6,51931).
+char(c,51932).
+char(m,51933).
+char(2,51934).
+char(3,51935).
+char(5,51936).
+char(c,51937).
+char(m,51938).
+char(2,51939).
+char(8,51940).
+char(6,51941).
+char(6,51942).
+char(p,51943).
+char(o,51944).
+char(p,51945).
+char(o,51946).
+char(o,51947).
+char(m,51948).
+char(o,51949).
+char(p,51950).
+char(5,51951).
+char(7,51952).
+char(0,51953).
+char(7,51954).
+char(c,51955).
+char(m,51956).
+char(o,51957).
+char(p,51958).
+char(o,51959).
+char(p,51960).
+char(7,51961).
+char(3,51962).
+char(4,51963).
+char(0,51964).
+char(p,51965).
+char(7,51966).
+char(6,51967).
+char(9,51968).
+char(2,51969).
+char(p,51970).
+char(5,51971).
+char(7,51972).
+char(9,51973).
+char(c,51974).
+char(p,51975).
+char(o,51976).
+char(p,51977).
+char(o,51978).
+char(m,51979).
+char(o,51980).
+char(p,51981).
+char(o,51982).
+char(m,51983).
+char(o,51984).
+char(o,51985).
+char(o,51986).
+char(p,51987).
+char(8,51988).
+char(8,51989).
+char(9,51990).
+char(9,51991).
+char(c,51992).
+char(m,51993).
+char(3,51994).
+char(3,51995).
+char(1,51996).
+char(m,51997).
+char(7,51998).
+char(4,51999).
+char(1,52000).
+char(5,52001).
+char(c,52002).
+char(m,52003).
+char(o,52004).
+char(5,52005).
+char(9,52006).
+char(7,52007).
+char(3,52008).
+char(m,52009).
+char(8,52010).
+char(0,52011).
+char(7,52012).
+char(1,52013).
+char(m,52014).
+char(o,52015).
+char(m,52016).
+char(6,52017).
+char(6,52018).
+char(5,52019).
+char(1,52020).
+char(c,52021).
+char(p,52022).
+char(o,52023).
+char(m,52024).
+char(o,52025).
+char(9,52026).
+char(3,52027).
+char(2,52028).
+char(6,52029).
+char(p,52030).
+char(1,52031).
+char(4,52032).
+char(3,52033).
+char(0,52034).
+char(m,52035).
+char(1,52036).
+char(3,52037).
+char(6,52038).
+char(2,52039).
+char(c,52040).
+char(p,52041).
+char(o,52042).
+char(p,52043).
+char(2,52044).
+char(9,52045).
+char(1,52046).
+char(2,52047).
+char(c,52048).
+char(c,52049).
+char(c,52050).
+char(p,52051).
+char(o,52052).
+char(m,52053).
+char(o,52054).
+char(o,52055).
+char(p,52056).
+char(9,52057).
+char(3,52058).
+char(9,52059).
+char(7,52060).
+char(p,52061).
+char(o,52062).
+char(9,52063).
+char(7,52064).
+char(1,52065).
+char(8,52066).
+char(c,52067).
+char(c,52068).
+char(m,52069).
+char(2,52070).
+char(9,52071).
+char(4,52072).
+char(1,52073).
+char(m,52074).
+char(o,52075).
+char(p,52076).
+char(4,52077).
+char(6,52078).
+char(4,52079).
+char(4,52080).
+char(m,52081).
+char(7,52082).
+char(9,52083).
+char(6,52084).
+char(c,52085).
+char(p,52086).
+char(o,52087).
+char(o,52088).
+char(o,52089).
+char(p,52090).
+char(o,52091).
+char(p,52092).
+char(o,52093).
+char(m,52094).
+char(3,52095).
+char(2,52096).
+char(7,52097).
+char(1,52098).
+char(c,52099).
+char(c,52100).
+char(c,52101).
+char(m,52102).
+char(o,52103).
+char(p,52104).
+char(7,52105).
+char(0,52106).
+char(3,52107).
+char(5,52108).
+char(c,52109).
+char(p,52110).
+char(o,52111).
+char(m,52112).
+char(o,52113).
+char(p,52114).
+char(o,52115).
+char(m,52116).
+char(4,52117).
+char(5,52118).
+char(1,52119).
+char(c,52120).
+char(c,52121).
+char(p,52122).
+char(1,52123).
+char(0,52124).
+char(0,52125).
+char(8,52126).
+char(p,52127).
+char(o,52128).
+char(1,52129).
+char(8,52130).
+char(9,52131).
+char(8,52132).
+char(c,52133).
+char(m,52134).
+char(6,52135).
+char(3,52136).
+char(4,52137).
+char(9,52138).
+char(m,52139).
+char(o,52140).
+char(m,52141).
+char(o,52142).
+char(p,52143).
+char(5,52144).
+char(4,52145).
+char(9,52146).
+char(2,52147).
+char(c,52148).
+char(m,52149).
+char(o,52150).
+char(p,52151).
+char(o,52152).
+char(m,52153).
+char(o,52154).
+char(m,52155).
+char(o,52156).
+char(m,52157).
+char(1,52158).
+char(8,52159).
+char(5,52160).
+char(0,52161).
+char(m,52162).
+char(6,52163).
+char(8,52164).
+char(2,52165).
+char(3,52166).
+char(c,52167).
+char(m,52168).
+char(o,52169).
+char(m,52170).
+char(o,52171).
+char(6,52172).
+char(3,52173).
+char(7,52174).
+char(7,52175).
+char(c,52176).
+char(p,52177).
+char(6,52178).
+char(2,52179).
+char(9,52180).
+char(6,52181).
+char(p,52182).
+char(o,52183).
+char(m,52184).
+char(o,52185).
+char(o,52186).
+char(o,52187).
+char(p,52188).
+char(o,52189).
+char(m,52190).
+char(1,52191).
+char(3,52192).
+char(6,52193).
+char(9,52194).
+char(p,52195).
+char(5,52196).
+char(4,52197).
+char(6,52198).
+char(3,52199).
+char(c,52200).
+char(m,52201).
+char(o,52202).
+char(p,52203).
+char(o,52204).
+char(m,52205).
+char(6,52206).
+char(0,52207).
+char(9,52208).
+char(0,52209).
+char(p,52210).
+char(o,52211).
+char(o,52212).
+char(p,52213).
+char(3,52214).
+char(4,52215).
+char(1,52216).
+char(6,52217).
+char(c,52218).
+char(p,52219).
+char(o,52220).
+char(p,52221).
+char(2,52222).
+char(3,52223).
+char(6,52224).
+char(9,52225).
+char(c,52226).
+char(p,52227).
+char(o,52228).
+char(o,52229).
+char(5,52230).
+char(6,52231).
+char(4,52232).
+char(c,52233).
+char(p,52234).
+char(o,52235).
+char(o,52236).
+char(m,52237).
+char(o,52238).
+char(8,52239).
+char(3,52240).
+char(1,52241).
+char(3,52242).
+char(m,52243).
+char(2,52244).
+char(6,52245).
+char(7,52246).
+char(0,52247).
+char(p,52248).
+char(o,52249).
+char(p,52250).
+char(6,52251).
+char(3,52252).
+char(0,52253).
+char(3,52254).
+char(p,52255).
+char(o,52256).
+char(p,52257).
+char(6,52258).
+char(1,52259).
+char(4,52260).
+char(4,52261).
+char(p,52262).
+char(o,52263).
+char(p,52264).
+char(o,52265).
+char(o,52266).
+char(3,52267).
+char(7,52268).
+char(6,52269).
+char(5,52270).
+char(p,52271).
+char(o,52272).
+char(7,52273).
+char(6,52274).
+char(9,52275).
+char(4,52276).
+char(p,52277).
+char(o,52278).
+char(p,52279).
+char(o,52280).
+char(p,52281).
+char(5,52282).
+char(8,52283).
+char(8,52284).
+char(0,52285).
+char(m,52286).
+char(o,52287).
+char(p,52288).
+char(o,52289).
+char(p,52290).
+char(7,52291).
+char(2,52292).
+char(4,52293).
+char(2,52294).
+char(p,52295).
+char(2,52296).
+char(8,52297).
+char(2,52298).
+char(3,52299).
+char(m,52300).
+char(5,52301).
+char(0,52302).
+char(1,52303).
+char(5,52304).
+char(m,52305).
+char(o,52306).
+char(2,52307).
+char(9,52308).
+char(2,52309).
+char(m,52310).
+char(6,52311).
+char(7,52312).
+char(2,52313).
+char(5,52314).
+char(c,52315).
+char(m,52316).
+char(7,52317).
+char(3,52318).
+char(0,52319).
+char(m,52320).
+char(4,52321).
+char(6,52322).
+char(1,52323).
+char(2,52324).
+char(c,52325).
+char(p,52326).
+char(o,52327).
+char(m,52328).
+char(3,52329).
+char(0,52330).
+char(6,52331).
+char(5,52332).
+char(c,52333).
+char(m,52334).
+char(o,52335).
+char(p,52336).
+char(3,52337).
+char(4,52338).
+char(4,52339).
+char(3,52340).
+char(p,52341).
+char(9,52342).
+char(6,52343).
+char(5,52344).
+char(9,52345).
+char(c,52346).
+char(m,52347).
+char(8,52348).
+char(2,52349).
+char(9,52350).
+char(0,52351).
+char(c,52352).
+char(p,52353).
+char(9,52354).
+char(3,52355).
+char(6,52356).
+char(0,52357).
+char(m,52358).
+char(3,52359).
+char(4,52360).
+char(2,52361).
+char(4,52362).
+char(m,52363).
+char(3,52364).
+char(1,52365).
+char(4,52366).
+char(8,52367).
+char(p,52368).
+char(6,52369).
+char(9,52370).
+char(8,52371).
+char(3,52372).
+char(m,52373).
+char(2,52374).
+char(8,52375).
+char(8,52376).
+char(1,52377).
+char(c,52378).
+char(m,52379).
+char(7,52380).
+char(4,52381).
+char(4,52382).
+char(0,52383).
+char(m,52384).
+char(o,52385).
+char(6,52386).
+char(4,52387).
+char(4,52388).
+char(7,52389).
+char(c,52390).
+char(m,52391).
+char(o,52392).
+char(m,52393).
+char(5,52394).
+char(7,52395).
+char(7,52396).
+char(5,52397).
+char(c,52398).
+char(m,52399).
+char(8,52400).
+char(8,52401).
+char(6,52402).
+char(0,52403).
+char(c,52404).
+char(m,52405).
+char(o,52406).
+char(m,52407).
+char(o,52408).
+char(p,52409).
+char(o,52410).
+char(3,52411).
+char(9,52412).
+char(6,52413).
+char(5,52414).
+char(m,52415).
+char(o,52416).
+char(o,52417).
+char(o,52418).
+char(m,52419).
+char(o,52420).
+char(7,52421).
+char(9,52422).
+char(5,52423).
+char(c,52424).
+char(c,52425).
+char(c,52426).
+char(c,52427).
+char(c,52428).
+char(m,52429).
+char(5,52430).
+char(0,52431).
+char(7,52432).
+char(7,52433).
+char(c,52434).
+char(c,52435).
+char(c,52436).
+char(m,52437).
+char(o,52438).
+char(p,52439).
+char(7,52440).
+char(8,52441).
+char(0,52442).
+char(3,52443).
+char(c,52444).
+char(c,52445).
+char(c,52446).
+char(p,52447).
+char(o,52448).
+char(m,52449).
+char(o,52450).
+char(p,52451).
+char(o,52452).
+char(m,52453).
+char(o,52454).
+char(3,52455).
+char(1,52456).
+char(8,52457).
+char(4,52458).
+char(c,52459).
+char(c,52460).
+char(p,52461).
+char(o,52462).
+char(p,52463).
+char(o,52464).
+char(7,52465).
+char(1,52466).
+char(4,52467).
+char(1,52468).
+char(p,52469).
+char(o,52470).
+char(p,52471).
+char(o,52472).
+char(4,52473).
+char(7,52474).
+char(1,52475).
+char(3,52476).
+char(c,52477).
+char(p,52478).
+char(o,52479).
+char(p,52480).
+char(4,52481).
+char(8,52482).
+char(7,52483).
+char(2,52484).
+char(m,52485).
+char(6,52486).
+char(9,52487).
+char(3,52488).
+char(3,52489).
+char(c,52490).
+char(c,52491).
+char(c,52492).
+char(m,52493).
+char(o,52494).
+char(p,52495).
+char(o,52496).
+char(o,52497).
+char(m,52498).
+char(2,52499).
+char(3,52500).
+char(3,52501).
+char(8,52502).
+char(m,52503).
+char(o,52504).
+char(m,52505).
+char(1,52506).
+char(8,52507).
+char(0,52508).
+char(1,52509).
+char(p,52510).
+char(7,52511).
+char(4,52512).
+char(5,52513).
+char(6,52514).
+char(m,52515).
+char(o,52516).
+char(m,52517).
+char(o,52518).
+char(p,52519).
+char(o,52520).
+char(m,52521).
+char(o,52522).
+char(m,52523).
+char(5,52524).
+char(0,52525).
+char(2,52526).
+char(7,52527).
+char(m,52528).
+char(7,52529).
+char(9,52530).
+char(7,52531).
+char(4,52532).
+char(c,52533).
+char(c,52534).
+char(c,52535).
+char(c,52536).
+char(m,52537).
+char(1,52538).
+char(8,52539).
+char(0,52540).
+char(1,52541).
+char(m,52542).
+char(o,52543).
+char(p,52544).
+char(2,52545).
+char(9,52546).
+char(8,52547).
+char(2,52548).
+char(c,52549).
+char(c,52550).
+char(c,52551).
+char(p,52552).
+char(o,52553).
+char(p,52554).
+char(o,52555).
+char(p,52556).
+char(5,52557).
+char(6,52558).
+char(5,52559).
+char(1,52560).
+char(c,52561).
+char(c,52562).
+char(p,52563).
+char(9,52564).
+char(4,52565).
+char(2,52566).
+char(8,52567).
+char(c,52568).
+char(p,52569).
+char(4,52570).
+char(2,52571).
+char(3,52572).
+char(8,52573).
+char(m,52574).
+char(7,52575).
+char(7,52576).
+char(0,52577).
+char(3,52578).
+char(p,52579).
+char(4,52580).
+char(4,52581).
+char(6,52582).
+char(0,52583).
+char(p,52584).
+char(4,52585).
+char(1,52586).
+char(0,52587).
+char(7,52588).
+char(m,52589).
+char(o,52590).
+char(p,52591).
+char(6,52592).
+char(2,52593).
+char(4,52594).
+char(3,52595).
+char(c,52596).
+char(p,52597).
+char(9,52598).
+char(1,52599).
+char(2,52600).
+char(9,52601).
+char(p,52602).
+char(o,52603).
+char(m,52604).
+char(1,52605).
+char(0,52606).
+char(0,52607).
+char(5,52608).
+char(m,52609).
+char(7,52610).
+char(1,52611).
+char(9,52612).
+char(9,52613).
+char(m,52614).
+char(o,52615).
+char(o,52616).
+char(p,52617).
+char(1,52618).
+char(7,52619).
+char(4,52620).
+char(4,52621).
+char(p,52622).
+char(2,52623).
+char(9,52624).
+char(6,52625).
+char(4,52626).
+char(p,52627).
+char(5,52628).
+char(2,52629).
+char(3,52630).
+char(0,52631).
+char(p,52632).
+char(o,52633).
+char(p,52634).
+char(o,52635).
+char(m,52636).
+char(o,52637).
+char(p,52638).
+char(8,52639).
+char(2,52640).
+char(8,52641).
+char(3,52642).
+char(m,52643).
+char(o,52644).
+char(p,52645).
+char(2,52646).
+char(6,52647).
+char(6,52648).
+char(0,52649).
+char(m,52650).
+char(4,52651).
+char(2,52652).
+char(5,52653).
+char(p,52654).
+char(2,52655).
+char(7,52656).
+char(3,52657).
+char(8,52658).
+char(m,52659).
+char(o,52660).
+char(6,52661).
+char(9,52662).
+char(0,52663).
+char(3,52664).
+char(p,52665).
+char(8,52666).
+char(3,52667).
+char(0,52668).
+char(7,52669).
+char(m,52670).
+char(3,52671).
+char(2,52672).
+char(1,52673).
+char(9,52674).
+char(m,52675).
+char(8,52676).
+char(5,52677).
+char(5,52678).
+char(3,52679).
+char(c,52680).
+char(c,52681).
+char(c,52682).
+char(c,52683).
+char(c,52684).
+char(m,52685).
+char(o,52686).
+char(p,52687).
+char(o,52688).
+char(p,52689).
+char(o,52690).
+char(p,52691).
+char(8,52692).
+char(5,52693).
+char(2,52694).
+char(2,52695).
+char(c,52696).
+char(c,52697).
+char(c,52698).
+char(m,52699).
+char(o,52700).
+char(p,52701).
+char(1,52702).
+char(1,52703).
+char(7,52704).
+char(2,52705).
+char(c,52706).
+char(c,52707).
+char(m,52708).
+char(o,52709).
+char(m,52710).
+char(o,52711).
+char(o,52712).
+char(o,52713).
+char(p,52714).
+char(5,52715).
+char(1,52716).
+char(8,52717).
+char(7,52718).
+char(c,52719).
+char(c,52720).
+char(p,52721).
+char(2,52722).
+char(7,52723).
+char(9,52724).
+char(4,52725).
+char(m,52726).
+char(o,52727).
+char(6,52728).
+char(0,52729).
+char(9,52730).
+char(1,52731).
+char(c,52732).
+char(m,52733).
+char(7,52734).
+char(2,52735).
+char(4,52736).
+char(7,52737).
+char(c,52738).
+char(c,52739).
+char(m,52740).
+char(o,52741).
+char(p,52742).
+char(8,52743).
+char(7,52744).
+char(3,52745).
+char(9,52746).
+char(c,52747).
+char(c,52748).
+char(p,52749).
+char(7,52750).
+char(9,52751).
+char(6,52752).
+char(6,52753).
+char(c,52754).
+char(c,52755).
+char(c,52756).
+char(c,52757).
+char(p,52758).
+char(3,52759).
+char(3,52760).
+char(5,52761).
+char(0,52762).
+char(c,52763).
+char(c,52764).
+char(m,52765).
+char(2,52766).
+char(5,52767).
+char(5,52768).
+char(1,52769).
+char(c,52770).
+char(p,52771).
+char(7,52772).
+char(2,52773).
+char(6,52774).
+char(2,52775).
+char(p,52776).
+char(o,52777).
+char(p,52778).
+char(o,52779).
+char(m,52780).
+char(4,52781).
+char(6,52782).
+char(9,52783).
+char(p,52784).
+char(o,52785).
+char(m,52786).
+char(o,52787).
+char(p,52788).
+char(1,52789).
+char(8,52790).
+char(8,52791).
+char(2,52792).
+char(m,52793).
+char(2,52794).
+char(6,52795).
+char(9,52796).
+char(5,52797).
+char(c,52798).
+char(c,52799).
+char(c,52800).
+char(c,52801).
+char(c,52802).
+char(c,52803).
+char(c,52804).
+char(m,52805).
+char(o,52806).
+char(p,52807).
+char(9,52808).
+char(0,52809).
+char(2,52810).
+char(9,52811).
+char(m,52812).
+char(6,52813).
+char(6,52814).
+char(3,52815).
+char(2,52816).
+char(c,52817).
+char(c,52818).
+char(m,52819).
+char(o,52820).
+char(o,52821).
+char(m,52822).
+char(7,52823).
+char(5,52824).
+char(8,52825).
+char(6,52826).
+char(c,52827).
+char(p,52828).
+char(8,52829).
+char(3,52830).
+char(0,52831).
+char(c,52832).
+char(m,52833).
+char(o,52834).
+char(p,52835).
+char(7,52836).
+char(3,52837).
+char(3,52838).
+char(6,52839).
+char(c,52840).
+char(c,52841).
+char(m,52842).
+char(o,52843).
+char(o,52844).
+char(m,52845).
+char(o,52846).
+char(p,52847).
+char(o,52848).
+char(6,52849).
+char(2,52850).
+char(0,52851).
+char(3,52852).
+char(c,52853).
+char(m,52854).
+char(o,52855).
+char(o,52856).
+char(m,52857).
+char(5,52858).
+char(8,52859).
+char(3,52860).
+char(0,52861).
+char(m,52862).
+char(o,52863).
+char(o,52864).
+char(o,52865).
+char(9,52866).
+char(1,52867).
+char(4,52868).
+char(1,52869).
+char(m,52870).
+char(o,52871).
+char(5,52872).
+char(5,52873).
+char(c,52874).
+char(c,52875).
+char(c,52876).
+char(c,52877).
+char(p,52878).
+char(o,52879).
+char(m,52880).
+char(o,52881).
+char(p,52882).
+char(o,52883).
+char(m,52884).
+char(1,52885).
+char(7,52886).
+char(8,52887).
+char(p,52888).
+char(7,52889).
+char(7,52890).
+char(2,52891).
+char(0,52892).
+char(c,52893).
+char(p,52894).
+char(o,52895).
+char(6,52896).
+char(9,52897).
+char(1,52898).
+char(5,52899).
+char(c,52900).
+char(c,52901).
+char(c,52902).
+char(c,52903).
+char(m,52904).
+char(1,52905).
+char(7,52906).
+char(4,52907).
+char(6,52908).
+char(c,52909).
+char(c,52910).
+char(p,52911).
+char(7,52912).
+char(3,52913).
+char(5,52914).
+char(2,52915).
+char(p,52916).
+char(o,52917).
+char(7,52918).
+char(5,52919).
+char(4,52920).
+char(9,52921).
+char(c,52922).
+char(p,52923).
+char(5,52924).
+char(2,52925).
+char(9,52926).
+char(9,52927).
+char(c,52928).
+char(m,52929).
+char(o,52930).
+char(p,52931).
+char(5,52932).
+char(5,52933).
+char(2,52934).
+char(1,52935).
+char(p,52936).
+char(3,52937).
+char(4,52938).
+char(7,52939).
+char(0,52940).
+char(c,52941).
+char(m,52942).
+char(o,52943).
+char(m,52944).
+char(7,52945).
+char(1,52946).
+char(0,52947).
+char(8,52948).
+char(p,52949).
+char(o,52950).
+char(2,52951).
+char(5,52952).
+char(5,52953).
+char(9,52954).
+char(m,52955).
+char(o,52956).
+char(1,52957).
+char(7,52958).
+char(7,52959).
+char(9,52960).
+char(p,52961).
+char(o,52962).
+char(p,52963).
+char(8,52964).
+char(0,52965).
+char(9,52966).
+char(5,52967).
+char(c,52968).
+char(p,52969).
+char(o,52970).
+char(m,52971).
+char(1,52972).
+char(7,52973).
+char(6,52974).
+char(6,52975).
+char(p,52976).
+char(5,52977).
+char(9,52978).
+char(9,52979).
+char(9,52980).
+char(c,52981).
+char(c,52982).
+char(c,52983).
+char(m,52984).
+char(4,52985).
+char(6,52986).
+char(8,52987).
+char(5,52988).
+char(c,52989).
+char(c,52990).
+char(c,52991).
+char(c,52992).
+char(c,52993).
+char(c,52994).
+char(p,52995).
+char(o,52996).
+char(m,52997).
+char(o,52998).
+char(m,52999).
+char(8,53000).
+char(3,53001).
+char(7,53002).
+char(c,53003).
+char(c,53004).
+char(c,53005).
+char(c,53006).
+char(p,53007).
+char(5,53008).
+char(4,53009).
+char(6,53010).
+char(5,53011).
+char(c,53012).
+char(c,53013).
+char(m,53014).
+char(o,53015).
+char(o,53016).
+char(9,53017).
+char(6,53018).
+char(1,53019).
+char(3,53020).
+char(m,53021).
+char(5,53022).
+char(0,53023).
+char(4,53024).
+char(1,53025).
+char(m,53026).
+char(o,53027).
+char(p,53028).
+char(o,53029).
+char(p,53030).
+char(1,53031).
+char(1,53032).
+char(1,53033).
+char(5,53034).
+char(c,53035).
+char(c,53036).
+char(m,53037).
+char(5,53038).
+char(0,53039).
+char(6,53040).
+char(3,53041).
+char(m,53042).
+char(o,53043).
+char(2,53044).
+char(3,53045).
+char(5,53046).
+char(7,53047).
+char(p,53048).
+char(o,53049).
+char(o,53050).
+char(p,53051).
+char(8,53052).
+char(3,53053).
+char(8,53054).
+char(8,53055).
+char(c,53056).
+char(c,53057).
+char(m,53058).
+char(o,53059).
+char(m,53060).
+char(6,53061).
+char(8,53062).
+char(1,53063).
+char(5,53064).
+char(c,53065).
+char(m,53066).
+char(6,53067).
+char(7,53068).
+char(9,53069).
+char(4,53070).
+char(p,53071).
+char(2,53072).
+char(3,53073).
+char(2,53074).
+char(8,53075).
+char(m,53076).
+char(5,53077).
+char(2,53078).
+char(6,53079).
+char(1,53080).
+char(m,53081).
+char(8,53082).
+char(4,53083).
+char(5,53084).
+char(9,53085).
+char(m,53086).
+char(4,53087).
+char(7,53088).
+char(2,53089).
+char(7,53090).
+char(p,53091).
+char(o,53092).
+char(m,53093).
+char(o,53094).
+char(p,53095).
+char(8,53096).
+char(4,53097).
+char(4,53098).
+char(1,53099).
+char(m,53100).
+char(o,53101).
+char(o,53102).
+char(p,53103).
+char(o,53104).
+char(m,53105).
+char(o,53106).
+char(p,53107).
+char(8,53108).
+char(6,53109).
+char(3,53110).
+char(6,53111).
+char(c,53112).
+char(c,53113).
+char(p,53114).
+char(o,53115).
+char(o,53116).
+char(m,53117).
+char(4,53118).
+char(9,53119).
+char(6,53120).
+char(9,53121).
+char(m,53122).
+char(o,53123).
+char(o,53124).
+char(o,53125).
+char(m,53126).
+char(o,53127).
+char(m,53128).
+char(6,53129).
+char(8,53130).
+char(1,53131).
+char(8,53132).
+char(c,53133).
+char(c,53134).
+char(m,53135).
+char(o,53136).
+char(9,53137).
+char(0,53138).
+char(6,53139).
+char(9,53140).
+char(c,53141).
+char(p,53142).
+char(o,53143).
+char(p,53144).
+char(o,53145).
+char(3,53146).
+char(5,53147).
+char(1,53148).
+char(2,53149).
+char(c,53150).
+char(m,53151).
+char(5,53152).
+char(3,53153).
+char(1,53154).
+char(1,53155).
+char(c,53156).
+char(m,53157).
+char(5,53158).
+char(7,53159).
+char(3,53160).
+char(4,53161).
+char(p,53162).
+char(o,53163).
+char(m,53164).
+char(o,53165).
+char(p,53166).
+char(6,53167).
+char(0,53168).
+char(5,53169).
+char(c,53170).
+char(c,53171).
+char(m,53172).
+char(7,53173).
+char(4,53174).
+char(1,53175).
+char(2,53176).
+char(p,53177).
+char(6,53178).
+char(5,53179).
+char(5,53180).
+char(6,53181).
+char(c,53182).
+char(c,53183).
+char(c,53184).
+char(c,53185).
+char(c,53186).
+char(c,53187).
+char(c,53188).
+char(m,53189).
+char(8,53190).
+char(c,53191).
+char(c,53192).
+char(p,53193).
+char(2,53194).
+char(5,53195).
+char(7,53196).
+char(7,53197).
+char(c,53198).
+char(p,53199).
+char(o,53200).
+char(o,53201).
+char(o,53202).
+char(m,53203).
+char(8,53204).
+char(0,53205).
+char(3,53206).
+char(6,53207).
+char(m,53208).
+char(9,53209).
+char(8,53210).
+char(1,53211).
+char(9,53212).
+char(c,53213).
+char(c,53214).
+char(p,53215).
+char(3,53216).
+char(4,53217).
+char(2,53218).
+char(0,53219).
+char(m,53220).
+char(o,53221).
+char(o,53222).
+char(m,53223).
+char(7,53224).
+char(9,53225).
+char(1,53226).
+char(5,53227).
+char(p,53228).
+char(o,53229).
+char(o,53230).
+char(o,53231).
+char(8,53232).
+char(0,53233).
+char(9,53234).
+char(6,53235).
+char(p,53236).
+char(8,53237).
+char(3,53238).
+char(0,53239).
+char(6,53240).
+char(c,53241).
+char(p,53242).
+char(o,53243).
+char(m,53244).
+char(o,53245).
+char(p,53246).
+char(o,53247).
+char(p,53248).
+char(8,53249).
+char(0,53250).
+char(4,53251).
+char(2,53252).
+char(m,53253).
+char(o,53254).
+char(p,53255).
+char(o,53256).
+char(5,53257).
+char(4,53258).
+char(3,53259).
+char(0,53260).
+char(c,53261).
+char(p,53262).
+char(o,53263).
+char(p,53264).
+char(o,53265).
+char(m,53266).
+char(o,53267).
+char(p,53268).
+char(o,53269).
+char(p,53270).
+char(8,53271).
+char(6,53272).
+char(4,53273).
+char(c,53274).
+char(p,53275).
+char(3,53276).
+char(9,53277).
+char(5,53278).
+char(2,53279).
+char(m,53280).
+char(o,53281).
+char(p,53282).
+char(2,53283).
+char(2,53284).
+char(1,53285).
+char(7,53286).
+char(p,53287).
+char(o,53288).
+char(8,53289).
+char(3,53290).
+char(3,53291).
+char(5,53292).
+char(c,53293).
+char(c,53294).
+char(m,53295).
+char(7,53296).
+char(3,53297).
+char(2,53298).
+char(4,53299).
+char(p,53300).
+char(o,53301).
+char(p,53302).
+char(o,53303).
+char(m,53304).
+char(8,53305).
+char(0,53306).
+char(3,53307).
+char(0,53308).
+char(c,53309).
+char(c,53310).
+char(m,53311).
+char(o,53312).
+char(m,53313).
+char(2,53314).
+char(7,53315).
+char(0,53316).
+char(9,53317).
+char(c,53318).
+char(c,53319).
+char(p,53320).
+char(o,53321).
+char(o,53322).
+char(5,53323).
+char(0,53324).
+char(3,53325).
+char(4,53326).
+char(p,53327).
+char(o,53328).
+char(p,53329).
+char(o,53330).
+char(4,53331).
+char(9,53332).
+char(3,53333).
+char(7,53334).
+char(m,53335).
+char(o,53336).
+char(m,53337).
+char(o,53338).
+char(p,53339).
+char(o,53340).
+char(p,53341).
+char(3,53342).
+char(7,53343).
+char(4,53344).
+char(7,53345).
+char(c,53346).
+char(m,53347).
+char(o,53348).
+char(1,53349).
+char(0,53350).
+char(6,53351).
+char(6,53352).
+char(m,53353).
+char(o,53354).
+char(m,53355).
+char(5,53356).
+char(7,53357).
+char(4,53358).
+char(1,53359).
+char(c,53360).
+char(c,53361).
+char(c,53362).
+char(c,53363).
+char(p,53364).
+char(o,53365).
+char(m,53366).
+char(o,53367).
+char(p,53368).
+char(o,53369).
+char(o,53370).
+char(m,53371).
+char(3,53372).
+char(1,53373).
+char(5,53374).
+char(9,53375).
+char(m,53376).
+char(8,53377).
+char(7,53378).
+char(7,53379).
+char(3,53380).
+char(c,53381).
+char(c,53382).
+char(c,53383).
+char(m,53384).
+char(o,53385).
+char(6,53386).
+char(4,53387).
+char(1,53388).
+char(4,53389).
+char(p,53390).
+char(o,53391).
+char(m,53392).
+char(7,53393).
+char(8,53394).
+char(6,53395).
+char(1,53396).
+char(c,53397).
+char(p,53398).
+char(o,53399).
+char(o,53400).
+char(m,53401).
+char(o,53402).
+char(p,53403).
+char(8,53404).
+char(4,53405).
+char(6,53406).
+char(7,53407).
+char(m,53408).
+char(7,53409).
+char(6,53410).
+char(3,53411).
+char(0,53412).
+char(m,53413).
+char(o,53414).
+char(p,53415).
+char(o,53416).
+char(m,53417).
+char(2,53418).
+char(8,53419).
+char(4,53420).
+char(7,53421).
+char(c,53422).
+char(c,53423).
+char(p,53424).
+char(o,53425).
+char(o,53426).
+char(m,53427).
+char(2,53428).
+char(4,53429).
+char(1,53430).
+char(7,53431).
+char(p,53432).
+char(6,53433).
+char(4,53434).
+char(9,53435).
+char(9,53436).
+char(c,53437).
+char(c,53438).
+char(c,53439).
+char(c,53440).
+char(p,53441).
+char(7,53442).
+char(0,53443).
+char(9,53444).
+char(7,53445).
+char(m,53446).
+char(3,53447).
+char(7,53448).
+char(5,53449).
+char(6,53450).
+char(m,53451).
+char(9,53452).
+char(1,53453).
+char(1,53454).
+char(p,53455).
+char(8,53456).
+char(1,53457).
+char(2,53458).
+char(1,53459).
+char(c,53460).
+char(m,53461).
+char(o,53462).
+char(p,53463).
+char(6,53464).
+char(7,53465).
+char(4,53466).
+char(6,53467).
+char(p,53468).
+char(o,53469).
+char(9,53470).
+char(1,53471).
+char(1,53472).
+char(c,53473).
+char(p,53474).
+char(o,53475).
+char(m,53476).
+char(8,53477).
+char(3,53478).
+char(8,53479).
+char(0,53480).
+char(c,53481).
+char(c,53482).
+char(p,53483).
+char(7,53484).
+char(7,53485).
+char(0,53486).
+char(0,53487).
+char(m,53488).
+char(o,53489).
+char(o,53490).
+char(m,53491).
+char(5,53492).
+char(6,53493).
+char(7,53494).
+char(4,53495).
+char(m,53496).
+char(o,53497).
+char(p,53498).
+char(o,53499).
+char(2,53500).
+char(5,53501).
+char(3,53502).
+char(8,53503).
+char(p,53504).
+char(2,53505).
+char(1,53506).
+char(4,53507).
+char(6,53508).
+char(m,53509).
+char(o,53510).
+char(m,53511).
+char(o,53512).
+char(o,53513).
+char(p,53514).
+char(6,53515).
+char(2,53516).
+char(4,53517).
+char(1,53518).
+char(m,53519).
+char(o,53520).
+char(p,53521).
+char(o,53522).
+char(m,53523).
+char(o,53524).
+char(o,53525).
+char(7,53526).
+char(9,53527).
+char(7,53528).
+char(0,53529).
+char(m,53530).
+char(6,53531).
+char(2,53532).
+char(7,53533).
+char(4,53534).
+char(c,53535).
+char(p,53536).
+char(1,53537).
+char(2,53538).
+char(8,53539).
+char(3,53540).
+char(c,53541).
+char(c,53542).
+char(c,53543).
+char(p,53544).
+char(o,53545).
+char(o,53546).
+char(p,53547).
+char(2,53548).
+char(9,53549).
+char(1,53550).
+char(7,53551).
+char(p,53552).
+char(o,53553).
+char(9,53554).
+char(8,53555).
+char(0,53556).
+char(4,53557).
+char(p,53558).
+char(2,53559).
+char(2,53560).
+char(1,53561).
+char(0,53562).
+char(p,53563).
+char(4,53564).
+char(9,53565).
+char(4,53566).
+char(2,53567).
+char(c,53568).
+char(p,53569).
+char(o,53570).
+char(p,53571).
+char(8,53572).
+char(2,53573).
+char(6,53574).
+char(7,53575).
+char(c,53576).
+char(m,53577).
+char(3,53578).
+char(2,53579).
+char(0,53580).
+char(1,53581).
+char(c,53582).
+char(c,53583).
+char(c,53584).
+char(p,53585).
+char(o,53586).
+char(p,53587).
+char(1,53588).
+char(6,53589).
+char(1,53590).
+char(3,53591).
+char(c,53592).
+char(p,53593).
+char(6,53594).
+char(2,53595).
+char(2,53596).
+char(1,53597).
+char(c,53598).
+char(c,53599).
+char(c,53600).
+char(c,53601).
+char(m,53602).
+char(o,53603).
+char(p,53604).
+char(4,53605).
+char(3,53606).
+char(4,53607).
+char(c,53608).
+char(c,53609).
+char(p,53610).
+char(8,53611).
+char(5,53612).
+char(7,53613).
+char(8,53614).
+char(p,53615).
+char(3,53616).
+char(6,53617).
+char(0,53618).
+char(3,53619).
+char(c,53620).
+char(p,53621).
+char(9,53622).
+char(8,53623).
+char(2,53624).
+char(m,53625).
+char(6,53626).
+char(6,53627).
+char(2,53628).
+char(4,53629).
+char(m,53630).
+char(7,53631).
+char(4,53632).
+char(5,53633).
+char(8,53634).
+char(c,53635).
+char(c,53636).
+char(c,53637).
+char(m,53638).
+char(3,53639).
+char(5,53640).
+char(1,53641).
+char(7,53642).
+char(c,53643).
+char(p,53644).
+char(o,53645).
+char(m,53646).
+char(o,53647).
+char(o,53648).
+char(p,53649).
+char(1,53650).
+char(4,53651).
+char(1,53652).
+char(2,53653).
+char(c,53654).
+char(c,53655).
+char(m,53656).
+char(5,53657).
+char(8,53658).
+char(6,53659).
+char(0,53660).
+char(c,53661).
+char(m,53662).
+char(o,53663).
+char(m,53664).
+char(o,53665).
+char(p,53666).
+char(o,53667).
+char(m,53668).
+char(5,53669).
+char(6,53670).
+char(9,53671).
+char(9,53672).
+char(c,53673).
+char(p,53674).
+char(8,53675).
+char(0,53676).
+char(0,53677).
+char(9,53678).
+char(p,53679).
+char(2,53680).
+char(8,53681).
+char(6,53682).
+char(7,53683).
+char(c,53684).
+char(c,53685).
+char(m,53686).
+char(o,53687).
+char(o,53688).
+char(m,53689).
+char(o,53690).
+char(p,53691).
+char(3,53692).
+char(2,53693).
+char(3,53694).
+char(6,53695).
+char(p,53696).
+char(o,53697).
+char(3,53698).
+char(2,53699).
+char(1,53700).
+char(5,53701).
+char(p,53702).
+char(7,53703).
+char(8,53704).
+char(1,53705).
+char(2,53706).
+char(c,53707).
+char(m,53708).
+char(5,53709).
+char(4,53710).
+char(1,53711).
+char(2,53712).
+char(c,53713).
+char(c,53714).
+char(m,53715).
+char(o,53716).
+char(p,53717).
+char(o,53718).
+char(m,53719).
+char(o,53720).
+char(p,53721).
+char(9,53722).
+char(9,53723).
+char(6,53724).
+char(1,53725).
+char(c,53726).
+char(m,53727).
+char(4,53728).
+char(0,53729).
+char(7,53730).
+char(1,53731).
+char(c,53732).
+char(m,53733).
+char(o,53734).
+char(m,53735).
+char(2,53736).
+char(0,53737).
+char(3,53738).
+char(9,53739).
+char(c,53740).
+char(m,53741).
+char(4,53742).
+char(2,53743).
+char(5,53744).
+char(5,53745).
+char(c,53746).
+char(p,53747).
+char(8,53748).
+char(1,53749).
+char(9,53750).
+char(9,53751).
+char(c,53752).
+char(m,53753).
+char(o,53754).
+char(m,53755).
+char(6,53756).
+char(3,53757).
+char(8,53758).
+char(5,53759).
+char(p,53760).
+char(o,53761).
+char(3,53762).
+char(4,53763).
+char(3,53764).
+char(9,53765).
+char(c,53766).
+char(c,53767).
+char(m,53768).
+char(5,53769).
+char(2,53770).
+char(7,53771).
+char(4,53772).
+char(c,53773).
+char(c,53774).
+char(c,53775).
+char(c,53776).
+char(m,53777).
+char(o,53778).
+char(p,53779).
+char(o,53780).
+char(2,53781).
+char(3,53782).
+char(2,53783).
+char(8,53784).
+char(c,53785).
+char(c,53786).
+char(c,53787).
+char(c,53788).
+char(m,53789).
+char(o,53790).
+char(p,53791).
+char(o,53792).
+char(5,53793).
+char(3,53794).
+char(0,53795).
+char(m,53796).
+char(2,53797).
+char(2,53798).
+char(9,53799).
+char(1,53800).
+char(m,53801).
+char(o,53802).
+char(p,53803).
+char(o,53804).
+char(m,53805).
+char(o,53806).
+char(m,53807).
+char(3,53808).
+char(1,53809).
+char(8,53810).
+char(5,53811).
+char(c,53812).
+char(m,53813).
+char(5,53814).
+char(6,53815).
+char(9,53816).
+char(5,53817).
+char(c,53818).
+char(c,53819).
+char(c,53820).
+char(p,53821).
+char(7,53822).
+char(3,53823).
+char(7,53824).
+char(9,53825).
+char(p,53826).
+char(1,53827).
+char(9,53828).
+char(7,53829).
+char(8,53830).
+char(m,53831).
+char(2,53832).
+char(8,53833).
+char(9,53834).
+char(7,53835).
+char(c,53836).
+char(c,53837).
+char(p,53838).
+char(3,53839).
+char(7,53840).
+char(0,53841).
+char(3,53842).
+char(m,53843).
+char(9,53844).
+char(7,53845).
+char(5,53846).
+char(1,53847).
+char(m,53848).
+char(5,53849).
+char(7,53850).
+char(4,53851).
+char(5,53852).
+char(p,53853).
+char(7,53854).
+char(1,53855).
+char(7,53856).
+char(7,53857).
+char(p,53858).
+char(8,53859).
+char(9,53860).
+char(7,53861).
+char(9,53862).
+char(c,53863).
+char(p,53864).
+char(1,53865).
+char(6,53866).
+char(9,53867).
+char(3,53868).
+char(m,53869).
+char(9,53870).
+char(1,53871).
+char(4,53872).
+char(9,53873).
+char(p,53874).
+char(o,53875).
+char(6,53876).
+char(5,53877).
+char(8,53878).
+char(2,53879).
+char(m,53880).
+char(7,53881).
+char(6,53882).
+char(4,53883).
+char(7,53884).
+char(c,53885).
+char(c,53886).
+char(m,53887).
+char(7,53888).
+char(1,53889).
+char(2,53890).
+char(9,53891).
+char(c,53892).
+char(c,53893).
+char(c,53894).
+char(p,53895).
+char(7,53896).
+char(3,53897).
+char(8,53898).
+char(7,53899).
+char(m,53900).
+char(o,53901).
+char(m,53902).
+char(o,53903).
+char(o,53904).
+char(o,53905).
+char(o,53906).
+char(8,53907).
+char(0,53908).
+char(2,53909).
+char(7,53910).
+char(p,53911).
+char(o,53912).
+char(p,53913).
+char(o,53914).
+char(m,53915).
+char(8,53916).
+char(8,53917).
+char(0,53918).
+char(1,53919).
+char(m,53920).
+char(o,53921).
+char(m,53922).
+char(6,53923).
+char(4,53924).
+char(6,53925).
+char(c,53926).
+char(p,53927).
+char(o,53928).
+char(m,53929).
+char(o,53930).
+char(p,53931).
+char(2,53932).
+char(1,53933).
+char(4,53934).
+char(c,53935).
+char(p,53936).
+char(o,53937).
+char(o,53938).
+char(p,53939).
+char(o,53940).
+char(p,53941).
+char(1,53942).
+char(7,53943).
+char(6,53944).
+char(5,53945).
+char(c,53946).
+char(c,53947).
+char(c,53948).
+char(c,53949).
+char(c,53950).
+char(c,53951).
+char(c,53952).
+char(m,53953).
+char(7,53954).
+char(3,53955).
+char(1,53956).
+char(5,53957).
+char(p,53958).
+char(4,53959).
+char(5,53960).
+char(2,53961).
+char(c,53962).
+char(c,53963).
+char(m,53964).
+char(3,53965).
+char(7,53966).
+char(1,53967).
+char(6,53968).
+char(m,53969).
+char(4,53970).
+char(5,53971).
+char(7,53972).
+char(8,53973).
+char(m,53974).
+char(o,53975).
+char(m,53976).
+char(o,53977).
+char(m,53978).
+char(9,53979).
+char(2,53980).
+char(8,53981).
+char(8,53982).
+char(c,53983).
+char(c,53984).
+char(c,53985).
+char(m,53986).
+char(o,53987).
+char(m,53988).
+char(o,53989).
+char(8,53990).
+char(0,53991).
+char(5,53992).
+char(p,53993).
+char(4,53994).
+char(9,53995).
+char(8,53996).
+char(2,53997).
+char(c,53998).
+char(m,53999).
+char(4,54000).
+char(6,54001).
+char(1,54002).
+char(0,54003).
+char(p,54004).
+char(4,54005).
+char(5,54006).
+char(7,54007).
+char(7,54008).
+char(m,54009).
+char(o,54010).
+char(m,54011).
+char(o,54012).
+char(p,54013).
+char(6,54014).
+char(1,54015).
+char(9,54016).
+char(7,54017).
+char(c,54018).
+char(p,54019).
+char(o,54020).
+char(m,54021).
+char(o,54022).
+char(m,54023).
+char(5,54024).
+char(5,54025).
+char(0,54026).
+char(5,54027).
+char(p,54028).
+char(5,54029).
+char(2,54030).
+char(4,54031).
+char(p,54032).
+char(8,54033).
+char(0,54034).
+char(8,54035).
+char(1,54036).
+char(p,54037).
+char(8,54038).
+char(9,54039).
+char(5,54040).
+char(3,54041).
+char(c,54042).
+char(m,54043).
+char(7,54044).
+char(7,54045).
+char(1,54046).
+char(6,54047).
+char(m,54048).
+char(o,54049).
+char(p,54050).
+char(o,54051).
+char(3,54052).
+char(4,54053).
+char(0,54054).
+char(c,54055).
+char(c,54056).
+char(p,54057).
+char(o,54058).
+char(m,54059).
+char(o,54060).
+char(p,54061).
+char(8,54062).
+char(4,54063).
+char(7,54064).
+char(2,54065).
+char(p,54066).
+char(1,54067).
+char(9,54068).
+char(1,54069).
+char(8,54070).
+char(p,54071).
+char(o,54072).
+char(m,54073).
+char(o,54074).
+char(p,54075).
+char(4,54076).
+char(9,54077).
+char(6,54078).
+char(2,54079).
+char(m,54080).
+char(o,54081).
+char(9,54082).
+char(2,54083).
+char(9,54084).
+char(0,54085).
+char(c,54086).
+char(p,54087).
+char(6,54088).
+char(6,54089).
+char(2,54090).
+char(4,54091).
+char(c,54092).
+char(c,54093).
+char(m,54094).
+char(5,54095).
+char(8,54096).
+char(8,54097).
+char(0,54098).
+char(c,54099).
+char(c,54100).
+char(c,54101).
+char(m,54102).
+char(o,54103).
+char(p,54104).
+char(o,54105).
+char(m,54106).
+char(o,54107).
+char(m,54108).
+char(2,54109).
+char(4,54110).
+char(7,54111).
+char(7,54112).
+char(c,54113).
+char(c,54114).
+char(c,54115).
+char(p,54116).
+char(o,54117).
+char(p,54118).
+char(o,54119).
+char(m,54120).
+char(9,54121).
+char(3,54122).
+char(3,54123).
+char(5,54124).
+char(c,54125).
+char(c,54126).
+char(m,54127).
+char(o,54128).
+char(m,54129).
+char(2,54130).
+char(8,54131).
+char(2,54132).
+char(6,54133).
+char(m,54134).
+char(4,54135).
+char(7,54136).
+char(4,54137).
+char(5,54138).
+char(c,54139).
+char(c,54140).
+char(c,54141).
+char(m,54142).
+char(o,54143).
+char(8,54144).
+char(2,54145).
+char(2,54146).
+char(3,54147).
+char(c,54148).
+char(m,54149).
+char(5,54150).
+char(4,54151).
+char(1,54152).
+char(9,54153).
+char(c,54154).
+char(m,54155).
+char(o,54156).
+char(m,54157).
+char(4,54158).
+char(5,54159).
+char(4,54160).
+char(6,54161).
+char(p,54162).
+char(8,54163).
+char(5,54164).
+char(3,54165).
+char(4,54166).
+char(p,54167).
+char(o,54168).
+char(m,54169).
+char(o,54170).
+char(p,54171).
+char(o,54172).
+char(p,54173).
+char(3,54174).
+char(1,54175).
+char(1,54176).
+char(4,54177).
+char(c,54178).
+char(c,54179).
+char(c,54180).
+char(c,54181).
+char(m,54182).
+char(6,54183).
+char(9,54184).
+char(7,54185).
+char(c,54186).
+char(c,54187).
+char(p,54188).
+char(o,54189).
+char(2,54190).
+char(4,54191).
+char(3,54192).
+char(6,54193).
+char(c,54194).
+char(c,54195).
+char(c,54196).
+char(m,54197).
+char(o,54198).
+char(o,54199).
+char(p,54200).
+char(1,54201).
+char(7,54202).
+char(0,54203).
+char(1,54204).
+char(c,54205).
+char(p,54206).
+char(o,54207).
+char(p,54208).
+char(8,54209).
+char(9,54210).
+char(1,54211).
+char(7,54212).
+char(m,54213).
+char(o,54214).
+char(p,54215).
+char(o,54216).
+char(m,54217).
+char(6,54218).
+char(6,54219).
+char(5,54220).
+char(9,54221).
+char(p,54222).
+char(o,54223).
+char(m,54224).
+char(o,54225).
+char(2,54226).
+char(1,54227).
+char(2,54228).
+char(5,54229).
+char(c,54230).
+char(c,54231).
+char(m,54232).
+char(o,54233).
+char(m,54234).
+char(1,54235).
+char(7,54236).
+char(4,54237).
+char(2,54238).
+char(c,54239).
+char(p,54240).
+char(3,54241).
+char(6,54242).
+char(4,54243).
+char(6,54244).
+char(p,54245).
+char(9,54246).
+char(8,54247).
+char(6,54248).
+char(0,54249).
+char(c,54250).
+char(c,54251).
+char(c,54252).
+char(m,54253).
+char(3,54254).
+char(3,54255).
+char(3,54256).
+char(4,54257).
+char(c,54258).
+char(c,54259).
+char(p,54260).
+char(3,54261).
+char(9,54262).
+char(6,54263).
+char(4,54264).
+char(c,54265).
+char(p,54266).
+char(o,54267).
+char(o,54268).
+char(p,54269).
+char(o,54270).
+char(3,54271).
+char(8,54272).
+char(7,54273).
+char(1,54274).
+char(c,54275).
+char(m,54276).
+char(2,54277).
+char(2,54278).
+char(3,54279).
+char(7,54280).
+char(c,54281).
+char(c,54282).
+char(c,54283).
+char(m,54284).
+char(7,54285).
+char(1,54286).
+char(1,54287).
+char(9,54288).
+char(c,54289).
+char(c,54290).
+char(c,54291).
+char(c,54292).
+char(c,54293).
+char(c,54294).
+char(m,54295).
+char(3,54296).
+char(6,54297).
+char(8,54298).
+char(7,54299).
+char(c,54300).
+char(m,54301).
+char(o,54302).
+char(m,54303).
+char(o,54304).
+char(m,54305).
+char(3,54306).
+char(0,54307).
+char(1,54308).
+char(6,54309).
+char(p,54310).
+char(3,54311).
+char(2,54312).
+char(1,54313).
+char(7,54314).
+char(m,54315).
+char(4,54316).
+char(6,54317).
+char(7,54318).
+char(8,54319).
+char(p,54320).
+char(o,54321).
+char(m,54322).
+char(o,54323).
+char(8,54324).
+char(5,54325).
+char(4,54326).
+char(7,54327).
+char(p,54328).
+char(2,54329).
+char(0,54330).
+char(6,54331).
+char(9,54332).
+char(m,54333).
+char(o,54334).
+char(p,54335).
+char(o,54336).
+char(p,54337).
+char(o,54338).
+char(m,54339).
+char(5,54340).
+char(4,54341).
+char(5,54342).
+char(4,54343).
+char(p,54344).
+char(7,54345).
+char(0,54346).
+char(4,54347).
+char(3,54348).
+char(m,54349).
+char(4,54350).
+char(6,54351).
+char(7,54352).
+char(1,54353).
+char(c,54354).
+char(c,54355).
+char(m,54356).
+char(o,54357).
+char(p,54358).
+char(o,54359).
+char(m,54360).
+char(9,54361).
+char(6,54362).
+char(2,54363).
+char(1,54364).
+char(m,54365).
+char(8,54366).
+char(4,54367).
+char(9,54368).
+char(1,54369).
+char(c,54370).
+char(p,54371).
+char(4,54372).
+char(3,54373).
+char(7,54374).
+char(8,54375).
+char(p,54376).
+char(o,54377).
+char(p,54378).
+char(5,54379).
+char(5,54380).
+char(5,54381).
+char(p,54382).
+char(7,54383).
+char(2,54384).
+char(1,54385).
+char(0,54386).
+char(c,54387).
+char(c,54388).
+char(p,54389).
+char(7,54390).
+char(8,54391).
+char(3,54392).
+char(2,54393).
+char(c,54394).
+char(c,54395).
+char(c,54396).
+char(p,54397).
+char(o,54398).
+char(5,54399).
+char(9,54400).
+char(7,54401).
+char(0,54402).
+char(p,54403).
+char(7,54404).
+char(2,54405).
+char(5,54406).
+char(5,54407).
+char(c,54408).
+char(c,54409).
+char(c,54410).
+char(m,54411).
+char(o,54412).
+char(m,54413).
+char(o,54414).
+char(o,54415).
+char(p,54416).
+char(5,54417).
+char(0,54418).
+char(4,54419).
+char(7,54420).
+char(c,54421).
+char(c,54422).
+char(m,54423).
+char(7,54424).
+char(4,54425).
+char(0,54426).
+char(m,54427).
+char(2,54428).
+char(1,54429).
+char(9,54430).
+char(9,54431).
+char(m,54432).
+char(3,54433).
+char(8,54434).
+char(5,54435).
+char(1,54436).
+char(c,54437).
+char(p,54438).
+char(o,54439).
+char(o,54440).
+char(p,54441).
+char(2,54442).
+char(3,54443).
+char(7,54444).
+char(2,54445).
+char(p,54446).
+char(o,54447).
+char(m,54448).
+char(6,54449).
+char(0,54450).
+char(6,54451).
+char(0,54452).
+char(p,54453).
+char(4,54454).
+char(4,54455).
+char(7,54456).
+char(2,54457).
+char(c,54458).
+char(c,54459).
+char(p,54460).
+char(o,54461).
+char(p,54462).
+char(9,54463).
+char(5,54464).
+char(0,54465).
+char(4,54466).
+char(p,54467).
+char(3,54468).
+char(1,54469).
+char(1,54470).
+char(8,54471).
+char(c,54472).
+char(p,54473).
+char(o,54474).
+char(m,54475).
+char(5,54476).
+char(9,54477).
+char(6,54478).
+char(0,54479).
+char(c,54480).
+char(p,54481).
+char(4,54482).
+char(3,54483).
+char(1,54484).
+char(8,54485).
+char(c,54486).
+char(c,54487).
+char(c,54488).
+char(p,54489).
+char(o,54490).
+char(o,54491).
+char(8,54492).
+char(1,54493).
+char(4,54494).
+char(1,54495).
+char(c,54496).
+char(c,54497).
+char(c,54498).
+char(c,54499).
+char(p,54500).
+char(o,54501).
+char(m,54502).
+char(1,54503).
+char(7,54504).
+char(3,54505).
+char(1,54506).
+char(m,54507).
+char(o,54508).
+char(m,54509).
+char(o,54510).
+char(9,54511).
+char(2,54512).
+char(3,54513).
+char(9,54514).
+char(c,54515).
+char(p,54516).
+char(o,54517).
+char(m,54518).
+char(o,54519).
+char(o,54520).
+char(m,54521).
+char(o,54522).
+char(p,54523).
+char(7,54524).
+char(3,54525).
+char(4,54526).
+char(8,54527).
+char(c,54528).
+char(c,54529).
+char(m,54530).
+char(o,54531).
+char(7,54532).
+char(0,54533).
+char(8,54534).
+char(5,54535).
+char(m,54536).
+char(o,54537).
+char(m,54538).
+char(3,54539).
+char(9,54540).
+char(6,54541).
+char(3,54542).
+char(m,54543).
+char(o,54544).
+char(p,54545).
+char(5,54546).
+char(5,54547).
+char(1,54548).
+char(2,54549).
+char(c,54550).
+char(c,54551).
+char(c,54552).
+char(m,54553).
+char(8,54554).
+char(8,54555).
+char(0,54556).
+char(3,54557).
+char(p,54558).
+char(9,54559).
+char(7,54560).
+char(7,54561).
+char(6,54562).
+char(c,54563).
+char(c,54564).
+char(p,54565).
+char(8,54566).
+char(1,54567).
+char(1,54568).
+char(4,54569).
+char(c,54570).
+char(m,54571).
+char(o,54572).
+char(o,54573).
+char(p,54574).
+char(4,54575).
+char(5,54576).
+char(1,54577).
+char(5,54578).
+char(c,54579).
+char(c,54580).
+char(c,54581).
+char(m,54582).
+char(5,54583).
+char(4,54584).
+char(7,54585).
+char(9,54586).
+char(p,54587).
+char(6,54588).
+char(6,54589).
+char(3,54590).
+char(8,54591).
+char(c,54592).
+char(p,54593).
+char(1,54594).
+char(6,54595).
+char(5,54596).
+char(2,54597).
+char(p,54598).
+char(8,54599).
+char(0,54600).
+char(3,54601).
+char(7,54602).
+char(c,54603).
+char(c,54604).
+char(p,54605).
+char(o,54606).
+char(1,54607).
+char(5,54608).
+char(0,54609).
+char(c,54610).
+char(c,54611).
+char(c,54612).
+char(m,54613).
+char(5,54614).
+char(0,54615).
+char(5,54616).
+char(p,54617).
+char(o,54618).
+char(p,54619).
+char(o,54620).
+char(8,54621).
+char(9,54622).
+char(9,54623).
+char(3,54624).
+char(p,54625).
+char(o,54626).
+char(p,54627).
+char(o,54628).
+char(m,54629).
+char(5,54630).
+char(6,54631).
+char(4,54632).
+char(8,54633).
+char(c,54634).
+char(c,54635).
+char(m,54636).
+char(1,54637).
+char(0,54638).
+char(6,54639).
+char(9,54640).
+char(c,54641).
+char(m,54642).
+char(6,54643).
+char(7,54644).
+char(1,54645).
+char(6,54646).
+char(c,54647).
+char(c,54648).
+char(c,54649).
+char(c,54650).
+char(c,54651).
+char(p,54652).
+char(1,54653).
+char(1,54654).
+char(6,54655).
+char(7,54656).
+char(c,54657).
+char(m,54658).
+char(o,54659).
+char(p,54660).
+char(o,54661).
+char(p,54662).
+char(o,54663).
+char(p,54664).
+char(8,54665).
+char(4,54666).
+char(6,54667).
+char(3,54668).
+char(m,54669).
+char(3,54670).
+char(0,54671).
+char(2,54672).
+char(1,54673).
+char(m,54674).
+char(o,54675).
+char(p,54676).
+char(o,54677).
+char(m,54678).
+char(o,54679).
+char(p,54680).
+char(2,54681).
+char(8,54682).
+char(4,54683).
+char(0,54684).
+char(p,54685).
+char(o,54686).
+char(p,54687).
+char(5,54688).
+char(3,54689).
+char(6,54690).
+char(7,54691).
+char(m,54692).
+char(o,54693).
+char(p,54694).
+char(3,54695).
+char(6,54696).
+char(9,54697).
+char(p,54698).
+char(2,54699).
+char(0,54700).
+char(4,54701).
+char(0,54702).
+char(p,54703).
+char(o,54704).
+char(m,54705).
+char(2,54706).
+char(8,54707).
+char(9,54708).
+char(4,54709).
+char(m,54710).
+char(8,54711).
+char(6,54712).
+char(6,54713).
+char(1,54714).
+char(c,54715).
+char(c,54716).
+char(c,54717).
+char(c,54718).
+char(c,54719).
+char(p,54720).
+char(o,54721).
+char(o,54722).
+char(p,54723).
+char(o,54724).
+char(m,54725).
+char(1,54726).
+char(4,54727).
+char(8,54728).
+char(4,54729).
+char(p,54730).
+char(o,54731).
+char(m,54732).
+char(o,54733).
+char(p,54734).
+char(4,54735).
+char(0,54736).
+char(8,54737).
+char(7,54738).
+char(c,54739).
+char(m,54740).
+char(7,54741).
+char(0,54742).
+char(3,54743).
+char(1,54744).
+char(c,54745).
+char(c,54746).
+char(c,54747).
+char(m,54748).
+char(7,54749).
+char(2,54750).
+char(8,54751).
+char(5,54752).
+char(p,54753).
+char(6,54754).
+char(8,54755).
+char(2,54756).
+char(5,54757).
+char(m,54758).
+char(o,54759).
+char(p,54760).
+char(o,54761).
+char(m,54762).
+char(4,54763).
+char(0,54764).
+char(0,54765).
+char(8,54766).
+char(c,54767).
+char(m,54768).
+char(8,54769).
+char(2,54770).
+char(9,54771).
+char(m,54772).
+char(9,54773).
+char(1,54774).
+char(5,54775).
+char(c,54776).
+char(c,54777).
+char(c,54778).
+char(p,54779).
+char(6,54780).
+char(8,54781).
+char(4,54782).
+char(8,54783).
+char(m,54784).
+char(o,54785).
+char(m,54786).
+char(4,54787).
+char(7,54788).
+char(4,54789).
+char(7,54790).
+char(c,54791).
+char(p,54792).
+char(o,54793).
+char(m,54794).
+char(o,54795).
+char(5,54796).
+char(8,54797).
+char(0,54798).
+char(8,54799).
+char(c,54800).
+char(c,54801).
+char(m,54802).
+char(1,54803).
+char(3,54804).
+char(7,54805).
+char(c,54806).
+char(c,54807).
+char(c,54808).
+char(m,54809).
+char(5,54810).
+char(8,54811).
+char(9,54812).
+char(9,54813).
+char(p,54814).
+char(o,54815).
+char(m,54816).
+char(2,54817).
+char(1,54818).
+char(6,54819).
+char(1,54820).
+char(c,54821).
+char(c,54822).
+char(c,54823).
+char(m,54824).
+char(o,54825).
+char(1,54826).
+char(0,54827).
+char(8,54828).
+char(0,54829).
+char(c,54830).
+char(c,54831).
+char(c,54832).
+char(m,54833).
+char(6,54834).
+char(8,54835).
+char(3,54836).
+char(4,54837).
+char(p,54838).
+char(o,54839).
+char(m,54840).
+char(3,54841).
+char(3,54842).
+char(0,54843).
+char(3,54844).
+char(c,54845).
+char(p,54846).
+char(7,54847).
+char(4,54848).
+char(2,54849).
+char(p,54850).
+char(1,54851).
+char(8,54852).
+char(7,54853).
+char(c,54854).
+char(c,54855).
+char(m,54856).
+char(o,54857).
+char(m,54858).
+char(7,54859).
+char(1,54860).
+char(9,54861).
+char(4,54862).
+char(m,54863).
+char(o,54864).
+char(5,54865).
+char(1,54866).
+char(9,54867).
+char(8,54868).
+char(p,54869).
+char(6,54870).
+char(5,54871).
+char(3,54872).
+char(3,54873).
+char(m,54874).
+char(9,54875).
+char(4,54876).
+char(1,54877).
+char(3,54878).
+char(p,54879).
+char(o,54880).
+char(o,54881).
+char(o,54882).
+char(p,54883).
+char(5,54884).
+char(2,54885).
+char(3,54886).
+char(3,54887).
+char(p,54888).
+char(o,54889).
+char(o,54890).
+char(o,54891).
+char(p,54892).
+char(o,54893).
+char(p,54894).
+char(o,54895).
+char(p,54896).
+char(o,54897).
+char(8,54898).
+char(7,54899).
+char(5,54900).
+char(7,54901).
+char(p,54902).
+char(o,54903).
+char(6,54904).
+char(2,54905).
+char(1,54906).
+char(c,54907).
+char(m,54908).
+char(o,54909).
+char(o,54910).
+char(o,54911).
+char(o,54912).
+char(3,54913).
+char(2,54914).
+char(2,54915).
+char(5,54916).
+char(m,54917).
+char(4,54918).
+char(5,54919).
+char(9,54920).
+char(2,54921).
+char(p,54922).
+char(o,54923).
+char(p,54924).
+char(o,54925).
+char(m,54926).
+char(9,54927).
+char(1,54928).
+char(2,54929).
+char(6,54930).
+char(p,54931).
+char(o,54932).
+char(m,54933).
+char(9,54934).
+char(3,54935).
+char(6,54936).
+char(4,54937).
+char(c,54938).
+char(c,54939).
+char(p,54940).
+char(1,54941).
+char(5,54942).
+char(2,54943).
+char(4,54944).
+char(c,54945).
+char(c,54946).
+char(c,54947).
+char(p,54948).
+char(o,54949).
+char(p,54950).
+char(o,54951).
+char(o,54952).
+char(p,54953).
+char(o,54954).
+char(3,54955).
+char(3,54956).
+char(5,54957).
+char(m,54958).
+char(o,54959).
+char(m,54960).
+char(o,54961).
+char(o,54962).
+char(7,54963).
+char(9,54964).
+char(7,54965).
+char(4,54966).
+char(c,54967).
+char(c,54968).
+char(m,54969).
+char(1,54970).
+char(5,54971).
+char(2,54972).
+char(4,54973).
+char(m,54974).
+char(o,54975).
+char(m,54976).
+char(o,54977).
+char(p,54978).
+char(o,54979).
+char(2,54980).
+char(8,54981).
+char(5,54982).
+char(5,54983).
+char(c,54984).
+char(c,54985).
+char(c,54986).
+char(m,54987).
+char(7,54988).
+char(1,54989).
+char(5,54990).
+char(8,54991).
+char(c,54992).
+char(c,54993).
+char(c,54994).
+char(p,54995).
+char(5,54996).
+char(9,54997).
+char(2,54998).
+char(6,54999).
+char(c,55000).
+char(p,55001).
+char(9,55002).
+char(6,55003).
+char(4,55004).
+char(8,55005).
+char(c,55006).
+char(c,55007).
+char(m,55008).
+char(2,55009).
+char(4,55010).
+char(9,55011).
+char(9,55012).
+char(c,55013).
+char(c,55014).
+char(c,55015).
+char(c,55016).
+char(c,55017).
+char(c,55018).
+char(p,55019).
+char(o,55020).
+char(m,55021).
+char(9,55022).
+char(0,55023).
+char(1,55024).
+char(9,55025).
+char(p,55026).
+char(8,55027).
+char(8,55028).
+char(7,55029).
+char(3,55030).
+char(c,55031).
+char(c,55032).
+char(c,55033).
+char(p,55034).
+char(3,55035).
+char(6,55036).
+char(3,55037).
+char(7,55038).
+char(c,55039).
+char(m,55040).
+char(8,55041).
+char(6,55042).
+char(p,55043).
+char(o,55044).
+char(p,55045).
+char(5,55046).
+char(7,55047).
+char(5,55048).
+char(9,55049).
+char(c,55050).
+char(c,55051).
+char(m,55052).
+char(5,55053).
+char(5,55054).
+char(3,55055).
+char(6,55056).
+char(m,55057).
+char(o,55058).
+char(o,55059).
+char(m,55060).
+char(o,55061).
+char(m,55062).
+char(2,55063).
+char(6,55064).
+char(0,55065).
+char(9,55066).
+char(c,55067).
+char(m,55068).
+char(o,55069).
+char(4,55070).
+char(2,55071).
+char(6,55072).
+char(6,55073).
+char(m,55074).
+char(o,55075).
+char(2,55076).
+char(0,55077).
+char(8,55078).
+char(4,55079).
+char(m,55080).
+char(7,55081).
+char(6,55082).
+char(7,55083).
+char(1,55084).
+char(c,55085).
+char(c,55086).
+char(p,55087).
+char(o,55088).
+char(p,55089).
+char(o,55090).
+char(m,55091).
+char(2,55092).
+char(9,55093).
+char(9,55094).
+char(1,55095).
+char(c,55096).
+char(m,55097).
+char(o,55098).
+char(p,55099).
+char(9,55100).
+char(7,55101).
+char(2,55102).
+char(5,55103).
+char(c,55104).
+char(p,55105).
+char(o,55106).
+char(m,55107).
+char(3,55108).
+char(1,55109).
+char(5,55110).
+char(5,55111).
+char(c,55112).
+char(c,55113).
+char(c,55114).
+char(c,55115).
+char(c,55116).
+char(m,55117).
+char(o,55118).
+char(p,55119).
+char(o,55120).
+char(p,55121).
+char(o,55122).
+char(p,55123).
+char(3,55124).
+char(1,55125).
+char(2,55126).
+char(2,55127).
+char(p,55128).
+char(o,55129).
+char(p,55130).
+char(o,55131).
+char(m,55132).
+char(o,55133).
+char(p,55134).
+char(7,55135).
+char(3,55136).
+char(4,55137).
+char(3,55138).
+char(p,55139).
+char(o,55140).
+char(p,55141).
+char(1,55142).
+char(2,55143).
+char(5,55144).
+char(2,55145).
+char(c,55146).
+char(m,55147).
+char(o,55148).
+char(o,55149).
+char(m,55150).
+char(6,55151).
+char(1,55152).
+char(4,55153).
+char(1,55154).
+char(c,55155).
+char(c,55156).
+char(c,55157).
+char(p,55158).
+char(o,55159).
+char(p,55160).
+char(6,55161).
+char(1,55162).
+char(7,55163).
+char(5,55164).
+char(c,55165).
+char(m,55166).
+char(o,55167).
+char(m,55168).
+char(7,55169).
+char(0,55170).
+char(3,55171).
+char(8,55172).
+char(m,55173).
+char(4,55174).
+char(1,55175).
+char(2,55176).
+char(7,55177).
+char(p,55178).
+char(3,55179).
+char(4,55180).
+char(1,55181).
+char(5,55182).
+char(p,55183).
+char(o,55184).
+char(m,55185).
+char(o,55186).
+char(5,55187).
+char(7,55188).
+char(2,55189).
+char(4,55190).
+char(m,55191).
+char(5,55192).
+char(7,55193).
+char(3,55194).
+char(3,55195).
+char(p,55196).
+char(o,55197).
+char(o,55198).
+char(8,55199).
+char(3,55200).
+char(4,55201).
+char(9,55202).
+char(p,55203).
+char(5,55204).
+char(7,55205).
+char(5,55206).
+char(8,55207).
+char(m,55208).
+char(9,55209).
+char(2,55210).
+char(6,55211).
+char(5,55212).
+char(p,55213).
+char(7,55214).
+char(8,55215).
+char(2,55216).
+char(6,55217).
+char(c,55218).
+char(c,55219).
+char(c,55220).
+char(c,55221).
+char(p,55222).
+char(6,55223).
+char(9,55224).
+char(8,55225).
+char(2,55226).
+char(c,55227).
+char(c,55228).
+char(c,55229).
+char(m,55230).
+char(o,55231).
+char(m,55232).
+char(7,55233).
+char(0,55234).
+char(2,55235).
+char(6,55236).
+char(c,55237).
+char(c,55238).
+char(c,55239).
+char(c,55240).
+char(c,55241).
+char(p,55242).
+char(o,55243).
+char(m,55244).
+char(3,55245).
+char(9,55246).
+char(2,55247).
+char(7,55248).
+char(p,55249).
+char(8,55250).
+char(1,55251).
+char(0,55252).
+char(7,55253).
+char(c,55254).
+char(c,55255).
+char(c,55256).
+char(p,55257).
+char(o,55258).
+char(2,55259).
+char(6,55260).
+char(6,55261).
+char(1,55262).
+char(p,55263).
+char(o,55264).
+char(m,55265).
+char(4,55266).
+char(0,55267).
+char(5,55268).
+char(6,55269).
+char(m,55270).
+char(9,55271).
+char(6,55272).
+char(9,55273).
+char(7,55274).
+char(c,55275).
+char(c,55276).
+char(c,55277).
+char(c,55278).
+char(m,55279).
+char(o,55280).
+char(6,55281).
+char(4,55282).
+char(9,55283).
+char(0,55284).
+char(m,55285).
+char(5,55286).
+char(4,55287).
+char(0,55288).
+char(0,55289).
+char(p,55290).
+char(9,55291).
+char(1,55292).
+char(8,55293).
+char(4,55294).
+char(p,55295).
+char(7,55296).
+char(5,55297).
+char(3,55298).
+char(6,55299).
+char(p,55300).
+char(o,55301).
+char(p,55302).
+char(o,55303).
+char(p,55304).
+char(o,55305).
+char(o,55306).
+char(p,55307).
+char(3,55308).
+char(5,55309).
+char(6,55310).
+char(9,55311).
+char(c,55312).
+char(c,55313).
+char(m,55314).
+char(o,55315).
+char(p,55316).
+char(o,55317).
+char(p,55318).
+char(5,55319).
+char(2,55320).
+char(8,55321).
+char(6,55322).
+char(p,55323).
+char(o,55324).
+char(o,55325).
+char(o,55326).
+char(m,55327).
+char(o,55328).
+char(o,55329).
+char(m,55330).
+char(5,55331).
+char(4,55332).
+char(7,55333).
+char(0,55334).
+char(c,55335).
+char(c,55336).
+char(m,55337).
+char(o,55338).
+char(m,55339).
+char(4,55340).
+char(1,55341).
+char(5,55342).
+char(9,55343).
+char(p,55344).
+char(9,55345).
+char(7,55346).
+char(7,55347).
+char(7,55348).
+char(m,55349).
+char(5,55350).
+char(8,55351).
+char(7,55352).
+char(p,55353).
+char(o,55354).
+char(m,55355).
+char(o,55356).
+char(p,55357).
+char(o,55358).
+char(o,55359).
+char(o,55360).
+char(m,55361).
+char(o,55362).
+char(o,55363).
+char(6,55364).
+char(6,55365).
+char(6,55366).
+char(0,55367).
+char(c,55368).
+char(m,55369).
+char(8,55370).
+char(3,55371).
+char(6,55372).
+char(9,55373).
+char(m,55374).
+char(8,55375).
+char(5,55376).
+char(8,55377).
+char(0,55378).
+char(p,55379).
+char(3,55380).
+char(0,55381).
+char(2,55382).
+char(9,55383).
+char(c,55384).
+char(c,55385).
+char(p,55386).
+char(o,55387).
+char(m,55388).
+char(8,55389).
+char(6,55390).
+char(8,55391).
+char(9,55392).
+char(p,55393).
+char(8,55394).
+char(3,55395).
+char(1,55396).
+char(8,55397).
+char(p,55398).
+char(o,55399).
+char(m,55400).
+char(o,55401).
+char(4,55402).
+char(8,55403).
+char(2,55404).
+char(3,55405).
+char(m,55406).
+char(7,55407).
+char(7,55408).
+char(6,55409).
+char(6,55410).
+char(m,55411).
+char(4,55412).
+char(9,55413).
+char(4,55414).
+char(m,55415).
+char(o,55416).
+char(m,55417).
+char(o,55418).
+char(m,55419).
+char(o,55420).
+char(m,55421).
+char(7,55422).
+char(0,55423).
+char(9,55424).
+char(1,55425).
+char(c,55426).
+char(p,55427).
+char(9,55428).
+char(1,55429).
+char(2,55430).
+char(0,55431).
+char(p,55432).
+char(6,55433).
+char(4,55434).
+char(1,55435).
+char(0,55436).
+char(c,55437).
+char(m,55438).
+char(2,55439).
+char(6,55440).
+char(6,55441).
+char(8,55442).
+char(p,55443).
+char(5,55444).
+char(6,55445).
+char(7,55446).
+char(1,55447).
+char(p,55448).
+char(o,55449).
+char(m,55450).
+char(o,55451).
+char(m,55452).
+char(o,55453).
+char(m,55454).
+char(9,55455).
+char(5,55456).
+char(1,55457).
+char(1,55458).
+char(c,55459).
+char(m,55460).
+char(7,55461).
+char(1,55462).
+char(8,55463).
+char(3,55464).
+char(c,55465).
+char(p,55466).
+char(o,55467).
+char(m,55468).
+char(5,55469).
+char(5,55470).
+char(1,55471).
+char(8,55472).
+char(p,55473).
+char(o,55474).
+char(p,55475).
+char(9,55476).
+char(1,55477).
+char(8,55478).
+char(8,55479).
+char(c,55480).
+char(c,55481).
+char(m,55482).
+char(3,55483).
+char(6,55484).
+char(8,55485).
+char(0,55486).
+char(m,55487).
+char(2,55488).
+char(2,55489).
+char(9,55490).
+char(0,55491).
+char(m,55492).
+char(o,55493).
+char(p,55494).
+char(o,55495).
+char(m,55496).
+char(7,55497).
+char(6,55498).
+char(6,55499).
+char(c,55500).
+char(c,55501).
+char(c,55502).
+char(m,55503).
+char(o,55504).
+char(7,55505).
+char(6,55506).
+char(1,55507).
+char(c,55508).
+char(m,55509).
+char(o,55510).
+char(p,55511).
+char(3,55512).
+char(6,55513).
+char(5,55514).
+char(3,55515).
+char(c,55516).
+char(m,55517).
+char(o,55518).
+char(o,55519).
+char(p,55520).
+char(2,55521).
+char(1,55522).
+char(8,55523).
+char(6,55524).
+char(m,55525).
+char(2,55526).
+char(0,55527).
+char(5,55528).
+char(6,55529).
+char(c,55530).
+char(p,55531).
+char(o,55532).
+char(m,55533).
+char(o,55534).
+char(m,55535).
+char(8,55536).
+char(3,55537).
+char(1,55538).
+char(2,55539).
+char(c,55540).
+char(c,55541).
+char(c,55542).
+char(p,55543).
+char(6,55544).
+char(6,55545).
+char(9,55546).
+char(5,55547).
+char(c,55548).
+char(c,55549).
+char(m,55550).
+char(o,55551).
+char(p,55552).
+char(5,55553).
+char(5,55554).
+char(1,55555).
+char(1,55556).
+char(c,55557).
+char(c,55558).
+char(c,55559).
+char(p,55560).
+char(o,55561).
+char(p,55562).
+char(o,55563).
+char(p,55564).
+char(o,55565).
+char(o,55566).
+char(p,55567).
+char(o,55568).
+char(p,55569).
+char(7,55570).
+char(2,55571).
+char(7,55572).
+char(9,55573).
+char(c,55574).
+char(c,55575).
+char(m,55576).
+char(o,55577).
+char(o,55578).
+char(o,55579).
+char(p,55580).
+char(o,55581).
+char(m,55582).
+char(9,55583).
+char(5,55584).
+char(3,55585).
+char(2,55586).
+char(c,55587).
+char(m,55588).
+char(9,55589).
+char(5,55590).
+char(5,55591).
+char(p,55592).
+char(4,55593).
+char(0,55594).
+char(4,55595).
+char(4,55596).
+char(p,55597).
+char(o,55598).
+char(p,55599).
+char(1,55600).
+char(6,55601).
+char(8,55602).
+char(7,55603).
+char(p,55604).
+char(1,55605).
+char(1,55606).
+char(4,55607).
+char(5,55608).
+char(c,55609).
+char(c,55610).
+char(c,55611).
+char(m,55612).
+char(4,55613).
+char(8,55614).
+char(0,55615).
+char(5,55616).
+char(c,55617).
+char(m,55618).
+char(2,55619).
+char(3,55620).
+char(7,55621).
+char(0,55622).
+char(p,55623).
+char(5,55624).
+char(9,55625).
+char(8,55626).
+char(7,55627).
+char(c,55628).
+char(c,55629).
+char(c,55630).
+char(c,55631).
+char(p,55632).
+char(o,55633).
+char(m,55634).
+char(6,55635).
+char(7,55636).
+char(1,55637).
+char(4,55638).
+char(c,55639).
+char(c,55640).
+char(c,55641).
+char(c,55642).
+char(c,55643).
+char(c,55644).
+char(m,55645).
+char(o,55646).
+char(o,55647).
+char(p,55648).
+char(1,55649).
+char(3,55650).
+char(1,55651).
+char(6,55652).
+char(p,55653).
+char(o,55654).
+char(o,55655).
+char(o,55656).
+char(o,55657).
+char(p,55658).
+char(o,55659).
+char(4,55660).
+char(5,55661).
+char(5,55662).
+char(2,55663).
+char(p,55664).
+char(8,55665).
+char(1,55666).
+char(8,55667).
+char(5,55668).
+char(c,55669).
+char(c,55670).
+char(p,55671).
+char(o,55672).
+char(m,55673).
+char(4,55674).
+char(8,55675).
+char(7,55676).
+char(4,55677).
+char(c,55678).
+char(c,55679).
+char(p,55680).
+char(1,55681).
+char(1,55682).
+char(6,55683).
+char(7,55684).
+char(p,55685).
+char(2,55686).
+char(1,55687).
+char(9,55688).
+char(5,55689).
+char(c,55690).
+char(p,55691).
+char(4,55692).
+char(4,55693).
+char(2,55694).
+char(0,55695).
+char(c,55696).
+char(c,55697).
+char(m,55698).
+char(1,55699).
+char(9,55700).
+char(2,55701).
+char(7,55702).
+char(m,55703).
+char(5,55704).
+char(7,55705).
+char(9,55706).
+char(5,55707).
+char(c,55708).
+char(c,55709).
+char(p,55710).
+char(4,55711).
+char(8,55712).
+char(2,55713).
+char(4,55714).
+char(c,55715).
+char(m,55716).
+char(o,55717).
+char(p,55718).
+char(o,55719).
+char(8,55720).
+char(1,55721).
+char(4,55722).
+char(0,55723).
+char(c,55724).
+char(c,55725).
+char(c,55726).
+char(c,55727).
+char(p,55728).
+char(o,55729).
+char(o,55730).
+char(m,55731).
+char(o,55732).
+char(m,55733).
+char(1,55734).
+char(3,55735).
+char(8,55736).
+char(2,55737).
+char(m,55738).
+char(o,55739).
+char(m,55740).
+char(5,55741).
+char(9,55742).
+char(9,55743).
+char(2,55744).
+char(c,55745).
+char(c,55746).
+char(c,55747).
+char(c,55748).
+char(c,55749).
+char(m,55750).
+char(o,55751).
+char(p,55752).
+char(8,55753).
+char(2,55754).
+char(4,55755).
+char(m,55756).
+char(o,55757).
+char(p,55758).
+char(o,55759).
+char(m,55760).
+char(8,55761).
+char(1,55762).
+char(2,55763).
+char(3,55764).
+char(p,55765).
+char(o,55766).
+char(m,55767).
+char(3,55768).
+char(2,55769).
+char(9,55770).
+char(3,55771).
+char(c,55772).
+char(c,55773).
+char(c,55774).
+char(c,55775).
+char(p,55776).
+char(1,55777).
+char(1,55778).
+char(4,55779).
+char(m,55780).
+char(o,55781).
+char(8,55782).
+char(3,55783).
+char(9,55784).
+char(9,55785).
+char(c,55786).
+char(c,55787).
+char(p,55788).
+char(5,55789).
+char(7,55790).
+char(4,55791).
+char(6,55792).
+char(c,55793).
+char(p,55794).
+char(o,55795).
+char(o,55796).
+char(m,55797).
+char(o,55798).
+char(m,55799).
+char(o,55800).
+char(m,55801).
+char(o,55802).
+char(p,55803).
+char(o,55804).
+char(p,55805).
+char(o,55806).
+char(7,55807).
+char(9,55808).
+char(0,55809).
+char(6,55810).
+char(m,55811).
+char(2,55812).
+char(8,55813).
+char(2,55814).
+char(3,55815).
+char(p,55816).
+char(o,55817).
+char(o,55818).
+char(o,55819).
+char(p,55820).
+char(3,55821).
+char(8,55822).
+char(1,55823).
+char(3,55824).
+char(c,55825).
+char(p,55826).
+char(o,55827).
+char(m,55828).
+char(o,55829).
+char(p,55830).
+char(5,55831).
+char(5,55832).
+char(7,55833).
+char(6,55834).
+char(p,55835).
+char(3,55836).
+char(5,55837).
+char(5,55838).
+char(p,55839).
+char(o,55840).
+char(p,55841).
+char(5,55842).
+char(7,55843).
+char(5,55844).
+char(8,55845).
+char(c,55846).
+char(m,55847).
+char(3,55848).
+char(6,55849).
+char(3,55850).
+char(1,55851).
+char(m,55852).
+char(o,55853).
+char(m,55854).
+char(1,55855).
+char(4,55856).
+char(3,55857).
+char(p,55858).
+char(o,55859).
+char(m,55860).
+char(5,55861).
+char(2,55862).
+char(0,55863).
+char(m,55864).
+char(o,55865).
+char(o,55866).
+char(o,55867).
+char(p,55868).
+char(o,55869).
+char(p,55870).
+char(o,55871).
+char(p,55872).
+char(o,55873).
+char(p,55874).
+char(3,55875).
+char(1,55876).
+char(6,55877).
+char(p,55878).
+char(o,55879).
+char(p,55880).
+char(o,55881).
+char(p,55882).
+char(1,55883).
+char(0,55884).
+char(8,55885).
+char(6,55886).
+char(c,55887).
+char(p,55888).
+char(9,55889).
+char(3,55890).
+char(6,55891).
+char(9,55892).
+char(c,55893).
+char(m,55894).
+char(5,55895).
+char(4,55896).
+char(9,55897).
+char(c,55898).
+char(c,55899).
+char(m,55900).
+char(o,55901).
+char(p,55902).
+char(o,55903).
+char(m,55904).
+char(o,55905).
+char(m,55906).
+char(1,55907).
+char(2,55908).
+char(5,55909).
+char(9,55910).
+char(p,55911).
+char(4,55912).
+char(1,55913).
+char(3,55914).
+char(9,55915).
+char(m,55916).
+char(o,55917).
+char(m,55918).
+char(o,55919).
+char(9,55920).
+char(6,55921).
+char(4,55922).
+char(8,55923).
+char(c,55924).
+char(c,55925).
+char(c,55926).
+char(m,55927).
+char(o,55928).
+char(o,55929).
+char(p,55930).
+char(3,55931).
+char(0,55932).
+char(4,55933).
+char(2,55934).
+char(c,55935).
+char(c,55936).
+char(c,55937).
+char(m,55938).
+char(o,55939).
+char(m,55940).
+char(o,55941).
+char(m,55942).
+char(o,55943).
+char(m,55944).
+char(8,55945).
+char(8,55946).
+char(5,55947).
+char(p,55948).
+char(9,55949).
+char(4,55950).
+char(2,55951).
+char(7,55952).
+char(c,55953).
+char(p,55954).
+char(7,55955).
+char(3,55956).
+char(3,55957).
+char(3,55958).
+char(c,55959).
+char(p,55960).
+char(2,55961).
+char(9,55962).
+char(3,55963).
+char(m,55964).
+char(o,55965).
+char(m,55966).
+char(o,55967).
+char(m,55968).
+char(o,55969).
+char(p,55970).
+char(6,55971).
+char(4,55972).
+char(6,55973).
+char(3,55974).
+char(c,55975).
+char(p,55976).
+char(o,55977).
+char(5,55978).
+char(9,55979).
+char(2,55980).
+char(9,55981).
+char(p,55982).
+char(o,55983).
+char(p,55984).
+char(o,55985).
+char(p,55986).
+char(o,55987).
+char(o,55988).
+char(m,55989).
+char(o,55990).
+char(o,55991).
+char(8,55992).
+char(8,55993).
+char(4,55994).
+char(2,55995).
+char(c,55996).
+char(c,55997).
+char(m,55998).
+char(o,55999).
+char(o,56000).
+char(p,56001).
+char(o,56002).
+char(p,56003).
+char(5,56004).
+char(5,56005).
+char(6,56006).
+char(2,56007).
+char(c,56008).
+char(c,56009).
+char(c,56010).
+char(c,56011).
+char(p,56012).
+char(6,56013).
+char(9,56014).
+char(0,56015).
+char(3,56016).
+char(p,56017).
+char(3,56018).
+char(0,56019).
+char(1,56020).
+char(7,56021).
+char(c,56022).
+char(c,56023).
+char(c,56024).
+char(c,56025).
+char(p,56026).
+char(2,56027).
+char(4,56028).
+char(2,56029).
+char(6,56030).
+char(m,56031).
+char(4,56032).
+char(8,56033).
+char(4,56034).
+char(7,56035).
+char(m,56036).
+char(o,56037).
+char(m,56038).
+char(o,56039).
+char(p,56040).
+char(o,56041).
+char(o,56042).
+char(m,56043).
+char(o,56044).
+char(o,56045).
+char(o,56046).
+char(7,56047).
+char(4,56048).
+char(1,56049).
+char(5,56050).
+char(c,56051).
+char(c,56052).
+char(c,56053).
+char(p,56054).
+char(2,56055).
+char(1,56056).
+char(8,56057).
+char(5,56058).
+char(c,56059).
+char(p,56060).
+char(o,56061).
+char(o,56062).
+char(o,56063).
+char(1,56064).
+char(8,56065).
+char(1,56066).
+char(7,56067).
+char(c,56068).
+char(m,56069).
+char(9,56070).
+char(0,56071).
+char(7,56072).
+char(2,56073).
+char(c,56074).
+char(p,56075).
+char(9,56076).
+char(0,56077).
+char(6,56078).
+char(1,56079).
+char(c,56080).
+char(c,56081).
+char(c,56082).
+char(m,56083).
+char(7,56084).
+char(4,56085).
+char(4,56086).
+char(5,56087).
+char(m,56088).
+char(7,56089).
+char(7,56090).
+char(5,56091).
+char(1,56092).
+char(p,56093).
+char(o,56094).
+char(m,56095).
+char(6,56096).
+char(9,56097).
+char(6,56098).
+char(5,56099).
+char(p,56100).
+char(5,56101).
+char(6,56102).
+char(4,56103).
+char(9,56104).
+char(p,56105).
+char(8,56106).
+char(8,56107).
+char(0,56108).
+char(9,56109).
+char(p,56110).
+char(3,56111).
+char(9,56112).
+char(7,56113).
+char(2,56114).
+char(p,56115).
+char(5,56116).
+char(8,56117).
+char(3,56118).
+char(7,56119).
+char(c,56120).
+char(c,56121).
+char(p,56122).
+char(7,56123).
+char(1,56124).
+char(9,56125).
+char(4,56126).
+char(m,56127).
+char(o,56128).
+char(o,56129).
+char(p,56130).
+char(5,56131).
+char(1,56132).
+char(0,56133).
+char(7,56134).
+char(p,56135).
+char(3,56136).
+char(1,56137).
+char(1,56138).
+char(2,56139).
+char(p,56140).
+char(4,56141).
+char(0,56142).
+char(9,56143).
+char(0,56144).
+char(m,56145).
+char(3,56146).
+char(4,56147).
+char(1,56148).
+char(4,56149).
+char(m,56150).
+char(4,56151).
+char(3,56152).
+char(1,56153).
+char(0,56154).
+char(c,56155).
+char(c,56156).
+char(c,56157).
+char(c,56158).
+char(m,56159).
+char(o,56160).
+char(m,56161).
+char(o,56162).
+char(p,56163).
+char(6,56164).
+char(2,56165).
+char(1,56166).
+char(1,56167).
+char(c,56168).
+char(c,56169).
+char(c,56170).
+char(m,56171).
+char(2,56172).
+char(9,56173).
+char(5,56174).
+char(7,56175).
+char(m,56176).
+char(o,56177).
+char(p,56178).
+char(9,56179).
+char(6,56180).
+char(6,56181).
+char(8,56182).
+char(p,56183).
+char(o,56184).
+char(m,56185).
+char(8,56186).
+char(7,56187).
+char(5,56188).
+char(5,56189).
+char(p,56190).
+char(o,56191).
+char(o,56192).
+char(o,56193).
+char(p,56194).
+char(4,56195).
+char(8,56196).
+char(7,56197).
+char(1,56198).
+char(c,56199).
+char(p,56200).
+char(o,56201).
+char(p,56202).
+char(o,56203).
+char(m,56204).
+char(o,56205).
+char(7,56206).
+char(3,56207).
+char(5,56208).
+char(1,56209).
+char(p,56210).
+char(2,56211).
+char(7,56212).
+char(8,56213).
+char(6,56214).
+char(m,56215).
+char(o,56216).
+char(o,56217).
+char(o,56218).
+char(m,56219).
+char(5,56220).
+char(0,56221).
+char(5,56222).
+char(3,56223).
+char(m,56224).
+char(7,56225).
+char(7,56226).
+char(5,56227).
+char(6,56228).
+char(m,56229).
+char(o,56230).
+char(p,56231).
+char(o,56232).
+char(p,56233).
+char(o,56234).
+char(p,56235).
+char(3,56236).
+char(4,56237).
+char(7,56238).
+char(1,56239).
+char(c,56240).
+char(m,56241).
+char(1,56242).
+char(9,56243).
+char(0,56244).
+char(c,56245).
+char(c,56246).
+char(c,56247).
+char(c,56248).
+char(p,56249).
+char(o,56250).
+char(p,56251).
+char(2,56252).
+char(2,56253).
+char(3,56254).
+char(9,56255).
+char(c,56256).
+char(c,56257).
+char(m,56258).
+char(o,56259).
+char(o,56260).
+char(7,56261).
+char(3,56262).
+char(3,56263).
+char(9,56264).
+char(m,56265).
+char(5,56266).
+char(8,56267).
+char(8,56268).
+char(3,56269).
+char(c,56270).
+char(c,56271).
+char(p,56272).
+char(7,56273).
+char(9,56274).
+char(6,56275).
+char(4,56276).
+char(p,56277).
+char(o,56278).
+char(p,56279).
+char(4,56280).
+char(2,56281).
+char(7,56282).
+char(6,56283).
+char(c,56284).
+char(c,56285).
+char(c,56286).
+char(c,56287).
+char(c,56288).
+char(c,56289).
+char(c,56290).
+char(c,56291).
+char(m,56292).
+char(o,56293).
+char(4,56294).
+char(0,56295).
+char(4,56296).
+char(3,56297).
+char(m,56298).
+char(o,56299).
+char(p,56300).
+char(7,56301).
+char(7,56302).
+char(9,56303).
+char(p,56304).
+char(4,56305).
+char(1,56306).
+char(9,56307).
+char(5,56308).
+char(p,56309).
+char(8,56310).
+char(2,56311).
+char(3,56312).
+char(2,56313).
+char(c,56314).
+char(m,56315).
+char(o,56316).
+char(p,56317).
+char(o,56318).
+char(m,56319).
+char(o,56320).
+char(4,56321).
+char(0,56322).
+char(9,56323).
+char(8,56324).
+char(c,56325).
+char(c,56326).
+char(c,56327).
+char(c,56328).
+char(c,56329).
+char(m,56330).
+char(o,56331).
+char(m,56332).
+char(8,56333).
+char(3,56334).
+char(3,56335).
+char(4,56336).
+char(p,56337).
+char(6,56338).
+char(6,56339).
+char(6,56340).
+char(2,56341).
+char(c,56342).
+char(m,56343).
+char(o,56344).
+char(m,56345).
+char(1,56346).
+char(7,56347).
+char(2,56348).
+char(0,56349).
+char(c,56350).
+char(c,56351).
+char(p,56352).
+char(8,56353).
+char(3,56354).
+char(7,56355).
+char(c,56356).
+char(c,56357).
+char(c,56358).
+char(m,56359).
+char(o,56360).
+char(2,56361).
+char(4,56362).
+char(9,56363).
+char(2,56364).
+char(p,56365).
+char(9,56366).
+char(9,56367).
+char(7,56368).
+char(2,56369).
+char(c,56370).
+char(p,56371).
+char(8,56372).
+char(8,56373).
+char(8,56374).
+char(5,56375).
+char(p,56376).
+char(4,56377).
+char(9,56378).
+char(3,56379).
+char(5,56380).
+char(m,56381).
+char(6,56382).
+char(3,56383).
+char(7,56384).
+char(1,56385).
+char(c,56386).
+char(c,56387).
+char(p,56388).
+char(8,56389).
+char(6,56390).
+char(8,56391).
+char(6,56392).
+char(m,56393).
+char(o,56394).
+char(1,56395).
+char(8,56396).
+char(0,56397).
+char(9,56398).
+char(m,56399).
+char(o,56400).
+char(p,56401).
+char(o,56402).
+char(7,56403).
+char(9,56404).
+char(9,56405).
+char(1,56406).
+char(c,56407).
+char(p,56408).
+char(o,56409).
+char(m,56410).
+char(5,56411).
+char(6,56412).
+char(3,56413).
+char(c,56414).
+char(c,56415).
+char(c,56416).
+char(c,56417).
+char(m,56418).
+char(o,56419).
+char(6,56420).
+char(5,56421).
+char(1,56422).
+char(3,56423).
+char(c,56424).
+char(c,56425).
+char(c,56426).
+char(m,56427).
+char(6,56428).
+char(2,56429).
+char(8,56430).
+char(1,56431).
+char(m,56432).
+char(o,56433).
+char(m,56434).
+char(1,56435).
+char(2,56436).
+char(1,56437).
+char(9,56438).
+char(p,56439).
+char(7,56440).
+char(1,56441).
+char(0,56442).
+char(5,56443).
+char(c,56444).
+char(c,56445).
+char(p,56446).
+char(5,56447).
+char(6,56448).
+char(9,56449).
+char(8,56450).
+char(m,56451).
+char(7,56452).
+char(0,56453).
+char(1,56454).
+char(8,56455).
+char(m,56456).
+char(o,56457).
+char(p,56458).
+char(o,56459).
+char(p,56460).
+char(6,56461).
+char(0,56462).
+char(7,56463).
+char(9,56464).
+char(p,56465).
+char(7,56466).
+char(9,56467).
+char(8,56468).
+char(7,56469).
+char(c,56470).
+char(p,56471).
+char(o,56472).
+char(1,56473).
+char(9,56474).
+char(7,56475).
+char(3,56476).
+char(p,56477).
+char(4,56478).
+char(7,56479).
+char(6,56480).
+char(9,56481).
+char(p,56482).
+char(8,56483).
+char(5,56484).
+char(3,56485).
+char(6,56486).
+char(m,56487).
+char(3,56488).
+char(7,56489).
+char(8,56490).
+char(1,56491).
+char(p,56492).
+char(o,56493).
+char(1,56494).
+char(3,56495).
+char(4,56496).
+char(3,56497).
+char(c,56498).
+char(c,56499).
+char(c,56500).
+char(c,56501).
+char(p,56502).
+char(9,56503).
+char(9,56504).
+char(1,56505).
+char(m,56506).
+char(o,56507).
+char(o,56508).
+char(m,56509).
+char(o,56510).
+char(p,56511).
+char(o,56512).
+char(m,56513).
+char(4,56514).
+char(2,56515).
+char(6,56516).
+char(2,56517).
+char(p,56518).
+char(o,56519).
+char(m,56520).
+char(7,56521).
+char(8,56522).
+char(9,56523).
+char(p,56524).
+char(o,56525).
+char(m,56526).
+char(o,56527).
+char(m,56528).
+char(o,56529).
+char(p,56530).
+char(4,56531).
+char(4,56532).
+char(2,56533).
+char(9,56534).
+char(c,56535).
+char(c,56536).
+char(c,56537).
+char(c,56538).
+char(c,56539).
+char(c,56540).
+char(c,56541).
+char(c,56542).
+char(c,56543).
+char(c,56544).
+char(p,56545).
+char(o,56546).
+char(m,56547).
+char(4,56548).
+char(4,56549).
+char(7,56550).
+char(3,56551).
+char(p,56552).
+char(o,56553).
+char(p,56554).
+char(o,56555).
+char(p,56556).
+char(o,56557).
+char(m,56558).
+char(3,56559).
+char(1,56560).
+char(c,56561).
+char(p,56562).
+char(o,56563).
+char(m,56564).
+char(6,56565).
+char(1,56566).
+char(7,56567).
+char(9,56568).
+char(c,56569).
+char(c,56570).
+char(c,56571).
+char(p,56572).
+char(o,56573).
+char(1,56574).
+char(1,56575).
+char(9,56576).
+char(5,56577).
+char(m,56578).
+char(o,56579).
+char(8,56580).
+char(3,56581).
+char(9,56582).
+char(1,56583).
+char(c,56584).
+char(c,56585).
+char(m,56586).
+char(2,56587).
+char(4,56588).
+char(9,56589).
+char(5,56590).
+char(p,56591).
+char(o,56592).
+char(o,56593).
+char(p,56594).
+char(o,56595).
+char(9,56596).
+char(7,56597).
+char(0,56598).
+char(6,56599).
+char(c,56600).
+char(c,56601).
+char(c,56602).
+char(c,56603).
+char(c,56604).
+char(m,56605).
+char(o,56606).
+char(p,56607).
+char(2,56608).
+char(9,56609).
+char(3,56610).
+char(9,56611).
+char(m,56612).
+char(o,56613).
+char(3,56614).
+char(4,56615).
+char(2,56616).
+char(9,56617).
+char(p,56618).
+char(o,56619).
+char(p,56620).
+char(o,56621).
+char(o,56622).
+char(m,56623).
+char(5,56624).
+char(6,56625).
+char(9,56626).
+char(6,56627).
+char(c,56628).
+char(c,56629).
+char(c,56630).
+char(c,56631).
+char(c,56632).
+char(m,56633).
+char(7,56634).
+char(9,56635).
+char(4,56636).
+char(4,56637).
+char(m,56638).
+char(9,56639).
+char(7,56640).
+char(5,56641).
+char(3,56642).
+char(m,56643).
+char(9,56644).
+char(4,56645).
+char(3,56646).
+char(7,56647).
+char(m,56648).
+char(9,56649).
+char(5,56650).
+char(5,56651).
+char(2,56652).
+char(m,56653).
+char(1,56654).
+char(9,56655).
+char(7,56656).
+char(4,56657).
+char(m,56658).
+char(8,56659).
+char(6,56660).
+char(c,56661).
+char(c,56662).
+char(m,56663).
+char(8,56664).
+char(3,56665).
+char(6,56666).
+char(p,56667).
+char(2,56668).
+char(1,56669).
+char(4,56670).
+char(6,56671).
+char(p,56672).
+char(o,56673).
+char(7,56674).
+char(1,56675).
+char(m,56676).
+char(5,56677).
+char(4,56678).
+char(8,56679).
+char(2,56680).
+char(p,56681).
+char(o,56682).
+char(o,56683).
+char(m,56684).
+char(o,56685).
+char(m,56686).
+char(9,56687).
+char(1,56688).
+char(8,56689).
+char(9,56690).
+char(p,56691).
+char(2,56692).
+char(4,56693).
+char(7,56694).
+char(0,56695).
+char(p,56696).
+char(o,56697).
+char(o,56698).
+char(o,56699).
+char(p,56700).
+char(o,56701).
+char(8,56702).
+char(0,56703).
+char(1,56704).
+char(5,56705).
+char(c,56706).
+char(p,56707).
+char(o,56708).
+char(m,56709).
+char(5,56710).
+char(7,56711).
+char(3,56712).
+char(7,56713).
+char(m,56714).
+char(3,56715).
+char(4,56716).
+char(5,56717).
+char(8,56718).
+char(p,56719).
+char(o,56720).
+char(m,56721).
+char(2,56722).
+char(3,56723).
+char(5,56724).
+char(6,56725).
+char(c,56726).
+char(c,56727).
+char(m,56728).
+char(o,56729).
+char(m,56730).
+char(7,56731).
+char(7,56732).
+char(4,56733).
+char(9,56734).
+char(c,56735).
+char(c,56736).
+char(p,56737).
+char(o,56738).
+char(p,56739).
+char(2,56740).
+char(6,56741).
+char(1,56742).
+char(4,56743).
+char(m,56744).
+char(9,56745).
+char(2,56746).
+char(5,56747).
+char(7,56748).
+char(p,56749).
+char(5,56750).
+char(5,56751).
+char(5,56752).
+char(8,56753).
+char(p,56754).
+char(o,56755).
+char(p,56756).
+char(o,56757).
+char(p,56758).
+char(1,56759).
+char(9,56760).
+char(4,56761).
+char(0,56762).
+char(p,56763).
+char(1,56764).
+char(7,56765).
+char(8,56766).
+char(0,56767).
+char(m,56768).
+char(o,56769).
+char(m,56770).
+char(o,56771).
+char(p,56772).
+char(o,56773).
+char(3,56774).
+char(p,56775).
+char(o,56776).
+char(m,56777).
+char(6,56778).
+char(9,56779).
+char(0,56780).
+char(3,56781).
+char(m,56782).
+char(5,56783).
+char(2,56784).
+char(1,56785).
+char(6,56786).
+char(c,56787).
+char(m,56788).
+char(6,56789).
+char(3,56790).
+char(6,56791).
+char(7,56792).
+char(c,56793).
+char(m,56794).
+char(o,56795).
+char(o,56796).
+char(2,56797).
+char(3,56798).
+char(2,56799).
+char(0,56800).
+char(p,56801).
+char(o,56802).
+char(o,56803).
+char(9,56804).
+char(9,56805).
+char(2,56806).
+char(5,56807).
+char(c,56808).
+char(c,56809).
+char(c,56810).
+char(c,56811).
+char(m,56812).
+char(2,56813).
+char(0,56814).
+char(5,56815).
+char(0,56816).
+char(c,56817).
+char(c,56818).
+char(c,56819).
+char(c,56820).
+char(c,56821).
+char(c,56822).
+char(p,56823).
+char(o,56824).
+char(m,56825).
+char(o,56826).
+char(m,56827).
+char(o,56828).
+char(p,56829).
+char(o,56830).
+char(p,56831).
+char(o,56832).
+char(m,56833).
+char(7,56834).
+char(0,56835).
+char(3,56836).
+char(7,56837).
+char(m,56838).
+char(5,56839).
+char(1,56840).
+char(4,56841).
+char(7,56842).
+char(c,56843).
+char(m,56844).
+char(2,56845).
+char(3,56846).
+char(0,56847).
+char(0,56848).
+char(c,56849).
+char(m,56850).
+char(7,56851).
+char(6,56852).
+char(7,56853).
+char(9,56854).
+char(c,56855).
+char(p,56856).
+char(4,56857).
+char(3,56858).
+char(9,56859).
+char(7,56860).
+char(c,56861).
+char(c,56862).
+char(p,56863).
+char(7,56864).
+char(9,56865).
+char(2,56866).
+char(8,56867).
+char(m,56868).
+char(4,56869).
+char(2,56870).
+char(8,56871).
+char(9,56872).
+char(p,56873).
+char(o,56874).
+char(o,56875).
+char(7,56876).
+char(8,56877).
+char(8,56878).
+char(9,56879).
+char(c,56880).
+char(m,56881).
+char(o,56882).
+char(6,56883).
+char(8,56884).
+char(5,56885).
+char(9,56886).
+char(p,56887).
+char(1,56888).
+char(0,56889).
+char(8,56890).
+char(8,56891).
+char(c,56892).
+char(m,56893).
+char(o,56894).
+char(m,56895).
+char(o,56896).
+char(m,56897).
+char(o,56898).
+char(m,56899).
+char(1,56900).
+char(2,56901).
+char(2,56902).
+char(1,56903).
+char(c,56904).
+char(c,56905).
+char(c,56906).
+char(c,56907).
+char(m,56908).
+char(o,56909).
+char(p,56910).
+char(o,56911).
+char(p,56912).
+char(9,56913).
+char(6,56914).
+char(6,56915).
+char(3,56916).
+char(m,56917).
+char(7,56918).
+char(3,56919).
+char(0,56920).
+char(5,56921).
+char(m,56922).
+char(o,56923).
+char(m,56924).
+char(5,56925).
+char(2,56926).
+char(9,56927).
+char(3,56928).
+char(m,56929).
+char(7,56930).
+char(6,56931).
+char(4,56932).
+char(4,56933).
+char(m,56934).
+char(5,56935).
+char(0,56936).
+char(8,56937).
+char(0,56938).
+char(c,56939).
+char(c,56940).
+char(m,56941).
+char(o,56942).
+char(m,56943).
+char(o,56944).
+char(p,56945).
+char(o,56946).
+char(p,56947).
+char(2,56948).
+char(9,56949).
+char(8,56950).
+char(2,56951).
+char(c,56952).
+char(c,56953).
+char(c,56954).
+char(c,56955).
+char(p,56956).
+char(4,56957).
+char(7,56958).
+char(9,56959).
+char(5,56960).
+char(c,56961).
+char(m,56962).
+char(o,56963).
+char(7,56964).
+char(6,56965).
+char(7,56966).
+char(2,56967).
+char(c,56968).
+char(p,56969).
+char(o,56970).
+char(p,56971).
+char(o,56972).
+char(9,56973).
+char(6,56974).
+char(0,56975).
+char(4,56976).
+char(p,56977).
+char(o,56978).
+char(m,56979).
+char(7,56980).
+char(5,56981).
+char(4,56982).
+char(2,56983).
+char(m,56984).
+char(o,56985).
+char(p,56986).
+char(o,56987).
+char(m,56988).
+char(o,56989).
+char(o,56990).
+char(m,56991).
+char(6,56992).
+char(0,56993).
+char(6,56994).
+char(1,56995).
+char(m,56996).
+char(o,56997).
+char(p,56998).
+char(2,56999).
+char(9,57000).
+char(8,57001).
+char(5,57002).
+char(c,57003).
+char(c,57004).
+char(m,57005).
+char(9,57006).
+char(1,57007).
+char(3,57008).
+char(5,57009).
+char(c,57010).
+char(c,57011).
+char(m,57012).
+char(o,57013).
+char(p,57014).
+char(7,57015).
+char(8,57016).
+char(9,57017).
+char(8,57018).
+char(c,57019).
+char(p,57020).
+char(1,57021).
+char(1,57022).
+char(1,57023).
+char(6,57024).
+char(c,57025).
+char(m,57026).
+char(o,57027).
+char(p,57028).
+char(7,57029).
+char(2,57030).
+char(3,57031).
+char(4,57032).
+char(c,57033).
+char(c,57034).
+char(m,57035).
+char(2,57036).
+char(6,57037).
+char(1,57038).
+char(m,57039).
+char(1,57040).
+char(4,57041).
+char(0,57042).
+char(1,57043).
+char(p,57044).
+char(o,57045).
+char(p,57046).
+char(o,57047).
+char(p,57048).
+char(2,57049).
+char(9,57050).
+char(4,57051).
+char(7,57052).
+char(c,57053).
+char(c,57054).
+char(p,57055).
+char(8,57056).
+char(9,57057).
+char(2,57058).
+char(8,57059).
+char(p,57060).
+char(5,57061).
+char(2,57062).
+char(9,57063).
+char(3,57064).
+char(m,57065).
+char(1,57066).
+char(4,57067).
+char(6,57068).
+char(2,57069).
+char(c,57070).
+char(m,57071).
+char(o,57072).
+char(p,57073).
+char(o,57074).
+char(p,57075).
+char(5,57076).
+char(6,57077).
+char(2,57078).
+char(c,57079).
+char(c,57080).
+char(m,57081).
+char(8,57082).
+char(4,57083).
+char(2,57084).
+char(8,57085).
+char(m,57086).
+char(o,57087).
+char(3,57088).
+char(9,57089).
+char(4,57090).
+char(0,57091).
+char(m,57092).
+char(o,57093).
+char(m,57094).
+char(o,57095).
+char(1,57096).
+char(5,57097).
+char(5,57098).
+char(6,57099).
+char(c,57100).
+char(c,57101).
+char(c,57102).
+char(c,57103).
+char(c,57104).
+char(p,57105).
+char(o,57106).
+char(m,57107).
+char(8,57108).
+char(1,57109).
+char(6,57110).
+char(2,57111).
+char(p,57112).
+char(9,57113).
+char(9,57114).
+char(4,57115).
+char(9,57116).
+char(c,57117).
+char(p,57118).
+char(1,57119).
+char(3,57120).
+char(2,57121).
+char(9,57122).
+char(m,57123).
+char(8,57124).
+char(3,57125).
+char(8,57126).
+char(3,57127).
+char(m,57128).
+char(8,57129).
+char(4,57130).
+char(0,57131).
+char(3,57132).
+char(c,57133).
+char(c,57134).
+char(c,57135).
+char(p,57136).
+char(o,57137).
+char(m,57138).
+char(o,57139).
+char(2,57140).
+char(2,57141).
+char(8,57142).
+char(3,57143).
+char(c,57144).
+char(m,57145).
+char(o,57146).
+char(m,57147).
+char(o,57148).
+char(m,57149).
+char(o,57150).
+char(m,57151).
+char(7,57152).
+char(1,57153).
+char(4,57154).
+char(c,57155).
+char(m,57156).
+char(o,57157).
+char(p,57158).
+char(8,57159).
+char(1,57160).
+char(6,57161).
+char(6,57162).
+char(p,57163).
+char(o,57164).
+char(2,57165).
+char(8,57166).
+char(6,57167).
+char(c,57168).
+char(c,57169).
+char(p,57170).
+char(4,57171).
+char(2,57172).
+char(9,57173).
+char(3,57174).
+char(c,57175).
+char(m,57176).
+char(o,57177).
+char(p,57178).
+char(o,57179).
+char(m,57180).
+char(o,57181).
+char(6,57182).
+char(7,57183).
+char(2,57184).
+char(6,57185).
+char(p,57186).
+char(2,57187).
+char(0,57188).
+char(9,57189).
+char(2,57190).
+char(c,57191).
+char(p,57192).
+char(2,57193).
+char(6,57194).
+char(0,57195).
+char(9,57196).
+char(p,57197).
+char(o,57198).
+char(o,57199).
+char(6,57200).
+char(3,57201).
+char(5,57202).
+char(8,57203).
+char(p,57204).
+char(1,57205).
+char(9,57206).
+char(6,57207).
+char(7,57208).
+char(p,57209).
+char(4,57210).
+char(7,57211).
+char(8,57212).
+char(p,57213).
+char(o,57214).
+char(4,57215).
+char(7,57216).
+char(9,57217).
+char(5,57218).
+char(c,57219).
+char(c,57220).
+char(p,57221).
+char(o,57222).
+char(m,57223).
+char(3,57224).
+char(6,57225).
+char(3,57226).
+char(1,57227).
+char(m,57228).
+char(3,57229).
+char(9,57230).
+char(0,57231).
+char(6,57232).
+char(m,57233).
+char(6,57234).
+char(3,57235).
+char(2,57236).
+char(m,57237).
+char(o,57238).
+char(p,57239).
+char(4,57240).
+char(1,57241).
+char(0,57242).
+char(m,57243).
+char(5,57244).
+char(9,57245).
+char(1,57246).
+char(3,57247).
+char(c,57248).
+char(p,57249).
+char(7,57250).
+char(7,57251).
+char(6,57252).
+char(5,57253).
+char(p,57254).
+char(5,57255).
+char(3,57256).
+char(7,57257).
+char(9,57258).
+char(m,57259).
+char(5,57260).
+char(0,57261).
+char(0,57262).
+char(5,57263).
+char(c,57264).
+char(p,57265).
+char(o,57266).
+char(m,57267).
+char(1,57268).
+char(1,57269).
+char(6,57270).
+char(c,57271).
+char(c,57272).
+char(p,57273).
+char(4,57274).
+char(4,57275).
+char(5,57276).
+char(p,57277).
+char(o,57278).
+char(3,57279).
+char(9,57280).
+char(0,57281).
+char(0,57282).
+char(p,57283).
+char(9,57284).
+char(6,57285).
+char(5,57286).
+char(2,57287).
+char(p,57288).
+char(1,57289).
+char(8,57290).
+char(5,57291).
+char(3,57292).
+char(m,57293).
+char(2,57294).
+char(6,57295).
+char(1,57296).
+char(0,57297).
+char(m,57298).
+char(o,57299).
+char(p,57300).
+char(8,57301).
+char(7,57302).
+char(8,57303).
+char(9,57304).
+char(p,57305).
+char(3,57306).
+char(1,57307).
+char(9,57308).
+char(5,57309).
+char(m,57310).
+char(7,57311).
+char(7,57312).
+char(6,57313).
+char(6,57314).
+char(p,57315).
+char(1,57316).
+char(6,57317).
+char(9,57318).
+char(5,57319).
+char(c,57320).
+char(m,57321).
+char(o,57322).
+char(3,57323).
+char(2,57324).
+char(9,57325).
+char(4,57326).
+char(c,57327).
+char(p,57328).
+char(o,57329).
+char(p,57330).
+char(o,57331).
+char(p,57332).
+char(4,57333).
+char(3,57334).
+char(5,57335).
+char(p,57336).
+char(o,57337).
+char(5,57338).
+char(3,57339).
+char(0,57340).
+char(5,57341).
+char(p,57342).
+char(o,57343).
+char(o,57344).
+char(1,57345).
+char(5,57346).
+char(6,57347).
+char(3,57348).
+char(c,57349).
+char(p,57350).
+char(8,57351).
+char(0,57352).
+char(4,57353).
+char(5,57354).
+char(c,57355).
+char(c,57356).
+char(c,57357).
+char(c,57358).
+char(c,57359).
+char(c,57360).
+char(p,57361).
+char(o,57362).
+char(m,57363).
+char(o,57364).
+char(o,57365).
+char(m,57366).
+char(o,57367).
+char(m,57368).
+char(o,57369).
+char(m,57370).
+char(1,57371).
+char(6,57372).
+char(0,57373).
+char(2,57374).
+char(c,57375).
+char(p,57376).
+char(4,57377).
+char(2,57378).
+char(0,57379).
+char(p,57380).
+char(4,57381).
+char(3,57382).
+char(5,57383).
+char(9,57384).
+char(m,57385).
+char(2,57386).
+char(2,57387).
+char(4,57388).
+char(6,57389).
+char(p,57390).
+char(o,57391).
+char(m,57392).
+char(9,57393).
+char(1,57394).
+char(0,57395).
+char(m,57396).
+char(6,57397).
+char(8,57398).
+char(3,57399).
+char(8,57400).
+char(p,57401).
+char(o,57402).
+char(m,57403).
+char(o,57404).
+char(m,57405).
+char(o,57406).
+char(p,57407).
+char(o,57408).
+char(m,57409).
+char(6,57410).
+char(9,57411).
+char(5,57412).
+char(5,57413).
+char(c,57414).
+char(c,57415).
+char(c,57416).
+char(c,57417).
+char(c,57418).
+char(p,57419).
+char(o,57420).
+char(m,57421).
+char(2,57422).
+char(4,57423).
+char(p,57424).
+char(o,57425).
+char(p,57426).
+char(o,57427).
+char(m,57428).
+char(o,57429).
+char(p,57430).
+char(o,57431).
+char(m,57432).
+char(7,57433).
+char(0,57434).
+char(4,57435).
+char(6,57436).
+char(c,57437).
+char(p,57438).
+char(9,57439).
+char(7,57440).
+char(5,57441).
+char(2,57442).
+char(c,57443).
+char(c,57444).
+char(c,57445).
+char(m,57446).
+char(o,57447).
+char(9,57448).
+char(5,57449).
+char(6,57450).
+char(2,57451).
+char(c,57452).
+char(c,57453).
+char(c,57454).
+char(c,57455).
+char(m,57456).
+char(9,57457).
+char(0,57458).
+char(9,57459).
+char(m,57460).
+char(3,57461).
+char(1,57462).
+char(4,57463).
+char(4,57464).
+char(c,57465).
+char(c,57466).
+char(c,57467).
+char(c,57468).
+char(c,57469).
+char(c,57470).
+char(c,57471).
+char(m,57472).
+char(o,57473).
+char(m,57474).
+char(2,57475).
+char(7,57476).
+char(4,57477).
+char(9,57478).
+char(c,57479).
+char(c,57480).
+char(p,57481).
+char(1,57482).
+char(3,57483).
+char(0,57484).
+char(7,57485).
+char(p,57486).
+char(o,57487).
+char(p,57488).
+char(o,57489).
+char(p,57490).
+char(o,57491).
+char(7,57492).
+char(7,57493).
+char(9,57494).
+char(5,57495).
+char(c,57496).
+char(p,57497).
+char(8,57498).
+char(4,57499).
+char(1,57500).
+char(3,57501).
+char(c,57502).
+char(m,57503).
+char(3,57504).
+char(0,57505).
+char(2,57506).
+char(1,57507).
+char(c,57508).
+char(c,57509).
+char(p,57510).
+char(o,57511).
+char(m,57512).
+char(3,57513).
+char(5,57514).
+char(4,57515).
+char(m,57516).
+char(3,57517).
+char(2,57518).
+char(8,57519).
+char(6,57520).
+char(p,57521).
+char(o,57522).
+char(o,57523).
+char(p,57524).
+char(o,57525).
+char(p,57526).
+char(5,57527).
+char(1,57528).
+char(8,57529).
+char(1,57530).
+char(p,57531).
+char(o,57532).
+char(p,57533).
+char(o,57534).
+char(2,57535).
+char(5,57536).
+char(1,57537).
+char(m,57538).
+char(5,57539).
+char(9,57540).
+char(4,57541).
+char(6,57542).
+char(c,57543).
+char(p,57544).
+char(o,57545).
+char(p,57546).
+char(o,57547).
+char(m,57548).
+char(2,57549).
+char(7,57550).
+char(7,57551).
+char(8,57552).
+char(c,57553).
+char(p,57554).
+char(o,57555).
+char(p,57556).
+char(2,57557).
+char(9,57558).
+char(9,57559).
+char(c,57560).
+char(c,57561).
+char(m,57562).
+char(o,57563).
+char(p,57564).
+char(6,57565).
+char(5,57566).
+char(4,57567).
+char(8,57568).
+char(m,57569).
+char(o,57570).
+char(m,57571).
+char(o,57572).
+char(p,57573).
+char(5,57574).
+char(9,57575).
+char(1,57576).
+char(5,57577).
+char(c,57578).
+char(c,57579).
+char(c,57580).
+char(m,57581).
+char(3,57582).
+char(5,57583).
+char(8,57584).
+char(0,57585).
+char(m,57586).
+char(o,57587).
+char(9,57588).
+char(6,57589).
+char(1,57590).
+char(6,57591).
+char(m,57592).
+char(1,57593).
+char(6,57594).
+char(9,57595).
+char(c,57596).
+char(c,57597).
+char(m,57598).
+char(o,57599).
+char(m,57600).
+char(6,57601).
+char(5,57602).
+char(7,57603).
+char(4,57604).
+char(c,57605).
+char(c,57606).
+char(c,57607).
+char(c,57608).
+char(p,57609).
+char(6,57610).
+char(9,57611).
+char(1,57612).
+char(m,57613).
+char(o,57614).
+char(m,57615).
+char(2,57616).
+char(1,57617).
+char(9,57618).
+char(1,57619).
+char(c,57620).
+char(m,57621).
+char(1,57622).
+char(3,57623).
+char(1,57624).
+char(8,57625).
+char(c,57626).
+char(c,57627).
+char(c,57628).
+char(c,57629).
+char(p,57630).
+char(o,57631).
+char(8,57632).
+char(6,57633).
+char(8,57634).
+char(8,57635).
+char(c,57636).
+char(m,57637).
+char(5,57638).
+char(2,57639).
+char(4,57640).
+char(2,57641).
+char(m,57642).
+char(3,57643).
+char(3,57644).
+char(5,57645).
+char(3,57646).
+char(c,57647).
+char(m,57648).
+char(6,57649).
+char(9,57650).
+char(2,57651).
+char(3,57652).
+char(m,57653).
+char(8,57654).
+char(3,57655).
+char(6,57656).
+char(4,57657).
+char(m,57658).
+char(1,57659).
+char(5,57660).
+char(9,57661).
+char(3,57662).
+char(p,57663).
+char(4,57664).
+char(2,57665).
+char(8,57666).
+char(6,57667).
+char(c,57668).
+char(p,57669).
+char(6,57670).
+char(6,57671).
+char(6,57672).
+char(0,57673).
+char(p,57674).
+char(o,57675).
+char(4,57676).
+char(1,57677).
+char(0,57678).
+char(8,57679).
+char(m,57680).
+char(o,57681).
+char(m,57682).
+char(3,57683).
+char(2,57684).
+char(6,57685).
+char(4,57686).
+char(c,57687).
+char(p,57688).
+char(o,57689).
+char(m,57690).
+char(1,57691).
+char(8,57692).
+char(7,57693).
+char(m,57694).
+char(9,57695).
+char(7,57696).
+char(0,57697).
+char(3,57698).
+char(p,57699).
+char(o,57700).
+char(m,57701).
+char(o,57702).
+char(m,57703).
+char(o,57704).
+char(m,57705).
+char(o,57706).
+char(m,57707).
+char(o,57708).
+char(m,57709).
+char(5,57710).
+char(9,57711).
+char(2,57712).
+char(9,57713).
+char(m,57714).
+char(o,57715).
+char(o,57716).
+char(1,57717).
+char(9,57718).
+char(7,57719).
+char(2,57720).
+char(c,57721).
+char(m,57722).
+char(4,57723).
+char(1,57724).
+char(3,57725).
+char(1,57726).
+char(m,57727).
+char(o,57728).
+char(8,57729).
+char(7,57730).
+char(9,57731).
+char(m,57732).
+char(7,57733).
+char(5,57734).
+char(2,57735).
+char(7,57736).
+char(c,57737).
+char(c,57738).
+char(c,57739).
+char(c,57740).
+char(m,57741).
+char(o,57742).
+char(4,57743).
+char(7,57744).
+char(1,57745).
+char(m,57746).
+char(4,57747).
+char(6,57748).
+char(4,57749).
+char(9,57750).
+char(p,57751).
+char(2,57752).
+char(6,57753).
+char(8,57754).
+char(7,57755).
+char(c,57756).
+char(c,57757).
+char(c,57758).
+char(c,57759).
+char(c,57760).
+char(c,57761).
+char(m,57762).
+char(8,57763).
+char(8,57764).
+char(4,57765).
+char(0,57766).
+char(m,57767).
+char(o,57768).
+char(6,57769).
+char(7,57770).
+char(6,57771).
+char(6,57772).
+char(c,57773).
+char(p,57774).
+char(3,57775).
+char(8,57776).
+char(5,57777).
+char(3,57778).
+char(c,57779).
+char(c,57780).
+char(m,57781).
+char(2,57782).
+char(9,57783).
+char(2,57784).
+char(m,57785).
+char(1,57786).
+char(6,57787).
+char(5,57788).
+char(1,57789).
+char(p,57790).
+char(o,57791).
+char(m,57792).
+char(9,57793).
+char(2,57794).
+char(4,57795).
+char(2,57796).
+char(m,57797).
+char(8,57798).
+char(4,57799).
+char(1,57800).
+char(0,57801).
+char(c,57802).
+char(c,57803).
+char(c,57804).
+char(m,57805).
+char(o,57806).
+char(7,57807).
+char(0,57808).
+char(1,57809).
+char(3,57810).
+char(c,57811).
+char(c,57812).
+char(m,57813).
+char(o,57814).
+char(o,57815).
+char(6,57816).
+char(3,57817).
+char(5,57818).
+char(2,57819).
+char(m,57820).
+char(3,57821).
+char(3,57822).
+char(4,57823).
+char(3,57824).
+char(m,57825).
+char(5,57826).
+char(5,57827).
+char(9,57828).
+char(6,57829).
+char(c,57830).
+char(c,57831).
+char(m,57832).
+char(1,57833).
+char(8,57834).
+char(6,57835).
+char(9,57836).
+char(m,57837).
+char(o,57838).
+char(8,57839).
+char(6,57840).
+char(4,57841).
+char(8,57842).
+char(c,57843).
+char(c,57844).
+char(p,57845).
+char(7,57846).
+char(2,57847).
+char(2,57848).
+char(9,57849).
+char(m,57850).
+char(4,57851).
+char(7,57852).
+char(9,57853).
+char(4,57854).
+char(p,57855).
+char(3,57856).
+char(7,57857).
+char(0,57858).
+char(5,57859).
+char(m,57860).
+char(8,57861).
+char(5,57862).
+char(3,57863).
+char(0,57864).
+char(c,57865).
+char(p,57866).
+char(o,57867).
+char(m,57868).
+char(o,57869).
+char(m,57870).
+char(o,57871).
+char(p,57872).
+char(2,57873).
+char(6,57874).
+char(0,57875).
+char(7,57876).
+char(p,57877).
+char(o,57878).
+char(m,57879).
+char(o,57880).
+char(p,57881).
+char(3,57882).
+char(7,57883).
+char(0,57884).
+char(p,57885).
+char(o,57886).
+char(o,57887).
+char(o,57888).
+char(o,57889).
+char(m,57890).
+char(o,57891).
+char(2,57892).
+char(1,57893).
+char(9,57894).
+char(5,57895).
+char(m,57896).
+char(1,57897).
+char(1,57898).
+char(5,57899).
+char(5,57900).
+char(c,57901).
+char(c,57902).
+char(c,57903).
+char(c,57904).
+char(c,57905).
+char(p,57906).
+char(o,57907).
+char(m,57908).
+char(o,57909).
+char(m,57910).
+char(7,57911).
+char(3,57912).
+char(8,57913).
+char(1,57914).
+char(m,57915).
+char(o,57916).
+char(o,57917).
+char(p,57918).
+char(o,57919).
+char(m,57920).
+char(o,57921).
+char(5,57922).
+char(7,57923).
+char(6,57924).
+char(p,57925).
+char(1,57926).
+char(0,57927).
+char(8,57928).
+char(c,57929).
+char(p,57930).
+char(o,57931).
+char(m,57932).
+char(7,57933).
+char(3,57934).
+char(5,57935).
+char(m,57936).
+char(2,57937).
+char(3,57938).
+char(8,57939).
+char(6,57940).
+char(c,57941).
+char(p,57942).
+char(o,57943).
+char(m,57944).
+char(o,57945).
+char(m,57946).
+char(1,57947).
+char(2,57948).
+char(2,57949).
+char(7,57950).
+char(m,57951).
+char(9,57952).
+char(8,57953).
+char(m,57954).
+char(9,57955).
+char(5,57956).
+char(5,57957).
+char(1,57958).
+char(c,57959).
+char(c,57960).
+char(m,57961).
+char(3,57962).
+char(1,57963).
+char(8,57964).
+char(8,57965).
+char(c,57966).
+char(m,57967).
+char(6,57968).
+char(1,57969).
+char(0,57970).
+char(0,57971).
+char(p,57972).
+char(o,57973).
+char(p,57974).
+char(o,57975).
+char(m,57976).
+char(8,57977).
+char(7,57978).
+char(3,57979).
+char(0,57980).
+char(c,57981).
+char(c,57982).
+char(m,57983).
+char(2,57984).
+char(2,57985).
+char(p,57986).
+char(2,57987).
+char(3,57988).
+char(4,57989).
+char(4,57990).
+char(m,57991).
+char(6,57992).
+char(5,57993).
+char(2,57994).
+char(8,57995).
+char(p,57996).
+char(7,57997).
+char(9,57998).
+char(6,57999).
+char(4,58000).
+char(m,58001).
+char(o,58002).
+char(p,58003).
+char(3,58004).
+char(9,58005).
+char(0,58006).
+char(6,58007).
+char(p,58008).
+char(2,58009).
+char(6,58010).
+char(5,58011).
+char(7,58012).
+char(c,58013).
+char(c,58014).
+char(c,58015).
+char(m,58016).
+char(o,58017).
+char(o,58018).
+char(m,58019).
+char(o,58020).
+char(p,58021).
+char(3,58022).
+char(2,58023).
+char(3,58024).
+char(5,58025).
+char(p,58026).
+char(o,58027).
+char(m,58028).
+char(3,58029).
+char(2,58030).
+char(5,58031).
+char(7,58032).
+char(m,58033).
+char(4,58034).
+char(7,58035).
+char(1,58036).
+char(5,58037).
+char(p,58038).
+char(o,58039).
+char(p,58040).
+char(4,58041).
+char(8,58042).
+char(3,58043).
+char(5,58044).
+char(c,58045).
+char(c,58046).
+char(m,58047).
+char(o,58048).
+char(m,58049).
+char(o,58050).
+char(4,58051).
+char(9,58052).
+char(3,58053).
+char(5,58054).
+char(p,58055).
+char(1,58056).
+char(3,58057).
+char(7,58058).
+char(6,58059).
+char(p,58060).
+char(2,58061).
+char(5,58062).
+char(8,58063).
+char(5,58064).
+char(c,58065).
+char(c,58066).
+char(p,58067).
+char(o,58068).
+char(p,58069).
+char(o,58070).
+char(o,58071).
+char(p,58072).
+char(5,58073).
+char(7,58074).
+char(0,58075).
+char(4,58076).
+char(c,58077).
+char(c,58078).
+char(m,58079).
+char(o,58080).
+char(m,58081).
+char(o,58082).
+char(m,58083).
+char(3,58084).
+char(4,58085).
+char(4,58086).
+char(8,58087).
+char(m,58088).
+char(1,58089).
+char(4,58090).
+char(8,58091).
+char(6,58092).
+char(c,58093).
+char(m,58094).
+char(o,58095).
+char(p,58096).
+char(4,58097).
+char(1,58098).
+char(9,58099).
+char(0,58100).
+char(m,58101).
+char(o,58102).
+char(p,58103).
+char(o,58104).
+char(m,58105).
+char(5,58106).
+char(1,58107).
+char(6,58108).
+char(4,58109).
+char(c,58110).
+char(c,58111).
+char(c,58112).
+char(c,58113).
+char(c,58114).
+char(m,58115).
+char(5,58116).
+char(8,58117).
+char(5,58118).
+char(8,58119).
+char(m,58120).
+char(4,58121).
+char(5,58122).
+char(5,58123).
+char(7,58124).
+char(m,58125).
+char(o,58126).
+char(m,58127).
+char(o,58128).
+char(m,58129).
+char(8,58130).
+char(5,58131).
+char(3,58132).
+char(4,58133).
+char(m,58134).
+char(o,58135).
+char(m,58136).
+char(o,58137).
+char(p,58138).
+char(o,58139).
+char(m,58140).
+char(5,58141).
+char(3,58142).
+char(6,58143).
+char(9,58144).
+char(c,58145).
+char(m,58146).
+char(o,58147).
+char(m,58148).
+char(5,58149).
+char(1,58150).
+char(5,58151).
+char(3,58152).
+char(m,58153).
+char(5,58154).
+char(2,58155).
+char(3,58156).
+char(1,58157).
+char(c,58158).
+char(p,58159).
+char(o,58160).
+char(o,58161).
+char(p,58162).
+char(9,58163).
+char(2,58164).
+char(7,58165).
+char(9,58166).
+char(p,58167).
+char(o,58168).
+char(o,58169).
+char(9,58170).
+char(2,58171).
+char(4,58172).
+char(6,58173).
+char(p,58174).
+char(3,58175).
+char(2,58176).
+char(4,58177).
+char(7,58178).
+char(m,58179).
+char(6,58180).
+char(2,58181).
+char(8,58182).
+char(0,58183).
+char(c,58184).
+char(p,58185).
+char(o,58186).
+char(o,58187).
+char(4,58188).
+char(0,58189).
+char(8,58190).
+char(6,58191).
+char(p,58192).
+char(o,58193).
+char(m,58194).
+char(o,58195).
+char(p,58196).
+char(1,58197).
+char(5,58198).
+char(5,58199).
+char(6,58200).
+char(c,58201).
+char(c,58202).
+char(p,58203).
+char(2,58204).
+char(4,58205).
+char(6,58206).
+char(6,58207).
+char(m,58208).
+char(o,58209).
+char(m,58210).
+char(5,58211).
+char(8,58212).
+char(3,58213).
+char(4,58214).
+char(p,58215).
+char(o,58216).
+char(p,58217).
+char(o,58218).
+char(m,58219).
+char(o,58220).
+char(p,58221).
+char(8,58222).
+char(0,58223).
+char(0,58224).
+char(7,58225).
+char(c,58226).
+char(c,58227).
+char(m,58228).
+char(o,58229).
+char(p,58230).
+char(o,58231).
+char(4,58232).
+char(0,58233).
+char(6,58234).
+char(8,58235).
+char(c,58236).
+char(c,58237).
+char(c,58238).
+char(c,58239).
+char(c,58240).
+char(c,58241).
+char(c,58242).
+char(c,58243).
+char(c,58244).
+char(c,58245).
+char(c,58246).
+char(m,58247).
+char(3,58248).
+char(3,58249).
+char(9,58250).
+char(7,58251).
+char(c,58252).
+char(m,58253).
+char(o,58254).
+char(p,58255).
+char(o,58256).
+char(p,58257).
+char(6,58258).
+char(3,58259).
+char(8,58260).
+char(6,58261).
+char(c,58262).
+char(p,58263).
+char(2,58264).
+char(9,58265).
+char(2,58266).
+char(1,58267).
+char(c,58268).
+char(c,58269).
+char(p,58270).
+char(o,58271).
+char(m,58272).
+char(o,58273).
+char(o,58274).
+char(p,58275).
+char(4,58276).
+char(1,58277).
+char(0,58278).
+char(9,58279).
+char(m,58280).
+char(o,58281).
+char(p,58282).
+char(o,58283).
+char(p,58284).
+char(7,58285).
+char(5,58286).
+char(5,58287).
+char(9,58288).
+char(c,58289).
+char(c,58290).
+char(p,58291).
+char(o,58292).
+char(7,58293).
+char(9,58294).
+char(1,58295).
+char(8,58296).
+char(c,58297).
+char(c,58298).
+char(p,58299).
+char(o,58300).
+char(1,58301).
+char(8,58302).
+char(4,58303).
+char(5,58304).
+char(c,58305).
+char(c,58306).
+char(c,58307).
+char(c,58308).
+char(m,58309).
+char(4,58310).
+char(2,58311).
+char(0,58312).
+char(3,58313).
+char(m,58314).
+char(o,58315).
+char(5,58316).
+char(7,58317).
+char(1,58318).
+char(4,58319).
+char(c,58320).
+char(c,58321).
+char(c,58322).
+char(p,58323).
+char(o,58324).
+char(o,58325).
+char(o,58326).
+char(o,58327).
+char(m,58328).
+char(6,58329).
+char(9,58330).
+char(8,58331).
+char(7,58332).
+char(c,58333).
+char(c,58334).
+char(m,58335).
+char(o,58336).
+char(4,58337).
+char(5,58338).
+char(8,58339).
+char(7,58340).
+char(c,58341).
+char(p,58342).
+char(5,58343).
+char(1,58344).
+char(6,58345).
+char(6,58346).
+char(p,58347).
+char(2,58348).
+char(5,58349).
+char(2,58350).
+char(7,58351).
+char(p,58352).
+char(1,58353).
+char(3,58354).
+char(2,58355).
+char(7,58356).
+char(c,58357).
+char(m,58358).
+char(6,58359).
+char(9,58360).
+char(1,58361).
+char(1,58362).
+char(c,58363).
+char(p,58364).
+char(o,58365).
+char(p,58366).
+char(6,58367).
+char(5,58368).
+char(3,58369).
+char(5,58370).
+char(p,58371).
+char(6,58372).
+char(0,58373).
+char(0,58374).
+char(1,58375).
+char(c,58376).
+char(c,58377).
+char(c,58378).
+char(p,58379).
+char(4,58380).
+char(4,58381).
+char(1,58382).
+char(8,58383).
+char(c,58384).
+char(c,58385).
+char(p,58386).
+char(o,58387).
+char(m,58388).
+char(4,58389).
+char(2,58390).
+char(5,58391).
+char(4,58392).
+char(c,58393).
+char(m,58394).
+char(o,58395).
+char(7,58396).
+char(5,58397).
+char(4,58398).
+char(9,58399).
+char(c,58400).
+char(c,58401).
+char(c,58402).
+char(c,58403).
+char(m,58404).
+char(o,58405).
+char(8,58406).
+char(8,58407).
+char(0,58408).
+char(9,58409).
+char(c,58410).
+char(c,58411).
+char(c,58412).
+char(p,58413).
+char(o,58414).
+char(m,58415).
+char(5,58416).
+char(3,58417).
+char(5,58418).
+char(5,58419).
+char(m,58420).
+char(o,58421).
+char(o,58422).
+char(o,58423).
+char(p,58424).
+char(5,58425).
+char(6,58426).
+char(2,58427).
+char(7,58428).
+char(c,58429).
+char(c,58430).
+char(c,58431).
+char(p,58432).
+char(o,58433).
+char(m,58434).
+char(2,58435).
+char(8,58436).
+char(9,58437).
+char(8,58438).
+char(c,58439).
+char(c,58440).
+char(p,58441).
+char(o,58442).
+char(p,58443).
+char(7,58444).
+char(0,58445).
+char(6,58446).
+char(4,58447).
+char(c,58448).
+char(m,58449).
+char(o,58450).
+char(m,58451).
+char(o,58452).
+char(p,58453).
+char(o,58454).
+char(p,58455).
+char(o,58456).
+char(4,58457).
+char(7,58458).
+char(2,58459).
+char(2,58460).
+char(p,58461).
+char(9,58462).
+char(5,58463).
+char(1,58464).
+char(0,58465).
+char(m,58466).
+char(1,58467).
+char(7,58468).
+char(9,58469).
+char(p,58470).
+char(o,58471).
+char(p,58472).
+char(o,58473).
+char(m,58474).
+char(2,58475).
+char(0,58476).
+char(7,58477).
+char(m,58478).
+char(o,58479).
+char(3,58480).
+char(1,58481).
+char(6,58482).
+char(1,58483).
+char(p,58484).
+char(4,58485).
+char(5,58486).
+char(8,58487).
+char(6,58488).
+char(p,58489).
+char(o,58490).
+char(p,58491).
+char(o,58492).
+char(p,58493).
+char(o,58494).
+char(7,58495).
+char(9,58496).
+char(9,58497).
+char(7,58498).
+char(c,58499).
+char(m,58500).
+char(5,58501).
+char(1,58502).
+char(4,58503).
+char(8,58504).
+char(p,58505).
+char(8,58506).
+char(5,58507).
+char(p,58508).
+char(6,58509).
+char(8,58510).
+char(8,58511).
+char(9,58512).
+char(c,58513).
+char(p,58514).
+char(9,58515).
+char(0,58516).
+char(1,58517).
+char(4,58518).
+char(c,58519).
+char(m,58520).
+char(o,58521).
+char(m,58522).
+char(7,58523).
+char(6,58524).
+char(1,58525).
+char(1,58526).
+char(p,58527).
+char(o,58528).
+char(p,58529).
+char(o,58530).
+char(p,58531).
+char(8,58532).
+char(0,58533).
+char(9,58534).
+char(c,58535).
+char(c,58536).
+char(c,58537).
+char(m,58538).
+char(9,58539).
+char(2,58540).
+char(4,58541).
+char(6,58542).
+char(m,58543).
+char(3,58544).
+char(1,58545).
+char(5,58546).
+char(3,58547).
+char(m,58548).
+char(7,58549).
+char(6,58550).
+char(1,58551).
+char(3,58552).
+char(c,58553).
+char(c,58554).
+char(c,58555).
+char(m,58556).
+char(o,58557).
+char(o,58558).
+char(5,58559).
+char(0,58560).
+char(5,58561).
+char(8,58562).
+char(m,58563).
+char(o,58564).
+char(p,58565).
+char(o,58566).
+char(p,58567).
+char(8,58568).
+char(0,58569).
+char(8,58570).
+char(0,58571).
+char(m,58572).
+char(o,58573).
+char(8,58574).
+char(1,58575).
+char(9,58576).
+char(7,58577).
+char(m,58578).
+char(2,58579).
+char(5,58580).
+char(1,58581).
+char(0,58582).
+char(c,58583).
+char(c,58584).
+char(c,58585).
+char(m,58586).
+char(3,58587).
+char(3,58588).
+char(5,58589).
+char(7,58590).
+char(c,58591).
+char(m,58592).
+char(o,58593).
+char(o,58594).
+char(o,58595).
+char(m,58596).
+char(o,58597).
+char(p,58598).
+char(o,58599).
+char(m,58600).
+char(o,58601).
+char(m,58602).
+char(1,58603).
+char(1,58604).
+char(7,58605).
+char(0,58606).
+char(c,58607).
+char(p,58608).
+char(o,58609).
+char(m,58610).
+char(8,58611).
+char(1,58612).
+char(3,58613).
+char(7,58614).
+char(c,58615).
+char(c,58616).
+char(p,58617).
+char(8,58618).
+char(4,58619).
+char(1,58620).
+char(9,58621).
+char(c,58622).
+char(m,58623).
+char(o,58624).
+char(o,58625).
+char(3,58626).
+char(2,58627).
+char(9,58628).
+char(2,58629).
+char(c,58630).
+char(m,58631).
+char(8,58632).
+char(2,58633).
+char(1,58634).
+char(8,58635).
+char(p,58636).
+char(o,58637).
+char(m,58638).
+char(o,58639).
+char(m,58640).
+char(o,58641).
+char(3,58642).
+char(7,58643).
+char(2,58644).
+char(7,58645).
+char(c,58646).
+char(c,58647).
+char(p,58648).
+char(o,58649).
+char(p,58650).
+char(o,58651).
+char(m,58652).
+char(3,58653).
+char(8,58654).
+char(1,58655).
+char(7,58656).
+char(p,58657).
+char(6,58658).
+char(3,58659).
+char(9,58660).
+char(6,58661).
+char(p,58662).
+char(o,58663).
+char(o,58664).
+char(o,58665).
+char(p,58666).
+char(o,58667).
+char(p,58668).
+char(o,58669).
+char(m,58670).
+char(6,58671).
+char(7,58672).
+char(3,58673).
+char(4,58674).
+char(p,58675).
+char(o,58676).
+char(p,58677).
+char(o,58678).
+char(m,58679).
+char(o,58680).
+char(p,58681).
+char(5,58682).
+char(9,58683).
+char(1,58684).
+char(0,58685).
+char(c,58686).
+char(c,58687).
+char(p,58688).
+char(4,58689).
+char(7,58690).
+char(5,58691).
+char(2,58692).
+char(c,58693).
+char(p,58694).
+char(o,58695).
+char(m,58696).
+char(9,58697).
+char(1,58698).
+char(8,58699).
+char(1,58700).
+char(p,58701).
+char(o,58702).
+char(6,58703).
+char(9,58704).
+char(6,58705).
+char(7,58706).
+char(p,58707).
+char(o,58708).
+char(p,58709).
+char(o,58710).
+char(m,58711).
+char(o,58712).
+char(p,58713).
+char(o,58714).
+char(m,58715).
+char(o,58716).
+char(o,58717).
+char(p,58718).
+char(o,58719).
+char(p,58720).
+char(8,58721).
+char(7,58722).
+char(6,58723).
+char(1,58724).
+char(p,58725).
+char(o,58726).
+char(o,58727).
+char(m,58728).
+char(o,58729).
+char(p,58730).
+char(o,58731).
+char(m,58732).
+char(5,58733).
+char(5,58734).
+char(3,58735).
+char(3,58736).
+char(c,58737).
+char(c,58738).
+char(m,58739).
+char(6,58740).
+char(6,58741).
+char(1,58742).
+char(7,58743).
+char(c,58744).
+char(m,58745).
+char(3,58746).
+char(5,58747).
+char(6,58748).
+char(5,58749).
+char(m,58750).
+char(8,58751).
+char(2,58752).
+char(3,58753).
+char(6,58754).
+char(c,58755).
+char(c,58756).
+char(c,58757).
+char(p,58758).
+char(8,58759).
+char(4,58760).
+char(1,58761).
+char(4,58762).
+char(p,58763).
+char(o,58764).
+char(o,58765).
+char(2,58766).
+char(6,58767).
+char(4,58768).
+char(3,58769).
+char(c,58770).
+char(c,58771).
+char(c,58772).
+char(c,58773).
+char(m,58774).
+char(9,58775).
+char(8,58776).
+char(6,58777).
+char(8,58778).
+char(m,58779).
+char(9,58780).
+char(9,58781).
+char(9,58782).
+char(6,58783).
+char(p,58784).
+char(1,58785).
+char(5,58786).
+char(0,58787).
+char(1,58788).
+char(c,58789).
+char(m,58790).
+char(o,58791).
+char(4,58792).
+char(4,58793).
+char(9,58794).
+char(2,58795).
+char(c,58796).
+char(m,58797).
+char(9,58798).
+char(3,58799).
+char(2,58800).
+char(9,58801).
+char(m,58802).
+char(8,58803).
+char(2,58804).
+char(5,58805).
+char(2,58806).
+char(p,58807).
+char(o,58808).
+char(m,58809).
+char(o,58810).
+char(p,58811).
+char(9,58812).
+char(1,58813).
+char(2,58814).
+char(c,58815).
+char(c,58816).
+char(p,58817).
+char(o,58818).
+char(m,58819).
+char(o,58820).
+char(p,58821).
+char(o,58822).
+char(5,58823).
+char(5,58824).
+char(5,58825).
+char(7,58826).
+char(c,58827).
+char(c,58828).
+char(p,58829).
+char(8,58830).
+char(5,58831).
+char(1,58832).
+char(8,58833).
+char(c,58834).
+char(m,58835).
+char(2,58836).
+char(4,58837).
+char(1,58838).
+char(4,58839).
+char(p,58840).
+char(o,58841).
+char(m,58842).
+char(1,58843).
+char(2,58844).
+char(5,58845).
+char(5,58846).
+char(c,58847).
+char(c,58848).
+char(c,58849).
+char(m,58850).
+char(o,58851).
+char(5,58852).
+char(1,58853).
+char(2,58854).
+char(7,58855).
+char(m,58856).
+char(2,58857).
+char(4,58858).
+char(1,58859).
+char(1,58860).
+char(m,58861).
+char(2,58862).
+char(6,58863).
+char(6,58864).
+char(7,58865).
+char(m,58866).
+char(1,58867).
+char(0,58868).
+char(0,58869).
+char(9,58870).
+char(p,58871).
+char(8,58872).
+char(2,58873).
+char(4,58874).
+char(6,58875).
+char(m,58876).
+char(1,58877).
+char(8,58878).
+char(6,58879).
+char(4,58880).
+char(c,58881).
+char(p,58882).
+char(o,58883).
+char(o,58884).
+char(p,58885).
+char(8,58886).
+char(3,58887).
+char(3,58888).
+char(9,58889).
+char(m,58890).
+char(1,58891).
+char(0,58892).
+char(6,58893).
+char(0,58894).
+char(c,58895).
+char(p,58896).
+char(1,58897).
+char(7,58898).
+char(4,58899).
+char(8,58900).
+char(m,58901).
+char(o,58902).
+char(p,58903).
+char(5,58904).
+char(3,58905).
+char(8,58906).
+char(1,58907).
+char(m,58908).
+char(o,58909).
+char(m,58910).
+char(3,58911).
+char(9,58912).
+char(0,58913).
+char(3,58914).
+char(c,58915).
+char(c,58916).
+char(c,58917).
+char(p,58918).
+char(o,58919).
+char(o,58920).
+char(p,58921).
+char(9,58922).
+char(8,58923).
+char(2,58924).
+char(2,58925).
+char(c,58926).
+char(m,58927).
+char(o,58928).
+char(p,58929).
+char(5,58930).
+char(8,58931).
+char(0,58932).
+char(9,58933).
+char(c,58934).
+char(p,58935).
+char(o,58936).
+char(p,58937).
+char(o,58938).
+char(m,58939).
+char(o,58940).
+char(8,58941).
+char(2,58942).
+char(0,58943).
+char(0,58944).
+char(c,58945).
+char(c,58946).
+char(m,58947).
+char(8,58948).
+char(3,58949).
+char(9,58950).
+char(2,58951).
+char(c,58952).
+char(m,58953).
+char(6,58954).
+char(1,58955).
+char(7,58956).
+char(5,58957).
+char(m,58958).
+char(o,58959).
+char(m,58960).
+char(o,58961).
+char(p,58962).
+char(8,58963).
+char(2,58964).
+char(1,58965).
+char(2,58966).
+char(m,58967).
+char(4,58968).
+char(5,58969).
+char(0,58970).
+char(8,58971).
+char(c,58972).
+char(c,58973).
+char(c,58974).
+char(c,58975).
+char(m,58976).
+char(o,58977).
+char(8,58978).
+char(4,58979).
+char(8,58980).
+char(0,58981).
+char(c,58982).
+char(m,58983).
+char(6,58984).
+char(2,58985).
+char(2,58986).
+char(0,58987).
+char(c,58988).
+char(c,58989).
+char(c,58990).
+char(c,58991).
+char(m,58992).
+char(2,58993).
+char(0,58994).
+char(9,58995).
+char(1,58996).
+char(c,58997).
+char(c,58998).
+char(c,58999).
+char(m,59000).
+char(o,59001).
+char(p,59002).
+char(o,59003).
+char(p,59004).
+char(o,59005).
+char(m,59006).
+char(8,59007).
+char(0,59008).
+char(8,59009).
+char(0,59010).
+char(c,59011).
+char(p,59012).
+char(o,59013).
+char(p,59014).
+char(o,59015).
+char(m,59016).
+char(o,59017).
+char(o,59018).
+char(p,59019).
+char(3,59020).
+char(2,59021).
+char(1,59022).
+char(c,59023).
+char(m,59024).
+char(9,59025).
+char(8,59026).
+char(3,59027).
+char(3,59028).
+char(c,59029).
+char(c,59030).
+char(m,59031).
+char(o,59032).
+char(m,59033).
+char(o,59034).
+char(p,59035).
+char(o,59036).
+char(p,59037).
+char(4,59038).
+char(4,59039).
+char(9,59040).
+char(c,59041).
+char(c,59042).
+char(c,59043).
+char(p,59044).
+char(9,59045).
+char(5,59046).
+char(3,59047).
+char(7,59048).
+char(m,59049).
+char(o,59050).
+char(p,59051).
+char(o,59052).
+char(o,59053).
+char(m,59054).
+char(1,59055).
+char(0,59056).
+char(2,59057).
+char(9,59058).
+char(p,59059).
+char(4,59060).
+char(0,59061).
+char(6,59062).
+char(m,59063).
+char(o,59064).
+char(o,59065).
+char(m,59066).
+char(4,59067).
+char(4,59068).
+char(8,59069).
+char(p,59070).
+char(2,59071).
+char(7,59072).
+char(6,59073).
+char(8,59074).
+char(c,59075).
+char(c,59076).
+char(p,59077).
+char(o,59078).
+char(o,59079).
+char(p,59080).
+char(o,59081).
+char(m,59082).
+char(7,59083).
+char(0,59084).
+char(2,59085).
+char(2,59086).
+char(c,59087).
+char(p,59088).
+char(1,59089).
+char(3,59090).
+char(1,59091).
+char(0,59092).
+char(c,59093).
+char(m,59094).
+char(3,59095).
+char(7,59096).
+char(3,59097).
+char(8,59098).
+char(p,59099).
+char(o,59100).
+char(p,59101).
+char(o,59102).
+char(o,59103).
+char(1,59104).
+char(8,59105).
+char(5,59106).
+char(8,59107).
+char(p,59108).
+char(o,59109).
+char(o,59110).
+char(m,59111).
+char(o,59112).
+char(8,59113).
+char(9,59114).
+char(2,59115).
+char(c,59116).
+char(c,59117).
+char(c,59118).
+char(m,59119).
+char(o,59120).
+char(m,59121).
+char(o,59122).
+char(p,59123).
+char(2,59124).
+char(4,59125).
+char(0,59126).
+char(9,59127).
+char(p,59128).
+char(5,59129).
+char(7,59130).
+char(2,59131).
+char(5,59132).
+char(p,59133).
+char(2,59134).
+char(6,59135).
+char(2,59136).
+char(5,59137).
+char(p,59138).
+char(4,59139).
+char(8,59140).
+char(4,59141).
+char(8,59142).
+char(c,59143).
+char(p,59144).
+char(8,59145).
+char(0,59146).
+char(0,59147).
+char(3,59148).
+char(p,59149).
+char(o,59150).
+char(6,59151).
+char(4,59152).
+char(7,59153).
+char(4,59154).
+char(c,59155).
+char(c,59156).
+char(p,59157).
+char(5,59158).
+char(4,59159).
+char(9,59160).
+char(0,59161).
+char(c,59162).
+char(c,59163).
+char(c,59164).
+char(p,59165).
+char(o,59166).
+char(p,59167).
+char(o,59168).
+char(m,59169).
+char(4,59170).
+char(7,59171).
+char(3,59172).
+char(5,59173).
+char(c,59174).
+char(p,59175).
+char(3,59176).
+char(8,59177).
+char(5,59178).
+char(3,59179).
+char(c,59180).
+char(m,59181).
+char(5,59182).
+char(7,59183).
+char(5,59184).
+char(9,59185).
+char(c,59186).
+char(c,59187).
+char(p,59188).
+char(3,59189).
+char(8,59190).
+char(8,59191).
+char(1,59192).
+char(c,59193).
+char(c,59194).
+char(m,59195).
+char(o,59196).
+char(p,59197).
+char(o,59198).
+char(m,59199).
+char(o,59200).
+char(o,59201).
+char(m,59202).
+char(3,59203).
+char(8,59204).
+char(3,59205).
+char(2,59206).
+char(c,59207).
+char(p,59208).
+char(4,59209).
+char(6,59210).
+char(0,59211).
+char(3,59212).
+char(c,59213).
+char(p,59214).
+char(1,59215).
+char(9,59216).
+char(9,59217).
+char(8,59218).
+char(c,59219).
+char(c,59220).
+char(p,59221).
+char(o,59222).
+char(m,59223).
+char(o,59224).
+char(p,59225).
+char(3,59226).
+char(8,59227).
+char(1,59228).
+char(3,59229).
+char(c,59230).
+char(c,59231).
+char(p,59232).
+char(o,59233).
+char(m,59234).
+char(o,59235).
+char(m,59236).
+char(o,59237).
+char(p,59238).
+char(1,59239).
+char(3,59240).
+char(8,59241).
+char(2,59242).
+char(m,59243).
+char(o,59244).
+char(m,59245).
+char(3,59246).
+char(5,59247).
+char(0,59248).
+char(6,59249).
+char(m,59250).
+char(9,59251).
+char(9,59252).
+char(8,59253).
+char(9,59254).
+char(c,59255).
+char(p,59256).
+char(o,59257).
+char(p,59258).
+char(o,59259).
+char(p,59260).
+char(o,59261).
+char(p,59262).
+char(o,59263).
+char(5,59264).
+char(2,59265).
+char(7,59266).
+char(9,59267).
+char(c,59268).
+char(p,59269).
+char(3,59270).
+char(5,59271).
+char(6,59272).
+char(0,59273).
+char(m,59274).
+char(6,59275).
+char(2,59276).
+char(4,59277).
+char(1,59278).
+char(c,59279).
+char(c,59280).
+char(c,59281).
+char(m,59282).
+char(8,59283).
+char(1,59284).
+char(0,59285).
+char(4,59286).
+char(c,59287).
+char(c,59288).
+char(c,59289).
+char(p,59290).
+char(8,59291).
+char(8,59292).
+char(3,59293).
+char(2,59294).
+char(m,59295).
+char(7,59296).
+char(7,59297).
+char(3,59298).
+char(6,59299).
+char(c,59300).
+char(c,59301).
+char(c,59302).
+char(p,59303).
+char(4,59304).
+char(3,59305).
+char(9,59306).
+char(2,59307).
+char(m,59308).
+char(5,59309).
+char(4,59310).
+char(9,59311).
+char(6,59312).
+char(c,59313).
+char(c,59314).
+char(m,59315).
+char(o,59316).
+char(m,59317).
+char(o,59318).
+char(m,59319).
+char(2,59320).
+char(6,59321).
+char(9,59322).
+char(8,59323).
+char(c,59324).
+char(p,59325).
+char(o,59326).
+char(p,59327).
+char(o,59328).
+char(m,59329).
+char(5,59330).
+char(5,59331).
+char(2,59332).
+char(p,59333).
+char(o,59334).
+char(o,59335).
+char(o,59336).
+char(p,59337).
+char(8,59338).
+char(8,59339).
+char(3,59340).
+char(0,59341).
+char(c,59342).
+char(c,59343).
+char(c,59344).
+char(c,59345).
+char(p,59346).
+char(o,59347).
+char(o,59348).
+char(p,59349).
+char(o,59350).
+char(4,59351).
+char(8,59352).
+char(1,59353).
+char(2,59354).
+char(p,59355).
+char(9,59356).
+char(7,59357).
+char(6,59358).
+char(6,59359).
+char(c,59360).
+char(c,59361).
+char(p,59362).
+char(2,59363).
+char(3,59364).
+char(2,59365).
+char(3,59366).
+char(c,59367).
+char(p,59368).
+char(o,59369).
+char(p,59370).
+char(5,59371).
+char(4,59372).
+char(5,59373).
+char(c,59374).
+char(c,59375).
+char(c,59376).
+char(p,59377).
+char(o,59378).
+char(p,59379).
+char(4,59380).
+char(4,59381).
+char(6,59382).
+char(1,59383).
+char(c,59384).
+char(c,59385).
+char(c,59386).
+char(c,59387).
+char(c,59388).
+char(m,59389).
+char(o,59390).
+char(m,59391).
+char(8,59392).
+char(2,59393).
+char(1,59394).
+char(5,59395).
+char(c,59396).
+char(c,59397).
+char(m,59398).
+char(9,59399).
+char(9,59400).
+char(9,59401).
+char(3,59402).
+char(c,59403).
+char(c,59404).
+char(m,59405).
+char(8,59406).
+char(1,59407).
+char(6,59408).
+char(6,59409).
+char(c,59410).
+char(p,59411).
+char(6,59412).
+char(8,59413).
+char(0,59414).
+char(1,59415).
+char(c,59416).
+char(c,59417).
+char(c,59418).
+char(p,59419).
+char(o,59420).
+char(p,59421).
+char(o,59422).
+char(p,59423).
+char(o,59424).
+char(m,59425).
+char(o,59426).
+char(m,59427).
+char(6,59428).
+char(6,59429).
+char(8,59430).
+char(4,59431).
+char(c,59432).
+char(c,59433).
+char(c,59434).
+char(p,59435).
+char(o,59436).
+char(o,59437).
+char(8,59438).
+char(9,59439).
+char(6,59440).
+char(c,59441).
+char(m,59442).
+char(o,59443).
+char(1,59444).
+char(5,59445).
+char(1,59446).
+char(4,59447).
+char(p,59448).
+char(6,59449).
+char(0,59450).
+char(5,59451).
+char(4,59452).
+char(c,59453).
+char(c,59454).
+char(p,59455).
+char(9,59456).
+char(0,59457).
+char(3,59458).
+char(4,59459).
+char(m,59460).
+char(o,59461).
+char(5,59462).
+char(3,59463).
+char(7,59464).
+char(9,59465).
+char(c,59466).
+char(c,59467).
+char(c,59468).
+char(m,59469).
+char(o,59470).
+char(m,59471).
+char(2,59472).
+char(2,59473).
+char(3,59474).
+char(6,59475).
+char(p,59476).
+char(o,59477).
+char(p,59478).
+char(4,59479).
+char(9,59480).
+char(0,59481).
+char(1,59482).
+char(c,59483).
+char(m,59484).
+char(o,59485).
+char(2,59486).
+char(2,59487).
+char(4,59488).
+char(0,59489).
+char(c,59490).
+char(m,59491).
+char(9,59492).
+char(4,59493).
+char(9,59494).
+char(0,59495).
+char(c,59496).
+char(c,59497).
+char(c,59498).
+char(p,59499).
+char(o,59500).
+char(6,59501).
+char(3,59502).
+char(1,59503).
+char(3,59504).
+char(m,59505).
+char(2,59506).
+char(6,59507).
+char(0,59508).
+char(7,59509).
+char(c,59510).
+char(c,59511).
+char(p,59512).
+char(1,59513).
+char(8,59514).
+char(7,59515).
+char(7,59516).
+char(p,59517).
+char(o,59518).
+char(p,59519).
+char(o,59520).
+char(o,59521).
+char(m,59522).
+char(o,59523).
+char(m,59524).
+char(o,59525).
+char(m,59526).
+char(o,59527).
+char(6,59528).
+char(3,59529).
+char(4,59530).
+char(1,59531).
+char(c,59532).
+char(p,59533).
+char(o,59534).
+char(o,59535).
+char(o,59536).
+char(o,59537).
+char(p,59538).
+char(o,59539).
+char(m,59540).
+char(o,59541).
+char(m,59542).
+char(o,59543).
+char(m,59544).
+char(o,59545).
+char(9,59546).
+char(5,59547).
+char(5,59548).
+char(1,59549).
+char(p,59550).
+char(o,59551).
+char(p,59552).
+char(o,59553).
+char(p,59554).
+char(o,59555).
+char(p,59556).
+char(3,59557).
+char(8,59558).
+char(8,59559).
+char(8,59560).
+char(p,59561).
+char(o,59562).
+char(p,59563).
+char(o,59564).
+char(m,59565).
+char(2,59566).
+char(0,59567).
+char(4,59568).
+char(8,59569).
+char(p,59570).
+char(9,59571).
+char(3,59572).
+char(8,59573).
+char(6,59574).
+char(c,59575).
+char(p,59576).
+char(7,59577).
+char(8,59578).
+char(2,59579).
+char(9,59580).
+char(m,59581).
+char(5,59582).
+char(9,59583).
+char(1,59584).
+char(6,59585).
+char(c,59586).
+char(c,59587).
+char(c,59588).
+char(p,59589).
+char(o,59590).
+char(o,59591).
+char(o,59592).
+char(8,59593).
+char(0,59594).
+char(1,59595).
+char(7,59596).
+char(p,59597).
+char(7,59598).
+char(1,59599).
+char(1,59600).
+char(2,59601).
+char(c,59602).
+char(p,59603).
+char(o,59604).
+char(o,59605).
+char(p,59606).
+char(5,59607).
+char(2,59608).
+char(0,59609).
+char(8,59610).
+char(c,59611).
+char(p,59612).
+char(o,59613).
+char(p,59614).
+char(8,59615).
+char(5,59616).
+char(4,59617).
+char(6,59618).
+char(p,59619).
+char(7,59620).
+char(2,59621).
+char(1,59622).
+char(0,59623).
+char(m,59624).
+char(8,59625).
+char(7,59626).
+char(5,59627).
+char(2,59628).
+char(c,59629).
+char(p,59630).
+char(5,59631).
+char(7,59632).
+char(2,59633).
+char(2,59634).
+char(c,59635).
+char(p,59636).
+char(6,59637).
+char(0,59638).
+char(8,59639).
+char(6,59640).
+char(p,59641).
+char(4,59642).
+char(4,59643).
+char(1,59644).
+char(5,59645).
+char(m,59646).
+char(3,59647).
+char(7,59648).
+char(9,59649).
+char(7,59650).
+char(c,59651).
+char(c,59652).
+char(p,59653).
+char(9,59654).
+char(1,59655).
+char(8,59656).
+char(3,59657).
+char(p,59658).
+char(o,59659).
+char(o,59660).
+char(p,59661).
+char(8,59662).
+char(0,59663).
+char(4,59664).
+char(2,59665).
+char(p,59666).
+char(o,59667).
+char(m,59668).
+char(o,59669).
+char(3,59670).
+char(9,59671).
+char(5,59672).
+char(1,59673).
+char(m,59674).
+char(o,59675).
+char(p,59676).
+char(9,59677).
+char(1,59678).
+char(7,59679).
+char(2,59680).
+char(c,59681).
+char(m,59682).
+char(o,59683).
+char(p,59684).
+char(7,59685).
+char(2,59686).
+char(9,59687).
+char(1,59688).
+char(p,59689).
+char(o,59690).
+char(p,59691).
+char(o,59692).
+char(o,59693).
+char(p,59694).
+char(5,59695).
+char(3,59696).
+char(4,59697).
+char(7,59698).
+char(c,59699).
+char(c,59700).
+char(c,59701).
+char(c,59702).
+char(c,59703).
+char(c,59704).
+char(c,59705).
+char(c,59706).
+char(p,59707).
+char(o,59708).
+char(8,59709).
+char(4,59710).
+char(1,59711).
+char(0,59712).
+char(m,59713).
+char(2,59714).
+char(9,59715).
+char(9,59716).
+char(0,59717).
+char(p,59718).
+char(4,59719).
+char(3,59720).
+char(1,59721).
+char(3,59722).
+char(m,59723).
+char(3,59724).
+char(9,59725).
+char(4,59726).
+char(9,59727).
+char(c,59728).
+char(m,59729).
+char(5,59730).
+char(8,59731).
+char(3,59732).
+char(2,59733).
+char(m,59734).
+char(1,59735).
+char(3,59736).
+char(2,59737).
+char(1,59738).
+char(c,59739).
+char(p,59740).
+char(o,59741).
+char(p,59742).
+char(o,59743).
+char(o,59744).
+char(m,59745).
+char(o,59746).
+char(p,59747).
+char(4,59748).
+char(9,59749).
+char(3,59750).
+char(3,59751).
+char(c,59752).
+char(m,59753).
+char(1,59754).
+char(6,59755).
+char(2,59756).
+char(0,59757).
+char(m,59758).
+char(6,59759).
+char(8,59760).
+char(2,59761).
+char(0,59762).
+char(m,59763).
+char(o,59764).
+char(p,59765).
+char(8,59766).
+char(1,59767).
+char(5,59768).
+char(7,59769).
+char(c,59770).
+char(p,59771).
+char(9,59772).
+char(0,59773).
+char(1,59774).
+char(p,59775).
+char(o,59776).
+char(o,59777).
+char(o,59778).
+char(p,59779).
+char(o,59780).
+char(p,59781).
+char(o,59782).
+char(p,59783).
+char(o,59784).
+char(p,59785).
+char(o,59786).
+char(o,59787).
+char(8,59788).
+char(6,59789).
+char(9,59790).
+char(2,59791).
+char(c,59792).
+char(p,59793).
+char(5,59794).
+char(4,59795).
+char(1,59796).
+char(2,59797).
+char(m,59798).
+char(o,59799).
+char(o,59800).
+char(m,59801).
+char(o,59802).
+char(p,59803).
+char(7,59804).
+char(0,59805).
+char(8,59806).
+char(c,59807).
+char(c,59808).
+char(m,59809).
+char(o,59810).
+char(m,59811).
+char(o,59812).
+char(o,59813).
+char(p,59814).
+char(6,59815).
+char(6,59816).
+char(1,59817).
+char(3,59818).
+char(c,59819).
+char(c,59820).
+char(p,59821).
+char(1,59822).
+char(2,59823).
+char(5,59824).
+char(3,59825).
+char(c,59826).
+char(p,59827).
+char(o,59828).
+char(o,59829).
+char(o,59830).
+char(o,59831).
+char(p,59832).
+char(9,59833).
+char(7,59834).
+char(5,59835).
+char(6,59836).
+char(m,59837).
+char(8,59838).
+char(4,59839).
+char(7,59840).
+char(9,59841).
+char(c,59842).
+char(p,59843).
+char(4,59844).
+char(8,59845).
+char(5,59846).
+char(2,59847).
+char(p,59848).
+char(4,59849).
+char(3,59850).
+char(8,59851).
+char(5,59852).
+char(c,59853).
+char(c,59854).
+char(p,59855).
+char(o,59856).
+char(4,59857).
+char(5,59858).
+char(4,59859).
+char(1,59860).
+char(c,59861).
+char(p,59862).
+char(o,59863).
+char(p,59864).
+char(o,59865).
+char(1,59866).
+char(9,59867).
+char(0,59868).
+char(4,59869).
+char(c,59870).
+char(m,59871).
+char(7,59872).
+char(6,59873).
+char(7,59874).
+char(6,59875).
+char(c,59876).
+char(c,59877).
+char(p,59878).
+char(3,59879).
+char(2,59880).
+char(2,59881).
+char(0,59882).
+char(c,59883).
+char(c,59884).
+char(p,59885).
+char(o,59886).
+char(p,59887).
+char(4,59888).
+char(5,59889).
+char(7,59890).
+char(3,59891).
+char(p,59892).
+char(o,59893).
+char(p,59894).
+char(o,59895).
+char(o,59896).
+char(m,59897).
+char(o,59898).
+char(m,59899).
+char(o,59900).
+char(p,59901).
+char(o,59902).
+char(o,59903).
+char(p,59904).
+char(o,59905).
+char(o,59906).
+char(m,59907).
+char(o,59908).
+char(1,59909).
+char(8,59910).
+char(4,59911).
+char(4,59912).
+char(c,59913).
+char(p,59914).
+char(o,59915).
+char(m,59916).
+char(o,59917).
+char(o,59918).
+char(p,59919).
+char(6,59920).
+char(2,59921).
+char(8,59922).
+char(4,59923).
+char(m,59924).
+char(3,59925).
+char(2,59926).
+char(0,59927).
+char(6,59928).
+char(c,59929).
+char(c,59930).
+char(p,59931).
+char(2,59932).
+char(7,59933).
+char(5,59934).
+char(2,59935).
+char(m,59936).
+char(9,59937).
+char(9,59938).
+char(4,59939).
+char(8,59940).
+char(c,59941).
+char(m,59942).
+char(o,59943).
+char(9,59944).
+char(7,59945).
+char(6,59946).
+char(c,59947).
+char(m,59948).
+char(o,59949).
+char(p,59950).
+char(1,59951).
+char(5,59952).
+char(7,59953).
+char(4,59954).
+char(c,59955).
+char(m,59956).
+char(o,59957).
+char(p,59958).
+char(3,59959).
+char(5,59960).
+char(0,59961).
+char(0,59962).
+char(p,59963).
+char(o,59964).
+char(p,59965).
+char(8,59966).
+char(3,59967).
+char(2,59968).
+char(8,59969).
+char(c,59970).
+char(c,59971).
+char(c,59972).
+char(c,59973).
+char(m,59974).
+char(o,59975).
+char(m,59976).
+char(o,59977).
+char(9,59978).
+char(3,59979).
+char(0,59980).
+char(8,59981).
+char(c,59982).
+char(c,59983).
+char(c,59984).
+char(c,59985).
+char(p,59986).
+char(4,59987).
+char(3,59988).
+char(1,59989).
+char(0,59990).
+char(p,59991).
+char(o,59992).
+char(o,59993).
+char(6,59994).
+char(1,59995).
+char(8,59996).
+char(7,59997).
+char(c,59998).
+char(c,59999).
+char(m,60000).
+char(9,60001).
+char(0,60002).
+char(7,60003).
+char(4,60004).
+char(m,60005).
+char(8,60006).
+char(1,60007).
+char(4,60008).
+char(c,60009).
+char(p,60010).
+char(o,60011).
+char(p,60012).
+char(6,60013).
+char(7,60014).
+char(3,60015).
+char(7,60016).
+char(c,60017).
+char(c,60018).
+char(m,60019).
+char(o,60020).
+char(o,60021).
+char(2,60022).
+char(3,60023).
+char(7,60024).
+char(2,60025).
+char(c,60026).
+char(m,60027).
+char(5,60028).
+char(7,60029).
+char(5,60030).
+char(8,60031).
+char(c,60032).
+char(c,60033).
+char(p,60034).
+char(5,60035).
+char(9,60036).
+char(7,60037).
+char(3,60038).
+char(p,60039).
+char(5,60040).
+char(4,60041).
+char(4,60042).
+char(p,60043).
+char(o,60044).
+char(o,60045).
+char(p,60046).
+char(1,60047).
+char(5,60048).
+char(4,60049).
+char(c,60050).
+char(m,60051).
+char(o,60052).
+char(p,60053).
+char(4,60054).
+char(2,60055).
+char(9,60056).
+char(2,60057).
+char(c,60058).
+char(m,60059).
+char(3,60060).
+char(0,60061).
+char(4,60062).
+char(4,60063).
+char(m,60064).
+char(8,60065).
+char(2,60066).
+char(9,60067).
+char(4,60068).
+char(p,60069).
+char(o,60070).
+char(o,60071).
+char(p,60072).
+char(7,60073).
+char(1,60074).
+char(8,60075).
+char(3,60076).
+char(m,60077).
+char(o,60078).
+char(4,60079).
+char(3,60080).
+char(6,60081).
+char(5,60082).
+char(c,60083).
+char(c,60084).
+char(c,60085).
+char(m,60086).
+char(1,60087).
+char(5,60088).
+char(1,60089).
+char(4,60090).
+char(c,60091).
+char(m,60092).
+char(o,60093).
+char(p,60094).
+char(3,60095).
+char(3,60096).
+char(4,60097).
+char(p,60098).
+char(o,60099).
+char(o,60100).
+char(m,60101).
+char(8,60102).
+char(3,60103).
+char(6,60104).
+char(p,60105).
+char(4,60106).
+char(2,60107).
+char(0,60108).
+char(7,60109).
+char(p,60110).
+char(o,60111).
+char(m,60112).
+char(9,60113).
+char(4,60114).
+char(4,60115).
+char(9,60116).
+char(c,60117).
+char(c,60118).
+char(c,60119).
+char(p,60120).
+char(2,60121).
+char(7,60122).
+char(1,60123).
+char(6,60124).
+char(m,60125).
+char(o,60126).
+char(9,60127).
+char(6,60128).
+char(0,60129).
+char(4,60130).
+char(c,60131).
+char(c,60132).
+char(c,60133).
+char(c,60134).
+char(p,60135).
+char(o,60136).
+char(m,60137).
+char(3,60138).
+char(7,60139).
+char(4,60140).
+char(1,60141).
+char(m,60142).
+char(o,60143).
+char(m,60144).
+char(o,60145).
+char(m,60146).
+char(8,60147).
+char(6,60148).
+char(9,60149).
+char(2,60150).
+char(c,60151).
+char(c,60152).
+char(c,60153).
+char(m,60154).
+char(6,60155).
+char(2,60156).
+char(6,60157).
+char(9,60158).
+char(c,60159).
+char(m,60160).
+char(3,60161).
+char(4,60162).
+char(7,60163).
+char(2,60164).
+char(c,60165).
+char(c,60166).
+char(m,60167).
+char(o,60168).
+char(3,60169).
+char(6,60170).
+char(4,60171).
+char(6,60172).
+char(c,60173).
+char(p,60174).
+char(5,60175).
+char(1,60176).
+char(1,60177).
+char(7,60178).
+char(c,60179).
+char(m,60180).
+char(3,60181).
+char(5,60182).
+char(7,60183).
+char(c,60184).
+char(m,60185).
+char(7,60186).
+char(4,60187).
+char(9,60188).
+char(0,60189).
+char(c,60190).
+char(c,60191).
+char(c,60192).
+char(p,60193).
+char(9,60194).
+char(9,60195).
+char(9,60196).
+char(c,60197).
+char(p,60198).
+char(o,60199).
+char(m,60200).
+char(2,60201).
+char(3,60202).
+char(9,60203).
+char(4,60204).
+char(m,60205).
+char(3,60206).
+char(0,60207).
+char(9,60208).
+char(1,60209).
+char(c,60210).
+char(p,60211).
+char(o,60212).
+char(5,60213).
+char(8,60214).
+char(6,60215).
+char(7,60216).
+char(c,60217).
+char(m,60218).
+char(8,60219).
+char(7,60220).
+char(9,60221).
+char(3,60222).
+char(c,60223).
+char(c,60224).
+char(c,60225).
+char(c,60226).
+char(p,60227).
+char(o,60228).
+char(m,60229).
+char(o,60230).
+char(m,60231).
+char(o,60232).
+char(4,60233).
+char(9,60234).
+char(7,60235).
+char(9,60236).
+char(p,60237).
+char(o,60238).
+char(m,60239).
+char(o,60240).
+char(p,60241).
+char(1,60242).
+char(9,60243).
+char(0,60244).
+char(7,60245).
+char(c,60246).
+char(c,60247).
+char(c,60248).
+char(c,60249).
+char(m,60250).
+char(4,60251).
+char(2,60252).
+char(9,60253).
+char(5,60254).
+char(m,60255).
+char(2,60256).
+char(8,60257).
+char(2,60258).
+char(9,60259).
+char(c,60260).
+char(c,60261).
+char(p,60262).
+char(6,60263).
+char(2,60264).
+char(1,60265).
+char(6,60266).
+char(c,60267).
+char(p,60268).
+char(o,60269).
+char(p,60270).
+char(8,60271).
+char(4,60272).
+char(3,60273).
+char(1,60274).
+char(m,60275).
+char(6,60276).
+char(5,60277).
+char(2,60278).
+char(9,60279).
+char(c,60280).
+char(c,60281).
+char(c,60282).
+char(c,60283).
+char(p,60284).
+char(5,60285).
+char(0,60286).
+char(9,60287).
+char(7,60288).
+char(m,60289).
+char(o,60290).
+char(m,60291).
+char(4,60292).
+char(0,60293).
+char(3,60294).
+char(7,60295).
+char(c,60296).
+char(m,60297).
+char(o,60298).
+char(o,60299).
+char(p,60300).
+char(3,60301).
+char(7,60302).
+char(5,60303).
+char(5,60304).
+char(m,60305).
+char(o,60306).
+char(9,60307).
+char(4,60308).
+char(5,60309).
+char(9,60310).
+char(c,60311).
+char(p,60312).
+char(o,60313).
+char(p,60314).
+char(o,60315).
+char(m,60316).
+char(8,60317).
+char(4,60318).
+char(2,60319).
+char(2,60320).
+char(c,60321).
+char(c,60322).
+char(p,60323).
+char(4,60324).
+char(3,60325).
+char(4,60326).
+char(5,60327).
+char(c,60328).
+char(c,60329).
+char(m,60330).
+char(o,60331).
+char(m,60332).
+char(7,60333).
+char(1,60334).
+char(0,60335).
+char(6,60336).
+char(c,60337).
+char(c,60338).
+char(c,60339).
+char(m,60340).
+char(4,60341).
+char(2,60342).
+char(8,60343).
+char(3,60344).
+char(m,60345).
+char(o,60346).
+char(1,60347).
+char(5,60348).
+char(9,60349).
+char(0,60350).
+char(m,60351).
+char(9,60352).
+char(5,60353).
+char(8,60354).
+char(8,60355).
+char(c,60356).
+char(c,60357).
+char(c,60358).
+char(c,60359).
+char(c,60360).
+char(m,60361).
+char(o,60362).
+char(m,60363).
+char(o,60364).
+char(m,60365).
+char(o,60366).
+char(8,60367).
+char(2,60368).
+char(1,60369).
+char(4,60370).
+char(m,60371).
+char(o,60372).
+char(m,60373).
+char(6,60374).
+char(1,60375).
+char(8,60376).
+char(4,60377).
+char(p,60378).
+char(o,60379).
+char(m,60380).
+char(o,60381).
+char(7,60382).
+char(8,60383).
+char(4,60384).
+char(8,60385).
+char(c,60386).
+char(c,60387).
+char(c,60388).
+char(p,60389).
+char(o,60390).
+char(o,60391).
+char(o,60392).
+char(m,60393).
+char(4,60394).
+char(9,60395).
+char(2,60396).
+char(4,60397).
+char(c,60398).
+char(m,60399).
+char(o,60400).
+char(9,60401).
+char(4,60402).
+char(7,60403).
+char(4,60404).
+char(c,60405).
+char(m,60406).
+char(o,60407).
+char(p,60408).
+char(9,60409).
+char(7,60410).
+char(m,60411).
+char(o,60412).
+char(m,60413).
+char(6,60414).
+char(1,60415).
+char(6,60416).
+char(7,60417).
+char(c,60418).
+char(m,60419).
+char(3,60420).
+char(4,60421).
+char(0,60422).
+char(2,60423).
+char(p,60424).
+char(9,60425).
+char(4,60426).
+char(4,60427).
+char(1,60428).
+char(c,60429).
+char(p,60430).
+char(o,60431).
+char(p,60432).
+char(o,60433).
+char(6,60434).
+char(5,60435).
+char(6,60436).
+char(3,60437).
+char(m,60438).
+char(9,60439).
+char(2,60440).
+char(3,60441).
+char(6,60442).
+char(c,60443).
+char(m,60444).
+char(o,60445).
+char(o,60446).
+char(5,60447).
+char(3,60448).
+char(1,60449).
+char(5,60450).
+char(c,60451).
+char(m,60452).
+char(5,60453).
+char(0,60454).
+char(3,60455).
+char(5,60456).
+char(p,60457).
+char(6,60458).
+char(0,60459).
+char(9,60460).
+char(c,60461).
+char(c,60462).
+char(p,60463).
+char(o,60464).
+char(p,60465).
+char(6,60466).
+char(5,60467).
+char(1,60468).
+char(2,60469).
+char(c,60470).
+char(m,60471).
+char(o,60472).
+char(p,60473).
+char(o,60474).
+char(m,60475).
+char(o,60476).
+char(p,60477).
+char(o,60478).
+char(m,60479).
+char(6,60480).
+char(7,60481).
+char(3,60482).
+char(c,60483).
+char(c,60484).
+char(c,60485).
+char(c,60486).
+char(m,60487).
+char(o,60488).
+char(p,60489).
+char(1,60490).
+char(5,60491).
+char(5,60492).
+char(1,60493).
+char(c,60494).
+char(m,60495).
+char(2,60496).
+char(5,60497).
+char(2,60498).
+char(5,60499).
+char(c,60500).
+char(c,60501).
+char(m,60502).
+char(9,60503).
+char(3,60504).
+char(7,60505).
+char(m,60506).
+char(2,60507).
+char(6,60508).
+char(1,60509).
+char(8,60510).
+char(m,60511).
+char(o,60512).
+char(p,60513).
+char(4,60514).
+char(1,60515).
+char(1,60516).
+char(4,60517).
+char(p,60518).
+char(1,60519).
+char(1,60520).
+char(5,60521).
+char(7,60522).
+char(p,60523).
+char(7,60524).
+char(5,60525).
+char(2,60526).
+char(p,60527).
+char(9,60528).
+char(8,60529).
+char(4,60530).
+char(5,60531).
+char(m,60532).
+char(9,60533).
+char(6,60534).
+char(6,60535).
+char(p,60536).
+char(o,60537).
+char(p,60538).
+char(9,60539).
+char(3,60540).
+char(1,60541).
+char(2,60542).
+char(c,60543).
+char(c,60544).
+char(p,60545).
+char(3,60546).
+char(3,60547).
+char(8,60548).
+char(4,60549).
+char(p,60550).
+char(3,60551).
+char(2,60552).
+char(0,60553).
+char(1,60554).
+char(m,60555).
+char(6,60556).
+char(4,60557).
+char(6,60558).
+char(7,60559).
+char(p,60560).
+char(9,60561).
+char(8,60562).
+char(4,60563).
+char(4,60564).
+char(m,60565).
+char(o,60566).
+char(m,60567).
+char(o,60568).
+char(m,60569).
+char(o,60570).
+char(p,60571).
+char(o,60572).
+char(9,60573).
+char(8,60574).
+char(8,60575).
+char(m,60576).
+char(o,60577).
+char(m,60578).
+char(o,60579).
+char(8,60580).
+char(0,60581).
+char(5,60582).
+char(5,60583).
+char(m,60584).
+char(o,60585).
+char(p,60586).
+char(4,60587).
+char(3,60588).
+char(2,60589).
+char(1,60590).
+char(c,60591).
+char(m,60592).
+char(3,60593).
+char(3,60594).
+char(0,60595).
+char(2,60596).
+char(c,60597).
+char(p,60598).
+char(4,60599).
+char(6,60600).
+char(8,60601).
+char(2,60602).
+char(m,60603).
+char(5,60604).
+char(1,60605).
+char(5,60606).
+char(6,60607).
+char(c,60608).
+char(c,60609).
+char(m,60610).
+char(o,60611).
+char(m,60612).
+char(8,60613).
+char(6,60614).
+char(8,60615).
+char(5,60616).
+char(m,60617).
+char(6,60618).
+char(6,60619).
+char(8,60620).
+char(0,60621).
+char(c,60622).
+char(m,60623).
+char(1,60624).
+char(9,60625).
+char(7,60626).
+char(1,60627).
+char(m,60628).
+char(7,60629).
+char(1,60630).
+char(3,60631).
+char(8,60632).
+char(m,60633).
+char(1,60634).
+char(7,60635).
+char(9,60636).
+char(m,60637).
+char(6,60638).
+char(4,60639).
+char(9,60640).
+char(2,60641).
+char(c,60642).
+char(m,60643).
+char(8,60644).
+char(7,60645).
+char(4,60646).
+char(8,60647).
+char(m,60648).
+char(o,60649).
+char(m,60650).
+char(4,60651).
+char(2,60652).
+char(1,60653).
+char(6,60654).
+char(p,60655).
+char(8,60656).
+char(7,60657).
+char(7,60658).
+char(9,60659).
+char(c,60660).
+char(c,60661).
+char(p,60662).
+char(9,60663).
+char(5,60664).
+char(9,60665).
+char(0,60666).
+char(c,60667).
+char(c,60668).
+char(p,60669).
+char(o,60670).
+char(m,60671).
+char(8,60672).
+char(2,60673).
+char(8,60674).
+char(1,60675).
+char(p,60676).
+char(o,60677).
+char(p,60678).
+char(o,60679).
+char(3,60680).
+char(9,60681).
+char(1,60682).
+char(4,60683).
+char(c,60684).
+char(c,60685).
+char(c,60686).
+char(c,60687).
+char(c,60688).
+char(c,60689).
+char(m,60690).
+char(8,60691).
+char(9,60692).
+char(2,60693).
+char(c,60694).
+char(c,60695).
+char(c,60696).
+char(m,60697).
+char(o,60698).
+char(o,60699).
+char(p,60700).
+char(o,60701).
+char(o,60702).
+char(m,60703).
+char(7,60704).
+char(3,60705).
+char(2,60706).
+char(4,60707).
+char(c,60708).
+char(c,60709).
+char(c,60710).
+char(m,60711).
+char(6,60712).
+char(9,60713).
+char(4,60714).
+char(3,60715).
+char(m,60716).
+char(3,60717).
+char(0,60718).
+char(6,60719).
+char(1,60720).
+char(m,60721).
+char(o,60722).
+char(p,60723).
+char(4,60724).
+char(4,60725).
+char(1,60726).
+char(3,60727).
+char(c,60728).
+char(m,60729).
+char(3,60730).
+char(4,60731).
+char(1,60732).
+char(2,60733).
+char(p,60734).
+char(o,60735).
+char(p,60736).
+char(o,60737).
+char(9,60738).
+char(0,60739).
+char(7,60740).
+char(1,60741).
+char(p,60742).
+char(1,60743).
+char(3,60744).
+char(4,60745).
+char(6,60746).
+char(c,60747).
+char(m,60748).
+char(4,60749).
+char(7,60750).
+char(7,60751).
+char(9,60752).
+char(p,60753).
+char(o,60754).
+char(m,60755).
+char(6,60756).
+char(8,60757).
+char(8,60758).
+char(c,60759).
+char(c,60760).
+char(p,60761).
+char(o,60762).
+char(p,60763).
+char(1,60764).
+char(6,60765).
+char(5,60766).
+char(4,60767).
+char(c,60768).
+char(p,60769).
+char(2,60770).
+char(7,60771).
+char(3,60772).
+char(8,60773).
+char(m,60774).
+char(5,60775).
+char(2,60776).
+char(7,60777).
+char(6,60778).
+char(c,60779).
+char(m,60780).
+char(2,60781).
+char(4,60782).
+char(9,60783).
+char(6,60784).
+char(m,60785).
+char(8,60786).
+char(8,60787).
+char(6,60788).
+char(c,60789).
+char(c,60790).
+char(p,60791).
+char(1,60792).
+char(5,60793).
+char(4,60794).
+char(4,60795).
+char(c,60796).
+char(c,60797).
+char(p,60798).
+char(2,60799).
+char(6,60800).
+char(7,60801).
+char(6,60802).
+char(m,60803).
+char(2,60804).
+char(9,60805).
+char(1,60806).
+char(8,60807).
+char(c,60808).
+char(m,60809).
+char(2,60810).
+char(3,60811).
+char(1,60812).
+char(6,60813).
+char(c,60814).
+char(p,60815).
+char(8,60816).
+char(4,60817).
+char(3,60818).
+char(9,60819).
+char(p,60820).
+char(o,60821).
+char(p,60822).
+char(o,60823).
+char(9,60824).
+char(4,60825).
+char(5,60826).
+char(8,60827).
+char(c,60828).
+char(p,60829).
+char(o,60830).
+char(m,60831).
+char(4,60832).
+char(1,60833).
+char(4,60834).
+char(6,60835).
+char(c,60836).
+char(p,60837).
+char(5,60838).
+char(8,60839).
+char(9,60840).
+char(3,60841).
+char(c,60842).
+char(m,60843).
+char(1,60844).
+char(3,60845).
+char(3,60846).
+char(3,60847).
+char(c,60848).
+char(m,60849).
+char(o,60850).
+char(m,60851).
+char(6,60852).
+char(1,60853).
+char(7,60854).
+char(3,60855).
+char(c,60856).
+char(c,60857).
+char(p,60858).
+char(o,60859).
+char(6,60860).
+char(3,60861).
+char(4,60862).
+char(1,60863).
+char(m,60864).
+char(o,60865).
+char(o,60866).
+char(p,60867).
+char(o,60868).
+char(m,60869).
+char(2,60870).
+char(5,60871).
+char(0,60872).
+char(1,60873).
+char(c,60874).
+char(m,60875).
+char(o,60876).
+char(p,60877).
+char(2,60878).
+char(0,60879).
+char(9,60880).
+char(4,60881).
+char(p,60882).
+char(5,60883).
+char(7,60884).
+char(2,60885).
+char(3,60886).
+char(c,60887).
+char(c,60888).
+char(m,60889).
+char(o,60890).
+char(p,60891).
+char(o,60892).
+char(m,60893).
+char(9,60894).
+char(1,60895).
+char(2,60896).
+char(9,60897).
+char(c,60898).
+char(c,60899).
+char(c,60900).
+char(p,60901).
+char(o,60902).
+char(p,60903).
+char(o,60904).
+char(p,60905).
+char(o,60906).
+char(m,60907).
+char(1,60908).
+char(7,60909).
+char(3,60910).
+char(2,60911).
+char(c,60912).
+char(c,60913).
+char(m,60914).
+char(2,60915).
+char(2,60916).
+char(6,60917).
+char(0,60918).
+char(c,60919).
+char(p,60920).
+char(7,60921).
+char(7,60922).
+char(3,60923).
+char(4,60924).
+char(c,60925).
+char(c,60926).
+char(c,60927).
+char(c,60928).
+char(c,60929).
+char(c,60930).
+char(c,60931).
+char(m,60932).
+char(6,60933).
+char(9,60934).
+char(9,60935).
+char(p,60936).
+char(o,60937).
+char(p,60938).
+char(3,60939).
+char(2,60940).
+char(4,60941).
+char(4,60942).
+char(c,60943).
+char(c,60944).
+char(c,60945).
+char(m,60946).
+char(o,60947).
+char(3,60948).
+char(2,60949).
+char(3,60950).
+char(2,60951).
+char(c,60952).
+char(p,60953).
+char(4,60954).
+char(0,60955).
+char(6,60956).
+char(2,60957).
+char(p,60958).
+char(o,60959).
+char(p,60960).
+char(1,60961).
+char(4,60962).
+char(1,60963).
+char(7,60964).
+char(m,60965).
+char(9,60966).
+char(0,60967).
+char(2,60968).
+char(7,60969).
+char(m,60970).
+char(o,60971).
+char(p,60972).
+char(4,60973).
+char(5,60974).
+char(2,60975).
+char(5,60976).
+char(m,60977).
+char(o,60978).
+char(m,60979).
+char(o,60980).
+char(p,60981).
+char(o,60982).
+char(p,60983).
+char(7,60984).
+char(4,60985).
+char(8,60986).
+char(5,60987).
+char(c,60988).
+char(c,60989).
+char(m,60990).
+char(o,60991).
+char(m,60992).
+char(6,60993).
+char(5,60994).
+char(2,60995).
+char(6,60996).
+char(m,60997).
+char(5,60998).
+char(6,60999).
+char(6,61000).
+char(5,61001).
+char(c,61002).
+char(c,61003).
+char(c,61004).
+char(c,61005).
+char(m,61006).
+char(2,61007).
+char(0,61008).
+char(6,61009).
+char(1,61010).
+char(c,61011).
+char(c,61012).
+char(m,61013).
+char(7,61014).
+char(2,61015).
+char(4,61016).
+char(1,61017).
+char(p,61018).
+char(o,61019).
+char(m,61020).
+char(6,61021).
+char(8,61022).
+char(8,61023).
+char(1,61024).
+char(c,61025).
+char(p,61026).
+char(o,61027).
+char(o,61028).
+char(o,61029).
+char(m,61030).
+char(o,61031).
+char(p,61032).
+char(4,61033).
+char(0,61034).
+char(3,61035).
+char(9,61036).
+char(p,61037).
+char(o,61038).
+char(3,61039).
+char(2,61040).
+char(4,61041).
+char(0,61042).
+char(m,61043).
+char(o,61044).
+char(m,61045).
+char(o,61046).
+char(o,61047).
+char(o,61048).
+char(6,61049).
+char(7,61050).
+char(2,61051).
+char(1,61052).
+char(c,61053).
+char(c,61054).
+char(m,61055).
+char(o,61056).
+char(o,61057).
+char(m,61058).
+char(o,61059).
+char(m,61060).
+char(o,61061).
+char(m,61062).
+char(8,61063).
+char(6,61064).
+char(4,61065).
+char(6,61066).
+char(m,61067).
+char(4,61068).
+char(6,61069).
+char(9,61070).
+char(6,61071).
+char(c,61072).
+char(c,61073).
+char(m,61074).
+char(o,61075).
+char(m,61076).
+char(o,61077).
+char(8,61078).
+char(0,61079).
+char(0,61080).
+char(9,61081).
+char(c,61082).
+char(p,61083).
+char(o,61084).
+char(o,61085).
+char(p,61086).
+char(o,61087).
+char(o,61088).
+char(m,61089).
+char(o,61090).
+char(m,61091).
+char(6,61092).
+char(4,61093).
+char(3,61094).
+char(6,61095).
+char(c,61096).
+char(m,61097).
+char(6,61098).
+char(8,61099).
+char(2,61100).
+char(7,61101).
+char(c,61102).
+char(c,61103).
+char(m,61104).
+char(3,61105).
+char(4,61106).
+char(0,61107).
+char(6,61108).
+char(p,61109).
+char(8,61110).
+char(9,61111).
+char(2,61112).
+char(2,61113).
+char(m,61114).
+char(5,61115).
+char(2,61116).
+char(0,61117).
+char(c,61118).
+char(p,61119).
+char(o,61120).
+char(p,61121).
+char(o,61122).
+char(m,61123).
+char(o,61124).
+char(p,61125).
+char(1,61126).
+char(2,61127).
+char(6,61128).
+char(5,61129).
+char(c,61130).
+char(m,61131).
+char(o,61132).
+char(p,61133).
+char(7,61134).
+char(1,61135).
+char(6,61136).
+char(c,61137).
+char(m,61138).
+char(6,61139).
+char(2,61140).
+char(2,61141).
+char(m,61142).
+char(2,61143).
+char(0,61144).
+char(4,61145).
+char(0,61146).
+char(m,61147).
+char(2,61148).
+char(4,61149).
+char(2,61150).
+char(5,61151).
+char(p,61152).
+char(o,61153).
+char(p,61154).
+char(8,61155).
+char(5,61156).
+char(3,61157).
+char(5,61158).
+char(m,61159).
+char(2,61160).
+char(7,61161).
+char(8,61162).
+char(0,61163).
+char(c,61164).
+char(c,61165).
+char(c,61166).
+char(c,61167).
+char(m,61168).
+char(o,61169).
+char(m,61170).
+char(5,61171).
+char(5,61172).
+char(7,61173).
+char(c,61174).
+char(m,61175).
+char(9,61176).
+char(8,61177).
+char(9,61178).
+char(6,61179).
+char(m,61180).
+char(1,61181).
+char(8,61182).
+char(c,61183).
+char(c,61184).
+char(c,61185).
+char(c,61186).
+char(c,61187).
+char(c,61188).
+char(m,61189).
+char(8,61190).
+char(4,61191).
+char(5,61192).
+char(0,61193).
+char(c,61194).
+char(c,61195).
+char(p,61196).
+char(o,61197).
+char(m,61198).
+char(o,61199).
+char(6,61200).
+char(2,61201).
+char(9,61202).
+char(1,61203).
+char(c,61204).
+char(m,61205).
+char(o,61206).
+char(m,61207).
+char(o,61208).
+char(p,61209).
+char(o,61210).
+char(m,61211).
+char(o,61212).
+char(p,61213).
+char(1,61214).
+char(3,61215).
+char(5,61216).
+char(1,61217).
+char(c,61218).
+char(m,61219).
+char(9,61220).
+char(7,61221).
+char(0,61222).
+char(9,61223).
+char(c,61224).
+char(c,61225).
+char(c,61226).
+char(c,61227).
+char(p,61228).
+char(3,61229).
+char(6,61230).
+char(m,61231).
+char(o,61232).
+char(p,61233).
+char(o,61234).
+char(3,61235).
+char(1,61236).
+char(5,61237).
+char(2,61238).
+char(m,61239).
+char(3,61240).
+char(1,61241).
+char(4,61242).
+char(0,61243).
+char(c,61244).
+char(p,61245).
+char(1,61246).
+char(6,61247).
+char(4,61248).
+char(8,61249).
+char(c,61250).
+char(c,61251).
+char(p,61252).
+char(6,61253).
+char(6,61254).
+char(0,61255).
+char(1,61256).
+char(c,61257).
+char(c,61258).
+char(p,61259).
+char(7,61260).
+char(4,61261).
+char(3,61262).
+char(0,61263).
+char(c,61264).
+char(m,61265).
+char(3,61266).
+char(7,61267).
+char(3,61268).
+char(4,61269).
+char(m,61270).
+char(o,61271).
+char(m,61272).
+char(o,61273).
+char(m,61274).
+char(o,61275).
+char(p,61276).
+char(o,61277).
+char(m,61278).
+char(o,61279).
+char(m,61280).
+char(7,61281).
+char(8,61282).
+char(4,61283).
+char(7,61284).
+char(c,61285).
+char(p,61286).
+char(o,61287).
+char(m,61288).
+char(6,61289).
+char(5,61290).
+char(9,61291).
+char(2,61292).
+char(m,61293).
+char(o,61294).
+char(p,61295).
+char(1,61296).
+char(1,61297).
+char(4,61298).
+char(9,61299).
+char(p,61300).
+char(8,61301).
+char(1,61302).
+char(3,61303).
+char(0,61304).
+char(p,61305).
+char(5,61306).
+char(0,61307).
+char(7,61308).
+char(4,61309).
+char(c,61310).
+char(c,61311).
+char(p,61312).
+char(4,61313).
+char(2,61314).
+char(3,61315).
+char(1,61316).
+char(m,61317).
+char(o,61318).
+char(o,61319).
+char(9,61320).
+char(8,61321).
+char(0,61322).
+char(m,61323).
+char(9,61324).
+char(2,61325).
+char(6,61326).
+char(c,61327).
+char(m,61328).
+char(o,61329).
+char(m,61330).
+char(4,61331).
+char(7,61332).
+char(9,61333).
+char(4,61334).
+char(p,61335).
+char(o,61336).
+char(p,61337).
+char(o,61338).
+char(m,61339).
+char(o,61340).
+char(p,61341).
+char(1,61342).
+char(9,61343).
+char(5,61344).
+char(5,61345).
+char(c,61346).
+char(m,61347).
+char(o,61348).
+char(m,61349).
+char(o,61350).
+char(p,61351).
+char(o,61352).
+char(m,61353).
+char(o,61354).
+char(p,61355).
+char(o,61356).
+char(o,61357).
+char(m,61358).
+char(9,61359).
+char(1,61360).
+char(0,61361).
+char(4,61362).
+char(p,61363).
+char(5,61364).
+char(0,61365).
+char(5,61366).
+char(8,61367).
+char(p,61368).
+char(2,61369).
+char(6,61370).
+char(1,61371).
+char(8,61372).
+char(m,61373).
+char(7,61374).
+char(4,61375).
+char(1,61376).
+char(5,61377).
+char(c,61378).
+char(m,61379).
+char(1,61380).
+char(3,61381).
+char(1,61382).
+char(4,61383).
+char(m,61384).
+char(9,61385).
+char(4,61386).
+char(7,61387).
+char(6,61388).
+char(p,61389).
+char(o,61390).
+char(p,61391).
+char(o,61392).
+char(p,61393).
+char(2,61394).
+char(5,61395).
+char(0,61396).
+char(9,61397).
+char(c,61398).
+char(p,61399).
+char(3,61400).
+char(4,61401).
+char(3,61402).
+char(1,61403).
+char(c,61404).
+char(c,61405).
+char(p,61406).
+char(o,61407).
+char(p,61408).
+char(o,61409).
+char(o,61410).
+char(p,61411).
+char(3,61412).
+char(9,61413).
+char(7,61414).
+char(3,61415).
+char(m,61416).
+char(o,61417).
+char(o,61418).
+char(m,61419).
+char(o,61420).
+char(m,61421).
+char(o,61422).
+char(p,61423).
+char(6,61424).
+char(9,61425).
+char(p,61426).
+char(o,61427).
+char(8,61428).
+char(9,61429).
+char(2,61430).
+char(5,61431).
+char(c,61432).
+char(c,61433).
+char(p,61434).
+char(3,61435).
+char(7,61436).
+char(2,61437).
+char(2,61438).
+char(c,61439).
+char(c,61440).
+char(c,61441).
+char(p,61442).
+char(9,61443).
+char(0,61444).
+char(7,61445).
+char(8,61446).
+char(p,61447).
+char(o,61448).
+char(m,61449).
+char(o,61450).
+char(m,61451).
+char(8,61452).
+char(7,61453).
+char(7,61454).
+char(5,61455).
+char(c,61456).
+char(c,61457).
+char(m,61458).
+char(5,61459).
+char(9,61460).
+char(6,61461).
+char(7,61462).
+char(m,61463).
+char(4,61464).
+char(8,61465).
+char(6,61466).
+char(3,61467).
+char(p,61468).
+char(7,61469).
+char(7,61470).
+char(3,61471).
+char(8,61472).
+char(p,61473).
+char(2,61474).
+char(2,61475).
+char(1,61476).
+char(c,61477).
+char(c,61478).
+char(c,61479).
+char(m,61480).
+char(o,61481).
+char(p,61482).
+char(o,61483).
+char(m,61484).
+char(o,61485).
+char(o,61486).
+char(p,61487).
+char(9,61488).
+char(7,61489).
+char(3,61490).
+char(7,61491).
+char(p,61492).
+char(o,61493).
+char(o,61494).
+char(m,61495).
+char(o,61496).
+char(p,61497).
+char(o,61498).
+char(m,61499).
+char(o,61500).
+char(m,61501).
+char(o,61502).
+char(m,61503).
+char(9,61504).
+char(2,61505).
+char(2,61506).
+char(9,61507).
+char(p,61508).
+char(7,61509).
+char(8,61510).
+char(4,61511).
+char(3,61512).
+char(p,61513).
+char(3,61514).
+char(7,61515).
+char(8,61516).
+char(7,61517).
+char(c,61518).
+char(p,61519).
+char(o,61520).
+char(p,61521).
+char(o,61522).
+char(p,61523).
+char(2,61524).
+char(0,61525).
+char(2,61526).
+char(0,61527).
+char(c,61528).
+char(c,61529).
+char(c,61530).
+char(c,61531).
+char(c,61532).
+char(m,61533).
+char(3,61534).
+char(9,61535).
+char(5,61536).
+char(3,61537).
+char(m,61538).
+char(o,61539).
+char(p,61540).
+char(7,61541).
+char(6,61542).
+char(8,61543).
+char(4,61544).
+char(m,61545).
+char(o,61546).
+char(p,61547).
+char(o,61548).
+char(m,61549).
+char(3,61550).
+char(6,61551).
+char(9,61552).
+char(3,61553).
+char(c,61554).
+char(c,61555).
+char(c,61556).
+char(c,61557).
+char(m,61558).
+char(4,61559).
+char(9,61560).
+char(6,61561).
+char(0,61562).
+char(p,61563).
+char(6,61564).
+char(9,61565).
+char(4,61566).
+char(c,61567).
+char(c,61568).
+char(c,61569).
+char(m,61570).
+char(5,61571).
+char(8,61572).
+char(1,61573).
+char(3,61574).
+char(c,61575).
+char(m,61576).
+char(o,61577).
+char(o,61578).
+char(p,61579).
+char(o,61580).
+char(2,61581).
+char(5,61582).
+char(7,61583).
+char(8,61584).
+char(c,61585).
+char(p,61586).
+char(4,61587).
+char(0,61588).
+char(4,61589).
+char(8,61590).
+char(c,61591).
+char(c,61592).
+char(m,61593).
+char(o,61594).
+char(p,61595).
+char(o,61596).
+char(m,61597).
+char(o,61598).
+char(p,61599).
+char(o,61600).
+char(o,61601).
+char(p,61602).
+char(o,61603).
+char(p,61604).
+char(5,61605).
+char(3,61606).
+char(1,61607).
+char(8,61608).
+char(p,61609).
+char(8,61610).
+char(1,61611).
+char(5,61612).
+char(7,61613).
+char(c,61614).
+char(m,61615).
+char(8,61616).
+char(1,61617).
+char(6,61618).
+char(0,61619).
+char(m,61620).
+char(4,61621).
+char(3,61622).
+char(3,61623).
+char(2,61624).
+char(c,61625).
+char(m,61626).
+char(5,61627).
+char(8,61628).
+char(7,61629).
+char(3,61630).
+char(p,61631).
+char(3,61632).
+char(0,61633).
+char(8,61634).
+char(8,61635).
+char(m,61636).
+char(4,61637).
+char(0,61638).
+char(3,61639).
+char(1,61640).
+char(c,61641).
+char(c,61642).
+char(c,61643).
+char(c,61644).
+char(c,61645).
+char(c,61646).
+char(p,61647).
+char(o,61648).
+char(o,61649).
+char(p,61650).
+char(o,61651).
+char(9,61652).
+char(1,61653).
+char(7,61654).
+char(0,61655).
+char(c,61656).
+char(m,61657).
+char(1,61658).
+char(5,61659).
+char(9,61660).
+char(1,61661).
+char(p,61662).
+char(2,61663).
+char(1,61664).
+char(4,61665).
+char(1,61666).
+char(p,61667).
+char(8,61668).
+char(1,61669).
+char(9,61670).
+char(0,61671).
+char(c,61672).
+char(c,61673).
+char(m,61674).
+char(o,61675).
+char(o,61676).
+char(p,61677).
+char(2,61678).
+char(3,61679).
+char(7,61680).
+char(6,61681).
+char(c,61682).
+char(c,61683).
+char(p,61684).
+char(6,61685).
+char(8,61686).
+char(0,61687).
+char(c,61688).
+char(p,61689).
+char(o,61690).
+char(m,61691).
+char(o,61692).
+char(m,61693).
+char(o,61694).
+char(p,61695).
+char(2,61696).
+char(5,61697).
+char(8,61698).
+char(2,61699).
+char(p,61700).
+char(o,61701).
+char(p,61702).
+char(o,61703).
+char(m,61704).
+char(o,61705).
+char(o,61706).
+char(m,61707).
+char(o,61708).
+char(3,61709).
+char(5,61710).
+char(2,61711).
+char(0,61712).
+char(c,61713).
+char(m,61714).
+char(3,61715).
+char(0,61716).
+char(5,61717).
+char(8,61718).
+char(c,61719).
+char(p,61720).
+char(5,61721).
+char(1,61722).
+char(7,61723).
+char(4,61724).
+char(m,61725).
+char(o,61726).
+char(6,61727).
+char(9,61728).
+char(9,61729).
+char(4,61730).
+char(p,61731).
+char(o,61732).
+char(m,61733).
+char(o,61734).
+char(o,61735).
+char(p,61736).
+char(o,61737).
+char(m,61738).
+char(o,61739).
+char(m,61740).
+char(5,61741).
+char(0,61742).
+char(4,61743).
+char(6,61744).
+char(p,61745).
+char(5,61746).
+char(8,61747).
+char(8,61748).
+char(5,61749).
+char(c,61750).
+char(c,61751).
+char(p,61752).
+char(4,61753).
+char(2,61754).
+char(8,61755).
+char(1,61756).
+char(m,61757).
+char(o,61758).
+char(p,61759).
+char(o,61760).
+char(m,61761).
+char(8,61762).
+char(3,61763).
+char(4,61764).
+char(9,61765).
+char(c,61766).
+char(p,61767).
+char(o,61768).
+char(m,61769).
+char(o,61770).
+char(m,61771).
+char(4,61772).
+char(4,61773).
+char(6,61774).
+char(9,61775).
+char(c,61776).
+char(p,61777).
+char(o,61778).
+char(p,61779).
+char(2,61780).
+char(4,61781).
+char(5,61782).
+char(6,61783).
+char(c,61784).
+char(c,61785).
+char(c,61786).
+char(p,61787).
+char(1,61788).
+char(9,61789).
+char(2,61790).
+char(5,61791).
+char(c,61792).
+char(m,61793).
+char(o,61794).
+char(m,61795).
+char(7,61796).
+char(2,61797).
+char(9,61798).
+char(7,61799).
+char(c,61800).
+char(c,61801).
+char(c,61802).
+char(c,61803).
+char(p,61804).
+char(2,61805).
+char(9,61806).
+char(8,61807).
+char(6,61808).
+char(p,61809).
+char(9,61810).
+char(9,61811).
+char(5,61812).
+char(9,61813).
+char(m,61814).
+char(o,61815).
+char(p,61816).
+char(2,61817).
+char(0,61818).
+char(4,61819).
+char(2,61820).
+char(m,61821).
+char(4,61822).
+char(9,61823).
+char(3,61824).
+char(0,61825).
+char(c,61826).
+char(p,61827).
+char(1,61828).
+char(6,61829).
+char(6,61830).
+char(0,61831).
+char(c,61832).
+char(p,61833).
+char(o,61834).
+char(p,61835).
+char(7,61836).
+char(0,61837).
+char(7,61838).
+char(6,61839).
+char(m,61840).
+char(2,61841).
+char(7,61842).
+char(9,61843).
+char(8,61844).
+char(c,61845).
+char(c,61846).
+char(c,61847).
+char(m,61848).
+char(7,61849).
+char(4,61850).
+char(2,61851).
+char(9,61852).
+char(c,61853).
+char(c,61854).
+char(p,61855).
+char(o,61856).
+char(o,61857).
+char(p,61858).
+char(7,61859).
+char(5,61860).
+char(6,61861).
+char(4,61862).
+char(m,61863).
+char(1,61864).
+char(5,61865).
+char(0,61866).
+char(9,61867).
+char(c,61868).
+char(p,61869).
+char(9,61870).
+char(5,61871).
+char(9,61872).
+char(5,61873).
+char(c,61874).
+char(m,61875).
+char(9,61876).
+char(3,61877).
+char(0,61878).
+char(6,61879).
+char(c,61880).
+char(c,61881).
+char(c,61882).
+char(p,61883).
+char(6,61884).
+char(2,61885).
+char(9,61886).
+char(c,61887).
+char(p,61888).
+char(8,61889).
+char(4,61890).
+char(7,61891).
+char(4,61892).
+char(m,61893).
+char(5,61894).
+char(1,61895).
+char(9,61896).
+char(9,61897).
+char(c,61898).
+char(c,61899).
+char(c,61900).
+char(p,61901).
+char(o,61902).
+char(6,61903).
+char(3,61904).
+char(3,61905).
+char(2,61906).
+char(p,61907).
+char(o,61908).
+char(m,61909).
+char(1,61910).
+char(9,61911).
+char(1,61912).
+char(m,61913).
+char(9,61914).
+char(3,61915).
+char(1,61916).
+char(4,61917).
+char(c,61918).
+char(m,61919).
+char(o,61920).
+char(m,61921).
+char(4,61922).
+char(0,61923).
+char(6,61924).
+char(6,61925).
+char(c,61926).
+char(p,61927).
+char(5,61928).
+char(8,61929).
+char(4,61930).
+char(3,61931).
+char(p,61932).
+char(o,61933).
+char(m,61934).
+char(6,61935).
+char(8,61936).
+char(0,61937).
+char(1,61938).
+char(m,61939).
+char(o,61940).
+char(p,61941).
+char(o,61942).
+char(6,61943).
+char(9,61944).
+char(2,61945).
+char(c,61946).
+char(p,61947).
+char(o,61948).
+char(o,61949).
+char(7,61950).
+char(8,61951).
+char(7,61952).
+char(7,61953).
+char(c,61954).
+char(m,61955).
+char(5,61956).
+char(1,61957).
+char(0,61958).
+char(2,61959).
+char(c,61960).
+char(p,61961).
+char(o,61962).
+char(m,61963).
+char(o,61964).
+char(p,61965).
+char(7,61966).
+char(3,61967).
+char(9,61968).
+char(4,61969).
+char(c,61970).
+char(p,61971).
+char(o,61972).
+char(m,61973).
+char(6,61974).
+char(0,61975).
+char(1,61976).
+char(0,61977).
+char(c,61978).
+char(p,61979).
+char(o,61980).
+char(o,61981).
+char(p,61982).
+char(9,61983).
+char(5,61984).
+char(9,61985).
+char(7,61986).
+char(c,61987).
+char(p,61988).
+char(o,61989).
+char(p,61990).
+char(9,61991).
+char(8,61992).
+char(2,61993).
+char(9,61994).
+char(m,61995).
+char(7,61996).
+char(5,61997).
+char(0,61998).
+char(8,61999).
+char(c,62000).
+char(m,62001).
+char(o,62002).
+char(p,62003).
+char(o,62004).
+char(p,62005).
+char(o,62006).
+char(p,62007).
+char(4,62008).
+char(7,62009).
+char(2,62010).
+char(5,62011).
+char(c,62012).
+char(m,62013).
+char(o,62014).
+char(m,62015).
+char(o,62016).
+char(m,62017).
+char(o,62018).
+char(p,62019).
+char(o,62020).
+char(m,62021).
+char(1,62022).
+char(2,62023).
+char(9,62024).
+char(5,62025).
+char(c,62026).
+char(c,62027).
+char(c,62028).
+char(p,62029).
+char(3,62030).
+char(2,62031).
+char(6,62032).
+char(1,62033).
+char(p,62034).
+char(o,62035).
+char(p,62036).
+char(9,62037).
+char(6,62038).
+char(0,62039).
+char(3,62040).
+char(c,62041).
+char(c,62042).
+char(p,62043).
+char(o,62044).
+char(o,62045).
+char(p,62046).
+char(o,62047).
+char(o,62048).
+char(o,62049).
+char(m,62050).
+char(5,62051).
+char(0,62052).
+char(1,62053).
+char(7,62054).
+char(c,62055).
+char(c,62056).
+char(c,62057).
+char(c,62058).
+char(m,62059).
+char(o,62060).
+char(o,62061).
+char(m,62062).
+char(7,62063).
+char(4,62064).
+char(7,62065).
+char(0,62066).
+char(m,62067).
+char(9,62068).
+char(9,62069).
+char(2,62070).
+char(9,62071).
+char(m,62072).
+char(o,62073).
+char(m,62074).
+char(o,62075).
+char(p,62076).
+char(o,62077).
+char(m,62078).
+char(9,62079).
+char(1,62080).
+char(9,62081).
+char(p,62082).
+char(4,62083).
+char(2,62084).
+char(8,62085).
+char(0,62086).
+char(m,62087).
+char(3,62088).
+char(5,62089).
+char(2,62090).
+char(8,62091).
+char(m,62092).
+char(o,62093).
+char(m,62094).
+char(o,62095).
+char(p,62096).
+char(1,62097).
+char(2,62098).
+char(6,62099).
+char(4,62100).
+char(p,62101).
+char(8,62102).
+char(8,62103).
+char(3,62104).
+char(3,62105).
+char(p,62106).
+char(1,62107).
+char(2,62108).
+char(4,62109).
+char(2,62110).
+char(c,62111).
+char(c,62112).
+char(p,62113).
+char(o,62114).
+char(m,62115).
+char(o,62116).
+char(p,62117).
+char(8,62118).
+char(4,62119).
+char(0,62120).
+char(9,62121).
+char(c,62122).
+char(c,62123).
+char(c,62124).
+char(c,62125).
+char(m,62126).
+char(9,62127).
+char(6,62128).
+char(2,62129).
+char(4,62130).
+char(p,62131).
+char(o,62132).
+char(m,62133).
+char(o,62134).
+char(o,62135).
+char(m,62136).
+char(o,62137).
+char(m,62138).
+char(o,62139).
+char(m,62140).
+char(o,62141).
+char(m,62142).
+char(o,62143).
+char(p,62144).
+char(o,62145).
+char(p,62146).
+char(o,62147).
+char(m,62148).
+char(3,62149).
+char(0,62150).
+char(7,62151).
+char(c,62152).
+char(p,62153).
+char(3,62154).
+char(9,62155).
+char(7,62156).
+char(8,62157).
+char(c,62158).
+char(m,62159).
+char(o,62160).
+char(p,62161).
+char(5,62162).
+char(1,62163).
+char(9,62164).
+char(4,62165).
+char(m,62166).
+char(9,62167).
+char(2,62168).
+char(1,62169).
+char(7,62170).
+char(p,62171).
+char(o,62172).
+char(o,62173).
+char(p,62174).
+char(7,62175).
+char(7,62176).
+char(8,62177).
+char(3,62178).
+char(c,62179).
+char(p,62180).
+char(4,62181).
+char(4,62182).
+char(0,62183).
+char(5,62184).
+char(p,62185).
+char(o,62186).
+char(m,62187).
+char(o,62188).
+char(o,62189).
+char(m,62190).
+char(8,62191).
+char(4,62192).
+char(8,62193).
+char(3,62194).
+char(p,62195).
+char(3,62196).
+char(9,62197).
+char(0,62198).
+char(1,62199).
+char(p,62200).
+char(o,62201).
+char(7,62202).
+char(1,62203).
+char(3,62204).
+char(2,62205).
+char(p,62206).
+char(7,62207).
+char(0,62208).
+char(0,62209).
+char(m,62210).
+char(o,62211).
+char(o,62212).
+char(o,62213).
+char(m,62214).
+char(4,62215).
+char(4,62216).
+char(4,62217).
+char(0,62218).
+char(c,62219).
+char(c,62220).
+char(p,62221).
+char(o,62222).
+char(o,62223).
+char(m,62224).
+char(8,62225).
+char(5,62226).
+char(7,62227).
+char(7,62228).
+char(c,62229).
+char(p,62230).
+char(o,62231).
+char(m,62232).
+char(5,62233).
+char(c,62234).
+char(m,62235).
+char(2,62236).
+char(1,62237).
+char(4,62238).
+char(m,62239).
+char(8,62240).
+char(6,62241).
+char(1,62242).
+char(7,62243).
+char(m,62244).
+char(o,62245).
+char(m,62246).
+char(6,62247).
+char(6,62248).
+char(6,62249).
+char(3,62250).
+char(m,62251).
+char(o,62252).
+char(2,62253).
+char(6,62254).
+char(5,62255).
+char(9,62256).
+char(p,62257).
+char(o,62258).
+char(m,62259).
+char(5,62260).
+char(5,62261).
+char(5,62262).
+char(2,62263).
+char(c,62264).
+char(p,62265).
+char(1,62266).
+char(4,62267).
+char(2,62268).
+char(4,62269).
+char(c,62270).
+char(p,62271).
+char(9,62272).
+char(0,62273).
+char(7,62274).
+char(5,62275).
+char(c,62276).
+char(c,62277).
+char(c,62278).
+char(c,62279).
+char(m,62280).
+char(3,62281).
+char(9,62282).
+char(5,62283).
+char(0,62284).
+char(p,62285).
+char(o,62286).
+char(p,62287).
+char(5,62288).
+char(8,62289).
+char(2,62290).
+char(0,62291).
+char(c,62292).
+char(p,62293).
+char(o,62294).
+char(o,62295).
+char(m,62296).
+char(1,62297).
+char(8,62298).
+char(9,62299).
+char(1,62300).
+char(c,62301).
+char(c,62302).
+char(m,62303).
+char(o,62304).
+char(m,62305).
+char(o,62306).
+char(p,62307).
+char(8,62308).
+char(0,62309).
+char(6,62310).
+char(8,62311).
+char(p,62312).
+char(1,62313).
+char(1,62314).
+char(1,62315).
+char(4,62316).
+char(p,62317).
+char(1,62318).
+char(9,62319).
+char(4,62320).
+char(0,62321).
+char(c,62322).
+char(m,62323).
+char(7,62324).
+char(9,62325).
+char(3,62326).
+char(3,62327).
+char(m,62328).
+char(6,62329).
+char(4,62330).
+char(8,62331).
+char(0,62332).
+char(c,62333).
+char(p,62334).
+char(6,62335).
+char(1,62336).
+char(1,62337).
+char(6,62338).
+char(p,62339).
+char(o,62340).
+char(p,62341).
+char(o,62342).
+char(m,62343).
+char(o,62344).
+char(p,62345).
+char(1,62346).
+char(1,62347).
+char(2,62348).
+char(3,62349).
+char(p,62350).
+char(3,62351).
+char(3,62352).
+char(2,62353).
+char(2,62354).
+char(m,62355).
+char(3,62356).
+char(8,62357).
+char(9,62358).
+char(5,62359).
+char(c,62360).
+char(c,62361).
+char(c,62362).
+char(m,62363).
+char(o,62364).
+char(4,62365).
+char(7,62366).
+char(6,62367).
+char(1,62368).
+char(c,62369).
+char(m,62370).
+char(7,62371).
+char(1,62372).
+char(7,62373).
+char(8,62374).
+char(c,62375).
+char(m,62376).
+char(o,62377).
+char(o,62378).
+char(m,62379).
+char(9,62380).
+char(8,62381).
+char(8,62382).
+char(4,62383).
+char(c,62384).
+char(c,62385).
+char(c,62386).
+char(p,62387).
+char(8,62388).
+char(3,62389).
+char(9,62390).
+char(7,62391).
+char(m,62392).
+char(2,62393).
+char(6,62394).
+char(2,62395).
+char(9,62396).
+char(c,62397).
+char(c,62398).
+char(c,62399).
+char(p,62400).
+char(o,62401).
+char(p,62402).
+char(6,62403).
+char(7,62404).
+char(1,62405).
+char(9,62406).
+char(c,62407).
+char(c,62408).
+char(c,62409).
+char(m,62410).
+char(o,62411).
+char(1,62412).
+char(0,62413).
+char(8,62414).
+char(8,62415).
+char(p,62416).
+char(o,62417).
+char(o,62418).
+char(7,62419).
+char(1,62420).
+char(9,62421).
+char(8,62422).
+char(c,62423).
+char(m,62424).
+char(8,62425).
+char(0,62426).
+char(1,62427).
+char(4,62428).
+char(c,62429).
+char(m,62430).
+char(8,62431).
+char(1,62432).
+char(0,62433).
+char(9,62434).
+char(c,62435).
+char(c,62436).
+char(m,62437).
+char(6,62438).
+char(4,62439).
+char(0,62440).
+char(4,62441).
+char(c,62442).
+char(p,62443).
+char(8,62444).
+char(7,62445).
+char(4,62446).
+char(2,62447).
+char(m,62448).
+char(o,62449).
+char(1,62450).
+char(8,62451).
+char(2,62452).
+char(0,62453).
+char(p,62454).
+char(6,62455).
+char(2,62456).
+char(3,62457).
+char(3,62458).
+char(m,62459).
+char(6,62460).
+char(3,62461).
+char(0,62462).
+char(6,62463).
+char(c,62464).
+char(c,62465).
+char(c,62466).
+char(c,62467).
+char(m,62468).
+char(9,62469).
+char(3,62470).
+char(0,62471).
+char(7,62472).
+char(m,62473).
+char(o,62474).
+char(o,62475).
+char(p,62476).
+char(o,62477).
+char(m,62478).
+char(8,62479).
+char(5,62480).
+char(1,62481).
+char(3,62482).
+char(m,62483).
+char(o,62484).
+char(5,62485).
+char(8,62486).
+char(7,62487).
+char(4,62488).
+char(p,62489).
+char(o,62490).
+char(m,62491).
+char(5,62492).
+char(6,62493).
+char(9,62494).
+char(5,62495).
+char(p,62496).
+char(9,62497).
+char(2,62498).
+char(6,62499).
+char(1,62500).
+char(m,62501).
+char(3,62502).
+char(7,62503).
+char(8,62504).
+char(9,62505).
+char(p,62506).
+char(9,62507).
+char(1,62508).
+char(4,62509).
+char(7,62510).
+char(p,62511).
+char(o,62512).
+char(p,62513).
+char(5,62514).
+char(8,62515).
+char(1,62516).
+char(5,62517).
+char(c,62518).
+char(m,62519).
+char(9,62520).
+char(4,62521).
+char(9,62522).
+char(c,62523).
+char(c,62524).
+char(c,62525).
+char(p,62526).
+char(9,62527).
+char(6,62528).
+char(2,62529).
+char(1,62530).
+char(c,62531).
+char(p,62532).
+char(3,62533).
+char(0,62534).
+char(3,62535).
+char(8,62536).
+char(m,62537).
+char(o,62538).
+char(p,62539).
+char(o,62540).
+char(m,62541).
+char(4,62542).
+char(1,62543).
+char(8,62544).
+char(8,62545).
+char(c,62546).
+char(m,62547).
+char(4,62548).
+char(7,62549).
+char(4,62550).
+char(6,62551).
+char(c,62552).
+char(c,62553).
+char(c,62554).
+char(c,62555).
+char(c,62556).
+char(c,62557).
+char(m,62558).
+char(4,62559).
+char(0,62560).
+char(6,62561).
+char(c,62562).
+char(m,62563).
+char(o,62564).
+char(7,62565).
+char(9,62566).
+char(4,62567).
+char(6,62568).
+char(c,62569).
+char(p,62570).
+char(3,62571).
+char(6,62572).
+char(2,62573).
+char(3,62574).
+char(p,62575).
+char(7,62576).
+char(0,62577).
+char(5,62578).
+char(3,62579).
+char(c,62580).
+char(c,62581).
+char(c,62582).
+char(m,62583).
+char(7,62584).
+char(0,62585).
+char(1,62586).
+char(m,62587).
+char(o,62588).
+char(p,62589).
+char(1,62590).
+char(6,62591).
+char(7,62592).
+char(1,62593).
+char(c,62594).
+char(c,62595).
+char(m,62596).
+char(4,62597).
+char(4,62598).
+char(4,62599).
+char(4,62600).
+char(m,62601).
+char(o,62602).
+char(m,62603).
+char(o,62604).
+char(m,62605).
+char(o,62606).
+char(4,62607).
+char(4,62608).
+char(4,62609).
+char(1,62610).
+char(m,62611).
+char(2,62612).
+char(1,62613).
+char(3,62614).
+char(4,62615).
+char(c,62616).
+char(m,62617).
+char(3,62618).
+char(3,62619).
+char(0,62620).
+char(6,62621).
+char(c,62622).
+char(c,62623).
+char(m,62624).
+char(o,62625).
+char(6,62626).
+char(9,62627).
+char(2,62628).
+char(0,62629).
+char(c,62630).
+char(m,62631).
+char(9,62632).
+char(9,62633).
+char(4,62634).
+char(6,62635).
+char(p,62636).
+char(o,62637).
+char(m,62638).
+char(3,62639).
+char(5,62640).
+char(7,62641).
+char(2,62642).
+char(p,62643).
+char(7,62644).
+char(5,62645).
+char(0,62646).
+char(9,62647).
+char(m,62648).
+char(5,62649).
+char(9,62650).
+char(6,62651).
+char(7,62652).
+char(c,62653).
+char(m,62654).
+char(o,62655).
+char(o,62656).
+char(p,62657).
+char(2,62658).
+char(9,62659).
+char(0,62660).
+char(4,62661).
+char(p,62662).
+char(6,62663).
+char(8,62664).
+char(4,62665).
+char(8,62666).
+char(m,62667).
+char(1,62668).
+char(9,62669).
+char(8,62670).
+char(1,62671).
+char(c,62672).
+char(c,62673).
+char(p,62674).
+char(8,62675).
+char(0,62676).
+char(1,62677).
+char(3,62678).
+char(c,62679).
+char(c,62680).
+char(m,62681).
+char(8,62682).
+char(1,62683).
+char(0,62684).
+char(9,62685).
+char(c,62686).
+char(c,62687).
+char(m,62688).
+char(o,62689).
+char(1,62690).
+char(5,62691).
+char(3,62692).
+char(8,62693).
+char(p,62694).
+char(o,62695).
+char(9,62696).
+char(6,62697).
+char(4,62698).
+char(1,62699).
+char(p,62700).
+char(o,62701).
+char(p,62702).
+char(5,62703).
+char(6,62704).
+char(1,62705).
+char(7,62706).
+char(c,62707).
+char(p,62708).
+char(o,62709).
+char(m,62710).
+char(6,62711).
+char(0,62712).
+char(5,62713).
+char(3,62714).
+char(c,62715).
+char(c,62716).
+char(c,62717).
+char(m,62718).
+char(o,62719).
+char(p,62720).
+char(o,62721).
+char(9,62722).
+char(6,62723).
+char(8,62724).
+char(2,62725).
+char(c,62726).
+char(m,62727).
+char(2,62728).
+char(1,62729).
+char(7,62730).
+char(5,62731).
+char(c,62732).
+char(p,62733).
+char(9,62734).
+char(5,62735).
+char(9,62736).
+char(8,62737).
+char(m,62738).
+char(o,62739).
+char(m,62740).
+char(o,62741).
+char(m,62742).
+char(6,62743).
+char(4,62744).
+char(0,62745).
+char(6,62746).
+char(c,62747).
+char(p,62748).
+char(o,62749).
+char(p,62750).
+char(o,62751).
+char(p,62752).
+char(3,62753).
+char(9,62754).
+char(5,62755).
+char(2,62756).
+char(c,62757).
+char(m,62758).
+char(o,62759).
+char(m,62760).
+char(o,62761).
+char(m,62762).
+char(o,62763).
+char(9,62764).
+char(1,62765).
+char(6,62766).
+char(2,62767).
+char(c,62768).
+char(c,62769).
+char(c,62770).
+char(c,62771).
+char(c,62772).
+char(c,62773).
+char(c,62774).
+char(m,62775).
+char(9,62776).
+char(9,62777).
+char(6,62778).
+char(8,62779).
+char(m,62780).
+char(9,62781).
+char(8,62782).
+char(0,62783).
+char(6,62784).
+char(m,62785).
+char(9,62786).
+char(9,62787).
+char(7,62788).
+char(7,62789).
+char(c,62790).
+char(m,62791).
+char(o,62792).
+char(o,62793).
+char(o,62794).
+char(p,62795).
+char(o,62796).
+char(p,62797).
+char(o,62798).
+char(1,62799).
+char(7,62800).
+char(5,62801).
+char(3,62802).
+char(m,62803).
+char(o,62804).
+char(p,62805).
+char(2,62806).
+char(9,62807).
+char(2,62808).
+char(6,62809).
+char(m,62810).
+char(9,62811).
+char(8,62812).
+char(8,62813).
+char(8,62814).
+char(p,62815).
+char(3,62816).
+char(9,62817).
+char(4,62818).
+char(6,62819).
+char(m,62820).
+char(1,62821).
+char(7,62822).
+char(0,62823).
+char(9,62824).
+char(p,62825).
+char(o,62826).
+char(m,62827).
+char(8,62828).
+char(9,62829).
+char(7,62830).
+char(8,62831).
+char(p,62832).
+char(o,62833).
+char(m,62834).
+char(6,62835).
+char(8,62836).
+char(0,62837).
+char(6,62838).
+char(p,62839).
+char(7,62840).
+char(1,62841).
+char(9,62842).
+char(3,62843).
+char(m,62844).
+char(2,62845).
+char(6,62846).
+char(2,62847).
+char(1,62848).
+char(p,62849).
+char(3,62850).
+char(7,62851).
+char(2,62852).
+char(9,62853).
+char(c,62854).
+char(m,62855).
+char(o,62856).
+char(9,62857).
+char(7,62858).
+char(5,62859).
+char(p,62860).
+char(4,62861).
+char(3,62862).
+char(2,62863).
+char(c,62864).
+char(p,62865).
+char(o,62866).
+char(m,62867).
+char(o,62868).
+char(m,62869).
+char(3,62870).
+char(5,62871).
+char(3,62872).
+char(7,62873).
+char(p,62874).
+char(o,62875).
+char(p,62876).
+char(1,62877).
+char(7,62878).
+char(9,62879).
+char(0,62880).
+char(p,62881).
+char(o,62882).
+char(p,62883).
+char(o,62884).
+char(m,62885).
+char(o,62886).
+char(p,62887).
+char(7,62888).
+char(4,62889).
+char(2,62890).
+char(p,62891).
+char(o,62892).
+char(p,62893).
+char(o,62894).
+char(m,62895).
+char(9,62896).
+char(8,62897).
+char(0,62898).
+char(7,62899).
+char(p,62900).
+char(1,62901).
+char(9,62902).
+char(8,62903).
+char(9,62904).
+char(c,62905).
+char(p,62906).
+char(o,62907).
+char(p,62908).
+char(o,62909).
+char(m,62910).
+char(o,62911).
+char(o,62912).
+char(p,62913).
+char(o,62914).
+char(o,62915).
+char(m,62916).
+char(6,62917).
+char(6,62918).
+char(2,62919).
+char(0,62920).
+char(m,62921).
+char(4,62922).
+char(6,62923).
+char(5,62924).
+char(0,62925).
+char(c,62926).
+char(c,62927).
+char(c,62928).
+char(p,62929).
+char(o,62930).
+char(o,62931).
+char(p,62932).
+char(o,62933).
+char(m,62934).
+char(o,62935).
+char(m,62936).
+char(o,62937).
+char(m,62938).
+char(o,62939).
+char(9,62940).
+char(1,62941).
+char(5,62942).
+char(p,62943).
+char(1,62944).
+char(5,62945).
+char(5,62946).
+char(1,62947).
+char(p,62948).
+char(o,62949).
+char(1,62950).
+char(1,62951).
+char(1,62952).
+char(2,62953).
+char(c,62954).
+char(m,62955).
+char(o,62956).
+char(o,62957).
+char(p,62958).
+char(o,62959).
+char(4,62960).
+char(3,62961).
+char(3,62962).
+char(8,62963).
+char(p,62964).
+char(5,62965).
+char(6,62966).
+char(7,62967).
+char(5,62968).
+char(c,62969).
+char(p,62970).
+char(3,62971).
+char(3,62972).
+char(0,62973).
+char(0,62974).
+char(m,62975).
+char(o,62976).
+char(7,62977).
+char(2,62978).
+char(7,62979).
+char(p,62980).
+char(2,62981).
+char(7,62982).
+char(6,62983).
+char(0,62984).
+char(c,62985).
+char(c,62986).
+char(m,62987).
+char(o,62988).
+char(p,62989).
+char(9,62990).
+char(3,62991).
+char(0,62992).
+char(5,62993).
+char(c,62994).
+char(c,62995).
+char(p,62996).
+char(o,62997).
+char(o,62998).
+char(7,62999).
+char(4,63000).
+char(6,63001).
+char(6,63002).
+char(c,63003).
+char(c,63004).
+char(p,63005).
+char(o,63006).
+char(p,63007).
+char(o,63008).
+char(o,63009).
+char(o,63010).
+char(p,63011).
+char(8,63012).
+char(0,63013).
+char(3,63014).
+char(0,63015).
+char(c,63016).
+char(c,63017).
+char(m,63018).
+char(5,63019).
+char(4,63020).
+char(0,63021).
+char(8,63022).
+char(p,63023).
+char(4,63024).
+char(4,63025).
+char(1,63026).
+char(0,63027).
+char(p,63028).
+char(8,63029).
+char(8,63030).
+char(2,63031).
+char(c,63032).
+char(c,63033).
+char(p,63034).
+char(o,63035).
+char(o,63036).
+char(o,63037).
+char(p,63038).
+char(o,63039).
+char(o,63040).
+char(p,63041).
+char(3,63042).
+char(6,63043).
+char(3,63044).
+char(0,63045).
+char(p,63046).
+char(o,63047).
+char(m,63048).
+char(o,63049).
+char(m,63050).
+char(o,63051).
+char(7,63052).
+char(2,63053).
+char(8,63054).
+char(4,63055).
+char(c,63056).
+char(p,63057).
+char(9,63058).
+char(5,63059).
+char(6,63060).
+char(4,63061).
+char(p,63062).
+char(o,63063).
+char(o,63064).
+char(m,63065).
+char(o,63066).
+char(m,63067).
+char(o,63068).
+char(m,63069).
+char(4,63070).
+char(9,63071).
+char(0,63072).
+char(3,63073).
+char(c,63074).
+char(p,63075).
+char(o,63076).
+char(p,63077).
+char(8,63078).
+char(7,63079).
+char(9,63080).
+char(9,63081).
+char(p,63082).
+char(o,63083).
+char(p,63084).
+char(9,63085).
+char(0,63086).
+char(9,63087).
+char(1,63088).
+char(m,63089).
+char(o,63090).
+char(o,63091).
+char(4,63092).
+char(8,63093).
+char(7,63094).
+char(3,63095).
+char(m,63096).
+char(4,63097).
+char(6,63098).
+char(9,63099).
+char(1,63100).
+char(c,63101).
+char(m,63102).
+char(9,63103).
+char(5,63104).
+char(8,63105).
+char(1,63106).
+char(c,63107).
+char(c,63108).
+char(c,63109).
+char(p,63110).
+char(o,63111).
+char(p,63112).
+char(o,63113).
+char(p,63114).
+char(o,63115).
+char(5,63116).
+char(6,63117).
+char(7,63118).
+char(7,63119).
+char(m,63120).
+char(5,63121).
+char(6,63122).
+char(2,63123).
+char(1,63124).
+char(p,63125).
+char(o,63126).
+char(p,63127).
+char(o,63128).
+char(m,63129).
+char(o,63130).
+char(2,63131).
+char(3,63132).
+char(8,63133).
+char(9,63134).
+char(m,63135).
+char(3,63136).
+char(5,63137).
+char(3,63138).
+char(4,63139).
+char(m,63140).
+char(2,63141).
+char(3,63142).
+char(8,63143).
+char(6,63144).
+char(c,63145).
+char(m,63146).
+char(o,63147).
+char(p,63148).
+char(6,63149).
+char(4,63150).
+char(7,63151).
+char(4,63152).
+char(p,63153).
+char(o,63154).
+char(m,63155).
+char(o,63156).
+char(p,63157).
+char(3,63158).
+char(7,63159).
+char(1,63160).
+char(7,63161).
+char(c,63162).
+char(c,63163).
+char(c,63164).
+char(c,63165).
+char(m,63166).
+char(8,63167).
+char(2,63168).
+char(8,63169).
+char(5,63170).
+char(c,63171).
+char(c,63172).
+char(m,63173).
+char(6,63174).
+char(8,63175).
+char(8,63176).
+char(3,63177).
+char(m,63178).
+char(7,63179).
+char(4,63180).
+char(2,63181).
+char(3,63182).
+char(p,63183).
+char(o,63184).
+char(o,63185).
+char(m,63186).
+char(8,63187).
+char(4,63188).
+char(8,63189).
+char(5,63190).
+char(c,63191).
+char(p,63192).
+char(6,63193).
+char(6,63194).
+char(3,63195).
+char(0,63196).
+char(m,63197).
+char(o,63198).
+char(o,63199).
+char(m,63200).
+char(8,63201).
+char(4,63202).
+char(4,63203).
+char(1,63204).
+char(c,63205).
+char(c,63206).
+char(m,63207).
+char(9,63208).
+char(5,63209).
+char(6,63210).
+char(6,63211).
+char(c,63212).
+char(m,63213).
+char(o,63214).
+char(p,63215).
+char(o,63216).
+char(p,63217).
+char(1,63218).
+char(6,63219).
+char(1,63220).
+char(9,63221).
+char(m,63222).
+char(9,63223).
+char(3,63224).
+char(1,63225).
+char(5,63226).
+char(p,63227).
+char(o,63228).
+char(2,63229).
+char(7,63230).
+char(5,63231).
+char(m,63232).
+char(9,63233).
+char(2,63234).
+char(5,63235).
+char(8,63236).
+char(c,63237).
+char(m,63238).
+char(o,63239).
+char(o,63240).
+char(o,63241).
+char(m,63242).
+char(8,63243).
+char(4,63244).
+char(5,63245).
+char(2,63246).
+char(c,63247).
+char(c,63248).
+char(m,63249).
+char(8,63250).
+char(4,63251).
+char(1,63252).
+char(2,63253).
+char(m,63254).
+char(o,63255).
+char(p,63256).
+char(2,63257).
+char(5,63258).
+char(c,63259).
+char(m,63260).
+char(2,63261).
+char(3,63262).
+char(5,63263).
+char(7,63264).
+char(m,63265).
+char(2,63266).
+char(2,63267).
+char(9,63268).
+char(2,63269).
+char(m,63270).
+char(o,63271).
+char(o,63272).
+char(o,63273).
+char(m,63274).
+char(7,63275).
+char(8,63276).
+char(4,63277).
+char(0,63278).
+char(m,63279).
+char(5,63280).
+char(8,63281).
+char(6,63282).
+char(0,63283).
+char(p,63284).
+char(7,63285).
+char(2,63286).
+char(6,63287).
+char(6,63288).
+char(m,63289).
+char(5,63290).
+char(7,63291).
+char(8,63292).
+char(c,63293).
+char(c,63294).
+char(m,63295).
+char(o,63296).
+char(p,63297).
+char(o,63298).
+char(m,63299).
+char(7,63300).
+char(6,63301).
+char(4,63302).
+char(0,63303).
+char(c,63304).
+char(c,63305).
+char(m,63306).
+char(7,63307).
+char(7,63308).
+char(7,63309).
+char(1,63310).
+char(p,63311).
+char(1,63312).
+char(8,63313).
+char(9,63314).
+char(1,63315).
+char(p,63316).
+char(4,63317).
+char(1,63318).
+char(5,63319).
+char(7,63320).
+char(m,63321).
+char(o,63322).
+char(m,63323).
+char(3,63324).
+char(7,63325).
+char(3,63326).
+char(5,63327).
+char(p,63328).
+char(o,63329).
+char(o,63330).
+char(p,63331).
+char(o,63332).
+char(p,63333).
+char(8,63334).
+char(1,63335).
+char(6,63336).
+char(4,63337).
+char(m,63338).
+char(5,63339).
+char(8,63340).
+char(9,63341).
+char(p,63342).
+char(o,63343).
+char(m,63344).
+char(o,63345).
+char(o,63346).
+char(m,63347).
+char(o,63348).
+char(m,63349).
+char(o,63350).
+char(m,63351).
+char(o,63352).
+char(6,63353).
+char(5,63354).
+char(9,63355).
+char(0,63356).
+char(c,63357).
+char(p,63358).
+char(4,63359).
+char(5,63360).
+char(0,63361).
+char(7,63362).
+char(p,63363).
+char(o,63364).
+char(p,63365).
+char(4,63366).
+char(2,63367).
+char(6,63368).
+char(3,63369).
+char(c,63370).
+char(m,63371).
+char(o,63372).
+char(m,63373).
+char(4,63374).
+char(7,63375).
+char(0,63376).
+char(9,63377).
+char(p,63378).
+char(o,63379).
+char(p,63380).
+char(5,63381).
+char(4,63382).
+char(9,63383).
+char(4,63384).
+char(p,63385).
+char(o,63386).
+char(5,63387).
+char(4,63388).
+char(7,63389).
+char(3,63390).
+char(p,63391).
+char(o,63392).
+char(m,63393).
+char(8,63394).
+char(7,63395).
+char(9,63396).
+char(2,63397).
+char(c,63398).
+char(p,63399).
+char(o,63400).
+char(8,63401).
+char(5,63402).
+char(5,63403).
+char(3,63404).
+char(p,63405).
+char(4,63406).
+char(3,63407).
+char(7,63408).
+char(1,63409).
+char(c,63410).
+char(c,63411).
+char(c,63412).
+char(c,63413).
+char(c,63414).
+char(c,63415).
+char(c,63416).
+char(m,63417).
+char(2,63418).
+char(5,63419).
+char(1,63420).
+char(4,63421).
+char(m,63422).
+char(o,63423).
+char(p,63424).
+char(o,63425).
+char(m,63426).
+char(o,63427).
+char(p,63428).
+char(o,63429).
+char(3,63430).
+char(9,63431).
+char(4,63432).
+char(2,63433).
+char(m,63434).
+char(o,63435).
+char(p,63436).
+char(7,63437).
+char(2,63438).
+char(2,63439).
+char(1,63440).
+char(m,63441).
+char(o,63442).
+char(4,63443).
+char(7,63444).
+char(9,63445).
+char(3,63446).
+char(c,63447).
+char(p,63448).
+char(o,63449).
+char(p,63450).
+char(5,63451).
+char(5,63452).
+char(8,63453).
+char(9,63454).
+char(p,63455).
+char(5,63456).
+char(8,63457).
+char(3,63458).
+char(3,63459).
+char(p,63460).
+char(o,63461).
+char(6,63462).
+char(5,63463).
+char(6,63464).
+char(6,63465).
+char(m,63466).
+char(3,63467).
+char(2,63468).
+char(1,63469).
+char(5,63470).
+char(p,63471).
+char(o,63472).
+char(m,63473).
+char(6,63474).
+char(9,63475).
+char(6,63476).
+char(8,63477).
+char(c,63478).
+char(c,63479).
+char(c,63480).
+char(c,63481).
+char(c,63482).
+char(c,63483).
+char(m,63484).
+char(4,63485).
+char(2,63486).
+char(8,63487).
+char(6,63488).
+char(m,63489).
+char(o,63490).
+char(o,63491).
+char(1,63492).
+char(1,63493).
+char(9,63494).
+char(7,63495).
+char(c,63496).
+char(m,63497).
+char(6,63498).
+char(0,63499).
+char(9,63500).
+char(2,63501).
+char(c,63502).
+char(p,63503).
+char(o,63504).
+char(5,63505).
+char(7,63506).
+char(5,63507).
+char(0,63508).
+char(c,63509).
+char(p,63510).
+char(o,63511).
+char(9,63512).
+char(0,63513).
+char(1,63514).
+char(2,63515).
+char(c,63516).
+char(c,63517).
+char(c,63518).
+char(p,63519).
+char(o,63520).
+char(m,63521).
+char(6,63522).
+char(6,63523).
+char(7,63524).
+char(2,63525).
+char(m,63526).
+char(o,63527).
+char(p,63528).
+char(o,63529).
+char(p,63530).
+char(7,63531).
+char(4,63532).
+char(5,63533).
+char(5,63534).
+char(c,63535).
+char(c,63536).
+char(m,63537).
+char(7,63538).
+char(6,63539).
+char(9,63540).
+char(8,63541).
+char(c,63542).
+char(p,63543).
+char(o,63544).
+char(o,63545).
+char(m,63546).
+char(5,63547).
+char(2,63548).
+char(9,63549).
+char(1,63550).
+char(p,63551).
+char(o,63552).
+char(m,63553).
+char(o,63554).
+char(p,63555).
+char(o,63556).
+char(o,63557).
+char(p,63558).
+char(1,63559).
+char(9,63560).
+char(6,63561).
+char(2,63562).
+char(c,63563).
+char(c,63564).
+char(c,63565).
+char(m,63566).
+char(o,63567).
+char(m,63568).
+char(o,63569).
+char(p,63570).
+char(o,63571).
+char(m,63572).
+char(o,63573).
+char(p,63574).
+char(o,63575).
+char(m,63576).
+char(o,63577).
+char(p,63578).
+char(4,63579).
+char(4,63580).
+char(7,63581).
+char(6,63582).
+char(c,63583).
+char(m,63584).
+char(o,63585).
+char(5,63586).
+char(2,63587).
+char(8,63588).
+char(1,63589).
+char(c,63590).
+char(m,63591).
+char(o,63592).
+char(p,63593).
+char(o,63594).
+char(p,63595).
+char(9,63596).
+char(8,63597).
+char(1,63598).
+char(3,63599).
+char(c,63600).
+char(p,63601).
+char(o,63602).
+char(p,63603).
+char(4,63604).
+char(1,63605).
+char(6,63606).
+char(0,63607).
+char(p,63608).
+char(4,63609).
+char(6,63610).
+char(9,63611).
+char(9,63612).
+char(p,63613).
+char(4,63614).
+char(6,63615).
+char(1,63616).
+char(7,63617).
+char(m,63618).
+char(3,63619).
+char(4,63620).
+char(9,63621).
+char(7,63622).
+char(m,63623).
+char(o,63624).
+char(o,63625).
+char(p,63626).
+char(o,63627).
+char(p,63628).
+char(o,63629).
+char(p,63630).
+char(o,63631).
+char(m,63632).
+char(o,63633).
+char(p,63634).
+char(2,63635).
+char(5,63636).
+char(2,63637).
+char(m,63638).
+char(o,63639).
+char(o,63640).
+char(m,63641).
+char(o,63642).
+char(m,63643).
+char(o,63644).
+char(p,63645).
+char(5,63646).
+char(8,63647).
+char(6,63648).
+char(0,63649).
+char(m,63650).
+char(o,63651).
+char(m,63652).
+char(6,63653).
+char(4,63654).
+char(5,63655).
+char(1,63656).
+char(m,63657).
+char(6,63658).
+char(7,63659).
+char(7,63660).
+char(1,63661).
+char(c,63662).
+char(c,63663).
+char(c,63664).
+char(p,63665).
+char(6,63666).
+char(6,63667).
+char(9,63668).
+char(6,63669).
+char(c,63670).
+char(p,63671).
+char(o,63672).
+char(m,63673).
+char(3,63674).
+char(0,63675).
+char(1,63676).
+char(2,63677).
+char(c,63678).
+char(c,63679).
+char(c,63680).
+char(c,63681).
+char(c,63682).
+char(c,63683).
+char(c,63684).
+char(m,63685).
+char(7,63686).
+char(4,63687).
+char(4,63688).
+char(c,63689).
+char(p,63690).
+char(1,63691).
+char(7,63692).
+char(1,63693).
+char(8,63694).
+char(m,63695).
+char(o,63696).
+char(p,63697).
+char(6,63698).
+char(2,63699).
+char(7,63700).
+char(6,63701).
+char(c,63702).
+char(c,63703).
+char(p,63704).
+char(o,63705).
+char(m,63706).
+char(2,63707).
+char(7,63708).
+char(1,63709).
+char(8,63710).
+char(c,63711).
+char(c,63712).
+char(p,63713).
+char(o,63714).
+char(o,63715).
+char(p,63716).
+char(5,63717).
+char(3,63718).
+char(8,63719).
+char(5,63720).
+char(c,63721).
+char(m,63722).
+char(6,63723).
+char(5,63724).
+char(1,63725).
+char(3,63726).
+char(c,63727).
+char(c,63728).
+char(m,63729).
+char(o,63730).
+char(p,63731).
+char(o,63732).
+char(p,63733).
+char(o,63734).
+char(p,63735).
+char(7,63736).
+char(9,63737).
+char(8,63738).
+char(9,63739).
+char(c,63740).
+char(c,63741).
+char(c,63742).
+char(p,63743).
+char(o,63744).
+char(8,63745).
+char(2,63746).
+char(1,63747).
+char(4,63748).
+char(p,63749).
+char(o,63750).
+char(5,63751).
+char(6,63752).
+char(8,63753).
+char(0,63754).
+char(c,63755).
+char(p,63756).
+char(4,63757).
+char(7,63758).
+char(0,63759).
+char(0,63760).
+char(p,63761).
+char(o,63762).
+char(o,63763).
+char(p,63764).
+char(8,63765).
+char(1,63766).
+char(1,63767).
+char(5,63768).
+char(m,63769).
+char(o,63770).
+char(p,63771).
+char(o,63772).
+char(p,63773).
+char(o,63774).
+char(m,63775).
+char(9,63776).
+char(1,63777).
+char(8,63778).
+char(1,63779).
+char(p,63780).
+char(2,63781).
+char(7,63782).
+char(3,63783).
+char(1,63784).
+char(c,63785).
+char(m,63786).
+char(o,63787).
+char(p,63788).
+char(8,63789).
+char(9,63790).
+char(1,63791).
+char(3,63792).
+char(p,63793).
+char(5,63794).
+char(2,63795).
+char(4,63796).
+char(3,63797).
+char(c,63798).
+char(p,63799).
+char(2,63800).
+char(3,63801).
+char(9,63802).
+char(0,63803).
+char(c,63804).
+char(m,63805).
+char(o,63806).
+char(3,63807).
+char(7,63808).
+char(5,63809).
+char(4,63810).
+char(p,63811).
+char(o,63812).
+char(p,63813).
+char(o,63814).
+char(m,63815).
+char(o,63816).
+char(o,63817).
+char(p,63818).
+char(5,63819).
+char(5,63820).
+char(2,63821).
+char(0,63822).
+char(p,63823).
+char(o,63824).
+char(m,63825).
+char(o,63826).
+char(p,63827).
+char(5,63828).
+char(9,63829).
+char(2,63830).
+char(8,63831).
+char(c,63832).
+char(c,63833).
+char(m,63834).
+char(o,63835).
+char(m,63836).
+char(o,63837).
+char(m,63838).
+char(o,63839).
+char(p,63840).
+char(o,63841).
+char(o,63842).
+char(1,63843).
+char(1,63844).
+char(8,63845).
+char(9,63846).
+char(p,63847).
+char(o,63848).
+char(m,63849).
+char(o,63850).
+char(o,63851).
+char(m,63852).
+char(o,63853).
+char(m,63854).
+char(4,63855).
+char(8,63856).
+char(7,63857).
+char(2,63858).
+char(c,63859).
+char(m,63860).
+char(2,63861).
+char(0,63862).
+char(8,63863).
+char(3,63864).
+char(c,63865).
+char(c,63866).
+char(m,63867).
+char(3,63868).
+char(6,63869).
+char(9,63870).
+char(7,63871).
+char(m,63872).
+char(6,63873).
+char(9,63874).
+char(6,63875).
+char(8,63876).
+char(m,63877).
+char(6,63878).
+char(4,63879).
+char(0,63880).
+char(9,63881).
+char(p,63882).
+char(o,63883).
+char(m,63884).
+char(o,63885).
+char(m,63886).
+char(o,63887).
+char(p,63888).
+char(o,63889).
+char(m,63890).
+char(o,63891).
+char(p,63892).
+char(7,63893).
+char(1,63894).
+char(5,63895).
+char(0,63896).
+char(c,63897).
+char(p,63898).
+char(o,63899).
+char(m,63900).
+char(3,63901).
+char(4,63902).
+char(3,63903).
+char(m,63904).
+char(8,63905).
+char(7,63906).
+char(2,63907).
+char(4,63908).
+char(c,63909).
+char(c,63910).
+char(c,63911).
+char(c,63912).
+char(p,63913).
+char(4,63914).
+char(3,63915).
+char(3,63916).
+char(0,63917).
+char(c,63918).
+char(p,63919).
+char(o,63920).
+char(p,63921).
+char(o,63922).
+char(m,63923).
+char(o,63924).
+char(o,63925).
+char(p,63926).
+char(o,63927).
+char(p,63928).
+char(o,63929).
+char(5,63930).
+char(2,63931).
+char(6,63932).
+char(8,63933).
+char(m,63934).
+char(5,63935).
+char(7,63936).
+char(2,63937).
+char(0,63938).
+char(m,63939).
+char(o,63940).
+char(o,63941).
+char(m,63942).
+char(6,63943).
+char(9,63944).
+char(2,63945).
+char(7,63946).
+char(p,63947).
+char(o,63948).
+char(m,63949).
+char(o,63950).
+char(o,63951).
+char(m,63952).
+char(o,63953).
+char(p,63954).
+char(7,63955).
+char(6,63956).
+char(3,63957).
+char(6,63958).
+char(m,63959).
+char(5,63960).
+char(8,63961).
+char(9,63962).
+char(6,63963).
+char(m,63964).
+char(5,63965).
+char(7,63966).
+char(7,63967).
+char(2,63968).
+char(p,63969).
+char(5,63970).
+char(4,63971).
+char(7,63972).
+char(7,63973).
+char(p,63974).
+char(8,63975).
+char(7,63976).
+char(8,63977).
+char(3,63978).
+char(m,63979).
+char(o,63980).
+char(8,63981).
+char(2,63982).
+char(5,63983).
+char(0,63984).
+char(m,63985).
+char(o,63986).
+char(m,63987).
+char(8,63988).
+char(5,63989).
+char(6,63990).
+char(3,63991).
+char(c,63992).
+char(p,63993).
+char(o,63994).
+char(m,63995).
+char(5,63996).
+char(0,63997).
+char(7,63998).
+char(6,63999).
+char(c,64000).
+char(c,64001).
+char(p,64002).
+char(9,64003).
+char(8,64004).
+char(8,64005).
+char(c,64006).
+char(c,64007).
+char(p,64008).
+char(4,64009).
+char(3,64010).
+char(6,64011).
+char(1,64012).
+char(m,64013).
+char(o,64014).
+char(2,64015).
+char(5,64016).
+char(8,64017).
+char(c,64018).
+char(c,64019).
+char(p,64020).
+char(4,64021).
+char(7,64022).
+char(5,64023).
+char(0,64024).
+char(c,64025).
+char(p,64026).
+char(o,64027).
+char(o,64028).
+char(5,64029).
+char(7,64030).
+char(0,64031).
+char(1,64032).
+char(c,64033).
+char(c,64034).
+char(p,64035).
+char(5,64036).
+char(8,64037).
+char(8,64038).
+char(4,64039).
+char(m,64040).
+char(7,64041).
+char(7,64042).
+char(3,64043).
+char(4,64044).
+char(p,64045).
+char(o,64046).
+char(p,64047).
+char(o,64048).
+char(p,64049).
+char(8,64050).
+char(4,64051).
+char(8,64052).
+char(p,64053).
+char(o,64054).
+char(m,64055).
+char(6,64056).
+char(6,64057).
+char(7,64058).
+char(0,64059).
+char(c,64060).
+char(c,64061).
+char(c,64062).
+char(c,64063).
+char(p,64064).
+char(o,64065).
+char(m,64066).
+char(o,64067).
+char(m,64068).
+char(9,64069).
+char(1,64070).
+char(9,64071).
+char(3,64072).
+char(c,64073).
+char(c,64074).
+char(c,64075).
+char(m,64076).
+char(o,64077).
+char(m,64078).
+char(2,64079).
+char(9,64080).
+char(5,64081).
+char(4,64082).
+char(c,64083).
+char(p,64084).
+char(o,64085).
+char(p,64086).
+char(o,64087).
+char(m,64088).
+char(7,64089).
+char(3,64090).
+char(4,64091).
+char(1,64092).
+char(c,64093).
+char(p,64094).
+char(6,64095).
+char(0,64096).
+char(9,64097).
+char(1,64098).
+char(m,64099).
+char(5,64100).
+char(5,64101).
+char(4,64102).
+char(0,64103).
+char(c,64104).
+char(c,64105).
+char(c,64106).
+char(m,64107).
+char(4,64108).
+char(7,64109).
+char(8,64110).
+char(4,64111).
+char(c,64112).
+char(m,64113).
+char(o,64114).
+char(m,64115).
+char(o,64116).
+char(p,64117).
+char(8,64118).
+char(8,64119).
+char(8,64120).
+char(5,64121).
+char(m,64122).
+char(4,64123).
+char(7,64124).
+char(3,64125).
+char(9,64126).
+char(c,64127).
+char(p,64128).
+char(o,64129).
+char(o,64130).
+char(p,64131).
+char(o,64132).
+char(o,64133).
+char(1,64134).
+char(9,64135).
+char(8,64136).
+char(0,64137).
+char(p,64138).
+char(1,64139).
+char(8,64140).
+char(4,64141).
+char(1,64142).
+char(c,64143).
+char(c,64144).
+char(c,64145).
+char(m,64146).
+char(5,64147).
+char(5,64148).
+char(1,64149).
+char(5,64150).
+char(p,64151).
+char(o,64152).
+char(5,64153).
+char(3,64154).
+char(1,64155).
+char(1,64156).
+char(p,64157).
+char(o,64158).
+char(p,64159).
+char(o,64160).
+char(m,64161).
+char(5,64162).
+char(9,64163).
+char(6,64164).
+char(9,64165).
+char(c,64166).
+char(c,64167).
+char(p,64168).
+char(o,64169).
+char(6,64170).
+char(2,64171).
+char(2,64172).
+char(8,64173).
+char(m,64174).
+char(o,64175).
+char(o,64176).
+char(2,64177).
+char(1,64178).
+char(7,64179).
+char(1,64180).
+char(c,64181).
+char(p,64182).
+char(4,64183).
+char(6,64184).
+char(1,64185).
+char(4,64186).
+char(c,64187).
+char(m,64188).
+char(o,64189).
+char(3,64190).
+char(6,64191).
+char(3,64192).
+char(2,64193).
+char(p,64194).
+char(o,64195).
+char(m,64196).
+char(1,64197).
+char(4,64198).
+char(2,64199).
+char(2,64200).
+char(p,64201).
+char(8,64202).
+char(0,64203).
+char(6,64204).
+char(5,64205).
+char(m,64206).
+char(9,64207).
+char(7,64208).
+char(1,64209).
+char(6,64210).
+char(c,64211).
+char(m,64212).
+char(o,64213).
+char(o,64214).
+char(m,64215).
+char(6,64216).
+char(4,64217).
+char(3,64218).
+char(2,64219).
+char(c,64220).
+char(c,64221).
+char(m,64222).
+char(o,64223).
+char(1,64224).
+char(8,64225).
+char(4,64226).
+char(5,64227).
+char(c,64228).
+char(p,64229).
+char(6,64230).
+char(2,64231).
+char(0,64232).
+char(0,64233).
+char(c,64234).
+char(c,64235).
+char(c,64236).
+char(p,64237).
+char(o,64238).
+char(m,64239).
+char(6,64240).
+char(6,64241).
+char(m,64242).
+char(o,64243).
+char(p,64244).
+char(5,64245).
+char(1,64246).
+char(6,64247).
+char(0,64248).
+char(p,64249).
+char(o,64250).
+char(p,64251).
+char(2,64252).
+char(0,64253).
+char(0,64254).
+char(4,64255).
+char(m,64256).
+char(o,64257).
+char(8,64258).
+char(0,64259).
+char(1,64260).
+char(3,64261).
+char(c,64262).
+char(p,64263).
+char(5,64264).
+char(3,64265).
+char(1,64266).
+char(1,64267).
+char(m,64268).
+char(o,64269).
+char(p,64270).
+char(7,64271).
+char(8,64272).
+char(0,64273).
+char(7,64274).
+char(c,64275).
+char(c,64276).
+char(c,64277).
+char(c,64278).
+char(c,64279).
+char(c,64280).
+char(p,64281).
+char(o,64282).
+char(1,64283).
+char(1,64284).
+char(1,64285).
+char(3,64286).
+char(p,64287).
+char(6,64288).
+char(5,64289).
+char(0,64290).
+char(1,64291).
+char(p,64292).
+char(1,64293).
+char(0,64294).
+char(7,64295).
+char(2,64296).
+char(m,64297).
+char(3,64298).
+char(3,64299).
+char(4,64300).
+char(1,64301).
+char(c,64302).
+char(m,64303).
+char(o,64304).
+char(8,64305).
+char(1,64306).
+char(7,64307).
+char(0,64308).
+char(m,64309).
+char(9,64310).
+char(7,64311).
+char(1,64312).
+char(6,64313).
+char(c,64314).
+char(c,64315).
+char(c,64316).
+char(p,64317).
+char(o,64318).
+char(m,64319).
+char(3,64320).
+char(0,64321).
+char(1,64322).
+char(8,64323).
+char(p,64324).
+char(5,64325).
+char(1,64326).
+char(1,64327).
+char(0,64328).
+char(c,64329).
+char(c,64330).
+char(c,64331).
+char(m,64332).
+char(5,64333).
+char(3,64334).
+char(5,64335).
+char(3,64336).
+char(c,64337).
+char(c,64338).
+char(m,64339).
+char(2,64340).
+char(9,64341).
+char(9,64342).
+char(2,64343).
+char(m,64344).
+char(o,64345).
+char(o,64346).
+char(5,64347).
+char(7,64348).
+char(6,64349).
+char(3,64350).
+char(c,64351).
+char(c,64352).
+char(c,64353).
+char(c,64354).
+char(c,64355).
+char(p,64356).
+char(o,64357).
+char(8,64358).
+char(1,64359).
+char(0,64360).
+char(4,64361).
+char(m,64362).
+char(o,64363).
+char(m,64364).
+char(6,64365).
+char(6,64366).
+char(1,64367).
+char(5,64368).
+char(c,64369).
+char(c,64370).
+char(c,64371).
+char(p,64372).
+char(o,64373).
+char(m,64374).
+char(o,64375).
+char(6,64376).
+char(4,64377).
+char(4,64378).
+char(2,64379).
+char(p,64380).
+char(3,64381).
+char(2,64382).
+char(2,64383).
+char(7,64384).
+char(p,64385).
+char(5,64386).
+char(8,64387).
+char(1,64388).
+char(9,64389).
+char(c,64390).
+char(c,64391).
+char(c,64392).
+char(c,64393).
+char(c,64394).
+char(c,64395).
+char(c,64396).
+char(m,64397).
+char(o,64398).
+char(1,64399).
+char(5,64400).
+char(4,64401).
+char(3,64402).
+char(p,64403).
+char(2,64404).
+char(3,64405).
+char(0,64406).
+char(4,64407).
+char(c,64408).
+char(m,64409).
+char(3,64410).
+char(6,64411).
+char(7,64412).
+char(2,64413).
+char(c,64414).
+char(p,64415).
+char(1,64416).
+char(0,64417).
+char(2,64418).
+char(8,64419).
+char(c,64420).
+char(c,64421).
+char(c,64422).
+char(c,64423).
+char(p,64424).
+char(o,64425).
+char(2,64426).
+char(2,64427).
+char(6,64428).
+char(5,64429).
+char(c,64430).
+char(m,64431).
+char(9,64432).
+char(3,64433).
+char(9,64434).
+char(1,64435).
+char(p,64436).
+char(2,64437).
+char(3,64438).
+char(5,64439).
+char(0,64440).
+char(c,64441).
+char(m,64442).
+char(9,64443).
+char(4,64444).
+char(4,64445).
+char(2,64446).
+char(p,64447).
+char(6,64448).
+char(0,64449).
+char(0,64450).
+char(2,64451).
+char(m,64452).
+char(o,64453).
+char(o,64454).
+char(p,64455).
+char(4,64456).
+char(6,64457).
+char(9,64458).
+char(3,64459).
+char(m,64460).
+char(o,64461).
+char(p,64462).
+char(9,64463).
+char(4,64464).
+char(1,64465).
+char(6,64466).
+char(c,64467).
+char(m,64468).
+char(3,64469).
+char(3,64470).
+char(1,64471).
+char(4,64472).
+char(c,64473).
+char(c,64474).
+char(c,64475).
+char(m,64476).
+char(3,64477).
+char(0,64478).
+char(2,64479).
+char(2,64480).
+char(c,64481).
+char(m,64482).
+char(o,64483).
+char(p,64484).
+char(7,64485).
+char(4,64486).
+char(2,64487).
+char(4,64488).
+char(c,64489).
+char(c,64490).
+char(p,64491).
+char(9,64492).
+char(1,64493).
+char(2,64494).
+char(4,64495).
+char(c,64496).
+char(c,64497).
+char(c,64498).
+char(m,64499).
+char(o,64500).
+char(p,64501).
+char(o,64502).
+char(m,64503).
+char(5,64504).
+char(5,64505).
+char(8,64506).
+char(7,64507).
+char(m,64508).
+char(o,64509).
+char(m,64510).
+char(3,64511).
+char(4,64512).
+char(2,64513).
+char(2,64514).
+char(c,64515).
+char(p,64516).
+char(3,64517).
+char(0,64518).
+char(1,64519).
+char(5,64520).
+char(p,64521).
+char(8,64522).
+char(6,64523).
+char(4,64524).
+char(c,64525).
+char(c,64526).
+char(c,64527).
+char(p,64528).
+char(5,64529).
+char(6,64530).
+char(2,64531).
+char(1,64532).
+char(m,64533).
+char(7,64534).
+char(0,64535).
+char(9,64536).
+char(0,64537).
+char(p,64538).
+char(o,64539).
+char(p,64540).
+char(3,64541).
+char(3,64542).
+char(4,64543).
+char(1,64544).
+char(m,64545).
+char(5,64546).
+char(7,64547).
+char(1,64548).
+char(8,64549).
+char(m,64550).
+char(8,64551).
+char(5,64552).
+char(3,64553).
+char(2,64554).
+char(c,64555).
+char(m,64556).
+char(o,64557).
+char(o,64558).
+char(m,64559).
+char(4,64560).
+char(1,64561).
+char(6,64562).
+char(3,64563).
+char(c,64564).
+char(m,64565).
+char(1,64566).
+char(0,64567).
+char(3,64568).
+char(8,64569).
+char(c,64570).
+char(c,64571).
+char(c,64572).
+char(m,64573).
+char(o,64574).
+char(m,64575).
+char(o,64576).
+char(p,64577).
+char(2,64578).
+char(5,64579).
+char(8,64580).
+char(m,64581).
+char(o,64582).
+char(p,64583).
+char(o,64584).
+char(p,64585).
+char(3,64586).
+char(1,64587).
+char(2,64588).
+char(c,64589).
+char(c,64590).
+char(c,64591).
+char(m,64592).
+char(o,64593).
+char(o,64594).
+char(m,64595).
+char(2,64596).
+char(5,64597).
+char(0,64598).
+char(5,64599).
+char(c,64600).
+char(p,64601).
+char(7,64602).
+char(2,64603).
+char(6,64604).
+char(3,64605).
+char(c,64606).
+char(m,64607).
+char(o,64608).
+char(o,64609).
+char(4,64610).
+char(3,64611).
+char(7,64612).
+char(0,64613).
+char(m,64614).
+char(o,64615).
+char(3,64616).
+char(4,64617).
+char(1,64618).
+char(1,64619).
+char(c,64620).
+char(m,64621).
+char(o,64622).
+char(p,64623).
+char(7,64624).
+char(4,64625).
+char(2,64626).
+char(m,64627).
+char(2,64628).
+char(0,64629).
+char(2,64630).
+char(5,64631).
+char(p,64632).
+char(3,64633).
+char(9,64634).
+char(8,64635).
+char(4,64636).
+char(c,64637).
+char(p,64638).
+char(4,64639).
+char(6,64640).
+char(9,64641).
+char(9,64642).
+char(c,64643).
+char(c,64644).
+char(c,64645).
+char(p,64646).
+char(o,64647).
+char(p,64648).
+char(o,64649).
+char(m,64650).
+char(o,64651).
+char(3,64652).
+char(2,64653).
+char(0,64654).
+char(8,64655).
+char(m,64656).
+char(o,64657).
+char(p,64658).
+char(5,64659).
+char(1,64660).
+char(7,64661).
+char(3,64662).
+char(p,64663).
+char(2,64664).
+char(0,64665).
+char(4,64666).
+char(3,64667).
+char(c,64668).
+char(m,64669).
+char(o,64670).
+char(m,64671).
+char(7,64672).
+char(1,64673).
+char(c,64674).
+char(c,64675).
+char(m,64676).
+char(o,64677).
+char(p,64678).
+char(o,64679).
+char(p,64680).
+char(8,64681).
+char(6,64682).
+char(8,64683).
+char(5,64684).
+char(c,64685).
+char(p,64686).
+char(5,64687).
+char(7,64688).
+char(6,64689).
+char(4,64690).
+char(m,64691).
+char(2,64692).
+char(6,64693).
+char(2,64694).
+char(9,64695).
+char(c,64696).
+char(p,64697).
+char(2,64698).
+char(0,64699).
+char(6,64700).
+char(7,64701).
+char(m,64702).
+char(o,64703).
+char(o,64704).
+char(o,64705).
+char(m,64706).
+char(6,64707).
+char(0,64708).
+char(0,64709).
+char(2,64710).
+char(c,64711).
+char(c,64712).
+char(c,64713).
+char(m,64714).
+char(o,64715).
+char(p,64716).
+char(o,64717).
+char(o,64718).
+char(m,64719).
+char(7,64720).
+char(0,64721).
+char(3,64722).
+char(2,64723).
+char(p,64724).
+char(o,64725).
+char(m,64726).
+char(o,64727).
+char(m,64728).
+char(5,64729).
+char(3,64730).
+char(8,64731).
+char(0,64732).
+char(c,64733).
+char(c,64734).
+char(m,64735).
+char(5,64736).
+char(6,64737).
+char(5,64738).
+char(8,64739).
+char(c,64740).
+char(p,64741).
+char(6,64742).
+char(8,64743).
+char(2,64744).
+char(8,64745).
+char(c,64746).
+char(c,64747).
+char(m,64748).
+char(2,64749).
+char(5,64750).
+char(2,64751).
+char(7,64752).
+char(p,64753).
+char(2,64754).
+char(8,64755).
+char(6,64756).
+char(6,64757).
+char(c,64758).
+char(m,64759).
+char(3,64760).
+char(0,64761).
+char(6,64762).
+char(0,64763).
+char(c,64764).
+char(m,64765).
+char(7,64766).
+char(1,64767).
+char(0,64768).
+char(2,64769).
+char(c,64770).
+char(p,64771).
+char(7,64772).
+char(3,64773).
+char(4,64774).
+char(4,64775).
+char(m,64776).
+char(8,64777).
+char(0,64778).
+char(2,64779).
+char(4,64780).
+char(p,64781).
+char(3,64782).
+char(0,64783).
+char(8,64784).
+char(6,64785).
+char(c,64786).
+char(m,64787).
+char(3,64788).
+char(9,64789).
+char(1,64790).
+char(p,64791).
+char(o,64792).
+char(6,64793).
+char(3,64794).
+char(6,64795).
+char(0,64796).
+char(p,64797).
+char(4,64798).
+char(1,64799).
+char(1,64800).
+char(6,64801).
+char(p,64802).
+char(o,64803).
+char(o,64804).
+char(p,64805).
+char(2,64806).
+char(4,64807).
+char(1,64808).
+char(5,64809).
+char(c,64810).
+char(p,64811).
+char(1,64812).
+char(0,64813).
+char(5,64814).
+char(5,64815).
+char(c,64816).
+char(p,64817).
+char(8,64818).
+char(3,64819).
+char(3,64820).
+char(2,64821).
+char(c,64822).
+char(c,64823).
+char(m,64824).
+char(o,64825).
+char(7,64826).
+char(6,64827).
+char(3,64828).
+char(4,64829).
+char(m,64830).
+char(3,64831).
+char(0,64832).
+char(9,64833).
+char(4,64834).
+char(c,64835).
+char(p,64836).
+char(o,64837).
+char(m,64838).
+char(o,64839).
+char(m,64840).
+char(4,64841).
+char(2,64842).
+char(7,64843).
+char(1,64844).
+char(p,64845).
+char(o,64846).
+char(p,64847).
+char(9,64848).
+char(6,64849).
+char(4,64850).
+char(6,64851).
+char(m,64852).
+char(o,64853).
+char(m,64854).
+char(o,64855).
+char(m,64856).
+char(o,64857).
+char(m,64858).
+char(o,64859).
+char(p,64860).
+char(o,64861).
+char(p,64862).
+char(o,64863).
+char(o,64864).
+char(o,64865).
+char(8,64866).
+char(7,64867).
+char(0,64868).
+char(c,64869).
+char(p,64870).
+char(3,64871).
+char(8,64872).
+char(3,64873).
+char(6,64874).
+char(m,64875).
+char(o,64876).
+char(m,64877).
+char(3,64878).
+char(3,64879).
+char(0,64880).
+char(7,64881).
+char(m,64882).
+char(5,64883).
+char(3,64884).
+char(6,64885).
+char(3,64886).
+char(c,64887).
+char(c,64888).
+char(c,64889).
+char(c,64890).
+char(c,64891).
+char(m,64892).
+char(3,64893).
+char(5,64894).
+char(4,64895).
+char(1,64896).
+char(m,64897).
+char(o,64898).
+char(p,64899).
+char(o,64900).
+char(p,64901).
+char(5,64902).
+char(0,64903).
+char(1,64904).
+char(6,64905).
+char(c,64906).
+char(c,64907).
+char(m,64908).
+char(o,64909).
+char(o,64910).
+char(o,64911).
+char(4,64912).
+char(9,64913).
+char(8,64914).
+char(5,64915).
+char(c,64916).
+char(p,64917).
+char(3,64918).
+char(4,64919).
+char(6,64920).
+char(9,64921).
+char(c,64922).
+char(m,64923).
+char(9,64924).
+char(2,64925).
+char(1,64926).
+char(5,64927).
+char(p,64928).
+char(2,64929).
+char(5,64930).
+char(1,64931).
+char(2,64932).
+char(p,64933).
+char(o,64934).
+char(1,64935).
+char(6,64936).
+char(2,64937).
+char(5,64938).
+char(c,64939).
+char(c,64940).
+char(c,64941).
+char(m,64942).
+char(4,64943).
+char(4,64944).
+char(7,64945).
+char(7,64946).
+char(c,64947).
+char(m,64948).
+char(9,64949).
+char(1,64950).
+char(6,64951).
+char(2,64952).
+char(m,64953).
+char(o,64954).
+char(p,64955).
+char(o,64956).
+char(p,64957).
+char(7,64958).
+char(4,64959).
+char(9,64960).
+char(8,64961).
+char(c,64962).
+char(m,64963).
+char(o,64964).
+char(m,64965).
+char(2,64966).
+char(9,64967).
+char(8,64968).
+char(2,64969).
+char(c,64970).
+char(m,64971).
+char(o,64972).
+char(m,64973).
+char(8,64974).
+char(8,64975).
+char(6,64976).
+char(8,64977).
+char(c,64978).
+char(m,64979).
+char(9,64980).
+char(0,64981).
+char(4,64982).
+char(4,64983).
+char(c,64984).
+char(p,64985).
+char(o,64986).
+char(m,64987).
+char(o,64988).
+char(m,64989).
+char(o,64990).
+char(4,64991).
+char(9,64992).
+char(2,64993).
+char(7,64994).
+char(m,64995).
+char(5,64996).
+char(8,64997).
+char(5,64998).
+char(3,64999).
+char(c,65000).
+char(c,65001).
+char(c,65002).
+char(p,65003).
+char(8,65004).
+char(1,65005).
+char(5,65006).
+char(9,65007).
+char(c,65008).
+char(c,65009).
+char(c,65010).
+char(m,65011).
+char(3,65012).
+char(5,65013).
+char(5,65014).
+char(8,65015).
+char(p,65016).
+char(o,65017).
+char(m,65018).
+char(o,65019).
+char(m,65020).
+char(3,65021).
+char(8,65022).
+char(1,65023).
+char(5,65024).
+char(c,65025).
+char(m,65026).
+char(8,65027).
+char(9,65028).
+char(5,65029).
+char(8,65030).
+char(c,65031).
+char(m,65032).
+char(9,65033).
+char(4,65034).
+char(6,65035).
+char(7,65036).
+char(p,65037).
+char(o,65038).
+char(9,65039).
+char(7,65040).
+char(1,65041).
+char(3,65042).
+char(p,65043).
+char(o,65044).
+char(o,65045).
+char(p,65046).
+char(5,65047).
+char(1,65048).
+char(7,65049).
+char(9,65050).
+char(p,65051).
+char(o,65052).
+char(o,65053).
+char(p,65054).
+char(2,65055).
+char(9,65056).
+char(1,65057).
+char(6,65058).
+char(c,65059).
+char(p,65060).
+char(5,65061).
+char(7,65062).
+char(0,65063).
+char(6,65064).
+char(c,65065).
+char(c,65066).
+char(c,65067).
+char(p,65068).
+char(4,65069).
+char(0,65070).
+char(9,65071).
+char(5,65072).
+char(c,65073).
+char(p,65074).
+char(o,65075).
+char(m,65076).
+char(o,65077).
+char(p,65078).
+char(1,65079).
+char(2,65080).
+char(5,65081).
+char(4,65082).
+char(c,65083).
+char(c,65084).
+char(m,65085).
+char(o,65086).
+char(m,65087).
+char(o,65088).
+char(m,65089).
+char(o,65090).
+char(p,65091).
+char(o,65092).
+char(p,65093).
+char(o,65094).
+char(m,65095).
+char(4,65096).
+char(5,65097).
+char(3,65098).
+char(9,65099).
+char(c,65100).
+char(p,65101).
+char(1,65102).
+char(8,65103).
+char(0,65104).
+char(7,65105).
+char(m,65106).
+char(3,65107).
+char(8,65108).
+char(4,65109).
+char(7,65110).
+char(m,65111).
+char(o,65112).
+char(m,65113).
+char(o,65114).
+char(p,65115).
+char(o,65116).
+char(p,65117).
+char(5,65118).
+char(4,65119).
+char(8,65120).
+char(1,65121).
+char(p,65122).
+char(o,65123).
+char(3,65124).
+char(3,65125).
+char(7,65126).
+char(3,65127).
+char(m,65128).
+char(9,65129).
+char(3,65130).
+char(0,65131).
+char(6,65132).
+char(p,65133).
+char(5,65134).
+char(4,65135).
+char(4,65136).
+char(6,65137).
+char(p,65138).
+char(4,65139).
+char(7,65140).
+char(1,65141).
+char(5,65142).
+char(p,65143).
+char(9,65144).
+char(6,65145).
+char(2,65146).
+char(5,65147).
+char(c,65148).
+char(p,65149).
+char(o,65150).
+char(7,65151).
+char(7,65152).
+char(7,65153).
+char(8,65154).
+char(p,65155).
+char(8,65156).
+char(0,65157).
+char(3,65158).
+char(2,65159).
+char(c,65160).
+char(c,65161).
+char(c,65162).
+char(c,65163).
+char(p,65164).
+char(6,65165).
+char(6,65166).
+char(4,65167).
+char(7,65168).
+char(c,65169).
+char(c,65170).
+char(m,65171).
+char(1,65172).
+char(6,65173).
+char(1,65174).
+char(5,65175).
+char(p,65176).
+char(6,65177).
+char(7,65178).
+char(3,65179).
+char(9,65180).
+char(c,65181).
+char(c,65182).
+char(p,65183).
+char(2,65184).
+char(1,65185).
+char(8,65186).
+char(1,65187).
+char(p,65188).
+char(o,65189).
+char(o,65190).
+char(p,65191).
+char(o,65192).
+char(p,65193).
+char(3,65194).
+char(4,65195).
+char(5,65196).
+char(4,65197).
+char(c,65198).
+char(c,65199).
+char(c,65200).
+char(c,65201).
+char(c,65202).
+char(c,65203).
+char(p,65204).
+char(o,65205).
+char(o,65206).
+char(p,65207).
+char(o,65208).
+char(o,65209).
+char(5,65210).
+char(9,65211).
+char(0,65212).
+char(0,65213).
+char(m,65214).
+char(o,65215).
+char(4,65216).
+char(4,65217).
+char(2,65218).
+char(5,65219).
+char(m,65220).
+char(8,65221).
+char(4,65222).
+char(4,65223).
+char(8,65224).
+char(p,65225).
+char(o,65226).
+char(9,65227).
+char(5,65228).
+char(5,65229).
+char(8,65230).
+char(c,65231).
+char(c,65232).
+char(m,65233).
+char(7,65234).
+char(1,65235).
+char(4,65236).
+char(9,65237).
+char(p,65238).
+char(o,65239).
+char(o,65240).
+char(p,65241).
+char(5,65242).
+char(9,65243).
+char(5,65244).
+char(1,65245).
+char(c,65246).
+char(p,65247).
+char(1,65248).
+char(7,65249).
+char(8,65250).
+char(m,65251).
+char(o,65252).
+char(o,65253).
+char(p,65254).
+char(o,65255).
+char(8,65256).
+char(6,65257).
+char(9,65258).
+char(9,65259).
+char(c,65260).
+char(c,65261).
+char(c,65262).
+char(c,65263).
+char(p,65264).
+char(o,65265).
+char(o,65266).
+char(p,65267).
+char(o,65268).
+char(p,65269).
+char(o,65270).
+char(m,65271).
+char(o,65272).
+char(p,65273).
+char(5,65274).
+char(0,65275).
+char(4,65276).
+char(m,65277).
+char(o,65278).
+char(m,65279).
+char(9,65280).
+char(1,65281).
+char(1,65282).
+char(6,65283).
+char(p,65284).
+char(1,65285).
+char(5,65286).
+char(8,65287).
+char(8,65288).
+char(c,65289).
+char(c,65290).
+char(c,65291).
+char(m,65292).
+char(7,65293).
+char(5,65294).
+char(7,65295).
+char(1,65296).
+char(c,65297).
+char(c,65298).
+char(c,65299).
+char(c,65300).
+char(c,65301).
+char(c,65302).
+char(c,65303).
+char(c,65304).
+char(p,65305).
+char(4,65306).
+char(7,65307).
+char(5,65308).
+char(4,65309).
+char(p,65310).
+char(8,65311).
+char(2,65312).
+char(1,65313).
+char(4,65314).
+char(p,65315).
+char(o,65316).
+char(m,65317).
+char(7,65318).
+char(4,65319).
+char(3,65320).
+char(6,65321).
+char(p,65322).
+char(5,65323).
+char(1,65324).
+char(7,65325).
+char(0,65326).
+char(p,65327).
+char(o,65328).
+char(p,65329).
+char(o,65330).
+char(o,65331).
+char(p,65332).
+char(4,65333).
+char(6,65334).
+char(8,65335).
+char(0,65336).
+char(m,65337).
+char(o,65338).
+char(m,65339).
+char(9,65340).
+char(1,65341).
+char(6,65342).
+char(0,65343).
+char(c,65344).
+char(p,65345).
+char(3,65346).
+char(6,65347).
+char(4,65348).
+char(1,65349).
+char(p,65350).
+char(o,65351).
+char(p,65352).
+char(6,65353).
+char(1,65354).
+char(6,65355).
+char(1,65356).
+char(m,65357).
+char(8,65358).
+char(0,65359).
+char(6,65360).
+char(2,65361).
+char(m,65362).
+char(8,65363).
+char(2,65364).
+char(1,65365).
+char(4,65366).
+char(p,65367).
+char(o,65368).
+char(m,65369).
+char(o,65370).
+char(p,65371).
+char(o,65372).
+char(p,65373).
+char(o,65374).
+char(p,65375).
+char(5,65376).
+char(4,65377).
+char(4,65378).
+char(6,65379).
+char(c,65380).
+char(m,65381).
+char(2,65382).
+char(3,65383).
+char(8,65384).
+char(5,65385).
+char(m,65386).
+char(5,65387).
+char(1,65388).
+char(7,65389).
+char(5,65390).
+char(p,65391).
+char(9,65392).
+char(4,65393).
+char(2,65394).
+char(7,65395).
+char(c,65396).
+char(m,65397).
+char(o,65398).
+char(m,65399).
+char(o,65400).
+char(m,65401).
+char(6,65402).
+char(1,65403).
+char(3,65404).
+char(5,65405).
+char(m,65406).
+char(3,65407).
+char(8,65408).
+char(1,65409).
+char(7,65410).
+char(m,65411).
+char(o,65412).
+char(p,65413).
+char(o,65414).
+char(m,65415).
+char(o,65416).
+char(o,65417).
+char(p,65418).
+char(3,65419).
+char(5,65420).
+char(9,65421).
+char(p,65422).
+char(o,65423).
+char(p,65424).
+char(7,65425).
+char(9,65426).
+char(5,65427).
+char(8,65428).
+char(c,65429).
+char(m,65430).
+char(5,65431).
+char(4,65432).
+char(0,65433).
+char(4,65434).
+char(c,65435).
+char(m,65436).
+char(o,65437).
+char(o,65438).
+char(4,65439).
+char(3,65440).
+char(1,65441).
+char(4,65442).
+char(p,65443).
+char(8,65444).
+char(6,65445).
+char(5,65446).
+char(1,65447).
+char(c,65448).
+char(m,65449).
+char(o,65450).
+char(m,65451).
+char(8,65452).
+char(6,65453).
+char(0,65454).
+char(4,65455).
+char(m,65456).
+char(o,65457).
+char(m,65458).
+char(1,65459).
+char(0,65460).
+char(1,65461).
+char(3,65462).
+char(p,65463).
+char(o,65464).
+char(o,65465).
+char(o,65466).
+char(m,65467).
+char(7,65468).
+char(8,65469).
+char(9,65470).
+char(5,65471).
+char(c,65472).
+char(m,65473).
+char(o,65474).
+char(m,65475).
+char(o,65476).
+char(p,65477).
+char(o,65478).
+char(p,65479).
+char(5,65480).
+char(2,65481).
+char(8,65482).
+char(8,65483).
+char(m,65484).
+char(9,65485).
+char(1,65486).
+char(6,65487).
+char(0,65488).
+char(m,65489).
+char(o,65490).
+char(m,65491).
+char(o,65492).
+char(p,65493).
+char(1,65494).
+char(6,65495).
+char(1,65496).
+char(2,65497).
+char(p,65498).
+char(8,65499).
+char(2,65500).
+char(1,65501).
+char(0,65502).
+char(p,65503).
+char(4,65504).
+char(3,65505).
+char(5,65506).
+char(5,65507).
+char(m,65508).
+char(o,65509).
+char(p,65510).
+char(8,65511).
+char(9,65512).
+char(1,65513).
+char(9,65514).
+char(c,65515).
+char(c,65516).
+char(m,65517).
+char(o,65518).
+char(p,65519).
+char(8,65520).
+char(7,65521).
+char(8,65522).
+char(6,65523).
+char(c,65524).
+char(c,65525).
+char(c,65526).
+char(c,65527).
+char(p,65528).
+char(o,65529).
+char(m,65530).
+char(1,65531).
+char(0,65532).
+char(9,65533).
+char(0,65534).
+char(c,65535).
+char(c,65536).
+char(c,65537).
+char(c,65538).
+char(c,65539).
+char(m,65540).
+char(2,65541).
+char(4,65542).
+char(c,65543).
+char(c,65544).
+char(c,65545).
+char(c,65546).
+char(c,65547).
+char(p,65548).
+char(o,65549).
+char(m,65550).
+char(3,65551).
+char(7,65552).
+char(1,65553).
+char(5,65554).
+char(c,65555).
+char(p,65556).
+char(o,65557).
+char(m,65558).
+char(4,65559).
+char(1,65560).
+char(5,65561).
+char(9,65562).
+char(c,65563).
+char(c,65564).
+char(p,65565).
+char(o,65566).
+char(5,65567).
+char(7,65568).
+char(9,65569).
+char(0,65570).
+char(c,65571).
+char(p,65572).
+char(o,65573).
+char(4,65574).
+char(7,65575).
+char(3,65576).
+char(2,65577).
+char(c,65578).
+char(c,65579).
+char(p,65580).
+char(2,65581).
+char(6,65582).
+char(1,65583).
+char(9,65584).
+char(p,65585).
+char(9,65586).
+char(4,65587).
+char(7,65588).
+char(6,65589).
+char(m,65590).
+char(o,65591).
+char(m,65592).
+char(9,65593).
+char(5,65594).
+char(3,65595).
+char(6,65596).
+char(c,65597).
+char(c,65598).
+char(m,65599).
+char(o,65600).
+char(6,65601).
+char(1,65602).
+char(0,65603).
+char(c,65604).
+char(c,65605).
+char(m,65606).
+char(6,65607).
+char(0,65608).
+char(6,65609).
+char(6,65610).
+char(c,65611).
+char(m,65612).
+char(o,65613).
+char(o,65614).
+char(m,65615).
+char(5,65616).
+char(5,65617).
+char(4,65618).
+char(4,65619).
+char(p,65620).
+char(5,65621).
+char(5,65622).
+char(7,65623).
+char(9,65624).
+char(c,65625).
+char(c,65626).
+char(m,65627).
+char(8,65628).
+char(9,65629).
+char(7,65630).
+char(c,65631).
+char(c,65632).
+char(c,65633).
+char(c,65634).
+char(m,65635).
+char(8,65636).
+char(1,65637).
+char(7,65638).
+char(5,65639).
+char(c,65640).
+char(p,65641).
+char(2,65642).
+char(2,65643).
+char(9,65644).
+char(8,65645).
+char(c,65646).
+char(c,65647).
+char(c,65648).
+char(c,65649).
+char(c,65650).
+char(m,65651).
+char(1,65652).
+char(5,65653).
+char(2,65654).
+char(5,65655).
+char(c,65656).
+char(m,65657).
+char(o,65658).
+char(m,65659).
+char(o,65660).
+char(o,65661).
+char(m,65662).
+char(9,65663).
+char(8,65664).
+char(m,65665).
+char(8,65666).
+char(7,65667).
+char(3,65668).
+char(2,65669).
+char(c,65670).
+char(c,65671).
+char(m,65672).
+char(o,65673).
+char(6,65674).
+char(2,65675).
+char(4,65676).
+char(7,65677).
+char(c,65678).
+char(p,65679).
+char(o,65680).
+char(p,65681).
+char(5,65682).
+char(9,65683).
+char(1,65684).
+char(6,65685).
+char(c,65686).
+char(m,65687).
+char(o,65688).
+char(p,65689).
+char(9,65690).
+char(3,65691).
+char(1,65692).
+char(8,65693).
+char(c,65694).
+char(p,65695).
+char(o,65696).
+char(p,65697).
+char(o,65698).
+char(m,65699).
+char(2,65700).
+char(0,65701).
+char(9,65702).
+char(9,65703).
+char(p,65704).
+char(o,65705).
+char(p,65706).
+char(4,65707).
+char(8,65708).
+char(0,65709).
+char(8,65710).
+char(p,65711).
+char(o,65712).
+char(m,65713).
+char(o,65714).
+char(p,65715).
+char(o,65716).
+char(o,65717).
+char(p,65718).
+char(o,65719).
+char(p,65720).
+char(3,65721).
+char(0,65722).
+char(9,65723).
+char(6,65724).
+char(c,65725).
+char(m,65726).
+char(o,65727).
+char(p,65728).
+char(o,65729).
+char(p,65730).
+char(o,65731).
+char(p,65732).
+char(o,65733).
+char(o,65734).
+char(m,65735).
+char(o,65736).
+char(o,65737).
+char(o,65738).
+char(3,65739).
+char(8,65740).
+char(3,65741).
+char(9,65742).
+char(m,65743).
+char(5,65744).
+char(2,65745).
+char(8,65746).
+char(5,65747).
+char(p,65748).
+char(o,65749).
+char(p,65750).
+char(1,65751).
+char(8,65752).
+char(0,65753).
+char(0,65754).
+char(m,65755).
+char(7,65756).
+char(2,65757).
+char(2,65758).
+char(6,65759).
+char(c,65760).
+char(c,65761).
+char(p,65762).
+char(4,65763).
+char(3,65764).
+char(1,65765).
+char(7,65766).
+char(p,65767).
+char(4,65768).
+char(5,65769).
+char(5,65770).
+char(2,65771).
+char(c,65772).
+char(c,65773).
+char(p,65774).
+char(o,65775).
+char(o,65776).
+char(m,65777).
+char(9,65778).
+char(9,65779).
+char(6,65780).
+char(9,65781).
+char(c,65782).
+char(c,65783).
+char(m,65784).
+char(o,65785).
+char(7,65786).
+char(6,65787).
+char(2,65788).
+char(3,65789).
+char(m,65790).
+char(o,65791).
+char(p,65792).
+char(o,65793).
+char(m,65794).
+char(o,65795).
+char(m,65796).
+char(o,65797).
+char(o,65798).
+char(p,65799).
+char(o,65800).
+char(o,65801).
+char(o,65802).
+char(6,65803).
+char(5,65804).
+char(0,65805).
+char(7,65806).
+char(c,65807).
+char(c,65808).
+char(c,65809).
+char(c,65810).
+char(m,65811).
+char(8,65812).
+char(2,65813).
+char(1,65814).
+char(0,65815).
+char(c,65816).
+char(c,65817).
+char(m,65818).
+char(6,65819).
+char(9,65820).
+char(7,65821).
+char(7,65822).
+char(p,65823).
+char(o,65824).
+char(p,65825).
+char(o,65826).
+char(6,65827).
+char(0,65828).
+char(0,65829).
+char(p,65830).
+char(o,65831).
+char(m,65832).
+char(o,65833).
+char(p,65834).
+char(o,65835).
+char(m,65836).
+char(2,65837).
+char(3,65838).
+char(1,65839).
+char(6,65840).
+char(c,65841).
+char(c,65842).
+char(c,65843).
+char(c,65844).
+char(m,65845).
+char(8,65846).
+char(4,65847).
+char(8,65848).
+char(2,65849).
+char(c,65850).
+char(c,65851).
+char(m,65852).
+char(2,65853).
+char(8,65854).
+char(3,65855).
+char(4,65856).
+char(c,65857).
+char(c,65858).
+char(p,65859).
+char(o,65860).
+char(p,65861).
+char(1,65862).
+char(1,65863).
+char(2,65864).
+char(4,65865).
+char(m,65866).
+char(9,65867).
+char(0,65868).
+char(c,65869).
+char(c,65870).
+char(c,65871).
+char(m,65872).
+char(6,65873).
+char(1,65874).
+char(6,65875).
+char(1,65876).
+char(c,65877).
+char(p,65878).
+char(3,65879).
+char(8,65880).
+char(9,65881).
+char(5,65882).
+char(c,65883).
+char(p,65884).
+char(o,65885).
+char(p,65886).
+char(9,65887).
+char(0,65888).
+char(6,65889).
+char(1,65890).
+char(c,65891).
+char(p,65892).
+char(o,65893).
+char(o,65894).
+char(p,65895).
+char(8,65896).
+char(7,65897).
+char(8,65898).
+char(5,65899).
+char(m,65900).
+char(6,65901).
+char(2,65902).
+char(7,65903).
+char(8,65904).
+char(c,65905).
+char(c,65906).
+char(m,65907).
+char(8,65908).
+char(5,65909).
+char(6,65910).
+char(5,65911).
+char(c,65912).
+char(p,65913).
+char(3,65914).
+char(9,65915).
+char(3,65916).
+char(4,65917).
+char(p,65918).
+char(1,65919).
+char(3,65920).
+char(3,65921).
+char(5,65922).
+char(c,65923).
+char(c,65924).
+char(c,65925).
+char(p,65926).
+char(o,65927).
+char(m,65928).
+char(o,65929).
+char(o,65930).
+char(3,65931).
+char(7,65932).
+char(8,65933).
+char(7,65934).
+char(c,65935).
+char(p,65936).
+char(o,65937).
+char(p,65938).
+char(o,65939).
+char(o,65940).
+char(o,65941).
+char(p,65942).
+char(6,65943).
+char(2,65944).
+char(9,65945).
+char(5,65946).
+char(c,65947).
+char(c,65948).
+char(m,65949).
+char(o,65950).
+char(m,65951).
+char(4,65952).
+char(6,65953).
+char(9,65954).
+char(3,65955).
+char(p,65956).
+char(9,65957).
+char(1,65958).
+char(0,65959).
+char(2,65960).
+char(c,65961).
+char(p,65962).
+char(o,65963).
+char(m,65964).
+char(6,65965).
+char(6,65966).
+char(0,65967).
+char(7,65968).
+char(c,65969).
+char(m,65970).
+char(9,65971).
+char(7,65972).
+char(4,65973).
+char(3,65974).
+char(c,65975).
+char(p,65976).
+char(o,65977).
+char(p,65978).
+char(4,65979).
+char(8,65980).
+char(7,65981).
+char(7,65982).
+char(p,65983).
+char(o,65984).
+char(m,65985).
+char(2,65986).
+char(7,65987).
+char(8,65988).
+char(9,65989).
+char(p,65990).
+char(o,65991).
+char(p,65992).
+char(o,65993).
+char(4,65994).
+char(1,65995).
+char(c,65996).
+char(c,65997).
+char(c,65998).
+char(p,65999).
+char(o,66000).
+char(p,66001).
+char(1,66002).
+char(9,66003).
+char(6,66004).
+char(7,66005).
+char(c,66006).
+char(c,66007).
+char(m,66008).
+char(o,66009).
+char(o,66010).
+char(p,66011).
+char(8,66012).
+char(8,66013).
+char(9,66014).
+char(6,66015).
+char(m,66016).
+char(o,66017).
+char(o,66018).
+char(m,66019).
+char(3,66020).
+char(0,66021).
+char(2,66022).
+char(0,66023).
+char(p,66024).
+char(5,66025).
+char(3,66026).
+char(7,66027).
+char(6,66028).
+char(c,66029).
+char(m,66030).
+char(3,66031).
+char(2,66032).
+char(1,66033).
+char(p,66034).
+char(1,66035).
+char(0,66036).
+char(5,66037).
+char(8,66038).
+char(p,66039).
+char(o,66040).
+char(4,66041).
+char(4,66042).
+char(2,66043).
+char(6,66044).
+char(m,66045).
+char(o,66046).
+char(1,66047).
+char(1,66048).
+char(7,66049).
+char(5,66050).
+char(c,66051).
+char(p,66052).
+char(3,66053).
+char(8,66054).
+char(9,66055).
+char(8,66056).
+char(c,66057).
+char(c,66058).
+char(p,66059).
+char(o,66060).
+char(m,66061).
+char(3,66062).
+char(5,66063).
+char(4,66064).
+char(3,66065).
+char(c,66066).
+char(p,66067).
+char(3,66068).
+char(2,66069).
+char(4,66070).
+char(9,66071).
+char(c,66072).
+char(c,66073).
+char(c,66074).
+char(m,66075).
+char(o,66076).
+char(p,66077).
+char(o,66078).
+char(m,66079).
+char(3,66080).
+char(7,66081).
+char(1,66082).
+char(9,66083).
+char(c,66084).
+char(p,66085).
+char(o,66086).
+char(o,66087).
+char(o,66088).
+char(2,66089).
+char(5,66090).
+char(2,66091).
+char(2,66092).
+char(c,66093).
+char(c,66094).
+char(c,66095).
+char(c,66096).
+char(c,66097).
+char(c,66098).
+char(c,66099).
+char(c,66100).
+char(m,66101).
+char(o,66102).
+char(o,66103).
+char(m,66104).
+char(o,66105).
+char(m,66106).
+char(9,66107).
+char(0,66108).
+char(2,66109).
+char(3,66110).
+char(p,66111).
+char(o,66112).
+char(o,66113).
+char(m,66114).
+char(8,66115).
+char(0,66116).
+char(3,66117).
+char(6,66118).
+char(c,66119).
+char(m,66120).
+char(o,66121).
+char(4,66122).
+char(5,66123).
+char(8,66124).
+char(1,66125).
+char(c,66126).
+char(c,66127).
+char(p,66128).
+char(o,66129).
+char(p,66130).
+char(4,66131).
+char(2,66132).
+char(0,66133).
+char(9,66134).
+char(m,66135).
+char(3,66136).
+char(9,66137).
+char(7,66138).
+char(3,66139).
+char(p,66140).
+char(o,66141).
+char(m,66142).
+char(9,66143).
+char(7,66144).
+char(2,66145).
+char(8,66146).
+char(c,66147).
+char(m,66148).
+char(1,66149).
+char(4,66150).
+char(0,66151).
+char(p,66152).
+char(o,66153).
+char(m,66154).
+char(o,66155).
+char(o,66156).
+char(o,66157).
+char(m,66158).
+char(8,66159).
+char(9,66160).
+char(0,66161).
+char(1,66162).
+char(c,66163).
+char(p,66164).
+char(o,66165).
+char(p,66166).
+char(5,66167).
+char(7,66168).
+char(4,66169).
+char(9,66170).
+char(c,66171).
+char(p,66172).
+char(7,66173).
+char(3,66174).
+char(1,66175).
+char(3,66176).
+char(c,66177).
+char(c,66178).
+char(m,66179).
+char(o,66180).
+char(o,66181).
+char(o,66182).
+char(m,66183).
+char(9,66184).
+char(9,66185).
+char(8,66186).
+char(p,66187).
+char(2,66188).
+char(2,66189).
+char(6,66190).
+char(4,66191).
+char(p,66192).
+char(o,66193).
+char(m,66194).
+char(3,66195).
+char(3,66196).
+char(7,66197).
+char(5,66198).
+char(m,66199).
+char(5,66200).
+char(1,66201).
+char(6,66202).
+char(1,66203).
+char(m,66204).
+char(8,66205).
+char(2,66206).
+char(8,66207).
+char(c,66208).
+char(p,66209).
+char(o,66210).
+char(m,66211).
+char(6,66212).
+char(8,66213).
+char(9,66214).
+char(7,66215).
+char(m,66216).
+char(3,66217).
+char(8,66218).
+char(5,66219).
+char(6,66220).
+char(m,66221).
+char(3,66222).
+char(6,66223).
+char(7,66224).
+char(6,66225).
+char(p,66226).
+char(9,66227).
+char(5,66228).
+char(0,66229).
+char(7,66230).
+char(m,66231).
+char(6,66232).
+char(3,66233).
+char(2,66234).
+char(9,66235).
+char(c,66236).
+char(c,66237).
+char(c,66238).
+char(c,66239).
+char(m,66240).
+char(4,66241).
+char(1,66242).
+char(3,66243).
+char(8,66244).
+char(p,66245).
+char(2,66246).
+char(6,66247).
+char(3,66248).
+char(3,66249).
+char(c,66250).
+char(c,66251).
+char(c,66252).
+char(p,66253).
+char(9,66254).
+char(7,66255).
+char(4,66256).
+char(6,66257).
+char(c,66258).
+char(c,66259).
+char(p,66260).
+char(o,66261).
+char(p,66262).
+char(1,66263).
+char(3,66264).
+char(9,66265).
+char(9,66266).
+char(c,66267).
+char(m,66268).
+char(o,66269).
+char(p,66270).
+char(4,66271).
+char(8,66272).
+char(9,66273).
+char(c,66274).
+char(m,66275).
+char(o,66276).
+char(o,66277).
+char(2,66278).
+char(1,66279).
+char(4,66280).
+char(0,66281).
+char(p,66282).
+char(4,66283).
+char(6,66284).
+char(4,66285).
+char(p,66286).
+char(o,66287).
+char(p,66288).
+char(3,66289).
+char(6,66290).
+char(8,66291).
+char(3,66292).
+char(m,66293).
+char(o,66294).
+char(p,66295).
+char(o,66296).
+char(o,66297).
+char(p,66298).
+char(5,66299).
+char(0,66300).
+char(0,66301).
+char(5,66302).
+char(c,66303).
+char(m,66304).
+char(6,66305).
+char(2,66306).
+char(2,66307).
+char(8,66308).
+char(m,66309).
+char(9,66310).
+char(1,66311).
+char(8,66312).
+char(6,66313).
+char(c,66314).
+char(m,66315).
+char(5,66316).
+char(5,66317).
+char(6,66318).
+char(1,66319).
+char(m,66320).
+char(o,66321).
+char(p,66322).
+char(o,66323).
+char(9,66324).
+char(4,66325).
+char(6,66326).
+char(1,66327).
+char(m,66328).
+char(o,66329).
+char(o,66330).
+char(7,66331).
+char(3,66332).
+char(2,66333).
+char(3,66334).
+char(m,66335).
+char(o,66336).
+char(p,66337).
+char(o,66338).
+char(p,66339).
+char(9,66340).
+char(6,66341).
+char(8,66342).
+char(8,66343).
+char(m,66344).
+char(9,66345).
+char(3,66346).
+char(6,66347).
+char(7,66348).
+char(p,66349).
+char(7,66350).
+char(5,66351).
+char(9,66352).
+char(2,66353).
+char(c,66354).
+char(c,66355).
+char(c,66356).
+char(c,66357).
+char(c,66358).
+char(c,66359).
+char(c,66360).
+char(c,66361).
+char(c,66362).
+char(m,66363).
+char(o,66364).
+char(m,66365).
+char(3,66366).
+char(5,66367).
+char(3,66368).
+char(8,66369).
+char(c,66370).
+char(c,66371).
+char(c,66372).
+char(p,66373).
+char(5,66374).
+char(5,66375).
+char(8,66376).
+char(6,66377).
+char(c,66378).
+char(m,66379).
+char(o,66380).
+char(o,66381).
+char(p,66382).
+char(o,66383).
+char(m,66384).
+char(8,66385).
+char(3,66386).
+char(0,66387).
+char(6,66388).
+char(c,66389).
+char(p,66390).
+char(o,66391).
+char(1,66392).
+char(0,66393).
+char(1,66394).
+char(c,66395).
+char(c,66396).
+char(p,66397).
+char(o,66398).
+char(m,66399).
+char(6,66400).
+char(6,66401).
+char(6,66402).
+char(5,66403).
+char(c,66404).
+char(m,66405).
+char(1,66406).
+char(3,66407).
+char(6,66408).
+char(7,66409).
+char(c,66410).
+char(p,66411).
+char(4,66412).
+char(4,66413).
+char(0,66414).
+char(7,66415).
+char(c,66416).
+char(p,66417).
+char(o,66418).
+char(m,66419).
+char(o,66420).
+char(o,66421).
+char(m,66422).
+char(o,66423).
+char(p,66424).
+char(o,66425).
+char(m,66426).
+char(9,66427).
+char(2,66428).
+char(7,66429).
+char(5,66430).
+char(m,66431).
+char(o,66432).
+char(o,66433).
+char(8,66434).
+char(6,66435).
+char(1,66436).
+char(1,66437).
+char(m,66438).
+char(o,66439).
+char(7,66440).
+char(6,66441).
+char(6,66442).
+char(8,66443).
+char(c,66444).
+char(c,66445).
+char(p,66446).
+char(2,66447).
+char(9,66448).
+char(9,66449).
+char(7,66450).
+char(c,66451).
+char(c,66452).
+char(p,66453).
+char(o,66454).
+char(p,66455).
+char(2,66456).
+char(2,66457).
+char(1,66458).
+char(p,66459).
+char(o,66460).
+char(4,66461).
+char(2,66462).
+char(7,66463).
+char(p,66464).
+char(o,66465).
+char(m,66466).
+char(1,66467).
+char(8,66468).
+char(6,66469).
+char(7,66470).
+char(c,66471).
+char(c,66472).
+char(m,66473).
+char(o,66474).
+char(4,66475).
+char(7,66476).
+char(7,66477).
+char(c,66478).
+char(m,66479).
+char(o,66480).
+char(7,66481).
+char(5,66482).
+char(9,66483).
+char(6,66484).
+char(m,66485).
+char(o,66486).
+char(m,66487).
+char(o,66488).
+char(m,66489).
+char(o,66490).
+char(o,66491).
+char(p,66492).
+char(o,66493).
+char(3,66494).
+char(0,66495).
+char(7,66496).
+char(8,66497).
+char(c,66498).
+char(m,66499).
+char(o,66500).
+char(m,66501).
+char(o,66502).
+char(m,66503).
+char(3,66504).
+char(9,66505).
+char(9,66506).
+char(0,66507).
+char(c,66508).
+char(p,66509).
+char(5,66510).
+char(4,66511).
+char(3,66512).
+char(p,66513).
+char(7,66514).
+char(9,66515).
+char(3,66516).
+char(4,66517).
+char(p,66518).
+char(2,66519).
+char(0,66520).
+char(0,66521).
+char(3,66522).
+char(m,66523).
+char(o,66524).
+char(m,66525).
+char(o,66526).
+char(m,66527).
+char(o,66528).
+char(m,66529).
+char(o,66530).
+char(1,66531).
+char(6,66532).
+char(8,66533).
+char(1,66534).
+char(c,66535).
+char(c,66536).
+char(c,66537).
+char(c,66538).
+char(c,66539).
+char(p,66540).
+char(o,66541).
+char(m,66542).
+char(o,66543).
+char(p,66544).
+char(o,66545).
+char(m,66546).
+char(o,66547).
+char(p,66548).
+char(o,66549).
+char(o,66550).
+char(o,66551).
+char(m,66552).
+char(o,66553).
+char(m,66554).
+char(o,66555).
+char(p,66556).
+char(o,66557).
+char(o,66558).
+char(m,66559).
+char(8,66560).
+char(1,66561).
+char(7,66562).
+char(7,66563).
+char(c,66564).
+char(c,66565).
+char(c,66566).
+char(m,66567).
+char(3,66568).
+char(5,66569).
+char(5,66570).
+char(5,66571).
+char(p,66572).
+char(9,66573).
+char(0,66574).
+char(7,66575).
+char(6,66576).
+char(c,66577).
+char(c,66578).
+char(m,66579).
+char(o,66580).
+char(o,66581).
+char(8,66582).
+char(6,66583).
+char(7,66584).
+char(2,66585).
+char(p,66586).
+char(o,66587).
+char(o,66588).
+char(m,66589).
+char(o,66590).
+char(m,66591).
+char(o,66592).
+char(m,66593).
+char(o,66594).
+char(m,66595).
+char(1,66596).
+char(7,66597).
+char(9,66598).
+char(p,66599).
+char(o,66600).
+char(o,66601).
+char(o,66602).
+char(m,66603).
+char(9,66604).
+char(8,66605).
+char(2,66606).
+char(7,66607).
+char(c,66608).
+char(m,66609).
+char(o,66610).
+char(m,66611).
+char(8,66612).
+char(1,66613).
+char(7,66614).
+char(0,66615).
+char(p,66616).
+char(7,66617).
+char(2,66618).
+char(2,66619).
+char(5,66620).
+char(c,66621).
+char(c,66622).
+char(p,66623).
+char(o,66624).
+char(m,66625).
+char(8,66626).
+char(4,66627).
+char(5,66628).
+char(6,66629).
+char(c,66630).
+char(c,66631).
+char(p,66632).
+char(9,66633).
+char(2,66634).
+char(3,66635).
+char(4,66636).
+char(c,66637).
+char(m,66638).
+char(2,66639).
+char(3,66640).
+char(1,66641).
+char(5,66642).
+char(m,66643).
+char(6,66644).
+char(9,66645).
+char(0,66646).
+char(1,66647).
+char(p,66648).
+char(2,66649).
+char(7,66650).
+char(9,66651).
+char(9,66652).
+char(p,66653).
+char(o,66654).
+char(p,66655).
+char(2,66656).
+char(7,66657).
+char(4,66658).
+char(3,66659).
+char(c,66660).
+char(c,66661).
+char(c,66662).
+char(m,66663).
+char(o,66664).
+char(o,66665).
+char(o,66666).
+char(m,66667).
+char(2,66668).
+char(4,66669).
+char(5,66670).
+char(m,66671).
+char(o,66672).
+char(5,66673).
+char(6,66674).
+char(2,66675).
+char(9,66676).
+char(p,66677).
+char(o,66678).
+char(m,66679).
+char(o,66680).
+char(7,66681).
+char(6,66682).
+char(0,66683).
+char(c,66684).
+char(p,66685).
+char(9,66686).
+char(6,66687).
+char(4,66688).
+char(1,66689).
+char(c,66690).
+char(m,66691).
+char(o,66692).
+char(p,66693).
+char(4,66694).
+char(9,66695).
+char(6,66696).
+char(p,66697).
+char(2,66698).
+char(3,66699).
+char(0,66700).
+char(0,66701).
+char(p,66702).
+char(4,66703).
+char(2,66704).
+char(6,66705).
+char(6,66706).
+char(p,66707).
+char(o,66708).
+char(o,66709).
+char(m,66710).
+char(o,66711).
+char(p,66712).
+char(8,66713).
+char(6,66714).
+char(0,66715).
+char(4,66716).
+char(c,66717).
+char(c,66718).
+char(c,66719).
+char(c,66720).
+char(p,66721).
+char(1,66722).
+char(7,66723).
+char(5,66724).
+char(8,66725).
+char(m,66726).
+char(o,66727).
+char(m,66728).
+char(o,66729).
+char(m,66730).
+char(3,66731).
+char(4,66732).
+char(7,66733).
+char(6,66734).
+char(c,66735).
+char(m,66736).
+char(o,66737).
+char(o,66738).
+char(p,66739).
+char(o,66740).
+char(p,66741).
+char(o,66742).
+char(p,66743).
+char(o,66744).
+char(m,66745).
+char(o,66746).
+char(o,66747).
+char(o,66748).
+char(o,66749).
+char(4,66750).
+char(8,66751).
+char(6,66752).
+char(4,66753).
+char(p,66754).
+char(o,66755).
+char(6,66756).
+char(5,66757).
+char(9,66758).
+char(0,66759).
+char(m,66760).
+char(o,66761).
+char(m,66762).
+char(5,66763).
+char(9,66764).
+char(0,66765).
+char(4,66766).
+char(m,66767).
+char(o,66768).
+char(4,66769).
+char(6,66770).
+char(6,66771).
+char(7,66772).
+char(c,66773).
+char(p,66774).
+char(o,66775).
+char(m,66776).
+char(9,66777).
+char(2,66778).
+char(8,66779).
+char(8,66780).
+char(c,66781).
+char(c,66782).
+char(c,66783).
+char(m,66784).
+char(9,66785).
+char(8,66786).
+char(7,66787).
+char(8,66788).
+char(c,66789).
+char(m,66790).
+char(5,66791).
+char(2,66792).
+char(6,66793).
+char(9,66794).
+char(m,66795).
+char(4,66796).
+char(0,66797).
+char(9,66798).
+char(2,66799).
+char(p,66800).
+char(o,66801).
+char(1,66802).
+char(7,66803).
+char(6,66804).
+char(2,66805).
+char(c,66806).
+char(m,66807).
+char(9,66808).
+char(7,66809).
+char(8,66810).
+char(8,66811).
+char(m,66812).
+char(2,66813).
+char(7,66814).
+char(8,66815).
+char(7,66816).
+char(c,66817).
+char(m,66818).
+char(o,66819).
+char(m,66820).
+char(9,66821).
+char(3,66822).
+char(9,66823).
+char(1,66824).
+char(m,66825).
+char(5,66826).
+char(1,66827).
+char(0,66828).
+char(3,66829).
+char(c,66830).
+char(p,66831).
+char(3,66832).
+char(6,66833).
+char(0,66834).
+char(6,66835).
+char(m,66836).
+char(o,66837).
+char(o,66838).
+char(m,66839).
+char(o,66840).
+char(p,66841).
+char(o,66842).
+char(5,66843).
+char(5,66844).
+char(9,66845).
+char(7,66846).
+char(c,66847).
+char(p,66848).
+char(6,66849).
+char(5,66850).
+char(7,66851).
+char(4,66852).
+char(m,66853).
+char(o,66854).
+char(p,66855).
+char(o,66856).
+char(p,66857).
+char(7,66858).
+char(3,66859).
+char(1,66860).
+char(0,66861).
+char(m,66862).
+char(o,66863).
+char(p,66864).
+char(o,66865).
+char(8,66866).
+char(4,66867).
+char(0,66868).
+char(5,66869).
+char(c,66870).
+char(m,66871).
+char(1,66872).
+char(5,66873).
+char(3,66874).
+char(1,66875).
+char(c,66876).
+char(c,66877).
+char(c,66878).
+char(c,66879).
+char(p,66880).
+char(8,66881).
+char(4,66882).
+char(1,66883).
+char(6,66884).
+char(c,66885).
+char(p,66886).
+char(o,66887).
+char(m,66888).
+char(o,66889).
+char(m,66890).
+char(o,66891).
+char(o,66892).
+char(m,66893).
+char(8,66894).
+char(5,66895).
+char(7,66896).
+char(p,66897).
+char(5,66898).
+char(1,66899).
+char(6,66900).
+char(7,66901).
+char(p,66902).
+char(9,66903).
+char(5,66904).
+char(9,66905).
+char(7,66906).
+char(m,66907).
+char(9,66908).
+char(5,66909).
+char(4,66910).
+char(1,66911).
+char(c,66912).
+char(c,66913).
+char(c,66914).
+char(p,66915).
+char(o,66916).
+char(p,66917).
+char(o,66918).
+char(m,66919).
+char(5,66920).
+char(5,66921).
+char(0,66922).
+char(0,66923).
+char(c,66924).
+char(c,66925).
+char(c,66926).
+char(p,66927).
+char(o,66928).
+char(o,66929).
+char(p,66930).
+char(6,66931).
+char(5,66932).
+char(7,66933).
+char(2,66934).
+char(c,66935).
+char(c,66936).
+char(c,66937).
+char(p,66938).
+char(7,66939).
+char(6,66940).
+char(4,66941).
+char(8,66942).
+char(c,66943).
+char(c,66944).
+char(m,66945).
+char(1,66946).
+char(6,66947).
+char(6,66948).
+char(m,66949).
+char(6,66950).
+char(7,66951).
+char(9,66952).
+char(c,66953).
+char(c,66954).
+char(c,66955).
+char(m,66956).
+char(o,66957).
+char(4,66958).
+char(3,66959).
+char(2,66960).
+char(6,66961).
+char(m,66962).
+char(o,66963).
+char(m,66964).
+char(o,66965).
+char(m,66966).
+char(4,66967).
+char(2,66968).
+char(5,66969).
+char(8,66970).
+char(c,66971).
+char(m,66972).
+char(9,66973).
+char(3,66974).
+char(4,66975).
+char(0,66976).
+char(c,66977).
+char(c,66978).
+char(p,66979).
+char(5,66980).
+char(7,66981).
+char(6,66982).
+char(1,66983).
+char(c,66984).
+char(c,66985).
+char(c,66986).
+char(c,66987).
+char(m,66988).
+char(o,66989).
+char(o,66990).
+char(p,66991).
+char(8,66992).
+char(2,66993).
+char(6,66994).
+char(3,66995).
+char(c,66996).
+char(c,66997).
+char(c,66998).
+char(p,66999).
+char(o,67000).
+char(m,67001).
+char(2,67002).
+char(5,67003).
+char(3,67004).
+char(2,67005).
+char(p,67006).
+char(o,67007).
+char(6,67008).
+char(8,67009).
+char(0,67010).
+char(3,67011).
+char(m,67012).
+char(8,67013).
+char(4,67014).
+char(5,67015).
+char(6,67016).
+char(c,67017).
+char(m,67018).
+char(7,67019).
+char(2,67020).
+char(3,67021).
+char(p,67022).
+char(4,67023).
+char(2,67024).
+char(2,67025).
+char(1,67026).
+char(p,67027).
+char(4,67028).
+char(1,67029).
+char(9,67030).
+char(7,67031).
+char(m,67032).
+char(9,67033).
+char(9,67034).
+char(7,67035).
+char(1,67036).
+char(c,67037).
+char(c,67038).
+char(c,67039).
+char(c,67040).
+char(c,67041).
+char(p,67042).
+char(8,67043).
+char(6,67044).
+char(9,67045).
+char(6,67046).
+char(c,67047).
+char(c,67048).
+char(c,67049).
+char(c,67050).
+char(p,67051).
+char(o,67052).
+char(3,67053).
+char(1,67054).
+char(9,67055).
+char(0,67056).
+char(c,67057).
+char(p,67058).
+char(o,67059).
+char(p,67060).
+char(o,67061).
+char(m,67062).
+char(o,67063).
+char(m,67064).
+char(o,67065).
+char(o,67066).
+char(m,67067).
+char(9,67068).
+char(3,67069).
+char(9,67070).
+char(2,67071).
+char(c,67072).
+char(c,67073).
+char(m,67074).
+char(o,67075).
+char(o,67076).
+char(m,67077).
+char(o,67078).
+char(5,67079).
+char(8,67080).
+char(9,67081).
+char(8,67082).
+char(c,67083).
+char(m,67084).
+char(9,67085).
+char(2,67086).
+char(4,67087).
+char(2,67088).
+char(m,67089).
+char(5,67090).
+char(9,67091).
+char(1,67092).
+char(8,67093).
+char(m,67094).
+char(o,67095).
+char(p,67096).
+char(o,67097).
+char(8,67098).
+char(8,67099).
+char(6,67100).
+char(5,67101).
+char(c,67102).
+char(p,67103).
+char(o,67104).
+char(9,67105).
+char(7,67106).
+char(7,67107).
+char(0,67108).
+char(p,67109).
+char(1,67110).
+char(4,67111).
+char(8,67112).
+char(3,67113).
+char(c,67114).
+char(c,67115).
+char(p,67116).
+char(6,67117).
+char(5,67118).
+char(7,67119).
+char(4,67120).
+char(c,67121).
+char(m,67122).
+char(6,67123).
+char(0,67124).
+char(6,67125).
+char(9,67126).
+char(c,67127).
+char(c,67128).
+char(c,67129).
+char(p,67130).
+char(o,67131).
+char(p,67132).
+char(o,67133).
+char(p,67134).
+char(o,67135).
+char(p,67136).
+char(o,67137).
+char(m,67138).
+char(3,67139).
+char(7,67140).
+char(5,67141).
+char(5,67142).
+char(c,67143).
+char(c,67144).
+char(m,67145).
+char(2,67146).
+char(0,67147).
+char(8,67148).
+char(0,67149).
+char(c,67150).
+char(c,67151).
+char(c,67152).
+char(c,67153).
+char(c,67154).
+char(p,67155).
+char(o,67156).
+char(m,67157).
+char(o,67158).
+char(7,67159).
+char(2,67160).
+char(c,67161).
+char(m,67162).
+char(o,67163).
+char(m,67164).
+char(o,67165).
+char(m,67166).
+char(6,67167).
+char(7,67168).
+char(2,67169).
+char(8,67170).
+char(c,67171).
+char(p,67172).
+char(2,67173).
+char(4,67174).
+char(5,67175).
+char(5,67176).
+char(c,67177).
+char(m,67178).
+char(o,67179).
+char(m,67180).
+char(3,67181).
+char(7,67182).
+char(2,67183).
+char(8,67184).
+char(p,67185).
+char(4,67186).
+char(3,67187).
+char(9,67188).
+char(c,67189).
+char(m,67190).
+char(1,67191).
+char(7,67192).
+char(4,67193).
+char(9,67194).
+char(c,67195).
+char(c,67196).
+char(c,67197).
+char(c,67198).
+char(m,67199).
+char(8,67200).
+char(1,67201).
+char(4,67202).
+char(1,67203).
+char(m,67204).
+char(o,67205).
+char(o,67206).
+char(p,67207).
+char(4,67208).
+char(4,67209).
+char(6,67210).
+char(5,67211).
+char(m,67212).
+char(o,67213).
+char(7,67214).
+char(4,67215).
+char(0,67216).
+char(5,67217).
+char(p,67218).
+char(o,67219).
+char(p,67220).
+char(4,67221).
+char(5,67222).
+char(5,67223).
+char(8,67224).
+char(c,67225).
+char(c,67226).
+char(c,67227).
+char(m,67228).
+char(8,67229).
+char(1,67230).
+char(0,67231).
+char(4,67232).
+char(c,67233).
+char(m,67234).
+char(o,67235).
+char(p,67236).
+char(4,67237).
+char(8,67238).
+char(6,67239).
+char(7,67240).
+char(p,67241).
+char(3,67242).
+char(1,67243).
+char(2,67244).
+char(4,67245).
+char(c,67246).
+char(p,67247).
+char(o,67248).
+char(p,67249).
+char(2,67250).
+char(2,67251).
+char(3,67252).
+char(2,67253).
+char(p,67254).
+char(o,67255).
+char(p,67256).
+char(2,67257).
+char(5,67258).
+char(8,67259).
+char(2,67260).
+char(c,67261).
+char(c,67262).
+char(c,67263).
+char(p,67264).
+char(9,67265).
+char(4,67266).
+char(2,67267).
+char(0,67268).
+char(m,67269).
+char(1,67270).
+char(8,67271).
+char(6,67272).
+char(3,67273).
+char(p,67274).
+char(5,67275).
+char(3,67276).
+char(7,67277).
+char(2,67278).
+char(c,67279).
+char(p,67280).
+char(o,67281).
+char(p,67282).
+char(3,67283).
+char(6,67284).
+char(8,67285).
+char(1,67286).
+char(c,67287).
+char(p,67288).
+char(o,67289).
+char(m,67290).
+char(o,67291).
+char(p,67292).
+char(o,67293).
+char(m,67294).
+char(4,67295).
+char(6,67296).
+char(3,67297).
+char(9,67298).
+char(c,67299).
+char(c,67300).
+char(c,67301).
+char(p,67302).
+char(3,67303).
+char(3,67304).
+char(9,67305).
+char(5,67306).
+char(c,67307).
+char(m,67308).
+char(o,67309).
+char(p,67310).
+char(6,67311).
+char(3,67312).
+char(8,67313).
+char(3,67314).
+char(c,67315).
+char(c,67316).
+char(m,67317).
+char(4,67318).
+char(6,67319).
+char(1,67320).
+char(5,67321).
+char(p,67322).
+char(o,67323).
+char(p,67324).
+char(3,67325).
+char(3,67326).
+char(8,67327).
+char(8,67328).
+char(p,67329).
+char(o,67330).
+char(p,67331).
+char(8,67332).
+char(4,67333).
+char(1,67334).
+char(m,67335).
+char(o,67336).
+char(p,67337).
+char(9,67338).
+char(0,67339).
+char(1,67340).
+char(9,67341).
+char(p,67342).
+char(o,67343).
+char(4,67344).
+char(0,67345).
+char(8,67346).
+char(4,67347).
+char(c,67348).
+char(c,67349).
+char(c,67350).
+char(c,67351).
+char(m,67352).
+char(o,67353).
+char(m,67354).
+char(7,67355).
+char(4,67356).
+char(6,67357).
+char(9,67358).
+char(c,67359).
+char(p,67360).
+char(2,67361).
+char(9,67362).
+char(5,67363).
+char(3,67364).
+char(m,67365).
+char(2,67366).
+char(4,67367).
+char(9,67368).
+char(8,67369).
+char(p,67370).
+char(o,67371).
+char(m,67372).
+char(3,67373).
+char(6,67374).
+char(2,67375).
+char(c,67376).
+char(m,67377).
+char(9,67378).
+char(6,67379).
+char(5,67380).
+char(2,67381).
+char(c,67382).
+char(p,67383).
+char(o,67384).
+char(o,67385).
+char(p,67386).
+char(7,67387).
+char(2,67388).
+char(4,67389).
+char(4,67390).
+char(c,67391).
+char(p,67392).
+char(o,67393).
+char(9,67394).
+char(1,67395).
+char(8,67396).
+char(4,67397).
+char(c,67398).
+char(c,67399).
+char(m,67400).
+char(o,67401).
+char(m,67402).
+char(o,67403).
+char(m,67404).
+char(o,67405).
+char(8,67406).
+char(3,67407).
+char(0,67408).
+char(2,67409).
+char(p,67410).
+char(o,67411).
+char(m,67412).
+char(o,67413).
+char(p,67414).
+char(1,67415).
+char(1,67416).
+char(6,67417).
+char(9,67418).
+char(c,67419).
+char(p,67420).
+char(o,67421).
+char(m,67422).
+char(1,67423).
+char(0,67424).
+char(0,67425).
+char(1,67426).
+char(m,67427).
+char(6,67428).
+char(0,67429).
+char(8,67430).
+char(2,67431).
+char(m,67432).
+char(o,67433).
+char(9,67434).
+char(0,67435).
+char(3,67436).
+char(6,67437).
+char(c,67438).
+char(c,67439).
+char(p,67440).
+char(8,67441).
+char(0,67442).
+char(6,67443).
+char(6,67444).
+char(c,67445).
+char(c,67446).
+char(m,67447).
+char(5,67448).
+char(5,67449).
+char(8,67450).
+char(7,67451).
+char(p,67452).
+char(3,67453).
+char(3,67454).
+char(7,67455).
+char(8,67456).
+char(c,67457).
+char(c,67458).
+char(p,67459).
+char(5,67460).
+char(3,67461).
+char(8,67462).
+char(2,67463).
+char(c,67464).
+char(m,67465).
+char(7,67466).
+char(5,67467).
+char(3,67468).
+char(6,67469).
+char(c,67470).
+char(p,67471).
+char(2,67472).
+char(4,67473).
+char(6,67474).
+char(6,67475).
+char(c,67476).
+char(c,67477).
+char(p,67478).
+char(2,67479).
+char(2,67480).
+char(1,67481).
+char(2,67482).
+char(p,67483).
+char(o,67484).
+char(p,67485).
+char(o,67486).
+char(p,67487).
+char(9,67488).
+char(2,67489).
+char(6,67490).
+char(8,67491).
+char(p,67492).
+char(4,67493).
+char(8,67494).
+char(1,67495).
+char(7,67496).
+char(c,67497).
+char(c,67498).
+char(m,67499).
+char(1,67500).
+char(4,67501).
+char(8,67502).
+char(0,67503).
+char(c,67504).
+char(m,67505).
+char(o,67506).
+char(o,67507).
+char(2,67508).
+char(7,67509).
+char(0,67510).
+char(2,67511).
+char(c,67512).
+char(c,67513).
+char(p,67514).
+char(o,67515).
+char(o,67516).
+char(m,67517).
+char(o,67518).
+char(p,67519).
+char(3,67520).
+char(3,67521).
+char(0,67522).
+char(3,67523).
+char(p,67524).
+char(o,67525).
+char(p,67526).
+char(3,67527).
+char(6,67528).
+char(6,67529).
+char(9,67530).
+char(c,67531).
+char(c,67532).
+char(c,67533).
+char(m,67534).
+char(5,67535).
+char(9,67536).
+char(6,67537).
+char(6,67538).
+char(c,67539).
+char(p,67540).
+char(o,67541).
+char(o,67542).
+char(o,67543).
+char(p,67544).
+char(4,67545).
+char(9,67546).
+char(8,67547).
+char(m,67548).
+char(4,67549).
+char(0,67550).
+char(1,67551).
+char(7,67552).
+char(c,67553).
+char(p,67554).
+char(o,67555).
+char(m,67556).
+char(3,67557).
+char(6,67558).
+char(6,67559).
+char(6,67560).
+char(p,67561).
+char(o,67562).
+char(p,67563).
+char(8,67564).
+char(5,67565).
+char(7,67566).
+char(7,67567).
+char(c,67568).
+char(c,67569).
+char(c,67570).
+char(p,67571).
+char(9,67572).
+char(1,67573).
+char(9,67574).
+char(6,67575).
+char(p,67576).
+char(8,67577).
+char(8,67578).
+char(2,67579).
+char(0,67580).
+char(c,67581).
+char(c,67582).
+char(m,67583).
+char(o,67584).
+char(m,67585).
+char(o,67586).
+char(3,67587).
+char(7,67588).
+char(0,67589).
+char(2,67590).
+char(c,67591).
+char(c,67592).
+char(c,67593).
+char(m,67594).
+char(7,67595).
+char(6,67596).
+char(3,67597).
+char(4,67598).
+char(m,67599).
+char(6,67600).
+char(2,67601).
+char(8,67602).
+char(c,67603).
+char(c,67604).
+char(p,67605).
+char(9,67606).
+char(4,67607).
+char(7,67608).
+char(5,67609).
+char(p,67610).
+char(o,67611).
+char(m,67612).
+char(8,67613).
+char(1,67614).
+char(6,67615).
+char(1,67616).
+char(c,67617).
+char(m,67618).
+char(5,67619).
+char(2,67620).
+char(2,67621).
+char(8,67622).
+char(c,67623).
+char(p,67624).
+char(3,67625).
+char(8,67626).
+char(3,67627).
+char(4,67628).
+char(p,67629).
+char(o,67630).
+char(m,67631).
+char(8,67632).
+char(1,67633).
+char(9,67634).
+char(2,67635).
+char(p,67636).
+char(7,67637).
+char(8,67638).
+char(6,67639).
+char(8,67640).
+char(m,67641).
+char(o,67642).
+char(o,67643).
+char(3,67644).
+char(4,67645).
+char(5,67646).
+char(c,67647).
+char(p,67648).
+char(o,67649).
+char(m,67650).
+char(o,67651).
+char(p,67652).
+char(o,67653).
+char(m,67654).
+char(4,67655).
+char(2,67656).
+char(9,67657).
+char(8,67658).
+char(m,67659).
+char(5,67660).
+char(7,67661).
+char(0,67662).
+char(9,67663).
+char(c,67664).
+char(c,67665).
+char(p,67666).
+char(1,67667).
+char(6,67668).
+char(2,67669).
+char(7,67670).
+char(p,67671).
+char(1,67672).
+char(8,67673).
+char(2,67674).
+char(0,67675).
+char(c,67676).
+char(c,67677).
+char(c,67678).
+char(c,67679).
+char(c,67680).
+char(c,67681).
+char(p,67682).
+char(1,67683).
+char(3,67684).
+char(0,67685).
+char(2,67686).
+char(m,67687).
+char(o,67688).
+char(m,67689).
+char(o,67690).
+char(p,67691).
+char(3,67692).
+char(2,67693).
+char(2,67694).
+char(6,67695).
+char(m,67696).
+char(1,67697).
+char(6,67698).
+char(6,67699).
+char(0,67700).
+char(m,67701).
+char(o,67702).
+char(1,67703).
+char(0,67704).
+char(3,67705).
+char(6,67706).
+char(c,67707).
+char(c,67708).
+char(p,67709).
+char(o,67710).
+char(p,67711).
+char(7,67712).
+char(1,67713).
+char(7,67714).
+char(7,67715).
+char(m,67716).
+char(o,67717).
+char(o,67718).
+char(p,67719).
+char(o,67720).
+char(o,67721).
+char(7,67722).
+char(9,67723).
+char(0,67724).
+char(0,67725).
+char(c,67726).
+char(m,67727).
+char(o,67728).
+char(m,67729).
+char(6,67730).
+char(8,67731).
+char(2,67732).
+char(8,67733).
+char(m,67734).
+char(o,67735).
+char(1,67736).
+char(3,67737).
+char(8,67738).
+char(6,67739).
+char(m,67740).
+char(o,67741).
+char(m,67742).
+char(o,67743).
+char(p,67744).
+char(o,67745).
+char(m,67746).
+char(3,67747).
+char(6,67748).
+char(7,67749).
+char(9,67750).
+char(c,67751).
+char(c,67752).
+char(c,67753).
+char(p,67754).
+char(o,67755).
+char(o,67756).
+char(p,67757).
+char(o,67758).
+char(o,67759).
+char(o,67760).
+char(1,67761).
+char(7,67762).
+char(3,67763).
+char(c,67764).
+char(m,67765).
+char(o,67766).
+char(m,67767).
+char(3,67768).
+char(2,67769).
+char(0,67770).
+char(6,67771).
+char(m,67772).
+char(o,67773).
+char(p,67774).
+char(o,67775).
+char(o,67776).
+char(p,67777).
+char(5,67778).
+char(3,67779).
+char(1,67780).
+char(5,67781).
+char(c,67782).
+char(m,67783).
+char(o,67784).
+char(m,67785).
+char(7,67786).
+char(7,67787).
+char(9,67788).
+char(9,67789).
+char(c,67790).
+char(c,67791).
+char(c,67792).
+char(c,67793).
+char(c,67794).
+char(c,67795).
+char(m,67796).
+char(5,67797).
+char(1,67798).
+char(7,67799).
+char(1,67800).
+char(p,67801).
+char(o,67802).
+char(p,67803).
+char(o,67804).
+char(1,67805).
+char(8,67806).
+char(0,67807).
+char(0,67808).
+char(p,67809).
+char(1,67810).
+char(1,67811).
+char(2,67812).
+char(8,67813).
+char(p,67814).
+char(7,67815).
+char(3,67816).
+char(2,67817).
+char(c,67818).
+char(c,67819).
+char(p,67820).
+char(o,67821).
+char(o,67822).
+char(o,67823).
+char(7,67824).
+char(4,67825).
+char(8,67826).
+char(6,67827).
+char(m,67828).
+char(o,67829).
+char(p,67830).
+char(6,67831).
+char(0,67832).
+char(2,67833).
+char(0,67834).
+char(c,67835).
+char(m,67836).
+char(8,67837).
+char(7,67838).
+char(4,67839).
+char(8,67840).
+char(c,67841).
+char(c,67842).
+char(c,67843).
+char(c,67844).
+char(c,67845).
+char(p,67846).
+char(5,67847).
+char(6,67848).
+char(5,67849).
+char(7,67850).
+char(p,67851).
+char(o,67852).
+char(m,67853).
+char(6,67854).
+char(7,67855).
+char(9,67856).
+char(9,67857).
+char(p,67858).
+char(2,67859).
+char(3,67860).
+char(7,67861).
+char(0,67862).
+char(m,67863).
+char(o,67864).
+char(m,67865).
+char(o,67866).
+char(m,67867).
+char(6,67868).
+char(1,67869).
+char(5,67870).
+char(8,67871).
+char(m,67872).
+char(1,67873).
+char(1,67874).
+char(2,67875).
+char(9,67876).
+char(c,67877).
+char(c,67878).
+char(p,67879).
+char(o,67880).
+char(p,67881).
+char(3,67882).
+char(5,67883).
+char(9,67884).
+char(3,67885).
+char(c,67886).
+char(c,67887).
+char(m,67888).
+char(8,67889).
+char(8,67890).
+char(8,67891).
+char(4,67892).
+char(p,67893).
+char(o,67894).
+char(o,67895).
+char(6,67896).
+char(2,67897).
+char(2,67898).
+char(m,67899).
+char(8,67900).
+char(8,67901).
+char(1,67902).
+char(8,67903).
+char(p,67904).
+char(4,67905).
+char(5,67906).
+char(1,67907).
+char(9,67908).
+char(m,67909).
+char(o,67910).
+char(p,67911).
+char(5,67912).
+char(9,67913).
+char(6,67914).
+char(2,67915).
+char(m,67916).
+char(4,67917).
+char(6,67918).
+char(7,67919).
+char(5,67920).
+char(c,67921).
+char(c,67922).
+char(c,67923).
+char(m,67924).
+char(o,67925).
+char(m,67926).
+char(7,67927).
+char(9,67928).
+char(8,67929).
+char(1,67930).
+char(p,67931).
+char(o,67932).
+char(p,67933).
+char(9,67934).
+char(9,67935).
+char(2,67936).
+char(c,67937).
+char(c,67938).
+char(p,67939).
+char(o,67940).
+char(o,67941).
+char(p,67942).
+char(o,67943).
+char(m,67944).
+char(o,67945).
+char(p,67946).
+char(2,67947).
+char(9,67948).
+char(9,67949).
+char(9,67950).
+char(p,67951).
+char(o,67952).
+char(4,67953).
+char(7,67954).
+char(5,67955).
+char(4,67956).
+char(p,67957).
+char(3,67958).
+char(8,67959).
+char(4,67960).
+char(5,67961).
+char(c,67962).
+char(m,67963).
+char(o,67964).
+char(m,67965).
+char(o,67966).
+char(m,67967).
+char(9,67968).
+char(1,67969).
+char(4,67970).
+char(6,67971).
+char(c,67972).
+char(p,67973).
+char(7,67974).
+char(3,67975).
+char(3,67976).
+char(3,67977).
+char(c,67978).
+char(p,67979).
+char(8,67980).
+char(3,67981).
+char(9,67982).
+char(8,67983).
+char(c,67984).
+char(m,67985).
+char(o,67986).
+char(p,67987).
+char(o,67988).
+char(m,67989).
+char(o,67990).
+char(m,67991).
+char(o,67992).
+char(p,67993).
+char(o,67994).
+char(m,67995).
+char(o,67996).
+char(p,67997).
+char(2,67998).
+char(5,67999).
+char(7,68000).
+char(9,68001).
+char(p,68002).
+char(o,68003).
+char(p,68004).
+char(o,68005).
+char(m,68006).
+char(o,68007).
+char(1,68008).
+char(1,68009).
+char(1,68010).
+char(1,68011).
+char(c,68012).
+char(c,68013).
+char(c,68014).
+char(p,68015).
+char(o,68016).
+char(m,68017).
+char(6,68018).
+char(3,68019).
+char(7,68020).
+char(8,68021).
+char(m,68022).
+char(o,68023).
+char(m,68024).
+char(o,68025).
+char(3,68026).
+char(6,68027).
+char(3,68028).
+char(6,68029).
+char(m,68030).
+char(o,68031).
+char(p,68032).
+char(o,68033).
+char(m,68034).
+char(o,68035).
+char(6,68036).
+char(2,68037).
+char(6,68038).
+char(0,68039).
+char(c,68040).
+char(c,68041).
+char(c,68042).
+char(m,68043).
+char(o,68044).
+char(m,68045).
+char(o,68046).
+char(p,68047).
+char(o,68048).
+char(o,68049).
+char(p,68050).
+char(o,68051).
+char(p,68052).
+char(6,68053).
+char(2,68054).
+char(1,68055).
+char(8,68056).
+char(p,68057).
+char(9,68058).
+char(3,68059).
+char(4,68060).
+char(9,68061).
+char(c,68062).
+char(c,68063).
+char(p,68064).
+char(o,68065).
+char(m,68066).
+char(7,68067).
+char(4,68068).
+char(4,68069).
+char(8,68070).
+char(c,68071).
+char(c,68072).
+char(m,68073).
+char(5,68074).
+char(6,68075).
+char(0,68076).
+char(0,68077).
+char(p,68078).
+char(o,68079).
+char(m,68080).
+char(o,68081).
+char(p,68082).
+char(o,68083).
+char(m,68084).
+char(o,68085).
+char(m,68086).
+char(2,68087).
+char(9,68088).
+char(7,68089).
+char(0,68090).
+char(c,68091).
+char(c,68092).
+char(c,68093).
+char(c,68094).
+char(c,68095).
+char(c,68096).
+char(m,68097).
+char(3,68098).
+char(4,68099).
+char(6,68100).
+char(3,68101).
+char(c,68102).
+char(p,68103).
+char(o,68104).
+char(6,68105).
+char(1,68106).
+char(7,68107).
+char(2,68108).
+char(p,68109).
+char(2,68110).
+char(9,68111).
+char(8,68112).
+char(0,68113).
+char(c,68114).
+char(p,68115).
+char(o,68116).
+char(p,68117).
+char(o,68118).
+char(p,68119).
+char(o,68120).
+char(p,68121).
+char(o,68122).
+char(m,68123).
+char(o,68124).
+char(p,68125).
+char(3,68126).
+char(7,68127).
+char(7,68128).
+char(6,68129).
+char(c,68130).
+char(c,68131).
+char(c,68132).
+char(c,68133).
+char(m,68134).
+char(6,68135).
+char(6,68136).
+char(2,68137).
+char(1,68138).
+char(m,68139).
+char(o,68140).
+char(o,68141).
+char(o,68142).
+char(o,68143).
+char(m,68144).
+char(1,68145).
+char(2,68146).
+char(7,68147).
+char(3,68148).
+char(c,68149).
+char(p,68150).
+char(o,68151).
+char(m,68152).
+char(9,68153).
+char(4,68154).
+char(7,68155).
+char(7,68156).
+char(m,68157).
+char(8,68158).
+char(6,68159).
+char(7,68160).
+char(7,68161).
+char(m,68162).
+char(4,68163).
+char(8,68164).
+char(3,68165).
+char(2,68166).
+char(m,68167).
+char(o,68168).
+char(p,68169).
+char(2,68170).
+char(7,68171).
+char(2,68172).
+char(3,68173).
+char(c,68174).
+char(m,68175).
+char(o,68176).
+char(p,68177).
+char(2,68178).
+char(7,68179).
+char(8,68180).
+char(5,68181).
+char(p,68182).
+char(o,68183).
+char(p,68184).
+char(o,68185).
+char(o,68186).
+char(m,68187).
+char(o,68188).
+char(p,68189).
+char(3,68190).
+char(2,68191).
+char(5,68192).
+char(6,68193).
+char(p,68194).
+char(o,68195).
+char(1,68196).
+char(7,68197).
+char(4,68198).
+char(p,68199).
+char(o,68200).
+char(6,68201).
+char(2,68202).
+char(9,68203).
+char(6,68204).
+char(m,68205).
+char(o,68206).
+char(m,68207).
+char(6,68208).
+char(1,68209).
+char(6,68210).
+char(2,68211).
+char(c,68212).
+char(p,68213).
+char(1,68214).
+char(2,68215).
+char(2,68216).
+char(2,68217).
+char(p,68218).
+char(o,68219).
+char(p,68220).
+char(o,68221).
+char(p,68222).
+char(6,68223).
+char(0,68224).
+char(5,68225).
+char(6,68226).
+char(c,68227).
+char(c,68228).
+char(c,68229).
+char(p,68230).
+char(1,68231).
+char(6,68232).
+char(7,68233).
+char(3,68234).
+char(c,68235).
+char(c,68236).
+char(p,68237).
+char(o,68238).
+char(m,68239).
+char(o,68240).
+char(m,68241).
+char(1,68242).
+char(2,68243).
+char(0,68244).
+char(6,68245).
+char(p,68246).
+char(5,68247).
+char(1,68248).
+char(2,68249).
+char(2,68250).
+char(c,68251).
+char(c,68252).
+char(m,68253).
+char(8,68254).
+char(9,68255).
+char(4,68256).
+char(8,68257).
+char(c,68258).
+char(p,68259).
+char(4,68260).
+char(6,68261).
+char(7,68262).
+char(5,68263).
+char(p,68264).
+char(o,68265).
+char(8,68266).
+char(2,68267).
+char(2,68268).
+char(3,68269).
+char(p,68270).
+char(3,68271).
+char(2,68272).
+char(7,68273).
+char(2,68274).
+char(p,68275).
+char(5,68276).
+char(7,68277).
+char(0,68278).
+char(p,68279).
+char(7,68280).
+char(7,68281).
+char(8,68282).
+char(8,68283).
+char(c,68284).
+char(c,68285).
+char(c,68286).
+char(c,68287).
+char(c,68288).
+char(c,68289).
+char(c,68290).
+char(m,68291).
+char(o,68292).
+char(3,68293).
+char(7,68294).
+char(7,68295).
+char(9,68296).
+char(c,68297).
+char(c,68298).
+char(c,68299).
+char(m,68300).
+char(o,68301).
+char(o,68302).
+char(p,68303).
+char(o,68304).
+char(m,68305).
+char(1,68306).
+char(8,68307).
+char(3,68308).
+char(1,68309).
+char(p,68310).
+char(2,68311).
+char(5,68312).
+char(0,68313).
+char(2,68314).
+char(c,68315).
+char(p,68316).
+char(4,68317).
+char(4,68318).
+char(8,68319).
+char(8,68320).
+char(m,68321).
+char(1,68322).
+char(0,68323).
+char(3,68324).
+char(7,68325).
+char(c,68326).
+char(m,68327).
+char(5,68328).
+char(1,68329).
+char(9,68330).
+char(5,68331).
+char(p,68332).
+char(o,68333).
+char(o,68334).
+char(m,68335).
+char(o,68336).
+char(m,68337).
+char(o,68338).
+char(2,68339).
+char(6,68340).
+char(4,68341).
+char(p,68342).
+char(o,68343).
+char(p,68344).
+char(9,68345).
+char(6,68346).
+char(8,68347).
+char(0,68348).
+char(c,68349).
+char(c,68350).
+char(c,68351).
+char(c,68352).
+char(m,68353).
+char(4,68354).
+char(8,68355).
+char(5,68356).
+char(1,68357).
+char(c,68358).
+char(p,68359).
+char(o,68360).
+char(m,68361).
+char(o,68362).
+char(5,68363).
+char(8,68364).
+char(8,68365).
+char(7,68366).
+char(p,68367).
+char(6,68368).
+char(1,68369).
+char(4,68370).
+char(2,68371).
+char(p,68372).
+char(o,68373).
+char(p,68374).
+char(o,68375).
+char(5,68376).
+char(1,68377).
+char(5,68378).
+char(2,68379).
+char(c,68380).
+char(c,68381).
+char(c,68382).
+char(c,68383).
+char(m,68384).
+char(o,68385).
+char(m,68386).
+char(9,68387).
+char(1,68388).
+char(0,68389).
+char(2,68390).
+char(p,68391).
+char(7,68392).
+char(1,68393).
+char(9,68394).
+char(3,68395).
+char(m,68396).
+char(9,68397).
+char(3,68398).
+char(4,68399).
+char(7,68400).
+char(m,68401).
+char(o,68402).
+char(p,68403).
+char(6,68404).
+char(9,68405).
+char(9,68406).
+char(5,68407).
+char(c,68408).
+char(c,68409).
+char(p,68410).
+char(6,68411).
+char(7,68412).
+char(6,68413).
+char(2,68414).
+char(p,68415).
+char(o,68416).
+char(p,68417).
+char(o,68418).
+char(5,68419).
+char(8,68420).
+char(0,68421).
+char(5,68422).
+char(c,68423).
+char(m,68424).
+char(3,68425).
+char(6,68426).
+char(1,68427).
+char(9,68428).
+char(p,68429).
+char(7,68430).
+char(0,68431).
+char(5,68432).
+char(4,68433).
+char(m,68434).
+char(o,68435).
+char(m,68436).
+char(6,68437).
+char(4,68438).
+char(9,68439).
+char(7,68440).
+char(c,68441).
+char(c,68442).
+char(c,68443).
+char(c,68444).
+char(p,68445).
+char(o,68446).
+char(9,68447).
+char(7,68448).
+char(2,68449).
+char(7,68450).
+char(m,68451).
+char(1,68452).
+char(3,68453).
+char(0,68454).
+char(9,68455).
+char(p,68456).
+char(2,68457).
+char(6,68458).
+char(7,68459).
+char(2,68460).
+char(c,68461).
+char(p,68462).
+char(9,68463).
+char(2,68464).
+char(3,68465).
+char(6,68466).
+char(p,68467).
+char(o,68468).
+char(o,68469).
+char(7,68470).
+char(0,68471).
+char(8,68472).
+char(5,68473).
+char(c,68474).
+char(c,68475).
+char(c,68476).
+char(p,68477).
+char(o,68478).
+char(m,68479).
+char(1,68480).
+char(3,68481).
+char(4,68482).
+char(9,68483).
+char(m,68484).
+char(6,68485).
+char(4,68486).
+char(9,68487).
+char(7,68488).
+char(p,68489).
+char(o,68490).
+char(p,68491).
+char(9,68492).
+char(1,68493).
+char(2,68494).
+char(9,68495).
+char(c,68496).
+char(p,68497).
+char(2,68498).
+char(1,68499).
+char(0,68500).
+char(0,68501).
+char(c,68502).
+char(c,68503).
+char(c,68504).
+char(p,68505).
+char(4,68506).
+char(1,68507).
+char(4,68508).
+char(5,68509).
+char(c,68510).
+char(p,68511).
+char(8,68512).
+char(1,68513).
+char(8,68514).
+char(p,68515).
+char(o,68516).
+char(m,68517).
+char(o,68518).
+char(p,68519).
+char(4,68520).
+char(4,68521).
+char(1,68522).
+char(5,68523).
+char(c,68524).
+char(m,68525).
+char(o,68526).
+char(p,68527).
+char(o,68528).
+char(o,68529).
+char(m,68530).
+char(o,68531).
+char(m,68532).
+char(o,68533).
+char(m,68534).
+char(o,68535).
+char(o,68536).
+char(p,68537).
+char(5,68538).
+char(4,68539).
+char(1,68540).
+char(c,68541).
+char(p,68542).
+char(o,68543).
+char(m,68544).
+char(o,68545).
+char(p,68546).
+char(o,68547).
+char(p,68548).
+char(3,68549).
+char(2,68550).
+char(0,68551).
+char(5,68552).
+char(p,68553).
+char(1,68554).
+char(9,68555).
+char(6,68556).
+char(8,68557).
+char(c,68558).
+char(c,68559).
+char(m,68560).
+char(o,68561).
+char(m,68562).
+char(o,68563).
+char(p,68564).
+char(o,68565).
+char(p,68566).
+char(o,68567).
+char(m,68568).
+char(o,68569).
+char(p,68570).
+char(7,68571).
+char(1,68572).
+char(4,68573).
+char(9,68574).
+char(c,68575).
+char(c,68576).
+char(m,68577).
+char(o,68578).
+char(6,68579).
+char(1,68580).
+char(7,68581).
+char(c,68582).
+char(c,68583).
+char(m,68584).
+char(o,68585).
+char(p,68586).
+char(o,68587).
+char(m,68588).
+char(o,68589).
+char(o,68590).
+char(9,68591).
+char(7,68592).
+char(2,68593).
+char(7,68594).
+char(p,68595).
+char(o,68596).
+char(o,68597).
+char(o,68598).
+char(p,68599).
+char(1,68600).
+char(3,68601).
+char(8,68602).
+char(4,68603).
+char(c,68604).
+char(c,68605).
+char(p,68606).
+char(6,68607).
+char(4,68608).
+char(4,68609).
+char(6,68610).
+char(m,68611).
+char(4,68612).
+char(6,68613).
+char(3,68614).
+char(c,68615).
+char(c,68616).
+char(m,68617).
+char(o,68618).
+char(m,68619).
+char(8,68620).
+char(3,68621).
+char(5,68622).
+char(7,68623).
+char(c,68624).
+char(m,68625).
+char(o,68626).
+char(p,68627).
+char(8,68628).
+char(5,68629).
+char(8,68630).
+char(3,68631).
+char(p,68632).
+char(8,68633).
+char(8,68634).
+char(2,68635).
+char(6,68636).
+char(c,68637).
+char(c,68638).
+char(c,68639).
+char(c,68640).
+char(p,68641).
+char(o,68642).
+char(o,68643).
+char(m,68644).
+char(o,68645).
+char(p,68646).
+char(9,68647).
+char(9,68648).
+char(3,68649).
+char(1,68650).
+char(m,68651).
+char(8,68652).
+char(6,68653).
+char(5,68654).
+char(3,68655).
+char(m,68656).
+char(1,68657).
+char(8,68658).
+char(3,68659).
+char(1,68660).
+char(c,68661).
+char(c,68662).
+char(c,68663).
+char(p,68664).
+char(4,68665).
+char(0,68666).
+char(1,68667).
+char(5,68668).
+char(c,68669).
+char(p,68670).
+char(o,68671).
+char(o,68672).
+char(p,68673).
+char(o,68674).
+char(m,68675).
+char(2,68676).
+char(2,68677).
+char(3,68678).
+char(c,68679).
+char(c,68680).
+char(m,68681).
+char(6,68682).
+char(1,68683).
+char(5,68684).
+char(1,68685).
+char(m,68686).
+char(o,68687).
+char(p,68688).
+char(o,68689).
+char(p,68690).
+char(o,68691).
+char(p,68692).
+char(o,68693).
+char(p,68694).
+char(7,68695).
+char(2,68696).
+char(9,68697).
+char(1,68698).
+char(c,68699).
+char(c,68700).
+char(m,68701).
+char(1,68702).
+char(4,68703).
+char(8,68704).
+char(2,68705).
+char(p,68706).
+char(o,68707).
+char(p,68708).
+char(o,68709).
+char(m,68710).
+char(4,68711).
+char(4,68712).
+char(9,68713).
+char(7,68714).
+char(m,68715).
+char(o,68716).
+char(m,68717).
+char(o,68718).
+char(p,68719).
+char(o,68720).
+char(7,68721).
+char(4,68722).
+char(9,68723).
+char(4,68724).
+char(m,68725).
+char(5,68726).
+char(6,68727).
+char(6,68728).
+char(4,68729).
+char(c,68730).
+char(m,68731).
+char(o,68732).
+char(m,68733).
+char(4,68734).
+char(9,68735).
+char(4,68736).
+char(5,68737).
+char(p,68738).
+char(o,68739).
+char(p,68740).
+char(7,68741).
+char(1,68742).
+char(8,68743).
+char(6,68744).
+char(c,68745).
+char(c,68746).
+char(c,68747).
+char(m,68748).
+char(7,68749).
+char(3,68750).
+char(4,68751).
+char(9,68752).
+char(c,68753).
+char(p,68754).
+char(7,68755).
+char(7,68756).
+char(8,68757).
+char(6,68758).
+char(c,68759).
+char(c,68760).
+char(c,68761).
+char(c,68762).
+char(c,68763).
+char(m,68764).
+char(7,68765).
+char(4,68766).
+char(2,68767).
+char(6,68768).
+char(p,68769).
+char(9,68770).
+char(5,68771).
+char(9,68772).
+char(7,68773).
+char(p,68774).
+char(7,68775).
+char(6,68776).
+char(0,68777).
+char(8,68778).
+char(m,68779).
+char(o,68780).
+char(m,68781).
+char(o,68782).
+char(o,68783).
+char(m,68784).
+char(o,68785).
+char(p,68786).
+char(9,68787).
+char(0,68788).
+char(2,68789).
+char(4,68790).
+char(c,68791).
+char(p,68792).
+char(o,68793).
+char(p,68794).
+char(9,68795).
+char(4,68796).
+char(1,68797).
+char(0,68798).
+char(m,68799).
+char(o,68800).
+char(m,68801).
+char(o,68802).
+char(3,68803).
+char(2,68804).
+char(5,68805).
+char(2,68806).
+char(c,68807).
+char(c,68808).
+char(p,68809).
+char(o,68810).
+char(2,68811).
+char(0,68812).
+char(0,68813).
+char(0,68814).
+char(p,68815).
+char(o,68816).
+char(4,68817).
+char(2,68818).
+char(4,68819).
+char(4,68820).
+char(p,68821).
+char(5,68822).
+char(1,68823).
+char(8,68824).
+char(0,68825).
+char(c,68826).
+char(m,68827).
+char(1,68828).
+char(2,68829).
+char(3,68830).
+char(4,68831).
+char(c,68832).
+char(c,68833).
+char(c,68834).
+char(m,68835).
+char(o,68836).
+char(m,68837).
+char(o,68838).
+char(p,68839).
+char(o,68840).
+char(o,68841).
+char(m,68842).
+char(6,68843).
+char(7,68844).
+char(c,68845).
+char(p,68846).
+char(o,68847).
+char(p,68848).
+char(o,68849).
+char(o,68850).
+char(o,68851).
+char(m,68852).
+char(o,68853).
+char(o,68854).
+char(m,68855).
+char(o,68856).
+char(6,68857).
+char(8,68858).
+char(9,68859).
+char(3,68860).
+char(m,68861).
+char(o,68862).
+char(p,68863).
+char(4,68864).
+char(5,68865).
+char(9,68866).
+char(2,68867).
+char(c,68868).
+char(p,68869).
+char(9,68870).
+char(6,68871).
+char(7,68872).
+char(9,68873).
+char(c,68874).
+char(m,68875).
+char(o,68876).
+char(p,68877).
+char(9,68878).
+char(8,68879).
+char(1,68880).
+char(6,68881).
+char(m,68882).
+char(6,68883).
+char(5,68884).
+char(0,68885).
+char(2,68886).
+char(m,68887).
+char(o,68888).
+char(p,68889).
+char(7,68890).
+char(0,68891).
+char(9,68892).
+char(8,68893).
+char(c,68894).
+char(c,68895).
+char(p,68896).
+char(o,68897).
+char(p,68898).
+char(3,68899).
+char(2,68900).
+char(8,68901).
+char(8,68902).
+char(p,68903).
+char(o,68904).
+char(p,68905).
+char(6,68906).
+char(1,68907).
+char(0,68908).
+char(6,68909).
+char(c,68910).
+char(p,68911).
+char(4,68912).
+char(2,68913).
+char(0,68914).
+char(4,68915).
+char(m,68916).
+char(o,68917).
+char(m,68918).
+char(2,68919).
+char(1,68920).
+char(7,68921).
+char(4,68922).
+char(c,68923).
+char(m,68924).
+char(4,68925).
+char(6,68926).
+char(1,68927).
+char(2,68928).
+char(c,68929).
+char(c,68930).
+char(c,68931).
+char(m,68932).
+char(6,68933).
+char(8,68934).
+char(8,68935).
+char(5,68936).
+char(m,68937).
+char(o,68938).
+char(o,68939).
+char(1,68940).
+char(5,68941).
+char(0,68942).
+char(5,68943).
+char(m,68944).
+char(o,68945).
+char(p,68946).
+char(o,68947).
+char(m,68948).
+char(1,68949).
+char(3,68950).
+char(2,68951).
+char(7,68952).
+char(c,68953).
+char(c,68954).
+char(c,68955).
+char(c,68956).
+char(c,68957).
+char(c,68958).
+char(c,68959).
+char(c,68960).
+char(c,68961).
+char(m,68962).
+char(o,68963).
+char(m,68964).
+char(o,68965).
+char(o,68966).
+char(p,68967).
+char(5,68968).
+char(5,68969).
+char(9,68970).
+char(1,68971).
+char(m,68972).
+char(o,68973).
+char(p,68974).
+char(2,68975).
+char(1,68976).
+char(6,68977).
+char(0,68978).
+char(m,68979).
+char(o,68980).
+char(m,68981).
+char(3,68982).
+char(3,68983).
+char(1,68984).
+char(6,68985).
+char(p,68986).
+char(o,68987).
+char(p,68988).
+char(4,68989).
+char(3,68990).
+char(2,68991).
+char(c,68992).
+char(c,68993).
+char(c,68994).
+char(c,68995).
+char(m,68996).
+char(o,68997).
+char(m,68998).
+char(o,68999).
+char(p,69000).
+char(o,69001).
+char(1,69002).
+char(7,69003).
+char(3,69004).
+char(7,69005).
+char(m,69006).
+char(7,69007).
+char(7,69008).
+char(6,69009).
+char(2,69010).
+char(m,69011).
+char(o,69012).
+char(p,69013).
+char(4,69014).
+char(8,69015).
+char(4,69016).
+char(9,69017).
+char(p,69018).
+char(6,69019).
+char(7,69020).
+char(6,69021).
+char(3,69022).
+char(c,69023).
+char(c,69024).
+char(m,69025).
+char(o,69026).
+char(p,69027).
+char(1,69028).
+char(5,69029).
+char(7,69030).
+char(5,69031).
+char(p,69032).
+char(o,69033).
+char(p,69034).
+char(o,69035).
+char(p,69036).
+char(o,69037).
+char(m,69038).
+char(3,69039).
+char(9,69040).
+char(9,69041).
+char(4,69042).
+char(c,69043).
+char(m,69044).
+char(3,69045).
+char(8,69046).
+char(9,69047).
+char(8,69048).
+char(m,69049).
+char(o,69050).
+char(p,69051).
+char(7,69052).
+char(0,69053).
+char(1,69054).
+char(1,69055).
+char(c,69056).
+char(m,69057).
+char(4,69058).
+char(0,69059).
+char(7,69060).
+char(1,69061).
+char(c,69062).
+char(c,69063).
+char(p,69064).
+char(4,69065).
+char(0,69066).
+char(2,69067).
+char(9,69068).
+char(c,69069).
+char(c,69070).
+char(m,69071).
+char(o,69072).
+char(9,69073).
+char(3,69074).
+char(8,69075).
+char(4,69076).
+char(c,69077).
+char(c,69078).
+char(c,69079).
+char(c,69080).
+char(c,69081).
+char(c,69082).
+char(p,69083).
+char(5,69084).
+char(6,69085).
+char(0,69086).
+char(2,69087).
+char(p,69088).
+char(o,69089).
+char(o,69090).
+char(m,69091).
+char(o,69092).
+char(p,69093).
+char(8,69094).
+char(5,69095).
+char(5,69096).
+char(1,69097).
+char(p,69098).
+char(o,69099).
+char(p,69100).
+char(o,69101).
+char(p,69102).
+char(6,69103).
+char(3,69104).
+char(9,69105).
+char(8,69106).
+char(m,69107).
+char(o,69108).
+char(o,69109).
+char(m,69110).
+char(o,69111).
+char(m,69112).
+char(o,69113).
+char(m,69114).
+char(o,69115).
+char(8,69116).
+char(4,69117).
+char(6,69118).
+char(8,69119).
+char(p,69120).
+char(o,69121).
+char(m,69122).
+char(o,69123).
+char(o,69124).
+char(m,69125).
+char(o,69126).
+char(2,69127).
+char(4,69128).
+char(8,69129).
+char(7,69130).
+char(c,69131).
+char(p,69132).
+char(9,69133).
+char(6,69134).
+char(1,69135).
+char(c,69136).
+char(m,69137).
+char(9,69138).
+char(4,69139).
+char(6,69140).
+char(3,69141).
+char(m,69142).
+char(o,69143).
+char(2,69144).
+char(5,69145).
+char(2,69146).
+char(5,69147).
+char(m,69148).
+char(o,69149).
+char(m,69150).
+char(7,69151).
+char(7,69152).
+char(4,69153).
+char(5,69154).
+char(c,69155).
+char(p,69156).
+char(o,69157).
+char(m,69158).
+char(6,69159).
+char(8,69160).
+char(6,69161).
+char(7,69162).
+char(c,69163).
+char(p,69164).
+char(6,69165).
+char(9,69166).
+char(9,69167).
+char(8,69168).
+char(c,69169).
+char(c,69170).
+char(c,69171).
+char(c,69172).
+char(c,69173).
+char(c,69174).
+char(c,69175).
+char(m,69176).
+char(1,69177).
+char(1,69178).
+char(1,69179).
+char(9,69180).
+char(p,69181).
+char(8,69182).
+char(0,69183).
+char(4,69184).
+char(9,69185).
+char(m,69186).
+char(7,69187).
+char(0,69188).
+char(5,69189).
+char(2,69190).
+char(m,69191).
+char(9,69192).
+char(2,69193).
+char(7,69194).
+char(8,69195).
+char(c,69196).
+char(p,69197).
+char(o,69198).
+char(p,69199).
+char(1,69200).
+char(6,69201).
+char(8,69202).
+char(m,69203).
+char(6,69204).
+char(1,69205).
+char(6,69206).
+char(9,69207).
+char(m,69208).
+char(7,69209).
+char(3,69210).
+char(6,69211).
+char(9,69212).
+char(c,69213).
+char(m,69214).
+char(1,69215).
+char(2,69216).
+char(8,69217).
+char(5,69218).
+char(m,69219).
+char(2,69220).
+char(8,69221).
+char(5,69222).
+char(5,69223).
+char(c,69224).
+char(p,69225).
+char(o,69226).
+char(2,69227).
+char(6,69228).
+char(9,69229).
+char(1,69230).
+char(p,69231).
+char(o,69232).
+char(m,69233).
+char(o,69234).
+char(p,69235).
+char(7,69236).
+char(4,69237).
+char(7,69238).
+char(6,69239).
+char(c,69240).
+char(p,69241).
+char(o,69242).
+char(o,69243).
+char(m,69244).
+char(7,69245).
+char(0,69246).
+char(4,69247).
+char(2,69248).
+char(p,69249).
+char(o,69250).
+char(5,69251).
+char(5,69252).
+char(2,69253).
+char(7,69254).
+char(m,69255).
+char(o,69256).
+char(m,69257).
+char(9,69258).
+char(9,69259).
+char(c,69260).
+char(c,69261).
+char(p,69262).
+char(8,69263).
+char(8,69264).
+char(3,69265).
+char(2,69266).
+char(m,69267).
+char(1,69268).
+char(0,69269).
+char(3,69270).
+char(p,69271).
+char(2,69272).
+char(4,69273).
+char(6,69274).
+char(0,69275).
+char(m,69276).
+char(o,69277).
+char(p,69278).
+char(o,69279).
+char(m,69280).
+char(7,69281).
+char(7,69282).
+char(4,69283).
+char(0,69284).
+char(p,69285).
+char(o,69286).
+char(4,69287).
+char(5,69288).
+char(8,69289).
+char(m,69290).
+char(o,69291).
+char(m,69292).
+char(o,69293).
+char(m,69294).
+char(3,69295).
+char(1,69296).
+char(4,69297).
+char(c,69298).
+char(p,69299).
+char(o,69300).
+char(m,69301).
+char(o,69302).
+char(p,69303).
+char(5,69304).
+char(6,69305).
+char(4,69306).
+char(9,69307).
+char(m,69308).
+char(o,69309).
+char(8,69310).
+char(0,69311).
+char(6,69312).
+char(1,69313).
+char(m,69314).
+char(o,69315).
+char(m,69316).
+char(o,69317).
+char(m,69318).
+char(9,69319).
+char(2,69320).
+char(4,69321).
+char(9,69322).
+char(m,69323).
+char(o,69324).
+char(m,69325).
+char(o,69326).
+char(6,69327).
+char(4,69328).
+char(1,69329).
+char(4,69330).
+char(c,69331).
+char(c,69332).
+char(c,69333).
+char(m,69334).
+char(3,69335).
+char(8,69336).
+char(6,69337).
+char(6,69338).
+char(c,69339).
+char(c,69340).
+char(c,69341).
+char(p,69342).
+char(o,69343).
+char(p,69344).
+char(5,69345).
+char(8,69346).
+char(8,69347).
+char(3,69348).
+char(p,69349).
+char(o,69350).
+char(m,69351).
+char(o,69352).
+char(o,69353).
+char(o,69354).
+char(p,69355).
+char(6,69356).
+char(5,69357).
+char(3,69358).
+char(4,69359).
+char(c,69360).
+char(p,69361).
+char(6,69362).
+char(5,69363).
+char(2,69364).
+char(5,69365).
+char(p,69366).
+char(o,69367).
+char(p,69368).
+char(o,69369).
+char(m,69370).
+char(3,69371).
+char(5,69372).
+char(1,69373).
+char(1,69374).
+char(c,69375).
+char(m,69376).
+char(o,69377).
+char(o,69378).
+char(p,69379).
+char(o,69380).
+char(m,69381).
+char(o,69382).
+char(m,69383).
+char(o,69384).
+char(m,69385).
+char(2,69386).
+char(9,69387).
+char(3,69388).
+char(3,69389).
+char(m,69390).
+char(o,69391).
+char(p,69392).
+char(o,69393).
+char(m,69394).
+char(6,69395).
+char(4,69396).
+char(7,69397).
+char(6,69398).
+char(c,69399).
+char(p,69400).
+char(6,69401).
+char(1,69402).
+char(7,69403).
+char(2,69404).
+char(c,69405).
+char(c,69406).
+char(c,69407).
+char(c,69408).
+char(c,69409).
+char(c,69410).
+char(m,69411).
+char(o,69412).
+char(m,69413).
+char(o,69414).
+char(p,69415).
+char(5,69416).
+char(7,69417).
+char(3,69418).
+char(9,69419).
+char(c,69420).
+char(m,69421).
+char(o,69422).
+char(p,69423).
+char(o,69424).
+char(p,69425).
+char(4,69426).
+char(8,69427).
+char(5,69428).
+char(0,69429).
+char(m,69430).
+char(o,69431).
+char(8,69432).
+char(4,69433).
+char(7,69434).
+char(1,69435).
+char(c,69436).
+char(c,69437).
+char(c,69438).
+char(m,69439).
+char(o,69440).
+char(o,69441).
+char(m,69442).
+char(o,69443).
+char(m,69444).
+char(o,69445).
+char(1,69446).
+char(9,69447).
+char(1,69448).
+char(5,69449).
+char(m,69450).
+char(7,69451).
+char(9,69452).
+char(4,69453).
+char(c,69454).
+char(p,69455).
+char(2,69456).
+char(2,69457).
+char(5,69458).
+char(c,69459).
+char(p,69460).
+char(9,69461).
+char(7,69462).
+char(0,69463).
+char(4,69464).
+char(p,69465).
+char(o,69466).
+char(m,69467).
+char(o,69468).
+char(p,69469).
+char(o,69470).
+char(m,69471).
+char(o,69472).
+char(o,69473).
+char(m,69474).
+char(o,69475).
+char(m,69476).
+char(8,69477).
+char(0,69478).
+char(6,69479).
+char(1,69480).
+char(c,69481).
+char(c,69482).
+char(c,69483).
+char(m,69484).
+char(o,69485).
+char(p,69486).
+char(9,69487).
+char(7,69488).
+char(5,69489).
+char(0,69490).
+char(c,69491).
+char(c,69492).
+char(c,69493).
+char(p,69494).
+char(5,69495).
+char(1,69496).
+char(3,69497).
+char(0,69498).
+char(c,69499).
+char(c,69500).
+char(c,69501).
+char(c,69502).
+char(m,69503).
+char(o,69504).
+char(8,69505).
+char(6,69506).
+char(2,69507).
+char(8,69508).
+char(c,69509).
+char(m,69510).
+char(5,69511).
+char(9,69512).
+char(0,69513).
+char(4,69514).
+char(p,69515).
+char(3,69516).
+char(9,69517).
+char(1,69518).
+char(5,69519).
+char(m,69520).
+char(o,69521).
+char(o,69522).
+char(p,69523).
+char(9,69524).
+char(1,69525).
+char(4,69526).
+char(2,69527).
+char(m,69528).
+char(o,69529).
+char(p,69530).
+char(o,69531).
+char(p,69532).
+char(3,69533).
+char(6,69534).
+char(7,69535).
+char(m,69536).
+char(o,69537).
+char(4,69538).
+char(9,69539).
+char(4,69540).
+char(6,69541).
+char(c,69542).
+char(p,69543).
+char(o,69544).
+char(o,69545).
+char(p,69546).
+char(o,69547).
+char(9,69548).
+char(1,69549).
+char(5,69550).
+char(0,69551).
+char(c,69552).
+char(p,69553).
+char(o,69554).
+char(p,69555).
+char(o,69556).
+char(p,69557).
+char(o,69558).
+char(o,69559).
+char(m,69560).
+char(7,69561).
+char(2,69562).
+char(0,69563).
+char(0,69564).
+char(p,69565).
+char(2,69566).
+char(5,69567).
+char(1,69568).
+char(2,69569).
+char(c,69570).
+char(c,69571).
+char(c,69572).
+char(c,69573).
+char(c,69574).
+char(p,69575).
+char(o,69576).
+char(p,69577).
+char(7,69578).
+char(7,69579).
+char(6,69580).
+char(7,69581).
+char(p,69582).
+char(1,69583).
+char(2,69584).
+char(0,69585).
+char(6,69586).
+char(c,69587).
+char(c,69588).
+char(c,69589).
+char(p,69590).
+char(3,69591).
+char(7,69592).
+char(3,69593).
+char(9,69594).
+char(m,69595).
+char(4,69596).
+char(1,69597).
+char(4,69598).
+char(2,69599).
+char(p,69600).
+char(3,69601).
+char(1,69602).
+char(2,69603).
+char(2,69604).
+char(c,69605).
+char(c,69606).
+char(c,69607).
+char(m,69608).
+char(2,69609).
+char(8,69610).
+char(3,69611).
+char(3,69612).
+char(c,69613).
+char(c,69614).
+char(c,69615).
+char(c,69616).
+char(c,69617).
+char(c,69618).
+char(c,69619).
+char(p,69620).
+char(5,69621).
+char(7,69622).
+char(5,69623).
+char(6,69624).
+char(p,69625).
+char(7,69626).
+char(9,69627).
+char(1,69628).
+char(0,69629).
+char(p,69630).
+char(o,69631).
+char(m,69632).
+char(o,69633).
+char(p,69634).
+char(o,69635).
+char(p,69636).
+char(1,69637).
+char(8,69638).
+char(4,69639).
+char(m,69640).
+char(o,69641).
+char(p,69642).
+char(6,69643).
+char(3,69644).
+char(3,69645).
+char(5,69646).
+char(c,69647).
+char(c,69648).
+char(c,69649).
+char(p,69650).
+char(o,69651).
+char(m,69652).
+char(8,69653).
+char(0,69654).
+char(8,69655).
+char(3,69656).
+char(c,69657).
+char(m,69658).
+char(o,69659).
+char(o,69660).
+char(7,69661).
+char(0,69662).
+char(0,69663).
+char(7,69664).
+char(m,69665).
+char(6,69666).
+char(6,69667).
+char(0,69668).
+char(2,69669).
+char(c,69670).
+char(m,69671).
+char(o,69672).
+char(p,69673).
+char(1,69674).
+char(5,69675).
+char(8,69676).
+char(5,69677).
+char(c,69678).
+char(c,69679).
+char(p,69680).
+char(o,69681).
+char(4,69682).
+char(1,69683).
+char(3,69684).
+char(6,69685).
+char(c,69686).
+char(p,69687).
+char(o,69688).
+char(p,69689).
+char(7,69690).
+char(0,69691).
+char(7,69692).
+char(4,69693).
+char(c,69694).
+char(c,69695).
+char(c,69696).
+char(m,69697).
+char(o,69698).
+char(p,69699).
+char(5,69700).
+char(9,69701).
+char(3,69702).
+char(2,69703).
+char(c,69704).
+char(p,69705).
+char(7,69706).
+char(8,69707).
+char(7,69708).
+char(0,69709).
+char(m,69710).
+char(o,69711).
+char(p,69712).
+char(o,69713).
+char(p,69714).
+char(o,69715).
+char(5,69716).
+char(9,69717).
+char(8,69718).
+char(2,69719).
+char(m,69720).
+char(o,69721).
+char(m,69722).
+char(o,69723).
+char(2,69724).
+char(4,69725).
+char(4,69726).
+char(3,69727).
+char(m,69728).
+char(o,69729).
+char(p,69730).
+char(o,69731).
+char(p,69732).
+char(6,69733).
+char(9,69734).
+char(6,69735).
+char(4,69736).
+char(m,69737).
+char(8,69738).
+char(3,69739).
+char(2,69740).
+char(4,69741).
+char(c,69742).
+char(p,69743).
+char(o,69744).
+char(p,69745).
+char(o,69746).
+char(p,69747).
+char(o,69748).
+char(p,69749).
+char(o,69750).
+char(p,69751).
+char(o,69752).
+char(m,69753).
+char(o,69754).
+char(o,69755).
+char(2,69756).
+char(5,69757).
+char(4,69758).
+char(7,69759).
+char(c,69760).
+char(p,69761).
+char(3,69762).
+char(5,69763).
+char(1,69764).
+char(7,69765).
+char(c,69766).
+char(m,69767).
+char(o,69768).
+char(6,69769).
+char(2,69770).
+char(4,69771).
+char(3,69772).
+char(c,69773).
+char(p,69774).
+char(o,69775).
+char(m,69776).
+char(o,69777).
+char(p,69778).
+char(o,69779).
+char(p,69780).
+char(o,69781).
+char(o,69782).
+char(o,69783).
+char(o,69784).
+char(9,69785).
+char(8,69786).
+char(2,69787).
+char(0,69788).
+char(p,69789).
+char(8,69790).
+char(9,69791).
+char(9,69792).
+char(0,69793).
+char(c,69794).
+char(p,69795).
+char(5,69796).
+char(9,69797).
+char(3,69798).
+char(8,69799).
+char(c,69800).
+char(m,69801).
+char(o,69802).
+char(o,69803).
+char(m,69804).
+char(3,69805).
+char(3,69806).
+char(4,69807).
+char(3,69808).
+char(m,69809).
+char(7,69810).
+char(0,69811).
+char(7,69812).
+char(3,69813).
+char(c,69814).
+char(c,69815).
+char(c,69816).
+char(c,69817).
+char(c,69818).
+char(p,69819).
+char(2,69820).
+char(9,69821).
+char(2,69822).
+char(4,69823).
+char(p,69824).
+char(o,69825).
+char(p,69826).
+char(3,69827).
+char(6,69828).
+char(6,69829).
+char(c,69830).
+char(p,69831).
+char(8,69832).
+char(1,69833).
+char(5,69834).
+char(1,69835).
+char(m,69836).
+char(3,69837).
+char(9,69838).
+char(2,69839).
+char(3,69840).
+char(c,69841).
+char(p,69842).
+char(o,69843).
+char(m,69844).
+char(8,69845).
+char(7,69846).
+char(6,69847).
+char(4,69848).
+char(p,69849).
+char(9,69850).
+char(0,69851).
+char(0,69852).
+char(8,69853).
+char(c,69854).
+char(c,69855).
+char(c,69856).
+char(c,69857).
+char(p,69858).
+char(8,69859).
+char(3,69860).
+char(0,69861).
+char(7,69862).
+char(c,69863).
+char(p,69864).
+char(o,69865).
+char(8,69866).
+char(2,69867).
+char(5,69868).
+char(4,69869).
+char(c,69870).
+char(c,69871).
+char(c,69872).
+char(p,69873).
+char(3,69874).
+char(4,69875).
+char(3,69876).
+char(p,69877).
+char(o,69878).
+char(o,69879).
+char(m,69880).
+char(o,69881).
+char(m,69882).
+char(o,69883).
+char(1,69884).
+char(0,69885).
+char(2,69886).
+char(c,69887).
+char(c,69888).
+char(c,69889).
+char(c,69890).
+char(p,69891).
+char(3,69892).
+char(6,69893).
+char(7,69894).
+char(4,69895).
+char(p,69896).
+char(4,69897).
+char(8,69898).
+char(4,69899).
+char(9,69900).
+char(p,69901).
+char(o,69902).
+char(m,69903).
+char(2,69904).
+char(0,69905).
+char(5,69906).
+char(9,69907).
+char(c,69908).
+char(c,69909).
+char(c,69910).
+char(p,69911).
+char(o,69912).
+char(p,69913).
+char(o,69914).
+char(p,69915).
+char(4,69916).
+char(7,69917).
+char(6,69918).
+char(4,69919).
+char(c,69920).
+char(p,69921).
+char(5,69922).
+char(7,69923).
+char(0,69924).
+char(m,69925).
+char(3,69926).
+char(4,69927).
+char(8,69928).
+char(p,69929).
+char(o,69930).
+char(m,69931).
+char(6,69932).
+char(5,69933).
+char(2,69934).
+char(c,69935).
+char(m,69936).
+char(9,69937).
+char(5,69938).
+char(0,69939).
+char(3,69940).
+char(c,69941).
+char(c,69942).
+char(c,69943).
+char(p,69944).
+char(7,69945).
+char(7,69946).
+char(0,69947).
+char(8,69948).
+char(p,69949).
+char(4,69950).
+char(2,69951).
+char(3,69952).
+char(5,69953).
+char(c,69954).
+char(c,69955).
+char(m,69956).
+char(o,69957).
+char(p,69958).
+char(o,69959).
+char(5,69960).
+char(4,69961).
+char(8,69962).
+char(7,69963).
+char(m,69964).
+char(o,69965).
+char(m,69966).
+char(o,69967).
+char(m,69968).
+char(7,69969).
+char(1,69970).
+char(8,69971).
+char(7,69972).
+char(c,69973).
+char(c,69974).
+char(p,69975).
+char(6,69976).
+char(1,69977).
+char(2,69978).
+char(5,69979).
+char(c,69980).
+char(c,69981).
+char(p,69982).
+char(4,69983).
+char(6,69984).
+char(7,69985).
+char(3,69986).
+char(m,69987).
+char(6,69988).
+char(7,69989).
+char(3,69990).
+char(3,69991).
+char(c,69992).
+char(m,69993).
+char(o,69994).
+char(p,69995).
+char(o,69996).
+char(m,69997).
+char(o,69998).
+char(p,69999).
+char(2,70000).
+char(6,70001).
+char(1,70002).
+char(7,70003).
+char(c,70004).
+char(c,70005).
+char(c,70006).
+char(p,70007).
+char(2,70008).
+char(1,70009).
+char(1,70010).
+char(0,70011).
+char(p,70012).
+char(8,70013).
+char(9,70014).
+char(6,70015).
+char(2,70016).
+char(m,70017).
+char(5,70018).
+char(1,70019).
+char(6,70020).
+char(6,70021).
+char(c,70022).
+char(c,70023).
+char(m,70024).
+char(5,70025).
+char(1,70026).
+char(4,70027).
+char(7,70028).
+char(c,70029).
+char(c,70030).
+char(p,70031).
+char(1,70032).
+char(1,70033).
+char(9,70034).
+char(6,70035).
+char(c,70036).
+char(m,70037).
+char(5,70038).
+char(9,70039).
+char(5,70040).
+char(8,70041).
+char(m,70042).
+char(4,70043).
+char(0,70044).
+char(2,70045).
+char(5,70046).
+char(p,70047).
+char(o,70048).
+char(m,70049).
+char(5,70050).
+char(8,70051).
+char(9,70052).
+char(6,70053).
+char(m,70054).
+char(o,70055).
+char(8,70056).
+char(6,70057).
+char(4,70058).
+char(1,70059).
+char(p,70060).
+char(9,70061).
+char(3,70062).
+char(1,70063).
+char(2,70064).
+char(c,70065).
+char(c,70066).
+char(m,70067).
+char(o,70068).
+char(m,70069).
+char(o,70070).
+char(8,70071).
+char(8,70072).
+char(2,70073).
+char(7,70074).
+char(c,70075).
+char(m,70076).
+char(7,70077).
+char(5,70078).
+char(1,70079).
+char(6,70080).
+char(c,70081).
+char(m,70082).
+char(o,70083).
+char(p,70084).
+char(o,70085).
+char(1,70086).
+char(5,70087).
+char(1,70088).
+char(0,70089).
+char(p,70090).
+char(o,70091).
+char(o,70092).
+char(p,70093).
+char(o,70094).
+char(p,70095).
+char(5,70096).
+char(9,70097).
+char(6,70098).
+char(2,70099).
+char(m,70100).
+char(4,70101).
+char(3,70102).
+char(1,70103).
+char(5,70104).
+char(c,70105).
+char(c,70106).
+char(p,70107).
+char(o,70108).
+char(o,70109).
+char(o,70110).
+char(4,70111).
+char(0,70112).
+char(8,70113).
+char(7,70114).
+char(c,70115).
+char(m,70116).
+char(7,70117).
+char(7,70118).
+char(4,70119).
+char(5,70120).
+char(c,70121).
+char(p,70122).
+char(7,70123).
+char(7,70124).
+char(0,70125).
+char(6,70126).
+char(c,70127).
+char(m,70128).
+char(3,70129).
+char(7,70130).
+char(2,70131).
+char(3,70132).
+char(p,70133).
+char(o,70134).
+char(8,70135).
+char(5,70136).
+char(5,70137).
+char(m,70138).
+char(4,70139).
+char(7,70140).
+char(5,70141).
+char(3,70142).
+char(m,70143).
+char(7,70144).
+char(5,70145).
+char(2,70146).
+char(8,70147).
+char(c,70148).
+char(c,70149).
+char(m,70150).
+char(9,70151).
+char(9,70152).
+char(3,70153).
+char(4,70154).
+char(c,70155).
+char(p,70156).
+char(2,70157).
+char(4,70158).
+char(2,70159).
+char(5,70160).
+char(c,70161).
+char(c,70162).
+char(c,70163).
+char(c,70164).
+char(p,70165).
+char(8,70166).
+char(0,70167).
+char(7,70168).
+char(1,70169).
+char(c,70170).
+char(c,70171).
+char(m,70172).
+char(9,70173).
+char(8,70174).
+char(4,70175).
+char(c,70176).
+char(c,70177).
+char(c,70178).
+char(c,70179).
+char(c,70180).
+char(p,70181).
+char(o,70182).
+char(p,70183).
+char(5,70184).
+char(3,70185).
+char(5,70186).
+char(1,70187).
+char(m,70188).
+char(o,70189).
+char(p,70190).
+char(8,70191).
+char(5,70192).
+char(1,70193).
+char(1,70194).
+char(c,70195).
+char(c,70196).
+char(m,70197).
+char(o,70198).
+char(p,70199).
+char(1,70200).
+char(5,70201).
+char(1,70202).
+char(2,70203).
+char(p,70204).
+char(7,70205).
+char(7,70206).
+char(4,70207).
+char(0,70208).
+char(m,70209).
+char(o,70210).
+char(m,70211).
+char(o,70212).
+char(m,70213).
+char(8,70214).
+char(3,70215).
+char(9,70216).
+char(6,70217).
+char(p,70218).
+char(6,70219).
+char(1,70220).
+char(4,70221).
+char(0,70222).
+char(c,70223).
+char(c,70224).
+char(p,70225).
+char(o,70226).
+char(o,70227).
+char(o,70228).
+char(p,70229).
+char(1,70230).
+char(7,70231).
+char(9,70232).
+char(7,70233).
+char(c,70234).
+char(m,70235).
+char(o,70236).
+char(p,70237).
+char(8,70238).
+char(6,70239).
+char(5,70240).
+char(c,70241).
+char(m,70242).
+char(o,70243).
+char(m,70244).
+char(7,70245).
+char(5,70246).
+char(0,70247).
+char(3,70248).
+char(p,70249).
+char(6,70250).
+char(2,70251).
+char(6,70252).
+char(8,70253).
+char(c,70254).
+char(p,70255).
+char(3,70256).
+char(7,70257).
+char(7,70258).
+char(8,70259).
+char(c,70260).
+char(c,70261).
+char(p,70262).
+char(3,70263).
+char(9,70264).
+char(9,70265).
+char(5,70266).
+char(p,70267).
+char(2,70268).
+char(9,70269).
+char(7,70270).
+char(6,70271).
+char(m,70272).
+char(o,70273).
+char(o,70274).
+char(p,70275).
+char(2,70276).
+char(1,70277).
+char(0,70278).
+char(8,70279).
+char(c,70280).
+char(c,70281).
+char(p,70282).
+char(o,70283).
+char(p,70284).
+char(o,70285).
+char(p,70286).
+char(7,70287).
+char(6,70288).
+char(8,70289).
+char(0,70290).
+char(c,70291).
+char(m,70292).
+char(o,70293).
+char(p,70294).
+char(9,70295).
+char(0,70296).
+char(2,70297).
+char(7,70298).
+char(c,70299).
+char(c,70300).
+char(m,70301).
+char(7,70302).
+char(2,70303).
+char(9,70304).
+char(8,70305).
+char(m,70306).
+char(3,70307).
+char(3,70308).
+char(3,70309).
+char(7,70310).
+char(p,70311).
+char(6,70312).
+char(9,70313).
+char(7,70314).
+char(6,70315).
+char(c,70316).
+char(c,70317).
+char(c,70318).
+char(c,70319).
+char(c,70320).
+char(p,70321).
+char(o,70322).
+char(m,70323).
+char(o,70324).
+char(p,70325).
+char(6,70326).
+char(3,70327).
+char(5,70328).
+char(4,70329).
+char(p,70330).
+char(3,70331).
+char(3,70332).
+char(2,70333).
+char(7,70334).
+char(c,70335).
+char(p,70336).
+char(o,70337).
+char(m,70338).
+char(o,70339).
+char(m,70340).
+char(9,70341).
+char(6,70342).
+char(6,70343).
+char(5,70344).
+char(c,70345).
+char(c,70346).
+char(c,70347).
+char(c,70348).
+char(c,70349).
+char(p,70350).
+char(9,70351).
+char(3,70352).
+char(4,70353).
+char(1,70354).
+char(m,70355).
+char(5,70356).
+char(6,70357).
+char(7,70358).
+char(9,70359).
+char(c,70360).
+char(m,70361).
+char(o,70362).
+char(m,70363).
+char(7,70364).
+char(5,70365).
+char(3,70366).
+char(6,70367).
+char(p,70368).
+char(3,70369).
+char(7,70370).
+char(5,70371).
+char(7,70372).
+char(c,70373).
+char(p,70374).
+char(o,70375).
+char(m,70376).
+char(o,70377).
+char(o,70378).
+char(p,70379).
+char(6,70380).
+char(9,70381).
+char(9,70382).
+char(5,70383).
+char(c,70384).
+char(p,70385).
+char(o,70386).
+char(m,70387).
+char(o,70388).
+char(o,70389).
+char(p,70390).
+char(o,70391).
+char(p,70392).
+char(1,70393).
+char(7,70394).
+char(8,70395).
+char(2,70396).
+char(p,70397).
+char(8,70398).
+char(3,70399).
+char(8,70400).
+char(m,70401).
+char(2,70402).
+char(4,70403).
+char(3,70404).
+char(1,70405).
+char(c,70406).
+char(p,70407).
+char(o,70408).
+char(4,70409).
+char(2,70410).
+char(9,70411).
+char(7,70412).
+char(m,70413).
+char(8,70414).
+char(3,70415).
+char(2,70416).
+char(3,70417).
+char(m,70418).
+char(4,70419).
+char(8,70420).
+char(2,70421).
+char(9,70422).
+char(m,70423).
+char(4,70424).
+char(5,70425).
+char(9,70426).
+char(3,70427).
+char(c,70428).
+char(p,70429).
+char(1,70430).
+char(3,70431).
+char(8,70432).
+char(8,70433).
+char(c,70434).
+char(c,70435).
+char(c,70436).
+char(m,70437).
+char(o,70438).
+char(p,70439).
+char(o,70440).
+char(p,70441).
+char(o,70442).
+char(o,70443).
+char(m,70444).
+char(o,70445).
+char(m,70446).
+char(o,70447).
+char(o,70448).
+char(3,70449).
+char(3,70450).
+char(9,70451).
+char(7,70452).
+char(c,70453).
+char(c,70454).
+char(p,70455).
+char(o,70456).
+char(p,70457).
+char(7,70458).
+char(8,70459).
+char(1,70460).
+char(8,70461).
+char(m,70462).
+char(9,70463).
+char(5,70464).
+char(6,70465).
+char(c,70466).
+char(c,70467).
+char(c,70468).
+char(p,70469).
+char(1,70470).
+char(5,70471).
+char(9,70472).
+char(5,70473).
+char(c,70474).
+char(p,70475).
+char(o,70476).
+char(o,70477).
+char(p,70478).
+char(2,70479).
+char(7,70480).
+char(4,70481).
+char(2,70482).
+char(m,70483).
+char(o,70484).
+char(m,70485).
+char(1,70486).
+char(3,70487).
+char(0,70488).
+char(4,70489).
+char(m,70490).
+char(o,70491).
+char(o,70492).
+char(m,70493).
+char(5,70494).
+char(6,70495).
+char(8,70496).
+char(0,70497).
+char(p,70498).
+char(3,70499).
+char(9,70500).
+char(9,70501).
+char(3,70502).
+char(m,70503).
+char(o,70504).
+char(p,70505).
+char(o,70506).
+char(p,70507).
+char(4,70508).
+char(4,70509).
+char(4,70510).
+char(7,70511).
+char(c,70512).
+char(c,70513).
+char(p,70514).
+char(9,70515).
+char(2,70516).
+char(2,70517).
+char(3,70518).
+char(c,70519).
+char(c,70520).
+char(c,70521).
+char(c,70522).
+char(p,70523).
+char(o,70524).
+char(p,70525).
+char(o,70526).
+char(m,70527).
+char(1,70528).
+char(5,70529).
+char(6,70530).
+char(0,70531).
+char(c,70532).
+char(c,70533).
+char(m,70534).
+char(8,70535).
+char(6,70536).
+char(0,70537).
+char(7,70538).
+char(m,70539).
+char(o,70540).
+char(2,70541).
+char(7,70542).
+char(0,70543).
+char(8,70544).
+char(m,70545).
+char(2,70546).
+char(1,70547).
+char(7,70548).
+char(0,70549).
+char(c,70550).
+char(c,70551).
+char(m,70552).
+char(8,70553).
+char(3,70554).
+char(1,70555).
+char(0,70556).
+char(m,70557).
+char(o,70558).
+char(m,70559).
+char(9,70560).
+char(9,70561).
+char(8,70562).
+char(2,70563).
+char(m,70564).
+char(7,70565).
+char(5,70566).
+char(1,70567).
+char(0,70568).
+char(p,70569).
+char(6,70570).
+char(6,70571).
+char(3,70572).
+char(3,70573).
+char(m,70574).
+char(o,70575).
+char(m,70576).
+char(o,70577).
+char(p,70578).
+char(6,70579).
+char(8,70580).
+char(3,70581).
+char(4,70582).
+char(c,70583).
+char(c,70584).
+char(c,70585).
+char(m,70586).
+char(1,70587).
+char(3,70588).
+char(0,70589).
+char(2,70590).
+char(p,70591).
+char(o,70592).
+char(m,70593).
+char(3,70594).
+char(0,70595).
+char(2,70596).
+char(7,70597).
+char(m,70598).
+char(o,70599).
+char(8,70600).
+char(0,70601).
+char(9,70602).
+char(9,70603).
+char(c,70604).
+char(c,70605).
+char(p,70606).
+char(o,70607).
+char(p,70608).
+char(8,70609).
+char(2,70610).
+char(1,70611).
+char(6,70612).
+char(p,70613).
+char(2,70614).
+char(4,70615).
+char(1,70616).
+char(8,70617).
+char(c,70618).
+char(p,70619).
+char(1,70620).
+char(7,70621).
+char(9,70622).
+char(9,70623).
+char(p,70624).
+char(o,70625).
+char(m,70626).
+char(o,70627).
+char(m,70628).
+char(6,70629).
+char(5,70630).
+char(1,70631).
+char(2,70632).
+char(c,70633).
+char(p,70634).
+char(o,70635).
+char(p,70636).
+char(o,70637).
+char(4,70638).
+char(7,70639).
+char(5,70640).
+char(2,70641).
+char(p,70642).
+char(o,70643).
+char(p,70644).
+char(o,70645).
+char(m,70646).
+char(9,70647).
+char(6,70648).
+char(8,70649).
+char(p,70650).
+char(9,70651).
+char(8,70652).
+char(6,70653).
+char(1,70654).
+char(c,70655).
+char(c,70656).
+char(m,70657).
+char(o,70658).
+char(7,70659).
+char(6,70660).
+char(8,70661).
+char(1,70662).
+char(c,70663).
+char(c,70664).
+char(m,70665).
+char(6,70666).
+char(5,70667).
+char(3,70668).
+char(p,70669).
+char(o,70670).
+char(m,70671).
+char(1,70672).
+char(1,70673).
+char(3,70674).
+char(c,70675).
+char(c,70676).
+char(p,70677).
+char(4,70678).
+char(4,70679).
+char(1,70680).
+char(2,70681).
+char(p,70682).
+char(o,70683).
+char(2,70684).
+char(8,70685).
+char(8,70686).
+char(8,70687).
+char(c,70688).
+char(m,70689).
+char(3,70690).
+char(8,70691).
+char(2,70692).
+char(1,70693).
+char(p,70694).
+char(o,70695).
+char(3,70696).
+char(8,70697).
+char(4,70698).
+char(3,70699).
+char(m,70700).
+char(o,70701).
+char(o,70702).
+char(m,70703).
+char(o,70704).
+char(7,70705).
+char(2,70706).
+char(4,70707).
+char(6,70708).
+char(c,70709).
+char(m,70710).
+char(o,70711).
+char(p,70712).
+char(2,70713).
+char(9,70714).
+char(0,70715).
+char(2,70716).
+char(m,70717).
+char(9,70718).
+char(8,70719).
+char(8,70720).
+char(3,70721).
+char(m,70722).
+char(o,70723).
+char(m,70724).
+char(o,70725).
+char(o,70726).
+char(m,70727).
+char(o,70728).
+char(m,70729).
+char(4,70730).
+char(6,70731).
+char(0,70732).
+char(9,70733).
+char(p,70734).
+char(6,70735).
+char(9,70736).
+char(6,70737).
+char(7,70738).
+char(c,70739).
+char(c,70740).
+char(c,70741).
+char(c,70742).
+char(p,70743).
+char(o,70744).
+char(m,70745).
+char(o,70746).
+char(o,70747).
+char(p,70748).
+char(o,70749).
+char(o,70750).
+char(p,70751).
+char(9,70752).
+char(2,70753).
+char(2,70754).
+char(7,70755).
+char(m,70756).
+char(3,70757).
+char(7,70758).
+char(1,70759).
+char(2,70760).
+char(m,70761).
+char(1,70762).
+char(5,70763).
+char(2,70764).
+char(c,70765).
+char(p,70766).
+char(5,70767).
+char(1,70768).
+char(0,70769).
+char(1,70770).
+char(c,70771).
+char(p,70772).
+char(5,70773).
+char(1,70774).
+char(9,70775).
+char(m,70776).
+char(4,70777).
+char(8,70778).
+char(2,70779).
+char(5,70780).
+char(m,70781).
+char(o,70782).
+char(o,70783).
+char(o,70784).
+char(m,70785).
+char(o,70786).
+char(m,70787).
+char(6,70788).
+char(2,70789).
+char(7,70790).
+char(6,70791).
+char(c,70792).
+char(c,70793).
+char(c,70794).
+char(c,70795).
+char(c,70796).
+char(m,70797).
+char(o,70798).
+char(m,70799).
+char(7,70800).
+char(2,70801).
+char(2,70802).
+char(3,70803).
+char(p,70804).
+char(o,70805).
+char(o,70806).
+char(o,70807).
+char(m,70808).
+char(2,70809).
+char(1,70810).
+char(3,70811).
+char(6,70812).
+char(p,70813).
+char(o,70814).
+char(p,70815).
+char(5,70816).
+char(6,70817).
+char(6,70818).
+char(6,70819).
+char(c,70820).
+char(p,70821).
+char(7,70822).
+char(0,70823).
+char(0,70824).
+char(0,70825).
+char(p,70826).
+char(o,70827).
+char(1,70828).
+char(8,70829).
+char(7,70830).
+char(0,70831).
+char(c,70832).
+char(p,70833).
+char(7,70834).
+char(8,70835).
+char(3,70836).
+char(8,70837).
+char(c,70838).
+char(c,70839).
+char(m,70840).
+char(o,70841).
+char(m,70842).
+char(6,70843).
+char(5,70844).
+char(8,70845).
+char(5,70846).
+char(p,70847).
+char(1,70848).
+char(3,70849).
+char(0,70850).
+char(2,70851).
+char(c,70852).
+char(p,70853).
+char(5,70854).
+char(3,70855).
+char(0,70856).
+char(c,70857).
+char(m,70858).
+char(o,70859).
+char(8,70860).
+char(1,70861).
+char(6,70862).
+char(2,70863).
+char(m,70864).
+char(2,70865).
+char(9,70866).
+char(1,70867).
+char(5,70868).
+char(m,70869).
+char(5,70870).
+char(9,70871).
+char(5,70872).
+char(2,70873).
+char(c,70874).
+char(c,70875).
+char(m,70876).
+char(o,70877).
+char(m,70878).
+char(5,70879).
+char(4,70880).
+char(9,70881).
+char(c,70882).
+char(c,70883).
+char(m,70884).
+char(o,70885).
+char(p,70886).
+char(3,70887).
+char(4,70888).
+char(5,70889).
+char(4,70890).
+char(c,70891).
+char(p,70892).
+char(6,70893).
+char(5,70894).
+char(5,70895).
+char(6,70896).
+char(c,70897).
+char(p,70898).
+char(o,70899).
+char(p,70900).
+char(3,70901).
+char(9,70902).
+char(8,70903).
+char(0,70904).
+char(m,70905).
+char(o,70906).
+char(o,70907).
+char(p,70908).
+char(o,70909).
+char(o,70910).
+char(p,70911).
+char(o,70912).
+char(1,70913).
+char(9,70914).
+char(2,70915).
+char(3,70916).
+char(m,70917).
+char(o,70918).
+char(m,70919).
+char(o,70920).
+char(p,70921).
+char(1,70922).
+char(8,70923).
+char(7,70924).
+char(3,70925).
+char(m,70926).
+char(o,70927).
+char(p,70928).
+char(3,70929).
+char(0,70930).
+char(1,70931).
+char(3,70932).
+char(c,70933).
+char(c,70934).
+char(c,70935).
+char(p,70936).
+char(3,70937).
+char(7,70938).
+char(6,70939).
+char(8,70940).
+char(p,70941).
+char(8,70942).
+char(7,70943).
+char(7,70944).
+char(3,70945).
+char(m,70946).
+char(o,70947).
+char(m,70948).
+char(9,70949).
+char(2,70950).
+char(5,70951).
+char(6,70952).
+char(p,70953).
+char(7,70954).
+char(0,70955).
+char(4,70956).
+char(4,70957).
+char(c,70958).
+char(m,70959).
+char(8,70960).
+char(8,70961).
+char(2,70962).
+char(7,70963).
+char(m,70964).
+char(o,70965).
+char(o,70966).
+char(m,70967).
+char(2,70968).
+char(6,70969).
+char(5,70970).
+char(2,70971).
+char(m,70972).
+char(o,70973).
+char(p,70974).
+char(3,70975).
+char(0,70976).
+char(0,70977).
+char(2,70978).
+char(c,70979).
+char(c,70980).
+char(c,70981).
+char(m,70982).
+char(3,70983).
+char(7,70984).
+char(2,70985).
+char(c,70986).
+char(c,70987).
+char(p,70988).
+char(8,70989).
+char(5,70990).
+char(4,70991).
+char(4,70992).
+char(c,70993).
+char(p,70994).
+char(7,70995).
+char(4,70996).
+char(2,70997).
+char(1,70998).
+char(c,70999).
+char(p,71000).
+char(o,71001).
+char(m,71002).
+char(1,71003).
+char(2,71004).
+char(8,71005).
+char(6,71006).
+char(m,71007).
+char(o,71008).
+char(p,71009).
+char(o,71010).
+char(m,71011).
+char(6,71012).
+char(3,71013).
+char(2,71014).
+char(6,71015).
+char(c,71016).
+char(c,71017).
+char(c,71018).
+char(p,71019).
+char(o,71020).
+char(o,71021).
+char(p,71022).
+char(o,71023).
+char(p,71024).
+char(o,71025).
+char(m,71026).
+char(o,71027).
+char(o,71028).
+char(p,71029).
+char(o,71030).
+char(8,71031).
+char(3,71032).
+char(7,71033).
+char(2,71034).
+char(c,71035).
+char(p,71036).
+char(o,71037).
+char(o,71038).
+char(1,71039).
+char(2,71040).
+char(4,71041).
+char(p,71042).
+char(9,71043).
+char(7,71044).
+char(1,71045).
+char(0,71046).
+char(p,71047).
+char(7,71048).
+char(2,71049).
+char(3,71050).
+char(8,71051).
+char(p,71052).
+char(5,71053).
+char(7,71054).
+char(2,71055).
+char(6,71056).
+char(c,71057).
+char(c,71058).
+char(c,71059).
+char(m,71060).
+char(o,71061).
+char(9,71062).
+char(6,71063).
+char(7,71064).
+char(5,71065).
+char(c,71066).
+char(c,71067).
+char(p,71068).
+char(6,71069).
+char(8,71070).
+char(0,71071).
+char(3,71072).
+char(c,71073).
+char(c,71074).
+char(m,71075).
+char(o,71076).
+char(p,71077).
+char(o,71078).
+char(p,71079).
+char(7,71080).
+char(7,71081).
+char(5,71082).
+char(0,71083).
+char(c,71084).
+char(c,71085).
+char(m,71086).
+char(3,71087).
+char(7,71088).
+char(4,71089).
+char(0,71090).
+char(m,71091).
+char(o,71092).
+char(m,71093).
+char(2,71094).
+char(6,71095).
+char(8,71096).
+char(2,71097).
+char(c,71098).
+char(m,71099).
+char(2,71100).
+char(8,71101).
+char(3,71102).
+char(3,71103).
+char(p,71104).
+char(9,71105).
+char(4,71106).
+char(3,71107).
+char(4,71108).
+char(c,71109).
+char(c,71110).
+char(c,71111).
+char(m,71112).
+char(3,71113).
+char(6,71114).
+char(6,71115).
+char(c,71116).
+char(m,71117).
+char(o,71118).
+char(o,71119).
+char(m,71120).
+char(6,71121).
+char(1,71122).
+char(1,71123).
+char(4,71124).
+char(c,71125).
+char(c,71126).
+char(c,71127).
+char(c,71128).
+char(c,71129).
+char(c,71130).
+char(p,71131).
+char(o,71132).
+char(p,71133).
+char(3,71134).
+char(3,71135).
+char(8,71136).
+char(7,71137).
+char(c,71138).
+char(c,71139).
+char(c,71140).
+char(c,71141).
+char(c,71142).
+char(p,71143).
+char(o,71144).
+char(p,71145).
+char(5,71146).
+char(0,71147).
+char(5,71148).
+char(5,71149).
+char(c,71150).
+char(p,71151).
+char(2,71152).
+char(1,71153).
+char(2,71154).
+char(9,71155).
+char(m,71156).
+char(o,71157).
+char(p,71158).
+char(1,71159).
+char(0,71160).
+char(4,71161).
+char(1,71162).
+char(c,71163).
+char(m,71164).
+char(o,71165).
+char(p,71166).
+char(6,71167).
+char(2,71168).
+char(3,71169).
+char(0,71170).
+char(c,71171).
+char(p,71172).
+char(o,71173).
+char(p,71174).
+char(3,71175).
+char(0,71176).
+char(5,71177).
+char(4,71178).
+char(m,71179).
+char(2,71180).
+char(3,71181).
+char(4,71182).
+char(5,71183).
+char(c,71184).
+char(c,71185).
+char(c,71186).
+char(m,71187).
+char(o,71188).
+char(o,71189).
+char(o,71190).
+char(m,71191).
+char(o,71192).
+char(m,71193).
+char(o,71194).
+char(3,71195).
+char(1,71196).
+char(1,71197).
+char(m,71198).
+char(o,71199).
+char(o,71200).
+char(1,71201).
+char(0,71202).
+char(9,71203).
+char(3,71204).
+char(c,71205).
+char(c,71206).
+char(c,71207).
+char(m,71208).
+char(o,71209).
+char(p,71210).
+char(o,71211).
+char(o,71212).
+char(p,71213).
+char(o,71214).
+char(6,71215).
+char(9,71216).
+char(9,71217).
+char(2,71218).
+char(c,71219).
+char(c,71220).
+char(c,71221).
+char(c,71222).
+char(c,71223).
+char(p,71224).
+char(o,71225).
+char(p,71226).
+char(o,71227).
+char(m,71228).
+char(o,71229).
+char(p,71230).
+char(o,71231).
+char(m,71232).
+char(2,71233).
+char(9,71234).
+char(9,71235).
+char(6,71236).
+char(c,71237).
+char(c,71238).
+char(m,71239).
+char(o,71240).
+char(m,71241).
+char(o,71242).
+char(m,71243).
+char(o,71244).
+char(m,71245).
+char(o,71246).
+char(7,71247).
+char(6,71248).
+char(9,71249).
+char(7,71250).
+char(c,71251).
+char(p,71252).
+char(o,71253).
+char(5,71254).
+char(7,71255).
+char(8,71256).
+char(1,71257).
+char(c,71258).
+char(c,71259).
+char(p,71260).
+char(o,71261).
+char(m,71262).
+char(1,71263).
+char(2,71264).
+char(2,71265).
+char(p,71266).
+char(5,71267).
+char(6,71268).
+char(0,71269).
+char(7,71270).
+char(c,71271).
+char(m,71272).
+char(4,71273).
+char(2,71274).
+char(8,71275).
+char(6,71276).
+char(c,71277).
+char(p,71278).
+char(o,71279).
+char(m,71280).
+char(o,71281).
+char(m,71282).
+char(2,71283).
+char(8,71284).
+char(7,71285).
+char(1,71286).
+char(c,71287).
+char(p,71288).
+char(o,71289).
+char(2,71290).
+char(0,71291).
+char(1,71292).
+char(3,71293).
+char(c,71294).
+char(c,71295).
+char(c,71296).
+char(c,71297).
+char(c,71298).
+char(p,71299).
+char(5,71300).
+char(4,71301).
+char(2,71302).
+char(8,71303).
+char(c,71304).
+char(c,71305).
+char(m,71306).
+char(5,71307).
+char(6,71308).
+char(2,71309).
+char(3,71310).
+char(m,71311).
+char(4,71312).
+char(9,71313).
+char(2,71314).
+char(1,71315).
+char(c,71316).
+char(p,71317).
+char(o,71318).
+char(p,71319).
+char(3,71320).
+char(1,71321).
+char(1,71322).
+char(4,71323).
+char(m,71324).
+char(2,71325).
+char(7,71326).
+char(5,71327).
+char(9,71328).
+char(c,71329).
+char(c,71330).
+char(c,71331).
+char(c,71332).
+char(c,71333).
+char(p,71334).
+char(4,71335).
+char(9,71336).
+char(3,71337).
+char(4,71338).
+char(m,71339).
+char(o,71340).
+char(4,71341).
+char(4,71342).
+char(6,71343).
+char(1,71344).
+char(m,71345).
+char(o,71346).
+char(p,71347).
+char(7,71348).
+char(3,71349).
+char(9,71350).
+char(5,71351).
+char(c,71352).
+char(c,71353).
+char(c,71354).
+char(c,71355).
+char(c,71356).
+char(c,71357).
+char(c,71358).
+char(c,71359).
+char(m,71360).
+char(9,71361).
+char(9,71362).
+char(3,71363).
+char(4,71364).
+char(c,71365).
+char(m,71366).
+char(o,71367).
+char(3,71368).
+char(6,71369).
+char(6,71370).
+char(5,71371).
+char(c,71372).
+char(c,71373).
+char(p,71374).
+char(o,71375).
+char(o,71376).
+char(4,71377).
+char(3,71378).
+char(6,71379).
+char(4,71380).
+char(m,71381).
+char(o,71382).
+char(p,71383).
+char(o,71384).
+char(p,71385).
+char(9,71386).
+char(8,71387).
+char(7,71388).
+char(0,71389).
+char(c,71390).
+char(m,71391).
+char(o,71392).
+char(2,71393).
+char(7,71394).
+char(3,71395).
+char(8,71396).
+char(c,71397).
+char(c,71398).
+char(c,71399).
+char(m,71400).
+char(8,71401).
+char(2,71402).
+char(3,71403).
+char(7,71404).
+char(c,71405).
+char(c,71406).
+char(c,71407).
+char(c,71408).
+char(c,71409).
+char(p,71410).
+char(o,71411).
+char(p,71412).
+char(o,71413).
+char(m,71414).
+char(8,71415).
+char(1,71416).
+char(9,71417).
+char(3,71418).
+char(m,71419).
+char(o,71420).
+char(m,71421).
+char(1,71422).
+char(6,71423).
+char(3,71424).
+char(5,71425).
+char(p,71426).
+char(9,71427).
+char(3,71428).
+char(4,71429).
+char(3,71430).
+char(c,71431).
+char(m,71432).
+char(o,71433).
+char(m,71434).
+char(o,71435).
+char(p,71436).
+char(o,71437).
+char(o,71438).
+char(o,71439).
+char(2,71440).
+char(1,71441).
+char(4,71442).
+char(2,71443).
+char(c,71444).
+char(c,71445).
+char(c,71446).
+char(c,71447).
+char(c,71448).
+char(m,71449).
+char(o,71450).
+char(o,71451).
+char(m,71452).
+char(4,71453).
+char(1,71454).
+char(5,71455).
+char(0,71456).
+char(p,71457).
+char(4,71458).
+char(3,71459).
+char(0,71460).
+char(2,71461).
+char(m,71462).
+char(o,71463).
+char(m,71464).
+char(6,71465).
+char(7,71466).
+char(3,71467).
+char(9,71468).
+char(m,71469).
+char(6,71470).
+char(9,71471).
+char(6,71472).
+char(0,71473).
+char(c,71474).
+char(c,71475).
+char(p,71476).
+char(o,71477).
+char(p,71478).
+char(o,71479).
+char(m,71480).
+char(6,71481).
+char(1,71482).
+char(9,71483).
+char(3,71484).
+char(m,71485).
+char(o,71486).
+char(o,71487).
+char(4,71488).
+char(0,71489).
+char(5,71490).
+char(5,71491).
+char(c,71492).
+char(c,71493).
+char(c,71494).
+char(c,71495).
+char(m,71496).
+char(o,71497).
+char(m,71498).
+char(1,71499).
+char(5,71500).
+char(9,71501).
+char(6,71502).
+char(p,71503).
+char(7,71504).
+char(6,71505).
+char(1,71506).
+char(7,71507).
+char(c,71508).
+char(c,71509).
+char(c,71510).
+char(c,71511).
+char(c,71512).
+char(c,71513).
+char(m,71514).
+char(9,71515).
+char(5,71516).
+char(4,71517).
+char(9,71518).
+char(c,71519).
+char(c,71520).
+char(m,71521).
+char(8,71522).
+char(9,71523).
+char(1,71524).
+char(c,71525).
+char(m,71526).
+char(1,71527).
+char(7,71528).
+char(6,71529).
+char(0,71530).
+char(c,71531).
+char(p,71532).
+char(o,71533).
+char(o,71534).
+char(m,71535).
+char(8,71536).
+char(8,71537).
+char(7,71538).
+char(6,71539).
+char(p,71540).
+char(o,71541).
+char(4,71542).
+char(4,71543).
+char(1,71544).
+char(2,71545).
+char(c,71546).
+char(c,71547).
+char(m,71548).
+char(7,71549).
+char(8,71550).
+char(8,71551).
+char(8,71552).
+char(c,71553).
+char(c,71554).
+char(p,71555).
+char(o,71556).
+char(m,71557).
+char(4,71558).
+char(1,71559).
+char(0,71560).
+char(9,71561).
+char(m,71562).
+char(9,71563).
+char(6,71564).
+char(9,71565).
+char(4,71566).
+char(c,71567).
+char(m,71568).
+char(5,71569).
+char(8,71570).
+char(5,71571).
+char(3,71572).
+char(m,71573).
+char(o,71574).
+char(6,71575).
+char(6,71576).
+char(5,71577).
+char(9,71578).
+char(c,71579).
+char(p,71580).
+char(5,71581).
+char(4,71582).
+char(0,71583).
+char(p,71584).
+char(4,71585).
+char(6,71586).
+char(0,71587).
+char(9,71588).
+char(p,71589).
+char(o,71590).
+char(m,71591).
+char(o,71592).
+char(p,71593).
+char(o,71594).
+char(o,71595).
+char(m,71596).
+char(3,71597).
+char(3,71598).
+char(7,71599).
+char(6,71600).
+char(c,71601).
+char(c,71602).
+char(m,71603).
+char(7,71604).
+char(0,71605).
+char(3,71606).
+char(0,71607).
+char(m,71608).
+char(o,71609).
+char(p,71610).
+char(o,71611).
+char(m,71612).
+char(o,71613).
+char(m,71614).
+char(2,71615).
+char(7,71616).
+char(6,71617).
+char(4,71618).
+char(m,71619).
+char(1,71620).
+char(3,71621).
+char(0,71622).
+char(3,71623).
+char(c,71624).
+char(c,71625).
+char(c,71626).
+char(c,71627).
+char(c,71628).
+char(c,71629).
+char(c,71630).
+char(c,71631).
+char(c,71632).
+char(m,71633).
+char(2,71634).
+char(9,71635).
+char(3,71636).
+char(c,71637).
+char(m,71638).
+char(5,71639).
+char(2,71640).
+char(3,71641).
+char(4,71642).
+char(c,71643).
+char(c,71644).
+char(c,71645).
+char(p,71646).
+char(4,71647).
+char(5,71648).
+char(7,71649).
+char(1,71650).
+char(p,71651).
+char(2,71652).
+char(9,71653).
+char(9,71654).
+char(5,71655).
+char(p,71656).
+char(1,71657).
+char(9,71658).
+char(3,71659).
+char(9,71660).
+char(c,71661).
+char(c,71662).
+char(p,71663).
+char(o,71664).
+char(o,71665).
+char(m,71666).
+char(o,71667).
+char(m,71668).
+char(o,71669).
+char(p,71670).
+char(o,71671).
+char(2,71672).
+char(1,71673).
+char(8,71674).
+char(5,71675).
+char(p,71676).
+char(o,71677).
+char(p,71678).
+char(8,71679).
+char(3,71680).
+char(4,71681).
+char(8,71682).
+char(c,71683).
+char(c,71684).
+char(c,71685).
+char(c,71686).
+char(c,71687).
+char(m,71688).
+char(8,71689).
+char(7,71690).
+char(8,71691).
+char(3,71692).
+char(m,71693).
+char(7,71694).
+char(8,71695).
+char(8,71696).
+char(5,71697).
+char(p,71698).
+char(o,71699).
+char(1,71700).
+char(8,71701).
+char(3,71702).
+char(1,71703).
+char(m,71704).
+char(5,71705).
+char(4,71706).
+char(0,71707).
+char(c,71708).
+char(c,71709).
+char(p,71710).
+char(o,71711).
+char(o,71712).
+char(m,71713).
+char(o,71714).
+char(o,71715).
+char(p,71716).
+char(9,71717).
+char(1,71718).
+char(1,71719).
+char(1,71720).
+char(m,71721).
+char(4,71722).
+char(7,71723).
+char(2,71724).
+char(7,71725).
+char(p,71726).
+char(o,71727).
+char(p,71728).
+char(o,71729).
+char(m,71730).
+char(2,71731).
+char(3,71732).
+char(4,71733).
+char(0,71734).
+char(c,71735).
+char(c,71736).
+char(m,71737).
+char(o,71738).
+char(o,71739).
+char(o,71740).
+char(m,71741).
+char(7,71742).
+char(6,71743).
+char(2,71744).
+char(3,71745).
+char(c,71746).
+char(p,71747).
+char(6,71748).
+char(4,71749).
+char(4,71750).
+char(6,71751).
+char(m,71752).
+char(o,71753).
+char(p,71754).
+char(6,71755).
+char(9,71756).
+char(6,71757).
+char(1,71758).
+char(p,71759).
+char(4,71760).
+char(6,71761).
+char(1,71762).
+char(2,71763).
+char(c,71764).
+char(c,71765).
+char(m,71766).
+char(o,71767).
+char(o,71768).
+char(1,71769).
+char(2,71770).
+char(6,71771).
+char(m,71772).
+char(9,71773).
+char(6,71774).
+char(6,71775).
+char(9,71776).
+char(c,71777).
+char(c,71778).
+char(c,71779).
+char(m,71780).
+char(o,71781).
+char(p,71782).
+char(o,71783).
+char(m,71784).
+char(o,71785).
+char(m,71786).
+char(o,71787).
+char(m,71788).
+char(o,71789).
+char(p,71790).
+char(o,71791).
+char(p,71792).
+char(o,71793).
+char(p,71794).
+char(9,71795).
+char(9,71796).
+char(8,71797).
+char(6,71798).
+char(p,71799).
+char(o,71800).
+char(p,71801).
+char(5,71802).
+char(1,71803).
+char(3,71804).
+char(7,71805).
+char(c,71806).
+char(m,71807).
+char(2,71808).
+char(5,71809).
+char(2,71810).
+char(8,71811).
+char(m,71812).
+char(3,71813).
+char(1,71814).
+char(0,71815).
+char(4,71816).
+char(m,71817).
+char(5,71818).
+char(6,71819).
+char(9,71820).
+char(9,71821).
+char(m,71822).
+char(9,71823).
+char(7,71824).
+char(1,71825).
+char(3,71826).
+char(p,71827).
+char(1,71828).
+char(4,71829).
+char(0,71830).
+char(3,71831).
+char(c,71832).
+char(c,71833).
+char(c,71834).
+char(p,71835).
+char(o,71836).
+char(m,71837).
+char(o,71838).
+char(o,71839).
+char(p,71840).
+char(8,71841).
+char(5,71842).
+char(8,71843).
+char(c,71844).
+char(c,71845).
+char(c,71846).
+char(c,71847).
+char(m,71848).
+char(o,71849).
+char(p,71850).
+char(o,71851).
+char(p,71852).
+char(6,71853).
+char(8,71854).
+char(4,71855).
+char(4,71856).
+char(p,71857).
+char(3,71858).
+char(3,71859).
+char(7,71860).
+char(7,71861).
+char(c,71862).
+char(m,71863).
+char(6,71864).
+char(1,71865).
+char(4,71866).
+char(7,71867).
+char(c,71868).
+char(m,71869).
+char(o,71870).
+char(o,71871).
+char(m,71872).
+char(8,71873).
+char(4,71874).
+char(9,71875).
+char(2,71876).
+char(m,71877).
+char(o,71878).
+char(1,71879).
+char(6,71880).
+char(8,71881).
+char(2,71882).
+char(p,71883).
+char(3,71884).
+char(3,71885).
+char(9,71886).
+char(6,71887).
+char(p,71888).
+char(o,71889).
+char(m,71890).
+char(4,71891).
+char(4,71892).
+char(8,71893).
+char(6,71894).
+char(m,71895).
+char(o,71896).
+char(o,71897).
+char(3,71898).
+char(1,71899).
+char(0,71900).
+char(3,71901).
+char(c,71902).
+char(c,71903).
+char(c,71904).
+char(m,71905).
+char(9,71906).
+char(8,71907).
+char(5,71908).
+char(9,71909).
+char(c,71910).
+char(c,71911).
+char(m,71912).
+char(4,71913).
+char(6,71914).
+char(4,71915).
+char(6,71916).
+char(c,71917).
+char(p,71918).
+char(o,71919).
+char(p,71920).
+char(o,71921).
+char(p,71922).
+char(7,71923).
+char(5,71924).
+char(6,71925).
+char(4,71926).
+char(m,71927).
+char(1,71928).
+char(0,71929).
+char(8,71930).
+char(9,71931).
+char(p,71932).
+char(o,71933).
+char(m,71934).
+char(2,71935).
+char(3,71936).
+char(4,71937).
+char(2,71938).
+char(c,71939).
+char(m,71940).
+char(5,71941).
+char(1,71942).
+char(6,71943).
+char(1,71944).
+char(c,71945).
+char(m,71946).
+char(3,71947).
+char(5,71948).
+char(8,71949).
+char(2,71950).
+char(p,71951).
+char(6,71952).
+char(1,71953).
+char(3,71954).
+char(8,71955).
+char(c,71956).
+char(c,71957).
+char(c,71958).
+char(c,71959).
+char(p,71960).
+char(6,71961).
+char(0,71962).
+char(0,71963).
+char(7,71964).
+char(p,71965).
+char(2,71966).
+char(0,71967).
+char(8,71968).
+char(0,71969).
+char(m,71970).
+char(o,71971).
+char(o,71972).
+char(p,71973).
+char(2,71974).
+char(6,71975).
+char(2,71976).
+char(7,71977).
+char(c,71978).
+char(m,71979).
+char(o,71980).
+char(p,71981).
+char(o,71982).
+char(p,71983).
+char(8,71984).
+char(4,71985).
+char(2,71986).
+char(5,71987).
+char(m,71988).
+char(o,71989).
+char(p,71990).
+char(7,71991).
+char(1,71992).
+char(4,71993).
+char(4,71994).
+char(p,71995).
+char(o,71996).
+char(9,71997).
+char(2,71998).
+char(4,71999).
+char(4,72000).
+char(p,72001).
+char(o,72002).
+char(o,72003).
+char(o,72004).
+char(o,72005).
+char(6,72006).
+char(9,72007).
+char(2,72008).
+char(5,72009).
+char(m,72010).
+char(5,72011).
+char(0,72012).
+char(0,72013).
+char(p,72014).
+char(4,72015).
+char(9,72016).
+char(9,72017).
+char(0,72018).
+char(m,72019).
+char(2,72020).
+char(4,72021).
+char(5,72022).
+char(6,72023).
+char(c,72024).
+char(c,72025).
+char(c,72026).
+char(c,72027).
+char(c,72028).
+char(c,72029).
+char(c,72030).
+char(p,72031).
+char(o,72032).
+char(1,72033).
+char(2,72034).
+char(8,72035).
+char(9,72036).
+char(m,72037).
+char(o,72038).
+char(o,72039).
+char(p,72040).
+char(o,72041).
+char(m,72042).
+char(9,72043).
+char(3,72044).
+char(7,72045).
+char(2,72046).
+char(c,72047).
+char(m,72048).
+char(o,72049).
+char(8,72050).
+char(9,72051).
+char(5,72052).
+char(7,72053).
+char(c,72054).
+char(c,72055).
+char(p,72056).
+char(o,72057).
+char(m,72058).
+char(7,72059).
+char(4,72060).
+char(5,72061).
+char(7,72062).
+char(m,72063).
+char(2,72064).
+char(7,72065).
+char(2,72066).
+char(3,72067).
+char(c,72068).
+char(p,72069).
+char(o,72070).
+char(p,72071).
+char(8,72072).
+char(4,72073).
+char(8,72074).
+char(9,72075).
+char(c,72076).
+char(m,72077).
+char(7,72078).
+char(8,72079).
+char(7,72080).
+char(2,72081).
+char(p,72082).
+char(o,72083).
+char(o,72084).
+char(m,72085).
+char(o,72086).
+char(m,72087).
+char(o,72088).
+char(p,72089).
+char(o,72090).
+char(3,72091).
+char(9,72092).
+char(3,72093).
+char(9,72094).
+char(p,72095).
+char(o,72096).
+char(6,72097).
+char(8,72098).
+char(9,72099).
+char(0,72100).
+char(c,72101).
+char(m,72102).
+char(8,72103).
+char(1,72104).
+char(4,72105).
+char(m,72106).
+char(9,72107).
+char(3,72108).
+char(9,72109).
+char(2,72110).
+char(c,72111).
+char(c,72112).
+char(c,72113).
+char(m,72114).
+char(o,72115).
+char(p,72116).
+char(1,72117).
+char(7,72118).
+char(8,72119).
+char(6,72120).
+char(m,72121).
+char(o,72122).
+char(m,72123).
+char(1,72124).
+char(3,72125).
+char(8,72126).
+char(3,72127).
+char(m,72128).
+char(2,72129).
+char(9,72130).
+char(0,72131).
+char(9,72132).
+char(c,72133).
+char(c,72134).
+char(p,72135).
+char(6,72136).
+char(5,72137).
+char(2,72138).
+char(9,72139).
+char(p,72140).
+char(o,72141).
+char(m,72142).
+char(o,72143).
+char(o,72144).
+char(m,72145).
+char(o,72146).
+char(o,72147).
+char(m,72148).
+char(o,72149).
+char(p,72150).
+char(4,72151).
+char(7,72152).
+char(0,72153).
+char(8,72154).
+char(c,72155).
+char(c,72156).
+char(c,72157).
+char(c,72158).
+char(c,72159).
+char(m,72160).
+char(3,72161).
+char(9,72162).
+char(6,72163).
+char(p,72164).
+char(9,72165).
+char(9,72166).
+char(4,72167).
+char(6,72168).
+char(c,72169).
+char(m,72170).
+char(o,72171).
+char(8,72172).
+char(9,72173).
+char(m,72174).
+char(o,72175).
+char(p,72176).
+char(5,72177).
+char(7,72178).
+char(9,72179).
+char(9,72180).
+char(p,72181).
+char(6,72182).
+char(2,72183).
+char(7,72184).
+char(9,72185).
+char(p,72186).
+char(9,72187).
+char(8,72188).
+char(8,72189).
+char(2,72190).
+char(p,72191).
+char(7,72192).
+char(9,72193).
+char(5,72194).
+char(9,72195).
+char(c,72196).
+char(c,72197).
+char(p,72198).
+char(6,72199).
+char(7,72200).
+char(5,72201).
+char(4,72202).
+char(c,72203).
+char(m,72204).
+char(o,72205).
+char(p,72206).
+char(8,72207).
+char(8,72208).
+char(2,72209).
+char(1,72210).
+char(p,72211).
+char(o,72212).
+char(o,72213).
+char(m,72214).
+char(o,72215).
+char(p,72216).
+char(o,72217).
+char(p,72218).
+char(o,72219).
+char(o,72220).
+char(p,72221).
+char(o,72222).
+char(m,72223).
+char(6,72224).
+char(2,72225).
+char(4,72226).
+char(8,72227).
+char(p,72228).
+char(1,72229).
+char(8,72230).
+char(0,72231).
+char(0,72232).
+char(c,72233).
+char(c,72234).
+char(c,72235).
+char(c,72236).
+char(m,72237).
+char(6,72238).
+char(6,72239).
+char(0,72240).
+char(1,72241).
+char(c,72242).
+char(c,72243).
+char(m,72244).
+char(3,72245).
+char(0,72246).
+char(5,72247).
+char(4,72248).
+char(p,72249).
+char(8,72250).
+char(8,72251).
+char(1,72252).
+char(8,72253).
+char(m,72254).
+char(1,72255).
+char(9,72256).
+char(8,72257).
+char(4,72258).
+char(m,72259).
+char(8,72260).
+char(9,72261).
+char(3,72262).
+char(7,72263).
+char(m,72264).
+char(o,72265).
+char(o,72266).
+char(m,72267).
+char(4,72268).
+char(9,72269).
+char(9,72270).
+char(0,72271).
+char(m,72272).
+char(o,72273).
+char(7,72274).
+char(1,72275).
+char(7,72276).
+char(0,72277).
+char(p,72278).
+char(3,72279).
+char(7,72280).
+char(1,72281).
+char(1,72282).
+char(c,72283).
+char(p,72284).
+char(o,72285).
+char(o,72286).
+char(m,72287).
+char(o,72288).
+char(6,72289).
+char(4,72290).
+char(9,72291).
+char(5,72292).
+char(c,72293).
+char(m,72294).
+char(o,72295).
+char(6,72296).
+char(3,72297).
+char(6,72298).
+char(c,72299).
+char(m,72300).
+char(o,72301).
+char(5,72302).
+char(8,72303).
+char(0,72304).
+char(0,72305).
+char(m,72306).
+char(9,72307).
+char(0,72308).
+char(3,72309).
+char(7,72310).
+char(p,72311).
+char(o,72312).
+char(p,72313).
+char(6,72314).
+char(3,72315).
+char(4,72316).
+char(8,72317).
+char(m,72318).
+char(o,72319).
+char(p,72320).
+char(4,72321).
+char(3,72322).
+char(2,72323).
+char(0,72324).
+char(p,72325).
+char(3,72326).
+char(0,72327).
+char(2,72328).
+char(9,72329).
+char(p,72330).
+char(5,72331).
+char(7,72332).
+char(2,72333).
+char(7,72334).
+char(p,72335).
+char(o,72336).
+char(m,72337).
+char(o,72338).
+char(p,72339).
+char(o,72340).
+char(m,72341).
+char(1,72342).
+char(3,72343).
+char(2,72344).
+char(8,72345).
+char(m,72346).
+char(1,72347).
+char(1,72348).
+char(4,72349).
+char(9,72350).
+char(p,72351).
+char(1,72352).
+char(5,72353).
+char(9,72354).
+char(9,72355).
+char(p,72356).
+char(2,72357).
+char(0,72358).
+char(7,72359).
+char(7,72360).
+char(c,72361).
+char(c,72362).
+char(p,72363).
+char(5,72364).
+char(5,72365).
+char(1,72366).
+char(9,72367).
+char(c,72368).
+char(c,72369).
+char(c,72370).
+char(p,72371).
+char(o,72372).
+char(p,72373).
+char(o,72374).
+char(m,72375).
+char(o,72376).
+char(o,72377).
+char(p,72378).
+char(o,72379).
+char(m,72380).
+char(5,72381).
+char(7,72382).
+char(6,72383).
+char(0,72384).
+char(p,72385).
+char(o,72386).
+char(p,72387).
+char(3,72388).
+char(7,72389).
+char(1,72390).
+char(8,72391).
+char(c,72392).
+char(p,72393).
+char(9,72394).
+char(5,72395).
+char(1,72396).
+char(5,72397).
+char(m,72398).
+char(o,72399).
+char(4,72400).
+char(6,72401).
+char(7,72402).
+char(1,72403).
+char(p,72404).
+char(5,72405).
+char(7,72406).
+char(8,72407).
+char(0,72408).
+char(m,72409).
+char(6,72410).
+char(2,72411).
+char(1,72412).
+char(2,72413).
+char(p,72414).
+char(o,72415).
+char(m,72416).
+char(o,72417).
+char(p,72418).
+char(5,72419).
+char(6,72420).
+char(3,72421).
+char(4,72422).
+char(c,72423).
+char(p,72424).
+char(o,72425).
+char(m,72426).
+char(8,72427).
+char(5,72428).
+char(6,72429).
+char(c,72430).
+char(p,72431).
+char(3,72432).
+char(6,72433).
+char(6,72434).
+char(0,72435).
+char(c,72436).
+char(c,72437).
+char(c,72438).
+char(p,72439).
+char(o,72440).
+char(p,72441).
+char(9,72442).
+char(5,72443).
+char(0,72444).
+char(5,72445).
+char(p,72446).
+char(6,72447).
+char(5,72448).
+char(2,72449).
+char(1,72450).
+char(c,72451).
+char(c,72452).
+char(c,72453).
+char(p,72454).
+char(o,72455).
+char(5,72456).
+char(7,72457).
+char(8,72458).
+char(4,72459).
+char(c,72460).
+char(p,72461).
+char(o,72462).
+char(m,72463).
+char(o,72464).
+char(m,72465).
+char(4,72466).
+char(4,72467).
+char(3,72468).
+char(8,72469).
+char(c,72470).
+char(c,72471).
+char(p,72472).
+char(o,72473).
+char(m,72474).
+char(8,72475).
+char(2,72476).
+char(5,72477).
+char(7,72478).
+char(c,72479).
+char(m,72480).
+char(o,72481).
+char(p,72482).
+char(o,72483).
+char(m,72484).
+char(6,72485).
+char(7,72486).
+char(8,72487).
+char(p,72488).
+char(o,72489).
+char(o,72490).
+char(m,72491).
+char(3,72492).
+char(5,72493).
+char(5,72494).
+char(1,72495).
+char(m,72496).
+char(o,72497).
+char(m,72498).
+char(o,72499).
+char(4,72500).
+char(7,72501).
+char(7,72502).
+char(7,72503).
+char(m,72504).
+char(2,72505).
+char(5,72506).
+char(1,72507).
+char(c,72508).
+char(p,72509).
+char(o,72510).
+char(m,72511).
+char(5,72512).
+char(6,72513).
+char(8,72514).
+char(1,72515).
+char(c,72516).
+char(p,72517).
+char(o,72518).
+char(m,72519).
+char(o,72520).
+char(5,72521).
+char(8,72522).
+char(9,72523).
+char(9,72524).
+char(m,72525).
+char(o,72526).
+char(p,72527).
+char(1,72528).
+char(3,72529).
+char(7,72530).
+char(0,72531).
+char(m,72532).
+char(3,72533).
+char(2,72534).
+char(8,72535).
+char(0,72536).
+char(p,72537).
+char(o,72538).
+char(m,72539).
+char(5,72540).
+char(6,72541).
+char(1,72542).
+char(3,72543).
+char(p,72544).
+char(o,72545).
+char(m,72546).
+char(6,72547).
+char(2,72548).
+char(4,72549).
+char(9,72550).
+char(p,72551).
+char(o,72552).
+char(m,72553).
+char(o,72554).
+char(o,72555).
+char(m,72556).
+char(8,72557).
+char(3,72558).
+char(6,72559).
+char(6,72560).
+char(c,72561).
+char(p,72562).
+char(4,72563).
+char(8,72564).
+char(1,72565).
+char(9,72566).
+char(m,72567).
+char(o,72568).
+char(p,72569).
+char(o,72570).
+char(m,72571).
+char(o,72572).
+char(m,72573).
+char(8,72574).
+char(6,72575).
+char(4,72576).
+char(7,72577).
+char(m,72578).
+char(6,72579).
+char(7,72580).
+char(0,72581).
+char(4,72582).
+char(c,72583).
+char(c,72584).
+char(p,72585).
+char(o,72586).
+char(9,72587).
+char(7,72588).
+char(4,72589).
+char(0,72590).
+char(m,72591).
+char(3,72592).
+char(8,72593).
+char(0,72594).
+char(9,72595).
+char(m,72596).
+char(o,72597).
+char(m,72598).
+char(1,72599).
+char(4,72600).
+char(3,72601).
+char(1,72602).
+char(p,72603).
+char(2,72604).
+char(3,72605).
+char(2,72606).
+char(6,72607).
+char(c,72608).
+char(c,72609).
+char(p,72610).
+char(o,72611).
+char(m,72612).
+char(7,72613).
+char(1,72614).
+char(7,72615).
+char(2,72616).
+char(c,72617).
+char(m,72618).
+char(o,72619).
+char(7,72620).
+char(8,72621).
+char(3,72622).
+char(6,72623).
+char(m,72624).
+char(o,72625).
+char(9,72626).
+char(1,72627).
+char(8,72628).
+char(9,72629).
+char(p,72630).
+char(o,72631).
+char(p,72632).
+char(5,72633).
+char(8,72634).
+char(6,72635).
+char(2,72636).
+char(c,72637).
+char(c,72638).
+char(c,72639).
+char(p,72640).
+char(6,72641).
+char(0,72642).
+char(1,72643).
+char(4,72644).
+char(c,72645).
+char(m,72646).
+char(o,72647).
+char(1,72648).
+char(3,72649).
+char(5,72650).
+char(1,72651).
+char(m,72652).
+char(9,72653).
+char(2,72654).
+char(8,72655).
+char(0,72656).
+char(c,72657).
+char(m,72658).
+char(8,72659).
+char(2,72660).
+char(8,72661).
+char(2,72662).
+char(p,72663).
+char(o,72664).
+char(m,72665).
+char(9,72666).
+char(3,72667).
+char(7,72668).
+char(7,72669).
+char(p,72670).
+char(4,72671).
+char(6,72672).
+char(0,72673).
+char(2,72674).
+char(c,72675).
+char(c,72676).
+char(m,72677).
+char(5,72678).
+char(9,72679).
+char(1,72680).
+char(1,72681).
+char(c,72682).
+char(c,72683).
+char(c,72684).
+char(c,72685).
+char(m,72686).
+char(3,72687).
+char(5,72688).
+char(8,72689).
+char(6,72690).
+char(m,72691).
+char(o,72692).
+char(p,72693).
+char(9,72694).
+char(0,72695).
+char(3,72696).
+char(1,72697).
+char(c,72698).
+char(c,72699).
+char(p,72700).
+char(o,72701).
+char(o,72702).
+char(p,72703).
+char(o,72704).
+char(m,72705).
+char(3,72706).
+char(5,72707).
+char(8,72708).
+char(5,72709).
+char(c,72710).
+char(p,72711).
+char(6,72712).
+char(6,72713).
+char(5,72714).
+char(6,72715).
+char(m,72716).
+char(5,72717).
+char(2,72718).
+char(9,72719).
+char(3,72720).
+char(c,72721).
+char(p,72722).
+char(8,72723).
+char(6,72724).
+char(7,72725).
+char(1,72726).
+char(p,72727).
+char(o,72728).
+char(m,72729).
+char(5,72730).
+char(2,72731).
+char(3,72732).
+char(3,72733).
+char(p,72734).
+char(o,72735).
+char(o,72736).
+char(m,72737).
+char(o,72738).
+char(p,72739).
+char(o,72740).
+char(m,72741).
+char(o,72742).
+char(p,72743).
+char(1,72744).
+char(2,72745).
+char(9,72746).
+char(9,72747).
+char(c,72748).
+char(m,72749).
+char(3,72750).
+char(5,72751).
+char(6,72752).
+char(9,72753).
+char(c,72754).
+char(m,72755).
+char(o,72756).
+char(p,72757).
+char(o,72758).
+char(m,72759).
+char(7,72760).
+char(5,72761).
+char(2,72762).
+char(8,72763).
+char(c,72764).
+char(m,72765).
+char(1,72766).
+char(5,72767).
+char(3,72768).
+char(5,72769).
+char(p,72770).
+char(2,72771).
+char(0,72772).
+char(8,72773).
+char(7,72774).
+char(c,72775).
+char(m,72776).
+char(o,72777).
+char(m,72778).
+char(7,72779).
+char(9,72780).
+char(2,72781).
+char(0,72782).
+char(p,72783).
+char(1,72784).
+char(4,72785).
+char(7,72786).
+char(4,72787).
+char(m,72788).
+char(4,72789).
+char(0,72790).
+char(9,72791).
+char(6,72792).
+char(m,72793).
+char(o,72794).
+char(p,72795).
+char(1,72796).
+char(2,72797).
+char(8,72798).
+char(6,72799).
+char(m,72800).
+char(o,72801).
+char(p,72802).
+char(o,72803).
+char(m,72804).
+char(4,72805).
+char(7,72806).
+char(9,72807).
+char(1,72808).
+char(m,72809).
+char(8,72810).
+char(1,72811).
+char(8,72812).
+char(p,72813).
+char(5,72814).
+char(6,72815).
+char(6,72816).
+char(8,72817).
+char(c,72818).
+char(p,72819).
+char(3,72820).
+char(6,72821).
+char(9,72822).
+char(8,72823).
+char(p,72824).
+char(3,72825).
+char(5,72826).
+char(2,72827).
+char(9,72828).
+char(m,72829).
+char(7,72830).
+char(7,72831).
+char(m,72832).
+char(7,72833).
+char(8,72834).
+char(5,72835).
+char(5,72836).
+char(p,72837).
+char(2,72838).
+char(1,72839).
+char(0,72840).
+char(2,72841).
+char(m,72842).
+char(o,72843).
+char(o,72844).
+char(o,72845).
+char(4,72846).
+char(3,72847).
+char(2,72848).
+char(4,72849).
+char(m,72850).
+char(7,72851).
+char(3,72852).
+char(2,72853).
+char(2,72854).
+char(c,72855).
+char(m,72856).
+char(6,72857).
+char(7,72858).
+char(2,72859).
+char(0,72860).
+char(m,72861).
+char(7,72862).
+char(6,72863).
+char(3,72864).
+char(6,72865).
+char(p,72866).
+char(1,72867).
+char(0,72868).
+char(3,72869).
+char(8,72870).
+char(p,72871).
+char(5,72872).
+char(8,72873).
+char(2,72874).
+char(p,72875).
+char(o,72876).
+char(p,72877).
+char(3,72878).
+char(0,72879).
+char(1,72880).
+char(5,72881).
+char(p,72882).
+char(1,72883).
+char(3,72884).
+char(2,72885).
+char(6,72886).
+char(c,72887).
+char(c,72888).
+char(p,72889).
+char(o,72890).
+char(p,72891).
+char(6,72892).
+char(5,72893).
+char(8,72894).
+char(3,72895).
+char(c,72896).
+char(m,72897).
+char(o,72898).
+char(o,72899).
+char(o,72900).
+char(m,72901).
+char(4,72902).
+char(4,72903).
+char(5,72904).
+char(4,72905).
+char(c,72906).
+char(m,72907).
+char(1,72908).
+char(3,72909).
+char(1,72910).
+char(3,72911).
+char(c,72912).
+char(c,72913).
+char(m,72914).
+char(o,72915).
+char(m,72916).
+char(2,72917).
+char(0,72918).
+char(6,72919).
+char(p,72920).
+char(5,72921).
+char(9,72922).
+char(6,72923).
+char(9,72924).
+char(p,72925).
+char(o,72926).
+char(p,72927).
+char(o,72928).
+char(m,72929).
+char(o,72930).
+char(p,72931).
+char(o,72932).
+char(p,72933).
+char(o,72934).
+char(p,72935).
+char(o,72936).
+char(5,72937).
+char(9,72938).
+char(4,72939).
+char(2,72940).
+char(p,72941).
+char(8,72942).
+char(0,72943).
+char(0,72944).
+char(3,72945).
+char(m,72946).
+char(1,72947).
+char(3,72948).
+char(9,72949).
+char(3,72950).
+char(c,72951).
+char(m,72952).
+char(4,72953).
+char(3,72954).
+char(0,72955).
+char(c,72956).
+char(p,72957).
+char(9,72958).
+char(3,72959).
+char(8,72960).
+char(0,72961).
+char(c,72962).
+char(p,72963).
+char(o,72964).
+char(o,72965).
+char(p,72966).
+char(o,72967).
+char(p,72968).
+char(3,72969).
+char(2,72970).
+char(4,72971).
+char(6,72972).
+char(c,72973).
+char(c,72974).
+char(c,72975).
+char(m,72976).
+char(3,72977).
+char(7,72978).
+char(8,72979).
+char(0,72980).
+char(c,72981).
+char(c,72982).
+char(p,72983).
+char(6,72984).
+char(7,72985).
+char(6,72986).
+char(7,72987).
+char(c,72988).
+char(c,72989).
+char(m,72990).
+char(o,72991).
+char(5,72992).
+char(1,72993).
+char(5,72994).
+char(8,72995).
+char(c,72996).
+char(m,72997).
+char(7,72998).
+char(1,72999).
+char(2,73000).
+char(c,73001).
+char(m,73002).
+char(o,73003).
+char(p,73004).
+char(2,73005).
+char(9,73006).
+char(6,73007).
+char(7,73008).
+char(m,73009).
+char(3,73010).
+char(6,73011).
+char(4,73012).
+char(m,73013).
+char(9,73014).
+char(0,73015).
+char(0,73016).
+char(8,73017).
+char(c,73018).
+char(m,73019).
+char(5,73020).
+char(4,73021).
+char(2,73022).
+char(2,73023).
+char(p,73024).
+char(7,73025).
+char(6,73026).
+char(4,73027).
+char(8,73028).
+char(m,73029).
+char(3,73030).
+char(5,73031).
+char(1,73032).
+char(5,73033).
+char(c,73034).
+char(c,73035).
+char(m,73036).
+char(3,73037).
+char(1,73038).
+char(7,73039).
+char(p,73040).
+char(9,73041).
+char(8,73042).
+char(1,73043).
+char(6,73044).
+char(c,73045).
+char(c,73046).
+char(c,73047).
+char(c,73048).
+char(p,73049).
+char(o,73050).
+char(p,73051).
+char(1,73052).
+char(1,73053).
+char(0,73054).
+char(8,73055).
+char(c,73056).
+char(c,73057).
+char(m,73058).
+char(7,73059).
+char(6,73060).
+char(2,73061).
+char(6,73062).
+char(c,73063).
+char(c,73064).
+char(m,73065).
+char(6,73066).
+char(7,73067).
+char(9,73068).
+char(1,73069).
+char(m,73070).
+char(6,73071).
+char(7,73072).
+char(3,73073).
+char(2,73074).
+char(c,73075).
+char(c,73076).
+char(m,73077).
+char(o,73078).
+char(o,73079).
+char(5,73080).
+char(1,73081).
+char(5,73082).
+char(6,73083).
+char(p,73084).
+char(5,73085).
+char(1,73086).
+char(0,73087).
+char(4,73088).
+char(c,73089).
+char(c,73090).
+char(p,73091).
+char(o,73092).
+char(p,73093).
+char(1,73094).
+char(0,73095).
+char(8,73096).
+char(m,73097).
+char(o,73098).
+char(m,73099).
+char(5,73100).
+char(2,73101).
+char(3,73102).
+char(5,73103).
+char(c,73104).
+char(c,73105).
+char(p,73106).
+char(o,73107).
+char(m,73108).
+char(9,73109).
+char(7,73110).
+char(3,73111).
+char(7,73112).
+char(m,73113).
+char(6,73114).
+char(7,73115).
+char(4,73116).
+char(8,73117).
+char(c,73118).
+char(m,73119).
+char(o,73120).
+char(m,73121).
+char(o,73122).
+char(p,73123).
+char(o,73124).
+char(o,73125).
+char(9,73126).
+char(3,73127).
+char(5,73128).
+char(m,73129).
+char(o,73130).
+char(p,73131).
+char(5,73132).
+char(4,73133).
+char(5,73134).
+char(9,73135).
+char(m,73136).
+char(5,73137).
+char(1,73138).
+char(5,73139).
+char(1,73140).
+char(c,73141).
+char(c,73142).
+char(p,73143).
+char(2,73144).
+char(0,73145).
+char(0,73146).
+char(4,73147).
+char(m,73148).
+char(o,73149).
+char(p,73150).
+char(7,73151).
+char(8,73152).
+char(9,73153).
+char(4,73154).
+char(p,73155).
+char(6,73156).
+char(3,73157).
+char(3,73158).
+char(9,73159).
+char(c,73160).
+char(c,73161).
+char(p,73162).
+char(6,73163).
+char(1,73164).
+char(2,73165).
+char(c,73166).
+char(p,73167).
+char(5,73168).
+char(6,73169).
+char(6,73170).
+char(4,73171).
+char(c,73172).
+char(c,73173).
+char(m,73174).
+char(3,73175).
+char(9,73176).
+char(3,73177).
+char(8,73178).
+char(c,73179).
+char(m,73180).
+char(8,73181).
+char(4,73182).
+char(2,73183).
+char(1,73184).
+char(c,73185).
+char(c,73186).
+char(p,73187).
+char(o,73188).
+char(p,73189).
+char(1,73190).
+char(8,73191).
+char(6,73192).
+char(7,73193).
+char(m,73194).
+char(o,73195).
+char(m,73196).
+char(8,73197).
+char(2,73198).
+char(4,73199).
+char(0,73200).
+char(c,73201).
+char(c,73202).
+char(c,73203).
+char(c,73204).
+char(c,73205).
+char(c,73206).
+char(m,73207).
+char(5,73208).
+char(0,73209).
+char(7,73210).
+char(7,73211).
+char(p,73212).
+char(o,73213).
+char(o,73214).
+char(m,73215).
+char(o,73216).
+char(o,73217).
+char(m,73218).
+char(5,73219).
+char(9,73220).
+char(0,73221).
+char(9,73222).
+char(c,73223).
+char(c,73224).
+char(c,73225).
+char(c,73226).
+char(c,73227).
+char(c,73228).
+char(c,73229).
+char(p,73230).
+char(4,73231).
+char(2,73232).
+char(1,73233).
+char(8,73234).
+char(m,73235).
+char(9,73236).
+char(5,73237).
+char(7,73238).
+char(5,73239).
+char(c,73240).
+char(p,73241).
+char(o,73242).
+char(m,73243).
+char(3,73244).
+char(2,73245).
+char(7,73246).
+char(2,73247).
+char(c,73248).
+char(c,73249).
+char(c,73250).
+char(c,73251).
+char(c,73252).
+char(c,73253).
+char(p,73254).
+char(o,73255).
+char(o,73256).
+char(p,73257).
+char(o,73258).
+char(m,73259).
+char(o,73260).
+char(5,73261).
+char(7,73262).
+char(0,73263).
+char(1,73264).
+char(c,73265).
+char(m,73266).
+char(4,73267).
+char(1,73268).
+char(9,73269).
+char(1,73270).
+char(c,73271).
+char(p,73272).
+char(6,73273).
+char(9,73274).
+char(5,73275).
+char(4,73276).
+char(c,73277).
+char(c,73278).
+char(c,73279).
+char(c,73280).
+char(p,73281).
+char(o,73282).
+char(o,73283).
+char(m,73284).
+char(8,73285).
+char(4,73286).
+char(4,73287).
+char(1,73288).
+char(c,73289).
+char(c,73290).
+char(p,73291).
+char(o,73292).
+char(4,73293).
+char(5,73294).
+char(7,73295).
+char(1,73296).
+char(c,73297).
+char(m,73298).
+char(o,73299).
+char(m,73300).
+char(o,73301).
+char(p,73302).
+char(7,73303).
+char(1,73304).
+char(9,73305).
+char(8,73306).
+char(p,73307).
+char(9,73308).
+char(5,73309).
+char(6,73310).
+char(p,73311).
+char(9,73312).
+char(0,73313).
+char(2,73314).
+char(1,73315).
+char(p,73316).
+char(4,73317).
+char(0,73318).
+char(1,73319).
+char(8,73320).
+char(m,73321).
+char(8,73322).
+char(6,73323).
+char(6,73324).
+char(5,73325).
+char(m,73326).
+char(o,73327).
+char(m,73328).
+char(1,73329).
+char(3,73330).
+char(3,73331).
+char(1,73332).
+char(c,73333).
+char(m,73334).
+char(o,73335).
+char(8,73336).
+char(3,73337).
+char(3,73338).
+char(0,73339).
+char(c,73340).
+char(p,73341).
+char(9,73342).
+char(9,73343).
+char(2,73344).
+char(4,73345).
+char(m,73346).
+char(8,73347).
+char(4,73348).
+char(7,73349).
+char(p,73350).
+char(o,73351).
+char(m,73352).
+char(o,73353).
+char(o,73354).
+char(o,73355).
+char(4,73356).
+char(7,73357).
+char(9,73358).
+char(1,73359).
+char(c,73360).
+char(p,73361).
+char(8,73362).
+char(2,73363).
+char(8,73364).
+char(5,73365).
+char(p,73366).
+char(o,73367).
+char(p,73368).
+char(6,73369).
+char(1,73370).
+char(6,73371).
+char(7,73372).
+char(m,73373).
+char(o,73374).
+char(o,73375).
+char(2,73376).
+char(8,73377).
+char(0,73378).
+char(1,73379).
+char(c,73380).
+char(m,73381).
+char(o,73382).
+char(p,73383).
+char(o,73384).
+char(1,73385).
+char(7,73386).
+char(6,73387).
+char(c,73388).
+char(m,73389).
+char(o,73390).
+char(m,73391).
+char(o,73392).
+char(m,73393).
+char(o,73394).
+char(p,73395).
+char(9,73396).
+char(9,73397).
+char(9,73398).
+char(7,73399).
+char(c,73400).
+char(c,73401).
+char(p,73402).
+char(o,73403).
+char(p,73404).
+char(6,73405).
+char(4,73406).
+char(1,73407).
+char(7,73408).
+char(p,73409).
+char(2,73410).
+char(7,73411).
+char(0,73412).
+char(8,73413).
+char(c,73414).
+char(m,73415).
+char(o,73416).
+char(p,73417).
+char(2,73418).
+char(7,73419).
+char(3,73420).
+char(7,73421).
+char(p,73422).
+char(9,73423).
+char(2,73424).
+char(9,73425).
+char(1,73426).
+char(c,73427).
+char(c,73428).
+char(p,73429).
+char(3,73430).
+char(0,73431).
+char(3,73432).
+char(4,73433).
+char(p,73434).
+char(5,73435).
+char(6,73436).
+char(1,73437).
+char(3,73438).
+char(c,73439).
+char(c,73440).
+char(p,73441).
+char(o,73442).
+char(m,73443).
+char(4,73444).
+char(3,73445).
+char(2,73446).
+char(6,73447).
+char(c,73448).
+char(p,73449).
+char(o,73450).
+char(o,73451).
+char(m,73452).
+char(5,73453).
+char(9,73454).
+char(8,73455).
+char(8,73456).
+char(p,73457).
+char(o,73458).
+char(7,73459).
+char(4,73460).
+char(2,73461).
+char(9,73462).
+char(m,73463).
+char(2,73464).
+char(4,73465).
+char(6,73466).
+char(5,73467).
+char(c,73468).
+char(p,73469).
+char(o,73470).
+char(m,73471).
+char(o,73472).
+char(p,73473).
+char(4,73474).
+char(1,73475).
+char(9,73476).
+char(3,73477).
+char(c,73478).
+char(p,73479).
+char(o,73480).
+char(1,73481).
+char(7,73482).
+char(2,73483).
+char(0,73484).
+char(m,73485).
+char(4,73486).
+char(1,73487).
+char(3,73488).
+char(9,73489).
+char(m,73490).
+char(o,73491).
+char(m,73492).
+char(8,73493).
+char(2,73494).
+char(4,73495).
+char(3,73496).
+char(c,73497).
+char(c,73498).
+char(c,73499).
+char(m,73500).
+char(7,73501).
+char(1,73502).
+char(1,73503).
+char(4,73504).
+char(c,73505).
+char(c,73506).
+char(m,73507).
+char(8,73508).
+char(4,73509).
+char(9,73510).
+char(6,73511).
+char(c,73512).
+char(c,73513).
+char(c,73514).
+char(c,73515).
+char(c,73516).
+char(m,73517).
+char(o,73518).
+char(p,73519).
+char(o,73520).
+char(5,73521).
+char(4,73522).
+char(0,73523).
+char(8,73524).
+char(p,73525).
+char(o,73526).
+char(o,73527).
+char(8,73528).
+char(5,73529).
+char(5,73530).
+char(8,73531).
+char(c,73532).
+char(m,73533).
+char(1,73534).
+char(5,73535).
+char(2,73536).
+char(4,73537).
+char(c,73538).
+char(c,73539).
+char(c,73540).
+char(m,73541).
+char(4,73542).
+char(8,73543).
+char(1,73544).
+char(6,73545).
+char(p,73546).
+char(o,73547).
+char(m,73548).
+char(o,73549).
+char(o,73550).
+char(p,73551).
+char(5,73552).
+char(7,73553).
+char(3,73554).
+char(3,73555).
+char(c,73556).
+char(p,73557).
+char(1,73558).
+char(0,73559).
+char(7,73560).
+char(3,73561).
+char(m,73562).
+char(o,73563).
+char(6,73564).
+char(1,73565).
+char(3,73566).
+char(c,73567).
+char(m,73568).
+char(o,73569).
+char(o,73570).
+char(2,73571).
+char(0,73572).
+char(5,73573).
+char(1,73574).
+char(c,73575).
+char(c,73576).
+char(p,73577).
+char(3,73578).
+char(6,73579).
+char(9,73580).
+char(6,73581).
+char(c,73582).
+char(c,73583).
+char(m,73584).
+char(8,73585).
+char(0,73586).
+char(6,73587).
+char(8,73588).
+char(c,73589).
+char(c,73590).
+char(c,73591).
+char(c,73592).
+char(c,73593).
+char(p,73594).
+char(o,73595).
+char(m,73596).
+char(9,73597).
+char(4,73598).
+char(3,73599).
+char(3,73600).
+char(p,73601).
+char(9,73602).
+char(7,73603).
+char(7,73604).
+char(8,73605).
+char(m,73606).
+char(8,73607).
+char(7,73608).
+char(4,73609).
+char(c,73610).
+char(m,73611).
+char(1,73612).
+char(2,73613).
+char(4,73614).
+char(2,73615).
+char(p,73616).
+char(4,73617).
+char(9,73618).
+char(9,73619).
+char(c,73620).
+char(p,73621).
+char(o,73622).
+char(7,73623).
+char(5,73624).
+char(1,73625).
+char(2,73626).
+char(c,73627).
+char(m,73628).
+char(4,73629).
+char(0,73630).
+char(2,73631).
+char(5,73632).
+char(m,73633).
+char(8,73634).
+char(6,73635).
+char(8,73636).
+char(7,73637).
+char(c,73638).
+char(m,73639).
+char(9,73640).
+char(8,73641).
+char(4,73642).
+char(0,73643).
+char(m,73644).
+char(9,73645).
+char(1,73646).
+char(9,73647).
+char(3,73648).
+char(c,73649).
+char(m,73650).
+char(2,73651).
+char(6,73652).
+char(5,73653).
+char(7,73654).
+char(c,73655).
+char(c,73656).
+char(p,73657).
+char(o,73658).
+char(4,73659).
+char(9,73660).
+char(4,73661).
+char(8,73662).
+char(c,73663).
+char(c,73664).
+char(c,73665).
+char(m,73666).
+char(o,73667).
+char(p,73668).
+char(3,73669).
+char(2,73670).
+char(2,73671).
+char(2,73672).
+char(p,73673).
+char(o,73674).
+char(p,73675).
+char(9,73676).
+char(4,73677).
+char(9,73678).
+char(5,73679).
+char(c,73680).
+char(m,73681).
+char(o,73682).
+char(m,73683).
+char(6,73684).
+char(0,73685).
+char(4,73686).
+char(2,73687).
+char(c,73688).
+char(p,73689).
+char(7,73690).
+char(2,73691).
+char(3,73692).
+char(9,73693).
+char(p,73694).
+char(4,73695).
+char(1,73696).
+char(5,73697).
+char(1,73698).
+char(p,73699).
+char(8,73700).
+char(7,73701).
+char(5,73702).
+char(4,73703).
+char(c,73704).
+char(p,73705).
+char(7,73706).
+char(1,73707).
+char(2,73708).
+char(p,73709).
+char(o,73710).
+char(8,73711).
+char(9,73712).
+char(6,73713).
+char(4,73714).
+char(p,73715).
+char(7,73716).
+char(7,73717).
+char(3,73718).
+char(8,73719).
+char(p,73720).
+char(7,73721).
+char(9,73722).
+char(4,73723).
+char(7,73724).
+char(c,73725).
+char(m,73726).
+char(o,73727).
+char(m,73728).
+char(o,73729).
+char(m,73730).
+char(o,73731).
+char(m,73732).
+char(2,73733).
+char(9,73734).
+char(7,73735).
+char(9,73736).
+char(p,73737).
+char(o,73738).
+char(7,73739).
+char(2,73740).
+char(1,73741).
+char(c,73742).
+char(p,73743).
+char(6,73744).
+char(7,73745).
+char(4,73746).
+char(8,73747).
+char(m,73748).
+char(8,73749).
+char(6,73750).
+char(7,73751).
+char(7,73752).
+char(c,73753).
+char(c,73754).
+char(c,73755).
+char(p,73756).
+char(8,73757).
+char(6,73758).
+char(1,73759).
+char(3,73760).
+char(c,73761).
+char(m,73762).
+char(o,73763).
+char(p,73764).
+char(5,73765).
+char(3,73766).
+char(9,73767).
+char(8,73768).
+char(m,73769).
+char(8,73770).
+char(6,73771).
+char(7,73772).
+char(p,73773).
+char(4,73774).
+char(8,73775).
+char(8,73776).
+char(9,73777).
+char(m,73778).
+char(3,73779).
+char(4,73780).
+char(9,73781).
+char(m,73782).
+char(o,73783).
+char(m,73784).
+char(o,73785).
+char(9,73786).
+char(1,73787).
+char(6,73788).
+char(3,73789).
+char(p,73790).
+char(o,73791).
+char(p,73792).
+char(2,73793).
+char(7,73794).
+char(2,73795).
+char(1,73796).
+char(c,73797).
+char(p,73798).
+char(o,73799).
+char(o,73800).
+char(m,73801).
+char(8,73802).
+char(0,73803).
+char(2,73804).
+char(2,73805).
+char(m,73806).
+char(o,73807).
+char(o,73808).
+char(m,73809).
+char(o,73810).
+char(p,73811).
+char(o,73812).
+char(p,73813).
+char(o,73814).
+char(p,73815).
+char(7,73816).
+char(3,73817).
+char(2,73818).
+char(4,73819).
+char(c,73820).
+char(m,73821).
+char(7,73822).
+char(3,73823).
+char(8,73824).
+char(2,73825).
+char(c,73826).
+char(p,73827).
+char(o,73828).
+char(o,73829).
+char(m,73830).
+char(o,73831).
+char(8,73832).
+char(3,73833).
+char(6,73834).
+char(5,73835).
+char(c,73836).
+char(c,73837).
+char(m,73838).
+char(5,73839).
+char(0,73840).
+char(2,73841).
+char(7,73842).
+char(c,73843).
+char(p,73844).
+char(1,73845).
+char(0,73846).
+char(4,73847).
+char(1,73848).
+char(p,73849).
+char(o,73850).
+char(m,73851).
+char(7,73852).
+char(1,73853).
+char(0,73854).
+char(6,73855).
+char(c,73856).
+char(p,73857).
+char(o,73858).
+char(p,73859).
+char(o,73860).
+char(8,73861).
+char(4,73862).
+char(1,73863).
+char(4,73864).
+char(m,73865).
+char(o,73866).
+char(o,73867).
+char(o,73868).
+char(m,73869).
+char(o,73870).
+char(o,73871).
+char(m,73872).
+char(3,73873).
+char(6,73874).
+char(8,73875).
+char(7,73876).
+char(m,73877).
+char(o,73878).
+char(o,73879).
+char(p,73880).
+char(o,73881).
+char(p,73882).
+char(6,73883).
+char(2,73884).
+char(6,73885).
+char(5,73886).
+char(p,73887).
+char(8,73888).
+char(2,73889).
+char(5,73890).
+char(2,73891).
+char(m,73892).
+char(o,73893).
+char(p,73894).
+char(6,73895).
+char(3,73896).
+char(4,73897).
+char(0,73898).
+char(c,73899).
+char(c,73900).
+char(c,73901).
+char(c,73902).
+char(p,73903).
+char(o,73904).
+char(p,73905).
+char(7,73906).
+char(6,73907).
+char(2,73908).
+char(2,73909).
+char(p,73910).
+char(o,73911).
+char(o,73912).
+char(9,73913).
+char(0,73914).
+char(8,73915).
+char(9,73916).
+char(m,73917).
+char(1,73918).
+char(1,73919).
+char(0,73920).
+char(5,73921).
+char(m,73922).
+char(5,73923).
+char(9,73924).
+char(9,73925).
+char(3,73926).
+char(c,73927).
+char(c,73928).
+char(p,73929).
+char(7,73930).
+char(1,73931).
+char(9,73932).
+char(7,73933).
+char(p,73934).
+char(4,73935).
+char(6,73936).
+char(8,73937).
+char(4,73938).
+char(c,73939).
+char(c,73940).
+char(c,73941).
+char(c,73942).
+char(c,73943).
+char(p,73944).
+char(o,73945).
+char(5,73946).
+char(9,73947).
+char(3,73948).
+char(4,73949).
+char(p,73950).
+char(o,73951).
+char(p,73952).
+char(o,73953).
+char(m,73954).
+char(3,73955).
+char(8,73956).
+char(7,73957).
+char(1,73958).
+char(p,73959).
+char(4,73960).
+char(7,73961).
+char(8,73962).
+char(0,73963).
+char(c,73964).
+char(p,73965).
+char(6,73966).
+char(6,73967).
+char(9,73968).
+char(1,73969).
+char(p,73970).
+char(o,73971).
+char(m,73972).
+char(o,73973).
+char(3,73974).
+char(8,73975).
+char(4,73976).
+char(m,73977).
+char(o,73978).
+char(m,73979).
+char(6,73980).
+char(6,73981).
+char(1,73982).
+char(6,73983).
+char(c,73984).
+char(p,73985).
+char(7,73986).
+char(6,73987).
+char(5,73988).
+char(4,73989).
+char(m,73990).
+char(6,73991).
+char(7,73992).
+char(9,73993).
+char(6,73994).
+char(c,73995).
+char(c,73996).
+char(m,73997).
+char(1,73998).
+char(3,73999).
+char(9,74000).
+char(p,74001).
+char(6,74002).
+char(8,74003).
+char(7,74004).
+char(2,74005).
+char(c,74006).
+char(p,74007).
+char(o,74008).
+char(p,74009).
+char(o,74010).
+char(8,74011).
+char(4,74012).
+char(7,74013).
+char(4,74014).
+char(c,74015).
+char(c,74016).
+char(c,74017).
+char(c,74018).
+char(c,74019).
+char(p,74020).
+char(o,74021).
+char(m,74022).
+char(1,74023).
+char(9,74024).
+char(2,74025).
+char(6,74026).
+char(c,74027).
+char(m,74028).
+char(8,74029).
+char(3,74030).
+char(0,74031).
+char(5,74032).
+char(c,74033).
+char(c,74034).
+char(m,74035).
+char(1,74036).
+char(5,74037).
+char(m,74038).
+char(6,74039).
+char(4,74040).
+char(6,74041).
+char(1,74042).
+char(c,74043).
+char(m,74044).
+char(o,74045).
+char(o,74046).
+char(2,74047).
+char(9,74048).
+char(5,74049).
+char(4,74050).
+char(p,74051).
+char(o,74052).
+char(m,74053).
+char(o,74054).
+char(3,74055).
+char(3,74056).
+char(5,74057).
+char(8,74058).
+char(p,74059).
+char(6,74060).
+char(8,74061).
+char(4,74062).
+char(2,74063).
+char(c,74064).
+char(p,74065).
+char(6,74066).
+char(9,74067).
+char(0,74068).
+char(4,74069).
+char(c,74070).
+char(m,74071).
+char(o,74072).
+char(p,74073).
+char(o,74074).
+char(p,74075).
+char(o,74076).
+char(p,74077).
+char(9,74078).
+char(7,74079).
+char(3,74080).
+char(1,74081).
+char(m,74082).
+char(o,74083).
+char(p,74084).
+char(6,74085).
+char(4,74086).
+char(3,74087).
+char(8,74088).
+char(p,74089).
+char(4,74090).
+char(0,74091).
+char(9,74092).
+char(0,74093).
+char(c,74094).
+char(m,74095).
+char(1,74096).
+char(6,74097).
+char(8,74098).
+char(3,74099).
+char(p,74100).
+char(1,74101).
+char(7,74102).
+char(8,74103).
+char(8,74104).
+char(c,74105).
+char(m,74106).
+char(o,74107).
+char(p,74108).
+char(o,74109).
+char(m,74110).
+char(o,74111).
+char(p,74112).
+char(o,74113).
+char(p,74114).
+char(o,74115).
+char(m,74116).
+char(o,74117).
+char(m,74118).
+char(3,74119).
+char(6,74120).
+char(6,74121).
+char(9,74122).
+char(c,74123).
+char(m,74124).
+char(7,74125).
+char(7,74126).
+char(9,74127).
+char(1,74128).
+char(m,74129).
+char(o,74130).
+char(p,74131).
+char(o,74132).
+char(p,74133).
+char(o,74134).
+char(p,74135).
+char(4,74136).
+char(1,74137).
+char(0,74138).
+char(1,74139).
+char(c,74140).
+char(p,74141).
+char(3,74142).
+char(8,74143).
+char(7,74144).
+char(4,74145).
+char(m,74146).
+char(6,74147).
+char(8,74148).
+char(3,74149).
+char(p,74150).
+char(o,74151).
+char(m,74152).
+char(6,74153).
+char(6,74154).
+char(5,74155).
+char(9,74156).
+char(c,74157).
+char(p,74158).
+char(1,74159).
+char(9,74160).
+char(7,74161).
+char(p,74162).
+char(5,74163).
+char(6,74164).
+char(6,74165).
+char(3,74166).
+char(c,74167).
+char(p,74168).
+char(2,74169).
+char(9,74170).
+char(3,74171).
+char(4,74172).
+char(m,74173).
+char(2,74174).
+char(3,74175).
+char(7,74176).
+char(9,74177).
+char(m,74178).
+char(1,74179).
+char(3,74180).
+char(3,74181).
+char(5,74182).
+char(c,74183).
+char(m,74184).
+char(8,74185).
+char(9,74186).
+char(4,74187).
+char(5,74188).
+char(c,74189).
+char(p,74190).
+char(o,74191).
+char(o,74192).
+char(4,74193).
+char(8,74194).
+char(1,74195).
+char(4,74196).
+char(c,74197).
+char(c,74198).
+char(c,74199).
+char(m,74200).
+char(6,74201).
+char(8,74202).
+char(6,74203).
+char(8,74204).
+char(c,74205).
+char(m,74206).
+char(o,74207).
+char(p,74208).
+char(4,74209).
+char(2,74210).
+char(1,74211).
+char(5,74212).
+char(p,74213).
+char(o,74214).
+char(p,74215).
+char(o,74216).
+char(m,74217).
+char(8,74218).
+char(0,74219).
+char(2,74220).
+char(5,74221).
+char(m,74222).
+char(5,74223).
+char(6,74224).
+char(3,74225).
+char(2,74226).
+char(c,74227).
+char(m,74228).
+char(o,74229).
+char(1,74230).
+char(5,74231).
+char(3,74232).
+char(6,74233).
+char(p,74234).
+char(o,74235).
+char(7,74236).
+char(3,74237).
+char(4,74238).
+char(9,74239).
+char(m,74240).
+char(9,74241).
+char(4,74242).
+char(2,74243).
+char(6,74244).
+char(m,74245).
+char(o,74246).
+char(3,74247).
+char(2,74248).
+char(4,74249).
+char(c,74250).
+char(c,74251).
+char(c,74252).
+char(c,74253).
+char(c,74254).
+char(c,74255).
+char(m,74256).
+char(5,74257).
+char(7,74258).
+char(9,74259).
+char(m,74260).
+char(1,74261).
+char(5,74262).
+char(4,74263).
+char(2,74264).
+char(m,74265).
+char(4,74266).
+char(8,74267).
+char(8,74268).
+char(5,74269).
+char(m,74270).
+char(o,74271).
+char(m,74272).
+char(o,74273).
+char(m,74274).
+char(5,74275).
+char(6,74276).
+char(3,74277).
+char(0,74278).
+char(p,74279).
+char(o,74280).
+char(m,74281).
+char(9,74282).
+char(1,74283).
+char(2,74284).
+char(3,74285).
+char(m,74286).
+char(5,74287).
+char(3,74288).
+char(6,74289).
+char(7,74290).
+char(m,74291).
+char(1,74292).
+char(0,74293).
+char(6,74294).
+char(6,74295).
+char(c,74296).
+char(m,74297).
+char(o,74298).
+char(m,74299).
+char(1,74300).
+char(8,74301).
+char(3,74302).
+char(4,74303).
+char(p,74304).
+char(2,74305).
+char(8,74306).
+char(1,74307).
+char(0,74308).
+char(c,74309).
+char(p,74310).
+char(o,74311).
+char(8,74312).
+char(9,74313).
+char(2,74314).
+char(6,74315).
+char(m,74316).
+char(7,74317).
+char(2,74318).
+char(9,74319).
+char(4,74320).
+char(c,74321).
+char(p,74322).
+char(o,74323).
+char(p,74324).
+char(4,74325).
+char(2,74326).
+char(7,74327).
+char(m,74328).
+char(o,74329).
+char(p,74330).
+char(5,74331).
+char(0,74332).
+char(1,74333).
+char(2,74334).
+char(p,74335).
+char(o,74336).
+char(m,74337).
+char(2,74338).
+char(0,74339).
+char(0,74340).
+char(9,74341).
+char(c,74342).
+char(c,74343).
+char(m,74344).
+char(1,74345).
+char(4,74346).
+char(5,74347).
+char(0,74348).
+char(p,74349).
+char(o,74350).
+char(m,74351).
+char(1,74352).
+char(1,74353).
+char(6,74354).
+char(0,74355).
+char(p,74356).
+char(o,74357).
+char(p,74358).
+char(o,74359).
+char(m,74360).
+char(o,74361).
+char(p,74362).
+char(o,74363).
+char(p,74364).
+char(6,74365).
+char(9,74366).
+char(1,74367).
+char(0,74368).
+char(c,74369).
+char(c,74370).
+char(p,74371).
+char(o,74372).
+char(o,74373).
+char(p,74374).
+char(8,74375).
+char(7,74376).
+char(0,74377).
+char(4,74378).
+char(c,74379).
+char(m,74380).
+char(8,74381).
+char(2,74382).
+char(7,74383).
+char(3,74384).
+char(p,74385).
+char(o,74386).
+char(p,74387).
+char(1,74388).
+char(1,74389).
+char(0,74390).
+char(3,74391).
+char(c,74392).
+char(c,74393).
+char(p,74394).
+char(o,74395).
+char(6,74396).
+char(2,74397).
+char(6,74398).
+char(1,74399).
+char(p,74400).
+char(9,74401).
+char(4,74402).
+char(6,74403).
+char(9,74404).
+char(m,74405).
+char(9,74406).
+char(6,74407).
+char(p,74408).
+char(6,74409).
+char(2,74410).
+char(3,74411).
+char(5,74412).
+char(c,74413).
+char(c,74414).
+char(c,74415).
+char(p,74416).
+char(8,74417).
+char(1,74418).
+char(1,74419).
+char(1,74420).
+char(m,74421).
+char(8,74422).
+char(0,74423).
+char(5,74424).
+char(3,74425).
+char(c,74426).
+char(c,74427).
+char(c,74428).
+char(c,74429).
+char(c,74430).
+char(m,74431).
+char(6,74432).
+char(8,74433).
+char(9,74434).
+char(4,74435).
+char(c,74436).
+char(c,74437).
+char(m,74438).
+char(1,74439).
+char(2,74440).
+char(3,74441).
+char(0,74442).
+char(m,74443).
+char(4,74444).
+char(1,74445).
+char(4,74446).
+char(9,74447).
+char(c,74448).
+char(p,74449).
+char(2,74450).
+char(0,74451).
+char(0,74452).
+char(7,74453).
+char(c,74454).
+char(m,74455).
+char(o,74456).
+char(4,74457).
+char(6,74458).
+char(5,74459).
+char(3,74460).
+char(m,74461).
+char(o,74462).
+char(m,74463).
+char(o,74464).
+char(m,74465).
+char(9,74466).
+char(7,74467).
+char(7,74468).
+char(4,74469).
+char(m,74470).
+char(2,74471).
+char(2,74472).
+char(9,74473).
+char(5,74474).
+char(m,74475).
+char(o,74476).
+char(o,74477).
+char(p,74478).
+char(o,74479).
+char(p,74480).
+char(o,74481).
+char(m,74482).
+char(o,74483).
+char(m,74484).
+char(o,74485).
+char(m,74486).
+char(9,74487).
+char(7,74488).
+char(6,74489).
+char(9,74490).
+char(m,74491).
+char(o,74492).
+char(p,74493).
+char(o,74494).
+char(p,74495).
+char(4,74496).
+char(3,74497).
+char(2,74498).
+char(5,74499).
+char(c,74500).
+char(m,74501).
+char(o,74502).
+char(m,74503).
+char(6,74504).
+char(8,74505).
+char(9,74506).
+char(9,74507).
+char(c,74508).
+char(p,74509).
+char(o,74510).
+char(m,74511).
+char(o,74512).
+char(o,74513).
+char(p,74514).
+char(7,74515).
+char(3,74516).
+char(7,74517).
+char(0,74518).
+char(c,74519).
+char(m,74520).
+char(o,74521).
+char(m,74522).
+char(8,74523).
+char(6,74524).
+char(2,74525).
+char(0,74526).
+char(p,74527).
+char(o,74528).
+char(p,74529).
+char(9,74530).
+char(5,74531).
+char(8,74532).
+char(2,74533).
+char(c,74534).
+char(c,74535).
+char(p,74536).
+char(o,74537).
+char(o,74538).
+char(m,74539).
+char(o,74540).
+char(5,74541).
+char(9,74542).
+char(9,74543).
+char(m,74544).
+char(4,74545).
+char(0,74546).
+char(5,74547).
+char(c,74548).
+char(c,74549).
+char(c,74550).
+char(c,74551).
+char(p,74552).
+char(o,74553).
+char(m,74554).
+char(o,74555).
+char(p,74556).
+char(7,74557).
+char(5,74558).
+char(1,74559).
+char(4,74560).
+char(c,74561).
+char(c,74562).
+char(m,74563).
+char(o,74564).
+char(m,74565).
+char(o,74566).
+char(4,74567).
+char(6,74568).
+char(9,74569).
+char(4,74570).
+char(p,74571).
+char(1,74572).
+char(0,74573).
+char(5,74574).
+char(2,74575).
+char(p,74576).
+char(o,74577).
+char(p,74578).
+char(o,74579).
+char(m,74580).
+char(o,74581).
+char(2,74582).
+char(2,74583).
+char(4,74584).
+char(9,74585).
+char(c,74586).
+char(p,74587).
+char(o,74588).
+char(p,74589).
+char(o,74590).
+char(p,74591).
+char(8,74592).
+char(9,74593).
+char(2,74594).
+char(8,74595).
+char(m,74596).
+char(o,74597).
+char(o,74598).
+char(5,74599).
+char(5,74600).
+char(4,74601).
+char(8,74602).
+char(p,74603).
+char(2,74604).
+char(4,74605).
+char(1,74606).
+char(3,74607).
+char(c,74608).
+char(p,74609).
+char(o,74610).
+char(m,74611).
+char(7,74612).
+char(2,74613).
+char(6,74614).
+char(1,74615).
+char(m,74616).
+char(1,74617).
+char(3,74618).
+char(5,74619).
+char(7,74620).
+char(p,74621).
+char(7,74622).
+char(1,74623).
+char(0,74624).
+char(6,74625).
+char(c,74626).
+char(p,74627).
+char(o,74628).
+char(m,74629).
+char(o,74630).
+char(p,74631).
+char(o,74632).
+char(m,74633).
+char(7,74634).
+char(5,74635).
+char(9,74636).
+char(9,74637).
+char(m,74638).
+char(o,74639).
+char(m,74640).
+char(3,74641).
+char(0,74642).
+char(6,74643).
+char(2,74644).
+char(m,74645).
+char(o,74646).
+char(m,74647).
+char(o,74648).
+char(p,74649).
+char(9,74650).
+char(4,74651).
+char(1,74652).
+char(1,74653).
+char(p,74654).
+char(o,74655).
+char(p,74656).
+char(3,74657).
+char(0,74658).
+char(2,74659).
+char(2,74660).
+char(c,74661).
+char(p,74662).
+char(o,74663).
+char(1,74664).
+char(9,74665).
+char(8,74666).
+char(6,74667).
+char(m,74668).
+char(6,74669).
+char(2,74670).
+char(7,74671).
+char(5,74672).
+char(p,74673).
+char(o,74674).
+char(p,74675).
+char(7,74676).
+char(9,74677).
+char(1,74678).
+char(8,74679).
+char(c,74680).
+char(p,74681).
+char(3,74682).
+char(2,74683).
+char(5,74684).
+char(8,74685).
+char(m,74686).
+char(9,74687).
+char(2,74688).
+char(7,74689).
+char(5,74690).
+char(m,74691).
+char(o,74692).
+char(m,74693).
+char(5,74694).
+char(1,74695).
+char(6,74696).
+char(7,74697).
+char(c,74698).
+char(c,74699).
+char(p,74700).
+char(o,74701).
+char(m,74702).
+char(6,74703).
+char(4,74704).
+char(4,74705).
+char(6,74706).
+char(p,74707).
+char(o,74708).
+char(p,74709).
+char(o,74710).
+char(6,74711).
+char(1,74712).
+char(3,74713).
+char(3,74714).
+char(p,74715).
+char(1,74716).
+char(4,74717).
+char(4,74718).
+char(0,74719).
+char(m,74720).
+char(7,74721).
+char(8,74722).
+char(1,74723).
+char(0,74724).
+char(p,74725).
+char(o,74726).
+char(p,74727).
+char(o,74728).
+char(5,74729).
+char(7,74730).
+char(8,74731).
+char(2,74732).
+char(c,74733).
+char(c,74734).
+char(p,74735).
+char(o,74736).
+char(m,74737).
+char(8,74738).
+char(6,74739).
+char(5,74740).
+char(1,74741).
+char(c,74742).
+char(m,74743).
+char(1,74744).
+char(0,74745).
+char(7,74746).
+char(4,74747).
+char(p,74748).
+char(9,74749).
+char(1,74750).
+char(6,74751).
+char(4,74752).
+char(p,74753).
+char(o,74754).
+char(p,74755).
+char(o,74756).
+char(m,74757).
+char(2,74758).
+char(6,74759).
+char(2,74760).
+char(1,74761).
+char(c,74762).
+char(m,74763).
+char(o,74764).
+char(m,74765).
+char(o,74766).
+char(m,74767).
+char(o,74768).
+char(p,74769).
+char(o,74770).
+char(3,74771).
+char(5,74772).
+char(0,74773).
+char(3,74774).
+char(m,74775).
+char(o,74776).
+char(o,74777).
+char(4,74778).
+char(3,74779).
+char(6,74780).
+char(0,74781).
+char(c,74782).
+char(c,74783).
+char(c,74784).
+char(p,74785).
+char(1,74786).
+char(8,74787).
+char(2,74788).
+char(8,74789).
+char(c,74790).
+char(m,74791).
+char(o,74792).
+char(o,74793).
+char(p,74794).
+char(8,74795).
+char(5,74796).
+char(8,74797).
+char(6,74798).
+char(c,74799).
+char(c,74800).
+char(c,74801).
+char(c,74802).
+char(c,74803).
+char(p,74804).
+char(7,74805).
+char(0,74806).
+char(4,74807).
+char(m,74808).
+char(4,74809).
+char(1,74810).
+char(0,74811).
+char(c,74812).
+char(c,74813).
+char(m,74814).
+char(o,74815).
+char(p,74816).
+char(o,74817).
+char(m,74818).
+char(7,74819).
+char(1,74820).
+char(0,74821).
+char(3,74822).
+char(p,74823).
+char(o,74824).
+char(o,74825).
+char(4,74826).
+char(2,74827).
+char(8,74828).
+char(8,74829).
+char(c,74830).
+char(m,74831).
+char(4,74832).
+char(0,74833).
+char(1,74834).
+char(8,74835).
+char(c,74836).
+char(m,74837).
+char(1,74838).
+char(4,74839).
+char(8,74840).
+char(0,74841).
+char(c,74842).
+char(c,74843).
+char(c,74844).
+char(c,74845).
+char(p,74846).
+char(1,74847).
+char(3,74848).
+char(5,74849).
+char(9,74850).
+char(p,74851).
+char(2,74852).
+char(3,74853).
+char(4,74854).
+char(2,74855).
+char(m,74856).
+char(o,74857).
+char(p,74858).
+char(o,74859).
+char(p,74860).
+char(2,74861).
+char(3,74862).
+char(7,74863).
+char(3,74864).
+char(m,74865).
+char(2,74866).
+char(2,74867).
+char(2,74868).
+char(3,74869).
+char(c,74870).
+char(p,74871).
+char(9,74872).
+char(0,74873).
+char(2,74874).
+char(0,74875).
+char(c,74876).
+char(m,74877).
+char(7,74878).
+char(2,74879).
+char(3,74880).
+char(0,74881).
+char(c,74882).
+char(m,74883).
+char(1,74884).
+char(3,74885).
+char(7,74886).
+char(1,74887).
+char(c,74888).
+char(c,74889).
+char(c,74890).
+char(p,74891).
+char(o,74892).
+char(p,74893).
+char(o,74894).
+char(9,74895).
+char(2,74896).
+char(5,74897).
+char(9,74898).
+char(m,74899).
+char(o,74900).
+char(p,74901).
+char(o,74902).
+char(p,74903).
+char(4,74904).
+char(8,74905).
+char(3,74906).
+char(4,74907).
+char(m,74908).
+char(5,74909).
+char(4,74910).
+char(4,74911).
+char(8,74912).
+char(m,74913).
+char(o,74914).
+char(o,74915).
+char(p,74916).
+char(o,74917).
+char(o,74918).
+char(7,74919).
+char(1,74920).
+char(p,74921).
+char(o,74922).
+char(m,74923).
+char(8,74924).
+char(6,74925).
+char(1,74926).
+char(6,74927).
+char(c,74928).
+char(m,74929).
+char(o,74930).
+char(o,74931).
+char(o,74932).
+char(p,74933).
+char(o,74934).
+char(m,74935).
+char(3,74936).
+char(7,74937).
+char(6,74938).
+char(6,74939).
+char(c,74940).
+char(c,74941).
+char(p,74942).
+char(5,74943).
+char(4,74944).
+char(6,74945).
+char(c,74946).
+char(m,74947).
+char(2,74948).
+char(3,74949).
+char(7,74950).
+char(0,74951).
+char(c,74952).
+char(m,74953).
+char(o,74954).
+char(3,74955).
+char(1,74956).
+char(2,74957).
+char(7,74958).
+char(m,74959).
+char(o,74960).
+char(p,74961).
+char(2,74962).
+char(1,74963).
+char(3,74964).
+char(1,74965).
+char(c,74966).
+char(c,74967).
+char(c,74968).
+char(c,74969).
+char(c,74970).
+char(c,74971).
+char(c,74972).
+char(c,74973).
+char(c,74974).
+char(c,74975).
+char(c,74976).
+char(c,74977).
+char(m,74978).
+char(o,74979).
+char(o,74980).
+char(p,74981).
+char(1,74982).
+char(1,74983).
+char(4,74984).
+char(8,74985).
+char(c,74986).
+char(c,74987).
+char(p,74988).
+char(o,74989).
+char(9,74990).
+char(3,74991).
+char(3,74992).
+char(4,74993).
+char(c,74994).
+char(m,74995).
+char(2,74996).
+char(7,74997).
+char(5,74998).
+char(8,74999).
+char(c,75000).
+char(p,75001).
+char(8,75002).
+char(0,75003).
+char(7,75004).
+char(7,75005).
+char(m,75006).
+char(1,75007).
+char(3,75008).
+char(5,75009).
+char(0,75010).
+char(c,75011).
+char(m,75012).
+char(o,75013).
+char(m,75014).
+char(8,75015).
+char(8,75016).
+char(6,75017).
+char(5,75018).
+char(m,75019).
+char(9,75020).
+char(6,75021).
+char(5,75022).
+char(1,75023).
+char(m,75024).
+char(8,75025).
+char(0,75026).
+char(3,75027).
+char(5,75028).
+char(c,75029).
+char(p,75030).
+char(o,75031).
+char(8,75032).
+char(7,75033).
+char(1,75034).
+char(9,75035).
+char(p,75036).
+char(o,75037).
+char(m,75038).
+char(o,75039).
+char(p,75040).
+char(o,75041).
+char(6,75042).
+char(4,75043).
+char(6,75044).
+char(1,75045).
+char(p,75046).
+char(3,75047).
+char(6,75048).
+char(9,75049).
+char(9,75050).
+char(c,75051).
+char(c,75052).
+char(c,75053).
+char(m,75054).
+char(o,75055).
+char(m,75056).
+char(o,75057).
+char(p,75058).
+char(o,75059).
+char(p,75060).
+char(2,75061).
+char(8,75062).
+char(8,75063).
+char(4,75064).
+char(c,75065).
+char(m,75066).
+char(o,75067).
+char(p,75068).
+char(o,75069).
+char(p,75070).
+char(5,75071).
+char(1,75072).
+char(0,75073).
+char(1,75074).
+char(p,75075).
+char(o,75076).
+char(m,75077).
+char(o,75078).
+char(p,75079).
+char(7,75080).
+char(6,75081).
+char(0,75082).
+char(0,75083).
+char(p,75084).
+char(o,75085).
+char(6,75086).
+char(2,75087).
+char(3,75088).
+char(1,75089).
+char(c,75090).
+char(m,75091).
+char(9,75092).
+char(0,75093).
+char(2,75094).
+char(c,75095).
+char(p,75096).
+char(o,75097).
+char(o,75098).
+char(3,75099).
+char(2,75100).
+char(3,75101).
+char(2,75102).
+char(m,75103).
+char(o,75104).
+char(o,75105).
+char(8,75106).
+char(3,75107).
+char(4,75108).
+char(5,75109).
+char(p,75110).
+char(6,75111).
+char(5,75112).
+char(6,75113).
+char(4,75114).
+char(p,75115).
+char(2,75116).
+char(7,75117).
+char(4,75118).
+char(2,75119).
+char(m,75120).
+char(o,75121).
+char(o,75122).
+char(p,75123).
+char(1,75124).
+char(4,75125).
+char(9,75126).
+char(6,75127).
+char(p,75128).
+char(o,75129).
+char(p,75130).
+char(o,75131).
+char(p,75132).
+char(8,75133).
+char(2,75134).
+char(9,75135).
+char(1,75136).
+char(c,75137).
+char(c,75138).
+char(c,75139).
+char(c,75140).
+char(m,75141).
+char(1,75142).
+char(2,75143).
+char(8,75144).
+char(3,75145).
+char(c,75146).
+char(m,75147).
+char(8,75148).
+char(5,75149).
+char(1,75150).
+char(8,75151).
+char(c,75152).
+char(p,75153).
+char(o,75154).
+char(p,75155).
+char(3,75156).
+char(4,75157).
+char(7,75158).
+char(4,75159).
+char(c,75160).
+char(c,75161).
+char(m,75162).
+char(1,75163).
+char(4,75164).
+char(8,75165).
+char(2,75166).
+char(c,75167).
+char(c,75168).
+char(m,75169).
+char(9,75170).
+char(3,75171).
+char(5,75172).
+char(4,75173).
+char(m,75174).
+char(4,75175).
+char(9,75176).
+char(2,75177).
+char(7,75178).
+char(p,75179).
+char(o,75180).
+char(p,75181).
+char(1,75182).
+char(3,75183).
+char(3,75184).
+char(4,75185).
+char(m,75186).
+char(9,75187).
+char(7,75188).
+char(9,75189).
+char(4,75190).
+char(m,75191).
+char(6,75192).
+char(6,75193).
+char(1,75194).
+char(9,75195).
+char(m,75196).
+char(6,75197).
+char(3,75198).
+char(1,75199).
+char(0,75200).
+char(c,75201).
+char(m,75202).
+char(2,75203).
+char(6,75204).
+char(0,75205).
+char(6,75206).
+char(m,75207).
+char(o,75208).
+char(7,75209).
+char(5,75210).
+char(8,75211).
+char(9,75212).
+char(p,75213).
+char(o,75214).
+char(p,75215).
+char(o,75216).
+char(o,75217).
+char(6,75218).
+char(4,75219).
+char(9,75220).
+char(c,75221).
+char(p,75222).
+char(o,75223).
+char(p,75224).
+char(3,75225).
+char(7,75226).
+char(8,75227).
+char(2,75228).
+char(m,75229).
+char(5,75230).
+char(1,75231).
+char(8,75232).
+char(1,75233).
+char(c,75234).
+char(m,75235).
+char(7,75236).
+char(5,75237).
+char(0,75238).
+char(c,75239).
+char(p,75240).
+char(o,75241).
+char(3,75242).
+char(9,75243).
+char(0,75244).
+char(6,75245).
+char(c,75246).
+char(p,75247).
+char(o,75248).
+char(m,75249).
+char(4,75250).
+char(4,75251).
+char(6,75252).
+char(2,75253).
+char(p,75254).
+char(o,75255).
+char(p,75256).
+char(4,75257).
+char(8,75258).
+char(5,75259).
+char(0,75260).
+char(c,75261).
+char(m,75262).
+char(1,75263).
+char(2,75264).
+char(8,75265).
+char(7,75266).
+char(p,75267).
+char(o,75268).
+char(p,75269).
+char(o,75270).
+char(p,75271).
+char(o,75272).
+char(p,75273).
+char(o,75274).
+char(m,75275).
+char(o,75276).
+char(2,75277).
+char(4,75278).
+char(3,75279).
+char(8,75280).
+char(c,75281).
+char(p,75282).
+char(9,75283).
+char(1,75284).
+char(7,75285).
+char(7,75286).
+char(p,75287).
+char(o,75288).
+char(m,75289).
+char(o,75290).
+char(p,75291).
+char(o,75292).
+char(p,75293).
+char(5,75294).
+char(4,75295).
+char(4,75296).
+char(4,75297).
+char(m,75298).
+char(o,75299).
+char(o,75300).
+char(m,75301).
+char(o,75302).
+char(o,75303).
+char(m,75304).
+char(o,75305).
+char(p,75306).
+char(o,75307).
+char(o,75308).
+char(m,75309).
+char(5,75310).
+char(8,75311).
+char(7,75312).
+char(4,75313).
+char(m,75314).
+char(o,75315).
+char(3,75316).
+char(7,75317).
+char(9,75318).
+char(3,75319).
+char(m,75320).
+char(2,75321).
+char(9,75322).
+char(4,75323).
+char(2,75324).
+char(p,75325).
+char(2,75326).
+char(7,75327).
+char(2,75328).
+char(9,75329).
+char(c,75330).
+char(c,75331).
+char(m,75332).
+char(o,75333).
+char(m,75334).
+char(o,75335).
+char(m,75336).
+char(4,75337).
+char(6,75338).
+char(2,75339).
+char(4,75340).
+char(c,75341).
+char(c,75342).
+char(p,75343).
+char(o,75344).
+char(p,75345).
+char(2,75346).
+char(4,75347).
+char(6,75348).
+char(6,75349).
+char(m,75350).
+char(3,75351).
+char(3,75352).
+char(4,75353).
+char(1,75354).
+char(m,75355).
+char(6,75356).
+char(1,75357).
+char(0,75358).
+char(0,75359).
+char(m,75360).
+char(8,75361).
+char(5,75362).
+char(0,75363).
+char(2,75364).
+char(c,75365).
+char(m,75366).
+char(8,75367).
+char(5,75368).
+char(5,75369).
+char(0,75370).
+char(c,75371).
+char(m,75372).
+char(4,75373).
+char(2,75374).
+char(7,75375).
+char(7,75376).
+char(p,75377).
+char(5,75378).
+char(4,75379).
+char(7,75380).
+char(9,75381).
+char(p,75382).
+char(2,75383).
+char(3,75384).
+char(1,75385).
+char(3,75386).
+char(p,75387).
+char(o,75388).
+char(p,75389).
+char(7,75390).
+char(0,75391).
+char(7,75392).
+char(8,75393).
+char(c,75394).
+char(c,75395).
+char(p,75396).
+char(6,75397).
+char(6,75398).
+char(3,75399).
+char(9,75400).
+char(c,75401).
+char(c,75402).
+char(c,75403).
+char(p,75404).
+char(2,75405).
+char(9,75406).
+char(4,75407).
+char(5,75408).
+char(c,75409).
+char(c,75410).
+char(m,75411).
+char(o,75412).
+char(o,75413).
+char(5,75414).
+char(6,75415).
+char(5,75416).
+char(4,75417).
+char(m,75418).
+char(9,75419).
+char(5,75420).
+char(7,75421).
+char(6,75422).
+char(m,75423).
+char(o,75424).
+char(m,75425).
+char(1,75426).
+char(6,75427).
+char(0,75428).
+char(m,75429).
+char(5,75430).
+char(5,75431).
+char(7,75432).
+char(5,75433).
+char(c,75434).
+char(p,75435).
+char(o,75436).
+char(o,75437).
+char(p,75438).
+char(o,75439).
+char(p,75440).
+char(8,75441).
+char(5,75442).
+char(7,75443).
+char(2,75444).
+char(c,75445).
+char(m,75446).
+char(o,75447).
+char(8,75448).
+char(6,75449).
+char(0,75450).
+char(3,75451).
+char(p,75452).
+char(6,75453).
+char(7,75454).
+char(8,75455).
+char(0,75456).
+char(m,75457).
+char(6,75458).
+char(5,75459).
+char(8,75460).
+char(4,75461).
+char(p,75462).
+char(o,75463).
+char(3,75464).
+char(2,75465).
+char(0,75466).
+char(9,75467).
+char(c,75468).
+char(m,75469).
+char(4,75470).
+char(5,75471).
+char(6,75472).
+char(2,75473).
+char(p,75474).
+char(7,75475).
+char(5,75476).
+char(7,75477).
+char(5,75478).
+char(c,75479).
+char(c,75480).
+char(c,75481).
+char(c,75482).
+char(c,75483).
+char(c,75484).
+char(m,75485).
+char(o,75486).
+char(m,75487).
+char(1,75488).
+char(8,75489).
+char(9,75490).
+char(5,75491).
+char(p,75492).
+char(5,75493).
+char(6,75494).
+char(5,75495).
+char(6,75496).
+char(c,75497).
+char(p,75498).
+char(5,75499).
+char(4,75500).
+char(6,75501).
+char(4,75502).
+char(c,75503).
+char(c,75504).
+char(m,75505).
+char(9,75506).
+char(5,75507).
+char(1,75508).
+char(c,75509).
+char(c,75510).
+char(p,75511).
+char(2,75512).
+char(5,75513).
+char(4,75514).
+char(9,75515).
+char(m,75516).
+char(1,75517).
+char(2,75518).
+char(9,75519).
+char(0,75520).
+char(c,75521).
+char(c,75522).
+char(m,75523).
+char(o,75524).
+char(p,75525).
+char(o,75526).
+char(o,75527).
+char(p,75528).
+char(2,75529).
+char(0,75530).
+char(p,75531).
+char(7,75532).
+char(5,75533).
+char(1,75534).
+char(1,75535).
+char(c,75536).
+char(p,75537).
+char(1,75538).
+char(3,75539).
+char(9,75540).
+char(7,75541).
+char(c,75542).
+char(c,75543).
+char(c,75544).
+char(p,75545).
+char(6,75546).
+char(8,75547).
+char(7,75548).
+char(7,75549).
+char(p,75550).
+char(7,75551).
+char(7,75552).
+char(3,75553).
+char(1,75554).
+char(m,75555).
+char(o,75556).
+char(m,75557).
+char(o,75558).
+char(p,75559).
+char(6,75560).
+char(5,75561).
+char(9,75562).
+char(5,75563).
+char(p,75564).
+char(1,75565).
+char(1,75566).
+char(2,75567).
+char(8,75568).
+char(c,75569).
+char(p,75570).
+char(o,75571).
+char(p,75572).
+char(5,75573).
+char(7,75574).
+char(2,75575).
+char(9,75576).
+char(p,75577).
+char(7,75578).
+char(4,75579).
+char(5,75580).
+char(7,75581).
+char(c,75582).
+char(c,75583).
+char(c,75584).
+char(c,75585).
+char(m,75586).
+char(o,75587).
+char(m,75588).
+char(o,75589).
+char(m,75590).
+char(1,75591).
+char(5,75592).
+char(8,75593).
+char(2,75594).
+char(c,75595).
+char(c,75596).
+char(m,75597).
+char(5,75598).
+char(2,75599).
+char(2,75600).
+char(0,75601).
+char(c,75602).
+char(c,75603).
+char(c,75604).
+char(c,75605).
+char(c,75606).
+char(p,75607).
+char(o,75608).
+char(p,75609).
+char(o,75610).
+char(5,75611).
+char(7,75612).
+char(2,75613).
+char(1,75614).
+char(p,75615).
+char(o,75616).
+char(m,75617).
+char(2,75618).
+char(1,75619).
+char(9,75620).
+char(9,75621).
+char(p,75622).
+char(o,75623).
+char(p,75624).
+char(1,75625).
+char(2,75626).
+char(8,75627).
+char(p,75628).
+char(o,75629).
+char(m,75630).
+char(o,75631).
+char(m,75632).
+char(1,75633).
+char(5,75634).
+char(9,75635).
+char(6,75636).
+char(c,75637).
+char(c,75638).
+char(m,75639).
+char(o,75640).
+char(m,75641).
+char(o,75642).
+char(o,75643).
+char(p,75644).
+char(2,75645).
+char(3,75646).
+char(5,75647).
+char(0,75648).
+char(c,75649).
+char(c,75650).
+char(c,75651).
+char(c,75652).
+char(c,75653).
+char(c,75654).
+char(m,75655).
+char(o,75656).
+char(p,75657).
+char(o,75658).
+char(m,75659).
+char(3,75660).
+char(3,75661).
+char(1,75662).
+char(4,75663).
+char(c,75664).
+char(p,75665).
+char(o,75666).
+char(p,75667).
+char(o,75668).
+char(m,75669).
+char(o,75670).
+char(m,75671).
+char(o,75672).
+char(m,75673).
+char(8,75674).
+char(6,75675).
+char(5,75676).
+char(8,75677).
+char(p,75678).
+char(8,75679).
+char(4,75680).
+char(5,75681).
+char(9,75682).
+char(m,75683).
+char(5,75684).
+char(8,75685).
+char(4,75686).
+char(5,75687).
+char(c,75688).
+char(c,75689).
+char(p,75690).
+char(1,75691).
+char(6,75692).
+char(4,75693).
+char(3,75694).
+char(p,75695).
+char(6,75696).
+char(5,75697).
+char(6,75698).
+char(8,75699).
+char(p,75700).
+char(o,75701).
+char(p,75702).
+char(7,75703).
+char(9,75704).
+char(4,75705).
+char(4,75706).
+char(m,75707).
+char(o,75708).
+char(m,75709).
+char(o,75710).
+char(m,75711).
+char(o,75712).
+char(p,75713).
+char(4,75714).
+char(1,75715).
+char(2,75716).
+char(3,75717).
+char(c,75718).
+char(m,75719).
+char(3,75720).
+char(2,75721).
+char(9,75722).
+char(1,75723).
+char(c,75724).
+char(c,75725).
+char(m,75726).
+char(o,75727).
+char(6,75728).
+char(1,75729).
+char(3,75730).
+char(5,75731).
+char(m,75732).
+char(4,75733).
+char(8,75734).
+char(7,75735).
+char(6,75736).
+char(p,75737).
+char(7,75738).
+char(7,75739).
+char(4,75740).
+char(8,75741).
+char(p,75742).
+char(o,75743).
+char(p,75744).
+char(o,75745).
+char(2,75746).
+char(8,75747).
+char(5,75748).
+char(8,75749).
+char(c,75750).
+char(c,75751).
+char(m,75752).
+char(9,75753).
+char(7,75754).
+char(5,75755).
+char(8,75756).
+char(c,75757).
+char(p,75758).
+char(o,75759).
+char(3,75760).
+char(9,75761).
+char(1,75762).
+char(p,75763).
+char(8,75764).
+char(5,75765).
+char(8,75766).
+char(5,75767).
+char(p,75768).
+char(7,75769).
+char(2,75770).
+char(7,75771).
+char(0,75772).
+char(m,75773).
+char(8,75774).
+char(2,75775).
+char(5,75776).
+char(1,75777).
+char(p,75778).
+char(o,75779).
+char(m,75780).
+char(6,75781).
+char(6,75782).
+char(4,75783).
+char(0,75784).
+char(p,75785).
+char(4,75786).
+char(6,75787).
+char(7,75788).
+char(8,75789).
+char(p,75790).
+char(2,75791).
+char(3,75792).
+char(5,75793).
+char(9,75794).
+char(c,75795).
+char(c,75796).
+char(m,75797).
+char(o,75798).
+char(o,75799).
+char(4,75800).
+char(5,75801).
+char(6,75802).
+char(1,75803).
+char(p,75804).
+char(1,75805).
+char(8,75806).
+char(5,75807).
+char(5,75808).
+char(m,75809).
+char(9,75810).
+char(3,75811).
+char(0,75812).
+char(2,75813).
+char(m,75814).
+char(5,75815).
+char(1,75816).
+char(3,75817).
+char(5,75818).
+char(c,75819).
+char(c,75820).
+char(c,75821).
+char(c,75822).
+char(m,75823).
+char(9,75824).
+char(1,75825).
+char(2,75826).
+char(0,75827).
+char(c,75828).
+char(p,75829).
+char(4,75830).
+char(2,75831).
+char(4,75832).
+char(2,75833).
+char(p,75834).
+char(o,75835).
+char(m,75836).
+char(6,75837).
+char(5,75838).
+char(6,75839).
+char(8,75840).
+char(m,75841).
+char(2,75842).
+char(1,75843).
+char(5,75844).
+char(9,75845).
+char(m,75846).
+char(o,75847).
+char(2,75848).
+char(9,75849).
+char(1,75850).
+char(3,75851).
+char(p,75852).
+char(o,75853).
+char(p,75854).
+char(o,75855).
+char(m,75856).
+char(6,75857).
+char(7,75858).
+char(5,75859).
+char(3,75860).
+char(p,75861).
+char(4,75862).
+char(7,75863).
+char(7,75864).
+char(4,75865).
+char(p,75866).
+char(o,75867).
+char(m,75868).
+char(4,75869).
+char(5,75870).
+char(5,75871).
+char(8,75872).
+char(p,75873).
+char(1,75874).
+char(6,75875).
+char(0,75876).
+char(8,75877).
+char(m,75878).
+char(8,75879).
+char(0,75880).
+char(7,75881).
+char(8,75882).
+char(m,75883).
+char(2,75884).
+char(2,75885).
+char(0,75886).
+char(5,75887).
+char(c,75888).
+char(p,75889).
+char(9,75890).
+char(3,75891).
+char(1,75892).
+char(7,75893).
+char(c,75894).
+char(c,75895).
+char(p,75896).
+char(o,75897).
+char(m,75898).
+char(o,75899).
+char(m,75900).
+char(1,75901).
+char(3,75902).
+char(9,75903).
+char(5,75904).
+char(m,75905).
+char(4,75906).
+char(1,75907).
+char(2,75908).
+char(5,75909).
+char(p,75910).
+char(1,75911).
+char(2,75912).
+char(6,75913).
+char(8,75914).
+char(c,75915).
+char(m,75916).
+char(3,75917).
+char(9,75918).
+char(9,75919).
+char(1,75920).
+char(c,75921).
+char(c,75922).
+char(c,75923).
+char(c,75924).
+char(m,75925).
+char(o,75926).
+char(m,75927).
+char(3,75928).
+char(2,75929).
+char(4,75930).
+char(4,75931).
+char(p,75932).
+char(7,75933).
+char(6,75934).
+char(3,75935).
+char(5,75936).
+char(c,75937).
+char(c,75938).
+char(c,75939).
+char(c,75940).
+char(c,75941).
+char(c,75942).
+char(c,75943).
+char(c,75944).
+char(c,75945).
+char(c,75946).
+char(p,75947).
+char(o,75948).
+char(p,75949).
+char(o,75950).
+char(p,75951).
+char(8,75952).
+char(2,75953).
+char(5,75954).
+char(5,75955).
+char(p,75956).
+char(5,75957).
+char(0,75958).
+char(4,75959).
+char(3,75960).
+char(p,75961).
+char(o,75962).
+char(8,75963).
+char(7,75964).
+char(4,75965).
+char(m,75966).
+char(5,75967).
+char(7,75968).
+char(2,75969).
+char(4,75970).
+char(c,75971).
+char(p,75972).
+char(o,75973).
+char(p,75974).
+char(o,75975).
+char(o,75976).
+char(p,75977).
+char(2,75978).
+char(0,75979).
+char(7,75980).
+char(7,75981).
+char(c,75982).
+char(c,75983).
+char(c,75984).
+char(m,75985).
+char(9,75986).
+char(3,75987).
+char(4,75988).
+char(p,75989).
+char(6,75990).
+char(5,75991).
+char(1,75992).
+char(1,75993).
+char(c,75994).
+char(c,75995).
+char(m,75996).
+char(o,75997).
+char(p,75998).
+char(9,75999).
+char(9,76000).
+char(7,76001).
+char(9,76002).
+char(p,76003).
+char(7,76004).
+char(2,76005).
+char(1,76006).
+char(1,76007).
+char(p,76008).
+char(o,76009).
+char(p,76010).
+char(9,76011).
+char(7,76012).
+char(0,76013).
+char(9,76014).
+char(m,76015).
+char(9,76016).
+char(7,76017).
+char(8,76018).
+char(7,76019).
+char(c,76020).
+char(c,76021).
+char(c,76022).
+char(c,76023).
+char(c,76024).
+char(c,76025).
+char(p,76026).
+char(o,76027).
+char(m,76028).
+char(2,76029).
+char(0,76030).
+char(1,76031).
+char(9,76032).
+char(c,76033).
+char(p,76034).
+char(o,76035).
+char(m,76036).
+char(o,76037).
+char(p,76038).
+char(3,76039).
+char(7,76040).
+char(7,76041).
+char(m,76042).
+char(5,76043).
+char(2,76044).
+char(6,76045).
+char(5,76046).
+char(m,76047).
+char(7,76048).
+char(5,76049).
+char(6,76050).
+char(8,76051).
+char(c,76052).
+char(c,76053).
+char(c,76054).
+char(c,76055).
+char(p,76056).
+char(o,76057).
+char(p,76058).
+char(o,76059).
+char(p,76060).
+char(o,76061).
+char(p,76062).
+char(1,76063).
+char(8,76064).
+char(1,76065).
+char(3,76066).
+char(m,76067).
+char(8,76068).
+char(5,76069).
+char(1,76070).
+char(6,76071).
+char(c,76072).
+char(c,76073).
+char(c,76074).
+char(p,76075).
+char(8,76076).
+char(4,76077).
+char(1,76078).
+char(4,76079).
+char(p,76080).
+char(4,76081).
+char(1,76082).
+char(1,76083).
+char(c,76084).
+char(c,76085).
+char(c,76086).
+char(m,76087).
+char(o,76088).
+char(m,76089).
+char(o,76090).
+char(m,76091).
+char(o,76092).
+char(p,76093).
+char(o,76094).
+char(o,76095).
+char(p,76096).
+char(o,76097).
+char(p,76098).
+char(o,76099).
+char(o,76100).
+char(p,76101).
+char(o,76102).
+char(6,76103).
+char(3,76104).
+char(9,76105).
+char(3,76106).
+char(c,76107).
+char(m,76108).
+char(3,76109).
+char(5,76110).
+char(4,76111).
+char(4,76112).
+char(c,76113).
+char(c,76114).
+char(c,76115).
+char(c,76116).
+char(c,76117).
+char(m,76118).
+char(8,76119).
+char(6,76120).
+char(8,76121).
+char(9,76122).
+char(m,76123).
+char(o,76124).
+char(m,76125).
+char(1,76126).
+char(1,76127).
+char(6,76128).
+char(1,76129).
+char(m,76130).
+char(1,76131).
+char(2,76132).
+char(1,76133).
+char(6,76134).
+char(c,76135).
+char(m,76136).
+char(6,76137).
+char(4,76138).
+char(8,76139).
+char(9,76140).
+char(m,76141).
+char(o,76142).
+char(p,76143).
+char(6,76144).
+char(3,76145).
+char(0,76146).
+char(6,76147).
+char(c,76148).
+char(p,76149).
+char(8,76150).
+char(6,76151).
+char(6,76152).
+char(9,76153).
+char(m,76154).
+char(9,76155).
+char(9,76156).
+char(3,76157).
+char(8,76158).
+char(p,76159).
+char(6,76160).
+char(5,76161).
+char(9,76162).
+char(2,76163).
+char(c,76164).
+char(p,76165).
+char(o,76166).
+char(o,76167).
+char(4,76168).
+char(0,76169).
+char(8,76170).
+char(m,76171).
+char(3,76172).
+char(6,76173).
+char(1,76174).
+char(7,76175).
+char(p,76176).
+char(o,76177).
+char(m,76178).
+char(7,76179).
+char(0,76180).
+char(2,76181).
+char(c,76182).
+char(m,76183).
+char(5,76184).
+char(5,76185).
+char(4,76186).
+char(5,76187).
+char(c,76188).
+char(c,76189).
+char(c,76190).
+char(p,76191).
+char(3,76192).
+char(1,76193).
+char(2,76194).
+char(8,76195).
+char(p,76196).
+char(o,76197).
+char(m,76198).
+char(2,76199).
+char(0,76200).
+char(5,76201).
+char(4,76202).
+char(c,76203).
+char(m,76204).
+char(o,76205).
+char(o,76206).
+char(7,76207).
+char(2,76208).
+char(4,76209).
+char(c,76210).
+char(c,76211).
+char(c,76212).
+char(p,76213).
+char(o,76214).
+char(p,76215).
+char(8,76216).
+char(8,76217).
+char(7,76218).
+char(5,76219).
+char(c,76220).
+char(p,76221).
+char(o,76222).
+char(p,76223).
+char(9,76224).
+char(9,76225).
+char(1,76226).
+char(0,76227).
+char(c,76228).
+char(m,76229).
+char(2,76230).
+char(8,76231).
+char(7,76232).
+char(3,76233).
+char(c,76234).
+char(c,76235).
+char(p,76236).
+char(o,76237).
+char(5,76238).
+char(4,76239).
+char(9,76240).
+char(3,76241).
+char(c,76242).
+char(m,76243).
+char(o,76244).
+char(m,76245).
+char(7,76246).
+char(3,76247).
+char(8,76248).
+char(1,76249).
+char(c,76250).
+char(p,76251).
+char(o,76252).
+char(o,76253).
+char(p,76254).
+char(o,76255).
+char(m,76256).
+char(o,76257).
+char(o,76258).
+char(2,76259).
+char(6,76260).
+char(5,76261).
+char(3,76262).
+char(c,76263).
+char(c,76264).
+char(c,76265).
+char(p,76266).
+char(3,76267).
+char(0,76268).
+char(6,76269).
+char(6,76270).
+char(c,76271).
+char(p,76272).
+char(o,76273).
+char(p,76274).
+char(3,76275).
+char(4,76276).
+char(0,76277).
+char(2,76278).
+char(c,76279).
+char(c,76280).
+char(p,76281).
+char(3,76282).
+char(5,76283).
+char(4,76284).
+char(3,76285).
+char(m,76286).
+char(4,76287).
+char(5,76288).
+char(6,76289).
+char(c,76290).
+char(c,76291).
+char(p,76292).
+char(o,76293).
+char(o,76294).
+char(o,76295).
+char(o,76296).
+char(m,76297).
+char(1,76298).
+char(1,76299).
+char(3,76300).
+char(9,76301).
+char(c,76302).
+char(c,76303).
+char(c,76304).
+char(c,76305).
+char(c,76306).
+char(p,76307).
+char(1,76308).
+char(5,76309).
+char(7,76310).
+char(5,76311).
+char(c,76312).
+char(m,76313).
+char(o,76314).
+char(o,76315).
+char(p,76316).
+char(o,76317).
+char(m,76318).
+char(9,76319).
+char(2,76320).
+char(7,76321).
+char(0,76322).
+char(p,76323).
+char(o,76324).
+char(m,76325).
+char(6,76326).
+char(1,76327).
+char(6,76328).
+char(5,76329).
+char(m,76330).
+char(9,76331).
+char(6,76332).
+char(6,76333).
+char(3,76334).
+char(p,76335).
+char(1,76336).
+char(8,76337).
+char(4,76338).
+char(3,76339).
+char(p,76340).
+char(1,76341).
+char(1,76342).
+char(0,76343).
+char(4,76344).
+char(m,76345).
+char(o,76346).
+char(2,76347).
+char(8,76348).
+char(5,76349).
+char(7,76350).
+char(c,76351).
+char(c,76352).
+char(m,76353).
+char(2,76354).
+char(8,76355).
+char(8,76356).
+char(6,76357).
+char(c,76358).
+char(c,76359).
+char(m,76360).
+char(3,76361).
+char(4,76362).
+char(8,76363).
+char(6,76364).
+char(m,76365).
+char(4,76366).
+char(2,76367).
+char(5,76368).
+char(7,76369).
+char(c,76370).
+char(m,76371).
+char(o,76372).
+char(m,76373).
+char(o,76374).
+char(o,76375).
+char(9,76376).
+char(9,76377).
+char(8,76378).
+char(6,76379).
+char(p,76380).
+char(o,76381).
+char(m,76382).
+char(o,76383).
+char(m,76384).
+char(o,76385).
+char(m,76386).
+char(o,76387).
+char(p,76388).
+char(4,76389).
+char(0,76390).
+char(0,76391).
+char(8,76392).
+char(p,76393).
+char(o,76394).
+char(p,76395).
+char(4,76396).
+char(8,76397).
+char(3,76398).
+char(c,76399).
+char(c,76400).
+char(c,76401).
+char(p,76402).
+char(9,76403).
+char(6,76404).
+char(4,76405).
+char(4,76406).
+char(c,76407).
+char(m,76408).
+char(3,76409).
+char(0,76410).
+char(4,76411).
+char(4,76412).
+char(p,76413).
+char(o,76414).
+char(m,76415).
+char(o,76416).
+char(8,76417).
+char(8,76418).
+char(6,76419).
+char(3,76420).
+char(m,76421).
+char(3,76422).
+char(6,76423).
+char(5,76424).
+char(0,76425).
+char(c,76426).
+char(c,76427).
+char(m,76428).
+char(o,76429).
+char(2,76430).
+char(7,76431).
+char(7,76432).
+char(8,76433).
+char(c,76434).
+char(c,76435).
+char(c,76436).
+char(c,76437).
+char(p,76438).
+char(8,76439).
+char(9,76440).
+char(9,76441).
+char(5,76442).
+char(c,76443).
+char(c,76444).
+char(m,76445).
+char(o,76446).
+char(o,76447).
+char(p,76448).
+char(4,76449).
+char(9,76450).
+char(6,76451).
+char(0,76452).
+char(c,76453).
+char(m,76454).
+char(3,76455).
+char(1,76456).
+char(1,76457).
+char(6,76458).
+char(m,76459).
+char(o,76460).
+char(p,76461).
+char(7,76462).
+char(4,76463).
+char(8,76464).
+char(2,76465).
+char(c,76466).
+char(c,76467).
+char(c,76468).
+char(p,76469).
+char(o,76470).
+char(p,76471).
+char(o,76472).
+char(m,76473).
+char(3,76474).
+char(3,76475).
+char(9,76476).
+char(0,76477).
+char(p,76478).
+char(5,76479).
+char(0,76480).
+char(c,76481).
+char(p,76482).
+char(o,76483).
+char(m,76484).
+char(o,76485).
+char(9,76486).
+char(1,76487).
+char(2,76488).
+char(7,76489).
+char(c,76490).
+char(m,76491).
+char(4,76492).
+char(6,76493).
+char(0,76494).
+char(6,76495).
+char(c,76496).
+char(p,76497).
+char(o,76498).
+char(p,76499).
+char(6,76500).
+char(2,76501).
+char(9,76502).
+char(0,76503).
+char(p,76504).
+char(1,76505).
+char(9,76506).
+char(9,76507).
+char(9,76508).
+char(m,76509).
+char(o,76510).
+char(m,76511).
+char(o,76512).
+char(p,76513).
+char(5,76514).
+char(7,76515).
+char(5,76516).
+char(6,76517).
+char(m,76518).
+char(2,76519).
+char(8,76520).
+char(2,76521).
+char(9,76522).
+char(c,76523).
+char(m,76524).
+char(6,76525).
+char(9,76526).
+char(3,76527).
+char(4,76528).
+char(c,76529).
+char(m,76530).
+char(o,76531).
+char(m,76532).
+char(o,76533).
+char(o,76534).
+char(m,76535).
+char(5,76536).
+char(5,76537).
+char(5,76538).
+char(c,76539).
+char(p,76540).
+char(7,76541).
+char(4,76542).
+char(4,76543).
+char(1,76544).
+char(c,76545).
+char(p,76546).
+char(o,76547).
+char(o,76548).
+char(o,76549).
+char(p,76550).
+char(5,76551).
+char(2,76552).
+char(6,76553).
+char(m,76554).
+char(o,76555).
+char(m,76556).
+char(1,76557).
+char(6,76558).
+char(1,76559).
+char(3,76560).
+char(p,76561).
+char(5,76562).
+char(8,76563).
+char(3,76564).
+char(7,76565).
+char(m,76566).
+char(o,76567).
+char(o,76568).
+char(8,76569).
+char(9,76570).
+char(7,76571).
+char(9,76572).
+char(p,76573).
+char(2,76574).
+char(7,76575).
+char(6,76576).
+char(2,76577).
+char(c,76578).
+char(p,76579).
+char(o,76580).
+char(p,76581).
+char(1,76582).
+char(1,76583).
+char(0,76584).
+char(9,76585).
+char(m,76586).
+char(o,76587).
+char(m,76588).
+char(o,76589).
+char(m,76590).
+char(o,76591).
+char(m,76592).
+char(o,76593).
+char(p,76594).
+char(o,76595).
+char(p,76596).
+char(3,76597).
+char(7,76598).
+char(7,76599).
+char(1,76600).
+char(c,76601).
+char(c,76602).
+char(c,76603).
+char(p,76604).
+char(o,76605).
+char(p,76606).
+char(7,76607).
+char(8,76608).
+char(9,76609).
+char(5,76610).
+char(m,76611).
+char(7,76612).
+char(7,76613).
+char(2,76614).
+char(3,76615).
+char(m,76616).
+char(o,76617).
+char(m,76618).
+char(4,76619).
+char(4,76620).
+char(9,76621).
+char(0,76622).
+char(p,76623).
+char(o,76624).
+char(p,76625).
+char(o,76626).
+char(2,76627).
+char(1,76628).
+char(7,76629).
+char(2,76630).
+char(m,76631).
+char(o,76632).
+char(o,76633).
+char(o,76634).
+char(m,76635).
+char(7,76636).
+char(3,76637).
+char(5,76638).
+char(m,76639).
+char(7,76640).
+char(4,76641).
+char(8,76642).
+char(2,76643).
+char(c,76644).
+char(c,76645).
+char(p,76646).
+char(2,76647).
+char(5,76648).
+char(1,76649).
+char(9,76650).
+char(c,76651).
+char(m,76652).
+char(o,76653).
+char(o,76654).
+char(p,76655).
+char(o,76656).
+char(p,76657).
+char(1,76658).
+char(3,76659).
+char(7,76660).
+char(9,76661).
+char(c,76662).
+char(c,76663).
+char(m,76664).
+char(7,76665).
+char(6,76666).
+char(0,76667).
+char(1,76668).
+char(m,76669).
+char(o,76670).
+char(m,76671).
+char(8,76672).
+char(1,76673).
+char(6,76674).
+char(0,76675).
+char(c,76676).
+char(m,76677).
+char(2,76678).
+char(0,76679).
+char(4,76680).
+char(5,76681).
+char(m,76682).
+char(9,76683).
+char(3,76684).
+char(3,76685).
+char(7,76686).
+char(m,76687).
+char(o,76688).
+char(4,76689).
+char(6,76690).
+char(9,76691).
+char(9,76692).
+char(c,76693).
+char(p,76694).
+char(o,76695).
+char(m,76696).
+char(o,76697).
+char(8,76698).
+char(0,76699).
+char(7,76700).
+char(0,76701).
+char(c,76702).
+char(m,76703).
+char(o,76704).
+char(m,76705).
+char(o,76706).
+char(m,76707).
+char(1,76708).
+char(0,76709).
+char(1,76710).
+char(3,76711).
+char(p,76712).
+char(5,76713).
+char(1,76714).
+char(7,76715).
+char(c,76716).
+char(m,76717).
+char(o,76718).
+char(m,76719).
+char(o,76720).
+char(o,76721).
+char(p,76722).
+char(o,76723).
+char(p,76724).
+char(o,76725).
+char(9,76726).
+char(9,76727).
+char(5,76728).
+char(7,76729).
+char(m,76730).
+char(o,76731).
+char(p,76732).
+char(8,76733).
+char(2,76734).
+char(6,76735).
+char(1,76736).
+char(p,76737).
+char(9,76738).
+char(6,76739).
+char(8,76740).
+char(0,76741).
+char(p,76742).
+char(6,76743).
+char(7,76744).
+char(5,76745).
+char(0,76746).
+char(m,76747).
+char(7,76748).
+char(1,76749).
+char(2,76750).
+char(9,76751).
+char(p,76752).
+char(1,76753).
+char(4,76754).
+char(9,76755).
+char(0,76756).
+char(c,76757).
+char(p,76758).
+char(o,76759).
+char(o,76760).
+char(p,76761).
+char(8,76762).
+char(6,76763).
+char(9,76764).
+char(c,76765).
+char(m,76766).
+char(5,76767).
+char(4,76768).
+char(3,76769).
+char(3,76770).
+char(p,76771).
+char(6,76772).
+char(3,76773).
+char(8,76774).
+char(0,76775).
+char(c,76776).
+char(c,76777).
+char(c,76778).
+char(p,76779).
+char(o,76780).
+char(m,76781).
+char(o,76782).
+char(p,76783).
+char(7,76784).
+char(4,76785).
+char(9,76786).
+char(3,76787).
+char(c,76788).
+char(c,76789).
+char(c,76790).
+char(c,76791).
+char(m,76792).
+char(8,76793).
+char(1,76794).
+char(8,76795).
+char(9,76796).
+char(c,76797).
+char(c,76798).
+char(c,76799).
+char(c,76800).
+char(m,76801).
+char(o,76802).
+char(o,76803).
+char(m,76804).
+char(8,76805).
+char(3,76806).
+char(6,76807).
+char(7,76808).
+char(c,76809).
+char(c,76810).
+char(c,76811).
+char(p,76812).
+char(3,76813).
+char(9,76814).
+char(0,76815).
+char(6,76816).
+char(c,76817).
+char(c,76818).
+char(p,76819).
+char(9,76820).
+char(6,76821).
+char(2,76822).
+char(7,76823).
+char(c,76824).
+char(p,76825).
+char(o,76826).
+char(m,76827).
+char(7,76828).
+char(1,76829).
+char(6,76830).
+char(0,76831).
+char(c,76832).
+char(p,76833).
+char(7,76834).
+char(4,76835).
+char(3,76836).
+char(8,76837).
+char(m,76838).
+char(4,76839).
+char(4,76840).
+char(4,76841).
+char(3,76842).
+char(m,76843).
+char(o,76844).
+char(p,76845).
+char(7,76846).
+char(2,76847).
+char(8,76848).
+char(5,76849).
+char(p,76850).
+char(8,76851).
+char(7,76852).
+char(3,76853).
+char(1,76854).
+char(m,76855).
+char(3,76856).
+char(9,76857).
+char(6,76858).
+char(c,76859).
+char(p,76860).
+char(5,76861).
+char(1,76862).
+char(5,76863).
+char(1,76864).
+char(m,76865).
+char(o,76866).
+char(p,76867).
+char(o,76868).
+char(m,76869).
+char(o,76870).
+char(o,76871).
+char(p,76872).
+char(5,76873).
+char(1,76874).
+char(6,76875).
+char(7,76876).
+char(p,76877).
+char(o,76878).
+char(m,76879).
+char(2,76880).
+char(9,76881).
+char(1,76882).
+char(3,76883).
+char(m,76884).
+char(6,76885).
+char(5,76886).
+char(0,76887).
+char(7,76888).
+char(c,76889).
+char(c,76890).
+char(c,76891).
+char(p,76892).
+char(5,76893).
+char(3,76894).
+char(2,76895).
+char(0,76896).
+char(p,76897).
+char(o,76898).
+char(m,76899).
+char(o,76900).
+char(m,76901).
+char(5,76902).
+char(5,76903).
+char(8,76904).
+char(7,76905).
+char(p,76906).
+char(8,76907).
+char(1,76908).
+char(0,76909).
+char(2,76910).
+char(c,76911).
+char(p,76912).
+char(o,76913).
+char(p,76914).
+char(6,76915).
+char(m,76916).
+char(8,76917).
+char(9,76918).
+char(0,76919).
+char(6,76920).
+char(p,76921).
+char(6,76922).
+char(8,76923).
+char(4,76924).
+char(7,76925).
+char(c,76926).
+char(p,76927).
+char(o,76928).
+char(p,76929).
+char(o,76930).
+char(o,76931).
+char(p,76932).
+char(6,76933).
+char(4,76934).
+char(4,76935).
+char(4,76936).
+char(p,76937).
+char(3,76938).
+char(8,76939).
+char(2,76940).
+char(1,76941).
+char(m,76942).
+char(8,76943).
+char(6,76944).
+char(0,76945).
+char(6,76946).
+char(p,76947).
+char(o,76948).
+char(m,76949).
+char(o,76950).
+char(2,76951).
+char(2,76952).
+char(3,76953).
+char(3,76954).
+char(m,76955).
+char(o,76956).
+char(p,76957).
+char(5,76958).
+char(8,76959).
+char(0,76960).
+char(5,76961).
+char(c,76962).
+char(c,76963).
+char(c,76964).
+char(m,76965).
+char(o,76966).
+char(4,76967).
+char(4,76968).
+char(2,76969).
+char(7,76970).
+char(c,76971).
+char(p,76972).
+char(o,76973).
+char(o,76974).
+char(p,76975).
+char(4,76976).
+char(6,76977).
+char(4,76978).
+char(2,76979).
+char(c,76980).
+char(c,76981).
+char(c,76982).
+char(m,76983).
+char(5,76984).
+char(6,76985).
+char(0,76986).
+char(6,76987).
+char(m,76988).
+char(o,76989).
+char(m,76990).
+char(6,76991).
+char(0,76992).
+char(m,76993).
+char(4,76994).
+char(6,76995).
+char(9,76996).
+char(7,76997).
+char(c,76998).
+char(c,76999).
+char(c,77000).
+char(c,77001).
+char(m,77002).
+char(2,77003).
+char(3,77004).
+char(3,77005).
+char(5,77006).
+char(m,77007).
+char(o,77008).
+char(7,77009).
+char(3,77010).
+char(5,77011).
+char(7,77012).
+char(p,77013).
+char(8,77014).
+char(3,77015).
+char(3,77016).
+char(2,77017).
+char(c,77018).
+char(m,77019).
+char(o,77020).
+char(p,77021).
+char(o,77022).
+char(p,77023).
+char(1,77024).
+char(2,77025).
+char(2,77026).
+char(6,77027).
+char(p,77028).
+char(8,77029).
+char(2,77030).
+char(3,77031).
+char(6,77032).
+char(p,77033).
+char(o,77034).
+char(1,77035).
+char(5,77036).
+char(6,77037).
+char(c,77038).
+char(c,77039).
+char(m,77040).
+char(9,77041).
+char(0,77042).
+char(4,77043).
+char(0,77044).
+char(p,77045).
+char(3,77046).
+char(5,77047).
+char(1,77048).
+char(1,77049).
+char(m,77050).
+char(o,77051).
+char(m,77052).
+char(8,77053).
+char(5,77054).
+char(9,77055).
+char(4,77056).
+char(c,77057).
+char(p,77058).
+char(o,77059).
+char(m,77060).
+char(o,77061).
+char(m,77062).
+char(4,77063).
+char(8,77064).
+char(6,77065).
+char(9,77066).
+char(p,77067).
+char(9,77068).
+char(2,77069).
+char(8,77070).
+char(0,77071).
+char(c,77072).
+char(c,77073).
+char(c,77074).
+char(c,77075).
+char(m,77076).
+char(7,77077).
+char(3,77078).
+char(9,77079).
+char(1,77080).
+char(c,77081).
+char(m,77082).
+char(o,77083).
+char(3,77084).
+char(3,77085).
+char(3,77086).
+char(5,77087).
+char(m,77088).
+char(7,77089).
+char(4,77090).
+char(9,77091).
+char(2,77092).
+char(m,77093).
+char(o,77094).
+char(p,77095).
+char(o,77096).
+char(m,77097).
+char(9,77098).
+char(6,77099).
+char(9,77100).
+char(1,77101).
+char(c,77102).
+char(c,77103).
+char(m,77104).
+char(o,77105).
+char(p,77106).
+char(2,77107).
+char(6,77108).
+char(2,77109).
+char(8,77110).
+char(c,77111).
+char(c,77112).
+char(p,77113).
+char(o,77114).
+char(m,77115).
+char(o,77116).
+char(m,77117).
+char(7,77118).
+char(9,77119).
+char(9,77120).
+char(p,77121).
+char(2,77122).
+char(2,77123).
+char(3,77124).
+char(5,77125).
+char(p,77126).
+char(o,77127).
+char(m,77128).
+char(6,77129).
+char(3,77130).
+char(3,77131).
+char(3,77132).
+char(c,77133).
+char(c,77134).
+char(c,77135).
+char(m,77136).
+char(8,77137).
+char(6,77138).
+char(2,77139).
+char(8,77140).
+char(m,77141).
+char(6,77142).
+char(9,77143).
+char(0,77144).
+char(4,77145).
+char(p,77146).
+char(9,77147).
+char(7,77148).
+char(7,77149).
+char(3,77150).
+char(c,77151).
+char(p,77152).
+char(6,77153).
+char(9,77154).
+char(0,77155).
+char(2,77156).
+char(p,77157).
+char(o,77158).
+char(p,77159).
+char(1,77160).
+char(0,77161).
+char(6,77162).
+char(6,77163).
+char(m,77164).
+char(o,77165).
+char(m,77166).
+char(o,77167).
+char(6,77168).
+char(3,77169).
+char(4,77170).
+char(4,77171).
+char(c,77172).
+char(p,77173).
+char(2,77174).
+char(9,77175).
+char(9,77176).
+char(6,77177).
+char(m,77178).
+char(8,77179).
+char(9,77180).
+char(9,77181).
+char(7,77182).
+char(c,77183).
+char(m,77184).
+char(1,77185).
+char(8,77186).
+char(4,77187).
+char(4,77188).
+char(c,77189).
+char(m,77190).
+char(o,77191).
+char(m,77192).
+char(o,77193).
+char(4,77194).
+char(2,77195).
+char(0,77196).
+char(5,77197).
+char(c,77198).
+char(c,77199).
+char(p,77200).
+char(o,77201).
+char(5,77202).
+char(0,77203).
+char(3,77204).
+char(6,77205).
+char(c,77206).
+char(c,77207).
+char(c,77208).
+char(c,77209).
+char(m,77210).
+char(4,77211).
+char(5,77212).
+char(3,77213).
+char(3,77214).
+char(p,77215).
+char(8,77216).
+char(3,77217).
+char(1,77218).
+char(1,77219).
+char(m,77220).
+char(o,77221).
+char(p,77222).
+char(4,77223).
+char(6,77224).
+char(9,77225).
+char(3,77226).
+char(c,77227).
+char(p,77228).
+char(o,77229).
+char(m,77230).
+char(9,77231).
+char(0,77232).
+char(1,77233).
+char(3,77234).
+char(c,77235).
+char(p,77236).
+char(4,77237).
+char(5,77238).
+char(8,77239).
+char(9,77240).
+char(c,77241).
+char(p,77242).
+char(o,77243).
+char(p,77244).
+char(o,77245).
+char(m,77246).
+char(o,77247).
+char(m,77248).
+char(9,77249).
+char(5,77250).
+char(5,77251).
+char(0,77252).
+char(p,77253).
+char(o,77254).
+char(7,77255).
+char(6,77256).
+char(5,77257).
+char(p,77258).
+char(4,77259).
+char(6,77260).
+char(3,77261).
+char(4,77262).
+char(c,77263).
+char(c,77264).
+char(c,77265).
+char(m,77266).
+char(2,77267).
+char(9,77268).
+char(9,77269).
+char(5,77270).
+char(c,77271).
+char(c,77272).
+char(p,77273).
+char(o,77274).
+char(p,77275).
+char(3,77276).
+char(7,77277).
+char(4,77278).
+char(2,77279).
+char(c,77280).
+char(m,77281).
+char(2,77282).
+char(5,77283).
+char(4,77284).
+char(p,77285).
+char(8,77286).
+char(6,77287).
+char(5,77288).
+char(3,77289).
+char(m,77290).
+char(o,77291).
+char(p,77292).
+char(o,77293).
+char(8,77294).
+char(3,77295).
+char(3,77296).
+char(c,77297).
+char(m,77298).
+char(8,77299).
+char(7,77300).
+char(7,77301).
+char(8,77302).
+char(c,77303).
+char(m,77304).
+char(2,77305).
+char(5,77306).
+char(8,77307).
+char(7,77308).
+char(m,77309).
+char(7,77310).
+char(4,77311).
+char(2,77312).
+char(7,77313).
+char(c,77314).
+char(p,77315).
+char(o,77316).
+char(o,77317).
+char(p,77318).
+char(1,77319).
+char(3,77320).
+char(6,77321).
+char(7,77322).
+char(c,77323).
+char(p,77324).
+char(o,77325).
+char(p,77326).
+char(1,77327).
+char(6,77328).
+char(6,77329).
+char(3,77330).
+char(m,77331).
+char(o,77332).
+char(m,77333).
+char(o,77334).
+char(2,77335).
+char(3,77336).
+char(7,77337).
+char(0,77338).
+char(c,77339).
+char(c,77340).
+char(c,77341).
+char(m,77342).
+char(1,77343).
+char(6,77344).
+char(6,77345).
+char(9,77346).
+char(c,77347).
+char(c,77348).
+char(p,77349).
+char(4,77350).
+char(2,77351).
+char(8,77352).
+char(2,77353).
+char(c,77354).
+char(p,77355).
+char(o,77356).
+char(m,77357).
+char(o,77358).
+char(p,77359).
+char(3,77360).
+char(4,77361).
+char(0,77362).
+char(8,77363).
+char(c,77364).
+char(c,77365).
+char(m,77366).
+char(6,77367).
+char(2,77368).
+char(7,77369).
+char(6,77370).
+char(c,77371).
+char(c,77372).
+char(c,77373).
+char(c,77374).
+char(c,77375).
+char(c,77376).
+char(p,77377).
+char(o,77378).
+char(p,77379).
+char(1,77380).
+char(3,77381).
+char(4,77382).
+char(9,77383).
+char(c,77384).
+char(p,77385).
+char(6,77386).
+char(8,77387).
+char(3,77388).
+char(3,77389).
+char(p,77390).
+char(3,77391).
+char(5,77392).
+char(8,77393).
+char(4,77394).
+char(c,77395).
+char(p,77396).
+char(6,77397).
+char(9,77398).
+char(7,77399).
+char(9,77400).
+char(m,77401).
+char(6,77402).
+char(8,77403).
+char(4,77404).
+char(7,77405).
+char(c,77406).
+char(p,77407).
+char(o,77408).
+char(5,77409).
+char(8,77410).
+char(7,77411).
+char(4,77412).
+char(c,77413).
+char(c,77414).
+char(c,77415).
+char(p,77416).
+char(4,77417).
+char(5,77418).
+char(0,77419).
+char(7,77420).
+char(p,77421).
+char(6,77422).
+char(8,77423).
+char(7,77424).
+char(0,77425).
+char(c,77426).
+char(c,77427).
+char(c,77428).
+char(c,77429).
+char(c,77430).
+char(c,77431).
+char(m,77432).
+char(7,77433).
+char(4,77434).
+char(1,77435).
+char(c,77436).
+char(c,77437).
+char(p,77438).
+char(5,77439).
+char(1,77440).
+char(6,77441).
+char(p,77442).
+char(o,77443).
+char(o,77444).
+char(m,77445).
+char(9,77446).
+char(7,77447).
+char(8,77448).
+char(7,77449).
+char(p,77450).
+char(1,77451).
+char(6,77452).
+char(8,77453).
+char(c,77454).
+char(c,77455).
+char(m,77456).
+char(o,77457).
+char(o,77458).
+char(o,77459).
+char(o,77460).
+char(m,77461).
+char(5,77462).
+char(1,77463).
+char(1,77464).
+char(7,77465).
+char(c,77466).
+char(c,77467).
+char(p,77468).
+char(o,77469).
+char(7,77470).
+char(5,77471).
+char(3,77472).
+char(8,77473).
+char(c,77474).
+char(m,77475).
+char(o,77476).
+char(p,77477).
+char(o,77478).
+char(2,77479).
+char(7,77480).
+char(4,77481).
+char(4,77482).
+char(c,77483).
+char(m,77484).
+char(7,77485).
+char(5,77486).
+char(0,77487).
+char(0,77488).
+char(c,77489).
+char(c,77490).
+char(c,77491).
+char(c,77492).
+char(m,77493).
+char(o,77494).
+char(p,77495).
+char(5,77496).
+char(5,77497).
+char(2,77498).
+char(5,77499).
+char(c,77500).
+char(m,77501).
+char(o,77502).
+char(m,77503).
+char(o,77504).
+char(m,77505).
+char(3,77506).
+char(9,77507).
+char(1,77508).
+char(8,77509).
+char(c,77510).
+char(c,77511).
+char(c,77512).
+char(c,77513).
+char(m,77514).
+char(o,77515).
+char(o,77516).
+char(p,77517).
+char(4,77518).
+char(9,77519).
+char(2,77520).
+char(9,77521).
+char(m,77522).
+char(8,77523).
+char(3,77524).
+char(1,77525).
+char(3,77526).
+char(c,77527).
+char(c,77528).
+char(c,77529).
+char(c,77530).
+char(p,77531).
+char(o,77532).
+char(7,77533).
+char(9,77534).
+char(9,77535).
+char(6,77536).
+char(p,77537).
+char(o,77538).
+char(m,77539).
+char(1,77540).
+char(6,77541).
+char(8,77542).
+char(c,77543).
+char(p,77544).
+char(3,77545).
+char(9,77546).
+char(0,77547).
+char(2,77548).
+char(c,77549).
+char(c,77550).
+char(c,77551).
+char(c,77552).
+char(c,77553).
+char(c,77554).
+char(c,77555).
+char(m,77556).
+char(3,77557).
+char(8,77558).
+char(5,77559).
+char(1,77560).
+char(c,77561).
+char(m,77562).
+char(2,77563).
+char(3,77564).
+char(3,77565).
+char(8,77566).
+char(c,77567).
+char(m,77568).
+char(o,77569).
+char(p,77570).
+char(o,77571).
+char(p,77572).
+char(6,77573).
+char(5,77574).
+char(8,77575).
+char(7,77576).
+char(p,77577).
+char(6,77578).
+char(2,77579).
+char(5,77580).
+char(2,77581).
+char(c,77582).
+char(c,77583).
+char(m,77584).
+char(o,77585).
+char(9,77586).
+char(7,77587).
+char(0,77588).
+char(c,77589).
+char(p,77590).
+char(o,77591).
+char(4,77592).
+char(6,77593).
+char(1,77594).
+char(5,77595).
+char(p,77596).
+char(o,77597).
+char(m,77598).
+char(8,77599).
+char(2,77600).
+char(5,77601).
+char(9,77602).
+char(p,77603).
+char(o,77604).
+char(p,77605).
+char(o,77606).
+char(m,77607).
+char(6,77608).
+char(5,77609).
+char(3,77610).
+char(9,77611).
+char(m,77612).
+char(o,77613).
+char(m,77614).
+char(8,77615).
+char(3,77616).
+char(3,77617).
+char(5,77618).
+char(m,77619).
+char(o,77620).
+char(m,77621).
+char(7,77622).
+char(4,77623).
+char(9,77624).
+char(0,77625).
+char(m,77626).
+char(o,77627).
+char(1,77628).
+char(9,77629).
+char(6,77630).
+char(1,77631).
+char(p,77632).
+char(o,77633).
+char(o,77634).
+char(p,77635).
+char(o,77636).
+char(o,77637).
+char(o,77638).
+char(7,77639).
+char(5,77640).
+char(9,77641).
+char(0,77642).
+char(c,77643).
+char(m,77644).
+char(4,77645).
+char(3,77646).
+char(6,77647).
+char(3,77648).
+char(c,77649).
+char(c,77650).
+char(c,77651).
+char(p,77652).
+char(o,77653).
+char(o,77654).
+char(3,77655).
+char(0,77656).
+char(8,77657).
+char(5,77658).
+char(p,77659).
+char(8,77660).
+char(9,77661).
+char(2,77662).
+char(7,77663).
+char(m,77664).
+char(6,77665).
+char(8,77666).
+char(7,77667).
+char(8,77668).
+char(p,77669).
+char(4,77670).
+char(4,77671).
+char(3,77672).
+char(9,77673).
+char(c,77674).
+char(m,77675).
+char(o,77676).
+char(m,77677).
+char(2,77678).
+char(9,77679).
+char(6,77680).
+char(9,77681).
+char(c,77682).
+char(m,77683).
+char(6,77684).
+char(7,77685).
+char(4,77686).
+char(2,77687).
+char(c,77688).
+char(p,77689).
+char(o,77690).
+char(o,77691).
+char(m,77692).
+char(o,77693).
+char(o,77694).
+char(p,77695).
+char(o,77696).
+char(m,77697).
+char(7,77698).
+char(5,77699).
+char(9,77700).
+char(6,77701).
+char(c,77702).
+char(m,77703).
+char(o,77704).
+char(o,77705).
+char(1,77706).
+char(7,77707).
+char(9,77708).
+char(0,77709).
+char(p,77710).
+char(o,77711).
+char(8,77712).
+char(6,77713).
+char(1,77714).
+char(5,77715).
+char(c,77716).
+char(m,77717).
+char(o,77718).
+char(p,77719).
+char(9,77720).
+char(8,77721).
+char(5,77722).
+char(8,77723).
+char(c,77724).
+char(c,77725).
+char(m,77726).
+char(o,77727).
+char(4,77728).
+char(5,77729).
+char(9,77730).
+char(0,77731).
+char(c,77732).
+char(p,77733).
+char(1,77734).
+char(7,77735).
+char(4,77736).
+char(3,77737).
+char(c,77738).
+char(m,77739).
+char(o,77740).
+char(o,77741).
+char(o,77742).
+char(m,77743).
+char(o,77744).
+char(m,77745).
+char(6,77746).
+char(7,77747).
+char(3,77748).
+char(6,77749).
+char(m,77750).
+char(o,77751).
+char(p,77752).
+char(9,77753).
+char(4,77754).
+char(0,77755).
+char(8,77756).
+char(c,77757).
+char(m,77758).
+char(9,77759).
+char(1,77760).
+char(1,77761).
+char(4,77762).
+char(m,77763).
+char(6,77764).
+char(8,77765).
+char(6,77766).
+char(4,77767).
+char(c,77768).
+char(m,77769).
+char(o,77770).
+char(m,77771).
+char(8,77772).
+char(4,77773).
+char(4,77774).
+char(3,77775).
+char(p,77776).
+char(5,77777).
+char(3,77778).
+char(2,77779).
+char(0,77780).
+char(m,77781).
+char(6,77782).
+char(5,77783).
+char(6,77784).
+char(6,77785).
+char(p,77786).
+char(o,77787).
+char(m,77788).
+char(o,77789).
+char(o,77790).
+char(m,77791).
+char(o,77792).
+char(m,77793).
+char(o,77794).
+char(o,77795).
+char(8,77796).
+char(9,77797).
+char(7,77798).
+char(3,77799).
+char(m,77800).
+char(2,77801).
+char(3,77802).
+char(7,77803).
+char(5,77804).
+char(m,77805).
+char(3,77806).
+char(7,77807).
+char(2,77808).
+char(7,77809).
+char(c,77810).
+char(m,77811).
+char(9,77812).
+char(0,77813).
+char(7,77814).
+char(p,77815).
+char(5,77816).
+char(6,77817).
+char(0,77818).
+char(8,77819).
+char(c,77820).
+char(p,77821).
+char(o,77822).
+char(p,77823).
+char(o,77824).
+char(o,77825).
+char(o,77826).
+char(m,77827).
+char(o,77828).
+char(o,77829).
+char(o,77830).
+char(m,77831).
+char(o,77832).
+char(m,77833).
+char(7,77834).
+char(0,77835).
+char(1,77836).
+char(0,77837).
+char(m,77838).
+char(o,77839).
+char(p,77840).
+char(o,77841).
+char(o,77842).
+char(p,77843).
+char(2,77844).
+char(5,77845).
+char(2,77846).
+char(3,77847).
+char(c,77848).
+char(c,77849).
+char(c,77850).
+char(c,77851).
+char(p,77852).
+char(o,77853).
+char(9,77854).
+char(5,77855).
+char(0,77856).
+char(6,77857).
+char(c,77858).
+char(m,77859).
+char(o,77860).
+char(p,77861).
+char(o,77862).
+char(m,77863).
+char(o,77864).
+char(8,77865).
+char(1,77866).
+char(4,77867).
+char(7,77868).
+char(p,77869).
+char(8,77870).
+char(6,77871).
+char(3,77872).
+char(3,77873).
+char(m,77874).
+char(8,77875).
+char(3,77876).
+char(0,77877).
+char(5,77878).
+char(p,77879).
+char(3,77880).
+char(7,77881).
+char(4,77882).
+char(8,77883).
+char(c,77884).
+char(c,77885).
+char(m,77886).
+char(6,77887).
+char(7,77888).
+char(7,77889).
+char(8,77890).
+char(p,77891).
+char(8,77892).
+char(8,77893).
+char(8,77894).
+char(3,77895).
+char(m,77896).
+char(2,77897).
+char(7,77898).
+char(6,77899).
+char(8,77900).
+char(p,77901).
+char(4,77902).
+char(1,77903).
+char(4,77904).
+char(8,77905).
+char(c,77906).
+char(p,77907).
+char(o,77908).
+char(p,77909).
+char(o,77910).
+char(p,77911).
+char(o,77912).
+char(m,77913).
+char(1,77914).
+char(5,77915).
+char(1,77916).
+char(3,77917).
+char(c,77918).
+char(p,77919).
+char(5,77920).
+char(3,77921).
+char(0,77922).
+char(c,77923).
+char(c,77924).
+char(c,77925).
+char(p,77926).
+char(o,77927).
+char(p,77928).
+char(1,77929).
+char(8,77930).
+char(2,77931).
+char(1,77932).
+char(m,77933).
+char(7,77934).
+char(7,77935).
+char(7,77936).
+char(2,77937).
+char(c,77938).
+char(p,77939).
+char(8,77940).
+char(6,77941).
+char(1,77942).
+char(0,77943).
+char(p,77944).
+char(o,77945).
+char(p,77946).
+char(o,77947).
+char(m,77948).
+char(5,77949).
+char(2,77950).
+char(5,77951).
+char(9,77952).
+char(c,77953).
+char(p,77954).
+char(4,77955).
+char(7,77956).
+char(4,77957).
+char(2,77958).
+char(p,77959).
+char(o,77960).
+char(4,77961).
+char(0,77962).
+char(8,77963).
+char(8,77964).
+char(p,77965).
+char(4,77966).
+char(9,77967).
+char(0,77968).
+char(7,77969).
+char(c,77970).
+char(c,77971).
+char(p,77972).
+char(o,77973).
+char(p,77974).
+char(o,77975).
+char(p,77976).
+char(1,77977).
+char(9,77978).
+char(8,77979).
+char(7,77980).
+char(c,77981).
+char(m,77982).
+char(o,77983).
+char(p,77984).
+char(9,77985).
+char(3,77986).
+char(1,77987).
+char(2,77988).
+char(c,77989).
+char(c,77990).
+char(c,77991).
+char(c,77992).
+char(c,77993).
+char(c,77994).
+char(p,77995).
+char(o,77996).
+char(p,77997).
+char(o,77998).
+char(m,77999).
+char(o,78000).
+char(9,78001).
+char(1,78002).
+char(7,78003).
+char(2,78004).
+char(p,78005).
+char(7,78006).
+char(0,78007).
+char(7,78008).
+char(8,78009).
+char(p,78010).
+char(6,78011).
+char(2,78012).
+char(5,78013).
+char(4,78014).
+char(m,78015).
+char(7,78016).
+char(6,78017).
+char(0,78018).
+char(1,78019).
+char(c,78020).
+char(c,78021).
+char(c,78022).
+char(p,78023).
+char(o,78024).
+char(8,78025).
+char(7,78026).
+char(5,78027).
+char(2,78028).
+char(p,78029).
+char(9,78030).
+char(2,78031).
+char(4,78032).
+char(7,78033).
+char(p,78034).
+char(3,78035).
+char(1,78036).
+char(9,78037).
+char(c,78038).
+char(m,78039).
+char(o,78040).
+char(o,78041).
+char(m,78042).
+char(o,78043).
+char(m,78044).
+char(o,78045).
+char(m,78046).
+char(8,78047).
+char(7,78048).
+char(6,78049).
+char(c,78050).
+char(c,78051).
+char(p,78052).
+char(6,78053).
+char(1,78054).
+char(2,78055).
+char(9,78056).
+char(c,78057).
+char(m,78058).
+char(2,78059).
+char(5,78060).
+char(8,78061).
+char(0,78062).
+char(m,78063).
+char(7,78064).
+char(2,78065).
+char(7,78066).
+char(0,78067).
+char(m,78068).
+char(o,78069).
+char(p,78070).
+char(7,78071).
+char(1,78072).
+char(3,78073).
+char(9,78074).
+char(c,78075).
+char(m,78076).
+char(8,78077).
+char(4,78078).
+char(5,78079).
+char(2,78080).
+char(c,78081).
+char(p,78082).
+char(1,78083).
+char(0,78084).
+char(8,78085).
+char(1,78086).
+char(p,78087).
+char(o,78088).
+char(m,78089).
+char(8,78090).
+char(9,78091).
+char(8,78092).
+char(3,78093).
+char(m,78094).
+char(3,78095).
+char(8,78096).
+char(3,78097).
+char(0,78098).
+char(p,78099).
+char(9,78100).
+char(9,78101).
+char(9,78102).
+char(1,78103).
+char(c,78104).
+char(p,78105).
+char(9,78106).
+char(1,78107).
+char(6,78108).
+char(0,78109).
+char(p,78110).
+char(o,78111).
+char(m,78112).
+char(o,78113).
+char(9,78114).
+char(6,78115).
+char(6,78116).
+char(1,78117).
+char(c,78118).
+char(c,78119).
+char(p,78120).
+char(o,78121).
+char(p,78122).
+char(9,78123).
+char(1,78124).
+char(9,78125).
+char(2,78126).
+char(m,78127).
+char(o,78128).
+char(p,78129).
+char(o,78130).
+char(m,78131).
+char(5,78132).
+char(6,78133).
+char(5,78134).
+char(6,78135).
+char(m,78136).
+char(1,78137).
+char(5,78138).
+char(0,78139).
+char(4,78140).
+char(p,78141).
+char(o,78142).
+char(9,78143).
+char(5,78144).
+char(7,78145).
+char(5,78146).
+char(c,78147).
+char(c,78148).
+char(c,78149).
+char(p,78150).
+char(3,78151).
+char(3,78152).
+char(0,78153).
+char(5,78154).
+char(c,78155).
+char(m,78156).
+char(o,78157).
+char(p,78158).
+char(o,78159).
+char(m,78160).
+char(8,78161).
+char(2,78162).
+char(8,78163).
+char(7,78164).
+char(c,78165).
+char(c,78166).
+char(c,78167).
+char(c,78168).
+char(m,78169).
+char(o,78170).
+char(p,78171).
+char(1,78172).
+char(4,78173).
+char(7,78174).
+char(7,78175).
+char(c,78176).
+char(p,78177).
+char(o,78178).
+char(p,78179).
+char(o,78180).
+char(m,78181).
+char(o,78182).
+char(m,78183).
+char(4,78184).
+char(8,78185).
+char(2,78186).
+char(c,78187).
+char(m,78188).
+char(2,78189).
+char(2,78190).
+char(9,78191).
+char(c,78192).
+char(c,78193).
+char(c,78194).
+char(c,78195).
+char(c,78196).
+char(p,78197).
+char(o,78198).
+char(9,78199).
+char(9,78200).
+char(5,78201).
+char(8,78202).
+char(c,78203).
+char(c,78204).
+char(c,78205).
+char(c,78206).
+char(p,78207).
+char(2,78208).
+char(1,78209).
+char(8,78210).
+char(4,78211).
+char(p,78212).
+char(4,78213).
+char(9,78214).
+char(6,78215).
+char(2,78216).
+char(c,78217).
+char(c,78218).
+char(m,78219).
+char(9,78220).
+char(7,78221).
+char(7,78222).
+char(2,78223).
+char(c,78224).
+char(m,78225).
+char(9,78226).
+char(7,78227).
+char(5,78228).
+char(m,78229).
+char(7,78230).
+char(9,78231).
+char(3,78232).
+char(3,78233).
+char(c,78234).
+char(m,78235).
+char(9,78236).
+char(1,78237).
+char(8,78238).
+char(2,78239).
+char(m,78240).
+char(8,78241).
+char(5,78242).
+char(2,78243).
+char(5,78244).
+char(c,78245).
+char(c,78246).
+char(p,78247).
+char(o,78248).
+char(m,78249).
+char(o,78250).
+char(p,78251).
+char(o,78252).
+char(p,78253).
+char(9,78254).
+char(7,78255).
+char(2,78256).
+char(5,78257).
+char(c,78258).
+char(c,78259).
+char(m,78260).
+char(5,78261).
+char(6,78262).
+char(9,78263).
+char(2,78264).
+char(p,78265).
+char(o,78266).
+char(o,78267).
+char(o,78268).
+char(o,78269).
+char(p,78270).
+char(7,78271).
+char(0,78272).
+char(1,78273).
+char(6,78274).
+char(m,78275).
+char(o,78276).
+char(p,78277).
+char(1,78278).
+char(9,78279).
+char(3,78280).
+char(4,78281).
+char(c,78282).
+char(c,78283).
+char(p,78284).
+char(9,78285).
+char(5,78286).
+char(1,78287).
+char(3,78288).
+char(m,78289).
+char(o,78290).
+char(7,78291).
+char(5,78292).
+char(2,78293).
+char(0,78294).
+char(m,78295).
+char(o,78296).
+char(m,78297).
+char(o,78298).
+char(p,78299).
+char(2,78300).
+char(7,78301).
+char(4,78302).
+char(4,78303).
+char(p,78304).
+char(o,78305).
+char(p,78306).
+char(2,78307).
+char(6,78308).
+char(5,78309).
+char(8,78310).
+char(p,78311).
+char(o,78312).
+char(o,78313).
+char(7,78314).
+char(4,78315).
+char(4,78316).
+char(6,78317).
+char(c,78318).
+char(p,78319).
+char(7,78320).
+char(7,78321).
+char(3,78322).
+char(5,78323).
+char(c,78324).
+char(p,78325).
+char(7,78326).
+char(0,78327).
+char(9,78328).
+char(6,78329).
+char(c,78330).
+char(c,78331).
+char(m,78332).
+char(3,78333).
+char(5,78334).
+char(8,78335).
+char(9,78336).
+char(c,78337).
+char(c,78338).
+char(c,78339).
+char(c,78340).
+char(m,78341).
+char(1,78342).
+char(2,78343).
+char(2,78344).
+char(1,78345).
+char(c,78346).
+char(c,78347).
+char(p,78348).
+char(6,78349).
+char(6,78350).
+char(2,78351).
+char(0,78352).
+char(c,78353).
+char(p,78354).
+char(o,78355).
+char(m,78356).
+char(o,78357).
+char(p,78358).
+char(o,78359).
+char(o,78360).
+char(o,78361).
+char(p,78362).
+char(5,78363).
+char(0,78364).
+char(3,78365).
+char(5,78366).
+char(c,78367).
+char(c,78368).
+char(c,78369).
+char(m,78370).
+char(4,78371).
+char(6,78372).
+char(1,78373).
+char(4,78374).
+char(c,78375).
+char(c,78376).
+char(m,78377).
+char(9,78378).
+char(8,78379).
+char(0,78380).
+char(p,78381).
+char(o,78382).
+char(p,78383).
+char(o,78384).
+char(m,78385).
+char(o,78386).
+char(p,78387).
+char(o,78388).
+char(1,78389).
+char(5,78390).
+char(3,78391).
+char(6,78392).
+char(c,78393).
+char(p,78394).
+char(o,78395).
+char(o,78396).
+char(o,78397).
+char(p,78398).
+char(o,78399).
+char(7,78400).
+char(8,78401).
+char(6,78402).
+char(0,78403).
+char(p,78404).
+char(6,78405).
+char(5,78406).
+char(7,78407).
+char(3,78408).
+char(c,78409).
+char(m,78410).
+char(9,78411).
+char(2,78412).
+char(7,78413).
+char(2,78414).
+char(c,78415).
+char(c,78416).
+char(c,78417).
+char(p,78418).
+char(o,78419).
+char(m,78420).
+char(o,78421).
+char(o,78422).
+char(p,78423).
+char(o,78424).
+char(o,78425).
+char(7,78426).
+char(0,78427).
+char(c,78428).
+char(c,78429).
+char(m,78430).
+char(o,78431).
+char(p,78432).
+char(3,78433).
+char(7,78434).
+char(0,78435).
+char(m,78436).
+char(6,78437).
+char(7,78438).
+char(5,78439).
+char(4,78440).
+char(c,78441).
+char(m,78442).
+char(1,78443).
+char(7,78444).
+char(2,78445).
+char(c,78446).
+char(m,78447).
+char(2,78448).
+char(3,78449).
+char(9,78450).
+char(m,78451).
+char(o,78452).
+char(o,78453).
+char(8,78454).
+char(8,78455).
+char(3,78456).
+char(0,78457).
+char(m,78458).
+char(o,78459).
+char(2,78460).
+char(2,78461).
+char(7,78462).
+char(9,78463).
+char(p,78464).
+char(o,78465).
+char(p,78466).
+char(o,78467).
+char(p,78468).
+char(7,78469).
+char(9,78470).
+char(3,78471).
+char(4,78472).
+char(p,78473).
+char(o,78474).
+char(o,78475).
+char(m,78476).
+char(7,78477).
+char(3,78478).
+char(c,78479).
+char(c,78480).
+char(c,78481).
+char(p,78482).
+char(9,78483).
+char(8,78484).
+char(9,78485).
+char(7,78486).
+char(c,78487).
+char(p,78488).
+char(7,78489).
+char(2,78490).
+char(3,78491).
+char(6,78492).
+char(c,78493).
+char(m,78494).
+char(o,78495).
+char(p,78496).
+char(o,78497).
+char(p,78498).
+char(o,78499).
+char(m,78500).
+char(o,78501).
+char(6,78502).
+char(7,78503).
+char(5,78504).
+char(0,78505).
+char(c,78506).
+char(m,78507).
+char(1,78508).
+char(9,78509).
+char(4,78510).
+char(0,78511).
+char(m,78512).
+char(o,78513).
+char(5,78514).
+char(4,78515).
+char(3,78516).
+char(p,78517).
+char(o,78518).
+char(p,78519).
+char(o,78520).
+char(m,78521).
+char(6,78522).
+char(0,78523).
+char(7,78524).
+char(9,78525).
+char(p,78526).
+char(o,78527).
+char(p,78528).
+char(4,78529).
+char(3,78530).
+char(6,78531).
+char(0,78532).
+char(c,78533).
+char(c,78534).
+char(c,78535).
+char(c,78536).
+char(m,78537).
+char(1,78538).
+char(3,78539).
+char(2,78540).
+char(5,78541).
+char(c,78542).
+char(c,78543).
+char(c,78544).
+char(m,78545).
+char(3,78546).
+char(1,78547).
+char(7,78548).
+char(6,78549).
+char(c,78550).
+char(c,78551).
+char(c,78552).
+char(m,78553).
+char(7,78554).
+char(4,78555).
+char(4,78556).
+char(2,78557).
+char(c,78558).
+char(c,78559).
+char(m,78560).
+char(5,78561).
+char(6,78562).
+char(5,78563).
+char(7,78564).
+char(m,78565).
+char(8,78566).
+char(8,78567).
+char(9,78568).
+char(8,78569).
+char(p,78570).
+char(o,78571).
+char(o,78572).
+char(p,78573).
+char(6,78574).
+char(6,78575).
+char(7,78576).
+char(8,78577).
+char(c,78578).
+char(p,78579).
+char(6,78580).
+char(6,78581).
+char(3,78582).
+char(2,78583).
+char(c,78584).
+char(m,78585).
+char(2,78586).
+char(9,78587).
+char(4,78588).
+char(c,78589).
+char(c,78590).
+char(c,78591).
+char(c,78592).
+char(c,78593).
+char(c,78594).
+char(m,78595).
+char(o,78596).
+char(p,78597).
+char(1,78598).
+char(1,78599).
+char(9,78600).
+char(4,78601).
+char(m,78602).
+char(o,78603).
+char(m,78604).
+char(6,78605).
+char(3,78606).
+char(1,78607).
+char(1,78608).
+char(p,78609).
+char(o,78610).
+char(m,78611).
+char(o,78612).
+char(2,78613).
+char(3,78614).
+char(0,78615).
+char(7,78616).
+char(c,78617).
+char(m,78618).
+char(o,78619).
+char(o,78620).
+char(5,78621).
+char(7,78622).
+char(5,78623).
+char(1,78624).
+char(p,78625).
+char(4,78626).
+char(7,78627).
+char(1,78628).
+char(3,78629).
+char(c,78630).
+char(p,78631).
+char(o,78632).
+char(m,78633).
+char(o,78634).
+char(p,78635).
+char(4,78636).
+char(3,78637).
+char(2,78638).
+char(3,78639).
+char(c,78640).
+char(m,78641).
+char(o,78642).
+char(2,78643).
+char(4,78644).
+char(3,78645).
+char(p,78646).
+char(o,78647).
+char(p,78648).
+char(o,78649).
+char(m,78650).
+char(2,78651).
+char(1,78652).
+char(5,78653).
+char(3,78654).
+char(c,78655).
+char(c,78656).
+char(c,78657).
+char(c,78658).
+char(m,78659).
+char(5,78660).
+char(6,78661).
+char(1,78662).
+char(1,78663).
+char(m,78664).
+char(o,78665).
+char(m,78666).
+char(4,78667).
+char(8,78668).
+char(6,78669).
+char(3,78670).
+char(m,78671).
+char(o,78672).
+char(1,78673).
+char(5,78674).
+char(8,78675).
+char(9,78676).
+char(m,78677).
+char(6,78678).
+char(1,78679).
+char(7,78680).
+char(1,78681).
+char(m,78682).
+char(o,78683).
+char(4,78684).
+char(1,78685).
+char(1,78686).
+char(8,78687).
+char(c,78688).
+char(c,78689).
+char(c,78690).
+char(c,78691).
+char(c,78692).
+char(m,78693).
+char(o,78694).
+char(p,78695).
+char(o,78696).
+char(7,78697).
+char(0,78698).
+char(9,78699).
+char(p,78700).
+char(o,78701).
+char(m,78702).
+char(o,78703).
+char(m,78704).
+char(1,78705).
+char(0,78706).
+char(6,78707).
+char(3,78708).
+char(p,78709).
+char(3,78710).
+char(6,78711).
+char(8,78712).
+char(2,78713).
+char(c,78714).
+char(m,78715).
+char(o,78716).
+char(o,78717).
+char(p,78718).
+char(o,78719).
+char(m,78720).
+char(5,78721).
+char(7,78722).
+char(2,78723).
+char(c,78724).
+char(c,78725).
+char(p,78726).
+char(5,78727).
+char(3,78728).
+char(6,78729).
+char(8,78730).
+char(c,78731).
+char(p,78732).
+char(7,78733).
+char(1,78734).
+char(7,78735).
+char(2,78736).
+char(c,78737).
+char(p,78738).
+char(o,78739).
+char(m,78740).
+char(7,78741).
+char(9,78742).
+char(3,78743).
+char(4,78744).
+char(c,78745).
+char(m,78746).
+char(1,78747).
+char(7,78748).
+char(3,78749).
+char(8,78750).
+char(p,78751).
+char(o,78752).
+char(m,78753).
+char(8,78754).
+char(5,78755).
+char(3,78756).
+char(7,78757).
+char(c,78758).
+char(p,78759).
+char(o,78760).
+char(2,78761).
+char(0,78762).
+char(6,78763).
+char(8,78764).
+char(p,78765).
+char(o,78766).
+char(m,78767).
+char(5,78768).
+char(8,78769).
+char(9,78770).
+char(8,78771).
+char(c,78772).
+char(c,78773).
+char(p,78774).
+char(o,78775).
+char(p,78776).
+char(o,78777).
+char(m,78778).
+char(3,78779).
+char(8,78780).
+char(2,78781).
+char(0,78782).
+char(c,78783).
+char(c,78784).
+char(m,78785).
+char(o,78786).
+char(p,78787).
+char(2,78788).
+char(2,78789).
+char(9,78790).
+char(5,78791).
+char(c,78792).
+char(c,78793).
+char(c,78794).
+char(p,78795).
+char(3,78796).
+char(7,78797).
+char(2,78798).
+char(2,78799).
+char(c,78800).
+char(m,78801).
+char(o,78802).
+char(m,78803).
+char(5,78804).
+char(8,78805).
+char(1,78806).
+char(9,78807).
+char(m,78808).
+char(o,78809).
+char(o,78810).
+char(m,78811).
+char(o,78812).
+char(o,78813).
+char(m,78814).
+char(o,78815).
+char(o,78816).
+char(9,78817).
+char(7,78818).
+char(2,78819).
+char(8,78820).
+char(c,78821).
+char(m,78822).
+char(o,78823).
+char(m,78824).
+char(o,78825).
+char(o,78826).
+char(p,78827).
+char(o,78828).
+char(p,78829).
+char(o,78830).
+char(9,78831).
+char(2,78832).
+char(7,78833).
+char(9,78834).
+char(p,78835).
+char(o,78836).
+char(5,78837).
+char(7,78838).
+char(5,78839).
+char(2,78840).
+char(p,78841).
+char(o,78842).
+char(o,78843).
+char(7,78844).
+char(2,78845).
+char(2,78846).
+char(c,78847).
+char(m,78848).
+char(o,78849).
+char(m,78850).
+char(o,78851).
+char(p,78852).
+char(7,78853).
+char(9,78854).
+char(7,78855).
+char(8,78856).
+char(m,78857).
+char(6,78858).
+char(6,78859).
+char(1,78860).
+char(8,78861).
+char(p,78862).
+char(7,78863).
+char(5,78864).
+char(1,78865).
+char(3,78866).
+char(c,78867).
+char(m,78868).
+char(o,78869).
+char(m,78870).
+char(o,78871).
+char(8,78872).
+char(5,78873).
+char(1,78874).
+char(8,78875).
+char(c,78876).
+char(m,78877).
+char(8,78878).
+char(6,78879).
+char(5,78880).
+char(8,78881).
+char(c,78882).
+char(m,78883).
+char(o,78884).
+char(p,78885).
+char(5,78886).
+char(4,78887).
+char(5,78888).
+char(9,78889).
+char(c,78890).
+char(c,78891).
+char(c,78892).
+char(m,78893).
+char(o,78894).
+char(m,78895).
+char(o,78896).
+char(p,78897).
+char(o,78898).
+char(m,78899).
+char(9,78900).
+char(6,78901).
+char(8,78902).
+char(9,78903).
+char(m,78904).
+char(5,78905).
+char(9,78906).
+char(6,78907).
+char(9,78908).
+char(m,78909).
+char(o,78910).
+char(o,78911).
+char(o,78912).
+char(p,78913).
+char(o,78914).
+char(5,78915).
+char(7,78916).
+char(0,78917).
+char(0,78918).
+char(m,78919).
+char(o,78920).
+char(p,78921).
+char(o,78922).
+char(m,78923).
+char(3,78924).
+char(3,78925).
+char(7,78926).
+char(0,78927).
+char(p,78928).
+char(7,78929).
+char(8,78930).
+char(0,78931).
+char(m,78932).
+char(7,78933).
+char(9,78934).
+char(0,78935).
+char(0,78936).
+char(c,78937).
+char(m,78938).
+char(4,78939).
+char(9,78940).
+char(1,78941).
+char(3,78942).
+char(c,78943).
+char(p,78944).
+char(o,78945).
+char(m,78946).
+char(7,78947).
+char(2,78948).
+char(4,78949).
+char(6,78950).
+char(c,78951).
+char(m,78952).
+char(9,78953).
+char(2,78954).
+char(7,78955).
+char(5,78956).
+char(c,78957).
+char(p,78958).
+char(o,78959).
+char(1,78960).
+char(7,78961).
+char(6,78962).
+char(0,78963).
+char(c,78964).
+char(m,78965).
+char(4,78966).
+char(5,78967).
+char(5,78968).
+char(c,78969).
+char(c,78970).
+char(c,78971).
+char(c,78972).
+char(m,78973).
+char(o,78974).
+char(o,78975).
+char(p,78976).
+char(6,78977).
+char(4,78978).
+char(9,78979).
+char(1,78980).
+char(m,78981).
+char(5,78982).
+char(6,78983).
+char(0,78984).
+char(7,78985).
+char(c,78986).
+char(c,78987).
+char(c,78988).
+char(p,78989).
+char(o,78990).
+char(p,78991).
+char(o,78992).
+char(p,78993).
+char(o,78994).
+char(m,78995).
+char(o,78996).
+char(p,78997).
+char(1,78998).
+char(7,78999).
+char(4,79000).
+char(2,79001).
+char(c,79002).
+char(c,79003).
+char(m,79004).
+char(o,79005).
+char(m,79006).
+char(o,79007).
+char(o,79008).
+char(o,79009).
+char(1,79010).
+char(4,79011).
+char(2,79012).
+char(3,79013).
+char(c,79014).
+char(c,79015).
+char(c,79016).
+char(p,79017).
+char(o,79018).
+char(p,79019).
+char(o,79020).
+char(m,79021).
+char(8,79022).
+char(6,79023).
+char(1,79024).
+char(5,79025).
+char(m,79026).
+char(8,79027).
+char(1,79028).
+char(9,79029).
+char(7,79030).
+char(m,79031).
+char(o,79032).
+char(1,79033).
+char(4,79034).
+char(9,79035).
+char(0,79036).
+char(m,79037).
+char(o,79038).
+char(m,79039).
+char(o,79040).
+char(m,79041).
+char(1,79042).
+char(1,79043).
+char(2,79044).
+char(0,79045).
+char(p,79046).
+char(9,79047).
+char(6,79048).
+char(1,79049).
+char(5,79050).
+char(c,79051).
+char(m,79052).
+char(o,79053).
+char(p,79054).
+char(o,79055).
+char(p,79056).
+char(3,79057).
+char(1,79058).
+char(6,79059).
+char(4,79060).
+char(c,79061).
+char(c,79062).
+char(p,79063).
+char(4,79064).
+char(9,79065).
+char(4,79066).
+char(1,79067).
+char(m,79068).
+char(8,79069).
+char(1,79070).
+char(4,79071).
+char(0,79072).
+char(p,79073).
+char(o,79074).
+char(p,79075).
+char(o,79076).
+char(p,79077).
+char(o,79078).
+char(o,79079).
+char(m,79080).
+char(8,79081).
+char(1,79082).
+char(0,79083).
+char(7,79084).
+char(m,79085).
+char(o,79086).
+char(m,79087).
+char(o,79088).
+char(m,79089).
+char(o,79090).
+char(o,79091).
+char(7,79092).
+char(0,79093).
+char(6,79094).
+char(2,79095).
+char(p,79096).
+char(8,79097).
+char(3,79098).
+char(5,79099).
+char(6,79100).
+char(m,79101).
+char(o,79102).
+char(p,79103).
+char(o,79104).
+char(m,79105).
+char(o,79106).
+char(p,79107).
+char(o,79108).
+char(m,79109).
+char(1,79110).
+char(9,79111).
+char(9,79112).
+char(2,79113).
+char(c,79114).
+char(c,79115).
+char(c,79116).
+char(c,79117).
+char(c,79118).
+char(c,79119).
+char(p,79120).
+char(6,79121).
+char(2,79122).
+char(2,79123).
+char(8,79124).
+char(m,79125).
+char(o,79126).
+char(o,79127).
+char(o,79128).
+char(m,79129).
+char(4,79130).
+char(8,79131).
+char(2,79132).
+char(6,79133).
+char(m,79134).
+char(1,79135).
+char(7,79136).
+char(8,79137).
+char(1,79138).
+char(p,79139).
+char(5,79140).
+char(7,79141).
+char(3,79142).
+char(1,79143).
+char(m,79144).
+char(4,79145).
+char(8,79146).
+char(5,79147).
+char(7,79148).
+char(c,79149).
+char(c,79150).
+char(m,79151).
+char(o,79152).
+char(o,79153).
+char(o,79154).
+char(m,79155).
+char(o,79156).
+char(1,79157).
+char(0,79158).
+char(5,79159).
+char(3,79160).
+char(c,79161).
+char(c,79162).
+char(c,79163).
+char(c,79164).
+char(c,79165).
+char(c,79166).
+char(c,79167).
+char(p,79168).
+char(o,79169).
+char(o,79170).
+char(m,79171).
+char(o,79172).
+char(m,79173).
+char(o,79174).
+char(m,79175).
+char(3,79176).
+char(3,79177).
+char(4,79178).
+char(6,79179).
+char(c,79180).
+char(m,79181).
+char(7,79182).
+char(1,79183).
+char(5,79184).
+char(1,79185).
+char(m,79186).
+char(7,79187).
+char(1,79188).
+char(4,79189).
+char(1,79190).
+char(p,79191).
+char(2,79192).
+char(0,79193).
+char(0,79194).
+char(1,79195).
+char(p,79196).
+char(o,79197).
+char(m,79198).
+char(o,79199).
+char(p,79200).
+char(o,79201).
+char(m,79202).
+char(o,79203).
+char(p,79204).
+char(o,79205).
+char(m,79206).
+char(8,79207).
+char(2,79208).
+char(0,79209).
+char(0,79210).
+char(p,79211).
+char(5,79212).
+char(7,79213).
+char(4,79214).
+char(2,79215).
+char(c,79216).
+char(c,79217).
+char(c,79218).
+char(m,79219).
+char(6,79220).
+char(6,79221).
+char(4,79222).
+char(5,79223).
+char(c,79224).
+char(p,79225).
+char(2,79226).
+char(9,79227).
+char(3,79228).
+char(5,79229).
+char(m,79230).
+char(7,79231).
+char(0,79232).
+char(7,79233).
+char(c,79234).
+char(m,79235).
+char(3,79236).
+char(0,79237).
+char(4,79238).
+char(1,79239).
+char(p,79240).
+char(4,79241).
+char(4,79242).
+char(4,79243).
+char(6,79244).
+char(c,79245).
+char(c,79246).
+char(c,79247).
+char(c,79248).
+char(c,79249).
+char(p,79250).
+char(7,79251).
+char(6,79252).
+char(0,79253).
+char(6,79254).
+char(p,79255).
+char(o,79256).
+char(1,79257).
+char(0,79258).
+char(4,79259).
+char(0,79260).
+char(m,79261).
+char(o,79262).
+char(5,79263).
+char(8,79264).
+char(4,79265).
+char(0,79266).
+char(p,79267).
+char(o,79268).
+char(m,79269).
+char(7,79270).
+char(1,79271).
+char(7,79272).
+char(2,79273).
+char(c,79274).
+char(c,79275).
+char(c,79276).
+char(p,79277).
+char(o,79278).
+char(o,79279).
+char(m,79280).
+char(o,79281).
+char(m,79282).
+char(1,79283).
+char(7,79284).
+char(5,79285).
+char(3,79286).
+char(m,79287).
+char(2,79288).
+char(9,79289).
+char(4,79290).
+char(6,79291).
+char(c,79292).
+char(c,79293).
+char(c,79294).
+char(m,79295).
+char(o,79296).
+char(p,79297).
+char(o,79298).
+char(p,79299).
+char(o,79300).
+char(m,79301).
+char(o,79302).
+char(m,79303).
+char(o,79304).
+char(m,79305).
+char(o,79306).
+char(p,79307).
+char(4,79308).
+char(0,79309).
+char(7,79310).
+char(2,79311).
+char(p,79312).
+char(o,79313).
+char(m,79314).
+char(o,79315).
+char(p,79316).
+char(o,79317).
+char(p,79318).
+char(6,79319).
+char(8,79320).
+char(4,79321).
+char(4,79322).
+char(c,79323).
+char(m,79324).
+char(o,79325).
+char(o,79326).
+char(6,79327).
+char(3,79328).
+char(4,79329).
+char(8,79330).
+char(c,79331).
+char(p,79332).
+char(o,79333).
+char(p,79334).
+char(o,79335).
+char(m,79336).
+char(9,79337).
+char(8,79338).
+char(7,79339).
+char(0,79340).
+char(p,79341).
+char(5,79342).
+char(2,79343).
+char(1,79344).
+char(c,79345).
+char(m,79346).
+char(3,79347).
+char(9,79348).
+char(8,79349).
+char(3,79350).
+char(c,79351).
+char(p,79352).
+char(6,79353).
+char(3,79354).
+char(2,79355).
+char(6,79356).
+char(p,79357).
+char(4,79358).
+char(4,79359).
+char(4,79360).
+char(1,79361).
+char(c,79362).
+char(c,79363).
+char(p,79364).
+char(8,79365).
+char(4,79366).
+char(2,79367).
+char(7,79368).
+char(c,79369).
+char(m,79370).
+char(o,79371).
+char(m,79372).
+char(o,79373).
+char(3,79374).
+char(9,79375).
+char(1,79376).
+char(m,79377).
+char(o,79378).
+char(m,79379).
+char(o,79380).
+char(4,79381).
+char(2,79382).
+char(4,79383).
+char(8,79384).
+char(c,79385).
+char(m,79386).
+char(2,79387).
+char(7,79388).
+char(9,79389).
+char(2,79390).
+char(c,79391).
+char(c,79392).
+char(c,79393).
+char(p,79394).
+char(9,79395).
+char(0,79396).
+char(0,79397).
+char(2,79398).
+char(p,79399).
+char(o,79400).
+char(m,79401).
+char(3,79402).
+char(5,79403).
+char(4,79404).
+char(4,79405).
+char(m,79406).
+char(1,79407).
+char(6,79408).
+char(3,79409).
+char(4,79410).
+char(p,79411).
+char(o,79412).
+char(m,79413).
+char(o,79414).
+char(p,79415).
+char(8,79416).
+char(4,79417).
+char(9,79418).
+char(1,79419).
+char(c,79420).
+char(p,79421).
+char(o,79422).
+char(m,79423).
+char(6,79424).
+char(9,79425).
+char(9,79426).
+char(3,79427).
+char(p,79428).
+char(6,79429).
+char(3,79430).
+char(1,79431).
+char(2,79432).
+char(p,79433).
+char(5,79434).
+char(6,79435).
+char(3,79436).
+char(0,79437).
+char(c,79438).
+char(c,79439).
+char(m,79440).
+char(5,79441).
+char(7,79442).
+char(1,79443).
+char(9,79444).
+char(m,79445).
+char(o,79446).
+char(m,79447).
+char(o,79448).
+char(m,79449).
+char(6,79450).
+char(5,79451).
+char(9,79452).
+char(7,79453).
+char(m,79454).
+char(5,79455).
+char(7,79456).
+char(0,79457).
+char(9,79458).
+char(m,79459).
+char(o,79460).
+char(m,79461).
+char(o,79462).
+char(o,79463).
+char(o,79464).
+char(3,79465).
+char(0,79466).
+char(3,79467).
+char(4,79468).
+char(m,79469).
+char(8,79470).
+char(1,79471).
+char(8,79472).
+char(5,79473).
+char(m,79474).
+char(1,79475).
+char(1,79476).
+char(8,79477).
+char(8,79478).
+char(p,79479).
+char(1,79480).
+char(0,79481).
+char(7,79482).
+char(0,79483).
+char(m,79484).
+char(o,79485).
+char(5,79486).
+char(9,79487).
+char(9,79488).
+char(6,79489).
+char(c,79490).
+char(p,79491).
+char(8,79492).
+char(7,79493).
+char(4,79494).
+char(5,79495).
+char(c,79496).
+char(c,79497).
+char(c,79498).
+char(c,79499).
+char(c,79500).
+char(p,79501).
+char(3,79502).
+char(2,79503).
+char(5,79504).
+char(5,79505).
+char(c,79506).
+char(m,79507).
+char(4,79508).
+char(9,79509).
+char(3,79510).
+char(9,79511).
+char(c,79512).
+char(m,79513).
+char(7,79514).
+char(7,79515).
+char(1,79516).
+char(4,79517).
+char(c,79518).
+char(m,79519).
+char(o,79520).
+char(p,79521).
+char(o,79522).
+char(o,79523).
+char(4,79524).
+char(9,79525).
+char(3,79526).
+char(p,79527).
+char(o,79528).
+char(p,79529).
+char(5,79530).
+char(8,79531).
+char(8,79532).
+char(7,79533).
+char(p,79534).
+char(o,79535).
+char(1,79536).
+char(2,79537).
+char(7,79538).
+char(2,79539).
+char(c,79540).
+char(c,79541).
+char(c,79542).
+char(c,79543).
+char(p,79544).
+char(9,79545).
+char(3,79546).
+char(3,79547).
+char(8,79548).
+char(m,79549).
+char(o,79550).
+char(2,79551).
+char(7,79552).
+char(7,79553).
+char(1,79554).
+char(m,79555).
+char(7,79556).
+char(5,79557).
+char(1,79558).
+char(6,79559).
+char(m,79560).
+char(8,79561).
+char(3,79562).
+char(8,79563).
+char(9,79564).
+char(c,79565).
+char(m,79566).
+char(7,79567).
+char(6,79568).
+char(7,79569).
+char(4,79570).
+char(m,79571).
+char(2,79572).
+char(3,79573).
+char(2,79574).
+char(1,79575).
+char(c,79576).
+char(c,79577).
+char(m,79578).
+char(o,79579).
+char(m,79580).
+char(o,79581).
+char(o,79582).
+char(p,79583).
+char(8,79584).
+char(4,79585).
+char(9,79586).
+char(4,79587).
+char(c,79588).
+char(c,79589).
+char(c,79590).
+char(p,79591).
+char(o,79592).
+char(m,79593).
+char(o,79594).
+char(p,79595).
+char(6,79596).
+char(2,79597).
+char(9,79598).
+char(3,79599).
+char(c,79600).
+char(p,79601).
+char(o,79602).
+char(p,79603).
+char(o,79604).
+char(p,79605).
+char(o,79606).
+char(p,79607).
+char(6,79608).
+char(3,79609).
+char(6,79610).
+char(2,79611).
+char(m,79612).
+char(2,79613).
+char(3,79614).
+char(1,79615).
+char(0,79616).
+char(c,79617).
+char(c,79618).
+char(p,79619).
+char(o,79620).
+char(m,79621).
+char(2,79622).
+char(1,79623).
+char(2,79624).
+char(7,79625).
+char(c,79626).
+char(p,79627).
+char(6,79628).
+char(8,79629).
+char(9,79630).
+char(8,79631).
+char(p,79632).
+char(1,79633).
+char(5,79634).
+char(3,79635).
+char(4,79636).
+char(p,79637).
+char(o,79638).
+char(p,79639).
+char(2,79640).
+char(0,79641).
+char(9,79642).
+char(6,79643).
+char(c,79644).
+char(m,79645).
+char(o,79646).
+char(o,79647).
+char(p,79648).
+char(o,79649).
+char(p,79650).
+char(o,79651).
+char(7,79652).
+char(9,79653).
+char(1,79654).
+char(2,79655).
+char(m,79656).
+char(o,79657).
+char(m,79658).
+char(5,79659).
+char(2,79660).
+char(8,79661).
+char(0,79662).
+char(p,79663).
+char(o,79664).
+char(p,79665).
+char(2,79666).
+char(9,79667).
+char(2,79668).
+char(5,79669).
+char(c,79670).
+char(c,79671).
+char(m,79672).
+char(o,79673).
+char(8,79674).
+char(1,79675).
+char(8,79676).
+char(5,79677).
+char(c,79678).
+char(m,79679).
+char(o,79680).
+char(m,79681).
+char(o,79682).
+char(p,79683).
+char(8,79684).
+char(0,79685).
+char(5,79686).
+char(2,79687).
+char(p,79688).
+char(o,79689).
+char(m,79690).
+char(5,79691).
+char(6,79692).
+char(3,79693).
+char(7,79694).
+char(m,79695).
+char(o,79696).
+char(p,79697).
+char(5,79698).
+char(9,79699).
+char(5,79700).
+char(8,79701).
+char(c,79702).
+char(c,79703).
+char(c,79704).
+char(m,79705).
+char(o,79706).
+char(m,79707).
+char(5,79708).
+char(4,79709).
+char(8,79710).
+char(7,79711).
+char(c,79712).
+char(c,79713).
+char(c,79714).
+char(p,79715).
+char(o,79716).
+char(4,79717).
+char(0,79718).
+char(5,79719).
+char(6,79720).
+char(c,79721).
+char(p,79722).
+char(o,79723).
+char(m,79724).
+char(o,79725).
+char(m,79726).
+char(8,79727).
+char(8,79728).
+char(1,79729).
+char(8,79730).
+char(c,79731).
+char(c,79732).
+char(m,79733).
+char(7,79734).
+char(0,79735).
+char(2,79736).
+char(2,79737).
+char(c,79738).
+char(m,79739).
+char(6,79740).
+char(7,79741).
+char(2,79742).
+char(6,79743).
+char(c,79744).
+char(p,79745).
+char(o,79746).
+char(p,79747).
+char(5,79748).
+char(9,79749).
+char(9,79750).
+char(5,79751).
+char(m,79752).
+char(o,79753).
+char(m,79754).
+char(8,79755).
+char(7,79756).
+char(9,79757).
+char(0,79758).
+char(c,79759).
+char(p,79760).
+char(9,79761).
+char(5,79762).
+char(5,79763).
+char(5,79764).
+char(m,79765).
+char(6,79766).
+char(3,79767).
+char(6,79768).
+char(7,79769).
+char(p,79770).
+char(8,79771).
+char(4,79772).
+char(8,79773).
+char(1,79774).
+char(c,79775).
+char(p,79776).
+char(7,79777).
+char(9,79778).
+char(4,79779).
+char(8,79780).
+char(m,79781).
+char(9,79782).
+char(5,79783).
+char(4,79784).
+char(2,79785).
+char(m,79786).
+char(3,79787).
+char(1,79788).
+char(1,79789).
+char(6,79790).
+char(c,79791).
+char(c,79792).
+char(m,79793).
+char(5,79794).
+char(7,79795).
+char(8,79796).
+char(4,79797).
+char(c,79798).
+char(p,79799).
+char(1,79800).
+char(4,79801).
+char(0,79802).
+char(2,79803).
+char(c,79804).
+char(c,79805).
+char(p,79806).
+char(8,79807).
+char(1,79808).
+char(7,79809).
+char(6,79810).
+char(m,79811).
+char(6,79812).
+char(0,79813).
+char(6,79814).
+char(4,79815).
+char(c,79816).
+char(p,79817).
+char(o,79818).
+char(m,79819).
+char(o,79820).
+char(p,79821).
+char(o,79822).
+char(2,79823).
+char(9,79824).
+char(3,79825).
+char(6,79826).
+char(c,79827).
+char(p,79828).
+char(o,79829).
+char(m,79830).
+char(o,79831).
+char(p,79832).
+char(8,79833).
+char(5,79834).
+char(6,79835).
+char(8,79836).
+char(m,79837).
+char(4,79838).
+char(7,79839).
+char(4,79840).
+char(8,79841).
+char(c,79842).
+char(p,79843).
+char(6,79844).
+char(0,79845).
+char(1,79846).
+char(2,79847).
+char(p,79848).
+char(3,79849).
+char(7,79850).
+char(3,79851).
+char(8,79852).
+char(p,79853).
+char(o,79854).
+char(p,79855).
+char(o,79856).
+char(m,79857).
+char(6,79858).
+char(9,79859).
+char(6,79860).
+char(0,79861).
+char(c,79862).
+char(m,79863).
+char(7,79864).
+char(7,79865).
+char(5,79866).
+char(3,79867).
+char(c,79868).
+char(m,79869).
+char(o,79870).
+char(m,79871).
+char(8,79872).
+char(5,79873).
+char(5,79874).
+char(3,79875).
+char(m,79876).
+char(o,79877).
+char(6,79878).
+char(6,79879).
+char(6,79880).
+char(1,79881).
+char(m,79882).
+char(o,79883).
+char(p,79884).
+char(8,79885).
+char(1,79886).
+char(9,79887).
+char(c,79888).
+char(c,79889).
+char(m,79890).
+char(4,79891).
+char(2,79892).
+char(6,79893).
+char(9,79894).
+char(p,79895).
+char(o,79896).
+char(6,79897).
+char(6,79898).
+char(6,79899).
+char(3,79900).
+char(c,79901).
+char(c,79902).
+char(c,79903).
+char(c,79904).
+char(p,79905).
+char(o,79906).
+char(p,79907).
+char(o,79908).
+char(o,79909).
+char(p,79910).
+char(4,79911).
+char(7,79912).
+char(2,79913).
+char(9,79914).
+char(c,79915).
+char(c,79916).
+char(c,79917).
+char(p,79918).
+char(9,79919).
+char(8,79920).
+char(6,79921).
+char(4,79922).
+char(m,79923).
+char(o,79924).
+char(p,79925).
+char(o,79926).
+char(o,79927).
+char(o,79928).
+char(o,79929).
+char(7,79930).
+char(3,79931).
+char(4,79932).
+char(4,79933).
+char(c,79934).
+char(p,79935).
+char(1,79936).
+char(7,79937).
+char(8,79938).
+char(9,79939).
+char(p,79940).
+char(o,79941).
+char(4,79942).
+char(3,79943).
+char(5,79944).
+char(3,79945).
+char(p,79946).
+char(2,79947).
+char(1,79948).
+char(5,79949).
+char(5,79950).
+char(p,79951).
+char(5,79952).
+char(2,79953).
+char(5,79954).
+char(0,79955).
+char(c,79956).
+char(p,79957).
+char(1,79958).
+char(8,79959).
+char(8,79960).
+char(8,79961).
+char(c,79962).
+char(m,79963).
+char(o,79964).
+char(m,79965).
+char(o,79966).
+char(p,79967).
+char(o,79968).
+char(o,79969).
+char(6,79970).
+char(4,79971).
+char(1,79972).
+char(6,79973).
+char(m,79974).
+char(o,79975).
+char(9,79976).
+char(8,79977).
+char(8,79978).
+char(7,79979).
+char(c,79980).
+char(c,79981).
+char(c,79982).
+char(m,79983).
+char(2,79984).
+char(2,79985).
+char(3,79986).
+char(8,79987).
+char(p,79988).
+char(5,79989).
+char(7,79990).
+char(7,79991).
+char(2,79992).
+char(m,79993).
+char(o,79994).
+char(o,79995).
+char(m,79996).
+char(4,79997).
+char(8,79998).
+char(4,79999).
+char(7,80000).
+char(c,80001).
+char(p,80002).
+char(o,80003).
+char(m,80004).
+char(5,80005).
+char(1,80006).
+char(8,80007).
+char(c,80008).
+char(c,80009).
+char(m,80010).
+char(2,80011).
+char(3,80012).
+char(2,80013).
+char(5,80014).
+char(m,80015).
+char(9,80016).
+char(7,80017).
+char(6,80018).
+char(6,80019).
+char(p,80020).
+char(o,80021).
+char(m,80022).
+char(o,80023).
+char(p,80024).
+char(o,80025).
+char(p,80026).
+char(7,80027).
+char(1,80028).
+char(6,80029).
+char(1,80030).
+char(c,80031).
+char(p,80032).
+char(3,80033).
+char(4,80034).
+char(6,80035).
+char(6,80036).
+char(p,80037).
+char(o,80038).
+char(1,80039).
+char(8,80040).
+char(5,80041).
+char(3,80042).
+char(c,80043).
+char(m,80044).
+char(5,80045).
+char(4,80046).
+char(1,80047).
+char(9,80048).
+char(c,80049).
+char(c,80050).
+char(c,80051).
+char(c,80052).
+char(p,80053).
+char(o,80054).
+char(m,80055).
+char(6,80056).
+char(8,80057).
+char(p,80058).
+char(o,80059).
+char(p,80060).
+char(o,80061).
+char(3,80062).
+char(6,80063).
+char(3,80064).
+char(8,80065).
+char(m,80066).
+char(2,80067).
+char(0,80068).
+char(1,80069).
+char(3,80070).
+char(c,80071).
+char(c,80072).
+char(m,80073).
+char(o,80074).
+char(8,80075).
+char(6,80076).
+char(3,80077).
+char(1,80078).
+char(m,80079).
+char(9,80080).
+char(6,80081).
+char(2,80082).
+char(7,80083).
+char(p,80084).
+char(5,80085).
+char(9,80086).
+char(7,80087).
+char(8,80088).
+char(p,80089).
+char(o,80090).
+char(o,80091).
+char(p,80092).
+char(8,80093).
+char(7,80094).
+char(9,80095).
+char(m,80096).
+char(o,80097).
+char(p,80098).
+char(o,80099).
+char(m,80100).
+char(o,80101).
+char(m,80102).
+char(o,80103).
+char(p,80104).
+char(o,80105).
+char(o,80106).
+char(p,80107).
+char(5,80108).
+char(6,80109).
+char(3,80110).
+char(1,80111).
+char(m,80112).
+char(o,80113).
+char(1,80114).
+char(3,80115).
+char(5,80116).
+char(c,80117).
+char(c,80118).
+char(m,80119).
+char(3,80120).
+char(4,80121).
+char(8,80122).
+char(5,80123).
+char(m,80124).
+char(1,80125).
+char(8,80126).
+char(4,80127).
+char(4,80128).
+char(m,80129).
+char(9,80130).
+char(8,80131).
+char(0,80132).
+char(1,80133).
+char(p,80134).
+char(6,80135).
+char(5,80136).
+char(9,80137).
+char(7,80138).
+char(m,80139).
+char(8,80140).
+char(3,80141).
+char(9,80142).
+char(5,80143).
+char(c,80144).
+char(p,80145).
+char(o,80146).
+char(m,80147).
+char(8,80148).
+char(8,80149).
+char(1,80150).
+char(9,80151).
+char(c,80152).
+char(c,80153).
+char(p,80154).
+char(o,80155).
+char(p,80156).
+char(7,80157).
+char(5,80158).
+char(8,80159).
+char(5,80160).
+char(c,80161).
+char(p,80162).
+char(6,80163).
+char(5,80164).
+char(7,80165).
+char(8,80166).
+char(c,80167).
+char(c,80168).
+char(c,80169).
+char(m,80170).
+char(7,80171).
+char(9,80172).
+char(7,80173).
+char(7,80174).
+char(c,80175).
+char(m,80176).
+char(o,80177).
+char(m,80178).
+char(o,80179).
+char(p,80180).
+char(9,80181).
+char(8,80182).
+char(2,80183).
+char(5,80184).
+char(c,80185).
+char(p,80186).
+char(9,80187).
+char(3,80188).
+char(8,80189).
+char(c,80190).
+char(c,80191).
+char(c,80192).
+char(c,80193).
+char(m,80194).
+char(8,80195).
+char(4,80196).
+char(8,80197).
+char(7,80198).
+char(c,80199).
+char(c,80200).
+char(c,80201).
+char(c,80202).
+char(p,80203).
+char(o,80204).
+char(8,80205).
+char(3,80206).
+char(3,80207).
+char(c,80208).
+char(c,80209).
+char(c,80210).
+char(c,80211).
+char(p,80212).
+char(o,80213).
+char(m,80214).
+char(9,80215).
+char(1,80216).
+char(9,80217).
+char(p,80218).
+char(o,80219).
+char(3,80220).
+char(6,80221).
+char(3,80222).
+char(5,80223).
+char(c,80224).
+char(c,80225).
+char(m,80226).
+char(o,80227).
+char(m,80228).
+char(o,80229).
+char(o,80230).
+char(o,80231).
+char(m,80232).
+char(1,80233).
+char(1,80234).
+char(6,80235).
+char(0,80236).
+char(c,80237).
+char(p,80238).
+char(7,80239).
+char(0,80240).
+char(1,80241).
+char(5,80242).
+char(c,80243).
+char(c,80244).
+char(m,80245).
+char(o,80246).
+char(m,80247).
+char(o,80248).
+char(p,80249).
+char(7,80250).
+char(5,80251).
+char(1,80252).
+char(5,80253).
+char(p,80254).
+char(o,80255).
+char(m,80256).
+char(4,80257).
+char(4,80258).
+char(3,80259).
+char(5,80260).
+char(c,80261).
+char(p,80262).
+char(8,80263).
+char(6,80264).
+char(9,80265).
+char(4,80266).
+char(m,80267).
+char(o,80268).
+char(m,80269).
+char(7,80270).
+char(9,80271).
+char(4,80272).
+char(1,80273).
+char(p,80274).
+char(o,80275).
+char(o,80276).
+char(o,80277).
+char(m,80278).
+char(o,80279).
+char(p,80280).
+char(6,80281).
+char(5,80282).
+char(3,80283).
+char(6,80284).
+char(m,80285).
+char(o,80286).
+char(m,80287).
+char(9,80288).
+char(1,80289).
+char(2,80290).
+char(c,80291).
+char(p,80292).
+char(8,80293).
+char(9,80294).
+char(9,80295).
+char(4,80296).
+char(p,80297).
+char(o,80298).
+char(p,80299).
+char(1,80300).
+char(8,80301).
+char(0,80302).
+char(9,80303).
+char(c,80304).
+char(m,80305).
+char(o,80306).
+char(p,80307).
+char(2,80308).
+char(5,80309).
+char(8,80310).
+char(0,80311).
+char(p,80312).
+char(o,80313).
+char(m,80314).
+char(2,80315).
+char(3,80316).
+char(4,80317).
+char(4,80318).
+char(c,80319).
+char(p,80320).
+char(o,80321).
+char(m,80322).
+char(8,80323).
+char(2,80324).
+char(0,80325).
+char(m,80326).
+char(4,80327).
+char(0,80328).
+char(6,80329).
+char(1,80330).
+char(m,80331).
+char(2,80332).
+char(7,80333).
+char(9,80334).
+char(9,80335).
+char(c,80336).
+char(p,80337).
+char(o,80338).
+char(p,80339).
+char(2,80340).
+char(7,80341).
+char(3,80342).
+char(7,80343).
+char(c,80344).
+char(c,80345).
+char(c,80346).
+char(m,80347).
+char(7,80348).
+char(7,80349).
+char(5,80350).
+char(6,80351).
+char(p,80352).
+char(o,80353).
+char(m,80354).
+char(o,80355).
+char(p,80356).
+char(o,80357).
+char(o,80358).
+char(p,80359).
+char(o,80360).
+char(p,80361).
+char(7,80362).
+char(6,80363).
+char(8,80364).
+char(5,80365).
+char(c,80366).
+char(p,80367).
+char(o,80368).
+char(m,80369).
+char(o,80370).
+char(p,80371).
+char(8,80372).
+char(7,80373).
+char(4,80374).
+char(2,80375).
+char(m,80376).
+char(1,80377).
+char(4,80378).
+char(7,80379).
+char(9,80380).
+char(c,80381).
+char(c,80382).
+char(p,80383).
+char(4,80384).
+char(9,80385).
+char(1,80386).
+char(8,80387).
+char(m,80388).
+char(o,80389).
+char(o,80390).
+char(p,80391).
+char(4,80392).
+char(5,80393).
+char(5,80394).
+char(3,80395).
+char(c,80396).
+char(m,80397).
+char(o,80398).
+char(m,80399).
+char(7,80400).
+char(8,80401).
+char(2,80402).
+char(4,80403).
+char(c,80404).
+char(p,80405).
+char(o,80406).
+char(m,80407).
+char(9,80408).
+char(4,80409).
+char(6,80410).
+char(1,80411).
+char(c,80412).
+char(m,80413).
+char(2,80414).
+char(9,80415).
+char(1,80416).
+char(0,80417).
+char(c,80418).
+char(m,80419).
+char(o,80420).
+char(p,80421).
+char(o,80422).
+char(4,80423).
+char(0,80424).
+char(9,80425).
+char(7,80426).
+char(c,80427).
+char(c,80428).
+char(c,80429).
+char(c,80430).
+char(c,80431).
+char(c,80432).
+char(c,80433).
+char(m,80434).
+char(o,80435).
+char(p,80436).
+char(9,80437).
+char(4,80438).
+char(0,80439).
+char(c,80440).
+char(m,80441).
+char(o,80442).
+char(m,80443).
+char(o,80444).
+char(p,80445).
+char(3,80446).
+char(0,80447).
+char(6,80448).
+char(1,80449).
+char(c,80450).
+char(m,80451).
+char(o,80452).
+char(o,80453).
+char(o,80454).
+char(p,80455).
+char(9,80456).
+char(7,80457).
+char(3,80458).
+char(4,80459).
+char(p,80460).
+char(7,80461).
+char(8,80462).
+char(3,80463).
+char(3,80464).
+char(c,80465).
+char(p,80466).
+char(o,80467).
+char(p,80468).
+char(4,80469).
+char(1,80470).
+char(6,80471).
+char(m,80472).
+char(o,80473).
+char(p,80474).
+char(o,80475).
+char(m,80476).
+char(5,80477).
+char(1,80478).
+char(7,80479).
+char(2,80480).
+char(m,80481).
+char(3,80482).
+char(6,80483).
+char(2,80484).
+char(4,80485).
+char(c,80486).
+char(m,80487).
+char(o,80488).
+char(p,80489).
+char(2,80490).
+char(6,80491).
+char(4,80492).
+char(9,80493).
+char(p,80494).
+char(5,80495).
+char(0,80496).
+char(4,80497).
+char(3,80498).
+char(p,80499).
+char(9,80500).
+char(8,80501).
+char(7,80502).
+char(7,80503).
+char(p,80504).
+char(o,80505).
+char(9,80506).
+char(8,80507).
+char(5,80508).
+char(5,80509).
+char(c,80510).
+char(p,80511).
+char(o,80512).
+char(m,80513).
+char(1,80514).
+char(8,80515).
+char(5,80516).
+char(9,80517).
+char(c,80518).
+char(c,80519).
+char(c,80520).
+char(m,80521).
+char(7,80522).
+char(1,80523).
+char(8,80524).
+char(p,80525).
+char(1,80526).
+char(2,80527).
+char(7,80528).
+char(8,80529).
+char(c,80530).
+char(c,80531).
+char(c,80532).
+char(c,80533).
+char(c,80534).
+char(c,80535).
+char(c,80536).
+char(c,80537).
+char(m,80538).
+char(o,80539).
+char(p,80540).
+char(o,80541).
+char(8,80542).
+char(5,80543).
+char(6,80544).
+char(0,80545).
+char(m,80546).
+char(7,80547).
+char(9,80548).
+char(5,80549).
+char(7,80550).
+char(p,80551).
+char(5,80552).
+char(6,80553).
+char(7,80554).
+char(3,80555).
+char(c,80556).
+char(c,80557).
+char(c,80558).
+char(p,80559).
+char(o,80560).
+char(p,80561).
+char(o,80562).
+char(m,80563).
+char(o,80564).
+char(m,80565).
+char(9,80566).
+char(7,80567).
+char(4,80568).
+char(6,80569).
+char(p,80570).
+char(2,80571).
+char(5,80572).
+char(5,80573).
+char(2,80574).
+char(c,80575).
+char(p,80576).
+char(o,80577).
+char(5,80578).
+char(7,80579).
+char(8,80580).
+char(7,80581).
+char(m,80582).
+char(8,80583).
+char(9,80584).
+char(2,80585).
+char(7,80586).
+char(p,80587).
+char(8,80588).
+char(3,80589).
+char(6,80590).
+char(5,80591).
+char(p,80592).
+char(3,80593).
+char(9,80594).
+char(2,80595).
+char(6,80596).
+char(p,80597).
+char(o,80598).
+char(4,80599).
+char(4,80600).
+char(9,80601).
+char(5,80602).
+char(p,80603).
+char(5,80604).
+char(4,80605).
+char(9,80606).
+char(5,80607).
+char(c,80608).
+char(m,80609).
+char(3,80610).
+char(1,80611).
+char(9,80612).
+char(p,80613).
+char(o,80614).
+char(o,80615).
+char(p,80616).
+char(o,80617).
+char(m,80618).
+char(o,80619).
+char(m,80620).
+char(7,80621).
+char(1,80622).
+char(1,80623).
+char(m,80624).
+char(o,80625).
+char(m,80626).
+char(o,80627).
+char(p,80628).
+char(o,80629).
+char(m,80630).
+char(o,80631).
+char(6,80632).
+char(1,80633).
+char(6,80634).
+char(5,80635).
+char(m,80636).
+char(3,80637).
+char(9,80638).
+char(8,80639).
+char(5,80640).
+char(p,80641).
+char(o,80642).
+char(p,80643).
+char(2,80644).
+char(5,80645).
+char(9,80646).
+char(8,80647).
+char(p,80648).
+char(o,80649).
+char(o,80650).
+char(m,80651).
+char(o,80652).
+char(p,80653).
+char(6,80654).
+char(3,80655).
+char(0,80656).
+char(7,80657).
+char(m,80658).
+char(1,80659).
+char(4,80660).
+char(9,80661).
+char(m,80662).
+char(o,80663).
+char(m,80664).
+char(4,80665).
+char(8,80666).
+char(1,80667).
+char(7,80668).
+char(c,80669).
+char(c,80670).
+char(c,80671).
+char(m,80672).
+char(o,80673).
+char(p,80674).
+char(o,80675).
+char(6,80676).
+char(4,80677).
+char(8,80678).
+char(5,80679).
+char(c,80680).
+char(p,80681).
+char(o,80682).
+char(p,80683).
+char(o,80684).
+char(p,80685).
+char(3,80686).
+char(1,80687).
+char(1,80688).
+char(2,80689).
+char(c,80690).
+char(p,80691).
+char(o,80692).
+char(p,80693).
+char(o,80694).
+char(m,80695).
+char(o,80696).
+char(p,80697).
+char(4,80698).
+char(2,80699).
+char(9,80700).
+char(0,80701).
+char(m,80702).
+char(3,80703).
+char(3,80704).
+char(6,80705).
+char(4,80706).
+char(m,80707).
+char(o,80708).
+char(o,80709).
+char(p,80710).
+char(o,80711).
+char(p,80712).
+char(o,80713).
+char(o,80714).
+char(o,80715).
+char(1,80716).
+char(3,80717).
+char(8,80718).
+char(0,80719).
+char(c,80720).
+char(c,80721).
+char(p,80722).
+char(o,80723).
+char(9,80724).
+char(7,80725).
+char(8,80726).
+char(5,80727).
+char(c,80728).
+char(m,80729).
+char(o,80730).
+char(p,80731).
+char(8,80732).
+char(0,80733).
+char(7,80734).
+char(1,80735).
+char(p,80736).
+char(o,80737).
+char(m,80738).
+char(o,80739).
+char(o,80740).
+char(m,80741).
+char(8,80742).
+char(5,80743).
+char(7,80744).
+char(5,80745).
+char(m,80746).
+char(o,80747).
+char(p,80748).
+char(o,80749).
+char(p,80750).
+char(o,80751).
+char(p,80752).
+char(o,80753).
+char(p,80754).
+char(7,80755).
+char(5,80756).
+char(9,80757).
+char(9,80758).
+char(m,80759).
+char(6,80760).
+char(2,80761).
+char(6,80762).
+char(4,80763).
+char(c,80764).
+char(m,80765).
+char(8,80766).
+char(8,80767).
+char(3,80768).
+char(c,80769).
+char(c,80770).
+char(c,80771).
+char(c,80772).
+char(p,80773).
+char(5,80774).
+char(2,80775).
+char(8,80776).
+char(3,80777).
+char(c,80778).
+char(c,80779).
+char(c,80780).
+char(m,80781).
+char(1,80782).
+char(6,80783).
+char(4,80784).
+char(8,80785).
+char(c,80786).
+char(c,80787).
+char(c,80788).
+char(c,80789).
+char(m,80790).
+char(o,80791).
+char(o,80792).
+char(m,80793).
+char(7,80794).
+char(3,80795).
+char(2,80796).
+char(9,80797).
+char(c,80798).
+char(c,80799).
+char(m,80800).
+char(o,80801).
+char(p,80802).
+char(o,80803).
+char(o,80804).
+char(m,80805).
+char(o,80806).
+char(p,80807).
+char(8,80808).
+char(7,80809).
+char(4,80810).
+char(3,80811).
+char(c,80812).
+char(m,80813).
+char(o,80814).
+char(p,80815).
+char(8,80816).
+char(5,80817).
+char(8,80818).
+char(5,80819).
+char(p,80820).
+char(4,80821).
+char(1,80822).
+char(2,80823).
+char(3,80824).
+char(m,80825).
+char(o,80826).
+char(3,80827).
+char(0,80828).
+char(7,80829).
+char(1,80830).
+char(c,80831).
+char(m,80832).
+char(5,80833).
+char(4,80834).
+char(2,80835).
+char(9,80836).
+char(c,80837).
+char(c,80838).
+char(m,80839).
+char(1,80840).
+char(3,80841).
+char(0,80842).
+char(9,80843).
+char(c,80844).
+char(c,80845).
+char(c,80846).
+char(m,80847).
+char(3,80848).
+char(4,80849).
+char(7,80850).
+char(8,80851).
+char(c,80852).
+char(p,80853).
+char(o,80854).
+char(o,80855).
+char(o,80856).
+char(m,80857).
+char(4,80858).
+char(2,80859).
+char(3,80860).
+char(1,80861).
+char(c,80862).
+char(c,80863).
+char(m,80864).
+char(5,80865).
+char(7,80866).
+char(5,80867).
+char(7,80868).
+char(p,80869).
+char(o,80870).
+char(o,80871).
+char(p,80872).
+char(8,80873).
+char(6,80874).
+char(6,80875).
+char(5,80876).
+char(p,80877).
+char(o,80878).
+char(p,80879).
+char(5,80880).
+char(5,80881).
+char(2,80882).
+char(4,80883).
+char(c,80884).
+char(m,80885).
+char(o,80886).
+char(4,80887).
+char(9,80888).
+char(3,80889).
+char(6,80890).
+char(c,80891).
+char(p,80892).
+char(o,80893).
+char(p,80894).
+char(1,80895).
+char(5,80896).
+char(8,80897).
+char(4,80898).
+char(p,80899).
+char(4,80900).
+char(2,80901).
+char(9,80902).
+char(6,80903).
+char(c,80904).
+char(p,80905).
+char(3,80906).
+char(9,80907).
+char(2,80908).
+char(9,80909).
+char(p,80910).
+char(8,80911).
+char(8,80912).
+char(1,80913).
+char(5,80914).
+char(p,80915).
+char(5,80916).
+char(1,80917).
+char(3,80918).
+char(0,80919).
+char(p,80920).
+char(5,80921).
+char(5,80922).
+char(0,80923).
+char(5,80924).
+char(p,80925).
+char(2,80926).
+char(6,80927).
+char(8,80928).
+char(1,80929).
+char(m,80930).
+char(o,80931).
+char(4,80932).
+char(1,80933).
+char(9,80934).
+char(0,80935).
+char(p,80936).
+char(3,80937).
+char(3,80938).
+char(7,80939).
+char(6,80940).
+char(c,80941).
+char(c,80942).
+char(p,80943).
+char(o,80944).
+char(m,80945).
+char(o,80946).
+char(m,80947).
+char(o,80948).
+char(p,80949).
+char(8,80950).
+char(8,80951).
+char(5,80952).
+char(5,80953).
+char(c,80954).
+char(c,80955).
+char(p,80956).
+char(o,80957).
+char(m,80958).
+char(o,80959).
+char(p,80960).
+char(o,80961).
+char(m,80962).
+char(3,80963).
+char(9,80964).
+char(8,80965).
+char(3,80966).
+char(c,80967).
+char(m,80968).
+char(6,80969).
+char(6,80970).
+char(2,80971).
+char(6,80972).
+char(p,80973).
+char(7,80974).
+char(9,80975).
+char(3,80976).
+char(7,80977).
+char(c,80978).
+char(p,80979).
+char(9,80980).
+char(0,80981).
+char(7,80982).
+char(8,80983).
+char(c,80984).
+char(m,80985).
+char(7,80986).
+char(1,80987).
+char(2,80988).
+char(7,80989).
+char(c,80990).
+char(p,80991).
+char(1,80992).
+char(6,80993).
+char(6,80994).
+char(7,80995).
+char(c,80996).
+char(c,80997).
+char(m,80998).
+char(o,80999).
+char(8,81000).
+char(7,81001).
+char(4,81002).
+char(1,81003).
+char(c,81004).
+char(c,81005).
+char(p,81006).
+char(o,81007).
+char(o,81008).
+char(p,81009).
+char(9,81010).
+char(3,81011).
+char(1,81012).
+char(6,81013).
+char(c,81014).
+char(m,81015).
+char(6,81016).
+char(9,81017).
+char(8,81018).
+char(8,81019).
+char(c,81020).
+char(p,81021).
+char(1,81022).
+char(0,81023).
+char(9,81024).
+char(9,81025).
+char(m,81026).
+char(7,81027).
+char(6,81028).
+char(8,81029).
+char(7,81030).
+char(c,81031).
+char(c,81032).
+char(p,81033).
+char(3,81034).
+char(7,81035).
+char(4,81036).
+char(p,81037).
+char(2,81038).
+char(7,81039).
+char(4,81040).
+char(9,81041).
+char(p,81042).
+char(7,81043).
+char(6,81044).
+char(4,81045).
+char(8,81046).
+char(p,81047).
+char(1,81048).
+char(0,81049).
+char(6,81050).
+char(7,81051).
+char(m,81052).
+char(4,81053).
+char(8,81054).
+char(6,81055).
+char(6,81056).
+char(p,81057).
+char(3,81058).
+char(1,81059).
+char(3,81060).
+char(7,81061).
+char(p,81062).
+char(6,81063).
+char(0,81064).
+char(3,81065).
+char(3,81066).
+char(p,81067).
+char(o,81068).
+char(m,81069).
+char(5,81070).
+char(7,81071).
+char(7,81072).
+char(3,81073).
+char(c,81074).
+char(m,81075).
+char(4,81076).
+char(1,81077).
+char(4,81078).
+char(5,81079).
+char(p,81080).
+char(o,81081).
+char(m,81082).
+char(o,81083).
+char(p,81084).
+char(o,81085).
+char(p,81086).
+char(o,81087).
+char(o,81088).
+char(o,81089).
+char(p,81090).
+char(o,81091).
+char(4,81092).
+char(6,81093).
+char(7,81094).
+char(m,81095).
+char(o,81096).
+char(6,81097).
+char(5,81098).
+char(7,81099).
+char(8,81100).
+char(m,81101).
+char(1,81102).
+char(6,81103).
+char(1,81104).
+char(8,81105).
+char(p,81106).
+char(o,81107).
+char(p,81108).
+char(o,81109).
+char(p,81110).
+char(o,81111).
+char(8,81112).
+char(9,81113).
+char(3,81114).
+char(4,81115).
+char(m,81116).
+char(o,81117).
+char(p,81118).
+char(o,81119).
+char(2,81120).
+char(6,81121).
+char(4,81122).
+char(8,81123).
+char(m,81124).
+char(o,81125).
+char(o,81126).
+char(p,81127).
+char(o,81128).
+char(m,81129).
+char(2,81130).
+char(8,81131).
+char(9,81132).
+char(3,81133).
+char(c,81134).
+char(c,81135).
+char(p,81136).
+char(3,81137).
+char(1,81138).
+char(6,81139).
+char(4,81140).
+char(c,81141).
+char(m,81142).
+char(o,81143).
+char(m,81144).
+char(o,81145).
+char(o,81146).
+char(o,81147).
+char(m,81148).
+char(o,81149).
+char(m,81150).
+char(o,81151).
+char(p,81152).
+char(o,81153).
+char(2,81154).
+char(0,81155).
+char(5,81156).
+char(2,81157).
+char(c,81158).
+char(c,81159).
+char(m,81160).
+char(o,81161).
+char(6,81162).
+char(3,81163).
+char(0,81164).
+char(m,81165).
+char(2,81166).
+char(6,81167).
+char(2,81168).
+char(4,81169).
+char(c,81170).
+char(c,81171).
+char(c,81172).
+char(m,81173).
+char(5,81174).
+char(4,81175).
+char(6,81176).
+char(6,81177).
+char(m,81178).
+char(o,81179).
+char(1,81180).
+char(3,81181).
+char(7,81182).
+char(c,81183).
+char(c,81184).
+char(c,81185).
+char(p,81186).
+char(6,81187).
+char(5,81188).
+char(1,81189).
+char(9,81190).
+char(c,81191).
+char(c,81192).
+char(m,81193).
+char(7,81194).
+char(7,81195).
+char(4,81196).
+char(1,81197).
+char(p,81198).
+char(6,81199).
+char(3,81200).
+char(9,81201).
+char(c,81202).
+char(m,81203).
+char(1,81204).
+char(6,81205).
+char(8,81206).
+char(c,81207).
+char(m,81208).
+char(8,81209).
+char(9,81210).
+char(4,81211).
+char(9,81212).
+char(c,81213).
+char(c,81214).
+char(c,81215).
+char(c,81216).
+char(m,81217).
+char(4,81218).
+char(6,81219).
+char(2,81220).
+char(2,81221).
+char(c,81222).
+char(m,81223).
+char(6,81224).
+char(9,81225).
+char(9,81226).
+char(6,81227).
+char(c,81228).
+char(m,81229).
+char(6,81230).
+char(8,81231).
+char(2,81232).
+char(0,81233).
+char(c,81234).
+char(m,81235).
+char(o,81236).
+char(m,81237).
+char(o,81238).
+char(o,81239).
+char(m,81240).
+char(6,81241).
+char(5,81242).
+char(2,81243).
+char(2,81244).
+char(c,81245).
+char(p,81246).
+char(2,81247).
+char(7,81248).
+char(3,81249).
+char(1,81250).
+char(c,81251).
+char(c,81252).
+char(c,81253).
+char(m,81254).
+char(6,81255).
+char(2,81256).
+char(8,81257).
+char(m,81258).
+char(4,81259).
+char(7,81260).
+char(7,81261).
+char(5,81262).
+char(c,81263).
+char(c,81264).
+char(c,81265).
+char(c,81266).
+char(p,81267).
+char(o,81268).
+char(p,81269).
+char(o,81270).
+char(m,81271).
+char(o,81272).
+char(m,81273).
+char(1,81274).
+char(5,81275).
+char(2,81276).
+char(2,81277).
+char(c,81278).
+char(c,81279).
+char(c,81280).
+char(m,81281).
+char(1,81282).
+char(2,81283).
+char(3,81284).
+char(0,81285).
+char(m,81286).
+char(o,81287).
+char(m,81288).
+char(o,81289).
+char(p,81290).
+char(o,81291).
+char(o,81292).
+char(m,81293).
+char(o,81294).
+char(p,81295).
+char(o,81296).
+char(o,81297).
+char(m,81298).
+char(4,81299).
+char(4,81300).
+char(9,81301).
+char(2,81302).
+char(m,81303).
+char(o,81304).
+char(3,81305).
+char(7,81306).
+char(6,81307).
+char(2,81308).
+char(c,81309).
+char(c,81310).
+char(m,81311).
+char(o,81312).
+char(p,81313).
+char(o,81314).
+char(m,81315).
+char(o,81316).
+char(m,81317).
+char(7,81318).
+char(8,81319).
+char(3,81320).
+char(6,81321).
+char(p,81322).
+char(3,81323).
+char(4,81324).
+char(8,81325).
+char(8,81326).
+char(c,81327).
+char(p,81328).
+char(4,81329).
+char(8,81330).
+char(0,81331).
+char(6,81332).
+char(c,81333).
+char(c,81334).
+char(c,81335).
+char(c,81336).
+char(c,81337).
+char(m,81338).
+char(o,81339).
+char(m,81340).
+char(3,81341).
+char(3,81342).
+char(0,81343).
+char(8,81344).
+char(c,81345).
+char(m,81346).
+char(8,81347).
+char(4,81348).
+char(4,81349).
+char(2,81350).
+char(c,81351).
+char(c,81352).
+char(c,81353).
+char(c,81354).
+char(c,81355).
+char(c,81356).
+char(c,81357).
+char(c,81358).
+char(p,81359).
+char(6,81360).
+char(4,81361).
+char(8,81362).
+char(5,81363).
+char(m,81364).
+char(7,81365).
+char(3,81366).
+char(9,81367).
+char(2,81368).
+char(c,81369).
+char(m,81370).
+char(o,81371).
+char(o,81372).
+char(o,81373).
+char(o,81374).
+char(7,81375).
+char(2,81376).
+char(6,81377).
+char(m,81378).
+char(5,81379).
+char(9,81380).
+char(1,81381).
+char(2,81382).
+char(m,81383).
+char(8,81384).
+char(1,81385).
+char(0,81386).
+char(3,81387).
+char(c,81388).
+char(c,81389).
+char(c,81390).
+char(c,81391).
+char(m,81392).
+char(o,81393).
+char(p,81394).
+char(9,81395).
+char(5,81396).
+char(c,81397).
+char(c,81398).
+char(m,81399).
+char(o,81400).
+char(p,81401).
+char(o,81402).
+char(3,81403).
+char(4,81404).
+char(5,81405).
+char(5,81406).
+char(c,81407).
+char(p,81408).
+char(9,81409).
+char(4,81410).
+char(1,81411).
+char(6,81412).
+char(m,81413).
+char(o,81414).
+char(m,81415).
+char(4,81416).
+char(1,81417).
+char(3,81418).
+char(3,81419).
+char(m,81420).
+char(o,81421).
+char(o,81422).
+char(m,81423).
+char(o,81424).
+char(1,81425).
+char(3,81426).
+char(5,81427).
+char(4,81428).
+char(c,81429).
+char(c,81430).
+char(c,81431).
+char(c,81432).
+char(c,81433).
+char(c,81434).
+char(c,81435).
+char(m,81436).
+char(o,81437).
+char(m,81438).
+char(o,81439).
+char(p,81440).
+char(7,81441).
+char(2,81442).
+char(7,81443).
+char(c,81444).
+char(c,81445).
+char(p,81446).
+char(5,81447).
+char(7,81448).
+char(0,81449).
+char(9,81450).
+char(c,81451).
+char(c,81452).
+char(c,81453).
+char(m,81454).
+char(o,81455).
+char(m,81456).
+char(1,81457).
+char(4,81458).
+char(2,81459).
+char(8,81460).
+char(c,81461).
+char(c,81462).
+char(c,81463).
+char(c,81464).
+char(c,81465).
+char(c,81466).
+char(c,81467).
+char(c,81468).
+char(c,81469).
+char(p,81470).
+char(o,81471).
+char(o,81472).
+char(p,81473).
+char(o,81474).
+char(p,81475).
+char(o,81476).
+char(o,81477).
+char(o,81478).
+char(m,81479).
+char(7,81480).
+char(2,81481).
+char(5,81482).
+char(6,81483).
+char(m,81484).
+char(6,81485).
+char(8,81486).
+char(0,81487).
+char(2,81488).
+char(m,81489).
+char(2,81490).
+char(8,81491).
+char(4,81492).
+char(8,81493).
+char(m,81494).
+char(4,81495).
+char(2,81496).
+char(0,81497).
+char(1,81498).
+char(c,81499).
+char(p,81500).
+char(o,81501).
+char(p,81502).
+char(o,81503).
+char(3,81504).
+char(2,81505).
+char(8,81506).
+char(1,81507).
+char(p,81508).
+char(7,81509).
+char(9,81510).
+char(7,81511).
+char(5,81512).
+char(m,81513).
+char(8,81514).
+char(5,81515).
+char(1,81516).
+char(7,81517).
+char(c,81518).
+char(c,81519).
+char(c,81520).
+char(m,81521).
+char(o,81522).
+char(2,81523).
+char(2,81524).
+char(4,81525).
+char(8,81526).
+char(p,81527).
+char(8,81528).
+char(5,81529).
+char(6,81530).
+char(c,81531).
+char(c,81532).
+char(c,81533).
+char(c,81534).
+char(c,81535).
+char(c,81536).
+char(c,81537).
+char(c,81538).
+char(m,81539).
+char(7,81540).
+char(4,81541).
+char(8,81542).
+char(p,81543).
+char(4,81544).
+char(9,81545).
+char(1,81546).
+char(6,81547).
+char(m,81548).
+char(1,81549).
+char(9,81550).
+char(3,81551).
+char(6,81552).
+char(c,81553).
+char(m,81554).
+char(o,81555).
+char(m,81556).
+char(7,81557).
+char(5,81558).
+char(4,81559).
+char(7,81560).
+char(c,81561).
+char(c,81562).
+char(c,81563).
+char(c,81564).
+char(m,81565).
+char(3,81566).
+char(5,81567).
+char(7,81568).
+char(5,81569).
+char(c,81570).
+char(c,81571).
+char(c,81572).
+char(c,81573).
+char(m,81574).
+char(6,81575).
+char(5,81576).
+char(6,81577).
+char(5,81578).
+char(p,81579).
+char(o,81580).
+char(p,81581).
+char(6,81582).
+char(8,81583).
+char(4,81584).
+char(p,81585).
+char(o,81586).
+char(p,81587).
+char(8,81588).
+char(2,81589).
+char(4,81590).
+char(5,81591).
+char(c,81592).
+char(p,81593).
+char(o,81594).
+char(m,81595).
+char(o,81596).
+char(m,81597).
+char(o,81598).
+char(p,81599).
+char(9,81600).
+char(2,81601).
+char(9,81602).
+char(1,81603).
+char(c,81604).
+char(m,81605).
+char(2,81606).
+char(8,81607).
+char(8,81608).
+char(2,81609).
+char(m,81610).
+char(o,81611).
+char(p,81612).
+char(2,81613).
+char(3,81614).
+char(4,81615).
+char(m,81616).
+char(1,81617).
+char(3,81618).
+char(7,81619).
+char(4,81620).
+char(c,81621).
+char(p,81622).
+char(7,81623).
+char(4,81624).
+char(9,81625).
+char(6,81626).
+char(m,81627).
+char(6,81628).
+char(2,81629).
+char(6,81630).
+char(8,81631).
+char(c,81632).
+char(c,81633).
+char(p,81634).
+char(o,81635).
+char(p,81636).
+char(o,81637).
+char(m,81638).
+char(o,81639).
+char(7,81640).
+char(4,81641).
+char(5,81642).
+char(8,81643).
+char(m,81644).
+char(o,81645).
+char(m,81646).
+char(o,81647).
+char(m,81648).
+char(o,81649).
+char(o,81650).
+char(m,81651).
+char(6,81652).
+char(3,81653).
+char(1,81654).
+char(5,81655).
+char(c,81656).
+char(c,81657).
+char(p,81658).
+char(o,81659).
+char(2,81660).
+char(3,81661).
+char(0,81662).
+char(5,81663).
+char(c,81664).
+char(m,81665).
+char(o,81666).
+char(5,81667).
+char(6,81668).
+char(4,81669).
+char(1,81670).
+char(c,81671).
+char(c,81672).
+char(p,81673).
+char(o,81674).
+char(9,81675).
+char(0,81676).
+char(1,81677).
+char(2,81678).
+char(c,81679).
+char(c,81680).
+char(p,81681).
+char(8,81682).
+char(0,81683).
+char(6,81684).
+char(4,81685).
+char(c,81686).
+char(m,81687).
+char(o,81688).
+char(p,81689).
+char(o,81690).
+char(p,81691).
+char(o,81692).
+char(o,81693).
+char(m,81694).
+char(o,81695).
+char(m,81696).
+char(o,81697).
+char(m,81698).
+char(7,81699).
+char(7,81700).
+char(6,81701).
+char(9,81702).
+char(c,81703).
+char(c,81704).
+char(p,81705).
+char(o,81706).
+char(5,81707).
+char(3,81708).
+char(0,81709).
+char(7,81710).
+char(m,81711).
+char(o,81712).
+char(m,81713).
+char(9,81714).
+char(5,81715).
+char(4,81716).
+char(4,81717).
+char(c,81718).
+char(c,81719).
+char(p,81720).
+char(o,81721).
+char(p,81722).
+char(7,81723).
+char(1,81724).
+char(0,81725).
+char(9,81726).
+char(c,81727).
+char(c,81728).
+char(c,81729).
+char(c,81730).
+char(p,81731).
+char(5,81732).
+char(0,81733).
+char(7,81734).
+char(7,81735).
+char(m,81736).
+char(o,81737).
+char(m,81738).
+char(o,81739).
+char(p,81740).
+char(5,81741).
+char(6,81742).
+char(9,81743).
+char(0,81744).
+char(c,81745).
+char(c,81746).
+char(m,81747).
+char(5,81748).
+char(3,81749).
+char(2,81750).
+char(7,81751).
+char(c,81752).
+char(p,81753).
+char(2,81754).
+char(0,81755).
+char(6,81756).
+char(m,81757).
+char(o,81758).
+char(p,81759).
+char(o,81760).
+char(p,81761).
+char(6,81762).
+char(1,81763).
+char(2,81764).
+char(4,81765).
+char(m,81766).
+char(o,81767).
+char(o,81768).
+char(m,81769).
+char(5,81770).
+char(9,81771).
+char(8,81772).
+char(3,81773).
+char(c,81774).
+char(c,81775).
+char(c,81776).
+char(c,81777).
+char(c,81778).
+char(p,81779).
+char(o,81780).
+char(m,81781).
+char(9,81782).
+char(5,81783).
+char(6,81784).
+char(5,81785).
+char(c,81786).
+char(c,81787).
+char(c,81788).
+char(p,81789).
+char(o,81790).
+char(p,81791).
+char(2,81792).
+char(1,81793).
+char(9,81794).
+char(c,81795).
+char(c,81796).
+char(c,81797).
+char(c,81798).
+char(c,81799).
+char(p,81800).
+char(o,81801).
+char(6,81802).
+char(2,81803).
+char(4,81804).
+char(m,81805).
+char(o,81806).
+char(p,81807).
+char(o,81808).
+char(o,81809).
+char(p,81810).
+char(o,81811).
+char(m,81812).
+char(o,81813).
+char(2,81814).
+char(8,81815).
+char(1,81816).
+char(7,81817).
+char(c,81818).
+char(c,81819).
+char(c,81820).
+char(c,81821).
+char(c,81822).
+char(c,81823).
+char(c,81824).
+char(c,81825).
+char(c,81826).
+char(c,81827).
+char(p,81828).
+char(o,81829).
+char(o,81830).
+char(m,81831).
+char(o,81832).
+char(m,81833).
+char(8,81834).
+char(8,81835).
+char(1,81836).
+char(7,81837).
+char(c,81838).
+char(c,81839).
+char(c,81840).
+char(c,81841).
+char(p,81842).
+char(6,81843).
+char(4,81844).
+char(7,81845).
+char(7,81846).
+char(c,81847).
+char(c,81848).
+char(m,81849).
+char(5,81850).
+char(0,81851).
+char(1,81852).
+char(3,81853).
+char(m,81854).
+char(4,81855).
+char(7,81856).
+char(6,81857).
+char(7,81858).
+char(c,81859).
+char(p,81860).
+char(6,81861).
+char(8,81862).
+char(6,81863).
+char(4,81864).
+char(c,81865).
+char(m,81866).
+char(o,81867).
+char(p,81868).
+char(7,81869).
+char(0,81870).
+char(4,81871).
+char(5,81872).
+char(p,81873).
+char(8,81874).
+char(4,81875).
+char(2,81876).
+char(8,81877).
+char(c,81878).
+char(p,81879).
+char(o,81880).
+char(m,81881).
+char(o,81882).
+char(m,81883).
+char(2,81884).
+char(3,81885).
+char(5,81886).
+char(p,81887).
+char(o,81888).
+char(o,81889).
+char(2,81890).
+char(5,81891).
+char(7,81892).
+char(9,81893).
+char(p,81894).
+char(4,81895).
+char(6,81896).
+char(0,81897).
+char(6,81898).
+char(m,81899).
+char(4,81900).
+char(8,81901).
+char(9,81902).
+char(2,81903).
+char(c,81904).
+char(c,81905).
+char(m,81906).
+char(5,81907).
+char(8,81908).
+char(8,81909).
+char(0,81910).
+char(c,81911).
+char(p,81912).
+char(9,81913).
+char(6,81914).
+char(6,81915).
+char(0,81916).
+char(m,81917).
+char(8,81918).
+char(0,81919).
+char(3,81920).
+char(3,81921).
+char(c,81922).
+char(c,81923).
+char(c,81924).
+char(m,81925).
+char(o,81926).
+char(m,81927).
+char(o,81928).
+char(o,81929).
+char(p,81930).
+char(1,81931).
+char(0,81932).
+char(3,81933).
+char(4,81934).
+char(c,81935).
+char(c,81936).
+char(c,81937).
+char(c,81938).
+char(c,81939).
+char(c,81940).
+char(c,81941).
+char(c,81942).
+char(p,81943).
+char(o,81944).
+char(p,81945).
+char(7,81946).
+char(1,81947).
+char(6,81948).
+char(7,81949).
+char(c,81950).
+char(g,81951).
+char(2,81952).
+char(9,81953).
+char(5,81954).
+char(3,81955).
+char(9,81956).
diff --git a/examples/gringo/gbie/instances/unsat_01.lp b/examples/gringo/gbie/instances/unsat_01.lp
new file mode 100644
index 0000000..6d79c98
--- /dev/null
+++ b/examples/gringo/gbie/instances/unsat_01.lp
@@ -0,0 +1,42 @@
+char(o,1).
+char(m,2).
+char(o,3).
+char(p,4).
+char(1,5).
+char(m,6).
+char(o,7).
+char(m,8).
+char(2,9).
+char(c,10).
+char(p,11).
+char(7,12).
+char(c,13).
+char(m,14).
+char(5,15).
+char(m,16).
+char(o,17).
+char(m,18).
+char(4,19).
+char(p,20).
+char(o,21).
+char(p,22).
+char(o,23).
+char(p,24).
+char(2,25).
+char(c,26).
+char(c,27).
+char(c,28).
+char(c,29).
+char(p,30).
+char(o,31).
+char(o,32).
+char(m,33).
+char(6,34).
+char(p,35).
+char(1,36).
+char(c,37).
+char(c,38).
+char(g,39).
+char(m,40).
+char(1,41).
+char(6,42).
diff --git a/examples/gringo/gbie/instances/unsat_02.lp b/examples/gringo/gbie/instances/unsat_02.lp
new file mode 100644
index 0000000..6f9755f
--- /dev/null
+++ b/examples/gringo/gbie/instances/unsat_02.lp
@@ -0,0 +1,83951 @@
+char(o,1).
+char(m,2).
+char(2,3).
+char(0,4).
+char(9,5).
+char(6,6).
+char(p,7).
+char(o,8).
+char(o,9).
+char(p,10).
+char(o,11).
+char(p,12).
+char(o,13).
+char(p,14).
+char(o,15).
+char(m,16).
+char(o,17).
+char(m,18).
+char(o,19).
+char(p,20).
+char(o,21).
+char(4,22).
+char(6,23).
+char(8,24).
+char(1,25).
+char(c,26).
+char(p,27).
+char(7,28).
+char(2,29).
+char(2,30).
+char(5,31).
+char(m,32).
+char(o,33).
+char(m,34).
+char(o,35).
+char(o,36).
+char(m,37).
+char(5,38).
+char(9,39).
+char(1,40).
+char(5,41).
+char(m,42).
+char(o,43).
+char(p,44).
+char(5,45).
+char(9,46).
+char(6,47).
+char(p,48).
+char(4,49).
+char(0,50).
+char(3,51).
+char(7,52).
+char(m,53).
+char(9,54).
+char(0,55).
+char(5,56).
+char(2,57).
+char(c,58).
+char(p,59).
+char(o,60).
+char(m,61).
+char(o,62).
+char(o,63).
+char(m,64).
+char(o,65).
+char(m,66).
+char(4,67).
+char(7,68).
+char(4,69).
+char(7,70).
+char(c,71).
+char(p,72).
+char(o,73).
+char(p,74).
+char(o,75).
+char(p,76).
+char(3,77).
+char(1,78).
+char(9,79).
+char(8,80).
+char(c,81).
+char(c,82).
+char(c,83).
+char(m,84).
+char(o,85).
+char(p,86).
+char(2,87).
+char(2,88).
+char(0,89).
+char(9,90).
+char(c,91).
+char(m,92).
+char(3,93).
+char(3,94).
+char(7,95).
+char(6,96).
+char(m,97).
+char(9,98).
+char(2,99).
+char(8,100).
+char(6,101).
+char(c,102).
+char(m,103).
+char(2,104).
+char(0,105).
+char(5,106).
+char(4,107).
+char(p,108).
+char(o,109).
+char(p,110).
+char(2,111).
+char(4,112).
+char(2,113).
+char(2,114).
+char(c,115).
+char(m,116).
+char(o,117).
+char(o,118).
+char(m,119).
+char(o,120).
+char(4,121).
+char(8,122).
+char(2,123).
+char(4,124).
+char(c,125).
+char(c,126).
+char(c,127).
+char(p,128).
+char(o,129).
+char(p,130).
+char(o,131).
+char(o,132).
+char(m,133).
+char(o,134).
+char(m,135).
+char(o,136).
+char(m,137).
+char(o,138).
+char(9,139).
+char(2,140).
+char(8,141).
+char(1,142).
+char(c,143).
+char(c,144).
+char(c,145).
+char(p,146).
+char(6,147).
+char(6,148).
+char(8,149).
+char(3,150).
+char(p,151).
+char(8,152).
+char(6,153).
+char(6,154).
+char(5,155).
+char(p,156).
+char(o,157).
+char(m,158).
+char(o,159).
+char(o,160).
+char(m,161).
+char(6,162).
+char(0,163).
+char(4,164).
+char(7,165).
+char(p,166).
+char(o,167).
+char(m,168).
+char(o,169).
+char(p,170).
+char(1,171).
+char(1,172).
+char(4,173).
+char(9,174).
+char(c,175).
+char(m,176).
+char(o,177).
+char(p,178).
+char(7,179).
+char(3,180).
+char(1,181).
+char(2,182).
+char(p,183).
+char(o,184).
+char(o,185).
+char(o,186).
+char(1,187).
+char(7,188).
+char(7,189).
+char(3,190).
+char(c,191).
+char(c,192).
+char(c,193).
+char(c,194).
+char(c,195).
+char(m,196).
+char(6,197).
+char(2,198).
+char(1,199).
+char(7,200).
+char(c,201).
+char(p,202).
+char(2,203).
+char(0,204).
+char(0,205).
+char(7,206).
+char(p,207).
+char(o,208).
+char(4,209).
+char(4,210).
+char(5,211).
+char(4,212).
+char(c,213).
+char(p,214).
+char(o,215).
+char(o,216).
+char(m,217).
+char(o,218).
+char(p,219).
+char(o,220).
+char(m,221).
+char(3,222).
+char(7,223).
+char(0,224).
+char(4,225).
+char(p,226).
+char(o,227).
+char(m,228).
+char(o,229).
+char(o,230).
+char(p,231).
+char(o,232).
+char(m,233).
+char(o,234).
+char(9,235).
+char(2,236).
+char(2,237).
+char(9,238).
+char(p,239).
+char(o,240).
+char(m,241).
+char(o,242).
+char(6,243).
+char(2,244).
+char(0,245).
+char(6,246).
+char(c,247).
+char(p,248).
+char(8,249).
+char(3,250).
+char(0,251).
+char(7,252).
+char(p,253).
+char(6,254).
+char(4,255).
+char(3,256).
+char(4,257).
+char(c,258).
+char(m,259).
+char(1,260).
+char(4,261).
+char(3,262).
+char(7,263).
+char(c,264).
+char(p,265).
+char(o,266).
+char(p,267).
+char(o,268).
+char(p,269).
+char(o,270).
+char(p,271).
+char(7,272).
+char(9,273).
+char(6,274).
+char(7,275).
+char(p,276).
+char(o,277).
+char(m,278).
+char(7,279).
+char(3,280).
+char(9,281).
+char(3,282).
+char(c,283).
+char(c,284).
+char(m,285).
+char(o,286).
+char(o,287).
+char(8,288).
+char(8,289).
+char(8,290).
+char(8,291).
+char(c,292).
+char(p,293).
+char(8,294).
+char(8,295).
+char(8,296).
+char(3,297).
+char(c,298).
+char(c,299).
+char(m,300).
+char(9,301).
+char(2,302).
+char(2,303).
+char(c,304).
+char(c,305).
+char(p,306).
+char(1,307).
+char(5,308).
+char(0,309).
+char(0,310).
+char(m,311).
+char(2,312).
+char(0,313).
+char(8,314).
+char(9,315).
+char(c,316).
+char(c,317).
+char(c,318).
+char(m,319).
+char(o,320).
+char(m,321).
+char(2,322).
+char(1,323).
+char(8,324).
+char(5,325).
+char(c,326).
+char(c,327).
+char(c,328).
+char(c,329).
+char(m,330).
+char(7,331).
+char(9,332).
+char(6,333).
+char(8,334).
+char(m,335).
+char(2,336).
+char(8,337).
+char(3,338).
+char(6,339).
+char(c,340).
+char(c,341).
+char(m,342).
+char(2,343).
+char(7,344).
+char(2,345).
+char(3,346).
+char(c,347).
+char(p,348).
+char(2,349).
+char(6,350).
+char(6,351).
+char(7,352).
+char(c,353).
+char(m,354).
+char(o,355).
+char(9,356).
+char(0,357).
+char(0,358).
+char(p,359).
+char(o,360).
+char(m,361).
+char(4,362).
+char(5,363).
+char(8,364).
+char(4,365).
+char(c,366).
+char(p,367).
+char(4,368).
+char(2,369).
+char(4,370).
+char(5,371).
+char(c,372).
+char(c,373).
+char(c,374).
+char(p,375).
+char(6,376).
+char(4,377).
+char(9,378).
+char(3,379).
+char(c,380).
+char(c,381).
+char(p,382).
+char(4,383).
+char(8,384).
+char(6,385).
+char(p,386).
+char(o,387).
+char(p,388).
+char(7,389).
+char(8,390).
+char(p,391).
+char(6,392).
+char(5,393).
+char(0,394).
+char(7,395).
+char(c,396).
+char(p,397).
+char(5,398).
+char(4,399).
+char(2,400).
+char(6,401).
+char(m,402).
+char(o,403).
+char(8,404).
+char(6,405).
+char(9,406).
+char(1,407).
+char(p,408).
+char(8,409).
+char(4,410).
+char(1,411).
+char(6,412).
+char(p,413).
+char(o,414).
+char(p,415).
+char(1,416).
+char(5,417).
+char(7,418).
+char(4,419).
+char(m,420).
+char(3,421).
+char(0,422).
+char(8,423).
+char(4,424).
+char(p,425).
+char(o,426).
+char(m,427).
+char(o,428).
+char(m,429).
+char(o,430).
+char(m,431).
+char(1,432).
+char(8,433).
+char(9,434).
+char(5,435).
+char(c,436).
+char(m,437).
+char(8,438).
+char(4,439).
+char(5,440).
+char(1,441).
+char(p,442).
+char(6,443).
+char(1,444).
+char(3,445).
+char(4,446).
+char(p,447).
+char(4,448).
+char(0,449).
+char(3,450).
+char(1,451).
+char(c,452).
+char(m,453).
+char(4,454).
+char(3,455).
+char(1,456).
+char(2,457).
+char(c,458).
+char(m,459).
+char(2,460).
+char(0,461).
+char(7,462).
+char(0,463).
+char(m,464).
+char(o,465).
+char(o,466).
+char(m,467).
+char(7,468).
+char(7,469).
+char(1,470).
+char(9,471).
+char(c,472).
+char(c,473).
+char(c,474).
+char(c,475).
+char(c,476).
+char(m,477).
+char(7,478).
+char(8,479).
+char(1,480).
+char(4,481).
+char(m,482).
+char(o,483).
+char(m,484).
+char(o,485).
+char(p,486).
+char(o,487).
+char(m,488).
+char(o,489).
+char(m,490).
+char(o,491).
+char(p,492).
+char(8,493).
+char(3,494).
+char(7,495).
+char(2,496).
+char(m,497).
+char(3,498).
+char(4,499).
+char(5,500).
+char(7,501).
+char(c,502).
+char(c,503).
+char(m,504).
+char(o,505).
+char(m,506).
+char(o,507).
+char(m,508).
+char(o,509).
+char(m,510).
+char(o,511).
+char(p,512).
+char(o,513).
+char(p,514).
+char(o,515).
+char(2,516).
+char(7,517).
+char(7,518).
+char(2,519).
+char(c,520).
+char(c,521).
+char(p,522).
+char(3,523).
+char(8,524).
+char(8,525).
+char(7,526).
+char(p,527).
+char(9,528).
+char(2,529).
+char(4,530).
+char(5,531).
+char(c,532).
+char(p,533).
+char(o,534).
+char(p,535).
+char(5,536).
+char(0,537).
+char(5,538).
+char(9,539).
+char(m,540).
+char(o,541).
+char(o,542).
+char(m,543).
+char(o,544).
+char(6,545).
+char(3,546).
+char(3,547).
+char(1,548).
+char(m,549).
+char(o,550).
+char(p,551).
+char(6,552).
+char(5,553).
+char(6,554).
+char(6,555).
+char(m,556).
+char(o,557).
+char(3,558).
+char(5,559).
+char(6,560).
+char(7,561).
+char(m,562).
+char(2,563).
+char(4,564).
+char(1,565).
+char(c,566).
+char(c,567).
+char(c,568).
+char(p,569).
+char(4,570).
+char(5,571).
+char(3,572).
+char(6,573).
+char(p,574).
+char(o,575).
+char(p,576).
+char(7,577).
+char(8,578).
+char(6,579).
+char(9,580).
+char(p,581).
+char(o,582).
+char(p,583).
+char(o,584).
+char(m,585).
+char(o,586).
+char(p,587).
+char(5,588).
+char(4,589).
+char(7,590).
+char(8,591).
+char(p,592).
+char(o,593).
+char(p,594).
+char(o,595).
+char(o,596).
+char(4,597).
+char(1,598).
+char(2,599).
+char(4,600).
+char(c,601).
+char(p,602).
+char(3,603).
+char(0,604).
+char(3,605).
+char(1,606).
+char(c,607).
+char(c,608).
+char(m,609).
+char(o,610).
+char(p,611).
+char(o,612).
+char(m,613).
+char(o,614).
+char(8,615).
+char(9,616).
+char(4,617).
+char(c,618).
+char(c,619).
+char(m,620).
+char(4,621).
+char(4,622).
+char(0,623).
+char(9,624).
+char(c,625).
+char(c,626).
+char(p,627).
+char(4,628).
+char(1,629).
+char(4,630).
+char(0,631).
+char(c,632).
+char(p,633).
+char(4,634).
+char(3,635).
+char(5,636).
+char(2,637).
+char(p,638).
+char(2,639).
+char(5,640).
+char(9,641).
+char(0,642).
+char(m,643).
+char(7,644).
+char(4,645).
+char(0,646).
+char(0,647).
+char(m,648).
+char(o,649).
+char(m,650).
+char(o,651).
+char(o,652).
+char(3,653).
+char(4,654).
+char(2,655).
+char(2,656).
+char(m,657).
+char(3,658).
+char(3,659).
+char(9,660).
+char(9,661).
+char(c,662).
+char(c,663).
+char(c,664).
+char(c,665).
+char(c,666).
+char(p,667).
+char(o,668).
+char(p,669).
+char(4,670).
+char(9,671).
+char(3,672).
+char(2,673).
+char(m,674).
+char(5,675).
+char(5,676).
+char(4,677).
+char(5,678).
+char(c,679).
+char(m,680).
+char(1,681).
+char(3,682).
+char(6,683).
+char(8,684).
+char(c,685).
+char(p,686).
+char(o,687).
+char(o,688).
+char(m,689).
+char(8,690).
+char(2,691).
+char(2,692).
+char(0,693).
+char(p,694).
+char(o,695).
+char(o,696).
+char(m,697).
+char(2,698).
+char(6,699).
+char(1,700).
+char(8,701).
+char(m,702).
+char(9,703).
+char(0,704).
+char(9,705).
+char(2,706).
+char(p,707).
+char(1,708).
+char(0,709).
+char(8,710).
+char(1,711).
+char(p,712).
+char(o,713).
+char(7,714).
+char(0,715).
+char(5,716).
+char(9,717).
+char(c,718).
+char(m,719).
+char(o,720).
+char(m,721).
+char(2,722).
+char(4,723).
+char(2,724).
+char(6,725).
+char(m,726).
+char(o,727).
+char(p,728).
+char(3,729).
+char(3,730).
+char(7,731).
+char(2,732).
+char(c,733).
+char(c,734).
+char(c,735).
+char(m,736).
+char(o,737).
+char(m,738).
+char(o,739).
+char(m,740).
+char(7,741).
+char(5,742).
+char(0,743).
+char(7,744).
+char(c,745).
+char(c,746).
+char(c,747).
+char(c,748).
+char(p,749).
+char(o,750).
+char(o,751).
+char(o,752).
+char(p,753).
+char(9,754).
+char(8,755).
+char(6,756).
+char(0,757).
+char(m,758).
+char(6,759).
+char(1,760).
+char(7,761).
+char(1,762).
+char(c,763).
+char(c,764).
+char(c,765).
+char(p,766).
+char(o,767).
+char(m,768).
+char(o,769).
+char(o,770).
+char(m,771).
+char(1,772).
+char(1,773).
+char(0,774).
+char(0,775).
+char(m,776).
+char(o,777).
+char(m,778).
+char(5,779).
+char(6,780).
+char(3,781).
+char(7,782).
+char(p,783).
+char(o,784).
+char(p,785).
+char(o,786).
+char(7,787).
+char(8,788).
+char(9,789).
+char(2,790).
+char(c,791).
+char(c,792).
+char(c,793).
+char(c,794).
+char(c,795).
+char(m,796).
+char(o,797).
+char(p,798).
+char(1,799).
+char(8,800).
+char(9,801).
+char(c,802).
+char(m,803).
+char(4,804).
+char(7,805).
+char(6,806).
+char(8,807).
+char(m,808).
+char(1,809).
+char(9,810).
+char(4,811).
+char(0,812).
+char(c,813).
+char(c,814).
+char(c,815).
+char(c,816).
+char(m,817).
+char(o,818).
+char(m,819).
+char(o,820).
+char(p,821).
+char(o,822).
+char(p,823).
+char(o,824).
+char(m,825).
+char(o,826).
+char(m,827).
+char(5,828).
+char(5,829).
+char(7,830).
+char(p,831).
+char(o,832).
+char(m,833).
+char(o,834).
+char(m,835).
+char(o,836).
+char(o,837).
+char(m,838).
+char(7,839).
+char(2,840).
+char(8,841).
+char(7,842).
+char(p,843).
+char(o,844).
+char(m,845).
+char(9,846).
+char(5,847).
+char(1,848).
+char(9,849).
+char(c,850).
+char(p,851).
+char(o,852).
+char(5,853).
+char(8,854).
+char(3,855).
+char(c,856).
+char(p,857).
+char(8,858).
+char(7,859).
+char(0,860).
+char(7,861).
+char(c,862).
+char(p,863).
+char(o,864).
+char(m,865).
+char(o,866).
+char(m,867).
+char(o,868).
+char(p,869).
+char(7,870).
+char(6,871).
+char(8,872).
+char(5,873).
+char(c,874).
+char(p,875).
+char(8,876).
+char(3,877).
+char(2,878).
+char(8,879).
+char(m,880).
+char(o,881).
+char(o,882).
+char(m,883).
+char(o,884).
+char(7,885).
+char(5,886).
+char(1,887).
+char(c,888).
+char(m,889).
+char(2,890).
+char(5,891).
+char(6,892).
+char(0,893).
+char(c,894).
+char(m,895).
+char(o,896).
+char(p,897).
+char(9,898).
+char(6,899).
+char(7,900).
+char(4,901).
+char(c,902).
+char(c,903).
+char(c,904).
+char(m,905).
+char(2,906).
+char(7,907).
+char(7,908).
+char(7,909).
+char(p,910).
+char(o,911).
+char(o,912).
+char(o,913).
+char(p,914).
+char(o,915).
+char(5,916).
+char(0,917).
+char(4,918).
+char(m,919).
+char(o,920).
+char(p,921).
+char(o,922).
+char(p,923).
+char(9,924).
+char(1,925).
+char(1,926).
+char(9,927).
+char(c,928).
+char(m,929).
+char(1,930).
+char(8,931).
+char(1,932).
+char(5,933).
+char(c,934).
+char(c,935).
+char(p,936).
+char(9,937).
+char(8,938).
+char(7,939).
+char(3,940).
+char(c,941).
+char(m,942).
+char(6,943).
+char(9,944).
+char(1,945).
+char(7,946).
+char(p,947).
+char(4,948).
+char(3,949).
+char(5,950).
+char(5,951).
+char(c,952).
+char(c,953).
+char(c,954).
+char(p,955).
+char(o,956).
+char(p,957).
+char(4,958).
+char(0,959).
+char(6,960).
+char(5,961).
+char(c,962).
+char(m,963).
+char(8,964).
+char(3,965).
+char(3,966).
+char(8,967).
+char(p,968).
+char(o,969).
+char(p,970).
+char(o,971).
+char(p,972).
+char(4,973).
+char(6,974).
+char(3,975).
+char(5,976).
+char(p,977).
+char(7,978).
+char(1,979).
+char(7,980).
+char(1,981).
+char(c,982).
+char(p,983).
+char(6,984).
+char(7,985).
+char(5,986).
+char(5,987).
+char(m,988).
+char(3,989).
+char(3,990).
+char(6,991).
+char(1,992).
+char(m,993).
+char(o,994).
+char(p,995).
+char(1,996).
+char(7,997).
+char(3,998).
+char(2,999).
+char(c,1000).
+char(m,1001).
+char(o,1002).
+char(o,1003).
+char(o,1004).
+char(1,1005).
+char(0,1006).
+char(5,1007).
+char(6,1008).
+char(p,1009).
+char(8,1010).
+char(9,1011).
+char(3,1012).
+char(c,1013).
+char(p,1014).
+char(9,1015).
+char(5,1016).
+char(6,1017).
+char(0,1018).
+char(c,1019).
+char(m,1020).
+char(o,1021).
+char(o,1022).
+char(o,1023).
+char(p,1024).
+char(6,1025).
+char(4,1026).
+char(7,1027).
+char(8,1028).
+char(p,1029).
+char(o,1030).
+char(p,1031).
+char(o,1032).
+char(m,1033).
+char(o,1034).
+char(p,1035).
+char(8,1036).
+char(2,1037).
+char(1,1038).
+char(1,1039).
+char(p,1040).
+char(o,1041).
+char(m,1042).
+char(8,1043).
+char(0,1044).
+char(3,1045).
+char(8,1046).
+char(c,1047).
+char(c,1048).
+char(m,1049).
+char(o,1050).
+char(p,1051).
+char(o,1052).
+char(p,1053).
+char(o,1054).
+char(m,1055).
+char(6,1056).
+char(7,1057).
+char(6,1058).
+char(4,1059).
+char(c,1060).
+char(c,1061).
+char(p,1062).
+char(o,1063).
+char(m,1064).
+char(o,1065).
+char(m,1066).
+char(o,1067).
+char(p,1068).
+char(1,1069).
+char(5,1070).
+char(8,1071).
+char(1,1072).
+char(c,1073).
+char(c,1074).
+char(m,1075).
+char(o,1076).
+char(m,1077).
+char(4,1078).
+char(5,1079).
+char(1,1080).
+char(9,1081).
+char(c,1082).
+char(c,1083).
+char(p,1084).
+char(9,1085).
+char(4,1086).
+char(c,1087).
+char(m,1088).
+char(o,1089).
+char(m,1090).
+char(4,1091).
+char(8,1092).
+char(1,1093).
+char(6,1094).
+char(p,1095).
+char(o,1096).
+char(o,1097).
+char(p,1098).
+char(o,1099).
+char(p,1100).
+char(o,1101).
+char(p,1102).
+char(o,1103).
+char(p,1104).
+char(2,1105).
+char(8,1106).
+char(8,1107).
+char(2,1108).
+char(m,1109).
+char(o,1110).
+char(m,1111).
+char(o,1112).
+char(m,1113).
+char(o,1114).
+char(m,1115).
+char(o,1116).
+char(o,1117).
+char(m,1118).
+char(o,1119).
+char(m,1120).
+char(o,1121).
+char(9,1122).
+char(1,1123).
+char(5,1124).
+char(6,1125).
+char(c,1126).
+char(c,1127).
+char(c,1128).
+char(m,1129).
+char(1,1130).
+char(8,1131).
+char(7,1132).
+char(6,1133).
+char(c,1134).
+char(m,1135).
+char(8,1136).
+char(4,1137).
+char(3,1138).
+char(7,1139).
+char(c,1140).
+char(c,1141).
+char(c,1142).
+char(c,1143).
+char(c,1144).
+char(m,1145).
+char(o,1146).
+char(p,1147).
+char(6,1148).
+char(8,1149).
+char(8,1150).
+char(4,1151).
+char(m,1152).
+char(9,1153).
+char(2,1154).
+char(1,1155).
+char(0,1156).
+char(c,1157).
+char(m,1158).
+char(o,1159).
+char(p,1160).
+char(o,1161).
+char(2,1162).
+char(5,1163).
+char(6,1164).
+char(3,1165).
+char(c,1166).
+char(p,1167).
+char(o,1168).
+char(p,1169).
+char(2,1170).
+char(6,1171).
+char(2,1172).
+char(p,1173).
+char(7,1174).
+char(1,1175).
+char(6,1176).
+char(8,1177).
+char(p,1178).
+char(7,1179).
+char(9,1180).
+char(7,1181).
+char(1,1182).
+char(c,1183).
+char(c,1184).
+char(m,1185).
+char(o,1186).
+char(p,1187).
+char(3,1188).
+char(1,1189).
+char(8,1190).
+char(2,1191).
+char(m,1192).
+char(o,1193).
+char(m,1194).
+char(2,1195).
+char(1,1196).
+char(9,1197).
+char(0,1198).
+char(p,1199).
+char(o,1200).
+char(o,1201).
+char(p,1202).
+char(o,1203).
+char(o,1204).
+char(o,1205).
+char(m,1206).
+char(o,1207).
+char(m,1208).
+char(7,1209).
+char(8,1210).
+char(2,1211).
+char(1,1212).
+char(p,1213).
+char(9,1214).
+char(6,1215).
+char(2,1216).
+char(0,1217).
+char(c,1218).
+char(c,1219).
+char(m,1220).
+char(o,1221).
+char(p,1222).
+char(o,1223).
+char(m,1224).
+char(o,1225).
+char(m,1226).
+char(o,1227).
+char(p,1228).
+char(o,1229).
+char(m,1230).
+char(o,1231).
+char(p,1232).
+char(2,1233).
+char(5,1234).
+char(2,1235).
+char(4,1236).
+char(p,1237).
+char(5,1238).
+char(8,1239).
+char(7,1240).
+char(1,1241).
+char(p,1242).
+char(o,1243).
+char(o,1244).
+char(m,1245).
+char(o,1246).
+char(p,1247).
+char(7,1248).
+char(6,1249).
+char(1,1250).
+char(6,1251).
+char(p,1252).
+char(o,1253).
+char(p,1254).
+char(o,1255).
+char(p,1256).
+char(5,1257).
+char(4,1258).
+char(5,1259).
+char(5,1260).
+char(c,1261).
+char(p,1262).
+char(2,1263).
+char(6,1264).
+char(6,1265).
+char(0,1266).
+char(c,1267).
+char(c,1268).
+char(c,1269).
+char(c,1270).
+char(c,1271).
+char(c,1272).
+char(m,1273).
+char(4,1274).
+char(5,1275).
+char(6,1276).
+char(8,1277).
+char(p,1278).
+char(o,1279).
+char(p,1280).
+char(o,1281).
+char(m,1282).
+char(3,1283).
+char(4,1284).
+char(4,1285).
+char(7,1286).
+char(p,1287).
+char(o,1288).
+char(m,1289).
+char(4,1290).
+char(6,1291).
+char(5,1292).
+char(9,1293).
+char(m,1294).
+char(o,1295).
+char(1,1296).
+char(6,1297).
+char(1,1298).
+char(8,1299).
+char(p,1300).
+char(5,1301).
+char(3,1302).
+char(3,1303).
+char(3,1304).
+char(m,1305).
+char(7,1306).
+char(2,1307).
+char(4,1308).
+char(2,1309).
+char(c,1310).
+char(p,1311).
+char(o,1312).
+char(m,1313).
+char(o,1314).
+char(o,1315).
+char(m,1316).
+char(3,1317).
+char(0,1318).
+char(8,1319).
+char(8,1320).
+char(p,1321).
+char(9,1322).
+char(0,1323).
+char(2,1324).
+char(m,1325).
+char(o,1326).
+char(p,1327).
+char(o,1328).
+char(p,1329).
+char(9,1330).
+char(2,1331).
+char(6,1332).
+char(7,1333).
+char(c,1334).
+char(m,1335).
+char(o,1336).
+char(p,1337).
+char(o,1338).
+char(7,1339).
+char(1,1340).
+char(2,1341).
+char(8,1342).
+char(p,1343).
+char(o,1344).
+char(p,1345).
+char(8,1346).
+char(2,1347).
+char(9,1348).
+char(6,1349).
+char(m,1350).
+char(2,1351).
+char(6,1352).
+char(6,1353).
+char(4,1354).
+char(c,1355).
+char(c,1356).
+char(p,1357).
+char(o,1358).
+char(m,1359).
+char(o,1360).
+char(m,1361).
+char(5,1362).
+char(5,1363).
+char(4,1364).
+char(1,1365).
+char(p,1366).
+char(o,1367).
+char(5,1368).
+char(3,1369).
+char(6,1370).
+char(6,1371).
+char(c,1372).
+char(p,1373).
+char(6,1374).
+char(3,1375).
+char(9,1376).
+char(8,1377).
+char(p,1378).
+char(o,1379).
+char(p,1380).
+char(o,1381).
+char(o,1382).
+char(5,1383).
+char(9,1384).
+char(0,1385).
+char(6,1386).
+char(m,1387).
+char(6,1388).
+char(0,1389).
+char(2,1390).
+char(5,1391).
+char(m,1392).
+char(4,1393).
+char(2,1394).
+char(9,1395).
+char(9,1396).
+char(m,1397).
+char(o,1398).
+char(p,1399).
+char(o,1400).
+char(m,1401).
+char(o,1402).
+char(o,1403).
+char(6,1404).
+char(3,1405).
+char(8,1406).
+char(0,1407).
+char(p,1408).
+char(o,1409).
+char(o,1410).
+char(m,1411).
+char(4,1412).
+char(4,1413).
+char(3,1414).
+char(1,1415).
+char(c,1416).
+char(p,1417).
+char(7,1418).
+char(9,1419).
+char(4,1420).
+char(2,1421).
+char(c,1422).
+char(p,1423).
+char(4,1424).
+char(9,1425).
+char(5,1426).
+char(7,1427).
+char(c,1428).
+char(c,1429).
+char(p,1430).
+char(4,1431).
+char(2,1432).
+char(0,1433).
+char(2,1434).
+char(m,1435).
+char(o,1436).
+char(p,1437).
+char(o,1438).
+char(m,1439).
+char(o,1440).
+char(p,1441).
+char(o,1442).
+char(p,1443).
+char(1,1444).
+char(3,1445).
+char(0,1446).
+char(5,1447).
+char(c,1448).
+char(m,1449).
+char(o,1450).
+char(7,1451).
+char(8,1452).
+char(9,1453).
+char(1,1454).
+char(p,1455).
+char(o,1456).
+char(p,1457).
+char(3,1458).
+char(4,1459).
+char(c,1460).
+char(c,1461).
+char(c,1462).
+char(c,1463).
+char(c,1464).
+char(m,1465).
+char(o,1466).
+char(m,1467).
+char(6,1468).
+char(2,1469).
+char(6,1470).
+char(9,1471).
+char(c,1472).
+char(c,1473).
+char(m,1474).
+char(8,1475).
+char(8,1476).
+char(2,1477).
+char(5,1478).
+char(m,1479).
+char(5,1480).
+char(0,1481).
+char(9,1482).
+char(2,1483).
+char(c,1484).
+char(c,1485).
+char(c,1486).
+char(p,1487).
+char(o,1488).
+char(m,1489).
+char(o,1490).
+char(p,1491).
+char(2,1492).
+char(6,1493).
+char(2,1494).
+char(8,1495).
+char(c,1496).
+char(m,1497).
+char(7,1498).
+char(5,1499).
+char(2,1500).
+char(2,1501).
+char(c,1502).
+char(c,1503).
+char(c,1504).
+char(c,1505).
+char(c,1506).
+char(c,1507).
+char(p,1508).
+char(o,1509).
+char(o,1510).
+char(o,1511).
+char(m,1512).
+char(o,1513).
+char(m,1514).
+char(2,1515).
+char(8,1516).
+char(6,1517).
+char(c,1518).
+char(m,1519).
+char(2,1520).
+char(0,1521).
+char(3,1522).
+char(1,1523).
+char(p,1524).
+char(o,1525).
+char(p,1526).
+char(6,1527).
+char(6,1528).
+char(1,1529).
+char(2,1530).
+char(c,1531).
+char(c,1532).
+char(c,1533).
+char(c,1534).
+char(m,1535).
+char(6,1536).
+char(4,1537).
+char(0,1538).
+char(0,1539).
+char(m,1540).
+char(o,1541).
+char(3,1542).
+char(5,1543).
+char(8,1544).
+char(c,1545).
+char(c,1546).
+char(c,1547).
+char(c,1548).
+char(c,1549).
+char(c,1550).
+char(p,1551).
+char(o,1552).
+char(m,1553).
+char(7,1554).
+char(2,1555).
+char(8,1556).
+char(6,1557).
+char(m,1558).
+char(o,1559).
+char(o,1560).
+char(p,1561).
+char(o,1562).
+char(m,1563).
+char(3,1564).
+char(2,1565).
+char(1,1566).
+char(8,1567).
+char(m,1568).
+char(o,1569).
+char(m,1570).
+char(o,1571).
+char(o,1572).
+char(p,1573).
+char(o,1574).
+char(p,1575).
+char(1,1576).
+char(2,1577).
+char(7,1578).
+char(2,1579).
+char(p,1580).
+char(1,1581).
+char(4,1582).
+char(3,1583).
+char(9,1584).
+char(c,1585).
+char(m,1586).
+char(o,1587).
+char(p,1588).
+char(o,1589).
+char(p,1590).
+char(7,1591).
+char(7,1592).
+char(2,1593).
+char(4,1594).
+char(c,1595).
+char(c,1596).
+char(c,1597).
+char(m,1598).
+char(o,1599).
+char(1,1600).
+char(8,1601).
+char(1,1602).
+char(8,1603).
+char(p,1604).
+char(3,1605).
+char(7,1606).
+char(8,1607).
+char(8,1608).
+char(c,1609).
+char(c,1610).
+char(c,1611).
+char(p,1612).
+char(8,1613).
+char(1,1614).
+char(3,1615).
+char(3,1616).
+char(c,1617).
+char(p,1618).
+char(o,1619).
+char(o,1620).
+char(p,1621).
+char(o,1622).
+char(m,1623).
+char(o,1624).
+char(p,1625).
+char(o,1626).
+char(p,1627).
+char(o,1628).
+char(p,1629).
+char(5,1630).
+char(3,1631).
+char(0,1632).
+char(3,1633).
+char(c,1634).
+char(c,1635).
+char(m,1636).
+char(1,1637).
+char(9,1638).
+char(2,1639).
+char(9,1640).
+char(m,1641).
+char(o,1642).
+char(o,1643).
+char(2,1644).
+char(4,1645).
+char(6,1646).
+char(0,1647).
+char(m,1648).
+char(o,1649).
+char(m,1650).
+char(4,1651).
+char(9,1652).
+char(3,1653).
+char(0,1654).
+char(m,1655).
+char(o,1656).
+char(m,1657).
+char(o,1658).
+char(m,1659).
+char(o,1660).
+char(1,1661).
+char(0,1662).
+char(5,1663).
+char(2,1664).
+char(p,1665).
+char(2,1666).
+char(0,1667).
+char(5,1668).
+char(8,1669).
+char(m,1670).
+char(o,1671).
+char(m,1672).
+char(7,1673).
+char(0,1674).
+char(9,1675).
+char(8,1676).
+char(m,1677).
+char(o,1678).
+char(m,1679).
+char(2,1680).
+char(9,1681).
+char(4,1682).
+char(8,1683).
+char(c,1684).
+char(m,1685).
+char(2,1686).
+char(8,1687).
+char(2,1688).
+char(6,1689).
+char(c,1690).
+char(m,1691).
+char(5,1692).
+char(1,1693).
+char(0,1694).
+char(3,1695).
+char(c,1696).
+char(c,1697).
+char(m,1698).
+char(o,1699).
+char(9,1700).
+char(9,1701).
+char(1,1702).
+char(0,1703).
+char(m,1704).
+char(5,1705).
+char(9,1706).
+char(8,1707).
+char(4,1708).
+char(c,1709).
+char(p,1710).
+char(o,1711).
+char(4,1712).
+char(3,1713).
+char(8,1714).
+char(2,1715).
+char(c,1716).
+char(p,1717).
+char(o,1718).
+char(p,1719).
+char(8,1720).
+char(2,1721).
+char(5,1722).
+char(5,1723).
+char(c,1724).
+char(p,1725).
+char(2,1726).
+char(6,1727).
+char(5,1728).
+char(5,1729).
+char(m,1730).
+char(1,1731).
+char(8,1732).
+char(9,1733).
+char(7,1734).
+char(p,1735).
+char(3,1736).
+char(3,1737).
+char(0,1738).
+char(4,1739).
+char(p,1740).
+char(o,1741).
+char(p,1742).
+char(9,1743).
+char(7,1744).
+char(0,1745).
+char(3,1746).
+char(c,1747).
+char(c,1748).
+char(m,1749).
+char(8,1750).
+char(0,1751).
+char(0,1752).
+char(3,1753).
+char(c,1754).
+char(p,1755).
+char(7,1756).
+char(3,1757).
+char(5,1758).
+char(0,1759).
+char(m,1760).
+char(3,1761).
+char(1,1762).
+char(6,1763).
+char(1,1764).
+char(c,1765).
+char(p,1766).
+char(4,1767).
+char(3,1768).
+char(0,1769).
+char(0,1770).
+char(m,1771).
+char(9,1772).
+char(6,1773).
+char(8,1774).
+char(0,1775).
+char(c,1776).
+char(c,1777).
+char(p,1778).
+char(2,1779).
+char(4,1780).
+char(7,1781).
+char(6,1782).
+char(c,1783).
+char(c,1784).
+char(c,1785).
+char(m,1786).
+char(o,1787).
+char(p,1788).
+char(9,1789).
+char(8,1790).
+char(5,1791).
+char(9,1792).
+char(c,1793).
+char(c,1794).
+char(p,1795).
+char(o,1796).
+char(p,1797).
+char(o,1798).
+char(p,1799).
+char(o,1800).
+char(m,1801).
+char(2,1802).
+char(0,1803).
+char(7,1804).
+char(1,1805).
+char(c,1806).
+char(c,1807).
+char(c,1808).
+char(c,1809).
+char(p,1810).
+char(9,1811).
+char(2,1812).
+char(3,1813).
+char(3,1814).
+char(c,1815).
+char(c,1816).
+char(c,1817).
+char(c,1818).
+char(c,1819).
+char(m,1820).
+char(o,1821).
+char(m,1822).
+char(o,1823).
+char(m,1824).
+char(3,1825).
+char(9,1826).
+char(3,1827).
+char(c,1828).
+char(m,1829).
+char(o,1830).
+char(o,1831).
+char(p,1832).
+char(o,1833).
+char(o,1834).
+char(3,1835).
+char(8,1836).
+char(3,1837).
+char(0,1838).
+char(p,1839).
+char(7,1840).
+char(2,1841).
+char(3,1842).
+char(7,1843).
+char(c,1844).
+char(p,1845).
+char(o,1846).
+char(8,1847).
+char(5,1848).
+char(2,1849).
+char(3,1850).
+char(p,1851).
+char(o,1852).
+char(2,1853).
+char(9,1854).
+char(1,1855).
+char(0,1856).
+char(m,1857).
+char(o,1858).
+char(p,1859).
+char(1,1860).
+char(9,1861).
+char(7,1862).
+char(3,1863).
+char(m,1864).
+char(o,1865).
+char(4,1866).
+char(7,1867).
+char(5,1868).
+char(9,1869).
+char(c,1870).
+char(p,1871).
+char(o,1872).
+char(m,1873).
+char(6,1874).
+char(1,1875).
+char(c,1876).
+char(c,1877).
+char(p,1878).
+char(6,1879).
+char(4,1880).
+char(0,1881).
+char(1,1882).
+char(c,1883).
+char(c,1884).
+char(m,1885).
+char(o,1886).
+char(m,1887).
+char(5,1888).
+char(8,1889).
+char(7,1890).
+char(9,1891).
+char(c,1892).
+char(m,1893).
+char(4,1894).
+char(6,1895).
+char(9,1896).
+char(7,1897).
+char(c,1898).
+char(c,1899).
+char(c,1900).
+char(c,1901).
+char(p,1902).
+char(o,1903).
+char(m,1904).
+char(o,1905).
+char(p,1906).
+char(o,1907).
+char(o,1908).
+char(p,1909).
+char(5,1910).
+char(5,1911).
+char(9,1912).
+char(2,1913).
+char(c,1914).
+char(p,1915).
+char(o,1916).
+char(o,1917).
+char(m,1918).
+char(9,1919).
+char(3,1920).
+char(8,1921).
+char(4,1922).
+char(c,1923).
+char(m,1924).
+char(o,1925).
+char(5,1926).
+char(6,1927).
+char(3,1928).
+char(9,1929).
+char(p,1930).
+char(8,1931).
+char(1,1932).
+char(0,1933).
+char(9,1934).
+char(p,1935).
+char(7,1936).
+char(3,1937).
+char(3,1938).
+char(4,1939).
+char(m,1940).
+char(o,1941).
+char(p,1942).
+char(1,1943).
+char(6,1944).
+char(9,1945).
+char(3,1946).
+char(p,1947).
+char(o,1948).
+char(p,1949).
+char(8,1950).
+char(6,1951).
+char(1,1952).
+char(8,1953).
+char(p,1954).
+char(o,1955).
+char(p,1956).
+char(o,1957).
+char(p,1958).
+char(o,1959).
+char(5,1960).
+char(8,1961).
+char(4,1962).
+char(9,1963).
+char(m,1964).
+char(7,1965).
+char(3,1966).
+char(2,1967).
+char(1,1968).
+char(p,1969).
+char(4,1970).
+char(4,1971).
+char(1,1972).
+char(9,1973).
+char(p,1974).
+char(2,1975).
+char(6,1976).
+char(3,1977).
+char(6,1978).
+char(p,1979).
+char(4,1980).
+char(1,1981).
+char(4,1982).
+char(3,1983).
+char(c,1984).
+char(m,1985).
+char(1,1986).
+char(0,1987).
+char(8,1988).
+char(4,1989).
+char(c,1990).
+char(m,1991).
+char(o,1992).
+char(p,1993).
+char(o,1994).
+char(o,1995).
+char(p,1996).
+char(4,1997).
+char(1,1998).
+char(3,1999).
+char(4,2000).
+char(m,2001).
+char(o,2002).
+char(m,2003).
+char(o,2004).
+char(5,2005).
+char(4,2006).
+char(4,2007).
+char(2,2008).
+char(c,2009).
+char(m,2010).
+char(o,2011).
+char(m,2012).
+char(o,2013).
+char(o,2014).
+char(m,2015).
+char(o,2016).
+char(p,2017).
+char(1,2018).
+char(4,2019).
+char(9,2020).
+char(2,2021).
+char(p,2022).
+char(4,2023).
+char(5,2024).
+char(1,2025).
+char(6,2026).
+char(p,2027).
+char(o,2028).
+char(m,2029).
+char(9,2030).
+char(4,2031).
+char(9,2032).
+char(8,2033).
+char(c,2034).
+char(c,2035).
+char(m,2036).
+char(6,2037).
+char(9,2038).
+char(9,2039).
+char(8,2040).
+char(p,2041).
+char(o,2042).
+char(9,2043).
+char(4,2044).
+char(8,2045).
+char(0,2046).
+char(c,2047).
+char(c,2048).
+char(c,2049).
+char(c,2050).
+char(m,2051).
+char(9,2052).
+char(5,2053).
+char(2,2054).
+char(2,2055).
+char(p,2056).
+char(o,2057).
+char(m,2058).
+char(1,2059).
+char(7,2060).
+char(3,2061).
+char(4,2062).
+char(c,2063).
+char(c,2064).
+char(p,2065).
+char(2,2066).
+char(7,2067).
+char(5,2068).
+char(6,2069).
+char(c,2070).
+char(c,2071).
+char(c,2072).
+char(c,2073).
+char(c,2074).
+char(m,2075).
+char(2,2076).
+char(0,2077).
+char(1,2078).
+char(1,2079).
+char(m,2080).
+char(7,2081).
+char(8,2082).
+char(9,2083).
+char(5,2084).
+char(c,2085).
+char(c,2086).
+char(c,2087).
+char(c,2088).
+char(p,2089).
+char(1,2090).
+char(0,2091).
+char(9,2092).
+char(4,2093).
+char(p,2094).
+char(2,2095).
+char(2,2096).
+char(1,2097).
+char(3,2098).
+char(c,2099).
+char(c,2100).
+char(m,2101).
+char(o,2102).
+char(m,2103).
+char(o,2104).
+char(p,2105).
+char(o,2106).
+char(m,2107).
+char(3,2108).
+char(0,2109).
+char(5,2110).
+char(1,2111).
+char(p,2112).
+char(3,2113).
+char(4,2114).
+char(7,2115).
+char(9,2116).
+char(c,2117).
+char(c,2118).
+char(p,2119).
+char(4,2120).
+char(0,2121).
+char(8,2122).
+char(5,2123).
+char(p,2124).
+char(o,2125).
+char(p,2126).
+char(4,2127).
+char(7,2128).
+char(9,2129).
+char(0,2130).
+char(m,2131).
+char(4,2132).
+char(9,2133).
+char(7,2134).
+char(7,2135).
+char(m,2136).
+char(o,2137).
+char(p,2138).
+char(o,2139).
+char(p,2140).
+char(o,2141).
+char(m,2142).
+char(1,2143).
+char(6,2144).
+char(4,2145).
+char(4,2146).
+char(c,2147).
+char(p,2148).
+char(o,2149).
+char(p,2150).
+char(8,2151).
+char(6,2152).
+char(4,2153).
+char(9,2154).
+char(c,2155).
+char(m,2156).
+char(3,2157).
+char(0,2158).
+char(5,2159).
+char(0,2160).
+char(c,2161).
+char(p,2162).
+char(o,2163).
+char(p,2164).
+char(6,2165).
+char(3,2166).
+char(2,2167).
+char(6,2168).
+char(c,2169).
+char(m,2170).
+char(7,2171).
+char(9,2172).
+char(6,2173).
+char(4,2174).
+char(c,2175).
+char(m,2176).
+char(o,2177).
+char(m,2178).
+char(8,2179).
+char(6,2180).
+char(9,2181).
+char(9,2182).
+char(p,2183).
+char(2,2184).
+char(1,2185).
+char(4,2186).
+char(2,2187).
+char(p,2188).
+char(o,2189).
+char(p,2190).
+char(7,2191).
+char(7,2192).
+char(9,2193).
+char(7,2194).
+char(m,2195).
+char(o,2196).
+char(o,2197).
+char(p,2198).
+char(4,2199).
+char(4,2200).
+char(6,2201).
+char(2,2202).
+char(c,2203).
+char(p,2204).
+char(o,2205).
+char(8,2206).
+char(6,2207).
+char(8,2208).
+char(1,2209).
+char(c,2210).
+char(c,2211).
+char(m,2212).
+char(5,2213).
+char(1,2214).
+char(2,2215).
+char(4,2216).
+char(m,2217).
+char(8,2218).
+char(3,2219).
+char(c,2220).
+char(c,2221).
+char(c,2222).
+char(c,2223).
+char(p,2224).
+char(o,2225).
+char(o,2226).
+char(p,2227).
+char(o,2228).
+char(m,2229).
+char(o,2230).
+char(p,2231).
+char(2,2232).
+char(7,2233).
+char(2,2234).
+char(7,2235).
+char(m,2236).
+char(7,2237).
+char(7,2238).
+char(1,2239).
+char(9,2240).
+char(m,2241).
+char(9,2242).
+char(3,2243).
+char(0,2244).
+char(7,2245).
+char(c,2246).
+char(c,2247).
+char(m,2248).
+char(o,2249).
+char(o,2250).
+char(p,2251).
+char(4,2252).
+char(5,2253).
+char(3,2254).
+char(6,2255).
+char(m,2256).
+char(3,2257).
+char(1,2258).
+char(2,2259).
+char(2,2260).
+char(c,2261).
+char(c,2262).
+char(c,2263).
+char(c,2264).
+char(m,2265).
+char(1,2266).
+char(5,2267).
+char(1,2268).
+char(8,2269).
+char(p,2270).
+char(5,2271).
+char(9,2272).
+char(3,2273).
+char(1,2274).
+char(p,2275).
+char(o,2276).
+char(o,2277).
+char(m,2278).
+char(3,2279).
+char(9,2280).
+char(5,2281).
+char(7,2282).
+char(m,2283).
+char(7,2284).
+char(5,2285).
+char(2,2286).
+char(1,2287).
+char(c,2288).
+char(m,2289).
+char(o,2290).
+char(2,2291).
+char(3,2292).
+char(6,2293).
+char(5,2294).
+char(p,2295).
+char(o,2296).
+char(p,2297).
+char(7,2298).
+char(3,2299).
+char(3,2300).
+char(2,2301).
+char(p,2302).
+char(5,2303).
+char(2,2304).
+char(0,2305).
+char(2,2306).
+char(c,2307).
+char(m,2308).
+char(o,2309).
+char(m,2310).
+char(3,2311).
+char(9,2312).
+char(1,2313).
+char(6,2314).
+char(p,2315).
+char(3,2316).
+char(1,2317).
+char(1,2318).
+char(4,2319).
+char(p,2320).
+char(o,2321).
+char(p,2322).
+char(1,2323).
+char(3,2324).
+char(6,2325).
+char(7,2326).
+char(m,2327).
+char(5,2328).
+char(5,2329).
+char(6,2330).
+char(1,2331).
+char(p,2332).
+char(2,2333).
+char(0,2334).
+char(8,2335).
+char(5,2336).
+char(m,2337).
+char(5,2338).
+char(1,2339).
+char(2,2340).
+char(5,2341).
+char(c,2342).
+char(c,2343).
+char(m,2344).
+char(o,2345).
+char(p,2346).
+char(o,2347).
+char(m,2348).
+char(o,2349).
+char(m,2350).
+char(5,2351).
+char(6,2352).
+char(8,2353).
+char(4,2354).
+char(c,2355).
+char(c,2356).
+char(c,2357).
+char(c,2358).
+char(p,2359).
+char(o,2360).
+char(o,2361).
+char(p,2362).
+char(o,2363).
+char(o,2364).
+char(o,2365).
+char(m,2366).
+char(9,2367).
+char(0,2368).
+char(3,2369).
+char(5,2370).
+char(m,2371).
+char(o,2372).
+char(p,2373).
+char(o,2374).
+char(p,2375).
+char(o,2376).
+char(7,2377).
+char(4,2378).
+char(1,2379).
+char(0,2380).
+char(p,2381).
+char(o,2382).
+char(m,2383).
+char(o,2384).
+char(m,2385).
+char(o,2386).
+char(3,2387).
+char(1,2388).
+char(2,2389).
+char(7,2390).
+char(p,2391).
+char(o,2392).
+char(m,2393).
+char(9,2394).
+char(4,2395).
+char(6,2396).
+char(4,2397).
+char(m,2398).
+char(6,2399).
+char(6,2400).
+char(0,2401).
+char(2,2402).
+char(c,2403).
+char(c,2404).
+char(p,2405).
+char(3,2406).
+char(7,2407).
+char(8,2408).
+char(6,2409).
+char(p,2410).
+char(5,2411).
+char(0,2412).
+char(7,2413).
+char(0,2414).
+char(c,2415).
+char(c,2416).
+char(c,2417).
+char(m,2418).
+char(o,2419).
+char(p,2420).
+char(6,2421).
+char(7,2422).
+char(0,2423).
+char(5,2424).
+char(p,2425).
+char(o,2426).
+char(m,2427).
+char(o,2428).
+char(p,2429).
+char(o,2430).
+char(p,2431).
+char(2,2432).
+char(7,2433).
+char(8,2434).
+char(9,2435).
+char(p,2436).
+char(8,2437).
+char(9,2438).
+char(9,2439).
+char(1,2440).
+char(c,2441).
+char(p,2442).
+char(o,2443).
+char(p,2444).
+char(o,2445).
+char(m,2446).
+char(o,2447).
+char(m,2448).
+char(o,2449).
+char(o,2450).
+char(m,2451).
+char(7,2452).
+char(3,2453).
+char(2,2454).
+char(8,2455).
+char(c,2456).
+char(c,2457).
+char(c,2458).
+char(m,2459).
+char(4,2460).
+char(3,2461).
+char(9,2462).
+char(7,2463).
+char(c,2464).
+char(p,2465).
+char(o,2466).
+char(p,2467).
+char(o,2468).
+char(4,2469).
+char(8,2470).
+char(8,2471).
+char(9,2472).
+char(c,2473).
+char(p,2474).
+char(o,2475).
+char(o,2476).
+char(p,2477).
+char(7,2478).
+char(7,2479).
+char(3,2480).
+char(7,2481).
+char(c,2482).
+char(c,2483).
+char(c,2484).
+char(p,2485).
+char(9,2486).
+char(7,2487).
+char(9,2488).
+char(5,2489).
+char(c,2490).
+char(m,2491).
+char(o,2492).
+char(m,2493).
+char(o,2494).
+char(p,2495).
+char(8,2496).
+char(3,2497).
+char(3,2498).
+char(2,2499).
+char(p,2500).
+char(2,2501).
+char(6,2502).
+char(9,2503).
+char(2,2504).
+char(m,2505).
+char(o,2506).
+char(p,2507).
+char(o,2508).
+char(o,2509).
+char(p,2510).
+char(5,2511).
+char(7,2512).
+char(6,2513).
+char(5,2514).
+char(m,2515).
+char(o,2516).
+char(o,2517).
+char(m,2518).
+char(o,2519).
+char(p,2520).
+char(4,2521).
+char(1,2522).
+char(6,2523).
+char(2,2524).
+char(c,2525).
+char(c,2526).
+char(p,2527).
+char(o,2528).
+char(9,2529).
+char(5,2530).
+char(2,2531).
+char(1,2532).
+char(c,2533).
+char(p,2534).
+char(2,2535).
+char(2,2536).
+char(8,2537).
+char(1,2538).
+char(p,2539).
+char(1,2540).
+char(2,2541).
+char(0,2542).
+char(6,2543).
+char(p,2544).
+char(8,2545).
+char(7,2546).
+char(6,2547).
+char(c,2548).
+char(c,2549).
+char(c,2550).
+char(p,2551).
+char(o,2552).
+char(p,2553).
+char(1,2554).
+char(6,2555).
+char(0,2556).
+char(1,2557).
+char(m,2558).
+char(3,2559).
+char(6,2560).
+char(0,2561).
+char(0,2562).
+char(m,2563).
+char(o,2564).
+char(p,2565).
+char(4,2566).
+char(3,2567).
+char(4,2568).
+char(c,2569).
+char(p,2570).
+char(o,2571).
+char(p,2572).
+char(7,2573).
+char(6,2574).
+char(2,2575).
+char(p,2576).
+char(o,2577).
+char(5,2578).
+char(0,2579).
+char(6,2580).
+char(2,2581).
+char(c,2582).
+char(p,2583).
+char(9,2584).
+char(5,2585).
+char(8,2586).
+char(2,2587).
+char(c,2588).
+char(c,2589).
+char(m,2590).
+char(5,2591).
+char(3,2592).
+char(0,2593).
+char(9,2594).
+char(c,2595).
+char(m,2596).
+char(o,2597).
+char(m,2598).
+char(o,2599).
+char(m,2600).
+char(2,2601).
+char(0,2602).
+char(4,2603).
+char(5,2604).
+char(m,2605).
+char(o,2606).
+char(p,2607).
+char(3,2608).
+char(1,2609).
+char(7,2610).
+char(c,2611).
+char(m,2612).
+char(o,2613).
+char(m,2614).
+char(5,2615).
+char(1,2616).
+char(5,2617).
+char(5,2618).
+char(c,2619).
+char(p,2620).
+char(o,2621).
+char(p,2622).
+char(o,2623).
+char(o,2624).
+char(p,2625).
+char(o,2626).
+char(p,2627).
+char(o,2628).
+char(m,2629).
+char(o,2630).
+char(m,2631).
+char(1,2632).
+char(8,2633).
+char(8,2634).
+char(5,2635).
+char(c,2636).
+char(p,2637).
+char(5,2638).
+char(5,2639).
+char(3,2640).
+char(3,2641).
+char(c,2642).
+char(c,2643).
+char(c,2644).
+char(m,2645).
+char(o,2646).
+char(m,2647).
+char(o,2648).
+char(m,2649).
+char(o,2650).
+char(o,2651).
+char(p,2652).
+char(9,2653).
+char(4,2654).
+char(6,2655).
+char(7,2656).
+char(c,2657).
+char(m,2658).
+char(o,2659).
+char(p,2660).
+char(1,2661).
+char(3,2662).
+char(3,2663).
+char(1,2664).
+char(c,2665).
+char(p,2666).
+char(8,2667).
+char(8,2668).
+char(5,2669).
+char(7,2670).
+char(c,2671).
+char(m,2672).
+char(4,2673).
+char(2,2674).
+char(8,2675).
+char(6,2676).
+char(c,2677).
+char(p,2678).
+char(o,2679).
+char(o,2680).
+char(m,2681).
+char(o,2682).
+char(p,2683).
+char(8,2684).
+char(2,2685).
+char(7,2686).
+char(1,2687).
+char(c,2688).
+char(p,2689).
+char(o,2690).
+char(m,2691).
+char(2,2692).
+char(8,2693).
+char(2,2694).
+char(1,2695).
+char(c,2696).
+char(m,2697).
+char(4,2698).
+char(8,2699).
+char(0,2700).
+char(c,2701).
+char(p,2702).
+char(o,2703).
+char(o,2704).
+char(m,2705).
+char(9,2706).
+char(0,2707).
+char(5,2708).
+char(5,2709).
+char(m,2710).
+char(o,2711).
+char(o,2712).
+char(m,2713).
+char(o,2714).
+char(6,2715).
+char(2,2716).
+char(7,2717).
+char(c,2718).
+char(p,2719).
+char(o,2720).
+char(p,2721).
+char(2,2722).
+char(7,2723).
+char(3,2724).
+char(1,2725).
+char(m,2726).
+char(o,2727).
+char(p,2728).
+char(2,2729).
+char(7,2730).
+char(8,2731).
+char(8,2732).
+char(m,2733).
+char(6,2734).
+char(0,2735).
+char(8,2736).
+char(7,2737).
+char(p,2738).
+char(o,2739).
+char(m,2740).
+char(7,2741).
+char(3,2742).
+char(8,2743).
+char(3,2744).
+char(c,2745).
+char(c,2746).
+char(c,2747).
+char(m,2748).
+char(2,2749).
+char(9,2750).
+char(8,2751).
+char(9,2752).
+char(c,2753).
+char(m,2754).
+char(o,2755).
+char(m,2756).
+char(9,2757).
+char(5,2758).
+char(8,2759).
+char(5,2760).
+char(m,2761).
+char(o,2762).
+char(o,2763).
+char(p,2764).
+char(1,2765).
+char(1,2766).
+char(c,2767).
+char(c,2768).
+char(c,2769).
+char(m,2770).
+char(o,2771).
+char(3,2772).
+char(3,2773).
+char(2,2774).
+char(1,2775).
+char(p,2776).
+char(5,2777).
+char(8,2778).
+char(2,2779).
+char(3,2780).
+char(c,2781).
+char(c,2782).
+char(m,2783).
+char(o,2784).
+char(o,2785).
+char(1,2786).
+char(9,2787).
+char(7,2788).
+char(6,2789).
+char(p,2790).
+char(7,2791).
+char(4,2792).
+char(7,2793).
+char(1,2794).
+char(p,2795).
+char(o,2796).
+char(p,2797).
+char(o,2798).
+char(o,2799).
+char(m,2800).
+char(1,2801).
+char(8,2802).
+char(2,2803).
+char(c,2804).
+char(c,2805).
+char(c,2806).
+char(p,2807).
+char(o,2808).
+char(o,2809).
+char(9,2810).
+char(7,2811).
+char(4,2812).
+char(2,2813).
+char(p,2814).
+char(o,2815).
+char(1,2816).
+char(1,2817).
+char(2,2818).
+char(4,2819).
+char(c,2820).
+char(c,2821).
+char(p,2822).
+char(7,2823).
+char(6,2824).
+char(9,2825).
+char(0,2826).
+char(c,2827).
+char(c,2828).
+char(m,2829).
+char(o,2830).
+char(o,2831).
+char(p,2832).
+char(o,2833).
+char(p,2834).
+char(6,2835).
+char(3,2836).
+char(0,2837).
+char(0,2838).
+char(m,2839).
+char(o,2840).
+char(m,2841).
+char(9,2842).
+char(9,2843).
+char(7,2844).
+char(9,2845).
+char(c,2846).
+char(m,2847).
+char(7,2848).
+char(4,2849).
+char(6,2850).
+char(1,2851).
+char(c,2852).
+char(m,2853).
+char(9,2854).
+char(7,2855).
+char(8,2856).
+char(1,2857).
+char(c,2858).
+char(c,2859).
+char(c,2860).
+char(m,2861).
+char(7,2862).
+char(2,2863).
+char(c,2864).
+char(c,2865).
+char(m,2866).
+char(o,2867).
+char(m,2868).
+char(o,2869).
+char(m,2870).
+char(o,2871).
+char(m,2872).
+char(5,2873).
+char(9,2874).
+char(3,2875).
+char(9,2876).
+char(c,2877).
+char(c,2878).
+char(p,2879).
+char(o,2880).
+char(p,2881).
+char(o,2882).
+char(o,2883).
+char(p,2884).
+char(5,2885).
+char(5,2886).
+char(8,2887).
+char(3,2888).
+char(m,2889).
+char(2,2890).
+char(2,2891).
+char(7,2892).
+char(7,2893).
+char(c,2894).
+char(m,2895).
+char(9,2896).
+char(8,2897).
+char(6,2898).
+char(8,2899).
+char(c,2900).
+char(p,2901).
+char(2,2902).
+char(8,2903).
+char(1,2904).
+char(7,2905).
+char(m,2906).
+char(2,2907).
+char(9,2908).
+char(3,2909).
+char(5,2910).
+char(c,2911).
+char(m,2912).
+char(8,2913).
+char(4,2914).
+char(4,2915).
+char(9,2916).
+char(m,2917).
+char(7,2918).
+char(3,2919).
+char(7,2920).
+char(9,2921).
+char(p,2922).
+char(o,2923).
+char(m,2924).
+char(2,2925).
+char(3,2926).
+char(2,2927).
+char(m,2928).
+char(9,2929).
+char(7,2930).
+char(0,2931).
+char(7,2932).
+char(m,2933).
+char(9,2934).
+char(6,2935).
+char(0,2936).
+char(2,2937).
+char(p,2938).
+char(o,2939).
+char(m,2940).
+char(o,2941).
+char(o,2942).
+char(m,2943).
+char(6,2944).
+char(0,2945).
+char(3,2946).
+char(7,2947).
+char(c,2948).
+char(c,2949).
+char(m,2950).
+char(1,2951).
+char(3,2952).
+char(2,2953).
+char(4,2954).
+char(c,2955).
+char(c,2956).
+char(m,2957).
+char(9,2958).
+char(1,2959).
+char(5,2960).
+char(7,2961).
+char(p,2962).
+char(o,2963).
+char(p,2964).
+char(8,2965).
+char(7,2966).
+char(5,2967).
+char(6,2968).
+char(m,2969).
+char(o,2970).
+char(p,2971).
+char(o,2972).
+char(p,2973).
+char(8,2974).
+char(0,2975).
+char(7,2976).
+char(1,2977).
+char(c,2978).
+char(m,2979).
+char(o,2980).
+char(m,2981).
+char(8,2982).
+char(6,2983).
+char(8,2984).
+char(3,2985).
+char(c,2986).
+char(p,2987).
+char(o,2988).
+char(o,2989).
+char(p,2990).
+char(4,2991).
+char(0,2992).
+char(1,2993).
+char(9,2994).
+char(m,2995).
+char(3,2996).
+char(2,2997).
+char(5,2998).
+char(9,2999).
+char(c,3000).
+char(c,3001).
+char(c,3002).
+char(p,3003).
+char(6,3004).
+char(5,3005).
+char(0,3006).
+char(9,3007).
+char(m,3008).
+char(6,3009).
+char(6,3010).
+char(8,3011).
+char(1,3012).
+char(m,3013).
+char(9,3014).
+char(9,3015).
+char(2,3016).
+char(3,3017).
+char(c,3018).
+char(m,3019).
+char(o,3020).
+char(m,3021).
+char(o,3022).
+char(6,3023).
+char(9,3024).
+char(2,3025).
+char(4,3026).
+char(c,3027).
+char(p,3028).
+char(5,3029).
+char(2,3030).
+char(6,3031).
+char(m,3032).
+char(o,3033).
+char(m,3034).
+char(o,3035).
+char(m,3036).
+char(o,3037).
+char(o,3038).
+char(m,3039).
+char(o,3040).
+char(m,3041).
+char(o,3042).
+char(m,3043).
+char(2,3044).
+char(5,3045).
+char(6,3046).
+char(3,3047).
+char(c,3048).
+char(m,3049).
+char(7,3050).
+char(7,3051).
+char(8,3052).
+char(3,3053).
+char(m,3054).
+char(2,3055).
+char(5,3056).
+char(8,3057).
+char(8,3058).
+char(c,3059).
+char(p,3060).
+char(o,3061).
+char(m,3062).
+char(3,3063).
+char(4,3064).
+char(6,3065).
+char(4,3066).
+char(p,3067).
+char(9,3068).
+char(2,3069).
+char(5,3070).
+char(5,3071).
+char(c,3072).
+char(c,3073).
+char(p,3074).
+char(9,3075).
+char(2,3076).
+char(6,3077).
+char(5,3078).
+char(c,3079).
+char(m,3080).
+char(o,3081).
+char(p,3082).
+char(6,3083).
+char(7,3084).
+char(6,3085).
+char(8,3086).
+char(c,3087).
+char(p,3088).
+char(2,3089).
+char(6,3090).
+char(5,3091).
+char(6,3092).
+char(c,3093).
+char(c,3094).
+char(m,3095).
+char(6,3096).
+char(0,3097).
+char(9,3098).
+char(4,3099).
+char(m,3100).
+char(8,3101).
+char(2,3102).
+char(3,3103).
+char(7,3104).
+char(m,3105).
+char(o,3106).
+char(1,3107).
+char(2,3108).
+char(8,3109).
+char(1,3110).
+char(p,3111).
+char(6,3112).
+char(5,3113).
+char(8,3114).
+char(0,3115).
+char(c,3116).
+char(c,3117).
+char(m,3118).
+char(o,3119).
+char(m,3120).
+char(o,3121).
+char(6,3122).
+char(7,3123).
+char(8,3124).
+char(9,3125).
+char(c,3126).
+char(p,3127).
+char(o,3128).
+char(m,3129).
+char(5,3130).
+char(1,3131).
+char(5,3132).
+char(6,3133).
+char(c,3134).
+char(c,3135).
+char(m,3136).
+char(7,3137).
+char(0,3138).
+char(1,3139).
+char(4,3140).
+char(m,3141).
+char(o,3142).
+char(p,3143).
+char(7,3144).
+char(7,3145).
+char(9,3146).
+char(c,3147).
+char(c,3148).
+char(c,3149).
+char(c,3150).
+char(m,3151).
+char(2,3152).
+char(9,3153).
+char(2,3154).
+char(c,3155).
+char(m,3156).
+char(1,3157).
+char(9,3158).
+char(1,3159).
+char(9,3160).
+char(p,3161).
+char(5,3162).
+char(0,3163).
+char(1,3164).
+char(4,3165).
+char(p,3166).
+char(1,3167).
+char(3,3168).
+char(0,3169).
+char(7,3170).
+char(m,3171).
+char(3,3172).
+char(6,3173).
+char(3,3174).
+char(6,3175).
+char(c,3176).
+char(c,3177).
+char(p,3178).
+char(o,3179).
+char(3,3180).
+char(2,3181).
+char(2,3182).
+char(8,3183).
+char(p,3184).
+char(o,3185).
+char(m,3186).
+char(o,3187).
+char(3,3188).
+char(1,3189).
+char(7,3190).
+char(6,3191).
+char(m,3192).
+char(7,3193).
+char(1,3194).
+char(0,3195).
+char(c,3196).
+char(p,3197).
+char(o,3198).
+char(m,3199).
+char(7,3200).
+char(8,3201).
+char(8,3202).
+char(4,3203).
+char(p,3204).
+char(7,3205).
+char(7,3206).
+char(0,3207).
+char(6,3208).
+char(m,3209).
+char(6,3210).
+char(1,3211).
+char(1,3212).
+char(0,3213).
+char(m,3214).
+char(o,3215).
+char(m,3216).
+char(5,3217).
+char(1,3218).
+char(0,3219).
+char(0,3220).
+char(m,3221).
+char(8,3222).
+char(2,3223).
+char(3,3224).
+char(9,3225).
+char(c,3226).
+char(c,3227).
+char(c,3228).
+char(p,3229).
+char(1,3230).
+char(9,3231).
+char(7,3232).
+char(3,3233).
+char(p,3234).
+char(o,3235).
+char(p,3236).
+char(o,3237).
+char(m,3238).
+char(5,3239).
+char(9,3240).
+char(6,3241).
+char(m,3242).
+char(o,3243).
+char(o,3244).
+char(4,3245).
+char(7,3246).
+char(0,3247).
+char(5,3248).
+char(m,3249).
+char(o,3250).
+char(o,3251).
+char(4,3252).
+char(7,3253).
+char(5,3254).
+char(9,3255).
+char(p,3256).
+char(7,3257).
+char(2,3258).
+char(0,3259).
+char(c,3260).
+char(c,3261).
+char(p,3262).
+char(o,3263).
+char(m,3264).
+char(o,3265).
+char(m,3266).
+char(o,3267).
+char(p,3268).
+char(9,3269).
+char(1,3270).
+char(5,3271).
+char(1,3272).
+char(p,3273).
+char(7,3274).
+char(7,3275).
+char(1,3276).
+char(4,3277).
+char(m,3278).
+char(o,3279).
+char(o,3280).
+char(p,3281).
+char(o,3282).
+char(m,3283).
+char(o,3284).
+char(p,3285).
+char(1,3286).
+char(5,3287).
+char(5,3288).
+char(6,3289).
+char(c,3290).
+char(c,3291).
+char(m,3292).
+char(o,3293).
+char(m,3294).
+char(o,3295).
+char(p,3296).
+char(3,3297).
+char(1,3298).
+char(c,3299).
+char(c,3300).
+char(p,3301).
+char(3,3302).
+char(9,3303).
+char(4,3304).
+char(5,3305).
+char(c,3306).
+char(p,3307).
+char(o,3308).
+char(o,3309).
+char(8,3310).
+char(6,3311).
+char(3,3312).
+char(0,3313).
+char(p,3314).
+char(3,3315).
+char(3,3316).
+char(4,3317).
+char(5,3318).
+char(m,3319).
+char(o,3320).
+char(p,3321).
+char(4,3322).
+char(8,3323).
+char(5,3324).
+char(5,3325).
+char(m,3326).
+char(4,3327).
+char(2,3328).
+char(9,3329).
+char(2,3330).
+char(c,3331).
+char(p,3332).
+char(o,3333).
+char(o,3334).
+char(m,3335).
+char(9,3336).
+char(4,3337).
+char(5,3338).
+char(5,3339).
+char(c,3340).
+char(m,3341).
+char(1,3342).
+char(5,3343).
+char(2,3344).
+char(m,3345).
+char(o,3346).
+char(p,3347).
+char(o,3348).
+char(m,3349).
+char(3,3350).
+char(0,3351).
+char(6,3352).
+char(p,3353).
+char(o,3354).
+char(m,3355).
+char(5,3356).
+char(2,3357).
+char(2,3358).
+char(6,3359).
+char(m,3360).
+char(o,3361).
+char(o,3362).
+char(m,3363).
+char(o,3364).
+char(9,3365).
+char(4,3366).
+char(5,3367).
+char(0,3368).
+char(c,3369).
+char(c,3370).
+char(c,3371).
+char(c,3372).
+char(c,3373).
+char(p,3374).
+char(5,3375).
+char(6,3376).
+char(6,3377).
+char(4,3378).
+char(m,3379).
+char(o,3380).
+char(p,3381).
+char(o,3382).
+char(m,3383).
+char(o,3384).
+char(p,3385).
+char(o,3386).
+char(5,3387).
+char(0,3388).
+char(7,3389).
+char(3,3390).
+char(c,3391).
+char(p,3392).
+char(9,3393).
+char(6,3394).
+char(7,3395).
+char(3,3396).
+char(c,3397).
+char(m,3398).
+char(5,3399).
+char(7,3400).
+char(6,3401).
+char(2,3402).
+char(m,3403).
+char(o,3404).
+char(2,3405).
+char(4,3406).
+char(9,3407).
+char(6,3408).
+char(c,3409).
+char(p,3410).
+char(4,3411).
+char(0,3412).
+char(1,3413).
+char(1,3414).
+char(c,3415).
+char(p,3416).
+char(3,3417).
+char(8,3418).
+char(7,3419).
+char(c,3420).
+char(c,3421).
+char(c,3422).
+char(m,3423).
+char(o,3424).
+char(m,3425).
+char(6,3426).
+char(9,3427).
+char(7,3428).
+char(3,3429).
+char(p,3430).
+char(o,3431).
+char(m,3432).
+char(7,3433).
+char(0,3434).
+char(9,3435).
+char(2,3436).
+char(m,3437).
+char(o,3438).
+char(o,3439).
+char(o,3440).
+char(o,3441).
+char(m,3442).
+char(o,3443).
+char(p,3444).
+char(7,3445).
+char(0,3446).
+char(6,3447).
+char(8,3448).
+char(c,3449).
+char(p,3450).
+char(5,3451).
+char(5,3452).
+char(2,3453).
+char(7,3454).
+char(m,3455).
+char(9,3456).
+char(3,3457).
+char(1,3458).
+char(3,3459).
+char(c,3460).
+char(c,3461).
+char(p,3462).
+char(2,3463).
+char(7,3464).
+char(2,3465).
+char(4,3466).
+char(p,3467).
+char(o,3468).
+char(m,3469).
+char(o,3470).
+char(p,3471).
+char(9,3472).
+char(0,3473).
+char(9,3474).
+char(4,3475).
+char(c,3476).
+char(m,3477).
+char(9,3478).
+char(6,3479).
+char(1,3480).
+char(6,3481).
+char(c,3482).
+char(c,3483).
+char(p,3484).
+char(o,3485).
+char(m,3486).
+char(o,3487).
+char(p,3488).
+char(o,3489).
+char(7,3490).
+char(9,3491).
+char(9,3492).
+char(4,3493).
+char(m,3494).
+char(o,3495).
+char(1,3496).
+char(7,3497).
+char(3,3498).
+char(2,3499).
+char(p,3500).
+char(9,3501).
+char(1,3502).
+char(0,3503).
+char(9,3504).
+char(c,3505).
+char(c,3506).
+char(m,3507).
+char(o,3508).
+char(5,3509).
+char(7,3510).
+char(7,3511).
+char(c,3512).
+char(p,3513).
+char(1,3514).
+char(8,3515).
+char(6,3516).
+char(9,3517).
+char(c,3518).
+char(p,3519).
+char(2,3520).
+char(0,3521).
+char(4,3522).
+char(5,3523).
+char(p,3524).
+char(o,3525).
+char(m,3526).
+char(o,3527).
+char(m,3528).
+char(6,3529).
+char(1,3530).
+char(8,3531).
+char(5,3532).
+char(c,3533).
+char(m,3534).
+char(1,3535).
+char(9,3536).
+char(1,3537).
+char(1,3538).
+char(c,3539).
+char(c,3540).
+char(m,3541).
+char(o,3542).
+char(p,3543).
+char(o,3544).
+char(o,3545).
+char(o,3546).
+char(m,3547).
+char(o,3548).
+char(m,3549).
+char(7,3550).
+char(9,3551).
+char(8,3552).
+char(8,3553).
+char(c,3554).
+char(m,3555).
+char(o,3556).
+char(p,3557).
+char(9,3558).
+char(0,3559).
+char(0,3560).
+char(8,3561).
+char(c,3562).
+char(p,3563).
+char(o,3564).
+char(p,3565).
+char(o,3566).
+char(m,3567).
+char(o,3568).
+char(p,3569).
+char(7,3570).
+char(0,3571).
+char(1,3572).
+char(7,3573).
+char(c,3574).
+char(m,3575).
+char(7,3576).
+char(1,3577).
+char(1,3578).
+char(1,3579).
+char(p,3580).
+char(o,3581).
+char(p,3582).
+char(o,3583).
+char(m,3584).
+char(6,3585).
+char(9,3586).
+char(0,3587).
+char(5,3588).
+char(m,3589).
+char(5,3590).
+char(0,3591).
+char(1,3592).
+char(2,3593).
+char(p,3594).
+char(6,3595).
+char(6,3596).
+char(0,3597).
+char(2,3598).
+char(p,3599).
+char(o,3600).
+char(m,3601).
+char(o,3602).
+char(m,3603).
+char(1,3604).
+char(1,3605).
+char(5,3606).
+char(9,3607).
+char(p,3608).
+char(2,3609).
+char(6,3610).
+char(2,3611).
+char(6,3612).
+char(c,3613).
+char(c,3614).
+char(m,3615).
+char(o,3616).
+char(6,3617).
+char(3,3618).
+char(9,3619).
+char(1,3620).
+char(c,3621).
+char(c,3622).
+char(p,3623).
+char(o,3624).
+char(p,3625).
+char(4,3626).
+char(8,3627).
+char(4,3628).
+char(1,3629).
+char(p,3630).
+char(3,3631).
+char(0,3632).
+char(6,3633).
+char(3,3634).
+char(p,3635).
+char(7,3636).
+char(2,3637).
+char(1,3638).
+char(9,3639).
+char(c,3640).
+char(m,3641).
+char(o,3642).
+char(p,3643).
+char(o,3644).
+char(p,3645).
+char(9,3646).
+char(2,3647).
+char(7,3648).
+char(2,3649).
+char(m,3650).
+char(6,3651).
+char(2,3652).
+char(6,3653).
+char(4,3654).
+char(c,3655).
+char(p,3656).
+char(1,3657).
+char(8,3658).
+char(0,3659).
+char(6,3660).
+char(c,3661).
+char(c,3662).
+char(c,3663).
+char(c,3664).
+char(m,3665).
+char(o,3666).
+char(p,3667).
+char(o,3668).
+char(p,3669).
+char(o,3670).
+char(m,3671).
+char(o,3672).
+char(p,3673).
+char(o,3674).
+char(o,3675).
+char(8,3676).
+char(5,3677).
+char(5,3678).
+char(9,3679).
+char(c,3680).
+char(c,3681).
+char(c,3682).
+char(p,3683).
+char(o,3684).
+char(m,3685).
+char(o,3686).
+char(o,3687).
+char(p,3688).
+char(8,3689).
+char(5,3690).
+char(9,3691).
+char(4,3692).
+char(c,3693).
+char(c,3694).
+char(m,3695).
+char(4,3696).
+char(3,3697).
+char(5,3698).
+char(8,3699).
+char(p,3700).
+char(6,3701).
+char(3,3702).
+char(2,3703).
+char(5,3704).
+char(m,3705).
+char(9,3706).
+char(9,3707).
+char(7,3708).
+char(8,3709).
+char(m,3710).
+char(9,3711).
+char(1,3712).
+char(3,3713).
+char(9,3714).
+char(m,3715).
+char(3,3716).
+char(7,3717).
+char(3,3718).
+char(c,3719).
+char(p,3720).
+char(o,3721).
+char(p,3722).
+char(8,3723).
+char(5,3724).
+char(5,3725).
+char(1,3726).
+char(p,3727).
+char(2,3728).
+char(7,3729).
+char(4,3730).
+char(c,3731).
+char(c,3732).
+char(p,3733).
+char(o,3734).
+char(p,3735).
+char(4,3736).
+char(0,3737).
+char(7,3738).
+char(7,3739).
+char(m,3740).
+char(8,3741).
+char(1,3742).
+char(0,3743).
+char(2,3744).
+char(c,3745).
+char(p,3746).
+char(o,3747).
+char(m,3748).
+char(o,3749).
+char(m,3750).
+char(2,3751).
+char(3,3752).
+char(2,3753).
+char(7,3754).
+char(c,3755).
+char(m,3756).
+char(o,3757).
+char(p,3758).
+char(2,3759).
+char(0,3760).
+char(2,3761).
+char(9,3762).
+char(c,3763).
+char(c,3764).
+char(c,3765).
+char(m,3766).
+char(o,3767).
+char(m,3768).
+char(1,3769).
+char(4,3770).
+char(8,3771).
+char(6,3772).
+char(c,3773).
+char(p,3774).
+char(o,3775).
+char(p,3776).
+char(o,3777).
+char(p,3778).
+char(o,3779).
+char(p,3780).
+char(7,3781).
+char(2,3782).
+char(8,3783).
+char(0,3784).
+char(m,3785).
+char(7,3786).
+char(7,3787).
+char(1,3788).
+char(9,3789).
+char(c,3790).
+char(p,3791).
+char(1,3792).
+char(9,3793).
+char(9,3794).
+char(8,3795).
+char(c,3796).
+char(p,3797).
+char(o,3798).
+char(m,3799).
+char(o,3800).
+char(o,3801).
+char(o,3802).
+char(5,3803).
+char(2,3804).
+char(0,3805).
+char(8,3806).
+char(c,3807).
+char(m,3808).
+char(o,3809).
+char(6,3810).
+char(9,3811).
+char(1,3812).
+char(7,3813).
+char(c,3814).
+char(m,3815).
+char(3,3816).
+char(4,3817).
+char(8,3818).
+char(6,3819).
+char(c,3820).
+char(c,3821).
+char(c,3822).
+char(p,3823).
+char(8,3824).
+char(6,3825).
+char(2,3826).
+char(p,3827).
+char(o,3828).
+char(2,3829).
+char(5,3830).
+char(2,3831).
+char(8,3832).
+char(c,3833).
+char(p,3834).
+char(o,3835).
+char(o,3836).
+char(m,3837).
+char(4,3838).
+char(5,3839).
+char(2,3840).
+char(0,3841).
+char(p,3842).
+char(8,3843).
+char(3,3844).
+char(0,3845).
+char(2,3846).
+char(c,3847).
+char(c,3848).
+char(p,3849).
+char(o,3850).
+char(m,3851).
+char(5,3852).
+char(0,3853).
+char(4,3854).
+char(1,3855).
+char(c,3856).
+char(c,3857).
+char(m,3858).
+char(o,3859).
+char(p,3860).
+char(o,3861).
+char(o,3862).
+char(m,3863).
+char(6,3864).
+char(4,3865).
+char(0,3866).
+char(2,3867).
+char(m,3868).
+char(2,3869).
+char(0,3870).
+char(5,3871).
+char(2,3872).
+char(c,3873).
+char(m,3874).
+char(o,3875).
+char(m,3876).
+char(o,3877).
+char(p,3878).
+char(6,3879).
+char(7,3880).
+char(4,3881).
+char(2,3882).
+char(p,3883).
+char(5,3884).
+char(3,3885).
+char(8,3886).
+char(1,3887).
+char(p,3888).
+char(o,3889).
+char(5,3890).
+char(8,3891).
+char(8,3892).
+char(1,3893).
+char(c,3894).
+char(c,3895).
+char(m,3896).
+char(o,3897).
+char(9,3898).
+char(7,3899).
+char(2,3900).
+char(1,3901).
+char(c,3902).
+char(m,3903).
+char(o,3904).
+char(8,3905).
+char(1,3906).
+char(3,3907).
+char(9,3908).
+char(p,3909).
+char(o,3910).
+char(m,3911).
+char(7,3912).
+char(5,3913).
+char(8,3914).
+char(5,3915).
+char(c,3916).
+char(m,3917).
+char(o,3918).
+char(p,3919).
+char(o,3920).
+char(o,3921).
+char(m,3922).
+char(o,3923).
+char(o,3924).
+char(m,3925).
+char(o,3926).
+char(o,3927).
+char(m,3928).
+char(8,3929).
+char(2,3930).
+char(8,3931).
+char(8,3932).
+char(c,3933).
+char(p,3934).
+char(2,3935).
+char(6,3936).
+char(1,3937).
+char(1,3938).
+char(p,3939).
+char(9,3940).
+char(5,3941).
+char(4,3942).
+char(p,3943).
+char(1,3944).
+char(2,3945).
+char(8,3946).
+char(0,3947).
+char(m,3948).
+char(o,3949).
+char(5,3950).
+char(9,3951).
+char(6,3952).
+char(2,3953).
+char(p,3954).
+char(o,3955).
+char(p,3956).
+char(4,3957).
+char(6,3958).
+char(2,3959).
+char(1,3960).
+char(c,3961).
+char(m,3962).
+char(2,3963).
+char(8,3964).
+char(3,3965).
+char(4,3966).
+char(p,3967).
+char(1,3968).
+char(5,3969).
+char(2,3970).
+char(5,3971).
+char(c,3972).
+char(c,3973).
+char(c,3974).
+char(m,3975).
+char(9,3976).
+char(0,3977).
+char(3,3978).
+char(1,3979).
+char(m,3980).
+char(o,3981).
+char(p,3982).
+char(3,3983).
+char(5,3984).
+char(1,3985).
+char(0,3986).
+char(c,3987).
+char(p,3988).
+char(o,3989).
+char(m,3990).
+char(o,3991).
+char(o,3992).
+char(p,3993).
+char(o,3994).
+char(o,3995).
+char(p,3996).
+char(7,3997).
+char(8,3998).
+char(4,3999).
+char(7,4000).
+char(c,4001).
+char(c,4002).
+char(p,4003).
+char(8,4004).
+char(2,4005).
+char(8,4006).
+char(0,4007).
+char(p,4008).
+char(o,4009).
+char(m,4010).
+char(o,4011).
+char(4,4012).
+char(0,4013).
+char(3,4014).
+char(0,4015).
+char(c,4016).
+char(c,4017).
+char(p,4018).
+char(o,4019).
+char(o,4020).
+char(m,4021).
+char(o,4022).
+char(o,4023).
+char(p,4024).
+char(3,4025).
+char(3,4026).
+char(0,4027).
+char(1,4028).
+char(p,4029).
+char(o,4030).
+char(p,4031).
+char(8,4032).
+char(3,4033).
+char(3,4034).
+char(3,4035).
+char(p,4036).
+char(5,4037).
+char(9,4038).
+char(3,4039).
+char(c,4040).
+char(c,4041).
+char(m,4042).
+char(2,4043).
+char(5,4044).
+char(5,4045).
+char(7,4046).
+char(c,4047).
+char(p,4048).
+char(o,4049).
+char(m,4050).
+char(6,4051).
+char(5,4052).
+char(4,4053).
+char(5,4054).
+char(c,4055).
+char(c,4056).
+char(p,4057).
+char(8,4058).
+char(2,4059).
+char(3,4060).
+char(0,4061).
+char(p,4062).
+char(4,4063).
+char(4,4064).
+char(0,4065).
+char(4,4066).
+char(c,4067).
+char(m,4068).
+char(o,4069).
+char(m,4070).
+char(o,4071).
+char(p,4072).
+char(1,4073).
+char(7,4074).
+char(3,4075).
+char(9,4076).
+char(c,4077).
+char(m,4078).
+char(9,4079).
+char(5,4080).
+char(1,4081).
+char(8,4082).
+char(m,4083).
+char(2,4084).
+char(8,4085).
+char(8,4086).
+char(6,4087).
+char(p,4088).
+char(o,4089).
+char(o,4090).
+char(p,4091).
+char(o,4092).
+char(o,4093).
+char(2,4094).
+char(2,4095).
+char(2,4096).
+char(3,4097).
+char(c,4098).
+char(c,4099).
+char(c,4100).
+char(p,4101).
+char(o,4102).
+char(p,4103).
+char(o,4104).
+char(p,4105).
+char(2,4106).
+char(1,4107).
+char(1,4108).
+char(6,4109).
+char(m,4110).
+char(3,4111).
+char(6,4112).
+char(8,4113).
+char(1,4114).
+char(p,4115).
+char(9,4116).
+char(1,4117).
+char(3,4118).
+char(0,4119).
+char(c,4120).
+char(c,4121).
+char(c,4122).
+char(c,4123).
+char(c,4124).
+char(c,4125).
+char(m,4126).
+char(8,4127).
+char(8,4128).
+char(2,4129).
+char(9,4130).
+char(c,4131).
+char(p,4132).
+char(9,4133).
+char(3,4134).
+char(9,4135).
+char(4,4136).
+char(c,4137).
+char(c,4138).
+char(m,4139).
+char(9,4140).
+char(9,4141).
+char(9,4142).
+char(7,4143).
+char(c,4144).
+char(m,4145).
+char(o,4146).
+char(p,4147).
+char(o,4148).
+char(m,4149).
+char(o,4150).
+char(o,4151).
+char(m,4152).
+char(o,4153).
+char(p,4154).
+char(2,4155).
+char(2,4156).
+char(6,4157).
+char(3,4158).
+char(c,4159).
+char(c,4160).
+char(c,4161).
+char(c,4162).
+char(c,4163).
+char(p,4164).
+char(7,4165).
+char(1,4166).
+char(3,4167).
+char(6,4168).
+char(m,4169).
+char(o,4170).
+char(o,4171).
+char(8,4172).
+char(8,4173).
+char(9,4174).
+char(6,4175).
+char(m,4176).
+char(8,4177).
+char(4,4178).
+char(4,4179).
+char(3,4180).
+char(p,4181).
+char(o,4182).
+char(m,4183).
+char(o,4184).
+char(5,4185).
+char(8,4186).
+char(0,4187).
+char(2,4188).
+char(c,4189).
+char(m,4190).
+char(8,4191).
+char(3,4192).
+char(4,4193).
+char(8,4194).
+char(m,4195).
+char(1,4196).
+char(3,4197).
+char(8,4198).
+char(5,4199).
+char(m,4200).
+char(o,4201).
+char(m,4202).
+char(o,4203).
+char(m,4204).
+char(9,4205).
+char(6,4206).
+char(7,4207).
+char(4,4208).
+char(c,4209).
+char(p,4210).
+char(o,4211).
+char(o,4212).
+char(1,4213).
+char(2,4214).
+char(0,4215).
+char(m,4216).
+char(o,4217).
+char(p,4218).
+char(o,4219).
+char(m,4220).
+char(2,4221).
+char(3,4222).
+char(0,4223).
+char(0,4224).
+char(m,4225).
+char(5,4226).
+char(3,4227).
+char(2,4228).
+char(1,4229).
+char(c,4230).
+char(c,4231).
+char(p,4232).
+char(3,4233).
+char(8,4234).
+char(7,4235).
+char(0,4236).
+char(m,4237).
+char(o,4238).
+char(o,4239).
+char(5,4240).
+char(5,4241).
+char(8,4242).
+char(8,4243).
+char(p,4244).
+char(3,4245).
+char(6,4246).
+char(3,4247).
+char(2,4248).
+char(c,4249).
+char(c,4250).
+char(c,4251).
+char(p,4252).
+char(3,4253).
+char(0,4254).
+char(9,4255).
+char(8,4256).
+char(m,4257).
+char(7,4258).
+char(4,4259).
+char(0,4260).
+char(3,4261).
+char(c,4262).
+char(p,4263).
+char(4,4264).
+char(2,4265).
+char(3,4266).
+char(8,4267).
+char(m,4268).
+char(o,4269).
+char(m,4270).
+char(o,4271).
+char(p,4272).
+char(o,4273).
+char(m,4274).
+char(o,4275).
+char(m,4276).
+char(6,4277).
+char(2,4278).
+char(1,4279).
+char(9,4280).
+char(c,4281).
+char(c,4282).
+char(c,4283).
+char(m,4284).
+char(9,4285).
+char(5,4286).
+char(1,4287).
+char(c,4288).
+char(c,4289).
+char(c,4290).
+char(c,4291).
+char(m,4292).
+char(4,4293).
+char(3,4294).
+char(9,4295).
+char(8,4296).
+char(c,4297).
+char(p,4298).
+char(6,4299).
+char(9,4300).
+char(0,4301).
+char(4,4302).
+char(c,4303).
+char(m,4304).
+char(4,4305).
+char(6,4306).
+char(8,4307).
+char(9,4308).
+char(c,4309).
+char(p,4310).
+char(8,4311).
+char(7,4312).
+char(6,4313).
+char(4,4314).
+char(c,4315).
+char(c,4316).
+char(m,4317).
+char(o,4318).
+char(p,4319).
+char(2,4320).
+char(1,4321).
+char(2,4322).
+char(8,4323).
+char(m,4324).
+char(o,4325).
+char(m,4326).
+char(5,4327).
+char(4,4328).
+char(9,4329).
+char(2,4330).
+char(p,4331).
+char(7,4332).
+char(0,4333).
+char(3,4334).
+char(c,4335).
+char(p,4336).
+char(o,4337).
+char(3,4338).
+char(0,4339).
+char(9,4340).
+char(3,4341).
+char(c,4342).
+char(c,4343).
+char(p,4344).
+char(8,4345).
+char(1,4346).
+char(7,4347).
+char(7,4348).
+char(c,4349).
+char(c,4350).
+char(c,4351).
+char(c,4352).
+char(p,4353).
+char(o,4354).
+char(p,4355).
+char(8,4356).
+char(6,4357).
+char(1,4358).
+char(1,4359).
+char(c,4360).
+char(c,4361).
+char(c,4362).
+char(c,4363).
+char(p,4364).
+char(3,4365).
+char(9,4366).
+char(4,4367).
+char(c,4368).
+char(m,4369).
+char(o,4370).
+char(m,4371).
+char(o,4372).
+char(p,4373).
+char(o,4374).
+char(p,4375).
+char(2,4376).
+char(9,4377).
+char(9,4378).
+char(1,4379).
+char(c,4380).
+char(p,4381).
+char(7,4382).
+char(4,4383).
+char(9,4384).
+char(4,4385).
+char(p,4386).
+char(o,4387).
+char(o,4388).
+char(o,4389).
+char(o,4390).
+char(p,4391).
+char(o,4392).
+char(o,4393).
+char(m,4394).
+char(1,4395).
+char(4,4396).
+char(8,4397).
+char(4,4398).
+char(c,4399).
+char(p,4400).
+char(2,4401).
+char(5,4402).
+char(4,4403).
+char(0,4404).
+char(p,4405).
+char(o,4406).
+char(p,4407).
+char(o,4408).
+char(m,4409).
+char(o,4410).
+char(o,4411).
+char(8,4412).
+char(9,4413).
+char(3,4414).
+char(p,4415).
+char(o,4416).
+char(m,4417).
+char(8,4418).
+char(1,4419).
+char(1,4420).
+char(1,4421).
+char(c,4422).
+char(c,4423).
+char(c,4424).
+char(c,4425).
+char(c,4426).
+char(c,4427).
+char(m,4428).
+char(6,4429).
+char(8,4430).
+char(3,4431).
+char(4,4432).
+char(c,4433).
+char(c,4434).
+char(p,4435).
+char(o,4436).
+char(m,4437).
+char(8,4438).
+char(1,4439).
+char(4,4440).
+char(2,4441).
+char(c,4442).
+char(m,4443).
+char(8,4444).
+char(4,4445).
+char(6,4446).
+char(7,4447).
+char(c,4448).
+char(p,4449).
+char(o,4450).
+char(m,4451).
+char(8,4452).
+char(6,4453).
+char(3,4454).
+char(1,4455).
+char(c,4456).
+char(p,4457).
+char(o,4458).
+char(8,4459).
+char(5,4460).
+char(4,4461).
+char(1,4462).
+char(m,4463).
+char(o,4464).
+char(m,4465).
+char(4,4466).
+char(9,4467).
+char(8,4468).
+char(1,4469).
+char(c,4470).
+char(p,4471).
+char(5,4472).
+char(8,4473).
+char(6,4474).
+char(0,4475).
+char(m,4476).
+char(2,4477).
+char(7,4478).
+char(2,4479).
+char(7,4480).
+char(c,4481).
+char(m,4482).
+char(o,4483).
+char(p,4484).
+char(o,4485).
+char(m,4486).
+char(6,4487).
+char(2,4488).
+char(1,4489).
+char(4,4490).
+char(m,4491).
+char(o,4492).
+char(p,4493).
+char(8,4494).
+char(8,4495).
+char(4,4496).
+char(0,4497).
+char(p,4498).
+char(o,4499).
+char(o,4500).
+char(p,4501).
+char(8,4502).
+char(3,4503).
+char(3,4504).
+char(p,4505).
+char(5,4506).
+char(7,4507).
+char(0,4508).
+char(6,4509).
+char(p,4510).
+char(o,4511).
+char(p,4512).
+char(o,4513).
+char(o,4514).
+char(5,4515).
+char(6,4516).
+char(7,4517).
+char(7,4518).
+char(c,4519).
+char(p,4520).
+char(o,4521).
+char(o,4522).
+char(o,4523).
+char(p,4524).
+char(9,4525).
+char(9,4526).
+char(3,4527).
+char(6,4528).
+char(p,4529).
+char(o,4530).
+char(m,4531).
+char(o,4532).
+char(7,4533).
+char(0,4534).
+char(5,4535).
+char(6,4536).
+char(c,4537).
+char(m,4538).
+char(9,4539).
+char(1,4540).
+char(0,4541).
+char(4,4542).
+char(c,4543).
+char(p,4544).
+char(5,4545).
+char(8,4546).
+char(5,4547).
+char(1,4548).
+char(c,4549).
+char(p,4550).
+char(8,4551).
+char(5,4552).
+char(c,4553).
+char(c,4554).
+char(c,4555).
+char(c,4556).
+char(p,4557).
+char(9,4558).
+char(7,4559).
+char(3,4560).
+char(6,4561).
+char(c,4562).
+char(c,4563).
+char(p,4564).
+char(o,4565).
+char(p,4566).
+char(4,4567).
+char(5,4568).
+char(9,4569).
+char(7,4570).
+char(c,4571).
+char(c,4572).
+char(m,4573).
+char(4,4574).
+char(4,4575).
+char(3,4576).
+char(5,4577).
+char(c,4578).
+char(p,4579).
+char(o,4580).
+char(m,4581).
+char(o,4582).
+char(p,4583).
+char(o,4584).
+char(p,4585).
+char(7,4586).
+char(4,4587).
+char(1,4588).
+char(p,4589).
+char(o,4590).
+char(9,4591).
+char(2,4592).
+char(8,4593).
+char(8,4594).
+char(p,4595).
+char(8,4596).
+char(7,4597).
+char(9,4598).
+char(4,4599).
+char(c,4600).
+char(c,4601).
+char(m,4602).
+char(9,4603).
+char(m,4604).
+char(o,4605).
+char(o,4606).
+char(p,4607).
+char(4,4608).
+char(2,4609).
+char(6,4610).
+char(5,4611).
+char(c,4612).
+char(m,4613).
+char(4,4614).
+char(5,4615).
+char(5,4616).
+char(7,4617).
+char(m,4618).
+char(o,4619).
+char(p,4620).
+char(o,4621).
+char(8,4622).
+char(6,4623).
+char(4,4624).
+char(4,4625).
+char(m,4626).
+char(o,4627).
+char(p,4628).
+char(7,4629).
+char(7,4630).
+char(1,4631).
+char(9,4632).
+char(c,4633).
+char(m,4634).
+char(o,4635).
+char(p,4636).
+char(2,4637).
+char(9,4638).
+char(7,4639).
+char(7,4640).
+char(m,4641).
+char(o,4642).
+char(5,4643).
+char(6,4644).
+char(6,4645).
+char(1,4646).
+char(m,4647).
+char(o,4648).
+char(o,4649).
+char(p,4650).
+char(1,4651).
+char(2,4652).
+char(9,4653).
+char(4,4654).
+char(c,4655).
+char(m,4656).
+char(o,4657).
+char(4,4658).
+char(6,4659).
+char(5,4660).
+char(2,4661).
+char(c,4662).
+char(c,4663).
+char(c,4664).
+char(c,4665).
+char(c,4666).
+char(c,4667).
+char(p,4668).
+char(o,4669).
+char(p,4670).
+char(o,4671).
+char(m,4672).
+char(o,4673).
+char(o,4674).
+char(m,4675).
+char(o,4676).
+char(o,4677).
+char(7,4678).
+char(8,4679).
+char(4,4680).
+char(2,4681).
+char(p,4682).
+char(1,4683).
+char(2,4684).
+char(0,4685).
+char(7,4686).
+char(m,4687).
+char(o,4688).
+char(9,4689).
+char(4,4690).
+char(9,4691).
+char(6,4692).
+char(c,4693).
+char(c,4694).
+char(m,4695).
+char(5,4696).
+char(7,4697).
+char(2,4698).
+char(2,4699).
+char(m,4700).
+char(9,4701).
+char(4,4702).
+char(1,4703).
+char(0,4704).
+char(p,4705).
+char(1,4706).
+char(3,4707).
+char(2,4708).
+char(8,4709).
+char(c,4710).
+char(p,4711).
+char(o,4712).
+char(o,4713).
+char(m,4714).
+char(o,4715).
+char(m,4716).
+char(3,4717).
+char(3,4718).
+char(5,4719).
+char(1,4720).
+char(p,4721).
+char(o,4722).
+char(p,4723).
+char(o,4724).
+char(m,4725).
+char(3,4726).
+char(0,4727).
+char(7,4728).
+char(8,4729).
+char(c,4730).
+char(m,4731).
+char(o,4732).
+char(m,4733).
+char(o,4734).
+char(o,4735).
+char(m,4736).
+char(5,4737).
+char(5,4738).
+char(1,4739).
+char(1,4740).
+char(m,4741).
+char(4,4742).
+char(5,4743).
+char(4,4744).
+char(4,4745).
+char(c,4746).
+char(m,4747).
+char(1,4748).
+char(1,4749).
+char(4,4750).
+char(1,4751).
+char(c,4752).
+char(m,4753).
+char(o,4754).
+char(p,4755).
+char(o,4756).
+char(p,4757).
+char(7,4758).
+char(5,4759).
+char(7,4760).
+char(5,4761).
+char(m,4762).
+char(o,4763).
+char(3,4764).
+char(6,4765).
+char(6,4766).
+char(m,4767).
+char(o,4768).
+char(8,4769).
+char(4,4770).
+char(7,4771).
+char(p,4772).
+char(o,4773).
+char(o,4774).
+char(o,4775).
+char(p,4776).
+char(o,4777).
+char(p,4778).
+char(4,4779).
+char(6,4780).
+char(4,4781).
+char(2,4782).
+char(c,4783).
+char(c,4784).
+char(c,4785).
+char(c,4786).
+char(p,4787).
+char(o,4788).
+char(m,4789).
+char(o,4790).
+char(p,4791).
+char(8,4792).
+char(9,4793).
+char(1,4794).
+char(0,4795).
+char(p,4796).
+char(4,4797).
+char(9,4798).
+char(5,4799).
+char(9,4800).
+char(c,4801).
+char(c,4802).
+char(c,4803).
+char(p,4804).
+char(o,4805).
+char(p,4806).
+char(1,4807).
+char(0,4808).
+char(1,4809).
+char(9,4810).
+char(p,4811).
+char(6,4812).
+char(3,4813).
+char(2,4814).
+char(6,4815).
+char(m,4816).
+char(o,4817).
+char(o,4818).
+char(m,4819).
+char(5,4820).
+char(0,4821).
+char(4,4822).
+char(0,4823).
+char(m,4824).
+char(o,4825).
+char(o,4826).
+char(p,4827).
+char(2,4828).
+char(4,4829).
+char(3,4830).
+char(3,4831).
+char(c,4832).
+char(c,4833).
+char(m,4834).
+char(o,4835).
+char(o,4836).
+char(m,4837).
+char(o,4838).
+char(o,4839).
+char(o,4840).
+char(m,4841).
+char(9,4842).
+char(5,4843).
+char(5,4844).
+char(1,4845).
+char(c,4846).
+char(p,4847).
+char(6,4848).
+char(8,4849).
+char(3,4850).
+char(8,4851).
+char(c,4852).
+char(m,4853).
+char(7,4854).
+char(8,4855).
+char(7,4856).
+char(7,4857).
+char(c,4858).
+char(m,4859).
+char(6,4860).
+char(6,4861).
+char(6,4862).
+char(8,4863).
+char(p,4864).
+char(o,4865).
+char(p,4866).
+char(2,4867).
+char(3,4868).
+char(7,4869).
+char(1,4870).
+char(c,4871).
+char(m,4872).
+char(o,4873).
+char(4,4874).
+char(0,4875).
+char(3,4876).
+char(p,4877).
+char(7,4878).
+char(0,4879).
+char(2,4880).
+char(5,4881).
+char(p,4882).
+char(o,4883).
+char(p,4884).
+char(o,4885).
+char(p,4886).
+char(2,4887).
+char(8,4888).
+char(3,4889).
+char(7,4890).
+char(p,4891).
+char(o,4892).
+char(m,4893).
+char(o,4894).
+char(m,4895).
+char(o,4896).
+char(p,4897).
+char(1,4898).
+char(3,4899).
+char(8,4900).
+char(0,4901).
+char(m,4902).
+char(9,4903).
+char(8,4904).
+char(9,4905).
+char(c,4906).
+char(c,4907).
+char(c,4908).
+char(c,4909).
+char(c,4910).
+char(c,4911).
+char(c,4912).
+char(c,4913).
+char(c,4914).
+char(p,4915).
+char(o,4916).
+char(p,4917).
+char(5,4918).
+char(3,4919).
+char(0,4920).
+char(8,4921).
+char(c,4922).
+char(c,4923).
+char(c,4924).
+char(p,4925).
+char(o,4926).
+char(p,4927).
+char(o,4928).
+char(p,4929).
+char(6,4930).
+char(2,4931).
+char(2,4932).
+char(0,4933).
+char(p,4934).
+char(2,4935).
+char(0,4936).
+char(7,4937).
+char(0,4938).
+char(p,4939).
+char(7,4940).
+char(3,4941).
+char(1,4942).
+char(9,4943).
+char(c,4944).
+char(c,4945).
+char(c,4946).
+char(p,4947).
+char(o,4948).
+char(p,4949).
+char(o,4950).
+char(m,4951).
+char(9,4952).
+char(6,4953).
+char(3,4954).
+char(c,4955).
+char(c,4956).
+char(c,4957).
+char(m,4958).
+char(4,4959).
+char(2,4960).
+char(1,4961).
+char(5,4962).
+char(c,4963).
+char(c,4964).
+char(c,4965).
+char(m,4966).
+char(9,4967).
+char(2,4968).
+char(7,4969).
+char(9,4970).
+char(c,4971).
+char(c,4972).
+char(c,4973).
+char(c,4974).
+char(c,4975).
+char(m,4976).
+char(2,4977).
+char(7,4978).
+char(8,4979).
+char(5,4980).
+char(m,4981).
+char(4,4982).
+char(0,4983).
+char(2,4984).
+char(c,4985).
+char(c,4986).
+char(c,4987).
+char(p,4988).
+char(8,4989).
+char(6,4990).
+char(2,4991).
+char(4,4992).
+char(m,4993).
+char(o,4994).
+char(m,4995).
+char(8,4996).
+char(1,4997).
+char(5,4998).
+char(6,4999).
+char(c,5000).
+char(c,5001).
+char(c,5002).
+char(m,5003).
+char(3,5004).
+char(2,5005).
+char(0,5006).
+char(9,5007).
+char(m,5008).
+char(o,5009).
+char(p,5010).
+char(o,5011).
+char(1,5012).
+char(0,5013).
+char(0,5014).
+char(1,5015).
+char(p,5016).
+char(6,5017).
+char(4,5018).
+char(4,5019).
+char(4,5020).
+char(c,5021).
+char(p,5022).
+char(o,5023).
+char(1,5024).
+char(4,5025).
+char(4,5026).
+char(3,5027).
+char(c,5028).
+char(c,5029).
+char(c,5030).
+char(c,5031).
+char(p,5032).
+char(9,5033).
+char(4,5034).
+char(3,5035).
+char(1,5036).
+char(c,5037).
+char(c,5038).
+char(p,5039).
+char(o,5040).
+char(m,5041).
+char(6,5042).
+char(2,5043).
+char(3,5044).
+char(7,5045).
+char(m,5046).
+char(o,5047).
+char(p,5048).
+char(o,5049).
+char(p,5050).
+char(o,5051).
+char(3,5052).
+char(7,5053).
+char(9,5054).
+char(5,5055).
+char(m,5056).
+char(7,5057).
+char(1,5058).
+char(2,5059).
+char(6,5060).
+char(p,5061).
+char(o,5062).
+char(1,5063).
+char(1,5064).
+char(6,5065).
+char(2,5066).
+char(c,5067).
+char(p,5068).
+char(4,5069).
+char(0,5070).
+char(9,5071).
+char(2,5072).
+char(c,5073).
+char(p,5074).
+char(o,5075).
+char(5,5076).
+char(1,5077).
+char(1,5078).
+char(8,5079).
+char(c,5080).
+char(c,5081).
+char(c,5082).
+char(m,5083).
+char(7,5084).
+char(7,5085).
+char(0,5086).
+char(1,5087).
+char(c,5088).
+char(p,5089).
+char(o,5090).
+char(p,5091).
+char(o,5092).
+char(m,5093).
+char(o,5094).
+char(p,5095).
+char(1,5096).
+char(6,5097).
+char(4,5098).
+char(6,5099).
+char(c,5100).
+char(p,5101).
+char(2,5102).
+char(2,5103).
+char(4,5104).
+char(4,5105).
+char(p,5106).
+char(3,5107).
+char(2,5108).
+char(3,5109).
+char(m,5110).
+char(6,5111).
+char(0,5112).
+char(8,5113).
+char(5,5114).
+char(p,5115).
+char(o,5116).
+char(9,5117).
+char(5,5118).
+char(8,5119).
+char(0,5120).
+char(c,5121).
+char(p,5122).
+char(2,5123).
+char(1,5124).
+char(8,5125).
+char(5,5126).
+char(c,5127).
+char(p,5128).
+char(o,5129).
+char(m,5130).
+char(o,5131).
+char(p,5132).
+char(o,5133).
+char(m,5134).
+char(7,5135).
+char(8,5136).
+char(2,5137).
+char(8,5138).
+char(p,5139).
+char(6,5140).
+char(8,5141).
+char(5,5142).
+char(5,5143).
+char(m,5144).
+char(3,5145).
+char(4,5146).
+char(2,5147).
+char(2,5148).
+char(p,5149).
+char(o,5150).
+char(p,5151).
+char(7,5152).
+char(0,5153).
+char(2,5154).
+char(m,5155).
+char(o,5156).
+char(p,5157).
+char(o,5158).
+char(m,5159).
+char(o,5160).
+char(p,5161).
+char(o,5162).
+char(p,5163).
+char(7,5164).
+char(8,5165).
+char(8,5166).
+char(1,5167).
+char(c,5168).
+char(c,5169).
+char(p,5170).
+char(3,5171).
+char(0,5172).
+char(7,5173).
+char(0,5174).
+char(m,5175).
+char(9,5176).
+char(2,5177).
+char(5,5178).
+char(2,5179).
+char(c,5180).
+char(c,5181).
+char(m,5182).
+char(o,5183).
+char(4,5184).
+char(5,5185).
+char(8,5186).
+char(3,5187).
+char(p,5188).
+char(4,5189).
+char(7,5190).
+char(5,5191).
+char(7,5192).
+char(p,5193).
+char(o,5194).
+char(m,5195).
+char(o,5196).
+char(4,5197).
+char(4,5198).
+char(4,5199).
+char(9,5200).
+char(p,5201).
+char(o,5202).
+char(p,5203).
+char(o,5204).
+char(p,5205).
+char(o,5206).
+char(6,5207).
+char(4,5208).
+char(8,5209).
+char(9,5210).
+char(c,5211).
+char(c,5212).
+char(c,5213).
+char(p,5214).
+char(o,5215).
+char(p,5216).
+char(3,5217).
+char(2,5218).
+char(7,5219).
+char(3,5220).
+char(m,5221).
+char(o,5222).
+char(3,5223).
+char(4,5224).
+char(0,5225).
+char(1,5226).
+char(c,5227).
+char(m,5228).
+char(1,5229).
+char(4,5230).
+char(5,5231).
+char(2,5232).
+char(c,5233).
+char(p,5234).
+char(6,5235).
+char(1,5236).
+char(6,5237).
+char(2,5238).
+char(c,5239).
+char(p,5240).
+char(o,5241).
+char(o,5242).
+char(p,5243).
+char(o,5244).
+char(m,5245).
+char(o,5246).
+char(1,5247).
+char(6,5248).
+char(8,5249).
+char(1,5250).
+char(c,5251).
+char(m,5252).
+char(5,5253).
+char(1,5254).
+char(0,5255).
+char(3,5256).
+char(c,5257).
+char(c,5258).
+char(c,5259).
+char(c,5260).
+char(c,5261).
+char(c,5262).
+char(p,5263).
+char(9,5264).
+char(0,5265).
+char(3,5266).
+char(1,5267).
+char(m,5268).
+char(o,5269).
+char(p,5270).
+char(o,5271).
+char(o,5272).
+char(m,5273).
+char(o,5274).
+char(p,5275).
+char(o,5276).
+char(5,5277).
+char(9,5278).
+char(1,5279).
+char(3,5280).
+char(c,5281).
+char(m,5282).
+char(o,5283).
+char(p,5284).
+char(6,5285).
+char(5,5286).
+char(7,5287).
+char(4,5288).
+char(m,5289).
+char(o,5290).
+char(p,5291).
+char(3,5292).
+char(9,5293).
+char(0,5294).
+char(5,5295).
+char(m,5296).
+char(6,5297).
+char(2,5298).
+char(6,5299).
+char(4,5300).
+char(m,5301).
+char(1,5302).
+char(3,5303).
+char(6,5304).
+char(2,5305).
+char(m,5306).
+char(8,5307).
+char(7,5308).
+char(5,5309).
+char(9,5310).
+char(c,5311).
+char(m,5312).
+char(5,5313).
+char(2,5314).
+char(7,5315).
+char(0,5316).
+char(c,5317).
+char(p,5318).
+char(o,5319).
+char(p,5320).
+char(9,5321).
+char(3,5322).
+char(1,5323).
+char(1,5324).
+char(c,5325).
+char(p,5326).
+char(2,5327).
+char(7,5328).
+char(9,5329).
+char(2,5330).
+char(m,5331).
+char(9,5332).
+char(7,5333).
+char(2,5334).
+char(5,5335).
+char(c,5336).
+char(p,5337).
+char(o,5338).
+char(p,5339).
+char(8,5340).
+char(1,5341).
+char(0,5342).
+char(8,5343).
+char(p,5344).
+char(o,5345).
+char(3,5346).
+char(6,5347).
+char(7,5348).
+char(1,5349).
+char(p,5350).
+char(2,5351).
+char(4,5352).
+char(2,5353).
+char(3,5354).
+char(p,5355).
+char(o,5356).
+char(7,5357).
+char(5,5358).
+char(8,5359).
+char(4,5360).
+char(c,5361).
+char(m,5362).
+char(6,5363).
+char(9,5364).
+char(8,5365).
+char(6,5366).
+char(p,5367).
+char(o,5368).
+char(m,5369).
+char(1,5370).
+char(6,5371).
+char(7,5372).
+char(0,5373).
+char(m,5374).
+char(o,5375).
+char(o,5376).
+char(m,5377).
+char(6,5378).
+char(5,5379).
+char(0,5380).
+char(9,5381).
+char(p,5382).
+char(o,5383).
+char(o,5384).
+char(9,5385).
+char(0,5386).
+char(7,5387).
+char(5,5388).
+char(p,5389).
+char(o,5390).
+char(m,5391).
+char(7,5392).
+char(3,5393).
+char(3,5394).
+char(p,5395).
+char(o,5396).
+char(p,5397).
+char(o,5398).
+char(p,5399).
+char(1,5400).
+char(0,5401).
+char(2,5402).
+char(9,5403).
+char(c,5404).
+char(c,5405).
+char(c,5406).
+char(c,5407).
+char(p,5408).
+char(o,5409).
+char(m,5410).
+char(o,5411).
+char(1,5412).
+char(4,5413).
+char(3,5414).
+char(3,5415).
+char(c,5416).
+char(c,5417).
+char(m,5418).
+char(8,5419).
+char(1,5420).
+char(2,5421).
+char(0,5422).
+char(m,5423).
+char(2,5424).
+char(1,5425).
+char(3,5426).
+char(0,5427).
+char(c,5428).
+char(m,5429).
+char(2,5430).
+char(1,5431).
+char(5,5432).
+char(7,5433).
+char(p,5434).
+char(o,5435).
+char(m,5436).
+char(4,5437).
+char(8,5438).
+char(1,5439).
+char(2,5440).
+char(m,5441).
+char(9,5442).
+char(4,5443).
+char(1,5444).
+char(7,5445).
+char(p,5446).
+char(9,5447).
+char(4,5448).
+char(7,5449).
+char(0,5450).
+char(c,5451).
+char(p,5452).
+char(o,5453).
+char(o,5454).
+char(p,5455).
+char(o,5456).
+char(o,5457).
+char(m,5458).
+char(o,5459).
+char(o,5460).
+char(p,5461).
+char(6,5462).
+char(3,5463).
+char(6,5464).
+char(8,5465).
+char(c,5466).
+char(m,5467).
+char(4,5468).
+char(8,5469).
+char(4,5470).
+char(5,5471).
+char(c,5472).
+char(c,5473).
+char(p,5474).
+char(o,5475).
+char(p,5476).
+char(8,5477).
+char(5,5478).
+char(0,5479).
+char(8,5480).
+char(c,5481).
+char(p,5482).
+char(o,5483).
+char(m,5484).
+char(o,5485).
+char(p,5486).
+char(1,5487).
+char(0,5488).
+char(6,5489).
+char(8,5490).
+char(p,5491).
+char(o,5492).
+char(p,5493).
+char(8,5494).
+char(8,5495).
+char(2,5496).
+char(4,5497).
+char(p,5498).
+char(o,5499).
+char(m,5500).
+char(7,5501).
+char(5,5502).
+char(8,5503).
+char(3,5504).
+char(m,5505).
+char(2,5506).
+char(6,5507).
+char(2,5508).
+char(5,5509).
+char(c,5510).
+char(p,5511).
+char(6,5512).
+char(4,5513).
+char(1,5514).
+char(p,5515).
+char(6,5516).
+char(7,5517).
+char(2,5518).
+char(9,5519).
+char(p,5520).
+char(o,5521).
+char(m,5522).
+char(o,5523).
+char(8,5524).
+char(0,5525).
+char(6,5526).
+char(1,5527).
+char(p,5528).
+char(2,5529).
+char(1,5530).
+char(2,5531).
+char(9,5532).
+char(c,5533).
+char(c,5534).
+char(c,5535).
+char(c,5536).
+char(c,5537).
+char(c,5538).
+char(c,5539).
+char(m,5540).
+char(o,5541).
+char(o,5542).
+char(o,5543).
+char(m,5544).
+char(o,5545).
+char(p,5546).
+char(5,5547).
+char(3,5548).
+char(8,5549).
+char(5,5550).
+char(p,5551).
+char(o,5552).
+char(p,5553).
+char(o,5554).
+char(o,5555).
+char(o,5556).
+char(o,5557).
+char(8,5558).
+char(8,5559).
+char(6,5560).
+char(3,5561).
+char(p,5562).
+char(o,5563).
+char(m,5564).
+char(o,5565).
+char(1,5566).
+char(3,5567).
+char(3,5568).
+char(3,5569).
+char(p,5570).
+char(o,5571).
+char(o,5572).
+char(m,5573).
+char(o,5574).
+char(m,5575).
+char(o,5576).
+char(p,5577).
+char(o,5578).
+char(m,5579).
+char(6,5580).
+char(2,5581).
+char(2,5582).
+char(5,5583).
+char(p,5584).
+char(7,5585).
+char(5,5586).
+char(5,5587).
+char(3,5588).
+char(c,5589).
+char(c,5590).
+char(p,5591).
+char(o,5592).
+char(m,5593).
+char(1,5594).
+char(1,5595).
+char(6,5596).
+char(2,5597).
+char(m,5598).
+char(9,5599).
+char(4,5600).
+char(7,5601).
+char(7,5602).
+char(m,5603).
+char(o,5604).
+char(5,5605).
+char(0,5606).
+char(2,5607).
+char(6,5608).
+char(c,5609).
+char(c,5610).
+char(c,5611).
+char(p,5612).
+char(7,5613).
+char(1,5614).
+char(8,5615).
+char(6,5616).
+char(m,5617).
+char(o,5618).
+char(p,5619).
+char(9,5620).
+char(3,5621).
+char(2,5622).
+char(c,5623).
+char(c,5624).
+char(p,5625).
+char(8,5626).
+char(2,5627).
+char(0,5628).
+char(c,5629).
+char(p,5630).
+char(o,5631).
+char(m,5632).
+char(o,5633).
+char(m,5634).
+char(o,5635).
+char(o,5636).
+char(p,5637).
+char(o,5638).
+char(m,5639).
+char(9,5640).
+char(4,5641).
+char(5,5642).
+char(2,5643).
+char(c,5644).
+char(m,5645).
+char(1,5646).
+char(6,5647).
+char(2,5648).
+char(0,5649).
+char(c,5650).
+char(p,5651).
+char(o,5652).
+char(5,5653).
+char(6,5654).
+char(7,5655).
+char(1,5656).
+char(p,5657).
+char(o,5658).
+char(p,5659).
+char(o,5660).
+char(m,5661).
+char(2,5662).
+char(6,5663).
+char(8,5664).
+char(0,5665).
+char(c,5666).
+char(c,5667).
+char(p,5668).
+char(o,5669).
+char(p,5670).
+char(o,5671).
+char(p,5672).
+char(o,5673).
+char(p,5674).
+char(o,5675).
+char(p,5676).
+char(o,5677).
+char(m,5678).
+char(o,5679).
+char(2,5680).
+char(2,5681).
+char(5,5682).
+char(2,5683).
+char(c,5684).
+char(c,5685).
+char(c,5686).
+char(c,5687).
+char(c,5688).
+char(m,5689).
+char(o,5690).
+char(p,5691).
+char(4,5692).
+char(2,5693).
+char(7,5694).
+char(9,5695).
+char(m,5696).
+char(3,5697).
+char(1,5698).
+char(6,5699).
+char(5,5700).
+char(c,5701).
+char(c,5702).
+char(c,5703).
+char(c,5704).
+char(m,5705).
+char(6,5706).
+char(8,5707).
+char(0,5708).
+char(6,5709).
+char(m,5710).
+char(o,5711).
+char(m,5712).
+char(8,5713).
+char(8,5714).
+char(2,5715).
+char(4,5716).
+char(c,5717).
+char(c,5718).
+char(p,5719).
+char(7,5720).
+char(9,5721).
+char(7,5722).
+char(4,5723).
+char(c,5724).
+char(c,5725).
+char(m,5726).
+char(o,5727).
+char(p,5728).
+char(o,5729).
+char(o,5730).
+char(o,5731).
+char(m,5732).
+char(o,5733).
+char(m,5734).
+char(6,5735).
+char(3,5736).
+char(6,5737).
+char(3,5738).
+char(m,5739).
+char(o,5740).
+char(m,5741).
+char(9,5742).
+char(9,5743).
+char(9,5744).
+char(7,5745).
+char(c,5746).
+char(m,5747).
+char(o,5748).
+char(m,5749).
+char(o,5750).
+char(m,5751).
+char(o,5752).
+char(p,5753).
+char(o,5754).
+char(o,5755).
+char(3,5756).
+char(1,5757).
+char(9,5758).
+char(0,5759).
+char(c,5760).
+char(m,5761).
+char(o,5762).
+char(3,5763).
+char(4,5764).
+char(6,5765).
+char(5,5766).
+char(c,5767).
+char(p,5768).
+char(4,5769).
+char(0,5770).
+char(c,5771).
+char(p,5772).
+char(o,5773).
+char(m,5774).
+char(o,5775).
+char(o,5776).
+char(8,5777).
+char(2,5778).
+char(3,5779).
+char(6,5780).
+char(c,5781).
+char(m,5782).
+char(o,5783).
+char(m,5784).
+char(o,5785).
+char(m,5786).
+char(o,5787).
+char(p,5788).
+char(6,5789).
+char(6,5790).
+char(5,5791).
+char(c,5792).
+char(p,5793).
+char(9,5794).
+char(4,5795).
+char(6,5796).
+char(6,5797).
+char(c,5798).
+char(p,5799).
+char(7,5800).
+char(5,5801).
+char(0,5802).
+char(4,5803).
+char(p,5804).
+char(o,5805).
+char(m,5806).
+char(6,5807).
+char(0,5808).
+char(6,5809).
+char(2,5810).
+char(c,5811).
+char(m,5812).
+char(o,5813).
+char(m,5814).
+char(1,5815).
+char(8,5816).
+char(1,5817).
+char(0,5818).
+char(m,5819).
+char(o,5820).
+char(o,5821).
+char(p,5822).
+char(o,5823).
+char(p,5824).
+char(7,5825).
+char(7,5826).
+char(8,5827).
+char(1,5828).
+char(c,5829).
+char(c,5830).
+char(c,5831).
+char(c,5832).
+char(c,5833).
+char(p,5834).
+char(5,5835).
+char(6,5836).
+char(0,5837).
+char(m,5838).
+char(o,5839).
+char(p,5840).
+char(o,5841).
+char(m,5842).
+char(8,5843).
+char(8,5844).
+char(5,5845).
+char(2,5846).
+char(p,5847).
+char(4,5848).
+char(5,5849).
+char(2,5850).
+char(0,5851).
+char(p,5852).
+char(4,5853).
+char(7,5854).
+char(5,5855).
+char(3,5856).
+char(m,5857).
+char(o,5858).
+char(p,5859).
+char(o,5860).
+char(p,5861).
+char(o,5862).
+char(m,5863).
+char(o,5864).
+char(p,5865).
+char(6,5866).
+char(8,5867).
+char(7,5868).
+char(3,5869).
+char(m,5870).
+char(o,5871).
+char(m,5872).
+char(o,5873).
+char(m,5874).
+char(9,5875).
+char(7,5876).
+char(3,5877).
+char(9,5878).
+char(c,5879).
+char(c,5880).
+char(c,5881).
+char(c,5882).
+char(m,5883).
+char(4,5884).
+char(4,5885).
+char(0,5886).
+char(c,5887).
+char(m,5888).
+char(5,5889).
+char(9,5890).
+char(6,5891).
+char(1,5892).
+char(c,5893).
+char(c,5894).
+char(c,5895).
+char(c,5896).
+char(c,5897).
+char(p,5898).
+char(o,5899).
+char(m,5900).
+char(o,5901).
+char(4,5902).
+char(1,5903).
+char(4,5904).
+char(1,5905).
+char(m,5906).
+char(9,5907).
+char(6,5908).
+char(4,5909).
+char(0,5910).
+char(p,5911).
+char(7,5912).
+char(8,5913).
+char(7,5914).
+char(5,5915).
+char(m,5916).
+char(2,5917).
+char(1,5918).
+char(9,5919).
+char(2,5920).
+char(c,5921).
+char(c,5922).
+char(c,5923).
+char(c,5924).
+char(c,5925).
+char(c,5926).
+char(c,5927).
+char(p,5928).
+char(o,5929).
+char(m,5930).
+char(o,5931).
+char(o,5932).
+char(m,5933).
+char(3,5934).
+char(8,5935).
+char(7,5936).
+char(2,5937).
+char(m,5938).
+char(o,5939).
+char(m,5940).
+char(o,5941).
+char(m,5942).
+char(o,5943).
+char(m,5944).
+char(1,5945).
+char(0,5946).
+char(4,5947).
+char(m,5948).
+char(o,5949).
+char(p,5950).
+char(7,5951).
+char(7,5952).
+char(0,5953).
+char(3,5954).
+char(p,5955).
+char(o,5956).
+char(p,5957).
+char(7,5958).
+char(0,5959).
+char(8,5960).
+char(3,5961).
+char(c,5962).
+char(p,5963).
+char(o,5964).
+char(o,5965).
+char(2,5966).
+char(1,5967).
+char(3,5968).
+char(9,5969).
+char(c,5970).
+char(p,5971).
+char(o,5972).
+char(o,5973).
+char(p,5974).
+char(8,5975).
+char(5,5976).
+char(3,5977).
+char(7,5978).
+char(m,5979).
+char(5,5980).
+char(1,5981).
+char(5,5982).
+char(c,5983).
+char(m,5984).
+char(o,5985).
+char(o,5986).
+char(p,5987).
+char(o,5988).
+char(o,5989).
+char(p,5990).
+char(5,5991).
+char(6,5992).
+char(7,5993).
+char(c,5994).
+char(p,5995).
+char(9,5996).
+char(5,5997).
+char(8,5998).
+char(0,5999).
+char(c,6000).
+char(c,6001).
+char(m,6002).
+char(o,6003).
+char(p,6004).
+char(o,6005).
+char(m,6006).
+char(7,6007).
+char(8,6008).
+char(0,6009).
+char(5,6010).
+char(p,6011).
+char(o,6012).
+char(m,6013).
+char(2,6014).
+char(2,6015).
+char(9,6016).
+char(8,6017).
+char(c,6018).
+char(c,6019).
+char(m,6020).
+char(o,6021).
+char(m,6022).
+char(7,6023).
+char(1,6024).
+char(7,6025).
+char(0,6026).
+char(c,6027).
+char(m,6028).
+char(o,6029).
+char(p,6030).
+char(o,6031).
+char(m,6032).
+char(4,6033).
+char(6,6034).
+char(7,6035).
+char(0,6036).
+char(c,6037).
+char(c,6038).
+char(c,6039).
+char(c,6040).
+char(c,6041).
+char(p,6042).
+char(o,6043).
+char(p,6044).
+char(o,6045).
+char(4,6046).
+char(6,6047).
+char(8,6048).
+char(3,6049).
+char(p,6050).
+char(o,6051).
+char(m,6052).
+char(5,6053).
+char(4,6054).
+char(2,6055).
+char(6,6056).
+char(m,6057).
+char(6,6058).
+char(4,6059).
+char(2,6060).
+char(9,6061).
+char(c,6062).
+char(c,6063).
+char(c,6064).
+char(m,6065).
+char(3,6066).
+char(9,6067).
+char(1,6068).
+char(5,6069).
+char(c,6070).
+char(m,6071).
+char(3,6072).
+char(8,6073).
+char(0,6074).
+char(6,6075).
+char(c,6076).
+char(m,6077).
+char(3,6078).
+char(5,6079).
+char(8,6080).
+char(2,6081).
+char(p,6082).
+char(o,6083).
+char(p,6084).
+char(2,6085).
+char(8,6086).
+char(3,6087).
+char(9,6088).
+char(m,6089).
+char(o,6090).
+char(o,6091).
+char(m,6092).
+char(9,6093).
+char(5,6094).
+char(8,6095).
+char(9,6096).
+char(m,6097).
+char(6,6098).
+char(2,6099).
+char(8,6100).
+char(6,6101).
+char(c,6102).
+char(c,6103).
+char(m,6104).
+char(2,6105).
+char(7,6106).
+char(0,6107).
+char(6,6108).
+char(c,6109).
+char(m,6110).
+char(o,6111).
+char(p,6112).
+char(2,6113).
+char(6,6114).
+char(1,6115).
+char(9,6116).
+char(p,6117).
+char(o,6118).
+char(p,6119).
+char(o,6120).
+char(o,6121).
+char(m,6122).
+char(4,6123).
+char(2,6124).
+char(3,6125).
+char(2,6126).
+char(m,6127).
+char(o,6128).
+char(o,6129).
+char(m,6130).
+char(o,6131).
+char(m,6132).
+char(o,6133).
+char(o,6134).
+char(m,6135).
+char(2,6136).
+char(0,6137).
+char(8,6138).
+char(c,6139).
+char(m,6140).
+char(o,6141).
+char(p,6142).
+char(3,6143).
+char(8,6144).
+char(9,6145).
+char(5,6146).
+char(p,6147).
+char(o,6148).
+char(m,6149).
+char(7,6150).
+char(4,6151).
+char(1,6152).
+char(7,6153).
+char(p,6154).
+char(o,6155).
+char(m,6156).
+char(o,6157).
+char(o,6158).
+char(p,6159).
+char(o,6160).
+char(m,6161).
+char(6,6162).
+char(9,6163).
+char(1,6164).
+char(1,6165).
+char(c,6166).
+char(p,6167).
+char(o,6168).
+char(m,6169).
+char(2,6170).
+char(0,6171).
+char(5,6172).
+char(6,6173).
+char(c,6174).
+char(c,6175).
+char(c,6176).
+char(m,6177).
+char(o,6178).
+char(6,6179).
+char(7,6180).
+char(3,6181).
+char(7,6182).
+char(c,6183).
+char(c,6184).
+char(c,6185).
+char(c,6186).
+char(c,6187).
+char(c,6188).
+char(m,6189).
+char(o,6190).
+char(p,6191).
+char(2,6192).
+char(1,6193).
+char(0,6194).
+char(5,6195).
+char(c,6196).
+char(p,6197).
+char(8,6198).
+char(1,6199).
+char(7,6200).
+char(5,6201).
+char(c,6202).
+char(m,6203).
+char(4,6204).
+char(4,6205).
+char(5,6206).
+char(9,6207).
+char(p,6208).
+char(o,6209).
+char(p,6210).
+char(1,6211).
+char(1,6212).
+char(0,6213).
+char(6,6214).
+char(c,6215).
+char(m,6216).
+char(o,6217).
+char(m,6218).
+char(o,6219).
+char(m,6220).
+char(8,6221).
+char(4,6222).
+char(4,6223).
+char(5,6224).
+char(c,6225).
+char(c,6226).
+char(p,6227).
+char(o,6228).
+char(3,6229).
+char(1,6230).
+char(8,6231).
+char(2,6232).
+char(m,6233).
+char(6,6234).
+char(2,6235).
+char(6,6236).
+char(5,6237).
+char(m,6238).
+char(2,6239).
+char(5,6240).
+char(3,6241).
+char(3,6242).
+char(c,6243).
+char(c,6244).
+char(m,6245).
+char(o,6246).
+char(p,6247).
+char(6,6248).
+char(7,6249).
+char(6,6250).
+char(2,6251).
+char(p,6252).
+char(3,6253).
+char(9,6254).
+char(4,6255).
+char(7,6256).
+char(c,6257).
+char(c,6258).
+char(c,6259).
+char(p,6260).
+char(o,6261).
+char(m,6262).
+char(2,6263).
+char(3,6264).
+char(8,6265).
+char(7,6266).
+char(c,6267).
+char(p,6268).
+char(o,6269).
+char(p,6270).
+char(9,6271).
+char(2,6272).
+char(0,6273).
+char(3,6274).
+char(c,6275).
+char(c,6276).
+char(c,6277).
+char(c,6278).
+char(c,6279).
+char(c,6280).
+char(c,6281).
+char(m,6282).
+char(9,6283).
+char(3,6284).
+char(1,6285).
+char(6,6286).
+char(p,6287).
+char(1,6288).
+char(0,6289).
+char(9,6290).
+char(2,6291).
+char(c,6292).
+char(m,6293).
+char(1,6294).
+char(7,6295).
+char(6,6296).
+char(8,6297).
+char(m,6298).
+char(6,6299).
+char(8,6300).
+char(9,6301).
+char(9,6302).
+char(p,6303).
+char(o,6304).
+char(p,6305).
+char(o,6306).
+char(m,6307).
+char(7,6308).
+char(4,6309).
+char(0,6310).
+char(8,6311).
+char(c,6312).
+char(c,6313).
+char(p,6314).
+char(1,6315).
+char(7,6316).
+char(1,6317).
+char(0,6318).
+char(m,6319).
+char(o,6320).
+char(p,6321).
+char(1,6322).
+char(2,6323).
+char(6,6324).
+char(c,6325).
+char(c,6326).
+char(m,6327).
+char(6,6328).
+char(1,6329).
+char(8,6330).
+char(3,6331).
+char(p,6332).
+char(o,6333).
+char(o,6334).
+char(m,6335).
+char(o,6336).
+char(o,6337).
+char(p,6338).
+char(o,6339).
+char(p,6340).
+char(o,6341).
+char(m,6342).
+char(1,6343).
+char(4,6344).
+char(9,6345).
+char(4,6346).
+char(c,6347).
+char(m,6348).
+char(9,6349).
+char(9,6350).
+char(2,6351).
+char(8,6352).
+char(c,6353).
+char(c,6354).
+char(p,6355).
+char(o,6356).
+char(m,6357).
+char(7,6358).
+char(8,6359).
+char(9,6360).
+char(m,6361).
+char(8,6362).
+char(3,6363).
+char(7,6364).
+char(5,6365).
+char(c,6366).
+char(p,6367).
+char(5,6368).
+char(5,6369).
+char(2,6370).
+char(0,6371).
+char(c,6372).
+char(m,6373).
+char(o,6374).
+char(p,6375).
+char(o,6376).
+char(4,6377).
+char(6,6378).
+char(6,6379).
+char(3,6380).
+char(m,6381).
+char(8,6382).
+char(0,6383).
+char(8,6384).
+char(3,6385).
+char(c,6386).
+char(p,6387).
+char(o,6388).
+char(o,6389).
+char(5,6390).
+char(9,6391).
+char(4,6392).
+char(9,6393).
+char(c,6394).
+char(c,6395).
+char(c,6396).
+char(p,6397).
+char(4,6398).
+char(9,6399).
+char(7,6400).
+char(0,6401).
+char(c,6402).
+char(c,6403).
+char(c,6404).
+char(c,6405).
+char(c,6406).
+char(c,6407).
+char(p,6408).
+char(o,6409).
+char(p,6410).
+char(5,6411).
+char(4,6412).
+char(9,6413).
+char(8,6414).
+char(m,6415).
+char(o,6416).
+char(1,6417).
+char(5,6418).
+char(2,6419).
+char(9,6420).
+char(c,6421).
+char(c,6422).
+char(p,6423).
+char(7,6424).
+char(6,6425).
+char(4,6426).
+char(3,6427).
+char(c,6428).
+char(c,6429).
+char(m,6430).
+char(o,6431).
+char(p,6432).
+char(1,6433).
+char(2,6434).
+char(9,6435).
+char(5,6436).
+char(p,6437).
+char(o,6438).
+char(m,6439).
+char(7,6440).
+char(3,6441).
+char(6,6442).
+char(0,6443).
+char(m,6444).
+char(2,6445).
+char(0,6446).
+char(4,6447).
+char(5,6448).
+char(p,6449).
+char(6,6450).
+char(8,6451).
+char(5,6452).
+char(5,6453).
+char(c,6454).
+char(c,6455).
+char(c,6456).
+char(p,6457).
+char(o,6458).
+char(p,6459).
+char(4,6460).
+char(4,6461).
+char(4,6462).
+char(7,6463).
+char(c,6464).
+char(p,6465).
+char(o,6466).
+char(5,6467).
+char(7,6468).
+char(2,6469).
+char(5,6470).
+char(m,6471).
+char(o,6472).
+char(m,6473).
+char(1,6474).
+char(2,6475).
+char(6,6476).
+char(3,6477).
+char(c,6478).
+char(p,6479).
+char(5,6480).
+char(8,6481).
+char(9,6482).
+char(5,6483).
+char(p,6484).
+char(5,6485).
+char(7,6486).
+char(8,6487).
+char(1,6488).
+char(c,6489).
+char(c,6490).
+char(c,6491).
+char(c,6492).
+char(p,6493).
+char(o,6494).
+char(m,6495).
+char(o,6496).
+char(m,6497).
+char(o,6498).
+char(o,6499).
+char(p,6500).
+char(3,6501).
+char(7,6502).
+char(3,6503).
+char(4,6504).
+char(c,6505).
+char(c,6506).
+char(c,6507).
+char(m,6508).
+char(o,6509).
+char(p,6510).
+char(o,6511).
+char(m,6512).
+char(o,6513).
+char(m,6514).
+char(9,6515).
+char(2,6516).
+char(2,6517).
+char(3,6518).
+char(p,6519).
+char(o,6520).
+char(1,6521).
+char(7,6522).
+char(9,6523).
+char(3,6524).
+char(p,6525).
+char(o,6526).
+char(p,6527).
+char(7,6528).
+char(4,6529).
+char(5,6530).
+char(3,6531).
+char(p,6532).
+char(8,6533).
+char(5,6534).
+char(1,6535).
+char(8,6536).
+char(c,6537).
+char(m,6538).
+char(4,6539).
+char(3,6540).
+char(5,6541).
+char(9,6542).
+char(m,6543).
+char(6,6544).
+char(1,6545).
+char(3,6546).
+char(7,6547).
+char(c,6548).
+char(p,6549).
+char(o,6550).
+char(p,6551).
+char(o,6552).
+char(o,6553).
+char(p,6554).
+char(9,6555).
+char(6,6556).
+char(5,6557).
+char(4,6558).
+char(c,6559).
+char(c,6560).
+char(c,6561).
+char(c,6562).
+char(c,6563).
+char(m,6564).
+char(o,6565).
+char(m,6566).
+char(5,6567).
+char(0,6568).
+char(3,6569).
+char(1,6570).
+char(m,6571).
+char(o,6572).
+char(m,6573).
+char(4,6574).
+char(5,6575).
+char(5,6576).
+char(5,6577).
+char(c,6578).
+char(c,6579).
+char(p,6580).
+char(1,6581).
+char(9,6582).
+char(4,6583).
+char(0,6584).
+char(c,6585).
+char(p,6586).
+char(o,6587).
+char(p,6588).
+char(5,6589).
+char(4,6590).
+char(1,6591).
+char(8,6592).
+char(p,6593).
+char(5,6594).
+char(7,6595).
+char(3,6596).
+char(8,6597).
+char(c,6598).
+char(p,6599).
+char(o,6600).
+char(m,6601).
+char(o,6602).
+char(o,6603).
+char(m,6604).
+char(7,6605).
+char(3,6606).
+char(0,6607).
+char(0,6608).
+char(p,6609).
+char(6,6610).
+char(3,6611).
+char(3,6612).
+char(7,6613).
+char(c,6614).
+char(p,6615).
+char(8,6616).
+char(2,6617).
+char(2,6618).
+char(8,6619).
+char(p,6620).
+char(o,6621).
+char(2,6622).
+char(8,6623).
+char(6,6624).
+char(2,6625).
+char(c,6626).
+char(m,6627).
+char(o,6628).
+char(o,6629).
+char(m,6630).
+char(o,6631).
+char(p,6632).
+char(3,6633).
+char(1,6634).
+char(9,6635).
+char(8,6636).
+char(p,6637).
+char(o,6638).
+char(o,6639).
+char(m,6640).
+char(4,6641).
+char(7,6642).
+char(5,6643).
+char(8,6644).
+char(c,6645).
+char(c,6646).
+char(p,6647).
+char(4,6648).
+char(5,6649).
+char(5,6650).
+char(1,6651).
+char(m,6652).
+char(7,6653).
+char(4,6654).
+char(2,6655).
+char(6,6656).
+char(p,6657).
+char(4,6658).
+char(8,6659).
+char(2,6660).
+char(3,6661).
+char(c,6662).
+char(c,6663).
+char(c,6664).
+char(p,6665).
+char(7,6666).
+char(1,6667).
+char(5,6668).
+char(3,6669).
+char(p,6670).
+char(6,6671).
+char(5,6672).
+char(5,6673).
+char(2,6674).
+char(m,6675).
+char(o,6676).
+char(p,6677).
+char(o,6678).
+char(o,6679).
+char(p,6680).
+char(o,6681).
+char(p,6682).
+char(9,6683).
+char(1,6684).
+char(1,6685).
+char(8,6686).
+char(c,6687).
+char(m,6688).
+char(o,6689).
+char(p,6690).
+char(6,6691).
+char(9,6692).
+char(5,6693).
+char(2,6694).
+char(c,6695).
+char(c,6696).
+char(c,6697).
+char(c,6698).
+char(p,6699).
+char(8,6700).
+char(0,6701).
+char(3,6702).
+char(5,6703).
+char(p,6704).
+char(o,6705).
+char(m,6706).
+char(2,6707).
+char(2,6708).
+char(9,6709).
+char(p,6710).
+char(3,6711).
+char(9,6712).
+char(1,6713).
+char(0,6714).
+char(c,6715).
+char(c,6716).
+char(c,6717).
+char(c,6718).
+char(c,6719).
+char(c,6720).
+char(c,6721).
+char(c,6722).
+char(c,6723).
+char(p,6724).
+char(o,6725).
+char(p,6726).
+char(9,6727).
+char(8,6728).
+char(9,6729).
+char(4,6730).
+char(m,6731).
+char(4,6732).
+char(2,6733).
+char(1,6734).
+char(1,6735).
+char(c,6736).
+char(c,6737).
+char(p,6738).
+char(o,6739).
+char(m,6740).
+char(3,6741).
+char(0,6742).
+char(3,6743).
+char(1,6744).
+char(m,6745).
+char(o,6746).
+char(p,6747).
+char(1,6748).
+char(7,6749).
+char(5,6750).
+char(2,6751).
+char(c,6752).
+char(c,6753).
+char(c,6754).
+char(m,6755).
+char(o,6756).
+char(p,6757).
+char(o,6758).
+char(p,6759).
+char(3,6760).
+char(2,6761).
+char(2,6762).
+char(m,6763).
+char(o,6764).
+char(5,6765).
+char(6,6766).
+char(6,6767).
+char(8,6768).
+char(m,6769).
+char(9,6770).
+char(2,6771).
+char(8,6772).
+char(7,6773).
+char(m,6774).
+char(o,6775).
+char(o,6776).
+char(m,6777).
+char(5,6778).
+char(5,6779).
+char(7,6780).
+char(3,6781).
+char(c,6782).
+char(p,6783).
+char(o,6784).
+char(m,6785).
+char(o,6786).
+char(m,6787).
+char(o,6788).
+char(p,6789).
+char(o,6790).
+char(m,6791).
+char(1,6792).
+char(2,6793).
+char(9,6794).
+char(6,6795).
+char(p,6796).
+char(o,6797).
+char(m,6798).
+char(4,6799).
+char(1,6800).
+char(2,6801).
+char(0,6802).
+char(m,6803).
+char(4,6804).
+char(6,6805).
+char(5,6806).
+char(0,6807).
+char(m,6808).
+char(4,6809).
+char(1,6810).
+char(9,6811).
+char(1,6812).
+char(c,6813).
+char(c,6814).
+char(c,6815).
+char(c,6816).
+char(m,6817).
+char(9,6818).
+char(6,6819).
+char(8,6820).
+char(7,6821).
+char(c,6822).
+char(m,6823).
+char(2,6824).
+char(1,6825).
+char(1,6826).
+char(8,6827).
+char(p,6828).
+char(o,6829).
+char(p,6830).
+char(5,6831).
+char(1,6832).
+char(0,6833).
+char(4,6834).
+char(p,6835).
+char(o,6836).
+char(p,6837).
+char(8,6838).
+char(2,6839).
+char(1,6840).
+char(4,6841).
+char(c,6842).
+char(c,6843).
+char(m,6844).
+char(7,6845).
+char(3,6846).
+char(2,6847).
+char(9,6848).
+char(c,6849).
+char(p,6850).
+char(4,6851).
+char(4,6852).
+char(0,6853).
+char(1,6854).
+char(c,6855).
+char(c,6856).
+char(c,6857).
+char(p,6858).
+char(2,6859).
+char(4,6860).
+char(6,6861).
+char(7,6862).
+char(c,6863).
+char(m,6864).
+char(o,6865).
+char(5,6866).
+char(6,6867).
+char(4,6868).
+char(4,6869).
+char(c,6870).
+char(c,6871).
+char(p,6872).
+char(o,6873).
+char(o,6874).
+char(p,6875).
+char(o,6876).
+char(m,6877).
+char(6,6878).
+char(8,6879).
+char(4,6880).
+char(7,6881).
+char(m,6882).
+char(5,6883).
+char(5,6884).
+char(5,6885).
+char(0,6886).
+char(c,6887).
+char(m,6888).
+char(o,6889).
+char(8,6890).
+char(4,6891).
+char(0,6892).
+char(7,6893).
+char(p,6894).
+char(3,6895).
+char(7,6896).
+char(4,6897).
+char(9,6898).
+char(p,6899).
+char(o,6900).
+char(p,6901).
+char(o,6902).
+char(9,6903).
+char(3,6904).
+char(2,6905).
+char(0,6906).
+char(c,6907).
+char(m,6908).
+char(1,6909).
+char(9,6910).
+char(6,6911).
+char(6,6912).
+char(m,6913).
+char(o,6914).
+char(m,6915).
+char(1,6916).
+char(1,6917).
+char(1,6918).
+char(3,6919).
+char(c,6920).
+char(p,6921).
+char(5,6922).
+char(2,6923).
+char(8,6924).
+char(4,6925).
+char(p,6926).
+char(2,6927).
+char(3,6928).
+char(0,6929).
+char(5,6930).
+char(c,6931).
+char(c,6932).
+char(m,6933).
+char(3,6934).
+char(3,6935).
+char(3,6936).
+char(8,6937).
+char(c,6938).
+char(m,6939).
+char(5,6940).
+char(8,6941).
+char(4,6942).
+char(4,6943).
+char(m,6944).
+char(o,6945).
+char(m,6946).
+char(o,6947).
+char(o,6948).
+char(m,6949).
+char(o,6950).
+char(m,6951).
+char(5,6952).
+char(8,6953).
+char(1,6954).
+char(8,6955).
+char(m,6956).
+char(6,6957).
+char(5,6958).
+char(4,6959).
+char(3,6960).
+char(c,6961).
+char(p,6962).
+char(o,6963).
+char(p,6964).
+char(6,6965).
+char(2,6966).
+char(7,6967).
+char(9,6968).
+char(c,6969).
+char(c,6970).
+char(m,6971).
+char(o,6972).
+char(m,6973).
+char(6,6974).
+char(6,6975).
+char(0,6976).
+char(1,6977).
+char(c,6978).
+char(c,6979).
+char(c,6980).
+char(c,6981).
+char(p,6982).
+char(o,6983).
+char(p,6984).
+char(3,6985).
+char(5,6986).
+char(0,6987).
+char(0,6988).
+char(m,6989).
+char(o,6990).
+char(m,6991).
+char(o,6992).
+char(p,6993).
+char(o,6994).
+char(p,6995).
+char(o,6996).
+char(o,6997).
+char(m,6998).
+char(o,6999).
+char(6,7000).
+char(0,7001).
+char(4,7002).
+char(2,7003).
+char(m,7004).
+char(2,7005).
+char(4,7006).
+char(6,7007).
+char(4,7008).
+char(p,7009).
+char(5,7010).
+char(8,7011).
+char(4,7012).
+char(1,7013).
+char(p,7014).
+char(o,7015).
+char(m,7016).
+char(8,7017).
+char(4,7018).
+char(3,7019).
+char(5,7020).
+char(c,7021).
+char(p,7022).
+char(o,7023).
+char(m,7024).
+char(o,7025).
+char(o,7026).
+char(p,7027).
+char(o,7028).
+char(p,7029).
+char(o,7030).
+char(m,7031).
+char(o,7032).
+char(m,7033).
+char(o,7034).
+char(p,7035).
+char(o,7036).
+char(m,7037).
+char(3,7038).
+char(8,7039).
+char(1,7040).
+char(5,7041).
+char(c,7042).
+char(m,7043).
+char(1,7044).
+char(9,7045).
+char(4,7046).
+char(9,7047).
+char(m,7048).
+char(o,7049).
+char(6,7050).
+char(8,7051).
+char(2,7052).
+char(3,7053).
+char(c,7054).
+char(p,7055).
+char(o,7056).
+char(m,7057).
+char(8,7058).
+char(7,7059).
+char(9,7060).
+char(6,7061).
+char(p,7062).
+char(6,7063).
+char(7,7064).
+char(5,7065).
+char(5,7066).
+char(m,7067).
+char(1,7068).
+char(6,7069).
+char(p,7070).
+char(o,7071).
+char(p,7072).
+char(o,7073).
+char(p,7074).
+char(5,7075).
+char(1,7076).
+char(1,7077).
+char(5,7078).
+char(p,7079).
+char(o,7080).
+char(p,7081).
+char(6,7082).
+char(2,7083).
+char(4,7084).
+char(4,7085).
+char(c,7086).
+char(c,7087).
+char(p,7088).
+char(o,7089).
+char(m,7090).
+char(o,7091).
+char(p,7092).
+char(5,7093).
+char(1,7094).
+char(7,7095).
+char(1,7096).
+char(c,7097).
+char(p,7098).
+char(o,7099).
+char(m,7100).
+char(7,7101).
+char(2,7102).
+char(8,7103).
+char(9,7104).
+char(m,7105).
+char(3,7106).
+char(8,7107).
+char(2,7108).
+char(9,7109).
+char(m,7110).
+char(9,7111).
+char(9,7112).
+char(1,7113).
+char(9,7114).
+char(m,7115).
+char(6,7116).
+char(8,7117).
+char(0,7118).
+char(2,7119).
+char(c,7120).
+char(c,7121).
+char(c,7122).
+char(c,7123).
+char(m,7124).
+char(o,7125).
+char(p,7126).
+char(o,7127).
+char(o,7128).
+char(m,7129).
+char(5,7130).
+char(6,7131).
+char(6,7132).
+char(c,7133).
+char(p,7134).
+char(o,7135).
+char(o,7136).
+char(p,7137).
+char(o,7138).
+char(m,7139).
+char(o,7140).
+char(m,7141).
+char(2,7142).
+char(9,7143).
+char(7,7144).
+char(5,7145).
+char(p,7146).
+char(3,7147).
+char(c,7148).
+char(c,7149).
+char(p,7150).
+char(o,7151).
+char(p,7152).
+char(o,7153).
+char(6,7154).
+char(8,7155).
+char(9,7156).
+char(4,7157).
+char(c,7158).
+char(c,7159).
+char(c,7160).
+char(c,7161).
+char(c,7162).
+char(c,7163).
+char(c,7164).
+char(c,7165).
+char(c,7166).
+char(c,7167).
+char(c,7168).
+char(c,7169).
+char(m,7170).
+char(8,7171).
+char(2,7172).
+char(6,7173).
+char(8,7174).
+char(m,7175).
+char(o,7176).
+char(o,7177).
+char(m,7178).
+char(o,7179).
+char(m,7180).
+char(o,7181).
+char(1,7182).
+char(6,7183).
+char(6,7184).
+char(5,7185).
+char(p,7186).
+char(6,7187).
+char(4,7188).
+char(9,7189).
+char(p,7190).
+char(o,7191).
+char(p,7192).
+char(8,7193).
+char(9,7194).
+char(c,7195).
+char(c,7196).
+char(c,7197).
+char(m,7198).
+char(o,7199).
+char(m,7200).
+char(5,7201).
+char(7,7202).
+char(1,7203).
+char(1,7204).
+char(p,7205).
+char(o,7206).
+char(6,7207).
+char(1,7208).
+char(7,7209).
+char(p,7210).
+char(1,7211).
+char(0,7212).
+char(8,7213).
+char(p,7214).
+char(4,7215).
+char(5,7216).
+char(9,7217).
+char(1,7218).
+char(c,7219).
+char(c,7220).
+char(c,7221).
+char(c,7222).
+char(c,7223).
+char(p,7224).
+char(6,7225).
+char(8,7226).
+char(7,7227).
+char(6,7228).
+char(c,7229).
+char(c,7230).
+char(c,7231).
+char(c,7232).
+char(p,7233).
+char(6,7234).
+char(7,7235).
+char(8,7236).
+char(8,7237).
+char(c,7238).
+char(c,7239).
+char(p,7240).
+char(o,7241).
+char(p,7242).
+char(8,7243).
+char(0,7244).
+char(7,7245).
+char(1,7246).
+char(m,7247).
+char(o,7248).
+char(m,7249).
+char(o,7250).
+char(o,7251).
+char(m,7252).
+char(2,7253).
+char(8,7254).
+char(2,7255).
+char(0,7256).
+char(c,7257).
+char(c,7258).
+char(m,7259).
+char(2,7260).
+char(4,7261).
+char(0,7262).
+char(3,7263).
+char(p,7264).
+char(o,7265).
+char(7,7266).
+char(9,7267).
+char(6,7268).
+char(7,7269).
+char(c,7270).
+char(p,7271).
+char(o,7272).
+char(p,7273).
+char(o,7274).
+char(7,7275).
+char(9,7276).
+char(2,7277).
+char(5,7278).
+char(m,7279).
+char(9,7280).
+char(0,7281).
+char(1,7282).
+char(4,7283).
+char(p,7284).
+char(o,7285).
+char(o,7286).
+char(p,7287).
+char(1,7288).
+char(2,7289).
+char(8,7290).
+char(9,7291).
+char(c,7292).
+char(c,7293).
+char(c,7294).
+char(m,7295).
+char(o,7296).
+char(p,7297).
+char(o,7298).
+char(m,7299).
+char(o,7300).
+char(m,7301).
+char(1,7302).
+char(6,7303).
+char(7,7304).
+char(5,7305).
+char(m,7306).
+char(8,7307).
+char(1,7308).
+char(7,7309).
+char(7,7310).
+char(c,7311).
+char(m,7312).
+char(9,7313).
+char(1,7314).
+char(0,7315).
+char(7,7316).
+char(c,7317).
+char(c,7318).
+char(c,7319).
+char(c,7320).
+char(c,7321).
+char(m,7322).
+char(5,7323).
+char(7,7324).
+char(7,7325).
+char(1,7326).
+char(p,7327).
+char(o,7328).
+char(o,7329).
+char(m,7330).
+char(o,7331).
+char(p,7332).
+char(8,7333).
+char(7,7334).
+char(3,7335).
+char(6,7336).
+char(p,7337).
+char(6,7338).
+char(3,7339).
+char(4,7340).
+char(3,7341).
+char(m,7342).
+char(o,7343).
+char(o,7344).
+char(p,7345).
+char(o,7346).
+char(p,7347).
+char(3,7348).
+char(0,7349).
+char(0,7350).
+char(0,7351).
+char(c,7352).
+char(c,7353).
+char(c,7354).
+char(c,7355).
+char(p,7356).
+char(5,7357).
+char(6,7358).
+char(0,7359).
+char(0,7360).
+char(m,7361).
+char(o,7362).
+char(m,7363).
+char(7,7364).
+char(5,7365).
+char(0,7366).
+char(0,7367).
+char(c,7368).
+char(p,7369).
+char(6,7370).
+char(0,7371).
+char(3,7372).
+char(3,7373).
+char(c,7374).
+char(m,7375).
+char(1,7376).
+char(2,7377).
+char(0,7378).
+char(2,7379).
+char(p,7380).
+char(2,7381).
+char(6,7382).
+char(2,7383).
+char(9,7384).
+char(m,7385).
+char(2,7386).
+char(4,7387).
+char(6,7388).
+char(p,7389).
+char(7,7390).
+char(7,7391).
+char(9,7392).
+char(6,7393).
+char(p,7394).
+char(2,7395).
+char(6,7396).
+char(3,7397).
+char(2,7398).
+char(m,7399).
+char(8,7400).
+char(9,7401).
+char(5,7402).
+char(c,7403).
+char(m,7404).
+char(4,7405).
+char(2,7406).
+char(9,7407).
+char(5,7408).
+char(c,7409).
+char(c,7410).
+char(m,7411).
+char(9,7412).
+char(4,7413).
+char(3,7414).
+char(1,7415).
+char(c,7416).
+char(c,7417).
+char(c,7418).
+char(p,7419).
+char(o,7420).
+char(p,7421).
+char(o,7422).
+char(5,7423).
+char(3,7424).
+char(1,7425).
+char(8,7426).
+char(c,7427).
+char(c,7428).
+char(p,7429).
+char(5,7430).
+char(3,7431).
+char(9,7432).
+char(7,7433).
+char(p,7434).
+char(o,7435).
+char(m,7436).
+char(o,7437).
+char(m,7438).
+char(1,7439).
+char(7,7440).
+char(8,7441).
+char(8,7442).
+char(c,7443).
+char(m,7444).
+char(o,7445).
+char(o,7446).
+char(o,7447).
+char(6,7448).
+char(7,7449).
+char(5,7450).
+char(5,7451).
+char(p,7452).
+char(o,7453).
+char(o,7454).
+char(m,7455).
+char(6,7456).
+char(5,7457).
+char(7,7458).
+char(8,7459).
+char(m,7460).
+char(o,7461).
+char(o,7462).
+char(m,7463).
+char(9,7464).
+char(8,7465).
+char(2,7466).
+char(9,7467).
+char(p,7468).
+char(o,7469).
+char(7,7470).
+char(3,7471).
+char(3,7472).
+char(1,7473).
+char(c,7474).
+char(c,7475).
+char(c,7476).
+char(c,7477).
+char(p,7478).
+char(o,7479).
+char(p,7480).
+char(9,7481).
+char(9,7482).
+char(4,7483).
+char(2,7484).
+char(c,7485).
+char(c,7486).
+char(m,7487).
+char(2,7488).
+char(1,7489).
+char(1,7490).
+char(7,7491).
+char(c,7492).
+char(c,7493).
+char(p,7494).
+char(3,7495).
+char(9,7496).
+char(2,7497).
+char(0,7498).
+char(c,7499).
+char(p,7500).
+char(5,7501).
+char(2,7502).
+char(9,7503).
+char(6,7504).
+char(c,7505).
+char(p,7506).
+char(o,7507).
+char(m,7508).
+char(5,7509).
+char(0,7510).
+char(4,7511).
+char(3,7512).
+char(c,7513).
+char(c,7514).
+char(c,7515).
+char(m,7516).
+char(1,7517).
+char(0,7518).
+char(9,7519).
+char(7,7520).
+char(c,7521).
+char(c,7522).
+char(c,7523).
+char(m,7524).
+char(7,7525).
+char(1,7526).
+char(5,7527).
+char(5,7528).
+char(c,7529).
+char(c,7530).
+char(c,7531).
+char(c,7532).
+char(m,7533).
+char(o,7534).
+char(m,7535).
+char(5,7536).
+char(4,7537).
+char(6,7538).
+char(9,7539).
+char(p,7540).
+char(o,7541).
+char(9,7542).
+char(8,7543).
+char(3,7544).
+char(1,7545).
+char(c,7546).
+char(c,7547).
+char(m,7548).
+char(2,7549).
+char(9,7550).
+char(7,7551).
+char(c,7552).
+char(m,7553).
+char(o,7554).
+char(m,7555).
+char(3,7556).
+char(0,7557).
+char(9,7558).
+char(9,7559).
+char(p,7560).
+char(3,7561).
+char(0,7562).
+char(0,7563).
+char(9,7564).
+char(m,7565).
+char(6,7566).
+char(0,7567).
+char(6,7568).
+char(5,7569).
+char(c,7570).
+char(p,7571).
+char(9,7572).
+char(3,7573).
+char(8,7574).
+char(0,7575).
+char(m,7576).
+char(o,7577).
+char(p,7578).
+char(2,7579).
+char(2,7580).
+char(0,7581).
+char(0,7582).
+char(c,7583).
+char(p,7584).
+char(o,7585).
+char(p,7586).
+char(5,7587).
+char(3,7588).
+char(0,7589).
+char(4,7590).
+char(c,7591).
+char(m,7592).
+char(o,7593).
+char(m,7594).
+char(5,7595).
+char(1,7596).
+char(5,7597).
+char(3,7598).
+char(p,7599).
+char(9,7600).
+char(9,7601).
+char(0,7602).
+char(8,7603).
+char(c,7604).
+char(c,7605).
+char(p,7606).
+char(o,7607).
+char(p,7608).
+char(o,7609).
+char(m,7610).
+char(6,7611).
+char(3,7612).
+char(5,7613).
+char(8,7614).
+char(p,7615).
+char(5,7616).
+char(7,7617).
+char(2,7618).
+char(1,7619).
+char(c,7620).
+char(c,7621).
+char(m,7622).
+char(3,7623).
+char(9,7624).
+char(9,7625).
+char(5,7626).
+char(m,7627).
+char(o,7628).
+char(m,7629).
+char(2,7630).
+char(2,7631).
+char(3,7632).
+char(7,7633).
+char(p,7634).
+char(8,7635).
+char(8,7636).
+char(1,7637).
+char(m,7638).
+char(8,7639).
+char(8,7640).
+char(6,7641).
+char(3,7642).
+char(p,7643).
+char(o,7644).
+char(m,7645).
+char(2,7646).
+char(0,7647).
+char(3,7648).
+char(1,7649).
+char(c,7650).
+char(c,7651).
+char(c,7652).
+char(c,7653).
+char(p,7654).
+char(o,7655).
+char(m,7656).
+char(o,7657).
+char(6,7658).
+char(7,7659).
+char(2,7660).
+char(6,7661).
+char(c,7662).
+char(m,7663).
+char(o,7664).
+char(9,7665).
+char(6,7666).
+char(9,7667).
+char(7,7668).
+char(p,7669).
+char(2,7670).
+char(5,7671).
+char(4,7672).
+char(3,7673).
+char(c,7674).
+char(c,7675).
+char(c,7676).
+char(m,7677).
+char(4,7678).
+char(3,7679).
+char(3,7680).
+char(7,7681).
+char(c,7682).
+char(m,7683).
+char(o,7684).
+char(o,7685).
+char(m,7686).
+char(5,7687).
+char(3,7688).
+char(0,7689).
+char(4,7690).
+char(c,7691).
+char(c,7692).
+char(m,7693).
+char(1,7694).
+char(6,7695).
+char(7,7696).
+char(1,7697).
+char(p,7698).
+char(3,7699).
+char(7,7700).
+char(8,7701).
+char(3,7702).
+char(m,7703).
+char(7,7704).
+char(3,7705).
+char(2,7706).
+char(m,7707).
+char(o,7708).
+char(m,7709).
+char(o,7710).
+char(m,7711).
+char(o,7712).
+char(p,7713).
+char(o,7714).
+char(p,7715).
+char(o,7716).
+char(5,7717).
+char(8,7718).
+char(9,7719).
+char(9,7720).
+char(p,7721).
+char(9,7722).
+char(6,7723).
+char(8,7724).
+char(1,7725).
+char(m,7726).
+char(o,7727).
+char(o,7728).
+char(m,7729).
+char(8,7730).
+char(7,7731).
+char(8,7732).
+char(2,7733).
+char(c,7734).
+char(m,7735).
+char(o,7736).
+char(p,7737).
+char(o,7738).
+char(p,7739).
+char(9,7740).
+char(1,7741).
+char(7,7742).
+char(3,7743).
+char(p,7744).
+char(o,7745).
+char(8,7746).
+char(3,7747).
+char(0,7748).
+char(4,7749).
+char(c,7750).
+char(m,7751).
+char(5,7752).
+char(8,7753).
+char(1,7754).
+char(0,7755).
+char(m,7756).
+char(2,7757).
+char(3,7758).
+char(8,7759).
+char(6,7760).
+char(m,7761).
+char(5,7762).
+char(0,7763).
+char(3,7764).
+char(0,7765).
+char(c,7766).
+char(m,7767).
+char(6,7768).
+char(6,7769).
+char(1,7770).
+char(0,7771).
+char(m,7772).
+char(1,7773).
+char(9,7774).
+char(1,7775).
+char(c,7776).
+char(m,7777).
+char(1,7778).
+char(6,7779).
+char(3,7780).
+char(6,7781).
+char(c,7782).
+char(c,7783).
+char(c,7784).
+char(p,7785).
+char(o,7786).
+char(o,7787).
+char(o,7788).
+char(7,7789).
+char(3,7790).
+char(3,7791).
+char(1,7792).
+char(c,7793).
+char(c,7794).
+char(c,7795).
+char(m,7796).
+char(6,7797).
+char(3,7798).
+char(7,7799).
+char(7,7800).
+char(c,7801).
+char(c,7802).
+char(c,7803).
+char(p,7804).
+char(o,7805).
+char(p,7806).
+char(5,7807).
+char(9,7808).
+char(c,7809).
+char(c,7810).
+char(c,7811).
+char(m,7812).
+char(o,7813).
+char(8,7814).
+char(0,7815).
+char(8,7816).
+char(1,7817).
+char(m,7818).
+char(5,7819).
+char(4,7820).
+char(8,7821).
+char(7,7822).
+char(p,7823).
+char(o,7824).
+char(4,7825).
+char(2,7826).
+char(3,7827).
+char(8,7828).
+char(m,7829).
+char(6,7830).
+char(9,7831).
+char(8,7832).
+char(4,7833).
+char(c,7834).
+char(m,7835).
+char(5,7836).
+char(8,7837).
+char(1,7838).
+char(8,7839).
+char(m,7840).
+char(o,7841).
+char(5,7842).
+char(3,7843).
+char(3,7844).
+char(5,7845).
+char(m,7846).
+char(9,7847).
+char(9,7848).
+char(4,7849).
+char(7,7850).
+char(c,7851).
+char(c,7852).
+char(m,7853).
+char(o,7854).
+char(p,7855).
+char(o,7856).
+char(p,7857).
+char(3,7858).
+char(7,7859).
+char(0,7860).
+char(m,7861).
+char(o,7862).
+char(p,7863).
+char(o,7864).
+char(p,7865).
+char(7,7866).
+char(1,7867).
+char(4,7868).
+char(c,7869).
+char(c,7870).
+char(p,7871).
+char(o,7872).
+char(o,7873).
+char(m,7874).
+char(o,7875).
+char(p,7876).
+char(3,7877).
+char(0,7878).
+char(9,7879).
+char(8,7880).
+char(c,7881).
+char(c,7882).
+char(c,7883).
+char(c,7884).
+char(m,7885).
+char(3,7886).
+char(5,7887).
+char(2,7888).
+char(6,7889).
+char(c,7890).
+char(c,7891).
+char(c,7892).
+char(c,7893).
+char(c,7894).
+char(p,7895).
+char(6,7896).
+char(0,7897).
+char(7,7898).
+char(4,7899).
+char(p,7900).
+char(3,7901).
+char(4,7902).
+char(9,7903).
+char(0,7904).
+char(m,7905).
+char(3,7906).
+char(4,7907).
+char(6,7908).
+char(0,7909).
+char(m,7910).
+char(8,7911).
+char(9,7912).
+char(6,7913).
+char(0,7914).
+char(m,7915).
+char(8,7916).
+char(0,7917).
+char(3,7918).
+char(3,7919).
+char(c,7920).
+char(c,7921).
+char(c,7922).
+char(p,7923).
+char(3,7924).
+char(4,7925).
+char(2,7926).
+char(c,7927).
+char(c,7928).
+char(m,7929).
+char(7,7930).
+char(6,7931).
+char(9,7932).
+char(9,7933).
+char(m,7934).
+char(o,7935).
+char(p,7936).
+char(9,7937).
+char(3,7938).
+char(3,7939).
+char(6,7940).
+char(m,7941).
+char(1,7942).
+char(7,7943).
+char(3,7944).
+char(9,7945).
+char(c,7946).
+char(m,7947).
+char(9,7948).
+char(3,7949).
+char(1,7950).
+char(4,7951).
+char(m,7952).
+char(7,7953).
+char(0,7954).
+char(1,7955).
+char(9,7956).
+char(c,7957).
+char(c,7958).
+char(p,7959).
+char(3,7960).
+char(6,7961).
+char(6,7962).
+char(7,7963).
+char(p,7964).
+char(4,7965).
+char(9,7966).
+char(0,7967).
+char(9,7968).
+char(c,7969).
+char(c,7970).
+char(p,7971).
+char(o,7972).
+char(7,7973).
+char(8,7974).
+char(6,7975).
+char(m,7976).
+char(o,7977).
+char(m,7978).
+char(8,7979).
+char(7,7980).
+char(6,7981).
+char(4,7982).
+char(c,7983).
+char(c,7984).
+char(c,7985).
+char(c,7986).
+char(p,7987).
+char(2,7988).
+char(9,7989).
+char(0,7990).
+char(0,7991).
+char(c,7992).
+char(c,7993).
+char(p,7994).
+char(o,7995).
+char(p,7996).
+char(o,7997).
+char(o,7998).
+char(m,7999).
+char(8,8000).
+char(3,8001).
+char(1,8002).
+char(7,8003).
+char(c,8004).
+char(m,8005).
+char(9,8006).
+char(6,8007).
+char(7,8008).
+char(1,8009).
+char(p,8010).
+char(o,8011).
+char(m,8012).
+char(5,8013).
+char(0,8014).
+char(9,8015).
+char(m,8016).
+char(8,8017).
+char(8,8018).
+char(4,8019).
+char(7,8020).
+char(m,8021).
+char(8,8022).
+char(5,8023).
+char(3,8024).
+char(0,8025).
+char(p,8026).
+char(2,8027).
+char(3,8028).
+char(3,8029).
+char(5,8030).
+char(p,8031).
+char(o,8032).
+char(p,8033).
+char(5,8034).
+char(3,8035).
+char(7,8036).
+char(7,8037).
+char(m,8038).
+char(8,8039).
+char(0,8040).
+char(1,8041).
+char(p,8042).
+char(8,8043).
+char(7,8044).
+char(2,8045).
+char(9,8046).
+char(c,8047).
+char(p,8048).
+char(o,8049).
+char(p,8050).
+char(6,8051).
+char(3,8052).
+char(5,8053).
+char(3,8054).
+char(m,8055).
+char(9,8056).
+char(3,8057).
+char(1,8058).
+char(7,8059).
+char(p,8060).
+char(o,8061).
+char(p,8062).
+char(o,8063).
+char(o,8064).
+char(p,8065).
+char(3,8066).
+char(3,8067).
+char(0,8068).
+char(5,8069).
+char(p,8070).
+char(o,8071).
+char(p,8072).
+char(o,8073).
+char(p,8074).
+char(3,8075).
+char(9,8076).
+char(9,8077).
+char(4,8078).
+char(c,8079).
+char(m,8080).
+char(3,8081).
+char(9,8082).
+char(3,8083).
+char(9,8084).
+char(m,8085).
+char(o,8086).
+char(p,8087).
+char(6,8088).
+char(3,8089).
+char(2,8090).
+char(7,8091).
+char(c,8092).
+char(p,8093).
+char(6,8094).
+char(4,8095).
+char(9,8096).
+char(6,8097).
+char(c,8098).
+char(c,8099).
+char(p,8100).
+char(8,8101).
+char(1,8102).
+char(5,8103).
+char(7,8104).
+char(m,8105).
+char(8,8106).
+char(2,8107).
+char(2,8108).
+char(9,8109).
+char(c,8110).
+char(m,8111).
+char(o,8112).
+char(m,8113).
+char(o,8114).
+char(m,8115).
+char(7,8116).
+char(5,8117).
+char(5,8118).
+char(9,8119).
+char(p,8120).
+char(1,8121).
+char(5,8122).
+char(6,8123).
+char(5,8124).
+char(c,8125).
+char(m,8126).
+char(o,8127).
+char(1,8128).
+char(2,8129).
+char(6,8130).
+char(1,8131).
+char(c,8132).
+char(c,8133).
+char(c,8134).
+char(m,8135).
+char(o,8136).
+char(p,8137).
+char(o,8138).
+char(o,8139).
+char(m,8140).
+char(8,8141).
+char(0,8142).
+char(4,8143).
+char(0,8144).
+char(c,8145).
+char(p,8146).
+char(o,8147).
+char(m,8148).
+char(9,8149).
+char(1,8150).
+char(8,8151).
+char(7,8152).
+char(p,8153).
+char(o,8154).
+char(o,8155).
+char(p,8156).
+char(4,8157).
+char(0,8158).
+char(1,8159).
+char(2,8160).
+char(c,8161).
+char(c,8162).
+char(m,8163).
+char(o,8164).
+char(m,8165).
+char(3,8166).
+char(5,8167).
+char(9,8168).
+char(7,8169).
+char(m,8170).
+char(7,8171).
+char(7,8172).
+char(5,8173).
+char(3,8174).
+char(m,8175).
+char(o,8176).
+char(2,8177).
+char(4,8178).
+char(5,8179).
+char(4,8180).
+char(m,8181).
+char(o,8182).
+char(9,8183).
+char(9,8184).
+char(7,8185).
+char(9,8186).
+char(p,8187).
+char(o,8188).
+char(m,8189).
+char(9,8190).
+char(8,8191).
+char(1,8192).
+char(1,8193).
+char(p,8194).
+char(o,8195).
+char(5,8196).
+char(2,8197).
+char(3,8198).
+char(7,8199).
+char(p,8200).
+char(o,8201).
+char(m,8202).
+char(o,8203).
+char(p,8204).
+char(1,8205).
+char(1,8206).
+char(4,8207).
+char(2,8208).
+char(c,8209).
+char(c,8210).
+char(c,8211).
+char(m,8212).
+char(2,8213).
+char(7,8214).
+char(6,8215).
+char(9,8216).
+char(p,8217).
+char(8,8218).
+char(8,8219).
+char(0,8220).
+char(9,8221).
+char(p,8222).
+char(7,8223).
+char(1,8224).
+char(0,8225).
+char(2,8226).
+char(p,8227).
+char(9,8228).
+char(0,8229).
+char(8,8230).
+char(1,8231).
+char(c,8232).
+char(p,8233).
+char(1,8234).
+char(4,8235).
+char(7,8236).
+char(m,8237).
+char(o,8238).
+char(m,8239).
+char(o,8240).
+char(6,8241).
+char(7,8242).
+char(3,8243).
+char(0,8244).
+char(c,8245).
+char(p,8246).
+char(7,8247).
+char(4,8248).
+char(2,8249).
+char(5,8250).
+char(p,8251).
+char(o,8252).
+char(m,8253).
+char(9,8254).
+char(1,8255).
+char(8,8256).
+char(7,8257).
+char(c,8258).
+char(p,8259).
+char(o,8260).
+char(p,8261).
+char(7,8262).
+char(8,8263).
+char(0,8264).
+char(3,8265).
+char(c,8266).
+char(m,8267).
+char(2,8268).
+char(9,8269).
+char(2,8270).
+char(4,8271).
+char(p,8272).
+char(o,8273).
+char(m,8274).
+char(o,8275).
+char(p,8276).
+char(4,8277).
+char(7,8278).
+char(1,8279).
+char(2,8280).
+char(c,8281).
+char(p,8282).
+char(o,8283).
+char(p,8284).
+char(1,8285).
+char(8,8286).
+char(1,8287).
+char(7,8288).
+char(p,8289).
+char(9,8290).
+char(7,8291).
+char(2,8292).
+char(1,8293).
+char(c,8294).
+char(m,8295).
+char(1,8296).
+char(9,8297).
+char(5,8298).
+char(1,8299).
+char(p,8300).
+char(o,8301).
+char(p,8302).
+char(9,8303).
+char(3,8304).
+char(4,8305).
+char(7,8306).
+char(p,8307).
+char(8,8308).
+char(7,8309).
+char(4,8310).
+char(6,8311).
+char(c,8312).
+char(c,8313).
+char(c,8314).
+char(c,8315).
+char(c,8316).
+char(c,8317).
+char(p,8318).
+char(o,8319).
+char(p,8320).
+char(3,8321).
+char(8,8322).
+char(8,8323).
+char(0,8324).
+char(c,8325).
+char(m,8326).
+char(o,8327).
+char(p,8328).
+char(o,8329).
+char(p,8330).
+char(9,8331).
+char(4,8332).
+char(9,8333).
+char(5,8334).
+char(p,8335).
+char(1,8336).
+char(5,8337).
+char(5,8338).
+char(8,8339).
+char(c,8340).
+char(m,8341).
+char(4,8342).
+char(7,8343).
+char(5,8344).
+char(5,8345).
+char(c,8346).
+char(c,8347).
+char(c,8348).
+char(c,8349).
+char(c,8350).
+char(c,8351).
+char(c,8352).
+char(m,8353).
+char(o,8354).
+char(p,8355).
+char(o,8356).
+char(6,8357).
+char(3,8358).
+char(4,8359).
+char(0,8360).
+char(m,8361).
+char(o,8362).
+char(o,8363).
+char(p,8364).
+char(5,8365).
+char(7,8366).
+char(0,8367).
+char(1,8368).
+char(c,8369).
+char(m,8370).
+char(6,8371).
+char(6,8372).
+char(9,8373).
+char(4,8374).
+char(c,8375).
+char(m,8376).
+char(9,8377).
+char(8,8378).
+char(7,8379).
+char(c,8380).
+char(c,8381).
+char(c,8382).
+char(c,8383).
+char(c,8384).
+char(c,8385).
+char(c,8386).
+char(p,8387).
+char(3,8388).
+char(1,8389).
+char(4,8390).
+char(2,8391).
+char(c,8392).
+char(m,8393).
+char(o,8394).
+char(p,8395).
+char(o,8396).
+char(p,8397).
+char(8,8398).
+char(8,8399).
+char(1,8400).
+char(8,8401).
+char(c,8402).
+char(p,8403).
+char(5,8404).
+char(3,8405).
+char(m,8406).
+char(3,8407).
+char(0,8408).
+char(5,8409).
+char(5,8410).
+char(c,8411).
+char(c,8412).
+char(m,8413).
+char(o,8414).
+char(p,8415).
+char(3,8416).
+char(3,8417).
+char(0,8418).
+char(0,8419).
+char(c,8420).
+char(p,8421).
+char(9,8422).
+char(2,8423).
+char(8,8424).
+char(4,8425).
+char(p,8426).
+char(8,8427).
+char(6,8428).
+char(3,8429).
+char(6,8430).
+char(c,8431).
+char(c,8432).
+char(p,8433).
+char(1,8434).
+char(0,8435).
+char(4,8436).
+char(1,8437).
+char(p,8438).
+char(6,8439).
+char(3,8440).
+char(8,8441).
+char(4,8442).
+char(c,8443).
+char(c,8444).
+char(c,8445).
+char(m,8446).
+char(o,8447).
+char(p,8448).
+char(o,8449).
+char(m,8450).
+char(o,8451).
+char(m,8452).
+char(o,8453).
+char(1,8454).
+char(3,8455).
+char(9,8456).
+char(2,8457).
+char(c,8458).
+char(c,8459).
+char(c,8460).
+char(m,8461).
+char(o,8462).
+char(m,8463).
+char(o,8464).
+char(m,8465).
+char(o,8466).
+char(m,8467).
+char(1,8468).
+char(2,8469).
+char(0,8470).
+char(c,8471).
+char(m,8472).
+char(4,8473).
+char(8,8474).
+char(4,8475).
+char(8,8476).
+char(m,8477).
+char(o,8478).
+char(8,8479).
+char(8,8480).
+char(6,8481).
+char(5,8482).
+char(c,8483).
+char(c,8484).
+char(c,8485).
+char(m,8486).
+char(o,8487).
+char(o,8488).
+char(p,8489).
+char(o,8490).
+char(p,8491).
+char(3,8492).
+char(1,8493).
+char(6,8494).
+char(4,8495).
+char(c,8496).
+char(c,8497).
+char(m,8498).
+char(8,8499).
+char(6,8500).
+char(5,8501).
+char(8,8502).
+char(m,8503).
+char(o,8504).
+char(m,8505).
+char(o,8506).
+char(p,8507).
+char(4,8508).
+char(2,8509).
+char(2,8510).
+char(2,8511).
+char(p,8512).
+char(o,8513).
+char(m,8514).
+char(o,8515).
+char(m,8516).
+char(o,8517).
+char(m,8518).
+char(o,8519).
+char(m,8520).
+char(o,8521).
+char(o,8522).
+char(m,8523).
+char(8,8524).
+char(9,8525).
+char(4,8526).
+char(c,8527).
+char(c,8528).
+char(m,8529).
+char(o,8530).
+char(p,8531).
+char(o,8532).
+char(m,8533).
+char(9,8534).
+char(9,8535).
+char(5,8536).
+char(c,8537).
+char(c,8538).
+char(m,8539).
+char(6,8540).
+char(6,8541).
+char(9,8542).
+char(3,8543).
+char(c,8544).
+char(p,8545).
+char(o,8546).
+char(p,8547).
+char(o,8548).
+char(m,8549).
+char(6,8550).
+char(2,8551).
+char(9,8552).
+char(0,8553).
+char(c,8554).
+char(m,8555).
+char(2,8556).
+char(6,8557).
+char(3,8558).
+char(c,8559).
+char(p,8560).
+char(6,8561).
+char(6,8562).
+char(7,8563).
+char(8,8564).
+char(p,8565).
+char(5,8566).
+char(3,8567).
+char(2,8568).
+char(6,8569).
+char(m,8570).
+char(o,8571).
+char(o,8572).
+char(9,8573).
+char(1,8574).
+char(4,8575).
+char(5,8576).
+char(c,8577).
+char(c,8578).
+char(m,8579).
+char(o,8580).
+char(o,8581).
+char(p,8582).
+char(o,8583).
+char(p,8584).
+char(o,8585).
+char(p,8586).
+char(o,8587).
+char(3,8588).
+char(6,8589).
+char(3,8590).
+char(8,8591).
+char(m,8592).
+char(o,8593).
+char(7,8594).
+char(1,8595).
+char(4,8596).
+char(1,8597).
+char(p,8598).
+char(6,8599).
+char(8,8600).
+char(3,8601).
+char(1,8602).
+char(p,8603).
+char(o,8604).
+char(2,8605).
+char(3,8606).
+char(4,8607).
+char(3,8608).
+char(c,8609).
+char(c,8610).
+char(p,8611).
+char(o,8612).
+char(p,8613).
+char(o,8614).
+char(1,8615).
+char(4,8616).
+char(3,8617).
+char(8,8618).
+char(c,8619).
+char(m,8620).
+char(o,8621).
+char(p,8622).
+char(o,8623).
+char(m,8624).
+char(3,8625).
+char(1,8626).
+char(8,8627).
+char(3,8628).
+char(p,8629).
+char(o,8630).
+char(p,8631).
+char(8,8632).
+char(4,8633).
+char(6,8634).
+char(2,8635).
+char(c,8636).
+char(c,8637).
+char(c,8638).
+char(m,8639).
+char(o,8640).
+char(m,8641).
+char(2,8642).
+char(3,8643).
+char(0,8644).
+char(8,8645).
+char(m,8646).
+char(7,8647).
+char(5,8648).
+char(2,8649).
+char(7,8650).
+char(m,8651).
+char(o,8652).
+char(m,8653).
+char(2,8654).
+char(0,8655).
+char(1,8656).
+char(9,8657).
+char(c,8658).
+char(c,8659).
+char(c,8660).
+char(c,8661).
+char(m,8662).
+char(3,8663).
+char(6,8664).
+char(6,8665).
+char(4,8666).
+char(c,8667).
+char(c,8668).
+char(c,8669).
+char(c,8670).
+char(c,8671).
+char(p,8672).
+char(3,8673).
+char(6,8674).
+char(7,8675).
+char(7,8676).
+char(m,8677).
+char(6,8678).
+char(5,8679).
+char(0,8680).
+char(c,8681).
+char(p,8682).
+char(5,8683).
+char(9,8684).
+char(9,8685).
+char(7,8686).
+char(p,8687).
+char(9,8688).
+char(7,8689).
+char(9,8690).
+char(5,8691).
+char(c,8692).
+char(m,8693).
+char(4,8694).
+char(6,8695).
+char(5,8696).
+char(8,8697).
+char(c,8698).
+char(c,8699).
+char(m,8700).
+char(o,8701).
+char(m,8702).
+char(2,8703).
+char(6,8704).
+char(5,8705).
+char(3,8706).
+char(c,8707).
+char(p,8708).
+char(o,8709).
+char(p,8710).
+char(o,8711).
+char(m,8712).
+char(o,8713).
+char(p,8714).
+char(o,8715).
+char(p,8716).
+char(o,8717).
+char(p,8718).
+char(1,8719).
+char(1,8720).
+char(3,8721).
+char(0,8722).
+char(m,8723).
+char(o,8724).
+char(m,8725).
+char(o,8726).
+char(m,8727).
+char(9,8728).
+char(0,8729).
+char(0,8730).
+char(c,8731).
+char(c,8732).
+char(c,8733).
+char(c,8734).
+char(c,8735).
+char(m,8736).
+char(o,8737).
+char(8,8738).
+char(0,8739).
+char(5,8740).
+char(2,8741).
+char(m,8742).
+char(5,8743).
+char(9,8744).
+char(8,8745).
+char(9,8746).
+char(p,8747).
+char(5,8748).
+char(2,8749).
+char(1,8750).
+char(7,8751).
+char(p,8752).
+char(9,8753).
+char(3,8754).
+char(3,8755).
+char(2,8756).
+char(c,8757).
+char(p,8758).
+char(o,8759).
+char(p,8760).
+char(o,8761).
+char(m,8762).
+char(5,8763).
+char(4,8764).
+char(0,8765).
+char(5,8766).
+char(c,8767).
+char(m,8768).
+char(9,8769).
+char(2,8770).
+char(8,8771).
+char(4,8772).
+char(c,8773).
+char(c,8774).
+char(p,8775).
+char(o,8776).
+char(3,8777).
+char(9,8778).
+char(4,8779).
+char(0,8780).
+char(p,8781).
+char(4,8782).
+char(0,8783).
+char(4,8784).
+char(2,8785).
+char(c,8786).
+char(p,8787).
+char(o,8788).
+char(o,8789).
+char(o,8790).
+char(o,8791).
+char(p,8792).
+char(o,8793).
+char(m,8794).
+char(o,8795).
+char(p,8796).
+char(4,8797).
+char(6,8798).
+char(1,8799).
+char(8,8800).
+char(m,8801).
+char(o,8802).
+char(m,8803).
+char(7,8804).
+char(2,8805).
+char(2,8806).
+char(8,8807).
+char(p,8808).
+char(2,8809).
+char(6,8810).
+char(6,8811).
+char(2,8812).
+char(p,8813).
+char(5,8814).
+char(6,8815).
+char(6,8816).
+char(9,8817).
+char(p,8818).
+char(6,8819).
+char(3,8820).
+char(7,8821).
+char(1,8822).
+char(m,8823).
+char(5,8824).
+char(7,8825).
+char(3,8826).
+char(1,8827).
+char(p,8828).
+char(o,8829).
+char(m,8830).
+char(9,8831).
+char(2,8832).
+char(7,8833).
+char(2,8834).
+char(c,8835).
+char(c,8836).
+char(p,8837).
+char(o,8838).
+char(5,8839).
+char(1,8840).
+char(6,8841).
+char(2,8842).
+char(p,8843).
+char(5,8844).
+char(9,8845).
+char(5,8846).
+char(3,8847).
+char(p,8848).
+char(o,8849).
+char(m,8850).
+char(o,8851).
+char(o,8852).
+char(o,8853).
+char(9,8854).
+char(0,8855).
+char(4,8856).
+char(4,8857).
+char(m,8858).
+char(o,8859).
+char(m,8860).
+char(o,8861).
+char(p,8862).
+char(o,8863).
+char(m,8864).
+char(4,8865).
+char(7,8866).
+char(7,8867).
+char(7,8868).
+char(c,8869).
+char(c,8870).
+char(c,8871).
+char(p,8872).
+char(o,8873).
+char(m,8874).
+char(o,8875).
+char(m,8876).
+char(o,8877).
+char(p,8878).
+char(o,8879).
+char(m,8880).
+char(o,8881).
+char(p,8882).
+char(o,8883).
+char(m,8884).
+char(6,8885).
+char(0,8886).
+char(9,8887).
+char(m,8888).
+char(4,8889).
+char(6,8890).
+char(3,8891).
+char(0,8892).
+char(p,8893).
+char(6,8894).
+char(4,8895).
+char(2,8896).
+char(1,8897).
+char(p,8898).
+char(6,8899).
+char(1,8900).
+char(8,8901).
+char(9,8902).
+char(c,8903).
+char(c,8904).
+char(c,8905).
+char(m,8906).
+char(5,8907).
+char(8,8908).
+char(7,8909).
+char(6,8910).
+char(m,8911).
+char(o,8912).
+char(m,8913).
+char(3,8914).
+char(1,8915).
+char(9,8916).
+char(4,8917).
+char(m,8918).
+char(2,8919).
+char(6,8920).
+char(9,8921).
+char(2,8922).
+char(p,8923).
+char(o,8924).
+char(8,8925).
+char(2,8926).
+char(3,8927).
+char(9,8928).
+char(c,8929).
+char(c,8930).
+char(c,8931).
+char(c,8932).
+char(p,8933).
+char(o,8934).
+char(p,8935).
+char(4,8936).
+char(6,8937).
+char(2,8938).
+char(7,8939).
+char(c,8940).
+char(c,8941).
+char(c,8942).
+char(c,8943).
+char(m,8944).
+char(o,8945).
+char(o,8946).
+char(o,8947).
+char(o,8948).
+char(p,8949).
+char(o,8950).
+char(m,8951).
+char(o,8952).
+char(4,8953).
+char(3,8954).
+char(1,8955).
+char(p,8956).
+char(o,8957).
+char(p,8958).
+char(o,8959).
+char(m,8960).
+char(o,8961).
+char(m,8962).
+char(5,8963).
+char(9,8964).
+char(0,8965).
+char(2,8966).
+char(c,8967).
+char(c,8968).
+char(c,8969).
+char(m,8970).
+char(o,8971).
+char(m,8972).
+char(o,8973).
+char(p,8974).
+char(o,8975).
+char(1,8976).
+char(7,8977).
+char(6,8978).
+char(9,8979).
+char(m,8980).
+char(o,8981).
+char(p,8982).
+char(o,8983).
+char(m,8984).
+char(5,8985).
+char(4,8986).
+char(3,8987).
+char(8,8988).
+char(p,8989).
+char(o,8990).
+char(1,8991).
+char(1,8992).
+char(6,8993).
+char(7,8994).
+char(p,8995).
+char(o,8996).
+char(o,8997).
+char(m,8998).
+char(o,8999).
+char(p,9000).
+char(o,9001).
+char(m,9002).
+char(o,9003).
+char(m,9004).
+char(o,9005).
+char(m,9006).
+char(o,9007).
+char(m,9008).
+char(3,9009).
+char(8,9010).
+char(1,9011).
+char(0,9012).
+char(p,9013).
+char(o,9014).
+char(o,9015).
+char(p,9016).
+char(1,9017).
+char(6,9018).
+char(4,9019).
+char(7,9020).
+char(p,9021).
+char(o,9022).
+char(p,9023).
+char(4,9024).
+char(4,9025).
+char(6,9026).
+char(5,9027).
+char(m,9028).
+char(7,9029).
+char(9,9030).
+char(7,9031).
+char(4,9032).
+char(c,9033).
+char(m,9034).
+char(6,9035).
+char(1,9036).
+char(4,9037).
+char(0,9038).
+char(p,9039).
+char(1,9040).
+char(3,9041).
+char(9,9042).
+char(7,9043).
+char(c,9044).
+char(c,9045).
+char(p,9046).
+char(o,9047).
+char(p,9048).
+char(1,9049).
+char(0,9050).
+char(4,9051).
+char(1,9052).
+char(c,9053).
+char(m,9054).
+char(6,9055).
+char(4,9056).
+char(7,9057).
+char(7,9058).
+char(p,9059).
+char(o,9060).
+char(3,9061).
+char(7,9062).
+char(3,9063).
+char(7,9064).
+char(p,9065).
+char(o,9066).
+char(m,9067).
+char(7,9068).
+char(5,9069).
+char(6,9070).
+char(7,9071).
+char(c,9072).
+char(c,9073).
+char(m,9074).
+char(5,9075).
+char(8,9076).
+char(1,9077).
+char(0,9078).
+char(p,9079).
+char(1,9080).
+char(1,9081).
+char(8,9082).
+char(1,9083).
+char(c,9084).
+char(c,9085).
+char(c,9086).
+char(p,9087).
+char(2,9088).
+char(3,9089).
+char(2,9090).
+char(1,9091).
+char(p,9092).
+char(2,9093).
+char(3,9094).
+char(1,9095).
+char(3,9096).
+char(c,9097).
+char(c,9098).
+char(c,9099).
+char(m,9100).
+char(5,9101).
+char(2,9102).
+char(3,9103).
+char(8,9104).
+char(p,9105).
+char(o,9106).
+char(6,9107).
+char(4,9108).
+char(4,9109).
+char(5,9110).
+char(m,9111).
+char(o,9112).
+char(p,9113).
+char(o,9114).
+char(p,9115).
+char(o,9116).
+char(o,9117).
+char(m,9118).
+char(7,9119).
+char(4,9120).
+char(2,9121).
+char(9,9122).
+char(c,9123).
+char(c,9124).
+char(c,9125).
+char(c,9126).
+char(m,9127).
+char(4,9128).
+char(5,9129).
+char(8,9130).
+char(6,9131).
+char(c,9132).
+char(c,9133).
+char(c,9134).
+char(c,9135).
+char(p,9136).
+char(o,9137).
+char(p,9138).
+char(o,9139).
+char(m,9140).
+char(6,9141).
+char(6,9142).
+char(2,9143).
+char(8,9144).
+char(p,9145).
+char(6,9146).
+char(8,9147).
+char(7,9148).
+char(5,9149).
+char(c,9150).
+char(c,9151).
+char(c,9152).
+char(p,9153).
+char(o,9154).
+char(p,9155).
+char(o,9156).
+char(p,9157).
+char(o,9158).
+char(o,9159).
+char(m,9160).
+char(o,9161).
+char(m,9162).
+char(5,9163).
+char(8,9164).
+char(2,9165).
+char(4,9166).
+char(c,9167).
+char(c,9168).
+char(m,9169).
+char(1,9170).
+char(8,9171).
+char(3,9172).
+char(2,9173).
+char(p,9174).
+char(o,9175).
+char(p,9176).
+char(o,9177).
+char(p,9178).
+char(8,9179).
+char(1,9180).
+char(1,9181).
+char(3,9182).
+char(p,9183).
+char(o,9184).
+char(m,9185).
+char(7,9186).
+char(7,9187).
+char(2,9188).
+char(5,9189).
+char(c,9190).
+char(m,9191).
+char(8,9192).
+char(4,9193).
+char(3,9194).
+char(0,9195).
+char(m,9196).
+char(1,9197).
+char(7,9198).
+char(2,9199).
+char(0,9200).
+char(c,9201).
+char(c,9202).
+char(p,9203).
+char(3,9204).
+char(3,9205).
+char(3,9206).
+char(8,9207).
+char(p,9208).
+char(1,9209).
+char(4,9210).
+char(2,9211).
+char(6,9212).
+char(c,9213).
+char(p,9214).
+char(4,9215).
+char(0,9216).
+char(5,9217).
+char(7,9218).
+char(c,9219).
+char(m,9220).
+char(o,9221).
+char(8,9222).
+char(4,9223).
+char(1,9224).
+char(6,9225).
+char(p,9226).
+char(o,9227).
+char(9,9228).
+char(2,9229).
+char(8,9230).
+char(3,9231).
+char(c,9232).
+char(p,9233).
+char(2,9234).
+char(7,9235).
+char(9,9236).
+char(m,9237).
+char(6,9238).
+char(2,9239).
+char(7,9240).
+char(p,9241).
+char(o,9242).
+char(m,9243).
+char(9,9244).
+char(1,9245).
+char(9,9246).
+char(1,9247).
+char(m,9248).
+char(o,9249).
+char(m,9250).
+char(o,9251).
+char(o,9252).
+char(m,9253).
+char(7,9254).
+char(5,9255).
+char(6,9256).
+char(3,9257).
+char(c,9258).
+char(m,9259).
+char(o,9260).
+char(m,9261).
+char(7,9262).
+char(8,9263).
+char(8,9264).
+char(1,9265).
+char(m,9266).
+char(1,9267).
+char(0,9268).
+char(4,9269).
+char(4,9270).
+char(c,9271).
+char(m,9272).
+char(7,9273).
+char(2,9274).
+char(3,9275).
+char(0,9276).
+char(c,9277).
+char(c,9278).
+char(m,9279).
+char(4,9280).
+char(0,9281).
+char(4,9282).
+char(9,9283).
+char(c,9284).
+char(p,9285).
+char(5,9286).
+char(3,9287).
+char(1,9288).
+char(0,9289).
+char(m,9290).
+char(o,9291).
+char(p,9292).
+char(6,9293).
+char(7,9294).
+char(3,9295).
+char(7,9296).
+char(p,9297).
+char(5,9298).
+char(8,9299).
+char(8,9300).
+char(8,9301).
+char(m,9302).
+char(o,9303).
+char(7,9304).
+char(5,9305).
+char(5,9306).
+char(6,9307).
+char(c,9308).
+char(c,9309).
+char(c,9310).
+char(p,9311).
+char(o,9312).
+char(m,9313).
+char(2,9314).
+char(9,9315).
+char(0,9316).
+char(9,9317).
+char(c,9318).
+char(p,9319).
+char(o,9320).
+char(p,9321).
+char(2,9322).
+char(6,9323).
+char(7,9324).
+char(0,9325).
+char(p,9326).
+char(o,9327).
+char(p,9328).
+char(6,9329).
+char(0,9330).
+char(3,9331).
+char(7,9332).
+char(c,9333).
+char(p,9334).
+char(7,9335).
+char(3,9336).
+char(8,9337).
+char(7,9338).
+char(c,9339).
+char(c,9340).
+char(p,9341).
+char(o,9342).
+char(m,9343).
+char(o,9344).
+char(p,9345).
+char(o,9346).
+char(7,9347).
+char(9,9348).
+char(6,9349).
+char(9,9350).
+char(m,9351).
+char(o,9352).
+char(p,9353).
+char(o,9354).
+char(m,9355).
+char(8,9356).
+char(4,9357).
+char(6,9358).
+char(6,9359).
+char(c,9360).
+char(c,9361).
+char(p,9362).
+char(4,9363).
+char(2,9364).
+char(p,9365).
+char(3,9366).
+char(0,9367).
+char(0,9368).
+char(9,9369).
+char(c,9370).
+char(c,9371).
+char(c,9372).
+char(c,9373).
+char(c,9374).
+char(c,9375).
+char(c,9376).
+char(c,9377).
+char(p,9378).
+char(o,9379).
+char(p,9380).
+char(3,9381).
+char(4,9382).
+char(7,9383).
+char(m,9384).
+char(9,9385).
+char(1,9386).
+char(6,9387).
+char(8,9388).
+char(p,9389).
+char(4,9390).
+char(0,9391).
+char(4,9392).
+char(4,9393).
+char(c,9394).
+char(p,9395).
+char(6,9396).
+char(0,9397).
+char(5,9398).
+char(p,9399).
+char(7,9400).
+char(8,9401).
+char(7,9402).
+char(6,9403).
+char(m,9404).
+char(o,9405).
+char(8,9406).
+char(4,9407).
+char(9,9408).
+char(0,9409).
+char(p,9410).
+char(9,9411).
+char(9,9412).
+char(5,9413).
+char(2,9414).
+char(p,9415).
+char(4,9416).
+char(4,9417).
+char(1,9418).
+char(7,9419).
+char(m,9420).
+char(o,9421).
+char(p,9422).
+char(o,9423).
+char(m,9424).
+char(o,9425).
+char(p,9426).
+char(9,9427).
+char(3,9428).
+char(6,9429).
+char(6,9430).
+char(p,9431).
+char(6,9432).
+char(6,9433).
+char(4,9434).
+char(5,9435).
+char(p,9436).
+char(7,9437).
+char(2,9438).
+char(0,9439).
+char(p,9440).
+char(o,9441).
+char(o,9442).
+char(m,9443).
+char(o,9444).
+char(p,9445).
+char(5,9446).
+char(7,9447).
+char(9,9448).
+char(4,9449).
+char(m,9450).
+char(o,9451).
+char(6,9452).
+char(5,9453).
+char(5,9454).
+char(c,9455).
+char(c,9456).
+char(c,9457).
+char(p,9458).
+char(o,9459).
+char(p,9460).
+char(o,9461).
+char(p,9462).
+char(o,9463).
+char(o,9464).
+char(m,9465).
+char(7,9466).
+char(9,9467).
+char(5,9468).
+char(0,9469).
+char(m,9470).
+char(o,9471).
+char(p,9472).
+char(o,9473).
+char(p,9474).
+char(o,9475).
+char(o,9476).
+char(p,9477).
+char(6,9478).
+char(6,9479).
+char(7,9480).
+char(9,9481).
+char(m,9482).
+char(o,9483).
+char(m,9484).
+char(o,9485).
+char(p,9486).
+char(o,9487).
+char(9,9488).
+char(8,9489).
+char(5,9490).
+char(7,9491).
+char(p,9492).
+char(9,9493).
+char(0,9494).
+char(7,9495).
+char(5,9496).
+char(p,9497).
+char(5,9498).
+char(8,9499).
+char(8,9500).
+char(7,9501).
+char(m,9502).
+char(7,9503).
+char(5,9504).
+char(9,9505).
+char(5,9506).
+char(m,9507).
+char(o,9508).
+char(m,9509).
+char(o,9510).
+char(1,9511).
+char(5,9512).
+char(6,9513).
+char(2,9514).
+char(m,9515).
+char(4,9516).
+char(9,9517).
+char(2,9518).
+char(2,9519).
+char(m,9520).
+char(3,9521).
+char(9,9522).
+char(3,9523).
+char(5,9524).
+char(c,9525).
+char(m,9526).
+char(5,9527).
+char(5,9528).
+char(0,9529).
+char(5,9530).
+char(c,9531).
+char(p,9532).
+char(o,9533).
+char(m,9534).
+char(5,9535).
+char(1,9536).
+char(1,9537).
+char(3,9538).
+char(c,9539).
+char(p,9540).
+char(o,9541).
+char(p,9542).
+char(o,9543).
+char(o,9544).
+char(m,9545).
+char(1,9546).
+char(8,9547).
+char(8,9548).
+char(5,9549).
+char(m,9550).
+char(o,9551).
+char(p,9552).
+char(6,9553).
+char(6,9554).
+char(9,9555).
+char(c,9556).
+char(c,9557).
+char(p,9558).
+char(o,9559).
+char(1,9560).
+char(6,9561).
+char(5,9562).
+char(m,9563).
+char(o,9564).
+char(o,9565).
+char(p,9566).
+char(o,9567).
+char(m,9568).
+char(3,9569).
+char(1,9570).
+char(1,9571).
+char(1,9572).
+char(m,9573).
+char(9,9574).
+char(7,9575).
+char(8,9576).
+char(4,9577).
+char(m,9578).
+char(8,9579).
+char(4,9580).
+char(8,9581).
+char(5,9582).
+char(p,9583).
+char(o,9584).
+char(o,9585).
+char(o,9586).
+char(5,9587).
+char(8,9588).
+char(4,9589).
+char(3,9590).
+char(c,9591).
+char(m,9592).
+char(o,9593).
+char(6,9594).
+char(9,9595).
+char(9,9596).
+char(3,9597).
+char(p,9598).
+char(o,9599).
+char(m,9600).
+char(o,9601).
+char(p,9602).
+char(o,9603).
+char(2,9604).
+char(1,9605).
+char(3,9606).
+char(5,9607).
+char(m,9608).
+char(o,9609).
+char(p,9610).
+char(o,9611).
+char(9,9612).
+char(6,9613).
+char(1,9614).
+char(4,9615).
+char(c,9616).
+char(c,9617).
+char(m,9618).
+char(4,9619).
+char(2,9620).
+char(5,9621).
+char(3,9622).
+char(c,9623).
+char(c,9624).
+char(p,9625).
+char(5,9626).
+char(6,9627).
+char(7,9628).
+char(0,9629).
+char(c,9630).
+char(m,9631).
+char(4,9632).
+char(9,9633).
+char(9,9634).
+char(8,9635).
+char(c,9636).
+char(p,9637).
+char(3,9638).
+char(7,9639).
+char(4,9640).
+char(3,9641).
+char(p,9642).
+char(4,9643).
+char(3,9644).
+char(6,9645).
+char(2,9646).
+char(m,9647).
+char(6,9648).
+char(3,9649).
+char(8,9650).
+char(8,9651).
+char(c,9652).
+char(c,9653).
+char(c,9654).
+char(m,9655).
+char(8,9656).
+char(7,9657).
+char(4,9658).
+char(1,9659).
+char(m,9660).
+char(o,9661).
+char(m,9662).
+char(5,9663).
+char(3,9664).
+char(0,9665).
+char(8,9666).
+char(c,9667).
+char(c,9668).
+char(p,9669).
+char(o,9670).
+char(p,9671).
+char(o,9672).
+char(o,9673).
+char(o,9674).
+char(p,9675).
+char(o,9676).
+char(2,9677).
+char(6,9678).
+char(6,9679).
+char(1,9680).
+char(c,9681).
+char(c,9682).
+char(c,9683).
+char(c,9684).
+char(c,9685).
+char(p,9686).
+char(o,9687).
+char(m,9688).
+char(5,9689).
+char(6,9690).
+char(6,9691).
+char(6,9692).
+char(m,9693).
+char(9,9694).
+char(6,9695).
+char(2,9696).
+char(4,9697).
+char(m,9698).
+char(5,9699).
+char(0,9700).
+char(1,9701).
+char(5,9702).
+char(m,9703).
+char(o,9704).
+char(p,9705).
+char(o,9706).
+char(o,9707).
+char(o,9708).
+char(p,9709).
+char(6,9710).
+char(5,9711).
+char(2,9712).
+char(c,9713).
+char(c,9714).
+char(m,9715).
+char(o,9716).
+char(m,9717).
+char(5,9718).
+char(2,9719).
+char(7,9720).
+char(7,9721).
+char(p,9722).
+char(o,9723).
+char(p,9724).
+char(o,9725).
+char(6,9726).
+char(5,9727).
+char(0,9728).
+char(2,9729).
+char(c,9730).
+char(c,9731).
+char(p,9732).
+char(3,9733).
+char(8,9734).
+char(7,9735).
+char(9,9736).
+char(p,9737).
+char(o,9738).
+char(o,9739).
+char(m,9740).
+char(1,9741).
+char(9,9742).
+char(0,9743).
+char(1,9744).
+char(c,9745).
+char(m,9746).
+char(o,9747).
+char(8,9748).
+char(6,9749).
+char(0,9750).
+char(7,9751).
+char(m,9752).
+char(8,9753).
+char(8,9754).
+char(6,9755).
+char(7,9756).
+char(p,9757).
+char(o,9758).
+char(p,9759).
+char(6,9760).
+char(0,9761).
+char(4,9762).
+char(7,9763).
+char(c,9764).
+char(c,9765).
+char(c,9766).
+char(p,9767).
+char(o,9768).
+char(m,9769).
+char(o,9770).
+char(m,9771).
+char(1,9772).
+char(1,9773).
+char(0,9774).
+char(8,9775).
+char(m,9776).
+char(o,9777).
+char(o,9778).
+char(p,9779).
+char(5,9780).
+char(4,9781).
+char(5,9782).
+char(1,9783).
+char(p,9784).
+char(7,9785).
+char(4,9786).
+char(4,9787).
+char(4,9788).
+char(m,9789).
+char(o,9790).
+char(m,9791).
+char(7,9792).
+char(4,9793).
+char(3,9794).
+char(5,9795).
+char(c,9796).
+char(c,9797).
+char(c,9798).
+char(c,9799).
+char(m,9800).
+char(o,9801).
+char(p,9802).
+char(7,9803).
+char(9,9804).
+char(9,9805).
+char(4,9806).
+char(c,9807).
+char(c,9808).
+char(p,9809).
+char(o,9810).
+char(p,9811).
+char(o,9812).
+char(m,9813).
+char(o,9814).
+char(m,9815).
+char(2,9816).
+char(9,9817).
+char(9,9818).
+char(9,9819).
+char(p,9820).
+char(o,9821).
+char(p,9822).
+char(o,9823).
+char(o,9824).
+char(o,9825).
+char(m,9826).
+char(o,9827).
+char(o,9828).
+char(m,9829).
+char(1,9830).
+char(1,9831).
+char(2,9832).
+char(7,9833).
+char(p,9834).
+char(4,9835).
+char(5,9836).
+char(5,9837).
+char(1,9838).
+char(c,9839).
+char(c,9840).
+char(p,9841).
+char(2,9842).
+char(5,9843).
+char(5,9844).
+char(8,9845).
+char(c,9846).
+char(m,9847).
+char(3,9848).
+char(3,9849).
+char(1,9850).
+char(1,9851).
+char(c,9852).
+char(m,9853).
+char(o,9854).
+char(4,9855).
+char(1,9856).
+char(1,9857).
+char(0,9858).
+char(m,9859).
+char(o,9860).
+char(p,9861).
+char(6,9862).
+char(8,9863).
+char(3,9864).
+char(9,9865).
+char(c,9866).
+char(m,9867).
+char(3,9868).
+char(5,9869).
+char(9,9870).
+char(1,9871).
+char(c,9872).
+char(c,9873).
+char(c,9874).
+char(c,9875).
+char(c,9876).
+char(p,9877).
+char(o,9878).
+char(1,9879).
+char(7,9880).
+char(2,9881).
+char(4,9882).
+char(p,9883).
+char(o,9884).
+char(p,9885).
+char(9,9886).
+char(4,9887).
+char(4,9888).
+char(9,9889).
+char(c,9890).
+char(c,9891).
+char(p,9892).
+char(8,9893).
+char(0,9894).
+char(2,9895).
+char(0,9896).
+char(p,9897).
+char(4,9898).
+char(3,9899).
+char(4,9900).
+char(7,9901).
+char(p,9902).
+char(3,9903).
+char(0,9904).
+char(4,9905).
+char(c,9906).
+char(c,9907).
+char(p,9908).
+char(o,9909).
+char(o,9910).
+char(m,9911).
+char(9,9912).
+char(7,9913).
+char(5,9914).
+char(3,9915).
+char(m,9916).
+char(8,9917).
+char(2,9918).
+char(0,9919).
+char(9,9920).
+char(p,9921).
+char(4,9922).
+char(0,9923).
+char(0,9924).
+char(1,9925).
+char(c,9926).
+char(m,9927).
+char(o,9928).
+char(m,9929).
+char(o,9930).
+char(m,9931).
+char(o,9932).
+char(p,9933).
+char(o,9934).
+char(p,9935).
+char(o,9936).
+char(p,9937).
+char(o,9938).
+char(o,9939).
+char(m,9940).
+char(o,9941).
+char(m,9942).
+char(o,9943).
+char(p,9944).
+char(6,9945).
+char(8,9946).
+char(7,9947).
+char(4,9948).
+char(c,9949).
+char(c,9950).
+char(c,9951).
+char(c,9952).
+char(p,9953).
+char(7,9954).
+char(4,9955).
+char(2,9956).
+char(1,9957).
+char(c,9958).
+char(m,9959).
+char(o,9960).
+char(m,9961).
+char(o,9962).
+char(m,9963).
+char(6,9964).
+char(8,9965).
+char(7,9966).
+char(9,9967).
+char(m,9968).
+char(o,9969).
+char(m,9970).
+char(8,9971).
+char(0,9972).
+char(8,9973).
+char(7,9974).
+char(c,9975).
+char(c,9976).
+char(p,9977).
+char(3,9978).
+char(3,9979).
+char(5,9980).
+char(4,9981).
+char(c,9982).
+char(c,9983).
+char(p,9984).
+char(o,9985).
+char(m,9986).
+char(o,9987).
+char(m,9988).
+char(o,9989).
+char(o,9990).
+char(9,9991).
+char(7,9992).
+char(7,9993).
+char(9,9994).
+char(p,9995).
+char(o,9996).
+char(m,9997).
+char(8,9998).
+char(9,9999).
+char(3,10000).
+char(1,10001).
+char(m,10002).
+char(o,10003).
+char(m,10004).
+char(o,10005).
+char(m,10006).
+char(o,10007).
+char(p,10008).
+char(6,10009).
+char(6,10010).
+char(8,10011).
+char(8,10012).
+char(c,10013).
+char(c,10014).
+char(c,10015).
+char(m,10016).
+char(o,10017).
+char(3,10018).
+char(9,10019).
+char(7,10020).
+char(4,10021).
+char(m,10022).
+char(o,10023).
+char(o,10024).
+char(m,10025).
+char(2,10026).
+char(9,10027).
+char(2,10028).
+char(9,10029).
+char(m,10030).
+char(o,10031).
+char(o,10032).
+char(m,10033).
+char(o,10034).
+char(p,10035).
+char(o,10036).
+char(o,10037).
+char(m,10038).
+char(4,10039).
+char(7,10040).
+char(6,10041).
+char(6,10042).
+char(c,10043).
+char(c,10044).
+char(c,10045).
+char(m,10046).
+char(6,10047).
+char(9,10048).
+char(7,10049).
+char(7,10050).
+char(p,10051).
+char(1,10052).
+char(4,10053).
+char(9,10054).
+char(7,10055).
+char(c,10056).
+char(p,10057).
+char(o,10058).
+char(7,10059).
+char(2,10060).
+char(5,10061).
+char(5,10062).
+char(p,10063).
+char(o,10064).
+char(o,10065).
+char(m,10066).
+char(2,10067).
+char(6,10068).
+char(4,10069).
+char(6,10070).
+char(m,10071).
+char(o,10072).
+char(9,10073).
+char(1,10074).
+char(9,10075).
+char(2,10076).
+char(c,10077).
+char(c,10078).
+char(c,10079).
+char(c,10080).
+char(m,10081).
+char(o,10082).
+char(m,10083).
+char(1,10084).
+char(6,10085).
+char(0,10086).
+char(c,10087).
+char(m,10088).
+char(o,10089).
+char(m,10090).
+char(8,10091).
+char(6,10092).
+char(0,10093).
+char(9,10094).
+char(c,10095).
+char(p,10096).
+char(2,10097).
+char(1,10098).
+char(0,10099).
+char(9,10100).
+char(p,10101).
+char(o,10102).
+char(m,10103).
+char(9,10104).
+char(7,10105).
+char(7,10106).
+char(0,10107).
+char(m,10108).
+char(8,10109).
+char(3,10110).
+char(2,10111).
+char(3,10112).
+char(p,10113).
+char(o,10114).
+char(o,10115).
+char(m,10116).
+char(o,10117).
+char(p,10118).
+char(o,10119).
+char(6,10120).
+char(8,10121).
+char(9,10122).
+char(9,10123).
+char(m,10124).
+char(o,10125).
+char(m,10126).
+char(o,10127).
+char(2,10128).
+char(9,10129).
+char(6,10130).
+char(2,10131).
+char(c,10132).
+char(c,10133).
+char(c,10134).
+char(m,10135).
+char(o,10136).
+char(p,10137).
+char(o,10138).
+char(m,10139).
+char(6,10140).
+char(6,10141).
+char(6,10142).
+char(1,10143).
+char(m,10144).
+char(5,10145).
+char(8,10146).
+char(7,10147).
+char(9,10148).
+char(m,10149).
+char(1,10150).
+char(3,10151).
+char(2,10152).
+char(4,10153).
+char(c,10154).
+char(c,10155).
+char(m,10156).
+char(o,10157).
+char(m,10158).
+char(8,10159).
+char(4,10160).
+char(8,10161).
+char(7,10162).
+char(c,10163).
+char(c,10164).
+char(p,10165).
+char(o,10166).
+char(p,10167).
+char(o,10168).
+char(p,10169).
+char(6,10170).
+char(9,10171).
+char(9,10172).
+char(4,10173).
+char(p,10174).
+char(9,10175).
+char(5,10176).
+char(7,10177).
+char(7,10178).
+char(c,10179).
+char(p,10180).
+char(4,10181).
+char(0,10182).
+char(5,10183).
+char(0,10184).
+char(c,10185).
+char(c,10186).
+char(c,10187).
+char(c,10188).
+char(c,10189).
+char(p,10190).
+char(o,10191).
+char(m,10192).
+char(6,10193).
+char(6,10194).
+char(0,10195).
+char(6,10196).
+char(c,10197).
+char(m,10198).
+char(3,10199).
+char(9,10200).
+char(7,10201).
+char(7,10202).
+char(m,10203).
+char(o,10204).
+char(p,10205).
+char(o,10206).
+char(9,10207).
+char(3,10208).
+char(7,10209).
+char(0,10210).
+char(p,10211).
+char(o,10212).
+char(o,10213).
+char(m,10214).
+char(2,10215).
+char(2,10216).
+char(0,10217).
+char(7,10218).
+char(c,10219).
+char(m,10220).
+char(o,10221).
+char(m,10222).
+char(7,10223).
+char(8,10224).
+char(6,10225).
+char(2,10226).
+char(m,10227).
+char(1,10228).
+char(6,10229).
+char(7,10230).
+char(4,10231).
+char(p,10232).
+char(9,10233).
+char(1,10234).
+char(2,10235).
+char(5,10236).
+char(m,10237).
+char(o,10238).
+char(o,10239).
+char(1,10240).
+char(6,10241).
+char(2,10242).
+char(4,10243).
+char(c,10244).
+char(m,10245).
+char(o,10246).
+char(p,10247).
+char(o,10248).
+char(p,10249).
+char(8,10250).
+char(0,10251).
+char(3,10252).
+char(p,10253).
+char(o,10254).
+char(6,10255).
+char(4,10256).
+char(7,10257).
+char(m,10258).
+char(3,10259).
+char(9,10260).
+char(0,10261).
+char(1,10262).
+char(p,10263).
+char(o,10264).
+char(o,10265).
+char(o,10266).
+char(6,10267).
+char(8,10268).
+char(7,10269).
+char(8,10270).
+char(m,10271).
+char(o,10272).
+char(p,10273).
+char(o,10274).
+char(m,10275).
+char(8,10276).
+char(1,10277).
+char(9,10278).
+char(2,10279).
+char(p,10280).
+char(o,10281).
+char(p,10282).
+char(o,10283).
+char(o,10284).
+char(p,10285).
+char(6,10286).
+char(6,10287).
+char(9,10288).
+char(6,10289).
+char(c,10290).
+char(c,10291).
+char(m,10292).
+char(5,10293).
+char(4,10294).
+char(3,10295).
+char(1,10296).
+char(c,10297).
+char(m,10298).
+char(2,10299).
+char(7,10300).
+char(0,10301).
+char(3,10302).
+char(p,10303).
+char(6,10304).
+char(6,10305).
+char(9,10306).
+char(5,10307).
+char(m,10308).
+char(7,10309).
+char(6,10310).
+char(1,10311).
+char(1,10312).
+char(c,10313).
+char(c,10314).
+char(p,10315).
+char(o,10316).
+char(p,10317).
+char(o,10318).
+char(p,10319).
+char(5,10320).
+char(6,10321).
+char(5,10322).
+char(8,10323).
+char(m,10324).
+char(3,10325).
+char(7,10326).
+char(8,10327).
+char(7,10328).
+char(c,10329).
+char(c,10330).
+char(m,10331).
+char(4,10332).
+char(5,10333).
+char(6,10334).
+char(3,10335).
+char(c,10336).
+char(c,10337).
+char(c,10338).
+char(c,10339).
+char(p,10340).
+char(7,10341).
+char(1,10342).
+char(2,10343).
+char(8,10344).
+char(m,10345).
+char(4,10346).
+char(4,10347).
+char(9,10348).
+char(5,10349).
+char(c,10350).
+char(m,10351).
+char(o,10352).
+char(m,10353).
+char(o,10354).
+char(p,10355).
+char(o,10356).
+char(p,10357).
+char(o,10358).
+char(p,10359).
+char(8,10360).
+char(1,10361).
+char(5,10362).
+char(5,10363).
+char(c,10364).
+char(c,10365).
+char(p,10366).
+char(o,10367).
+char(6,10368).
+char(8,10369).
+char(8,10370).
+char(4,10371).
+char(c,10372).
+char(m,10373).
+char(o,10374).
+char(5,10375).
+char(1,10376).
+char(1,10377).
+char(3,10378).
+char(p,10379).
+char(o,10380).
+char(m,10381).
+char(7,10382).
+char(1,10383).
+char(2,10384).
+char(2,10385).
+char(c,10386).
+char(p,10387).
+char(o,10388).
+char(m,10389).
+char(o,10390).
+char(p,10391).
+char(o,10392).
+char(o,10393).
+char(p,10394).
+char(o,10395).
+char(p,10396).
+char(o,10397).
+char(m,10398).
+char(2,10399).
+char(3,10400).
+char(8,10401).
+char(4,10402).
+char(p,10403).
+char(4,10404).
+char(7,10405).
+char(2,10406).
+char(4,10407).
+char(m,10408).
+char(2,10409).
+char(7,10410).
+char(8,10411).
+char(9,10412).
+char(c,10413).
+char(p,10414).
+char(o,10415).
+char(o,10416).
+char(m,10417).
+char(o,10418).
+char(m,10419).
+char(5,10420).
+char(2,10421).
+char(7,10422).
+char(5,10423).
+char(p,10424).
+char(o,10425).
+char(o,10426).
+char(p,10427).
+char(5,10428).
+char(7,10429).
+char(3,10430).
+char(c,10431).
+char(p,10432).
+char(3,10433).
+char(5,10434).
+char(0,10435).
+char(8,10436).
+char(p,10437).
+char(9,10438).
+char(9,10439).
+char(8,10440).
+char(1,10441).
+char(c,10442).
+char(c,10443).
+char(c,10444).
+char(p,10445).
+char(4,10446).
+char(2,10447).
+char(5,10448).
+char(4,10449).
+char(c,10450).
+char(m,10451).
+char(o,10452).
+char(o,10453).
+char(p,10454).
+char(o,10455).
+char(1,10456).
+char(5,10457).
+char(5,10458).
+char(5,10459).
+char(c,10460).
+char(c,10461).
+char(m,10462).
+char(9,10463).
+char(8,10464).
+char(2,10465).
+char(9,10466).
+char(p,10467).
+char(1,10468).
+char(2,10469).
+char(2,10470).
+char(1,10471).
+char(c,10472).
+char(c,10473).
+char(p,10474).
+char(7,10475).
+char(5,10476).
+char(0,10477).
+char(0,10478).
+char(p,10479).
+char(o,10480).
+char(o,10481).
+char(8,10482).
+char(6,10483).
+char(5,10484).
+char(1,10485).
+char(c,10486).
+char(c,10487).
+char(c,10488).
+char(m,10489).
+char(4,10490).
+char(3,10491).
+char(5,10492).
+char(m,10493).
+char(o,10494).
+char(3,10495).
+char(6,10496).
+char(6,10497).
+char(4,10498).
+char(m,10499).
+char(8,10500).
+char(7,10501).
+char(6,10502).
+char(8,10503).
+char(m,10504).
+char(8,10505).
+char(0,10506).
+char(1,10507).
+char(0,10508).
+char(c,10509).
+char(c,10510).
+char(c,10511).
+char(p,10512).
+char(o,10513).
+char(7,10514).
+char(6,10515).
+char(9,10516).
+char(5,10517).
+char(p,10518).
+char(o,10519).
+char(o,10520).
+char(p,10521).
+char(8,10522).
+char(7,10523).
+char(0,10524).
+char(0,10525).
+char(c,10526).
+char(c,10527).
+char(c,10528).
+char(c,10529).
+char(p,10530).
+char(o,10531).
+char(p,10532).
+char(5,10533).
+char(8,10534).
+char(8,10535).
+char(9,10536).
+char(m,10537).
+char(8,10538).
+char(0,10539).
+char(1,10540).
+char(2,10541).
+char(c,10542).
+char(p,10543).
+char(6,10544).
+char(1,10545).
+char(7,10546).
+char(2,10547).
+char(c,10548).
+char(c,10549).
+char(c,10550).
+char(c,10551).
+char(p,10552).
+char(o,10553).
+char(o,10554).
+char(m,10555).
+char(3,10556).
+char(9,10557).
+char(3,10558).
+char(4,10559).
+char(c,10560).
+char(p,10561).
+char(5,10562).
+char(9,10563).
+char(9,10564).
+char(m,10565).
+char(9,10566).
+char(6,10567).
+char(8,10568).
+char(2,10569).
+char(p,10570).
+char(o,10571).
+char(p,10572).
+char(4,10573).
+char(6,10574).
+char(3,10575).
+char(7,10576).
+char(p,10577).
+char(o,10578).
+char(o,10579).
+char(p,10580).
+char(7,10581).
+char(7,10582).
+char(3,10583).
+char(p,10584).
+char(6,10585).
+char(6,10586).
+char(8,10587).
+char(2,10588).
+char(p,10589).
+char(o,10590).
+char(m,10591).
+char(9,10592).
+char(8,10593).
+char(6,10594).
+char(2,10595).
+char(c,10596).
+char(c,10597).
+char(m,10598).
+char(4,10599).
+char(0,10600).
+char(0,10601).
+char(8,10602).
+char(m,10603).
+char(5,10604).
+char(8,10605).
+char(7,10606).
+char(6,10607).
+char(p,10608).
+char(o,10609).
+char(p,10610).
+char(2,10611).
+char(1,10612).
+char(0,10613).
+char(1,10614).
+char(c,10615).
+char(p,10616).
+char(o,10617).
+char(p,10618).
+char(1,10619).
+char(8,10620).
+char(3,10621).
+char(9,10622).
+char(m,10623).
+char(6,10624).
+char(7,10625).
+char(4,10626).
+char(3,10627).
+char(p,10628).
+char(o,10629).
+char(p,10630).
+char(5,10631).
+char(5,10632).
+char(2,10633).
+char(0,10634).
+char(c,10635).
+char(p,10636).
+char(4,10637).
+char(3,10638).
+char(6,10639).
+char(9,10640).
+char(m,10641).
+char(o,10642).
+char(o,10643).
+char(m,10644).
+char(o,10645).
+char(p,10646).
+char(6,10647).
+char(8,10648).
+char(7,10649).
+char(p,10650).
+char(o,10651).
+char(3,10652).
+char(9,10653).
+char(3,10654).
+char(7,10655).
+char(p,10656).
+char(4,10657).
+char(0,10658).
+char(7,10659).
+char(m,10660).
+char(5,10661).
+char(6,10662).
+char(2,10663).
+char(0,10664).
+char(m,10665).
+char(o,10666).
+char(p,10667).
+char(1,10668).
+char(8,10669).
+char(8,10670).
+char(2,10671).
+char(m,10672).
+char(3,10673).
+char(3,10674).
+char(2,10675).
+char(3,10676).
+char(c,10677).
+char(p,10678).
+char(6,10679).
+char(8,10680).
+char(5,10681).
+char(0,10682).
+char(c,10683).
+char(m,10684).
+char(o,10685).
+char(p,10686).
+char(o,10687).
+char(p,10688).
+char(o,10689).
+char(o,10690).
+char(m,10691).
+char(6,10692).
+char(3,10693).
+char(9,10694).
+char(9,10695).
+char(c,10696).
+char(c,10697).
+char(m,10698).
+char(2,10699).
+char(6,10700).
+char(0,10701).
+char(c,10702).
+char(c,10703).
+char(c,10704).
+char(p,10705).
+char(o,10706).
+char(o,10707).
+char(m,10708).
+char(3,10709).
+char(7,10710).
+char(4,10711).
+char(5,10712).
+char(c,10713).
+char(p,10714).
+char(5,10715).
+char(9,10716).
+char(3,10717).
+char(3,10718).
+char(p,10719).
+char(o,10720).
+char(p,10721).
+char(o,10722).
+char(p,10723).
+char(o,10724).
+char(4,10725).
+char(0,10726).
+char(1,10727).
+char(6,10728).
+char(c,10729).
+char(c,10730).
+char(c,10731).
+char(p,10732).
+char(o,10733).
+char(4,10734).
+char(8,10735).
+char(8,10736).
+char(6,10737).
+char(c,10738).
+char(c,10739).
+char(m,10740).
+char(o,10741).
+char(2,10742).
+char(1,10743).
+char(9,10744).
+char(6,10745).
+char(p,10746).
+char(o,10747).
+char(2,10748).
+char(4,10749).
+char(4,10750).
+char(4,10751).
+char(m,10752).
+char(6,10753).
+char(7,10754).
+char(7,10755).
+char(6,10756).
+char(c,10757).
+char(c,10758).
+char(m,10759).
+char(6,10760).
+char(2,10761).
+char(3,10762).
+char(3,10763).
+char(c,10764).
+char(m,10765).
+char(o,10766).
+char(p,10767).
+char(4,10768).
+char(1,10769).
+char(0,10770).
+char(8,10771).
+char(c,10772).
+char(c,10773).
+char(c,10774).
+char(c,10775).
+char(m,10776).
+char(o,10777).
+char(3,10778).
+char(0,10779).
+char(8,10780).
+char(6,10781).
+char(p,10782).
+char(5,10783).
+char(0,10784).
+char(4,10785).
+char(4,10786).
+char(c,10787).
+char(p,10788).
+char(o,10789).
+char(1,10790).
+char(7,10791).
+char(2,10792).
+char(p,10793).
+char(o,10794).
+char(p,10795).
+char(o,10796).
+char(p,10797).
+char(4,10798).
+char(0,10799).
+char(3,10800).
+char(6,10801).
+char(p,10802).
+char(o,10803).
+char(8,10804).
+char(9,10805).
+char(0,10806).
+char(5,10807).
+char(c,10808).
+char(p,10809).
+char(o,10810).
+char(m,10811).
+char(o,10812).
+char(o,10813).
+char(o,10814).
+char(o,10815).
+char(m,10816).
+char(o,10817).
+char(o,10818).
+char(4,10819).
+char(0,10820).
+char(8,10821).
+char(5,10822).
+char(c,10823).
+char(p,10824).
+char(o,10825).
+char(p,10826).
+char(4,10827).
+char(6,10828).
+char(9,10829).
+char(0,10830).
+char(p,10831).
+char(o,10832).
+char(m,10833).
+char(1,10834).
+char(9,10835).
+char(4,10836).
+char(0,10837).
+char(c,10838).
+char(m,10839).
+char(o,10840).
+char(p,10841).
+char(o,10842).
+char(p,10843).
+char(2,10844).
+char(2,10845).
+char(6,10846).
+char(4,10847).
+char(c,10848).
+char(c,10849).
+char(c,10850).
+char(c,10851).
+char(c,10852).
+char(m,10853).
+char(o,10854).
+char(p,10855).
+char(7,10856).
+char(7,10857).
+char(0,10858).
+char(1,10859).
+char(p,10860).
+char(o,10861).
+char(p,10862).
+char(3,10863).
+char(3,10864).
+char(6,10865).
+char(8,10866).
+char(m,10867).
+char(o,10868).
+char(8,10869).
+char(1,10870).
+char(6,10871).
+char(5,10872).
+char(c,10873).
+char(c,10874).
+char(p,10875).
+char(1,10876).
+char(4,10877).
+char(3,10878).
+char(4,10879).
+char(c,10880).
+char(c,10881).
+char(c,10882).
+char(c,10883).
+char(c,10884).
+char(c,10885).
+char(c,10886).
+char(c,10887).
+char(m,10888).
+char(4,10889).
+char(5,10890).
+char(4,10891).
+char(3,10892).
+char(c,10893).
+char(p,10894).
+char(9,10895).
+char(2,10896).
+char(2,10897).
+char(2,10898).
+char(m,10899).
+char(9,10900).
+char(3,10901).
+char(9,10902).
+char(7,10903).
+char(p,10904).
+char(o,10905).
+char(p,10906).
+char(o,10907).
+char(m,10908).
+char(o,10909).
+char(p,10910).
+char(o,10911).
+char(o,10912).
+char(o,10913).
+char(m,10914).
+char(7,10915).
+char(9,10916).
+char(2,10917).
+char(7,10918).
+char(p,10919).
+char(o,10920).
+char(m,10921).
+char(o,10922).
+char(o,10923).
+char(2,10924).
+char(0,10925).
+char(6,10926).
+char(0,10927).
+char(m,10928).
+char(o,10929).
+char(p,10930).
+char(o,10931).
+char(o,10932).
+char(o,10933).
+char(m,10934).
+char(o,10935).
+char(p,10936).
+char(o,10937).
+char(p,10938).
+char(o,10939).
+char(p,10940).
+char(6,10941).
+char(5,10942).
+char(9,10943).
+char(1,10944).
+char(c,10945).
+char(p,10946).
+char(o,10947).
+char(8,10948).
+char(4,10949).
+char(8,10950).
+char(2,10951).
+char(m,10952).
+char(o,10953).
+char(p,10954).
+char(9,10955).
+char(1,10956).
+char(2,10957).
+char(5,10958).
+char(c,10959).
+char(p,10960).
+char(o,10961).
+char(p,10962).
+char(o,10963).
+char(m,10964).
+char(o,10965).
+char(m,10966).
+char(5,10967).
+char(2,10968).
+char(4,10969).
+char(7,10970).
+char(p,10971).
+char(o,10972).
+char(p,10973).
+char(8,10974).
+char(0,10975).
+char(6,10976).
+char(2,10977).
+char(c,10978).
+char(c,10979).
+char(c,10980).
+char(p,10981).
+char(o,10982).
+char(m,10983).
+char(4,10984).
+char(2,10985).
+char(5,10986).
+char(4,10987).
+char(p,10988).
+char(o,10989).
+char(m,10990).
+char(2,10991).
+char(7,10992).
+char(6,10993).
+char(c,10994).
+char(p,10995).
+char(7,10996).
+char(9,10997).
+char(9,10998).
+char(0,10999).
+char(c,11000).
+char(p,11001).
+char(1,11002).
+char(7,11003).
+char(1,11004).
+char(4,11005).
+char(p,11006).
+char(8,11007).
+char(4,11008).
+char(6,11009).
+char(c,11010).
+char(p,11011).
+char(o,11012).
+char(p,11013).
+char(8,11014).
+char(8,11015).
+char(4,11016).
+char(8,11017).
+char(c,11018).
+char(m,11019).
+char(o,11020).
+char(m,11021).
+char(o,11022).
+char(p,11023).
+char(o,11024).
+char(4,11025).
+char(6,11026).
+char(4,11027).
+char(4,11028).
+char(c,11029).
+char(p,11030).
+char(o,11031).
+char(m,11032).
+char(8,11033).
+char(4,11034).
+char(2,11035).
+char(1,11036).
+char(m,11037).
+char(o,11038).
+char(p,11039).
+char(o,11040).
+char(2,11041).
+char(0,11042).
+char(8,11043).
+char(6,11044).
+char(c,11045).
+char(c,11046).
+char(p,11047).
+char(o,11048).
+char(m,11049).
+char(o,11050).
+char(m,11051).
+char(8,11052).
+char(1,11053).
+char(2,11054).
+char(c,11055).
+char(c,11056).
+char(p,11057).
+char(o,11058).
+char(p,11059).
+char(1,11060).
+char(8,11061).
+char(2,11062).
+char(1,11063).
+char(p,11064).
+char(1,11065).
+char(2,11066).
+char(8,11067).
+char(6,11068).
+char(p,11069).
+char(o,11070).
+char(p,11071).
+char(8,11072).
+char(9,11073).
+char(3,11074).
+char(2,11075).
+char(c,11076).
+char(c,11077).
+char(m,11078).
+char(7,11079).
+char(8,11080).
+char(0,11081).
+char(9,11082).
+char(c,11083).
+char(m,11084).
+char(1,11085).
+char(7,11086).
+char(4,11087).
+char(3,11088).
+char(c,11089).
+char(c,11090).
+char(c,11091).
+char(m,11092).
+char(8,11093).
+char(7,11094).
+char(9,11095).
+char(0,11096).
+char(m,11097).
+char(6,11098).
+char(3,11099).
+char(6,11100).
+char(4,11101).
+char(p,11102).
+char(o,11103).
+char(o,11104).
+char(o,11105).
+char(m,11106).
+char(o,11107).
+char(p,11108).
+char(9,11109).
+char(8,11110).
+char(3,11111).
+char(8,11112).
+char(p,11113).
+char(3,11114).
+char(1,11115).
+char(7,11116).
+char(1,11117).
+char(p,11118).
+char(o,11119).
+char(p,11120).
+char(6,11121).
+char(7,11122).
+char(7,11123).
+char(3,11124).
+char(c,11125).
+char(p,11126).
+char(1,11127).
+char(5,11128).
+char(8,11129).
+char(9,11130).
+char(p,11131).
+char(o,11132).
+char(m,11133).
+char(4,11134).
+char(0,11135).
+char(0,11136).
+char(0,11137).
+char(c,11138).
+char(c,11139).
+char(m,11140).
+char(9,11141).
+char(8,11142).
+char(2,11143).
+char(c,11144).
+char(c,11145).
+char(m,11146).
+char(7,11147).
+char(6,11148).
+char(1,11149).
+char(4,11150).
+char(p,11151).
+char(6,11152).
+char(7,11153).
+char(5,11154).
+char(m,11155).
+char(o,11156).
+char(p,11157).
+char(2,11158).
+char(6,11159).
+char(3,11160).
+char(8,11161).
+char(m,11162).
+char(6,11163).
+char(8,11164).
+char(6,11165).
+char(5,11166).
+char(p,11167).
+char(6,11168).
+char(3,11169).
+char(7,11170).
+char(3,11171).
+char(c,11172).
+char(p,11173).
+char(8,11174).
+char(8,11175).
+char(6,11176).
+char(9,11177).
+char(p,11178).
+char(o,11179).
+char(1,11180).
+char(6,11181).
+char(4,11182).
+char(5,11183).
+char(c,11184).
+char(p,11185).
+char(o,11186).
+char(p,11187).
+char(o,11188).
+char(m,11189).
+char(o,11190).
+char(p,11191).
+char(o,11192).
+char(9,11193).
+char(2,11194).
+char(7,11195).
+char(8,11196).
+char(p,11197).
+char(o,11198).
+char(m,11199).
+char(o,11200).
+char(p,11201).
+char(8,11202).
+char(7,11203).
+char(5,11204).
+char(1,11205).
+char(c,11206).
+char(m,11207).
+char(2,11208).
+char(3,11209).
+char(7,11210).
+char(0,11211).
+char(p,11212).
+char(o,11213).
+char(m,11214).
+char(o,11215).
+char(m,11216).
+char(o,11217).
+char(o,11218).
+char(2,11219).
+char(9,11220).
+char(1,11221).
+char(6,11222).
+char(p,11223).
+char(o,11224).
+char(m,11225).
+char(9,11226).
+char(2,11227).
+char(5,11228).
+char(3,11229).
+char(c,11230).
+char(c,11231).
+char(c,11232).
+char(c,11233).
+char(c,11234).
+char(c,11235).
+char(c,11236).
+char(m,11237).
+char(o,11238).
+char(3,11239).
+char(6,11240).
+char(4,11241).
+char(1,11242).
+char(c,11243).
+char(c,11244).
+char(c,11245).
+char(c,11246).
+char(p,11247).
+char(o,11248).
+char(m,11249).
+char(o,11250).
+char(p,11251).
+char(3,11252).
+char(2,11253).
+char(4,11254).
+char(8,11255).
+char(c,11256).
+char(c,11257).
+char(c,11258).
+char(m,11259).
+char(o,11260).
+char(m,11261).
+char(1,11262).
+char(6,11263).
+char(9,11264).
+char(2,11265).
+char(p,11266).
+char(8,11267).
+char(6,11268).
+char(4,11269).
+char(3,11270).
+char(c,11271).
+char(m,11272).
+char(6,11273).
+char(6,11274).
+char(3,11275).
+char(5,11276).
+char(p,11277).
+char(o,11278).
+char(p,11279).
+char(4,11280).
+char(1,11281).
+char(7,11282).
+char(6,11283).
+char(m,11284).
+char(o,11285).
+char(m,11286).
+char(5,11287).
+char(6,11288).
+char(5,11289).
+char(c,11290).
+char(c,11291).
+char(p,11292).
+char(o,11293).
+char(p,11294).
+char(o,11295).
+char(m,11296).
+char(8,11297).
+char(7,11298).
+char(8,11299).
+char(1,11300).
+char(p,11301).
+char(5,11302).
+char(7,11303).
+char(4,11304).
+char(7,11305).
+char(m,11306).
+char(4,11307).
+char(8,11308).
+char(8,11309).
+char(4,11310).
+char(p,11311).
+char(4,11312).
+char(3,11313).
+char(4,11314).
+char(6,11315).
+char(m,11316).
+char(o,11317).
+char(p,11318).
+char(o,11319).
+char(m,11320).
+char(o,11321).
+char(p,11322).
+char(4,11323).
+char(2,11324).
+char(9,11325).
+char(8,11326).
+char(c,11327).
+char(c,11328).
+char(c,11329).
+char(c,11330).
+char(m,11331).
+char(6,11332).
+char(7,11333).
+char(3,11334).
+char(9,11335).
+char(p,11336).
+char(7,11337).
+char(6,11338).
+char(3,11339).
+char(4,11340).
+char(m,11341).
+char(o,11342).
+char(p,11343).
+char(o,11344).
+char(m,11345).
+char(o,11346).
+char(m,11347).
+char(6,11348).
+char(0,11349).
+char(2,11350).
+char(c,11351).
+char(c,11352).
+char(c,11353).
+char(c,11354).
+char(m,11355).
+char(o,11356).
+char(p,11357).
+char(1,11358).
+char(1,11359).
+char(1,11360).
+char(4,11361).
+char(p,11362).
+char(2,11363).
+char(4,11364).
+char(1,11365).
+char(c,11366).
+char(m,11367).
+char(o,11368).
+char(o,11369).
+char(p,11370).
+char(o,11371).
+char(m,11372).
+char(o,11373).
+char(p,11374).
+char(o,11375).
+char(o,11376).
+char(m,11377).
+char(2,11378).
+char(9,11379).
+char(7,11380).
+char(6,11381).
+char(c,11382).
+char(c,11383).
+char(c,11384).
+char(c,11385).
+char(p,11386).
+char(o,11387).
+char(o,11388).
+char(m,11389).
+char(7,11390).
+char(0,11391).
+char(4,11392).
+char(9,11393).
+char(c,11394).
+char(c,11395).
+char(m,11396).
+char(o,11397).
+char(8,11398).
+char(2,11399).
+char(1,11400).
+char(7,11401).
+char(c,11402).
+char(p,11403).
+char(6,11404).
+char(5,11405).
+char(2,11406).
+char(9,11407).
+char(c,11408).
+char(p,11409).
+char(2,11410).
+char(2,11411).
+char(3,11412).
+char(4,11413).
+char(m,11414).
+char(5,11415).
+char(4,11416).
+char(8,11417).
+char(7,11418).
+char(m,11419).
+char(2,11420).
+char(6,11421).
+char(2,11422).
+char(4,11423).
+char(c,11424).
+char(c,11425).
+char(c,11426).
+char(m,11427).
+char(9,11428).
+char(6,11429).
+char(9,11430).
+char(3,11431).
+char(p,11432).
+char(2,11433).
+char(8,11434).
+char(2,11435).
+char(1,11436).
+char(c,11437).
+char(c,11438).
+char(c,11439).
+char(c,11440).
+char(m,11441).
+char(5,11442).
+char(9,11443).
+char(3,11444).
+char(8,11445).
+char(c,11446).
+char(p,11447).
+char(o,11448).
+char(m,11449).
+char(o,11450).
+char(m,11451).
+char(o,11452).
+char(p,11453).
+char(9,11454).
+char(3,11455).
+char(8,11456).
+char(5,11457).
+char(c,11458).
+char(m,11459).
+char(3,11460).
+char(5,11461).
+char(7,11462).
+char(4,11463).
+char(c,11464).
+char(m,11465).
+char(1,11466).
+char(0,11467).
+char(1,11468).
+char(1,11469).
+char(p,11470).
+char(o,11471).
+char(m,11472).
+char(o,11473).
+char(o,11474).
+char(m,11475).
+char(1,11476).
+char(9,11477).
+char(7,11478).
+char(c,11479).
+char(c,11480).
+char(c,11481).
+char(m,11482).
+char(o,11483).
+char(m,11484).
+char(o,11485).
+char(3,11486).
+char(0,11487).
+char(0,11488).
+char(4,11489).
+char(p,11490).
+char(8,11491).
+char(8,11492).
+char(0,11493).
+char(3,11494).
+char(c,11495).
+char(c,11496).
+char(m,11497).
+char(3,11498).
+char(8,11499).
+char(9,11500).
+char(2,11501).
+char(p,11502).
+char(5,11503).
+char(9,11504).
+char(1,11505).
+char(2,11506).
+char(c,11507).
+char(m,11508).
+char(o,11509).
+char(p,11510).
+char(6,11511).
+char(0,11512).
+char(7,11513).
+char(c,11514).
+char(c,11515).
+char(m,11516).
+char(8,11517).
+char(8,11518).
+char(0,11519).
+char(p,11520).
+char(o,11521).
+char(p,11522).
+char(3,11523).
+char(2,11524).
+char(9,11525).
+char(1,11526).
+char(c,11527).
+char(c,11528).
+char(m,11529).
+char(o,11530).
+char(p,11531).
+char(o,11532).
+char(m,11533).
+char(o,11534).
+char(p,11535).
+char(o,11536).
+char(p,11537).
+char(o,11538).
+char(o,11539).
+char(p,11540).
+char(o,11541).
+char(m,11542).
+char(o,11543).
+char(p,11544).
+char(8,11545).
+char(2,11546).
+char(7,11547).
+char(1,11548).
+char(c,11549).
+char(c,11550).
+char(c,11551).
+char(p,11552).
+char(o,11553).
+char(m,11554).
+char(4,11555).
+char(5,11556).
+char(9,11557).
+char(1,11558).
+char(p,11559).
+char(9,11560).
+char(3,11561).
+char(7,11562).
+char(1,11563).
+char(c,11564).
+char(p,11565).
+char(o,11566).
+char(m,11567).
+char(8,11568).
+char(8,11569).
+char(9,11570).
+char(9,11571).
+char(c,11572).
+char(p,11573).
+char(3,11574).
+char(4,11575).
+char(3,11576).
+char(c,11577).
+char(c,11578).
+char(c,11579).
+char(m,11580).
+char(9,11581).
+char(1,11582).
+char(5,11583).
+char(7,11584).
+char(p,11585).
+char(o,11586).
+char(p,11587).
+char(o,11588).
+char(m,11589).
+char(4,11590).
+char(8,11591).
+char(4,11592).
+char(4,11593).
+char(c,11594).
+char(c,11595).
+char(p,11596).
+char(o,11597).
+char(p,11598).
+char(9,11599).
+char(4,11600).
+char(5,11601).
+char(6,11602).
+char(p,11603).
+char(o,11604).
+char(p,11605).
+char(1,11606).
+char(0,11607).
+char(4,11608).
+char(8,11609).
+char(p,11610).
+char(o,11611).
+char(m,11612).
+char(7,11613).
+char(1,11614).
+char(8,11615).
+char(9,11616).
+char(c,11617).
+char(m,11618).
+char(6,11619).
+char(9,11620).
+char(8,11621).
+char(1,11622).
+char(p,11623).
+char(2,11624).
+char(3,11625).
+char(6,11626).
+char(1,11627).
+char(c,11628).
+char(p,11629).
+char(o,11630).
+char(p,11631).
+char(o,11632).
+char(o,11633).
+char(m,11634).
+char(6,11635).
+char(6,11636).
+char(6,11637).
+char(7,11638).
+char(p,11639).
+char(o,11640).
+char(m,11641).
+char(4,11642).
+char(0,11643).
+char(9,11644).
+char(3,11645).
+char(c,11646).
+char(m,11647).
+char(5,11648).
+char(5,11649).
+char(5,11650).
+char(1,11651).
+char(m,11652).
+char(o,11653).
+char(1,11654).
+char(1,11655).
+char(5,11656).
+char(0,11657).
+char(c,11658).
+char(c,11659).
+char(m,11660).
+char(1,11661).
+char(5,11662).
+char(9,11663).
+char(8,11664).
+char(c,11665).
+char(c,11666).
+char(c,11667).
+char(c,11668).
+char(p,11669).
+char(o,11670).
+char(m,11671).
+char(o,11672).
+char(m,11673).
+char(o,11674).
+char(m,11675).
+char(o,11676).
+char(p,11677).
+char(5,11678).
+char(0,11679).
+char(6,11680).
+char(3,11681).
+char(c,11682).
+char(m,11683).
+char(o,11684).
+char(m,11685).
+char(o,11686).
+char(m,11687).
+char(o,11688).
+char(o,11689).
+char(m,11690).
+char(5,11691).
+char(0,11692).
+char(9,11693).
+char(1,11694).
+char(c,11695).
+char(p,11696).
+char(2,11697).
+char(3,11698).
+char(9,11699).
+char(9,11700).
+char(m,11701).
+char(o,11702).
+char(4,11703).
+char(6,11704).
+char(1,11705).
+char(1,11706).
+char(m,11707).
+char(o,11708).
+char(m,11709).
+char(1,11710).
+char(8,11711).
+char(9,11712).
+char(p,11713).
+char(9,11714).
+char(0,11715).
+char(7,11716).
+char(8,11717).
+char(p,11718).
+char(o,11719).
+char(p,11720).
+char(o,11721).
+char(m,11722).
+char(o,11723).
+char(o,11724).
+char(p,11725).
+char(o,11726).
+char(2,11727).
+char(7,11728).
+char(0,11729).
+char(8,11730).
+char(p,11731).
+char(o,11732).
+char(m,11733).
+char(4,11734).
+char(8,11735).
+char(7,11736).
+char(4,11737).
+char(p,11738).
+char(6,11739).
+char(5,11740).
+char(1,11741).
+char(6,11742).
+char(c,11743).
+char(c,11744).
+char(p,11745).
+char(9,11746).
+char(8,11747).
+char(4,11748).
+char(1,11749).
+char(c,11750).
+char(c,11751).
+char(p,11752).
+char(6,11753).
+char(2,11754).
+char(4,11755).
+char(5,11756).
+char(m,11757).
+char(7,11758).
+char(7,11759).
+char(5,11760).
+char(1,11761).
+char(p,11762).
+char(4,11763).
+char(6,11764).
+char(0,11765).
+char(1,11766).
+char(m,11767).
+char(3,11768).
+char(8,11769).
+char(0,11770).
+char(7,11771).
+char(c,11772).
+char(m,11773).
+char(6,11774).
+char(5,11775).
+char(6,11776).
+char(2,11777).
+char(m,11778).
+char(o,11779).
+char(4,11780).
+char(6,11781).
+char(1,11782).
+char(3,11783).
+char(c,11784).
+char(c,11785).
+char(m,11786).
+char(2,11787).
+char(3,11788).
+char(2,11789).
+char(c,11790).
+char(c,11791).
+char(p,11792).
+char(4,11793).
+char(5,11794).
+char(0,11795).
+char(2,11796).
+char(c,11797).
+char(p,11798).
+char(4,11799).
+char(4,11800).
+char(9,11801).
+char(1,11802).
+char(c,11803).
+char(m,11804).
+char(9,11805).
+char(3,11806).
+char(0,11807).
+char(9,11808).
+char(c,11809).
+char(c,11810).
+char(p,11811).
+char(o,11812).
+char(m,11813).
+char(o,11814).
+char(o,11815).
+char(m,11816).
+char(o,11817).
+char(8,11818).
+char(3,11819).
+char(7,11820).
+char(8,11821).
+char(m,11822).
+char(o,11823).
+char(o,11824).
+char(p,11825).
+char(7,11826).
+char(6,11827).
+char(3,11828).
+char(7,11829).
+char(m,11830).
+char(7,11831).
+char(0,11832).
+char(5,11833).
+char(0,11834).
+char(m,11835).
+char(1,11836).
+char(5,11837).
+char(6,11838).
+char(6,11839).
+char(c,11840).
+char(c,11841).
+char(m,11842).
+char(o,11843).
+char(o,11844).
+char(p,11845).
+char(8,11846).
+char(7,11847).
+char(9,11848).
+char(p,11849).
+char(o,11850).
+char(p,11851).
+char(o,11852).
+char(m,11853).
+char(o,11854).
+char(p,11855).
+char(o,11856).
+char(p,11857).
+char(o,11858).
+char(m,11859).
+char(o,11860).
+char(o,11861).
+char(p,11862).
+char(2,11863).
+char(6,11864).
+char(3,11865).
+char(2,11866).
+char(c,11867).
+char(p,11868).
+char(2,11869).
+char(3,11870).
+char(2,11871).
+char(7,11872).
+char(p,11873).
+char(4,11874).
+char(9,11875).
+char(2,11876).
+char(7,11877).
+char(p,11878).
+char(9,11879).
+char(4,11880).
+char(1,11881).
+char(8,11882).
+char(c,11883).
+char(p,11884).
+char(2,11885).
+char(8,11886).
+char(3,11887).
+char(3,11888).
+char(c,11889).
+char(c,11890).
+char(c,11891).
+char(c,11892).
+char(m,11893).
+char(3,11894).
+char(3,11895).
+char(0,11896).
+char(9,11897).
+char(p,11898).
+char(o,11899).
+char(m,11900).
+char(6,11901).
+char(7,11902).
+char(1,11903).
+char(5,11904).
+char(p,11905).
+char(7,11906).
+char(9,11907).
+char(9,11908).
+char(2,11909).
+char(m,11910).
+char(o,11911).
+char(m,11912).
+char(5,11913).
+char(6,11914).
+char(6,11915).
+char(8,11916).
+char(m,11917).
+char(8,11918).
+char(1,11919).
+char(2,11920).
+char(1,11921).
+char(p,11922).
+char(o,11923).
+char(9,11924).
+char(5,11925).
+char(0,11926).
+char(5,11927).
+char(c,11928).
+char(p,11929).
+char(o,11930).
+char(m,11931).
+char(o,11932).
+char(o,11933).
+char(o,11934).
+char(m,11935).
+char(9,11936).
+char(1,11937).
+char(3,11938).
+char(9,11939).
+char(c,11940).
+char(p,11941).
+char(1,11942).
+char(6,11943).
+char(0,11944).
+char(1,11945).
+char(c,11946).
+char(m,11947).
+char(6,11948).
+char(6,11949).
+char(7,11950).
+char(3,11951).
+char(c,11952).
+char(p,11953).
+char(3,11954).
+char(0,11955).
+char(3,11956).
+char(5,11957).
+char(c,11958).
+char(p,11959).
+char(8,11960).
+char(3,11961).
+char(0,11962).
+char(4,11963).
+char(c,11964).
+char(p,11965).
+char(o,11966).
+char(o,11967).
+char(m,11968).
+char(2,11969).
+char(3,11970).
+char(5,11971).
+char(8,11972).
+char(c,11973).
+char(p,11974).
+char(7,11975).
+char(4,11976).
+char(7,11977).
+char(8,11978).
+char(m,11979).
+char(o,11980).
+char(o,11981).
+char(7,11982).
+char(8,11983).
+char(8,11984).
+char(9,11985).
+char(c,11986).
+char(c,11987).
+char(c,11988).
+char(c,11989).
+char(p,11990).
+char(2,11991).
+char(9,11992).
+char(3,11993).
+char(5,11994).
+char(c,11995).
+char(c,11996).
+char(m,11997).
+char(o,11998).
+char(o,11999).
+char(p,12000).
+char(o,12001).
+char(p,12002).
+char(5,12003).
+char(4,12004).
+char(9,12005).
+char(0,12006).
+char(p,12007).
+char(7,12008).
+char(8,12009).
+char(9,12010).
+char(6,12011).
+char(c,12012).
+char(c,12013).
+char(m,12014).
+char(6,12015).
+char(4,12016).
+char(0,12017).
+char(4,12018).
+char(c,12019).
+char(p,12020).
+char(6,12021).
+char(1,12022).
+char(5,12023).
+char(0,12024).
+char(m,12025).
+char(5,12026).
+char(6,12027).
+char(9,12028).
+char(4,12029).
+char(m,12030).
+char(o,12031).
+char(m,12032).
+char(1,12033).
+char(1,12034).
+char(7,12035).
+char(0,12036).
+char(p,12037).
+char(o,12038).
+char(m,12039).
+char(3,12040).
+char(9,12041).
+char(6,12042).
+char(0,12043).
+char(c,12044).
+char(m,12045).
+char(o,12046).
+char(o,12047).
+char(m,12048).
+char(o,12049).
+char(5,12050).
+char(5,12051).
+char(2,12052).
+char(9,12053).
+char(p,12054).
+char(o,12055).
+char(p,12056).
+char(o,12057).
+char(m,12058).
+char(o,12059).
+char(p,12060).
+char(6,12061).
+char(7,12062).
+char(6,12063).
+char(4,12064).
+char(m,12065).
+char(4,12066).
+char(8,12067).
+char(1,12068).
+char(2,12069).
+char(m,12070).
+char(9,12071).
+char(1,12072).
+char(2,12073).
+char(4,12074).
+char(m,12075).
+char(o,12076).
+char(p,12077).
+char(o,12078).
+char(m,12079).
+char(4,12080).
+char(7,12081).
+char(8,12082).
+char(8,12083).
+char(c,12084).
+char(c,12085).
+char(c,12086).
+char(c,12087).
+char(c,12088).
+char(m,12089).
+char(o,12090).
+char(m,12091).
+char(2,12092).
+char(3,12093).
+char(7,12094).
+char(3,12095).
+char(c,12096).
+char(c,12097).
+char(p,12098).
+char(3,12099).
+char(7,12100).
+char(8,12101).
+char(4,12102).
+char(c,12103).
+char(c,12104).
+char(p,12105).
+char(1,12106).
+char(1,12107).
+char(0,12108).
+char(9,12109).
+char(c,12110).
+char(m,12111).
+char(o,12112).
+char(m,12113).
+char(o,12114).
+char(m,12115).
+char(4,12116).
+char(6,12117).
+char(8,12118).
+char(4,12119).
+char(p,12120).
+char(2,12121).
+char(4,12122).
+char(6,12123).
+char(1,12124).
+char(p,12125).
+char(o,12126).
+char(p,12127).
+char(7,12128).
+char(8,12129).
+char(3,12130).
+char(9,12131).
+char(m,12132).
+char(o,12133).
+char(p,12134).
+char(4,12135).
+char(4,12136).
+char(8,12137).
+char(2,12138).
+char(c,12139).
+char(c,12140).
+char(p,12141).
+char(o,12142).
+char(m,12143).
+char(o,12144).
+char(m,12145).
+char(6,12146).
+char(5,12147).
+char(6,12148).
+char(7,12149).
+char(p,12150).
+char(4,12151).
+char(2,12152).
+char(7,12153).
+char(c,12154).
+char(m,12155).
+char(3,12156).
+char(5,12157).
+char(1,12158).
+char(4,12159).
+char(m,12160).
+char(8,12161).
+char(7,12162).
+char(6,12163).
+char(9,12164).
+char(c,12165).
+char(c,12166).
+char(c,12167).
+char(c,12168).
+char(m,12169).
+char(o,12170).
+char(o,12171).
+char(p,12172).
+char(8,12173).
+char(8,12174).
+char(6,12175).
+char(p,12176).
+char(6,12177).
+char(2,12178).
+char(5,12179).
+char(5,12180).
+char(c,12181).
+char(p,12182).
+char(o,12183).
+char(m,12184).
+char(o,12185).
+char(o,12186).
+char(m,12187).
+char(6,12188).
+char(5,12189).
+char(7,12190).
+char(1,12191).
+char(p,12192).
+char(9,12193).
+char(6,12194).
+char(9,12195).
+char(2,12196).
+char(c,12197).
+char(m,12198).
+char(o,12199).
+char(m,12200).
+char(9,12201).
+char(6,12202).
+char(9,12203).
+char(0,12204).
+char(c,12205).
+char(m,12206).
+char(o,12207).
+char(m,12208).
+char(o,12209).
+char(p,12210).
+char(o,12211).
+char(m,12212).
+char(7,12213).
+char(8,12214).
+char(2,12215).
+char(1,12216).
+char(c,12217).
+char(c,12218).
+char(m,12219).
+char(o,12220).
+char(m,12221).
+char(5,12222).
+char(1,12223).
+char(5,12224).
+char(0,12225).
+char(m,12226).
+char(7,12227).
+char(3,12228).
+char(5,12229).
+char(1,12230).
+char(c,12231).
+char(m,12232).
+char(9,12233).
+char(7,12234).
+char(7,12235).
+char(4,12236).
+char(p,12237).
+char(6,12238).
+char(1,12239).
+char(9,12240).
+char(m,12241).
+char(o,12242).
+char(4,12243).
+char(6,12244).
+char(9,12245).
+char(4,12246).
+char(m,12247).
+char(2,12248).
+char(1,12249).
+char(8,12250).
+char(0,12251).
+char(p,12252).
+char(o,12253).
+char(1,12254).
+char(3,12255).
+char(2,12256).
+char(8,12257).
+char(m,12258).
+char(o,12259).
+char(m,12260).
+char(3,12261).
+char(2,12262).
+char(6,12263).
+char(6,12264).
+char(c,12265).
+char(c,12266).
+char(m,12267).
+char(o,12268).
+char(p,12269).
+char(2,12270).
+char(1,12271).
+char(8,12272).
+char(0,12273).
+char(m,12274).
+char(2,12275).
+char(2,12276).
+char(3,12277).
+char(1,12278).
+char(c,12279).
+char(p,12280).
+char(o,12281).
+char(p,12282).
+char(o,12283).
+char(m,12284).
+char(7,12285).
+char(2,12286).
+char(6,12287).
+char(3,12288).
+char(c,12289).
+char(c,12290).
+char(p,12291).
+char(o,12292).
+char(m,12293).
+char(o,12294).
+char(m,12295).
+char(7,12296).
+char(4,12297).
+char(m,12298).
+char(o,12299).
+char(m,12300).
+char(o,12301).
+char(p,12302).
+char(o,12303).
+char(m,12304).
+char(3,12305).
+char(1,12306).
+char(1,12307).
+char(7,12308).
+char(p,12309).
+char(3,12310).
+char(4,12311).
+char(7,12312).
+char(9,12313).
+char(c,12314).
+char(p,12315).
+char(2,12316).
+char(7,12317).
+char(3,12318).
+char(7,12319).
+char(c,12320).
+char(p,12321).
+char(3,12322).
+char(9,12323).
+char(1,12324).
+char(3,12325).
+char(m,12326).
+char(4,12327).
+char(5,12328).
+char(9,12329).
+char(4,12330).
+char(m,12331).
+char(8,12332).
+char(7,12333).
+char(3,12334).
+char(0,12335).
+char(c,12336).
+char(c,12337).
+char(c,12338).
+char(c,12339).
+char(m,12340).
+char(8,12341).
+char(1,12342).
+char(6,12343).
+char(9,12344).
+char(p,12345).
+char(o,12346).
+char(m,12347).
+char(o,12348).
+char(1,12349).
+char(7,12350).
+char(6,12351).
+char(6,12352).
+char(c,12353).
+char(c,12354).
+char(c,12355).
+char(c,12356).
+char(c,12357).
+char(c,12358).
+char(c,12359).
+char(c,12360).
+char(m,12361).
+char(o,12362).
+char(m,12363).
+char(1,12364).
+char(4,12365).
+char(9,12366).
+char(3,12367).
+char(c,12368).
+char(c,12369).
+char(c,12370).
+char(c,12371).
+char(p,12372).
+char(1,12373).
+char(9,12374).
+char(1,12375).
+char(3,12376).
+char(c,12377).
+char(m,12378).
+char(1,12379).
+char(7,12380).
+char(8,12381).
+char(1,12382).
+char(c,12383).
+char(c,12384).
+char(m,12385).
+char(o,12386).
+char(p,12387).
+char(5,12388).
+char(7,12389).
+char(5,12390).
+char(5,12391).
+char(c,12392).
+char(c,12393).
+char(c,12394).
+char(c,12395).
+char(p,12396).
+char(o,12397).
+char(p,12398).
+char(2,12399).
+char(6,12400).
+char(4,12401).
+char(0,12402).
+char(p,12403).
+char(4,12404).
+char(0,12405).
+char(7,12406).
+char(2,12407).
+char(c,12408).
+char(p,12409).
+char(o,12410).
+char(o,12411).
+char(o,12412).
+char(m,12413).
+char(o,12414).
+char(m,12415).
+char(o,12416).
+char(p,12417).
+char(o,12418).
+char(2,12419).
+char(6,12420).
+char(3,12421).
+char(7,12422).
+char(m,12423).
+char(o,12424).
+char(m,12425).
+char(o,12426).
+char(p,12427).
+char(8,12428).
+char(4,12429).
+char(7,12430).
+char(m,12431).
+char(o,12432).
+char(o,12433).
+char(p,12434).
+char(9,12435).
+char(8,12436).
+char(3,12437).
+char(1,12438).
+char(c,12439).
+char(p,12440).
+char(o,12441).
+char(p,12442).
+char(9,12443).
+char(0,12444).
+char(7,12445).
+char(1,12446).
+char(m,12447).
+char(o,12448).
+char(m,12449).
+char(3,12450).
+char(7,12451).
+char(6,12452).
+char(2,12453).
+char(m,12454).
+char(o,12455).
+char(m,12456).
+char(7,12457).
+char(6,12458).
+char(9,12459).
+char(c,12460).
+char(c,12461).
+char(p,12462).
+char(o,12463).
+char(m,12464).
+char(o,12465).
+char(p,12466).
+char(8,12467).
+char(2,12468).
+char(2,12469).
+char(7,12470).
+char(p,12471).
+char(6,12472).
+char(0,12473).
+char(5,12474).
+char(p,12475).
+char(1,12476).
+char(7,12477).
+char(6,12478).
+char(0,12479).
+char(p,12480).
+char(o,12481).
+char(p,12482).
+char(o,12483).
+char(p,12484).
+char(o,12485).
+char(8,12486).
+char(8,12487).
+char(5,12488).
+char(8,12489).
+char(m,12490).
+char(o,12491).
+char(m,12492).
+char(9,12493).
+char(4,12494).
+char(0,12495).
+char(8,12496).
+char(m,12497).
+char(o,12498).
+char(p,12499).
+char(5,12500).
+char(2,12501).
+char(1,12502).
+char(1,12503).
+char(c,12504).
+char(c,12505).
+char(p,12506).
+char(6,12507).
+char(4,12508).
+char(1,12509).
+char(8,12510).
+char(p,12511).
+char(1,12512).
+char(5,12513).
+char(9,12514).
+char(6,12515).
+char(c,12516).
+char(m,12517).
+char(1,12518).
+char(0,12519).
+char(0,12520).
+char(p,12521).
+char(6,12522).
+char(3,12523).
+char(7,12524).
+char(4,12525).
+char(m,12526).
+char(o,12527).
+char(m,12528).
+char(5,12529).
+char(9,12530).
+char(2,12531).
+char(7,12532).
+char(c,12533).
+char(p,12534).
+char(o,12535).
+char(o,12536).
+char(p,12537).
+char(6,12538).
+char(1,12539).
+char(5,12540).
+char(9,12541).
+char(p,12542).
+char(3,12543).
+char(2,12544).
+char(2,12545).
+char(5,12546).
+char(c,12547).
+char(c,12548).
+char(c,12549).
+char(c,12550).
+char(c,12551).
+char(p,12552).
+char(o,12553).
+char(m,12554).
+char(5,12555).
+char(8,12556).
+char(8,12557).
+char(4,12558).
+char(c,12559).
+char(p,12560).
+char(1,12561).
+char(9,12562).
+char(3,12563).
+char(7,12564).
+char(c,12565).
+char(m,12566).
+char(o,12567).
+char(p,12568).
+char(o,12569).
+char(m,12570).
+char(o,12571).
+char(7,12572).
+char(1,12573).
+char(9,12574).
+char(6,12575).
+char(c,12576).
+char(p,12577).
+char(4,12578).
+char(3,12579).
+char(0,12580).
+char(0,12581).
+char(p,12582).
+char(o,12583).
+char(p,12584).
+char(9,12585).
+char(0,12586).
+char(0,12587).
+char(9,12588).
+char(c,12589).
+char(m,12590).
+char(6,12591).
+char(6,12592).
+char(3,12593).
+char(0,12594).
+char(c,12595).
+char(p,12596).
+char(o,12597).
+char(m,12598).
+char(6,12599).
+char(6,12600).
+char(2,12601).
+char(9,12602).
+char(c,12603).
+char(p,12604).
+char(6,12605).
+char(0,12606).
+char(9,12607).
+char(0,12608).
+char(c,12609).
+char(p,12610).
+char(2,12611).
+char(0,12612).
+char(0,12613).
+char(m,12614).
+char(o,12615).
+char(p,12616).
+char(o,12617).
+char(p,12618).
+char(9,12619).
+char(6,12620).
+char(4,12621).
+char(7,12622).
+char(c,12623).
+char(c,12624).
+char(c,12625).
+char(c,12626).
+char(m,12627).
+char(o,12628).
+char(p,12629).
+char(8,12630).
+char(4,12631).
+char(7,12632).
+char(9,12633).
+char(p,12634).
+char(7,12635).
+char(6,12636).
+char(5,12637).
+char(0,12638).
+char(c,12639).
+char(c,12640).
+char(c,12641).
+char(c,12642).
+char(c,12643).
+char(c,12644).
+char(c,12645).
+char(c,12646).
+char(m,12647).
+char(9,12648).
+char(9,12649).
+char(7,12650).
+char(6,12651).
+char(c,12652).
+char(p,12653).
+char(2,12654).
+char(7,12655).
+char(0,12656).
+char(6,12657).
+char(c,12658).
+char(p,12659).
+char(o,12660).
+char(p,12661).
+char(1,12662).
+char(7,12663).
+char(8,12664).
+char(0,12665).
+char(m,12666).
+char(o,12667).
+char(p,12668).
+char(o,12669).
+char(m,12670).
+char(o,12671).
+char(p,12672).
+char(9,12673).
+char(3,12674).
+char(1,12675).
+char(0,12676).
+char(c,12677).
+char(c,12678).
+char(m,12679).
+char(o,12680).
+char(m,12681).
+char(o,12682).
+char(p,12683).
+char(6,12684).
+char(0,12685).
+char(1,12686).
+char(9,12687).
+char(c,12688).
+char(m,12689).
+char(9,12690).
+char(9,12691).
+char(4,12692).
+char(4,12693).
+char(m,12694).
+char(4,12695).
+char(1,12696).
+char(6,12697).
+char(1,12698).
+char(c,12699).
+char(c,12700).
+char(m,12701).
+char(o,12702).
+char(p,12703).
+char(5,12704).
+char(4,12705).
+char(8,12706).
+char(0,12707).
+char(m,12708).
+char(3,12709).
+char(2,12710).
+char(4,12711).
+char(7,12712).
+char(p,12713).
+char(6,12714).
+char(5,12715).
+char(5,12716).
+char(8,12717).
+char(c,12718).
+char(m,12719).
+char(7,12720).
+char(8,12721).
+char(5,12722).
+char(4,12723).
+char(m,12724).
+char(o,12725).
+char(p,12726).
+char(3,12727).
+char(4,12728).
+char(7,12729).
+char(8,12730).
+char(c,12731).
+char(p,12732).
+char(o,12733).
+char(m,12734).
+char(6,12735).
+char(5,12736).
+char(2,12737).
+char(8,12738).
+char(p,12739).
+char(5,12740).
+char(6,12741).
+char(3,12742).
+char(8,12743).
+char(c,12744).
+char(m,12745).
+char(3,12746).
+char(0,12747).
+char(2,12748).
+char(5,12749).
+char(c,12750).
+char(m,12751).
+char(5,12752).
+char(1,12753).
+char(6,12754).
+char(7,12755).
+char(c,12756).
+char(m,12757).
+char(o,12758).
+char(m,12759).
+char(o,12760).
+char(4,12761).
+char(3,12762).
+char(7,12763).
+char(3,12764).
+char(c,12765).
+char(c,12766).
+char(c,12767).
+char(m,12768).
+char(4,12769).
+char(1,12770).
+char(1,12771).
+char(1,12772).
+char(c,12773).
+char(c,12774).
+char(c,12775).
+char(m,12776).
+char(o,12777).
+char(4,12778).
+char(1,12779).
+char(2,12780).
+char(c,12781).
+char(c,12782).
+char(p,12783).
+char(o,12784).
+char(m,12785).
+char(o,12786).
+char(p,12787).
+char(o,12788).
+char(8,12789).
+char(4,12790).
+char(0,12791).
+char(8,12792).
+char(m,12793).
+char(1,12794).
+char(8,12795).
+char(5,12796).
+char(9,12797).
+char(p,12798).
+char(o,12799).
+char(p,12800).
+char(o,12801).
+char(o,12802).
+char(o,12803).
+char(o,12804).
+char(1,12805).
+char(2,12806).
+char(5,12807).
+char(p,12808).
+char(o,12809).
+char(p,12810).
+char(8,12811).
+char(8,12812).
+char(8,12813).
+char(4,12814).
+char(c,12815).
+char(c,12816).
+char(p,12817).
+char(o,12818).
+char(m,12819).
+char(o,12820).
+char(o,12821).
+char(2,12822).
+char(5,12823).
+char(8,12824).
+char(7,12825).
+char(p,12826).
+char(7,12827).
+char(0,12828).
+char(5,12829).
+char(0,12830).
+char(m,12831).
+char(1,12832).
+char(4,12833).
+char(4,12834).
+char(6,12835).
+char(p,12836).
+char(o,12837).
+char(m,12838).
+char(1,12839).
+char(7,12840).
+char(2,12841).
+char(5,12842).
+char(p,12843).
+char(4,12844).
+char(2,12845).
+char(6,12846).
+char(0,12847).
+char(c,12848).
+char(m,12849).
+char(3,12850).
+char(6,12851).
+char(1,12852).
+char(2,12853).
+char(c,12854).
+char(c,12855).
+char(p,12856).
+char(4,12857).
+char(2,12858).
+char(m,12859).
+char(o,12860).
+char(p,12861).
+char(9,12862).
+char(4,12863).
+char(2,12864).
+char(c,12865).
+char(p,12866).
+char(9,12867).
+char(8,12868).
+char(0,12869).
+char(4,12870).
+char(c,12871).
+char(m,12872).
+char(7,12873).
+char(5,12874).
+char(7,12875).
+char(7,12876).
+char(c,12877).
+char(c,12878).
+char(p,12879).
+char(o,12880).
+char(p,12881).
+char(5,12882).
+char(2,12883).
+char(8,12884).
+char(8,12885).
+char(p,12886).
+char(6,12887).
+char(1,12888).
+char(3,12889).
+char(1,12890).
+char(c,12891).
+char(c,12892).
+char(p,12893).
+char(o,12894).
+char(p,12895).
+char(o,12896).
+char(m,12897).
+char(o,12898).
+char(p,12899).
+char(6,12900).
+char(3,12901).
+char(8,12902).
+char(3,12903).
+char(c,12904).
+char(p,12905).
+char(o,12906).
+char(m,12907).
+char(6,12908).
+char(4,12909).
+char(0,12910).
+char(7,12911).
+char(m,12912).
+char(o,12913).
+char(o,12914).
+char(p,12915).
+char(8,12916).
+char(4,12917).
+char(3,12918).
+char(p,12919).
+char(7,12920).
+char(6,12921).
+char(9,12922).
+char(6,12923).
+char(c,12924).
+char(c,12925).
+char(p,12926).
+char(3,12927).
+char(0,12928).
+char(5,12929).
+char(3,12930).
+char(c,12931).
+char(m,12932).
+char(2,12933).
+char(4,12934).
+char(5,12935).
+char(1,12936).
+char(m,12937).
+char(o,12938).
+char(m,12939).
+char(3,12940).
+char(1,12941).
+char(3,12942).
+char(8,12943).
+char(p,12944).
+char(o,12945).
+char(m,12946).
+char(o,12947).
+char(m,12948).
+char(o,12949).
+char(p,12950).
+char(4,12951).
+char(6,12952).
+char(9,12953).
+char(5,12954).
+char(p,12955).
+char(1,12956).
+char(5,12957).
+char(2,12958).
+char(3,12959).
+char(c,12960).
+char(m,12961).
+char(o,12962).
+char(o,12963).
+char(m,12964).
+char(o,12965).
+char(m,12966).
+char(o,12967).
+char(p,12968).
+char(o,12969).
+char(p,12970).
+char(o,12971).
+char(m,12972).
+char(o,12973).
+char(m,12974).
+char(o,12975).
+char(p,12976).
+char(8,12977).
+char(6,12978).
+char(7,12979).
+char(8,12980).
+char(c,12981).
+char(p,12982).
+char(o,12983).
+char(p,12984).
+char(5,12985).
+char(9,12986).
+char(3,12987).
+char(8,12988).
+char(c,12989).
+char(m,12990).
+char(7,12991).
+char(4,12992).
+char(7,12993).
+char(8,12994).
+char(c,12995).
+char(c,12996).
+char(c,12997).
+char(m,12998).
+char(1,12999).
+char(2,13000).
+char(4,13001).
+char(6,13002).
+char(m,13003).
+char(o,13004).
+char(p,13005).
+char(o,13006).
+char(p,13007).
+char(2,13008).
+char(6,13009).
+char(3,13010).
+char(0,13011).
+char(c,13012).
+char(c,13013).
+char(c,13014).
+char(c,13015).
+char(c,13016).
+char(c,13017).
+char(c,13018).
+char(m,13019).
+char(1,13020).
+char(9,13021).
+char(0,13022).
+char(1,13023).
+char(m,13024).
+char(9,13025).
+char(2,13026).
+char(3,13027).
+char(8,13028).
+char(c,13029).
+char(p,13030).
+char(o,13031).
+char(m,13032).
+char(o,13033).
+char(p,13034).
+char(4,13035).
+char(9,13036).
+char(1,13037).
+char(5,13038).
+char(p,13039).
+char(6,13040).
+char(9,13041).
+char(6,13042).
+char(2,13043).
+char(m,13044).
+char(1,13045).
+char(9,13046).
+char(8,13047).
+char(1,13048).
+char(c,13049).
+char(c,13050).
+char(p,13051).
+char(o,13052).
+char(p,13053).
+char(8,13054).
+char(2,13055).
+char(5,13056).
+char(p,13057).
+char(o,13058).
+char(p,13059).
+char(8,13060).
+char(6,13061).
+char(6,13062).
+char(5,13063).
+char(c,13064).
+char(p,13065).
+char(o,13066).
+char(1,13067).
+char(0,13068).
+char(3,13069).
+char(7,13070).
+char(m,13071).
+char(4,13072).
+char(6,13073).
+char(6,13074).
+char(5,13075).
+char(p,13076).
+char(5,13077).
+char(5,13078).
+char(7,13079).
+char(2,13080).
+char(m,13081).
+char(o,13082).
+char(p,13083).
+char(o,13084).
+char(p,13085).
+char(o,13086).
+char(m,13087).
+char(o,13088).
+char(o,13089).
+char(o,13090).
+char(o,13091).
+char(m,13092).
+char(o,13093).
+char(p,13094).
+char(8,13095).
+char(9,13096).
+char(1,13097).
+char(1,13098).
+char(m,13099).
+char(6,13100).
+char(8,13101).
+char(3,13102).
+char(8,13103).
+char(c,13104).
+char(c,13105).
+char(c,13106).
+char(m,13107).
+char(1,13108).
+char(6,13109).
+char(0,13110).
+char(7,13111).
+char(p,13112).
+char(o,13113).
+char(4,13114).
+char(1,13115).
+char(2,13116).
+char(6,13117).
+char(p,13118).
+char(7,13119).
+char(6,13120).
+char(7,13121).
+char(1,13122).
+char(c,13123).
+char(m,13124).
+char(4,13125).
+char(8,13126).
+char(8,13127).
+char(1,13128).
+char(m,13129).
+char(o,13130).
+char(1,13131).
+char(1,13132).
+char(4,13133).
+char(9,13134).
+char(p,13135).
+char(8,13136).
+char(9,13137).
+char(3,13138).
+char(m,13139).
+char(8,13140).
+char(6,13141).
+char(0,13142).
+char(4,13143).
+char(m,13144).
+char(o,13145).
+char(m,13146).
+char(9,13147).
+char(9,13148).
+char(1,13149).
+char(1,13150).
+char(p,13151).
+char(o,13152).
+char(p,13153).
+char(4,13154).
+char(5,13155).
+char(0,13156).
+char(7,13157).
+char(c,13158).
+char(m,13159).
+char(o,13160).
+char(o,13161).
+char(m,13162).
+char(o,13163).
+char(p,13164).
+char(9,13165).
+char(2,13166).
+char(7,13167).
+char(m,13168).
+char(6,13169).
+char(3,13170).
+char(6,13171).
+char(2,13172).
+char(m,13173).
+char(8,13174).
+char(0,13175).
+char(7,13176).
+char(6,13177).
+char(c,13178).
+char(c,13179).
+char(c,13180).
+char(p,13181).
+char(8,13182).
+char(8,13183).
+char(0,13184).
+char(0,13185).
+char(m,13186).
+char(8,13187).
+char(0,13188).
+char(5,13189).
+char(7,13190).
+char(m,13191).
+char(1,13192).
+char(3,13193).
+char(8,13194).
+char(c,13195).
+char(p,13196).
+char(o,13197).
+char(p,13198).
+char(o,13199).
+char(m,13200).
+char(o,13201).
+char(4,13202).
+char(5,13203).
+char(1,13204).
+char(1,13205).
+char(c,13206).
+char(c,13207).
+char(m,13208).
+char(o,13209).
+char(p,13210).
+char(o,13211).
+char(2,13212).
+char(7,13213).
+char(1,13214).
+char(c,13215).
+char(c,13216).
+char(c,13217).
+char(m,13218).
+char(5,13219).
+char(3,13220).
+char(9,13221).
+char(8,13222).
+char(p,13223).
+char(4,13224).
+char(7,13225).
+char(6,13226).
+char(9,13227).
+char(p,13228).
+char(o,13229).
+char(m,13230).
+char(o,13231).
+char(p,13232).
+char(o,13233).
+char(m,13234).
+char(o,13235).
+char(m,13236).
+char(o,13237).
+char(o,13238).
+char(p,13239).
+char(o,13240).
+char(m,13241).
+char(5,13242).
+char(3,13243).
+char(4,13244).
+char(4,13245).
+char(p,13246).
+char(o,13247).
+char(p,13248).
+char(4,13249).
+char(1,13250).
+char(6,13251).
+char(9,13252).
+char(c,13253).
+char(p,13254).
+char(3,13255).
+char(5,13256).
+char(6,13257).
+char(5,13258).
+char(m,13259).
+char(9,13260).
+char(2,13261).
+char(6,13262).
+char(c,13263).
+char(p,13264).
+char(1,13265).
+char(5,13266).
+char(6,13267).
+char(5,13268).
+char(c,13269).
+char(c,13270).
+char(p,13271).
+char(o,13272).
+char(m,13273).
+char(1,13274).
+char(8,13275).
+char(6,13276).
+char(7,13277).
+char(m,13278).
+char(6,13279).
+char(0,13280).
+char(6,13281).
+char(9,13282).
+char(p,13283).
+char(3,13284).
+char(2,13285).
+char(2,13286).
+char(c,13287).
+char(c,13288).
+char(c,13289).
+char(m,13290).
+char(o,13291).
+char(p,13292).
+char(o,13293).
+char(p,13294).
+char(1,13295).
+char(4,13296).
+char(8,13297).
+char(c,13298).
+char(p,13299).
+char(o,13300).
+char(m,13301).
+char(8,13302).
+char(9,13303).
+char(8,13304).
+char(8,13305).
+char(m,13306).
+char(o,13307).
+char(6,13308).
+char(0,13309).
+char(0,13310).
+char(7,13311).
+char(c,13312).
+char(m,13313).
+char(3,13314).
+char(1,13315).
+char(6,13316).
+char(2,13317).
+char(p,13318).
+char(2,13319).
+char(2,13320).
+char(1,13321).
+char(2,13322).
+char(p,13323).
+char(9,13324).
+char(9,13325).
+char(2,13326).
+char(c,13327).
+char(p,13328).
+char(o,13329).
+char(8,13330).
+char(6,13331).
+char(8,13332).
+char(1,13333).
+char(c,13334).
+char(p,13335).
+char(o,13336).
+char(p,13337).
+char(3,13338).
+char(0,13339).
+char(5,13340).
+char(0,13341).
+char(c,13342).
+char(p,13343).
+char(5,13344).
+char(0,13345).
+char(c,13346).
+char(c,13347).
+char(c,13348).
+char(c,13349).
+char(c,13350).
+char(c,13351).
+char(c,13352).
+char(p,13353).
+char(3,13354).
+char(6,13355).
+char(9,13356).
+char(2,13357).
+char(c,13358).
+char(c,13359).
+char(c,13360).
+char(c,13361).
+char(m,13362).
+char(o,13363).
+char(m,13364).
+char(o,13365).
+char(m,13366).
+char(8,13367).
+char(4,13368).
+char(3,13369).
+char(5,13370).
+char(c,13371).
+char(m,13372).
+char(1,13373).
+char(7,13374).
+char(2,13375).
+char(4,13376).
+char(p,13377).
+char(2,13378).
+char(7,13379).
+char(9,13380).
+char(0,13381).
+char(c,13382).
+char(c,13383).
+char(c,13384).
+char(m,13385).
+char(2,13386).
+char(2,13387).
+char(0,13388).
+char(9,13389).
+char(c,13390).
+char(p,13391).
+char(o,13392).
+char(m,13393).
+char(o,13394).
+char(p,13395).
+char(3,13396).
+char(4,13397).
+char(7,13398).
+char(p,13399).
+char(o,13400).
+char(m,13401).
+char(7,13402).
+char(8,13403).
+char(3,13404).
+char(0,13405).
+char(p,13406).
+char(o,13407).
+char(o,13408).
+char(p,13409).
+char(8,13410).
+char(2,13411).
+char(0,13412).
+char(c,13413).
+char(m,13414).
+char(o,13415).
+char(m,13416).
+char(o,13417).
+char(m,13418).
+char(9,13419).
+char(7,13420).
+char(7,13421).
+char(4,13422).
+char(m,13423).
+char(5,13424).
+char(2,13425).
+char(3,13426).
+char(0,13427).
+char(p,13428).
+char(o,13429).
+char(p,13430).
+char(1,13431).
+char(0,13432).
+char(6,13433).
+char(m,13434).
+char(8,13435).
+char(2,13436).
+char(8,13437).
+char(0,13438).
+char(m,13439).
+char(o,13440).
+char(m,13441).
+char(o,13442).
+char(p,13443).
+char(9,13444).
+char(6,13445).
+char(0,13446).
+char(2,13447).
+char(c,13448).
+char(c,13449).
+char(c,13450).
+char(p,13451).
+char(6,13452).
+char(2,13453).
+char(8,13454).
+char(6,13455).
+char(m,13456).
+char(9,13457).
+char(1,13458).
+char(2,13459).
+char(6,13460).
+char(c,13461).
+char(c,13462).
+char(p,13463).
+char(1,13464).
+char(2,13465).
+char(3,13466).
+char(3,13467).
+char(m,13468).
+char(7,13469).
+char(5,13470).
+char(4,13471).
+char(c,13472).
+char(p,13473).
+char(7,13474).
+char(6,13475).
+char(6,13476).
+char(c,13477).
+char(c,13478).
+char(p,13479).
+char(o,13480).
+char(m,13481).
+char(5,13482).
+char(8,13483).
+char(8,13484).
+char(c,13485).
+char(c,13486).
+char(c,13487).
+char(c,13488).
+char(m,13489).
+char(5,13490).
+char(0,13491).
+char(6,13492).
+char(9,13493).
+char(c,13494).
+char(c,13495).
+char(c,13496).
+char(c,13497).
+char(m,13498).
+char(3,13499).
+char(3,13500).
+char(9,13501).
+char(8,13502).
+char(c,13503).
+char(m,13504).
+char(1,13505).
+char(1,13506).
+char(8,13507).
+char(2,13508).
+char(m,13509).
+char(9,13510).
+char(1,13511).
+char(7,13512).
+char(3,13513).
+char(m,13514).
+char(6,13515).
+char(4,13516).
+char(1,13517).
+char(5,13518).
+char(m,13519).
+char(1,13520).
+char(2,13521).
+char(5,13522).
+char(1,13523).
+char(m,13524).
+char(o,13525).
+char(2,13526).
+char(5,13527).
+char(3,13528).
+char(6,13529).
+char(c,13530).
+char(p,13531).
+char(o,13532).
+char(m,13533).
+char(2,13534).
+char(6,13535).
+char(5,13536).
+char(8,13537).
+char(m,13538).
+char(2,13539).
+char(4,13540).
+char(7,13541).
+char(3,13542).
+char(m,13543).
+char(o,13544).
+char(p,13545).
+char(1,13546).
+char(5,13547).
+char(9,13548).
+char(9,13549).
+char(m,13550).
+char(o,13551).
+char(p,13552).
+char(4,13553).
+char(5,13554).
+char(9,13555).
+char(2,13556).
+char(m,13557).
+char(o,13558).
+char(m,13559).
+char(o,13560).
+char(o,13561).
+char(p,13562).
+char(o,13563).
+char(p,13564).
+char(5,13565).
+char(0,13566).
+char(1,13567).
+char(6,13568).
+char(c,13569).
+char(p,13570).
+char(4,13571).
+char(2,13572).
+char(4,13573).
+char(8,13574).
+char(p,13575).
+char(5,13576).
+char(9,13577).
+char(9,13578).
+char(1,13579).
+char(c,13580).
+char(c,13581).
+char(m,13582).
+char(5,13583).
+char(1,13584).
+char(8,13585).
+char(0,13586).
+char(c,13587).
+char(p,13588).
+char(o,13589).
+char(m,13590).
+char(o,13591).
+char(6,13592).
+char(1,13593).
+char(6,13594).
+char(6,13595).
+char(m,13596).
+char(o,13597).
+char(7,13598).
+char(8,13599).
+char(6,13600).
+char(4,13601).
+char(c,13602).
+char(c,13603).
+char(c,13604).
+char(p,13605).
+char(4,13606).
+char(3,13607).
+char(9,13608).
+char(2,13609).
+char(m,13610).
+char(o,13611).
+char(p,13612).
+char(o,13613).
+char(m,13614).
+char(3,13615).
+char(9,13616).
+char(4,13617).
+char(c,13618).
+char(p,13619).
+char(o,13620).
+char(p,13621).
+char(5,13622).
+char(0,13623).
+char(8,13624).
+char(3,13625).
+char(c,13626).
+char(c,13627).
+char(m,13628).
+char(3,13629).
+char(1,13630).
+char(4,13631).
+char(4,13632).
+char(m,13633).
+char(o,13634).
+char(m,13635).
+char(1,13636).
+char(6,13637).
+char(6,13638).
+char(m,13639).
+char(o,13640).
+char(m,13641).
+char(6,13642).
+char(4,13643).
+char(7,13644).
+char(4,13645).
+char(c,13646).
+char(c,13647).
+char(c,13648).
+char(c,13649).
+char(c,13650).
+char(c,13651).
+char(c,13652).
+char(c,13653).
+char(m,13654).
+char(5,13655).
+char(0,13656).
+char(4,13657).
+char(6,13658).
+char(c,13659).
+char(c,13660).
+char(m,13661).
+char(6,13662).
+char(5,13663).
+char(0,13664).
+char(7,13665).
+char(c,13666).
+char(p,13667).
+char(o,13668).
+char(m,13669).
+char(o,13670).
+char(m,13671).
+char(5,13672).
+char(6,13673).
+char(6,13674).
+char(8,13675).
+char(p,13676).
+char(o,13677).
+char(m,13678).
+char(o,13679).
+char(p,13680).
+char(o,13681).
+char(p,13682).
+char(o,13683).
+char(m,13684).
+char(o,13685).
+char(p,13686).
+char(2,13687).
+char(1,13688).
+char(4,13689).
+char(5,13690).
+char(c,13691).
+char(c,13692).
+char(c,13693).
+char(c,13694).
+char(m,13695).
+char(o,13696).
+char(o,13697).
+char(m,13698).
+char(1,13699).
+char(7,13700).
+char(4,13701).
+char(3,13702).
+char(p,13703).
+char(o,13704).
+char(8,13705).
+char(9,13706).
+char(3,13707).
+char(2,13708).
+char(c,13709).
+char(c,13710).
+char(p,13711).
+char(o,13712).
+char(p,13713).
+char(o,13714).
+char(m,13715).
+char(o,13716).
+char(m,13717).
+char(7,13718).
+char(4,13719).
+char(0,13720).
+char(7,13721).
+char(c,13722).
+char(c,13723).
+char(p,13724).
+char(o,13725).
+char(3,13726).
+char(5,13727).
+char(6,13728).
+char(8,13729).
+char(m,13730).
+char(4,13731).
+char(8,13732).
+char(5,13733).
+char(4,13734).
+char(m,13735).
+char(o,13736).
+char(p,13737).
+char(7,13738).
+char(5,13739).
+char(2,13740).
+char(0,13741).
+char(c,13742).
+char(p,13743).
+char(o,13744).
+char(p,13745).
+char(o,13746).
+char(o,13747).
+char(o,13748).
+char(o,13749).
+char(7,13750).
+char(1,13751).
+char(1,13752).
+char(0,13753).
+char(c,13754).
+char(c,13755).
+char(c,13756).
+char(c,13757).
+char(c,13758).
+char(c,13759).
+char(c,13760).
+char(c,13761).
+char(p,13762).
+char(9,13763).
+char(5,13764).
+char(1,13765).
+char(6,13766).
+char(c,13767).
+char(p,13768).
+char(o,13769).
+char(m,13770).
+char(4,13771).
+char(5,13772).
+char(6,13773).
+char(3,13774).
+char(m,13775).
+char(7,13776).
+char(6,13777).
+char(1,13778).
+char(7,13779).
+char(p,13780).
+char(9,13781).
+char(9,13782).
+char(3,13783).
+char(6,13784).
+char(p,13785).
+char(9,13786).
+char(8,13787).
+char(8,13788).
+char(2,13789).
+char(p,13790).
+char(o,13791).
+char(1,13792).
+char(1,13793).
+char(2,13794).
+char(7,13795).
+char(c,13796).
+char(p,13797).
+char(5,13798).
+char(4,13799).
+char(4,13800).
+char(4,13801).
+char(c,13802).
+char(p,13803).
+char(2,13804).
+char(3,13805).
+char(2,13806).
+char(9,13807).
+char(p,13808).
+char(7,13809).
+char(5,13810).
+char(5,13811).
+char(m,13812).
+char(4,13813).
+char(7,13814).
+char(0,13815).
+char(0,13816).
+char(p,13817).
+char(6,13818).
+char(0,13819).
+char(5,13820).
+char(7,13821).
+char(m,13822).
+char(4,13823).
+char(5,13824).
+char(1,13825).
+char(4,13826).
+char(p,13827).
+char(o,13828).
+char(p,13829).
+char(9,13830).
+char(3,13831).
+char(6,13832).
+char(9,13833).
+char(c,13834).
+char(m,13835).
+char(9,13836).
+char(6,13837).
+char(2,13838).
+char(4,13839).
+char(c,13840).
+char(c,13841).
+char(m,13842).
+char(6,13843).
+char(7,13844).
+char(0,13845).
+char(5,13846).
+char(p,13847).
+char(8,13848).
+char(2,13849).
+char(5,13850).
+char(5,13851).
+char(c,13852).
+char(c,13853).
+char(c,13854).
+char(c,13855).
+char(m,13856).
+char(1,13857).
+char(4,13858).
+char(4,13859).
+char(1,13860).
+char(c,13861).
+char(c,13862).
+char(p,13863).
+char(5,13864).
+char(1,13865).
+char(5,13866).
+char(5,13867).
+char(c,13868).
+char(p,13869).
+char(o,13870).
+char(o,13871).
+char(8,13872).
+char(6,13873).
+char(7,13874).
+char(2,13875).
+char(m,13876).
+char(o,13877).
+char(p,13878).
+char(o,13879).
+char(m,13880).
+char(o,13881).
+char(p,13882).
+char(o,13883).
+char(o,13884).
+char(o,13885).
+char(p,13886).
+char(o,13887).
+char(o,13888).
+char(8,13889).
+char(7,13890).
+char(5,13891).
+char(7,13892).
+char(c,13893).
+char(p,13894).
+char(6,13895).
+char(7,13896).
+char(0,13897).
+char(7,13898).
+char(c,13899).
+char(m,13900).
+char(4,13901).
+char(4,13902).
+char(1,13903).
+char(4,13904).
+char(c,13905).
+char(m,13906).
+char(8,13907).
+char(0,13908).
+char(6,13909).
+char(c,13910).
+char(m,13911).
+char(5,13912).
+char(7,13913).
+char(0,13914).
+char(0,13915).
+char(m,13916).
+char(4,13917).
+char(6,13918).
+char(8,13919).
+char(3,13920).
+char(p,13921).
+char(4,13922).
+char(7,13923).
+char(6,13924).
+char(2,13925).
+char(c,13926).
+char(p,13927).
+char(o,13928).
+char(m,13929).
+char(o,13930).
+char(o,13931).
+char(p,13932).
+char(5,13933).
+char(1,13934).
+char(9,13935).
+char(1,13936).
+char(m,13937).
+char(o,13938).
+char(m,13939).
+char(o,13940).
+char(p,13941).
+char(o,13942).
+char(m,13943).
+char(3,13944).
+char(6,13945).
+char(8,13946).
+char(1,13947).
+char(c,13948).
+char(p,13949).
+char(9,13950).
+char(8,13951).
+char(4,13952).
+char(2,13953).
+char(c,13954).
+char(c,13955).
+char(m,13956).
+char(o,13957).
+char(1,13958).
+char(7,13959).
+char(4,13960).
+char(9,13961).
+char(c,13962).
+char(p,13963).
+char(o,13964).
+char(p,13965).
+char(o,13966).
+char(p,13967).
+char(o,13968).
+char(m,13969).
+char(7,13970).
+char(5,13971).
+char(2,13972).
+char(7,13973).
+char(m,13974).
+char(o,13975).
+char(o,13976).
+char(m,13977).
+char(o,13978).
+char(9,13979).
+char(8,13980).
+char(1,13981).
+char(1,13982).
+char(c,13983).
+char(m,13984).
+char(o,13985).
+char(p,13986).
+char(8,13987).
+char(9,13988).
+char(8,13989).
+char(4,13990).
+char(c,13991).
+char(c,13992).
+char(p,13993).
+char(4,13994).
+char(2,13995).
+char(7,13996).
+char(2,13997).
+char(c,13998).
+char(c,13999).
+char(c,14000).
+char(c,14001).
+char(m,14002).
+char(7,14003).
+char(0,14004).
+char(0,14005).
+char(3,14006).
+char(c,14007).
+char(p,14008).
+char(o,14009).
+char(5,14010).
+char(8,14011).
+char(6,14012).
+char(1,14013).
+char(c,14014).
+char(p,14015).
+char(3,14016).
+char(5,14017).
+char(5,14018).
+char(6,14019).
+char(c,14020).
+char(c,14021).
+char(c,14022).
+char(p,14023).
+char(o,14024).
+char(p,14025).
+char(o,14026).
+char(p,14027).
+char(6,14028).
+char(8,14029).
+char(9,14030).
+char(8,14031).
+char(c,14032).
+char(c,14033).
+char(c,14034).
+char(p,14035).
+char(o,14036).
+char(p,14037).
+char(o,14038).
+char(m,14039).
+char(o,14040).
+char(4,14041).
+char(5,14042).
+char(2,14043).
+char(9,14044).
+char(c,14045).
+char(c,14046).
+char(p,14047).
+char(o,14048).
+char(o,14049).
+char(o,14050).
+char(m,14051).
+char(o,14052).
+char(1,14053).
+char(6,14054).
+char(8,14055).
+char(2,14056).
+char(c,14057).
+char(m,14058).
+char(o,14059).
+char(m,14060).
+char(o,14061).
+char(m,14062).
+char(o,14063).
+char(p,14064).
+char(o,14065).
+char(p,14066).
+char(9,14067).
+char(0,14068).
+char(4,14069).
+char(3,14070).
+char(c,14071).
+char(c,14072).
+char(m,14073).
+char(1,14074).
+char(8,14075).
+char(4,14076).
+char(2,14077).
+char(p,14078).
+char(3,14079).
+char(0,14080).
+char(9,14081).
+char(1,14082).
+char(c,14083).
+char(c,14084).
+char(p,14085).
+char(1,14086).
+char(1,14087).
+char(0,14088).
+char(4,14089).
+char(m,14090).
+char(o,14091).
+char(m,14092).
+char(4,14093).
+char(3,14094).
+char(8,14095).
+char(7,14096).
+char(m,14097).
+char(o,14098).
+char(m,14099).
+char(4,14100).
+char(5,14101).
+char(7,14102).
+char(1,14103).
+char(c,14104).
+char(m,14105).
+char(o,14106).
+char(o,14107).
+char(m,14108).
+char(4,14109).
+char(5,14110).
+char(6,14111).
+char(c,14112).
+char(p,14113).
+char(o,14114).
+char(m,14115).
+char(5,14116).
+char(2,14117).
+char(6,14118).
+char(6,14119).
+char(m,14120).
+char(o,14121).
+char(p,14122).
+char(o,14123).
+char(5,14124).
+char(1,14125).
+char(7,14126).
+char(7,14127).
+char(c,14128).
+char(c,14129).
+char(m,14130).
+char(5,14131).
+char(8,14132).
+char(6,14133).
+char(9,14134).
+char(c,14135).
+char(m,14136).
+char(o,14137).
+char(m,14138).
+char(2,14139).
+char(0,14140).
+char(1,14141).
+char(1,14142).
+char(c,14143).
+char(c,14144).
+char(m,14145).
+char(o,14146).
+char(m,14147).
+char(7,14148).
+char(1,14149).
+char(2,14150).
+char(5,14151).
+char(m,14152).
+char(5,14153).
+char(7,14154).
+char(4,14155).
+char(3,14156).
+char(p,14157).
+char(o,14158).
+char(7,14159).
+char(7,14160).
+char(1,14161).
+char(1,14162).
+char(c,14163).
+char(m,14164).
+char(3,14165).
+char(7,14166).
+char(2,14167).
+char(4,14168).
+char(m,14169).
+char(o,14170).
+char(m,14171).
+char(o,14172).
+char(4,14173).
+char(3,14174).
+char(6,14175).
+char(m,14176).
+char(o,14177).
+char(6,14178).
+char(7,14179).
+char(2,14180).
+char(8,14181).
+char(m,14182).
+char(o,14183).
+char(m,14184).
+char(5,14185).
+char(7,14186).
+char(3,14187).
+char(8,14188).
+char(c,14189).
+char(m,14190).
+char(3,14191).
+char(2,14192).
+char(1,14193).
+char(2,14194).
+char(c,14195).
+char(p,14196).
+char(9,14197).
+char(6,14198).
+char(7,14199).
+char(6,14200).
+char(m,14201).
+char(7,14202).
+char(3,14203).
+char(7,14204).
+char(8,14205).
+char(c,14206).
+char(c,14207).
+char(c,14208).
+char(c,14209).
+char(p,14210).
+char(2,14211).
+char(2,14212).
+char(4,14213).
+char(7,14214).
+char(c,14215).
+char(c,14216).
+char(c,14217).
+char(p,14218).
+char(o,14219).
+char(p,14220).
+char(o,14221).
+char(3,14222).
+char(1,14223).
+char(2,14224).
+char(9,14225).
+char(p,14226).
+char(8,14227).
+char(3,14228).
+char(5,14229).
+char(5,14230).
+char(c,14231).
+char(c,14232).
+char(m,14233).
+char(o,14234).
+char(o,14235).
+char(m,14236).
+char(o,14237).
+char(o,14238).
+char(3,14239).
+char(1,14240).
+char(2,14241).
+char(5,14242).
+char(p,14243).
+char(o,14244).
+char(p,14245).
+char(2,14246).
+char(1,14247).
+char(9,14248).
+char(0,14249).
+char(c,14250).
+char(c,14251).
+char(c,14252).
+char(m,14253).
+char(o,14254).
+char(p,14255).
+char(9,14256).
+char(5,14257).
+char(4,14258).
+char(4,14259).
+char(p,14260).
+char(o,14261).
+char(p,14262).
+char(o,14263).
+char(p,14264).
+char(3,14265).
+char(7,14266).
+char(2,14267).
+char(5,14268).
+char(m,14269).
+char(o,14270).
+char(8,14271).
+char(2,14272).
+char(2,14273).
+char(1,14274).
+char(c,14275).
+char(c,14276).
+char(c,14277).
+char(p,14278).
+char(o,14279).
+char(7,14280).
+char(5,14281).
+char(1,14282).
+char(9,14283).
+char(c,14284).
+char(c,14285).
+char(c,14286).
+char(c,14287).
+char(c,14288).
+char(c,14289).
+char(c,14290).
+char(p,14291).
+char(4,14292).
+char(7,14293).
+char(6,14294).
+char(6,14295).
+char(c,14296).
+char(c,14297).
+char(m,14298).
+char(o,14299).
+char(m,14300).
+char(1,14301).
+char(1,14302).
+char(6,14303).
+char(7,14304).
+char(c,14305).
+char(c,14306).
+char(m,14307).
+char(4,14308).
+char(9,14309).
+char(5,14310).
+char(7,14311).
+char(m,14312).
+char(o,14313).
+char(p,14314).
+char(2,14315).
+char(7,14316).
+char(7,14317).
+char(6,14318).
+char(c,14319).
+char(m,14320).
+char(o,14321).
+char(9,14322).
+char(0,14323).
+char(1,14324).
+char(2,14325).
+char(m,14326).
+char(o,14327).
+char(p,14328).
+char(o,14329).
+char(p,14330).
+char(8,14331).
+char(7,14332).
+char(1,14333).
+char(6,14334).
+char(p,14335).
+char(8,14336).
+char(3,14337).
+char(9,14338).
+char(9,14339).
+char(p,14340).
+char(o,14341).
+char(o,14342).
+char(m,14343).
+char(5,14344).
+char(9,14345).
+char(8,14346).
+char(8,14347).
+char(c,14348).
+char(p,14349).
+char(1,14350).
+char(7,14351).
+char(2,14352).
+char(7,14353).
+char(c,14354).
+char(p,14355).
+char(4,14356).
+char(0,14357).
+char(6,14358).
+char(6,14359).
+char(m,14360).
+char(o,14361).
+char(p,14362).
+char(o,14363).
+char(m,14364).
+char(5,14365).
+char(3,14366).
+char(1,14367).
+char(5,14368).
+char(m,14369).
+char(o,14370).
+char(m,14371).
+char(4,14372).
+char(5,14373).
+char(8,14374).
+char(6,14375).
+char(m,14376).
+char(o,14377).
+char(o,14378).
+char(m,14379).
+char(o,14380).
+char(p,14381).
+char(o,14382).
+char(m,14383).
+char(5,14384).
+char(7,14385).
+char(5,14386).
+char(1,14387).
+char(m,14388).
+char(o,14389).
+char(o,14390).
+char(m,14391).
+char(8,14392).
+char(2,14393).
+char(5,14394).
+char(3,14395).
+char(m,14396).
+char(o,14397).
+char(o,14398).
+char(p,14399).
+char(7,14400).
+char(4,14401).
+char(3,14402).
+char(9,14403).
+char(p,14404).
+char(1,14405).
+char(9,14406).
+char(9,14407).
+char(p,14408).
+char(o,14409).
+char(m,14410).
+char(o,14411).
+char(o,14412).
+char(m,14413).
+char(o,14414).
+char(m,14415).
+char(o,14416).
+char(m,14417).
+char(5,14418).
+char(8,14419).
+char(4,14420).
+char(c,14421).
+char(c,14422).
+char(p,14423).
+char(o,14424).
+char(m,14425).
+char(7,14426).
+char(5,14427).
+char(8,14428).
+char(3,14429).
+char(c,14430).
+char(p,14431).
+char(8,14432).
+char(5,14433).
+char(1,14434).
+char(2,14435).
+char(c,14436).
+char(c,14437).
+char(c,14438).
+char(p,14439).
+char(9,14440).
+char(4,14441).
+char(0,14442).
+char(1,14443).
+char(c,14444).
+char(p,14445).
+char(9,14446).
+char(0,14447).
+char(5,14448).
+char(1,14449).
+char(p,14450).
+char(o,14451).
+char(m,14452).
+char(o,14453).
+char(6,14454).
+char(8,14455).
+char(4,14456).
+char(4,14457).
+char(p,14458).
+char(o,14459).
+char(6,14460).
+char(4,14461).
+char(7,14462).
+char(4,14463).
+char(p,14464).
+char(o,14465).
+char(o,14466).
+char(o,14467).
+char(p,14468).
+char(o,14469).
+char(m,14470).
+char(o,14471).
+char(m,14472).
+char(1,14473).
+char(8,14474).
+char(7,14475).
+char(0,14476).
+char(c,14477).
+char(c,14478).
+char(c,14479).
+char(c,14480).
+char(p,14481).
+char(o,14482).
+char(p,14483).
+char(o,14484).
+char(p,14485).
+char(o,14486).
+char(p,14487).
+char(2,14488).
+char(1,14489).
+char(2,14490).
+char(1,14491).
+char(m,14492).
+char(o,14493).
+char(1,14494).
+char(7,14495).
+char(1,14496).
+char(8,14497).
+char(m,14498).
+char(7,14499).
+char(1,14500).
+char(8,14501).
+char(6,14502).
+char(m,14503).
+char(o,14504).
+char(m,14505).
+char(o,14506).
+char(m,14507).
+char(o,14508).
+char(m,14509).
+char(o,14510).
+char(m,14511).
+char(6,14512).
+char(6,14513).
+char(0,14514).
+char(m,14515).
+char(o,14516).
+char(p,14517).
+char(7,14518).
+char(8,14519).
+char(8,14520).
+char(5,14521).
+char(p,14522).
+char(1,14523).
+char(7,14524).
+char(8,14525).
+char(8,14526).
+char(m,14527).
+char(8,14528).
+char(9,14529).
+char(1,14530).
+char(1,14531).
+char(m,14532).
+char(6,14533).
+char(2,14534).
+char(6,14535).
+char(1,14536).
+char(c,14537).
+char(p,14538).
+char(o,14539).
+char(m,14540).
+char(9,14541).
+char(3,14542).
+char(5,14543).
+char(9,14544).
+char(c,14545).
+char(p,14546).
+char(o,14547).
+char(o,14548).
+char(m,14549).
+char(o,14550).
+char(o,14551).
+char(8,14552).
+char(9,14553).
+char(0,14554).
+char(1,14555).
+char(p,14556).
+char(o,14557).
+char(m,14558).
+char(o,14559).
+char(m,14560).
+char(o,14561).
+char(o,14562).
+char(m,14563).
+char(o,14564).
+char(o,14565).
+char(p,14566).
+char(o,14567).
+char(9,14568).
+char(7,14569).
+char(9,14570).
+char(7,14571).
+char(c,14572).
+char(c,14573).
+char(c,14574).
+char(c,14575).
+char(m,14576).
+char(o,14577).
+char(m,14578).
+char(o,14579).
+char(p,14580).
+char(o,14581).
+char(o,14582).
+char(m,14583).
+char(o,14584).
+char(8,14585).
+char(8,14586).
+char(0,14587).
+char(0,14588).
+char(p,14589).
+char(o,14590).
+char(p,14591).
+char(4,14592).
+char(9,14593).
+char(8,14594).
+char(9,14595).
+char(c,14596).
+char(m,14597).
+char(o,14598).
+char(p,14599).
+char(o,14600).
+char(p,14601).
+char(4,14602).
+char(0,14603).
+char(4,14604).
+char(2,14605).
+char(c,14606).
+char(p,14607).
+char(o,14608).
+char(4,14609).
+char(2,14610).
+char(6,14611).
+char(3,14612).
+char(p,14613).
+char(o,14614).
+char(1,14615).
+char(6,14616).
+char(9,14617).
+char(4,14618).
+char(m,14619).
+char(6,14620).
+char(7,14621).
+char(2,14622).
+char(8,14623).
+char(c,14624).
+char(p,14625).
+char(o,14626).
+char(7,14627).
+char(5,14628).
+char(6,14629).
+char(1,14630).
+char(c,14631).
+char(m,14632).
+char(o,14633).
+char(p,14634).
+char(o,14635).
+char(m,14636).
+char(6,14637).
+char(8,14638).
+char(5,14639).
+char(1,14640).
+char(c,14641).
+char(p,14642).
+char(o,14643).
+char(p,14644).
+char(1,14645).
+char(0,14646).
+char(8,14647).
+char(8,14648).
+char(c,14649).
+char(p,14650).
+char(o,14651).
+char(3,14652).
+char(0,14653).
+char(4,14654).
+char(7,14655).
+char(c,14656).
+char(p,14657).
+char(5,14658).
+char(6,14659).
+char(4,14660).
+char(6,14661).
+char(c,14662).
+char(c,14663).
+char(c,14664).
+char(c,14665).
+char(c,14666).
+char(c,14667).
+char(c,14668).
+char(m,14669).
+char(o,14670).
+char(m,14671).
+char(o,14672).
+char(o,14673).
+char(p,14674).
+char(3,14675).
+char(1,14676).
+char(4,14677).
+char(c,14678).
+char(p,14679).
+char(1,14680).
+char(2,14681).
+char(1,14682).
+char(8,14683).
+char(c,14684).
+char(c,14685).
+char(c,14686).
+char(c,14687).
+char(c,14688).
+char(c,14689).
+char(p,14690).
+char(4,14691).
+char(5,14692).
+char(7,14693).
+char(9,14694).
+char(m,14695).
+char(o,14696).
+char(4,14697).
+char(7,14698).
+char(6,14699).
+char(9,14700).
+char(c,14701).
+char(m,14702).
+char(o,14703).
+char(p,14704).
+char(6,14705).
+char(3,14706).
+char(3,14707).
+char(2,14708).
+char(c,14709).
+char(c,14710).
+char(c,14711).
+char(c,14712).
+char(m,14713).
+char(4,14714).
+char(9,14715).
+char(1,14716).
+char(0,14717).
+char(c,14718).
+char(c,14719).
+char(c,14720).
+char(m,14721).
+char(o,14722).
+char(m,14723).
+char(1,14724).
+char(0,14725).
+char(2,14726).
+char(c,14727).
+char(c,14728).
+char(m,14729).
+char(o,14730).
+char(o,14731).
+char(o,14732).
+char(3,14733).
+char(2,14734).
+char(0,14735).
+char(8,14736).
+char(m,14737).
+char(o,14738).
+char(m,14739).
+char(o,14740).
+char(p,14741).
+char(o,14742).
+char(o,14743).
+char(m,14744).
+char(7,14745).
+char(6,14746).
+char(5,14747).
+char(6,14748).
+char(p,14749).
+char(2,14750).
+char(9,14751).
+char(2,14752).
+char(2,14753).
+char(m,14754).
+char(8,14755).
+char(0,14756).
+char(4,14757).
+char(0,14758).
+char(m,14759).
+char(o,14760).
+char(m,14761).
+char(7,14762).
+char(7,14763).
+char(2,14764).
+char(7,14765).
+char(p,14766).
+char(o,14767).
+char(4,14768).
+char(0,14769).
+char(7,14770).
+char(7,14771).
+char(c,14772).
+char(c,14773).
+char(c,14774).
+char(c,14775).
+char(m,14776).
+char(o,14777).
+char(m,14778).
+char(1,14779).
+char(2,14780).
+char(3,14781).
+char(6,14782).
+char(c,14783).
+char(c,14784).
+char(m,14785).
+char(o,14786).
+char(5,14787).
+char(3,14788).
+char(5,14789).
+char(6,14790).
+char(c,14791).
+char(p,14792).
+char(7,14793).
+char(2,14794).
+char(8,14795).
+char(2,14796).
+char(c,14797).
+char(m,14798).
+char(9,14799).
+char(7,14800).
+char(3,14801).
+char(2,14802).
+char(p,14803).
+char(o,14804).
+char(p,14805).
+char(o,14806).
+char(m,14807).
+char(o,14808).
+char(7,14809).
+char(4,14810).
+char(3,14811).
+char(2,14812).
+char(c,14813).
+char(p,14814).
+char(o,14815).
+char(m,14816).
+char(o,14817).
+char(o,14818).
+char(o,14819).
+char(6,14820).
+char(3,14821).
+char(2,14822).
+char(5,14823).
+char(c,14824).
+char(c,14825).
+char(p,14826).
+char(o,14827).
+char(2,14828).
+char(0,14829).
+char(0,14830).
+char(6,14831).
+char(m,14832).
+char(3,14833).
+char(9,14834).
+char(9,14835).
+char(c,14836).
+char(c,14837).
+char(c,14838).
+char(p,14839).
+char(o,14840).
+char(p,14841).
+char(o,14842).
+char(m,14843).
+char(4,14844).
+char(7,14845).
+char(4,14846).
+char(m,14847).
+char(o,14848).
+char(m,14849).
+char(o,14850).
+char(p,14851).
+char(7,14852).
+char(8,14853).
+char(9,14854).
+char(5,14855).
+char(c,14856).
+char(m,14857).
+char(o,14858).
+char(m,14859).
+char(o,14860).
+char(p,14861).
+char(8,14862).
+char(7,14863).
+char(4,14864).
+char(9,14865).
+char(c,14866).
+char(p,14867).
+char(o,14868).
+char(p,14869).
+char(7,14870).
+char(1,14871).
+char(3,14872).
+char(1,14873).
+char(p,14874).
+char(o,14875).
+char(p,14876).
+char(o,14877).
+char(2,14878).
+char(5,14879).
+char(5,14880).
+char(1,14881).
+char(c,14882).
+char(c,14883).
+char(c,14884).
+char(c,14885).
+char(c,14886).
+char(m,14887).
+char(2,14888).
+char(5,14889).
+char(6,14890).
+char(4,14891).
+char(c,14892).
+char(p,14893).
+char(4,14894).
+char(9,14895).
+char(7,14896).
+char(0,14897).
+char(p,14898).
+char(o,14899).
+char(p,14900).
+char(o,14901).
+char(m,14902).
+char(o,14903).
+char(p,14904).
+char(8,14905).
+char(2,14906).
+char(7,14907).
+char(m,14908).
+char(5,14909).
+char(3,14910).
+char(2,14911).
+char(8,14912).
+char(m,14913).
+char(o,14914).
+char(o,14915).
+char(m,14916).
+char(o,14917).
+char(p,14918).
+char(o,14919).
+char(p,14920).
+char(3,14921).
+char(4,14922).
+char(9,14923).
+char(7,14924).
+char(p,14925).
+char(7,14926).
+char(7,14927).
+char(9,14928).
+char(4,14929).
+char(c,14930).
+char(m,14931).
+char(4,14932).
+char(0,14933).
+char(4,14934).
+char(0,14935).
+char(p,14936).
+char(8,14937).
+char(3,14938).
+char(2,14939).
+char(8,14940).
+char(c,14941).
+char(m,14942).
+char(o,14943).
+char(p,14944).
+char(3,14945).
+char(6,14946).
+char(7,14947).
+char(6,14948).
+char(c,14949).
+char(c,14950).
+char(c,14951).
+char(c,14952).
+char(m,14953).
+char(4,14954).
+char(1,14955).
+char(4,14956).
+char(2,14957).
+char(m,14958).
+char(4,14959).
+char(3,14960).
+char(4,14961).
+char(6,14962).
+char(c,14963).
+char(m,14964).
+char(o,14965).
+char(m,14966).
+char(o,14967).
+char(p,14968).
+char(2,14969).
+char(1,14970).
+char(3,14971).
+char(2,14972).
+char(c,14973).
+char(m,14974).
+char(o,14975).
+char(4,14976).
+char(0,14977).
+char(3,14978).
+char(1,14979).
+char(p,14980).
+char(7,14981).
+char(9,14982).
+char(7,14983).
+char(2,14984).
+char(c,14985).
+char(p,14986).
+char(o,14987).
+char(m,14988).
+char(o,14989).
+char(m,14990).
+char(1,14991).
+char(9,14992).
+char(0,14993).
+char(7,14994).
+char(c,14995).
+char(c,14996).
+char(p,14997).
+char(o,14998).
+char(p,14999).
+char(3,15000).
+char(9,15001).
+char(9,15002).
+char(4,15003).
+char(c,15004).
+char(c,15005).
+char(c,15006).
+char(p,15007).
+char(o,15008).
+char(p,15009).
+char(o,15010).
+char(m,15011).
+char(o,15012).
+char(p,15013).
+char(9,15014).
+char(0,15015).
+char(9,15016).
+char(0,15017).
+char(m,15018).
+char(5,15019).
+char(3,15020).
+char(3,15021).
+char(p,15022).
+char(o,15023).
+char(m,15024).
+char(o,15025).
+char(m,15026).
+char(6,15027).
+char(8,15028).
+char(8,15029).
+char(c,15030).
+char(c,15031).
+char(c,15032).
+char(m,15033).
+char(o,15034).
+char(p,15035).
+char(6,15036).
+char(6,15037).
+char(2,15038).
+char(0,15039).
+char(c,15040).
+char(m,15041).
+char(o,15042).
+char(p,15043).
+char(9,15044).
+char(6,15045).
+char(5,15046).
+char(6,15047).
+char(p,15048).
+char(1,15049).
+char(9,15050).
+char(3,15051).
+char(3,15052).
+char(m,15053).
+char(o,15054).
+char(m,15055).
+char(o,15056).
+char(m,15057).
+char(o,15058).
+char(p,15059).
+char(o,15060).
+char(m,15061).
+char(8,15062).
+char(3,15063).
+char(4,15064).
+char(m,15065).
+char(9,15066).
+char(9,15067).
+char(7,15068).
+char(0,15069).
+char(c,15070).
+char(c,15071).
+char(p,15072).
+char(6,15073).
+char(3,15074).
+char(3,15075).
+char(9,15076).
+char(p,15077).
+char(o,15078).
+char(p,15079).
+char(2,15080).
+char(9,15081).
+char(1,15082).
+char(8,15083).
+char(c,15084).
+char(c,15085).
+char(p,15086).
+char(o,15087).
+char(m,15088).
+char(4,15089).
+char(1,15090).
+char(3,15091).
+char(9,15092).
+char(p,15093).
+char(o,15094).
+char(p,15095).
+char(4,15096).
+char(8,15097).
+char(0,15098).
+char(8,15099).
+char(c,15100).
+char(p,15101).
+char(6,15102).
+char(0,15103).
+char(8,15104).
+char(8,15105).
+char(c,15106).
+char(m,15107).
+char(9,15108).
+char(3,15109).
+char(6,15110).
+char(8,15111).
+char(p,15112).
+char(o,15113).
+char(m,15114).
+char(o,15115).
+char(p,15116).
+char(7,15117).
+char(0,15118).
+char(6,15119).
+char(7,15120).
+char(c,15121).
+char(p,15122).
+char(o,15123).
+char(p,15124).
+char(5,15125).
+char(6,15126).
+char(9,15127).
+char(9,15128).
+char(m,15129).
+char(1,15130).
+char(7,15131).
+char(0,15132).
+char(3,15133).
+char(c,15134).
+char(m,15135).
+char(9,15136).
+char(4,15137).
+char(1,15138).
+char(9,15139).
+char(c,15140).
+char(m,15141).
+char(o,15142).
+char(p,15143).
+char(o,15144).
+char(m,15145).
+char(o,15146).
+char(m,15147).
+char(o,15148).
+char(o,15149).
+char(9,15150).
+char(4,15151).
+char(6,15152).
+char(5,15153).
+char(c,15154).
+char(c,15155).
+char(p,15156).
+char(o,15157).
+char(m,15158).
+char(6,15159).
+char(8,15160).
+char(7,15161).
+char(0,15162).
+char(c,15163).
+char(m,15164).
+char(5,15165).
+char(4,15166).
+char(1,15167).
+char(1,15168).
+char(c,15169).
+char(c,15170).
+char(p,15171).
+char(6,15172).
+char(5,15173).
+char(0,15174).
+char(1,15175).
+char(p,15176).
+char(o,15177).
+char(6,15178).
+char(5,15179).
+char(9,15180).
+char(1,15181).
+char(c,15182).
+char(c,15183).
+char(c,15184).
+char(m,15185).
+char(o,15186).
+char(m,15187).
+char(o,15188).
+char(p,15189).
+char(2,15190).
+char(6,15191).
+char(4,15192).
+char(8,15193).
+char(c,15194).
+char(m,15195).
+char(2,15196).
+char(1,15197).
+char(8,15198).
+char(5,15199).
+char(m,15200).
+char(o,15201).
+char(6,15202).
+char(4,15203).
+char(4,15204).
+char(1,15205).
+char(m,15206).
+char(8,15207).
+char(1,15208).
+char(0,15209).
+char(5,15210).
+char(c,15211).
+char(c,15212).
+char(c,15213).
+char(p,15214).
+char(o,15215).
+char(m,15216).
+char(o,15217).
+char(o,15218).
+char(o,15219).
+char(m,15220).
+char(o,15221).
+char(m,15222).
+char(3,15223).
+char(8,15224).
+char(0,15225).
+char(2,15226).
+char(c,15227).
+char(m,15228).
+char(3,15229).
+char(9,15230).
+char(7,15231).
+char(4,15232).
+char(c,15233).
+char(m,15234).
+char(8,15235).
+char(0,15236).
+char(6,15237).
+char(0,15238).
+char(c,15239).
+char(c,15240).
+char(p,15241).
+char(1,15242).
+char(1,15243).
+char(9,15244).
+char(1,15245).
+char(c,15246).
+char(p,15247).
+char(o,15248).
+char(m,15249).
+char(o,15250).
+char(o,15251).
+char(m,15252).
+char(6,15253).
+char(9,15254).
+char(4,15255).
+char(4,15256).
+char(m,15257).
+char(9,15258).
+char(3,15259).
+char(0,15260).
+char(3,15261).
+char(c,15262).
+char(m,15263).
+char(8,15264).
+char(2,15265).
+char(0,15266).
+char(c,15267).
+char(p,15268).
+char(7,15269).
+char(1,15270).
+char(4,15271).
+char(7,15272).
+char(c,15273).
+char(p,15274).
+char(7,15275).
+char(8,15276).
+char(2,15277).
+char(6,15278).
+char(m,15279).
+char(o,15280).
+char(p,15281).
+char(6,15282).
+char(9,15283).
+char(2,15284).
+char(c,15285).
+char(c,15286).
+char(p,15287).
+char(o,15288).
+char(o,15289).
+char(2,15290).
+char(2,15291).
+char(7,15292).
+char(7,15293).
+char(p,15294).
+char(o,15295).
+char(m,15296).
+char(o,15297).
+char(m,15298).
+char(o,15299).
+char(5,15300).
+char(8,15301).
+char(9,15302).
+char(3,15303).
+char(c,15304).
+char(c,15305).
+char(c,15306).
+char(c,15307).
+char(m,15308).
+char(5,15309).
+char(2,15310).
+char(2,15311).
+char(9,15312).
+char(c,15313).
+char(c,15314).
+char(m,15315).
+char(o,15316).
+char(m,15317).
+char(2,15318).
+char(6,15319).
+char(1,15320).
+char(4,15321).
+char(c,15322).
+char(c,15323).
+char(p,15324).
+char(6,15325).
+char(3,15326).
+char(1,15327).
+char(3,15328).
+char(c,15329).
+char(c,15330).
+char(m,15331).
+char(7,15332).
+char(8,15333).
+char(3,15334).
+char(1,15335).
+char(m,15336).
+char(o,15337).
+char(o,15338).
+char(p,15339).
+char(o,15340).
+char(m,15341).
+char(5,15342).
+char(5,15343).
+char(5,15344).
+char(9,15345).
+char(p,15346).
+char(4,15347).
+char(7,15348).
+char(2,15349).
+char(p,15350).
+char(o,15351).
+char(o,15352).
+char(p,15353).
+char(2,15354).
+char(9,15355).
+char(8,15356).
+char(3,15357).
+char(c,15358).
+char(c,15359).
+char(c,15360).
+char(c,15361).
+char(p,15362).
+char(o,15363).
+char(m,15364).
+char(4,15365).
+char(4,15366).
+char(6,15367).
+char(5,15368).
+char(c,15369).
+char(m,15370).
+char(3,15371).
+char(5,15372).
+char(4,15373).
+char(4,15374).
+char(c,15375).
+char(c,15376).
+char(c,15377).
+char(c,15378).
+char(c,15379).
+char(c,15380).
+char(c,15381).
+char(c,15382).
+char(c,15383).
+char(p,15384).
+char(4,15385).
+char(9,15386).
+char(8,15387).
+char(m,15388).
+char(o,15389).
+char(p,15390).
+char(6,15391).
+char(5,15392).
+char(6,15393).
+char(5,15394).
+char(c,15395).
+char(c,15396).
+char(c,15397).
+char(c,15398).
+char(c,15399).
+char(m,15400).
+char(7,15401).
+char(8,15402).
+char(7,15403).
+char(1,15404).
+char(c,15405).
+char(c,15406).
+char(p,15407).
+char(9,15408).
+char(7,15409).
+char(8,15410).
+char(2,15411).
+char(c,15412).
+char(p,15413).
+char(o,15414).
+char(p,15415).
+char(4,15416).
+char(9,15417).
+char(0,15418).
+char(0,15419).
+char(p,15420).
+char(3,15421).
+char(6,15422).
+char(9,15423).
+char(1,15424).
+char(c,15425).
+char(m,15426).
+char(6,15427).
+char(8,15428).
+char(8,15429).
+char(4,15430).
+char(c,15431).
+char(m,15432).
+char(1,15433).
+char(9,15434).
+char(6,15435).
+char(7,15436).
+char(p,15437).
+char(o,15438).
+char(1,15439).
+char(8,15440).
+char(2,15441).
+char(6,15442).
+char(p,15443).
+char(9,15444).
+char(2,15445).
+char(0,15446).
+char(5,15447).
+char(m,15448).
+char(6,15449).
+char(5,15450).
+char(7,15451).
+char(p,15452).
+char(o,15453).
+char(m,15454).
+char(9,15455).
+char(8,15456).
+char(0,15457).
+char(9,15458).
+char(c,15459).
+char(p,15460).
+char(9,15461).
+char(9,15462).
+char(6,15463).
+char(3,15464).
+char(c,15465).
+char(c,15466).
+char(m,15467).
+char(o,15468).
+char(2,15469).
+char(5,15470).
+char(8,15471).
+char(7,15472).
+char(m,15473).
+char(o,15474).
+char(m,15475).
+char(o,15476).
+char(m,15477).
+char(o,15478).
+char(p,15479).
+char(o,15480).
+char(p,15481).
+char(7,15482).
+char(4,15483).
+char(3,15484).
+char(8,15485).
+char(c,15486).
+char(p,15487).
+char(4,15488).
+char(2,15489).
+char(4,15490).
+char(1,15491).
+char(p,15492).
+char(o,15493).
+char(p,15494).
+char(3,15495).
+char(2,15496).
+char(3,15497).
+char(2,15498).
+char(p,15499).
+char(8,15500).
+char(5,15501).
+char(2,15502).
+char(m,15503).
+char(o,15504).
+char(m,15505).
+char(o,15506).
+char(2,15507).
+char(9,15508).
+char(1,15509).
+char(2,15510).
+char(c,15511).
+char(m,15512).
+char(6,15513).
+char(0,15514).
+char(9,15515).
+char(3,15516).
+char(p,15517).
+char(3,15518).
+char(2,15519).
+char(1,15520).
+char(4,15521).
+char(p,15522).
+char(o,15523).
+char(o,15524).
+char(m,15525).
+char(o,15526).
+char(m,15527).
+char(9,15528).
+char(8,15529).
+char(7,15530).
+char(p,15531).
+char(o,15532).
+char(7,15533).
+char(2,15534).
+char(7,15535).
+char(7,15536).
+char(p,15537).
+char(o,15538).
+char(m,15539).
+char(o,15540).
+char(o,15541).
+char(p,15542).
+char(o,15543).
+char(6,15544).
+char(4,15545).
+char(4,15546).
+char(1,15547).
+char(c,15548).
+char(p,15549).
+char(o,15550).
+char(p,15551).
+char(5,15552).
+char(2,15553).
+char(7,15554).
+char(2,15555).
+char(p,15556).
+char(o,15557).
+char(p,15558).
+char(3,15559).
+char(6,15560).
+char(4,15561).
+char(4,15562).
+char(c,15563).
+char(m,15564).
+char(5,15565).
+char(1,15566).
+char(7,15567).
+char(9,15568).
+char(p,15569).
+char(o,15570).
+char(m,15571).
+char(o,15572).
+char(m,15573).
+char(2,15574).
+char(3,15575).
+char(5,15576).
+char(3,15577).
+char(p,15578).
+char(2,15579).
+char(5,15580).
+char(0,15581).
+char(3,15582).
+char(c,15583).
+char(c,15584).
+char(c,15585).
+char(c,15586).
+char(c,15587).
+char(c,15588).
+char(c,15589).
+char(m,15590).
+char(6,15591).
+char(4,15592).
+char(3,15593).
+char(9,15594).
+char(m,15595).
+char(o,15596).
+char(8,15597).
+char(5,15598).
+char(0,15599).
+char(2,15600).
+char(c,15601).
+char(p,15602).
+char(o,15603).
+char(p,15604).
+char(o,15605).
+char(p,15606).
+char(o,15607).
+char(p,15608).
+char(9,15609).
+char(2,15610).
+char(7,15611).
+char(3,15612).
+char(m,15613).
+char(o,15614).
+char(o,15615).
+char(m,15616).
+char(o,15617).
+char(p,15618).
+char(o,15619).
+char(o,15620).
+char(o,15621).
+char(p,15622).
+char(o,15623).
+char(m,15624).
+char(o,15625).
+char(o,15626).
+char(p,15627).
+char(o,15628).
+char(p,15629).
+char(o,15630).
+char(m,15631).
+char(6,15632).
+char(0,15633).
+char(6,15634).
+char(5,15635).
+char(p,15636).
+char(o,15637).
+char(m,15638).
+char(o,15639).
+char(m,15640).
+char(8,15641).
+char(5,15642).
+char(1,15643).
+char(9,15644).
+char(c,15645).
+char(m,15646).
+char(1,15647).
+char(7,15648).
+char(2,15649).
+char(1,15650).
+char(p,15651).
+char(3,15652).
+char(4,15653).
+char(9,15654).
+char(2,15655).
+char(p,15656).
+char(o,15657).
+char(6,15658).
+char(3,15659).
+char(2,15660).
+char(6,15661).
+char(m,15662).
+char(o,15663).
+char(o,15664).
+char(2,15665).
+char(7,15666).
+char(0,15667).
+char(7,15668).
+char(m,15669).
+char(o,15670).
+char(p,15671).
+char(o,15672).
+char(m,15673).
+char(o,15674).
+char(o,15675).
+char(p,15676).
+char(o,15677).
+char(2,15678).
+char(0,15679).
+char(7,15680).
+char(4,15681).
+char(c,15682).
+char(c,15683).
+char(c,15684).
+char(p,15685).
+char(9,15686).
+char(6,15687).
+char(8,15688).
+char(2,15689).
+char(m,15690).
+char(2,15691).
+char(9,15692).
+char(1,15693).
+char(9,15694).
+char(c,15695).
+char(p,15696).
+char(o,15697).
+char(7,15698).
+char(8,15699).
+char(4,15700).
+char(3,15701).
+char(c,15702).
+char(c,15703).
+char(p,15704).
+char(o,15705).
+char(m,15706).
+char(5,15707).
+char(9,15708).
+char(5,15709).
+char(5,15710).
+char(m,15711).
+char(o,15712).
+char(o,15713).
+char(o,15714).
+char(o,15715).
+char(m,15716).
+char(9,15717).
+char(3,15718).
+char(8,15719).
+char(1,15720).
+char(m,15721).
+char(5,15722).
+char(0,15723).
+char(8,15724).
+char(0,15725).
+char(m,15726).
+char(2,15727).
+char(4,15728).
+char(5,15729).
+char(2,15730).
+char(c,15731).
+char(m,15732).
+char(5,15733).
+char(8,15734).
+char(7,15735).
+char(6,15736).
+char(c,15737).
+char(c,15738).
+char(c,15739).
+char(p,15740).
+char(5,15741).
+char(4,15742).
+char(4,15743).
+char(4,15744).
+char(c,15745).
+char(c,15746).
+char(c,15747).
+char(c,15748).
+char(c,15749).
+char(c,15750).
+char(c,15751).
+char(p,15752).
+char(4,15753).
+char(4,15754).
+char(1,15755).
+char(p,15756).
+char(8,15757).
+char(2,15758).
+char(0,15759).
+char(1,15760).
+char(c,15761).
+char(c,15762).
+char(m,15763).
+char(9,15764).
+char(7,15765).
+char(9,15766).
+char(0,15767).
+char(c,15768).
+char(c,15769).
+char(c,15770).
+char(m,15771).
+char(8,15772).
+char(8,15773).
+char(5,15774).
+char(5,15775).
+char(c,15776).
+char(c,15777).
+char(c,15778).
+char(p,15779).
+char(o,15780).
+char(o,15781).
+char(p,15782).
+char(o,15783).
+char(m,15784).
+char(2,15785).
+char(0,15786).
+char(5,15787).
+char(8,15788).
+char(p,15789).
+char(9,15790).
+char(1,15791).
+char(5,15792).
+char(8,15793).
+char(c,15794).
+char(c,15795).
+char(c,15796).
+char(c,15797).
+char(p,15798).
+char(3,15799).
+char(8,15800).
+char(9,15801).
+char(7,15802).
+char(c,15803).
+char(c,15804).
+char(c,15805).
+char(c,15806).
+char(m,15807).
+char(4,15808).
+char(3,15809).
+char(5,15810).
+char(3,15811).
+char(c,15812).
+char(c,15813).
+char(c,15814).
+char(c,15815).
+char(c,15816).
+char(c,15817).
+char(c,15818).
+char(c,15819).
+char(m,15820).
+char(3,15821).
+char(2,15822).
+char(3,15823).
+char(1,15824).
+char(c,15825).
+char(c,15826).
+char(c,15827).
+char(c,15828).
+char(c,15829).
+char(p,15830).
+char(o,15831).
+char(p,15832).
+char(9,15833).
+char(8,15834).
+char(9,15835).
+char(4,15836).
+char(c,15837).
+char(m,15838).
+char(o,15839).
+char(m,15840).
+char(o,15841).
+char(o,15842).
+char(o,15843).
+char(p,15844).
+char(9,15845).
+char(8,15846).
+char(4,15847).
+char(8,15848).
+char(m,15849).
+char(o,15850).
+char(p,15851).
+char(o,15852).
+char(p,15853).
+char(9,15854).
+char(1,15855).
+char(7,15856).
+char(3,15857).
+char(m,15858).
+char(o,15859).
+char(o,15860).
+char(p,15861).
+char(o,15862).
+char(p,15863).
+char(o,15864).
+char(o,15865).
+char(p,15866).
+char(o,15867).
+char(m,15868).
+char(1,15869).
+char(5,15870).
+char(9,15871).
+char(9,15872).
+char(c,15873).
+char(c,15874).
+char(c,15875).
+char(m,15876).
+char(3,15877).
+char(3,15878).
+char(9,15879).
+char(8,15880).
+char(c,15881).
+char(c,15882).
+char(c,15883).
+char(c,15884).
+char(c,15885).
+char(c,15886).
+char(c,15887).
+char(c,15888).
+char(c,15889).
+char(p,15890).
+char(o,15891).
+char(m,15892).
+char(o,15893).
+char(m,15894).
+char(2,15895).
+char(9,15896).
+char(8,15897).
+char(6,15898).
+char(p,15899).
+char(6,15900).
+char(5,15901).
+char(5,15902).
+char(6,15903).
+char(c,15904).
+char(c,15905).
+char(c,15906).
+char(p,15907).
+char(o,15908).
+char(m,15909).
+char(o,15910).
+char(o,15911).
+char(o,15912).
+char(p,15913).
+char(o,15914).
+char(8,15915).
+char(9,15916).
+char(5,15917).
+char(7,15918).
+char(c,15919).
+char(c,15920).
+char(c,15921).
+char(p,15922).
+char(9,15923).
+char(2,15924).
+char(2,15925).
+char(8,15926).
+char(p,15927).
+char(o,15928).
+char(p,15929).
+char(o,15930).
+char(m,15931).
+char(o,15932).
+char(p,15933).
+char(1,15934).
+char(4,15935).
+char(3,15936).
+char(m,15937).
+char(o,15938).
+char(4,15939).
+char(0,15940).
+char(3,15941).
+char(3,15942).
+char(c,15943).
+char(m,15944).
+char(8,15945).
+char(8,15946).
+char(2,15947).
+char(c,15948).
+char(c,15949).
+char(p,15950).
+char(o,15951).
+char(o,15952).
+char(m,15953).
+char(6,15954).
+char(2,15955).
+char(7,15956).
+char(7,15957).
+char(c,15958).
+char(p,15959).
+char(o,15960).
+char(o,15961).
+char(7,15962).
+char(5,15963).
+char(4,15964).
+char(2,15965).
+char(c,15966).
+char(p,15967).
+char(o,15968).
+char(m,15969).
+char(6,15970).
+char(1,15971).
+char(7,15972).
+char(2,15973).
+char(c,15974).
+char(c,15975).
+char(m,15976).
+char(2,15977).
+char(1,15978).
+char(m,15979).
+char(4,15980).
+char(4,15981).
+char(0,15982).
+char(7,15983).
+char(m,15984).
+char(7,15985).
+char(2,15986).
+char(7,15987).
+char(5,15988).
+char(c,15989).
+char(c,15990).
+char(c,15991).
+char(m,15992).
+char(o,15993).
+char(p,15994).
+char(1,15995).
+char(8,15996).
+char(3,15997).
+char(c,15998).
+char(p,15999).
+char(2,16000).
+char(6,16001).
+char(5,16002).
+char(8,16003).
+char(c,16004).
+char(c,16005).
+char(m,16006).
+char(o,16007).
+char(o,16008).
+char(o,16009).
+char(o,16010).
+char(1,16011).
+char(3,16012).
+char(9,16013).
+char(6,16014).
+char(c,16015).
+char(m,16016).
+char(7,16017).
+char(7,16018).
+char(5,16019).
+char(7,16020).
+char(c,16021).
+char(m,16022).
+char(o,16023).
+char(o,16024).
+char(4,16025).
+char(2,16026).
+char(5,16027).
+char(6,16028).
+char(m,16029).
+char(3,16030).
+char(4,16031).
+char(1,16032).
+char(1,16033).
+char(c,16034).
+char(m,16035).
+char(9,16036).
+char(5,16037).
+char(8,16038).
+char(3,16039).
+char(m,16040).
+char(4,16041).
+char(8,16042).
+char(2,16043).
+char(p,16044).
+char(3,16045).
+char(6,16046).
+char(0,16047).
+char(c,16048).
+char(p,16049).
+char(o,16050).
+char(p,16051).
+char(o,16052).
+char(p,16053).
+char(o,16054).
+char(p,16055).
+char(6,16056).
+char(3,16057).
+char(6,16058).
+char(9,16059).
+char(c,16060).
+char(m,16061).
+char(o,16062).
+char(p,16063).
+char(o,16064).
+char(m,16065).
+char(6,16066).
+char(1,16067).
+char(6,16068).
+char(1,16069).
+char(m,16070).
+char(8,16071).
+char(1,16072).
+char(0,16073).
+char(6,16074).
+char(p,16075).
+char(o,16076).
+char(m,16077).
+char(o,16078).
+char(7,16079).
+char(7,16080).
+char(4,16081).
+char(0,16082).
+char(c,16083).
+char(c,16084).
+char(c,16085).
+char(c,16086).
+char(c,16087).
+char(m,16088).
+char(o,16089).
+char(m,16090).
+char(4,16091).
+char(0,16092).
+char(7,16093).
+char(1,16094).
+char(m,16095).
+char(o,16096).
+char(1,16097).
+char(5,16098).
+char(2,16099).
+char(5,16100).
+char(c,16101).
+char(m,16102).
+char(9,16103).
+char(6,16104).
+char(4,16105).
+char(0,16106).
+char(c,16107).
+char(m,16108).
+char(6,16109).
+char(3,16110).
+char(8,16111).
+char(2,16112).
+char(c,16113).
+char(c,16114).
+char(p,16115).
+char(o,16116).
+char(p,16117).
+char(3,16118).
+char(6,16119).
+char(8,16120).
+char(7,16121).
+char(m,16122).
+char(o,16123).
+char(8,16124).
+char(7,16125).
+char(0,16126).
+char(0,16127).
+char(p,16128).
+char(o,16129).
+char(o,16130).
+char(m,16131).
+char(7,16132).
+char(5,16133).
+char(6,16134).
+char(6,16135).
+char(c,16136).
+char(m,16137).
+char(o,16138).
+char(p,16139).
+char(1,16140).
+char(6,16141).
+char(0,16142).
+char(6,16143).
+char(c,16144).
+char(c,16145).
+char(m,16146).
+char(9,16147).
+char(3,16148).
+char(0,16149).
+char(8,16150).
+char(p,16151).
+char(o,16152).
+char(p,16153).
+char(o,16154).
+char(4,16155).
+char(2,16156).
+char(7,16157).
+char(2,16158).
+char(m,16159).
+char(6,16160).
+char(5,16161).
+char(7,16162).
+char(9,16163).
+char(c,16164).
+char(c,16165).
+char(c,16166).
+char(p,16167).
+char(9,16168).
+char(3,16169).
+char(7,16170).
+char(0,16171).
+char(m,16172).
+char(5,16173).
+char(9,16174).
+char(5,16175).
+char(0,16176).
+char(c,16177).
+char(m,16178).
+char(1,16179).
+char(0,16180).
+char(6,16181).
+char(9,16182).
+char(m,16183).
+char(o,16184).
+char(o,16185).
+char(m,16186).
+char(6,16187).
+char(6,16188).
+char(9,16189).
+char(1,16190).
+char(c,16191).
+char(m,16192).
+char(o,16193).
+char(m,16194).
+char(o,16195).
+char(p,16196).
+char(5,16197).
+char(0,16198).
+char(0,16199).
+char(8,16200).
+char(c,16201).
+char(m,16202).
+char(8,16203).
+char(7,16204).
+char(3,16205).
+char(7,16206).
+char(p,16207).
+char(o,16208).
+char(m,16209).
+char(o,16210).
+char(m,16211).
+char(5,16212).
+char(7,16213).
+char(4,16214).
+char(3,16215).
+char(m,16216).
+char(o,16217).
+char(m,16218).
+char(2,16219).
+char(0,16220).
+char(1,16221).
+char(4,16222).
+char(c,16223).
+char(c,16224).
+char(c,16225).
+char(c,16226).
+char(c,16227).
+char(m,16228).
+char(o,16229).
+char(p,16230).
+char(6,16231).
+char(5,16232).
+char(6,16233).
+char(2,16234).
+char(c,16235).
+char(c,16236).
+char(p,16237).
+char(o,16238).
+char(p,16239).
+char(o,16240).
+char(p,16241).
+char(o,16242).
+char(4,16243).
+char(6,16244).
+char(9,16245).
+char(9,16246).
+char(p,16247).
+char(o,16248).
+char(m,16249).
+char(o,16250).
+char(p,16251).
+char(6,16252).
+char(8,16253).
+char(6,16254).
+char(3,16255).
+char(m,16256).
+char(3,16257).
+char(7,16258).
+char(3,16259).
+char(8,16260).
+char(p,16261).
+char(6,16262).
+char(9,16263).
+char(3,16264).
+char(9,16265).
+char(m,16266).
+char(4,16267).
+char(9,16268).
+char(3,16269).
+char(9,16270).
+char(m,16271).
+char(o,16272).
+char(m,16273).
+char(4,16274).
+char(0,16275).
+char(1,16276).
+char(9,16277).
+char(c,16278).
+char(m,16279).
+char(o,16280).
+char(m,16281).
+char(3,16282).
+char(7,16283).
+char(1,16284).
+char(3,16285).
+char(c,16286).
+char(m,16287).
+char(5,16288).
+char(0,16289).
+char(5,16290).
+char(6,16291).
+char(c,16292).
+char(c,16293).
+char(m,16294).
+char(o,16295).
+char(m,16296).
+char(o,16297).
+char(p,16298).
+char(o,16299).
+char(o,16300).
+char(o,16301).
+char(p,16302).
+char(1,16303).
+char(2,16304).
+char(5,16305).
+char(4,16306).
+char(m,16307).
+char(o,16308).
+char(m,16309).
+char(4,16310).
+char(6,16311).
+char(9,16312).
+char(2,16313).
+char(c,16314).
+char(m,16315).
+char(8,16316).
+char(2,16317).
+char(5,16318).
+char(6,16319).
+char(p,16320).
+char(3,16321).
+char(5,16322).
+char(2,16323).
+char(2,16324).
+char(c,16325).
+char(m,16326).
+char(o,16327).
+char(o,16328).
+char(o,16329).
+char(m,16330).
+char(o,16331).
+char(p,16332).
+char(4,16333).
+char(6,16334).
+char(4,16335).
+char(1,16336).
+char(p,16337).
+char(o,16338).
+char(o,16339).
+char(p,16340).
+char(o,16341).
+char(p,16342).
+char(1,16343).
+char(2,16344).
+char(2,16345).
+char(2,16346).
+char(m,16347).
+char(1,16348).
+char(5,16349).
+char(4,16350).
+char(9,16351).
+char(m,16352).
+char(o,16353).
+char(p,16354).
+char(o,16355).
+char(m,16356).
+char(o,16357).
+char(o,16358).
+char(4,16359).
+char(7,16360).
+char(4,16361).
+char(m,16362).
+char(o,16363).
+char(m,16364).
+char(o,16365).
+char(m,16366).
+char(1,16367).
+char(7,16368).
+char(2,16369).
+char(5,16370).
+char(c,16371).
+char(p,16372).
+char(o,16373).
+char(p,16374).
+char(9,16375).
+char(9,16376).
+char(1,16377).
+char(4,16378).
+char(c,16379).
+char(m,16380).
+char(1,16381).
+char(8,16382).
+char(9,16383).
+char(9,16384).
+char(c,16385).
+char(p,16386).
+char(9,16387).
+char(0,16388).
+char(8,16389).
+char(3,16390).
+char(p,16391).
+char(o,16392).
+char(p,16393).
+char(o,16394).
+char(p,16395).
+char(8,16396).
+char(7,16397).
+char(5,16398).
+char(7,16399).
+char(c,16400).
+char(m,16401).
+char(o,16402).
+char(9,16403).
+char(2,16404).
+char(2,16405).
+char(9,16406).
+char(m,16407).
+char(o,16408).
+char(m,16409).
+char(6,16410).
+char(3,16411).
+char(2,16412).
+char(4,16413).
+char(p,16414).
+char(1,16415).
+char(0,16416).
+char(3,16417).
+char(8,16418).
+char(p,16419).
+char(7,16420).
+char(2,16421).
+char(7,16422).
+char(4,16423).
+char(p,16424).
+char(2,16425).
+char(5,16426).
+char(1,16427).
+char(4,16428).
+char(c,16429).
+char(c,16430).
+char(c,16431).
+char(p,16432).
+char(5,16433).
+char(7,16434).
+char(1,16435).
+char(2,16436).
+char(c,16437).
+char(m,16438).
+char(o,16439).
+char(m,16440).
+char(o,16441).
+char(m,16442).
+char(1,16443).
+char(0,16444).
+char(2,16445).
+char(0,16446).
+char(p,16447).
+char(8,16448).
+char(3,16449).
+char(0,16450).
+char(9,16451).
+char(c,16452).
+char(p,16453).
+char(o,16454).
+char(8,16455).
+char(2,16456).
+char(6,16457).
+char(1,16458).
+char(m,16459).
+char(8,16460).
+char(5,16461).
+char(6,16462).
+char(2,16463).
+char(c,16464).
+char(m,16465).
+char(5,16466).
+char(2,16467).
+char(8,16468).
+char(3,16469).
+char(m,16470).
+char(9,16471).
+char(6,16472).
+char(9,16473).
+char(0,16474).
+char(c,16475).
+char(m,16476).
+char(9,16477).
+char(4,16478).
+char(5,16479).
+char(p,16480).
+char(4,16481).
+char(8,16482).
+char(6,16483).
+char(4,16484).
+char(m,16485).
+char(2,16486).
+char(0,16487).
+char(6,16488).
+char(0,16489).
+char(m,16490).
+char(6,16491).
+char(5,16492).
+char(7,16493).
+char(2,16494).
+char(c,16495).
+char(c,16496).
+char(p,16497).
+char(o,16498).
+char(m,16499).
+char(6,16500).
+char(1,16501).
+char(3,16502).
+char(9,16503).
+char(c,16504).
+char(c,16505).
+char(c,16506).
+char(m,16507).
+char(7,16508).
+char(5,16509).
+char(6,16510).
+char(c,16511).
+char(c,16512).
+char(c,16513).
+char(c,16514).
+char(m,16515).
+char(2,16516).
+char(3,16517).
+char(6,16518).
+char(1,16519).
+char(m,16520).
+char(o,16521).
+char(m,16522).
+char(6,16523).
+char(2,16524).
+char(4,16525).
+char(0,16526).
+char(c,16527).
+char(c,16528).
+char(m,16529).
+char(o,16530).
+char(p,16531).
+char(1,16532).
+char(1,16533).
+char(4,16534).
+char(8,16535).
+char(p,16536).
+char(o,16537).
+char(m,16538).
+char(9,16539).
+char(7,16540).
+char(1,16541).
+char(4,16542).
+char(c,16543).
+char(p,16544).
+char(9,16545).
+char(0,16546).
+char(8,16547).
+char(0,16548).
+char(c,16549).
+char(p,16550).
+char(o,16551).
+char(2,16552).
+char(2,16553).
+char(9,16554).
+char(5,16555).
+char(p,16556).
+char(1,16557).
+char(0,16558).
+char(3,16559).
+char(8,16560).
+char(c,16561).
+char(c,16562).
+char(m,16563).
+char(o,16564).
+char(m,16565).
+char(3,16566).
+char(2,16567).
+char(3,16568).
+char(7,16569).
+char(c,16570).
+char(m,16571).
+char(7,16572).
+char(5,16573).
+char(4,16574).
+char(4,16575).
+char(m,16576).
+char(9,16577).
+char(8,16578).
+char(3,16579).
+char(p,16580).
+char(4,16581).
+char(3,16582).
+char(9,16583).
+char(9,16584).
+char(c,16585).
+char(m,16586).
+char(5,16587).
+char(9,16588).
+char(9,16589).
+char(c,16590).
+char(m,16591).
+char(3,16592).
+char(9,16593).
+char(4,16594).
+char(1,16595).
+char(c,16596).
+char(p,16597).
+char(o,16598).
+char(m,16599).
+char(o,16600).
+char(7,16601).
+char(1,16602).
+char(5,16603).
+char(1,16604).
+char(p,16605).
+char(o,16606).
+char(m,16607).
+char(o,16608).
+char(p,16609).
+char(o,16610).
+char(p,16611).
+char(3,16612).
+char(8,16613).
+char(3,16614).
+char(3,16615).
+char(c,16616).
+char(c,16617).
+char(c,16618).
+char(p,16619).
+char(o,16620).
+char(p,16621).
+char(o,16622).
+char(9,16623).
+char(0,16624).
+char(0,16625).
+char(7,16626).
+char(m,16627).
+char(3,16628).
+char(3,16629).
+char(6,16630).
+char(2,16631).
+char(c,16632).
+char(p,16633).
+char(o,16634).
+char(m,16635).
+char(6,16636).
+char(5,16637).
+char(6,16638).
+char(7,16639).
+char(c,16640).
+char(c,16641).
+char(c,16642).
+char(c,16643).
+char(c,16644).
+char(c,16645).
+char(c,16646).
+char(m,16647).
+char(o,16648).
+char(5,16649).
+char(4,16650).
+char(9,16651).
+char(0,16652).
+char(p,16653).
+char(1,16654).
+char(5,16655).
+char(0,16656).
+char(1,16657).
+char(c,16658).
+char(p,16659).
+char(o,16660).
+char(p,16661).
+char(o,16662).
+char(9,16663).
+char(8,16664).
+char(7,16665).
+char(5,16666).
+char(c,16667).
+char(c,16668).
+char(c,16669).
+char(c,16670).
+char(m,16671).
+char(o,16672).
+char(o,16673).
+char(m,16674).
+char(7,16675).
+char(1,16676).
+char(3,16677).
+char(2,16678).
+char(c,16679).
+char(c,16680).
+char(c,16681).
+char(c,16682).
+char(m,16683).
+char(2,16684).
+char(3,16685).
+char(7,16686).
+char(8,16687).
+char(c,16688).
+char(c,16689).
+char(p,16690).
+char(o,16691).
+char(o,16692).
+char(m,16693).
+char(o,16694).
+char(o,16695).
+char(o,16696).
+char(m,16697).
+char(o,16698).
+char(o,16699).
+char(p,16700).
+char(3,16701).
+char(9,16702).
+char(8,16703).
+char(9,16704).
+char(p,16705).
+char(o,16706).
+char(m,16707).
+char(7,16708).
+char(8,16709).
+char(3,16710).
+char(c,16711).
+char(p,16712).
+char(o,16713).
+char(o,16714).
+char(m,16715).
+char(o,16716).
+char(7,16717).
+char(9,16718).
+char(7,16719).
+char(1,16720).
+char(p,16721).
+char(o,16722).
+char(p,16723).
+char(o,16724).
+char(2,16725).
+char(7,16726).
+char(8,16727).
+char(8,16728).
+char(m,16729).
+char(9,16730).
+char(8,16731).
+char(8,16732).
+char(6,16733).
+char(p,16734).
+char(1,16735).
+char(3,16736).
+char(6,16737).
+char(7,16738).
+char(c,16739).
+char(c,16740).
+char(p,16741).
+char(5,16742).
+char(6,16743).
+char(4,16744).
+char(3,16745).
+char(c,16746).
+char(c,16747).
+char(c,16748).
+char(p,16749).
+char(o,16750).
+char(5,16751).
+char(4,16752).
+char(5,16753).
+char(3,16754).
+char(p,16755).
+char(o,16756).
+char(p,16757).
+char(4,16758).
+char(4,16759).
+char(2,16760).
+char(1,16761).
+char(c,16762).
+char(c,16763).
+char(m,16764).
+char(o,16765).
+char(p,16766).
+char(5,16767).
+char(6,16768).
+char(6,16769).
+char(4,16770).
+char(c,16771).
+char(c,16772).
+char(c,16773).
+char(c,16774).
+char(m,16775).
+char(8,16776).
+char(2,16777).
+char(2,16778).
+char(0,16779).
+char(c,16780).
+char(c,16781).
+char(p,16782).
+char(1,16783).
+char(3,16784).
+char(4,16785).
+char(2,16786).
+char(m,16787).
+char(o,16788).
+char(m,16789).
+char(o,16790).
+char(m,16791).
+char(2,16792).
+char(9,16793).
+char(0,16794).
+char(m,16795).
+char(o,16796).
+char(p,16797).
+char(o,16798).
+char(p,16799).
+char(o,16800).
+char(o,16801).
+char(p,16802).
+char(o,16803).
+char(m,16804).
+char(o,16805).
+char(o,16806).
+char(9,16807).
+char(0,16808).
+char(2,16809).
+char(9,16810).
+char(c,16811).
+char(p,16812).
+char(1,16813).
+char(2,16814).
+char(7,16815).
+char(5,16816).
+char(m,16817).
+char(o,16818).
+char(m,16819).
+char(o,16820).
+char(7,16821).
+char(9,16822).
+char(8,16823).
+char(6,16824).
+char(p,16825).
+char(4,16826).
+char(5,16827).
+char(0,16828).
+char(1,16829).
+char(c,16830).
+char(m,16831).
+char(o,16832).
+char(o,16833).
+char(m,16834).
+char(o,16835).
+char(m,16836).
+char(2,16837).
+char(4,16838).
+char(2,16839).
+char(1,16840).
+char(c,16841).
+char(c,16842).
+char(m,16843).
+char(o,16844).
+char(5,16845).
+char(6,16846).
+char(0,16847).
+char(0,16848).
+char(m,16849).
+char(o,16850).
+char(m,16851).
+char(8,16852).
+char(1,16853).
+char(5,16854).
+char(9,16855).
+char(p,16856).
+char(o,16857).
+char(m,16858).
+char(9,16859).
+char(4,16860).
+char(3,16861).
+char(0,16862).
+char(c,16863).
+char(c,16864).
+char(m,16865).
+char(o,16866).
+char(4,16867).
+char(6,16868).
+char(1,16869).
+char(4,16870).
+char(p,16871).
+char(o,16872).
+char(p,16873).
+char(1,16874).
+char(8,16875).
+char(9,16876).
+char(1,16877).
+char(p,16878).
+char(5,16879).
+char(0,16880).
+char(7,16881).
+char(8,16882).
+char(c,16883).
+char(m,16884).
+char(o,16885).
+char(p,16886).
+char(o,16887).
+char(p,16888).
+char(3,16889).
+char(4,16890).
+char(7,16891).
+char(9,16892).
+char(p,16893).
+char(8,16894).
+char(8,16895).
+char(3,16896).
+char(5,16897).
+char(m,16898).
+char(8,16899).
+char(4,16900).
+char(4,16901).
+char(1,16902).
+char(m,16903).
+char(o,16904).
+char(p,16905).
+char(o,16906).
+char(o,16907).
+char(p,16908).
+char(4,16909).
+char(9,16910).
+char(8,16911).
+char(3,16912).
+char(c,16913).
+char(p,16914).
+char(o,16915).
+char(o,16916).
+char(p,16917).
+char(o,16918).
+char(m,16919).
+char(o,16920).
+char(m,16921).
+char(5,16922).
+char(5,16923).
+char(8,16924).
+char(6,16925).
+char(c,16926).
+char(c,16927).
+char(m,16928).
+char(o,16929).
+char(5,16930).
+char(2,16931).
+char(2,16932).
+char(p,16933).
+char(2,16934).
+char(3,16935).
+char(2,16936).
+char(8,16937).
+char(p,16938).
+char(2,16939).
+char(3,16940).
+char(4,16941).
+char(2,16942).
+char(c,16943).
+char(p,16944).
+char(1,16945).
+char(9,16946).
+char(8,16947).
+char(9,16948).
+char(c,16949).
+char(c,16950).
+char(p,16951).
+char(o,16952).
+char(7,16953).
+char(0,16954).
+char(0,16955).
+char(8,16956).
+char(m,16957).
+char(o,16958).
+char(1,16959).
+char(7,16960).
+char(0,16961).
+char(0,16962).
+char(c,16963).
+char(m,16964).
+char(2,16965).
+char(9,16966).
+char(7,16967).
+char(1,16968).
+char(c,16969).
+char(c,16970).
+char(c,16971).
+char(c,16972).
+char(m,16973).
+char(o,16974).
+char(p,16975).
+char(6,16976).
+char(7,16977).
+char(0,16978).
+char(4,16979).
+char(c,16980).
+char(c,16981).
+char(p,16982).
+char(6,16983).
+char(8,16984).
+char(2,16985).
+char(1,16986).
+char(p,16987).
+char(o,16988).
+char(p,16989).
+char(2,16990).
+char(5,16991).
+char(1,16992).
+char(0,16993).
+char(c,16994).
+char(c,16995).
+char(c,16996).
+char(c,16997).
+char(c,16998).
+char(m,16999).
+char(o,17000).
+char(9,17001).
+char(2,17002).
+char(5,17003).
+char(7,17004).
+char(m,17005).
+char(o,17006).
+char(p,17007).
+char(o,17008).
+char(m,17009).
+char(o,17010).
+char(4,17011).
+char(5,17012).
+char(c,17013).
+char(m,17014).
+char(2,17015).
+char(4,17016).
+char(0,17017).
+char(1,17018).
+char(p,17019).
+char(o,17020).
+char(o,17021).
+char(p,17022).
+char(o,17023).
+char(o,17024).
+char(m,17025).
+char(6,17026).
+char(4,17027).
+char(4,17028).
+char(9,17029).
+char(c,17030).
+char(c,17031).
+char(c,17032).
+char(m,17033).
+char(1,17034).
+char(3,17035).
+char(6,17036).
+char(4,17037).
+char(c,17038).
+char(m,17039).
+char(3,17040).
+char(4,17041).
+char(1,17042).
+char(m,17043).
+char(o,17044).
+char(p,17045).
+char(o,17046).
+char(p,17047).
+char(3,17048).
+char(5,17049).
+char(4,17050).
+char(7,17051).
+char(m,17052).
+char(2,17053).
+char(4,17054).
+char(4,17055).
+char(c,17056).
+char(p,17057).
+char(o,17058).
+char(9,17059).
+char(8,17060).
+char(4,17061).
+char(8,17062).
+char(c,17063).
+char(c,17064).
+char(m,17065).
+char(9,17066).
+char(7,17067).
+char(6,17068).
+char(5,17069).
+char(m,17070).
+char(o,17071).
+char(m,17072).
+char(o,17073).
+char(7,17074).
+char(0,17075).
+char(1,17076).
+char(0,17077).
+char(m,17078).
+char(9,17079).
+char(3,17080).
+char(1,17081).
+char(2,17082).
+char(c,17083).
+char(c,17084).
+char(c,17085).
+char(c,17086).
+char(p,17087).
+char(o,17088).
+char(m,17089).
+char(o,17090).
+char(p,17091).
+char(5,17092).
+char(0,17093).
+char(9,17094).
+char(2,17095).
+char(p,17096).
+char(9,17097).
+char(0,17098).
+char(9,17099).
+char(3,17100).
+char(m,17101).
+char(7,17102).
+char(6,17103).
+char(4,17104).
+char(8,17105).
+char(p,17106).
+char(6,17107).
+char(1,17108).
+char(2,17109).
+char(8,17110).
+char(m,17111).
+char(6,17112).
+char(7,17113).
+char(7,17114).
+char(8,17115).
+char(c,17116).
+char(c,17117).
+char(c,17118).
+char(m,17119).
+char(8,17120).
+char(7,17121).
+char(9,17122).
+char(9,17123).
+char(c,17124).
+char(m,17125).
+char(o,17126).
+char(p,17127).
+char(7,17128).
+char(0,17129).
+char(4,17130).
+char(3,17131).
+char(c,17132).
+char(c,17133).
+char(c,17134).
+char(p,17135).
+char(9,17136).
+char(5,17137).
+char(4,17138).
+char(m,17139).
+char(o,17140).
+char(3,17141).
+char(0,17142).
+char(8,17143).
+char(3,17144).
+char(c,17145).
+char(c,17146).
+char(m,17147).
+char(7,17148).
+char(5,17149).
+char(3,17150).
+char(0,17151).
+char(m,17152).
+char(o,17153).
+char(m,17154).
+char(5,17155).
+char(3,17156).
+char(5,17157).
+char(6,17158).
+char(c,17159).
+char(c,17160).
+char(p,17161).
+char(3,17162).
+char(5,17163).
+char(5,17164).
+char(6,17165).
+char(c,17166).
+char(p,17167).
+char(o,17168).
+char(6,17169).
+char(2,17170).
+char(7,17171).
+char(8,17172).
+char(m,17173).
+char(o,17174).
+char(m,17175).
+char(o,17176).
+char(m,17177).
+char(8,17178).
+char(8,17179).
+char(0,17180).
+char(1,17181).
+char(p,17182).
+char(4,17183).
+char(3,17184).
+char(6,17185).
+char(1,17186).
+char(m,17187).
+char(o,17188).
+char(o,17189).
+char(7,17190).
+char(1,17191).
+char(2,17192).
+char(6,17193).
+char(m,17194).
+char(o,17195).
+char(p,17196).
+char(o,17197).
+char(o,17198).
+char(o,17199).
+char(o,17200).
+char(p,17201).
+char(3,17202).
+char(4,17203).
+char(5,17204).
+char(6,17205).
+char(p,17206).
+char(6,17207).
+char(5,17208).
+char(3,17209).
+char(8,17210).
+char(m,17211).
+char(o,17212).
+char(o,17213).
+char(o,17214).
+char(p,17215).
+char(2,17216).
+char(5,17217).
+char(2,17218).
+char(c,17219).
+char(c,17220).
+char(p,17221).
+char(4,17222).
+char(5,17223).
+char(8,17224).
+char(1,17225).
+char(c,17226).
+char(c,17227).
+char(p,17228).
+char(o,17229).
+char(p,17230).
+char(4,17231).
+char(5,17232).
+char(9,17233).
+char(5,17234).
+char(c,17235).
+char(c,17236).
+char(m,17237).
+char(5,17238).
+char(9,17239).
+char(1,17240).
+char(2,17241).
+char(c,17242).
+char(m,17243).
+char(o,17244).
+char(m,17245).
+char(o,17246).
+char(8,17247).
+char(6,17248).
+char(8,17249).
+char(9,17250).
+char(p,17251).
+char(o,17252).
+char(m,17253).
+char(8,17254).
+char(7,17255).
+char(7,17256).
+char(8,17257).
+char(m,17258).
+char(o,17259).
+char(m,17260).
+char(o,17261).
+char(m,17262).
+char(o,17263).
+char(p,17264).
+char(7,17265).
+char(2,17266).
+char(3,17267).
+char(3,17268).
+char(m,17269).
+char(3,17270).
+char(5,17271).
+char(3,17272).
+char(0,17273).
+char(p,17274).
+char(6,17275).
+char(7,17276).
+char(5,17277).
+char(7,17278).
+char(m,17279).
+char(o,17280).
+char(m,17281).
+char(o,17282).
+char(p,17283).
+char(o,17284).
+char(p,17285).
+char(o,17286).
+char(p,17287).
+char(o,17288).
+char(m,17289).
+char(o,17290).
+char(p,17291).
+char(2,17292).
+char(4,17293).
+char(9,17294).
+char(c,17295).
+char(p,17296).
+char(2,17297).
+char(3,17298).
+char(8,17299).
+char(p,17300).
+char(o,17301).
+char(o,17302).
+char(p,17303).
+char(2,17304).
+char(2,17305).
+char(8,17306).
+char(5,17307).
+char(m,17308).
+char(o,17309).
+char(p,17310).
+char(5,17311).
+char(9,17312).
+char(5,17313).
+char(1,17314).
+char(p,17315).
+char(o,17316).
+char(m,17317).
+char(8,17318).
+char(1,17319).
+char(0,17320).
+char(8,17321).
+char(c,17322).
+char(m,17323).
+char(o,17324).
+char(p,17325).
+char(o,17326).
+char(1,17327).
+char(6,17328).
+char(7,17329).
+char(p,17330).
+char(9,17331).
+char(7,17332).
+char(8,17333).
+char(6,17334).
+char(p,17335).
+char(9,17336).
+char(3,17337).
+char(8,17338).
+char(c,17339).
+char(c,17340).
+char(c,17341).
+char(c,17342).
+char(c,17343).
+char(c,17344).
+char(c,17345).
+char(p,17346).
+char(8,17347).
+char(5,17348).
+char(4,17349).
+char(6,17350).
+char(c,17351).
+char(c,17352).
+char(p,17353).
+char(o,17354).
+char(p,17355).
+char(2,17356).
+char(4,17357).
+char(4,17358).
+char(8,17359).
+char(c,17360).
+char(m,17361).
+char(o,17362).
+char(o,17363).
+char(m,17364).
+char(o,17365).
+char(m,17366).
+char(o,17367).
+char(6,17368).
+char(8,17369).
+char(c,17370).
+char(c,17371).
+char(c,17372).
+char(c,17373).
+char(c,17374).
+char(m,17375).
+char(o,17376).
+char(p,17377).
+char(1,17378).
+char(0,17379).
+char(3,17380).
+char(1,17381).
+char(c,17382).
+char(m,17383).
+char(4,17384).
+char(9,17385).
+char(2,17386).
+char(0,17387).
+char(m,17388).
+char(1,17389).
+char(2,17390).
+char(8,17391).
+char(0,17392).
+char(m,17393).
+char(7,17394).
+char(4,17395).
+char(3,17396).
+char(3,17397).
+char(c,17398).
+char(c,17399).
+char(c,17400).
+char(c,17401).
+char(m,17402).
+char(o,17403).
+char(p,17404).
+char(o,17405).
+char(m,17406).
+char(o,17407).
+char(p,17408).
+char(6,17409).
+char(6,17410).
+char(9,17411).
+char(m,17412).
+char(8,17413).
+char(9,17414).
+char(2,17415).
+char(m,17416).
+char(9,17417).
+char(6,17418).
+char(2,17419).
+char(0,17420).
+char(m,17421).
+char(2,17422).
+char(4,17423).
+char(7,17424).
+char(2,17425).
+char(c,17426).
+char(p,17427).
+char(9,17428).
+char(3,17429).
+char(5,17430).
+char(4,17431).
+char(p,17432).
+char(4,17433).
+char(0,17434).
+char(7,17435).
+char(9,17436).
+char(c,17437).
+char(m,17438).
+char(1,17439).
+char(5,17440).
+char(1,17441).
+char(3,17442).
+char(m,17443).
+char(o,17444).
+char(8,17445).
+char(4,17446).
+char(9,17447).
+char(5,17448).
+char(m,17449).
+char(2,17450).
+char(3,17451).
+char(6,17452).
+char(2,17453).
+char(m,17454).
+char(1,17455).
+char(0,17456).
+char(9,17457).
+char(8,17458).
+char(c,17459).
+char(m,17460).
+char(o,17461).
+char(p,17462).
+char(o,17463).
+char(6,17464).
+char(6,17465).
+char(8,17466).
+char(6,17467).
+char(c,17468).
+char(p,17469).
+char(o,17470).
+char(m,17471).
+char(o,17472).
+char(m,17473).
+char(4,17474).
+char(6,17475).
+char(0,17476).
+char(1,17477).
+char(c,17478).
+char(m,17479).
+char(o,17480).
+char(m,17481).
+char(o,17482).
+char(3,17483).
+char(2,17484).
+char(7,17485).
+char(3,17486).
+char(p,17487).
+char(o,17488).
+char(p,17489).
+char(9,17490).
+char(0,17491).
+char(0,17492).
+char(3,17493).
+char(c,17494).
+char(c,17495).
+char(p,17496).
+char(o,17497).
+char(p,17498).
+char(1,17499).
+char(5,17500).
+char(2,17501).
+char(3,17502).
+char(m,17503).
+char(7,17504).
+char(1,17505).
+char(0,17506).
+char(3,17507).
+char(c,17508).
+char(c,17509).
+char(c,17510).
+char(m,17511).
+char(o,17512).
+char(1,17513).
+char(5,17514).
+char(5,17515).
+char(c,17516).
+char(c,17517).
+char(m,17518).
+char(3,17519).
+char(3,17520).
+char(7,17521).
+char(9,17522).
+char(m,17523).
+char(o,17524).
+char(m,17525).
+char(o,17526).
+char(m,17527).
+char(o,17528).
+char(o,17529).
+char(o,17530).
+char(m,17531).
+char(3,17532).
+char(0,17533).
+char(4,17534).
+char(0,17535).
+char(c,17536).
+char(m,17537).
+char(9,17538).
+char(6,17539).
+char(0,17540).
+char(8,17541).
+char(p,17542).
+char(4,17543).
+char(6,17544).
+char(1,17545).
+char(c,17546).
+char(m,17547).
+char(o,17548).
+char(7,17549).
+char(8,17550).
+char(3,17551).
+char(1,17552).
+char(c,17553).
+char(c,17554).
+char(p,17555).
+char(5,17556).
+char(5,17557).
+char(0,17558).
+char(5,17559).
+char(c,17560).
+char(p,17561).
+char(2,17562).
+char(3,17563).
+char(9,17564).
+char(8,17565).
+char(c,17566).
+char(c,17567).
+char(c,17568).
+char(c,17569).
+char(c,17570).
+char(m,17571).
+char(8,17572).
+char(6,17573).
+char(5,17574).
+char(7,17575).
+char(p,17576).
+char(o,17577).
+char(p,17578).
+char(o,17579).
+char(o,17580).
+char(p,17581).
+char(5,17582).
+char(1,17583).
+char(7,17584).
+char(6,17585).
+char(c,17586).
+char(m,17587).
+char(o,17588).
+char(p,17589).
+char(8,17590).
+char(2,17591).
+char(3,17592).
+char(4,17593).
+char(c,17594).
+char(p,17595).
+char(8,17596).
+char(7,17597).
+char(0,17598).
+char(9,17599).
+char(c,17600).
+char(p,17601).
+char(o,17602).
+char(o,17603).
+char(o,17604).
+char(p,17605).
+char(5,17606).
+char(3,17607).
+char(4,17608).
+char(7,17609).
+char(c,17610).
+char(m,17611).
+char(o,17612).
+char(8,17613).
+char(0,17614).
+char(0,17615).
+char(5,17616).
+char(p,17617).
+char(o,17618).
+char(8,17619).
+char(5,17620).
+char(4,17621).
+char(6,17622).
+char(m,17623).
+char(4,17624).
+char(6,17625).
+char(7,17626).
+char(4,17627).
+char(c,17628).
+char(m,17629).
+char(o,17630).
+char(o,17631).
+char(2,17632).
+char(6,17633).
+char(8,17634).
+char(4,17635).
+char(p,17636).
+char(9,17637).
+char(6,17638).
+char(9,17639).
+char(1,17640).
+char(c,17641).
+char(p,17642).
+char(8,17643).
+char(8,17644).
+char(3,17645).
+char(9,17646).
+char(m,17647).
+char(o,17648).
+char(6,17649).
+char(8,17650).
+char(7,17651).
+char(1,17652).
+char(m,17653).
+char(8,17654).
+char(1,17655).
+char(6,17656).
+char(9,17657).
+char(c,17658).
+char(p,17659).
+char(o,17660).
+char(8,17661).
+char(1,17662).
+char(8,17663).
+char(5,17664).
+char(c,17665).
+char(c,17666).
+char(c,17667).
+char(p,17668).
+char(o,17669).
+char(m,17670).
+char(6,17671).
+char(7,17672).
+char(4,17673).
+char(9,17674).
+char(c,17675).
+char(p,17676).
+char(o,17677).
+char(o,17678).
+char(m,17679).
+char(8,17680).
+char(2,17681).
+char(6,17682).
+char(4,17683).
+char(p,17684).
+char(o,17685).
+char(m,17686).
+char(6,17687).
+char(8,17688).
+char(3,17689).
+char(1,17690).
+char(c,17691).
+char(m,17692).
+char(1,17693).
+char(7,17694).
+char(4,17695).
+char(0,17696).
+char(m,17697).
+char(o,17698).
+char(m,17699).
+char(7,17700).
+char(3,17701).
+char(0,17702).
+char(6,17703).
+char(m,17704).
+char(7,17705).
+char(9,17706).
+char(5,17707).
+char(6,17708).
+char(c,17709).
+char(m,17710).
+char(o,17711).
+char(p,17712).
+char(2,17713).
+char(5,17714).
+char(9,17715).
+char(1,17716).
+char(p,17717).
+char(1,17718).
+char(3,17719).
+char(8,17720).
+char(8,17721).
+char(c,17722).
+char(c,17723).
+char(p,17724).
+char(4,17725).
+char(8,17726).
+char(6,17727).
+char(4,17728).
+char(p,17729).
+char(2,17730).
+char(5,17731).
+char(2,17732).
+char(6,17733).
+char(m,17734).
+char(9,17735).
+char(3,17736).
+char(6,17737).
+char(9,17738).
+char(p,17739).
+char(o,17740).
+char(m,17741).
+char(o,17742).
+char(p,17743).
+char(7,17744).
+char(7,17745).
+char(5,17746).
+char(9,17747).
+char(c,17748).
+char(m,17749).
+char(o,17750).
+char(p,17751).
+char(3,17752).
+char(7,17753).
+char(3,17754).
+char(5,17755).
+char(m,17756).
+char(o,17757).
+char(m,17758).
+char(o,17759).
+char(2,17760).
+char(7,17761).
+char(5,17762).
+char(9,17763).
+char(c,17764).
+char(c,17765).
+char(c,17766).
+char(m,17767).
+char(4,17768).
+char(1,17769).
+char(8,17770).
+char(3,17771).
+char(p,17772).
+char(o,17773).
+char(m,17774).
+char(o,17775).
+char(m,17776).
+char(4,17777).
+char(6,17778).
+char(2,17779).
+char(m,17780).
+char(5,17781).
+char(7,17782).
+char(9,17783).
+char(3,17784).
+char(p,17785).
+char(7,17786).
+char(1,17787).
+char(1,17788).
+char(c,17789).
+char(c,17790).
+char(c,17791).
+char(c,17792).
+char(p,17793).
+char(o,17794).
+char(p,17795).
+char(o,17796).
+char(m,17797).
+char(5,17798).
+char(1,17799).
+char(3,17800).
+char(1,17801).
+char(c,17802).
+char(p,17803).
+char(o,17804).
+char(p,17805).
+char(o,17806).
+char(o,17807).
+char(m,17808).
+char(8,17809).
+char(6,17810).
+char(3,17811).
+char(3,17812).
+char(c,17813).
+char(c,17814).
+char(m,17815).
+char(o,17816).
+char(m,17817).
+char(o,17818).
+char(p,17819).
+char(o,17820).
+char(p,17821).
+char(2,17822).
+char(1,17823).
+char(4,17824).
+char(c,17825).
+char(p,17826).
+char(o,17827).
+char(p,17828).
+char(3,17829).
+char(9,17830).
+char(1,17831).
+char(4,17832).
+char(p,17833).
+char(9,17834).
+char(6,17835).
+char(7,17836).
+char(5,17837).
+char(c,17838).
+char(p,17839).
+char(o,17840).
+char(m,17841).
+char(o,17842).
+char(o,17843).
+char(p,17844).
+char(o,17845).
+char(m,17846).
+char(7,17847).
+char(9,17848).
+char(3,17849).
+char(9,17850).
+char(p,17851).
+char(9,17852).
+char(1,17853).
+char(7,17854).
+char(1,17855).
+char(c,17856).
+char(c,17857).
+char(c,17858).
+char(c,17859).
+char(c,17860).
+char(m,17861).
+char(1,17862).
+char(7,17863).
+char(8,17864).
+char(7,17865).
+char(p,17866).
+char(6,17867).
+char(6,17868).
+char(7,17869).
+char(5,17870).
+char(c,17871).
+char(p,17872).
+char(o,17873).
+char(o,17874).
+char(4,17875).
+char(6,17876).
+char(5,17877).
+char(5,17878).
+char(p,17879).
+char(3,17880).
+char(8,17881).
+char(3,17882).
+char(6,17883).
+char(c,17884).
+char(c,17885).
+char(p,17886).
+char(o,17887).
+char(o,17888).
+char(o,17889).
+char(m,17890).
+char(o,17891).
+char(m,17892).
+char(6,17893).
+char(3,17894).
+char(2,17895).
+char(4,17896).
+char(p,17897).
+char(4,17898).
+char(1,17899).
+char(9,17900).
+char(7,17901).
+char(p,17902).
+char(7,17903).
+char(4,17904).
+char(0,17905).
+char(0,17906).
+char(c,17907).
+char(p,17908).
+char(1,17909).
+char(1,17910).
+char(5,17911).
+char(4,17912).
+char(c,17913).
+char(c,17914).
+char(p,17915).
+char(3,17916).
+char(4,17917).
+char(9,17918).
+char(0,17919).
+char(m,17920).
+char(8,17921).
+char(6,17922).
+char(2,17923).
+char(1,17924).
+char(p,17925).
+char(4,17926).
+char(6,17927).
+char(0,17928).
+char(8,17929).
+char(c,17930).
+char(m,17931).
+char(3,17932).
+char(4,17933).
+char(0,17934).
+char(7,17935).
+char(p,17936).
+char(1,17937).
+char(1,17938).
+char(0,17939).
+char(7,17940).
+char(c,17941).
+char(c,17942).
+char(c,17943).
+char(c,17944).
+char(c,17945).
+char(c,17946).
+char(c,17947).
+char(p,17948).
+char(4,17949).
+char(7,17950).
+char(5,17951).
+char(9,17952).
+char(p,17953).
+char(o,17954).
+char(p,17955).
+char(o,17956).
+char(p,17957).
+char(8,17958).
+char(8,17959).
+char(9,17960).
+char(0,17961).
+char(c,17962).
+char(c,17963).
+char(c,17964).
+char(m,17965).
+char(o,17966).
+char(m,17967).
+char(7,17968).
+char(1,17969).
+char(1,17970).
+char(1,17971).
+char(c,17972).
+char(c,17973).
+char(c,17974).
+char(c,17975).
+char(c,17976).
+char(c,17977).
+char(c,17978).
+char(c,17979).
+char(p,17980).
+char(4,17981).
+char(6,17982).
+char(0,17983).
+char(0,17984).
+char(m,17985).
+char(4,17986).
+char(3,17987).
+char(p,17988).
+char(6,17989).
+char(0,17990).
+char(5,17991).
+char(2,17992).
+char(c,17993).
+char(m,17994).
+char(4,17995).
+char(9,17996).
+char(9,17997).
+char(5,17998).
+char(m,17999).
+char(1,18000).
+char(7,18001).
+char(0,18002).
+char(1,18003).
+char(c,18004).
+char(c,18005).
+char(c,18006).
+char(c,18007).
+char(c,18008).
+char(m,18009).
+char(5,18010).
+char(9,18011).
+char(9,18012).
+char(3,18013).
+char(c,18014).
+char(m,18015).
+char(o,18016).
+char(o,18017).
+char(m,18018).
+char(1,18019).
+char(4,18020).
+char(1,18021).
+char(2,18022).
+char(p,18023).
+char(o,18024).
+char(o,18025).
+char(m,18026).
+char(7,18027).
+char(5,18028).
+char(1,18029).
+char(5,18030).
+char(c,18031).
+char(c,18032).
+char(c,18033).
+char(p,18034).
+char(o,18035).
+char(m,18036).
+char(9,18037).
+char(6,18038).
+char(6,18039).
+char(9,18040).
+char(p,18041).
+char(9,18042).
+char(8,18043).
+char(3,18044).
+char(4,18045).
+char(m,18046).
+char(8,18047).
+char(6,18048).
+char(4,18049).
+char(7,18050).
+char(m,18051).
+char(3,18052).
+char(5,18053).
+char(8,18054).
+char(0,18055).
+char(c,18056).
+char(p,18057).
+char(5,18058).
+char(0,18059).
+char(4,18060).
+char(c,18061).
+char(c,18062).
+char(p,18063).
+char(4,18064).
+char(9,18065).
+char(1,18066).
+char(0,18067).
+char(c,18068).
+char(c,18069).
+char(c,18070).
+char(m,18071).
+char(5,18072).
+char(4,18073).
+char(3,18074).
+char(7,18075).
+char(c,18076).
+char(p,18077).
+char(6,18078).
+char(2,18079).
+char(1,18080).
+char(4,18081).
+char(m,18082).
+char(4,18083).
+char(7,18084).
+char(4,18085).
+char(0,18086).
+char(m,18087).
+char(3,18088).
+char(9,18089).
+char(5,18090).
+char(3,18091).
+char(c,18092).
+char(p,18093).
+char(o,18094).
+char(2,18095).
+char(0,18096).
+char(4,18097).
+char(7,18098).
+char(m,18099).
+char(o,18100).
+char(p,18101).
+char(3,18102).
+char(3,18103).
+char(5,18104).
+char(m,18105).
+char(o,18106).
+char(m,18107).
+char(o,18108).
+char(o,18109).
+char(m,18110).
+char(o,18111).
+char(o,18112).
+char(7,18113).
+char(8,18114).
+char(5,18115).
+char(0,18116).
+char(c,18117).
+char(c,18118).
+char(c,18119).
+char(m,18120).
+char(7,18121).
+char(4,18122).
+char(8,18123).
+char(0,18124).
+char(c,18125).
+char(c,18126).
+char(c,18127).
+char(c,18128).
+char(m,18129).
+char(o,18130).
+char(p,18131).
+char(6,18132).
+char(9,18133).
+char(5,18134).
+char(7,18135).
+char(p,18136).
+char(o,18137).
+char(p,18138).
+char(4,18139).
+char(3,18140).
+char(1,18141).
+char(5,18142).
+char(m,18143).
+char(o,18144).
+char(m,18145).
+char(o,18146).
+char(m,18147).
+char(5,18148).
+char(6,18149).
+char(8,18150).
+char(c,18151).
+char(c,18152).
+char(m,18153).
+char(o,18154).
+char(o,18155).
+char(4,18156).
+char(0,18157).
+char(8,18158).
+char(3,18159).
+char(c,18160).
+char(p,18161).
+char(1,18162).
+char(0,18163).
+char(7,18164).
+char(9,18165).
+char(m,18166).
+char(3,18167).
+char(0,18168).
+char(4,18169).
+char(9,18170).
+char(c,18171).
+char(m,18172).
+char(2,18173).
+char(1,18174).
+char(4,18175).
+char(5,18176).
+char(c,18177).
+char(m,18178).
+char(o,18179).
+char(p,18180).
+char(o,18181).
+char(m,18182).
+char(o,18183).
+char(m,18184).
+char(6,18185).
+char(0,18186).
+char(5,18187).
+char(1,18188).
+char(c,18189).
+char(c,18190).
+char(p,18191).
+char(o,18192).
+char(o,18193).
+char(m,18194).
+char(7,18195).
+char(4,18196).
+char(7,18197).
+char(2,18198).
+char(p,18199).
+char(o,18200).
+char(m,18201).
+char(o,18202).
+char(p,18203).
+char(o,18204).
+char(m,18205).
+char(7,18206).
+char(5,18207).
+char(0,18208).
+char(0,18209).
+char(c,18210).
+char(p,18211).
+char(6,18212).
+char(4,18213).
+char(4,18214).
+char(3,18215).
+char(c,18216).
+char(c,18217).
+char(c,18218).
+char(c,18219).
+char(m,18220).
+char(o,18221).
+char(o,18222).
+char(p,18223).
+char(3,18224).
+char(8,18225).
+char(8,18226).
+char(c,18227).
+char(p,18228).
+char(o,18229).
+char(o,18230).
+char(9,18231).
+char(3,18232).
+char(6,18233).
+char(8,18234).
+char(c,18235).
+char(c,18236).
+char(m,18237).
+char(o,18238).
+char(m,18239).
+char(9,18240).
+char(2,18241).
+char(6,18242).
+char(2,18243).
+char(c,18244).
+char(m,18245).
+char(7,18246).
+char(6,18247).
+char(5,18248).
+char(7,18249).
+char(c,18250).
+char(c,18251).
+char(m,18252).
+char(o,18253).
+char(p,18254).
+char(6,18255).
+char(1,18256).
+char(4,18257).
+char(4,18258).
+char(c,18259).
+char(c,18260).
+char(m,18261).
+char(o,18262).
+char(p,18263).
+char(2,18264).
+char(5,18265).
+char(1,18266).
+char(0,18267).
+char(m,18268).
+char(o,18269).
+char(o,18270).
+char(m,18271).
+char(4,18272).
+char(4,18273).
+char(1,18274).
+char(1,18275).
+char(c,18276).
+char(c,18277).
+char(c,18278).
+char(c,18279).
+char(c,18280).
+char(m,18281).
+char(1,18282).
+char(5,18283).
+char(6,18284).
+char(9,18285).
+char(p,18286).
+char(o,18287).
+char(m,18288).
+char(8,18289).
+char(4,18290).
+char(9,18291).
+char(7,18292).
+char(p,18293).
+char(6,18294).
+char(6,18295).
+char(1,18296).
+char(3,18297).
+char(c,18298).
+char(m,18299).
+char(o,18300).
+char(5,18301).
+char(6,18302).
+char(0,18303).
+char(2,18304).
+char(m,18305).
+char(3,18306).
+char(9,18307).
+char(9,18308).
+char(1,18309).
+char(c,18310).
+char(m,18311).
+char(o,18312).
+char(p,18313).
+char(o,18314).
+char(p,18315).
+char(o,18316).
+char(p,18317).
+char(o,18318).
+char(p,18319).
+char(o,18320).
+char(p,18321).
+char(o,18322).
+char(m,18323).
+char(6,18324).
+char(4,18325).
+char(4,18326).
+char(6,18327).
+char(p,18328).
+char(3,18329).
+char(0,18330).
+char(2,18331).
+char(0,18332).
+char(p,18333).
+char(o,18334).
+char(1,18335).
+char(2,18336).
+char(8,18337).
+char(7,18338).
+char(p,18339).
+char(o,18340).
+char(p,18341).
+char(5,18342).
+char(2,18343).
+char(8,18344).
+char(5,18345).
+char(m,18346).
+char(o,18347).
+char(p,18348).
+char(o,18349).
+char(m,18350).
+char(6,18351).
+char(3,18352).
+char(6,18353).
+char(4,18354).
+char(c,18355).
+char(p,18356).
+char(o,18357).
+char(m,18358).
+char(o,18359).
+char(m,18360).
+char(o,18361).
+char(p,18362).
+char(4,18363).
+char(7,18364).
+char(7,18365).
+char(5,18366).
+char(m,18367).
+char(o,18368).
+char(p,18369).
+char(o,18370).
+char(p,18371).
+char(2,18372).
+char(4,18373).
+char(4,18374).
+char(0,18375).
+char(c,18376).
+char(p,18377).
+char(8,18378).
+char(1,18379).
+char(1,18380).
+char(4,18381).
+char(p,18382).
+char(8,18383).
+char(9,18384).
+char(6,18385).
+char(5,18386).
+char(c,18387).
+char(m,18388).
+char(o,18389).
+char(p,18390).
+char(o,18391).
+char(p,18392).
+char(o,18393).
+char(m,18394).
+char(o,18395).
+char(m,18396).
+char(o,18397).
+char(o,18398).
+char(6,18399).
+char(5,18400).
+char(0,18401).
+char(6,18402).
+char(m,18403).
+char(5,18404).
+char(8,18405).
+char(8,18406).
+char(4,18407).
+char(m,18408).
+char(o,18409).
+char(m,18410).
+char(1,18411).
+char(9,18412).
+char(2,18413).
+char(c,18414).
+char(c,18415).
+char(m,18416).
+char(1,18417).
+char(3,18418).
+char(0,18419).
+char(0,18420).
+char(c,18421).
+char(m,18422).
+char(8,18423).
+char(3,18424).
+char(4,18425).
+char(1,18426).
+char(m,18427).
+char(o,18428).
+char(8,18429).
+char(8,18430).
+char(4,18431).
+char(0,18432).
+char(c,18433).
+char(m,18434).
+char(o,18435).
+char(m,18436).
+char(2,18437).
+char(4,18438).
+char(1,18439).
+char(9,18440).
+char(m,18441).
+char(3,18442).
+char(4,18443).
+char(7,18444).
+char(5,18445).
+char(m,18446).
+char(o,18447).
+char(m,18448).
+char(4,18449).
+char(1,18450).
+char(8,18451).
+char(7,18452).
+char(p,18453).
+char(o,18454).
+char(o,18455).
+char(o,18456).
+char(m,18457).
+char(o,18458).
+char(o,18459).
+char(m,18460).
+char(o,18461).
+char(m,18462).
+char(o,18463).
+char(p,18464).
+char(o,18465).
+char(m,18466).
+char(o,18467).
+char(m,18468).
+char(o,18469).
+char(p,18470).
+char(o,18471).
+char(3,18472).
+char(9,18473).
+char(2,18474).
+char(4,18475).
+char(m,18476).
+char(6,18477).
+char(4,18478).
+char(4,18479).
+char(1,18480).
+char(m,18481).
+char(o,18482).
+char(o,18483).
+char(m,18484).
+char(o,18485).
+char(o,18486).
+char(m,18487).
+char(o,18488).
+char(m,18489).
+char(o,18490).
+char(p,18491).
+char(o,18492).
+char(o,18493).
+char(m,18494).
+char(9,18495).
+char(5,18496).
+char(3,18497).
+char(8,18498).
+char(p,18499).
+char(1,18500).
+char(2,18501).
+char(4,18502).
+char(6,18503).
+char(c,18504).
+char(p,18505).
+char(7,18506).
+char(2,18507).
+char(1,18508).
+char(3,18509).
+char(c,18510).
+char(c,18511).
+char(m,18512).
+char(o,18513).
+char(m,18514).
+char(o,18515).
+char(p,18516).
+char(5,18517).
+char(9,18518).
+char(3,18519).
+char(c,18520).
+char(c,18521).
+char(m,18522).
+char(2,18523).
+char(5,18524).
+char(1,18525).
+char(1,18526).
+char(c,18527).
+char(m,18528).
+char(5,18529).
+char(9,18530).
+char(9,18531).
+char(9,18532).
+char(p,18533).
+char(o,18534).
+char(m,18535).
+char(o,18536).
+char(p,18537).
+char(o,18538).
+char(m,18539).
+char(2,18540).
+char(8,18541).
+char(3,18542).
+char(c,18543).
+char(m,18544).
+char(6,18545).
+char(5,18546).
+char(3,18547).
+char(8,18548).
+char(c,18549).
+char(p,18550).
+char(o,18551).
+char(o,18552).
+char(m,18553).
+char(7,18554).
+char(9,18555).
+char(3,18556).
+char(c,18557).
+char(p,18558).
+char(2,18559).
+char(5,18560).
+char(4,18561).
+char(8,18562).
+char(c,18563).
+char(m,18564).
+char(2,18565).
+char(6,18566).
+char(3,18567).
+char(4,18568).
+char(p,18569).
+char(3,18570).
+char(5,18571).
+char(6,18572).
+char(m,18573).
+char(o,18574).
+char(o,18575).
+char(o,18576).
+char(o,18577).
+char(7,18578).
+char(9,18579).
+char(6,18580).
+char(0,18581).
+char(c,18582).
+char(m,18583).
+char(o,18584).
+char(p,18585).
+char(o,18586).
+char(m,18587).
+char(o,18588).
+char(m,18589).
+char(o,18590).
+char(o,18591).
+char(p,18592).
+char(3,18593).
+char(2,18594).
+char(5,18595).
+char(6,18596).
+char(c,18597).
+char(p,18598).
+char(2,18599).
+char(0,18600).
+char(3,18601).
+char(8,18602).
+char(c,18603).
+char(p,18604).
+char(7,18605).
+char(4,18606).
+char(6,18607).
+char(1,18608).
+char(m,18609).
+char(o,18610).
+char(p,18611).
+char(2,18612).
+char(7,18613).
+char(5,18614).
+char(4,18615).
+char(m,18616).
+char(4,18617).
+char(8,18618).
+char(4,18619).
+char(9,18620).
+char(c,18621).
+char(c,18622).
+char(c,18623).
+char(p,18624).
+char(6,18625).
+char(3,18626).
+char(5,18627).
+char(1,18628).
+char(m,18629).
+char(o,18630).
+char(m,18631).
+char(8,18632).
+char(9,18633).
+char(6,18634).
+char(2,18635).
+char(m,18636).
+char(4,18637).
+char(7,18638).
+char(3,18639).
+char(0,18640).
+char(c,18641).
+char(m,18642).
+char(6,18643).
+char(1,18644).
+char(8,18645).
+char(9,18646).
+char(m,18647).
+char(6,18648).
+char(3,18649).
+char(1,18650).
+char(1,18651).
+char(c,18652).
+char(c,18653).
+char(c,18654).
+char(p,18655).
+char(o,18656).
+char(2,18657).
+char(6,18658).
+char(3,18659).
+char(6,18660).
+char(c,18661).
+char(c,18662).
+char(m,18663).
+char(o,18664).
+char(m,18665).
+char(o,18666).
+char(o,18667).
+char(3,18668).
+char(7,18669).
+char(8,18670).
+char(0,18671).
+char(c,18672).
+char(c,18673).
+char(p,18674).
+char(o,18675).
+char(p,18676).
+char(2,18677).
+char(7,18678).
+char(6,18679).
+char(1,18680).
+char(c,18681).
+char(p,18682).
+char(7,18683).
+char(2,18684).
+char(0,18685).
+char(2,18686).
+char(c,18687).
+char(m,18688).
+char(o,18689).
+char(p,18690).
+char(1,18691).
+char(7,18692).
+char(8,18693).
+char(7,18694).
+char(m,18695).
+char(1,18696).
+char(2,18697).
+char(7,18698).
+char(6,18699).
+char(m,18700).
+char(o,18701).
+char(m,18702).
+char(o,18703).
+char(p,18704).
+char(6,18705).
+char(7,18706).
+char(3,18707).
+char(3,18708).
+char(c,18709).
+char(p,18710).
+char(o,18711).
+char(m,18712).
+char(o,18713).
+char(p,18714).
+char(o,18715).
+char(p,18716).
+char(o,18717).
+char(p,18718).
+char(o,18719).
+char(p,18720).
+char(4,18721).
+char(3,18722).
+char(c,18723).
+char(p,18724).
+char(9,18725).
+char(5,18726).
+char(0,18727).
+char(0,18728).
+char(c,18729).
+char(c,18730).
+char(m,18731).
+char(3,18732).
+char(5,18733).
+char(9,18734).
+char(c,18735).
+char(m,18736).
+char(2,18737).
+char(3,18738).
+char(7,18739).
+char(5,18740).
+char(c,18741).
+char(c,18742).
+char(c,18743).
+char(m,18744).
+char(6,18745).
+char(7,18746).
+char(8,18747).
+char(8,18748).
+char(p,18749).
+char(o,18750).
+char(o,18751).
+char(p,18752).
+char(6,18753).
+char(5,18754).
+char(6,18755).
+char(6,18756).
+char(m,18757).
+char(o,18758).
+char(9,18759).
+char(6,18760).
+char(7,18761).
+char(7,18762).
+char(c,18763).
+char(c,18764).
+char(m,18765).
+char(8,18766).
+char(5,18767).
+char(1,18768).
+char(1,18769).
+char(m,18770).
+char(o,18771).
+char(m,18772).
+char(8,18773).
+char(0,18774).
+char(1,18775).
+char(1,18776).
+char(m,18777).
+char(7,18778).
+char(6,18779).
+char(3,18780).
+char(8,18781).
+char(c,18782).
+char(c,18783).
+char(p,18784).
+char(o,18785).
+char(p,18786).
+char(o,18787).
+char(p,18788).
+char(o,18789).
+char(o,18790).
+char(2,18791).
+char(5,18792).
+char(9,18793).
+char(p,18794).
+char(o,18795).
+char(p,18796).
+char(o,18797).
+char(3,18798).
+char(6,18799).
+char(7,18800).
+char(7,18801).
+char(m,18802).
+char(o,18803).
+char(m,18804).
+char(1,18805).
+char(6,18806).
+char(2,18807).
+char(3,18808).
+char(c,18809).
+char(m,18810).
+char(4,18811).
+char(5,18812).
+char(c,18813).
+char(c,18814).
+char(p,18815).
+char(5,18816).
+char(4,18817).
+char(5,18818).
+char(2,18819).
+char(c,18820).
+char(c,18821).
+char(m,18822).
+char(o,18823).
+char(o,18824).
+char(m,18825).
+char(4,18826).
+char(0,18827).
+char(1,18828).
+char(3,18829).
+char(p,18830).
+char(6,18831).
+char(3,18832).
+char(2,18833).
+char(6,18834).
+char(c,18835).
+char(m,18836).
+char(o,18837).
+char(m,18838).
+char(o,18839).
+char(m,18840).
+char(8,18841).
+char(4,18842).
+char(7,18843).
+char(3,18844).
+char(c,18845).
+char(c,18846).
+char(c,18847).
+char(m,18848).
+char(1,18849).
+char(4,18850).
+char(4,18851).
+char(2,18852).
+char(c,18853).
+char(p,18854).
+char(o,18855).
+char(p,18856).
+char(o,18857).
+char(2,18858).
+char(5,18859).
+char(2,18860).
+char(5,18861).
+char(p,18862).
+char(6,18863).
+char(1,18864).
+char(7,18865).
+char(2,18866).
+char(c,18867).
+char(m,18868).
+char(1,18869).
+char(3,18870).
+char(2,18871).
+char(9,18872).
+char(m,18873).
+char(1,18874).
+char(8,18875).
+char(1,18876).
+char(c,18877).
+char(m,18878).
+char(o,18879).
+char(m,18880).
+char(4,18881).
+char(2,18882).
+char(8,18883).
+char(2,18884).
+char(m,18885).
+char(o,18886).
+char(o,18887).
+char(2,18888).
+char(2,18889).
+char(9,18890).
+char(3,18891).
+char(c,18892).
+char(m,18893).
+char(o,18894).
+char(p,18895).
+char(6,18896).
+char(5,18897).
+char(3,18898).
+char(3,18899).
+char(c,18900).
+char(c,18901).
+char(c,18902).
+char(m,18903).
+char(6,18904).
+char(0,18905).
+char(3,18906).
+char(7,18907).
+char(m,18908).
+char(o,18909).
+char(m,18910).
+char(2,18911).
+char(0,18912).
+char(4,18913).
+char(1,18914).
+char(p,18915).
+char(o,18916).
+char(m,18917).
+char(2,18918).
+char(6,18919).
+char(0,18920).
+char(6,18921).
+char(m,18922).
+char(o,18923).
+char(p,18924).
+char(o,18925).
+char(m,18926).
+char(3,18927).
+char(7,18928).
+char(5,18929).
+char(8,18930).
+char(m,18931).
+char(7,18932).
+char(2,18933).
+char(5,18934).
+char(8,18935).
+char(m,18936).
+char(8,18937).
+char(9,18938).
+char(7,18939).
+char(9,18940).
+char(p,18941).
+char(7,18942).
+char(8,18943).
+char(0,18944).
+char(2,18945).
+char(p,18946).
+char(1,18947).
+char(8,18948).
+char(2,18949).
+char(0,18950).
+char(c,18951).
+char(m,18952).
+char(5,18953).
+char(7,18954).
+char(9,18955).
+char(3,18956).
+char(c,18957).
+char(c,18958).
+char(m,18959).
+char(o,18960).
+char(2,18961).
+char(0,18962).
+char(9,18963).
+char(3,18964).
+char(p,18965).
+char(o,18966).
+char(m,18967).
+char(3,18968).
+char(7,18969).
+char(5,18970).
+char(5,18971).
+char(p,18972).
+char(2,18973).
+char(1,18974).
+char(2,18975).
+char(9,18976).
+char(c,18977).
+char(p,18978).
+char(o,18979).
+char(m,18980).
+char(o,18981).
+char(m,18982).
+char(6,18983).
+char(6,18984).
+char(5,18985).
+char(6,18986).
+char(c,18987).
+char(p,18988).
+char(2,18989).
+char(2,18990).
+char(8,18991).
+char(4,18992).
+char(c,18993).
+char(p,18994).
+char(3,18995).
+char(2,18996).
+char(9,18997).
+char(6,18998).
+char(c,18999).
+char(c,19000).
+char(m,19001).
+char(o,19002).
+char(p,19003).
+char(o,19004).
+char(p,19005).
+char(3,19006).
+char(5,19007).
+char(9,19008).
+char(9,19009).
+char(c,19010).
+char(p,19011).
+char(7,19012).
+char(9,19013).
+char(6,19014).
+char(5,19015).
+char(p,19016).
+char(o,19017).
+char(m,19018).
+char(o,19019).
+char(m,19020).
+char(9,19021).
+char(7,19022).
+char(9,19023).
+char(6,19024).
+char(m,19025).
+char(4,19026).
+char(5,19027).
+char(8,19028).
+char(9,19029).
+char(c,19030).
+char(c,19031).
+char(c,19032).
+char(m,19033).
+char(o,19034).
+char(m,19035).
+char(8,19036).
+char(4,19037).
+char(8,19038).
+char(1,19039).
+char(c,19040).
+char(c,19041).
+char(m,19042).
+char(4,19043).
+char(5,19044).
+char(8,19045).
+char(5,19046).
+char(c,19047).
+char(c,19048).
+char(m,19049).
+char(o,19050).
+char(o,19051).
+char(m,19052).
+char(7,19053).
+char(5,19054).
+char(9,19055).
+char(c,19056).
+char(p,19057).
+char(8,19058).
+char(8,19059).
+char(8,19060).
+char(0,19061).
+char(m,19062).
+char(3,19063).
+char(2,19064).
+char(2,19065).
+char(1,19066).
+char(m,19067).
+char(o,19068).
+char(p,19069).
+char(8,19070).
+char(0,19071).
+char(4,19072).
+char(3,19073).
+char(c,19074).
+char(m,19075).
+char(3,19076).
+char(7,19077).
+char(9,19078).
+char(1,19079).
+char(c,19080).
+char(m,19081).
+char(2,19082).
+char(1,19083).
+char(7,19084).
+char(7,19085).
+char(m,19086).
+char(7,19087).
+char(1,19088).
+char(1,19089).
+char(4,19090).
+char(p,19091).
+char(2,19092).
+char(5,19093).
+char(1,19094).
+char(9,19095).
+char(p,19096).
+char(5,19097).
+char(4,19098).
+char(8,19099).
+char(2,19100).
+char(m,19101).
+char(o,19102).
+char(m,19103).
+char(o,19104).
+char(p,19105).
+char(o,19106).
+char(7,19107).
+char(0,19108).
+char(0,19109).
+char(0,19110).
+char(p,19111).
+char(o,19112).
+char(p,19113).
+char(o,19114).
+char(m,19115).
+char(o,19116).
+char(p,19117).
+char(3,19118).
+char(5,19119).
+char(0,19120).
+char(5,19121).
+char(m,19122).
+char(7,19123).
+char(9,19124).
+char(5,19125).
+char(3,19126).
+char(c,19127).
+char(c,19128).
+char(p,19129).
+char(4,19130).
+char(1,19131).
+char(7,19132).
+char(0,19133).
+char(m,19134).
+char(o,19135).
+char(m,19136).
+char(4,19137).
+char(1,19138).
+char(1,19139).
+char(3,19140).
+char(m,19141).
+char(2,19142).
+char(6,19143).
+char(2,19144).
+char(1,19145).
+char(c,19146).
+char(c,19147).
+char(c,19148).
+char(c,19149).
+char(p,19150).
+char(o,19151).
+char(m,19152).
+char(o,19153).
+char(m,19154).
+char(3,19155).
+char(2,19156).
+char(7,19157).
+char(3,19158).
+char(m,19159).
+char(o,19160).
+char(p,19161).
+char(o,19162).
+char(p,19163).
+char(1,19164).
+char(4,19165).
+char(1,19166).
+char(p,19167).
+char(o,19168).
+char(3,19169).
+char(6,19170).
+char(1,19171).
+char(8,19172).
+char(c,19173).
+char(m,19174).
+char(6,19175).
+char(2,19176).
+char(2,19177).
+char(0,19178).
+char(c,19179).
+char(c,19180).
+char(c,19181).
+char(p,19182).
+char(8,19183).
+char(9,19184).
+char(8,19185).
+char(1,19186).
+char(c,19187).
+char(c,19188).
+char(p,19189).
+char(5,19190).
+char(6,19191).
+char(3,19192).
+char(c,19193).
+char(m,19194).
+char(2,19195).
+char(2,19196).
+char(7,19197).
+char(2,19198).
+char(p,19199).
+char(o,19200).
+char(m,19201).
+char(5,19202).
+char(1,19203).
+char(9,19204).
+char(0,19205).
+char(p,19206).
+char(o,19207).
+char(m,19208).
+char(o,19209).
+char(o,19210).
+char(o,19211).
+char(p,19212).
+char(o,19213).
+char(m,19214).
+char(o,19215).
+char(m,19216).
+char(4,19217).
+char(6,19218).
+char(3,19219).
+char(6,19220).
+char(c,19221).
+char(m,19222).
+char(o,19223).
+char(m,19224).
+char(o,19225).
+char(p,19226).
+char(1,19227).
+char(7,19228).
+char(9,19229).
+char(6,19230).
+char(c,19231).
+char(c,19232).
+char(c,19233).
+char(c,19234).
+char(p,19235).
+char(o,19236).
+char(m,19237).
+char(o,19238).
+char(p,19239).
+char(4,19240).
+char(9,19241).
+char(5,19242).
+char(0,19243).
+char(c,19244).
+char(c,19245).
+char(p,19246).
+char(2,19247).
+char(8,19248).
+char(3,19249).
+char(3,19250).
+char(m,19251).
+char(3,19252).
+char(0,19253).
+char(0,19254).
+char(0,19255).
+char(m,19256).
+char(3,19257).
+char(8,19258).
+char(9,19259).
+char(2,19260).
+char(c,19261).
+char(m,19262).
+char(1,19263).
+char(2,19264).
+char(3,19265).
+char(2,19266).
+char(m,19267).
+char(o,19268).
+char(p,19269).
+char(7,19270).
+char(3,19271).
+char(5,19272).
+char(6,19273).
+char(c,19274).
+char(c,19275).
+char(c,19276).
+char(m,19277).
+char(o,19278).
+char(7,19279).
+char(8,19280).
+char(5,19281).
+char(4,19282).
+char(c,19283).
+char(m,19284).
+char(o,19285).
+char(o,19286).
+char(m,19287).
+char(o,19288).
+char(p,19289).
+char(o,19290).
+char(p,19291).
+char(o,19292).
+char(m,19293).
+char(o,19294).
+char(p,19295).
+char(1,19296).
+char(6,19297).
+char(0,19298).
+char(4,19299).
+char(c,19300).
+char(m,19301).
+char(6,19302).
+char(6,19303).
+char(6,19304).
+char(7,19305).
+char(c,19306).
+char(c,19307).
+char(m,19308).
+char(9,19309).
+char(3,19310).
+char(8,19311).
+char(8,19312).
+char(p,19313).
+char(o,19314).
+char(o,19315).
+char(m,19316).
+char(4,19317).
+char(5,19318).
+char(9,19319).
+char(5,19320).
+char(c,19321).
+char(c,19322).
+char(p,19323).
+char(1,19324).
+char(2,19325).
+char(m,19326).
+char(6,19327).
+char(1,19328).
+char(8,19329).
+char(0,19330).
+char(m,19331).
+char(o,19332).
+char(p,19333).
+char(5,19334).
+char(5,19335).
+char(3,19336).
+char(c,19337).
+char(c,19338).
+char(p,19339).
+char(8,19340).
+char(1,19341).
+char(0,19342).
+char(2,19343).
+char(m,19344).
+char(o,19345).
+char(m,19346).
+char(o,19347).
+char(m,19348).
+char(8,19349).
+char(8,19350).
+char(3,19351).
+char(9,19352).
+char(c,19353).
+char(c,19354).
+char(m,19355).
+char(o,19356).
+char(m,19357).
+char(o,19358).
+char(p,19359).
+char(o,19360).
+char(m,19361).
+char(o,19362).
+char(m,19363).
+char(o,19364).
+char(p,19365).
+char(9,19366).
+char(8,19367).
+char(1,19368).
+char(1,19369).
+char(c,19370).
+char(p,19371).
+char(o,19372).
+char(m,19373).
+char(o,19374).
+char(o,19375).
+char(p,19376).
+char(9,19377).
+char(4,19378).
+char(6,19379).
+char(7,19380).
+char(c,19381).
+char(m,19382).
+char(o,19383).
+char(p,19384).
+char(8,19385).
+char(8,19386).
+char(2,19387).
+char(5,19388).
+char(p,19389).
+char(o,19390).
+char(o,19391).
+char(p,19392).
+char(o,19393).
+char(m,19394).
+char(o,19395).
+char(o,19396).
+char(o,19397).
+char(o,19398).
+char(p,19399).
+char(o,19400).
+char(p,19401).
+char(1,19402).
+char(5,19403).
+char(1,19404).
+char(9,19405).
+char(m,19406).
+char(2,19407).
+char(5,19408).
+char(5,19409).
+char(7,19410).
+char(c,19411).
+char(p,19412).
+char(4,19413).
+char(8,19414).
+char(3,19415).
+char(4,19416).
+char(c,19417).
+char(c,19418).
+char(c,19419).
+char(p,19420).
+char(o,19421).
+char(m,19422).
+char(2,19423).
+char(7,19424).
+char(7,19425).
+char(c,19426).
+char(m,19427).
+char(o,19428).
+char(p,19429).
+char(6,19430).
+char(0,19431).
+char(5,19432).
+char(8,19433).
+char(c,19434).
+char(p,19435).
+char(o,19436).
+char(m,19437).
+char(2,19438).
+char(8,19439).
+char(8,19440).
+char(8,19441).
+char(c,19442).
+char(p,19443).
+char(o,19444).
+char(8,19445).
+char(8,19446).
+char(9,19447).
+char(4,19448).
+char(c,19449).
+char(c,19450).
+char(c,19451).
+char(c,19452).
+char(c,19453).
+char(c,19454).
+char(c,19455).
+char(p,19456).
+char(o,19457).
+char(o,19458).
+char(o,19459).
+char(p,19460).
+char(6,19461).
+char(6,19462).
+char(7,19463).
+char(9,19464).
+char(c,19465).
+char(c,19466).
+char(c,19467).
+char(c,19468).
+char(c,19469).
+char(m,19470).
+char(6,19471).
+char(9,19472).
+char(3,19473).
+char(6,19474).
+char(m,19475).
+char(o,19476).
+char(o,19477).
+char(p,19478).
+char(8,19479).
+char(3,19480).
+char(5,19481).
+char(9,19482).
+char(c,19483).
+char(p,19484).
+char(8,19485).
+char(2,19486).
+char(0,19487).
+char(4,19488).
+char(c,19489).
+char(c,19490).
+char(m,19491).
+char(2,19492).
+char(7,19493).
+char(4,19494).
+char(2,19495).
+char(p,19496).
+char(o,19497).
+char(m,19498).
+char(o,19499).
+char(m,19500).
+char(o,19501).
+char(2,19502).
+char(1,19503).
+char(7,19504).
+char(5,19505).
+char(c,19506).
+char(m,19507).
+char(1,19508).
+char(0,19509).
+char(9,19510).
+char(4,19511).
+char(c,19512).
+char(c,19513).
+char(c,19514).
+char(c,19515).
+char(p,19516).
+char(o,19517).
+char(m,19518).
+char(4,19519).
+char(7,19520).
+char(9,19521).
+char(9,19522).
+char(c,19523).
+char(m,19524).
+char(6,19525).
+char(8,19526).
+char(7,19527).
+char(c,19528).
+char(c,19529).
+char(m,19530).
+char(o,19531).
+char(7,19532).
+char(5,19533).
+char(0,19534).
+char(7,19535).
+char(c,19536).
+char(c,19537).
+char(c,19538).
+char(m,19539).
+char(o,19540).
+char(p,19541).
+char(7,19542).
+char(3,19543).
+char(9,19544).
+char(4,19545).
+char(p,19546).
+char(o,19547).
+char(o,19548).
+char(m,19549).
+char(o,19550).
+char(p,19551).
+char(o,19552).
+char(p,19553).
+char(o,19554).
+char(p,19555).
+char(o,19556).
+char(m,19557).
+char(o,19558).
+char(9,19559).
+char(3,19560).
+char(6,19561).
+char(6,19562).
+char(c,19563).
+char(m,19564).
+char(o,19565).
+char(m,19566).
+char(o,19567).
+char(2,19568).
+char(5,19569).
+char(0,19570).
+char(9,19571).
+char(p,19572).
+char(o,19573).
+char(1,19574).
+char(9,19575).
+char(7,19576).
+char(5,19577).
+char(c,19578).
+char(c,19579).
+char(c,19580).
+char(p,19581).
+char(7,19582).
+char(3,19583).
+char(2,19584).
+char(2,19585).
+char(p,19586).
+char(8,19587).
+char(3,19588).
+char(4,19589).
+char(8,19590).
+char(m,19591).
+char(3,19592).
+char(2,19593).
+char(3,19594).
+char(1,19595).
+char(p,19596).
+char(o,19597).
+char(1,19598).
+char(7,19599).
+char(4,19600).
+char(3,19601).
+char(c,19602).
+char(c,19603).
+char(m,19604).
+char(2,19605).
+char(4,19606).
+char(2,19607).
+char(0,19608).
+char(m,19609).
+char(o,19610).
+char(p,19611).
+char(o,19612).
+char(m,19613).
+char(1,19614).
+char(6,19615).
+char(5,19616).
+char(9,19617).
+char(p,19618).
+char(o,19619).
+char(m,19620).
+char(9,19621).
+char(5,19622).
+char(4,19623).
+char(0,19624).
+char(c,19625).
+char(p,19626).
+char(o,19627).
+char(5,19628).
+char(8,19629).
+char(8,19630).
+char(4,19631).
+char(c,19632).
+char(c,19633).
+char(c,19634).
+char(m,19635).
+char(o,19636).
+char(m,19637).
+char(2,19638).
+char(6,19639).
+char(0,19640).
+char(1,19641).
+char(c,19642).
+char(p,19643).
+char(6,19644).
+char(4,19645).
+char(1,19646).
+char(3,19647).
+char(m,19648).
+char(o,19649).
+char(p,19650).
+char(7,19651).
+char(4,19652).
+char(2,19653).
+char(9,19654).
+char(p,19655).
+char(o,19656).
+char(9,19657).
+char(5,19658).
+char(9,19659).
+char(3,19660).
+char(m,19661).
+char(6,19662).
+char(8,19663).
+char(0,19664).
+char(7,19665).
+char(m,19666).
+char(o,19667).
+char(m,19668).
+char(8,19669).
+char(c,19670).
+char(c,19671).
+char(p,19672).
+char(8,19673).
+char(0,19674).
+char(4,19675).
+char(2,19676).
+char(c,19677).
+char(m,19678).
+char(o,19679).
+char(m,19680).
+char(5,19681).
+char(5,19682).
+char(3,19683).
+char(0,19684).
+char(c,19685).
+char(c,19686).
+char(m,19687).
+char(o,19688).
+char(p,19689).
+char(6,19690).
+char(8,19691).
+char(3,19692).
+char(6,19693).
+char(m,19694).
+char(1,19695).
+char(3,19696).
+char(0,19697).
+char(9,19698).
+char(m,19699).
+char(4,19700).
+char(4,19701).
+char(2,19702).
+char(0,19703).
+char(m,19704).
+char(9,19705).
+char(8,19706).
+char(1,19707).
+char(7,19708).
+char(p,19709).
+char(o,19710).
+char(8,19711).
+char(1,19712).
+char(0,19713).
+char(8,19714).
+char(c,19715).
+char(c,19716).
+char(c,19717).
+char(p,19718).
+char(o,19719).
+char(2,19720).
+char(7,19721).
+char(1,19722).
+char(6,19723).
+char(m,19724).
+char(o,19725).
+char(m,19726).
+char(o,19727).
+char(m,19728).
+char(7,19729).
+char(1,19730).
+char(8,19731).
+char(7,19732).
+char(c,19733).
+char(p,19734).
+char(8,19735).
+char(2,19736).
+char(8,19737).
+char(6,19738).
+char(c,19739).
+char(p,19740).
+char(o,19741).
+char(o,19742).
+char(9,19743).
+char(2,19744).
+char(7,19745).
+char(0,19746).
+char(c,19747).
+char(p,19748).
+char(4,19749).
+char(8,19750).
+char(5,19751).
+char(7,19752).
+char(c,19753).
+char(c,19754).
+char(c,19755).
+char(m,19756).
+char(3,19757).
+char(6,19758).
+char(1,19759).
+char(3,19760).
+char(m,19761).
+char(9,19762).
+char(3,19763).
+char(5,19764).
+char(4,19765).
+char(m,19766).
+char(o,19767).
+char(m,19768).
+char(o,19769).
+char(m,19770).
+char(o,19771).
+char(p,19772).
+char(o,19773).
+char(m,19774).
+char(o,19775).
+char(m,19776).
+char(o,19777).
+char(p,19778).
+char(3,19779).
+char(3,19780).
+char(5,19781).
+char(3,19782).
+char(m,19783).
+char(9,19784).
+char(0,19785).
+char(3,19786).
+char(6,19787).
+char(c,19788).
+char(c,19789).
+char(m,19790).
+char(o,19791).
+char(p,19792).
+char(o,19793).
+char(p,19794).
+char(9,19795).
+char(0,19796).
+char(5,19797).
+char(7,19798).
+char(c,19799).
+char(c,19800).
+char(m,19801).
+char(3,19802).
+char(5,19803).
+char(3,19804).
+char(6,19805).
+char(c,19806).
+char(c,19807).
+char(p,19808).
+char(8,19809).
+char(3,19810).
+char(0,19811).
+char(5,19812).
+char(c,19813).
+char(p,19814).
+char(2,19815).
+char(6,19816).
+char(2,19817).
+char(3,19818).
+char(p,19819).
+char(o,19820).
+char(5,19821).
+char(9,19822).
+char(7,19823).
+char(1,19824).
+char(m,19825).
+char(8,19826).
+char(6,19827).
+char(3,19828).
+char(0,19829).
+char(p,19830).
+char(o,19831).
+char(p,19832).
+char(8,19833).
+char(3,19834).
+char(7,19835).
+char(3,19836).
+char(m,19837).
+char(6,19838).
+char(9,19839).
+char(7,19840).
+char(p,19841).
+char(2,19842).
+char(2,19843).
+char(6,19844).
+char(4,19845).
+char(m,19846).
+char(o,19847).
+char(m,19848).
+char(o,19849).
+char(p,19850).
+char(o,19851).
+char(p,19852).
+char(8,19853).
+char(6,19854).
+char(9,19855).
+char(4,19856).
+char(c,19857).
+char(c,19858).
+char(m,19859).
+char(o,19860).
+char(3,19861).
+char(7,19862).
+char(2,19863).
+char(1,19864).
+char(c,19865).
+char(c,19866).
+char(m,19867).
+char(o,19868).
+char(p,19869).
+char(7,19870).
+char(6,19871).
+char(3,19872).
+char(p,19873).
+char(o,19874).
+char(m,19875).
+char(o,19876).
+char(p,19877).
+char(o,19878).
+char(m,19879).
+char(o,19880).
+char(m,19881).
+char(o,19882).
+char(m,19883).
+char(1,19884).
+char(1,19885).
+char(8,19886).
+char(0,19887).
+char(c,19888).
+char(m,19889).
+char(o,19890).
+char(p,19891).
+char(2,19892).
+char(1,19893).
+char(9,19894).
+char(7,19895).
+char(m,19896).
+char(o,19897).
+char(m,19898).
+char(o,19899).
+char(p,19900).
+char(o,19901).
+char(5,19902).
+char(1,19903).
+char(5,19904).
+char(0,19905).
+char(p,19906).
+char(3,19907).
+char(9,19908).
+char(0,19909).
+char(0,19910).
+char(m,19911).
+char(o,19912).
+char(m,19913).
+char(o,19914).
+char(m,19915).
+char(9,19916).
+char(9,19917).
+char(2,19918).
+char(7,19919).
+char(m,19920).
+char(o,19921).
+char(p,19922).
+char(4,19923).
+char(9,19924).
+char(1,19925).
+char(8,19926).
+char(c,19927).
+char(c,19928).
+char(p,19929).
+char(o,19930).
+char(5,19931).
+char(5,19932).
+char(0,19933).
+char(7,19934).
+char(c,19935).
+char(m,19936).
+char(1,19937).
+char(0,19938).
+char(4,19939).
+char(0,19940).
+char(m,19941).
+char(o,19942).
+char(m,19943).
+char(5,19944).
+char(4,19945).
+char(3,19946).
+char(0,19947).
+char(c,19948).
+char(p,19949).
+char(4,19950).
+char(8,19951).
+char(1,19952).
+char(9,19953).
+char(c,19954).
+char(c,19955).
+char(c,19956).
+char(p,19957).
+char(8,19958).
+char(4,19959).
+char(3,19960).
+char(0,19961).
+char(m,19962).
+char(o,19963).
+char(p,19964).
+char(8,19965).
+char(5,19966).
+char(7,19967).
+char(9,19968).
+char(c,19969).
+char(c,19970).
+char(m,19971).
+char(8,19972).
+char(6,19973).
+char(7,19974).
+char(4,19975).
+char(p,19976).
+char(7,19977).
+char(2,19978).
+char(2,19979).
+char(1,19980).
+char(m,19981).
+char(o,19982).
+char(p,19983).
+char(1,19984).
+char(3,19985).
+char(4,19986).
+char(3,19987).
+char(p,19988).
+char(8,19989).
+char(9,19990).
+char(9,19991).
+char(3,19992).
+char(p,19993).
+char(o,19994).
+char(m,19995).
+char(o,19996).
+char(m,19997).
+char(1,19998).
+char(3,19999).
+char(1,20000).
+char(8,20001).
+char(c,20002).
+char(c,20003).
+char(p,20004).
+char(o,20005).
+char(m,20006).
+char(o,20007).
+char(4,20008).
+char(7,20009).
+char(8,20010).
+char(6,20011).
+char(c,20012).
+char(c,20013).
+char(m,20014).
+char(3,20015).
+char(7,20016).
+char(1,20017).
+char(5,20018).
+char(p,20019).
+char(4,20020).
+char(8,20021).
+char(6,20022).
+char(2,20023).
+char(p,20024).
+char(2,20025).
+char(1,20026).
+char(5,20027).
+char(5,20028).
+char(m,20029).
+char(o,20030).
+char(3,20031).
+char(8,20032).
+char(8,20033).
+char(1,20034).
+char(c,20035).
+char(c,20036).
+char(p,20037).
+char(2,20038).
+char(2,20039).
+char(2,20040).
+char(5,20041).
+char(c,20042).
+char(c,20043).
+char(c,20044).
+char(c,20045).
+char(m,20046).
+char(o,20047).
+char(p,20048).
+char(1,20049).
+char(5,20050).
+char(2,20051).
+char(9,20052).
+char(c,20053).
+char(c,20054).
+char(p,20055).
+char(o,20056).
+char(m,20057).
+char(2,20058).
+char(8,20059).
+char(3,20060).
+char(7,20061).
+char(c,20062).
+char(p,20063).
+char(5,20064).
+char(6,20065).
+char(8,20066).
+char(9,20067).
+char(p,20068).
+char(3,20069).
+char(5,20070).
+char(6,20071).
+char(c,20072).
+char(c,20073).
+char(c,20074).
+char(c,20075).
+char(p,20076).
+char(7,20077).
+char(5,20078).
+char(4,20079).
+char(8,20080).
+char(m,20081).
+char(o,20082).
+char(m,20083).
+char(8,20084).
+char(8,20085).
+char(3,20086).
+char(1,20087).
+char(p,20088).
+char(o,20089).
+char(m,20090).
+char(o,20091).
+char(p,20092).
+char(o,20093).
+char(o,20094).
+char(4,20095).
+char(6,20096).
+char(9,20097).
+char(5,20098).
+char(m,20099).
+char(9,20100).
+char(6,20101).
+char(6,20102).
+char(3,20103).
+char(c,20104).
+char(m,20105).
+char(5,20106).
+char(5,20107).
+char(9,20108).
+char(3,20109).
+char(m,20110).
+char(o,20111).
+char(m,20112).
+char(8,20113).
+char(8,20114).
+char(4,20115).
+char(7,20116).
+char(c,20117).
+char(p,20118).
+char(o,20119).
+char(m,20120).
+char(o,20121).
+char(m,20122).
+char(4,20123).
+char(6,20124).
+char(1,20125).
+char(4,20126).
+char(c,20127).
+char(m,20128).
+char(o,20129).
+char(p,20130).
+char(o,20131).
+char(m,20132).
+char(9,20133).
+char(4,20134).
+char(2,20135).
+char(3,20136).
+char(p,20137).
+char(o,20138).
+char(p,20139).
+char(o,20140).
+char(4,20141).
+char(5,20142).
+char(6,20143).
+char(9,20144).
+char(c,20145).
+char(c,20146).
+char(c,20147).
+char(p,20148).
+char(o,20149).
+char(o,20150).
+char(m,20151).
+char(o,20152).
+char(p,20153).
+char(7,20154).
+char(1,20155).
+char(3,20156).
+char(6,20157).
+char(c,20158).
+char(m,20159).
+char(9,20160).
+char(2,20161).
+char(8,20162).
+char(0,20163).
+char(p,20164).
+char(o,20165).
+char(p,20166).
+char(8,20167).
+char(3,20168).
+char(4,20169).
+char(1,20170).
+char(c,20171).
+char(c,20172).
+char(c,20173).
+char(c,20174).
+char(c,20175).
+char(c,20176).
+char(c,20177).
+char(p,20178).
+char(o,20179).
+char(7,20180).
+char(0,20181).
+char(0,20182).
+char(0,20183).
+char(c,20184).
+char(c,20185).
+char(m,20186).
+char(o,20187).
+char(p,20188).
+char(2,20189).
+char(7,20190).
+char(8,20191).
+char(6,20192).
+char(c,20193).
+char(m,20194).
+char(o,20195).
+char(o,20196).
+char(o,20197).
+char(p,20198).
+char(8,20199).
+char(1,20200).
+char(1,20201).
+char(1,20202).
+char(c,20203).
+char(m,20204).
+char(4,20205).
+char(2,20206).
+char(1,20207).
+char(p,20208).
+char(o,20209).
+char(m,20210).
+char(o,20211).
+char(o,20212).
+char(o,20213).
+char(m,20214).
+char(o,20215).
+char(p,20216).
+char(o,20217).
+char(m,20218).
+char(3,20219).
+char(8,20220).
+char(9,20221).
+char(1,20222).
+char(c,20223).
+char(m,20224).
+char(4,20225).
+char(5,20226).
+char(0,20227).
+char(9,20228).
+char(m,20229).
+char(o,20230).
+char(o,20231).
+char(2,20232).
+char(7,20233).
+char(6,20234).
+char(1,20235).
+char(c,20236).
+char(c,20237).
+char(c,20238).
+char(c,20239).
+char(p,20240).
+char(8,20241).
+char(2,20242).
+char(3,20243).
+char(c,20244).
+char(p,20245).
+char(o,20246).
+char(m,20247).
+char(4,20248).
+char(8,20249).
+char(9,20250).
+char(5,20251).
+char(c,20252).
+char(p,20253).
+char(2,20254).
+char(4,20255).
+char(1,20256).
+char(6,20257).
+char(p,20258).
+char(o,20259).
+char(p,20260).
+char(2,20261).
+char(4,20262).
+char(7,20263).
+char(7,20264).
+char(c,20265).
+char(m,20266).
+char(8,20267).
+char(0,20268).
+char(1,20269).
+char(7,20270).
+char(c,20271).
+char(m,20272).
+char(o,20273).
+char(9,20274).
+char(0,20275).
+char(5,20276).
+char(6,20277).
+char(c,20278).
+char(p,20279).
+char(o,20280).
+char(5,20281).
+char(6,20282).
+char(5,20283).
+char(9,20284).
+char(c,20285).
+char(p,20286).
+char(1,20287).
+char(4,20288).
+char(2,20289).
+char(1,20290).
+char(m,20291).
+char(o,20292).
+char(m,20293).
+char(o,20294).
+char(p,20295).
+char(o,20296).
+char(1,20297).
+char(3,20298).
+char(0,20299).
+char(5,20300).
+char(p,20301).
+char(7,20302).
+char(5,20303).
+char(0,20304).
+char(3,20305).
+char(p,20306).
+char(1,20307).
+char(6,20308).
+char(5,20309).
+char(0,20310).
+char(m,20311).
+char(1,20312).
+char(8,20313).
+char(1,20314).
+char(1,20315).
+char(m,20316).
+char(o,20317).
+char(5,20318).
+char(9,20319).
+char(5,20320).
+char(2,20321).
+char(m,20322).
+char(5,20323).
+char(3,20324).
+char(3,20325).
+char(m,20326).
+char(8,20327).
+char(2,20328).
+char(6,20329).
+char(3,20330).
+char(p,20331).
+char(o,20332).
+char(p,20333).
+char(o,20334).
+char(p,20335).
+char(5,20336).
+char(3,20337).
+char(4,20338).
+char(2,20339).
+char(p,20340).
+char(3,20341).
+char(0,20342).
+char(7,20343).
+char(1,20344).
+char(c,20345).
+char(m,20346).
+char(7,20347).
+char(3,20348).
+char(1,20349).
+char(8,20350).
+char(p,20351).
+char(5,20352).
+char(5,20353).
+char(4,20354).
+char(6,20355).
+char(c,20356).
+char(p,20357).
+char(8,20358).
+char(1,20359).
+char(2,20360).
+char(6,20361).
+char(p,20362).
+char(8,20363).
+char(1,20364).
+char(7,20365).
+char(c,20366).
+char(m,20367).
+char(o,20368).
+char(m,20369).
+char(o,20370).
+char(2,20371).
+char(4,20372).
+char(2,20373).
+char(7,20374).
+char(p,20375).
+char(o,20376).
+char(p,20377).
+char(7,20378).
+char(3,20379).
+char(8,20380).
+char(0,20381).
+char(m,20382).
+char(4,20383).
+char(4,20384).
+char(8,20385).
+char(6,20386).
+char(c,20387).
+char(c,20388).
+char(p,20389).
+char(3,20390).
+char(4,20391).
+char(5,20392).
+char(3,20393).
+char(p,20394).
+char(1,20395).
+char(0,20396).
+char(5,20397).
+char(3,20398).
+char(m,20399).
+char(o,20400).
+char(m,20401).
+char(o,20402).
+char(p,20403).
+char(7,20404).
+char(1,20405).
+char(4,20406).
+char(5,20407).
+char(p,20408).
+char(2,20409).
+char(6,20410).
+char(1,20411).
+char(9,20412).
+char(c,20413).
+char(m,20414).
+char(o,20415).
+char(p,20416).
+char(o,20417).
+char(p,20418).
+char(o,20419).
+char(m,20420).
+char(5,20421).
+char(0,20422).
+char(4,20423).
+char(3,20424).
+char(c,20425).
+char(c,20426).
+char(m,20427).
+char(o,20428).
+char(p,20429).
+char(5,20430).
+char(9,20431).
+char(7,20432).
+char(7,20433).
+char(p,20434).
+char(o,20435).
+char(8,20436).
+char(0,20437).
+char(3,20438).
+char(6,20439).
+char(m,20440).
+char(o,20441).
+char(p,20442).
+char(o,20443).
+char(m,20444).
+char(o,20445).
+char(p,20446).
+char(2,20447).
+char(3,20448).
+char(7,20449).
+char(5,20450).
+char(c,20451).
+char(p,20452).
+char(4,20453).
+char(8,20454).
+char(5,20455).
+char(1,20456).
+char(p,20457).
+char(5,20458).
+char(9,20459).
+char(4,20460).
+char(8,20461).
+char(m,20462).
+char(8,20463).
+char(2,20464).
+char(6,20465).
+char(5,20466).
+char(c,20467).
+char(p,20468).
+char(o,20469).
+char(m,20470).
+char(1,20471).
+char(6,20472).
+char(9,20473).
+char(8,20474).
+char(p,20475).
+char(o,20476).
+char(m,20477).
+char(o,20478).
+char(m,20479).
+char(9,20480).
+char(4,20481).
+char(3,20482).
+char(3,20483).
+char(p,20484).
+char(5,20485).
+char(8,20486).
+char(5,20487).
+char(0,20488).
+char(p,20489).
+char(4,20490).
+char(5,20491).
+char(6,20492).
+char(0,20493).
+char(m,20494).
+char(4,20495).
+char(1,20496).
+char(3,20497).
+char(5,20498).
+char(m,20499).
+char(5,20500).
+char(4,20501).
+char(9,20502).
+char(3,20503).
+char(c,20504).
+char(c,20505).
+char(c,20506).
+char(c,20507).
+char(c,20508).
+char(c,20509).
+char(c,20510).
+char(c,20511).
+char(c,20512).
+char(c,20513).
+char(p,20514).
+char(o,20515).
+char(o,20516).
+char(m,20517).
+char(6,20518).
+char(8,20519).
+char(5,20520).
+char(2,20521).
+char(c,20522).
+char(p,20523).
+char(1,20524).
+char(1,20525).
+char(9,20526).
+char(4,20527).
+char(p,20528).
+char(o,20529).
+char(m,20530).
+char(1,20531).
+char(7,20532).
+char(8,20533).
+char(5,20534).
+char(p,20535).
+char(4,20536).
+char(1,20537).
+char(1,20538).
+char(p,20539).
+char(o,20540).
+char(o,20541).
+char(p,20542).
+char(2,20543).
+char(8,20544).
+char(9,20545).
+char(6,20546).
+char(c,20547).
+char(c,20548).
+char(c,20549).
+char(m,20550).
+char(o,20551).
+char(6,20552).
+char(5,20553).
+char(2,20554).
+char(8,20555).
+char(c,20556).
+char(m,20557).
+char(o,20558).
+char(p,20559).
+char(o,20560).
+char(o,20561).
+char(m,20562).
+char(o,20563).
+char(5,20564).
+char(9,20565).
+char(8,20566).
+char(2,20567).
+char(p,20568).
+char(2,20569).
+char(2,20570).
+char(0,20571).
+char(8,20572).
+char(m,20573).
+char(5,20574).
+char(4,20575).
+char(7,20576).
+char(7,20577).
+char(c,20578).
+char(c,20579).
+char(c,20580).
+char(c,20581).
+char(m,20582).
+char(4,20583).
+char(3,20584).
+char(1,20585).
+char(2,20586).
+char(c,20587).
+char(c,20588).
+char(p,20589).
+char(o,20590).
+char(m,20591).
+char(8,20592).
+char(7,20593).
+char(6,20594).
+char(4,20595).
+char(m,20596).
+char(o,20597).
+char(m,20598).
+char(o,20599).
+char(m,20600).
+char(9,20601).
+char(5,20602).
+char(c,20603).
+char(p,20604).
+char(1,20605).
+char(4,20606).
+char(1,20607).
+char(6,20608).
+char(p,20609).
+char(o,20610).
+char(o,20611).
+char(p,20612).
+char(o,20613).
+char(m,20614).
+char(o,20615).
+char(p,20616).
+char(1,20617).
+char(7,20618).
+char(1,20619).
+char(7,20620).
+char(c,20621).
+char(c,20622).
+char(m,20623).
+char(8,20624).
+char(0,20625).
+char(1,20626).
+char(0,20627).
+char(m,20628).
+char(o,20629).
+char(p,20630).
+char(5,20631).
+char(1,20632).
+char(9,20633).
+char(3,20634).
+char(m,20635).
+char(8,20636).
+char(9,20637).
+char(5,20638).
+char(3,20639).
+char(c,20640).
+char(c,20641).
+char(m,20642).
+char(8,20643).
+char(7,20644).
+char(7,20645).
+char(6,20646).
+char(m,20647).
+char(6,20648).
+char(1,20649).
+char(4,20650).
+char(4,20651).
+char(m,20652).
+char(o,20653).
+char(m,20654).
+char(7,20655).
+char(0,20656).
+char(8,20657).
+char(0,20658).
+char(c,20659).
+char(c,20660).
+char(m,20661).
+char(o,20662).
+char(p,20663).
+char(o,20664).
+char(m,20665).
+char(o,20666).
+char(9,20667).
+char(7,20668).
+char(6,20669).
+char(8,20670).
+char(c,20671).
+char(m,20672).
+char(4,20673).
+char(4,20674).
+char(0,20675).
+char(2,20676).
+char(c,20677).
+char(m,20678).
+char(o,20679).
+char(m,20680).
+char(9,20681).
+char(3,20682).
+char(9,20683).
+char(2,20684).
+char(p,20685).
+char(6,20686).
+char(8,20687).
+char(8,20688).
+char(0,20689).
+char(c,20690).
+char(p,20691).
+char(9,20692).
+char(4,20693).
+char(0,20694).
+char(7,20695).
+char(p,20696).
+char(o,20697).
+char(m,20698).
+char(8,20699).
+char(9,20700).
+char(2,20701).
+char(1,20702).
+char(m,20703).
+char(4,20704).
+char(1,20705).
+char(2,20706).
+char(6,20707).
+char(c,20708).
+char(c,20709).
+char(p,20710).
+char(o,20711).
+char(o,20712).
+char(p,20713).
+char(5,20714).
+char(6,20715).
+char(3,20716).
+char(5,20717).
+char(c,20718).
+char(m,20719).
+char(5,20720).
+char(2,20721).
+char(2,20722).
+char(8,20723).
+char(c,20724).
+char(c,20725).
+char(m,20726).
+char(o,20727).
+char(p,20728).
+char(o,20729).
+char(p,20730).
+char(o,20731).
+char(6,20732).
+char(4,20733).
+char(8,20734).
+char(4,20735).
+char(c,20736).
+char(c,20737).
+char(c,20738).
+char(m,20739).
+char(o,20740).
+char(p,20741).
+char(7,20742).
+char(9,20743).
+char(5,20744).
+char(7,20745).
+char(c,20746).
+char(c,20747).
+char(c,20748).
+char(m,20749).
+char(o,20750).
+char(m,20751).
+char(o,20752).
+char(o,20753).
+char(o,20754).
+char(m,20755).
+char(o,20756).
+char(m,20757).
+char(o,20758).
+char(m,20759).
+char(o,20760).
+char(o,20761).
+char(p,20762).
+char(o,20763).
+char(p,20764).
+char(3,20765).
+char(5,20766).
+char(4,20767).
+char(9,20768).
+char(m,20769).
+char(o,20770).
+char(p,20771).
+char(o,20772).
+char(p,20773).
+char(o,20774).
+char(6,20775).
+char(6,20776).
+char(0,20777).
+char(2,20778).
+char(p,20779).
+char(6,20780).
+char(9,20781).
+char(4,20782).
+char(1,20783).
+char(c,20784).
+char(m,20785).
+char(5,20786).
+char(3,20787).
+char(7,20788).
+char(4,20789).
+char(c,20790).
+char(m,20791).
+char(o,20792).
+char(p,20793).
+char(7,20794).
+char(7,20795).
+char(4,20796).
+char(6,20797).
+char(m,20798).
+char(o,20799).
+char(p,20800).
+char(o,20801).
+char(p,20802).
+char(5,20803).
+char(4,20804).
+char(8,20805).
+char(0,20806).
+char(c,20807).
+char(c,20808).
+char(p,20809).
+char(5,20810).
+char(4,20811).
+char(8,20812).
+char(0,20813).
+char(c,20814).
+char(m,20815).
+char(o,20816).
+char(p,20817).
+char(8,20818).
+char(7,20819).
+char(4,20820).
+char(7,20821).
+char(c,20822).
+char(p,20823).
+char(o,20824).
+char(m,20825).
+char(o,20826).
+char(p,20827).
+char(o,20828).
+char(7,20829).
+char(6,20830).
+char(4,20831).
+char(1,20832).
+char(m,20833).
+char(o,20834).
+char(p,20835).
+char(o,20836).
+char(o,20837).
+char(o,20838).
+char(o,20839).
+char(o,20840).
+char(4,20841).
+char(6,20842).
+char(9,20843).
+char(5,20844).
+char(c,20845).
+char(m,20846).
+char(o,20847).
+char(2,20848).
+char(9,20849).
+char(0,20850).
+char(5,20851).
+char(m,20852).
+char(o,20853).
+char(m,20854).
+char(o,20855).
+char(p,20856).
+char(2,20857).
+char(1,20858).
+char(6,20859).
+char(1,20860).
+char(m,20861).
+char(o,20862).
+char(3,20863).
+char(7,20864).
+char(3,20865).
+char(2,20866).
+char(c,20867).
+char(c,20868).
+char(c,20869).
+char(c,20870).
+char(p,20871).
+char(o,20872).
+char(p,20873).
+char(7,20874).
+char(8,20875).
+char(6,20876).
+char(4,20877).
+char(c,20878).
+char(c,20879).
+char(c,20880).
+char(p,20881).
+char(9,20882).
+char(0,20883).
+char(2,20884).
+char(c,20885).
+char(m,20886).
+char(5,20887).
+char(2,20888).
+char(4,20889).
+char(2,20890).
+char(c,20891).
+char(p,20892).
+char(6,20893).
+char(3,20894).
+char(5,20895).
+char(6,20896).
+char(m,20897).
+char(8,20898).
+char(1,20899).
+char(9,20900).
+char(2,20901).
+char(m,20902).
+char(o,20903).
+char(m,20904).
+char(8,20905).
+char(6,20906).
+char(2,20907).
+char(2,20908).
+char(p,20909).
+char(2,20910).
+char(3,20911).
+char(2,20912).
+char(2,20913).
+char(c,20914).
+char(p,20915).
+char(5,20916).
+char(4,20917).
+char(6,20918).
+char(p,20919).
+char(9,20920).
+char(0,20921).
+char(5,20922).
+char(6,20923).
+char(m,20924).
+char(o,20925).
+char(p,20926).
+char(o,20927).
+char(m,20928).
+char(7,20929).
+char(9,20930).
+char(8,20931).
+char(1,20932).
+char(c,20933).
+char(p,20934).
+char(7,20935).
+char(2,20936).
+char(4,20937).
+char(2,20938).
+char(p,20939).
+char(o,20940).
+char(p,20941).
+char(o,20942).
+char(m,20943).
+char(o,20944).
+char(o,20945).
+char(m,20946).
+char(o,20947).
+char(p,20948).
+char(9,20949).
+char(2,20950).
+char(3,20951).
+char(p,20952).
+char(1,20953).
+char(9,20954).
+char(1,20955).
+char(8,20956).
+char(m,20957).
+char(o,20958).
+char(p,20959).
+char(4,20960).
+char(4,20961).
+char(2,20962).
+char(0,20963).
+char(c,20964).
+char(m,20965).
+char(3,20966).
+char(0,20967).
+char(5,20968).
+char(6,20969).
+char(c,20970).
+char(c,20971).
+char(p,20972).
+char(o,20973).
+char(m,20974).
+char(1,20975).
+char(6,20976).
+char(7,20977).
+char(9,20978).
+char(m,20979).
+char(o,20980).
+char(m,20981).
+char(o,20982).
+char(m,20983).
+char(8,20984).
+char(4,20985).
+char(1,20986).
+char(6,20987).
+char(c,20988).
+char(c,20989).
+char(p,20990).
+char(9,20991).
+char(2,20992).
+char(2,20993).
+char(0,20994).
+char(c,20995).
+char(c,20996).
+char(p,20997).
+char(o,20998).
+char(p,20999).
+char(o,21000).
+char(5,21001).
+char(6,21002).
+char(3,21003).
+char(0,21004).
+char(m,21005).
+char(o,21006).
+char(m,21007).
+char(7,21008).
+char(9,21009).
+char(1,21010).
+char(7,21011).
+char(p,21012).
+char(o,21013).
+char(p,21014).
+char(9,21015).
+char(4,21016).
+char(8,21017).
+char(3,21018).
+char(c,21019).
+char(p,21020).
+char(o,21021).
+char(p,21022).
+char(7,21023).
+char(1,21024).
+char(3,21025).
+char(8,21026).
+char(m,21027).
+char(2,21028).
+char(5,21029).
+char(5,21030).
+char(m,21031).
+char(8,21032).
+char(6,21033).
+char(4,21034).
+char(8,21035).
+char(m,21036).
+char(8,21037).
+char(6,21038).
+char(9,21039).
+char(5,21040).
+char(m,21041).
+char(o,21042).
+char(m,21043).
+char(o,21044).
+char(m,21045).
+char(o,21046).
+char(m,21047).
+char(3,21048).
+char(9,21049).
+char(1,21050).
+char(2,21051).
+char(m,21052).
+char(2,21053).
+char(4,21054).
+char(m,21055).
+char(o,21056).
+char(m,21057).
+char(1,21058).
+char(6,21059).
+char(2,21060).
+char(4,21061).
+char(m,21062).
+char(9,21063).
+char(0,21064).
+char(9,21065).
+char(8,21066).
+char(p,21067).
+char(o,21068).
+char(p,21069).
+char(o,21070).
+char(o,21071).
+char(3,21072).
+char(1,21073).
+char(1,21074).
+char(8,21075).
+char(c,21076).
+char(p,21077).
+char(5,21078).
+char(6,21079).
+char(4,21080).
+char(4,21081).
+char(c,21082).
+char(c,21083).
+char(c,21084).
+char(c,21085).
+char(m,21086).
+char(o,21087).
+char(m,21088).
+char(o,21089).
+char(p,21090).
+char(o,21091).
+char(p,21092).
+char(2,21093).
+char(8,21094).
+char(7,21095).
+char(0,21096).
+char(m,21097).
+char(6,21098).
+char(4,21099).
+char(1,21100).
+char(1,21101).
+char(p,21102).
+char(9,21103).
+char(7,21104).
+char(2,21105).
+char(3,21106).
+char(c,21107).
+char(c,21108).
+char(c,21109).
+char(m,21110).
+char(o,21111).
+char(m,21112).
+char(o,21113).
+char(m,21114).
+char(5,21115).
+char(3,21116).
+char(0,21117).
+char(4,21118).
+char(c,21119).
+char(p,21120).
+char(8,21121).
+char(3,21122).
+char(3,21123).
+char(8,21124).
+char(m,21125).
+char(2,21126).
+char(4,21127).
+char(6,21128).
+char(2,21129).
+char(m,21130).
+char(6,21131).
+char(7,21132).
+char(8,21133).
+char(8,21134).
+char(p,21135).
+char(2,21136).
+char(9,21137).
+char(8,21138).
+char(5,21139).
+char(c,21140).
+char(c,21141).
+char(c,21142).
+char(p,21143).
+char(4,21144).
+char(9,21145).
+char(2,21146).
+char(3,21147).
+char(c,21148).
+char(c,21149).
+char(c,21150).
+char(c,21151).
+char(c,21152).
+char(m,21153).
+char(o,21154).
+char(o,21155).
+char(4,21156).
+char(8,21157).
+char(7,21158).
+char(1,21159).
+char(p,21160).
+char(o,21161).
+char(p,21162).
+char(7,21163).
+char(4,21164).
+char(1,21165).
+char(6,21166).
+char(c,21167).
+char(c,21168).
+char(c,21169).
+char(c,21170).
+char(c,21171).
+char(c,21172).
+char(p,21173).
+char(o,21174).
+char(m,21175).
+char(9,21176).
+char(7,21177).
+char(8,21178).
+char(1,21179).
+char(p,21180).
+char(3,21181).
+char(1,21182).
+char(1,21183).
+char(2,21184).
+char(m,21185).
+char(o,21186).
+char(o,21187).
+char(m,21188).
+char(o,21189).
+char(5,21190).
+char(6,21191).
+char(7,21192).
+char(5,21193).
+char(c,21194).
+char(c,21195).
+char(m,21196).
+char(o,21197).
+char(p,21198).
+char(5,21199).
+char(9,21200).
+char(5,21201).
+char(c,21202).
+char(c,21203).
+char(p,21204).
+char(8,21205).
+char(2,21206).
+char(2,21207).
+char(p,21208).
+char(8,21209).
+char(9,21210).
+char(4,21211).
+char(9,21212).
+char(m,21213).
+char(5,21214).
+char(0,21215).
+char(9,21216).
+char(8,21217).
+char(c,21218).
+char(m,21219).
+char(o,21220).
+char(p,21221).
+char(6,21222).
+char(4,21223).
+char(6,21224).
+char(5,21225).
+char(m,21226).
+char(1,21227).
+char(5,21228).
+char(0,21229).
+char(3,21230).
+char(c,21231).
+char(p,21232).
+char(2,21233).
+char(1,21234).
+char(0,21235).
+char(4,21236).
+char(p,21237).
+char(6,21238).
+char(1,21239).
+char(9,21240).
+char(4,21241).
+char(m,21242).
+char(8,21243).
+char(2,21244).
+char(1,21245).
+char(8,21246).
+char(c,21247).
+char(c,21248).
+char(m,21249).
+char(8,21250).
+char(6,21251).
+char(5,21252).
+char(6,21253).
+char(m,21254).
+char(8,21255).
+char(6,21256).
+char(9,21257).
+char(3,21258).
+char(c,21259).
+char(m,21260).
+char(o,21261).
+char(p,21262).
+char(8,21263).
+char(0,21264).
+char(7,21265).
+char(4,21266).
+char(m,21267).
+char(o,21268).
+char(3,21269).
+char(4,21270).
+char(5,21271).
+char(1,21272).
+char(c,21273).
+char(p,21274).
+char(o,21275).
+char(p,21276).
+char(o,21277).
+char(m,21278).
+char(o,21279).
+char(m,21280).
+char(8,21281).
+char(5,21282).
+char(9,21283).
+char(2,21284).
+char(p,21285).
+char(6,21286).
+char(3,21287).
+char(8,21288).
+char(6,21289).
+char(c,21290).
+char(c,21291).
+char(p,21292).
+char(o,21293).
+char(p,21294).
+char(o,21295).
+char(m,21296).
+char(o,21297).
+char(1,21298).
+char(9,21299).
+char(9,21300).
+char(7,21301).
+char(c,21302).
+char(m,21303).
+char(5,21304).
+char(1,21305).
+char(5,21306).
+char(4,21307).
+char(p,21308).
+char(8,21309).
+char(4,21310).
+char(6,21311).
+char(1,21312).
+char(c,21313).
+char(c,21314).
+char(c,21315).
+char(m,21316).
+char(8,21317).
+char(2,21318).
+char(8,21319).
+char(p,21320).
+char(8,21321).
+char(0,21322).
+char(9,21323).
+char(7,21324).
+char(m,21325).
+char(o,21326).
+char(o,21327).
+char(o,21328).
+char(m,21329).
+char(o,21330).
+char(p,21331).
+char(o,21332).
+char(p,21333).
+char(o,21334).
+char(o,21335).
+char(o,21336).
+char(o,21337).
+char(9,21338).
+char(9,21339).
+char(6,21340).
+char(1,21341).
+char(c,21342).
+char(p,21343).
+char(o,21344).
+char(p,21345).
+char(o,21346).
+char(p,21347).
+char(2,21348).
+char(1,21349).
+char(4,21350).
+char(9,21351).
+char(c,21352).
+char(p,21353).
+char(o,21354).
+char(m,21355).
+char(o,21356).
+char(o,21357).
+char(m,21358).
+char(8,21359).
+char(6,21360).
+char(8,21361).
+char(3,21362).
+char(c,21363).
+char(c,21364).
+char(p,21365).
+char(o,21366).
+char(m,21367).
+char(o,21368).
+char(m,21369).
+char(2,21370).
+char(6,21371).
+char(8,21372).
+char(0,21373).
+char(c,21374).
+char(m,21375).
+char(2,21376).
+char(0,21377).
+char(1,21378).
+char(1,21379).
+char(c,21380).
+char(c,21381).
+char(m,21382).
+char(o,21383).
+char(m,21384).
+char(7,21385).
+char(1,21386).
+char(5,21387).
+char(6,21388).
+char(c,21389).
+char(p,21390).
+char(o,21391).
+char(o,21392).
+char(o,21393).
+char(p,21394).
+char(o,21395).
+char(6,21396).
+char(7,21397).
+char(5,21398).
+char(1,21399).
+char(c,21400).
+char(c,21401).
+char(p,21402).
+char(o,21403).
+char(o,21404).
+char(p,21405).
+char(o,21406).
+char(p,21407).
+char(o,21408).
+char(p,21409).
+char(o,21410).
+char(m,21411).
+char(o,21412).
+char(p,21413).
+char(9,21414).
+char(7,21415).
+char(9,21416).
+char(2,21417).
+char(c,21418).
+char(c,21419).
+char(p,21420).
+char(2,21421).
+char(9,21422).
+char(1,21423).
+char(9,21424).
+char(c,21425).
+char(p,21426).
+char(o,21427).
+char(m,21428).
+char(o,21429).
+char(p,21430).
+char(o,21431).
+char(m,21432).
+char(o,21433).
+char(3,21434).
+char(4,21435).
+char(6,21436).
+char(4,21437).
+char(p,21438).
+char(o,21439).
+char(m,21440).
+char(o,21441).
+char(7,21442).
+char(1,21443).
+char(6,21444).
+char(3,21445).
+char(c,21446).
+char(m,21447).
+char(8,21448).
+char(3,21449).
+char(7,21450).
+char(3,21451).
+char(p,21452).
+char(o,21453).
+char(p,21454).
+char(9,21455).
+char(5,21456).
+char(7,21457).
+char(7,21458).
+char(p,21459).
+char(9,21460).
+char(1,21461).
+char(4,21462).
+char(p,21463).
+char(o,21464).
+char(o,21465).
+char(6,21466).
+char(9,21467).
+char(2,21468).
+char(2,21469).
+char(m,21470).
+char(o,21471).
+char(o,21472).
+char(p,21473).
+char(5,21474).
+char(1,21475).
+char(1,21476).
+char(4,21477).
+char(p,21478).
+char(7,21479).
+char(5,21480).
+char(0,21481).
+char(4,21482).
+char(m,21483).
+char(o,21484).
+char(o,21485).
+char(5,21486).
+char(7,21487).
+char(9,21488).
+char(m,21489).
+char(o,21490).
+char(p,21491).
+char(5,21492).
+char(4,21493).
+char(9,21494).
+char(c,21495).
+char(c,21496).
+char(p,21497).
+char(9,21498).
+char(6,21499).
+char(1,21500).
+char(6,21501).
+char(p,21502).
+char(4,21503).
+char(1,21504).
+char(2,21505).
+char(5,21506).
+char(p,21507).
+char(1,21508).
+char(2,21509).
+char(2,21510).
+char(6,21511).
+char(m,21512).
+char(8,21513).
+char(2,21514).
+char(2,21515).
+char(6,21516).
+char(c,21517).
+char(c,21518).
+char(c,21519).
+char(p,21520).
+char(2,21521).
+char(4,21522).
+char(0,21523).
+char(0,21524).
+char(m,21525).
+char(6,21526).
+char(6,21527).
+char(8,21528).
+char(6,21529).
+char(m,21530).
+char(7,21531).
+char(8,21532).
+char(0,21533).
+char(5,21534).
+char(p,21535).
+char(o,21536).
+char(m,21537).
+char(o,21538).
+char(p,21539).
+char(3,21540).
+char(2,21541).
+char(9,21542).
+char(9,21543).
+char(p,21544).
+char(3,21545).
+char(5,21546).
+char(9,21547).
+char(5,21548).
+char(c,21549).
+char(c,21550).
+char(c,21551).
+char(p,21552).
+char(7,21553).
+char(0,21554).
+char(9,21555).
+char(8,21556).
+char(c,21557).
+char(c,21558).
+char(c,21559).
+char(c,21560).
+char(p,21561).
+char(o,21562).
+char(m,21563).
+char(o,21564).
+char(p,21565).
+char(o,21566).
+char(4,21567).
+char(2,21568).
+char(4,21569).
+char(8,21570).
+char(p,21571).
+char(8,21572).
+char(4,21573).
+char(2,21574).
+char(3,21575).
+char(p,21576).
+char(o,21577).
+char(m,21578).
+char(o,21579).
+char(o,21580).
+char(p,21581).
+char(o,21582).
+char(m,21583).
+char(4,21584).
+char(9,21585).
+char(5,21586).
+char(2,21587).
+char(c,21588).
+char(c,21589).
+char(c,21590).
+char(c,21591).
+char(p,21592).
+char(o,21593).
+char(p,21594).
+char(o,21595).
+char(o,21596).
+char(m,21597).
+char(o,21598).
+char(p,21599).
+char(o,21600).
+char(m,21601).
+char(o,21602).
+char(1,21603).
+char(5,21604).
+char(5,21605).
+char(4,21606).
+char(p,21607).
+char(1,21608).
+char(0,21609).
+char(4,21610).
+char(8,21611).
+char(p,21612).
+char(4,21613).
+char(2,21614).
+char(1,21615).
+char(c,21616).
+char(m,21617).
+char(o,21618).
+char(o,21619).
+char(o,21620).
+char(p,21621).
+char(4,21622).
+char(8,21623).
+char(9,21624).
+char(4,21625).
+char(c,21626).
+char(c,21627).
+char(c,21628).
+char(p,21629).
+char(o,21630).
+char(m,21631).
+char(o,21632).
+char(o,21633).
+char(1,21634).
+char(6,21635).
+char(7,21636).
+char(4,21637).
+char(p,21638).
+char(5,21639).
+char(7,21640).
+char(4,21641).
+char(5,21642).
+char(p,21643).
+char(o,21644).
+char(o,21645).
+char(1,21646).
+char(6,21647).
+char(7,21648).
+char(8,21649).
+char(c,21650).
+char(c,21651).
+char(p,21652).
+char(o,21653).
+char(m,21654).
+char(8,21655).
+char(2,21656).
+char(6,21657).
+char(1,21658).
+char(m,21659).
+char(o,21660).
+char(m,21661).
+char(o,21662).
+char(m,21663).
+char(o,21664).
+char(o,21665).
+char(m,21666).
+char(o,21667).
+char(m,21668).
+char(o,21669).
+char(m,21670).
+char(o,21671).
+char(4,21672).
+char(6,21673).
+char(4,21674).
+char(3,21675).
+char(m,21676).
+char(o,21677).
+char(o,21678).
+char(1,21679).
+char(1,21680).
+char(7,21681).
+char(4,21682).
+char(p,21683).
+char(3,21684).
+char(3,21685).
+char(4,21686).
+char(1,21687).
+char(c,21688).
+char(p,21689).
+char(o,21690).
+char(m,21691).
+char(8,21692).
+char(3,21693).
+char(0,21694).
+char(p,21695).
+char(o,21696).
+char(m,21697).
+char(4,21698).
+char(6,21699).
+char(2,21700).
+char(5,21701).
+char(c,21702).
+char(c,21703).
+char(m,21704).
+char(o,21705).
+char(m,21706).
+char(4,21707).
+char(8,21708).
+char(7,21709).
+char(2,21710).
+char(c,21711).
+char(m,21712).
+char(5,21713).
+char(8,21714).
+char(6,21715).
+char(3,21716).
+char(c,21717).
+char(m,21718).
+char(o,21719).
+char(p,21720).
+char(o,21721).
+char(p,21722).
+char(7,21723).
+char(3,21724).
+char(4,21725).
+char(5,21726).
+char(m,21727).
+char(o,21728).
+char(m,21729).
+char(6,21730).
+char(6,21731).
+char(6,21732).
+char(7,21733).
+char(c,21734).
+char(m,21735).
+char(9,21736).
+char(5,21737).
+char(8,21738).
+char(6,21739).
+char(m,21740).
+char(6,21741).
+char(0,21742).
+char(8,21743).
+char(3,21744).
+char(m,21745).
+char(o,21746).
+char(p,21747).
+char(o,21748).
+char(o,21749).
+char(m,21750).
+char(8,21751).
+char(5,21752).
+char(5,21753).
+char(0,21754).
+char(m,21755).
+char(3,21756).
+char(8,21757).
+char(8,21758).
+char(p,21759).
+char(o,21760).
+char(m,21761).
+char(o,21762).
+char(o,21763).
+char(8,21764).
+char(2,21765).
+char(1,21766).
+char(6,21767).
+char(m,21768).
+char(o,21769).
+char(6,21770).
+char(1,21771).
+char(6,21772).
+char(5,21773).
+char(c,21774).
+char(c,21775).
+char(c,21776).
+char(p,21777).
+char(2,21778).
+char(4,21779).
+char(7,21780).
+char(8,21781).
+char(c,21782).
+char(m,21783).
+char(2,21784).
+char(4,21785).
+char(1,21786).
+char(3,21787).
+char(m,21788).
+char(o,21789).
+char(p,21790).
+char(o,21791).
+char(p,21792).
+char(9,21793).
+char(4,21794).
+char(5,21795).
+char(0,21796).
+char(c,21797).
+char(m,21798).
+char(9,21799).
+char(2,21800).
+char(5,21801).
+char(1,21802).
+char(m,21803).
+char(o,21804).
+char(m,21805).
+char(o,21806).
+char(p,21807).
+char(o,21808).
+char(6,21809).
+char(7,21810).
+char(5,21811).
+char(p,21812).
+char(o,21813).
+char(m,21814).
+char(o,21815).
+char(m,21816).
+char(5,21817).
+char(6,21818).
+char(5,21819).
+char(3,21820).
+char(c,21821).
+char(c,21822).
+char(c,21823).
+char(m,21824).
+char(7,21825).
+char(1,21826).
+char(0,21827).
+char(2,21828).
+char(c,21829).
+char(c,21830).
+char(p,21831).
+char(o,21832).
+char(p,21833).
+char(6,21834).
+char(0,21835).
+char(5,21836).
+char(6,21837).
+char(m,21838).
+char(2,21839).
+char(8,21840).
+char(6,21841).
+char(3,21842).
+char(c,21843).
+char(p,21844).
+char(9,21845).
+char(4,21846).
+char(9,21847).
+char(1,21848).
+char(c,21849).
+char(p,21850).
+char(o,21851).
+char(p,21852).
+char(1,21853).
+char(9,21854).
+char(3,21855).
+char(0,21856).
+char(m,21857).
+char(8,21858).
+char(7,21859).
+char(1,21860).
+char(0,21861).
+char(c,21862).
+char(p,21863).
+char(2,21864).
+char(5,21865).
+char(4,21866).
+char(4,21867).
+char(c,21868).
+char(p,21869).
+char(o,21870).
+char(p,21871).
+char(o,21872).
+char(m,21873).
+char(6,21874).
+char(1,21875).
+char(3,21876).
+char(9,21877).
+char(m,21878).
+char(o,21879).
+char(9,21880).
+char(2,21881).
+char(5,21882).
+char(4,21883).
+char(c,21884).
+char(c,21885).
+char(c,21886).
+char(c,21887).
+char(c,21888).
+char(c,21889).
+char(c,21890).
+char(p,21891).
+char(o,21892).
+char(p,21893).
+char(1,21894).
+char(1,21895).
+char(0,21896).
+char(4,21897).
+char(p,21898).
+char(1,21899).
+char(4,21900).
+char(9,21901).
+char(9,21902).
+char(m,21903).
+char(7,21904).
+char(6,21905).
+char(7,21906).
+char(2,21907).
+char(p,21908).
+char(o,21909).
+char(o,21910).
+char(p,21911).
+char(9,21912).
+char(3,21913).
+char(6,21914).
+char(5,21915).
+char(c,21916).
+char(c,21917).
+char(c,21918).
+char(c,21919).
+char(c,21920).
+char(p,21921).
+char(o,21922).
+char(m,21923).
+char(o,21924).
+char(3,21925).
+char(3,21926).
+char(4,21927).
+char(c,21928).
+char(c,21929).
+char(c,21930).
+char(p,21931).
+char(9,21932).
+char(6,21933).
+char(6,21934).
+char(8,21935).
+char(c,21936).
+char(c,21937).
+char(p,21938).
+char(o,21939).
+char(o,21940).
+char(o,21941).
+char(o,21942).
+char(m,21943).
+char(6,21944).
+char(8,21945).
+char(1,21946).
+char(9,21947).
+char(c,21948).
+char(c,21949).
+char(m,21950).
+char(o,21951).
+char(m,21952).
+char(o,21953).
+char(p,21954).
+char(3,21955).
+char(7,21956).
+char(2,21957).
+char(9,21958).
+char(m,21959).
+char(o,21960).
+char(p,21961).
+char(o,21962).
+char(m,21963).
+char(o,21964).
+char(5,21965).
+char(7,21966).
+char(5,21967).
+char(3,21968).
+char(c,21969).
+char(p,21970).
+char(3,21971).
+char(0,21972).
+char(6,21973).
+char(1,21974).
+char(p,21975).
+char(3,21976).
+char(7,21977).
+char(2,21978).
+char(3,21979).
+char(c,21980).
+char(p,21981).
+char(o,21982).
+char(m,21983).
+char(o,21984).
+char(p,21985).
+char(o,21986).
+char(m,21987).
+char(o,21988).
+char(m,21989).
+char(o,21990).
+char(p,21991).
+char(8,21992).
+char(3,21993).
+char(5,21994).
+char(c,21995).
+char(c,21996).
+char(m,21997).
+char(o,21998).
+char(p,21999).
+char(8,22000).
+char(9,22001).
+char(9,22002).
+char(3,22003).
+char(m,22004).
+char(6,22005).
+char(6,22006).
+char(6,22007).
+char(6,22008).
+char(c,22009).
+char(m,22010).
+char(o,22011).
+char(p,22012).
+char(o,22013).
+char(m,22014).
+char(o,22015).
+char(m,22016).
+char(o,22017).
+char(1,22018).
+char(5,22019).
+char(8,22020).
+char(3,22021).
+char(m,22022).
+char(o,22023).
+char(2,22024).
+char(7,22025).
+char(5,22026).
+char(1,22027).
+char(c,22028).
+char(c,22029).
+char(m,22030).
+char(4,22031).
+char(7,22032).
+char(0,22033).
+char(9,22034).
+char(m,22035).
+char(6,22036).
+char(0,22037).
+char(5,22038).
+char(7,22039).
+char(c,22040).
+char(p,22041).
+char(6,22042).
+char(8,22043).
+char(2,22044).
+char(c,22045).
+char(c,22046).
+char(c,22047).
+char(m,22048).
+char(o,22049).
+char(m,22050).
+char(o,22051).
+char(7,22052).
+char(1,22053).
+char(4,22054).
+char(4,22055).
+char(c,22056).
+char(m,22057).
+char(o,22058).
+char(p,22059).
+char(o,22060).
+char(p,22061).
+char(o,22062).
+char(o,22063).
+char(p,22064).
+char(o,22065).
+char(m,22066).
+char(o,22067).
+char(m,22068).
+char(o,22069).
+char(m,22070).
+char(3,22071).
+char(5,22072).
+char(2,22073).
+char(0,22074).
+char(c,22075).
+char(m,22076).
+char(4,22077).
+char(6,22078).
+char(4,22079).
+char(6,22080).
+char(m,22081).
+char(2,22082).
+char(7,22083).
+char(4,22084).
+char(2,22085).
+char(m,22086).
+char(o,22087).
+char(p,22088).
+char(8,22089).
+char(4,22090).
+char(8,22091).
+char(6,22092).
+char(m,22093).
+char(o,22094).
+char(1,22095).
+char(3,22096).
+char(1,22097).
+char(5,22098).
+char(c,22099).
+char(m,22100).
+char(o,22101).
+char(m,22102).
+char(o,22103).
+char(m,22104).
+char(8,22105).
+char(0,22106).
+char(0,22107).
+char(0,22108).
+char(c,22109).
+char(c,22110).
+char(c,22111).
+char(p,22112).
+char(5,22113).
+char(3,22114).
+char(4,22115).
+char(9,22116).
+char(c,22117).
+char(m,22118).
+char(3,22119).
+char(9,22120).
+char(6,22121).
+char(9,22122).
+char(p,22123).
+char(9,22124).
+char(7,22125).
+char(8,22126).
+char(0,22127).
+char(p,22128).
+char(o,22129).
+char(p,22130).
+char(o,22131).
+char(o,22132).
+char(o,22133).
+char(p,22134).
+char(o,22135).
+char(o,22136).
+char(p,22137).
+char(o,22138).
+char(7,22139).
+char(7,22140).
+char(0,22141).
+char(2,22142).
+char(c,22143).
+char(m,22144).
+char(o,22145).
+char(m,22146).
+char(4,22147).
+char(9,22148).
+char(8,22149).
+char(6,22150).
+char(m,22151).
+char(8,22152).
+char(4,22153).
+char(1,22154).
+char(m,22155).
+char(8,22156).
+char(5,22157).
+char(0,22158).
+char(5,22159).
+char(c,22160).
+char(m,22161).
+char(o,22162).
+char(1,22163).
+char(5,22164).
+char(8,22165).
+char(9,22166).
+char(c,22167).
+char(m,22168).
+char(6,22169).
+char(5,22170).
+char(0,22171).
+char(8,22172).
+char(c,22173).
+char(c,22174).
+char(c,22175).
+char(p,22176).
+char(o,22177).
+char(m,22178).
+char(6,22179).
+char(3,22180).
+char(0,22181).
+char(8,22182).
+char(p,22183).
+char(o,22184).
+char(p,22185).
+char(3,22186).
+char(6,22187).
+char(9,22188).
+char(3,22189).
+char(m,22190).
+char(7,22191).
+char(5,22192).
+char(3,22193).
+char(4,22194).
+char(c,22195).
+char(c,22196).
+char(c,22197).
+char(c,22198).
+char(m,22199).
+char(7,22200).
+char(3,22201).
+char(9,22202).
+char(c,22203).
+char(p,22204).
+char(6,22205).
+char(4,22206).
+char(1,22207).
+char(1,22208).
+char(m,22209).
+char(8,22210).
+char(3,22211).
+char(2,22212).
+char(3,22213).
+char(p,22214).
+char(o,22215).
+char(3,22216).
+char(6,22217).
+char(4,22218).
+char(4,22219).
+char(m,22220).
+char(5,22221).
+char(4,22222).
+char(7,22223).
+char(4,22224).
+char(c,22225).
+char(c,22226).
+char(p,22227).
+char(o,22228).
+char(p,22229).
+char(3,22230).
+char(7,22231).
+char(5,22232).
+char(4,22233).
+char(m,22234).
+char(o,22235).
+char(3,22236).
+char(0,22237).
+char(6,22238).
+char(2,22239).
+char(m,22240).
+char(o,22241).
+char(p,22242).
+char(o,22243).
+char(p,22244).
+char(3,22245).
+char(2,22246).
+char(6,22247).
+char(1,22248).
+char(p,22249).
+char(3,22250).
+char(2,22251).
+char(8,22252).
+char(m,22253).
+char(o,22254).
+char(9,22255).
+char(6,22256).
+char(3,22257).
+char(8,22258).
+char(p,22259).
+char(o,22260).
+char(p,22261).
+char(5,22262).
+char(6,22263).
+char(8,22264).
+char(3,22265).
+char(c,22266).
+char(c,22267).
+char(c,22268).
+char(c,22269).
+char(p,22270).
+char(o,22271).
+char(p,22272).
+char(1,22273).
+char(7,22274).
+char(4,22275).
+char(6,22276).
+char(p,22277).
+char(o,22278).
+char(m,22279).
+char(o,22280).
+char(o,22281).
+char(m,22282).
+char(5,22283).
+char(8,22284).
+char(6,22285).
+char(2,22286).
+char(c,22287).
+char(c,22288).
+char(c,22289).
+char(p,22290).
+char(o,22291).
+char(4,22292).
+char(6,22293).
+char(c,22294).
+char(c,22295).
+char(m,22296).
+char(o,22297).
+char(o,22298).
+char(p,22299).
+char(o,22300).
+char(m,22301).
+char(1,22302).
+char(4,22303).
+char(7,22304).
+char(2,22305).
+char(m,22306).
+char(8,22307).
+char(6,22308).
+char(7,22309).
+char(c,22310).
+char(m,22311).
+char(6,22312).
+char(4,22313).
+char(7,22314).
+char(3,22315).
+char(c,22316).
+char(p,22317).
+char(1,22318).
+char(5,22319).
+char(6,22320).
+char(1,22321).
+char(c,22322).
+char(p,22323).
+char(o,22324).
+char(o,22325).
+char(4,22326).
+char(8,22327).
+char(7,22328).
+char(3,22329).
+char(p,22330).
+char(o,22331).
+char(m,22332).
+char(o,22333).
+char(m,22334).
+char(o,22335).
+char(o,22336).
+char(7,22337).
+char(1,22338).
+char(1,22339).
+char(m,22340).
+char(1,22341).
+char(1,22342).
+char(4,22343).
+char(4,22344).
+char(m,22345).
+char(o,22346).
+char(m,22347).
+char(2,22348).
+char(7,22349).
+char(3,22350).
+char(1,22351).
+char(c,22352).
+char(m,22353).
+char(o,22354).
+char(o,22355).
+char(p,22356).
+char(o,22357).
+char(m,22358).
+char(3,22359).
+char(1,22360).
+char(9,22361).
+char(9,22362).
+char(p,22363).
+char(o,22364).
+char(p,22365).
+char(o,22366).
+char(9,22367).
+char(0,22368).
+char(6,22369).
+char(5,22370).
+char(c,22371).
+char(c,22372).
+char(p,22373).
+char(7,22374).
+char(9,22375).
+char(3,22376).
+char(9,22377).
+char(c,22378).
+char(m,22379).
+char(o,22380).
+char(m,22381).
+char(o,22382).
+char(m,22383).
+char(o,22384).
+char(m,22385).
+char(o,22386).
+char(o,22387).
+char(o,22388).
+char(p,22389).
+char(7,22390).
+char(0,22391).
+char(8,22392).
+char(8,22393).
+char(c,22394).
+char(p,22395).
+char(o,22396).
+char(o,22397).
+char(m,22398).
+char(o,22399).
+char(8,22400).
+char(0,22401).
+char(9,22402).
+char(4,22403).
+char(c,22404).
+char(p,22405).
+char(4,22406).
+char(1,22407).
+char(1,22408).
+char(c,22409).
+char(c,22410).
+char(c,22411).
+char(p,22412).
+char(o,22413).
+char(m,22414).
+char(o,22415).
+char(p,22416).
+char(o,22417).
+char(p,22418).
+char(1,22419).
+char(1,22420).
+char(3,22421).
+char(7,22422).
+char(c,22423).
+char(c,22424).
+char(c,22425).
+char(m,22426).
+char(o,22427).
+char(5,22428).
+char(3,22429).
+char(7,22430).
+char(6,22431).
+char(p,22432).
+char(2,22433).
+char(5,22434).
+char(5,22435).
+char(1,22436).
+char(m,22437).
+char(o,22438).
+char(p,22439).
+char(5,22440).
+char(6,22441).
+char(2,22442).
+char(6,22443).
+char(c,22444).
+char(m,22445).
+char(6,22446).
+char(5,22447).
+char(7,22448).
+char(9,22449).
+char(p,22450).
+char(7,22451).
+char(1,22452).
+char(5,22453).
+char(3,22454).
+char(c,22455).
+char(c,22456).
+char(p,22457).
+char(o,22458).
+char(o,22459).
+char(o,22460).
+char(p,22461).
+char(o,22462).
+char(m,22463).
+char(7,22464).
+char(3,22465).
+char(3,22466).
+char(2,22467).
+char(c,22468).
+char(p,22469).
+char(o,22470).
+char(7,22471).
+char(9,22472).
+char(3,22473).
+char(6,22474).
+char(c,22475).
+char(c,22476).
+char(p,22477).
+char(o,22478).
+char(m,22479).
+char(o,22480).
+char(5,22481).
+char(6,22482).
+char(6,22483).
+char(1,22484).
+char(p,22485).
+char(2,22486).
+char(6,22487).
+char(9,22488).
+char(4,22489).
+char(c,22490).
+char(m,22491).
+char(o,22492).
+char(o,22493).
+char(p,22494).
+char(o,22495).
+char(1,22496).
+char(8,22497).
+char(2,22498).
+char(8,22499).
+char(p,22500).
+char(o,22501).
+char(o,22502).
+char(p,22503).
+char(3,22504).
+char(5,22505).
+char(5,22506).
+char(9,22507).
+char(c,22508).
+char(c,22509).
+char(m,22510).
+char(o,22511).
+char(m,22512).
+char(6,22513).
+char(9,22514).
+char(7,22515).
+char(4,22516).
+char(c,22517).
+char(c,22518).
+char(c,22519).
+char(m,22520).
+char(7,22521).
+char(6,22522).
+char(7,22523).
+char(c,22524).
+char(p,22525).
+char(o,22526).
+char(o,22527).
+char(m,22528).
+char(2,22529).
+char(3,22530).
+char(7,22531).
+char(6,22532).
+char(m,22533).
+char(2,22534).
+char(4,22535).
+char(5,22536).
+char(8,22537).
+char(m,22538).
+char(7,22539).
+char(4,22540).
+char(2,22541).
+char(0,22542).
+char(c,22543).
+char(m,22544).
+char(9,22545).
+char(5,22546).
+char(5,22547).
+char(3,22548).
+char(c,22549).
+char(c,22550).
+char(c,22551).
+char(c,22552).
+char(c,22553).
+char(c,22554).
+char(c,22555).
+char(p,22556).
+char(2,22557).
+char(3,22558).
+char(5,22559).
+char(1,22560).
+char(c,22561).
+char(m,22562).
+char(2,22563).
+char(5,22564).
+char(9,22565).
+char(p,22566).
+char(3,22567).
+char(2,22568).
+char(7,22569).
+char(4,22570).
+char(p,22571).
+char(o,22572).
+char(7,22573).
+char(4,22574).
+char(0,22575).
+char(p,22576).
+char(o,22577).
+char(m,22578).
+char(4,22579).
+char(0,22580).
+char(8,22581).
+char(6,22582).
+char(m,22583).
+char(o,22584).
+char(m,22585).
+char(6,22586).
+char(6,22587).
+char(6,22588).
+char(0,22589).
+char(c,22590).
+char(c,22591).
+char(m,22592).
+char(o,22593).
+char(4,22594).
+char(7,22595).
+char(8,22596).
+char(7,22597).
+char(m,22598).
+char(4,22599).
+char(4,22600).
+char(1,22601).
+char(2,22602).
+char(p,22603).
+char(5,22604).
+char(8,22605).
+char(2,22606).
+char(4,22607).
+char(c,22608).
+char(c,22609).
+char(p,22610).
+char(9,22611).
+char(7,22612).
+char(8,22613).
+char(m,22614).
+char(o,22615).
+char(m,22616).
+char(9,22617).
+char(1,22618).
+char(8,22619).
+char(1,22620).
+char(m,22621).
+char(9,22622).
+char(8,22623).
+char(9,22624).
+char(3,22625).
+char(p,22626).
+char(9,22627).
+char(3,22628).
+char(8,22629).
+char(7,22630).
+char(c,22631).
+char(c,22632).
+char(m,22633).
+char(9,22634).
+char(3,22635).
+char(1,22636).
+char(1,22637).
+char(c,22638).
+char(c,22639).
+char(m,22640).
+char(o,22641).
+char(p,22642).
+char(3,22643).
+char(9,22644).
+char(8,22645).
+char(4,22646).
+char(c,22647).
+char(c,22648).
+char(c,22649).
+char(c,22650).
+char(c,22651).
+char(c,22652).
+char(c,22653).
+char(p,22654).
+char(o,22655).
+char(1,22656).
+char(2,22657).
+char(0,22658).
+char(8,22659).
+char(m,22660).
+char(7,22661).
+char(5,22662).
+char(9,22663).
+char(m,22664).
+char(o,22665).
+char(m,22666).
+char(o,22667).
+char(m,22668).
+char(5,22669).
+char(1,22670).
+char(1,22671).
+char(3,22672).
+char(c,22673).
+char(c,22674).
+char(c,22675).
+char(p,22676).
+char(o,22677).
+char(p,22678).
+char(5,22679).
+char(2,22680).
+char(7,22681).
+char(9,22682).
+char(m,22683).
+char(2,22684).
+char(5,22685).
+char(c,22686).
+char(c,22687).
+char(m,22688).
+char(5,22689).
+char(7,22690).
+char(6,22691).
+char(4,22692).
+char(c,22693).
+char(p,22694).
+char(4,22695).
+char(1,22696).
+char(m,22697).
+char(o,22698).
+char(p,22699).
+char(4,22700).
+char(7,22701).
+char(9,22702).
+char(0,22703).
+char(c,22704).
+char(c,22705).
+char(m,22706).
+char(o,22707).
+char(p,22708).
+char(o,22709).
+char(p,22710).
+char(3,22711).
+char(5,22712).
+char(7,22713).
+char(8,22714).
+char(p,22715).
+char(5,22716).
+char(5,22717).
+char(1,22718).
+char(2,22719).
+char(m,22720).
+char(o,22721).
+char(p,22722).
+char(2,22723).
+char(1,22724).
+char(5,22725).
+char(6,22726).
+char(p,22727).
+char(2,22728).
+char(9,22729).
+char(9,22730).
+char(0,22731).
+char(c,22732).
+char(c,22733).
+char(p,22734).
+char(o,22735).
+char(o,22736).
+char(m,22737).
+char(7,22738).
+char(6,22739).
+char(2,22740).
+char(5,22741).
+char(m,22742).
+char(2,22743).
+char(5,22744).
+char(0,22745).
+char(5,22746).
+char(c,22747).
+char(c,22748).
+char(c,22749).
+char(m,22750).
+char(o,22751).
+char(o,22752).
+char(p,22753).
+char(o,22754).
+char(o,22755).
+char(m,22756).
+char(8,22757).
+char(2,22758).
+char(9,22759).
+char(4,22760).
+char(c,22761).
+char(c,22762).
+char(m,22763).
+char(o,22764).
+char(4,22765).
+char(6,22766).
+char(2,22767).
+char(6,22768).
+char(c,22769).
+char(p,22770).
+char(2,22771).
+char(8,22772).
+char(7,22773).
+char(2,22774).
+char(c,22775).
+char(c,22776).
+char(m,22777).
+char(4,22778).
+char(1,22779).
+char(5,22780).
+char(3,22781).
+char(p,22782).
+char(3,22783).
+char(6,22784).
+char(9,22785).
+char(0,22786).
+char(c,22787).
+char(m,22788).
+char(2,22789).
+char(9,22790).
+char(8,22791).
+char(0,22792).
+char(c,22793).
+char(c,22794).
+char(c,22795).
+char(c,22796).
+char(c,22797).
+char(m,22798).
+char(5,22799).
+char(2,22800).
+char(2,22801).
+char(2,22802).
+char(c,22803).
+char(p,22804).
+char(8,22805).
+char(9,22806).
+char(9,22807).
+char(c,22808).
+char(c,22809).
+char(m,22810).
+char(o,22811).
+char(p,22812).
+char(o,22813).
+char(m,22814).
+char(o,22815).
+char(m,22816).
+char(6,22817).
+char(6,22818).
+char(5,22819).
+char(1,22820).
+char(m,22821).
+char(7,22822).
+char(4,22823).
+char(4,22824).
+char(2,22825).
+char(c,22826).
+char(m,22827).
+char(1,22828).
+char(0,22829).
+char(1,22830).
+char(p,22831).
+char(7,22832).
+char(7,22833).
+char(2,22834).
+char(3,22835).
+char(c,22836).
+char(c,22837).
+char(p,22838).
+char(9,22839).
+char(6,22840).
+char(3,22841).
+char(2,22842).
+char(p,22843).
+char(2,22844).
+char(8,22845).
+char(4,22846).
+char(2,22847).
+char(m,22848).
+char(o,22849).
+char(o,22850).
+char(p,22851).
+char(1,22852).
+char(9,22853).
+char(1,22854).
+char(2,22855).
+char(c,22856).
+char(m,22857).
+char(o,22858).
+char(9,22859).
+char(3,22860).
+char(0,22861).
+char(m,22862).
+char(o,22863).
+char(p,22864).
+char(5,22865).
+char(0,22866).
+char(8,22867).
+char(4,22868).
+char(p,22869).
+char(5,22870).
+char(6,22871).
+char(4,22872).
+char(9,22873).
+char(m,22874).
+char(8,22875).
+char(7,22876).
+char(4,22877).
+char(0,22878).
+char(c,22879).
+char(m,22880).
+char(3,22881).
+char(5,22882).
+char(7,22883).
+char(3,22884).
+char(c,22885).
+char(c,22886).
+char(c,22887).
+char(m,22888).
+char(6,22889).
+char(7,22890).
+char(7,22891).
+char(1,22892).
+char(c,22893).
+char(c,22894).
+char(c,22895).
+char(p,22896).
+char(5,22897).
+char(4,22898).
+char(5,22899).
+char(5,22900).
+char(m,22901).
+char(o,22902).
+char(m,22903).
+char(o,22904).
+char(m,22905).
+char(o,22906).
+char(m,22907).
+char(9,22908).
+char(1,22909).
+char(7,22910).
+char(2,22911).
+char(p,22912).
+char(4,22913).
+char(9,22914).
+char(8,22915).
+char(9,22916).
+char(p,22917).
+char(6,22918).
+char(6,22919).
+char(8,22920).
+char(4,22921).
+char(c,22922).
+char(p,22923).
+char(8,22924).
+char(3,22925).
+char(0,22926).
+char(2,22927).
+char(p,22928).
+char(1,22929).
+char(3,22930).
+char(4,22931).
+char(6,22932).
+char(c,22933).
+char(c,22934).
+char(p,22935).
+char(o,22936).
+char(p,22937).
+char(o,22938).
+char(9,22939).
+char(3,22940).
+char(6,22941).
+char(3,22942).
+char(m,22943).
+char(2,22944).
+char(6,22945).
+char(8,22946).
+char(3,22947).
+char(c,22948).
+char(m,22949).
+char(o,22950).
+char(8,22951).
+char(5,22952).
+char(2,22953).
+char(6,22954).
+char(c,22955).
+char(p,22956).
+char(4,22957).
+char(6,22958).
+char(0,22959).
+char(9,22960).
+char(p,22961).
+char(o,22962).
+char(m,22963).
+char(o,22964).
+char(o,22965).
+char(p,22966).
+char(3,22967).
+char(4,22968).
+char(1,22969).
+char(4,22970).
+char(c,22971).
+char(p,22972).
+char(o,22973).
+char(1,22974).
+char(8,22975).
+char(3,22976).
+char(3,22977).
+char(c,22978).
+char(p,22979).
+char(9,22980).
+char(7,22981).
+char(1,22982).
+char(1,22983).
+char(m,22984).
+char(o,22985).
+char(p,22986).
+char(o,22987).
+char(m,22988).
+char(o,22989).
+char(p,22990).
+char(o,22991).
+char(9,22992).
+char(1,22993).
+char(7,22994).
+char(p,22995).
+char(2,22996).
+char(7,22997).
+char(8,22998).
+char(8,22999).
+char(c,23000).
+char(m,23001).
+char(o,23002).
+char(p,23003).
+char(o,23004).
+char(1,23005).
+char(6,23006).
+char(3,23007).
+char(2,23008).
+char(m,23009).
+char(o,23010).
+char(p,23011).
+char(5,23012).
+char(8,23013).
+char(1,23014).
+char(9,23015).
+char(p,23016).
+char(o,23017).
+char(m,23018).
+char(o,23019).
+char(7,23020).
+char(7,23021).
+char(7,23022).
+char(3,23023).
+char(m,23024).
+char(o,23025).
+char(m,23026).
+char(o,23027).
+char(o,23028).
+char(m,23029).
+char(9,23030).
+char(2,23031).
+char(1,23032).
+char(3,23033).
+char(p,23034).
+char(7,23035).
+char(4,23036).
+char(2,23037).
+char(9,23038).
+char(m,23039).
+char(o,23040).
+char(p,23041).
+char(2,23042).
+char(9,23043).
+char(6,23044).
+char(7,23045).
+char(m,23046).
+char(o,23047).
+char(o,23048).
+char(o,23049).
+char(p,23050).
+char(3,23051).
+char(4,23052).
+char(0,23053).
+char(0,23054).
+char(m,23055).
+char(3,23056).
+char(3,23057).
+char(5,23058).
+char(4,23059).
+char(c,23060).
+char(p,23061).
+char(o,23062).
+char(m,23063).
+char(8,23064).
+char(0,23065).
+char(8,23066).
+char(4,23067).
+char(c,23068).
+char(c,23069).
+char(m,23070).
+char(o,23071).
+char(7,23072).
+char(3,23073).
+char(2,23074).
+char(9,23075).
+char(c,23076).
+char(p,23077).
+char(o,23078).
+char(p,23079).
+char(1,23080).
+char(1,23081).
+char(8,23082).
+char(6,23083).
+char(p,23084).
+char(1,23085).
+char(3,23086).
+char(1,23087).
+char(2,23088).
+char(c,23089).
+char(p,23090).
+char(8,23091).
+char(7,23092).
+char(c,23093).
+char(p,23094).
+char(o,23095).
+char(p,23096).
+char(o,23097).
+char(m,23098).
+char(o,23099).
+char(m,23100).
+char(o,23101).
+char(p,23102).
+char(o,23103).
+char(6,23104).
+char(1,23105).
+char(9,23106).
+char(9,23107).
+char(c,23108).
+char(c,23109).
+char(p,23110).
+char(o,23111).
+char(p,23112).
+char(o,23113).
+char(m,23114).
+char(8,23115).
+char(6,23116).
+char(3,23117).
+char(3,23118).
+char(c,23119).
+char(m,23120).
+char(3,23121).
+char(9,23122).
+char(6,23123).
+char(c,23124).
+char(c,23125).
+char(c,23126).
+char(c,23127).
+char(m,23128).
+char(2,23129).
+char(1,23130).
+char(2,23131).
+char(5,23132).
+char(m,23133).
+char(4,23134).
+char(8,23135).
+char(5,23136).
+char(5,23137).
+char(p,23138).
+char(o,23139).
+char(p,23140).
+char(o,23141).
+char(3,23142).
+char(3,23143).
+char(1,23144).
+char(5,23145).
+char(p,23146).
+char(3,23147).
+char(9,23148).
+char(1,23149).
+char(1,23150).
+char(c,23151).
+char(c,23152).
+char(c,23153).
+char(m,23154).
+char(o,23155).
+char(p,23156).
+char(o,23157).
+char(o,23158).
+char(m,23159).
+char(o,23160).
+char(m,23161).
+char(7,23162).
+char(8,23163).
+char(8,23164).
+char(1,23165).
+char(p,23166).
+char(2,23167).
+char(4,23168).
+char(9,23169).
+char(0,23170).
+char(c,23171).
+char(p,23172).
+char(1,23173).
+char(2,23174).
+char(5,23175).
+char(p,23176).
+char(9,23177).
+char(7,23178).
+char(9,23179).
+char(7,23180).
+char(c,23181).
+char(p,23182).
+char(o,23183).
+char(p,23184).
+char(o,23185).
+char(o,23186).
+char(m,23187).
+char(o,23188).
+char(m,23189).
+char(7,23190).
+char(5,23191).
+char(4,23192).
+char(2,23193).
+char(c,23194).
+char(m,23195).
+char(o,23196).
+char(m,23197).
+char(o,23198).
+char(p,23199).
+char(o,23200).
+char(p,23201).
+char(6,23202).
+char(9,23203).
+char(1,23204).
+char(1,23205).
+char(c,23206).
+char(m,23207).
+char(o,23208).
+char(m,23209).
+char(9,23210).
+char(4,23211).
+char(8,23212).
+char(7,23213).
+char(p,23214).
+char(9,23215).
+char(9,23216).
+char(3,23217).
+char(5,23218).
+char(c,23219).
+char(c,23220).
+char(c,23221).
+char(p,23222).
+char(o,23223).
+char(p,23224).
+char(4,23225).
+char(4,23226).
+char(0,23227).
+char(9,23228).
+char(p,23229).
+char(o,23230).
+char(m,23231).
+char(o,23232).
+char(6,23233).
+char(5,23234).
+char(1,23235).
+char(6,23236).
+char(c,23237).
+char(m,23238).
+char(o,23239).
+char(6,23240).
+char(9,23241).
+char(6,23242).
+char(3,23243).
+char(c,23244).
+char(c,23245).
+char(p,23246).
+char(7,23247).
+char(8,23248).
+char(8,23249).
+char(6,23250).
+char(c,23251).
+char(c,23252).
+char(c,23253).
+char(m,23254).
+char(o,23255).
+char(m,23256).
+char(o,23257).
+char(p,23258).
+char(o,23259).
+char(p,23260).
+char(9,23261).
+char(3,23262).
+char(8,23263).
+char(c,23264).
+char(m,23265).
+char(o,23266).
+char(p,23267).
+char(o,23268).
+char(m,23269).
+char(o,23270).
+char(o,23271).
+char(p,23272).
+char(1,23273).
+char(4,23274).
+char(0,23275).
+char(0,23276).
+char(c,23277).
+char(c,23278).
+char(c,23279).
+char(m,23280).
+char(o,23281).
+char(3,23282).
+char(3,23283).
+char(7,23284).
+char(2,23285).
+char(p,23286).
+char(1,23287).
+char(6,23288).
+char(5,23289).
+char(5,23290).
+char(m,23291).
+char(8,23292).
+char(6,23293).
+char(6,23294).
+char(0,23295).
+char(m,23296).
+char(o,23297).
+char(p,23298).
+char(o,23299).
+char(m,23300).
+char(o,23301).
+char(3,23302).
+char(1,23303).
+char(4,23304).
+char(4,23305).
+char(p,23306).
+char(5,23307).
+char(8,23308).
+char(6,23309).
+char(4,23310).
+char(c,23311).
+char(m,23312).
+char(o,23313).
+char(m,23314).
+char(o,23315).
+char(5,23316).
+char(1,23317).
+char(1,23318).
+char(9,23319).
+char(c,23320).
+char(p,23321).
+char(o,23322).
+char(m,23323).
+char(o,23324).
+char(o,23325).
+char(m,23326).
+char(5,23327).
+char(9,23328).
+char(3,23329).
+char(0,23330).
+char(c,23331).
+char(p,23332).
+char(o,23333).
+char(o,23334).
+char(p,23335).
+char(4,23336).
+char(9,23337).
+char(5,23338).
+char(m,23339).
+char(o,23340).
+char(p,23341).
+char(o,23342).
+char(6,23343).
+char(6,23344).
+char(2,23345).
+char(6,23346).
+char(c,23347).
+char(m,23348).
+char(2,23349).
+char(3,23350).
+char(c,23351).
+char(m,23352).
+char(5,23353).
+char(8,23354).
+char(0,23355).
+char(3,23356).
+char(p,23357).
+char(o,23358).
+char(p,23359).
+char(o,23360).
+char(3,23361).
+char(8,23362).
+char(3,23363).
+char(7,23364).
+char(c,23365).
+char(m,23366).
+char(3,23367).
+char(7,23368).
+char(4,23369).
+char(3,23370).
+char(c,23371).
+char(m,23372).
+char(1,23373).
+char(4,23374).
+char(6,23375).
+char(7,23376).
+char(m,23377).
+char(o,23378).
+char(m,23379).
+char(o,23380).
+char(m,23381).
+char(o,23382).
+char(m,23383).
+char(o,23384).
+char(p,23385).
+char(o,23386).
+char(p,23387).
+char(5,23388).
+char(9,23389).
+char(3,23390).
+char(6,23391).
+char(m,23392).
+char(2,23393).
+char(6,23394).
+char(2,23395).
+char(6,23396).
+char(c,23397).
+char(c,23398).
+char(m,23399).
+char(7,23400).
+char(6,23401).
+char(9,23402).
+char(5,23403).
+char(c,23404).
+char(m,23405).
+char(3,23406).
+char(9,23407).
+char(1,23408).
+char(2,23409).
+char(p,23410).
+char(7,23411).
+char(6,23412).
+char(5,23413).
+char(8,23414).
+char(c,23415).
+char(c,23416).
+char(c,23417).
+char(c,23418).
+char(p,23419).
+char(8,23420).
+char(1,23421).
+char(3,23422).
+char(0,23423).
+char(c,23424).
+char(p,23425).
+char(o,23426).
+char(p,23427).
+char(o,23428).
+char(m,23429).
+char(o,23430).
+char(p,23431).
+char(o,23432).
+char(o,23433).
+char(1,23434).
+char(3,23435).
+char(7,23436).
+char(5,23437).
+char(c,23438).
+char(m,23439).
+char(6,23440).
+char(9,23441).
+char(8,23442).
+char(2,23443).
+char(c,23444).
+char(m,23445).
+char(o,23446).
+char(o,23447).
+char(p,23448).
+char(7,23449).
+char(1,23450).
+char(9,23451).
+char(3,23452).
+char(p,23453).
+char(o,23454).
+char(o,23455).
+char(p,23456).
+char(o,23457).
+char(p,23458).
+char(9,23459).
+char(3,23460).
+char(9,23461).
+char(2,23462).
+char(m,23463).
+char(o,23464).
+char(p,23465).
+char(8,23466).
+char(5,23467).
+char(0,23468).
+char(2,23469).
+char(m,23470).
+char(o,23471).
+char(p,23472).
+char(4,23473).
+char(8,23474).
+char(9,23475).
+char(8,23476).
+char(c,23477).
+char(c,23478).
+char(m,23479).
+char(1,23480).
+char(0,23481).
+char(3,23482).
+char(4,23483).
+char(p,23484).
+char(4,23485).
+char(0,23486).
+char(1,23487).
+char(c,23488).
+char(c,23489).
+char(p,23490).
+char(o,23491).
+char(p,23492).
+char(9,23493).
+char(7,23494).
+char(6,23495).
+char(5,23496).
+char(c,23497).
+char(c,23498).
+char(p,23499).
+char(9,23500).
+char(4,23501).
+char(0,23502).
+char(5,23503).
+char(m,23504).
+char(8,23505).
+char(6,23506).
+char(6,23507).
+char(1,23508).
+char(c,23509).
+char(c,23510).
+char(c,23511).
+char(c,23512).
+char(c,23513).
+char(m,23514).
+char(2,23515).
+char(2,23516).
+char(4,23517).
+char(m,23518).
+char(3,23519).
+char(8,23520).
+char(5,23521).
+char(4,23522).
+char(c,23523).
+char(p,23524).
+char(o,23525).
+char(p,23526).
+char(1,23527).
+char(3,23528).
+char(5,23529).
+char(1,23530).
+char(m,23531).
+char(o,23532).
+char(m,23533).
+char(o,23534).
+char(m,23535).
+char(2,23536).
+char(8,23537).
+char(4,23538).
+char(8,23539).
+char(c,23540).
+char(c,23541).
+char(c,23542).
+char(p,23543).
+char(4,23544).
+char(9,23545).
+char(7,23546).
+char(5,23547).
+char(c,23548).
+char(p,23549).
+char(o,23550).
+char(2,23551).
+char(7,23552).
+char(6,23553).
+char(9,23554).
+char(m,23555).
+char(o,23556).
+char(m,23557).
+char(5,23558).
+char(7,23559).
+char(1,23560).
+char(0,23561).
+char(m,23562).
+char(o,23563).
+char(m,23564).
+char(7,23565).
+char(3,23566).
+char(0,23567).
+char(7,23568).
+char(c,23569).
+char(c,23570).
+char(c,23571).
+char(c,23572).
+char(m,23573).
+char(2,23574).
+char(1,23575).
+char(7,23576).
+char(9,23577).
+char(m,23578).
+char(2,23579).
+char(5,23580).
+char(1,23581).
+char(8,23582).
+char(p,23583).
+char(9,23584).
+char(0,23585).
+char(0,23586).
+char(4,23587).
+char(p,23588).
+char(o,23589).
+char(m,23590).
+char(o,23591).
+char(7,23592).
+char(7,23593).
+char(7,23594).
+char(1,23595).
+char(c,23596).
+char(c,23597).
+char(p,23598).
+char(8,23599).
+char(5,23600).
+char(7,23601).
+char(7,23602).
+char(c,23603).
+char(m,23604).
+char(5,23605).
+char(8,23606).
+char(2,23607).
+char(8,23608).
+char(p,23609).
+char(8,23610).
+char(2,23611).
+char(7,23612).
+char(p,23613).
+char(o,23614).
+char(o,23615).
+char(m,23616).
+char(5,23617).
+char(7,23618).
+char(6,23619).
+char(3,23620).
+char(c,23621).
+char(p,23622).
+char(o,23623).
+char(m,23624).
+char(1,23625).
+char(0,23626).
+char(7,23627).
+char(1,23628).
+char(m,23629).
+char(o,23630).
+char(m,23631).
+char(7,23632).
+char(6,23633).
+char(8,23634).
+char(p,23635).
+char(o,23636).
+char(p,23637).
+char(o,23638).
+char(p,23639).
+char(o,23640).
+char(m,23641).
+char(o,23642).
+char(m,23643).
+char(o,23644).
+char(m,23645).
+char(5,23646).
+char(1,23647).
+char(9,23648).
+char(2,23649).
+char(m,23650).
+char(o,23651).
+char(3,23652).
+char(9,23653).
+char(7,23654).
+char(9,23655).
+char(p,23656).
+char(o,23657).
+char(p,23658).
+char(o,23659).
+char(7,23660).
+char(3,23661).
+char(4,23662).
+char(9,23663).
+char(c,23664).
+char(c,23665).
+char(p,23666).
+char(o,23667).
+char(p,23668).
+char(o,23669).
+char(m,23670).
+char(6,23671).
+char(5,23672).
+char(6,23673).
+char(7,23674).
+char(p,23675).
+char(o,23676).
+char(p,23677).
+char(3,23678).
+char(9,23679).
+char(0,23680).
+char(2,23681).
+char(m,23682).
+char(7,23683).
+char(5,23684).
+char(2,23685).
+char(3,23686).
+char(c,23687).
+char(p,23688).
+char(o,23689).
+char(7,23690).
+char(0,23691).
+char(1,23692).
+char(m,23693).
+char(1,23694).
+char(1,23695).
+char(4,23696).
+char(0,23697).
+char(p,23698).
+char(o,23699).
+char(o,23700).
+char(o,23701).
+char(3,23702).
+char(0,23703).
+char(6,23704).
+char(3,23705).
+char(p,23706).
+char(o,23707).
+char(o,23708).
+char(o,23709).
+char(m,23710).
+char(4,23711).
+char(4,23712).
+char(6,23713).
+char(6,23714).
+char(c,23715).
+char(c,23716).
+char(c,23717).
+char(c,23718).
+char(m,23719).
+char(o,23720).
+char(m,23721).
+char(o,23722).
+char(m,23723).
+char(o,23724).
+char(m,23725).
+char(o,23726).
+char(3,23727).
+char(0,23728).
+char(9,23729).
+char(5,23730).
+char(m,23731).
+char(o,23732).
+char(m,23733).
+char(2,23734).
+char(3,23735).
+char(6,23736).
+char(8,23737).
+char(c,23738).
+char(p,23739).
+char(o,23740).
+char(m,23741).
+char(o,23742).
+char(o,23743).
+char(p,23744).
+char(o,23745).
+char(p,23746).
+char(o,23747).
+char(m,23748).
+char(2,23749).
+char(6,23750).
+char(3,23751).
+char(8,23752).
+char(p,23753).
+char(o,23754).
+char(m,23755).
+char(9,23756).
+char(1,23757).
+char(5,23758).
+char(6,23759).
+char(m,23760).
+char(o,23761).
+char(p,23762).
+char(9,23763).
+char(7,23764).
+char(9,23765).
+char(7,23766).
+char(p,23767).
+char(o,23768).
+char(m,23769).
+char(o,23770).
+char(1,23771).
+char(8,23772).
+char(4,23773).
+char(9,23774).
+char(p,23775).
+char(o,23776).
+char(p,23777).
+char(2,23778).
+char(6,23779).
+char(2,23780).
+char(7,23781).
+char(c,23782).
+char(c,23783).
+char(c,23784).
+char(p,23785).
+char(o,23786).
+char(o,23787).
+char(6,23788).
+char(8,23789).
+char(4,23790).
+char(p,23791).
+char(o,23792).
+char(p,23793).
+char(o,23794).
+char(o,23795).
+char(p,23796).
+char(3,23797).
+char(3,23798).
+char(9,23799).
+char(7,23800).
+char(c,23801).
+char(c,23802).
+char(c,23803).
+char(c,23804).
+char(c,23805).
+char(p,23806).
+char(9,23807).
+char(8,23808).
+char(1,23809).
+char(0,23810).
+char(p,23811).
+char(5,23812).
+char(3,23813).
+char(1,23814).
+char(3,23815).
+char(m,23816).
+char(o,23817).
+char(p,23818).
+char(o,23819).
+char(4,23820).
+char(3,23821).
+char(0,23822).
+char(9,23823).
+char(c,23824).
+char(c,23825).
+char(m,23826).
+char(9,23827).
+char(3,23828).
+char(9,23829).
+char(0,23830).
+char(m,23831).
+char(o,23832).
+char(m,23833).
+char(o,23834).
+char(p,23835).
+char(8,23836).
+char(0,23837).
+char(9,23838).
+char(0,23839).
+char(p,23840).
+char(8,23841).
+char(3,23842).
+char(7,23843).
+char(5,23844).
+char(c,23845).
+char(p,23846).
+char(6,23847).
+char(2,23848).
+char(2,23849).
+char(4,23850).
+char(p,23851).
+char(o,23852).
+char(m,23853).
+char(o,23854).
+char(p,23855).
+char(4,23856).
+char(4,23857).
+char(3,23858).
+char(8,23859).
+char(c,23860).
+char(p,23861).
+char(6,23862).
+char(2,23863).
+char(4,23864).
+char(6,23865).
+char(c,23866).
+char(p,23867).
+char(2,23868).
+char(5,23869).
+char(1,23870).
+char(3,23871).
+char(c,23872).
+char(p,23873).
+char(o,23874).
+char(o,23875).
+char(o,23876).
+char(4,23877).
+char(5,23878).
+char(2,23879).
+char(7,23880).
+char(c,23881).
+char(p,23882).
+char(o,23883).
+char(2,23884).
+char(2,23885).
+char(1,23886).
+char(3,23887).
+char(c,23888).
+char(c,23889).
+char(m,23890).
+char(6,23891).
+char(6,23892).
+char(6,23893).
+char(2,23894).
+char(p,23895).
+char(6,23896).
+char(7,23897).
+char(7,23898).
+char(5,23899).
+char(m,23900).
+char(o,23901).
+char(4,23902).
+char(4,23903).
+char(9,23904).
+char(7,23905).
+char(m,23906).
+char(6,23907).
+char(9,23908).
+char(7,23909).
+char(5,23910).
+char(c,23911).
+char(c,23912).
+char(p,23913).
+char(o,23914).
+char(p,23915).
+char(o,23916).
+char(m,23917).
+char(5,23918).
+char(8,23919).
+char(4,23920).
+char(1,23921).
+char(p,23922).
+char(7,23923).
+char(1,23924).
+char(c,23925).
+char(p,23926).
+char(5,23927).
+char(5,23928).
+char(6,23929).
+char(3,23930).
+char(c,23931).
+char(p,23932).
+char(o,23933).
+char(m,23934).
+char(9,23935).
+char(4,23936).
+char(9,23937).
+char(1,23938).
+char(m,23939).
+char(o,23940).
+char(o,23941).
+char(2,23942).
+char(9,23943).
+char(5,23944).
+char(7,23945).
+char(p,23946).
+char(o,23947).
+char(m,23948).
+char(o,23949).
+char(3,23950).
+char(7,23951).
+char(0,23952).
+char(3,23953).
+char(c,23954).
+char(c,23955).
+char(m,23956).
+char(9,23957).
+char(9,23958).
+char(0,23959).
+char(7,23960).
+char(c,23961).
+char(m,23962).
+char(8,23963).
+char(5,23964).
+char(2,23965).
+char(p,23966).
+char(o,23967).
+char(p,23968).
+char(1,23969).
+char(1,23970).
+char(1,23971).
+char(9,23972).
+char(p,23973).
+char(o,23974).
+char(p,23975).
+char(o,23976).
+char(m,23977).
+char(o,23978).
+char(m,23979).
+char(o,23980).
+char(p,23981).
+char(o,23982).
+char(m,23983).
+char(9,23984).
+char(8,23985).
+char(8,23986).
+char(2,23987).
+char(p,23988).
+char(9,23989).
+char(6,23990).
+char(1,23991).
+char(1,23992).
+char(m,23993).
+char(o,23994).
+char(p,23995).
+char(o,23996).
+char(o,23997).
+char(m,23998).
+char(o,23999).
+char(o,24000).
+char(m,24001).
+char(o,24002).
+char(o,24003).
+char(m,24004).
+char(5,24005).
+char(1,24006).
+char(0,24007).
+char(6,24008).
+char(p,24009).
+char(o,24010).
+char(3,24011).
+char(6,24012).
+char(7,24013).
+char(2,24014).
+char(m,24015).
+char(o,24016).
+char(m,24017).
+char(o,24018).
+char(p,24019).
+char(6,24020).
+char(0,24021).
+char(0,24022).
+char(3,24023).
+char(m,24024).
+char(o,24025).
+char(o,24026).
+char(8,24027).
+char(9,24028).
+char(0,24029).
+char(c,24030).
+char(m,24031).
+char(o,24032).
+char(p,24033).
+char(o,24034).
+char(m,24035).
+char(o,24036).
+char(p,24037).
+char(o,24038).
+char(p,24039).
+char(5,24040).
+char(9,24041).
+char(5,24042).
+char(4,24043).
+char(c,24044).
+char(p,24045).
+char(5,24046).
+char(7,24047).
+char(7,24048).
+char(0,24049).
+char(m,24050).
+char(o,24051).
+char(o,24052).
+char(m,24053).
+char(2,24054).
+char(9,24055).
+char(1,24056).
+char(2,24057).
+char(c,24058).
+char(c,24059).
+char(c,24060).
+char(c,24061).
+char(p,24062).
+char(o,24063).
+char(m,24064).
+char(2,24065).
+char(0,24066).
+char(8,24067).
+char(1,24068).
+char(m,24069).
+char(9,24070).
+char(0,24071).
+char(6,24072).
+char(6,24073).
+char(c,24074).
+char(c,24075).
+char(p,24076).
+char(2,24077).
+char(4,24078).
+char(7,24079).
+char(4,24080).
+char(m,24081).
+char(o,24082).
+char(p,24083).
+char(6,24084).
+char(0,24085).
+char(0,24086).
+char(5,24087).
+char(c,24088).
+char(p,24089).
+char(4,24090).
+char(0,24091).
+char(0,24092).
+char(7,24093).
+char(c,24094).
+char(c,24095).
+char(m,24096).
+char(o,24097).
+char(o,24098).
+char(m,24099).
+char(7,24100).
+char(2,24101).
+char(4,24102).
+char(7,24103).
+char(c,24104).
+char(c,24105).
+char(p,24106).
+char(1,24107).
+char(0,24108).
+char(0,24109).
+char(0,24110).
+char(p,24111).
+char(4,24112).
+char(3,24113).
+char(4,24114).
+char(2,24115).
+char(c,24116).
+char(c,24117).
+char(m,24118).
+char(1,24119).
+char(9,24120).
+char(6,24121).
+char(0,24122).
+char(m,24123).
+char(o,24124).
+char(p,24125).
+char(5,24126).
+char(8,24127).
+char(9,24128).
+char(6,24129).
+char(c,24130).
+char(c,24131).
+char(c,24132).
+char(c,24133).
+char(c,24134).
+char(c,24135).
+char(c,24136).
+char(p,24137).
+char(o,24138).
+char(3,24139).
+char(0,24140).
+char(7,24141).
+char(9,24142).
+char(c,24143).
+char(c,24144).
+char(c,24145).
+char(p,24146).
+char(4,24147).
+char(5,24148).
+char(5,24149).
+char(6,24150).
+char(p,24151).
+char(o,24152).
+char(9,24153).
+char(2,24154).
+char(3,24155).
+char(4,24156).
+char(c,24157).
+char(p,24158).
+char(o,24159).
+char(o,24160).
+char(m,24161).
+char(o,24162).
+char(9,24163).
+char(0,24164).
+char(2,24165).
+char(4,24166).
+char(p,24167).
+char(8,24168).
+char(0,24169).
+char(9,24170).
+char(2,24171).
+char(c,24172).
+char(c,24173).
+char(m,24174).
+char(o,24175).
+char(o,24176).
+char(p,24177).
+char(o,24178).
+char(p,24179).
+char(5,24180).
+char(1,24181).
+char(3,24182).
+char(6,24183).
+char(m,24184).
+char(1,24185).
+char(3,24186).
+char(6,24187).
+char(7,24188).
+char(c,24189).
+char(m,24190).
+char(9,24191).
+char(0,24192).
+char(8,24193).
+char(5,24194).
+char(c,24195).
+char(c,24196).
+char(c,24197).
+char(m,24198).
+char(o,24199).
+char(p,24200).
+char(o,24201).
+char(m,24202).
+char(5,24203).
+char(4,24204).
+char(6,24205).
+char(4,24206).
+char(c,24207).
+char(c,24208).
+char(c,24209).
+char(c,24210).
+char(c,24211).
+char(c,24212).
+char(c,24213).
+char(c,24214).
+char(p,24215).
+char(o,24216).
+char(p,24217).
+char(o,24218).
+char(7,24219).
+char(6,24220).
+char(9,24221).
+char(4,24222).
+char(m,24223).
+char(o,24224).
+char(p,24225).
+char(o,24226).
+char(4,24227).
+char(9,24228).
+char(4,24229).
+char(1,24230).
+char(c,24231).
+char(m,24232).
+char(o,24233).
+char(o,24234).
+char(p,24235).
+char(5,24236).
+char(5,24237).
+char(0,24238).
+char(1,24239).
+char(c,24240).
+char(p,24241).
+char(o,24242).
+char(p,24243).
+char(6,24244).
+char(7,24245).
+char(3,24246).
+char(4,24247).
+char(m,24248).
+char(3,24249).
+char(2,24250).
+char(7,24251).
+char(5,24252).
+char(m,24253).
+char(o,24254).
+char(m,24255).
+char(o,24256).
+char(p,24257).
+char(o,24258).
+char(m,24259).
+char(o,24260).
+char(p,24261).
+char(8,24262).
+char(4,24263).
+char(6,24264).
+char(0,24265).
+char(c,24266).
+char(m,24267).
+char(o,24268).
+char(o,24269).
+char(o,24270).
+char(m,24271).
+char(o,24272).
+char(p,24273).
+char(o,24274).
+char(o,24275).
+char(m,24276).
+char(o,24277).
+char(m,24278).
+char(9,24279).
+char(3,24280).
+char(8,24281).
+char(c,24282).
+char(c,24283).
+char(c,24284).
+char(c,24285).
+char(m,24286).
+char(5,24287).
+char(9,24288).
+char(9,24289).
+char(7,24290).
+char(m,24291).
+char(o,24292).
+char(m,24293).
+char(6,24294).
+char(3,24295).
+char(2,24296).
+char(6,24297).
+char(m,24298).
+char(o,24299).
+char(8,24300).
+char(9,24301).
+char(2,24302).
+char(8,24303).
+char(c,24304).
+char(c,24305).
+char(p,24306).
+char(o,24307).
+char(o,24308).
+char(m,24309).
+char(o,24310).
+char(m,24311).
+char(o,24312).
+char(o,24313).
+char(m,24314).
+char(o,24315).
+char(1,24316).
+char(6,24317).
+char(4,24318).
+char(3,24319).
+char(c,24320).
+char(m,24321).
+char(o,24322).
+char(o,24323).
+char(8,24324).
+char(0,24325).
+char(4,24326).
+char(6,24327).
+char(p,24328).
+char(5,24329).
+char(7,24330).
+char(0,24331).
+char(9,24332).
+char(c,24333).
+char(c,24334).
+char(c,24335).
+char(c,24336).
+char(m,24337).
+char(o,24338).
+char(o,24339).
+char(m,24340).
+char(8,24341).
+char(7,24342).
+char(2,24343).
+char(4,24344).
+char(p,24345).
+char(6,24346).
+char(0,24347).
+char(0,24348).
+char(5,24349).
+char(m,24350).
+char(2,24351).
+char(5,24352).
+char(3,24353).
+char(1,24354).
+char(c,24355).
+char(m,24356).
+char(2,24357).
+char(3,24358).
+char(1,24359).
+char(5,24360).
+char(c,24361).
+char(m,24362).
+char(1,24363).
+char(0,24364).
+char(5,24365).
+char(4,24366).
+char(c,24367).
+char(m,24368).
+char(7,24369).
+char(5,24370).
+char(2,24371).
+char(2,24372).
+char(p,24373).
+char(8,24374).
+char(3,24375).
+char(7,24376).
+char(6,24377).
+char(m,24378).
+char(o,24379).
+char(6,24380).
+char(6,24381).
+char(4,24382).
+char(2,24383).
+char(c,24384).
+char(c,24385).
+char(c,24386).
+char(m,24387).
+char(8,24388).
+char(4,24389).
+char(0,24390).
+char(5,24391).
+char(p,24392).
+char(8,24393).
+char(9,24394).
+char(2,24395).
+char(9,24396).
+char(c,24397).
+char(m,24398).
+char(o,24399).
+char(o,24400).
+char(o,24401).
+char(o,24402).
+char(o,24403).
+char(m,24404).
+char(4,24405).
+char(6,24406).
+char(3,24407).
+char(5,24408).
+char(m,24409).
+char(o,24410).
+char(m,24411).
+char(3,24412).
+char(3,24413).
+char(4,24414).
+char(4,24415).
+char(c,24416).
+char(m,24417).
+char(7,24418).
+char(3,24419).
+char(1,24420).
+char(3,24421).
+char(p,24422).
+char(o,24423).
+char(m,24424).
+char(o,24425).
+char(p,24426).
+char(o,24427).
+char(o,24428).
+char(7,24429).
+char(6,24430).
+char(6,24431).
+char(9,24432).
+char(c,24433).
+char(m,24434).
+char(o,24435).
+char(p,24436).
+char(o,24437).
+char(p,24438).
+char(o,24439).
+char(o,24440).
+char(m,24441).
+char(2,24442).
+char(0,24443).
+char(7,24444).
+char(8,24445).
+char(c,24446).
+char(p,24447).
+char(o,24448).
+char(m,24449).
+char(o,24450).
+char(p,24451).
+char(2,24452).
+char(8,24453).
+char(2,24454).
+char(1,24455).
+char(c,24456).
+char(p,24457).
+char(1,24458).
+char(1,24459).
+char(7,24460).
+char(5,24461).
+char(c,24462).
+char(c,24463).
+char(c,24464).
+char(c,24465).
+char(m,24466).
+char(2,24467).
+char(9,24468).
+char(3,24469).
+char(2,24470).
+char(p,24471).
+char(o,24472).
+char(p,24473).
+char(o,24474).
+char(o,24475).
+char(p,24476).
+char(9,24477).
+char(9,24478).
+char(0,24479).
+char(5,24480).
+char(c,24481).
+char(c,24482).
+char(p,24483).
+char(5,24484).
+char(4,24485).
+char(5,24486).
+char(c,24487).
+char(c,24488).
+char(p,24489).
+char(o,24490).
+char(p,24491).
+char(o,24492).
+char(m,24493).
+char(o,24494).
+char(m,24495).
+char(o,24496).
+char(o,24497).
+char(6,24498).
+char(5,24499).
+char(2,24500).
+char(2,24501).
+char(m,24502).
+char(3,24503).
+char(9,24504).
+char(4,24505).
+char(4,24506).
+char(p,24507).
+char(4,24508).
+char(1,24509).
+char(7,24510).
+char(7,24511).
+char(m,24512).
+char(o,24513).
+char(p,24514).
+char(6,24515).
+char(5,24516).
+char(5,24517).
+char(8,24518).
+char(m,24519).
+char(6,24520).
+char(9,24521).
+char(0,24522).
+char(c,24523).
+char(p,24524).
+char(o,24525).
+char(o,24526).
+char(p,24527).
+char(8,24528).
+char(3,24529).
+char(8,24530).
+char(3,24531).
+char(m,24532).
+char(3,24533).
+char(1,24534).
+char(8,24535).
+char(7,24536).
+char(c,24537).
+char(p,24538).
+char(o,24539).
+char(m,24540).
+char(o,24541).
+char(o,24542).
+char(6,24543).
+char(8,24544).
+char(2,24545).
+char(1,24546).
+char(p,24547).
+char(5,24548).
+char(5,24549).
+char(5,24550).
+char(7,24551).
+char(c,24552).
+char(c,24553).
+char(p,24554).
+char(o,24555).
+char(2,24556).
+char(9,24557).
+char(0,24558).
+char(0,24559).
+char(m,24560).
+char(1,24561).
+char(7,24562).
+char(0,24563).
+char(3,24564).
+char(c,24565).
+char(c,24566).
+char(c,24567).
+char(c,24568).
+char(c,24569).
+char(c,24570).
+char(c,24571).
+char(c,24572).
+char(c,24573).
+char(p,24574).
+char(7,24575).
+char(4,24576).
+char(9,24577).
+char(6,24578).
+char(m,24579).
+char(7,24580).
+char(2,24581).
+char(8,24582).
+char(3,24583).
+char(m,24584).
+char(5,24585).
+char(7,24586).
+char(0,24587).
+char(5,24588).
+char(m,24589).
+char(o,24590).
+char(m,24591).
+char(o,24592).
+char(p,24593).
+char(o,24594).
+char(m,24595).
+char(3,24596).
+char(9,24597).
+char(4,24598).
+char(2,24599).
+char(c,24600).
+char(p,24601).
+char(1,24602).
+char(4,24603).
+char(4,24604).
+char(3,24605).
+char(c,24606).
+char(c,24607).
+char(c,24608).
+char(p,24609).
+char(o,24610).
+char(p,24611).
+char(o,24612).
+char(5,24613).
+char(8,24614).
+char(5,24615).
+char(1,24616).
+char(m,24617).
+char(o,24618).
+char(p,24619).
+char(4,24620).
+char(8,24621).
+char(1,24622).
+char(6,24623).
+char(m,24624).
+char(o,24625).
+char(p,24626).
+char(4,24627).
+char(7,24628).
+char(9,24629).
+char(4,24630).
+char(m,24631).
+char(4,24632).
+char(1,24633).
+char(0,24634).
+char(5,24635).
+char(c,24636).
+char(p,24637).
+char(9,24638).
+char(4,24639).
+char(8,24640).
+char(6,24641).
+char(m,24642).
+char(o,24643).
+char(o,24644).
+char(7,24645).
+char(0,24646).
+char(2,24647).
+char(0,24648).
+char(m,24649).
+char(8,24650).
+char(2,24651).
+char(1,24652).
+char(2,24653).
+char(m,24654).
+char(9,24655).
+char(7,24656).
+char(0,24657).
+char(9,24658).
+char(m,24659).
+char(3,24660).
+char(6,24661).
+char(1,24662).
+char(4,24663).
+char(m,24664).
+char(o,24665).
+char(o,24666).
+char(o,24667).
+char(m,24668).
+char(3,24669).
+char(2,24670).
+char(4,24671).
+char(4,24672).
+char(m,24673).
+char(1,24674).
+char(8,24675).
+char(3,24676).
+char(2,24677).
+char(m,24678).
+char(o,24679).
+char(m,24680).
+char(9,24681).
+char(1,24682).
+char(7,24683).
+char(8,24684).
+char(c,24685).
+char(p,24686).
+char(6,24687).
+char(2,24688).
+char(5,24689).
+char(7,24690).
+char(m,24691).
+char(7,24692).
+char(7,24693).
+char(9,24694).
+char(5,24695).
+char(c,24696).
+char(p,24697).
+char(9,24698).
+char(7,24699).
+char(1,24700).
+char(5,24701).
+char(c,24702).
+char(c,24703).
+char(p,24704).
+char(8,24705).
+char(1,24706).
+char(2,24707).
+char(2,24708).
+char(p,24709).
+char(2,24710).
+char(7,24711).
+char(5,24712).
+char(1,24713).
+char(p,24714).
+char(7,24715).
+char(6,24716).
+char(9,24717).
+char(0,24718).
+char(m,24719).
+char(o,24720).
+char(p,24721).
+char(o,24722).
+char(p,24723).
+char(o,24724).
+char(o,24725).
+char(m,24726).
+char(5,24727).
+char(3,24728).
+char(3,24729).
+char(9,24730).
+char(c,24731).
+char(c,24732).
+char(p,24733).
+char(o,24734).
+char(o,24735).
+char(m,24736).
+char(2,24737).
+char(0,24738).
+char(5,24739).
+char(7,24740).
+char(c,24741).
+char(c,24742).
+char(p,24743).
+char(7,24744).
+char(6,24745).
+char(7,24746).
+char(9,24747).
+char(m,24748).
+char(4,24749).
+char(7,24750).
+char(3,24751).
+char(6,24752).
+char(p,24753).
+char(o,24754).
+char(m,24755).
+char(o,24756).
+char(m,24757).
+char(o,24758).
+char(8,24759).
+char(1,24760).
+char(6,24761).
+char(4,24762).
+char(p,24763).
+char(o,24764).
+char(p,24765).
+char(2,24766).
+char(5,24767).
+char(6,24768).
+char(4,24769).
+char(c,24770).
+char(m,24771).
+char(1,24772).
+char(3,24773).
+char(3,24774).
+char(5,24775).
+char(c,24776).
+char(p,24777).
+char(o,24778).
+char(6,24779).
+char(0,24780).
+char(2,24781).
+char(0,24782).
+char(p,24783).
+char(o,24784).
+char(4,24785).
+char(2,24786).
+char(0,24787).
+char(7,24788).
+char(c,24789).
+char(p,24790).
+char(6,24791).
+char(8,24792).
+char(5,24793).
+char(9,24794).
+char(c,24795).
+char(p,24796).
+char(o,24797).
+char(p,24798).
+char(o,24799).
+char(p,24800).
+char(o,24801).
+char(p,24802).
+char(3,24803).
+char(7,24804).
+char(0,24805).
+char(6,24806).
+char(c,24807).
+char(m,24808).
+char(6,24809).
+char(6,24810).
+char(7,24811).
+char(2,24812).
+char(c,24813).
+char(m,24814).
+char(o,24815).
+char(o,24816).
+char(m,24817).
+char(3,24818).
+char(5,24819).
+char(8,24820).
+char(7,24821).
+char(p,24822).
+char(4,24823).
+char(5,24824).
+char(0,24825).
+char(0,24826).
+char(m,24827).
+char(o,24828).
+char(2,24829).
+char(2,24830).
+char(7,24831).
+char(4,24832).
+char(p,24833).
+char(6,24834).
+char(4,24835).
+char(5,24836).
+char(0,24837).
+char(c,24838).
+char(m,24839).
+char(o,24840).
+char(m,24841).
+char(1,24842).
+char(5,24843).
+char(1,24844).
+char(6,24845).
+char(p,24846).
+char(o,24847).
+char(p,24848).
+char(o,24849).
+char(4,24850).
+char(5,24851).
+char(1,24852).
+char(5,24853).
+char(p,24854).
+char(o,24855).
+char(p,24856).
+char(o,24857).
+char(p,24858).
+char(3,24859).
+char(1,24860).
+char(8,24861).
+char(9,24862).
+char(m,24863).
+char(3,24864).
+char(5,24865).
+char(2,24866).
+char(p,24867).
+char(o,24868).
+char(m,24869).
+char(7,24870).
+char(1,24871).
+char(7,24872).
+char(0,24873).
+char(p,24874).
+char(7,24875).
+char(4,24876).
+char(0,24877).
+char(0,24878).
+char(c,24879).
+char(c,24880).
+char(m,24881).
+char(o,24882).
+char(1,24883).
+char(0,24884).
+char(2,24885).
+char(0,24886).
+char(p,24887).
+char(8,24888).
+char(6,24889).
+char(6,24890).
+char(3,24891).
+char(c,24892).
+char(p,24893).
+char(o,24894).
+char(p,24895).
+char(o,24896).
+char(3,24897).
+char(9,24898).
+char(1,24899).
+char(3,24900).
+char(p,24901).
+char(8,24902).
+char(2,24903).
+char(6,24904).
+char(8,24905).
+char(c,24906).
+char(p,24907).
+char(1,24908).
+char(4,24909).
+char(9,24910).
+char(7,24911).
+char(c,24912).
+char(p,24913).
+char(o,24914).
+char(o,24915).
+char(o,24916).
+char(p,24917).
+char(6,24918).
+char(2,24919).
+char(3,24920).
+char(c,24921).
+char(m,24922).
+char(2,24923).
+char(2,24924).
+char(7,24925).
+char(5,24926).
+char(c,24927).
+char(c,24928).
+char(c,24929).
+char(m,24930).
+char(o,24931).
+char(5,24932).
+char(9,24933).
+char(6,24934).
+char(4,24935).
+char(c,24936).
+char(c,24937).
+char(m,24938).
+char(6,24939).
+char(0,24940).
+char(7,24941).
+char(c,24942).
+char(m,24943).
+char(6,24944).
+char(3,24945).
+char(8,24946).
+char(0,24947).
+char(c,24948).
+char(m,24949).
+char(6,24950).
+char(1,24951).
+char(7,24952).
+char(3,24953).
+char(c,24954).
+char(p,24955).
+char(o,24956).
+char(p,24957).
+char(7,24958).
+char(3,24959).
+char(3,24960).
+char(0,24961).
+char(c,24962).
+char(p,24963).
+char(4,24964).
+char(4,24965).
+char(3,24966).
+char(9,24967).
+char(m,24968).
+char(2,24969).
+char(8,24970).
+char(9,24971).
+char(9,24972).
+char(m,24973).
+char(o,24974).
+char(p,24975).
+char(o,24976).
+char(2,24977).
+char(4,24978).
+char(6,24979).
+char(1,24980).
+char(c,24981).
+char(c,24982).
+char(p,24983).
+char(2,24984).
+char(5,24985).
+char(0,24986).
+char(0,24987).
+char(c,24988).
+char(p,24989).
+char(o,24990).
+char(o,24991).
+char(o,24992).
+char(m,24993).
+char(o,24994).
+char(m,24995).
+char(3,24996).
+char(3,24997).
+char(1,24998).
+char(8,24999).
+char(c,25000).
+char(p,25001).
+char(2,25002).
+char(7,25003).
+char(2,25004).
+char(5,25005).
+char(p,25006).
+char(o,25007).
+char(o,25008).
+char(p,25009).
+char(o,25010).
+char(p,25011).
+char(3,25012).
+char(6,25013).
+char(1,25014).
+char(5,25015).
+char(c,25016).
+char(m,25017).
+char(7,25018).
+char(1,25019).
+char(7,25020).
+char(c,25021).
+char(c,25022).
+char(c,25023).
+char(p,25024).
+char(2,25025).
+char(2,25026).
+char(5,25027).
+char(7,25028).
+char(m,25029).
+char(7,25030).
+char(7,25031).
+char(5,25032).
+char(5,25033).
+char(m,25034).
+char(o,25035).
+char(p,25036).
+char(5,25037).
+char(6,25038).
+char(1,25039).
+char(c,25040).
+char(c,25041).
+char(c,25042).
+char(m,25043).
+char(1,25044).
+char(3,25045).
+char(2,25046).
+char(4,25047).
+char(p,25048).
+char(7,25049).
+char(0,25050).
+char(6,25051).
+char(4,25052).
+char(p,25053).
+char(o,25054).
+char(4,25055).
+char(2,25056).
+char(0,25057).
+char(9,25058).
+char(c,25059).
+char(c,25060).
+char(c,25061).
+char(c,25062).
+char(c,25063).
+char(c,25064).
+char(c,25065).
+char(c,25066).
+char(c,25067).
+char(m,25068).
+char(o,25069).
+char(o,25070).
+char(m,25071).
+char(o,25072).
+char(p,25073).
+char(o,25074).
+char(4,25075).
+char(9,25076).
+char(8,25077).
+char(5,25078).
+char(p,25079).
+char(5,25080).
+char(4,25081).
+char(6,25082).
+char(1,25083).
+char(m,25084).
+char(o,25085).
+char(6,25086).
+char(7,25087).
+char(0,25088).
+char(2,25089).
+char(p,25090).
+char(2,25091).
+char(2,25092).
+char(8,25093).
+char(2,25094).
+char(p,25095).
+char(o,25096).
+char(o,25097).
+char(p,25098).
+char(1,25099).
+char(6,25100).
+char(9,25101).
+char(0,25102).
+char(c,25103).
+char(m,25104).
+char(9,25105).
+char(5,25106).
+char(0,25107).
+char(2,25108).
+char(c,25109).
+char(c,25110).
+char(c,25111).
+char(c,25112).
+char(p,25113).
+char(o,25114).
+char(m,25115).
+char(3,25116).
+char(2,25117).
+char(3,25118).
+char(4,25119).
+char(m,25120).
+char(o,25121).
+char(p,25122).
+char(o,25123).
+char(o,25124).
+char(m,25125).
+char(5,25126).
+char(8,25127).
+char(8,25128).
+char(7,25129).
+char(c,25130).
+char(c,25131).
+char(c,25132).
+char(c,25133).
+char(c,25134).
+char(m,25135).
+char(6,25136).
+char(1,25137).
+char(6,25138).
+char(0,25139).
+char(m,25140).
+char(4,25141).
+char(4,25142).
+char(7,25143).
+char(2,25144).
+char(c,25145).
+char(c,25146).
+char(c,25147).
+char(c,25148).
+char(p,25149).
+char(o,25150).
+char(p,25151).
+char(o,25152).
+char(p,25153).
+char(3,25154).
+char(0,25155).
+char(8,25156).
+char(7,25157).
+char(m,25158).
+char(9,25159).
+char(1,25160).
+char(5,25161).
+char(9,25162).
+char(p,25163).
+char(o,25164).
+char(p,25165).
+char(o,25166).
+char(1,25167).
+char(9,25168).
+char(9,25169).
+char(0,25170).
+char(c,25171).
+char(c,25172).
+char(c,25173).
+char(m,25174).
+char(8,25175).
+char(4,25176).
+char(8,25177).
+char(0,25178).
+char(p,25179).
+char(o,25180).
+char(m,25181).
+char(o,25182).
+char(o,25183).
+char(m,25184).
+char(o,25185).
+char(m,25186).
+char(o,25187).
+char(p,25188).
+char(4,25189).
+char(6,25190).
+char(7,25191).
+char(0,25192).
+char(m,25193).
+char(o,25194).
+char(6,25195).
+char(9,25196).
+char(0,25197).
+char(6,25198).
+char(c,25199).
+char(m,25200).
+char(o,25201).
+char(o,25202).
+char(o,25203).
+char(p,25204).
+char(4,25205).
+char(0,25206).
+char(7,25207).
+char(c,25208).
+char(p,25209).
+char(8,25210).
+char(4,25211).
+char(5,25212).
+char(c,25213).
+char(c,25214).
+char(c,25215).
+char(p,25216).
+char(o,25217).
+char(m,25218).
+char(9,25219).
+char(9,25220).
+char(5,25221).
+char(2,25222).
+char(p,25223).
+char(8,25224).
+char(3,25225).
+char(3,25226).
+char(4,25227).
+char(c,25228).
+char(p,25229).
+char(9,25230).
+char(4,25231).
+char(4,25232).
+char(p,25233).
+char(4,25234).
+char(7,25235).
+char(2,25236).
+char(6,25237).
+char(m,25238).
+char(o,25239).
+char(4,25240).
+char(8,25241).
+char(6,25242).
+char(9,25243).
+char(m,25244).
+char(2,25245).
+char(9,25246).
+char(8,25247).
+char(9,25248).
+char(p,25249).
+char(o,25250).
+char(o,25251).
+char(p,25252).
+char(o,25253).
+char(p,25254).
+char(2,25255).
+char(0,25256).
+char(7,25257).
+char(1,25258).
+char(c,25259).
+char(c,25260).
+char(c,25261).
+char(c,25262).
+char(m,25263).
+char(o,25264).
+char(m,25265).
+char(3,25266).
+char(1,25267).
+char(2,25268).
+char(0,25269).
+char(c,25270).
+char(m,25271).
+char(o,25272).
+char(5,25273).
+char(0,25274).
+char(1,25275).
+char(5,25276).
+char(c,25277).
+char(m,25278).
+char(o,25279).
+char(o,25280).
+char(o,25281).
+char(m,25282).
+char(o,25283).
+char(m,25284).
+char(3,25285).
+char(1,25286).
+char(4,25287).
+char(8,25288).
+char(c,25289).
+char(c,25290).
+char(c,25291).
+char(c,25292).
+char(p,25293).
+char(o,25294).
+char(o,25295).
+char(m,25296).
+char(o,25297).
+char(p,25298).
+char(o,25299).
+char(6,25300).
+char(5,25301).
+char(3,25302).
+char(8,25303).
+char(c,25304).
+char(c,25305).
+char(c,25306).
+char(c,25307).
+char(p,25308).
+char(o,25309).
+char(m,25310).
+char(o,25311).
+char(o,25312).
+char(m,25313).
+char(1,25314).
+char(6,25315).
+char(0,25316).
+char(p,25317).
+char(2,25318).
+char(1,25319).
+char(6,25320).
+char(7,25321).
+char(p,25322).
+char(2,25323).
+char(8,25324).
+char(7,25325).
+char(m,25326).
+char(o,25327).
+char(p,25328).
+char(o,25329).
+char(o,25330).
+char(m,25331).
+char(o,25332).
+char(m,25333).
+char(8,25334).
+char(8,25335).
+char(8,25336).
+char(6,25337).
+char(p,25338).
+char(9,25339).
+char(2,25340).
+char(6,25341).
+char(9,25342).
+char(c,25343).
+char(c,25344).
+char(p,25345).
+char(3,25346).
+char(2,25347).
+char(9,25348).
+char(9,25349).
+char(c,25350).
+char(m,25351).
+char(o,25352).
+char(p,25353).
+char(o,25354).
+char(m,25355).
+char(o,25356).
+char(p,25357).
+char(o,25358).
+char(p,25359).
+char(o,25360).
+char(9,25361).
+char(6,25362).
+char(2,25363).
+char(0,25364).
+char(p,25365).
+char(o,25366).
+char(m,25367).
+char(o,25368).
+char(p,25369).
+char(8,25370).
+char(6,25371).
+char(6,25372).
+char(9,25373).
+char(m,25374).
+char(8,25375).
+char(5,25376).
+char(5,25377).
+char(8,25378).
+char(c,25379).
+char(m,25380).
+char(o,25381).
+char(p,25382).
+char(4,25383).
+char(9,25384).
+char(9,25385).
+char(8,25386).
+char(c,25387).
+char(c,25388).
+char(p,25389).
+char(o,25390).
+char(p,25391).
+char(o,25392).
+char(p,25393).
+char(2,25394).
+char(6,25395).
+char(5,25396).
+char(5,25397).
+char(c,25398).
+char(p,25399).
+char(2,25400).
+char(1,25401).
+char(5,25402).
+char(9,25403).
+char(c,25404).
+char(c,25405).
+char(c,25406).
+char(m,25407).
+char(o,25408).
+char(o,25409).
+char(p,25410).
+char(o,25411).
+char(m,25412).
+char(8,25413).
+char(5,25414).
+char(5,25415).
+char(0,25416).
+char(m,25417).
+char(1,25418).
+char(8,25419).
+char(8,25420).
+char(5,25421).
+char(c,25422).
+char(c,25423).
+char(p,25424).
+char(6,25425).
+char(5,25426).
+char(3,25427).
+char(7,25428).
+char(c,25429).
+char(m,25430).
+char(o,25431).
+char(p,25432).
+char(8,25433).
+char(5,25434).
+char(7,25435).
+char(9,25436).
+char(c,25437).
+char(c,25438).
+char(c,25439).
+char(c,25440).
+char(c,25441).
+char(p,25442).
+char(o,25443).
+char(p,25444).
+char(o,25445).
+char(8,25446).
+char(8,25447).
+char(8,25448).
+char(7,25449).
+char(c,25450).
+char(c,25451).
+char(m,25452).
+char(o,25453).
+char(m,25454).
+char(6,25455).
+char(6,25456).
+char(2,25457).
+char(c,25458).
+char(c,25459).
+char(p,25460).
+char(2,25461).
+char(2,25462).
+char(5,25463).
+char(8,25464).
+char(c,25465).
+char(p,25466).
+char(o,25467).
+char(m,25468).
+char(o,25469).
+char(m,25470).
+char(o,25471).
+char(m,25472).
+char(5,25473).
+char(8,25474).
+char(7,25475).
+char(7,25476).
+char(m,25477).
+char(o,25478).
+char(m,25479).
+char(5,25480).
+char(7,25481).
+char(2,25482).
+char(8,25483).
+char(p,25484).
+char(5,25485).
+char(0,25486).
+char(5,25487).
+char(2,25488).
+char(c,25489).
+char(m,25490).
+char(6,25491).
+char(3,25492).
+char(7,25493).
+char(2,25494).
+char(m,25495).
+char(o,25496).
+char(p,25497).
+char(3,25498).
+char(6,25499).
+char(1,25500).
+char(6,25501).
+char(p,25502).
+char(7,25503).
+char(2,25504).
+char(4,25505).
+char(3,25506).
+char(p,25507).
+char(o,25508).
+char(m,25509).
+char(9,25510).
+char(8,25511).
+char(4,25512).
+char(4,25513).
+char(c,25514).
+char(m,25515).
+char(o,25516).
+char(p,25517).
+char(o,25518).
+char(p,25519).
+char(8,25520).
+char(2,25521).
+char(9,25522).
+char(9,25523).
+char(c,25524).
+char(c,25525).
+char(c,25526).
+char(p,25527).
+char(2,25528).
+char(7,25529).
+char(8,25530).
+char(6,25531).
+char(c,25532).
+char(c,25533).
+char(c,25534).
+char(c,25535).
+char(c,25536).
+char(c,25537).
+char(c,25538).
+char(p,25539).
+char(6,25540).
+char(0,25541).
+char(2,25542).
+char(9,25543).
+char(c,25544).
+char(p,25545).
+char(o,25546).
+char(p,25547).
+char(o,25548).
+char(p,25549).
+char(8,25550).
+char(7,25551).
+char(2,25552).
+char(8,25553).
+char(p,25554).
+char(o,25555).
+char(6,25556).
+char(5,25557).
+char(5,25558).
+char(8,25559).
+char(c,25560).
+char(m,25561).
+char(5,25562).
+char(9,25563).
+char(3,25564).
+char(6,25565).
+char(p,25566).
+char(6,25567).
+char(6,25568).
+char(3,25569).
+char(3,25570).
+char(m,25571).
+char(3,25572).
+char(9,25573).
+char(5,25574).
+char(9,25575).
+char(p,25576).
+char(4,25577).
+char(3,25578).
+char(2,25579).
+char(7,25580).
+char(m,25581).
+char(o,25582).
+char(p,25583).
+char(9,25584).
+char(0,25585).
+char(0,25586).
+char(3,25587).
+char(m,25588).
+char(3,25589).
+char(6,25590).
+char(1,25591).
+char(9,25592).
+char(m,25593).
+char(o,25594).
+char(m,25595).
+char(5,25596).
+char(4,25597).
+char(3,25598).
+char(5,25599).
+char(c,25600).
+char(c,25601).
+char(c,25602).
+char(p,25603).
+char(o,25604).
+char(p,25605).
+char(6,25606).
+char(0,25607).
+char(6,25608).
+char(7,25609).
+char(c,25610).
+char(m,25611).
+char(o,25612).
+char(m,25613).
+char(o,25614).
+char(p,25615).
+char(2,25616).
+char(2,25617).
+char(8,25618).
+char(c,25619).
+char(c,25620).
+char(m,25621).
+char(2,25622).
+char(3,25623).
+char(6,25624).
+char(1,25625).
+char(p,25626).
+char(o,25627).
+char(p,25628).
+char(o,25629).
+char(m,25630).
+char(2,25631).
+char(9,25632).
+char(0,25633).
+char(6,25634).
+char(m,25635).
+char(6,25636).
+char(3,25637).
+char(7,25638).
+char(3,25639).
+char(m,25640).
+char(5,25641).
+char(2,25642).
+char(1,25643).
+char(5,25644).
+char(c,25645).
+char(p,25646).
+char(o,25647).
+char(p,25648).
+char(7,25649).
+char(7,25650).
+char(6,25651).
+char(7,25652).
+char(m,25653).
+char(5,25654).
+char(0,25655).
+char(1,25656).
+char(1,25657).
+char(p,25658).
+char(o,25659).
+char(p,25660).
+char(o,25661).
+char(p,25662).
+char(2,25663).
+char(1,25664).
+char(4,25665).
+char(3,25666).
+char(c,25667).
+char(p,25668).
+char(2,25669).
+char(9,25670).
+char(9,25671).
+char(9,25672).
+char(p,25673).
+char(9,25674).
+char(8,25675).
+char(9,25676).
+char(9,25677).
+char(p,25678).
+char(1,25679).
+char(0,25680).
+char(6,25681).
+char(7,25682).
+char(p,25683).
+char(o,25684).
+char(m,25685).
+char(9,25686).
+char(3,25687).
+char(9,25688).
+char(3,25689).
+char(c,25690).
+char(c,25691).
+char(m,25692).
+char(7,25693).
+char(9,25694).
+char(9,25695).
+char(6,25696).
+char(c,25697).
+char(m,25698).
+char(o,25699).
+char(p,25700).
+char(o,25701).
+char(7,25702).
+char(5,25703).
+char(8,25704).
+char(6,25705).
+char(m,25706).
+char(o,25707).
+char(m,25708).
+char(2,25709).
+char(9,25710).
+char(8,25711).
+char(0,25712).
+char(p,25713).
+char(1,25714).
+char(5,25715).
+char(7,25716).
+char(2,25717).
+char(c,25718).
+char(c,25719).
+char(c,25720).
+char(c,25721).
+char(c,25722).
+char(c,25723).
+char(m,25724).
+char(o,25725).
+char(p,25726).
+char(o,25727).
+char(p,25728).
+char(5,25729).
+char(6,25730).
+char(2,25731).
+char(m,25732).
+char(4,25733).
+char(6,25734).
+char(3,25735).
+char(6,25736).
+char(p,25737).
+char(o,25738).
+char(m,25739).
+char(o,25740).
+char(m,25741).
+char(3,25742).
+char(6,25743).
+char(0,25744).
+char(2,25745).
+char(p,25746).
+char(o,25747).
+char(p,25748).
+char(2,25749).
+char(8,25750).
+char(1,25751).
+char(8,25752).
+char(p,25753).
+char(o,25754).
+char(m,25755).
+char(5,25756).
+char(9,25757).
+char(9,25758).
+char(5,25759).
+char(c,25760).
+char(c,25761).
+char(m,25762).
+char(5,25763).
+char(4,25764).
+char(6,25765).
+char(1,25766).
+char(c,25767).
+char(p,25768).
+char(o,25769).
+char(5,25770).
+char(9,25771).
+char(2,25772).
+char(9,25773).
+char(c,25774).
+char(c,25775).
+char(c,25776).
+char(p,25777).
+char(o,25778).
+char(7,25779).
+char(7,25780).
+char(8,25781).
+char(9,25782).
+char(c,25783).
+char(c,25784).
+char(c,25785).
+char(p,25786).
+char(1,25787).
+char(1,25788).
+char(1,25789).
+char(6,25790).
+char(c,25791).
+char(c,25792).
+char(p,25793).
+char(o,25794).
+char(m,25795).
+char(8,25796).
+char(9,25797).
+char(4,25798).
+char(5,25799).
+char(c,25800).
+char(m,25801).
+char(4,25802).
+char(9,25803).
+char(5,25804).
+char(4,25805).
+char(c,25806).
+char(m,25807).
+char(7,25808).
+char(2,25809).
+char(9,25810).
+char(0,25811).
+char(c,25812).
+char(c,25813).
+char(c,25814).
+char(m,25815).
+char(5,25816).
+char(5,25817).
+char(9,25818).
+char(c,25819).
+char(m,25820).
+char(o,25821).
+char(m,25822).
+char(o,25823).
+char(m,25824).
+char(1,25825).
+char(7,25826).
+char(7,25827).
+char(7,25828).
+char(p,25829).
+char(5,25830).
+char(1,25831).
+char(7,25832).
+char(3,25833).
+char(m,25834).
+char(o,25835).
+char(m,25836).
+char(4,25837).
+char(2,25838).
+char(0,25839).
+char(5,25840).
+char(m,25841).
+char(5,25842).
+char(7,25843).
+char(6,25844).
+char(4,25845).
+char(p,25846).
+char(2,25847).
+char(7,25848).
+char(7,25849).
+char(3,25850).
+char(m,25851).
+char(o,25852).
+char(p,25853).
+char(1,25854).
+char(9,25855).
+char(9,25856).
+char(8,25857).
+char(p,25858).
+char(8,25859).
+char(3,25860).
+char(2,25861).
+char(6,25862).
+char(c,25863).
+char(m,25864).
+char(8,25865).
+char(5,25866).
+char(4,25867).
+char(7,25868).
+char(c,25869).
+char(c,25870).
+char(p,25871).
+char(7,25872).
+char(1,25873).
+char(9,25874).
+char(6,25875).
+char(c,25876).
+char(p,25877).
+char(3,25878).
+char(0,25879).
+char(6,25880).
+char(3,25881).
+char(p,25882).
+char(1,25883).
+char(3,25884).
+char(9,25885).
+char(1,25886).
+char(m,25887).
+char(1,25888).
+char(8,25889).
+char(0,25890).
+char(0,25891).
+char(c,25892).
+char(p,25893).
+char(o,25894).
+char(m,25895).
+char(o,25896).
+char(p,25897).
+char(3,25898).
+char(4,25899).
+char(1,25900).
+char(4,25901).
+char(c,25902).
+char(c,25903).
+char(c,25904).
+char(m,25905).
+char(o,25906).
+char(p,25907).
+char(o,25908).
+char(p,25909).
+char(o,25910).
+char(m,25911).
+char(o,25912).
+char(8,25913).
+char(1,25914).
+char(6,25915).
+char(p,25916).
+char(7,25917).
+char(2,25918).
+char(3,25919).
+char(0,25920).
+char(m,25921).
+char(8,25922).
+char(2,25923).
+char(2,25924).
+char(3,25925).
+char(c,25926).
+char(p,25927).
+char(o,25928).
+char(p,25929).
+char(5,25930).
+char(4,25931).
+char(9,25932).
+char(6,25933).
+char(c,25934).
+char(c,25935).
+char(m,25936).
+char(o,25937).
+char(p,25938).
+char(2,25939).
+char(4,25940).
+char(5,25941).
+char(5,25942).
+char(m,25943).
+char(9,25944).
+char(9,25945).
+char(0,25946).
+char(3,25947).
+char(c,25948).
+char(c,25949).
+char(p,25950).
+char(o,25951).
+char(p,25952).
+char(5,25953).
+char(8,25954).
+char(9,25955).
+char(9,25956).
+char(m,25957).
+char(3,25958).
+char(6,25959).
+char(9,25960).
+char(4,25961).
+char(c,25962).
+char(m,25963).
+char(o,25964).
+char(p,25965).
+char(o,25966).
+char(m,25967).
+char(o,25968).
+char(m,25969).
+char(3,25970).
+char(2,25971).
+char(3,25972).
+char(6,25973).
+char(m,25974).
+char(o,25975).
+char(m,25976).
+char(3,25977).
+char(0,25978).
+char(5,25979).
+char(5,25980).
+char(p,25981).
+char(8,25982).
+char(9,25983).
+char(6,25984).
+char(8,25985).
+char(m,25986).
+char(3,25987).
+char(9,25988).
+char(9,25989).
+char(5,25990).
+char(p,25991).
+char(5,25992).
+char(1,25993).
+char(4,25994).
+char(9,25995).
+char(p,25996).
+char(6,25997).
+char(5,25998).
+char(7,25999).
+char(7,26000).
+char(c,26001).
+char(c,26002).
+char(m,26003).
+char(o,26004).
+char(p,26005).
+char(7,26006).
+char(3,26007).
+char(0,26008).
+char(6,26009).
+char(c,26010).
+char(c,26011).
+char(c,26012).
+char(c,26013).
+char(c,26014).
+char(p,26015).
+char(7,26016).
+char(8,26017).
+char(5,26018).
+char(9,26019).
+char(p,26020).
+char(o,26021).
+char(o,26022).
+char(m,26023).
+char(4,26024).
+char(9,26025).
+char(5,26026).
+char(3,26027).
+char(c,26028).
+char(c,26029).
+char(c,26030).
+char(c,26031).
+char(c,26032).
+char(c,26033).
+char(c,26034).
+char(c,26035).
+char(c,26036).
+char(c,26037).
+char(m,26038).
+char(o,26039).
+char(o,26040).
+char(o,26041).
+char(p,26042).
+char(9,26043).
+char(2,26044).
+char(5,26045).
+char(6,26046).
+char(m,26047).
+char(1,26048).
+char(2,26049).
+char(5,26050).
+char(3,26051).
+char(p,26052).
+char(o,26053).
+char(m,26054).
+char(1,26055).
+char(1,26056).
+char(3,26057).
+char(2,26058).
+char(c,26059).
+char(p,26060).
+char(o,26061).
+char(m,26062).
+char(2,26063).
+char(9,26064).
+char(6,26065).
+char(5,26066).
+char(m,26067).
+char(o,26068).
+char(m,26069).
+char(8,26070).
+char(6,26071).
+char(8,26072).
+char(4,26073).
+char(m,26074).
+char(o,26075).
+char(o,26076).
+char(p,26077).
+char(8,26078).
+char(1,26079).
+char(7,26080).
+char(9,26081).
+char(c,26082).
+char(m,26083).
+char(o,26084).
+char(4,26085).
+char(3,26086).
+char(3,26087).
+char(1,26088).
+char(c,26089).
+char(p,26090).
+char(4,26091).
+char(2,26092).
+char(7,26093).
+char(4,26094).
+char(c,26095).
+char(c,26096).
+char(c,26097).
+char(c,26098).
+char(m,26099).
+char(o,26100).
+char(o,26101).
+char(m,26102).
+char(6,26103).
+char(5,26104).
+char(2,26105).
+char(4,26106).
+char(p,26107).
+char(6,26108).
+char(5,26109).
+char(0,26110).
+char(0,26111).
+char(m,26112).
+char(4,26113).
+char(1,26114).
+char(5,26115).
+char(9,26116).
+char(p,26117).
+char(o,26118).
+char(7,26119).
+char(7,26120).
+char(0,26121).
+char(p,26122).
+char(5,26123).
+char(9,26124).
+char(1,26125).
+char(1,26126).
+char(p,26127).
+char(o,26128).
+char(o,26129).
+char(5,26130).
+char(2,26131).
+char(2,26132).
+char(8,26133).
+char(p,26134).
+char(1,26135).
+char(5,26136).
+char(4,26137).
+char(2,26138).
+char(c,26139).
+char(p,26140).
+char(o,26141).
+char(m,26142).
+char(o,26143).
+char(m,26144).
+char(o,26145).
+char(m,26146).
+char(1,26147).
+char(7,26148).
+char(4,26149).
+char(9,26150).
+char(c,26151).
+char(c,26152).
+char(c,26153).
+char(p,26154).
+char(8,26155).
+char(0,26156).
+char(3,26157).
+char(0,26158).
+char(c,26159).
+char(p,26160).
+char(o,26161).
+char(m,26162).
+char(5,26163).
+char(2,26164).
+char(9,26165).
+char(3,26166).
+char(p,26167).
+char(o,26168).
+char(p,26169).
+char(4,26170).
+char(2,26171).
+char(4,26172).
+char(2,26173).
+char(p,26174).
+char(2,26175).
+char(2,26176).
+char(6,26177).
+char(2,26178).
+char(c,26179).
+char(m,26180).
+char(o,26181).
+char(m,26182).
+char(o,26183).
+char(p,26184).
+char(8,26185).
+char(3,26186).
+char(9,26187).
+char(8,26188).
+char(m,26189).
+char(o,26190).
+char(9,26191).
+char(9,26192).
+char(1,26193).
+char(8,26194).
+char(p,26195).
+char(3,26196).
+char(9,26197).
+char(1,26198).
+char(1,26199).
+char(c,26200).
+char(m,26201).
+char(3,26202).
+char(3,26203).
+char(8,26204).
+char(9,26205).
+char(p,26206).
+char(3,26207).
+char(1,26208).
+char(0,26209).
+char(1,26210).
+char(p,26211).
+char(2,26212).
+char(8,26213).
+char(6,26214).
+char(9,26215).
+char(c,26216).
+char(p,26217).
+char(7,26218).
+char(1,26219).
+char(7,26220).
+char(7,26221).
+char(m,26222).
+char(3,26223).
+char(2,26224).
+char(2,26225).
+char(1,26226).
+char(p,26227).
+char(5,26228).
+char(4,26229).
+char(0,26230).
+char(6,26231).
+char(p,26232).
+char(o,26233).
+char(p,26234).
+char(7,26235).
+char(1,26236).
+char(5,26237).
+char(9,26238).
+char(p,26239).
+char(o,26240).
+char(m,26241).
+char(8,26242).
+char(1,26243).
+char(0,26244).
+char(1,26245).
+char(m,26246).
+char(o,26247).
+char(o,26248).
+char(o,26249).
+char(m,26250).
+char(o,26251).
+char(6,26252).
+char(4,26253).
+char(8,26254).
+char(8,26255).
+char(m,26256).
+char(1,26257).
+char(4,26258).
+char(4,26259).
+char(3,26260).
+char(m,26261).
+char(o,26262).
+char(o,26263).
+char(m,26264).
+char(o,26265).
+char(6,26266).
+char(3,26267).
+char(6,26268).
+char(2,26269).
+char(c,26270).
+char(p,26271).
+char(o,26272).
+char(o,26273).
+char(p,26274).
+char(o,26275).
+char(p,26276).
+char(9,26277).
+char(3,26278).
+char(7,26279).
+char(p,26280).
+char(o,26281).
+char(6,26282).
+char(6,26283).
+char(7,26284).
+char(p,26285).
+char(3,26286).
+char(1,26287).
+char(6,26288).
+char(9,26289).
+char(c,26290).
+char(p,26291).
+char(6,26292).
+char(1,26293).
+char(2,26294).
+char(c,26295).
+char(c,26296).
+char(m,26297).
+char(5,26298).
+char(3,26299).
+char(p,26300).
+char(o,26301).
+char(o,26302).
+char(8,26303).
+char(8,26304).
+char(8,26305).
+char(3,26306).
+char(c,26307).
+char(m,26308).
+char(4,26309).
+char(8,26310).
+char(1,26311).
+char(0,26312).
+char(c,26313).
+char(c,26314).
+char(c,26315).
+char(c,26316).
+char(c,26317).
+char(m,26318).
+char(6,26319).
+char(6,26320).
+char(8,26321).
+char(4,26322).
+char(p,26323).
+char(7,26324).
+char(6,26325).
+char(7,26326).
+char(5,26327).
+char(p,26328).
+char(o,26329).
+char(m,26330).
+char(6,26331).
+char(4,26332).
+char(8,26333).
+char(p,26334).
+char(o,26335).
+char(p,26336).
+char(o,26337).
+char(o,26338).
+char(3,26339).
+char(6,26340).
+char(3,26341).
+char(2,26342).
+char(c,26343).
+char(m,26344).
+char(o,26345).
+char(p,26346).
+char(o,26347).
+char(o,26348).
+char(p,26349).
+char(8,26350).
+char(6,26351).
+char(3,26352).
+char(4,26353).
+char(p,26354).
+char(1,26355).
+char(1,26356).
+char(8,26357).
+char(3,26358).
+char(m,26359).
+char(1,26360).
+char(1,26361).
+char(9,26362).
+char(3,26363).
+char(c,26364).
+char(c,26365).
+char(c,26366).
+char(c,26367).
+char(m,26368).
+char(7,26369).
+char(8,26370).
+char(0,26371).
+char(5,26372).
+char(m,26373).
+char(6,26374).
+char(8,26375).
+char(4,26376).
+char(6,26377).
+char(c,26378).
+char(m,26379).
+char(o,26380).
+char(p,26381).
+char(5,26382).
+char(3,26383).
+char(6,26384).
+char(p,26385).
+char(o,26386).
+char(m,26387).
+char(o,26388).
+char(o,26389).
+char(p,26390).
+char(o,26391).
+char(m,26392).
+char(8,26393).
+char(9,26394).
+char(6,26395).
+char(0,26396).
+char(m,26397).
+char(o,26398).
+char(8,26399).
+char(3,26400).
+char(2,26401).
+char(3,26402).
+char(m,26403).
+char(o,26404).
+char(p,26405).
+char(3,26406).
+char(2,26407).
+char(9,26408).
+char(5,26409).
+char(c,26410).
+char(m,26411).
+char(o,26412).
+char(p,26413).
+char(o,26414).
+char(p,26415).
+char(2,26416).
+char(5,26417).
+char(3,26418).
+char(4,26419).
+char(m,26420).
+char(o,26421).
+char(p,26422).
+char(o,26423).
+char(m,26424).
+char(o,26425).
+char(o,26426).
+char(p,26427).
+char(1,26428).
+char(9,26429).
+char(5,26430).
+char(8,26431).
+char(m,26432).
+char(o,26433).
+char(p,26434).
+char(4,26435).
+char(4,26436).
+char(8,26437).
+char(p,26438).
+char(1,26439).
+char(0,26440).
+char(4,26441).
+char(4,26442).
+char(p,26443).
+char(o,26444).
+char(o,26445).
+char(p,26446).
+char(o,26447).
+char(p,26448).
+char(o,26449).
+char(m,26450).
+char(4,26451).
+char(1,26452).
+char(0,26453).
+char(3,26454).
+char(m,26455).
+char(o,26456).
+char(1,26457).
+char(1,26458).
+char(2,26459).
+char(1,26460).
+char(p,26461).
+char(o,26462).
+char(p,26463).
+char(6,26464).
+char(6,26465).
+char(4,26466).
+char(5,26467).
+char(p,26468).
+char(9,26469).
+char(2,26470).
+char(4,26471).
+char(1,26472).
+char(c,26473).
+char(p,26474).
+char(3,26475).
+char(2,26476).
+char(8,26477).
+char(c,26478).
+char(m,26479).
+char(o,26480).
+char(o,26481).
+char(m,26482).
+char(6,26483).
+char(6,26484).
+char(4,26485).
+char(4,26486).
+char(p,26487).
+char(o,26488).
+char(2,26489).
+char(0,26490).
+char(8,26491).
+char(p,26492).
+char(6,26493).
+char(1,26494).
+char(1,26495).
+char(2,26496).
+char(c,26497).
+char(p,26498).
+char(6,26499).
+char(0,26500).
+char(3,26501).
+char(0,26502).
+char(c,26503).
+char(m,26504).
+char(o,26505).
+char(m,26506).
+char(6,26507).
+char(9,26508).
+char(2,26509).
+char(0,26510).
+char(p,26511).
+char(8,26512).
+char(6,26513).
+char(3,26514).
+char(6,26515).
+char(c,26516).
+char(m,26517).
+char(5,26518).
+char(1,26519).
+char(1,26520).
+char(2,26521).
+char(c,26522).
+char(c,26523).
+char(c,26524).
+char(m,26525).
+char(4,26526).
+char(6,26527).
+char(1,26528).
+char(8,26529).
+char(m,26530).
+char(o,26531).
+char(m,26532).
+char(o,26533).
+char(p,26534).
+char(o,26535).
+char(m,26536).
+char(o,26537).
+char(p,26538).
+char(9,26539).
+char(2,26540).
+char(5,26541).
+char(0,26542).
+char(p,26543).
+char(9,26544).
+char(7,26545).
+char(8,26546).
+char(0,26547).
+char(c,26548).
+char(c,26549).
+char(c,26550).
+char(c,26551).
+char(p,26552).
+char(o,26553).
+char(m,26554).
+char(o,26555).
+char(9,26556).
+char(5,26557).
+char(0,26558).
+char(4,26559).
+char(m,26560).
+char(5,26561).
+char(1,26562).
+char(3,26563).
+char(8,26564).
+char(p,26565).
+char(1,26566).
+char(1,26567).
+char(9,26568).
+char(8,26569).
+char(m,26570).
+char(6,26571).
+char(0,26572).
+char(4,26573).
+char(0,26574).
+char(m,26575).
+char(o,26576).
+char(m,26577).
+char(3,26578).
+char(3,26579).
+char(7,26580).
+char(9,26581).
+char(m,26582).
+char(8,26583).
+char(7,26584).
+char(1,26585).
+char(5,26586).
+char(p,26587).
+char(o,26588).
+char(p,26589).
+char(o,26590).
+char(m,26591).
+char(o,26592).
+char(p,26593).
+char(2,26594).
+char(6,26595).
+char(2,26596).
+char(3,26597).
+char(c,26598).
+char(c,26599).
+char(p,26600).
+char(5,26601).
+char(0,26602).
+char(4,26603).
+char(7,26604).
+char(p,26605).
+char(o,26606).
+char(o,26607).
+char(m,26608).
+char(o,26609).
+char(p,26610).
+char(o,26611).
+char(m,26612).
+char(o,26613).
+char(m,26614).
+char(o,26615).
+char(o,26616).
+char(m,26617).
+char(o,26618).
+char(m,26619).
+char(o,26620).
+char(m,26621).
+char(o,26622).
+char(m,26623).
+char(o,26624).
+char(m,26625).
+char(o,26626).
+char(m,26627).
+char(4,26628).
+char(3,26629).
+char(1,26630).
+char(0,26631).
+char(p,26632).
+char(3,26633).
+char(2,26634).
+char(8,26635).
+char(1,26636).
+char(c,26637).
+char(p,26638).
+char(4,26639).
+char(3,26640).
+char(7,26641).
+char(8,26642).
+char(p,26643).
+char(5,26644).
+char(6,26645).
+char(5,26646).
+char(p,26647).
+char(4,26648).
+char(2,26649).
+char(6,26650).
+char(8,26651).
+char(p,26652).
+char(o,26653).
+char(3,26654).
+char(3,26655).
+char(0,26656).
+char(p,26657).
+char(o,26658).
+char(o,26659).
+char(p,26660).
+char(9,26661).
+char(1,26662).
+char(0,26663).
+char(c,26664).
+char(c,26665).
+char(c,26666).
+char(m,26667).
+char(o,26668).
+char(1,26669).
+char(2,26670).
+char(9,26671).
+char(9,26672).
+char(c,26673).
+char(m,26674).
+char(9,26675).
+char(9,26676).
+char(2,26677).
+char(0,26678).
+char(c,26679).
+char(m,26680).
+char(3,26681).
+char(4,26682).
+char(2,26683).
+char(5,26684).
+char(m,26685).
+char(o,26686).
+char(8,26687).
+char(3,26688).
+char(3,26689).
+char(0,26690).
+char(p,26691).
+char(o,26692).
+char(3,26693).
+char(5,26694).
+char(2,26695).
+char(6,26696).
+char(m,26697).
+char(2,26698).
+char(9,26699).
+char(4,26700).
+char(6,26701).
+char(c,26702).
+char(c,26703).
+char(p,26704).
+char(o,26705).
+char(o,26706).
+char(m,26707).
+char(5,26708).
+char(2,26709).
+char(9,26710).
+char(8,26711).
+char(p,26712).
+char(3,26713).
+char(5,26714).
+char(4,26715).
+char(0,26716).
+char(c,26717).
+char(m,26718).
+char(1,26719).
+char(3,26720).
+char(4,26721).
+char(9,26722).
+char(m,26723).
+char(6,26724).
+char(3,26725).
+char(3,26726).
+char(5,26727).
+char(c,26728).
+char(c,26729).
+char(m,26730).
+char(6,26731).
+char(4,26732).
+char(8,26733).
+char(1,26734).
+char(p,26735).
+char(6,26736).
+char(1,26737).
+char(8,26738).
+char(9,26739).
+char(c,26740).
+char(m,26741).
+char(o,26742).
+char(o,26743).
+char(m,26744).
+char(o,26745).
+char(1,26746).
+char(9,26747).
+char(3,26748).
+char(6,26749).
+char(c,26750).
+char(m,26751).
+char(7,26752).
+char(4,26753).
+char(3,26754).
+char(9,26755).
+char(p,26756).
+char(o,26757).
+char(m,26758).
+char(3,26759).
+char(8,26760).
+char(2,26761).
+char(2,26762).
+char(c,26763).
+char(c,26764).
+char(p,26765).
+char(6,26766).
+char(0,26767).
+char(6,26768).
+char(3,26769).
+char(c,26770).
+char(c,26771).
+char(c,26772).
+char(c,26773).
+char(p,26774).
+char(5,26775).
+char(3,26776).
+char(8,26777).
+char(7,26778).
+char(c,26779).
+char(c,26780).
+char(m,26781).
+char(9,26782).
+char(2,26783).
+char(1,26784).
+char(0,26785).
+char(c,26786).
+char(c,26787).
+char(m,26788).
+char(o,26789).
+char(p,26790).
+char(9,26791).
+char(9,26792).
+char(7,26793).
+char(9,26794).
+char(c,26795).
+char(c,26796).
+char(c,26797).
+char(c,26798).
+char(c,26799).
+char(c,26800).
+char(c,26801).
+char(c,26802).
+char(c,26803).
+char(c,26804).
+char(c,26805).
+char(c,26806).
+char(p,26807).
+char(o,26808).
+char(m,26809).
+char(5,26810).
+char(7,26811).
+char(7,26812).
+char(1,26813).
+char(c,26814).
+char(c,26815).
+char(m,26816).
+char(o,26817).
+char(o,26818).
+char(p,26819).
+char(o,26820).
+char(9,26821).
+char(0,26822).
+char(8,26823).
+char(8,26824).
+char(c,26825).
+char(m,26826).
+char(5,26827).
+char(1,26828).
+char(1,26829).
+char(0,26830).
+char(c,26831).
+char(m,26832).
+char(o,26833).
+char(m,26834).
+char(9,26835).
+char(2,26836).
+char(1,26837).
+char(0,26838).
+char(m,26839).
+char(2,26840).
+char(0,26841).
+char(2,26842).
+char(2,26843).
+char(c,26844).
+char(c,26845).
+char(p,26846).
+char(1,26847).
+char(8,26848).
+char(6,26849).
+char(0,26850).
+char(m,26851).
+char(o,26852).
+char(p,26853).
+char(o,26854).
+char(p,26855).
+char(1,26856).
+char(3,26857).
+char(5,26858).
+char(9,26859).
+char(c,26860).
+char(c,26861).
+char(m,26862).
+char(3,26863).
+char(0,26864).
+char(5,26865).
+char(8,26866).
+char(c,26867).
+char(m,26868).
+char(7,26869).
+char(4,26870).
+char(4,26871).
+char(7,26872).
+char(c,26873).
+char(p,26874).
+char(9,26875).
+char(4,26876).
+char(8,26877).
+char(6,26878).
+char(c,26879).
+char(m,26880).
+char(2,26881).
+char(8,26882).
+char(0,26883).
+char(3,26884).
+char(c,26885).
+char(p,26886).
+char(o,26887).
+char(m,26888).
+char(o,26889).
+char(o,26890).
+char(m,26891).
+char(9,26892).
+char(0,26893).
+char(0,26894).
+char(c,26895).
+char(c,26896).
+char(c,26897).
+char(m,26898).
+char(2,26899).
+char(9,26900).
+char(3,26901).
+char(3,26902).
+char(m,26903).
+char(5,26904).
+char(3,26905).
+char(8,26906).
+char(9,26907).
+char(p,26908).
+char(1,26909).
+char(2,26910).
+char(7,26911).
+char(2,26912).
+char(c,26913).
+char(p,26914).
+char(9,26915).
+char(5,26916).
+char(8,26917).
+char(9,26918).
+char(p,26919).
+char(5,26920).
+char(9,26921).
+char(5,26922).
+char(2,26923).
+char(p,26924).
+char(o,26925).
+char(6,26926).
+char(9,26927).
+char(2,26928).
+char(3,26929).
+char(c,26930).
+char(c,26931).
+char(p,26932).
+char(o,26933).
+char(m,26934).
+char(o,26935).
+char(m,26936).
+char(o,26937).
+char(m,26938).
+char(8,26939).
+char(8,26940).
+char(0,26941).
+char(3,26942).
+char(c,26943).
+char(c,26944).
+char(c,26945).
+char(c,26946).
+char(m,26947).
+char(6,26948).
+char(9,26949).
+char(1,26950).
+char(0,26951).
+char(m,26952).
+char(o,26953).
+char(p,26954).
+char(2,26955).
+char(6,26956).
+char(7,26957).
+char(0,26958).
+char(m,26959).
+char(8,26960).
+char(4,26961).
+char(7,26962).
+char(0,26963).
+char(p,26964).
+char(3,26965).
+char(9,26966).
+char(5,26967).
+char(1,26968).
+char(c,26969).
+char(p,26970).
+char(o,26971).
+char(2,26972).
+char(0,26973).
+char(2,26974).
+char(9,26975).
+char(p,26976).
+char(o,26977).
+char(p,26978).
+char(2,26979).
+char(6,26980).
+char(1,26981).
+char(8,26982).
+char(m,26983).
+char(9,26984).
+char(5,26985).
+char(6,26986).
+char(4,26987).
+char(c,26988).
+char(c,26989).
+char(m,26990).
+char(o,26991).
+char(p,26992).
+char(1,26993).
+char(9,26994).
+char(3,26995).
+char(5,26996).
+char(p,26997).
+char(8,26998).
+char(4,26999).
+char(1,27000).
+char(3,27001).
+char(p,27002).
+char(o,27003).
+char(3,27004).
+char(5,27005).
+char(1,27006).
+char(4,27007).
+char(c,27008).
+char(c,27009).
+char(p,27010).
+char(1,27011).
+char(4,27012).
+char(6,27013).
+char(0,27014).
+char(m,27015).
+char(7,27016).
+char(8,27017).
+char(9,27018).
+char(0,27019).
+char(c,27020).
+char(p,27021).
+char(o,27022).
+char(p,27023).
+char(2,27024).
+char(4,27025).
+char(8,27026).
+char(8,27027).
+char(m,27028).
+char(6,27029).
+char(9,27030).
+char(7,27031).
+char(0,27032).
+char(m,27033).
+char(o,27034).
+char(p,27035).
+char(o,27036).
+char(o,27037).
+char(p,27038).
+char(5,27039).
+char(2,27040).
+char(0,27041).
+char(c,27042).
+char(p,27043).
+char(5,27044).
+char(0,27045).
+char(8,27046).
+char(4,27047).
+char(c,27048).
+char(c,27049).
+char(c,27050).
+char(c,27051).
+char(c,27052).
+char(p,27053).
+char(o,27054).
+char(m,27055).
+char(o,27056).
+char(p,27057).
+char(5,27058).
+char(9,27059).
+char(0,27060).
+char(c,27061).
+char(m,27062).
+char(8,27063).
+char(1,27064).
+char(4,27065).
+char(0,27066).
+char(m,27067).
+char(9,27068).
+char(2,27069).
+char(1,27070).
+char(8,27071).
+char(m,27072).
+char(o,27073).
+char(p,27074).
+char(9,27075).
+char(7,27076).
+char(7,27077).
+char(8,27078).
+char(p,27079).
+char(9,27080).
+char(4,27081).
+char(6,27082).
+char(6,27083).
+char(c,27084).
+char(c,27085).
+char(c,27086).
+char(c,27087).
+char(c,27088).
+char(c,27089).
+char(c,27090).
+char(m,27091).
+char(o,27092).
+char(o,27093).
+char(4,27094).
+char(0,27095).
+char(2,27096).
+char(0,27097).
+char(p,27098).
+char(o,27099).
+char(m,27100).
+char(7,27101).
+char(1,27102).
+char(0,27103).
+char(7,27104).
+char(m,27105).
+char(7,27106).
+char(0,27107).
+char(8,27108).
+char(0,27109).
+char(m,27110).
+char(o,27111).
+char(o,27112).
+char(p,27113).
+char(o,27114).
+char(2,27115).
+char(8,27116).
+char(2,27117).
+char(5,27118).
+char(m,27119).
+char(o,27120).
+char(p,27121).
+char(o,27122).
+char(8,27123).
+char(9,27124).
+char(8,27125).
+char(1,27126).
+char(p,27127).
+char(o,27128).
+char(p,27129).
+char(o,27130).
+char(m,27131).
+char(o,27132).
+char(m,27133).
+char(o,27134).
+char(p,27135).
+char(2,27136).
+char(5,27137).
+char(4,27138).
+char(6,27139).
+char(p,27140).
+char(9,27141).
+char(2,27142).
+char(7,27143).
+char(3,27144).
+char(c,27145).
+char(c,27146).
+char(c,27147).
+char(c,27148).
+char(c,27149).
+char(c,27150).
+char(m,27151).
+char(6,27152).
+char(8,27153).
+char(8,27154).
+char(5,27155).
+char(c,27156).
+char(c,27157).
+char(c,27158).
+char(c,27159).
+char(p,27160).
+char(3,27161).
+char(9,27162).
+char(9,27163).
+char(1,27164).
+char(m,27165).
+char(5,27166).
+char(9,27167).
+char(8,27168).
+char(5,27169).
+char(c,27170).
+char(c,27171).
+char(m,27172).
+char(2,27173).
+char(4,27174).
+char(4,27175).
+char(9,27176).
+char(c,27177).
+char(m,27178).
+char(7,27179).
+char(2,27180).
+char(0,27181).
+char(7,27182).
+char(c,27183).
+char(c,27184).
+char(m,27185).
+char(2,27186).
+char(0,27187).
+char(4,27188).
+char(8,27189).
+char(m,27190).
+char(o,27191).
+char(4,27192).
+char(7,27193).
+char(7,27194).
+char(6,27195).
+char(m,27196).
+char(o,27197).
+char(p,27198).
+char(4,27199).
+char(0,27200).
+char(6,27201).
+char(3,27202).
+char(m,27203).
+char(o,27204).
+char(p,27205).
+char(o,27206).
+char(m,27207).
+char(4,27208).
+char(4,27209).
+char(0,27210).
+char(9,27211).
+char(c,27212).
+char(c,27213).
+char(m,27214).
+char(3,27215).
+char(2,27216).
+char(2,27217).
+char(5,27218).
+char(c,27219).
+char(m,27220).
+char(8,27221).
+char(4,27222).
+char(1,27223).
+char(9,27224).
+char(m,27225).
+char(9,27226).
+char(4,27227).
+char(1,27228).
+char(6,27229).
+char(c,27230).
+char(p,27231).
+char(o,27232).
+char(m,27233).
+char(o,27234).
+char(p,27235).
+char(2,27236).
+char(2,27237).
+char(1,27238).
+char(1,27239).
+char(m,27240).
+char(4,27241).
+char(0,27242).
+char(8,27243).
+char(1,27244).
+char(c,27245).
+char(c,27246).
+char(p,27247).
+char(2,27248).
+char(6,27249).
+char(5,27250).
+char(8,27251).
+char(c,27252).
+char(m,27253).
+char(5,27254).
+char(2,27255).
+char(9,27256).
+char(9,27257).
+char(m,27258).
+char(o,27259).
+char(o,27260).
+char(p,27261).
+char(o,27262).
+char(p,27263).
+char(o,27264).
+char(m,27265).
+char(o,27266).
+char(p,27267).
+char(o,27268).
+char(o,27269).
+char(p,27270).
+char(o,27271).
+char(p,27272).
+char(7,27273).
+char(0,27274).
+char(3,27275).
+char(m,27276).
+char(o,27277).
+char(p,27278).
+char(4,27279).
+char(5,27280).
+char(5,27281).
+char(7,27282).
+char(p,27283).
+char(o,27284).
+char(o,27285).
+char(p,27286).
+char(o,27287).
+char(o,27288).
+char(m,27289).
+char(3,27290).
+char(8,27291).
+char(5,27292).
+char(0,27293).
+char(p,27294).
+char(o,27295).
+char(p,27296).
+char(2,27297).
+char(8,27298).
+char(3,27299).
+char(6,27300).
+char(c,27301).
+char(c,27302).
+char(c,27303).
+char(c,27304).
+char(c,27305).
+char(m,27306).
+char(o,27307).
+char(m,27308).
+char(7,27309).
+char(5,27310).
+char(5,27311).
+char(6,27312).
+char(c,27313).
+char(m,27314).
+char(2,27315).
+char(3,27316).
+char(3,27317).
+char(5,27318).
+char(m,27319).
+char(4,27320).
+char(8,27321).
+char(8,27322).
+char(8,27323).
+char(c,27324).
+char(c,27325).
+char(c,27326).
+char(m,27327).
+char(2,27328).
+char(2,27329).
+char(1,27330).
+char(6,27331).
+char(p,27332).
+char(5,27333).
+char(2,27334).
+char(9,27335).
+char(c,27336).
+char(c,27337).
+char(p,27338).
+char(1,27339).
+char(3,27340).
+char(3,27341).
+char(2,27342).
+char(m,27343).
+char(3,27344).
+char(5,27345).
+char(3,27346).
+char(0,27347).
+char(p,27348).
+char(1,27349).
+char(7,27350).
+char(9,27351).
+char(1,27352).
+char(c,27353).
+char(p,27354).
+char(3,27355).
+char(7,27356).
+char(3,27357).
+char(p,27358).
+char(o,27359).
+char(m,27360).
+char(o,27361).
+char(4,27362).
+char(9,27363).
+char(7,27364).
+char(8,27365).
+char(m,27366).
+char(7,27367).
+char(0,27368).
+char(5,27369).
+char(1,27370).
+char(m,27371).
+char(o,27372).
+char(8,27373).
+char(1,27374).
+char(8,27375).
+char(c,27376).
+char(m,27377).
+char(o,27378).
+char(m,27379).
+char(6,27380).
+char(2,27381).
+char(2,27382).
+char(c,27383).
+char(p,27384).
+char(5,27385).
+char(4,27386).
+char(6,27387).
+char(8,27388).
+char(p,27389).
+char(7,27390).
+char(6,27391).
+char(1,27392).
+char(7,27393).
+char(c,27394).
+char(p,27395).
+char(1,27396).
+char(7,27397).
+char(5,27398).
+char(6,27399).
+char(c,27400).
+char(m,27401).
+char(o,27402).
+char(o,27403).
+char(p,27404).
+char(4,27405).
+char(5,27406).
+char(7,27407).
+char(6,27408).
+char(p,27409).
+char(o,27410).
+char(m,27411).
+char(o,27412).
+char(m,27413).
+char(9,27414).
+char(5,27415).
+char(8,27416).
+char(1,27417).
+char(c,27418).
+char(p,27419).
+char(3,27420).
+char(5,27421).
+char(4,27422).
+char(9,27423).
+char(c,27424).
+char(p,27425).
+char(o,27426).
+char(p,27427).
+char(o,27428).
+char(m,27429).
+char(o,27430).
+char(m,27431).
+char(9,27432).
+char(5,27433).
+char(9,27434).
+char(6,27435).
+char(p,27436).
+char(6,27437).
+char(3,27438).
+char(6,27439).
+char(4,27440).
+char(c,27441).
+char(p,27442).
+char(5,27443).
+char(8,27444).
+char(4,27445).
+char(2,27446).
+char(c,27447).
+char(p,27448).
+char(o,27449).
+char(m,27450).
+char(4,27451).
+char(5,27452).
+char(2,27453).
+char(8,27454).
+char(c,27455).
+char(p,27456).
+char(o,27457).
+char(p,27458).
+char(6,27459).
+char(6,27460).
+char(c,27461).
+char(c,27462).
+char(c,27463).
+char(c,27464).
+char(c,27465).
+char(c,27466).
+char(p,27467).
+char(3,27468).
+char(4,27469).
+char(9,27470).
+char(8,27471).
+char(c,27472).
+char(m,27473).
+char(1,27474).
+char(0,27475).
+char(6,27476).
+char(0,27477).
+char(c,27478).
+char(m,27479).
+char(o,27480).
+char(m,27481).
+char(o,27482).
+char(2,27483).
+char(3,27484).
+char(5,27485).
+char(7,27486).
+char(m,27487).
+char(6,27488).
+char(2,27489).
+char(7,27490).
+char(p,27491).
+char(o,27492).
+char(9,27493).
+char(8,27494).
+char(2,27495).
+char(3,27496).
+char(c,27497).
+char(c,27498).
+char(c,27499).
+char(c,27500).
+char(c,27501).
+char(c,27502).
+char(c,27503).
+char(p,27504).
+char(o,27505).
+char(1,27506).
+char(6,27507).
+char(1,27508).
+char(2,27509).
+char(c,27510).
+char(p,27511).
+char(o,27512).
+char(m,27513).
+char(o,27514).
+char(m,27515).
+char(4,27516).
+char(3,27517).
+char(5,27518).
+char(7,27519).
+char(p,27520).
+char(o,27521).
+char(p,27522).
+char(o,27523).
+char(m,27524).
+char(1,27525).
+char(8,27526).
+char(8,27527).
+char(5,27528).
+char(m,27529).
+char(6,27530).
+char(7,27531).
+char(9,27532).
+char(9,27533).
+char(c,27534).
+char(m,27535).
+char(o,27536).
+char(m,27537).
+char(o,27538).
+char(m,27539).
+char(o,27540).
+char(m,27541).
+char(9,27542).
+char(4,27543).
+char(7,27544).
+char(p,27545).
+char(o,27546).
+char(o,27547).
+char(p,27548).
+char(o,27549).
+char(p,27550).
+char(o,27551).
+char(m,27552).
+char(8,27553).
+char(9,27554).
+char(0,27555).
+char(2,27556).
+char(p,27557).
+char(2,27558).
+char(4,27559).
+char(5,27560).
+char(0,27561).
+char(c,27562).
+char(p,27563).
+char(3,27564).
+char(1,27565).
+char(4,27566).
+char(p,27567).
+char(o,27568).
+char(p,27569).
+char(o,27570).
+char(p,27571).
+char(o,27572).
+char(o,27573).
+char(9,27574).
+char(1,27575).
+char(7,27576).
+char(6,27577).
+char(c,27578).
+char(p,27579).
+char(o,27580).
+char(o,27581).
+char(o,27582).
+char(p,27583).
+char(8,27584).
+char(1,27585).
+char(3,27586).
+char(8,27587).
+char(m,27588).
+char(o,27589).
+char(p,27590).
+char(o,27591).
+char(p,27592).
+char(6,27593).
+char(9,27594).
+char(2,27595).
+char(5,27596).
+char(c,27597).
+char(m,27598).
+char(o,27599).
+char(m,27600).
+char(o,27601).
+char(o,27602).
+char(m,27603).
+char(8,27604).
+char(1,27605).
+char(1,27606).
+char(7,27607).
+char(c,27608).
+char(c,27609).
+char(c,27610).
+char(m,27611).
+char(1,27612).
+char(5,27613).
+char(7,27614).
+char(0,27615).
+char(c,27616).
+char(m,27617).
+char(7,27618).
+char(3,27619).
+char(4,27620).
+char(5,27621).
+char(m,27622).
+char(o,27623).
+char(p,27624).
+char(1,27625).
+char(0,27626).
+char(5,27627).
+char(4,27628).
+char(m,27629).
+char(2,27630).
+char(8,27631).
+char(4,27632).
+char(9,27633).
+char(c,27634).
+char(p,27635).
+char(6,27636).
+char(5,27637).
+char(6,27638).
+char(2,27639).
+char(m,27640).
+char(5,27641).
+char(4,27642).
+char(8,27643).
+char(4,27644).
+char(m,27645).
+char(o,27646).
+char(o,27647).
+char(p,27648).
+char(o,27649).
+char(o,27650).
+char(p,27651).
+char(o,27652).
+char(p,27653).
+char(6,27654).
+char(3,27655).
+char(9,27656).
+char(4,27657).
+char(p,27658).
+char(8,27659).
+char(2,27660).
+char(1,27661).
+char(2,27662).
+char(c,27663).
+char(m,27664).
+char(o,27665).
+char(p,27666).
+char(o,27667).
+char(p,27668).
+char(9,27669).
+char(9,27670).
+char(8,27671).
+char(9,27672).
+char(c,27673).
+char(c,27674).
+char(c,27675).
+char(c,27676).
+char(m,27677).
+char(o,27678).
+char(o,27679).
+char(m,27680).
+char(o,27681).
+char(o,27682).
+char(p,27683).
+char(o,27684).
+char(p,27685).
+char(o,27686).
+char(p,27687).
+char(o,27688).
+char(m,27689).
+char(o,27690).
+char(m,27691).
+char(1,27692).
+char(0,27693).
+char(3,27694).
+char(3,27695).
+char(c,27696).
+char(m,27697).
+char(o,27698).
+char(p,27699).
+char(o,27700).
+char(p,27701).
+char(o,27702).
+char(m,27703).
+char(o,27704).
+char(m,27705).
+char(3,27706).
+char(7,27707).
+char(6,27708).
+char(2,27709).
+char(p,27710).
+char(1,27711).
+char(8,27712).
+char(6,27713).
+char(1,27714).
+char(c,27715).
+char(p,27716).
+char(o,27717).
+char(5,27718).
+char(2,27719).
+char(0,27720).
+char(9,27721).
+char(p,27722).
+char(1,27723).
+char(2,27724).
+char(2,27725).
+char(1,27726).
+char(p,27727).
+char(1,27728).
+char(1,27729).
+char(9,27730).
+char(3,27731).
+char(c,27732).
+char(c,27733).
+char(c,27734).
+char(c,27735).
+char(m,27736).
+char(8,27737).
+char(4,27738).
+char(8,27739).
+char(3,27740).
+char(p,27741).
+char(6,27742).
+char(7,27743).
+char(7,27744).
+char(4,27745).
+char(c,27746).
+char(m,27747).
+char(o,27748).
+char(p,27749).
+char(7,27750).
+char(9,27751).
+char(0,27752).
+char(6,27753).
+char(c,27754).
+char(c,27755).
+char(p,27756).
+char(o,27757).
+char(m,27758).
+char(5,27759).
+char(1,27760).
+char(3,27761).
+char(7,27762).
+char(m,27763).
+char(9,27764).
+char(9,27765).
+char(5,27766).
+char(9,27767).
+char(c,27768).
+char(p,27769).
+char(7,27770).
+char(9,27771).
+char(6,27772).
+char(2,27773).
+char(m,27774).
+char(6,27775).
+char(5,27776).
+char(1,27777).
+char(2,27778).
+char(c,27779).
+char(m,27780).
+char(o,27781).
+char(5,27782).
+char(6,27783).
+char(5,27784).
+char(7,27785).
+char(c,27786).
+char(p,27787).
+char(8,27788).
+char(5,27789).
+char(1,27790).
+char(3,27791).
+char(m,27792).
+char(2,27793).
+char(7,27794).
+char(8,27795).
+char(3,27796).
+char(c,27797).
+char(m,27798).
+char(o,27799).
+char(p,27800).
+char(4,27801).
+char(1,27802).
+char(2,27803).
+char(5,27804).
+char(m,27805).
+char(5,27806).
+char(0,27807).
+char(7,27808).
+char(0,27809).
+char(m,27810).
+char(2,27811).
+char(8,27812).
+char(1,27813).
+char(7,27814).
+char(c,27815).
+char(m,27816).
+char(2,27817).
+char(0,27818).
+char(4,27819).
+char(8,27820).
+char(c,27821).
+char(m,27822).
+char(o,27823).
+char(4,27824).
+char(0,27825).
+char(8,27826).
+char(7,27827).
+char(m,27828).
+char(7,27829).
+char(7,27830).
+char(0,27831).
+char(c,27832).
+char(p,27833).
+char(o,27834).
+char(o,27835).
+char(o,27836).
+char(o,27837).
+char(4,27838).
+char(8,27839).
+char(7,27840).
+char(3,27841).
+char(p,27842).
+char(o,27843).
+char(m,27844).
+char(8,27845).
+char(1,27846).
+char(2,27847).
+char(3,27848).
+char(m,27849).
+char(o,27850).
+char(m,27851).
+char(6,27852).
+char(2,27853).
+char(5,27854).
+char(1,27855).
+char(c,27856).
+char(m,27857).
+char(o,27858).
+char(o,27859).
+char(p,27860).
+char(5,27861).
+char(9,27862).
+char(6,27863).
+char(6,27864).
+char(p,27865).
+char(o,27866).
+char(8,27867).
+char(4,27868).
+char(0,27869).
+char(8,27870).
+char(p,27871).
+char(o,27872).
+char(m,27873).
+char(2,27874).
+char(0,27875).
+char(5,27876).
+char(2,27877).
+char(c,27878).
+char(m,27879).
+char(o,27880).
+char(p,27881).
+char(2,27882).
+char(2,27883).
+char(8,27884).
+char(5,27885).
+char(p,27886).
+char(o,27887).
+char(3,27888).
+char(0,27889).
+char(4,27890).
+char(9,27891).
+char(m,27892).
+char(2,27893).
+char(1,27894).
+char(1,27895).
+char(6,27896).
+char(c,27897).
+char(c,27898).
+char(p,27899).
+char(o,27900).
+char(m,27901).
+char(5,27902).
+char(8,27903).
+char(6,27904).
+char(c,27905).
+char(p,27906).
+char(5,27907).
+char(2,27908).
+char(7,27909).
+char(4,27910).
+char(p,27911).
+char(4,27912).
+char(3,27913).
+char(4,27914).
+char(8,27915).
+char(c,27916).
+char(m,27917).
+char(o,27918).
+char(p,27919).
+char(6,27920).
+char(3,27921).
+char(9,27922).
+char(2,27923).
+char(m,27924).
+char(o,27925).
+char(m,27926).
+char(o,27927).
+char(p,27928).
+char(4,27929).
+char(7,27930).
+char(1,27931).
+char(8,27932).
+char(c,27933).
+char(m,27934).
+char(4,27935).
+char(0,27936).
+char(0,27937).
+char(9,27938).
+char(p,27939).
+char(o,27940).
+char(3,27941).
+char(8,27942).
+char(9,27943).
+char(8,27944).
+char(c,27945).
+char(c,27946).
+char(p,27947).
+char(5,27948).
+char(0,27949).
+char(4,27950).
+char(9,27951).
+char(c,27952).
+char(c,27953).
+char(m,27954).
+char(o,27955).
+char(o,27956).
+char(p,27957).
+char(3,27958).
+char(3,27959).
+char(c,27960).
+char(p,27961).
+char(5,27962).
+char(9,27963).
+char(6,27964).
+char(1,27965).
+char(c,27966).
+char(c,27967).
+char(c,27968).
+char(c,27969).
+char(c,27970).
+char(c,27971).
+char(c,27972).
+char(c,27973).
+char(c,27974).
+char(p,27975).
+char(2,27976).
+char(8,27977).
+char(6,27978).
+char(c,27979).
+char(c,27980).
+char(p,27981).
+char(o,27982).
+char(m,27983).
+char(o,27984).
+char(2,27985).
+char(6,27986).
+char(1,27987).
+char(7,27988).
+char(m,27989).
+char(3,27990).
+char(1,27991).
+char(2,27992).
+char(5,27993).
+char(m,27994).
+char(8,27995).
+char(0,27996).
+char(7,27997).
+char(5,27998).
+char(c,27999).
+char(c,28000).
+char(p,28001).
+char(2,28002).
+char(4,28003).
+char(6,28004).
+char(6,28005).
+char(m,28006).
+char(o,28007).
+char(m,28008).
+char(o,28009).
+char(3,28010).
+char(0,28011).
+char(9,28012).
+char(9,28013).
+char(c,28014).
+char(m,28015).
+char(7,28016).
+char(2,28017).
+char(2,28018).
+char(2,28019).
+char(c,28020).
+char(c,28021).
+char(p,28022).
+char(7,28023).
+char(8,28024).
+char(2,28025).
+char(2,28026).
+char(m,28027).
+char(6,28028).
+char(5,28029).
+char(0,28030).
+char(6,28031).
+char(c,28032).
+char(c,28033).
+char(c,28034).
+char(c,28035).
+char(c,28036).
+char(c,28037).
+char(c,28038).
+char(c,28039).
+char(c,28040).
+char(p,28041).
+char(o,28042).
+char(m,28043).
+char(o,28044).
+char(p,28045).
+char(5,28046).
+char(5,28047).
+char(0,28048).
+char(2,28049).
+char(m,28050).
+char(o,28051).
+char(m,28052).
+char(4,28053).
+char(3,28054).
+char(0,28055).
+char(c,28056).
+char(p,28057).
+char(3,28058).
+char(4,28059).
+char(5,28060).
+char(c,28061).
+char(c,28062).
+char(c,28063).
+char(p,28064).
+char(o,28065).
+char(m,28066).
+char(2,28067).
+char(5,28068).
+char(4,28069).
+char(1,28070).
+char(c,28071).
+char(c,28072).
+char(c,28073).
+char(c,28074).
+char(c,28075).
+char(m,28076).
+char(o,28077).
+char(o,28078).
+char(p,28079).
+char(8,28080).
+char(8,28081).
+char(3,28082).
+char(5,28083).
+char(c,28084).
+char(m,28085).
+char(8,28086).
+char(5,28087).
+char(2,28088).
+char(3,28089).
+char(p,28090).
+char(o,28091).
+char(p,28092).
+char(o,28093).
+char(m,28094).
+char(1,28095).
+char(8,28096).
+char(6,28097).
+char(0,28098).
+char(p,28099).
+char(o,28100).
+char(p,28101).
+char(o,28102).
+char(m,28103).
+char(o,28104).
+char(p,28105).
+char(o,28106).
+char(m,28107).
+char(o,28108).
+char(o,28109).
+char(p,28110).
+char(o,28111).
+char(8,28112).
+char(0,28113).
+char(0,28114).
+char(1,28115).
+char(m,28116).
+char(1,28117).
+char(0,28118).
+char(5,28119).
+char(3,28120).
+char(m,28121).
+char(o,28122).
+char(m,28123).
+char(7,28124).
+char(2,28125).
+char(0,28126).
+char(2,28127).
+char(c,28128).
+char(p,28129).
+char(4,28130).
+char(3,28131).
+char(5,28132).
+char(1,28133).
+char(c,28134).
+char(p,28135).
+char(7,28136).
+char(4,28137).
+char(3,28138).
+char(1,28139).
+char(p,28140).
+char(o,28141).
+char(m,28142).
+char(o,28143).
+char(m,28144).
+char(4,28145).
+char(7,28146).
+char(8,28147).
+char(6,28148).
+char(m,28149).
+char(o,28150).
+char(p,28151).
+char(o,28152).
+char(6,28153).
+char(2,28154).
+char(3,28155).
+char(9,28156).
+char(m,28157).
+char(o,28158).
+char(m,28159).
+char(4,28160).
+char(7,28161).
+char(8,28162).
+char(5,28163).
+char(c,28164).
+char(c,28165).
+char(p,28166).
+char(5,28167).
+char(3,28168).
+char(3,28169).
+char(3,28170).
+char(c,28171).
+char(p,28172).
+char(o,28173).
+char(p,28174).
+char(o,28175).
+char(o,28176).
+char(m,28177).
+char(o,28178).
+char(3,28179).
+char(4,28180).
+char(3,28181).
+char(3,28182).
+char(m,28183).
+char(o,28184).
+char(p,28185).
+char(5,28186).
+char(4,28187).
+char(9,28188).
+char(3,28189).
+char(c,28190).
+char(m,28191).
+char(o,28192).
+char(m,28193).
+char(8,28194).
+char(3,28195).
+char(0,28196).
+char(5,28197).
+char(c,28198).
+char(m,28199).
+char(3,28200).
+char(5,28201).
+char(2,28202).
+char(c,28203).
+char(p,28204).
+char(o,28205).
+char(m,28206).
+char(o,28207).
+char(m,28208).
+char(2,28209).
+char(1,28210).
+char(3,28211).
+char(6,28212).
+char(p,28213).
+char(o,28214).
+char(p,28215).
+char(6,28216).
+char(4,28217).
+char(4,28218).
+char(9,28219).
+char(p,28220).
+char(4,28221).
+char(7,28222).
+char(2,28223).
+char(7,28224).
+char(c,28225).
+char(c,28226).
+char(m,28227).
+char(1,28228).
+char(3,28229).
+char(4,28230).
+char(4,28231).
+char(p,28232).
+char(6,28233).
+char(0,28234).
+char(4,28235).
+char(c,28236).
+char(c,28237).
+char(m,28238).
+char(o,28239).
+char(m,28240).
+char(o,28241).
+char(p,28242).
+char(1,28243).
+char(8,28244).
+char(9,28245).
+char(7,28246).
+char(m,28247).
+char(o,28248).
+char(m,28249).
+char(3,28250).
+char(1,28251).
+char(7,28252).
+char(2,28253).
+char(p,28254).
+char(7,28255).
+char(0,28256).
+char(5,28257).
+char(5,28258).
+char(m,28259).
+char(o,28260).
+char(p,28261).
+char(9,28262).
+char(2,28263).
+char(7,28264).
+char(4,28265).
+char(c,28266).
+char(p,28267).
+char(o,28268).
+char(p,28269).
+char(o,28270).
+char(m,28271).
+char(o,28272).
+char(m,28273).
+char(8,28274).
+char(9,28275).
+char(4,28276).
+char(1,28277).
+char(c,28278).
+char(c,28279).
+char(m,28280).
+char(5,28281).
+char(2,28282).
+char(0,28283).
+char(6,28284).
+char(m,28285).
+char(9,28286).
+char(4,28287).
+char(0,28288).
+char(8,28289).
+char(m,28290).
+char(o,28291).
+char(p,28292).
+char(o,28293).
+char(p,28294).
+char(4,28295).
+char(4,28296).
+char(1,28297).
+char(3,28298).
+char(c,28299).
+char(p,28300).
+char(o,28301).
+char(o,28302).
+char(m,28303).
+char(o,28304).
+char(p,28305).
+char(o,28306).
+char(m,28307).
+char(3,28308).
+char(1,28309).
+char(1,28310).
+char(8,28311).
+char(p,28312).
+char(8,28313).
+char(5,28314).
+char(6,28315).
+char(0,28316).
+char(c,28317).
+char(c,28318).
+char(p,28319).
+char(7,28320).
+char(1,28321).
+char(0,28322).
+char(2,28323).
+char(p,28324).
+char(7,28325).
+char(6,28326).
+char(7,28327).
+char(5,28328).
+char(c,28329).
+char(p,28330).
+char(6,28331).
+char(2,28332).
+char(0,28333).
+char(9,28334).
+char(p,28335).
+char(3,28336).
+char(0,28337).
+char(1,28338).
+char(6,28339).
+char(m,28340).
+char(3,28341).
+char(7,28342).
+char(3,28343).
+char(2,28344).
+char(m,28345).
+char(o,28346).
+char(o,28347).
+char(m,28348).
+char(o,28349).
+char(m,28350).
+char(8,28351).
+char(7,28352).
+char(3,28353).
+char(3,28354).
+char(c,28355).
+char(p,28356).
+char(o,28357).
+char(p,28358).
+char(o,28359).
+char(o,28360).
+char(o,28361).
+char(p,28362).
+char(o,28363).
+char(p,28364).
+char(4,28365).
+char(2,28366).
+char(4,28367).
+char(7,28368).
+char(p,28369).
+char(o,28370).
+char(9,28371).
+char(4,28372).
+char(2,28373).
+char(4,28374).
+char(p,28375).
+char(8,28376).
+char(9,28377).
+char(5,28378).
+char(5,28379).
+char(m,28380).
+char(o,28381).
+char(p,28382).
+char(6,28383).
+char(6,28384).
+char(0,28385).
+char(4,28386).
+char(p,28387).
+char(8,28388).
+char(0,28389).
+char(2,28390).
+char(9,28391).
+char(p,28392).
+char(8,28393).
+char(3,28394).
+char(6,28395).
+char(0,28396).
+char(m,28397).
+char(1,28398).
+char(5,28399).
+char(2,28400).
+char(7,28401).
+char(c,28402).
+char(m,28403).
+char(3,28404).
+char(8,28405).
+char(7,28406).
+char(6,28407).
+char(c,28408).
+char(c,28409).
+char(c,28410).
+char(c,28411).
+char(c,28412).
+char(p,28413).
+char(o,28414).
+char(p,28415).
+char(o,28416).
+char(p,28417).
+char(o,28418).
+char(m,28419).
+char(4,28420).
+char(2,28421).
+char(8,28422).
+char(9,28423).
+char(m,28424).
+char(6,28425).
+char(6,28426).
+char(5,28427).
+char(9,28428).
+char(c,28429).
+char(c,28430).
+char(c,28431).
+char(p,28432).
+char(o,28433).
+char(p,28434).
+char(o,28435).
+char(m,28436).
+char(7,28437).
+char(9,28438).
+char(8,28439).
+char(8,28440).
+char(m,28441).
+char(5,28442).
+char(7,28443).
+char(8,28444).
+char(7,28445).
+char(p,28446).
+char(o,28447).
+char(m,28448).
+char(2,28449).
+char(7,28450).
+char(4,28451).
+char(1,28452).
+char(p,28453).
+char(8,28454).
+char(2,28455).
+char(1,28456).
+char(1,28457).
+char(c,28458).
+char(c,28459).
+char(m,28460).
+char(4,28461).
+char(7,28462).
+char(3,28463).
+char(9,28464).
+char(c,28465).
+char(p,28466).
+char(9,28467).
+char(5,28468).
+char(9,28469).
+char(6,28470).
+char(p,28471).
+char(o,28472).
+char(3,28473).
+char(8,28474).
+char(5,28475).
+char(9,28476).
+char(c,28477).
+char(p,28478).
+char(o,28479).
+char(o,28480).
+char(p,28481).
+char(8,28482).
+char(7,28483).
+char(9,28484).
+char(5,28485).
+char(p,28486).
+char(4,28487).
+char(5,28488).
+char(9,28489).
+char(2,28490).
+char(c,28491).
+char(m,28492).
+char(o,28493).
+char(p,28494).
+char(3,28495).
+char(3,28496).
+char(9,28497).
+char(7,28498).
+char(c,28499).
+char(c,28500).
+char(c,28501).
+char(p,28502).
+char(9,28503).
+char(0,28504).
+char(1,28505).
+char(6,28506).
+char(m,28507).
+char(8,28508).
+char(3,28509).
+char(2,28510).
+char(p,28511).
+char(6,28512).
+char(4,28513).
+char(6,28514).
+char(p,28515).
+char(2,28516).
+char(7,28517).
+char(2,28518).
+char(3,28519).
+char(c,28520).
+char(p,28521).
+char(9,28522).
+char(0,28523).
+char(6,28524).
+char(0,28525).
+char(c,28526).
+char(p,28527).
+char(2,28528).
+char(7,28529).
+char(8,28530).
+char(0,28531).
+char(c,28532).
+char(m,28533).
+char(o,28534).
+char(o,28535).
+char(p,28536).
+char(4,28537).
+char(3,28538).
+char(3,28539).
+char(5,28540).
+char(p,28541).
+char(o,28542).
+char(5,28543).
+char(2,28544).
+char(3,28545).
+char(8,28546).
+char(m,28547).
+char(o,28548).
+char(p,28549).
+char(2,28550).
+char(4,28551).
+char(8,28552).
+char(7,28553).
+char(m,28554).
+char(o,28555).
+char(p,28556).
+char(o,28557).
+char(p,28558).
+char(1,28559).
+char(3,28560).
+char(1,28561).
+char(3,28562).
+char(c,28563).
+char(m,28564).
+char(7,28565).
+char(4,28566).
+char(8,28567).
+char(0,28568).
+char(c,28569).
+char(c,28570).
+char(c,28571).
+char(c,28572).
+char(p,28573).
+char(o,28574).
+char(5,28575).
+char(8,28576).
+char(9,28577).
+char(5,28578).
+char(c,28579).
+char(c,28580).
+char(p,28581).
+char(8,28582).
+char(5,28583).
+char(6,28584).
+char(7,28585).
+char(m,28586).
+char(o,28587).
+char(o,28588).
+char(p,28589).
+char(o,28590).
+char(p,28591).
+char(5,28592).
+char(5,28593).
+char(3,28594).
+char(7,28595).
+char(m,28596).
+char(6,28597).
+char(5,28598).
+char(6,28599).
+char(8,28600).
+char(m,28601).
+char(8,28602).
+char(8,28603).
+char(7,28604).
+char(5,28605).
+char(c,28606).
+char(p,28607).
+char(o,28608).
+char(p,28609).
+char(o,28610).
+char(o,28611).
+char(m,28612).
+char(o,28613).
+char(m,28614).
+char(o,28615).
+char(p,28616).
+char(9,28617).
+char(2,28618).
+char(2,28619).
+char(p,28620).
+char(o,28621).
+char(o,28622).
+char(p,28623).
+char(o,28624).
+char(m,28625).
+char(3,28626).
+char(6,28627).
+char(9,28628).
+char(9,28629).
+char(p,28630).
+char(1,28631).
+char(2,28632).
+char(9,28633).
+char(4,28634).
+char(c,28635).
+char(p,28636).
+char(o,28637).
+char(1,28638).
+char(3,28639).
+char(9,28640).
+char(8,28641).
+char(c,28642).
+char(m,28643).
+char(o,28644).
+char(m,28645).
+char(o,28646).
+char(p,28647).
+char(o,28648).
+char(4,28649).
+char(7,28650).
+char(5,28651).
+char(9,28652).
+char(c,28653).
+char(m,28654).
+char(4,28655).
+char(5,28656).
+char(1,28657).
+char(9,28658).
+char(p,28659).
+char(o,28660).
+char(p,28661).
+char(1,28662).
+char(0,28663).
+char(1,28664).
+char(5,28665).
+char(c,28666).
+char(m,28667).
+char(8,28668).
+char(0,28669).
+char(0,28670).
+char(3,28671).
+char(m,28672).
+char(4,28673).
+char(3,28674).
+char(6,28675).
+char(5,28676).
+char(m,28677).
+char(o,28678).
+char(m,28679).
+char(5,28680).
+char(8,28681).
+char(5,28682).
+char(6,28683).
+char(p,28684).
+char(3,28685).
+char(1,28686).
+char(0,28687).
+char(2,28688).
+char(m,28689).
+char(7,28690).
+char(2,28691).
+char(3,28692).
+char(9,28693).
+char(c,28694).
+char(c,28695).
+char(m,28696).
+char(8,28697).
+char(1,28698).
+char(2,28699).
+char(4,28700).
+char(c,28701).
+char(p,28702).
+char(8,28703).
+char(9,28704).
+char(6,28705).
+char(m,28706).
+char(o,28707).
+char(1,28708).
+char(7,28709).
+char(1,28710).
+char(2,28711).
+char(p,28712).
+char(o,28713).
+char(p,28714).
+char(7,28715).
+char(0,28716).
+char(8,28717).
+char(6,28718).
+char(c,28719).
+char(p,28720).
+char(6,28721).
+char(3,28722).
+char(5,28723).
+char(1,28724).
+char(p,28725).
+char(1,28726).
+char(1,28727).
+char(4,28728).
+char(7,28729).
+char(c,28730).
+char(c,28731).
+char(c,28732).
+char(m,28733).
+char(8,28734).
+char(8,28735).
+char(0,28736).
+char(0,28737).
+char(c,28738).
+char(p,28739).
+char(o,28740).
+char(p,28741).
+char(5,28742).
+char(5,28743).
+char(6,28744).
+char(2,28745).
+char(c,28746).
+char(m,28747).
+char(o,28748).
+char(m,28749).
+char(9,28750).
+char(3,28751).
+char(6,28752).
+char(1,28753).
+char(c,28754).
+char(c,28755).
+char(c,28756).
+char(m,28757).
+char(o,28758).
+char(o,28759).
+char(p,28760).
+char(2,28761).
+char(6,28762).
+char(3,28763).
+char(1,28764).
+char(m,28765).
+char(o,28766).
+char(p,28767).
+char(o,28768).
+char(p,28769).
+char(8,28770).
+char(7,28771).
+char(7,28772).
+char(0,28773).
+char(m,28774).
+char(7,28775).
+char(5,28776).
+char(1,28777).
+char(2,28778).
+char(c,28779).
+char(p,28780).
+char(5,28781).
+char(8,28782).
+char(8,28783).
+char(4,28784).
+char(m,28785).
+char(2,28786).
+char(1,28787).
+char(7,28788).
+char(5,28789).
+char(c,28790).
+char(c,28791).
+char(c,28792).
+char(m,28793).
+char(8,28794).
+char(2,28795).
+char(p,28796).
+char(4,28797).
+char(1,28798).
+char(3,28799).
+char(8,28800).
+char(p,28801).
+char(2,28802).
+char(9,28803).
+char(1,28804).
+char(1,28805).
+char(p,28806).
+char(o,28807).
+char(m,28808).
+char(o,28809).
+char(o,28810).
+char(m,28811).
+char(o,28812).
+char(p,28813).
+char(4,28814).
+char(2,28815).
+char(7,28816).
+char(7,28817).
+char(m,28818).
+char(o,28819).
+char(p,28820).
+char(o,28821).
+char(m,28822).
+char(o,28823).
+char(m,28824).
+char(3,28825).
+char(2,28826).
+char(2,28827).
+char(1,28828).
+char(c,28829).
+char(m,28830).
+char(6,28831).
+char(5,28832).
+char(8,28833).
+char(1,28834).
+char(p,28835).
+char(4,28836).
+char(6,28837).
+char(1,28838).
+char(2,28839).
+char(c,28840).
+char(c,28841).
+char(p,28842).
+char(o,28843).
+char(p,28844).
+char(o,28845).
+char(m,28846).
+char(6,28847).
+char(6,28848).
+char(8,28849).
+char(5,28850).
+char(c,28851).
+char(m,28852).
+char(o,28853).
+char(m,28854).
+char(5,28855).
+char(9,28856).
+char(5,28857).
+char(c,28858).
+char(c,28859).
+char(c,28860).
+char(p,28861).
+char(o,28862).
+char(m,28863).
+char(5,28864).
+char(1,28865).
+char(1,28866).
+char(2,28867).
+char(p,28868).
+char(4,28869).
+char(4,28870).
+char(c,28871).
+char(m,28872).
+char(2,28873).
+char(5,28874).
+char(2,28875).
+char(0,28876).
+char(p,28877).
+char(5,28878).
+char(2,28879).
+char(8,28880).
+char(1,28881).
+char(m,28882).
+char(6,28883).
+char(9,28884).
+char(5,28885).
+char(2,28886).
+char(m,28887).
+char(4,28888).
+char(8,28889).
+char(9,28890).
+char(0,28891).
+char(p,28892).
+char(o,28893).
+char(p,28894).
+char(o,28895).
+char(m,28896).
+char(3,28897).
+char(7,28898).
+char(5,28899).
+char(3,28900).
+char(c,28901).
+char(c,28902).
+char(c,28903).
+char(c,28904).
+char(p,28905).
+char(7,28906).
+char(7,28907).
+char(0,28908).
+char(m,28909).
+char(o,28910).
+char(p,28911).
+char(6,28912).
+char(2,28913).
+char(6,28914).
+char(0,28915).
+char(p,28916).
+char(7,28917).
+char(0,28918).
+char(9,28919).
+char(1,28920).
+char(p,28921).
+char(6,28922).
+char(7,28923).
+char(1,28924).
+char(9,28925).
+char(c,28926).
+char(p,28927).
+char(5,28928).
+char(6,28929).
+char(9,28930).
+char(4,28931).
+char(c,28932).
+char(c,28933).
+char(p,28934).
+char(o,28935).
+char(m,28936).
+char(3,28937).
+char(2,28938).
+char(8,28939).
+char(5,28940).
+char(p,28941).
+char(o,28942).
+char(8,28943).
+char(7,28944).
+char(9,28945).
+char(c,28946).
+char(m,28947).
+char(8,28948).
+char(4,28949).
+char(6,28950).
+char(0,28951).
+char(c,28952).
+char(m,28953).
+char(3,28954).
+char(2,28955).
+char(9,28956).
+char(5,28957).
+char(c,28958).
+char(c,28959).
+char(c,28960).
+char(c,28961).
+char(m,28962).
+char(3,28963).
+char(3,28964).
+char(8,28965).
+char(7,28966).
+char(c,28967).
+char(p,28968).
+char(o,28969).
+char(o,28970).
+char(p,28971).
+char(o,28972).
+char(p,28973).
+char(o,28974).
+char(m,28975).
+char(o,28976).
+char(o,28977).
+char(p,28978).
+char(o,28979).
+char(p,28980).
+char(o,28981).
+char(p,28982).
+char(9,28983).
+char(1,28984).
+char(6,28985).
+char(4,28986).
+char(c,28987).
+char(p,28988).
+char(7,28989).
+char(1,28990).
+char(2,28991).
+char(9,28992).
+char(c,28993).
+char(c,28994).
+char(c,28995).
+char(c,28996).
+char(m,28997).
+char(o,28998).
+char(m,28999).
+char(5,29000).
+char(3,29001).
+char(4,29002).
+char(3,29003).
+char(c,29004).
+char(m,29005).
+char(7,29006).
+char(0,29007).
+char(1,29008).
+char(p,29009).
+char(5,29010).
+char(7,29011).
+char(9,29012).
+char(1,29013).
+char(m,29014).
+char(8,29015).
+char(8,29016).
+char(5,29017).
+char(9,29018).
+char(m,29019).
+char(8,29020).
+char(6,29021).
+char(0,29022).
+char(0,29023).
+char(c,29024).
+char(c,29025).
+char(m,29026).
+char(o,29027).
+char(p,29028).
+char(1,29029).
+char(8,29030).
+char(4,29031).
+char(4,29032).
+char(c,29033).
+char(c,29034).
+char(m,29035).
+char(o,29036).
+char(5,29037).
+char(4,29038).
+char(6,29039).
+char(8,29040).
+char(c,29041).
+char(p,29042).
+char(6,29043).
+char(3,29044).
+char(0,29045).
+char(1,29046).
+char(c,29047).
+char(c,29048).
+char(c,29049).
+char(c,29050).
+char(c,29051).
+char(m,29052).
+char(8,29053).
+char(0,29054).
+char(3,29055).
+char(8,29056).
+char(p,29057).
+char(o,29058).
+char(o,29059).
+char(p,29060).
+char(9,29061).
+char(2,29062).
+char(1,29063).
+char(9,29064).
+char(p,29065).
+char(3,29066).
+char(1,29067).
+char(3,29068).
+char(0,29069).
+char(p,29070).
+char(o,29071).
+char(6,29072).
+char(1,29073).
+char(9,29074).
+char(4,29075).
+char(c,29076).
+char(c,29077).
+char(m,29078).
+char(9,29079).
+char(5,29080).
+char(5,29081).
+char(0,29082).
+char(m,29083).
+char(o,29084).
+char(m,29085).
+char(7,29086).
+char(0,29087).
+char(0,29088).
+char(4,29089).
+char(p,29090).
+char(o,29091).
+char(p,29092).
+char(3,29093).
+char(8,29094).
+char(6,29095).
+char(0,29096).
+char(c,29097).
+char(m,29098).
+char(o,29099).
+char(o,29100).
+char(p,29101).
+char(o,29102).
+char(p,29103).
+char(o,29104).
+char(2,29105).
+char(2,29106).
+char(6,29107).
+char(7,29108).
+char(p,29109).
+char(7,29110).
+char(2,29111).
+char(0,29112).
+char(7,29113).
+char(c,29114).
+char(c,29115).
+char(p,29116).
+char(o,29117).
+char(p,29118).
+char(o,29119).
+char(3,29120).
+char(4,29121).
+char(7,29122).
+char(3,29123).
+char(c,29124).
+char(c,29125).
+char(c,29126).
+char(c,29127).
+char(p,29128).
+char(8,29129).
+char(0,29130).
+char(4,29131).
+char(0,29132).
+char(c,29133).
+char(c,29134).
+char(m,29135).
+char(o,29136).
+char(m,29137).
+char(1,29138).
+char(3,29139).
+char(9,29140).
+char(0,29141).
+char(m,29142).
+char(8,29143).
+char(6,29144).
+char(4,29145).
+char(7,29146).
+char(c,29147).
+char(p,29148).
+char(5,29149).
+char(0,29150).
+char(6,29151).
+char(2,29152).
+char(c,29153).
+char(c,29154).
+char(c,29155).
+char(c,29156).
+char(c,29157).
+char(c,29158).
+char(c,29159).
+char(p,29160).
+char(o,29161).
+char(6,29162).
+char(6,29163).
+char(0,29164).
+char(2,29165).
+char(c,29166).
+char(p,29167).
+char(9,29168).
+char(4,29169).
+char(5,29170).
+char(7,29171).
+char(m,29172).
+char(4,29173).
+char(7,29174).
+char(3,29175).
+char(8,29176).
+char(c,29177).
+char(m,29178).
+char(o,29179).
+char(p,29180).
+char(7,29181).
+char(5,29182).
+char(7,29183).
+char(4,29184).
+char(m,29185).
+char(o,29186).
+char(m,29187).
+char(5,29188).
+char(7,29189).
+char(4,29190).
+char(5,29191).
+char(c,29192).
+char(m,29193).
+char(o,29194).
+char(4,29195).
+char(8,29196).
+char(8,29197).
+char(7,29198).
+char(p,29199).
+char(o,29200).
+char(o,29201).
+char(3,29202).
+char(6,29203).
+char(3,29204).
+char(6,29205).
+char(p,29206).
+char(o,29207).
+char(o,29208).
+char(p,29209).
+char(o,29210).
+char(p,29211).
+char(o,29212).
+char(m,29213).
+char(o,29214).
+char(p,29215).
+char(9,29216).
+char(7,29217).
+char(3,29218).
+char(8,29219).
+char(m,29220).
+char(o,29221).
+char(o,29222).
+char(o,29223).
+char(o,29224).
+char(p,29225).
+char(2,29226).
+char(2,29227).
+char(7,29228).
+char(7,29229).
+char(c,29230).
+char(c,29231).
+char(c,29232).
+char(c,29233).
+char(c,29234).
+char(c,29235).
+char(p,29236).
+char(o,29237).
+char(p,29238).
+char(o,29239).
+char(p,29240).
+char(6,29241).
+char(3,29242).
+char(5,29243).
+char(4,29244).
+char(p,29245).
+char(o,29246).
+char(o,29247).
+char(p,29248).
+char(1,29249).
+char(2,29250).
+char(0,29251).
+char(9,29252).
+char(c,29253).
+char(c,29254).
+char(p,29255).
+char(3,29256).
+char(4,29257).
+char(6,29258).
+char(7,29259).
+char(m,29260).
+char(5,29261).
+char(7,29262).
+char(1,29263).
+char(1,29264).
+char(p,29265).
+char(8,29266).
+char(3,29267).
+char(0,29268).
+char(p,29269).
+char(o,29270).
+char(p,29271).
+char(1,29272).
+char(6,29273).
+char(1,29274).
+char(7,29275).
+char(p,29276).
+char(4,29277).
+char(6,29278).
+char(9,29279).
+char(3,29280).
+char(c,29281).
+char(m,29282).
+char(2,29283).
+char(2,29284).
+char(2,29285).
+char(1,29286).
+char(p,29287).
+char(o,29288).
+char(m,29289).
+char(o,29290).
+char(o,29291).
+char(m,29292).
+char(o,29293).
+char(m,29294).
+char(6,29295).
+char(1,29296).
+char(6,29297).
+char(4,29298).
+char(c,29299).
+char(m,29300).
+char(2,29301).
+char(6,29302).
+char(2,29303).
+char(c,29304).
+char(c,29305).
+char(c,29306).
+char(c,29307).
+char(p,29308).
+char(o,29309).
+char(m,29310).
+char(o,29311).
+char(p,29312).
+char(o,29313).
+char(p,29314).
+char(o,29315).
+char(3,29316).
+char(5,29317).
+char(5,29318).
+char(6,29319).
+char(c,29320).
+char(c,29321).
+char(p,29322).
+char(o,29323).
+char(p,29324).
+char(o,29325).
+char(p,29326).
+char(o,29327).
+char(p,29328).
+char(o,29329).
+char(m,29330).
+char(o,29331).
+char(2,29332).
+char(3,29333).
+char(4,29334).
+char(8,29335).
+char(p,29336).
+char(o,29337).
+char(p,29338).
+char(7,29339).
+char(5,29340).
+char(8,29341).
+char(c,29342).
+char(p,29343).
+char(6,29344).
+char(0,29345).
+char(5,29346).
+char(m,29347).
+char(7,29348).
+char(5,29349).
+char(1,29350).
+char(7,29351).
+char(c,29352).
+char(p,29353).
+char(o,29354).
+char(p,29355).
+char(o,29356).
+char(p,29357).
+char(7,29358).
+char(6,29359).
+char(6,29360).
+char(7,29361).
+char(p,29362).
+char(o,29363).
+char(p,29364).
+char(o,29365).
+char(m,29366).
+char(o,29367).
+char(m,29368).
+char(4,29369).
+char(1,29370).
+char(5,29371).
+char(1,29372).
+char(c,29373).
+char(c,29374).
+char(c,29375).
+char(p,29376).
+char(9,29377).
+char(6,29378).
+char(8,29379).
+char(3,29380).
+char(m,29381).
+char(o,29382).
+char(m,29383).
+char(o,29384).
+char(p,29385).
+char(o,29386).
+char(m,29387).
+char(o,29388).
+char(m,29389).
+char(o,29390).
+char(p,29391).
+char(o,29392).
+char(3,29393).
+char(6,29394).
+char(5,29395).
+char(7,29396).
+char(p,29397).
+char(2,29398).
+char(7,29399).
+char(9,29400).
+char(2,29401).
+char(p,29402).
+char(o,29403).
+char(o,29404).
+char(4,29405).
+char(2,29406).
+char(9,29407).
+char(7,29408).
+char(m,29409).
+char(o,29410).
+char(7,29411).
+char(8,29412).
+char(0,29413).
+char(3,29414).
+char(c,29415).
+char(c,29416).
+char(c,29417).
+char(m,29418).
+char(o,29419).
+char(o,29420).
+char(4,29421).
+char(6,29422).
+char(9,29423).
+char(9,29424).
+char(c,29425).
+char(c,29426).
+char(p,29427).
+char(8,29428).
+char(4,29429).
+char(3,29430).
+char(6,29431).
+char(c,29432).
+char(c,29433).
+char(m,29434).
+char(o,29435).
+char(o,29436).
+char(o,29437).
+char(p,29438).
+char(7,29439).
+char(7,29440).
+char(2,29441).
+char(2,29442).
+char(p,29443).
+char(3,29444).
+char(6,29445).
+char(0,29446).
+char(0,29447).
+char(c,29448).
+char(m,29449).
+char(8,29450).
+char(8,29451).
+char(8,29452).
+char(3,29453).
+char(c,29454).
+char(c,29455).
+char(c,29456).
+char(c,29457).
+char(m,29458).
+char(4,29459).
+char(4,29460).
+char(8,29461).
+char(7,29462).
+char(p,29463).
+char(7,29464).
+char(p,29465).
+char(o,29466).
+char(o,29467).
+char(m,29468).
+char(o,29469).
+char(p,29470).
+char(o,29471).
+char(p,29472).
+char(2,29473).
+char(2,29474).
+char(5,29475).
+char(2,29476).
+char(m,29477).
+char(o,29478).
+char(p,29479).
+char(o,29480).
+char(o,29481).
+char(p,29482).
+char(o,29483).
+char(m,29484).
+char(6,29485).
+char(5,29486).
+char(0,29487).
+char(6,29488).
+char(m,29489).
+char(4,29490).
+char(4,29491).
+char(9,29492).
+char(7,29493).
+char(p,29494).
+char(9,29495).
+char(6,29496).
+char(3,29497).
+char(6,29498).
+char(c,29499).
+char(p,29500).
+char(o,29501).
+char(m,29502).
+char(3,29503).
+char(6,29504).
+char(4,29505).
+char(1,29506).
+char(c,29507).
+char(c,29508).
+char(m,29509).
+char(o,29510).
+char(m,29511).
+char(o,29512).
+char(3,29513).
+char(5,29514).
+char(0,29515).
+char(8,29516).
+char(p,29517).
+char(o,29518).
+char(5,29519).
+char(5,29520).
+char(4,29521).
+char(5,29522).
+char(p,29523).
+char(4,29524).
+char(6,29525).
+char(4,29526).
+char(0,29527).
+char(p,29528).
+char(7,29529).
+char(6,29530).
+char(2,29531).
+char(c,29532).
+char(p,29533).
+char(o,29534).
+char(6,29535).
+char(c,29536).
+char(p,29537).
+char(7,29538).
+char(1,29539).
+char(1,29540).
+char(p,29541).
+char(o,29542).
+char(1,29543).
+char(1,29544).
+char(1,29545).
+char(0,29546).
+char(p,29547).
+char(o,29548).
+char(p,29549).
+char(o,29550).
+char(p,29551).
+char(6,29552).
+char(4,29553).
+char(3,29554).
+char(4,29555).
+char(m,29556).
+char(o,29557).
+char(9,29558).
+char(8,29559).
+char(8,29560).
+char(3,29561).
+char(c,29562).
+char(p,29563).
+char(o,29564).
+char(o,29565).
+char(m,29566).
+char(o,29567).
+char(p,29568).
+char(7,29569).
+char(4,29570).
+char(6,29571).
+char(5,29572).
+char(c,29573).
+char(p,29574).
+char(4,29575).
+char(1,29576).
+char(3,29577).
+char(2,29578).
+char(p,29579).
+char(3,29580).
+char(0,29581).
+char(5,29582).
+char(3,29583).
+char(p,29584).
+char(o,29585).
+char(o,29586).
+char(m,29587).
+char(4,29588).
+char(3,29589).
+char(9,29590).
+char(9,29591).
+char(c,29592).
+char(p,29593).
+char(5,29594).
+char(6,29595).
+char(6,29596).
+char(6,29597).
+char(m,29598).
+char(5,29599).
+char(6,29600).
+char(8,29601).
+char(0,29602).
+char(p,29603).
+char(o,29604).
+char(m,29605).
+char(1,29606).
+char(2,29607).
+char(4,29608).
+char(6,29609).
+char(c,29610).
+char(c,29611).
+char(p,29612).
+char(8,29613).
+char(6,29614).
+char(7,29615).
+char(m,29616).
+char(8,29617).
+char(2,29618).
+char(8,29619).
+char(9,29620).
+char(c,29621).
+char(p,29622).
+char(o,29623).
+char(m,29624).
+char(4,29625).
+char(9,29626).
+char(6,29627).
+char(3,29628).
+char(p,29629).
+char(9,29630).
+char(2,29631).
+char(1,29632).
+char(8,29633).
+char(c,29634).
+char(m,29635).
+char(o,29636).
+char(o,29637).
+char(p,29638).
+char(o,29639).
+char(p,29640).
+char(5,29641).
+char(4,29642).
+char(7,29643).
+char(c,29644).
+char(c,29645).
+char(c,29646).
+char(c,29647).
+char(m,29648).
+char(5,29649).
+char(5,29650).
+char(1,29651).
+char(6,29652).
+char(c,29653).
+char(c,29654).
+char(m,29655).
+char(o,29656).
+char(o,29657).
+char(o,29658).
+char(m,29659).
+char(2,29660).
+char(0,29661).
+char(7,29662).
+char(2,29663).
+char(m,29664).
+char(o,29665).
+char(m,29666).
+char(o,29667).
+char(8,29668).
+char(0,29669).
+char(5,29670).
+char(3,29671).
+char(c,29672).
+char(c,29673).
+char(m,29674).
+char(7,29675).
+char(5,29676).
+char(1,29677).
+char(0,29678).
+char(c,29679).
+char(m,29680).
+char(o,29681).
+char(5,29682).
+char(8,29683).
+char(0,29684).
+char(4,29685).
+char(c,29686).
+char(c,29687).
+char(m,29688).
+char(o,29689).
+char(m,29690).
+char(6,29691).
+char(1,29692).
+char(1,29693).
+char(5,29694).
+char(m,29695).
+char(o,29696).
+char(p,29697).
+char(3,29698).
+char(8,29699).
+char(7,29700).
+char(3,29701).
+char(m,29702).
+char(o,29703).
+char(p,29704).
+char(o,29705).
+char(p,29706).
+char(o,29707).
+char(p,29708).
+char(o,29709).
+char(m,29710).
+char(3,29711).
+char(0,29712).
+char(7,29713).
+char(1,29714).
+char(c,29715).
+char(c,29716).
+char(p,29717).
+char(4,29718).
+char(0,29719).
+char(3,29720).
+char(4,29721).
+char(m,29722).
+char(6,29723).
+char(1,29724).
+char(3,29725).
+char(5,29726).
+char(m,29727).
+char(o,29728).
+char(p,29729).
+char(o,29730).
+char(o,29731).
+char(m,29732).
+char(5,29733).
+char(0,29734).
+char(7,29735).
+char(5,29736).
+char(m,29737).
+char(o,29738).
+char(p,29739).
+char(9,29740).
+char(2,29741).
+char(0,29742).
+char(4,29743).
+char(p,29744).
+char(o,29745).
+char(m,29746).
+char(7,29747).
+char(8,29748).
+char(9,29749).
+char(4,29750).
+char(c,29751).
+char(c,29752).
+char(c,29753).
+char(m,29754).
+char(1,29755).
+char(1,29756).
+char(6,29757).
+char(3,29758).
+char(c,29759).
+char(c,29760).
+char(p,29761).
+char(2,29762).
+char(3,29763).
+char(5,29764).
+char(6,29765).
+char(m,29766).
+char(7,29767).
+char(9,29768).
+char(4,29769).
+char(3,29770).
+char(c,29771).
+char(c,29772).
+char(c,29773).
+char(c,29774).
+char(c,29775).
+char(m,29776).
+char(o,29777).
+char(m,29778).
+char(2,29779).
+char(6,29780).
+char(m,29781).
+char(3,29782).
+char(1,29783).
+char(8,29784).
+char(9,29785).
+char(p,29786).
+char(o,29787).
+char(p,29788).
+char(3,29789).
+char(5,29790).
+char(6,29791).
+char(1,29792).
+char(p,29793).
+char(o,29794).
+char(p,29795).
+char(4,29796).
+char(0,29797).
+char(3,29798).
+char(7,29799).
+char(c,29800).
+char(c,29801).
+char(c,29802).
+char(c,29803).
+char(m,29804).
+char(o,29805).
+char(1,29806).
+char(8,29807).
+char(4,29808).
+char(0,29809).
+char(m,29810).
+char(o,29811).
+char(p,29812).
+char(2,29813).
+char(1,29814).
+char(m,29815).
+char(4,29816).
+char(8,29817).
+char(9,29818).
+char(5,29819).
+char(m,29820).
+char(4,29821).
+char(9,29822).
+char(8,29823).
+char(1,29824).
+char(c,29825).
+char(p,29826).
+char(o,29827).
+char(m,29828).
+char(5,29829).
+char(9,29830).
+char(9,29831).
+char(1,29832).
+char(p,29833).
+char(2,29834).
+char(9,29835).
+char(4,29836).
+char(8,29837).
+char(p,29838).
+char(3,29839).
+char(5,29840).
+char(7,29841).
+char(8,29842).
+char(p,29843).
+char(1,29844).
+char(4,29845).
+char(4,29846).
+char(c,29847).
+char(c,29848).
+char(p,29849).
+char(o,29850).
+char(p,29851).
+char(o,29852).
+char(m,29853).
+char(o,29854).
+char(m,29855).
+char(o,29856).
+char(5,29857).
+char(1,29858).
+char(7,29859).
+char(c,29860).
+char(c,29861).
+char(c,29862).
+char(c,29863).
+char(c,29864).
+char(m,29865).
+char(o,29866).
+char(p,29867).
+char(o,29868).
+char(6,29869).
+char(3,29870).
+char(8,29871).
+char(9,29872).
+char(c,29873).
+char(c,29874).
+char(c,29875).
+char(c,29876).
+char(c,29877).
+char(m,29878).
+char(o,29879).
+char(p,29880).
+char(9,29881).
+char(4,29882).
+char(4,29883).
+char(2,29884).
+char(m,29885).
+char(o,29886).
+char(2,29887).
+char(1,29888).
+char(0,29889).
+char(6,29890).
+char(m,29891).
+char(o,29892).
+char(p,29893).
+char(5,29894).
+char(9,29895).
+char(5,29896).
+char(3,29897).
+char(c,29898).
+char(c,29899).
+char(p,29900).
+char(o,29901).
+char(m,29902).
+char(1,29903).
+char(3,29904).
+char(2,29905).
+char(5,29906).
+char(p,29907).
+char(o,29908).
+char(2,29909).
+char(5,29910).
+char(8,29911).
+char(c,29912).
+char(c,29913).
+char(m,29914).
+char(o,29915).
+char(m,29916).
+char(o,29917).
+char(p,29918).
+char(4,29919).
+char(5,29920).
+char(2,29921).
+char(5,29922).
+char(c,29923).
+char(c,29924).
+char(m,29925).
+char(o,29926).
+char(m,29927).
+char(9,29928).
+char(4,29929).
+char(2,29930).
+char(8,29931).
+char(c,29932).
+char(c,29933).
+char(c,29934).
+char(m,29935).
+char(o,29936).
+char(1,29937).
+char(4,29938).
+char(1,29939).
+char(4,29940).
+char(c,29941).
+char(m,29942).
+char(o,29943).
+char(p,29944).
+char(2,29945).
+char(7,29946).
+char(8,29947).
+char(1,29948).
+char(c,29949).
+char(c,29950).
+char(c,29951).
+char(c,29952).
+char(c,29953).
+char(p,29954).
+char(7,29955).
+char(8,29956).
+char(2,29957).
+char(2,29958).
+char(p,29959).
+char(o,29960).
+char(m,29961).
+char(3,29962).
+char(4,29963).
+char(5,29964).
+char(0,29965).
+char(p,29966).
+char(2,29967).
+char(9,29968).
+char(4,29969).
+char(3,29970).
+char(c,29971).
+char(c,29972).
+char(c,29973).
+char(p,29974).
+char(o,29975).
+char(m,29976).
+char(o,29977).
+char(m,29978).
+char(4,29979).
+char(8,29980).
+char(9,29981).
+char(4,29982).
+char(p,29983).
+char(o,29984).
+char(1,29985).
+char(7,29986).
+char(5,29987).
+char(5,29988).
+char(c,29989).
+char(m,29990).
+char(o,29991).
+char(p,29992).
+char(2,29993).
+char(6,29994).
+char(4,29995).
+char(0,29996).
+char(m,29997).
+char(o,29998).
+char(p,29999).
+char(o,30000).
+char(3,30001).
+char(2,30002).
+char(7,30003).
+char(8,30004).
+char(c,30005).
+char(c,30006).
+char(m,30007).
+char(2,30008).
+char(0,30009).
+char(3,30010).
+char(7,30011).
+char(p,30012).
+char(6,30013).
+char(3,30014).
+char(1,30015).
+char(c,30016).
+char(m,30017).
+char(9,30018).
+char(8,30019).
+char(6,30020).
+char(0,30021).
+char(c,30022).
+char(c,30023).
+char(m,30024).
+char(o,30025).
+char(m,30026).
+char(1,30027).
+char(3,30028).
+char(8,30029).
+char(8,30030).
+char(c,30031).
+char(p,30032).
+char(o,30033).
+char(m,30034).
+char(4,30035).
+char(1,30036).
+char(0,30037).
+char(5,30038).
+char(m,30039).
+char(1,30040).
+char(4,30041).
+char(2,30042).
+char(0,30043).
+char(c,30044).
+char(m,30045).
+char(o,30046).
+char(p,30047).
+char(3,30048).
+char(7,30049).
+char(5,30050).
+char(m,30051).
+char(o,30052).
+char(8,30053).
+char(2,30054).
+char(2,30055).
+char(8,30056).
+char(c,30057).
+char(p,30058).
+char(o,30059).
+char(p,30060).
+char(6,30061).
+char(9,30062).
+char(8,30063).
+char(8,30064).
+char(p,30065).
+char(9,30066).
+char(4,30067).
+char(7,30068).
+char(4,30069).
+char(c,30070).
+char(c,30071).
+char(p,30072).
+char(o,30073).
+char(3,30074).
+char(6,30075).
+char(c,30076).
+char(m,30077).
+char(o,30078).
+char(4,30079).
+char(2,30080).
+char(5,30081).
+char(8,30082).
+char(p,30083).
+char(4,30084).
+char(5,30085).
+char(5,30086).
+char(9,30087).
+char(p,30088).
+char(o,30089).
+char(m,30090).
+char(9,30091).
+char(9,30092).
+char(3,30093).
+char(9,30094).
+char(m,30095).
+char(o,30096).
+char(1,30097).
+char(6,30098).
+char(4,30099).
+char(2,30100).
+char(m,30101).
+char(o,30102).
+char(o,30103).
+char(2,30104).
+char(8,30105).
+char(8,30106).
+char(6,30107).
+char(c,30108).
+char(c,30109).
+char(c,30110).
+char(m,30111).
+char(8,30112).
+char(4,30113).
+char(4,30114).
+char(m,30115).
+char(o,30116).
+char(m,30117).
+char(3,30118).
+char(2,30119).
+char(9,30120).
+char(4,30121).
+char(p,30122).
+char(o,30123).
+char(o,30124).
+char(m,30125).
+char(o,30126).
+char(m,30127).
+char(1,30128).
+char(5,30129).
+char(0,30130).
+char(2,30131).
+char(c,30132).
+char(m,30133).
+char(o,30134).
+char(p,30135).
+char(o,30136).
+char(6,30137).
+char(0,30138).
+char(7,30139).
+char(9,30140).
+char(c,30141).
+char(c,30142).
+char(p,30143).
+char(9,30144).
+char(9,30145).
+char(8,30146).
+char(0,30147).
+char(m,30148).
+char(o,30149).
+char(p,30150).
+char(o,30151).
+char(m,30152).
+char(8,30153).
+char(4,30154).
+char(7,30155).
+char(5,30156).
+char(c,30157).
+char(c,30158).
+char(p,30159).
+char(1,30160).
+char(9,30161).
+char(2,30162).
+char(7,30163).
+char(p,30164).
+char(4,30165).
+char(4,30166).
+char(6,30167).
+char(m,30168).
+char(9,30169).
+char(0,30170).
+char(3,30171).
+char(2,30172).
+char(p,30173).
+char(o,30174).
+char(o,30175).
+char(m,30176).
+char(6,30177).
+char(5,30178).
+char(4,30179).
+char(0,30180).
+char(c,30181).
+char(c,30182).
+char(p,30183).
+char(o,30184).
+char(m,30185).
+char(o,30186).
+char(m,30187).
+char(o,30188).
+char(o,30189).
+char(4,30190).
+char(0,30191).
+char(1,30192).
+char(c,30193).
+char(p,30194).
+char(o,30195).
+char(p,30196).
+char(9,30197).
+char(0,30198).
+char(0,30199).
+char(3,30200).
+char(m,30201).
+char(4,30202).
+char(1,30203).
+char(5,30204).
+char(4,30205).
+char(c,30206).
+char(m,30207).
+char(o,30208).
+char(m,30209).
+char(o,30210).
+char(p,30211).
+char(7,30212).
+char(2,30213).
+char(3,30214).
+char(8,30215).
+char(m,30216).
+char(o,30217).
+char(p,30218).
+char(1,30219).
+char(0,30220).
+char(3,30221).
+char(8,30222).
+char(m,30223).
+char(6,30224).
+char(9,30225).
+char(3,30226).
+char(0,30227).
+char(c,30228).
+char(p,30229).
+char(o,30230).
+char(2,30231).
+char(5,30232).
+char(5,30233).
+char(m,30234).
+char(o,30235).
+char(m,30236).
+char(2,30237).
+char(4,30238).
+char(9,30239).
+char(4,30240).
+char(m,30241).
+char(o,30242).
+char(m,30243).
+char(5,30244).
+char(4,30245).
+char(7,30246).
+char(c,30247).
+char(c,30248).
+char(c,30249).
+char(c,30250).
+char(p,30251).
+char(7,30252).
+char(3,30253).
+char(8,30254).
+char(9,30255).
+char(p,30256).
+char(4,30257).
+char(8,30258).
+char(3,30259).
+char(4,30260).
+char(p,30261).
+char(1,30262).
+char(7,30263).
+char(4,30264).
+char(1,30265).
+char(m,30266).
+char(o,30267).
+char(m,30268).
+char(o,30269).
+char(m,30270).
+char(o,30271).
+char(m,30272).
+char(o,30273).
+char(m,30274).
+char(o,30275).
+char(p,30276).
+char(6,30277).
+char(2,30278).
+char(9,30279).
+char(0,30280).
+char(c,30281).
+char(c,30282).
+char(p,30283).
+char(o,30284).
+char(m,30285).
+char(7,30286).
+char(4,30287).
+char(8,30288).
+char(4,30289).
+char(m,30290).
+char(3,30291).
+char(2,30292).
+char(6,30293).
+char(9,30294).
+char(m,30295).
+char(o,30296).
+char(p,30297).
+char(2,30298).
+char(6,30299).
+char(7,30300).
+char(m,30301).
+char(o,30302).
+char(o,30303).
+char(p,30304).
+char(o,30305).
+char(p,30306).
+char(1,30307).
+char(9,30308).
+char(6,30309).
+char(9,30310).
+char(c,30311).
+char(c,30312).
+char(c,30313).
+char(c,30314).
+char(m,30315).
+char(o,30316).
+char(m,30317).
+char(o,30318).
+char(p,30319).
+char(o,30320).
+char(m,30321).
+char(2,30322).
+char(6,30323).
+char(3,30324).
+char(1,30325).
+char(c,30326).
+char(m,30327).
+char(1,30328).
+char(8,30329).
+char(9,30330).
+char(7,30331).
+char(p,30332).
+char(o,30333).
+char(5,30334).
+char(3,30335).
+char(6,30336).
+char(0,30337).
+char(c,30338).
+char(p,30339).
+char(o,30340).
+char(o,30341).
+char(o,30342).
+char(p,30343).
+char(1,30344).
+char(5,30345).
+char(5,30346).
+char(7,30347).
+char(p,30348).
+char(o,30349).
+char(p,30350).
+char(2,30351).
+char(6,30352).
+char(5,30353).
+char(4,30354).
+char(m,30355).
+char(2,30356).
+char(8,30357).
+char(4,30358).
+char(6,30359).
+char(c,30360).
+char(c,30361).
+char(c,30362).
+char(p,30363).
+char(6,30364).
+char(1,30365).
+char(7,30366).
+char(3,30367).
+char(c,30368).
+char(c,30369).
+char(c,30370).
+char(c,30371).
+char(m,30372).
+char(o,30373).
+char(m,30374).
+char(8,30375).
+char(8,30376).
+char(2,30377).
+char(8,30378).
+char(m,30379).
+char(4,30380).
+char(4,30381).
+char(7,30382).
+char(5,30383).
+char(p,30384).
+char(6,30385).
+char(6,30386).
+char(6,30387).
+char(9,30388).
+char(p,30389).
+char(8,30390).
+char(8,30391).
+char(1,30392).
+char(p,30393).
+char(6,30394).
+char(9,30395).
+char(5,30396).
+char(6,30397).
+char(m,30398).
+char(o,30399).
+char(m,30400).
+char(o,30401).
+char(o,30402).
+char(1,30403).
+char(6,30404).
+char(1,30405).
+char(1,30406).
+char(p,30407).
+char(o,30408).
+char(m,30409).
+char(o,30410).
+char(m,30411).
+char(4,30412).
+char(4,30413).
+char(1,30414).
+char(c,30415).
+char(p,30416).
+char(8,30417).
+char(8,30418).
+char(6,30419).
+char(2,30420).
+char(m,30421).
+char(o,30422).
+char(o,30423).
+char(p,30424).
+char(4,30425).
+char(2,30426).
+char(8,30427).
+char(m,30428).
+char(8,30429).
+char(1,30430).
+char(8,30431).
+char(3,30432).
+char(c,30433).
+char(c,30434).
+char(c,30435).
+char(c,30436).
+char(p,30437).
+char(4,30438).
+char(7,30439).
+char(7,30440).
+char(1,30441).
+char(c,30442).
+char(c,30443).
+char(m,30444).
+char(o,30445).
+char(p,30446).
+char(6,30447).
+char(2,30448).
+char(5,30449).
+char(4,30450).
+char(c,30451).
+char(m,30452).
+char(1,30453).
+char(6,30454).
+char(1,30455).
+char(4,30456).
+char(c,30457).
+char(c,30458).
+char(m,30459).
+char(4,30460).
+char(8,30461).
+char(2,30462).
+char(7,30463).
+char(c,30464).
+char(m,30465).
+char(o,30466).
+char(p,30467).
+char(4,30468).
+char(1,30469).
+char(5,30470).
+char(6,30471).
+char(c,30472).
+char(c,30473).
+char(p,30474).
+char(7,30475).
+char(0,30476).
+char(0,30477).
+char(5,30478).
+char(c,30479).
+char(p,30480).
+char(7,30481).
+char(3,30482).
+char(4,30483).
+char(6,30484).
+char(c,30485).
+char(c,30486).
+char(c,30487).
+char(c,30488).
+char(c,30489).
+char(c,30490).
+char(p,30491).
+char(6,30492).
+char(7,30493).
+char(3,30494).
+char(6,30495).
+char(p,30496).
+char(9,30497).
+char(1,30498).
+char(1,30499).
+char(2,30500).
+char(c,30501).
+char(p,30502).
+char(2,30503).
+char(6,30504).
+char(3,30505).
+char(4,30506).
+char(c,30507).
+char(c,30508).
+char(c,30509).
+char(p,30510).
+char(4,30511).
+char(5,30512).
+char(7,30513).
+char(7,30514).
+char(p,30515).
+char(2,30516).
+char(5,30517).
+char(2,30518).
+char(p,30519).
+char(2,30520).
+char(8,30521).
+char(6,30522).
+char(c,30523).
+char(p,30524).
+char(o,30525).
+char(p,30526).
+char(1,30527).
+char(4,30528).
+char(7,30529).
+char(9,30530).
+char(c,30531).
+char(m,30532).
+char(9,30533).
+char(5,30534).
+char(4,30535).
+char(7,30536).
+char(p,30537).
+char(o,30538).
+char(9,30539).
+char(8,30540).
+char(0,30541).
+char(9,30542).
+char(m,30543).
+char(o,30544).
+char(m,30545).
+char(9,30546).
+char(8,30547).
+char(8,30548).
+char(4,30549).
+char(p,30550).
+char(8,30551).
+char(8,30552).
+char(3,30553).
+char(5,30554).
+char(c,30555).
+char(m,30556).
+char(o,30557).
+char(p,30558).
+char(o,30559).
+char(p,30560).
+char(o,30561).
+char(3,30562).
+char(2,30563).
+char(7,30564).
+char(0,30565).
+char(c,30566).
+char(p,30567).
+char(o,30568).
+char(p,30569).
+char(2,30570).
+char(2,30571).
+char(8,30572).
+char(4,30573).
+char(c,30574).
+char(c,30575).
+char(m,30576).
+char(o,30577).
+char(m,30578).
+char(o,30579).
+char(1,30580).
+char(2,30581).
+char(8,30582).
+char(8,30583).
+char(p,30584).
+char(o,30585).
+char(m,30586).
+char(o,30587).
+char(p,30588).
+char(1,30589).
+char(2,30590).
+char(2,30591).
+char(6,30592).
+char(c,30593).
+char(p,30594).
+char(5,30595).
+char(9,30596).
+char(8,30597).
+char(3,30598).
+char(p,30599).
+char(o,30600).
+char(p,30601).
+char(o,30602).
+char(m,30603).
+char(6,30604).
+char(6,30605).
+char(2,30606).
+char(0,30607).
+char(c,30608).
+char(c,30609).
+char(c,30610).
+char(m,30611).
+char(3,30612).
+char(4,30613).
+char(8,30614).
+char(4,30615).
+char(p,30616).
+char(o,30617).
+char(5,30618).
+char(8,30619).
+char(9,30620).
+char(2,30621).
+char(c,30622).
+char(c,30623).
+char(m,30624).
+char(o,30625).
+char(p,30626).
+char(o,30627).
+char(o,30628).
+char(m,30629).
+char(2,30630).
+char(8,30631).
+char(5,30632).
+char(2,30633).
+char(p,30634).
+char(o,30635).
+char(m,30636).
+char(8,30637).
+char(5,30638).
+char(6,30639).
+char(5,30640).
+char(c,30641).
+char(c,30642).
+char(c,30643).
+char(c,30644).
+char(p,30645).
+char(o,30646).
+char(o,30647).
+char(m,30648).
+char(o,30649).
+char(p,30650).
+char(1,30651).
+char(2,30652).
+char(2,30653).
+char(9,30654).
+char(m,30655).
+char(o,30656).
+char(p,30657).
+char(5,30658).
+char(0,30659).
+char(4,30660).
+char(0,30661).
+char(c,30662).
+char(c,30663).
+char(c,30664).
+char(c,30665).
+char(m,30666).
+char(2,30667).
+char(5,30668).
+char(0,30669).
+char(p,30670).
+char(8,30671).
+char(4,30672).
+char(9,30673).
+char(7,30674).
+char(c,30675).
+char(c,30676).
+char(c,30677).
+char(m,30678).
+char(o,30679).
+char(o,30680).
+char(p,30681).
+char(o,30682).
+char(m,30683).
+char(o,30684).
+char(m,30685).
+char(6,30686).
+char(4,30687).
+char(0,30688).
+char(6,30689).
+char(p,30690).
+char(o,30691).
+char(p,30692).
+char(o,30693).
+char(m,30694).
+char(3,30695).
+char(7,30696).
+char(0,30697).
+char(8,30698).
+char(p,30699).
+char(o,30700).
+char(m,30701).
+char(o,30702).
+char(o,30703).
+char(p,30704).
+char(8,30705).
+char(0,30706).
+char(1,30707).
+char(7,30708).
+char(m,30709).
+char(6,30710).
+char(3,30711).
+char(0,30712).
+char(p,30713).
+char(o,30714).
+char(m,30715).
+char(o,30716).
+char(p,30717).
+char(o,30718).
+char(p,30719).
+char(o,30720).
+char(o,30721).
+char(p,30722).
+char(o,30723).
+char(p,30724).
+char(5,30725).
+char(3,30726).
+char(9,30727).
+char(1,30728).
+char(p,30729).
+char(6,30730).
+char(4,30731).
+char(9,30732).
+char(p,30733).
+char(9,30734).
+char(2,30735).
+char(6,30736).
+char(0,30737).
+char(m,30738).
+char(o,30739).
+char(m,30740).
+char(o,30741).
+char(8,30742).
+char(4,30743).
+char(4,30744).
+char(1,30745).
+char(p,30746).
+char(o,30747).
+char(p,30748).
+char(o,30749).
+char(o,30750).
+char(p,30751).
+char(o,30752).
+char(o,30753).
+char(p,30754).
+char(o,30755).
+char(m,30756).
+char(3,30757).
+char(2,30758).
+char(8,30759).
+char(5,30760).
+char(c,30761).
+char(p,30762).
+char(2,30763).
+char(6,30764).
+char(3,30765).
+char(9,30766).
+char(m,30767).
+char(o,30768).
+char(p,30769).
+char(5,30770).
+char(5,30771).
+char(0,30772).
+char(3,30773).
+char(c,30774).
+char(c,30775).
+char(c,30776).
+char(c,30777).
+char(m,30778).
+char(6,30779).
+char(7,30780).
+char(9,30781).
+char(8,30782).
+char(p,30783).
+char(o,30784).
+char(p,30785).
+char(1,30786).
+char(5,30787).
+char(9,30788).
+char(m,30789).
+char(3,30790).
+char(1,30791).
+char(6,30792).
+char(8,30793).
+char(c,30794).
+char(c,30795).
+char(c,30796).
+char(m,30797).
+char(2,30798).
+char(0,30799).
+char(3,30800).
+char(6,30801).
+char(c,30802).
+char(c,30803).
+char(c,30804).
+char(m,30805).
+char(o,30806).
+char(o,30807).
+char(1,30808).
+char(4,30809).
+char(8,30810).
+char(4,30811).
+char(p,30812).
+char(4,30813).
+char(0,30814).
+char(9,30815).
+char(8,30816).
+char(p,30817).
+char(4,30818).
+char(7,30819).
+char(3,30820).
+char(c,30821).
+char(p,30822).
+char(8,30823).
+char(0,30824).
+char(4,30825).
+char(8,30826).
+char(m,30827).
+char(1,30828).
+char(0,30829).
+char(8,30830).
+char(3,30831).
+char(c,30832).
+char(c,30833).
+char(p,30834).
+char(6,30835).
+char(2,30836).
+char(9,30837).
+char(3,30838).
+char(c,30839).
+char(p,30840).
+char(6,30841).
+char(4,30842).
+char(6,30843).
+char(4,30844).
+char(c,30845).
+char(p,30846).
+char(o,30847).
+char(p,30848).
+char(o,30849).
+char(m,30850).
+char(o,30851).
+char(8,30852).
+char(8,30853).
+char(5,30854).
+char(2,30855).
+char(c,30856).
+char(m,30857).
+char(o,30858).
+char(p,30859).
+char(9,30860).
+char(2,30861).
+char(6,30862).
+char(9,30863).
+char(c,30864).
+char(c,30865).
+char(m,30866).
+char(o,30867).
+char(m,30868).
+char(2,30869).
+char(7,30870).
+char(3,30871).
+char(6,30872).
+char(m,30873).
+char(2,30874).
+char(6,30875).
+char(5,30876).
+char(1,30877).
+char(m,30878).
+char(o,30879).
+char(o,30880).
+char(o,30881).
+char(9,30882).
+char(8,30883).
+char(5,30884).
+char(8,30885).
+char(c,30886).
+char(c,30887).
+char(p,30888).
+char(o,30889).
+char(m,30890).
+char(6,30891).
+char(1,30892).
+char(5,30893).
+char(c,30894).
+char(c,30895).
+char(p,30896).
+char(4,30897).
+char(7,30898).
+char(6,30899).
+char(9,30900).
+char(m,30901).
+char(1,30902).
+char(9,30903).
+char(5,30904).
+char(0,30905).
+char(c,30906).
+char(p,30907).
+char(9,30908).
+char(2,30909).
+char(9,30910).
+char(c,30911).
+char(c,30912).
+char(c,30913).
+char(m,30914).
+char(6,30915).
+char(4,30916).
+char(7,30917).
+char(4,30918).
+char(p,30919).
+char(o,30920).
+char(p,30921).
+char(o,30922).
+char(m,30923).
+char(3,30924).
+char(6,30925).
+char(4,30926).
+char(6,30927).
+char(c,30928).
+char(c,30929).
+char(p,30930).
+char(o,30931).
+char(p,30932).
+char(o,30933).
+char(p,30934).
+char(o,30935).
+char(4,30936).
+char(0,30937).
+char(8,30938).
+char(5,30939).
+char(c,30940).
+char(m,30941).
+char(o,30942).
+char(m,30943).
+char(o,30944).
+char(8,30945).
+char(8,30946).
+char(2,30947).
+char(9,30948).
+char(c,30949).
+char(c,30950).
+char(c,30951).
+char(c,30952).
+char(m,30953).
+char(7,30954).
+char(9,30955).
+char(m,30956).
+char(5,30957).
+char(7,30958).
+char(6,30959).
+char(8,30960).
+char(p,30961).
+char(3,30962).
+char(7,30963).
+char(9,30964).
+char(4,30965).
+char(m,30966).
+char(o,30967).
+char(o,30968).
+char(p,30969).
+char(5,30970).
+char(6,30971).
+char(1,30972).
+char(1,30973).
+char(p,30974).
+char(o,30975).
+char(p,30976).
+char(5,30977).
+char(3,30978).
+char(7,30979).
+char(7,30980).
+char(p,30981).
+char(o,30982).
+char(p,30983).
+char(7,30984).
+char(3,30985).
+char(3,30986).
+char(8,30987).
+char(c,30988).
+char(m,30989).
+char(o,30990).
+char(p,30991).
+char(o,30992).
+char(p,30993).
+char(4,30994).
+char(3,30995).
+char(5,30996).
+char(0,30997).
+char(p,30998).
+char(2,30999).
+char(0,31000).
+char(5,31001).
+char(5,31002).
+char(c,31003).
+char(c,31004).
+char(c,31005).
+char(c,31006).
+char(c,31007).
+char(m,31008).
+char(3,31009).
+char(1,31010).
+char(2,31011).
+char(5,31012).
+char(m,31013).
+char(o,31014).
+char(m,31015).
+char(o,31016).
+char(o,31017).
+char(m,31018).
+char(4,31019).
+char(6,31020).
+char(0,31021).
+char(4,31022).
+char(p,31023).
+char(3,31024).
+char(1,31025).
+char(0,31026).
+char(6,31027).
+char(c,31028).
+char(c,31029).
+char(c,31030).
+char(m,31031).
+char(o,31032).
+char(1,31033).
+char(1,31034).
+char(9,31035).
+char(3,31036).
+char(c,31037).
+char(c,31038).
+char(c,31039).
+char(c,31040).
+char(c,31041).
+char(c,31042).
+char(m,31043).
+char(8,31044).
+char(9,31045).
+char(1,31046).
+char(c,31047).
+char(c,31048).
+char(c,31049).
+char(c,31050).
+char(c,31051).
+char(p,31052).
+char(3,31053).
+char(3,31054).
+char(2,31055).
+char(3,31056).
+char(m,31057).
+char(o,31058).
+char(1,31059).
+char(4,31060).
+char(0,31061).
+char(4,31062).
+char(c,31063).
+char(p,31064).
+char(o,31065).
+char(m,31066).
+char(5,31067).
+char(2,31068).
+char(1,31069).
+char(9,31070).
+char(c,31071).
+char(m,31072).
+char(o,31073).
+char(o,31074).
+char(m,31075).
+char(5,31076).
+char(9,31077).
+char(9,31078).
+char(0,31079).
+char(c,31080).
+char(p,31081).
+char(o,31082).
+char(p,31083).
+char(6,31084).
+char(7,31085).
+char(3,31086).
+char(0,31087).
+char(c,31088).
+char(p,31089).
+char(7,31090).
+char(6,31091).
+char(1,31092).
+char(7,31093).
+char(c,31094).
+char(c,31095).
+char(c,31096).
+char(c,31097).
+char(c,31098).
+char(c,31099).
+char(c,31100).
+char(p,31101).
+char(o,31102).
+char(o,31103).
+char(m,31104).
+char(6,31105).
+char(9,31106).
+char(0,31107).
+char(m,31108).
+char(o,31109).
+char(m,31110).
+char(2,31111).
+char(8,31112).
+char(3,31113).
+char(7,31114).
+char(p,31115).
+char(8,31116).
+char(6,31117).
+char(4,31118).
+char(2,31119).
+char(m,31120).
+char(4,31121).
+char(8,31122).
+char(9,31123).
+char(3,31124).
+char(c,31125).
+char(m,31126).
+char(o,31127).
+char(p,31128).
+char(7,31129).
+char(2,31130).
+char(7,31131).
+char(5,31132).
+char(m,31133).
+char(o,31134).
+char(o,31135).
+char(p,31136).
+char(8,31137).
+char(3,31138).
+char(7,31139).
+char(4,31140).
+char(m,31141).
+char(2,31142).
+char(0,31143).
+char(4,31144).
+char(7,31145).
+char(p,31146).
+char(o,31147).
+char(p,31148).
+char(o,31149).
+char(p,31150).
+char(o,31151).
+char(6,31152).
+char(9,31153).
+char(9,31154).
+char(6,31155).
+char(p,31156).
+char(o,31157).
+char(p,31158).
+char(o,31159).
+char(1,31160).
+char(1,31161).
+char(1,31162).
+char(2,31163).
+char(m,31164).
+char(o,31165).
+char(p,31166).
+char(7,31167).
+char(6,31168).
+char(3,31169).
+char(6,31170).
+char(c,31171).
+char(c,31172).
+char(m,31173).
+char(o,31174).
+char(o,31175).
+char(p,31176).
+char(9,31177).
+char(8,31178).
+char(6,31179).
+char(1,31180).
+char(p,31181).
+char(5,31182).
+char(1,31183).
+char(9,31184).
+char(7,31185).
+char(m,31186).
+char(o,31187).
+char(1,31188).
+char(6,31189).
+char(5,31190).
+char(2,31191).
+char(m,31192).
+char(o,31193).
+char(m,31194).
+char(o,31195).
+char(o,31196).
+char(p,31197).
+char(2,31198).
+char(5,31199).
+char(7,31200).
+char(2,31201).
+char(p,31202).
+char(o,31203).
+char(o,31204).
+char(8,31205).
+char(0,31206).
+char(0,31207).
+char(6,31208).
+char(c,31209).
+char(p,31210).
+char(o,31211).
+char(p,31212).
+char(o,31213).
+char(p,31214).
+char(1,31215).
+char(0,31216).
+char(4,31217).
+char(9,31218).
+char(c,31219).
+char(c,31220).
+char(c,31221).
+char(p,31222).
+char(o,31223).
+char(p,31224).
+char(5,31225).
+char(9,31226).
+char(2,31227).
+char(5,31228).
+char(c,31229).
+char(m,31230).
+char(o,31231).
+char(m,31232).
+char(o,31233).
+char(m,31234).
+char(8,31235).
+char(5,31236).
+char(5,31237).
+char(m,31238).
+char(4,31239).
+char(8,31240).
+char(1,31241).
+char(8,31242).
+char(c,31243).
+char(p,31244).
+char(9,31245).
+char(7,31246).
+char(5,31247).
+char(7,31248).
+char(c,31249).
+char(m,31250).
+char(o,31251).
+char(p,31252).
+char(5,31253).
+char(1,31254).
+char(5,31255).
+char(p,31256).
+char(o,31257).
+char(9,31258).
+char(8,31259).
+char(3,31260).
+char(2,31261).
+char(c,31262).
+char(c,31263).
+char(m,31264).
+char(o,31265).
+char(m,31266).
+char(8,31267).
+char(3,31268).
+char(3,31269).
+char(8,31270).
+char(m,31271).
+char(o,31272).
+char(2,31273).
+char(8,31274).
+char(6,31275).
+char(9,31276).
+char(m,31277).
+char(o,31278).
+char(m,31279).
+char(5,31280).
+char(7,31281).
+char(1,31282).
+char(5,31283).
+char(m,31284).
+char(7,31285).
+char(2,31286).
+char(7,31287).
+char(3,31288).
+char(c,31289).
+char(p,31290).
+char(o,31291).
+char(o,31292).
+char(o,31293).
+char(9,31294).
+char(5,31295).
+char(1,31296).
+char(6,31297).
+char(c,31298).
+char(m,31299).
+char(o,31300).
+char(m,31301).
+char(o,31302).
+char(o,31303).
+char(p,31304).
+char(7,31305).
+char(4,31306).
+char(5,31307).
+char(3,31308).
+char(m,31309).
+char(4,31310).
+char(6,31311).
+char(8,31312).
+char(7,31313).
+char(c,31314).
+char(c,31315).
+char(c,31316).
+char(m,31317).
+char(o,31318).
+char(m,31319).
+char(o,31320).
+char(m,31321).
+char(o,31322).
+char(p,31323).
+char(1,31324).
+char(0,31325).
+char(2,31326).
+char(8,31327).
+char(c,31328).
+char(c,31329).
+char(p,31330).
+char(o,31331).
+char(p,31332).
+char(4,31333).
+char(3,31334).
+char(9,31335).
+char(5,31336).
+char(c,31337).
+char(m,31338).
+char(o,31339).
+char(p,31340).
+char(o,31341).
+char(p,31342).
+char(6,31343).
+char(3,31344).
+char(1,31345).
+char(8,31346).
+char(p,31347).
+char(8,31348).
+char(4,31349).
+char(5,31350).
+char(8,31351).
+char(c,31352).
+char(p,31353).
+char(9,31354).
+char(0,31355).
+char(8,31356).
+char(7,31357).
+char(p,31358).
+char(6,31359).
+char(4,31360).
+char(1,31361).
+char(3,31362).
+char(p,31363).
+char(8,31364).
+char(1,31365).
+char(2,31366).
+char(1,31367).
+char(c,31368).
+char(c,31369).
+char(p,31370).
+char(9,31371).
+char(7,31372).
+char(0,31373).
+char(3,31374).
+char(c,31375).
+char(c,31376).
+char(p,31377).
+char(3,31378).
+char(9,31379).
+char(0,31380).
+char(2,31381).
+char(c,31382).
+char(c,31383).
+char(c,31384).
+char(m,31385).
+char(9,31386).
+char(2,31387).
+char(9,31388).
+char(2,31389).
+char(m,31390).
+char(9,31391).
+char(8,31392).
+char(4,31393).
+char(2,31394).
+char(p,31395).
+char(9,31396).
+char(0,31397).
+char(7,31398).
+char(0,31399).
+char(p,31400).
+char(o,31401).
+char(p,31402).
+char(2,31403).
+char(7,31404).
+char(4,31405).
+char(3,31406).
+char(c,31407).
+char(c,31408).
+char(p,31409).
+char(o,31410).
+char(o,31411).
+char(o,31412).
+char(p,31413).
+char(o,31414).
+char(m,31415).
+char(6,31416).
+char(4,31417).
+char(0,31418).
+char(4,31419).
+char(p,31420).
+char(o,31421).
+char(o,31422).
+char(m,31423).
+char(4,31424).
+char(9,31425).
+char(8,31426).
+char(c,31427).
+char(m,31428).
+char(3,31429).
+char(6,31430).
+char(6,31431).
+char(3,31432).
+char(m,31433).
+char(1,31434).
+char(4,31435).
+char(9,31436).
+char(4,31437).
+char(p,31438).
+char(8,31439).
+char(5,31440).
+char(6,31441).
+char(1,31442).
+char(c,31443).
+char(c,31444).
+char(p,31445).
+char(6,31446).
+char(1,31447).
+char(0,31448).
+char(5,31449).
+char(p,31450).
+char(3,31451).
+char(7,31452).
+char(7,31453).
+char(6,31454).
+char(p,31455).
+char(o,31456).
+char(p,31457).
+char(o,31458).
+char(m,31459).
+char(8,31460).
+char(7,31461).
+char(3,31462).
+char(6,31463).
+char(c,31464).
+char(c,31465).
+char(c,31466).
+char(c,31467).
+char(c,31468).
+char(p,31469).
+char(o,31470).
+char(m,31471).
+char(o,31472).
+char(p,31473).
+char(5,31474).
+char(7,31475).
+char(1,31476).
+char(m,31477).
+char(o,31478).
+char(m,31479).
+char(o,31480).
+char(o,31481).
+char(p,31482).
+char(o,31483).
+char(p,31484).
+char(o,31485).
+char(p,31486).
+char(2,31487).
+char(1,31488).
+char(9,31489).
+char(6,31490).
+char(c,31491).
+char(c,31492).
+char(c,31493).
+char(c,31494).
+char(c,31495).
+char(m,31496).
+char(o,31497).
+char(p,31498).
+char(o,31499).
+char(m,31500).
+char(7,31501).
+char(0,31502).
+char(6,31503).
+char(4,31504).
+char(c,31505).
+char(c,31506).
+char(c,31507).
+char(c,31508).
+char(c,31509).
+char(m,31510).
+char(o,31511).
+char(m,31512).
+char(5,31513).
+char(2,31514).
+char(9,31515).
+char(6,31516).
+char(c,31517).
+char(c,31518).
+char(c,31519).
+char(m,31520).
+char(3,31521).
+char(0,31522).
+char(5,31523).
+char(9,31524).
+char(c,31525).
+char(c,31526).
+char(p,31527).
+char(4,31528).
+char(7,31529).
+char(8,31530).
+char(0,31531).
+char(p,31532).
+char(o,31533).
+char(o,31534).
+char(o,31535).
+char(m,31536).
+char(o,31537).
+char(p,31538).
+char(o,31539).
+char(p,31540).
+char(1,31541).
+char(2,31542).
+char(1,31543).
+char(6,31544).
+char(m,31545).
+char(4,31546).
+char(4,31547).
+char(1,31548).
+char(0,31549).
+char(c,31550).
+char(c,31551).
+char(c,31552).
+char(c,31553).
+char(m,31554).
+char(1,31555).
+char(0,31556).
+char(8,31557).
+char(8,31558).
+char(m,31559).
+char(o,31560).
+char(p,31561).
+char(3,31562).
+char(7,31563).
+char(9,31564).
+char(6,31565).
+char(c,31566).
+char(c,31567).
+char(c,31568).
+char(c,31569).
+char(c,31570).
+char(p,31571).
+char(o,31572).
+char(o,31573).
+char(m,31574).
+char(3,31575).
+char(2,31576).
+char(1,31577).
+char(4,31578).
+char(m,31579).
+char(o,31580).
+char(p,31581).
+char(9,31582).
+char(0,31583).
+char(8,31584).
+char(0,31585).
+char(c,31586).
+char(c,31587).
+char(c,31588).
+char(c,31589).
+char(c,31590).
+char(c,31591).
+char(p,31592).
+char(4,31593).
+char(4,31594).
+char(9,31595).
+char(4,31596).
+char(p,31597).
+char(o,31598).
+char(o,31599).
+char(p,31600).
+char(o,31601).
+char(m,31602).
+char(o,31603).
+char(o,31604).
+char(m,31605).
+char(o,31606).
+char(2,31607).
+char(2,31608).
+char(6,31609).
+char(9,31610).
+char(c,31611).
+char(c,31612).
+char(p,31613).
+char(8,31614).
+char(3,31615).
+char(0,31616).
+char(8,31617).
+char(m,31618).
+char(o,31619).
+char(1,31620).
+char(3,31621).
+char(4,31622).
+char(3,31623).
+char(p,31624).
+char(1,31625).
+char(7,31626).
+char(1,31627).
+char(0,31628).
+char(c,31629).
+char(c,31630).
+char(c,31631).
+char(m,31632).
+char(o,31633).
+char(4,31634).
+char(2,31635).
+char(6,31636).
+char(m,31637).
+char(o,31638).
+char(8,31639).
+char(5,31640).
+char(3,31641).
+char(2,31642).
+char(m,31643).
+char(7,31644).
+char(2,31645).
+char(0,31646).
+char(3,31647).
+char(c,31648).
+char(c,31649).
+char(c,31650).
+char(c,31651).
+char(m,31652).
+char(o,31653).
+char(2,31654).
+char(0,31655).
+char(9,31656).
+char(9,31657).
+char(m,31658).
+char(o,31659).
+char(1,31660).
+char(2,31661).
+char(9,31662).
+char(c,31663).
+char(p,31664).
+char(o,31665).
+char(p,31666).
+char(o,31667).
+char(m,31668).
+char(4,31669).
+char(6,31670).
+char(0,31671).
+char(5,31672).
+char(p,31673).
+char(1,31674).
+char(8,31675).
+char(4,31676).
+char(2,31677).
+char(c,31678).
+char(c,31679).
+char(m,31680).
+char(9,31681).
+char(7,31682).
+char(6,31683).
+char(1,31684).
+char(p,31685).
+char(o,31686).
+char(p,31687).
+char(o,31688).
+char(9,31689).
+char(4,31690).
+char(4,31691).
+char(7,31692).
+char(c,31693).
+char(m,31694).
+char(o,31695).
+char(8,31696).
+char(1,31697).
+char(1,31698).
+char(c,31699).
+char(c,31700).
+char(c,31701).
+char(m,31702).
+char(o,31703).
+char(m,31704).
+char(2,31705).
+char(7,31706).
+char(6,31707).
+char(1,31708).
+char(p,31709).
+char(o,31710).
+char(6,31711).
+char(0,31712).
+char(6,31713).
+char(3,31714).
+char(m,31715).
+char(o,31716).
+char(m,31717).
+char(7,31718).
+char(0,31719).
+char(5,31720).
+char(6,31721).
+char(p,31722).
+char(6,31723).
+char(5,31724).
+char(1,31725).
+char(6,31726).
+char(c,31727).
+char(c,31728).
+char(m,31729).
+char(1,31730).
+char(1,31731).
+char(3,31732).
+char(4,31733).
+char(p,31734).
+char(o,31735).
+char(m,31736).
+char(1,31737).
+char(1,31738).
+char(9,31739).
+char(c,31740).
+char(p,31741).
+char(o,31742).
+char(3,31743).
+char(5,31744).
+char(8,31745).
+char(1,31746).
+char(p,31747).
+char(o,31748).
+char(p,31749).
+char(o,31750).
+char(p,31751).
+char(o,31752).
+char(o,31753).
+char(m,31754).
+char(7,31755).
+char(0,31756).
+char(7,31757).
+char(6,31758).
+char(c,31759).
+char(m,31760).
+char(o,31761).
+char(o,31762).
+char(p,31763).
+char(4,31764).
+char(5,31765).
+char(2,31766).
+char(2,31767).
+char(m,31768).
+char(7,31769).
+char(8,31770).
+char(7,31771).
+char(5,31772).
+char(p,31773).
+char(4,31774).
+char(8,31775).
+char(3,31776).
+char(8,31777).
+char(c,31778).
+char(c,31779).
+char(p,31780).
+char(9,31781).
+char(9,31782).
+char(6,31783).
+char(7,31784).
+char(p,31785).
+char(o,31786).
+char(p,31787).
+char(o,31788).
+char(m,31789).
+char(o,31790).
+char(o,31791).
+char(m,31792).
+char(6,31793).
+char(1,31794).
+char(9,31795).
+char(3,31796).
+char(c,31797).
+char(p,31798).
+char(o,31799).
+char(p,31800).
+char(5,31801).
+char(2,31802).
+char(8,31803).
+char(1,31804).
+char(m,31805).
+char(o,31806).
+char(m,31807).
+char(o,31808).
+char(8,31809).
+char(0,31810).
+char(3,31811).
+char(9,31812).
+char(m,31813).
+char(3,31814).
+char(8,31815).
+char(9,31816).
+char(9,31817).
+char(c,31818).
+char(p,31819).
+char(9,31820).
+char(9,31821).
+char(7,31822).
+char(4,31823).
+char(p,31824).
+char(o,31825).
+char(m,31826).
+char(o,31827).
+char(p,31828).
+char(7,31829).
+char(5,31830).
+char(9,31831).
+char(8,31832).
+char(c,31833).
+char(p,31834).
+char(o,31835).
+char(o,31836).
+char(m,31837).
+char(o,31838).
+char(4,31839).
+char(1,31840).
+char(5,31841).
+char(5,31842).
+char(m,31843).
+char(o,31844).
+char(m,31845).
+char(6,31846).
+char(0,31847).
+char(0,31848).
+char(9,31849).
+char(c,31850).
+char(p,31851).
+char(o,31852).
+char(p,31853).
+char(6,31854).
+char(7,31855).
+char(4,31856).
+char(5,31857).
+char(c,31858).
+char(c,31859).
+char(c,31860).
+char(c,31861).
+char(c,31862).
+char(c,31863).
+char(p,31864).
+char(7,31865).
+char(1,31866).
+char(p,31867).
+char(6,31868).
+char(1,31869).
+char(2,31870).
+char(c,31871).
+char(m,31872).
+char(9,31873).
+char(7,31874).
+char(5,31875).
+char(0,31876).
+char(m,31877).
+char(1,31878).
+char(8,31879).
+char(5,31880).
+char(6,31881).
+char(p,31882).
+char(o,31883).
+char(m,31884).
+char(9,31885).
+char(0,31886).
+char(0,31887).
+char(8,31888).
+char(c,31889).
+char(p,31890).
+char(7,31891).
+char(0,31892).
+char(1,31893).
+char(8,31894).
+char(c,31895).
+char(c,31896).
+char(p,31897).
+char(o,31898).
+char(p,31899).
+char(6,31900).
+char(6,31901).
+char(2,31902).
+char(5,31903).
+char(m,31904).
+char(5,31905).
+char(1,31906).
+char(3,31907).
+char(0,31908).
+char(p,31909).
+char(o,31910).
+char(p,31911).
+char(o,31912).
+char(p,31913).
+char(o,31914).
+char(4,31915).
+char(4,31916).
+char(3,31917).
+char(8,31918).
+char(c,31919).
+char(c,31920).
+char(p,31921).
+char(4,31922).
+char(2,31923).
+char(4,31924).
+char(3,31925).
+char(c,31926).
+char(m,31927).
+char(o,31928).
+char(o,31929).
+char(p,31930).
+char(o,31931).
+char(p,31932).
+char(7,31933).
+char(2,31934).
+char(6,31935).
+char(1,31936).
+char(p,31937).
+char(2,31938).
+char(7,31939).
+char(0,31940).
+char(3,31941).
+char(c,31942).
+char(m,31943).
+char(7,31944).
+char(0,31945).
+char(1,31946).
+char(9,31947).
+char(c,31948).
+char(c,31949).
+char(p,31950).
+char(o,31951).
+char(p,31952).
+char(6,31953).
+char(0,31954).
+char(9,31955).
+char(c,31956).
+char(m,31957).
+char(o,31958).
+char(o,31959).
+char(m,31960).
+char(9,31961).
+char(5,31962).
+char(7,31963).
+char(8,31964).
+char(p,31965).
+char(o,31966).
+char(o,31967).
+char(m,31968).
+char(7,31969).
+char(8,31970).
+char(1,31971).
+char(0,31972).
+char(c,31973).
+char(c,31974).
+char(c,31975).
+char(c,31976).
+char(m,31977).
+char(o,31978).
+char(m,31979).
+char(o,31980).
+char(p,31981).
+char(3,31982).
+char(3,31983).
+char(6,31984).
+char(9,31985).
+char(c,31986).
+char(p,31987).
+char(7,31988).
+char(8,31989).
+char(4,31990).
+char(8,31991).
+char(p,31992).
+char(o,31993).
+char(2,31994).
+char(6,31995).
+char(0,31996).
+char(m,31997).
+char(4,31998).
+char(1,31999).
+char(9,32000).
+char(1,32001).
+char(c,32002).
+char(p,32003).
+char(1,32004).
+char(3,32005).
+char(8,32006).
+char(8,32007).
+char(m,32008).
+char(3,32009).
+char(6,32010).
+char(5,32011).
+char(8,32012).
+char(c,32013).
+char(c,32014).
+char(c,32015).
+char(c,32016).
+char(p,32017).
+char(4,32018).
+char(0,32019).
+char(7,32020).
+char(3,32021).
+char(c,32022).
+char(m,32023).
+char(o,32024).
+char(p,32025).
+char(4,32026).
+char(0,32027).
+char(8,32028).
+char(1,32029).
+char(p,32030).
+char(8,32031).
+char(5,32032).
+char(8,32033).
+char(1,32034).
+char(p,32035).
+char(o,32036).
+char(p,32037).
+char(o,32038).
+char(m,32039).
+char(4,32040).
+char(9,32041).
+char(7,32042).
+char(3,32043).
+char(p,32044).
+char(o,32045).
+char(m,32046).
+char(o,32047).
+char(p,32048).
+char(8,32049).
+char(1,32050).
+char(5,32051).
+char(3,32052).
+char(c,32053).
+char(c,32054).
+char(c,32055).
+char(c,32056).
+char(c,32057).
+char(m,32058).
+char(o,32059).
+char(m,32060).
+char(o,32061).
+char(o,32062).
+char(p,32063).
+char(4,32064).
+char(8,32065).
+char(8,32066).
+char(6,32067).
+char(p,32068).
+char(7,32069).
+char(0,32070).
+char(2,32071).
+char(6,32072).
+char(p,32073).
+char(9,32074).
+char(2,32075).
+char(7,32076).
+char(3,32077).
+char(c,32078).
+char(p,32079).
+char(o,32080).
+char(o,32081).
+char(6,32082).
+char(6,32083).
+char(6,32084).
+char(5,32085).
+char(c,32086).
+char(m,32087).
+char(o,32088).
+char(5,32089).
+char(4,32090).
+char(2,32091).
+char(c,32092).
+char(c,32093).
+char(p,32094).
+char(7,32095).
+char(6,32096).
+char(7,32097).
+char(3,32098).
+char(p,32099).
+char(o,32100).
+char(p,32101).
+char(o,32102).
+char(m,32103).
+char(o,32104).
+char(p,32105).
+char(5,32106).
+char(1,32107).
+char(8,32108).
+char(2,32109).
+char(m,32110).
+char(9,32111).
+char(0,32112).
+char(1,32113).
+char(6,32114).
+char(c,32115).
+char(c,32116).
+char(p,32117).
+char(6,32118).
+char(1,32119).
+char(1,32120).
+char(1,32121).
+char(c,32122).
+char(m,32123).
+char(9,32124).
+char(5,32125).
+char(3,32126).
+char(7,32127).
+char(c,32128).
+char(p,32129).
+char(4,32130).
+char(1,32131).
+char(9,32132).
+char(0,32133).
+char(m,32134).
+char(o,32135).
+char(1,32136).
+char(5,32137).
+char(1,32138).
+char(9,32139).
+char(p,32140).
+char(o,32141).
+char(2,32142).
+char(7,32143).
+char(1,32144).
+char(0,32145).
+char(p,32146).
+char(1,32147).
+char(2,32148).
+char(7,32149).
+char(6,32150).
+char(c,32151).
+char(m,32152).
+char(o,32153).
+char(m,32154).
+char(o,32155).
+char(m,32156).
+char(o,32157).
+char(6,32158).
+char(3,32159).
+char(2,32160).
+char(6,32161).
+char(c,32162).
+char(c,32163).
+char(p,32164).
+char(o,32165).
+char(p,32166).
+char(8,32167).
+char(7,32168).
+char(9,32169).
+char(7,32170).
+char(c,32171).
+char(c,32172).
+char(c,32173).
+char(m,32174).
+char(o,32175).
+char(p,32176).
+char(o,32177).
+char(m,32178).
+char(o,32179).
+char(m,32180).
+char(o,32181).
+char(p,32182).
+char(6,32183).
+char(8,32184).
+char(3,32185).
+char(0,32186).
+char(c,32187).
+char(c,32188).
+char(c,32189).
+char(p,32190).
+char(o,32191).
+char(7,32192).
+char(9,32193).
+char(0,32194).
+char(4,32195).
+char(c,32196).
+char(c,32197).
+char(p,32198).
+char(3,32199).
+char(0,32200).
+char(1,32201).
+char(8,32202).
+char(c,32203).
+char(m,32204).
+char(o,32205).
+char(m,32206).
+char(o,32207).
+char(m,32208).
+char(o,32209).
+char(o,32210).
+char(p,32211).
+char(9,32212).
+char(5,32213).
+char(9,32214).
+char(6,32215).
+char(m,32216).
+char(o,32217).
+char(m,32218).
+char(o,32219).
+char(o,32220).
+char(p,32221).
+char(9,32222).
+char(7,32223).
+char(3,32224).
+char(8,32225).
+char(p,32226).
+char(o,32227).
+char(p,32228).
+char(o,32229).
+char(6,32230).
+char(4,32231).
+char(2,32232).
+char(0,32233).
+char(c,32234).
+char(c,32235).
+char(c,32236).
+char(c,32237).
+char(c,32238).
+char(c,32239).
+char(m,32240).
+char(o,32241).
+char(o,32242).
+char(p,32243).
+char(o,32244).
+char(p,32245).
+char(o,32246).
+char(o,32247).
+char(m,32248).
+char(9,32249).
+char(3,32250).
+char(0,32251).
+char(1,32252).
+char(c,32253).
+char(m,32254).
+char(4,32255).
+char(4,32256).
+char(6,32257).
+char(0,32258).
+char(c,32259).
+char(p,32260).
+char(6,32261).
+char(7,32262).
+char(0,32263).
+char(5,32264).
+char(c,32265).
+char(m,32266).
+char(o,32267).
+char(p,32268).
+char(o,32269).
+char(o,32270).
+char(m,32271).
+char(o,32272).
+char(m,32273).
+char(o,32274).
+char(o,32275).
+char(p,32276).
+char(3,32277).
+char(0,32278).
+char(9,32279).
+char(8,32280).
+char(c,32281).
+char(p,32282).
+char(7,32283).
+char(6,32284).
+char(5,32285).
+char(3,32286).
+char(p,32287).
+char(o,32288).
+char(p,32289).
+char(o,32290).
+char(o,32291).
+char(o,32292).
+char(m,32293).
+char(o,32294).
+char(5,32295).
+char(5,32296).
+char(2,32297).
+char(c,32298).
+char(c,32299).
+char(m,32300).
+char(8,32301).
+char(8,32302).
+char(7,32303).
+char(2,32304).
+char(m,32305).
+char(5,32306).
+char(5,32307).
+char(1,32308).
+char(5,32309).
+char(c,32310).
+char(p,32311).
+char(o,32312).
+char(3,32313).
+char(2,32314).
+char(4,32315).
+char(0,32316).
+char(c,32317).
+char(m,32318).
+char(o,32319).
+char(m,32320).
+char(1,32321).
+char(5,32322).
+char(5,32323).
+char(7,32324).
+char(m,32325).
+char(5,32326).
+char(6,32327).
+char(6,32328).
+char(1,32329).
+char(p,32330).
+char(9,32331).
+char(2,32332).
+char(2,32333).
+char(5,32334).
+char(c,32335).
+char(m,32336).
+char(o,32337).
+char(p,32338).
+char(o,32339).
+char(1,32340).
+char(8,32341).
+char(9,32342).
+char(6,32343).
+char(m,32344).
+char(o,32345).
+char(o,32346).
+char(p,32347).
+char(o,32348).
+char(m,32349).
+char(o,32350).
+char(m,32351).
+char(3,32352).
+char(6,32353).
+char(5,32354).
+char(6,32355).
+char(c,32356).
+char(c,32357).
+char(m,32358).
+char(5,32359).
+char(1,32360).
+char(8,32361).
+char(9,32362).
+char(p,32363).
+char(6,32364).
+char(7,32365).
+char(7,32366).
+char(6,32367).
+char(c,32368).
+char(c,32369).
+char(m,32370).
+char(7,32371).
+char(9,32372).
+char(5,32373).
+char(6,32374).
+char(c,32375).
+char(p,32376).
+char(6,32377).
+char(5,32378).
+char(9,32379).
+char(2,32380).
+char(c,32381).
+char(c,32382).
+char(m,32383).
+char(8,32384).
+char(1,32385).
+char(2,32386).
+char(4,32387).
+char(m,32388).
+char(o,32389).
+char(m,32390).
+char(3,32391).
+char(5,32392).
+char(7,32393).
+char(5,32394).
+char(c,32395).
+char(p,32396).
+char(o,32397).
+char(p,32398).
+char(6,32399).
+char(3,32400).
+char(8,32401).
+char(6,32402).
+char(m,32403).
+char(2,32404).
+char(3,32405).
+char(2,32406).
+char(9,32407).
+char(p,32408).
+char(5,32409).
+char(0,32410).
+char(2,32411).
+char(c,32412).
+char(m,32413).
+char(4,32414).
+char(4,32415).
+char(4,32416).
+char(6,32417).
+char(c,32418).
+char(p,32419).
+char(5,32420).
+char(2,32421).
+char(p,32422).
+char(o,32423).
+char(m,32424).
+char(1,32425).
+char(2,32426).
+char(9,32427).
+char(8,32428).
+char(m,32429).
+char(6,32430).
+char(9,32431).
+char(9,32432).
+char(8,32433).
+char(m,32434).
+char(o,32435).
+char(p,32436).
+char(o,32437).
+char(p,32438).
+char(o,32439).
+char(p,32440).
+char(6,32441).
+char(8,32442).
+char(4,32443).
+char(9,32444).
+char(c,32445).
+char(m,32446).
+char(o,32447).
+char(4,32448).
+char(1,32449).
+char(3,32450).
+char(3,32451).
+char(c,32452).
+char(m,32453).
+char(o,32454).
+char(m,32455).
+char(6,32456).
+char(1,32457).
+char(7,32458).
+char(7,32459).
+char(c,32460).
+char(m,32461).
+char(o,32462).
+char(p,32463).
+char(o,32464).
+char(o,32465).
+char(9,32466).
+char(5,32467).
+char(7,32468).
+char(8,32469).
+char(c,32470).
+char(m,32471).
+char(o,32472).
+char(m,32473).
+char(1,32474).
+char(5,32475).
+char(1,32476).
+char(4,32477).
+char(p,32478).
+char(9,32479).
+char(2,32480).
+char(9,32481).
+char(3,32482).
+char(c,32483).
+char(c,32484).
+char(c,32485).
+char(c,32486).
+char(c,32487).
+char(p,32488).
+char(o,32489).
+char(p,32490).
+char(8,32491).
+char(8,32492).
+char(2,32493).
+char(0,32494).
+char(c,32495).
+char(p,32496).
+char(5,32497).
+char(4,32498).
+char(7,32499).
+char(0,32500).
+char(c,32501).
+char(p,32502).
+char(o,32503).
+char(p,32504).
+char(4,32505).
+char(7,32506).
+char(3,32507).
+char(5,32508).
+char(p,32509).
+char(9,32510).
+char(0,32511).
+char(3,32512).
+char(8,32513).
+char(p,32514).
+char(6,32515).
+char(3,32516).
+char(5,32517).
+char(c,32518).
+char(c,32519).
+char(p,32520).
+char(1,32521).
+char(7,32522).
+char(8,32523).
+char(0,32524).
+char(c,32525).
+char(p,32526).
+char(o,32527).
+char(o,32528).
+char(p,32529).
+char(o,32530).
+char(m,32531).
+char(9,32532).
+char(6,32533).
+char(9,32534).
+char(4,32535).
+char(c,32536).
+char(m,32537).
+char(6,32538).
+char(9,32539).
+char(9,32540).
+char(5,32541).
+char(p,32542).
+char(o,32543).
+char(o,32544).
+char(p,32545).
+char(6,32546).
+char(4,32547).
+char(1,32548).
+char(7,32549).
+char(p,32550).
+char(o,32551).
+char(p,32552).
+char(o,32553).
+char(o,32554).
+char(4,32555).
+char(8,32556).
+char(3,32557).
+char(3,32558).
+char(c,32559).
+char(m,32560).
+char(o,32561).
+char(m,32562).
+char(8,32563).
+char(2,32564).
+char(6,32565).
+char(8,32566).
+char(m,32567).
+char(o,32568).
+char(m,32569).
+char(6,32570).
+char(1,32571).
+char(4,32572).
+char(5,32573).
+char(p,32574).
+char(8,32575).
+char(1,32576).
+char(4,32577).
+char(1,32578).
+char(c,32579).
+char(c,32580).
+char(p,32581).
+char(o,32582).
+char(m,32583).
+char(o,32584).
+char(m,32585).
+char(5,32586).
+char(4,32587).
+char(0,32588).
+char(3,32589).
+char(c,32590).
+char(c,32591).
+char(m,32592).
+char(o,32593).
+char(m,32594).
+char(o,32595).
+char(m,32596).
+char(o,32597).
+char(p,32598).
+char(o,32599).
+char(p,32600).
+char(o,32601).
+char(p,32602).
+char(o,32603).
+char(p,32604).
+char(o,32605).
+char(p,32606).
+char(9,32607).
+char(2,32608).
+char(4,32609).
+char(p,32610).
+char(o,32611).
+char(m,32612).
+char(o,32613).
+char(p,32614).
+char(5,32615).
+char(8,32616).
+char(7,32617).
+char(8,32618).
+char(p,32619).
+char(6,32620).
+char(5,32621).
+char(0,32622).
+char(0,32623).
+char(c,32624).
+char(p,32625).
+char(1,32626).
+char(4,32627).
+char(0,32628).
+char(5,32629).
+char(p,32630).
+char(1,32631).
+char(2,32632).
+char(5,32633).
+char(1,32634).
+char(c,32635).
+char(m,32636).
+char(6,32637).
+char(4,32638).
+char(3,32639).
+char(2,32640).
+char(p,32641).
+char(7,32642).
+char(7,32643).
+char(0,32644).
+char(8,32645).
+char(c,32646).
+char(m,32647).
+char(6,32648).
+char(0,32649).
+char(2,32650).
+char(3,32651).
+char(m,32652).
+char(o,32653).
+char(o,32654).
+char(o,32655).
+char(p,32656).
+char(o,32657).
+char(4,32658).
+char(2,32659).
+char(2,32660).
+char(6,32661).
+char(c,32662).
+char(c,32663).
+char(c,32664).
+char(m,32665).
+char(9,32666).
+char(1,32667).
+char(1,32668).
+char(6,32669).
+char(c,32670).
+char(p,32671).
+char(o,32672).
+char(m,32673).
+char(4,32674).
+char(9,32675).
+char(1,32676).
+char(4,32677).
+char(p,32678).
+char(o,32679).
+char(m,32680).
+char(o,32681).
+char(p,32682).
+char(9,32683).
+char(4,32684).
+char(3,32685).
+char(9,32686).
+char(c,32687).
+char(p,32688).
+char(o,32689).
+char(4,32690).
+char(8,32691).
+char(1,32692).
+char(9,32693).
+char(m,32694).
+char(o,32695).
+char(p,32696).
+char(1,32697).
+char(6,32698).
+char(7,32699).
+char(p,32700).
+char(o,32701).
+char(m,32702).
+char(o,32703).
+char(p,32704).
+char(6,32705).
+char(5,32706).
+char(6,32707).
+char(2,32708).
+char(m,32709).
+char(o,32710).
+char(p,32711).
+char(6,32712).
+char(4,32713).
+char(5,32714).
+char(5,32715).
+char(m,32716).
+char(2,32717).
+char(5,32718).
+char(0,32719).
+char(8,32720).
+char(p,32721).
+char(o,32722).
+char(o,32723).
+char(m,32724).
+char(6,32725).
+char(7,32726).
+char(4,32727).
+char(9,32728).
+char(c,32729).
+char(p,32730).
+char(o,32731).
+char(9,32732).
+char(8,32733).
+char(3,32734).
+char(2,32735).
+char(c,32736).
+char(c,32737).
+char(c,32738).
+char(p,32739).
+char(o,32740).
+char(p,32741).
+char(o,32742).
+char(p,32743).
+char(9,32744).
+char(2,32745).
+char(6,32746).
+char(9,32747).
+char(c,32748).
+char(m,32749).
+char(8,32750).
+char(5,32751).
+char(4,32752).
+char(0,32753).
+char(c,32754).
+char(p,32755).
+char(o,32756).
+char(o,32757).
+char(1,32758).
+char(2,32759).
+char(9,32760).
+char(0,32761).
+char(c,32762).
+char(m,32763).
+char(2,32764).
+char(5,32765).
+char(7,32766).
+char(0,32767).
+char(m,32768).
+char(7,32769).
+char(8,32770).
+char(2,32771).
+char(1,32772).
+char(m,32773).
+char(5,32774).
+char(0,32775).
+char(2,32776).
+char(9,32777).
+char(p,32778).
+char(6,32779).
+char(5,32780).
+char(9,32781).
+char(7,32782).
+char(c,32783).
+char(c,32784).
+char(c,32785).
+char(c,32786).
+char(p,32787).
+char(2,32788).
+char(6,32789).
+char(5,32790).
+char(7,32791).
+char(m,32792).
+char(2,32793).
+char(1,32794).
+char(4,32795).
+char(0,32796).
+char(c,32797).
+char(c,32798).
+char(c,32799).
+char(c,32800).
+char(c,32801).
+char(m,32802).
+char(2,32803).
+char(1,32804).
+char(4,32805).
+char(0,32806).
+char(p,32807).
+char(1,32808).
+char(3,32809).
+char(4,32810).
+char(1,32811).
+char(m,32812).
+char(o,32813).
+char(m,32814).
+char(3,32815).
+char(8,32816).
+char(0,32817).
+char(8,32818).
+char(c,32819).
+char(p,32820).
+char(1,32821).
+char(5,32822).
+char(4,32823).
+char(c,32824).
+char(p,32825).
+char(o,32826).
+char(4,32827).
+char(0,32828).
+char(9,32829).
+char(c,32830).
+char(c,32831).
+char(p,32832).
+char(1,32833).
+char(4,32834).
+char(0,32835).
+char(8,32836).
+char(p,32837).
+char(9,32838).
+char(9,32839).
+char(9,32840).
+char(1,32841).
+char(c,32842).
+char(c,32843).
+char(c,32844).
+char(c,32845).
+char(c,32846).
+char(m,32847).
+char(5,32848).
+char(8,32849).
+char(4,32850).
+char(0,32851).
+char(c,32852).
+char(p,32853).
+char(9,32854).
+char(1,32855).
+char(5,32856).
+char(5,32857).
+char(c,32858).
+char(m,32859).
+char(o,32860).
+char(6,32861).
+char(5,32862).
+char(6,32863).
+char(5,32864).
+char(p,32865).
+char(9,32866).
+char(7,32867).
+char(2,32868).
+char(2,32869).
+char(p,32870).
+char(o,32871).
+char(2,32872).
+char(6,32873).
+char(2,32874).
+char(7,32875).
+char(c,32876).
+char(c,32877).
+char(p,32878).
+char(4,32879).
+char(0,32880).
+char(0,32881).
+char(6,32882).
+char(m,32883).
+char(1,32884).
+char(8,32885).
+char(9,32886).
+char(2,32887).
+char(c,32888).
+char(m,32889).
+char(9,32890).
+char(9,32891).
+char(6,32892).
+char(5,32893).
+char(m,32894).
+char(o,32895).
+char(m,32896).
+char(o,32897).
+char(p,32898).
+char(5,32899).
+char(3,32900).
+char(2,32901).
+char(1,32902).
+char(p,32903).
+char(2,32904).
+char(7,32905).
+char(0,32906).
+char(4,32907).
+char(p,32908).
+char(7,32909).
+char(6,32910).
+char(4,32911).
+char(4,32912).
+char(m,32913).
+char(o,32914).
+char(m,32915).
+char(o,32916).
+char(p,32917).
+char(o,32918).
+char(5,32919).
+char(8,32920).
+char(8,32921).
+char(8,32922).
+char(p,32923).
+char(1,32924).
+char(6,32925).
+char(6,32926).
+char(3,32927).
+char(m,32928).
+char(o,32929).
+char(9,32930).
+char(1,32931).
+char(5,32932).
+char(4,32933).
+char(c,32934).
+char(p,32935).
+char(o,32936).
+char(7,32937).
+char(7,32938).
+char(8,32939).
+char(3,32940).
+char(c,32941).
+char(c,32942).
+char(c,32943).
+char(m,32944).
+char(o,32945).
+char(p,32946).
+char(o,32947).
+char(1,32948).
+char(0,32949).
+char(8,32950).
+char(8,32951).
+char(c,32952).
+char(p,32953).
+char(7,32954).
+char(2,32955).
+char(6,32956).
+char(5,32957).
+char(c,32958).
+char(m,32959).
+char(o,32960).
+char(m,32961).
+char(o,32962).
+char(o,32963).
+char(o,32964).
+char(m,32965).
+char(o,32966).
+char(m,32967).
+char(1,32968).
+char(0,32969).
+char(9,32970).
+char(2,32971).
+char(p,32972).
+char(5,32973).
+char(6,32974).
+char(9,32975).
+char(9,32976).
+char(p,32977).
+char(o,32978).
+char(p,32979).
+char(8,32980).
+char(6,32981).
+char(7,32982).
+char(8,32983).
+char(p,32984).
+char(o,32985).
+char(9,32986).
+char(0,32987).
+char(7,32988).
+char(7,32989).
+char(c,32990).
+char(c,32991).
+char(c,32992).
+char(c,32993).
+char(m,32994).
+char(6,32995).
+char(5,32996).
+char(6,32997).
+char(3,32998).
+char(c,32999).
+char(c,33000).
+char(c,33001).
+char(c,33002).
+char(p,33003).
+char(o,33004).
+char(m,33005).
+char(o,33006).
+char(4,33007).
+char(7,33008).
+char(0,33009).
+char(0,33010).
+char(m,33011).
+char(o,33012).
+char(p,33013).
+char(o,33014).
+char(p,33015).
+char(5,33016).
+char(4,33017).
+char(8,33018).
+char(4,33019).
+char(c,33020).
+char(p,33021).
+char(o,33022).
+char(m,33023).
+char(o,33024).
+char(o,33025).
+char(o,33026).
+char(p,33027).
+char(o,33028).
+char(p,33029).
+char(o,33030).
+char(m,33031).
+char(o,33032).
+char(p,33033).
+char(o,33034).
+char(p,33035).
+char(o,33036).
+char(p,33037).
+char(o,33038).
+char(m,33039).
+char(9,33040).
+char(1,33041).
+char(3,33042).
+char(8,33043).
+char(p,33044).
+char(9,33045).
+char(5,33046).
+char(7,33047).
+char(1,33048).
+char(m,33049).
+char(1,33050).
+char(1,33051).
+char(7,33052).
+char(9,33053).
+char(m,33054).
+char(o,33055).
+char(p,33056).
+char(o,33057).
+char(4,33058).
+char(2,33059).
+char(0,33060).
+char(8,33061).
+char(m,33062).
+char(o,33063).
+char(o,33064).
+char(m,33065).
+char(2,33066).
+char(9,33067).
+char(4,33068).
+char(3,33069).
+char(c,33070).
+char(c,33071).
+char(c,33072).
+char(m,33073).
+char(o,33074).
+char(p,33075).
+char(o,33076).
+char(m,33077).
+char(o,33078).
+char(p,33079).
+char(5,33080).
+char(7,33081).
+char(4,33082).
+char(2,33083).
+char(p,33084).
+char(o,33085).
+char(p,33086).
+char(5,33087).
+char(3,33088).
+char(4,33089).
+char(4,33090).
+char(c,33091).
+char(c,33092).
+char(p,33093).
+char(o,33094).
+char(o,33095).
+char(o,33096).
+char(4,33097).
+char(2,33098).
+char(6,33099).
+char(1,33100).
+char(c,33101).
+char(c,33102).
+char(c,33103).
+char(c,33104).
+char(c,33105).
+char(p,33106).
+char(8,33107).
+char(8,33108).
+char(4,33109).
+char(9,33110).
+char(p,33111).
+char(o,33112).
+char(p,33113).
+char(o,33114).
+char(o,33115).
+char(m,33116).
+char(4,33117).
+char(9,33118).
+char(7,33119).
+char(5,33120).
+char(c,33121).
+char(m,33122).
+char(5,33123).
+char(6,33124).
+char(2,33125).
+char(5,33126).
+char(c,33127).
+char(c,33128).
+char(c,33129).
+char(m,33130).
+char(o,33131).
+char(p,33132).
+char(5,33133).
+char(1,33134).
+char(8,33135).
+char(1,33136).
+char(p,33137).
+char(5,33138).
+char(3,33139).
+char(0,33140).
+char(8,33141).
+char(m,33142).
+char(5,33143).
+char(3,33144).
+char(8,33145).
+char(3,33146).
+char(m,33147).
+char(o,33148).
+char(1,33149).
+char(2,33150).
+char(8,33151).
+char(2,33152).
+char(m,33153).
+char(7,33154).
+char(2,33155).
+char(2,33156).
+char(8,33157).
+char(m,33158).
+char(5,33159).
+char(7,33160).
+char(9,33161).
+char(6,33162).
+char(m,33163).
+char(o,33164).
+char(m,33165).
+char(o,33166).
+char(3,33167).
+char(0,33168).
+char(2,33169).
+char(m,33170).
+char(7,33171).
+char(7,33172).
+char(2,33173).
+char(5,33174).
+char(c,33175).
+char(c,33176).
+char(m,33177).
+char(o,33178).
+char(p,33179).
+char(o,33180).
+char(p,33181).
+char(o,33182).
+char(p,33183).
+char(o,33184).
+char(o,33185).
+char(m,33186).
+char(o,33187).
+char(o,33188).
+char(o,33189).
+char(m,33190).
+char(4,33191).
+char(7,33192).
+char(1,33193).
+char(9,33194).
+char(c,33195).
+char(p,33196).
+char(8,33197).
+char(7,33198).
+char(0,33199).
+char(1,33200).
+char(p,33201).
+char(o,33202).
+char(m,33203).
+char(7,33204).
+char(9,33205).
+char(2,33206).
+char(6,33207).
+char(p,33208).
+char(1,33209).
+char(0,33210).
+char(5,33211).
+char(7,33212).
+char(c,33213).
+char(p,33214).
+char(o,33215).
+char(7,33216).
+char(8,33217).
+char(7,33218).
+char(6,33219).
+char(c,33220).
+char(c,33221).
+char(c,33222).
+char(m,33223).
+char(o,33224).
+char(p,33225).
+char(8,33226).
+char(0,33227).
+char(9,33228).
+char(7,33229).
+char(c,33230).
+char(m,33231).
+char(o,33232).
+char(o,33233).
+char(2,33234).
+char(2,33235).
+char(0,33236).
+char(5,33237).
+char(c,33238).
+char(c,33239).
+char(m,33240).
+char(o,33241).
+char(o,33242).
+char(m,33243).
+char(5,33244).
+char(9,33245).
+char(2,33246).
+char(4,33247).
+char(c,33248).
+char(c,33249).
+char(c,33250).
+char(p,33251).
+char(o,33252).
+char(p,33253).
+char(5,33254).
+char(1,33255).
+char(6,33256).
+char(1,33257).
+char(m,33258).
+char(o,33259).
+char(8,33260).
+char(5,33261).
+char(9,33262).
+char(3,33263).
+char(c,33264).
+char(c,33265).
+char(c,33266).
+char(m,33267).
+char(5,33268).
+char(2,33269).
+char(3,33270).
+char(3,33271).
+char(c,33272).
+char(m,33273).
+char(4,33274).
+char(2,33275).
+char(3,33276).
+char(6,33277).
+char(m,33278).
+char(o,33279).
+char(m,33280).
+char(7,33281).
+char(7,33282).
+char(1,33283).
+char(7,33284).
+char(c,33285).
+char(c,33286).
+char(c,33287).
+char(c,33288).
+char(c,33289).
+char(m,33290).
+char(5,33291).
+char(4,33292).
+char(7,33293).
+char(5,33294).
+char(m,33295).
+char(o,33296).
+char(o,33297).
+char(p,33298).
+char(o,33299).
+char(4,33300).
+char(8,33301).
+char(8,33302).
+char(9,33303).
+char(p,33304).
+char(9,33305).
+char(3,33306).
+char(1,33307).
+char(p,33308).
+char(6,33309).
+char(0,33310).
+char(9,33311).
+char(5,33312).
+char(c,33313).
+char(c,33314).
+char(m,33315).
+char(o,33316).
+char(m,33317).
+char(o,33318).
+char(m,33319).
+char(o,33320).
+char(m,33321).
+char(o,33322).
+char(o,33323).
+char(p,33324).
+char(o,33325).
+char(p,33326).
+char(o,33327).
+char(8,33328).
+char(1,33329).
+char(8,33330).
+char(5,33331).
+char(c,33332).
+char(c,33333).
+char(c,33334).
+char(m,33335).
+char(o,33336).
+char(m,33337).
+char(3,33338).
+char(8,33339).
+char(4,33340).
+char(6,33341).
+char(p,33342).
+char(5,33343).
+char(7,33344).
+char(3,33345).
+char(5,33346).
+char(c,33347).
+char(c,33348).
+char(m,33349).
+char(5,33350).
+char(4,33351).
+char(6,33352).
+char(0,33353).
+char(c,33354).
+char(m,33355).
+char(o,33356).
+char(4,33357).
+char(6,33358).
+char(5,33359).
+char(m,33360).
+char(o,33361).
+char(m,33362).
+char(o,33363).
+char(m,33364).
+char(o,33365).
+char(o,33366).
+char(o,33367).
+char(7,33368).
+char(9,33369).
+char(3,33370).
+char(4,33371).
+char(c,33372).
+char(c,33373).
+char(p,33374).
+char(6,33375).
+char(5,33376).
+char(6,33377).
+char(4,33378).
+char(c,33379).
+char(m,33380).
+char(o,33381).
+char(7,33382).
+char(7,33383).
+char(1,33384).
+char(2,33385).
+char(p,33386).
+char(5,33387).
+char(3,33388).
+char(6,33389).
+char(4,33390).
+char(c,33391).
+char(m,33392).
+char(8,33393).
+char(0,33394).
+char(2,33395).
+char(9,33396).
+char(c,33397).
+char(m,33398).
+char(9,33399).
+char(4,33400).
+char(8,33401).
+char(6,33402).
+char(m,33403).
+char(o,33404).
+char(p,33405).
+char(1,33406).
+char(1,33407).
+char(5,33408).
+char(0,33409).
+char(c,33410).
+char(m,33411).
+char(7,33412).
+char(4,33413).
+char(4,33414).
+char(6,33415).
+char(p,33416).
+char(9,33417).
+char(8,33418).
+char(0,33419).
+char(2,33420).
+char(m,33421).
+char(o,33422).
+char(p,33423).
+char(o,33424).
+char(p,33425).
+char(o,33426).
+char(p,33427).
+char(2,33428).
+char(4,33429).
+char(2,33430).
+char(1,33431).
+char(c,33432).
+char(c,33433).
+char(c,33434).
+char(m,33435).
+char(o,33436).
+char(m,33437).
+char(3,33438).
+char(8,33439).
+char(5,33440).
+char(1,33441).
+char(m,33442).
+char(7,33443).
+char(5,33444).
+char(3,33445).
+char(0,33446).
+char(c,33447).
+char(p,33448).
+char(o,33449).
+char(m,33450).
+char(4,33451).
+char(5,33452).
+char(9,33453).
+char(8,33454).
+char(p,33455).
+char(2,33456).
+char(4,33457).
+char(1,33458).
+char(5,33459).
+char(c,33460).
+char(m,33461).
+char(o,33462).
+char(p,33463).
+char(o,33464).
+char(m,33465).
+char(o,33466).
+char(o,33467).
+char(o,33468).
+char(p,33469).
+char(6,33470).
+char(6,33471).
+char(7,33472).
+char(7,33473).
+char(p,33474).
+char(o,33475).
+char(m,33476).
+char(9,33477).
+char(4,33478).
+char(1,33479).
+char(4,33480).
+char(p,33481).
+char(5,33482).
+char(0,33483).
+char(9,33484).
+char(6,33485).
+char(c,33486).
+char(c,33487).
+char(p,33488).
+char(o,33489).
+char(m,33490).
+char(o,33491).
+char(p,33492).
+char(o,33493).
+char(m,33494).
+char(o,33495).
+char(p,33496).
+char(o,33497).
+char(p,33498).
+char(o,33499).
+char(p,33500).
+char(o,33501).
+char(m,33502).
+char(o,33503).
+char(m,33504).
+char(o,33505).
+char(p,33506).
+char(o,33507).
+char(m,33508).
+char(7,33509).
+char(2,33510).
+char(7,33511).
+char(8,33512).
+char(p,33513).
+char(o,33514).
+char(7,33515).
+char(1,33516).
+char(8,33517).
+char(2,33518).
+char(p,33519).
+char(9,33520).
+char(9,33521).
+char(2,33522).
+char(9,33523).
+char(m,33524).
+char(o,33525).
+char(m,33526).
+char(1,33527).
+char(7,33528).
+char(7,33529).
+char(p,33530).
+char(1,33531).
+char(0,33532).
+char(2,33533).
+char(3,33534).
+char(c,33535).
+char(c,33536).
+char(m,33537).
+char(9,33538).
+char(6,33539).
+char(4,33540).
+char(4,33541).
+char(c,33542).
+char(c,33543).
+char(c,33544).
+char(p,33545).
+char(9,33546).
+char(3,33547).
+char(0,33548).
+char(7,33549).
+char(c,33550).
+char(m,33551).
+char(o,33552).
+char(p,33553).
+char(o,33554).
+char(p,33555).
+char(o,33556).
+char(7,33557).
+char(6,33558).
+char(7,33559).
+char(7,33560).
+char(c,33561).
+char(c,33562).
+char(p,33563).
+char(o,33564).
+char(o,33565).
+char(p,33566).
+char(8,33567).
+char(1,33568).
+char(2,33569).
+char(4,33570).
+char(m,33571).
+char(3,33572).
+char(5,33573).
+char(1,33574).
+char(5,33575).
+char(c,33576).
+char(c,33577).
+char(c,33578).
+char(c,33579).
+char(c,33580).
+char(c,33581).
+char(c,33582).
+char(m,33583).
+char(o,33584).
+char(m,33585).
+char(2,33586).
+char(5,33587).
+char(2,33588).
+char(1,33589).
+char(m,33590).
+char(5,33591).
+char(1,33592).
+char(5,33593).
+char(0,33594).
+char(p,33595).
+char(2,33596).
+char(3,33597).
+char(1,33598).
+char(8,33599).
+char(c,33600).
+char(c,33601).
+char(p,33602).
+char(o,33603).
+char(o,33604).
+char(p,33605).
+char(3,33606).
+char(2,33607).
+char(1,33608).
+char(1,33609).
+char(p,33610).
+char(1,33611).
+char(5,33612).
+char(9,33613).
+char(7,33614).
+char(m,33615).
+char(3,33616).
+char(1,33617).
+char(2,33618).
+char(5,33619).
+char(p,33620).
+char(7,33621).
+char(4,33622).
+char(1,33623).
+char(6,33624).
+char(c,33625).
+char(c,33626).
+char(p,33627).
+char(4,33628).
+char(4,33629).
+char(6,33630).
+char(0,33631).
+char(p,33632).
+char(o,33633).
+char(p,33634).
+char(o,33635).
+char(o,33636).
+char(1,33637).
+char(2,33638).
+char(4,33639).
+char(0,33640).
+char(m,33641).
+char(5,33642).
+char(3,33643).
+char(7,33644).
+char(6,33645).
+char(c,33646).
+char(c,33647).
+char(c,33648).
+char(c,33649).
+char(p,33650).
+char(o,33651).
+char(p,33652).
+char(o,33653).
+char(3,33654).
+char(2,33655).
+char(5,33656).
+char(4,33657).
+char(m,33658).
+char(o,33659).
+char(p,33660).
+char(1,33661).
+char(9,33662).
+char(1,33663).
+char(6,33664).
+char(c,33665).
+char(c,33666).
+char(c,33667).
+char(c,33668).
+char(m,33669).
+char(5,33670).
+char(0,33671).
+char(9,33672).
+char(5,33673).
+char(p,33674).
+char(o,33675).
+char(m,33676).
+char(o,33677).
+char(p,33678).
+char(6,33679).
+char(8,33680).
+char(5,33681).
+char(3,33682).
+char(c,33683).
+char(p,33684).
+char(o,33685).
+char(p,33686).
+char(o,33687).
+char(p,33688).
+char(3,33689).
+char(6,33690).
+char(2,33691).
+char(7,33692).
+char(c,33693).
+char(m,33694).
+char(5,33695).
+char(6,33696).
+char(3,33697).
+char(7,33698).
+char(c,33699).
+char(c,33700).
+char(c,33701).
+char(p,33702).
+char(o,33703).
+char(p,33704).
+char(o,33705).
+char(p,33706).
+char(6,33707).
+char(2,33708).
+char(5,33709).
+char(8,33710).
+char(m,33711).
+char(5,33712).
+char(9,33713).
+char(3,33714).
+char(4,33715).
+char(p,33716).
+char(9,33717).
+char(6,33718).
+char(4,33719).
+char(9,33720).
+char(m,33721).
+char(o,33722).
+char(p,33723).
+char(4,33724).
+char(4,33725).
+char(8,33726).
+char(8,33727).
+char(m,33728).
+char(o,33729).
+char(p,33730).
+char(8,33731).
+char(4,33732).
+char(6,33733).
+char(1,33734).
+char(p,33735).
+char(o,33736).
+char(m,33737).
+char(o,33738).
+char(p,33739).
+char(4,33740).
+char(9,33741).
+char(2,33742).
+char(8,33743).
+char(p,33744).
+char(6,33745).
+char(5,33746).
+char(8,33747).
+char(5,33748).
+char(m,33749).
+char(8,33750).
+char(5,33751).
+char(0,33752).
+char(0,33753).
+char(c,33754).
+char(c,33755).
+char(c,33756).
+char(p,33757).
+char(o,33758).
+char(p,33759).
+char(o,33760).
+char(p,33761).
+char(o,33762).
+char(p,33763).
+char(6,33764).
+char(7,33765).
+char(7,33766).
+char(2,33767).
+char(c,33768).
+char(p,33769).
+char(7,33770).
+char(7,33771).
+char(8,33772).
+char(3,33773).
+char(c,33774).
+char(c,33775).
+char(m,33776).
+char(o,33777).
+char(m,33778).
+char(5,33779).
+char(3,33780).
+char(7,33781).
+char(5,33782).
+char(m,33783).
+char(o,33784).
+char(5,33785).
+char(2,33786).
+char(7,33787).
+char(3,33788).
+char(c,33789).
+char(c,33790).
+char(m,33791).
+char(o,33792).
+char(p,33793).
+char(o,33794).
+char(m,33795).
+char(o,33796).
+char(1,33797).
+char(0,33798).
+char(1,33799).
+char(1,33800).
+char(c,33801).
+char(c,33802).
+char(p,33803).
+char(8,33804).
+char(4,33805).
+char(2,33806).
+char(c,33807).
+char(p,33808).
+char(4,33809).
+char(8,33810).
+char(0,33811).
+char(4,33812).
+char(c,33813).
+char(c,33814).
+char(c,33815).
+char(p,33816).
+char(o,33817).
+char(p,33818).
+char(o,33819).
+char(m,33820).
+char(7,33821).
+char(0,33822).
+char(2,33823).
+char(0,33824).
+char(c,33825).
+char(p,33826).
+char(5,33827).
+char(3,33828).
+char(1,33829).
+char(4,33830).
+char(p,33831).
+char(o,33832).
+char(8,33833).
+char(0,33834).
+char(7,33835).
+char(c,33836).
+char(m,33837).
+char(o,33838).
+char(p,33839).
+char(o,33840).
+char(m,33841).
+char(8,33842).
+char(4,33843).
+char(3,33844).
+char(0,33845).
+char(p,33846).
+char(o,33847).
+char(m,33848).
+char(o,33849).
+char(3,33850).
+char(5,33851).
+char(4,33852).
+char(1,33853).
+char(m,33854).
+char(o,33855).
+char(2,33856).
+char(2,33857).
+char(5,33858).
+char(0,33859).
+char(m,33860).
+char(3,33861).
+char(2,33862).
+char(8,33863).
+char(5,33864).
+char(c,33865).
+char(c,33866).
+char(p,33867).
+char(8,33868).
+char(6,33869).
+char(0,33870).
+char(6,33871).
+char(m,33872).
+char(7,33873).
+char(8,33874).
+char(5,33875).
+char(3,33876).
+char(c,33877).
+char(c,33878).
+char(p,33879).
+char(o,33880).
+char(9,33881).
+char(6,33882).
+char(4,33883).
+char(6,33884).
+char(m,33885).
+char(1,33886).
+char(4,33887).
+char(3,33888).
+char(4,33889).
+char(m,33890).
+char(4,33891).
+char(6,33892).
+char(9,33893).
+char(3,33894).
+char(p,33895).
+char(7,33896).
+char(8,33897).
+char(1,33898).
+char(7,33899).
+char(c,33900).
+char(c,33901).
+char(c,33902).
+char(p,33903).
+char(o,33904).
+char(m,33905).
+char(o,33906).
+char(m,33907).
+char(4,33908).
+char(8,33909).
+char(p,33910).
+char(o,33911).
+char(o,33912).
+char(m,33913).
+char(9,33914).
+char(0,33915).
+char(8,33916).
+char(3,33917).
+char(c,33918).
+char(c,33919).
+char(c,33920).
+char(c,33921).
+char(p,33922).
+char(1,33923).
+char(8,33924).
+char(3,33925).
+char(8,33926).
+char(p,33927).
+char(3,33928).
+char(0,33929).
+char(4,33930).
+char(6,33931).
+char(p,33932).
+char(3,33933).
+char(2,33934).
+char(7,33935).
+char(4,33936).
+char(c,33937).
+char(m,33938).
+char(2,33939).
+char(0,33940).
+char(8,33941).
+char(3,33942).
+char(c,33943).
+char(c,33944).
+char(p,33945).
+char(o,33946).
+char(m,33947).
+char(1,33948).
+char(7,33949).
+char(0,33950).
+char(5,33951).
+char(m,33952).
+char(o,33953).
+char(p,33954).
+char(o,33955).
+char(5,33956).
+char(6,33957).
+char(2,33958).
+char(0,33959).
+char(c,33960).
+char(p,33961).
+char(o,33962).
+char(3,33963).
+char(9,33964).
+char(5,33965).
+char(6,33966).
+char(p,33967).
+char(o,33968).
+char(m,33969).
+char(2,33970).
+char(6,33971).
+char(0,33972).
+char(0,33973).
+char(c,33974).
+char(c,33975).
+char(p,33976).
+char(o,33977).
+char(p,33978).
+char(o,33979).
+char(m,33980).
+char(o,33981).
+char(p,33982).
+char(2,33983).
+char(3,33984).
+char(0,33985).
+char(9,33986).
+char(m,33987).
+char(5,33988).
+char(1,33989).
+char(3,33990).
+char(7,33991).
+char(c,33992).
+char(c,33993).
+char(m,33994).
+char(2,33995).
+char(8,33996).
+char(9,33997).
+char(0,33998).
+char(m,33999).
+char(1,34000).
+char(5,34001).
+char(6,34002).
+char(9,34003).
+char(c,34004).
+char(p,34005).
+char(o,34006).
+char(o,34007).
+char(5,34008).
+char(6,34009).
+char(2,34010).
+char(7,34011).
+char(m,34012).
+char(o,34013).
+char(p,34014).
+char(o,34015).
+char(6,34016).
+char(6,34017).
+char(0,34018).
+char(8,34019).
+char(c,34020).
+char(c,34021).
+char(p,34022).
+char(3,34023).
+char(7,34024).
+char(7,34025).
+char(2,34026).
+char(p,34027).
+char(o,34028).
+char(p,34029).
+char(3,34030).
+char(0,34031).
+char(9,34032).
+char(4,34033).
+char(c,34034).
+char(m,34035).
+char(6,34036).
+char(9,34037).
+char(6,34038).
+char(0,34039).
+char(m,34040).
+char(o,34041).
+char(o,34042).
+char(m,34043).
+char(3,34044).
+char(5,34045).
+char(7,34046).
+char(6,34047).
+char(c,34048).
+char(p,34049).
+char(4,34050).
+char(8,34051).
+char(7,34052).
+char(8,34053).
+char(p,34054).
+char(6,34055).
+char(0,34056).
+char(2,34057).
+char(0,34058).
+char(c,34059).
+char(c,34060).
+char(p,34061).
+char(2,34062).
+char(0,34063).
+char(3,34064).
+char(4,34065).
+char(m,34066).
+char(7,34067).
+char(2,34068).
+char(2,34069).
+char(7,34070).
+char(m,34071).
+char(o,34072).
+char(p,34073).
+char(8,34074).
+char(0,34075).
+char(3,34076).
+char(3,34077).
+char(c,34078).
+char(c,34079).
+char(m,34080).
+char(o,34081).
+char(9,34082).
+char(2,34083).
+char(7,34084).
+char(5,34085).
+char(m,34086).
+char(o,34087).
+char(o,34088).
+char(m,34089).
+char(o,34090).
+char(4,34091).
+char(8,34092).
+char(8,34093).
+char(1,34094).
+char(c,34095).
+char(m,34096).
+char(6,34097).
+char(5,34098).
+char(9,34099).
+char(9,34100).
+char(c,34101).
+char(m,34102).
+char(o,34103).
+char(m,34104).
+char(4,34105).
+char(8,34106).
+char(4,34107).
+char(7,34108).
+char(c,34109).
+char(m,34110).
+char(6,34111).
+char(9,34112).
+char(7,34113).
+char(2,34114).
+char(p,34115).
+char(o,34116).
+char(1,34117).
+char(6,34118).
+char(2,34119).
+char(1,34120).
+char(c,34121).
+char(c,34122).
+char(c,34123).
+char(p,34124).
+char(9,34125).
+char(6,34126).
+char(6,34127).
+char(4,34128).
+char(p,34129).
+char(8,34130).
+char(9,34131).
+char(6,34132).
+char(m,34133).
+char(3,34134).
+char(7,34135).
+char(4,34136).
+char(0,34137).
+char(p,34138).
+char(o,34139).
+char(p,34140).
+char(3,34141).
+char(6,34142).
+char(5,34143).
+char(1,34144).
+char(m,34145).
+char(8,34146).
+char(0,34147).
+char(2,34148).
+char(1,34149).
+char(c,34150).
+char(m,34151).
+char(1,34152).
+char(4,34153).
+char(4,34154).
+char(0,34155).
+char(p,34156).
+char(o,34157).
+char(m,34158).
+char(o,34159).
+char(m,34160).
+char(8,34161).
+char(7,34162).
+char(9,34163).
+char(3,34164).
+char(p,34165).
+char(o,34166).
+char(m,34167).
+char(5,34168).
+char(1,34169).
+char(9,34170).
+char(0,34171).
+char(p,34172).
+char(o,34173).
+char(p,34174).
+char(o,34175).
+char(p,34176).
+char(2,34177).
+char(7,34178).
+char(4,34179).
+char(2,34180).
+char(m,34181).
+char(o,34182).
+char(p,34183).
+char(o,34184).
+char(m,34185).
+char(o,34186).
+char(p,34187).
+char(7,34188).
+char(0,34189).
+char(8,34190).
+char(7,34191).
+char(c,34192).
+char(c,34193).
+char(c,34194).
+char(p,34195).
+char(o,34196).
+char(p,34197).
+char(5,34198).
+char(9,34199).
+char(7,34200).
+char(6,34201).
+char(c,34202).
+char(m,34203).
+char(o,34204).
+char(m,34205).
+char(3,34206).
+char(5,34207).
+char(7,34208).
+char(8,34209).
+char(c,34210).
+char(m,34211).
+char(o,34212).
+char(p,34213).
+char(2,34214).
+char(9,34215).
+char(5,34216).
+char(3,34217).
+char(c,34218).
+char(c,34219).
+char(c,34220).
+char(m,34221).
+char(o,34222).
+char(8,34223).
+char(5,34224).
+char(7,34225).
+char(c,34226).
+char(m,34227).
+char(2,34228).
+char(0,34229).
+char(1,34230).
+char(3,34231).
+char(c,34232).
+char(c,34233).
+char(c,34234).
+char(c,34235).
+char(c,34236).
+char(c,34237).
+char(p,34238).
+char(3,34239).
+char(1,34240).
+char(1,34241).
+char(1,34242).
+char(c,34243).
+char(p,34244).
+char(9,34245).
+char(0,34246).
+char(3,34247).
+char(0,34248).
+char(m,34249).
+char(5,34250).
+char(8,34251).
+char(6,34252).
+char(9,34253).
+char(c,34254).
+char(c,34255).
+char(c,34256).
+char(c,34257).
+char(c,34258).
+char(p,34259).
+char(o,34260).
+char(m,34261).
+char(4,34262).
+char(9,34263).
+char(7,34264).
+char(2,34265).
+char(m,34266).
+char(o,34267).
+char(5,34268).
+char(5,34269).
+char(7,34270).
+char(6,34271).
+char(p,34272).
+char(o,34273).
+char(o,34274).
+char(4,34275).
+char(1,34276).
+char(9,34277).
+char(1,34278).
+char(c,34279).
+char(c,34280).
+char(p,34281).
+char(o,34282).
+char(m,34283).
+char(o,34284).
+char(m,34285).
+char(8,34286).
+char(3,34287).
+char(9,34288).
+char(7,34289).
+char(c,34290).
+char(m,34291).
+char(8,34292).
+char(0,34293).
+char(3,34294).
+char(1,34295).
+char(m,34296).
+char(3,34297).
+char(0,34298).
+char(1,34299).
+char(4,34300).
+char(c,34301).
+char(c,34302).
+char(c,34303).
+char(p,34304).
+char(o,34305).
+char(p,34306).
+char(6,34307).
+char(4,34308).
+char(2,34309).
+char(7,34310).
+char(p,34311).
+char(o,34312).
+char(m,34313).
+char(o,34314).
+char(p,34315).
+char(o,34316).
+char(m,34317).
+char(o,34318).
+char(m,34319).
+char(o,34320).
+char(3,34321).
+char(2,34322).
+char(3,34323).
+char(4,34324).
+char(m,34325).
+char(7,34326).
+char(6,34327).
+char(8,34328).
+char(4,34329).
+char(m,34330).
+char(o,34331).
+char(5,34332).
+char(8,34333).
+char(4,34334).
+char(1,34335).
+char(p,34336).
+char(2,34337).
+char(6,34338).
+char(5,34339).
+char(1,34340).
+char(c,34341).
+char(c,34342).
+char(c,34343).
+char(m,34344).
+char(o,34345).
+char(m,34346).
+char(o,34347).
+char(m,34348).
+char(7,34349).
+char(5,34350).
+char(4,34351).
+char(6,34352).
+char(c,34353).
+char(c,34354).
+char(c,34355).
+char(c,34356).
+char(m,34357).
+char(o,34358).
+char(p,34359).
+char(2,34360).
+char(5,34361).
+char(0,34362).
+char(7,34363).
+char(m,34364).
+char(o,34365).
+char(p,34366).
+char(o,34367).
+char(p,34368).
+char(8,34369).
+char(9,34370).
+char(6,34371).
+char(5,34372).
+char(c,34373).
+char(c,34374).
+char(c,34375).
+char(p,34376).
+char(o,34377).
+char(p,34378).
+char(7,34379).
+char(7,34380).
+char(6,34381).
+char(7,34382).
+char(c,34383).
+char(c,34384).
+char(c,34385).
+char(c,34386).
+char(c,34387).
+char(c,34388).
+char(p,34389).
+char(8,34390).
+char(0,34391).
+char(7,34392).
+char(5,34393).
+char(c,34394).
+char(c,34395).
+char(c,34396).
+char(m,34397).
+char(6,34398).
+char(6,34399).
+char(2,34400).
+char(5,34401).
+char(c,34402).
+char(m,34403).
+char(1,34404).
+char(5,34405).
+char(0,34406).
+char(4,34407).
+char(c,34408).
+char(c,34409).
+char(p,34410).
+char(6,34411).
+char(5,34412).
+char(2,34413).
+char(5,34414).
+char(m,34415).
+char(6,34416).
+char(1,34417).
+char(8,34418).
+char(5,34419).
+char(m,34420).
+char(o,34421).
+char(o,34422).
+char(m,34423).
+char(7,34424).
+char(9,34425).
+char(4,34426).
+char(8,34427).
+char(c,34428).
+char(c,34429).
+char(c,34430).
+char(c,34431).
+char(c,34432).
+char(m,34433).
+char(o,34434).
+char(8,34435).
+char(6,34436).
+char(6,34437).
+char(c,34438).
+char(m,34439).
+char(o,34440).
+char(m,34441).
+char(o,34442).
+char(m,34443).
+char(o,34444).
+char(o,34445).
+char(m,34446).
+char(o,34447).
+char(m,34448).
+char(9,34449).
+char(7,34450).
+char(9,34451).
+char(m,34452).
+char(o,34453).
+char(p,34454).
+char(o,34455).
+char(o,34456).
+char(m,34457).
+char(o,34458).
+char(3,34459).
+char(6,34460).
+char(7,34461).
+char(7,34462).
+char(m,34463).
+char(6,34464).
+char(1,34465).
+char(0,34466).
+char(8,34467).
+char(m,34468).
+char(3,34469).
+char(7,34470).
+char(1,34471).
+char(5,34472).
+char(c,34473).
+char(p,34474).
+char(o,34475).
+char(p,34476).
+char(o,34477).
+char(m,34478).
+char(4,34479).
+char(0,34480).
+char(0,34481).
+char(3,34482).
+char(c,34483).
+char(c,34484).
+char(c,34485).
+char(c,34486).
+char(c,34487).
+char(c,34488).
+char(c,34489).
+char(p,34490).
+char(5,34491).
+char(1,34492).
+char(6,34493).
+char(1,34494).
+char(c,34495).
+char(p,34496).
+char(6,34497).
+char(9,34498).
+char(7,34499).
+char(6,34500).
+char(c,34501).
+char(c,34502).
+char(m,34503).
+char(o,34504).
+char(1,34505).
+char(3,34506).
+char(6,34507).
+char(7,34508).
+char(p,34509).
+char(9,34510).
+char(5,34511).
+char(3,34512).
+char(9,34513).
+char(c,34514).
+char(c,34515).
+char(c,34516).
+char(c,34517).
+char(m,34518).
+char(o,34519).
+char(m,34520).
+char(o,34521).
+char(p,34522).
+char(o,34523).
+char(m,34524).
+char(4,34525).
+char(3,34526).
+char(6,34527).
+char(5,34528).
+char(p,34529).
+char(o,34530).
+char(m,34531).
+char(4,34532).
+char(8,34533).
+char(9,34534).
+char(3,34535).
+char(m,34536).
+char(9,34537).
+char(9,34538).
+char(3,34539).
+char(8,34540).
+char(m,34541).
+char(1,34542).
+char(2,34543).
+char(4,34544).
+char(2,34545).
+char(c,34546).
+char(c,34547).
+char(m,34548).
+char(4,34549).
+char(0,34550).
+char(1,34551).
+char(3,34552).
+char(m,34553).
+char(9,34554).
+char(4,34555).
+char(6,34556).
+char(0,34557).
+char(c,34558).
+char(c,34559).
+char(m,34560).
+char(o,34561).
+char(m,34562).
+char(o,34563).
+char(p,34564).
+char(5,34565).
+char(9,34566).
+char(9,34567).
+char(3,34568).
+char(p,34569).
+char(2,34570).
+char(4,34571).
+char(5,34572).
+char(4,34573).
+char(c,34574).
+char(p,34575).
+char(o,34576).
+char(m,34577).
+char(o,34578).
+char(p,34579).
+char(o,34580).
+char(p,34581).
+char(o,34582).
+char(m,34583).
+char(o,34584).
+char(5,34585).
+char(3,34586).
+char(7,34587).
+char(3,34588).
+char(p,34589).
+char(o,34590).
+char(m,34591).
+char(o,34592).
+char(p,34593).
+char(2,34594).
+char(2,34595).
+char(7,34596).
+char(4,34597).
+char(c,34598).
+char(m,34599).
+char(7,34600).
+char(7,34601).
+char(7,34602).
+char(3,34603).
+char(c,34604).
+char(c,34605).
+char(m,34606).
+char(o,34607).
+char(m,34608).
+char(6,34609).
+char(0,34610).
+char(0,34611).
+char(c,34612).
+char(p,34613).
+char(o,34614).
+char(m,34615).
+char(o,34616).
+char(p,34617).
+char(o,34618).
+char(m,34619).
+char(o,34620).
+char(m,34621).
+char(4,34622).
+char(5,34623).
+char(5,34624).
+char(7,34625).
+char(m,34626).
+char(o,34627).
+char(p,34628).
+char(o,34629).
+char(p,34630).
+char(8,34631).
+char(8,34632).
+char(2,34633).
+char(5,34634).
+char(c,34635).
+char(c,34636).
+char(c,34637).
+char(m,34638).
+char(o,34639).
+char(p,34640).
+char(o,34641).
+char(p,34642).
+char(1,34643).
+char(8,34644).
+char(1,34645).
+char(2,34646).
+char(m,34647).
+char(o,34648).
+char(p,34649).
+char(7,34650).
+char(8,34651).
+char(7,34652).
+char(0,34653).
+char(c,34654).
+char(m,34655).
+char(1,34656).
+char(8,34657).
+char(4,34658).
+char(8,34659).
+char(p,34660).
+char(2,34661).
+char(2,34662).
+char(5,34663).
+char(p,34664).
+char(o,34665).
+char(o,34666).
+char(p,34667).
+char(7,34668).
+char(2,34669).
+char(9,34670).
+char(0,34671).
+char(m,34672).
+char(o,34673).
+char(m,34674).
+char(7,34675).
+char(6,34676).
+char(9,34677).
+char(4,34678).
+char(c,34679).
+char(p,34680).
+char(o,34681).
+char(o,34682).
+char(9,34683).
+char(5,34684).
+char(3,34685).
+char(0,34686).
+char(p,34687).
+char(1,34688).
+char(0,34689).
+char(3,34690).
+char(6,34691).
+char(m,34692).
+char(7,34693).
+char(4,34694).
+char(3,34695).
+char(2,34696).
+char(m,34697).
+char(o,34698).
+char(6,34699).
+char(1,34700).
+char(9,34701).
+char(5,34702).
+char(c,34703).
+char(c,34704).
+char(c,34705).
+char(p,34706).
+char(5,34707).
+char(9,34708).
+char(1,34709).
+char(2,34710).
+char(c,34711).
+char(m,34712).
+char(o,34713).
+char(m,34714).
+char(7,34715).
+char(8,34716).
+char(8,34717).
+char(8,34718).
+char(c,34719).
+char(p,34720).
+char(2,34721).
+char(1,34722).
+char(7,34723).
+char(3,34724).
+char(m,34725).
+char(8,34726).
+char(2,34727).
+char(7,34728).
+char(8,34729).
+char(m,34730).
+char(o,34731).
+char(2,34732).
+char(7,34733).
+char(7,34734).
+char(0,34735).
+char(p,34736).
+char(o,34737).
+char(p,34738).
+char(o,34739).
+char(p,34740).
+char(8,34741).
+char(8,34742).
+char(0,34743).
+char(2,34744).
+char(p,34745).
+char(9,34746).
+char(4,34747).
+char(6,34748).
+char(8,34749).
+char(c,34750).
+char(p,34751).
+char(o,34752).
+char(m,34753).
+char(o,34754).
+char(m,34755).
+char(o,34756).
+char(4,34757).
+char(4,34758).
+char(0,34759).
+char(3,34760).
+char(c,34761).
+char(p,34762).
+char(o,34763).
+char(m,34764).
+char(o,34765).
+char(o,34766).
+char(p,34767).
+char(o,34768).
+char(p,34769).
+char(o,34770).
+char(4,34771).
+char(6,34772).
+char(0,34773).
+char(3,34774).
+char(c,34775).
+char(c,34776).
+char(p,34777).
+char(o,34778).
+char(9,34779).
+char(8,34780).
+char(9,34781).
+char(c,34782).
+char(c,34783).
+char(p,34784).
+char(2,34785).
+char(0,34786).
+char(7,34787).
+char(0,34788).
+char(p,34789).
+char(6,34790).
+char(2,34791).
+char(9,34792).
+char(8,34793).
+char(m,34794).
+char(o,34795).
+char(p,34796).
+char(2,34797).
+char(8,34798).
+char(5,34799).
+char(0,34800).
+char(c,34801).
+char(c,34802).
+char(c,34803).
+char(c,34804).
+char(c,34805).
+char(p,34806).
+char(2,34807).
+char(9,34808).
+char(4,34809).
+char(0,34810).
+char(c,34811).
+char(p,34812).
+char(o,34813).
+char(4,34814).
+char(6,34815).
+char(5,34816).
+char(2,34817).
+char(c,34818).
+char(m,34819).
+char(4,34820).
+char(0,34821).
+char(0,34822).
+char(0,34823).
+char(c,34824).
+char(c,34825).
+char(m,34826).
+char(9,34827).
+char(8,34828).
+char(8,34829).
+char(c,34830).
+char(m,34831).
+char(o,34832).
+char(p,34833).
+char(o,34834).
+char(p,34835).
+char(o,34836).
+char(5,34837).
+char(9,34838).
+char(0,34839).
+char(2,34840).
+char(m,34841).
+char(o,34842).
+char(3,34843).
+char(8,34844).
+char(4,34845).
+char(4,34846).
+char(c,34847).
+char(p,34848).
+char(o,34849).
+char(p,34850).
+char(3,34851).
+char(9,34852).
+char(8,34853).
+char(5,34854).
+char(m,34855).
+char(o,34856).
+char(o,34857).
+char(p,34858).
+char(o,34859).
+char(p,34860).
+char(o,34861).
+char(p,34862).
+char(o,34863).
+char(6,34864).
+char(5,34865).
+char(0,34866).
+char(0,34867).
+char(c,34868).
+char(m,34869).
+char(o,34870).
+char(p,34871).
+char(o,34872).
+char(m,34873).
+char(o,34874).
+char(2,34875).
+char(5,34876).
+char(1,34877).
+char(2,34878).
+char(c,34879).
+char(p,34880).
+char(o,34881).
+char(m,34882).
+char(o,34883).
+char(p,34884).
+char(2,34885).
+char(4,34886).
+char(8,34887).
+char(4,34888).
+char(c,34889).
+char(c,34890).
+char(c,34891).
+char(c,34892).
+char(m,34893).
+char(5,34894).
+char(1,34895).
+char(6,34896).
+char(8,34897).
+char(p,34898).
+char(o,34899).
+char(o,34900).
+char(m,34901).
+char(9,34902).
+char(4,34903).
+char(0,34904).
+char(1,34905).
+char(m,34906).
+char(o,34907).
+char(p,34908).
+char(o,34909).
+char(p,34910).
+char(o,34911).
+char(p,34912).
+char(9,34913).
+char(4,34914).
+char(6,34915).
+char(0,34916).
+char(m,34917).
+char(o,34918).
+char(p,34919).
+char(o,34920).
+char(p,34921).
+char(o,34922).
+char(p,34923).
+char(8,34924).
+char(9,34925).
+char(4,34926).
+char(4,34927).
+char(p,34928).
+char(o,34929).
+char(9,34930).
+char(8,34931).
+char(7,34932).
+char(2,34933).
+char(p,34934).
+char(o,34935).
+char(p,34936).
+char(8,34937).
+char(4,34938).
+char(8,34939).
+char(9,34940).
+char(c,34941).
+char(p,34942).
+char(o,34943).
+char(o,34944).
+char(o,34945).
+char(p,34946).
+char(o,34947).
+char(o,34948).
+char(o,34949).
+char(m,34950).
+char(1,34951).
+char(9,34952).
+char(3,34953).
+char(5,34954).
+char(c,34955).
+char(m,34956).
+char(9,34957).
+char(8,34958).
+char(8,34959).
+char(9,34960).
+char(c,34961).
+char(c,34962).
+char(c,34963).
+char(m,34964).
+char(o,34965).
+char(o,34966).
+char(m,34967).
+char(o,34968).
+char(o,34969).
+char(m,34970).
+char(1,34971).
+char(5,34972).
+char(3,34973).
+char(2,34974).
+char(p,34975).
+char(5,34976).
+char(1,34977).
+char(0,34978).
+char(0,34979).
+char(c,34980).
+char(c,34981).
+char(c,34982).
+char(c,34983).
+char(c,34984).
+char(p,34985).
+char(9,34986).
+char(4,34987).
+char(0,34988).
+char(9,34989).
+char(p,34990).
+char(7,34991).
+char(0,34992).
+char(4,34993).
+char(2,34994).
+char(m,34995).
+char(o,34996).
+char(m,34997).
+char(o,34998).
+char(p,34999).
+char(o,35000).
+char(p,35001).
+char(o,35002).
+char(p,35003).
+char(o,35004).
+char(m,35005).
+char(1,35006).
+char(6,35007).
+char(9,35008).
+char(9,35009).
+char(p,35010).
+char(2,35011).
+char(1,35012).
+char(4,35013).
+char(8,35014).
+char(p,35015).
+char(4,35016).
+char(4,35017).
+char(4,35018).
+char(7,35019).
+char(c,35020).
+char(c,35021).
+char(m,35022).
+char(8,35023).
+char(8,35024).
+char(2,35025).
+char(2,35026).
+char(c,35027).
+char(m,35028).
+char(4,35029).
+char(7,35030).
+char(6,35031).
+char(c,35032).
+char(m,35033).
+char(1,35034).
+char(3,35035).
+char(6,35036).
+char(9,35037).
+char(c,35038).
+char(m,35039).
+char(1,35040).
+char(0,35041).
+char(1,35042).
+char(9,35043).
+char(p,35044).
+char(o,35045).
+char(o,35046).
+char(o,35047).
+char(o,35048).
+char(o,35049).
+char(o,35050).
+char(3,35051).
+char(9,35052).
+char(9,35053).
+char(3,35054).
+char(p,35055).
+char(8,35056).
+char(2,35057).
+char(9,35058).
+char(1,35059).
+char(c,35060).
+char(p,35061).
+char(2,35062).
+char(9,35063).
+char(4,35064).
+char(6,35065).
+char(m,35066).
+char(5,35067).
+char(7,35068).
+char(6,35069).
+char(5,35070).
+char(c,35071).
+char(c,35072).
+char(m,35073).
+char(o,35074).
+char(o,35075).
+char(p,35076).
+char(o,35077).
+char(o,35078).
+char(m,35079).
+char(5,35080).
+char(5,35081).
+char(6,35082).
+char(3,35083).
+char(p,35084).
+char(o,35085).
+char(m,35086).
+char(o,35087).
+char(o,35088).
+char(p,35089).
+char(5,35090).
+char(3,35091).
+char(0,35092).
+char(5,35093).
+char(c,35094).
+char(c,35095).
+char(m,35096).
+char(o,35097).
+char(o,35098).
+char(o,35099).
+char(o,35100).
+char(m,35101).
+char(o,35102).
+char(m,35103).
+char(o,35104).
+char(4,35105).
+char(0,35106).
+char(0,35107).
+char(1,35108).
+char(p,35109).
+char(o,35110).
+char(m,35111).
+char(2,35112).
+char(4,35113).
+char(0,35114).
+char(3,35115).
+char(p,35116).
+char(o,35117).
+char(3,35118).
+char(4,35119).
+char(8,35120).
+char(5,35121).
+char(m,35122).
+char(o,35123).
+char(o,35124).
+char(m,35125).
+char(o,35126).
+char(o,35127).
+char(5,35128).
+char(6,35129).
+char(1,35130).
+char(7,35131).
+char(c,35132).
+char(c,35133).
+char(c,35134).
+char(m,35135).
+char(6,35136).
+char(5,35137).
+char(4,35138).
+char(5,35139).
+char(p,35140).
+char(o,35141).
+char(p,35142).
+char(3,35143).
+char(9,35144).
+char(1,35145).
+char(c,35146).
+char(c,35147).
+char(m,35148).
+char(o,35149).
+char(o,35150).
+char(p,35151).
+char(o,35152).
+char(o,35153).
+char(p,35154).
+char(2,35155).
+char(7,35156).
+char(4,35157).
+char(1,35158).
+char(c,35159).
+char(p,35160).
+char(7,35161).
+char(3,35162).
+char(0,35163).
+char(8,35164).
+char(c,35165).
+char(p,35166).
+char(o,35167).
+char(m,35168).
+char(1,35169).
+char(2,35170).
+char(0,35171).
+char(0,35172).
+char(c,35173).
+char(c,35174).
+char(m,35175).
+char(o,35176).
+char(o,35177).
+char(p,35178).
+char(3,35179).
+char(9,35180).
+char(3,35181).
+char(2,35182).
+char(p,35183).
+char(7,35184).
+char(6,35185).
+char(2,35186).
+char(7,35187).
+char(m,35188).
+char(7,35189).
+char(9,35190).
+char(0,35191).
+char(2,35192).
+char(c,35193).
+char(c,35194).
+char(c,35195).
+char(m,35196).
+char(o,35197).
+char(m,35198).
+char(7,35199).
+char(5,35200).
+char(6,35201).
+char(0,35202).
+char(c,35203).
+char(m,35204).
+char(o,35205).
+char(o,35206).
+char(p,35207).
+char(o,35208).
+char(p,35209).
+char(8,35210).
+char(3,35211).
+char(6,35212).
+char(2,35213).
+char(c,35214).
+char(c,35215).
+char(c,35216).
+char(m,35217).
+char(5,35218).
+char(8,35219).
+char(7,35220).
+char(3,35221).
+char(m,35222).
+char(o,35223).
+char(o,35224).
+char(m,35225).
+char(o,35226).
+char(p,35227).
+char(o,35228).
+char(p,35229).
+char(5,35230).
+char(6,35231).
+char(2,35232).
+char(6,35233).
+char(c,35234).
+char(c,35235).
+char(p,35236).
+char(4,35237).
+char(7,35238).
+char(2,35239).
+char(9,35240).
+char(c,35241).
+char(c,35242).
+char(c,35243).
+char(p,35244).
+char(4,35245).
+char(5,35246).
+char(6,35247).
+char(3,35248).
+char(c,35249).
+char(c,35250).
+char(p,35251).
+char(9,35252).
+char(6,35253).
+char(6,35254).
+char(c,35255).
+char(p,35256).
+char(o,35257).
+char(m,35258).
+char(3,35259).
+char(1,35260).
+char(8,35261).
+char(2,35262).
+char(m,35263).
+char(o,35264).
+char(p,35265).
+char(1,35266).
+char(1,35267).
+char(2,35268).
+char(7,35269).
+char(m,35270).
+char(o,35271).
+char(5,35272).
+char(1,35273).
+char(0,35274).
+char(3,35275).
+char(m,35276).
+char(2,35277).
+char(4,35278).
+char(9,35279).
+char(1,35280).
+char(m,35281).
+char(o,35282).
+char(p,35283).
+char(o,35284).
+char(p,35285).
+char(o,35286).
+char(p,35287).
+char(o,35288).
+char(p,35289).
+char(9,35290).
+char(1,35291).
+char(5,35292).
+char(5,35293).
+char(m,35294).
+char(6,35295).
+char(9,35296).
+char(6,35297).
+char(4,35298).
+char(m,35299).
+char(4,35300).
+char(0,35301).
+char(5,35302).
+char(7,35303).
+char(c,35304).
+char(c,35305).
+char(c,35306).
+char(m,35307).
+char(o,35308).
+char(p,35309).
+char(o,35310).
+char(o,35311).
+char(o,35312).
+char(o,35313).
+char(p,35314).
+char(2,35315).
+char(9,35316).
+char(6,35317).
+char(9,35318).
+char(c,35319).
+char(c,35320).
+char(c,35321).
+char(c,35322).
+char(c,35323).
+char(c,35324).
+char(p,35325).
+char(3,35326).
+char(7,35327).
+char(7,35328).
+char(5,35329).
+char(m,35330).
+char(o,35331).
+char(p,35332).
+char(o,35333).
+char(p,35334).
+char(4,35335).
+char(1,35336).
+char(9,35337).
+char(1,35338).
+char(m,35339).
+char(o,35340).
+char(p,35341).
+char(1,35342).
+char(6,35343).
+char(8,35344).
+char(7,35345).
+char(c,35346).
+char(m,35347).
+char(o,35348).
+char(o,35349).
+char(o,35350).
+char(m,35351).
+char(3,35352).
+char(7,35353).
+char(2,35354).
+char(5,35355).
+char(p,35356).
+char(o,35357).
+char(m,35358).
+char(8,35359).
+char(1,35360).
+char(5,35361).
+char(c,35362).
+char(c,35363).
+char(c,35364).
+char(p,35365).
+char(o,35366).
+char(p,35367).
+char(6,35368).
+char(1,35369).
+char(9,35370).
+char(7,35371).
+char(c,35372).
+char(c,35373).
+char(c,35374).
+char(c,35375).
+char(c,35376).
+char(c,35377).
+char(m,35378).
+char(4,35379).
+char(6,35380).
+char(0,35381).
+char(8,35382).
+char(m,35383).
+char(4,35384).
+char(3,35385).
+char(0,35386).
+char(4,35387).
+char(c,35388).
+char(p,35389).
+char(o,35390).
+char(o,35391).
+char(m,35392).
+char(5,35393).
+char(6,35394).
+char(7,35395).
+char(3,35396).
+char(m,35397).
+char(2,35398).
+char(7,35399).
+char(3,35400).
+char(0,35401).
+char(c,35402).
+char(c,35403).
+char(c,35404).
+char(p,35405).
+char(o,35406).
+char(5,35407).
+char(7,35408).
+char(6,35409).
+char(5,35410).
+char(c,35411).
+char(p,35412).
+char(o,35413).
+char(p,35414).
+char(8,35415).
+char(3,35416).
+char(4,35417).
+char(6,35418).
+char(p,35419).
+char(1,35420).
+char(7,35421).
+char(3,35422).
+char(2,35423).
+char(m,35424).
+char(1,35425).
+char(9,35426).
+char(3,35427).
+char(8,35428).
+char(c,35429).
+char(c,35430).
+char(c,35431).
+char(c,35432).
+char(p,35433).
+char(o,35434).
+char(1,35435).
+char(4,35436).
+char(9,35437).
+char(6,35438).
+char(c,35439).
+char(p,35440).
+char(1,35441).
+char(0,35442).
+char(0,35443).
+char(8,35444).
+char(p,35445).
+char(6,35446).
+char(8,35447).
+char(7,35448).
+char(4,35449).
+char(m,35450).
+char(o,35451).
+char(p,35452).
+char(o,35453).
+char(p,35454).
+char(o,35455).
+char(p,35456).
+char(o,35457).
+char(m,35458).
+char(o,35459).
+char(o,35460).
+char(p,35461).
+char(9,35462).
+char(1,35463).
+char(3,35464).
+char(6,35465).
+char(c,35466).
+char(p,35467).
+char(o,35468).
+char(m,35469).
+char(9,35470).
+char(1,35471).
+char(9,35472).
+char(4,35473).
+char(m,35474).
+char(5,35475).
+char(8,35476).
+char(4,35477).
+char(5,35478).
+char(c,35479).
+char(m,35480).
+char(3,35481).
+char(6,35482).
+char(5,35483).
+char(2,35484).
+char(c,35485).
+char(c,35486).
+char(m,35487).
+char(9,35488).
+char(9,35489).
+char(1,35490).
+char(7,35491).
+char(p,35492).
+char(o,35493).
+char(m,35494).
+char(6,35495).
+char(0,35496).
+char(7,35497).
+char(1,35498).
+char(c,35499).
+char(c,35500).
+char(m,35501).
+char(o,35502).
+char(m,35503).
+char(o,35504).
+char(3,35505).
+char(6,35506).
+char(2,35507).
+char(4,35508).
+char(p,35509).
+char(2,35510).
+char(2,35511).
+char(0,35512).
+char(3,35513).
+char(c,35514).
+char(c,35515).
+char(m,35516).
+char(o,35517).
+char(p,35518).
+char(5,35519).
+char(7,35520).
+char(4,35521).
+char(p,35522).
+char(o,35523).
+char(o,35524).
+char(m,35525).
+char(o,35526).
+char(m,35527).
+char(1,35528).
+char(6,35529).
+char(6,35530).
+char(0,35531).
+char(c,35532).
+char(m,35533).
+char(1,35534).
+char(9,35535).
+char(0,35536).
+char(9,35537).
+char(c,35538).
+char(c,35539).
+char(c,35540).
+char(p,35541).
+char(7,35542).
+char(3,35543).
+char(9,35544).
+char(9,35545).
+char(m,35546).
+char(o,35547).
+char(7,35548).
+char(8,35549).
+char(5,35550).
+char(8,35551).
+char(c,35552).
+char(c,35553).
+char(m,35554).
+char(o,35555).
+char(o,35556).
+char(p,35557).
+char(5,35558).
+char(4,35559).
+char(2,35560).
+char(8,35561).
+char(m,35562).
+char(3,35563).
+char(3,35564).
+char(8,35565).
+char(6,35566).
+char(c,35567).
+char(c,35568).
+char(p,35569).
+char(9,35570).
+char(0,35571).
+char(8,35572).
+char(8,35573).
+char(c,35574).
+char(c,35575).
+char(c,35576).
+char(m,35577).
+char(o,35578).
+char(m,35579).
+char(o,35580).
+char(m,35581).
+char(o,35582).
+char(1,35583).
+char(1,35584).
+char(4,35585).
+char(1,35586).
+char(p,35587).
+char(o,35588).
+char(p,35589).
+char(4,35590).
+char(3,35591).
+char(6,35592).
+char(7,35593).
+char(c,35594).
+char(c,35595).
+char(m,35596).
+char(o,35597).
+char(m,35598).
+char(5,35599).
+char(1,35600).
+char(1,35601).
+char(c,35602).
+char(c,35603).
+char(m,35604).
+char(8,35605).
+char(8,35606).
+char(4,35607).
+char(8,35608).
+char(c,35609).
+char(p,35610).
+char(o,35611).
+char(p,35612).
+char(o,35613).
+char(o,35614).
+char(1,35615).
+char(4,35616).
+char(0,35617).
+char(3,35618).
+char(p,35619).
+char(3,35620).
+char(6,35621).
+char(9,35622).
+char(0,35623).
+char(m,35624).
+char(4,35625).
+char(0,35626).
+char(7,35627).
+char(1,35628).
+char(c,35629).
+char(c,35630).
+char(c,35631).
+char(c,35632).
+char(c,35633).
+char(p,35634).
+char(o,35635).
+char(m,35636).
+char(9,35637).
+char(3,35638).
+char(8,35639).
+char(7,35640).
+char(c,35641).
+char(c,35642).
+char(p,35643).
+char(5,35644).
+char(7,35645).
+char(6,35646).
+char(2,35647).
+char(p,35648).
+char(5,35649).
+char(1,35650).
+char(8,35651).
+char(9,35652).
+char(c,35653).
+char(m,35654).
+char(o,35655).
+char(p,35656).
+char(o,35657).
+char(5,35658).
+char(3,35659).
+char(4,35660).
+char(1,35661).
+char(m,35662).
+char(o,35663).
+char(3,35664).
+char(5,35665).
+char(4,35666).
+char(7,35667).
+char(m,35668).
+char(o,35669).
+char(o,35670).
+char(m,35671).
+char(5,35672).
+char(3,35673).
+char(7,35674).
+char(4,35675).
+char(c,35676).
+char(c,35677).
+char(c,35678).
+char(p,35679).
+char(7,35680).
+char(3,35681).
+char(9,35682).
+char(2,35683).
+char(c,35684).
+char(c,35685).
+char(c,35686).
+char(m,35687).
+char(o,35688).
+char(m,35689).
+char(3,35690).
+char(9,35691).
+char(8,35692).
+char(8,35693).
+char(p,35694).
+char(o,35695).
+char(p,35696).
+char(4,35697).
+char(9,35698).
+char(8,35699).
+char(3,35700).
+char(p,35701).
+char(3,35702).
+char(9,35703).
+char(3,35704).
+char(2,35705).
+char(m,35706).
+char(o,35707).
+char(m,35708).
+char(o,35709).
+char(m,35710).
+char(1,35711).
+char(1,35712).
+char(7,35713).
+char(1,35714).
+char(c,35715).
+char(c,35716).
+char(c,35717).
+char(c,35718).
+char(c,35719).
+char(c,35720).
+char(c,35721).
+char(p,35722).
+char(2,35723).
+char(9,35724).
+char(6,35725).
+char(6,35726).
+char(m,35727).
+char(o,35728).
+char(o,35729).
+char(p,35730).
+char(4,35731).
+char(4,35732).
+char(3,35733).
+char(2,35734).
+char(m,35735).
+char(9,35736).
+char(9,35737).
+char(8,35738).
+char(1,35739).
+char(m,35740).
+char(o,35741).
+char(m,35742).
+char(6,35743).
+char(9,35744).
+char(8,35745).
+char(2,35746).
+char(p,35747).
+char(1,35748).
+char(1,35749).
+char(9,35750).
+char(c,35751).
+char(c,35752).
+char(p,35753).
+char(1,35754).
+char(0,35755).
+char(5,35756).
+char(2,35757).
+char(m,35758).
+char(9,35759).
+char(6,35760).
+char(3,35761).
+char(9,35762).
+char(m,35763).
+char(o,35764).
+char(5,35765).
+char(7,35766).
+char(3,35767).
+char(2,35768).
+char(p,35769).
+char(o,35770).
+char(p,35771).
+char(o,35772).
+char(p,35773).
+char(o,35774).
+char(o,35775).
+char(p,35776).
+char(o,35777).
+char(m,35778).
+char(6,35779).
+char(2,35780).
+char(3,35781).
+char(8,35782).
+char(c,35783).
+char(m,35784).
+char(2,35785).
+char(1,35786).
+char(7,35787).
+char(6,35788).
+char(m,35789).
+char(8,35790).
+char(2,35791).
+char(5,35792).
+char(9,35793).
+char(c,35794).
+char(p,35795).
+char(o,35796).
+char(p,35797).
+char(o,35798).
+char(p,35799).
+char(o,35800).
+char(p,35801).
+char(o,35802).
+char(p,35803).
+char(9,35804).
+char(4,35805).
+char(6,35806).
+char(1,35807).
+char(c,35808).
+char(c,35809).
+char(c,35810).
+char(c,35811).
+char(m,35812).
+char(o,35813).
+char(o,35814).
+char(m,35815).
+char(6,35816).
+char(8,35817).
+char(2,35818).
+char(6,35819).
+char(c,35820).
+char(p,35821).
+char(o,35822).
+char(9,35823).
+char(4,35824).
+char(1,35825).
+char(1,35826).
+char(m,35827).
+char(8,35828).
+char(6,35829).
+char(3,35830).
+char(5,35831).
+char(m,35832).
+char(6,35833).
+char(6,35834).
+char(7,35835).
+char(7,35836).
+char(c,35837).
+char(c,35838).
+char(c,35839).
+char(c,35840).
+char(p,35841).
+char(1,35842).
+char(3,35843).
+char(4,35844).
+char(9,35845).
+char(m,35846).
+char(o,35847).
+char(p,35848).
+char(o,35849).
+char(p,35850).
+char(5,35851).
+char(5,35852).
+char(9,35853).
+char(3,35854).
+char(c,35855).
+char(p,35856).
+char(7,35857).
+char(2,35858).
+char(1,35859).
+char(p,35860).
+char(o,35861).
+char(p,35862).
+char(o,35863).
+char(p,35864).
+char(9,35865).
+char(5,35866).
+char(8,35867).
+char(1,35868).
+char(p,35869).
+char(3,35870).
+char(5,35871).
+char(2,35872).
+char(0,35873).
+char(p,35874).
+char(o,35875).
+char(p,35876).
+char(7,35877).
+char(2,35878).
+char(7,35879).
+char(0,35880).
+char(c,35881).
+char(p,35882).
+char(1,35883).
+char(6,35884).
+char(2,35885).
+char(3,35886).
+char(p,35887).
+char(5,35888).
+char(9,35889).
+char(9,35890).
+char(9,35891).
+char(c,35892).
+char(p,35893).
+char(9,35894).
+char(4,35895).
+char(0,35896).
+char(4,35897).
+char(m,35898).
+char(o,35899).
+char(m,35900).
+char(5,35901).
+char(1,35902).
+char(3,35903).
+char(1,35904).
+char(c,35905).
+char(c,35906).
+char(c,35907).
+char(m,35908).
+char(o,35909).
+char(m,35910).
+char(9,35911).
+char(1,35912).
+char(5,35913).
+char(3,35914).
+char(m,35915).
+char(4,35916).
+char(6,35917).
+char(8,35918).
+char(3,35919).
+char(m,35920).
+char(o,35921).
+char(p,35922).
+char(o,35923).
+char(p,35924).
+char(2,35925).
+char(9,35926).
+char(0,35927).
+char(7,35928).
+char(p,35929).
+char(o,35930).
+char(m,35931).
+char(7,35932).
+char(0,35933).
+char(9,35934).
+char(8,35935).
+char(c,35936).
+char(c,35937).
+char(p,35938).
+char(o,35939).
+char(m,35940).
+char(8,35941).
+char(6,35942).
+char(6,35943).
+char(3,35944).
+char(c,35945).
+char(c,35946).
+char(c,35947).
+char(m,35948).
+char(1,35949).
+char(3,35950).
+char(7,35951).
+char(5,35952).
+char(p,35953).
+char(o,35954).
+char(m,35955).
+char(o,35956).
+char(m,35957).
+char(6,35958).
+char(8,35959).
+char(0,35960).
+char(m,35961).
+char(o,35962).
+char(m,35963).
+char(9,35964).
+char(1,35965).
+char(8,35966).
+char(p,35967).
+char(6,35968).
+char(7,35969).
+char(3,35970).
+char(4,35971).
+char(m,35972).
+char(o,35973).
+char(m,35974).
+char(o,35975).
+char(p,35976).
+char(4,35977).
+char(9,35978).
+char(1,35979).
+char(5,35980).
+char(c,35981).
+char(p,35982).
+char(8,35983).
+char(9,35984).
+char(8,35985).
+char(9,35986).
+char(p,35987).
+char(o,35988).
+char(p,35989).
+char(2,35990).
+char(9,35991).
+char(9,35992).
+char(5,35993).
+char(p,35994).
+char(o,35995).
+char(m,35996).
+char(4,35997).
+char(3,35998).
+char(1,35999).
+char(5,36000).
+char(p,36001).
+char(o,36002).
+char(p,36003).
+char(o,36004).
+char(9,36005).
+char(8,36006).
+char(2,36007).
+char(4,36008).
+char(m,36009).
+char(o,36010).
+char(1,36011).
+char(0,36012).
+char(9,36013).
+char(5,36014).
+char(m,36015).
+char(8,36016).
+char(6,36017).
+char(7,36018).
+char(0,36019).
+char(m,36020).
+char(9,36021).
+char(3,36022).
+char(1,36023).
+char(3,36024).
+char(p,36025).
+char(o,36026).
+char(p,36027).
+char(3,36028).
+char(2,36029).
+char(4,36030).
+char(5,36031).
+char(c,36032).
+char(m,36033).
+char(2,36034).
+char(9,36035).
+char(5,36036).
+char(3,36037).
+char(p,36038).
+char(o,36039).
+char(o,36040).
+char(p,36041).
+char(5,36042).
+char(9,36043).
+char(5,36044).
+char(0,36045).
+char(m,36046).
+char(5,36047).
+char(7,36048).
+char(7,36049).
+char(8,36050).
+char(c,36051).
+char(p,36052).
+char(8,36053).
+char(4,36054).
+char(5,36055).
+char(9,36056).
+char(c,36057).
+char(m,36058).
+char(7,36059).
+char(9,36060).
+char(4,36061).
+char(3,36062).
+char(m,36063).
+char(o,36064).
+char(o,36065).
+char(m,36066).
+char(9,36067).
+char(6,36068).
+char(4,36069).
+char(m,36070).
+char(o,36071).
+char(p,36072).
+char(o,36073).
+char(o,36074).
+char(m,36075).
+char(2,36076).
+char(8,36077).
+char(2,36078).
+char(2,36079).
+char(m,36080).
+char(o,36081).
+char(p,36082).
+char(4,36083).
+char(8,36084).
+char(9,36085).
+char(5,36086).
+char(p,36087).
+char(2,36088).
+char(3,36089).
+char(8,36090).
+char(5,36091).
+char(c,36092).
+char(c,36093).
+char(m,36094).
+char(o,36095).
+char(5,36096).
+char(9,36097).
+char(2,36098).
+char(2,36099).
+char(m,36100).
+char(o,36101).
+char(p,36102).
+char(o,36103).
+char(p,36104).
+char(1,36105).
+char(7,36106).
+char(2,36107).
+char(1,36108).
+char(c,36109).
+char(p,36110).
+char(o,36111).
+char(m,36112).
+char(1,36113).
+char(0,36114).
+char(6,36115).
+char(5,36116).
+char(p,36117).
+char(2,36118).
+char(2,36119).
+char(5,36120).
+char(6,36121).
+char(p,36122).
+char(2,36123).
+char(1,36124).
+char(1,36125).
+char(3,36126).
+char(c,36127).
+char(c,36128).
+char(c,36129).
+char(c,36130).
+char(m,36131).
+char(o,36132).
+char(m,36133).
+char(7,36134).
+char(3,36135).
+char(7,36136).
+char(c,36137).
+char(p,36138).
+char(o,36139).
+char(m,36140).
+char(o,36141).
+char(9,36142).
+char(1,36143).
+char(9,36144).
+char(7,36145).
+char(c,36146).
+char(c,36147).
+char(p,36148).
+char(o,36149).
+char(p,36150).
+char(o,36151).
+char(4,36152).
+char(3,36153).
+char(9,36154).
+char(6,36155).
+char(m,36156).
+char(o,36157).
+char(m,36158).
+char(o,36159).
+char(8,36160).
+char(6,36161).
+char(0,36162).
+char(c,36163).
+char(c,36164).
+char(c,36165).
+char(m,36166).
+char(6,36167).
+char(5,36168).
+char(2,36169).
+char(1,36170).
+char(c,36171).
+char(c,36172).
+char(p,36173).
+char(o,36174).
+char(m,36175).
+char(6,36176).
+char(8,36177).
+char(2,36178).
+char(2,36179).
+char(p,36180).
+char(o,36181).
+char(p,36182).
+char(5,36183).
+char(4,36184).
+char(4,36185).
+char(6,36186).
+char(m,36187).
+char(3,36188).
+char(8,36189).
+char(4,36190).
+char(p,36191).
+char(o,36192).
+char(o,36193).
+char(m,36194).
+char(3,36195).
+char(8,36196).
+char(9,36197).
+char(1,36198).
+char(c,36199).
+char(p,36200).
+char(4,36201).
+char(5,36202).
+char(5,36203).
+char(8,36204).
+char(c,36205).
+char(p,36206).
+char(o,36207).
+char(o,36208).
+char(m,36209).
+char(o,36210).
+char(8,36211).
+char(9,36212).
+char(m,36213).
+char(3,36214).
+char(9,36215).
+char(6,36216).
+char(7,36217).
+char(c,36218).
+char(p,36219).
+char(o,36220).
+char(p,36221).
+char(5,36222).
+char(6,36223).
+char(4,36224).
+char(0,36225).
+char(m,36226).
+char(7,36227).
+char(3,36228).
+char(2,36229).
+char(8,36230).
+char(m,36231).
+char(o,36232).
+char(m,36233).
+char(o,36234).
+char(p,36235).
+char(o,36236).
+char(m,36237).
+char(3,36238).
+char(4,36239).
+char(3,36240).
+char(0,36241).
+char(m,36242).
+char(3,36243).
+char(9,36244).
+char(9,36245).
+char(1,36246).
+char(p,36247).
+char(5,36248).
+char(4,36249).
+char(1,36250).
+char(3,36251).
+char(c,36252).
+char(c,36253).
+char(c,36254).
+char(m,36255).
+char(o,36256).
+char(8,36257).
+char(1,36258).
+char(7,36259).
+char(c,36260).
+char(m,36261).
+char(1,36262).
+char(0,36263).
+char(9,36264).
+char(4,36265).
+char(c,36266).
+char(c,36267).
+char(p,36268).
+char(o,36269).
+char(m,36270).
+char(9,36271).
+char(7,36272).
+char(9,36273).
+char(1,36274).
+char(c,36275).
+char(m,36276).
+char(1,36277).
+char(4,36278).
+char(3,36279).
+char(2,36280).
+char(c,36281).
+char(c,36282).
+char(c,36283).
+char(c,36284).
+char(p,36285).
+char(3,36286).
+char(2,36287).
+char(5,36288).
+char(0,36289).
+char(p,36290).
+char(9,36291).
+char(1,36292).
+char(9,36293).
+char(8,36294).
+char(m,36295).
+char(8,36296).
+char(7,36297).
+char(7,36298).
+char(1,36299).
+char(m,36300).
+char(o,36301).
+char(o,36302).
+char(m,36303).
+char(o,36304).
+char(p,36305).
+char(o,36306).
+char(p,36307).
+char(4,36308).
+char(6,36309).
+char(0,36310).
+char(0,36311).
+char(m,36312).
+char(8,36313).
+char(5,36314).
+char(4,36315).
+char(3,36316).
+char(c,36317).
+char(c,36318).
+char(p,36319).
+char(8,36320).
+char(1,36321).
+char(2,36322).
+char(3,36323).
+char(m,36324).
+char(o,36325).
+char(7,36326).
+char(0,36327).
+char(8,36328).
+char(2,36329).
+char(m,36330).
+char(o,36331).
+char(m,36332).
+char(8,36333).
+char(8,36334).
+char(1,36335).
+char(7,36336).
+char(c,36337).
+char(p,36338).
+char(4,36339).
+char(0,36340).
+char(8,36341).
+char(0,36342).
+char(m,36343).
+char(9,36344).
+char(7,36345).
+char(8,36346).
+char(4,36347).
+char(p,36348).
+char(7,36349).
+char(2,36350).
+char(3,36351).
+char(4,36352).
+char(c,36353).
+char(c,36354).
+char(m,36355).
+char(o,36356).
+char(o,36357).
+char(p,36358).
+char(1,36359).
+char(2,36360).
+char(0,36361).
+char(7,36362).
+char(m,36363).
+char(o,36364).
+char(7,36365).
+char(0,36366).
+char(5,36367).
+char(8,36368).
+char(p,36369).
+char(o,36370).
+char(p,36371).
+char(3,36372).
+char(9,36373).
+char(6,36374).
+char(8,36375).
+char(p,36376).
+char(o,36377).
+char(p,36378).
+char(o,36379).
+char(p,36380).
+char(5,36381).
+char(6,36382).
+char(4,36383).
+char(0,36384).
+char(c,36385).
+char(c,36386).
+char(m,36387).
+char(o,36388).
+char(m,36389).
+char(o,36390).
+char(o,36391).
+char(p,36392).
+char(o,36393).
+char(o,36394).
+char(p,36395).
+char(o,36396).
+char(m,36397).
+char(6,36398).
+char(6,36399).
+char(3,36400).
+char(c,36401).
+char(m,36402).
+char(6,36403).
+char(3,36404).
+char(9,36405).
+char(1,36406).
+char(c,36407).
+char(c,36408).
+char(c,36409).
+char(p,36410).
+char(8,36411).
+char(6,36412).
+char(3,36413).
+char(3,36414).
+char(c,36415).
+char(m,36416).
+char(o,36417).
+char(o,36418).
+char(p,36419).
+char(o,36420).
+char(p,36421).
+char(o,36422).
+char(p,36423).
+char(o,36424).
+char(m,36425).
+char(2,36426).
+char(4,36427).
+char(0,36428).
+char(5,36429).
+char(c,36430).
+char(p,36431).
+char(2,36432).
+char(9,36433).
+char(4,36434).
+char(0,36435).
+char(p,36436).
+char(o,36437).
+char(m,36438).
+char(4,36439).
+char(7,36440).
+char(7,36441).
+char(8,36442).
+char(m,36443).
+char(9,36444).
+char(9,36445).
+char(1,36446).
+char(1,36447).
+char(c,36448).
+char(c,36449).
+char(m,36450).
+char(8,36451).
+char(0,36452).
+char(4,36453).
+char(8,36454).
+char(c,36455).
+char(c,36456).
+char(c,36457).
+char(p,36458).
+char(3,36459).
+char(4,36460).
+char(6,36461).
+char(5,36462).
+char(c,36463).
+char(c,36464).
+char(c,36465).
+char(c,36466).
+char(c,36467).
+char(p,36468).
+char(o,36469).
+char(p,36470).
+char(o,36471).
+char(m,36472).
+char(7,36473).
+char(9,36474).
+char(4,36475).
+char(7,36476).
+char(c,36477).
+char(c,36478).
+char(m,36479).
+char(4,36480).
+char(2,36481).
+char(3,36482).
+char(2,36483).
+char(c,36484).
+char(m,36485).
+char(o,36486).
+char(9,36487).
+char(0,36488).
+char(4,36489).
+char(3,36490).
+char(p,36491).
+char(9,36492).
+char(0,36493).
+char(5,36494).
+char(7,36495).
+char(m,36496).
+char(o,36497).
+char(o,36498).
+char(p,36499).
+char(5,36500).
+char(9,36501).
+char(8,36502).
+char(3,36503).
+char(p,36504).
+char(2,36505).
+char(7,36506).
+char(5,36507).
+char(2,36508).
+char(p,36509).
+char(1,36510).
+char(6,36511).
+char(9,36512).
+char(8,36513).
+char(c,36514).
+char(c,36515).
+char(p,36516).
+char(o,36517).
+char(6,36518).
+char(0,36519).
+char(7,36520).
+char(7,36521).
+char(m,36522).
+char(6,36523).
+char(3,36524).
+char(2,36525).
+char(6,36526).
+char(c,36527).
+char(c,36528).
+char(m,36529).
+char(1,36530).
+char(4,36531).
+char(7,36532).
+char(6,36533).
+char(p,36534).
+char(3,36535).
+char(1,36536).
+char(3,36537).
+char(0,36538).
+char(c,36539).
+char(c,36540).
+char(p,36541).
+char(5,36542).
+char(8,36543).
+char(2,36544).
+char(c,36545).
+char(c,36546).
+char(c,36547).
+char(c,36548).
+char(p,36549).
+char(1,36550).
+char(4,36551).
+char(8,36552).
+char(4,36553).
+char(p,36554).
+char(7,36555).
+char(9,36556).
+char(2,36557).
+char(5,36558).
+char(c,36559).
+char(p,36560).
+char(o,36561).
+char(m,36562).
+char(5,36563).
+char(4,36564).
+char(8,36565).
+char(c,36566).
+char(m,36567).
+char(o,36568).
+char(o,36569).
+char(o,36570).
+char(p,36571).
+char(o,36572).
+char(p,36573).
+char(o,36574).
+char(p,36575).
+char(2,36576).
+char(3,36577).
+char(7,36578).
+char(0,36579).
+char(p,36580).
+char(2,36581).
+char(1,36582).
+char(2,36583).
+char(3,36584).
+char(p,36585).
+char(8,36586).
+char(3,36587).
+char(3,36588).
+char(m,36589).
+char(2,36590).
+char(1,36591).
+char(7,36592).
+char(9,36593).
+char(p,36594).
+char(o,36595).
+char(m,36596).
+char(o,36597).
+char(m,36598).
+char(2,36599).
+char(9,36600).
+char(0,36601).
+char(6,36602).
+char(c,36603).
+char(c,36604).
+char(c,36605).
+char(m,36606).
+char(9,36607).
+char(5,36608).
+char(8,36609).
+char(6,36610).
+char(c,36611).
+char(c,36612).
+char(c,36613).
+char(p,36614).
+char(2,36615).
+char(3,36616).
+char(1,36617).
+char(c,36618).
+char(p,36619).
+char(o,36620).
+char(m,36621).
+char(3,36622).
+char(7,36623).
+char(1,36624).
+char(8,36625).
+char(m,36626).
+char(o,36627).
+char(7,36628).
+char(1,36629).
+char(2,36630).
+char(0,36631).
+char(p,36632).
+char(o,36633).
+char(m,36634).
+char(8,36635).
+char(7,36636).
+char(7,36637).
+char(p,36638).
+char(7,36639).
+char(5,36640).
+char(3,36641).
+char(4,36642).
+char(p,36643).
+char(4,36644).
+char(9,36645).
+char(2,36646).
+char(8,36647).
+char(c,36648).
+char(c,36649).
+char(m,36650).
+char(o,36651).
+char(o,36652).
+char(m,36653).
+char(o,36654).
+char(p,36655).
+char(8,36656).
+char(6,36657).
+char(3,36658).
+char(1,36659).
+char(c,36660).
+char(c,36661).
+char(c,36662).
+char(m,36663).
+char(3,36664).
+char(3,36665).
+char(4,36666).
+char(0,36667).
+char(m,36668).
+char(5,36669).
+char(3,36670).
+char(2,36671).
+char(3,36672).
+char(c,36673).
+char(m,36674).
+char(4,36675).
+char(8,36676).
+char(1,36677).
+char(2,36678).
+char(c,36679).
+char(c,36680).
+char(p,36681).
+char(o,36682).
+char(p,36683).
+char(6,36684).
+char(5,36685).
+char(6,36686).
+char(9,36687).
+char(p,36688).
+char(o,36689).
+char(o,36690).
+char(m,36691).
+char(o,36692).
+char(m,36693).
+char(5,36694).
+char(0,36695).
+char(3,36696).
+char(9,36697).
+char(c,36698).
+char(m,36699).
+char(o,36700).
+char(8,36701).
+char(5,36702).
+char(1,36703).
+char(4,36704).
+char(c,36705).
+char(c,36706).
+char(c,36707).
+char(p,36708).
+char(7,36709).
+char(6,36710).
+char(4,36711).
+char(0,36712).
+char(p,36713).
+char(2,36714).
+char(6,36715).
+char(1,36716).
+char(0,36717).
+char(m,36718).
+char(9,36719).
+char(1,36720).
+char(5,36721).
+char(3,36722).
+char(c,36723).
+char(c,36724).
+char(c,36725).
+char(c,36726).
+char(p,36727).
+char(o,36728).
+char(m,36729).
+char(o,36730).
+char(2,36731).
+char(5,36732).
+char(1,36733).
+char(9,36734).
+char(p,36735).
+char(5,36736).
+char(5,36737).
+char(8,36738).
+char(c,36739).
+char(p,36740).
+char(o,36741).
+char(p,36742).
+char(5,36743).
+char(9,36744).
+char(0,36745).
+char(4,36746).
+char(m,36747).
+char(o,36748).
+char(p,36749).
+char(o,36750).
+char(2,36751).
+char(9,36752).
+char(1,36753).
+char(2,36754).
+char(c,36755).
+char(m,36756).
+char(8,36757).
+char(5,36758).
+char(8,36759).
+char(8,36760).
+char(p,36761).
+char(o,36762).
+char(p,36763).
+char(o,36764).
+char(p,36765).
+char(o,36766).
+char(m,36767).
+char(o,36768).
+char(m,36769).
+char(o,36770).
+char(p,36771).
+char(o,36772).
+char(p,36773).
+char(4,36774).
+char(2,36775).
+char(1,36776).
+char(1,36777).
+char(p,36778).
+char(o,36779).
+char(p,36780).
+char(2,36781).
+char(2,36782).
+char(8,36783).
+char(0,36784).
+char(c,36785).
+char(p,36786).
+char(o,36787).
+char(p,36788).
+char(o,36789).
+char(o,36790).
+char(m,36791).
+char(o,36792).
+char(m,36793).
+char(o,36794).
+char(o,36795).
+char(m,36796).
+char(6,36797).
+char(5,36798).
+char(7,36799).
+char(5,36800).
+char(m,36801).
+char(o,36802).
+char(m,36803).
+char(o,36804).
+char(o,36805).
+char(p,36806).
+char(8,36807).
+char(3,36808).
+char(5,36809).
+char(0,36810).
+char(c,36811).
+char(p,36812).
+char(6,36813).
+char(9,36814).
+char(0,36815).
+char(2,36816).
+char(m,36817).
+char(o,36818).
+char(m,36819).
+char(o,36820).
+char(m,36821).
+char(o,36822).
+char(p,36823).
+char(3,36824).
+char(0,36825).
+char(5,36826).
+char(6,36827).
+char(p,36828).
+char(o,36829).
+char(o,36830).
+char(m,36831).
+char(o,36832).
+char(m,36833).
+char(o,36834).
+char(m,36835).
+char(5,36836).
+char(2,36837).
+char(7,36838).
+char(0,36839).
+char(c,36840).
+char(p,36841).
+char(7,36842).
+char(9,36843).
+char(3,36844).
+char(2,36845).
+char(p,36846).
+char(o,36847).
+char(4,36848).
+char(8,36849).
+char(1,36850).
+char(8,36851).
+char(c,36852).
+char(p,36853).
+char(o,36854).
+char(m,36855).
+char(9,36856).
+char(0,36857).
+char(7,36858).
+char(6,36859).
+char(m,36860).
+char(2,36861).
+char(4,36862).
+char(5,36863).
+char(p,36864).
+char(4,36865).
+char(2,36866).
+char(4,36867).
+char(m,36868).
+char(o,36869).
+char(m,36870).
+char(9,36871).
+char(1,36872).
+char(9,36873).
+char(4,36874).
+char(p,36875).
+char(9,36876).
+char(8,36877).
+char(6,36878).
+char(6,36879).
+char(c,36880).
+char(m,36881).
+char(8,36882).
+char(3,36883).
+char(8,36884).
+char(2,36885).
+char(m,36886).
+char(o,36887).
+char(p,36888).
+char(8,36889).
+char(0,36890).
+char(2,36891).
+char(5,36892).
+char(m,36893).
+char(9,36894).
+char(8,36895).
+char(5,36896).
+char(5,36897).
+char(c,36898).
+char(c,36899).
+char(c,36900).
+char(p,36901).
+char(o,36902).
+char(p,36903).
+char(o,36904).
+char(m,36905).
+char(8,36906).
+char(2,36907).
+char(7,36908).
+char(7,36909).
+char(c,36910).
+char(c,36911).
+char(p,36912).
+char(6,36913).
+char(6,36914).
+char(6,36915).
+char(9,36916).
+char(c,36917).
+char(c,36918).
+char(p,36919).
+char(o,36920).
+char(p,36921).
+char(o,36922).
+char(o,36923).
+char(o,36924).
+char(8,36925).
+char(9,36926).
+char(4,36927).
+char(6,36928).
+char(p,36929).
+char(o,36930).
+char(o,36931).
+char(p,36932).
+char(2,36933).
+char(1,36934).
+char(4,36935).
+char(8,36936).
+char(m,36937).
+char(o,36938).
+char(5,36939).
+char(8,36940).
+char(9,36941).
+char(8,36942).
+char(p,36943).
+char(o,36944).
+char(o,36945).
+char(m,36946).
+char(o,36947).
+char(p,36948).
+char(o,36949).
+char(p,36950).
+char(5,36951).
+char(1,36952).
+char(0,36953).
+char(4,36954).
+char(c,36955).
+char(c,36956).
+char(c,36957).
+char(m,36958).
+char(7,36959).
+char(9,36960).
+char(9,36961).
+char(3,36962).
+char(c,36963).
+char(p,36964).
+char(5,36965).
+char(6,36966).
+char(3,36967).
+char(2,36968).
+char(c,36969).
+char(p,36970).
+char(6,36971).
+char(5,36972).
+char(3,36973).
+char(7,36974).
+char(p,36975).
+char(5,36976).
+char(2,36977).
+char(0,36978).
+char(0,36979).
+char(p,36980).
+char(o,36981).
+char(o,36982).
+char(6,36983).
+char(6,36984).
+char(5,36985).
+char(0,36986).
+char(c,36987).
+char(m,36988).
+char(o,36989).
+char(m,36990).
+char(1,36991).
+char(6,36992).
+char(1,36993).
+char(5,36994).
+char(c,36995).
+char(m,36996).
+char(o,36997).
+char(o,36998).
+char(m,36999).
+char(o,37000).
+char(p,37001).
+char(o,37002).
+char(o,37003).
+char(p,37004).
+char(o,37005).
+char(o,37006).
+char(m,37007).
+char(o,37008).
+char(o,37009).
+char(p,37010).
+char(1,37011).
+char(8,37012).
+char(6,37013).
+char(8,37014).
+char(m,37015).
+char(9,37016).
+char(4,37017).
+char(3,37018).
+char(5,37019).
+char(m,37020).
+char(5,37021).
+char(0,37022).
+char(2,37023).
+char(4,37024).
+char(m,37025).
+char(o,37026).
+char(p,37027).
+char(o,37028).
+char(m,37029).
+char(o,37030).
+char(o,37031).
+char(3,37032).
+char(9,37033).
+char(8,37034).
+char(2,37035).
+char(c,37036).
+char(c,37037).
+char(m,37038).
+char(o,37039).
+char(o,37040).
+char(3,37041).
+char(3,37042).
+char(6,37043).
+char(5,37044).
+char(p,37045).
+char(2,37046).
+char(8,37047).
+char(4,37048).
+char(0,37049).
+char(m,37050).
+char(o,37051).
+char(p,37052).
+char(o,37053).
+char(o,37054).
+char(m,37055).
+char(o,37056).
+char(p,37057).
+char(4,37058).
+char(9,37059).
+char(0,37060).
+char(8,37061).
+char(c,37062).
+char(m,37063).
+char(o,37064).
+char(o,37065).
+char(o,37066).
+char(m,37067).
+char(o,37068).
+char(7,37069).
+char(9,37070).
+char(5,37071).
+char(5,37072).
+char(m,37073).
+char(4,37074).
+char(8,37075).
+char(3,37076).
+char(7,37077).
+char(c,37078).
+char(p,37079).
+char(1,37080).
+char(2,37081).
+char(9,37082).
+char(p,37083).
+char(o,37084).
+char(3,37085).
+char(2,37086).
+char(8,37087).
+char(7,37088).
+char(c,37089).
+char(m,37090).
+char(o,37091).
+char(5,37092).
+char(0,37093).
+char(6,37094).
+char(9,37095).
+char(p,37096).
+char(o,37097).
+char(o,37098).
+char(3,37099).
+char(3,37100).
+char(6,37101).
+char(6,37102).
+char(p,37103).
+char(4,37104).
+char(8,37105).
+char(4,37106).
+char(3,37107).
+char(c,37108).
+char(c,37109).
+char(c,37110).
+char(c,37111).
+char(m,37112).
+char(o,37113).
+char(m,37114).
+char(o,37115).
+char(o,37116).
+char(m,37117).
+char(6,37118).
+char(8,37119).
+char(5,37120).
+char(4,37121).
+char(c,37122).
+char(m,37123).
+char(o,37124).
+char(p,37125).
+char(o,37126).
+char(o,37127).
+char(8,37128).
+char(9,37129).
+char(3,37130).
+char(3,37131).
+char(c,37132).
+char(m,37133).
+char(o,37134).
+char(p,37135).
+char(o,37136).
+char(p,37137).
+char(o,37138).
+char(p,37139).
+char(o,37140).
+char(p,37141).
+char(o,37142).
+char(p,37143).
+char(o,37144).
+char(7,37145).
+char(9,37146).
+char(3,37147).
+char(8,37148).
+char(p,37149).
+char(o,37150).
+char(p,37151).
+char(6,37152).
+char(0,37153).
+char(8,37154).
+char(7,37155).
+char(p,37156).
+char(4,37157).
+char(3,37158).
+char(9,37159).
+char(1,37160).
+char(c,37161).
+char(c,37162).
+char(p,37163).
+char(5,37164).
+char(3,37165).
+char(1,37166).
+char(p,37167).
+char(5,37168).
+char(9,37169).
+char(8,37170).
+char(9,37171).
+char(p,37172).
+char(o,37173).
+char(p,37174).
+char(1,37175).
+char(3,37176).
+char(5,37177).
+char(6,37178).
+char(m,37179).
+char(o,37180).
+char(m,37181).
+char(9,37182).
+char(4,37183).
+char(4,37184).
+char(0,37185).
+char(p,37186).
+char(o,37187).
+char(m,37188).
+char(1,37189).
+char(4,37190).
+char(9,37191).
+char(6,37192).
+char(p,37193).
+char(o,37194).
+char(p,37195).
+char(3,37196).
+char(8,37197).
+char(2,37198).
+char(9,37199).
+char(m,37200).
+char(3,37201).
+char(5,37202).
+char(3,37203).
+char(0,37204).
+char(c,37205).
+char(p,37206).
+char(9,37207).
+char(7,37208).
+char(6,37209).
+char(0,37210).
+char(p,37211).
+char(2,37212).
+char(5,37213).
+char(4,37214).
+char(0,37215).
+char(c,37216).
+char(m,37217).
+char(3,37218).
+char(2,37219).
+char(4,37220).
+char(0,37221).
+char(c,37222).
+char(p,37223).
+char(7,37224).
+char(7,37225).
+char(7,37226).
+char(7,37227).
+char(c,37228).
+char(m,37229).
+char(o,37230).
+char(m,37231).
+char(o,37232).
+char(m,37233).
+char(8,37234).
+char(4,37235).
+char(7,37236).
+char(9,37237).
+char(c,37238).
+char(p,37239).
+char(3,37240).
+char(8,37241).
+char(4,37242).
+char(2,37243).
+char(c,37244).
+char(p,37245).
+char(o,37246).
+char(o,37247).
+char(p,37248).
+char(o,37249).
+char(p,37250).
+char(7,37251).
+char(8,37252).
+char(5,37253).
+char(5,37254).
+char(c,37255).
+char(c,37256).
+char(m,37257).
+char(o,37258).
+char(p,37259).
+char(o,37260).
+char(p,37261).
+char(o,37262).
+char(m,37263).
+char(9,37264).
+char(7,37265).
+char(7,37266).
+char(2,37267).
+char(c,37268).
+char(m,37269).
+char(o,37270).
+char(o,37271).
+char(4,37272).
+char(6,37273).
+char(6,37274).
+char(2,37275).
+char(c,37276).
+char(c,37277).
+char(m,37278).
+char(4,37279).
+char(0,37280).
+char(7,37281).
+char(0,37282).
+char(m,37283).
+char(5,37284).
+char(0,37285).
+char(4,37286).
+char(6,37287).
+char(c,37288).
+char(p,37289).
+char(4,37290).
+char(8,37291).
+char(2,37292).
+char(4,37293).
+char(m,37294).
+char(o,37295).
+char(p,37296).
+char(3,37297).
+char(3,37298).
+char(3,37299).
+char(2,37300).
+char(p,37301).
+char(2,37302).
+char(0,37303).
+char(0,37304).
+char(8,37305).
+char(c,37306).
+char(p,37307).
+char(o,37308).
+char(p,37309).
+char(4,37310).
+char(8,37311).
+char(3,37312).
+char(5,37313).
+char(c,37314).
+char(m,37315).
+char(o,37316).
+char(m,37317).
+char(o,37318).
+char(p,37319).
+char(o,37320).
+char(o,37321).
+char(p,37322).
+char(o,37323).
+char(p,37324).
+char(4,37325).
+char(5,37326).
+char(6,37327).
+char(6,37328).
+char(p,37329).
+char(6,37330).
+char(5,37331).
+char(0,37332).
+char(3,37333).
+char(c,37334).
+char(c,37335).
+char(m,37336).
+char(o,37337).
+char(o,37338).
+char(7,37339).
+char(9,37340).
+char(5,37341).
+char(4,37342).
+char(c,37343).
+char(m,37344).
+char(o,37345).
+char(4,37346).
+char(6,37347).
+char(8,37348).
+char(7,37349).
+char(c,37350).
+char(c,37351).
+char(p,37352).
+char(o,37353).
+char(6,37354).
+char(5,37355).
+char(9,37356).
+char(7,37357).
+char(c,37358).
+char(c,37359).
+char(p,37360).
+char(7,37361).
+char(3,37362).
+char(5,37363).
+char(8,37364).
+char(m,37365).
+char(o,37366).
+char(m,37367).
+char(3,37368).
+char(4,37369).
+char(9,37370).
+char(7,37371).
+char(m,37372).
+char(8,37373).
+char(8,37374).
+char(2,37375).
+char(7,37376).
+char(c,37377).
+char(p,37378).
+char(2,37379).
+char(3,37380).
+char(6,37381).
+char(7,37382).
+char(c,37383).
+char(c,37384).
+char(m,37385).
+char(o,37386).
+char(o,37387).
+char(m,37388).
+char(o,37389).
+char(m,37390).
+char(o,37391).
+char(m,37392).
+char(3,37393).
+char(7,37394).
+char(3,37395).
+char(4,37396).
+char(p,37397).
+char(4,37398).
+char(4,37399).
+char(8,37400).
+char(4,37401).
+char(c,37402).
+char(c,37403).
+char(c,37404).
+char(p,37405).
+char(2,37406).
+char(6,37407).
+char(2,37408).
+char(8,37409).
+char(c,37410).
+char(c,37411).
+char(c,37412).
+char(m,37413).
+char(o,37414).
+char(4,37415).
+char(4,37416).
+char(8,37417).
+char(1,37418).
+char(c,37419).
+char(c,37420).
+char(p,37421).
+char(o,37422).
+char(p,37423).
+char(8,37424).
+char(5,37425).
+char(3,37426).
+char(5,37427).
+char(m,37428).
+char(1,37429).
+char(1,37430).
+char(9,37431).
+char(0,37432).
+char(c,37433).
+char(p,37434).
+char(o,37435).
+char(4,37436).
+char(7,37437).
+char(0,37438).
+char(0,37439).
+char(m,37440).
+char(8,37441).
+char(7,37442).
+char(0,37443).
+char(0,37444).
+char(c,37445).
+char(c,37446).
+char(c,37447).
+char(c,37448).
+char(p,37449).
+char(9,37450).
+char(1,37451).
+char(5,37452).
+char(6,37453).
+char(c,37454).
+char(m,37455).
+char(2,37456).
+char(1,37457).
+char(7,37458).
+char(2,37459).
+char(c,37460).
+char(m,37461).
+char(o,37462).
+char(p,37463).
+char(6,37464).
+char(3,37465).
+char(0,37466).
+char(4,37467).
+char(c,37468).
+char(c,37469).
+char(c,37470).
+char(p,37471).
+char(o,37472).
+char(1,37473).
+char(3,37474).
+char(9,37475).
+char(6,37476).
+char(p,37477).
+char(1,37478).
+char(8,37479).
+char(1,37480).
+char(m,37481).
+char(7,37482).
+char(5,37483).
+char(2,37484).
+char(3,37485).
+char(p,37486).
+char(3,37487).
+char(6,37488).
+char(1,37489).
+char(1,37490).
+char(p,37491).
+char(o,37492).
+char(p,37493).
+char(o,37494).
+char(m,37495).
+char(o,37496).
+char(p,37497).
+char(3,37498).
+char(2,37499).
+char(2,37500).
+char(2,37501).
+char(c,37502).
+char(c,37503).
+char(p,37504).
+char(1,37505).
+char(6,37506).
+char(3,37507).
+char(0,37508).
+char(p,37509).
+char(o,37510).
+char(1,37511).
+char(2,37512).
+char(3,37513).
+char(6,37514).
+char(m,37515).
+char(o,37516).
+char(m,37517).
+char(7,37518).
+char(2,37519).
+char(7,37520).
+char(5,37521).
+char(c,37522).
+char(c,37523).
+char(c,37524).
+char(m,37525).
+char(8,37526).
+char(6,37527).
+char(9,37528).
+char(0,37529).
+char(c,37530).
+char(c,37531).
+char(m,37532).
+char(2,37533).
+char(9,37534).
+char(5,37535).
+char(1,37536).
+char(c,37537).
+char(m,37538).
+char(2,37539).
+char(8,37540).
+char(6,37541).
+char(4,37542).
+char(c,37543).
+char(p,37544).
+char(6,37545).
+char(8,37546).
+char(2,37547).
+char(3,37548).
+char(c,37549).
+char(p,37550).
+char(o,37551).
+char(p,37552).
+char(2,37553).
+char(2,37554).
+char(1,37555).
+char(7,37556).
+char(c,37557).
+char(p,37558).
+char(6,37559).
+char(9,37560).
+char(4,37561).
+char(0,37562).
+char(c,37563).
+char(c,37564).
+char(p,37565).
+char(o,37566).
+char(m,37567).
+char(o,37568).
+char(8,37569).
+char(0,37570).
+char(6,37571).
+char(0,37572).
+char(c,37573).
+char(p,37574).
+char(1,37575).
+char(1,37576).
+char(6,37577).
+char(8,37578).
+char(m,37579).
+char(6,37580).
+char(7,37581).
+char(2,37582).
+char(8,37583).
+char(c,37584).
+char(c,37585).
+char(c,37586).
+char(c,37587).
+char(p,37588).
+char(3,37589).
+char(7,37590).
+char(6,37591).
+char(1,37592).
+char(c,37593).
+char(p,37594).
+char(o,37595).
+char(m,37596).
+char(o,37597).
+char(o,37598).
+char(m,37599).
+char(o,37600).
+char(m,37601).
+char(o,37602).
+char(p,37603).
+char(o,37604).
+char(m,37605).
+char(9,37606).
+char(5,37607).
+char(2,37608).
+char(6,37609).
+char(c,37610).
+char(c,37611).
+char(c,37612).
+char(c,37613).
+char(p,37614).
+char(o,37615).
+char(m,37616).
+char(o,37617).
+char(9,37618).
+char(3,37619).
+char(8,37620).
+char(7,37621).
+char(c,37622).
+char(m,37623).
+char(2,37624).
+char(0,37625).
+char(6,37626).
+char(4,37627).
+char(p,37628).
+char(6,37629).
+char(9,37630).
+char(8,37631).
+char(p,37632).
+char(o,37633).
+char(p,37634).
+char(1,37635).
+char(3,37636).
+char(3,37637).
+char(6,37638).
+char(m,37639).
+char(o,37640).
+char(o,37641).
+char(p,37642).
+char(o,37643).
+char(o,37644).
+char(p,37645).
+char(o,37646).
+char(5,37647).
+char(6,37648).
+char(8,37649).
+char(1,37650).
+char(c,37651).
+char(c,37652).
+char(c,37653).
+char(c,37654).
+char(c,37655).
+char(m,37656).
+char(3,37657).
+char(1,37658).
+char(3,37659).
+char(5,37660).
+char(c,37661).
+char(p,37662).
+char(o,37663).
+char(m,37664).
+char(o,37665).
+char(m,37666).
+char(6,37667).
+char(8,37668).
+char(0,37669).
+char(5,37670).
+char(c,37671).
+char(c,37672).
+char(c,37673).
+char(p,37674).
+char(o,37675).
+char(m,37676).
+char(o,37677).
+char(o,37678).
+char(p,37679).
+char(o,37680).
+char(p,37681).
+char(o,37682).
+char(m,37683).
+char(4,37684).
+char(9,37685).
+char(8,37686).
+char(4,37687).
+char(m,37688).
+char(1,37689).
+char(9,37690).
+char(4,37691).
+char(4,37692).
+char(c,37693).
+char(p,37694).
+char(6,37695).
+char(7,37696).
+char(5,37697).
+char(7,37698).
+char(c,37699).
+char(m,37700).
+char(o,37701).
+char(p,37702).
+char(o,37703).
+char(p,37704).
+char(o,37705).
+char(p,37706).
+char(1,37707).
+char(8,37708).
+char(8,37709).
+char(c,37710).
+char(p,37711).
+char(o,37712).
+char(o,37713).
+char(m,37714).
+char(3,37715).
+char(4,37716).
+char(5,37717).
+char(1,37718).
+char(m,37719).
+char(4,37720).
+char(5,37721).
+char(5,37722).
+char(8,37723).
+char(m,37724).
+char(o,37725).
+char(6,37726).
+char(0,37727).
+char(0,37728).
+char(1,37729).
+char(m,37730).
+char(9,37731).
+char(1,37732).
+char(4,37733).
+char(9,37734).
+char(p,37735).
+char(2,37736).
+char(9,37737).
+char(2,37738).
+char(7,37739).
+char(m,37740).
+char(6,37741).
+char(4,37742).
+char(8,37743).
+char(2,37744).
+char(c,37745).
+char(m,37746).
+char(2,37747).
+char(9,37748).
+char(6,37749).
+char(6,37750).
+char(p,37751).
+char(o,37752).
+char(p,37753).
+char(7,37754).
+char(9,37755).
+char(0,37756).
+char(3,37757).
+char(m,37758).
+char(o,37759).
+char(6,37760).
+char(7,37761).
+char(9,37762).
+char(2,37763).
+char(p,37764).
+char(o,37765).
+char(o,37766).
+char(p,37767).
+char(8,37768).
+char(3,37769).
+char(4,37770).
+char(m,37771).
+char(o,37772).
+char(5,37773).
+char(3,37774).
+char(2,37775).
+char(9,37776).
+char(m,37777).
+char(7,37778).
+char(9,37779).
+char(9,37780).
+char(8,37781).
+char(p,37782).
+char(o,37783).
+char(3,37784).
+char(2,37785).
+char(5,37786).
+char(5,37787).
+char(p,37788).
+char(1,37789).
+char(9,37790).
+char(4,37791).
+char(3,37792).
+char(c,37793).
+char(m,37794).
+char(6,37795).
+char(2,37796).
+char(1,37797).
+char(6,37798).
+char(m,37799).
+char(o,37800).
+char(m,37801).
+char(o,37802).
+char(m,37803).
+char(3,37804).
+char(6,37805).
+char(7,37806).
+char(4,37807).
+char(c,37808).
+char(p,37809).
+char(o,37810).
+char(p,37811).
+char(8,37812).
+char(5,37813).
+char(4,37814).
+char(5,37815).
+char(m,37816).
+char(o,37817).
+char(p,37818).
+char(2,37819).
+char(1,37820).
+char(8,37821).
+char(5,37822).
+char(p,37823).
+char(2,37824).
+char(6,37825).
+char(7,37826).
+char(4,37827).
+char(p,37828).
+char(6,37829).
+char(8,37830).
+char(7,37831).
+char(9,37832).
+char(p,37833).
+char(o,37834).
+char(m,37835).
+char(2,37836).
+char(3,37837).
+char(1,37838).
+char(1,37839).
+char(c,37840).
+char(p,37841).
+char(o,37842).
+char(m,37843).
+char(7,37844).
+char(4,37845).
+char(1,37846).
+char(7,37847).
+char(m,37848).
+char(6,37849).
+char(4,37850).
+char(2,37851).
+char(7,37852).
+char(c,37853).
+char(c,37854).
+char(c,37855).
+char(p,37856).
+char(1,37857).
+char(9,37858).
+char(8,37859).
+char(2,37860).
+char(c,37861).
+char(p,37862).
+char(o,37863).
+char(p,37864).
+char(o,37865).
+char(p,37866).
+char(o,37867).
+char(o,37868).
+char(p,37869).
+char(o,37870).
+char(p,37871).
+char(9,37872).
+char(3,37873).
+char(9,37874).
+char(3,37875).
+char(c,37876).
+char(c,37877).
+char(p,37878).
+char(o,37879).
+char(m,37880).
+char(o,37881).
+char(m,37882).
+char(o,37883).
+char(p,37884).
+char(o,37885).
+char(o,37886).
+char(m,37887).
+char(8,37888).
+char(8,37889).
+char(1,37890).
+char(2,37891).
+char(p,37892).
+char(o,37893).
+char(p,37894).
+char(2,37895).
+char(9,37896).
+char(3,37897).
+char(6,37898).
+char(m,37899).
+char(6,37900).
+char(0,37901).
+char(5,37902).
+char(6,37903).
+char(m,37904).
+char(o,37905).
+char(m,37906).
+char(o,37907).
+char(p,37908).
+char(o,37909).
+char(p,37910).
+char(o,37911).
+char(m,37912).
+char(5,37913).
+char(7,37914).
+char(4,37915).
+char(4,37916).
+char(m,37917).
+char(3,37918).
+char(0,37919).
+char(9,37920).
+char(9,37921).
+char(c,37922).
+char(c,37923).
+char(c,37924).
+char(p,37925).
+char(2,37926).
+char(7,37927).
+char(9,37928).
+char(3,37929).
+char(c,37930).
+char(c,37931).
+char(p,37932).
+char(o,37933).
+char(1,37934).
+char(0,37935).
+char(3,37936).
+char(p,37937).
+char(o,37938).
+char(m,37939).
+char(7,37940).
+char(4,37941).
+char(6,37942).
+char(8,37943).
+char(m,37944).
+char(9,37945).
+char(1,37946).
+char(9,37947).
+char(9,37948).
+char(p,37949).
+char(o,37950).
+char(m,37951).
+char(3,37952).
+char(2,37953).
+char(0,37954).
+char(6,37955).
+char(m,37956).
+char(o,37957).
+char(m,37958).
+char(o,37959).
+char(p,37960).
+char(o,37961).
+char(p,37962).
+char(o,37963).
+char(m,37964).
+char(8,37965).
+char(6,37966).
+char(6,37967).
+char(1,37968).
+char(p,37969).
+char(3,37970).
+char(8,37971).
+char(2,37972).
+char(5,37973).
+char(c,37974).
+char(p,37975).
+char(o,37976).
+char(6,37977).
+char(8,37978).
+char(2,37979).
+char(2,37980).
+char(p,37981).
+char(2,37982).
+char(5,37983).
+char(7,37984).
+char(2,37985).
+char(c,37986).
+char(c,37987).
+char(c,37988).
+char(c,37989).
+char(c,37990).
+char(m,37991).
+char(6,37992).
+char(1,37993).
+char(6,37994).
+char(1,37995).
+char(c,37996).
+char(m,37997).
+char(o,37998).
+char(o,37999).
+char(p,38000).
+char(8,38001).
+char(4,38002).
+char(3,38003).
+char(4,38004).
+char(p,38005).
+char(o,38006).
+char(m,38007).
+char(8,38008).
+char(4,38009).
+char(5,38010).
+char(8,38011).
+char(p,38012).
+char(o,38013).
+char(8,38014).
+char(1,38015).
+char(1,38016).
+char(m,38017).
+char(4,38018).
+char(6,38019).
+char(2,38020).
+char(8,38021).
+char(m,38022).
+char(o,38023).
+char(o,38024).
+char(o,38025).
+char(m,38026).
+char(1,38027).
+char(0,38028).
+char(2,38029).
+char(0,38030).
+char(c,38031).
+char(c,38032).
+char(m,38033).
+char(o,38034).
+char(m,38035).
+char(8,38036).
+char(3,38037).
+char(2,38038).
+char(4,38039).
+char(c,38040).
+char(c,38041).
+char(c,38042).
+char(m,38043).
+char(o,38044).
+char(p,38045).
+char(o,38046).
+char(o,38047).
+char(m,38048).
+char(o,38049).
+char(p,38050).
+char(o,38051).
+char(m,38052).
+char(o,38053).
+char(6,38054).
+char(2,38055).
+char(3,38056).
+char(6,38057).
+char(m,38058).
+char(6,38059).
+char(0,38060).
+char(6,38061).
+char(8,38062).
+char(c,38063).
+char(c,38064).
+char(c,38065).
+char(c,38066).
+char(c,38067).
+char(c,38068).
+char(p,38069).
+char(1,38070).
+char(4,38071).
+char(3,38072).
+char(1,38073).
+char(c,38074).
+char(m,38075).
+char(o,38076).
+char(m,38077).
+char(o,38078).
+char(m,38079).
+char(1,38080).
+char(7,38081).
+char(5,38082).
+char(6,38083).
+char(c,38084).
+char(c,38085).
+char(p,38086).
+char(4,38087).
+char(8,38088).
+char(3,38089).
+char(1,38090).
+char(c,38091).
+char(p,38092).
+char(5,38093).
+char(7,38094).
+char(6,38095).
+char(0,38096).
+char(c,38097).
+char(m,38098).
+char(6,38099).
+char(1,38100).
+char(9,38101).
+char(7,38102).
+char(p,38103).
+char(o,38104).
+char(p,38105).
+char(o,38106).
+char(p,38107).
+char(5,38108).
+char(1,38109).
+char(8,38110).
+char(1,38111).
+char(m,38112).
+char(o,38113).
+char(m,38114).
+char(9,38115).
+char(8,38116).
+char(5,38117).
+char(7,38118).
+char(c,38119).
+char(c,38120).
+char(c,38121).
+char(p,38122).
+char(2,38123).
+char(8,38124).
+char(7,38125).
+char(0,38126).
+char(c,38127).
+char(p,38128).
+char(2,38129).
+char(6,38130).
+char(8,38131).
+char(0,38132).
+char(p,38133).
+char(o,38134).
+char(o,38135).
+char(p,38136).
+char(9,38137).
+char(5,38138).
+char(9,38139).
+char(3,38140).
+char(c,38141).
+char(m,38142).
+char(8,38143).
+char(3,38144).
+char(0,38145).
+char(p,38146).
+char(6,38147).
+char(0,38148).
+char(5,38149).
+char(7,38150).
+char(c,38151).
+char(c,38152).
+char(c,38153).
+char(c,38154).
+char(m,38155).
+char(o,38156).
+char(p,38157).
+char(o,38158).
+char(4,38159).
+char(0,38160).
+char(2,38161).
+char(5,38162).
+char(p,38163).
+char(o,38164).
+char(o,38165).
+char(p,38166).
+char(9,38167).
+char(7,38168).
+char(1,38169).
+char(3,38170).
+char(c,38171).
+char(c,38172).
+char(c,38173).
+char(m,38174).
+char(7,38175).
+char(0,38176).
+char(1,38177).
+char(4,38178).
+char(c,38179).
+char(p,38180).
+char(5,38181).
+char(5,38182).
+char(7,38183).
+char(1,38184).
+char(m,38185).
+char(o,38186).
+char(p,38187).
+char(o,38188).
+char(o,38189).
+char(o,38190).
+char(p,38191).
+char(7,38192).
+char(6,38193).
+char(1,38194).
+char(8,38195).
+char(p,38196).
+char(6,38197).
+char(5,38198).
+char(8,38199).
+char(2,38200).
+char(m,38201).
+char(7,38202).
+char(2,38203).
+char(9,38204).
+char(8,38205).
+char(p,38206).
+char(8,38207).
+char(4,38208).
+char(7,38209).
+char(9,38210).
+char(c,38211).
+char(m,38212).
+char(o,38213).
+char(o,38214).
+char(m,38215).
+char(2,38216).
+char(0,38217).
+char(7,38218).
+char(8,38219).
+char(m,38220).
+char(1,38221).
+char(4,38222).
+char(4,38223).
+char(9,38224).
+char(m,38225).
+char(o,38226).
+char(4,38227).
+char(8,38228).
+char(2,38229).
+char(4,38230).
+char(c,38231).
+char(c,38232).
+char(c,38233).
+char(c,38234).
+char(c,38235).
+char(c,38236).
+char(c,38237).
+char(c,38238).
+char(m,38239).
+char(o,38240).
+char(m,38241).
+char(o,38242).
+char(3,38243).
+char(1,38244).
+char(2,38245).
+char(6,38246).
+char(m,38247).
+char(o,38248).
+char(m,38249).
+char(6,38250).
+char(4,38251).
+char(7,38252).
+char(1,38253).
+char(c,38254).
+char(m,38255).
+char(o,38256).
+char(9,38257).
+char(2,38258).
+char(2,38259).
+char(7,38260).
+char(c,38261).
+char(p,38262).
+char(6,38263).
+char(3,38264).
+char(1,38265).
+char(3,38266).
+char(c,38267).
+char(p,38268).
+char(2,38269).
+char(8,38270).
+char(9,38271).
+char(9,38272).
+char(c,38273).
+char(c,38274).
+char(c,38275).
+char(p,38276).
+char(o,38277).
+char(4,38278).
+char(9,38279).
+char(7,38280).
+char(8,38281).
+char(m,38282).
+char(o,38283).
+char(m,38284).
+char(o,38285).
+char(p,38286).
+char(o,38287).
+char(p,38288).
+char(1,38289).
+char(9,38290).
+char(7,38291).
+char(4,38292).
+char(p,38293).
+char(9,38294).
+char(0,38295).
+char(8,38296).
+char(1,38297).
+char(c,38298).
+char(c,38299).
+char(c,38300).
+char(c,38301).
+char(c,38302).
+char(c,38303).
+char(p,38304).
+char(3,38305).
+char(3,38306).
+char(2,38307).
+char(9,38308).
+char(m,38309).
+char(o,38310).
+char(m,38311).
+char(6,38312).
+char(0,38313).
+char(2,38314).
+char(5,38315).
+char(p,38316).
+char(o,38317).
+char(3,38318).
+char(7,38319).
+char(6,38320).
+char(7,38321).
+char(p,38322).
+char(1,38323).
+char(0,38324).
+char(0,38325).
+char(2,38326).
+char(m,38327).
+char(5,38328).
+char(6,38329).
+char(9,38330).
+char(3,38331).
+char(c,38332).
+char(c,38333).
+char(c,38334).
+char(p,38335).
+char(o,38336).
+char(m,38337).
+char(o,38338).
+char(5,38339).
+char(7,38340).
+char(9,38341).
+char(0,38342).
+char(c,38343).
+char(p,38344).
+char(5,38345).
+char(6,38346).
+char(0,38347).
+char(c,38348).
+char(p,38349).
+char(7,38350).
+char(7,38351).
+char(9,38352).
+char(3,38353).
+char(c,38354).
+char(p,38355).
+char(4,38356).
+char(7,38357).
+char(0,38358).
+char(3,38359).
+char(c,38360).
+char(p,38361).
+char(o,38362).
+char(m,38363).
+char(o,38364).
+char(m,38365).
+char(o,38366).
+char(m,38367).
+char(5,38368).
+char(0,38369).
+char(7,38370).
+char(m,38371).
+char(o,38372).
+char(p,38373).
+char(o,38374).
+char(p,38375).
+char(4,38376).
+char(9,38377).
+char(7,38378).
+char(8,38379).
+char(m,38380).
+char(o,38381).
+char(9,38382).
+char(9,38383).
+char(6,38384).
+char(7,38385).
+char(m,38386).
+char(3,38387).
+char(6,38388).
+char(1,38389).
+char(6,38390).
+char(p,38391).
+char(o,38392).
+char(p,38393).
+char(3,38394).
+char(5,38395).
+char(1,38396).
+char(m,38397).
+char(1,38398).
+char(8,38399).
+char(4,38400).
+char(c,38401).
+char(c,38402).
+char(m,38403).
+char(o,38404).
+char(m,38405).
+char(3,38406).
+char(1,38407).
+char(9,38408).
+char(9,38409).
+char(p,38410).
+char(o,38411).
+char(5,38412).
+char(4,38413).
+char(6,38414).
+char(8,38415).
+char(c,38416).
+char(c,38417).
+char(p,38418).
+char(8,38419).
+char(0,38420).
+char(7,38421).
+char(5,38422).
+char(m,38423).
+char(o,38424).
+char(m,38425).
+char(o,38426).
+char(p,38427).
+char(9,38428).
+char(1,38429).
+char(7,38430).
+char(6,38431).
+char(p,38432).
+char(o,38433).
+char(m,38434).
+char(o,38435).
+char(p,38436).
+char(7,38437).
+char(3,38438).
+char(6,38439).
+char(1,38440).
+char(p,38441).
+char(2,38442).
+char(4,38443).
+char(1,38444).
+char(3,38445).
+char(c,38446).
+char(c,38447).
+char(c,38448).
+char(p,38449).
+char(2,38450).
+char(8,38451).
+char(8,38452).
+char(7,38453).
+char(c,38454).
+char(m,38455).
+char(9,38456).
+char(7,38457).
+char(6,38458).
+char(9,38459).
+char(m,38460).
+char(o,38461).
+char(p,38462).
+char(9,38463).
+char(4,38464).
+char(3,38465).
+char(9,38466).
+char(p,38467).
+char(o,38468).
+char(o,38469).
+char(8,38470).
+char(3,38471).
+char(3,38472).
+char(p,38473).
+char(5,38474).
+char(0,38475).
+char(2,38476).
+char(2,38477).
+char(c,38478).
+char(c,38479).
+char(m,38480).
+char(o,38481).
+char(p,38482).
+char(3,38483).
+char(3,38484).
+char(2,38485).
+char(4,38486).
+char(c,38487).
+char(c,38488).
+char(p,38489).
+char(o,38490).
+char(m,38491).
+char(4,38492).
+char(5,38493).
+char(4,38494).
+char(9,38495).
+char(p,38496).
+char(4,38497).
+char(1,38498).
+char(7,38499).
+char(c,38500).
+char(m,38501).
+char(o,38502).
+char(m,38503).
+char(9,38504).
+char(2,38505).
+char(8,38506).
+char(3,38507).
+char(c,38508).
+char(m,38509).
+char(o,38510).
+char(m,38511).
+char(8,38512).
+char(6,38513).
+char(9,38514).
+char(2,38515).
+char(c,38516).
+char(m,38517).
+char(o,38518).
+char(m,38519).
+char(7,38520).
+char(0,38521).
+char(6,38522).
+char(7,38523).
+char(c,38524).
+char(c,38525).
+char(m,38526).
+char(o,38527).
+char(p,38528).
+char(9,38529).
+char(0,38530).
+char(1,38531).
+char(9,38532).
+char(c,38533).
+char(c,38534).
+char(c,38535).
+char(m,38536).
+char(1,38537).
+char(9,38538).
+char(1,38539).
+char(3,38540).
+char(m,38541).
+char(o,38542).
+char(p,38543).
+char(o,38544).
+char(p,38545).
+char(o,38546).
+char(1,38547).
+char(5,38548).
+char(1,38549).
+char(8,38550).
+char(c,38551).
+char(c,38552).
+char(c,38553).
+char(c,38554).
+char(c,38555).
+char(c,38556).
+char(c,38557).
+char(p,38558).
+char(o,38559).
+char(p,38560).
+char(o,38561).
+char(m,38562).
+char(7,38563).
+char(7,38564).
+char(1,38565).
+char(4,38566).
+char(c,38567).
+char(c,38568).
+char(m,38569).
+char(o,38570).
+char(o,38571).
+char(p,38572).
+char(o,38573).
+char(5,38574).
+char(2,38575).
+char(3,38576).
+char(9,38577).
+char(c,38578).
+char(p,38579).
+char(8,38580).
+char(2,38581).
+char(7,38582).
+char(1,38583).
+char(p,38584).
+char(o,38585).
+char(p,38586).
+char(3,38587).
+char(1,38588).
+char(3,38589).
+char(7,38590).
+char(m,38591).
+char(6,38592).
+char(3,38593).
+char(0,38594).
+char(2,38595).
+char(c,38596).
+char(p,38597).
+char(4,38598).
+char(0,38599).
+char(5,38600).
+char(1,38601).
+char(p,38602).
+char(9,38603).
+char(8,38604).
+char(3,38605).
+char(2,38606).
+char(m,38607).
+char(7,38608).
+char(7,38609).
+char(9,38610).
+char(3,38611).
+char(c,38612).
+char(c,38613).
+char(m,38614).
+char(o,38615).
+char(m,38616).
+char(6,38617).
+char(1,38618).
+char(0,38619).
+char(4,38620).
+char(c,38621).
+char(c,38622).
+char(c,38623).
+char(c,38624).
+char(p,38625).
+char(1,38626).
+char(6,38627).
+char(5,38628).
+char(2,38629).
+char(c,38630).
+char(m,38631).
+char(o,38632).
+char(p,38633).
+char(7,38634).
+char(6,38635).
+char(4,38636).
+char(m,38637).
+char(o,38638).
+char(o,38639).
+char(p,38640).
+char(o,38641).
+char(p,38642).
+char(7,38643).
+char(1,38644).
+char(7,38645).
+char(8,38646).
+char(m,38647).
+char(o,38648).
+char(m,38649).
+char(8,38650).
+char(4,38651).
+char(7,38652).
+char(2,38653).
+char(c,38654).
+char(c,38655).
+char(m,38656).
+char(o,38657).
+char(p,38658).
+char(o,38659).
+char(m,38660).
+char(2,38661).
+char(7,38662).
+char(9,38663).
+char(9,38664).
+char(c,38665).
+char(c,38666).
+char(c,38667).
+char(c,38668).
+char(c,38669).
+char(p,38670).
+char(7,38671).
+char(2,38672).
+char(5,38673).
+char(3,38674).
+char(c,38675).
+char(c,38676).
+char(p,38677).
+char(o,38678).
+char(5,38679).
+char(3,38680).
+char(4,38681).
+char(5,38682).
+char(c,38683).
+char(c,38684).
+char(c,38685).
+char(c,38686).
+char(c,38687).
+char(p,38688).
+char(4,38689).
+char(6,38690).
+char(7,38691).
+char(4,38692).
+char(c,38693).
+char(p,38694).
+char(7,38695).
+char(6,38696).
+char(4,38697).
+char(0,38698).
+char(m,38699).
+char(o,38700).
+char(p,38701).
+char(o,38702).
+char(o,38703).
+char(p,38704).
+char(1,38705).
+char(1,38706).
+char(9,38707).
+char(8,38708).
+char(c,38709).
+char(c,38710).
+char(m,38711).
+char(7,38712).
+char(1,38713).
+char(6,38714).
+char(9,38715).
+char(c,38716).
+char(m,38717).
+char(2,38718).
+char(1,38719).
+char(0,38720).
+char(5,38721).
+char(m,38722).
+char(3,38723).
+char(1,38724).
+char(6,38725).
+char(6,38726).
+char(m,38727).
+char(3,38728).
+char(3,38729).
+char(6,38730).
+char(6,38731).
+char(p,38732).
+char(3,38733).
+char(9,38734).
+char(9,38735).
+char(7,38736).
+char(m,38737).
+char(o,38738).
+char(m,38739).
+char(o,38740).
+char(p,38741).
+char(o,38742).
+char(p,38743).
+char(5,38744).
+char(1,38745).
+char(3,38746).
+char(2,38747).
+char(c,38748).
+char(m,38749).
+char(o,38750).
+char(m,38751).
+char(6,38752).
+char(8,38753).
+char(6,38754).
+char(3,38755).
+char(c,38756).
+char(m,38757).
+char(o,38758).
+char(p,38759).
+char(o,38760).
+char(m,38761).
+char(o,38762).
+char(m,38763).
+char(9,38764).
+char(6,38765).
+char(9,38766).
+char(2,38767).
+char(c,38768).
+char(m,38769).
+char(4,38770).
+char(6,38771).
+char(7,38772).
+char(4,38773).
+char(c,38774).
+char(c,38775).
+char(m,38776).
+char(o,38777).
+char(p,38778).
+char(o,38779).
+char(m,38780).
+char(o,38781).
+char(o,38782).
+char(o,38783).
+char(m,38784).
+char(9,38785).
+char(4,38786).
+char(5,38787).
+char(3,38788).
+char(c,38789).
+char(c,38790).
+char(p,38791).
+char(o,38792).
+char(8,38793).
+char(7,38794).
+char(0,38795).
+char(6,38796).
+char(m,38797).
+char(o,38798).
+char(m,38799).
+char(o,38800).
+char(p,38801).
+char(o,38802).
+char(m,38803).
+char(o,38804).
+char(m,38805).
+char(5,38806).
+char(6,38807).
+char(3,38808).
+char(0,38809).
+char(p,38810).
+char(1,38811).
+char(7,38812).
+char(8,38813).
+char(2,38814).
+char(c,38815).
+char(c,38816).
+char(p,38817).
+char(o,38818).
+char(p,38819).
+char(5,38820).
+char(5,38821).
+char(4,38822).
+char(6,38823).
+char(m,38824).
+char(7,38825).
+char(8,38826).
+char(8,38827).
+char(0,38828).
+char(c,38829).
+char(c,38830).
+char(c,38831).
+char(m,38832).
+char(o,38833).
+char(6,38834).
+char(0,38835).
+char(3,38836).
+char(3,38837).
+char(c,38838).
+char(c,38839).
+char(m,38840).
+char(o,38841).
+char(3,38842).
+char(9,38843).
+char(2,38844).
+char(5,38845).
+char(c,38846).
+char(m,38847).
+char(o,38848).
+char(p,38849).
+char(9,38850).
+char(6,38851).
+char(7,38852).
+char(9,38853).
+char(m,38854).
+char(8,38855).
+char(7,38856).
+char(8,38857).
+char(4,38858).
+char(c,38859).
+char(m,38860).
+char(o,38861).
+char(4,38862).
+char(3,38863).
+char(3,38864).
+char(9,38865).
+char(m,38866).
+char(1,38867).
+char(7,38868).
+char(2,38869).
+char(2,38870).
+char(p,38871).
+char(5,38872).
+char(8,38873).
+char(3,38874).
+char(9,38875).
+char(m,38876).
+char(o,38877).
+char(o,38878).
+char(p,38879).
+char(o,38880).
+char(m,38881).
+char(o,38882).
+char(m,38883).
+char(4,38884).
+char(9,38885).
+char(8,38886).
+char(2,38887).
+char(p,38888).
+char(o,38889).
+char(p,38890).
+char(4,38891).
+char(1,38892).
+char(0,38893).
+char(0,38894).
+char(p,38895).
+char(6,38896).
+char(5,38897).
+char(6,38898).
+char(0,38899).
+char(m,38900).
+char(6,38901).
+char(8,38902).
+char(7,38903).
+char(1,38904).
+char(c,38905).
+char(c,38906).
+char(m,38907).
+char(8,38908).
+char(8,38909).
+char(6,38910).
+char(3,38911).
+char(p,38912).
+char(3,38913).
+char(8,38914).
+char(0,38915).
+char(5,38916).
+char(c,38917).
+char(m,38918).
+char(o,38919).
+char(p,38920).
+char(2,38921).
+char(8,38922).
+char(8,38923).
+char(2,38924).
+char(m,38925).
+char(8,38926).
+char(3,38927).
+char(2,38928).
+char(9,38929).
+char(c,38930).
+char(m,38931).
+char(7,38932).
+char(4,38933).
+char(3,38934).
+char(6,38935).
+char(m,38936).
+char(8,38937).
+char(2,38938).
+char(3,38939).
+char(2,38940).
+char(c,38941).
+char(p,38942).
+char(2,38943).
+char(9,38944).
+char(8,38945).
+char(5,38946).
+char(m,38947).
+char(7,38948).
+char(9,38949).
+char(7,38950).
+char(6,38951).
+char(c,38952).
+char(p,38953).
+char(7,38954).
+char(2,38955).
+char(4,38956).
+char(3,38957).
+char(c,38958).
+char(c,38959).
+char(c,38960).
+char(p,38961).
+char(o,38962).
+char(m,38963).
+char(o,38964).
+char(m,38965).
+char(8,38966).
+char(7,38967).
+char(6,38968).
+char(4,38969).
+char(c,38970).
+char(p,38971).
+char(o,38972).
+char(p,38973).
+char(1,38974).
+char(2,38975).
+char(2,38976).
+char(1,38977).
+char(c,38978).
+char(c,38979).
+char(c,38980).
+char(m,38981).
+char(1,38982).
+char(9,38983).
+char(2,38984).
+char(3,38985).
+char(c,38986).
+char(c,38987).
+char(c,38988).
+char(m,38989).
+char(o,38990).
+char(p,38991).
+char(6,38992).
+char(6,38993).
+char(7,38994).
+char(5,38995).
+char(c,38996).
+char(c,38997).
+char(c,38998).
+char(p,38999).
+char(9,39000).
+char(8,39001).
+char(3,39002).
+char(3,39003).
+char(c,39004).
+char(c,39005).
+char(p,39006).
+char(7,39007).
+char(5,39008).
+char(0,39009).
+char(9,39010).
+char(p,39011).
+char(4,39012).
+char(5,39013).
+char(8,39014).
+char(8,39015).
+char(c,39016).
+char(c,39017).
+char(c,39018).
+char(m,39019).
+char(o,39020).
+char(m,39021).
+char(8,39022).
+char(5,39023).
+char(5,39024).
+char(6,39025).
+char(p,39026).
+char(1,39027).
+char(9,39028).
+char(6,39029).
+char(5,39030).
+char(p,39031).
+char(3,39032).
+char(1,39033).
+char(2,39034).
+char(5,39035).
+char(p,39036).
+char(o,39037).
+char(p,39038).
+char(o,39039).
+char(p,39040).
+char(o,39041).
+char(p,39042).
+char(6,39043).
+char(4,39044).
+char(4,39045).
+char(4,39046).
+char(c,39047).
+char(m,39048).
+char(o,39049).
+char(p,39050).
+char(3,39051).
+char(0,39052).
+char(9,39053).
+char(p,39054).
+char(o,39055).
+char(o,39056).
+char(o,39057).
+char(m,39058).
+char(4,39059).
+char(3,39060).
+char(1,39061).
+char(5,39062).
+char(p,39063).
+char(9,39064).
+char(0,39065).
+char(3,39066).
+char(7,39067).
+char(m,39068).
+char(o,39069).
+char(o,39070).
+char(p,39071).
+char(o,39072).
+char(m,39073).
+char(o,39074).
+char(p,39075).
+char(5,39076).
+char(1,39077).
+char(4,39078).
+char(9,39079).
+char(c,39080).
+char(c,39081).
+char(p,39082).
+char(o,39083).
+char(o,39084).
+char(m,39085).
+char(o,39086).
+char(p,39087).
+char(7,39088).
+char(3,39089).
+char(1,39090).
+char(6,39091).
+char(m,39092).
+char(6,39093).
+char(3,39094).
+char(1,39095).
+char(0,39096).
+char(c,39097).
+char(p,39098).
+char(o,39099).
+char(p,39100).
+char(o,39101).
+char(9,39102).
+char(4,39103).
+char(1,39104).
+char(8,39105).
+char(p,39106).
+char(1,39107).
+char(4,39108).
+char(5,39109).
+char(9,39110).
+char(c,39111).
+char(c,39112).
+char(c,39113).
+char(c,39114).
+char(c,39115).
+char(c,39116).
+char(p,39117).
+char(7,39118).
+char(7,39119).
+char(0,39120).
+char(4,39121).
+char(m,39122).
+char(o,39123).
+char(o,39124).
+char(p,39125).
+char(5,39126).
+char(2,39127).
+char(6,39128).
+char(1,39129).
+char(c,39130).
+char(m,39131).
+char(7,39132).
+char(0,39133).
+char(7,39134).
+char(4,39135).
+char(m,39136).
+char(o,39137).
+char(o,39138).
+char(p,39139).
+char(2,39140).
+char(0,39141).
+char(9,39142).
+char(c,39143).
+char(p,39144).
+char(o,39145).
+char(m,39146).
+char(8,39147).
+char(9,39148).
+char(9,39149).
+char(2,39150).
+char(m,39151).
+char(o,39152).
+char(o,39153).
+char(m,39154).
+char(o,39155).
+char(p,39156).
+char(8,39157).
+char(1,39158).
+char(8,39159).
+char(7,39160).
+char(p,39161).
+char(o,39162).
+char(m,39163).
+char(o,39164).
+char(m,39165).
+char(o,39166).
+char(m,39167).
+char(o,39168).
+char(p,39169).
+char(2,39170).
+char(2,39171).
+char(5,39172).
+char(5,39173).
+char(m,39174).
+char(1,39175).
+char(8,39176).
+char(7,39177).
+char(7,39178).
+char(c,39179).
+char(c,39180).
+char(c,39181).
+char(m,39182).
+char(o,39183).
+char(m,39184).
+char(9,39185).
+char(5,39186).
+char(7,39187).
+char(8,39188).
+char(p,39189).
+char(8,39190).
+char(7,39191).
+char(4,39192).
+char(1,39193).
+char(c,39194).
+char(c,39195).
+char(m,39196).
+char(o,39197).
+char(m,39198).
+char(3,39199).
+char(1,39200).
+char(9,39201).
+char(m,39202).
+char(o,39203).
+char(p,39204).
+char(o,39205).
+char(m,39206).
+char(o,39207).
+char(p,39208).
+char(o,39209).
+char(p,39210).
+char(o,39211).
+char(m,39212).
+char(o,39213).
+char(p,39214).
+char(o,39215).
+char(m,39216).
+char(o,39217).
+char(o,39218).
+char(p,39219).
+char(9,39220).
+char(7,39221).
+char(9,39222).
+char(9,39223).
+char(c,39224).
+char(c,39225).
+char(m,39226).
+char(5,39227).
+char(2,39228).
+char(2,39229).
+char(1,39230).
+char(p,39231).
+char(9,39232).
+char(5,39233).
+char(7,39234).
+char(4,39235).
+char(c,39236).
+char(m,39237).
+char(8,39238).
+char(2,39239).
+char(5,39240).
+char(2,39241).
+char(m,39242).
+char(3,39243).
+char(5,39244).
+char(0,39245).
+char(4,39246).
+char(c,39247).
+char(c,39248).
+char(c,39249).
+char(m,39250).
+char(2,39251).
+char(0,39252).
+char(2,39253).
+char(3,39254).
+char(p,39255).
+char(o,39256).
+char(4,39257).
+char(8,39258).
+char(1,39259).
+char(4,39260).
+char(m,39261).
+char(1,39262).
+char(9,39263).
+char(8,39264).
+char(6,39265).
+char(c,39266).
+char(p,39267).
+char(o,39268).
+char(2,39269).
+char(7,39270).
+char(1,39271).
+char(4,39272).
+char(m,39273).
+char(3,39274).
+char(2,39275).
+char(2,39276).
+char(5,39277).
+char(m,39278).
+char(o,39279).
+char(p,39280).
+char(7,39281).
+char(3,39282).
+char(3,39283).
+char(7,39284).
+char(c,39285).
+char(p,39286).
+char(o,39287).
+char(4,39288).
+char(6,39289).
+char(9,39290).
+char(8,39291).
+char(m,39292).
+char(o,39293).
+char(m,39294).
+char(o,39295).
+char(3,39296).
+char(1,39297).
+char(8,39298).
+char(m,39299).
+char(o,39300).
+char(8,39301).
+char(0,39302).
+char(5,39303).
+char(2,39304).
+char(c,39305).
+char(c,39306).
+char(c,39307).
+char(c,39308).
+char(c,39309).
+char(c,39310).
+char(p,39311).
+char(6,39312).
+char(6,39313).
+char(8,39314).
+char(8,39315).
+char(c,39316).
+char(p,39317).
+char(8,39318).
+char(2,39319).
+char(0,39320).
+char(9,39321).
+char(c,39322).
+char(c,39323).
+char(m,39324).
+char(1,39325).
+char(3,39326).
+char(5,39327).
+char(7,39328).
+char(m,39329).
+char(2,39330).
+char(8,39331).
+char(2,39332).
+char(c,39333).
+char(m,39334).
+char(8,39335).
+char(0,39336).
+char(6,39337).
+char(3,39338).
+char(c,39339).
+char(c,39340).
+char(c,39341).
+char(c,39342).
+char(c,39343).
+char(c,39344).
+char(c,39345).
+char(p,39346).
+char(7,39347).
+char(2,39348).
+char(0,39349).
+char(9,39350).
+char(c,39351).
+char(m,39352).
+char(o,39353).
+char(m,39354).
+char(o,39355).
+char(p,39356).
+char(8,39357).
+char(0,39358).
+char(2,39359).
+char(3,39360).
+char(m,39361).
+char(3,39362).
+char(5,39363).
+char(2,39364).
+char(7,39365).
+char(c,39366).
+char(c,39367).
+char(p,39368).
+char(o,39369).
+char(o,39370).
+char(m,39371).
+char(o,39372).
+char(p,39373).
+char(2,39374).
+char(8,39375).
+char(3,39376).
+char(2,39377).
+char(c,39378).
+char(c,39379).
+char(p,39380).
+char(o,39381).
+char(p,39382).
+char(3,39383).
+char(8,39384).
+char(0,39385).
+char(c,39386).
+char(m,39387).
+char(4,39388).
+char(4,39389).
+char(6,39390).
+char(4,39391).
+char(m,39392).
+char(o,39393).
+char(m,39394).
+char(2,39395).
+char(8,39396).
+char(8,39397).
+char(4,39398).
+char(c,39399).
+char(c,39400).
+char(p,39401).
+char(1,39402).
+char(5,39403).
+char(9,39404).
+char(2,39405).
+char(m,39406).
+char(o,39407).
+char(9,39408).
+char(8,39409).
+char(1,39410).
+char(3,39411).
+char(m,39412).
+char(o,39413).
+char(o,39414).
+char(5,39415).
+char(4,39416).
+char(9,39417).
+char(3,39418).
+char(c,39419).
+char(c,39420).
+char(p,39421).
+char(2,39422).
+char(5,39423).
+char(4,39424).
+char(8,39425).
+char(c,39426).
+char(c,39427).
+char(c,39428).
+char(m,39429).
+char(5,39430).
+char(5,39431).
+char(8,39432).
+char(8,39433).
+char(c,39434).
+char(c,39435).
+char(c,39436).
+char(c,39437).
+char(m,39438).
+char(6,39439).
+char(4,39440).
+char(9,39441).
+char(2,39442).
+char(c,39443).
+char(c,39444).
+char(m,39445).
+char(o,39446).
+char(m,39447).
+char(o,39448).
+char(p,39449).
+char(o,39450).
+char(m,39451).
+char(6,39452).
+char(1,39453).
+char(7,39454).
+char(6,39455).
+char(c,39456).
+char(m,39457).
+char(o,39458).
+char(4,39459).
+char(1,39460).
+char(1,39461).
+char(2,39462).
+char(p,39463).
+char(2,39464).
+char(3,39465).
+char(5,39466).
+char(4,39467).
+char(p,39468).
+char(o,39469).
+char(3,39470).
+char(4,39471).
+char(5,39472).
+char(7,39473).
+char(c,39474).
+char(c,39475).
+char(p,39476).
+char(4,39477).
+char(9,39478).
+char(3,39479).
+char(9,39480).
+char(c,39481).
+char(m,39482).
+char(o,39483).
+char(2,39484).
+char(5,39485).
+char(7,39486).
+char(1,39487).
+char(m,39488).
+char(4,39489).
+char(2,39490).
+char(6,39491).
+char(3,39492).
+char(c,39493).
+char(c,39494).
+char(c,39495).
+char(c,39496).
+char(p,39497).
+char(o,39498).
+char(m,39499).
+char(4,39500).
+char(9,39501).
+char(8,39502).
+char(3,39503).
+char(c,39504).
+char(c,39505).
+char(c,39506).
+char(c,39507).
+char(c,39508).
+char(m,39509).
+char(o,39510).
+char(p,39511).
+char(9,39512).
+char(4,39513).
+char(3,39514).
+char(2,39515).
+char(c,39516).
+char(p,39517).
+char(2,39518).
+char(2,39519).
+char(1,39520).
+char(3,39521).
+char(p,39522).
+char(1,39523).
+char(9,39524).
+char(3,39525).
+char(7,39526).
+char(p,39527).
+char(9,39528).
+char(9,39529).
+char(1,39530).
+char(2,39531).
+char(p,39532).
+char(o,39533).
+char(p,39534).
+char(o,39535).
+char(m,39536).
+char(8,39537).
+char(5,39538).
+char(3,39539).
+char(4,39540).
+char(c,39541).
+char(p,39542).
+char(o,39543).
+char(o,39544).
+char(p,39545).
+char(o,39546).
+char(p,39547).
+char(o,39548).
+char(9,39549).
+char(8,39550).
+char(7,39551).
+char(8,39552).
+char(c,39553).
+char(c,39554).
+char(c,39555).
+char(c,39556).
+char(m,39557).
+char(o,39558).
+char(m,39559).
+char(4,39560).
+char(5,39561).
+char(6,39562).
+char(1,39563).
+char(m,39564).
+char(o,39565).
+char(9,39566).
+char(5,39567).
+char(1,39568).
+char(2,39569).
+char(p,39570).
+char(o,39571).
+char(7,39572).
+char(7,39573).
+char(8,39574).
+char(c,39575).
+char(p,39576).
+char(o,39577).
+char(m,39578).
+char(o,39579).
+char(p,39580).
+char(o,39581).
+char(p,39582).
+char(o,39583).
+char(8,39584).
+char(1,39585).
+char(8,39586).
+char(2,39587).
+char(p,39588).
+char(6,39589).
+char(3,39590).
+char(7,39591).
+char(6,39592).
+char(c,39593).
+char(p,39594).
+char(1,39595).
+char(0,39596).
+char(3,39597).
+char(1,39598).
+char(c,39599).
+char(c,39600).
+char(c,39601).
+char(c,39602).
+char(c,39603).
+char(p,39604).
+char(5,39605).
+char(9,39606).
+char(5,39607).
+char(6,39608).
+char(c,39609).
+char(c,39610).
+char(c,39611).
+char(c,39612).
+char(m,39613).
+char(o,39614).
+char(m,39615).
+char(o,39616).
+char(m,39617).
+char(o,39618).
+char(m,39619).
+char(2,39620).
+char(4,39621).
+char(7,39622).
+char(1,39623).
+char(p,39624).
+char(3,39625).
+char(0,39626).
+char(3,39627).
+char(8,39628).
+char(c,39629).
+char(m,39630).
+char(o,39631).
+char(2,39632).
+char(2,39633).
+char(6,39634).
+char(0,39635).
+char(c,39636).
+char(c,39637).
+char(m,39638).
+char(o,39639).
+char(m,39640).
+char(o,39641).
+char(o,39642).
+char(8,39643).
+char(8,39644).
+char(0,39645).
+char(8,39646).
+char(p,39647).
+char(o,39648).
+char(o,39649).
+char(p,39650).
+char(2,39651).
+char(9,39652).
+char(6,39653).
+char(0,39654).
+char(c,39655).
+char(m,39656).
+char(o,39657).
+char(p,39658).
+char(o,39659).
+char(1,39660).
+char(8,39661).
+char(m,39662).
+char(o,39663).
+char(6,39664).
+char(9,39665).
+char(6,39666).
+char(4,39667).
+char(c,39668).
+char(c,39669).
+char(c,39670).
+char(c,39671).
+char(c,39672).
+char(c,39673).
+char(c,39674).
+char(c,39675).
+char(c,39676).
+char(c,39677).
+char(c,39678).
+char(p,39679).
+char(2,39680).
+char(6,39681).
+char(9,39682).
+char(4,39683).
+char(c,39684).
+char(p,39685).
+char(o,39686).
+char(m,39687).
+char(o,39688).
+char(p,39689).
+char(o,39690).
+char(o,39691).
+char(m,39692).
+char(o,39693).
+char(m,39694).
+char(4,39695).
+char(1,39696).
+char(9,39697).
+char(4,39698).
+char(c,39699).
+char(c,39700).
+char(m,39701).
+char(o,39702).
+char(p,39703).
+char(o,39704).
+char(p,39705).
+char(1,39706).
+char(3,39707).
+char(2,39708).
+char(1,39709).
+char(c,39710).
+char(m,39711).
+char(o,39712).
+char(m,39713).
+char(o,39714).
+char(p,39715).
+char(o,39716).
+char(m,39717).
+char(o,39718).
+char(o,39719).
+char(m,39720).
+char(o,39721).
+char(m,39722).
+char(o,39723).
+char(p,39724).
+char(6,39725).
+char(1,39726).
+char(6,39727).
+char(3,39728).
+char(p,39729).
+char(7,39730).
+char(0,39731).
+char(6,39732).
+char(4,39733).
+char(p,39734).
+char(o,39735).
+char(p,39736).
+char(o,39737).
+char(p,39738).
+char(6,39739).
+char(0,39740).
+char(4,39741).
+char(9,39742).
+char(p,39743).
+char(o,39744).
+char(p,39745).
+char(o,39746).
+char(3,39747).
+char(4,39748).
+char(3,39749).
+char(5,39750).
+char(c,39751).
+char(c,39752).
+char(c,39753).
+char(p,39754).
+char(1,39755).
+char(9,39756).
+char(1,39757).
+char(4,39758).
+char(c,39759).
+char(p,39760).
+char(1,39761).
+char(2,39762).
+char(1,39763).
+char(9,39764).
+char(m,39765).
+char(o,39766).
+char(m,39767).
+char(o,39768).
+char(m,39769).
+char(o,39770).
+char(p,39771).
+char(o,39772).
+char(o,39773).
+char(m,39774).
+char(2,39775).
+char(4,39776).
+char(0,39777).
+char(9,39778).
+char(c,39779).
+char(c,39780).
+char(p,39781).
+char(o,39782).
+char(m,39783).
+char(o,39784).
+char(m,39785).
+char(o,39786).
+char(m,39787).
+char(6,39788).
+char(7,39789).
+char(7,39790).
+char(6,39791).
+char(c,39792).
+char(c,39793).
+char(c,39794).
+char(c,39795).
+char(c,39796).
+char(c,39797).
+char(c,39798).
+char(m,39799).
+char(3,39800).
+char(3,39801).
+char(4,39802).
+char(0,39803).
+char(p,39804).
+char(o,39805).
+char(p,39806).
+char(o,39807).
+char(4,39808).
+char(6,39809).
+char(0,39810).
+char(0,39811).
+char(m,39812).
+char(2,39813).
+char(1,39814).
+char(8,39815).
+char(9,39816).
+char(c,39817).
+char(c,39818).
+char(c,39819).
+char(m,39820).
+char(9,39821).
+char(5,39822).
+char(8,39823).
+char(5,39824).
+char(p,39825).
+char(o,39826).
+char(p,39827).
+char(o,39828).
+char(4,39829).
+char(3,39830).
+char(9,39831).
+char(8,39832).
+char(p,39833).
+char(o,39834).
+char(p,39835).
+char(1,39836).
+char(3,39837).
+char(0,39838).
+char(1,39839).
+char(c,39840).
+char(p,39841).
+char(7,39842).
+char(6,39843).
+char(2,39844).
+char(1,39845).
+char(c,39846).
+char(c,39847).
+char(p,39848).
+char(2,39849).
+char(6,39850).
+char(6,39851).
+char(c,39852).
+char(c,39853).
+char(m,39854).
+char(8,39855).
+char(0,39856).
+char(5,39857).
+char(0,39858).
+char(c,39859).
+char(m,39860).
+char(o,39861).
+char(p,39862).
+char(o,39863).
+char(p,39864).
+char(2,39865).
+char(7,39866).
+char(9,39867).
+char(7,39868).
+char(c,39869).
+char(p,39870).
+char(5,39871).
+char(1,39872).
+char(3,39873).
+char(8,39874).
+char(c,39875).
+char(m,39876).
+char(7,39877).
+char(6,39878).
+char(5,39879).
+char(2,39880).
+char(c,39881).
+char(p,39882).
+char(5,39883).
+char(7,39884).
+char(0,39885).
+char(1,39886).
+char(m,39887).
+char(7,39888).
+char(9,39889).
+char(3,39890).
+char(3,39891).
+char(p,39892).
+char(4,39893).
+char(2,39894).
+char(9,39895).
+char(0,39896).
+char(m,39897).
+char(4,39898).
+char(4,39899).
+char(8,39900).
+char(4,39901).
+char(p,39902).
+char(o,39903).
+char(p,39904).
+char(o,39905).
+char(m,39906).
+char(7,39907).
+char(0,39908).
+char(7,39909).
+char(6,39910).
+char(m,39911).
+char(o,39912).
+char(p,39913).
+char(o,39914).
+char(m,39915).
+char(o,39916).
+char(m,39917).
+char(o,39918).
+char(p,39919).
+char(o,39920).
+char(o,39921).
+char(9,39922).
+char(6,39923).
+char(0,39924).
+char(0,39925).
+char(m,39926).
+char(5,39927).
+char(7,39928).
+char(9,39929).
+char(m,39930).
+char(3,39931).
+char(0,39932).
+char(9,39933).
+char(5,39934).
+char(c,39935).
+char(c,39936).
+char(c,39937).
+char(p,39938).
+char(8,39939).
+char(2,39940).
+char(7,39941).
+char(7,39942).
+char(m,39943).
+char(o,39944).
+char(m,39945).
+char(1,39946).
+char(0,39947).
+char(8,39948).
+char(p,39949).
+char(o,39950).
+char(p,39951).
+char(3,39952).
+char(9,39953).
+char(1,39954).
+char(9,39955).
+char(c,39956).
+char(c,39957).
+char(c,39958).
+char(c,39959).
+char(p,39960).
+char(o,39961).
+char(m,39962).
+char(2,39963).
+char(3,39964).
+char(5,39965).
+char(2,39966).
+char(c,39967).
+char(m,39968).
+char(o,39969).
+char(p,39970).
+char(2,39971).
+char(5,39972).
+char(8,39973).
+char(2,39974).
+char(c,39975).
+char(c,39976).
+char(p,39977).
+char(2,39978).
+char(7,39979).
+char(9,39980).
+char(7,39981).
+char(m,39982).
+char(o,39983).
+char(m,39984).
+char(2,39985).
+char(5,39986).
+char(6,39987).
+char(4,39988).
+char(p,39989).
+char(4,39990).
+char(5,39991).
+char(1,39992).
+char(4,39993).
+char(p,39994).
+char(o,39995).
+char(o,39996).
+char(8,39997).
+char(3,39998).
+char(4,39999).
+char(6,40000).
+char(c,40001).
+char(m,40002).
+char(9,40003).
+char(2,40004).
+char(7,40005).
+char(4,40006).
+char(m,40007).
+char(9,40008).
+char(6,40009).
+char(1,40010).
+char(9,40011).
+char(c,40012).
+char(c,40013).
+char(c,40014).
+char(m,40015).
+char(1,40016).
+char(8,40017).
+char(2,40018).
+char(7,40019).
+char(c,40020).
+char(c,40021).
+char(c,40022).
+char(c,40023).
+char(p,40024).
+char(o,40025).
+char(o,40026).
+char(p,40027).
+char(3,40028).
+char(9,40029).
+char(5,40030).
+char(c,40031).
+char(m,40032).
+char(8,40033).
+char(0,40034).
+char(7,40035).
+char(3,40036).
+char(c,40037).
+char(c,40038).
+char(c,40039).
+char(m,40040).
+char(o,40041).
+char(9,40042).
+char(7,40043).
+char(4,40044).
+char(p,40045).
+char(2,40046).
+char(1,40047).
+char(5,40048).
+char(c,40049).
+char(p,40050).
+char(5,40051).
+char(9,40052).
+char(2,40053).
+char(6,40054).
+char(p,40055).
+char(2,40056).
+char(3,40057).
+char(9,40058).
+char(3,40059).
+char(c,40060).
+char(c,40061).
+char(c,40062).
+char(p,40063).
+char(o,40064).
+char(o,40065).
+char(m,40066).
+char(o,40067).
+char(o,40068).
+char(p,40069).
+char(5,40070).
+char(8,40071).
+char(4,40072).
+char(7,40073).
+char(p,40074).
+char(o,40075).
+char(m,40076).
+char(o,40077).
+char(o,40078).
+char(1,40079).
+char(5,40080).
+char(1,40081).
+char(8,40082).
+char(c,40083).
+char(p,40084).
+char(2,40085).
+char(0,40086).
+char(6,40087).
+char(0,40088).
+char(m,40089).
+char(9,40090).
+char(3,40091).
+char(1,40092).
+char(7,40093).
+char(c,40094).
+char(m,40095).
+char(o,40096).
+char(3,40097).
+char(6,40098).
+char(3,40099).
+char(7,40100).
+char(m,40101).
+char(5,40102).
+char(7,40103).
+char(3,40104).
+char(m,40105).
+char(o,40106).
+char(m,40107).
+char(1,40108).
+char(7,40109).
+char(1,40110).
+char(3,40111).
+char(p,40112).
+char(5,40113).
+char(7,40114).
+char(8,40115).
+char(3,40116).
+char(c,40117).
+char(m,40118).
+char(o,40119).
+char(m,40120).
+char(o,40121).
+char(m,40122).
+char(4,40123).
+char(7,40124).
+char(3,40125).
+char(6,40126).
+char(c,40127).
+char(c,40128).
+char(c,40129).
+char(m,40130).
+char(9,40131).
+char(9,40132).
+char(9,40133).
+char(2,40134).
+char(c,40135).
+char(p,40136).
+char(o,40137).
+char(m,40138).
+char(6,40139).
+char(1,40140).
+char(3,40141).
+char(5,40142).
+char(p,40143).
+char(o,40144).
+char(o,40145).
+char(p,40146).
+char(o,40147).
+char(p,40148).
+char(2,40149).
+char(7,40150).
+char(4,40151).
+char(3,40152).
+char(c,40153).
+char(p,40154).
+char(o,40155).
+char(o,40156).
+char(m,40157).
+char(o,40158).
+char(6,40159).
+char(5,40160).
+char(1,40161).
+char(1,40162).
+char(c,40163).
+char(c,40164).
+char(m,40165).
+char(3,40166).
+char(1,40167).
+char(8,40168).
+char(4,40169).
+char(m,40170).
+char(o,40171).
+char(p,40172).
+char(o,40173).
+char(p,40174).
+char(4,40175).
+char(2,40176).
+char(0,40177).
+char(2,40178).
+char(p,40179).
+char(6,40180).
+char(5,40181).
+char(0,40182).
+char(6,40183).
+char(m,40184).
+char(o,40185).
+char(p,40186).
+char(4,40187).
+char(4,40188).
+char(5,40189).
+char(0,40190).
+char(m,40191).
+char(o,40192).
+char(p,40193).
+char(8,40194).
+char(4,40195).
+char(2,40196).
+char(4,40197).
+char(c,40198).
+char(m,40199).
+char(4,40200).
+char(3,40201).
+char(2,40202).
+char(4,40203).
+char(c,40204).
+char(p,40205).
+char(o,40206).
+char(m,40207).
+char(o,40208).
+char(3,40209).
+char(3,40210).
+char(2,40211).
+char(0,40212).
+char(c,40213).
+char(c,40214).
+char(c,40215).
+char(m,40216).
+char(8,40217).
+char(1,40218).
+char(4,40219).
+char(9,40220).
+char(p,40221).
+char(1,40222).
+char(8,40223).
+char(2,40224).
+char(4,40225).
+char(c,40226).
+char(p,40227).
+char(8,40228).
+char(6,40229).
+char(2,40230).
+char(4,40231).
+char(c,40232).
+char(c,40233).
+char(m,40234).
+char(o,40235).
+char(o,40236).
+char(m,40237).
+char(o,40238).
+char(2,40239).
+char(2,40240).
+char(4,40241).
+char(0,40242).
+char(c,40243).
+char(m,40244).
+char(o,40245).
+char(7,40246).
+char(0,40247).
+char(3,40248).
+char(4,40249).
+char(c,40250).
+char(p,40251).
+char(o,40252).
+char(m,40253).
+char(4,40254).
+char(4,40255).
+char(4,40256).
+char(5,40257).
+char(c,40258).
+char(p,40259).
+char(1,40260).
+char(6,40261).
+char(0,40262).
+char(m,40263).
+char(o,40264).
+char(o,40265).
+char(p,40266).
+char(o,40267).
+char(m,40268).
+char(o,40269).
+char(p,40270).
+char(7,40271).
+char(5,40272).
+char(5,40273).
+char(9,40274).
+char(c,40275).
+char(m,40276).
+char(5,40277).
+char(7,40278).
+char(3,40279).
+char(c,40280).
+char(c,40281).
+char(c,40282).
+char(c,40283).
+char(m,40284).
+char(1,40285).
+char(0,40286).
+char(3,40287).
+char(7,40288).
+char(c,40289).
+char(m,40290).
+char(o,40291).
+char(m,40292).
+char(o,40293).
+char(m,40294).
+char(4,40295).
+char(2,40296).
+char(4,40297).
+char(m,40298).
+char(5,40299).
+char(1,40300).
+char(9,40301).
+char(7,40302).
+char(c,40303).
+char(c,40304).
+char(p,40305).
+char(5,40306).
+char(2,40307).
+char(0,40308).
+char(5,40309).
+char(c,40310).
+char(p,40311).
+char(o,40312).
+char(o,40313).
+char(m,40314).
+char(5,40315).
+char(2,40316).
+char(9,40317).
+char(8,40318).
+char(c,40319).
+char(c,40320).
+char(m,40321).
+char(5,40322).
+char(0,40323).
+char(3,40324).
+char(9,40325).
+char(c,40326).
+char(p,40327).
+char(o,40328).
+char(1,40329).
+char(8,40330).
+char(1,40331).
+char(c,40332).
+char(p,40333).
+char(o,40334).
+char(m,40335).
+char(o,40336).
+char(p,40337).
+char(7,40338).
+char(2,40339).
+char(1,40340).
+char(2,40341).
+char(m,40342).
+char(o,40343).
+char(m,40344).
+char(o,40345).
+char(o,40346).
+char(p,40347).
+char(o,40348).
+char(o,40349).
+char(o,40350).
+char(4,40351).
+char(8,40352).
+char(8,40353).
+char(c,40354).
+char(c,40355).
+char(c,40356).
+char(m,40357).
+char(o,40358).
+char(o,40359).
+char(p,40360).
+char(1,40361).
+char(4,40362).
+char(2,40363).
+char(3,40364).
+char(c,40365).
+char(c,40366).
+char(c,40367).
+char(c,40368).
+char(c,40369).
+char(m,40370).
+char(o,40371).
+char(m,40372).
+char(1,40373).
+char(0,40374).
+char(6,40375).
+char(9,40376).
+char(c,40377).
+char(p,40378).
+char(o,40379).
+char(m,40380).
+char(2,40381).
+char(4,40382).
+char(1,40383).
+char(7,40384).
+char(c,40385).
+char(c,40386).
+char(m,40387).
+char(o,40388).
+char(p,40389).
+char(o,40390).
+char(4,40391).
+char(2,40392).
+char(5,40393).
+char(2,40394).
+char(c,40395).
+char(m,40396).
+char(8,40397).
+char(4,40398).
+char(0,40399).
+char(6,40400).
+char(m,40401).
+char(7,40402).
+char(5,40403).
+char(8,40404).
+char(6,40405).
+char(p,40406).
+char(o,40407).
+char(5,40408).
+char(9,40409).
+char(6,40410).
+char(1,40411).
+char(m,40412).
+char(o,40413).
+char(m,40414).
+char(6,40415).
+char(0,40416).
+char(5,40417).
+char(c,40418).
+char(c,40419).
+char(p,40420).
+char(8,40421).
+char(6,40422).
+char(7,40423).
+char(6,40424).
+char(p,40425).
+char(6,40426).
+char(4,40427).
+char(3,40428).
+char(2,40429).
+char(p,40430).
+char(2,40431).
+char(1,40432).
+char(3,40433).
+char(4,40434).
+char(p,40435).
+char(o,40436).
+char(p,40437).
+char(2,40438).
+char(9,40439).
+char(3,40440).
+char(m,40441).
+char(o,40442).
+char(p,40443).
+char(5,40444).
+char(3,40445).
+char(6,40446).
+char(6,40447).
+char(p,40448).
+char(6,40449).
+char(3,40450).
+char(2,40451).
+char(3,40452).
+char(m,40453).
+char(9,40454).
+char(6,40455).
+char(3,40456).
+char(c,40457).
+char(c,40458).
+char(c,40459).
+char(p,40460).
+char(o,40461).
+char(o,40462).
+char(p,40463).
+char(o,40464).
+char(3,40465).
+char(7,40466).
+char(0,40467).
+char(6,40468).
+char(m,40469).
+char(5,40470).
+char(5,40471).
+char(9,40472).
+char(7,40473).
+char(c,40474).
+char(c,40475).
+char(c,40476).
+char(c,40477).
+char(c,40478).
+char(m,40479).
+char(o,40480).
+char(o,40481).
+char(o,40482).
+char(m,40483).
+char(1,40484).
+char(0,40485).
+char(8,40486).
+char(1,40487).
+char(c,40488).
+char(c,40489).
+char(p,40490).
+char(4,40491).
+char(6,40492).
+char(7,40493).
+char(4,40494).
+char(c,40495).
+char(c,40496).
+char(p,40497).
+char(2,40498).
+char(3,40499).
+char(8,40500).
+char(1,40501).
+char(p,40502).
+char(o,40503).
+char(m,40504).
+char(4,40505).
+char(5,40506).
+char(8,40507).
+char(0,40508).
+char(p,40509).
+char(o,40510).
+char(o,40511).
+char(m,40512).
+char(o,40513).
+char(p,40514).
+char(8,40515).
+char(9,40516).
+char(5,40517).
+char(7,40518).
+char(c,40519).
+char(p,40520).
+char(4,40521).
+char(1,40522).
+char(2,40523).
+char(c,40524).
+char(c,40525).
+char(m,40526).
+char(7,40527).
+char(5,40528).
+char(6,40529).
+char(2,40530).
+char(m,40531).
+char(3,40532).
+char(0,40533).
+char(2,40534).
+char(4,40535).
+char(c,40536).
+char(m,40537).
+char(7,40538).
+char(1,40539).
+char(8,40540).
+char(2,40541).
+char(c,40542).
+char(c,40543).
+char(m,40544).
+char(6,40545).
+char(7,40546).
+char(4,40547).
+char(1,40548).
+char(p,40549).
+char(o,40550).
+char(m,40551).
+char(7,40552).
+char(6,40553).
+char(0,40554).
+char(6,40555).
+char(p,40556).
+char(5,40557).
+char(9,40558).
+char(6,40559).
+char(4,40560).
+char(m,40561).
+char(o,40562).
+char(m,40563).
+char(4,40564).
+char(8,40565).
+char(9,40566).
+char(9,40567).
+char(p,40568).
+char(o,40569).
+char(o,40570).
+char(m,40571).
+char(6,40572).
+char(1,40573).
+char(9,40574).
+char(0,40575).
+char(p,40576).
+char(4,40577).
+char(7,40578).
+char(9,40579).
+char(6,40580).
+char(p,40581).
+char(7,40582).
+char(0,40583).
+char(3,40584).
+char(8,40585).
+char(c,40586).
+char(c,40587).
+char(c,40588).
+char(p,40589).
+char(o,40590).
+char(p,40591).
+char(4,40592).
+char(6,40593).
+char(7,40594).
+char(2,40595).
+char(c,40596).
+char(m,40597).
+char(6,40598).
+char(4,40599).
+char(3,40600).
+char(6,40601).
+char(c,40602).
+char(m,40603).
+char(6,40604).
+char(4,40605).
+char(6,40606).
+char(7,40607).
+char(m,40608).
+char(o,40609).
+char(m,40610).
+char(o,40611).
+char(p,40612).
+char(4,40613).
+char(4,40614).
+char(2,40615).
+char(8,40616).
+char(c,40617).
+char(p,40618).
+char(o,40619).
+char(p,40620).
+char(o,40621).
+char(m,40622).
+char(o,40623).
+char(p,40624).
+char(8,40625).
+char(4,40626).
+char(6,40627).
+char(9,40628).
+char(c,40629).
+char(m,40630).
+char(o,40631).
+char(m,40632).
+char(1,40633).
+char(9,40634).
+char(7,40635).
+char(4,40636).
+char(c,40637).
+char(c,40638).
+char(c,40639).
+char(m,40640).
+char(4,40641).
+char(3,40642).
+char(2,40643).
+char(8,40644).
+char(m,40645).
+char(2,40646).
+char(4,40647).
+char(2,40648).
+char(7,40649).
+char(p,40650).
+char(7,40651).
+char(4,40652).
+char(2,40653).
+char(c,40654).
+char(c,40655).
+char(p,40656).
+char(o,40657).
+char(3,40658).
+char(1,40659).
+char(5,40660).
+char(m,40661).
+char(o,40662).
+char(p,40663).
+char(6,40664).
+char(3,40665).
+char(0,40666).
+char(4,40667).
+char(c,40668).
+char(c,40669).
+char(c,40670).
+char(c,40671).
+char(c,40672).
+char(m,40673).
+char(1,40674).
+char(5,40675).
+char(5,40676).
+char(5,40677).
+char(c,40678).
+char(c,40679).
+char(c,40680).
+char(p,40681).
+char(3,40682).
+char(9,40683).
+char(7,40684).
+char(4,40685).
+char(c,40686).
+char(m,40687).
+char(o,40688).
+char(6,40689).
+char(3,40690).
+char(2,40691).
+char(4,40692).
+char(m,40693).
+char(o,40694).
+char(m,40695).
+char(o,40696).
+char(m,40697).
+char(4,40698).
+char(6,40699).
+char(6,40700).
+char(4,40701).
+char(p,40702).
+char(6,40703).
+char(8,40704).
+char(8,40705).
+char(9,40706).
+char(p,40707).
+char(o,40708).
+char(p,40709).
+char(o,40710).
+char(m,40711).
+char(4,40712).
+char(9,40713).
+char(1,40714).
+char(3,40715).
+char(c,40716).
+char(c,40717).
+char(p,40718).
+char(o,40719).
+char(o,40720).
+char(p,40721).
+char(8,40722).
+char(1,40723).
+char(1,40724).
+char(m,40725).
+char(o,40726).
+char(m,40727).
+char(o,40728).
+char(p,40729).
+char(o,40730).
+char(o,40731).
+char(p,40732).
+char(o,40733).
+char(p,40734).
+char(o,40735).
+char(m,40736).
+char(4,40737).
+char(8,40738).
+char(0,40739).
+char(8,40740).
+char(c,40741).
+char(c,40742).
+char(c,40743).
+char(p,40744).
+char(4,40745).
+char(5,40746).
+char(4,40747).
+char(c,40748).
+char(c,40749).
+char(p,40750).
+char(3,40751).
+char(8,40752).
+char(3,40753).
+char(6,40754).
+char(c,40755).
+char(c,40756).
+char(m,40757).
+char(o,40758).
+char(m,40759).
+char(o,40760).
+char(m,40761).
+char(8,40762).
+char(6,40763).
+char(3,40764).
+char(1,40765).
+char(m,40766).
+char(8,40767).
+char(2,40768).
+char(7,40769).
+char(2,40770).
+char(m,40771).
+char(6,40772).
+char(1,40773).
+char(1,40774).
+char(9,40775).
+char(m,40776).
+char(8,40777).
+char(8,40778).
+char(0,40779).
+char(5,40780).
+char(c,40781).
+char(c,40782).
+char(c,40783).
+char(c,40784).
+char(c,40785).
+char(c,40786).
+char(p,40787).
+char(9,40788).
+char(7,40789).
+char(7,40790).
+char(8,40791).
+char(c,40792).
+char(c,40793).
+char(p,40794).
+char(9,40795).
+char(1,40796).
+char(8,40797).
+char(1,40798).
+char(m,40799).
+char(1,40800).
+char(3,40801).
+char(1,40802).
+char(4,40803).
+char(c,40804).
+char(p,40805).
+char(o,40806).
+char(p,40807).
+char(o,40808).
+char(p,40809).
+char(o,40810).
+char(o,40811).
+char(p,40812).
+char(o,40813).
+char(p,40814).
+char(o,40815).
+char(o,40816).
+char(p,40817).
+char(7,40818).
+char(7,40819).
+char(5,40820).
+char(3,40821).
+char(c,40822).
+char(m,40823).
+char(1,40824).
+char(8,40825).
+char(6,40826).
+char(4,40827).
+char(p,40828).
+char(o,40829).
+char(9,40830).
+char(6,40831).
+char(4,40832).
+char(4,40833).
+char(c,40834).
+char(c,40835).
+char(m,40836).
+char(8,40837).
+char(9,40838).
+char(7,40839).
+char(p,40840).
+char(4,40841).
+char(6,40842).
+char(1,40843).
+char(8,40844).
+char(c,40845).
+char(c,40846).
+char(m,40847).
+char(o,40848).
+char(p,40849).
+char(1,40850).
+char(0,40851).
+char(8,40852).
+char(1,40853).
+char(c,40854).
+char(c,40855).
+char(c,40856).
+char(p,40857).
+char(o,40858).
+char(p,40859).
+char(8,40860).
+char(7,40861).
+char(0,40862).
+char(2,40863).
+char(p,40864).
+char(5,40865).
+char(5,40866).
+char(8,40867).
+char(6,40868).
+char(p,40869).
+char(4,40870).
+char(7,40871).
+char(5,40872).
+char(9,40873).
+char(c,40874).
+char(c,40875).
+char(p,40876).
+char(1,40877).
+char(4,40878).
+char(4,40879).
+char(7,40880).
+char(m,40881).
+char(o,40882).
+char(p,40883).
+char(o,40884).
+char(p,40885).
+char(7,40886).
+char(6,40887).
+char(3,40888).
+char(9,40889).
+char(m,40890).
+char(o,40891).
+char(m,40892).
+char(o,40893).
+char(p,40894).
+char(o,40895).
+char(1,40896).
+char(0,40897).
+char(2,40898).
+char(8,40899).
+char(c,40900).
+char(m,40901).
+char(2,40902).
+char(6,40903).
+char(0,40904).
+char(5,40905).
+char(c,40906).
+char(m,40907).
+char(3,40908).
+char(6,40909).
+char(4,40910).
+char(8,40911).
+char(m,40912).
+char(6,40913).
+char(3,40914).
+char(9,40915).
+char(4,40916).
+char(p,40917).
+char(o,40918).
+char(p,40919).
+char(2,40920).
+char(6,40921).
+char(6,40922).
+char(c,40923).
+char(m,40924).
+char(3,40925).
+char(1,40926).
+char(6,40927).
+char(p,40928).
+char(1,40929).
+char(8,40930).
+char(3,40931).
+char(9,40932).
+char(c,40933).
+char(c,40934).
+char(c,40935).
+char(m,40936).
+char(o,40937).
+char(p,40938).
+char(o,40939).
+char(p,40940).
+char(2,40941).
+char(0,40942).
+char(1,40943).
+char(2,40944).
+char(p,40945).
+char(o,40946).
+char(o,40947).
+char(p,40948).
+char(o,40949).
+char(m,40950).
+char(o,40951).
+char(p,40952).
+char(o,40953).
+char(o,40954).
+char(m,40955).
+char(o,40956).
+char(m,40957).
+char(o,40958).
+char(p,40959).
+char(o,40960).
+char(7,40961).
+char(5,40962).
+char(3,40963).
+char(8,40964).
+char(c,40965).
+char(p,40966).
+char(o,40967).
+char(m,40968).
+char(3,40969).
+char(4,40970).
+char(1,40971).
+char(8,40972).
+char(p,40973).
+char(o,40974).
+char(p,40975).
+char(o,40976).
+char(o,40977).
+char(8,40978).
+char(8,40979).
+char(7,40980).
+char(5,40981).
+char(c,40982).
+char(c,40983).
+char(p,40984).
+char(2,40985).
+char(5,40986).
+char(4,40987).
+char(0,40988).
+char(m,40989).
+char(o,40990).
+char(p,40991).
+char(o,40992).
+char(p,40993).
+char(o,40994).
+char(p,40995).
+char(o,40996).
+char(m,40997).
+char(2,40998).
+char(9,40999).
+char(8,41000).
+char(5,41001).
+char(p,41002).
+char(2,41003).
+char(2,41004).
+char(2,41005).
+char(7,41006).
+char(p,41007).
+char(2,41008).
+char(6,41009).
+char(8,41010).
+char(3,41011).
+char(c,41012).
+char(c,41013).
+char(c,41014).
+char(m,41015).
+char(o,41016).
+char(p,41017).
+char(3,41018).
+char(5,41019).
+char(7,41020).
+char(7,41021).
+char(m,41022).
+char(4,41023).
+char(1,41024).
+char(9,41025).
+char(9,41026).
+char(m,41027).
+char(o,41028).
+char(p,41029).
+char(2,41030).
+char(8,41031).
+char(9,41032).
+char(1,41033).
+char(m,41034).
+char(3,41035).
+char(1,41036).
+char(9,41037).
+char(5,41038).
+char(m,41039).
+char(5,41040).
+char(9,41041).
+char(9,41042).
+char(5,41043).
+char(c,41044).
+char(c,41045).
+char(c,41046).
+char(c,41047).
+char(p,41048).
+char(3,41049).
+char(6,41050).
+char(6,41051).
+char(3,41052).
+char(c,41053).
+char(m,41054).
+char(6,41055).
+char(6,41056).
+char(1,41057).
+char(6,41058).
+char(c,41059).
+char(c,41060).
+char(m,41061).
+char(o,41062).
+char(p,41063).
+char(o,41064).
+char(p,41065).
+char(o,41066).
+char(5,41067).
+char(9,41068).
+char(5,41069).
+char(8,41070).
+char(c,41071).
+char(p,41072).
+char(o,41073).
+char(5,41074).
+char(5,41075).
+char(5,41076).
+char(1,41077).
+char(p,41078).
+char(o,41079).
+char(3,41080).
+char(0,41081).
+char(9,41082).
+char(6,41083).
+char(c,41084).
+char(c,41085).
+char(c,41086).
+char(c,41087).
+char(c,41088).
+char(c,41089).
+char(m,41090).
+char(o,41091).
+char(m,41092).
+char(1,41093).
+char(1,41094).
+char(4,41095).
+char(9,41096).
+char(c,41097).
+char(p,41098).
+char(o,41099).
+char(p,41100).
+char(o,41101).
+char(p,41102).
+char(o,41103).
+char(4,41104).
+char(1,41105).
+char(7,41106).
+char(2,41107).
+char(c,41108).
+char(m,41109).
+char(o,41110).
+char(m,41111).
+char(2,41112).
+char(3,41113).
+char(9,41114).
+char(9,41115).
+char(p,41116).
+char(9,41117).
+char(3,41118).
+char(2,41119).
+char(8,41120).
+char(c,41121).
+char(m,41122).
+char(9,41123).
+char(6,41124).
+char(4,41125).
+char(6,41126).
+char(p,41127).
+char(o,41128).
+char(m,41129).
+char(5,41130).
+char(4,41131).
+char(0,41132).
+char(2,41133).
+char(m,41134).
+char(o,41135).
+char(o,41136).
+char(p,41137).
+char(7,41138).
+char(6,41139).
+char(2,41140).
+char(6,41141).
+char(m,41142).
+char(o,41143).
+char(m,41144).
+char(o,41145).
+char(8,41146).
+char(1,41147).
+char(7,41148).
+char(4,41149).
+char(c,41150).
+char(m,41151).
+char(o,41152).
+char(o,41153).
+char(m,41154).
+char(o,41155).
+char(m,41156).
+char(o,41157).
+char(o,41158).
+char(m,41159).
+char(o,41160).
+char(p,41161).
+char(3,41162).
+char(4,41163).
+char(2,41164).
+char(6,41165).
+char(p,41166).
+char(8,41167).
+char(8,41168).
+char(2,41169).
+char(6,41170).
+char(c,41171).
+char(c,41172).
+char(m,41173).
+char(o,41174).
+char(m,41175).
+char(5,41176).
+char(5,41177).
+char(0,41178).
+char(0,41179).
+char(c,41180).
+char(m,41181).
+char(o,41182).
+char(4,41183).
+char(4,41184).
+char(1,41185).
+char(0,41186).
+char(c,41187).
+char(p,41188).
+char(8,41189).
+char(0,41190).
+char(0,41191).
+char(8,41192).
+char(m,41193).
+char(6,41194).
+char(4,41195).
+char(6,41196).
+char(3,41197).
+char(c,41198).
+char(c,41199).
+char(p,41200).
+char(5,41201).
+char(9,41202).
+char(4,41203).
+char(m,41204).
+char(7,41205).
+char(3,41206).
+char(6,41207).
+char(0,41208).
+char(c,41209).
+char(c,41210).
+char(c,41211).
+char(c,41212).
+char(c,41213).
+char(p,41214).
+char(o,41215).
+char(p,41216).
+char(2,41217).
+char(5,41218).
+char(2,41219).
+char(2,41220).
+char(m,41221).
+char(8,41222).
+char(3,41223).
+char(2,41224).
+char(3,41225).
+char(m,41226).
+char(o,41227).
+char(p,41228).
+char(o,41229).
+char(p,41230).
+char(o,41231).
+char(p,41232).
+char(7,41233).
+char(3,41234).
+char(8,41235).
+char(4,41236).
+char(c,41237).
+char(p,41238).
+char(o,41239).
+char(p,41240).
+char(5,41241).
+char(3,41242).
+char(1,41243).
+char(7,41244).
+char(c,41245).
+char(m,41246).
+char(o,41247).
+char(o,41248).
+char(m,41249).
+char(o,41250).
+char(p,41251).
+char(o,41252).
+char(p,41253).
+char(o,41254).
+char(6,41255).
+char(9,41256).
+char(6,41257).
+char(9,41258).
+char(p,41259).
+char(8,41260).
+char(5,41261).
+char(6,41262).
+char(5,41263).
+char(p,41264).
+char(2,41265).
+char(7,41266).
+char(3,41267).
+char(7,41268).
+char(c,41269).
+char(c,41270).
+char(m,41271).
+char(5,41272).
+char(9,41273).
+char(3,41274).
+char(8,41275).
+char(p,41276).
+char(1,41277).
+char(8,41278).
+char(4,41279).
+char(1,41280).
+char(c,41281).
+char(c,41282).
+char(p,41283).
+char(o,41284).
+char(p,41285).
+char(o,41286).
+char(o,41287).
+char(m,41288).
+char(3,41289).
+char(2,41290).
+char(8,41291).
+char(4,41292).
+char(p,41293).
+char(o,41294).
+char(p,41295).
+char(8,41296).
+char(3,41297).
+char(8,41298).
+char(5,41299).
+char(p,41300).
+char(7,41301).
+char(9,41302).
+char(0,41303).
+char(4,41304).
+char(c,41305).
+char(c,41306).
+char(p,41307).
+char(o,41308).
+char(m,41309).
+char(o,41310).
+char(o,41311).
+char(m,41312).
+char(7,41313).
+char(8,41314).
+char(6,41315).
+char(5,41316).
+char(c,41317).
+char(c,41318).
+char(p,41319).
+char(o,41320).
+char(o,41321).
+char(p,41322).
+char(o,41323).
+char(m,41324).
+char(o,41325).
+char(o,41326).
+char(o,41327).
+char(p,41328).
+char(o,41329).
+char(m,41330).
+char(6,41331).
+char(9,41332).
+char(6,41333).
+char(7,41334).
+char(p,41335).
+char(5,41336).
+char(8,41337).
+char(0,41338).
+char(5,41339).
+char(c,41340).
+char(p,41341).
+char(o,41342).
+char(p,41343).
+char(o,41344).
+char(p,41345).
+char(2,41346).
+char(1,41347).
+char(4,41348).
+char(9,41349).
+char(c,41350).
+char(c,41351).
+char(p,41352).
+char(o,41353).
+char(m,41354).
+char(2,41355).
+char(1,41356).
+char(4,41357).
+char(6,41358).
+char(c,41359).
+char(c,41360).
+char(m,41361).
+char(4,41362).
+char(6,41363).
+char(5,41364).
+char(m,41365).
+char(o,41366).
+char(p,41367).
+char(o,41368).
+char(m,41369).
+char(o,41370).
+char(m,41371).
+char(o,41372).
+char(p,41373).
+char(o,41374).
+char(5,41375).
+char(9,41376).
+char(9,41377).
+char(3,41378).
+char(c,41379).
+char(p,41380).
+char(o,41381).
+char(p,41382).
+char(1,41383).
+char(7,41384).
+char(1,41385).
+char(7,41386).
+char(c,41387).
+char(c,41388).
+char(p,41389).
+char(o,41390).
+char(7,41391).
+char(2,41392).
+char(9,41393).
+char(9,41394).
+char(c,41395).
+char(p,41396).
+char(o,41397).
+char(1,41398).
+char(8,41399).
+char(2,41400).
+char(5,41401).
+char(p,41402).
+char(o,41403).
+char(m,41404).
+char(o,41405).
+char(m,41406).
+char(9,41407).
+char(3,41408).
+char(1,41409).
+char(6,41410).
+char(c,41411).
+char(p,41412).
+char(o,41413).
+char(o,41414).
+char(p,41415).
+char(8,41416).
+char(5,41417).
+char(0,41418).
+char(8,41419).
+char(p,41420).
+char(o,41421).
+char(m,41422).
+char(2,41423).
+char(5,41424).
+char(7,41425).
+char(0,41426).
+char(m,41427).
+char(o,41428).
+char(m,41429).
+char(1,41430).
+char(3,41431).
+char(6,41432).
+char(5,41433).
+char(m,41434).
+char(o,41435).
+char(m,41436).
+char(o,41437).
+char(o,41438).
+char(o,41439).
+char(p,41440).
+char(o,41441).
+char(m,41442).
+char(o,41443).
+char(6,41444).
+char(0,41445).
+char(1,41446).
+char(3,41447).
+char(c,41448).
+char(p,41449).
+char(7,41450).
+char(8,41451).
+char(9,41452).
+char(1,41453).
+char(p,41454).
+char(4,41455).
+char(6,41456).
+char(6,41457).
+char(6,41458).
+char(c,41459).
+char(c,41460).
+char(c,41461).
+char(m,41462).
+char(o,41463).
+char(p,41464).
+char(7,41465).
+char(3,41466).
+char(0,41467).
+char(1,41468).
+char(c,41469).
+char(c,41470).
+char(p,41471).
+char(o,41472).
+char(5,41473).
+char(3,41474).
+char(8,41475).
+char(4,41476).
+char(m,41477).
+char(4,41478).
+char(0,41479).
+char(9,41480).
+char(m,41481).
+char(o,41482).
+char(p,41483).
+char(9,41484).
+char(3,41485).
+char(7,41486).
+char(6,41487).
+char(m,41488).
+char(7,41489).
+char(3,41490).
+char(0,41491).
+char(5,41492).
+char(c,41493).
+char(m,41494).
+char(8,41495).
+char(4,41496).
+char(3,41497).
+char(1,41498).
+char(p,41499).
+char(3,41500).
+char(8,41501).
+char(2,41502).
+char(6,41503).
+char(p,41504).
+char(o,41505).
+char(m,41506).
+char(6,41507).
+char(8,41508).
+char(4,41509).
+char(8,41510).
+char(c,41511).
+char(c,41512).
+char(c,41513).
+char(p,41514).
+char(7,41515).
+char(7,41516).
+char(3,41517).
+char(1,41518).
+char(c,41519).
+char(m,41520).
+char(3,41521).
+char(8,41522).
+char(7,41523).
+char(3,41524).
+char(m,41525).
+char(6,41526).
+char(2,41527).
+char(6,41528).
+char(9,41529).
+char(p,41530).
+char(6,41531).
+char(4,41532).
+char(4,41533).
+char(6,41534).
+char(c,41535).
+char(p,41536).
+char(o,41537).
+char(m,41538).
+char(o,41539).
+char(m,41540).
+char(2,41541).
+char(4,41542).
+char(4,41543).
+char(2,41544).
+char(c,41545).
+char(m,41546).
+char(9,41547).
+char(5,41548).
+char(3,41549).
+char(9,41550).
+char(c,41551).
+char(c,41552).
+char(m,41553).
+char(4,41554).
+char(5,41555).
+char(6,41556).
+char(1,41557).
+char(c,41558).
+char(c,41559).
+char(c,41560).
+char(p,41561).
+char(o,41562).
+char(p,41563).
+char(3,41564).
+char(9,41565).
+char(9,41566).
+char(1,41567).
+char(p,41568).
+char(o,41569).
+char(m,41570).
+char(6,41571).
+char(0,41572).
+char(3,41573).
+char(4,41574).
+char(p,41575).
+char(6,41576).
+char(6,41577).
+char(8,41578).
+char(c,41579).
+char(c,41580).
+char(c,41581).
+char(m,41582).
+char(o,41583).
+char(m,41584).
+char(o,41585).
+char(o,41586).
+char(m,41587).
+char(8,41588).
+char(7,41589).
+char(6,41590).
+char(9,41591).
+char(p,41592).
+char(3,41593).
+char(7,41594).
+char(3,41595).
+char(6,41596).
+char(c,41597).
+char(c,41598).
+char(m,41599).
+char(o,41600).
+char(p,41601).
+char(4,41602).
+char(8,41603).
+char(4,41604).
+char(1,41605).
+char(p,41606).
+char(7,41607).
+char(4,41608).
+char(2,41609).
+char(8,41610).
+char(c,41611).
+char(p,41612).
+char(6,41613).
+char(5,41614).
+char(1,41615).
+char(4,41616).
+char(c,41617).
+char(c,41618).
+char(m,41619).
+char(o,41620).
+char(5,41621).
+char(9,41622).
+char(3,41623).
+char(5,41624).
+char(p,41625).
+char(o,41626).
+char(m,41627).
+char(9,41628).
+char(9,41629).
+char(1,41630).
+char(1,41631).
+char(m,41632).
+char(o,41633).
+char(p,41634).
+char(o,41635).
+char(p,41636).
+char(o,41637).
+char(5,41638).
+char(1,41639).
+char(3,41640).
+char(0,41641).
+char(c,41642).
+char(p,41643).
+char(o,41644).
+char(m,41645).
+char(7,41646).
+char(5,41647).
+char(5,41648).
+char(3,41649).
+char(m,41650).
+char(o,41651).
+char(p,41652).
+char(9,41653).
+char(3,41654).
+char(3,41655).
+char(9,41656).
+char(p,41657).
+char(o,41658).
+char(1,41659).
+char(0,41660).
+char(0,41661).
+char(2,41662).
+char(m,41663).
+char(6,41664).
+char(6,41665).
+char(4,41666).
+char(0,41667).
+char(c,41668).
+char(c,41669).
+char(c,41670).
+char(c,41671).
+char(m,41672).
+char(1,41673).
+char(2,41674).
+char(3,41675).
+char(8,41676).
+char(p,41677).
+char(o,41678).
+char(m,41679).
+char(o,41680).
+char(8,41681).
+char(1,41682).
+char(1,41683).
+char(8,41684).
+char(c,41685).
+char(m,41686).
+char(o,41687).
+char(5,41688).
+char(4,41689).
+char(7,41690).
+char(3,41691).
+char(p,41692).
+char(o,41693).
+char(p,41694).
+char(o,41695).
+char(m,41696).
+char(3,41697).
+char(2,41698).
+char(7,41699).
+char(3,41700).
+char(c,41701).
+char(p,41702).
+char(8,41703).
+char(9,41704).
+char(8,41705).
+char(9,41706).
+char(c,41707).
+char(c,41708).
+char(c,41709).
+char(p,41710).
+char(o,41711).
+char(4,41712).
+char(3,41713).
+char(2,41714).
+char(6,41715).
+char(m,41716).
+char(o,41717).
+char(o,41718).
+char(o,41719).
+char(m,41720).
+char(o,41721).
+char(5,41722).
+char(6,41723).
+char(9,41724).
+char(9,41725).
+char(p,41726).
+char(2,41727).
+char(4,41728).
+char(2,41729).
+char(c,41730).
+char(c,41731).
+char(p,41732).
+char(o,41733).
+char(o,41734).
+char(m,41735).
+char(5,41736).
+char(6,41737).
+char(2,41738).
+char(5,41739).
+char(c,41740).
+char(m,41741).
+char(o,41742).
+char(m,41743).
+char(o,41744).
+char(m,41745).
+char(o,41746).
+char(2,41747).
+char(4,41748).
+char(7,41749).
+char(3,41750).
+char(c,41751).
+char(c,41752).
+char(p,41753).
+char(2,41754).
+char(9,41755).
+char(6,41756).
+char(3,41757).
+char(m,41758).
+char(4,41759).
+char(1,41760).
+char(1,41761).
+char(2,41762).
+char(c,41763).
+char(m,41764).
+char(o,41765).
+char(2,41766).
+char(1,41767).
+char(9,41768).
+char(7,41769).
+char(p,41770).
+char(o,41771).
+char(p,41772).
+char(o,41773).
+char(p,41774).
+char(o,41775).
+char(2,41776).
+char(7,41777).
+char(1,41778).
+char(1,41779).
+char(p,41780).
+char(9,41781).
+char(2,41782).
+char(7,41783).
+char(4,41784).
+char(m,41785).
+char(o,41786).
+char(p,41787).
+char(o,41788).
+char(p,41789).
+char(o,41790).
+char(2,41791).
+char(4,41792).
+char(1,41793).
+char(8,41794).
+char(m,41795).
+char(4,41796).
+char(9,41797).
+char(8,41798).
+char(4,41799).
+char(c,41800).
+char(c,41801).
+char(p,41802).
+char(o,41803).
+char(m,41804).
+char(o,41805).
+char(m,41806).
+char(o,41807).
+char(p,41808).
+char(4,41809).
+char(5,41810).
+char(7,41811).
+char(9,41812).
+char(p,41813).
+char(3,41814).
+char(0,41815).
+char(5,41816).
+char(1,41817).
+char(c,41818).
+char(m,41819).
+char(o,41820).
+char(o,41821).
+char(4,41822).
+char(6,41823).
+char(8,41824).
+char(9,41825).
+char(c,41826).
+char(p,41827).
+char(4,41828).
+char(5,41829).
+char(3,41830).
+char(5,41831).
+char(m,41832).
+char(o,41833).
+char(m,41834).
+char(o,41835).
+char(o,41836).
+char(m,41837).
+char(o,41838).
+char(m,41839).
+char(7,41840).
+char(8,41841).
+char(3,41842).
+char(0,41843).
+char(c,41844).
+char(c,41845).
+char(m,41846).
+char(2,41847).
+char(7,41848).
+char(7,41849).
+char(4,41850).
+char(c,41851).
+char(c,41852).
+char(p,41853).
+char(o,41854).
+char(p,41855).
+char(o,41856).
+char(p,41857).
+char(o,41858).
+char(o,41859).
+char(p,41860).
+char(o,41861).
+char(m,41862).
+char(6,41863).
+char(6,41864).
+char(9,41865).
+char(1,41866).
+char(m,41867).
+char(o,41868).
+char(m,41869).
+char(5,41870).
+char(0,41871).
+char(1,41872).
+char(2,41873).
+char(c,41874).
+char(c,41875).
+char(p,41876).
+char(o,41877).
+char(m,41878).
+char(1,41879).
+char(4,41880).
+char(0,41881).
+char(9,41882).
+char(c,41883).
+char(m,41884).
+char(o,41885).
+char(2,41886).
+char(9,41887).
+char(2,41888).
+char(0,41889).
+char(m,41890).
+char(1,41891).
+char(0,41892).
+char(6,41893).
+char(9,41894).
+char(p,41895).
+char(3,41896).
+char(2,41897).
+char(0,41898).
+char(1,41899).
+char(m,41900).
+char(5,41901).
+char(0,41902).
+char(3,41903).
+char(4,41904).
+char(c,41905).
+char(c,41906).
+char(c,41907).
+char(c,41908).
+char(p,41909).
+char(o,41910).
+char(o,41911).
+char(o,41912).
+char(p,41913).
+char(1,41914).
+char(9,41915).
+char(7,41916).
+char(1,41917).
+char(p,41918).
+char(4,41919).
+char(5,41920).
+char(8,41921).
+char(5,41922).
+char(p,41923).
+char(o,41924).
+char(8,41925).
+char(6,41926).
+char(0,41927).
+char(8,41928).
+char(c,41929).
+char(c,41930).
+char(m,41931).
+char(6,41932).
+char(9,41933).
+char(9,41934).
+char(4,41935).
+char(c,41936).
+char(m,41937).
+char(9,41938).
+char(8,41939).
+char(1,41940).
+char(2,41941).
+char(m,41942).
+char(o,41943).
+char(o,41944).
+char(p,41945).
+char(7,41946).
+char(0,41947).
+char(6,41948).
+char(7,41949).
+char(c,41950).
+char(m,41951).
+char(o,41952).
+char(8,41953).
+char(5,41954).
+char(3,41955).
+char(8,41956).
+char(c,41957).
+char(p,41958).
+char(7,41959).
+char(9,41960).
+char(8,41961).
+char(1,41962).
+char(c,41963).
+char(c,41964).
+char(c,41965).
+char(p,41966).
+char(7,41967).
+char(8,41968).
+char(7,41969).
+char(8,41970).
+char(m,41971).
+char(8,41972).
+char(7,41973).
+char(6,41974).
+char(9,41975).
+char(p,41976).
+char(o,41977).
+char(m,41978).
+char(o,41979).
+char(3,41980).
+char(2,41981).
+char(7,41982).
+char(1,41983).
+char(m,41984).
+char(o,41985).
+char(o,41986).
+char(o,41987).
+char(p,41988).
+char(9,41989).
+char(7,41990).
+char(5,41991).
+char(1,41992).
+char(p,41993).
+char(o,41994).
+char(m,41995).
+char(o,41996).
+char(p,41997).
+char(1,41998).
+char(3,41999).
+char(1,42000).
+char(3,42001).
+char(p,42002).
+char(9,42003).
+char(6,42004).
+char(9,42005).
+char(3,42006).
+char(m,42007).
+char(o,42008).
+char(m,42009).
+char(o,42010).
+char(p,42011).
+char(4,42012).
+char(9,42013).
+char(4,42014).
+char(2,42015).
+char(m,42016).
+char(4,42017).
+char(7,42018).
+char(8,42019).
+char(p,42020).
+char(o,42021).
+char(p,42022).
+char(o,42023).
+char(m,42024).
+char(7,42025).
+char(6,42026).
+char(8,42027).
+char(c,42028).
+char(m,42029).
+char(3,42030).
+char(9,42031).
+char(5,42032).
+char(5,42033).
+char(c,42034).
+char(m,42035).
+char(o,42036).
+char(p,42037).
+char(o,42038).
+char(o,42039).
+char(p,42040).
+char(o,42041).
+char(o,42042).
+char(p,42043).
+char(1,42044).
+char(1,42045).
+char(3,42046).
+char(9,42047).
+char(p,42048).
+char(o,42049).
+char(3,42050).
+char(5,42051).
+char(2,42052).
+char(1,42053).
+char(c,42054).
+char(c,42055).
+char(m,42056).
+char(o,42057).
+char(7,42058).
+char(8,42059).
+char(6,42060).
+char(7,42061).
+char(c,42062).
+char(c,42063).
+char(c,42064).
+char(p,42065).
+char(o,42066).
+char(o,42067).
+char(p,42068).
+char(o,42069).
+char(m,42070).
+char(2,42071).
+char(5,42072).
+char(5,42073).
+char(0,42074).
+char(p,42075).
+char(8,42076).
+char(9,42077).
+char(6,42078).
+char(3,42079).
+char(c,42080).
+char(c,42081).
+char(c,42082).
+char(c,42083).
+char(c,42084).
+char(m,42085).
+char(o,42086).
+char(m,42087).
+char(2,42088).
+char(1,42089).
+char(1,42090).
+char(1,42091).
+char(m,42092).
+char(1,42093).
+char(0,42094).
+char(4,42095).
+char(9,42096).
+char(c,42097).
+char(c,42098).
+char(c,42099).
+char(c,42100).
+char(m,42101).
+char(o,42102).
+char(o,42103).
+char(m,42104).
+char(4,42105).
+char(1,42106).
+char(7,42107).
+char(8,42108).
+char(c,42109).
+char(c,42110).
+char(m,42111).
+char(2,42112).
+char(1,42113).
+char(9,42114).
+char(5,42115).
+char(p,42116).
+char(o,42117).
+char(m,42118).
+char(5,42119).
+char(2,42120).
+char(4,42121).
+char(7,42122).
+char(m,42123).
+char(o,42124).
+char(o,42125).
+char(m,42126).
+char(2,42127).
+char(9,42128).
+char(1,42129).
+char(6,42130).
+char(c,42131).
+char(c,42132).
+char(p,42133).
+char(o,42134).
+char(p,42135).
+char(7,42136).
+char(5,42137).
+char(3,42138).
+char(3,42139).
+char(m,42140).
+char(2,42141).
+char(9,42142).
+char(1,42143).
+char(p,42144).
+char(6,42145).
+char(0,42146).
+char(1,42147).
+char(6,42148).
+char(m,42149).
+char(4,42150).
+char(4,42151).
+char(7,42152).
+char(6,42153).
+char(c,42154).
+char(p,42155).
+char(8,42156).
+char(8,42157).
+char(0,42158).
+char(1,42159).
+char(c,42160).
+char(p,42161).
+char(o,42162).
+char(o,42163).
+char(p,42164).
+char(5,42165).
+char(6,42166).
+char(1,42167).
+char(4,42168).
+char(m,42169).
+char(o,42170).
+char(m,42171).
+char(8,42172).
+char(2,42173).
+char(4,42174).
+char(9,42175).
+char(m,42176).
+char(o,42177).
+char(8,42178).
+char(7,42179).
+char(9,42180).
+char(2,42181).
+char(p,42182).
+char(o,42183).
+char(m,42184).
+char(o,42185).
+char(1,42186).
+char(5,42187).
+char(2,42188).
+char(9,42189).
+char(c,42190).
+char(c,42191).
+char(m,42192).
+char(o,42193).
+char(p,42194).
+char(4,42195).
+char(3,42196).
+char(4,42197).
+char(4,42198).
+char(m,42199).
+char(o,42200).
+char(o,42201).
+char(m,42202).
+char(o,42203).
+char(p,42204).
+char(7,42205).
+char(2,42206).
+char(0,42207).
+char(m,42208).
+char(4,42209).
+char(9,42210).
+char(6,42211).
+char(4,42212).
+char(c,42213).
+char(c,42214).
+char(m,42215).
+char(8,42216).
+char(5,42217).
+char(3,42218).
+char(2,42219).
+char(c,42220).
+char(c,42221).
+char(m,42222).
+char(4,42223).
+char(6,42224).
+char(0,42225).
+char(8,42226).
+char(m,42227).
+char(2,42228).
+char(1,42229).
+char(3,42230).
+char(6,42231).
+char(p,42232).
+char(3,42233).
+char(2,42234).
+char(1,42235).
+char(2,42236).
+char(m,42237).
+char(o,42238).
+char(m,42239).
+char(9,42240).
+char(9,42241).
+char(p,42242).
+char(6,42243).
+char(8,42244).
+char(8,42245).
+char(5,42246).
+char(c,42247).
+char(m,42248).
+char(6,42249).
+char(1,42250).
+char(7,42251).
+char(1,42252).
+char(m,42253).
+char(o,42254).
+char(9,42255).
+char(8,42256).
+char(2,42257).
+char(1,42258).
+char(m,42259).
+char(o,42260).
+char(p,42261).
+char(3,42262).
+char(6,42263).
+char(7,42264).
+char(8,42265).
+char(m,42266).
+char(o,42267).
+char(m,42268).
+char(3,42269).
+char(6,42270).
+char(6,42271).
+char(4,42272).
+char(p,42273).
+char(o,42274).
+char(o,42275).
+char(3,42276).
+char(7,42277).
+char(7,42278).
+char(p,42279).
+char(o,42280).
+char(m,42281).
+char(7,42282).
+char(1,42283).
+char(7,42284).
+char(1,42285).
+char(c,42286).
+char(c,42287).
+char(p,42288).
+char(o,42289).
+char(7,42290).
+char(9,42291).
+char(4,42292).
+char(1,42293).
+char(p,42294).
+char(9,42295).
+char(7,42296).
+char(9,42297).
+char(9,42298).
+char(c,42299).
+char(p,42300).
+char(3,42301).
+char(5,42302).
+char(7,42303).
+char(7,42304).
+char(p,42305).
+char(8,42306).
+char(6,42307).
+char(0,42308).
+char(9,42309).
+char(p,42310).
+char(o,42311).
+char(o,42312).
+char(p,42313).
+char(o,42314).
+char(p,42315).
+char(8,42316).
+char(5,42317).
+char(4,42318).
+char(6,42319).
+char(c,42320).
+char(c,42321).
+char(p,42322).
+char(o,42323).
+char(o,42324).
+char(m,42325).
+char(4,42326).
+char(1,42327).
+char(7,42328).
+char(3,42329).
+char(c,42330).
+char(c,42331).
+char(c,42332).
+char(m,42333).
+char(9,42334).
+char(4,42335).
+char(0,42336).
+char(5,42337).
+char(m,42338).
+char(o,42339).
+char(m,42340).
+char(o,42341).
+char(o,42342).
+char(7,42343).
+char(4,42344).
+char(9,42345).
+char(c,42346).
+char(c,42347).
+char(m,42348).
+char(2,42349).
+char(0,42350).
+char(6,42351).
+char(7,42352).
+char(m,42353).
+char(o,42354).
+char(p,42355).
+char(o,42356).
+char(p,42357).
+char(6,42358).
+char(4,42359).
+char(4,42360).
+char(c,42361).
+char(m,42362).
+char(o,42363).
+char(m,42364).
+char(o,42365).
+char(o,42366).
+char(m,42367).
+char(o,42368).
+char(o,42369).
+char(o,42370).
+char(p,42371).
+char(o,42372).
+char(p,42373).
+char(2,42374).
+char(6,42375).
+char(4,42376).
+char(2,42377).
+char(p,42378).
+char(6,42379).
+char(8,42380).
+char(3,42381).
+char(3,42382).
+char(c,42383).
+char(c,42384).
+char(p,42385).
+char(6,42386).
+char(8,42387).
+char(1,42388).
+char(3,42389).
+char(c,42390).
+char(p,42391).
+char(3,42392).
+char(1,42393).
+char(3,42394).
+char(7,42395).
+char(c,42396).
+char(c,42397).
+char(m,42398).
+char(o,42399).
+char(p,42400).
+char(6,42401).
+char(8,42402).
+char(1,42403).
+char(9,42404).
+char(c,42405).
+char(m,42406).
+char(o,42407).
+char(o,42408).
+char(p,42409).
+char(8,42410).
+char(3,42411).
+char(9,42412).
+char(8,42413).
+char(p,42414).
+char(3,42415).
+char(5,42416).
+char(2,42417).
+char(9,42418).
+char(m,42419).
+char(o,42420).
+char(m,42421).
+char(5,42422).
+char(4,42423).
+char(9,42424).
+char(9,42425).
+char(c,42426).
+char(c,42427).
+char(p,42428).
+char(5,42429).
+char(6,42430).
+char(1,42431).
+char(7,42432).
+char(p,42433).
+char(7,42434).
+char(4,42435).
+char(2,42436).
+char(0,42437).
+char(p,42438).
+char(1,42439).
+char(5,42440).
+char(5,42441).
+char(6,42442).
+char(c,42443).
+char(c,42444).
+char(c,42445).
+char(c,42446).
+char(c,42447).
+char(c,42448).
+char(m,42449).
+char(4,42450).
+char(3,42451).
+char(9,42452).
+char(1,42453).
+char(c,42454).
+char(m,42455).
+char(9,42456).
+char(3,42457).
+char(2,42458).
+char(5,42459).
+char(m,42460).
+char(1,42461).
+char(8,42462).
+char(7,42463).
+char(4,42464).
+char(m,42465).
+char(o,42466).
+char(o,42467).
+char(9,42468).
+char(7,42469).
+char(6,42470).
+char(1,42471).
+char(m,42472).
+char(8,42473).
+char(1,42474).
+char(0,42475).
+char(8,42476).
+char(p,42477).
+char(5,42478).
+char(4,42479).
+char(9,42480).
+char(0,42481).
+char(c,42482).
+char(m,42483).
+char(5,42484).
+char(9,42485).
+char(1,42486).
+char(4,42487).
+char(p,42488).
+char(o,42489).
+char(m,42490).
+char(1,42491).
+char(8,42492).
+char(9,42493).
+char(9,42494).
+char(c,42495).
+char(p,42496).
+char(o,42497).
+char(p,42498).
+char(4,42499).
+char(1,42500).
+char(6,42501).
+char(1,42502).
+char(p,42503).
+char(1,42504).
+char(2,42505).
+char(7,42506).
+char(8,42507).
+char(p,42508).
+char(2,42509).
+char(5,42510).
+char(4,42511).
+char(0,42512).
+char(c,42513).
+char(p,42514).
+char(1,42515).
+char(4,42516).
+char(0,42517).
+char(2,42518).
+char(c,42519).
+char(c,42520).
+char(p,42521).
+char(4,42522).
+char(6,42523).
+char(3,42524).
+char(0,42525).
+char(c,42526).
+char(m,42527).
+char(o,42528).
+char(2,42529).
+char(4,42530).
+char(0,42531).
+char(8,42532).
+char(p,42533).
+char(o,42534).
+char(o,42535).
+char(o,42536).
+char(p,42537).
+char(o,42538).
+char(m,42539).
+char(o,42540).
+char(7,42541).
+char(7,42542).
+char(5,42543).
+char(6,42544).
+char(c,42545).
+char(m,42546).
+char(o,42547).
+char(6,42548).
+char(5,42549).
+char(4,42550).
+char(3,42551).
+char(p,42552).
+char(1,42553).
+char(6,42554).
+char(0,42555).
+char(2,42556).
+char(c,42557).
+char(c,42558).
+char(p,42559).
+char(o,42560).
+char(m,42561).
+char(o,42562).
+char(p,42563).
+char(5,42564).
+char(9,42565).
+char(1,42566).
+char(9,42567).
+char(m,42568).
+char(o,42569).
+char(p,42570).
+char(6,42571).
+char(3,42572).
+char(0,42573).
+char(8,42574).
+char(c,42575).
+char(c,42576).
+char(c,42577).
+char(c,42578).
+char(c,42579).
+char(c,42580).
+char(m,42581).
+char(o,42582).
+char(m,42583).
+char(o,42584).
+char(p,42585).
+char(o,42586).
+char(p,42587).
+char(o,42588).
+char(9,42589).
+char(5,42590).
+char(7,42591).
+char(4,42592).
+char(p,42593).
+char(o,42594).
+char(p,42595).
+char(o,42596).
+char(o,42597).
+char(p,42598).
+char(o,42599).
+char(p,42600).
+char(o,42601).
+char(p,42602).
+char(4,42603).
+char(9,42604).
+char(0,42605).
+char(9,42606).
+char(c,42607).
+char(m,42608).
+char(8,42609).
+char(7,42610).
+char(4,42611).
+char(7,42612).
+char(m,42613).
+char(o,42614).
+char(p,42615).
+char(o,42616).
+char(m,42617).
+char(6,42618).
+char(0,42619).
+char(3,42620).
+char(0,42621).
+char(c,42622).
+char(c,42623).
+char(c,42624).
+char(p,42625).
+char(o,42626).
+char(m,42627).
+char(7,42628).
+char(3,42629).
+char(8,42630).
+char(7,42631).
+char(p,42632).
+char(o,42633).
+char(p,42634).
+char(5,42635).
+char(8,42636).
+char(7,42637).
+char(3,42638).
+char(p,42639).
+char(o,42640).
+char(o,42641).
+char(p,42642).
+char(o,42643).
+char(9,42644).
+char(3,42645).
+char(5,42646).
+char(c,42647).
+char(p,42648).
+char(5,42649).
+char(3,42650).
+char(5,42651).
+char(6,42652).
+char(p,42653).
+char(3,42654).
+char(3,42655).
+char(0,42656).
+char(0,42657).
+char(c,42658).
+char(p,42659).
+char(1,42660).
+char(5,42661).
+char(4,42662).
+char(1,42663).
+char(p,42664).
+char(3,42665).
+char(9,42666).
+char(0,42667).
+char(3,42668).
+char(c,42669).
+char(c,42670).
+char(m,42671).
+char(2,42672).
+char(5,42673).
+char(4,42674).
+char(5,42675).
+char(p,42676).
+char(9,42677).
+char(1,42678).
+char(3,42679).
+char(5,42680).
+char(c,42681).
+char(p,42682).
+char(o,42683).
+char(m,42684).
+char(2,42685).
+char(1,42686).
+char(4,42687).
+char(8,42688).
+char(c,42689).
+char(c,42690).
+char(c,42691).
+char(c,42692).
+char(c,42693).
+char(c,42694).
+char(p,42695).
+char(o,42696).
+char(5,42697).
+char(2,42698).
+char(1,42699).
+char(8,42700).
+char(c,42701).
+char(c,42702).
+char(p,42703).
+char(o,42704).
+char(3,42705).
+char(1,42706).
+char(9,42707).
+char(2,42708).
+char(c,42709).
+char(c,42710).
+char(c,42711).
+char(m,42712).
+char(o,42713).
+char(2,42714).
+char(2,42715).
+char(5,42716).
+char(6,42717).
+char(p,42718).
+char(8,42719).
+char(8,42720).
+char(4,42721).
+char(0,42722).
+char(c,42723).
+char(p,42724).
+char(8,42725).
+char(5,42726).
+char(5,42727).
+char(5,42728).
+char(c,42729).
+char(c,42730).
+char(c,42731).
+char(m,42732).
+char(4,42733).
+char(2,42734).
+char(5,42735).
+char(5,42736).
+char(c,42737).
+char(c,42738).
+char(p,42739).
+char(o,42740).
+char(o,42741).
+char(9,42742).
+char(5,42743).
+char(4,42744).
+char(6,42745).
+char(c,42746).
+char(c,42747).
+char(p,42748).
+char(o,42749).
+char(3,42750).
+char(0,42751).
+char(9,42752).
+char(7,42753).
+char(m,42754).
+char(1,42755).
+char(8,42756).
+char(1,42757).
+char(4,42758).
+char(c,42759).
+char(m,42760).
+char(o,42761).
+char(m,42762).
+char(3,42763).
+char(9,42764).
+char(5,42765).
+char(1,42766).
+char(c,42767).
+char(c,42768).
+char(m,42769).
+char(o,42770).
+char(m,42771).
+char(o,42772).
+char(p,42773).
+char(1,42774).
+char(7,42775).
+char(0,42776).
+char(8,42777).
+char(c,42778).
+char(c,42779).
+char(m,42780).
+char(o,42781).
+char(p,42782).
+char(o,42783).
+char(m,42784).
+char(o,42785).
+char(p,42786).
+char(o,42787).
+char(o,42788).
+char(o,42789).
+char(8,42790).
+char(2,42791).
+char(4,42792).
+char(0,42793).
+char(p,42794).
+char(o,42795).
+char(m,42796).
+char(o,42797).
+char(7,42798).
+char(8,42799).
+char(7,42800).
+char(3,42801).
+char(c,42802).
+char(m,42803).
+char(6,42804).
+char(7,42805).
+char(0,42806).
+char(7,42807).
+char(p,42808).
+char(5,42809).
+char(8,42810).
+char(4,42811).
+char(0,42812).
+char(c,42813).
+char(c,42814).
+char(p,42815).
+char(8,42816).
+char(4,42817).
+char(6,42818).
+char(5,42819).
+char(m,42820).
+char(o,42821).
+char(p,42822).
+char(8,42823).
+char(8,42824).
+char(3,42825).
+char(4,42826).
+char(c,42827).
+char(m,42828).
+char(o,42829).
+char(m,42830).
+char(o,42831).
+char(o,42832).
+char(3,42833).
+char(4,42834).
+char(0,42835).
+char(0,42836).
+char(p,42837).
+char(3,42838).
+char(7,42839).
+char(1,42840).
+char(6,42841).
+char(c,42842).
+char(m,42843).
+char(o,42844).
+char(m,42845).
+char(o,42846).
+char(m,42847).
+char(o,42848).
+char(m,42849).
+char(o,42850).
+char(o,42851).
+char(p,42852).
+char(o,42853).
+char(m,42854).
+char(7,42855).
+char(1,42856).
+char(0,42857).
+char(9,42858).
+char(m,42859).
+char(2,42860).
+char(9,42861).
+char(9,42862).
+char(8,42863).
+char(c,42864).
+char(m,42865).
+char(7,42866).
+char(7,42867).
+char(4,42868).
+char(8,42869).
+char(m,42870).
+char(9,42871).
+char(5,42872).
+char(9,42873).
+char(m,42874).
+char(o,42875).
+char(o,42876).
+char(m,42877).
+char(1,42878).
+char(7,42879).
+char(0,42880).
+char(6,42881).
+char(m,42882).
+char(1,42883).
+char(4,42884).
+char(6,42885).
+char(p,42886).
+char(7,42887).
+char(2,42888).
+char(3,42889).
+char(5,42890).
+char(p,42891).
+char(o,42892).
+char(m,42893).
+char(1,42894).
+char(2,42895).
+char(4,42896).
+char(3,42897).
+char(m,42898).
+char(1,42899).
+char(3,42900).
+char(7,42901).
+char(0,42902).
+char(p,42903).
+char(o,42904).
+char(o,42905).
+char(p,42906).
+char(8,42907).
+char(2,42908).
+char(3,42909).
+char(p,42910).
+char(5,42911).
+char(9,42912).
+char(2,42913).
+char(4,42914).
+char(m,42915).
+char(2,42916).
+char(0,42917).
+char(4,42918).
+char(4,42919).
+char(c,42920).
+char(c,42921).
+char(m,42922).
+char(1,42923).
+char(3,42924).
+char(8,42925).
+char(1,42926).
+char(c,42927).
+char(p,42928).
+char(o,42929).
+char(m,42930).
+char(6,42931).
+char(6,42932).
+char(7,42933).
+char(6,42934).
+char(c,42935).
+char(p,42936).
+char(o,42937).
+char(p,42938).
+char(7,42939).
+char(9,42940).
+char(7,42941).
+char(4,42942).
+char(m,42943).
+char(o,42944).
+char(p,42945).
+char(o,42946).
+char(p,42947).
+char(o,42948).
+char(m,42949).
+char(1,42950).
+char(8,42951).
+char(5,42952).
+char(7,42953).
+char(c,42954).
+char(m,42955).
+char(2,42956).
+char(6,42957).
+char(2,42958).
+char(1,42959).
+char(c,42960).
+char(p,42961).
+char(o,42962).
+char(p,42963).
+char(o,42964).
+char(m,42965).
+char(o,42966).
+char(p,42967).
+char(o,42968).
+char(m,42969).
+char(o,42970).
+char(p,42971).
+char(5,42972).
+char(2,42973).
+char(8,42974).
+char(8,42975).
+char(p,42976).
+char(o,42977).
+char(o,42978).
+char(m,42979).
+char(o,42980).
+char(m,42981).
+char(o,42982).
+char(m,42983).
+char(8,42984).
+char(8,42985).
+char(8,42986).
+char(6,42987).
+char(p,42988).
+char(o,42989).
+char(p,42990).
+char(9,42991).
+char(4,42992).
+char(7,42993).
+char(6,42994).
+char(m,42995).
+char(9,42996).
+char(7,42997).
+char(6,42998).
+char(8,42999).
+char(p,43000).
+char(o,43001).
+char(m,43002).
+char(o,43003).
+char(o,43004).
+char(8,43005).
+char(1,43006).
+char(3,43007).
+char(2,43008).
+char(c,43009).
+char(m,43010).
+char(o,43011).
+char(m,43012).
+char(9,43013).
+char(9,43014).
+char(5,43015).
+char(c,43016).
+char(p,43017).
+char(o,43018).
+char(o,43019).
+char(p,43020).
+char(o,43021).
+char(m,43022).
+char(4,43023).
+char(6,43024).
+char(9,43025).
+char(4,43026).
+char(m,43027).
+char(o,43028).
+char(o,43029).
+char(o,43030).
+char(p,43031).
+char(o,43032).
+char(o,43033).
+char(o,43034).
+char(5,43035).
+char(8,43036).
+char(6,43037).
+char(6,43038).
+char(c,43039).
+char(c,43040).
+char(p,43041).
+char(5,43042).
+char(6,43043).
+char(1,43044).
+char(7,43045).
+char(c,43046).
+char(c,43047).
+char(m,43048).
+char(o,43049).
+char(p,43050).
+char(7,43051).
+char(7,43052).
+char(7,43053).
+char(1,43054).
+char(c,43055).
+char(c,43056).
+char(c,43057).
+char(c,43058).
+char(p,43059).
+char(o,43060).
+char(o,43061).
+char(m,43062).
+char(o,43063).
+char(m,43064).
+char(o,43065).
+char(m,43066).
+char(6,43067).
+char(9,43068).
+char(6,43069).
+char(5,43070).
+char(c,43071).
+char(p,43072).
+char(7,43073).
+char(2,43074).
+char(6,43075).
+char(3,43076).
+char(c,43077).
+char(m,43078).
+char(3,43079).
+char(9,43080).
+char(5,43081).
+char(4,43082).
+char(c,43083).
+char(c,43084).
+char(c,43085).
+char(c,43086).
+char(c,43087).
+char(m,43088).
+char(o,43089).
+char(8,43090).
+char(4,43091).
+char(4,43092).
+char(7,43093).
+char(c,43094).
+char(c,43095).
+char(c,43096).
+char(c,43097).
+char(c,43098).
+char(c,43099).
+char(p,43100).
+char(4,43101).
+char(0,43102).
+char(2,43103).
+char(2,43104).
+char(c,43105).
+char(m,43106).
+char(o,43107).
+char(p,43108).
+char(9,43109).
+char(6,43110).
+char(2,43111).
+char(3,43112).
+char(c,43113).
+char(c,43114).
+char(c,43115).
+char(c,43116).
+char(p,43117).
+char(o,43118).
+char(p,43119).
+char(o,43120).
+char(m,43121).
+char(8,43122).
+char(7,43123).
+char(0,43124).
+char(7,43125).
+char(c,43126).
+char(p,43127).
+char(o,43128).
+char(p,43129).
+char(2,43130).
+char(9,43131).
+char(1,43132).
+char(0,43133).
+char(c,43134).
+char(c,43135).
+char(m,43136).
+char(4,43137).
+char(9,43138).
+char(1,43139).
+char(7,43140).
+char(c,43141).
+char(p,43142).
+char(o,43143).
+char(p,43144).
+char(o,43145).
+char(1,43146).
+char(5,43147).
+char(5,43148).
+char(3,43149).
+char(m,43150).
+char(o,43151).
+char(m,43152).
+char(o,43153).
+char(m,43154).
+char(o,43155).
+char(1,43156).
+char(0,43157).
+char(2,43158).
+char(1,43159).
+char(c,43160).
+char(c,43161).
+char(m,43162).
+char(o,43163).
+char(m,43164).
+char(o,43165).
+char(o,43166).
+char(m,43167).
+char(o,43168).
+char(p,43169).
+char(4,43170).
+char(7,43171).
+char(9,43172).
+char(2,43173).
+char(c,43174).
+char(c,43175).
+char(c,43176).
+char(m,43177).
+char(o,43178).
+char(9,43179).
+char(3,43180).
+char(3,43181).
+char(m,43182).
+char(9,43183).
+char(8,43184).
+char(7,43185).
+char(8,43186).
+char(c,43187).
+char(m,43188).
+char(1,43189).
+char(6,43190).
+char(8,43191).
+char(m,43192).
+char(o,43193).
+char(m,43194).
+char(5,43195).
+char(5,43196).
+char(3,43197).
+char(7,43198).
+char(p,43199).
+char(8,43200).
+char(9,43201).
+char(7,43202).
+char(7,43203).
+char(c,43204).
+char(m,43205).
+char(3,43206).
+char(1,43207).
+char(c,43208).
+char(p,43209).
+char(o,43210).
+char(m,43211).
+char(o,43212).
+char(p,43213).
+char(o,43214).
+char(m,43215).
+char(5,43216).
+char(1,43217).
+char(5,43218).
+char(0,43219).
+char(c,43220).
+char(p,43221).
+char(o,43222).
+char(m,43223).
+char(6,43224).
+char(4,43225).
+char(5,43226).
+char(5,43227).
+char(c,43228).
+char(c,43229).
+char(c,43230).
+char(c,43231).
+char(c,43232).
+char(c,43233).
+char(p,43234).
+char(6,43235).
+char(5,43236).
+char(7,43237).
+char(6,43238).
+char(c,43239).
+char(m,43240).
+char(o,43241).
+char(o,43242).
+char(p,43243).
+char(7,43244).
+char(0,43245).
+char(7,43246).
+char(0,43247).
+char(c,43248).
+char(m,43249).
+char(7,43250).
+char(3,43251).
+char(6,43252).
+char(m,43253).
+char(o,43254).
+char(m,43255).
+char(o,43256).
+char(8,43257).
+char(7,43258).
+char(6,43259).
+char(6,43260).
+char(p,43261).
+char(5,43262).
+char(4,43263).
+char(6,43264).
+char(5,43265).
+char(p,43266).
+char(3,43267).
+char(2,43268).
+char(0,43269).
+char(9,43270).
+char(c,43271).
+char(c,43272).
+char(c,43273).
+char(m,43274).
+char(o,43275).
+char(p,43276).
+char(o,43277).
+char(9,43278).
+char(5,43279).
+char(4,43280).
+char(2,43281).
+char(c,43282).
+char(p,43283).
+char(9,43284).
+char(5,43285).
+char(9,43286).
+char(0,43287).
+char(m,43288).
+char(3,43289).
+char(9,43290).
+char(8,43291).
+char(m,43292).
+char(o,43293).
+char(m,43294).
+char(9,43295).
+char(8,43296).
+char(5,43297).
+char(1,43298).
+char(m,43299).
+char(o,43300).
+char(m,43301).
+char(o,43302).
+char(p,43303).
+char(o,43304).
+char(m,43305).
+char(9,43306).
+char(0,43307).
+char(7,43308).
+char(8,43309).
+char(m,43310).
+char(o,43311).
+char(m,43312).
+char(4,43313).
+char(1,43314).
+char(0,43315).
+char(7,43316).
+char(p,43317).
+char(5,43318).
+char(1,43319).
+char(2,43320).
+char(0,43321).
+char(c,43322).
+char(c,43323).
+char(p,43324).
+char(o,43325).
+char(p,43326).
+char(o,43327).
+char(o,43328).
+char(m,43329).
+char(5,43330).
+char(8,43331).
+char(3,43332).
+char(8,43333).
+char(p,43334).
+char(o,43335).
+char(m,43336).
+char(6,43337).
+char(4,43338).
+char(2,43339).
+char(0,43340).
+char(p,43341).
+char(o,43342).
+char(o,43343).
+char(p,43344).
+char(1,43345).
+char(9,43346).
+char(6,43347).
+char(1,43348).
+char(c,43349).
+char(c,43350).
+char(m,43351).
+char(1,43352).
+char(1,43353).
+char(5,43354).
+char(7,43355).
+char(p,43356).
+char(1,43357).
+char(0,43358).
+char(7,43359).
+char(4,43360).
+char(c,43361).
+char(m,43362).
+char(1,43363).
+char(1,43364).
+char(8,43365).
+char(2,43366).
+char(m,43367).
+char(3,43368).
+char(7,43369).
+char(8,43370).
+char(7,43371).
+char(m,43372).
+char(o,43373).
+char(p,43374).
+char(o,43375).
+char(m,43376).
+char(9,43377).
+char(0,43378).
+char(3,43379).
+char(5,43380).
+char(c,43381).
+char(m,43382).
+char(8,43383).
+char(4,43384).
+char(5,43385).
+char(2,43386).
+char(c,43387).
+char(c,43388).
+char(c,43389).
+char(p,43390).
+char(o,43391).
+char(o,43392).
+char(m,43393).
+char(5,43394).
+char(4,43395).
+char(6,43396).
+char(6,43397).
+char(c,43398).
+char(p,43399).
+char(3,43400).
+char(6,43401).
+char(0,43402).
+char(4,43403).
+char(c,43404).
+char(p,43405).
+char(o,43406).
+char(m,43407).
+char(o,43408).
+char(p,43409).
+char(7,43410).
+char(7,43411).
+char(8,43412).
+char(7,43413).
+char(m,43414).
+char(o,43415).
+char(p,43416).
+char(o,43417).
+char(m,43418).
+char(6,43419).
+char(5,43420).
+char(1,43421).
+char(4,43422).
+char(m,43423).
+char(4,43424).
+char(3,43425).
+char(1,43426).
+char(8,43427).
+char(p,43428).
+char(o,43429).
+char(m,43430).
+char(3,43431).
+char(7,43432).
+char(2,43433).
+char(0,43434).
+char(m,43435).
+char(5,43436).
+char(0,43437).
+char(9,43438).
+char(1,43439).
+char(c,43440).
+char(c,43441).
+char(m,43442).
+char(2,43443).
+char(6,43444).
+char(7,43445).
+char(8,43446).
+char(c,43447).
+char(m,43448).
+char(9,43449).
+char(9,43450).
+char(2,43451).
+char(9,43452).
+char(c,43453).
+char(p,43454).
+char(4,43455).
+char(7,43456).
+char(6,43457).
+char(6,43458).
+char(c,43459).
+char(c,43460).
+char(p,43461).
+char(o,43462).
+char(m,43463).
+char(9,43464).
+char(8,43465).
+char(6,43466).
+char(6,43467).
+char(c,43468).
+char(c,43469).
+char(m,43470).
+char(o,43471).
+char(m,43472).
+char(5,43473).
+char(0,43474).
+char(8,43475).
+char(m,43476).
+char(8,43477).
+char(1,43478).
+char(2,43479).
+char(9,43480).
+char(c,43481).
+char(c,43482).
+char(c,43483).
+char(c,43484).
+char(c,43485).
+char(c,43486).
+char(c,43487).
+char(c,43488).
+char(m,43489).
+char(o,43490).
+char(o,43491).
+char(o,43492).
+char(7,43493).
+char(9,43494).
+char(4,43495).
+char(8,43496).
+char(p,43497).
+char(7,43498).
+char(0,43499).
+char(8,43500).
+char(9,43501).
+char(m,43502).
+char(o,43503).
+char(p,43504).
+char(9,43505).
+char(8,43506).
+char(2,43507).
+char(5,43508).
+char(p,43509).
+char(3,43510).
+char(9,43511).
+char(1,43512).
+char(9,43513).
+char(p,43514).
+char(6,43515).
+char(0,43516).
+char(0,43517).
+char(5,43518).
+char(m,43519).
+char(2,43520).
+char(5,43521).
+char(3,43522).
+char(2,43523).
+char(p,43524).
+char(5,43525).
+char(6,43526).
+char(9,43527).
+char(7,43528).
+char(p,43529).
+char(6,43530).
+char(0,43531).
+char(7,43532).
+char(2,43533).
+char(m,43534).
+char(o,43535).
+char(m,43536).
+char(o,43537).
+char(m,43538).
+char(1,43539).
+char(7,43540).
+char(9,43541).
+char(8,43542).
+char(c,43543).
+char(c,43544).
+char(c,43545).
+char(m,43546).
+char(4,43547).
+char(8,43548).
+char(2,43549).
+char(6,43550).
+char(p,43551).
+char(o,43552).
+char(m,43553).
+char(o,43554).
+char(7,43555).
+char(7,43556).
+char(1,43557).
+char(6,43558).
+char(p,43559).
+char(9,43560).
+char(9,43561).
+char(6,43562).
+char(m,43563).
+char(o,43564).
+char(m,43565).
+char(o,43566).
+char(p,43567).
+char(6,43568).
+char(1,43569).
+char(5,43570).
+char(1,43571).
+char(m,43572).
+char(8,43573).
+char(5,43574).
+char(3,43575).
+char(c,43576).
+char(p,43577).
+char(2,43578).
+char(5,43579).
+char(2,43580).
+char(6,43581).
+char(c,43582).
+char(m,43583).
+char(o,43584).
+char(m,43585).
+char(o,43586).
+char(p,43587).
+char(o,43588).
+char(o,43589).
+char(p,43590).
+char(o,43591).
+char(m,43592).
+char(6,43593).
+char(4,43594).
+char(8,43595).
+char(7,43596).
+char(c,43597).
+char(m,43598).
+char(o,43599).
+char(o,43600).
+char(m,43601).
+char(2,43602).
+char(7,43603).
+char(6,43604).
+char(5,43605).
+char(p,43606).
+char(o,43607).
+char(p,43608).
+char(o,43609).
+char(6,43610).
+char(7,43611).
+char(0,43612).
+char(p,43613).
+char(7,43614).
+char(5,43615).
+char(7,43616).
+char(7,43617).
+char(c,43618).
+char(m,43619).
+char(o,43620).
+char(m,43621).
+char(o,43622).
+char(o,43623).
+char(m,43624).
+char(o,43625).
+char(p,43626).
+char(o,43627).
+char(m,43628).
+char(o,43629).
+char(p,43630).
+char(o,43631).
+char(m,43632).
+char(6,43633).
+char(3,43634).
+char(5,43635).
+char(3,43636).
+char(c,43637).
+char(c,43638).
+char(p,43639).
+char(o,43640).
+char(p,43641).
+char(o,43642).
+char(p,43643).
+char(9,43644).
+char(5,43645).
+char(0,43646).
+char(2,43647).
+char(m,43648).
+char(o,43649).
+char(p,43650).
+char(7,43651).
+char(2,43652).
+char(5,43653).
+char(7,43654).
+char(c,43655).
+char(m,43656).
+char(o,43657).
+char(m,43658).
+char(o,43659).
+char(p,43660).
+char(o,43661).
+char(m,43662).
+char(5,43663).
+char(4,43664).
+char(4,43665).
+char(0,43666).
+char(c,43667).
+char(c,43668).
+char(m,43669).
+char(o,43670).
+char(m,43671).
+char(1,43672).
+char(6,43673).
+char(3,43674).
+char(6,43675).
+char(p,43676).
+char(3,43677).
+char(9,43678).
+char(6,43679).
+char(5,43680).
+char(c,43681).
+char(p,43682).
+char(4,43683).
+char(4,43684).
+char(3,43685).
+char(0,43686).
+char(c,43687).
+char(m,43688).
+char(o,43689).
+char(p,43690).
+char(2,43691).
+char(4,43692).
+char(4,43693).
+char(1,43694).
+char(m,43695).
+char(o,43696).
+char(7,43697).
+char(8,43698).
+char(2,43699).
+char(6,43700).
+char(c,43701).
+char(c,43702).
+char(m,43703).
+char(6,43704).
+char(3,43705).
+char(0,43706).
+char(7,43707).
+char(p,43708).
+char(o,43709).
+char(p,43710).
+char(o,43711).
+char(p,43712).
+char(o,43713).
+char(4,43714).
+char(7,43715).
+char(3,43716).
+char(1,43717).
+char(c,43718).
+char(c,43719).
+char(c,43720).
+char(c,43721).
+char(c,43722).
+char(c,43723).
+char(c,43724).
+char(c,43725).
+char(c,43726).
+char(p,43727).
+char(4,43728).
+char(1,43729).
+char(5,43730).
+char(4,43731).
+char(m,43732).
+char(4,43733).
+char(9,43734).
+char(7,43735).
+char(3,43736).
+char(p,43737).
+char(6,43738).
+char(4,43739).
+char(0,43740).
+char(0,43741).
+char(c,43742).
+char(c,43743).
+char(c,43744).
+char(c,43745).
+char(c,43746).
+char(c,43747).
+char(c,43748).
+char(c,43749).
+char(m,43750).
+char(9,43751).
+char(8,43752).
+char(5,43753).
+char(5,43754).
+char(c,43755).
+char(m,43756).
+char(4,43757).
+char(1,43758).
+char(2,43759).
+char(7,43760).
+char(m,43761).
+char(o,43762).
+char(p,43763).
+char(4,43764).
+char(8,43765).
+char(2,43766).
+char(7,43767).
+char(p,43768).
+char(o,43769).
+char(o,43770).
+char(p,43771).
+char(o,43772).
+char(m,43773).
+char(7,43774).
+char(1,43775).
+char(1,43776).
+char(6,43777).
+char(c,43778).
+char(c,43779).
+char(c,43780).
+char(c,43781).
+char(c,43782).
+char(p,43783).
+char(o,43784).
+char(p,43785).
+char(o,43786).
+char(p,43787).
+char(1,43788).
+char(1,43789).
+char(7,43790).
+char(0,43791).
+char(c,43792).
+char(m,43793).
+char(8,43794).
+char(1,43795).
+char(7,43796).
+char(9,43797).
+char(c,43798).
+char(c,43799).
+char(c,43800).
+char(p,43801).
+char(o,43802).
+char(m,43803).
+char(8,43804).
+char(5,43805).
+char(3,43806).
+char(9,43807).
+char(c,43808).
+char(m,43809).
+char(8,43810).
+char(0,43811).
+char(0,43812).
+char(3,43813).
+char(m,43814).
+char(9,43815).
+char(2,43816).
+char(4,43817).
+char(6,43818).
+char(c,43819).
+char(p,43820).
+char(7,43821).
+char(4,43822).
+char(9,43823).
+char(4,43824).
+char(m,43825).
+char(o,43826).
+char(p,43827).
+char(o,43828).
+char(p,43829).
+char(o,43830).
+char(p,43831).
+char(1,43832).
+char(0,43833).
+char(0,43834).
+char(6,43835).
+char(c,43836).
+char(c,43837).
+char(m,43838).
+char(3,43839).
+char(3,43840).
+char(7,43841).
+char(4,43842).
+char(c,43843).
+char(m,43844).
+char(9,43845).
+char(5,43846).
+char(5,43847).
+char(5,43848).
+char(c,43849).
+char(c,43850).
+char(m,43851).
+char(6,43852).
+char(4,43853).
+char(6,43854).
+char(6,43855).
+char(c,43856).
+char(c,43857).
+char(p,43858).
+char(o,43859).
+char(m,43860).
+char(5,43861).
+char(1,43862).
+char(9,43863).
+char(3,43864).
+char(c,43865).
+char(c,43866).
+char(p,43867).
+char(o,43868).
+char(o,43869).
+char(o,43870).
+char(p,43871).
+char(8,43872).
+char(5,43873).
+char(8,43874).
+char(5,43875).
+char(c,43876).
+char(c,43877).
+char(m,43878).
+char(2,43879).
+char(4,43880).
+char(9,43881).
+char(6,43882).
+char(c,43883).
+char(m,43884).
+char(8,43885).
+char(6,43886).
+char(1,43887).
+char(4,43888).
+char(m,43889).
+char(o,43890).
+char(7,43891).
+char(4,43892).
+char(6,43893).
+char(5,43894).
+char(c,43895).
+char(m,43896).
+char(o,43897).
+char(1,43898).
+char(8,43899).
+char(8,43900).
+char(8,43901).
+char(p,43902).
+char(4,43903).
+char(2,43904).
+char(3,43905).
+char(3,43906).
+char(c,43907).
+char(m,43908).
+char(o,43909).
+char(m,43910).
+char(o,43911).
+char(m,43912).
+char(7,43913).
+char(1,43914).
+char(6,43915).
+char(9,43916).
+char(p,43917).
+char(1,43918).
+char(5,43919).
+char(6,43920).
+char(3,43921).
+char(c,43922).
+char(p,43923).
+char(o,43924).
+char(o,43925).
+char(3,43926).
+char(8,43927).
+char(2,43928).
+char(8,43929).
+char(m,43930).
+char(8,43931).
+char(4,43932).
+char(4,43933).
+char(9,43934).
+char(m,43935).
+char(2,43936).
+char(0,43937).
+char(7,43938).
+char(p,43939).
+char(2,43940).
+char(2,43941).
+char(2,43942).
+char(6,43943).
+char(p,43944).
+char(7,43945).
+char(5,43946).
+char(1,43947).
+char(c,43948).
+char(p,43949).
+char(o,43950).
+char(1,43951).
+char(2,43952).
+char(8,43953).
+char(4,43954).
+char(c,43955).
+char(m,43956).
+char(8,43957).
+char(4,43958).
+char(9,43959).
+char(4,43960).
+char(c,43961).
+char(c,43962).
+char(c,43963).
+char(c,43964).
+char(m,43965).
+char(o,43966).
+char(m,43967).
+char(o,43968).
+char(p,43969).
+char(6,43970).
+char(4,43971).
+char(7,43972).
+char(5,43973).
+char(c,43974).
+char(m,43975).
+char(2,43976).
+char(4,43977).
+char(4,43978).
+char(c,43979).
+char(c,43980).
+char(p,43981).
+char(o,43982).
+char(p,43983).
+char(o,43984).
+char(p,43985).
+char(9,43986).
+char(1,43987).
+char(1,43988).
+char(0,43989).
+char(p,43990).
+char(4,43991).
+char(2,43992).
+char(3,43993).
+char(3,43994).
+char(p,43995).
+char(4,43996).
+char(9,43997).
+char(9,43998).
+char(c,43999).
+char(p,44000).
+char(1,44001).
+char(3,44002).
+char(5,44003).
+char(c,44004).
+char(c,44005).
+char(c,44006).
+char(p,44007).
+char(o,44008).
+char(o,44009).
+char(p,44010).
+char(4,44011).
+char(2,44012).
+char(7,44013).
+char(2,44014).
+char(c,44015).
+char(p,44016).
+char(4,44017).
+char(8,44018).
+char(7,44019).
+char(0,44020).
+char(c,44021).
+char(c,44022).
+char(c,44023).
+char(p,44024).
+char(o,44025).
+char(m,44026).
+char(o,44027).
+char(p,44028).
+char(2,44029).
+char(1,44030).
+char(3,44031).
+char(1,44032).
+char(c,44033).
+char(c,44034).
+char(m,44035).
+char(o,44036).
+char(m,44037).
+char(2,44038).
+char(3,44039).
+char(2,44040).
+char(8,44041).
+char(c,44042).
+char(m,44043).
+char(7,44044).
+char(7,44045).
+char(2,44046).
+char(1,44047).
+char(c,44048).
+char(c,44049).
+char(c,44050).
+char(m,44051).
+char(8,44052).
+char(0,44053).
+char(0,44054).
+char(2,44055).
+char(c,44056).
+char(m,44057).
+char(7,44058).
+char(7,44059).
+char(4,44060).
+char(2,44061).
+char(c,44062).
+char(c,44063).
+char(m,44064).
+char(9,44065).
+char(4,44066).
+char(3,44067).
+char(7,44068).
+char(c,44069).
+char(p,44070).
+char(6,44071).
+char(6,44072).
+char(9,44073).
+char(5,44074).
+char(m,44075).
+char(3,44076).
+char(9,44077).
+char(3,44078).
+char(7,44079).
+char(c,44080).
+char(m,44081).
+char(o,44082).
+char(o,44083).
+char(m,44084).
+char(4,44085).
+char(6,44086).
+char(6,44087).
+char(p,44088).
+char(o,44089).
+char(m,44090).
+char(1,44091).
+char(0,44092).
+char(3,44093).
+char(5,44094).
+char(m,44095).
+char(5,44096).
+char(7,44097).
+char(1,44098).
+char(0,44099).
+char(c,44100).
+char(m,44101).
+char(o,44102).
+char(p,44103).
+char(6,44104).
+char(4,44105).
+char(8,44106).
+char(1,44107).
+char(c,44108).
+char(c,44109).
+char(c,44110).
+char(p,44111).
+char(o,44112).
+char(p,44113).
+char(2,44114).
+char(2,44115).
+char(3,44116).
+char(7,44117).
+char(p,44118).
+char(1,44119).
+char(7,44120).
+char(8,44121).
+char(0,44122).
+char(c,44123).
+char(m,44124).
+char(2,44125).
+char(0,44126).
+char(8,44127).
+char(7,44128).
+char(c,44129).
+char(p,44130).
+char(o,44131).
+char(o,44132).
+char(o,44133).
+char(m,44134).
+char(5,44135).
+char(6,44136).
+char(8,44137).
+char(4,44138).
+char(c,44139).
+char(p,44140).
+char(o,44141).
+char(o,44142).
+char(p,44143).
+char(o,44144).
+char(p,44145).
+char(o,44146).
+char(p,44147).
+char(o,44148).
+char(o,44149).
+char(7,44150).
+char(7,44151).
+char(6,44152).
+char(c,44153).
+char(m,44154).
+char(9,44155).
+char(1,44156).
+char(2,44157).
+char(8,44158).
+char(m,44159).
+char(o,44160).
+char(p,44161).
+char(o,44162).
+char(m,44163).
+char(o,44164).
+char(p,44165).
+char(2,44166).
+char(0,44167).
+char(3,44168).
+char(c,44169).
+char(m,44170).
+char(o,44171).
+char(p,44172).
+char(o,44173).
+char(m,44174).
+char(4,44175).
+char(8,44176).
+char(5,44177).
+char(6,44178).
+char(c,44179).
+char(c,44180).
+char(m,44181).
+char(o,44182).
+char(2,44183).
+char(6,44184).
+char(2,44185).
+char(0,44186).
+char(c,44187).
+char(c,44188).
+char(p,44189).
+char(3,44190).
+char(2,44191).
+char(7,44192).
+char(8,44193).
+char(p,44194).
+char(o,44195).
+char(3,44196).
+char(0,44197).
+char(0,44198).
+char(5,44199).
+char(c,44200).
+char(p,44201).
+char(1,44202).
+char(4,44203).
+char(4,44204).
+char(6,44205).
+char(p,44206).
+char(8,44207).
+char(8,44208).
+char(9,44209).
+char(7,44210).
+char(c,44211).
+char(m,44212).
+char(o,44213).
+char(p,44214).
+char(o,44215).
+char(p,44216).
+char(4,44217).
+char(3,44218).
+char(9,44219).
+char(2,44220).
+char(p,44221).
+char(o,44222).
+char(7,44223).
+char(2,44224).
+char(3,44225).
+char(7,44226).
+char(c,44227).
+char(c,44228).
+char(m,44229).
+char(6,44230).
+char(7,44231).
+char(c,44232).
+char(m,44233).
+char(1,44234).
+char(4,44235).
+char(6,44236).
+char(5,44237).
+char(c,44238).
+char(m,44239).
+char(6,44240).
+char(1,44241).
+char(9,44242).
+char(1,44243).
+char(c,44244).
+char(c,44245).
+char(c,44246).
+char(m,44247).
+char(2,44248).
+char(9,44249).
+char(4,44250).
+char(p,44251).
+char(o,44252).
+char(m,44253).
+char(o,44254).
+char(o,44255).
+char(m,44256).
+char(3,44257).
+char(2,44258).
+char(2,44259).
+char(6,44260).
+char(m,44261).
+char(o,44262).
+char(p,44263).
+char(5,44264).
+char(9,44265).
+char(5,44266).
+char(4,44267).
+char(p,44268).
+char(6,44269).
+char(8,44270).
+char(3,44271).
+char(2,44272).
+char(m,44273).
+char(8,44274).
+char(1,44275).
+char(c,44276).
+char(c,44277).
+char(c,44278).
+char(m,44279).
+char(2,44280).
+char(0,44281).
+char(0,44282).
+char(3,44283).
+char(m,44284).
+char(7,44285).
+char(4,44286).
+char(8,44287).
+char(2,44288).
+char(p,44289).
+char(3,44290).
+char(0,44291).
+char(7,44292).
+char(m,44293).
+char(9,44294).
+char(7,44295).
+char(1,44296).
+char(0,44297).
+char(p,44298).
+char(o,44299).
+char(m,44300).
+char(7,44301).
+char(1,44302).
+char(6,44303).
+char(3,44304).
+char(p,44305).
+char(7,44306).
+char(7,44307).
+char(4,44308).
+char(4,44309).
+char(c,44310).
+char(m,44311).
+char(8,44312).
+char(1,44313).
+char(5,44314).
+char(4,44315).
+char(m,44316).
+char(5,44317).
+char(6,44318).
+char(1,44319).
+char(0,44320).
+char(c,44321).
+char(c,44322).
+char(c,44323).
+char(m,44324).
+char(o,44325).
+char(7,44326).
+char(6,44327).
+char(5,44328).
+char(0,44329).
+char(c,44330).
+char(m,44331).
+char(o,44332).
+char(m,44333).
+char(4,44334).
+char(2,44335).
+char(7,44336).
+char(2,44337).
+char(c,44338).
+char(p,44339).
+char(o,44340).
+char(1,44341).
+char(4,44342).
+char(1,44343).
+char(9,44344).
+char(c,44345).
+char(p,44346).
+char(o,44347).
+char(p,44348).
+char(o,44349).
+char(8,44350).
+char(1,44351).
+char(2,44352).
+char(5,44353).
+char(p,44354).
+char(o,44355).
+char(m,44356).
+char(7,44357).
+char(8,44358).
+char(1,44359).
+char(2,44360).
+char(c,44361).
+char(p,44362).
+char(o,44363).
+char(p,44364).
+char(o,44365).
+char(6,44366).
+char(5,44367).
+char(4,44368).
+char(9,44369).
+char(p,44370).
+char(1,44371).
+char(5,44372).
+char(0,44373).
+char(6,44374).
+char(c,44375).
+char(c,44376).
+char(p,44377).
+char(o,44378).
+char(m,44379).
+char(o,44380).
+char(m,44381).
+char(8,44382).
+char(0,44383).
+char(6,44384).
+char(6,44385).
+char(c,44386).
+char(m,44387).
+char(1,44388).
+char(6,44389).
+char(8,44390).
+char(4,44391).
+char(m,44392).
+char(o,44393).
+char(o,44394).
+char(p,44395).
+char(8,44396).
+char(9,44397).
+char(0,44398).
+char(8,44399).
+char(c,44400).
+char(m,44401).
+char(6,44402).
+char(1,44403).
+char(9,44404).
+char(1,44405).
+char(c,44406).
+char(m,44407).
+char(o,44408).
+char(p,44409).
+char(o,44410).
+char(p,44411).
+char(o,44412).
+char(o,44413).
+char(4,44414).
+char(3,44415).
+char(2,44416).
+char(2,44417).
+char(c,44418).
+char(c,44419).
+char(c,44420).
+char(m,44421).
+char(1,44422).
+char(7,44423).
+char(3,44424).
+char(4,44425).
+char(c,44426).
+char(c,44427).
+char(p,44428).
+char(o,44429).
+char(p,44430).
+char(o,44431).
+char(o,44432).
+char(p,44433).
+char(o,44434).
+char(m,44435).
+char(9,44436).
+char(7,44437).
+char(6,44438).
+char(9,44439).
+char(c,44440).
+char(m,44441).
+char(o,44442).
+char(p,44443).
+char(o,44444).
+char(p,44445).
+char(5,44446).
+char(5,44447).
+char(7,44448).
+char(5,44449).
+char(m,44450).
+char(o,44451).
+char(1,44452).
+char(5,44453).
+char(4,44454).
+char(c,44455).
+char(m,44456).
+char(1,44457).
+char(3,44458).
+char(4,44459).
+char(8,44460).
+char(m,44461).
+char(o,44462).
+char(m,44463).
+char(o,44464).
+char(p,44465).
+char(4,44466).
+char(3,44467).
+char(8,44468).
+char(8,44469).
+char(p,44470).
+char(o,44471).
+char(m,44472).
+char(o,44473).
+char(p,44474).
+char(6,44475).
+char(0,44476).
+char(3,44477).
+char(8,44478).
+char(c,44479).
+char(c,44480).
+char(c,44481).
+char(c,44482).
+char(m,44483).
+char(1,44484).
+char(7,44485).
+char(8,44486).
+char(5,44487).
+char(p,44488).
+char(o,44489).
+char(p,44490).
+char(o,44491).
+char(p,44492).
+char(o,44493).
+char(p,44494).
+char(o,44495).
+char(p,44496).
+char(7,44497).
+char(9,44498).
+char(0,44499).
+char(7,44500).
+char(c,44501).
+char(m,44502).
+char(o,44503).
+char(m,44504).
+char(o,44505).
+char(m,44506).
+char(o,44507).
+char(9,44508).
+char(9,44509).
+char(2,44510).
+char(5,44511).
+char(c,44512).
+char(c,44513).
+char(m,44514).
+char(2,44515).
+char(5,44516).
+char(9,44517).
+char(1,44518).
+char(c,44519).
+char(c,44520).
+char(c,44521).
+char(c,44522).
+char(m,44523).
+char(9,44524).
+char(3,44525).
+char(8,44526).
+char(p,44527).
+char(o,44528).
+char(p,44529).
+char(5,44530).
+char(4,44531).
+char(4,44532).
+char(m,44533).
+char(o,44534).
+char(p,44535).
+char(8,44536).
+char(3,44537).
+char(7,44538).
+char(5,44539).
+char(c,44540).
+char(m,44541).
+char(o,44542).
+char(2,44543).
+char(5,44544).
+char(7,44545).
+char(2,44546).
+char(c,44547).
+char(m,44548).
+char(o,44549).
+char(o,44550).
+char(m,44551).
+char(o,44552).
+char(m,44553).
+char(8,44554).
+char(5,44555).
+char(1,44556).
+char(m,44557).
+char(1,44558).
+char(1,44559).
+char(4,44560).
+char(6,44561).
+char(c,44562).
+char(c,44563).
+char(c,44564).
+char(m,44565).
+char(o,44566).
+char(o,44567).
+char(m,44568).
+char(o,44569).
+char(o,44570).
+char(3,44571).
+char(5,44572).
+char(2,44573).
+char(7,44574).
+char(c,44575).
+char(c,44576).
+char(c,44577).
+char(m,44578).
+char(8,44579).
+char(7,44580).
+char(7,44581).
+char(6,44582).
+char(c,44583).
+char(m,44584).
+char(4,44585).
+char(3,44586).
+char(7,44587).
+char(2,44588).
+char(m,44589).
+char(7,44590).
+char(6,44591).
+char(5,44592).
+char(1,44593).
+char(c,44594).
+char(c,44595).
+char(p,44596).
+char(2,44597).
+char(5,44598).
+char(5,44599).
+char(5,44600).
+char(m,44601).
+char(9,44602).
+char(3,44603).
+char(0,44604).
+char(6,44605).
+char(p,44606).
+char(5,44607).
+char(2,44608).
+char(2,44609).
+char(1,44610).
+char(c,44611).
+char(m,44612).
+char(o,44613).
+char(p,44614).
+char(o,44615).
+char(m,44616).
+char(6,44617).
+char(1,44618).
+char(2,44619).
+char(c,44620).
+char(c,44621).
+char(p,44622).
+char(o,44623).
+char(p,44624).
+char(o,44625).
+char(m,44626).
+char(o,44627).
+char(p,44628).
+char(9,44629).
+char(5,44630).
+char(8,44631).
+char(5,44632).
+char(c,44633).
+char(m,44634).
+char(o,44635).
+char(p,44636).
+char(3,44637).
+char(2,44638).
+char(6,44639).
+char(p,44640).
+char(3,44641).
+char(4,44642).
+char(9,44643).
+char(7,44644).
+char(p,44645).
+char(2,44646).
+char(8,44647).
+char(1,44648).
+char(0,44649).
+char(c,44650).
+char(p,44651).
+char(o,44652).
+char(1,44653).
+char(1,44654).
+char(3,44655).
+char(2,44656).
+char(m,44657).
+char(o,44658).
+char(m,44659).
+char(o,44660).
+char(m,44661).
+char(7,44662).
+char(6,44663).
+char(0,44664).
+char(9,44665).
+char(c,44666).
+char(c,44667).
+char(m,44668).
+char(2,44669).
+char(9,44670).
+char(9,44671).
+char(2,44672).
+char(c,44673).
+char(c,44674).
+char(m,44675).
+char(3,44676).
+char(3,44677).
+char(8,44678).
+char(5,44679).
+char(m,44680).
+char(1,44681).
+char(5,44682).
+char(5,44683).
+char(7,44684).
+char(m,44685).
+char(o,44686).
+char(p,44687).
+char(o,44688).
+char(o,44689).
+char(p,44690).
+char(6,44691).
+char(5,44692).
+char(6,44693).
+char(2,44694).
+char(c,44695).
+char(c,44696).
+char(m,44697).
+char(7,44698).
+char(3,44699).
+char(1,44700).
+char(8,44701).
+char(p,44702).
+char(6,44703).
+char(3,44704).
+char(7,44705).
+char(5,44706).
+char(m,44707).
+char(8,44708).
+char(0,44709).
+char(2,44710).
+char(1,44711).
+char(p,44712).
+char(9,44713).
+char(2,44714).
+char(8,44715).
+char(6,44716).
+char(m,44717).
+char(o,44718).
+char(m,44719).
+char(o,44720).
+char(m,44721).
+char(8,44722).
+char(5,44723).
+char(8,44724).
+char(3,44725).
+char(m,44726).
+char(o,44727).
+char(8,44728).
+char(3,44729).
+char(0,44730).
+char(0,44731).
+char(c,44732).
+char(c,44733).
+char(m,44734).
+char(3,44735).
+char(4,44736).
+char(4,44737).
+char(6,44738).
+char(m,44739).
+char(o,44740).
+char(o,44741).
+char(m,44742).
+char(o,44743).
+char(m,44744).
+char(1,44745).
+char(5,44746).
+char(9,44747).
+char(8,44748).
+char(p,44749).
+char(o,44750).
+char(p,44751).
+char(o,44752).
+char(p,44753).
+char(8,44754).
+char(8,44755).
+char(5,44756).
+char(3,44757).
+char(c,44758).
+char(m,44759).
+char(9,44760).
+char(2,44761).
+char(9,44762).
+char(p,44763).
+char(o,44764).
+char(3,44765).
+char(1,44766).
+char(7,44767).
+char(3,44768).
+char(m,44769).
+char(o,44770).
+char(m,44771).
+char(7,44772).
+char(5,44773).
+char(0,44774).
+char(6,44775).
+char(c,44776).
+char(c,44777).
+char(m,44778).
+char(o,44779).
+char(m,44780).
+char(4,44781).
+char(8,44782).
+char(4,44783).
+char(3,44784).
+char(c,44785).
+char(c,44786).
+char(c,44787).
+char(p,44788).
+char(9,44789).
+char(6,44790).
+char(9,44791).
+char(6,44792).
+char(c,44793).
+char(c,44794).
+char(c,44795).
+char(c,44796).
+char(c,44797).
+char(c,44798).
+char(c,44799).
+char(c,44800).
+char(c,44801).
+char(c,44802).
+char(p,44803).
+char(o,44804).
+char(m,44805).
+char(o,44806).
+char(o,44807).
+char(p,44808).
+char(5,44809).
+char(2,44810).
+char(1,44811).
+char(7,44812).
+char(m,44813).
+char(o,44814).
+char(7,44815).
+char(0,44816).
+char(1,44817).
+char(0,44818).
+char(m,44819).
+char(3,44820).
+char(8,44821).
+char(8,44822).
+char(9,44823).
+char(m,44824).
+char(4,44825).
+char(2,44826).
+char(7,44827).
+char(5,44828).
+char(p,44829).
+char(o,44830).
+char(m,44831).
+char(o,44832).
+char(m,44833).
+char(8,44834).
+char(7,44835).
+char(6,44836).
+char(8,44837).
+char(c,44838).
+char(c,44839).
+char(c,44840).
+char(c,44841).
+char(p,44842).
+char(o,44843).
+char(2,44844).
+char(6,44845).
+char(6,44846).
+char(4,44847).
+char(m,44848).
+char(2,44849).
+char(5,44850).
+char(5,44851).
+char(5,44852).
+char(c,44853).
+char(c,44854).
+char(c,44855).
+char(c,44856).
+char(p,44857).
+char(6,44858).
+char(8,44859).
+char(0,44860).
+char(9,44861).
+char(c,44862).
+char(c,44863).
+char(m,44864).
+char(8,44865).
+char(1,44866).
+char(6,44867).
+char(8,44868).
+char(c,44869).
+char(p,44870).
+char(1,44871).
+char(7,44872).
+char(2,44873).
+char(9,44874).
+char(c,44875).
+char(c,44876).
+char(c,44877).
+char(c,44878).
+char(m,44879).
+char(5,44880).
+char(4,44881).
+char(7,44882).
+char(4,44883).
+char(m,44884).
+char(3,44885).
+char(8,44886).
+char(5,44887).
+char(3,44888).
+char(p,44889).
+char(o,44890).
+char(p,44891).
+char(o,44892).
+char(m,44893).
+char(7,44894).
+char(5,44895).
+char(2,44896).
+char(3,44897).
+char(p,44898).
+char(o,44899).
+char(p,44900).
+char(o,44901).
+char(p,44902).
+char(4,44903).
+char(6,44904).
+char(5,44905).
+char(0,44906).
+char(c,44907).
+char(c,44908).
+char(c,44909).
+char(m,44910).
+char(o,44911).
+char(m,44912).
+char(8,44913).
+char(7,44914).
+char(4,44915).
+char(2,44916).
+char(p,44917).
+char(2,44918).
+char(2,44919).
+char(7,44920).
+char(7,44921).
+char(p,44922).
+char(o,44923).
+char(m,44924).
+char(o,44925).
+char(m,44926).
+char(o,44927).
+char(m,44928).
+char(o,44929).
+char(m,44930).
+char(o,44931).
+char(p,44932).
+char(1,44933).
+char(4,44934).
+char(9,44935).
+char(4,44936).
+char(m,44937).
+char(6,44938).
+char(4,44939).
+char(6,44940).
+char(5,44941).
+char(m,44942).
+char(o,44943).
+char(p,44944).
+char(9,44945).
+char(1,44946).
+char(8,44947).
+char(4,44948).
+char(c,44949).
+char(c,44950).
+char(c,44951).
+char(m,44952).
+char(5,44953).
+char(3,44954).
+char(7,44955).
+char(4,44956).
+char(p,44957).
+char(9,44958).
+char(4,44959).
+char(6,44960).
+char(6,44961).
+char(c,44962).
+char(c,44963).
+char(c,44964).
+char(c,44965).
+char(m,44966).
+char(o,44967).
+char(m,44968).
+char(o,44969).
+char(3,44970).
+char(7,44971).
+char(8,44972).
+char(6,44973).
+char(c,44974).
+char(p,44975).
+char(o,44976).
+char(p,44977).
+char(o,44978).
+char(p,44979).
+char(2,44980).
+char(5,44981).
+char(8,44982).
+char(6,44983).
+char(p,44984).
+char(7,44985).
+char(1,44986).
+char(0,44987).
+char(0,44988).
+char(c,44989).
+char(c,44990).
+char(p,44991).
+char(o,44992).
+char(m,44993).
+char(7,44994).
+char(5,44995).
+char(9,44996).
+char(9,44997).
+char(c,44998).
+char(c,44999).
+char(p,45000).
+char(8,45001).
+char(0,45002).
+char(7,45003).
+char(1,45004).
+char(c,45005).
+char(c,45006).
+char(c,45007).
+char(c,45008).
+char(m,45009).
+char(9,45010).
+char(4,45011).
+char(3,45012).
+char(2,45013).
+char(m,45014).
+char(4,45015).
+char(2,45016).
+char(4,45017).
+char(2,45018).
+char(m,45019).
+char(8,45020).
+char(4,45021).
+char(9,45022).
+char(p,45023).
+char(o,45024).
+char(m,45025).
+char(o,45026).
+char(m,45027).
+char(o,45028).
+char(p,45029).
+char(o,45030).
+char(3,45031).
+char(6,45032).
+char(0,45033).
+char(m,45034).
+char(2,45035).
+char(6,45036).
+char(5,45037).
+char(3,45038).
+char(c,45039).
+char(p,45040).
+char(7,45041).
+char(7,45042).
+char(9,45043).
+char(7,45044).
+char(m,45045).
+char(4,45046).
+char(6,45047).
+char(0,45048).
+char(0,45049).
+char(m,45050).
+char(o,45051).
+char(o,45052).
+char(o,45053).
+char(m,45054).
+char(o,45055).
+char(p,45056).
+char(o,45057).
+char(p,45058).
+char(8,45059).
+char(1,45060).
+char(7,45061).
+char(7,45062).
+char(p,45063).
+char(o,45064).
+char(p,45065).
+char(o,45066).
+char(p,45067).
+char(o,45068).
+char(p,45069).
+char(3,45070).
+char(6,45071).
+char(3,45072).
+char(9,45073).
+char(m,45074).
+char(1,45075).
+char(8,45076).
+char(5,45077).
+char(3,45078).
+char(c,45079).
+char(c,45080).
+char(c,45081).
+char(p,45082).
+char(4,45083).
+char(3,45084).
+char(2,45085).
+char(2,45086).
+char(m,45087).
+char(1,45088).
+char(6,45089).
+char(1,45090).
+char(2,45091).
+char(c,45092).
+char(c,45093).
+char(p,45094).
+char(3,45095).
+char(1,45096).
+char(6,45097).
+char(6,45098).
+char(m,45099).
+char(1,45100).
+char(4,45101).
+char(0,45102).
+char(5,45103).
+char(c,45104).
+char(c,45105).
+char(m,45106).
+char(o,45107).
+char(4,45108).
+char(4,45109).
+char(2,45110).
+char(3,45111).
+char(c,45112).
+char(c,45113).
+char(c,45114).
+char(c,45115).
+char(m,45116).
+char(7,45117).
+char(4,45118).
+char(8,45119).
+char(8,45120).
+char(m,45121).
+char(8,45122).
+char(1,45123).
+char(6,45124).
+char(1,45125).
+char(p,45126).
+char(o,45127).
+char(m,45128).
+char(7,45129).
+char(3,45130).
+char(5,45131).
+char(6,45132).
+char(c,45133).
+char(c,45134).
+char(c,45135).
+char(c,45136).
+char(c,45137).
+char(m,45138).
+char(4,45139).
+char(2,45140).
+char(9,45141).
+char(0,45142).
+char(c,45143).
+char(c,45144).
+char(c,45145).
+char(p,45146).
+char(o,45147).
+char(o,45148).
+char(8,45149).
+char(4,45150).
+char(5,45151).
+char(0,45152).
+char(p,45153).
+char(9,45154).
+char(2,45155).
+char(8,45156).
+char(2,45157).
+char(c,45158).
+char(c,45159).
+char(p,45160).
+char(3,45161).
+char(0,45162).
+char(6,45163).
+char(9,45164).
+char(p,45165).
+char(o,45166).
+char(o,45167).
+char(p,45168).
+char(o,45169).
+char(p,45170).
+char(o,45171).
+char(5,45172).
+char(9,45173).
+char(6,45174).
+char(9,45175).
+char(p,45176).
+char(o,45177).
+char(p,45178).
+char(o,45179).
+char(o,45180).
+char(p,45181).
+char(7,45182).
+char(7,45183).
+char(9,45184).
+char(7,45185).
+char(m,45186).
+char(9,45187).
+char(7,45188).
+char(3,45189).
+char(5,45190).
+char(p,45191).
+char(1,45192).
+char(8,45193).
+char(2,45194).
+char(5,45195).
+char(p,45196).
+char(4,45197).
+char(1,45198).
+char(3,45199).
+char(5,45200).
+char(c,45201).
+char(m,45202).
+char(o,45203).
+char(p,45204).
+char(o,45205).
+char(p,45206).
+char(o,45207).
+char(1,45208).
+char(1,45209).
+char(5,45210).
+char(5,45211).
+char(p,45212).
+char(9,45213).
+char(8,45214).
+char(2,45215).
+char(0,45216).
+char(c,45217).
+char(p,45218).
+char(o,45219).
+char(m,45220).
+char(3,45221).
+char(4,45222).
+char(0,45223).
+char(7,45224).
+char(m,45225).
+char(o,45226).
+char(o,45227).
+char(p,45228).
+char(o,45229).
+char(6,45230).
+char(4,45231).
+char(0,45232).
+char(1,45233).
+char(c,45234).
+char(p,45235).
+char(6,45236).
+char(6,45237).
+char(2,45238).
+char(0,45239).
+char(p,45240).
+char(o,45241).
+char(m,45242).
+char(9,45243).
+char(6,45244).
+char(1,45245).
+char(4,45246).
+char(c,45247).
+char(c,45248).
+char(p,45249).
+char(o,45250).
+char(9,45251).
+char(0,45252).
+char(c,45253).
+char(m,45254).
+char(4,45255).
+char(3,45256).
+char(1,45257).
+char(3,45258).
+char(c,45259).
+char(p,45260).
+char(5,45261).
+char(5,45262).
+char(8,45263).
+char(7,45264).
+char(c,45265).
+char(c,45266).
+char(p,45267).
+char(o,45268).
+char(6,45269).
+char(4,45270).
+char(6,45271).
+char(7,45272).
+char(c,45273).
+char(m,45274).
+char(o,45275).
+char(o,45276).
+char(m,45277).
+char(4,45278).
+char(7,45279).
+char(0,45280).
+char(8,45281).
+char(c,45282).
+char(m,45283).
+char(8,45284).
+char(9,45285).
+char(0,45286).
+char(9,45287).
+char(p,45288).
+char(o,45289).
+char(m,45290).
+char(o,45291).
+char(p,45292).
+char(9,45293).
+char(7,45294).
+char(5,45295).
+char(0,45296).
+char(p,45297).
+char(5,45298).
+char(3,45299).
+char(8,45300).
+char(3,45301).
+char(c,45302).
+char(c,45303).
+char(c,45304).
+char(p,45305).
+char(3,45306).
+char(5,45307).
+char(2,45308).
+char(1,45309).
+char(m,45310).
+char(o,45311).
+char(o,45312).
+char(p,45313).
+char(o,45314).
+char(m,45315).
+char(o,45316).
+char(p,45317).
+char(o,45318).
+char(m,45319).
+char(o,45320).
+char(p,45321).
+char(o,45322).
+char(o,45323).
+char(p,45324).
+char(o,45325).
+char(m,45326).
+char(4,45327).
+char(4,45328).
+char(2,45329).
+char(1,45330).
+char(c,45331).
+char(m,45332).
+char(o,45333).
+char(p,45334).
+char(o,45335).
+char(1,45336).
+char(0,45337).
+char(2,45338).
+char(6,45339).
+char(c,45340).
+char(c,45341).
+char(p,45342).
+char(o,45343).
+char(p,45344).
+char(o,45345).
+char(m,45346).
+char(o,45347).
+char(5,45348).
+char(2,45349).
+char(3,45350).
+char(5,45351).
+char(m,45352).
+char(o,45353).
+char(p,45354).
+char(1,45355).
+char(0,45356).
+char(4,45357).
+char(4,45358).
+char(c,45359).
+char(c,45360).
+char(m,45361).
+char(8,45362).
+char(3,45363).
+char(7,45364).
+char(c,45365).
+char(c,45366).
+char(c,45367).
+char(c,45368).
+char(p,45369).
+char(3,45370).
+char(7,45371).
+char(7,45372).
+char(4,45373).
+char(c,45374).
+char(m,45375).
+char(o,45376).
+char(p,45377).
+char(o,45378).
+char(m,45379).
+char(7,45380).
+char(0,45381).
+char(7,45382).
+char(0,45383).
+char(p,45384).
+char(o,45385).
+char(m,45386).
+char(o,45387).
+char(p,45388).
+char(o,45389).
+char(m,45390).
+char(7,45391).
+char(8,45392).
+char(5,45393).
+char(8,45394).
+char(c,45395).
+char(c,45396).
+char(c,45397).
+char(m,45398).
+char(o,45399).
+char(p,45400).
+char(o,45401).
+char(o,45402).
+char(p,45403).
+char(9,45404).
+char(5,45405).
+char(0,45406).
+char(6,45407).
+char(c,45408).
+char(c,45409).
+char(m,45410).
+char(o,45411).
+char(7,45412).
+char(0,45413).
+char(8,45414).
+char(3,45415).
+char(c,45416).
+char(c,45417).
+char(c,45418).
+char(m,45419).
+char(6,45420).
+char(5,45421).
+char(0,45422).
+char(6,45423).
+char(c,45424).
+char(c,45425).
+char(m,45426).
+char(o,45427).
+char(p,45428).
+char(o,45429).
+char(o,45430).
+char(m,45431).
+char(5,45432).
+char(0,45433).
+char(9,45434).
+char(8,45435).
+char(c,45436).
+char(c,45437).
+char(c,45438).
+char(m,45439).
+char(7,45440).
+char(6,45441).
+char(9,45442).
+char(2,45443).
+char(c,45444).
+char(c,45445).
+char(p,45446).
+char(o,45447).
+char(6,45448).
+char(4,45449).
+char(8,45450).
+char(3,45451).
+char(c,45452).
+char(p,45453).
+char(2,45454).
+char(5,45455).
+char(5,45456).
+char(m,45457).
+char(o,45458).
+char(p,45459).
+char(4,45460).
+char(3,45461).
+char(0,45462).
+char(4,45463).
+char(m,45464).
+char(o,45465).
+char(o,45466).
+char(m,45467).
+char(2,45468).
+char(7,45469).
+char(1,45470).
+char(6,45471).
+char(c,45472).
+char(c,45473).
+char(m,45474).
+char(4,45475).
+char(4,45476).
+char(3,45477).
+char(9,45478).
+char(p,45479).
+char(o,45480).
+char(p,45481).
+char(1,45482).
+char(9,45483).
+char(2,45484).
+char(0,45485).
+char(c,45486).
+char(c,45487).
+char(c,45488).
+char(c,45489).
+char(c,45490).
+char(p,45491).
+char(2,45492).
+char(2,45493).
+char(0,45494).
+char(8,45495).
+char(m,45496).
+char(9,45497).
+char(4,45498).
+char(5,45499).
+char(1,45500).
+char(c,45501).
+char(c,45502).
+char(p,45503).
+char(9,45504).
+char(9,45505).
+char(8,45506).
+char(9,45507).
+char(c,45508).
+char(p,45509).
+char(o,45510).
+char(1,45511).
+char(3,45512).
+char(6,45513).
+char(3,45514).
+char(c,45515).
+char(p,45516).
+char(o,45517).
+char(2,45518).
+char(3,45519).
+char(4,45520).
+char(7,45521).
+char(c,45522).
+char(m,45523).
+char(o,45524).
+char(p,45525).
+char(1,45526).
+char(5,45527).
+char(9,45528).
+char(1,45529).
+char(p,45530).
+char(9,45531).
+char(4,45532).
+char(m,45533).
+char(o,45534).
+char(m,45535).
+char(8,45536).
+char(9,45537).
+char(8,45538).
+char(7,45539).
+char(c,45540).
+char(m,45541).
+char(o,45542).
+char(1,45543).
+char(1,45544).
+char(9,45545).
+char(8,45546).
+char(c,45547).
+char(c,45548).
+char(m,45549).
+char(1,45550).
+char(0,45551).
+char(0,45552).
+char(3,45553).
+char(m,45554).
+char(8,45555).
+char(5,45556).
+char(2,45557).
+char(2,45558).
+char(m,45559).
+char(o,45560).
+char(m,45561).
+char(o,45562).
+char(m,45563).
+char(2,45564).
+char(6,45565).
+char(0,45566).
+char(8,45567).
+char(c,45568).
+char(c,45569).
+char(c,45570).
+char(m,45571).
+char(5,45572).
+char(7,45573).
+char(1,45574).
+char(5,45575).
+char(p,45576).
+char(o,45577).
+char(3,45578).
+char(9,45579).
+char(9,45580).
+char(1,45581).
+char(c,45582).
+char(c,45583).
+char(m,45584).
+char(o,45585).
+char(p,45586).
+char(5,45587).
+char(8,45588).
+char(7,45589).
+char(1,45590).
+char(p,45591).
+char(8,45592).
+char(5,45593).
+char(9,45594).
+char(4,45595).
+char(c,45596).
+char(c,45597).
+char(m,45598).
+char(o,45599).
+char(1,45600).
+char(5,45601).
+char(4,45602).
+char(8,45603).
+char(c,45604).
+char(p,45605).
+char(8,45606).
+char(8,45607).
+char(3,45608).
+char(2,45609).
+char(m,45610).
+char(3,45611).
+char(2,45612).
+char(8,45613).
+char(6,45614).
+char(c,45615).
+char(p,45616).
+char(9,45617).
+char(2,45618).
+char(1,45619).
+char(0,45620).
+char(c,45621).
+char(p,45622).
+char(4,45623).
+char(9,45624).
+char(0,45625).
+char(7,45626).
+char(m,45627).
+char(5,45628).
+char(3,45629).
+char(2,45630).
+char(c,45631).
+char(c,45632).
+char(p,45633).
+char(2,45634).
+char(9,45635).
+char(3,45636).
+char(5,45637).
+char(c,45638).
+char(c,45639).
+char(p,45640).
+char(5,45641).
+char(9,45642).
+char(9,45643).
+char(5,45644).
+char(c,45645).
+char(c,45646).
+char(c,45647).
+char(m,45648).
+char(2,45649).
+char(2,45650).
+char(5,45651).
+char(9,45652).
+char(m,45653).
+char(4,45654).
+char(1,45655).
+char(9,45656).
+char(2,45657).
+char(p,45658).
+char(6,45659).
+char(0,45660).
+char(5,45661).
+char(7,45662).
+char(c,45663).
+char(c,45664).
+char(m,45665).
+char(o,45666).
+char(p,45667).
+char(o,45668).
+char(m,45669).
+char(2,45670).
+char(8,45671).
+char(1,45672).
+char(9,45673).
+char(p,45674).
+char(o,45675).
+char(m,45676).
+char(o,45677).
+char(o,45678).
+char(p,45679).
+char(5,45680).
+char(4,45681).
+char(6,45682).
+char(5,45683).
+char(m,45684).
+char(o,45685).
+char(9,45686).
+char(0,45687).
+char(8,45688).
+char(3,45689).
+char(c,45690).
+char(p,45691).
+char(o,45692).
+char(m,45693).
+char(8,45694).
+char(9,45695).
+char(5,45696).
+char(c,45697).
+char(m,45698).
+char(2,45699).
+char(0,45700).
+char(1,45701).
+char(3,45702).
+char(m,45703).
+char(1,45704).
+char(9,45705).
+char(9,45706).
+char(p,45707).
+char(o,45708).
+char(p,45709).
+char(o,45710).
+char(m,45711).
+char(o,45712).
+char(p,45713).
+char(6,45714).
+char(2,45715).
+char(1,45716).
+char(1,45717).
+char(m,45718).
+char(o,45719).
+char(3,45720).
+char(0,45721).
+char(1,45722).
+char(4,45723).
+char(p,45724).
+char(o,45725).
+char(2,45726).
+char(6,45727).
+char(0,45728).
+char(6,45729).
+char(c,45730).
+char(p,45731).
+char(o,45732).
+char(6,45733).
+char(1,45734).
+char(5,45735).
+char(7,45736).
+char(c,45737).
+char(c,45738).
+char(m,45739).
+char(o,45740).
+char(m,45741).
+char(o,45742).
+char(p,45743).
+char(7,45744).
+char(5,45745).
+char(5,45746).
+char(1,45747).
+char(c,45748).
+char(c,45749).
+char(p,45750).
+char(o,45751).
+char(o,45752).
+char(4,45753).
+char(0,45754).
+char(0,45755).
+char(3,45756).
+char(c,45757).
+char(m,45758).
+char(6,45759).
+char(6,45760).
+char(8,45761).
+char(7,45762).
+char(m,45763).
+char(1,45764).
+char(2,45765).
+char(2,45766).
+char(5,45767).
+char(c,45768).
+char(m,45769).
+char(o,45770).
+char(1,45771).
+char(8,45772).
+char(5,45773).
+char(6,45774).
+char(p,45775).
+char(5,45776).
+char(9,45777).
+char(1,45778).
+char(6,45779).
+char(c,45780).
+char(p,45781).
+char(9,45782).
+char(7,45783).
+char(8,45784).
+char(8,45785).
+char(m,45786).
+char(6,45787).
+char(2,45788).
+char(8,45789).
+char(5,45790).
+char(p,45791).
+char(o,45792).
+char(m,45793).
+char(8,45794).
+char(9,45795).
+char(9,45796).
+char(9,45797).
+char(c,45798).
+char(c,45799).
+char(c,45800).
+char(m,45801).
+char(3,45802).
+char(4,45803).
+char(6,45804).
+char(9,45805).
+char(c,45806).
+char(p,45807).
+char(5,45808).
+char(4,45809).
+char(3,45810).
+char(3,45811).
+char(c,45812).
+char(p,45813).
+char(8,45814).
+char(4,45815).
+char(6,45816).
+char(1,45817).
+char(m,45818).
+char(4,45819).
+char(1,45820).
+char(4,45821).
+char(c,45822).
+char(m,45823).
+char(o,45824).
+char(o,45825).
+char(m,45826).
+char(o,45827).
+char(o,45828).
+char(7,45829).
+char(6,45830).
+char(4,45831).
+char(1,45832).
+char(c,45833).
+char(c,45834).
+char(c,45835).
+char(m,45836).
+char(8,45837).
+char(9,45838).
+char(9,45839).
+char(0,45840).
+char(p,45841).
+char(9,45842).
+char(2,45843).
+char(9,45844).
+char(5,45845).
+char(m,45846).
+char(2,45847).
+char(1,45848).
+char(5,45849).
+char(1,45850).
+char(m,45851).
+char(8,45852).
+char(3,45853).
+char(9,45854).
+char(5,45855).
+char(c,45856).
+char(c,45857).
+char(c,45858).
+char(c,45859).
+char(m,45860).
+char(o,45861).
+char(p,45862).
+char(5,45863).
+char(1,45864).
+char(7,45865).
+char(1,45866).
+char(m,45867).
+char(7,45868).
+char(4,45869).
+char(0,45870).
+char(6,45871).
+char(m,45872).
+char(o,45873).
+char(p,45874).
+char(7,45875).
+char(7,45876).
+char(5,45877).
+char(2,45878).
+char(m,45879).
+char(o,45880).
+char(p,45881).
+char(2,45882).
+char(3,45883).
+char(3,45884).
+char(9,45885).
+char(p,45886).
+char(o,45887).
+char(p,45888).
+char(4,45889).
+char(8,45890).
+char(5,45891).
+char(m,45892).
+char(7,45893).
+char(7,45894).
+char(4,45895).
+char(8,45896).
+char(c,45897).
+char(m,45898).
+char(3,45899).
+char(9,45900).
+char(1,45901).
+char(3,45902).
+char(c,45903).
+char(c,45904).
+char(c,45905).
+char(c,45906).
+char(c,45907).
+char(c,45908).
+char(m,45909).
+char(o,45910).
+char(m,45911).
+char(8,45912).
+char(8,45913).
+char(3,45914).
+char(9,45915).
+char(m,45916).
+char(o,45917).
+char(p,45918).
+char(o,45919).
+char(6,45920).
+char(9,45921).
+char(0,45922).
+char(m,45923).
+char(o,45924).
+char(m,45925).
+char(o,45926).
+char(p,45927).
+char(2,45928).
+char(7,45929).
+char(0,45930).
+char(9,45931).
+char(c,45932).
+char(m,45933).
+char(o,45934).
+char(p,45935).
+char(o,45936).
+char(o,45937).
+char(p,45938).
+char(o,45939).
+char(o,45940).
+char(m,45941).
+char(2,45942).
+char(2,45943).
+char(4,45944).
+char(3,45945).
+char(p,45946).
+char(2,45947).
+char(1,45948).
+char(6,45949).
+char(3,45950).
+char(p,45951).
+char(6,45952).
+char(9,45953).
+char(4,45954).
+char(2,45955).
+char(p,45956).
+char(o,45957).
+char(m,45958).
+char(o,45959).
+char(1,45960).
+char(0,45961).
+char(1,45962).
+char(5,45963).
+char(c,45964).
+char(c,45965).
+char(c,45966).
+char(c,45967).
+char(c,45968).
+char(p,45969).
+char(o,45970).
+char(1,45971).
+char(7,45972).
+char(6,45973).
+char(7,45974).
+char(c,45975).
+char(c,45976).
+char(p,45977).
+char(7,45978).
+char(3,45979).
+char(1,45980).
+char(3,45981).
+char(c,45982).
+char(p,45983).
+char(o,45984).
+char(p,45985).
+char(o,45986).
+char(m,45987).
+char(1,45988).
+char(1,45989).
+char(1,45990).
+char(1,45991).
+char(c,45992).
+char(c,45993).
+char(c,45994).
+char(p,45995).
+char(1,45996).
+char(6,45997).
+char(1,45998).
+char(1,45999).
+char(p,46000).
+char(5,46001).
+char(2,46002).
+char(8,46003).
+char(8,46004).
+char(m,46005).
+char(2,46006).
+char(8,46007).
+char(6,46008).
+char(5,46009).
+char(m,46010).
+char(7,46011).
+char(1,46012).
+char(7,46013).
+char(8,46014).
+char(m,46015).
+char(8,46016).
+char(8,46017).
+char(8,46018).
+char(5,46019).
+char(m,46020).
+char(7,46021).
+char(2,46022).
+char(8,46023).
+char(3,46024).
+char(m,46025).
+char(1,46026).
+char(2,46027).
+char(1,46028).
+char(4,46029).
+char(m,46030).
+char(o,46031).
+char(o,46032).
+char(o,46033).
+char(o,46034).
+char(o,46035).
+char(p,46036).
+char(o,46037).
+char(m,46038).
+char(o,46039).
+char(m,46040).
+char(9,46041).
+char(9,46042).
+char(5,46043).
+char(6,46044).
+char(c,46045).
+char(c,46046).
+char(c,46047).
+char(p,46048).
+char(o,46049).
+char(p,46050).
+char(1,46051).
+char(1,46052).
+char(p,46053).
+char(o,46054).
+char(o,46055).
+char(o,46056).
+char(m,46057).
+char(o,46058).
+char(5,46059).
+char(3,46060).
+char(2,46061).
+char(6,46062).
+char(p,46063).
+char(o,46064).
+char(p,46065).
+char(3,46066).
+char(5,46067).
+char(0,46068).
+char(5,46069).
+char(p,46070).
+char(5,46071).
+char(4,46072).
+char(3,46073).
+char(4,46074).
+char(c,46075).
+char(p,46076).
+char(2,46077).
+char(5,46078).
+char(0,46079).
+char(8,46080).
+char(c,46081).
+char(c,46082).
+char(c,46083).
+char(c,46084).
+char(c,46085).
+char(c,46086).
+char(c,46087).
+char(m,46088).
+char(o,46089).
+char(m,46090).
+char(o,46091).
+char(p,46092).
+char(5,46093).
+char(4,46094).
+char(0,46095).
+char(6,46096).
+char(p,46097).
+char(9,46098).
+char(1,46099).
+char(3,46100).
+char(4,46101).
+char(m,46102).
+char(o,46103).
+char(m,46104).
+char(1,46105).
+char(8,46106).
+char(4,46107).
+char(1,46108).
+char(c,46109).
+char(c,46110).
+char(m,46111).
+char(4,46112).
+char(4,46113).
+char(9,46114).
+char(8,46115).
+char(p,46116).
+char(o,46117).
+char(o,46118).
+char(p,46119).
+char(o,46120).
+char(p,46121).
+char(o,46122).
+char(p,46123).
+char(5,46124).
+char(1,46125).
+char(9,46126).
+char(8,46127).
+char(m,46128).
+char(9,46129).
+char(5,46130).
+char(8,46131).
+char(4,46132).
+char(c,46133).
+char(c,46134).
+char(c,46135).
+char(c,46136).
+char(m,46137).
+char(4,46138).
+char(7,46139).
+char(2,46140).
+char(4,46141).
+char(m,46142).
+char(o,46143).
+char(p,46144).
+char(6,46145).
+char(2,46146).
+char(3,46147).
+char(4,46148).
+char(c,46149).
+char(p,46150).
+char(o,46151).
+char(o,46152).
+char(m,46153).
+char(5,46154).
+char(9,46155).
+char(8,46156).
+char(5,46157).
+char(c,46158).
+char(p,46159).
+char(2,46160).
+char(7,46161).
+char(1,46162).
+char(2,46163).
+char(c,46164).
+char(p,46165).
+char(o,46166).
+char(m,46167).
+char(o,46168).
+char(p,46169).
+char(5,46170).
+char(7,46171).
+char(0,46172).
+char(4,46173).
+char(c,46174).
+char(m,46175).
+char(o,46176).
+char(o,46177).
+char(m,46178).
+char(6,46179).
+char(1,46180).
+char(6,46181).
+char(1,46182).
+char(m,46183).
+char(4,46184).
+char(8,46185).
+char(9,46186).
+char(4,46187).
+char(m,46188).
+char(2,46189).
+char(8,46190).
+char(1,46191).
+char(3,46192).
+char(m,46193).
+char(3,46194).
+char(2,46195).
+char(1,46196).
+char(0,46197).
+char(m,46198).
+char(o,46199).
+char(p,46200).
+char(o,46201).
+char(p,46202).
+char(o,46203).
+char(9,46204).
+char(2,46205).
+char(5,46206).
+char(p,46207).
+char(o,46208).
+char(m,46209).
+char(o,46210).
+char(o,46211).
+char(p,46212).
+char(o,46213).
+char(p,46214).
+char(9,46215).
+char(7,46216).
+char(0,46217).
+char(3,46218).
+char(m,46219).
+char(2,46220).
+char(4,46221).
+char(8,46222).
+char(3,46223).
+char(c,46224).
+char(c,46225).
+char(c,46226).
+char(p,46227).
+char(9,46228).
+char(8,46229).
+char(1,46230).
+char(m,46231).
+char(o,46232).
+char(o,46233).
+char(1,46234).
+char(0,46235).
+char(4,46236).
+char(1,46237).
+char(m,46238).
+char(7,46239).
+char(7,46240).
+char(3,46241).
+char(1,46242).
+char(c,46243).
+char(c,46244).
+char(c,46245).
+char(m,46246).
+char(o,46247).
+char(p,46248).
+char(7,46249).
+char(8,46250).
+char(0,46251).
+char(7,46252).
+char(m,46253).
+char(o,46254).
+char(p,46255).
+char(4,46256).
+char(9,46257).
+char(1,46258).
+char(6,46259).
+char(m,46260).
+char(o,46261).
+char(p,46262).
+char(2,46263).
+char(8,46264).
+char(8,46265).
+char(7,46266).
+char(c,46267).
+char(m,46268).
+char(o,46269).
+char(m,46270).
+char(6,46271).
+char(5,46272).
+char(3,46273).
+char(4,46274).
+char(c,46275).
+char(c,46276).
+char(p,46277).
+char(2,46278).
+char(5,46279).
+char(6,46280).
+char(m,46281).
+char(o,46282).
+char(8,46283).
+char(7,46284).
+char(1,46285).
+char(0,46286).
+char(m,46287).
+char(2,46288).
+char(9,46289).
+char(1,46290).
+char(5,46291).
+char(c,46292).
+char(c,46293).
+char(c,46294).
+char(c,46295).
+char(m,46296).
+char(5,46297).
+char(8,46298).
+char(9,46299).
+char(0,46300).
+char(p,46301).
+char(o,46302).
+char(m,46303).
+char(o,46304).
+char(p,46305).
+char(o,46306).
+char(3,46307).
+char(7,46308).
+char(3,46309).
+char(3,46310).
+char(m,46311).
+char(o,46312).
+char(m,46313).
+char(1,46314).
+char(9,46315).
+char(3,46316).
+char(4,46317).
+char(m,46318).
+char(4,46319).
+char(5,46320).
+char(2,46321).
+char(3,46322).
+char(c,46323).
+char(p,46324).
+char(1,46325).
+char(9,46326).
+char(8,46327).
+char(7,46328).
+char(p,46329).
+char(o,46330).
+char(p,46331).
+char(4,46332).
+char(7,46333).
+char(1,46334).
+char(c,46335).
+char(m,46336).
+char(o,46337).
+char(m,46338).
+char(1,46339).
+char(3,46340).
+char(m,46341).
+char(1,46342).
+char(8,46343).
+char(6,46344).
+char(7,46345).
+char(c,46346).
+char(c,46347).
+char(c,46348).
+char(m,46349).
+char(2,46350).
+char(9,46351).
+char(5,46352).
+char(1,46353).
+char(c,46354).
+char(p,46355).
+char(9,46356).
+char(3,46357).
+char(5,46358).
+char(8,46359).
+char(c,46360).
+char(c,46361).
+char(c,46362).
+char(c,46363).
+char(c,46364).
+char(c,46365).
+char(m,46366).
+char(3,46367).
+char(9,46368).
+char(9,46369).
+char(4,46370).
+char(c,46371).
+char(p,46372).
+char(7,46373).
+char(1,46374).
+char(8,46375).
+char(8,46376).
+char(p,46377).
+char(1,46378).
+char(9,46379).
+char(2,46380).
+char(2,46381).
+char(c,46382).
+char(c,46383).
+char(c,46384).
+char(m,46385).
+char(3,46386).
+char(3,46387).
+char(6,46388).
+char(3,46389).
+char(p,46390).
+char(2,46391).
+char(6,46392).
+char(7,46393).
+char(0,46394).
+char(m,46395).
+char(o,46396).
+char(p,46397).
+char(2,46398).
+char(4,46399).
+char(0,46400).
+char(4,46401).
+char(c,46402).
+char(m,46403).
+char(9,46404).
+char(8,46405).
+char(1,46406).
+char(9,46407).
+char(p,46408).
+char(o,46409).
+char(p,46410).
+char(9,46411).
+char(8,46412).
+char(3,46413).
+char(7,46414).
+char(c,46415).
+char(c,46416).
+char(c,46417).
+char(c,46418).
+char(p,46419).
+char(4,46420).
+char(0,46421).
+char(3,46422).
+char(7,46423).
+char(c,46424).
+char(c,46425).
+char(c,46426).
+char(c,46427).
+char(m,46428).
+char(2,46429).
+char(8,46430).
+char(1,46431).
+char(3,46432).
+char(c,46433).
+char(p,46434).
+char(o,46435).
+char(m,46436).
+char(o,46437).
+char(o,46438).
+char(p,46439).
+char(5,46440).
+char(8,46441).
+char(6,46442).
+char(p,46443).
+char(o,46444).
+char(m,46445).
+char(1,46446).
+char(7,46447).
+char(1,46448).
+char(p,46449).
+char(3,46450).
+char(2,46451).
+char(4,46452).
+char(6,46453).
+char(c,46454).
+char(c,46455).
+char(c,46456).
+char(c,46457).
+char(c,46458).
+char(m,46459).
+char(9,46460).
+char(7,46461).
+char(2,46462).
+char(6,46463).
+char(m,46464).
+char(o,46465).
+char(p,46466).
+char(8,46467).
+char(7,46468).
+char(4,46469).
+char(3,46470).
+char(c,46471).
+char(p,46472).
+char(o,46473).
+char(p,46474).
+char(2,46475).
+char(8,46476).
+char(0,46477).
+char(1,46478).
+char(p,46479).
+char(o,46480).
+char(9,46481).
+char(3,46482).
+char(0,46483).
+char(3,46484).
+char(c,46485).
+char(m,46486).
+char(5,46487).
+char(4,46488).
+char(1,46489).
+char(3,46490).
+char(p,46491).
+char(o,46492).
+char(m,46493).
+char(7,46494).
+char(1,46495).
+char(9,46496).
+char(8,46497).
+char(c,46498).
+char(c,46499).
+char(p,46500).
+char(o,46501).
+char(p,46502).
+char(8,46503).
+char(8,46504).
+char(6,46505).
+char(1,46506).
+char(c,46507).
+char(c,46508).
+char(p,46509).
+char(o,46510).
+char(p,46511).
+char(9,46512).
+char(0,46513).
+char(6,46514).
+char(9,46515).
+char(p,46516).
+char(o,46517).
+char(3,46518).
+char(0,46519).
+char(3,46520).
+char(4,46521).
+char(m,46522).
+char(o,46523).
+char(m,46524).
+char(o,46525).
+char(o,46526).
+char(p,46527).
+char(o,46528).
+char(2,46529).
+char(0,46530).
+char(3,46531).
+char(2,46532).
+char(c,46533).
+char(p,46534).
+char(o,46535).
+char(p,46536).
+char(o,46537).
+char(p,46538).
+char(9,46539).
+char(1,46540).
+char(7,46541).
+char(c,46542).
+char(c,46543).
+char(c,46544).
+char(c,46545).
+char(m,46546).
+char(5,46547).
+char(7,46548).
+char(7,46549).
+char(6,46550).
+char(c,46551).
+char(m,46552).
+char(o,46553).
+char(p,46554).
+char(1,46555).
+char(1,46556).
+char(7,46557).
+char(8,46558).
+char(c,46559).
+char(c,46560).
+char(c,46561).
+char(c,46562).
+char(p,46563).
+char(o,46564).
+char(1,46565).
+char(2,46566).
+char(5,46567).
+char(1,46568).
+char(c,46569).
+char(m,46570).
+char(8,46571).
+char(5,46572).
+char(9,46573).
+char(7,46574).
+char(m,46575).
+char(2,46576).
+char(8,46577).
+char(9,46578).
+char(3,46579).
+char(p,46580).
+char(1,46581).
+char(9,46582).
+char(m,46583).
+char(3,46584).
+char(8,46585).
+char(4,46586).
+char(1,46587).
+char(m,46588).
+char(o,46589).
+char(p,46590).
+char(o,46591).
+char(p,46592).
+char(o,46593).
+char(p,46594).
+char(5,46595).
+char(5,46596).
+char(5,46597).
+char(7,46598).
+char(p,46599).
+char(o,46600).
+char(p,46601).
+char(o,46602).
+char(m,46603).
+char(2,46604).
+char(5,46605).
+char(2,46606).
+char(9,46607).
+char(p,46608).
+char(o,46609).
+char(p,46610).
+char(2,46611).
+char(8,46612).
+char(3,46613).
+char(8,46614).
+char(c,46615).
+char(c,46616).
+char(c,46617).
+char(c,46618).
+char(c,46619).
+char(c,46620).
+char(c,46621).
+char(p,46622).
+char(8,46623).
+char(7,46624).
+char(4,46625).
+char(6,46626).
+char(p,46627).
+char(o,46628).
+char(m,46629).
+char(7,46630).
+char(4,46631).
+char(2,46632).
+char(6,46633).
+char(p,46634).
+char(o,46635).
+char(m,46636).
+char(o,46637).
+char(m,46638).
+char(2,46639).
+char(9,46640).
+char(9,46641).
+char(6,46642).
+char(m,46643).
+char(o,46644).
+char(o,46645).
+char(m,46646).
+char(o,46647).
+char(o,46648).
+char(m,46649).
+char(8,46650).
+char(9,46651).
+char(0,46652).
+char(0,46653).
+char(c,46654).
+char(c,46655).
+char(p,46656).
+char(o,46657).
+char(m,46658).
+char(o,46659).
+char(p,46660).
+char(4,46661).
+char(1,46662).
+char(8,46663).
+char(8,46664).
+char(p,46665).
+char(8,46666).
+char(4,46667).
+char(7,46668).
+char(0,46669).
+char(m,46670).
+char(8,46671).
+char(9,46672).
+char(9,46673).
+char(p,46674).
+char(3,46675).
+char(7,46676).
+char(4,46677).
+char(3,46678).
+char(c,46679).
+char(m,46680).
+char(o,46681).
+char(m,46682).
+char(o,46683).
+char(2,46684).
+char(8,46685).
+char(4,46686).
+char(7,46687).
+char(m,46688).
+char(8,46689).
+char(7,46690).
+char(5,46691).
+char(9,46692).
+char(p,46693).
+char(2,46694).
+char(8,46695).
+char(3,46696).
+char(7,46697).
+char(c,46698).
+char(p,46699).
+char(o,46700).
+char(m,46701).
+char(9,46702).
+char(0,46703).
+char(0,46704).
+char(2,46705).
+char(c,46706).
+char(c,46707).
+char(p,46708).
+char(5,46709).
+char(8,46710).
+char(7,46711).
+char(0,46712).
+char(m,46713).
+char(7,46714).
+char(4,46715).
+char(9,46716).
+char(c,46717).
+char(c,46718).
+char(p,46719).
+char(o,46720).
+char(m,46721).
+char(5,46722).
+char(3,46723).
+char(5,46724).
+char(9,46725).
+char(p,46726).
+char(2,46727).
+char(3,46728).
+char(1,46729).
+char(3,46730).
+char(c,46731).
+char(p,46732).
+char(o,46733).
+char(m,46734).
+char(9,46735).
+char(3,46736).
+char(4,46737).
+char(m,46738).
+char(o,46739).
+char(8,46740).
+char(4,46741).
+char(1,46742).
+char(p,46743).
+char(9,46744).
+char(3,46745).
+char(1,46746).
+char(4,46747).
+char(c,46748).
+char(p,46749).
+char(6,46750).
+char(1,46751).
+char(4,46752).
+char(6,46753).
+char(c,46754).
+char(c,46755).
+char(c,46756).
+char(c,46757).
+char(m,46758).
+char(7,46759).
+char(3,46760).
+char(6,46761).
+char(1,46762).
+char(p,46763).
+char(o,46764).
+char(p,46765).
+char(5,46766).
+char(5,46767).
+char(8,46768).
+char(8,46769).
+char(p,46770).
+char(o,46771).
+char(2,46772).
+char(0,46773).
+char(8,46774).
+char(2,46775).
+char(c,46776).
+char(m,46777).
+char(o,46778).
+char(m,46779).
+char(o,46780).
+char(o,46781).
+char(m,46782).
+char(8,46783).
+char(1,46784).
+char(5,46785).
+char(6,46786).
+char(c,46787).
+char(c,46788).
+char(c,46789).
+char(c,46790).
+char(c,46791).
+char(c,46792).
+char(c,46793).
+char(c,46794).
+char(m,46795).
+char(8,46796).
+char(2,46797).
+char(0,46798).
+char(3,46799).
+char(c,46800).
+char(c,46801).
+char(c,46802).
+char(p,46803).
+char(1,46804).
+char(6,46805).
+char(6,46806).
+char(0,46807).
+char(c,46808).
+char(m,46809).
+char(o,46810).
+char(p,46811).
+char(o,46812).
+char(o,46813).
+char(m,46814).
+char(o,46815).
+char(1,46816).
+char(0,46817).
+char(5,46818).
+char(4,46819).
+char(c,46820).
+char(m,46821).
+char(o,46822).
+char(o,46823).
+char(p,46824).
+char(1,46825).
+char(2,46826).
+char(4,46827).
+char(2,46828).
+char(c,46829).
+char(p,46830).
+char(1,46831).
+char(3,46832).
+char(8,46833).
+char(1,46834).
+char(m,46835).
+char(4,46836).
+char(3,46837).
+char(2,46838).
+char(5,46839).
+char(c,46840).
+char(c,46841).
+char(c,46842).
+char(p,46843).
+char(3,46844).
+char(0,46845).
+char(2,46846).
+char(0,46847).
+char(m,46848).
+char(o,46849).
+char(5,46850).
+char(7,46851).
+char(5,46852).
+char(2,46853).
+char(c,46854).
+char(m,46855).
+char(7,46856).
+char(5,46857).
+char(0,46858).
+char(c,46859).
+char(c,46860).
+char(m,46861).
+char(o,46862).
+char(m,46863).
+char(o,46864).
+char(8,46865).
+char(0,46866).
+char(5,46867).
+char(0,46868).
+char(p,46869).
+char(o,46870).
+char(p,46871).
+char(o,46872).
+char(p,46873).
+char(7,46874).
+char(4,46875).
+char(0,46876).
+char(c,46877).
+char(c,46878).
+char(c,46879).
+char(m,46880).
+char(8,46881).
+char(9,46882).
+char(8,46883).
+char(1,46884).
+char(m,46885).
+char(5,46886).
+char(0,46887).
+char(5,46888).
+char(c,46889).
+char(c,46890).
+char(p,46891).
+char(o,46892).
+char(6,46893).
+char(0,46894).
+char(8,46895).
+char(8,46896).
+char(c,46897).
+char(p,46898).
+char(o,46899).
+char(p,46900).
+char(o,46901).
+char(m,46902).
+char(8,46903).
+char(2,46904).
+char(1,46905).
+char(8,46906).
+char(c,46907).
+char(p,46908).
+char(3,46909).
+char(0,46910).
+char(2,46911).
+char(6,46912).
+char(c,46913).
+char(c,46914).
+char(m,46915).
+char(5,46916).
+char(8,46917).
+char(9,46918).
+char(m,46919).
+char(2,46920).
+char(6,46921).
+char(2,46922).
+char(3,46923).
+char(c,46924).
+char(p,46925).
+char(o,46926).
+char(1,46927).
+char(3,46928).
+char(1,46929).
+char(7,46930).
+char(c,46931).
+char(m,46932).
+char(o,46933).
+char(o,46934).
+char(m,46935).
+char(o,46936).
+char(p,46937).
+char(o,46938).
+char(p,46939).
+char(o,46940).
+char(m,46941).
+char(o,46942).
+char(o,46943).
+char(o,46944).
+char(m,46945).
+char(2,46946).
+char(2,46947).
+char(1,46948).
+char(6,46949).
+char(m,46950).
+char(o,46951).
+char(o,46952).
+char(p,46953).
+char(8,46954).
+char(3,46955).
+char(1,46956).
+char(6,46957).
+char(c,46958).
+char(c,46959).
+char(p,46960).
+char(1,46961).
+char(0,46962).
+char(7,46963).
+char(4,46964).
+char(m,46965).
+char(o,46966).
+char(p,46967).
+char(o,46968).
+char(p,46969).
+char(8,46970).
+char(6,46971).
+char(7,46972).
+char(9,46973).
+char(p,46974).
+char(o,46975).
+char(m,46976).
+char(o,46977).
+char(p,46978).
+char(7,46979).
+char(2,46980).
+char(7,46981).
+char(p,46982).
+char(3,46983).
+char(3,46984).
+char(9,46985).
+char(1,46986).
+char(c,46987).
+char(p,46988).
+char(2,46989).
+char(3,46990).
+char(2,46991).
+char(6,46992).
+char(p,46993).
+char(1,46994).
+char(8,46995).
+char(2,46996).
+char(p,46997).
+char(1,46998).
+char(0,46999).
+char(5,47000).
+char(4,47001).
+char(c,47002).
+char(c,47003).
+char(c,47004).
+char(m,47005).
+char(3,47006).
+char(9,47007).
+char(9,47008).
+char(7,47009).
+char(p,47010).
+char(5,47011).
+char(8,47012).
+char(4,47013).
+char(c,47014).
+char(p,47015).
+char(o,47016).
+char(m,47017).
+char(9,47018).
+char(1,47019).
+char(6,47020).
+char(c,47021).
+char(c,47022).
+char(p,47023).
+char(o,47024).
+char(p,47025).
+char(2,47026).
+char(1,47027).
+char(0,47028).
+char(2,47029).
+char(c,47030).
+char(m,47031).
+char(o,47032).
+char(p,47033).
+char(9,47034).
+char(2,47035).
+char(2,47036).
+char(m,47037).
+char(7,47038).
+char(2,47039).
+char(8,47040).
+char(3,47041).
+char(c,47042).
+char(m,47043).
+char(8,47044).
+char(4,47045).
+char(2,47046).
+char(1,47047).
+char(c,47048).
+char(c,47049).
+char(c,47050).
+char(c,47051).
+char(c,47052).
+char(c,47053).
+char(m,47054).
+char(o,47055).
+char(o,47056).
+char(m,47057).
+char(o,47058).
+char(p,47059).
+char(1,47060).
+char(4,47061).
+char(4,47062).
+char(3,47063).
+char(c,47064).
+char(p,47065).
+char(o,47066).
+char(p,47067).
+char(3,47068).
+char(2,47069).
+char(2,47070).
+char(2,47071).
+char(p,47072).
+char(3,47073).
+char(9,47074).
+char(4,47075).
+char(1,47076).
+char(c,47077).
+char(c,47078).
+char(c,47079).
+char(c,47080).
+char(p,47081).
+char(5,47082).
+char(6,47083).
+char(0,47084).
+char(4,47085).
+char(p,47086).
+char(o,47087).
+char(m,47088).
+char(o,47089).
+char(p,47090).
+char(4,47091).
+char(3,47092).
+char(5,47093).
+char(0,47094).
+char(m,47095).
+char(o,47096).
+char(p,47097).
+char(o,47098).
+char(p,47099).
+char(2,47100).
+char(3,47101).
+char(8,47102).
+char(5,47103).
+char(m,47104).
+char(o,47105).
+char(5,47106).
+char(7,47107).
+char(8,47108).
+char(8,47109).
+char(c,47110).
+char(c,47111).
+char(p,47112).
+char(2,47113).
+char(3,47114).
+char(1,47115).
+char(8,47116).
+char(m,47117).
+char(o,47118).
+char(m,47119).
+char(o,47120).
+char(m,47121).
+char(o,47122).
+char(o,47123).
+char(p,47124).
+char(8,47125).
+char(8,47126).
+char(0,47127).
+char(6,47128).
+char(c,47129).
+char(c,47130).
+char(c,47131).
+char(m,47132).
+char(o,47133).
+char(p,47134).
+char(1,47135).
+char(4,47136).
+char(9,47137).
+char(1,47138).
+char(c,47139).
+char(c,47140).
+char(c,47141).
+char(c,47142).
+char(m,47143).
+char(o,47144).
+char(5,47145).
+char(4,47146).
+char(3,47147).
+char(7,47148).
+char(c,47149).
+char(p,47150).
+char(1,47151).
+char(8,47152).
+char(8,47153).
+char(0,47154).
+char(c,47155).
+char(m,47156).
+char(o,47157).
+char(p,47158).
+char(5,47159).
+char(4,47160).
+char(1,47161).
+char(8,47162).
+char(c,47163).
+char(p,47164).
+char(o,47165).
+char(p,47166).
+char(o,47167).
+char(o,47168).
+char(1,47169).
+char(9,47170).
+char(6,47171).
+char(5,47172).
+char(p,47173).
+char(o,47174).
+char(p,47175).
+char(5,47176).
+char(6,47177).
+char(0,47178).
+char(9,47179).
+char(m,47180).
+char(6,47181).
+char(6,47182).
+char(3,47183).
+char(4,47184).
+char(m,47185).
+char(4,47186).
+char(6,47187).
+char(7,47188).
+char(9,47189).
+char(c,47190).
+char(m,47191).
+char(o,47192).
+char(p,47193).
+char(o,47194).
+char(m,47195).
+char(1,47196).
+char(6,47197).
+char(0,47198).
+char(6,47199).
+char(c,47200).
+char(p,47201).
+char(5,47202).
+char(4,47203).
+char(3,47204).
+char(2,47205).
+char(m,47206).
+char(1,47207).
+char(4,47208).
+char(6,47209).
+char(4,47210).
+char(m,47211).
+char(o,47212).
+char(o,47213).
+char(m,47214).
+char(9,47215).
+char(8,47216).
+char(3,47217).
+char(c,47218).
+char(c,47219).
+char(c,47220).
+char(m,47221).
+char(8,47222).
+char(9,47223).
+char(4,47224).
+char(6,47225).
+char(c,47226).
+char(c,47227).
+char(c,47228).
+char(p,47229).
+char(o,47230).
+char(p,47231).
+char(7,47232).
+char(7,47233).
+char(5,47234).
+char(4,47235).
+char(c,47236).
+char(c,47237).
+char(p,47238).
+char(o,47239).
+char(p,47240).
+char(7,47241).
+char(9,47242).
+char(4,47243).
+char(9,47244).
+char(p,47245).
+char(o,47246).
+char(m,47247).
+char(4,47248).
+char(5,47249).
+char(5,47250).
+char(8,47251).
+char(p,47252).
+char(o,47253).
+char(p,47254).
+char(o,47255).
+char(3,47256).
+char(8,47257).
+char(0,47258).
+char(5,47259).
+char(c,47260).
+char(c,47261).
+char(c,47262).
+char(p,47263).
+char(o,47264).
+char(m,47265).
+char(4,47266).
+char(9,47267).
+char(7,47268).
+char(2,47269).
+char(p,47270).
+char(o,47271).
+char(m,47272).
+char(9,47273).
+char(3,47274).
+char(4,47275).
+char(3,47276).
+char(p,47277).
+char(o,47278).
+char(m,47279).
+char(o,47280).
+char(m,47281).
+char(8,47282).
+char(7,47283).
+char(8,47284).
+char(0,47285).
+char(m,47286).
+char(6,47287).
+char(9,47288).
+char(8,47289).
+char(3,47290).
+char(p,47291).
+char(9,47292).
+char(3,47293).
+char(7,47294).
+char(c,47295).
+char(c,47296).
+char(c,47297).
+char(m,47298).
+char(4,47299).
+char(9,47300).
+char(9,47301).
+char(p,47302).
+char(4,47303).
+char(4,47304).
+char(2,47305).
+char(3,47306).
+char(m,47307).
+char(3,47308).
+char(9,47309).
+char(4,47310).
+char(8,47311).
+char(c,47312).
+char(p,47313).
+char(6,47314).
+char(8,47315).
+char(0,47316).
+char(3,47317).
+char(c,47318).
+char(m,47319).
+char(4,47320).
+char(7,47321).
+char(7,47322).
+char(9,47323).
+char(c,47324).
+char(m,47325).
+char(7,47326).
+char(5,47327).
+char(5,47328).
+char(3,47329).
+char(c,47330).
+char(c,47331).
+char(c,47332).
+char(c,47333).
+char(c,47334).
+char(m,47335).
+char(o,47336).
+char(m,47337).
+char(1,47338).
+char(3,47339).
+char(3,47340).
+char(1,47341).
+char(p,47342).
+char(o,47343).
+char(p,47344).
+char(8,47345).
+char(1,47346).
+char(6,47347).
+char(8,47348).
+char(m,47349).
+char(7,47350).
+char(3,47351).
+char(1,47352).
+char(7,47353).
+char(m,47354).
+char(1,47355).
+char(0,47356).
+char(5,47357).
+char(7,47358).
+char(c,47359).
+char(p,47360).
+char(o,47361).
+char(o,47362).
+char(m,47363).
+char(o,47364).
+char(p,47365).
+char(o,47366).
+char(m,47367).
+char(o,47368).
+char(7,47369).
+char(7,47370).
+char(6,47371).
+char(0,47372).
+char(c,47373).
+char(c,47374).
+char(m,47375).
+char(7,47376).
+char(9,47377).
+char(4,47378).
+char(5,47379).
+char(c,47380).
+char(c,47381).
+char(m,47382).
+char(2,47383).
+char(4,47384).
+char(7,47385).
+char(1,47386).
+char(m,47387).
+char(o,47388).
+char(p,47389).
+char(o,47390).
+char(6,47391).
+char(9,47392).
+char(3,47393).
+char(9,47394).
+char(p,47395).
+char(1,47396).
+char(9,47397).
+char(6,47398).
+char(6,47399).
+char(m,47400).
+char(1,47401).
+char(1,47402).
+char(1,47403).
+char(3,47404).
+char(c,47405).
+char(c,47406).
+char(p,47407).
+char(o,47408).
+char(m,47409).
+char(o,47410).
+char(p,47411).
+char(5,47412).
+char(6,47413).
+char(7,47414).
+char(3,47415).
+char(m,47416).
+char(o,47417).
+char(p,47418).
+char(7,47419).
+char(3,47420).
+char(9,47421).
+char(0,47422).
+char(c,47423).
+char(c,47424).
+char(p,47425).
+char(3,47426).
+char(3,47427).
+char(8,47428).
+char(5,47429).
+char(c,47430).
+char(m,47431).
+char(o,47432).
+char(p,47433).
+char(2,47434).
+char(0,47435).
+char(8,47436).
+char(6,47437).
+char(m,47438).
+char(7,47439).
+char(2,47440).
+char(0,47441).
+char(5,47442).
+char(c,47443).
+char(m,47444).
+char(o,47445).
+char(m,47446).
+char(o,47447).
+char(m,47448).
+char(5,47449).
+char(5,47450).
+char(3,47451).
+char(4,47452).
+char(p,47453).
+char(1,47454).
+char(6,47455).
+char(5,47456).
+char(0,47457).
+char(p,47458).
+char(3,47459).
+char(4,47460).
+char(0,47461).
+char(2,47462).
+char(p,47463).
+char(o,47464).
+char(m,47465).
+char(2,47466).
+char(1,47467).
+char(8,47468).
+char(1,47469).
+char(c,47470).
+char(m,47471).
+char(o,47472).
+char(5,47473).
+char(8,47474).
+char(3,47475).
+char(5,47476).
+char(c,47477).
+char(c,47478).
+char(c,47479).
+char(c,47480).
+char(p,47481).
+char(9,47482).
+char(8,47483).
+char(0,47484).
+char(3,47485).
+char(c,47486).
+char(m,47487).
+char(o,47488).
+char(m,47489).
+char(o,47490).
+char(p,47491).
+char(o,47492).
+char(p,47493).
+char(o,47494).
+char(p,47495).
+char(8,47496).
+char(0,47497).
+char(2,47498).
+char(p,47499).
+char(6,47500).
+char(4,47501).
+char(2,47502).
+char(5,47503).
+char(m,47504).
+char(o,47505).
+char(o,47506).
+char(p,47507).
+char(o,47508).
+char(5,47509).
+char(9,47510).
+char(9,47511).
+char(6,47512).
+char(m,47513).
+char(o,47514).
+char(p,47515).
+char(1,47516).
+char(9,47517).
+char(6,47518).
+char(1,47519).
+char(c,47520).
+char(m,47521).
+char(o,47522).
+char(m,47523).
+char(1,47524).
+char(1,47525).
+char(9,47526).
+char(3,47527).
+char(p,47528).
+char(2,47529).
+char(7,47530).
+char(1,47531).
+char(3,47532).
+char(c,47533).
+char(c,47534).
+char(c,47535).
+char(c,47536).
+char(p,47537).
+char(5,47538).
+char(7,47539).
+char(7,47540).
+char(0,47541).
+char(p,47542).
+char(o,47543).
+char(5,47544).
+char(6,47545).
+char(9,47546).
+char(2,47547).
+char(p,47548).
+char(1,47549).
+char(8,47550).
+char(3,47551).
+char(c,47552).
+char(c,47553).
+char(p,47554).
+char(9,47555).
+char(7,47556).
+char(3,47557).
+char(8,47558).
+char(m,47559).
+char(6,47560).
+char(4,47561).
+char(3,47562).
+char(8,47563).
+char(c,47564).
+char(c,47565).
+char(c,47566).
+char(m,47567).
+char(3,47568).
+char(7,47569).
+char(7,47570).
+char(2,47571).
+char(m,47572).
+char(o,47573).
+char(2,47574).
+char(1,47575).
+char(2,47576).
+char(4,47577).
+char(m,47578).
+char(o,47579).
+char(6,47580).
+char(6,47581).
+char(6,47582).
+char(7,47583).
+char(c,47584).
+char(c,47585).
+char(c,47586).
+char(c,47587).
+char(c,47588).
+char(c,47589).
+char(c,47590).
+char(p,47591).
+char(8,47592).
+char(9,47593).
+char(2,47594).
+char(9,47595).
+char(c,47596).
+char(p,47597).
+char(7,47598).
+char(0,47599).
+char(9,47600).
+char(7,47601).
+char(m,47602).
+char(1,47603).
+char(0,47604).
+char(3,47605).
+char(7,47606).
+char(c,47607).
+char(c,47608).
+char(m,47609).
+char(9,47610).
+char(4,47611).
+char(7,47612).
+char(4,47613).
+char(c,47614).
+char(c,47615).
+char(c,47616).
+char(c,47617).
+char(c,47618).
+char(m,47619).
+char(o,47620).
+char(m,47621).
+char(8,47622).
+char(5,47623).
+char(9,47624).
+char(c,47625).
+char(c,47626).
+char(c,47627).
+char(m,47628).
+char(4,47629).
+char(7,47630).
+char(4,47631).
+char(0,47632).
+char(m,47633).
+char(7,47634).
+char(6,47635).
+char(7,47636).
+char(2,47637).
+char(p,47638).
+char(o,47639).
+char(m,47640).
+char(6,47641).
+char(8,47642).
+char(8,47643).
+char(9,47644).
+char(c,47645).
+char(c,47646).
+char(c,47647).
+char(m,47648).
+char(o,47649).
+char(o,47650).
+char(m,47651).
+char(9,47652).
+char(9,47653).
+char(0,47654).
+char(1,47655).
+char(c,47656).
+char(m,47657).
+char(o,47658).
+char(o,47659).
+char(p,47660).
+char(1,47661).
+char(8,47662).
+char(6,47663).
+char(3,47664).
+char(c,47665).
+char(p,47666).
+char(5,47667).
+char(9,47668).
+char(6,47669).
+char(4,47670).
+char(p,47671).
+char(o,47672).
+char(m,47673).
+char(o,47674).
+char(m,47675).
+char(1,47676).
+char(2,47677).
+char(7,47678).
+char(6,47679).
+char(m,47680).
+char(3,47681).
+char(4,47682).
+char(5,47683).
+char(2,47684).
+char(c,47685).
+char(m,47686).
+char(5,47687).
+char(2,47688).
+char(4,47689).
+char(2,47690).
+char(c,47691).
+char(c,47692).
+char(c,47693).
+char(c,47694).
+char(c,47695).
+char(m,47696).
+char(o,47697).
+char(o,47698).
+char(p,47699).
+char(7,47700).
+char(9,47701).
+char(7,47702).
+char(8,47703).
+char(p,47704).
+char(o,47705).
+char(o,47706).
+char(m,47707).
+char(o,47708).
+char(m,47709).
+char(4,47710).
+char(9,47711).
+char(3,47712).
+char(5,47713).
+char(c,47714).
+char(c,47715).
+char(c,47716).
+char(m,47717).
+char(o,47718).
+char(m,47719).
+char(7,47720).
+char(3,47721).
+char(2,47722).
+char(1,47723).
+char(c,47724).
+char(c,47725).
+char(p,47726).
+char(8,47727).
+char(5,47728).
+char(7,47729).
+char(6,47730).
+char(c,47731).
+char(c,47732).
+char(c,47733).
+char(p,47734).
+char(5,47735).
+char(9,47736).
+char(8,47737).
+char(5,47738).
+char(c,47739).
+char(c,47740).
+char(c,47741).
+char(p,47742).
+char(o,47743).
+char(m,47744).
+char(o,47745).
+char(p,47746).
+char(2,47747).
+char(2,47748).
+char(9,47749).
+char(6,47750).
+char(p,47751).
+char(o,47752).
+char(m,47753).
+char(o,47754).
+char(8,47755).
+char(1,47756).
+char(0,47757).
+char(9,47758).
+char(c,47759).
+char(p,47760).
+char(9,47761).
+char(1,47762).
+char(4,47763).
+char(7,47764).
+char(c,47765).
+char(p,47766).
+char(8,47767).
+char(2,47768).
+char(2,47769).
+char(0,47770).
+char(p,47771).
+char(o,47772).
+char(p,47773).
+char(o,47774).
+char(p,47775).
+char(1,47776).
+char(8,47777).
+char(2,47778).
+char(2,47779).
+char(c,47780).
+char(c,47781).
+char(m,47782).
+char(o,47783).
+char(1,47784).
+char(9,47785).
+char(9,47786).
+char(2,47787).
+char(c,47788).
+char(c,47789).
+char(c,47790).
+char(c,47791).
+char(c,47792).
+char(p,47793).
+char(5,47794).
+char(9,47795).
+char(2,47796).
+char(3,47797).
+char(p,47798).
+char(1,47799).
+char(0,47800).
+char(4,47801).
+char(2,47802).
+char(c,47803).
+char(c,47804).
+char(p,47805).
+char(7,47806).
+char(8,47807).
+char(0,47808).
+char(5,47809).
+char(c,47810).
+char(c,47811).
+char(c,47812).
+char(c,47813).
+char(c,47814).
+char(p,47815).
+char(7,47816).
+char(2,47817).
+char(2,47818).
+char(1,47819).
+char(p,47820).
+char(8,47821).
+char(2,47822).
+char(6,47823).
+char(7,47824).
+char(p,47825).
+char(6,47826).
+char(5,47827).
+char(8,47828).
+char(4,47829).
+char(m,47830).
+char(8,47831).
+char(3,47832).
+char(3,47833).
+char(3,47834).
+char(m,47835).
+char(1,47836).
+char(6,47837).
+char(7,47838).
+char(p,47839).
+char(o,47840).
+char(m,47841).
+char(o,47842).
+char(m,47843).
+char(o,47844).
+char(p,47845).
+char(o,47846).
+char(m,47847).
+char(o,47848).
+char(p,47849).
+char(o,47850).
+char(o,47851).
+char(p,47852).
+char(8,47853).
+char(6,47854).
+char(4,47855).
+char(9,47856).
+char(c,47857).
+char(c,47858).
+char(c,47859).
+char(c,47860).
+char(c,47861).
+char(c,47862).
+char(p,47863).
+char(o,47864).
+char(p,47865).
+char(4,47866).
+char(3,47867).
+char(5,47868).
+char(2,47869).
+char(c,47870).
+char(c,47871).
+char(c,47872).
+char(p,47873).
+char(o,47874).
+char(p,47875).
+char(7,47876).
+char(2,47877).
+char(7,47878).
+char(1,47879).
+char(m,47880).
+char(5,47881).
+char(1,47882).
+char(6,47883).
+char(8,47884).
+char(c,47885).
+char(p,47886).
+char(o,47887).
+char(m,47888).
+char(3,47889).
+char(8,47890).
+char(6,47891).
+char(p,47892).
+char(o,47893).
+char(p,47894).
+char(3,47895).
+char(m,47896).
+char(o,47897).
+char(p,47898).
+char(5,47899).
+char(2,47900).
+char(4,47901).
+char(c,47902).
+char(p,47903).
+char(4,47904).
+char(1,47905).
+char(0,47906).
+char(2,47907).
+char(m,47908).
+char(o,47909).
+char(6,47910).
+char(7,47911).
+char(3,47912).
+char(c,47913).
+char(c,47914).
+char(c,47915).
+char(p,47916).
+char(o,47917).
+char(m,47918).
+char(o,47919).
+char(o,47920).
+char(p,47921).
+char(8,47922).
+char(2,47923).
+char(4,47924).
+char(5,47925).
+char(c,47926).
+char(m,47927).
+char(o,47928).
+char(o,47929).
+char(m,47930).
+char(o,47931).
+char(p,47932).
+char(o,47933).
+char(m,47934).
+char(o,47935).
+char(o,47936).
+char(p,47937).
+char(3,47938).
+char(7,47939).
+char(7,47940).
+char(c,47941).
+char(c,47942).
+char(m,47943).
+char(o,47944).
+char(p,47945).
+char(9,47946).
+char(2,47947).
+char(9,47948).
+char(p,47949).
+char(7,47950).
+char(5,47951).
+char(4,47952).
+char(5,47953).
+char(c,47954).
+char(p,47955).
+char(9,47956).
+char(7,47957).
+char(6,47958).
+char(7,47959).
+char(m,47960).
+char(o,47961).
+char(5,47962).
+char(1,47963).
+char(2,47964).
+char(c,47965).
+char(c,47966).
+char(c,47967).
+char(c,47968).
+char(c,47969).
+char(p,47970).
+char(o,47971).
+char(m,47972).
+char(8,47973).
+char(2,47974).
+char(0,47975).
+char(8,47976).
+char(c,47977).
+char(m,47978).
+char(o,47979).
+char(m,47980).
+char(o,47981).
+char(o,47982).
+char(p,47983).
+char(o,47984).
+char(m,47985).
+char(6,47986).
+char(9,47987).
+char(8,47988).
+char(m,47989).
+char(o,47990).
+char(m,47991).
+char(o,47992).
+char(p,47993).
+char(5,47994).
+char(4,47995).
+char(7,47996).
+char(4,47997).
+char(p,47998).
+char(o,47999).
+char(p,48000).
+char(6,48001).
+char(6,48002).
+char(7,48003).
+char(7,48004).
+char(c,48005).
+char(c,48006).
+char(c,48007).
+char(c,48008).
+char(c,48009).
+char(m,48010).
+char(4,48011).
+char(9,48012).
+char(0,48013).
+char(7,48014).
+char(c,48015).
+char(c,48016).
+char(c,48017).
+char(p,48018).
+char(4,48019).
+char(5,48020).
+char(8,48021).
+char(8,48022).
+char(c,48023).
+char(p,48024).
+char(1,48025).
+char(1,48026).
+char(7,48027).
+char(8,48028).
+char(c,48029).
+char(c,48030).
+char(m,48031).
+char(7,48032).
+char(5,48033).
+char(5,48034).
+char(2,48035).
+char(c,48036).
+char(c,48037).
+char(c,48038).
+char(p,48039).
+char(7,48040).
+char(0,48041).
+char(8,48042).
+char(9,48043).
+char(c,48044).
+char(c,48045).
+char(c,48046).
+char(c,48047).
+char(c,48048).
+char(c,48049).
+char(m,48050).
+char(8,48051).
+char(4,48052).
+char(6,48053).
+char(6,48054).
+char(c,48055).
+char(c,48056).
+char(p,48057).
+char(8,48058).
+char(5,48059).
+char(9,48060).
+char(p,48061).
+char(1,48062).
+char(3,48063).
+char(6,48064).
+char(2,48065).
+char(c,48066).
+char(p,48067).
+char(o,48068).
+char(m,48069).
+char(7,48070).
+char(9,48071).
+char(5,48072).
+char(8,48073).
+char(c,48074).
+char(m,48075).
+char(5,48076).
+char(2,48077).
+char(5,48078).
+char(5,48079).
+char(p,48080).
+char(o,48081).
+char(6,48082).
+char(5,48083).
+char(5,48084).
+char(9,48085).
+char(p,48086).
+char(o,48087).
+char(p,48088).
+char(2,48089).
+char(0,48090).
+char(5,48091).
+char(2,48092).
+char(m,48093).
+char(o,48094).
+char(p,48095).
+char(8,48096).
+char(5,48097).
+char(1,48098).
+char(8,48099).
+char(c,48100).
+char(c,48101).
+char(p,48102).
+char(o,48103).
+char(3,48104).
+char(0,48105).
+char(9,48106).
+char(4,48107).
+char(m,48108).
+char(6,48109).
+char(5,48110).
+char(6,48111).
+char(9,48112).
+char(p,48113).
+char(o,48114).
+char(p,48115).
+char(3,48116).
+char(8,48117).
+char(7,48118).
+char(2,48119).
+char(c,48120).
+char(p,48121).
+char(o,48122).
+char(p,48123).
+char(4,48124).
+char(2,48125).
+char(6,48126).
+char(5,48127).
+char(c,48128).
+char(c,48129).
+char(c,48130).
+char(c,48131).
+char(c,48132).
+char(m,48133).
+char(3,48134).
+char(8,48135).
+char(2,48136).
+char(3,48137).
+char(p,48138).
+char(4,48139).
+char(6,48140).
+char(1,48141).
+char(0,48142).
+char(c,48143).
+char(c,48144).
+char(c,48145).
+char(m,48146).
+char(o,48147).
+char(m,48148).
+char(o,48149).
+char(p,48150).
+char(2,48151).
+char(5,48152).
+char(3,48153).
+char(0,48154).
+char(c,48155).
+char(m,48156).
+char(1,48157).
+char(3,48158).
+char(1,48159).
+char(6,48160).
+char(c,48161).
+char(p,48162).
+char(9,48163).
+char(0,48164).
+char(7,48165).
+char(0,48166).
+char(c,48167).
+char(c,48168).
+char(p,48169).
+char(o,48170).
+char(p,48171).
+char(1,48172).
+char(1,48173).
+char(5,48174).
+char(9,48175).
+char(c,48176).
+char(c,48177).
+char(c,48178).
+char(p,48179).
+char(1,48180).
+char(4,48181).
+char(3,48182).
+char(6,48183).
+char(m,48184).
+char(o,48185).
+char(m,48186).
+char(o,48187).
+char(m,48188).
+char(6,48189).
+char(3,48190).
+char(9,48191).
+char(3,48192).
+char(c,48193).
+char(p,48194).
+char(6,48195).
+char(0,48196).
+char(5,48197).
+char(2,48198).
+char(m,48199).
+char(o,48200).
+char(o,48201).
+char(p,48202).
+char(o,48203).
+char(m,48204).
+char(o,48205).
+char(7,48206).
+char(3,48207).
+char(5,48208).
+char(4,48209).
+char(c,48210).
+char(m,48211).
+char(o,48212).
+char(o,48213).
+char(m,48214).
+char(6,48215).
+char(1,48216).
+char(6,48217).
+char(1,48218).
+char(p,48219).
+char(o,48220).
+char(o,48221).
+char(p,48222).
+char(5,48223).
+char(7,48224).
+char(4,48225).
+char(c,48226).
+char(m,48227).
+char(7,48228).
+char(4,48229).
+char(9,48230).
+char(3,48231).
+char(c,48232).
+char(m,48233).
+char(o,48234).
+char(1,48235).
+char(3,48236).
+char(5,48237).
+char(5,48238).
+char(m,48239).
+char(o,48240).
+char(1,48241).
+char(6,48242).
+char(4,48243).
+char(p,48244).
+char(o,48245).
+char(p,48246).
+char(o,48247).
+char(p,48248).
+char(o,48249).
+char(m,48250).
+char(5,48251).
+char(2,48252).
+char(8,48253).
+char(6,48254).
+char(p,48255).
+char(2,48256).
+char(4,48257).
+char(0,48258).
+char(3,48259).
+char(c,48260).
+char(c,48261).
+char(m,48262).
+char(6,48263).
+char(1,48264).
+char(8,48265).
+char(4,48266).
+char(c,48267).
+char(m,48268).
+char(o,48269).
+char(p,48270).
+char(o,48271).
+char(m,48272).
+char(3,48273).
+char(2,48274).
+char(0,48275).
+char(c,48276).
+char(c,48277).
+char(m,48278).
+char(4,48279).
+char(9,48280).
+char(1,48281).
+char(2,48282).
+char(m,48283).
+char(3,48284).
+char(2,48285).
+char(1,48286).
+char(9,48287).
+char(m,48288).
+char(5,48289).
+char(7,48290).
+char(4,48291).
+char(m,48292).
+char(o,48293).
+char(p,48294).
+char(8,48295).
+char(2,48296).
+char(6,48297).
+char(4,48298).
+char(c,48299).
+char(p,48300).
+char(o,48301).
+char(o,48302).
+char(m,48303).
+char(o,48304).
+char(p,48305).
+char(9,48306).
+char(6,48307).
+char(5,48308).
+char(0,48309).
+char(c,48310).
+char(c,48311).
+char(p,48312).
+char(6,48313).
+char(3,48314).
+char(1,48315).
+char(c,48316).
+char(m,48317).
+char(1,48318).
+char(7,48319).
+char(3,48320).
+char(2,48321).
+char(m,48322).
+char(o,48323).
+char(m,48324).
+char(5,48325).
+char(7,48326).
+char(5,48327).
+char(4,48328).
+char(c,48329).
+char(c,48330).
+char(p,48331).
+char(o,48332).
+char(4,48333).
+char(2,48334).
+char(0,48335).
+char(6,48336).
+char(c,48337).
+char(p,48338).
+char(4,48339).
+char(0,48340).
+char(8,48341).
+char(8,48342).
+char(p,48343).
+char(o,48344).
+char(p,48345).
+char(o,48346).
+char(2,48347).
+char(2,48348).
+char(3,48349).
+char(1,48350).
+char(m,48351).
+char(4,48352).
+char(9,48353).
+char(4,48354).
+char(9,48355).
+char(p,48356).
+char(o,48357).
+char(p,48358).
+char(o,48359).
+char(6,48360).
+char(8,48361).
+char(5,48362).
+char(6,48363).
+char(p,48364).
+char(2,48365).
+char(9,48366).
+char(8,48367).
+char(1,48368).
+char(c,48369).
+char(m,48370).
+char(1,48371).
+char(1,48372).
+char(9,48373).
+char(5,48374).
+char(c,48375).
+char(c,48376).
+char(c,48377).
+char(c,48378).
+char(c,48379).
+char(m,48380).
+char(7,48381).
+char(6,48382).
+char(6,48383).
+char(4,48384).
+char(c,48385).
+char(c,48386).
+char(c,48387).
+char(p,48388).
+char(5,48389).
+char(7,48390).
+char(5,48391).
+char(3,48392).
+char(c,48393).
+char(c,48394).
+char(c,48395).
+char(m,48396).
+char(o,48397).
+char(4,48398).
+char(0,48399).
+char(1,48400).
+char(0,48401).
+char(p,48402).
+char(o,48403).
+char(o,48404).
+char(4,48405).
+char(1,48406).
+char(3,48407).
+char(8,48408).
+char(p,48409).
+char(o,48410).
+char(1,48411).
+char(1,48412).
+char(5,48413).
+char(5,48414).
+char(c,48415).
+char(c,48416).
+char(c,48417).
+char(c,48418).
+char(c,48419).
+char(m,48420).
+char(9,48421).
+char(2,48422).
+char(2,48423).
+char(8,48424).
+char(c,48425).
+char(m,48426).
+char(o,48427).
+char(m,48428).
+char(3,48429).
+char(0,48430).
+char(3,48431).
+char(1,48432).
+char(m,48433).
+char(2,48434).
+char(9,48435).
+char(7,48436).
+char(4,48437).
+char(m,48438).
+char(9,48439).
+char(7,48440).
+char(3,48441).
+char(2,48442).
+char(c,48443).
+char(p,48444).
+char(5,48445).
+char(6,48446).
+char(8,48447).
+char(m,48448).
+char(o,48449).
+char(p,48450).
+char(4,48451).
+char(7,48452).
+char(1,48453).
+char(9,48454).
+char(c,48455).
+char(c,48456).
+char(c,48457).
+char(c,48458).
+char(m,48459).
+char(5,48460).
+char(1,48461).
+char(6,48462).
+char(4,48463).
+char(m,48464).
+char(6,48465).
+char(6,48466).
+char(8,48467).
+char(5,48468).
+char(c,48469).
+char(c,48470).
+char(c,48471).
+char(p,48472).
+char(5,48473).
+char(7,48474).
+char(8,48475).
+char(9,48476).
+char(m,48477).
+char(4,48478).
+char(7,48479).
+char(3,48480).
+char(3,48481).
+char(p,48482).
+char(5,48483).
+char(8,48484).
+char(1,48485).
+char(0,48486).
+char(p,48487).
+char(3,48488).
+char(0,48489).
+char(3,48490).
+char(2,48491).
+char(c,48492).
+char(p,48493).
+char(o,48494).
+char(o,48495).
+char(o,48496).
+char(m,48497).
+char(o,48498).
+char(m,48499).
+char(o,48500).
+char(m,48501).
+char(8,48502).
+char(2,48503).
+char(1,48504).
+char(5,48505).
+char(p,48506).
+char(o,48507).
+char(p,48508).
+char(3,48509).
+char(9,48510).
+char(2,48511).
+char(3,48512).
+char(c,48513).
+char(p,48514).
+char(o,48515).
+char(p,48516).
+char(8,48517).
+char(4,48518).
+char(5,48519).
+char(2,48520).
+char(m,48521).
+char(o,48522).
+char(o,48523).
+char(o,48524).
+char(p,48525).
+char(o,48526).
+char(m,48527).
+char(o,48528).
+char(p,48529).
+char(1,48530).
+char(7,48531).
+char(3,48532).
+char(9,48533).
+char(m,48534).
+char(o,48535).
+char(1,48536).
+char(9,48537).
+char(3,48538).
+char(c,48539).
+char(c,48540).
+char(m,48541).
+char(6,48542).
+char(1,48543).
+char(3,48544).
+char(9,48545).
+char(c,48546).
+char(c,48547).
+char(c,48548).
+char(m,48549).
+char(o,48550).
+char(o,48551).
+char(m,48552).
+char(9,48553).
+char(4,48554).
+char(9,48555).
+char(3,48556).
+char(p,48557).
+char(o,48558).
+char(8,48559).
+char(5,48560).
+char(9,48561).
+char(7,48562).
+char(m,48563).
+char(o,48564).
+char(p,48565).
+char(o,48566).
+char(p,48567).
+char(o,48568).
+char(p,48569).
+char(7,48570).
+char(2,48571).
+char(8,48572).
+char(2,48573).
+char(c,48574).
+char(c,48575).
+char(m,48576).
+char(1,48577).
+char(8,48578).
+char(7,48579).
+char(0,48580).
+char(c,48581).
+char(p,48582).
+char(o,48583).
+char(m,48584).
+char(8,48585).
+char(5,48586).
+char(6,48587).
+char(9,48588).
+char(p,48589).
+char(o,48590).
+char(m,48591).
+char(o,48592).
+char(m,48593).
+char(4,48594).
+char(3,48595).
+char(9,48596).
+char(6,48597).
+char(c,48598).
+char(c,48599).
+char(m,48600).
+char(9,48601).
+char(3,48602).
+char(2,48603).
+char(2,48604).
+char(p,48605).
+char(o,48606).
+char(p,48607).
+char(7,48608).
+char(2,48609).
+char(7,48610).
+char(9,48611).
+char(c,48612).
+char(m,48613).
+char(o,48614).
+char(m,48615).
+char(o,48616).
+char(p,48617).
+char(o,48618).
+char(o,48619).
+char(p,48620).
+char(o,48621).
+char(m,48622).
+char(7,48623).
+char(0,48624).
+char(4,48625).
+char(2,48626).
+char(p,48627).
+char(4,48628).
+char(6,48629).
+char(2,48630).
+char(0,48631).
+char(c,48632).
+char(c,48633).
+char(c,48634).
+char(m,48635).
+char(o,48636).
+char(9,48637).
+char(3,48638).
+char(6,48639).
+char(4,48640).
+char(m,48641).
+char(1,48642).
+char(1,48643).
+char(8,48644).
+char(6,48645).
+char(m,48646).
+char(o,48647).
+char(m,48648).
+char(o,48649).
+char(9,48650).
+char(6,48651).
+char(1,48652).
+char(2,48653).
+char(c,48654).
+char(p,48655).
+char(o,48656).
+char(m,48657).
+char(o,48658).
+char(p,48659).
+char(6,48660).
+char(7,48661).
+char(9,48662).
+char(7,48663).
+char(m,48664).
+char(o,48665).
+char(p,48666).
+char(1,48667).
+char(2,48668).
+char(2,48669).
+char(3,48670).
+char(m,48671).
+char(o,48672).
+char(2,48673).
+char(0,48674).
+char(1,48675).
+char(2,48676).
+char(c,48677).
+char(m,48678).
+char(o,48679).
+char(3,48680).
+char(8,48681).
+char(9,48682).
+char(0,48683).
+char(m,48684).
+char(4,48685).
+char(7,48686).
+char(8,48687).
+char(0,48688).
+char(c,48689).
+char(p,48690).
+char(4,48691).
+char(9,48692).
+char(3,48693).
+char(1,48694).
+char(m,48695).
+char(o,48696).
+char(o,48697).
+char(m,48698).
+char(6,48699).
+char(6,48700).
+char(4,48701).
+char(c,48702).
+char(p,48703).
+char(2,48704).
+char(5,48705).
+char(5,48706).
+char(2,48707).
+char(c,48708).
+char(p,48709).
+char(6,48710).
+char(3,48711).
+char(4,48712).
+char(7,48713).
+char(c,48714).
+char(m,48715).
+char(o,48716).
+char(o,48717).
+char(o,48718).
+char(o,48719).
+char(m,48720).
+char(4,48721).
+char(4,48722).
+char(7,48723).
+char(2,48724).
+char(c,48725).
+char(m,48726).
+char(o,48727).
+char(o,48728).
+char(p,48729).
+char(7,48730).
+char(8,48731).
+char(6,48732).
+char(p,48733).
+char(2,48734).
+char(5,48735).
+char(9,48736).
+char(c,48737).
+char(c,48738).
+char(m,48739).
+char(5,48740).
+char(0,48741).
+char(6,48742).
+char(4,48743).
+char(p,48744).
+char(6,48745).
+char(7,48746).
+char(4,48747).
+char(0,48748).
+char(c,48749).
+char(p,48750).
+char(o,48751).
+char(m,48752).
+char(o,48753).
+char(m,48754).
+char(5,48755).
+char(9,48756).
+char(7,48757).
+char(8,48758).
+char(c,48759).
+char(c,48760).
+char(m,48761).
+char(o,48762).
+char(p,48763).
+char(5,48764).
+char(9,48765).
+char(0,48766).
+char(2,48767).
+char(c,48768).
+char(m,48769).
+char(o,48770).
+char(m,48771).
+char(8,48772).
+char(1,48773).
+char(9,48774).
+char(5,48775).
+char(c,48776).
+char(c,48777).
+char(c,48778).
+char(c,48779).
+char(m,48780).
+char(4,48781).
+char(5,48782).
+char(3,48783).
+char(4,48784).
+char(c,48785).
+char(p,48786).
+char(8,48787).
+char(2,48788).
+char(7,48789).
+char(6,48790).
+char(c,48791).
+char(c,48792).
+char(m,48793).
+char(2,48794).
+char(4,48795).
+char(9,48796).
+char(2,48797).
+char(c,48798).
+char(c,48799).
+char(c,48800).
+char(c,48801).
+char(c,48802).
+char(p,48803).
+char(o,48804).
+char(m,48805).
+char(7,48806).
+char(3,48807).
+char(8,48808).
+char(5,48809).
+char(p,48810).
+char(o,48811).
+char(m,48812).
+char(3,48813).
+char(9,48814).
+char(5,48815).
+char(1,48816).
+char(c,48817).
+char(c,48818).
+char(c,48819).
+char(m,48820).
+char(o,48821).
+char(m,48822).
+char(o,48823).
+char(m,48824).
+char(1,48825).
+char(0,48826).
+char(9,48827).
+char(0,48828).
+char(p,48829).
+char(4,48830).
+char(6,48831).
+char(3,48832).
+char(6,48833).
+char(m,48834).
+char(6,48835).
+char(0,48836).
+char(6,48837).
+char(3,48838).
+char(c,48839).
+char(c,48840).
+char(p,48841).
+char(o,48842).
+char(m,48843).
+char(o,48844).
+char(m,48845).
+char(8,48846).
+char(3,48847).
+char(4,48848).
+char(m,48849).
+char(o,48850).
+char(o,48851).
+char(1,48852).
+char(7,48853).
+char(7,48854).
+char(9,48855).
+char(m,48856).
+char(o,48857).
+char(p,48858).
+char(o,48859).
+char(p,48860).
+char(4,48861).
+char(9,48862).
+char(6,48863).
+char(3,48864).
+char(c,48865).
+char(p,48866).
+char(o,48867).
+char(p,48868).
+char(4,48869).
+char(7,48870).
+char(4,48871).
+char(4,48872).
+char(m,48873).
+char(o,48874).
+char(m,48875).
+char(o,48876).
+char(m,48877).
+char(o,48878).
+char(9,48879).
+char(3,48880).
+char(3,48881).
+char(3,48882).
+char(m,48883).
+char(o,48884).
+char(m,48885).
+char(3,48886).
+char(1,48887).
+char(0,48888).
+char(2,48889).
+char(c,48890).
+char(p,48891).
+char(4,48892).
+char(6,48893).
+char(5,48894).
+char(8,48895).
+char(m,48896).
+char(2,48897).
+char(7,48898).
+char(8,48899).
+char(6,48900).
+char(c,48901).
+char(p,48902).
+char(6,48903).
+char(7,48904).
+char(2,48905).
+char(2,48906).
+char(c,48907).
+char(c,48908).
+char(c,48909).
+char(m,48910).
+char(2,48911).
+char(8,48912).
+char(9,48913).
+char(2,48914).
+char(m,48915).
+char(3,48916).
+char(3,48917).
+char(9,48918).
+char(9,48919).
+char(p,48920).
+char(3,48921).
+char(0,48922).
+char(8,48923).
+char(2,48924).
+char(c,48925).
+char(c,48926).
+char(m,48927).
+char(8,48928).
+char(7,48929).
+char(4,48930).
+char(5,48931).
+char(c,48932).
+char(m,48933).
+char(8,48934).
+char(7,48935).
+char(4,48936).
+char(1,48937).
+char(m,48938).
+char(o,48939).
+char(m,48940).
+char(3,48941).
+char(3,48942).
+char(9,48943).
+char(9,48944).
+char(c,48945).
+char(c,48946).
+char(c,48947).
+char(m,48948).
+char(o,48949).
+char(p,48950).
+char(8,48951).
+char(2,48952).
+char(2,48953).
+char(6,48954).
+char(p,48955).
+char(o,48956).
+char(o,48957).
+char(m,48958).
+char(3,48959).
+char(0,48960).
+char(1,48961).
+char(4,48962).
+char(p,48963).
+char(o,48964).
+char(m,48965).
+char(2,48966).
+char(4,48967).
+char(4,48968).
+char(9,48969).
+char(c,48970).
+char(m,48971).
+char(1,48972).
+char(3,48973).
+char(6,48974).
+char(3,48975).
+char(c,48976).
+char(p,48977).
+char(4,48978).
+char(2,48979).
+char(4,48980).
+char(9,48981).
+char(p,48982).
+char(2,48983).
+char(9,48984).
+char(8,48985).
+char(0,48986).
+char(m,48987).
+char(4,48988).
+char(9,48989).
+char(4,48990).
+char(8,48991).
+char(c,48992).
+char(p,48993).
+char(9,48994).
+char(6,48995).
+char(0,48996).
+char(8,48997).
+char(c,48998).
+char(m,48999).
+char(2,49000).
+char(7,49001).
+char(1,49002).
+char(7,49003).
+char(c,49004).
+char(m,49005).
+char(2,49006).
+char(2,49007).
+char(1,49008).
+char(1,49009).
+char(c,49010).
+char(c,49011).
+char(m,49012).
+char(1,49013).
+char(5,49014).
+char(1,49015).
+char(1,49016).
+char(p,49017).
+char(o,49018).
+char(o,49019).
+char(m,49020).
+char(2,49021).
+char(3,49022).
+char(4,49023).
+char(5,49024).
+char(c,49025).
+char(c,49026).
+char(m,49027).
+char(o,49028).
+char(2,49029).
+char(1,49030).
+char(7,49031).
+char(c,49032).
+char(c,49033).
+char(c,49034).
+char(p,49035).
+char(6,49036).
+char(4,49037).
+char(2,49038).
+char(m,49039).
+char(o,49040).
+char(p,49041).
+char(o,49042).
+char(m,49043).
+char(8,49044).
+char(4,49045).
+char(6,49046).
+char(3,49047).
+char(m,49048).
+char(2,49049).
+char(3,49050).
+char(0,49051).
+char(4,49052).
+char(c,49053).
+char(c,49054).
+char(p,49055).
+char(5,49056).
+char(3,49057).
+char(1,49058).
+char(1,49059).
+char(c,49060).
+char(c,49061).
+char(c,49062).
+char(m,49063).
+char(4,49064).
+char(0,49065).
+char(7,49066).
+char(8,49067).
+char(c,49068).
+char(c,49069).
+char(c,49070).
+char(c,49071).
+char(p,49072).
+char(o,49073).
+char(p,49074).
+char(o,49075).
+char(p,49076).
+char(8,49077).
+char(8,49078).
+char(3,49079).
+char(5,49080).
+char(c,49081).
+char(c,49082).
+char(c,49083).
+char(c,49084).
+char(p,49085).
+char(o,49086).
+char(m,49087).
+char(4,49088).
+char(4,49089).
+char(5,49090).
+char(7,49091).
+char(c,49092).
+char(c,49093).
+char(c,49094).
+char(m,49095).
+char(2,49096).
+char(1,49097).
+char(4,49098).
+char(6,49099).
+char(p,49100).
+char(o,49101).
+char(p,49102).
+char(o,49103).
+char(8,49104).
+char(4,49105).
+char(1,49106).
+char(3,49107).
+char(p,49108).
+char(8,49109).
+char(1,49110).
+char(5,49111).
+char(c,49112).
+char(c,49113).
+char(c,49114).
+char(c,49115).
+char(c,49116).
+char(c,49117).
+char(m,49118).
+char(o,49119).
+char(p,49120).
+char(o,49121).
+char(4,49122).
+char(1,49123).
+char(0,49124).
+char(9,49125).
+char(c,49126).
+char(m,49127).
+char(o,49128).
+char(p,49129).
+char(2,49130).
+char(2,49131).
+char(2,49132).
+char(9,49133).
+char(p,49134).
+char(o,49135).
+char(m,49136).
+char(7,49137).
+char(7,49138).
+char(6,49139).
+char(2,49140).
+char(c,49141).
+char(c,49142).
+char(c,49143).
+char(c,49144).
+char(c,49145).
+char(c,49146).
+char(c,49147).
+char(c,49148).
+char(p,49149).
+char(8,49150).
+char(1,49151).
+char(4,49152).
+char(4,49153).
+char(p,49154).
+char(5,49155).
+char(7,49156).
+char(1,49157).
+char(4,49158).
+char(c,49159).
+char(c,49160).
+char(m,49161).
+char(o,49162).
+char(p,49163).
+char(o,49164).
+char(m,49165).
+char(9,49166).
+char(2,49167).
+char(7,49168).
+char(8,49169).
+char(c,49170).
+char(m,49171).
+char(8,49172).
+char(5,49173).
+char(1,49174).
+char(1,49175).
+char(c,49176).
+char(p,49177).
+char(7,49178).
+char(3,49179).
+char(6,49180).
+char(4,49181).
+char(c,49182).
+char(c,49183).
+char(m,49184).
+char(2,49185).
+char(9,49186).
+char(3,49187).
+char(8,49188).
+char(m,49189).
+char(1,49190).
+char(4,49191).
+char(4,49192).
+char(4,49193).
+char(c,49194).
+char(c,49195).
+char(c,49196).
+char(c,49197).
+char(m,49198).
+char(o,49199).
+char(m,49200).
+char(9,49201).
+char(9,49202).
+char(4,49203).
+char(p,49204).
+char(o,49205).
+char(2,49206).
+char(2,49207).
+char(1,49208).
+char(8,49209).
+char(p,49210).
+char(1,49211).
+char(3,49212).
+char(1,49213).
+char(9,49214).
+char(m,49215).
+char(5,49216).
+char(3,49217).
+char(3,49218).
+char(7,49219).
+char(m,49220).
+char(5,49221).
+char(4,49222).
+char(8,49223).
+char(8,49224).
+char(c,49225).
+char(m,49226).
+char(o,49227).
+char(p,49228).
+char(o,49229).
+char(p,49230).
+char(1,49231).
+char(1,49232).
+char(5,49233).
+char(2,49234).
+char(m,49235).
+char(o,49236).
+char(o,49237).
+char(p,49238).
+char(7,49239).
+char(7,49240).
+char(8,49241).
+char(4,49242).
+char(c,49243).
+char(p,49244).
+char(o,49245).
+char(o,49246).
+char(o,49247).
+char(p,49248).
+char(3,49249).
+char(5,49250).
+char(4,49251).
+char(4,49252).
+char(c,49253).
+char(c,49254).
+char(c,49255).
+char(c,49256).
+char(c,49257).
+char(c,49258).
+char(c,49259).
+char(p,49260).
+char(o,49261).
+char(m,49262).
+char(9,49263).
+char(5,49264).
+char(0,49265).
+char(9,49266).
+char(m,49267).
+char(o,49268).
+char(m,49269).
+char(o,49270).
+char(m,49271).
+char(7,49272).
+char(5,49273).
+char(5,49274).
+char(8,49275).
+char(c,49276).
+char(p,49277).
+char(8,49278).
+char(0,49279).
+char(1,49280).
+char(8,49281).
+char(m,49282).
+char(o,49283).
+char(5,49284).
+char(4,49285).
+char(7,49286).
+char(2,49287).
+char(c,49288).
+char(p,49289).
+char(2,49290).
+char(6,49291).
+char(6,49292).
+char(3,49293).
+char(c,49294).
+char(p,49295).
+char(o,49296).
+char(6,49297).
+char(6,49298).
+char(1,49299).
+char(3,49300).
+char(c,49301).
+char(c,49302).
+char(c,49303).
+char(c,49304).
+char(c,49305).
+char(c,49306).
+char(m,49307).
+char(6,49308).
+char(2,49309).
+char(7,49310).
+char(8,49311).
+char(c,49312).
+char(c,49313).
+char(c,49314).
+char(c,49315).
+char(c,49316).
+char(m,49317).
+char(o,49318).
+char(o,49319).
+char(4,49320).
+char(1,49321).
+char(9,49322).
+char(p,49323).
+char(7,49324).
+char(5,49325).
+char(7,49326).
+char(7,49327).
+char(p,49328).
+char(6,49329).
+char(0,49330).
+char(7,49331).
+char(1,49332).
+char(p,49333).
+char(9,49334).
+char(5,49335).
+char(7,49336).
+char(9,49337).
+char(p,49338).
+char(o,49339).
+char(8,49340).
+char(8,49341).
+char(9,49342).
+char(5,49343).
+char(c,49344).
+char(m,49345).
+char(8,49346).
+char(7,49347).
+char(0,49348).
+char(8,49349).
+char(p,49350).
+char(8,49351).
+char(6,49352).
+char(4,49353).
+char(4,49354).
+char(c,49355).
+char(c,49356).
+char(p,49357).
+char(o,49358).
+char(7,49359).
+char(1,49360).
+char(0,49361).
+char(0,49362).
+char(m,49363).
+char(2,49364).
+char(3,49365).
+char(7,49366).
+char(1,49367).
+char(p,49368).
+char(7,49369).
+char(6,49370).
+char(5,49371).
+char(3,49372).
+char(c,49373).
+char(c,49374).
+char(c,49375).
+char(c,49376).
+char(m,49377).
+char(o,49378).
+char(p,49379).
+char(o,49380).
+char(m,49381).
+char(o,49382).
+char(2,49383).
+char(9,49384).
+char(6,49385).
+char(5,49386).
+char(c,49387).
+char(c,49388).
+char(m,49389).
+char(7,49390).
+char(6,49391).
+char(5,49392).
+char(1,49393).
+char(m,49394).
+char(6,49395).
+char(3,49396).
+char(8,49397).
+char(7,49398).
+char(p,49399).
+char(9,49400).
+char(1,49401).
+char(8,49402).
+char(c,49403).
+char(c,49404).
+char(c,49405).
+char(p,49406).
+char(o,49407).
+char(o,49408).
+char(4,49409).
+char(6,49410).
+char(5,49411).
+char(4,49412).
+char(c,49413).
+char(c,49414).
+char(c,49415).
+char(c,49416).
+char(c,49417).
+char(c,49418).
+char(c,49419).
+char(m,49420).
+char(o,49421).
+char(o,49422).
+char(p,49423).
+char(o,49424).
+char(1,49425).
+char(5,49426).
+char(5,49427).
+char(5,49428).
+char(c,49429).
+char(c,49430).
+char(p,49431).
+char(6,49432).
+char(7,49433).
+char(1,49434).
+char(0,49435).
+char(c,49436).
+char(c,49437).
+char(c,49438).
+char(m,49439).
+char(o,49440).
+char(o,49441).
+char(o,49442).
+char(p,49443).
+char(o,49444).
+char(7,49445).
+char(0,49446).
+char(7,49447).
+char(7,49448).
+char(m,49449).
+char(o,49450).
+char(6,49451).
+char(5,49452).
+char(4,49453).
+char(8,49454).
+char(c,49455).
+char(p,49456).
+char(o,49457).
+char(p,49458).
+char(o,49459).
+char(m,49460).
+char(1,49461).
+char(2,49462).
+char(3,49463).
+char(1,49464).
+char(c,49465).
+char(p,49466).
+char(o,49467).
+char(m,49468).
+char(1,49469).
+char(7,49470).
+char(0,49471).
+char(9,49472).
+char(c,49473).
+char(p,49474).
+char(o,49475).
+char(m,49476).
+char(1,49477).
+char(0,49478).
+char(6,49479).
+char(7,49480).
+char(c,49481).
+char(c,49482).
+char(c,49483).
+char(p,49484).
+char(o,49485).
+char(p,49486).
+char(3,49487).
+char(2,49488).
+char(2,49489).
+char(5,49490).
+char(c,49491).
+char(p,49492).
+char(o,49493).
+char(p,49494).
+char(2,49495).
+char(5,49496).
+char(6,49497).
+char(5,49498).
+char(c,49499).
+char(m,49500).
+char(o,49501).
+char(m,49502).
+char(7,49503).
+char(9,49504).
+char(2,49505).
+char(2,49506).
+char(m,49507).
+char(o,49508).
+char(p,49509).
+char(o,49510).
+char(p,49511).
+char(o,49512).
+char(o,49513).
+char(m,49514).
+char(1,49515).
+char(7,49516).
+char(9,49517).
+char(7,49518).
+char(c,49519).
+char(p,49520).
+char(o,49521).
+char(4,49522).
+char(0,49523).
+char(5,49524).
+char(8,49525).
+char(m,49526).
+char(o,49527).
+char(p,49528).
+char(8,49529).
+char(3,49530).
+char(1,49531).
+char(c,49532).
+char(c,49533).
+char(c,49534).
+char(c,49535).
+char(c,49536).
+char(c,49537).
+char(m,49538).
+char(5,49539).
+char(3,49540).
+char(1,49541).
+char(m,49542).
+char(4,49543).
+char(5,49544).
+char(3,49545).
+char(p,49546).
+char(o,49547).
+char(p,49548).
+char(9,49549).
+char(9,49550).
+char(7,49551).
+char(4,49552).
+char(m,49553).
+char(4,49554).
+char(1,49555).
+char(3,49556).
+char(6,49557).
+char(c,49558).
+char(p,49559).
+char(o,49560).
+char(m,49561).
+char(3,49562).
+char(6,49563).
+char(2,49564).
+char(c,49565).
+char(p,49566).
+char(o,49567).
+char(m,49568).
+char(7,49569).
+char(5,49570).
+char(3,49571).
+char(4,49572).
+char(c,49573).
+char(c,49574).
+char(c,49575).
+char(p,49576).
+char(6,49577).
+char(1,49578).
+char(7,49579).
+char(5,49580).
+char(c,49581).
+char(c,49582).
+char(p,49583).
+char(6,49584).
+char(6,49585).
+char(4,49586).
+char(1,49587).
+char(c,49588).
+char(p,49589).
+char(o,49590).
+char(m,49591).
+char(1,49592).
+char(6,49593).
+char(3,49594).
+char(9,49595).
+char(p,49596).
+char(o,49597).
+char(p,49598).
+char(o,49599).
+char(p,49600).
+char(2,49601).
+char(6,49602).
+char(5,49603).
+char(1,49604).
+char(p,49605).
+char(2,49606).
+char(3,49607).
+char(1,49608).
+char(2,49609).
+char(c,49610).
+char(p,49611).
+char(7,49612).
+char(8,49613).
+char(8,49614).
+char(2,49615).
+char(c,49616).
+char(c,49617).
+char(c,49618).
+char(p,49619).
+char(o,49620).
+char(m,49621).
+char(3,49622).
+char(9,49623).
+char(5,49624).
+char(9,49625).
+char(m,49626).
+char(7,49627).
+char(0,49628).
+char(4,49629).
+char(7,49630).
+char(c,49631).
+char(c,49632).
+char(c,49633).
+char(p,49634).
+char(o,49635).
+char(p,49636).
+char(o,49637).
+char(p,49638).
+char(o,49639).
+char(p,49640).
+char(o,49641).
+char(m,49642).
+char(8,49643).
+char(7,49644).
+char(8,49645).
+char(p,49646).
+char(3,49647).
+char(3,49648).
+char(6,49649).
+char(9,49650).
+char(c,49651).
+char(m,49652).
+char(o,49653).
+char(o,49654).
+char(9,49655).
+char(7,49656).
+char(2,49657).
+char(p,49658).
+char(8,49659).
+char(6,49660).
+char(2,49661).
+char(1,49662).
+char(c,49663).
+char(p,49664).
+char(o,49665).
+char(o,49666).
+char(m,49667).
+char(o,49668).
+char(9,49669).
+char(8,49670).
+char(7,49671).
+char(1,49672).
+char(p,49673).
+char(5,49674).
+char(9,49675).
+char(4,49676).
+char(c,49677).
+char(p,49678).
+char(o,49679).
+char(m,49680).
+char(o,49681).
+char(o,49682).
+char(p,49683).
+char(1,49684).
+char(7,49685).
+char(0,49686).
+char(3,49687).
+char(c,49688).
+char(c,49689).
+char(c,49690).
+char(p,49691).
+char(6,49692).
+char(2,49693).
+char(0,49694).
+char(7,49695).
+char(c,49696).
+char(m,49697).
+char(3,49698).
+char(2,49699).
+char(1,49700).
+char(4,49701).
+char(c,49702).
+char(p,49703).
+char(8,49704).
+char(7,49705).
+char(4,49706).
+char(1,49707).
+char(m,49708).
+char(o,49709).
+char(p,49710).
+char(o,49711).
+char(6,49712).
+char(7,49713).
+char(5,49714).
+char(c,49715).
+char(p,49716).
+char(3,49717).
+char(5,49718).
+char(2,49719).
+char(c,49720).
+char(c,49721).
+char(c,49722).
+char(c,49723).
+char(c,49724).
+char(m,49725).
+char(7,49726).
+char(5,49727).
+char(7,49728).
+char(1,49729).
+char(p,49730).
+char(3,49731).
+char(2,49732).
+char(9,49733).
+char(p,49734).
+char(o,49735).
+char(m,49736).
+char(2,49737).
+char(3,49738).
+char(2,49739).
+char(1,49740).
+char(c,49741).
+char(m,49742).
+char(o,49743).
+char(8,49744).
+char(1,49745).
+char(2,49746).
+char(1,49747).
+char(c,49748).
+char(c,49749).
+char(m,49750).
+char(9,49751).
+char(3,49752).
+char(7,49753).
+char(0,49754).
+char(m,49755).
+char(o,49756).
+char(p,49757).
+char(o,49758).
+char(o,49759).
+char(m,49760).
+char(o,49761).
+char(p,49762).
+char(2,49763).
+char(7,49764).
+char(9,49765).
+char(p,49766).
+char(o,49767).
+char(m,49768).
+char(o,49769).
+char(m,49770).
+char(1,49771).
+char(3,49772).
+char(8,49773).
+char(2,49774).
+char(c,49775).
+char(m,49776).
+char(o,49777).
+char(4,49778).
+char(8,49779).
+char(0,49780).
+char(3,49781).
+char(p,49782).
+char(1,49783).
+char(4,49784).
+char(8,49785).
+char(2,49786).
+char(c,49787).
+char(m,49788).
+char(3,49789).
+char(3,49790).
+char(9,49791).
+char(6,49792).
+char(c,49793).
+char(c,49794).
+char(p,49795).
+char(o,49796).
+char(m,49797).
+char(o,49798).
+char(p,49799).
+char(o,49800).
+char(p,49801).
+char(6,49802).
+char(3,49803).
+char(4,49804).
+char(7,49805).
+char(m,49806).
+char(o,49807).
+char(m,49808).
+char(o,49809).
+char(o,49810).
+char(o,49811).
+char(m,49812).
+char(o,49813).
+char(p,49814).
+char(o,49815).
+char(p,49816).
+char(o,49817).
+char(5,49818).
+char(6,49819).
+char(8,49820).
+char(7,49821).
+char(p,49822).
+char(o,49823).
+char(p,49824).
+char(o,49825).
+char(p,49826).
+char(o,49827).
+char(p,49828).
+char(8,49829).
+char(8,49830).
+char(8,49831).
+char(2,49832).
+char(m,49833).
+char(o,49834).
+char(m,49835).
+char(o,49836).
+char(o,49837).
+char(9,49838).
+char(2,49839).
+char(3,49840).
+char(4,49841).
+char(c,49842).
+char(m,49843).
+char(o,49844).
+char(o,49845).
+char(p,49846).
+char(3,49847).
+char(7,49848).
+char(6,49849).
+char(0,49850).
+char(c,49851).
+char(c,49852).
+char(c,49853).
+char(c,49854).
+char(c,49855).
+char(c,49856).
+char(m,49857).
+char(8,49858).
+char(7,49859).
+char(0,49860).
+char(3,49861).
+char(m,49862).
+char(4,49863).
+char(3,49864).
+char(3,49865).
+char(9,49866).
+char(c,49867).
+char(m,49868).
+char(o,49869).
+char(4,49870).
+char(1,49871).
+char(3,49872).
+char(6,49873).
+char(c,49874).
+char(m,49875).
+char(o,49876).
+char(m,49877).
+char(o,49878).
+char(m,49879).
+char(7,49880).
+char(5,49881).
+char(1,49882).
+char(1,49883).
+char(p,49884).
+char(o,49885).
+char(m,49886).
+char(1,49887).
+char(0,49888).
+char(8,49889).
+char(4,49890).
+char(c,49891).
+char(p,49892).
+char(6,49893).
+char(0,49894).
+char(5,49895).
+char(7,49896).
+char(c,49897).
+char(c,49898).
+char(c,49899).
+char(c,49900).
+char(c,49901).
+char(c,49902).
+char(m,49903).
+char(3,49904).
+char(2,49905).
+char(6,49906).
+char(2,49907).
+char(c,49908).
+char(c,49909).
+char(m,49910).
+char(8,49911).
+char(4,49912).
+char(2,49913).
+char(6,49914).
+char(m,49915).
+char(8,49916).
+char(8,49917).
+char(1,49918).
+char(8,49919).
+char(c,49920).
+char(c,49921).
+char(c,49922).
+char(m,49923).
+char(2,49924).
+char(0,49925).
+char(7,49926).
+char(8,49927).
+char(c,49928).
+char(m,49929).
+char(9,49930).
+char(4,49931).
+char(1,49932).
+char(5,49933).
+char(c,49934).
+char(m,49935).
+char(o,49936).
+char(o,49937).
+char(m,49938).
+char(8,49939).
+char(4,49940).
+char(1,49941).
+char(0,49942).
+char(p,49943).
+char(o,49944).
+char(o,49945).
+char(p,49946).
+char(o,49947).
+char(o,49948).
+char(m,49949).
+char(o,49950).
+char(o,49951).
+char(m,49952).
+char(o,49953).
+char(p,49954).
+char(1,49955).
+char(9,49956).
+char(9,49957).
+char(7,49958).
+char(m,49959).
+char(o,49960).
+char(7,49961).
+char(9,49962).
+char(8,49963).
+char(1,49964).
+char(c,49965).
+char(p,49966).
+char(o,49967).
+char(m,49968).
+char(9,49969).
+char(2,49970).
+char(8,49971).
+char(8,49972).
+char(c,49973).
+char(c,49974).
+char(m,49975).
+char(o,49976).
+char(p,49977).
+char(o,49978).
+char(p,49979).
+char(o,49980).
+char(p,49981).
+char(9,49982).
+char(5,49983).
+char(4,49984).
+char(2,49985).
+char(p,49986).
+char(o,49987).
+char(8,49988).
+char(2,49989).
+char(6,49990).
+char(p,49991).
+char(o,49992).
+char(p,49993).
+char(o,49994).
+char(o,49995).
+char(m,49996).
+char(6,49997).
+char(9,49998).
+char(3,49999).
+char(9,50000).
+char(c,50001).
+char(p,50002).
+char(5,50003).
+char(4,50004).
+char(9,50005).
+char(5,50006).
+char(m,50007).
+char(o,50008).
+char(2,50009).
+char(0,50010).
+char(0,50011).
+char(5,50012).
+char(p,50013).
+char(9,50014).
+char(1,50015).
+char(2,50016).
+char(2,50017).
+char(p,50018).
+char(6,50019).
+char(6,50020).
+char(3,50021).
+char(3,50022).
+char(m,50023).
+char(o,50024).
+char(8,50025).
+char(1,50026).
+char(8,50027).
+char(7,50028).
+char(p,50029).
+char(o,50030).
+char(o,50031).
+char(p,50032).
+char(o,50033).
+char(p,50034).
+char(8,50035).
+char(8,50036).
+char(4,50037).
+char(6,50038).
+char(c,50039).
+char(c,50040).
+char(c,50041).
+char(m,50042).
+char(o,50043).
+char(8,50044).
+char(6,50045).
+char(2,50046).
+char(8,50047).
+char(p,50048).
+char(6,50049).
+char(2,50050).
+char(1,50051).
+char(7,50052).
+char(m,50053).
+char(o,50054).
+char(7,50055).
+char(4,50056).
+char(8,50057).
+char(2,50058).
+char(p,50059).
+char(4,50060).
+char(1,50061).
+char(4,50062).
+char(7,50063).
+char(p,50064).
+char(o,50065).
+char(p,50066).
+char(o,50067).
+char(m,50068).
+char(5,50069).
+char(7,50070).
+char(8,50071).
+char(m,50072).
+char(9,50073).
+char(6,50074).
+char(6,50075).
+char(5,50076).
+char(m,50077).
+char(5,50078).
+char(8,50079).
+char(5,50080).
+char(1,50081).
+char(p,50082).
+char(3,50083).
+char(6,50084).
+char(9,50085).
+char(p,50086).
+char(o,50087).
+char(p,50088).
+char(o,50089).
+char(p,50090).
+char(5,50091).
+char(3,50092).
+char(0,50093).
+char(5,50094).
+char(p,50095).
+char(o,50096).
+char(p,50097).
+char(o,50098).
+char(m,50099).
+char(3,50100).
+char(5,50101).
+char(2,50102).
+char(4,50103).
+char(m,50104).
+char(o,50105).
+char(9,50106).
+char(1,50107).
+char(4,50108).
+char(7,50109).
+char(c,50110).
+char(c,50111).
+char(m,50112).
+char(6,50113).
+char(4,50114).
+char(6,50115).
+char(8,50116).
+char(c,50117).
+char(c,50118).
+char(c,50119).
+char(p,50120).
+char(o,50121).
+char(p,50122).
+char(o,50123).
+char(p,50124).
+char(6,50125).
+char(6,50126).
+char(6,50127).
+char(2,50128).
+char(c,50129).
+char(p,50130).
+char(3,50131).
+char(4,50132).
+char(1,50133).
+char(0,50134).
+char(c,50135).
+char(m,50136).
+char(9,50137).
+char(2,50138).
+char(2,50139).
+char(8,50140).
+char(p,50141).
+char(o,50142).
+char(p,50143).
+char(2,50144).
+char(5,50145).
+char(0,50146).
+char(1,50147).
+char(m,50148).
+char(1,50149).
+char(9,50150).
+char(0,50151).
+char(7,50152).
+char(p,50153).
+char(o,50154).
+char(m,50155).
+char(o,50156).
+char(p,50157).
+char(o,50158).
+char(m,50159).
+char(9,50160).
+char(4,50161).
+char(9,50162).
+char(3,50163).
+char(c,50164).
+char(c,50165).
+char(p,50166).
+char(1,50167).
+char(3,50168).
+char(3,50169).
+char(0,50170).
+char(c,50171).
+char(m,50172).
+char(o,50173).
+char(p,50174).
+char(2,50175).
+char(4,50176).
+char(8,50177).
+char(p,50178).
+char(2,50179).
+char(7,50180).
+char(0,50181).
+char(3,50182).
+char(p,50183).
+char(7,50184).
+char(0,50185).
+char(3,50186).
+char(5,50187).
+char(c,50188).
+char(c,50189).
+char(p,50190).
+char(o,50191).
+char(m,50192).
+char(1,50193).
+char(7,50194).
+char(0,50195).
+char(9,50196).
+char(c,50197).
+char(p,50198).
+char(2,50199).
+char(8,50200).
+char(9,50201).
+char(p,50202).
+char(o,50203).
+char(m,50204).
+char(o,50205).
+char(m,50206).
+char(o,50207).
+char(o,50208).
+char(m,50209).
+char(9,50210).
+char(9,50211).
+char(9,50212).
+char(2,50213).
+char(c,50214).
+char(c,50215).
+char(m,50216).
+char(o,50217).
+char(p,50218).
+char(o,50219).
+char(m,50220).
+char(o,50221).
+char(p,50222).
+char(8,50223).
+char(6,50224).
+char(8,50225).
+char(0,50226).
+char(m,50227).
+char(3,50228).
+char(4,50229).
+char(2,50230).
+char(4,50231).
+char(m,50232).
+char(9,50233).
+char(7,50234).
+char(4,50235).
+char(4,50236).
+char(p,50237).
+char(8,50238).
+char(3,50239).
+char(4,50240).
+char(m,50241).
+char(9,50242).
+char(1,50243).
+char(3,50244).
+char(2,50245).
+char(c,50246).
+char(c,50247).
+char(m,50248).
+char(2,50249).
+char(6,50250).
+char(2,50251).
+char(4,50252).
+char(m,50253).
+char(4,50254).
+char(5,50255).
+char(1,50256).
+char(2,50257).
+char(p,50258).
+char(o,50259).
+char(m,50260).
+char(o,50261).
+char(m,50262).
+char(o,50263).
+char(o,50264).
+char(m,50265).
+char(o,50266).
+char(m,50267).
+char(6,50268).
+char(5,50269).
+char(6,50270).
+char(9,50271).
+char(p,50272).
+char(o,50273).
+char(p,50274).
+char(3,50275).
+char(9,50276).
+char(9,50277).
+char(c,50278).
+char(c,50279).
+char(c,50280).
+char(c,50281).
+char(c,50282).
+char(p,50283).
+char(3,50284).
+char(7,50285).
+char(0,50286).
+char(6,50287).
+char(c,50288).
+char(c,50289).
+char(c,50290).
+char(p,50291).
+char(o,50292).
+char(o,50293).
+char(3,50294).
+char(3,50295).
+char(3,50296).
+char(5,50297).
+char(c,50298).
+char(c,50299).
+char(c,50300).
+char(c,50301).
+char(m,50302).
+char(5,50303).
+char(3,50304).
+char(1,50305).
+char(8,50306).
+char(m,50307).
+char(o,50308).
+char(p,50309).
+char(4,50310).
+char(3,50311).
+char(9,50312).
+char(8,50313).
+char(c,50314).
+char(c,50315).
+char(c,50316).
+char(c,50317).
+char(m,50318).
+char(o,50319).
+char(p,50320).
+char(8,50321).
+char(1,50322).
+char(9,50323).
+char(4,50324).
+char(p,50325).
+char(3,50326).
+char(7,50327).
+char(4,50328).
+char(6,50329).
+char(m,50330).
+char(5,50331).
+char(1,50332).
+char(6,50333).
+char(5,50334).
+char(c,50335).
+char(c,50336).
+char(p,50337).
+char(o,50338).
+char(m,50339).
+char(o,50340).
+char(4,50341).
+char(8,50342).
+char(6,50343).
+char(0,50344).
+char(c,50345).
+char(m,50346).
+char(2,50347).
+char(1,50348).
+char(5,50349).
+char(6,50350).
+char(c,50351).
+char(m,50352).
+char(o,50353).
+char(9,50354).
+char(9,50355).
+char(1,50356).
+char(3,50357).
+char(c,50358).
+char(p,50359).
+char(o,50360).
+char(6,50361).
+char(8,50362).
+char(6,50363).
+char(5,50364).
+char(c,50365).
+char(m,50366).
+char(o,50367).
+char(m,50368).
+char(3,50369).
+char(4,50370).
+char(2,50371).
+char(m,50372).
+char(2,50373).
+char(1,50374).
+char(5,50375).
+char(8,50376).
+char(c,50377).
+char(c,50378).
+char(m,50379).
+char(1,50380).
+char(7,50381).
+char(1,50382).
+char(1,50383).
+char(c,50384).
+char(p,50385).
+char(8,50386).
+char(4,50387).
+char(7,50388).
+char(6,50389).
+char(m,50390).
+char(4,50391).
+char(2,50392).
+char(3,50393).
+char(9,50394).
+char(c,50395).
+char(p,50396).
+char(7,50397).
+char(1,50398).
+char(2,50399).
+char(c,50400).
+char(c,50401).
+char(m,50402).
+char(o,50403).
+char(m,50404).
+char(6,50405).
+char(7,50406).
+char(2,50407).
+char(0,50408).
+char(m,50409).
+char(o,50410).
+char(p,50411).
+char(o,50412).
+char(m,50413).
+char(4,50414).
+char(2,50415).
+char(4,50416).
+char(2,50417).
+char(c,50418).
+char(p,50419).
+char(4,50420).
+char(4,50421).
+char(2,50422).
+char(4,50423).
+char(p,50424).
+char(4,50425).
+char(4,50426).
+char(2,50427).
+char(1,50428).
+char(p,50429).
+char(1,50430).
+char(8,50431).
+char(0,50432).
+char(2,50433).
+char(m,50434).
+char(o,50435).
+char(3,50436).
+char(4,50437).
+char(2,50438).
+char(1,50439).
+char(c,50440).
+char(c,50441).
+char(c,50442).
+char(m,50443).
+char(4,50444).
+char(0,50445).
+char(0,50446).
+char(2,50447).
+char(c,50448).
+char(m,50449).
+char(9,50450).
+char(2,50451).
+char(3,50452).
+char(2,50453).
+char(c,50454).
+char(c,50455).
+char(c,50456).
+char(m,50457).
+char(4,50458).
+char(5,50459).
+char(6,50460).
+char(3,50461).
+char(p,50462).
+char(4,50463).
+char(3,50464).
+char(3,50465).
+char(2,50466).
+char(m,50467).
+char(1,50468).
+char(0,50469).
+char(1,50470).
+char(9,50471).
+char(c,50472).
+char(c,50473).
+char(c,50474).
+char(c,50475).
+char(c,50476).
+char(m,50477).
+char(8,50478).
+char(8,50479).
+char(7,50480).
+char(c,50481).
+char(c,50482).
+char(p,50483).
+char(5,50484).
+char(1,50485).
+char(4,50486).
+char(0,50487).
+char(c,50488).
+char(m,50489).
+char(o,50490).
+char(m,50491).
+char(o,50492).
+char(m,50493).
+char(o,50494).
+char(o,50495).
+char(p,50496).
+char(4,50497).
+char(9,50498).
+char(0,50499).
+char(8,50500).
+char(p,50501).
+char(9,50502).
+char(6,50503).
+char(3,50504).
+char(4,50505).
+char(m,50506).
+char(o,50507).
+char(p,50508).
+char(2,50509).
+char(2,50510).
+char(8,50511).
+char(9,50512).
+char(m,50513).
+char(2,50514).
+char(9,50515).
+char(7,50516).
+char(8,50517).
+char(m,50518).
+char(6,50519).
+char(7,50520).
+char(7,50521).
+char(9,50522).
+char(p,50523).
+char(3,50524).
+char(7,50525).
+char(1,50526).
+char(7,50527).
+char(c,50528).
+char(m,50529).
+char(6,50530).
+char(0,50531).
+char(8,50532).
+char(0,50533).
+char(m,50534).
+char(o,50535).
+char(p,50536).
+char(o,50537).
+char(p,50538).
+char(4,50539).
+char(6,50540).
+char(4,50541).
+char(6,50542).
+char(c,50543).
+char(m,50544).
+char(o,50545).
+char(p,50546).
+char(1,50547).
+char(4,50548).
+char(9,50549).
+char(5,50550).
+char(p,50551).
+char(o,50552).
+char(p,50553).
+char(o,50554).
+char(m,50555).
+char(o,50556).
+char(m,50557).
+char(o,50558).
+char(m,50559).
+char(5,50560).
+char(5,50561).
+char(4,50562).
+char(p,50563).
+char(1,50564).
+char(9,50565).
+char(7,50566).
+char(8,50567).
+char(m,50568).
+char(1,50569).
+char(5,50570).
+char(0,50571).
+char(2,50572).
+char(p,50573).
+char(5,50574).
+char(4,50575).
+char(6,50576).
+char(3,50577).
+char(m,50578).
+char(o,50579).
+char(p,50580).
+char(o,50581).
+char(m,50582).
+char(o,50583).
+char(5,50584).
+char(9,50585).
+char(6,50586).
+char(6,50587).
+char(p,50588).
+char(7,50589).
+char(2,50590).
+char(0,50591).
+char(2,50592).
+char(c,50593).
+char(p,50594).
+char(4,50595).
+char(9,50596).
+char(0,50597).
+char(8,50598).
+char(c,50599).
+char(c,50600).
+char(c,50601).
+char(m,50602).
+char(o,50603).
+char(p,50604).
+char(1,50605).
+char(4,50606).
+char(9,50607).
+char(6,50608).
+char(c,50609).
+char(c,50610).
+char(c,50611).
+char(c,50612).
+char(c,50613).
+char(c,50614).
+char(p,50615).
+char(o,50616).
+char(p,50617).
+char(1,50618).
+char(7,50619).
+char(1,50620).
+char(p,50621).
+char(o,50622).
+char(p,50623).
+char(o,50624).
+char(1,50625).
+char(2,50626).
+char(9,50627).
+char(3,50628).
+char(p,50629).
+char(o,50630).
+char(m,50631).
+char(o,50632).
+char(o,50633).
+char(3,50634).
+char(4,50635).
+char(7,50636).
+char(3,50637).
+char(c,50638).
+char(p,50639).
+char(o,50640).
+char(m,50641).
+char(1,50642).
+char(2,50643).
+char(5,50644).
+char(7,50645).
+char(c,50646).
+char(c,50647).
+char(c,50648).
+char(c,50649).
+char(p,50650).
+char(8,50651).
+char(5,50652).
+char(5,50653).
+char(4,50654).
+char(c,50655).
+char(c,50656).
+char(c,50657).
+char(c,50658).
+char(m,50659).
+char(7,50660).
+char(4,50661).
+char(7,50662).
+char(9,50663).
+char(c,50664).
+char(m,50665).
+char(o,50666).
+char(p,50667).
+char(4,50668).
+char(5,50669).
+char(1,50670).
+char(0,50671).
+char(m,50672).
+char(2,50673).
+char(1,50674).
+char(8,50675).
+char(6,50676).
+char(c,50677).
+char(c,50678).
+char(c,50679).
+char(p,50680).
+char(o,50681).
+char(o,50682).
+char(m,50683).
+char(o,50684).
+char(m,50685).
+char(2,50686).
+char(9,50687).
+char(9,50688).
+char(2,50689).
+char(p,50690).
+char(4,50691).
+char(6,50692).
+char(6,50693).
+char(8,50694).
+char(c,50695).
+char(p,50696).
+char(o,50697).
+char(p,50698).
+char(o,50699).
+char(m,50700).
+char(o,50701).
+char(m,50702).
+char(o,50703).
+char(m,50704).
+char(o,50705).
+char(m,50706).
+char(o,50707).
+char(m,50708).
+char(o,50709).
+char(p,50710).
+char(8,50711).
+char(5,50712).
+char(0,50713).
+char(6,50714).
+char(c,50715).
+char(p,50716).
+char(6,50717).
+char(1,50718).
+char(2,50719).
+char(4,50720).
+char(m,50721).
+char(3,50722).
+char(1,50723).
+char(4,50724).
+char(4,50725).
+char(m,50726).
+char(o,50727).
+char(p,50728).
+char(4,50729).
+char(2,50730).
+char(1,50731).
+char(4,50732).
+char(p,50733).
+char(o,50734).
+char(m,50735).
+char(o,50736).
+char(5,50737).
+char(9,50738).
+char(5,50739).
+char(m,50740).
+char(o,50741).
+char(p,50742).
+char(3,50743).
+char(4,50744).
+char(5,50745).
+char(2,50746).
+char(m,50747).
+char(7,50748).
+char(7,50749).
+char(5,50750).
+char(3,50751).
+char(c,50752).
+char(p,50753).
+char(o,50754).
+char(o,50755).
+char(p,50756).
+char(2,50757).
+char(0,50758).
+char(6,50759).
+char(3,50760).
+char(m,50761).
+char(o,50762).
+char(m,50763).
+char(o,50764).
+char(p,50765).
+char(7,50766).
+char(9,50767).
+char(5,50768).
+char(3,50769).
+char(p,50770).
+char(8,50771).
+char(4,50772).
+char(4,50773).
+char(9,50774).
+char(p,50775).
+char(o,50776).
+char(p,50777).
+char(o,50778).
+char(p,50779).
+char(6,50780).
+char(1,50781).
+char(8,50782).
+char(1,50783).
+char(m,50784).
+char(3,50785).
+char(9,50786).
+char(6,50787).
+char(4,50788).
+char(c,50789).
+char(c,50790).
+char(p,50791).
+char(o,50792).
+char(m,50793).
+char(o,50794).
+char(4,50795).
+char(7,50796).
+char(6,50797).
+char(4,50798).
+char(c,50799).
+char(m,50800).
+char(o,50801).
+char(9,50802).
+char(1,50803).
+char(7,50804).
+char(0,50805).
+char(m,50806).
+char(5,50807).
+char(2,50808).
+char(2,50809).
+char(p,50810).
+char(o,50811).
+char(m,50812).
+char(o,50813).
+char(m,50814).
+char(o,50815).
+char(m,50816).
+char(o,50817).
+char(m,50818).
+char(o,50819).
+char(p,50820).
+char(6,50821).
+char(5,50822).
+char(3,50823).
+char(4,50824).
+char(c,50825).
+char(c,50826).
+char(c,50827).
+char(c,50828).
+char(c,50829).
+char(c,50830).
+char(p,50831).
+char(o,50832).
+char(o,50833).
+char(m,50834).
+char(o,50835).
+char(o,50836).
+char(p,50837).
+char(o,50838).
+char(m,50839).
+char(o,50840).
+char(m,50841).
+char(o,50842).
+char(o,50843).
+char(o,50844).
+char(p,50845).
+char(6,50846).
+char(0,50847).
+char(9,50848).
+char(5,50849).
+char(m,50850).
+char(o,50851).
+char(p,50852).
+char(3,50853).
+char(4,50854).
+char(2,50855).
+char(9,50856).
+char(c,50857).
+char(c,50858).
+char(c,50859).
+char(c,50860).
+char(c,50861).
+char(p,50862).
+char(6,50863).
+char(5,50864).
+char(2,50865).
+char(8,50866).
+char(p,50867).
+char(1,50868).
+char(7,50869).
+char(7,50870).
+char(7,50871).
+char(c,50872).
+char(m,50873).
+char(o,50874).
+char(p,50875).
+char(3,50876).
+char(1,50877).
+char(4,50878).
+char(2,50879).
+char(p,50880).
+char(2,50881).
+char(0,50882).
+char(9,50883).
+char(5,50884).
+char(c,50885).
+char(c,50886).
+char(m,50887).
+char(o,50888).
+char(p,50889).
+char(o,50890).
+char(p,50891).
+char(o,50892).
+char(m,50893).
+char(o,50894).
+char(p,50895).
+char(3,50896).
+char(4,50897).
+char(6,50898).
+char(8,50899).
+char(c,50900).
+char(c,50901).
+char(m,50902).
+char(5,50903).
+char(0,50904).
+char(1,50905).
+char(3,50906).
+char(c,50907).
+char(c,50908).
+char(c,50909).
+char(c,50910).
+char(m,50911).
+char(o,50912).
+char(m,50913).
+char(8,50914).
+char(0,50915).
+char(9,50916).
+char(2,50917).
+char(c,50918).
+char(c,50919).
+char(p,50920).
+char(9,50921).
+char(4,50922).
+char(4,50923).
+char(5,50924).
+char(p,50925).
+char(6,50926).
+char(9,50927).
+char(3,50928).
+char(4,50929).
+char(c,50930).
+char(m,50931).
+char(4,50932).
+char(0,50933).
+char(9,50934).
+char(4,50935).
+char(p,50936).
+char(o,50937).
+char(2,50938).
+char(5,50939).
+char(0,50940).
+char(4,50941).
+char(c,50942).
+char(c,50943).
+char(m,50944).
+char(4,50945).
+char(5,50946).
+char(3,50947).
+char(2,50948).
+char(p,50949).
+char(9,50950).
+char(1,50951).
+char(1,50952).
+char(7,50953).
+char(c,50954).
+char(c,50955).
+char(c,50956).
+char(m,50957).
+char(o,50958).
+char(m,50959).
+char(o,50960).
+char(m,50961).
+char(o,50962).
+char(p,50963).
+char(o,50964).
+char(p,50965).
+char(o,50966).
+char(m,50967).
+char(o,50968).
+char(m,50969).
+char(o,50970).
+char(p,50971).
+char(7,50972).
+char(1,50973).
+char(6,50974).
+char(1,50975).
+char(m,50976).
+char(o,50977).
+char(p,50978).
+char(o,50979).
+char(6,50980).
+char(6,50981).
+char(0,50982).
+char(4,50983).
+char(c,50984).
+char(c,50985).
+char(c,50986).
+char(c,50987).
+char(c,50988).
+char(c,50989).
+char(c,50990).
+char(p,50991).
+char(o,50992).
+char(5,50993).
+char(7,50994).
+char(6,50995).
+char(2,50996).
+char(p,50997).
+char(9,50998).
+char(3,50999).
+char(0,51000).
+char(4,51001).
+char(c,51002).
+char(p,51003).
+char(o,51004).
+char(o,51005).
+char(o,51006).
+char(m,51007).
+char(2,51008).
+char(3,51009).
+char(3,51010).
+char(p,51011).
+char(9,51012).
+char(5,51013).
+char(1,51014).
+char(0,51015).
+char(c,51016).
+char(c,51017).
+char(m,51018).
+char(9,51019).
+char(2,51020).
+char(5,51021).
+char(3,51022).
+char(c,51023).
+char(p,51024).
+char(o,51025).
+char(p,51026).
+char(o,51027).
+char(p,51028).
+char(3,51029).
+char(1,51030).
+char(4,51031).
+char(1,51032).
+char(c,51033).
+char(m,51034).
+char(8,51035).
+char(8,51036).
+char(7,51037).
+char(7,51038).
+char(c,51039).
+char(c,51040).
+char(c,51041).
+char(m,51042).
+char(2,51043).
+char(2,51044).
+char(3,51045).
+char(0,51046).
+char(c,51047).
+char(m,51048).
+char(3,51049).
+char(8,51050).
+char(8,51051).
+char(c,51052).
+char(m,51053).
+char(o,51054).
+char(5,51055).
+char(5,51056).
+char(5,51057).
+char(2,51058).
+char(m,51059).
+char(8,51060).
+char(8,51061).
+char(3,51062).
+char(p,51063).
+char(6,51064).
+char(1,51065).
+char(0,51066).
+char(1,51067).
+char(m,51068).
+char(o,51069).
+char(p,51070).
+char(o,51071).
+char(4,51072).
+char(5,51073).
+char(9,51074).
+char(0,51075).
+char(c,51076).
+char(m,51077).
+char(o,51078).
+char(p,51079).
+char(5,51080).
+char(9,51081).
+char(6,51082).
+char(3,51083).
+char(m,51084).
+char(o,51085).
+char(p,51086).
+char(o,51087).
+char(m,51088).
+char(o,51089).
+char(p,51090).
+char(o,51091).
+char(m,51092).
+char(o,51093).
+char(p,51094).
+char(1,51095).
+char(5,51096).
+char(9,51097).
+char(1,51098).
+char(c,51099).
+char(p,51100).
+char(6,51101).
+char(9,51102).
+char(2,51103).
+char(6,51104).
+char(p,51105).
+char(o,51106).
+char(p,51107).
+char(9,51108).
+char(5,51109).
+char(7,51110).
+char(3,51111).
+char(m,51112).
+char(o,51113).
+char(5,51114).
+char(4,51115).
+char(8,51116).
+char(8,51117).
+char(m,51118).
+char(5,51119).
+char(2,51120).
+char(5,51121).
+char(6,51122).
+char(c,51123).
+char(m,51124).
+char(9,51125).
+char(4,51126).
+char(0,51127).
+char(1,51128).
+char(c,51129).
+char(p,51130).
+char(o,51131).
+char(m,51132).
+char(4,51133).
+char(9,51134).
+char(7,51135).
+char(8,51136).
+char(c,51137).
+char(c,51138).
+char(m,51139).
+char(6,51140).
+char(8,51141).
+char(9,51142).
+char(9,51143).
+char(p,51144).
+char(1,51145).
+char(0,51146).
+char(2,51147).
+char(3,51148).
+char(p,51149).
+char(7,51150).
+char(6,51151).
+char(0,51152).
+char(5,51153).
+char(p,51154).
+char(o,51155).
+char(p,51156).
+char(8,51157).
+char(0,51158).
+char(8,51159).
+char(8,51160).
+char(p,51161).
+char(o,51162).
+char(o,51163).
+char(p,51164).
+char(o,51165).
+char(o,51166).
+char(m,51167).
+char(2,51168).
+char(2,51169).
+char(4,51170).
+char(1,51171).
+char(c,51172).
+char(p,51173).
+char(o,51174).
+char(p,51175).
+char(o,51176).
+char(p,51177).
+char(9,51178).
+char(6,51179).
+char(9,51180).
+char(1,51181).
+char(m,51182).
+char(7,51183).
+char(3,51184).
+char(5,51185).
+char(2,51186).
+char(m,51187).
+char(1,51188).
+char(6,51189).
+char(7,51190).
+char(7,51191).
+char(c,51192).
+char(m,51193).
+char(o,51194).
+char(o,51195).
+char(p,51196).
+char(5,51197).
+char(2,51198).
+char(2,51199).
+char(9,51200).
+char(p,51201).
+char(4,51202).
+char(8,51203).
+char(0,51204).
+char(2,51205).
+char(p,51206).
+char(2,51207).
+char(9,51208).
+char(7,51209).
+char(9,51210).
+char(c,51211).
+char(p,51212).
+char(o,51213).
+char(m,51214).
+char(8,51215).
+char(9,51216).
+char(0,51217).
+char(c,51218).
+char(c,51219).
+char(m,51220).
+char(1,51221).
+char(4,51222).
+char(3,51223).
+char(9,51224).
+char(c,51225).
+char(m,51226).
+char(8,51227).
+char(5,51228).
+char(9,51229).
+char(1,51230).
+char(m,51231).
+char(1,51232).
+char(3,51233).
+char(1,51234).
+char(1,51235).
+char(p,51236).
+char(o,51237).
+char(p,51238).
+char(7,51239).
+char(8,51240).
+char(6,51241).
+char(8,51242).
+char(c,51243).
+char(m,51244).
+char(7,51245).
+char(2,51246).
+char(0,51247).
+char(9,51248).
+char(p,51249).
+char(o,51250).
+char(m,51251).
+char(o,51252).
+char(m,51253).
+char(o,51254).
+char(9,51255).
+char(3,51256).
+char(0,51257).
+char(3,51258).
+char(c,51259).
+char(c,51260).
+char(c,51261).
+char(m,51262).
+char(9,51263).
+char(0,51264).
+char(1,51265).
+char(5,51266).
+char(c,51267).
+char(m,51268).
+char(7,51269).
+char(5,51270).
+char(8,51271).
+char(c,51272).
+char(p,51273).
+char(6,51274).
+char(4,51275).
+char(2,51276).
+char(6,51277).
+char(p,51278).
+char(o,51279).
+char(o,51280).
+char(m,51281).
+char(o,51282).
+char(7,51283).
+char(1,51284).
+char(9,51285).
+char(3,51286).
+char(m,51287).
+char(3,51288).
+char(6,51289).
+char(4,51290).
+char(1,51291).
+char(c,51292).
+char(m,51293).
+char(3,51294).
+char(5,51295).
+char(4,51296).
+char(0,51297).
+char(c,51298).
+char(p,51299).
+char(o,51300).
+char(3,51301).
+char(8,51302).
+char(0,51303).
+char(3,51304).
+char(c,51305).
+char(c,51306).
+char(c,51307).
+char(c,51308).
+char(m,51309).
+char(1,51310).
+char(2,51311).
+char(7,51312).
+char(5,51313).
+char(p,51314).
+char(o,51315).
+char(m,51316).
+char(2,51317).
+char(2,51318).
+char(5,51319).
+char(2,51320).
+char(c,51321).
+char(m,51322).
+char(1,51323).
+char(9,51324).
+char(6,51325).
+char(c,51326).
+char(p,51327).
+char(o,51328).
+char(p,51329).
+char(o,51330).
+char(m,51331).
+char(7,51332).
+char(4,51333).
+char(5,51334).
+char(6,51335).
+char(c,51336).
+char(p,51337).
+char(1,51338).
+char(4,51339).
+char(2,51340).
+char(2,51341).
+char(m,51342).
+char(1,51343).
+char(4,51344).
+char(8,51345).
+char(c,51346).
+char(c,51347).
+char(c,51348).
+char(p,51349).
+char(o,51350).
+char(1,51351).
+char(8,51352).
+char(6,51353).
+char(7,51354).
+char(c,51355).
+char(p,51356).
+char(3,51357).
+char(2,51358).
+char(2,51359).
+char(6,51360).
+char(p,51361).
+char(o,51362).
+char(m,51363).
+char(6,51364).
+char(0,51365).
+char(4,51366).
+char(8,51367).
+char(c,51368).
+char(m,51369).
+char(o,51370).
+char(p,51371).
+char(1,51372).
+char(0,51373).
+char(m,51374).
+char(o,51375).
+char(p,51376).
+char(2,51377).
+char(0,51378).
+char(9,51379).
+char(7,51380).
+char(p,51381).
+char(4,51382).
+char(5,51383).
+char(3,51384).
+char(p,51385).
+char(o,51386).
+char(p,51387).
+char(2,51388).
+char(5,51389).
+char(9,51390).
+char(1,51391).
+char(m,51392).
+char(5,51393).
+char(1,51394).
+char(5,51395).
+char(1,51396).
+char(m,51397).
+char(1,51398).
+char(1,51399).
+char(4,51400).
+char(6,51401).
+char(c,51402).
+char(c,51403).
+char(p,51404).
+char(o,51405).
+char(p,51406).
+char(8,51407).
+char(7,51408).
+char(0,51409).
+char(1,51410).
+char(c,51411).
+char(m,51412).
+char(o,51413).
+char(p,51414).
+char(o,51415).
+char(m,51416).
+char(o,51417).
+char(m,51418).
+char(o,51419).
+char(p,51420).
+char(1,51421).
+char(4,51422).
+char(2,51423).
+char(8,51424).
+char(p,51425).
+char(5,51426).
+char(3,51427).
+char(0,51428).
+char(4,51429).
+char(p,51430).
+char(4,51431).
+char(8,51432).
+char(6,51433).
+char(p,51434).
+char(o,51435).
+char(p,51436).
+char(o,51437).
+char(o,51438).
+char(o,51439).
+char(m,51440).
+char(9,51441).
+char(0,51442).
+char(4,51443).
+char(8,51444).
+char(p,51445).
+char(o,51446).
+char(p,51447).
+char(3,51448).
+char(3,51449).
+char(4,51450).
+char(9,51451).
+char(p,51452).
+char(5,51453).
+char(4,51454).
+char(2,51455).
+char(8,51456).
+char(c,51457).
+char(c,51458).
+char(m,51459).
+char(9,51460).
+char(5,51461).
+char(2,51462).
+char(m,51463).
+char(6,51464).
+char(5,51465).
+char(0,51466).
+char(8,51467).
+char(c,51468).
+char(p,51469).
+char(3,51470).
+char(7,51471).
+char(5,51472).
+char(7,51473).
+char(m,51474).
+char(o,51475).
+char(p,51476).
+char(o,51477).
+char(6,51478).
+char(2,51479).
+char(4,51480).
+char(7,51481).
+char(m,51482).
+char(8,51483).
+char(7,51484).
+char(1,51485).
+char(2,51486).
+char(m,51487).
+char(8,51488).
+char(9,51489).
+char(3,51490).
+char(4,51491).
+char(c,51492).
+char(m,51493).
+char(o,51494).
+char(p,51495).
+char(o,51496).
+char(o,51497).
+char(m,51498).
+char(o,51499).
+char(p,51500).
+char(o,51501).
+char(6,51502).
+char(0,51503).
+char(0,51504).
+char(6,51505).
+char(c,51506).
+char(m,51507).
+char(9,51508).
+char(5,51509).
+char(3,51510).
+char(6,51511).
+char(p,51512).
+char(o,51513).
+char(o,51514).
+char(m,51515).
+char(1,51516).
+char(2,51517).
+char(2,51518).
+char(1,51519).
+char(m,51520).
+char(o,51521).
+char(m,51522).
+char(8,51523).
+char(9,51524).
+char(2,51525).
+char(2,51526).
+char(m,51527).
+char(o,51528).
+char(o,51529).
+char(o,51530).
+char(m,51531).
+char(o,51532).
+char(2,51533).
+char(0,51534).
+char(3,51535).
+char(0,51536).
+char(c,51537).
+char(c,51538).
+char(m,51539).
+char(o,51540).
+char(p,51541).
+char(o,51542).
+char(p,51543).
+char(o,51544).
+char(m,51545).
+char(2,51546).
+char(5,51547).
+char(2,51548).
+char(6,51549).
+char(c,51550).
+char(p,51551).
+char(2,51552).
+char(3,51553).
+char(0,51554).
+char(5,51555).
+char(m,51556).
+char(3,51557).
+char(5,51558).
+char(1,51559).
+char(2,51560).
+char(c,51561).
+char(c,51562).
+char(p,51563).
+char(o,51564).
+char(7,51565).
+char(4,51566).
+char(7,51567).
+char(7,51568).
+char(c,51569).
+char(c,51570).
+char(m,51571).
+char(9,51572).
+char(5,51573).
+char(2,51574).
+char(5,51575).
+char(c,51576).
+char(c,51577).
+char(c,51578).
+char(c,51579).
+char(p,51580).
+char(o,51581).
+char(p,51582).
+char(9,51583).
+char(3,51584).
+char(7,51585).
+char(9,51586).
+char(c,51587).
+char(c,51588).
+char(p,51589).
+char(o,51590).
+char(m,51591).
+char(o,51592).
+char(o,51593).
+char(p,51594).
+char(o,51595).
+char(p,51596).
+char(2,51597).
+char(2,51598).
+char(3,51599).
+char(2,51600).
+char(p,51601).
+char(1,51602).
+char(9,51603).
+char(4,51604).
+char(6,51605).
+char(m,51606).
+char(o,51607).
+char(m,51608).
+char(9,51609).
+char(1,51610).
+char(8,51611).
+char(2,51612).
+char(c,51613).
+char(m,51614).
+char(o,51615).
+char(p,51616).
+char(o,51617).
+char(o,51618).
+char(o,51619).
+char(p,51620).
+char(4,51621).
+char(5,51622).
+char(2,51623).
+char(7,51624).
+char(c,51625).
+char(m,51626).
+char(o,51627).
+char(2,51628).
+char(3,51629).
+char(2,51630).
+char(2,51631).
+char(m,51632).
+char(1,51633).
+char(4,51634).
+char(4,51635).
+char(3,51636).
+char(m,51637).
+char(4,51638).
+char(8,51639).
+char(3,51640).
+char(p,51641).
+char(3,51642).
+char(7,51643).
+char(0,51644).
+char(8,51645).
+char(m,51646).
+char(o,51647).
+char(m,51648).
+char(o,51649).
+char(4,51650).
+char(2,51651).
+char(3,51652).
+char(2,51653).
+char(p,51654).
+char(o,51655).
+char(m,51656).
+char(o,51657).
+char(o,51658).
+char(p,51659).
+char(8,51660).
+char(7,51661).
+char(6,51662).
+char(6,51663).
+char(m,51664).
+char(1,51665).
+char(6,51666).
+char(3,51667).
+char(3,51668).
+char(p,51669).
+char(o,51670).
+char(p,51671).
+char(7,51672).
+char(5,51673).
+char(8,51674).
+char(9,51675).
+char(c,51676).
+char(p,51677).
+char(o,51678).
+char(o,51679).
+char(o,51680).
+char(m,51681).
+char(o,51682).
+char(6,51683).
+char(2,51684).
+char(4,51685).
+char(2,51686).
+char(p,51687).
+char(7,51688).
+char(6,51689).
+char(9,51690).
+char(9,51691).
+char(m,51692).
+char(o,51693).
+char(4,51694).
+char(3,51695).
+char(8,51696).
+char(1,51697).
+char(m,51698).
+char(5,51699).
+char(0,51700).
+char(3,51701).
+char(1,51702).
+char(p,51703).
+char(7,51704).
+char(2,51705).
+char(4,51706).
+char(7,51707).
+char(p,51708).
+char(9,51709).
+char(5,51710).
+char(4,51711).
+char(7,51712).
+char(p,51713).
+char(o,51714).
+char(p,51715).
+char(1,51716).
+char(9,51717).
+char(3,51718).
+char(5,51719).
+char(c,51720).
+char(c,51721).
+char(c,51722).
+char(m,51723).
+char(9,51724).
+char(6,51725).
+char(2,51726).
+char(4,51727).
+char(m,51728).
+char(2,51729).
+char(4,51730).
+char(8,51731).
+char(4,51732).
+char(p,51733).
+char(5,51734).
+char(4,51735).
+char(3,51736).
+char(0,51737).
+char(c,51738).
+char(c,51739).
+char(m,51740).
+char(o,51741).
+char(m,51742).
+char(9,51743).
+char(9,51744).
+char(1,51745).
+char(3,51746).
+char(c,51747).
+char(c,51748).
+char(p,51749).
+char(2,51750).
+char(2,51751).
+char(1,51752).
+char(p,51753).
+char(3,51754).
+char(0,51755).
+char(9,51756).
+char(3,51757).
+char(c,51758).
+char(c,51759).
+char(m,51760).
+char(o,51761).
+char(9,51762).
+char(2,51763).
+char(2,51764).
+char(8,51765).
+char(m,51766).
+char(5,51767).
+char(7,51768).
+char(7,51769).
+char(3,51770).
+char(p,51771).
+char(o,51772).
+char(p,51773).
+char(6,51774).
+char(1,51775).
+char(7,51776).
+char(3,51777).
+char(c,51778).
+char(c,51779).
+char(m,51780).
+char(3,51781).
+char(7,51782).
+char(5,51783).
+char(0,51784).
+char(c,51785).
+char(c,51786).
+char(p,51787).
+char(8,51788).
+char(0,51789).
+char(1,51790).
+char(5,51791).
+char(m,51792).
+char(o,51793).
+char(m,51794).
+char(8,51795).
+char(2,51796).
+char(7,51797).
+char(0,51798).
+char(c,51799).
+char(m,51800).
+char(o,51801).
+char(p,51802).
+char(8,51803).
+char(8,51804).
+char(7,51805).
+char(2,51806).
+char(m,51807).
+char(3,51808).
+char(8,51809).
+char(1,51810).
+char(2,51811).
+char(c,51812).
+char(c,51813).
+char(c,51814).
+char(m,51815).
+char(o,51816).
+char(p,51817).
+char(o,51818).
+char(m,51819).
+char(4,51820).
+char(5,51821).
+char(9,51822).
+char(2,51823).
+char(c,51824).
+char(m,51825).
+char(8,51826).
+char(4,51827).
+char(9,51828).
+char(6,51829).
+char(m,51830).
+char(6,51831).
+char(2,51832).
+char(5,51833).
+char(3,51834).
+char(m,51835).
+char(7,51836).
+char(6,51837).
+char(4,51838).
+char(m,51839).
+char(9,51840).
+char(1,51841).
+char(5,51842).
+char(8,51843).
+char(p,51844).
+char(3,51845).
+char(6,51846).
+char(9,51847).
+char(2,51848).
+char(c,51849).
+char(c,51850).
+char(c,51851).
+char(m,51852).
+char(1,51853).
+char(7,51854).
+char(6,51855).
+char(0,51856).
+char(p,51857).
+char(o,51858).
+char(m,51859).
+char(o,51860).
+char(7,51861).
+char(8,51862).
+char(8,51863).
+char(0,51864).
+char(p,51865).
+char(o,51866).
+char(m,51867).
+char(o,51868).
+char(p,51869).
+char(o,51870).
+char(m,51871).
+char(9,51872).
+char(6,51873).
+char(5,51874).
+char(1,51875).
+char(p,51876).
+char(8,51877).
+char(2,51878).
+char(2,51879).
+char(8,51880).
+char(c,51881).
+char(m,51882).
+char(o,51883).
+char(p,51884).
+char(9,51885).
+char(7,51886).
+char(7,51887).
+char(2,51888).
+char(c,51889).
+char(m,51890).
+char(1,51891).
+char(1,51892).
+char(9,51893).
+char(m,51894).
+char(o,51895).
+char(p,51896).
+char(o,51897).
+char(3,51898).
+char(8,51899).
+char(5,51900).
+char(6,51901).
+char(c,51902).
+char(c,51903).
+char(m,51904).
+char(o,51905).
+char(o,51906).
+char(6,51907).
+char(6,51908).
+char(3,51909).
+char(6,51910).
+char(m,51911).
+char(o,51912).
+char(m,51913).
+char(o,51914).
+char(p,51915).
+char(8,51916).
+char(8,51917).
+char(9,51918).
+char(6,51919).
+char(c,51920).
+char(p,51921).
+char(9,51922).
+char(6,51923).
+char(4,51924).
+char(3,51925).
+char(c,51926).
+char(c,51927).
+char(c,51928).
+char(c,51929).
+char(c,51930).
+char(c,51931).
+char(c,51932).
+char(m,51933).
+char(6,51934).
+char(6,51935).
+char(8,51936).
+char(1,51937).
+char(c,51938).
+char(c,51939).
+char(c,51940).
+char(m,51941).
+char(6,51942).
+char(3,51943).
+char(6,51944).
+char(4,51945).
+char(m,51946).
+char(6,51947).
+char(4,51948).
+char(5,51949).
+char(0,51950).
+char(m,51951).
+char(o,51952).
+char(m,51953).
+char(8,51954).
+char(0,51955).
+char(5,51956).
+char(7,51957).
+char(p,51958).
+char(o,51959).
+char(m,51960).
+char(4,51961).
+char(2,51962).
+char(6,51963).
+char(4,51964).
+char(c,51965).
+char(p,51966).
+char(2,51967).
+char(1,51968).
+char(1,51969).
+char(0,51970).
+char(p,51971).
+char(o,51972).
+char(m,51973).
+char(o,51974).
+char(m,51975).
+char(o,51976).
+char(m,51977).
+char(o,51978).
+char(m,51979).
+char(5,51980).
+char(1,51981).
+char(5,51982).
+char(9,51983).
+char(m,51984).
+char(o,51985).
+char(p,51986).
+char(7,51987).
+char(9,51988).
+char(1,51989).
+char(8,51990).
+char(c,51991).
+char(m,51992).
+char(1,51993).
+char(6,51994).
+char(3,51995).
+char(8,51996).
+char(c,51997).
+char(c,51998).
+char(c,51999).
+char(m,52000).
+char(2,52001).
+char(0,52002).
+char(1,52003).
+char(5,52004).
+char(p,52005).
+char(2,52006).
+char(9,52007).
+char(7,52008).
+char(0,52009).
+char(c,52010).
+char(c,52011).
+char(c,52012).
+char(p,52013).
+char(1,52014).
+char(6,52015).
+char(4,52016).
+char(4,52017).
+char(p,52018).
+char(o,52019).
+char(o,52020).
+char(m,52021).
+char(o,52022).
+char(p,52023).
+char(4,52024).
+char(6,52025).
+char(3,52026).
+char(3,52027).
+char(c,52028).
+char(p,52029).
+char(o,52030).
+char(m,52031).
+char(o,52032).
+char(o,52033).
+char(m,52034).
+char(1,52035).
+char(8,52036).
+char(3,52037).
+char(5,52038).
+char(m,52039).
+char(o,52040).
+char(m,52041).
+char(8,52042).
+char(6,52043).
+char(2,52044).
+char(4,52045).
+char(p,52046).
+char(8,52047).
+char(3,52048).
+char(1,52049).
+char(9,52050).
+char(p,52051).
+char(o,52052).
+char(m,52053).
+char(o,52054).
+char(o,52055).
+char(o,52056).
+char(p,52057).
+char(o,52058).
+char(m,52059).
+char(o,52060).
+char(m,52061).
+char(3,52062).
+char(7,52063).
+char(7,52064).
+char(9,52065).
+char(p,52066).
+char(o,52067).
+char(m,52068).
+char(6,52069).
+char(1,52070).
+char(7,52071).
+char(6,52072).
+char(c,52073).
+char(c,52074).
+char(m,52075).
+char(2,52076).
+char(6,52077).
+char(9,52078).
+char(1,52079).
+char(c,52080).
+char(p,52081).
+char(o,52082).
+char(p,52083).
+char(9,52084).
+char(5,52085).
+char(9,52086).
+char(1,52087).
+char(p,52088).
+char(8,52089).
+char(7,52090).
+char(8,52091).
+char(4,52092).
+char(m,52093).
+char(o,52094).
+char(o,52095).
+char(m,52096).
+char(2,52097).
+char(1,52098).
+char(5,52099).
+char(1,52100).
+char(m,52101).
+char(o,52102).
+char(o,52103).
+char(9,52104).
+char(1,52105).
+char(1,52106).
+char(4,52107).
+char(m,52108).
+char(o,52109).
+char(5,52110).
+char(9,52111).
+char(3,52112).
+char(1,52113).
+char(c,52114).
+char(p,52115).
+char(o,52116).
+char(p,52117).
+char(o,52118).
+char(m,52119).
+char(6,52120).
+char(9,52121).
+char(5,52122).
+char(3,52123).
+char(c,52124).
+char(c,52125).
+char(m,52126).
+char(4,52127).
+char(4,52128).
+char(3,52129).
+char(2,52130).
+char(p,52131).
+char(2,52132).
+char(3,52133).
+char(8,52134).
+char(4,52135).
+char(c,52136).
+char(c,52137).
+char(c,52138).
+char(c,52139).
+char(c,52140).
+char(c,52141).
+char(m,52142).
+char(o,52143).
+char(o,52144).
+char(o,52145).
+char(p,52146).
+char(o,52147).
+char(p,52148).
+char(o,52149).
+char(m,52150).
+char(8,52151).
+char(7,52152).
+char(0,52153).
+char(5,52154).
+char(c,52155).
+char(m,52156).
+char(o,52157).
+char(6,52158).
+char(8,52159).
+char(8,52160).
+char(6,52161).
+char(p,52162).
+char(5,52163).
+char(4,52164).
+char(2,52165).
+char(2,52166).
+char(c,52167).
+char(p,52168).
+char(o,52169).
+char(1,52170).
+char(4,52171).
+char(1,52172).
+char(5,52173).
+char(p,52174).
+char(o,52175).
+char(2,52176).
+char(3,52177).
+char(1,52178).
+char(2,52179).
+char(m,52180).
+char(4,52181).
+char(3,52182).
+char(0,52183).
+char(3,52184).
+char(c,52185).
+char(p,52186).
+char(o,52187).
+char(m,52188).
+char(o,52189).
+char(m,52190).
+char(2,52191).
+char(0,52192).
+char(0,52193).
+char(6,52194).
+char(c,52195).
+char(c,52196).
+char(p,52197).
+char(o,52198).
+char(o,52199).
+char(p,52200).
+char(9,52201).
+char(9,52202).
+char(6,52203).
+char(0,52204).
+char(c,52205).
+char(c,52206).
+char(p,52207).
+char(9,52208).
+char(2,52209).
+char(6,52210).
+char(9,52211).
+char(c,52212).
+char(m,52213).
+char(o,52214).
+char(2,52215).
+char(5,52216).
+char(6,52217).
+char(9,52218).
+char(c,52219).
+char(c,52220).
+char(p,52221).
+char(o,52222).
+char(o,52223).
+char(m,52224).
+char(o,52225).
+char(p,52226).
+char(4,52227).
+char(7,52228).
+char(6,52229).
+char(3,52230).
+char(c,52231).
+char(m,52232).
+char(o,52233).
+char(p,52234).
+char(o,52235).
+char(o,52236).
+char(5,52237).
+char(7,52238).
+char(2,52239).
+char(6,52240).
+char(m,52241).
+char(2,52242).
+char(8,52243).
+char(4,52244).
+char(0,52245).
+char(p,52246).
+char(3,52247).
+char(6,52248).
+char(6,52249).
+char(2,52250).
+char(m,52251).
+char(4,52252).
+char(8,52253).
+char(4,52254).
+char(1,52255).
+char(p,52256).
+char(5,52257).
+char(5,52258).
+char(3,52259).
+char(2,52260).
+char(p,52261).
+char(1,52262).
+char(7,52263).
+char(4,52264).
+char(8,52265).
+char(c,52266).
+char(m,52267).
+char(o,52268).
+char(8,52269).
+char(7,52270).
+char(6,52271).
+char(1,52272).
+char(c,52273).
+char(p,52274).
+char(o,52275).
+char(p,52276).
+char(6,52277).
+char(4,52278).
+char(0,52279).
+char(9,52280).
+char(c,52281).
+char(c,52282).
+char(c,52283).
+char(p,52284).
+char(8,52285).
+char(9,52286).
+char(2,52287).
+char(0,52288).
+char(c,52289).
+char(c,52290).
+char(c,52291).
+char(m,52292).
+char(o,52293).
+char(o,52294).
+char(o,52295).
+char(p,52296).
+char(o,52297).
+char(p,52298).
+char(o,52299).
+char(m,52300).
+char(o,52301).
+char(m,52302).
+char(o,52303).
+char(8,52304).
+char(9,52305).
+char(1,52306).
+char(5,52307).
+char(c,52308).
+char(c,52309).
+char(m,52310).
+char(o,52311).
+char(p,52312).
+char(o,52313).
+char(9,52314).
+char(0,52315).
+char(6,52316).
+char(0,52317).
+char(c,52318).
+char(c,52319).
+char(m,52320).
+char(8,52321).
+char(5,52322).
+char(4,52323).
+char(3,52324).
+char(m,52325).
+char(1,52326).
+char(1,52327).
+char(5,52328).
+char(4,52329).
+char(c,52330).
+char(c,52331).
+char(p,52332).
+char(o,52333).
+char(2,52334).
+char(8,52335).
+char(5,52336).
+char(7,52337).
+char(m,52338).
+char(o,52339).
+char(7,52340).
+char(6,52341).
+char(1,52342).
+char(6,52343).
+char(c,52344).
+char(p,52345).
+char(4,52346).
+char(0,52347).
+char(2,52348).
+char(8,52349).
+char(m,52350).
+char(o,52351).
+char(m,52352).
+char(o,52353).
+char(2,52354).
+char(9,52355).
+char(4,52356).
+char(3,52357).
+char(c,52358).
+char(c,52359).
+char(m,52360).
+char(o,52361).
+char(8,52362).
+char(4,52363).
+char(1,52364).
+char(0,52365).
+char(p,52366).
+char(1,52367).
+char(0,52368).
+char(6,52369).
+char(8,52370).
+char(c,52371).
+char(p,52372).
+char(o,52373).
+char(m,52374).
+char(o,52375).
+char(m,52376).
+char(o,52377).
+char(2,52378).
+char(2,52379).
+char(2,52380).
+char(2,52381).
+char(m,52382).
+char(o,52383).
+char(5,52384).
+char(4,52385).
+char(2,52386).
+char(1,52387).
+char(m,52388).
+char(9,52389).
+char(9,52390).
+char(0,52391).
+char(3,52392).
+char(p,52393).
+char(5,52394).
+char(8,52395).
+char(8,52396).
+char(3,52397).
+char(c,52398).
+char(c,52399).
+char(m,52400).
+char(o,52401).
+char(p,52402).
+char(o,52403).
+char(1,52404).
+char(9,52405).
+char(5,52406).
+char(8,52407).
+char(p,52408).
+char(2,52409).
+char(6,52410).
+char(2,52411).
+char(8,52412).
+char(m,52413).
+char(o,52414).
+char(m,52415).
+char(9,52416).
+char(3,52417).
+char(4,52418).
+char(3,52419).
+char(p,52420).
+char(o,52421).
+char(p,52422).
+char(o,52423).
+char(o,52424).
+char(o,52425).
+char(p,52426).
+char(7,52427).
+char(4,52428).
+char(5,52429).
+char(7,52430).
+char(m,52431).
+char(5,52432).
+char(3,52433).
+char(8,52434).
+char(6,52435).
+char(c,52436).
+char(c,52437).
+char(c,52438).
+char(c,52439).
+char(c,52440).
+char(m,52441).
+char(o,52442).
+char(o,52443).
+char(p,52444).
+char(o,52445).
+char(p,52446).
+char(7,52447).
+char(2,52448).
+char(7,52449).
+char(0,52450).
+char(p,52451).
+char(1,52452).
+char(3,52453).
+char(3,52454).
+char(2,52455).
+char(p,52456).
+char(o,52457).
+char(p,52458).
+char(7,52459).
+char(3,52460).
+char(9,52461).
+char(4,52462).
+char(c,52463).
+char(c,52464).
+char(m,52465).
+char(9,52466).
+char(9,52467).
+char(8,52468).
+char(7,52469).
+char(p,52470).
+char(7,52471).
+char(6,52472).
+char(1,52473).
+char(7,52474).
+char(p,52475).
+char(o,52476).
+char(m,52477).
+char(5,52478).
+char(1,52479).
+char(1,52480).
+char(8,52481).
+char(p,52482).
+char(9,52483).
+char(8,52484).
+char(9,52485).
+char(2,52486).
+char(c,52487).
+char(p,52488).
+char(2,52489).
+char(9,52490).
+char(8,52491).
+char(5,52492).
+char(c,52493).
+char(c,52494).
+char(c,52495).
+char(m,52496).
+char(3,52497).
+char(9,52498).
+char(7,52499).
+char(c,52500).
+char(c,52501).
+char(m,52502).
+char(o,52503).
+char(p,52504).
+char(6,52505).
+char(2,52506).
+char(9,52507).
+char(8,52508).
+char(m,52509).
+char(4,52510).
+char(3,52511).
+char(6,52512).
+char(p,52513).
+char(7,52514).
+char(2,52515).
+char(6,52516).
+char(6,52517).
+char(c,52518).
+char(p,52519).
+char(o,52520).
+char(p,52521).
+char(8,52522).
+char(3,52523).
+char(6,52524).
+char(2,52525).
+char(m,52526).
+char(4,52527).
+char(7,52528).
+char(2,52529).
+char(8,52530).
+char(c,52531).
+char(p,52532).
+char(o,52533).
+char(9,52534).
+char(5,52535).
+char(4,52536).
+char(0,52537).
+char(c,52538).
+char(p,52539).
+char(9,52540).
+char(8,52541).
+char(7,52542).
+char(6,52543).
+char(c,52544).
+char(m,52545).
+char(o,52546).
+char(o,52547).
+char(m,52548).
+char(5,52549).
+char(7,52550).
+char(8,52551).
+char(p,52552).
+char(2,52553).
+char(4,52554).
+char(2,52555).
+char(4,52556).
+char(p,52557).
+char(o,52558).
+char(p,52559).
+char(o,52560).
+char(m,52561).
+char(o,52562).
+char(m,52563).
+char(o,52564).
+char(1,52565).
+char(0,52566).
+char(1,52567).
+char(3,52568).
+char(p,52569).
+char(o,52570).
+char(p,52571).
+char(7,52572).
+char(5,52573).
+char(5,52574).
+char(c,52575).
+char(c,52576).
+char(c,52577).
+char(c,52578).
+char(p,52579).
+char(o,52580).
+char(p,52581).
+char(o,52582).
+char(p,52583).
+char(o,52584).
+char(m,52585).
+char(8,52586).
+char(1,52587).
+char(3,52588).
+char(m,52589).
+char(2,52590).
+char(3,52591).
+char(2,52592).
+char(7,52593).
+char(c,52594).
+char(m,52595).
+char(4,52596).
+char(0,52597).
+char(0,52598).
+char(3,52599).
+char(m,52600).
+char(o,52601).
+char(m,52602).
+char(o,52603).
+char(6,52604).
+char(3,52605).
+char(9,52606).
+char(7,52607).
+char(c,52608).
+char(p,52609).
+char(o,52610).
+char(m,52611).
+char(o,52612).
+char(m,52613).
+char(o,52614).
+char(o,52615).
+char(p,52616).
+char(2,52617).
+char(1,52618).
+char(9,52619).
+char(0,52620).
+char(m,52621).
+char(o,52622).
+char(p,52623).
+char(9,52624).
+char(4,52625).
+char(8,52626).
+char(2,52627).
+char(m,52628).
+char(2,52629).
+char(6,52630).
+char(9,52631).
+char(6,52632).
+char(p,52633).
+char(8,52634).
+char(3,52635).
+char(4,52636).
+char(8,52637).
+char(m,52638).
+char(8,52639).
+char(9,52640).
+char(0,52641).
+char(3,52642).
+char(m,52643).
+char(o,52644).
+char(p,52645).
+char(o,52646).
+char(p,52647).
+char(1,52648).
+char(7,52649).
+char(3,52650).
+char(7,52651).
+char(m,52652).
+char(8,52653).
+char(9,52654).
+char(4,52655).
+char(5,52656).
+char(p,52657).
+char(7,52658).
+char(9,52659).
+char(3,52660).
+char(c,52661).
+char(c,52662).
+char(m,52663).
+char(o,52664).
+char(p,52665).
+char(9,52666).
+char(4,52667).
+char(8,52668).
+char(c,52669).
+char(m,52670).
+char(o,52671).
+char(o,52672).
+char(o,52673).
+char(p,52674).
+char(o,52675).
+char(4,52676).
+char(6,52677).
+char(8,52678).
+char(1,52679).
+char(c,52680).
+char(m,52681).
+char(o,52682).
+char(p,52683).
+char(o,52684).
+char(m,52685).
+char(o,52686).
+char(m,52687).
+char(o,52688).
+char(o,52689).
+char(p,52690).
+char(1,52691).
+char(2,52692).
+char(3,52693).
+char(6,52694).
+char(p,52695).
+char(o,52696).
+char(m,52697).
+char(4,52698).
+char(2,52699).
+char(4,52700).
+char(6,52701).
+char(m,52702).
+char(6,52703).
+char(3,52704).
+char(7,52705).
+char(3,52706).
+char(p,52707).
+char(o,52708).
+char(p,52709).
+char(o,52710).
+char(m,52711).
+char(2,52712).
+char(9,52713).
+char(0,52714).
+char(p,52715).
+char(o,52716).
+char(p,52717).
+char(5,52718).
+char(1,52719).
+char(8,52720).
+char(p,52721).
+char(o,52722).
+char(o,52723).
+char(p,52724).
+char(4,52725).
+char(2,52726).
+char(7,52727).
+char(9,52728).
+char(c,52729).
+char(p,52730).
+char(1,52731).
+char(4,52732).
+char(1,52733).
+char(3,52734).
+char(p,52735).
+char(o,52736).
+char(2,52737).
+char(0,52738).
+char(2,52739).
+char(2,52740).
+char(p,52741).
+char(o,52742).
+char(p,52743).
+char(o,52744).
+char(m,52745).
+char(o,52746).
+char(m,52747).
+char(3,52748).
+char(1,52749).
+char(1,52750).
+char(c,52751).
+char(c,52752).
+char(p,52753).
+char(o,52754).
+char(p,52755).
+char(o,52756).
+char(p,52757).
+char(5,52758).
+char(5,52759).
+char(8,52760).
+char(c,52761).
+char(c,52762).
+char(c,52763).
+char(c,52764).
+char(m,52765).
+char(5,52766).
+char(7,52767).
+char(7,52768).
+char(p,52769).
+char(9,52770).
+char(5,52771).
+char(0,52772).
+char(m,52773).
+char(o,52774).
+char(9,52775).
+char(4,52776).
+char(3,52777).
+char(9,52778).
+char(m,52779).
+char(o,52780).
+char(o,52781).
+char(m,52782).
+char(1,52783).
+char(3,52784).
+char(6,52785).
+char(6,52786).
+char(c,52787).
+char(m,52788).
+char(o,52789).
+char(p,52790).
+char(o,52791).
+char(p,52792).
+char(6,52793).
+char(3,52794).
+char(6,52795).
+char(m,52796).
+char(9,52797).
+char(4,52798).
+char(4,52799).
+char(0,52800).
+char(c,52801).
+char(m,52802).
+char(8,52803).
+char(8,52804).
+char(7,52805).
+char(p,52806).
+char(3,52807).
+char(8,52808).
+char(4,52809).
+char(4,52810).
+char(c,52811).
+char(c,52812).
+char(c,52813).
+char(m,52814).
+char(o,52815).
+char(m,52816).
+char(o,52817).
+char(o,52818).
+char(p,52819).
+char(o,52820).
+char(m,52821).
+char(o,52822).
+char(p,52823).
+char(3,52824).
+char(7,52825).
+char(3,52826).
+char(3,52827).
+char(c,52828).
+char(m,52829).
+char(5,52830).
+char(0,52831).
+char(6,52832).
+char(3,52833).
+char(c,52834).
+char(c,52835).
+char(c,52836).
+char(p,52837).
+char(1,52838).
+char(6,52839).
+char(4,52840).
+char(5,52841).
+char(p,52842).
+char(o,52843).
+char(m,52844).
+char(7,52845).
+char(7,52846).
+char(4,52847).
+char(1,52848).
+char(p,52849).
+char(9,52850).
+char(3,52851).
+char(3,52852).
+char(4,52853).
+char(c,52854).
+char(p,52855).
+char(o,52856).
+char(m,52857).
+char(o,52858).
+char(p,52859).
+char(o,52860).
+char(m,52861).
+char(o,52862).
+char(o,52863).
+char(m,52864).
+char(9,52865).
+char(2,52866).
+char(9,52867).
+char(4,52868).
+char(m,52869).
+char(o,52870).
+char(p,52871).
+char(o,52872).
+char(3,52873).
+char(1,52874).
+char(0,52875).
+char(7,52876).
+char(c,52877).
+char(c,52878).
+char(c,52879).
+char(c,52880).
+char(m,52881).
+char(o,52882).
+char(m,52883).
+char(o,52884).
+char(m,52885).
+char(1,52886).
+char(0,52887).
+char(7,52888).
+char(9,52889).
+char(c,52890).
+char(m,52891).
+char(o,52892).
+char(m,52893).
+char(o,52894).
+char(p,52895).
+char(5,52896).
+char(6,52897).
+char(7,52898).
+char(2,52899).
+char(p,52900).
+char(1,52901).
+char(4,52902).
+char(2,52903).
+char(3,52904).
+char(m,52905).
+char(7,52906).
+char(1,52907).
+char(2,52908).
+char(3,52909).
+char(p,52910).
+char(5,52911).
+char(3,52912).
+char(5,52913).
+char(1,52914).
+char(p,52915).
+char(6,52916).
+char(7,52917).
+char(0,52918).
+char(4,52919).
+char(c,52920).
+char(p,52921).
+char(o,52922).
+char(p,52923).
+char(4,52924).
+char(8,52925).
+char(9,52926).
+char(5,52927).
+char(p,52928).
+char(o,52929).
+char(p,52930).
+char(o,52931).
+char(m,52932).
+char(9,52933).
+char(6,52934).
+char(7,52935).
+char(4,52936).
+char(p,52937).
+char(4,52938).
+char(4,52939).
+char(1,52940).
+char(9,52941).
+char(c,52942).
+char(c,52943).
+char(c,52944).
+char(c,52945).
+char(m,52946).
+char(o,52947).
+char(m,52948).
+char(6,52949).
+char(7,52950).
+char(1,52951).
+char(0,52952).
+char(p,52953).
+char(4,52954).
+char(0,52955).
+char(3,52956).
+char(5,52957).
+char(p,52958).
+char(1,52959).
+char(4,52960).
+char(3,52961).
+char(4,52962).
+char(p,52963).
+char(o,52964).
+char(o,52965).
+char(p,52966).
+char(o,52967).
+char(m,52968).
+char(o,52969).
+char(o,52970).
+char(m,52971).
+char(o,52972).
+char(m,52973).
+char(4,52974).
+char(5,52975).
+char(9,52976).
+char(4,52977).
+char(c,52978).
+char(c,52979).
+char(m,52980).
+char(o,52981).
+char(o,52982).
+char(4,52983).
+char(2,52984).
+char(5,52985).
+char(1,52986).
+char(p,52987).
+char(o,52988).
+char(m,52989).
+char(5,52990).
+char(3,52991).
+char(5,52992).
+char(0,52993).
+char(p,52994).
+char(5,52995).
+char(3,52996).
+char(5,52997).
+char(6,52998).
+char(c,52999).
+char(c,53000).
+char(m,53001).
+char(5,53002).
+char(6,53003).
+char(5,53004).
+char(1,53005).
+char(p,53006).
+char(o,53007).
+char(p,53008).
+char(7,53009).
+char(5,53010).
+char(3,53011).
+char(p,53012).
+char(1,53013).
+char(2,53014).
+char(9,53015).
+char(1,53016).
+char(c,53017).
+char(m,53018).
+char(6,53019).
+char(3,53020).
+char(9,53021).
+char(8,53022).
+char(m,53023).
+char(o,53024).
+char(m,53025).
+char(8,53026).
+char(9,53027).
+char(2,53028).
+char(2,53029).
+char(m,53030).
+char(o,53031).
+char(p,53032).
+char(2,53033).
+char(6,53034).
+char(5,53035).
+char(1,53036).
+char(c,53037).
+char(p,53038).
+char(5,53039).
+char(2,53040).
+char(4,53041).
+char(9,53042).
+char(m,53043).
+char(6,53044).
+char(3,53045).
+char(4,53046).
+char(6,53047).
+char(c,53048).
+char(c,53049).
+char(p,53050).
+char(7,53051).
+char(5,53052).
+char(0,53053).
+char(1,53054).
+char(c,53055).
+char(c,53056).
+char(c,53057).
+char(p,53058).
+char(o,53059).
+char(p,53060).
+char(9,53061).
+char(4,53062).
+char(7,53063).
+char(3,53064).
+char(p,53065).
+char(o,53066).
+char(o,53067).
+char(m,53068).
+char(o,53069).
+char(m,53070).
+char(o,53071).
+char(p,53072).
+char(4,53073).
+char(7,53074).
+char(5,53075).
+char(1,53076).
+char(c,53077).
+char(m,53078).
+char(1,53079).
+char(8,53080).
+char(9,53081).
+char(4,53082).
+char(c,53083).
+char(m,53084).
+char(4,53085).
+char(9,53086).
+char(3,53087).
+char(6,53088).
+char(m,53089).
+char(o,53090).
+char(p,53091).
+char(6,53092).
+char(1,53093).
+char(m,53094).
+char(9,53095).
+char(2,53096).
+char(7,53097).
+char(6,53098).
+char(m,53099).
+char(o,53100).
+char(p,53101).
+char(2,53102).
+char(8,53103).
+char(4,53104).
+char(2,53105).
+char(p,53106).
+char(9,53107).
+char(7,53108).
+char(0,53109).
+char(4,53110).
+char(p,53111).
+char(o,53112).
+char(p,53113).
+char(7,53114).
+char(7,53115).
+char(5,53116).
+char(4,53117).
+char(c,53118).
+char(c,53119).
+char(c,53120).
+char(c,53121).
+char(c,53122).
+char(m,53123).
+char(5,53124).
+char(3,53125).
+char(1,53126).
+char(8,53127).
+char(c,53128).
+char(m,53129).
+char(o,53130).
+char(o,53131).
+char(m,53132).
+char(o,53133).
+char(p,53134).
+char(2,53135).
+char(3,53136).
+char(0,53137).
+char(9,53138).
+char(c,53139).
+char(c,53140).
+char(c,53141).
+char(p,53142).
+char(2,53143).
+char(8,53144).
+char(3,53145).
+char(5,53146).
+char(m,53147).
+char(1,53148).
+char(2,53149).
+char(8,53150).
+char(7,53151).
+char(c,53152).
+char(p,53153).
+char(6,53154).
+char(1,53155).
+char(9,53156).
+char(7,53157).
+char(c,53158).
+char(p,53159).
+char(5,53160).
+char(2,53161).
+char(1,53162).
+char(c,53163).
+char(m,53164).
+char(8,53165).
+char(2,53166).
+char(5,53167).
+char(6,53168).
+char(c,53169).
+char(m,53170).
+char(o,53171).
+char(m,53172).
+char(8,53173).
+char(9,53174).
+char(9,53175).
+char(7,53176).
+char(c,53177).
+char(c,53178).
+char(m,53179).
+char(3,53180).
+char(7,53181).
+char(1,53182).
+char(2,53183).
+char(c,53184).
+char(c,53185).
+char(c,53186).
+char(m,53187).
+char(o,53188).
+char(m,53189).
+char(o,53190).
+char(p,53191).
+char(3,53192).
+char(2,53193).
+char(3,53194).
+char(3,53195).
+char(m,53196).
+char(o,53197).
+char(m,53198).
+char(o,53199).
+char(m,53200).
+char(o,53201).
+char(m,53202).
+char(6,53203).
+char(5,53204).
+char(7,53205).
+char(c,53206).
+char(m,53207).
+char(6,53208).
+char(1,53209).
+char(0,53210).
+char(8,53211).
+char(m,53212).
+char(o,53213).
+char(5,53214).
+char(6,53215).
+char(3,53216).
+char(4,53217).
+char(c,53218).
+char(p,53219).
+char(9,53220).
+char(8,53221).
+char(2,53222).
+char(8,53223).
+char(m,53224).
+char(o,53225).
+char(m,53226).
+char(5,53227).
+char(3,53228).
+char(8,53229).
+char(3,53230).
+char(c,53231).
+char(c,53232).
+char(m,53233).
+char(o,53234).
+char(m,53235).
+char(o,53236).
+char(o,53237).
+char(o,53238).
+char(p,53239).
+char(o,53240).
+char(m,53241).
+char(o,53242).
+char(1,53243).
+char(3,53244).
+char(0,53245).
+char(4,53246).
+char(c,53247).
+char(p,53248).
+char(2,53249).
+char(4,53250).
+char(8,53251).
+char(4,53252).
+char(c,53253).
+char(p,53254).
+char(o,53255).
+char(p,53256).
+char(o,53257).
+char(o,53258).
+char(3,53259).
+char(0,53260).
+char(0,53261).
+char(9,53262).
+char(m,53263).
+char(o,53264).
+char(o,53265).
+char(p,53266).
+char(7,53267).
+char(1,53268).
+char(6,53269).
+char(c,53270).
+char(c,53271).
+char(c,53272).
+char(m,53273).
+char(o,53274).
+char(p,53275).
+char(4,53276).
+char(2,53277).
+char(8,53278).
+char(5,53279).
+char(m,53280).
+char(1,53281).
+char(5,53282).
+char(6,53283).
+char(3,53284).
+char(c,53285).
+char(c,53286).
+char(m,53287).
+char(o,53288).
+char(m,53289).
+char(o,53290).
+char(o,53291).
+char(3,53292).
+char(1,53293).
+char(5,53294).
+char(4,53295).
+char(p,53296).
+char(o,53297).
+char(m,53298).
+char(2,53299).
+char(6,53300).
+char(8,53301).
+char(7,53302).
+char(c,53303).
+char(c,53304).
+char(c,53305).
+char(p,53306).
+char(o,53307).
+char(o,53308).
+char(p,53309).
+char(o,53310).
+char(m,53311).
+char(o,53312).
+char(3,53313).
+char(2,53314).
+char(2,53315).
+char(9,53316).
+char(c,53317).
+char(c,53318).
+char(c,53319).
+char(c,53320).
+char(c,53321).
+char(p,53322).
+char(o,53323).
+char(m,53324).
+char(o,53325).
+char(p,53326).
+char(2,53327).
+char(9,53328).
+char(2,53329).
+char(0,53330).
+char(c,53331).
+char(p,53332).
+char(9,53333).
+char(9,53334).
+char(4,53335).
+char(9,53336).
+char(p,53337).
+char(1,53338).
+char(8,53339).
+char(3,53340).
+char(3,53341).
+char(m,53342).
+char(2,53343).
+char(3,53344).
+char(c,53345).
+char(p,53346).
+char(2,53347).
+char(2,53348).
+char(7,53349).
+char(5,53350).
+char(p,53351).
+char(1,53352).
+char(1,53353).
+char(5,53354).
+char(1,53355).
+char(c,53356).
+char(c,53357).
+char(m,53358).
+char(o,53359).
+char(p,53360).
+char(2,53361).
+char(7,53362).
+char(0,53363).
+char(5,53364).
+char(c,53365).
+char(c,53366).
+char(c,53367).
+char(c,53368).
+char(c,53369).
+char(m,53370).
+char(o,53371).
+char(p,53372).
+char(7,53373).
+char(5,53374).
+char(0,53375).
+char(9,53376).
+char(c,53377).
+char(c,53378).
+char(m,53379).
+char(7,53380).
+char(7,53381).
+char(7,53382).
+char(3,53383).
+char(c,53384).
+char(m,53385).
+char(o,53386).
+char(p,53387).
+char(6,53388).
+char(9,53389).
+char(0,53390).
+char(4,53391).
+char(c,53392).
+char(c,53393).
+char(m,53394).
+char(o,53395).
+char(m,53396).
+char(o,53397).
+char(p,53398).
+char(o,53399).
+char(9,53400).
+char(5,53401).
+char(4,53402).
+char(9,53403).
+char(p,53404).
+char(7,53405).
+char(9,53406).
+char(2,53407).
+char(4,53408).
+char(m,53409).
+char(o,53410).
+char(m,53411).
+char(o,53412).
+char(m,53413).
+char(o,53414).
+char(p,53415).
+char(o,53416).
+char(p,53417).
+char(7,53418).
+char(9,53419).
+char(8,53420).
+char(2,53421).
+char(c,53422).
+char(c,53423).
+char(c,53424).
+char(p,53425).
+char(6,53426).
+char(1,53427).
+char(2,53428).
+char(0,53429).
+char(c,53430).
+char(p,53431).
+char(o,53432).
+char(p,53433).
+char(6,53434).
+char(8,53435).
+char(0,53436).
+char(p,53437).
+char(o,53438).
+char(5,53439).
+char(6,53440).
+char(7,53441).
+char(5,53442).
+char(m,53443).
+char(2,53444).
+char(4,53445).
+char(5,53446).
+char(1,53447).
+char(p,53448).
+char(o,53449).
+char(p,53450).
+char(o,53451).
+char(p,53452).
+char(o,53453).
+char(p,53454).
+char(2,53455).
+char(5,53456).
+char(2,53457).
+char(5,53458).
+char(m,53459).
+char(6,53460).
+char(0,53461).
+char(7,53462).
+char(5,53463).
+char(p,53464).
+char(3,53465).
+char(6,53466).
+char(3,53467).
+char(8,53468).
+char(c,53469).
+char(c,53470).
+char(c,53471).
+char(m,53472).
+char(6,53473).
+char(9,53474).
+char(6,53475).
+char(5,53476).
+char(m,53477).
+char(3,53478).
+char(1,53479).
+char(3,53480).
+char(8,53481).
+char(c,53482).
+char(c,53483).
+char(m,53484).
+char(6,53485).
+char(9,53486).
+char(7,53487).
+char(2,53488).
+char(p,53489).
+char(o,53490).
+char(p,53491).
+char(1,53492).
+char(3,53493).
+char(5,53494).
+char(3,53495).
+char(m,53496).
+char(o,53497).
+char(p,53498).
+char(o,53499).
+char(m,53500).
+char(5,53501).
+char(6,53502).
+char(1,53503).
+char(8,53504).
+char(c,53505).
+char(c,53506).
+char(c,53507).
+char(p,53508).
+char(o,53509).
+char(o,53510).
+char(m,53511).
+char(o,53512).
+char(2,53513).
+char(4,53514).
+char(4,53515).
+char(6,53516).
+char(c,53517).
+char(c,53518).
+char(p,53519).
+char(6,53520).
+char(6,53521).
+char(9,53522).
+char(7,53523).
+char(c,53524).
+char(c,53525).
+char(p,53526).
+char(7,53527).
+char(5,53528).
+char(0,53529).
+char(6,53530).
+char(m,53531).
+char(4,53532).
+char(2,53533).
+char(2,53534).
+char(6,53535).
+char(c,53536).
+char(c,53537).
+char(c,53538).
+char(c,53539).
+char(p,53540).
+char(4,53541).
+char(4,53542).
+char(2,53543).
+char(m,53544).
+char(3,53545).
+char(1,53546).
+char(0,53547).
+char(6,53548).
+char(m,53549).
+char(o,53550).
+char(m,53551).
+char(o,53552).
+char(o,53553).
+char(4,53554).
+char(0,53555).
+char(5,53556).
+char(9,53557).
+char(c,53558).
+char(c,53559).
+char(p,53560).
+char(1,53561).
+char(3,53562).
+char(5,53563).
+char(7,53564).
+char(c,53565).
+char(p,53566).
+char(o,53567).
+char(4,53568).
+char(1,53569).
+char(9,53570).
+char(1,53571).
+char(m,53572).
+char(o,53573).
+char(m,53574).
+char(o,53575).
+char(p,53576).
+char(9,53577).
+char(3,53578).
+char(1,53579).
+char(6,53580).
+char(p,53581).
+char(3,53582).
+char(3,53583).
+char(5,53584).
+char(8,53585).
+char(p,53586).
+char(2,53587).
+char(7,53588).
+char(5,53589).
+char(2,53590).
+char(c,53591).
+char(c,53592).
+char(c,53593).
+char(p,53594).
+char(o,53595).
+char(6,53596).
+char(2,53597).
+char(1,53598).
+char(0,53599).
+char(m,53600).
+char(o,53601).
+char(m,53602).
+char(o,53603).
+char(m,53604).
+char(o,53605).
+char(m,53606).
+char(7,53607).
+char(0,53608).
+char(2,53609).
+char(5,53610).
+char(c,53611).
+char(m,53612).
+char(8,53613).
+char(7,53614).
+char(6,53615).
+char(1,53616).
+char(c,53617).
+char(p,53618).
+char(o,53619).
+char(m,53620).
+char(o,53621).
+char(m,53622).
+char(8,53623).
+char(2,53624).
+char(0,53625).
+char(5,53626).
+char(c,53627).
+char(p,53628).
+char(o,53629).
+char(p,53630).
+char(o,53631).
+char(m,53632).
+char(2,53633).
+char(0,53634).
+char(8,53635).
+char(2,53636).
+char(c,53637).
+char(m,53638).
+char(o,53639).
+char(p,53640).
+char(o,53641).
+char(m,53642).
+char(7,53643).
+char(2,53644).
+char(2,53645).
+char(4,53646).
+char(m,53647).
+char(5,53648).
+char(1,53649).
+char(1,53650).
+char(1,53651).
+char(p,53652).
+char(3,53653).
+char(2,53654).
+char(8,53655).
+char(5,53656).
+char(p,53657).
+char(9,53658).
+char(4,53659).
+char(1,53660).
+char(1,53661).
+char(c,53662).
+char(m,53663).
+char(1,53664).
+char(4,53665).
+char(6,53666).
+char(5,53667).
+char(c,53668).
+char(c,53669).
+char(c,53670).
+char(c,53671).
+char(c,53672).
+char(m,53673).
+char(7,53674).
+char(7,53675).
+char(6,53676).
+char(4,53677).
+char(c,53678).
+char(p,53679).
+char(o,53680).
+char(o,53681).
+char(m,53682).
+char(o,53683).
+char(p,53684).
+char(o,53685).
+char(m,53686).
+char(7,53687).
+char(2,53688).
+char(3,53689).
+char(1,53690).
+char(p,53691).
+char(1,53692).
+char(3,53693).
+char(0,53694).
+char(8,53695).
+char(p,53696).
+char(o,53697).
+char(p,53698).
+char(4,53699).
+char(0,53700).
+char(0,53701).
+char(6,53702).
+char(p,53703).
+char(o,53704).
+char(o,53705).
+char(4,53706).
+char(7,53707).
+char(6,53708).
+char(5,53709).
+char(m,53710).
+char(8,53711).
+char(0,53712).
+char(5,53713).
+char(5,53714).
+char(c,53715).
+char(m,53716).
+char(o,53717).
+char(p,53718).
+char(o,53719).
+char(p,53720).
+char(o,53721).
+char(m,53722).
+char(o,53723).
+char(p,53724).
+char(9,53725).
+char(2,53726).
+char(2,53727).
+char(9,53728).
+char(c,53729).
+char(c,53730).
+char(c,53731).
+char(p,53732).
+char(1,53733).
+char(3,53734).
+char(1,53735).
+char(0,53736).
+char(c,53737).
+char(p,53738).
+char(1,53739).
+char(7,53740).
+char(3,53741).
+char(6,53742).
+char(c,53743).
+char(c,53744).
+char(c,53745).
+char(c,53746).
+char(c,53747).
+char(m,53748).
+char(6,53749).
+char(6,53750).
+char(8,53751).
+char(6,53752).
+char(c,53753).
+char(c,53754).
+char(m,53755).
+char(4,53756).
+char(8,53757).
+char(2,53758).
+char(9,53759).
+char(m,53760).
+char(5,53761).
+char(5,53762).
+char(5,53763).
+char(8,53764).
+char(p,53765).
+char(o,53766).
+char(2,53767).
+char(3,53768).
+char(2,53769).
+char(2,53770).
+char(m,53771).
+char(1,53772).
+char(6,53773).
+char(7,53774).
+char(2,53775).
+char(p,53776).
+char(8,53777).
+char(0,53778).
+char(5,53779).
+char(1,53780).
+char(m,53781).
+char(o,53782).
+char(p,53783).
+char(5,53784).
+char(5,53785).
+char(4,53786).
+char(5,53787).
+char(c,53788).
+char(c,53789).
+char(c,53790).
+char(p,53791).
+char(o,53792).
+char(p,53793).
+char(8,53794).
+char(8,53795).
+char(3,53796).
+char(0,53797).
+char(p,53798).
+char(o,53799).
+char(m,53800).
+char(8,53801).
+char(2,53802).
+char(5,53803).
+char(3,53804).
+char(p,53805).
+char(o,53806).
+char(p,53807).
+char(7,53808).
+char(2,53809).
+char(9,53810).
+char(0,53811).
+char(c,53812).
+char(p,53813).
+char(5,53814).
+char(6,53815).
+char(2,53816).
+char(4,53817).
+char(p,53818).
+char(o,53819).
+char(p,53820).
+char(o,53821).
+char(o,53822).
+char(o,53823).
+char(m,53824).
+char(4,53825).
+char(7,53826).
+char(6,53827).
+char(7,53828).
+char(p,53829).
+char(o,53830).
+char(5,53831).
+char(0,53832).
+char(4,53833).
+char(6,53834).
+char(m,53835).
+char(o,53836).
+char(5,53837).
+char(8,53838).
+char(7,53839).
+char(9,53840).
+char(m,53841).
+char(o,53842).
+char(m,53843).
+char(3,53844).
+char(5,53845).
+char(6,53846).
+char(4,53847).
+char(c,53848).
+char(c,53849).
+char(p,53850).
+char(1,53851).
+char(8,53852).
+char(5,53853).
+char(2,53854).
+char(c,53855).
+char(p,53856).
+char(o,53857).
+char(m,53858).
+char(o,53859).
+char(p,53860).
+char(o,53861).
+char(m,53862).
+char(9,53863).
+char(4,53864).
+char(0,53865).
+char(0,53866).
+char(m,53867).
+char(o,53868).
+char(p,53869).
+char(9,53870).
+char(1,53871).
+char(7,53872).
+char(1,53873).
+char(m,53874).
+char(o,53875).
+char(m,53876).
+char(o,53877).
+char(m,53878).
+char(o,53879).
+char(o,53880).
+char(p,53881).
+char(1,53882).
+char(8,53883).
+char(c,53884).
+char(p,53885).
+char(o,53886).
+char(p,53887).
+char(5,53888).
+char(1,53889).
+char(7,53890).
+char(7,53891).
+char(m,53892).
+char(6,53893).
+char(2,53894).
+char(8,53895).
+char(c,53896).
+char(c,53897).
+char(c,53898).
+char(c,53899).
+char(c,53900).
+char(m,53901).
+char(o,53902).
+char(p,53903).
+char(8,53904).
+char(4,53905).
+char(2,53906).
+char(m,53907).
+char(o,53908).
+char(p,53909).
+char(7,53910).
+char(1,53911).
+char(4,53912).
+char(8,53913).
+char(c,53914).
+char(p,53915).
+char(o,53916).
+char(o,53917).
+char(4,53918).
+char(7,53919).
+char(9,53920).
+char(5,53921).
+char(c,53922).
+char(c,53923).
+char(m,53924).
+char(6,53925).
+char(9,53926).
+char(9,53927).
+char(3,53928).
+char(m,53929).
+char(o,53930).
+char(p,53931).
+char(7,53932).
+char(7,53933).
+char(7,53934).
+char(9,53935).
+char(c,53936).
+char(c,53937).
+char(c,53938).
+char(p,53939).
+char(5,53940).
+char(3,53941).
+char(8,53942).
+char(3,53943).
+char(p,53944).
+char(8,53945).
+char(9,53946).
+char(0,53947).
+char(2,53948).
+char(p,53949).
+char(2,53950).
+char(2,53951).
+char(0,53952).
+char(6,53953).
+char(c,53954).
+char(c,53955).
+char(c,53956).
+char(p,53957).
+char(o,53958).
+char(p,53959).
+char(2,53960).
+char(1,53961).
+char(6,53962).
+char(9,53963).
+char(c,53964).
+char(m,53965).
+char(o,53966).
+char(m,53967).
+char(8,53968).
+char(8,53969).
+char(8,53970).
+char(8,53971).
+char(p,53972).
+char(8,53973).
+char(6,53974).
+char(7,53975).
+char(3,53976).
+char(p,53977).
+char(o,53978).
+char(m,53979).
+char(o,53980).
+char(m,53981).
+char(9,53982).
+char(4,53983).
+char(6,53984).
+char(6,53985).
+char(c,53986).
+char(p,53987).
+char(o,53988).
+char(m,53989).
+char(o,53990).
+char(p,53991).
+char(3,53992).
+char(6,53993).
+char(9,53994).
+char(9,53995).
+char(p,53996).
+char(4,53997).
+char(1,53998).
+char(5,53999).
+char(6,54000).
+char(p,54001).
+char(o,54002).
+char(m,54003).
+char(o,54004).
+char(o,54005).
+char(5,54006).
+char(9,54007).
+char(6,54008).
+char(4,54009).
+char(m,54010).
+char(o,54011).
+char(m,54012).
+char(3,54013).
+char(8,54014).
+char(0,54015).
+char(2,54016).
+char(c,54017).
+char(p,54018).
+char(o,54019).
+char(p,54020).
+char(o,54021).
+char(4,54022).
+char(8,54023).
+char(6,54024).
+char(0,54025).
+char(p,54026).
+char(o,54027).
+char(m,54028).
+char(o,54029).
+char(p,54030).
+char(1,54031).
+char(9,54032).
+char(4,54033).
+char(4,54034).
+char(c,54035).
+char(p,54036).
+char(o,54037).
+char(m,54038).
+char(o,54039).
+char(m,54040).
+char(5,54041).
+char(7,54042).
+char(6,54043).
+char(6,54044).
+char(p,54045).
+char(o,54046).
+char(m,54047).
+char(4,54048).
+char(7,54049).
+char(4,54050).
+char(6,54051).
+char(m,54052).
+char(8,54053).
+char(2,54054).
+char(6,54055).
+char(7,54056).
+char(c,54057).
+char(c,54058).
+char(c,54059).
+char(c,54060).
+char(p,54061).
+char(5,54062).
+char(2,54063).
+char(1,54064).
+char(4,54065).
+char(m,54066).
+char(o,54067).
+char(p,54068).
+char(5,54069).
+char(8,54070).
+char(7,54071).
+char(c,54072).
+char(m,54073).
+char(o,54074).
+char(m,54075).
+char(1,54076).
+char(3,54077).
+char(0,54078).
+char(4,54079).
+char(m,54080).
+char(8,54081).
+char(0,54082).
+char(8,54083).
+char(9,54084).
+char(c,54085).
+char(c,54086).
+char(m,54087).
+char(o,54088).
+char(m,54089).
+char(4,54090).
+char(5,54091).
+char(8,54092).
+char(6,54093).
+char(c,54094).
+char(p,54095).
+char(o,54096).
+char(m,54097).
+char(o,54098).
+char(p,54099).
+char(1,54100).
+char(5,54101).
+char(2,54102).
+char(3,54103).
+char(m,54104).
+char(6,54105).
+char(1,54106).
+char(9,54107).
+char(0,54108).
+char(c,54109).
+char(p,54110).
+char(o,54111).
+char(5,54112).
+char(4,54113).
+char(8,54114).
+char(7,54115).
+char(m,54116).
+char(6,54117).
+char(6,54118).
+char(4,54119).
+char(0,54120).
+char(m,54121).
+char(4,54122).
+char(1,54123).
+char(8,54124).
+char(5,54125).
+char(p,54126).
+char(1,54127).
+char(8,54128).
+char(2,54129).
+char(6,54130).
+char(m,54131).
+char(7,54132).
+char(5,54133).
+char(2,54134).
+char(3,54135).
+char(p,54136).
+char(o,54137).
+char(p,54138).
+char(6,54139).
+char(4,54140).
+char(5,54141).
+char(1,54142).
+char(m,54143).
+char(o,54144).
+char(2,54145).
+char(9,54146).
+char(5,54147).
+char(7,54148).
+char(c,54149).
+char(m,54150).
+char(o,54151).
+char(p,54152).
+char(o,54153).
+char(p,54154).
+char(7,54155).
+char(6,54156).
+char(3,54157).
+char(c,54158).
+char(p,54159).
+char(3,54160).
+char(7,54161).
+char(2,54162).
+char(4,54163).
+char(m,54164).
+char(8,54165).
+char(9,54166).
+char(8,54167).
+char(5,54168).
+char(c,54169).
+char(p,54170).
+char(4,54171).
+char(1,54172).
+char(7,54173).
+char(c,54174).
+char(c,54175).
+char(c,54176).
+char(c,54177).
+char(m,54178).
+char(o,54179).
+char(p,54180).
+char(2,54181).
+char(4,54182).
+char(6,54183).
+char(1,54184).
+char(m,54185).
+char(6,54186).
+char(4,54187).
+char(2,54188).
+char(0,54189).
+char(m,54190).
+char(3,54191).
+char(1,54192).
+char(5,54193).
+char(5,54194).
+char(m,54195).
+char(2,54196).
+char(3,54197).
+char(6,54198).
+char(8,54199).
+char(p,54200).
+char(1,54201).
+char(9,54202).
+char(0,54203).
+char(1,54204).
+char(p,54205).
+char(o,54206).
+char(o,54207).
+char(p,54208).
+char(o,54209).
+char(p,54210).
+char(o,54211).
+char(m,54212).
+char(o,54213).
+char(p,54214).
+char(2,54215).
+char(8,54216).
+char(5,54217).
+char(1,54218).
+char(m,54219).
+char(3,54220).
+char(4,54221).
+char(4,54222).
+char(9,54223).
+char(p,54224).
+char(9,54225).
+char(8,54226).
+char(1,54227).
+char(5,54228).
+char(c,54229).
+char(c,54230).
+char(p,54231).
+char(o,54232).
+char(m,54233).
+char(o,54234).
+char(o,54235).
+char(o,54236).
+char(p,54237).
+char(o,54238).
+char(p,54239).
+char(7,54240).
+char(1,54241).
+char(6,54242).
+char(5,54243).
+char(c,54244).
+char(c,54245).
+char(p,54246).
+char(o,54247).
+char(o,54248).
+char(p,54249).
+char(o,54250).
+char(2,54251).
+char(9,54252).
+char(6,54253).
+char(3,54254).
+char(m,54255).
+char(9,54256).
+char(3,54257).
+char(6,54258).
+char(6,54259).
+char(m,54260).
+char(1,54261).
+char(2,54262).
+char(8,54263).
+char(4,54264).
+char(c,54265).
+char(c,54266).
+char(m,54267).
+char(o,54268).
+char(m,54269).
+char(o,54270).
+char(m,54271).
+char(7,54272).
+char(8,54273).
+char(0,54274).
+char(0,54275).
+char(c,54276).
+char(c,54277).
+char(c,54278).
+char(c,54279).
+char(p,54280).
+char(3,54281).
+char(9,54282).
+char(6,54283).
+char(8,54284).
+char(c,54285).
+char(p,54286).
+char(o,54287).
+char(m,54288).
+char(o,54289).
+char(p,54290).
+char(o,54291).
+char(m,54292).
+char(o,54293).
+char(p,54294).
+char(2,54295).
+char(3,54296).
+char(2,54297).
+char(4,54298).
+char(c,54299).
+char(p,54300).
+char(o,54301).
+char(1,54302).
+char(6,54303).
+char(0,54304).
+char(c,54305).
+char(m,54306).
+char(o,54307).
+char(9,54308).
+char(3,54309).
+char(4,54310).
+char(8,54311).
+char(p,54312).
+char(o,54313).
+char(p,54314).
+char(o,54315).
+char(m,54316).
+char(3,54317).
+char(3,54318).
+char(8,54319).
+char(1,54320).
+char(c,54321).
+char(c,54322).
+char(p,54323).
+char(5,54324).
+char(9,54325).
+char(8,54326).
+char(3,54327).
+char(m,54328).
+char(o,54329).
+char(m,54330).
+char(o,54331).
+char(m,54332).
+char(o,54333).
+char(m,54334).
+char(o,54335).
+char(p,54336).
+char(o,54337).
+char(p,54338).
+char(2,54339).
+char(7,54340).
+char(8,54341).
+char(c,54342).
+char(m,54343).
+char(2,54344).
+char(5,54345).
+char(3,54346).
+char(3,54347).
+char(p,54348).
+char(o,54349).
+char(o,54350).
+char(p,54351).
+char(4,54352).
+char(5,54353).
+char(5,54354).
+char(4,54355).
+char(c,54356).
+char(c,54357).
+char(p,54358).
+char(7,54359).
+char(5,54360).
+char(3,54361).
+char(5,54362).
+char(p,54363).
+char(o,54364).
+char(p,54365).
+char(1,54366).
+char(7,54367).
+char(2,54368).
+char(c,54369).
+char(m,54370).
+char(3,54371).
+char(6,54372).
+char(0,54373).
+char(1,54374).
+char(c,54375).
+char(c,54376).
+char(m,54377).
+char(3,54378).
+char(5,54379).
+char(8,54380).
+char(0,54381).
+char(m,54382).
+char(6,54383).
+char(0,54384).
+char(1,54385).
+char(1,54386).
+char(c,54387).
+char(m,54388).
+char(5,54389).
+char(8,54390).
+char(4,54391).
+char(0,54392).
+char(c,54393).
+char(p,54394).
+char(2,54395).
+char(7,54396).
+char(5,54397).
+char(6,54398).
+char(p,54399).
+char(o,54400).
+char(p,54401).
+char(5,54402).
+char(8,54403).
+char(8,54404).
+char(4,54405).
+char(c,54406).
+char(p,54407).
+char(o,54408).
+char(m,54409).
+char(4,54410).
+char(4,54411).
+char(9,54412).
+char(1,54413).
+char(p,54414).
+char(o,54415).
+char(m,54416).
+char(4,54417).
+char(7,54418).
+char(4,54419).
+char(3,54420).
+char(m,54421).
+char(o,54422).
+char(p,54423).
+char(o,54424).
+char(p,54425).
+char(o,54426).
+char(m,54427).
+char(o,54428).
+char(m,54429).
+char(2,54430).
+char(5,54431).
+char(7,54432).
+char(c,54433).
+char(c,54434).
+char(p,54435).
+char(o,54436).
+char(p,54437).
+char(5,54438).
+char(9,54439).
+char(6,54440).
+char(0,54441).
+char(m,54442).
+char(o,54443).
+char(p,54444).
+char(o,54445).
+char(o,54446).
+char(p,54447).
+char(o,54448).
+char(o,54449).
+char(m,54450).
+char(o,54451).
+char(o,54452).
+char(m,54453).
+char(6,54454).
+char(0,54455).
+char(0,54456).
+char(6,54457).
+char(m,54458).
+char(1,54459).
+char(1,54460).
+char(0,54461).
+char(5,54462).
+char(c,54463).
+char(c,54464).
+char(p,54465).
+char(5,54466).
+char(0,54467).
+char(9,54468).
+char(6,54469).
+char(c,54470).
+char(c,54471).
+char(m,54472).
+char(o,54473).
+char(m,54474).
+char(2,54475).
+char(4,54476).
+char(6,54477).
+char(3,54478).
+char(c,54479).
+char(c,54480).
+char(p,54481).
+char(2,54482).
+char(0,54483).
+char(4,54484).
+char(2,54485).
+char(p,54486).
+char(o,54487).
+char(3,54488).
+char(0,54489).
+char(6,54490).
+char(1,54491).
+char(p,54492).
+char(o,54493).
+char(m,54494).
+char(o,54495).
+char(o,54496).
+char(o,54497).
+char(m,54498).
+char(o,54499).
+char(p,54500).
+char(8,54501).
+char(1,54502).
+char(3,54503).
+char(7,54504).
+char(c,54505).
+char(c,54506).
+char(c,54507).
+char(p,54508).
+char(o,54509).
+char(5,54510).
+char(2,54511).
+char(2,54512).
+char(m,54513).
+char(o,54514).
+char(o,54515).
+char(m,54516).
+char(o,54517).
+char(o,54518).
+char(p,54519).
+char(o,54520).
+char(7,54521).
+char(6,54522).
+char(3,54523).
+char(8,54524).
+char(c,54525).
+char(c,54526).
+char(c,54527).
+char(c,54528).
+char(m,54529).
+char(o,54530).
+char(1,54531).
+char(4,54532).
+char(5,54533).
+char(2,54534).
+char(m,54535).
+char(4,54536).
+char(1,54537).
+char(3,54538).
+char(8,54539).
+char(c,54540).
+char(c,54541).
+char(p,54542).
+char(o,54543).
+char(m,54544).
+char(4,54545).
+char(6,54546).
+char(5,54547).
+char(4,54548).
+char(m,54549).
+char(9,54550).
+char(8,54551).
+char(1,54552).
+char(5,54553).
+char(p,54554).
+char(2,54555).
+char(1,54556).
+char(8,54557).
+char(4,54558).
+char(c,54559).
+char(c,54560).
+char(c,54561).
+char(m,54562).
+char(o,54563).
+char(o,54564).
+char(m,54565).
+char(o,54566).
+char(o,54567).
+char(p,54568).
+char(o,54569).
+char(3,54570).
+char(1,54571).
+char(0,54572).
+char(4,54573).
+char(c,54574).
+char(c,54575).
+char(c,54576).
+char(c,54577).
+char(c,54578).
+char(c,54579).
+char(m,54580).
+char(o,54581).
+char(m,54582).
+char(7,54583).
+char(0,54584).
+char(1,54585).
+char(1,54586).
+char(c,54587).
+char(p,54588).
+char(2,54589).
+char(1,54590).
+char(2,54591).
+char(8,54592).
+char(m,54593).
+char(6,54594).
+char(1,54595).
+char(1,54596).
+char(6,54597).
+char(c,54598).
+char(c,54599).
+char(p,54600).
+char(9,54601).
+char(2,54602).
+char(0,54603).
+char(8,54604).
+char(c,54605).
+char(c,54606).
+char(c,54607).
+char(p,54608).
+char(o,54609).
+char(o,54610).
+char(m,54611).
+char(7,54612).
+char(0,54613).
+char(1,54614).
+char(5,54615).
+char(p,54616).
+char(o,54617).
+char(p,54618).
+char(9,54619).
+char(4,54620).
+char(4,54621).
+char(0,54622).
+char(c,54623).
+char(m,54624).
+char(3,54625).
+char(3,54626).
+char(9,54627).
+char(2,54628).
+char(m,54629).
+char(o,54630).
+char(m,54631).
+char(5,54632).
+char(1,54633).
+char(2,54634).
+char(9,54635).
+char(c,54636).
+char(m,54637).
+char(o,54638).
+char(m,54639).
+char(o,54640).
+char(o,54641).
+char(o,54642).
+char(m,54643).
+char(8,54644).
+char(9,54645).
+char(3,54646).
+char(3,54647).
+char(m,54648).
+char(7,54649).
+char(4,54650).
+char(3,54651).
+char(p,54652).
+char(o,54653).
+char(p,54654).
+char(6,54655).
+char(4,54656).
+char(2,54657).
+char(2,54658).
+char(m,54659).
+char(6,54660).
+char(8,54661).
+char(2,54662).
+char(2,54663).
+char(p,54664).
+char(3,54665).
+char(1,54666).
+char(0,54667).
+char(7,54668).
+char(m,54669).
+char(o,54670).
+char(4,54671).
+char(5,54672).
+char(6,54673).
+char(0,54674).
+char(c,54675).
+char(c,54676).
+char(p,54677).
+char(o,54678).
+char(p,54679).
+char(9,54680).
+char(7,54681).
+char(8,54682).
+char(3,54683).
+char(p,54684).
+char(9,54685).
+char(4,54686).
+char(8,54687).
+char(6,54688).
+char(p,54689).
+char(o,54690).
+char(8,54691).
+char(4,54692).
+char(1,54693).
+char(5,54694).
+char(p,54695).
+char(5,54696).
+char(5,54697).
+char(8,54698).
+char(6,54699).
+char(c,54700).
+char(c,54701).
+char(p,54702).
+char(6,54703).
+char(1,54704).
+char(4,54705).
+char(6,54706).
+char(p,54707).
+char(1,54708).
+char(9,54709).
+char(7,54710).
+char(1,54711).
+char(c,54712).
+char(m,54713).
+char(7,54714).
+char(0,54715).
+char(7,54716).
+char(8,54717).
+char(p,54718).
+char(o,54719).
+char(m,54720).
+char(5,54721).
+char(1,54722).
+char(1,54723).
+char(2,54724).
+char(p,54725).
+char(o,54726).
+char(p,54727).
+char(o,54728).
+char(m,54729).
+char(o,54730).
+char(p,54731).
+char(1,54732).
+char(8,54733).
+char(5,54734).
+char(1,54735).
+char(m,54736).
+char(1,54737).
+char(1,54738).
+char(6,54739).
+char(0,54740).
+char(p,54741).
+char(o,54742).
+char(p,54743).
+char(9,54744).
+char(6,54745).
+char(6,54746).
+char(3,54747).
+char(c,54748).
+char(c,54749).
+char(c,54750).
+char(p,54751).
+char(o,54752).
+char(p,54753).
+char(4,54754).
+char(2,54755).
+char(8,54756).
+char(1,54757).
+char(m,54758).
+char(o,54759).
+char(m,54760).
+char(o,54761).
+char(m,54762).
+char(5,54763).
+char(0,54764).
+char(0,54765).
+char(0,54766).
+char(m,54767).
+char(o,54768).
+char(p,54769).
+char(o,54770).
+char(p,54771).
+char(o,54772).
+char(7,54773).
+char(0,54774).
+char(9,54775).
+char(1,54776).
+char(c,54777).
+char(p,54778).
+char(o,54779).
+char(p,54780).
+char(1,54781).
+char(9,54782).
+char(1,54783).
+char(7,54784).
+char(m,54785).
+char(2,54786).
+char(7,54787).
+char(4,54788).
+char(1,54789).
+char(p,54790).
+char(7,54791).
+char(3,54792).
+char(6,54793).
+char(3,54794).
+char(m,54795).
+char(o,54796).
+char(p,54797).
+char(4,54798).
+char(2,54799).
+char(4,54800).
+char(3,54801).
+char(c,54802).
+char(m,54803).
+char(o,54804).
+char(m,54805).
+char(o,54806).
+char(m,54807).
+char(o,54808).
+char(m,54809).
+char(4,54810).
+char(6,54811).
+char(8,54812).
+char(7,54813).
+char(p,54814).
+char(8,54815).
+char(6,54816).
+char(9,54817).
+char(4,54818).
+char(p,54819).
+char(6,54820).
+char(2,54821).
+char(6,54822).
+char(9,54823).
+char(p,54824).
+char(6,54825).
+char(4,54826).
+char(2,54827).
+char(0,54828).
+char(m,54829).
+char(6,54830).
+char(8,54831).
+char(5,54832).
+char(3,54833).
+char(c,54834).
+char(m,54835).
+char(8,54836).
+char(3,54837).
+char(0,54838).
+char(0,54839).
+char(c,54840).
+char(m,54841).
+char(4,54842).
+char(5,54843).
+char(0,54844).
+char(3,54845).
+char(m,54846).
+char(o,54847).
+char(m,54848).
+char(6,54849).
+char(9,54850).
+char(2,54851).
+char(4,54852).
+char(c,54853).
+char(c,54854).
+char(c,54855).
+char(p,54856).
+char(9,54857).
+char(9,54858).
+char(0,54859).
+char(9,54860).
+char(m,54861).
+char(o,54862).
+char(p,54863).
+char(o,54864).
+char(m,54865).
+char(4,54866).
+char(8,54867).
+char(0,54868).
+char(0,54869).
+char(c,54870).
+char(m,54871).
+char(o,54872).
+char(m,54873).
+char(o,54874).
+char(3,54875).
+char(6,54876).
+char(8,54877).
+char(8,54878).
+char(c,54879).
+char(c,54880).
+char(m,54881).
+char(4,54882).
+char(4,54883).
+char(0,54884).
+char(0,54885).
+char(c,54886).
+char(c,54887).
+char(p,54888).
+char(7,54889).
+char(9,54890).
+char(3,54891).
+char(9,54892).
+char(m,54893).
+char(o,54894).
+char(8,54895).
+char(8,54896).
+char(7,54897).
+char(0,54898).
+char(c,54899).
+char(c,54900).
+char(c,54901).
+char(c,54902).
+char(p,54903).
+char(5,54904).
+char(3,54905).
+char(9,54906).
+char(0,54907).
+char(c,54908).
+char(c,54909).
+char(c,54910).
+char(c,54911).
+char(p,54912).
+char(o,54913).
+char(o,54914).
+char(o,54915).
+char(p,54916).
+char(o,54917).
+char(m,54918).
+char(5,54919).
+char(p,54920).
+char(o,54921).
+char(o,54922).
+char(m,54923).
+char(6,54924).
+char(5,54925).
+char(1,54926).
+char(8,54927).
+char(m,54928).
+char(o,54929).
+char(m,54930).
+char(o,54931).
+char(p,54932).
+char(9,54933).
+char(9,54934).
+char(5,54935).
+char(2,54936).
+char(c,54937).
+char(c,54938).
+char(m,54939).
+char(o,54940).
+char(p,54941).
+char(o,54942).
+char(m,54943).
+char(o,54944).
+char(p,54945).
+char(7,54946).
+char(6,54947).
+char(4,54948).
+char(0,54949).
+char(m,54950).
+char(8,54951).
+char(4,54952).
+char(2,54953).
+char(0,54954).
+char(c,54955).
+char(c,54956).
+char(p,54957).
+char(o,54958).
+char(p,54959).
+char(4,54960).
+char(0,54961).
+char(0,54962).
+char(4,54963).
+char(m,54964).
+char(2,54965).
+char(1,54966).
+char(9,54967).
+char(4,54968).
+char(c,54969).
+char(c,54970).
+char(c,54971).
+char(p,54972).
+char(4,54973).
+char(1,54974).
+char(3,54975).
+char(1,54976).
+char(p,54977).
+char(o,54978).
+char(p,54979).
+char(1,54980).
+char(2,54981).
+char(7,54982).
+char(7,54983).
+char(p,54984).
+char(o,54985).
+char(p,54986).
+char(8,54987).
+char(8,54988).
+char(7,54989).
+char(8,54990).
+char(c,54991).
+char(c,54992).
+char(c,54993).
+char(c,54994).
+char(p,54995).
+char(o,54996).
+char(p,54997).
+char(o,54998).
+char(7,54999).
+char(7,55000).
+char(7,55001).
+char(1,55002).
+char(c,55003).
+char(p,55004).
+char(o,55005).
+char(1,55006).
+char(7,55007).
+char(9,55008).
+char(6,55009).
+char(c,55010).
+char(m,55011).
+char(3,55012).
+char(2,55013).
+char(1,55014).
+char(0,55015).
+char(m,55016).
+char(7,55017).
+char(1,55018).
+char(2,55019).
+char(3,55020).
+char(p,55021).
+char(o,55022).
+char(m,55023).
+char(4,55024).
+char(0,55025).
+char(4,55026).
+char(4,55027).
+char(m,55028).
+char(o,55029).
+char(m,55030).
+char(o,55031).
+char(p,55032).
+char(5,55033).
+char(8,55034).
+char(7,55035).
+char(2,55036).
+char(p,55037).
+char(7,55038).
+char(9,55039).
+char(8,55040).
+char(7,55041).
+char(c,55042).
+char(m,55043).
+char(o,55044).
+char(m,55045).
+char(o,55046).
+char(m,55047).
+char(o,55048).
+char(m,55049).
+char(9,55050).
+char(3,55051).
+char(6,55052).
+char(7,55053).
+char(m,55054).
+char(o,55055).
+char(o,55056).
+char(o,55057).
+char(o,55058).
+char(o,55059).
+char(p,55060).
+char(o,55061).
+char(p,55062).
+char(o,55063).
+char(m,55064).
+char(o,55065).
+char(p,55066).
+char(6,55067).
+char(4,55068).
+char(6,55069).
+char(0,55070).
+char(p,55071).
+char(o,55072).
+char(m,55073).
+char(7,55074).
+char(3,55075).
+char(9,55076).
+char(1,55077).
+char(m,55078).
+char(o,55079).
+char(m,55080).
+char(o,55081).
+char(p,55082).
+char(o,55083).
+char(p,55084).
+char(4,55085).
+char(8,55086).
+char(7,55087).
+char(1,55088).
+char(c,55089).
+char(p,55090).
+char(9,55091).
+char(6,55092).
+char(3,55093).
+char(9,55094).
+char(p,55095).
+char(o,55096).
+char(p,55097).
+char(7,55098).
+char(2,55099).
+char(0,55100).
+char(7,55101).
+char(m,55102).
+char(o,55103).
+char(m,55104).
+char(o,55105).
+char(p,55106).
+char(o,55107).
+char(o,55108).
+char(m,55109).
+char(8,55110).
+char(8,55111).
+char(6,55112).
+char(7,55113).
+char(m,55114).
+char(9,55115).
+char(5,55116).
+char(7,55117).
+char(c,55118).
+char(m,55119).
+char(6,55120).
+char(8,55121).
+char(9,55122).
+char(7,55123).
+char(c,55124).
+char(m,55125).
+char(o,55126).
+char(9,55127).
+char(7,55128).
+char(8,55129).
+char(3,55130).
+char(m,55131).
+char(o,55132).
+char(p,55133).
+char(3,55134).
+char(9,55135).
+char(4,55136).
+char(7,55137).
+char(m,55138).
+char(4,55139).
+char(7,55140).
+char(4,55141).
+char(8,55142).
+char(c,55143).
+char(c,55144).
+char(c,55145).
+char(c,55146).
+char(m,55147).
+char(o,55148).
+char(o,55149).
+char(o,55150).
+char(p,55151).
+char(o,55152).
+char(m,55153).
+char(8,55154).
+char(8,55155).
+char(4,55156).
+char(2,55157).
+char(c,55158).
+char(c,55159).
+char(p,55160).
+char(o,55161).
+char(7,55162).
+char(8,55163).
+char(5,55164).
+char(7,55165).
+char(c,55166).
+char(c,55167).
+char(m,55168).
+char(4,55169).
+char(9,55170).
+char(4,55171).
+char(2,55172).
+char(c,55173).
+char(c,55174).
+char(p,55175).
+char(o,55176).
+char(m,55177).
+char(o,55178).
+char(m,55179).
+char(o,55180).
+char(o,55181).
+char(o,55182).
+char(p,55183).
+char(o,55184).
+char(m,55185).
+char(9,55186).
+char(8,55187).
+char(2,55188).
+char(8,55189).
+char(p,55190).
+char(o,55191).
+char(7,55192).
+char(0,55193).
+char(2,55194).
+char(4,55195).
+char(c,55196).
+char(p,55197).
+char(o,55198).
+char(m,55199).
+char(o,55200).
+char(m,55201).
+char(2,55202).
+char(2,55203).
+char(8,55204).
+char(8,55205).
+char(p,55206).
+char(o,55207).
+char(6,55208).
+char(5,55209).
+char(7,55210).
+char(c,55211).
+char(p,55212).
+char(o,55213).
+char(1,55214).
+char(2,55215).
+char(9,55216).
+char(6,55217).
+char(c,55218).
+char(m,55219).
+char(o,55220).
+char(4,55221).
+char(2,55222).
+char(5,55223).
+char(6,55224).
+char(c,55225).
+char(c,55226).
+char(p,55227).
+char(7,55228).
+char(9,55229).
+char(8,55230).
+char(c,55231).
+char(p,55232).
+char(o,55233).
+char(m,55234).
+char(8,55235).
+char(6,55236).
+char(7,55237).
+char(4,55238).
+char(m,55239).
+char(o,55240).
+char(p,55241).
+char(1,55242).
+char(1,55243).
+char(2,55244).
+char(1,55245).
+char(p,55246).
+char(o,55247).
+char(m,55248).
+char(o,55249).
+char(m,55250).
+char(7,55251).
+char(1,55252).
+char(0,55253).
+char(5,55254).
+char(c,55255).
+char(m,55256).
+char(2,55257).
+char(0,55258).
+char(1,55259).
+char(2,55260).
+char(m,55261).
+char(o,55262).
+char(o,55263).
+char(o,55264).
+char(m,55265).
+char(o,55266).
+char(m,55267).
+char(6,55268).
+char(9,55269).
+char(6,55270).
+char(9,55271).
+char(c,55272).
+char(m,55273).
+char(o,55274).
+char(p,55275).
+char(o,55276).
+char(o,55277).
+char(p,55278).
+char(o,55279).
+char(m,55280).
+char(9,55281).
+char(2,55282).
+char(6,55283).
+char(9,55284).
+char(c,55285).
+char(p,55286).
+char(o,55287).
+char(p,55288).
+char(o,55289).
+char(p,55290).
+char(o,55291).
+char(m,55292).
+char(o,55293).
+char(p,55294).
+char(o,55295).
+char(m,55296).
+char(o,55297).
+char(p,55298).
+char(o,55299).
+char(m,55300).
+char(8,55301).
+char(0,55302).
+char(2,55303).
+char(1,55304).
+char(c,55305).
+char(c,55306).
+char(m,55307).
+char(o,55308).
+char(5,55309).
+char(8,55310).
+char(3,55311).
+char(c,55312).
+char(c,55313).
+char(c,55314).
+char(m,55315).
+char(o,55316).
+char(p,55317).
+char(5,55318).
+char(4,55319).
+char(5,55320).
+char(3,55321).
+char(m,55322).
+char(o,55323).
+char(m,55324).
+char(o,55325).
+char(p,55326).
+char(o,55327).
+char(o,55328).
+char(m,55329).
+char(9,55330).
+char(4,55331).
+char(7,55332).
+char(6,55333).
+char(c,55334).
+char(p,55335).
+char(4,55336).
+char(1,55337).
+char(0,55338).
+char(9,55339).
+char(p,55340).
+char(o,55341).
+char(m,55342).
+char(o,55343).
+char(p,55344).
+char(o,55345).
+char(o,55346).
+char(o,55347).
+char(m,55348).
+char(1,55349).
+char(1,55350).
+char(6,55351).
+char(7,55352).
+char(p,55353).
+char(o,55354).
+char(p,55355).
+char(o,55356).
+char(5,55357).
+char(2,55358).
+char(8,55359).
+char(0,55360).
+char(c,55361).
+char(c,55362).
+char(m,55363).
+char(o,55364).
+char(p,55365).
+char(1,55366).
+char(1,55367).
+char(5,55368).
+char(2,55369).
+char(c,55370).
+char(p,55371).
+char(o,55372).
+char(p,55373).
+char(3,55374).
+char(0,55375).
+char(0,55376).
+char(9,55377).
+char(m,55378).
+char(4,55379).
+char(1,55380).
+char(5,55381).
+char(4,55382).
+char(m,55383).
+char(o,55384).
+char(p,55385).
+char(8,55386).
+char(1,55387).
+char(4,55388).
+char(3,55389).
+char(c,55390).
+char(p,55391).
+char(o,55392).
+char(5,55393).
+char(3,55394).
+char(1,55395).
+char(3,55396).
+char(m,55397).
+char(9,55398).
+char(7,55399).
+char(7,55400).
+char(7,55401).
+char(c,55402).
+char(c,55403).
+char(c,55404).
+char(c,55405).
+char(p,55406).
+char(3,55407).
+char(1,55408).
+char(8,55409).
+char(0,55410).
+char(c,55411).
+char(m,55412).
+char(8,55413).
+char(2,55414).
+char(5,55415).
+char(4,55416).
+char(c,55417).
+char(c,55418).
+char(p,55419).
+char(8,55420).
+char(0,55421).
+char(0,55422).
+char(7,55423).
+char(m,55424).
+char(7,55425).
+char(6,55426).
+char(0,55427).
+char(8,55428).
+char(m,55429).
+char(o,55430).
+char(o,55431).
+char(m,55432).
+char(o,55433).
+char(m,55434).
+char(5,55435).
+char(8,55436).
+char(1,55437).
+char(1,55438).
+char(c,55439).
+char(p,55440).
+char(2,55441).
+char(7,55442).
+char(4,55443).
+char(9,55444).
+char(p,55445).
+char(o,55446).
+char(p,55447).
+char(o,55448).
+char(m,55449).
+char(7,55450).
+char(6,55451).
+char(3,55452).
+char(6,55453).
+char(p,55454).
+char(5,55455).
+char(9,55456).
+char(6,55457).
+char(4,55458).
+char(c,55459).
+char(c,55460).
+char(m,55461).
+char(o,55462).
+char(m,55463).
+char(o,55464).
+char(o,55465).
+char(o,55466).
+char(m,55467).
+char(o,55468).
+char(p,55469).
+char(9,55470).
+char(0,55471).
+char(2,55472).
+char(0,55473).
+char(c,55474).
+char(c,55475).
+char(c,55476).
+char(c,55477).
+char(c,55478).
+char(c,55479).
+char(c,55480).
+char(m,55481).
+char(9,55482).
+char(1,55483).
+char(9,55484).
+char(7,55485).
+char(c,55486).
+char(p,55487).
+char(o,55488).
+char(m,55489).
+char(8,55490).
+char(9,55491).
+char(0,55492).
+char(5,55493).
+char(c,55494).
+char(c,55495).
+char(c,55496).
+char(c,55497).
+char(c,55498).
+char(c,55499).
+char(c,55500).
+char(m,55501).
+char(o,55502).
+char(m,55503).
+char(o,55504).
+char(p,55505).
+char(o,55506).
+char(m,55507).
+char(o,55508).
+char(m,55509).
+char(8,55510).
+char(1,55511).
+char(7,55512).
+char(p,55513).
+char(2,55514).
+char(5,55515).
+char(4,55516).
+char(3,55517).
+char(c,55518).
+char(p,55519).
+char(1,55520).
+char(7,55521).
+char(6,55522).
+char(2,55523).
+char(c,55524).
+char(p,55525).
+char(o,55526).
+char(o,55527).
+char(4,55528).
+char(3,55529).
+char(3,55530).
+char(0,55531).
+char(c,55532).
+char(m,55533).
+char(o,55534).
+char(m,55535).
+char(o,55536).
+char(m,55537).
+char(8,55538).
+char(6,55539).
+char(4,55540).
+char(m,55541).
+char(o,55542).
+char(p,55543).
+char(o,55544).
+char(p,55545).
+char(o,55546).
+char(m,55547).
+char(9,55548).
+char(5,55549).
+char(8,55550).
+char(8,55551).
+char(c,55552).
+char(p,55553).
+char(o,55554).
+char(m,55555).
+char(1,55556).
+char(4,55557).
+char(8,55558).
+char(6,55559).
+char(m,55560).
+char(5,55561).
+char(0,55562).
+char(9,55563).
+char(6,55564).
+char(p,55565).
+char(5,55566).
+char(2,55567).
+char(0,55568).
+char(3,55569).
+char(c,55570).
+char(c,55571).
+char(p,55572).
+char(6,55573).
+char(4,55574).
+char(2,55575).
+char(5,55576).
+char(m,55577).
+char(o,55578).
+char(o,55579).
+char(p,55580).
+char(o,55581).
+char(p,55582).
+char(o,55583).
+char(p,55584).
+char(3,55585).
+char(0,55586).
+char(8,55587).
+char(1,55588).
+char(c,55589).
+char(m,55590).
+char(2,55591).
+char(0,55592).
+char(5,55593).
+char(1,55594).
+char(p,55595).
+char(o,55596).
+char(p,55597).
+char(3,55598).
+char(6,55599).
+char(3,55600).
+char(0,55601).
+char(c,55602).
+char(c,55603).
+char(c,55604).
+char(p,55605).
+char(2,55606).
+char(4,55607).
+char(1,55608).
+char(1,55609).
+char(c,55610).
+char(c,55611).
+char(p,55612).
+char(o,55613).
+char(m,55614).
+char(o,55615).
+char(o,55616).
+char(o,55617).
+char(m,55618).
+char(o,55619).
+char(6,55620).
+char(6,55621).
+char(1,55622).
+char(4,55623).
+char(p,55624).
+char(9,55625).
+char(8,55626).
+char(2,55627).
+char(8,55628).
+char(p,55629).
+char(o,55630).
+char(m,55631).
+char(4,55632).
+char(3,55633).
+char(8,55634).
+char(c,55635).
+char(m,55636).
+char(o,55637).
+char(p,55638).
+char(9,55639).
+char(9,55640).
+char(5,55641).
+char(7,55642).
+char(c,55643).
+char(p,55644).
+char(o,55645).
+char(m,55646).
+char(o,55647).
+char(o,55648).
+char(p,55649).
+char(9,55650).
+char(6,55651).
+char(5,55652).
+char(5,55653).
+char(c,55654).
+char(p,55655).
+char(o,55656).
+char(o,55657).
+char(m,55658).
+char(o,55659).
+char(p,55660).
+char(o,55661).
+char(m,55662).
+char(o,55663).
+char(o,55664).
+char(m,55665).
+char(o,55666).
+char(9,55667).
+char(6,55668).
+char(4,55669).
+char(p,55670).
+char(7,55671).
+char(3,55672).
+char(5,55673).
+char(4,55674).
+char(c,55675).
+char(c,55676).
+char(p,55677).
+char(2,55678).
+char(6,55679).
+char(6,55680).
+char(0,55681).
+char(c,55682).
+char(p,55683).
+char(o,55684).
+char(3,55685).
+char(5,55686).
+char(0,55687).
+char(8,55688).
+char(c,55689).
+char(m,55690).
+char(6,55691).
+char(9,55692).
+char(4,55693).
+char(5,55694).
+char(c,55695).
+char(m,55696).
+char(o,55697).
+char(o,55698).
+char(p,55699).
+char(o,55700).
+char(2,55701).
+char(2,55702).
+char(3,55703).
+char(8,55704).
+char(c,55705).
+char(m,55706).
+char(4,55707).
+char(5,55708).
+char(8,55709).
+char(c,55710).
+char(p,55711).
+char(o,55712).
+char(p,55713).
+char(3,55714).
+char(0,55715).
+char(4,55716).
+char(7,55717).
+char(c,55718).
+char(c,55719).
+char(c,55720).
+char(c,55721).
+char(c,55722).
+char(m,55723).
+char(3,55724).
+char(4,55725).
+char(2,55726).
+char(5,55727).
+char(c,55728).
+char(p,55729).
+char(o,55730).
+char(4,55731).
+char(1,55732).
+char(2,55733).
+char(5,55734).
+char(m,55735).
+char(o,55736).
+char(o,55737).
+char(p,55738).
+char(8,55739).
+char(8,55740).
+char(6,55741).
+char(c,55742).
+char(m,55743).
+char(o,55744).
+char(o,55745).
+char(m,55746).
+char(o,55747).
+char(m,55748).
+char(o,55749).
+char(m,55750).
+char(2,55751).
+char(2,55752).
+char(3,55753).
+char(8,55754).
+char(m,55755).
+char(5,55756).
+char(0,55757).
+char(7,55758).
+char(3,55759).
+char(c,55760).
+char(c,55761).
+char(m,55762).
+char(3,55763).
+char(4,55764).
+char(0,55765).
+char(0,55766).
+char(c,55767).
+char(m,55768).
+char(o,55769).
+char(o,55770).
+char(m,55771).
+char(o,55772).
+char(o,55773).
+char(m,55774).
+char(5,55775).
+char(7,55776).
+char(4,55777).
+char(5,55778).
+char(m,55779).
+char(o,55780).
+char(o,55781).
+char(o,55782).
+char(m,55783).
+char(8,55784).
+char(8,55785).
+char(2,55786).
+char(0,55787).
+char(m,55788).
+char(6,55789).
+char(3,55790).
+char(4,55791).
+char(8,55792).
+char(c,55793).
+char(p,55794).
+char(3,55795).
+char(4,55796).
+char(5,55797).
+char(m,55798).
+char(2,55799).
+char(5,55800).
+char(3,55801).
+char(c,55802).
+char(c,55803).
+char(c,55804).
+char(m,55805).
+char(o,55806).
+char(p,55807).
+char(o,55808).
+char(o,55809).
+char(8,55810).
+char(5,55811).
+char(0,55812).
+char(9,55813).
+char(p,55814).
+char(3,55815).
+char(0,55816).
+char(5,55817).
+char(1,55818).
+char(p,55819).
+char(8,55820).
+char(3,55821).
+char(2,55822).
+char(0,55823).
+char(m,55824).
+char(2,55825).
+char(2,55826).
+char(4,55827).
+char(9,55828).
+char(m,55829).
+char(2,55830).
+char(4,55831).
+char(0,55832).
+char(1,55833).
+char(c,55834).
+char(m,55835).
+char(o,55836).
+char(o,55837).
+char(m,55838).
+char(1,55839).
+char(8,55840).
+char(3,55841).
+char(8,55842).
+char(c,55843).
+char(m,55844).
+char(o,55845).
+char(p,55846).
+char(o,55847).
+char(p,55848).
+char(o,55849).
+char(m,55850).
+char(4,55851).
+char(9,55852).
+char(3,55853).
+char(8,55854).
+char(m,55855).
+char(o,55856).
+char(4,55857).
+char(6,55858).
+char(5,55859).
+char(c,55860).
+char(c,55861).
+char(p,55862).
+char(o,55863).
+char(4,55864).
+char(0,55865).
+char(5,55866).
+char(1,55867).
+char(c,55868).
+char(p,55869).
+char(o,55870).
+char(p,55871).
+char(o,55872).
+char(m,55873).
+char(o,55874).
+char(p,55875).
+char(o,55876).
+char(m,55877).
+char(7,55878).
+char(4,55879).
+char(3,55880).
+char(0,55881).
+char(m,55882).
+char(9,55883).
+char(0,55884).
+char(4,55885).
+char(8,55886).
+char(m,55887).
+char(o,55888).
+char(6,55889).
+char(5,55890).
+char(9,55891).
+char(3,55892).
+char(c,55893).
+char(c,55894).
+char(c,55895).
+char(c,55896).
+char(m,55897).
+char(o,55898).
+char(5,55899).
+char(3,55900).
+char(6,55901).
+char(2,55902).
+char(c,55903).
+char(c,55904).
+char(c,55905).
+char(p,55906).
+char(7,55907).
+char(4,55908).
+char(9,55909).
+char(3,55910).
+char(m,55911).
+char(5,55912).
+char(4,55913).
+char(6,55914).
+char(2,55915).
+char(c,55916).
+char(m,55917).
+char(o,55918).
+char(m,55919).
+char(6,55920).
+char(5,55921).
+char(2,55922).
+char(8,55923).
+char(m,55924).
+char(2,55925).
+char(9,55926).
+char(5,55927).
+char(2,55928).
+char(c,55929).
+char(p,55930).
+char(o,55931).
+char(m,55932).
+char(7,55933).
+char(3,55934).
+char(6,55935).
+char(4,55936).
+char(m,55937).
+char(o,55938).
+char(m,55939).
+char(3,55940).
+char(5,55941).
+char(1,55942).
+char(9,55943).
+char(c,55944).
+char(c,55945).
+char(m,55946).
+char(o,55947).
+char(p,55948).
+char(o,55949).
+char(4,55950).
+char(2,55951).
+char(4,55952).
+char(0,55953).
+char(c,55954).
+char(p,55955).
+char(o,55956).
+char(p,55957).
+char(o,55958).
+char(m,55959).
+char(o,55960).
+char(3,55961).
+char(1,55962).
+char(7,55963).
+char(2,55964).
+char(c,55965).
+char(p,55966).
+char(o,55967).
+char(p,55968).
+char(3,55969).
+char(2,55970).
+char(5,55971).
+char(m,55972).
+char(2,55973).
+char(7,55974).
+char(1,55975).
+char(3,55976).
+char(c,55977).
+char(c,55978).
+char(m,55979).
+char(o,55980).
+char(6,55981).
+char(3,55982).
+char(3,55983).
+char(4,55984).
+char(c,55985).
+char(m,55986).
+char(o,55987).
+char(p,55988).
+char(o,55989).
+char(p,55990).
+char(o,55991).
+char(o,55992).
+char(m,55993).
+char(o,55994).
+char(p,55995).
+char(6,55996).
+char(9,55997).
+char(1,55998).
+char(3,55999).
+char(m,56000).
+char(1,56001).
+char(3,56002).
+char(1,56003).
+char(m,56004).
+char(7,56005).
+char(6,56006).
+char(3,56007).
+char(5,56008).
+char(m,56009).
+char(o,56010).
+char(p,56011).
+char(5,56012).
+char(3,56013).
+char(7,56014).
+char(2,56015).
+char(m,56016).
+char(2,56017).
+char(2,56018).
+char(6,56019).
+char(0,56020).
+char(c,56021).
+char(p,56022).
+char(o,56023).
+char(p,56024).
+char(6,56025).
+char(8,56026).
+char(6,56027).
+char(6,56028).
+char(p,56029).
+char(o,56030).
+char(p,56031).
+char(8,56032).
+char(5,56033).
+char(6,56034).
+char(0,56035).
+char(c,56036).
+char(m,56037).
+char(2,56038).
+char(3,56039).
+char(9,56040).
+char(2,56041).
+char(c,56042).
+char(c,56043).
+char(c,56044).
+char(m,56045).
+char(o,56046).
+char(p,56047).
+char(o,56048).
+char(m,56049).
+char(o,56050).
+char(3,56051).
+char(0,56052).
+char(3,56053).
+char(5,56054).
+char(c,56055).
+char(m,56056).
+char(o,56057).
+char(p,56058).
+char(9,56059).
+char(2,56060).
+char(2,56061).
+char(1,56062).
+char(c,56063).
+char(p,56064).
+char(2,56065).
+char(9,56066).
+char(3,56067).
+char(5,56068).
+char(c,56069).
+char(p,56070).
+char(o,56071).
+char(p,56072).
+char(o,56073).
+char(m,56074).
+char(o,56075).
+char(m,56076).
+char(o,56077).
+char(p,56078).
+char(3,56079).
+char(3,56080).
+char(5,56081).
+char(4,56082).
+char(c,56083).
+char(c,56084).
+char(p,56085).
+char(6,56086).
+char(5,56087).
+char(3,56088).
+char(1,56089).
+char(c,56090).
+char(c,56091).
+char(c,56092).
+char(m,56093).
+char(o,56094).
+char(p,56095).
+char(5,56096).
+char(5,56097).
+char(6,56098).
+char(5,56099).
+char(c,56100).
+char(c,56101).
+char(m,56102).
+char(4,56103).
+char(7,56104).
+char(9,56105).
+char(4,56106).
+char(c,56107).
+char(c,56108).
+char(c,56109).
+char(p,56110).
+char(5,56111).
+char(1,56112).
+char(0,56113).
+char(2,56114).
+char(m,56115).
+char(o,56116).
+char(o,56117).
+char(o,56118).
+char(p,56119).
+char(7,56120).
+char(2,56121).
+char(5,56122).
+char(1,56123).
+char(c,56124).
+char(c,56125).
+char(c,56126).
+char(m,56127).
+char(o,56128).
+char(o,56129).
+char(2,56130).
+char(1,56131).
+char(4,56132).
+char(3,56133).
+char(c,56134).
+char(m,56135).
+char(2,56136).
+char(6,56137).
+char(1,56138).
+char(8,56139).
+char(c,56140).
+char(m,56141).
+char(1,56142).
+char(8,56143).
+char(7,56144).
+char(1,56145).
+char(p,56146).
+char(6,56147).
+char(1,56148).
+char(4,56149).
+char(0,56150).
+char(c,56151).
+char(m,56152).
+char(4,56153).
+char(5,56154).
+char(1,56155).
+char(6,56156).
+char(c,56157).
+char(m,56158).
+char(6,56159).
+char(7,56160).
+char(3,56161).
+char(5,56162).
+char(c,56163).
+char(p,56164).
+char(9,56165).
+char(0,56166).
+char(7,56167).
+char(1,56168).
+char(c,56169).
+char(m,56170).
+char(1,56171).
+char(2,56172).
+char(2,56173).
+char(1,56174).
+char(c,56175).
+char(c,56176).
+char(c,56177).
+char(c,56178).
+char(m,56179).
+char(o,56180).
+char(1,56181).
+char(9,56182).
+char(3,56183).
+char(0,56184).
+char(c,56185).
+char(c,56186).
+char(m,56187).
+char(7,56188).
+char(0,56189).
+char(5,56190).
+char(c,56191).
+char(m,56192).
+char(3,56193).
+char(1,56194).
+char(8,56195).
+char(9,56196).
+char(p,56197).
+char(o,56198).
+char(m,56199).
+char(o,56200).
+char(m,56201).
+char(o,56202).
+char(p,56203).
+char(o,56204).
+char(p,56205).
+char(o,56206).
+char(m,56207).
+char(o,56208).
+char(5,56209).
+char(4,56210).
+char(c,56211).
+char(m,56212).
+char(o,56213).
+char(p,56214).
+char(6,56215).
+char(9,56216).
+char(5,56217).
+char(9,56218).
+char(c,56219).
+char(c,56220).
+char(c,56221).
+char(p,56222).
+char(2,56223).
+char(1,56224).
+char(3,56225).
+char(9,56226).
+char(m,56227).
+char(o,56228).
+char(9,56229).
+char(5,56230).
+char(1,56231).
+char(1,56232).
+char(m,56233).
+char(1,56234).
+char(7,56235).
+char(9,56236).
+char(3,56237).
+char(c,56238).
+char(c,56239).
+char(c,56240).
+char(p,56241).
+char(4,56242).
+char(0,56243).
+char(7,56244).
+char(0,56245).
+char(c,56246).
+char(c,56247).
+char(p,56248).
+char(5,56249).
+char(6,56250).
+char(2,56251).
+char(0,56252).
+char(c,56253).
+char(c,56254).
+char(p,56255).
+char(3,56256).
+char(0,56257).
+char(7,56258).
+char(0,56259).
+char(c,56260).
+char(c,56261).
+char(c,56262).
+char(c,56263).
+char(p,56264).
+char(o,56265).
+char(p,56266).
+char(o,56267).
+char(p,56268).
+char(o,56269).
+char(m,56270).
+char(o,56271).
+char(m,56272).
+char(9,56273).
+char(5,56274).
+char(2,56275).
+char(5,56276).
+char(c,56277).
+char(m,56278).
+char(8,56279).
+char(4,56280).
+char(3,56281).
+char(c,56282).
+char(p,56283).
+char(o,56284).
+char(o,56285).
+char(3,56286).
+char(1,56287).
+char(3,56288).
+char(3,56289).
+char(c,56290).
+char(p,56291).
+char(4,56292).
+char(1,56293).
+char(7,56294).
+char(6,56295).
+char(p,56296).
+char(5,56297).
+char(3,56298).
+char(2,56299).
+char(c,56300).
+char(c,56301).
+char(c,56302).
+char(p,56303).
+char(3,56304).
+char(2,56305).
+char(6,56306).
+char(5,56307).
+char(c,56308).
+char(c,56309).
+char(p,56310).
+char(o,56311).
+char(m,56312).
+char(o,56313).
+char(m,56314).
+char(3,56315).
+char(7,56316).
+char(3,56317).
+char(7,56318).
+char(c,56319).
+char(p,56320).
+char(5,56321).
+char(0,56322).
+char(7,56323).
+char(2,56324).
+char(m,56325).
+char(o,56326).
+char(o,56327).
+char(p,56328).
+char(9,56329).
+char(7,56330).
+char(7,56331).
+char(4,56332).
+char(p,56333).
+char(o,56334).
+char(m,56335).
+char(4,56336).
+char(5,56337).
+char(7,56338).
+char(4,56339).
+char(c,56340).
+char(c,56341).
+char(c,56342).
+char(c,56343).
+char(m,56344).
+char(9,56345).
+char(3,56346).
+char(3,56347).
+char(8,56348).
+char(p,56349).
+char(1,56350).
+char(4,56351).
+char(6,56352).
+char(7,56353).
+char(p,56354).
+char(o,56355).
+char(m,56356).
+char(o,56357).
+char(2,56358).
+char(8,56359).
+char(0,56360).
+char(7,56361).
+char(p,56362).
+char(o,56363).
+char(o,56364).
+char(o,56365).
+char(m,56366).
+char(o,56367).
+char(m,56368).
+char(o,56369).
+char(1,56370).
+char(8,56371).
+char(0,56372).
+char(m,56373).
+char(4,56374).
+char(8,56375).
+char(5,56376).
+char(1,56377).
+char(m,56378).
+char(o,56379).
+char(p,56380).
+char(1,56381).
+char(6,56382).
+char(5,56383).
+char(p,56384).
+char(o,56385).
+char(o,56386).
+char(p,56387).
+char(7,56388).
+char(3,56389).
+char(8,56390).
+char(3,56391).
+char(c,56392).
+char(p,56393).
+char(o,56394).
+char(o,56395).
+char(m,56396).
+char(o,56397).
+char(m,56398).
+char(o,56399).
+char(m,56400).
+char(o,56401).
+char(3,56402).
+char(2,56403).
+char(3,56404).
+char(7,56405).
+char(m,56406).
+char(4,56407).
+char(2,56408).
+char(6,56409).
+char(p,56410).
+char(o,56411).
+char(p,56412).
+char(6,56413).
+char(9,56414).
+char(1,56415).
+char(7,56416).
+char(c,56417).
+char(p,56418).
+char(o,56419).
+char(p,56420).
+char(9,56421).
+char(9,56422).
+char(0,56423).
+char(7,56424).
+char(c,56425).
+char(m,56426).
+char(7,56427).
+char(2,56428).
+char(6,56429).
+char(3,56430).
+char(c,56431).
+char(m,56432).
+char(3,56433).
+char(0,56434).
+char(1,56435).
+char(4,56436).
+char(c,56437).
+char(p,56438).
+char(2,56439).
+char(5,56440).
+char(8,56441).
+char(8,56442).
+char(m,56443).
+char(o,56444).
+char(o,56445).
+char(8,56446).
+char(0,56447).
+char(1,56448).
+char(2,56449).
+char(c,56450).
+char(c,56451).
+char(c,56452).
+char(c,56453).
+char(c,56454).
+char(c,56455).
+char(m,56456).
+char(9,56457).
+char(0,56458).
+char(6,56459).
+char(0,56460).
+char(c,56461).
+char(c,56462).
+char(m,56463).
+char(o,56464).
+char(m,56465).
+char(o,56466).
+char(m,56467).
+char(o,56468).
+char(p,56469).
+char(o,56470).
+char(p,56471).
+char(2,56472).
+char(5,56473).
+char(5,56474).
+char(4,56475).
+char(m,56476).
+char(1,56477).
+char(3,56478).
+char(9,56479).
+char(8,56480).
+char(c,56481).
+char(c,56482).
+char(p,56483).
+char(o,56484).
+char(m,56485).
+char(o,56486).
+char(m,56487).
+char(9,56488).
+char(0,56489).
+char(2,56490).
+char(2,56491).
+char(c,56492).
+char(p,56493).
+char(o,56494).
+char(o,56495).
+char(p,56496).
+char(o,56497).
+char(o,56498).
+char(o,56499).
+char(7,56500).
+char(9,56501).
+char(5,56502).
+char(1,56503).
+char(m,56504).
+char(o,56505).
+char(m,56506).
+char(o,56507).
+char(p,56508).
+char(o,56509).
+char(m,56510).
+char(3,56511).
+char(6,56512).
+char(9,56513).
+char(2,56514).
+char(c,56515).
+char(m,56516).
+char(2,56517).
+char(8,56518).
+char(3,56519).
+char(7,56520).
+char(c,56521).
+char(c,56522).
+char(m,56523).
+char(2,56524).
+char(0,56525).
+char(9,56526).
+char(1,56527).
+char(c,56528).
+char(c,56529).
+char(m,56530).
+char(6,56531).
+char(0,56532).
+char(9,56533).
+char(6,56534).
+char(p,56535).
+char(4,56536).
+char(4,56537).
+char(1,56538).
+char(2,56539).
+char(c,56540).
+char(p,56541).
+char(6,56542).
+char(8,56543).
+char(6,56544).
+char(3,56545).
+char(m,56546).
+char(o,56547).
+char(m,56548).
+char(o,56549).
+char(m,56550).
+char(1,56551).
+char(8,56552).
+char(2,56553).
+char(4,56554).
+char(c,56555).
+char(p,56556).
+char(o,56557).
+char(o,56558).
+char(p,56559).
+char(o,56560).
+char(m,56561).
+char(5,56562).
+char(4,56563).
+char(0,56564).
+char(0,56565).
+char(m,56566).
+char(o,56567).
+char(5,56568).
+char(6,56569).
+char(5,56570).
+char(9,56571).
+char(c,56572).
+char(p,56573).
+char(o,56574).
+char(p,56575).
+char(7,56576).
+char(4,56577).
+char(1,56578).
+char(6,56579).
+char(m,56580).
+char(o,56581).
+char(p,56582).
+char(o,56583).
+char(p,56584).
+char(3,56585).
+char(0,56586).
+char(1,56587).
+char(c,56588).
+char(m,56589).
+char(o,56590).
+char(p,56591).
+char(9,56592).
+char(7,56593).
+char(7,56594).
+char(5,56595).
+char(c,56596).
+char(c,56597).
+char(m,56598).
+char(o,56599).
+char(m,56600).
+char(o,56601).
+char(o,56602).
+char(p,56603).
+char(9,56604).
+char(3,56605).
+char(8,56606).
+char(c,56607).
+char(p,56608).
+char(9,56609).
+char(7,56610).
+char(5,56611).
+char(8,56612).
+char(p,56613).
+char(o,56614).
+char(p,56615).
+char(5,56616).
+char(0,56617).
+char(0,56618).
+char(9,56619).
+char(p,56620).
+char(o,56621).
+char(p,56622).
+char(o,56623).
+char(m,56624).
+char(o,56625).
+char(p,56626).
+char(o,56627).
+char(p,56628).
+char(8,56629).
+char(0,56630).
+char(1,56631).
+char(8,56632).
+char(p,56633).
+char(3,56634).
+char(9,56635).
+char(1,56636).
+char(c,56637).
+char(m,56638).
+char(4,56639).
+char(2,56640).
+char(2,56641).
+char(9,56642).
+char(m,56643).
+char(o,56644).
+char(m,56645).
+char(o,56646).
+char(p,56647).
+char(2,56648).
+char(0,56649).
+char(4,56650).
+char(7,56651).
+char(m,56652).
+char(2,56653).
+char(1,56654).
+char(3,56655).
+char(5,56656).
+char(c,56657).
+char(c,56658).
+char(c,56659).
+char(c,56660).
+char(p,56661).
+char(o,56662).
+char(p,56663).
+char(o,56664).
+char(p,56665).
+char(o,56666).
+char(m,56667).
+char(o,56668).
+char(o,56669).
+char(o,56670).
+char(1,56671).
+char(0,56672).
+char(2,56673).
+char(5,56674).
+char(m,56675).
+char(o,56676).
+char(o,56677).
+char(o,56678).
+char(p,56679).
+char(6,56680).
+char(8,56681).
+char(4,56682).
+char(9,56683).
+char(c,56684).
+char(m,56685).
+char(4,56686).
+char(1,56687).
+char(6,56688).
+char(3,56689).
+char(c,56690).
+char(m,56691).
+char(2,56692).
+char(2,56693).
+char(7,56694).
+char(0,56695).
+char(p,56696).
+char(o,56697).
+char(p,56698).
+char(3,56699).
+char(8,56700).
+char(1,56701).
+char(5,56702).
+char(c,56703).
+char(p,56704).
+char(o,56705).
+char(m,56706).
+char(o,56707).
+char(p,56708).
+char(o,56709).
+char(4,56710).
+char(0,56711).
+char(6,56712).
+char(5,56713).
+char(c,56714).
+char(p,56715).
+char(o,56716).
+char(2,56717).
+char(8,56718).
+char(9,56719).
+char(2,56720).
+char(p,56721).
+char(2,56722).
+char(8,56723).
+char(0,56724).
+char(4,56725).
+char(p,56726).
+char(2,56727).
+char(3,56728).
+char(1,56729).
+char(1,56730).
+char(c,56731).
+char(m,56732).
+char(o,56733).
+char(o,56734).
+char(6,56735).
+char(1,56736).
+char(5,56737).
+char(4,56738).
+char(c,56739).
+char(p,56740).
+char(o,56741).
+char(p,56742).
+char(9,56743).
+char(0,56744).
+char(9,56745).
+char(c,56746).
+char(m,56747).
+char(1,56748).
+char(2,56749).
+char(3,56750).
+char(9,56751).
+char(c,56752).
+char(c,56753).
+char(c,56754).
+char(p,56755).
+char(7,56756).
+char(4,56757).
+char(6,56758).
+char(4,56759).
+char(c,56760).
+char(c,56761).
+char(m,56762).
+char(o,56763).
+char(m,56764).
+char(o,56765).
+char(2,56766).
+char(2,56767).
+char(9,56768).
+char(0,56769).
+char(c,56770).
+char(c,56771).
+char(m,56772).
+char(o,56773).
+char(m,56774).
+char(o,56775).
+char(m,56776).
+char(o,56777).
+char(m,56778).
+char(o,56779).
+char(p,56780).
+char(o,56781).
+char(m,56782).
+char(o,56783).
+char(2,56784).
+char(9,56785).
+char(7,56786).
+char(7,56787).
+char(m,56788).
+char(1,56789).
+char(2,56790).
+char(6,56791).
+char(0,56792).
+char(m,56793).
+char(o,56794).
+char(p,56795).
+char(o,56796).
+char(m,56797).
+char(2,56798).
+char(2,56799).
+char(9,56800).
+char(2,56801).
+char(c,56802).
+char(p,56803).
+char(6,56804).
+char(6,56805).
+char(0,56806).
+char(4,56807).
+char(p,56808).
+char(8,56809).
+char(3,56810).
+char(8,56811).
+char(m,56812).
+char(3,56813).
+char(5,56814).
+char(2,56815).
+char(4,56816).
+char(c,56817).
+char(p,56818).
+char(o,56819).
+char(p,56820).
+char(8,56821).
+char(8,56822).
+char(7,56823).
+char(1,56824).
+char(m,56825).
+char(3,56826).
+char(9,56827).
+char(3,56828).
+char(7,56829).
+char(m,56830).
+char(2,56831).
+char(2,56832).
+char(7,56833).
+char(5,56834).
+char(c,56835).
+char(m,56836).
+char(6,56837).
+char(4,56838).
+char(5,56839).
+char(8,56840).
+char(p,56841).
+char(o,56842).
+char(o,56843).
+char(7,56844).
+char(1,56845).
+char(9,56846).
+char(2,56847).
+char(c,56848).
+char(p,56849).
+char(8,56850).
+char(7,56851).
+char(1,56852).
+char(8,56853).
+char(c,56854).
+char(p,56855).
+char(o,56856).
+char(p,56857).
+char(o,56858).
+char(m,56859).
+char(4,56860).
+char(5,56861).
+char(1,56862).
+char(6,56863).
+char(m,56864).
+char(o,56865).
+char(p,56866).
+char(1,56867).
+char(8,56868).
+char(1,56869).
+char(1,56870).
+char(p,56871).
+char(1,56872).
+char(2,56873).
+char(0,56874).
+char(2,56875).
+char(c,56876).
+char(c,56877).
+char(c,56878).
+char(m,56879).
+char(9,56880).
+char(8,56881).
+char(5,56882).
+char(7,56883).
+char(m,56884).
+char(4,56885).
+char(0,56886).
+char(8,56887).
+char(3,56888).
+char(p,56889).
+char(o,56890).
+char(p,56891).
+char(8,56892).
+char(0,56893).
+char(2,56894).
+char(2,56895).
+char(m,56896).
+char(o,56897).
+char(p,56898).
+char(4,56899).
+char(8,56900).
+char(0,56901).
+char(1,56902).
+char(m,56903).
+char(o,56904).
+char(m,56905).
+char(o,56906).
+char(m,56907).
+char(2,56908).
+char(6,56909).
+char(8,56910).
+char(0,56911).
+char(c,56912).
+char(c,56913).
+char(c,56914).
+char(p,56915).
+char(o,56916).
+char(p,56917).
+char(o,56918).
+char(p,56919).
+char(o,56920).
+char(o,56921).
+char(m,56922).
+char(o,56923).
+char(o,56924).
+char(3,56925).
+char(4,56926).
+char(1,56927).
+char(4,56928).
+char(c,56929).
+char(p,56930).
+char(5,56931).
+char(7,56932).
+char(1,56933).
+char(3,56934).
+char(c,56935).
+char(c,56936).
+char(p,56937).
+char(6,56938).
+char(5,56939).
+char(8,56940).
+char(8,56941).
+char(m,56942).
+char(o,56943).
+char(p,56944).
+char(4,56945).
+char(0,56946).
+char(4,56947).
+char(p,56948).
+char(o,56949).
+char(p,56950).
+char(1,56951).
+char(2,56952).
+char(4,56953).
+char(1,56954).
+char(m,56955).
+char(o,56956).
+char(o,56957).
+char(6,56958).
+char(9,56959).
+char(0,56960).
+char(m,56961).
+char(o,56962).
+char(p,56963).
+char(o,56964).
+char(m,56965).
+char(o,56966).
+char(p,56967).
+char(o,56968).
+char(5,56969).
+char(5,56970).
+char(0,56971).
+char(6,56972).
+char(p,56973).
+char(o,56974).
+char(m,56975).
+char(1,56976).
+char(9,56977).
+char(5,56978).
+char(4,56979).
+char(c,56980).
+char(m,56981).
+char(o,56982).
+char(8,56983).
+char(4,56984).
+char(5,56985).
+char(7,56986).
+char(c,56987).
+char(p,56988).
+char(2,56989).
+char(2,56990).
+char(5,56991).
+char(7,56992).
+char(c,56993).
+char(p,56994).
+char(2,56995).
+char(5,56996).
+char(5,56997).
+char(3,56998).
+char(p,56999).
+char(6,57000).
+char(8,57001).
+char(0,57002).
+char(m,57003).
+char(1,57004).
+char(4,57005).
+char(2,57006).
+char(3,57007).
+char(p,57008).
+char(o,57009).
+char(p,57010).
+char(o,57011).
+char(m,57012).
+char(3,57013).
+char(2,57014).
+char(1,57015).
+char(5,57016).
+char(c,57017).
+char(c,57018).
+char(c,57019).
+char(c,57020).
+char(m,57021).
+char(6,57022).
+char(3,57023).
+char(6,57024).
+char(c,57025).
+char(m,57026).
+char(2,57027).
+char(8,57028).
+char(7,57029).
+char(6,57030).
+char(c,57031).
+char(c,57032).
+char(p,57033).
+char(o,57034).
+char(1,57035).
+char(4,57036).
+char(9,57037).
+char(8,57038).
+char(c,57039).
+char(p,57040).
+char(9,57041).
+char(8,57042).
+char(3,57043).
+char(6,57044).
+char(p,57045).
+char(8,57046).
+char(5,57047).
+char(1,57048).
+char(4,57049).
+char(c,57050).
+char(p,57051).
+char(o,57052).
+char(o,57053).
+char(o,57054).
+char(9,57055).
+char(5,57056).
+char(3,57057).
+char(0,57058).
+char(c,57059).
+char(p,57060).
+char(o,57061).
+char(5,57062).
+char(6,57063).
+char(8,57064).
+char(8,57065).
+char(c,57066).
+char(c,57067).
+char(m,57068).
+char(7,57069).
+char(7,57070).
+char(7,57071).
+char(3,57072).
+char(m,57073).
+char(6,57074).
+char(3,57075).
+char(9,57076).
+char(7,57077).
+char(c,57078).
+char(m,57079).
+char(o,57080).
+char(m,57081).
+char(6,57082).
+char(0,57083).
+char(1,57084).
+char(m,57085).
+char(6,57086).
+char(9,57087).
+char(7,57088).
+char(9,57089).
+char(c,57090).
+char(m,57091).
+char(7,57092).
+char(3,57093).
+char(8,57094).
+char(1,57095).
+char(c,57096).
+char(m,57097).
+char(o,57098).
+char(m,57099).
+char(2,57100).
+char(5,57101).
+char(8,57102).
+char(5,57103).
+char(p,57104).
+char(o,57105).
+char(m,57106).
+char(1,57107).
+char(8,57108).
+char(7,57109).
+char(7,57110).
+char(c,57111).
+char(c,57112).
+char(m,57113).
+char(7,57114).
+char(5,57115).
+char(4,57116).
+char(1,57117).
+char(p,57118).
+char(9,57119).
+char(1,57120).
+char(5,57121).
+char(2,57122).
+char(m,57123).
+char(4,57124).
+char(6,57125).
+char(4,57126).
+char(0,57127).
+char(m,57128).
+char(5,57129).
+char(5,57130).
+char(6,57131).
+char(8,57132).
+char(m,57133).
+char(9,57134).
+char(5,57135).
+char(0,57136).
+char(1,57137).
+char(c,57138).
+char(c,57139).
+char(p,57140).
+char(o,57141).
+char(p,57142).
+char(9,57143).
+char(3,57144).
+char(2,57145).
+char(6,57146).
+char(c,57147).
+char(c,57148).
+char(c,57149).
+char(p,57150).
+char(o,57151).
+char(4,57152).
+char(7,57153).
+char(8,57154).
+char(4,57155).
+char(c,57156).
+char(c,57157).
+char(c,57158).
+char(m,57159).
+char(o,57160).
+char(m,57161).
+char(3,57162).
+char(8,57163).
+char(5,57164).
+char(4,57165).
+char(c,57166).
+char(c,57167).
+char(c,57168).
+char(c,57169).
+char(p,57170).
+char(o,57171).
+char(p,57172).
+char(7,57173).
+char(3,57174).
+char(9,57175).
+char(0,57176).
+char(c,57177).
+char(p,57178).
+char(o,57179).
+char(o,57180).
+char(p,57181).
+char(8,57182).
+char(1,57183).
+char(2,57184).
+char(5,57185).
+char(c,57186).
+char(c,57187).
+char(m,57188).
+char(o,57189).
+char(8,57190).
+char(4,57191).
+char(8,57192).
+char(6,57193).
+char(c,57194).
+char(m,57195).
+char(5,57196).
+char(9,57197).
+char(8,57198).
+char(9,57199).
+char(c,57200).
+char(m,57201).
+char(o,57202).
+char(9,57203).
+char(4,57204).
+char(2,57205).
+char(1,57206).
+char(c,57207).
+char(m,57208).
+char(2,57209).
+char(9,57210).
+char(0,57211).
+char(6,57212).
+char(p,57213).
+char(6,57214).
+char(6,57215).
+char(1,57216).
+char(7,57217).
+char(c,57218).
+char(p,57219).
+char(o,57220).
+char(m,57221).
+char(o,57222).
+char(p,57223).
+char(o,57224).
+char(6,57225).
+char(9,57226).
+char(0,57227).
+char(9,57228).
+char(c,57229).
+char(p,57230).
+char(o,57231).
+char(3,57232).
+char(3,57233).
+char(7,57234).
+char(3,57235).
+char(c,57236).
+char(c,57237).
+char(c,57238).
+char(c,57239).
+char(p,57240).
+char(o,57241).
+char(m,57242).
+char(8,57243).
+char(8,57244).
+char(2,57245).
+char(6,57246).
+char(c,57247).
+char(c,57248).
+char(c,57249).
+char(c,57250).
+char(c,57251).
+char(c,57252).
+char(m,57253).
+char(o,57254).
+char(p,57255).
+char(o,57256).
+char(p,57257).
+char(2,57258).
+char(8,57259).
+char(2,57260).
+char(1,57261).
+char(p,57262).
+char(6,57263).
+char(8,57264).
+char(4,57265).
+char(6,57266).
+char(c,57267).
+char(c,57268).
+char(p,57269).
+char(o,57270).
+char(o,57271).
+char(4,57272).
+char(5,57273).
+char(2,57274).
+char(p,57275).
+char(o,57276).
+char(m,57277).
+char(1,57278).
+char(3,57279).
+char(7,57280).
+char(9,57281).
+char(c,57282).
+char(c,57283).
+char(m,57284).
+char(o,57285).
+char(7,57286).
+char(8,57287).
+char(0,57288).
+char(8,57289).
+char(c,57290).
+char(c,57291).
+char(m,57292).
+char(o,57293).
+char(o,57294).
+char(m,57295).
+char(6,57296).
+char(2,57297).
+char(8,57298).
+char(4,57299).
+char(c,57300).
+char(c,57301).
+char(c,57302).
+char(p,57303).
+char(4,57304).
+char(3,57305).
+char(5,57306).
+char(9,57307).
+char(c,57308).
+char(p,57309).
+char(o,57310).
+char(o,57311).
+char(p,57312).
+char(8,57313).
+char(9,57314).
+char(8,57315).
+char(1,57316).
+char(c,57317).
+char(m,57318).
+char(4,57319).
+char(7,57320).
+char(5,57321).
+char(5,57322).
+char(p,57323).
+char(o,57324).
+char(p,57325).
+char(o,57326).
+char(o,57327).
+char(p,57328).
+char(2,57329).
+char(4,57330).
+char(6,57331).
+char(1,57332).
+char(p,57333).
+char(o,57334).
+char(o,57335).
+char(p,57336).
+char(6,57337).
+char(5,57338).
+char(4,57339).
+char(5,57340).
+char(m,57341).
+char(2,57342).
+char(6,57343).
+char(7,57344).
+char(9,57345).
+char(c,57346).
+char(c,57347).
+char(c,57348).
+char(c,57349).
+char(c,57350).
+char(c,57351).
+char(c,57352).
+char(c,57353).
+char(p,57354).
+char(o,57355).
+char(p,57356).
+char(o,57357).
+char(o,57358).
+char(p,57359).
+char(o,57360).
+char(o,57361).
+char(o,57362).
+char(m,57363).
+char(o,57364).
+char(p,57365).
+char(6,57366).
+char(7,57367).
+char(1,57368).
+char(c,57369).
+char(c,57370).
+char(c,57371).
+char(c,57372).
+char(c,57373).
+char(p,57374).
+char(o,57375).
+char(m,57376).
+char(8,57377).
+char(1,57378).
+char(4,57379).
+char(1,57380).
+char(m,57381).
+char(7,57382).
+char(7,57383).
+char(9,57384).
+char(5,57385).
+char(m,57386).
+char(8,57387).
+char(1,57388).
+char(8,57389).
+char(7,57390).
+char(c,57391).
+char(p,57392).
+char(1,57393).
+char(9,57394).
+char(8,57395).
+char(9,57396).
+char(c,57397).
+char(c,57398).
+char(p,57399).
+char(3,57400).
+char(8,57401).
+char(6,57402).
+char(0,57403).
+char(c,57404).
+char(p,57405).
+char(8,57406).
+char(9,57407).
+char(7,57408).
+char(5,57409).
+char(c,57410).
+char(c,57411).
+char(c,57412).
+char(m,57413).
+char(9,57414).
+char(9,57415).
+char(4,57416).
+char(6,57417).
+char(m,57418).
+char(4,57419).
+char(9,57420).
+char(4,57421).
+char(5,57422).
+char(p,57423).
+char(3,57424).
+char(3,57425).
+char(6,57426).
+char(3,57427).
+char(p,57428).
+char(o,57429).
+char(m,57430).
+char(7,57431).
+char(4,57432).
+char(0,57433).
+char(7,57434).
+char(c,57435).
+char(c,57436).
+char(c,57437).
+char(m,57438).
+char(1,57439).
+char(3,57440).
+char(9,57441).
+char(3,57442).
+char(p,57443).
+char(7,57444).
+char(6,57445).
+char(1,57446).
+char(6,57447).
+char(c,57448).
+char(p,57449).
+char(3,57450).
+char(2,57451).
+char(1,57452).
+char(3,57453).
+char(m,57454).
+char(o,57455).
+char(4,57456).
+char(0,57457).
+char(4,57458).
+char(0,57459).
+char(m,57460).
+char(1,57461).
+char(1,57462).
+char(6,57463).
+char(1,57464).
+char(c,57465).
+char(p,57466).
+char(4,57467).
+char(8,57468).
+char(8,57469).
+char(8,57470).
+char(c,57471).
+char(c,57472).
+char(c,57473).
+char(p,57474).
+char(5,57475).
+char(8,57476).
+char(1,57477).
+char(7,57478).
+char(p,57479).
+char(o,57480).
+char(o,57481).
+char(m,57482).
+char(5,57483).
+char(9,57484).
+char(9,57485).
+char(7,57486).
+char(c,57487).
+char(p,57488).
+char(o,57489).
+char(m,57490).
+char(4,57491).
+char(0,57492).
+char(8,57493).
+char(3,57494).
+char(c,57495).
+char(c,57496).
+char(p,57497).
+char(4,57498).
+char(7,57499).
+char(4,57500).
+char(6,57501).
+char(p,57502).
+char(1,57503).
+char(7,57504).
+char(4,57505).
+char(3,57506).
+char(c,57507).
+char(c,57508).
+char(p,57509).
+char(o,57510).
+char(m,57511).
+char(o,57512).
+char(p,57513).
+char(8,57514).
+char(9,57515).
+char(5,57516).
+char(7,57517).
+char(m,57518).
+char(5,57519).
+char(2,57520).
+char(8,57521).
+char(8,57522).
+char(p,57523).
+char(o,57524).
+char(m,57525).
+char(o,57526).
+char(m,57527).
+char(4,57528).
+char(1,57529).
+char(9,57530).
+char(p,57531).
+char(2,57532).
+char(2,57533).
+char(8,57534).
+char(0,57535).
+char(m,57536).
+char(o,57537).
+char(m,57538).
+char(o,57539).
+char(p,57540).
+char(9,57541).
+char(5,57542).
+char(4,57543).
+char(2,57544).
+char(m,57545).
+char(2,57546).
+char(8,57547).
+char(9,57548).
+char(9,57549).
+char(c,57550).
+char(c,57551).
+char(p,57552).
+char(o,57553).
+char(o,57554).
+char(m,57555).
+char(o,57556).
+char(m,57557).
+char(o,57558).
+char(m,57559).
+char(o,57560).
+char(m,57561).
+char(4,57562).
+char(6,57563).
+char(6,57564).
+char(4,57565).
+char(c,57566).
+char(m,57567).
+char(1,57568).
+char(5,57569).
+char(8,57570).
+char(0,57571).
+char(m,57572).
+char(9,57573).
+char(7,57574).
+char(5,57575).
+char(4,57576).
+char(c,57577).
+char(p,57578).
+char(5,57579).
+char(8,57580).
+char(3,57581).
+char(9,57582).
+char(m,57583).
+char(o,57584).
+char(p,57585).
+char(o,57586).
+char(p,57587).
+char(o,57588).
+char(9,57589).
+char(8,57590).
+char(7,57591).
+char(2,57592).
+char(m,57593).
+char(9,57594).
+char(9,57595).
+char(3,57596).
+char(0,57597).
+char(c,57598).
+char(m,57599).
+char(4,57600).
+char(7,57601).
+char(6,57602).
+char(9,57603).
+char(c,57604).
+char(c,57605).
+char(m,57606).
+char(4,57607).
+char(5,57608).
+char(2,57609).
+char(4,57610).
+char(m,57611).
+char(9,57612).
+char(9,57613).
+char(5,57614).
+char(8,57615).
+char(m,57616).
+char(8,57617).
+char(6,57618).
+char(9,57619).
+char(1,57620).
+char(m,57621).
+char(o,57622).
+char(p,57623).
+char(2,57624).
+char(2,57625).
+char(6,57626).
+char(c,57627).
+char(m,57628).
+char(6,57629).
+char(8,57630).
+char(3,57631).
+char(m,57632).
+char(o,57633).
+char(m,57634).
+char(6,57635).
+char(6,57636).
+char(5,57637).
+char(0,57638).
+char(c,57639).
+char(p,57640).
+char(6,57641).
+char(4,57642).
+char(0,57643).
+char(8,57644).
+char(p,57645).
+char(9,57646).
+char(0,57647).
+char(5,57648).
+char(1,57649).
+char(c,57650).
+char(p,57651).
+char(o,57652).
+char(m,57653).
+char(o,57654).
+char(m,57655).
+char(o,57656).
+char(m,57657).
+char(o,57658).
+char(o,57659).
+char(4,57660).
+char(4,57661).
+char(0,57662).
+char(m,57663).
+char(o,57664).
+char(4,57665).
+char(4,57666).
+char(5,57667).
+char(5,57668).
+char(m,57669).
+char(5,57670).
+char(6,57671).
+char(0,57672).
+char(7,57673).
+char(c,57674).
+char(p,57675).
+char(4,57676).
+char(7,57677).
+char(7,57678).
+char(8,57679).
+char(c,57680).
+char(c,57681).
+char(m,57682).
+char(o,57683).
+char(m,57684).
+char(o,57685).
+char(m,57686).
+char(o,57687).
+char(9,57688).
+char(7,57689).
+char(4,57690).
+char(0,57691).
+char(c,57692).
+char(p,57693).
+char(7,57694).
+char(9,57695).
+char(3,57696).
+char(m,57697).
+char(o,57698).
+char(m,57699).
+char(3,57700).
+char(8,57701).
+char(8,57702).
+char(8,57703).
+char(m,57704).
+char(o,57705).
+char(p,57706).
+char(o,57707).
+char(m,57708).
+char(o,57709).
+char(p,57710).
+char(o,57711).
+char(m,57712).
+char(o,57713).
+char(m,57714).
+char(o,57715).
+char(m,57716).
+char(1,57717).
+char(2,57718).
+char(2,57719).
+char(m,57720).
+char(o,57721).
+char(m,57722).
+char(o,57723).
+char(p,57724).
+char(4,57725).
+char(5,57726).
+char(9,57727).
+char(0,57728).
+char(p,57729).
+char(1,57730).
+char(9,57731).
+char(0,57732).
+char(c,57733).
+char(p,57734).
+char(1,57735).
+char(5,57736).
+char(1,57737).
+char(4,57738).
+char(c,57739).
+char(c,57740).
+char(c,57741).
+char(m,57742).
+char(o,57743).
+char(6,57744).
+char(0,57745).
+char(9,57746).
+char(1,57747).
+char(c,57748).
+char(m,57749).
+char(1,57750).
+char(6,57751).
+char(2,57752).
+char(7,57753).
+char(m,57754).
+char(1,57755).
+char(4,57756).
+char(0,57757).
+char(3,57758).
+char(c,57759).
+char(p,57760).
+char(4,57761).
+char(1,57762).
+char(3,57763).
+char(0,57764).
+char(p,57765).
+char(o,57766).
+char(m,57767).
+char(o,57768).
+char(m,57769).
+char(6,57770).
+char(8,57771).
+char(5,57772).
+char(0,57773).
+char(p,57774).
+char(o,57775).
+char(m,57776).
+char(1,57777).
+char(1,57778).
+char(2,57779).
+char(0,57780).
+char(c,57781).
+char(p,57782).
+char(1,57783).
+char(1,57784).
+char(7,57785).
+char(9,57786).
+char(c,57787).
+char(p,57788).
+char(o,57789).
+char(p,57790).
+char(o,57791).
+char(m,57792).
+char(7,57793).
+char(3,57794).
+char(6,57795).
+char(7,57796).
+char(p,57797).
+char(o,57798).
+char(o,57799).
+char(p,57800).
+char(4,57801).
+char(8,57802).
+char(0,57803).
+char(p,57804).
+char(2,57805).
+char(1,57806).
+char(8,57807).
+char(9,57808).
+char(c,57809).
+char(m,57810).
+char(3,57811).
+char(6,57812).
+char(7,57813).
+char(p,57814).
+char(o,57815).
+char(o,57816).
+char(m,57817).
+char(o,57818).
+char(p,57819).
+char(4,57820).
+char(0,57821).
+char(5,57822).
+char(5,57823).
+char(p,57824).
+char(6,57825).
+char(6,57826).
+char(5,57827).
+char(6,57828).
+char(m,57829).
+char(o,57830).
+char(m,57831).
+char(o,57832).
+char(1,57833).
+char(4,57834).
+char(6,57835).
+char(4,57836).
+char(m,57837).
+char(6,57838).
+char(2,57839).
+char(6,57840).
+char(9,57841).
+char(m,57842).
+char(4,57843).
+char(2,57844).
+char(4,57845).
+char(6,57846).
+char(c,57847).
+char(c,57848).
+char(p,57849).
+char(6,57850).
+char(8,57851).
+char(7,57852).
+char(p,57853).
+char(o,57854).
+char(o,57855).
+char(p,57856).
+char(o,57857).
+char(8,57858).
+char(5,57859).
+char(5,57860).
+char(8,57861).
+char(p,57862).
+char(8,57863).
+char(6,57864).
+char(8,57865).
+char(5,57866).
+char(c,57867).
+char(m,57868).
+char(3,57869).
+char(9,57870).
+char(4,57871).
+char(9,57872).
+char(c,57873).
+char(m,57874).
+char(o,57875).
+char(m,57876).
+char(3,57877).
+char(6,57878).
+char(1,57879).
+char(5,57880).
+char(c,57881).
+char(m,57882).
+char(o,57883).
+char(7,57884).
+char(8,57885).
+char(7,57886).
+char(2,57887).
+char(p,57888).
+char(o,57889).
+char(2,57890).
+char(0,57891).
+char(3,57892).
+char(6,57893).
+char(m,57894).
+char(7,57895).
+char(3,57896).
+char(7,57897).
+char(0,57898).
+char(c,57899).
+char(c,57900).
+char(p,57901).
+char(o,57902).
+char(p,57903).
+char(5,57904).
+char(5,57905).
+char(8,57906).
+char(7,57907).
+char(p,57908).
+char(o,57909).
+char(m,57910).
+char(9,57911).
+char(1,57912).
+char(3,57913).
+char(4,57914).
+char(c,57915).
+char(c,57916).
+char(c,57917).
+char(p,57918).
+char(6,57919).
+char(7,57920).
+char(6,57921).
+char(7,57922).
+char(c,57923).
+char(p,57924).
+char(o,57925).
+char(m,57926).
+char(2,57927).
+char(2,57928).
+char(5,57929).
+char(8,57930).
+char(c,57931).
+char(p,57932).
+char(o,57933).
+char(6,57934).
+char(2,57935).
+char(2,57936).
+char(0,57937).
+char(c,57938).
+char(c,57939).
+char(p,57940).
+char(o,57941).
+char(p,57942).
+char(o,57943).
+char(7,57944).
+char(7,57945).
+char(3,57946).
+char(0,57947).
+char(c,57948).
+char(c,57949).
+char(m,57950).
+char(o,57951).
+char(9,57952).
+char(3,57953).
+char(7,57954).
+char(8,57955).
+char(p,57956).
+char(8,57957).
+char(6,57958).
+char(4,57959).
+char(1,57960).
+char(p,57961).
+char(7,57962).
+char(4,57963).
+char(1,57964).
+char(9,57965).
+char(c,57966).
+char(p,57967).
+char(o,57968).
+char(o,57969).
+char(m,57970).
+char(5,57971).
+char(9,57972).
+char(0,57973).
+char(4,57974).
+char(c,57975).
+char(c,57976).
+char(c,57977).
+char(m,57978).
+char(9,57979).
+char(2,57980).
+char(5,57981).
+char(5,57982).
+char(c,57983).
+char(p,57984).
+char(o,57985).
+char(m,57986).
+char(7,57987).
+char(5,57988).
+char(7,57989).
+char(5,57990).
+char(c,57991).
+char(p,57992).
+char(o,57993).
+char(o,57994).
+char(m,57995).
+char(3,57996).
+char(6,57997).
+char(3,57998).
+char(2,57999).
+char(c,58000).
+char(m,58001).
+char(o,58002).
+char(4,58003).
+char(0,58004).
+char(1,58005).
+char(9,58006).
+char(c,58007).
+char(p,58008).
+char(3,58009).
+char(9,58010).
+char(7,58011).
+char(4,58012).
+char(p,58013).
+char(5,58014).
+char(2,58015).
+char(0,58016).
+char(0,58017).
+char(m,58018).
+char(o,58019).
+char(p,58020).
+char(o,58021).
+char(8,58022).
+char(5,58023).
+char(8,58024).
+char(6,58025).
+char(c,58026).
+char(p,58027).
+char(o,58028).
+char(7,58029).
+char(4,58030).
+char(4,58031).
+char(3,58032).
+char(m,58033).
+char(4,58034).
+char(6,58035).
+char(3,58036).
+char(c,58037).
+char(c,58038).
+char(p,58039).
+char(o,58040).
+char(m,58041).
+char(o,58042).
+char(m,58043).
+char(9,58044).
+char(4,58045).
+char(6,58046).
+char(3,58047).
+char(p,58048).
+char(o,58049).
+char(o,58050).
+char(m,58051).
+char(o,58052).
+char(p,58053).
+char(3,58054).
+char(2,58055).
+char(9,58056).
+char(5,58057).
+char(c,58058).
+char(p,58059).
+char(3,58060).
+char(9,58061).
+char(0,58062).
+char(c,58063).
+char(m,58064).
+char(3,58065).
+char(9,58066).
+char(7,58067).
+char(p,58068).
+char(4,58069).
+char(5,58070).
+char(3,58071).
+char(1,58072).
+char(m,58073).
+char(7,58074).
+char(3,58075).
+char(5,58076).
+char(p,58077).
+char(o,58078).
+char(p,58079).
+char(6,58080).
+char(0,58081).
+char(4,58082).
+char(7,58083).
+char(c,58084).
+char(p,58085).
+char(o,58086).
+char(p,58087).
+char(3,58088).
+char(9,58089).
+char(c,58090).
+char(p,58091).
+char(6,58092).
+char(2,58093).
+char(5,58094).
+char(2,58095).
+char(c,58096).
+char(p,58097).
+char(4,58098).
+char(2,58099).
+char(1,58100).
+char(c,58101).
+char(p,58102).
+char(o,58103).
+char(o,58104).
+char(p,58105).
+char(o,58106).
+char(o,58107).
+char(p,58108).
+char(6,58109).
+char(4,58110).
+char(7,58111).
+char(9,58112).
+char(c,58113).
+char(c,58114).
+char(c,58115).
+char(c,58116).
+char(m,58117).
+char(6,58118).
+char(5,58119).
+char(4,58120).
+char(7,58121).
+char(c,58122).
+char(p,58123).
+char(3,58124).
+char(7,58125).
+char(5,58126).
+char(2,58127).
+char(p,58128).
+char(6,58129).
+char(4,58130).
+char(1,58131).
+char(1,58132).
+char(m,58133).
+char(o,58134).
+char(p,58135).
+char(o,58136).
+char(o,58137).
+char(p,58138).
+char(o,58139).
+char(p,58140).
+char(o,58141).
+char(7,58142).
+char(5,58143).
+char(0,58144).
+char(1,58145).
+char(c,58146).
+char(c,58147).
+char(c,58148).
+char(c,58149).
+char(c,58150).
+char(p,58151).
+char(7,58152).
+char(8,58153).
+char(2,58154).
+char(9,58155).
+char(p,58156).
+char(o,58157).
+char(p,58158).
+char(4,58159).
+char(1,58160).
+char(2,58161).
+char(5,58162).
+char(m,58163).
+char(o,58164).
+char(p,58165).
+char(o,58166).
+char(m,58167).
+char(o,58168).
+char(m,58169).
+char(1,58170).
+char(3,58171).
+char(0,58172).
+char(3,58173).
+char(p,58174).
+char(1,58175).
+char(8,58176).
+char(3,58177).
+char(3,58178).
+char(m,58179).
+char(7,58180).
+char(1,58181).
+char(8,58182).
+char(8,58183).
+char(c,58184).
+char(m,58185).
+char(o,58186).
+char(m,58187).
+char(o,58188).
+char(2,58189).
+char(3,58190).
+char(1,58191).
+char(p,58192).
+char(2,58193).
+char(2,58194).
+char(4,58195).
+char(m,58196).
+char(6,58197).
+char(2,58198).
+char(3,58199).
+char(1,58200).
+char(c,58201).
+char(m,58202).
+char(o,58203).
+char(m,58204).
+char(4,58205).
+char(0,58206).
+char(2,58207).
+char(7,58208).
+char(c,58209).
+char(m,58210).
+char(o,58211).
+char(p,58212).
+char(4,58213).
+char(0,58214).
+char(7,58215).
+char(6,58216).
+char(c,58217).
+char(c,58218).
+char(m,58219).
+char(3,58220).
+char(3,58221).
+char(7,58222).
+char(5,58223).
+char(m,58224).
+char(o,58225).
+char(o,58226).
+char(m,58227).
+char(8,58228).
+char(4,58229).
+char(8,58230).
+char(2,58231).
+char(c,58232).
+char(m,58233).
+char(o,58234).
+char(6,58235).
+char(0,58236).
+char(2,58237).
+char(2,58238).
+char(p,58239).
+char(o,58240).
+char(m,58241).
+char(3,58242).
+char(2,58243).
+char(8,58244).
+char(4,58245).
+char(c,58246).
+char(c,58247).
+char(c,58248).
+char(c,58249).
+char(c,58250).
+char(c,58251).
+char(m,58252).
+char(o,58253).
+char(9,58254).
+char(7,58255).
+char(7,58256).
+char(4,58257).
+char(c,58258).
+char(m,58259).
+char(o,58260).
+char(m,58261).
+char(6,58262).
+char(6,58263).
+char(4,58264).
+char(5,58265).
+char(p,58266).
+char(1,58267).
+char(9,58268).
+char(6,58269).
+char(7,58270).
+char(p,58271).
+char(o,58272).
+char(p,58273).
+char(o,58274).
+char(1,58275).
+char(3,58276).
+char(7,58277).
+char(4,58278).
+char(c,58279).
+char(c,58280).
+char(m,58281).
+char(7,58282).
+char(1,58283).
+char(9,58284).
+char(2,58285).
+char(c,58286).
+char(m,58287).
+char(1,58288).
+char(6,58289).
+char(6,58290).
+char(4,58291).
+char(p,58292).
+char(3,58293).
+char(6,58294).
+char(7,58295).
+char(4,58296).
+char(c,58297).
+char(p,58298).
+char(9,58299).
+char(6,58300).
+char(5,58301).
+char(7,58302).
+char(c,58303).
+char(m,58304).
+char(5,58305).
+char(2,58306).
+char(6,58307).
+char(1,58308).
+char(m,58309).
+char(3,58310).
+char(5,58311).
+char(4,58312).
+char(7,58313).
+char(p,58314).
+char(7,58315).
+char(3,58316).
+char(9,58317).
+char(9,58318).
+char(c,58319).
+char(p,58320).
+char(o,58321).
+char(o,58322).
+char(m,58323).
+char(1,58324).
+char(9,58325).
+char(7,58326).
+char(3,58327).
+char(m,58328).
+char(2,58329).
+char(9,58330).
+char(7,58331).
+char(4,58332).
+char(m,58333).
+char(5,58334).
+char(3,58335).
+char(7,58336).
+char(6,58337).
+char(p,58338).
+char(6,58339).
+char(4,58340).
+char(1,58341).
+char(8,58342).
+char(c,58343).
+char(c,58344).
+char(m,58345).
+char(o,58346).
+char(m,58347).
+char(o,58348).
+char(p,58349).
+char(3,58350).
+char(8,58351).
+char(8,58352).
+char(7,58353).
+char(m,58354).
+char(3,58355).
+char(6,58356).
+char(7,58357).
+char(8,58358).
+char(p,58359).
+char(9,58360).
+char(4,58361).
+char(6,58362).
+char(4,58363).
+char(c,58364).
+char(p,58365).
+char(6,58366).
+char(0,58367).
+char(7,58368).
+char(6,58369).
+char(c,58370).
+char(p,58371).
+char(o,58372).
+char(p,58373).
+char(o,58374).
+char(p,58375).
+char(o,58376).
+char(o,58377).
+char(o,58378).
+char(p,58379).
+char(4,58380).
+char(1,58381).
+char(8,58382).
+char(0,58383).
+char(m,58384).
+char(o,58385).
+char(o,58386).
+char(6,58387).
+char(0,58388).
+char(1,58389).
+char(0,58390).
+char(c,58391).
+char(p,58392).
+char(o,58393).
+char(o,58394).
+char(o,58395).
+char(p,58396).
+char(2,58397).
+char(3,58398).
+char(8,58399).
+char(9,58400).
+char(p,58401).
+char(6,58402).
+char(2,58403).
+char(4,58404).
+char(0,58405).
+char(p,58406).
+char(o,58407).
+char(9,58408).
+char(1,58409).
+char(0,58410).
+char(3,58411).
+char(m,58412).
+char(8,58413).
+char(9,58414).
+char(8,58415).
+char(5,58416).
+char(c,58417).
+char(m,58418).
+char(7,58419).
+char(9,58420).
+char(4,58421).
+char(c,58422).
+char(m,58423).
+char(o,58424).
+char(p,58425).
+char(3,58426).
+char(1,58427).
+char(3,58428).
+char(9,58429).
+char(c,58430).
+char(c,58431).
+char(c,58432).
+char(p,58433).
+char(2,58434).
+char(9,58435).
+char(5,58436).
+char(0,58437).
+char(c,58438).
+char(p,58439).
+char(6,58440).
+char(8,58441).
+char(8,58442).
+char(5,58443).
+char(m,58444).
+char(o,58445).
+char(p,58446).
+char(3,58447).
+char(1,58448).
+char(7,58449).
+char(c,58450).
+char(c,58451).
+char(c,58452).
+char(c,58453).
+char(p,58454).
+char(o,58455).
+char(m,58456).
+char(o,58457).
+char(8,58458).
+char(7,58459).
+char(8,58460).
+char(5,58461).
+char(c,58462).
+char(c,58463).
+char(m,58464).
+char(o,58465).
+char(9,58466).
+char(1,58467).
+char(4,58468).
+char(9,58469).
+char(c,58470).
+char(c,58471).
+char(m,58472).
+char(o,58473).
+char(o,58474).
+char(m,58475).
+char(1,58476).
+char(1,58477).
+char(2,58478).
+char(2,58479).
+char(m,58480).
+char(o,58481).
+char(7,58482).
+char(3,58483).
+char(0,58484).
+char(6,58485).
+char(p,58486).
+char(5,58487).
+char(5,58488).
+char(2,58489).
+char(2,58490).
+char(p,58491).
+char(6,58492).
+char(2,58493).
+char(4,58494).
+char(7,58495).
+char(c,58496).
+char(c,58497).
+char(m,58498).
+char(4,58499).
+char(6,58500).
+char(4,58501).
+char(0,58502).
+char(m,58503).
+char(o,58504).
+char(m,58505).
+char(o,58506).
+char(8,58507).
+char(3,58508).
+char(7,58509).
+char(2,58510).
+char(c,58511).
+char(c,58512).
+char(m,58513).
+char(1,58514).
+char(4,58515).
+char(9,58516).
+char(3,58517).
+char(c,58518).
+char(p,58519).
+char(4,58520).
+char(4,58521).
+char(5,58522).
+char(3,58523).
+char(c,58524).
+char(c,58525).
+char(c,58526).
+char(p,58527).
+char(o,58528).
+char(m,58529).
+char(6,58530).
+char(5,58531).
+char(3,58532).
+char(8,58533).
+char(p,58534).
+char(8,58535).
+char(8,58536).
+char(8,58537).
+char(6,58538).
+char(m,58539).
+char(3,58540).
+char(0,58541).
+char(1,58542).
+char(6,58543).
+char(m,58544).
+char(9,58545).
+char(7,58546).
+char(4,58547).
+char(4,58548).
+char(p,58549).
+char(4,58550).
+char(8,58551).
+char(7,58552).
+char(4,58553).
+char(m,58554).
+char(4,58555).
+char(6,58556).
+char(5,58557).
+char(3,58558).
+char(c,58559).
+char(m,58560).
+char(2,58561).
+char(5,58562).
+char(0,58563).
+char(6,58564).
+char(c,58565).
+char(c,58566).
+char(m,58567).
+char(7,58568).
+char(2,58569).
+char(0,58570).
+char(3,58571).
+char(c,58572).
+char(c,58573).
+char(m,58574).
+char(4,58575).
+char(5,58576).
+char(3,58577).
+char(3,58578).
+char(c,58579).
+char(p,58580).
+char(o,58581).
+char(p,58582).
+char(o,58583).
+char(6,58584).
+char(5,58585).
+char(0,58586).
+char(8,58587).
+char(m,58588).
+char(o,58589).
+char(1,58590).
+char(1,58591).
+char(6,58592).
+char(7,58593).
+char(c,58594).
+char(c,58595).
+char(m,58596).
+char(o,58597).
+char(p,58598).
+char(o,58599).
+char(p,58600).
+char(o,58601).
+char(m,58602).
+char(o,58603).
+char(o,58604).
+char(o,58605).
+char(5,58606).
+char(7,58607).
+char(1,58608).
+char(7,58609).
+char(c,58610).
+char(p,58611).
+char(o,58612).
+char(9,58613).
+char(7,58614).
+char(2,58615).
+char(7,58616).
+char(m,58617).
+char(7,58618).
+char(5,58619).
+char(6,58620).
+char(0,58621).
+char(c,58622).
+char(c,58623).
+char(m,58624).
+char(o,58625).
+char(o,58626).
+char(o,58627).
+char(m,58628).
+char(o,58629).
+char(m,58630).
+char(o,58631).
+char(o,58632).
+char(m,58633).
+char(o,58634).
+char(p,58635).
+char(o,58636).
+char(p,58637).
+char(6,58638).
+char(2,58639).
+char(5,58640).
+char(5,58641).
+char(p,58642).
+char(7,58643).
+char(1,58644).
+char(0,58645).
+char(2,58646).
+char(c,58647).
+char(c,58648).
+char(c,58649).
+char(m,58650).
+char(4,58651).
+char(2,58652).
+char(6,58653).
+char(3,58654).
+char(c,58655).
+char(c,58656).
+char(c,58657).
+char(m,58658).
+char(o,58659).
+char(m,58660).
+char(o,58661).
+char(p,58662).
+char(o,58663).
+char(m,58664).
+char(o,58665).
+char(p,58666).
+char(o,58667).
+char(2,58668).
+char(3,58669).
+char(4,58670).
+char(8,58671).
+char(m,58672).
+char(o,58673).
+char(5,58674).
+char(4,58675).
+char(4,58676).
+char(8,58677).
+char(c,58678).
+char(m,58679).
+char(o,58680).
+char(6,58681).
+char(9,58682).
+char(9,58683).
+char(4,58684).
+char(p,58685).
+char(5,58686).
+char(1,58687).
+char(9,58688).
+char(3,58689).
+char(m,58690).
+char(7,58691).
+char(2,58692).
+char(5,58693).
+char(c,58694).
+char(p,58695).
+char(8,58696).
+char(3,58697).
+char(0,58698).
+char(p,58699).
+char(1,58700).
+char(7,58701).
+char(6,58702).
+char(8,58703).
+char(c,58704).
+char(c,58705).
+char(c,58706).
+char(c,58707).
+char(c,58708).
+char(m,58709).
+char(9,58710).
+char(7,58711).
+char(2,58712).
+char(5,58713).
+char(c,58714).
+char(p,58715).
+char(9,58716).
+char(9,58717).
+char(6,58718).
+char(4,58719).
+char(p,58720).
+char(5,58721).
+char(6,58722).
+char(0,58723).
+char(c,58724).
+char(c,58725).
+char(c,58726).
+char(c,58727).
+char(c,58728).
+char(p,58729).
+char(o,58730).
+char(o,58731).
+char(o,58732).
+char(p,58733).
+char(4,58734).
+char(5,58735).
+char(7,58736).
+char(m,58737).
+char(o,58738).
+char(p,58739).
+char(1,58740).
+char(2,58741).
+char(6,58742).
+char(c,58743).
+char(p,58744).
+char(9,58745).
+char(6,58746).
+char(9,58747).
+char(0,58748).
+char(c,58749).
+char(p,58750).
+char(o,58751).
+char(7,58752).
+char(6,58753).
+char(2,58754).
+char(6,58755).
+char(c,58756).
+char(m,58757).
+char(o,58758).
+char(p,58759).
+char(8,58760).
+char(4,58761).
+char(3,58762).
+char(9,58763).
+char(p,58764).
+char(o,58765).
+char(9,58766).
+char(8,58767).
+char(9,58768).
+char(8,58769).
+char(c,58770).
+char(m,58771).
+char(8,58772).
+char(0,58773).
+char(7,58774).
+char(2,58775).
+char(p,58776).
+char(6,58777).
+char(1,58778).
+char(5,58779).
+char(7,58780).
+char(m,58781).
+char(5,58782).
+char(6,58783).
+char(2,58784).
+char(7,58785).
+char(m,58786).
+char(1,58787).
+char(1,58788).
+char(3,58789).
+char(5,58790).
+char(p,58791).
+char(2,58792).
+char(8,58793).
+char(8,58794).
+char(c,58795).
+char(m,58796).
+char(2,58797).
+char(1,58798).
+char(9,58799).
+char(4,58800).
+char(c,58801).
+char(c,58802).
+char(c,58803).
+char(c,58804).
+char(p,58805).
+char(o,58806).
+char(m,58807).
+char(o,58808).
+char(p,58809).
+char(o,58810).
+char(p,58811).
+char(o,58812).
+char(o,58813).
+char(o,58814).
+char(p,58815).
+char(o,58816).
+char(m,58817).
+char(o,58818).
+char(p,58819).
+char(o,58820).
+char(o,58821).
+char(p,58822).
+char(3,58823).
+char(5,58824).
+char(6,58825).
+char(9,58826).
+char(p,58827).
+char(6,58828).
+char(3,58829).
+char(4,58830).
+char(4,58831).
+char(m,58832).
+char(4,58833).
+char(6,58834).
+char(4,58835).
+char(2,58836).
+char(p,58837).
+char(o,58838).
+char(p,58839).
+char(o,58840).
+char(p,58841).
+char(9,58842).
+char(2,58843).
+char(5,58844).
+char(0,58845).
+char(c,58846).
+char(c,58847).
+char(p,58848).
+char(1,58849).
+char(0,58850).
+char(6,58851).
+char(0,58852).
+char(m,58853).
+char(7,58854).
+char(0,58855).
+char(6,58856).
+char(1,58857).
+char(m,58858).
+char(o,58859).
+char(p,58860).
+char(o,58861).
+char(5,58862).
+char(8,58863).
+char(4,58864).
+char(p,58865).
+char(7,58866).
+char(6,58867).
+char(7,58868).
+char(6,58869).
+char(m,58870).
+char(o,58871).
+char(m,58872).
+char(8,58873).
+char(4,58874).
+char(1,58875).
+char(6,58876).
+char(c,58877).
+char(c,58878).
+char(c,58879).
+char(c,58880).
+char(c,58881).
+char(c,58882).
+char(c,58883).
+char(p,58884).
+char(o,58885).
+char(m,58886).
+char(o,58887).
+char(m,58888).
+char(1,58889).
+char(4,58890).
+char(2,58891).
+char(8,58892).
+char(c,58893).
+char(m,58894).
+char(9,58895).
+char(1,58896).
+char(2,58897).
+char(9,58898).
+char(p,58899).
+char(7,58900).
+char(8,58901).
+char(1,58902).
+char(p,58903).
+char(5,58904).
+char(4,58905).
+char(9,58906).
+char(3,58907).
+char(m,58908).
+char(5,58909).
+char(4,58910).
+char(5,58911).
+char(9,58912).
+char(c,58913).
+char(c,58914).
+char(c,58915).
+char(m,58916).
+char(2,58917).
+char(0,58918).
+char(1,58919).
+char(c,58920).
+char(c,58921).
+char(c,58922).
+char(p,58923).
+char(o,58924).
+char(p,58925).
+char(5,58926).
+char(5,58927).
+char(3,58928).
+char(2,58929).
+char(m,58930).
+char(o,58931).
+char(3,58932).
+char(6,58933).
+char(0,58934).
+char(0,58935).
+char(c,58936).
+char(c,58937).
+char(m,58938).
+char(o,58939).
+char(m,58940).
+char(o,58941).
+char(p,58942).
+char(o,58943).
+char(p,58944).
+char(o,58945).
+char(p,58946).
+char(9,58947).
+char(3,58948).
+char(c,58949).
+char(c,58950).
+char(p,58951).
+char(6,58952).
+char(6,58953).
+char(4,58954).
+char(5,58955).
+char(p,58956).
+char(9,58957).
+char(6,58958).
+char(4,58959).
+char(9,58960).
+char(p,58961).
+char(o,58962).
+char(p,58963).
+char(o,58964).
+char(m,58965).
+char(9,58966).
+char(0,58967).
+char(2,58968).
+char(5,58969).
+char(c,58970).
+char(c,58971).
+char(c,58972).
+char(c,58973).
+char(c,58974).
+char(c,58975).
+char(p,58976).
+char(8,58977).
+char(2,58978).
+char(7,58979).
+char(0,58980).
+char(c,58981).
+char(p,58982).
+char(9,58983).
+char(4,58984).
+char(6,58985).
+char(3,58986).
+char(p,58987).
+char(4,58988).
+char(8,58989).
+char(0,58990).
+char(7,58991).
+char(m,58992).
+char(5,58993).
+char(0,58994).
+char(5,58995).
+char(9,58996).
+char(m,58997).
+char(8,58998).
+char(5,58999).
+char(8,59000).
+char(9,59001).
+char(p,59002).
+char(7,59003).
+char(8,59004).
+char(0,59005).
+char(2,59006).
+char(c,59007).
+char(m,59008).
+char(o,59009).
+char(m,59010).
+char(o,59011).
+char(m,59012).
+char(o,59013).
+char(o,59014).
+char(m,59015).
+char(o,59016).
+char(m,59017).
+char(o,59018).
+char(m,59019).
+char(1,59020).
+char(3,59021).
+char(9,59022).
+char(0,59023).
+char(p,59024).
+char(8,59025).
+char(5,59026).
+char(0,59027).
+char(2,59028).
+char(m,59029).
+char(5,59030).
+char(5,59031).
+char(2,59032).
+char(6,59033).
+char(c,59034).
+char(m,59035).
+char(7,59036).
+char(6,59037).
+char(2,59038).
+char(4,59039).
+char(c,59040).
+char(p,59041).
+char(5,59042).
+char(0,59043).
+char(4,59044).
+char(3,59045).
+char(p,59046).
+char(o,59047).
+char(9,59048).
+char(7,59049).
+char(7,59050).
+char(8,59051).
+char(m,59052).
+char(o,59053).
+char(m,59054).
+char(4,59055).
+char(6,59056).
+char(1,59057).
+char(p,59058).
+char(o,59059).
+char(m,59060).
+char(3,59061).
+char(2,59062).
+char(0,59063).
+char(5,59064).
+char(c,59065).
+char(m,59066).
+char(o,59067).
+char(p,59068).
+char(o,59069).
+char(m,59070).
+char(o,59071).
+char(m,59072).
+char(o,59073).
+char(p,59074).
+char(o,59075).
+char(8,59076).
+char(8,59077).
+char(3,59078).
+char(7,59079).
+char(c,59080).
+char(p,59081).
+char(o,59082).
+char(o,59083).
+char(o,59084).
+char(o,59085).
+char(m,59086).
+char(o,59087).
+char(m,59088).
+char(o,59089).
+char(o,59090).
+char(m,59091).
+char(o,59092).
+char(m,59093).
+char(o,59094).
+char(8,59095).
+char(3,59096).
+char(6,59097).
+char(2,59098).
+char(p,59099).
+char(6,59100).
+char(8,59101).
+char(9,59102).
+char(2,59103).
+char(c,59104).
+char(c,59105).
+char(m,59106).
+char(4,59107).
+char(8,59108).
+char(2,59109).
+char(2,59110).
+char(c,59111).
+char(m,59112).
+char(o,59113).
+char(p,59114).
+char(o,59115).
+char(p,59116).
+char(3,59117).
+char(6,59118).
+char(8,59119).
+char(1,59120).
+char(m,59121).
+char(4,59122).
+char(8,59123).
+char(4,59124).
+char(1,59125).
+char(c,59126).
+char(c,59127).
+char(m,59128).
+char(o,59129).
+char(p,59130).
+char(o,59131).
+char(m,59132).
+char(o,59133).
+char(p,59134).
+char(8,59135).
+char(8,59136).
+char(8,59137).
+char(6,59138).
+char(m,59139).
+char(6,59140).
+char(4,59141).
+char(0,59142).
+char(0,59143).
+char(p,59144).
+char(o,59145).
+char(p,59146).
+char(o,59147).
+char(2,59148).
+char(1,59149).
+char(3,59150).
+char(2,59151).
+char(m,59152).
+char(o,59153).
+char(p,59154).
+char(6,59155).
+char(7,59156).
+char(4,59157).
+char(3,59158).
+char(c,59159).
+char(p,59160).
+char(8,59161).
+char(4,59162).
+char(c,59163).
+char(c,59164).
+char(p,59165).
+char(4,59166).
+char(8,59167).
+char(2,59168).
+char(2,59169).
+char(c,59170).
+char(c,59171).
+char(p,59172).
+char(7,59173).
+char(2,59174).
+char(9,59175).
+char(3,59176).
+char(c,59177).
+char(c,59178).
+char(c,59179).
+char(m,59180).
+char(o,59181).
+char(8,59182).
+char(3,59183).
+char(0,59184).
+char(5,59185).
+char(m,59186).
+char(3,59187).
+char(8,59188).
+char(3,59189).
+char(3,59190).
+char(m,59191).
+char(o,59192).
+char(7,59193).
+char(9,59194).
+char(6,59195).
+char(9,59196).
+char(p,59197).
+char(8,59198).
+char(9,59199).
+char(6,59200).
+char(c,59201).
+char(c,59202).
+char(c,59203).
+char(p,59204).
+char(o,59205).
+char(p,59206).
+char(4,59207).
+char(0,59208).
+char(1,59209).
+char(9,59210).
+char(p,59211).
+char(o,59212).
+char(m,59213).
+char(o,59214).
+char(p,59215).
+char(o,59216).
+char(o,59217).
+char(p,59218).
+char(o,59219).
+char(p,59220).
+char(o,59221).
+char(6,59222).
+char(8,59223).
+char(1,59224).
+char(9,59225).
+char(c,59226).
+char(m,59227).
+char(o,59228).
+char(p,59229).
+char(o,59230).
+char(m,59231).
+char(o,59232).
+char(m,59233).
+char(8,59234).
+char(1,59235).
+char(6,59236).
+char(6,59237).
+char(p,59238).
+char(9,59239).
+char(3,59240).
+char(0,59241).
+char(c,59242).
+char(c,59243).
+char(p,59244).
+char(o,59245).
+char(p,59246).
+char(o,59247).
+char(p,59248).
+char(6,59249).
+char(0,59250).
+char(0,59251).
+char(3,59252).
+char(m,59253).
+char(o,59254).
+char(m,59255).
+char(o,59256).
+char(p,59257).
+char(o,59258).
+char(7,59259).
+char(6,59260).
+char(2,59261).
+char(9,59262).
+char(c,59263).
+char(p,59264).
+char(o,59265).
+char(3,59266).
+char(4,59267).
+char(0,59268).
+char(9,59269).
+char(p,59270).
+char(3,59271).
+char(9,59272).
+char(5,59273).
+char(8,59274).
+char(c,59275).
+char(p,59276).
+char(o,59277).
+char(p,59278).
+char(2,59279).
+char(5,59280).
+char(2,59281).
+char(9,59282).
+char(p,59283).
+char(9,59284).
+char(0,59285).
+char(1,59286).
+char(9,59287).
+char(c,59288).
+char(p,59289).
+char(o,59290).
+char(o,59291).
+char(m,59292).
+char(7,59293).
+char(1,59294).
+char(6,59295).
+char(4,59296).
+char(m,59297).
+char(5,59298).
+char(2,59299).
+char(1,59300).
+char(4,59301).
+char(c,59302).
+char(p,59303).
+char(o,59304).
+char(m,59305).
+char(4,59306).
+char(8,59307).
+char(3,59308).
+char(2,59309).
+char(m,59310).
+char(9,59311).
+char(2,59312).
+char(3,59313).
+char(7,59314).
+char(c,59315).
+char(c,59316).
+char(m,59317).
+char(o,59318).
+char(1,59319).
+char(4,59320).
+char(1,59321).
+char(0,59322).
+char(c,59323).
+char(p,59324).
+char(9,59325).
+char(8,59326).
+char(6,59327).
+char(0,59328).
+char(m,59329).
+char(o,59330).
+char(m,59331).
+char(o,59332).
+char(m,59333).
+char(o,59334).
+char(p,59335).
+char(o,59336).
+char(8,59337).
+char(5,59338).
+char(3,59339).
+char(6,59340).
+char(m,59341).
+char(o,59342).
+char(m,59343).
+char(o,59344).
+char(p,59345).
+char(o,59346).
+char(p,59347).
+char(o,59348).
+char(p,59349).
+char(1,59350).
+char(7,59351).
+char(5,59352).
+char(7,59353).
+char(p,59354).
+char(o,59355).
+char(m,59356).
+char(o,59357).
+char(m,59358).
+char(o,59359).
+char(p,59360).
+char(o,59361).
+char(9,59362).
+char(2,59363).
+char(1,59364).
+char(p,59365).
+char(1,59366).
+char(2,59367).
+char(5,59368).
+char(6,59369).
+char(c,59370).
+char(m,59371).
+char(o,59372).
+char(m,59373).
+char(o,59374).
+char(2,59375).
+char(2,59376).
+char(9,59377).
+char(7,59378).
+char(p,59379).
+char(o,59380).
+char(p,59381).
+char(9,59382).
+char(9,59383).
+char(8,59384).
+char(5,59385).
+char(p,59386).
+char(6,59387).
+char(8,59388).
+char(1,59389).
+char(8,59390).
+char(c,59391).
+char(m,59392).
+char(6,59393).
+char(8,59394).
+char(8,59395).
+char(8,59396).
+char(m,59397).
+char(9,59398).
+char(1,59399).
+char(4,59400).
+char(2,59401).
+char(p,59402).
+char(o,59403).
+char(m,59404).
+char(8,59405).
+char(5,59406).
+char(0,59407).
+char(5,59408).
+char(p,59409).
+char(o,59410).
+char(2,59411).
+char(5,59412).
+char(6,59413).
+char(2,59414).
+char(c,59415).
+char(c,59416).
+char(c,59417).
+char(m,59418).
+char(5,59419).
+char(2,59420).
+char(9,59421).
+char(5,59422).
+char(m,59423).
+char(3,59424).
+char(4,59425).
+char(8,59426).
+char(0,59427).
+char(c,59428).
+char(c,59429).
+char(c,59430).
+char(c,59431).
+char(c,59432).
+char(m,59433).
+char(7,59434).
+char(5,59435).
+char(9,59436).
+char(8,59437).
+char(m,59438).
+char(o,59439).
+char(m,59440).
+char(o,59441).
+char(p,59442).
+char(o,59443).
+char(m,59444).
+char(3,59445).
+char(7,59446).
+char(3,59447).
+char(2,59448).
+char(c,59449).
+char(m,59450).
+char(o,59451).
+char(8,59452).
+char(3,59453).
+char(8,59454).
+char(p,59455).
+char(o,59456).
+char(m,59457).
+char(o,59458).
+char(p,59459).
+char(3,59460).
+char(8,59461).
+char(5,59462).
+char(c,59463).
+char(c,59464).
+char(m,59465).
+char(2,59466).
+char(8,59467).
+char(9,59468).
+char(4,59469).
+char(c,59470).
+char(c,59471).
+char(p,59472).
+char(9,59473).
+char(1,59474).
+char(8,59475).
+char(m,59476).
+char(6,59477).
+char(8,59478).
+char(0,59479).
+char(8,59480).
+char(p,59481).
+char(o,59482).
+char(p,59483).
+char(o,59484).
+char(p,59485).
+char(8,59486).
+char(0,59487).
+char(1,59488).
+char(7,59489).
+char(p,59490).
+char(o,59491).
+char(m,59492).
+char(o,59493).
+char(o,59494).
+char(o,59495).
+char(m,59496).
+char(1,59497).
+char(3,59498).
+char(8,59499).
+char(4,59500).
+char(p,59501).
+char(o,59502).
+char(p,59503).
+char(o,59504).
+char(m,59505).
+char(2,59506).
+char(5,59507).
+char(1,59508).
+char(3,59509).
+char(c,59510).
+char(m,59511).
+char(1,59512).
+char(7,59513).
+char(1,59514).
+char(7,59515).
+char(c,59516).
+char(p,59517).
+char(o,59518).
+char(p,59519).
+char(o,59520).
+char(o,59521).
+char(6,59522).
+char(4,59523).
+char(9,59524).
+char(2,59525).
+char(c,59526).
+char(c,59527).
+char(c,59528).
+char(p,59529).
+char(3,59530).
+char(5,59531).
+char(9,59532).
+char(2,59533).
+char(p,59534).
+char(o,59535).
+char(p,59536).
+char(o,59537).
+char(m,59538).
+char(o,59539).
+char(2,59540).
+char(7,59541).
+char(6,59542).
+char(7,59543).
+char(c,59544).
+char(p,59545).
+char(6,59546).
+char(7,59547).
+char(2,59548).
+char(2,59549).
+char(m,59550).
+char(o,59551).
+char(p,59552).
+char(o,59553).
+char(p,59554).
+char(o,59555).
+char(4,59556).
+char(3,59557).
+char(1,59558).
+char(8,59559).
+char(m,59560).
+char(6,59561).
+char(7,59562).
+char(8,59563).
+char(6,59564).
+char(p,59565).
+char(2,59566).
+char(0,59567).
+char(2,59568).
+char(1,59569).
+char(m,59570).
+char(4,59571).
+char(4,59572).
+char(5,59573).
+char(7,59574).
+char(m,59575).
+char(o,59576).
+char(3,59577).
+char(0,59578).
+char(6,59579).
+char(1,59580).
+char(c,59581).
+char(c,59582).
+char(m,59583).
+char(o,59584).
+char(m,59585).
+char(o,59586).
+char(p,59587).
+char(3,59588).
+char(4,59589).
+char(1,59590).
+char(2,59591).
+char(c,59592).
+char(c,59593).
+char(c,59594).
+char(m,59595).
+char(5,59596).
+char(2,59597).
+char(2,59598).
+char(4,59599).
+char(p,59600).
+char(9,59601).
+char(8,59602).
+char(3,59603).
+char(4,59604).
+char(m,59605).
+char(o,59606).
+char(m,59607).
+char(o,59608).
+char(2,59609).
+char(0,59610).
+char(4,59611).
+char(8,59612).
+char(c,59613).
+char(p,59614).
+char(o,59615).
+char(o,59616).
+char(o,59617).
+char(o,59618).
+char(m,59619).
+char(6,59620).
+char(3,59621).
+char(8,59622).
+char(1,59623).
+char(m,59624).
+char(o,59625).
+char(o,59626).
+char(p,59627).
+char(7,59628).
+char(3,59629).
+char(1,59630).
+char(4,59631).
+char(p,59632).
+char(o,59633).
+char(m,59634).
+char(2,59635).
+char(7,59636).
+char(2,59637).
+char(4,59638).
+char(c,59639).
+char(m,59640).
+char(o,59641).
+char(p,59642).
+char(o,59643).
+char(m,59644).
+char(9,59645).
+char(3,59646).
+char(9,59647).
+char(8,59648).
+char(m,59649).
+char(o,59650).
+char(o,59651).
+char(p,59652).
+char(o,59653).
+char(o,59654).
+char(5,59655).
+char(7,59656).
+char(3,59657).
+char(6,59658).
+char(c,59659).
+char(c,59660).
+char(p,59661).
+char(o,59662).
+char(m,59663).
+char(o,59664).
+char(o,59665).
+char(m,59666).
+char(o,59667).
+char(m,59668).
+char(o,59669).
+char(m,59670).
+char(1,59671).
+char(6,59672).
+char(8,59673).
+char(2,59674).
+char(m,59675).
+char(5,59676).
+char(0,59677).
+char(9,59678).
+char(6,59679).
+char(c,59680).
+char(m,59681).
+char(o,59682).
+char(1,59683).
+char(5,59684).
+char(4,59685).
+char(6,59686).
+char(c,59687).
+char(c,59688).
+char(m,59689).
+char(9,59690).
+char(8,59691).
+char(6,59692).
+char(1,59693).
+char(m,59694).
+char(o,59695).
+char(m,59696).
+char(8,59697).
+char(5,59698).
+char(6,59699).
+char(8,59700).
+char(c,59701).
+char(p,59702).
+char(o,59703).
+char(o,59704).
+char(p,59705).
+char(o,59706).
+char(m,59707).
+char(3,59708).
+char(8,59709).
+char(7,59710).
+char(2,59711).
+char(c,59712).
+char(c,59713).
+char(c,59714).
+char(c,59715).
+char(p,59716).
+char(5,59717).
+char(0,59718).
+char(1,59719).
+char(6,59720).
+char(c,59721).
+char(c,59722).
+char(p,59723).
+char(3,59724).
+char(0,59725).
+char(5,59726).
+char(2,59727).
+char(m,59728).
+char(4,59729).
+char(4,59730).
+char(9,59731).
+char(2,59732).
+char(m,59733).
+char(o,59734).
+char(5,59735).
+char(3,59736).
+char(0,59737).
+char(4,59738).
+char(c,59739).
+char(p,59740).
+char(6,59741).
+char(8,59742).
+char(4,59743).
+char(0,59744).
+char(c,59745).
+char(m,59746).
+char(o,59747).
+char(m,59748).
+char(5,59749).
+char(2,59750).
+char(6,59751).
+char(3,59752).
+char(p,59753).
+char(o,59754).
+char(p,59755).
+char(8,59756).
+char(5,59757).
+char(4,59758).
+char(1,59759).
+char(m,59760).
+char(o,59761).
+char(8,59762).
+char(4,59763).
+char(1,59764).
+char(0,59765).
+char(p,59766).
+char(4,59767).
+char(5,59768).
+char(3,59769).
+char(c,59770).
+char(m,59771).
+char(7,59772).
+char(6,59773).
+char(9,59774).
+char(6,59775).
+char(c,59776).
+char(c,59777).
+char(c,59778).
+char(c,59779).
+char(c,59780).
+char(m,59781).
+char(o,59782).
+char(m,59783).
+char(3,59784).
+char(3,59785).
+char(2,59786).
+char(3,59787).
+char(c,59788).
+char(p,59789).
+char(o,59790).
+char(p,59791).
+char(o,59792).
+char(p,59793).
+char(5,59794).
+char(7,59795).
+char(9,59796).
+char(0,59797).
+char(c,59798).
+char(p,59799).
+char(o,59800).
+char(o,59801).
+char(m,59802).
+char(7,59803).
+char(4,59804).
+char(6,59805).
+char(0,59806).
+char(m,59807).
+char(o,59808).
+char(o,59809).
+char(m,59810).
+char(o,59811).
+char(p,59812).
+char(o,59813).
+char(m,59814).
+char(5,59815).
+char(1,59816).
+char(4,59817).
+char(m,59818).
+char(5,59819).
+char(4,59820).
+char(4,59821).
+char(6,59822).
+char(c,59823).
+char(p,59824).
+char(o,59825).
+char(m,59826).
+char(o,59827).
+char(p,59828).
+char(6,59829).
+char(6,59830).
+char(8,59831).
+char(5,59832).
+char(p,59833).
+char(o,59834).
+char(9,59835).
+char(3,59836).
+char(6,59837).
+char(c,59838).
+char(c,59839).
+char(m,59840).
+char(o,59841).
+char(p,59842).
+char(9,59843).
+char(8,59844).
+char(3,59845).
+char(2,59846).
+char(c,59847).
+char(m,59848).
+char(3,59849).
+char(9,59850).
+char(9,59851).
+char(0,59852).
+char(c,59853).
+char(c,59854).
+char(p,59855).
+char(o,59856).
+char(6,59857).
+char(1,59858).
+char(0,59859).
+char(c,59860).
+char(c,59861).
+char(c,59862).
+char(m,59863).
+char(1,59864).
+char(6,59865).
+char(5,59866).
+char(9,59867).
+char(c,59868).
+char(c,59869).
+char(p,59870).
+char(6,59871).
+char(4,59872).
+char(1,59873).
+char(7,59874).
+char(c,59875).
+char(c,59876).
+char(c,59877).
+char(m,59878).
+char(8,59879).
+char(8,59880).
+char(3,59881).
+char(0,59882).
+char(p,59883).
+char(o,59884).
+char(p,59885).
+char(5,59886).
+char(6,59887).
+char(3,59888).
+char(6,59889).
+char(c,59890).
+char(m,59891).
+char(7,59892).
+char(6,59893).
+char(1,59894).
+char(7,59895).
+char(p,59896).
+char(o,59897).
+char(p,59898).
+char(o,59899).
+char(o,59900).
+char(m,59901).
+char(o,59902).
+char(m,59903).
+char(6,59904).
+char(9,59905).
+char(7,59906).
+char(9,59907).
+char(m,59908).
+char(9,59909).
+char(8,59910).
+char(6,59911).
+char(4,59912).
+char(c,59913).
+char(c,59914).
+char(c,59915).
+char(c,59916).
+char(c,59917).
+char(p,59918).
+char(8,59919).
+char(0,59920).
+char(0,59921).
+char(8,59922).
+char(m,59923).
+char(o,59924).
+char(o,59925).
+char(p,59926).
+char(7,59927).
+char(1,59928).
+char(1,59929).
+char(7,59930).
+char(p,59931).
+char(2,59932).
+char(4,59933).
+char(5,59934).
+char(c,59935).
+char(m,59936).
+char(3,59937).
+char(5,59938).
+char(2,59939).
+char(5,59940).
+char(m,59941).
+char(o,59942).
+char(o,59943).
+char(p,59944).
+char(o,59945).
+char(p,59946).
+char(o,59947).
+char(m,59948).
+char(7,59949).
+char(0,59950).
+char(1,59951).
+char(7,59952).
+char(p,59953).
+char(6,59954).
+char(9,59955).
+char(2,59956).
+char(6,59957).
+char(m,59958).
+char(9,59959).
+char(3,59960).
+char(5,59961).
+char(7,59962).
+char(m,59963).
+char(3,59964).
+char(8,59965).
+char(2,59966).
+char(9,59967).
+char(m,59968).
+char(7,59969).
+char(9,59970).
+char(8,59971).
+char(3,59972).
+char(c,59973).
+char(m,59974).
+char(o,59975).
+char(p,59976).
+char(3,59977).
+char(0,59978).
+char(6,59979).
+char(5,59980).
+char(m,59981).
+char(o,59982).
+char(9,59983).
+char(0,59984).
+char(0,59985).
+char(0,59986).
+char(m,59987).
+char(o,59988).
+char(p,59989).
+char(9,59990).
+char(4,59991).
+char(2,59992).
+char(4,59993).
+char(c,59994).
+char(c,59995).
+char(c,59996).
+char(c,59997).
+char(c,59998).
+char(m,59999).
+char(6,60000).
+char(3,60001).
+char(2,60002).
+char(8,60003).
+char(c,60004).
+char(c,60005).
+char(c,60006).
+char(c,60007).
+char(c,60008).
+char(c,60009).
+char(c,60010).
+char(p,60011).
+char(o,60012).
+char(m,60013).
+char(6,60014).
+char(9,60015).
+char(9,60016).
+char(7,60017).
+char(m,60018).
+char(o,60019).
+char(m,60020).
+char(3,60021).
+char(4,60022).
+char(8,60023).
+char(3,60024).
+char(c,60025).
+char(m,60026).
+char(o,60027).
+char(p,60028).
+char(o,60029).
+char(m,60030).
+char(1,60031).
+char(4,60032).
+char(0,60033).
+char(4,60034).
+char(p,60035).
+char(o,60036).
+char(m,60037).
+char(o,60038).
+char(p,60039).
+char(o,60040).
+char(4,60041).
+char(9,60042).
+char(6,60043).
+char(8,60044).
+char(c,60045).
+char(c,60046).
+char(c,60047).
+char(m,60048).
+char(o,60049).
+char(m,60050).
+char(4,60051).
+char(7,60052).
+char(6,60053).
+char(3,60054).
+char(c,60055).
+char(p,60056).
+char(o,60057).
+char(p,60058).
+char(8,60059).
+char(9,60060).
+char(5,60061).
+char(2,60062).
+char(m,60063).
+char(o,60064).
+char(o,60065).
+char(o,60066).
+char(m,60067).
+char(7,60068).
+char(6,60069).
+char(5,60070).
+char(5,60071).
+char(p,60072).
+char(o,60073).
+char(m,60074).
+char(5,60075).
+char(2,60076).
+char(4,60077).
+char(1,60078).
+char(p,60079).
+char(o,60080).
+char(9,60081).
+char(4,60082).
+char(6,60083).
+char(0,60084).
+char(c,60085).
+char(c,60086).
+char(p,60087).
+char(o,60088).
+char(m,60089).
+char(4,60090).
+char(2,60091).
+char(2,60092).
+char(1,60093).
+char(c,60094).
+char(c,60095).
+char(m,60096).
+char(2,60097).
+char(0,60098).
+char(6,60099).
+char(2,60100).
+char(m,60101).
+char(o,60102).
+char(p,60103).
+char(8,60104).
+char(5,60105).
+char(0,60106).
+char(3,60107).
+char(c,60108).
+char(m,60109).
+char(5,60110).
+char(3,60111).
+char(4,60112).
+char(4,60113).
+char(c,60114).
+char(c,60115).
+char(c,60116).
+char(c,60117).
+char(m,60118).
+char(o,60119).
+char(p,60120).
+char(4,60121).
+char(7,60122).
+char(4,60123).
+char(c,60124).
+char(c,60125).
+char(m,60126).
+char(o,60127).
+char(o,60128).
+char(7,60129).
+char(6,60130).
+char(0,60131).
+char(3,60132).
+char(p,60133).
+char(4,60134).
+char(9,60135).
+char(3,60136).
+char(9,60137).
+char(c,60138).
+char(c,60139).
+char(m,60140).
+char(4,60141).
+char(4,60142).
+char(7,60143).
+char(2,60144).
+char(m,60145).
+char(8,60146).
+char(2,60147).
+char(4,60148).
+char(3,60149).
+char(p,60150).
+char(o,60151).
+char(m,60152).
+char(o,60153).
+char(o,60154).
+char(p,60155).
+char(o,60156).
+char(o,60157).
+char(p,60158).
+char(1,60159).
+char(9,60160).
+char(8,60161).
+char(3,60162).
+char(c,60163).
+char(c,60164).
+char(c,60165).
+char(c,60166).
+char(c,60167).
+char(c,60168).
+char(p,60169).
+char(o,60170).
+char(m,60171).
+char(1,60172).
+char(6,60173).
+char(7,60174).
+char(6,60175).
+char(m,60176).
+char(8,60177).
+char(4,60178).
+char(8,60179).
+char(5,60180).
+char(p,60181).
+char(o,60182).
+char(p,60183).
+char(9,60184).
+char(5,60185).
+char(7,60186).
+char(3,60187).
+char(c,60188).
+char(p,60189).
+char(o,60190).
+char(o,60191).
+char(m,60192).
+char(5,60193).
+char(6,60194).
+char(4,60195).
+char(9,60196).
+char(p,60197).
+char(5,60198).
+char(6,60199).
+char(2,60200).
+char(6,60201).
+char(c,60202).
+char(c,60203).
+char(p,60204).
+char(6,60205).
+char(8,60206).
+char(3,60207).
+char(8,60208).
+char(m,60209).
+char(6,60210).
+char(0,60211).
+char(0,60212).
+char(8,60213).
+char(c,60214).
+char(p,60215).
+char(1,60216).
+char(1,60217).
+char(8,60218).
+char(9,60219).
+char(m,60220).
+char(5,60221).
+char(7,60222).
+char(3,60223).
+char(8,60224).
+char(c,60225).
+char(c,60226).
+char(c,60227).
+char(c,60228).
+char(c,60229).
+char(c,60230).
+char(c,60231).
+char(m,60232).
+char(o,60233).
+char(o,60234).
+char(m,60235).
+char(5,60236).
+char(5,60237).
+char(8,60238).
+char(5,60239).
+char(p,60240).
+char(o,60241).
+char(p,60242).
+char(o,60243).
+char(m,60244).
+char(o,60245).
+char(1,60246).
+char(1,60247).
+char(4,60248).
+char(p,60249).
+char(o,60250).
+char(p,60251).
+char(9,60252).
+char(2,60253).
+char(2,60254).
+char(8,60255).
+char(m,60256).
+char(o,60257).
+char(p,60258).
+char(o,60259).
+char(o,60260).
+char(m,60261).
+char(8,60262).
+char(1,60263).
+char(6,60264).
+char(2,60265).
+char(m,60266).
+char(3,60267).
+char(8,60268).
+char(5,60269).
+char(5,60270).
+char(c,60271).
+char(m,60272).
+char(9,60273).
+char(3,60274).
+char(2,60275).
+char(m,60276).
+char(8,60277).
+char(7,60278).
+char(5,60279).
+char(7,60280).
+char(p,60281).
+char(o,60282).
+char(5,60283).
+char(2,60284).
+char(1,60285).
+char(4,60286).
+char(m,60287).
+char(o,60288).
+char(o,60289).
+char(p,60290).
+char(o,60291).
+char(m,60292).
+char(o,60293).
+char(p,60294).
+char(o,60295).
+char(2,60296).
+char(0,60297).
+char(3,60298).
+char(2,60299).
+char(m,60300).
+char(1,60301).
+char(3,60302).
+char(4,60303).
+char(7,60304).
+char(c,60305).
+char(p,60306).
+char(o,60307).
+char(m,60308).
+char(o,60309).
+char(m,60310).
+char(3,60311).
+char(6,60312).
+char(5,60313).
+char(2,60314).
+char(m,60315).
+char(7,60316).
+char(2,60317).
+char(3,60318).
+char(1,60319).
+char(m,60320).
+char(o,60321).
+char(6,60322).
+char(5,60323).
+char(7,60324).
+char(5,60325).
+char(m,60326).
+char(9,60327).
+char(2,60328).
+char(3,60329).
+char(0,60330).
+char(c,60331).
+char(m,60332).
+char(8,60333).
+char(1,60334).
+char(4,60335).
+char(0,60336).
+char(c,60337).
+char(c,60338).
+char(c,60339).
+char(c,60340).
+char(c,60341).
+char(m,60342).
+char(9,60343).
+char(5,60344).
+char(3,60345).
+char(5,60346).
+char(m,60347).
+char(8,60348).
+char(0,60349).
+char(8,60350).
+char(9,60351).
+char(c,60352).
+char(m,60353).
+char(8,60354).
+char(1,60355).
+char(8,60356).
+char(9,60357).
+char(m,60358).
+char(o,60359).
+char(o,60360).
+char(m,60361).
+char(o,60362).
+char(p,60363).
+char(1,60364).
+char(1,60365).
+char(8,60366).
+char(1,60367).
+char(c,60368).
+char(c,60369).
+char(p,60370).
+char(o,60371).
+char(p,60372).
+char(4,60373).
+char(9,60374).
+char(4,60375).
+char(4,60376).
+char(c,60377).
+char(c,60378).
+char(c,60379).
+char(m,60380).
+char(8,60381).
+char(4,60382).
+char(6,60383).
+char(7,60384).
+char(p,60385).
+char(6,60386).
+char(9,60387).
+char(4,60388).
+char(3,60389).
+char(m,60390).
+char(3,60391).
+char(5,60392).
+char(3,60393).
+char(8,60394).
+char(c,60395).
+char(c,60396).
+char(p,60397).
+char(4,60398).
+char(2,60399).
+char(0,60400).
+char(2,60401).
+char(c,60402).
+char(c,60403).
+char(m,60404).
+char(o,60405).
+char(m,60406).
+char(1,60407).
+char(3,60408).
+char(9,60409).
+char(7,60410).
+char(m,60411).
+char(8,60412).
+char(3,60413).
+char(7,60414).
+char(9,60415).
+char(c,60416).
+char(c,60417).
+char(p,60418).
+char(6,60419).
+char(7,60420).
+char(6,60421).
+char(2,60422).
+char(p,60423).
+char(4,60424).
+char(2,60425).
+char(3,60426).
+char(6,60427).
+char(c,60428).
+char(c,60429).
+char(c,60430).
+char(c,60431).
+char(c,60432).
+char(m,60433).
+char(o,60434).
+char(p,60435).
+char(o,60436).
+char(7,60437).
+char(5,60438).
+char(0,60439).
+char(4,60440).
+char(c,60441).
+char(c,60442).
+char(p,60443).
+char(6,60444).
+char(9,60445).
+char(5,60446).
+char(0,60447).
+char(m,60448).
+char(4,60449).
+char(3,60450).
+char(9,60451).
+char(c,60452).
+char(p,60453).
+char(o,60454).
+char(m,60455).
+char(8,60456).
+char(0,60457).
+char(8,60458).
+char(7,60459).
+char(p,60460).
+char(o,60461).
+char(o,60462).
+char(o,60463).
+char(m,60464).
+char(4,60465).
+char(4,60466).
+char(6,60467).
+char(3,60468).
+char(p,60469).
+char(o,60470).
+char(p,60471).
+char(o,60472).
+char(o,60473).
+char(p,60474).
+char(o,60475).
+char(m,60476).
+char(5,60477).
+char(6,60478).
+char(9,60479).
+char(0,60480).
+char(p,60481).
+char(o,60482).
+char(m,60483).
+char(2,60484).
+char(3,60485).
+char(0,60486).
+char(8,60487).
+char(c,60488).
+char(p,60489).
+char(o,60490).
+char(4,60491).
+char(8,60492).
+char(c,60493).
+char(p,60494).
+char(o,60495).
+char(6,60496).
+char(1,60497).
+char(0,60498).
+char(5,60499).
+char(p,60500).
+char(2,60501).
+char(6,60502).
+char(4,60503).
+char(m,60504).
+char(5,60505).
+char(6,60506).
+char(7,60507).
+char(2,60508).
+char(c,60509).
+char(p,60510).
+char(o,60511).
+char(5,60512).
+char(2,60513).
+char(6,60514).
+char(3,60515).
+char(c,60516).
+char(m,60517).
+char(o,60518).
+char(p,60519).
+char(o,60520).
+char(m,60521).
+char(o,60522).
+char(m,60523).
+char(1,60524).
+char(7,60525).
+char(9,60526).
+char(6,60527).
+char(m,60528).
+char(o,60529).
+char(8,60530).
+char(8,60531).
+char(9,60532).
+char(1,60533).
+char(c,60534).
+char(c,60535).
+char(c,60536).
+char(p,60537).
+char(6,60538).
+char(4,60539).
+char(2,60540).
+char(4,60541).
+char(c,60542).
+char(c,60543).
+char(p,60544).
+char(o,60545).
+char(p,60546).
+char(1,60547).
+char(1,60548).
+char(1,60549).
+char(0,60550).
+char(c,60551).
+char(c,60552).
+char(p,60553).
+char(3,60554).
+char(2,60555).
+char(5,60556).
+char(9,60557).
+char(m,60558).
+char(o,60559).
+char(1,60560).
+char(6,60561).
+char(5,60562).
+char(5,60563).
+char(c,60564).
+char(c,60565).
+char(p,60566).
+char(6,60567).
+char(0,60568).
+char(1,60569).
+char(2,60570).
+char(c,60571).
+char(p,60572).
+char(o,60573).
+char(m,60574).
+char(o,60575).
+char(p,60576).
+char(o,60577).
+char(p,60578).
+char(7,60579).
+char(1,60580).
+char(2,60581).
+char(0,60582).
+char(c,60583).
+char(c,60584).
+char(c,60585).
+char(p,60586).
+char(o,60587).
+char(7,60588).
+char(2,60589).
+char(0,60590).
+char(3,60591).
+char(p,60592).
+char(1,60593).
+char(8,60594).
+char(5,60595).
+char(0,60596).
+char(c,60597).
+char(m,60598).
+char(o,60599).
+char(7,60600).
+char(3,60601).
+char(5,60602).
+char(6,60603).
+char(p,60604).
+char(7,60605).
+char(4,60606).
+char(6,60607).
+char(1,60608).
+char(p,60609).
+char(9,60610).
+char(2,60611).
+char(2,60612).
+char(8,60613).
+char(p,60614).
+char(8,60615).
+char(8,60616).
+char(2,60617).
+char(1,60618).
+char(p,60619).
+char(3,60620).
+char(3,60621).
+char(2,60622).
+char(7,60623).
+char(c,60624).
+char(c,60625).
+char(p,60626).
+char(4,60627).
+char(6,60628).
+char(0,60629).
+char(9,60630).
+char(p,60631).
+char(o,60632).
+char(p,60633).
+char(5,60634).
+char(4,60635).
+char(7,60636).
+char(7,60637).
+char(c,60638).
+char(p,60639).
+char(7,60640).
+char(9,60641).
+char(0,60642).
+char(7,60643).
+char(p,60644).
+char(9,60645).
+char(0,60646).
+char(3,60647).
+char(9,60648).
+char(m,60649).
+char(6,60650).
+char(5,60651).
+char(0,60652).
+char(2,60653).
+char(c,60654).
+char(c,60655).
+char(c,60656).
+char(c,60657).
+char(p,60658).
+char(o,60659).
+char(p,60660).
+char(2,60661).
+char(0,60662).
+char(3,60663).
+char(2,60664).
+char(c,60665).
+char(m,60666).
+char(o,60667).
+char(m,60668).
+char(7,60669).
+char(0,60670).
+char(6,60671).
+char(3,60672).
+char(c,60673).
+char(c,60674).
+char(c,60675).
+char(c,60676).
+char(c,60677).
+char(m,60678).
+char(1,60679).
+char(6,60680).
+char(1,60681).
+char(0,60682).
+char(c,60683).
+char(c,60684).
+char(p,60685).
+char(o,60686).
+char(p,60687).
+char(o,60688).
+char(p,60689).
+char(o,60690).
+char(6,60691).
+char(4,60692).
+char(6,60693).
+char(9,60694).
+char(c,60695).
+char(m,60696).
+char(7,60697).
+char(9,60698).
+char(7,60699).
+char(7,60700).
+char(c,60701).
+char(c,60702).
+char(c,60703).
+char(c,60704).
+char(p,60705).
+char(9,60706).
+char(6,60707).
+char(2,60708).
+char(0,60709).
+char(p,60710).
+char(o,60711).
+char(m,60712).
+char(o,60713).
+char(m,60714).
+char(o,60715).
+char(1,60716).
+char(5,60717).
+char(4,60718).
+char(4,60719).
+char(m,60720).
+char(6,60721).
+char(0,60722).
+char(8,60723).
+char(1,60724).
+char(m,60725).
+char(6,60726).
+char(1,60727).
+char(9,60728).
+char(9,60729).
+char(m,60730).
+char(o,60731).
+char(m,60732).
+char(6,60733).
+char(8,60734).
+char(9,60735).
+char(3,60736).
+char(c,60737).
+char(c,60738).
+char(m,60739).
+char(9,60740).
+char(8,60741).
+char(7,60742).
+char(1,60743).
+char(m,60744).
+char(o,60745).
+char(m,60746).
+char(2,60747).
+char(9,60748).
+char(0,60749).
+char(m,60750).
+char(5,60751).
+char(9,60752).
+char(6,60753).
+char(6,60754).
+char(c,60755).
+char(c,60756).
+char(c,60757).
+char(p,60758).
+char(6,60759).
+char(2,60760).
+char(9,60761).
+char(8,60762).
+char(p,60763).
+char(o,60764).
+char(m,60765).
+char(o,60766).
+char(m,60767).
+char(o,60768).
+char(1,60769).
+char(2,60770).
+char(7,60771).
+char(8,60772).
+char(m,60773).
+char(1,60774).
+char(6,60775).
+char(4,60776).
+char(0,60777).
+char(c,60778).
+char(m,60779).
+char(9,60780).
+char(8,60781).
+char(4,60782).
+char(2,60783).
+char(c,60784).
+char(c,60785).
+char(c,60786).
+char(m,60787).
+char(o,60788).
+char(p,60789).
+char(o,60790).
+char(m,60791).
+char(o,60792).
+char(m,60793).
+char(o,60794).
+char(m,60795).
+char(o,60796).
+char(p,60797).
+char(o,60798).
+char(1,60799).
+char(9,60800).
+char(9,60801).
+char(2,60802).
+char(m,60803).
+char(7,60804).
+char(7,60805).
+char(8,60806).
+char(0,60807).
+char(p,60808).
+char(8,60809).
+char(0,60810).
+char(8,60811).
+char(2,60812).
+char(m,60813).
+char(o,60814).
+char(m,60815).
+char(o,60816).
+char(p,60817).
+char(5,60818).
+char(2,60819).
+char(7,60820).
+char(2,60821).
+char(c,60822).
+char(c,60823).
+char(m,60824).
+char(o,60825).
+char(p,60826).
+char(o,60827).
+char(2,60828).
+char(1,60829).
+char(8,60830).
+char(1,60831).
+char(p,60832).
+char(o,60833).
+char(m,60834).
+char(2,60835).
+char(3,60836).
+char(8,60837).
+char(1,60838).
+char(p,60839).
+char(o,60840).
+char(p,60841).
+char(6,60842).
+char(6,60843).
+char(8,60844).
+char(1,60845).
+char(c,60846).
+char(c,60847).
+char(p,60848).
+char(o,60849).
+char(m,60850).
+char(o,60851).
+char(o,60852).
+char(p,60853).
+char(o,60854).
+char(1,60855).
+char(2,60856).
+char(c,60857).
+char(c,60858).
+char(c,60859).
+char(m,60860).
+char(8,60861).
+char(8,60862).
+char(0,60863).
+char(5,60864).
+char(m,60865).
+char(2,60866).
+char(7,60867).
+char(3,60868).
+char(c,60869).
+char(c,60870).
+char(m,60871).
+char(o,60872).
+char(o,60873).
+char(o,60874).
+char(o,60875).
+char(p,60876).
+char(o,60877).
+char(5,60878).
+char(1,60879).
+char(6,60880).
+char(8,60881).
+char(c,60882).
+char(m,60883).
+char(o,60884).
+char(6,60885).
+char(0,60886).
+char(4,60887).
+char(0,60888).
+char(p,60889).
+char(o,60890).
+char(p,60891).
+char(9,60892).
+char(1,60893).
+char(0,60894).
+char(3,60895).
+char(c,60896).
+char(m,60897).
+char(o,60898).
+char(m,60899).
+char(4,60900).
+char(8,60901).
+char(3,60902).
+char(4,60903).
+char(p,60904).
+char(8,60905).
+char(7,60906).
+char(5,60907).
+char(6,60908).
+char(c,60909).
+char(m,60910).
+char(o,60911).
+char(m,60912).
+char(o,60913).
+char(m,60914).
+char(3,60915).
+char(9,60916).
+char(6,60917).
+char(0,60918).
+char(c,60919).
+char(p,60920).
+char(o,60921).
+char(m,60922).
+char(o,60923).
+char(6,60924).
+char(1,60925).
+char(7,60926).
+char(c,60927).
+char(c,60928).
+char(m,60929).
+char(o,60930).
+char(m,60931).
+char(o,60932).
+char(p,60933).
+char(o,60934).
+char(m,60935).
+char(o,60936).
+char(p,60937).
+char(o,60938).
+char(m,60939).
+char(7,60940).
+char(4,60941).
+char(3,60942).
+char(1,60943).
+char(p,60944).
+char(o,60945).
+char(p,60946).
+char(o,60947).
+char(p,60948).
+char(o,60949).
+char(p,60950).
+char(o,60951).
+char(m,60952).
+char(6,60953).
+char(8,60954).
+char(0,60955).
+char(9,60956).
+char(c,60957).
+char(c,60958).
+char(m,60959).
+char(o,60960).
+char(o,60961).
+char(m,60962).
+char(1,60963).
+char(7,60964).
+char(8,60965).
+char(6,60966).
+char(p,60967).
+char(o,60968).
+char(p,60969).
+char(2,60970).
+char(5,60971).
+char(3,60972).
+char(6,60973).
+char(p,60974).
+char(1,60975).
+char(0,60976).
+char(4,60977).
+char(3,60978).
+char(p,60979).
+char(o,60980).
+char(p,60981).
+char(o,60982).
+char(p,60983).
+char(4,60984).
+char(7,60985).
+char(0,60986).
+char(0,60987).
+char(c,60988).
+char(m,60989).
+char(6,60990).
+char(3,60991).
+char(6,60992).
+char(6,60993).
+char(c,60994).
+char(p,60995).
+char(o,60996).
+char(p,60997).
+char(o,60998).
+char(p,60999).
+char(9,61000).
+char(6,61001).
+char(8,61002).
+char(7,61003).
+char(p,61004).
+char(o,61005).
+char(6,61006).
+char(8,61007).
+char(3,61008).
+char(6,61009).
+char(c,61010).
+char(p,61011).
+char(9,61012).
+char(4,61013).
+char(5,61014).
+char(7,61015).
+char(m,61016).
+char(o,61017).
+char(o,61018).
+char(m,61019).
+char(o,61020).
+char(o,61021).
+char(m,61022).
+char(o,61023).
+char(p,61024).
+char(o,61025).
+char(p,61026).
+char(5,61027).
+char(5,61028).
+char(8,61029).
+char(0,61030).
+char(c,61031).
+char(c,61032).
+char(m,61033).
+char(o,61034).
+char(m,61035).
+char(8,61036).
+char(1,61037).
+char(9,61038).
+char(m,61039).
+char(o,61040).
+char(p,61041).
+char(o,61042).
+char(p,61043).
+char(o,61044).
+char(p,61045).
+char(o,61046).
+char(o,61047).
+char(o,61048).
+char(p,61049).
+char(7,61050).
+char(5,61051).
+char(2,61052).
+char(4,61053).
+char(c,61054).
+char(m,61055).
+char(3,61056).
+char(9,61057).
+char(0,61058).
+char(2,61059).
+char(p,61060).
+char(o,61061).
+char(o,61062).
+char(m,61063).
+char(3,61064).
+char(2,61065).
+char(1,61066).
+char(0,61067).
+char(m,61068).
+char(o,61069).
+char(m,61070).
+char(o,61071).
+char(o,61072).
+char(p,61073).
+char(o,61074).
+char(p,61075).
+char(5,61076).
+char(1,61077).
+char(1,61078).
+char(2,61079).
+char(c,61080).
+char(p,61081).
+char(6,61082).
+char(3,61083).
+char(1,61084).
+char(3,61085).
+char(c,61086).
+char(c,61087).
+char(p,61088).
+char(o,61089).
+char(p,61090).
+char(o,61091).
+char(o,61092).
+char(m,61093).
+char(o,61094).
+char(m,61095).
+char(4,61096).
+char(2,61097).
+char(5,61098).
+char(3,61099).
+char(c,61100).
+char(c,61101).
+char(m,61102).
+char(8,61103).
+char(9,61104).
+char(9,61105).
+char(9,61106).
+char(c,61107).
+char(m,61108).
+char(9,61109).
+char(3,61110).
+char(3,61111).
+char(3,61112).
+char(c,61113).
+char(c,61114).
+char(c,61115).
+char(p,61116).
+char(o,61117).
+char(m,61118).
+char(3,61119).
+char(4,61120).
+char(1,61121).
+char(1,61122).
+char(p,61123).
+char(o,61124).
+char(o,61125).
+char(m,61126).
+char(5,61127).
+char(1,61128).
+char(6,61129).
+char(6,61130).
+char(c,61131).
+char(c,61132).
+char(c,61133).
+char(c,61134).
+char(m,61135).
+char(o,61136).
+char(o,61137).
+char(m,61138).
+char(4,61139).
+char(6,61140).
+char(6,61141).
+char(2,61142).
+char(c,61143).
+char(c,61144).
+char(p,61145).
+char(9,61146).
+char(2,61147).
+char(1,61148).
+char(5,61149).
+char(c,61150).
+char(c,61151).
+char(c,61152).
+char(c,61153).
+char(m,61154).
+char(o,61155).
+char(p,61156).
+char(5,61157).
+char(5,61158).
+char(7,61159).
+char(8,61160).
+char(p,61161).
+char(2,61162).
+char(6,61163).
+char(6,61164).
+char(9,61165).
+char(m,61166).
+char(2,61167).
+char(4,61168).
+char(6,61169).
+char(4,61170).
+char(p,61171).
+char(8,61172).
+char(0,61173).
+char(6,61174).
+char(1,61175).
+char(p,61176).
+char(9,61177).
+char(6,61178).
+char(2,61179).
+char(1,61180).
+char(p,61181).
+char(o,61182).
+char(o,61183).
+char(2,61184).
+char(0,61185).
+char(9,61186).
+char(2,61187).
+char(c,61188).
+char(m,61189).
+char(o,61190).
+char(p,61191).
+char(8,61192).
+char(8,61193).
+char(6,61194).
+char(8,61195).
+char(p,61196).
+char(3,61197).
+char(8,61198).
+char(6,61199).
+char(8,61200).
+char(m,61201).
+char(4,61202).
+char(5,61203).
+char(3,61204).
+char(5,61205).
+char(c,61206).
+char(m,61207).
+char(o,61208).
+char(p,61209).
+char(o,61210).
+char(2,61211).
+char(7,61212).
+char(4,61213).
+char(4,61214).
+char(c,61215).
+char(p,61216).
+char(o,61217).
+char(p,61218).
+char(o,61219).
+char(m,61220).
+char(6,61221).
+char(7,61222).
+char(2,61223).
+char(7,61224).
+char(m,61225).
+char(8,61226).
+char(9,61227).
+char(7,61228).
+char(0,61229).
+char(p,61230).
+char(5,61231).
+char(1,61232).
+char(4,61233).
+char(1,61234).
+char(p,61235).
+char(1,61236).
+char(8,61237).
+char(9,61238).
+char(4,61239).
+char(c,61240).
+char(p,61241).
+char(o,61242).
+char(m,61243).
+char(5,61244).
+char(6,61245).
+char(6,61246).
+char(3,61247).
+char(c,61248).
+char(c,61249).
+char(c,61250).
+char(m,61251).
+char(o,61252).
+char(o,61253).
+char(p,61254).
+char(o,61255).
+char(o,61256).
+char(o,61257).
+char(p,61258).
+char(7,61259).
+char(1,61260).
+char(6,61261).
+char(4,61262).
+char(c,61263).
+char(c,61264).
+char(m,61265).
+char(o,61266).
+char(m,61267).
+char(2,61268).
+char(1,61269).
+char(3,61270).
+char(4,61271).
+char(m,61272).
+char(4,61273).
+char(8,61274).
+char(5,61275).
+char(6,61276).
+char(c,61277).
+char(p,61278).
+char(4,61279).
+char(5,61280).
+char(3,61281).
+char(4,61282).
+char(m,61283).
+char(5,61284).
+char(5,61285).
+char(5,61286).
+char(0,61287).
+char(c,61288).
+char(p,61289).
+char(1,61290).
+char(4,61291).
+char(8,61292).
+char(0,61293).
+char(p,61294).
+char(9,61295).
+char(8,61296).
+char(6,61297).
+char(4,61298).
+char(p,61299).
+char(o,61300).
+char(m,61301).
+char(o,61302).
+char(p,61303).
+char(3,61304).
+char(5,61305).
+char(4,61306).
+char(1,61307).
+char(c,61308).
+char(c,61309).
+char(c,61310).
+char(m,61311).
+char(o,61312).
+char(m,61313).
+char(o,61314).
+char(m,61315).
+char(o,61316).
+char(m,61317).
+char(o,61318).
+char(7,61319).
+char(9,61320).
+char(1,61321).
+char(c,61322).
+char(m,61323).
+char(o,61324).
+char(p,61325).
+char(o,61326).
+char(p,61327).
+char(o,61328).
+char(p,61329).
+char(o,61330).
+char(5,61331).
+char(1,61332).
+char(4,61333).
+char(7,61334).
+char(m,61335).
+char(o,61336).
+char(p,61337).
+char(4,61338).
+char(5,61339).
+char(3,61340).
+char(2,61341).
+char(c,61342).
+char(c,61343).
+char(p,61344).
+char(1,61345).
+char(2,61346).
+char(1,61347).
+char(3,61348).
+char(p,61349).
+char(o,61350).
+char(6,61351).
+char(1,61352).
+char(9,61353).
+char(3,61354).
+char(p,61355).
+char(o,61356).
+char(p,61357).
+char(o,61358).
+char(m,61359).
+char(5,61360).
+char(8,61361).
+char(2,61362).
+char(1,61363).
+char(p,61364).
+char(1,61365).
+char(2,61366).
+char(3,61367).
+char(2,61368).
+char(p,61369).
+char(o,61370).
+char(m,61371).
+char(o,61372).
+char(p,61373).
+char(o,61374).
+char(m,61375).
+char(o,61376).
+char(m,61377).
+char(1,61378).
+char(1,61379).
+char(2,61380).
+char(9,61381).
+char(m,61382).
+char(o,61383).
+char(p,61384).
+char(o,61385).
+char(o,61386).
+char(p,61387).
+char(3,61388).
+char(4,61389).
+char(1,61390).
+char(2,61391).
+char(c,61392).
+char(c,61393).
+char(p,61394).
+char(9,61395).
+char(3,61396).
+char(6,61397).
+char(0,61398).
+char(m,61399).
+char(5,61400).
+char(2,61401).
+char(1,61402).
+char(5,61403).
+char(m,61404).
+char(3,61405).
+char(3,61406).
+char(7,61407).
+char(5,61408).
+char(c,61409).
+char(m,61410).
+char(6,61411).
+char(3,61412).
+char(2,61413).
+char(5,61414).
+char(p,61415).
+char(o,61416).
+char(m,61417).
+char(6,61418).
+char(4,61419).
+char(6,61420).
+char(9,61421).
+char(m,61422).
+char(o,61423).
+char(7,61424).
+char(2,61425).
+char(2,61426).
+char(c,61427).
+char(m,61428).
+char(o,61429).
+char(p,61430).
+char(3,61431).
+char(4,61432).
+char(1,61433).
+char(3,61434).
+char(p,61435).
+char(o,61436).
+char(m,61437).
+char(7,61438).
+char(1,61439).
+char(6,61440).
+char(6,61441).
+char(m,61442).
+char(o,61443).
+char(p,61444).
+char(o,61445).
+char(p,61446).
+char(3,61447).
+char(0,61448).
+char(9,61449).
+char(7,61450).
+char(m,61451).
+char(o,61452).
+char(p,61453).
+char(2,61454).
+char(6,61455).
+char(6,61456).
+char(8,61457).
+char(m,61458).
+char(o,61459).
+char(m,61460).
+char(o,61461).
+char(m,61462).
+char(8,61463).
+char(3,61464).
+char(8,61465).
+char(3,61466).
+char(c,61467).
+char(c,61468).
+char(p,61469).
+char(1,61470).
+char(7,61471).
+char(1,61472).
+char(1,61473).
+char(c,61474).
+char(c,61475).
+char(c,61476).
+char(m,61477).
+char(o,61478).
+char(m,61479).
+char(o,61480).
+char(1,61481).
+char(6,61482).
+char(4,61483).
+char(3,61484).
+char(c,61485).
+char(c,61486).
+char(m,61487).
+char(o,61488).
+char(m,61489).
+char(4,61490).
+char(3,61491).
+char(9,61492).
+char(4,61493).
+char(p,61494).
+char(6,61495).
+char(6,61496).
+char(1,61497).
+char(9,61498).
+char(p,61499).
+char(7,61500).
+char(1,61501).
+char(9,61502).
+char(3,61503).
+char(c,61504).
+char(m,61505).
+char(o,61506).
+char(m,61507).
+char(o,61508).
+char(3,61509).
+char(8,61510).
+char(3,61511).
+char(3,61512).
+char(m,61513).
+char(1,61514).
+char(7,61515).
+char(8,61516).
+char(1,61517).
+char(p,61518).
+char(1,61519).
+char(7,61520).
+char(4,61521).
+char(4,61522).
+char(c,61523).
+char(p,61524).
+char(6,61525).
+char(2,61526).
+char(8,61527).
+char(5,61528).
+char(m,61529).
+char(o,61530).
+char(m,61531).
+char(o,61532).
+char(m,61533).
+char(o,61534).
+char(m,61535).
+char(9,61536).
+char(7,61537).
+char(6,61538).
+char(5,61539).
+char(c,61540).
+char(c,61541).
+char(m,61542).
+char(2,61543).
+char(3,61544).
+char(5,61545).
+char(6,61546).
+char(m,61547).
+char(1,61548).
+char(5,61549).
+char(4,61550).
+char(2,61551).
+char(m,61552).
+char(o,61553).
+char(p,61554).
+char(o,61555).
+char(p,61556).
+char(o,61557).
+char(m,61558).
+char(o,61559).
+char(p,61560).
+char(o,61561).
+char(p,61562).
+char(6,61563).
+char(9,61564).
+char(9,61565).
+char(9,61566).
+char(c,61567).
+char(c,61568).
+char(c,61569).
+char(m,61570).
+char(o,61571).
+char(p,61572).
+char(9,61573).
+char(9,61574).
+char(1,61575).
+char(1,61576).
+char(m,61577).
+char(o,61578).
+char(3,61579).
+char(5,61580).
+char(3,61581).
+char(1,61582).
+char(m,61583).
+char(1,61584).
+char(4,61585).
+char(2,61586).
+char(6,61587).
+char(m,61588).
+char(o,61589).
+char(p,61590).
+char(o,61591).
+char(p,61592).
+char(3,61593).
+char(3,61594).
+char(9,61595).
+char(3,61596).
+char(m,61597).
+char(9,61598).
+char(4,61599).
+char(1,61600).
+char(4,61601).
+char(p,61602).
+char(1,61603).
+char(8,61604).
+char(0,61605).
+char(3,61606).
+char(c,61607).
+char(c,61608).
+char(p,61609).
+char(o,61610).
+char(m,61611).
+char(9,61612).
+char(2,61613).
+char(0,61614).
+char(2,61615).
+char(c,61616).
+char(c,61617).
+char(p,61618).
+char(2,61619).
+char(9,61620).
+char(0,61621).
+char(9,61622).
+char(c,61623).
+char(c,61624).
+char(p,61625).
+char(9,61626).
+char(9,61627).
+char(5,61628).
+char(1,61629).
+char(p,61630).
+char(4,61631).
+char(8,61632).
+char(5,61633).
+char(5,61634).
+char(p,61635).
+char(o,61636).
+char(p,61637).
+char(7,61638).
+char(8,61639).
+char(7,61640).
+char(6,61641).
+char(c,61642).
+char(c,61643).
+char(p,61644).
+char(7,61645).
+char(7,61646).
+char(8,61647).
+char(7,61648).
+char(p,61649).
+char(o,61650).
+char(m,61651).
+char(o,61652).
+char(p,61653).
+char(5,61654).
+char(6,61655).
+char(5,61656).
+char(7,61657).
+char(c,61658).
+char(c,61659).
+char(c,61660).
+char(m,61661).
+char(o,61662).
+char(p,61663).
+char(o,61664).
+char(m,61665).
+char(o,61666).
+char(o,61667).
+char(4,61668).
+char(0,61669).
+char(5,61670).
+char(9,61671).
+char(m,61672).
+char(o,61673).
+char(m,61674).
+char(o,61675).
+char(m,61676).
+char(o,61677).
+char(m,61678).
+char(9,61679).
+char(9,61680).
+char(0,61681).
+char(6,61682).
+char(c,61683).
+char(m,61684).
+char(6,61685).
+char(0,61686).
+char(7,61687).
+char(2,61688).
+char(c,61689).
+char(c,61690).
+char(c,61691).
+char(c,61692).
+char(p,61693).
+char(o,61694).
+char(o,61695).
+char(m,61696).
+char(o,61697).
+char(m,61698).
+char(o,61699).
+char(m,61700).
+char(o,61701).
+char(o,61702).
+char(p,61703).
+char(5,61704).
+char(9,61705).
+char(1,61706).
+char(5,61707).
+char(p,61708).
+char(6,61709).
+char(2,61710).
+char(8,61711).
+char(1,61712).
+char(c,61713).
+char(c,61714).
+char(p,61715).
+char(2,61716).
+char(8,61717).
+char(5,61718).
+char(5,61719).
+char(m,61720).
+char(8,61721).
+char(0,61722).
+char(2,61723).
+char(3,61724).
+char(m,61725).
+char(4,61726).
+char(0,61727).
+char(4,61728).
+char(6,61729).
+char(c,61730).
+char(c,61731).
+char(c,61732).
+char(m,61733).
+char(8,61734).
+char(6,61735).
+char(7,61736).
+char(4,61737).
+char(c,61738).
+char(c,61739).
+char(m,61740).
+char(6,61741).
+char(9,61742).
+char(8,61743).
+char(1,61744).
+char(c,61745).
+char(p,61746).
+char(o,61747).
+char(o,61748).
+char(p,61749).
+char(o,61750).
+char(o,61751).
+char(p,61752).
+char(4,61753).
+char(3,61754).
+char(4,61755).
+char(6,61756).
+char(p,61757).
+char(7,61758).
+char(9,61759).
+char(4,61760).
+char(9,61761).
+char(p,61762).
+char(2,61763).
+char(3,61764).
+char(9,61765).
+char(0,61766).
+char(c,61767).
+char(p,61768).
+char(o,61769).
+char(m,61770).
+char(6,61771).
+char(5,61772).
+char(m,61773).
+char(2,61774).
+char(3,61775).
+char(1,61776).
+char(5,61777).
+char(c,61778).
+char(c,61779).
+char(m,61780).
+char(7,61781).
+char(4,61782).
+char(0,61783).
+char(8,61784).
+char(c,61785).
+char(p,61786).
+char(o,61787).
+char(8,61788).
+char(6,61789).
+char(8,61790).
+char(8,61791).
+char(c,61792).
+char(m,61793).
+char(o,61794).
+char(p,61795).
+char(1,61796).
+char(9,61797).
+char(4,61798).
+char(2,61799).
+char(m,61800).
+char(7,61801).
+char(6,61802).
+char(8,61803).
+char(4,61804).
+char(p,61805).
+char(o,61806).
+char(m,61807).
+char(2,61808).
+char(4,61809).
+char(3,61810).
+char(6,61811).
+char(c,61812).
+char(c,61813).
+char(c,61814).
+char(p,61815).
+char(4,61816).
+char(4,61817).
+char(8,61818).
+char(9,61819).
+char(m,61820).
+char(o,61821).
+char(o,61822).
+char(p,61823).
+char(o,61824).
+char(o,61825).
+char(9,61826).
+char(5,61827).
+char(1,61828).
+char(3,61829).
+char(c,61830).
+char(p,61831).
+char(8,61832).
+char(5,61833).
+char(9,61834).
+char(p,61835).
+char(1,61836).
+char(5,61837).
+char(7,61838).
+char(9,61839).
+char(m,61840).
+char(o,61841).
+char(m,61842).
+char(1,61843).
+char(4,61844).
+char(1,61845).
+char(0,61846).
+char(p,61847).
+char(o,61848).
+char(p,61849).
+char(o,61850).
+char(8,61851).
+char(3,61852).
+char(8,61853).
+char(6,61854).
+char(p,61855).
+char(o,61856).
+char(p,61857).
+char(o,61858).
+char(o,61859).
+char(m,61860).
+char(o,61861).
+char(p,61862).
+char(1,61863).
+char(4,61864).
+char(6,61865).
+char(7,61866).
+char(c,61867).
+char(c,61868).
+char(c,61869).
+char(c,61870).
+char(m,61871).
+char(o,61872).
+char(o,61873).
+char(o,61874).
+char(2,61875).
+char(3,61876).
+char(8,61877).
+char(3,61878).
+char(c,61879).
+char(c,61880).
+char(p,61881).
+char(o,61882).
+char(m,61883).
+char(o,61884).
+char(p,61885).
+char(5,61886).
+char(7,61887).
+char(8,61888).
+char(4,61889).
+char(m,61890).
+char(o,61891).
+char(o,61892).
+char(m,61893).
+char(3,61894).
+char(7,61895).
+char(2,61896).
+char(c,61897).
+char(p,61898).
+char(4,61899).
+char(1,61900).
+char(5,61901).
+char(8,61902).
+char(c,61903).
+char(c,61904).
+char(p,61905).
+char(7,61906).
+char(3,61907).
+char(1,61908).
+char(0,61909).
+char(m,61910).
+char(5,61911).
+char(2,61912).
+char(1,61913).
+char(2,61914).
+char(p,61915).
+char(8,61916).
+char(2,61917).
+char(7,61918).
+char(0,61919).
+char(c,61920).
+char(m,61921).
+char(2,61922).
+char(2,61923).
+char(9,61924).
+char(7,61925).
+char(m,61926).
+char(3,61927).
+char(0,61928).
+char(6,61929).
+char(1,61930).
+char(c,61931).
+char(m,61932).
+char(2,61933).
+char(3,61934).
+char(8,61935).
+char(7,61936).
+char(c,61937).
+char(c,61938).
+char(c,61939).
+char(p,61940).
+char(3,61941).
+char(5,61942).
+char(6,61943).
+char(7,61944).
+char(m,61945).
+char(6,61946).
+char(6,61947).
+char(0,61948).
+char(0,61949).
+char(m,61950).
+char(2,61951).
+char(7,61952).
+char(2,61953).
+char(7,61954).
+char(c,61955).
+char(c,61956).
+char(c,61957).
+char(c,61958).
+char(c,61959).
+char(p,61960).
+char(o,61961).
+char(o,61962).
+char(p,61963).
+char(o,61964).
+char(o,61965).
+char(p,61966).
+char(5,61967).
+char(5,61968).
+char(6,61969).
+char(2,61970).
+char(c,61971).
+char(c,61972).
+char(m,61973).
+char(6,61974).
+char(9,61975).
+char(1,61976).
+char(9,61977).
+char(c,61978).
+char(c,61979).
+char(c,61980).
+char(c,61981).
+char(c,61982).
+char(m,61983).
+char(o,61984).
+char(o,61985).
+char(m,61986).
+char(o,61987).
+char(p,61988).
+char(1,61989).
+char(9,61990).
+char(8,61991).
+char(9,61992).
+char(p,61993).
+char(1,61994).
+char(8,61995).
+char(4,61996).
+char(6,61997).
+char(c,61998).
+char(c,61999).
+char(c,62000).
+char(c,62001).
+char(c,62002).
+char(c,62003).
+char(c,62004).
+char(m,62005).
+char(8,62006).
+char(1,62007).
+char(6,62008).
+char(3,62009).
+char(c,62010).
+char(c,62011).
+char(c,62012).
+char(c,62013).
+char(p,62014).
+char(1,62015).
+char(3,62016).
+char(3,62017).
+char(3,62018).
+char(c,62019).
+char(c,62020).
+char(c,62021).
+char(c,62022).
+char(m,62023).
+char(6,62024).
+char(1,62025).
+char(3,62026).
+char(9,62027).
+char(c,62028).
+char(p,62029).
+char(o,62030).
+char(2,62031).
+char(2,62032).
+char(0,62033).
+char(4,62034).
+char(m,62035).
+char(o,62036).
+char(o,62037).
+char(p,62038).
+char(o,62039).
+char(m,62040).
+char(7,62041).
+char(8,62042).
+char(7,62043).
+char(0,62044).
+char(c,62045).
+char(c,62046).
+char(m,62047).
+char(o,62048).
+char(2,62049).
+char(8,62050).
+char(6,62051).
+char(7,62052).
+char(c,62053).
+char(p,62054).
+char(o,62055).
+char(m,62056).
+char(5,62057).
+char(9,62058).
+char(5,62059).
+char(8,62060).
+char(c,62061).
+char(c,62062).
+char(c,62063).
+char(c,62064).
+char(m,62065).
+char(8,62066).
+char(1,62067).
+char(7,62068).
+char(1,62069).
+char(c,62070).
+char(c,62071).
+char(c,62072).
+char(c,62073).
+char(c,62074).
+char(c,62075).
+char(p,62076).
+char(9,62077).
+char(4,62078).
+char(7,62079).
+char(m,62080).
+char(o,62081).
+char(p,62082).
+char(5,62083).
+char(4,62084).
+char(9,62085).
+char(0,62086).
+char(c,62087).
+char(m,62088).
+char(3,62089).
+char(6,62090).
+char(0,62091).
+char(1,62092).
+char(c,62093).
+char(m,62094).
+char(6,62095).
+char(9,62096).
+char(1,62097).
+char(6,62098).
+char(p,62099).
+char(o,62100).
+char(m,62101).
+char(6,62102).
+char(6,62103).
+char(3,62104).
+char(6,62105).
+char(c,62106).
+char(p,62107).
+char(o,62108).
+char(m,62109).
+char(4,62110).
+char(4,62111).
+char(5,62112).
+char(3,62113).
+char(m,62114).
+char(6,62115).
+char(7,62116).
+char(4,62117).
+char(8,62118).
+char(c,62119).
+char(c,62120).
+char(p,62121).
+char(o,62122).
+char(8,62123).
+char(4,62124).
+char(1,62125).
+char(1,62126).
+char(p,62127).
+char(7,62128).
+char(2,62129).
+char(2,62130).
+char(0,62131).
+char(c,62132).
+char(p,62133).
+char(5,62134).
+char(1,62135).
+char(3,62136).
+char(0,62137).
+char(c,62138).
+char(c,62139).
+char(c,62140).
+char(p,62141).
+char(o,62142).
+char(m,62143).
+char(1,62144).
+char(0,62145).
+char(7,62146).
+char(5,62147).
+char(m,62148).
+char(5,62149).
+char(5,62150).
+char(1,62151).
+char(9,62152).
+char(m,62153).
+char(o,62154).
+char(m,62155).
+char(o,62156).
+char(p,62157).
+char(o,62158).
+char(m,62159).
+char(o,62160).
+char(m,62161).
+char(1,62162).
+char(7,62163).
+char(9,62164).
+char(4,62165).
+char(c,62166).
+char(p,62167).
+char(o,62168).
+char(o,62169).
+char(m,62170).
+char(o,62171).
+char(o,62172).
+char(o,62173).
+char(p,62174).
+char(3,62175).
+char(2,62176).
+char(8,62177).
+char(3,62178).
+char(p,62179).
+char(1,62180).
+char(9,62181).
+char(3,62182).
+char(1,62183).
+char(c,62184).
+char(p,62185).
+char(6,62186).
+char(3,62187).
+char(6,62188).
+char(2,62189).
+char(c,62190).
+char(c,62191).
+char(m,62192).
+char(1,62193).
+char(1,62194).
+char(7,62195).
+char(1,62196).
+char(m,62197).
+char(o,62198).
+char(m,62199).
+char(o,62200).
+char(2,62201).
+char(5,62202).
+char(4,62203).
+char(3,62204).
+char(m,62205).
+char(4,62206).
+char(7,62207).
+char(6,62208).
+char(2,62209).
+char(c,62210).
+char(c,62211).
+char(m,62212).
+char(o,62213).
+char(2,62214).
+char(9,62215).
+char(5,62216).
+char(3,62217).
+char(c,62218).
+char(c,62219).
+char(c,62220).
+char(c,62221).
+char(m,62222).
+char(o,62223).
+char(o,62224).
+char(m,62225).
+char(4,62226).
+char(9,62227).
+char(0,62228).
+char(1,62229).
+char(c,62230).
+char(c,62231).
+char(c,62232).
+char(c,62233).
+char(c,62234).
+char(c,62235).
+char(c,62236).
+char(m,62237).
+char(5,62238).
+char(7,62239).
+char(3,62240).
+char(6,62241).
+char(m,62242).
+char(7,62243).
+char(3,62244).
+char(0,62245).
+char(c,62246).
+char(c,62247).
+char(p,62248).
+char(o,62249).
+char(o,62250).
+char(m,62251).
+char(o,62252).
+char(9,62253).
+char(3,62254).
+char(0,62255).
+char(2,62256).
+char(c,62257).
+char(p,62258).
+char(o,62259).
+char(o,62260).
+char(p,62261).
+char(6,62262).
+char(4,62263).
+char(5,62264).
+char(9,62265).
+char(c,62266).
+char(m,62267).
+char(o,62268).
+char(p,62269).
+char(5,62270).
+char(3,62271).
+char(5,62272).
+char(0,62273).
+char(m,62274).
+char(9,62275).
+char(4,62276).
+char(2,62277).
+char(6,62278).
+char(p,62279).
+char(3,62280).
+char(1,62281).
+char(3,62282).
+char(8,62283).
+char(c,62284).
+char(p,62285).
+char(8,62286).
+char(5,62287).
+char(4,62288).
+char(0,62289).
+char(c,62290).
+char(c,62291).
+char(m,62292).
+char(o,62293).
+char(4,62294).
+char(8,62295).
+char(1,62296).
+char(1,62297).
+char(c,62298).
+char(c,62299).
+char(c,62300).
+char(c,62301).
+char(m,62302).
+char(o,62303).
+char(m,62304).
+char(4,62305).
+char(4,62306).
+char(0,62307).
+char(9,62308).
+char(c,62309).
+char(c,62310).
+char(c,62311).
+char(c,62312).
+char(m,62313).
+char(7,62314).
+char(5,62315).
+char(4,62316).
+char(1,62317).
+char(p,62318).
+char(o,62319).
+char(p,62320).
+char(o,62321).
+char(p,62322).
+char(o,62323).
+char(m,62324).
+char(9,62325).
+char(6,62326).
+char(9,62327).
+char(0,62328).
+char(p,62329).
+char(o,62330).
+char(8,62331).
+char(7,62332).
+char(1,62333).
+char(5,62334).
+char(c,62335).
+char(m,62336).
+char(6,62337).
+char(9,62338).
+char(9,62339).
+char(8,62340).
+char(p,62341).
+char(7,62342).
+char(0,62343).
+char(3,62344).
+char(0,62345).
+char(c,62346).
+char(c,62347).
+char(c,62348).
+char(c,62349).
+char(c,62350).
+char(c,62351).
+char(p,62352).
+char(3,62353).
+char(5,62354).
+char(6,62355).
+char(2,62356).
+char(p,62357).
+char(3,62358).
+char(6,62359).
+char(4,62360).
+char(4,62361).
+char(c,62362).
+char(m,62363).
+char(2,62364).
+char(1,62365).
+char(3,62366).
+char(1,62367).
+char(c,62368).
+char(c,62369).
+char(m,62370).
+char(1,62371).
+char(3,62372).
+char(9,62373).
+char(2,62374).
+char(m,62375).
+char(o,62376).
+char(p,62377).
+char(6,62378).
+char(8,62379).
+char(3,62380).
+char(2,62381).
+char(c,62382).
+char(c,62383).
+char(c,62384).
+char(p,62385).
+char(4,62386).
+char(8,62387).
+char(5,62388).
+char(3,62389).
+char(c,62390).
+char(c,62391).
+char(p,62392).
+char(8,62393).
+char(4,62394).
+char(7,62395).
+char(9,62396).
+char(c,62397).
+char(p,62398).
+char(7,62399).
+char(4,62400).
+char(8,62401).
+char(0,62402).
+char(p,62403).
+char(o,62404).
+char(o,62405).
+char(p,62406).
+char(8,62407).
+char(2,62408).
+char(0,62409).
+char(7,62410).
+char(c,62411).
+char(c,62412).
+char(c,62413).
+char(c,62414).
+char(c,62415).
+char(c,62416).
+char(c,62417).
+char(c,62418).
+char(m,62419).
+char(o,62420).
+char(m,62421).
+char(o,62422).
+char(p,62423).
+char(o,62424).
+char(m,62425).
+char(1,62426).
+char(3,62427).
+char(3,62428).
+char(8,62429).
+char(m,62430).
+char(o,62431).
+char(m,62432).
+char(3,62433).
+char(8,62434).
+char(2,62435).
+char(1,62436).
+char(p,62437).
+char(o,62438).
+char(p,62439).
+char(3,62440).
+char(1,62441).
+char(p,62442).
+char(o,62443).
+char(p,62444).
+char(o,62445).
+char(m,62446).
+char(6,62447).
+char(5,62448).
+char(7,62449).
+char(9,62450).
+char(m,62451).
+char(7,62452).
+char(7,62453).
+char(8,62454).
+char(p,62455).
+char(o,62456).
+char(o,62457).
+char(8,62458).
+char(2,62459).
+char(8,62460).
+char(7,62461).
+char(c,62462).
+char(c,62463).
+char(c,62464).
+char(p,62465).
+char(o,62466).
+char(m,62467).
+char(9,62468).
+char(7,62469).
+char(0,62470).
+char(8,62471).
+char(c,62472).
+char(p,62473).
+char(7,62474).
+char(0,62475).
+char(5,62476).
+char(8,62477).
+char(c,62478).
+char(c,62479).
+char(c,62480).
+char(c,62481).
+char(m,62482).
+char(9,62483).
+char(7,62484).
+char(8,62485).
+char(0,62486).
+char(m,62487).
+char(o,62488).
+char(o,62489).
+char(p,62490).
+char(9,62491).
+char(8,62492).
+char(4,62493).
+char(2,62494).
+char(c,62495).
+char(c,62496).
+char(m,62497).
+char(o,62498).
+char(9,62499).
+char(4,62500).
+char(7,62501).
+char(2,62502).
+char(c,62503).
+char(c,62504).
+char(c,62505).
+char(m,62506).
+char(o,62507).
+char(o,62508).
+char(m,62509).
+char(5,62510).
+char(0,62511).
+char(0,62512).
+char(3,62513).
+char(p,62514).
+char(6,62515).
+char(8,62516).
+char(4,62517).
+char(3,62518).
+char(c,62519).
+char(p,62520).
+char(o,62521).
+char(p,62522).
+char(3,62523).
+char(6,62524).
+char(7,62525).
+char(4,62526).
+char(c,62527).
+char(c,62528).
+char(m,62529).
+char(8,62530).
+char(2,62531).
+char(6,62532).
+char(6,62533).
+char(c,62534).
+char(m,62535).
+char(7,62536).
+char(5,62537).
+char(7,62538).
+char(3,62539).
+char(m,62540).
+char(o,62541).
+char(9,62542).
+char(4,62543).
+char(2,62544).
+char(8,62545).
+char(m,62546).
+char(5,62547).
+char(5,62548).
+char(9,62549).
+char(7,62550).
+char(c,62551).
+char(c,62552).
+char(m,62553).
+char(1,62554).
+char(9,62555).
+char(0,62556).
+char(6,62557).
+char(c,62558).
+char(c,62559).
+char(p,62560).
+char(8,62561).
+char(2,62562).
+char(7,62563).
+char(3,62564).
+char(m,62565).
+char(9,62566).
+char(1,62567).
+char(1,62568).
+char(3,62569).
+char(p,62570).
+char(8,62571).
+char(0,62572).
+char(7,62573).
+char(8,62574).
+char(c,62575).
+char(m,62576).
+char(5,62577).
+char(8,62578).
+char(7,62579).
+char(0,62580).
+char(p,62581).
+char(o,62582).
+char(m,62583).
+char(6,62584).
+char(1,62585).
+char(5,62586).
+char(6,62587).
+char(c,62588).
+char(c,62589).
+char(m,62590).
+char(5,62591).
+char(7,62592).
+char(6,62593).
+char(1,62594).
+char(m,62595).
+char(o,62596).
+char(p,62597).
+char(8,62598).
+char(8,62599).
+char(5,62600).
+char(3,62601).
+char(c,62602).
+char(c,62603).
+char(c,62604).
+char(m,62605).
+char(3,62606).
+char(3,62607).
+char(1,62608).
+char(m,62609).
+char(4,62610).
+char(9,62611).
+char(8,62612).
+char(0,62613).
+char(m,62614).
+char(1,62615).
+char(8,62616).
+char(8,62617).
+char(6,62618).
+char(c,62619).
+char(p,62620).
+char(3,62621).
+char(8,62622).
+char(7,62623).
+char(1,62624).
+char(c,62625).
+char(p,62626).
+char(o,62627).
+char(o,62628).
+char(9,62629).
+char(5,62630).
+char(4,62631).
+char(4,62632).
+char(c,62633).
+char(m,62634).
+char(o,62635).
+char(m,62636).
+char(o,62637).
+char(m,62638).
+char(2,62639).
+char(7,62640).
+char(7,62641).
+char(2,62642).
+char(p,62643).
+char(o,62644).
+char(m,62645).
+char(o,62646).
+char(m,62647).
+char(9,62648).
+char(3,62649).
+char(2,62650).
+char(3,62651).
+char(p,62652).
+char(o,62653).
+char(o,62654).
+char(p,62655).
+char(o,62656).
+char(m,62657).
+char(8,62658).
+char(3,62659).
+char(c,62660).
+char(p,62661).
+char(o,62662).
+char(o,62663).
+char(4,62664).
+char(2,62665).
+char(0,62666).
+char(2,62667).
+char(c,62668).
+char(p,62669).
+char(o,62670).
+char(m,62671).
+char(o,62672).
+char(m,62673).
+char(6,62674).
+char(4,62675).
+char(9,62676).
+char(5,62677).
+char(p,62678).
+char(o,62679).
+char(o,62680).
+char(8,62681).
+char(4,62682).
+char(7,62683).
+char(m,62684).
+char(8,62685).
+char(0,62686).
+char(3,62687).
+char(8,62688).
+char(c,62689).
+char(p,62690).
+char(o,62691).
+char(3,62692).
+char(2,62693).
+char(6,62694).
+char(5,62695).
+char(m,62696).
+char(o,62697).
+char(p,62698).
+char(8,62699).
+char(9,62700).
+char(1,62701).
+char(0,62702).
+char(p,62703).
+char(5,62704).
+char(4,62705).
+char(9,62706).
+char(8,62707).
+char(p,62708).
+char(8,62709).
+char(1,62710).
+char(4,62711).
+char(7,62712).
+char(m,62713).
+char(o,62714).
+char(o,62715).
+char(p,62716).
+char(3,62717).
+char(3,62718).
+char(3,62719).
+char(6,62720).
+char(c,62721).
+char(m,62722).
+char(5,62723).
+char(8,62724).
+char(2,62725).
+char(0,62726).
+char(c,62727).
+char(c,62728).
+char(m,62729).
+char(9,62730).
+char(3,62731).
+char(8,62732).
+char(5,62733).
+char(c,62734).
+char(p,62735).
+char(2,62736).
+char(1,62737).
+char(7,62738).
+char(4,62739).
+char(p,62740).
+char(o,62741).
+char(m,62742).
+char(9,62743).
+char(4,62744).
+char(0,62745).
+char(0,62746).
+char(p,62747).
+char(o,62748).
+char(m,62749).
+char(8,62750).
+char(3,62751).
+char(1,62752).
+char(c,62753).
+char(p,62754).
+char(o,62755).
+char(8,62756).
+char(6,62757).
+char(6,62758).
+char(c,62759).
+char(p,62760).
+char(o,62761).
+char(o,62762).
+char(o,62763).
+char(p,62764).
+char(o,62765).
+char(o,62766).
+char(p,62767).
+char(7,62768).
+char(3,62769).
+char(8,62770).
+char(2,62771).
+char(p,62772).
+char(1,62773).
+char(5,62774).
+char(0,62775).
+char(9,62776).
+char(c,62777).
+char(c,62778).
+char(c,62779).
+char(c,62780).
+char(p,62781).
+char(6,62782).
+char(8,62783).
+char(6,62784).
+char(1,62785).
+char(p,62786).
+char(7,62787).
+char(4,62788).
+char(6,62789).
+char(2,62790).
+char(p,62791).
+char(9,62792).
+char(2,62793).
+char(9,62794).
+char(3,62795).
+char(c,62796).
+char(c,62797).
+char(p,62798).
+char(7,62799).
+char(6,62800).
+char(5,62801).
+char(8,62802).
+char(c,62803).
+char(c,62804).
+char(c,62805).
+char(m,62806).
+char(o,62807).
+char(o,62808).
+char(m,62809).
+char(7,62810).
+char(9,62811).
+char(5,62812).
+char(4,62813).
+char(c,62814).
+char(m,62815).
+char(o,62816).
+char(p,62817).
+char(o,62818).
+char(p,62819).
+char(o,62820).
+char(m,62821).
+char(7,62822).
+char(1,62823).
+char(8,62824).
+char(7,62825).
+char(m,62826).
+char(1,62827).
+char(4,62828).
+char(5,62829).
+char(1,62830).
+char(c,62831).
+char(c,62832).
+char(c,62833).
+char(p,62834).
+char(6,62835).
+char(1,62836).
+char(7,62837).
+char(7,62838).
+char(c,62839).
+char(c,62840).
+char(p,62841).
+char(4,62842).
+char(4,62843).
+char(8,62844).
+char(0,62845).
+char(p,62846).
+char(5,62847).
+char(3,62848).
+char(5,62849).
+char(5,62850).
+char(m,62851).
+char(o,62852).
+char(m,62853).
+char(o,62854).
+char(9,62855).
+char(4,62856).
+char(7,62857).
+char(7,62858).
+char(m,62859).
+char(o,62860).
+char(m,62861).
+char(1,62862).
+char(8,62863).
+char(0,62864).
+char(2,62865).
+char(m,62866).
+char(o,62867).
+char(p,62868).
+char(o,62869).
+char(p,62870).
+char(o,62871).
+char(m,62872).
+char(5,62873).
+char(6,62874).
+char(2,62875).
+char(2,62876).
+char(m,62877).
+char(o,62878).
+char(p,62879).
+char(o,62880).
+char(m,62881).
+char(7,62882).
+char(4,62883).
+char(5,62884).
+char(2,62885).
+char(c,62886).
+char(c,62887).
+char(c,62888).
+char(c,62889).
+char(p,62890).
+char(4,62891).
+char(4,62892).
+char(0,62893).
+char(0,62894).
+char(p,62895).
+char(5,62896).
+char(7,62897).
+char(3,62898).
+char(8,62899).
+char(m,62900).
+char(o,62901).
+char(o,62902).
+char(o,62903).
+char(p,62904).
+char(2,62905).
+char(8,62906).
+char(9,62907).
+char(2,62908).
+char(c,62909).
+char(c,62910).
+char(m,62911).
+char(9,62912).
+char(5,62913).
+char(3,62914).
+char(p,62915).
+char(o,62916).
+char(p,62917).
+char(9,62918).
+char(7,62919).
+char(2,62920).
+char(2,62921).
+char(c,62922).
+char(c,62923).
+char(c,62924).
+char(c,62925).
+char(c,62926).
+char(c,62927).
+char(c,62928).
+char(c,62929).
+char(c,62930).
+char(c,62931).
+char(m,62932).
+char(o,62933).
+char(p,62934).
+char(5,62935).
+char(2,62936).
+char(4,62937).
+char(4,62938).
+char(p,62939).
+char(o,62940).
+char(m,62941).
+char(o,62942).
+char(p,62943).
+char(6,62944).
+char(0,62945).
+char(6,62946).
+char(9,62947).
+char(p,62948).
+char(o,62949).
+char(6,62950).
+char(0,62951).
+char(1,62952).
+char(1,62953).
+char(c,62954).
+char(p,62955).
+char(o,62956).
+char(p,62957).
+char(5,62958).
+char(3,62959).
+char(9,62960).
+char(2,62961).
+char(m,62962).
+char(7,62963).
+char(1,62964).
+char(0,62965).
+char(8,62966).
+char(c,62967).
+char(p,62968).
+char(o,62969).
+char(5,62970).
+char(0,62971).
+char(8,62972).
+char(8,62973).
+char(p,62974).
+char(3,62975).
+char(7,62976).
+char(5,62977).
+char(2,62978).
+char(m,62979).
+char(8,62980).
+char(8,62981).
+char(5,62982).
+char(3,62983).
+char(c,62984).
+char(c,62985).
+char(c,62986).
+char(c,62987).
+char(p,62988).
+char(o,62989).
+char(8,62990).
+char(5,62991).
+char(7,62992).
+char(6,62993).
+char(m,62994).
+char(4,62995).
+char(2,62996).
+char(3,62997).
+char(c,62998).
+char(m,62999).
+char(9,63000).
+char(8,63001).
+char(7,63002).
+char(4,63003).
+char(c,63004).
+char(p,63005).
+char(o,63006).
+char(8,63007).
+char(9,63008).
+char(0,63009).
+char(2,63010).
+char(c,63011).
+char(c,63012).
+char(c,63013).
+char(m,63014).
+char(6,63015).
+char(3,63016).
+char(7,63017).
+char(6,63018).
+char(c,63019).
+char(c,63020).
+char(m,63021).
+char(4,63022).
+char(1,63023).
+char(c,63024).
+char(c,63025).
+char(c,63026).
+char(p,63027).
+char(6,63028).
+char(1,63029).
+char(4,63030).
+char(1,63031).
+char(m,63032).
+char(1,63033).
+char(1,63034).
+char(8,63035).
+char(2,63036).
+char(p,63037).
+char(9,63038).
+char(0,63039).
+char(7,63040).
+char(7,63041).
+char(m,63042).
+char(o,63043).
+char(p,63044).
+char(o,63045).
+char(m,63046).
+char(o,63047).
+char(o,63048).
+char(m,63049).
+char(5,63050).
+char(2,63051).
+char(6,63052).
+char(3,63053).
+char(p,63054).
+char(5,63055).
+char(0,63056).
+char(1,63057).
+char(p,63058).
+char(7,63059).
+char(0,63060).
+char(0,63061).
+char(3,63062).
+char(c,63063).
+char(c,63064).
+char(c,63065).
+char(m,63066).
+char(5,63067).
+char(2,63068).
+char(3,63069).
+char(2,63070).
+char(p,63071).
+char(1,63072).
+char(7,63073).
+char(3,63074).
+char(9,63075).
+char(m,63076).
+char(7,63077).
+char(7,63078).
+char(6,63079).
+char(5,63080).
+char(c,63081).
+char(c,63082).
+char(m,63083).
+char(7,63084).
+char(5,63085).
+char(8,63086).
+char(0,63087).
+char(p,63088).
+char(o,63089).
+char(m,63090).
+char(8,63091).
+char(8,63092).
+char(2,63093).
+char(1,63094).
+char(c,63095).
+char(m,63096).
+char(1,63097).
+char(0,63098).
+char(4,63099).
+char(3,63100).
+char(m,63101).
+char(o,63102).
+char(m,63103).
+char(o,63104).
+char(m,63105).
+char(o,63106).
+char(m,63107).
+char(3,63108).
+char(3,63109).
+char(0,63110).
+char(7,63111).
+char(c,63112).
+char(c,63113).
+char(p,63114).
+char(1,63115).
+char(4,63116).
+char(9,63117).
+char(8,63118).
+char(c,63119).
+char(m,63120).
+char(4,63121).
+char(0,63122).
+char(2,63123).
+char(5,63124).
+char(m,63125).
+char(o,63126).
+char(m,63127).
+char(7,63128).
+char(9,63129).
+char(9,63130).
+char(6,63131).
+char(c,63132).
+char(c,63133).
+char(c,63134).
+char(p,63135).
+char(o,63136).
+char(m,63137).
+char(o,63138).
+char(m,63139).
+char(5,63140).
+char(5,63141).
+char(4,63142).
+char(c,63143).
+char(m,63144).
+char(9,63145).
+char(1,63146).
+char(6,63147).
+char(4,63148).
+char(p,63149).
+char(2,63150).
+char(1,63151).
+char(5,63152).
+char(7,63153).
+char(c,63154).
+char(c,63155).
+char(m,63156).
+char(6,63157).
+char(1,63158).
+char(5,63159).
+char(3,63160).
+char(m,63161).
+char(o,63162).
+char(p,63163).
+char(o,63164).
+char(m,63165).
+char(o,63166).
+char(7,63167).
+char(1,63168).
+char(9,63169).
+char(5,63170).
+char(p,63171).
+char(3,63172).
+char(0,63173).
+char(8,63174).
+char(0,63175).
+char(m,63176).
+char(6,63177).
+char(6,63178).
+char(2,63179).
+char(5,63180).
+char(c,63181).
+char(m,63182).
+char(o,63183).
+char(3,63184).
+char(9,63185).
+char(4,63186).
+char(0,63187).
+char(c,63188).
+char(c,63189).
+char(c,63190).
+char(c,63191).
+char(c,63192).
+char(c,63193).
+char(m,63194).
+char(o,63195).
+char(p,63196).
+char(o,63197).
+char(p,63198).
+char(o,63199).
+char(p,63200).
+char(8,63201).
+char(5,63202).
+char(1,63203).
+char(3,63204).
+char(c,63205).
+char(c,63206).
+char(m,63207).
+char(o,63208).
+char(p,63209).
+char(1,63210).
+char(5,63211).
+char(4,63212).
+char(7,63213).
+char(m,63214).
+char(8,63215).
+char(5,63216).
+char(9,63217).
+char(p,63218).
+char(o,63219).
+char(5,63220).
+char(0,63221).
+char(1,63222).
+char(6,63223).
+char(c,63224).
+char(c,63225).
+char(m,63226).
+char(o,63227).
+char(m,63228).
+char(o,63229).
+char(p,63230).
+char(o,63231).
+char(o,63232).
+char(2,63233).
+char(6,63234).
+char(7,63235).
+char(5,63236).
+char(c,63237).
+char(p,63238).
+char(o,63239).
+char(m,63240).
+char(o,63241).
+char(o,63242).
+char(p,63243).
+char(6,63244).
+char(8,63245).
+char(8,63246).
+char(1,63247).
+char(p,63248).
+char(6,63249).
+char(2,63250).
+char(0,63251).
+char(2,63252).
+char(c,63253).
+char(c,63254).
+char(p,63255).
+char(7,63256).
+char(3,63257).
+char(5,63258).
+char(8,63259).
+char(c,63260).
+char(m,63261).
+char(3,63262).
+char(0,63263).
+char(1,63264).
+char(0,63265).
+char(m,63266).
+char(o,63267).
+char(1,63268).
+char(2,63269).
+char(9,63270).
+char(4,63271).
+char(c,63272).
+char(c,63273).
+char(c,63274).
+char(m,63275).
+char(o,63276).
+char(m,63277).
+char(o,63278).
+char(4,63279).
+char(3,63280).
+char(6,63281).
+char(0,63282).
+char(c,63283).
+char(m,63284).
+char(o,63285).
+char(m,63286).
+char(1,63287).
+char(1,63288).
+char(2,63289).
+char(8,63290).
+char(p,63291).
+char(6,63292).
+char(2,63293).
+char(9,63294).
+char(5,63295).
+char(m,63296).
+char(o,63297).
+char(m,63298).
+char(7,63299).
+char(7,63300).
+char(1,63301).
+char(8,63302).
+char(c,63303).
+char(p,63304).
+char(6,63305).
+char(9,63306).
+char(2,63307).
+char(9,63308).
+char(p,63309).
+char(o,63310).
+char(2,63311).
+char(4,63312).
+char(7,63313).
+char(3,63314).
+char(m,63315).
+char(4,63316).
+char(4,63317).
+char(6,63318).
+char(5,63319).
+char(c,63320).
+char(c,63321).
+char(c,63322).
+char(c,63323).
+char(m,63324).
+char(8,63325).
+char(7,63326).
+char(4,63327).
+char(6,63328).
+char(m,63329).
+char(8,63330).
+char(3,63331).
+char(8,63332).
+char(6,63333).
+char(c,63334).
+char(c,63335).
+char(m,63336).
+char(7,63337).
+char(6,63338).
+char(1,63339).
+char(m,63340).
+char(o,63341).
+char(o,63342).
+char(p,63343).
+char(7,63344).
+char(6,63345).
+char(4,63346).
+char(8,63347).
+char(c,63348).
+char(m,63349).
+char(o,63350).
+char(p,63351).
+char(o,63352).
+char(m,63353).
+char(o,63354).
+char(p,63355).
+char(4,63356).
+char(0,63357).
+char(7,63358).
+char(5,63359).
+char(c,63360).
+char(m,63361).
+char(o,63362).
+char(m,63363).
+char(o,63364).
+char(o,63365).
+char(p,63366).
+char(o,63367).
+char(m,63368).
+char(3,63369).
+char(7,63370).
+char(5,63371).
+char(7,63372).
+char(c,63373).
+char(m,63374).
+char(6,63375).
+char(9,63376).
+char(3,63377).
+char(8,63378).
+char(p,63379).
+char(4,63380).
+char(2,63381).
+char(1,63382).
+char(6,63383).
+char(c,63384).
+char(m,63385).
+char(o,63386).
+char(p,63387).
+char(o,63388).
+char(m,63389).
+char(6,63390).
+char(3,63391).
+char(1,63392).
+char(9,63393).
+char(c,63394).
+char(p,63395).
+char(5,63396).
+char(3,63397).
+char(1,63398).
+char(c,63399).
+char(p,63400).
+char(1,63401).
+char(1,63402).
+char(3,63403).
+char(7,63404).
+char(p,63405).
+char(7,63406).
+char(2,63407).
+char(3,63408).
+char(1,63409).
+char(m,63410).
+char(o,63411).
+char(p,63412).
+char(o,63413).
+char(p,63414).
+char(1,63415).
+char(7,63416).
+char(5,63417).
+char(9,63418).
+char(p,63419).
+char(o,63420).
+char(m,63421).
+char(1,63422).
+char(3,63423).
+char(6,63424).
+char(3,63425).
+char(m,63426).
+char(4,63427).
+char(1,63428).
+char(6,63429).
+char(3,63430).
+char(c,63431).
+char(p,63432).
+char(3,63433).
+char(7,63434).
+char(0,63435).
+char(4,63436).
+char(c,63437).
+char(m,63438).
+char(8,63439).
+char(8,63440).
+char(3,63441).
+char(6,63442).
+char(p,63443).
+char(4,63444).
+char(8,63445).
+char(7,63446).
+char(1,63447).
+char(c,63448).
+char(m,63449).
+char(o,63450).
+char(p,63451).
+char(8,63452).
+char(7,63453).
+char(0,63454).
+char(6,63455).
+char(m,63456).
+char(8,63457).
+char(8,63458).
+char(5,63459).
+char(7,63460).
+char(c,63461).
+char(c,63462).
+char(p,63463).
+char(o,63464).
+char(3,63465).
+char(2,63466).
+char(5,63467).
+char(m,63468).
+char(5,63469).
+char(1,63470).
+char(2,63471).
+char(6,63472).
+char(c,63473).
+char(c,63474).
+char(p,63475).
+char(9,63476).
+char(7,63477).
+char(1,63478).
+char(3,63479).
+char(c,63480).
+char(c,63481).
+char(m,63482).
+char(o,63483).
+char(p,63484).
+char(4,63485).
+char(2,63486).
+char(7,63487).
+char(5,63488).
+char(c,63489).
+char(c,63490).
+char(p,63491).
+char(o,63492).
+char(m,63493).
+char(4,63494).
+char(9,63495).
+char(5,63496).
+char(8,63497).
+char(c,63498).
+char(p,63499).
+char(6,63500).
+char(7,63501).
+char(7,63502).
+char(5,63503).
+char(c,63504).
+char(p,63505).
+char(7,63506).
+char(2,63507).
+char(2,63508).
+char(9,63509).
+char(m,63510).
+char(o,63511).
+char(p,63512).
+char(o,63513).
+char(p,63514).
+char(o,63515).
+char(m,63516).
+char(9,63517).
+char(6,63518).
+char(7,63519).
+char(2,63520).
+char(c,63521).
+char(p,63522).
+char(o,63523).
+char(o,63524).
+char(p,63525).
+char(3,63526).
+char(4,63527).
+char(7,63528).
+char(1,63529).
+char(p,63530).
+char(8,63531).
+char(6,63532).
+char(7,63533).
+char(3,63534).
+char(c,63535).
+char(m,63536).
+char(o,63537).
+char(p,63538).
+char(7,63539).
+char(8,63540).
+char(5,63541).
+char(5,63542).
+char(m,63543).
+char(1,63544).
+char(7,63545).
+char(2,63546).
+char(2,63547).
+char(p,63548).
+char(o,63549).
+char(m,63550).
+char(9,63551).
+char(2,63552).
+char(4,63553).
+char(0,63554).
+char(m,63555).
+char(3,63556).
+char(4,63557).
+char(7,63558).
+char(7,63559).
+char(p,63560).
+char(o,63561).
+char(8,63562).
+char(1,63563).
+char(1,63564).
+char(5,63565).
+char(p,63566).
+char(o,63567).
+char(m,63568).
+char(6,63569).
+char(8,63570).
+char(0,63571).
+char(9,63572).
+char(c,63573).
+char(c,63574).
+char(m,63575).
+char(o,63576).
+char(p,63577).
+char(o,63578).
+char(p,63579).
+char(o,63580).
+char(o,63581).
+char(p,63582).
+char(9,63583).
+char(9,63584).
+char(2,63585).
+char(3,63586).
+char(c,63587).
+char(p,63588).
+char(8,63589).
+char(4,63590).
+char(4,63591).
+char(m,63592).
+char(4,63593).
+char(9,63594).
+char(2,63595).
+char(1,63596).
+char(p,63597).
+char(o,63598).
+char(o,63599).
+char(p,63600).
+char(9,63601).
+char(8,63602).
+char(9,63603).
+char(c,63604).
+char(m,63605).
+char(6,63606).
+char(1,63607).
+char(7,63608).
+char(7,63609).
+char(p,63610).
+char(5,63611).
+char(3,63612).
+char(1,63613).
+char(m,63614).
+char(o,63615).
+char(o,63616).
+char(m,63617).
+char(o,63618).
+char(p,63619).
+char(o,63620).
+char(m,63621).
+char(4,63622).
+char(1,63623).
+char(7,63624).
+char(c,63625).
+char(m,63626).
+char(o,63627).
+char(m,63628).
+char(9,63629).
+char(4,63630).
+char(3,63631).
+char(1,63632).
+char(p,63633).
+char(o,63634).
+char(p,63635).
+char(o,63636).
+char(m,63637).
+char(o,63638).
+char(2,63639).
+char(3,63640).
+char(8,63641).
+char(3,63642).
+char(m,63643).
+char(3,63644).
+char(3,63645).
+char(5,63646).
+char(2,63647).
+char(m,63648).
+char(8,63649).
+char(0,63650).
+char(5,63651).
+char(6,63652).
+char(m,63653).
+char(8,63654).
+char(2,63655).
+char(4,63656).
+char(3,63657).
+char(c,63658).
+char(c,63659).
+char(c,63660).
+char(c,63661).
+char(c,63662).
+char(c,63663).
+char(p,63664).
+char(o,63665).
+char(m,63666).
+char(o,63667).
+char(5,63668).
+char(9,63669).
+char(7,63670).
+char(7,63671).
+char(c,63672).
+char(c,63673).
+char(m,63674).
+char(7,63675).
+char(3,63676).
+char(4,63677).
+char(0,63678).
+char(m,63679).
+char(o,63680).
+char(p,63681).
+char(2,63682).
+char(2,63683).
+char(8,63684).
+char(3,63685).
+char(c,63686).
+char(c,63687).
+char(c,63688).
+char(m,63689).
+char(3,63690).
+char(0,63691).
+char(8,63692).
+char(3,63693).
+char(c,63694).
+char(p,63695).
+char(o,63696).
+char(m,63697).
+char(o,63698).
+char(p,63699).
+char(o,63700).
+char(p,63701).
+char(8,63702).
+char(0,63703).
+char(6,63704).
+char(8,63705).
+char(p,63706).
+char(o,63707).
+char(9,63708).
+char(4,63709).
+char(2,63710).
+char(p,63711).
+char(8,63712).
+char(2,63713).
+char(0,63714).
+char(2,63715).
+char(c,63716).
+char(m,63717).
+char(8,63718).
+char(2,63719).
+char(7,63720).
+char(6,63721).
+char(c,63722).
+char(p,63723).
+char(6,63724).
+char(7,63725).
+char(0,63726).
+char(4,63727).
+char(c,63728).
+char(p,63729).
+char(o,63730).
+char(p,63731).
+char(9,63732).
+char(4,63733).
+char(7,63734).
+char(8,63735).
+char(m,63736).
+char(2,63737).
+char(7,63738).
+char(3,63739).
+char(1,63740).
+char(c,63741).
+char(c,63742).
+char(p,63743).
+char(o,63744).
+char(o,63745).
+char(m,63746).
+char(o,63747).
+char(p,63748).
+char(o,63749).
+char(3,63750).
+char(8,63751).
+char(5,63752).
+char(6,63753).
+char(c,63754).
+char(p,63755).
+char(1,63756).
+char(0,63757).
+char(3,63758).
+char(5,63759).
+char(p,63760).
+char(o,63761).
+char(5,63762).
+char(2,63763).
+char(8,63764).
+char(2,63765).
+char(m,63766).
+char(6,63767).
+char(9,63768).
+char(3,63769).
+char(2,63770).
+char(c,63771).
+char(p,63772).
+char(o,63773).
+char(m,63774).
+char(o,63775).
+char(m,63776).
+char(o,63777).
+char(o,63778).
+char(8,63779).
+char(3,63780).
+char(6,63781).
+char(5,63782).
+char(p,63783).
+char(o,63784).
+char(p,63785).
+char(o,63786).
+char(p,63787).
+char(o,63788).
+char(p,63789).
+char(6,63790).
+char(5,63791).
+char(9,63792).
+char(5,63793).
+char(m,63794).
+char(7,63795).
+char(9,63796).
+char(0,63797).
+char(9,63798).
+char(m,63799).
+char(8,63800).
+char(2,63801).
+char(5,63802).
+char(7,63803).
+char(c,63804).
+char(c,63805).
+char(m,63806).
+char(o,63807).
+char(5,63808).
+char(3,63809).
+char(9,63810).
+char(8,63811).
+char(m,63812).
+char(o,63813).
+char(4,63814).
+char(5,63815).
+char(3,63816).
+char(c,63817).
+char(c,63818).
+char(c,63819).
+char(p,63820).
+char(4,63821).
+char(2,63822).
+char(0,63823).
+char(1,63824).
+char(c,63825).
+char(p,63826).
+char(6,63827).
+char(4,63828).
+char(2,63829).
+char(m,63830).
+char(1,63831).
+char(3,63832).
+char(2,63833).
+char(4,63834).
+char(m,63835).
+char(7,63836).
+char(1,63837).
+char(4,63838).
+char(c,63839).
+char(c,63840).
+char(c,63841).
+char(p,63842).
+char(7,63843).
+char(6,63844).
+char(8,63845).
+char(c,63846).
+char(c,63847).
+char(p,63848).
+char(8,63849).
+char(0,63850).
+char(9,63851).
+char(c,63852).
+char(c,63853).
+char(c,63854).
+char(c,63855).
+char(p,63856).
+char(7,63857).
+char(3,63858).
+char(5,63859).
+char(7,63860).
+char(c,63861).
+char(p,63862).
+char(o,63863).
+char(4,63864).
+char(8,63865).
+char(4,63866).
+char(1,63867).
+char(p,63868).
+char(8,63869).
+char(3,63870).
+char(4,63871).
+char(4,63872).
+char(c,63873).
+char(c,63874).
+char(m,63875).
+char(o,63876).
+char(m,63877).
+char(3,63878).
+char(2,63879).
+char(2,63880).
+char(1,63881).
+char(c,63882).
+char(m,63883).
+char(o,63884).
+char(9,63885).
+char(1,63886).
+char(7,63887).
+char(4,63888).
+char(m,63889).
+char(6,63890).
+char(8,63891).
+char(c,63892).
+char(c,63893).
+char(c,63894).
+char(c,63895).
+char(p,63896).
+char(5,63897).
+char(8,63898).
+char(8,63899).
+char(c,63900).
+char(c,63901).
+char(c,63902).
+char(c,63903).
+char(c,63904).
+char(p,63905).
+char(1,63906).
+char(5,63907).
+char(6,63908).
+char(7,63909).
+char(c,63910).
+char(p,63911).
+char(o,63912).
+char(m,63913).
+char(o,63914).
+char(m,63915).
+char(5,63916).
+char(2,63917).
+char(9,63918).
+char(9,63919).
+char(c,63920).
+char(c,63921).
+char(m,63922).
+char(o,63923).
+char(m,63924).
+char(o,63925).
+char(p,63926).
+char(o,63927).
+char(o,63928).
+char(p,63929).
+char(5,63930).
+char(3,63931).
+char(0,63932).
+char(8,63933).
+char(m,63934).
+char(o,63935).
+char(m,63936).
+char(o,63937).
+char(o,63938).
+char(m,63939).
+char(o,63940).
+char(o,63941).
+char(o,63942).
+char(p,63943).
+char(5,63944).
+char(7,63945).
+char(2,63946).
+char(7,63947).
+char(c,63948).
+char(p,63949).
+char(o,63950).
+char(o,63951).
+char(p,63952).
+char(o,63953).
+char(p,63954).
+char(7,63955).
+char(6,63956).
+char(7,63957).
+char(3,63958).
+char(c,63959).
+char(c,63960).
+char(c,63961).
+char(c,63962).
+char(c,63963).
+char(m,63964).
+char(2,63965).
+char(8,63966).
+char(6,63967).
+char(p,63968).
+char(o,63969).
+char(m,63970).
+char(o,63971).
+char(m,63972).
+char(5,63973).
+char(8,63974).
+char(1,63975).
+char(2,63976).
+char(m,63977).
+char(4,63978).
+char(5,63979).
+char(9,63980).
+char(2,63981).
+char(c,63982).
+char(c,63983).
+char(m,63984).
+char(o,63985).
+char(m,63986).
+char(6,63987).
+char(2,63988).
+char(5,63989).
+char(c,63990).
+char(c,63991).
+char(p,63992).
+char(o,63993).
+char(p,63994).
+char(6,63995).
+char(4,63996).
+char(4,63997).
+char(2,63998).
+char(c,63999).
+char(c,64000).
+char(m,64001).
+char(3,64002).
+char(5,64003).
+char(7,64004).
+char(5,64005).
+char(m,64006).
+char(7,64007).
+char(3,64008).
+char(8,64009).
+char(8,64010).
+char(p,64011).
+char(o,64012).
+char(6,64013).
+char(6,64014).
+char(1,64015).
+char(0,64016).
+char(c,64017).
+char(p,64018).
+char(9,64019).
+char(0,64020).
+char(1,64021).
+char(3,64022).
+char(p,64023).
+char(2,64024).
+char(8,64025).
+char(0,64026).
+char(c,64027).
+char(p,64028).
+char(o,64029).
+char(o,64030).
+char(m,64031).
+char(o,64032).
+char(m,64033).
+char(o,64034).
+char(m,64035).
+char(o,64036).
+char(p,64037).
+char(7,64038).
+char(5,64039).
+char(8,64040).
+char(8,64041).
+char(m,64042).
+char(5,64043).
+char(4,64044).
+char(0,64045).
+char(4,64046).
+char(p,64047).
+char(o,64048).
+char(5,64049).
+char(9,64050).
+char(3,64051).
+char(6,64052).
+char(p,64053).
+char(o,64054).
+char(p,64055).
+char(o,64056).
+char(m,64057).
+char(o,64058).
+char(p,64059).
+char(o,64060).
+char(m,64061).
+char(2,64062).
+char(7,64063).
+char(0,64064).
+char(5,64065).
+char(p,64066).
+char(9,64067).
+char(0,64068).
+char(7,64069).
+char(0,64070).
+char(c,64071).
+char(c,64072).
+char(p,64073).
+char(o,64074).
+char(p,64075).
+char(o,64076).
+char(m,64077).
+char(o,64078).
+char(m,64079).
+char(5,64080).
+char(1,64081).
+char(6,64082).
+char(c,64083).
+char(m,64084).
+char(o,64085).
+char(m,64086).
+char(o,64087).
+char(p,64088).
+char(o,64089).
+char(m,64090).
+char(o,64091).
+char(p,64092).
+char(2,64093).
+char(4,64094).
+char(3,64095).
+char(3,64096).
+char(c,64097).
+char(m,64098).
+char(3,64099).
+char(9,64100).
+char(1,64101).
+char(0,64102).
+char(m,64103).
+char(o,64104).
+char(m,64105).
+char(o,64106).
+char(o,64107).
+char(m,64108).
+char(4,64109).
+char(5,64110).
+char(3,64111).
+char(9,64112).
+char(m,64113).
+char(o,64114).
+char(p,64115).
+char(o,64116).
+char(p,64117).
+char(o,64118).
+char(8,64119).
+char(5,64120).
+char(1,64121).
+char(p,64122).
+char(6,64123).
+char(4,64124).
+char(1,64125).
+char(4,64126).
+char(c,64127).
+char(c,64128).
+char(p,64129).
+char(o,64130).
+char(m,64131).
+char(3,64132).
+char(9,64133).
+char(1,64134).
+char(8,64135).
+char(p,64136).
+char(o,64137).
+char(7,64138).
+char(6,64139).
+char(3,64140).
+char(1,64141).
+char(c,64142).
+char(m,64143).
+char(7,64144).
+char(9,64145).
+char(4,64146).
+char(8,64147).
+char(c,64148).
+char(c,64149).
+char(c,64150).
+char(m,64151).
+char(o,64152).
+char(m,64153).
+char(3,64154).
+char(7,64155).
+char(5,64156).
+char(9,64157).
+char(c,64158).
+char(p,64159).
+char(6,64160).
+char(0,64161).
+char(4,64162).
+char(m,64163).
+char(o,64164).
+char(m,64165).
+char(1,64166).
+char(7,64167).
+char(9,64168).
+char(6,64169).
+char(c,64170).
+char(c,64171).
+char(c,64172).
+char(c,64173).
+char(p,64174).
+char(7,64175).
+char(4,64176).
+char(1,64177).
+char(2,64178).
+char(m,64179).
+char(5,64180).
+char(2,64181).
+char(3,64182).
+char(8,64183).
+char(p,64184).
+char(o,64185).
+char(9,64186).
+char(6,64187).
+char(3,64188).
+char(1,64189).
+char(c,64190).
+char(c,64191).
+char(m,64192).
+char(o,64193).
+char(m,64194).
+char(1,64195).
+char(2,64196).
+char(7,64197).
+char(6,64198).
+char(p,64199).
+char(o,64200).
+char(p,64201).
+char(o,64202).
+char(6,64203).
+char(9,64204).
+char(6,64205).
+char(7,64206).
+char(c,64207).
+char(c,64208).
+char(p,64209).
+char(o,64210).
+char(8,64211).
+char(3,64212).
+char(8,64213).
+char(7,64214).
+char(c,64215).
+char(c,64216).
+char(c,64217).
+char(c,64218).
+char(c,64219).
+char(c,64220).
+char(c,64221).
+char(c,64222).
+char(c,64223).
+char(p,64224).
+char(7,64225).
+char(8,64226).
+char(2,64227).
+char(2,64228).
+char(p,64229).
+char(1,64230).
+char(9,64231).
+char(9,64232).
+char(5,64233).
+char(c,64234).
+char(c,64235).
+char(c,64236).
+char(c,64237).
+char(c,64238).
+char(p,64239).
+char(o,64240).
+char(m,64241).
+char(1,64242).
+char(9,64243).
+char(8,64244).
+char(8,64245).
+char(c,64246).
+char(m,64247).
+char(o,64248).
+char(o,64249).
+char(m,64250).
+char(5,64251).
+char(9,64252).
+char(8,64253).
+char(m,64254).
+char(2,64255).
+char(2,64256).
+char(3,64257).
+char(8,64258).
+char(p,64259).
+char(o,64260).
+char(o,64261).
+char(3,64262).
+char(3,64263).
+char(3,64264).
+char(7,64265).
+char(c,64266).
+char(c,64267).
+char(c,64268).
+char(c,64269).
+char(p,64270).
+char(o,64271).
+char(2,64272).
+char(7,64273).
+char(4,64274).
+char(8,64275).
+char(c,64276).
+char(c,64277).
+char(c,64278).
+char(p,64279).
+char(o,64280).
+char(m,64281).
+char(o,64282).
+char(m,64283).
+char(o,64284).
+char(1,64285).
+char(1,64286).
+char(1,64287).
+char(3,64288).
+char(c,64289).
+char(m,64290).
+char(1,64291).
+char(5,64292).
+char(1,64293).
+char(4,64294).
+char(c,64295).
+char(p,64296).
+char(2,64297).
+char(1,64298).
+char(5,64299).
+char(3,64300).
+char(m,64301).
+char(4,64302).
+char(2,64303).
+char(1,64304).
+char(2,64305).
+char(m,64306).
+char(4,64307).
+char(6,64308).
+char(5,64309).
+char(9,64310).
+char(m,64311).
+char(o,64312).
+char(o,64313).
+char(p,64314).
+char(o,64315).
+char(p,64316).
+char(4,64317).
+char(4,64318).
+char(6,64319).
+char(9,64320).
+char(m,64321).
+char(o,64322).
+char(m,64323).
+char(5,64324).
+char(3,64325).
+char(5,64326).
+char(6,64327).
+char(c,64328).
+char(c,64329).
+char(p,64330).
+char(o,64331).
+char(o,64332).
+char(p,64333).
+char(2,64334).
+char(9,64335).
+char(4,64336).
+char(4,64337).
+char(m,64338).
+char(4,64339).
+char(0,64340).
+char(1,64341).
+char(0,64342).
+char(c,64343).
+char(m,64344).
+char(o,64345).
+char(m,64346).
+char(3,64347).
+char(2,64348).
+char(7,64349).
+char(9,64350).
+char(c,64351).
+char(c,64352).
+char(p,64353).
+char(4,64354).
+char(2,64355).
+char(4,64356).
+char(3,64357).
+char(p,64358).
+char(o,64359).
+char(o,64360).
+char(m,64361).
+char(9,64362).
+char(9,64363).
+char(0,64364).
+char(6,64365).
+char(m,64366).
+char(6,64367).
+char(8,64368).
+char(8,64369).
+char(6,64370).
+char(p,64371).
+char(o,64372).
+char(m,64373).
+char(3,64374).
+char(8,64375).
+char(5,64376).
+char(4,64377).
+char(p,64378).
+char(o,64379).
+char(3,64380).
+char(3,64381).
+char(3,64382).
+char(8,64383).
+char(m,64384).
+char(8,64385).
+char(2,64386).
+char(2,64387).
+char(5,64388).
+char(c,64389).
+char(m,64390).
+char(6,64391).
+char(1,64392).
+char(0,64393).
+char(7,64394).
+char(p,64395).
+char(7,64396).
+char(4,64397).
+char(3,64398).
+char(4,64399).
+char(p,64400).
+char(3,64401).
+char(7,64402).
+char(9,64403).
+char(4,64404).
+char(c,64405).
+char(c,64406).
+char(m,64407).
+char(7,64408).
+char(7,64409).
+char(7,64410).
+char(6,64411).
+char(c,64412).
+char(c,64413).
+char(c,64414).
+char(c,64415).
+char(c,64416).
+char(c,64417).
+char(c,64418).
+char(p,64419).
+char(o,64420).
+char(m,64421).
+char(2,64422).
+char(9,64423).
+char(6,64424).
+char(5,64425).
+char(c,64426).
+char(c,64427).
+char(m,64428).
+char(4,64429).
+char(3,64430).
+char(8,64431).
+char(8,64432).
+char(c,64433).
+char(c,64434).
+char(p,64435).
+char(o,64436).
+char(o,64437).
+char(o,64438).
+char(m,64439).
+char(9,64440).
+char(6,64441).
+char(6,64442).
+char(7,64443).
+char(p,64444).
+char(6,64445).
+char(8,64446).
+char(4,64447).
+char(2,64448).
+char(c,64449).
+char(m,64450).
+char(o,64451).
+char(m,64452).
+char(3,64453).
+char(6,64454).
+char(0,64455).
+char(0,64456).
+char(c,64457).
+char(m,64458).
+char(3,64459).
+char(9,64460).
+char(8,64461).
+char(7,64462).
+char(c,64463).
+char(p,64464).
+char(o,64465).
+char(p,64466).
+char(1,64467).
+char(9,64468).
+char(0,64469).
+char(6,64470).
+char(p,64471).
+char(o,64472).
+char(p,64473).
+char(9,64474).
+char(7,64475).
+char(4,64476).
+char(c,64477).
+char(m,64478).
+char(o,64479).
+char(o,64480).
+char(9,64481).
+char(5,64482).
+char(1,64483).
+char(8,64484).
+char(c,64485).
+char(p,64486).
+char(7,64487).
+char(5,64488).
+char(3,64489).
+char(3,64490).
+char(m,64491).
+char(o,64492).
+char(o,64493).
+char(o,64494).
+char(m,64495).
+char(8,64496).
+char(4,64497).
+char(6,64498).
+char(2,64499).
+char(p,64500).
+char(o,64501).
+char(o,64502).
+char(6,64503).
+char(2,64504).
+char(4,64505).
+char(9,64506).
+char(c,64507).
+char(p,64508).
+char(o,64509).
+char(p,64510).
+char(o,64511).
+char(o,64512).
+char(m,64513).
+char(o,64514).
+char(m,64515).
+char(9,64516).
+char(7,64517).
+char(9,64518).
+char(4,64519).
+char(p,64520).
+char(o,64521).
+char(m,64522).
+char(o,64523).
+char(p,64524).
+char(2,64525).
+char(5,64526).
+char(7,64527).
+char(0,64528).
+char(p,64529).
+char(8,64530).
+char(3,64531).
+char(7,64532).
+char(8,64533).
+char(p,64534).
+char(5,64535).
+char(1,64536).
+char(5,64537).
+char(6,64538).
+char(c,64539).
+char(m,64540).
+char(o,64541).
+char(p,64542).
+char(o,64543).
+char(6,64544).
+char(5,64545).
+char(7,64546).
+char(4,64547).
+char(c,64548).
+char(c,64549).
+char(c,64550).
+char(c,64551).
+char(p,64552).
+char(4,64553).
+char(1,64554).
+char(3,64555).
+char(5,64556).
+char(c,64557).
+char(p,64558).
+char(o,64559).
+char(m,64560).
+char(8,64561).
+char(7,64562).
+char(4,64563).
+char(6,64564).
+char(c,64565).
+char(m,64566).
+char(o,64567).
+char(m,64568).
+char(8,64569).
+char(1,64570).
+char(3,64571).
+char(8,64572).
+char(p,64573).
+char(5,64574).
+char(7,64575).
+char(0,64576).
+char(6,64577).
+char(c,64578).
+char(p,64579).
+char(o,64580).
+char(p,64581).
+char(9,64582).
+char(1,64583).
+char(7,64584).
+char(2,64585).
+char(p,64586).
+char(5,64587).
+char(3,64588).
+char(5,64589).
+char(7,64590).
+char(m,64591).
+char(8,64592).
+char(4,64593).
+char(0,64594).
+char(6,64595).
+char(c,64596).
+char(c,64597).
+char(p,64598).
+char(3,64599).
+char(2,64600).
+char(5,64601).
+char(m,64602).
+char(3,64603).
+char(4,64604).
+char(4,64605).
+char(1,64606).
+char(p,64607).
+char(8,64608).
+char(2,64609).
+char(2,64610).
+char(1,64611).
+char(m,64612).
+char(o,64613).
+char(o,64614).
+char(4,64615).
+char(4,64616).
+char(3,64617).
+char(5,64618).
+char(c,64619).
+char(p,64620).
+char(2,64621).
+char(5,64622).
+char(6,64623).
+char(2,64624).
+char(c,64625).
+char(c,64626).
+char(p,64627).
+char(o,64628).
+char(p,64629).
+char(9,64630).
+char(3,64631).
+char(7,64632).
+char(6,64633).
+char(m,64634).
+char(3,64635).
+char(9,64636).
+char(4,64637).
+char(7,64638).
+char(m,64639).
+char(4,64640).
+char(1,64641).
+char(3,64642).
+char(5,64643).
+char(m,64644).
+char(o,64645).
+char(o,64646).
+char(o,64647).
+char(9,64648).
+char(9,64649).
+char(5,64650).
+char(9,64651).
+char(p,64652).
+char(3,64653).
+char(6,64654).
+char(5,64655).
+char(5,64656).
+char(m,64657).
+char(o,64658).
+char(9,64659).
+char(7,64660).
+char(2,64661).
+char(8,64662).
+char(p,64663).
+char(o,64664).
+char(7,64665).
+char(8,64666).
+char(9,64667).
+char(6,64668).
+char(m,64669).
+char(4,64670).
+char(6,64671).
+char(0,64672).
+char(8,64673).
+char(p,64674).
+char(o,64675).
+char(o,64676).
+char(p,64677).
+char(o,64678).
+char(o,64679).
+char(m,64680).
+char(4,64681).
+char(5,64682).
+char(0,64683).
+char(8,64684).
+char(c,64685).
+char(p,64686).
+char(1,64687).
+char(3,64688).
+char(9,64689).
+char(9,64690).
+char(c,64691).
+char(c,64692).
+char(p,64693).
+char(o,64694).
+char(m,64695).
+char(o,64696).
+char(o,64697).
+char(p,64698).
+char(1,64699).
+char(6,64700).
+char(3,64701).
+char(5,64702).
+char(c,64703).
+char(p,64704).
+char(o,64705).
+char(p,64706).
+char(8,64707).
+char(2,64708).
+char(0,64709).
+char(8,64710).
+char(c,64711).
+char(p,64712).
+char(o,64713).
+char(o,64714).
+char(p,64715).
+char(o,64716).
+char(o,64717).
+char(7,64718).
+char(2,64719).
+char(4,64720).
+char(2,64721).
+char(p,64722).
+char(2,64723).
+char(4,64724).
+char(0,64725).
+char(6,64726).
+char(c,64727).
+char(c,64728).
+char(c,64729).
+char(m,64730).
+char(o,64731).
+char(m,64732).
+char(o,64733).
+char(m,64734).
+char(3,64735).
+char(8,64736).
+char(9,64737).
+char(6,64738).
+char(p,64739).
+char(8,64740).
+char(9,64741).
+char(0,64742).
+char(c,64743).
+char(c,64744).
+char(m,64745).
+char(o,64746).
+char(p,64747).
+char(2,64748).
+char(4,64749).
+char(6,64750).
+char(c,64751).
+char(c,64752).
+char(c,64753).
+char(m,64754).
+char(o,64755).
+char(p,64756).
+char(o,64757).
+char(m,64758).
+char(9,64759).
+char(8,64760).
+char(9,64761).
+char(7,64762).
+char(m,64763).
+char(1,64764).
+char(6,64765).
+char(6,64766).
+char(9,64767).
+char(c,64768).
+char(c,64769).
+char(p,64770).
+char(o,64771).
+char(p,64772).
+char(o,64773).
+char(m,64774).
+char(o,64775).
+char(p,64776).
+char(o,64777).
+char(p,64778).
+char(o,64779).
+char(p,64780).
+char(o,64781).
+char(p,64782).
+char(o,64783).
+char(p,64784).
+char(7,64785).
+char(6,64786).
+char(5,64787).
+char(0,64788).
+char(m,64789).
+char(o,64790).
+char(m,64791).
+char(1,64792).
+char(3,64793).
+char(1,64794).
+char(4,64795).
+char(c,64796).
+char(c,64797).
+char(c,64798).
+char(c,64799).
+char(c,64800).
+char(c,64801).
+char(c,64802).
+char(c,64803).
+char(p,64804).
+char(o,64805).
+char(1,64806).
+char(8,64807).
+char(3,64808).
+char(7,64809).
+char(m,64810).
+char(5,64811).
+char(7,64812).
+char(1,64813).
+char(4,64814).
+char(c,64815).
+char(m,64816).
+char(2,64817).
+char(8,64818).
+char(8,64819).
+char(3,64820).
+char(p,64821).
+char(o,64822).
+char(p,64823).
+char(1,64824).
+char(5,64825).
+char(4,64826).
+char(0,64827).
+char(m,64828).
+char(o,64829).
+char(o,64830).
+char(p,64831).
+char(5,64832).
+char(1,64833).
+char(m,64834).
+char(8,64835).
+char(9,64836).
+char(2,64837).
+char(0,64838).
+char(p,64839).
+char(4,64840).
+char(0,64841).
+char(2,64842).
+char(3,64843).
+char(c,64844).
+char(c,64845).
+char(p,64846).
+char(8,64847).
+char(8,64848).
+char(1,64849).
+char(1,64850).
+char(c,64851).
+char(m,64852).
+char(o,64853).
+char(p,64854).
+char(4,64855).
+char(0,64856).
+char(2,64857).
+char(4,64858).
+char(m,64859).
+char(7,64860).
+char(4,64861).
+char(9,64862).
+char(c,64863).
+char(m,64864).
+char(o,64865).
+char(m,64866).
+char(9,64867).
+char(3,64868).
+char(7,64869).
+char(3,64870).
+char(c,64871).
+char(c,64872).
+char(m,64873).
+char(9,64874).
+char(2,64875).
+char(7,64876).
+char(8,64877).
+char(m,64878).
+char(7,64879).
+char(0,64880).
+char(8,64881).
+char(5,64882).
+char(c,64883).
+char(c,64884).
+char(c,64885).
+char(m,64886).
+char(o,64887).
+char(p,64888).
+char(o,64889).
+char(m,64890).
+char(4,64891).
+char(5,64892).
+char(1,64893).
+char(0,64894).
+char(c,64895).
+char(p,64896).
+char(o,64897).
+char(5,64898).
+char(5,64899).
+char(7,64900).
+char(5,64901).
+char(p,64902).
+char(7,64903).
+char(3,64904).
+char(0,64905).
+char(6,64906).
+char(m,64907).
+char(5,64908).
+char(9,64909).
+char(9,64910).
+char(5,64911).
+char(c,64912).
+char(c,64913).
+char(c,64914).
+char(p,64915).
+char(o,64916).
+char(p,64917).
+char(3,64918).
+char(6,64919).
+char(1,64920).
+char(3,64921).
+char(c,64922).
+char(c,64923).
+char(m,64924).
+char(2,64925).
+char(8,64926).
+char(6,64927).
+char(5,64928).
+char(c,64929).
+char(p,64930).
+char(6,64931).
+char(4,64932).
+char(0,64933).
+char(7,64934).
+char(c,64935).
+char(m,64936).
+char(5,64937).
+char(5,64938).
+char(0,64939).
+char(8,64940).
+char(c,64941).
+char(p,64942).
+char(9,64943).
+char(2,64944).
+char(0,64945).
+char(3,64946).
+char(c,64947).
+char(c,64948).
+char(p,64949).
+char(1,64950).
+char(3,64951).
+char(3,64952).
+char(8,64953).
+char(c,64954).
+char(m,64955).
+char(7,64956).
+char(6,64957).
+char(3,64958).
+char(8,64959).
+char(c,64960).
+char(c,64961).
+char(p,64962).
+char(o,64963).
+char(4,64964).
+char(2,64965).
+char(1,64966).
+char(c,64967).
+char(c,64968).
+char(m,64969).
+char(o,64970).
+char(o,64971).
+char(m,64972).
+char(o,64973).
+char(o,64974).
+char(o,64975).
+char(m,64976).
+char(1,64977).
+char(8,64978).
+char(9,64979).
+char(8,64980).
+char(p,64981).
+char(o,64982).
+char(5,64983).
+char(6,64984).
+char(3,64985).
+char(m,64986).
+char(7,64987).
+char(7,64988).
+char(3,64989).
+char(3,64990).
+char(p,64991).
+char(o,64992).
+char(p,64993).
+char(1,64994).
+char(1,64995).
+char(0,64996).
+char(4,64997).
+char(m,64998).
+char(o,64999).
+char(1,65000).
+char(4,65001).
+char(8,65002).
+char(6,65003).
+char(c,65004).
+char(p,65005).
+char(o,65006).
+char(m,65007).
+char(o,65008).
+char(p,65009).
+char(5,65010).
+char(6,65011).
+char(6,65012).
+char(9,65013).
+char(p,65014).
+char(6,65015).
+char(5,65016).
+char(0,65017).
+char(0,65018).
+char(p,65019).
+char(2,65020).
+char(1,65021).
+char(7,65022).
+char(0,65023).
+char(c,65024).
+char(c,65025).
+char(p,65026).
+char(6,65027).
+char(9,65028).
+char(7,65029).
+char(9,65030).
+char(m,65031).
+char(o,65032).
+char(o,65033).
+char(m,65034).
+char(o,65035).
+char(p,65036).
+char(o,65037).
+char(p,65038).
+char(7,65039).
+char(4,65040).
+char(8,65041).
+char(1,65042).
+char(p,65043).
+char(6,65044).
+char(2,65045).
+char(5,65046).
+char(6,65047).
+char(c,65048).
+char(c,65049).
+char(p,65050).
+char(1,65051).
+char(9,65052).
+char(9,65053).
+char(8,65054).
+char(m,65055).
+char(5,65056).
+char(8,65057).
+char(6,65058).
+char(8,65059).
+char(p,65060).
+char(o,65061).
+char(6,65062).
+char(0,65063).
+char(8,65064).
+char(1,65065).
+char(p,65066).
+char(o,65067).
+char(m,65068).
+char(6,65069).
+char(0,65070).
+char(2,65071).
+char(9,65072).
+char(m,65073).
+char(o,65074).
+char(m,65075).
+char(4,65076).
+char(9,65077).
+char(3,65078).
+char(8,65079).
+char(m,65080).
+char(o,65081).
+char(m,65082).
+char(o,65083).
+char(m,65084).
+char(o,65085).
+char(p,65086).
+char(o,65087).
+char(p,65088).
+char(o,65089).
+char(m,65090).
+char(o,65091).
+char(p,65092).
+char(o,65093).
+char(p,65094).
+char(o,65095).
+char(m,65096).
+char(4,65097).
+char(2,65098).
+char(9,65099).
+char(8,65100).
+char(m,65101).
+char(7,65102).
+char(8,65103).
+char(9,65104).
+char(6,65105).
+char(c,65106).
+char(m,65107).
+char(9,65108).
+char(0,65109).
+char(1,65110).
+char(6,65111).
+char(p,65112).
+char(o,65113).
+char(7,65114).
+char(6,65115).
+char(0,65116).
+char(0,65117).
+char(m,65118).
+char(o,65119).
+char(p,65120).
+char(6,65121).
+char(8,65122).
+char(6,65123).
+char(4,65124).
+char(c,65125).
+char(p,65126).
+char(2,65127).
+char(7,65128).
+char(3,65129).
+char(3,65130).
+char(p,65131).
+char(o,65132).
+char(p,65133).
+char(o,65134).
+char(m,65135).
+char(5,65136).
+char(8,65137).
+char(9,65138).
+char(2,65139).
+char(m,65140).
+char(9,65141).
+char(7,65142).
+char(8,65143).
+char(2,65144).
+char(p,65145).
+char(o,65146).
+char(m,65147).
+char(8,65148).
+char(6,65149).
+char(9,65150).
+char(4,65151).
+char(c,65152).
+char(c,65153).
+char(p,65154).
+char(2,65155).
+char(9,65156).
+char(5,65157).
+char(2,65158).
+char(p,65159).
+char(7,65160).
+char(7,65161).
+char(2,65162).
+char(6,65163).
+char(c,65164).
+char(c,65165).
+char(p,65166).
+char(o,65167).
+char(p,65168).
+char(8,65169).
+char(3,65170).
+char(5,65171).
+char(7,65172).
+char(c,65173).
+char(c,65174).
+char(p,65175).
+char(o,65176).
+char(m,65177).
+char(2,65178).
+char(7,65179).
+char(7,65180).
+char(6,65181).
+char(p,65182).
+char(8,65183).
+char(1,65184).
+char(0,65185).
+char(4,65186).
+char(c,65187).
+char(p,65188).
+char(o,65189).
+char(m,65190).
+char(o,65191).
+char(m,65192).
+char(2,65193).
+char(1,65194).
+char(5,65195).
+char(2,65196).
+char(m,65197).
+char(1,65198).
+char(2,65199).
+char(2,65200).
+char(9,65201).
+char(c,65202).
+char(p,65203).
+char(1,65204).
+char(7,65205).
+char(5,65206).
+char(9,65207).
+char(c,65208).
+char(c,65209).
+char(m,65210).
+char(o,65211).
+char(m,65212).
+char(o,65213).
+char(p,65214).
+char(o,65215).
+char(p,65216).
+char(o,65217).
+char(m,65218).
+char(5,65219).
+char(0,65220).
+char(8,65221).
+char(5,65222).
+char(c,65223).
+char(m,65224).
+char(8,65225).
+char(7,65226).
+char(6,65227).
+char(0,65228).
+char(p,65229).
+char(4,65230).
+char(6,65231).
+char(4,65232).
+char(1,65233).
+char(c,65234).
+char(p,65235).
+char(1,65236).
+char(1,65237).
+char(8,65238).
+char(1,65239).
+char(p,65240).
+char(9,65241).
+char(2,65242).
+char(8,65243).
+char(1,65244).
+char(m,65245).
+char(1,65246).
+char(3,65247).
+char(9,65248).
+char(3,65249).
+char(m,65250).
+char(5,65251).
+char(7,65252).
+char(9,65253).
+char(9,65254).
+char(c,65255).
+char(c,65256).
+char(c,65257).
+char(m,65258).
+char(o,65259).
+char(m,65260).
+char(7,65261).
+char(4,65262).
+char(2,65263).
+char(9,65264).
+char(p,65265).
+char(8,65266).
+char(7,65267).
+char(5,65268).
+char(4,65269).
+char(m,65270).
+char(4,65271).
+char(5,65272).
+char(6,65273).
+char(5,65274).
+char(c,65275).
+char(m,65276).
+char(3,65277).
+char(1,65278).
+char(4,65279).
+char(8,65280).
+char(p,65281).
+char(8,65282).
+char(5,65283).
+char(7,65284).
+char(1,65285).
+char(p,65286).
+char(3,65287).
+char(7,65288).
+char(0,65289).
+char(4,65290).
+char(m,65291).
+char(4,65292).
+char(7,65293).
+char(1,65294).
+char(1,65295).
+char(c,65296).
+char(p,65297).
+char(9,65298).
+char(8,65299).
+char(5,65300).
+char(4,65301).
+char(c,65302).
+char(c,65303).
+char(p,65304).
+char(o,65305).
+char(m,65306).
+char(3,65307).
+char(8,65308).
+char(0,65309).
+char(9,65310).
+char(c,65311).
+char(m,65312).
+char(3,65313).
+char(3,65314).
+char(4,65315).
+char(c,65316).
+char(p,65317).
+char(7,65318).
+char(2,65319).
+char(7,65320).
+char(9,65321).
+char(c,65322).
+char(c,65323).
+char(c,65324).
+char(c,65325).
+char(p,65326).
+char(7,65327).
+char(1,65328).
+char(2,65329).
+char(9,65330).
+char(c,65331).
+char(c,65332).
+char(c,65333).
+char(c,65334).
+char(p,65335).
+char(8,65336).
+char(4,65337).
+char(8,65338).
+char(7,65339).
+char(c,65340).
+char(m,65341).
+char(7,65342).
+char(0,65343).
+char(3,65344).
+char(5,65345).
+char(c,65346).
+char(m,65347).
+char(o,65348).
+char(p,65349).
+char(o,65350).
+char(m,65351).
+char(8,65352).
+char(2,65353).
+char(7,65354).
+char(0,65355).
+char(c,65356).
+char(m,65357).
+char(o,65358).
+char(1,65359).
+char(6,65360).
+char(7,65361).
+char(2,65362).
+char(m,65363).
+char(o,65364).
+char(5,65365).
+char(8,65366).
+char(7,65367).
+char(3,65368).
+char(c,65369).
+char(m,65370).
+char(8,65371).
+char(5,65372).
+char(5,65373).
+char(6,65374).
+char(p,65375).
+char(o,65376).
+char(9,65377).
+char(3,65378).
+char(3,65379).
+char(3,65380).
+char(p,65381).
+char(o,65382).
+char(p,65383).
+char(5,65384).
+char(4,65385).
+char(5,65386).
+char(6,65387).
+char(c,65388).
+char(m,65389).
+char(4,65390).
+char(4,65391).
+char(4,65392).
+char(p,65393).
+char(o,65394).
+char(m,65395).
+char(o,65396).
+char(6,65397).
+char(6,65398).
+char(3,65399).
+char(0,65400).
+char(m,65401).
+char(o,65402).
+char(p,65403).
+char(o,65404).
+char(m,65405).
+char(9,65406).
+char(2,65407).
+char(7,65408).
+char(1,65409).
+char(p,65410).
+char(9,65411).
+char(2,65412).
+char(6,65413).
+char(5,65414).
+char(m,65415).
+char(6,65416).
+char(2,65417).
+char(6,65418).
+char(7,65419).
+char(m,65420).
+char(5,65421).
+char(8,65422).
+char(0,65423).
+char(2,65424).
+char(p,65425).
+char(o,65426).
+char(p,65427).
+char(o,65428).
+char(6,65429).
+char(6,65430).
+char(7,65431).
+char(6,65432).
+char(p,65433).
+char(6,65434).
+char(3,65435).
+char(8,65436).
+char(7,65437).
+char(p,65438).
+char(o,65439).
+char(o,65440).
+char(m,65441).
+char(1,65442).
+char(6,65443).
+char(6,65444).
+char(1,65445).
+char(m,65446).
+char(2,65447).
+char(0,65448).
+char(5,65449).
+char(p,65450).
+char(o,65451).
+char(m,65452).
+char(1,65453).
+char(2,65454).
+char(0,65455).
+char(8,65456).
+char(p,65457).
+char(o,65458).
+char(p,65459).
+char(8,65460).
+char(6,65461).
+char(8,65462).
+char(3,65463).
+char(c,65464).
+char(p,65465).
+char(o,65466).
+char(m,65467).
+char(o,65468).
+char(o,65469).
+char(p,65470).
+char(9,65471).
+char(1,65472).
+char(1,65473).
+char(7,65474).
+char(c,65475).
+char(c,65476).
+char(p,65477).
+char(5,65478).
+char(1,65479).
+char(6,65480).
+char(2,65481).
+char(c,65482).
+char(c,65483).
+char(m,65484).
+char(o,65485).
+char(o,65486).
+char(7,65487).
+char(3,65488).
+char(9,65489).
+char(7,65490).
+char(p,65491).
+char(1,65492).
+char(8,65493).
+char(4,65494).
+char(3,65495).
+char(c,65496).
+char(c,65497).
+char(m,65498).
+char(2,65499).
+char(3,65500).
+char(5,65501).
+char(6,65502).
+char(c,65503).
+char(p,65504).
+char(7,65505).
+char(1,65506).
+char(4,65507).
+char(7,65508).
+char(c,65509).
+char(c,65510).
+char(m,65511).
+char(o,65512).
+char(o,65513).
+char(o,65514).
+char(o,65515).
+char(p,65516).
+char(o,65517).
+char(p,65518).
+char(o,65519).
+char(p,65520).
+char(9,65521).
+char(3,65522).
+char(4,65523).
+char(7,65524).
+char(c,65525).
+char(c,65526).
+char(c,65527).
+char(p,65528).
+char(7,65529).
+char(1,65530).
+char(3,65531).
+char(7,65532).
+char(c,65533).
+char(m,65534).
+char(o,65535).
+char(p,65536).
+char(5,65537).
+char(3,65538).
+char(5,65539).
+char(7,65540).
+char(c,65541).
+char(m,65542).
+char(o,65543).
+char(m,65544).
+char(o,65545).
+char(m,65546).
+char(5,65547).
+char(3,65548).
+char(0,65549).
+char(7,65550).
+char(p,65551).
+char(6,65552).
+char(9,65553).
+char(1,65554).
+char(5,65555).
+char(c,65556).
+char(c,65557).
+char(c,65558).
+char(c,65559).
+char(p,65560).
+char(o,65561).
+char(2,65562).
+char(5,65563).
+char(7,65564).
+char(0,65565).
+char(c,65566).
+char(c,65567).
+char(p,65568).
+char(1,65569).
+char(1,65570).
+char(8,65571).
+char(9,65572).
+char(m,65573).
+char(9,65574).
+char(7,65575).
+char(3,65576).
+char(7,65577).
+char(p,65578).
+char(3,65579).
+char(4,65580).
+char(8,65581).
+char(m,65582).
+char(8,65583).
+char(1,65584).
+char(4,65585).
+char(9,65586).
+char(c,65587).
+char(c,65588).
+char(c,65589).
+char(c,65590).
+char(m,65591).
+char(o,65592).
+char(p,65593).
+char(o,65594).
+char(m,65595).
+char(o,65596).
+char(m,65597).
+char(5,65598).
+char(1,65599).
+char(9,65600).
+char(0,65601).
+char(m,65602).
+char(o,65603).
+char(m,65604).
+char(o,65605).
+char(m,65606).
+char(o,65607).
+char(m,65608).
+char(o,65609).
+char(o,65610).
+char(p,65611).
+char(o,65612).
+char(m,65613).
+char(4,65614).
+char(9,65615).
+char(8,65616).
+char(0,65617).
+char(m,65618).
+char(o,65619).
+char(p,65620).
+char(3,65621).
+char(2,65622).
+char(8,65623).
+char(0,65624).
+char(m,65625).
+char(2,65626).
+char(5,65627).
+char(8,65628).
+char(9,65629).
+char(c,65630).
+char(p,65631).
+char(1,65632).
+char(3,65633).
+char(6,65634).
+char(5,65635).
+char(p,65636).
+char(o,65637).
+char(o,65638).
+char(m,65639).
+char(3,65640).
+char(8,65641).
+char(2,65642).
+char(1,65643).
+char(c,65644).
+char(c,65645).
+char(c,65646).
+char(c,65647).
+char(p,65648).
+char(o,65649).
+char(o,65650).
+char(p,65651).
+char(3,65652).
+char(7,65653).
+char(0,65654).
+char(3,65655).
+char(c,65656).
+char(p,65657).
+char(o,65658).
+char(m,65659).
+char(4,65660).
+char(4,65661).
+char(4,65662).
+char(4,65663).
+char(c,65664).
+char(m,65665).
+char(6,65666).
+char(6,65667).
+char(1,65668).
+char(1,65669).
+char(c,65670).
+char(p,65671).
+char(9,65672).
+char(7,65673).
+char(c,65674).
+char(c,65675).
+char(c,65676).
+char(p,65677).
+char(o,65678).
+char(p,65679).
+char(9,65680).
+char(3,65681).
+char(8,65682).
+char(3,65683).
+char(c,65684).
+char(c,65685).
+char(c,65686).
+char(p,65687).
+char(5,65688).
+char(0,65689).
+char(4,65690).
+char(8,65691).
+char(m,65692).
+char(o,65693).
+char(p,65694).
+char(o,65695).
+char(m,65696).
+char(o,65697).
+char(p,65698).
+char(6,65699).
+char(1,65700).
+char(0,65701).
+char(p,65702).
+char(o,65703).
+char(p,65704).
+char(8,65705).
+char(0,65706).
+char(2,65707).
+char(8,65708).
+char(m,65709).
+char(o,65710).
+char(p,65711).
+char(2,65712).
+char(5,65713).
+char(4,65714).
+char(c,65715).
+char(c,65716).
+char(p,65717).
+char(o,65718).
+char(o,65719).
+char(5,65720).
+char(5,65721).
+char(2,65722).
+char(5,65723).
+char(p,65724).
+char(o,65725).
+char(p,65726).
+char(5,65727).
+char(2,65728).
+char(3,65729).
+char(c,65730).
+char(c,65731).
+char(m,65732).
+char(o,65733).
+char(o,65734).
+char(p,65735).
+char(o,65736).
+char(p,65737).
+char(9,65738).
+char(2,65739).
+char(6,65740).
+char(6,65741).
+char(c,65742).
+char(m,65743).
+char(o,65744).
+char(7,65745).
+char(6,65746).
+char(9,65747).
+char(5,65748).
+char(m,65749).
+char(o,65750).
+char(p,65751).
+char(9,65752).
+char(6,65753).
+char(8,65754).
+char(2,65755).
+char(c,65756).
+char(c,65757).
+char(c,65758).
+char(m,65759).
+char(3,65760).
+char(0,65761).
+char(0,65762).
+char(8,65763).
+char(c,65764).
+char(m,65765).
+char(2,65766).
+char(4,65767).
+char(8,65768).
+char(7,65769).
+char(c,65770).
+char(m,65771).
+char(6,65772).
+char(6,65773).
+char(1,65774).
+char(1,65775).
+char(c,65776).
+char(p,65777).
+char(o,65778).
+char(p,65779).
+char(5,65780).
+char(0,65781).
+char(6,65782).
+char(7,65783).
+char(c,65784).
+char(p,65785).
+char(o,65786).
+char(m,65787).
+char(o,65788).
+char(p,65789).
+char(9,65790).
+char(7,65791).
+char(7,65792).
+char(6,65793).
+char(p,65794).
+char(7,65795).
+char(1,65796).
+char(4,65797).
+char(7,65798).
+char(c,65799).
+char(p,65800).
+char(o,65801).
+char(m,65802).
+char(o,65803).
+char(p,65804).
+char(o,65805).
+char(p,65806).
+char(o,65807).
+char(o,65808).
+char(3,65809).
+char(3,65810).
+char(1,65811).
+char(7,65812).
+char(c,65813).
+char(c,65814).
+char(p,65815).
+char(o,65816).
+char(p,65817).
+char(o,65818).
+char(m,65819).
+char(9,65820).
+char(6,65821).
+char(3,65822).
+char(1,65823).
+char(p,65824).
+char(o,65825).
+char(p,65826).
+char(9,65827).
+char(0,65828).
+char(9,65829).
+char(2,65830).
+char(c,65831).
+char(p,65832).
+char(2,65833).
+char(8,65834).
+char(5,65835).
+char(4,65836).
+char(p,65837).
+char(o,65838).
+char(p,65839).
+char(9,65840).
+char(1,65841).
+char(2,65842).
+char(1,65843).
+char(m,65844).
+char(o,65845).
+char(o,65846).
+char(m,65847).
+char(3,65848).
+char(9,65849).
+char(4,65850).
+char(3,65851).
+char(c,65852).
+char(m,65853).
+char(o,65854).
+char(m,65855).
+char(o,65856).
+char(m,65857).
+char(o,65858).
+char(p,65859).
+char(o,65860).
+char(m,65861).
+char(9,65862).
+char(3,65863).
+char(9,65864).
+char(c,65865).
+char(p,65866).
+char(o,65867).
+char(m,65868).
+char(5,65869).
+char(4,65870).
+char(6,65871).
+char(9,65872).
+char(m,65873).
+char(o,65874).
+char(p,65875).
+char(o,65876).
+char(m,65877).
+char(o,65878).
+char(p,65879).
+char(o,65880).
+char(m,65881).
+char(5,65882).
+char(9,65883).
+char(3,65884).
+char(7,65885).
+char(c,65886).
+char(p,65887).
+char(o,65888).
+char(o,65889).
+char(m,65890).
+char(o,65891).
+char(m,65892).
+char(o,65893).
+char(3,65894).
+char(5,65895).
+char(5,65896).
+char(6,65897).
+char(c,65898).
+char(p,65899).
+char(o,65900).
+char(p,65901).
+char(o,65902).
+char(p,65903).
+char(5,65904).
+char(5,65905).
+char(7,65906).
+char(9,65907).
+char(c,65908).
+char(p,65909).
+char(5,65910).
+char(8,65911).
+char(8,65912).
+char(4,65913).
+char(c,65914).
+char(c,65915).
+char(c,65916).
+char(m,65917).
+char(6,65918).
+char(9,65919).
+char(1,65920).
+char(7,65921).
+char(p,65922).
+char(3,65923).
+char(2,65924).
+char(7,65925).
+char(2,65926).
+char(c,65927).
+char(c,65928).
+char(m,65929).
+char(o,65930).
+char(o,65931).
+char(m,65932).
+char(o,65933).
+char(2,65934).
+char(4,65935).
+char(c,65936).
+char(c,65937).
+char(c,65938).
+char(p,65939).
+char(o,65940).
+char(7,65941).
+char(1,65942).
+char(8,65943).
+char(2,65944).
+char(c,65945).
+char(c,65946).
+char(m,65947).
+char(1,65948).
+char(7,65949).
+char(3,65950).
+char(0,65951).
+char(c,65952).
+char(m,65953).
+char(2,65954).
+char(7,65955).
+char(3,65956).
+char(4,65957).
+char(c,65958).
+char(c,65959).
+char(c,65960).
+char(c,65961).
+char(p,65962).
+char(4,65963).
+char(6,65964).
+char(0,65965).
+char(9,65966).
+char(c,65967).
+char(m,65968).
+char(o,65969).
+char(o,65970).
+char(m,65971).
+char(o,65972).
+char(o,65973).
+char(p,65974).
+char(o,65975).
+char(p,65976).
+char(o,65977).
+char(o,65978).
+char(m,65979).
+char(8,65980).
+char(2,65981).
+char(6,65982).
+char(c,65983).
+char(p,65984).
+char(2,65985).
+char(1,65986).
+char(8,65987).
+char(m,65988).
+char(o,65989).
+char(o,65990).
+char(m,65991).
+char(3,65992).
+char(6,65993).
+char(5,65994).
+char(1,65995).
+char(m,65996).
+char(o,65997).
+char(p,65998).
+char(2,65999).
+char(4,66000).
+char(4,66001).
+char(5,66002).
+char(m,66003).
+char(4,66004).
+char(1,66005).
+char(3,66006).
+char(m,66007).
+char(5,66008).
+char(3,66009).
+char(3,66010).
+char(3,66011).
+char(p,66012).
+char(9,66013).
+char(6,66014).
+char(8,66015).
+char(3,66016).
+char(c,66017).
+char(m,66018).
+char(o,66019).
+char(p,66020).
+char(o,66021).
+char(m,66022).
+char(o,66023).
+char(o,66024).
+char(6,66025).
+char(1,66026).
+char(3,66027).
+char(p,66028).
+char(o,66029).
+char(o,66030).
+char(p,66031).
+char(5,66032).
+char(0,66033).
+char(6,66034).
+char(6,66035).
+char(p,66036).
+char(o,66037).
+char(p,66038).
+char(o,66039).
+char(m,66040).
+char(o,66041).
+char(3,66042).
+char(3,66043).
+char(2,66044).
+char(1,66045).
+char(p,66046).
+char(o,66047).
+char(p,66048).
+char(o,66049).
+char(p,66050).
+char(o,66051).
+char(m,66052).
+char(o,66053).
+char(m,66054).
+char(4,66055).
+char(1,66056).
+char(9,66057).
+char(0,66058).
+char(c,66059).
+char(c,66060).
+char(p,66061).
+char(o,66062).
+char(m,66063).
+char(5,66064).
+char(6,66065).
+char(2,66066).
+char(c,66067).
+char(c,66068).
+char(p,66069).
+char(9,66070).
+char(4,66071).
+char(2,66072).
+char(4,66073).
+char(m,66074).
+char(o,66075).
+char(m,66076).
+char(7,66077).
+char(1,66078).
+char(0,66079).
+char(9,66080).
+char(p,66081).
+char(1,66082).
+char(5,66083).
+char(5,66084).
+char(9,66085).
+char(c,66086).
+char(p,66087).
+char(1,66088).
+char(8,66089).
+char(2,66090).
+char(6,66091).
+char(c,66092).
+char(c,66093).
+char(c,66094).
+char(p,66095).
+char(o,66096).
+char(p,66097).
+char(6,66098).
+char(8,66099).
+char(7,66100).
+char(7,66101).
+char(m,66102).
+char(o,66103).
+char(p,66104).
+char(o,66105).
+char(p,66106).
+char(o,66107).
+char(m,66108).
+char(o,66109).
+char(9,66110).
+char(9,66111).
+char(7,66112).
+char(0,66113).
+char(c,66114).
+char(c,66115).
+char(p,66116).
+char(o,66117).
+char(m,66118).
+char(8,66119).
+char(5,66120).
+char(0,66121).
+char(2,66122).
+char(m,66123).
+char(1,66124).
+char(9,66125).
+char(5,66126).
+char(m,66127).
+char(o,66128).
+char(3,66129).
+char(8,66130).
+char(7,66131).
+char(5,66132).
+char(m,66133).
+char(o,66134).
+char(m,66135).
+char(4,66136).
+char(1,66137).
+char(9,66138).
+char(3,66139).
+char(c,66140).
+char(c,66141).
+char(c,66142).
+char(c,66143).
+char(c,66144).
+char(c,66145).
+char(m,66146).
+char(4,66147).
+char(8,66148).
+char(1,66149).
+char(p,66150).
+char(3,66151).
+char(3,66152).
+char(7,66153).
+char(5,66154).
+char(c,66155).
+char(c,66156).
+char(c,66157).
+char(p,66158).
+char(o,66159).
+char(p,66160).
+char(o,66161).
+char(p,66162).
+char(o,66163).
+char(o,66164).
+char(m,66165).
+char(1,66166).
+char(3,66167).
+char(5,66168).
+char(3,66169).
+char(p,66170).
+char(o,66171).
+char(m,66172).
+char(o,66173).
+char(m,66174).
+char(2,66175).
+char(5,66176).
+char(7,66177).
+char(1,66178).
+char(m,66179).
+char(5,66180).
+char(4,66181).
+char(1,66182).
+char(0,66183).
+char(p,66184).
+char(5,66185).
+char(7,66186).
+char(2,66187).
+char(5,66188).
+char(c,66189).
+char(c,66190).
+char(c,66191).
+char(c,66192).
+char(c,66193).
+char(c,66194).
+char(c,66195).
+char(c,66196).
+char(m,66197).
+char(4,66198).
+char(0,66199).
+char(0,66200).
+char(c,66201).
+char(c,66202).
+char(p,66203).
+char(4,66204).
+char(0,66205).
+char(2,66206).
+char(3,66207).
+char(c,66208).
+char(p,66209).
+char(o,66210).
+char(m,66211).
+char(4,66212).
+char(8,66213).
+char(9,66214).
+char(9,66215).
+char(c,66216).
+char(p,66217).
+char(o,66218).
+char(p,66219).
+char(4,66220).
+char(5,66221).
+char(1,66222).
+char(6,66223).
+char(p,66224).
+char(1,66225).
+char(0,66226).
+char(1,66227).
+char(0,66228).
+char(c,66229).
+char(m,66230).
+char(o,66231).
+char(o,66232).
+char(p,66233).
+char(o,66234).
+char(2,66235).
+char(2,66236).
+char(4,66237).
+char(c,66238).
+char(p,66239).
+char(9,66240).
+char(0,66241).
+char(5,66242).
+char(5,66243).
+char(p,66244).
+char(o,66245).
+char(m,66246).
+char(6,66247).
+char(8,66248).
+char(3,66249).
+char(5,66250).
+char(c,66251).
+char(c,66252).
+char(p,66253).
+char(6,66254).
+char(9,66255).
+char(8,66256).
+char(2,66257).
+char(m,66258).
+char(o,66259).
+char(m,66260).
+char(9,66261).
+char(1,66262).
+char(2,66263).
+char(8,66264).
+char(p,66265).
+char(o,66266).
+char(m,66267).
+char(o,66268).
+char(m,66269).
+char(8,66270).
+char(3,66271).
+char(8,66272).
+char(1,66273).
+char(c,66274).
+char(c,66275).
+char(c,66276).
+char(c,66277).
+char(p,66278).
+char(o,66279).
+char(m,66280).
+char(5,66281).
+char(1,66282).
+char(9,66283).
+char(0,66284).
+char(c,66285).
+char(c,66286).
+char(c,66287).
+char(c,66288).
+char(c,66289).
+char(p,66290).
+char(5,66291).
+char(0,66292).
+char(1,66293).
+char(5,66294).
+char(p,66295).
+char(o,66296).
+char(p,66297).
+char(o,66298).
+char(m,66299).
+char(o,66300).
+char(6,66301).
+char(6,66302).
+char(3,66303).
+char(5,66304).
+char(c,66305).
+char(c,66306).
+char(c,66307).
+char(p,66308).
+char(o,66309).
+char(p,66310).
+char(o,66311).
+char(m,66312).
+char(5,66313).
+char(9,66314).
+char(2,66315).
+char(2,66316).
+char(p,66317).
+char(7,66318).
+char(0,66319).
+char(5,66320).
+char(6,66321).
+char(p,66322).
+char(5,66323).
+char(8,66324).
+char(4,66325).
+char(c,66326).
+char(m,66327).
+char(o,66328).
+char(m,66329).
+char(3,66330).
+char(7,66331).
+char(0,66332).
+char(1,66333).
+char(c,66334).
+char(c,66335).
+char(c,66336).
+char(m,66337).
+char(3,66338).
+char(9,66339).
+char(5,66340).
+char(1,66341).
+char(c,66342).
+char(c,66343).
+char(c,66344).
+char(c,66345).
+char(p,66346).
+char(o,66347).
+char(m,66348).
+char(3,66349).
+char(4,66350).
+char(2,66351).
+char(4,66352).
+char(m,66353).
+char(2,66354).
+char(0,66355).
+char(3,66356).
+char(8,66357).
+char(m,66358).
+char(o,66359).
+char(p,66360).
+char(4,66361).
+char(3,66362).
+char(5,66363).
+char(9,66364).
+char(m,66365).
+char(8,66366).
+char(9,66367).
+char(5,66368).
+char(8,66369).
+char(c,66370).
+char(p,66371).
+char(4,66372).
+char(7,66373).
+char(7,66374).
+char(m,66375).
+char(o,66376).
+char(6,66377).
+char(2,66378).
+char(3,66379).
+char(5,66380).
+char(c,66381).
+char(m,66382).
+char(o,66383).
+char(m,66384).
+char(1,66385).
+char(2,66386).
+char(7,66387).
+char(c,66388).
+char(c,66389).
+char(m,66390).
+char(o,66391).
+char(p,66392).
+char(6,66393).
+char(3,66394).
+char(7,66395).
+char(2,66396).
+char(p,66397).
+char(1,66398).
+char(6,66399).
+char(9,66400).
+char(2,66401).
+char(c,66402).
+char(p,66403).
+char(o,66404).
+char(m,66405).
+char(o,66406).
+char(m,66407).
+char(2,66408).
+char(2,66409).
+char(7,66410).
+char(4,66411).
+char(p,66412).
+char(4,66413).
+char(1,66414).
+char(3,66415).
+char(m,66416).
+char(6,66417).
+char(6,66418).
+char(8,66419).
+char(9,66420).
+char(c,66421).
+char(m,66422).
+char(o,66423).
+char(m,66424).
+char(7,66425).
+char(5,66426).
+char(4,66427).
+char(1,66428).
+char(m,66429).
+char(8,66430).
+char(3,66431).
+char(1,66432).
+char(2,66433).
+char(c,66434).
+char(p,66435).
+char(5,66436).
+char(7,66437).
+char(4,66438).
+char(4,66439).
+char(c,66440).
+char(c,66441).
+char(m,66442).
+char(o,66443).
+char(m,66444).
+char(o,66445).
+char(m,66446).
+char(3,66447).
+char(7,66448).
+char(3,66449).
+char(7,66450).
+char(c,66451).
+char(c,66452).
+char(c,66453).
+char(c,66454).
+char(m,66455).
+char(o,66456).
+char(m,66457).
+char(o,66458).
+char(p,66459).
+char(o,66460).
+char(o,66461).
+char(m,66462).
+char(o,66463).
+char(o,66464).
+char(p,66465).
+char(2,66466).
+char(8,66467).
+char(6,66468).
+char(c,66469).
+char(c,66470).
+char(c,66471).
+char(p,66472).
+char(o,66473).
+char(p,66474).
+char(o,66475).
+char(p,66476).
+char(o,66477).
+char(o,66478).
+char(p,66479).
+char(o,66480).
+char(o,66481).
+char(3,66482).
+char(3,66483).
+char(1,66484).
+char(c,66485).
+char(c,66486).
+char(p,66487).
+char(o,66488).
+char(o,66489).
+char(m,66490).
+char(5,66491).
+char(3,66492).
+char(8,66493).
+char(m,66494).
+char(o,66495).
+char(p,66496).
+char(8,66497).
+char(5,66498).
+char(8,66499).
+char(2,66500).
+char(m,66501).
+char(4,66502).
+char(3,66503).
+char(6,66504).
+char(c,66505).
+char(p,66506).
+char(4,66507).
+char(9,66508).
+char(3,66509).
+char(p,66510).
+char(o,66511).
+char(m,66512).
+char(3,66513).
+char(0,66514).
+char(8,66515).
+char(c,66516).
+char(m,66517).
+char(1,66518).
+char(2,66519).
+char(9,66520).
+char(5,66521).
+char(c,66522).
+char(c,66523).
+char(m,66524).
+char(1,66525).
+char(5,66526).
+char(4,66527).
+char(9,66528).
+char(p,66529).
+char(o,66530).
+char(p,66531).
+char(3,66532).
+char(0,66533).
+char(3,66534).
+char(1,66535).
+char(m,66536).
+char(o,66537).
+char(m,66538).
+char(o,66539).
+char(1,66540).
+char(3,66541).
+char(0,66542).
+char(5,66543).
+char(m,66544).
+char(o,66545).
+char(m,66546).
+char(8,66547).
+char(9,66548).
+char(4,66549).
+char(0,66550).
+char(m,66551).
+char(2,66552).
+char(0,66553).
+char(0,66554).
+char(8,66555).
+char(c,66556).
+char(c,66557).
+char(c,66558).
+char(m,66559).
+char(o,66560).
+char(p,66561).
+char(4,66562).
+char(4,66563).
+char(4,66564).
+char(p,66565).
+char(o,66566).
+char(8,66567).
+char(7,66568).
+char(9,66569).
+char(2,66570).
+char(p,66571).
+char(o,66572).
+char(p,66573).
+char(o,66574).
+char(2,66575).
+char(2,66576).
+char(1,66577).
+char(8,66578).
+char(p,66579).
+char(o,66580).
+char(p,66581).
+char(o,66582).
+char(m,66583).
+char(4,66584).
+char(0,66585).
+char(6,66586).
+char(0,66587).
+char(p,66588).
+char(o,66589).
+char(o,66590).
+char(4,66591).
+char(4,66592).
+char(4,66593).
+char(8,66594).
+char(c,66595).
+char(c,66596).
+char(c,66597).
+char(p,66598).
+char(o,66599).
+char(p,66600).
+char(3,66601).
+char(2,66602).
+char(6,66603).
+char(3,66604).
+char(c,66605).
+char(c,66606).
+char(p,66607).
+char(o,66608).
+char(o,66609).
+char(m,66610).
+char(5,66611).
+char(8,66612).
+char(1,66613).
+char(9,66614).
+char(m,66615).
+char(o,66616).
+char(p,66617).
+char(7,66618).
+char(7,66619).
+char(3,66620).
+char(3,66621).
+char(m,66622).
+char(o,66623).
+char(m,66624).
+char(o,66625).
+char(o,66626).
+char(m,66627).
+char(6,66628).
+char(7,66629).
+char(9,66630).
+char(7,66631).
+char(c,66632).
+char(m,66633).
+char(o,66634).
+char(m,66635).
+char(o,66636).
+char(m,66637).
+char(9,66638).
+char(0,66639).
+char(4,66640).
+char(2,66641).
+char(p,66642).
+char(2,66643).
+char(2,66644).
+char(5,66645).
+char(3,66646).
+char(p,66647).
+char(2,66648).
+char(4,66649).
+char(4,66650).
+char(c,66651).
+char(m,66652).
+char(o,66653).
+char(p,66654).
+char(4,66655).
+char(5,66656).
+char(2,66657).
+char(5,66658).
+char(c,66659).
+char(p,66660).
+char(7,66661).
+char(8,66662).
+char(3,66663).
+char(1,66664).
+char(c,66665).
+char(c,66666).
+char(p,66667).
+char(1,66668).
+char(7,66669).
+char(8,66670).
+char(8,66671).
+char(c,66672).
+char(c,66673).
+char(p,66674).
+char(o,66675).
+char(p,66676).
+char(o,66677).
+char(p,66678).
+char(4,66679).
+char(3,66680).
+char(8,66681).
+char(7,66682).
+char(c,66683).
+char(m,66684).
+char(8,66685).
+char(1,66686).
+char(8,66687).
+char(5,66688).
+char(m,66689).
+char(o,66690).
+char(p,66691).
+char(3,66692).
+char(5,66693).
+char(4,66694).
+char(c,66695).
+char(c,66696).
+char(p,66697).
+char(o,66698).
+char(m,66699).
+char(8,66700).
+char(2,66701).
+char(3,66702).
+char(3,66703).
+char(c,66704).
+char(c,66705).
+char(c,66706).
+char(p,66707).
+char(4,66708).
+char(3,66709).
+char(1,66710).
+char(0,66711).
+char(m,66712).
+char(o,66713).
+char(p,66714).
+char(o,66715).
+char(p,66716).
+char(o,66717).
+char(p,66718).
+char(7,66719).
+char(2,66720).
+char(9,66721).
+char(7,66722).
+char(c,66723).
+char(m,66724).
+char(2,66725).
+char(5,66726).
+char(5,66727).
+char(m,66728).
+char(8,66729).
+char(4,66730).
+char(3,66731).
+char(7,66732).
+char(p,66733).
+char(5,66734).
+char(2,66735).
+char(5,66736).
+char(9,66737).
+char(c,66738).
+char(p,66739).
+char(4,66740).
+char(3,66741).
+char(4,66742).
+char(8,66743).
+char(c,66744).
+char(c,66745).
+char(m,66746).
+char(8,66747).
+char(5,66748).
+char(8,66749).
+char(1,66750).
+char(p,66751).
+char(5,66752).
+char(3,66753).
+char(8,66754).
+char(7,66755).
+char(c,66756).
+char(c,66757).
+char(p,66758).
+char(4,66759).
+char(8,66760).
+char(9,66761).
+char(2,66762).
+char(m,66763).
+char(o,66764).
+char(p,66765).
+char(o,66766).
+char(p,66767).
+char(o,66768).
+char(7,66769).
+char(5,66770).
+char(7,66771).
+char(5,66772).
+char(c,66773).
+char(c,66774).
+char(c,66775).
+char(c,66776).
+char(c,66777).
+char(c,66778).
+char(c,66779).
+char(c,66780).
+char(c,66781).
+char(c,66782).
+char(c,66783).
+char(c,66784).
+char(m,66785).
+char(6,66786).
+char(8,66787).
+char(7,66788).
+char(4,66789).
+char(c,66790).
+char(m,66791).
+char(o,66792).
+char(o,66793).
+char(3,66794).
+char(0,66795).
+char(3,66796).
+char(8,66797).
+char(m,66798).
+char(o,66799).
+char(o,66800).
+char(p,66801).
+char(o,66802).
+char(p,66803).
+char(o,66804).
+char(m,66805).
+char(5,66806).
+char(1,66807).
+char(1,66808).
+char(p,66809).
+char(5,66810).
+char(9,66811).
+char(0,66812).
+char(0,66813).
+char(m,66814).
+char(3,66815).
+char(3,66816).
+char(1,66817).
+char(8,66818).
+char(m,66819).
+char(1,66820).
+char(4,66821).
+char(3,66822).
+char(2,66823).
+char(c,66824).
+char(m,66825).
+char(o,66826).
+char(p,66827).
+char(o,66828).
+char(m,66829).
+char(9,66830).
+char(8,66831).
+char(3,66832).
+char(9,66833).
+char(c,66834).
+char(p,66835).
+char(o,66836).
+char(m,66837).
+char(o,66838).
+char(1,66839).
+char(6,66840).
+char(1,66841).
+char(5,66842).
+char(c,66843).
+char(m,66844).
+char(o,66845).
+char(p,66846).
+char(7,66847).
+char(6,66848).
+char(9,66849).
+char(4,66850).
+char(p,66851).
+char(o,66852).
+char(p,66853).
+char(o,66854).
+char(o,66855).
+char(p,66856).
+char(o,66857).
+char(p,66858).
+char(6,66859).
+char(9,66860).
+char(2,66861).
+char(0,66862).
+char(c,66863).
+char(p,66864).
+char(o,66865).
+char(1,66866).
+char(7,66867).
+char(8,66868).
+char(1,66869).
+char(c,66870).
+char(p,66871).
+char(o,66872).
+char(2,66873).
+char(5,66874).
+char(3,66875).
+char(3,66876).
+char(m,66877).
+char(o,66878).
+char(o,66879).
+char(p,66880).
+char(o,66881).
+char(4,66882).
+char(8,66883).
+char(4,66884).
+char(5,66885).
+char(c,66886).
+char(c,66887).
+char(p,66888).
+char(o,66889).
+char(m,66890).
+char(o,66891).
+char(o,66892).
+char(m,66893).
+char(o,66894).
+char(o,66895).
+char(p,66896).
+char(2,66897).
+char(2,66898).
+char(7,66899).
+char(5,66900).
+char(p,66901).
+char(8,66902).
+char(1,66903).
+char(8,66904).
+char(7,66905).
+char(c,66906).
+char(c,66907).
+char(m,66908).
+char(o,66909).
+char(m,66910).
+char(o,66911).
+char(o,66912).
+char(m,66913).
+char(1,66914).
+char(2,66915).
+char(6,66916).
+char(2,66917).
+char(m,66918).
+char(o,66919).
+char(p,66920).
+char(6,66921).
+char(6,66922).
+char(5,66923).
+char(5,66924).
+char(p,66925).
+char(1,66926).
+char(3,66927).
+char(c,66928).
+char(c,66929).
+char(c,66930).
+char(p,66931).
+char(5,66932).
+char(3,66933).
+char(6,66934).
+char(3,66935).
+char(c,66936).
+char(c,66937).
+char(c,66938).
+char(m,66939).
+char(7,66940).
+char(9,66941).
+char(0,66942).
+char(8,66943).
+char(c,66944).
+char(p,66945).
+char(6,66946).
+char(8,66947).
+char(2,66948).
+char(5,66949).
+char(c,66950).
+char(p,66951).
+char(1,66952).
+char(1,66953).
+char(1,66954).
+char(5,66955).
+char(m,66956).
+char(4,66957).
+char(7,66958).
+char(9,66959).
+char(1,66960).
+char(c,66961).
+char(c,66962).
+char(m,66963).
+char(o,66964).
+char(p,66965).
+char(o,66966).
+char(p,66967).
+char(6,66968).
+char(8,66969).
+char(4,66970).
+char(7,66971).
+char(c,66972).
+char(p,66973).
+char(2,66974).
+char(1,66975).
+char(2,66976).
+char(2,66977).
+char(c,66978).
+char(c,66979).
+char(m,66980).
+char(o,66981).
+char(m,66982).
+char(3,66983).
+char(0,66984).
+char(4,66985).
+char(9,66986).
+char(p,66987).
+char(o,66988).
+char(p,66989).
+char(o,66990).
+char(m,66991).
+char(o,66992).
+char(m,66993).
+char(o,66994).
+char(1,66995).
+char(6,66996).
+char(0,66997).
+char(5,66998).
+char(p,66999).
+char(o,67000).
+char(4,67001).
+char(9,67002).
+char(8,67003).
+char(0,67004).
+char(p,67005).
+char(o,67006).
+char(3,67007).
+char(6,67008).
+char(6,67009).
+char(1,67010).
+char(p,67011).
+char(8,67012).
+char(9,67013).
+char(4,67014).
+char(8,67015).
+char(c,67016).
+char(m,67017).
+char(o,67018).
+char(m,67019).
+char(o,67020).
+char(o,67021).
+char(p,67022).
+char(o,67023).
+char(m,67024).
+char(7,67025).
+char(8,67026).
+char(8,67027).
+char(2,67028).
+char(c,67029).
+char(m,67030).
+char(o,67031).
+char(p,67032).
+char(o,67033).
+char(p,67034).
+char(o,67035).
+char(m,67036).
+char(9,67037).
+char(5,67038).
+char(9,67039).
+char(7,67040).
+char(c,67041).
+char(m,67042).
+char(o,67043).
+char(o,67044).
+char(p,67045).
+char(o,67046).
+char(p,67047).
+char(o,67048).
+char(5,67049).
+char(6,67050).
+char(1,67051).
+char(9,67052).
+char(c,67053).
+char(c,67054).
+char(c,67055).
+char(m,67056).
+char(4,67057).
+char(3,67058).
+char(9,67059).
+char(1,67060).
+char(m,67061).
+char(2,67062).
+char(6,67063).
+char(4,67064).
+char(7,67065).
+char(m,67066).
+char(o,67067).
+char(p,67068).
+char(o,67069).
+char(o,67070).
+char(m,67071).
+char(o,67072).
+char(p,67073).
+char(5,67074).
+char(5,67075).
+char(0,67076).
+char(2,67077).
+char(c,67078).
+char(c,67079).
+char(c,67080).
+char(c,67081).
+char(m,67082).
+char(o,67083).
+char(9,67084).
+char(7,67085).
+char(2,67086).
+char(4,67087).
+char(c,67088).
+char(p,67089).
+char(1,67090).
+char(9,67091).
+char(3,67092).
+char(6,67093).
+char(c,67094).
+char(c,67095).
+char(c,67096).
+char(c,67097).
+char(c,67098).
+char(c,67099).
+char(c,67100).
+char(c,67101).
+char(c,67102).
+char(m,67103).
+char(o,67104).
+char(m,67105).
+char(o,67106).
+char(p,67107).
+char(o,67108).
+char(o,67109).
+char(p,67110).
+char(o,67111).
+char(p,67112).
+char(8,67113).
+char(3,67114).
+char(0,67115).
+char(2,67116).
+char(c,67117).
+char(m,67118).
+char(o,67119).
+char(o,67120).
+char(6,67121).
+char(8,67122).
+char(8,67123).
+char(5,67124).
+char(p,67125).
+char(8,67126).
+char(6,67127).
+char(8,67128).
+char(5,67129).
+char(c,67130).
+char(p,67131).
+char(2,67132).
+char(7,67133).
+char(7,67134).
+char(5,67135).
+char(c,67136).
+char(p,67137).
+char(1,67138).
+char(9,67139).
+char(8,67140).
+char(4,67141).
+char(m,67142).
+char(7,67143).
+char(6,67144).
+char(9,67145).
+char(3,67146).
+char(m,67147).
+char(o,67148).
+char(m,67149).
+char(2,67150).
+char(2,67151).
+char(4,67152).
+char(7,67153).
+char(m,67154).
+char(3,67155).
+char(7,67156).
+char(4,67157).
+char(1,67158).
+char(m,67159).
+char(7,67160).
+char(8,67161).
+char(7,67162).
+char(0,67163).
+char(p,67164).
+char(3,67165).
+char(3,67166).
+char(6,67167).
+char(1,67168).
+char(m,67169).
+char(o,67170).
+char(m,67171).
+char(9,67172).
+char(8,67173).
+char(2,67174).
+char(0,67175).
+char(c,67176).
+char(c,67177).
+char(c,67178).
+char(p,67179).
+char(o,67180).
+char(o,67181).
+char(6,67182).
+char(5,67183).
+char(2,67184).
+char(2,67185).
+char(p,67186).
+char(o,67187).
+char(p,67188).
+char(o,67189).
+char(m,67190).
+char(o,67191).
+char(4,67192).
+char(4,67193).
+char(3,67194).
+char(0,67195).
+char(c,67196).
+char(p,67197).
+char(3,67198).
+char(2,67199).
+char(4,67200).
+char(7,67201).
+char(c,67202).
+char(p,67203).
+char(5,67204).
+char(8,67205).
+char(8,67206).
+char(4,67207).
+char(m,67208).
+char(9,67209).
+char(4,67210).
+char(6,67211).
+char(7,67212).
+char(m,67213).
+char(o,67214).
+char(p,67215).
+char(o,67216).
+char(p,67217).
+char(o,67218).
+char(1,67219).
+char(8,67220).
+char(4,67221).
+char(7,67222).
+char(c,67223).
+char(c,67224).
+char(c,67225).
+char(c,67226).
+char(p,67227).
+char(3,67228).
+char(2,67229).
+char(3,67230).
+char(4,67231).
+char(m,67232).
+char(3,67233).
+char(5,67234).
+char(6,67235).
+char(5,67236).
+char(m,67237).
+char(6,67238).
+char(4,67239).
+char(6,67240).
+char(8,67241).
+char(c,67242).
+char(m,67243).
+char(2,67244).
+char(1,67245).
+char(8,67246).
+char(8,67247).
+char(c,67248).
+char(m,67249).
+char(6,67250).
+char(6,67251).
+char(0,67252).
+char(0,67253).
+char(c,67254).
+char(c,67255).
+char(c,67256).
+char(c,67257).
+char(c,67258).
+char(c,67259).
+char(c,67260).
+char(c,67261).
+char(c,67262).
+char(c,67263).
+char(c,67264).
+char(m,67265).
+char(o,67266).
+char(p,67267).
+char(o,67268).
+char(o,67269).
+char(2,67270).
+char(6,67271).
+char(3,67272).
+char(3,67273).
+char(c,67274).
+char(p,67275).
+char(9,67276).
+char(2,67277).
+char(7,67278).
+char(0,67279).
+char(c,67280).
+char(c,67281).
+char(c,67282).
+char(c,67283).
+char(c,67284).
+char(m,67285).
+char(o,67286).
+char(2,67287).
+char(8,67288).
+char(8,67289).
+char(0,67290).
+char(p,67291).
+char(7,67292).
+char(4,67293).
+char(2,67294).
+char(5,67295).
+char(c,67296).
+char(c,67297).
+char(m,67298).
+char(8,67299).
+char(1,67300).
+char(0,67301).
+char(9,67302).
+char(c,67303).
+char(m,67304).
+char(o,67305).
+char(o,67306).
+char(p,67307).
+char(o,67308).
+char(p,67309).
+char(o,67310).
+char(1,67311).
+char(7,67312).
+char(8,67313).
+char(3,67314).
+char(m,67315).
+char(8,67316).
+char(1,67317).
+char(0,67318).
+char(5,67319).
+char(c,67320).
+char(m,67321).
+char(6,67322).
+char(1,67323).
+char(8,67324).
+char(0,67325).
+char(m,67326).
+char(8,67327).
+char(1,67328).
+char(2,67329).
+char(1,67330).
+char(c,67331).
+char(c,67332).
+char(c,67333).
+char(p,67334).
+char(2,67335).
+char(3,67336).
+char(6,67337).
+char(0,67338).
+char(c,67339).
+char(c,67340).
+char(c,67341).
+char(c,67342).
+char(c,67343).
+char(m,67344).
+char(3,67345).
+char(6,67346).
+char(4,67347).
+char(1,67348).
+char(c,67349).
+char(p,67350).
+char(o,67351).
+char(m,67352).
+char(1,67353).
+char(0,67354).
+char(7,67355).
+char(8,67356).
+char(p,67357).
+char(1,67358).
+char(4,67359).
+char(3,67360).
+char(0,67361).
+char(m,67362).
+char(3,67363).
+char(4,67364).
+char(9,67365).
+char(1,67366).
+char(m,67367).
+char(6,67368).
+char(2,67369).
+char(3,67370).
+char(6,67371).
+char(p,67372).
+char(1,67373).
+char(7,67374).
+char(7,67375).
+char(4,67376).
+char(m,67377).
+char(5,67378).
+char(2,67379).
+char(2,67380).
+char(2,67381).
+char(p,67382).
+char(o,67383).
+char(m,67384).
+char(o,67385).
+char(m,67386).
+char(1,67387).
+char(3,67388).
+char(3,67389).
+char(7,67390).
+char(c,67391).
+char(c,67392).
+char(c,67393).
+char(m,67394).
+char(4,67395).
+char(2,67396).
+char(8,67397).
+char(9,67398).
+char(c,67399).
+char(c,67400).
+char(m,67401).
+char(1,67402).
+char(2,67403).
+char(9,67404).
+char(5,67405).
+char(c,67406).
+char(m,67407).
+char(6,67408).
+char(9,67409).
+char(8,67410).
+char(8,67411).
+char(c,67412).
+char(m,67413).
+char(o,67414).
+char(p,67415).
+char(1,67416).
+char(5,67417).
+char(4,67418).
+char(5,67419).
+char(c,67420).
+char(p,67421).
+char(7,67422).
+char(7,67423).
+char(1,67424).
+char(7,67425).
+char(c,67426).
+char(m,67427).
+char(2,67428).
+char(9,67429).
+char(3,67430).
+char(5,67431).
+char(c,67432).
+char(c,67433).
+char(c,67434).
+char(c,67435).
+char(c,67436).
+char(c,67437).
+char(m,67438).
+char(3,67439).
+char(3,67440).
+char(6,67441).
+char(1,67442).
+char(m,67443).
+char(o,67444).
+char(p,67445).
+char(o,67446).
+char(o,67447).
+char(p,67448).
+char(o,67449).
+char(p,67450).
+char(o,67451).
+char(3,67452).
+char(1,67453).
+char(4,67454).
+char(2,67455).
+char(c,67456).
+char(p,67457).
+char(o,67458).
+char(p,67459).
+char(o,67460).
+char(m,67461).
+char(o,67462).
+char(1,67463).
+char(6,67464).
+char(2,67465).
+char(0,67466).
+char(p,67467).
+char(o,67468).
+char(m,67469).
+char(1,67470).
+char(9,67471).
+char(c,67472).
+char(p,67473).
+char(9,67474).
+char(5,67475).
+char(6,67476).
+char(3,67477).
+char(c,67478).
+char(c,67479).
+char(c,67480).
+char(c,67481).
+char(m,67482).
+char(o,67483).
+char(4,67484).
+char(1,67485).
+char(9,67486).
+char(8,67487).
+char(p,67488).
+char(o,67489).
+char(m,67490).
+char(2,67491).
+char(1,67492).
+char(3,67493).
+char(0,67494).
+char(c,67495).
+char(c,67496).
+char(m,67497).
+char(5,67498).
+char(4,67499).
+char(6,67500).
+char(4,67501).
+char(c,67502).
+char(c,67503).
+char(c,67504).
+char(c,67505).
+char(m,67506).
+char(o,67507).
+char(1,67508).
+char(0,67509).
+char(7,67510).
+char(4,67511).
+char(c,67512).
+char(m,67513).
+char(o,67514).
+char(p,67515).
+char(4,67516).
+char(6,67517).
+char(7,67518).
+char(6,67519).
+char(m,67520).
+char(o,67521).
+char(o,67522).
+char(m,67523).
+char(o,67524).
+char(m,67525).
+char(o,67526).
+char(p,67527).
+char(2,67528).
+char(0,67529).
+char(0,67530).
+char(1,67531).
+char(c,67532).
+char(p,67533).
+char(8,67534).
+char(1,67535).
+char(1,67536).
+char(7,67537).
+char(m,67538).
+char(6,67539).
+char(3,67540).
+char(3,67541).
+char(8,67542).
+char(m,67543).
+char(o,67544).
+char(7,67545).
+char(0,67546).
+char(4,67547).
+char(5,67548).
+char(c,67549).
+char(c,67550).
+char(c,67551).
+char(p,67552).
+char(o,67553).
+char(7,67554).
+char(1,67555).
+char(6,67556).
+char(p,67557).
+char(o,67558).
+char(m,67559).
+char(o,67560).
+char(m,67561).
+char(2,67562).
+char(2,67563).
+char(2,67564).
+char(6,67565).
+char(p,67566).
+char(6,67567).
+char(9,67568).
+char(4,67569).
+char(7,67570).
+char(c,67571).
+char(c,67572).
+char(c,67573).
+char(c,67574).
+char(m,67575).
+char(o,67576).
+char(m,67577).
+char(o,67578).
+char(p,67579).
+char(4,67580).
+char(9,67581).
+char(6,67582).
+char(1,67583).
+char(p,67584).
+char(4,67585).
+char(9,67586).
+char(0,67587).
+char(m,67588).
+char(o,67589).
+char(4,67590).
+char(3,67591).
+char(0,67592).
+char(5,67593).
+char(m,67594).
+char(4,67595).
+char(4,67596).
+char(4,67597).
+char(2,67598).
+char(c,67599).
+char(c,67600).
+char(c,67601).
+char(c,67602).
+char(c,67603).
+char(m,67604).
+char(o,67605).
+char(p,67606).
+char(o,67607).
+char(m,67608).
+char(o,67609).
+char(m,67610).
+char(9,67611).
+char(0,67612).
+char(8,67613).
+char(c,67614).
+char(m,67615).
+char(o,67616).
+char(p,67617).
+char(7,67618).
+char(6,67619).
+char(5,67620).
+char(8,67621).
+char(p,67622).
+char(o,67623).
+char(p,67624).
+char(5,67625).
+char(1,67626).
+char(2,67627).
+char(2,67628).
+char(p,67629).
+char(5,67630).
+char(7,67631).
+char(5,67632).
+char(1,67633).
+char(c,67634).
+char(c,67635).
+char(c,67636).
+char(c,67637).
+char(c,67638).
+char(c,67639).
+char(p,67640).
+char(o,67641).
+char(p,67642).
+char(o,67643).
+char(o,67644).
+char(8,67645).
+char(6,67646).
+char(3,67647).
+char(4,67648).
+char(p,67649).
+char(o,67650).
+char(m,67651).
+char(5,67652).
+char(7,67653).
+char(2,67654).
+char(2,67655).
+char(c,67656).
+char(m,67657).
+char(o,67658).
+char(m,67659).
+char(8,67660).
+char(8,67661).
+char(9,67662).
+char(6,67663).
+char(p,67664).
+char(5,67665).
+char(0,67666).
+char(2,67667).
+char(7,67668).
+char(c,67669).
+char(m,67670).
+char(o,67671).
+char(o,67672).
+char(o,67673).
+char(1,67674).
+char(4,67675).
+char(4,67676).
+char(7,67677).
+char(c,67678).
+char(m,67679).
+char(o,67680).
+char(p,67681).
+char(o,67682).
+char(m,67683).
+char(9,67684).
+char(5,67685).
+char(6,67686).
+char(6,67687).
+char(m,67688).
+char(o,67689).
+char(8,67690).
+char(8,67691).
+char(9,67692).
+char(6,67693).
+char(m,67694).
+char(8,67695).
+char(1,67696).
+char(4,67697).
+char(9,67698).
+char(c,67699).
+char(c,67700).
+char(c,67701).
+char(c,67702).
+char(m,67703).
+char(4,67704).
+char(2,67705).
+char(8,67706).
+char(1,67707).
+char(m,67708).
+char(3,67709).
+char(4,67710).
+char(1,67711).
+char(7,67712).
+char(m,67713).
+char(8,67714).
+char(9,67715).
+char(3,67716).
+char(7,67717).
+char(c,67718).
+char(c,67719).
+char(p,67720).
+char(2,67721).
+char(5,67722).
+char(5,67723).
+char(6,67724).
+char(c,67725).
+char(c,67726).
+char(p,67727).
+char(6,67728).
+char(5,67729).
+char(9,67730).
+char(1,67731).
+char(p,67732).
+char(o,67733).
+char(o,67734).
+char(p,67735).
+char(o,67736).
+char(p,67737).
+char(6,67738).
+char(3,67739).
+char(8,67740).
+char(3,67741).
+char(p,67742).
+char(1,67743).
+char(8,67744).
+char(5,67745).
+char(0,67746).
+char(p,67747).
+char(o,67748).
+char(p,67749).
+char(8,67750).
+char(3,67751).
+char(7,67752).
+char(p,67753).
+char(o,67754).
+char(6,67755).
+char(9,67756).
+char(7,67757).
+char(7,67758).
+char(m,67759).
+char(4,67760).
+char(3,67761).
+char(0,67762).
+char(3,67763).
+char(p,67764).
+char(1,67765).
+char(3,67766).
+char(1,67767).
+char(9,67768).
+char(c,67769).
+char(p,67770).
+char(o,67771).
+char(m,67772).
+char(o,67773).
+char(m,67774).
+char(o,67775).
+char(9,67776).
+char(7,67777).
+char(7,67778).
+char(0,67779).
+char(m,67780).
+char(o,67781).
+char(p,67782).
+char(9,67783).
+char(0,67784).
+char(7,67785).
+char(1,67786).
+char(c,67787).
+char(c,67788).
+char(c,67789).
+char(c,67790).
+char(m,67791).
+char(o,67792).
+char(p,67793).
+char(o,67794).
+char(3,67795).
+char(8,67796).
+char(7,67797).
+char(5,67798).
+char(c,67799).
+char(p,67800).
+char(2,67801).
+char(2,67802).
+char(8,67803).
+char(1,67804).
+char(m,67805).
+char(8,67806).
+char(6,67807).
+char(3,67808).
+char(c,67809).
+char(c,67810).
+char(c,67811).
+char(c,67812).
+char(p,67813).
+char(o,67814).
+char(p,67815).
+char(1,67816).
+char(6,67817).
+char(9,67818).
+char(c,67819).
+char(m,67820).
+char(6,67821).
+char(6,67822).
+char(6,67823).
+char(5,67824).
+char(c,67825).
+char(c,67826).
+char(c,67827).
+char(p,67828).
+char(o,67829).
+char(p,67830).
+char(o,67831).
+char(7,67832).
+char(5,67833).
+char(4,67834).
+char(7,67835).
+char(m,67836).
+char(7,67837).
+char(0,67838).
+char(1,67839).
+char(p,67840).
+char(7,67841).
+char(3,67842).
+char(8,67843).
+char(4,67844).
+char(c,67845).
+char(m,67846).
+char(o,67847).
+char(p,67848).
+char(o,67849).
+char(p,67850).
+char(o,67851).
+char(o,67852).
+char(5,67853).
+char(6,67854).
+char(8,67855).
+char(2,67856).
+char(m,67857).
+char(5,67858).
+char(8,67859).
+char(0,67860).
+char(1,67861).
+char(m,67862).
+char(o,67863).
+char(5,67864).
+char(7,67865).
+char(0,67866).
+char(7,67867).
+char(c,67868).
+char(c,67869).
+char(c,67870).
+char(c,67871).
+char(c,67872).
+char(m,67873).
+char(3,67874).
+char(1,67875).
+char(1,67876).
+char(8,67877).
+char(c,67878).
+char(m,67879).
+char(7,67880).
+char(6,67881).
+char(3,67882).
+char(0,67883).
+char(c,67884).
+char(c,67885).
+char(p,67886).
+char(o,67887).
+char(p,67888).
+char(o,67889).
+char(m,67890).
+char(7,67891).
+char(2,67892).
+char(3,67893).
+char(7,67894).
+char(c,67895).
+char(c,67896).
+char(c,67897).
+char(c,67898).
+char(m,67899).
+char(o,67900).
+char(p,67901).
+char(9,67902).
+char(0,67903).
+char(8,67904).
+char(8,67905).
+char(c,67906).
+char(p,67907).
+char(2,67908).
+char(0,67909).
+char(0,67910).
+char(9,67911).
+char(c,67912).
+char(p,67913).
+char(o,67914).
+char(p,67915).
+char(6,67916).
+char(1,67917).
+char(8,67918).
+char(m,67919).
+char(2,67920).
+char(8,67921).
+char(1,67922).
+char(0,67923).
+char(p,67924).
+char(2,67925).
+char(6,67926).
+char(3,67927).
+char(c,67928).
+char(m,67929).
+char(2,67930).
+char(6,67931).
+char(0,67932).
+char(4,67933).
+char(c,67934).
+char(c,67935).
+char(c,67936).
+char(c,67937).
+char(c,67938).
+char(m,67939).
+char(8,67940).
+char(3,67941).
+char(9,67942).
+char(2,67943).
+char(p,67944).
+char(o,67945).
+char(p,67946).
+char(6,67947).
+char(4,67948).
+char(4,67949).
+char(7,67950).
+char(c,67951).
+char(m,67952).
+char(8,67953).
+char(8,67954).
+char(9,67955).
+char(1,67956).
+char(m,67957).
+char(6,67958).
+char(1,67959).
+char(4,67960).
+char(0,67961).
+char(m,67962).
+char(o,67963).
+char(o,67964).
+char(m,67965).
+char(1,67966).
+char(4,67967).
+char(8,67968).
+char(1,67969).
+char(c,67970).
+char(c,67971).
+char(p,67972).
+char(o,67973).
+char(o,67974).
+char(p,67975).
+char(7,67976).
+char(7,67977).
+char(7,67978).
+char(8,67979).
+char(m,67980).
+char(9,67981).
+char(5,67982).
+char(1,67983).
+char(1,67984).
+char(c,67985).
+char(m,67986).
+char(o,67987).
+char(8,67988).
+char(2,67989).
+char(6,67990).
+char(1,67991).
+char(c,67992).
+char(c,67993).
+char(c,67994).
+char(c,67995).
+char(p,67996).
+char(o,67997).
+char(m,67998).
+char(o,67999).
+char(p,68000).
+char(6,68001).
+char(2,68002).
+char(0,68003).
+char(1,68004).
+char(c,68005).
+char(m,68006).
+char(o,68007).
+char(3,68008).
+char(7,68009).
+char(2,68010).
+char(m,68011).
+char(o,68012).
+char(p,68013).
+char(8,68014).
+char(0,68015).
+char(8,68016).
+char(2,68017).
+char(m,68018).
+char(o,68019).
+char(p,68020).
+char(7,68021).
+char(4,68022).
+char(7,68023).
+char(1,68024).
+char(m,68025).
+char(o,68026).
+char(o,68027).
+char(o,68028).
+char(8,68029).
+char(3,68030).
+char(6,68031).
+char(4,68032).
+char(c,68033).
+char(p,68034).
+char(7,68035).
+char(9,68036).
+char(2,68037).
+char(0,68038).
+char(m,68039).
+char(1,68040).
+char(0,68041).
+char(0,68042).
+char(6,68043).
+char(c,68044).
+char(p,68045).
+char(6,68046).
+char(4,68047).
+char(1,68048).
+char(8,68049).
+char(c,68050).
+char(p,68051).
+char(9,68052).
+char(2,68053).
+char(9,68054).
+char(2,68055).
+char(p,68056).
+char(4,68057).
+char(1,68058).
+char(2,68059).
+char(5,68060).
+char(c,68061).
+char(p,68062).
+char(o,68063).
+char(m,68064).
+char(o,68065).
+char(p,68066).
+char(4,68067).
+char(1,68068).
+char(3,68069).
+char(1,68070).
+char(m,68071).
+char(8,68072).
+char(8,68073).
+char(6,68074).
+char(6,68075).
+char(m,68076).
+char(1,68077).
+char(9,68078).
+char(1,68079).
+char(4,68080).
+char(c,68081).
+char(p,68082).
+char(1,68083).
+char(6,68084).
+char(0,68085).
+char(1,68086).
+char(p,68087).
+char(7,68088).
+char(5,68089).
+char(7,68090).
+char(4,68091).
+char(p,68092).
+char(o,68093).
+char(p,68094).
+char(o,68095).
+char(8,68096).
+char(7,68097).
+char(3,68098).
+char(5,68099).
+char(c,68100).
+char(c,68101).
+char(c,68102).
+char(c,68103).
+char(p,68104).
+char(o,68105).
+char(o,68106).
+char(m,68107).
+char(o,68108).
+char(o,68109).
+char(m,68110).
+char(5,68111).
+char(6,68112).
+char(9,68113).
+char(2,68114).
+char(p,68115).
+char(9,68116).
+char(2,68117).
+char(7,68118).
+char(4,68119).
+char(c,68120).
+char(m,68121).
+char(o,68122).
+char(m,68123).
+char(2,68124).
+char(9,68125).
+char(9,68126).
+char(5,68127).
+char(p,68128).
+char(o,68129).
+char(p,68130).
+char(o,68131).
+char(p,68132).
+char(8,68133).
+char(9,68134).
+char(4,68135).
+char(5,68136).
+char(c,68137).
+char(m,68138).
+char(7,68139).
+char(7,68140).
+char(0,68141).
+char(2,68142).
+char(c,68143).
+char(p,68144).
+char(o,68145).
+char(m,68146).
+char(4,68147).
+char(6,68148).
+char(3,68149).
+char(0,68150).
+char(c,68151).
+char(c,68152).
+char(m,68153).
+char(o,68154).
+char(o,68155).
+char(o,68156).
+char(p,68157).
+char(1,68158).
+char(5,68159).
+char(m,68160).
+char(4,68161).
+char(4,68162).
+char(5,68163).
+char(3,68164).
+char(c,68165).
+char(m,68166).
+char(4,68167).
+char(5,68168).
+char(6,68169).
+char(8,68170).
+char(c,68171).
+char(c,68172).
+char(c,68173).
+char(m,68174).
+char(9,68175).
+char(9,68176).
+char(2,68177).
+char(9,68178).
+char(c,68179).
+char(p,68180).
+char(3,68181).
+char(1,68182).
+char(8,68183).
+char(9,68184).
+char(p,68185).
+char(4,68186).
+char(0,68187).
+char(9,68188).
+char(1,68189).
+char(c,68190).
+char(c,68191).
+char(c,68192).
+char(c,68193).
+char(c,68194).
+char(p,68195).
+char(o,68196).
+char(p,68197).
+char(6,68198).
+char(7,68199).
+char(0,68200).
+char(8,68201).
+char(c,68202).
+char(m,68203).
+char(o,68204).
+char(p,68205).
+char(6,68206).
+char(1,68207).
+char(4,68208).
+char(5,68209).
+char(p,68210).
+char(7,68211).
+char(2,68212).
+char(7,68213).
+char(2,68214).
+char(c,68215).
+char(p,68216).
+char(3,68217).
+char(2,68218).
+char(3,68219).
+char(5,68220).
+char(c,68221).
+char(m,68222).
+char(9,68223).
+char(9,68224).
+char(8,68225).
+char(3,68226).
+char(c,68227).
+char(p,68228).
+char(o,68229).
+char(p,68230).
+char(5,68231).
+char(6,68232).
+char(4,68233).
+char(5,68234).
+char(p,68235).
+char(o,68236).
+char(3,68237).
+char(8,68238).
+char(8,68239).
+char(6,68240).
+char(c,68241).
+char(c,68242).
+char(p,68243).
+char(o,68244).
+char(p,68245).
+char(7,68246).
+char(7,68247).
+char(3,68248).
+char(6,68249).
+char(c,68250).
+char(p,68251).
+char(9,68252).
+char(4,68253).
+char(1,68254).
+char(0,68255).
+char(c,68256).
+char(p,68257).
+char(1,68258).
+char(1,68259).
+char(0,68260).
+char(2,68261).
+char(p,68262).
+char(o,68263).
+char(5,68264).
+char(2,68265).
+char(1,68266).
+char(1,68267).
+char(c,68268).
+char(c,68269).
+char(p,68270).
+char(o,68271).
+char(o,68272).
+char(m,68273).
+char(o,68274).
+char(o,68275).
+char(p,68276).
+char(o,68277).
+char(m,68278).
+char(o,68279).
+char(9,68280).
+char(5,68281).
+char(7,68282).
+char(5,68283).
+char(c,68284).
+char(c,68285).
+char(m,68286).
+char(3,68287).
+char(1,68288).
+char(2,68289).
+char(0,68290).
+char(p,68291).
+char(o,68292).
+char(o,68293).
+char(p,68294).
+char(o,68295).
+char(o,68296).
+char(m,68297).
+char(2,68298).
+char(1,68299).
+char(7,68300).
+char(1,68301).
+char(c,68302).
+char(p,68303).
+char(7,68304).
+char(9,68305).
+char(9,68306).
+char(9,68307).
+char(p,68308).
+char(o,68309).
+char(m,68310).
+char(3,68311).
+char(1,68312).
+char(4,68313).
+char(8,68314).
+char(c,68315).
+char(m,68316).
+char(7,68317).
+char(4,68318).
+char(5,68319).
+char(0,68320).
+char(c,68321).
+char(c,68322).
+char(c,68323).
+char(m,68324).
+char(o,68325).
+char(m,68326).
+char(o,68327).
+char(p,68328).
+char(o,68329).
+char(o,68330).
+char(o,68331).
+char(o,68332).
+char(4,68333).
+char(1,68334).
+char(4,68335).
+char(0,68336).
+char(m,68337).
+char(o,68338).
+char(p,68339).
+char(2,68340).
+char(4,68341).
+char(8,68342).
+char(9,68343).
+char(m,68344).
+char(3,68345).
+char(6,68346).
+char(9,68347).
+char(0,68348).
+char(c,68349).
+char(c,68350).
+char(m,68351).
+char(o,68352).
+char(m,68353).
+char(o,68354).
+char(m,68355).
+char(4,68356).
+char(6,68357).
+char(7,68358).
+char(4,68359).
+char(c,68360).
+char(p,68361).
+char(2,68362).
+char(4,68363).
+char(2,68364).
+char(c,68365).
+char(p,68366).
+char(o,68367).
+char(m,68368).
+char(2,68369).
+char(5,68370).
+char(4,68371).
+char(0,68372).
+char(c,68373).
+char(c,68374).
+char(c,68375).
+char(c,68376).
+char(c,68377).
+char(c,68378).
+char(m,68379).
+char(o,68380).
+char(p,68381).
+char(6,68382).
+char(0,68383).
+char(2,68384).
+char(4,68385).
+char(c,68386).
+char(m,68387).
+char(5,68388).
+char(9,68389).
+char(c,68390).
+char(m,68391).
+char(o,68392).
+char(p,68393).
+char(o,68394).
+char(m,68395).
+char(9,68396).
+char(6,68397).
+char(4,68398).
+char(8,68399).
+char(c,68400).
+char(c,68401).
+char(c,68402).
+char(m,68403).
+char(o,68404).
+char(m,68405).
+char(o,68406).
+char(o,68407).
+char(m,68408).
+char(8,68409).
+char(5,68410).
+char(0,68411).
+char(1,68412).
+char(c,68413).
+char(c,68414).
+char(c,68415).
+char(c,68416).
+char(p,68417).
+char(o,68418).
+char(m,68419).
+char(3,68420).
+char(8,68421).
+char(6,68422).
+char(3,68423).
+char(m,68424).
+char(o,68425).
+char(m,68426).
+char(4,68427).
+char(4,68428).
+char(3,68429).
+char(4,68430).
+char(c,68431).
+char(p,68432).
+char(o,68433).
+char(o,68434).
+char(o,68435).
+char(1,68436).
+char(9,68437).
+char(c,68438).
+char(m,68439).
+char(6,68440).
+char(7,68441).
+char(1,68442).
+char(5,68443).
+char(c,68444).
+char(m,68445).
+char(8,68446).
+char(5,68447).
+char(9,68448).
+char(1,68449).
+char(p,68450).
+char(o,68451).
+char(5,68452).
+char(5,68453).
+char(1,68454).
+char(c,68455).
+char(c,68456).
+char(c,68457).
+char(p,68458).
+char(o,68459).
+char(o,68460).
+char(p,68461).
+char(o,68462).
+char(m,68463).
+char(o,68464).
+char(m,68465).
+char(o,68466).
+char(p,68467).
+char(4,68468).
+char(9,68469).
+char(4,68470).
+char(0,68471).
+char(c,68472).
+char(c,68473).
+char(c,68474).
+char(c,68475).
+char(c,68476).
+char(m,68477).
+char(o,68478).
+char(o,68479).
+char(m,68480).
+char(4,68481).
+char(3,68482).
+char(7,68483).
+char(m,68484).
+char(o,68485).
+char(8,68486).
+char(8,68487).
+char(m,68488).
+char(o,68489).
+char(3,68490).
+char(3,68491).
+char(2,68492).
+char(0,68493).
+char(m,68494).
+char(3,68495).
+char(7,68496).
+char(3,68497).
+char(8,68498).
+char(m,68499).
+char(o,68500).
+char(m,68501).
+char(o,68502).
+char(o,68503).
+char(p,68504).
+char(7,68505).
+char(3,68506).
+char(8,68507).
+char(7,68508).
+char(c,68509).
+char(c,68510).
+char(p,68511).
+char(7,68512).
+char(4,68513).
+char(5,68514).
+char(6,68515).
+char(c,68516).
+char(c,68517).
+char(c,68518).
+char(p,68519).
+char(o,68520).
+char(p,68521).
+char(o,68522).
+char(p,68523).
+char(8,68524).
+char(1,68525).
+char(8,68526).
+char(1,68527).
+char(c,68528).
+char(c,68529).
+char(p,68530).
+char(3,68531).
+char(3,68532).
+char(4,68533).
+char(1,68534).
+char(c,68535).
+char(c,68536).
+char(c,68537).
+char(m,68538).
+char(o,68539).
+char(m,68540).
+char(o,68541).
+char(p,68542).
+char(o,68543).
+char(m,68544).
+char(o,68545).
+char(p,68546).
+char(3,68547).
+char(0,68548).
+char(0,68549).
+char(9,68550).
+char(m,68551).
+char(7,68552).
+char(4,68553).
+char(3,68554).
+char(7,68555).
+char(m,68556).
+char(o,68557).
+char(p,68558).
+char(7,68559).
+char(5,68560).
+char(1,68561).
+char(7,68562).
+char(c,68563).
+char(c,68564).
+char(c,68565).
+char(c,68566).
+char(c,68567).
+char(m,68568).
+char(2,68569).
+char(9,68570).
+char(3,68571).
+char(6,68572).
+char(m,68573).
+char(1,68574).
+char(8,68575).
+char(2,68576).
+char(7,68577).
+char(p,68578).
+char(o,68579).
+char(m,68580).
+char(2,68581).
+char(7,68582).
+char(2,68583).
+char(1,68584).
+char(m,68585).
+char(9,68586).
+char(4,68587).
+char(3,68588).
+char(7,68589).
+char(m,68590).
+char(o,68591).
+char(m,68592).
+char(o,68593).
+char(p,68594).
+char(5,68595).
+char(7,68596).
+char(9,68597).
+char(2,68598).
+char(c,68599).
+char(c,68600).
+char(m,68601).
+char(8,68602).
+char(8,68603).
+char(5,68604).
+char(3,68605).
+char(c,68606).
+char(p,68607).
+char(o,68608).
+char(o,68609).
+char(o,68610).
+char(m,68611).
+char(o,68612).
+char(m,68613).
+char(5,68614).
+char(6,68615).
+char(7,68616).
+char(9,68617).
+char(c,68618).
+char(m,68619).
+char(o,68620).
+char(p,68621).
+char(o,68622).
+char(m,68623).
+char(2,68624).
+char(9,68625).
+char(8,68626).
+char(3,68627).
+char(p,68628).
+char(5,68629).
+char(7,68630).
+char(3,68631).
+char(8,68632).
+char(c,68633).
+char(p,68634).
+char(1,68635).
+char(9,68636).
+char(4,68637).
+char(3,68638).
+char(c,68639).
+char(c,68640).
+char(c,68641).
+char(c,68642).
+char(c,68643).
+char(c,68644).
+char(m,68645).
+char(o,68646).
+char(o,68647).
+char(m,68648).
+char(5,68649).
+char(7,68650).
+char(5,68651).
+char(9,68652).
+char(p,68653).
+char(4,68654).
+char(7,68655).
+char(7,68656).
+char(5,68657).
+char(m,68658).
+char(o,68659).
+char(m,68660).
+char(o,68661).
+char(m,68662).
+char(o,68663).
+char(o,68664).
+char(m,68665).
+char(o,68666).
+char(m,68667).
+char(3,68668).
+char(4,68669).
+char(5,68670).
+char(8,68671).
+char(m,68672).
+char(o,68673).
+char(m,68674).
+char(o,68675).
+char(p,68676).
+char(o,68677).
+char(m,68678).
+char(o,68679).
+char(p,68680).
+char(o,68681).
+char(p,68682).
+char(6,68683).
+char(5,68684).
+char(7,68685).
+char(2,68686).
+char(c,68687).
+char(m,68688).
+char(o,68689).
+char(o,68690).
+char(p,68691).
+char(o,68692).
+char(p,68693).
+char(o,68694).
+char(p,68695).
+char(8,68696).
+char(3,68697).
+char(4,68698).
+char(1,68699).
+char(c,68700).
+char(p,68701).
+char(7,68702).
+char(8,68703).
+char(0,68704).
+char(7,68705).
+char(c,68706).
+char(p,68707).
+char(o,68708).
+char(m,68709).
+char(o,68710).
+char(8,68711).
+char(8,68712).
+char(4,68713).
+char(6,68714).
+char(p,68715).
+char(4,68716).
+char(0,68717).
+char(5,68718).
+char(3,68719).
+char(m,68720).
+char(5,68721).
+char(6,68722).
+char(3,68723).
+char(9,68724).
+char(c,68725).
+char(p,68726).
+char(9,68727).
+char(3,68728).
+char(3,68729).
+char(2,68730).
+char(p,68731).
+char(o,68732).
+char(m,68733).
+char(o,68734).
+char(m,68735).
+char(o,68736).
+char(m,68737).
+char(2,68738).
+char(8,68739).
+char(3,68740).
+char(2,68741).
+char(c,68742).
+char(c,68743).
+char(p,68744).
+char(6,68745).
+char(0,68746).
+char(3,68747).
+char(2,68748).
+char(p,68749).
+char(1,68750).
+char(7,68751).
+char(0,68752).
+char(9,68753).
+char(c,68754).
+char(p,68755).
+char(8,68756).
+char(3,68757).
+char(1,68758).
+char(7,68759).
+char(c,68760).
+char(c,68761).
+char(c,68762).
+char(c,68763).
+char(c,68764).
+char(c,68765).
+char(m,68766).
+char(o,68767).
+char(m,68768).
+char(o,68769).
+char(p,68770).
+char(o,68771).
+char(p,68772).
+char(o,68773).
+char(m,68774).
+char(3,68775).
+char(8,68776).
+char(9,68777).
+char(6,68778).
+char(p,68779).
+char(8,68780).
+char(6,68781).
+char(6,68782).
+char(6,68783).
+char(p,68784).
+char(o,68785).
+char(m,68786).
+char(6,68787).
+char(0,68788).
+char(1,68789).
+char(7,68790).
+char(c,68791).
+char(p,68792).
+char(3,68793).
+char(9,68794).
+char(2,68795).
+char(5,68796).
+char(c,68797).
+char(m,68798).
+char(o,68799).
+char(m,68800).
+char(8,68801).
+char(9,68802).
+char(5,68803).
+char(8,68804).
+char(m,68805).
+char(8,68806).
+char(8,68807).
+char(1,68808).
+char(7,68809).
+char(p,68810).
+char(9,68811).
+char(2,68812).
+char(3,68813).
+char(6,68814).
+char(c,68815).
+char(c,68816).
+char(p,68817).
+char(o,68818).
+char(o,68819).
+char(p,68820).
+char(o,68821).
+char(p,68822).
+char(o,68823).
+char(m,68824).
+char(o,68825).
+char(o,68826).
+char(m,68827).
+char(o,68828).
+char(p,68829).
+char(o,68830).
+char(m,68831).
+char(1,68832).
+char(5,68833).
+char(7,68834).
+char(2,68835).
+char(c,68836).
+char(m,68837).
+char(o,68838).
+char(o,68839).
+char(p,68840).
+char(8,68841).
+char(5,68842).
+char(8,68843).
+char(2,68844).
+char(m,68845).
+char(4,68846).
+char(1,68847).
+char(6,68848).
+char(3,68849).
+char(c,68850).
+char(m,68851).
+char(3,68852).
+char(3,68853).
+char(9,68854).
+char(0,68855).
+char(m,68856).
+char(3,68857).
+char(7,68858).
+char(8,68859).
+char(6,68860).
+char(m,68861).
+char(o,68862).
+char(o,68863).
+char(m,68864).
+char(o,68865).
+char(p,68866).
+char(7,68867).
+char(2,68868).
+char(7,68869).
+char(6,68870).
+char(p,68871).
+char(o,68872).
+char(p,68873).
+char(o,68874).
+char(m,68875).
+char(o,68876).
+char(9,68877).
+char(7,68878).
+char(2,68879).
+char(3,68880).
+char(c,68881).
+char(p,68882).
+char(5,68883).
+char(2,68884).
+char(4,68885).
+char(3,68886).
+char(m,68887).
+char(o,68888).
+char(3,68889).
+char(9,68890).
+char(4,68891).
+char(6,68892).
+char(m,68893).
+char(8,68894).
+char(5,68895).
+char(0,68896).
+char(2,68897).
+char(c,68898).
+char(m,68899).
+char(o,68900).
+char(m,68901).
+char(o,68902).
+char(m,68903).
+char(o,68904).
+char(m,68905).
+char(o,68906).
+char(o,68907).
+char(m,68908).
+char(o,68909).
+char(o,68910).
+char(m,68911).
+char(9,68912).
+char(5,68913).
+char(4,68914).
+char(5,68915).
+char(c,68916).
+char(p,68917).
+char(8,68918).
+char(0,68919).
+char(6,68920).
+char(9,68921).
+char(p,68922).
+char(o,68923).
+char(p,68924).
+char(o,68925).
+char(m,68926).
+char(o,68927).
+char(m,68928).
+char(o,68929).
+char(m,68930).
+char(o,68931).
+char(o,68932).
+char(m,68933).
+char(o,68934).
+char(m,68935).
+char(4,68936).
+char(9,68937).
+char(4,68938).
+char(3,68939).
+char(m,68940).
+char(o,68941).
+char(3,68942).
+char(4,68943).
+char(6,68944).
+char(1,68945).
+char(p,68946).
+char(9,68947).
+char(7,68948).
+char(2,68949).
+char(3,68950).
+char(c,68951).
+char(c,68952).
+char(m,68953).
+char(7,68954).
+char(0,68955).
+char(6,68956).
+char(3,68957).
+char(c,68958).
+char(c,68959).
+char(c,68960).
+char(m,68961).
+char(3,68962).
+char(7,68963).
+char(6,68964).
+char(4,68965).
+char(c,68966).
+char(m,68967).
+char(9,68968).
+char(3,68969).
+char(7,68970).
+char(2,68971).
+char(c,68972).
+char(m,68973).
+char(o,68974).
+char(2,68975).
+char(3,68976).
+char(4,68977).
+char(0,68978).
+char(p,68979).
+char(3,68980).
+char(8,68981).
+char(1,68982).
+char(7,68983).
+char(c,68984).
+char(c,68985).
+char(c,68986).
+char(p,68987).
+char(5,68988).
+char(7,68989).
+char(6,68990).
+char(0,68991).
+char(p,68992).
+char(5,68993).
+char(4,68994).
+char(4,68995).
+char(0,68996).
+char(c,68997).
+char(p,68998).
+char(8,68999).
+char(4,69000).
+char(3,69001).
+char(8,69002).
+char(c,69003).
+char(p,69004).
+char(o,69005).
+char(p,69006).
+char(3,69007).
+char(7,69008).
+char(8,69009).
+char(9,69010).
+char(p,69011).
+char(1,69012).
+char(4,69013).
+char(9,69014).
+char(2,69015).
+char(c,69016).
+char(p,69017).
+char(o,69018).
+char(p,69019).
+char(1,69020).
+char(8,69021).
+char(4,69022).
+char(8,69023).
+char(c,69024).
+char(m,69025).
+char(3,69026).
+char(8,69027).
+char(5,69028).
+char(c,69029).
+char(c,69030).
+char(c,69031).
+char(c,69032).
+char(c,69033).
+char(c,69034).
+char(m,69035).
+char(o,69036).
+char(3,69037).
+char(1,69038).
+char(6,69039).
+char(9,69040).
+char(c,69041).
+char(c,69042).
+char(p,69043).
+char(3,69044).
+char(1,69045).
+char(5,69046).
+char(7,69047).
+char(m,69048).
+char(o,69049).
+char(m,69050).
+char(o,69051).
+char(m,69052).
+char(o,69053).
+char(m,69054).
+char(6,69055).
+char(7,69056).
+char(0,69057).
+char(7,69058).
+char(c,69059).
+char(c,69060).
+char(p,69061).
+char(o,69062).
+char(3,69063).
+char(8,69064).
+char(6,69065).
+char(5,69066).
+char(c,69067).
+char(p,69068).
+char(8,69069).
+char(6,69070).
+char(8,69071).
+char(p,69072).
+char(o,69073).
+char(p,69074).
+char(8,69075).
+char(2,69076).
+char(9,69077).
+char(5,69078).
+char(c,69079).
+char(c,69080).
+char(c,69081).
+char(m,69082).
+char(o,69083).
+char(p,69084).
+char(1,69085).
+char(5,69086).
+char(8,69087).
+char(c,69088).
+char(c,69089).
+char(c,69090).
+char(c,69091).
+char(m,69092).
+char(2,69093).
+char(6,69094).
+char(3,69095).
+char(4,69096).
+char(c,69097).
+char(c,69098).
+char(c,69099).
+char(c,69100).
+char(c,69101).
+char(c,69102).
+char(c,69103).
+char(p,69104).
+char(o,69105).
+char(m,69106).
+char(o,69107).
+char(2,69108).
+char(8,69109).
+char(7,69110).
+char(2,69111).
+char(p,69112).
+char(2,69113).
+char(9,69114).
+char(3,69115).
+char(5,69116).
+char(c,69117).
+char(c,69118).
+char(m,69119).
+char(o,69120).
+char(4,69121).
+char(6,69122).
+char(7,69123).
+char(0,69124).
+char(c,69125).
+char(m,69126).
+char(o,69127).
+char(p,69128).
+char(o,69129).
+char(p,69130).
+char(o,69131).
+char(m,69132).
+char(o,69133).
+char(o,69134).
+char(1,69135).
+char(3,69136).
+char(7,69137).
+char(8,69138).
+char(c,69139).
+char(c,69140).
+char(c,69141).
+char(c,69142).
+char(c,69143).
+char(m,69144).
+char(5,69145).
+char(2,69146).
+char(3,69147).
+char(4,69148).
+char(p,69149).
+char(o,69150).
+char(o,69151).
+char(m,69152).
+char(o,69153).
+char(o,69154).
+char(p,69155).
+char(o,69156).
+char(o,69157).
+char(p,69158).
+char(2,69159).
+char(2,69160).
+char(1,69161).
+char(2,69162).
+char(p,69163).
+char(3,69164).
+char(6,69165).
+char(3,69166).
+char(2,69167).
+char(c,69168).
+char(c,69169).
+char(p,69170).
+char(o,69171).
+char(p,69172).
+char(5,69173).
+char(7,69174).
+char(9,69175).
+char(2,69176).
+char(c,69177).
+char(m,69178).
+char(7,69179).
+char(7,69180).
+char(6,69181).
+char(7,69182).
+char(p,69183).
+char(8,69184).
+char(4,69185).
+char(2,69186).
+char(5,69187).
+char(m,69188).
+char(o,69189).
+char(p,69190).
+char(o,69191).
+char(o,69192).
+char(p,69193).
+char(7,69194).
+char(6,69195).
+char(3,69196).
+char(m,69197).
+char(2,69198).
+char(6,69199).
+char(7,69200).
+char(c,69201).
+char(p,69202).
+char(o,69203).
+char(p,69204).
+char(3,69205).
+char(0,69206).
+char(3,69207).
+char(7,69208).
+char(m,69209).
+char(o,69210).
+char(m,69211).
+char(6,69212).
+char(1,69213).
+char(5,69214).
+char(1,69215).
+char(c,69216).
+char(m,69217).
+char(o,69218).
+char(m,69219).
+char(3,69220).
+char(9,69221).
+char(0,69222).
+char(7,69223).
+char(m,69224).
+char(o,69225).
+char(m,69226).
+char(2,69227).
+char(5,69228).
+char(8,69229).
+char(3,69230).
+char(p,69231).
+char(o,69232).
+char(o,69233).
+char(m,69234).
+char(6,69235).
+char(7,69236).
+char(9,69237).
+char(4,69238).
+char(c,69239).
+char(p,69240).
+char(7,69241).
+char(1,69242).
+char(6,69243).
+char(2,69244).
+char(p,69245).
+char(o,69246).
+char(p,69247).
+char(3,69248).
+char(4,69249).
+char(4,69250).
+char(0,69251).
+char(m,69252).
+char(o,69253).
+char(p,69254).
+char(1,69255).
+char(9,69256).
+char(2,69257).
+char(0,69258).
+char(p,69259).
+char(o,69260).
+char(o,69261).
+char(m,69262).
+char(1,69263).
+char(8,69264).
+char(1,69265).
+char(9,69266).
+char(c,69267).
+char(c,69268).
+char(c,69269).
+char(p,69270).
+char(o,69271).
+char(m,69272).
+char(o,69273).
+char(p,69274).
+char(9,69275).
+char(5,69276).
+char(1,69277).
+char(8,69278).
+char(m,69279).
+char(3,69280).
+char(4,69281).
+char(0,69282).
+char(6,69283).
+char(c,69284).
+char(m,69285).
+char(o,69286).
+char(m,69287).
+char(7,69288).
+char(1,69289).
+char(1,69290).
+char(4,69291).
+char(p,69292).
+char(9,69293).
+char(4,69294).
+char(8,69295).
+char(7,69296).
+char(p,69297).
+char(o,69298).
+char(p,69299).
+char(o,69300).
+char(o,69301).
+char(p,69302).
+char(o,69303).
+char(m,69304).
+char(o,69305).
+char(p,69306).
+char(o,69307).
+char(p,69308).
+char(8,69309).
+char(2,69310).
+char(3,69311).
+char(3,69312).
+char(c,69313).
+char(c,69314).
+char(p,69315).
+char(o,69316).
+char(p,69317).
+char(o,69318).
+char(m,69319).
+char(o,69320).
+char(m,69321).
+char(o,69322).
+char(p,69323).
+char(2,69324).
+char(1,69325).
+char(5,69326).
+char(7,69327).
+char(m,69328).
+char(o,69329).
+char(m,69330).
+char(5,69331).
+char(8,69332).
+char(5,69333).
+char(9,69334).
+char(c,69335).
+char(c,69336).
+char(c,69337).
+char(c,69338).
+char(c,69339).
+char(p,69340).
+char(8,69341).
+char(9,69342).
+char(2,69343).
+char(8,69344).
+char(c,69345).
+char(m,69346).
+char(2,69347).
+char(3,69348).
+char(1,69349).
+char(5,69350).
+char(m,69351).
+char(o,69352).
+char(o,69353).
+char(7,69354).
+char(8,69355).
+char(7,69356).
+char(4,69357).
+char(c,69358).
+char(c,69359).
+char(p,69360).
+char(4,69361).
+char(7,69362).
+char(4,69363).
+char(m,69364).
+char(1,69365).
+char(3,69366).
+char(7,69367).
+char(1,69368).
+char(p,69369).
+char(o,69370).
+char(p,69371).
+char(o,69372).
+char(p,69373).
+char(o,69374).
+char(m,69375).
+char(o,69376).
+char(p,69377).
+char(3,69378).
+char(9,69379).
+char(3,69380).
+char(9,69381).
+char(c,69382).
+char(p,69383).
+char(o,69384).
+char(8,69385).
+char(3,69386).
+char(4,69387).
+char(1,69388).
+char(c,69389).
+char(m,69390).
+char(o,69391).
+char(o,69392).
+char(4,69393).
+char(9,69394).
+char(1,69395).
+char(6,69396).
+char(p,69397).
+char(o,69398).
+char(p,69399).
+char(o,69400).
+char(m,69401).
+char(o,69402).
+char(m,69403).
+char(4,69404).
+char(5,69405).
+char(7,69406).
+char(7,69407).
+char(c,69408).
+char(c,69409).
+char(p,69410).
+char(o,69411).
+char(p,69412).
+char(5,69413).
+char(2,69414).
+char(1,69415).
+char(8,69416).
+char(c,69417).
+char(c,69418).
+char(c,69419).
+char(c,69420).
+char(c,69421).
+char(c,69422).
+char(p,69423).
+char(o,69424).
+char(p,69425).
+char(o,69426).
+char(m,69427).
+char(o,69428).
+char(o,69429).
+char(m,69430).
+char(o,69431).
+char(m,69432).
+char(o,69433).
+char(m,69434).
+char(o,69435).
+char(o,69436).
+char(m,69437).
+char(5,69438).
+char(1,69439).
+char(5,69440).
+char(9,69441).
+char(p,69442).
+char(1,69443).
+char(7,69444).
+char(1,69445).
+char(8,69446).
+char(m,69447).
+char(1,69448).
+char(2,69449).
+char(9,69450).
+char(9,69451).
+char(c,69452).
+char(m,69453).
+char(6,69454).
+char(5,69455).
+char(5,69456).
+char(2,69457).
+char(c,69458).
+char(c,69459).
+char(c,69460).
+char(p,69461).
+char(3,69462).
+char(8,69463).
+char(9,69464).
+char(2,69465).
+char(m,69466).
+char(o,69467).
+char(p,69468).
+char(8,69469).
+char(4,69470).
+char(3,69471).
+char(8,69472).
+char(c,69473).
+char(c,69474).
+char(p,69475).
+char(o,69476).
+char(p,69477).
+char(o,69478).
+char(m,69479).
+char(3,69480).
+char(6,69481).
+char(2,69482).
+char(c,69483).
+char(c,69484).
+char(p,69485).
+char(o,69486).
+char(p,69487).
+char(9,69488).
+char(6,69489).
+char(2,69490).
+char(6,69491).
+char(p,69492).
+char(6,69493).
+char(3,69494).
+char(4,69495).
+char(c,69496).
+char(c,69497).
+char(p,69498).
+char(o,69499).
+char(p,69500).
+char(o,69501).
+char(p,69502).
+char(o,69503).
+char(o,69504).
+char(m,69505).
+char(1,69506).
+char(4,69507).
+char(6,69508).
+char(3,69509).
+char(p,69510).
+char(o,69511).
+char(p,69512).
+char(9,69513).
+char(6,69514).
+char(8,69515).
+char(0,69516).
+char(c,69517).
+char(p,69518).
+char(8,69519).
+char(6,69520).
+char(3,69521).
+char(9,69522).
+char(c,69523).
+char(p,69524).
+char(o,69525).
+char(p,69526).
+char(7,69527).
+char(8,69528).
+char(3,69529).
+char(7,69530).
+char(m,69531).
+char(8,69532).
+char(2,69533).
+char(6,69534).
+char(2,69535).
+char(c,69536).
+char(m,69537).
+char(9,69538).
+char(5,69539).
+char(9,69540).
+char(4,69541).
+char(m,69542).
+char(7,69543).
+char(2,69544).
+char(1,69545).
+char(6,69546).
+char(p,69547).
+char(o,69548).
+char(p,69549).
+char(o,69550).
+char(p,69551).
+char(o,69552).
+char(p,69553).
+char(o,69554).
+char(o,69555).
+char(5,69556).
+char(0,69557).
+char(5,69558).
+char(0,69559).
+char(c,69560).
+char(m,69561).
+char(2,69562).
+char(2,69563).
+char(8,69564).
+char(2,69565).
+char(c,69566).
+char(c,69567).
+char(c,69568).
+char(c,69569).
+char(c,69570).
+char(p,69571).
+char(o,69572).
+char(m,69573).
+char(9,69574).
+char(6,69575).
+char(6,69576).
+char(1,69577).
+char(p,69578).
+char(o,69579).
+char(m,69580).
+char(o,69581).
+char(1,69582).
+char(3,69583).
+char(5,69584).
+char(9,69585).
+char(p,69586).
+char(o,69587).
+char(5,69588).
+char(8,69589).
+char(3,69590).
+char(6,69591).
+char(c,69592).
+char(p,69593).
+char(o,69594).
+char(p,69595).
+char(o,69596).
+char(m,69597).
+char(o,69598).
+char(p,69599).
+char(9,69600).
+char(7,69601).
+char(3,69602).
+char(5,69603).
+char(p,69604).
+char(2,69605).
+char(5,69606).
+char(8,69607).
+char(5,69608).
+char(c,69609).
+char(m,69610).
+char(5,69611).
+char(1,69612).
+char(3,69613).
+char(6,69614).
+char(c,69615).
+char(p,69616).
+char(o,69617).
+char(o,69618).
+char(m,69619).
+char(9,69620).
+char(1,69621).
+char(9,69622).
+char(7,69623).
+char(c,69624).
+char(c,69625).
+char(p,69626).
+char(2,69627).
+char(1,69628).
+char(2,69629).
+char(8,69630).
+char(c,69631).
+char(c,69632).
+char(c,69633).
+char(c,69634).
+char(c,69635).
+char(m,69636).
+char(o,69637).
+char(1,69638).
+char(6,69639).
+char(6,69640).
+char(9,69641).
+char(p,69642).
+char(o,69643).
+char(m,69644).
+char(o,69645).
+char(o,69646).
+char(2,69647).
+char(2,69648).
+char(7,69649).
+char(3,69650).
+char(m,69651).
+char(7,69652).
+char(5,69653).
+char(0,69654).
+char(1,69655).
+char(c,69656).
+char(c,69657).
+char(c,69658).
+char(c,69659).
+char(c,69660).
+char(c,69661).
+char(p,69662).
+char(1,69663).
+char(0,69664).
+char(8,69665).
+char(8,69666).
+char(p,69667).
+char(o,69668).
+char(m,69669).
+char(o,69670).
+char(m,69671).
+char(3,69672).
+char(7,69673).
+char(9,69674).
+char(m,69675).
+char(o,69676).
+char(9,69677).
+char(6,69678).
+char(4,69679).
+char(0,69680).
+char(m,69681).
+char(o,69682).
+char(7,69683).
+char(8,69684).
+char(0,69685).
+char(5,69686).
+char(c,69687).
+char(c,69688).
+char(c,69689).
+char(c,69690).
+char(c,69691).
+char(c,69692).
+char(m,69693).
+char(o,69694).
+char(3,69695).
+char(8,69696).
+char(5,69697).
+char(1,69698).
+char(c,69699).
+char(p,69700).
+char(6,69701).
+char(6,69702).
+char(4,69703).
+char(2,69704).
+char(c,69705).
+char(c,69706).
+char(c,69707).
+char(c,69708).
+char(c,69709).
+char(c,69710).
+char(c,69711).
+char(c,69712).
+char(c,69713).
+char(m,69714).
+char(o,69715).
+char(p,69716).
+char(o,69717).
+char(m,69718).
+char(5,69719).
+char(4,69720).
+char(2,69721).
+char(1,69722).
+char(c,69723).
+char(m,69724).
+char(4,69725).
+char(4,69726).
+char(1,69727).
+char(9,69728).
+char(c,69729).
+char(c,69730).
+char(c,69731).
+char(c,69732).
+char(m,69733).
+char(o,69734).
+char(m,69735).
+char(7,69736).
+char(8,69737).
+char(4,69738).
+char(8,69739).
+char(c,69740).
+char(p,69741).
+char(o,69742).
+char(m,69743).
+char(5,69744).
+char(5,69745).
+char(4,69746).
+char(6,69747).
+char(c,69748).
+char(c,69749).
+char(m,69750).
+char(6,69751).
+char(8,69752).
+char(9,69753).
+char(7,69754).
+char(c,69755).
+char(p,69756).
+char(1,69757).
+char(6,69758).
+char(5,69759).
+char(0,69760).
+char(m,69761).
+char(o,69762).
+char(p,69763).
+char(o,69764).
+char(m,69765).
+char(7,69766).
+char(7,69767).
+char(8,69768).
+char(0,69769).
+char(m,69770).
+char(o,69771).
+char(4,69772).
+char(1,69773).
+char(7,69774).
+char(3,69775).
+char(m,69776).
+char(8,69777).
+char(5,69778).
+char(2,69779).
+char(0,69780).
+char(m,69781).
+char(4,69782).
+char(0,69783).
+char(7,69784).
+char(8,69785).
+char(c,69786).
+char(c,69787).
+char(c,69788).
+char(c,69789).
+char(p,69790).
+char(6,69791).
+char(8,69792).
+char(5,69793).
+char(1,69794).
+char(m,69795).
+char(6,69796).
+char(9,69797).
+char(5,69798).
+char(c,69799).
+char(c,69800).
+char(m,69801).
+char(o,69802).
+char(p,69803).
+char(o,69804).
+char(8,69805).
+char(4,69806).
+char(9,69807).
+char(6,69808).
+char(c,69809).
+char(c,69810).
+char(c,69811).
+char(c,69812).
+char(c,69813).
+char(c,69814).
+char(c,69815).
+char(c,69816).
+char(m,69817).
+char(7,69818).
+char(1,69819).
+char(7,69820).
+char(4,69821).
+char(m,69822).
+char(5,69823).
+char(6,69824).
+char(7,69825).
+char(5,69826).
+char(c,69827).
+char(c,69828).
+char(c,69829).
+char(m,69830).
+char(2,69831).
+char(6,69832).
+char(2,69833).
+char(8,69834).
+char(m,69835).
+char(1,69836).
+char(7,69837).
+char(9,69838).
+char(m,69839).
+char(o,69840).
+char(m,69841).
+char(6,69842).
+char(1,69843).
+char(2,69844).
+char(1,69845).
+char(c,69846).
+char(c,69847).
+char(c,69848).
+char(c,69849).
+char(m,69850).
+char(8,69851).
+char(0,69852).
+char(5,69853).
+char(7,69854).
+char(m,69855).
+char(8,69856).
+char(7,69857).
+char(6,69858).
+char(3,69859).
+char(p,69860).
+char(o,69861).
+char(p,69862).
+char(o,69863).
+char(p,69864).
+char(o,69865).
+char(1,69866).
+char(5,69867).
+char(1,69868).
+char(9,69869).
+char(c,69870).
+char(m,69871).
+char(o,69872).
+char(m,69873).
+char(o,69874).
+char(p,69875).
+char(o,69876).
+char(o,69877).
+char(p,69878).
+char(4,69879).
+char(2,69880).
+char(6,69881).
+char(p,69882).
+char(o,69883).
+char(m,69884).
+char(o,69885).
+char(m,69886).
+char(2,69887).
+char(8,69888).
+char(1,69889).
+char(4,69890).
+char(c,69891).
+char(c,69892).
+char(m,69893).
+char(7,69894).
+char(3,69895).
+char(3,69896).
+char(6,69897).
+char(c,69898).
+char(m,69899).
+char(o,69900).
+char(m,69901).
+char(o,69902).
+char(6,69903).
+char(0,69904).
+char(1,69905).
+char(1,69906).
+char(c,69907).
+char(c,69908).
+char(p,69909).
+char(3,69910).
+char(9,69911).
+char(7,69912).
+char(7,69913).
+char(m,69914).
+char(o,69915).
+char(o,69916).
+char(o,69917).
+char(p,69918).
+char(4,69919).
+char(9,69920).
+char(9,69921).
+char(3,69922).
+char(m,69923).
+char(o,69924).
+char(8,69925).
+char(8,69926).
+char(9,69927).
+char(4,69928).
+char(m,69929).
+char(6,69930).
+char(9,69931).
+char(3,69932).
+char(8,69933).
+char(c,69934).
+char(c,69935).
+char(p,69936).
+char(9,69937).
+char(4,69938).
+char(8,69939).
+char(6,69940).
+char(m,69941).
+char(3,69942).
+char(5,69943).
+char(7,69944).
+char(5,69945).
+char(m,69946).
+char(3,69947).
+char(8,69948).
+char(c,69949).
+char(p,69950).
+char(o,69951).
+char(p,69952).
+char(7,69953).
+char(9,69954).
+char(1,69955).
+char(1,69956).
+char(c,69957).
+char(p,69958).
+char(o,69959).
+char(m,69960).
+char(6,69961).
+char(3,69962).
+char(5,69963).
+char(1,69964).
+char(m,69965).
+char(5,69966).
+char(7,69967).
+char(0,69968).
+char(7,69969).
+char(c,69970).
+char(p,69971).
+char(o,69972).
+char(m,69973).
+char(o,69974).
+char(m,69975).
+char(o,69976).
+char(m,69977).
+char(o,69978).
+char(4,69979).
+char(0,69980).
+char(4,69981).
+char(5,69982).
+char(p,69983).
+char(o,69984).
+char(m,69985).
+char(o,69986).
+char(p,69987).
+char(o,69988).
+char(p,69989).
+char(7,69990).
+char(8,69991).
+char(7,69992).
+char(7,69993).
+char(c,69994).
+char(p,69995).
+char(o,69996).
+char(1,69997).
+char(3,69998).
+char(8,69999).
+char(4,70000).
+char(c,70001).
+char(c,70002).
+char(c,70003).
+char(p,70004).
+char(o,70005).
+char(p,70006).
+char(o,70007).
+char(6,70008).
+char(8,70009).
+char(3,70010).
+char(3,70011).
+char(c,70012).
+char(p,70013).
+char(4,70014).
+char(7,70015).
+char(1,70016).
+char(8,70017).
+char(m,70018).
+char(o,70019).
+char(p,70020).
+char(o,70021).
+char(m,70022).
+char(3,70023).
+char(3,70024).
+char(1,70025).
+char(3,70026).
+char(c,70027).
+char(c,70028).
+char(m,70029).
+char(2,70030).
+char(0,70031).
+char(8,70032).
+char(c,70033).
+char(m,70034).
+char(8,70035).
+char(3,70036).
+char(5,70037).
+char(4,70038).
+char(c,70039).
+char(p,70040).
+char(5,70041).
+char(3,70042).
+char(8,70043).
+char(1,70044).
+char(c,70045).
+char(c,70046).
+char(m,70047).
+char(5,70048).
+char(8,70049).
+char(5,70050).
+char(p,70051).
+char(7,70052).
+char(9,70053).
+char(6,70054).
+char(1,70055).
+char(c,70056).
+char(m,70057).
+char(2,70058).
+char(9,70059).
+char(5,70060).
+char(8,70061).
+char(p,70062).
+char(9,70063).
+char(5,70064).
+char(1,70065).
+char(2,70066).
+char(p,70067).
+char(o,70068).
+char(p,70069).
+char(o,70070).
+char(o,70071).
+char(4,70072).
+char(4,70073).
+char(6,70074).
+char(2,70075).
+char(c,70076).
+char(p,70077).
+char(o,70078).
+char(m,70079).
+char(3,70080).
+char(0,70081).
+char(0,70082).
+char(1,70083).
+char(c,70084).
+char(m,70085).
+char(o,70086).
+char(m,70087).
+char(o,70088).
+char(8,70089).
+char(4,70090).
+char(0,70091).
+char(1,70092).
+char(c,70093).
+char(c,70094).
+char(c,70095).
+char(c,70096).
+char(c,70097).
+char(c,70098).
+char(p,70099).
+char(2,70100).
+char(1,70101).
+char(1,70102).
+char(4,70103).
+char(c,70104).
+char(m,70105).
+char(o,70106).
+char(p,70107).
+char(4,70108).
+char(7,70109).
+char(6,70110).
+char(3,70111).
+char(p,70112).
+char(4,70113).
+char(8,70114).
+char(3,70115).
+char(3,70116).
+char(p,70117).
+char(0,70118).
+char(c,70119).
+char(c,70120).
+char(c,70121).
+char(p,70122).
+char(o,70123).
+char(m,70124).
+char(o,70125).
+char(m,70126).
+char(o,70127).
+char(o,70128).
+char(m,70129).
+char(o,70130).
+char(m,70131).
+char(o,70132).
+char(p,70133).
+char(9,70134).
+char(1,70135).
+char(5,70136).
+char(3,70137).
+char(m,70138).
+char(o,70139).
+char(p,70140).
+char(8,70141).
+char(2,70142).
+char(3,70143).
+char(3,70144).
+char(p,70145).
+char(1,70146).
+char(7,70147).
+char(2,70148).
+char(5,70149).
+char(p,70150).
+char(o,70151).
+char(m,70152).
+char(o,70153).
+char(p,70154).
+char(o,70155).
+char(p,70156).
+char(o,70157).
+char(p,70158).
+char(o,70159).
+char(p,70160).
+char(1,70161).
+char(4,70162).
+char(5,70163).
+char(2,70164).
+char(p,70165).
+char(8,70166).
+char(4,70167).
+char(6,70168).
+char(0,70169).
+char(p,70170).
+char(o,70171).
+char(p,70172).
+char(o,70173).
+char(m,70174).
+char(3,70175).
+char(9,70176).
+char(9,70177).
+char(8,70178).
+char(p,70179).
+char(3,70180).
+char(1,70181).
+char(7,70182).
+char(8,70183).
+char(p,70184).
+char(8,70185).
+char(4,70186).
+char(1,70187).
+char(6,70188).
+char(c,70189).
+char(c,70190).
+char(m,70191).
+char(1,70192).
+char(2,70193).
+char(7,70194).
+char(7,70195).
+char(p,70196).
+char(o,70197).
+char(p,70198).
+char(o,70199).
+char(m,70200).
+char(8,70201).
+char(5,70202).
+char(2,70203).
+char(6,70204).
+char(c,70205).
+char(p,70206).
+char(o,70207).
+char(5,70208).
+char(1,70209).
+char(6,70210).
+char(9,70211).
+char(m,70212).
+char(8,70213).
+char(2,70214).
+char(7,70215).
+char(3,70216).
+char(p,70217).
+char(5,70218).
+char(0,70219).
+char(9,70220).
+char(p,70221).
+char(7,70222).
+char(0,70223).
+char(0,70224).
+char(7,70225).
+char(c,70226).
+char(c,70227).
+char(c,70228).
+char(c,70229).
+char(p,70230).
+char(1,70231).
+char(6,70232).
+char(8,70233).
+char(1,70234).
+char(p,70235).
+char(3,70236).
+char(6,70237).
+char(2,70238).
+char(0,70239).
+char(p,70240).
+char(o,70241).
+char(m,70242).
+char(4,70243).
+char(7,70244).
+char(9,70245).
+char(5,70246).
+char(m,70247).
+char(5,70248).
+char(3,70249).
+char(5,70250).
+char(1,70251).
+char(p,70252).
+char(1,70253).
+char(1,70254).
+char(1,70255).
+char(2,70256).
+char(c,70257).
+char(c,70258).
+char(m,70259).
+char(o,70260).
+char(m,70261).
+char(4,70262).
+char(4,70263).
+char(2,70264).
+char(c,70265).
+char(c,70266).
+char(m,70267).
+char(o,70268).
+char(p,70269).
+char(3,70270).
+char(0,70271).
+char(4,70272).
+char(4,70273).
+char(p,70274).
+char(7,70275).
+char(5,70276).
+char(6,70277).
+char(9,70278).
+char(c,70279).
+char(p,70280).
+char(7,70281).
+char(2,70282).
+char(0,70283).
+char(9,70284).
+char(c,70285).
+char(c,70286).
+char(c,70287).
+char(c,70288).
+char(c,70289).
+char(m,70290).
+char(8,70291).
+char(9,70292).
+char(3,70293).
+char(m,70294).
+char(o,70295).
+char(8,70296).
+char(2,70297).
+char(6,70298).
+char(6,70299).
+char(c,70300).
+char(c,70301).
+char(c,70302).
+char(p,70303).
+char(4,70304).
+char(2,70305).
+char(4,70306).
+char(9,70307).
+char(m,70308).
+char(o,70309).
+char(p,70310).
+char(4,70311).
+char(9,70312).
+char(5,70313).
+char(2,70314).
+char(c,70315).
+char(m,70316).
+char(3,70317).
+char(8,70318).
+char(2,70319).
+char(3,70320).
+char(p,70321).
+char(7,70322).
+char(1,70323).
+char(7,70324).
+char(1,70325).
+char(m,70326).
+char(o,70327).
+char(2,70328).
+char(2,70329).
+char(1,70330).
+char(1,70331).
+char(c,70332).
+char(m,70333).
+char(8,70334).
+char(8,70335).
+char(1,70336).
+char(0,70337).
+char(c,70338).
+char(c,70339).
+char(p,70340).
+char(o,70341).
+char(p,70342).
+char(5,70343).
+char(4,70344).
+char(8,70345).
+char(2,70346).
+char(m,70347).
+char(o,70348).
+char(m,70349).
+char(8,70350).
+char(2,70351).
+char(3,70352).
+char(7,70353).
+char(c,70354).
+char(c,70355).
+char(p,70356).
+char(o,70357).
+char(p,70358).
+char(4,70359).
+char(5,70360).
+char(6,70361).
+char(3,70362).
+char(p,70363).
+char(2,70364).
+char(4,70365).
+char(3,70366).
+char(2,70367).
+char(m,70368).
+char(2,70369).
+char(8,70370).
+char(8,70371).
+char(p,70372).
+char(o,70373).
+char(p,70374).
+char(8,70375).
+char(9,70376).
+char(0,70377).
+char(3,70378).
+char(p,70379).
+char(7,70380).
+char(6,70381).
+char(0,70382).
+char(2,70383).
+char(p,70384).
+char(o,70385).
+char(o,70386).
+char(p,70387).
+char(3,70388).
+char(7,70389).
+char(6,70390).
+char(p,70391).
+char(o,70392).
+char(o,70393).
+char(8,70394).
+char(3,70395).
+char(4,70396).
+char(5,70397).
+char(p,70398).
+char(4,70399).
+char(5,70400).
+char(2,70401).
+char(2,70402).
+char(c,70403).
+char(p,70404).
+char(o,70405).
+char(7,70406).
+char(4,70407).
+char(6,70408).
+char(1,70409).
+char(m,70410).
+char(o,70411).
+char(m,70412).
+char(o,70413).
+char(m,70414).
+char(2,70415).
+char(4,70416).
+char(9,70417).
+char(0,70418).
+char(m,70419).
+char(o,70420).
+char(m,70421).
+char(o,70422).
+char(m,70423).
+char(o,70424).
+char(p,70425).
+char(5,70426).
+char(4,70427).
+char(0,70428).
+char(c,70429).
+char(p,70430).
+char(9,70431).
+char(4,70432).
+char(0,70433).
+char(1,70434).
+char(c,70435).
+char(c,70436).
+char(p,70437).
+char(o,70438).
+char(m,70439).
+char(6,70440).
+char(5,70441).
+char(4,70442).
+char(0,70443).
+char(m,70444).
+char(o,70445).
+char(p,70446).
+char(2,70447).
+char(3,70448).
+char(6,70449).
+char(1,70450).
+char(p,70451).
+char(o,70452).
+char(m,70453).
+char(5,70454).
+char(3,70455).
+char(6,70456).
+char(3,70457).
+char(c,70458).
+char(c,70459).
+char(p,70460).
+char(o,70461).
+char(o,70462).
+char(p,70463).
+char(o,70464).
+char(p,70465).
+char(1,70466).
+char(1,70467).
+char(0,70468).
+char(1,70469).
+char(c,70470).
+char(c,70471).
+char(c,70472).
+char(m,70473).
+char(7,70474).
+char(0,70475).
+char(1,70476).
+char(1,70477).
+char(m,70478).
+char(o,70479).
+char(p,70480).
+char(3,70481).
+char(3,70482).
+char(2,70483).
+char(3,70484).
+char(c,70485).
+char(c,70486).
+char(p,70487).
+char(o,70488).
+char(m,70489).
+char(o,70490).
+char(o,70491).
+char(p,70492).
+char(o,70493).
+char(p,70494).
+char(o,70495).
+char(m,70496).
+char(o,70497).
+char(o,70498).
+char(m,70499).
+char(o,70500).
+char(p,70501).
+char(6,70502).
+char(7,70503).
+char(2,70504).
+char(6,70505).
+char(c,70506).
+char(m,70507).
+char(3,70508).
+char(2,70509).
+char(2,70510).
+char(m,70511).
+char(8,70512).
+char(5,70513).
+char(7,70514).
+char(6,70515).
+char(p,70516).
+char(1,70517).
+char(6,70518).
+char(7,70519).
+char(1,70520).
+char(c,70521).
+char(c,70522).
+char(c,70523).
+char(c,70524).
+char(m,70525).
+char(o,70526).
+char(m,70527).
+char(o,70528).
+char(1,70529).
+char(2,70530).
+char(0,70531).
+char(2,70532).
+char(p,70533).
+char(o,70534).
+char(m,70535).
+char(7,70536).
+char(5,70537).
+char(7,70538).
+char(7,70539).
+char(c,70540).
+char(c,70541).
+char(c,70542).
+char(c,70543).
+char(c,70544).
+char(m,70545).
+char(o,70546).
+char(7,70547).
+char(0,70548).
+char(3,70549).
+char(7,70550).
+char(m,70551).
+char(o,70552).
+char(m,70553).
+char(o,70554).
+char(m,70555).
+char(o,70556).
+char(o,70557).
+char(p,70558).
+char(8,70559).
+char(3,70560).
+char(7,70561).
+char(5,70562).
+char(m,70563).
+char(o,70564).
+char(m,70565).
+char(9,70566).
+char(8,70567).
+char(6,70568).
+char(8,70569).
+char(p,70570).
+char(5,70571).
+char(9,70572).
+char(1,70573).
+char(7,70574).
+char(m,70575).
+char(3,70576).
+char(8,70577).
+char(4,70578).
+char(4,70579).
+char(p,70580).
+char(o,70581).
+char(m,70582).
+char(1,70583).
+char(0,70584).
+char(9,70585).
+char(2,70586).
+char(c,70587).
+char(p,70588).
+char(9,70589).
+char(4,70590).
+char(9,70591).
+char(3,70592).
+char(c,70593).
+char(c,70594).
+char(c,70595).
+char(p,70596).
+char(o,70597).
+char(o,70598).
+char(p,70599).
+char(5,70600).
+char(6,70601).
+char(9,70602).
+char(0,70603).
+char(c,70604).
+char(c,70605).
+char(m,70606).
+char(o,70607).
+char(p,70608).
+char(o,70609).
+char(m,70610).
+char(o,70611).
+char(8,70612).
+char(4,70613).
+char(2,70614).
+char(8,70615).
+char(c,70616).
+char(p,70617).
+char(3,70618).
+char(2,70619).
+char(0,70620).
+char(7,70621).
+char(c,70622).
+char(c,70623).
+char(c,70624).
+char(p,70625).
+char(8,70626).
+char(5,70627).
+char(8,70628).
+char(8,70629).
+char(p,70630).
+char(o,70631).
+char(p,70632).
+char(o,70633).
+char(o,70634).
+char(p,70635).
+char(8,70636).
+char(3,70637).
+char(0,70638).
+char(1,70639).
+char(p,70640).
+char(o,70641).
+char(o,70642).
+char(m,70643).
+char(o,70644).
+char(m,70645).
+char(5,70646).
+char(8,70647).
+char(3,70648).
+char(2,70649).
+char(c,70650).
+char(p,70651).
+char(o,70652).
+char(o,70653).
+char(5,70654).
+char(6,70655).
+char(9,70656).
+char(c,70657).
+char(c,70658).
+char(c,70659).
+char(p,70660).
+char(5,70661).
+char(4,70662).
+char(2,70663).
+char(2,70664).
+char(c,70665).
+char(c,70666).
+char(p,70667).
+char(o,70668).
+char(m,70669).
+char(6,70670).
+char(2,70671).
+char(6,70672).
+char(2,70673).
+char(c,70674).
+char(c,70675).
+char(m,70676).
+char(o,70677).
+char(m,70678).
+char(2,70679).
+char(5,70680).
+char(3,70681).
+char(c,70682).
+char(m,70683).
+char(8,70684).
+char(4,70685).
+char(1,70686).
+char(c,70687).
+char(m,70688).
+char(3,70689).
+char(8,70690).
+char(0,70691).
+char(6,70692).
+char(c,70693).
+char(c,70694).
+char(c,70695).
+char(m,70696).
+char(7,70697).
+char(5,70698).
+char(1,70699).
+char(6,70700).
+char(m,70701).
+char(5,70702).
+char(2,70703).
+char(4,70704).
+char(m,70705).
+char(1,70706).
+char(0,70707).
+char(4,70708).
+char(8,70709).
+char(p,70710).
+char(o,70711).
+char(m,70712).
+char(6,70713).
+char(6,70714).
+char(7,70715).
+char(4,70716).
+char(p,70717).
+char(o,70718).
+char(p,70719).
+char(9,70720).
+char(0,70721).
+char(9,70722).
+char(9,70723).
+char(p,70724).
+char(o,70725).
+char(m,70726).
+char(2,70727).
+char(5,70728).
+char(2,70729).
+char(1,70730).
+char(c,70731).
+char(c,70732).
+char(c,70733).
+char(m,70734).
+char(4,70735).
+char(2,70736).
+char(9,70737).
+char(c,70738).
+char(p,70739).
+char(9,70740).
+char(5,70741).
+char(9,70742).
+char(7,70743).
+char(p,70744).
+char(1,70745).
+char(1,70746).
+char(3,70747).
+char(3,70748).
+char(p,70749).
+char(o,70750).
+char(3,70751).
+char(3,70752).
+char(2,70753).
+char(7,70754).
+char(m,70755).
+char(6,70756).
+char(0,70757).
+char(9,70758).
+char(0,70759).
+char(c,70760).
+char(c,70761).
+char(p,70762).
+char(7,70763).
+char(6,70764).
+char(5,70765).
+char(0,70766).
+char(c,70767).
+char(m,70768).
+char(o,70769).
+char(m,70770).
+char(3,70771).
+char(4,70772).
+char(7,70773).
+char(8,70774).
+char(m,70775).
+char(2,70776).
+char(1,70777).
+char(1,70778).
+char(8,70779).
+char(m,70780).
+char(6,70781).
+char(0,70782).
+char(4,70783).
+char(4,70784).
+char(m,70785).
+char(o,70786).
+char(2,70787).
+char(2,70788).
+char(1,70789).
+char(5,70790).
+char(c,70791).
+char(p,70792).
+char(6,70793).
+char(7,70794).
+char(9,70795).
+char(2,70796).
+char(c,70797).
+char(p,70798).
+char(o,70799).
+char(o,70800).
+char(o,70801).
+char(m,70802).
+char(o,70803).
+char(o,70804).
+char(7,70805).
+char(0,70806).
+char(6,70807).
+char(6,70808).
+char(c,70809).
+char(c,70810).
+char(c,70811).
+char(p,70812).
+char(4,70813).
+char(9,70814).
+char(9,70815).
+char(1,70816).
+char(p,70817).
+char(1,70818).
+char(6,70819).
+char(6,70820).
+char(9,70821).
+char(c,70822).
+char(c,70823).
+char(m,70824).
+char(o,70825).
+char(p,70826).
+char(9,70827).
+char(6,70828).
+char(3,70829).
+char(4,70830).
+char(p,70831).
+char(o,70832).
+char(o,70833).
+char(o,70834).
+char(2,70835).
+char(9,70836).
+char(9,70837).
+char(6,70838).
+char(c,70839).
+char(c,70840).
+char(m,70841).
+char(2,70842).
+char(5,70843).
+char(5,70844).
+char(1,70845).
+char(p,70846).
+char(o,70847).
+char(m,70848).
+char(o,70849).
+char(p,70850).
+char(o,70851).
+char(m,70852).
+char(o,70853).
+char(o,70854).
+char(m,70855).
+char(o,70856).
+char(p,70857).
+char(9,70858).
+char(0,70859).
+char(5,70860).
+char(6,70861).
+char(c,70862).
+char(c,70863).
+char(p,70864).
+char(7,70865).
+char(7,70866).
+char(6,70867).
+char(0,70868).
+char(m,70869).
+char(o,70870).
+char(p,70871).
+char(3,70872).
+char(0,70873).
+char(8,70874).
+char(8,70875).
+char(c,70876).
+char(c,70877).
+char(p,70878).
+char(o,70879).
+char(m,70880).
+char(o,70881).
+char(2,70882).
+char(8,70883).
+char(8,70884).
+char(1,70885).
+char(p,70886).
+char(7,70887).
+char(2,70888).
+char(8,70889).
+char(p,70890).
+char(2,70891).
+char(6,70892).
+char(7,70893).
+char(1,70894).
+char(c,70895).
+char(m,70896).
+char(o,70897).
+char(m,70898).
+char(2,70899).
+char(2,70900).
+char(2,70901).
+char(c,70902).
+char(c,70903).
+char(c,70904).
+char(p,70905).
+char(o,70906).
+char(p,70907).
+char(9,70908).
+char(7,70909).
+char(2,70910).
+char(4,70911).
+char(m,70912).
+char(5,70913).
+char(0,70914).
+char(8,70915).
+char(3,70916).
+char(c,70917).
+char(m,70918).
+char(2,70919).
+char(7,70920).
+char(5,70921).
+char(2,70922).
+char(c,70923).
+char(c,70924).
+char(c,70925).
+char(p,70926).
+char(o,70927).
+char(3,70928).
+char(7,70929).
+char(0,70930).
+char(1,70931).
+char(m,70932).
+char(o,70933).
+char(p,70934).
+char(4,70935).
+char(1,70936).
+char(3,70937).
+char(4,70938).
+char(p,70939).
+char(6,70940).
+char(8,70941).
+char(7,70942).
+char(4,70943).
+char(m,70944).
+char(o,70945).
+char(o,70946).
+char(o,70947).
+char(p,70948).
+char(9,70949).
+char(4,70950).
+char(5,70951).
+char(m,70952).
+char(o,70953).
+char(o,70954).
+char(p,70955).
+char(5,70956).
+char(5,70957).
+char(5,70958).
+char(4,70959).
+char(m,70960).
+char(o,70961).
+char(o,70962).
+char(m,70963).
+char(o,70964).
+char(5,70965).
+char(7,70966).
+char(9,70967).
+char(4,70968).
+char(p,70969).
+char(o,70970).
+char(p,70971).
+char(o,70972).
+char(o,70973).
+char(m,70974).
+char(8,70975).
+char(5,70976).
+char(8,70977).
+char(2,70978).
+char(c,70979).
+char(c,70980).
+char(c,70981).
+char(p,70982).
+char(4,70983).
+char(0,70984).
+char(9,70985).
+char(4,70986).
+char(p,70987).
+char(o,70988).
+char(m,70989).
+char(o,70990).
+char(8,70991).
+char(7,70992).
+char(6,70993).
+char(m,70994).
+char(o,70995).
+char(m,70996).
+char(9,70997).
+char(1,70998).
+char(4,70999).
+char(6,71000).
+char(p,71001).
+char(o,71002).
+char(m,71003).
+char(7,71004).
+char(8,71005).
+char(3,71006).
+char(2,71007).
+char(c,71008).
+char(m,71009).
+char(4,71010).
+char(3,71011).
+char(7,71012).
+char(8,71013).
+char(m,71014).
+char(o,71015).
+char(5,71016).
+char(1,71017).
+char(5,71018).
+char(9,71019).
+char(c,71020).
+char(m,71021).
+char(1,71022).
+char(4,71023).
+char(6,71024).
+char(2,71025).
+char(p,71026).
+char(8,71027).
+char(3,71028).
+char(0,71029).
+char(3,71030).
+char(p,71031).
+char(o,71032).
+char(p,71033).
+char(2,71034).
+char(5,71035).
+char(4,71036).
+char(7,71037).
+char(p,71038).
+char(2,71039).
+char(8,71040).
+char(1,71041).
+char(1,71042).
+char(c,71043).
+char(p,71044).
+char(o,71045).
+char(m,71046).
+char(1,71047).
+char(0,71048).
+char(2,71049).
+char(3,71050).
+char(p,71051).
+char(o,71052).
+char(p,71053).
+char(o,71054).
+char(o,71055).
+char(p,71056).
+char(o,71057).
+char(m,71058).
+char(o,71059).
+char(1,71060).
+char(6,71061).
+char(9,71062).
+char(5,71063).
+char(m,71064).
+char(3,71065).
+char(9,71066).
+char(5,71067).
+char(9,71068).
+char(c,71069).
+char(c,71070).
+char(c,71071).
+char(p,71072).
+char(o,71073).
+char(m,71074).
+char(o,71075).
+char(p,71076).
+char(o,71077).
+char(1,71078).
+char(3,71079).
+char(9,71080).
+char(8,71081).
+char(c,71082).
+char(p,71083).
+char(7,71084).
+char(8,71085).
+char(0,71086).
+char(9,71087).
+char(m,71088).
+char(o,71089).
+char(o,71090).
+char(p,71091).
+char(5,71092).
+char(3,71093).
+char(8,71094).
+char(7,71095).
+char(m,71096).
+char(o,71097).
+char(p,71098).
+char(o,71099).
+char(3,71100).
+char(8,71101).
+char(7,71102).
+char(3,71103).
+char(p,71104).
+char(3,71105).
+char(9,71106).
+char(2,71107).
+char(3,71108).
+char(c,71109).
+char(m,71110).
+char(9,71111).
+char(3,71112).
+char(3,71113).
+char(1,71114).
+char(c,71115).
+char(c,71116).
+char(m,71117).
+char(3,71118).
+char(4,71119).
+char(6,71120).
+char(6,71121).
+char(c,71122).
+char(m,71123).
+char(o,71124).
+char(m,71125).
+char(o,71126).
+char(p,71127).
+char(o,71128).
+char(m,71129).
+char(o,71130).
+char(p,71131).
+char(9,71132).
+char(8,71133).
+char(3,71134).
+char(3,71135).
+char(c,71136).
+char(m,71137).
+char(8,71138).
+char(5,71139).
+char(1,71140).
+char(c,71141).
+char(c,71142).
+char(c,71143).
+char(c,71144).
+char(c,71145).
+char(c,71146).
+char(p,71147).
+char(9,71148).
+char(7,71149).
+char(1,71150).
+char(0,71151).
+char(c,71152).
+char(p,71153).
+char(o,71154).
+char(m,71155).
+char(1,71156).
+char(6,71157).
+char(7,71158).
+char(6,71159).
+char(c,71160).
+char(m,71161).
+char(7,71162).
+char(1,71163).
+char(3,71164).
+char(4,71165).
+char(c,71166).
+char(p,71167).
+char(o,71168).
+char(m,71169).
+char(7,71170).
+char(5,71171).
+char(4,71172).
+char(8,71173).
+char(m,71174).
+char(o,71175).
+char(o,71176).
+char(4,71177).
+char(4,71178).
+char(7,71179).
+char(6,71180).
+char(m,71181).
+char(o,71182).
+char(5,71183).
+char(7,71184).
+char(8,71185).
+char(3,71186).
+char(m,71187).
+char(6,71188).
+char(9,71189).
+char(4,71190).
+char(1,71191).
+char(c,71192).
+char(c,71193).
+char(c,71194).
+char(m,71195).
+char(o,71196).
+char(m,71197).
+char(1,71198).
+char(5,71199).
+char(1,71200).
+char(6,71201).
+char(m,71202).
+char(7,71203).
+char(7,71204).
+char(9,71205).
+char(9,71206).
+char(m,71207).
+char(8,71208).
+char(1,71209).
+char(7,71210).
+char(6,71211).
+char(c,71212).
+char(c,71213).
+char(m,71214).
+char(o,71215).
+char(o,71216).
+char(p,71217).
+char(o,71218).
+char(m,71219).
+char(2,71220).
+char(2,71221).
+char(7,71222).
+char(8,71223).
+char(m,71224).
+char(o,71225).
+char(8,71226).
+char(5,71227).
+char(3,71228).
+char(4,71229).
+char(m,71230).
+char(9,71231).
+char(0,71232).
+char(7,71233).
+char(4,71234).
+char(p,71235).
+char(o,71236).
+char(m,71237).
+char(o,71238).
+char(p,71239).
+char(o,71240).
+char(m,71241).
+char(o,71242).
+char(m,71243).
+char(o,71244).
+char(m,71245).
+char(o,71246).
+char(m,71247).
+char(3,71248).
+char(6,71249).
+char(6,71250).
+char(m,71251).
+char(3,71252).
+char(0,71253).
+char(6,71254).
+char(c,71255).
+char(c,71256).
+char(c,71257).
+char(m,71258).
+char(o,71259).
+char(p,71260).
+char(o,71261).
+char(m,71262).
+char(4,71263).
+char(4,71264).
+char(7,71265).
+char(0,71266).
+char(c,71267).
+char(m,71268).
+char(5,71269).
+char(0,71270).
+char(3,71271).
+char(7,71272).
+char(p,71273).
+char(9,71274).
+char(2,71275).
+char(9,71276).
+char(2,71277).
+char(m,71278).
+char(o,71279).
+char(p,71280).
+char(o,71281).
+char(m,71282).
+char(o,71283).
+char(p,71284).
+char(4,71285).
+char(4,71286).
+char(6,71287).
+char(4,71288).
+char(p,71289).
+char(o,71290).
+char(p,71291).
+char(7,71292).
+char(6,71293).
+char(2,71294).
+char(8,71295).
+char(p,71296).
+char(o,71297).
+char(m,71298).
+char(o,71299).
+char(p,71300).
+char(o,71301).
+char(o,71302).
+char(p,71303).
+char(o,71304).
+char(8,71305).
+char(5,71306).
+char(0,71307).
+char(1,71308).
+char(m,71309).
+char(o,71310).
+char(p,71311).
+char(o,71312).
+char(m,71313).
+char(o,71314).
+char(p,71315).
+char(8,71316).
+char(4,71317).
+char(3,71318).
+char(4,71319).
+char(c,71320).
+char(c,71321).
+char(m,71322).
+char(o,71323).
+char(o,71324).
+char(m,71325).
+char(5,71326).
+char(2,71327).
+char(8,71328).
+char(8,71329).
+char(p,71330).
+char(1,71331).
+char(7,71332).
+char(8,71333).
+char(4,71334).
+char(p,71335).
+char(o,71336).
+char(7,71337).
+char(1,71338).
+char(2,71339).
+char(6,71340).
+char(c,71341).
+char(c,71342).
+char(c,71343).
+char(m,71344).
+char(5,71345).
+char(6,71346).
+char(1,71347).
+char(7,71348).
+char(c,71349).
+char(m,71350).
+char(o,71351).
+char(m,71352).
+char(6,71353).
+char(4,71354).
+char(8,71355).
+char(8,71356).
+char(c,71357).
+char(c,71358).
+char(c,71359).
+char(p,71360).
+char(2,71361).
+char(9,71362).
+char(4,71363).
+char(0,71364).
+char(c,71365).
+char(m,71366).
+char(o,71367).
+char(m,71368).
+char(8,71369).
+char(5,71370).
+char(6,71371).
+char(2,71372).
+char(c,71373).
+char(c,71374).
+char(c,71375).
+char(c,71376).
+char(p,71377).
+char(4,71378).
+char(1,71379).
+char(1,71380).
+char(8,71381).
+char(m,71382).
+char(7,71383).
+char(5,71384).
+char(7,71385).
+char(4,71386).
+char(c,71387).
+char(m,71388).
+char(1,71389).
+char(9,71390).
+char(3,71391).
+char(8,71392).
+char(m,71393).
+char(o,71394).
+char(2,71395).
+char(7,71396).
+char(3,71397).
+char(5,71398).
+char(c,71399).
+char(c,71400).
+char(c,71401).
+char(m,71402).
+char(7,71403).
+char(6,71404).
+char(9,71405).
+char(4,71406).
+char(c,71407).
+char(m,71408).
+char(3,71409).
+char(3,71410).
+char(4,71411).
+char(6,71412).
+char(c,71413).
+char(c,71414).
+char(m,71415).
+char(3,71416).
+char(7,71417).
+char(6,71418).
+char(8,71419).
+char(c,71420).
+char(p,71421).
+char(7,71422).
+char(4,71423).
+char(8,71424).
+char(6,71425).
+char(m,71426).
+char(3,71427).
+char(4,71428).
+char(9,71429).
+char(3,71430).
+char(c,71431).
+char(p,71432).
+char(6,71433).
+char(7,71434).
+char(6,71435).
+char(0,71436).
+char(c,71437).
+char(m,71438).
+char(o,71439).
+char(o,71440).
+char(m,71441).
+char(o,71442).
+char(m,71443).
+char(9,71444).
+char(2,71445).
+char(1,71446).
+char(1,71447).
+char(c,71448).
+char(c,71449).
+char(c,71450).
+char(c,71451).
+char(m,71452).
+char(o,71453).
+char(8,71454).
+char(2,71455).
+char(8,71456).
+char(1,71457).
+char(c,71458).
+char(p,71459).
+char(o,71460).
+char(p,71461).
+char(o,71462).
+char(8,71463).
+char(1,71464).
+char(5,71465).
+char(c,71466).
+char(m,71467).
+char(o,71468).
+char(5,71469).
+char(3,71470).
+char(3,71471).
+char(m,71472).
+char(o,71473).
+char(9,71474).
+char(8,71475).
+char(6,71476).
+char(4,71477).
+char(c,71478).
+char(c,71479).
+char(m,71480).
+char(5,71481).
+char(4,71482).
+char(5,71483).
+char(6,71484).
+char(c,71485).
+char(m,71486).
+char(5,71487).
+char(7,71488).
+char(6,71489).
+char(5,71490).
+char(c,71491).
+char(c,71492).
+char(c,71493).
+char(c,71494).
+char(c,71495).
+char(p,71496).
+char(6,71497).
+char(8,71498).
+char(6,71499).
+char(0,71500).
+char(c,71501).
+char(m,71502).
+char(2,71503).
+char(1,71504).
+char(1,71505).
+char(2,71506).
+char(c,71507).
+char(m,71508).
+char(6,71509).
+char(5,71510).
+char(0,71511).
+char(1,71512).
+char(p,71513).
+char(4,71514).
+char(2,71515).
+char(3,71516).
+char(0,71517).
+char(c,71518).
+char(p,71519).
+char(4,71520).
+char(0,71521).
+char(0,71522).
+char(1,71523).
+char(m,71524).
+char(9,71525).
+char(7,71526).
+char(3,71527).
+char(1,71528).
+char(m,71529).
+char(1,71530).
+char(4,71531).
+char(9,71532).
+char(8,71533).
+char(c,71534).
+char(c,71535).
+char(c,71536).
+char(c,71537).
+char(c,71538).
+char(c,71539).
+char(c,71540).
+char(p,71541).
+char(2,71542).
+char(4,71543).
+char(4,71544).
+char(3,71545).
+char(m,71546).
+char(5,71547).
+char(2,71548).
+char(2,71549).
+char(6,71550).
+char(m,71551).
+char(o,71552).
+char(p,71553).
+char(o,71554).
+char(p,71555).
+char(o,71556).
+char(p,71557).
+char(4,71558).
+char(8,71559).
+char(p,71560).
+char(o,71561).
+char(o,71562).
+char(p,71563).
+char(4,71564).
+char(0,71565).
+char(6,71566).
+char(0,71567).
+char(c,71568).
+char(c,71569).
+char(p,71570).
+char(o,71571).
+char(p,71572).
+char(7,71573).
+char(6,71574).
+char(4,71575).
+char(0,71576).
+char(p,71577).
+char(o,71578).
+char(m,71579).
+char(o,71580).
+char(p,71581).
+char(9,71582).
+char(6,71583).
+char(2,71584).
+char(7,71585).
+char(c,71586).
+char(c,71587).
+char(c,71588).
+char(c,71589).
+char(c,71590).
+char(p,71591).
+char(7,71592).
+char(5,71593).
+char(7,71594).
+char(9,71595).
+char(p,71596).
+char(o,71597).
+char(p,71598).
+char(6,71599).
+char(5,71600).
+char(1,71601).
+char(4,71602).
+char(p,71603).
+char(5,71604).
+char(3,71605).
+char(2,71606).
+char(m,71607).
+char(o,71608).
+char(7,71609).
+char(0,71610).
+char(1,71611).
+char(7,71612).
+char(m,71613).
+char(7,71614).
+char(1,71615).
+char(5,71616).
+char(9,71617).
+char(p,71618).
+char(o,71619).
+char(m,71620).
+char(9,71621).
+char(3,71622).
+char(8,71623).
+char(4,71624).
+char(c,71625).
+char(m,71626).
+char(o,71627).
+char(m,71628).
+char(o,71629).
+char(m,71630).
+char(o,71631).
+char(p,71632).
+char(1,71633).
+char(6,71634).
+char(1,71635).
+char(9,71636).
+char(c,71637).
+char(m,71638).
+char(o,71639).
+char(m,71640).
+char(o,71641).
+char(o,71642).
+char(6,71643).
+char(2,71644).
+char(4,71645).
+char(p,71646).
+char(4,71647).
+char(1,71648).
+char(7,71649).
+char(9,71650).
+char(c,71651).
+char(p,71652).
+char(3,71653).
+char(0,71654).
+char(0,71655).
+char(6,71656).
+char(c,71657).
+char(m,71658).
+char(4,71659).
+char(4,71660).
+char(5,71661).
+char(6,71662).
+char(c,71663).
+char(m,71664).
+char(4,71665).
+char(2,71666).
+char(5,71667).
+char(1,71668).
+char(m,71669).
+char(o,71670).
+char(1,71671).
+char(2,71672).
+char(3,71673).
+char(1,71674).
+char(p,71675).
+char(4,71676).
+char(5,71677).
+char(5,71678).
+char(2,71679).
+char(c,71680).
+char(c,71681).
+char(p,71682).
+char(8,71683).
+char(6,71684).
+char(2,71685).
+char(1,71686).
+char(m,71687).
+char(o,71688).
+char(4,71689).
+char(7,71690).
+char(0,71691).
+char(m,71692).
+char(5,71693).
+char(5,71694).
+char(2,71695).
+char(0,71696).
+char(m,71697).
+char(6,71698).
+char(6,71699).
+char(8,71700).
+char(2,71701).
+char(c,71702).
+char(c,71703).
+char(c,71704).
+char(c,71705).
+char(m,71706).
+char(2,71707).
+char(9,71708).
+char(3,71709).
+char(2,71710).
+char(c,71711).
+char(p,71712).
+char(o,71713).
+char(o,71714).
+char(p,71715).
+char(o,71716).
+char(p,71717).
+char(o,71718).
+char(o,71719).
+char(m,71720).
+char(1,71721).
+char(8,71722).
+char(3,71723).
+char(0,71724).
+char(p,71725).
+char(o,71726).
+char(p,71727).
+char(2,71728).
+char(1,71729).
+char(8,71730).
+char(p,71731).
+char(o,71732).
+char(6,71733).
+char(7,71734).
+char(8,71735).
+char(7,71736).
+char(c,71737).
+char(c,71738).
+char(c,71739).
+char(c,71740).
+char(c,71741).
+char(c,71742).
+char(p,71743).
+char(o,71744).
+char(p,71745).
+char(5,71746).
+char(8,71747).
+char(9,71748).
+char(8,71749).
+char(m,71750).
+char(5,71751).
+char(5,71752).
+char(0,71753).
+char(6,71754).
+char(c,71755).
+char(p,71756).
+char(1,71757).
+char(8,71758).
+char(0,71759).
+char(5,71760).
+char(m,71761).
+char(o,71762).
+char(m,71763).
+char(3,71764).
+char(1,71765).
+char(1,71766).
+char(5,71767).
+char(c,71768).
+char(p,71769).
+char(5,71770).
+char(9,71771).
+char(3,71772).
+char(9,71773).
+char(p,71774).
+char(6,71775).
+char(5,71776).
+char(3,71777).
+char(5,71778).
+char(m,71779).
+char(o,71780).
+char(o,71781).
+char(m,71782).
+char(o,71783).
+char(p,71784).
+char(o,71785).
+char(p,71786).
+char(o,71787).
+char(m,71788).
+char(1,71789).
+char(7,71790).
+char(5,71791).
+char(8,71792).
+char(c,71793).
+char(p,71794).
+char(5,71795).
+char(1,71796).
+char(2,71797).
+char(9,71798).
+char(p,71799).
+char(5,71800).
+char(2,71801).
+char(6,71802).
+char(7,71803).
+char(c,71804).
+char(c,71805).
+char(c,71806).
+char(p,71807).
+char(7,71808).
+char(0,71809).
+char(2,71810).
+char(8,71811).
+char(c,71812).
+char(c,71813).
+char(c,71814).
+char(c,71815).
+char(m,71816).
+char(4,71817).
+char(3,71818).
+char(9,71819).
+char(3,71820).
+char(p,71821).
+char(8,71822).
+char(9,71823).
+char(9,71824).
+char(4,71825).
+char(p,71826).
+char(8,71827).
+char(6,71828).
+char(1,71829).
+char(5,71830).
+char(p,71831).
+char(6,71832).
+char(5,71833).
+char(4,71834).
+char(8,71835).
+char(m,71836).
+char(3,71837).
+char(7,71838).
+char(2,71839).
+char(0,71840).
+char(p,71841).
+char(9,71842).
+char(4,71843).
+char(8,71844).
+char(c,71845).
+char(p,71846).
+char(o,71847).
+char(p,71848).
+char(o,71849).
+char(m,71850).
+char(8,71851).
+char(8,71852).
+char(4,71853).
+char(7,71854).
+char(c,71855).
+char(c,71856).
+char(p,71857).
+char(1,71858).
+char(8,71859).
+char(2,71860).
+char(2,71861).
+char(c,71862).
+char(c,71863).
+char(c,71864).
+char(p,71865).
+char(o,71866).
+char(m,71867).
+char(o,71868).
+char(p,71869).
+char(o,71870).
+char(o,71871).
+char(o,71872).
+char(2,71873).
+char(0,71874).
+char(6,71875).
+char(0,71876).
+char(c,71877).
+char(c,71878).
+char(c,71879).
+char(c,71880).
+char(c,71881).
+char(p,71882).
+char(o,71883).
+char(m,71884).
+char(1,71885).
+char(7,71886).
+char(5,71887).
+char(4,71888).
+char(c,71889).
+char(c,71890).
+char(m,71891).
+char(o,71892).
+char(p,71893).
+char(o,71894).
+char(m,71895).
+char(9,71896).
+char(6,71897).
+char(8,71898).
+char(9,71899).
+char(c,71900).
+char(p,71901).
+char(8,71902).
+char(8,71903).
+char(7,71904).
+char(3,71905).
+char(c,71906).
+char(c,71907).
+char(c,71908).
+char(c,71909).
+char(c,71910).
+char(p,71911).
+char(4,71912).
+char(6,71913).
+char(3,71914).
+char(1,71915).
+char(c,71916).
+char(p,71917).
+char(5,71918).
+char(1,71919).
+char(0,71920).
+char(2,71921).
+char(c,71922).
+char(c,71923).
+char(c,71924).
+char(c,71925).
+char(c,71926).
+char(p,71927).
+char(5,71928).
+char(4,71929).
+char(5,71930).
+char(0,71931).
+char(c,71932).
+char(c,71933).
+char(c,71934).
+char(m,71935).
+char(o,71936).
+char(p,71937).
+char(7,71938).
+char(2,71939).
+char(5,71940).
+char(5,71941).
+char(p,71942).
+char(o,71943).
+char(m,71944).
+char(8,71945).
+char(3,71946).
+char(3,71947).
+char(0,71948).
+char(c,71949).
+char(c,71950).
+char(c,71951).
+char(c,71952).
+char(m,71953).
+char(o,71954).
+char(p,71955).
+char(o,71956).
+char(2,71957).
+char(9,71958).
+char(8,71959).
+char(2,71960).
+char(m,71961).
+char(o,71962).
+char(p,71963).
+char(1,71964).
+char(0,71965).
+char(8,71966).
+char(8,71967).
+char(c,71968).
+char(c,71969).
+char(m,71970).
+char(5,71971).
+char(3,71972).
+char(3,71973).
+char(4,71974).
+char(c,71975).
+char(c,71976).
+char(c,71977).
+char(c,71978).
+char(m,71979).
+char(9,71980).
+char(0,71981).
+char(0,71982).
+char(5,71983).
+char(p,71984).
+char(o,71985).
+char(1,71986).
+char(3,71987).
+char(4,71988).
+char(3,71989).
+char(p,71990).
+char(o,71991).
+char(m,71992).
+char(6,71993).
+char(0,71994).
+char(8,71995).
+char(6,71996).
+char(c,71997).
+char(p,71998).
+char(3,71999).
+char(3,72000).
+char(9,72001).
+char(0,72002).
+char(p,72003).
+char(5,72004).
+char(3,72005).
+char(5,72006).
+char(0,72007).
+char(m,72008).
+char(o,72009).
+char(p,72010).
+char(8,72011).
+char(8,72012).
+char(3,72013).
+char(8,72014).
+char(m,72015).
+char(o,72016).
+char(9,72017).
+char(8,72018).
+char(1,72019).
+char(2,72020).
+char(c,72021).
+char(c,72022).
+char(p,72023).
+char(1,72024).
+char(7,72025).
+char(1,72026).
+char(9,72027).
+char(p,72028).
+char(3,72029).
+char(1,72030).
+char(7,72031).
+char(2,72032).
+char(c,72033).
+char(p,72034).
+char(o,72035).
+char(o,72036).
+char(p,72037).
+char(6,72038).
+char(3,72039).
+char(3,72040).
+char(3,72041).
+char(p,72042).
+char(3,72043).
+char(4,72044).
+char(8,72045).
+char(c,72046).
+char(c,72047).
+char(p,72048).
+char(o,72049).
+char(m,72050).
+char(o,72051).
+char(m,72052).
+char(3,72053).
+char(4,72054).
+char(0,72055).
+char(7,72056).
+char(p,72057).
+char(1,72058).
+char(6,72059).
+char(3,72060).
+char(6,72061).
+char(m,72062).
+char(o,72063).
+char(p,72064).
+char(2,72065).
+char(3,72066).
+char(8,72067).
+char(8,72068).
+char(m,72069).
+char(8,72070).
+char(5,72071).
+char(1,72072).
+char(6,72073).
+char(m,72074).
+char(o,72075).
+char(m,72076).
+char(o,72077).
+char(o,72078).
+char(p,72079).
+char(8,72080).
+char(2,72081).
+char(7,72082).
+char(6,72083).
+char(m,72084).
+char(o,72085).
+char(p,72086).
+char(3,72087).
+char(8,72088).
+char(6,72089).
+char(6,72090).
+char(c,72091).
+char(c,72092).
+char(p,72093).
+char(9,72094).
+char(6,72095).
+char(0,72096).
+char(0,72097).
+char(c,72098).
+char(c,72099).
+char(c,72100).
+char(c,72101).
+char(c,72102).
+char(c,72103).
+char(c,72104).
+char(c,72105).
+char(c,72106).
+char(c,72107).
+char(p,72108).
+char(9,72109).
+char(3,72110).
+char(9,72111).
+char(3,72112).
+char(m,72113).
+char(o,72114).
+char(8,72115).
+char(2,72116).
+char(0,72117).
+char(8,72118).
+char(c,72119).
+char(p,72120).
+char(o,72121).
+char(3,72122).
+char(1,72123).
+char(8,72124).
+char(6,72125).
+char(c,72126).
+char(p,72127).
+char(4,72128).
+char(1,72129).
+char(5,72130).
+char(2,72131).
+char(m,72132).
+char(o,72133).
+char(m,72134).
+char(o,72135).
+char(p,72136).
+char(8,72137).
+char(8,72138).
+char(1,72139).
+char(7,72140).
+char(p,72141).
+char(9,72142).
+char(8,72143).
+char(3,72144).
+char(0,72145).
+char(p,72146).
+char(1,72147).
+char(1,72148).
+char(1,72149).
+char(8,72150).
+char(p,72151).
+char(6,72152).
+char(4,72153).
+char(9,72154).
+char(6,72155).
+char(m,72156).
+char(3,72157).
+char(1,72158).
+char(6,72159).
+char(4,72160).
+char(c,72161).
+char(m,72162).
+char(5,72163).
+char(2,72164).
+char(3,72165).
+char(7,72166).
+char(c,72167).
+char(p,72168).
+char(o,72169).
+char(p,72170).
+char(o,72171).
+char(p,72172).
+char(o,72173).
+char(6,72174).
+char(2,72175).
+char(5,72176).
+char(4,72177).
+char(m,72178).
+char(9,72179).
+char(8,72180).
+char(0,72181).
+char(6,72182).
+char(c,72183).
+char(m,72184).
+char(o,72185).
+char(m,72186).
+char(o,72187).
+char(m,72188).
+char(o,72189).
+char(8,72190).
+char(3,72191).
+char(2,72192).
+char(7,72193).
+char(m,72194).
+char(o,72195).
+char(p,72196).
+char(4,72197).
+char(1,72198).
+char(0,72199).
+char(0,72200).
+char(c,72201).
+char(c,72202).
+char(c,72203).
+char(m,72204).
+char(o,72205).
+char(p,72206).
+char(4,72207).
+char(7,72208).
+char(9,72209).
+char(9,72210).
+char(c,72211).
+char(c,72212).
+char(p,72213).
+char(o,72214).
+char(o,72215).
+char(p,72216).
+char(4,72217).
+char(3,72218).
+char(0,72219).
+char(1,72220).
+char(c,72221).
+char(m,72222).
+char(9,72223).
+char(3,72224).
+char(2,72225).
+char(4,72226).
+char(c,72227).
+char(p,72228).
+char(3,72229).
+char(7,72230).
+char(9,72231).
+char(6,72232).
+char(m,72233).
+char(o,72234).
+char(p,72235).
+char(o,72236).
+char(4,72237).
+char(3,72238).
+char(4,72239).
+char(1,72240).
+char(m,72241).
+char(5,72242).
+char(5,72243).
+char(9,72244).
+char(0,72245).
+char(m,72246).
+char(1,72247).
+char(9,72248).
+char(7,72249).
+char(6,72250).
+char(c,72251).
+char(m,72252).
+char(3,72253).
+char(8,72254).
+char(1,72255).
+char(2,72256).
+char(c,72257).
+char(m,72258).
+char(3,72259).
+char(3,72260).
+char(7,72261).
+char(5,72262).
+char(m,72263).
+char(o,72264).
+char(p,72265).
+char(2,72266).
+char(9,72267).
+char(4,72268).
+char(4,72269).
+char(c,72270).
+char(p,72271).
+char(0,72272).
+char(p,72273).
+char(3,72274).
+char(6,72275).
+char(5,72276).
+char(9,72277).
+char(p,72278).
+char(1,72279).
+char(4,72280).
+char(2,72281).
+char(5,72282).
+char(c,72283).
+char(m,72284).
+char(2,72285).
+char(4,72286).
+char(7,72287).
+char(1,72288).
+char(p,72289).
+char(o,72290).
+char(3,72291).
+char(4,72292).
+char(9,72293).
+char(4,72294).
+char(c,72295).
+char(m,72296).
+char(o,72297).
+char(2,72298).
+char(6,72299).
+char(8,72300).
+char(5,72301).
+char(c,72302).
+char(c,72303).
+char(m,72304).
+char(o,72305).
+char(p,72306).
+char(4,72307).
+char(5,72308).
+char(9,72309).
+char(5,72310).
+char(p,72311).
+char(o,72312).
+char(p,72313).
+char(8,72314).
+char(1,72315).
+char(6,72316).
+char(5,72317).
+char(m,72318).
+char(o,72319).
+char(m,72320).
+char(o,72321).
+char(m,72322).
+char(1,72323).
+char(3,72324).
+char(6,72325).
+char(m,72326).
+char(2,72327).
+char(3,72328).
+char(6,72329).
+char(6,72330).
+char(c,72331).
+char(c,72332).
+char(c,72333).
+char(p,72334).
+char(o,72335).
+char(o,72336).
+char(o,72337).
+char(p,72338).
+char(o,72339).
+char(p,72340).
+char(2,72341).
+char(4,72342).
+char(1,72343).
+char(1,72344).
+char(c,72345).
+char(c,72346).
+char(c,72347).
+char(p,72348).
+char(7,72349).
+char(3,72350).
+char(5,72351).
+char(6,72352).
+char(m,72353).
+char(2,72354).
+char(0,72355).
+char(1,72356).
+char(5,72357).
+char(p,72358).
+char(o,72359).
+char(p,72360).
+char(8,72361).
+char(6,72362).
+char(6,72363).
+char(0,72364).
+char(c,72365).
+char(p,72366).
+char(o,72367).
+char(9,72368).
+char(1,72369).
+char(5,72370).
+char(9,72371).
+char(p,72372).
+char(o,72373).
+char(m,72374).
+char(1,72375).
+char(6,72376).
+char(3,72377).
+char(2,72378).
+char(p,72379).
+char(o,72380).
+char(m,72381).
+char(8,72382).
+char(2,72383).
+char(8,72384).
+char(0,72385).
+char(p,72386).
+char(7,72387).
+char(4,72388).
+char(3,72389).
+char(6,72390).
+char(c,72391).
+char(c,72392).
+char(c,72393).
+char(c,72394).
+char(p,72395).
+char(o,72396).
+char(o,72397).
+char(p,72398).
+char(o,72399).
+char(m,72400).
+char(o,72401).
+char(m,72402).
+char(o,72403).
+char(p,72404).
+char(1,72405).
+char(2,72406).
+char(4,72407).
+char(7,72408).
+char(c,72409).
+char(c,72410).
+char(c,72411).
+char(c,72412).
+char(c,72413).
+char(m,72414).
+char(o,72415).
+char(p,72416).
+char(6,72417).
+char(1,72418).
+char(4,72419).
+char(1,72420).
+char(p,72421).
+char(o,72422).
+char(p,72423).
+char(2,72424).
+char(1,72425).
+char(0,72426).
+char(3,72427).
+char(p,72428).
+char(o,72429).
+char(o,72430).
+char(m,72431).
+char(7,72432).
+char(7,72433).
+char(0,72434).
+char(4,72435).
+char(c,72436).
+char(c,72437).
+char(c,72438).
+char(c,72439).
+char(c,72440).
+char(c,72441).
+char(p,72442).
+char(o,72443).
+char(1,72444).
+char(7,72445).
+char(8,72446).
+char(3,72447).
+char(p,72448).
+char(o,72449).
+char(m,72450).
+char(o,72451).
+char(p,72452).
+char(9,72453).
+char(9,72454).
+char(0,72455).
+char(5,72456).
+char(c,72457).
+char(c,72458).
+char(c,72459).
+char(c,72460).
+char(p,72461).
+char(6,72462).
+char(7,72463).
+char(7,72464).
+char(9,72465).
+char(p,72466).
+char(2,72467).
+char(8,72468).
+char(7,72469).
+char(4,72470).
+char(m,72471).
+char(o,72472).
+char(p,72473).
+char(o,72474).
+char(p,72475).
+char(6,72476).
+char(5,72477).
+char(7,72478).
+char(9,72479).
+char(c,72480).
+char(p,72481).
+char(o,72482).
+char(o,72483).
+char(p,72484).
+char(2,72485).
+char(2,72486).
+char(4,72487).
+char(9,72488).
+char(p,72489).
+char(o,72490).
+char(m,72491).
+char(o,72492).
+char(9,72493).
+char(5,72494).
+char(6,72495).
+char(3,72496).
+char(m,72497).
+char(4,72498).
+char(3,72499).
+char(5,72500).
+char(9,72501).
+char(p,72502).
+char(8,72503).
+char(4,72504).
+char(5,72505).
+char(2,72506).
+char(p,72507).
+char(7,72508).
+char(1,72509).
+char(6,72510).
+char(4,72511).
+char(p,72512).
+char(o,72513).
+char(p,72514).
+char(o,72515).
+char(p,72516).
+char(o,72517).
+char(1,72518).
+char(4,72519).
+char(4,72520).
+char(5,72521).
+char(c,72522).
+char(m,72523).
+char(8,72524).
+char(7,72525).
+char(0,72526).
+char(3,72527).
+char(m,72528).
+char(3,72529).
+char(1,72530).
+char(1,72531).
+char(4,72532).
+char(c,72533).
+char(p,72534).
+char(o,72535).
+char(m,72536).
+char(2,72537).
+char(0,72538).
+char(3,72539).
+char(0,72540).
+char(c,72541).
+char(c,72542).
+char(c,72543).
+char(p,72544).
+char(1,72545).
+char(8,72546).
+char(5,72547).
+char(4,72548).
+char(c,72549).
+char(m,72550).
+char(o,72551).
+char(p,72552).
+char(o,72553).
+char(6,72554).
+char(7,72555).
+char(6,72556).
+char(3,72557).
+char(c,72558).
+char(c,72559).
+char(p,72560).
+char(3,72561).
+char(5,72562).
+char(1,72563).
+char(8,72564).
+char(c,72565).
+char(c,72566).
+char(c,72567).
+char(p,72568).
+char(7,72569).
+char(3,72570).
+char(7,72571).
+char(6,72572).
+char(c,72573).
+char(c,72574).
+char(p,72575).
+char(o,72576).
+char(6,72577).
+char(3,72578).
+char(2,72579).
+char(4,72580).
+char(c,72581).
+char(c,72582).
+char(m,72583).
+char(o,72584).
+char(p,72585).
+char(3,72586).
+char(4,72587).
+char(9,72588).
+char(1,72589).
+char(m,72590).
+char(o,72591).
+char(p,72592).
+char(8,72593).
+char(7,72594).
+char(3,72595).
+char(2,72596).
+char(c,72597).
+char(c,72598).
+char(p,72599).
+char(4,72600).
+char(8,72601).
+char(5,72602).
+char(0,72603).
+char(m,72604).
+char(o,72605).
+char(p,72606).
+char(o,72607).
+char(o,72608).
+char(o,72609).
+char(7,72610).
+char(3,72611).
+char(8,72612).
+char(7,72613).
+char(c,72614).
+char(c,72615).
+char(m,72616).
+char(6,72617).
+char(7,72618).
+char(2,72619).
+char(9,72620).
+char(c,72621).
+char(c,72622).
+char(p,72623).
+char(o,72624).
+char(m,72625).
+char(1,72626).
+char(9,72627).
+char(1,72628).
+char(8,72629).
+char(p,72630).
+char(9,72631).
+char(2,72632).
+char(9,72633).
+char(5,72634).
+char(c,72635).
+char(c,72636).
+char(p,72637).
+char(6,72638).
+char(4,72639).
+char(7,72640).
+char(6,72641).
+char(m,72642).
+char(7,72643).
+char(2,72644).
+char(9,72645).
+char(9,72646).
+char(p,72647).
+char(7,72648).
+char(4,72649).
+char(5,72650).
+char(8,72651).
+char(c,72652).
+char(c,72653).
+char(p,72654).
+char(4,72655).
+char(2,72656).
+char(2,72657).
+char(6,72658).
+char(p,72659).
+char(4,72660).
+char(1,72661).
+char(9,72662).
+char(2,72663).
+char(m,72664).
+char(5,72665).
+char(4,72666).
+char(3,72667).
+char(6,72668).
+char(c,72669).
+char(c,72670).
+char(c,72671).
+char(m,72672).
+char(o,72673).
+char(p,72674).
+char(1,72675).
+char(2,72676).
+char(1,72677).
+char(5,72678).
+char(c,72679).
+char(p,72680).
+char(o,72681).
+char(o,72682).
+char(p,72683).
+char(o,72684).
+char(m,72685).
+char(o,72686).
+char(m,72687).
+char(1,72688).
+char(1,72689).
+char(1,72690).
+char(1,72691).
+char(m,72692).
+char(6,72693).
+char(7,72694).
+char(2,72695).
+char(9,72696).
+char(m,72697).
+char(6,72698).
+char(3,72699).
+char(1,72700).
+char(9,72701).
+char(m,72702).
+char(3,72703).
+char(9,72704).
+char(0,72705).
+char(2,72706).
+char(m,72707).
+char(1,72708).
+char(9,72709).
+char(2,72710).
+char(3,72711).
+char(c,72712).
+char(c,72713).
+char(p,72714).
+char(4,72715).
+char(3,72716).
+char(2,72717).
+char(9,72718).
+char(c,72719).
+char(p,72720).
+char(4,72721).
+char(4,72722).
+char(2,72723).
+char(3,72724).
+char(m,72725).
+char(o,72726).
+char(p,72727).
+char(o,72728).
+char(1,72729).
+char(8,72730).
+char(5,72731).
+char(1,72732).
+char(p,72733).
+char(7,72734).
+char(5,72735).
+char(4,72736).
+char(0,72737).
+char(c,72738).
+char(m,72739).
+char(o,72740).
+char(p,72741).
+char(o,72742).
+char(p,72743).
+char(o,72744).
+char(p,72745).
+char(o,72746).
+char(o,72747).
+char(p,72748).
+char(o,72749).
+char(m,72750).
+char(3,72751).
+char(1,72752).
+char(8,72753).
+char(5,72754).
+char(c,72755).
+char(m,72756).
+char(8,72757).
+char(3,72758).
+char(7,72759).
+char(5,72760).
+char(m,72761).
+char(8,72762).
+char(1,72763).
+char(1,72764).
+char(8,72765).
+char(c,72766).
+char(p,72767).
+char(2,72768).
+char(0,72769).
+char(0,72770).
+char(5,72771).
+char(c,72772).
+char(c,72773).
+char(c,72774).
+char(p,72775).
+char(6,72776).
+char(9,72777).
+char(5,72778).
+char(8,72779).
+char(c,72780).
+char(m,72781).
+char(4,72782).
+char(9,72783).
+char(4,72784).
+char(2,72785).
+char(m,72786).
+char(o,72787).
+char(m,72788).
+char(o,72789).
+char(p,72790).
+char(o,72791).
+char(m,72792).
+char(3,72793).
+char(6,72794).
+char(4,72795).
+char(5,72796).
+char(p,72797).
+char(o,72798).
+char(p,72799).
+char(5,72800).
+char(4,72801).
+char(8,72802).
+char(7,72803).
+char(c,72804).
+char(c,72805).
+char(c,72806).
+char(m,72807).
+char(o,72808).
+char(p,72809).
+char(3,72810).
+char(2,72811).
+char(9,72812).
+char(1,72813).
+char(c,72814).
+char(c,72815).
+char(c,72816).
+char(m,72817).
+char(1,72818).
+char(6,72819).
+char(4,72820).
+char(0,72821).
+char(c,72822).
+char(c,72823).
+char(c,72824).
+char(c,72825).
+char(c,72826).
+char(p,72827).
+char(7,72828).
+char(8,72829).
+char(7,72830).
+char(3,72831).
+char(m,72832).
+char(o,72833).
+char(m,72834).
+char(o,72835).
+char(5,72836).
+char(3,72837).
+char(7,72838).
+char(0,72839).
+char(c,72840).
+char(c,72841).
+char(m,72842).
+char(1,72843).
+char(0,72844).
+char(3,72845).
+char(9,72846).
+char(c,72847).
+char(m,72848).
+char(2,72849).
+char(5,72850).
+char(4,72851).
+char(0,72852).
+char(c,72853).
+char(c,72854).
+char(p,72855).
+char(o,72856).
+char(m,72857).
+char(9,72858).
+char(7,72859).
+char(6,72860).
+char(7,72861).
+char(c,72862).
+char(c,72863).
+char(m,72864).
+char(1,72865).
+char(5,72866).
+char(7,72867).
+char(8,72868).
+char(c,72869).
+char(p,72870).
+char(8,72871).
+char(3,72872).
+char(9,72873).
+char(3,72874).
+char(c,72875).
+char(p,72876).
+char(o,72877).
+char(m,72878).
+char(o,72879).
+char(o,72880).
+char(4,72881).
+char(1,72882).
+char(8,72883).
+char(5,72884).
+char(p,72885).
+char(7,72886).
+char(6,72887).
+char(9,72888).
+char(3,72889).
+char(c,72890).
+char(m,72891).
+char(o,72892).
+char(6,72893).
+char(4,72894).
+char(9,72895).
+char(p,72896).
+char(o,72897).
+char(p,72898).
+char(o,72899).
+char(m,72900).
+char(o,72901).
+char(m,72902).
+char(1,72903).
+char(0,72904).
+char(3,72905).
+char(6,72906).
+char(m,72907).
+char(o,72908).
+char(1,72909).
+char(5,72910).
+char(0,72911).
+char(7,72912).
+char(c,72913).
+char(m,72914).
+char(o,72915).
+char(p,72916).
+char(6,72917).
+char(3,72918).
+char(7,72919).
+char(p,72920).
+char(3,72921).
+char(8,72922).
+char(3,72923).
+char(3,72924).
+char(c,72925).
+char(c,72926).
+char(p,72927).
+char(o,72928).
+char(2,72929).
+char(4,72930).
+char(8,72931).
+char(9,72932).
+char(p,72933).
+char(5,72934).
+char(1,72935).
+char(1,72936).
+char(9,72937).
+char(m,72938).
+char(6,72939).
+char(9,72940).
+char(4,72941).
+char(8,72942).
+char(p,72943).
+char(o,72944).
+char(p,72945).
+char(7,72946).
+char(9,72947).
+char(9,72948).
+char(8,72949).
+char(c,72950).
+char(c,72951).
+char(p,72952).
+char(5,72953).
+char(8,72954).
+char(7,72955).
+char(8,72956).
+char(m,72957).
+char(o,72958).
+char(m,72959).
+char(3,72960).
+char(2,72961).
+char(0,72962).
+char(m,72963).
+char(9,72964).
+char(5,72965).
+char(9,72966).
+char(3,72967).
+char(c,72968).
+char(p,72969).
+char(1,72970).
+char(2,72971).
+char(6,72972).
+char(6,72973).
+char(m,72974).
+char(o,72975).
+char(p,72976).
+char(o,72977).
+char(o,72978).
+char(m,72979).
+char(o,72980).
+char(p,72981).
+char(9,72982).
+char(4,72983).
+char(9,72984).
+char(1,72985).
+char(c,72986).
+char(m,72987).
+char(o,72988).
+char(m,72989).
+char(o,72990).
+char(m,72991).
+char(4,72992).
+char(2,72993).
+char(2,72994).
+char(3,72995).
+char(c,72996).
+char(p,72997).
+char(2,72998).
+char(3,72999).
+char(3,73000).
+char(8,73001).
+char(m,73002).
+char(5,73003).
+char(6,73004).
+char(9,73005).
+char(0,73006).
+char(p,73007).
+char(o,73008).
+char(p,73009).
+char(3,73010).
+char(1,73011).
+char(8,73012).
+char(8,73013).
+char(m,73014).
+char(2,73015).
+char(7,73016).
+char(7,73017).
+char(0,73018).
+char(c,73019).
+char(m,73020).
+char(o,73021).
+char(o,73022).
+char(p,73023).
+char(9,73024).
+char(4,73025).
+char(5,73026).
+char(9,73027).
+char(c,73028).
+char(c,73029).
+char(c,73030).
+char(c,73031).
+char(c,73032).
+char(c,73033).
+char(c,73034).
+char(p,73035).
+char(5,73036).
+char(2,73037).
+char(3,73038).
+char(0,73039).
+char(c,73040).
+char(p,73041).
+char(7,73042).
+char(7,73043).
+char(5,73044).
+char(4,73045).
+char(p,73046).
+char(2,73047).
+char(8,73048).
+char(9,73049).
+char(0,73050).
+char(c,73051).
+char(c,73052).
+char(c,73053).
+char(c,73054).
+char(c,73055).
+char(p,73056).
+char(3,73057).
+char(7,73058).
+char(8,73059).
+char(2,73060).
+char(c,73061).
+char(p,73062).
+char(o,73063).
+char(p,73064).
+char(o,73065).
+char(p,73066).
+char(o,73067).
+char(m,73068).
+char(o,73069).
+char(m,73070).
+char(3,73071).
+char(6,73072).
+char(6,73073).
+char(9,73074).
+char(p,73075).
+char(1,73076).
+char(1,73077).
+char(0,73078).
+char(c,73079).
+char(c,73080).
+char(c,73081).
+char(c,73082).
+char(c,73083).
+char(c,73084).
+char(p,73085).
+char(o,73086).
+char(3,73087).
+char(1,73088).
+char(4,73089).
+char(6,73090).
+char(m,73091).
+char(1,73092).
+char(2,73093).
+char(7,73094).
+char(9,73095).
+char(c,73096).
+char(c,73097).
+char(m,73098).
+char(o,73099).
+char(m,73100).
+char(7,73101).
+char(6,73102).
+char(8,73103).
+char(7,73104).
+char(p,73105).
+char(o,73106).
+char(p,73107).
+char(o,73108).
+char(1,73109).
+char(3,73110).
+char(5,73111).
+char(7,73112).
+char(p,73113).
+char(9,73114).
+char(9,73115).
+char(3,73116).
+char(5,73117).
+char(c,73118).
+char(p,73119).
+char(o,73120).
+char(o,73121).
+char(p,73122).
+char(1,73123).
+char(2,73124).
+char(2,73125).
+char(1,73126).
+char(m,73127).
+char(o,73128).
+char(m,73129).
+char(o,73130).
+char(m,73131).
+char(o,73132).
+char(p,73133).
+char(7,73134).
+char(7,73135).
+char(3,73136).
+char(7,73137).
+char(c,73138).
+char(p,73139).
+char(o,73140).
+char(m,73141).
+char(o,73142).
+char(o,73143).
+char(p,73144).
+char(6,73145).
+char(5,73146).
+char(8,73147).
+char(5,73148).
+char(c,73149).
+char(m,73150).
+char(6,73151).
+char(0,73152).
+char(9,73153).
+char(5,73154).
+char(m,73155).
+char(8,73156).
+char(2,73157).
+char(8,73158).
+char(1,73159).
+char(m,73160).
+char(o,73161).
+char(7,73162).
+char(8,73163).
+char(0,73164).
+char(5,73165).
+char(c,73166).
+char(m,73167).
+char(o,73168).
+char(2,73169).
+char(4,73170).
+char(1,73171).
+char(6,73172).
+char(p,73173).
+char(8,73174).
+char(3,73175).
+char(9,73176).
+char(8,73177).
+char(c,73178).
+char(c,73179).
+char(c,73180).
+char(c,73181).
+char(m,73182).
+char(9,73183).
+char(4,73184).
+char(7,73185).
+char(9,73186).
+char(c,73187).
+char(c,73188).
+char(p,73189).
+char(9,73190).
+char(6,73191).
+char(2,73192).
+char(4,73193).
+char(c,73194).
+char(p,73195).
+char(o,73196).
+char(9,73197).
+char(9,73198).
+char(0,73199).
+char(7,73200).
+char(p,73201).
+char(4,73202).
+char(9,73203).
+char(0,73204).
+char(6,73205).
+char(c,73206).
+char(c,73207).
+char(c,73208).
+char(c,73209).
+char(c,73210).
+char(p,73211).
+char(4,73212).
+char(8,73213).
+char(8,73214).
+char(1,73215).
+char(c,73216).
+char(m,73217).
+char(1,73218).
+char(1,73219).
+char(1,73220).
+char(0,73221).
+char(m,73222).
+char(3,73223).
+char(9,73224).
+char(5,73225).
+char(2,73226).
+char(c,73227).
+char(m,73228).
+char(o,73229).
+char(p,73230).
+char(2,73231).
+char(8,73232).
+char(3,73233).
+char(3,73234).
+char(m,73235).
+char(9,73236).
+char(7,73237).
+char(7,73238).
+char(9,73239).
+char(c,73240).
+char(c,73241).
+char(c,73242).
+char(p,73243).
+char(9,73244).
+char(8,73245).
+char(6,73246).
+char(1,73247).
+char(c,73248).
+char(p,73249).
+char(o,73250).
+char(m,73251).
+char(o,73252).
+char(3,73253).
+char(4,73254).
+char(3,73255).
+char(5,73256).
+char(c,73257).
+char(p,73258).
+char(o,73259).
+char(p,73260).
+char(o,73261).
+char(p,73262).
+char(o,73263).
+char(6,73264).
+char(1,73265).
+char(4,73266).
+char(8,73267).
+char(c,73268).
+char(c,73269).
+char(m,73270).
+char(3,73271).
+char(7,73272).
+char(6,73273).
+char(4,73274).
+char(m,73275).
+char(o,73276).
+char(m,73277).
+char(o,73278).
+char(p,73279).
+char(o,73280).
+char(p,73281).
+char(o,73282).
+char(1,73283).
+char(2,73284).
+char(8,73285).
+char(6,73286).
+char(c,73287).
+char(m,73288).
+char(2,73289).
+char(9,73290).
+char(1,73291).
+char(9,73292).
+char(c,73293).
+char(p,73294).
+char(4,73295).
+char(7,73296).
+char(1,73297).
+char(7,73298).
+char(c,73299).
+char(c,73300).
+char(c,73301).
+char(c,73302).
+char(c,73303).
+char(c,73304).
+char(c,73305).
+char(c,73306).
+char(p,73307).
+char(o,73308).
+char(m,73309).
+char(1,73310).
+char(2,73311).
+char(2,73312).
+char(c,73313).
+char(m,73314).
+char(o,73315).
+char(p,73316).
+char(o,73317).
+char(o,73318).
+char(o,73319).
+char(m,73320).
+char(8,73321).
+char(6,73322).
+char(2,73323).
+char(8,73324).
+char(m,73325).
+char(3,73326).
+char(9,73327).
+char(6,73328).
+char(7,73329).
+char(c,73330).
+char(c,73331).
+char(m,73332).
+char(3,73333).
+char(4,73334).
+char(2,73335).
+char(5,73336).
+char(c,73337).
+char(p,73338).
+char(6,73339).
+char(6,73340).
+char(7,73341).
+char(9,73342).
+char(c,73343).
+char(m,73344).
+char(o,73345).
+char(4,73346).
+char(5,73347).
+char(1,73348).
+char(1,73349).
+char(p,73350).
+char(3,73351).
+char(1,73352).
+char(5,73353).
+char(7,73354).
+char(m,73355).
+char(2,73356).
+char(7,73357).
+char(3,73358).
+char(5,73359).
+char(m,73360).
+char(o,73361).
+char(p,73362).
+char(o,73363).
+char(p,73364).
+char(o,73365).
+char(m,73366).
+char(1,73367).
+char(9,73368).
+char(2,73369).
+char(5,73370).
+char(m,73371).
+char(3,73372).
+char(1,73373).
+char(8,73374).
+char(8,73375).
+char(p,73376).
+char(4,73377).
+char(2,73378).
+char(5,73379).
+char(3,73380).
+char(c,73381).
+char(p,73382).
+char(o,73383).
+char(o,73384).
+char(o,73385).
+char(o,73386).
+char(o,73387).
+char(o,73388).
+char(m,73389).
+char(o,73390).
+char(o,73391).
+char(m,73392).
+char(o,73393).
+char(p,73394).
+char(o,73395).
+char(o,73396).
+char(p,73397).
+char(o,73398).
+char(p,73399).
+char(8,73400).
+char(0,73401).
+char(0,73402).
+char(9,73403).
+char(c,73404).
+char(c,73405).
+char(p,73406).
+char(o,73407).
+char(m,73408).
+char(o,73409).
+char(m,73410).
+char(2,73411).
+char(8,73412).
+char(2,73413).
+char(3,73414).
+char(m,73415).
+char(o,73416).
+char(p,73417).
+char(7,73418).
+char(9,73419).
+char(9,73420).
+char(2,73421).
+char(c,73422).
+char(c,73423).
+char(m,73424).
+char(5,73425).
+char(5,73426).
+char(6,73427).
+char(m,73428).
+char(o,73429).
+char(p,73430).
+char(2,73431).
+char(5,73432).
+char(1,73433).
+char(9,73434).
+char(c,73435).
+char(m,73436).
+char(o,73437).
+char(2,73438).
+char(2,73439).
+char(5,73440).
+char(1,73441).
+char(c,73442).
+char(c,73443).
+char(p,73444).
+char(2,73445).
+char(9,73446).
+char(9,73447).
+char(5,73448).
+char(c,73449).
+char(c,73450).
+char(c,73451).
+char(m,73452).
+char(o,73453).
+char(m,73454).
+char(2,73455).
+char(9,73456).
+char(3,73457).
+char(m,73458).
+char(8,73459).
+char(9,73460).
+char(1,73461).
+char(5,73462).
+char(p,73463).
+char(8,73464).
+char(7,73465).
+char(6,73466).
+char(5,73467).
+char(p,73468).
+char(o,73469).
+char(o,73470).
+char(m,73471).
+char(o,73472).
+char(p,73473).
+char(o,73474).
+char(o,73475).
+char(m,73476).
+char(1,73477).
+char(5,73478).
+char(6,73479).
+char(3,73480).
+char(p,73481).
+char(o,73482).
+char(2,73483).
+char(5,73484).
+char(1,73485).
+char(0,73486).
+char(c,73487).
+char(c,73488).
+char(p,73489).
+char(8,73490).
+char(6,73491).
+char(8,73492).
+char(4,73493).
+char(c,73494).
+char(c,73495).
+char(c,73496).
+char(p,73497).
+char(o,73498).
+char(m,73499).
+char(o,73500).
+char(p,73501).
+char(8,73502).
+char(5,73503).
+char(1,73504).
+char(8,73505).
+char(c,73506).
+char(m,73507).
+char(1,73508).
+char(5,73509).
+char(2,73510).
+char(9,73511).
+char(c,73512).
+char(c,73513).
+char(c,73514).
+char(m,73515).
+char(o,73516).
+char(p,73517).
+char(o,73518).
+char(p,73519).
+char(8,73520).
+char(5,73521).
+char(8,73522).
+char(4,73523).
+char(c,73524).
+char(c,73525).
+char(c,73526).
+char(p,73527).
+char(2,73528).
+char(1,73529).
+char(1,73530).
+char(2,73531).
+char(m,73532).
+char(o,73533).
+char(m,73534).
+char(5,73535).
+char(6,73536).
+char(3,73537).
+char(6,73538).
+char(c,73539).
+char(c,73540).
+char(m,73541).
+char(6,73542).
+char(7,73543).
+char(4,73544).
+char(7,73545).
+char(p,73546).
+char(8,73547).
+char(7,73548).
+char(2,73549).
+char(1,73550).
+char(p,73551).
+char(o,73552).
+char(o,73553).
+char(o,73554).
+char(p,73555).
+char(o,73556).
+char(m,73557).
+char(o,73558).
+char(o,73559).
+char(m,73560).
+char(9,73561).
+char(2,73562).
+char(4,73563).
+char(6,73564).
+char(c,73565).
+char(m,73566).
+char(o,73567).
+char(m,73568).
+char(4,73569).
+char(0,73570).
+char(9,73571).
+char(6,73572).
+char(m,73573).
+char(6,73574).
+char(0,73575).
+char(6,73576).
+char(4,73577).
+char(c,73578).
+char(m,73579).
+char(8,73580).
+char(3,73581).
+char(3,73582).
+char(5,73583).
+char(c,73584).
+char(p,73585).
+char(1,73586).
+char(3,73587).
+char(9,73588).
+char(6,73589).
+char(p,73590).
+char(o,73591).
+char(m,73592).
+char(6,73593).
+char(7,73594).
+char(5,73595).
+char(9,73596).
+char(p,73597).
+char(6,73598).
+char(8,73599).
+char(1,73600).
+char(8,73601).
+char(c,73602).
+char(c,73603).
+char(m,73604).
+char(4,73605).
+char(6,73606).
+char(7,73607).
+char(9,73608).
+char(c,73609).
+char(p,73610).
+char(6,73611).
+char(4,73612).
+char(1,73613).
+char(5,73614).
+char(p,73615).
+char(o,73616).
+char(m,73617).
+char(3,73618).
+char(8,73619).
+char(6,73620).
+char(4,73621).
+char(m,73622).
+char(o,73623).
+char(4,73624).
+char(2,73625).
+char(2,73626).
+char(2,73627).
+char(p,73628).
+char(o,73629).
+char(o,73630).
+char(p,73631).
+char(o,73632).
+char(p,73633).
+char(9,73634).
+char(6,73635).
+char(4,73636).
+char(5,73637).
+char(c,73638).
+char(c,73639).
+char(p,73640).
+char(o,73641).
+char(m,73642).
+char(o,73643).
+char(m,73644).
+char(3,73645).
+char(5,73646).
+char(2,73647).
+char(5,73648).
+char(c,73649).
+char(c,73650).
+char(c,73651).
+char(c,73652).
+char(m,73653).
+char(o,73654).
+char(m,73655).
+char(8,73656).
+char(8,73657).
+char(8,73658).
+char(0,73659).
+char(p,73660).
+char(7,73661).
+char(6,73662).
+char(2,73663).
+char(3,73664).
+char(p,73665).
+char(8,73666).
+char(4,73667).
+char(6,73668).
+char(3,73669).
+char(c,73670).
+char(c,73671).
+char(c,73672).
+char(c,73673).
+char(c,73674).
+char(p,73675).
+char(9,73676).
+char(0,73677).
+char(8,73678).
+char(8,73679).
+char(p,73680).
+char(o,73681).
+char(8,73682).
+char(1,73683).
+char(3,73684).
+char(c,73685).
+char(m,73686).
+char(1,73687).
+char(4,73688).
+char(7,73689).
+char(2,73690).
+char(c,73691).
+char(m,73692).
+char(8,73693).
+char(4,73694).
+char(0,73695).
+char(5,73696).
+char(p,73697).
+char(o,73698).
+char(m,73699).
+char(6,73700).
+char(6,73701).
+char(9,73702).
+char(1,73703).
+char(p,73704).
+char(o,73705).
+char(m,73706).
+char(o,73707).
+char(m,73708).
+char(9,73709).
+char(7,73710).
+char(2,73711).
+char(3,73712).
+char(m,73713).
+char(3,73714).
+char(2,73715).
+char(9,73716).
+char(6,73717).
+char(c,73718).
+char(c,73719).
+char(m,73720).
+char(4,73721).
+char(0,73722).
+char(8,73723).
+char(4,73724).
+char(m,73725).
+char(o,73726).
+char(7,73727).
+char(9,73728).
+char(5,73729).
+char(8,73730).
+char(p,73731).
+char(o,73732).
+char(p,73733).
+char(o,73734).
+char(m,73735).
+char(5,73736).
+char(5,73737).
+char(1,73738).
+char(5,73739).
+char(p,73740).
+char(o,73741).
+char(m,73742).
+char(o,73743).
+char(o,73744).
+char(o,73745).
+char(m,73746).
+char(3,73747).
+char(3,73748).
+char(7,73749).
+char(7,73750).
+char(c,73751).
+char(p,73752).
+char(2,73753).
+char(6,73754).
+char(2,73755).
+char(c,73756).
+char(c,73757).
+char(m,73758).
+char(o,73759).
+char(5,73760).
+char(4,73761).
+char(6,73762).
+char(c,73763).
+char(p,73764).
+char(7,73765).
+char(1,73766).
+char(4,73767).
+char(1,73768).
+char(c,73769).
+char(c,73770).
+char(p,73771).
+char(8,73772).
+char(0,73773).
+char(0,73774).
+char(4,73775).
+char(c,73776).
+char(c,73777).
+char(c,73778).
+char(c,73779).
+char(m,73780).
+char(o,73781).
+char(2,73782).
+char(5,73783).
+char(2,73784).
+char(0,73785).
+char(c,73786).
+char(m,73787).
+char(8,73788).
+char(9,73789).
+char(6,73790).
+char(5,73791).
+char(m,73792).
+char(o,73793).
+char(p,73794).
+char(o,73795).
+char(o,73796).
+char(o,73797).
+char(o,73798).
+char(o,73799).
+char(o,73800).
+char(m,73801).
+char(5,73802).
+char(7,73803).
+char(6,73804).
+char(1,73805).
+char(p,73806).
+char(o,73807).
+char(m,73808).
+char(9,73809).
+char(0,73810).
+char(4,73811).
+char(5,73812).
+char(p,73813).
+char(7,73814).
+char(0,73815).
+char(4,73816).
+char(9,73817).
+char(c,73818).
+char(p,73819).
+char(o,73820).
+char(p,73821).
+char(o,73822).
+char(m,73823).
+char(o,73824).
+char(o,73825).
+char(6,73826).
+char(2,73827).
+char(5,73828).
+char(5,73829).
+char(m,73830).
+char(o,73831).
+char(p,73832).
+char(1,73833).
+char(2,73834).
+char(2,73835).
+char(8,73836).
+char(c,73837).
+char(p,73838).
+char(o,73839).
+char(p,73840).
+char(o,73841).
+char(p,73842).
+char(6,73843).
+char(5,73844).
+char(3,73845).
+char(1,73846).
+char(p,73847).
+char(1,73848).
+char(0,73849).
+char(2,73850).
+char(8,73851).
+char(c,73852).
+char(m,73853).
+char(o,73854).
+char(m,73855).
+char(o,73856).
+char(9,73857).
+char(1,73858).
+char(5,73859).
+char(1,73860).
+char(c,73861).
+char(p,73862).
+char(4,73863).
+char(9,73864).
+char(0,73865).
+char(7,73866).
+char(p,73867).
+char(6,73868).
+char(1,73869).
+char(7,73870).
+char(6,73871).
+char(c,73872).
+char(c,73873).
+char(p,73874).
+char(o,73875).
+char(2,73876).
+char(0,73877).
+char(9,73878).
+char(c,73879).
+char(m,73880).
+char(3,73881).
+char(5,73882).
+char(6,73883).
+char(0,73884).
+char(p,73885).
+char(6,73886).
+char(5,73887).
+char(4,73888).
+char(3,73889).
+char(c,73890).
+char(p,73891).
+char(9,73892).
+char(5,73893).
+char(1,73894).
+char(4,73895).
+char(c,73896).
+char(c,73897).
+char(c,73898).
+char(c,73899).
+char(c,73900).
+char(p,73901).
+char(3,73902).
+char(5,73903).
+char(4,73904).
+char(3,73905).
+char(c,73906).
+char(c,73907).
+char(m,73908).
+char(3,73909).
+char(1,73910).
+char(1,73911).
+char(2,73912).
+char(m,73913).
+char(4,73914).
+char(6,73915).
+char(7,73916).
+char(2,73917).
+char(p,73918).
+char(5,73919).
+char(2,73920).
+char(6,73921).
+char(0,73922).
+char(c,73923).
+char(p,73924).
+char(o,73925).
+char(p,73926).
+char(o,73927).
+char(m,73928).
+char(4,73929).
+char(3,73930).
+char(1,73931).
+char(5,73932).
+char(m,73933).
+char(7,73934).
+char(6,73935).
+char(5,73936).
+char(4,73937).
+char(c,73938).
+char(p,73939).
+char(o,73940).
+char(o,73941).
+char(m,73942).
+char(4,73943).
+char(5,73944).
+char(8,73945).
+char(9,73946).
+char(c,73947).
+char(m,73948).
+char(o,73949).
+char(m,73950).
+char(o,73951).
+char(o,73952).
+char(p,73953).
+char(o,73954).
+char(1,73955).
+char(5,73956).
+char(3,73957).
+char(5,73958).
+char(c,73959).
+char(c,73960).
+char(c,73961).
+char(m,73962).
+char(3,73963).
+char(3,73964).
+char(7,73965).
+char(5,73966).
+char(m,73967).
+char(o,73968).
+char(p,73969).
+char(7,73970).
+char(2,73971).
+char(9,73972).
+char(9,73973).
+char(p,73974).
+char(o,73975).
+char(m,73976).
+char(o,73977).
+char(m,73978).
+char(o,73979).
+char(p,73980).
+char(9,73981).
+char(4,73982).
+char(7,73983).
+char(0,73984).
+char(c,73985).
+char(c,73986).
+char(m,73987).
+char(o,73988).
+char(o,73989).
+char(m,73990).
+char(7,73991).
+char(3,73992).
+char(7,73993).
+char(6,73994).
+char(p,73995).
+char(o,73996).
+char(m,73997).
+char(4,73998).
+char(9,73999).
+char(1,74000).
+char(c,74001).
+char(m,74002).
+char(9,74003).
+char(8,74004).
+char(7,74005).
+char(4,74006).
+char(m,74007).
+char(3,74008).
+char(9,74009).
+char(4,74010).
+char(8,74011).
+char(c,74012).
+char(m,74013).
+char(o,74014).
+char(o,74015).
+char(p,74016).
+char(3,74017).
+char(0,74018).
+char(4,74019).
+char(m,74020).
+char(2,74021).
+char(8,74022).
+char(2,74023).
+char(8,74024).
+char(c,74025).
+char(p,74026).
+char(8,74027).
+char(9,74028).
+char(9,74029).
+char(m,74030).
+char(o,74031).
+char(m,74032).
+char(o,74033).
+char(o,74034).
+char(6,74035).
+char(4,74036).
+char(7,74037).
+char(8,74038).
+char(c,74039).
+char(p,74040).
+char(4,74041).
+char(5,74042).
+char(5,74043).
+char(c,74044).
+char(c,74045).
+char(c,74046).
+char(m,74047).
+char(o,74048).
+char(1,74049).
+char(3,74050).
+char(2,74051).
+char(0,74052).
+char(p,74053).
+char(o,74054).
+char(p,74055).
+char(1,74056).
+char(1,74057).
+char(1,74058).
+char(8,74059).
+char(m,74060).
+char(8,74061).
+char(2,74062).
+char(6,74063).
+char(4,74064).
+char(c,74065).
+char(c,74066).
+char(c,74067).
+char(c,74068).
+char(m,74069).
+char(o,74070).
+char(o,74071).
+char(o,74072).
+char(p,74073).
+char(2,74074).
+char(1,74075).
+char(4,74076).
+char(5,74077).
+char(p,74078).
+char(5,74079).
+char(6,74080).
+char(6,74081).
+char(4,74082).
+char(c,74083).
+char(c,74084).
+char(p,74085).
+char(4,74086).
+char(4,74087).
+char(0,74088).
+char(2,74089).
+char(m,74090).
+char(o,74091).
+char(p,74092).
+char(2,74093).
+char(1,74094).
+char(1,74095).
+char(2,74096).
+char(p,74097).
+char(o,74098).
+char(o,74099).
+char(m,74100).
+char(9,74101).
+char(6,74102).
+char(7,74103).
+char(5,74104).
+char(m,74105).
+char(2,74106).
+char(9,74107).
+char(6,74108).
+char(c,74109).
+char(m,74110).
+char(o,74111).
+char(m,74112).
+char(o,74113).
+char(o,74114).
+char(m,74115).
+char(o,74116).
+char(p,74117).
+char(o,74118).
+char(p,74119).
+char(o,74120).
+char(m,74121).
+char(3,74122).
+char(6,74123).
+char(4,74124).
+char(8,74125).
+char(m,74126).
+char(o,74127).
+char(m,74128).
+char(8,74129).
+char(4,74130).
+char(4,74131).
+char(0,74132).
+char(c,74133).
+char(c,74134).
+char(c,74135).
+char(m,74136).
+char(o,74137).
+char(p,74138).
+char(o,74139).
+char(p,74140).
+char(o,74141).
+char(3,74142).
+char(3,74143).
+char(9,74144).
+char(8,74145).
+char(m,74146).
+char(6,74147).
+char(9,74148).
+char(4,74149).
+char(0,74150).
+char(c,74151).
+char(m,74152).
+char(o,74153).
+char(m,74154).
+char(9,74155).
+char(0,74156).
+char(4,74157).
+char(m,74158).
+char(6,74159).
+char(8,74160).
+char(4,74161).
+char(2,74162).
+char(p,74163).
+char(o,74164).
+char(8,74165).
+char(7,74166).
+char(2,74167).
+char(2,74168).
+char(p,74169).
+char(9,74170).
+char(1,74171).
+char(2,74172).
+char(3,74173).
+char(m,74174).
+char(1,74175).
+char(9,74176).
+char(2,74177).
+char(6,74178).
+char(c,74179).
+char(p,74180).
+char(5,74181).
+char(6,74182).
+char(0,74183).
+char(c,74184).
+char(c,74185).
+char(c,74186).
+char(c,74187).
+char(c,74188).
+char(p,74189).
+char(o,74190).
+char(m,74191).
+char(2,74192).
+char(4,74193).
+char(9,74194).
+char(2,74195).
+char(c,74196).
+char(c,74197).
+char(p,74198).
+char(o,74199).
+char(m,74200).
+char(7,74201).
+char(8,74202).
+char(p,74203).
+char(o,74204).
+char(p,74205).
+char(o,74206).
+char(m,74207).
+char(o,74208).
+char(m,74209).
+char(o,74210).
+char(m,74211).
+char(4,74212).
+char(7,74213).
+char(2,74214).
+char(m,74215).
+char(o,74216).
+char(p,74217).
+char(o,74218).
+char(p,74219).
+char(o,74220).
+char(3,74221).
+char(3,74222).
+char(2,74223).
+char(9,74224).
+char(p,74225).
+char(o,74226).
+char(o,74227).
+char(o,74228).
+char(p,74229).
+char(o,74230).
+char(o,74231).
+char(7,74232).
+char(9,74233).
+char(6,74234).
+char(0,74235).
+char(p,74236).
+char(9,74237).
+char(3,74238).
+char(1,74239).
+char(c,74240).
+char(p,74241).
+char(o,74242).
+char(m,74243).
+char(o,74244).
+char(p,74245).
+char(9,74246).
+char(9,74247).
+char(9,74248).
+char(5,74249).
+char(p,74250).
+char(8,74251).
+char(8,74252).
+char(5,74253).
+char(p,74254).
+char(o,74255).
+char(p,74256).
+char(8,74257).
+char(7,74258).
+char(7,74259).
+char(6,74260).
+char(c,74261).
+char(p,74262).
+char(o,74263).
+char(5,74264).
+char(6,74265).
+char(4,74266).
+char(7,74267).
+char(c,74268).
+char(p,74269).
+char(o,74270).
+char(m,74271).
+char(o,74272).
+char(p,74273).
+char(o,74274).
+char(p,74275).
+char(o,74276).
+char(m,74277).
+char(o,74278).
+char(m,74279).
+char(o,74280).
+char(o,74281).
+char(o,74282).
+char(2,74283).
+char(3,74284).
+char(6,74285).
+char(1,74286).
+char(c,74287).
+char(m,74288).
+char(2,74289).
+char(7,74290).
+char(8,74291).
+char(4,74292).
+char(c,74293).
+char(c,74294).
+char(m,74295).
+char(o,74296).
+char(p,74297).
+char(o,74298).
+char(7,74299).
+char(9,74300).
+char(2,74301).
+char(7,74302).
+char(p,74303).
+char(2,74304).
+char(2,74305).
+char(7,74306).
+char(c,74307).
+char(p,74308).
+char(8,74309).
+char(9,74310).
+char(3,74311).
+char(6,74312).
+char(m,74313).
+char(1,74314).
+char(8,74315).
+char(5,74316).
+char(4,74317).
+char(p,74318).
+char(8,74319).
+char(0,74320).
+char(6,74321).
+char(5,74322).
+char(c,74323).
+char(c,74324).
+char(p,74325).
+char(o,74326).
+char(p,74327).
+char(8,74328).
+char(1,74329).
+char(2,74330).
+char(6,74331).
+char(c,74332).
+char(c,74333).
+char(c,74334).
+char(p,74335).
+char(o,74336).
+char(o,74337).
+char(m,74338).
+char(o,74339).
+char(o,74340).
+char(p,74341).
+char(1,74342).
+char(2,74343).
+char(9,74344).
+char(2,74345).
+char(c,74346).
+char(c,74347).
+char(p,74348).
+char(o,74349).
+char(o,74350).
+char(m,74351).
+char(o,74352).
+char(o,74353).
+char(m,74354).
+char(o,74355).
+char(p,74356).
+char(6,74357).
+char(4,74358).
+char(5,74359).
+char(4,74360).
+char(c,74361).
+char(c,74362).
+char(c,74363).
+char(p,74364).
+char(o,74365).
+char(p,74366).
+char(8,74367).
+char(9,74368).
+char(6,74369).
+char(0,74370).
+char(p,74371).
+char(o,74372).
+char(m,74373).
+char(o,74374).
+char(m,74375).
+char(7,74376).
+char(6,74377).
+char(1,74378).
+char(c,74379).
+char(p,74380).
+char(o,74381).
+char(p,74382).
+char(o,74383).
+char(m,74384).
+char(4,74385).
+char(7,74386).
+char(3,74387).
+char(7,74388).
+char(m,74389).
+char(9,74390).
+char(9,74391).
+char(6,74392).
+char(8,74393).
+char(p,74394).
+char(o,74395).
+char(m,74396).
+char(o,74397).
+char(m,74398).
+char(o,74399).
+char(5,74400).
+char(9,74401).
+char(4,74402).
+char(2,74403).
+char(c,74404).
+char(c,74405).
+char(p,74406).
+char(5,74407).
+char(7,74408).
+char(0,74409).
+char(5,74410).
+char(p,74411).
+char(9,74412).
+char(9,74413).
+char(9,74414).
+char(7,74415).
+char(c,74416).
+char(c,74417).
+char(c,74418).
+char(p,74419).
+char(o,74420).
+char(o,74421).
+char(m,74422).
+char(4,74423).
+char(7,74424).
+char(6,74425).
+char(5,74426).
+char(c,74427).
+char(c,74428).
+char(p,74429).
+char(o,74430).
+char(m,74431).
+char(2,74432).
+char(5,74433).
+char(3,74434).
+char(8,74435).
+char(m,74436).
+char(o,74437).
+char(p,74438).
+char(o,74439).
+char(o,74440).
+char(m,74441).
+char(1,74442).
+char(8,74443).
+char(5,74444).
+char(1,74445).
+char(c,74446).
+char(c,74447).
+char(m,74448).
+char(1,74449).
+char(4,74450).
+char(7,74451).
+char(p,74452).
+char(o,74453).
+char(m,74454).
+char(o,74455).
+char(m,74456).
+char(2,74457).
+char(9,74458).
+char(2,74459).
+char(8,74460).
+char(c,74461).
+char(c,74462).
+char(c,74463).
+char(m,74464).
+char(5,74465).
+char(0,74466).
+char(3,74467).
+char(3,74468).
+char(m,74469).
+char(3,74470).
+char(5,74471).
+char(3,74472).
+char(1,74473).
+char(m,74474).
+char(o,74475).
+char(m,74476).
+char(o,74477).
+char(p,74478).
+char(o,74479).
+char(m,74480).
+char(2,74481).
+char(1,74482).
+char(6,74483).
+char(1,74484).
+char(p,74485).
+char(o,74486).
+char(5,74487).
+char(3,74488).
+char(0,74489).
+char(2,74490).
+char(c,74491).
+char(m,74492).
+char(o,74493).
+char(p,74494).
+char(o,74495).
+char(o,74496).
+char(p,74497).
+char(o,74498).
+char(o,74499).
+char(p,74500).
+char(o,74501).
+char(m,74502).
+char(4,74503).
+char(5,74504).
+char(8,74505).
+char(6,74506).
+char(c,74507).
+char(m,74508).
+char(1,74509).
+char(6,74510).
+char(7,74511).
+char(0,74512).
+char(c,74513).
+char(c,74514).
+char(c,74515).
+char(m,74516).
+char(3,74517).
+char(3,74518).
+char(8,74519).
+char(0,74520).
+char(c,74521).
+char(c,74522).
+char(p,74523).
+char(2,74524).
+char(6,74525).
+char(0,74526).
+char(8,74527).
+char(c,74528).
+char(c,74529).
+char(c,74530).
+char(p,74531).
+char(6,74532).
+char(0,74533).
+char(5,74534).
+char(2,74535).
+char(p,74536).
+char(o,74537).
+char(p,74538).
+char(o,74539).
+char(m,74540).
+char(9,74541).
+char(4,74542).
+char(0,74543).
+char(c,74544).
+char(c,74545).
+char(p,74546).
+char(5,74547).
+char(6,74548).
+char(0,74549).
+char(4,74550).
+char(c,74551).
+char(m,74552).
+char(o,74553).
+char(m,74554).
+char(7,74555).
+char(7,74556).
+char(0,74557).
+char(3,74558).
+char(m,74559).
+char(o,74560).
+char(m,74561).
+char(o,74562).
+char(p,74563).
+char(o,74564).
+char(9,74565).
+char(5,74566).
+char(7,74567).
+char(4,74568).
+char(m,74569).
+char(9,74570).
+char(5,74571).
+char(9,74572).
+char(2,74573).
+char(m,74574).
+char(9,74575).
+char(3,74576).
+char(6,74577).
+char(8,74578).
+char(c,74579).
+char(m,74580).
+char(4,74581).
+char(9,74582).
+char(2,74583).
+char(5,74584).
+char(c,74585).
+char(m,74586).
+char(3,74587).
+char(7,74588).
+char(0,74589).
+char(0,74590).
+char(p,74591).
+char(4,74592).
+char(7,74593).
+char(5,74594).
+char(c,74595).
+char(p,74596).
+char(7,74597).
+char(4,74598).
+char(4,74599).
+char(3,74600).
+char(c,74601).
+char(m,74602).
+char(o,74603).
+char(m,74604).
+char(o,74605).
+char(m,74606).
+char(3,74607).
+char(1,74608).
+char(3,74609).
+char(8,74610).
+char(c,74611).
+char(p,74612).
+char(o,74613).
+char(m,74614).
+char(8,74615).
+char(5,74616).
+char(2,74617).
+char(1,74618).
+char(c,74619).
+char(m,74620).
+char(8,74621).
+char(1,74622).
+char(1,74623).
+char(8,74624).
+char(p,74625).
+char(o,74626).
+char(m,74627).
+char(8,74628).
+char(3,74629).
+char(8,74630).
+char(5,74631).
+char(m,74632).
+char(o,74633).
+char(m,74634).
+char(o,74635).
+char(p,74636).
+char(o,74637).
+char(o,74638).
+char(o,74639).
+char(m,74640).
+char(8,74641).
+char(4,74642).
+char(7,74643).
+char(4,74644).
+char(c,74645).
+char(m,74646).
+char(o,74647).
+char(o,74648).
+char(5,74649).
+char(6,74650).
+char(6,74651).
+char(7,74652).
+char(m,74653).
+char(o,74654).
+char(m,74655).
+char(6,74656).
+char(5,74657).
+char(8,74658).
+char(3,74659).
+char(c,74660).
+char(c,74661).
+char(p,74662).
+char(9,74663).
+char(0,74664).
+char(1,74665).
+char(1,74666).
+char(m,74667).
+char(8,74668).
+char(9,74669).
+char(c,74670).
+char(p,74671).
+char(o,74672).
+char(p,74673).
+char(o,74674).
+char(3,74675).
+char(0,74676).
+char(1,74677).
+char(6,74678).
+char(p,74679).
+char(9,74680).
+char(4,74681).
+char(9,74682).
+char(c,74683).
+char(p,74684).
+char(5,74685).
+char(5,74686).
+char(2,74687).
+char(2,74688).
+char(c,74689).
+char(p,74690).
+char(o,74691).
+char(8,74692).
+char(4,74693).
+char(7,74694).
+char(2,74695).
+char(p,74696).
+char(4,74697).
+char(2,74698).
+char(9,74699).
+char(5,74700).
+char(m,74701).
+char(1,74702).
+char(7,74703).
+char(8,74704).
+char(9,74705).
+char(p,74706).
+char(3,74707).
+char(2,74708).
+char(0,74709).
+char(2,74710).
+char(m,74711).
+char(6,74712).
+char(1,74713).
+char(0,74714).
+char(5,74715).
+char(c,74716).
+char(m,74717).
+char(7,74718).
+char(9,74719).
+char(0,74720).
+char(p,74721).
+char(o,74722).
+char(m,74723).
+char(8,74724).
+char(2,74725).
+char(2,74726).
+char(5,74727).
+char(m,74728).
+char(o,74729).
+char(2,74730).
+char(4,74731).
+char(4,74732).
+char(6,74733).
+char(c,74734).
+char(m,74735).
+char(8,74736).
+char(9,74737).
+char(5,74738).
+char(5,74739).
+char(p,74740).
+char(6,74741).
+char(5,74742).
+char(8,74743).
+char(1,74744).
+char(p,74745).
+char(9,74746).
+char(0,74747).
+char(0,74748).
+char(8,74749).
+char(p,74750).
+char(8,74751).
+char(3,74752).
+char(0,74753).
+char(3,74754).
+char(c,74755).
+char(m,74756).
+char(o,74757).
+char(m,74758).
+char(o,74759).
+char(p,74760).
+char(o,74761).
+char(9,74762).
+char(6,74763).
+char(4,74764).
+char(6,74765).
+char(c,74766).
+char(c,74767).
+char(p,74768).
+char(1,74769).
+char(1,74770).
+char(6,74771).
+char(9,74772).
+char(c,74773).
+char(c,74774).
+char(c,74775).
+char(m,74776).
+char(9,74777).
+char(5,74778).
+char(4,74779).
+char(4,74780).
+char(p,74781).
+char(o,74782).
+char(m,74783).
+char(o,74784).
+char(m,74785).
+char(o,74786).
+char(p,74787).
+char(5,74788).
+char(1,74789).
+char(6,74790).
+char(1,74791).
+char(c,74792).
+char(c,74793).
+char(p,74794).
+char(o,74795).
+char(6,74796).
+char(6,74797).
+char(1,74798).
+char(3,74799).
+char(c,74800).
+char(p,74801).
+char(o,74802).
+char(m,74803).
+char(9,74804).
+char(5,74805).
+char(7,74806).
+char(7,74807).
+char(c,74808).
+char(p,74809).
+char(1,74810).
+char(5,74811).
+char(6,74812).
+char(5,74813).
+char(p,74814).
+char(7,74815).
+char(9,74816).
+char(3,74817).
+char(5,74818).
+char(p,74819).
+char(7,74820).
+char(6,74821).
+char(7,74822).
+char(5,74823).
+char(c,74824).
+char(c,74825).
+char(c,74826).
+char(m,74827).
+char(5,74828).
+char(6,74829).
+char(6,74830).
+char(1,74831).
+char(m,74832).
+char(o,74833).
+char(p,74834).
+char(o,74835).
+char(o,74836).
+char(4,74837).
+char(8,74838).
+char(5,74839).
+char(1,74840).
+char(c,74841).
+char(m,74842).
+char(7,74843).
+char(2,74844).
+char(8,74845).
+char(p,74846).
+char(1,74847).
+char(7,74848).
+char(4,74849).
+char(9,74850).
+char(p,74851).
+char(o,74852).
+char(m,74853).
+char(5,74854).
+char(5,74855).
+char(0,74856).
+char(5,74857).
+char(p,74858).
+char(o,74859).
+char(m,74860).
+char(o,74861).
+char(o,74862).
+char(o,74863).
+char(p,74864).
+char(9,74865).
+char(1,74866).
+char(6,74867).
+char(0,74868).
+char(c,74869).
+char(c,74870).
+char(m,74871).
+char(o,74872).
+char(p,74873).
+char(o,74874).
+char(p,74875).
+char(o,74876).
+char(5,74877).
+char(9,74878).
+char(6,74879).
+char(0,74880).
+char(p,74881).
+char(8,74882).
+char(4,74883).
+char(1,74884).
+char(5,74885).
+char(p,74886).
+char(5,74887).
+char(5,74888).
+char(3,74889).
+char(1,74890).
+char(p,74891).
+char(o,74892).
+char(p,74893).
+char(3,74894).
+char(4,74895).
+char(8,74896).
+char(5,74897).
+char(c,74898).
+char(c,74899).
+char(c,74900).
+char(p,74901).
+char(o,74902).
+char(p,74903).
+char(o,74904).
+char(p,74905).
+char(o,74906).
+char(m,74907).
+char(o,74908).
+char(p,74909).
+char(9,74910).
+char(5,74911).
+char(6,74912).
+char(2,74913).
+char(c,74914).
+char(c,74915).
+char(p,74916).
+char(3,74917).
+char(6,74918).
+char(4,74919).
+char(3,74920).
+char(c,74921).
+char(c,74922).
+char(c,74923).
+char(m,74924).
+char(1,74925).
+char(0,74926).
+char(4,74927).
+char(8,74928).
+char(c,74929).
+char(p,74930).
+char(o,74931).
+char(p,74932).
+char(o,74933).
+char(o,74934).
+char(m,74935).
+char(o,74936).
+char(m,74937).
+char(o,74938).
+char(o,74939).
+char(m,74940).
+char(o,74941).
+char(m,74942).
+char(2,74943).
+char(1,74944).
+char(1,74945).
+char(8,74946).
+char(p,74947).
+char(o,74948).
+char(p,74949).
+char(o,74950).
+char(o,74951).
+char(p,74952).
+char(o,74953).
+char(o,74954).
+char(o,74955).
+char(o,74956).
+char(p,74957).
+char(7,74958).
+char(5,74959).
+char(0,74960).
+char(5,74961).
+char(c,74962).
+char(c,74963).
+char(c,74964).
+char(m,74965).
+char(7,74966).
+char(0,74967).
+char(7,74968).
+char(1,74969).
+char(p,74970).
+char(o,74971).
+char(m,74972).
+char(4,74973).
+char(7,74974).
+char(7,74975).
+char(p,74976).
+char(6,74977).
+char(8,74978).
+char(5,74979).
+char(6,74980).
+char(c,74981).
+char(c,74982).
+char(m,74983).
+char(3,74984).
+char(9,74985).
+char(5,74986).
+char(4,74987).
+char(m,74988).
+char(2,74989).
+char(0,74990).
+char(6,74991).
+char(m,74992).
+char(o,74993).
+char(o,74994).
+char(p,74995).
+char(o,74996).
+char(p,74997).
+char(8,74998).
+char(8,74999).
+char(0,75000).
+char(3,75001).
+char(c,75002).
+char(p,75003).
+char(9,75004).
+char(0,75005).
+char(8,75006).
+char(6,75007).
+char(c,75008).
+char(c,75009).
+char(m,75010).
+char(1,75011).
+char(4,75012).
+char(2,75013).
+char(3,75014).
+char(p,75015).
+char(4,75016).
+char(9,75017).
+char(7,75018).
+char(3,75019).
+char(c,75020).
+char(c,75021).
+char(c,75022).
+char(p,75023).
+char(o,75024).
+char(p,75025).
+char(6,75026).
+char(4,75027).
+char(0,75028).
+char(3,75029).
+char(m,75030).
+char(o,75031).
+char(o,75032).
+char(o,75033).
+char(m,75034).
+char(8,75035).
+char(1,75036).
+char(2,75037).
+char(0,75038).
+char(m,75039).
+char(6,75040).
+char(0,75041).
+char(8,75042).
+char(9,75043).
+char(m,75044).
+char(o,75045).
+char(p,75046).
+char(4,75047).
+char(8,75048).
+char(1,75049).
+char(8,75050).
+char(c,75051).
+char(p,75052).
+char(o,75053).
+char(p,75054).
+char(5,75055).
+char(3,75056).
+char(4,75057).
+char(9,75058).
+char(c,75059).
+char(p,75060).
+char(6,75061).
+char(0,75062).
+char(2,75063).
+char(7,75064).
+char(c,75065).
+char(p,75066).
+char(1,75067).
+char(7,75068).
+char(2,75069).
+char(5,75070).
+char(c,75071).
+char(c,75072).
+char(p,75073).
+char(o,75074).
+char(p,75075).
+char(3,75076).
+char(3,75077).
+char(0,75078).
+char(6,75079).
+char(m,75080).
+char(o,75081).
+char(p,75082).
+char(o,75083).
+char(p,75084).
+char(8,75085).
+char(4,75086).
+char(1,75087).
+char(4,75088).
+char(c,75089).
+char(m,75090).
+char(4,75091).
+char(5,75092).
+char(7,75093).
+char(1,75094).
+char(p,75095).
+char(o,75096).
+char(p,75097).
+char(o,75098).
+char(m,75099).
+char(o,75100).
+char(m,75101).
+char(o,75102).
+char(p,75103).
+char(o,75104).
+char(o,75105).
+char(p,75106).
+char(o,75107).
+char(o,75108).
+char(m,75109).
+char(3,75110).
+char(6,75111).
+char(4,75112).
+char(9,75113).
+char(c,75114).
+char(c,75115).
+char(p,75116).
+char(o,75117).
+char(p,75118).
+char(o,75119).
+char(7,75120).
+char(0,75121).
+char(6,75122).
+char(8,75123).
+char(c,75124).
+char(p,75125).
+char(o,75126).
+char(m,75127).
+char(1,75128).
+char(2,75129).
+char(5,75130).
+char(0,75131).
+char(c,75132).
+char(m,75133).
+char(o,75134).
+char(p,75135).
+char(o,75136).
+char(6,75137).
+char(7,75138).
+char(9,75139).
+char(6,75140).
+char(c,75141).
+char(c,75142).
+char(c,75143).
+char(c,75144).
+char(c,75145).
+char(c,75146).
+char(p,75147).
+char(2,75148).
+char(8,75149).
+char(7,75150).
+char(9,75151).
+char(c,75152).
+char(c,75153).
+char(c,75154).
+char(p,75155).
+char(8,75156).
+char(4,75157).
+char(0,75158).
+char(5,75159).
+char(p,75160).
+char(4,75161).
+char(9,75162).
+char(c,75163).
+char(p,75164).
+char(o,75165).
+char(p,75166).
+char(o,75167).
+char(p,75168).
+char(o,75169).
+char(5,75170).
+char(4,75171).
+char(9,75172).
+char(3,75173).
+char(c,75174).
+char(p,75175).
+char(6,75176).
+char(5,75177).
+char(0,75178).
+char(2,75179).
+char(m,75180).
+char(2,75181).
+char(4,75182).
+char(8,75183).
+char(9,75184).
+char(p,75185).
+char(o,75186).
+char(p,75187).
+char(o,75188).
+char(m,75189).
+char(9,75190).
+char(2,75191).
+char(2,75192).
+char(1,75193).
+char(p,75194).
+char(5,75195).
+char(8,75196).
+char(0,75197).
+char(9,75198).
+char(c,75199).
+char(c,75200).
+char(c,75201).
+char(c,75202).
+char(c,75203).
+char(p,75204).
+char(9,75205).
+char(9,75206).
+char(0,75207).
+char(1,75208).
+char(m,75209).
+char(1,75210).
+char(5,75211).
+char(2,75212).
+char(4,75213).
+char(c,75214).
+char(p,75215).
+char(2,75216).
+char(0,75217).
+char(9,75218).
+char(0,75219).
+char(c,75220).
+char(p,75221).
+char(o,75222).
+char(o,75223).
+char(m,75224).
+char(o,75225).
+char(o,75226).
+char(3,75227).
+char(2,75228).
+char(9,75229).
+char(4,75230).
+char(m,75231).
+char(o,75232).
+char(m,75233).
+char(5,75234).
+char(6,75235).
+char(9,75236).
+char(4,75237).
+char(c,75238).
+char(c,75239).
+char(c,75240).
+char(m,75241).
+char(4,75242).
+char(3,75243).
+char(1,75244).
+char(1,75245).
+char(c,75246).
+char(c,75247).
+char(c,75248).
+char(p,75249).
+char(o,75250).
+char(o,75251).
+char(1,75252).
+char(6,75253).
+char(8,75254).
+char(7,75255).
+char(p,75256).
+char(6,75257).
+char(8,75258).
+char(5,75259).
+char(0,75260).
+char(c,75261).
+char(p,75262).
+char(o,75263).
+char(m,75264).
+char(5,75265).
+char(0,75266).
+char(9,75267).
+char(2,75268).
+char(p,75269).
+char(9,75270).
+char(9,75271).
+char(9,75272).
+char(1,75273).
+char(m,75274).
+char(5,75275).
+char(6,75276).
+char(1,75277).
+char(9,75278).
+char(c,75279).
+char(c,75280).
+char(c,75281).
+char(c,75282).
+char(c,75283).
+char(c,75284).
+char(m,75285).
+char(6,75286).
+char(0,75287).
+char(5,75288).
+char(0,75289).
+char(c,75290).
+char(p,75291).
+char(o,75292).
+char(o,75293).
+char(o,75294).
+char(p,75295).
+char(o,75296).
+char(p,75297).
+char(o,75298).
+char(p,75299).
+char(7,75300).
+char(2,75301).
+char(1,75302).
+char(7,75303).
+char(c,75304).
+char(c,75305).
+char(c,75306).
+char(m,75307).
+char(5,75308).
+char(5,75309).
+char(8,75310).
+char(0,75311).
+char(m,75312).
+char(o,75313).
+char(m,75314).
+char(o,75315).
+char(p,75316).
+char(o,75317).
+char(m,75318).
+char(3,75319).
+char(5,75320).
+char(7,75321).
+char(1,75322).
+char(c,75323).
+char(p,75324).
+char(1,75325).
+char(8,75326).
+char(2,75327).
+char(2,75328).
+char(c,75329).
+char(p,75330).
+char(o,75331).
+char(p,75332).
+char(1,75333).
+char(6,75334).
+char(5,75335).
+char(3,75336).
+char(p,75337).
+char(o,75338).
+char(p,75339).
+char(o,75340).
+char(6,75341).
+char(8,75342).
+char(9,75343).
+char(2,75344).
+char(p,75345).
+char(o,75346).
+char(p,75347).
+char(9,75348).
+char(1,75349).
+char(5,75350).
+char(3,75351).
+char(c,75352).
+char(m,75353).
+char(o,75354).
+char(m,75355).
+char(5,75356).
+char(0,75357).
+char(6,75358).
+char(0,75359).
+char(c,75360).
+char(m,75361).
+char(7,75362).
+char(7,75363).
+char(0,75364).
+char(5,75365).
+char(p,75366).
+char(o,75367).
+char(1,75368).
+char(7,75369).
+char(0,75370).
+char(7,75371).
+char(p,75372).
+char(5,75373).
+char(3,75374).
+char(7,75375).
+char(7,75376).
+char(c,75377).
+char(c,75378).
+char(c,75379).
+char(m,75380).
+char(o,75381).
+char(5,75382).
+char(0,75383).
+char(0,75384).
+char(9,75385).
+char(c,75386).
+char(p,75387).
+char(o,75388).
+char(m,75389).
+char(o,75390).
+char(m,75391).
+char(3,75392).
+char(8,75393).
+char(0,75394).
+char(5,75395).
+char(c,75396).
+char(m,75397).
+char(9,75398).
+char(9,75399).
+char(0,75400).
+char(5,75401).
+char(m,75402).
+char(o,75403).
+char(p,75404).
+char(6,75405).
+char(0,75406).
+char(7,75407).
+char(9,75408).
+char(c,75409).
+char(c,75410).
+char(c,75411).
+char(m,75412).
+char(o,75413).
+char(p,75414).
+char(1,75415).
+char(0,75416).
+char(3,75417).
+char(5,75418).
+char(c,75419).
+char(m,75420).
+char(2,75421).
+char(5,75422).
+char(7,75423).
+char(6,75424).
+char(m,75425).
+char(9,75426).
+char(1,75427).
+char(4,75428).
+char(c,75429).
+char(m,75430).
+char(o,75431).
+char(1,75432).
+char(7,75433).
+char(8,75434).
+char(4,75435).
+char(m,75436).
+char(o,75437).
+char(p,75438).
+char(7,75439).
+char(7,75440).
+char(7,75441).
+char(4,75442).
+char(p,75443).
+char(o,75444).
+char(m,75445).
+char(5,75446).
+char(9,75447).
+char(0,75448).
+char(2,75449).
+char(c,75450).
+char(m,75451).
+char(o,75452).
+char(3,75453).
+char(5,75454).
+char(0,75455).
+char(2,75456).
+char(c,75457).
+char(c,75458).
+char(c,75459).
+char(p,75460).
+char(o,75461).
+char(p,75462).
+char(o,75463).
+char(m,75464).
+char(o,75465).
+char(5,75466).
+char(3,75467).
+char(4,75468).
+char(c,75469).
+char(p,75470).
+char(5,75471).
+char(7,75472).
+char(7,75473).
+char(5,75474).
+char(c,75475).
+char(c,75476).
+char(m,75477).
+char(o,75478).
+char(m,75479).
+char(o,75480).
+char(o,75481).
+char(m,75482).
+char(7,75483).
+char(3,75484).
+char(2,75485).
+char(7,75486).
+char(c,75487).
+char(c,75488).
+char(c,75489).
+char(c,75490).
+char(c,75491).
+char(c,75492).
+char(c,75493).
+char(c,75494).
+char(p,75495).
+char(o,75496).
+char(p,75497).
+char(4,75498).
+char(0,75499).
+char(8,75500).
+char(8,75501).
+char(m,75502).
+char(o,75503).
+char(m,75504).
+char(1,75505).
+char(6,75506).
+char(8,75507).
+char(2,75508).
+char(c,75509).
+char(p,75510).
+char(8,75511).
+char(9,75512).
+char(6,75513).
+char(3,75514).
+char(p,75515).
+char(1,75516).
+char(8,75517).
+char(3,75518).
+char(9,75519).
+char(c,75520).
+char(p,75521).
+char(o,75522).
+char(p,75523).
+char(6,75524).
+char(0,75525).
+char(9,75526).
+char(5,75527).
+char(c,75528).
+char(p,75529).
+char(o,75530).
+char(p,75531).
+char(4,75532).
+char(4,75533).
+char(4,75534).
+char(0,75535).
+char(p,75536).
+char(8,75537).
+char(7,75538).
+char(7,75539).
+char(1,75540).
+char(c,75541).
+char(p,75542).
+char(o,75543).
+char(o,75544).
+char(o,75545).
+char(2,75546).
+char(5,75547).
+char(5,75548).
+char(4,75549).
+char(m,75550).
+char(8,75551).
+char(7,75552).
+char(3,75553).
+char(6,75554).
+char(m,75555).
+char(7,75556).
+char(9,75557).
+char(0,75558).
+char(3,75559).
+char(p,75560).
+char(o,75561).
+char(p,75562).
+char(1,75563).
+char(9,75564).
+char(5,75565).
+char(8,75566).
+char(c,75567).
+char(p,75568).
+char(o,75569).
+char(p,75570).
+char(7,75571).
+char(3,75572).
+char(4,75573).
+char(7,75574).
+char(c,75575).
+char(p,75576).
+char(5,75577).
+char(9,75578).
+char(8,75579).
+char(1,75580).
+char(c,75581).
+char(c,75582).
+char(c,75583).
+char(p,75584).
+char(7,75585).
+char(7,75586).
+char(4,75587).
+char(9,75588).
+char(c,75589).
+char(m,75590).
+char(o,75591).
+char(m,75592).
+char(o,75593).
+char(o,75594).
+char(p,75595).
+char(o,75596).
+char(p,75597).
+char(o,75598).
+char(m,75599).
+char(9,75600).
+char(0,75601).
+char(1,75602).
+char(3,75603).
+char(m,75604).
+char(8,75605).
+char(3,75606).
+char(4,75607).
+char(5,75608).
+char(c,75609).
+char(p,75610).
+char(o,75611).
+char(o,75612).
+char(m,75613).
+char(o,75614).
+char(m,75615).
+char(o,75616).
+char(m,75617).
+char(o,75618).
+char(o,75619).
+char(2,75620).
+char(7,75621).
+char(1,75622).
+char(0,75623).
+char(p,75624).
+char(3,75625).
+char(9,75626).
+char(4,75627).
+char(9,75628).
+char(p,75629).
+char(o,75630).
+char(m,75631).
+char(o,75632).
+char(m,75633).
+char(1,75634).
+char(7,75635).
+char(0,75636).
+char(4,75637).
+char(c,75638).
+char(m,75639).
+char(6,75640).
+char(5,75641).
+char(8,75642).
+char(7,75643).
+char(m,75644).
+char(7,75645).
+char(2,75646).
+char(0,75647).
+char(3,75648).
+char(c,75649).
+char(c,75650).
+char(c,75651).
+char(p,75652).
+char(o,75653).
+char(m,75654).
+char(o,75655).
+char(p,75656).
+char(2,75657).
+char(7,75658).
+char(6,75659).
+char(8,75660).
+char(c,75661).
+char(m,75662).
+char(o,75663).
+char(p,75664).
+char(o,75665).
+char(p,75666).
+char(7,75667).
+char(3,75668).
+char(8,75669).
+char(7,75670).
+char(m,75671).
+char(o,75672).
+char(m,75673).
+char(7,75674).
+char(4,75675).
+char(4,75676).
+char(8,75677).
+char(m,75678).
+char(o,75679).
+char(p,75680).
+char(5,75681).
+char(8,75682).
+char(3,75683).
+char(8,75684).
+char(c,75685).
+char(m,75686).
+char(9,75687).
+char(3,75688).
+char(1,75689).
+char(5,75690).
+char(m,75691).
+char(o,75692).
+char(m,75693).
+char(o,75694).
+char(m,75695).
+char(o,75696).
+char(o,75697).
+char(o,75698).
+char(m,75699).
+char(o,75700).
+char(o,75701).
+char(p,75702).
+char(o,75703).
+char(o,75704).
+char(o,75705).
+char(o,75706).
+char(m,75707).
+char(6,75708).
+char(2,75709).
+char(3,75710).
+char(c,75711).
+char(c,75712).
+char(p,75713).
+char(4,75714).
+char(4,75715).
+char(8,75716).
+char(1,75717).
+char(c,75718).
+char(c,75719).
+char(c,75720).
+char(p,75721).
+char(1,75722).
+char(4,75723).
+char(9,75724).
+char(2,75725).
+char(m,75726).
+char(o,75727).
+char(2,75728).
+char(8,75729).
+char(6,75730).
+char(9,75731).
+char(m,75732).
+char(8,75733).
+char(6,75734).
+char(1,75735).
+char(1,75736).
+char(p,75737).
+char(7,75738).
+char(9,75739).
+char(8,75740).
+char(9,75741).
+char(c,75742).
+char(m,75743).
+char(o,75744).
+char(p,75745).
+char(o,75746).
+char(p,75747).
+char(o,75748).
+char(m,75749).
+char(o,75750).
+char(p,75751).
+char(5,75752).
+char(1,75753).
+char(4,75754).
+char(m,75755).
+char(o,75756).
+char(p,75757).
+char(5,75758).
+char(6,75759).
+char(6,75760).
+char(5,75761).
+char(p,75762).
+char(5,75763).
+char(2,75764).
+char(3,75765).
+char(4,75766).
+char(p,75767).
+char(o,75768).
+char(p,75769).
+char(o,75770).
+char(1,75771).
+char(4,75772).
+char(2,75773).
+char(4,75774).
+char(c,75775).
+char(c,75776).
+char(p,75777).
+char(o,75778).
+char(o,75779).
+char(p,75780).
+char(o,75781).
+char(p,75782).
+char(1,75783).
+char(1,75784).
+char(4,75785).
+char(4,75786).
+char(c,75787).
+char(m,75788).
+char(o,75789).
+char(p,75790).
+char(3,75791).
+char(0,75792).
+char(5,75793).
+char(0,75794).
+char(c,75795).
+char(c,75796).
+char(m,75797).
+char(4,75798).
+char(8,75799).
+char(6,75800).
+char(3,75801).
+char(c,75802).
+char(c,75803).
+char(c,75804).
+char(m,75805).
+char(o,75806).
+char(p,75807).
+char(o,75808).
+char(m,75809).
+char(7,75810).
+char(1,75811).
+char(0,75812).
+char(7,75813).
+char(p,75814).
+char(1,75815).
+char(9,75816).
+char(1,75817).
+char(1,75818).
+char(c,75819).
+char(c,75820).
+char(c,75821).
+char(c,75822).
+char(c,75823).
+char(m,75824).
+char(2,75825).
+char(7,75826).
+char(1,75827).
+char(8,75828).
+char(c,75829).
+char(p,75830).
+char(5,75831).
+char(4,75832).
+char(1,75833).
+char(m,75834).
+char(2,75835).
+char(6,75836).
+char(3,75837).
+char(p,75838).
+char(o,75839).
+char(p,75840).
+char(o,75841).
+char(p,75842).
+char(o,75843).
+char(p,75844).
+char(o,75845).
+char(p,75846).
+char(9,75847).
+char(1,75848).
+char(2,75849).
+char(7,75850).
+char(p,75851).
+char(o,75852).
+char(p,75853).
+char(o,75854).
+char(m,75855).
+char(o,75856).
+char(m,75857).
+char(9,75858).
+char(9,75859).
+char(1,75860).
+char(0,75861).
+char(p,75862).
+char(3,75863).
+char(5,75864).
+char(4,75865).
+char(1,75866).
+char(c,75867).
+char(c,75868).
+char(p,75869).
+char(o,75870).
+char(m,75871).
+char(4,75872).
+char(7,75873).
+char(7,75874).
+char(m,75875).
+char(6,75876).
+char(6,75877).
+char(9,75878).
+char(4,75879).
+char(c,75880).
+char(m,75881).
+char(9,75882).
+char(2,75883).
+char(5,75884).
+char(7,75885).
+char(c,75886).
+char(m,75887).
+char(o,75888).
+char(5,75889).
+char(1,75890).
+char(5,75891).
+char(1,75892).
+char(p,75893).
+char(8,75894).
+char(7,75895).
+char(3,75896).
+char(2,75897).
+char(c,75898).
+char(p,75899).
+char(o,75900).
+char(m,75901).
+char(o,75902).
+char(p,75903).
+char(o,75904).
+char(m,75905).
+char(o,75906).
+char(m,75907).
+char(o,75908).
+char(m,75909).
+char(o,75910).
+char(p,75911).
+char(7,75912).
+char(2,75913).
+char(9,75914).
+char(9,75915).
+char(c,75916).
+char(p,75917).
+char(2,75918).
+char(8,75919).
+char(7,75920).
+char(9,75921).
+char(m,75922).
+char(5,75923).
+char(0,75924).
+char(2,75925).
+char(6,75926).
+char(p,75927).
+char(o,75928).
+char(p,75929).
+char(8,75930).
+char(8,75931).
+char(0,75932).
+char(8,75933).
+char(p,75934).
+char(o,75935).
+char(m,75936).
+char(3,75937).
+char(9,75938).
+char(1,75939).
+char(m,75940).
+char(o,75941).
+char(p,75942).
+char(o,75943).
+char(m,75944).
+char(8,75945).
+char(9,75946).
+char(8,75947).
+char(3,75948).
+char(c,75949).
+char(m,75950).
+char(2,75951).
+char(7,75952).
+char(8,75953).
+char(4,75954).
+char(m,75955).
+char(3,75956).
+char(0,75957).
+char(7,75958).
+char(1,75959).
+char(p,75960).
+char(9,75961).
+char(0,75962).
+char(8,75963).
+char(4,75964).
+char(p,75965).
+char(o,75966).
+char(p,75967).
+char(8,75968).
+char(6,75969).
+char(0,75970).
+char(1,75971).
+char(c,75972).
+char(c,75973).
+char(c,75974).
+char(p,75975).
+char(o,75976).
+char(p,75977).
+char(2,75978).
+char(2,75979).
+char(1,75980).
+char(9,75981).
+char(m,75982).
+char(5,75983).
+char(6,75984).
+char(3,75985).
+char(0,75986).
+char(c,75987).
+char(c,75988).
+char(m,75989).
+char(1,75990).
+char(3,75991).
+char(4,75992).
+char(6,75993).
+char(m,75994).
+char(o,75995).
+char(8,75996).
+char(1,75997).
+char(0,75998).
+char(1,75999).
+char(p,76000).
+char(7,76001).
+char(2,76002).
+char(7,76003).
+char(8,76004).
+char(p,76005).
+char(o,76006).
+char(9,76007).
+char(m,76008).
+char(o,76009).
+char(m,76010).
+char(o,76011).
+char(m,76012).
+char(o,76013).
+char(p,76014).
+char(o,76015).
+char(o,76016).
+char(o,76017).
+char(p,76018).
+char(o,76019).
+char(p,76020).
+char(o,76021).
+char(m,76022).
+char(3,76023).
+char(8,76024).
+char(4,76025).
+char(7,76026).
+char(c,76027).
+char(p,76028).
+char(o,76029).
+char(m,76030).
+char(o,76031).
+char(p,76032).
+char(7,76033).
+char(0,76034).
+char(3,76035).
+char(c,76036).
+char(c,76037).
+char(c,76038).
+char(c,76039).
+char(c,76040).
+char(m,76041).
+char(o,76042).
+char(p,76043).
+char(6,76044).
+char(3,76045).
+char(8,76046).
+char(8,76047).
+char(c,76048).
+char(p,76049).
+char(o,76050).
+char(p,76051).
+char(o,76052).
+char(p,76053).
+char(o,76054).
+char(7,76055).
+char(8,76056).
+char(3,76057).
+char(p,76058).
+char(o,76059).
+char(m,76060).
+char(o,76061).
+char(p,76062).
+char(o,76063).
+char(4,76064).
+char(1,76065).
+char(5,76066).
+char(9,76067).
+char(c,76068).
+char(p,76069).
+char(o,76070).
+char(p,76071).
+char(7,76072).
+char(3,76073).
+char(1,76074).
+char(3,76075).
+char(m,76076).
+char(8,76077).
+char(6,76078).
+char(0,76079).
+char(4,76080).
+char(m,76081).
+char(o,76082).
+char(p,76083).
+char(3,76084).
+char(0,76085).
+char(7,76086).
+char(2,76087).
+char(c,76088).
+char(c,76089).
+char(p,76090).
+char(o,76091).
+char(5,76092).
+char(9,76093).
+char(0,76094).
+char(8,76095).
+char(c,76096).
+char(c,76097).
+char(c,76098).
+char(c,76099).
+char(p,76100).
+char(4,76101).
+char(6,76102).
+char(8,76103).
+char(5,76104).
+char(m,76105).
+char(o,76106).
+char(p,76107).
+char(3,76108).
+char(8,76109).
+char(9,76110).
+char(6,76111).
+char(c,76112).
+char(c,76113).
+char(p,76114).
+char(8,76115).
+char(6,76116).
+char(3,76117).
+char(9,76118).
+char(p,76119).
+char(6,76120).
+char(4,76121).
+char(0,76122).
+char(1,76123).
+char(c,76124).
+char(c,76125).
+char(c,76126).
+char(m,76127).
+char(o,76128).
+char(m,76129).
+char(3,76130).
+char(0,76131).
+char(7,76132).
+char(6,76133).
+char(c,76134).
+char(c,76135).
+char(p,76136).
+char(o,76137).
+char(m,76138).
+char(o,76139).
+char(o,76140).
+char(m,76141).
+char(4,76142).
+char(0,76143).
+char(2,76144).
+char(6,76145).
+char(p,76146).
+char(4,76147).
+char(9,76148).
+char(1,76149).
+char(7,76150).
+char(c,76151).
+char(c,76152).
+char(c,76153).
+char(p,76154).
+char(1,76155).
+char(4,76156).
+char(3,76157).
+char(3,76158).
+char(c,76159).
+char(p,76160).
+char(6,76161).
+char(6,76162).
+char(3,76163).
+char(2,76164).
+char(c,76165).
+char(m,76166).
+char(o,76167).
+char(3,76168).
+char(5,76169).
+char(5,76170).
+char(3,76171).
+char(p,76172).
+char(o,76173).
+char(6,76174).
+char(6,76175).
+char(4,76176).
+char(5,76177).
+char(c,76178).
+char(m,76179).
+char(o,76180).
+char(m,76181).
+char(3,76182).
+char(6,76183).
+char(7,76184).
+char(6,76185).
+char(p,76186).
+char(4,76187).
+char(0,76188).
+char(4,76189).
+char(2,76190).
+char(m,76191).
+char(o,76192).
+char(m,76193).
+char(1,76194).
+char(0,76195).
+char(1,76196).
+char(9,76197).
+char(m,76198).
+char(o,76199).
+char(p,76200).
+char(2,76201).
+char(7,76202).
+char(0,76203).
+char(m,76204).
+char(9,76205).
+char(7,76206).
+char(9,76207).
+char(6,76208).
+char(c,76209).
+char(p,76210).
+char(o,76211).
+char(m,76212).
+char(o,76213).
+char(m,76214).
+char(o,76215).
+char(1,76216).
+char(5,76217).
+char(9,76218).
+char(2,76219).
+char(c,76220).
+char(c,76221).
+char(c,76222).
+char(c,76223).
+char(p,76224).
+char(o,76225).
+char(1,76226).
+char(6,76227).
+char(1,76228).
+char(9,76229).
+char(c,76230).
+char(m,76231).
+char(7,76232).
+char(0,76233).
+char(7,76234).
+char(1,76235).
+char(c,76236).
+char(c,76237).
+char(m,76238).
+char(1,76239).
+char(0,76240).
+char(2,76241).
+char(6,76242).
+char(c,76243).
+char(p,76244).
+char(o,76245).
+char(p,76246).
+char(o,76247).
+char(p,76248).
+char(4,76249).
+char(3,76250).
+char(1,76251).
+char(6,76252).
+char(c,76253).
+char(c,76254).
+char(p,76255).
+char(o,76256).
+char(p,76257).
+char(6,76258).
+char(0,76259).
+char(8,76260).
+char(0,76261).
+char(c,76262).
+char(c,76263).
+char(c,76264).
+char(c,76265).
+char(p,76266).
+char(2,76267).
+char(4,76268).
+char(0,76269).
+char(3,76270).
+char(m,76271).
+char(o,76272).
+char(m,76273).
+char(o,76274).
+char(m,76275).
+char(o,76276).
+char(m,76277).
+char(o,76278).
+char(8,76279).
+char(7,76280).
+char(9,76281).
+char(4,76282).
+char(c,76283).
+char(c,76284).
+char(p,76285).
+char(7,76286).
+char(3,76287).
+char(8,76288).
+char(1,76289).
+char(m,76290).
+char(4,76291).
+char(4,76292).
+char(7,76293).
+char(1,76294).
+char(c,76295).
+char(p,76296).
+char(2,76297).
+char(9,76298).
+char(4,76299).
+char(9,76300).
+char(c,76301).
+char(m,76302).
+char(o,76303).
+char(m,76304).
+char(o,76305).
+char(p,76306).
+char(9,76307).
+char(2,76308).
+char(9,76309).
+char(3,76310).
+char(m,76311).
+char(3,76312).
+char(5,76313).
+char(0,76314).
+char(c,76315).
+char(c,76316).
+char(c,76317).
+char(c,76318).
+char(p,76319).
+char(8,76320).
+char(2,76321).
+char(2,76322).
+char(5,76323).
+char(c,76324).
+char(c,76325).
+char(m,76326).
+char(4,76327).
+char(6,76328).
+char(7,76329).
+char(6,76330).
+char(p,76331).
+char(o,76332).
+char(m,76333).
+char(6,76334).
+char(2,76335).
+char(7,76336).
+char(5,76337).
+char(p,76338).
+char(o,76339).
+char(o,76340).
+char(o,76341).
+char(m,76342).
+char(o,76343).
+char(p,76344).
+char(8,76345).
+char(2,76346).
+char(8,76347).
+char(0,76348).
+char(p,76349).
+char(5,76350).
+char(0,76351).
+char(3,76352).
+char(2,76353).
+char(m,76354).
+char(o,76355).
+char(2,76356).
+char(9,76357).
+char(2,76358).
+char(1,76359).
+char(p,76360).
+char(o,76361).
+char(m,76362).
+char(6,76363).
+char(6,76364).
+char(6,76365).
+char(3,76366).
+char(c,76367).
+char(c,76368).
+char(c,76369).
+char(p,76370).
+char(o,76371).
+char(m,76372).
+char(o,76373).
+char(o,76374).
+char(m,76375).
+char(o,76376).
+char(m,76377).
+char(o,76378).
+char(p,76379).
+char(7,76380).
+char(1,76381).
+char(2,76382).
+char(4,76383).
+char(c,76384).
+char(m,76385).
+char(o,76386).
+char(p,76387).
+char(3,76388).
+char(3,76389).
+char(7,76390).
+char(9,76391).
+char(c,76392).
+char(p,76393).
+char(o,76394).
+char(6,76395).
+char(0,76396).
+char(1,76397).
+char(7,76398).
+char(c,76399).
+char(c,76400).
+char(c,76401).
+char(c,76402).
+char(p,76403).
+char(o,76404).
+char(m,76405).
+char(7,76406).
+char(1,76407).
+char(1,76408).
+char(3,76409).
+char(p,76410).
+char(2,76411).
+char(2,76412).
+char(3,76413).
+char(6,76414).
+char(p,76415).
+char(o,76416).
+char(m,76417).
+char(1,76418).
+char(5,76419).
+char(3,76420).
+char(3,76421).
+char(p,76422).
+char(8,76423).
+char(2,76424).
+char(1,76425).
+char(3,76426).
+char(p,76427).
+char(o,76428).
+char(p,76429).
+char(o,76430).
+char(o,76431).
+char(p,76432).
+char(o,76433).
+char(p,76434).
+char(o,76435).
+char(p,76436).
+char(9,76437).
+char(2,76438).
+char(6,76439).
+char(7,76440).
+char(c,76441).
+char(m,76442).
+char(9,76443).
+char(9,76444).
+char(7,76445).
+char(6,76446).
+char(p,76447).
+char(o,76448).
+char(m,76449).
+char(5,76450).
+char(9,76451).
+char(2,76452).
+char(5,76453).
+char(m,76454).
+char(1,76455).
+char(6,76456).
+char(9,76457).
+char(7,76458).
+char(p,76459).
+char(6,76460).
+char(7,76461).
+char(9,76462).
+char(4,76463).
+char(p,76464).
+char(9,76465).
+char(9,76466).
+char(9,76467).
+char(3,76468).
+char(c,76469).
+char(c,76470).
+char(p,76471).
+char(6,76472).
+char(7,76473).
+char(7,76474).
+char(8,76475).
+char(m,76476).
+char(3,76477).
+char(0,76478).
+char(7,76479).
+char(m,76480).
+char(2,76481).
+char(7,76482).
+char(7,76483).
+char(3,76484).
+char(c,76485).
+char(p,76486).
+char(o,76487).
+char(p,76488).
+char(6,76489).
+char(4,76490).
+char(2,76491).
+char(7,76492).
+char(c,76493).
+char(p,76494).
+char(o,76495).
+char(p,76496).
+char(3,76497).
+char(4,76498).
+char(5,76499).
+char(4,76500).
+char(m,76501).
+char(2,76502).
+char(0,76503).
+char(5,76504).
+char(1,76505).
+char(c,76506).
+char(p,76507).
+char(o,76508).
+char(m,76509).
+char(o,76510).
+char(p,76511).
+char(4,76512).
+char(1,76513).
+char(2,76514).
+char(3,76515).
+char(m,76516).
+char(o,76517).
+char(p,76518).
+char(o,76519).
+char(7,76520).
+char(0,76521).
+char(5,76522).
+char(9,76523).
+char(m,76524).
+char(o,76525).
+char(5,76526).
+char(1,76527).
+char(0,76528).
+char(2,76529).
+char(c,76530).
+char(m,76531).
+char(7,76532).
+char(6,76533).
+char(2,76534).
+char(c,76535).
+char(c,76536).
+char(m,76537).
+char(o,76538).
+char(m,76539).
+char(8,76540).
+char(3,76541).
+char(2,76542).
+char(c,76543).
+char(p,76544).
+char(6,76545).
+char(8,76546).
+char(3,76547).
+char(p,76548).
+char(o,76549).
+char(6,76550).
+char(7,76551).
+char(0,76552).
+char(2,76553).
+char(c,76554).
+char(c,76555).
+char(c,76556).
+char(c,76557).
+char(p,76558).
+char(9,76559).
+char(9,76560).
+char(4,76561).
+char(m,76562).
+char(3,76563).
+char(5,76564).
+char(8,76565).
+char(5,76566).
+char(p,76567).
+char(o,76568).
+char(8,76569).
+char(0,76570).
+char(2,76571).
+char(3,76572).
+char(p,76573).
+char(1,76574).
+char(8,76575).
+char(8,76576).
+char(5,76577).
+char(c,76578).
+char(p,76579).
+char(4,76580).
+char(8,76581).
+char(1,76582).
+char(0,76583).
+char(c,76584).
+char(m,76585).
+char(o,76586).
+char(p,76587).
+char(3,76588).
+char(6,76589).
+char(0,76590).
+char(0,76591).
+char(p,76592).
+char(7,76593).
+char(5,76594).
+char(3,76595).
+char(5,76596).
+char(c,76597).
+char(c,76598).
+char(c,76599).
+char(m,76600).
+char(o,76601).
+char(p,76602).
+char(7,76603).
+char(3,76604).
+char(9,76605).
+char(1,76606).
+char(m,76607).
+char(o,76608).
+char(p,76609).
+char(7,76610).
+char(1,76611).
+char(8,76612).
+char(2,76613).
+char(c,76614).
+char(p,76615).
+char(3,76616).
+char(1,76617).
+char(3,76618).
+char(6,76619).
+char(m,76620).
+char(4,76621).
+char(6,76622).
+char(7,76623).
+char(6,76624).
+char(c,76625).
+char(c,76626).
+char(c,76627).
+char(c,76628).
+char(p,76629).
+char(o,76630).
+char(m,76631).
+char(o,76632).
+char(p,76633).
+char(o,76634).
+char(6,76635).
+char(7,76636).
+char(4,76637).
+char(2,76638).
+char(p,76639).
+char(o,76640).
+char(p,76641).
+char(2,76642).
+char(6,76643).
+char(6,76644).
+char(4,76645).
+char(p,76646).
+char(o,76647).
+char(p,76648).
+char(8,76649).
+char(c,76650).
+char(m,76651).
+char(o,76652).
+char(p,76653).
+char(7,76654).
+char(0,76655).
+char(6,76656).
+char(0,76657).
+char(c,76658).
+char(c,76659).
+char(m,76660).
+char(o,76661).
+char(o,76662).
+char(m,76663).
+char(5,76664).
+char(4,76665).
+char(8,76666).
+char(0,76667).
+char(m,76668).
+char(o,76669).
+char(1,76670).
+char(4,76671).
+char(2,76672).
+char(5,76673).
+char(c,76674).
+char(m,76675).
+char(9,76676).
+char(8,76677).
+char(0,76678).
+char(9,76679).
+char(c,76680).
+char(c,76681).
+char(p,76682).
+char(2,76683).
+char(2,76684).
+char(6,76685).
+char(7,76686).
+char(c,76687).
+char(c,76688).
+char(c,76689).
+char(c,76690).
+char(c,76691).
+char(m,76692).
+char(9,76693).
+char(1,76694).
+char(3,76695).
+char(3,76696).
+char(m,76697).
+char(5,76698).
+char(6,76699).
+char(6,76700).
+char(4,76701).
+char(c,76702).
+char(c,76703).
+char(c,76704).
+char(c,76705).
+char(c,76706).
+char(c,76707).
+char(p,76708).
+char(o,76709).
+char(o,76710).
+char(m,76711).
+char(8,76712).
+char(8,76713).
+char(7,76714).
+char(1,76715).
+char(c,76716).
+char(c,76717).
+char(c,76718).
+char(p,76719).
+char(4,76720).
+char(3,76721).
+char(1,76722).
+char(0,76723).
+char(p,76724).
+char(2,76725).
+char(2,76726).
+char(7,76727).
+char(2,76728).
+char(c,76729).
+char(p,76730).
+char(9,76731).
+char(3,76732).
+char(4,76733).
+char(5,76734).
+char(m,76735).
+char(8,76736).
+char(2,76737).
+char(6,76738).
+char(1,76739).
+char(p,76740).
+char(o,76741).
+char(o,76742).
+char(p,76743).
+char(1,76744).
+char(1,76745).
+char(0,76746).
+char(3,76747).
+char(p,76748).
+char(o,76749).
+char(p,76750).
+char(o,76751).
+char(o,76752).
+char(m,76753).
+char(4,76754).
+char(9,76755).
+char(4,76756).
+char(p,76757).
+char(o,76758).
+char(p,76759).
+char(3,76760).
+char(5,76761).
+char(7,76762).
+char(c,76763).
+char(c,76764).
+char(c,76765).
+char(p,76766).
+char(o,76767).
+char(p,76768).
+char(3,76769).
+char(4,76770).
+char(6,76771).
+char(2,76772).
+char(c,76773).
+char(m,76774).
+char(1,76775).
+char(6,76776).
+char(9,76777).
+char(1,76778).
+char(c,76779).
+char(m,76780).
+char(7,76781).
+char(0,76782).
+char(7,76783).
+char(7,76784).
+char(m,76785).
+char(o,76786).
+char(o,76787).
+char(m,76788).
+char(o,76789).
+char(o,76790).
+char(p,76791).
+char(5,76792).
+char(2,76793).
+char(9,76794).
+char(7,76795).
+char(p,76796).
+char(o,76797).
+char(m,76798).
+char(o,76799).
+char(p,76800).
+char(o,76801).
+char(m,76802).
+char(o,76803).
+char(m,76804).
+char(o,76805).
+char(5,76806).
+char(0,76807).
+char(2,76808).
+char(2,76809).
+char(m,76810).
+char(7,76811).
+char(8,76812).
+char(6,76813).
+char(7,76814).
+char(p,76815).
+char(o,76816).
+char(6,76817).
+char(8,76818).
+char(5,76819).
+char(3,76820).
+char(c,76821).
+char(c,76822).
+char(p,76823).
+char(o,76824).
+char(m,76825).
+char(o,76826).
+char(o,76827).
+char(m,76828).
+char(o,76829).
+char(m,76830).
+char(4,76831).
+char(8,76832).
+char(4,76833).
+char(7,76834).
+char(c,76835).
+char(c,76836).
+char(p,76837).
+char(9,76838).
+char(6,76839).
+char(9,76840).
+char(9,76841).
+char(p,76842).
+char(o,76843).
+char(p,76844).
+char(o,76845).
+char(m,76846).
+char(o,76847).
+char(m,76848).
+char(8,76849).
+char(3,76850).
+char(8,76851).
+char(4,76852).
+char(m,76853).
+char(5,76854).
+char(1,76855).
+char(9,76856).
+char(c,76857).
+char(c,76858).
+char(p,76859).
+char(6,76860).
+char(9,76861).
+char(5,76862).
+char(1,76863).
+char(c,76864).
+char(c,76865).
+char(c,76866).
+char(c,76867).
+char(c,76868).
+char(m,76869).
+char(o,76870).
+char(7,76871).
+char(0,76872).
+char(6,76873).
+char(1,76874).
+char(m,76875).
+char(4,76876).
+char(3,76877).
+char(5,76878).
+char(2,76879).
+char(p,76880).
+char(o,76881).
+char(o,76882).
+char(p,76883).
+char(8,76884).
+char(0,76885).
+char(0,76886).
+char(2,76887).
+char(c,76888).
+char(m,76889).
+char(2,76890).
+char(2,76891).
+char(6,76892).
+char(3,76893).
+char(c,76894).
+char(c,76895).
+char(m,76896).
+char(o,76897).
+char(p,76898).
+char(o,76899).
+char(p,76900).
+char(o,76901).
+char(m,76902).
+char(5,76903).
+char(9,76904).
+char(5,76905).
+char(1,76906).
+char(m,76907).
+char(9,76908).
+char(3,76909).
+char(5,76910).
+char(9,76911).
+char(c,76912).
+char(m,76913).
+char(1,76914).
+char(4,76915).
+char(6,76916).
+char(7,76917).
+char(p,76918).
+char(4,76919).
+char(3,76920).
+char(6,76921).
+char(0,76922).
+char(p,76923).
+char(2,76924).
+char(6,76925).
+char(1,76926).
+char(5,76927).
+char(c,76928).
+char(p,76929).
+char(7,76930).
+char(9,76931).
+char(0,76932).
+char(8,76933).
+char(c,76934).
+char(c,76935).
+char(c,76936).
+char(p,76937).
+char(o,76938).
+char(7,76939).
+char(6,76940).
+char(6,76941).
+char(p,76942).
+char(8,76943).
+char(5,76944).
+char(9,76945).
+char(5,76946).
+char(p,76947).
+char(o,76948).
+char(m,76949).
+char(8,76950).
+char(4,76951).
+char(3,76952).
+char(1,76953).
+char(c,76954).
+char(c,76955).
+char(m,76956).
+char(4,76957).
+char(2,76958).
+char(3,76959).
+char(7,76960).
+char(p,76961).
+char(o,76962).
+char(m,76963).
+char(o,76964).
+char(p,76965).
+char(3,76966).
+char(9,76967).
+char(3,76968).
+char(4,76969).
+char(p,76970).
+char(o,76971).
+char(p,76972).
+char(1,76973).
+char(4,76974).
+char(3,76975).
+char(7,76976).
+char(p,76977).
+char(1,76978).
+char(2,76979).
+char(0,76980).
+char(2,76981).
+char(p,76982).
+char(6,76983).
+char(4,76984).
+char(4,76985).
+char(7,76986).
+char(c,76987).
+char(m,76988).
+char(o,76989).
+char(m,76990).
+char(7,76991).
+char(5,76992).
+char(2,76993).
+char(3,76994).
+char(p,76995).
+char(o,76996).
+char(p,76997).
+char(5,76998).
+char(6,76999).
+char(8,77000).
+char(5,77001).
+char(c,77002).
+char(p,77003).
+char(o,77004).
+char(o,77005).
+char(p,77006).
+char(o,77007).
+char(p,77008).
+char(7,77009).
+char(8,77010).
+char(7,77011).
+char(5,77012).
+char(m,77013).
+char(o,77014).
+char(p,77015).
+char(8,77016).
+char(9,77017).
+char(8,77018).
+char(0,77019).
+char(m,77020).
+char(1,77021).
+char(7,77022).
+char(3,77023).
+char(1,77024).
+char(p,77025).
+char(o,77026).
+char(p,77027).
+char(o,77028).
+char(p,77029).
+char(9,77030).
+char(0,77031).
+char(8,77032).
+char(5,77033).
+char(c,77034).
+char(m,77035).
+char(o,77036).
+char(5,77037).
+char(6,77038).
+char(4,77039).
+char(4,77040).
+char(c,77041).
+char(c,77042).
+char(c,77043).
+char(c,77044).
+char(c,77045).
+char(c,77046).
+char(c,77047).
+char(m,77048).
+char(9,77049).
+char(2,77050).
+char(5,77051).
+char(0,77052).
+char(c,77053).
+char(c,77054).
+char(p,77055).
+char(o,77056).
+char(o,77057).
+char(9,77058).
+char(6,77059).
+char(2,77060).
+char(1,77061).
+char(c,77062).
+char(c,77063).
+char(c,77064).
+char(c,77065).
+char(p,77066).
+char(o,77067).
+char(p,77068).
+char(o,77069).
+char(p,77070).
+char(o,77071).
+char(p,77072).
+char(6,77073).
+char(0,77074).
+char(7,77075).
+char(5,77076).
+char(c,77077).
+char(c,77078).
+char(c,77079).
+char(c,77080).
+char(c,77081).
+char(p,77082).
+char(5,77083).
+char(3,77084).
+char(4,77085).
+char(3,77086).
+char(m,77087).
+char(o,77088).
+char(o,77089).
+char(6,77090).
+char(9,77091).
+char(3,77092).
+char(m,77093).
+char(2,77094).
+char(1,77095).
+char(9,77096).
+char(7,77097).
+char(c,77098).
+char(p,77099).
+char(3,77100).
+char(9,77101).
+char(3,77102).
+char(8,77103).
+char(c,77104).
+char(c,77105).
+char(c,77106).
+char(c,77107).
+char(c,77108).
+char(m,77109).
+char(o,77110).
+char(m,77111).
+char(9,77112).
+char(6,77113).
+char(3,77114).
+char(6,77115).
+char(c,77116).
+char(m,77117).
+char(o,77118).
+char(m,77119).
+char(4,77120).
+char(5,77121).
+char(8,77122).
+char(6,77123).
+char(p,77124).
+char(o,77125).
+char(o,77126).
+char(p,77127).
+char(9,77128).
+char(9,77129).
+char(9,77130).
+char(5,77131).
+char(p,77132).
+char(o,77133).
+char(m,77134).
+char(o,77135).
+char(m,77136).
+char(7,77137).
+char(3,77138).
+char(2,77139).
+char(1,77140).
+char(c,77141).
+char(p,77142).
+char(o,77143).
+char(2,77144).
+char(3,77145).
+char(9,77146).
+char(m,77147).
+char(o,77148).
+char(m,77149).
+char(o,77150).
+char(1,77151).
+char(6,77152).
+char(6,77153).
+char(6,77154).
+char(p,77155).
+char(1,77156).
+char(7,77157).
+char(6,77158).
+char(8,77159).
+char(c,77160).
+char(c,77161).
+char(c,77162).
+char(p,77163).
+char(1,77164).
+char(6,77165).
+char(7,77166).
+char(0,77167).
+char(c,77168).
+char(c,77169).
+char(c,77170).
+char(p,77171).
+char(6,77172).
+char(5,77173).
+char(5,77174).
+char(7,77175).
+char(m,77176).
+char(o,77177).
+char(o,77178).
+char(p,77179).
+char(o,77180).
+char(m,77181).
+char(1,77182).
+char(4,77183).
+char(2,77184).
+char(8,77185).
+char(m,77186).
+char(6,77187).
+char(2,77188).
+char(6,77189).
+char(2,77190).
+char(m,77191).
+char(3,77192).
+char(9,77193).
+char(2,77194).
+char(5,77195).
+char(c,77196).
+char(c,77197).
+char(p,77198).
+char(9,77199).
+char(9,77200).
+char(4,77201).
+char(0,77202).
+char(p,77203).
+char(6,77204).
+char(9,77205).
+char(1,77206).
+char(9,77207).
+char(m,77208).
+char(o,77209).
+char(m,77210).
+char(o,77211).
+char(p,77212).
+char(o,77213).
+char(m,77214).
+char(o,77215).
+char(p,77216).
+char(o,77217).
+char(o,77218).
+char(m,77219).
+char(o,77220).
+char(p,77221).
+char(o,77222).
+char(o,77223).
+char(m,77224).
+char(o,77225).
+char(o,77226).
+char(o,77227).
+char(p,77228).
+char(2,77229).
+char(4,77230).
+char(6,77231).
+char(c,77232).
+char(c,77233).
+char(c,77234).
+char(c,77235).
+char(m,77236).
+char(o,77237).
+char(m,77238).
+char(9,77239).
+char(3,77240).
+char(0,77241).
+char(1,77242).
+char(p,77243).
+char(o,77244).
+char(m,77245).
+char(4,77246).
+char(7,77247).
+char(7,77248).
+char(0,77249).
+char(c,77250).
+char(p,77251).
+char(6,77252).
+char(0,77253).
+char(8,77254).
+char(8,77255).
+char(p,77256).
+char(2,77257).
+char(1,77258).
+char(7,77259).
+char(2,77260).
+char(c,77261).
+char(c,77262).
+char(p,77263).
+char(5,77264).
+char(3,77265).
+char(7,77266).
+char(9,77267).
+char(m,77268).
+char(o,77269).
+char(m,77270).
+char(o,77271).
+char(o,77272).
+char(o,77273).
+char(8,77274).
+char(2,77275).
+char(2,77276).
+char(1,77277).
+char(c,77278).
+char(p,77279).
+char(7,77280).
+char(5,77281).
+char(7,77282).
+char(8,77283).
+char(m,77284).
+char(2,77285).
+char(8,77286).
+char(3,77287).
+char(7,77288).
+char(m,77289).
+char(3,77290).
+char(1,77291).
+char(1,77292).
+char(0,77293).
+char(p,77294).
+char(o,77295).
+char(m,77296).
+char(3,77297).
+char(8,77298).
+char(5,77299).
+char(8,77300).
+char(p,77301).
+char(6,77302).
+char(8,77303).
+char(1,77304).
+char(1,77305).
+char(c,77306).
+char(c,77307).
+char(c,77308).
+char(m,77309).
+char(6,77310).
+char(7,77311).
+char(9,77312).
+char(3,77313).
+char(c,77314).
+char(m,77315).
+char(4,77316).
+char(6,77317).
+char(2,77318).
+char(2,77319).
+char(p,77320).
+char(o,77321).
+char(o,77322).
+char(p,77323).
+char(3,77324).
+char(7,77325).
+char(9,77326).
+char(8,77327).
+char(p,77328).
+char(o,77329).
+char(p,77330).
+char(7,77331).
+char(3,77332).
+char(7,77333).
+char(7,77334).
+char(m,77335).
+char(o,77336).
+char(o,77337).
+char(p,77338).
+char(6,77339).
+char(3,77340).
+char(9,77341).
+char(2,77342).
+char(c,77343).
+char(p,77344).
+char(5,77345).
+char(5,77346).
+char(6,77347).
+char(3,77348).
+char(c,77349).
+char(p,77350).
+char(2,77351).
+char(0,77352).
+char(2,77353).
+char(8,77354).
+char(p,77355).
+char(7,77356).
+char(9,77357).
+char(9,77358).
+char(9,77359).
+char(c,77360).
+char(p,77361).
+char(o,77362).
+char(m,77363).
+char(o,77364).
+char(m,77365).
+char(o,77366).
+char(m,77367).
+char(1,77368).
+char(8,77369).
+char(4,77370).
+char(2,77371).
+char(m,77372).
+char(3,77373).
+char(7,77374).
+char(6,77375).
+char(3,77376).
+char(c,77377).
+char(p,77378).
+char(o,77379).
+char(p,77380).
+char(o,77381).
+char(o,77382).
+char(m,77383).
+char(o,77384).
+char(p,77385).
+char(o,77386).
+char(o,77387).
+char(p,77388).
+char(8,77389).
+char(2,77390).
+char(0,77391).
+char(5,77392).
+char(c,77393).
+char(m,77394).
+char(8,77395).
+char(5,77396).
+char(4,77397).
+char(5,77398).
+char(p,77399).
+char(5,77400).
+char(2,77401).
+char(2,77402).
+char(6,77403).
+char(c,77404).
+char(c,77405).
+char(p,77406).
+char(o,77407).
+char(m,77408).
+char(9,77409).
+char(7,77410).
+char(6,77411).
+char(8,77412).
+char(c,77413).
+char(m,77414).
+char(1,77415).
+char(8,77416).
+char(5,77417).
+char(6,77418).
+char(c,77419).
+char(c,77420).
+char(m,77421).
+char(3,77422).
+char(7,77423).
+char(9,77424).
+char(c,77425).
+char(c,77426).
+char(m,77427).
+char(o,77428).
+char(m,77429).
+char(9,77430).
+char(0,77431).
+char(8,77432).
+char(7,77433).
+char(c,77434).
+char(m,77435).
+char(2,77436).
+char(3,77437).
+char(1,77438).
+char(6,77439).
+char(m,77440).
+char(o,77441).
+char(m,77442).
+char(o,77443).
+char(m,77444).
+char(o,77445).
+char(p,77446).
+char(6,77447).
+char(4,77448).
+char(7,77449).
+char(3,77450).
+char(c,77451).
+char(p,77452).
+char(o,77453).
+char(p,77454).
+char(o,77455).
+char(m,77456).
+char(3,77457).
+char(0,77458).
+char(5,77459).
+char(7,77460).
+char(p,77461).
+char(2,77462).
+char(5,77463).
+char(6,77464).
+char(1,77465).
+char(p,77466).
+char(8,77467).
+char(2,77468).
+char(7,77469).
+char(0,77470).
+char(c,77471).
+char(c,77472).
+char(m,77473).
+char(1,77474).
+char(9,77475).
+char(0,77476).
+char(9,77477).
+char(c,77478).
+char(p,77479).
+char(o,77480).
+char(m,77481).
+char(o,77482).
+char(p,77483).
+char(o,77484).
+char(o,77485).
+char(3,77486).
+char(9,77487).
+char(0,77488).
+char(4,77489).
+char(c,77490).
+char(c,77491).
+char(m,77492).
+char(o,77493).
+char(o,77494).
+char(m,77495).
+char(7,77496).
+char(0,77497).
+char(1,77498).
+char(9,77499).
+char(c,77500).
+char(c,77501).
+char(c,77502).
+char(m,77503).
+char(o,77504).
+char(2,77505).
+char(3,77506).
+char(7,77507).
+char(1,77508).
+char(m,77509).
+char(o,77510).
+char(p,77511).
+char(o,77512).
+char(m,77513).
+char(4,77514).
+char(7,77515).
+char(8,77516).
+char(8,77517).
+char(c,77518).
+char(c,77519).
+char(p,77520).
+char(8,77521).
+char(5,77522).
+char(2,77523).
+char(7,77524).
+char(p,77525).
+char(6,77526).
+char(4,77527).
+char(1,77528).
+char(5,77529).
+char(p,77530).
+char(o,77531).
+char(1,77532).
+char(9,77533).
+char(5,77534).
+char(9,77535).
+char(c,77536).
+char(c,77537).
+char(m,77538).
+char(o,77539).
+char(4,77540).
+char(3,77541).
+char(6,77542).
+char(0,77543).
+char(c,77544).
+char(p,77545).
+char(o,77546).
+char(m,77547).
+char(o,77548).
+char(p,77549).
+char(o,77550).
+char(m,77551).
+char(2,77552).
+char(8,77553).
+char(3,77554).
+char(4,77555).
+char(p,77556).
+char(7,77557).
+char(4,77558).
+char(8,77559).
+char(9,77560).
+char(p,77561).
+char(9,77562).
+char(1,77563).
+char(7,77564).
+char(5,77565).
+char(c,77566).
+char(c,77567).
+char(c,77568).
+char(m,77569).
+char(o,77570).
+char(o,77571).
+char(m,77572).
+char(8,77573).
+char(3,77574).
+char(4,77575).
+char(7,77576).
+char(c,77577).
+char(c,77578).
+char(m,77579).
+char(o,77580).
+char(m,77581).
+char(o,77582).
+char(o,77583).
+char(p,77584).
+char(7,77585).
+char(0,77586).
+char(5,77587).
+char(8,77588).
+char(p,77589).
+char(3,77590).
+char(6,77591).
+char(1,77592).
+char(9,77593).
+char(c,77594).
+char(c,77595).
+char(c,77596).
+char(m,77597).
+char(7,77598).
+char(0,77599).
+char(4,77600).
+char(9,77601).
+char(m,77602).
+char(9,77603).
+char(9,77604).
+char(8,77605).
+char(0,77606).
+char(m,77607).
+char(1,77608).
+char(7,77609).
+char(8,77610).
+char(2,77611).
+char(c,77612).
+char(p,77613).
+char(o,77614).
+char(3,77615).
+char(7,77616).
+char(5,77617).
+char(0,77618).
+char(c,77619).
+char(c,77620).
+char(c,77621).
+char(c,77622).
+char(p,77623).
+char(o,77624).
+char(m,77625).
+char(o,77626).
+char(p,77627).
+char(o,77628).
+char(m,77629).
+char(2,77630).
+char(8,77631).
+char(0,77632).
+char(2,77633).
+char(c,77634).
+char(c,77635).
+char(p,77636).
+char(o,77637).
+char(p,77638).
+char(9,77639).
+char(4,77640).
+char(m,77641).
+char(2,77642).
+char(1,77643).
+char(5,77644).
+char(1,77645).
+char(p,77646).
+char(4,77647).
+char(3,77648).
+char(6,77649).
+char(2,77650).
+char(p,77651).
+char(o,77652).
+char(9,77653).
+char(2,77654).
+char(6,77655).
+char(0,77656).
+char(p,77657).
+char(o,77658).
+char(m,77659).
+char(3,77660).
+char(1,77661).
+char(3,77662).
+char(4,77663).
+char(c,77664).
+char(c,77665).
+char(c,77666).
+char(c,77667).
+char(c,77668).
+char(p,77669).
+char(3,77670).
+char(7,77671).
+char(0,77672).
+char(8,77673).
+char(p,77674).
+char(o,77675).
+char(m,77676).
+char(4,77677).
+char(4,77678).
+char(7,77679).
+char(4,77680).
+char(m,77681).
+char(2,77682).
+char(6,77683).
+char(1,77684).
+char(9,77685).
+char(p,77686).
+char(o,77687).
+char(m,77688).
+char(1,77689).
+char(6,77690).
+char(4,77691).
+char(8,77692).
+char(m,77693).
+char(3,77694).
+char(3,77695).
+char(3,77696).
+char(3,77697).
+char(p,77698).
+char(o,77699).
+char(p,77700).
+char(o,77701).
+char(p,77702).
+char(3,77703).
+char(2,77704).
+char(2,77705).
+char(7,77706).
+char(c,77707).
+char(m,77708).
+char(o,77709).
+char(o,77710).
+char(2,77711).
+char(5,77712).
+char(5,77713).
+char(7,77714).
+char(p,77715).
+char(o,77716).
+char(m,77717).
+char(1,77718).
+char(5,77719).
+char(1,77720).
+char(8,77721).
+char(m,77722).
+char(4,77723).
+char(6,77724).
+char(9,77725).
+char(1,77726).
+char(p,77727).
+char(o,77728).
+char(o,77729).
+char(m,77730).
+char(o,77731).
+char(p,77732).
+char(o,77733).
+char(p,77734).
+char(o,77735).
+char(p,77736).
+char(3,77737).
+char(4,77738).
+char(2,77739).
+char(1,77740).
+char(c,77741).
+char(m,77742).
+char(o,77743).
+char(m,77744).
+char(o,77745).
+char(p,77746).
+char(o,77747).
+char(m,77748).
+char(1,77749).
+char(6,77750).
+char(0,77751).
+char(0,77752).
+char(c,77753).
+char(p,77754).
+char(6,77755).
+char(2,77756).
+char(3,77757).
+char(5,77758).
+char(m,77759).
+char(o,77760).
+char(m,77761).
+char(o,77762).
+char(m,77763).
+char(o,77764).
+char(m,77765).
+char(8,77766).
+char(9,77767).
+char(3,77768).
+char(p,77769).
+char(o,77770).
+char(o,77771).
+char(m,77772).
+char(o,77773).
+char(p,77774).
+char(o,77775).
+char(m,77776).
+char(7,77777).
+char(4,77778).
+char(6,77779).
+char(0,77780).
+char(p,77781).
+char(o,77782).
+char(p,77783).
+char(2,77784).
+char(9,77785).
+char(3,77786).
+char(4,77787).
+char(c,77788).
+char(c,77789).
+char(m,77790).
+char(o,77791).
+char(o,77792).
+char(m,77793).
+char(o,77794).
+char(p,77795).
+char(1,77796).
+char(4,77797).
+char(9,77798).
+char(8,77799).
+char(p,77800).
+char(8,77801).
+char(1,77802).
+char(9,77803).
+char(8,77804).
+char(m,77805).
+char(5,77806).
+char(4,77807).
+char(9,77808).
+char(0,77809).
+char(c,77810).
+char(p,77811).
+char(7,77812).
+char(2,77813).
+char(8,77814).
+char(6,77815).
+char(m,77816).
+char(o,77817).
+char(p,77818).
+char(1,77819).
+char(7,77820).
+char(9,77821).
+char(9,77822).
+char(c,77823).
+char(p,77824).
+char(8,77825).
+char(9,77826).
+char(6,77827).
+char(5,77828).
+char(p,77829).
+char(4,77830).
+char(8,77831).
+char(8,77832).
+char(2,77833).
+char(c,77834).
+char(c,77835).
+char(p,77836).
+char(o,77837).
+char(o,77838).
+char(p,77839).
+char(o,77840).
+char(p,77841).
+char(o,77842).
+char(p,77843).
+char(o,77844).
+char(p,77845).
+char(o,77846).
+char(o,77847).
+char(m,77848).
+char(o,77849).
+char(m,77850).
+char(o,77851).
+char(m,77852).
+char(o,77853).
+char(m,77854).
+char(o,77855).
+char(p,77856).
+char(3,77857).
+char(4,77858).
+char(6,77859).
+char(3,77860).
+char(p,77861).
+char(1,77862).
+char(0,77863).
+char(9,77864).
+char(8,77865).
+char(m,77866).
+char(9,77867).
+char(1,77868).
+char(6,77869).
+char(8,77870).
+char(m,77871).
+char(4,77872).
+char(1,77873).
+char(6,77874).
+char(6,77875).
+char(m,77876).
+char(4,77877).
+char(7,77878).
+char(0,77879).
+char(8,77880).
+char(m,77881).
+char(1,77882).
+char(3,77883).
+char(4,77884).
+char(2,77885).
+char(c,77886).
+char(c,77887).
+char(p,77888).
+char(1,77889).
+char(8,77890).
+char(9,77891).
+char(3,77892).
+char(c,77893).
+char(c,77894).
+char(m,77895).
+char(4,77896).
+char(4,77897).
+char(2,77898).
+char(0,77899).
+char(c,77900).
+char(c,77901).
+char(c,77902).
+char(c,77903).
+char(m,77904).
+char(6,77905).
+char(1,77906).
+char(7,77907).
+char(2,77908).
+char(c,77909).
+char(m,77910).
+char(3,77911).
+char(3,77912).
+char(8,77913).
+char(m,77914).
+char(o,77915).
+char(m,77916).
+char(o,77917).
+char(3,77918).
+char(1,77919).
+char(4,77920).
+char(c,77921).
+char(c,77922).
+char(c,77923).
+char(p,77924).
+char(o,77925).
+char(p,77926).
+char(o,77927).
+char(6,77928).
+char(1,77929).
+char(5,77930).
+char(1,77931).
+char(c,77932).
+char(c,77933).
+char(c,77934).
+char(c,77935).
+char(p,77936).
+char(8,77937).
+char(7,77938).
+char(9,77939).
+char(9,77940).
+char(p,77941).
+char(2,77942).
+char(1,77943).
+char(3,77944).
+char(8,77945).
+char(c,77946).
+char(p,77947).
+char(o,77948).
+char(m,77949).
+char(9,77950).
+char(9,77951).
+char(3,77952).
+char(2,77953).
+char(m,77954).
+char(6,77955).
+char(4,77956).
+char(8,77957).
+char(1,77958).
+char(c,77959).
+char(c,77960).
+char(c,77961).
+char(p,77962).
+char(o,77963).
+char(m,77964).
+char(7,77965).
+char(8,77966).
+char(8,77967).
+char(6,77968).
+char(c,77969).
+char(p,77970).
+char(o,77971).
+char(m,77972).
+char(9,77973).
+char(4,77974).
+char(9,77975).
+char(6,77976).
+char(p,77977).
+char(o,77978).
+char(m,77979).
+char(5,77980).
+char(1,77981).
+char(1,77982).
+char(8,77983).
+char(p,77984).
+char(o,77985).
+char(4,77986).
+char(2,77987).
+char(5,77988).
+char(0,77989).
+char(p,77990).
+char(o,77991).
+char(p,77992).
+char(o,77993).
+char(m,77994).
+char(9,77995).
+char(7,77996).
+char(2,77997).
+char(7,77998).
+char(c,77999).
+char(c,78000).
+char(p,78001).
+char(o,78002).
+char(7,78003).
+char(1,78004).
+char(1,78005).
+char(1,78006).
+char(p,78007).
+char(9,78008).
+char(1,78009).
+char(7,78010).
+char(6,78011).
+char(p,78012).
+char(8,78013).
+char(3,78014).
+char(1,78015).
+char(9,78016).
+char(c,78017).
+char(p,78018).
+char(o,78019).
+char(o,78020).
+char(m,78021).
+char(3,78022).
+char(8,78023).
+char(3,78024).
+char(5,78025).
+char(p,78026).
+char(8,78027).
+char(2,78028).
+char(0,78029).
+char(7,78030).
+char(p,78031).
+char(6,78032).
+char(7,78033).
+char(1,78034).
+char(6,78035).
+char(c,78036).
+char(c,78037).
+char(c,78038).
+char(m,78039).
+char(o,78040).
+char(o,78041).
+char(5,78042).
+char(7,78043).
+char(8,78044).
+char(7,78045).
+char(c,78046).
+char(m,78047).
+char(o,78048).
+char(2,78049).
+char(0,78050).
+char(5,78051).
+char(9,78052).
+char(c,78053).
+char(m,78054).
+char(9,78055).
+char(7,78056).
+char(9,78057).
+char(2,78058).
+char(p,78059).
+char(o,78060).
+char(p,78061).
+char(3,78062).
+char(7,78063).
+char(6,78064).
+char(8,78065).
+char(p,78066).
+char(o,78067).
+char(m,78068).
+char(o,78069).
+char(m,78070).
+char(o,78071).
+char(m,78072).
+char(o,78073).
+char(m,78074).
+char(9,78075).
+char(0,78076).
+char(7,78077).
+char(2,78078).
+char(c,78079).
+char(c,78080).
+char(c,78081).
+char(c,78082).
+char(c,78083).
+char(c,78084).
+char(m,78085).
+char(8,78086).
+char(6,78087).
+char(0,78088).
+char(4,78089).
+char(m,78090).
+char(o,78091).
+char(o,78092).
+char(o,78093).
+char(m,78094).
+char(5,78095).
+char(5,78096).
+char(9,78097).
+char(2,78098).
+char(c,78099).
+char(p,78100).
+char(o,78101).
+char(m,78102).
+char(o,78103).
+char(p,78104).
+char(o,78105).
+char(p,78106).
+char(9,78107).
+char(3,78108).
+char(1,78109).
+char(5,78110).
+char(c,78111).
+char(m,78112).
+char(8,78113).
+char(1,78114).
+char(0,78115).
+char(0,78116).
+char(m,78117).
+char(o,78118).
+char(o,78119).
+char(p,78120).
+char(o,78121).
+char(o,78122).
+char(m,78123).
+char(4,78124).
+char(0,78125).
+char(3,78126).
+char(8,78127).
+char(m,78128).
+char(2,78129).
+char(5,78130).
+char(7,78131).
+char(9,78132).
+char(c,78133).
+char(c,78134).
+char(c,78135).
+char(p,78136).
+char(6,78137).
+char(9,78138).
+char(2,78139).
+char(8,78140).
+char(c,78141).
+char(c,78142).
+char(c,78143).
+char(c,78144).
+char(c,78145).
+char(p,78146).
+char(9,78147).
+char(3,78148).
+char(2,78149).
+char(6,78150).
+char(c,78151).
+char(c,78152).
+char(m,78153).
+char(2,78154).
+char(4,78155).
+char(9,78156).
+char(7,78157).
+char(m,78158).
+char(o,78159).
+char(m,78160).
+char(2,78161).
+char(9,78162).
+char(7,78163).
+char(8,78164).
+char(c,78165).
+char(m,78166).
+char(4,78167).
+char(7,78168).
+char(5,78169).
+char(7,78170).
+char(p,78171).
+char(o,78172).
+char(p,78173).
+char(o,78174).
+char(m,78175).
+char(o,78176).
+char(p,78177).
+char(4,78178).
+char(2,78179).
+char(c,78180).
+char(m,78181).
+char(7,78182).
+char(1,78183).
+char(7,78184).
+char(5,78185).
+char(m,78186).
+char(5,78187).
+char(7,78188).
+char(5,78189).
+char(2,78190).
+char(c,78191).
+char(c,78192).
+char(c,78193).
+char(p,78194).
+char(o,78195).
+char(p,78196).
+char(o,78197).
+char(7,78198).
+char(9,78199).
+char(9,78200).
+char(c,78201).
+char(c,78202).
+char(c,78203).
+char(c,78204).
+char(c,78205).
+char(c,78206).
+char(p,78207).
+char(4,78208).
+char(1,78209).
+char(2,78210).
+char(8,78211).
+char(p,78212).
+char(o,78213).
+char(m,78214).
+char(7,78215).
+char(2,78216).
+char(1,78217).
+char(2,78218).
+char(p,78219).
+char(o,78220).
+char(m,78221).
+char(o,78222).
+char(p,78223).
+char(9,78224).
+char(3,78225).
+char(5,78226).
+char(9,78227).
+char(c,78228).
+char(m,78229).
+char(6,78230).
+char(8,78231).
+char(5,78232).
+char(3,78233).
+char(c,78234).
+char(p,78235).
+char(o,78236).
+char(5,78237).
+char(1,78238).
+char(5,78239).
+char(8,78240).
+char(p,78241).
+char(o,78242).
+char(p,78243).
+char(4,78244).
+char(4,78245).
+char(5,78246).
+char(9,78247).
+char(c,78248).
+char(c,78249).
+char(c,78250).
+char(c,78251).
+char(m,78252).
+char(o,78253).
+char(p,78254).
+char(6,78255).
+char(4,78256).
+char(9,78257).
+char(4,78258).
+char(p,78259).
+char(1,78260).
+char(0,78261).
+char(2,78262).
+char(1,78263).
+char(m,78264).
+char(o,78265).
+char(8,78266).
+char(5,78267).
+char(3,78268).
+char(c,78269).
+char(c,78270).
+char(m,78271).
+char(2,78272).
+char(1,78273).
+char(4,78274).
+char(4,78275).
+char(m,78276).
+char(1,78277).
+char(7,78278).
+char(3,78279).
+char(2,78280).
+char(c,78281).
+char(p,78282).
+char(7,78283).
+char(3,78284).
+char(0,78285).
+char(4,78286).
+char(c,78287).
+char(c,78288).
+char(c,78289).
+char(m,78290).
+char(8,78291).
+char(0,78292).
+char(1,78293).
+char(6,78294).
+char(m,78295).
+char(3,78296).
+char(9,78297).
+char(m,78298).
+char(o,78299).
+char(p,78300).
+char(1,78301).
+char(3,78302).
+char(3,78303).
+char(5,78304).
+char(m,78305).
+char(2,78306).
+char(7,78307).
+char(4,78308).
+char(6,78309).
+char(c,78310).
+char(c,78311).
+char(p,78312).
+char(o,78313).
+char(o,78314).
+char(m,78315).
+char(9,78316).
+char(7,78317).
+char(6,78318).
+char(1,78319).
+char(c,78320).
+char(m,78321).
+char(1,78322).
+char(2,78323).
+char(9,78324).
+char(7,78325).
+char(m,78326).
+char(5,78327).
+char(0,78328).
+char(5,78329).
+char(c,78330).
+char(p,78331).
+char(3,78332).
+char(3,78333).
+char(6,78334).
+char(3,78335).
+char(c,78336).
+char(c,78337).
+char(c,78338).
+char(p,78339).
+char(7,78340).
+char(6,78341).
+char(8,78342).
+char(8,78343).
+char(p,78344).
+char(4,78345).
+char(1,78346).
+char(8,78347).
+char(7,78348).
+char(m,78349).
+char(8,78350).
+char(7,78351).
+char(1,78352).
+char(5,78353).
+char(p,78354).
+char(o,78355).
+char(p,78356).
+char(o,78357).
+char(p,78358).
+char(7,78359).
+char(3,78360).
+char(5,78361).
+char(1,78362).
+char(m,78363).
+char(1,78364).
+char(2,78365).
+char(0,78366).
+char(7,78367).
+char(c,78368).
+char(c,78369).
+char(p,78370).
+char(7,78371).
+char(0,78372).
+char(5,78373).
+char(7,78374).
+char(c,78375).
+char(p,78376).
+char(o,78377).
+char(4,78378).
+char(9,78379).
+char(8,78380).
+char(6,78381).
+char(m,78382).
+char(o,78383).
+char(m,78384).
+char(o,78385).
+char(p,78386).
+char(9,78387).
+char(3,78388).
+char(2,78389).
+char(5,78390).
+char(c,78391).
+char(m,78392).
+char(8,78393).
+char(6,78394).
+char(7,78395).
+char(4,78396).
+char(c,78397).
+char(c,78398).
+char(m,78399).
+char(7,78400).
+char(5,78401).
+char(3,78402).
+char(4,78403).
+char(c,78404).
+char(p,78405).
+char(5,78406).
+char(5,78407).
+char(6,78408).
+char(0,78409).
+char(m,78410).
+char(o,78411).
+char(o,78412).
+char(o,78413).
+char(p,78414).
+char(o,78415).
+char(3,78416).
+char(7,78417).
+char(8,78418).
+char(3,78419).
+char(c,78420).
+char(c,78421).
+char(c,78422).
+char(m,78423).
+char(o,78424).
+char(m,78425).
+char(o,78426).
+char(m,78427).
+char(o,78428).
+char(m,78429).
+char(o,78430).
+char(m,78431).
+char(5,78432).
+char(5,78433).
+char(3,78434).
+char(c,78435).
+char(m,78436).
+char(o,78437).
+char(p,78438).
+char(o,78439).
+char(p,78440).
+char(2,78441).
+char(2,78442).
+char(2,78443).
+char(5,78444).
+char(c,78445).
+char(c,78446).
+char(p,78447).
+char(o,78448).
+char(m,78449).
+char(1,78450).
+char(6,78451).
+char(8,78452).
+char(9,78453).
+char(p,78454).
+char(o,78455).
+char(p,78456).
+char(5,78457).
+char(4,78458).
+char(7,78459).
+char(p,78460).
+char(o,78461).
+char(p,78462).
+char(o,78463).
+char(o,78464).
+char(4,78465).
+char(3,78466).
+char(6,78467).
+char(2,78468).
+char(c,78469).
+char(p,78470).
+char(o,78471).
+char(p,78472).
+char(o,78473).
+char(p,78474).
+char(9,78475).
+char(7,78476).
+char(2,78477).
+char(0,78478).
+char(c,78479).
+char(c,78480).
+char(c,78481).
+char(p,78482).
+char(o,78483).
+char(p,78484).
+char(5,78485).
+char(9,78486).
+char(1,78487).
+char(4,78488).
+char(c,78489).
+char(c,78490).
+char(p,78491).
+char(8,78492).
+char(8,78493).
+char(4,78494).
+char(6,78495).
+char(m,78496).
+char(8,78497).
+char(5,78498).
+char(9,78499).
+char(8,78500).
+char(c,78501).
+char(m,78502).
+char(o,78503).
+char(p,78504).
+char(o,78505).
+char(p,78506).
+char(4,78507).
+char(4,78508).
+char(9,78509).
+char(1,78510).
+char(c,78511).
+char(c,78512).
+char(p,78513).
+char(o,78514).
+char(p,78515).
+char(9,78516).
+char(0,78517).
+char(6,78518).
+char(1,78519).
+char(m,78520).
+char(o,78521).
+char(o,78522).
+char(6,78523).
+char(4,78524).
+char(1,78525).
+char(1,78526).
+char(c,78527).
+char(m,78528).
+char(7,78529).
+char(6,78530).
+char(0,78531).
+char(5,78532).
+char(c,78533).
+char(m,78534).
+char(o,78535).
+char(o,78536).
+char(m,78537).
+char(o,78538).
+char(p,78539).
+char(o,78540).
+char(p,78541).
+char(o,78542).
+char(p,78543).
+char(8,78544).
+char(4,78545).
+char(2,78546).
+char(m,78547).
+char(8,78548).
+char(4,78549).
+char(8,78550).
+char(c,78551).
+char(c,78552).
+char(p,78553).
+char(o,78554).
+char(m,78555).
+char(o,78556).
+char(p,78557).
+char(o,78558).
+char(p,78559).
+char(7,78560).
+char(2,78561).
+char(8,78562).
+char(5,78563).
+char(c,78564).
+char(p,78565).
+char(5,78566).
+char(6,78567).
+char(2,78568).
+char(3,78569).
+char(m,78570).
+char(6,78571).
+char(9,78572).
+char(6,78573).
+char(0,78574).
+char(c,78575).
+char(c,78576).
+char(m,78577).
+char(o,78578).
+char(p,78579).
+char(o,78580).
+char(o,78581).
+char(o,78582).
+char(7,78583).
+char(8,78584).
+char(1,78585).
+char(6,78586).
+char(c,78587).
+char(c,78588).
+char(m,78589).
+char(1,78590).
+char(9,78591).
+char(5,78592).
+char(1,78593).
+char(c,78594).
+char(p,78595).
+char(7,78596).
+char(1,78597).
+char(1,78598).
+char(3,78599).
+char(c,78600).
+char(c,78601).
+char(c,78602).
+char(c,78603).
+char(m,78604).
+char(8,78605).
+char(1,78606).
+char(3,78607).
+char(6,78608).
+char(p,78609).
+char(2,78610).
+char(1,78611).
+char(6,78612).
+char(8,78613).
+char(c,78614).
+char(m,78615).
+char(3,78616).
+char(2,78617).
+char(5,78618).
+char(4,78619).
+char(m,78620).
+char(5,78621).
+char(8,78622).
+char(6,78623).
+char(8,78624).
+char(c,78625).
+char(c,78626).
+char(c,78627).
+char(m,78628).
+char(2,78629).
+char(7,78630).
+char(4,78631).
+char(1,78632).
+char(p,78633).
+char(o,78634).
+char(m,78635).
+char(o,78636).
+char(p,78637).
+char(o,78638).
+char(p,78639).
+char(7,78640).
+char(4,78641).
+char(1,78642).
+char(6,78643).
+char(p,78644).
+char(6,78645).
+char(9,78646).
+char(4,78647).
+char(5,78648).
+char(c,78649).
+char(p,78650).
+char(o,78651).
+char(o,78652).
+char(o,78653).
+char(p,78654).
+char(o,78655).
+char(m,78656).
+char(o,78657).
+char(o,78658).
+char(p,78659).
+char(8,78660).
+char(0,78661).
+char(m,78662).
+char(1,78663).
+char(4,78664).
+char(0,78665).
+char(6,78666).
+char(p,78667).
+char(9,78668).
+char(0,78669).
+char(1,78670).
+char(3,78671).
+char(c,78672).
+char(c,78673).
+char(c,78674).
+char(c,78675).
+char(c,78676).
+char(c,78677).
+char(c,78678).
+char(c,78679).
+char(c,78680).
+char(m,78681).
+char(o,78682).
+char(p,78683).
+char(4,78684).
+char(7,78685).
+char(4,78686).
+char(c,78687).
+char(m,78688).
+char(4,78689).
+char(5,78690).
+char(4,78691).
+char(1,78692).
+char(c,78693).
+char(m,78694).
+char(7,78695).
+char(5,78696).
+char(5,78697).
+char(9,78698).
+char(c,78699).
+char(c,78700).
+char(p,78701).
+char(7,78702).
+char(2,78703).
+char(1,78704).
+char(2,78705).
+char(c,78706).
+char(p,78707).
+char(6,78708).
+char(6,78709).
+char(7,78710).
+char(2,78711).
+char(c,78712).
+char(c,78713).
+char(m,78714).
+char(o,78715).
+char(p,78716).
+char(o,78717).
+char(m,78718).
+char(3,78719).
+char(5,78720).
+char(0,78721).
+char(1,78722).
+char(p,78723).
+char(4,78724).
+char(5,78725).
+char(0,78726).
+char(4,78727).
+char(m,78728).
+char(9,78729).
+char(9,78730).
+char(1,78731).
+char(0,78732).
+char(c,78733).
+char(p,78734).
+char(1,78735).
+char(2,78736).
+char(4,78737).
+char(1,78738).
+char(c,78739).
+char(m,78740).
+char(1,78741).
+char(4,78742).
+char(3,78743).
+char(4,78744).
+char(m,78745).
+char(o,78746).
+char(p,78747).
+char(o,78748).
+char(m,78749).
+char(o,78750).
+char(o,78751).
+char(m,78752).
+char(6,78753).
+char(7,78754).
+char(6,78755).
+char(9,78756).
+char(c,78757).
+char(m,78758).
+char(o,78759).
+char(m,78760).
+char(o,78761).
+char(m,78762).
+char(8,78763).
+char(0,78764).
+char(4,78765).
+char(3,78766).
+char(m,78767).
+char(7,78768).
+char(9,78769).
+char(3,78770).
+char(5,78771).
+char(p,78772).
+char(o,78773).
+char(m,78774).
+char(o,78775).
+char(m,78776).
+char(4,78777).
+char(5,78778).
+char(5,78779).
+char(3,78780).
+char(c,78781).
+char(c,78782).
+char(m,78783).
+char(o,78784).
+char(2,78785).
+char(6,78786).
+char(1,78787).
+char(9,78788).
+char(c,78789).
+char(c,78790).
+char(c,78791).
+char(m,78792).
+char(9,78793).
+char(0,78794).
+char(4,78795).
+char(7,78796).
+char(c,78797).
+char(c,78798).
+char(c,78799).
+char(c,78800).
+char(c,78801).
+char(m,78802).
+char(4,78803).
+char(7,78804).
+char(4,78805).
+char(0,78806).
+char(m,78807).
+char(8,78808).
+char(8,78809).
+char(3,78810).
+char(5,78811).
+char(p,78812).
+char(5,78813).
+char(8,78814).
+char(6,78815).
+char(c,78816).
+char(c,78817).
+char(c,78818).
+char(m,78819).
+char(2,78820).
+char(2,78821).
+char(2,78822).
+char(8,78823).
+char(p,78824).
+char(5,78825).
+char(9,78826).
+char(6,78827).
+char(9,78828).
+char(m,78829).
+char(o,78830).
+char(m,78831).
+char(8,78832).
+char(3,78833).
+char(4,78834).
+char(4,78835).
+char(p,78836).
+char(o,78837).
+char(o,78838).
+char(o,78839).
+char(p,78840).
+char(o,78841).
+char(m,78842).
+char(1,78843).
+char(6,78844).
+char(0,78845).
+char(0,78846).
+char(p,78847).
+char(o,78848).
+char(p,78849).
+char(o,78850).
+char(m,78851).
+char(o,78852).
+char(8,78853).
+char(9,78854).
+char(2,78855).
+char(9,78856).
+char(p,78857).
+char(7,78858).
+char(1,78859).
+char(7,78860).
+char(9,78861).
+char(c,78862).
+char(c,78863).
+char(c,78864).
+char(c,78865).
+char(p,78866).
+char(o,78867).
+char(p,78868).
+char(o,78869).
+char(p,78870).
+char(9,78871).
+char(3,78872).
+char(3,78873).
+char(1,78874).
+char(m,78875).
+char(1,78876).
+char(0,78877).
+char(c,78878).
+char(c,78879).
+char(m,78880).
+char(o,78881).
+char(o,78882).
+char(m,78883).
+char(o,78884).
+char(m,78885).
+char(3,78886).
+char(5,78887).
+char(4,78888).
+char(2,78889).
+char(m,78890).
+char(2,78891).
+char(6,78892).
+char(9,78893).
+char(9,78894).
+char(p,78895).
+char(9,78896).
+char(5,78897).
+char(2,78898).
+char(8,78899).
+char(p,78900).
+char(8,78901).
+char(5,78902).
+char(5,78903).
+char(4,78904).
+char(p,78905).
+char(o,78906).
+char(m,78907).
+char(9,78908).
+char(9,78909).
+char(8,78910).
+char(6,78911).
+char(m,78912).
+char(o,78913).
+char(m,78914).
+char(o,78915).
+char(p,78916).
+char(9,78917).
+char(6,78918).
+char(2,78919).
+char(0,78920).
+char(c,78921).
+char(m,78922).
+char(o,78923).
+char(m,78924).
+char(o,78925).
+char(5,78926).
+char(8,78927).
+char(4,78928).
+char(3,78929).
+char(c,78930).
+char(c,78931).
+char(c,78932).
+char(c,78933).
+char(p,78934).
+char(o,78935).
+char(4,78936).
+char(8,78937).
+char(9,78938).
+char(5,78939).
+char(m,78940).
+char(o,78941).
+char(m,78942).
+char(6,78943).
+char(1,78944).
+char(7,78945).
+char(8,78946).
+char(c,78947).
+char(m,78948).
+char(o,78949).
+char(m,78950).
+char(o,78951).
+char(p,78952).
+char(4,78953).
+char(1,78954).
+char(4,78955).
+char(5,78956).
+char(c,78957).
+char(p,78958).
+char(o,78959).
+char(p,78960).
+char(o,78961).
+char(p,78962).
+char(9,78963).
+char(4,78964).
+char(3,78965).
+char(8,78966).
+char(c,78967).
+char(c,78968).
+char(c,78969).
+char(c,78970).
+char(c,78971).
+char(m,78972).
+char(8,78973).
+char(1,78974).
+char(9,78975).
+char(2,78976).
+char(p,78977).
+char(o,78978).
+char(m,78979).
+char(o,78980).
+char(p,78981).
+char(2,78982).
+char(8,78983).
+char(2,78984).
+char(4,78985).
+char(m,78986).
+char(4,78987).
+char(8,78988).
+char(9,78989).
+char(2,78990).
+char(c,78991).
+char(c,78992).
+char(c,78993).
+char(c,78994).
+char(c,78995).
+char(c,78996).
+char(c,78997).
+char(m,78998).
+char(6,78999).
+char(8,79000).
+char(0,79001).
+char(8,79002).
+char(c,79003).
+char(c,79004).
+char(c,79005).
+char(m,79006).
+char(2,79007).
+char(8,79008).
+char(3,79009).
+char(7,79010).
+char(c,79011).
+char(c,79012).
+char(m,79013).
+char(7,79014).
+char(0,79015).
+char(8,79016).
+char(4,79017).
+char(p,79018).
+char(4,79019).
+char(7,79020).
+char(2,79021).
+char(5,79022).
+char(c,79023).
+char(p,79024).
+char(7,79025).
+char(6,79026).
+char(5,79027).
+char(2,79028).
+char(c,79029).
+char(m,79030).
+char(o,79031).
+char(o,79032).
+char(8,79033).
+char(1,79034).
+char(1,79035).
+char(3,79036).
+char(p,79037).
+char(o,79038).
+char(9,79039).
+char(3,79040).
+char(4,79041).
+char(0,79042).
+char(p,79043).
+char(8,79044).
+char(4,79045).
+char(3,79046).
+char(3,79047).
+char(p,79048).
+char(7,79049).
+char(2,79050).
+char(8,79051).
+char(7,79052).
+char(m,79053).
+char(o,79054).
+char(p,79055).
+char(o,79056).
+char(m,79057).
+char(o,79058).
+char(p,79059).
+char(3,79060).
+char(2,79061).
+char(8,79062).
+char(2,79063).
+char(m,79064).
+char(1,79065).
+char(4,79066).
+char(2,79067).
+char(6,79068).
+char(c,79069).
+char(c,79070).
+char(c,79071).
+char(m,79072).
+char(7,79073).
+char(4,79074).
+char(8,79075).
+char(3,79076).
+char(c,79077).
+char(m,79078).
+char(o,79079).
+char(p,79080).
+char(o,79081).
+char(m,79082).
+char(o,79083).
+char(o,79084).
+char(m,79085).
+char(8,79086).
+char(5,79087).
+char(5,79088).
+char(p,79089).
+char(3,79090).
+char(8,79091).
+char(1,79092).
+char(9,79093).
+char(p,79094).
+char(7,79095).
+char(1,79096).
+char(2,79097).
+char(7,79098).
+char(m,79099).
+char(o,79100).
+char(m,79101).
+char(o,79102).
+char(m,79103).
+char(o,79104).
+char(p,79105).
+char(8,79106).
+char(5,79107).
+char(6,79108).
+char(1,79109).
+char(m,79110).
+char(2,79111).
+char(9,79112).
+char(6,79113).
+char(3,79114).
+char(c,79115).
+char(p,79116).
+char(o,79117).
+char(o,79118).
+char(o,79119).
+char(p,79120).
+char(5,79121).
+char(8,79122).
+char(5,79123).
+char(1,79124).
+char(p,79125).
+char(1,79126).
+char(4,79127).
+char(1,79128).
+char(8,79129).
+char(c,79130).
+char(c,79131).
+char(c,79132).
+char(m,79133).
+char(o,79134).
+char(m,79135).
+char(3,79136).
+char(3,79137).
+char(0,79138).
+char(m,79139).
+char(6,79140).
+char(4,79141).
+char(0,79142).
+char(7,79143).
+char(m,79144).
+char(1,79145).
+char(9,79146).
+char(6,79147).
+char(0,79148).
+char(c,79149).
+char(p,79150).
+char(o,79151).
+char(9,79152).
+char(4,79153).
+char(0,79154).
+char(2,79155).
+char(p,79156).
+char(8,79157).
+char(1,79158).
+char(7,79159).
+char(6,79160).
+char(p,79161).
+char(o,79162).
+char(m,79163).
+char(7,79164).
+char(1,79165).
+char(0,79166).
+char(3,79167).
+char(m,79168).
+char(2,79169).
+char(9,79170).
+char(8,79171).
+char(9,79172).
+char(c,79173).
+char(m,79174).
+char(o,79175).
+char(m,79176).
+char(2,79177).
+char(8,79178).
+char(0,79179).
+char(6,79180).
+char(p,79181).
+char(8,79182).
+char(6,79183).
+char(2,79184).
+char(7,79185).
+char(m,79186).
+char(o,79187).
+char(p,79188).
+char(3,79189).
+char(2,79190).
+char(9,79191).
+char(7,79192).
+char(c,79193).
+char(p,79194).
+char(6,79195).
+char(0,79196).
+char(c,79197).
+char(c,79198).
+char(c,79199).
+char(c,79200).
+char(m,79201).
+char(o,79202).
+char(m,79203).
+char(5,79204).
+char(1,79205).
+char(3,79206).
+char(c,79207).
+char(p,79208).
+char(o,79209).
+char(6,79210).
+char(5,79211).
+char(5,79212).
+char(9,79213).
+char(m,79214).
+char(o,79215).
+char(o,79216).
+char(p,79217).
+char(9,79218).
+char(9,79219).
+char(7,79220).
+char(6,79221).
+char(c,79222).
+char(c,79223).
+char(c,79224).
+char(c,79225).
+char(m,79226).
+char(3,79227).
+char(3,79228).
+char(8,79229).
+char(2,79230).
+char(m,79231).
+char(o,79232).
+char(o,79233).
+char(m,79234).
+char(7,79235).
+char(8,79236).
+char(3,79237).
+char(7,79238).
+char(p,79239).
+char(6,79240).
+char(7,79241).
+char(4,79242).
+char(1,79243).
+char(c,79244).
+char(c,79245).
+char(c,79246).
+char(c,79247).
+char(c,79248).
+char(c,79249).
+char(c,79250).
+char(p,79251).
+char(7,79252).
+char(5,79253).
+char(1,79254).
+char(1,79255).
+char(c,79256).
+char(p,79257).
+char(7,79258).
+char(5,79259).
+char(4,79260).
+char(1,79261).
+char(p,79262).
+char(o,79263).
+char(m,79264).
+char(o,79265).
+char(5,79266).
+char(6,79267).
+char(6,79268).
+char(0,79269).
+char(c,79270).
+char(m,79271).
+char(4,79272).
+char(6,79273).
+char(8,79274).
+char(0,79275).
+char(p,79276).
+char(5,79277).
+char(8,79278).
+char(5,79279).
+char(8,79280).
+char(c,79281).
+char(m,79282).
+char(5,79283).
+char(9,79284).
+char(7,79285).
+char(9,79286).
+char(p,79287).
+char(o,79288).
+char(m,79289).
+char(7,79290).
+char(8,79291).
+char(1,79292).
+char(2,79293).
+char(m,79294).
+char(o,79295).
+char(p,79296).
+char(5,79297).
+char(7,79298).
+char(3,79299).
+char(9,79300).
+char(c,79301).
+char(m,79302).
+char(8,79303).
+char(7,79304).
+char(9,79305).
+char(6,79306).
+char(c,79307).
+char(p,79308).
+char(o,79309).
+char(p,79310).
+char(o,79311).
+char(p,79312).
+char(o,79313).
+char(p,79314).
+char(5,79315).
+char(3,79316).
+char(2,79317).
+char(1,79318).
+char(p,79319).
+char(8,79320).
+char(2,79321).
+char(7,79322).
+char(5,79323).
+char(c,79324).
+char(p,79325).
+char(4,79326).
+char(2,79327).
+char(4,79328).
+char(9,79329).
+char(c,79330).
+char(c,79331).
+char(p,79332).
+char(5,79333).
+char(7,79334).
+char(5,79335).
+char(9,79336).
+char(c,79337).
+char(p,79338).
+char(1,79339).
+char(6,79340).
+char(3,79341).
+char(p,79342).
+char(o,79343).
+char(p,79344).
+char(o,79345).
+char(o,79346).
+char(p,79347).
+char(9,79348).
+char(9,79349).
+char(4,79350).
+char(0,79351).
+char(p,79352).
+char(o,79353).
+char(m,79354).
+char(o,79355).
+char(7,79356).
+char(6,79357).
+char(6,79358).
+char(8,79359).
+char(c,79360).
+char(p,79361).
+char(1,79362).
+char(2,79363).
+char(0,79364).
+char(0,79365).
+char(c,79366).
+char(c,79367).
+char(c,79368).
+char(p,79369).
+char(8,79370).
+char(9,79371).
+char(5,79372).
+char(9,79373).
+char(m,79374).
+char(3,79375).
+char(2,79376).
+char(4,79377).
+char(1,79378).
+char(c,79379).
+char(m,79380).
+char(3,79381).
+char(9,79382).
+char(5,79383).
+char(1,79384).
+char(p,79385).
+char(o,79386).
+char(m,79387).
+char(o,79388).
+char(m,79389).
+char(o,79390).
+char(p,79391).
+char(8,79392).
+char(7,79393).
+char(7,79394).
+char(6,79395).
+char(m,79396).
+char(o,79397).
+char(p,79398).
+char(6,79399).
+char(2,79400).
+char(0,79401).
+char(m,79402).
+char(3,79403).
+char(3,79404).
+char(1,79405).
+char(0,79406).
+char(m,79407).
+char(o,79408).
+char(o,79409).
+char(p,79410).
+char(1,79411).
+char(9,79412).
+char(4,79413).
+char(1,79414).
+char(c,79415).
+char(c,79416).
+char(c,79417).
+char(c,79418).
+char(p,79419).
+char(o,79420).
+char(m,79421).
+char(8,79422).
+char(5,79423).
+char(1,79424).
+char(1,79425).
+char(p,79426).
+char(7,79427).
+char(9,79428).
+char(1,79429).
+char(5,79430).
+char(c,79431).
+char(m,79432).
+char(3,79433).
+char(3,79434).
+char(8,79435).
+char(7,79436).
+char(p,79437).
+char(7,79438).
+char(1,79439).
+char(6,79440).
+char(8,79441).
+char(c,79442).
+char(c,79443).
+char(c,79444).
+char(c,79445).
+char(c,79446).
+char(c,79447).
+char(c,79448).
+char(m,79449).
+char(o,79450).
+char(m,79451).
+char(o,79452).
+char(m,79453).
+char(o,79454).
+char(m,79455).
+char(7,79456).
+char(3,79457).
+char(7,79458).
+char(p,79459).
+char(1,79460).
+char(1,79461).
+char(p,79462).
+char(o,79463).
+char(p,79464).
+char(7,79465).
+char(6,79466).
+char(3,79467).
+char(1,79468).
+char(p,79469).
+char(2,79470).
+char(7,79471).
+char(1,79472).
+char(p,79473).
+char(o,79474).
+char(p,79475).
+char(o,79476).
+char(p,79477).
+char(o,79478).
+char(2,79479).
+char(1,79480).
+char(6,79481).
+char(4,79482).
+char(c,79483).
+char(p,79484).
+char(3,79485).
+char(7,79486).
+char(8,79487).
+char(0,79488).
+char(c,79489).
+char(p,79490).
+char(o,79491).
+char(o,79492).
+char(p,79493).
+char(o,79494).
+char(m,79495).
+char(9,79496).
+char(3,79497).
+char(3,79498).
+char(7,79499).
+char(c,79500).
+char(c,79501).
+char(c,79502).
+char(m,79503).
+char(o,79504).
+char(o,79505).
+char(m,79506).
+char(o,79507).
+char(p,79508).
+char(o,79509).
+char(p,79510).
+char(o,79511).
+char(p,79512).
+char(o,79513).
+char(o,79514).
+char(m,79515).
+char(o,79516).
+char(p,79517).
+char(o,79518).
+char(p,79519).
+char(8,79520).
+char(6,79521).
+char(9,79522).
+char(8,79523).
+char(c,79524).
+char(p,79525).
+char(o,79526).
+char(o,79527).
+char(p,79528).
+char(o,79529).
+char(o,79530).
+char(m,79531).
+char(o,79532).
+char(p,79533).
+char(7,79534).
+char(9,79535).
+char(2,79536).
+char(7,79537).
+char(p,79538).
+char(o,79539).
+char(m,79540).
+char(9,79541).
+char(1,79542).
+char(8,79543).
+char(4,79544).
+char(c,79545).
+char(c,79546).
+char(m,79547).
+char(6,79548).
+char(3,79549).
+char(2,79550).
+char(5,79551).
+char(c,79552).
+char(c,79553).
+char(m,79554).
+char(5,79555).
+char(0,79556).
+char(2,79557).
+char(3,79558).
+char(m,79559).
+char(1,79560).
+char(6,79561).
+char(9,79562).
+char(8,79563).
+char(m,79564).
+char(5,79565).
+char(3,79566).
+char(9,79567).
+char(9,79568).
+char(c,79569).
+char(c,79570).
+char(c,79571).
+char(c,79572).
+char(c,79573).
+char(c,79574).
+char(p,79575).
+char(5,79576).
+char(1,79577).
+char(2,79578).
+char(2,79579).
+char(c,79580).
+char(c,79581).
+char(p,79582).
+char(o,79583).
+char(p,79584).
+char(o,79585).
+char(m,79586).
+char(1,79587).
+char(4,79588).
+char(4,79589).
+char(1,79590).
+char(m,79591).
+char(5,79592).
+char(1,79593).
+char(8,79594).
+char(1,79595).
+char(m,79596).
+char(9,79597).
+char(0,79598).
+char(8,79599).
+char(5,79600).
+char(c,79601).
+char(p,79602).
+char(5,79603).
+char(4,79604).
+char(6,79605).
+char(8,79606).
+char(p,79607).
+char(4,79608).
+char(0,79609).
+char(7,79610).
+char(8,79611).
+char(p,79612).
+char(8,79613).
+char(8,79614).
+char(1,79615).
+char(0,79616).
+char(m,79617).
+char(o,79618).
+char(9,79619).
+char(9,79620).
+char(7,79621).
+char(1,79622).
+char(c,79623).
+char(p,79624).
+char(o,79625).
+char(p,79626).
+char(o,79627).
+char(o,79628).
+char(p,79629).
+char(o,79630).
+char(m,79631).
+char(o,79632).
+char(m,79633).
+char(6,79634).
+char(8,79635).
+char(6,79636).
+char(1,79637).
+char(c,79638).
+char(p,79639).
+char(o,79640).
+char(m,79641).
+char(o,79642).
+char(o,79643).
+char(9,79644).
+char(6,79645).
+char(3,79646).
+char(9,79647).
+char(c,79648).
+char(c,79649).
+char(m,79650).
+char(o,79651).
+char(p,79652).
+char(9,79653).
+char(3,79654).
+char(7,79655).
+char(6,79656).
+char(p,79657).
+char(o,79658).
+char(m,79659).
+char(9,79660).
+char(4,79661).
+char(5,79662).
+char(5,79663).
+char(c,79664).
+char(m,79665).
+char(5,79666).
+char(1,79667).
+char(5,79668).
+char(1,79669).
+char(c,79670).
+char(m,79671).
+char(6,79672).
+char(2,79673).
+char(0,79674).
+char(4,79675).
+char(m,79676).
+char(7,79677).
+char(9,79678).
+char(8,79679).
+char(1,79680).
+char(c,79681).
+char(c,79682).
+char(m,79683).
+char(5,79684).
+char(0,79685).
+char(9,79686).
+char(0,79687).
+char(m,79688).
+char(6,79689).
+char(8,79690).
+char(4,79691).
+char(0,79692).
+char(c,79693).
+char(c,79694).
+char(c,79695).
+char(p,79696).
+char(o,79697).
+char(p,79698).
+char(o,79699).
+char(p,79700).
+char(o,79701).
+char(7,79702).
+char(5,79703).
+char(8,79704).
+char(8,79705).
+char(p,79706).
+char(o,79707).
+char(m,79708).
+char(2,79709).
+char(4,79710).
+char(9,79711).
+char(9,79712).
+char(m,79713).
+char(o,79714).
+char(m,79715).
+char(o,79716).
+char(p,79717).
+char(o,79718).
+char(p,79719).
+char(7,79720).
+char(1,79721).
+char(2,79722).
+char(6,79723).
+char(p,79724).
+char(o,79725).
+char(3,79726).
+char(7,79727).
+char(1,79728).
+char(0,79729).
+char(p,79730).
+char(2,79731).
+char(9,79732).
+char(2,79733).
+char(p,79734).
+char(o,79735).
+char(p,79736).
+char(3,79737).
+char(1,79738).
+char(8,79739).
+char(m,79740).
+char(4,79741).
+char(6,79742).
+char(3,79743).
+char(5,79744).
+char(c,79745).
+char(p,79746).
+char(o,79747).
+char(m,79748).
+char(o,79749).
+char(p,79750).
+char(8,79751).
+char(7,79752).
+char(7,79753).
+char(0,79754).
+char(p,79755).
+char(o,79756).
+char(o,79757).
+char(5,79758).
+char(1,79759).
+char(6,79760).
+char(c,79761).
+char(c,79762).
+char(p,79763).
+char(3,79764).
+char(8,79765).
+char(1,79766).
+char(c,79767).
+char(m,79768).
+char(o,79769).
+char(m,79770).
+char(9,79771).
+char(5,79772).
+char(4,79773).
+char(1,79774).
+char(c,79775).
+char(m,79776).
+char(o,79777).
+char(1,79778).
+char(7,79779).
+char(8,79780).
+char(8,79781).
+char(m,79782).
+char(o,79783).
+char(p,79784).
+char(o,79785).
+char(p,79786).
+char(o,79787).
+char(m,79788).
+char(o,79789).
+char(p,79790).
+char(1,79791).
+char(2,79792).
+char(9,79793).
+char(7,79794).
+char(c,79795).
+char(c,79796).
+char(c,79797).
+char(c,79798).
+char(c,79799).
+char(p,79800).
+char(o,79801).
+char(m,79802).
+char(3,79803).
+char(9,79804).
+char(6,79805).
+char(4,79806).
+char(p,79807).
+char(o,79808).
+char(p,79809).
+char(1,79810).
+char(6,79811).
+char(7,79812).
+char(8,79813).
+char(c,79814).
+char(c,79815).
+char(c,79816).
+char(m,79817).
+char(5,79818).
+char(5,79819).
+char(9,79820).
+char(0,79821).
+char(c,79822).
+char(c,79823).
+char(m,79824).
+char(o,79825).
+char(1,79826).
+char(1,79827).
+char(2,79828).
+char(6,79829).
+char(p,79830).
+char(o,79831).
+char(1,79832).
+char(9,79833).
+char(5,79834).
+char(3,79835).
+char(p,79836).
+char(o,79837).
+char(p,79838).
+char(o,79839).
+char(p,79840).
+char(5,79841).
+char(0,79842).
+char(5,79843).
+char(8,79844).
+char(c,79845).
+char(c,79846).
+char(p,79847).
+char(7,79848).
+char(5,79849).
+char(2,79850).
+char(3,79851).
+char(c,79852).
+char(m,79853).
+char(o,79854).
+char(m,79855).
+char(o,79856).
+char(5,79857).
+char(6,79858).
+char(2,79859).
+char(p,79860).
+char(o,79861).
+char(o,79862).
+char(m,79863).
+char(o,79864).
+char(p,79865).
+char(8,79866).
+char(1,79867).
+char(7,79868).
+char(0,79869).
+char(m,79870).
+char(2,79871).
+char(8,79872).
+char(6,79873).
+char(9,79874).
+char(c,79875).
+char(p,79876).
+char(4,79877).
+char(8,79878).
+char(2,79879).
+char(1,79880).
+char(p,79881).
+char(o,79882).
+char(m,79883).
+char(6,79884).
+char(9,79885).
+char(0,79886).
+char(6,79887).
+char(m,79888).
+char(o,79889).
+char(m,79890).
+char(2,79891).
+char(5,79892).
+char(3,79893).
+char(2,79894).
+char(c,79895).
+char(c,79896).
+char(c,79897).
+char(p,79898).
+char(o,79899).
+char(2,79900).
+char(9,79901).
+char(9,79902).
+char(0,79903).
+char(p,79904).
+char(5,79905).
+char(0,79906).
+char(2,79907).
+char(9,79908).
+char(c,79909).
+char(p,79910).
+char(8,79911).
+char(7,79912).
+char(1,79913).
+char(6,79914).
+char(p,79915).
+char(4,79916).
+char(5,79917).
+char(9,79918).
+char(3,79919).
+char(p,79920).
+char(4,79921).
+char(7,79922).
+char(0,79923).
+char(1,79924).
+char(c,79925).
+char(p,79926).
+char(2,79927).
+char(8,79928).
+char(2,79929).
+char(p,79930).
+char(9,79931).
+char(7,79932).
+char(8,79933).
+char(3,79934).
+char(p,79935).
+char(6,79936).
+char(3,79937).
+char(4,79938).
+char(4,79939).
+char(c,79940).
+char(c,79941).
+char(c,79942).
+char(p,79943).
+char(8,79944).
+char(1,79945).
+char(8,79946).
+char(4,79947).
+char(c,79948).
+char(m,79949).
+char(5,79950).
+char(9,79951).
+char(7,79952).
+char(0,79953).
+char(c,79954).
+char(m,79955).
+char(5,79956).
+char(3,79957).
+char(3,79958).
+char(1,79959).
+char(c,79960).
+char(c,79961).
+char(p,79962).
+char(8,79963).
+char(3,79964).
+char(4,79965).
+char(8,79966).
+char(m,79967).
+char(o,79968).
+char(p,79969).
+char(o,79970).
+char(p,79971).
+char(o,79972).
+char(m,79973).
+char(o,79974).
+char(p,79975).
+char(5,79976).
+char(8,79977).
+char(2,79978).
+char(9,79979).
+char(p,79980).
+char(2,79981).
+char(7,79982).
+char(0,79983).
+char(c,79984).
+char(m,79985).
+char(o,79986).
+char(m,79987).
+char(5,79988).
+char(2,79989).
+char(0,79990).
+char(9,79991).
+char(c,79992).
+char(c,79993).
+char(c,79994).
+char(p,79995).
+char(7,79996).
+char(6,79997).
+char(5,79998).
+char(7,79999).
+char(p,80000).
+char(4,80001).
+char(7,80002).
+char(6,80003).
+char(9,80004).
+char(p,80005).
+char(o,80006).
+char(p,80007).
+char(1,80008).
+char(3,80009).
+char(8,80010).
+char(6,80011).
+char(c,80012).
+char(m,80013).
+char(o,80014).
+char(m,80015).
+char(9,80016).
+char(1,80017).
+char(2,80018).
+char(5,80019).
+char(c,80020).
+char(c,80021).
+char(m,80022).
+char(o,80023).
+char(p,80024).
+char(3,80025).
+char(1,80026).
+char(4,80027).
+char(4,80028).
+char(p,80029).
+char(o,80030).
+char(8,80031).
+char(4,80032).
+char(5,80033).
+char(0,80034).
+char(m,80035).
+char(o,80036).
+char(9,80037).
+char(8,80038).
+char(1,80039).
+char(5,80040).
+char(c,80041).
+char(p,80042).
+char(o,80043).
+char(p,80044).
+char(9,80045).
+char(3,80046).
+char(2,80047).
+char(1,80048).
+char(m,80049).
+char(9,80050).
+char(2,80051).
+char(3,80052).
+char(3,80053).
+char(m,80054).
+char(o,80055).
+char(o,80056).
+char(m,80057).
+char(2,80058).
+char(8,80059).
+char(7,80060).
+char(8,80061).
+char(p,80062).
+char(6,80063).
+char(1,80064).
+char(4,80065).
+char(3,80066).
+char(c,80067).
+char(m,80068).
+char(2,80069).
+char(3,80070).
+char(8,80071).
+char(6,80072).
+char(c,80073).
+char(p,80074).
+char(o,80075).
+char(m,80076).
+char(o,80077).
+char(p,80078).
+char(o,80079).
+char(m,80080).
+char(8,80081).
+char(0,80082).
+char(7,80083).
+char(m,80084).
+char(2,80085).
+char(4,80086).
+char(9,80087).
+char(2,80088).
+char(c,80089).
+char(c,80090).
+char(p,80091).
+char(o,80092).
+char(m,80093).
+char(5,80094).
+char(2,80095).
+char(9,80096).
+char(4,80097).
+char(c,80098).
+char(p,80099).
+char(8,80100).
+char(1,80101).
+char(2,80102).
+char(3,80103).
+char(m,80104).
+char(o,80105).
+char(p,80106).
+char(o,80107).
+char(m,80108).
+char(9,80109).
+char(3,80110).
+char(3,80111).
+char(2,80112).
+char(p,80113).
+char(4,80114).
+char(2,80115).
+char(1,80116).
+char(5,80117).
+char(c,80118).
+char(c,80119).
+char(c,80120).
+char(c,80121).
+char(p,80122).
+char(6,80123).
+char(2,80124).
+char(2,80125).
+char(6,80126).
+char(c,80127).
+char(c,80128).
+char(m,80129).
+char(3,80130).
+char(2,80131).
+char(4,80132).
+char(9,80133).
+char(c,80134).
+char(c,80135).
+char(c,80136).
+char(p,80137).
+char(o,80138).
+char(p,80139).
+char(o,80140).
+char(6,80141).
+char(8,80142).
+char(4,80143).
+char(1,80144).
+char(p,80145).
+char(8,80146).
+char(2,80147).
+char(0,80148).
+char(8,80149).
+char(m,80150).
+char(o,80151).
+char(3,80152).
+char(4,80153).
+char(2,80154).
+char(9,80155).
+char(m,80156).
+char(1,80157).
+char(9,80158).
+char(6,80159).
+char(7,80160).
+char(m,80161).
+char(6,80162).
+char(1,80163).
+char(0,80164).
+char(9,80165).
+char(c,80166).
+char(p,80167).
+char(o,80168).
+char(p,80169).
+char(9,80170).
+char(9,80171).
+char(0,80172).
+char(3,80173).
+char(p,80174).
+char(o,80175).
+char(p,80176).
+char(o,80177).
+char(m,80178).
+char(o,80179).
+char(m,80180).
+char(o,80181).
+char(4,80182).
+char(1,80183).
+char(0,80184).
+char(7,80185).
+char(p,80186).
+char(o,80187).
+char(m,80188).
+char(o,80189).
+char(p,80190).
+char(o,80191).
+char(m,80192).
+char(o,80193).
+char(p,80194).
+char(3,80195).
+char(1,80196).
+char(9,80197).
+char(8,80198).
+char(c,80199).
+char(c,80200).
+char(p,80201).
+char(9,80202).
+char(7,80203).
+char(0,80204).
+char(8,80205).
+char(c,80206).
+char(c,80207).
+char(m,80208).
+char(o,80209).
+char(3,80210).
+char(4,80211).
+char(2,80212).
+char(1,80213).
+char(m,80214).
+char(5,80215).
+char(4,80216).
+char(3,80217).
+char(5,80218).
+char(c,80219).
+char(p,80220).
+char(3,80221).
+char(5,80222).
+char(8,80223).
+char(2,80224).
+char(m,80225).
+char(9,80226).
+char(7,80227).
+char(8,80228).
+char(9,80229).
+char(c,80230).
+char(c,80231).
+char(c,80232).
+char(m,80233).
+char(o,80234).
+char(m,80235).
+char(3,80236).
+char(2,80237).
+char(6,80238).
+char(5,80239).
+char(c,80240).
+char(c,80241).
+char(m,80242).
+char(o,80243).
+char(7,80244).
+char(9,80245).
+char(9,80246).
+char(0,80247).
+char(p,80248).
+char(o,80249).
+char(p,80250).
+char(4,80251).
+char(1,80252).
+char(2,80253).
+char(5,80254).
+char(m,80255).
+char(o,80256).
+char(o,80257).
+char(m,80258).
+char(o,80259).
+char(o,80260).
+char(o,80261).
+char(m,80262).
+char(o,80263).
+char(5,80264).
+char(1,80265).
+char(m,80266).
+char(o,80267).
+char(m,80268).
+char(4,80269).
+char(4,80270).
+char(9,80271).
+char(c,80272).
+char(c,80273).
+char(p,80274).
+char(5,80275).
+char(8,80276).
+char(3,80277).
+char(7,80278).
+char(c,80279).
+char(c,80280).
+char(m,80281).
+char(8,80282).
+char(8,80283).
+char(2,80284).
+char(7,80285).
+char(c,80286).
+char(p,80287).
+char(o,80288).
+char(p,80289).
+char(o,80290).
+char(p,80291).
+char(o,80292).
+char(m,80293).
+char(4,80294).
+char(1,80295).
+char(2,80296).
+char(6,80297).
+char(m,80298).
+char(o,80299).
+char(p,80300).
+char(3,80301).
+char(3,80302).
+char(4,80303).
+char(9,80304).
+char(p,80305).
+char(4,80306).
+char(4,80307).
+char(0,80308).
+char(4,80309).
+char(c,80310).
+char(p,80311).
+char(1,80312).
+char(9,80313).
+char(5,80314).
+char(4,80315).
+char(c,80316).
+char(p,80317).
+char(5,80318).
+char(5,80319).
+char(4,80320).
+char(7,80321).
+char(c,80322).
+char(c,80323).
+char(c,80324).
+char(p,80325).
+char(o,80326).
+char(m,80327).
+char(o,80328).
+char(5,80329).
+char(2,80330).
+char(1,80331).
+char(7,80332).
+char(p,80333).
+char(o,80334).
+char(8,80335).
+char(6,80336).
+char(3,80337).
+char(7,80338).
+char(c,80339).
+char(c,80340).
+char(m,80341).
+char(8,80342).
+char(2,80343).
+char(0,80344).
+char(8,80345).
+char(p,80346).
+char(6,80347).
+char(0,80348).
+char(2,80349).
+char(4,80350).
+char(c,80351).
+char(p,80352).
+char(4,80353).
+char(0,80354).
+char(6,80355).
+char(5,80356).
+char(p,80357).
+char(6,80358).
+char(2,80359).
+char(5,80360).
+char(8,80361).
+char(c,80362).
+char(p,80363).
+char(o,80364).
+char(o,80365).
+char(p,80366).
+char(7,80367).
+char(8,80368).
+char(2,80369).
+char(1,80370).
+char(p,80371).
+char(o,80372).
+char(o,80373).
+char(2,80374).
+char(4,80375).
+char(0,80376).
+char(8,80377).
+char(p,80378).
+char(5,80379).
+char(2,80380).
+char(1,80381).
+char(8,80382).
+char(c,80383).
+char(c,80384).
+char(c,80385).
+char(c,80386).
+char(c,80387).
+char(m,80388).
+char(o,80389).
+char(p,80390).
+char(o,80391).
+char(p,80392).
+char(o,80393).
+char(p,80394).
+char(o,80395).
+char(p,80396).
+char(8,80397).
+char(9,80398).
+char(6,80399).
+char(5,80400).
+char(c,80401).
+char(c,80402).
+char(c,80403).
+char(c,80404).
+char(c,80405).
+char(m,80406).
+char(o,80407).
+char(p,80408).
+char(o,80409).
+char(m,80410).
+char(o,80411).
+char(o,80412).
+char(4,80413).
+char(9,80414).
+char(2,80415).
+char(9,80416).
+char(c,80417).
+char(p,80418).
+char(o,80419).
+char(4,80420).
+char(9,80421).
+char(8,80422).
+char(8,80423).
+char(p,80424).
+char(1,80425).
+char(3,80426).
+char(8,80427).
+char(m,80428).
+char(o,80429).
+char(o,80430).
+char(m,80431).
+char(o,80432).
+char(m,80433).
+char(o,80434).
+char(m,80435).
+char(1,80436).
+char(9,80437).
+char(1,80438).
+char(9,80439).
+char(c,80440).
+char(c,80441).
+char(m,80442).
+char(o,80443).
+char(p,80444).
+char(1,80445).
+char(9,80446).
+char(2,80447).
+char(c,80448).
+char(c,80449).
+char(p,80450).
+char(7,80451).
+char(3,80452).
+char(2,80453).
+char(2,80454).
+char(p,80455).
+char(2,80456).
+char(3,80457).
+char(1,80458).
+char(1,80459).
+char(p,80460).
+char(o,80461).
+char(p,80462).
+char(7,80463).
+char(9,80464).
+char(1,80465).
+char(3,80466).
+char(c,80467).
+char(p,80468).
+char(1,80469).
+char(6,80470).
+char(9,80471).
+char(6,80472).
+char(p,80473).
+char(o,80474).
+char(o,80475).
+char(o,80476).
+char(m,80477).
+char(o,80478).
+char(o,80479).
+char(m,80480).
+char(o,80481).
+char(m,80482).
+char(5,80483).
+char(6,80484).
+char(0,80485).
+char(c,80486).
+char(c,80487).
+char(c,80488).
+char(c,80489).
+char(m,80490).
+char(6,80491).
+char(3,80492).
+char(1,80493).
+char(8,80494).
+char(c,80495).
+char(p,80496).
+char(2,80497).
+char(8,80498).
+char(1,80499).
+char(6,80500).
+char(p,80501).
+char(5,80502).
+char(1,80503).
+char(8,80504).
+char(5,80505).
+char(p,80506).
+char(o,80507).
+char(p,80508).
+char(3,80509).
+char(9,80510).
+char(0,80511).
+char(5,80512).
+char(m,80513).
+char(o,80514).
+char(m,80515).
+char(o,80516).
+char(m,80517).
+char(o,80518).
+char(p,80519).
+char(4,80520).
+char(7,80521).
+char(7,80522).
+char(p,80523).
+char(4,80524).
+char(9,80525).
+char(5,80526).
+char(0,80527).
+char(c,80528).
+char(p,80529).
+char(o,80530).
+char(m,80531).
+char(8,80532).
+char(4,80533).
+char(4,80534).
+char(0,80535).
+char(m,80536).
+char(o,80537).
+char(p,80538).
+char(3,80539).
+char(8,80540).
+char(0,80541).
+char(6,80542).
+char(m,80543).
+char(5,80544).
+char(4,80545).
+char(9,80546).
+char(5,80547).
+char(p,80548).
+char(2,80549).
+char(2,80550).
+char(0,80551).
+char(0,80552).
+char(c,80553).
+char(c,80554).
+char(p,80555).
+char(3,80556).
+char(5,80557).
+char(4,80558).
+char(3,80559).
+char(p,80560).
+char(6,80561).
+char(1,80562).
+char(4,80563).
+char(6,80564).
+char(c,80565).
+char(c,80566).
+char(p,80567).
+char(o,80568).
+char(o,80569).
+char(p,80570).
+char(7,80571).
+char(2,80572).
+char(9,80573).
+char(0,80574).
+char(c,80575).
+char(c,80576).
+char(m,80577).
+char(4,80578).
+char(2,80579).
+char(0,80580).
+char(4,80581).
+char(p,80582).
+char(o,80583).
+char(9,80584).
+char(7,80585).
+char(6,80586).
+char(7,80587).
+char(c,80588).
+char(c,80589).
+char(m,80590).
+char(3,80591).
+char(4,80592).
+char(0,80593).
+char(6,80594).
+char(c,80595).
+char(c,80596).
+char(p,80597).
+char(o,80598).
+char(o,80599).
+char(p,80600).
+char(o,80601).
+char(p,80602).
+char(o,80603).
+char(m,80604).
+char(o,80605).
+char(p,80606).
+char(5,80607).
+char(4,80608).
+char(0,80609).
+char(6,80610).
+char(c,80611).
+char(m,80612).
+char(2,80613).
+char(1,80614).
+char(6,80615).
+char(1,80616).
+char(c,80617).
+char(c,80618).
+char(c,80619).
+char(c,80620).
+char(p,80621).
+char(o,80622).
+char(o,80623).
+char(o,80624).
+char(p,80625).
+char(7,80626).
+char(1,80627).
+char(1,80628).
+char(4,80629).
+char(c,80630).
+char(c,80631).
+char(c,80632).
+char(m,80633).
+char(7,80634).
+char(9,80635).
+char(6,80636).
+char(8,80637).
+char(m,80638).
+char(4,80639).
+char(3,80640).
+char(6,80641).
+char(0,80642).
+char(p,80643).
+char(o,80644).
+char(9,80645).
+char(1,80646).
+char(5,80647).
+char(2,80648).
+char(m,80649).
+char(o,80650).
+char(m,80651).
+char(5,80652).
+char(6,80653).
+char(0,80654).
+char(0,80655).
+char(m,80656).
+char(2,80657).
+char(4,80658).
+char(1,80659).
+char(c,80660).
+char(c,80661).
+char(c,80662).
+char(p,80663).
+char(1,80664).
+char(0,80665).
+char(2,80666).
+char(0,80667).
+char(c,80668).
+char(c,80669).
+char(c,80670).
+char(c,80671).
+char(c,80672).
+char(p,80673).
+char(2,80674).
+char(7,80675).
+char(0,80676).
+char(2,80677).
+char(m,80678).
+char(o,80679).
+char(4,80680).
+char(0,80681).
+char(5,80682).
+char(7,80683).
+char(p,80684).
+char(o,80685).
+char(m,80686).
+char(3,80687).
+char(8,80688).
+char(3,80689).
+char(1,80690).
+char(c,80691).
+char(m,80692).
+char(7,80693).
+char(5,80694).
+char(9,80695).
+char(6,80696).
+char(c,80697).
+char(c,80698).
+char(m,80699).
+char(5,80700).
+char(5,80701).
+char(9,80702).
+char(0,80703).
+char(m,80704).
+char(4,80705).
+char(1,80706).
+char(6,80707).
+char(6,80708).
+char(c,80709).
+char(p,80710).
+char(9,80711).
+char(9,80712).
+char(5,80713).
+char(7,80714).
+char(c,80715).
+char(c,80716).
+char(p,80717).
+char(o,80718).
+char(p,80719).
+char(7,80720).
+char(2,80721).
+char(0,80722).
+char(1,80723).
+char(m,80724).
+char(3,80725).
+char(0,80726).
+char(5,80727).
+char(1,80728).
+char(c,80729).
+char(c,80730).
+char(c,80731).
+char(p,80732).
+char(9,80733).
+char(7,80734).
+char(8,80735).
+char(4,80736).
+char(c,80737).
+char(c,80738).
+char(c,80739).
+char(c,80740).
+char(c,80741).
+char(c,80742).
+char(c,80743).
+char(p,80744).
+char(o,80745).
+char(p,80746).
+char(o,80747).
+char(p,80748).
+char(o,80749).
+char(o,80750).
+char(p,80751).
+char(o,80752).
+char(m,80753).
+char(o,80754).
+char(7,80755).
+char(0,80756).
+char(0,80757).
+char(9,80758).
+char(c,80759).
+char(p,80760).
+char(o,80761).
+char(p,80762).
+char(o,80763).
+char(m,80764).
+char(2,80765).
+char(7,80766).
+char(9,80767).
+char(5,80768).
+char(c,80769).
+char(c,80770).
+char(m,80771).
+char(7,80772).
+char(3,80773).
+char(2,80774).
+char(2,80775).
+char(c,80776).
+char(p,80777).
+char(o,80778).
+char(8,80779).
+char(6,80780).
+char(5,80781).
+char(9,80782).
+char(p,80783).
+char(1,80784).
+char(1,80785).
+char(3,80786).
+char(5,80787).
+char(m,80788).
+char(o,80789).
+char(p,80790).
+char(8,80791).
+char(3,80792).
+char(m,80793).
+char(2,80794).
+char(2,80795).
+char(5,80796).
+char(0,80797).
+char(p,80798).
+char(o,80799).
+char(m,80800).
+char(4,80801).
+char(2,80802).
+char(4,80803).
+char(c,80804).
+char(p,80805).
+char(o,80806).
+char(o,80807).
+char(8,80808).
+char(5,80809).
+char(9,80810).
+char(3,80811).
+char(c,80812).
+char(m,80813).
+char(9,80814).
+char(0,80815).
+char(0,80816).
+char(3,80817).
+char(p,80818).
+char(2,80819).
+char(9,80820).
+char(5,80821).
+char(7,80822).
+char(c,80823).
+char(m,80824).
+char(o,80825).
+char(p,80826).
+char(o,80827).
+char(4,80828).
+char(1,80829).
+char(4,80830).
+char(4,80831).
+char(c,80832).
+char(c,80833).
+char(c,80834).
+char(m,80835).
+char(8,80836).
+char(8,80837).
+char(1,80838).
+char(8,80839).
+char(p,80840).
+char(o,80841).
+char(p,80842).
+char(2,80843).
+char(0,80844).
+char(3,80845).
+char(3,80846).
+char(c,80847).
+char(c,80848).
+char(c,80849).
+char(m,80850).
+char(o,80851).
+char(m,80852).
+char(o,80853).
+char(2,80854).
+char(7,80855).
+char(3,80856).
+char(6,80857).
+char(p,80858).
+char(5,80859).
+char(6,80860).
+char(4,80861).
+char(c,80862).
+char(c,80863).
+char(m,80864).
+char(o,80865).
+char(m,80866).
+char(o,80867).
+char(p,80868).
+char(1,80869).
+char(4,80870).
+char(4,80871).
+char(6,80872).
+char(c,80873).
+char(p,80874).
+char(6,80875).
+char(2,80876).
+char(4,80877).
+char(1,80878).
+char(c,80879).
+char(p,80880).
+char(9,80881).
+char(8,80882).
+char(4,80883).
+char(4,80884).
+char(c,80885).
+char(c,80886).
+char(c,80887).
+char(c,80888).
+char(m,80889).
+char(o,80890).
+char(o,80891).
+char(p,80892).
+char(o,80893).
+char(o,80894).
+char(m,80895).
+char(6,80896).
+char(4,80897).
+char(8,80898).
+char(6,80899).
+char(p,80900).
+char(9,80901).
+char(8,80902).
+char(5,80903).
+char(0,80904).
+char(m,80905).
+char(o,80906).
+char(m,80907).
+char(o,80908).
+char(p,80909).
+char(1,80910).
+char(9,80911).
+char(4,80912).
+char(3,80913).
+char(p,80914).
+char(o,80915).
+char(m,80916).
+char(o,80917).
+char(p,80918).
+char(o,80919).
+char(p,80920).
+char(6,80921).
+char(4,80922).
+char(8,80923).
+char(5,80924).
+char(c,80925).
+char(c,80926).
+char(c,80927).
+char(c,80928).
+char(c,80929).
+char(p,80930).
+char(1,80931).
+char(2,80932).
+char(1,80933).
+char(8,80934).
+char(c,80935).
+char(p,80936).
+char(o,80937).
+char(6,80938).
+char(7,80939).
+char(6,80940).
+char(0,80941).
+char(p,80942).
+char(1,80943).
+char(9,80944).
+char(6,80945).
+char(2,80946).
+char(c,80947).
+char(c,80948).
+char(c,80949).
+char(p,80950).
+char(o,80951).
+char(m,80952).
+char(1,80953).
+char(2,80954).
+char(0,80955).
+char(3,80956).
+char(c,80957).
+char(c,80958).
+char(c,80959).
+char(p,80960).
+char(7,80961).
+char(0,80962).
+char(0,80963).
+char(1,80964).
+char(p,80965).
+char(9,80966).
+char(5,80967).
+char(2,80968).
+char(4,80969).
+char(m,80970).
+char(o,80971).
+char(m,80972).
+char(o,80973).
+char(o,80974).
+char(o,80975).
+char(m,80976).
+char(o,80977).
+char(m,80978).
+char(2,80979).
+char(5,80980).
+char(6,80981).
+char(5,80982).
+char(m,80983).
+char(o,80984).
+char(m,80985).
+char(9,80986).
+char(2,80987).
+char(6,80988).
+char(8,80989).
+char(m,80990).
+char(o,80991).
+char(9,80992).
+char(9,80993).
+char(5,80994).
+char(5,80995).
+char(c,80996).
+char(c,80997).
+char(m,80998).
+char(o,80999).
+char(4,81000).
+char(2,81001).
+char(7,81002).
+char(3,81003).
+char(c,81004).
+char(c,81005).
+char(c,81006).
+char(p,81007).
+char(o,81008).
+char(p,81009).
+char(o,81010).
+char(p,81011).
+char(o,81012).
+char(m,81013).
+char(o,81014).
+char(p,81015).
+char(o,81016).
+char(o,81017).
+char(p,81018).
+char(o,81019).
+char(m,81020).
+char(1,81021).
+char(7,81022).
+char(9,81023).
+char(3,81024).
+char(c,81025).
+char(c,81026).
+char(c,81027).
+char(c,81028).
+char(c,81029).
+char(c,81030).
+char(c,81031).
+char(p,81032).
+char(o,81033).
+char(o,81034).
+char(m,81035).
+char(8,81036).
+char(4,81037).
+char(2,81038).
+char(4,81039).
+char(c,81040).
+char(p,81041).
+char(6,81042).
+char(6,81043).
+char(3,81044).
+char(3,81045).
+char(m,81046).
+char(o,81047).
+char(p,81048).
+char(2,81049).
+char(8,81050).
+char(2,81051).
+char(9,81052).
+char(c,81053).
+char(c,81054).
+char(m,81055).
+char(4,81056).
+char(8,81057).
+char(2,81058).
+char(0,81059).
+char(c,81060).
+char(p,81061).
+char(o,81062).
+char(m,81063).
+char(7,81064).
+char(5,81065).
+char(3,81066).
+char(3,81067).
+char(p,81068).
+char(o,81069).
+char(m,81070).
+char(4,81071).
+char(3,81072).
+char(8,81073).
+char(6,81074).
+char(p,81075).
+char(3,81076).
+char(1,81077).
+char(3,81078).
+char(5,81079).
+char(p,81080).
+char(1,81081).
+char(5,81082).
+char(8,81083).
+char(6,81084).
+char(c,81085).
+char(p,81086).
+char(8,81087).
+char(2,81088).
+char(9,81089).
+char(6,81090).
+char(c,81091).
+char(m,81092).
+char(o,81093).
+char(4,81094).
+char(1,81095).
+char(5,81096).
+char(1,81097).
+char(c,81098).
+char(c,81099).
+char(p,81100).
+char(o,81101).
+char(p,81102).
+char(2,81103).
+char(6,81104).
+char(7,81105).
+char(9,81106).
+char(c,81107).
+char(p,81108).
+char(7,81109).
+char(5,81110).
+char(0,81111).
+char(5,81112).
+char(p,81113).
+char(o,81114).
+char(p,81115).
+char(o,81116).
+char(m,81117).
+char(o,81118).
+char(p,81119).
+char(3,81120).
+char(9,81121).
+char(0,81122).
+char(7,81123).
+char(p,81124).
+char(2,81125).
+char(8,81126).
+char(6,81127).
+char(8,81128).
+char(c,81129).
+char(m,81130).
+char(o,81131).
+char(m,81132).
+char(7,81133).
+char(1,81134).
+char(3,81135).
+char(6,81136).
+char(c,81137).
+char(c,81138).
+char(c,81139).
+char(c,81140).
+char(c,81141).
+char(m,81142).
+char(o,81143).
+char(o,81144).
+char(m,81145).
+char(6,81146).
+char(3,81147).
+char(2,81148).
+char(3,81149).
+char(m,81150).
+char(1,81151).
+char(3,81152).
+char(0,81153).
+char(5,81154).
+char(p,81155).
+char(o,81156).
+char(6,81157).
+char(2,81158).
+char(3,81159).
+char(3,81160).
+char(c,81161).
+char(c,81162).
+char(m,81163).
+char(1,81164).
+char(1,81165).
+char(9,81166).
+char(0,81167).
+char(m,81168).
+char(o,81169).
+char(o,81170).
+char(p,81171).
+char(5,81172).
+char(8,81173).
+char(7,81174).
+char(c,81175).
+char(p,81176).
+char(o,81177).
+char(9,81178).
+char(8,81179).
+char(5,81180).
+char(4,81181).
+char(p,81182).
+char(o,81183).
+char(p,81184).
+char(o,81185).
+char(p,81186).
+char(1,81187).
+char(0,81188).
+char(0,81189).
+char(1,81190).
+char(m,81191).
+char(1,81192).
+char(5,81193).
+char(7,81194).
+char(9,81195).
+char(c,81196).
+char(c,81197).
+char(p,81198).
+char(6,81199).
+char(3,81200).
+char(5,81201).
+char(0,81202).
+char(c,81203).
+char(c,81204).
+char(p,81205).
+char(9,81206).
+char(4,81207).
+char(1,81208).
+char(1,81209).
+char(c,81210).
+char(c,81211).
+char(c,81212).
+char(m,81213).
+char(o,81214).
+char(p,81215).
+char(1,81216).
+char(3,81217).
+char(0,81218).
+char(7,81219).
+char(p,81220).
+char(7,81221).
+char(3,81222).
+char(8,81223).
+char(4,81224).
+char(c,81225).
+char(m,81226).
+char(4,81227).
+char(1,81228).
+char(8,81229).
+char(6,81230).
+char(c,81231).
+char(p,81232).
+char(1,81233).
+char(0,81234).
+char(3,81235).
+char(5,81236).
+char(c,81237).
+char(p,81238).
+char(o,81239).
+char(m,81240).
+char(o,81241).
+char(m,81242).
+char(9,81243).
+char(5,81244).
+char(1,81245).
+char(9,81246).
+char(c,81247).
+char(p,81248).
+char(3,81249).
+char(4,81250).
+char(6,81251).
+char(5,81252).
+char(m,81253).
+char(o,81254).
+char(m,81255).
+char(3,81256).
+char(8,81257).
+char(4,81258).
+char(0,81259).
+char(c,81260).
+char(m,81261).
+char(o,81262).
+char(m,81263).
+char(o,81264).
+char(o,81265).
+char(p,81266).
+char(7,81267).
+char(5,81268).
+char(6,81269).
+char(7,81270).
+char(p,81271).
+char(o,81272).
+char(m,81273).
+char(o,81274).
+char(o,81275).
+char(m,81276).
+char(o,81277).
+char(p,81278).
+char(6,81279).
+char(0,81280).
+char(0,81281).
+char(2,81282).
+char(c,81283).
+char(c,81284).
+char(p,81285).
+char(o,81286).
+char(m,81287).
+char(9,81288).
+char(6,81289).
+char(3,81290).
+char(8,81291).
+char(c,81292).
+char(c,81293).
+char(p,81294).
+char(o,81295).
+char(p,81296).
+char(1,81297).
+char(9,81298).
+char(1,81299).
+char(3,81300).
+char(c,81301).
+char(p,81302).
+char(4,81303).
+char(1,81304).
+char(1,81305).
+char(4,81306).
+char(c,81307).
+char(c,81308).
+char(p,81309).
+char(5,81310).
+char(6,81311).
+char(2,81312).
+char(4,81313).
+char(c,81314).
+char(c,81315).
+char(c,81316).
+char(p,81317).
+char(3,81318).
+char(8,81319).
+char(9,81320).
+char(5,81321).
+char(m,81322).
+char(o,81323).
+char(p,81324).
+char(6,81325).
+char(4,81326).
+char(9,81327).
+char(8,81328).
+char(m,81329).
+char(6,81330).
+char(0,81331).
+char(2,81332).
+char(0,81333).
+char(c,81334).
+char(c,81335).
+char(c,81336).
+char(c,81337).
+char(m,81338).
+char(o,81339).
+char(2,81340).
+char(1,81341).
+char(6,81342).
+char(0,81343).
+char(p,81344).
+char(6,81345).
+char(4,81346).
+char(2,81347).
+char(1,81348).
+char(c,81349).
+char(c,81350).
+char(p,81351).
+char(o,81352).
+char(p,81353).
+char(4,81354).
+char(2,81355).
+char(2,81356).
+char(0,81357).
+char(c,81358).
+char(c,81359).
+char(c,81360).
+char(p,81361).
+char(3,81362).
+char(5,81363).
+char(7,81364).
+char(4,81365).
+char(c,81366).
+char(m,81367).
+char(o,81368).
+char(m,81369).
+char(9,81370).
+char(6,81371).
+char(7,81372).
+char(c,81373).
+char(p,81374).
+char(7,81375).
+char(7,81376).
+char(5,81377).
+char(7,81378).
+char(c,81379).
+char(c,81380).
+char(c,81381).
+char(c,81382).
+char(c,81383).
+char(c,81384).
+char(c,81385).
+char(m,81386).
+char(4,81387).
+char(1,81388).
+char(0,81389).
+char(4,81390).
+char(c,81391).
+char(p,81392).
+char(o,81393).
+char(o,81394).
+char(p,81395).
+char(o,81396).
+char(1,81397).
+char(4,81398).
+char(0,81399).
+char(9,81400).
+char(c,81401).
+char(p,81402).
+char(o,81403).
+char(p,81404).
+char(o,81405).
+char(1,81406).
+char(9,81407).
+char(8,81408).
+char(4,81409).
+char(p,81410).
+char(o,81411).
+char(m,81412).
+char(o,81413).
+char(6,81414).
+char(0,81415).
+char(2,81416).
+char(2,81417).
+char(c,81418).
+char(m,81419).
+char(o,81420).
+char(p,81421).
+char(6,81422).
+char(9,81423).
+char(5,81424).
+char(0,81425).
+char(p,81426).
+char(o,81427).
+char(9,81428).
+char(3,81429).
+char(8,81430).
+char(6,81431).
+char(m,81432).
+char(1,81433).
+char(1,81434).
+char(9,81435).
+char(6,81436).
+char(c,81437).
+char(c,81438).
+char(c,81439).
+char(c,81440).
+char(m,81441).
+char(7,81442).
+char(3,81443).
+char(9,81444).
+char(3,81445).
+char(p,81446).
+char(7,81447).
+char(0,81448).
+char(4,81449).
+char(2,81450).
+char(c,81451).
+char(c,81452).
+char(m,81453).
+char(o,81454).
+char(m,81455).
+char(9,81456).
+char(0,81457).
+char(8,81458).
+char(5,81459).
+char(c,81460).
+char(p,81461).
+char(7,81462).
+char(7,81463).
+char(2,81464).
+char(4,81465).
+char(c,81466).
+char(c,81467).
+char(p,81468).
+char(5,81469).
+char(6,81470).
+char(3,81471).
+char(1,81472).
+char(c,81473).
+char(m,81474).
+char(6,81475).
+char(5,81476).
+char(8,81477).
+char(9,81478).
+char(m,81479).
+char(o,81480).
+char(p,81481).
+char(o,81482).
+char(3,81483).
+char(8,81484).
+char(1,81485).
+char(c,81486).
+char(c,81487).
+char(p,81488).
+char(4,81489).
+char(1,81490).
+char(0,81491).
+char(2,81492).
+char(c,81493).
+char(c,81494).
+char(p,81495).
+char(1,81496).
+char(1,81497).
+char(3,81498).
+char(8,81499).
+char(c,81500).
+char(c,81501).
+char(c,81502).
+char(m,81503).
+char(6,81504).
+char(4,81505).
+char(5,81506).
+char(0,81507).
+char(c,81508).
+char(m,81509).
+char(5,81510).
+char(6,81511).
+char(9,81512).
+char(8,81513).
+char(c,81514).
+char(c,81515).
+char(c,81516).
+char(c,81517).
+char(m,81518).
+char(2,81519).
+char(7,81520).
+char(2,81521).
+char(6,81522).
+char(m,81523).
+char(7,81524).
+char(8,81525).
+char(0,81526).
+char(1,81527).
+char(m,81528).
+char(o,81529).
+char(m,81530).
+char(9,81531).
+char(2,81532).
+char(8,81533).
+char(2,81534).
+char(p,81535).
+char(o,81536).
+char(o,81537).
+char(o,81538).
+char(p,81539).
+char(1,81540).
+char(1,81541).
+char(4,81542).
+char(7,81543).
+char(c,81544).
+char(m,81545).
+char(6,81546).
+char(9,81547).
+char(1,81548).
+char(7,81549).
+char(c,81550).
+char(c,81551).
+char(c,81552).
+char(c,81553).
+char(c,81554).
+char(m,81555).
+char(8,81556).
+char(3,81557).
+char(2,81558).
+char(9,81559).
+char(c,81560).
+char(m,81561).
+char(1,81562).
+char(2,81563).
+char(7,81564).
+char(0,81565).
+char(c,81566).
+char(m,81567).
+char(7,81568).
+char(3,81569).
+char(2,81570).
+char(5,81571).
+char(m,81572).
+char(o,81573).
+char(4,81574).
+char(6,81575).
+char(2,81576).
+char(7,81577).
+char(p,81578).
+char(o,81579).
+char(p,81580).
+char(o,81581).
+char(7,81582).
+char(8,81583).
+char(5,81584).
+char(8,81585).
+char(p,81586).
+char(3,81587).
+char(5,81588).
+char(6,81589).
+char(1,81590).
+char(p,81591).
+char(7,81592).
+char(5,81593).
+char(0,81594).
+char(2,81595).
+char(c,81596).
+char(c,81597).
+char(c,81598).
+char(p,81599).
+char(4,81600).
+char(0,81601).
+char(0,81602).
+char(0,81603).
+char(c,81604).
+char(m,81605).
+char(3,81606).
+char(2,81607).
+char(4,81608).
+char(1,81609).
+char(c,81610).
+char(p,81611).
+char(o,81612).
+char(p,81613).
+char(4,81614).
+char(3,81615).
+char(2,81616).
+char(1,81617).
+char(c,81618).
+char(c,81619).
+char(c,81620).
+char(c,81621).
+char(p,81622).
+char(o,81623).
+char(o,81624).
+char(m,81625).
+char(o,81626).
+char(o,81627).
+char(o,81628).
+char(6,81629).
+char(1,81630).
+char(9,81631).
+char(c,81632).
+char(m,81633).
+char(o,81634).
+char(p,81635).
+char(o,81636).
+char(6,81637).
+char(4,81638).
+char(9,81639).
+char(c,81640).
+char(c,81641).
+char(p,81642).
+char(4,81643).
+char(8,81644).
+char(2,81645).
+char(6,81646).
+char(m,81647).
+char(9,81648).
+char(0,81649).
+char(3,81650).
+char(6,81651).
+char(c,81652).
+char(p,81653).
+char(o,81654).
+char(m,81655).
+char(3,81656).
+char(9,81657).
+char(8,81658).
+char(0,81659).
+char(c,81660).
+char(p,81661).
+char(9,81662).
+char(0,81663).
+char(6,81664).
+char(1,81665).
+char(c,81666).
+char(p,81667).
+char(4,81668).
+char(7,81669).
+char(0,81670).
+char(8,81671).
+char(m,81672).
+char(5,81673).
+char(7,81674).
+char(8,81675).
+char(1,81676).
+char(c,81677).
+char(c,81678).
+char(p,81679).
+char(2,81680).
+char(5,81681).
+char(5,81682).
+char(9,81683).
+char(m,81684).
+char(5,81685).
+char(4,81686).
+char(1,81687).
+char(2,81688).
+char(c,81689).
+char(m,81690).
+char(o,81691).
+char(p,81692).
+char(9,81693).
+char(5,81694).
+char(8,81695).
+char(6,81696).
+char(c,81697).
+char(c,81698).
+char(p,81699).
+char(4,81700).
+char(2,81701).
+char(8,81702).
+char(9,81703).
+char(c,81704).
+char(p,81705).
+char(o,81706).
+char(1,81707).
+char(5,81708).
+char(3,81709).
+char(4,81710).
+char(c,81711).
+char(c,81712).
+char(p,81713).
+char(6,81714).
+char(6,81715).
+char(5,81716).
+char(6,81717).
+char(c,81718).
+char(c,81719).
+char(m,81720).
+char(7,81721).
+char(1,81722).
+char(6,81723).
+char(0,81724).
+char(c,81725).
+char(c,81726).
+char(p,81727).
+char(o,81728).
+char(p,81729).
+char(3,81730).
+char(8,81731).
+char(9,81732).
+char(3,81733).
+char(m,81734).
+char(4,81735).
+char(7,81736).
+char(1,81737).
+char(7,81738).
+char(c,81739).
+char(c,81740).
+char(p,81741).
+char(o,81742).
+char(m,81743).
+char(o,81744).
+char(p,81745).
+char(o,81746).
+char(3,81747).
+char(8,81748).
+char(7,81749).
+char(0,81750).
+char(c,81751).
+char(p,81752).
+char(o,81753).
+char(3,81754).
+char(5,81755).
+char(8,81756).
+char(2,81757).
+char(p,81758).
+char(6,81759).
+char(7,81760).
+char(2,81761).
+char(9,81762).
+char(p,81763).
+char(o,81764).
+char(p,81765).
+char(o,81766).
+char(p,81767).
+char(8,81768).
+char(0,81769).
+char(4,81770).
+char(0,81771).
+char(m,81772).
+char(2,81773).
+char(5,81774).
+char(2,81775).
+char(9,81776).
+char(c,81777).
+char(m,81778).
+char(7,81779).
+char(6,81780).
+char(5,81781).
+char(5,81782).
+char(c,81783).
+char(m,81784).
+char(5,81785).
+char(0,81786).
+char(7,81787).
+char(2,81788).
+char(m,81789).
+char(o,81790).
+char(m,81791).
+char(o,81792).
+char(o,81793).
+char(m,81794).
+char(2,81795).
+char(0,81796).
+char(9,81797).
+char(9,81798).
+char(c,81799).
+char(c,81800).
+char(c,81801).
+char(m,81802).
+char(3,81803).
+char(2,81804).
+char(2,81805).
+char(c,81806).
+char(c,81807).
+char(m,81808).
+char(2,81809).
+char(7,81810).
+char(9,81811).
+char(c,81812).
+char(c,81813).
+char(p,81814).
+char(1,81815).
+char(8,81816).
+char(7,81817).
+char(3,81818).
+char(c,81819).
+char(c,81820).
+char(c,81821).
+char(c,81822).
+char(c,81823).
+char(c,81824).
+char(c,81825).
+char(c,81826).
+char(c,81827).
+char(p,81828).
+char(o,81829).
+char(o,81830).
+char(o,81831).
+char(7,81832).
+char(9,81833).
+char(4,81834).
+char(6,81835).
+char(c,81836).
+char(m,81837).
+char(o,81838).
+char(8,81839).
+char(8,81840).
+char(5,81841).
+char(1,81842).
+char(c,81843).
+char(c,81844).
+char(c,81845).
+char(p,81846).
+char(o,81847).
+char(p,81848).
+char(9,81849).
+char(9,81850).
+char(8,81851).
+char(6,81852).
+char(c,81853).
+char(c,81854).
+char(c,81855).
+char(c,81856).
+char(c,81857).
+char(p,81858).
+char(6,81859).
+char(7,81860).
+char(4,81861).
+char(7,81862).
+char(c,81863).
+char(c,81864).
+char(c,81865).
+char(c,81866).
+char(m,81867).
+char(o,81868).
+char(o,81869).
+char(m,81870).
+char(4,81871).
+char(6,81872).
+char(p,81873).
+char(o,81874).
+char(m,81875).
+char(o,81876).
+char(m,81877).
+char(o,81878).
+char(p,81879).
+char(o,81880).
+char(m,81881).
+char(1,81882).
+char(3,81883).
+char(4,81884).
+char(c,81885).
+char(m,81886).
+char(3,81887).
+char(5,81888).
+char(2,81889).
+char(6,81890).
+char(c,81891).
+char(c,81892).
+char(p,81893).
+char(o,81894).
+char(m,81895).
+char(7,81896).
+char(4,81897).
+char(5,81898).
+char(5,81899).
+char(c,81900).
+char(p,81901).
+char(o,81902).
+char(m,81903).
+char(o,81904).
+char(9,81905).
+char(5,81906).
+char(3,81907).
+char(6,81908).
+char(c,81909).
+char(c,81910).
+char(p,81911).
+char(o,81912).
+char(m,81913).
+char(o,81914).
+char(5,81915).
+char(5,81916).
+char(3,81917).
+char(8,81918).
+char(p,81919).
+char(o,81920).
+char(o,81921).
+char(p,81922).
+char(o,81923).
+char(m,81924).
+char(o,81925).
+char(o,81926).
+char(o,81927).
+char(o,81928).
+char(p,81929).
+char(o,81930).
+char(m,81931).
+char(7,81932).
+char(4,81933).
+char(6,81934).
+char(8,81935).
+char(p,81936).
+char(2,81937).
+char(4,81938).
+char(4,81939).
+char(6,81940).
+char(c,81941).
+char(p,81942).
+char(o,81943).
+char(3,81944).
+char(5,81945).
+char(8,81946).
+char(p,81947).
+char(o,81948).
+char(m,81949).
+char(2,81950).
+char(7,81951).
+char(7,81952).
+char(8,81953).
+char(c,81954).
+char(m,81955).
+char(o,81956).
+char(p,81957).
+char(1,81958).
+char(0,81959).
+char(2,81960).
+char(1,81961).
+char(m,81962).
+char(2,81963).
+char(3,81964).
+char(7,81965).
+char(7,81966).
+char(m,81967).
+char(6,81968).
+char(1,81969).
+char(3,81970).
+char(9,81971).
+char(p,81972).
+char(o,81973).
+char(m,81974).
+char(2,81975).
+char(5,81976).
+char(9,81977).
+char(3,81978).
+char(m,81979).
+char(1,81980).
+char(6,81981).
+char(6,81982).
+char(7,81983).
+char(c,81984).
+char(p,81985).
+char(2,81986).
+char(4,81987).
+char(0,81988).
+char(4,81989).
+char(c,81990).
+char(c,81991).
+char(m,81992).
+char(6,81993).
+char(9,81994).
+char(4,81995).
+char(7,81996).
+char(m,81997).
+char(o,81998).
+char(m,81999).
+char(6,82000).
+char(1,82001).
+char(6,82002).
+char(1,82003).
+char(p,82004).
+char(9,82005).
+char(9,82006).
+char(6,82007).
+char(4,82008).
+char(c,82009).
+char(p,82010).
+char(o,82011).
+char(m,82012).
+char(o,82013).
+char(3,82014).
+char(5,82015).
+char(2,82016).
+char(1,82017).
+char(c,82018).
+char(m,82019).
+char(o,82020).
+char(p,82021).
+char(o,82022).
+char(o,82023).
+char(m,82024).
+char(7,82025).
+char(9,82026).
+char(3,82027).
+char(6,82028).
+char(p,82029).
+char(7,82030).
+char(2,82031).
+char(4,82032).
+char(3,82033).
+char(c,82034).
+char(c,82035).
+char(p,82036).
+char(o,82037).
+char(4,82038).
+char(7,82039).
+char(6,82040).
+char(3,82041).
+char(m,82042).
+char(4,82043).
+char(3,82044).
+char(3,82045).
+char(9,82046).
+char(m,82047).
+char(o,82048).
+char(p,82049).
+char(7,82050).
+char(1,82051).
+char(8,82052).
+char(2,82053).
+char(c,82054).
+char(c,82055).
+char(c,82056).
+char(p,82057).
+char(9,82058).
+char(2,82059).
+char(2,82060).
+char(2,82061).
+char(p,82062).
+char(o,82063).
+char(p,82064).
+char(7,82065).
+char(1,82066).
+char(9,82067).
+char(9,82068).
+char(m,82069).
+char(o,82070).
+char(3,82071).
+char(9,82072).
+char(8,82073).
+char(3,82074).
+char(c,82075).
+char(c,82076).
+char(p,82077).
+char(o,82078).
+char(m,82079).
+char(9,82080).
+char(2,82081).
+char(0,82082).
+char(c,82083).
+char(p,82084).
+char(2,82085).
+char(5,82086).
+char(2,82087).
+char(0,82088).
+char(c,82089).
+char(c,82090).
+char(c,82091).
+char(c,82092).
+char(c,82093).
+char(p,82094).
+char(o,82095).
+char(m,82096).
+char(o,82097).
+char(o,82098).
+char(m,82099).
+char(4,82100).
+char(5,82101).
+char(9,82102).
+char(5,82103).
+char(c,82104).
+char(p,82105).
+char(o,82106).
+char(o,82107).
+char(p,82108).
+char(9,82109).
+char(4,82110).
+char(2,82111).
+char(7,82112).
+char(c,82113).
+char(c,82114).
+char(m,82115).
+char(1,82116).
+char(5,82117).
+char(5,82118).
+char(2,82119).
+char(p,82120).
+char(5,82121).
+char(0,82122).
+char(7,82123).
+char(0,82124).
+char(p,82125).
+char(o,82126).
+char(o,82127).
+char(m,82128).
+char(o,82129).
+char(m,82130).
+char(8,82131).
+char(8,82132).
+char(2,82133).
+char(4,82134).
+char(m,82135).
+char(7,82136).
+char(4,82137).
+char(1,82138).
+char(0,82139).
+char(c,82140).
+char(c,82141).
+char(c,82142).
+char(c,82143).
+char(c,82144).
+char(m,82145).
+char(3,82146).
+char(6,82147).
+char(7,82148).
+char(m,82149).
+char(6,82150).
+char(1,82151).
+char(5,82152).
+char(5,82153).
+char(p,82154).
+char(3,82155).
+char(9,82156).
+char(2,82157).
+char(2,82158).
+char(m,82159).
+char(o,82160).
+char(o,82161).
+char(o,82162).
+char(p,82163).
+char(8,82164).
+char(3,82165).
+char(8,82166).
+char(6,82167).
+char(c,82168).
+char(c,82169).
+char(m,82170).
+char(o,82171).
+char(p,82172).
+char(o,82173).
+char(m,82174).
+char(7,82175).
+char(2,82176).
+char(3,82177).
+char(0,82178).
+char(c,82179).
+char(c,82180).
+char(c,82181).
+char(c,82182).
+char(m,82183).
+char(o,82184).
+char(p,82185).
+char(o,82186).
+char(5,82187).
+char(0,82188).
+char(8,82189).
+char(8,82190).
+char(c,82191).
+char(c,82192).
+char(c,82193).
+char(p,82194).
+char(o,82195).
+char(p,82196).
+char(5,82197).
+char(0,82198).
+char(8,82199).
+char(7,82200).
+char(p,82201).
+char(o,82202).
+char(m,82203).
+char(5,82204).
+char(3,82205).
+char(7,82206).
+char(1,82207).
+char(m,82208).
+char(9,82209).
+char(1,82210).
+char(4,82211).
+char(5,82212).
+char(m,82213).
+char(o,82214).
+char(m,82215).
+char(1,82216).
+char(5,82217).
+char(0,82218).
+char(5,82219).
+char(c,82220).
+char(p,82221).
+char(4,82222).
+char(5,82223).
+char(3,82224).
+char(p,82225).
+char(o,82226).
+char(p,82227).
+char(o,82228).
+char(p,82229).
+char(6,82230).
+char(0,82231).
+char(1,82232).
+char(6,82233).
+char(c,82234).
+char(c,82235).
+char(m,82236).
+char(7,82237).
+char(8,82238).
+char(9,82239).
+char(6,82240).
+char(c,82241).
+char(p,82242).
+char(o,82243).
+char(8,82244).
+char(9,82245).
+char(1,82246).
+char(7,82247).
+char(c,82248).
+char(c,82249).
+char(m,82250).
+char(6,82251).
+char(3,82252).
+char(8,82253).
+char(c,82254).
+char(m,82255).
+char(o,82256).
+char(p,82257).
+char(5,82258).
+char(8,82259).
+char(2,82260).
+char(3,82261).
+char(c,82262).
+char(c,82263).
+char(c,82264).
+char(m,82265).
+char(2,82266).
+char(3,82267).
+char(5,82268).
+char(2,82269).
+char(m,82270).
+char(o,82271).
+char(1,82272).
+char(4,82273).
+char(5,82274).
+char(8,82275).
+char(p,82276).
+char(o,82277).
+char(o,82278).
+char(m,82279).
+char(3,82280).
+char(4,82281).
+char(9,82282).
+char(2,82283).
+char(c,82284).
+char(m,82285).
+char(o,82286).
+char(p,82287).
+char(8,82288).
+char(6,82289).
+char(4,82290).
+char(6,82291).
+char(c,82292).
+char(m,82293).
+char(o,82294).
+char(m,82295).
+char(1,82296).
+char(9,82297).
+char(3,82298).
+char(9,82299).
+char(m,82300).
+char(o,82301).
+char(p,82302).
+char(o,82303).
+char(m,82304).
+char(o,82305).
+char(o,82306).
+char(p,82307).
+char(o,82308).
+char(o,82309).
+char(m,82310).
+char(9,82311).
+char(8,82312).
+char(8,82313).
+char(6,82314).
+char(c,82315).
+char(c,82316).
+char(p,82317).
+char(o,82318).
+char(p,82319).
+char(o,82320).
+char(6,82321).
+char(2,82322).
+char(6,82323).
+char(p,82324).
+char(o,82325).
+char(p,82326).
+char(o,82327).
+char(p,82328).
+char(o,82329).
+char(p,82330).
+char(o,82331).
+char(p,82332).
+char(o,82333).
+char(m,82334).
+char(5,82335).
+char(0,82336).
+char(3,82337).
+char(7,82338).
+char(c,82339).
+char(m,82340).
+char(o,82341).
+char(m,82342).
+char(7,82343).
+char(5,82344).
+char(8,82345).
+char(4,82346).
+char(m,82347).
+char(8,82348).
+char(0,82349).
+char(5,82350).
+char(6,82351).
+char(c,82352).
+char(p,82353).
+char(5,82354).
+char(3,82355).
+char(7,82356).
+char(6,82357).
+char(m,82358).
+char(1,82359).
+char(7,82360).
+char(9,82361).
+char(9,82362).
+char(m,82363).
+char(9,82364).
+char(4,82365).
+char(2,82366).
+char(5,82367).
+char(c,82368).
+char(m,82369).
+char(o,82370).
+char(p,82371).
+char(6,82372).
+char(1,82373).
+char(1,82374).
+char(4,82375).
+char(m,82376).
+char(3,82377).
+char(3,82378).
+char(9,82379).
+char(6,82380).
+char(m,82381).
+char(o,82382).
+char(p,82383).
+char(1,82384).
+char(7,82385).
+char(6,82386).
+char(5,82387).
+char(c,82388).
+char(p,82389).
+char(5,82390).
+char(4,82391).
+char(8,82392).
+char(0,82393).
+char(m,82394).
+char(o,82395).
+char(m,82396).
+char(o,82397).
+char(p,82398).
+char(7,82399).
+char(1,82400).
+char(5,82401).
+char(5,82402).
+char(c,82403).
+char(m,82404).
+char(o,82405).
+char(p,82406).
+char(1,82407).
+char(5,82408).
+char(2,82409).
+char(3,82410).
+char(c,82411).
+char(p,82412).
+char(o,82413).
+char(p,82414).
+char(4,82415).
+char(4,82416).
+char(7,82417).
+char(6,82418).
+char(p,82419).
+char(o,82420).
+char(o,82421).
+char(m,82422).
+char(9,82423).
+char(6,82424).
+char(5,82425).
+char(8,82426).
+char(m,82427).
+char(2,82428).
+char(4,82429).
+char(1,82430).
+char(8,82431).
+char(c,82432).
+char(m,82433).
+char(o,82434).
+char(p,82435).
+char(7,82436).
+char(6,82437).
+char(8,82438).
+char(3,82439).
+char(p,82440).
+char(o,82441).
+char(o,82442).
+char(o,82443).
+char(m,82444).
+char(8,82445).
+char(5,82446).
+char(5,82447).
+char(3,82448).
+char(m,82449).
+char(o,82450).
+char(p,82451).
+char(3,82452).
+char(4,82453).
+char(7,82454).
+char(0,82455).
+char(m,82456).
+char(2,82457).
+char(9,82458).
+char(1,82459).
+char(6,82460).
+char(c,82461).
+char(p,82462).
+char(6,82463).
+char(0,82464).
+char(9,82465).
+char(0,82466).
+char(p,82467).
+char(o,82468).
+char(7,82469).
+char(2,82470).
+char(9,82471).
+char(3,82472).
+char(p,82473).
+char(o,82474).
+char(m,82475).
+char(7,82476).
+char(9,82477).
+char(0,82478).
+char(3,82479).
+char(m,82480).
+char(3,82481).
+char(7,82482).
+char(8,82483).
+char(4,82484).
+char(p,82485).
+char(o,82486).
+char(m,82487).
+char(6,82488).
+char(1,82489).
+char(2,82490).
+char(1,82491).
+char(m,82492).
+char(6,82493).
+char(3,82494).
+char(7,82495).
+char(4,82496).
+char(c,82497).
+char(c,82498).
+char(p,82499).
+char(o,82500).
+char(p,82501).
+char(8,82502).
+char(4,82503).
+char(8,82504).
+char(0,82505).
+char(m,82506).
+char(o,82507).
+char(o,82508).
+char(m,82509).
+char(8,82510).
+char(4,82511).
+char(7,82512).
+char(8,82513).
+char(c,82514).
+char(c,82515).
+char(c,82516).
+char(c,82517).
+char(c,82518).
+char(m,82519).
+char(o,82520).
+char(m,82521).
+char(6,82522).
+char(3,82523).
+char(7,82524).
+char(3,82525).
+char(c,82526).
+char(c,82527).
+char(c,82528).
+char(c,82529).
+char(c,82530).
+char(c,82531).
+char(c,82532).
+char(p,82533).
+char(o,82534).
+char(2,82535).
+char(2,82536).
+char(0,82537).
+char(8,82538).
+char(c,82539).
+char(c,82540).
+char(c,82541).
+char(c,82542).
+char(m,82543).
+char(6,82544).
+char(4,82545).
+char(3,82546).
+char(4,82547).
+char(c,82548).
+char(c,82549).
+char(c,82550).
+char(p,82551).
+char(o,82552).
+char(5,82553).
+char(5,82554).
+char(9,82555).
+char(7,82556).
+char(m,82557).
+char(3,82558).
+char(6,82559).
+char(8,82560).
+char(1,82561).
+char(c,82562).
+char(c,82563).
+char(c,82564).
+char(c,82565).
+char(c,82566).
+char(c,82567).
+char(m,82568).
+char(5,82569).
+char(5,82570).
+char(6,82571).
+char(1,82572).
+char(p,82573).
+char(3,82574).
+char(3,82575).
+char(9,82576).
+char(1,82577).
+char(c,82578).
+char(c,82579).
+char(c,82580).
+char(c,82581).
+char(p,82582).
+char(1,82583).
+char(8,82584).
+char(3,82585).
+char(1,82586).
+char(p,82587).
+char(o,82588).
+char(p,82589).
+char(6,82590).
+char(6,82591).
+char(9,82592).
+char(1,82593).
+char(m,82594).
+char(o,82595).
+char(p,82596).
+char(o,82597).
+char(m,82598).
+char(o,82599).
+char(o,82600).
+char(p,82601).
+char(5,82602).
+char(4,82603).
+char(5,82604).
+char(1,82605).
+char(c,82606).
+char(p,82607).
+char(o,82608).
+char(7,82609).
+char(3,82610).
+char(9,82611).
+char(7,82612).
+char(p,82613).
+char(o,82614).
+char(m,82615).
+char(7,82616).
+char(2,82617).
+char(8,82618).
+char(3,82619).
+char(p,82620).
+char(o,82621).
+char(p,82622).
+char(3,82623).
+char(1,82624).
+char(8,82625).
+char(8,82626).
+char(c,82627).
+char(c,82628).
+char(c,82629).
+char(c,82630).
+char(c,82631).
+char(c,82632).
+char(p,82633).
+char(6,82634).
+char(0,82635).
+char(1,82636).
+char(7,82637).
+char(p,82638).
+char(o,82639).
+char(7,82640).
+char(0,82641).
+char(8,82642).
+char(4,82643).
+char(m,82644).
+char(o,82645).
+char(m,82646).
+char(7,82647).
+char(3,82648).
+char(7,82649).
+char(9,82650).
+char(p,82651).
+char(o,82652).
+char(m,82653).
+char(7,82654).
+char(9,82655).
+char(6,82656).
+char(6,82657).
+char(c,82658).
+char(c,82659).
+char(m,82660).
+char(o,82661).
+char(m,82662).
+char(9,82663).
+char(6,82664).
+char(3,82665).
+char(5,82666).
+char(c,82667).
+char(m,82668).
+char(6,82669).
+char(6,82670).
+char(5,82671).
+char(9,82672).
+char(c,82673).
+char(p,82674).
+char(o,82675).
+char(m,82676).
+char(5,82677).
+char(3,82678).
+char(9,82679).
+char(0,82680).
+char(m,82681).
+char(o,82682).
+char(m,82683).
+char(o,82684).
+char(m,82685).
+char(o,82686).
+char(m,82687).
+char(1,82688).
+char(9,82689).
+char(2,82690).
+char(6,82691).
+char(m,82692).
+char(o,82693).
+char(m,82694).
+char(7,82695).
+char(0,82696).
+char(6,82697).
+char(4,82698).
+char(p,82699).
+char(o,82700).
+char(o,82701).
+char(p,82702).
+char(o,82703).
+char(7,82704).
+char(2,82705).
+char(4,82706).
+char(m,82707).
+char(4,82708).
+char(2,82709).
+char(1,82710).
+char(8,82711).
+char(m,82712).
+char(3,82713).
+char(5,82714).
+char(7,82715).
+char(6,82716).
+char(c,82717).
+char(c,82718).
+char(p,82719).
+char(o,82720).
+char(m,82721).
+char(o,82722).
+char(m,82723).
+char(4,82724).
+char(1,82725).
+char(4,82726).
+char(6,82727).
+char(p,82728).
+char(7,82729).
+char(9,82730).
+char(2,82731).
+char(8,82732).
+char(p,82733).
+char(o,82734).
+char(m,82735).
+char(1,82736).
+char(4,82737).
+char(1,82738).
+char(m,82739).
+char(9,82740).
+char(9,82741).
+char(3,82742).
+char(7,82743).
+char(c,82744).
+char(c,82745).
+char(c,82746).
+char(c,82747).
+char(m,82748).
+char(1,82749).
+char(5,82750).
+char(3,82751).
+char(5,82752).
+char(c,82753).
+char(c,82754).
+char(c,82755).
+char(m,82756).
+char(o,82757).
+char(7,82758).
+char(3,82759).
+char(5,82760).
+char(9,82761).
+char(c,82762).
+char(c,82763).
+char(m,82764).
+char(o,82765).
+char(2,82766).
+char(0,82767).
+char(7,82768).
+char(3,82769).
+char(m,82770).
+char(o,82771).
+char(p,82772).
+char(5,82773).
+char(6,82774).
+char(4,82775).
+char(5,82776).
+char(c,82777).
+char(m,82778).
+char(8,82779).
+char(9,82780).
+char(3,82781).
+char(7,82782).
+char(c,82783).
+char(c,82784).
+char(p,82785).
+char(o,82786).
+char(p,82787).
+char(o,82788).
+char(o,82789).
+char(p,82790).
+char(o,82791).
+char(m,82792).
+char(o,82793).
+char(o,82794).
+char(9,82795).
+char(0,82796).
+char(3,82797).
+char(5,82798).
+char(c,82799).
+char(c,82800).
+char(m,82801).
+char(o,82802).
+char(o,82803).
+char(m,82804).
+char(o,82805).
+char(p,82806).
+char(o,82807).
+char(p,82808).
+char(o,82809).
+char(p,82810).
+char(2,82811).
+char(3,82812).
+char(c,82813).
+char(p,82814).
+char(6,82815).
+char(7,82816).
+char(2,82817).
+char(4,82818).
+char(c,82819).
+char(m,82820).
+char(o,82821).
+char(m,82822).
+char(1,82823).
+char(8,82824).
+char(5,82825).
+char(5,82826).
+char(c,82827).
+char(p,82828).
+char(o,82829).
+char(o,82830).
+char(m,82831).
+char(1,82832).
+char(0,82833).
+char(2,82834).
+char(8,82835).
+char(c,82836).
+char(p,82837).
+char(o,82838).
+char(m,82839).
+char(1,82840).
+char(8,82841).
+char(6,82842).
+char(8,82843).
+char(c,82844).
+char(c,82845).
+char(p,82846).
+char(o,82847).
+char(p,82848).
+char(6,82849).
+char(4,82850).
+char(4,82851).
+char(c,82852).
+char(m,82853).
+char(o,82854).
+char(m,82855).
+char(6,82856).
+char(9,82857).
+char(4,82858).
+char(4,82859).
+char(c,82860).
+char(m,82861).
+char(1,82862).
+char(3,82863).
+char(2,82864).
+char(0,82865).
+char(c,82866).
+char(c,82867).
+char(m,82868).
+char(o,82869).
+char(m,82870).
+char(5,82871).
+char(7,82872).
+char(0,82873).
+char(2,82874).
+char(c,82875).
+char(m,82876).
+char(o,82877).
+char(p,82878).
+char(9,82879).
+char(0,82880).
+char(6,82881).
+char(p,82882).
+char(o,82883).
+char(m,82884).
+char(9,82885).
+char(4,82886).
+char(6,82887).
+char(5,82888).
+char(p,82889).
+char(o,82890).
+char(o,82891).
+char(p,82892).
+char(7,82893).
+char(4,82894).
+char(1,82895).
+char(5,82896).
+char(p,82897).
+char(o,82898).
+char(p,82899).
+char(o,82900).
+char(p,82901).
+char(o,82902).
+char(p,82903).
+char(o,82904).
+char(p,82905).
+char(9,82906).
+char(7,82907).
+char(8,82908).
+char(p,82909).
+char(o,82910).
+char(m,82911).
+char(4,82912).
+char(0,82913).
+char(8,82914).
+char(5,82915).
+char(c,82916).
+char(p,82917).
+char(4,82918).
+char(1,82919).
+char(0,82920).
+char(8,82921).
+char(p,82922).
+char(o,82923).
+char(m,82924).
+char(4,82925).
+char(6,82926).
+char(1,82927).
+char(1,82928).
+char(c,82929).
+char(c,82930).
+char(m,82931).
+char(1,82932).
+char(8,82933).
+char(4,82934).
+char(0,82935).
+char(c,82936).
+char(c,82937).
+char(m,82938).
+char(2,82939).
+char(2,82940).
+char(5,82941).
+char(9,82942).
+char(c,82943).
+char(p,82944).
+char(o,82945).
+char(m,82946).
+char(o,82947).
+char(o,82948).
+char(o,82949).
+char(p,82950).
+char(2,82951).
+char(0,82952).
+char(4,82953).
+char(6,82954).
+char(c,82955).
+char(c,82956).
+char(c,82957).
+char(c,82958).
+char(c,82959).
+char(m,82960).
+char(o,82961).
+char(p,82962).
+char(o,82963).
+char(o,82964).
+char(p,82965).
+char(5,82966).
+char(9,82967).
+char(0,82968).
+char(4,82969).
+char(p,82970).
+char(o,82971).
+char(m,82972).
+char(9,82973).
+char(6,82974).
+char(7,82975).
+char(9,82976).
+char(c,82977).
+char(p,82978).
+char(8,82979).
+char(4,82980).
+char(9,82981).
+char(5,82982).
+char(m,82983).
+char(o,82984).
+char(p,82985).
+char(9,82986).
+char(1,82987).
+char(3,82988).
+char(2,82989).
+char(c,82990).
+char(p,82991).
+char(5,82992).
+char(5,82993).
+char(6,82994).
+char(1,82995).
+char(m,82996).
+char(o,82997).
+char(p,82998).
+char(o,82999).
+char(m,83000).
+char(1,83001).
+char(2,83002).
+char(7,83003).
+char(7,83004).
+char(m,83005).
+char(o,83006).
+char(5,83007).
+char(2,83008).
+char(1,83009).
+char(6,83010).
+char(c,83011).
+char(c,83012).
+char(c,83013).
+char(c,83014).
+char(c,83015).
+char(c,83016).
+char(p,83017).
+char(o,83018).
+char(5,83019).
+char(8,83020).
+char(0,83021).
+char(6,83022).
+char(m,83023).
+char(5,83024).
+char(6,83025).
+char(c,83026).
+char(p,83027).
+char(o,83028).
+char(p,83029).
+char(o,83030).
+char(m,83031).
+char(2,83032).
+char(3,83033).
+char(3,83034).
+char(0,83035).
+char(m,83036).
+char(o,83037).
+char(p,83038).
+char(o,83039).
+char(m,83040).
+char(1,83041).
+char(9,83042).
+char(6,83043).
+char(c,83044).
+char(p,83045).
+char(o,83046).
+char(8,83047).
+char(6,83048).
+char(1,83049).
+char(3,83050).
+char(c,83051).
+char(m,83052).
+char(o,83053).
+char(m,83054).
+char(o,83055).
+char(m,83056).
+char(o,83057).
+char(m,83058).
+char(o,83059).
+char(9,83060).
+char(0,83061).
+char(2,83062).
+char(3,83063).
+char(m,83064).
+char(5,83065).
+char(1,83066).
+char(6,83067).
+char(9,83068).
+char(m,83069).
+char(o,83070).
+char(m,83071).
+char(o,83072).
+char(o,83073).
+char(m,83074).
+char(8,83075).
+char(9,83076).
+char(3,83077).
+char(0,83078).
+char(m,83079).
+char(o,83080).
+char(p,83081).
+char(6,83082).
+char(8,83083).
+char(0,83084).
+char(c,83085).
+char(c,83086).
+char(m,83087).
+char(4,83088).
+char(6,83089).
+char(4,83090).
+char(3,83091).
+char(m,83092).
+char(6,83093).
+char(2,83094).
+char(0,83095).
+char(2,83096).
+char(m,83097).
+char(1,83098).
+char(2,83099).
+char(8,83100).
+char(4,83101).
+char(c,83102).
+char(p,83103).
+char(3,83104).
+char(7,83105).
+char(7,83106).
+char(8,83107).
+char(c,83108).
+char(p,83109).
+char(o,83110).
+char(m,83111).
+char(o,83112).
+char(m,83113).
+char(6,83114).
+char(9,83115).
+char(1,83116).
+char(4,83117).
+char(m,83118).
+char(1,83119).
+char(5,83120).
+char(6,83121).
+char(8,83122).
+char(m,83123).
+char(1,83124).
+char(1,83125).
+char(1,83126).
+char(1,83127).
+char(c,83128).
+char(c,83129).
+char(c,83130).
+char(c,83131).
+char(m,83132).
+char(o,83133).
+char(p,83134).
+char(o,83135).
+char(m,83136).
+char(2,83137).
+char(2,83138).
+char(2,83139).
+char(1,83140).
+char(c,83141).
+char(p,83142).
+char(o,83143).
+char(m,83144).
+char(4,83145).
+char(9,83146).
+char(1,83147).
+char(0,83148).
+char(c,83149).
+char(c,83150).
+char(c,83151).
+char(c,83152).
+char(c,83153).
+char(p,83154).
+char(8,83155).
+char(7,83156).
+char(6,83157).
+char(4,83158).
+char(c,83159).
+char(c,83160).
+char(p,83161).
+char(8,83162).
+char(1,83163).
+char(0,83164).
+char(5,83165).
+char(p,83166).
+char(1,83167).
+char(5,83168).
+char(5,83169).
+char(2,83170).
+char(c,83171).
+char(p,83172).
+char(o,83173).
+char(o,83174).
+char(1,83175).
+char(8,83176).
+char(9,83177).
+char(7,83178).
+char(c,83179).
+char(m,83180).
+char(o,83181).
+char(p,83182).
+char(6,83183).
+char(5,83184).
+char(7,83185).
+char(0,83186).
+char(c,83187).
+char(p,83188).
+char(o,83189).
+char(p,83190).
+char(o,83191).
+char(m,83192).
+char(4,83193).
+char(8,83194).
+char(5,83195).
+char(5,83196).
+char(p,83197).
+char(9,83198).
+char(3,83199).
+char(3,83200).
+char(0,83201).
+char(c,83202).
+char(p,83203).
+char(3,83204).
+char(9,83205).
+char(9,83206).
+char(9,83207).
+char(c,83208).
+char(c,83209).
+char(c,83210).
+char(p,83211).
+char(6,83212).
+char(8,83213).
+char(5,83214).
+char(6,83215).
+char(c,83216).
+char(p,83217).
+char(1,83218).
+char(1,83219).
+char(8,83220).
+char(6,83221).
+char(c,83222).
+char(m,83223).
+char(o,83224).
+char(o,83225).
+char(p,83226).
+char(9,83227).
+char(4,83228).
+char(3,83229).
+char(0,83230).
+char(p,83231).
+char(o,83232).
+char(p,83233).
+char(9,83234).
+char(2,83235).
+char(9,83236).
+char(c,83237).
+char(c,83238).
+char(m,83239).
+char(o,83240).
+char(o,83241).
+char(o,83242).
+char(m,83243).
+char(3,83244).
+char(6,83245).
+char(2,83246).
+char(7,83247).
+char(p,83248).
+char(o,83249).
+char(m,83250).
+char(4,83251).
+char(1,83252).
+char(3,83253).
+char(4,83254).
+char(p,83255).
+char(7,83256).
+char(6,83257).
+char(2,83258).
+char(8,83259).
+char(p,83260).
+char(6,83261).
+char(9,83262).
+char(0,83263).
+char(0,83264).
+char(m,83265).
+char(3,83266).
+char(2,83267).
+char(1,83268).
+char(6,83269).
+char(c,83270).
+char(c,83271).
+char(p,83272).
+char(7,83273).
+char(9,83274).
+char(3,83275).
+char(4,83276).
+char(m,83277).
+char(o,83278).
+char(p,83279).
+char(4,83280).
+char(8,83281).
+char(9,83282).
+char(9,83283).
+char(c,83284).
+char(p,83285).
+char(o,83286).
+char(p,83287).
+char(6,83288).
+char(5,83289).
+char(0,83290).
+char(1,83291).
+char(p,83292).
+char(8,83293).
+char(8,83294).
+char(9,83295).
+char(4,83296).
+char(p,83297).
+char(o,83298).
+char(3,83299).
+char(8,83300).
+char(1,83301).
+char(1,83302).
+char(p,83303).
+char(o,83304).
+char(o,83305).
+char(6,83306).
+char(9,83307).
+char(9,83308).
+char(6,83309).
+char(c,83310).
+char(p,83311).
+char(4,83312).
+char(1,83313).
+char(8,83314).
+char(2,83315).
+char(c,83316).
+char(c,83317).
+char(c,83318).
+char(p,83319).
+char(o,83320).
+char(p,83321).
+char(o,83322).
+char(o,83323).
+char(o,83324).
+char(m,83325).
+char(o,83326).
+char(o,83327).
+char(m,83328).
+char(o,83329).
+char(6,83330).
+char(2,83331).
+char(9,83332).
+char(4,83333).
+char(c,83334).
+char(c,83335).
+char(m,83336).
+char(4,83337).
+char(4,83338).
+char(2,83339).
+char(7,83340).
+char(c,83341).
+char(c,83342).
+char(m,83343).
+char(5,83344).
+char(1,83345).
+char(0,83346).
+char(2,83347).
+char(c,83348).
+char(p,83349).
+char(5,83350).
+char(0,83351).
+char(1,83352).
+char(1,83353).
+char(c,83354).
+char(c,83355).
+char(p,83356).
+char(9,83357).
+char(3,83358).
+char(5,83359).
+char(0,83360).
+char(p,83361).
+char(o,83362).
+char(m,83363).
+char(2,83364).
+char(3,83365).
+char(0,83366).
+char(1,83367).
+char(m,83368).
+char(o,83369).
+char(m,83370).
+char(o,83371).
+char(9,83372).
+char(9,83373).
+char(3,83374).
+char(5,83375).
+char(c,83376).
+char(c,83377).
+char(c,83378).
+char(c,83379).
+char(m,83380).
+char(6,83381).
+char(1,83382).
+char(6,83383).
+char(c,83384).
+char(m,83385).
+char(2,83386).
+char(2,83387).
+char(8,83388).
+char(6,83389).
+char(c,83390).
+char(c,83391).
+char(c,83392).
+char(p,83393).
+char(o,83394).
+char(o,83395).
+char(m,83396).
+char(8,83397).
+char(1,83398).
+char(9,83399).
+char(5,83400).
+char(p,83401).
+char(9,83402).
+char(3,83403).
+char(1,83404).
+char(7,83405).
+char(p,83406).
+char(6,83407).
+char(0,83408).
+char(6,83409).
+char(5,83410).
+char(p,83411).
+char(3,83412).
+char(1,83413).
+char(5,83414).
+char(5,83415).
+char(m,83416).
+char(5,83417).
+char(9,83418).
+char(0,83419).
+char(1,83420).
+char(c,83421).
+char(m,83422).
+char(o,83423).
+char(p,83424).
+char(o,83425).
+char(p,83426).
+char(o,83427).
+char(m,83428).
+char(o,83429).
+char(o,83430).
+char(m,83431).
+char(o,83432).
+char(p,83433).
+char(2,83434).
+char(1,83435).
+char(7,83436).
+char(5,83437).
+char(c,83438).
+char(c,83439).
+char(p,83440).
+char(9,83441).
+char(9,83442).
+char(7,83443).
+char(6,83444).
+char(c,83445).
+char(m,83446).
+char(o,83447).
+char(o,83448).
+char(o,83449).
+char(p,83450).
+char(7,83451).
+char(4,83452).
+char(2,83453).
+char(p,83454).
+char(8,83455).
+char(3,83456).
+char(9,83457).
+char(0,83458).
+char(p,83459).
+char(o,83460).
+char(p,83461).
+char(7,83462).
+char(3,83463).
+char(0,83464).
+char(m,83465).
+char(o,83466).
+char(m,83467).
+char(o,83468).
+char(p,83469).
+char(1,83470).
+char(2,83471).
+char(8,83472).
+char(6,83473).
+char(c,83474).
+char(m,83475).
+char(o,83476).
+char(m,83477).
+char(o,83478).
+char(m,83479).
+char(6,83480).
+char(3,83481).
+char(4,83482).
+char(9,83483).
+char(c,83484).
+char(c,83485).
+char(m,83486).
+char(o,83487).
+char(m,83488).
+char(o,83489).
+char(4,83490).
+char(0,83491).
+char(2,83492).
+char(2,83493).
+char(p,83494).
+char(o,83495).
+char(p,83496).
+char(4,83497).
+char(7,83498).
+char(2,83499).
+char(5,83500).
+char(p,83501).
+char(o,83502).
+char(o,83503).
+char(o,83504).
+char(m,83505).
+char(o,83506).
+char(m,83507).
+char(4,83508).
+char(0,83509).
+char(8,83510).
+char(4,83511).
+char(m,83512).
+char(o,83513).
+char(m,83514).
+char(o,83515).
+char(p,83516).
+char(9,83517).
+char(8,83518).
+char(8,83519).
+char(6,83520).
+char(c,83521).
+char(m,83522).
+char(5,83523).
+char(5,83524).
+char(9,83525).
+char(4,83526).
+char(c,83527).
+char(c,83528).
+char(c,83529).
+char(c,83530).
+char(m,83531).
+char(o,83532).
+char(p,83533).
+char(o,83534).
+char(m,83535).
+char(o,83536).
+char(o,83537).
+char(p,83538).
+char(o,83539).
+char(p,83540).
+char(o,83541).
+char(m,83542).
+char(o,83543).
+char(7,83544).
+char(8,83545).
+char(9,83546).
+char(8,83547).
+char(m,83548).
+char(2,83549).
+char(8,83550).
+char(6,83551).
+char(c,83552).
+char(c,83553).
+char(c,83554).
+char(p,83555).
+char(7,83556).
+char(1,83557).
+char(3,83558).
+char(7,83559).
+char(p,83560).
+char(o,83561).
+char(m,83562).
+char(o,83563).
+char(m,83564).
+char(o,83565).
+char(m,83566).
+char(1,83567).
+char(4,83568).
+char(7,83569).
+char(6,83570).
+char(c,83571).
+char(p,83572).
+char(8,83573).
+char(2,83574).
+char(c,83575).
+char(m,83576).
+char(o,83577).
+char(o,83578).
+char(p,83579).
+char(o,83580).
+char(m,83581).
+char(3,83582).
+char(2,83583).
+char(7,83584).
+char(8,83585).
+char(m,83586).
+char(3,83587).
+char(8,83588).
+char(5,83589).
+char(1,83590).
+char(c,83591).
+char(p,83592).
+char(7,83593).
+char(2,83594).
+char(4,83595).
+char(5,83596).
+char(m,83597).
+char(6,83598).
+char(3,83599).
+char(0,83600).
+char(7,83601).
+char(c,83602).
+char(c,83603).
+char(c,83604).
+char(c,83605).
+char(c,83606).
+char(p,83607).
+char(o,83608).
+char(m,83609).
+char(o,83610).
+char(m,83611).
+char(o,83612).
+char(m,83613).
+char(o,83614).
+char(p,83615).
+char(o,83616).
+char(o,83617).
+char(m,83618).
+char(3,83619).
+char(3,83620).
+char(4,83621).
+char(1,83622).
+char(m,83623).
+char(6,83624).
+char(6,83625).
+char(9,83626).
+char(7,83627).
+char(m,83628).
+char(4,83629).
+char(2,83630).
+char(8,83631).
+char(9,83632).
+char(c,83633).
+char(c,83634).
+char(p,83635).
+char(3,83636).
+char(8,83637).
+char(4,83638).
+char(3,83639).
+char(c,83640).
+char(c,83641).
+char(p,83642).
+char(o,83643).
+char(m,83644).
+char(8,83645).
+char(5,83646).
+char(9,83647).
+char(6,83648).
+char(c,83649).
+char(m,83650).
+char(1,83651).
+char(5,83652).
+char(3,83653).
+char(2,83654).
+char(c,83655).
+char(p,83656).
+char(o,83657).
+char(9,83658).
+char(5,83659).
+char(4,83660).
+char(9,83661).
+char(m,83662).
+char(4,83663).
+char(8,83664).
+char(3,83665).
+char(5,83666).
+char(p,83667).
+char(9,83668).
+char(5,83669).
+char(0,83670).
+char(3,83671).
+char(p,83672).
+char(o,83673).
+char(m,83674).
+char(o,83675).
+char(p,83676).
+char(o,83677).
+char(m,83678).
+char(8,83679).
+char(5,83680).
+char(9,83681).
+char(4,83682).
+char(p,83683).
+char(o,83684).
+char(o,83685).
+char(m,83686).
+char(o,83687).
+char(m,83688).
+char(o,83689).
+char(p,83690).
+char(9,83691).
+char(5,83692).
+char(1,83693).
+char(2,83694).
+char(c,83695).
+char(c,83696).
+char(c,83697).
+char(m,83698).
+char(6,83699).
+char(3,83700).
+char(7,83701).
+char(4,83702).
+char(c,83703).
+char(c,83704).
+char(m,83705).
+char(6,83706).
+char(6,83707).
+char(6,83708).
+char(5,83709).
+char(m,83710).
+char(o,83711).
+char(p,83712).
+char(9,83713).
+char(2,83714).
+char(3,83715).
+char(0,83716).
+char(c,83717).
+char(c,83718).
+char(c,83719).
+char(p,83720).
+char(8,83721).
+char(7,83722).
+char(0,83723).
+char(9,83724).
+char(c,83725).
+char(c,83726).
+char(m,83727).
+char(6,83728).
+char(4,83729).
+char(3,83730).
+char(2,83731).
+char(c,83732).
+char(m,83733).
+char(1,83734).
+char(0,83735).
+char(6,83736).
+char(8,83737).
+char(c,83738).
+char(p,83739).
+char(4,83740).
+char(6,83741).
+char(5,83742).
+char(c,83743).
+char(c,83744).
+char(c,83745).
+char(c,83746).
+char(p,83747).
+char(o,83748).
+char(p,83749).
+char(8,83750).
+char(1,83751).
+char(9,83752).
+char(c,83753).
+char(m,83754).
+char(2,83755).
+char(7,83756).
+char(3,83757).
+char(7,83758).
+char(m,83759).
+char(4,83760).
+char(6,83761).
+char(6,83762).
+char(3,83763).
+char(c,83764).
+char(m,83765).
+char(o,83766).
+char(m,83767).
+char(3,83768).
+char(0,83769).
+char(6,83770).
+char(8,83771).
+char(m,83772).
+char(o,83773).
+char(o,83774).
+char(o,83775).
+char(7,83776).
+char(6,83777).
+char(6,83778).
+char(m,83779).
+char(o,83780).
+char(p,83781).
+char(2,83782).
+char(4,83783).
+char(0,83784).
+char(0,83785).
+char(c,83786).
+char(p,83787).
+char(9,83788).
+char(7,83789).
+char(4,83790).
+char(c,83791).
+char(c,83792).
+char(c,83793).
+char(c,83794).
+char(c,83795).
+char(m,83796).
+char(8,83797).
+char(7,83798).
+char(8,83799).
+char(8,83800).
+char(m,83801).
+char(o,83802).
+char(p,83803).
+char(o,83804).
+char(p,83805).
+char(o,83806).
+char(m,83807).
+char(9,83808).
+char(6,83809).
+char(3,83810).
+char(6,83811).
+char(c,83812).
+char(c,83813).
+char(c,83814).
+char(p,83815).
+char(o,83816).
+char(m,83817).
+char(6,83818).
+char(9,83819).
+char(0,83820).
+char(m,83821).
+char(1,83822).
+char(5,83823).
+char(7,83824).
+char(3,83825).
+char(p,83826).
+char(1,83827).
+char(8,83828).
+char(1,83829).
+char(7,83830).
+char(c,83831).
+char(c,83832).
+char(c,83833).
+char(c,83834).
+char(c,83835).
+char(c,83836).
+char(c,83837).
+char(m,83838).
+char(7,83839).
+char(0,83840).
+char(6,83841).
+char(7,83842).
+char(p,83843).
+char(o,83844).
+char(4,83845).
+char(4,83846).
+char(5,83847).
+char(1,83848).
+char(c,83849).
+char(c,83850).
+char(p,83851).
+char(o,83852).
+char(8,83853).
+char(1,83854).
+char(1,83855).
+char(9,83856).
+char(p,83857).
+char(9,83858).
+char(0,83859).
+char(3,83860).
+char(5,83861).
+char(m,83862).
+char(2,83863).
+char(9,83864).
+char(6,83865).
+char(3,83866).
+char(c,83867).
+char(c,83868).
+char(m,83869).
+char(o,83870).
+char(p,83871).
+char(3,83872).
+char(5,83873).
+char(4,83874).
+char(4,83875).
+char(p,83876).
+char(2,83877).
+char(7,83878).
+char(5,83879).
+char(7,83880).
+char(p,83881).
+char(5,83882).
+char(7,83883).
+char(6,83884).
+char(9,83885).
+char(c,83886).
+char(c,83887).
+char(c,83888).
+char(p,83889).
+char(o,83890).
+char(o,83891).
+char(3,83892).
+char(0,83893).
+char(9,83894).
+char(5,83895).
+char(m,83896).
+char(6,83897).
+char(4,83898).
+char(5,83899).
+char(8,83900).
+char(c,83901).
+char(m,83902).
+char(1,83903).
+char(9,83904).
+char(8,83905).
+char(8,83906).
+char(c,83907).
+char(p,83908).
+char(9,83909).
+char(7,83910).
+char(9,83911).
+char(8,83912).
+char(m,83913).
+char(o,83914).
+char(1,83915).
+char(1,83916).
+char(4,83917).
+char(0,83918).
+char(c,83919).
+char(c,83920).
+char(p,83921).
+char(o,83922).
+char(m,83923).
+char(9,83924).
+char(7,83925).
+char(0,83926).
+char(1,83927).
+char(p,83928).
+char(4,83929).
+char(6,83930).
+char(6,83931).
+char(c,83932).
+char(c,83933).
+char(p,83934).
+char(9,83935).
+char(1,83936).
+char(5,83937).
+char(m,83938).
+char(3,83939).
+char(0,83940).
+char(9,83941).
+char(0,83942).
+char(c,83943).
+char(c,83944).
+char(c,83945).
+char(g,83946).
+char(1,83947).
+char(7,83948).
+char(2,83949).
+char(7,83950).
+char(5,83951).
diff --git a/examples/gringo/project/README b/examples/gringo/project/README
new file mode 100644
index 0000000..9c0210d
--- /dev/null
+++ b/examples/gringo/project/README
@@ -0,0 +1,5 @@
+Example showcasing the #project directive.
+
+Example calls:
+    clingo --project 0 example.lp
+
diff --git a/examples/gringo/project/example.lp b/examples/gringo/project/example.lp
new file mode 100644
index 0000000..848d772
--- /dev/null
+++ b/examples/gringo/project/example.lp
@@ -0,0 +1,5 @@
+#project p(X).
+
+1 { p(1..2) } 1.
+1 { q(1..2) } 1.
+
diff --git a/examples/gringo/queens/README b/examples/gringo/queens/README
new file mode 100644
index 0000000..7a9c36a
--- /dev/null
+++ b/examples/gringo/queens/README
@@ -0,0 +1,6 @@
+Two examples that encode the n-queens problem.
+
+Example calls:
+    clingo queens1.lp
+    clingo queens2.lp
+
diff --git a/examples/gringo/queens/queens1.lp b/examples/gringo/queens/queens1.lp
new file mode 100644
index 0000000..ff81413
--- /dev/null
+++ b/examples/gringo/queens/queens1.lp
@@ -0,0 +1,15 @@
+#const n = 10.
+n(1..n).
+
+q(X,Y) :- n(X), n(Y), not not q(X,Y).
+
+        c(r,X; c,Y) :- q(X,Y).
+not not c(r,N; c,N) :- n(N).
+
+n(r,X,Y-1,X,Y; c,X-1,Y,X,Y; d1,X-1,Y-1,X,Y;     d2,X-1,Y+1,X,Y      ) :- n(X), n(Y).
+c(r,N,0;       c,0,N;       d1,N-1,0; d1,0,N-1; d2,N-1,n+1; d2,0,N+1) :- n(N).
+
+c(C,XX,YY) :-     c(C,X,Y), n(C,X,Y,XX,YY), not q(XX,YY).
+           :- not c(C,X,Y), n(C,X,Y,XX,YY),     q(XX,YY).
+
+#show q/2.
diff --git a/examples/gringo/queens/queens2.lp b/examples/gringo/queens/queens2.lp
new file mode 100644
index 0000000..b733ac0
--- /dev/null
+++ b/examples/gringo/queens/queens2.lp
@@ -0,0 +1,18 @@
+num(1).
+num(X+1) :- num(X), X < 10.
+
+queen(X,Y) :- not free(X,Y), num(X), num(Y).
+free(X,Y) :- not queen(X,Y), num(X), num(Y).
+
+row(X) :- queen(X,Y).
+col(Y) :- queen(X,Y).
+
+fail :- num(X), not row(X), not fail.
+fail :- num(Y), not col(Y), not fail.
+
+fail :- queen(X,Y), queen(X,V), Y < V, not fail.
+fail :- queen(X,Y), queen(U,Y), X < U, not fail.
+
+fail :- queen(X,Y), queen(U,V), X-Y == U-V, f(X,Y) < f(U,V), not fail.
+fail :- queen(X,Y), queen(U,V), X+Y == U+V, f(X,Y) < f(U,V), not fail.
+
diff --git a/examples/gringo/rec-cond/README b/examples/gringo/rec-cond/README
new file mode 100644
index 0000000..8bebfee
--- /dev/null
+++ b/examples/gringo/rec-cond/README
@@ -0,0 +1,4 @@
+This example shows the use of recursive conditional literals.
+
+Example call:
+    clingo encoding.lp instance.lp
diff --git a/examples/gringo/rec-cond/encoding.lp b/examples/gringo/rec-cond/encoding.lp
new file mode 100644
index 0000000..acb2cf9
--- /dev/null
+++ b/examples/gringo/rec-cond/encoding.lp
@@ -0,0 +1,61 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% INNER VERTICES WITHOUT SELF-LOOP ARE REDUCIBLE %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+inner(V) :- edge(_,V), edge(V,_), not edge(V,V).
+
+link(U,V) :- edge(U,V), 1 { inner(U); inner(V) }.
+
+linked(U,V) :- link(U,V).
+linked(U,V) :- link(U,W), linked(W,V), inner(W), 1 { inner(U); inner(V) }.
+
+inlink(V,N) :- inner(V), N = { linked(U,V) : U != V }.
+oulink(V,N) :- inner(V), N = { linked(V,W) : V != W }.
+
+prefer(V,N) :- inner(V), N = { inner(1..V-1) }.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% ITERATIVELY REDUCE INNER VERTICES AS LONG AS SOME HAS ONE PREDECESSOR/SUCCESSOR %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+unreduced(V,1)   :- inner(V).
+unreduced(V,I+1) :- unreduced(V,I), reduced(W,I), V != W.
+
+linked(U,V,1)   :- link(U,V).
+linked(U,V,I+1) :- linked(U,W,I), linked(W,V,I), reduced(W,I).
+linked(U,V,I+1) :- linked(U,V,I), reduced(I),
+         2 { unreduced(U,I+1); unreduced(V,I+1); not inner(U); not inner(V) }.
+
+irreducible(V,I) :- unreduced(V,I), linked(V,V,I).
+irreducible(V,I) :- unreduced(V,I),
+         2 { linked(U,V,I) : U != V }, 2 { linked(V,W,I) : V != W }.
+
+unlinked(U,V,1)   :- linked(U,V), not link(U,V).
+unlinked(U,V,I+1) :- linked(U,V,I), reduced(U,I), inner(V).
+unlinked(U,V,I+1) :- linked(U,V,I), reduced(V,I), inner(U).
+unlinked(U,V,I+1) :- unlinked(U,V,I), reduced(U,J), J <= I, unreduced(V,I+1).
+unlinked(U,V,I+1) :- unlinked(U,V,I), reduced(V,J), J <= I, unreduced(U,I+1).
+unlinked(U,V,I+1) :- unlinked(U,V,I), reduced(W,I), U != W, V != W,
+           1 { unlinked(U,W,I); unlinked(W,V,I); not linked(U,W); not linked(W,V) }.
+
+reducible(V,I) :- unreduced(V,I), inlink(V,N),
+      N-1 { unlinked(U,V,I) : U != V }, 1 { unlinked(V,V,I); not linked(V,V) }.
+reducible(V,I) :- unreduced(V,I), oulink(V,N),
+      N-1 { unlinked(V,W,I) : V != W }, 1 { unlinked(V,V,I); not linked(V,V) }.
+
+reduced(V,I) :- reducible(V,I), prefer(V,N),
+      N { irreducible(1..V-1,I); reduced(W,J) : W < V, J < I }.
+reduced(I)   :- reduced(_,I).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% FINAL RESULT OF ITERATIVE REDUCTION %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+outvertex(V) :- vertex(V), not inner(V).
+outvertex(V) :- unreduced(V,I), not reduced(I).
+
+outedge(U,V) :- edge(U,V), not link(U,V).
+outedge(U,V) :- linked(U,V,I), not reduced(I).
+
+#show outvertex/1.
+#show outedge/2.
diff --git a/examples/gringo/rec-cond/instance.lp b/examples/gringo/rec-cond/instance.lp
new file mode 100644
index 0000000..bd95319
--- /dev/null
+++ b/examples/gringo/rec-cond/instance.lp
@@ -0,0 +1,132 @@
+%%%%%%%%%%%%%%%%%%%%
+% INPUT PREDICATES %
+%%%%%%%%%%%%%%%%%%%%
+
+vertex(1). vertex(2). vertex(3). vertex(4). vertex(5). vertex(6). vertex(7). vertex(8).
+edge(1,3). edge(2,3). edge(3,4). edge(3,6). edge(4,5). edge(4,6). edge(6,7). edge(6,8).
+
+% 1-+ 4-+-5
+%   | | |
+%   3-+-6-+-7
+%   |     |
+% 2-+     8
+
+%%%%%%%%%%%%%%%%%%%%
+% Intended Result: %
+%%%%%%%%%%%%%%%%%%%%
+
+%*
+outvertex(1) outvertex(2) outvertex(3) outvertex(5) outvertex(7) outvertex(8)
+outedge(1,3) outedge(2,3) outedge(3,5) outedge(3,7) outedge(3,8)
+*%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Intended Instantiation: %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%*
+inner(6).
+inner(4).
+inner(3).
+link(6,8).
+link(6,7).
+link(4,6).
+link(4,5).
+link(3,6).
+link(3,4).
+link(2,3).
+link(1,3).
+linked(1,3).
+linked(2,3).
+linked(3,4).
+linked(3,6).
+linked(4,5).
+linked(4,6).
+linked(6,7).
+linked(6,8).
+linked(1,6).
+linked(1,4).
+linked(2,6).
+linked(2,4).
+linked(3,5).
+linked(3,8).
+linked(3,7).
+linked(4,8).
+linked(4,7).
+inlink(3,2).
+inlink(4,3).
+inlink(6,4).
+oulink(3,5).
+oulink(4,4).
+oulink(6,2).
+prefer(3,0).
+prefer(4,1).
+prefer(6,2).
+
+unreduced(3,1).
+unreduced(4,1).
+unreduced(6,1).
+linked(6,8,1).
+linked(6,7,1).
+linked(4,6,1).
+linked(4,5,1).
+linked(3,6,1).
+linked(3,4,1).
+linked(2,3,1).
+linked(1,3,1).
+irreducible(3,1).
+irreducible(6,1).
+unlinked(1,6,1).
+unlinked(1,4,1).
+unlinked(2,6,1).
+unlinked(2,4,1).
+unlinked(3,5,1).
+unlinked(3,8,1).
+unlinked(3,7,1).
+unlinked(4,8,1).
+unlinked(4,7,1).
+reducible(4,1).
+reduced(4,1).
+reduced(1).
+
+unreduced(3,2).
+unreduced(6,2).
+linked(3,5,2).
+linked(3,6,2).
+linked(6,8,2).
+linked(6,7,2).
+linked(2,3,2).
+linked(1,3,2).
+irreducible(3,2).
+unlinked(4,6,2).
+unlinked(3,4,2).
+unlinked(1,6,2).
+unlinked(2,6,2).
+unlinked(3,8,2).
+unlinked(3,7,2).
+reducible(6,2).
+reduced(6,2).
+reduced(2).
+
+unreduced(3,3).
+linked(3,7,3).
+linked(3,8,3).
+linked(3,5,3).
+linked(2,3,3).
+linked(1,3,3).
+irreducible(3,3).
+unlinked(3,6,3).
+unlinked(3,4,3).
+
+outvertex(1).
+outvertex(2).
+outvertex(3).
+outvertex(5).
+outvertex(7).
+outvertex(8).
+outedge(3,7).
+outedge(3,8).
+outedge(3,5).
+outedge(2,3).
+outedge(1,3).
+*%
diff --git a/examples/gringo/subset/README b/examples/gringo/subset/README
new file mode 100644
index 0000000..ee5844b
--- /dev/null
+++ b/examples/gringo/subset/README
@@ -0,0 +1,6 @@
+Example showcasing the #heuristic directive.  The call below calculates all
+subset minimal models.
+
+Example calls:
+    clingo --heuristic=domain --enum-mode=domRec 0 example.lp
+
diff --git a/examples/gringo/subset/example.lp b/examples/gringo/subset/example.lp
new file mode 100644
index 0000000..41b29e7
--- /dev/null
+++ b/examples/gringo/subset/example.lp
@@ -0,0 +1,7 @@
+#heuristic p(X). [1,false]
+
+3 { p(1..10) }.
+2 { p(1..5) }.
+4 { p(3..8) }.
+2 { p(7..9) }.
+3 { p(2..9) }.
diff --git a/examples/gringo/toh/README b/examples/gringo/toh/README
new file mode 100644
index 0000000..e23083b
--- /dev/null
+++ b/examples/gringo/toh/README
@@ -0,0 +1,6 @@
+Incrementally solve a Towers of Hanoi problem. Note incremental solving is only
+supported by recent clasp versions.
+
+Example calls:
+  gringo -c imax=16 tohE.lp tohI.lp | clasp
+  clingo tohI.lp tohE.lp
diff --git a/examples/gringo/toh/tohE.lp b/examples/gringo/toh/tohE.lp
new file mode 100644
index 0000000..9bbaa73
--- /dev/null
+++ b/examples/gringo/toh/tohE.lp
@@ -0,0 +1,22 @@
+#include .
+
+#program base.
+on(D,P,0) :- init_on(D,P).
+
+#program step(t).
+1 { move(D,P,t) : disk(D), peg(P) } 1.
+
+move(D,t)        :- move(D,P,t).
+on(D,P,t)        :- move(D,P,t).
+on(D,P,t)        :- on(D,P,t-1), not move(D,t).
+blocked(D-1,P,t) :- on(D,P,t-1).
+blocked(D-1,P,t) :- blocked(D,P,t), disk(D).
+
+:- move(D,P,t), blocked(D-1,P,t).
+:- move(D,t), on(D,P,t-1), blocked(D,P,t).
+:- not 1 { on(D,P,t) } 1, disk(D).
+
+#program check(t).
+:- query(t), goal_on(D,P), not on(D,P,t).
+
+#show move/3.
diff --git a/examples/gringo/toh/tohI.lp b/examples/gringo/toh/tohI.lp
new file mode 100644
index 0000000..83837d5
--- /dev/null
+++ b/examples/gringo/toh/tohI.lp
@@ -0,0 +1,6 @@
+#program base.
+peg(a;b;c).
+disk(1..4).
+init_on(1..4,a).
+goal_on(1..4,c).
+
diff --git a/examples/reify/README b/examples/reify/README
new file mode 100644
index 0000000..058d897
--- /dev/null
+++ b/examples/reify/README
@@ -0,0 +1,24 @@
+Example Calls
+=============
+
+Non-reified + Cardinality Minimization
+--------------------------------------
+
+$ clingo example1.lp --opt-mode=optN -q1 0
+
+Reified + Cardinality Minimization
+----------------------------------
+
+$ clingo example1.lp --pre --rewrite-minimize | reify --calculate-sccs |\
+  clingo -Wno-atom-undefined - meta.lp metaD.lp metaO.lp <(echo "optimize(0,1,card).") 0
+
+Reified + Subset Minimization
+-----------------------------
+
+$ clingo example1.lp --pre --rewrite-minimize | reify --calculate-sccs |\
+  clingo -Wno-atom-undefined - meta.lp metaD.lp metaO.lp <(echo "optimize(0,1,incl).") 0
+
+Reified + Subset Minimization + Query to Solve the Conformant Planning Problem
+------------------------------------------------------------------------------
+$ clingo example2.lp --pre | reify |\
+  clingo - meta.lp metaD.lp metaO.lp --project 0
diff --git a/examples/reify/example1.lp b/examples/reify/example1.lp
new file mode 100644
index 0000000..b11c685
--- /dev/null
+++ b/examples/reify/example1.lp
@@ -0,0 +1,5 @@
+1 { p; t }   :- 1 { r; s; not t } 2.
+  { q; r } 1 :- 1 { p; t }.
+    s        :- not q, not r.
+
+#minimize { 1,p:p; 1,q:q; 1,r:r; 1,s:s }.
diff --git a/examples/reify/example2.lp b/examples/reify/example2.lp
new file mode 100644
index 0000000..5ed5056
--- /dev/null
+++ b/examples/reify/example2.lp
@@ -0,0 +1,220 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% setup %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#const horizon=9.
+time(1..horizon).
+
+complement(F,F,neg(F)) :- fluent(F).
+complement(F,neg(F)) :- fluent(F).
+complement(neg(F),F) :- fluent(F).
+
+contradict(F)  :- complement(F,L,M), effect(A,L,N1), effect(A,M,N2),
+                  #false : condition(A,M,N1), condition(A,L,N2), complement(L,M).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% NP generator %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+1 { occurs(A,T) : action(A) } 1 :- time(T).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% co-NP check %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% initial state
+
+{ holds(F,0) } :- complement(F,L,M), not initially(L), not initially(M).
+  holds(F,0)   :- initially(L), complement(F,L,M).
+
+holds_oneof(N,B)  :- 
+    initially_oneof(N,_,B);
+    not holds(F,0) : initially_oneof(N,M,B), complement(F,L,M);
+        holds(F,0) : initially_oneof(N,L,B), complement(F,L,M).
+
+ :- initially_oneof(N,_,_), not 1 { holds_oneof(N,B) } 1.
+ :- not holds(F,0), initially_oneof(N,M,B), not holds_oneof(N,B), complement(F,L,M).
+ :-     holds(F,0), initially_oneof(N,L,B), not holds_oneof(N,B), complement(F,L,M).
+
+% planning
+
+fail :- occurs(A,T), executable(A,L), not holds(F,T-1), complement(F,L,M).
+fail :- occurs(A,T), executable(A,M),     holds(F,T-1), complement(F,L,M).
+
+holds(L,T) :- occurs(A,T), effect(A,L,N), holds(C,T-1) : condition(A,C,N).
+holds(L,T) :- time(T), holds(L,T-1), complement(L,M), not holds(M,T).
+fail :- contradict(F), complement(F,L,M), holds(L,T), holds(M,T).
+
+caused(L,T) :- 
+    occurs(A,T), effect(A,L,N), 
+    not holds(F',T-1) : condition(A,M',N), complement(F',L',M');
+        holds(F',T-1) : condition(A,L',N), complement(F',L',M').
+holds(F,T) :- caused(L,T), complement(F,L,M).
+holds(F,T) :- time(T), holds(F,T-1), complement(F,L,M), not caused(M,T).
+fail :- caused((L),T), caused((M),T), contradict(F), complement(F,L,M).
+
+% goal
+
+fail :- goal(L), not holds(F,horizon), complement(F,L,M).
+fail :- goal(M),     holds(F,horizon), complement(F,L,M).
+
+%%%%%%%%%%%%%%%%%%%%%%%%% subset minimization + query %%%%%%%%%%%%%%%%%%%%%%%%%
+
+_query :- not fail.
+
+_criteria(0,1,query) :- _query.
+_criteria(0,1,occurs(A,T)) :- occurs(A,T).
+
+_optimize(0,1,incl).
+
+#show occurs/2.
+#show _criteria/3.
+#show _optimize/3.
+#show _query/0.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% instance %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+fluent(cpa_at(cpa_f1, cpa_p1)).
+fluent(cpa_inside(cpa_e1)).
+fluent(cpa_at(cpa_f1, cpa_p0)).
+fluent(cpa_have(cpa_c0)).
+fluent(cpa_have(cpa_c1)).
+fluent(cpa_at(cpa_f0, cpa_p1)).
+fluent(cpa_inside(cpa_e0)).
+fluent(cpa_at(cpa_f0, cpa_p0)).
+fluent(cpa_in(cpa_e0, cpa_f0)).
+fluent(cpa_in(cpa_e0, cpa_f1)).
+fluent(cpa_in(cpa_e1, cpa_f0)).
+fluent(cpa_in(cpa_e1, cpa_f1)).
+fluent(cpa_coin_at(cpa_c0, cpa_f1, cpa_p0)).
+fluent(cpa_coin_at(cpa_c0, cpa_f1, cpa_p1)).
+fluent(cpa_coin_at(cpa_c1, cpa_f1, cpa_p0)).
+fluent(cpa_coin_at(cpa_c1, cpa_f1, cpa_p1)).
+
+%% actions ------ 
+
+action(cpa_collect(cpa_c0, cpa_f0, cpa_p0)).
+action(cpa_collect(cpa_c0, cpa_f0, cpa_p1)).
+action(cpa_collect(cpa_c0, cpa_f1, cpa_p0)).
+action(cpa_collect(cpa_c0, cpa_f1, cpa_p1)).
+action(cpa_collect(cpa_c1, cpa_f0, cpa_p0)).
+action(cpa_collect(cpa_c1, cpa_f0, cpa_p1)).
+action(cpa_collect(cpa_c1, cpa_f1, cpa_p0)).
+action(cpa_collect(cpa_c1, cpa_f1, cpa_p1)).
+action(cpa_go_down(cpa_e0, cpa_f1, cpa_f0)).
+action(cpa_go_down(cpa_e1, cpa_f1, cpa_f0)).
+action(cpa_go_up(cpa_e0, cpa_f0, cpa_f1)).
+action(cpa_go_up(cpa_e1, cpa_f0, cpa_f1)).
+action(cpa_move_left(cpa_f0, cpa_p1, cpa_p0)).
+action(cpa_move_left(cpa_f1, cpa_p1, cpa_p0)).
+action(cpa_move_right(cpa_f0, cpa_p0, cpa_p1)).
+action(cpa_move_right(cpa_f1, cpa_p0, cpa_p1)).
+action(cpa_step_in(cpa_e0, cpa_f0, cpa_p0)).
+action(cpa_step_in(cpa_e0, cpa_f1, cpa_p0)).
+action(cpa_step_in(cpa_e1, cpa_f0, cpa_p1)).
+action(cpa_step_in(cpa_e1, cpa_f1, cpa_p1)).
+action(cpa_step_out(cpa_e0, cpa_f0, cpa_p0)).
+action(cpa_step_out(cpa_e0, cpa_f1, cpa_p0)).
+action(cpa_step_out(cpa_e1, cpa_f0, cpa_p1)).
+action(cpa_step_out(cpa_e1, cpa_f1, cpa_p1)).
+
+%% executable ------ 
+
+executable(cpa_collect(cpa_c0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_collect(cpa_c0, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_collect(cpa_c1, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_collect(cpa_c1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0)).
+executable(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0)).
+executable(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1)).
+executable(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1)).
+executable(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_inside(cpa_e0)).
+executable(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_inside(cpa_e0)).
+executable(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_inside(cpa_e1)).
+executable(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_inside(cpa_e1)).
+
+%% effects ------ 
+
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_have(cpa_c0),1).
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p0),neg(cpa_coin_at(cpa_c0, cpa_f1, cpa_p0)),1).
+condition(cpa_collect(cpa_c0, cpa_f1, cpa_p0),cpa_coin_at(cpa_c0, cpa_f1, cpa_p0),1).
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_have(cpa_c0),1).
+effect(cpa_collect(cpa_c0, cpa_f1, cpa_p1),neg(cpa_coin_at(cpa_c0, cpa_f1, cpa_p1)),1).
+condition(cpa_collect(cpa_c0, cpa_f1, cpa_p1),cpa_coin_at(cpa_c0, cpa_f1, cpa_p1),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_have(cpa_c1),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p0),neg(cpa_coin_at(cpa_c1, cpa_f1, cpa_p0)),1).
+condition(cpa_collect(cpa_c1, cpa_f1, cpa_p0),cpa_coin_at(cpa_c1, cpa_f1, cpa_p0),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_have(cpa_c1),1).
+effect(cpa_collect(cpa_c1, cpa_f1, cpa_p1),neg(cpa_coin_at(cpa_c1, cpa_f1, cpa_p1)),1).
+condition(cpa_collect(cpa_c1, cpa_f1, cpa_p1),cpa_coin_at(cpa_c1, cpa_f1, cpa_p1),1).
+effect(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),neg(cpa_in(cpa_e0, cpa_f1)),1).
+condition(cpa_go_down(cpa_e0, cpa_f1, cpa_f0),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),neg(cpa_in(cpa_e1, cpa_f1)),1).
+condition(cpa_go_down(cpa_e1, cpa_f1, cpa_f0),cpa_in(cpa_e1, cpa_f1),1).
+effect(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),neg(cpa_in(cpa_e0, cpa_f0)),1).
+condition(cpa_go_up(cpa_e0, cpa_f0, cpa_f1),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),cpa_in(cpa_e1, cpa_f1),1).
+effect(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),neg(cpa_in(cpa_e1, cpa_f0)),1).
+condition(cpa_go_up(cpa_e1, cpa_f0, cpa_f1),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),neg(cpa_at(cpa_f0, cpa_p1)),1).
+effect(cpa_move_left(cpa_f0, cpa_p1, cpa_p0),cpa_at(cpa_f0, cpa_p0),1).
+effect(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),neg(cpa_at(cpa_f1, cpa_p1)),1).
+effect(cpa_move_left(cpa_f1, cpa_p1, cpa_p0),cpa_at(cpa_f1, cpa_p0),1).
+effect(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),neg(cpa_at(cpa_f0, cpa_p0)),1).
+effect(cpa_move_right(cpa_f0, cpa_p0, cpa_p1),cpa_at(cpa_f0, cpa_p1),1).
+effect(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),neg(cpa_at(cpa_f1, cpa_p0)),1).
+effect(cpa_move_right(cpa_f1, cpa_p0, cpa_p1),cpa_at(cpa_f1, cpa_p1),1).
+effect(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_inside(cpa_e0),1).
+effect(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),neg(cpa_at(cpa_f0, cpa_p0)),1).
+condition(cpa_step_in(cpa_e0, cpa_f0, cpa_p0),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_inside(cpa_e0),1).
+effect(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),neg(cpa_at(cpa_f1, cpa_p0)),1).
+condition(cpa_step_in(cpa_e0, cpa_f1, cpa_p0),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_inside(cpa_e1),1).
+effect(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),neg(cpa_at(cpa_f0, cpa_p1)),1).
+condition(cpa_step_in(cpa_e1, cpa_f0, cpa_p1),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_inside(cpa_e1),1).
+effect(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),neg(cpa_at(cpa_f1, cpa_p1)),1).
+condition(cpa_step_in(cpa_e1, cpa_f1, cpa_p1),cpa_in(cpa_e1, cpa_f1),1).
+effect(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_at(cpa_f0, cpa_p0),1).
+effect(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),neg(cpa_inside(cpa_e0)),1).
+condition(cpa_step_out(cpa_e0, cpa_f0, cpa_p0),cpa_in(cpa_e0, cpa_f0),1).
+effect(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_at(cpa_f1, cpa_p0),1).
+effect(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),neg(cpa_inside(cpa_e0)),1).
+condition(cpa_step_out(cpa_e0, cpa_f1, cpa_p0),cpa_in(cpa_e0, cpa_f1),1).
+effect(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_at(cpa_f0, cpa_p1),1).
+effect(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),neg(cpa_inside(cpa_e1)),1).
+condition(cpa_step_out(cpa_e1, cpa_f0, cpa_p1),cpa_in(cpa_e1, cpa_f0),1).
+effect(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_at(cpa_f1, cpa_p1),1).
+effect(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),neg(cpa_inside(cpa_e1)),1).
+condition(cpa_step_out(cpa_e1, cpa_f1, cpa_p1),cpa_in(cpa_e1, cpa_f1),1).
+
+%% initial state ------ 
+
+initially(cpa_at(cpa_f0, cpa_p0)).
+initially(neg(cpa_at(cpa_f0, cpa_p1))).
+initially(neg(cpa_at(cpa_f1, cpa_p0))).
+initially(neg(cpa_at(cpa_f1, cpa_p1))).
+initially(neg(cpa_inside(cpa_e0))).
+initially(neg(cpa_inside(cpa_e1))).
+initially(neg(cpa_have(cpa_c0))).
+initially(neg(cpa_have(cpa_c1))).
+initially_oneof(1,cpa_in(cpa_e0, cpa_f0),1).
+initially_oneof(1,cpa_in(cpa_e0, cpa_f1),2).
+initially_oneof(2,cpa_in(cpa_e1, cpa_f0),1).
+initially_oneof(2,cpa_in(cpa_e1, cpa_f1),2).
+initially_oneof(3,cpa_coin_at(cpa_c0, cpa_f1, cpa_p0),1).
+initially_oneof(3,cpa_coin_at(cpa_c1, cpa_f1, cpa_p0),1).
+initially_oneof(3,cpa_coin_at(cpa_c0, cpa_f1, cpa_p1),2).
+initially_oneof(3,cpa_coin_at(cpa_c1, cpa_f1, cpa_p1),2).
+
+%% goal state ---------- 
+
+goal(cpa_have(cpa_c0)).
+goal(cpa_have(cpa_c1)).
+
diff --git a/examples/reify/meta.lp b/examples/reify/meta.lp
new file mode 100644
index 0000000..09bf846
--- /dev/null
+++ b/examples/reify/meta.lp
@@ -0,0 +1,39 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% This file is part of clingo.                                            %
+%                                                                         %
+% Authors: Martin Gebser, Roland Kaminski, Torsten Schaub                 %
+%                                                                         %
+% This program is free software: you can redistribute it and/or modify    %
+% it under the terms of the GNU General Public License as published by    %
+% the Free Software Foundation, either version 3 of the License, or       %
+% (at your option) any later version.                                     %
+%                                                                         %
+% This program is distributed in the hope that it will be useful,         %
+% but WITHOUT ANY WARRANTY; without even the implied warranty of          %
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           %
+% GNU General Public License for more details.                            %
+%                                                                         %
+% You should have received a copy of the GNU General Public License       %
+% along with this program.  If not, see .   %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+conjunction(B) :- literal_tuple(B),
+        hold(L) : literal_tuple(B, L), L > 0;
+    not hold(L) : literal_tuple(B,-L), L > 0.
+
+body(normal(B)) :- rule(_,normal(B)), conjunction(B).
+body(sum(B,G))  :- rule(_,sum(B,G)),
+    #sum { W,L :     hold(L), weighted_literal_tuple(B, L,W), L > 0 ;
+           W,L : not hold(L), weighted_literal_tuple(B,-L,W), L > 0 } >= G.
+
+  hold(A) : atom_tuple(H,A)   :- rule(disjunction(H),B), body(B).
+{ hold(A) : atom_tuple(H,A) } :- rule(     choice(H),B), body(B).
+
+optimize(J,W,Q) :- output(_optimize(J,W,Q),B), conjunction(B).
+ :- output(_query,B), not conjunction(B).
+
+hide(_criteria(J,W,Q)) :- output(_criteria(J,W,Q),_).
+hide(_query)           :- output(_query,_).
+hide(_optimize(J,W,Q)) :- output(_optimize(J,W,Q),_).
+#show.
+#show T : output(T,B), conjunction(B), not hide(T).
diff --git a/examples/reify/metaD.lp b/examples/reify/metaD.lp
new file mode 100644
index 0000000..e7975a8
--- /dev/null
+++ b/examples/reify/metaD.lp
@@ -0,0 +1,85 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% This file is part of clingo.                                            %
+%                                                                         %
+% Authors: Martin Gebser, Roland Kaminski, Torsten Schaub                 %
+%                                                                         %
+% This program is free software: you can redistribute it and/or modify    %
+% it under the terms of the GNU General Public License as published by    %
+% the Free Software Foundation, either version 3 of the License, or       %
+% (at your option) any later version.                                     %
+%                                                                         %
+% This program is distributed in the hope that it will be useful,         %
+% but WITHOUT ANY WARRANTY; without even the implied warranty of          %
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           %
+% GNU General Public License for more details.                            %
+%                                                                         %
+% You should have received a copy of the GNU General Public License       %
+% along with this program.  If not, see .   %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% NOTE: assumes that a rule has no more than one head
+
+sum(B,G,T) :- rule(_,sum(B,G)), T = #sum { W,L : weighted_literal_tuple(B,L,W) }.
+
+% extract supports of atoms and facts
+
+supp(A,B) :- rule(     choice(H),B), atom_tuple(H,A).
+supp(A,B) :- rule(disjunction(H),B), atom_tuple(H,A).
+
+supp(A) :- supp(A,_).
+
+atom(|L|) :- weighted_literal_tuple(_,L,_).
+atom(|L|) :- literal_tuple(_,L).
+atom( A ) :- atom_tuple(_,A).
+
+fact(A) :- rule(disjunction(H),normal(B)), atom_tuple(H,A), not literal_tuple(B,_).
+
+% generate interpretation
+
+true(atom(A))                :- fact(A).
+true(atom(A)); fail(atom(A)) :- supp(A), not fact(A).
+               fail(atom(A)) :- atom(A), not supp(A).
+
+true(normal(B)) :- literal_tuple(B),
+    true(atom(L)) : literal_tuple(B, L), L > 0;
+    fail(atom(L)) : literal_tuple(B,-L), L > 0.
+fail(normal(B)) :- literal_tuple(B, L), fail(atom(L)), L > 0.
+fail(normal(B)) :- literal_tuple(B,-L), true(atom(L)), L > 0.
+
+true(sum(B,G)) :- sum(B,G,T),
+    #sum { W,L : true(atom(L)), weighted_literal_tuple(B, L,W), L > 0 ;
+           W,L : fail(atom(L)), weighted_literal_tuple(B,-L,W), L > 0 } >= G.
+fail(sum(B,G)) :- sum(B,G,T),
+    #sum { W,L : fail(atom(L)), weighted_literal_tuple(B, L,W), L > 0 ;
+           W,L : true(atom(L)), weighted_literal_tuple(B,-L,W), L > 0 } >= T-G+1.
+
+% verify supported model properties
+
+bot :- rule(disjunction(H),B), true(B), fail(atom(A)) : atom_tuple(H,A).
+bot :- true(atom(A)), fail(B) : supp(A,B).
+
+% verify acyclic derivability
+
+internal(C,normal(B)) :- scc(C,A), supp(A,normal(B)), scc(C,A'), literal_tuple(B,A').
+internal(C,sum(B,G))  :- scc(C,A), supp(A,sum(B,G)),  scc(C,A'), weighted_literal_tuple(B,A',W).
+
+external(C,normal(B)) :- scc(C,A), supp(A,normal(B)), not internal(C,normal(B)).
+external(C,sum(B,G))  :- scc(C,A), supp(A,sum(B,G)),  not internal(C,sum(B,G)).
+
+steps(C,Z) :- scc(C,_), Z = { scc(C,A) : not fact(A) }.
+
+wait(C,atom(A),0)   :- scc(C,A), fail(B) : external(C,B).
+wait(C,normal(B),I) :- internal(C,normal(B)), literal_tuple(B,A), wait(C,atom(A),I), steps(C,Z), I < Z.
+wait(C,sum(B,G),I)  :- internal(C,sum(B,G)), steps(C,Z), I = 0..Z-1, sum(B,G,T),
+    #sum { W,L :   fail(atom(L)),   weighted_literal_tuple(B, L,W), L > 0, not scc(C,L) ;
+           W,L : wait(C,atom(L),I), weighted_literal_tuple(B, L,W), L > 0,     scc(C,L) ;
+           W,L :   true(atom(L)),   weighted_literal_tuple(B,-L,W), L > 0               } >= T-G+1.
+wait(C,atom(A),I)   :- wait(C,atom(A),0), steps(C,Z), I = 1..Z, wait(C,B,I-1) : supp(A,B), internal(C,B).
+
+bot :- scc(C,A), true(atom(A)), wait(C,atom(A),Z), steps(C,Z).
+
+% saturate interpretations that are not answer sets
+
+true(atom(A)) :- supp(A), not fact(A), bot.
+fail(atom(A)) :- supp(A), not fact(A), bot.
+
diff --git a/examples/reify/metaO.lp b/examples/reify/metaO.lp
new file mode 100644
index 0000000..82aff2c
--- /dev/null
+++ b/examples/reify/metaO.lp
@@ -0,0 +1,79 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% This file is part of clingo.                                             %
+%                                                                         %
+% Authors: Martin Gebser, Roland Kaminski, Torsten Schaub                 %
+%                                                                         %
+% This program is free software: you can redistribute it and/or modify    %
+% it under the terms of the GNU General Public License as published by    %
+% the Free Software Foundation, either version 3 of the License, or       %
+% (at your option) any later version.                                     %
+%                                                                         %
+% This program is distributed in the hope that it will be useful,         %
+% but WITHOUT ANY WARRANTY; without even the implied warranty of          %
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           %
+% GNU General Public License for more details.                            %
+%                                                                         %
+% You should have received a copy of the GNU General Public License       %
+% along with this program.  If not, see .   %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+cxopt(card).  cxopt(incl).  cxopt(pref).
+
+criteria(J,W,Q,A) :- output(_criteria(J,W,Q),A).
+criteria(J,W,A) :- criteria(J,W,Q,A).
+
+cxopt(J,W,O)    :- criteria(J,W,_,_), cxopt(O), optimize(J,W,O).
+cxopt(J,W,card) :- criteria(J,W,_,_), #false : optimize(J,W,O).
+
+%%%%%%%%%% verify dominance
+
+equal(J) :- cxopt(J,_,_), equal(J,W,O) : cxopt(J,W,O).
+
+chain(J1,J2) :- cxopt(J1,_,_), cxopt(J2,_,_), J2 < J1,
+                #false : cxopt(J3,W,O), J2 < J3, J3 < J1.
+
+check(J2) :- cxopt(J2,_,_), #false : chain(J1,J2).
+check(J2) :- chain(J1,J2), check(J1), equal(J1).
+
+bot :- #false : cxopt(J,W,O).
+bot :- check(J1), worse(J1).
+bot :- check(J1), equal(J1), #false : chain(J1,J2).
+
+% require non-existence of dominating answer set
+
+:- not bot.
+
+%%%%%%%%%% check cardinality criteria
+
+equal(J,W,card) :- cxopt(J,W,card), #sum { -1,Q : not not conjunction(A),  criteria(J,W,Q,A) ;
+                                            1,Q :         true(normal(A)), criteria(J,W,Q,A) } >= 0.
+worse(J)        :- cxopt(J,W,card), #sum { -1,Q : not not conjunction(A),  criteria(J,W,Q,A) ;
+                                            1,Q :         true(normal(A)), criteria(J,W,Q,A) } >= 1.
+%%%%%%%%%% check inclusion criteria
+
+ndiff(A) :- cxopt(J,W,incl), criteria(J,W,A), true(normal(A)).
+ndiff(A) :- cxopt(J,W,incl), criteria(J,W,A), not conjunction(A).
+
+equal(J,W,incl) :- cxopt(J,W,incl), ndiff(A) : criteria(J,W,A).
+worse(J)        :- cxopt(J,W,incl), criteria(J,W,A), true(normal(A)), not conjunction(A).
+
+%%%%%%%%%% check preference criteria (relative to user predicate prefer/2)
+
+cando(A) :- cxopt(J,W,pref), criteria(J,W,A), fail(normal(A)),     conjunction(A).
+nocan(A) :- cxopt(J,W,pref), criteria(J,W,A), true(normal(A)).
+nocan(A) :- cxopt(J,W,pref), criteria(J,W,A), not conjunction(A).
+
+condo(A) :- cxopt(J,W,pref), criteria(J,W,A), true(normal(A)), not conjunction(A).
+nocon(A) :- cxopt(J,W,pref), criteria(J,W,A), fail(normal(A)).
+nocon(A) :- cxopt(J,W,pref), criteria(J,W,A),     conjunction(A).
+
+cando(J,W,A)    :- cxopt(J,W,pref), criteria(J,W,A), criteria(J,W,A'), prefer(A,A'), A != A', cando(A), condo(A').
+
+nocon(J,W,A)    :- cxopt(J,W,pref), criteria(J,W,A), nocon(A).
+nocon(J,W,A)    :- cxopt(J,W,pref), criteria(J,W,A), nocan(A') : criteria(J,W,A'), A != A', prefer(A,A').
+nocon(J,W,A)    :- cxopt(J,W,pref), criteria(J,W,A), criteria(J,W,A'), prefer(A',A), not prefer(A,A'), cando(A').
+
+equal(J,W,pref) :- cxopt(J,W,pref), criteria(J,W,A), cando(J,W,A), nocon(A') : criteria(J,W,A'), prefer(A',A), not prefer(A,A').
+
+worse(J)        :- cxopt(J,W,pref), nocon(J,W,A) : criteria(J,W,A).
+
diff --git a/examples/test.sh b/examples/test.sh
new file mode 100755
index 0000000..b063691
--- /dev/null
+++ b/examples/test.sh
@@ -0,0 +1,129 @@
+#!/bin/bash
+function check() {
+    f="$1"
+    shift
+    cat <
+#include 
+namespace Clasp { namespace Asp {
+
+/**
+ * \addtogroup asp
+ */
+//@{
+
+//! Preprocesses (i.e. simplifies) a logic program.
+/*!
+ * Preprocesses (i.e. simplifies) a logic program and associates variables with
+ * the nodes of the simplified logic program.
+ */
+class Preprocessor {
+public:
+	Preprocessor() : prg_(0), dfs_(true) {}
+	//! Possible eq-preprocessing types.
+	enum EqType {
+		no_eq,    //!< No eq-preprocessing, associate a new var with each supported atom and body.
+		full_eq   //!< Check for all kinds of equivalences between atoms and bodies.
+	};
+
+	const LogicProgram* program() const  { return prg_; }
+	      LogicProgram* program()        { return prg_; }
+
+	//! Starts preprocessing of the logic program.
+	/*!
+	 * Computes the maximum consequences of prg and associates a variable
+	 * with each supported atom and body.
+	 * \param prg The logic program to preprocess.
+	 * \param t   Type of eq-preprocessing.
+	 * \param maxIters If t == full_eq, maximal number of iterations during eq preprocessing.
+	 * \param dfs If t == full_eq, classify in df-order (true) or bf-order (false).
+	 */
+	bool preprocess(LogicProgram& prg, EqType t, uint32 maxIters, bool dfs = true) {
+		prg_  = &prg;
+		dfs_  = dfs;
+		type_ = t;
+		return t == full_eq
+			? preprocessEq(maxIters)
+			: preprocessSimple();
+	}
+
+	bool eq() const { return type_ == full_eq; }
+	Var  getRootAtom(Literal p) const { return p.id() < litToNode_.size() ? litToNode_[p.id()] : varMax; }
+	void setRootAtom(Literal p, uint32 atomId) {
+		if (p.id() >= litToNode_.size()) litToNode_.resize(p.id()+1, varMax);
+		litToNode_[p.id()] = atomId;
+	}
+private:
+	Preprocessor(const Preprocessor&);
+	Preprocessor& operator=(const Preprocessor&);
+	bool    preprocessEq(uint32 maxIters);
+	bool    preprocessSimple();
+	// ------------------------------------------------------------------------
+	typedef PrgHead* const *             HeadIter;
+	typedef std::pair HeadRange;
+	// Eq-Preprocessing
+	struct BodyExtra {
+		BodyExtra() : known(0), mBody(0), bSeen(0) {}
+		uint32 known  :30;  // Number of predecessors already classified, only used for bodies
+		uint32 mBody  : 1;  // A flag for marking bodies
+		uint32 bSeen  : 1;  // First time we see this body?
+	};
+	bool     classifyProgram(const VarVec& supportedBodies);
+	ValueRep simplifyClassifiedProgram(const HeadRange& atoms, bool more, VarVec& supported);
+	PrgBody* addBodyVar(uint32 bodyId);
+	bool     addHeadsToUpper(PrgBody* body);
+	bool     addHeadToUpper(PrgHead* head, PrgEdge support);
+	bool     propagateAtomVar(PrgAtom*, PrgEdge source);
+	bool     propagateAtomValue(PrgAtom*, ValueRep val, PrgEdge source);
+	bool     mergeEqBodies(PrgBody* b, Var rootId, bool equalLits);
+	bool     hasRootLiteral(PrgBody* b) const;
+	bool     superfluous(PrgBody* b) const;
+	ValueRep simplifyHead(PrgHead* h, bool reclassify);
+	ValueRep simplifyBody(PrgBody* b, bool reclassify, VarVec& supported);
+	uint32   nextBodyId(VarVec::size_type& idx) {
+		if (follow_.empty() || idx == follow_.size()) { return varMax; }
+		if (dfs_) {
+			uint32 id = follow_.back();
+			follow_.pop_back();
+			return id;
+		}
+		return follow_[idx++];;
+	}
+	// ------------------------------------------------------------------------
+	typedef PodVector::type BodyData;
+	LogicProgram* prg_;      // program to preprocess
+	VarVec        follow_;   // bodies yet to classify
+	BodyData      bodyInfo_; // information about the program nodes
+	VarVec        litToNode_;// the roots of our equivalence classes
+	uint32        pass_;     // current iteration number
+	uint32        maxPass_;  // force stop after maxPass_ iterations
+	EqType        type_;     // type of eq-preprocessing
+	bool          dfs_;      // classify bodies in DF or BF order
+};
+//@}
+} }
+#endif
+
diff --git a/libclasp/clasp/cb_enumerator.h b/libclasp/clasp/cb_enumerator.h
new file mode 100644
index 0000000..8ac97c0
--- /dev/null
+++ b/libclasp/clasp/cb_enumerator.h
@@ -0,0 +1,66 @@
+//
+// Copyright (c) 2006-2011, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#ifndef CLASP_CB_ENUMERATOR_H
+#define CLASP_CB_ENUMERATOR_H
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include 
+
+namespace Clasp {
+
+//! Enumerator for computing the brave/cautious consequences of a logic program.
+/*!
+ * \ingroup enumerator
+ */
+class CBConsequences : public Enumerator {
+public:
+	enum Type {
+		Brave    = Model::Brave,
+		Cautious = Model::Cautious,
+	};
+	enum Algo { Default, Query };
+	/*!
+	 * \param type Type of consequences to compute.
+	 * \param a Type of algorithm to apply if type is Cautious.
+	 */
+	explicit CBConsequences(Type type, Algo a = Default);
+	~CBConsequences();
+	int  modelType() const { return type_; }
+	bool exhaustive()const { return true; }
+	bool supportsSplitting(const SharedContext& problem) const;
+	int  unsatType() const;
+private:
+	class  CBFinder;
+	class  QueryFinder;
+	class  SharedConstraint;
+	ConPtr doInit(SharedContext& ctx, SharedMinimizeData* m, int numModels);
+	void   addLit(SharedContext& ctx, Literal p);
+	void   addCurrent(Solver& s, LitVec& con, ValueVec& m, uint32 rootL = 0);
+	LitVec            cons_;
+	SharedConstraint* shared_;
+	Type              type_;
+	Algo              algo_;
+};
+
+}
+#endif
diff --git a/libclasp/clasp/clasp_facade.h b/libclasp/clasp/clasp_facade.h
new file mode 100644
index 0000000..281e6b7
--- /dev/null
+++ b/libclasp/clasp/clasp_facade.h
@@ -0,0 +1,490 @@
+//
+// Copyright (c) 2006-2016, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#ifndef CLASP_CLASP_FACADE_H_INCLUDED
+#define CLASP_CLASP_FACADE_H_INCLUDED
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#if !defined(CLASP_VERSION)
+#define CLASP_VERSION "3.2.1"
+#endif
+#if !defined(CLASP_LEGAL)
+#define CLASP_LEGAL \
+"Copyright (C) Benjamin Kaufmann\n"\
+"License GPLv2+: GNU GPL version 2 or later \n"\
+"clasp is free software: you are free to change and redistribute it.\n"\
+"There is NO WARRANTY, to the extent permitted by law."
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if WITH_THREADS
+#include 
+namespace Clasp {
+	//! Options for controlling enumeration and solving.
+	struct SolveOptions : Clasp::mt::ParallelSolveOptions, EnumOptions {};
+}
+#else
+#include 
+#include 
+namespace Clasp {
+	struct SolveOptions : Clasp::BasicSolveOptions, EnumOptions {};
+}
+#endif
+
+/*!
+ * \file
+ * \brief High-level API
+ *
+ * This file provides a facade around the clasp library.
+ * I.e. a simplified interface for (multishot) solving a problem using
+ * some configuration (set of parameters).
+ * \ingroup facade
+ */
+namespace Clasp {
+/////////////////////////////////////////////////////////////////////////////////////////
+// Configuration
+/////////////////////////////////////////////////////////////////////////////////////////
+/*!
+ * \defgroup facade Facade
+ * \brief Simplified interface for (multishot) solving.
+ *
+ * @{
+ */
+//! Configuration object for configuring solving via the ClaspFacade.
+class ClaspConfig : public BasicSatConfig {
+public:
+	//! Interface for injecting user-provided post propagators.
+	class Configurator {
+	public:
+		virtual ~Configurator();
+		virtual void prepare(SharedContext&);
+		virtual bool addPost(Solver& s) = 0;
+	};
+	typedef BasicSatConfig UserConfig;
+	typedef Solver**       SolverIt;
+	typedef Asp::LogicProgram::AspOptions AspOptions;
+	ClaspConfig();
+	~ClaspConfig();
+	// Base interface
+	void           prepare(SharedContext&);
+	void           reset();
+	Configuration* config(const char*);
+	//! Adds an unfounded set checker to the given solver if necessary.
+	/*!
+	 * If asp.suppMod is false and the problem in s is a non-tight asp-problem,
+	 * the function adds an unfounded set checker to s.
+	 */
+	bool           addPost(Solver& s) const;
+	// own interface
+	UserConfig*    testerConfig() const { return tester_; }
+	UserConfig*    addTesterConfig();
+	//! Registers c as additional callback for when addPost() is called.
+	/*!
+	 * \param c         Additional configuration to apply.
+	 * \param ownership If Ownership_t::Acquire, ownership of c is transferred to the configuration object.
+	 * \param once      Whether c should be called once in the first step or also in each subsequent step.
+	 */
+	void           addConfigurator(Configurator* c, Ownership_t::Type ownership = Ownership_t::Retain, bool once = true);
+	SolveOptions   solve; /*!< Options for solve algorithm and enumerator. */
+	AspOptions     asp;   /*!< Options for asp preprocessing.      */
+	ParserOptions  parse; /*!< Options for input parser. */
+private:
+	struct Impl;
+	ClaspConfig(const ClaspConfig&);
+	ClaspConfig& operator=(const ClaspConfig&);
+	UserConfig* tester_;
+	Impl*       impl_;
+};
+/////////////////////////////////////////////////////////////////////////////////////////
+// ClaspFacade
+/////////////////////////////////////////////////////////////////////////////////////////
+//! Result of a solving step.
+struct SolveResult {
+	//! Possible solving results.
+	enum Base {
+		UNKNOWN  = 0, //!< Satisfiability unknown - a given solve limit was hit.
+		SAT      = 1, //!< Problem is satisfiable (a model was found).
+		UNSAT    = 2, //!< Problem is unsatisfiable.
+	};
+	//! Additional flags applicable to a solve result.
+	enum Ext {
+		EXT_EXHAUST  = 4, //!< Search space is exhausted.
+		EXT_INTERRUPT= 8, //!< The run was interrupted from outside.
+	};
+	bool sat()        const { return *this == SAT; }
+	bool unsat()      const { return *this == UNSAT; }
+	bool unknown()    const { return *this == UNKNOWN; }
+	bool exhausted()  const { return (flags & EXT_EXHAUST)   != 0; }
+	bool interrupted()const { return (flags & EXT_INTERRUPT) != 0; }
+	operator Base()   const { return static_cast(flags & 3u);}
+	operator double() const { return (double(signal)*256.0) + flags; }
+	uint8 flags;  //!< Set of Base and Ext flags.
+	uint8 signal; //!< Term signal or 0.
+};
+
+//! Provides a simplified interface to the services of the clasp library.
+class ClaspFacade : public ModelHandler {
+	struct SolveData;
+	struct SolveStrategy;
+public:
+	typedef SolveResult Result;
+	typedef Potassco::AbstractStatistics AbstractStatistics;
+	//! Type summarizing one or more solving steps.
+	struct Summary {
+		typedef const ClaspFacade* FacadePtr;
+		void init(ClaspFacade& f);
+		//! Logic program elements added in the current step or 0 if not an asp problem.
+		const Asp::LpStats*  lpStep()       const;
+		//! Logic program stats or 0 if not an asp problem.
+		const Asp::LpStats*  lpStats()      const;
+		//! Active problem.
+		const SharedContext& ctx()          const { return facade->ctx; }
+		/*!
+		 * \name Result functions
+		 * Solve and enumeration result - not accumulated.
+		 * @{
+		 */
+		bool                 sat()          const { return result.sat(); }
+		bool                 unsat()        const { return result.unsat(); }
+		bool                 complete()     const { return result.exhausted(); }
+		bool                 optimum()      const { return costs() && (complete() || model()->opt); }
+		const Model*         model()        const;
+		const char*          consequences() const; /**< Cautious/brave reasoning active? */
+		bool                 optimize()     const; /**< Optimization active? */
+		const SumVec*        costs()        const; /**< Models have associated costs? */
+		uint64               optimal()      const; /**< Number of optimal models found. */
+		bool                 hasLower()     const;
+		SumVec               lower()        const;
+		//@}
+		//! Visits this summary object.
+		void accept(StatsVisitor& out) const;
+		FacadePtr facade;    //!< Facade object of this run.
+		double    totalTime; //!< Total wall clock time.
+		double    cpuTime;   //!< Total cpu time.
+		double    solveTime; //!< Wall clock time for solving.
+		double    unsatTime; //!< Wall clock time to prove unsat.
+		double    satTime;   //!< Wall clock time to first model.
+		uint64    numEnum;   //!< Total models enumerated.
+		uint64    numOptimal;//!< Optimal models enumerated.
+		uint32    step;      //!< Step number (multishot solving).
+		Result    result;    //!< Result of step.
+	};
+	ClaspFacade();
+	~ClaspFacade();
+
+	/*!
+	 * \name Query functions
+	 * Functions for checking the state of this object.
+	 * @{ */
+	//! Returns whether the problem is still valid.
+	bool               ok()                  const { return program() ? program()->ok() : ctx.ok(); }
+	//! Returns whether the active step is ready for solving.
+	bool               prepared()            const;
+	//! Returns whether the active step is currently being solved.
+	bool               solving()             const;
+	//! Returns whether the active step has been solved, i.e., has a result.
+	bool               solved()              const;
+	//! Returns whether solving of the active step was interrupted.
+	bool               interrupted()         const;
+	//! Returns the summary of the active step.
+	const Summary&     summary()             const { return step_; }
+	//! Returns the summary of the active (accu = false) or all steps.
+	const Summary&     summary(bool accu)    const;
+	//! Returns solving statistics or throws std::logic_error if step is not yet solved.
+	AbstractStatistics*getStats()            const;
+	//! Returns the active configuration.
+	const ClaspConfig* config()              const { return config_;}
+	//! Returns the current solving step (starts at 0).
+	int                step()                const { return (int)step_.step;}
+	//! Returns the result of the active step (unknown if run is not yet completed).
+	Result             result()              const { return step_.result; }
+	//! Returns the active program or 0 if it was already released.
+	ProgramBuilder*    program()             const { return builder_.get(); }
+	//! Returns whether program updates are enabled.
+	bool               incremental()         const;
+	//! Returns the active enumerator or 0 if there is none.
+	Enumerator*        enumerator()          const;
+	//@}
+
+	//! Event type used to signal that a new step has started.
+	struct StepStart : Event_t {
+		explicit StepStart(const ClaspFacade& f) : Event_t(subsystem_facade, verbosity_quiet), facade(&f) {}
+		const ClaspFacade* facade;
+	};
+	//! Event type used to signal that a solve step has terminated.
+	struct StepReady : Event_t {
+		explicit StepReady(const Summary& x) : Event_t(subsystem_facade, verbosity_quiet), summary(&x) {}
+		const Summary* summary;
+	};
+
+	SharedContext ctx; //!< Context-object used to store problem.
+
+	/*!
+	 * \name Start functions
+	 * Functions for defining a problem.
+	 * Calling one of the start functions discards any previous problem
+	 * and emits a StepStart event.
+	 * @{ */
+	//! Starts definition of an ASP-problem.
+	Asp::LogicProgram& startAsp(ClaspConfig& config, bool enableProgramUpdates = false);
+	//! Starts definition of a SAT-problem.
+	SatBuilder&        startSat(ClaspConfig& config);
+	//! Starts definition of a PB-problem.
+	PBBuilder&         startPB(ClaspConfig& config);
+	//! Starts definition of a problem of type t.
+	ProgramBuilder&    start(ClaspConfig& config, ProblemType t);
+	//! Starts definition of a problem given in stream.
+	ProgramBuilder&    start(ClaspConfig& config, std::istream& stream);
+	//! Enables support for program updates if supported by the program.
+	/*!
+	 * \pre program() != 0 and not prepared().
+	 * \return true if program updates are supported. Otherwise, false.
+	 */
+	bool               enableProgramUpdates();
+	//! Enables support for (asynchronous) solve interrupts.
+	void               enableSolveInterrupts();
+	//! Tries to detect the problem type from the given input stream.
+	static ProblemType detectProblemType(std::istream& str);
+	//! Tries to read the next program part from the stream passed to start().
+	/*!
+	 * \return false if nothing was read because the stream is exhausted, solving was interrupted,
+	 * or the problem is unconditionally unsat.
+	 */
+	bool               read();
+	//@}
+
+
+	/*!
+	* \name Solve functions
+	* Functions for solving a problem.
+	* @{ */
+
+	enum EnumMode { enum_volatile, enum_static };
+	//! Finishes the definition of a problem and prepares it for solving.
+	/*!
+	 * \pre !solving()
+	 * \post prepared() || !ok()
+	 * \param m Mode to be used for handling enumeration-related knowledge.
+	 *          If m is enum_volatile, enumeration knowledge is learnt under an
+	 *          assumption that is retracted on program update. Otherwise,
+	 *          no special assumption is used and enumeration-related knowledge
+	 *          might become unretractable.
+	 * \note If solved() is true, prepare() first starts a new solving step.
+	 */
+	void               prepare(EnumMode m = enum_volatile);
+
+	//! Solves the current problem.
+	/*!
+	 * If prepared() is false, the function first calls prepare() to prepare the problem for solving.
+	 * \pre !solving()
+	 * \post solved()
+	 * \param eh An optional event handler that is notified on each model and
+	 *           once the solve operation has completed.
+	 * \param a A list of unit-assumptions under which solving should operate.
+	 */
+	Result             solve(EventHandler* eh = 0, const LitVec& a = LitVec());
+
+	//! A generator for querying models one-by-one.
+	class ModelGenerator {
+	public:
+		explicit ModelGenerator(SolveStrategy& impl);
+		ModelGenerator(const ModelGenerator&);
+		~ModelGenerator();
+		//! Searches for the next model and returns whether one was found.
+		bool         next()   const;
+		//! Returns the last model found.
+		const Model& model()  const;
+		//! Stops the generator so that further calls to next() will return false.
+		void         stop()   const;
+		//! Returns the result of the last call to next().
+		Result       result() const;
+	private:
+		ModelGenerator& operator=(const ModelGenerator&);
+		SolveStrategy* impl_;
+	};
+
+	//! Starts solving of the current problem signaling models via the returned generator object.
+	/*!
+	* Instead of signaling results via a callback, the returned generator object
+	* can be used to query models one by one.
+	* \pre !solving()
+	* \note It is the caller's responsibility to finish the solve operation,
+	* either by extracting models until ModelGenerator::next() returns false, or
+	* by calling ModelGenerator::stop().
+	*/
+	ModelGenerator     startSolve(const LitVec& a = LitVec());
+
+#if WITH_THREADS
+	class  AsyncResult;
+	struct AsyncSolve;
+	//! Asynchronously solves the current problem.
+	/*!
+	 * \see solve(EventHandler* eh, const LitVec&);
+	 * \note The optional event handler is notified in the context of the
+	 *       asynchronous operation.
+	 */
+	AsyncResult        solveAsync(EventHandler* eh = 0, const LitVec& a = LitVec());
+
+	//! Asynchronously solves the current problem signaling models one by one.
+	/*!
+	 * The function behaves similar to solveAsync() but allows to get models
+	 * one by one via the returned result object.
+	 * \pre !solving()
+	 *
+	 * To iterate over models use a loop like:
+	 * \code
+	 * for (AsyncResult it = facade.startSolveAsync(); !it.end(); it.next()) {
+	 *   printModel(it.model());
+	 * }
+	 * \endcode
+	 *
+	 * \note It is the caller's responsibility to finish the solve operation,
+	 * either by extracting models until AsyncResult::end() returns true, or
+	 * by calling AsyncResult::cancel().
+	 */
+	AsyncResult        startSolveAsync(const LitVec& a = LitVec());
+
+	//! A type for accessing the result(s) of an asynchronous solve operation.
+	class AsyncResult {
+	public:
+		typedef  StepReady Ready;
+		typedef const Model& ModelRef;
+		explicit AsyncResult(SolveData& x);
+		~AsyncResult();
+		AsyncResult(const AsyncResult&);
+		AsyncResult& operator=(AsyncResult temp)            { swap(*this, temp); return *this; }
+		friend void swap(AsyncResult& lhs, AsyncResult& rhs){ std::swap(lhs.state_, rhs.state_); }
+		/*!
+		 * \name Blocking operations
+		 */
+		//@{
+		//! Waits until a result is ready and returns it.
+		Result   get()              const;
+		//! Waits until a result is ready.
+		void     wait()             const;
+		//! Waits for a result but for at most sec seconds.
+		bool     waitFor(double sec)const;
+		//! Tries to cancel the active async operation.
+		bool     cancel()           const;
+		//! Waits for a result and returns whether the operation is exhausted.
+		bool     end()              const;
+		//@}
+
+		/*!
+		* \name Non-blocking operations
+		*/
+		//@{
+		//! Tests whether a result is ready.
+		bool     ready()            const;
+		//! Returns the active result in r if it is ready.
+		bool     ready(Result& r)   const;
+		//! Tests whether the asynchronous operation was interrupted and if so returns the interruption signal.
+		int      interrupted()      const;
+		//! Tests whether a result is ready and has a stored exception.
+		bool     error()            const;
+		//! Tests whether the asynchronous operation is still active.
+		bool     running()          const;
+		//! Returns the current model provided that end() is false.
+		ModelRef model()            const;
+		//! Kicks off search for the next result if not end().
+		bool     next()             const;
+	private:
+		AsyncSolve* state_;
+	};
+#endif
+	//! Tries to interrupt the active solve operation.
+	/*!
+	 * The function sends the given signal to the active solve operation.
+	 * If no solve operation is active (i.e. solving() is false), the signal
+	 * is queued and applied to the next solve operation.
+	 *
+	 * \param sig The signal to raise or 0, to re-raises a previously queued signal.
+	 * \return false if no operation was interrupted, because
+	 *         there is no active solve operation,
+	 *         or the operation does not support interrupts,
+	 *         or sig was 0 and there was no queued signal.
+	 *
+	 * \see enableSolveInterrupts()
+	 */
+	bool               interrupt(int sig);
+
+	//! Forces termination of the current solving step.
+	/*!
+	 * \post solved()
+	 * \return summary(true)
+	 */
+	const Summary&     shutdown();
+
+	//! Starts update of the active problem.
+	/*!
+	 * \pre solving() is false and program updates are enabled (incremental() is true).
+	 * \post !solved()
+	 * \param updateConfig If true, the function applies any configuration changes.
+	 * \param sigQ An action to be performed for any queued signal.
+	 *        The default is to apply the signal to the next solve operation, while
+	 *        SIGN_IGN can be used to discard queued signals.
+	 */
+	ProgramBuilder&    update(bool updateConfig, void (*sigQ)(int));
+	ProgramBuilder&    update(bool updateConfig = false);
+	//@}
+private:
+	struct Statistics;
+	typedef SingleOwnerPtr BuilderPtr;
+	typedef SingleOwnerPtr      SolvePtr;
+	typedef SingleOwnerPtr        SummaryPtr;
+	typedef SingleOwnerPtr     StatsPtr;
+	void   init(ClaspConfig& cfg, bool discardProblem);
+	void   initBuilder(ProgramBuilder* in);
+	bool   isAsp() const { return program() && type_ == Problem_t::Asp; }
+	void   discardProblem();
+	void   startStep(uint32 num);
+	Result stopStep(int signal, bool complete);
+	void   updateStats();
+	bool   onModel(const Solver& s, const Model& m);
+	void   doUpdate(ProgramBuilder* p, bool updateConfig, void (*sig)(int));
+	ProblemType  type_;
+	Summary      step_;
+	LitVec       assume_;
+	ClaspConfig* config_;
+	BuilderPtr   builder_;
+	SummaryPtr   accu_;
+	StatsPtr     stats_; // statistics: only if requested
+	SolvePtr     solve_; // NOTE: last so that it is destroyed first;
+};
+
+/**
+ * \example example2.cpp
+ * This is an example of how to use the ClaspFacade class for basic solving.
+ *
+ * \example example3.cpp
+ * This is an example of how to use the ClaspFacade class for async solving.
+ */
+
+//!@}
+
+}
+#endif
diff --git a/libclasp/clasp/claspfwd.h b/libclasp/clasp/claspfwd.h
new file mode 100644
index 0000000..e040971
--- /dev/null
+++ b/libclasp/clasp/claspfwd.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2013-2016, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#ifndef CLASP_CLASP_FWD_H_INCLUDED
+#define CLASP_CLASP_FWD_H_INCLUDED
+/*!
+ * \file
+ * \brief Forward declarations of important clasp and potassco types.
+ */
+
+namespace Potassco {
+class TheoryAtom;
+class TheoryTerm;
+class TheoryData;
+template  struct Span;
+struct Heuristic_t;
+class BufferedStream;
+class AbstractStatistics;
+}
+//! Root namespace for all types and functions of libclasp.
+namespace Clasp {
+class SharedContext;
+class MinimizeBuilder;
+class SharedMinimizeData;
+class Configuration;
+class Constraint;
+class ConstraintInfo;
+class Solver;
+struct Model;
+//! Supported problem types.
+struct Problem_t {
+	enum Type {Sat = 0, Pb = 1, Asp = 2};
+};
+typedef Problem_t::Type ProblemType;
+class ProgramBuilder;
+class ProgramParser;
+class SatBuilder;
+class PBBuilder;
+class ExtDepGraph;
+class ConstString;
+typedef Potassco::Span StrView;
+typedef Potassco::Heuristic_t DomModType;
+//! Namespace for types and functions used to define ASP programs.
+namespace Asp {
+class LogicProgram;
+class Preprocessor;
+class LpStats;
+class PrgAtom;
+class PrgBody;
+class PrgDisj;
+class PrgHead;
+class PrgNode;
+class PrgDepGraph;
+struct PrgEdge;
+}}
+
+#endif
diff --git a/libclasp/clasp/clause.h b/libclasp/clasp/clause.h
new file mode 100644
index 0000000..575dc39
--- /dev/null
+++ b/libclasp/clasp/clause.h
@@ -0,0 +1,541 @@
+//
+// Copyright (c) 2006-2016, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+#ifndef CLASP_CLAUSE_H_INCLUDED
+#define CLASP_CLAUSE_H_INCLUDED
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include 
+#include 
+namespace Clasp {
+
+//! An array of literals that can be shared between threads.
+/*!
+ * \ingroup shared_con
+ */
+class SharedLiterals {
+public:
+	//! Creates a shareable (ref-counted) object containing the literals in lits.
+	/*!
+	 * \note The reference count is set to numRefs.
+	 */
+	static SharedLiterals* newShareable(const LitVec& lits, ConstraintType t, uint32 numRefs = 1) {
+		return newShareable(!lits.empty() ? &lits[0]:0, static_cast(lits.size()), t, numRefs);
+	}
+	static SharedLiterals* newShareable(const Literal* lits, uint32 size, ConstraintType t, uint32 numRefs = 1);
+
+	//! Returns a pointer to the beginning of the literal array.
+	const Literal* begin() const { return lits_; }
+	//! Returns a pointer to the end of the literal array.
+	const Literal* end()   const { return lits_+size(); }
+	//! Returns the number of literals in the array.
+	uint32         size()  const { return size_type_ >> 2; }
+	//! Returns the type of constraint from which the literals originated.
+	ConstraintType type()  const { return ConstraintType( size_type_ & uint32(3) ); }
+	//! Simplifies the literals w.r.t to the assignment in s.
+	/*!
+	 * Returns the number of non-false literals in this object or 0 if
+	 * the array contains a true literal.
+	 * \note If the object is currently not shared, simplify() removes
+	 * all false literals from the array.
+	 */
+	uint32 simplify(Solver& s);
+
+	void            release() { release(1); }
+	void            release(uint32 numRefs);
+  SharedLiterals* share();
+	bool            unique()   const { return refCount_ <= 1; }
+	uint32          refCount() const { return refCount_; }
+private:
+	void destroy();
+	SharedLiterals(const Literal* lits, uint32 size, ConstraintType t, uint32 numRefs);
+	SharedLiterals(const SharedLiterals&);
+	SharedLiterals& operator=(const SharedLiterals&);
+	typedef Clasp::Atomic_t::type RCType;
+	RCType  refCount_;
+	uint32  size_type_;
+CLASP_WARNING_BEGIN_RELAXED
+	Literal lits_[0];
+CLASP_WARNING_END_RELAXED
+};
+
+//! A helper-class for creating/adding clauses.
+/*!
+ * \ingroup constraint
+ * This class simplifies clause creation. It hides the special handling of
+ * short, and shared clauses. It also makes sure that learnt clauses watch
+ * the literals from the highest decision levels.
+ */
+class ClauseCreator {
+public:
+	typedef ConstraintInfo ClauseInfo;
+	//! Creates a new ClauseCreator object.
+	/*!
+	 * \param s the Solver in which to store created clauses.
+	 */
+	explicit ClauseCreator(Solver* s = 0);
+	//! Sets the solver in which created clauses are stored.
+	void setSolver(Solver& s)         { solver_ = &s; }
+	//! Adds additional flags to be applied in end().
+	void addDefaultFlags(uint32 f)    { flags_ |= f; }
+	//! Reserve space for a clause of size s.
+	void reserve(LitVec::size_type s) { literals_.reserve(s); }
+	//! Discards the current clause.
+	void clear()                      { literals_.clear(); }
+
+	//! Status of a clause.
+	/*!
+	 * For a clause with literals [l1,...,ln], status is one of:
+	 */
+	enum Status {
+		// BASE STATUS
+		status_open         = 0,  //!< Clause is neither sat, unsat, or unit.
+		status_sat          = 1,  //!< At least one literal is true.
+		status_unsat        = 2,  //!< All literals are false.
+		status_unit         = 4,  //!< All but one literal false.
+		// COMPLEX STATUS
+		status_sat_asserting= 5,  //!< Sat but literal is implied on lower dl.
+		status_asserting    = 6,  //!< Unsat but literal is implied on second highest dl.
+		status_subsumed     = 9,  //!< Sat and one literal is true on level 0.
+		status_empty        = 10, //!< Unsat and all literals are false on level 0.
+	};
+	//! A type for storing the result of a clause insertion operation.
+	struct Result {
+		explicit Result(ClauseHead* loc = 0, Status st = status_open)
+			: local(loc)
+			, status(st) {}
+		ClauseHead*     local;
+		Status          status;
+		//! Returns false is clause is conflicting w.r.t current assignment.
+		bool     ok()   const { return (status & status_unsat) == 0; }
+		//! Returns true if the clause implies a literal (possibly after backtracking).
+		bool     unit() const { return (status & status_unit) != 0; }
+		operator bool() const { return ok(); }
+	};
+	//! Starts the creation of a new clause.
+	/*!
+	 * \pre s.decisionLevel() == 0 || t != Constraint_t::Static
+	 */
+	ClauseCreator& start(ConstraintType t = Constraint_t::Static);
+	//! Sets the initial activity of the clause under construction.
+	ClauseCreator& setActivity(uint32 a)      { extra_.setActivity(a);  return *this; }
+	//! Sets the initial literal block distance of the clause under construction.
+	ClauseCreator& setLbd(uint32 lbd)         { extra_.setLbd(lbd); return *this; }
+	//! Adds the literal p to the clause under construction.
+	ClauseCreator& add(const Literal& p)      { literals_.push_back(p); return *this; }
+	//! Removes subsumed lits and orders first lits w.r.t watch order.
+	ClauseRep      prepare(bool fullSimplify);
+	//! Returns the current size of the clause under construction.
+	uint32         size()    const { return (uint32)literals_.size(); }
+	//! Returns the literal at the given idx.
+	Literal&       operator[](uint32 i)       { return literals_[i]; }
+	Literal        operator[](uint32 i) const { return literals_[i]; }
+	//! Returns the literals of the clause under construction.
+	const LitVec&  lits()    const { return literals_; }
+	LitVec&        lits()          { return literals_; }
+	//! Returns the clause's type.
+	ConstraintType type()    const { return extra_.type(); }
+	//! Returns the aux info of the clause under construction.
+	ConstraintInfo info()    const { return extra_; }
+	//! Creates a new clause object for the clause under construction.
+	/*!
+	 * \pre The clause does not contain duplicate/complementary literals or
+	 *      flags contains clause_force_simplify.
+	 *
+	 * \note If the clause to be added is empty, end() fails and s.hasConflict() is set to true.
+	 * \see Result ClauseCreator::create(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info);
+	 */
+	Result end(uint32 flags = clause_not_sat | clause_not_conflict);
+
+	/*!
+	 * \name Factory functions
+	 * Functions for creating and integrating clauses.
+	 */
+	//@{
+	//! Flags controlling clause creation and integration.
+	enum CreateFlag {
+		// REPRESENTATION
+		clause_no_add        = 1,  //!< Do not add clause to solver db.
+		clause_explicit      = 2,  //!< Force creation of explicit clause even if size <= 3.
+		// STATUS
+		clause_not_sat       = 4,  //!< Do not add clause if it is satisfied (but not asserting) w.r.t current assignment.
+		clause_not_root_sat  = 8,  //!< Do not add clause if it is satisfied w.r.t the root assignment.
+		clause_not_conflict  = 16, //!< Do not add clause if it is conflicting w.r.t the current assignment.
+		// INTEGRATE
+		clause_no_release    = 32, //!< Do not call release on shared literals.
+		clause_int_lbd       = 64, //!< Compute lbd when integrating asserting clauses.
+		// PREPARE
+		clause_no_prepare    = 128,//!< Assume clause is already ordered w.r.t watches.
+		clause_force_simplify= 256,//!< Call simplify() on create.
+		clause_no_heuristic  = 512,//!< Do not notify heuristic about new clause.
+		// WATCH MODE - only for problem clauses
+		clause_watch_first   =1024,//!< Watch first free literals.
+		clause_watch_rand    =2048,//!< Watch rand literals.
+		clause_watch_least   =4096,//!< Watch least watched literals.
+	};
+	//! Returns the status of the given clause w.r.t s.
+	static Status    status(const Solver& s, const Literal* clause_begin, const Literal* clause_end);
+	static Status    status(const Solver& s, const ClauseRep& c);
+
+	//! Returns an abstraction of p's decision level that can be used to order literals.
+	/*!
+	 * The function returns a value, s.th
+	 * order(any true literal) > order(any free literal) > order(any false literal).
+	 * Furthermore, for equally assigned literals p and q, order(p) > order(q), iff
+	 * level(p) > level(q).
+	 */
+	static uint32    watchOrder(const Solver& s, Literal p);
+
+	//! Prepares the clause given in lits.
+	/*!
+	 * A prepared clause [l1...ln] with n >= 2 is a clause that,
+	 *  - does not contain any duplicate or complementary literals, and
+	 *  - does not contain any subsumed literals (i.e. literals assigned on decision level 0), and
+	 *  - is partially ordered w.r.t watchOrder(), i.e., watchOrder(l1) >= watchOrder(l2), and there
+	 *    is no lj, j > 2, s.th. watchOrder(lj) > watchOrder(l2)
+	 *  .
+	 *
+	 * Removes subsumed literals from lits and reorders lits s.th.
+	 * the first literals are valid watches. Furthermore,
+	 * if flags contains clause_force_simplify,
+	 * duplicate literals are removed from lits and tautologies are
+	 * replaced with the single literal True.
+	 */
+	static ClauseRep prepare(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info = ClauseInfo());
+
+	//! Creates a clause from the literals given in lits.
+	/*!
+	 * \param s     The solver to which the clause should be added.
+	 * \param lits  The literals of the clause.
+	 * \param flags Flag set controlling creation (see ClauseCreator::CreateFlag).
+	 * \param info  Initial information (e.g. type) for the new clause.
+	 *
+	 * \pre !s.hasConflict() and s.decisionLevel() == 0 or extra.learnt()
+	 * \pre lits is fully prepared or flags contains suitable prepare flags.
+	 *
+	 * \note
+	 *   If the given clause is unit (or asserting), the unit-resulting literal is
+	 *   asserted on the (numerical) lowest level possible but the new information
+	 *   is not immediately propagated, i.e. on return queueSize() may be greater than 0.
+	 *
+	 * \note
+	 *   The local representation of the clause is always attached to the solver
+	 *   but only added to the solver if clause_no_add is not contained in flags.
+	 *   Otherwise, the returned clause is owned by the caller
+	 *   and it is the caller's responsibility to manage it. Furthermore,
+	 *   learnt statistics are *not* updated automatically in that case.
+	 *
+	 * \see prepare()
+	 */
+	static Result create(Solver& s, LitVec& lits, uint32 flags, const ClauseInfo& info = ClauseInfo());
+
+	/*!
+	 * \overload
+	 */
+	static Result create(Solver& s, const ClauseRep& rep, uint32 flags);
+
+	//! Integrates the given clause into the current search of s.
+	/*!
+	 * \pre the assignment in s is not conflicting
+	 * \param s      The solver in which the clause should be integrated.
+	 * \param clause The clause to be integrated.
+	 * \param flags  A set of flags controlling integration (see ClauseCreator::CreateFlag).
+	 * \param t      Constraint type to use for the local representation.
+	 *
+	 * \note
+	 *   The function behaves similar to ClauseCreator::create() with the exception that
+	 *   it does not add local representations for implicit clauses (i.e. size <= 3)
+	 *   unless flags contains clause_explicit.
+	 *   In that case, an explicit representation is created.
+	 *   Implicit representations can only be created via ClauseCreator::create().
+	 *
+	 * \note
+	 *   The function acts as a sink for the given clause (i.e. it decreases its reference count)
+	 *   unless flags contains clause_no_release.
+	 *
+	 * \note integrate() is intended to be called in a post propagator.
+	 *   To integrate a set of clauses F, one would use a loop like this:
+	 *   \code
+	 *   bool MyPostProp::propagate(Solver& s) {
+	 *     bool r = true;
+	 *     while (!F.empty() && r) {
+	 *       SharedLiterals* C = f.pop();
+	 *       r = integrate(s, C, ...).ok;
+	 *     }
+	 *     return r;
+	 *   \endcode
+	 */
+	static Result integrate(Solver& s, SharedLiterals* clause, uint32 flags, ConstraintType t);
+
+	/*!
+	 * \overload
+	 */
+	static Result integrate(Solver& s, SharedLiterals* clause, uint32 flags);
+	//@}
+private:
+	static ClauseRep   prepare(Solver& s, const Literal* in, uint32 inSize, const ClauseInfo& e, uint32 flags, Literal* out, uint32 outMax = UINT32_MAX);
+	static Result      create_prepared(Solver& s, const ClauseRep& pc, uint32 flags);
+	static ClauseHead* newProblemClause(Solver& s, const ClauseRep& clause, uint32 flags);
+	static ClauseHead* newLearntClause(Solver& s, const ClauseRep& clause, uint32 flags);
+	static ClauseHead* newUnshared(Solver& s, SharedLiterals* clause, const Literal* w, const ClauseInfo& e);
+	static bool        ignoreClause(const Solver& s, const ClauseRep& cl, Status st, uint32 modeFlags);
+	Solver*    solver_;   // solver in which new clauses are stored
+	LitVec     literals_; // literals of the new clause
+	ClauseInfo extra_;    // extra info
+	uint32     flags_;    // default flags to be used in end()
+};
+
+//! Class for representing a clause in a solver.
+/*!
+ * \ingroup constraint
+ */
+class Clause : public ClauseHead {
+public:
+	typedef Constraint::PropResult PropResult;
+	enum { MAX_SHORT_LEN = 5 };
+
+	//! Allocates memory for storing a (learnt) clause with nLits literals.
+	static void* alloc(Solver& s, uint32 mLits, bool learnt);
+
+	//! Creates a new clause from the clause given in rep.
+	/*!
+	 * \param s   Solver in which the new clause is to be used.
+	 * \param rep The raw representation of the clause.
+	 *
+	 * \pre The clause given in lits is prepared and contains at least two literals.
+	 * \note The clause must be destroyed using Clause::destroy.
+	 * \see ClauseCreator::prepare()
+	 */
+	static ClauseHead*  newClause(Solver& s, const ClauseRep& rep) {
+		return newClause(alloc(s, rep.size, rep.info.learnt()), s, rep);
+	}
+	//! Creates a new clause object in mem.
+	/*!
+	 * \pre mem points to a memory block that was allocated via Clause::alloc().
+	 */
+	static ClauseHead*  newClause(void* mem, Solver& s, const ClauseRep& rep);
+
+	//! Creates a new contracted clause from the clause given in rep.
+	/*!
+	 * A contracted clause consists of an active head and a tail of false literals.
+	 * Propagation is restricted to the head.
+	 * The tail is only needed to compute reasons from assignments.
+	 *
+	 * \param s       Solver in which the new clause is to be used.
+	 * \param rep     The raw representation of the clause.
+	 * \param tailPos The starting index of the tail (first literal that should be temporarily removed from the clause).
+	 * \param extend  Extend head part of clause as tail literals become free?
+	 */
+	static ClauseHead*  newContractedClause(Solver& s, const ClauseRep& rep, uint32 tailPos, bool extend);
+
+	//! Creates a new local surrogate for shared_lits to be used in the given solver.
+	/*!
+	 * \param s      The solver in which this clause will be used.
+	 * \param lits   The shared literals of this clause.
+	 * \param e      Initial meta data for the new (local) clause.
+	 * \param head   Watches and cache literal for the new (local) clause.
+	 * \param addRef Increment ref count of lits.
+	 */
+	static ClauseHead* newShared(Solver& s, SharedLiterals* lits, const InfoType& e, const Literal head[3], bool addRef = true);
+
+	// Constraint-Interface
+
+	Constraint* cloneAttach(Solver& other);
+
+	/*!
+	 * For a clause [x y p] the reason for p is ~x and ~y.
+	 * \pre *this previously asserted p
+	 * \note if the clause is a learnt clause, calling reason increases
+	 * the clause's activity.
+	 */
+	void reason(Solver& s, Literal p, LitVec& lits);
+
+	bool minimize(Solver& m, Literal p, CCMinRecursive* r);
+
+	bool isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN);
+
+	//! Returns true if clause is SAT.
+	/*!
+	 * Removes from the clause all literals that are false.
+	 */
+	bool simplify(Solver& s, bool = false);
+
+	//! Destroys the clause and frees its memory.
+	void destroy(Solver* s = 0, bool detach = false);
+
+	// LearntConstraint interface
+
+	//! Returns type() if the clause is currently not satisfied and t.inSet(type()).
+	uint32 isOpen(const Solver& s, const TypeSet& t, LitVec& freeLits);
+
+	// clause interface
+	BoolPair strengthen(Solver& s, Literal p, bool allowToShort);
+	void     detach(Solver&);
+	uint32   size()                 const;
+	void     toLits(LitVec& out)    const;
+	bool     contracted()           const;
+	bool     isSmall()              const;
+	bool     strengthened()         const;
+	uint32   computeAllocSize()     const;
+private:
+	Clause(Solver& s, const ClauseRep& rep, uint32 tail = UINT32_MAX, bool extend = false);
+	Clause(Solver& s, const Clause& other);
+	typedef std::pair LitRange;
+	void     undoLevel(Solver& s);
+	bool     updateWatch(Solver& s, uint32 pos);
+	Literal* end() { return head_+local_.size(); }
+	Literal* removeFromTail(Solver& s, Literal* it, Literal* end);
+	Literal* small();
+	LitRange tail();
+};
+
+//! Constraint for Loop-Formulas.
+/*!
+ * \ingroup constraint
+ * Special purpose constraint for loop formulas of the form: L v B1 v ... v Bm,
+ * where L is an unfounded set represented as a set of atom literals {~a1, ..., ~an}.
+ * Representing such a loop formula explicitly as n clauses
+ *   - (1) ~a1 v B1 v ... v Bm
+ *   - ...
+ *   - (n) ~an v B1 v ... v Bm
+ *   .
+ * is wasteful because each clause contains the same set of bodies.
+ *
+ * The idea behind LoopFormula is to treat L as a "macro-literal"
+ * with the following properties:
+ * - isTrue(L), iff for all ai isTrue(~ai)
+ * - isFalse(L), iff for some ai isFalse(~ai)
+ * - L is watchable, iff not isFalse(L)
+ * - Watching L means watching all ai.
+ * - setting L to true means setting all ai to false.
+ * Using this convention the TWL-algo can be implemented as in a clause.
+ *
+ * \par Implementation:
+ * - The literal-array is divided into two parts, an "active clause" part and an atom part.
+ * - The "active clause" contains one atom and all bodies: [~ai B1 ... Bj]
+ * - The atom part contains all atoms: [~a1 ... ~an]
+ * - Two of the literals of the "active clause" are watched (again: watching an atom means watching all atoms)
+ * - If a watched atom becomes true, it is copied into the "active clause" and the TWL-algo starts.
+ */
+class LoopFormula : public Constraint {
+public:
+	//! Creates a new loop-constraint for the given atoms.
+	/*!
+	* \param s      Solver in which the new constraint is to be used.
+	* \param c1     First clause of the new constraint.
+	* \param atoms  Set of atoms in the loop.
+	* \param nAtoms Number of atoms in the loop.
+	* \param updateHeuristic Whether to notify heuristic about new constraint.
+	*
+	* \pre The clause given in c1 is prepared and c1.size > 1 and c1.lits[0] is a literal in atoms.
+	* \see ClauseCreator::prepare()
+	*/
+	static LoopFormula* newLoopFormula(Solver& s, const ClauseRep& c1, const Literal* atoms, uint32 nAtoms, bool updateHeuristic = true);
+
+	//! Returns the number of literals in the loop-formula.
+	uint32 size() const;
+
+	// Constraint interface
+	Constraint* cloneAttach(Solver&) { return 0; }
+	PropResult  propagate(Solver& s, Literal p, uint32& data);
+	void reason(Solver&, Literal p, LitVec& lits);
+	bool minimize(Solver& s, Literal p, CCMinRecursive* ccMin);
+	bool simplify(Solver& s, bool = false);
+	void destroy(Solver* = 0, bool = false);
+
+	// LearntConstraint interface
+	bool locked(const Solver& s) const;
+
+	uint32 isOpen(const Solver& s, const TypeSet& t, LitVec& freeLits);
+
+	//! Returns the loop-formula's activity.
+	/*!
+	 * The activity of a loop-formula is increased, whenever reason() is called.
+	 */
+	ScoreType activity() const { return act_; }
+
+	//! Halves the loop-formula's activity.
+	void decreaseActivity() { act_.reduce(); }
+	void resetActivity()    { act_.reset(); }
+
+	//! Returns Constraint_t::Loop.
+	ConstraintType type() const { return Constraint_t::Loop; }
+private:
+	LoopFormula(Solver& s, const ClauseRep& c1, const Literal* atoms, uint32 nAtoms, bool heu);
+	void detach(Solver& s);
+	bool otherIsSat(const Solver& s);
+	Literal* begin() { return lits_ + 1; }
+	Literal* xBegin(){ return lits_ + end_ + 1; }
+	Literal* xEnd()  { return lits_ + size_; }
+	ScoreType act_;     // activity of constraint
+	uint32    end_;     // position of second sentinel
+	uint32    size_:30; // size of lits_
+	uint32    str_ : 1; // removed literal(s) during simplify?
+	uint32    xPos_: 1; // position of ai in lits_ or 0 if no atom
+	uint32    other_;   // stores the position of a literal that was recently true
+CLASP_WARNING_BEGIN_RELAXED
+	Literal   lits_[0]; // S ai B1...Bm S a1...an
+CLASP_WARNING_END_RELAXED
+};
+
+namespace mt {
+
+//! Stores the local part of a shared clause.
+/*!
+ * \ingroup constraint
+ * The local part of a shared clause consists of a
+ * clause head and and a pointer to the shared literals.
+ * Since the local part is owned by a particular solver
+ * it can be safely modified. Destroying a SharedLitsClause
+ * means destroying the local part and decreasing the
+ * shared literals' reference count.
+ */
+class SharedLitsClause : public ClauseHead {
+public:
+	//! Creates a new SharedLitsClause to be used in the given solver.
+	/*!
+	 * \param s The solver in which this clause will be used.
+	 * \param shared_lits The shared literals of this clause.
+	 * \param e Initial meta data for the new (local) clause.
+	 * \param lits Watches and cache literal for the new (local) clause.
+	 * \param addRef Increment ref count of shared_lits.
+	 */
+	static ClauseHead* newClause(Solver& s, SharedLiterals* shared_lits, const InfoType& e, const Literal* lits, bool addRef = true);
+
+	Constraint* cloneAttach(Solver& other);
+	void        reason(Solver& s, Literal p, LitVec& out);
+	bool        minimize(Solver& s, Literal p, CCMinRecursive* rec);
+	bool        isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN);
+	bool        simplify(Solver& s, bool);
+	void        destroy(Solver* s, bool detach);
+	uint32      isOpen(const Solver& s, const TypeSet& t, LitVec& freeLits);
+	uint32      size() const;
+	void        toLits(LitVec& out) const;
+private:
+	SharedLitsClause(Solver& s, SharedLiterals* x, const Literal* lits, const InfoType&,  bool addRef);
+	bool     updateWatch(Solver& s, uint32 pos);
+	BoolPair strengthen(Solver& s, Literal p, bool allowToShort);
+};
+}
+
+}
+#endif
diff --git a/libclasp/clasp/cli/clasp_cli_configs.inl b/libclasp/clasp/cli/clasp_cli_configs.inl
new file mode 100644
index 0000000..772ce16
--- /dev/null
+++ b/libclasp/clasp/cli/clasp_cli_configs.inl
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2013, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+/*!
+ * \file
+ * \brief Supermacros for defining clasp's default configurations.
+ * \code
+ * CONFIG(sId, name, "", "", "")
+ * \endcode
+ *
+ * A configuration consists of a solver id and a name followed by three option strings:
+ * - ""     : options that are always part of the configuration
+ * - "": options to add if configuration is used as a stand-alone configuration (e.g. global options)
+ * - ""  : options to add if configuration is used in a portfolio
+ * .
+ * \note The solver id is used to identify a configuration in the default portfolio.
+ */
+
+#if !defined(CONFIG) || (!defined(CLASP_CLI_DEFAULT_CONFIGS) && !defined(CLASP_CLI_AUX_CONFIGS))
+#error Invalid include context
+#endif
+
+//! Named default configurations accessible via option "--configuration=".
+#if defined(CLASP_CLI_DEFAULT_CONFIGS)
+CLASP_CLI_DEFAULT_CONFIGS
+CONFIG(0, tweety\
+       , "--heuristic=Vsids,92 --restarts=L,60 --deletion=basic,50,0 --del-max=2000000 --del-estimate=1 --del-cfl=+,2000,100,20 --del-grow=0 --del-glue=2,0"\
+         " --strengthen=recursive,0 --otfs=2 --init-moms --score-other=2 --update-lbd=1 --save-progress=160 --init-watches=2 --local-restarts --loops=shared"\
+       , "--eq=3 --trans-ext=dynamic"\
+       , "--opt-strat=bb,1")
+CONFIG(1, trendy\
+       , "--heuristic=Vsids --restarts=D,100,0.7 --deletion=basic,50,0 --del-init=3.0,500,19500 --del-grow=1.1,20.0,x,100,1.5 --del-cfl=+,10000,2000 --del-glue=2"\
+         " --strengthen=recursive --update-lbd --otfs=2 --save-p=75 --counter-restarts=3 --counter-bump=1023 --reverse-arcs=2 --contraction=250 --loops=common"\
+       , "--sat-p=2,20,25,240 --trans-ext=dynamic"\
+       , "--opt-heu=1 --opt-strat=usc,1")
+CONFIG(2, frumpy\
+       , "--heuristic=Berkmin --restarts=x,100,1.5 --deletion=basic,75 --del-init=3.0,200,40000 --del-max=400000 --contraction=250 --loops=common --save-p=180"\
+         " --del-grow=1.1 --strengthen=local --sign-def-disj=1"\
+       , "--eq=5"\
+       , "--restart-on-model --opt-heu=2")
+CONFIG(3, crafty\
+       , "--restarts=x,128,1.5 --deletion=basic,75,0 --del-init=10.0,1000,9000 --del-grow=1.1,20.0 --del-cfl=+,10000,1000 --del-glue=2 --otfs=2"\
+         " --reverse-arcs=1 --counter-restarts=3 --contraction=250"\
+       , "--sat-p=2,10,25,240 --trans-ext=dynamic --backprop --heuristic=Vsids --save-p=180"\
+       , "--heuristic=domain --dom-mod=4,8 --opt-strat=bb,1")
+CONFIG(4, jumpy\
+       , "--heuristic=Vsids --restarts=L,100 --deletion=basic,75,2 --del-init=3.0,1000,20000 --del-grow=1.1,25,x,100,1.5 --del-cfl=x,10000,1.1 --del-glue=2"\
+         " --update-lbd=3 --strengthen=recursive --otfs=2 --save-p=70"\
+       , "--sat-p=2,20,25,240 --trans-ext=dynamic"\
+       , "--restart-on-model --opt-heu=3 --opt-strat=bb,2")
+CONFIG(5, handy\
+       , "--heuristic=Vsids --restarts=D,100,0.7 --deletion=sort,50,2 --del-max=200000 --del-init=20.0,1000,14000 --del-cfl=+,4000,600 --del-glue=2 --update-lbd"\
+         " --strengthen=recursive --otfs=2 --save-p=20 --contraction=600 --loops=distinct --counter-restarts=7 --counter-bump=1023 --reverse-arcs=2"\
+       , "--sat-p=2,10,25,240 --trans-ext=dynamic --backprop"\
+       , "")
+#undef CLASP_CLI_DEFAULT_CONFIGS
+#endif
+//! Auxiliary configurations accessible via default portfolio ("--configuration=many").
+#if defined(CLASP_CLI_AUX_CONFIGS)
+CLASP_CLI_AUX_CONFIGS
+CONFIG(6,  s6,  "--heuristic=Berkmin,512 --restarts=x,100,1.5 --deletion=basic,75 --del-init=3.0,200,40000 --del-max=400000 --contraction=250 --loops=common --del-grow=1.1,25 --otfs=2 --reverse-arcs=2 --strengthen=recursive --init-w=2 --lookahead=atom,10", "", "")
+CONFIG(7,  s7,  "--heuristic=Vsids --reverse-arcs=1 --otfs=1 --local-restarts --save-progress=0 --contraction=250 --counter-restart=7 --counter-bump=200 --restarts=x,100,1.5 --del-init=3.0,800,-1 --deletion=basic,60,0 --strengthen=local --del-grow=1.0,1.0 --del-glue=4 --del-cfl=+,4000,300,100",  "", "")
+CONFIG(8,  s8,  "--heuristic=Vsids --restarts=L,256 --counter-restart=3 --strengthen=recursive --update-lbd --del-glue=2 --otfs=2 --deletion=ipSort,75,2 --del-init=20.0,1000,19000", "", "")
+CONFIG(9,  s9,  "--heuristic=Berkmin,512 --restarts=F,16000 --lookahead=atom,50",  "", "")
+CONFIG(10, s10, "--heuristic=Vmtf --strengthen=no --contr=0 --restarts=x,100,1.3 --del-init=3.0,800,9200",  "", "")
+CONFIG(11, s11, "--heuristic=Vsids --strengthen=recursive --restarts=x,100,1.5,15 --contraction=0",  "", "")
+CONFIG(12, s12, "--heuristic=Vsids --restarts=L,128 --save-p --otfs=1 --init-w=2 --contr=0 --opt-heu=3",  "", "")
+CONFIG(13, s13, "--heuristic=Berkmin,512 --restarts=x,100,1.5,6 --local-restarts --init-w=2 --contr=0",  "", "")
+CONFIG(14, nolearn, "--no-lookback --heuristic=Unit --lookahead=atom --deletion=no --restarts=no",  "", "")
+CONFIG(15, tester,  "--heuristic=Vsids --restarts=D,100,0.7 --deletion=sort,50,2 --del-max=200000 --del-init=20.0,1000,14000 --del-cfl=+,4000,600 --del-glue=2 --update-lbd"\
+                    " --strengthen=recursive --otfs=2 --save-p=20 --contraction=600 --counter-restarts=7 --counter-bump=1023 --reverse-arcs=2"\
+                 ,  "--sat-p=2,10,25,240", "")
+#undef CLASP_CLI_AUX_CONFIGS
+#endif
+#undef CONFIG
diff --git a/libclasp/clasp/cli/clasp_cli_options.inl b/libclasp/clasp/cli/clasp_cli_options.inl
new file mode 100644
index 0000000..acb5226
--- /dev/null
+++ b/libclasp/clasp/cli/clasp_cli_options.inl
@@ -0,0 +1,493 @@
+//
+// Copyright (c) 2013-2016, Benjamin Kaufmann
+//
+// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
+//
+// Clasp is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Clasp is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Clasp; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+/*!
+ * \file
+ * \brief Supermacros for describing clasp's options.
+ * \code
+ * OPTION(key, "ext", ARG(...), "help", set, get)
+ * \endcode
+ * An option consists of:
+ *  - a key  (valid and unique c identifier in 'snake_case')
+ *  - a key extension ("[!][,][,@]") as understood by ProgramOptions::OptionInitHelper
+ *  - an arg description (ARG macro) as understood by ProgramOptions::Value
+ *  - a description (string)
+ *  - a set action to be executed when a value (string) for the option is found in a source
+ *  - a get action to be executed when the current value for an option is requested
+ *  .
+ *
+ * \note In the implementation of ClaspCliConfig, each key is mapped to an enumeration constant and
+ * the stringified version of key (i.e. \#key) is used to identify options.
+ * Furthermore, the key is also used for generating command-line option names.
+ * As a convention, compound keys using 'snake_case' to separate words
+ * are mapped to dash-separated command-line option names.
+ * E.g. an \ is mapped to the command-line option "option-like-this".
+ *
+ * \note ClaspCliConfig assumes a certain option order. In particular, context options shall
+ * precede all solver/search options, which in turn shall precede global asp/solving options.
+ *
+ * \note The following set actions may be used:
+ *  - STORE(obj): converts the string value to the type of obj and stores the result in obj.
+ *  - STORE_LEQ(n, max): converts the string value to an unsinged int and stores the result in n if it is <= max.
+ *  - STORE_FLAG(n): converts the string value to a bool and stores the result in n as either 0 or 1.
+ *  - STORE_OR_FILL(n): converts the string value to an unsinged int t and sets n to std::min(t, maxValue(n)).
+ *  - FUN(arg): anonymous function of type bool (ArgStream& arg), where arg provides the following interface:
+ *    - arg.ok()     : returns whether arg is still valid
+ *    - arg.empty()  : returns whether arg is empty (i.e. all tokens were extracted)
+ *    - arg.off()    : returns whether arg contains a single token representing a valid off value
+ *    - arg >> x     : extracts and converts the current token and stores it in x. Sets failbit if conversion fails.
+ *    - arg >> opt(x): extracts an optional argument, shorthand for (!arg.empty() ? arg>>obj : arg)
+ *    .
+ *
+ * \note The following get actions may be used:
+ *  - GET_FUN(str)  : anonymous function of type void (OutputStream& str)
+ *  - GET(obj...)   : shorthand for GET_FUN(str) { (str << obj)...; }
+ *  - GET_IF(C, obj): shorthand for GET_FUN(str) { ITE(C, str << obj, str << off); }
+ *  .
+ *
+ * \note The following primitives may be used in the set/get arguments:
+ *  - off                  : singleton object representing a valid off value ("no", "off", "false", "0")
+ *  - ITE(C, x, y)         : if-then-else expression, i.e. behaves like (C ? x : y).
+ *  - SET(x, y)            : shorthand for (x=y) == y.
+ *  - SET_LEQ(x, v, m)     : shorthand for (x <= m && SET(x, v)).
+ *  - SET_GEQ(x, v, m)     : shorthand for (x >= m && SET(x, v)).
+ *  - SET_OR_FILL(x, v)    : behaves like SET(x, min(v, maxValue(x)))
+ *  - SET_OR_ZERO(x,v)     : behaves like ITE(v <= maxValue(x), SET(x, v), SET(x, 0)).
+ *  .
+ */
+#if !defined(OPTION) || defined(SELF)
+#error Invalid include context
+#endif
+
+#if !defined(GROUP_BEGIN)
+#define GROUP_BEGIN(X)
+#endif
+
+#if !defined(GROUP_END)
+#define GROUP_END(X)
+#endif
+
+//! Options for configuring a SharedContext object stored in a Clasp::ContextParams object.
+#if defined(CLASP_CONTEXT_OPTIONS)
+#define SELF CLASP_CONTEXT_OPTIONS
+GROUP_BEGIN(SELF)
+OPTION(share, "!,@1", ARG_EXT(defaultsTo("auto")->state(Value::value_defaulted), DEFINE_ENUM_MAPPING(ContextParams::ShareMode, \
+       MAP("no"  , ContextParams::share_no)  , MAP("all", ContextParams::share_all),\
+       MAP("auto", ContextParams::share_auto), MAP("problem", ContextParams::share_problem),\
+       MAP("learnt", ContextParams::share_learnt))),\
+       "Configure physical sharing of constraints [%D]\n"\
+       "      %A: {auto|problem|learnt|all}", FUN(arg) {ContextParams::ShareMode x; return arg>>x && SET(SELF.shareMode, (uint32)x);}, GET((ContextParams::ShareMode)SELF.shareMode))
+OPTION(learn_explicit, ",@1" , ARG(flag()), "Do not use Short Implication Graph for learning\n", STORE_FLAG(SELF.shortMode), GET(SELF.shortMode))
+OPTION(sat_prepro    , "!,@1", ARG(implicit("2")), "Run SatELite-like preprocessing (Implicit: %I)\n" \
+       "      %A: [,...(0=no limit)]\n"                \
+       "        : Run {1=VE|2=VE with BCE|3=BCE followed by VE}\n"\
+       "          : Set iteration limit to            [0]\n"\
+       "          : Set variable occurrence limit to  [0]\n"\
+       "          : Set time limit to  seconds        [0]\n"\
+       "          : Set frozen variables limit to %%   [0]\n"\
+       "          : Set clause limit to *1000      [4000]", FUN(arg) {\
+       SatPreParams& pre = SELF.satPre; uint32 x;\
+       return ITE(arg.off(), SET(pre.type, 0u), arg>>x && SET_GEQ(pre.type, x, 1u)\
+         && arg >> opt(x = 0)    && SET_OR_ZERO(pre.limIters , x)\
+         && arg >> opt(x = 0)    && SET_OR_ZERO(pre.limOcc   , x)\
+         && arg >> opt(x = 0)    && SET_OR_ZERO(pre.limTime  , x)\
+         && arg >> opt(x = 0)    && SET_OR_ZERO(pre.limFrozen, x)\
+         && arg >> opt(x = 4000) && SET_OR_ZERO(pre.limClause, x));},\
+       GET_FUN(str) { SatPreParams& pre = SELF.satPre;\
+         ITE(pre.type, str<arg("[,]")), "Enable {1=basic|2=full} statistics ( for tester)",\
+    FUN(arg) { uint32 s = 0; uint32 t = 0;\
+      return (arg.off() || (arg >> s && s > 0)) && arg >> opt(t) && arg.empty()
+        && SET(SELF.stats, s) && ((!SELF.testerConfig() && t == 0) || SET(SELF.addTesterConfig()->stats, t));
+    },\
+    GET_FUN(str) { ITE(!SELF.testerConfig() || !SELF.testerConfig()->stats, str << SELF.stats, str << SELF.stats << SELF.testerConfig()->stats); })
+OPTION(parse_ext, "!", ARG(flag()), "Enable extensions in non-aspif input",\
+    FUN(arg) { bool b = false; return (arg.off() || arg >> b) && SET(SELF.parse.ext, (b ? unsigned(ParserOptions::parse_full):0u)); }, \
+    GET((SELF.parse.ext != 0)))
+GROUP_END(SELF)
+#undef CLASP_GLOBAL_OPTIONS
+#undef SELF
+#endif
+
+//! Solver options (see SolverParams).
+#if defined(CLASP_SOLVER_OPTIONS)
+#define SELF CLASP_SOLVER_OPTIONS
+GROUP_BEGIN(SELF)
+OPTION(opt_strategy , ""  , ARG_EXT(arg("")->implicit("1"), DEFINE_ENUM_MAPPING(MinimizeMode_t::Strategy,\
+       MAP("bb", MinimizeMode_t::opt_bb), MAP("usc", MinimizeMode_t::opt_usc))),  "Configure optimization strategy\n" \
+       "      %A: {bb|usc}[,]\n" \
+       "        bb : model-guided (branch and bound) optimization ()\n"\
+       "          0: default algorithm with minimal steps\n"                      \
+       "          1: hierarchical algorithm and constant steps\n"                 \
+       "          2: hierarchical algorithm and exponentially increasing steps\n" \
+       "          3: hierarchical algorithm and exponentially decreasing steps\n" \
+       "        usc: unsatisfiable-core guided optimization (bitmask )\n"\
+       "          1: enable disjoint-core preprocessing\n"                        \
+       "          2: disable redundant (symmetry) constraints\n"                  \
+       "          4: enable PMRES instead of OLL algorithm\n"                     \
+       "          8: enable stratification heuristic for handling weights"       ,\
+       FUN(arg) { MinimizeMode_t::Strategy sc = MinimizeMode_t::opt_bb; uint32 n;\
+         return ((SET_LEQ(n, uint32(arg.peek()-'0'), 9u) && arg >> n && (n < 4u || (SET(sc, MinimizeMode_t::opt_usc) && (n -= 4u) < 16u)))\
+           || (arg>>sc>>opt(n = 0))) && SET(SELF.optStrat, (uint32)sc) && SET(SELF.optParam, n) && (n < 4u || sc == MinimizeMode_t::opt_usc);},\
+       GET(static_cast(SELF.optStrat), SELF.optParam))
+OPTION(opt_heuristic, ""  , ARG(implicit("1")->arg("{0..3}")), "Use opt. in {1=sign|2=model|3=both} heuristics", STORE_LEQ(SELF.optHeu,  3u), GET(SELF.optHeu))
+OPTION(restart_on_model, "", ARG(flag()), "Restart after each model\n", STORE_FLAG(SELF.restartOnModel), GET(SELF.restartOnModel))
+OPTION(lookahead    , "!", ARG_EXT(implicit("atom"), DEFINE_ENUM_MAPPING(VarType, \
+       MAP("atom", Var_t::Atom), MAP("body", Var_t::Body), MAP("hybrid", Var_t::Hybrid))),\
+       "Configure failed-literal detection (fld)\n" \
+       "      %A: [,] / Implicit: %I\n" \
+       "         : Run fld via {atom|body|hybrid} lookahead\n" \
+       "        : Disable fld after  applications ([0]=no limit)\n" \
+       "      --lookahead=atom is default if --no-lookback is used\n", FUN(arg) { \
+       VarType type; uint32 limit = (SELF.lookOps = 0u);\
+       return ITE(arg.off(), SET(SELF.lookType, 0u), arg>>type>>opt(limit) && SET(SELF.lookType, (uint32)type)) && SET_OR_ZERO(SELF.lookOps, limit);},\
+       GET_IF(SELF.lookType, (VarType)SELF.lookType, SELF.lookOps))
+OPTION(heuristic, "", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(Heuristic_t::Type, \
+       MAP("berkmin", Heuristic_t::Berkmin), MAP("vmtf"  , Heuristic_t::Vmtf), \
+       MAP("vsids"  , Heuristic_t::Vsids)  , MAP("domain", Heuristic_t::Domain), \
+       MAP("unit"   , Heuristic_t::Unit)   , MAP("auto", Heuristic_t::Default), MAP("none"  , Heuristic_t::None))), \
+       "Configure decision heuristic\n"  \
+       "      %A: {Berkmin|Vmtf|Vsids|Domain|Unit|None}[,]\n" \
+       "        Berkmin: Use BerkMin-like heuristic (Check last  nogoods [0]=all)\n" \
+       "        Vmtf   : Use Siege-like heuristic (Move  literals to the front [8])\n" \
+       "        Vsids  : Use Chaff-like heuristic (Use 1.0/0. as decay factor  [95])\n"\
+       "        Domain : Use domain knowledge in Vsids-like heuristic\n"\
+       "        Unit   : Use Smodels-like heuristic (Default if --no-lookback)\n" \
+       "        None   : Select the first free variable", FUN(arg) { Heuristic_t::Type h; uint32 n = 0u; \
+       return arg>>h>>opt(n) && SET(SELF.heuId, (uint32)h) && (Heuristic_t::isLookback(h) || !n) && SET_OR_FILL(SELF.heuristic.param, n);},\
+       GET((Heuristic_t::Type)SELF.heuId, SELF.heuristic.param))
+OPTION(init_moms  , "!,@2", ARG(flag())    , "Initialize heuristic with MOMS-score", STORE_FLAG(SELF.heuristic.moms), GET(SELF.heuristic.moms))
+OPTION(score_res  , ",@2" , ARG(arg("")), "Resolution score {0=default|1=min|2=set|3=multiset}", STORE_LEQ(SELF.heuristic.score,3u), GET(SELF.heuristic.score))
+OPTION(score_other, ",@2" , ARG(arg("")), "Score {0=no|1=loop|2=all} other learnt nogoods", STORE_LEQ(SELF.heuristic.other,2u), GET(SELF.heuristic.other))
+OPTION(sign_def   , ""    , ARG(arg("")), "Default sign: {0=asp|1=pos|2=neg|3=rnd}", STORE_LEQ(SELF.signDef,3u), GET(SELF.signDef))
+OPTION(sign_fix   , "!"   , ARG(flag())    , "Disable sign heuristics and use default signs only", STORE_FLAG(SELF.signFix), GET(SELF.signFix))
+OPTION(berk_huang , "!,@2", ARG(flag())    , "Enable/Disable Huang-scoring in Berkmin", STORE_FLAG(SELF.heuristic.huang), GET(SELF.heuristic.huang))
+OPTION(vsids_acids, "!,@2", ARG(flag())    , "Enable/Disable acids-scheme in Vsids/Domain", STORE_FLAG(SELF.heuristic.acids), GET(SELF.heuristic.acids))
+OPTION(vsids_progress, ",@2", NO_ARG, "Enable dynamic decaying scheme in Vsids/Domain\n"\
+       "      %A: [,][,]|(0=disable)\n"\
+       "         : Set initial decay factor to 1.0/0.\n"\
+       "         : Set decay update to /100.0      [1]\n"\
+       "         : Decrease decay every  conflicts [5000]", \
+       FUN(arg) { uint32 n = 80; uint32 i = 1; uint32 c = 5000; \
+       return ITE(arg.off(), SET(SELF.heuristic.decay.init, 0), (arg >> n >> opt(i) >> opt(c))\
+         && SET(SELF.heuristic.decay.init, n) && SET_LEQ(SELF.heuristic.decay.bump, i, 100) && SET(SELF.heuristic.decay.freq, c));}, \
+       GET_IF(SELF.heuristic.decay.init, SELF.heuristic.decay.init, SELF.heuristic.decay.bump, SELF.heuristic.decay.freq))
+OPTION(nant       , "!,@2", ARG(flag())    , "Prefer negative antecedents of P in heuristic", STORE_FLAG(SELF.heuristic.nant), GET(SELF.heuristic.nant))
+OPTION(dom_mod    , ",@2" , NO_ARG         , "Default modification for domain heuristic\n"\
+       "      %A: [,]\n"\
+       "          : Modifier {1=level|2=pos|3=true|4=neg|5=false|6=init|7=factor}\n"\
+       "         : Apply  to {0=all|1=scc|2=hcc|4=disj|8=min|16=show} atoms",\
+       FUN(arg) { uint32 n; return arg>>n && SET_LEQ(SELF.heuristic.domMod, n, 7u) && arg>>opt(n = 0) && SET(SELF.heuristic.domPref, n);},\
+       GET(SELF.heuristic.domMod, SELF.heuristic.domPref))
+OPTION(save_progress, "", ARG(implicit("1")->arg("")), "Use RSat-like progress saving on backjumps > %A", STORE_OR_FILL(SELF.saveProgress), GET(SELF.saveProgress))
+OPTION(init_watches , ",@2", ARG(arg("{0..2}")->defaultsTo("1")->state(Value::value_defaulted)),\
+       "Configure watched literal initialization [%D]\n" \
+       "      Watch {0=first|1=random|2=least watched} literals in nogoods", STORE_LEQ(SELF.initWatches, 2u), GET(SELF.initWatches))
+OPTION(update_mode   , ",@2", ARG(arg("")), "Process messages on {0=propagation|1=conflict)", STORE_LEQ(SELF.upMode, 1u), GET(SELF.upMode))
+OPTION(acyc_prop, ",@2", ARG(implicit("1")->arg("{0..1}")), "Acyc propagate with {0=inc|1=inc+back}", \
+       FUN(arg) { uint32 x; return arg>>x && SET_LEQ(SELF.acycFwd, (1u-x), 1u); }, GET(1u-SELF.acycFwd))
+OPTION(seed          , ""   , ARG(arg("")),"Set random number generator's seed to %A", STORE(SELF.seed), GET(SELF.seed))
+OPTION(no_lookback   , ""   , ARG(flag()), "Disable all lookback strategies\n", STORE_FLAG(SELF.search),GET(static_cast(SELF.search == SolverStrategies::no_learning)))
+OPTION(forget_on_step, ""   , ARG(arg("")), "Configure forgetting on (incremental) step\n"\
+       "      Forget {1=heuristic,2=signs,4=nogood activities,8=learnt nogoods}\n", STORE_LEQ(SELF.forgetSet, 15u), GET(SELF.forgetSet))
+OPTION(strengthen    , "!"  , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolverStrategies::CCMinType, \
+       MAP("local", SolverStrategies::cc_local), MAP("recursive", SolverStrategies::cc_recursive))), \
+       "Use MiniSAT-like conflict nogood strengthening\n" \
+       "      %A: [,][,]\n" \
+       "        : Use {local|recursive} self-subsumption check\n" \
+       "        : Follow {0=all|1=short|2=binary} antecedents   [0]\n"\
+       "        : {0=Increase|1=Keep} activities of antecedents [0]", FUN(arg) {\
+       SolverStrategies::CCMinType m = SolverStrategies::cc_local; uint32 t; uint32 k = 0; \
+       return ITE(arg.off(), SET(t, 0u), arg>>m>>opt(t = 0u)>>opt(k) && ++t) && SET(SELF.ccMinAntes, t) && SET(SELF.ccMinRec, (uint32)m) && SET(SELF.ccMinKeepAct, k);},\
+       GET_IF(SELF.ccMinAntes, (SolverStrategies::CCMinType)SELF.ccMinRec, SELF.ccMinAntes-uint32(1), SELF.ccMinKeepAct))
+OPTION(otfs        , ""   , ARG(implicit("1")->arg("{0..2}")), "Enable {1=partial|2=full} on-the-fly subsumption", STORE_LEQ(SELF.otfs, 2u), GET(SELF.otfs))
+OPTION(update_lbd  , ",@2", ARG(implicit("1")->arg("{0..3}")), "Update LBDs of learnt nogoods {1=<|2=strict<|3=+1<}", STORE_LEQ(SELF.updateLbd, 3u),GET(SELF.updateLbd))
+OPTION(update_act  , ",@2", ARG(flag()), "Enable LBD-based activity bumping", STORE_FLAG(SELF.bumpVarAct), GET(SELF.bumpVarAct))
+OPTION(reverse_arcs, ""   , ARG(implicit("1")->arg("{0..3}")), "Enable ManySAT-like inverse-arc learning", STORE_LEQ(SELF.reverseArcs, 3u), GET(SELF.reverseArcs))
+OPTION(contraction , "!"  , NO_ARG, "Configure handling of long learnt nogoods\n"
+       "      %A: [,]\n"\
+       "          : Contract nogoods if size >  (0=disable)\n"\
+       "        : Replace literal blocks with {1=decisions|2=uips} ([0]=disable)\n", FUN(arg) { uint32 n = 0; uint32 r = 0;\
+       return (arg.off() || (arg>>n>>opt(r) && n != 0u)) && SET_OR_FILL(SELF.compress, n) && SET_LEQ(SELF.ccRepMode, r,3u);},\
+       GET_IF(SELF.compress, SELF.compress, SELF.ccRepMode))
+OPTION(loops, "" , ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(DefaultUnfoundedCheck::ReasonStrategy,\
+       MAP("common"  , DefaultUnfoundedCheck::common_reason)  , MAP("shared", DefaultUnfoundedCheck::shared_reason), \
+       MAP("distinct", DefaultUnfoundedCheck::distinct_reason), MAP("no", DefaultUnfoundedCheck::only_reason))),\
+       "Configure learning of loop nogoods\n" \
+       "      %A: {common|distinct|shared|no}\n" \
+       "        common  : Create loop nogoods for atoms in an unfounded set\n" \
+       "        distinct: Create distinct loop nogood for each atom in an unfounded set\n" \
+       "        shared  : Create loop formula for a whole unfounded set\n" \
+       "        no      : Do not learn loop formulas\n", FUN(arg) {DefaultUnfoundedCheck::ReasonStrategy x; return arg>>x && SET(SELF.loopRep, (uint32)x);},\
+       GET(static_cast(SELF.loopRep)))
+GROUP_END(SELF)
+#undef CLASP_SOLVER_OPTIONS
+#undef SELF
+#endif
+
+//! Search-related options (see SolveParams).
+#if defined(CLASP_SEARCH_OPTIONS)
+#define SELF CLASP_SEARCH_OPTIONS
+GROUP_BEGIN(SELF)
+OPTION(partial_check, "", ARG(implicit("50")), "Configure partial stability tests\n" \
+       "      %A: 

[,] / Implicit: %I\n" \ + "

: Partial check skip percentage\n" \ + " : Init/update value for high bound ([0]=umax)", FUN(arg) {\ + uint32 p = 0; uint32 h = 0; \ + return (arg.off() || (arg>>p>>opt(h) && p)) && SET_LEQ(SELF.fwdCheck.highPct, p, 100u) && SET_OR_ZERO(SELF.fwdCheck.highStep, h);},\ + GET_IF(SELF.fwdCheck.highPct, SELF.fwdCheck.highPct, SELF.fwdCheck.highStep)) +OPTION(sign_def_disj, "", ARG(arg("")), "Default sign for atoms in disjunctions", STORE_LEQ(SELF.fwdCheck.signDef,3u), GET(SELF.fwdCheck.signDef)) +OPTION(rand_freq, "!", ARG(arg("

")), "Make random decisions with probability %A", FUN(arg) {\ + double f = 0.0; \ + return (arg.off() || arg>>f) && SET_R(SELF.randProb, (float)f, 0.0f, 1.0f);}, GET(SELF.randProb)) +OPTION(rand_prob, "!", ARG(implicit("10,100")), "Configure random probing (Implicit: %I)\n" \ + " %A: [,]\n" \ + " Run random passes with at most conflicts each", FUN(arg) {\ + uint32 n1 = 0; uint32 n2 = 100;\ + return (arg.off() || (arg>>n1>>opt(n2) && n1)) && SET_OR_FILL(SELF.randRuns, n1) && SET_OR_FILL(SELF.randConf, n2);},\ + GET_IF(SELF.randRuns, SELF.randRuns,SELF.randConf)) +#undef SELF +//! Options for configuring the restart strategy of a solver. +#define SELF CLASP_SEARCH_RESTART_OPTIONS +#if defined(NOTIFY_SUBGROUPS) +GROUP_BEGIN(SELF) +#endif +OPTION(restarts, "!,r", ARG(arg("")), "Configure restart policy\n" \ + " %A: ,[,][,]\n" \ + " F, : Run fixed sequence of conflicts\n" \ + " L, : Run Luby et al.'s sequence with unit length \n" \ + " x,,: Run geometric seq. of *(^i) conflicts ( >= 1.0)\n" \ + " +,,: Run arithmetic seq. of +(*i) conflicts ()\n"\ + " ...,: Repeat seq. every +j restarts ( != F)\n" \ + " D,,: Restart based on moving LBD average over last conflicts\n" \ + " Mavg(,LBD)* > avg(LBD)\n" \ + " use conflict level average if > 0 and avg(LBD) > \n"\ + " no|0 : Disable restarts", FUN(arg) { return ITE(arg.off(), (SELF.disable(),true), \ + arg>>SELF.sched && SET(SELF.dynRestart, uint32(SELF.sched.type == ScheduleStrategy::User)));}, GET(SELF.sched)) +OPTION(reset_restarts , "" , ARG(arg("0..2")->implicit("1")), "{0=Keep|1=Reset|2=Disable} restart seq. after model", STORE_LEQ(SELF.upRestart, 2u), GET(SELF.upRestart)) +OPTION(local_restarts , "" , ARG(flag()), "Use Ryvchin et al.'s local restarts", STORE_FLAG(SELF.cntLocal), GET(SELF.cntLocal)) +OPTION(counter_restarts, "" , ARG(arg("")), "Do a counter implication restart every restarts", STORE_OR_FILL(SELF.counterRestart),GET(SELF.counterRestart)) +OPTION(counter_bump , ",@2", ARG(arg("")) , "Set CIR bump factor to %A", STORE_OR_FILL(SELF.counterBump), GET(SELF.counterBump)) +OPTION(block_restarts , "" , ARG(arg("")), "Use glucose-style blocking restarts\n" \ + " %A: [,][,]\n" \ + " : Window size for moving average (0=disable blocking)\n" \ + " : Block restart if assignment > average * [1.4]\n" \ + " : Disable blocking for the first conflicts [10000]\n", FUN(arg) { \ + uint32 n = 0; double R = 0.0; uint32 x = 0;\ + return (arg.off() || (arg>>n>>opt(R = 1.4)>>opt(x = 10000) && n && R >= 1.0 && R <= 5.0))\ + && SET(SELF.blockWindow, n) && SET(SELF.blockScale, (float)R) && SET_OR_FILL(SELF.blockFirst, x);},\ + GET_IF(SELF.blockWindow, SELF.blockWindow, SELF.blockScale, SELF.blockFirst)) +OPTION(shuffle , "!" , ARG(arg(",")), "Shuffle problem after +(*i) restarts\n", FUN(arg) { uint32 n1 = 0; uint32 n2 = 0;\ + return (arg.off() || (arg>>n1>>opt(n2) && n1)) && SET_OR_FILL(SELF.shuffle, n1) && SET_OR_FILL(SELF.shuffleNext, n2);},\ + GET_IF(SELF.shuffle, SELF.shuffle, SELF.shuffleNext)) +#if defined(NOTIFY_SUBGROUPS) +GROUP_END(SELF) +#endif +#undef SELF +#undef CLASP_SEARCH_RESTART_OPTIONS +//! Options for configuring the deletion strategy of a solver. +#define SELF CLASP_SEARCH_REDUCE_OPTIONS +#if defined(NOTIFY_SUBGROUPS) +GROUP_BEGIN(SELF) +#endif +OPTION(deletion , "!,d", ARG_EXT(defaultsTo("basic,75,0")->state(Value::value_defaulted), DEFINE_ENUM_MAPPING(ReduceStrategy::Algorithm,\ + MAP("basic", ReduceStrategy::reduce_linear), MAP("sort", ReduceStrategy::reduce_stable),\ + MAP("ipSort", ReduceStrategy::reduce_sort) , MAP("ipHeap", ReduceStrategy::reduce_heap))), + "Configure deletion algorithm [%D]\n" \ + " %A: [,][,]\n" \ + " : Use {basic|sort|ipSort|ipHeap} algorithm\n" \ + " : Delete at most %% of nogoods on reduction [75]\n" \ + " : Use {0=activity|1=lbd|2=combined} nogood scores [0]\n" \ + " no : Disable nogood deletion", FUN(arg){\ + ReduceStrategy::Algorithm algo; uint32 n; uint32 sc;\ + return ITE(arg.off(), (SELF.disable(), true), arg>>algo>>opt(n = 75)>>opt(sc = 0)\ + && SET(SELF.strategy.algo, (uint32)algo) && SET_R(SELF.strategy.fReduce, n, 1, 100) && SET_LEQ(SELF.strategy.score, sc, 2));},\ + GET_IF(SELF.strategy.fReduce, (ReduceStrategy::Algorithm)SELF.strategy.algo, SELF.strategy.fReduce,SELF.strategy.score)) +OPTION(del_grow , "!", NO_ARG, "Configure size-based deletion policy\n" \ + " %A: [,][,] ( >= 1.0)\n" \ + " : Keep at most T = X*(^i) learnt nogoods with X being the\n"\ + " initial limit and i the number of times fired\n" \ + " : Stop growth once T > P* (0=no limit) [3.0]\n" \ + " : Set grow schedule () [grow on restart]", FUN(arg){ double f; double g; ScheduleStrategy sc = ScheduleStrategy::def();\ + return ITE(arg.off(), (SELF.growSched = ScheduleStrategy::none(), SELF.fGrow = 0.0f, true),\ + arg>>f>>opt(g = 3.0)>>opt(sc) && SET_R(SELF.fGrow, (float)f, 1.0f, FLT_MAX) && SET_R(SELF.fMax, (float)g, 0.0f, FLT_MAX)\ + && (sc.defaulted() || sc.type != ScheduleStrategy::User) && (SELF.growSched=sc, true));},\ + GET_FUN(str) { if (SELF.fGrow == 0.0f) str<")), "Configure conflict-based deletion policy\n" \ + " %A: ,... (see restarts)", FUN(arg){\ + return ITE(arg.off(), (SELF.cflSched=ScheduleStrategy::none()).disabled(), arg>>SELF.cflSched && SELF.cflSched.type != ScheduleStrategy::User);}, GET(SELF.cflSched)) +OPTION(del_init , "" , ARG(defaultsTo("3.0")->state(Value::value_defaulted)), "Configure initial deletion limit\n"\ + " %A: [,,] ( > 0)\n" \ + " : Set initial limit to P=estimated problem size/ [%D]\n" \ + " ,: Clamp initial limit to the range [,+]" , FUN(arg) { double f; uint32 lo = 10; uint32 hi = UINT32_MAX;\ + return arg>>f>>opt(lo)>>opt(hi) && f > 0.0 && (SELF.fInit = float(1.0 / f)) > 0 && SET_OR_FILL(SELF.initRange.lo, lo) && SET_OR_FILL(SELF.initRange.hi, (uint64(hi)+SELF.initRange.lo));},\ + GET_IF(SELF.fInit, 1.0/SELF.fInit, SELF.initRange.lo, SELF.initRange.hi - SELF.initRange.lo)) +OPTION(del_estimate, "", ARG(arg("0..3")->implicit("1")), "Use estimated problem complexity in limits", STORE_LEQ(SELF.strategy.estimate, 3u), GET(SELF.strategy.estimate)) +OPTION(del_max , "!", ARG(arg(",")), "Keep at most learnt nogoods taking up to MB", FUN(arg) { uint32 n = UINT32_MAX; uint32 mb = 0; \ + return (arg.off() || arg>>n>>opt(mb)) && SET_GEQ(SELF.maxRange, n, 1u) && SET(SELF.memMax, mb);}, GET(SELF.maxRange, SELF.memMax)) +OPTION(del_glue , "", NO_ARG, "Configure glue clause handling\n" \ + " %A: [,]\n" \ + " : Do not delete nogoods with LBD <= \n" \ + " : Count (0) or ignore (1) glue clauses in size limit [0]", FUN(arg) {uint32 lbd; uint32 m = 0; \ + return arg>>lbd>>opt(m) && SET(SELF.strategy.glue, lbd) && SET(SELF.strategy.noGlue, m);}, GET(SELF.strategy.glue, SELF.strategy.noGlue)) +OPTION(del_protect , "", ARG(arg("")), "Protect recently updated nogoods if new LBD <= ", STORE_LEQ(SELF.strategy.protect, uint32(Clasp::LBD_MAX)), GET(SELF.strategy.protect)) +OPTION(del_on_restart, "", ARG(arg("")->implicit("33")), "Delete %A%% of learnt nogoods on each restart", STORE_LEQ(SELF.strategy.fRestart, 100u), GET(SELF.strategy.fRestart)) +#if defined(NOTIFY_SUBGROUPS) +GROUP_END(SELF) +#endif +#undef SELF +#undef CLASP_SEARCH_REDUCE_OPTIONS +GROUP_END(CLASP_SEARCH_OPTIONS) +#undef CLASP_SEARCH_OPTIONS +#endif + +//! ASP-front-end options stored in an Clasp::Asp::LogicProgram::AspOptions object. +#if defined(CLASP_ASP_OPTIONS) +#define SELF CLASP_ASP_OPTIONS +GROUP_BEGIN(SELF) +OPTION(supp_models, ",@1" , ARG(flag()) , "Compute supported models", STORE_FLAG(SELF.suppMod), GET(SELF.suppMod)) +OPTION(no_ufs_check, ",@1" , ARG(flag()) , "Disable unfounded set check", STORE_FLAG(SELF.noSCC), GET(SELF.noSCC)) +OPTION(eq , "" , ARG(arg("")), "Configure equivalence preprocessing\n" \ + " Run for at most %A iterations (-1=run to fixpoint)", STORE_OR_FILL(SELF.iters), GET(SELF.iters)) +OPTION(backprop , "!,@1", ARG(flag()) , "Use backpropagation in ASP-preprocessing", STORE_FLAG(SELF.backprop), GET(SELF.backprop)) +OPTION(no_gamma , ",@1" , ARG(flag()) , "Do not add gamma rules for non-hcf disjunctions", STORE_FLAG(SELF.noGamma), GET(SELF.noGamma)) +OPTION(eq_dfs , ",@2" , ARG(flag()) , "Enable df-order in eq-preprocessing", STORE_FLAG(SELF.dfOrder), GET(SELF.dfOrder)) +OPTION(dlp_old_map, ",@3" , ARG(flag()) , "Enable old mapping for disjunctive LPs", STORE_FLAG(SELF.oldMap), GET(SELF.oldMap)) +OPTION(trans_ext , "!", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(Asp::LogicProgram::ExtendedRuleMode,\ + MAP("no" , Asp::LogicProgram::mode_native) , MAP("all" , Asp::LogicProgram::mode_transform),\ + MAP("choice", Asp::LogicProgram::mode_transform_choice), MAP("card", Asp::LogicProgram::mode_transform_card),\ + MAP("weight", Asp::LogicProgram::mode_transform_weight), MAP("scc" , Asp::LogicProgram::mode_transform_scc),\ + MAP("integ" , Asp::LogicProgram::mode_transform_integ) , MAP("dynamic", Asp::LogicProgram::mode_transform_dynamic))),\ + "Configure handling of extended rules\n"\ + " %A: {all|choice|card|weight|integ|dynamic}\n"\ + " all : Transform all extended rules to basic rules\n"\ + " choice : Transform choice rules, but keep cardinality and weight rules\n"\ + " card : Transform cardinality rules, but keep choice and weight rules\n"\ + " weight : Transform cardinality and weight rules, but keep choice rules\n"\ + " scc : Transform \"recursive\" cardinality and weight rules\n"\ + " integ : Transform cardinality integrity constraints\n"\ + " dynamic: Transform \"simple\" extended rules, but keep more complex ones", STORE(SELF.erMode), GET((Asp::LogicProgram::ExtendedRuleMode)SELF.erMode)) +GROUP_END(SELF) +#undef CLASP_ASP_OPTIONS +#undef SELF +#endif + +//! Options for the solving algorithm (see Clasp::SolveOptions) +#if defined(CLASP_SOLVE_OPTIONS) +#define SELF CLASP_SOLVE_OPTIONS +GROUP_BEGIN(SELF) +OPTION(solve_limit , "", ARG(arg("[,]")), "Stop search after conflicts or restarts\n", FUN(arg) {\ + uint32 n = UINT32_MAX; uint32 m = UINT32_MAX;\ + return ((arg.off() && arg.peek() != '0') || arg>>n>>opt(m)) && (SELF.limit=SolveLimits(n == UINT32_MAX ? UINT64_MAX : n, m == UINT32_MAX ? UINT64_MAX : m), true);},\ + GET((uint32)Range(0u,UINT32_MAX).clamp(SELF.limit.conflicts),(uint32)Range(0u,UINT32_MAX).clamp(SELF.limit.restarts))) +#if defined(WITH_THREADS) && WITH_THREADS == 1 +OPTION(parallel_mode, ",t", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(SolveOptions::Algorithm::SearchMode,\ + MAP("compete", SolveOptions::Algorithm::mode_compete), MAP("split", SolveOptions::Algorithm::mode_split))),\ + "Run parallel search with given number of threads\n" \ + " %A: [,]\n" \ + " : Number of threads to use in search\n"\ + " : Run competition or splitting based search [compete]\n", FUN(arg){\ + uint32 n; SolveOptions::Algorithm::SearchMode mode;\ + return arg>>n>>opt(mode = SolveOptions::Algorithm::mode_compete) && SET_R(SELF.algorithm.threads, n, 1u, 64u) && SET(SELF.algorithm.mode, mode);},\ + GET(SELF.algorithm.threads, (SolveOptions::Algorithm::SearchMode)SELF.algorithm.mode)) +OPTION(global_restarts, ",@1", ARG(implicit("5")->arg("")), "Configure global restart policy\n" \ + " %A: [,] / Implicit: %I\n" \ + " : Maximal number of global restarts (0=disable)\n" \ + " : Restart schedule [x,100,1.5] ()\n", FUN(arg) {\ + return ITE(arg.off(), (SELF.restarts = SolveOptions::GRestarts(), true), arg>>SELF.restarts.maxR>>opt(SELF.restarts.sched = ScheduleStrategy())\ + && SELF.restarts.maxR && SELF.restarts.sched.type != ScheduleStrategy::User);},\ + GET_IF(SELF.restarts.maxR, SELF.restarts.maxR, SELF.restarts.sched)) +OPTION(dist_mode , ",@2" , ARG(defaultsTo("0")->state(Value::value_defaulted)), "Use {0=global|1=thread} distribution", STORE_LEQ(SELF.distribute.mode,1u), GET(SELF.distribute.mode)) +OPTION(distribute, "!,@1", ARG_EXT(defaultsTo("conflict,4"), DEFINE_ENUM_MAPPING(Distributor::Policy::Types,\ + MAP("all", Distributor::Policy::all), MAP("short", Distributor::Policy::implicit),\ + MAP("conflict", Distributor::Policy::conflict), MAP("loop" , Distributor::Policy::loop))),\ + "Configure nogood distribution [%D]\n" \ + " %A: [,][,]\n" \ + " : Distribute {all|short|conflict|loop} nogoods\n" \ + " : Distribute only if LBD <= [4]\n" \ + " : Distribute only if size <= [-1]", FUN(arg) {\ + Distributor::Policy::Types type; uint32 lbd; uint32 size; + return ITE(arg.off(), (SELF.distribute.policy()=Distributor::Policy(0,0,0), true),\ + arg>>type>>opt(lbd = 4)>>opt(size = UINT32_MAX) && SET(SELF.distribute.types, (uint32)type) && SET(SELF.distribute.lbd, lbd) && SET_OR_FILL(SELF.distribute.size, size));},\ + GET_IF(SELF.distribute.types, (Distributor::Policy::Types)SELF.distribute.types, SELF.distribute.lbd,SELF.distribute.size)) +OPTION(integrate, ",@1", ARG_EXT(defaultsTo("gp")->state(Value::value_defaulted),\ + DEFINE_ENUM_MAPPING(SolveOptions::Integration::Filter, \ + MAP("all", SolveOptions::Integration::filter_no), MAP("gp", SolveOptions::Integration::filter_gp),\ + MAP("unsat", SolveOptions::Integration::filter_sat), MAP("active", SolveOptions::Integration::filter_heuristic))\ + DEFINE_ENUM_MAPPING(SolveOptions::Integration::Topology, \ + MAP("all" , SolveOptions::Integration::topo_all) , MAP("ring" , SolveOptions::Integration::topo_ring),\ + MAP("cube", SolveOptions::Integration::topo_cube), MAP("cubex", SolveOptions::Integration::topo_cubex))),\ + "Configure nogood integration [%D]\n" \ + " %A: [,][,]\n" \ + " : Add {all|unsat|gp(unsat wrt guiding path)|active} nogoods\n" \ + " : Always keep at least last integrated nogoods [1024]\n" \ + " : Accept nogoods from {all|ring|cube|cubex} peers [all]\n", FUN(arg) {\ + SolveOptions::Integration::Filter pick; uint32 n; SolveOptions::Integration::Topology topo; + return arg>>pick>>opt(n = 1024)>>opt(topo = SolveOptions::Integration::topo_all) && SET(SELF.integrate.filter, (uint32)pick) && SET_OR_FILL(SELF.integrate.grace, n) && SET(SELF.integrate.topo, (uint32)topo);},\ + GET((SolveOptions::Integration::Filter)SELF.integrate.filter, SELF.integrate.grace, (SolveOptions::Integration::Topology)SELF.integrate.topo)) +#endif +OPTION(enum_mode , ",e", ARG_EXT(defaultsTo("auto")->state(Value::value_defaulted), DEFINE_ENUM_MAPPING(SolveOptions::EnumType,\ + MAP("bt", SolveOptions::enum_bt), MAP("record", SolveOptions::enum_record), MAP("domRec", SolveOptions::enum_dom_record),\ + MAP("brave", SolveOptions::enum_brave), MAP("cautious", SolveOptions::enum_cautious), MAP("query", SolveOptions::enum_query),\ + MAP("auto", SolveOptions::enum_auto), MAP("user", SolveOptions::enum_user))),\ + "Configure enumeration algorithm [%D]\n" \ + " %A: {bt|record|brave|cautious|auto}\n" \ + " bt : Backtrack decision literals from solutions\n" \ + " record : Add nogoods for computed solutions\n" \ + " domRec : Add nogoods over true domain atoms\n" \ + " brave : Compute brave consequences (union of models)\n" \ + " cautious: Compute cautious consequences (intersection of models)\n" \ + " auto : Use bt for enumeration and record for optimization", STORE(SELF.enumMode), GET(SELF.enumMode)) +OPTION(project, "", ARG(implicit("6")), "Enable projective solution enumeration", STORE_LEQ(SELF.project, 7u), GET(SELF.project)) +OPTION(models, ",n", ARG(arg("")), "Compute at most %A models (0 for all)\n", STORE(SELF.numModels), GET(SELF.numModels)) +OPTION(opt_mode , "", ARG_EXT(arg(""), DEFINE_ENUM_MAPPING(MinimizeMode_t::Mode,\ + MAP("opt" , MinimizeMode_t::optimize), MAP("enum" , MinimizeMode_t::enumerate),\ + MAP("optN", MinimizeMode_t::enumOpt) , MAP("ignore", MinimizeMode_t::ignore))),\ + "Configure optimization algorithm\n"\ + " %A: {opt|enum|optN|ignore}\n" \ + " opt : Find optimal model\n" \ + " enum : Find models with costs <= initial bound\n" \ + " optN : Find optimum, then enumerate optimal models\n"\ + " ignore: Ignore optimize statements", STORE(SELF.optMode), GET((MinimizeMode_t::Mode)SELF.optMode)) +OPTION(opt_bound, "!" , ARG(arg("...")), "Initialize objective function(s)", FUN(arg) {\ + SumVec B; \ + return (arg.off() || arg>>B) && (SELF.optBound.swap(B), true);},\ + GET_IF(!SELF.optBound.empty(), SELF.optBound)) +OPTION(opt_sat , "" , ARG(flag()) , "Treat dimacs input as MaxSAT optimization problem", STORE(SELF.maxSat), GET(SELF.maxSat)) +GROUP_END(SELF) +#undef CLASP_SOLVE_OPTIONS +#undef SELF +#endif + +#undef GROUP_BEGIN +#undef GROUP_END +#undef OPTION +#undef NOTIFY_SUBGROUPS +#undef ARG +#undef ARG_EXT +#undef NO_ARG diff --git a/libclasp/clasp/cli/clasp_options.h b/libclasp/clasp/cli/clasp_options.h new file mode 100644 index 0000000..0446041 --- /dev/null +++ b/libclasp/clasp/cli/clasp_options.h @@ -0,0 +1,311 @@ +// +// Copyright (c) 2006-2013, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_CLI_CLASP_OPTIONS_H_INCLUDED +#define CLASP_CLI_CLASP_OPTIONS_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include +namespace ProgramOptions { +class OptionContext; +class OptionGroup; +class ParsedOptions; +} +/*! + * \file + * \brief Types and functions for processing command-line options. + */ +namespace Clasp { +//! Namespace for types and functions used by the command-line interface. +namespace Cli { + +/** + * \defgroup cli Cli + * \brief Types mainly relevant to the command-line interface. + * \ingroup facade + * @{ + */ + +class ClaspCliConfig; +//! Class for iterating over a set of configurations. +class ConfigIter { +public: + const char* name() const; + const char* base() const; + const char* args() const; + bool valid()const; + bool next(); +private: + friend class ClaspCliConfig; + ConfigIter(const char* x); + const char* base_; +}; +//! Valid configuration keys. +/*! + * \see clasp_cli_configs.inl + */ +enum ConfigKey { +#define CONFIG(id,k,c,s,p) config_##k, +#define CLASP_CLI_DEFAULT_CONFIGS config_default = 0, +#define CLASP_CLI_AUX_CONFIGS config_default_max_value, +#include + config_aux_max_value, + config_many, // default portfolio + config_max_value, + config_asp_default = config_tweety, + config_sat_default = config_trendy, + config_tester_default= config_tester, +}; +/*! + * \brief Class for storing/processing command-line options. + * + * Caveats (when using incrementally, e.g. from clingo): + * - supp-models: State Transition (yes<->no) not supported. + * - supp-models=yes is irreversible for a step + * because it enables possibly destructive simplifications + * and skips SCC-checking (i.e. new SCCs are silently discarded). + * - Nogoods learnt during supp-models=no are not tagged and + * hence can't simply be removed on transition to yes. + * . + * - stats: Stats level can only be increased. + * - A stats level once activated stays activated even if + * level is subsequently decreased via option. + * . + * - save-progress, sign-fix, opt-heuristic: No unset of previously set values. + * - Once set, signs are only unset if forgetOnStep includes sign. + * . + * - no-lookback: State Transition (yes<->no) not supported. + * - noLookback=yes is a destructive meta-option that disables lookback-options by changing their value + * - noLookback=no does not re-enable those options. + * . + */ +class ClaspCliConfig : public ClaspConfig { +public: + //! Returns defaults for the given problem type. + static const char* getDefaults(ProblemType f); + //! Returns the configuration with the given key. + static ConfigIter getConfig(ConfigKey key); + + ClaspCliConfig(); + ~ClaspCliConfig(); + // Base interface + virtual void prepare(SharedContext&); + virtual void reset(); + virtual Configuration* config(const char*); + + /*! + * \name Key-based low-level interface + * + * The functions in this group do not throw exceptions but + * signal logic errors via return values < 0. + * @{ */ + + typedef uint32 KeyType; + static const KeyType KEY_INVALID; //!< Invalid key used to signal errors. + static const KeyType KEY_ROOT; //!< Root key of a configuration, i.e. "." + static const KeyType KEY_TESTER; //!< Root key for tester options, i.e. "tester." + static const KeyType KEY_SOLVER; //!< Root key for (array of) solver options, i.e. "solver." + + //! Returns true if k is a leaf, i.e. has no subkeys. + static bool isLeafKey(KeyType k); + + //! Retrieves a handle to the specified key. + /*! + * \param key A valid handle to a key. + * \param name The name of the subkey to retrieve. + * \return + * - key, if name is 0 or empty. + * - KEY_INVALID, if name is not a subkey of key. + * - A handle to the subkey. + * . + */ + KeyType getKey(KeyType key, const char* name = 0) const; + + //! Retrieves a handle to the specified element of the given array key. + /*! + * \param arr A valid handle to an array. + * \param element The index of the element to retrieve. + * \return + * - A handle to the requested element, or + * - KEY_INVALID, if arr does not reference an array or element is out of bounds. + * . + */ + KeyType getArrKey(KeyType arr, unsigned element) const; + + //! Retrieves information about the specified key. + /*! + * \param key A valid handle to a key. + * \param[out] nSubkeys The number of subkeys of this key or 0 if key is a leaf. + * \param[out] arrLen If key is an array, the length of the array (can be 0). Otherwise, -1. + * \param[out] help A description of the key. + * \param[out] nValues The number of values the key currently has (0 or 1) or -1 if it can't have values. + * \note All out parameters are optional, i.e. can be 0. + * \return The number of out values or -1 if key is invalid. + */ + int getKeyInfo(KeyType key, int* nSubkeys = 0, int* arrLen = 0, const char** help = 0, int* nValues = 0) const; + + //! Returns the name of the i'th subkey of k or 0 if no such subkey exists. + const char* getSubkey(KeyType k, uint32 i) const; + + //! Creates and returns a string representation of the value of the given key. + /*! + * \param k A valid handle to a key. + * \param[out] value The current value of the key. + * \return The length of value or < 0 if k either has no value (-1) or an error occurred while writing the value (< -1). + */ + int getValue(KeyType k, std::string& value) const; + + //! Writes a null-terminated string representation of the value of the given key into the supplied buffer. + /*! + * \param k A valid handle to a key. + * \param[out] buffer The current value of the key. + * \param bufSize The size of buffer. + * \note Although the number returned can be larger than the bufSize, the function + * never writes more than bufSize bytes into the buffer. + */ + int getValue(KeyType k, char* buffer, std::size_t bufSize) const; + + //! Sets the option identified by the given key. + /*! + * \param key A valid handle to a key. + * \param value The value to set. + * \return + * - > 0: if the value was set. + * - = 0: if value is not a valid value for the given key. + * - < 0: f key does not accept a value (-1), or some error occurred (< -1). + * . + */ + int setValue(KeyType key, const char* value); + + //@} + + /*! + * \name String-based interface + * + * The functions in this group wrap the key-based functions and + * signal logic errors by throwing exceptions. + * @{ */ + //! Returns the value of the option identified by the given key. + std::string getValue(const char* key) const; + //! Returns true if the given key has an associated value. + bool hasValue(const char* key) const; + //! Sets the option identified by the given key. + bool setValue(const char* key, const char* value); + //@} + + //! Validates this configuration. + bool validate(); + + /*! + * \name App interface + * + * Functions for connecting a configuration with the ProgramOptions library. + * @{ */ + //! Adds all available options to root. + /*! + * Once options are added, root can be used with an option source (e.g. the command-line) + * to populate this object. + */ + void addOptions(ProgramOptions::OptionContext& root); + //! Adds options that are disabled by the options contained in parsed to parsed. + void addDisabled(ProgramOptions::ParsedOptions& parsed); + //! Applies the options in parsed and finalizes and validates this configuration. + bool finalize(const ProgramOptions::ParsedOptions& parsed, ProblemType type, bool applyDefaults); + //! Populates this configuration with the options given in [first, last) and finalizes it. + /*! + * \param [first, last) a range of options in argv format. + * \param t Problem type for which this configuration is created. Used to set defaults. + */ + template + bool setConfig(IT first, IT last, ProblemType t) { + RawConfig config("setConfig"); + while (first != last) { config.addArg(*first++); } + return setAppConfig(config, t); + } + //! Releases internal option objects needed for command-line style option processing. + /*! + * \note Subsequent calls to certain functions of this object (e.g. addOptions(), setConfig()) + * recreate the option objects if necessary. + */ + void releaseOptions(); + //@} +private: + static const uint8 mode_solver = 1u; + static const uint8 mode_tester = 2u; + static const uint8 mode_relaxed= 4u; + struct ParseContext; + struct OptIndex; + class ProgOption; + typedef ProgramOptions::OptionContext OptionContext; + typedef ProgramOptions::OptionGroup Options; + typedef SingleOwnerPtr OptionsPtr; + typedef PodVector::type ConfigVec; + typedef ProgramOptions::ParsedOptions ParsedOpts; + struct ScopedSet { + ScopedSet(ClaspCliConfig& s, uint8 mode, uint32 sId = 0); + ~ScopedSet(); + ClaspCliConfig* operator->()const { return self; } + ClaspCliConfig* self; + }; + struct RawConfig { + std::string raw; + explicit RawConfig(const char* name); + void addArg(const char* arg); + void addArg(const std::string& arg); + ConfigIter iterator() const { return ConfigIter(raw.data()); } + }; + // Operations on active config and solver + int setActive(int o, const char* value); + int getActive(int o, std::string* value, const char** desc, const char** opt) const; + int applyActive(int o, const char* setValue, std::string* getValue, const char** getDesc, const char** name); + // App interface impl + bool setAppConfig(const RawConfig& c, ProblemType t); + int setAppOpt(int o, const char* value); + bool setAppDefaults(UserConfig* active, uint32 sId, const ParsedOpts& exclude, ProblemType t); + bool finalizeAppConfig(UserConfig* active, const ParsedOpts& exclude, ProblemType t, bool defs); + const ParsedOpts& finalizeParsed(UserConfig* active, const ParsedOpts& parsed, ParsedOpts& exclude) const; + void createOptions(); + ProgOption* createOption(int o); + bool assignDefaults(const ParsedOpts&); + // Configurations + static bool appendConfig(std::string& to, const std::string& line); + static bool loadConfig(std::string& to, const char* fileName); + ConfigIter getConfig(uint8 key, std::string& tempMem); + bool setConfig(const ConfigIter& it, bool allowAppOpt, const ParsedOpts& exclude, ParsedOpts* out); + // helpers + bool isGenerator() const { return (cliMode & mode_tester) == 0; } + const UserConfig*active()const { return isGenerator() ? this : testerConfig(); } + UserConfig* active() { return isGenerator() ? this : testerConfig(); } + bool match(const char*& path, const char* what) const; + static OptIndex index_g; + OptionsPtr opts_; + std::string config_[2]; + bool initTester_; +}; +//! Validates the given solver configuration and throws an exception if invalid. +void validate(const char* ctx, const SolverParams& solver, const SolveParams& search); +//@} + +}} +#endif diff --git a/libclasp/clasp/cli/clasp_output.h b/libclasp/clasp/cli/clasp_output.h new file mode 100644 index 0000000..935e8d9 --- /dev/null +++ b/libclasp/clasp/cli/clasp_output.h @@ -0,0 +1,251 @@ +// +// Copyright (c) 2009-2013, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_CLI_OUTPUT_H_INCLUDED +#define CLASP_CLI_OUTPUT_H_INCLUDED +#include +#include +#include +#include +namespace Clasp { namespace Cli { +void format(const Clasp::BasicSolveEvent& ev, char* out, uint32 outSize); +void format(const Clasp::SolveTestEvent& ev, char* out, uint32 outSize); +#if WITH_THREADS +void format(const Clasp::mt::MessageEvent& ev, char* out, uint32 outSize); +#endif + +/*! + * \addtogroup cli + * @{ */ +/*! + * \brief Interface for printing status and input format dependent information, + * like models, optimization values, and summaries. + */ +class Output : public EventHandler { +public: + //! Supported levels for printing models, optimize values, and individual calls. + enum PrintLevel { + print_all = 0, //!< Print all models, optimize values, or calls. + print_best = 1, //!< Only print last model, optimize value, or call. + print_no = 2, //!< Do not print any models, optimize values, or calls. + }; + explicit Output(uint32 verb = 1); + virtual ~Output(); + //! Active verbosity level. + uint32 verbosity() const { return verbose_; } + //! Do not output any models? + bool quiet() const { return modelQ() == 2 && optQ() == 2; } + //! Print level for models. + int modelQ() const { return static_cast(quiet_[0]); } + //! Print level for optimization values. + int optQ() const { return static_cast(quiet_[1]); } + //! Print level for individual (solve) calls. + int callQ() const { return static_cast(quiet_[2]); } + + using EventHandler::setVerbosity; + void setVerbosity(uint32 verb); + void setModelQuiet(PrintLevel model); + void setOptQuiet(PrintLevel opt); + void setCallQuiet(PrintLevel call); + + //! Shall be called once on startup. + virtual void run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput) = 0; + //! Shall be called once on shutdown. + virtual void shutdown(const ClaspFacade::Summary& summary); + virtual void shutdown() = 0; + //! Handles ClaspFacade events by forwarding calls to startStep() and stopStep(). + virtual void onEvent(const Event& ev); + //! Checks quiet-levels and forwards to printModel() if appropriate. + virtual bool onModel(const Solver& s, const Model& m); + //! Checks quiet-levels and forwards to printLower() if appropriate. + virtual bool onUnsat(const Solver& s, const Model& m); + //! Shall print the given model. + virtual void printModel(const OutputTable& out, const Model& m, PrintLevel x) = 0; + //! Called on unsat - may print new info. + virtual void printUnsat(const OutputTable& out, const LowerBound* lower, const Model* prevModel); + //! A solving step has started. + virtual void startStep(const ClaspFacade&); + //! A solving step has stopped. + virtual void stopStep(const ClaspFacade::Summary& summary); + //! Shall print the given summary. + virtual void printSummary(const ClaspFacade::Summary& summary, bool final) = 0; + //! Shall print the given statistics. + virtual void printStatistics(const ClaspFacade::Summary& summary, bool final) = 0; +protected: + typedef std::pair OutPair; + typedef uintp UPtr; + typedef std::pair UPair; + const Model* getModel() const { return saved_.values ? &saved_ : 0; } + void saveModel(const Model& m); + void clearModel() { saved_.reset(); } + void printWitness(const OutputTable& out, const Model& m, UPtr data); + virtual UPtr doPrint(const OutPair& out, uintp data); + UPair numCons(const OutputTable& out, const Model& m) const; + bool stats(const ClaspFacade::Summary& summary) const; +private: + Output(const Output&); + Output& operator=(const Output&); + typedef const ClaspFacade::Summary* SumPtr ; + SumPtr summary_ ; // summary of last step + ValueVec vals_ ; // saved values from most recent model + SumVec costs_ ; // saved costs from most recent model + Model saved_ ; // most recent model + uint32 verbose_ ; // verbosity level + uint8 quiet_[3]; // quiet levels for models, optimize, calls +}; + +//! Prints models and solving statistics in Json-format to stdout. +class JsonOutput : public Output, private StatsVisitor { +public: + explicit JsonOutput(uint32 verb); + ~JsonOutput(); + virtual void run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput); + virtual void shutdown(const ClaspFacade::Summary& summary); + virtual void shutdown(); + virtual void printSummary(const ClaspFacade::Summary& summary, bool final); + virtual void printStatistics(const ClaspFacade::Summary& summary, bool final); +private: + virtual void startStep(const ClaspFacade&); + virtual void stopStep(const ClaspFacade::Summary& summary); + virtual bool visitThreads(Operation op); + virtual bool visitTester(Operation op); + virtual bool visitHccs(Operation op); + + virtual void visitThread(uint32, const SolverStats& stats); + virtual void visitHcc(uint32, const ProblemStats& p, const SolverStats& s); + virtual void visitLogicProgramStats(const Asp::LpStats& stats); + virtual void visitProblemStats(const ProblemStats& stats); + virtual void visitSolverStats(const SolverStats& stats); + virtual UPtr doPrint(const OutPair& out, UPtr data); + enum ObjType { type_object, type_array }; + void pushObject(const char* k = 0, ObjType t = type_object); + char popObject(); + void printKeyValue(const char* k, const char* v) ; + void printKeyValue(const char* k, uint64 v); + void printKeyValue(const char* k, uint32 v); + void printKeyValue(const char* k, double d); + void printString(const char* s, const char* sep); + void printKey(const char* k); + void printModel(const OutputTable& out, const Model& m, PrintLevel x); + void printCosts(const SumVec& costs, const char* name = "Costs"); + void printCons(const UPair& cons); + void printCoreStats(const CoreStats&); + void printExtStats(const ExtendedStats&, bool generator); + void printJumpStats(const JumpStats&); + void startModel(); + bool hasWitness() const { return !objStack_.empty() && *objStack_.rbegin() == '['; } + uint32 indent() const { return static_cast(objStack_.size() * 2); } + const char* open_; + std::string objStack_; +}; + +//! Default clasp format printer. +/*! + * Prints all output to stdout in given format: + * - format_asp prints in clasp's default asp format + * - format_aspcomp prints in in ASP competition format + * - format_sat09 prints in SAT-competition format + * - format_pb09 in PB-competition format + * . + * \see https://www.mat.unical.it/aspcomp2013/ + * \see http://www.satcompetition.org/2009/format-solvers2009.html + * \see http://www.cril.univ-artois.fr/PB09/solver_req.html + * + */ +class TextOutput : public Output, private StatsVisitor { +public: + //! Supported text formats. + enum Format { format_asp, format_aspcomp, format_sat09, format_pb09 }; + enum ResultStr { res_unknonw = 0, res_sat = 1, res_unsat = 2, res_opt = 3, num_str }; + enum CategoryKey { cat_comment, cat_value, cat_objective, cat_result, cat_value_term, cat_atom_name, cat_atom_var, num_cat }; + + const char* result[num_str]; //!< Default result strings. + const char* format[num_cat]; //!< Format strings. + + TextOutput(uint32 verbosity, Format f, const char* catAtom = 0, char ifs = ' '); + ~TextOutput(); + + //! Prints a (comment) message containing the given solver and input. + virtual void run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput); + virtual void shutdown(); + //! Prints the given model. + /*! + * Prints format[cat_value] followed by the elements of the model. Individual + * elements e are printed as format[cat_atom] and separated by the internal field separator. + */ + virtual void printModel(const OutputTable& out, const Model& m, PrintLevel x); + //! Prints the given lower bound and upper bounds that are known to be optimal. + virtual void printUnsat(const OutputTable& out, const LowerBound* lower, const Model* prevModel); + //! Called once a solving step has completed. + /*! + * Always prints "format[cat_result] result[s.result()]". + * Furthermore, if verbosity() > 0, prints a summary consisting of + * - the number of computed models m and whether the search space was exhausted + * - the number of enumerated models e if e != m + * - the state of any optimization and whether the last model was optimal + * - the state of consequence computation and whether the last model corresponded to the consequences + * - timing information + * . + */ + virtual void printSummary(const ClaspFacade::Summary& s , bool final); + virtual void printStatistics(const ClaspFacade::Summary& s, bool final); + //! Prints progress events (preprocessing/solving) if verbosity() > 1. + virtual void onEvent(const Event& ev); + //! A solving step has started. + virtual void startStep(const ClaspFacade&); + //! Prints a comment message. + void comment(uint32 v, const char* fmt, ...) const; +protected: + virtual bool visitThreads(Operation op); + virtual bool visitTester(Operation op); + + virtual void visitThread(uint32, const SolverStats& stats); + virtual void visitHcc(uint32, const ProblemStats& p, const SolverStats& s); + virtual void visitLogicProgramStats(const Asp::LpStats& stats); + virtual void visitProblemStats(const ProblemStats& stats); + virtual void visitSolverStats(const SolverStats& stats); + + virtual UPtr doPrint(const OutPair& out, UPtr data); + const char* fieldSeparator() const; + int printSep(CategoryKey c) const; + void printCosts(const SumVec&) const; + void printBounds(const SumVec& upper, const SumVec& lower) const; + void printStats(const SolverStats& stats) const; + void printJumps(const JumpStats&) const; + bool startSection(const char* n) const; + void startObject(const char* n, uint32 i) const; + void setState(uint32 state, uint32 verb, const char* st); + void printSolveProgress(const Event& ev); + void printValues(const OutputTable& out, const Model& m); + void printMeta(const OutputTable& out, const Model& m); +private: + typedef Clasp::Atomic_t::type EvType; + std::string fmt_; + double stTime_;// time on state enter + EvType ev_; // last event type + int width_; // output width + int line_; // lines to print until next separator + uint32 state_; // active state + char ifs_[2];// field separator + bool accu_; +}; +//@} + +}} +#endif diff --git a/libclasp/clasp/cli/clifwd.h b/libclasp/clasp/cli/clifwd.h new file mode 100644 index 0000000..a9650ab --- /dev/null +++ b/libclasp/clasp/cli/clifwd.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2013, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_CLI_FWD_H_INCLUDED +#define CLASP_CLI_FWD_H_INCLUDED +#include +namespace ProgramOptions { +class OptionContext; +class OptionGroup; +class ParsedOptions; +} +namespace Clasp { namespace Cli { +template bool store(const char* value, T& out); +bool isDisabled(const char* optValue); +}} +#endif diff --git a/libclasp/clasp/clingo.h b/libclasp/clasp/clingo.h new file mode 100644 index 0000000..94a27b5 --- /dev/null +++ b/libclasp/clasp/clingo.h @@ -0,0 +1,144 @@ +// +// Copyright (c) 2015-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_CLINGO_H_INCLUDED +#define CLASP_CLINGO_H_INCLUDED +/*! + * \file + * \brief Types for implementing theory propagation from clingo. + */ +#include +#include +namespace Clasp { + +/*! + * \defgroup clingo Clingo + * \brief Additional classes mainly used by clingo. + * \ingroup facade + * @{ */ + +//! Lock interface called by libclasp during (multi-threaded) theory propagation. +/*! + * The interface may be implemented by the application to lock + * certain global data structures. For example, in clingo, + * this interface wraps python's global interpreter lock. + */ +class ClingoPropagatorLock { +public: + virtual ~ClingoPropagatorLock(); + virtual void lock() = 0; + virtual void unlock() = 0; +}; + +//! Adaptor for a Potassco::AbstractPropagator. +/*! + * The class adapts a given Potassco::AbstractPropagator so that + * it is usable as a PostPropagator within libclasp. + * \note This class is meant to be a final class. + */ +class ClingoPropagator : public Clasp::PostPropagator { +public: + typedef Potassco::AbstractPropagator::ChangeList ChangeList; + typedef Clasp::PostPropagator::PropResult PPair; + + /*! + * If lock is not null, calls to cb are wrapped in a lock->lock()/lock->unlock() pair + */ + ClingoPropagator(const LitVec& watches, Potassco::AbstractPropagator& cb, ClingoPropagatorLock* lock = 0); + + // PostPropagator + virtual uint32 priority() const; + virtual bool init(Solver& s); + virtual bool propagateFixpoint(Clasp::Solver& s, Clasp::PostPropagator* ctx); + virtual PPair propagate(Solver&, Literal, uint32&); + virtual bool isModel(Solver& s); + virtual void reason(Solver&, Literal, LitVec&); + virtual void undoLevel(Solver& s); + virtual bool simplify(Solver& s, bool reinit); + virtual void destroy(Solver* s, bool detach); +private: + typedef LitVec::size_type size_t; + typedef Potassco::Lit_t Lit_t; + class Control; + enum State { state_ctrl = 1u, state_prop = 2u }; + struct ClauseTodo { + bool empty() const { return mem.empty(); } + void clear() { mem.clear(); } + LitVec mem; + ClauseRep clause; + uint32 flags; + }; + typedef PodVector::type TrailVec; + typedef PodVector::type ClauseDB; + typedef Potassco::AbstractPropagator* Callback; + typedef ClingoPropagatorLock* ClingoLock; + typedef const LitVec& Watches; + bool addClause(Solver& s, uint32 state); + void toClause(Solver& s, const Potassco::LitSpan& clause, Potassco::Clause_t prop); + Watches watches_; // set of watched literals + Callback call_; // actual theory propagator + ClingoLock lock_; // optional lock for protecting calls to theory propagator + TrailVec trail_; // assignment trail: watched literals that are true + VarVec undo_; // offsets into trail marking beginnings of decision levels + ClauseDB db_; // clauses added with flag static + ClauseTodo todo_; // active clause to be added (received from theory propagator) + size_t init_; // offset into watches separating old and newly added ones + size_t prop_; // offset into trail: literals [0, prop_) were propagated + size_t epoch_; // number of calls into callback + uint32 level_; // highest decision level in trail + Literal aux_; // max active literal +}; + +//! Initialization adaptor for a Potassco::AbstractPropagator. +/*! + * The class provides a function for registering watches for the propagator. + * Furthermore, it can be added to a clasp configuration so that + * a (suitably adapted) propagator is added to solvers that are attached to the configuration. + */ +class ClingoPropagatorInit : public ClaspConfig::Configurator { +public: + //! Creates a new adaptor. + /*! + * \param cb The (theory) propagator that should be added to solvers. + * \param lock An optional lock that should be applied during theory propagation. + */ + ClingoPropagatorInit(Potassco::AbstractPropagator& cb, ClingoPropagatorLock* lock = 0); + ~ClingoPropagatorInit(); + // base class + virtual void prepare(SharedContext&); + //! Adds a ClingoPropagator adapting the propagator() to s. + virtual bool addPost(Solver& s); + + // for clingo + //! Registers a watch for lit and returns encodeLit(lit). + Potassco::Lit_t addWatch(Literal lit); + + //! Returns the propagator that was given on construction. + Potassco::AbstractPropagator* propagator() const { return prop_; } +private: + ClingoPropagatorInit(const ClingoPropagatorInit&); + ClingoPropagatorInit& operator=(const ClingoPropagatorInit&); + Potassco::AbstractPropagator* prop_; + ClingoPropagatorLock* lock_; + LitVec watches_; + VarVec seen_; +}; +///@} +} +#endif diff --git a/libclasp/clasp/constraint.h b/libclasp/clasp/constraint.h new file mode 100644 index 0000000..c46fe57 --- /dev/null +++ b/libclasp/clasp/constraint.h @@ -0,0 +1,584 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_CONSTRAINT_H_INCLUDED +#define CLASP_CONSTRAINT_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include // bits stuff +#include + +/*! + * \file + * \brief Defines the base classes for boolean constraints. + */ +namespace Clasp { + +class SharedContext; +class Solver; +class ClauseHead; +struct CCMinRecursive; + +/** + * \defgroup constraint Constraints + * \brief Boolean Constraints, post propagators, and related types. + * @{ */ + +//! Constraint types distinguished by a Solver. +struct Constraint_t { + enum Type { + Static = 0, //!< An unremovable constraint (e.g. a problem constraint). + Conflict = 1, //!< A removable constraint derived from conflict analysis. + Loop = 2, //!< A removable constraint derived from unfounded set checking. + Other = 3, //!< A removable constraint learnt by some other means. + Type__max = Other + }; + struct Set { + Set() : m(0) {} + bool inSet(Type t) const { return (m & (uint32(1)<[priority_class_simple, priority_class_general) + * - class_general: post propagators that are non-deterministic or those that are not limited to extending + * the current decision level shall have a priority of priority_class_general. They are called in FIFO order + * after \b all simple post propagators have reached a fixpoint. + * + * \note There are currently three reserved priority values, namely + * - priority_reserved_msg for message and termination handler (if any), + * - priority_reserved_ufs for the default unfounded set checker (if any), + * - and priority_reserved_look for the default lookahead operator (if any). + * . + */ +class PostPropagator : public Constraint { +public: + PostPropagator(); + virtual ~PostPropagator(); + using Constraint::propagate; // Enable overloading! + + PostPropagator* next; // main propagation lists of post propagators + //! Default priorities for post propagators. + enum Priority { + priority_class_simple = 0, //!< Starting priority of simple post propagators. + priority_reserved_msg = 0, //!< Reserved priority for message/termination handlers (if any). + priority_reserved_ufs = 10, //!< Reserved priority for the default unfounded set checker (if any). + priority_reserved_look = 1023, //!< Reserved priority for the default lookahead operator (if any). + priority_class_general = 1024, //!< Priortiy of extended post propagators. + }; + + //! Shall return a value representing the priority of this propagator. + /*! + * The priority is used to order sequences of post propagators and to + * classify post propagators w.r.t the classes: class_simple and class_general. + * \note See class description for an overview of the two priority classes. + */ + virtual uint32 priority() const = 0; + + //! Called during initialization of s. + /*! + * \note During initialization a post propagator may assign variables + * but it must not yet propagate them. + */ + virtual bool init(Solver& s); + + //! Shall enqueue and propagate new assignments implied by this propagator. + /*! + * This function shall enqueue and propagate all assignments currently implied by + * this propagator until a fixpoint is reached w.r.t this post propagator or + * a conflict is detected. + * + * \pre The assignment is fully propagated w.r.t any previous post propagator. + * \param s The solver in which this post propagator is used. + * \param ctx The post propagator from which this post propagator is called or + * 0 if no other post propagator is currently active. + * \post s.queueSize() == 0 || s.hasConflict() + * \return false if propagation led to conflict, true otherwise + * + * \note + * The function shall not call Solver::propagate() + * or any other function that would result in a recursive chain + * of propagate() calls. On the other hand, it shall call + * Solver::propagateUntil(this) after enqueuing any new assignments + * to initiate propagation up to this propagator. + * + * Typically, propagateFixpoint() should implemet a loop like this: + * \code + * for (;;) { + * if (!assign_newly_implied_literals(s)){ return false; } + * if (s.queueSize() == 0) { return true; } + * if (!s.propagateUntil(this)) { return false; } + * } + * \endcode + */ + virtual bool propagateFixpoint(Solver& s, PostPropagator* ctx) = 0; + + //! Aborts an active propagation operation. + /*! + * The function reset() is called whenever propagation on the + * current decision level is stopped before a fixpoint is reached. + * In particular, a solver calls reset() when a conflict is detected + * during propagation. + * + * \note The default implementation is a noop. + */ + virtual void reset(); + + //! Is the current total assignment a model? + /*! + * \pre The assignment is total and not conflicting. + * \return + * - true if the assignment is a model w.r.t this post propagator + * - false otherwise + * \post If the function returned true: s.numFreeVars() == 0 && !s.hasConflict(). + * If the function returned false: s.numFreeVars() > 0 || s.hasConflict(). + * \note The default implementation returns Constraint::valid(s); + */ + virtual bool isModel(Solver& s); +protected: + //! Calls reset on post propagators following this. + void cancelPropagation(); + + //! PostPropagators are not clonable by default. + Constraint* cloneAttach(Solver&) { return 0; } + // Constraint interface - noops + PropResult propagate(Solver&, Literal, uint32&); + void reason(Solver&, Literal, LitVec& ); +private: + PostPropagator(const PostPropagator&); + PostPropagator& operator=(const PostPropagator&); +}; + +//! A special post propagator used to handle messages and signals. +class MessageHandler : public PostPropagator { +public: + MessageHandler(); + virtual bool handleMessages() = 0; + virtual uint32 priority()const { return PostPropagator::priority_reserved_msg; } + virtual bool propagateFixpoint(Solver&, PostPropagator*) { return handleMessages(); } +}; + +//! An intrusive list of post propagators ordered by priority. +/*! + * Propagators in the list are owned by the list. + */ +class PropagatorList { +public: + PropagatorList(); + ~PropagatorList(); + void add(PostPropagator* p); + void remove(PostPropagator* p); + void clear(); + PostPropagator* find(uint32 prio) const; + PostPropagator*const* head() const { return &head_; } + PostPropagator** head() { return &head_; } +private: + PropagatorList(const PropagatorList&); + PropagatorList& operator=(const PropagatorList&); + PostPropagator* head_;// head of pp-list +}; +//@} + +/** +* \addtogroup constraint +* @{ */ + +//! Stores a reference to the constraint that implied a literal. +/*! + * Stores a reference to the constraint that implied a certain literal or + * null if the literal has no antecedent (i.e. is a decision literal or a top-level fact). + * + * \note + * The constraint that implied a literal can have three different representations: + * - it can be a single literal (binary clause constraint) + * - it can be two literals (ternary clause constraint) + * - it can be a pointer to a constraint (generic constraint) + * . + * + * \par Implementation: + * + * The class stores all three representations in one tagged 64-bit integer, i.e. + * from the 64-bits the 2 LSBs encode the type stored: + * - 00: Pointer to constraint + * - 01: ternary constraint (i.e. two literals stored in the remaining 62 bits). + * - 10: binary constraint (i.e. one literal stored in the highest 31 bits) + * . + */ +class Antecedent { +public: + enum Type { Generic = 0, Ternary = 1, Binary = 2}; + //! Creates a null Antecedent. + /*! + * \post: isNull() == true && type == Generic + */ + Antecedent() : data_(0) {} + + //! Creates an Antecedent from the literal p. + /*! + * \post: type() == Binary && firstLiteral() == p + */ + Antecedent(const Literal& p) { + // first lit is stored in high dword + data_ = (((uint64)p.id()) << 33) + Binary; + assert(type() == Binary && firstLiteral() == p); + } + + //! Creates an Antecedent from the literals p and q. + /*! + * \post type() == Ternary && firstLiteral() == p && secondLiteral() == q + */ + Antecedent(const Literal& p, const Literal& q) { + // first lit is stored in high dword + // second lit is stored in low dword + data_ = (((uint64)p.id()) << 33) + (((uint64)q.id()) << 2) + Ternary; + assert(type() == Ternary && firstLiteral() == p && secondLiteral() == q); + } + + //! Creates an Antecedent from the Constraint con. + /*! + * \post type() == Generic && constraint() == con + */ + Antecedent(Constraint* con) : data_((uintp)con) { + static_assert(sizeof(Constraint*) <= sizeof(uint64), "unsupported pointer size"); + assert(type() == Generic && constraint() == con); + } + + //! Returns true if this antecedent does not refer to any constraint. + bool isNull() const { return data_ == 0; } + //! Returns the antecedent's type. + Type type() const { return Type( data_ & 3 ); } + //! Returns true if the antecedent is a learnt nogood. + bool learnt() const { return data_ && (data_ & 3u) == 0 && constraint()->type() != Constraint_t::Static; } + + //! Extracts the constraint-pointer stored in this object. + /*! + * \pre type() == Generic + */ + Constraint* constraint() const { + assert(type() == Generic); + return (Constraint*)(uintp)data_; + } + + //! Extracts the first literal stored in this object. + /*! + * \pre type() != Generic + */ + Literal firstLiteral() const { + assert(type() != Generic); + return Literal::fromId(static_cast(data_ >> 33)); + } + + //! Extracts the second literal stored in this object. + /*! + * \pre type() == Ternary + */ + Literal secondLiteral() const { + assert(type() == Ternary); + return Literal::fromId( static_cast(data_>>1) >> 1 ); + } + + //! Returns the reason for p. + /*! + * \pre !isNull() + */ + void reason(Solver& s, Literal p, LitVec& lits) const { + assert(!isNull()); + Type t = type(); + if (t == Generic) { + constraint()->reason(s, p, lits); + return; + } + lits.push_back(firstLiteral()); + if (t == Ternary) { lits.push_back(secondLiteral()); } + } + template + bool minimize(S& s, Literal p, CCMinRecursive* rec) const { + assert(!isNull()); + Type t = type(); + if (t == Generic) { + return constraint()->minimize(s, p, rec); + } + return s.ccMinimize(firstLiteral(), rec) && (t != Ternary || s.ccMinimize(secondLiteral(), rec)); + } + + //! Returns true iff the antecedent refers to the constraint con. + bool operator==(const Constraint* con) const { + return static_cast(data_) == reinterpret_cast(con); + } + uint64 asUint() const { return data_; } + uint64& asUint() { return data_; } +private: + uint64 data_; +}; + +enum { LBD_MAX = 127u, ACT_MAX = (1u << 20) - 1 }; +//! Type storing a constraint's activity. +struct ConstraintScore { + typedef ConstraintScore Score; + enum { LBD_SHIFT = 20, BMP_BIT = 27, BITS_USED = 28, LBD_MASK = LBD_MAX<> LBD_SHIFT) : uint32(LBD_MAX); } + bool hasLbd() const { return (rep & LBD_MASK) != 0; } + bool bumped() const { return test_bit(rep, BMP_BIT); } + void bumpActivity() { if (activity() < uint32(ACT_MAX)) ++rep; } + void bumpLbd(uint32 x) { if (x < lbd()) { rep &= ~uint32(LBD_MASK); rep |= (x << LBD_SHIFT) | bit_mask(BMP_BIT); } } + void clearBumped() { store_clear_bit(rep, BMP_BIT); } + void reduce() { clearBumped(); if (uint32 a = activity()) { rep &= ~uint32(ACT_MAX); rep |= (a>>1); } } + void assign(Score o) { rep &= ~uint32(BITS_MASK); rep |= (o.rep & BITS_MASK); } + uint32 rep; +}; +inline ConstraintScore makeScore(uint32 act = 0, uint32 lbd = 0) { + ConstraintScore sc = {0}; sc.reset(act, lbd); + return sc; +} +//! Type storing meta information about a constraint. +class ConstraintInfo : private ConstraintScore { +public: + typedef ConstraintInfo Info; + typedef ConstraintScore Score; + ConstraintInfo(ConstraintType t = Constraint_t::Static) { + static_assert(ConstraintScore::BITS_USED <= 28, "invalid score"); + rep = uint32(t) << TYPE_SHIFT; + } + using ConstraintScore::lbd; + using ConstraintScore::activity; + ConstraintType type() const { return static_cast( (rep & uint32(TYPE_MASK)) >> TYPE_SHIFT ); } + bool tagged() const { return test_bit(rep, TAG_BIT); } + bool aux() const { return tagged() || test_bit(rep, AUX_BIT); } + bool learnt() const { return type() != Constraint_t::Static; } + const Score& score() const { return *this; } + Score& score() { return *this; } + + Info& setType(ConstraintType t) { rep &= ~uint32(TYPE_MASK); rep |= (uint32(t) << TYPE_SHIFT); return *this; } + Info& setScore(Score sc) { assign(sc); return *this; } + Info& setActivity(uint32 a) { assign(makeScore(a, lbd())); return *this; } + Info& setLbd(uint32 lbd) { assign(makeScore(activity(), lbd)); return *this; } + Info& setTagged(bool b) { if (test_bit(rep, TAG_BIT) != b) store_toggle_bit(rep, TAG_BIT); return *this; } + Info& setAux(bool b) { if (test_bit(rep, AUX_BIT) != b) store_toggle_bit(rep, AUX_BIT); return *this; } +private: + enum { TYPE_SHIFT = 28, AUX_BIT = 30, TAG_BIT = 31, TYPE_MASK = (3u << TYPE_SHIFT) }; +}; +//@} + +/** +* \defgroup shared_con Shared +* \brief %Constraint data that can safely be shared between solvers. +* \ingroup constraint +*/ + +} +#endif diff --git a/libclasp/clasp/dependency_graph.h b/libclasp/clasp/dependency_graph.h new file mode 100644 index 0000000..90c04e8 --- /dev/null +++ b/libclasp/clasp/dependency_graph.h @@ -0,0 +1,472 @@ +// +// Copyright (c) 2010-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_DEPENDENCY_GRAPH_H_INCLUDED +#define CLASP_DEPENDENCY_GRAPH_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include +namespace Clasp { +class Solver; +class SharedContext; +struct SolverStats; +//! Event type used to signal a (partial) check in disjunctive solving. +struct SolveTestEvent : SolveEvent { + SolveTestEvent(const Solver& s, uint32 hcc, bool partial); + int result; //!< -1: before test, 0: unstable, 1: stable + uint32 hcc :31;//!< hcc under test + uint32 partial : 1;//!< partial test? + uint64 confDelta; //!< conflicts before test + uint64 choiceDelta;//!< choices before test + double time; //!< time for test + + uint64 conflicts() const; + uint64 choices() const; +}; +struct LoopReason_t { + enum Type { Explicit = 0u, Implicit = 1u, }; +}; +typedef LoopReason_t::Type LoopType; + +namespace Asp { +//! (Positive) Body-Atom-Dependency Graph. +/*! + * \ingroup shared_con + * + * Represents the PBADG of a logic program. Once initialized, the + * PBDAG is static and read-only and thus can be shared between multiple solvers. + * + * \note Initialization is *not* thread-safe, i.e. must be done only once by one thread. + */ +class PrgDepGraph { +public: + enum NonHcfMapType { + map_old = 0, + map_new = 1 + }; + explicit PrgDepGraph(NonHcfMapType m = map_old); + ~PrgDepGraph(); + typedef uint32 NodeId; + //! Type for storing a non head-cycle-free component of a disjunctive program. + class NonHcfComponent { + public: + explicit NonHcfComponent(uint32 id, const PrgDepGraph& dep, SharedContext& generator, Configuration* c, uint32 scc, const VarVec& atoms, const VarVec& bodies); + ~NonHcfComponent(); + void assumptionsFromAssignment(const Solver& generator, LitVec& assumptionsOut) const; + bool test(const Solver& generator, const LitVec& assumptions, VarVec& unfoundedOut) const; + bool simplify(const Solver& generator) const; + const SharedContext& ctx() const { return *prg_; } + void update(const SharedContext& generator); + uint32 id() const { return id_; } + uint32 scc() const { return scc_; } + private: + friend class PrgDepGraph; + NonHcfComponent(const NonHcfComponent&); + NonHcfComponent& operator=(const NonHcfComponent&); + class ComponentMap; + const PrgDepGraph* dep_; + SharedContext* prg_; + ComponentMap* comp_; + uint32 id_; + uint32 scc_; + }; + //! A class for storing statistics on checking of non head-cycle-free components. + class NonHcfStats { + public: + NonHcfStats(PrgDepGraph& g, uint32 level, bool inc); + ~NonHcfStats(); + void accept(StatsVisitor& out, bool final) const; + void startStep(uint32 statsLevel); + void endStep(); + void addTo(StatsMap& problem, StatsMap& solving, StatsMap* accu) const; + private: + friend class PrgDepGraph; + void addHcc(const NonHcfComponent&); + void removeHcc(const NonHcfComponent&); + NonHcfStats(const NonHcfStats&); + NonHcfStats& operator=(const NonHcfStats&); + struct Data; + PrgDepGraph* graph_; + Data* data_; + }; + typedef PodVector::type ComponentVec; + typedef ComponentVec::const_iterator NonHcfIter; + //! Base type for nodes. + struct Node { + Node(Literal l = Literal(0, false), uint32 sc = PrgNode::noScc) + : lit(l), scc(sc), data(0), adj_(0), sep_(0) {} + Literal lit; // literal of this node + uint32 scc : 28;// scc of this node + uint32 data : 4;// additional atom/body data + NodeId* adj_; // list of adjacent nodes + NodeId* sep_; // separates successor/predecessor nodes + }; + //! An atom node. + /*! + * The PBDAG stores a node of type AtomNode for each non-trivially connected atom. + * The predecessors of an AtomNode are the bodies that define the atom. Its successors + * are those bodies from the same SCC that contain the atom positively. + */ + struct AtomNode : public Node { + enum Property { property_in_choice = 1u, property_in_disj = 2u, property_in_ext = 4u, property_in_non_hcf = 8u }; + AtomNode() {} + void set(Property p) { data |= (uint32)p; } + void setProperties(uint32 f) { assert(f < 8); data |= f; } + //! Contained in the head of a choice rule? + bool inChoice() const { return (data & property_in_choice) != 0; } + //! Contained in the head of a non-hcf disjunctive rule? + bool inDisjunctive()const { return (data & property_in_disj) != 0; } + //! Contained in an extended body? + bool inExtended() const { return (data& property_in_ext) != 0; } + //! Contained in a non-hcf SCC? + bool inNonHcf() const { return (data & property_in_non_hcf) != 0; } + //! Bodies (i.e. predecessors): bodies from other SCCs precede those from same SCC. + const NodeId* bodies_begin() const { return adj_; } + const NodeId* bodies_end() const { return sep_; } + NodeId body(uint32 i) const { return bodies_begin()[i]; } + //! Successors from same SCC [B1,...Bn, idMax]. + /*! + * \note If extended() is true, the atom is adjacent to some extended body. + * In that case, the returned list looks like this: + * [Bn1, ..., Bnj, idMax, Bext1, pos1, ..., Bextn, posn, idMax], where + * each Bni is a normal body, each Bexti is an extended body and posi is the + * position of this atom in Bexti. + */ + const NodeId* succs() const { return sep_; } + //! Calls the given function object p once for each body containing this atom. + template + void visitSuccessors(const P& p) const { + const NodeId* s = succs(); + for (; *s != idMax; ++s) { p(*s); } + if (inExtended()) { + for (++s; *s != idMax; s += 2) { p(*s, *(s+1)); } + } + } + }; + enum { sentinel_atom = 0u }; + + //! A body node. + /*! + * The PBDAG stores a node of type BodyNode for each body that defines + * a non-trivially connected atom. + * The predecessors of a BodyNode are the body's subgoals. + * Its successors are the heads that are defined by the body. + * \note Normal bodies only store the positive subgoals from the same SCC, while + * extended rule bodies store all subgoals. In the latter case, the positive subgoals from + * the same SCC are stored as AtomNodes. All other subgoals are stored as literals. + */ + struct BodyNode : public Node { + enum Flag { flag_has_bound = 1u, flag_has_weights = 2u, flag_has_delta = 4u, flag_seen = 8u }; + explicit BodyNode(PrgBody* b, uint32 scc) : Node(b->literal(), scc) { + if (scc == PrgNode::noScc || b->type() == Body_t::Normal) { + data = 0; + } + else if (b->type() == Body_t::Count){ data = flag_has_bound; } + else if (b->type() == Body_t::Sum) { data = flag_has_bound | flag_has_weights; } + else { assert("UNKNOWN BODY TYPE!\n"); } + } + bool seen() const { return (data & flag_seen) != 0; } + void seen(bool b) { if (b) data |= flag_seen; else data &= ~uint32(flag_seen); } + + //! Heads (i.e. successors): atoms from same SCC precede those from other SCCs. + /*! + * \note Disjunctive heads are stored in flattened atom-lists, where the + * lists are terminated on both ends with the special sentinal atom 0. + * E.g. given + * x :- B. + * y :- B. + * a|b:- B. + * a|c:- B. + * would result in: [x,y,0,a,b,0,0,a,c,0] + */ + const NodeId* heads_begin() const { return adj_; } + const NodeId* heads_end() const { return sep_ - extended(); } + //! Any disjunctive heads? + bool delta() const { return (data & flag_has_delta) != 0; } + //! Predecessors from same SCC [a1,...an, idMax]. + /*! + * \note If extended() is true, the body stores all its subgoals and preds looks + * like this: [a1, [w1], ..., aj, [wj], idMax, l1, [w1], ..., lk, [wk], idMax], where + * each ai is an atom from the same SCC, each li is a literal of a subgoal from + * other SCCs and wi is an optional weight (only for weight rules). + */ + const NodeId* preds() const { assert(scc != PrgNode::noScc); return sep_; } + //! Returns idx of atomId in preds. + uint32 get_pred_idx(NodeId atomId) const { + const uint32 inc = pred_inc(); + uint32 idx = 0; + for (const NodeId* x = preds(); *x != idMax; x += inc, ++idx) { + if (*x == atomId) return idx; + } + return idMax; + } + NodeId get_pred(uint32 idx) const { return *(preds() + (idx*pred_inc())); } + //! Increment to jump from one pred to the next. + uint32 pred_inc() const { return 1 + sum(); } + //! Weight of ith subgoal. + /*! + * \pre i in [0, num_preds()) + */ + uint32 pred_weight(uint32 i, bool ext) const { + return !sum() + ? 1 + : *(preds() + (i*pred_inc()) + (1+uint32(ext))); + } + //! Number of predecessors (counting external subgoals). + uint32 num_preds() const { + if (scc == PrgNode::noScc) return 0; + uint32 p = 0; + const NodeId* x = preds(); + const uint32 inc = pred_inc(); + for (; *x != idMax; x += inc) { ++p; } + x += extended(); + for (; *x != idMax; x += inc) { ++p; } + return p; + } + //! Is the body an extended body? + bool extended()const { return (data & flag_has_bound) != 0u; } + //! Is the body a sum body? + bool sum() const { return (data & flag_has_weights) != 0u; } + //! Bound of extended body. + weight_t ext_bound() const { return sep_[-1]; } + }; + //! Adds SCCs to the graph. + /*! + * \param prg The logic program for which the dependency graph is to be created. + * \param sccAtoms Atoms of the logic program that are strongly connected. + * \param nonHcfs Sorted list of non-hcf sccs + */ + void addSccs(LogicProgram& prg, const AtomList& sccAtoms, const NonHcfSet& nonHcfs); + + //! Removes inactive non-hcfs. + void simplify(const Solver& s); + //! Number of atoms in graph. + uint32 numAtoms() const { return (uint32)atoms_.size(); } + //! Number of bodies in graph. + uint32 numBodies()const { return (uint32)bodies_.size(); } + //! Sum of atoms and bodies. + uint32 nodes() const { return numAtoms()+numBodies(); } + + //! Returns AtomNode of atom with given id. + const AtomNode& getAtom(NodeId atomId) const { + assert(atomId < atoms_.size()); + return atoms_[atomId]; + } + NodeId id(const AtomNode& n) const { return static_cast(&n - &atoms_[0]); } + //! Returns BodyNode of body with given id. + const BodyNode& getBody(NodeId bodyId) const { + assert(bodyId < bodies_.size()); + return bodies_[bodyId]; + } + //! Calls the given function object p once for each body-literal. + template + void visitBodyLiterals(const BodyNode& n, const P& p) const { + const NodeId* x = n.preds(); + const uint32 inc = n.pred_inc(); + uint32 i = 0; + for (; *x != idMax; x += inc, ++i) { p(getAtom(*x).lit, i, false); } + x += n.extended(); + for (; *x != idMax; x += inc, ++i) { p(Literal::fromRep(*x), i, true); } + } + NonHcfIter nonHcfBegin() const { return components_.begin(); } + NonHcfIter nonHcfEnd() const { return components_.end(); } + uint32 numNonHcfs() const { return (uint32)components_.size(); } + NonHcfStats* nonHcfStats() const { return stats_; } + NonHcfStats* enableNonHcfStats(uint32 level, bool incremental); +private: + typedef PodVector::type AtomVec; + typedef PodVector::type BodyVec; + PrgDepGraph(const PrgDepGraph&); + PrgDepGraph& operator=(const PrgDepGraph&); + inline bool relevantPrgAtom(const Solver& s, PrgAtom* a) const; + inline bool relevantPrgBody(const Solver& s, PrgBody* b) const; + NonHcfMapType nonHcfMapType() const { return static_cast(mapType_); } + NodeId createBody(PrgBody* b, uint32 bScc); + NodeId createAtom(Literal lit, uint32 aScc); + NodeId addBody(const LogicProgram& prg, PrgBody*); + NodeId addDisj(const LogicProgram& prg, PrgDisj*); + uint32 addHeads(const LogicProgram& prg, PrgBody*, VarVec& atoms) const; + uint32 getAtoms(const LogicProgram& prg, PrgDisj*, VarVec& atoms) const; + void addPreds(const LogicProgram& prg, PrgBody*, uint32 bScc, VarVec& preds) const; + void initBody(uint32 id, const VarVec& preds, const VarVec& atHeads); + void initAtom(uint32 id, uint32 prop, const VarVec& adj, uint32 preds); + void addNonHcf(uint32 id, SharedContext& ctx, Configuration* c, uint32 scc); + AtomVec atoms_; + BodyVec bodies_; + ComponentVec components_; + NonHcfStats* stats_; + uint32 seenComponents_ : 31; + uint32 mapType_ : 1; +}; +} // namespace Asp + +//! External dependency graph. +/*! + * \ingroup shared_con + * + * Represents external dependencies explicitly given by the user. + * For example, via aspif edge directives or the graph block in extended dimacs format. + * \note Initialization is *not* thread-safe, i.e. must be done only once by one thread. + */ +class ExtDepGraph { +public: + struct Arc { + Literal lit; + uint32 node[2]; + uint32 tail() const { return node[0]; } + uint32 head() const { return node[1]; } + static Arc create(Literal x, uint32 nodeX, uint32 nodeY) { Arc a = {x, {nodeX, nodeY}}; return a; } + }; + struct Inv { + uint32 tail() const { return rep >> 1; } + Literal lit; + uint32 rep; + }; + template + struct CmpArc { + bool operator()(const Arc& lhs, uint32 n) const { return lhs.node[x] < n; } + bool operator()(uint32 n, const Arc& rhs) const { return n < rhs.node[x]; } + bool operator()(const Arc& lhs, const Arc& rhs) const { + return lhs.node[x] < rhs.node[x] + || (lhs.node[x] == rhs.node[x] && lhs.node[1-x] < rhs.node[1-x]); + } + }; + explicit ExtDepGraph(uint32 numNodeGuess = 0); + ~ExtDepGraph(); + void addEdge(Literal lit, uint32 startNode, uint32 endNode); + void update(); + uint32 finalize(SharedContext& ctx); + bool frozen() const; + uint64 attach(Solver& s, Constraint& p, uint64 genId); + void detach(Solver* s, Constraint& p); + + const Arc& arc(uint32 id) const { return fwdArcs_[id]; } + const Arc* fwdBegin(uint32 n) const { + uint32 X = nodes_[n].fwdOff; + return validOff(X) ? &fwdArcs_[X] : 0; + } + const Arc* fwdNext(const Arc* a)const { assert(a); return a[0].node[0] == a[1].node[0] ? ++a : 0; } + const Inv* invBegin(uint32 n) const { + uint32 X = nodes_[n].invOff; + return validOff(X) ? &invArcs_[X] : 0; + } + const Inv* invNext(const Inv* a)const { assert(a); return (a->rep & 1u) == 1u ? ++a : 0; } + uint32 nodes() const { return maxNode_; } + uint32 edges() const { return comEdge_; } + bool validNode(uint32 n) const { return n < maxNode_; } +private: + ExtDepGraph(const ExtDepGraph&); + ExtDepGraph& operator=(const ExtDepGraph&); + struct Node { + uint32 fwdOff; + uint32 invOff; + }; + typedef PodVector::type ArcVec; + typedef PodVector::type InvVec; + typedef PodVector::type NodeVec; + bool validOff(uint32 n) const { + return n != UINT32_MAX; + } + ArcVec fwdArcs_; // arcs ordered by node id + InvVec invArcs_; // inverse arcs ordered by node id + NodeVec nodes_; // data for the nodes of this graph + uint32 maxNode_; // nodes have ids in the range [0, maxNode_) + uint32 comEdge_; // number of edges committed + uint32 genCnt_; // generation count (for incremental updates) +}; + +//! Acyclicity checker that operates on a ExtDepGraph. +/*! + * \ingroup propagator + * \see M. Gebser, T. Janhunen, and J. Rintanen: "SAT Modulo Graphs: Acyclicity" + */ +class AcyclicityCheck : public PostPropagator { +public: + enum Strategy { + prop_full = 0, // forward and backward check with clause generation + prop_full_imp = 1, // forward and backward check without clause generation + prop_fwd = 2, // only forward check + }; + enum { PRIO = PostPropagator::priority_reserved_ufs + 1 }; + typedef ExtDepGraph DependencyGraph; + explicit AcyclicityCheck(DependencyGraph* graph); + ~AcyclicityCheck(); + void setStrategy(Strategy p); + void setStrategy(const SolverParams& opts); + // base interface + uint32 priority() const { return uint32(PRIO); } + bool init(Solver&); + void reset(); + bool propagateFixpoint(Solver& s, PostPropagator* ctx); + bool isModel(Solver& s); + bool valid(Solver& s); + void destroy(Solver* s, bool detach); +private: + AcyclicityCheck(const AcyclicityCheck&); + AcyclicityCheck& operator=(const AcyclicityCheck&); + struct Parent { + static Parent create(Literal x, uint32 n) { Parent p = {x, n}; return p; } + Literal lit; + uint32 node; + }; + enum { config_bit = 2 }; + struct ReasonStore; + typedef DependencyGraph::Arc Arc; + typedef DependencyGraph::Inv Inv; + typedef PodQueue EdgeQueue; + typedef PodVector::type TagVec; + typedef PodVector::type ParentVec; + bool dfsForward(Solver& s, const Arc& e); + bool dfsBackward(Solver& s, const Arc& e); + void setParent(Var node, const Parent& p){ parent_[node] = p; } + void pushVisit(Var node, uint32 tv) { nStack_.push_back(node); tags_[node] = tv; } + bool visited(Var node, uint32 tv) const { return tags_[node] == tv; } + uint32 startSearch(); + void addClauseLit(Solver& s, Literal p); + void setReason(Literal p, LitVec::const_iterator first, LitVec::const_iterator end); + // ------------------------------------------------------------------------------------------- + // constraint interface + PropResult propagate(Solver&, Literal, uint32& eId) { + todo_.push(graph_->arc(eId)); + return PropResult(true, true); + } + void reason(Solver& s, Literal, LitVec&); + Strategy strategy() const { return static_cast(strat_ & 3u); } + DependencyGraph* graph_; // my graph + Solver* solver_; // my solver + ReasonStore* nogoods_;// stores at most one reason per literal + uint32 strat_; // active propagation strategy + uint32 tagCnt_; // generation counter for searches + EdgeQueue todo_; // edges that recently became enabled + TagVec tags_; // tag for each node + ParentVec parent_; // parents for each node + VarVec nStack_; // node stack for df-search + LitVec reason_; // reason for conflict/implication + uint64 genId_; // generation identifier +}; + +} +#endif + diff --git a/libclasp/clasp/enumerator.h b/libclasp/clasp/enumerator.h new file mode 100644 index 0000000..ddb87aa --- /dev/null +++ b/libclasp/clasp/enumerator.h @@ -0,0 +1,321 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_ENUMERATOR_H_INCLUDED +#define CLASP_ENUMERATOR_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif +#include +#include +#include +#include + +namespace Clasp { +class Solver; +class SharedContext; +class Enumerator; +class EnumerationConstraint; + +//! Type for storing a model. +struct Model { + enum Type { Sat = 0u, Brave = 1u, Cautious = 2u, User = 4u }; + enum { cons_mask = 3u, est_pos_mask= 4u, est_neg_mask = 8u }; + static uint8 estMask(Literal p) { return est_pos_mask << ((int)p.sign()); } + bool hasVar(Var v) const { return values && v < values->size(); } + //! True if this model stores current (cautious/brave) consequences. + bool consequences() const { return (type & cons_mask) != 0; } + //! For sat models, value of v in model. Otherwise, undefined. + ValueRep value(Var v) const { assert(hasVar(v)); return (*values)[v] & 3u; } + //! True if p is true in model or part of current consequences. + bool isTrue(Literal p) const { return (value(p.var()) & trueValue(p)) != 0; } + //! True if p is part of a definite answer. + bool isDef(Literal p) const { return isTrue(p) && (def || ((type & Cautious) == 0u) || !isEst(p)); } + //! True if p is part of the current estimate of consequences. + bool isEst(Literal p) const { assert(hasVar(p.var())); return ((*values)[p.var()] & estMask(p)) != 0; } + void reset(); + uint64 num; // running number of this model + const Enumerator* ctx; // ctx in which model was found + const ValueVec* values; // variable assignment or consequences + const SumVec* costs; // associated costs (or 0) + uint32 sId :16;// id of solver that found the model + uint32 type:12;// type of model + uint32 opt : 1;// whether the model is optimal w.r.t costs (0: unknown) + uint32 def : 1;// whether the model is definite w.r.t consequences (0: unknown) + uint32 sym : 1;// whether symmetric models are possible + uint32 up : 1;// whether the model was updated on last unsat +}; + +/** + * \defgroup enumerator Solving + * \brief Enumerators and solve algorithms. + */ +//@{ + +//! Options for configuring enumeration. +struct EnumOptions { + typedef MinimizeMode OptMode; + enum EnumType { enum_auto = 0, enum_bt = 1, enum_record = 2, enum_dom_record = 3, enum_consequences = 4, enum_brave = 5, enum_cautious = 6, enum_query = 7, enum_user = 8 }; + EnumOptions() : numModels(-1), enumMode(enum_auto), optMode(MinimizeMode_t::optimize), project(0), maxSat(false) {} + static Enumerator* createModelEnumerator(const EnumOptions& opts); + static Enumerator* createConsEnumerator(const EnumOptions& opts); + static Enumerator* nullEnumerator(); + static Enumerator* createEnumerator(const EnumOptions& opts); + bool consequences() const { return (enumMode & enum_consequences) != 0; } + bool models() const { return (enumMode < enum_consequences); } + bool optimize() const { return ((optMode & MinimizeMode_t::optimize) != 0); } + int64 numModels; /*!< Number of models to compute. */ + EnumType enumMode; /*!< Enumeration type to use. */ + OptMode optMode; /*!< Optimization mode to use. */ + uint32 project; /*!< Options for projection. */ + SumVec optBound; /*!< Initial bound for optimize statements. */ + bool maxSat; /*!< Treat DIMACS input as MaxSat. */ +}; +const char* modelType(const Model& m); + + +//! Interface for supporting enumeration of models. +/*! + * Enumerators are global w.r.t a solve algorithm. That is, + * even if the solve algorithm itself uses a parallel search, there + * shall be only one enumerator and it is the user's responsibility + * to protect the enumerator with appropriate locking. + * + * Concrete enumerators must implement a function for preparing a problem for enumeration + * and an EnumerationConstraint to be added to each solver attached to the problem. + * It is then the job of the actual solve algorithm to commit models to the enumerator + * and to integrate new information into attached solvers via appropriate calls to + * Enumerator::update(). + */ +class Enumerator { +public: + typedef EnumerationConstraint* ConPtr; + typedef const EnumerationConstraint* ConPtrConst; + typedef const SharedMinimizeData* Minimizer; + typedef EnumOptions::OptMode OptMode; + class ThreadQueue; + explicit Enumerator(); + virtual ~Enumerator(); + + void reset(); + + //! Prepares the problem for enumeration. + /*! + * The function shall be called once before search is started and before SharedContext::endInit() + * was called. It freezes enumeration-related variables and adds a suitable enumeration constraint + * to the master solver. + * + * \pre The problem is not yet frozen, i.e. SharedContext::endInit() was not yet called. + * \param problem The problem on which this enumerator should work. + * \param opt Minimization mode to apply during enumeration. + * \param limit Optional hint on max number of models to compute. + * + * \note In the incremental setting, init() must be called once for each incremental step. + */ + int init(SharedContext& problem, OptMode opt = MinimizeMode_t::optimize, int limit = 0); + + //! Prepares the given solver for enumeration under the given path. + /*! + * The function shall be called once before solving is started. It pushes the + * given path to the solver by calling Solver::pushRoot() and prepares s for + * enumeration/optimization. + * \return true if path was added. + */ + bool start(Solver& s, const LitVec& path = LitVec(), bool disjointPath = false) const; + + //! Updates the given solver with enumeration-related information. + /*! + * The function is used to integrate enumeration-related information, + * like minimization bounds or previously committed models, into the search space of s. + * It shall be called after each commit. + * + * \param s The solver to update. + * \note The function is concurrency-safe, i.e. can be called + * concurrently by different solvers. + */ + bool update(Solver& s) const; + + /*! + * \name Commit functions + * Functions for committing enumeration-related information to the enumerator. + * \note The functions in this group are *not* concurrency-safe, i.e. in a parallel search + * at most one solver shall call a commit function at any one time. + */ + //@{ + + //! Commits the model stored in the given solver. + /*! + * If the model is valid and unique, the function returns true and the + * model can be accessed via a call to Enumerator::lastModel(). + * Otherwise, the function returns false. + * In either case, Enumerator::update(s) shall be called + * in order to continue search for further models. + * + * \pre The solver's assignment is total. + */ + bool commitModel(Solver& s); + //! Expands the next symmetric model if any. + bool commitSymmetric(Solver& s); + //! Commits an unsatisfiable path stored in the given solver. + /*! + * The return value determines how search should proceed. + * If true is returned, the enumerator has relaxed an enumeration constraint + * and search may continue after a call to Enumerator::update(s). + * Otherwise, the search shall be stopped. + */ + bool commitUnsat(Solver& s); + //! Commits the given clause to this enumerator. + bool commitClause(const LitVec& clause) const; + //! Marks current enumeration phase as completed. + /*! + * If the enumerator was initialized with a minimization constraint and + * optimization mode MinimizeMode_t::enumOpt, the optimal bound is committed, + * the enumerator is prepared for enumerating optimal models, and the function + * returns false. Otherwise, the function returns true and search shall be stopped. + */ + bool commitComplete(); + //! Commits the state stored in the given solver. + /*! + * Calls commitModel() or commitUnsat() depending on the state of s. + * The function returns value_true, to signal that s stores a valid and + * unique model, value_false to signal that search shall be stopped, and + * value_free otherwise. + * \see commitModel() + * \see commitUnsat() + */ + uint8 commit(Solver& s); + //@} + + //! Removes from s the path that was passed to start() and any active (minimization) bound. + void end(Solver& s) const; + //! Returns the number of models enumerated so far. + uint64 enumerated() const { return model_.num; } + //! Returns the last model enumerated. + /*! + * \note If enumerated() is equal to 0, the returned object is in an indeterminate state. + */ + const Model& lastModel() const { return model_; } + //! Returns whether optimization is active. + bool optimize() const { return mini_ && mini_->mode() != MinimizeMode_t::enumerate && model_.opt == 0; } + //! Returns whether computed models are still tentative. + bool tentative() const { return mini_ && mini_->mode() == MinimizeMode_t::enumOpt && model_.opt == 0; } + //! Returns the active minimization constraint if any. + Minimizer minimizer() const { return mini_; } + //! Returns the type of models this enumerator computes. + virtual int modelType() const { return Model::Sat; } + enum UnsatType { + unsat_stop = 0u, /*!< First unsat stops search - commitUnsat() always return false. */ + unsat_cont = 1u, /*!< Unsat may be tentative - commitUnsat() may return true. */ + unsat_sync = 3u, /*!< Similar to unsat_cont but additionally requires synchronization among threads. */ + }; + //! Returns whether unsat may be tentative and/or requires synchronization. + virtual int unsatType() const; + //! Returns whether or not this enumerator supports full restarts once a model was found. + virtual bool supportsRestarts() const { return true; } + //! Returns whether or not this enumerator supports parallel search. + virtual bool supportsParallel() const { return true; } + //! Returns whether or not this enumerator supports splitting-based search. + virtual bool supportsSplitting(const SharedContext& problem) const; + //! Returns whether this enumerator requires exhaustive search to produce a definite answer. + virtual bool exhaustive() const { return mini_ && mini_->mode() != MinimizeMode_t::enumerate; } + //! Sets whether the search path stored in s is disjoint from all others. + void setDisjoint(Solver& s, bool b) const; + //! Sets whether symmetric should be ignored. + void setIgnoreSymmetric(bool b); + ConPtr constraint(const Solver& s) const; +protected: + //! Shall prepare the enumerator and freeze any enumeration-related variable. + /*! + * \return A prototypical enumeration constraint to be used in a solver. + */ + virtual ConPtr doInit(SharedContext& ctx, SharedMinimizeData* min, int numModels) = 0; + virtual void doReset(); + Model& model(); +private: + class SharedQueue; + Enumerator(const Enumerator&); + Enumerator& operator=(const Enumerator&); + SharedMinimizeData* mini_; + SharedQueue* queue_; + SumVec costs_; + Model model_; +}; + +//! A solver-local (i.e. thread-local) constraint to support enumeration. +/*! + * An enumeration constraint is used to extract/store enumeration-related information + * from models. + */ +class EnumerationConstraint : public Constraint { +public: + typedef EnumerationConstraint* ConPtr; + typedef MinimizeConstraint* MinPtr; + typedef Enumerator::ThreadQueue* QueuePtr; + //! Returns true if search-path is disjoint from all others. + bool disjointPath()const { return (flags_ & flag_path_disjoint) != 0u; } + ValueRep state() const { return static_cast(flags_ & 3u); } + //! Returns true if optimization is active. + bool optimize() const; + MinPtr minimizer() const { return mini_; } + // Methods used by enumerator + void init(Solver& s, SharedMinimizeData* min, QueuePtr q); + bool start(Solver& s, const LitVec& path, bool disjoint); + void end(Solver& s); + bool update(Solver& s); + void setDisjoint(bool x); + bool integrateBound(Solver& s); + bool integrateNogoods(Solver& s); + bool commitModel(Enumerator& ctx, Solver& s); + bool commitUnsat(Enumerator& ctx, Solver& s); + void setMinimizer(MinPtr min) { mini_ = min; } + void add(Constraint* c); + void modelHeuristic(Solver& s); +protected: + EnumerationConstraint(); + virtual ~EnumerationConstraint(); + // base interface + virtual void destroy(Solver* s, bool detach); + virtual PropResult propagate(Solver&, Literal, uint32&) { return PropResult(true, true); } + virtual void reason(Solver&, Literal, LitVec&) {} + virtual bool simplify(Solver& s, bool reinit); + virtual bool valid(Solver& s); + virtual Constraint* cloneAttach(Solver& s); + // own interface + virtual ConPtr clone() = 0; + virtual bool doUpdate(Solver& s) = 0; + virtual void doCommitModel(Enumerator&, Solver&) {} + virtual void doCommitUnsat(Enumerator&, Solver&) {} + uint32 rootLevel() const { return root_; } +private: + enum Flag { flag_path_disjoint = 4u, flag_model_heuristic = 8u }; + enum { clear_state_mask = ~uint32(value_true|value_false) }; + typedef PodVector::type ConstraintDB; + typedef SingleOwnerPtr QPtr; + MinimizeConstraint* mini_; + QPtr queue_; + ConstraintDB nogoods_; + LitVec next_; + uint32 flags_ : 4; + uint32 root_ : 28; +}; +//@} +} + +#endif diff --git a/libclasp/clasp/heuristics.h b/libclasp/clasp/heuristics.h new file mode 100644 index 0000000..ed5467c --- /dev/null +++ b/libclasp/clasp/heuristics.h @@ -0,0 +1,399 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_HEURISTICS_H_INCLUDED +#define CLASP_HEURISTICS_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +/*! + * \file + * \brief Defines various decision heuristics to be used in clasp. + */ + +#include +#include +#include +#include +namespace Clasp { + +//! Computes a moms-like score for var v. +uint32 momsScore(const Solver& s, Var v); + +//! A variant of the BerkMin decision heuristic from the BerkMin Sat-Solver. +/*! + * \ingroup heuristic + * \see E. Goldberg, Y. Navikov: "BerkMin: a Fast and Robust Sat-Solver" + * + * \note + * This version of the BerkMin heuristic varies mostly in the following points from the original BerkMin: + * -# it considers loop-nogoods if requested (this is the default) + * -# it uses a MOMS-like heuristic as long as there are no conflicts (and therefore no activities) + * -# it uses a MOMS-like score to break ties whenever multiple variables from an unsatisfied learnt constraint have equal activities + * -# it uses a lazy decaying scheme that only touches active variables + */ +class ClaspBerkmin : public DecisionHeuristic { +public: + /*! + * \note Checks at most params.param candidates when searching for not yet + * satisfied learnt constraints. If param is 0, all candidates are checked. + */ + explicit ClaspBerkmin(const HeuParams& params = HeuParams()); + void setConfig(const HeuParams& params); + void startInit(const Solver& s); + void endInit(Solver& s); + void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t); + void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit); + bool bump(const Solver& s, const WeightLitVec& lits, double adj); + void undoUntil(const Solver&, LitVec::size_type); + void updateVar(const Solver& s, Var v, uint32 n); +protected: + Literal doSelect(Solver& s); +private: + Literal selectLiteral(Solver& s, Var v, bool vsids) const; + Literal selectRange(Solver& s, const Literal* first, const Literal* last); + bool initHuang() const { return order_.score[0].occ == 1; } + void initHuang(bool b) { order_.score[0].occ = b; } + bool hasActivities() const { return order_.score[0].act != 0; } + void hasActivities(bool b) { order_.score[0].act = b; } + Var getMostActiveFreeVar(const Solver& s); + Var getTopMoms(const Solver& s); + bool hasTopUnsat(Solver& s); + // Gathers heuristic information for one variable v. + struct HScore { + HScore(uint32 d = 0) : occ(0), act(0), dec(uint16(d)) {} + void incAct(uint32 gd, bool h, bool sign) { + occ += int(h) * (1 - (2*int(sign))); + decay(gd, h); + ++act; + } + void incOcc(bool sign) { occ += 1 - (2*int(sign)); } + uint32 decay(uint32 gd, bool h) { + if (uint32 x = (gd-dec)) { + // NOTE: shifts might overflow, i.e. + // activity is actually shifted by x%32. + // We deliberately ignore this "logical inaccuracy" + // and treat it as random noise ;) + act >>= x; + dec = uint16(gd); + occ /= (1<<(x*int(h))); + } + return act; + } + int32 occ; + uint16 act; + uint16 dec; + }; + typedef PodVector::type Scores; + typedef VarVec::iterator Pos; + + struct Order { + explicit Order() : decay(0), huang(false), resScore(3u) {} + struct Compare { + explicit Compare(Order* o) : self(o) {} + bool operator()(Var v1, Var v2) const { + return self->decayedScore(v1) > self->decayedScore(v2) + || (self->score[v1].act == self->score[v2].act && v1 < v2); + } + Order* self; + }; + uint32 decayedScore(Var v) { return score[v].decay(decay, huang); } + int32 occ(Var v) const { return score[v].occ; } + void inc(Literal p, bool inNant) { + if (!this->nant || inNant) { + score[p.var()].incAct(decay, huang, p.sign()); + } + } + void incOcc(Literal p) { score[p.var()].incOcc(p.sign()); } + int compare(Var v1, Var v2) { + return int(decayedScore(v1)) - int(decayedScore(v2)); + } + void resetDecay(); + Scores score; // For each var v score_[v] stores heuristic score of v + uint32 decay; // "global" decay counter. Increased every decP_ decisions + bool huang; // Use Huang's scoring scheme (see: Jinbo Huang: "A Case for Simple SAT Solvers") + bool nant; // only score vars v with varInfo(v).nant()? + uint8 resScore; + private: + Order(const Order&); + Order& operator=(const Order&); + } order_; + VarVec cache_; // Caches the most active variables + LitVec freeLits_; // Stores free variables of the last learnt conflict clause that is not sat + LitVec freeOtherLits_; // Stores free variables of the last other learnt nogood that is not sat + uint32 topConflict_; // Index into the array of learnt nogoods used when searching for conflict clauses that are not sat + uint32 topOther_; // Index into the array of learnt nogoods used when searching for other learnt nogoods that are not sat + Var front_; // First variable whose truth-value is not already known - reset on backtracking + Pos cacheFront_; // First unprocessed cache position - reset on backtracking + uint32 cacheSize_; // Cache at most cacheSize_ variables + uint32 numVsids_; // Number of consecutive vsids-based decisions + uint32 maxBerkmin_; // When searching for an open learnt constraint, check at most maxBerkmin_ candidates. + TypeSet types_; // When searching for an open learnt constraint, consider these types of nogoods. + RNG rng_; +}; + +//! Variable Move To Front decision strategies inspired by Siege. +/*! + * \ingroup heuristic + * \see Lawrence Ryan: "Efficient Algorithms for Clause Learning SAT-Solvers" + * + * \note This implementation of VMTF differs from the original implementation in three points: + * - it optionally moves to the front a selection of variables from learnt loop nogoods + * - it measures variable activity by using a BerkMin-like score scheme + * - the initial order of the var list is determined using a MOMs-like score scheme + */ +class ClaspVmtf : public DecisionHeuristic { +public: + /*! + * \note Moves at most params.param literals from constraints used during + * conflict resolution to the front. If params.param is 0, the default is + * to move up to 8 literals. + */ + explicit ClaspVmtf(const HeuParams& params = HeuParams()); + void setConfig(const HeuParams& params); + void startInit(const Solver& s); + void endInit(Solver&); + void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t); + void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit); + bool bump(const Solver& s, const WeightLitVec& lits, double adj); + void simplify(const Solver&, LitVec::size_type); + void undoUntil(const Solver&, LitVec::size_type); + void updateVar(const Solver& s, Var v, uint32 n); +protected: + Literal doSelect(Solver& s); +private: + Literal selectRange(Solver& s, const Literal* first, const Literal* last); + typedef std::list VarList; + typedef VarList::iterator VarPos; + struct VarInfo { + VarInfo(VarPos it) : pos_(it), activity_(0), occ_(0), decay_(0) { } + VarPos pos_; // position of var in var list + uint32 activity_; // activity of var - initially 0 + int32 occ_; // which literal of var occurred more often in learnt constraints? + uint32 decay_; // counter for lazy decaying activity + uint32& activity(uint32 globalDecay) { + if (uint32 x = (globalDecay - decay_)) { + activity_ >>= (x<<1); + decay_ = globalDecay; + } + return activity_; + } + }; + typedef PodVector::type Score; + + struct LessLevel { + LessLevel(const Solver& s, const Score& sc) : s_(s), sc_(sc) {} + bool operator()(Var v1, Var v2) const { + return s_.level(v1) < s_.level(v2) + || (s_.level(v1) == s_.level(v2) && sc_[v1].activity_ > sc_[v2].activity_); + } + bool operator()(Literal l1, Literal l2) const { + return (*this)(l1.var(), l2.var()); + } + private: + LessLevel& operator=(const LessLevel&); + const Solver& s_; + const Score& sc_; + }; + Score score_; // For each var v score_[v] stores heuristic score of v + VarList vars_; // List of possible choices, initially ordered by MOMs-like score + VarVec mtf_; // Vars to be moved to the front of vars_ + VarPos front_; // Current front-position in var list - reset on backtracking + uint32 decay_; // "Global" decay counter. Increased every 512 decisions + uint32 nMove_; // Limit on number of vars to move + TypeSet types_; // Type of nogoods to score during resolution + uint32 scType_;// Type of scoring + bool nant_; // only move vars v with varInfo(v).nant()? +}; + +//! Score type for VSIDS heuristic. +/*! + * \see ClaspVsids + */ +struct VsidsScore { + typedef VsidsScore SC; + VsidsScore(double sc = 0.0) : value(sc) {} + double get() const { return value; } + bool operator>(const SC& o) const { return value > o.value; } + void set(double f) { value = f; } + template + static double applyFactor(C&, Var, double f) { return f; } + double value; // activity +}; + +//! A variable state independent decision heuristic favoring variables that were active in recent conflicts. +/*! + * \ingroup heuristic + * \see M. W. Moskewicz, C. F. Madigan, Y. Zhao, L. Zhang, and S. Malik: + * "Chaff: Engineering an Efficient SAT Solver" + * + * \note By default, the implementation uses the exponential VSIDS scheme from MiniSAT and + * applies a MOMs-like score scheme to get an initial var order. + */ +template +class ClaspVsids_t : public DecisionHeuristic { +public: + /*! + * \note Uses params.param to init the decay value d and inc factor 1.0/d. + * If params.param is 0, d is set 0.95. Otherwise, d is set to 0.x, where x is params.param. + */ + explicit ClaspVsids_t(const HeuParams& params = HeuParams()); + virtual void setConfig(const HeuParams& params); + virtual void startInit(const Solver& s); + virtual void endInit(Solver&); + virtual void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t); + virtual void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit); + virtual bool bump(const Solver& s, const WeightLitVec& lits, double adj); + virtual void undoUntil(const Solver&, LitVec::size_type); + virtual void simplify(const Solver&, LitVec::size_type); + virtual void updateVar(const Solver& s, Var v, uint32 n); +protected: + virtual Literal doSelect(Solver& s); + virtual Literal selectRange(Solver& s, const Literal* first, const Literal* last); + virtual void initScores(Solver& s, bool moms); + typedef typename PodVector::type ScoreVec; + typedef PodVector::type OccVec; + void updateVarActivity(const Solver& s, Var v, double f = 1.0); + void incOcc(Literal p) { occ_[p.var()] += 1 - (int(p.sign()) << 1); } + int occ(Var v) const { return occ_[v]; } + void normalize(); + struct CmpScore { + explicit CmpScore(const ScoreVec& s) : sc_(s) {} + bool operator()(Var v1, Var v2) const { return sc_[v1] > sc_[v2]; } + private: + CmpScore& operator=(const CmpScore&); + const ScoreVec& sc_; + }; + typedef bk_lib::indexed_priority_queue VarOrder; + struct Decay : Range{ + Decay(double x = 0.0, double y = 0.95, uint32 b = 0, uint32 f = 0) : Range(x, y), bump(b), freq(f), next(f) { + this->df = 1.0 / (freq && lo > 0.0 ? lo : hi); + } + double df; // active decay factor for evsids (>= 1.0) + uint32 bump; + uint32 freq : 16; + uint32 next : 16; + }; + ScoreVec score_; // vsids score for each variable + OccVec occ_; // occurrence balance of each variable + VarOrder vars_; // priority heap of variables + Decay decay_; // (dynamic) decaying strategy + double inc_; // var bump for evsids or conflict index for acids (increased on conflict) + TypeSet types_; // set of constraints to score + uint32 scType_;// score type (one of HeuParams::Score) + bool acids_; // whether to use acids instead if evsids scoring + bool nant_; // whether bumps are restricted to vars v with varInfo(v).nant() +}; +typedef ClaspVsids_t ClaspVsids; + +//! Score type for DomainHeuristic. +/*! + * \see DomainHeuristic + */ +struct DomScore : VsidsScore { + static const uint32 domMax = (1u << 30) - 1; + typedef DomScore SC; + DomScore(double v = 0.0) : VsidsScore(v), level(0), factor(1), domP(domMax), sign(0), init(0) {} + bool operator>(const SC& o) const { return (level > o.level) || (level == o.level && value > o.value); } + bool isDom() const { return domP != domMax; } + void setDom(uint32 key) { domP = key; } + template + static double applyFactor(C& sc, Var v, double f) { + int16 df = sc[v].factor; + return df == 1 ? f : static_cast(df) * f; + } + int16 level; // priority level + int16 factor; // factor used when bumping activity + uint32 domP : 30; // index into dom-table if dom var + uint32 sign : 1; // whether v has a sign modification + uint32 init : 1; // whether value is from init modification +}; + +//! A VSIDS heuristic supporting additional domain knowledge. +/*! + * \ingroup heuristic + * + * \see M. Gebser, B. Kaufmann, R. Otero, J. Romero, T. Schaub, P. Wanko: + * "Domain-specific Heuristics in Answer Set Programming", + * http://www.cs.uni-potsdam.de/wv/pdfformat/gekaotroscwa13a.pdf + */ +class DomainHeuristic : public ClaspVsids_t + , private Constraint { +public: + typedef ClaspVsids_t BaseType; + explicit DomainHeuristic(const HeuParams& params = HeuParams()); + ~DomainHeuristic(); + void setDefaultMod(HeuParams::DomMod mod, uint32 prefSet); + virtual void setConfig(const HeuParams& params); + virtual void startInit(const Solver& s); + const DomScore& score(Var v) const { return score_[v]; } +protected: + // base interface + virtual Literal doSelect(Solver& s); + virtual void initScores(Solver& s, bool moms); + virtual void detach(Solver& s); + // Constraint interface + virtual Constraint* cloneAttach(Solver&) { return 0; } + virtual void reason(Solver&, Literal, LitVec&){} + virtual PropResult propagate(Solver&, Literal, uint32&); + virtual void undoLevel(Solver& s); +private: + struct DomAction { + static const uint32 UNDO_NIL = (1u << 31) - 1; + uint32 var:30; // dom var to be modified + uint32 mod: 2; // modification to apply + uint32 undo:31;// next action in undo list + uint32 next: 1;// next action belongs to same condition? + int16 bias; // value to apply + uint16 prio; // prio of modification + }; + struct DomPrio { + void clear() { prio[0] = prio[1] = prio[2] = prio[3] = 0; } + uint16 operator[](unsigned i) const { return prio[i]; } + uint16& operator[](unsigned i) { return prio[i]; } + uint16 prio[4]; + }; + struct Frame { + Frame(uint32 lev, uint32 h) : dl(lev), head(h) {} + uint32 dl; + uint32 head; + }; + typedef PodVector::type ActionVec; + typedef PodVector::type PrioVec; + typedef PodVector::type FrameVec; + typedef DomainTable::ValueType DomMod; + typedef PodVector >::type VarScoreVec; + + uint32 addDomAction(const DomMod& e, Solver& s, VarScoreVec& outInit, Literal& lastW); + void addDefAction(Solver& s, Literal x, int16 lev, uint32 domKey); + void pushUndo(uint32& head, uint32 actionId); + void applyAction(Solver& s, DomAction& act, uint16& oldPrio); + uint16& prio(Var v, uint32 mod) { return prios_[score_[v].domP][mod]; } + PrioVec prios_; // priorities for domain vars + ActionVec actions_; // dynamic modifications + FrameVec frames_; // dynamic undo information + uint32 domSeen_; // offset into domain table + uint32 defMax_; // max var with default modification + uint16 defMod_; // default modifier + uint16 defPref_; // default preferences +}; +} +#endif diff --git a/libclasp/clasp/literal.h b/libclasp/clasp/literal.h new file mode 100644 index 0000000..d790da8 --- /dev/null +++ b/libclasp/clasp/literal.h @@ -0,0 +1,243 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_LITERAL_H_INCLUDED +#define CLASP_LITERAL_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif +#include +#include +#include // std::swap +#include +/*! + * \file + * \brief Types and functions related to literals and variables. + */ +namespace Clasp { +/*! + * \addtogroup constraint + */ +//@{ + +//! A variable is an integer in the range [0..varMax). +typedef uint32 Var; + +//! varMax is not a valid variale, i.e. currently Clasp supports at most 2^30 variables. +const Var varMax = (Var(1) << 30); + +//! The variable 0 has a special meaning in the solver. +const Var sentVar = 0; + +//! Literal ids are in the range [0..litIdMax). +const uint32 litIdMax = (Var(1) << 31); + +//! Possible types of a variable. +struct Var_t { + enum Type { Atom = 1, Body = 2, Hybrid = Atom | Body}; + static bool isBody(Type t) { + return (static_cast(t) & static_cast(Body)) != 0; + } + static bool isAtom(Type t) { + return (static_cast(t) & static_cast(Atom)) != 0; + } +}; +typedef Var_t::Type VarType; + +//! A literal is a variable or its negation. +/*! + * \par Implementation: + * A literal's state is stored in a single 32-bit integer as follows: + * - 30-bits : variable id + * - 1-bit : sign, 1 if negative, 0 if positive + * - 1-bit : general purpose flag for marking a literal instance + */ +class Literal { +public: + static const uint32 sign_bit = 2u; + static const uint32 flag_bit = 1u; + + //! The default constructor creates the positive literal of the special sentinel var. + Literal() : rep_(0) { } + + //! Creates a literal of the variable var with sign s. + /*! + * \param var The literal's variable. + * \param sign true if new literal should be negative. + * \pre var < varMax + */ + Literal(Var var, bool sign) : rep_( (var<> sign_bit; } + + //! Returns the sign of the literal. + /*! + * \return true if the literal is negative. Otherwise false. + */ + bool sign() const { return (rep_ & sign_bit) != 0; } + + //! Returns var and sign encoded in a unique id. + /*! + * \note The watch-flag is ignored and thus the id of a literal can be stored in 31-bits. + */ + uint32 id() const { return rep_ >> flag_bit; } + + //! Returns the stored representation of this literal. + uint32& rep() { return rep_; } + uint32 rep() const { return rep_; } + + //! Creates a literal from an id. + static Literal fromId(uint32 id) { + assert(id < litIdMax); + return Literal(id<(-p)) : posLit(static_cast(p)); } +//! Converts the given (non-sentinel) literal to a signed integer s.th. p == toLit(toInt(p)). +inline int32 toInt(Literal p) { return p.sign() ? -static_cast(p.var()) : static_cast(p.var()); } +//! Always-true literal. +// TODO: replace with constant using constexpr ctor once we switch to C++11 +inline Literal lit_true() { return Literal(sentVar, false); } +//! Always-false literal. +// TODO: replace with constant using constexpr ctor once we switch to C++11 +inline Literal lit_false() { return Literal(sentVar, true); } +//! Returns true if p represents the special variable 0 +inline bool isSentinel(Literal p) { return p.var() == sentVar; } + +// Low-level conversion between Literals and int literals. +// We cannot use toInt() here because it is not defined for the +// sentinel literals lit_true() and lit_false(). +inline int32 encodeLit(Literal x) { return !x.sign() ? static_cast(x.var()+1) : -static_cast(x.var()+1); } +inline Var decodeVar(int32 x) { return static_cast(x >= 0 ? x : -x) - 1; } +inline Literal decodeLit(int32 x) { return Literal(decodeVar(x), x < 0); } + +inline unsigned hashId(unsigned key) { + key = ~key + (key << 15); + key ^= (key >> 11); + key += (key << 3); + key ^= (key >> 5); + key += (key << 10); + key ^= (key >> 16); + return key; +} +inline uint32 hashLit(Literal p) { return hashId(p.id()); } + +//! A signed integer type used to represent weights. +typedef int32 weight_t; +//! A signed integer type used to represent sums of weights. +typedef int64 wsum_t; +#define CLASP_WEIGHT_T_MAX ( 2147483647) +#define CLASP_WEIGHT_T_MIN (-2147483647 - 1) +#define CLASP_WEIGHT_SUM_MAX INT64_MAX +#define CLASP_WEIGHT_SUM_MIN INT64_MIN + +typedef PodVector::type VarVec; //!< A vector of variables. +typedef PodVector::type LitVec; //!< A vector of literals. +typedef PodVector::type WeightVec; //!< A vector of weights. +typedef PodVector::type SumVec; //!< A vector of sums of weights. +typedef std::pair WeightLiteral; //!< A literal associated with a weight. +typedef PodVector::type WeightLitVec; //!< A vector of weight-literals. +/////////////////////////////////////////////////////////////////////////////// +// Truth values +/////////////////////////////////////////////////////////////////////////////// +typedef uint8 ValueRep; //!< Type of the three value-literals. +const ValueRep value_true = 1; //!< Value used for variables that are true. +const ValueRep value_false = 2; //!< Value used for variables that are false. +const ValueRep value_free = 0; //!< Value used for variables that are unassigned. +typedef PodVector::type ValueVec; + +//! Returns the value that makes the literal lit true. +/*! + * \param lit The literal for which the true-value should be determined. + * \return + * - value_true iff lit is a positive literal + * - value_false iff lit is a negative literal. + * . + */ +inline ValueRep trueValue(const Literal& lit) { return 1 + lit.sign(); } + +//! Returns the value that makes the literal lit false. +/*! + * \param lit The literal for which the false-value should be determined. + * \return + * - value_false iff lit is a positive literal + * - value_true iff lit is a negative literal. + * . + */ +inline ValueRep falseValue(const Literal& lit) { return 1 + !lit.sign(); } + +//! Returns the sign that matches the value. +/*! + * \return + * - false iff v == value_true + * - true otherwise + */ +inline bool valSign(ValueRep v) { return v != value_true; } +//@} +} +#endif diff --git a/libclasp/clasp/logic_program.h b/libclasp/clasp/logic_program.h new file mode 100644 index 0000000..37e9a1a --- /dev/null +++ b/libclasp/clasp/logic_program.h @@ -0,0 +1,644 @@ +// +// Copyright (c) 2013-2016 Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_LOGIC_PROGRAM_H_INCLUDED +#define CLASP_LOGIC_PROGRAM_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif +#include +#include +#include +#include +namespace Clasp { namespace Asp { +/*! + * \file + * \defgroup asp Asp + * \brief Classes and functions for defining logic programs. + * \ingroup problem + */ +//@{ + +//! A struct for counting program rules and directives. +struct RuleStats { + typedef uint32& Ref_t; + typedef uint32 const& CRef_t; + //! Rules and directives counted by this object. + enum Key { + Normal = Head_t::Disjunctive,//!< Normal or disjunctive rules. + Choice = Head_t::Choice, //!< Choice rules. + Minimize , //!< Distinct minimize constraints. + Acyc , //!< Edge directives. + Heuristic , //!< Heuristic directives. + Key__num + }; + //! Returns a string representation of the given key. + static const char* toStr(int k); + //! Returns the number of keys distinguished by this type. + static uint32 numKeys() { return Key__num; } + //! Updates the number of rules of the given type. + void up(Key k, int amount) { key[k] += static_cast(amount); } + //! Returns the number of rules of the given type. + Ref_t operator[](int k) { return key[k]; } + //! @copydoc operator[](int k) + CRef_t operator[](int k) const { return key[k]; } + //! Returns the sum of all rules. + uint32 sum() const; + uint32 key[Key__num]; //!< @private +}; +//! A struct for counting distinct program bodies. +struct BodyStats { + typedef uint32& Ref_t; + typedef uint32 const& CRef_t; + //! Body types distinguished by this object. + typedef Body_t Key; + //! Returns a string representation of the given key. + static const char* toStr(int k); + //! Returns the number of keys distinguished by this type. + static uint32 numKeys() { return Body_t::eMax + 1; } + //! Updates the number of bodies of the given type. + void up(Key k, int amount) { key[k] += static_cast(amount); } + //! Returns the number of bodies of the given type. + Ref_t operator[](int k) { return key[k]; } + //! @copydoc operator[](int k) + CRef_t operator[](int k) const { return key[k]; } + //! Returns the sum of all bodies. + uint32 sum() const; + uint32 key[Body_t::eMax + 1]; //!< @private +}; + +//! A type for maintaining a set of program statistics. +class LpStats { +public: + LpStats() { reset(); } + void reset(); + //! Returns the sum of all equivalences. + uint32 eqs() const { return eqs(Var_t::Atom) + eqs(Var_t::Body) + eqs(Var_t::Hybrid); } + //! Returns the number of equivalences of the given type. + uint32 eqs(VarType t) const { return eqs_[t-1]; } + //! Increments the number of equivalences of the given type. + void incEqs(VarType t) { ++eqs_[t-1]; } + //! Computes *this += o. + void accu(const LpStats& o); + RuleStats rules[2]; /**< RuleStats (initial, final). */ + BodyStats bodies[2]; /**< BodyStats (initial, final). */ + uint32 atoms; /**< Number of program atoms. */ + uint32 auxAtoms; /**< Number of aux atoms created. */ + uint32 disjunctions[2]; /**< Number of disjunctions (initial, non-hcf). */ + uint32 sccs; /**< How many strongly connected components? */ + uint32 nonHcfs; /**< How many non head-cycle free components?*/ + uint32 gammas; /**< How many non-hcf gamma rules. */ + uint32 ufsNodes; /**< How many nodes in the positive dependency graph? */ + // StatisticObject + static uint32 size(); + static const char* key(uint32 i); + StatisticObject at(const char* k) const; +private: + uint32 eqs_[3]; +}; +//! Exception type for signaling an invalid incremental program update. +class RedefinitionError : public std::logic_error { +public: + explicit RedefinitionError(unsigned atomId, const char* atomName = ""); + unsigned atom() const { return atomId_; } +private: + unsigned atomId_; +}; +using Potassco::TheoryData; + +//! A class for defining a logic program. +/*! + * Use this class to specify a logic program. Once the program is completly defined, + * call endProgram() to load the logic program into a SharedContext object. + */ +class LogicProgram : public ProgramBuilder { +public: + LogicProgram(); + ~LogicProgram(); + //! Defines the possible modes for handling extended rules, i.e. choice, cardinality, and weight rules. + enum ExtendedRuleMode { + mode_native = 0, //!< Handle extended rules natively. + mode_transform = 1, //!< Transform extended rules to normal rules. + mode_transform_choice = 2, //!< Transform only choice rules to normal rules. + mode_transform_card = 3, //!< Transform only cardinality rules to normal rules. + mode_transform_weight = 4, //!< Transform cardinality- and weight rules to normal rules. + mode_transform_scc = 5, //!< Transform recursive cardinality- and weight rules to normal rules. + mode_transform_nhcf = 6, //!< Transform cardinality- and weight rules in non-hcf components to normal rules. + mode_transform_integ = 7, //!< Transform cardinality-based integrity constraints. + mode_transform_dynamic= 8 //!< Heuristically decide whether or not to transform a particular extended rule. + }; + + //! Options for the Asp-Preprocessor. + struct AspOptions { + static const uint32 MAX_EQ_ITERS = static_cast( (1u<<26)-1 ); + typedef ExtendedRuleMode TrMode; + AspOptions() { + std::memset(this, 0, sizeof(AspOptions)); + iters = 5; + } + AspOptions& iterations(uint32 it) { iters = it;return *this;} + AspOptions& depthFirst() { dfOrder = 1; return *this;} + AspOptions& backpropagate() { backprop= 1; return *this;} + AspOptions& noScc() { noSCC = 1; return *this;} + AspOptions& noEq() { iters = 0; return *this;} + AspOptions& disableGamma() { noGamma = 1; return *this;} + AspOptions& ext(ExtendedRuleMode m) { erMode = m; return *this;} + TrMode erMode; //!< How to handle extended rules? + uint32 iters : 26;//!< Number of iterations in eq-preprocessing or 0 to disable. + uint32 noSCC : 1;//!< Disable scc checking? + uint32 suppMod : 1;//!< Disable scc checking and compute supported models. + uint32 dfOrder : 1;//!< Visit nodes in eq-preprocessing in depth-first order? + uint32 backprop : 1;//!< Enable backpropagation during preprocessing? + uint32 oldMap : 1;//!< Use old and larger mapping for disjunctive programs. + uint32 noGamma : 1;//!< Disable creation of (shifted) gamma rules for non-hcf disjunctions? + }; + + /*! + * \name Step control functions + */ + //@{ + + //! Starts the definition of a logic program. + LogicProgram& start(SharedContext& ctx, const AspOptions& opts = AspOptions()) { + startProgram(ctx); + setOptions(opts); + return *this; + } + //! Sets the mode for handling extended rules (default: mode_native). + void setExtendedRuleMode(ExtendedRuleMode m) { opts_.ext(m); } + //! Sets preprocessing options. + void setOptions(const AspOptions& opts); + //! Sets the configuration to be used for checker solvers in disjunctive LP solving. + void setNonHcfConfiguration(Configuration* c){ nonHcfs_.config = c; } + + //! Unfreezes a currently frozen program and starts an incremental step. + /*! + * If a program is to be defined incrementally, this function must be called + * exactly once for each step before any new rules or atoms are added. + * \note Program update only works correctly under the following assumptions: + * - Atoms introduced in step i are either: + * - solely defined in step i OR, + * - marked as frozen in step i and solely defined in step i+k OR, + * - forced to false by a compute statement in step 0. + * + * \pre The program is either frozen or at step 0. + * \post The program is no longer frozen and calling program mutating functions is valid again. + * \throws std::logic_error precondition is violated. + * \note The function is an alias for ProgramBuilder::updateProgram(). + */ + bool update() { return updateProgram(); } + + //! Finishes the definition of the logic program (or its current increment). + /*! + * Applies program mutating operations issued in the current step and transforms + * the new program into the solver's internal representation. + * + * \return false if the program is conflicting, true otherwise. + * + * \post + * - If true is returned, the program is considered to be "frozen" and calling + * program mutating functions is invalid until the next call to update(). + * - If false is returned, the state of the object is undefined and start() + * and dispose() are the only remaining valid operations. + * . + * \note The function is an alias for ProgramBuilder::endProgram(). + */ + bool end() { return endProgram(); } + + //! Visits the the simplified program by notifying out on its elements. + void accept(Potassco::AbstractProgram& out); + + //! Disposes (parts of) the internal representation of the logic program. + /*! + * \param forceFullDispose If set to true, the whole program is disposed. Otherwise, + * only the rules (of the current step) are disposed but atoms and any incremental + * control data remain. + */ + void dispose(bool forceFullDispose); + + //! Clones the program and adds it to the given ctx. + /* + * \pre The program is currently frozen. + */ + bool clone(SharedContext& ctx); + + //@} + + /*! + * \name Program mutating functions + * + * Functions in this group shall only be called if the program is currently not + * frozen. That is, only between the call to start() (resp. update() if in + * incremental setting) and end(). A std::logic_error is raised if this precondition is violated. + * + */ + //@{ + + //! Adds a new atom to the program and returns the new atom's id. + Atom_t newAtom(); + + //! Sets atomId as the last input atom of the current step. + /*! + * All (new or existing) atoms with a larger id than atomId + * are considered to be auxiliary and automatically removed before + * a new incremental step is started. + * + * \pre atomId >= startAtom() + * \post startAuxAtom() == atomId + 1 + */ + void setMaxInputAtom(uint32 atomId); + + //! Adds a new conjunctive condition to the program. + /*! + * \param cond A (possibly empty) list of atom literals. + * \return The id of the new condition, which can be later passed to + * extractCondition() or getLiteral(). + */ + Id_t newCondition(const Potassco::LitSpan& cond); + + //! Adds the given string to the problem's output table. + /*! + * \param str The string to add. + * \param cond The condition under which str should be considered part of a model. + */ + LogicProgram& addOutput(const ConstString& str, const Potassco::LitSpan& cond); + LogicProgram& addOutput(const ConstString& str, Id_t cond); + + //! Adds the given atoms to the set of projection variables. + LogicProgram& addProject(const Potassco::AtomSpan& atoms); + + //! Protects an otherwise undefined atom from preprocessing. + /*! + * If the atom is defined in this or a previous step, the operation has no effect. + * \note If atomId is not yet known, an atom with the given id is implicitly created. + * \note The second parameter defines the assumption that shall hold during solving, i.e. + * - posLit(atomId), if value is value_true, + * - negLit(atomId), if value is value_false, or + * - no assumption, if value is value_free. + * + * \see ProgramBuilder::getAssumptions(LitVec&) const; + */ + LogicProgram& freeze(Atom_t atomId, ValueRep value = value_false); + + //! Removes any protection from the given atom. + /*! + * If the atom is defined in this or a previous step, the operation has no effect. + * \note + * - The effect is logically equivalent to adding a rule atomId :- false. + * - A call to unfreeze() always overwrites a call to freeze() even if the + * latter comes after the former + * . + */ + LogicProgram& unfreeze(Atom_t atomId); + + //! Adds the given rule (or integrity constraint) to the program. + /*! + * \pre The the rule does not define an atom from a previous incremental step. + * + * Simplifies the given rule and adds it to the program if it + * is neither tautological (e.g. a :- a) nor contradictory (e.g. a :- b, not b). + * Atoms in the simplified rule that are not yet known are implicitly created. + * + * \throws RedefinitionError if the precondition is violated. + * \note If the head of the simplified rule mentions an atom from a previous step, + * that atom shall either be frozen or false. In the former case, + * unfreeze() is implicitly called. In the latter case, the rule is interpreted + * as an integrity constraint. + */ + LogicProgram& addRule(const Rule& rule); + LogicProgram& addRule(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body); + LogicProgram& addRule(Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& lits); + LogicProgram& addRule(Potassco::RuleBuilder& rb); + //! Adds the given minimize statement. + /*! + * \param prio The priority of the minimize statement. + * \param lits The literals to minimize. + * \note All minimize statements of the same priority are merged into one. + */ + LogicProgram& addMinimize(weight_t prio, const Potassco::WeightLitSpan& lits); + + //! Adds an edge to the extended (user-defined) dependency graph. + LogicProgram& addAcycEdge(uint32 n1, uint32 n2, const Potassco::LitSpan& condition) { return addAcycEdge(n1, n2, newCondition(condition)); } + LogicProgram& addAcycEdge(uint32 n1, uint32 n2, Id_t cond); + + //! Adds a conditional domain heuristic directive to the program. + LogicProgram& addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio, const Potassco::LitSpan& condition) { return addDomHeuristic(atom, t, bias, prio, newCondition(condition)); } + LogicProgram& addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio, Id_t cond); + //! Adds an unconditional domain heuristic directive to the program. + LogicProgram& addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio); + + //! Forces the given literals to be true during solving. + /*! + * Assumptions are retracted on the next program update. + */ + LogicProgram& addAssumption(const Potassco::LitSpan& cube); + + //! Adds or updates the given external atom. + /*! + * \see LogicProgram::freeze(Atom_t atomId, ValueRep value); + * \see LogicProgram::unfreeze(Atom_t atomId); + */ + LogicProgram& addExternal(Atom_t atomId, Potassco::Value_t value); + + //! Returns an object for adding theory data to this program. + TheoryData& theoryData(); + //@} + + /*! + * \name Query functions + * + * Functions in this group are useful to query important information + * once the program is frozen, i.e. after end() was called. + * They do not throw exceptions. + */ + //@{ + //! Returns whether the program can be represented in internal smodels format. + bool supportsSmodels() const; + //! Returns whether the program is to be defined incrementally. + bool isIncremental() const { return incData_ != 0; } + //! Returns whether the program contains any minimize statements. + bool hasMinimize() const { return !minimize_.empty(); } + //! Returns whether the program contains any theory data. + bool hasTheoryData() const { return theory_ != 0; } + //! Returns the number of atoms in the logic program. + uint32 numAtoms() const { return (uint32)atoms_.size()-1; } + //! Returns the number of bodies in the current (slice of the) logic program. + uint32 numBodies() const { return (uint32)bodies_.size(); } + //! Returns the number of disjunctive heads. + uint32 numDisjunctions() const { return (uint32)disjunctions_.size(); } + //! Returns the id of the first atom of the current step. + Atom_t startAtom() const { return input_.lo; } + //! Returns an id one past the last valid atom id in the program. + Atom_t endAtom() const { return numAtoms() + 1; } + //! Returns the id of the first atom that is not an input atom or endAtom() if no such atoms exists. + Atom_t startAuxAtom() const; + //! Returns whether a is an atom in the (simplified) program. + bool inProgram(Atom_t a) const; + //! Returns whether a is an external atom, i.e. is frozen in this step. + bool isExternal(Atom_t a) const; + //! Returns whether a occurs in the head of a rule. + bool isDefined(Atom_t a) const; + //! Returns whether a is a fact. + bool isFact(Atom_t a) const; + //! Returns the internal solver literal that is associated with the given atom or condition. + /*! + * \pre id is the id of a valid atom literal or was previously returned by newCondition(). + * \note Untill end() is called, the function returns lit_false() for + * all atoms and conditions defined in the current step. + * \note For an atom literal lit with Potassco::atom(lit) == a, + * getLiteral(Potassco::id(lit)) returns + * getLiteral(a), iff lit == a, or + * ~getLiteral(a), iff lit == -a. + */ + Literal getLiteral(Id_t id) const; + //! Returns the atom literals belonging to the given condition. + /*! + * \pre cId was previously returned by newCondition() in the current step. + */ + bool extractCondition(Id_t cId, Potassco::LitVec& lits) const; + LpStats stats; //!< Statistics of the current step. + //@} + + /*! + * \name Implementation functions + * Low-level implementation functions. Use with care and only if you + * know what you are doing! + */ + //@{ + typedef VarVec::const_iterator VarIter; + typedef PrgHead*const* HeadIter; + typedef std::pair EdgeRange; + typedef std::pair HeadRange; + struct SRule { + SRule() : hash(0), pos(0), bid(varMax) {} + uint32 hash; // hash value of the body + uint32 pos; // positive size of body + uint32 bid; // id of existing body or varMax + }; + const AspOptions& options() const { return opts_; } + bool hasConflict() const { return getTrueAtom()->literal() != lit_true(); } + bool ok() const { return !hasConflict() && ProgramBuilder::ok(); } + PrgAtom* getAtom(Id_t atomId)const { return atoms_[atomId]; } + PrgHead* getHead(PrgEdge it) const { return it.isAtom() ? (PrgHead*)getAtom(it.node()) : (PrgHead*)getDisj(it.node()); } + PrgNode* getSupp(PrgEdge it) const { return it.isBody() ? (PrgNode*)getBody(it.node()) : (PrgNode*)getDisj(it.node()); } + Id_t getRootId(Id_t atom)const { return getEqNode(atoms_, atom); } + PrgAtom* getRootAtom(Id_t a) const { return getAtom(getRootId(a)); } + PrgBody* getBody(Id_t bodyId)const { return bodies_[bodyId]; } + Id_t getEqBody(Id_t b) const { return getEqNode(bodies_, b); } + PrgDisj* getDisj(Id_t disjId)const { return disjunctions_[disjId]; } + HeadIter disj_begin() const { return disjunctions_.empty() ? 0 : reinterpret_cast(&disjunctions_[0]); } + HeadIter disj_end() const { return disj_begin() + numDisjunctions(); } + HeadIter atom_begin() const { return reinterpret_cast(&atoms_[0]); } + HeadIter atom_end() const { return atom_begin() + (numAtoms()+1); } + VarIter unfreeze_begin() const { return incData_?incData_->unfreeze.begin() : propQ_.end(); } + VarIter unfreeze_end() const { return incData_?incData_->unfreeze.end() : propQ_.end(); } + bool validAtom(Id_t aId) const { return aId < (uint32)atoms_.size(); } + bool validBody(Id_t bId) const { return bId < numBodies(); } + bool validDisj(Id_t dId) const { return dId < numDisjunctions(); } + Literal getDomLiteral(Atom_t a) const; + bool isFact(PrgAtom* a) const; + const char*findName(Atom_t x) const; + bool simplifyRule(const Rule& r, Potassco::RuleBuilder& out, SRule& meta); + Atom_t falseAtom(); + VarVec& getSupportedBodies(bool sorted); + uint32 update(PrgBody* b, uint32 oldHash, uint32 newHash); + bool assignValue(PrgAtom* a, ValueRep v, PrgEdge reason); + bool assignValue(PrgHead* h, ValueRep v, PrgEdge reason); + bool propagate(bool backprop); + PrgAtom* mergeEqAtoms(PrgAtom* a, Id_t rootAtom); + PrgBody* mergeEqBodies(PrgBody* b, Id_t rootBody, bool hashEq, bool atomsAssigned); + bool propagate() { return propagate(options().backprop != 0); } + void setConflict() { getTrueAtom()->setLiteral(lit_false()); } + AtomState& atomState() { return atomState_; } + void addMinimize(); + // ------------------------------------------------------------------------ + // Statistics + void incTrAux(uint32 n) { stats.auxAtoms += n; } + void incEqs(VarType t) { stats.incEqs(t); } + void upStat(RuleStats::Key k, int n = 1){ stats.rules[statsId_].up(k, n); } + void upStat(Body_t k, int n = 1) { stats.bodies[statsId_].up(k, n); } + void upStat(Head_t k, int n = 1) { stats.rules[statsId_].up(static_cast(unsigned(k)), n); } + // ------------------------------------------------------------------------ + //@} +private: + LogicProgram(const LogicProgram&); + LogicProgram& operator=(const LogicProgram&); + struct DlpTr; + struct AcycArc { Id_t cond; uint32 node[2]; }; + struct DomRule { uint32 atom : 29; uint32 type : 3; Id_t cond; int16 bias; uint16 prio; }; + struct Eq { Atom_t var; Literal lit; }; + struct TFilter { bool operator()(const Potassco::TheoryAtom& atom) const; LogicProgram* self; }; + struct Min { weight_t prio; Potassco::WLitVec lits; }; + struct CmpMin { bool operator()(const Min* m1, const Min* m2) const { return m1->prio < m2->prio; } }; + typedef Potassco::RuleBuilder RuleBuilder; + typedef std::pair ShowPair; + typedef PodVector::type ShowVec; + typedef PodVector::type DomRules; + typedef PodVector::type AcycRules; + typedef PodVector::type RuleList; + typedef PodVector::type MinList; + typedef PodVector::type SccMap; + typedef PodVector::type EqVec; + typedef Clasp::HashMap_t::multi_map_type IndexMap; + typedef IndexMap::iterator IndexIter; + typedef std::pair IndexRange; + typedef Potassco::WLitVec LpWLitVec; + typedef Potassco::LitVec LpLitVec; + typedef Range AtomRange; + // ------------------------------------------------------------------------ + // virtual overrides + bool doStartProgram(); + bool doUpdateProgram(); + bool doEndProgram(); + void doGetAssumptions(LitVec& out) const; + ProgramParser* doCreateParser(); + int doType() const { return Problem_t::Asp; } + // ------------------------------------------------------------------------ + // Program definition + bool isNew(Atom_t atomId) const { return atomId >= startAtom(); } + PrgAtom* resize(Atom_t atomId); + void pushFrozen(PrgAtom* atom, ValueRep v); + void addRule(const Rule& r, const SRule& meta); + void addFact(const Potassco::AtomSpan& head); + void addIntegrity(const Rule& b, const SRule& meta); + bool handleNatively(const Rule& r) const; + bool transformNoAux(const Rule& r) const; + void freezeTheory(); + void transformExtended(); + void transformIntegrity(uint32 nAtoms, uint32 maxAux); + PrgBody* getBodyFor(const Rule& r, const SRule& m, bool addDeps = true); + PrgBody* getTrueBody(); + PrgDisj* getDisjFor(const Potassco::AtomSpan& heads, uint32 headHash); + PrgBody* assignBodyFor(const Rule& r, const SRule& m, EdgeType x, bool strongSimp); + bool equalLits(const PrgBody& b, const WeightLitSpan& lits) const; + bool simplifyNormal(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body, RuleBuilder& out, SRule& info); + bool simplifySum(Head_t ht, const Potassco::AtomSpan& head, const Potassco::Sum_t& body, RuleBuilder& out, SRule& info); + bool pushHead(Head_t ht, const Potassco::AtomSpan& head, weight_t slack, RuleBuilder& out); + ValueRep litVal(const PrgAtom* a, bool pos) const; + uint32 findBody(uint32 hash, Body_t type, uint32 size, weight_t bound = -1, Potassco::WeightLit_t* wlits = 0); + uint32 findEqBody(const PrgBody* b, uint32 hash); + uint32 removeBody(PrgBody* b, uint32 oldHash); + Literal getEqAtomLit(Literal lit, const BodyList& supports, Preprocessor& p, const SccMap& x); + bool positiveLoopSafe(PrgBody* b, PrgBody* root) const; + void prepareExternals(); + void updateFrozenAtoms(); + void normalize(); + template + Id_t getEqNode(C& vec, Id_t id) const { + if (!vec[id]->eq()) return id; + typedef typename C::value_type NodeType; + NodeType n = vec[id], r; + Id_t root = n->id(); + for (r = vec[root]; r->eq(); r = vec[root]) { + // n == r and r == r' -> n == r' + assert(root != r->id()); + n->setEq(root = r->id()); + } + return root; + } + bool checkBody(const PrgBody& rhs, Body_t type, uint32 size, weight_t bound) const { + return (rhs.relevant() || (rhs.eq() && getBody(getEqBody(rhs.id()))->relevant())) + && rhs.type() == type && rhs.size() == size && rhs.bound() == bound; + } + // ------------------------------------------------------------------------ + // Nogood creation + void prepareProgram(bool checkSccs); + void prepareOutputTable(); + void finalizeDisjunctions(Preprocessor& p, uint32 numSccs); + void prepareComponents(); + bool addConstraints(); + void addAcycConstraint(); + void addDomRules(); + // ------------------------------------------------------------------------ + void deleteAtoms(uint32 start); + PrgAtom* getTrueAtom() const { return atoms_[0]; } + RuleBuilder rule_; // temporary: active rule + AtomState atomState_; // which atoms appear in the active rule? + IndexMap bodyIndex_; // hash -> body id + IndexMap disjIndex_; // hash -> disjunction id + IndexMap domEqIndex_; // maps eq atoms modified by dom heuristic to aux vars + BodyList bodies_; // all bodies + AtomList atoms_; // all atoms + DisjList disjunctions_;// all (head) disjunctions + MinList minimize_; // list of minimize rules + RuleList extended_; // extended rules to be translated + ShowVec show_; // shown atoms/conditions + VarVec initialSupp_; // bodies that are (initially) supported + VarVec propQ_; // assigned atoms + VarVec frozen_; // list of frozen atoms + NonHcfSet nonHcfs_; // set of non-hcf sccs + TheoryData* theory_; // optional map of theory data + AtomRange input_; // input atoms of current step + int statsId_; // which stats to update (0 or 1) + struct Aux { + AtomList scc; // atoms that are strongly connected + DomRules dom; // list of domain heuristic directives + AcycRules acyc; // list of user-defined edges for acyclicity check + LpLitVec assume; // set of assumptions + VarVec project; // atoms in projection directives + VarVec external; // atoms in external directives + }* auxData_; // additional state for handling extended constructs + struct Incremental { + Incremental(); + uint32 startScc; // first valid scc number in this iteration + VarVec unfreeze; // list of atoms to unfreeze in this step + VarVec doms; // list of atom variables with domain modification + }* incData_; // additional state for handling incrementally defined programs + AspOptions opts_; // preprocessing +}; +//! Returns the internal solver literal that is associated with the given atom literal. +/*! + * \pre The prg is frozen and atomLit is a known atom in prg. + */ +inline Literal solverLiteral(const LogicProgram& prg, Potassco::Lit_t atomLit) { + CLASP_ASSERT_CONTRACT(prg.frozen() && prg.validAtom(Potassco::atom(atomLit))); + return prg.getLiteral(Potassco::id(atomLit)); +} +//! Adapts a LogicProgram object to the Potassco::AbstractProgram interface. +class LogicProgramAdapter : public Potassco::AbstractProgram { +public: + LogicProgramAdapter(LogicProgram& prg); + void initProgram(bool inc); + void beginStep(); + void endStep(); + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body); + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body); + void minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits); + void project(const Potassco::AtomSpan& atoms); + void output(const Potassco::StringSpan& str, const Potassco::LitSpan& cond); + void external(Potassco::Atom_t a, Potassco::Value_t v); + void assume(const Potassco::LitSpan& lits); + void heuristic(Potassco::Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, const Potassco::LitSpan& cond); + void acycEdge(int s, int t, const Potassco::LitSpan& cond); + void theoryTerm(Potassco::Id_t termId, int number); + void theoryTerm(Potassco::Id_t termId, const Potassco::StringSpan& name); + void theoryTerm(Potassco::Id_t termId, int cId, const Potassco::IdSpan& args); + void theoryElement(Potassco::Id_t elementId, const Potassco::IdSpan& terms, const Potassco::LitSpan& cond); + void theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements); + void theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements, Potassco::Id_t op, Potassco::Id_t rhs); +protected: + Asp::LogicProgram* lp_; + bool inc_; +}; +//@} + +} } // end namespace Asp +#endif diff --git a/libclasp/clasp/logic_program_types.h b/libclasp/clasp/logic_program_types.h new file mode 100644 index 0000000..1530721 --- /dev/null +++ b/libclasp/clasp/logic_program_types.h @@ -0,0 +1,640 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_LOGIC_PROGRAM_TYPES_H_INCLUDED +#define CLASP_LOGIC_PROGRAM_TYPES_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif +/*! + * \file + * \brief Basic types for working with a logic program. + */ +#include +#include +#include +#include +namespace Potassco { + typedef Clasp::PodVector::type LitVec; + typedef Clasp::PodVector::type WLitVec; +} +namespace Clasp { +class ClauseCreator; +using Potassco::idMax; +namespace Asp { +typedef PodVector::type AtomList; +typedef PodVector::type BodyList; +typedef PodVector::type DisjList; +const ValueRep value_weak_true = 3; /**< true but no proof */ +using Potassco::Atom_t; +using Potassco::Id_t; +/*! + * \addtogroup asp + */ +//@{ +//! A node of a program-dependency graph. +/*! + * A node represents a relevant part in a logic program. Each node + * has at least a literal and a value. + */ +class PrgNode { +public: + //! Supported node types. + enum Type { Atom = 0u, Body = 1u, Disj = 2u }; + static const uint32 noScc = (1u << 27)-1; + static const uint32 noNode = (1u << 28)-1; + static const uint32 noLit = 1; + //! Creates a new node that corresponds to a literal that is false. + explicit PrgNode(uint32 id, bool checkScc = true); + //! Is the node still relevant or removed() resp. eq()? + bool relevant() const { return eq_ == 0; } + //! Was the node removed? + bool removed() const { return eq_ != 0 && id_ == noNode; } + //! Ignore the node during scc checking? + bool ignoreScc()const { return noScc_ != 0; } + //! Returns true if this node is equivalent to some other node. + /*! + * If eq() is true, the node is no longer relevant and must not be used any further. + * The only sensible operation is to call id() in order to get the id of the node + * that is equivalent to this node. + */ + bool eq() const { return eq_ != 0 && id_ != noNode; } + bool seen() const { return seen_ != 0; } + //! Returns true if node has an associated variable in a solver. + bool hasVar() const { return litId_ != noLit; } + //! Returns the variable associated with this node or sentVar if no var is associated with this node. + Var var() const { return litId_ >> 1; } + //! Returns the literal associated with this node or a sentinel literal if no var is associated with this node. + Literal literal() const { return Literal::fromId(litId_); } + //! Returns the value currently assigned to this node. + ValueRep value() const { return val_; } + //! Returns the current id of this node. + uint32 id() const { return id_; } + //! Returns the literal that must be true in order to fulfill the truth-value of this node. + Literal trueLit() const { + return value() == value_free + ? lit_true() + : literal() ^ (value() == value_false); + } + + /*! + * \name implementation functions + * Low-level implementation functions. Use with care and only if you + * know what you are doing! + */ + //@{ + void setLiteral(Literal x) { litId_ = x.id(); } + void clearLiteral(bool clVal){ litId_ = noLit; if (clVal) val_ = value_free; } + void setValue(ValueRep v) { val_ = v; } + void setEq(uint32 eqId) { id_ = eqId; eq_ = 1; seen_ = 1; } + void setIgnoreScc(bool b) { noScc_ = (uint32)b; } + void markRemoved() { if (!eq()) setEq(noNode); } + void setSeen(bool b) { seen_ = uint32(b); } + void resetId(uint32 id, bool seen) { + id_ = id; + eq_ = 0; + seen_ = (uint32)seen; + } + bool assignValueImpl(ValueRep v, bool noWeak) { + if (v == value_weak_true && noWeak) { v = value_true; } + if (value() == value_free || v == value() || (value() == value_weak_true && v == value_true)) { + setValue(v); + return true; + } + return v == value_weak_true && value() == value_true; + } + //@} +protected: + uint32 litId_ : 31; // literal-id in solver + uint32 noScc_ : 1; // ignore during scc checks? + uint32 id_ : 28; // own id/eq-id/root-id/ufs-id + uint32 val_ : 2; // assigned value + uint32 eq_ : 1; // removed or eq to some other node? + uint32 seen_ : 1; // marked as seen? +private: + PrgNode(const PrgNode&); + PrgNode& operator=(const PrgNode&); +}; +typedef PrgNode::Type NodeType; +//! An edge of a program-dependency graph. +/*! + * Currently, clasp distinguishes four types of edges: + * - a Normal edge stipulates an implication between body and head, + * i.e. tableau-rules FTA and BFA for atoms. + * - a Choice edge only stipulates a support. + * - a Gamma edge is like a Normal edge that is only considered during + * nogood creation but ignored in the dependency graph. + * - a GammaChoice edge is like a Gamma edge but only stipulates a support. + * The head of a rule is either an atom or a disjunction. + */ +struct PrgEdge { + //! Type of edge. + enum Type { Normal = 0, Gamma = 1, Choice = 2, GammaChoice = 3 }; + static PrgEdge noEdge() { PrgEdge x; x.rep = UINT32_MAX; return x; } + + template + static PrgEdge newEdge(const NT& n, Type eType) { + // 28-bit node id, 2-bit node type, 2-bit edge type + PrgEdge x = { (n.id() << 4) | (static_cast(n.nodeType()) << 2) | eType }; + return x; + } + //! Returns the id of the adjacent node. + uint32 node() const { return rep >> 4; } + //! Returns the type of this edge. + Type type() const { return Type(rep & 3u); } + //! Returns the type of adjacent node. + NodeType nodeType() const { return NodeType((rep >> 2) & 3u); } + //! Returns true if edge has normal semantic (normal edge or gamma edge). + bool isNormal() const { return (rep & 2u) == 0; } + //! Returns true if edge has choice semantic. + bool isChoice() const { return (rep & 2u) != 0; } + //! Returns true if the edge is a gamma (aux normal) edge. + bool isGamma() const { return (rep & 1u) != 0; } + //! Returns true if the adjacent node is a body. + bool isBody() const { return nodeType() == PrgNode::Body; } + //! Returns true if the adjacant node is an atom. + bool isAtom() const { return nodeType() == PrgNode::Atom; } + //! Returns true if the adjacent node is a disjunction. + bool isDisj() const { return nodeType() == PrgNode::Disj; } + bool operator< (PrgEdge rhs) const { return rep < rhs.rep; } + bool operator==(PrgEdge rhs) const { return rep == rhs.rep; } + uint32 rep; +}; + +typedef PrgEdge::Type EdgeType; +typedef const PrgEdge* EdgeIterator; +typedef bk_lib::pod_vector EdgeVec; +inline bool isChoice(EdgeType t) { return t >= PrgEdge::Choice; } + +using Potassco::Body_t; +using Potassco::Head_t; +using Potassco::WeightLitSpan; +typedef Potassco::Rule_t Rule; +//! A class for translating extended rules to normal rules. +class RuleTransform { +public: + //! Interface that must be implemented to get the result of a transformation. + struct ProgramAdapter { + virtual Atom_t newAtom() = 0; + virtual void addRule(const Rule& r) = 0; + protected: ~ProgramAdapter() {} + }; + //! Supported transformation strategies. + enum Strategy { strategy_default, strategy_select_no_aux, strategy_split_aux }; + RuleTransform(ProgramAdapter& prg); + RuleTransform(LogicProgram& prg); + ~RuleTransform(); + //! Transforms the given (extended) rule to a set of normal rules. + uint32 transform(const Rule& r, Strategy s = strategy_default); +private: + RuleTransform(const RuleTransform&); + RuleTransform& operator=(const RuleTransform&); + struct Impl; + Impl* impl_; +}; + +//! A set of flags used during rule simplification. +class AtomState { +public: + static const uint8 pos_flag = 0x1u; //!< In positive body of active rule + static const uint8 neg_flag = 0x2u; //!< In negative body of active rule + static const uint8 head_flag = 0x4u; //!< In normal head of active rule + static const uint8 choice_flag = 0x8u; //!< In choice head of active rule + static const uint8 disj_flag = 0x10u;//!< In disjunctive head of active rule + static const uint8 rule_mask = 0x1Fu;//!< In active rule + static const uint8 fact_flag = 0x20u;//!< Atom is a fact (sticky) + static const uint8 false_flag = 0x40u;//!< Atom is false (sticky) + static const uint8 simp_mask = 0x7fu;//!< In active rule or assigned + static const uint8 dom_flag = 0x80u;//!< Var of atom is a dom var (sticky) + AtomState() {} + void swap(AtomState& o) { state_.swap(o.state_); } + //! Does t.node() appear in the head of the active rule? + bool inHead(PrgEdge t) const { return isSet(t.node(), headFlag(t)); } + bool inHead(Atom_t atom) const { return isSet(atom, head_flag); } + //! Does p appear in the body of the active rule? + bool inBody(Literal p) const { return isSet(p.var(), pos_flag+p.sign()); } + bool isSet(Var v, uint8 f) const { return v < state_.size() && (state_[v] & f) != 0; } + bool isFact(Var v) const { return isSet(v, fact_flag); } + //! Mark v as a head of the active rule. + void addToHead(Atom_t v) { set(v, head_flag); } + void addToHead(PrgEdge t) { set(t.node(), headFlag(t)); } + //! Mark p as a literal contained in the active rule. + void addToBody(Literal p) { set(p.var(), pos_flag+p.sign()); } + + void set(Var v, uint8 f) { grow(v); state_[v] |= f; } + void clear(Var v, uint8 f) { if (v < state_.size()) { state_[v] &= ~f; } } + void clearRule(Var v) { clear(v, rule_mask); } + void clearHead(PrgEdge t) { clear(t.node(), headFlag(t)); } + void clearBody(Literal p) { clear(p.var(), pos_flag+p.sign()); } + void resize(uint32 sz) { state_.resize(sz); } + + template + bool allMarked(IT first, IT last, uint8 f) const { + for (; first != last; ++first) { + if (!isSet(*first, f)) return false; + } + return true; + } + bool inBody(const Literal* first, const Literal* last) const { + bool all = true; + for (; first != last && (all = inBody(*first)) == true; ++first) { ; } + return all; + } +private: + typedef PodVector::type StateVec; + void grow(Var v) { if (v >= state_.size()) { state_.resize(v+1); } } + uint8 headFlag(PrgEdge t) const { + return t.isAtom() ? (head_flag << uint8(t.isChoice())) : disj_flag; + } + StateVec state_; +}; + +//! A head node of a program-dependency graph. +/*! + * A head node is either an atom or a disjunction + * and stores its possible supports. + */ +class PrgHead : public PrgNode { +public: + enum Simplify { no_simplify = 0, force_simplify = 1 }; + typedef EdgeIterator sup_iterator; + + //! Is the head part of the (simplified) program? + bool inUpper() const { return relevant() && upper_ != 0; } + //! Is this head an atom? + bool isAtom() const { return isAtom_ != 0; } + //! Number of supports (rules) for this head. + uint32 supports() const { return supports_.size(); } + sup_iterator supps_begin()const { return supports_.begin(); } + sup_iterator supps_end() const { return supports_.end(); } + //! External atom (or defined in a later incremental step)? + bool frozen() const { return freeze_ != uint32(freeze_no); } + //! If frozen(), value to assume during solving. + ValueRep freezeValue()const { return static_cast(freeze_ - uint32(freeze_ != 0)); } + //! If frozen(), literal to assume during solving. + Literal assumption() const { return freeze_ > uint32(freeze_free) ? literal() ^ (freeze_ == freeze_false) : lit_true(); } + //! Adds r as support edge for this node. + void addSupport(PrgEdge r){ addSupport(r, force_simplify); } + void addSupport(PrgEdge r, Simplify s); + //! Removes r from the head's list of supports. + void removeSupport(PrgEdge r); + void clearSupports(); + void clearSupports(EdgeVec& to) { to.swap(supports_); clearSupports(); } + //! Removes any superfluous/irrelevant supports. + bool simplifySupports(LogicProgram& prg, bool strong, uint32* numDiffSupps = 0); + //! Assigns the value v to this head. + bool assignValue(ValueRep v) { return assignValueImpl(v, ignoreScc() && !frozen()); } + /*! + * \name implementation functions + * Low-level implementation functions. Use with care and only if you + * know what you are doing! + */ + //@{ + void setInUpper(bool b) { upper_ = (uint32)b; } + void markDirty() { dirty_ = 1; } + void assignVar(LogicProgram& prg, PrgEdge it, bool allowEq = true); + NodeType nodeType() const { return isAtom() ? PrgNode::Atom : PrgNode::Disj; } + //@} +protected: + enum FreezeState { freeze_no = 0u, freeze_free = 1u, freeze_true = 2u, freeze_false = 3u }; + //! Creates a new node that corresponds to a literal that is false. + explicit PrgHead(uint32 id, NodeType t, uint32 data = 0, bool checkScc = true); + bool backpropagate(LogicProgram& prg, ValueRep val, bool bpFull); + EdgeVec supports_; // possible supports (body or disjunction) + uint32 data_ : 27; // number of atoms in disjunction or scc of atom + uint32 upper_ : 1; // in (simplified) program? + uint32 dirty_ : 1; // is list of supports dirty? + uint32 freeze_: 2; // incremental freeze state + uint32 isAtom_: 1; // is this head an atom? +}; + +//! An atom in a logic program. +/*! + * An atom stores the list of bodies depending on it. + * Furthermore, once strongly-connected components are identified, + * atoms store their SCC-number. All trivial SCCs are represented + * with the special SCC-number PrgNode::noScc. + */ +class PrgAtom : public PrgHead { +public: + enum Dependency { dep_pos = 0, dep_neg = 1, dep_all = 2 }; + typedef LitVec::const_iterator dep_iterator; + explicit PrgAtom(uint32 id, bool checkScc = true); + NodeType nodeType() const { return PrgNode::Atom; } + //! Strongly connected component of this node. + uint32 scc() const { return data_; } + //! If eq(), stores the literal that is eq to this atom. + Literal eqGoal(bool sign) const; + //! Returns true if atom belongs to a disjunctive head. + bool inDisj() const; + /*! + * \name forward dependencies (bodies containing this atom) + */ + //@{ + dep_iterator deps_begin() const { return deps_.begin(); } + dep_iterator deps_end() const { return deps_.end(); } + bool hasDep(Dependency d) const; + void addDep(Id_t bodyId, bool pos); + void removeDep(Id_t bodyId, bool pos); + void clearDeps(Dependency d); + //@} + + /*! + * \name implementation functions + * Low-level implementation functions. Use with care and only if you + * know what you are doing! + */ + //@{ + void setEqGoal(Literal x); + bool propagateValue(LogicProgram& prg, bool backprop); + bool addConstraints(const LogicProgram& prg, ClauseCreator& c); + void setScc(uint32 scc) { data_ = scc; } + void markFrozen(ValueRep v){ freeze_ = v + freeze_free; } + void clearFrozen() { freeze_ = freeze_no; markDirty(); } + //@} +private: + LitVec deps_; // bodies depending on this atom +}; + +//! A (rule) body in a logic program. +class PrgBody : public PrgNode { +public: + typedef EdgeIterator head_iterator; + typedef const Literal* goal_iterator; + + //! Creates a new body node and (optionally) connects it to its predecessors (i.e. atoms). + /*! + * \param prg The program in which the new body is used. + * \param id The id for the new body node. + * \param rule The rule for which a body node is to be created. + * \param pos Positive body size. + * \param addDeps If true, add an edge between each atom subgoal and the new node. + */ + static PrgBody* create(LogicProgram& prg, uint32 id, const Rule& rule, uint32 pos, bool addDeps); + //! Destroys a body node created via create(). + void destroy(); + Body_t type() const { return Body_t(static_cast(type_)); } + //! Returns the number of atoms in the body. + uint32 size() const { return size_; } + bool noScc() const { return size() == 0 || goal(0).sign(); } + //! Returns the bound of this body, or size() if the body is a normal body. + weight_t bound() const { if (type() == Body_t::Normal) return (weight_t)size(); else return hasWeights() ? sumData()->bound : aggData().bound; } + //! Returns the sum of the subgoals weights, or size() if the body is not a sum with weights. + weight_t sumW() const { return static_cast(!hasWeights() ? (weight_t)size() : sumData()->sumW); } + //! Returns the idx'th subgoal as a literal. + Literal goal(uint32 idx) const { assert(idx < size()); return *(goals_begin()+idx); } + //! Returns the weight of the idx'th subgoal. + weight_t weight(uint32 idx)const { assert(idx < size()); return !hasWeights() ? 1 : sumData()->weights[idx]; } + //! Returns true if the body node is supported. + /*! + * A normal body is supported, iff all of its positive subgoals are supported. + * A count/sum body is supported if the sum of the weights of the supported positive + + * the sum of the negative weights is >= lowerBound(). + */ + bool isSupported() const { return unsupp_ <= 0; } + //! Returns true if this body defines any head. + bool hasHeads() const { return isSmallHead() ? head_ != 0 : !largeHead()->empty(); } + bool inRule() const { return hasHeads() || freeze_; } + + head_iterator heads_begin() const { return isSmallHead() ? smallHead() : largeHead()->begin(); } + head_iterator heads_end() const { return isSmallHead() ? smallHead()+head_ : largeHead()->end(); } + goal_iterator goals_begin() const { return const_cast(this)->goals_begin(); } + goal_iterator goals_end() const { return goals_begin() + size(); } + //! Adds a rule edge between this body and the given head. + /*! + * \note + * The function also adds a corresponding back edge to the head. + * \note + * Adding a head invalidates the set property for the heads of this body. + * To restore it, call simplifyHeads() + */ + void addHead(PrgHead* h, EdgeType t); + //! Simplifies the heads of this body and establishes set property. + /*! + * Removes superfluous heads and sets the body to false if for some atom a + * in the head of this body B, Ta -> FB. In that case, all heads atoms are removed, because + * a false body can't define any atom. + * If strong is true, removes head atoms that are not associated with a variable. + * \return + * setValue(value_false) if setting a head of this body to true would + * make the body false (i.e. the body is a selfblocker). Otherwise, true. + */ + bool simplifyHeads(LogicProgram& prg, bool strong); + bool mergeHeads(LogicProgram& prg, PrgBody& heads, bool strong, bool simplify = true); + void removeHead(PrgHead* h, EdgeType t); + bool hasHead(PrgHead* h, EdgeType t) const; + //! Simplifies the body, i.e. its predecessors-lists. + /*! + * - removes true/false atoms from B+/B- resp. + * - removes/merges duplicate subgoals + * - checks whether body must be false (e.g. contains false/true atoms in B+/B- resp. or contains p and ~p) + * + * \pre prg.getBody(id()) == this + * + * \param[in] prg The program containing this body. + * \param[in] strong If true, treats atoms that have no variable associated as false. + * \param[out] eqId The id of a body in prg that is equivalent to this body. + * + * \return + * - true if simplification was successful + * - false if simplification detected a conflict + */ + bool simplifyBody(LogicProgram& prg, bool strong, uint32* eqId = 0); + //! Calls simplifyBody() and/or simplifyHeads() if necessary. + bool simplify(LogicProgram& prg, bool strong, uint32* eqId = 0) { + return simplifyBody(prg, strong, eqId) && simplifyHeads(prg, strong); + } + bool toData(const LogicProgram& prg, Potassco::RuleBuilder& out) const; + //! Notifies the body node about the fact that its positive subgoal v is supported. + /*! + * \return true if the body is now also supported, false otherwise. + */ + bool propagateSupported(Var /* v */); + //! Propagates the assignment of subgoal p. + bool propagateAssigned(LogicProgram& prg, Literal p, ValueRep v); + //! Propagates the assignment of a head. + bool propagateAssigned(LogicProgram& prg, PrgHead* h, EdgeType t); + //! Propagates the value of this body. + bool propagateValue(LogicProgram& prg, bool backprop); + bool propagateValue(LogicProgram& prg); + bool addConstraints(const LogicProgram& prg, ClauseCreator& c); + void markDirty() { sBody_ = 1; } + void markHeadsDirty() { sHead_ = 1; } + void markFrozen() { freeze_= 1; } + void clearHeads(); + bool resetSupported(); + void assignVar(LogicProgram& prg); + bool assignValue(ValueRep v) { return assignValueImpl(v, noScc()); } + uint32 scc(const LogicProgram& prg) const; + bool hasWeights() const { return type() == Body_t::Sum; } + void clearRule(AtomState& rs) const { + for (head_iterator it = heads_begin(), end = heads_end(); it != end; ++it) { + rs.clearRule(it->node()); + } + for (const Literal* it = goals_begin(), *end = it + size(); it != end; ++it) { + rs.clearRule(it->var()); + } + } + NodeType nodeType() const { return PrgNode::Body; } +private: + static const uint32 maxSize = (1u<<26)-1; + typedef unsigned char byte_t; +CLASP_WARNING_BEGIN_RELAXED + struct SumData { + enum { LIT_OFFSET = sizeof(void*)/sizeof(uint32) }; + static SumData* create(uint32 size, weight_t bnd, weight_t ws); + void destroy(); + weight_t bound; + weight_t sumW; + weight_t weights[0]; + }; + struct Agg { + union { + SumData* sum; + weight_t bound; + }; + Literal lits[0]; + }; + struct Norm { Literal lits[0]; }; + PrgBody(uint32 id, LogicProgram& prg, const Potassco::LitSpan& lits, uint32 pos, bool addDeps); + PrgBody(uint32 id, LogicProgram& prg, const Potassco::Sum_t& sum, bool hasWeights, uint32 pos, bool addDeps); + void init(Body_t t, uint32 sz); + ~PrgBody(); + uint32 findLit(const LogicProgram& prg, Literal p) const; + bool normalize(const LogicProgram& prg, weight_t bound, weight_t sumW, weight_t reachW, uint32& hashOut); + void prepareSimplifyHeads(LogicProgram& prg, AtomState& rs); + bool simplifyHeadsImpl(LogicProgram& prg, PrgBody& target, AtomState& rs, bool strong); + bool superfluousHead(const LogicProgram& prg, const PrgHead* head, PrgEdge it, const AtomState& rs) const; + bool blockedHead(PrgEdge it, const AtomState& rs) const; + void addHead(PrgEdge h); + bool eraseHead(PrgEdge h); + bool isSmallHead() const { return head_ != 3u; } + byte_t* data() const { return const_cast(static_cast(data_)); } + PrgEdge* smallHead() const { return const_cast(headData_.sm); } + EdgeVec* largeHead() const { return headData_.ext; } + SumData* sumData() const { return aggData().sum;} + Agg& aggData() const { return *reinterpret_cast(data()); } + Literal* goals_begin() { return type() == Body_t::Normal ? reinterpret_cast(data())->lits : aggData().lits; } + Literal* goals_end() { return goals_begin() + size(); } + + uint32 size_ : 25; // |B| + uint32 head_ : 2; // simple or extended head? + uint32 type_ : 2; // body type + uint32 sBody_ : 1; // simplify body? + uint32 sHead_ : 1; // simplify head? + uint32 freeze_ : 1; // keep body even if it does not occur in a rule? + weight_t unsupp_; // <= 0 -> body is supported + union Head { + PrgEdge sm[2]; + EdgeVec* ext; + } headData_; // successors of this body + byte_t data_[0]; // empty or one of Agg|Norm +CLASP_WARNING_END_RELAXED +}; +//! The head of a disjunctive rule. +class PrgDisj : public PrgHead { +public: + typedef const Var* atom_iterator; + //! Constructor for disjunctions. + static PrgDisj* create(uint32 id, const Potassco::AtomSpan& head); + //! Destroys a disjunction created via create(). + void destroy(); + void detach(LogicProgram& prg); + //! Number of atoms in disjunction. + uint32 size() const { return data_; } + atom_iterator begin() const { return atoms_; } + atom_iterator end() const { return atoms_ + size(); } + //! Propagates the assignment of an atom in this disjunction. + bool propagateAssigned(LogicProgram& prg, PrgHead* at, EdgeType t); +private: + explicit PrgDisj(uint32 id, const Potassco::AtomSpan& head); + ~PrgDisj(); +CLASP_WARNING_BEGIN_RELAXED + Var atoms_[0]; // atoms in disjunction +CLASP_WARNING_END_RELAXED +}; + +inline ValueRep getMergeValue(const PrgNode* lhs, const PrgNode* rhs) { + return static_cast(std::min(static_cast(lhs->value()-1), static_cast(rhs->value()-1)) + 1); +} + +template +bool mergeValue(NT* lhs, NT* rhs){ + ValueRep mv = getMergeValue(lhs, rhs); + return (lhs->value() == mv || lhs->assignValue(mv)) + && (rhs->value() == mv || rhs->assignValue(mv)); +} + +//! A class for computing strongly connected components of the positive atom-body dependency graph. +class SccChecker { +public: + SccChecker(LogicProgram& prg, AtomList& sccAtoms, uint32 startScc); + uint32 sccs() const { return sccs_; } + void visit(PrgBody* body) { visitDfs(body, PrgNode::Body); } + void visit(PrgAtom* atom) { visitDfs(atom, PrgNode::Atom); } + void visit(PrgDisj* disj) { visitDfs(disj, PrgNode::Disj); } +private: + struct Call { + uintp node; + uint32 min; + uint32 next; + }; + typedef PodVector::type CallStack; + typedef PodVector::type NodeStack; + static uintp packNode(PrgNode* n, NodeType t) { return reinterpret_cast(n) + uintp(t); } + static PrgNode* unpackNode(uintp n) { return reinterpret_cast(n & ~uintp(3u));} + static bool isNode(uintp n, NodeType t) { return (n & 3u) == uintp(t); } + bool doVisit(PrgNode* n, bool seen = true) const { return !n->ignoreScc() && n->relevant() && n->hasVar() && (!seen || !n->seen()); } + void visitDfs(PrgNode* n, NodeType t); + bool recurse(Call& c); + bool onNode(PrgNode* n, NodeType t, Call& c, uint32 data); + void addCall(PrgNode* n, NodeType t, uint32 next, uint32 min = 0) { + Call c = {packNode(n, t), min, next}; + callStack_.push_back(c); + } + CallStack callStack_; + NodeStack nodeStack_; + LogicProgram* prg_; + AtomList* sccAtoms_; + uint32 count_; + uint32 sccs_; +}; +//! A set of ids of strongly connected components having at least one head-cycle. +struct NonHcfSet : private PodVector::type { +public: + typedef PodVector::type base_type; + typedef base_type::const_iterator const_iterator; + using base_type::begin; + using base_type::end; + using base_type::size; + NonHcfSet() : config(0) {} + void add(uint32 scc) { + iterator it = std::lower_bound(begin(), end(), scc); + if (it == end() || *it != scc) { insert(it, scc); } + } + bool find(uint32 scc) const { + const_iterator it = scc != PrgNode::noScc ? std::lower_bound(begin(), end(), scc) : end(); + return it != end() && *it == scc; + } + Configuration* config; +}; +//@} +} } +#endif diff --git a/libclasp/clasp/lookahead.h b/libclasp/clasp/lookahead.h new file mode 100644 index 0000000..ab8c094 --- /dev/null +++ b/libclasp/clasp/lookahead.h @@ -0,0 +1,239 @@ +// +// Copyright (c) 2009, 2012 Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_LOOKAHEAD_H_INCLUDED +#define CLASP_LOOKAHEAD_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +/*! + * \file + * \brief Defines lookahead related types. + * + * Lookahead can be used as a post propagator (e.g. failed-literal detection) and + * optionally as an heuristic. + */ + +#include +#include +namespace Clasp { +/*! + * \addtogroup propagator + */ +//@{ + +//! Type used to store lookahead-information for one variable. +struct VarScore { + VarScore() { clear(); } + void clear() { std::memset(this, 0, sizeof(VarScore)); } + //! Mark literal p as dependent. + void setSeen( Literal p ) { seen_ |= uint32(p.sign()) + 1; } + //! Is literal p dependent? + bool seen(Literal p) const { return (seen_ & (uint32(p.sign())+1)) != 0; } + //! Is this var dependent? + bool seen() const { return seen_ != 0; } + //! Mark literal p as tested during lookahead. + void setTested( Literal p ) { tested_ |= uint32(p.sign()) + 1; } + //! Was literal p tested during lookahead? + bool tested(Literal p) const { return (tested_ & (uint32(p.sign())+1)) != 0; } + //! Was some literal of this var tested? + bool tested() const { return tested_ != 0; } + //! Were both literals of this var tested? + bool testedBoth() const { return tested_ == 3; } + + //! Sets the score for literal p to value and marks p as tested. + void setScore(Literal p, LitVec::size_type value) { + if (value > (1U<<14)-1) value = (1U<<14)-1; + if (p.sign()) nVal_ = uint32(value); + else pVal_ = uint32(value); + setTested(p); + } + //! Sets the score of a dependent literal p to min(sc, current score). + void setDepScore(Literal p, uint32 sc) { + if (!seen(p) || score(p) > sc) { + if (sc > (1U<<14)-1) sc = (1U<<14)-1; + if (p.sign()) nVal_ = std::min(uint32(nVal_-(nVal_==0)), sc); + else pVal_ = std::min(uint32(pVal_-(pVal_==0)), sc); + } + } + //! Returns the score for literal p. + uint32 score(Literal p) const { return p.sign() ? nVal_ : pVal_; } + //! Returns the scores of the two literals of a variable. + /*! + * \param[out] mx The maximum score. + * \param[out] mn The minimum score. + */ + void score(uint32& mx, uint32& mn) const { + if (nVal_ > pVal_) { + mx = nVal_; + mn = pVal_; + } + else { + mx = pVal_; + mn = nVal_; + } + } + //! Returns the sign of the literal that has the higher score. + bool prefSign() const { return nVal_ > pVal_; } + + uint32 nVal() const { return nVal_; } + uint32 pVal() const { return pVal_; } +private: + uint32 pVal_ : 14; + uint32 nVal_ : 14; + uint32 seen_ : 2; + uint32 tested_: 2; +}; + +//! A small helper class used to score the result of a lookahead operation. +struct ScoreLook { + enum Mode { score_max, score_max_min }; + typedef PodVector::type VarScores; /**< A vector of variable-scores */ + ScoreLook() : best(0), mode(score_max), addDeps(true), nant(false) {} + bool validVar(Var v) const { return v < score.size(); } + void scoreLits(const Solver& s, const Literal* b, const Literal *e); + void clearDeps(); + uint32 countNant(const Solver& s, const Literal* b, const Literal *e) const; + bool greater(Var lhs, Var rhs)const; + bool greaterMax(Var x, uint32 max) const { + return score[x].nVal() > max || score[x].pVal() > max; + } + bool greaterMaxMin(Var lhs, uint32 max, uint32 min) const { + uint32 lhsMin, lhsMax; + score[lhs].score(lhsMax, lhsMin); + return lhsMin > min || (lhsMin == min && lhsMax > max); + } + VarScores score; //!< score[v] stores lookahead score of v + VarVec deps; //!< Tested vars and those that follow from them. + VarType types; //!< Var types to consider. + Var best; //!< Var with best score among those in deps. + Mode mode; //!< Score mode to apply. + bool addDeps;//!< Add/score dependent vars? + bool nant; //!< Score only atoms in NegAnte(P)? +}; + +class UnitHeuristic; + +//! Lookahead extends propagation with failed-literal detection. +/*! + * The class provides different kinds of one-step lookahead. + * Atom- and body-lookahead are uniform lookahead types, where + * either only atoms or bodies are tested. Hybrid-lookahead tests + * both types of vars but each only in a single phase. I.e. atoms + * are only tested negatively while bodies are tested positively. + */ +class Lookahead : public PostPropagator { +public: + //! Set of parameters to configure lookahead. + struct Params { + Params(VarType t = Var_t::Atom) : type(t), lim(0), topLevelImps(true), restrictNant(false) {} + Params& lookahead(VarType t){ type = t; return *this; } + Params& addImps(bool b) { topLevelImps = b; return *this; } + Params& nant(bool b) { restrictNant = b; return *this; } + Params& limit(uint32 x) { lim = x; return *this; } + VarType type; + uint32 lim; + bool topLevelImps; + bool restrictNant; + }; + static bool isType(uint32 t) { return t != 0 && t <= Var_t::Hybrid; } + /*! + * \param p Lookahead parameters to use. + */ + explicit Lookahead(const Params& p); + ~Lookahead(); + + bool init(Solver& s); + //! Clears the lookahead list. + void clear(); + //! Returns true if lookahead list is empty. + bool empty() const { return head()->next == head_id; } + //! Adds literal p to the lookahead list. + void append(Literal p, bool testBoth); + //! Executes a single-step lookahead on all vars in the loookahead list. + bool propagateFixpoint(Solver& s, PostPropagator*); + //! Returns PostPropagator::priority_reserved_look. + uint32 priority() const; + void destroy(Solver* s, bool detach); + ScoreLook score; //!< State of last lookahead operation. + //! Returns "best" literal w.r.t scoring of last lookahead or lit_true() if no such literal exists. + Literal heuristic(Solver& s); + void detach(Solver& s); + bool hasLimit() const { return limit_ != 0; } +protected: + bool propagateLevel(Solver& s); // called by propagate + void undoLevel(Solver& s); + bool test(Solver& s, Literal p); +private: + typedef uint32 NodeId; + enum { head_id = NodeId(0), undo_id = NodeId(1) }; + struct LitNode { + LitNode(Literal x) : lit(x), next(UINT32_MAX) {} + Literal lit; + NodeId next; + }; + typedef PodVector::type UndoStack; + typedef PodVector::type LookList; + typedef UnitHeuristic* HeuPtr; + void splice(NodeId n); + LitNode* node(NodeId n) { return &nodes_[n]; } + LitNode* head() { return &nodes_[head_id]; } // head of circular candidate list + LitNode* undo() { return &nodes_[undo_id]; } // head of undo list + bool checkImps(Solver& s, Literal p); + const LitNode* head() const { return &nodes_[head_id]; } + LookList nodes_; // list of literals to test + UndoStack saved_; // stack of undo lists + LitVec imps_; // additional top-level implications + NodeId last_; // last candidate in list; invariant: node(last_)->next == head_id; + NodeId pos_; // current lookahead start position + uint32 top_; // size of top-level + uint32 limit_; // stop lookahead after this number of applications +}; +//@} + +//! Heuristic that uses the results of lookahead. +/*! + * \ingroup heuristic + * The heuristic uses a Lookahead post propagator to select a literal with the highest score, + * where the score is determined by counting assignments made during + * failed-literal detection. For hybrid_lookahead, the heuristic selects the literal that + * derived the most literals. On the other hand, for uniform_lookahead the heuristic is similar to + * the smodels lookahead heuristic and selects the literal that maximizes the minimum. + * \see Patrik Simons: "Extending and Implementing the Stable Model Semantics" for a + * detailed description of the lookahead heuristic. + * + * \note The heuristic might itself apply some lookahead but only on variables that + * did not fail in a previous call to Lookahead::propagateFixpoint(). I.e. if + * priorities are correct for all post propagators in s, the lookahead operations can't fail. + * + * \note If no Lookahead post propagator exists in the solver, the heuristic selects the first free variable! + */ +class UnitHeuristic : public SelectFirst { +public: + UnitHeuristic(); + //! Decorates the heuristic given in other with temporary lookahead. + static UnitHeuristic* restricted(DecisionHeuristic* other); + void endInit(Solver& /* s */); + Literal doSelect(Solver& s); +}; + +} +#endif diff --git a/libclasp/clasp/minimize_constraint.h b/libclasp/clasp/minimize_constraint.h new file mode 100644 index 0000000..264c05f --- /dev/null +++ b/libclasp/clasp/minimize_constraint.h @@ -0,0 +1,571 @@ +// +// Copyright (c) 2010-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_MINIMIZE_CONSTRAINT_H_INCLUDED +#define CLASP_MINIMIZE_CONSTRAINT_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif +/*! +* \file +* \brief Types and functions for implementing minimization constraints. +*/ +#include +#include +#include +#include + +namespace Clasp { +class MinimizeConstraint; +class WeightConstraint; + +//! Supported minimization modes. +/*! + * \ingroup constraint + * Defines the possible minimization modes used during solving. + * If optimize is used, a valid candidate model is a solution that is + * strictly smaller than all previous solutions. Otherwise, + * solutions with costs no greater than a fixed bound are considered valid. + */ +struct MinimizeMode_t { + enum Mode { + ignore = 0, //!< Ignore optimize statements during solving. + optimize = 1, //!< Optimize via a decreasing bound. + enumerate = 2, //!< Enumerate models with cost less or equal to a fixed bound. + enumOpt = 3, //!< Enumerate models with cost equal to optimum. + }; + //! Strategy to use when optimization is active. + enum Strategy { + opt_bb = 0, //!< Branch and bound based optimization. + opt_usc= 1, //!< Unsatisfiable-core based optimization. + }; + //! Options for branch and bound based optimization. + enum BBOption { + bb_step_def = 0u, //!< Branch and bound with fixed step of size 1. + bb_step_hier = 1u, //!< Hierarchical branch and bound. + bb_step_inc = 2u, //!< Hierarchical branch and bound with increasing steps. + bb_step_dec = 3u, //!< Hierarchical branch and bound with decreasing steps. + }; + //! Options for unsatisfiable-core based optimization. + enum UscOption { + usc_preprocess = 1u, //!< Enable (disjoint) preprocessing. + usc_imp_only = 2u, //!< Only add constraints for one direction (instead of eq). + usc_clauses = 4u, //!< Only add clauses (instead of cardinality constraints). + usc_stratify = 8u, //!< Use stratified heuristic for weighted optimization. + }; + //! Heuristic options common to all optimization strategies. + enum Heuristic { + heu_sign = 1, //!< Use optimize statements in sign heuristic. + heu_model = 2, //!< Apply model heuristic when optimizing. + }; + static bool supportsSplitting(Strategy s) { return s != opt_usc; } +}; +typedef MinimizeMode_t::Mode MinimizeMode; + +//! A type holding data (possibly) shared between a set of minimize constraints. +/*! + * \ingroup shared_con + */ +class SharedMinimizeData { +public: + typedef SharedMinimizeData ThisType; + //! A type to represent a weight at a certain level. + /*! + * Objects of this type are used to create sparse vectors of weights. E.g. + * a weight vector (w1\@L1, w2\@L3, w3\@L5) is represented as \[\\\\], + * where each \-tuple is an object of type LevelWeight. + */ + struct LevelWeight { + LevelWeight(uint32 l, weight_t w) : level(l), next(0), weight(w) {} + uint32 level : 31; //!< The level of this weight. + uint32 next : 1; //!< Does this weight belong to a sparse vector of weights? + weight_t weight; //!< The weight at this level. + }; + //! A type for holding sparse vectors of level weights of a multi-level constraint. + typedef PodVector::type WeightVec; + typedef PodVector::type PrioVec; + explicit SharedMinimizeData(const SumVec& lhsAdjust, MinimizeMode m = MinimizeMode_t::optimize); + //! Increases the reference count of this object. + ThisType* share() { ++count_; return this; } + //! Decreases the object's reference count and destroys it if reference count drops to 0. + void release() { if (--count_ == 0) destroy(); } + //! Number of minimize statements contained in this constraint. + uint32 numRules() const{ return static_cast(adjust_.size()); } + uint32 maxLevel() const{ return numRules()-1; } + static wsum_t maxBound() { return INT64_MAX; } + //! Returns the active minimization mode. + MinimizeMode mode() const{ return mode_; } + //! Returns true if optimization is active. + bool optimize() const{ return optGen_ ? checkNext() : mode_ != MinimizeMode_t::enumerate; } + //! Returns the lower bound of level x. + wsum_t lower(uint32 x) const; + //! Returns the upper bound of level x. + wsum_t upper(uint32 x) const{ return upper()[x]; } + const wsum_t* upper() const{ return &(up_ + (gCount_ & 1u))->front(); } + //! Returns the sum of level x in the most recent model. + wsum_t sum(uint32 x) const{ return sum()[x]; } + const wsum_t* sum() const{ return (mode_ != MinimizeMode_t::enumerate) ? upper() : &up_[1][0]; } + //! Returns the adjustment for level x. + wsum_t adjust(uint32 x) const{ return adjust_[x]; } + const wsum_t* adjust() const{ return &adjust_[0]; } + //! Returns the current (ajusted and possibly tentative) optimum for level x. + wsum_t optimum(uint32 x)const; + //! Returns the highest level of the literal with the given index i. + uint32 level(uint32 i) const{ return numRules() == 1 ? 0 : weights[lits[i].second].level; } + //! Returns the most important weight of the literal with the given index i. + weight_t weight(uint32 i) const{ return numRules() == 1 ? lits[i].second : weights[lits[i].second].weight; } + uint32 generation() const{ return gCount_; } + //! Returns whether minimization should search for solutions with current or next smaller upper bound. + bool checkNext() const{ return mode() != MinimizeMode_t::enumerate && generation() != optGen_; } + /*! + * \name interface for optimization + * If not otherwise specified, the following functions shall not be called concurrently. + */ + //@{ + + //! Sets the enumeration mode and (optionally) an initial bound. + /*! + * \note If m is MinimizeMode::enumerate, the caller should always + * set a bound. Otherwise, *all* solutions are considered valid. + */ + bool setMode(MinimizeMode m, const wsum_t* bound = 0, uint32 boundSize = 0); + bool setMode(MinimizeMode m, const SumVec& bound) { return setMode(m, bound.empty() ? 0 : &bound[0], (uint32)bound.size()); } + void resetBounds(); + + //! Attaches a new minimize constraint to this data object. + /*! + * \param s Solver in which the new minimize constraint should apply. + * \param strat The optimization strategy to use (see MinimizeMode_t::Strategy). + * \param param Parameter to pass to the optimization strategy. + * \param addRef If true, the ref count of the shared object is increased. + * Otherwise, the new minimize constraint inherits the reference to the shared object. + */ + MinimizeConstraint* attach(Solver& s, MinimizeMode_t::Strategy strat, uint32 param = 0, bool addRef = true); + + //! Makes opt the new (tentative) optimum. + /*! + * \pre opt is a pointer to an array of size numRules() + */ + const SumVec* setOptimum(const wsum_t* opt); + //! Marks the current tentative optimum as the final optimum. + /*! + * \note Once a final optimum is set, further calls to setOptimum() + * are ignored until resetBounds() is called. + */ + void markOptimal(); + //! Sets the lower bound of level lev to low. + void setLower(uint32 lev, wsum_t low); + //! Sets the lower bound of level lev to the maximum of low and the existing value lower(lev). + /*! + * \note This function is thread-safe, i.e., can be called safely from multiple threads. + */ + wsum_t incLower(uint32 lev, wsum_t low); + //@} + + /*! + * \name Arithmetic functions on weights. + */ + //@{ + //! Computes lhs += weight(lit). + void add(wsum_t* lhs, const WeightLiteral& lit) const { if (weights.empty()) *lhs += lit.second; else add(lhs, &weights[lit.second]); } + void add(wsum_t* lhs, const LevelWeight* w) const { do { lhs[w->level] += w->weight; } while (w++->next); } + //! Computes lhs -= weight(lit). + void sub(wsum_t* lhs, const WeightLiteral& lit, uint32& aLev) const { if (weights.empty()) *lhs -= lit.second; else sub(lhs, &weights[lit.second], aLev); } + void sub(wsum_t* lhs, const LevelWeight* w, uint32& aLev) const; + //! Returns (lhs + weight(lit)) > rhs + bool imp(wsum_t* lhs, const WeightLiteral& lit, const wsum_t* rhs, uint32& lev) const { + return weights.empty() ? (*lhs+lit.second) > *rhs : imp(lhs, &weights[lit.second], rhs, lev); + } + bool imp(wsum_t* lhs, const LevelWeight* w, const wsum_t* rhs, uint32& lev) const; + //! Returns the weight of lit at level lev. + weight_t weight(const WeightLiteral& lit, uint32 lev) const { + if (numRules() == 1) { return lit.second * (lev == 0); } + const LevelWeight* w = &weights[lit.second]; + do { if (w->level == lev) return w->weight; } while (w++->next); + return 0; + } + //@} +private: + typedef Clasp::Atomic_t::type CounterType; + typedef Clasp::Atomic_t::type LowerType; + SumVec adjust_; // initial bound adjustments + SumVec up_[2]; // buffers for update via "double buffering" + LowerType* lower_; // (unadjusted) lower bound of constraint + MinimizeMode mode_; // how to compare assignments? + CounterType count_; // number of refs to this object + CounterType gCount_; // generation count - used when updating optimum + uint32 optGen_; // generation of optimal bound +public: + WeightVec weights; // sparse vectors of weights - only used for multi-level constraints + PrioVec prios; // (optional): maps levels to original priorities +CLASP_WARNING_BEGIN_RELAXED + WeightLiteral lits[0]; // (shared) literals - terminated with lit_true() +CLASP_WARNING_END_RELAXED +private: + ~SharedMinimizeData(); + void destroy() const; + SharedMinimizeData(const SharedMinimizeData&); + SharedMinimizeData& operator=(const SharedMinimizeData&); +}; +//! Helper class for creating minimize constraints. +/*! + * \ingroup constraint + */ +class MinimizeBuilder { +public: + typedef SharedMinimizeData SharedData; + MinimizeBuilder(); + + MinimizeBuilder& add(weight_t prio, const WeightLitVec& lits); + MinimizeBuilder& add(weight_t prio, WeightLiteral lit); + MinimizeBuilder& add(weight_t prio, weight_t adjust); + MinimizeBuilder& add(const SharedData& minCon); + + bool empty() const; + + //! Creates a new data object from previously added minimize literals. + /*! + * The function creates a new minimize data object from + * the previously added literals to minimize. The returned + * object can be used to attach one or more MinimizeConstraints. + * \param ctx A ctx object to be associated with the new minmize constraint. + * \return A data object representing previously added minimize statements or 0 if empty(). + * \pre ctx.ok() and !ctx.frozen() + * \post empty() + */ + SharedData* build(SharedContext& ctx); + + //! Discards any previously added minimize literals. + void clear(); +private: + struct MLit { + MLit(const WeightLiteral& wl, weight_t at) : lit(wl.first), prio(at), weight(wl.second) {} + Literal lit; + weight_t prio; + weight_t weight; + }; + struct CmpPrio { bool operator()(const MLit& lhs, const MLit& rhs) const; }; + struct CmpLit { bool operator()(const MLit& lhs, const MLit& rhs) const; }; + struct CmpWeight{ + CmpWeight(const SharedData::WeightVec* w) : weights(w) {} + bool operator()(const MLit& lhs, const MLit& rhs) const; + const SharedData::WeightVec* weights; + }; + typedef PodVector::type LitVec; + void prepareLevels(const Solver& s, SumVec& adjustOut, WeightVec& priosOut); + void mergeLevels(SumVec& adjust, SharedData::WeightVec& weightsOut); + SharedData* createShared(SharedContext& ctx, const SumVec& adjust, const CmpWeight& cmp); + LitVec lits_; +}; + +//! Base class for implementing (mulit-level) minimize statements. +/*! + * \ingroup constraint + * A solver contains at most one minimize constraint, but a minimize constraint + * may represent several minimize statements. In that case, each minimize statement + * has a unique level (starting at 0) and minimize statements with a lower level + * have higher priority. Priorities are handled like in smodels, i.e. statements + * with lower priority become relevant only if all statements with higher priority + * currently have an optimal assignment. + * + * MinimizeConstraint supports two modes of operation: if mode is set to + * optimize, solutions are considered optimal only if they are strictly smaller + * than previous solutions. Otherwise, if mode is set to enumerate a + * solution is valid if it is not greater than the initially set optimum. + * Example: + * m0: {a, b} + * m1: {c, d} + * All models: {a, c,...}, {a, d,...} {b, c,...}, {b, d,...} {a, b,...} + * Mode = optimize: {a, c, ...} (m0 = 1, m1 = 1} + * Mode = enumerate and initial opt=1,1: {a, c, ...}, {a, d,...}, {b, c,...}, {b, d,...} + * + */ +class MinimizeConstraint : public Constraint { +public: + typedef SharedMinimizeData SharedData; + typedef const SharedData* SharedDataP; + //! Returns a pointer to the shared representation of this constraint. + SharedDataP shared() const { return shared_; } + //! Attaches this object to the given solver. + virtual bool attach(Solver& s) = 0; + //! Shall activate the minimize constraint by integrating bounds stored in the shared data object. + virtual bool integrate(Solver& s) = 0; + //! Shall relax this constraint (i.e. remove any bounds). + /*! + * If reset is true, shall also remove search-path related state. + */ + virtual bool relax(Solver& s, bool reset) = 0; + //! Shall commit the model in s to the shared data object. + /*! + * The return value indicates whether the model is valid w.r.t the + * costs stored in the shared data object. + */ + virtual bool handleModel(Solver& s) = 0; + //! Shall handle the unsatisfiable path in s. + virtual bool handleUnsat(Solver& s, bool upShared, LitVec& restore) = 0; + virtual bool supportsSplitting() const { return true; } + // base interface + void destroy(Solver*, bool); + Constraint* cloneAttach(Solver&) { return 0; } +protected: + MinimizeConstraint(SharedData* s); + ~MinimizeConstraint(); + void reportLower(Solver& s, uint32 level, wsum_t low) const; + bool prepare(Solver& s, bool useTag); + SharedData* shared_; // common shared data + Literal tag_; // (optional) literal for tagging reasons +}; + +//! Minimization via branch and bound. +/*! + * \ingroup constraint + * The class supports both basic branch and bound as well as + * hierarchical branch and bound (with or without varying step sizes). + */ +class DefaultMinimize : public MinimizeConstraint { +public: + explicit DefaultMinimize(SharedData* d, uint32 strat); + // base interface + //! Attaches the constraint to the given solver. + /*! + * \pre s.decisionLevel() == 0 + * \note If either MinimizeMode_t::enumOpt or hierarchical optimization + * is active, s.sharedContext()->tagLiteral() shall be an unassigned literal. + */ + bool attach(Solver& s); + bool integrate(Solver& s) { return integrateBound(s); } + bool relax(Solver&, bool reset) { return relaxBound(reset); } + bool handleModel(Solver& s) { commitUpperBound(s); return true; } + bool handleUnsat(Solver& s, bool up, LitVec& out); + // constraint interface + PropResult propagate(Solver& s, Literal p, uint32& data); + void undoLevel(Solver& s); + void reason(Solver& s, Literal p, LitVec& lits); + bool minimize(Solver& s, Literal p, CCMinRecursive* r); + void destroy(Solver*, bool); + // own interface + bool active() const { return *opt() != SharedData::maxBound(); } + //! Number of minimize statements contained in this constraint. + uint32 numRules()const { return size_; } + //! Tries to integrate the next tentative bound into this constraint. + /*! + * Starting from the current optimum stored in the shared data object, + * the function tries to integrate the next candidate bound into + * this constraint. + * + * \return The function returns true if integration succeeded. Otherwise + * false is returned and s.hasConflict() is true. + * + * \note If integrateBound() failed, the bound of this constraint + * is relaxed. The caller has to resolve the conflict first + * and then integrateBound() shall be called again. + * + * \note The caller has to call s.propagate() to propagate any new information + * from the new bound. + * + * \note If the tag literal (if any) is not true, the minimize constraint first assumes it. + */ + bool integrateBound(Solver& s); + + //! Sets the current local sum as the global optimum (upper bound). + /*! + * commitUpperBound() shall be called whenever the solver finds a model. + * The current local sum is recorded as new optimum in the shared data object. + * Once the local bound is committed, the function integrateBound() has to be + * called in order to continue optimization. + */ + void commitUpperBound(const Solver& s); + //! Sets the current local upper bound as the lower bound of this constraint. + /*! + * commitLowerBound() shall be called on unsat. The function stores + * the local upper bound as new lower bound in this constraint. If upShared is true, + * the lower bound is also copied to the shared data object. + * + * Once the local bound is committed, the function integrateBound() has to be + * called in order to continue optimization. + * \return false if search-space is exceeded w.r.t this constraint. + */ + bool commitLowerBound(Solver& s, bool upShared); + + //! Removes the local upper bound of this constraint and therefore disables it. + /*! + * If full is true, also removes search-path related state. + */ + bool relaxBound(bool full = false); + + bool more() const { return step_.lev != size_; } + + // FOR TESTING ONLY! + wsum_t sum(uint32 i, bool adjust) const { return sum()[i] + (adjust ? shared_->adjust(i):0); } +private: + enum PropMode { propagate_new_sum, propagate_new_opt }; + union UndoInfo; + typedef const WeightLiteral* Iter; + ~DefaultMinimize(); + // bound operations + wsum_t* opt() const { return bounds_; } + wsum_t* sum() const { return bounds_ + size_; } + wsum_t* temp()const { return bounds_ + (size_*2); } + wsum_t* end() const { return bounds_ + (size_*3); } + void assign(wsum_t* lhs, wsum_t* rhs) const; + bool greater(wsum_t* lhs, wsum_t* rhs, uint32 len, uint32& aLev) const; + // propagation & undo + uint32 lastUndoLevel(const Solver& s) const; + bool litSeen(uint32 i) const; + bool propagateImpl(Solver& s, PropMode m); + uint32 computeImplicationSet(const Solver& s, const WeightLiteral& it, uint32& undoPos); + void pushUndo(Solver& s, uint32 litIdx); + bool updateBounds(bool applyStep); + // step + wsum_t& stepLow() const { return *(end() + step_.lev); } + void stepInit(uint32 n); + wsum_t* bounds_; // [upper,sum,temp[,lower]] + Iter pos_; // position of literal to look at next + UndoInfo* undo_; // one "seen" flag for each literal + + uint32 undoTop_; // undo stack holding assigned literals + uint32 posTop_; // stack of saved "look at" positions + const uint32 size_; // number of rules + uint32 actLev_; // first level to look at when comparing bounds + struct Step { // how to reduce next tentative bound + uint32 size; // size of step + uint32 lev : 30; // level on which step is applied + uint32 type: 2; // type of step (one of MinimizeMode_t::BBOption) + } step_; +}; + +//! Minimization via unsat cores. +/*! + * \ingroup constraint + */ +class UncoreMinimize : public MinimizeConstraint { +public: + // constraint interface + PropResult propagate(Solver& s, Literal p, uint32& data); + void reason(Solver& s, Literal p, LitVec& lits); + void destroy(Solver*, bool); + bool simplify(Solver& s, bool reinit = false); + // base interface + bool attach(Solver& s); + bool integrate(Solver& s); + bool relax(Solver&, bool reset); + bool valid(Solver& s); + bool handleModel(Solver& s); + bool handleUnsat(Solver& s, bool up, LitVec& out); + bool supportsSplitting() const { return false; } +private: + friend class SharedMinimizeData; + explicit UncoreMinimize(SharedData* d, uint32 options = 0u); + typedef DefaultMinimize* EnumPtr; + struct LitData { + LitData(weight_t w, bool as, uint32 c) : weight(w), coreId(c), assume((uint32)as) {} + weight_t weight; + uint32 coreId : 31; + uint32 assume : 1; + }; + struct LitPair { + LitPair(Literal p, uint32 dataId) : lit(p), id(dataId) {} + Literal lit; + uint32 id; + }; + struct Core { + Core(WeightConstraint* c, weight_t b, weight_t w) : con(c), bound(b), weight(w) {} + uint32 size() const; + Literal at(uint32 i) const; + Literal tag() const; + WeightConstraint* con; + weight_t bound; + weight_t weight; + }; + struct WCTemp { + typedef WeightLitVec WLitVec; + void start(weight_t b){ lits.clear(); bound = b; } + void add(Solver& s, Literal p); + bool unsat() const { return bound > 0 && static_cast(bound) > static_cast(lits.size()); } + weight_t bound; + WLitVec lits; + }; + typedef PodVector::type LitTable; + typedef PodVector::type CoreTable; + typedef PodVector::type ConTable; + typedef PodVector::type LitSet; + // literal and core management + bool hasCore(const LitData& x) const { return x.coreId != 0; } + LitData& getData(uint32 id) { return litData_[id-1];} + Core& getCore(const LitData& x) { return open_[x.coreId-1]; } + LitData& addLit(Literal p, weight_t w); + void releaseLits(); + bool addCore(Solver& s, const LitPair* lits, uint32 size, weight_t w); + uint32 allocCore(WeightConstraint* con, weight_t bound, weight_t weight, bool open); + bool closeCore(Solver& s, LitData& x, bool sat); + bool addOll(Solver& s, const LitPair* lits, uint32 size, weight_t w); + bool addOllCon(Solver& s, const WCTemp& wc, weight_t w); + enum CompType { comp_disj = 0, comp_conj = 1 }; + bool addPmr(Solver& s, const LitPair* lits, uint32 size, weight_t w); + bool addPmrCon(CompType t, Solver& s, Literal head, Literal body1, Literal body2); + // algorithm + void init(); + uint32 initRoot(Solver& s); + bool initLevel(Solver& s); + uint32 analyze(Solver& s, weight_t& minW, LitVec& poppedOther); + bool pushPath(Solver& s); + void integrateOpt(Solver& s); + bool popPath(Solver& s, uint32 dl, LitVec& out); + bool fixLit(Solver& s, Literal p); + bool fixLevel(Solver& s); + void detach(Solver* s, bool b); + wsum_t* computeSum(Solver& s) const; + void setLower(wsum_t x); + bool validLowerBound() const { + wsum_t cmp = lower_ - upper_; + return cmp < 0 || (cmp == 0 && level_ == shared_->maxLevel() && !shared_->checkNext()); + } + // data + EnumPtr enum_; // for supporting (optimal) model enumeration in parallel mode + wsum_t* sum_; // costs of active model + LitTable litData_; // data for active literals (tag lits for cores + lits from active minimize) + CoreTable open_; // open cores, i.e. relaxable and referenced by an assumption + ConTable closed_; // closed cores represented as weight constraints + LitSet assume_; // current set of assumptions + LitSet todo_; // core(s) not yet represented as constraint + LitVec fix_; // set of fixed literals + LitVec conflict_; // temporary: conficting set of assumptions + WCTemp temp_; // temporary: used for creating weight constraints + wsum_t lower_; // lower bound of active level + wsum_t upper_; // upper bound of active level + uint32 auxInit_; // number of solver aux vars on attach + uint32 auxAdd_; // number of aux vars added for cores + uint32 gen_; // active generation + uint32 level_ : 26;// active level + uint32 valid_ : 1;// valid w.r.t active generation? + uint32 sat_ : 1;// update because of model + uint32 pre_ : 1;// preprocessing active? + uint32 path_ : 1;// push path? + uint32 next_ : 1;// assume next level? + uint32 init_ : 1;// init constraint? + weight_t actW_; // active weight limit (only weighted minimization with preprocessing) + weight_t nextW_; // next weight limit (only weighted minimization with preprocessing) + uint32 eRoot_; // saved root level of solver (initial gp) + uint32 aTop_; // saved assumption level (added by us) + uint32 freeOpen_; // head of open core free list + uint32 options_; // active options +}; + +} // end namespace Clasp + +#endif diff --git a/libclasp/clasp/model_enumerators.h b/libclasp/clasp/model_enumerators.h new file mode 100644 index 0000000..17be901 --- /dev/null +++ b/libclasp/clasp/model_enumerators.h @@ -0,0 +1,117 @@ +// +// Copyright (c) 2006-2011, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +//! \file +//! \brief Model enumeration with minimization and projection. +#ifndef CLASP_MODEL_ENUMERATORS_H +#define CLASP_MODEL_ENUMERATORS_H + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include + +namespace Clasp { + +//! Class for model enumeration with minimization and projection. +/*! + * This class implements algorithms for enumerating models with or without optimization + * and/or projection. It supports two different algorithms (strategies). First, enumeration + * via restricted backjumping, and second, enumeration via recording of solution nogoods. + * + * The first strategy, strategy_backtrack, maintains a special backtracking level to + * suppress certain backjumps that could otherwise "re-open" search spaces already visited. + * If projection is not active, no extra nogoods are created. + * Otherwise, the number of additional solution nogoods is linear in the number of projection atoms. + * + * The second strategy, strategy_record, enumerates models by recording nogoods for found solutions. + * In general, this strategy is exponential in space (bounded by the number of solutions). + * On the other hand, if optimization is active, additional nogoods are not needed + * because the optimization constraint already serves as solution nogood. + * + * There is also a third strategy, strategy_auto, provided for convenience. This + * strategy automatically selects between strategy_backtrack and strategy_record + * based on the problem at hand. It uses strategy_record, if one of the following holds: + * - optimization is active, or + * - only one model is requested, or + * - both parallel search as well as projection are active + * . + * In all other cases, strategy_auto selects strategy_backtrack. + * + * \ingroup enumerator + */ +class ModelEnumerator : public Enumerator { +public: + //! Enumeration algorithms. + enum Strategy { + strategy_auto = 0, //!< Use strategy best suited to problem. + strategy_backtrack = 1, //!< Use backtrack-based enumeration. + strategy_record = 2 //!< Use nogood-based enumeration. + }; + //! Projective solution enumeration and options. + enum ProjectOptions { + project_enable_simple = 1, //!< Enable projective solution enumeration. + project_use_heuristic = 2, //!< Use heuristic when selecting a literal from a projection nogood. + project_save_progress = 4, //!< Enable progress saving after the first solution was found. + project_enable_full = 6, //!< Enable projective solution enumeration with heuristic and progress saving. + project_dom_lits = 8, //!< In strategy record, project only on true domain literals. + }; + /*! + * \param st Enumeration strategy to apply. + */ + explicit ModelEnumerator(Strategy st = strategy_auto); + ~ModelEnumerator(); + + //! Configure strategy. + /*! + * \param st Enumeration strategy to use. + * \param projection The set of ProjectOptions to be applied or 0 to disable projective enumeration. + * \param filter Ignore output predicates starting with filter in projective enumeration. + */ + void setStrategy(Strategy st = strategy_auto, uint32 projection = 0, char filter = '_'); + bool projectionEnabled()const { return projectOpts() != 0; } + Strategy strategy() const { return static_cast(options_ & 3u); } + bool project(Var v) const; +protected: + bool supportsRestarts() const { return optimize() || strategy() == strategy_record; } + bool supportsParallel() const { return !projectionEnabled() || strategy() != strategy_backtrack; } + bool supportsSplitting(const SharedContext& problem) const { + return (strategy() == strategy_backtrack || (projectOpts() & project_dom_lits) == 0u) && Enumerator::supportsSplitting(problem); + } + ConPtr doInit(SharedContext& ctx, SharedMinimizeData* m, int numModels); +private: + enum { detect_strategy_flag = 4u, trivial_flag = 8u, strategy_opts_mask = 15u }; + class ModelFinder; + class BacktrackFinder; + class RecordFinder; + typedef PodVector::type WordVec; + void initProjection(SharedContext& ctx); + void addProject(SharedContext& ctx, Var v); + uint32 projectOpts() const { return (options_ >> 4) & strategy_opts_mask; } + bool detectStrategy() const { return (options_ & detect_strategy_flag) == detect_strategy_flag; } + bool trivial() const { return (options_ & trivial_flag) == trivial_flag; } + LitVec domRec_; + uint32 options_; + WordVec project_; +}; + +} +#endif diff --git a/libclasp/clasp/parallel_solve.h b/libclasp/clasp/parallel_solve.h new file mode 100644 index 0000000..74a9e3c --- /dev/null +++ b/libclasp/clasp/parallel_solve.h @@ -0,0 +1,368 @@ +// +// Copyright (c) 2010-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_PARALLEL_SOLVE_H_INCLUDED +#define CLASP_PARALLEL_SOLVE_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#if WITH_THREADS + +#include +#include +#include +#include +#include +#include + +/*! + * \file + * \brief Defines classes controlling multi-threaded parallel solving. + */ +namespace Clasp { +//! Namespace for types and functions needed for implementing multi-threaded parallel solving. +namespace mt { + +/** + * \defgroup mt Multi-threading + * \brief Parallel solving and related classes. + * \ingroup enumerator + */ +//@{ + +class ParallelHandler; +class ParallelSolve; + +//! Options for controlling parallel solving. +struct ParallelSolveOptions : BasicSolveOptions { + //! Nogood distribution options. + struct Distribution : Distributor::Policy { + enum Mode { mode_global = 0, mode_local = 1 }; + Distribution(Mode m = mode_global) : Distributor::Policy(), mode(m) {} + Distributor::Policy& policy() { return *this; } + uint32 mode; + }; + ParallelSolveOptions() {} + //! Algorithm options. + struct Algorithm { + //! Possible search strategies. + enum SearchMode { mode_split = 0, mode_compete = 1 }; + Algorithm() : threads(1), mode(mode_compete) {} + uint32 threads; + SearchMode mode; + }; + //! Nogood integration options. + struct Integration { + static const uint32 GRACE_MAX = (1u<<28)-1; + Integration() : grace(1024), filter(filter_gp), topo(topo_all) {} + enum Filter { filter_no = 0, filter_gp = 1, filter_sat = 2, filter_heuristic = 3 }; + enum Topology { topo_all = 0, topo_ring = 1, topo_cube = 2, topo_cubex = 3 }; + uint32 grace : 28; /**< Lower bound on number of shared nogoods to keep. */ + uint32 filter: 2; /**< Filter for integrating shared nogoods (one of Filter). */ + uint32 topo : 2; /**< Integration topology */ + }; + //! Global restart options. + struct GRestarts { + GRestarts():maxR(0) {} + uint32 maxR; + ScheduleStrategy sched; + }; + Integration integrate; //!< Nogood integration options to apply during search. + Distribution distribute;//!< Nogood distribution options to apply during search. + GRestarts restarts; //!< Global restart strategy to apply during search. + Algorithm algorithm; //!< Parallel algorithm to use. + //! Allocates a new solve object. + SolveAlgorithm* createSolveObject() const; + //! Returns the number of threads that can run concurrently on the current hardware. + static uint32 recommendedSolvers() { return Clasp::mt::thread::hardware_concurrency(); } + //! Returns number of maximal number of supported threads. + static uint32 supportedSolvers() { return 64; } + //! Returns the peers of the solver with the given id assuming the given topology. + static uint64 initPeerMask(uint32 sId, Integration::Topology topo, uint32 numThreads); + uint32 numSolver() const { return algorithm.threads; } + void setSolvers(uint32 i) { algorithm.threads = std::max(uint32(1), i); } + bool defaultPortfolio() const { return algorithm.mode == Algorithm::mode_compete; } +}; + +//! A parallel algorithm for multi-threaded solving with and without search-space splitting. +/*! + * The class adapts clasp's basic solve algorithm + * to a parallel solve algorithm that solves + * a problem using a given number of threads. + * It supports guiding path based solving, portfolio based solving, as well + * as a combination of these two approaches. + */ +class ParallelSolve : public SolveAlgorithm { +public: + explicit ParallelSolve(const ParallelSolveOptions& opts); + ~ParallelSolve(); + // base interface + virtual bool interrupted() const; + virtual void resetSolve(); + virtual void enableInterrupts(); + // own interface + //! Returns the number of active threads. + uint32 numThreads() const; + bool integrateUseHeuristic() const { return test_bit(intFlags_, 31); } + uint32 integrateGrace() const { return intGrace_; } + uint32 integrateFlags() const { return intFlags_; } + uint64 hasErrors() const; + //! Requests a global restart. + void requestRestart(); + bool handleMessages(Solver& s); + bool integrateModels(Solver& s, uint32& mCount); + void pushWork(LitVec* gp); + bool commitModel(Solver& s); + bool commitUnsat(Solver& s); + enum GpType { gp_none = 0, gp_split = 1, gp_fixed = 2 }; +private: + ParallelSolve(const ParallelSolve&); + ParallelSolve& operator=(const ParallelSolve&); + typedef SingleOwnerPtr PathPtr; + enum ErrorCode { error_none = 0, error_oom = 1, error_runtime = 2, error_other = 4 }; + enum { masterId = 0 }; + // ------------------------------------------------------------------------------------------- + // Thread setup + struct EntryPoint; + void destroyThread(uint32 id); + void allocThread(uint32 id, Solver& s, const SolveParams& p); + void joinThreads(); + // ------------------------------------------------------------------------------------------- + // Algorithm steps + void setIntegrate(uint32 grace, uint8 filter); + void setRestarts(uint32 maxR, const ScheduleStrategy& rs); + bool beginSolve(SharedContext& ctx, const LitVec& assume); + bool doSolve(SharedContext& ctx, const LitVec& assume); + void doStart(SharedContext& ctx, const LitVec& assume); + int doNext(int last); + void doStop(); + bool doInterrupt(); + void solveParallel(uint32 id); + void initQueue(); + bool requestWork(Solver& s, PathPtr& out); + void terminate(Solver& s, bool complete); + bool waitOnSync(Solver& s); + void exception(uint32 id, PathPtr& path, ErrorCode e, const char* what); + void reportProgress(const Event& ev) const; + void reportProgress(const Solver& s, const char* msg) const; + // ------------------------------------------------------------------------------------------- + typedef ParallelSolveOptions::Distribution Distribution; + struct SharedData; + // SHARED DATA + SharedData* shared_; // Shared control data + ParallelHandler** thread_; // Thread-locl control data + // READ ONLY + Distribution distribution_; // distribution options + uint32 maxRestarts_; // disable global restarts once reached + uint32 intGrace_ : 30;// grace period for clauses to integrate + uint32 intTopo_ : 2;// integration topology + uint32 intFlags_; // bitset controlling clause integration + bool modeSplit_; +}; +//! An event type for debugging messages sent between threads. +struct MessageEvent : SolveEvent { + enum Action { sent, received, completed }; + MessageEvent(const Solver& s, const char* message, Action a, double t = 0.0) + : SolveEvent(s, verbosity_high), msg(message), time(t) { op = (uint32)a; } + const char* msg; // name of message + double time; // only for action completed +}; +//! A per-solver (i.e. thread) class that implements message handling and knowledge integration. +/*! + * The class adds itself as a post propagator to the given solver. During propagation + * it checks for new messages and lemmas to integrate. + */ +class ParallelHandler : public MessageHandler { +public: + typedef ParallelSolve::GpType GpType; + + //! Creates a new parallel handler to be used in the given solve group. + /*! + * \param ctrl The object controlling the parallel solve operation. + * \param s The solver that is to be controlled by this object. + * \param p The solver-specific solve options. + */ + explicit ParallelHandler(ParallelSolve& ctrl, Solver& s, const SolveParams& p); + ~ParallelHandler(); + //! Attaches the object's solver to ctx and adds this object as a post propagator. + bool attach(SharedContext& ctx); + //! Removes this object from the list of post propagators of its solver and detaches the solver from ctx. + void detach(SharedContext& ctx, bool fastExit); + + void setError(int e) { error_ = e; } + int error() const { return (int)error_; } + void setWinner() { win_ = 1; } + bool winner() const { return win_ != 0; } + void setThread(Clasp::mt::thread& x) { assert(!joinable()); x.swap(thread_); assert(joinable()); } + + //! True if *this has an associated thread of execution, false otherwise. + bool joinable() const { return thread_.joinable(); } + //! Waits for the thread of execution associated with *this to finish. + int join() { if (joinable()) { thread_.join(); } return error(); } + + // overridden methods + + //! Integrates new information. + bool propagateFixpoint(Solver& s, PostPropagator*); + bool handleMessages() { return ctrl_->handleMessages(solver()); } + void reset() { up_ = 1; } + bool simplify(Solver& s, bool re); + //! Checks whether new information has invalidated current model. + bool isModel(Solver& s); + + // own interface + + // TODO: make functions virtual once necessary + + //! Returns true if handler's guiding path is disjoint from all others. + bool disjointPath() const { return gp_.type == ParallelSolve::gp_split; } + //! Returns true if handler has a guiding path. + bool hasPath() const { return gp_.type != ParallelSolve::gp_none; } + void setGpType(GpType t) { gp_.type = t; } + + //! Entry point for solving the given guiding path. + /*! + * \param solve The object used for solving. + * \param type The guiding path's type. + * \param restart Request restart after restart number of conflicts. + */ + ValueRep solveGP(BasicSolve& solve, GpType type, uint64 restart); + + /*! + * \name Message handlers + * \note + * Message handlers are intended as callbacks for ParallelSolve::handleMessages(). + * They shall not change the assignment of the solver object. + */ + //@{ + + //! Algorithm is about to terminate. + /*! + * Removes this object from the solver's list of post propagators. + */ + void handleTerminateMessage(); + + //! Request for split. + /*! + * Splits off a new guiding path and adds it to the control object. + * \pre The guiding path of this object is "splittable" + */ + void handleSplitMessage(); + + //! Request for (global) restart. + /*! + * \return true if restart is valid, else false. + */ + bool handleRestartMessage(); + + Solver& solver() { return *solver_; } + const SolveParams& params() const{ return *params_; } + //@} +private: + void add(ClauseHead* h); + void clearDB(Solver* s); + bool integrate(Solver& s); + typedef PodVector::type ClauseDB; + typedef SharedLiterals** RecBuffer; + enum { RECEIVE_BUFFER_SIZE = 32 }; + ParallelSolve* ctrl_; // my message source + Solver* solver_; // my solver + const SolveParams* params_; // my solving params + Clasp::mt::thread thread_; // active thread or empty for master + RecBuffer received_; // received clauses not yet integrated + ClauseDB integrated_; // my integrated clauses + uint32 recEnd_; // where to put next received clause + uint32 intEnd_; // where to put next clause + uint32 error_:30; // error code or 0 if ok + uint32 win_ : 1; // 1 if thread was the first to terminate the search + uint32 up_ : 1; // 1 if next propagate should check for new lemmas/models + uint32 act_ : 1; // 1 if gp is active + struct GP { + uint64 restart; // don't give up before restart number of conflicts + uint32 modCount; // integration counter for synchronizing models + GpType type ; // type of gp + void reset(uint64 r = UINT64_MAX, GpType t = ParallelSolve::gp_none) { + restart = r; + modCount= 0; + type = t; + } + } gp_; +}; +//! A class that uses a global list to exchange nogoods between threads. +class GlobalDistribution : public Distributor { +public: + explicit GlobalDistribution(const Policy& p, uint32 maxShare, uint32 topo); + ~GlobalDistribution(); + uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut); + void publish(const Solver& source, SharedLiterals* n); +private: + void release(); + struct ClausePair { + ClausePair(uint32 sId = UINT32_MAX, SharedLiterals* x = 0) : sender(sId), lits(x) {} + uint32 sender; + SharedLiterals* lits; + }; + class Queue : public MultiQueue { + public: + typedef MultiQueue base_type; + using base_type::publish; + Queue(uint32 m) : base_type(m) {} + }; + struct ThreadInfo { + uint64 peerMask; + union { + Queue::ThreadId id; + uint64 rep; + }; + char pad[64 - (sizeof(uint64)*2)]; + }; + Queue::ThreadId& getThreadId(uint32 sId) const { return threadId_[sId].id; } + uint64 getPeerMask(uint32 sId) const { return threadId_[sId].peerMask; } + Queue* queue_; + ThreadInfo* threadId_; +}; +//! A class that uses thread-local lists to exchange nogoods between threads. +class LocalDistribution : public Distributor { +public: + explicit LocalDistribution(const Policy& p, uint32 maxShare, uint32 topo); + ~LocalDistribution(); + uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut); + void publish(const Solver& source, SharedLiterals* n); +private: + typedef Detail::RawStack RawStack; + typedef MPSCPtrQueue::Node QNode; + enum { BLOCK_CAP = 128 }; + QNode* allocNode(uint32 tId, SharedLiterals* clause); + void freeNode(uint32 tId, QNode* n) const; + struct ThreadData { + MPSCPtrQueue received; // queue holding received clauses + uint64 peers; // set of peers from which this thread receives clauses + QNode sentinal; // sentinal node for simplifying queue impl + QNode* free; // local free list - only accessed by this thread + }** thread_; // one entry for each thread + RawStack blocks_; // allocated node blocks + uint32 numThread_; // number of threads, i.e. size of array thread_ +}; +//@} +} } +#endif + +#endif diff --git a/libclasp/clasp/parser.h b/libclasp/clasp/parser.h new file mode 100644 index 0000000..422c00e --- /dev/null +++ b/libclasp/clasp/parser.h @@ -0,0 +1,187 @@ +// +// Copyright (c) Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_PARSER_H_INCLUDED +#define CLASP_PARSER_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +/*! + * \file + * \brief Defines parsers for supported input formats. + */ +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// PARSING BASE +///////////////////////////////////////////////////////////////////////////////////////// +/*! + * \addtogroup problem + */ +//@{ + +//! Auto-detect type of program given in prg. +ProblemType detectProblemType(std::istream& prg); + +//! Parse additional information in symbol table/comments. +struct ParserOptions { + //! Supported parser extensions. + enum Extension { + parse_heuristic = 1u, //!< Parse heuristic info in smodels, dimacs, and pb format. + parse_acyc_edge = 2u, //!< Parse acyc info in smodels, dimacs, and pb format. + parse_minimize = 4u, //!< Parse cost function in dimacs format. + parse_project = 8u, //!< Parse project directive in dimacs and pb format. + parse_assume = 16u,//!< Parse assumption directive in dimacs and pb format. + parse_output = 32u,//!< Parse output directive in dimacs and pb format. + parse_full = 63u + }; + ParserOptions() : ext(0) {} + ParserOptions& enableHeuristic() { ext |= parse_heuristic; return *this; } + ParserOptions& enableAcycEdges() { ext |= parse_acyc_edge; return *this; } + ParserOptions& enableMinimize() { ext |= parse_minimize; return *this; } + ParserOptions& enableProject() { ext |= parse_project; return *this; } + ParserOptions& enableAssume() { ext |= parse_assume; return *this;} + ParserOptions& enableOutput() { ext |= parse_output; return *this; } + bool isEnabled(Extension e) const { return (ext & static_cast(e)) != 0u; } + bool isEnabled(uint8 f) const { return (ext & f) != 0u; } + uint8 ext; +}; +//! Base class for parsers. +class ProgramParser { +public: + typedef Potassco::ProgramReader StrategyType; + static const Var VAR_MAX = varMax - 1; + ProgramParser(); + virtual ~ProgramParser(); + bool accept(std::istream& str, const ParserOptions& o = ParserOptions()); + bool incremental() const; + bool isOpen() const; + bool parse(); + bool more(); + void reset(); +private: + virtual StrategyType* doAccept(std::istream& str, const ParserOptions& o) = 0; + StrategyType* strat_; +}; + +//! Parser for logic programs in smodels-internal or aspif format. +class AspParser : public ProgramParser { +public: + static bool accept(char c); + explicit AspParser(Asp::LogicProgram& prg); + ~AspParser(); + enum Format { format_smodels = -1, format_aspif = 1 }; + static void write(Asp::LogicProgram& prg, std::ostream& os); + static void write(Asp::LogicProgram& prg, std::ostream& os, Format f); +protected: + virtual StrategyType* doAccept(std::istream& str, const ParserOptions& o); +private: + struct SmAdapter; + Asp::LogicProgram* lp_; + StrategyType* in_; + Potassco::AbstractProgram* out_; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// SAT parsing +///////////////////////////////////////////////////////////////////////////////////////// +//! Base class for dimacs and opb parser. +class SatReader : public Potassco::ProgramReader { +public: + SatReader(); + ParserOptions options; +protected: + bool skipLines(char start); + void parseExt(const char* pre, uint32 maxVar, SharedContext& ctx); + // ::= { } + void parseProject(uint32 maxVar, SharedContext& ctx); + // ::= { } + void parseAssume(uint32 maxVar); + // ::= + void parseHeuristic(uint32 maxVar, SharedContext& ctx); + // ::= "range" + // | + void parseOutput(uint32 maxVar, SharedContext& ctx); + void parseGraph(uint32 maxVar, const char* pre, ExtDepGraph& graph); + virtual void addObjective(const WeightLitVec& vec) = 0; + virtual void addAssumption(Literal x) = 0; +private: + Literal matchLit(Var max); +}; +//! Parser for (extended) dimacs format. +class DimacsReader : public SatReader { +public: + static bool accept(char c) { return c == 'c' || c == 'p'; } + DimacsReader(SatBuilder&); +protected: + virtual bool doAttach(bool& inc); + virtual bool doParse(); + virtual void addObjective(const WeightLitVec& vec); + virtual void addAssumption(Literal x); +private: + SatBuilder* program_; + Var numVar_; + bool wcnf_; +}; +//! Parser for opb format. +class OpbReader : public SatReader { +public: + OpbReader(PBBuilder&); + static bool accept(char c) { return c == '*'; } +protected: + virtual bool doAttach(bool& inc); + virtual bool doParse(); + virtual void addObjective(const WeightLitVec& vec); + virtual void addAssumption(Literal x); + void parseOptObjective(); + void parseConstraint(); + void parseSum(); + void parseTerm(); +private: + PBBuilder* program_; + weight_t minCost_; + weight_t maxCost_; + struct Temp { + WeightLitVec lits; + LitVec term; + weight_t bound; + bool eq; + } active_; +}; +//! Parser for SAT or PB problems. +class SatParser : public ProgramParser { +public: + explicit SatParser(SatBuilder& prg); + explicit SatParser(PBBuilder& prg); + ~SatParser(); +protected: + virtual StrategyType* doAccept(std::istream& str, const ParserOptions& o); +private: + SatReader* reader_; +}; +//@} + +} +#endif diff --git a/libclasp/clasp/pod_vector.h b/libclasp/clasp/pod_vector.h new file mode 100644 index 0000000..e95b589 --- /dev/null +++ b/libclasp/clasp/pod_vector.h @@ -0,0 +1,103 @@ +// +// Copyright (c) 2006-2007, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_POD_VECTOR_H_INCLUDED +#define CLASP_POD_VECTOR_H_INCLUDED +#include +#include +#include +#include + +namespace Clasp { + +#if defined(_DEBUG) && _DEBUG + template + struct PodVector { + typedef std::vector type; + static void destruct(type& t) {t.clear();} + }; +#else + //! Type selector for a vector type optimized for storing POD-types. + template + struct PodVector { + typedef bk_lib::pod_vector type; + static void destruct(type& t) { + for (typename type::size_type i = 0, end = t.size(); i != end; ++i) { + t[i].~Type(); + } + t.clear(); + } + }; +#endif +inline uint32 toU32(std::size_t x) { + assert(sizeof(std::size_t) <= sizeof(uint32) || x <= static_cast(UINT32_MAX)); + return static_cast(x); +} +template +inline uint32 sizeVec(const T& c) { return toU32(c.size()); } +template +inline void releaseVec(T& t) { + T().swap(t); +} + +template +inline void shrinkVecTo(T& t, typename T::size_type j) { + t.erase(t.begin()+j, t.end()); +} + +template +inline void growVecTo(T& vec, typename T::size_type j, const typename T::value_type& val = typename T::value_type()) { + if (vec.size() < j) { + if (vec.capacity() < j) { vec.reserve(j + j / 2); } + vec.resize(j, val); + } +} + +template +void moveDown(T& t, typename T::size_type from, typename T::size_type to) { + for (typename T::size_type end = t.size(); from != end;) { + t[to++] = t[from++]; + } + shrinkVecTo(t, to); +} +//! A simple vector-based fifo queue for storing POD-types. +template +struct PodQueue { + typedef typename PodVector::type vec_type; + typedef typename vec_type::size_type size_type; + PodQueue() : qFront(0) {} + bool empty() const { return qFront == vec.size(); } + size_type size() const { return vec.size() - qFront; } + const T& front() const { return vec[qFront]; } + const T& back() const { return vec.back(); } + T& front() { return vec[qFront]; } + T& back() { return vec.back(); } + void push(const T& x){ vec.push_back(x); } + void pop() { ++qFront; } + T pop_ret() { return vec[qFront++]; } + void clear() { vec.clear(); qFront = 0; } + void rewind() { qFront = 0; } + vec_type vec; // the underlying vector holding the items + size_type qFront; // front position +}; + +} + +#endif diff --git a/libclasp/clasp/program_builder.h b/libclasp/clasp/program_builder.h new file mode 100644 index 0000000..2c7a7d1 --- /dev/null +++ b/libclasp/clasp/program_builder.h @@ -0,0 +1,248 @@ +// +// Copyright (c) 2006-2015 Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_PROGRAM_BUILDER_H_INCLUDED +#define CLASP_PROGRAM_BUILDER_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + +namespace Clasp { + +/** + * \file + * \defgroup problem Input + * \brief Classes and functions for defining input programs. + */ +//@{ + +//! Interface for defining an input program. +class ProgramBuilder { +public: + typedef SharedMinimizeData SharedMinimize; + typedef SingleOwnerPtr MinPtr; + + ProgramBuilder(); + virtual ~ProgramBuilder(); + //! Starts the definition of a program. + /*! + * This function shall be called exactly once before a new program is defined. + * It discards any previously added program. + * + * \param ctx The context object in which the program should be stored. + */ + bool startProgram(SharedContext& ctx); + //! Parses the given stream as a program of type() and adds it to this object. + bool parseProgram(std::istream& prg); + //! Unfreezes a currently frozen program. + bool updateProgram(); + //! Loads the program into the shared context passed to startProgram(). + bool endProgram(); + //! Returns any assumptions that shall hold during solving. + /*! + * \pre frozen() + */ + void getAssumptions(LitVec& out) const; + //! Returns bounds that shall hold during minimization. + void getWeakBounds(SumVec& out) const; + //! Returns the type of program that is created by this builder. + int type() const { return doType(); } + //! Returns true if the program is currently frozen. + bool frozen() const { return frozen_; } + //! Returns true if the program is not conflicting. + virtual bool ok() const; + //! Returns the stored context object. + SharedContext* ctx() const { return ctx_; } + //! Returns a parser for this type of program associated with this object. + ProgramParser& parser(); +protected: + void addMinLit(weight_t prio, WeightLiteral x); + void setFrozen(bool frozen) { frozen_ = frozen; } + void setCtx(SharedContext* x){ ctx_ = x; } + void markOutputVariables() const; +private: + typedef SingleOwnerPtr MinBuildPtr; + typedef SingleOwnerPtr ParserPtr; + ProgramBuilder(const ProgramBuilder&); + ProgramBuilder& operator=(ProgramBuilder&); + virtual bool doStartProgram() = 0; + virtual bool doUpdateProgram() = 0; + virtual bool doEndProgram() = 0; + virtual void doGetWeakBounds(SumVec& out) const; + virtual void doGetAssumptions(LitVec& out) const = 0; + virtual int doType() const = 0; + virtual ProgramParser* doCreateParser() = 0; + SharedContext* ctx_; + ParserPtr parser_; + bool frozen_; +}; + +//! A class for defining a SAT-problem in CNF. +class SatBuilder : public ProgramBuilder { +public: + explicit SatBuilder(bool maxSat = false); + // program definition + + //! Creates necessary variables and prepares the problem. + /*! + * \param numVars Number of variables to create. + * \param hardClauseWeight Weight identifying hard clauses (0 means no weight). + * Clauses added with a weight != hardClauseWeight are + * considered soft clauses (see addClause()). + * \param clauseHint A hint on how many clauses will be added. + */ + void prepareProblem(uint32 numVars, wsum_t hardClauseWeight = 0, uint32 clauseHint = 100); + //! Returns the number of variables in the problem. + Var numVars() const { return vars_; } + //! Adds the given clause to the problem. + /*! + * The SatBuilder supports the creation of (weighted) MaxSAT problems + * via the creation of "soft clauses". For this, clauses + * added to this object have an associated weight cw. If cw + * does not equal hardClauseWeight (typically 0), the clause is a + * soft clause and not satisfying it results in a penalty of cw. + * + * \pre v <= numVars(), for all variables v occuring in clause. + * \pre cw >= 0. + * \param clause The clause to add. + * \param cw The weight associated with the clause. + */ + bool addClause(LitVec& clause, wsum_t cw = 0); + //! Adds min as an objective function to the problem. + bool addObjective(const WeightLitVec& min); + //! Adds v to the set of projection vars. + void addProject(Var v); + //! Adds x to the set of initial assumptions. + void addAssumption(Literal x); +private: + typedef PodVector::type VarState; + bool doStartProgram(); + ProgramParser* doCreateParser(); + int doType() const { return Problem_t::Sat; } + bool doUpdateProgram() { return !frozen(); } + void doGetAssumptions(LitVec& a) const { a.insert(a.end(), assume_.begin(), assume_.end()); } + bool doEndProgram(); + bool satisfied(LitVec& clause); + bool markAssigned(); + void markLit(Literal x) { varState_[x.var()] |= 1 + x.sign(); } + VarState varState_; + LitVec softClauses_; + LitVec assume_; + wsum_t hardWeight_; + Var vars_; + uint32 pos_; + bool maxSat_; +}; + +//! A class for defining a PB-problem. +class PBBuilder : public ProgramBuilder { +public: + PBBuilder(); + // program definition + //! Creates necessary variables and prepares the problem. + /*! + * \param numVars Number of problem variables to create. + * \param maxProduct Max number of products in the problem. + * \param maxSoft Max number of soft constraints in the problem. + * \param constraintHint A hint on how many clauses will be added. + */ + void prepareProblem(uint32 numVars, uint32 maxProduct, uint32 maxSoft, uint32 constraintHint = 100); + //! Returns the number of variables in the problem. + uint32 numVars() const { return auxVar_ - 1; } + //! Adds the given PB-constraint to the problem. + /*! + * A PB-constraint consists of a list of weighted Boolean literals (lhs), + * a comparison operator (either >= or =), and an integer bound (rhs). + * + * \pre v <= numVars(), for all variables v occuring in lits. + * \pre bound >= 0 && cw >= 0. + * + * \param lits The lhs of the PB-constraint. + * \param bound The rhs of the PB-constraint. + * \param eq If true, use '=' instead of '>=' as comparison operator. + * \param cw If > 0, treat constraint as soft constraint with weight cw. + */ + bool addConstraint(WeightLitVec& lits, weight_t bound, bool eq = false, weight_t cw = 0); + //! Adds the given product to the problem. + /*! + * The function creates the equality x == l1 && ... && ln, where x is a new + * literal and each li is a literal in lits. + * \pre The number of products added so far is < maxProduct that was given in prepareProblem(). + */ + Literal addProduct(LitVec& lits); + //! Adds min as an objective function to the problem. + bool addObjective(const WeightLitVec& min); + //! Adds v to the set of projection vars. + void addProject(Var v); + //! Adds x to the set of initial assumptions. + void addAssumption(Literal x); + //! Only allow solutions where the sum of violated soft constraint is less than bound. + bool setSoftBound(wsum_t bound); +private: + struct PKey { + LitVec lits; + std::size_t operator()(const PKey& k) const { return k.lits[0].rep(); } + bool operator()(const PKey& lhs, const PKey& rhs) const { return lhs.lits == rhs.lits; } + }; + typedef Clasp::HashMap_t::map_type ProductIndex; + bool doStartProgram(); + void doGetWeakBounds(SumVec& out) const; + int doType() const { return Problem_t::Pb; } + bool doUpdateProgram() { return !frozen(); } + void doGetAssumptions(LitVec& a) const { a.insert(a.end(), assume_.begin(), assume_.end()); } + ProgramParser* doCreateParser(); + bool doEndProgram(); + bool productSubsumed(LitVec& lits, PKey& prod); + void addProductConstraints(Literal eqLit, LitVec& lits); + Var getAuxVar(); + ProductIndex products_; + PKey prod_; + LitVec assume_; + uint32 auxVar_; + uint32 endVar_; + wsum_t soft_; +}; + +//! Adapts a Sat or PB builder to the Potassco::AbstractProgram interface. +class BasicProgramAdapter : public Potassco::AbstractProgram { +public: + BasicProgramAdapter(ProgramBuilder& prg); + void initProgram(bool inc); + void beginStep(); + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body); + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body); + void minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits); +protected: + ProgramBuilder* prg_; + LitVec clause_; + WeightLitVec constraint_; + bool inc_; +}; + +} +#endif diff --git a/libclasp/clasp/satelite.h b/libclasp/clasp/satelite.h new file mode 100644 index 0000000..a634593 --- /dev/null +++ b/libclasp/clasp/satelite.h @@ -0,0 +1,170 @@ +// +// Copyright (c) 2006-2010, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +//! \file +//! \brief Types and functions for SAT-based preprocessing. +#ifndef CLASP_SATELITE_H_INCLUDED +#define CLASP_SATELITE_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include + +namespace Clasp { +//! SatElite preprocessor for clauses. +/*! + * \ingroup shared + * The preprocessor implements subsumption, self-subsumption, variable elimination, + * and (optionally) blocked clause elimination. + * \see + * - Niklas Eén, Armin Biere: "Effective Preprocessing in SAT through Variable and Clause Elimination" + * - Matti Järvisalo, Armin Biere, Marijn Heule: "Blocked Clause Elimination" + * - Parts of the SatElite preprocessor are adapted from MiniSAT 2.0 beta + * available under the MIT licence from http://minisat.se/MiniSat.html + * . + */ +class SatElite : public Clasp::SatPreprocessor { +public: + SatElite(); + ~SatElite(); + Clasp::SatPreprocessor* clone(); + //! Event type for providing information on preprocessing progress. + struct Progress : public Event_t { + enum EventOp { event_algorithm = '*', event_bce = 'B', event_var_elim = 'E', event_subsumption = 'S', }; + Progress(SatElite* p, EventOp o, uint32 i, uint32 m) : Event_t(Event::subsystem_prepare, Event::verbosity_high), self(p), cur(i), max(m) { + op = (uint32)o; + } + SatElite* self; + uint32 cur; + uint32 max; + }; +protected: + bool initPreprocess(Options& opts); + void reportProgress(Progress::EventOp, uint32 curr, uint32 max); + bool doPreprocess(); + void doExtendModel(ValueVec& m, LitVec& open); + void doCleanUp(); +private: + typedef PodVector::type TouchedList; + typedef bk_lib::left_right_sequence ClWList; + typedef ClWList::left_iterator ClIter; + typedef ClWList::right_iterator WIter; + typedef std::pair ClRange; + SatElite(const SatElite&); + const SatElite& operator=(const SatElite&); + // For each var v + struct OccurList { + OccurList() : pos(0), bce(0), dirty(0), neg(0), litMark(0) {} + ClWList refs; // left : ids of clauses containing v or ~v (var() == id, sign() == v or ~v) + // right: ids of clauses watching v or ~v (literal 0 is the watched literal) + uint32 pos:30; // number of *relevant* clauses containing v + uint32 bce:1; // in BCE queue? + uint32 dirty:1; // does clauses contain removed clauses? + uint32 neg:30; // number of *relevant* clauses containing v + uint32 litMark:2; // 00: no literal of v marked, 01: v marked, 10: ~v marked + uint32 numOcc() const { return pos + neg; } + uint32 cost() const { return pos * neg; } + ClRange clauseRange() const { return ClRange(const_cast(refs).left_begin(), const_cast(refs).left_end()); } + void clear() { + this->~OccurList(); + new (this) OccurList(); + } + void addWatch(uint32 clId) { refs.push_right(clId); } + void removeWatch(uint32 clId) { refs.erase_right(std::find(refs.right_begin(), refs.right_end(), clId)); } + void add(uint32 id, bool sign){ + pos += uint32(!sign); + neg += uint32(sign); + refs.push_left(Literal(id, sign)); + } + void remove(uint32 id, bool sign, bool updateClauseList) { + pos -= uint32(!sign); + neg -= uint32(sign); + if (updateClauseList) { + refs.erase_left(std::find(refs.left_begin(), refs.left_end(), Literal(id, sign))); + } + else { dirty = 1; } + } + // note: only one literal of v shall be marked at a time + bool marked(bool sign) const { return (litMark & (1+int(sign))) != 0; } + void mark(bool sign) { litMark = (1+int(sign)); } + void unmark() { litMark = 0; } + }; + struct LessOccCost { + explicit LessOccCost(OccurList*& occ) : occ_(occ) {} + bool operator()(Var v1, Var v2) const { return occ_[v1].cost() < occ_[v2].cost(); } + private: + const LessOccCost& operator=(LessOccCost&); + OccurList*& occ_; + }; + typedef bk_lib::indexed_priority_queue ElimHeap; + Clause* peekSubQueue() const { + assert(qFront_ < queue_.size()); + return (Clause*)clause( queue_[qFront_] ); + } + inline Clause* popSubQueue(); + inline void addToSubQueue(uint32 clauseId); + void updateHeap(Var v) { + assert(ctx_); + if (!ctx_->varInfo(v).frozen() && !ctx_->eliminated(v)) { + elimHeap_.update(v); + if (occurs_[v].bce == 0 && occurs_[0].bce != 0) { + occurs_[0].addWatch(v); + occurs_[v].bce = 1; + } + } + } + inline uint32 findUnmarkedLit(const Clause& c, uint32 x) const; + void attach(uint32 cId, bool initialClause); + void detach(uint32 cId); + void bceVeRemove(uint32 cId, bool freeId, Var v, bool blocked); + bool propagateFacts(); + bool backwardSubsume(); + Literal subsumes(const Clause& c, const Clause& other, Literal res) const; + bool strengthenClause(uint32 clauseId, Literal p); + bool subsumed(LitVec& cl); + bool eliminateVars(); + bool bce(); + bool bceVe(Var v, uint32 maxCnt); + ClRange splitOcc(Var v, bool mark); + bool trivialResolvent(const Clause& c2, Var v) const; + void markAll(const Literal* lits, uint32 size) const; + void unmarkAll(const Literal* lits, uint32 size) const; + bool addResolvent(uint32 newId, const Clause& c1, const Clause& c2); + bool cutoff(Var v) const { + return opts_->occLimit(occurs_[v].pos, occurs_[v].neg) + || (occurs_[v].cost() == 0 && ctx_->preserveModels()); + } + bool timeout() const { return time(0) > timeout_; } + enum OccSign { pos = 0, neg = 1}; + OccurList* occurs_; // occur list for each variable + ElimHeap elimHeap_; // candidates for variable elimination; ordered by increasing occurrence-cost + VarVec occT_[2]; // temporary clause lists used in eliminateVar + ClauseList resCands_; // pairs of clauses to be resolved + LitVec resolvent_; // temporary, used in addResolvent + VarVec queue_; // indices of clauses waiting for subsumption-check + uint32 qFront_; // front of queue_, i.e. [queue_.begin()+qFront_, queue.end()) is the subsumption queue + uint32 facts_; // [facts_, solver.trail.size()): new top-level facts + std::time_t timeout_; // stop once time > timeout_ +}; +} +#endif diff --git a/libclasp/clasp/shared_context.h b/libclasp/clasp/shared_context.h new file mode 100644 index 0000000..826bdea --- /dev/null +++ b/libclasp/clasp/shared_context.h @@ -0,0 +1,939 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_SHARED_CONTEXT_H_INCLUDED +#define CLASP_SHARED_CONTEXT_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif +#include +#include +#include +#include +#include +#include +/*! + * \file + * \brief Contains common types shared between different solvers. + */ +namespace Clasp { +class Assignment; +class SharedLiterals; +struct SolverStats; +class StatisticObject; +typedef Asp::PrgDepGraph PrgDepGraph; +//! An immutable string with efficient copying. +/*! + * \ingroup misc + */ +class ConstString { +public: + //! Creates a string from str. + /*! + * \note If o is Ownership_t::Acquire (the default), str is copied. + * Otherwise, no copy is made and the lifetime of str shall extend + * past that of the constructed object. + */ + ConstString(const char* str = "", Ownership_t::Type o = Ownership_t::Acquire); + //! Creates a copy of str. + ConstString(const StrView& str); + ConstString(const ConstString& other); + ~ConstString(); + static ConstString fromLiteral(const char* str) { return ConstString(str, Ownership_t::Retain); } + ConstString& operator=(const ConstString& rhs); + const char* c_str() const; + operator const char* () const { return c_str(); } + void swap(ConstString& o); +private: + typedef uint64 RefType; + RefType ref_; +}; +/** +* \defgroup shared SharedContext +* \brief %SharedContext and related types. +*/ + +//! Base class for event handlers. +/*! + * \ingroup shared + */ +class EventHandler : public ModelHandler { +public: + //! Creates a handler for events with given verbosity or lower. + explicit EventHandler(Event::Verbosity verbosity = Event::verbosity_quiet); + virtual ~EventHandler(); + //! Sets the verbosity for the given event source. + /*! + * Events with higher verbosity are not dispatched to this handler. + */ + void setVerbosity(Event::Subsystem sys, Event::Verbosity verb); + //! Sets the active event source to sys if sys is not yet active. + bool setActive(Event::Subsystem sys); + Event::Subsystem active() const; + uint32 verbosity(Event::Subsystem sys) const { return (uint32(verb_) >> (uint32(sys)<(ev.system))) { onEvent(ev); } } + virtual void onEvent(const Event& /* ev */) {} + virtual bool onModel(const Solver&, const Model&) { return true; } +private: + enum { VERB_SHIFT = 2u, VERB_MAX = 15u }; + EventHandler(const EventHandler&); + EventHandler& operator=(const EventHandler&); + uint16 verb_; + uint16 sys_; +}; + +//! Event type for log or warning messages. +/*! + * \ingroup enumerator + */ +struct LogEvent : Event_t { + enum Type { Message = 'M', Warning = 'W' }; + LogEvent(Subsystem sys, Verbosity verb, Type t, const Solver* s, const char* what) : Event_t(sys, verb), solver(s), msg(what) { + op = static_cast(t); + } + bool isWarning() const { return op == static_cast(Warning); } + const Solver* solver; + const char* msg; +}; + +//! Base class for preprocessors working on clauses only. +/*! + * \ingroup shared + */ +class SatPreprocessor { +public: + //! A clause class optimized for preprocessing. + class Clause { + public: + static Clause* newClause(const Literal* lits, uint32 size); + static uint64 abstractLit(Literal p) { return uint64(1) << ((p.var()-1) & 63); } + uint32 size() const { return size_; } + const Literal& operator[](uint32 x) const { return lits_[x]; } + bool inQ() const { return inQ_ != 0; } + uint64 abstraction() const { return data_.abstr; } + Clause* next() const { return data_.next; } + bool marked() const { return marked_ != 0;} + Literal& operator[](uint32 x) { return lits_[x]; } + void setInQ(bool b) { inQ_ = (uint32)b;} + void setMarked(bool b) { marked_ = (uint32)b;} + uint64& abstraction() { return data_.abstr; } + Clause* linkRemoved(Clause* next) { data_.next = next; return this; } + void strengthen(Literal p); + void simplify(Solver& s); + void destroy(); + private: + Clause(const Literal* lits, uint32 size); + union { + uint64 abstr; // abstraction of literals + Clause* next; // next removed clause + } data_; + uint32 size_ : 30; // size of the clause + uint32 inQ_ : 1; // in todo-queue? + uint32 marked_ : 1; // a marker flag + Literal lits_[1]; // literals of the clause: [lits_[0], lits_[size_]) + }; + + SatPreprocessor(); + virtual ~SatPreprocessor(); + + //! Creates a clone of this preprocessor. + /*! + * \note The function does not clone any clauses already added to *this. + */ + virtual SatPreprocessor* clone() = 0; + + uint32 numClauses() const { return (uint32)clauses_.size(); } + //! Adds a clause to the preprocessor. + /*! + * \pre clause is not a tautology (i.e. does not contain both l and ~l) + * \pre clause is a set (i.e. does not contain l more than once) + * \return true if clause was added. False if adding the clause makes the problem UNSAT + */ + bool addClause(const LitVec& cl) { return addClause(!cl.empty() ? &cl[0] : 0, sizeVec(cl)); } + bool addClause(const Literal* clause, uint32 size); + //! Runs the preprocessor on all clauses that were previously added. + /*! + * \pre A ctx.startAddConstraint() was called and has variables for all added clauses. + */ + bool preprocess(SharedContext& ctx, SatPreParams& opts); + bool preprocess(SharedContext& ctx); + + //! Force removal of state & clauses. + void cleanUp(bool discardEliminated = false); + + //! Extends the model in m with values for any eliminated variables. + void extendModel(ValueVec& m, LitVec& open); + struct Stats { + Stats() : clRemoved(0), clAdded(0), litsRemoved(0) {} + uint32 clRemoved; + uint32 clAdded; + uint32 litsRemoved; + } stats; + typedef SatPreParams Options; +protected: + typedef PodVector::type ClauseList; + virtual bool initPreprocess(SatPreParams& opts) = 0; + virtual bool doPreprocess() = 0; + virtual void doExtendModel(ValueVec& m, LitVec& open) = 0; + virtual void doCleanUp() = 0; + Clause* clause(uint32 clId) { return clauses_[clId]; } + const Clause* clause(uint32 clId) const { return clauses_[clId]; } + void freezeSeen(); + void discardClauses(bool discardEliminated); + void setClause(uint32 clId, const LitVec& cl) { + clauses_[clId] = Clause::newClause(&cl[0], (uint32)cl.size()); + } + void destroyClause(uint32 clId){ + clauses_[clId]->destroy(); + clauses_[clId] = 0; + ++stats.clRemoved; + } + void eliminateClause(uint32 id){ + elimTop_ = clauses_[id]->linkRemoved(elimTop_); + clauses_[id] = 0; + ++stats.clRemoved; + } + SharedContext* ctx_; // current context + const Options* opts_; // active options + Clause* elimTop_; // stack of blocked/eliminated clauses +private: + SatPreprocessor(const SatPreprocessor&); + SatPreprocessor& operator=(const SatPreprocessor&); + ClauseList clauses_; // initial non-unit clauses + LitVec units_; // initial unit clauses + Range32 seen_; // vars seen in previous step +}; + +/////////////////////////////////////////////////////////////////////////////// +// Problem statistics +/////////////////////////////////////////////////////////////////////////////// +/*! + * \addtogroup shared + * @{ + */ +//! A struct for aggregating basic problem statistics. +struct ProblemStats { + ProblemStats() { reset(); } + struct { uint32 num, eliminated, frozen; } vars; + struct { uint32 other, binary, ternary; } constraints; + uint32 acycEdges; + uint32 complexity; + void reset() { std::memset(this, 0, sizeof(*this)); } + uint32 numConstraints() const { return constraints.other + constraints.binary + constraints.ternary; } + void diff(const ProblemStats& o) { + vars.num = std::max(vars.num, o.vars.num)-std::min(vars.num, o.vars.num); + vars.eliminated = std::max(vars.eliminated, o.vars.eliminated)-std::min(vars.eliminated, o.vars.eliminated); + vars.frozen = std::max(vars.frozen, o.vars.frozen)-std::min(vars.frozen, o.vars.frozen); + constraints.other = std::max(constraints.other, o.constraints.other) - std::min(constraints.other, o.constraints.other); + constraints.binary = std::max(constraints.binary, o.constraints.binary) - std::min(constraints.binary, o.constraints.binary); + constraints.ternary= std::max(constraints.ternary, o.constraints.ternary) - std::min(constraints.ternary, o.constraints.ternary); + acycEdges = std::max(acycEdges, o.acycEdges) - std::min(acycEdges, o.acycEdges); + } + void accu(const ProblemStats& o) { + vars.num += o.vars.num; + vars.eliminated += o.vars.eliminated; + vars.frozen += o.vars.frozen; + constraints.other += o.constraints.other; + constraints.binary += o.constraints.binary; + constraints.ternary += o.constraints.ternary; + acycEdges += o.acycEdges; + } + // StatisticObject + static uint32 size(); + static const char* key(uint32 i); + StatisticObject at(const char* k) const; +}; + +//! Stores static information about a variable. +struct VarInfo { + //! Possible flags. + enum Flag { + Mark_p = 0x1u, //!< Mark for positive literal. + Mark_n = 0x2u, //!< Mark for negative literal. + Input = 0x4u, //!< Is this var an input variable? + Body = 0x8u, //!< Is this var representing a body? + Eq = 0x10u, //!< Is this var representing both a body and an atom? + Nant = 0x20u, //!< Is this var in NAnt(P)? + Frozen = 0x40u, //!< Is the variable frozen? + Output = 0x80u //!< Is the variable an output variable? + }; + static uint8 flags(VarType t) { + if (t == Var_t::Body) { return VarInfo::Body; } + if (t == Var_t::Hybrid){ return VarInfo::Eq; } + return 0; + } + explicit VarInfo(uint8 r = 0) : rep(r) { } + //! Returns the type of the variable (or Var_t::Hybrid if variable was created with parameter eq=true). + VarType type() const { return has(VarInfo::Eq) ? Var_t::Hybrid : VarType(Var_t::Atom + has(VarInfo::Body)); } + //! Returns whether var is part of negative antecedents (occurs negatively or in the head of a choice rule). + bool nant() const { return has(VarInfo::Nant); } + //! Returns true if var is excluded from variable elimination. + bool frozen() const { return has(VarInfo::Frozen); } + //! Returns true if var is an input variable. + bool input() const { return has(VarInfo::Input); } + //! Returns true if var is marked as output variable. + bool output() const { return has(VarInfo::Output); } + //! Returns the preferred sign of this variable w.r.t its type. + /*! + * \return false (i.e no sign) if var originated from body, otherwise true. + */ + bool preferredSign() const { return !has(VarInfo::Body); } + + bool has(Flag f) const { return (rep & flag(f)) != 0; } + bool has(uint32 f) const { return (rep & f) != 0; } + bool hasAll(uint32 f)const { return (rep & f) == f; } + void set(Flag f) { rep |= flag(f); } + void toggle(Flag f) { rep ^= flag(f); } + static uint8 flag(Flag x) { return uint8(x); } + uint8 rep; +}; + +//! A class for efficiently storing and propagating binary and ternary clauses. +/*! + * \ingroup shared_con + */ +class ShortImplicationsGraph { +public: + ShortImplicationsGraph(); + ~ShortImplicationsGraph(); + enum ImpType { binary_imp = 2, ternary_imp = 3 }; + + //! Makes room for nodes number of nodes. + void resize(uint32 nodes); + //! Mark the instance as shared/unshared. + /*! + * A shared instance adds learnt binary/ternary clauses + * to specialized shared blocks of memory. + */ + void markShared(bool b) { shared_ = b; } + //! Adds the given constraint to the implication graph. + /*! + * \return true iff a new implication was added. + */ + bool add(ImpType t, bool learnt, const Literal* lits); + + //! Removes p and its implications. + /*! + * \pre s.isTrue(p) + */ + void removeTrue(const Solver& s, Literal p); + + //! Propagates consequences of p following from binary and ternary clauses. + /*! + * \pre s.isTrue(p) + */ + bool propagate(Solver& s, Literal p) const; + //! Propagates immediate consequences of p following from binary clauses only. + bool propagateBin(Assignment& out, Literal p, uint32 dl) const; + //! Checks whether there is a reverse arc implying p and if so returns it in out. + bool reverseArc(const Solver& s, Literal p, uint32 maxLev, Antecedent& out) const; + + uint32 numBinary() const { return bin_[0]; } + uint32 numTernary()const { return tern_[0]; } + uint32 numLearnt() const { return bin_[1] + tern_[1]; } + uint32 numEdges(Literal p) const; + uint32 size() const { return sizeVec(graph_); } + //! Applies op on all unary- and binary implications following from p. + /*! + * OP must provide two functions: + * - bool unary(Literal, Literal) + * - bool binary(Literal, Literal, Literal) + * The first argument will be p, the second (resp. third) the unary + * (resp. binary) clause implied by p. + * \note For learnt imps, at least one literal has its watch-flag set. + */ + template + bool forEach(Literal p, const OP& op) const { + const ImplicationList& x = graph_[p.id()]; + if (x.empty()) return true; + ImplicationList::const_right_iterator rEnd = x.right_end(); // prefetch + for (ImplicationList::const_left_iterator it = x.left_begin(), end = x.left_end(); it != end; ++it) { + if (!op.unary(p, *it)) { return false; } + } + for (ImplicationList::const_right_iterator it = x.right_begin(); it != rEnd; ++it) { + if (!op.binary(p, it->first, it->second)) { return false; } + } +#if WITH_THREADS + for (Block* b = (x).learnt; b ; b = b->next) { + p.flag(); bool r = true; + for (Block::const_iterator imp = b->begin(), endOf = b->end(); imp != endOf; ) { + if (!imp->flagged()) { r = op.binary(p, imp[0], imp[1]); imp += 2; } + else { r = op.unary(p, imp[0]); imp += 1; } + if (!r) { return false; } + } + } +#endif + return true; + } +private: + ShortImplicationsGraph(const ShortImplicationsGraph&); + ShortImplicationsGraph& operator=(ShortImplicationsGraph&); + struct Propagate; + struct ReverseArc; +#if WITH_THREADS + struct Block { + typedef Clasp::mt::atomic atomic_size; + typedef Clasp::mt::atomic atomic_ptr; + typedef const Literal* const_iterator; + typedef Literal* iterator; + enum { block_cap = (64 - (sizeof(atomic_size)+sizeof(atomic_ptr)))/sizeof(Literal) }; + explicit Block(); + const_iterator begin() const { return data; } + const_iterator end() const { return data+size(); } + iterator end() { return data+size(); } + uint32 size() const { return size_lock >> 1; } + bool tryLock(uint32& lockedSize); + void addUnlock(uint32 lockedSize, const Literal* x, uint32 xs); + atomic_ptr next; + atomic_size size_lock; + Literal data[block_cap]; + }; + typedef Block::atomic_ptr SharedBlockPtr; + typedef bk_lib::left_right_sequence, 64-sizeof(SharedBlockPtr)> ImpListBase; + struct ImplicationList : public ImpListBase { + ImplicationList() : ImpListBase() { learnt = 0; } + ImplicationList(const ImplicationList& other) : ImpListBase(other), learnt() { + learnt = static_cast(other.learnt); + } + ImplicationList& operator=(const ImplicationList& other) { + ImpListBase::operator=(other); + learnt = static_cast(other.learnt); + return *this; + } + ~ImplicationList(); + bool hasLearnt(Literal q, Literal r = lit_false()) const; + void addLearnt(Literal q, Literal r = lit_false()); + void simplifyLearnt(const Solver& s); + bool empty() const { return ImpListBase::empty() && learnt == static_cast(0); } + void move(ImplicationList& other); + void clear(bool b); + SharedBlockPtr learnt; + }; +#else + typedef bk_lib::left_right_sequence, 64> ImplicationList; +#endif + ImplicationList& getList(Literal p) { return graph_[p.id()]; } + void remove_bin(ImplicationList& w, Literal p); + void remove_tern(ImplicationList& w, Literal p); + typedef PodVector::type ImpLists; + ImpLists graph_; // one implication list for each literal + uint32 bin_[2]; // number of binary constraints (0: problem / 1: learnt) + uint32 tern_[2]; // number of ternary constraints(0: problem / 1: learnt) + bool shared_; +}; + +//! Base class for distributing learnt knowledge between solvers. +class Distributor { +public: + struct Policy { + enum Types { + no = 0, + conflict = Constraint_t::Conflict, + loop = Constraint_t::Loop, + all = conflict | loop, + implicit = all + 1 + }; + Policy(uint32 a_sz = 0, uint32 a_lbd = 0, uint32 a_type = 0) : size(a_sz), lbd(a_lbd), types(a_type) {} + uint32 size : 22; /*!< Allow distribution up to this size only. */ + uint32 lbd : 7; /*!< Allow distribution up to this lbd only. */ + uint32 types : 3; /*!< Restrict distribution to these types. */ + }; + static uint64 mask(uint32 i) { return uint64(1) << i; } + static uint32 initSet(uint32 sz) { return (uint64(1) << sz) - 1; } + static bool inSet(uint64 s, uint32 id) { return (s & mask(id)) != 0; } + explicit Distributor(const Policy& p); + virtual ~Distributor(); + bool isCandidate(uint32 size, uint32 lbd, uint32 type) const { + return size <= policy_.size && lbd <= policy_.lbd && ((type & policy_.types) != 0); + } + virtual void publish(const Solver& source, SharedLiterals* lits) = 0; + virtual uint32 receive(const Solver& in, SharedLiterals** out, uint32 maxOut) = 0; +private: + Distributor(const Distributor&); + Distributor& operator=(const Distributor&); + Policy policy_; +}; + +//! Output table that contains predicates to be output on model. +class OutputTable { +public: + typedef ConstString NameType; + typedef Range32 RangeType; + struct PredType { + NameType name; + Literal cond; + uint32 user; + }; + typedef PodVector::type FactVec; + typedef PodVector::type PredVec; + typedef FactVec::const_iterator fact_iterator; + typedef PredVec::const_iterator pred_iterator; + typedef num_iterator range_iterator; + typedef LitVec::const_iterator lit_iterator; + enum ProjectMode { project_output = 0u, project_explicit = 1u }; + + OutputTable(); + ~OutputTable(); + //! Ignore predicates starting with c. + void setFilter(char c); + //! Adds a fact. + bool add(const NameType& fact); + //! Adds an output predicate, i.e. n is output if c is true. + bool add(const NameType& n, Literal c, uint32 u = 0); + //! Sets a range of output variables. + void setVarRange(const RangeType& r); + + //! Returns whether n would be filtered out. + bool filter(const NameType& n) const; + + fact_iterator fact_begin() const { return facts_.begin(); } + fact_iterator fact_end() const { return facts_.end(); } + pred_iterator pred_begin() const { return preds_.begin(); } + pred_iterator pred_end() const { return preds_.end(); } + range_iterator vars_begin() const { return range_iterator(vars_.lo); } + range_iterator vars_end() const { return range_iterator(vars_.hi); } + + ProjectMode projectMode()const { return proj_.empty() ? project_output : project_explicit; } + lit_iterator proj_begin() const { return proj_.begin(); } + lit_iterator proj_end() const { return proj_.end(); } + void addProject(Literal x); + + //! Returns the number of output elements, counting each element in a var range. + uint32 size() const; + uint32 numFacts() const { return static_cast(facts_.size()); } + uint32 numPreds() const { return static_cast(preds_.size()); } + uint32 numVars() const { return static_cast(vars_.hi - vars_.lo); } + + //! An optional callback for getting additional theory output. + class Theory { + public: + virtual ~Theory(); + //! Called once on new model m. Shall return 0 to indicate no output. + virtual const char* first(const Model& m) = 0; + //! Shall return 0 to indicate no output. + virtual const char* next() = 0; + }* theory; +private: + FactVec facts_; + PredVec preds_; + LitVec proj_; + Range32 vars_; + char hide_; +}; +//! A type for storing information to be used in clasp's domain heuristic. +class DomainTable { +public: + DomainTable(); + //! A type storing a single domain modification for a variable. + class ValueType { + public: + ValueType(Var v, DomModType t, int16 bias, uint16 prio, Literal cond); + bool hasCondition() const { return cond_ != 0; } + Literal cond() const { return Literal::fromId(cond_); } + Var var() const { return var_; } + DomModType type() const; + int16 bias() const { return bias_; } + uint16 prio() const { return prio_; } + bool comp() const { return comp_ != 0; } + private: + uint32 cond_ : 31; + uint32 comp_ : 1; + uint32 var_ : 30; + uint32 type_ : 2; + int16 bias_; + uint16 prio_; + }; + typedef PodVector::type DomVec; + typedef DomVec::const_iterator iterator; + + void add(Var v, DomModType t, int16 bias, uint16 prio, Literal cond); + uint32 simplify(); + void reset(); + bool empty() const; + uint32 size() const; + iterator begin() const; + iterator end() const; + LitVec* domRec; +private: + static bool cmp(const ValueType& lhs, const ValueType& rhs) { + return lhs.cond() < rhs.cond() || (lhs.cond() == rhs.cond() && lhs.var() < rhs.var()); + } + DomVec entries_; + uint32 seen_; // size of domain table after last simplify +}; + +//! Aggregates information to be shared between solver objects. +/*! + * Among other things, SharedContext objects store + * static information on variables, an output table, as well as the + * binary and ternary implication graph of the input problem. + * + * Furthermore, a SharedContext object always stores a distinguished + * master solver that is used to store and simplify problem constraints. + * Additional solvers can be added via SharedContext::pushSolver(). + * Once initialization is completed, any additional solvers must be attached + * to this object by calling SharedContext::attach(). + */ +class SharedContext { +public: + typedef PodVector::type SolverVec; + typedef SingleOwnerPtr SccGraph; + typedef SingleOwnerPtr ExtGraph; + typedef Configuration* ConfigPtr; + typedef SingleOwnerPtr DistrPtr; + typedef const ProblemStats& StatsCRef; + typedef DomainTable DomTab; + typedef OutputTable Output; + typedef LitVec::size_type size_type; + typedef ShortImplicationsGraph ImpGraph; + typedef const ImpGraph& ImpGraphRef; + typedef EventHandler* LogPtr; + typedef SingleOwnerPtrSatPrePtr; + typedef SharedMinimizeData* MinPtr; + enum ResizeMode { resize_reserve = 0u, resize_push = 1u, resize_pop = 2u, resize_resize = 3u}; + enum PreproMode { prepro_preserve_models = 1u, prepro_preserve_shown = 2u }; + enum ReportMode { report_default = 0u, report_conflict = 1u }; + enum SolveMode { solve_once = 0u, solve_multi = 1u }; + /*! + * \name Configuration + * \brief Functions for creating and configuring a shared context. + * @{ */ + //! Creates a new object for sharing variables and the binary and ternary implication graph. + explicit SharedContext(); + ~SharedContext(); + //! Resets this object to the state after default construction. + void reset(); + //! Enables event reporting via the given event handler. + void setEventHandler(LogPtr r, ReportMode m = report_default) { progress_ = r; share_.report = uint32(m); } + //! Sets solve mode, which can be used by other objects to query whether multi-shot solving is active. + void setSolveMode(SolveMode m); + //! Sets how to handle physical sharing of constraints. + void setShareMode(ContextParams::ShareMode m); + //! Sets whether the short implication graph should be used for storing short learnt constraints. + void setShortMode(ContextParams::ShortMode m); + //! Sets maximal number of solvers sharing this object. + void setConcurrency(uint32 numSolver, ResizeMode m = resize_reserve); + //! If b is true, sets preprocessing mode to model-preserving operations only. + void setPreserveModels(bool b = true) { setPreproMode(prepro_preserve_models, b); } + //! If b is true, excludes all shown variables from variable elimination. + void setPreserveShown(bool b = true) { setPreproMode(prepro_preserve_shown, b); } + + //! Adds an additional solver to this object and returns it. + Solver& pushSolver(); + //! Configures the statistic object of attached solvers. + /*! + * The level determines the amount of extra statistics. + * \see ExtendedStats + * \see JumpStats + */ + void enableStats(uint32 level); + //! Sets the configuration for this object and its attached solvers. + /*! + * \note If ownership is Ownership_t::Acquire, ownership of c is transferred. + */ + void setConfiguration(Configuration* c, Ownership_t::Type ownership); + SatPrePtr satPrepro; /*!< Preprocessor for simplifying the problem. */ + SccGraph sccGraph; /*!< Program dependency graph - only used for ASP-problems. */ + ExtGraph extGraph; /*!< External dependency graph - given by user. */ + + //! Returns the current configuration used in this object. + ConfigPtr configuration() const { return config_.get(); } + //! Returns the active event handler or 0 if none was set. + LogPtr eventHandler() const { return progress_; } + //! Returns whether this object seeds the RNG of new solvers. + bool seedSolvers() const { return share_.seed != 0; } + //! Returns the number of solvers that can share this object. + uint32 concurrency() const { return share_.count; } + bool preserveModels() const { return (share_.satPreM & prepro_preserve_models) != 0; } + bool preserveShown() const { return (share_.satPreM & prepro_preserve_shown) != 0; } + //! Returns whether physical sharing is enabled for constraints of type t. + bool physicalShare(ConstraintType t) const { return (share_.shareM & (1 + (t != Constraint_t::Static))) != 0; } + //! Returns whether pyhiscal sharing of problem constraints is enabled. + bool physicalShareProblem() const { return (share_.shareM & ContextParams::share_problem) != 0; } + //! Returns whether short constraints of type t can be stored in the short implication graph. + bool allowImplicit(ConstraintType t) const { return t != Constraint_t::Static ? share_.shortM != ContextParams::short_explicit : !isShared(); } + //! Returns the configured solve mode. + SolveMode solveMode() const { return static_cast(share_.solveM); } + //@} + + /*! + * \name Problem introspection + * \brief Functions for querying information about the problem. + */ + //@{ + //! Returns true unless the master has an unresolvable top-level conflict. + bool ok() const; + //! Returns whether the problem is currently frozen and therefore ready for being solved. + bool frozen() const { return share_.frozen;} + //! Returns whether more than one solver is actively working on the problem. + bool isShared() const { return frozen() && concurrency() > 1; } + //! Returns whether the problem is more than a simple CNF. + bool isExtended() const { return stats_.vars.frozen != 0; } + //! Returns whether this object has a solver associcated with the given id. + bool hasSolver(uint32 id) const { return id < solvers_.size(); } + //! Returns the master solver associated with this object. + Solver* master() const { return solver(0); } + //! Returns the solver with the given id. + Solver* solver(uint32 id) const { return solvers_[id]; } + + //! Returns the number of problem variables. + /*! + * \note The special sentinel-var 0 is not counted, i.e. numVars() returns + * the number of problem-variables. + * To iterate over all problem variables use a loop like: + * \code + * for (Var i = 1; i <= numVars(); ++i) {...} + * \endcode + */ + uint32 numVars() const { return static_cast(varInfo_.size() - 1); } + //! Returns the number of eliminated vars. + uint32 numEliminatedVars() const { return stats_.vars.eliminated; } + //! Returns true if var represents a valid variable in this problem. + /*! + * \note The range of valid variables is [1..numVars()]. The variable 0 + * is a special sentinel variable. + */ + bool validVar(Var var) const { return var < static_cast(varInfo_.size()); } + //! Returns information about the given variable. + VarInfo varInfo(Var v) const { assert(validVar(v)); return varInfo_[v]; } + //! Returns true if v is currently eliminated, i.e. no longer part of the problem. + bool eliminated(Var v) const; + bool marked(Literal p) const { return varInfo(p.var()).has(VarInfo::Mark_p + p.sign()); } + //! Returns the number of problem constraints. + uint32 numConstraints() const; + //! Returns the number of binary constraints. + uint32 numBinary() const { return btig_.numBinary(); } + //! Returns the number of ternary constraints. + uint32 numTernary() const { return btig_.numTernary(); } + //! Returns the number of unary constraints. + uint32 numUnary() const { return lastTopLevel_; } + //! Returns an estimate of the problem complexity based on the number and type of constraints. + uint32 problemComplexity() const; + //! Returns whether the problem contains minimize (i.e. weak) constraints. + bool hasMinimize() const; + StatsCRef stats() const { return stats_; } + //@} + + /*! + * \name Problem setup + * \brief Functions for specifying the problem. + * + * Problem specification is a four-stage process: + * -# Add variables to the SharedContext object. + * -# Call startAddConstraints(). + * -# Add problem constraints. + * -# Call endInit() to finish the initialization process. + * . + * \note After endInit() was called, other solvers can be attached to this object. + * \note In incremental setting, the process must be repeated for each incremental step. + * + * \note Problem specification is *not* thread-safe, i.e. during initialization no other thread shall + * access the context. + * + * \note !frozen() is a precondition for all functions in this group! + * @{ */ + //! Unfreezes a frozen program and prepares it for updates. + /*! + * The function also triggers forgetting of volatile knowledge and removes + * any auxiliary variables. + * \see requestStepVar() + * \see Solver::popAuxVar() + */ + bool unfreeze(); + + //! Adds a new variable and returns its numerical id. + /*! + * \param type Type of variable. + * \param flags Additional information associated with the new variable. + * \note Problem variables are numbered from 1 onwards! + */ + Var addVar(VarType type, uint8 flags = VarInfo::Nant | VarInfo::Input) { return addVars(1, type, flags); } + Var addVars(uint32 nVars, VarType type, uint8 flags = VarInfo::Nant | VarInfo::Input); + //! Removes the n most recently added problem variables. + /*! + * \pre The variables have either not yet been committed by a call to startAddConstraints() + * or they do not occur in any constraint. + */ + void popVars(uint32 n = 1); + //! Freezes/defreezes a variable (a frozen var is exempt from Sat-preprocessing). + void setFrozen(Var v, bool b); + //! Marks/unmarks v as input variable. + void setInput(Var v, bool b) { set(v, VarInfo::Input, b); } + //! Marks/unmarks v as output variable. + void setOutput(Var v, bool b) { set(v, VarInfo::Output, b); } + //! Marks/unmarks v as part of negative antecedents. + void setNant(Var v, bool b) { set(v, VarInfo::Nant, b); } + void setVarEq(Var v, bool b) { set(v, VarInfo::Eq, b); } + void set(Var v, VarInfo::Flag f, bool b) { if (b != varInfo(v).has(f)) varInfo_[v].toggle(f); } + void mark(Literal p) { assert(validVar(p.var())); varInfo_[p.var()].rep |= (VarInfo::Mark_p + p.sign()); } + void unmark(Var v) { assert(validVar(v)); varInfo_[v].rep &= ~(VarInfo::Mark_p|VarInfo::Mark_n); } + //! Eliminates the variable v from the problem. + /*! + * \pre v must not occur in any constraint and frozen(v) == false and value(v) == value_free + */ + void eliminate(Var v); + + //! Prepares the master solver so that constraints can be added. + /*! + * Must be called to publish previously added variables to master solver + * and before constraints over these variables can be added. + * \return The master solver associated with this object. + */ + Solver& startAddConstraints(uint32 constraintGuess = 100); + + //! A convenience method for adding facts to the master. + bool addUnary(Literal x); + //! A convenience method for adding binary clauses. + bool addBinary(Literal x, Literal y); + //! A convenience method for adding ternary clauses. + bool addTernary(Literal x, Literal y, Literal z); + //! A convenience method for adding constraints to the master. + void add(Constraint* c); + //! Add weak constraint :~ x.first \[x.second\@p\]. + void addMinimize(WeightLiteral x, weight_t p); + //! Returns a pointer to an optimized representation of all minimize constraints in this problem. + MinPtr minimize(); + //! List of output predicates and/or variables. + Output output; + //! Set of heuristic modifications. + DomTab heuristic; + //! Requests a special variable for tagging volatile knowledge in multi-shot solving. + /*! + * The step variable is created on the next call to endInit() and removed on the next + * call to unfreeze(). + * Once the step variable S is set, learnt constraints containing ~S are + * considered to be "volatile" and removed on the next call to unfreeze(). + * For this to work correctly, S shall be a root assumption during search. + */ + void requestStepVar(); + //! Finishes initialization of the master solver. + /*! + * The function must be called once before search is started. After endInit() + * was called, previously added solvers can be attached to the + * shared context and learnt constraints may be added to solver. + * \param attachAll If true, also calls attach() for all solvers that were added to this object. + * \return If the constraints are initially conflicting, false. Otherwise, true. + * \note + * The master solver can't recover from top-level conflicts, i.e. if endInit() + * returned false, the solver is in an unusable state. + * \post frozen() + */ + bool endInit(bool attachAll = false); + //@} + + /*! + * \name (Parallel) solving + * Functions to be called during (parallel) solving. + * + * \note If not otherwise noted, the functions in this group can be safely called + * from multiple threads. + * @{ */ + //! Returns the active step literal (see requestStepVar()). + Literal stepLiteral() const { return step_; } + //! Attaches the solver with the given id to this object. + /*! + * \note It is safe to attach multiple solvers concurrently + * but the master solver shall not change during the whole operation. + * + * \pre hasSolver(id) + */ + bool attach(uint32 id) { return attach(*solver(id)); } + bool attach(Solver& s); + + //! Detaches the solver with the given id from this object. + /*! + * The function removes any tentative constraints from s. + * Shall be called once after search has stopped. + * \note The function is concurrency-safe w.r.t to different solver objects, + * i.e. in a parallel search different solvers may call detach() + * concurrently. + */ + void detach(uint32 id, bool reset = false) { return detach(*solver(id), reset); } + void detach(Solver& s, bool reset = false); + + DistrPtr distributor;/*!< Distributor object to use for distribution of learnt constraints.*/ + + uint32 winner() const { return share_.winner; } + void setWinner(uint32 sId) { share_.winner = std::min(sId, concurrency()); } + + //! Simplifies the problem constraints w.r.t the master's assignment. + void simplify(bool shuffle); + //! Removes the constraint with the given idx from the master's db. + void removeConstraint(uint32 idx, bool detach); + //! Removes all minimize constraints from this object. + void removeMinimize(); + + //! Adds the given short implication to the short implication graph if possible. + /*! + * \return + * - > 0 if implication was added. + * - < 0 if implication can't be added because allowImplicit() is false for ct. + * - = 0 if implication is subsumed by some constraint in the short implication graph. + */ + int addImp(ImpGraph::ImpType t, const Literal* lits, ConstraintType ct); + //! Returns the number of learnt short implications. + uint32 numLearntShort() const { return btig_.numLearnt(); } + ImpGraphRef shortImplications() const { return btig_; } + void simplifyShort(const Solver& s, Literal p); + void report(const Event& ev) const { if (progress_) progress_->dispatch(ev); } + bool report(const Solver& s, const Model& m) const { return !progress_ || progress_->onModel(s, m); } + void report(const char* what, const Solver* s = 0) const; + void report(Event::Subsystem sys) const; + void warn(const char* what) const; + ReportMode reportMode() const { return static_cast(share_.report); } + void initStats(Solver& s) const; + SolverStats& solverStats(uint32 sId) const; // stats of solver i + const SolverStats& accuStats(SolverStats& out) const; // accumulates all solver stats in out + //@} +private: + SharedContext(const SharedContext&); + SharedContext& operator=(const SharedContext&); + bool unfreezeStep(); + Literal addStepLit(); + typedef SingleOwnerPtr Config; + typedef PodVector::type VarVec; + void setPreproMode(uint32 m, bool b); + struct Minimize; + ProblemStats stats_; // problem statistics + VarVec varInfo_; // varInfo[v] stores info about variable v + ImpGraph btig_; // binary-/ternary implication graph + Config config_; // active configuration + SolverVec solvers_; // solvers associated with this context + Minimize* mini_; // pointer to set of weak constraints + LogPtr progress_; // event handler or 0 if not used + Literal step_; // literal for tagging enumeration/step constraints + uint32 lastTopLevel_; // size of master's top-level after last init + struct Share { // Additional data + uint32 count :10; // max number of objects sharing this object + uint32 winner :10; // id of solver that terminated the search + uint32 shareM : 3; // physical sharing mode + uint32 shortM : 1; // short clause mode + uint32 solveM : 1; // solve mode + uint32 frozen : 1; // is adding of problem constraints allowed? + uint32 seed : 1; // set seed of new solvers + uint32 satPreM : 2; // preprocessing mode + uint32 report : 2; // report mode + uint32 reserved: 1; + Share() : count(1), winner(0), shareM((uint32)ContextParams::share_auto), shortM(0), solveM(0), frozen(0), seed(0), satPreM(0), report(0) {} + } share_; +}; +//@} +} +#endif diff --git a/libclasp/clasp/solve_algorithms.h b/libclasp/clasp/solve_algorithms.h new file mode 100644 index 0000000..71adb86 --- /dev/null +++ b/libclasp/clasp/solve_algorithms.h @@ -0,0 +1,271 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_SOLVE_ALGORITHMS_H_INCLUDED +#define CLASP_SOLVE_ALGORITHMS_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include +/*! + * \file + * \brief Defines top-level functions for solving problems. + */ +namespace Clasp { + +///! \addtogroup enumerator +//@{ + +//! Type for holding global solve limits. +struct SolveLimits { + explicit SolveLimits(uint64 conf = UINT64_MAX, uint64 r = UINT64_MAX) + : conflicts(conf) + , restarts(r) { + } + bool reached() const { return conflicts == 0 || restarts == 0; } + bool enabled() const { return conflicts != UINT64_MAX || restarts != UINT32_MAX; } + uint64 conflicts; /*!< Number of conflicts. */ + uint64 restarts; /*!< Number of restarts. */ +}; + +/////////////////////////////////////////////////////////////////////////////// +// Basic solving +/////////////////////////////////////////////////////////////////////////////// +//! Basic (sequential) solving using given solving options. +class BasicSolve { +public: + //! Creates a new object for solving with the given solver using the given solving options. + /*! + * If an optional solve limit is given, solving stops once this limit is reached. + * \pre s is attached to a problem (SharedContext). + */ + BasicSolve(Solver& s, const SolveParams& p, const SolveLimits& lim = SolveLimits()); + BasicSolve(Solver& s, const SolveLimits& lim = SolveLimits()); + ~BasicSolve(); + + bool hasLimit() const { return limits_.enabled(); } + + //! Enables solving under the given assumptions. + /*! + * The use of assumptions allows for incremental solving. Literals contained + * in assumptions are assumed to be true during search but can be undone afterwards. + * + * \param assumptions A list of unit assumptions to be assumed true. + * \return false if assumptions are conflicting. + */ + bool assume(const LitVec& assumptions); + + //! Solves the path stored in the given solver using the given solving options. + /*! + * \return + * - value_true if search stopped on a model. + * - value_false if the search-space was completely examined. + * - value_free if the given solve limit was hit. + * + * \note + * The function maintains the current solving state (number of restarts, learnt limits, ...) + * between calls. + */ + ValueRep solve(); + //! Returns whether the given problem is satisfiable under the given assumptions. + /*! + * Calls assume(assumptions) followed by solve() but does not maintain any solving state. + * \param assumptions Possibly empty set of assumptions to apply before solving. + * \param init Call InitParams::randomize() before starting search? + */ + bool satisfiable(const LitVec& assumptions, bool init); + + //! Resets the internal solving state while keeping the solver and the solving options. + void reset(bool reinit = false); + //! Replaces *this with BasicSolve(s, p). + void reset(Solver& s, const SolveParams& p, const SolveLimits& lim = SolveLimits()); + Solver& solver() { return *solver_; } +private: + BasicSolve(const BasicSolve&); + BasicSolve& operator=(const BasicSolve&); + typedef const SolveParams Params; + typedef SolveLimits Limits; + struct State; + Solver* solver_; // active solver + Params* params_; // active solving options + Limits limits_; // active solving limits + State* state_; // internal solving state +}; +//! Event type for reporting basic solve events like restarts or deletion. +struct BasicSolveEvent : SolveEvent { + //! Type of operation that emitted the event. + enum EventOp { event_none = 0, event_deletion = 'D', event_exit = 'E', event_grow = 'G', event_restart = 'R' }; + BasicSolveEvent(const Solver& s, EventOp a_op, uint64 cLim, uint32 lLim) : SolveEvent(s, verbosity_max), cLimit(cLim), lLimit(lLim) { + op = a_op; + } + uint64 cLimit; //!< Next conflict limit + uint32 lLimit; //!< Next learnt limit +}; +/////////////////////////////////////////////////////////////////////////////// +// General solve +/////////////////////////////////////////////////////////////////////////////// +class Enumerator; +//! Interface for complex solve algorithms. +/*! + * \ingroup enumerator + * \relates Solver + * SolveAlgorithms implement complex algorithms like enumeration or optimization. + */ +class SolveAlgorithm { +public: + /*! + * \param limit An optional solve limit applied in solve(). + */ + explicit SolveAlgorithm(const SolveLimits& limit = SolveLimits()); + virtual ~SolveAlgorithm(); + + const Enumerator* enumerator() const { return enum_.get(); } + const SolveLimits& limits() const { return limits_; } + virtual bool interrupted()const = 0; + const Model& model() const; + + void setEnumerator(Enumerator& e); + void setEnumLimit(uint64 m) { enumLimit_= m; } + void setLimits(const SolveLimits& x) { limits_ = x; } + + //! Runs the solve algorithm. + /*! + * \param ctx A context object containing the problem. + * \param assume A list of initial unit-assumptions. + * \param onModel Optional handler to be called on each model. + * + * \return + * - true: if the search stopped before the search-space was exceeded. + * - false: if the search-space was completely examined. + * + * \note + * The use of assumptions allows for incremental solving. Literals contained + * in assumptions are assumed to be true during search but are undone before solve returns. + * + * \note + * Conceptually, solve() behaves as follows: + * \code + * start(ctx, assume); + * while (next()) { + * if (!report(model()) || enum_limit_reached()) { stop(); } + * } + * return more(); + * \endcode + * where report() notifies all registered model handlers. + */ + bool solve(SharedContext& ctx, const LitVec& assume = LitVec(), ModelHandler* onModel = 0); + + //! Prepares the solve algorithm for enumerating models. + /*! + * \pre The algorithm is not yet active. + */ + void start(SharedContext& ctx, const LitVec& assume = LitVec(), ModelHandler* onModel = 0); + //! Searches for the next model and returns whether such a model was found. + /*! + * \pre start() was called. + */ + bool next(); + //! Stops the algorithms. + void stop(); + //! Returns whether the last search completely exhausted the search-space. + bool more(); + + //! Resets solving state and sticky messages like terminate. + /*! + * \note The function must be called between successive calls to solve(). + */ + virtual void resetSolve() = 0; + + //! Prepares the algorithm for handling (asynchronous) calls to SolveAlgorithm::interrupt(). + virtual void enableInterrupts() = 0; + + //! Tries to terminate the current solve process. + /*! + * \note If enableInterrupts() was not called, SolveAlgorithm::interrupt() may return false + * to signal that (asynchronous) termination is not supported. + */ + bool interrupt(); +protected: + SolveAlgorithm(const SolveAlgorithm&); + SolveAlgorithm& operator=(const SolveAlgorithm&); + //! The actual solve algorithm. + virtual bool doSolve(SharedContext& ctx, const LitVec& assume) = 0; + //! Shall return true if termination is supported, otherwise false. + virtual bool doInterrupt() = 0; + + virtual void doStart(SharedContext& ctx, const LitVec& assume); + virtual int doNext(int last); + virtual void doStop(); + + bool reportModel(Solver& s) const; + bool reportUnsat(Solver& s) const; + Enumerator& enumerator() { return *enum_; } + SharedContext& ctx() const { return *ctx_; } + const LitVec& path() const { return *path_; } + uint64 maxModels() const { return enumLimit_; } + bool moreModels(const Solver& s) const; +private: + typedef SingleOwnerPtr EnumPtr; + typedef SingleOwnerPtr PathPtr; + bool attach(SharedContext& ctx, ModelHandler* onModel); + void detach(); + SolveLimits limits_; + SharedContext* ctx_; + EnumPtr enum_; + ModelHandler* onModel_; + PathPtr path_; + uint64 enumLimit_; + double time_; + int last_; +}; +//! A class that implements clasp's sequential solving algorithm. +class SequentialSolve : public SolveAlgorithm { +public: + explicit SequentialSolve(const SolveLimits& limit = SolveLimits()); + virtual bool interrupted() const; + virtual void resetSolve(); + virtual void enableInterrupts(); +protected: + virtual bool doSolve(SharedContext& ctx, const LitVec& assume); + virtual bool doInterrupt(); + virtual void doStart(SharedContext& ctx, const LitVec& assume); + virtual int doNext(int last); + virtual void doStop(); +private: + typedef SingleOwnerPtr SolvePtr; + SolvePtr solve_; + volatile int term_; +}; + +//! Options for controlling solving. +struct BasicSolveOptions { + SolveLimits limit; //!< Solve limit (disabled by default). + SolveAlgorithm* createSolveObject() const { return new SequentialSolve(limit); } + static uint32 supportedSolvers() { return 1; } + static uint32 recommendedSolvers() { return 1; } + uint32 numSolver() const { return 1; } + void setSolvers(uint32) {} + bool defaultPortfolio() const { return false; } +}; +//@} + +} +#endif diff --git a/libclasp/clasp/solver.h b/libclasp/clasp/solver.h new file mode 100644 index 0000000..94cba01 --- /dev/null +++ b/libclasp/clasp/solver.h @@ -0,0 +1,1072 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_SOLVER_H_INCLUDED +#define CLASP_SOLVER_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include + +namespace Clasp { + +/** + * \file + * \defgroup solver Solver + * \brief %Solver and related classes. + */ +//@{ + +//! clasp's Solver class. +/*! + * A Solver-object maintains the state and provides the functions + * necessary to implement our CDNL-algorithm. + * + * The interface supports incremental solving (search under assumptions) as well as + * solution enumeration. To make this possible the solver maintains two special + * decision levels: the root-level and the backtrack-level. + * + * The root-level is the lowest decision level to which a search + * can return. Conflicts on the root-level are non-resolvable and end a search - the + * root-level therefore acts as an artificial top-level during search. + * Incremental solving is then implemented by first adding a list of unit assumptions + * and second initializing the root-level to the current decision level. + * Once search terminates assumptions can be undone by calling clearAssumptions + * and a new a search can be started using different assumptions. + * + * For model enumeration the solver maintains a backtrack-level that restricts + * backjumping in order to prevent repeating already enumerated solutions. + * The solver will never backjump above that level and conflicts on the backtrack-level + * are resolved by backtracking, i.e. flipping the corresponding decision literal. + * + * \see "Conflict-Driven Answer Set Enumeration" for a detailed description of this approach. + * + */ +class Solver { +public: + typedef PodVector::type ConstraintDB; + typedef const ConstraintDB& DBRef; + typedef SingleOwnerPtr HeuristicPtr; +private: + friend class SharedContext; + // Creates an empty solver object with all strategies set to their default value. + Solver(SharedContext* ctx, uint32 id); + ~Solver(); + // Resets a solver object to the state it had after construction. + void reset(); + void resetConfig(); + void startInit(uint32 constraintGuess, const SolverParams& params); + void updateVars(); + bool cloneDB(const ConstraintDB& db); + bool preparePost(); + bool endInit(); + bool endStep(uint32 top, const SolverParams& params); +public: + typedef SolverStrategies::SearchStrategy SearchMode; + typedef SolverStrategies::UpdateMode UpdateMode; + typedef SolverStrategies::WatchInit WatchInitMode; + //! Returns a pointer to the shared context object of this solver. + const SharedContext* sharedContext() const { return shared_; } + //! Returns a pointer to the sat-preprocessor used by this solver. + SatPreprocessor* satPrepro() const; + //! Returns the solver's solve parameters. + const SolveParams& searchConfig() const; + SearchMode searchMode() const { return static_cast(strategy_.search); } + UpdateMode updateMode() const { return static_cast(strategy_.upMode); } + WatchInitMode watchInitMode() const { return static_cast(strategy_.initWatches); } + uint32 compressLimit() const { return strategy_.compress ? strategy_.compress : UINT32_MAX; } + bool restartOnModel()const { return strategy_.restartOnModel; } + DecisionHeuristic* heuristic() const { return heuristic_.get();} + uint32 id() const { return strategy_.id; } + VarInfo varInfo(Var v) const { return shared_->validVar(v) ? shared_->varInfo(v) : VarInfo(); } + const OutputTable& outputTable() const { return shared_->output; } + Literal tagLiteral() const { return tag_; } + bool isMaster() const { return this == sharedContext()->master(); } + /*! + * \name Setup functions + * Functions in this group are typically used before a search is started. + * @{ */ + //! Adds the problem constraint c to the solver. + /*! + * Problem constraints shall only be added to the master solver of + * a SharedContext object and only during the setup phase. + * \pre this == sharedContext()->master() && !sharedContext()->frozen(). + */ + void add(Constraint* c); + //! Adds a suitable representation of the given clause to the solver. + /*! + * Depending on the type and size of the given clause, the function + * either adds a (learnt) constraint to this solver or an implication + * to the shared implication graph. + * \note If c is a problem clause, the precondition of add(Constraint* c) applies. + */ + bool add(const ClauseRep& c, bool isNew = true); + //! Returns whether c can be stored in the shared short implication graph. + bool allowImplicit(const ClauseRep& c) const { + return c.isImp() + ? shared_->allowImplicit(c.info.type()) && !c.info.aux() && (c.prep == 1 || (!auxVar(c.lits[0].var()) && !auxVar(c.lits[1].var()) && (c.size == 2 || !auxVar(c.lits[2].var())))) + : c.size <= 1; + } + //! Returns the post propagator with the given priority or 0 if no such post propagator exists. + PostPropagator* getPost(uint32 prio) const; + //! Adds p as post propagator to this solver. + /*! + * \pre p was not added previously and is not part of any other solver. + * \note Post propagators are stored and called in priority order. + * \see PostPropagator::priority() + */ + bool addPost(PostPropagator* p); + //! Removes p from the solver's list of post propagators. + /*! + * \note The function shall not be called during propagation of any other post propagator. + */ + void removePost(PostPropagator* p); + + //! Adds path to the current root-path and adjusts the root-level accordingly. + bool pushRoot(const LitVec& path); + bool pushRoot(Literal p); + void setEnumerationConstraint(Constraint* c); + //! Requests a special aux variable for tagging conditional knowledge. + /*! + * Once a tag variable t is set, learnt clauses containing ~t are + * tagged as "conditional". Conditional clauses are removed once t becomes + * unassigned or Solver::removeConditional() is called. Furthermore, calling + * Solver::strengthenConditional() removes ~t from conditional clauses and + * transforms them to unconditional knowledge. + * + * \note Typically, the tag variable is a root assumption and hence true during + * the whole search. + */ + Var pushTagVar(bool pushToRoot); + //@} + + /*! + * \name CDNL functions + * Top level functions that are important to the CDNL algorithm. + * @{ */ + + //! Searches for a model as long as the given limit is not reached. + /*! + * The function searches for a model as long as none of the limits given by limit + * is reached. The limits are updated during search. + * + * \param limit Imposed limit on conflicts and number of learnt constraints. + * \param randf Pick next decision variable randomly with a probability of randf. + * \return + * - value_true: if a model was found. + * - value_false: if the problem is unsatisfiable (under assumptions, if any). + * - value_free: if search was stopped because limit was reached. + * . + * + * \note search treats the root level as top-level, i.e. it will never backtrack below that level. + */ + ValueRep search(SearchLimits& limit, double randf = 0.0); + ValueRep search(uint64 maxC, uint32 maxL, bool local = false, double rp = 0.0); + + //! Moves the root-level i levels down (i.e. away from the top-level). + /*! + * The root-level is similar to the top-level in that it cannot be + * undone during search, i.e. the solver will not resolve conflicts that are on or + * above the root-level. + */ + void pushRootLevel(uint32 i = 1) { + levels_.root = std::min(decisionLevel(), levels_.root+i); + levels_.flip = std::max(levels_.flip, levels_.root); + } + + //! Moves the root-level i levels up (i.e. towards the top-level). + /*! + * The function removes all levels between the new root level and the current decision level, + * resets the current backtrack-level, and re-assigns any implied literals. + * \param i Number of root decisions to pop. + * \param[out] popped Optional storage for popped root decisions. + * \param aux Whether or not aux variables should be added to popped. + * \post decisionLevel() == rootLevel() + * \note The function first calls clearStopConflict() to remove any stop conflicts. + * \note The function *does not* propagate any asserted literals. It is + * the caller's responsibility to call propagate() after the function returned. + */ + bool popRootLevel(uint32 i = 1, LitVec* popped = 0, bool aux = true); + + //! Removes a previously set stop conflict and restores the root level. + void clearStopConflict(); + + //! Returns the current root level. + uint32 rootLevel() const { return levels_.root; } + + //! Removes any implications made between the top-level and the root-level. + /*! + * The function also resets the current backtrack-level and re-assigns learnt facts. + * \note + * Equivalent to popRootLevel(rootLevel()) followed by simplify(). + */ + bool clearAssumptions(); + + //! Adds c as a learnt constraint to the solver. + void addLearnt(Constraint* c, uint32 size, ConstraintType type) { + learnts_.push_back(c); + stats.addLearnt(size, type); + } + void addLearnt(Constraint* c, uint32 size) { addLearnt(c, size, c->type()); } + //! Tries to receive at most maxOut clauses. + /*! + * The function queries the distributor object for new clauses to be delivered to + * this solver. Clauses are stored in out. + * \return The number of clauses received. + */ + uint32 receive(SharedLiterals** out, uint32 maxOut) const; + //! Distributes the clause in lits via the distributor. + /*! + * The function first calls the distribution strategy + * to decides whether the clause is a valid candidate for distribution. + * If so and a distributor was set, it distributes the clause and returns a handle to the + * now shared literals of the clause. Otherwise, it returns 0. + * + * \param lits The literals of the clause. + * \param size The number of literals in the clause. + * \param extra Additional information about the clause. + * \note + * If the return value is not null, it is the caller's + * responsibility to release the returned handle (i.e. by calling release()). + * \note If the clause contains aux vars, it is not distributed. + */ + SharedLiterals* distribute(const Literal* lits, uint32 size, const ConstraintInfo& extra); + + + //! Returns to the maximum of rootLevel() and backtrackLevel() and increases the number of restarts. + void restart() { + undoUntil(0); + ++stats.restarts; + ccInfo_.score().bumpActivity(); + } + enum UndoMode { undo_default = 0u, undo_pop_bt_level = 1u, undo_pop_proj_level = 2u, undo_save_phases = 4u }; + //! Sets the backtracking level to dl. + /*! + * Depending on mode, the backtracking level either applies + * to normal or projective solution enumeration. + * \see "Solution Enumeration for Projected Boolean Search Problems". + */ + void setBacktrackLevel(uint32 dl, UndoMode mode = undo_pop_bt_level) { + if (uint32(mode) >= levels_.mode) { + levels_.flip = std::max(std::min(dl, decisionLevel()), rootLevel()); + levels_.mode = std::max(uint32(mode & 3u), uint32(undo_pop_bt_level)); + } + } + //! Returns the current backtracking level. + uint32 backtrackLevel() const { return levels_.flip; } + //! Returns the backjump level during an undo operation. + uint32 jumpLevel() const { return decisionLevel() - levels_.jump; } + + //! Returns whether the solver can split-off work. + bool splittable() const; + + //! Tries to split-off disjoint work from the solver's currrent guiding path and returns it in out. + /*! + * \return splittable() + */ + bool split(LitVec& out); + + //! Copies the solver's currrent guiding path to gp. + /*! + * \note The solver's guiding path consists of: + * - the decisions from levels [1, rootLevel()] + * - any literals that are implied on a level <= rootLevel() because of newly learnt + * information. This particularly includes literals that were flipped during model enumeration. + * + * \param[out] out Where to store the guiding path. + */ + void copyGuidingPath(LitVec& out); + + //! If called on top-level, removes SAT-clauses + Constraints for which Constraint::simplify returned true. + /*! + * \note If this method is called on a decision-level > 0, it is a noop and will + * simply return true. + * \return false, if a top-level conflict is detected. Otherwise, true. + */ + bool simplify(); + //! Shuffle constraints upon next simplification. + void shuffleOnNextSimplify(){ shufSimp_ = 1; } + + + //! Removes all conditional knowledge, i.e. all previously tagged learnt clauses. + /*! + * \see Solver::pushTagVar() + */ + void removeConditional(); + + //! Resolves all tagged clauses with the tag literal and thereby strengthens the learnt db. + /*! + * \see Solver::pushTagVar() + */ + void strengthenConditional(); + + //! Sets the literal p to true and schedules p for propagation. + /*! + * Setting a literal p to true means assigning the appropriate value to + * p's variable. That is: value_false if p is a negative literal and value_true + * if p is a positive literal. + * \param p The literal that should become true. + * \param a The reason for the literal to become true or 0 if no reason exists. + * + * \return + * - false if p is already false + * - otherwise true. + * + * \pre hasConflict() == false + * \pre a.isNull() == false || decisionLevel() <= rootLevel() || searchMode() == no_learning + * \post + * p.var() == trueValue(p) || p.var() == falseValue(p) && hasConflict() == true + * + * \note if setting p to true leads to a conflict, the nogood that caused the + * conflict can be requested using the conflict() function. + */ + bool force(const Literal& p, const Antecedent& a) { + assert(!hasConflict() || isTrue(p)); + if (assign_.assign(p, decisionLevel(), a)) return true; + setConflict(p, a, UINT32_MAX); + return false; + } + /*! + * \overload bool Solver::force(const Literal&, const Antecedent&) + */ + bool force(const Literal& p, const Antecedent& a, uint32 data) { + return data != UINT32_MAX + ? assign_.assign(p, decisionLevel(), a.constraint(), data) || (setConflict(p, a, data), false) + : force(p, a); + } + + //! Assigns p at dl because of r. + /*! + * \pre dl <= decisionLevel() + * \note + * If dl < ul = max(rootLevel(), backtrackLevel()), p is actually assigned + * at ul but the solver stores enough information to reassign + * p on backtracking. + */ + bool force(Literal p, uint32 dl, const Antecedent& r, uint32 d = UINT32_MAX) { + return dl == decisionLevel() ? force(p, r, d) : force(ImpliedLiteral(p, dl, r, d)); + } + //! Assigns p as a fact at decision level 0. + bool force(Literal p) { return force(p, 0, Antecedent(lit_true())); } + + //! Assumes the literal p if possible. + /*! + * If p is currently unassigned, sets p to true and starts a new decision level. + * \pre validVar(p.var()) == true + * \param p The literal to assume. + * \return !isFalse(p) + */ + bool assume(const Literal& p); + + //! Selects and assumes the next branching literal by calling the installed decision heuristic. + /*! + * \pre queueSize() == 0 + * \note The next decision literal will be selected randomly with probability f. + * \return + * - true if the assignment is not total and a literal was assumed (or forced). + * - false otherwise + * . + * \see DecisionHeuristic + */ + bool decideNextBranch(double f = 0.0); + + //! Sets a conflict that forces the solver to terminate its search. + /*! + * \pre !hasConflict() + * \post hasConflict() + * + * \note + * To prevent the solver from resolving the stop conflict, the + * function sets the root level to the current decision level. + * Call clearStopConflict() to remove the conflict and to restore + * the previous root-level. + */ + void setStopConflict(); + + /*! + * Propagates all enqueued literals. If a conflict arises during propagation + * propagate returns false and the current conflict (as a set of literals) + * is stored in the solver's conflict variable. + * \pre !hasConflict() + * \see Solver::force + * \see Solver::assume + * \note Shall not be called recursively. + */ + bool propagate(); + + /*! + * Does unit propagation and calls x->propagateFixpoint(*this) + * for all post propagators x up to but not including p. + * \note The function is meant to be called only in the context of p. + * \pre p is a post propagator of this solver, i.e. was previously added via addPost(). + * \pre Post propagators are active, i.e. the solver is fully initialized. + */ + bool propagateUntil(PostPropagator* p); + + //! Executes a one-step lookahead on p. + /*! + * Assumes p and propagates this assumption. If propagations leads to + * a conflict, false is returned. Otherwise the assumption is undone and + * the function returns true. + * \param p The literal to test. + * \param c The constraint that wants to test p (can be 0). + * \pre p is free + * \note If c is not null and testing p does not lead to a conflict, + * c->undoLevel() is called *before* p is undone. Hence, the + * range [s.levelStart(s.decisionLevel()), s.assignment().size()) + * contains p followed by all literals that were forced because of p. + * \note propagateUntil(c) is used to propagate p. + */ + bool test(Literal p, PostPropagator* c); + + //! Estimates the number of assignments following from setting p to true. + /*! + * \note For the estimate only binary clauses are considered. + */ + uint32 estimateBCP(const Literal& p, int maxRecursionDepth = 5) const; + + //! Computes the number of in-edges for each assigned literal. + /*! + * \pre !hasConflict() + * \note For a literal p assigned on level level(p), only in-edges from + * levels < level(p) are counted. + * \return The maximum number of in-edges. + */ + uint32 inDegree(WeightLitVec& out); + + struct DBInfo { uint32 size; uint32 locked; uint32 pinned; }; + //! Removes upto remMax percent of the learnt nogoods. + /*! + * \param remMax Fraction of nogoods to remove ([0.0,1.0]). + * \param rs Strategy to apply during nogood deletion. + * \return The number of locked and active/glue clauses currently exempt from deletion. + * \note + * Nogoods that are the reason for a literal to be in the assignment + * are said to be locked and won't be removed. + */ + DBInfo reduceLearnts(float remMax, const ReduceStrategy& rs = ReduceStrategy()); + + //! Resolves the active conflict using the selected strategy. + /*! + * If searchMode() is set to learning, resolveConflict implements + * First-UIP learning and backjumping. Otherwise, it simply applies + * chronological backtracking. + * \pre hasConflict() + * \return + * - true if the conflict was successfully resolved + * - false otherwise + * \note + * If decisionLevel() == rootLevel() false is returned. + */ + bool resolveConflict(); + + //! Backtracks the last decision and updates the backtrack-level if necessary. + /*! + * \return + * - true if backtracking was possible + * - false if decisionLevel() == rootLevel() + */ + bool backtrack(); + + //! Undoes all assignments up to (but not including) decision level dl. + /*! + * \post decision level == max(min(decisionLevel(), dl), max(rootLevel(), backtrackLevel())) + * \return The decision level after undoing assignments. + * \note + * undoUntil() stops at the current backtrack level unless undoMode includes the mode + * that was used when setting the backtrack level. + * \note + * If undoMode contains undo_save_phases, the functions saves the values of variables that are undone. + * Otherwise, phases are only saved if indicated by the active strategy. + */ + uint32 undoUntil(uint32 dl, uint32 undoMode); + //! Behaves like undoUntil(dl, undo_default). + uint32 undoUntil(uint32 dl) { return undoUntilImpl(dl, false); } + //! Returns whether undoUntil(decisionLevel()-1) is valid and would remove decisionLevel(). + bool isUndoLevel() const; + + //! Adds a new auxiliary variable to this solver. + /*! + * Auxiliary variables are local to one solver and are not considered + * as part of the problem. They shall be added/used only during solving, i.e. + * after problem setup is completed. + */ + Var pushAuxVar(); + //! Pops the num most recently added auxiliary variables and destroys all constraints in auxCons. + void popAuxVar(uint32 num = UINT32_MAX, ConstraintDB* auxCons = 0); + //@} + + /*! + * \name State inspection + * Functions for inspecting the state of the solver & search. + * \note validVar(v) is a precondition for all functions that take a variable as + * parameter. + * @{ */ + //! Returns the number of problem variables. + uint32 numProblemVars() const { return shared_->numVars(); } + //! Returns the number of active solver-local aux variables. + uint32 numAuxVars() const { return numVars() - numProblemVars(); } + //! Returns the number of solver variables, i.e. numProblemVars() + numAuxVars() + uint32 numVars() const { return assign_.numVars() - 1; } + //! Returns true if var represents a valid variable in this solver. + bool validVar(Var var) const { return var <= numVars(); } + //! Returns true if var is a solver-local aux var. + bool auxVar(Var var) const { return shared_->numVars() < var; } + //! Returns the number of assigned variables. + uint32 numAssignedVars() const { return assign_.assigned(); } + //! Returns the number of free variables. + /*! + * The number of free variables is the number of vars that are neither + * assigned nor eliminated. + */ + uint32 numFreeVars() const { return assign_.free()-1; } + //! Returns the value of v w.r.t the current assignment. + ValueRep value(Var v) const { assert(validVar(v)); return assign_.value(v); } + //! Returns the value of v w.r.t the top level. + ValueRep topValue(Var v) const { return level(v) == 0 ? value(v) : value_free; } + //! Returns the set of preferred values of v. + ValueSet pref(Var v) const { assert(validVar(v)); return assign_.pref(v);} + //! Returns true if p is true w.r.t the current assignment. + bool isTrue(Literal p) const { assert(validVar(p.var())); return assign_.value(p.var()) == trueValue(p); } + //! Returns true if p is false w.r.t the current assignment. + bool isFalse(Literal p) const { assert(validVar(p.var())); return assign_.value(p.var()) == falseValue(p); } + //! Returns the literal of v being true in the current assignment. + /*! + * \pre v is assigned a value in the current assignment + */ + Literal trueLit(Var v) const { assert(value(v) != value_free); return Literal(v, valSign(value(v))); } + Literal defaultLit(Var v) const; + //! Returns the decision level on which v was assigned. + /*! + * \note The returned value is only meaningful if value(v) != value_free. + */ + uint32 level(Var v) const { assert(validVar(v)); return assign_.level(v); } + //! Returns true if v is currently marked as seen. + /*! + * Note: variables assigned on level 0 are always marked. + */ + bool seen(Var v) const { assert(validVar(v)); return assign_.seen(v, 3u); } + //! Returns true if the literal p is currently marked as seen. + bool seen(Literal p) const { assert(validVar(p.var())); return assign_.seen(p.var(), uint8(1+p.sign())); } + //! Returns the current decision level. + uint32 decisionLevel() const { return (uint32)levels_.size(); } + bool validLevel(uint32 dl) const { return dl != 0 && dl <= decisionLevel(); } + //! Returns the starting position of decision level dl in the trail. + /*! + * \pre validLevel(dl) + */ + uint32 levelStart(uint32 dl) const { assert(validLevel(dl)); return levels_[dl-1].trailPos; } + //! Returns the decision literal of the decision level dl. + /*! + * \pre validLevel(dl) + */ + Literal decision(uint32 dl) const { assert(validLevel(dl)); return assign_.trail[ levels_[dl-1].trailPos ]; } + //! Returns true, if the current assignment is conflicting. + bool hasConflict() const { return !conflict_.empty(); } + bool hasStopConflict() const { return hasConflict() && conflict_[0] == lit_false(); } + //! Returns the number of (unprocessed) literals in the propagation queue. + uint32 queueSize() const { return (uint32) assign_.qSize(); } + //! Number of problem constraints in this solver. + uint32 numConstraints() const; + //! Returns the number of constraints that are currently in the solver's learnt database. + uint32 numLearntConstraints() const { return (uint32)learnts_.size(); } + //! Returns the reason for p being true. + /*! + * \pre p is true w.r.t the current assignment + */ + const Antecedent& reason(Literal p) const { assert(isTrue(p)); return assign_.reason(p.var()); } + //! Returns the additional reason data associated with p. + uint32 reasonData(Literal p) const { return assign_.data(p.var()); } + //! Returns the current (partial) assignment as a set of true literals. + /*! + * \note Although the special var 0 always has a value it is not considered to be + * part of the assignment. + */ + const LitVec& trail() const { return assign_.trail; } + const Assignment& assignment() const { return assign_; } + //! Returns the current conflict as a set of literals. + const LitVec& conflict() const { return conflict_; } + //! Returns the most recently derived conflict clause. + const LitVec& conflictClause() const { return cc_; } + //! Returns the set of eliminated literals that are unconstraint w.r.t the last model. + const LitVec& symmetric() const { return temp_; } + //! Returns the enumeration constraint set by the enumerator used. + Constraint* enumerationConstraint() const { return enum_; } + DBRef constraints() const { return constraints_; } + //! Returns the idx'th learnt constraint. + /*! + * \pre idx < numLearntConstraints() + */ + Constraint& getLearnt(uint32 idx) const { + assert(idx < numLearntConstraints()); + return *learnts_[ idx ]; + } + + mutable RNG rng; //!< Random number generator for this object. + ValueVec model; //!< Stores the last model (if any). + LowerBound lower; //!< Stores the last lower bound found (if any). + SolverStats stats; //!< Stores statistics about the solving process. + //@} + + /*! + * \name Watch management + * Functions for setting/removing watches. + * \pre validVar(v) + * @{ */ + //! Returns the number of constraints watching the literal p. + uint32 numWatches(Literal p) const; + //! Returns true if the constraint c watches the literal p. + bool hasWatch(Literal p, Constraint* c) const; + bool hasWatch(Literal p, ClauseHead* c) const; + //! Returns c's watch-structure associated with p. + /*! + * \note returns 0, if hasWatch(p, c) == false + */ + GenericWatch* getWatch(Literal p, Constraint* c) const; + //! Adds c to the watch-list of p. + /*! + * When p becomes true, c->propagate(p, data, *this) is called. + * \post hasWatch(p, c) == true + */ + void addWatch(Literal p, Constraint* c, uint32 data = 0) { + assert(validWatch(p)); + watches_[p.id()].push_right(GenericWatch(c, data)); + } + //! Adds w to the clause watch-list of p. + void addWatch(Literal p, const ClauseWatch& w) { + assert(validWatch(p)); + watches_[p.id()].push_left(w); + } + //! Removes c from p's watch-list. + /*! + * \post hasWatch(p, c) == false + */ + void removeWatch(const Literal& p, Constraint* c); + void removeWatch(const Literal& p, ClauseHead* c); + //! Adds c to the watch-list of decision-level dl. + /*! + * Constraints in the watch-list of a decision level are + * notified when that decision level is about to be backtracked. + * \pre validLevel(dl) + */ + void addUndoWatch(uint32 dl, Constraint* c) { + assert(validLevel(dl)); + if (levels_[dl-1].undo != 0) { + levels_[dl-1].undo->push_back(c); + } + else { + levels_[dl-1].undo = allocUndo(c); + } + } + //! Removes c from the watch-list of the decision level dl. + bool removeUndoWatch(uint32 dl, Constraint* c); + //@} + + /*! + * \name Misc functions + * Low-level implementation functions. Use with care and only if you + * know what you are doing! + * @{ */ + bool addPost(PostPropagator* p, bool init); + //! Updates the reason for p being true. + /*! + * \pre p is true and x is a valid reason for p + */ + bool setReason(Literal p, const Antecedent& x, uint32 data = UINT32_MAX) { + assert(isTrue(p) || shared_->eliminated(p.var())); + assign_.setReason(p.var(), x); + if (data != UINT32_MAX) { assign_.setData(p.var(), data); } + return true; + } + void setPref(Var v, ValueSet::Value which, ValueRep to) { + assert(validVar(v) && to <= value_false); + assign_.requestPrefs(); + assign_.setPref(v, which, to); + } + void resetPrefs() { assign_.resetPrefs(); } + void resetLearntActivities(); + //! Returns the reason for p being true as a set of literals. + void reason(Literal p, LitVec& out) { assert(isTrue(p)); out.clear(); return assign_.reason(p.var()).reason(*this, p, out); } + + //! Helper function for updating antecedent scores during conflict resolution. + /*! + * \param sc The current score of the active antecedent. + * \param p The literal implied by the active antecedent. + * \param lits The literals of the active antecedent. + * \return true if a score was updated. + * + * \note Depending on the active solver strategies, the function + * increases the activity and/or updates the lbd of the given antecedent. + * + * \note If SolverStrategies::bumpVarAct is active, p's activity + * is increased if the new lbd is smaller than the lbd of the + * conflict clause that is currently being derived. + */ + bool updateOnReason(ConstraintScore& sc, Literal p, const LitVec& lits) { + // update only during conflict resolution + if (&lits != &conflict_) { return false; } + sc.bumpActivity(); + uint32 up = strategy_.updateLbd; + if ((up || !sc.hasLbd()) && !lits.empty()) { + uint32 lbd = sc.lbd(); + uint32 inc = uint32(up != 1u); + uint32 nLbd = countLevels(&lits[0], &lits[0] + lits.size(), lbd - inc); + if ((nLbd + inc) < lbd) { + sc.bumpLbd(nLbd + uint32(up == 2u)); + } + } + if (strategy_.bumpVarAct && isTrue(p)) { bumpAct_.push_back(WeightLiteral(p, sc.lbd())); } + return true; + } + + //! Helper function for increasing antecedent activities during conflict clause minimization. + bool updateOnMinimize(ConstraintScore& sc) { + return !strategy_.ccMinKeepAct && (sc.bumpActivity(), true); + } + + //! Helper function for antecedents to be called during conflict clause minimization. + bool ccMinimize(Literal p, CCMinRecursive* rec) const { + return seen(p.var()) || (rec && hasLevel(level(p.var())) && ccMinRecurse(*rec, p)); + } + + //! Allocates a small block (32-bytes) from the solver's small block pool. + void* allocSmall() { return smallAlloc_.allocate(); } + //! Frees a small block previously allocated from the solver's small block pool. + void freeSmall(void* m) { smallAlloc_.free(m); } + + void addLearntBytes(uint32 bytes) { memUse_ += bytes; } + void freeLearntBytes(uint64 bytes) { memUse_ -= (bytes < memUse_) ? bytes : memUse_; } + + bool restartReached(const SearchLimits& limit) const; + bool reduceReached(const SearchLimits& limit) const; + + //! simplifies cc and returns finalizeConflictClause(cc, info); + uint32 simplifyConflictClause(LitVec& cc, ConstraintInfo& info, ClauseHead* rhs); + uint32 finalizeConflictClause(LitVec& cc, ConstraintInfo& info, uint32 ccRepMode = 0); + uint32 countLevels(const Literal* first, const Literal* last, uint32 maxLevels = Clasp::LBD_MAX); + bool hasLevel(uint32 dl) const { assert(validLevel(dl)); return levels_[dl-1].marked != 0; } + bool frozenLevel(uint32 dl) const { assert(validLevel(dl)); return levels_[dl-1].freeze != 0; } + bool inputVar(Literal p) const { return varInfo(p.var()).input(); } + void markLevel(uint32 dl) { assert(validLevel(dl)); levels_[dl-1].marked = 1; } + void freezeLevel(uint32 dl) { assert(validLevel(dl)); levels_[dl-1].freeze = 1; } + void unmarkLevel(uint32 dl) { assert(validLevel(dl)); levels_[dl-1].marked = 0; } + void unfreezeLevel(uint32 dl){ assert(validLevel(dl)); levels_[dl-1].freeze = 0; } + void markSeen(Var v) { assert(validVar(v)); assign_.setSeen(v, 3u); } + void markSeen(Literal p) { assert(validVar(p.var())); assign_.setSeen(p.var(), uint8(1+p.sign())); } + void clearSeen(Var v) { assert(validVar(v)); assign_.clearSeen(v); } + void setHeuristic(DecisionHeuristic* h, Ownership_t::Type own); + void destroyDB(ConstraintDB& db); + SolverStrategies& strategies() { return strategy_; } + bool resolveToFlagged(const LitVec& conflictClause, uint8 vflag, LitVec& out, uint32& lbd) const; + void resolveToCore(LitVec& out); + //@} +private: + struct DLevel { + explicit DLevel(uint32 pos = 0, ConstraintDB* u = 0) + : trailPos(pos) + , marked(0) + , freeze(0) + , undo(u) {} + uint32 trailPos : 30; + uint32 marked : 1; + uint32 freeze : 1; + ConstraintDB* undo; + }; + struct DecisionLevels : public PodVector::type { + DecisionLevels() : root(0), flip(0), mode(0), jump(0) {} + uint32 root; // root level + uint32 flip : 30; // backtrack level + uint32 mode : 2; // type of backtrack level + uint32 jump; // length of active undo + }; + typedef PodVector::type ReasonVec; + typedef PodVector::type Watches; + struct Dirty; + struct CmpScore { + typedef std::pair ViewPair; + CmpScore(const ConstraintDB& learnts, ReduceStrategy::Score sc, uint32 g, uint32 f = 0) : db(learnts), rs(sc), glue(g), freeze(f) {} + uint32 score(const ConstraintScore& act) const { return ReduceStrategy::asScore(rs, act); } + bool operator()(uint32 lhsId, uint32 rhsId) const { return (*this)(db[lhsId], db[rhsId]); } + bool operator()(const ViewPair& lhs, const ViewPair& rhs) const { return this->operator()(lhs.second, rhs.second); } + bool operator()(ConstraintScore lhs, ConstraintScore rhs) const { return ReduceStrategy::compare(rs, lhs, rhs) < 0;} + bool operator()(const Constraint* lhs, const Constraint* rhs) const { return this->operator()(lhs->activity(), rhs->activity()); } + bool isFrozen(const ConstraintScore& a) const { return a.bumped() && a.lbd() <= freeze; } + bool isGlue(const ConstraintScore& a) const { return a.lbd() <= glue; } + const ConstraintDB& db; + ReduceStrategy::Score rs; + uint32 glue; + uint32 freeze; + private: CmpScore& operator=(const CmpScore&); + }; + bool validWatch(Literal p) const { return p.id() < (uint32)watches_.size(); } + void freeMem(); + void resetHeuristic(); + bool simplifySAT(); + bool unitPropagate(); + bool postPropagate(PostPropagator* stop); + void cancelPropagation(); + uint32 undoUntilImpl(uint32 dl, bool sp); + void undoLevel(bool sp); + uint32 analyzeConflict(); + bool isModel(); + bool resolveToFlagged(const LitVec& conflictClause, uint8 vf, LitVec& out, uint32& lbd); + void otfs(Antecedent& lhs, const Antecedent& rhs, Literal p, bool final); + ClauseHead* otfsRemove(ClauseHead* c, const LitVec* newC); + uint32 ccMinimize(LitVec& cc, LitVec& removed, uint32 antes, CCMinRecursive* ccMin); + void ccMinRecurseInit(CCMinRecursive& ccMin); + bool ccMinRecurse(CCMinRecursive& ccMin, Literal p) const; + bool ccRemovable(Literal p, uint32 antes, CCMinRecursive* ccMin); + Antecedent ccHasReverseArc(Literal p, uint32 maxLevel, uint32 maxNew); + void ccResolve(LitVec& cc, uint32 pos, const LitVec& reason); + void undoFree(ConstraintDB* x); + void setConflict(Literal p, const Antecedent& a, uint32 data); + bool force(const ImpliedLiteral& p); + void updateBranch(uint32 n); + uint32 incEpoch(uint32 size, uint32 inc = 1); + DBInfo reduceLinear(uint32 maxR, const CmpScore& cmp); + DBInfo reduceSort(uint32 maxR, const CmpScore& cmp); + DBInfo reduceSortInPlace(uint32 maxR, const CmpScore& cmp, bool onlyPartialSort); + Literal popVars(uint32 num, bool popLearnt, ConstraintDB* popAux); + ConstraintDB* allocUndo(Constraint* c); + SharedContext* shared_; // initialized by master thread - otherwise read-only! + SolverStrategies strategy_; // strategies used by this object + HeuristicPtr heuristic_; // active decision heuristic + CCMinRecursive* ccMin_; // additional data for supporting recursive strengthen + PostPropagator** postHead_; // head of post propagator list to propagate + ConstraintDB* undoHead_; // free list of undo DBs + Constraint* enum_; // enumeration constraint - set by enumerator + uint64 memUse_; // memory used by learnt constraints (estimate) + Dirty* lazyRem_; // set of watch lists that contain invalid constraints + SmallClauseAlloc smallAlloc_; // allocator object for small clauses + Assignment assign_; // three-valued assignment. + DecisionLevels levels_; // information (e.g. position in trail) on each decision level + ConstraintDB constraints_; // problem constraints + ConstraintDB learnts_; // learnt constraints + PropagatorList post_; // (possibly empty) list of post propagators + Watches watches_; // for each literal p: list of constraints watching p + LitVec conflict_; // conflict-literals for later analysis + LitVec cc_; // temporary: conflict clause within analyzeConflict + LitVec temp_; // temporary: redundant literals in simplifyConflictClause + WeightLitVec bumpAct_; // temporary: lits from current dl whose activity might get an extra bump + VarVec epoch_; // temporary vector for computing LBD + VarVec cflStamp_; // temporary vector for computing number of conflicts in branch + ImpliedList impliedLits_; // lits that were asserted on current dl but are logically implied earlier + ConstraintInfo ccInfo_; // temporary: information about conflict clause cc_ + Literal tag_; // aux literal for tagging learnt constraints + uint32 dbIdx_; // position of first new problem constraint in master db + uint32 lastSimp_ :30;// number of top-level assignments on last call to simplify + uint32 shufSimp_ : 1;// shuffle db on next simplify? + uint32 initPost_ : 1;// initialize new post propagators? +}; +inline bool isRevLit(const Solver& s, Literal p, uint32 maxL) { + return s.isFalse(p) && (s.seen(p) || s.level(p.var()) < maxL); +} +//! Simplifies the constraints in db and removes those that are satisfied. +template +void simplifyDB(Solver& s, C& db, bool shuffle) { + typename C::size_type j = 0; + for (typename C::size_type i = j, end = db.size(); i != end; ++i) { + Constraint* c = db[i]; + if (c->simplify(s, shuffle)){ c->destroy(&s, false); } + else { db[j++] = c; } + } + shrinkVecTo(db, j); +} +//! Destroys (and optionally detaches) all constraints in db. +void destroyDB(Solver::ConstraintDB& db, Solver* s, bool detach); +//! Returns the default decision literal of the given variable. +inline Literal Solver::defaultLit(Var v) const { + switch(strategy_.signDef) { + default: // + case SolverStrategies::sign_atom: return Literal(v, !varInfo(v).has(VarInfo::Body)); + case SolverStrategies::sign_pos : return posLit(v); + case SolverStrategies::sign_neg : return negLit(v); + case SolverStrategies::sign_rnd : return Literal(v, rng.drand() < 0.5); + } +} +//! Event type optionally emitted after a conflict. +struct NewConflictEvent : SolveEvent { + NewConflictEvent(const Solver& s, const LitVec& c, const ConstraintInfo& i) : SolveEvent(s, verbosity_quiet), learnt(&c), info(i) {} + const LitVec* learnt; //!< Learnt conflict clause. + ConstraintInfo info; //!< Additional information associated with the conflict clause. +}; +//@} + +/** + * \defgroup heuristic Decision Heuristics + * \brief Decision heuristics and related classes. + * \ingroup solver + */ +//@{ +//! Base class for decision heuristics to be used in a Solver. +/*! + * During search the decision heuristic is used whenever the DPLL-procedure must pick + * a new variable to branch on. Each concrete decision heuristic can implement a + * different algorithm for selecting the next decision variable. + */ +class DecisionHeuristic { +public: + DecisionHeuristic() {} + virtual ~DecisionHeuristic(); + /*! + * Called once after all problem variables are known to the solver. + * The default-implementation is a noop. + * \param s The solver in which this heuristic is used. + */ + virtual void startInit(const Solver& s) { (void)s; } + + /*! + * Called once after all problem constraints are known to the solver + * and the problem was simplified. + * The default-implementation is a noop. + * \param s The solver in which this heuristic is used. + */ + virtual void endInit(Solver& s) { (void)s; } + + //! Called once if s switches to a different heuristic. + virtual void detach(Solver& s) { (void)s; } + + //! Called if configuration has changed. + virtual void setConfig(const HeuParams& p) { (void)p; } + + /*! + * Called if the state of one or more variables changed. + * A state change is one of: + * - A previously eliminated variable is resurrected. + * - A new aux variable was added. + * - An aux variable was removed. + * . + * \param s Solver in which the state change occurred. + * \param v The first variable affected by the change. + * \param n The range of variables affected, i.e. [v, v+n). + * \note Use s.validVar(v) and s.auxVar(v) to determine the reason for the update. + */ + virtual void updateVar(const Solver& s, Var v, uint32 n) = 0; + + /*! + * Called on decision level 0. Variables that are assigned on this level + * may be removed from any decision heuristic. + * \note Whenever the solver returns to dl 0, simplify is only called again + * if the solver learnt new facts since the last call to simplify. + * + * \param s The solver that reached decision level 0. + * \param st The position in the trail of the first new learnt fact. + */ + virtual void simplify(const Solver& s, LitVec::size_type st) { (void)s; (void)st; } + + /*! + * Called whenever the solver backracks. + * Literals in the range [s.trail()[st], s.trail().size()) are subject to backtracking. + * The default-implementation is a noop. + * \param s The solver that is about to backtrack. + * \param st Position in the trail of the first literal that will be backtracked. + */ + virtual void undoUntil(const Solver& s, LitVec::size_type st) { (void)s; (void)st; } + + /*! + * Called whenever a new constraint is added to the solver s. + * The default-implementation is a noop. + * \param s The solver to which the constraint is added. + * \param first First literal of the new constraint. + * \param size Size of the new constraint. + * \param t Type of the new constraint. + * \note first points to an array of size size. + */ + virtual void newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t) { (void)s; (void)first; (void)size; (void)t; } + + /*! + * Called for each new reason-set that is traversed during conflict analysis. + * The default-implementation is a noop. + * \param s The solver in which the conflict is analyzed. + * \param lits The current reason-set under inspection. + * \param resolveLit The literal that is currently resolved. + * \note When a conflict is detected, the solver passes the conflicting literals + * in lits during the first call to updateReason. On that first call resolveLit + * is the sentinel-literal. + */ + virtual void updateReason(const Solver& s, const LitVec& lits, Literal resolveLit) { (void)s; (void)lits; (void)resolveLit; } + + //! Shall bump the activity of literals in lits by lits.second * adj. + /*! + * The default-implementation is a noop and always returns false. + * \return true if heuristic supports activities, false otherwise. + */ + virtual bool bump(const Solver& s, const WeightLitVec& lits, double adj) { (void)s; (void)lits; (void)adj; return false; } + + /*! + * Called whenever the solver must pick a new variable to branch on. + * \param s The solver that needs a new decision variable. + * \return + * - true : if the decision heuristic assumed a literal + * - false : if no decision could be made because assignment is total or there is a conflict + * . + * \post + * If true is returned, the heuristic has asserted a literal. + */ + bool select(Solver& s) { return s.numFreeVars() != 0 && s.assume(doSelect(s)); } + + //! Implements the actual selection process. + /*! + * \pre s.numFreeVars() > 0, i.e. there is at least one variable to branch on. + * \return + * - a literal that is currently free or + * - a sentinel literal. In that case, the heuristic shall have asserted a literal! + */ + virtual Literal doSelect(Solver& s) = 0; + + /*! + * Shall select one of the literals in the range [first, last). + * \param s The solver that needs a new decision variable. + * \param first Pointer to first literal in range. + * \param last Pointer to the end of the range. + * \pre [first, last) is not empty and all literals in the range are currently unassigned. + * \note The default implementation returns *first. + */ + virtual Literal selectRange(Solver& s, const Literal* first, const Literal* last) { + (void)s; (void)last; + return *first; + } + static Literal selectLiteral(Solver& s, Var v, int signScore) { + ValueSet prefs = s.pref(v); + if (signScore != 0 && !prefs.has(ValueSet::user_value | ValueSet::saved_value | ValueSet::pref_value)) { + return Literal(v, signScore < 0); + } + else if (!prefs.empty()) { + return Literal(v, prefs.sign()); + } + return s.defaultLit(v); + } +private: + DecisionHeuristic(const DecisionHeuristic&); + DecisionHeuristic& operator=(const DecisionHeuristic&); +}; +//! Selects the first free literal w.r.t to the initial variable order. +class SelectFirst : public DecisionHeuristic { +public: + void updateVar(const Solver&, Var, uint32) {} +protected: + Literal doSelect(Solver& s); +}; +//@} +} +#endif + diff --git a/libclasp/clasp/solver_strategies.h b/libclasp/clasp/solver_strategies.h new file mode 100644 index 0000000..fd3efd8 --- /dev/null +++ b/libclasp/clasp/solver_strategies.h @@ -0,0 +1,528 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_SOLVER_STRATEGIES_H_INCLUDED +#define CLASP_SOLVER_STRATEGIES_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include + +#if !defined(CLASP_ALIGN_BITFIELD) +# if defined(EMSCRIPTEN) +// Force alignment of bitfield to T in order to prevent +// code-generation bug in emcc +// see: https://github.com/kripken/emscripten/issues/4540 +# define CLASP_ALIGN_BITFIELD(T) T : 0; +# else +# define CLASP_ALIGN_BITFIELD(T) +# endif +#endif + +/*! + * \file + * \brief Contains strategies and options used to configure solvers and search. + */ +namespace Clasp { +//! Implements clasp's configurable schedule-strategies. +/*! + * clasp currently supports the following basic strategies: + * - geometric sequence : X = n1 * n2^k (k >= 0) + * - arithmetic sequence : X = n1 + (n2*k) (k >= 0) + * - fixed sequence : X = n1 + (0*k) (k >= 0) + * - luby's sequence : X = n1 * luby(k)(k >= 0) + * . + * Furthermore, an inner-outer scheme can be applied to the selected sequence. + * In that case, the sequence is repeated every \+j restarts, where + * \ is the initial outer-limit and j is the number of times the + * sequence was already repeated. + * + * \note For luby's seqeuence, j is not a repetition counter + * but the index where the sequence grows to the next power of two. + * + * \see Luby et al. "Optimal speedup of las vegas algorithms." + * + */ +struct ScheduleStrategy { +public: + //! Supported strategies. + enum Type { Geometric = 0, Arithmetic = 1, Luby = 2, User = 3 }; + + ScheduleStrategy(Type t = Geometric, uint32 b = 100, double g = 1.5, uint32 o = 0); + //! Creates luby's sequence with unit-length unit and optional outer limit. + static ScheduleStrategy luby(uint32 unit, uint32 limit = 0) { return ScheduleStrategy(Luby, unit, 0, limit); } + //! Creates geometric sequence base * (grow^k) with optional outer limit. + static ScheduleStrategy geom(uint32 base, double grow, uint32 limit = 0) { return ScheduleStrategy(Geometric, base, grow, limit); } + //! Creates arithmetic sequence base + (add*k) with optional outer limit. + static ScheduleStrategy arith(uint32 base, double add, uint32 limit = 0) { return ScheduleStrategy(Arithmetic, base, add, limit); } + //! Creates fixed sequence with length base. + static ScheduleStrategy fixed(uint32 base) { return ScheduleStrategy(Arithmetic, base, 0, 0); } + static ScheduleStrategy none() { return ScheduleStrategy(Geometric, 0); } + static ScheduleStrategy def() { return ScheduleStrategy(User, 0, 0.0); } + uint64 current() const; + bool disabled() const { return base == 0; } + bool defaulted()const { return base == 0 && type == User; } + void reset() { idx = 0; } + uint64 next(); + void advanceTo(uint32 idx); + uint32 base : 30; // base of sequence (n1) + uint32 type : 2; // type of basic sequence + uint32 idx; // current index into sequence + uint32 len; // length of sequence (0 if infinite) (once reached, sequence is repeated and len increased) + float grow; // update parameter n2 +}; +//! Returns the idx'th value of the luby sequence. +uint32 lubyR(uint32 idx); +//! Returns the idx'th value of the geometric sequence with the given growth factor. +double growR(uint32 idx, double g); +//! Returns the idx'th value of the arithmetic sequence with the given addend. +double addR(uint32 idx, double a); + +class DecisionHeuristic; +//! Parameter-Object for grouping solver strategies. +struct SolverStrategies { + //! Clasp's two general search strategies. + enum SearchStrategy { + use_learning = 0, //!< Analyze conflicts and learn First-1-UIP-clause. + no_learning = 1 //!< Don't analyze conflicts - chronological backtracking. + }; + //! Default sign heuristic. + enum SignHeu { + sign_atom = 0, //!< Prefer negative literal for atoms. + sign_pos = 1, //!< Prefer positive literal. + sign_neg = 2, //!< Prefer negative literal. + sign_rnd = 3, //!< Prefer random literal. + }; + //! Conflict clause minimization strategy. + enum CCMinType { + cc_local = 0, //!< Basic algorithm. + cc_recursive = 1, //!< Extended algorithm. + }; + //! Antecedents to consider during conflict clause minimization. + enum CCMinAntes { + no_antes = 0, //!< Don't minimize conflict clauses. + all_antes = 1, //!< Consider all antecedents. + short_antes = 2, //!< Consider only short antecedents. + binary_antes = 3, //!< Consider only binary antecedents. + }; + //! Simplifications for long conflict clauses. + enum CCRepMode { + cc_no_replace = 0,//!< Don't replace literals in conflict clauses. + cc_rep_decision= 1,//!< Replace conflict clause with decision sequence. + cc_rep_uip = 2,//!< Replace conflict clause with all uip clause. + cc_rep_dynamic = 3,//!< Dynamically select between cc_rep_decision and cc_rep_uip. + }; + //! Strategy for initializing watched literals in clauses. + enum WatchInit { watch_first = 0, watch_rand = 1, watch_least = 2 }; + //! Strategy for integrating new information in parallel solving. + enum UpdateMode { update_on_propagate = 0, update_on_conflict = 1 }; + + SolverStrategies(); + void prepare(); + //----- 32 bit ------------ + uint32 compress : 16; /*!< If > 0, enable compression for learnt clauses of size > compress. */ + uint32 saveProgress : 16; /*!< Enable progress saving if > 0. */ + //----- 32 bit ------------ + uint32 heuId : 3; /*!< Type of decision heuristic. */ + uint32 reverseArcs : 2; /*!< Use "reverse-arcs" during learning if > 0. */ + uint32 otfs : 2; /*!< Enable "on-the-fly" subsumption if > 0. */ + uint32 updateLbd : 2; /*!< Update lbds of antecedents during conflict analysis. */ + uint32 ccMinAntes : 2; /*!< Antecedents to look at during conflict clause minimization. */ + uint32 ccRepMode : 2; /*!< One of CCRepMode. */ + uint32 ccMinRec : 1; /*!< If 1, use more expensive recursive nogood minimization. */ + uint32 ccMinKeepAct : 1; /*!< Do not increase nogood activities during nogood minimization? */ + uint32 initWatches : 2; /*!< Initialize watches randomly in clauses. */ + uint32 upMode : 1; /*!< One of UpdateMode. */ + uint32 bumpVarAct : 1; /*!< Bump activities of vars implied by learnt clauses with small lbd. */ + uint32 search : 1; /*!< Current search strategy. */ + uint32 restartOnModel: 1; /*!< Do a restart after each model. */ + uint32 signDef : 2; /*!< Default sign heuristic. */ + uint32 signFix : 1; /*!< Disable all sign heuristics and always use default sign. */ + uint32 reserved : 1; + uint32 hasConfig : 1; /*!< Config applied to solver? */ + uint32 id : 6; /*!< Solver id - SHALL ONLY BE SET BY Shared Context! */ +}; +//! Parameter-Object for grouping additional heuristic options. +struct HeuParams { + //! Strategy for scoring clauses not learnt by conflict analysis. + enum ScoreOther { other_no = 0u, other_loop = 1u, other_all = 2u, other_auto = 3u }; + //! Strategy for scoring during conflict analysis. + enum Score { score_auto = 0u, score_min = 1u, score_set = 2u, score_multi_set = 3u }; + //! Global preference for domain heuristic. + enum DomPref { pref_atom = 0u, pref_scc = 1u, pref_hcc = 2u, pref_disj = 4u, pref_min = 8u, pref_show = 16u }; + //! Global modification for domain heuristic. + enum DomMod { mod_none = 0u, mod_level = 1u, mod_spos = 2u, mod_true = 3u, mod_sneg = 4u, mod_false = 5u, mod_init = 6u, mod_factor = 7u }; + //! Values for dynamic decaying scheme. + struct VsidsDecay { + uint32 init: 10; /*!< Starting decay factor: 1/0.\. */ + uint32 bump: 7; /*!< Decay decrease value : \/100. */ + uint32 freq: 15; /*!< Update decay factor every \ conflicts. */ + }; + HeuParams(); + uint32 param : 16; /*!< Extra parameter for heuristic with meaning depending on type. */ + uint32 score : 2; /*!< Type of scoring during resolution. */ + uint32 other : 2; /*!< Consider other learnt nogoods in heuristic. */ + uint32 moms : 1; /*!< Use MOMS-score as top-level heuristic. */ + uint32 nant : 1; /*!< Prefer elements in NegAnte(P). */ + uint32 huang : 1; /*!< Only for Berkmin. */ + uint32 acids : 1; /*!< Only for Vsids/Dom. */ + uint32 domPref : 5; /*!< Default pref for doamin heuristic (set of DomPref). */ + uint32 domMod : 3; /*!< Default mod for domain heuristic (one of DomMod). */ + union { + uint32 extra; + VsidsDecay decay; /*!< Only for Vsids/Dom. */ + }; +}; + +//! Parameter-Object for configuring a solver. +struct SolverParams : SolverStrategies { + SolverParams(); + uint32 prepare(); + inline bool forgetHeuristic() const { return (forgetSet & 1u) != 0; } + inline bool forgetSigns() const { return (forgetSet & 2u) != 0; } + inline bool forgetActivities()const { return (forgetSet & 4u) != 0; } + inline bool forgetLearnts() const { return (forgetSet & 8u) != 0; } + SolverParams& setId(uint32 id) { this->id = id; return *this; } + HeuParams heuristic; /*!< Parameters for decision heuristic. */ + // 64-bit + uint32 seed; /*!< Seed for the random number generator. */ + uint32 lookOps : 16; /*!< Max. number of lookahead operations (0: no limit). */ + uint32 optStrat : 1; /*!< Optimization strategy (see MinimizeMode_t::Strategy).*/ + uint32 optParam : 4; /*!< Parameter for optimization strategy (see MinimizeMode_t::BBOption / MinimizeMode_t::UscOption). */ + uint32 optHeu : 2; /*!< Set of optimize heuristics. */ + uint32 lookType : 2; /*!< Type of lookahead operations. */ + uint32 loopRep : 2; /*!< How to represent loops? */ + uint32 acycFwd : 1; /*!< Disable backward propagation in acyclicity checker. */ + uint32 forgetSet : 4; /*!< What to forget on (incremental step). */ +}; + +typedef Range Range32; + +//! Aggregates restart-parameters to configure restarts during search. +/*! + * \see ScheduleStrategy + */ +struct RestartParams { + RestartParams(); + enum SeqUpdate { seq_continue = 0, seq_repeat = 1, seq_disable = 2 }; + uint32 prepare(bool withLookback); + void disable(); + bool dynamic() const { return dynRestart != 0; } + bool local() const { return cntLocal != 0; } + SeqUpdate update() const { return static_cast(upRestart); } + ScheduleStrategy sched; /**< Restart schedule to use. */ + float blockScale; /**< Scaling factor for blocking restarts. */ + uint32 blockWindow: 16; /**< Size of moving assignment average for blocking restarts (0: disable). */ + uint32 blockFirst : 16; /**< Enable blocking restarts after blockFirst conflicts. */ + CLASP_ALIGN_BITFIELD(uint32) + uint32 counterRestart:16;/**< Apply counter implication bump every counterRestart restarts (0: disable). */ + uint32 counterBump:16; /**< Bump factor for counter implication restarts. */ + CLASP_ALIGN_BITFIELD(uint32) + uint32 shuffle :14; /**< Shuffle program after shuffle restarts (0: disable). */ + uint32 shuffleNext:14; /**< Re-Shuffle program every shuffleNext restarts (0: disable). */ + uint32 upRestart : 2; /**< How to update restart sequence after a model was found (one of SeqUpdate). */ + uint32 cntLocal : 1; /**< Count conflicts globally or relative to current branch? */ + uint32 dynRestart : 1; /**< Dynamic restarts enabled? */ +}; + +//! Reduce strategy used during solving. +/*! + * A reduce strategy mainly consists of an algorithm and a scoring scheme + * for measuring "activity" of learnt constraints. + */ +struct ReduceStrategy { + //! Reduction algorithm to use during solving. + enum Algorithm { + reduce_linear = 0, //!< Linear algorithm from clasp-1.3.x. + reduce_stable = 1, //!< Sort constraints by score but keep order in learnt db. + reduce_sort = 2, //!< Sort learnt db by score and remove fraction with lowest score. + reduce_heap = 3 //!< Similar to reduce_sort but only partially sorts learnt db. + }; + //! Score to measure "activity" of learnt constraints. + enum Score { + score_act = 0, //!< Activity only: how often constraint is used during conflict analysis. + score_lbd = 1, //!< Use literal block distance as activity. + score_both = 2 //!< Use activity and lbd together. + }; + //! Strategy for estimating size of problem. + enum EstimateSize { + est_dynamic = 0, //!< Dynamically decide whether to use number of variables or constraints. + est_con_complexity = 1, //!< Measure size in terms of constraint complexities. + est_num_constraints = 2, //!< Measure size in terms of number constraints. + est_num_vars = 3 //!< Measure size in terms of number variable. + }; + static uint32 scoreAct(const ConstraintScore& sc) { return sc.activity(); } + static uint32 scoreLbd(const ConstraintScore& sc) { return uint32(LBD_MAX+1)-sc.lbd(); } + static uint32 scoreBoth(const ConstraintScore& sc) { return (sc.activity()+1) * scoreLbd(sc); } + static int compare(Score sc, const ConstraintScore& lhs, const ConstraintScore& rhs) { + int fs = 0; + if (sc == score_act) { fs = ((int)scoreAct(lhs)) - ((int)scoreAct(rhs)); } + else if (sc == score_lbd) { fs = ((int)scoreLbd(lhs)) - ((int)scoreLbd(rhs)); } + return fs != 0 ? fs : ((int)scoreBoth(lhs)) - ((int)scoreBoth(rhs)); + } + static uint32 asScore(Score sc, const Clasp::ConstraintScore& act) { + if (sc == score_act) { return scoreAct(act); } + if (sc == score_lbd) { return scoreLbd(act); } + /* sc == score_both*/{ return scoreBoth(act);} + } + ReduceStrategy() : protect(0), glue(0), fReduce(75), fRestart(0), score(0), algo(0), estimate(0), noGlue(0) { + static_assert(sizeof(ReduceStrategy) == sizeof(uint32), "invalid bitset"); + } + uint32 protect : 7; /*!< Protect nogoods whose lbd was reduced and is now <= freeze. */ + uint32 glue : 4; /*!< Don't remove nogoods with lbd <= glue. */ + uint32 fReduce : 7; /*!< Fraction of nogoods to remove in percent. */ + uint32 fRestart: 7; /*!< Fraction of nogoods to remove on restart. */ + uint32 score : 2; /*!< One of Score. */ + uint32 algo : 2; /*!< One of Algorithm. */ + uint32 estimate: 2; /*!< How to estimate problem size in init. */ + uint32 noGlue : 1; /*!< Do not count glue clauses in limit. */ +}; + +//! Aggregates parameters for the nogood deletion heuristic used during search. +/*! + * - S:delCond {yes,no} + * - no:del {0}[0] + * - no:del | delCond in {no} + * - deletion | delCond in {yes} + * - del-* | delCond in {yes} + * - {delCond=yes, del-grow=no, del-cfl=no} + * . + */ +struct ReduceParams { + ReduceParams() : cflSched(ScheduleStrategy::none()), growSched(ScheduleStrategy::def()) + , fInit(1.0f/3.0f) + , fMax(3.0f) + , fGrow(1.1f) + , initRange(10, UINT32_MAX) + , maxRange(UINT32_MAX) + , memMax(0) {} + void disable(); + uint32 prepare(bool withLookback); + Range32 sizeInit(const SharedContext& ctx) const; + uint32 cflInit(const SharedContext& ctx) const; + uint32 getBase(const SharedContext& ctx) const; + float fReduce() const { return strategy.fReduce / 100.0f; } + float fRestart() const { return strategy.fRestart/ 100.0f; } + static uint32 getLimit(uint32 base, double f, const Range& r); + ScheduleStrategy cflSched; /**< Conflict-based deletion schedule. */ + ScheduleStrategy growSched; /**< Growth-based deletion schedule. */ + ReduceStrategy strategy; /**< Strategy to apply during nogood deletion. */ + float fInit; /**< Initial limit. X = P*fInit clamped to initRange.*/ + float fMax; /**< Maximal limit. X = P*fMax clamped to maxRange. */ + float fGrow; /**< Growth factor for db. */ + Range32 initRange; /**< Allowed range for initial limit. */ + uint32 maxRange; /**< Allowed range for maximal limit: [initRange.lo,maxRange]*/ + uint32 memMax; /**< Memory limit in MB (0 = no limit). */ +}; + +//! Parameter-Object for grouping solve-related options. +/*! + * \ingroup enumerator + */ +struct SolveParams { + //! Creates a default-initialized object. + /*! + * The following parameters are used: + * - restart : quadratic: 100*1.5^k / no restarts after first solution + * - deletion : initial size: vars()/3, grow factor: 1.1, max factor: 3.0, do not reduce on restart + * - randomization: disabled + * - randomProp : 0.0 (disabled) + * . + */ + SolveParams(); + uint32 prepare(bool withLookback); + bool randomize(Solver& s) const; + RestartParams restart; + ReduceParams reduce; + uint32 randRuns:16; /*!< Number of initial randomized-runs. */ + uint32 randConf:16; /*!< Number of conflicts comprising one randomized-run. */ + float randProb; /*!< Use random heuristic with given probability ([0,1]) */ + struct FwdCheck { /*!< Options for (partial checks in) DLP-solving; */ + uint32 highStep : 24; /*!< Init/inc high level when reached. */ + uint32 highPct : 7; /*!< Check on low + (high - low) * highPct/100 */ + uint32 signDef : 2; /*!< Default sign heuristic for atoms in disjunctions. */ + FwdCheck() { std::memset(this, 0, sizeof(*this)); } + } fwdCheck; +}; + +class SharedContext; +class SatPreprocessor; + +//! Parameters for (optional) Sat-preprocessing. +struct SatPreParams { + enum Algo { + sat_pre_no = 0, /**< Disable sat-preprocessing. */ + sat_pre_ve = 1, /**< Run variable elimination. */ + sat_pre_ve_bce = 2, /**< Run variable- and limited blocked clause elimination. */ + sat_pre_full = 3, /**< Run variable- and full blocked clause elimination. */ + }; + SatPreParams() : type(0u), limIters(0u), limTime(0u), limFrozen(0u), limClause(4000u), limOcc(0u) {} + uint32 type : 2; /**< One of algo. */ + uint32 limIters : 11; /**< Max. number of iterations. (0=no limit)*/ + uint32 limTime : 12; /**< Max. runtime in sec, checked after each iteration. (0=no limit)*/ + uint32 limFrozen: 7; /**< Run only if percent of frozen vars < maxFrozen. (0=no limit)*/ + uint32 limClause: 16; /**< Run only if \#clauses \< (limClause*1000) (0=no limit)*/ + uint32 limOcc : 16; /**< Skip v, if \#occ(v) \>= limOcc && \#occ(~v) \>= limOcc.(0=no limit) */ + bool clauseLimit(uint32 nc) const { return limClause && nc > (limClause*1000u); } + bool occLimit(uint32 pos, uint32 neg) const { return limOcc && pos > (limOcc-1u) && neg > (limOcc-1u); } + uint32 bce() const { return type != sat_pre_no ? type - 1 : 0; } + void disableBce() { type = std::min(type, uint32(sat_pre_ve));} + static SatPreprocessor* create(const SatPreParams&); +}; + +//! Parameters for a SharedContext object. +struct ContextParams { + //! How to handle short learnt clauses. + enum ShortMode { + short_implicit = 0, /*!< Share short learnt clauses via short implication graph. */ + short_explicit = 1, /*!< Do not use short implication graph. */ + }; + //! How to handle physical sharing of (explicit) constraints. + enum ShareMode { + share_no = 0, /*!< Do not physically share constraints (use copies instead). */ + share_problem = 1, /*!< Share problem constraints but copy learnt constraints. */ + share_learnt = 2, /*!< Copy problem constraints but share learnt constraints. */ + share_all = 3, /*!< Share all constraints. */ + share_auto = 4, /*!< Use share_no or share_all depending on number of solvers. */ + }; + ContextParams() : shareMode(share_auto), stats(0), shortMode(short_implicit), seed(1), hasConfig(0), cliConfig(0), cliId(0), cliMode(0) {} + SatPreParams satPre; /*!< Preprocessing options. */ + uint8 shareMode : 3; /*!< Physical sharing mode (one of ShareMode). */ + uint8 stats : 2; /*!< See SharedContext::enableStats(). */ + uint8 shortMode : 1; /*!< One of ShortMode. */ + uint8 seed : 1; /*!< Apply new seed when adding solvers. */ + uint8 hasConfig : 1; /*!< Reserved for command-line interface. */ + uint8 cliConfig; /*!< Reserved for command-line interface. */ + uint8 cliId; /*!< Reserved for command-line interface. */ + uint8 cliMode; /*!< Reserved for command-line interface. */ +}; + +//! Interface for configuring a SharedContext object and its associated solvers. +class Configuration { +public: + typedef SolverParams SolverOpts; + typedef SolveParams SearchOpts; + typedef ContextParams CtxOpts; + virtual ~Configuration(); + //! Prepares this configuration for the usage in the given context. + virtual void prepare(SharedContext&) = 0; + //! Returns the options for the shared context. + virtual const CtxOpts& context() const = 0; + //! Returns the number of solver options in this config. + virtual uint32 numSolver() const = 0; + //! Returns the number of search options in this config. + virtual uint32 numSearch() const = 0; + //! Returns the solver options for the i'th solver to be attached to the SharedContext. + virtual const SolverOpts& solver(uint32 i) const = 0; + //! Returns the search options for the i'th solver of the SharedContext. + virtual const SearchOpts& search(uint32 i) const = 0; + //! Returns the heuristic to be used in the i'th solver. + /*! + * The function is called in Solver::startInit(). + * \note The returned object is owned by the caller. + */ + virtual DecisionHeuristic* heuristic(uint32 i) const = 0; + //! Adds post propagators to the given solver. + virtual bool addPost(Solver& s) const = 0; + //! Returns the configuration with the given name or 0 if no such config exists. + /*! + * The default implementation returns this + * if n is empty or one of "." or "/". + * Otherwise, 0 is returned. + */ + virtual Configuration* config(const char* n); +}; + +//! Base class for user-provided configurations. +class UserConfiguration : public Configuration { +public: + //! Adds a lookahead post propagator to the given solver if requested. + /*! + * The function adds a lookahead post propagator if indicated by + * the solver's SolverParams. + */ + virtual bool addPost(Solver& s) const; + //! Returns the (modifiable) solver options for the i'th solver. + virtual SolverOpts& addSolver(uint32 i) = 0; + //! Returns the (modifiable) search options for the i'th solver. + virtual SearchOpts& addSearch(uint32 i) = 0; +}; + +//! Simple factory for decision heuristics. +struct Heuristic_t { + enum Type { Default = 0, Berkmin = 1, Vsids = 2, Vmtf = 3, Domain = 4, Unit = 5, None = 6, User = 7 }; + typedef DecisionHeuristic* (*Creator)(Type t, const HeuParams& p); + static inline bool isLookback(uint32 type) { return type >= (uint32)Berkmin && type < (uint32)Unit; } + //! Default callback for creating decision heuristics. + static DecisionHeuristic* create(Type t, const HeuParams& p); +}; + +//! Basic configuration for one or more SAT solvers. +class BasicSatConfig : public UserConfiguration, public ContextParams { +public: + typedef Heuristic_t::Creator HeuristicCreator; + BasicSatConfig(); + void prepare(SharedContext&); + const CtxOpts& context() const { return *this; } + uint32 numSolver() const { return sizeVec(solver_); } + uint32 numSearch() const { return sizeVec(search_); } + const SolverOpts& solver(uint32 i) const { return solver_[i % solver_.size() ]; } + const SearchOpts& search(uint32 i) const { return search_[i % search_.size() ]; } + DecisionHeuristic* heuristic(uint32 i) const; + SolverOpts& addSolver(uint32 i); + SearchOpts& addSearch(uint32 i); + + virtual void reset(); + virtual void resize(uint32 numSolver, uint32 numSearch); + //! Sets callback function for creating heuristics. + void setHeuristicCreator(HeuristicCreator hc); +private: + typedef PodVector::type SolverVec; + typedef PodVector::type SearchVec; + SolverVec solver_; + SearchVec search_; + HeuristicCreator heu_; +}; + +//! Base class for solving related events. +template +struct SolveEvent : Event_t { + SolveEvent(const Solver& s, Event::Verbosity verb) : Event_t(Event::subsystem_solve, verb), solver(&s) {} + const Solver* solver; +}; +struct Model; +//! Base class for handling results of a solve operation. +class ModelHandler { +public: + virtual ~ModelHandler(); + virtual bool onModel(const Solver&, const Model&) = 0; + virtual bool onUnsat(const Solver&, const Model&); +}; +//! Type for storing the lower bound of a minimize statement. +struct LowerBound { + LowerBound() : level(0), bound(0) {} + void reset() { level = 0; bound = 0; } + uint32 level; + wsum_t bound; +}; + +} +#endif diff --git a/libclasp/clasp/solver_types.h b/libclasp/clasp/solver_types.h new file mode 100644 index 0000000..9730c68 --- /dev/null +++ b/libclasp/clasp/solver_types.h @@ -0,0 +1,793 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_SOLVER_TYPES_H_INCLUDED +#define CLASP_SOLVER_TYPES_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +/*! + * \file + * \brief Types and functions used by a Solver + */ +namespace Clasp { +class SharedLiterals; + +/*! + * \addtogroup solver + */ +//@{ +/////////////////////////////////////////////////////////////////////////////// +// SearchLimits +/////////////////////////////////////////////////////////////////////////////// +struct DynamicLimit; +struct BlockLimit; + +//! Parameter-Object for managing search limits. +struct SearchLimits { + typedef DynamicLimit* LimitPtr; + typedef BlockLimit* BlockPtr; + SearchLimits(); + uint64 used; + struct { + uint64 conflicts; //!< Soft limit on number of conflicts for restart. + LimitPtr dynamic; //!< Use dynamic restarts based on lbd or conflict level. + BlockPtr block; //!< Optional strategy to increase restart limit. + bool local; //!< Apply conflict limit against active branch. + } restart; //!< Restart limits. + uint64 conflicts; //!< Soft limit on number of conflicts. + uint64 memory; //!< Soft memory limit for learnt lemmas (in bytes). + uint32 learnts; //!< Limit on number of learnt lemmas. +}; + +//! Type for implementing Glucose-style dynamic restarts. +/*! + * \see G. Audemard, L. Simon. "Refining Restarts Strategies for SAT and UNSAT" + * \note In contrast to Glucose's dynamic restarts, this class also implements + * a heuristic for dynamically adjusting the margin ratio K. + */ +struct DynamicLimit { + enum Type { lbd_limit, level_limit }; + //! Creates new limit with bounded queue of the given window size. + static DynamicLimit* create(uint32 window); + //! Destroys this object and its bounded queue. + void destroy(); + //! Resets moving average and adjust limit. + void init(float k, Type type, uint32 uLimit = 16000); + //! Resets moving average, i.e. clears the bounded queue. + void resetRun(); + //! Resets moving and global average. + void reset(); + //! Adds an observation and updates the moving average. Typically called on conflict. + void update(uint32 conflictLevel, uint32 lbd); + //! Notifies this object about a restart. + /*! + * The function checks whether to adjust the active margin ratio and/or + * whether to switch from LBD based to conflict level based restarts. + * + * \param maxLBD Threshold for switching between lbd and conflict level queue. + * \param k Lower bound for margin ratio. + */ + uint32 restart(uint32 maxLBD, float k); + //! Returns the number of updates since last restart. + uint32 runLen() const { return num_; } + //! Returns the maximal size of the bounded queue. + uint32 window() const { return cap_; } + //! Returns whether it is time to restart. + bool reached() const { return runLen() >= window() && (sma(adjust.type) * adjust.rk) > global.avg(adjust.type); } + struct { + //! Returns the global lbd or conflict level average. + double avg(Type t) const { return ratio(sum[t], samples); } + uint64 sum[2]; //!< Sum of lbds/conflict levels since last call to resetGlobal(). + uint64 samples;//!< Samples since last call to resetGlobal(). + } global; //!< Global lbd/conflict level data. + struct { + //! Returns the average restart length, i.e. number of conflicts between restarts. + double avgRestart() const { return ratio(samples, restarts); } + uint32 limit; //!< Number of conflicts before an update is forced. + uint32 restarts;//!< Number of restarts since last update. + uint32 samples; //!< Number of samples since last update. + float rk; //!< BD/CFL dynamic limit factor (typically < 1.0). + Type type; //!< Dynamic limit based on lbd or confllict level. + } adjust; //!< Data for dynamically adjusting margin ratio (rk). +private: + DynamicLimit(uint32 size); + DynamicLimit(const DynamicLimit&); + DynamicLimit& operator=(const DynamicLimit&); + double sma(Type t) const { return sum_[t] / double(cap_); } + uint32 smaU(Type t) const { return static_cast(sum_[t] / cap_); } + uint64 sum_[2]; + uint32 cap_; + uint32 pos_; + uint32 num_; +CLASP_WARNING_BEGIN_RELAXED + uint32 buffer_[0]; +CLASP_WARNING_END_RELAXED +}; + +//! Type for implementing Glucose-style blocking of restarts. +/*! + * \see G. Audemard, L. Simon "Refining Restarts Strategies for SAT and UNSAT" + * \see A. Biere, A. Froehlich "Evaluating CDCL Variable Scoring Schemes" + */ +struct BlockLimit { + explicit BlockLimit(uint32 windowSize, double R = 1.4); + bool push(uint32 nAssign) { + ema = n >= span + ? exponentialMovingAverage(ema, nAssign, alpha) + : cumulativeMovingAverage(ema, nAssign, n); + return ++n >= next; + } + //! Returns the exponential moving average scaled by r. + double scaled() const { return ema * r; } + double ema; //!< Current exponential moving average. + double alpha; //!< Smoothing factor: 2/(span+1). + uint64 next; //!< Enable once n >= next. + uint64 inc; //!< Block restart for next inc conflicts. + uint64 n; //!< Number of data points seen so far. + uint32 span; //!< Minimum observation window. + float r; //!< Scale factor for ema. +}; +/////////////////////////////////////////////////////////////////////////////// +// Statistics +/////////////////////////////////////////////////////////////////////////////// +class StatisticObject; +class StatsMap; +#if !defined(DOXY) +#define DOXY(X) +#endif +#define CLASP_STAT_DEFINE(m, k, a, accu) m +#define NO_ARG +#define CLASP_DECLARE_ISTATS(T) \ + void accu(const T& o);\ + static uint32 size();\ + static const char* key(uint32 i);\ + StatisticObject at(const char* key) const + +//! A struct for holding core statistics used by a solver. +/*! + * Core statistics are always present in a solver and hence + * can be used by heuristics. + */ +struct CoreStats { +#define CLASP_CORE_STATS(STAT, LHS, RHS) \ + STAT(uint64 choices; DOXY(number of choices) , "choices" , VALUE(choices) , LHS.choices += RHS.choices )\ + STAT(uint64 conflicts; DOXY(number of conflicts) , "conflicts" , VALUE(conflicts) , LHS.conflicts += RHS.conflicts )\ + STAT(uint64 analyzed; DOXY(number of conflicts analyzed), "conflicts_analyzed", VALUE(analyzed) , LHS.analyzed += RHS.analyzed )\ + STAT(uint64 restarts; DOXY(number of restarts) , "restarts" , VALUE(restarts) , LHS.restarts += RHS.restarts )\ + STAT(uint64 lastRestart;DOXY(length of last restart), "restarts_last" , VALUE(lastRestart), LHS.lastRestart = std::max(LHS.lastRestart, RHS.lastRestart)) + + CoreStats() { reset(); } + void reset(); + uint64 backtracks() const { return conflicts-analyzed; } + uint64 backjumps() const { return analyzed; } + double avgRestart() const { return ratio(analyzed, restarts); } + CLASP_DECLARE_ISTATS(CoreStats); + CLASP_CORE_STATS(CLASP_STAT_DEFINE, NO_ARG, NO_ARG) +}; +//! A struct for holding (optional) jump statistics. +struct JumpStats { +#define CLASP_JUMP_STATS(STAT, LHS, RHS) \ + STAT(uint64 jumps; DOXY(number of backjumps) , "jumps" , VALUE(jumps) , LHS.jumps += RHS.jumps) \ + STAT(uint64 bounded; DOXY(backjumps bounded by root level) , "jumps_bounded" , VALUE(bounded) , LHS.bounded += RHS.bounded) \ + STAT(uint64 jumpSum; DOXY(levels removed by jumps) , "levels" , VALUE(jumpSum) , LHS.jumpSum += RHS.jumpSum) \ + STAT(uint64 boundSum; DOXY(levels kept because of root level) , "levels_bounded" , VALUE(boundSum) , LHS.boundSum += RHS.boundSum) \ + STAT(uint32 maxJump; DOXY(longest backjump) , "max" , VALUE(maxJump) , MAX_MEM(LHS.maxJump, RHS.maxJump)) \ + STAT(uint32 maxJumpEx;DOXY(longest unbounded backjump) , "max_executed" , VALUE(maxJumpEx), MAX_MEM(LHS.maxJumpEx,RHS.maxJumpEx)) \ + STAT(uint32 maxBound; DOXY(max levels kept because of root level), "max_bounded" , VALUE(maxBound) , MAX_MEM(LHS.maxBound, RHS.maxBound)) + + JumpStats() { reset(); } + void reset(); + void update(uint32 dl, uint32 uipLevel, uint32 bLevel) { + ++jumps; + jumpSum += dl - uipLevel; + maxJump = std::max(maxJump, dl - uipLevel); + if (uipLevel < bLevel) { + ++bounded; + boundSum += bLevel - uipLevel; + maxJumpEx = std::max(maxJumpEx, dl - bLevel); + maxBound = std::max(maxBound, bLevel - uipLevel); + } + else { maxJumpEx = maxJump; } + } + uint64 jumped() const { return jumpSum - boundSum; } + double jumpedRatio()const { return ratio(jumped(), jumpSum); } + double avgBound() const { return ratio(boundSum, bounded); } + double avgJump() const { return ratio(jumpSum, jumps); } + double avgJumpEx() const { return ratio(jumped(), jumps); } + CLASP_DECLARE_ISTATS(JumpStats); + CLASP_JUMP_STATS(CLASP_STAT_DEFINE, NO_ARG, NO_ARG) +}; + +//! A struct for holding (optional) extended statistics. +struct ExtendedStats { + typedef ConstraintType type_t; + //! An array for storing a value[t-1] for each learnt Constraint_t::Type t. + typedef uint64 Array[Constraint_t::Type__max]; +#define CLASP_EXTENDED_STATS(STAT, LHS, RHS) \ + STAT(uint64 domChoices; DOXY(number of domain choices) , "domain_choices" , VALUE(domChoices) , LHS.domChoices += RHS.domChoices) \ + STAT(uint64 models; DOXY(number of models) , "models" , VALUE(models) , LHS.models += RHS.models) \ + STAT(uint64 modelLits; DOXY(decision levels in models) , "models_level" , VALUE(modelLits) , LHS.modelLits += RHS.modelLits) \ + STAT(uint64 hccTests; DOXY(number of stability tests) , "hcc_tests" , VALUE(hccTests) , LHS.hccTests += RHS.hccTests) \ + STAT(uint64 hccPartial; DOXY(number of partial tests) , "hcc_partial" , VALUE(hccPartial) , LHS.hccPartial += RHS.hccPartial) \ + STAT(uint64 deleted; DOXY(lemmas deleted ) , "lemmas_deleted" , VALUE(deleted) , LHS.deleted += RHS.deleted) \ + STAT(uint64 distributed;DOXY(lemmas distributed ) , "distributed" , VALUE(distributed), LHS.distributed+= RHS.distributed)\ + STAT(uint64 sumDistLbd; DOXY(lbds of distributed lemmas) , "distributed_sum_lbd" , VALUE(sumDistLbd) , LHS.sumDistLbd += RHS.sumDistLbd) \ + STAT(uint64 integrated; DOXY(lemmas integrated ) , "integrated" , VALUE(integrated) , LHS.integrated += RHS.integrated) \ + STAT(Array learnts; DOXY(lemmas of each learnt type) , "lemmas" , MEM_FUN(lemmas) , NO_ARG) \ + STAT(Array lits; DOXY(lits of each learnt type) , "lits_learnt" , MEM_FUN(learntLits), NO_ARG) \ + STAT(uint32 binary; DOXY(number of binary lemmas) , "lemmas_binary" , VALUE(binary) , LHS.binary += RHS.binary) \ + STAT(uint32 ternary; DOXY(number of ternary lemmas) , "lemmas_ternary" , VALUE(ternary) , LHS.ternary += RHS.ternary) \ + STAT(double cpuTime; DOXY(cpu time used ) , "cpu_time" , VALUE(cpuTime) , LHS.cpuTime += RHS.cpuTime) \ + STAT(uint64 intImps; DOXY(implications on integrating), "integrated_imps" , VALUE(intImps) , LHS.intImps+= RHS.intImps) \ + STAT(uint64 intJumps; DOXY(backjumps on integrating) , "integrated_jumps" , VALUE(intJumps), LHS.intJumps+=RHS.intJumps) \ + STAT(uint64 gpLits; DOXY(lits in received gps) , "guiding_paths_lits" , VALUE(gpLits) , LHS.gpLits += RHS.gpLits) \ + STAT(uint32 gps; DOXY(guiding paths received) , "guiding_paths" , VALUE(gps) , LHS.gps += RHS.gps) \ + STAT(uint32 splits; DOXY(split requests handled) , "splits" , VALUE(splits) , LHS.splits += RHS.splits) \ + STAT(NO_ARG , "lemmas_conflict", VALUE(learnts[0]) , LHS.learnts[0] += RHS.learnts[0]) \ + STAT(NO_ARG , "lemmas_loop" , VALUE(learnts[1]) , LHS.learnts[1] += RHS.learnts[1]) \ + STAT(NO_ARG , "lemmas_other" , VALUE(learnts[2]) , LHS.learnts[2] += RHS.learnts[2]) \ + STAT(NO_ARG , "lits_conflict" , VALUE(lits[0]) , LHS.lits[0] += RHS.lits[0]) \ + STAT(NO_ARG , "lits_loop" , VALUE(lits[1]) , LHS.lits[1] += RHS.lits[1]) \ + STAT(NO_ARG , "lits_other" , VALUE(lits[2]) , LHS.lits[2] += RHS.lits[2]) \ + STAT(JumpStats jumps;DOXY(backjump statistics) , "jumps" , MAP(jumps) , LHS.jumps.accu(RHS.jumps)) + + ExtendedStats() { reset(); } + void reset(); + void addLearnt(uint32 size, type_t t) { + if (t == Constraint_t::Static) return; + learnts[t-1]+= 1; + lits[t-1] += size; + binary += (size == 2); + ternary += (size == 3); + } + //! Total number of lemmas learnt. + uint64 lemmas() const { return std::accumulate(learnts, learnts+Constraint_t::Type__max, uint64(0)); } + //! Total number of literals in all learnt lemmas. + uint64 learntLits() const { return std::accumulate(lits, lits+Constraint_t::Type__max, uint64(0)); } + //! Number of lemmas of learnt type t. + uint64 lemmas(type_t t)const { return learnts[t-1]; } + //! Average length of lemmas of learnt type t. + double avgLen(type_t t)const { return ratio(lits[t-1], lemmas(t)); } + //! Average decision level on which models were found. + double avgModel() const { return ratio(modelLits, models); } + //! Ratio of lemmas that were distributed to other threads. + double distRatio() const { return ratio(distributed, learnts[0] + learnts[1]); } + //! Average lbd of lemmas that were distributed to other threads. + double avgDistLbd() const { return ratio(sumDistLbd, distributed); } + double avgIntJump() const { return ratio(intJumps, intImps); } + //! Average length (i.e. number of literals) of guiding paths. + double avgGp() const { return ratio(gpLits, gps); } + //! Ratio of lemmas integrated. + double intRatio() const { return ratio(integrated, distributed); } + CLASP_DECLARE_ISTATS(ExtendedStats); + CLASP_EXTENDED_STATS(CLASP_STAT_DEFINE,NO_ARG,NO_ARG) +}; + +//! A struct for aggregating statistics maintained in a solver object. +struct SolverStats : public CoreStats { + SolverStats(); + SolverStats(const SolverStats& o); + ~SolverStats(); + bool enableExtended(); + bool enable(const SolverStats& o) { return !o.extra || enableExtended(); } + void enableLimit(uint32 size); + void reset(); + void accu(const SolverStats& o); + void accu(const SolverStats& o, bool enableRhs); + void swapStats(SolverStats& o); + void flush() const; + uint32 size() const; + const char* key(uint32 i) const; + StatisticObject at(const char* key) const; + void addTo(const char* key, StatsMap& solving, StatsMap* accu) const; + inline void addLearnt(uint32 size, ConstraintType t); + inline void addConflict(uint32 dl, uint32 uipLevel, uint32 bLevel, uint32 lbd); + inline void addDeleted(uint32 num); + inline void addDistributed(uint32 lbd, ConstraintType t); + inline void addTest(bool partial); + inline void addModel(uint32 decisionLevel); + inline void addCpuTime(double t); + inline void addSplit(uint32 num = 1); + inline void addDomChoice(uint32 num = 1); + inline void addIntegratedAsserting(uint32 receivedDL, uint32 jumpDL); + inline void addIntegrated(uint32 num = 1); + inline void removeIntegrated(uint32 num = 1); + inline void addPath(const LitVec::size_type& sz); + DynamicLimit* limit; /**< Optional dynamic limit. */ + ExtendedStats* extra; /**< Optional extended statistics. */ + SolverStats* multi; /**< Not owned: set to accu stats in multishot solving. */ +private: SolverStats& operator=(const SolverStats&); +}; +inline void SolverStats::addLearnt(uint32 size, ConstraintType t) { if (extra) { extra->addLearnt(size, t); } } +inline void SolverStats::addDeleted(uint32 num) { if (extra) { extra->deleted += num; } } +inline void SolverStats::addDistributed(uint32 lbd, ConstraintType){ if (extra) { ++extra->distributed; extra->sumDistLbd += lbd; } } +inline void SolverStats::addIntegrated(uint32 n) { if (extra) { extra->integrated += n;} } +inline void SolverStats::removeIntegrated(uint32 n) { if (extra) { extra->integrated -= n;} } +inline void SolverStats::addCpuTime(double t) { if (extra) { extra->cpuTime += t; } } +inline void SolverStats::addSplit(uint32 num) { if (extra) { extra->splits += num; } } +inline void SolverStats::addPath(const LitVec::size_type& sz) { if (extra) { ++extra->gps; extra->gpLits += sz; } } +inline void SolverStats::addTest(bool partial) { if (extra) { ++extra->hccTests; extra->hccPartial += (uint32)partial; } } +inline void SolverStats::addModel(uint32 DL) { if (extra) { ++extra->models; extra->modelLits += DL; } } +inline void SolverStats::addDomChoice(uint32 n) { if (extra) { extra->domChoices += n; } } +inline void SolverStats::addIntegratedAsserting(uint32 rDL, uint32 jDL) { + if (extra) { ++extra->intImps; extra->intJumps += (rDL - jDL); } +} +inline void SolverStats::addConflict(uint32 dl, uint32 uipLevel, uint32 bLevel, uint32 lbd) { + ++analyzed; + if (limit) { limit->update(dl, lbd); } + if (extra) { extra->jumps.update(dl, uipLevel, bLevel); } +} +#undef CLASP_STAT_DEFINE +#undef NO_ARG +#undef DOXY +#undef CLASP_DECLARE_ISTATS +/////////////////////////////////////////////////////////////////////////////// +// Clauses +/////////////////////////////////////////////////////////////////////////////// +//! Primitive representation of a clause. +struct ClauseRep { + typedef ConstraintInfo Info; + static ClauseRep create(Literal* cl, uint32 sz, const Info& i = Info()) { return ClauseRep(cl, sz, false, i);} + static ClauseRep prepared(Literal* cl, uint32 sz, const Info& i = Info()){ return ClauseRep(cl, sz, true, i); } + ClauseRep(Literal* cl = 0, uint32 sz = 0, bool p = false, const Info& i = Info()) : info(i), size(sz), prep(uint32(p)), lits(cl) {} + Info info; /*!< Additional clause info. */ + uint32 size:31; /*!< Size of array of literals. */ + uint32 prep: 1; /*!< Whether lits is already prepared. */ + Literal* lits; /*!< Pointer to array of literals (not owned!). */ + bool isImp() const { return size > 1 && size < 4; } +}; + +//! (Abstract) base class for clause types. +/*! + * ClauseHead is used to enforce a common memory-layout for all clauses. + * It contains the two watched literals and a cache literal to improve + * propagation performance. A virtual call to Constraint::propagate() + * is only needed if the other watch is not true and the cache literal + * is false. + */ +class ClauseHead : public Constraint { +public: + enum { HEAD_LITS = 3, MAX_SHORT_LEN = 5 }; + explicit ClauseHead(const InfoType& init); + // base interface + //! Propagates the head and calls updateWatch() if necessary. + PropResult propagate(Solver& s, Literal, uint32& data); + //! Type of clause. + Type type() const { return info_.type(); } + //! Returns the activity of this clause. + ScoreType activity() const { return info_.score(); } + //! True if this clause currently is the antecedent of an assignment. + bool locked(const Solver& s) const; + //! Halves the activity of this clause. + void decreaseActivity() { info_.score().reduce(); } + void resetActivity() { info_.score().reset(); } + //! Downcast from LearntConstraint. + ClauseHead* clause() { return this; } + + // clause interface + typedef std::pair BoolPair; + //! Adds watches for first two literals in head to solver. + void attach(Solver& s); + void resetScore(ScoreType sc); + //! Returns true if head is satisfied w.r.t current assignment in s. + bool satisfied(const Solver& s) const; + //! Conditional clause? + bool tagged() const { return info_.tagged(); } + //! Contains aux vars? + bool aux() const { return info_.aux(); } + bool learnt() const { return info_.learnt(); } + uint32 lbd() const { return info_.lbd(); } + //! Removes watches from s. + virtual void detach(Solver& s); + //! Returns the size of this clause. + virtual uint32 size() const = 0; + //! Returns the literals of this clause in out. + virtual void toLits(LitVec& out) const = 0; + //! Returns true if this clause is a valid "reverse antecedent" for p. + virtual bool isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN) = 0; + //! Removes p from clause if possible. + /*! + * \return + * The first component of the returned pair specifies whether or not + * p was removed from the clause. + * The second component of the returned pair specifies whether + * the clause should be kept (false) or removed (true). + */ + virtual BoolPair strengthen(Solver& s, Literal p, bool allowToShort = true) = 0; +protected: + struct Local { + void init(uint32 sz); + bool isSmall() const { return (mem[0] & 1u) == 0u; } + bool contracted() const { return (mem[0] & 3u) == 3u; } + bool strengthened()const { return (mem[0] & 5u) == 5u; } + uint32 size() const { return mem[0] >> 3; } + void setSize(uint32 size) { mem[0] = (size << 3) | (mem[0] & 7u); } + void markContracted() { mem[0] |= 2u; } + void markStrengthened() { mem[0] |= 4u; } + void clearContracted() { mem[0] &= ~2u; } + void clearIdx() { mem[1] = 0; } + uint32 mem[2]; + }; + bool toImplication(Solver& s); + void clearTagged() { info_.setTagged(false); } + void setLbd(uint32 x) { info_.setLbd(x); } + //! Shall replace the watched literal at position pos with a non-false literal. + /*! + * \pre pos in [0,1] + * \pre s.isFalse(head_[pos]) && s.isFalse(head_[2]) + * \pre head_[pos^1] is the other watched literal + */ + virtual bool updateWatch(Solver& s, uint32 pos) = 0; + union { + Local local_; + SharedLiterals* shared_; + }; + InfoType info_; + Literal head_[HEAD_LITS]; // two watched literals and one cache literal +}; +//! Allocator for small (at most 32-byte) clauses. +class SmallClauseAlloc { +public: + SmallClauseAlloc(); + ~SmallClauseAlloc(); + void* allocate() { + if(freeList_ == 0) { + allocBlock(); + } + Chunk* r = freeList_; + freeList_ = r->next; + return r; + } + void free(void* mem) { + Chunk* b = reinterpret_cast(mem); + b->next = freeList_; + freeList_= b; + } +private: + SmallClauseAlloc(const SmallClauseAlloc&); + SmallClauseAlloc& operator=(const SmallClauseAlloc&); + struct Chunk { + Chunk* next; // enforce ptr alignment + unsigned char mem[32 - sizeof(Chunk*)]; + }; + struct Block { + enum { num_chunks = 1023 }; + Block* next; + unsigned char pad[32-sizeof(Block*)]; + Chunk chunk[num_chunks]; + }; + void allocBlock(); + Block* blocks_; + Chunk* freeList_; +}; +/////////////////////////////////////////////////////////////////////////////// +// Watches +/////////////////////////////////////////////////////////////////////////////// +//! Represents a clause watch in a Solver. +struct ClauseWatch { + //! Clause watch: clause head + explicit ClauseWatch(ClauseHead* a_head) : head(a_head) { } + ClauseHead* head; + struct EqHead { + explicit EqHead(ClauseHead* h) : head(h) {} + bool operator()(const ClauseWatch& w) const { return head == w.head; } + ClauseHead* head; + }; +}; + +//! Represents a generic watch in a Solver. +struct GenericWatch { + //! A constraint and some associated data. + explicit GenericWatch(Constraint* a_con, uint32 a_data = 0) : con(a_con), data(a_data) {} + //! Calls propagate on the stored constraint and passes the stored data to that constraint. + Constraint::PropResult propagate(Solver& s, Literal p) { return con->propagate(s, p, data); } + + Constraint* con; /**< The constraint watching a certain literal. */ + uint32 data; /**< Additional data associated with this watch - passed to constraint on update. */ + + struct EqConstraint { + explicit EqConstraint(Constraint* c) : con(c) {} + bool operator()(const GenericWatch& w) const { return con == w.con; } + Constraint* con; + }; +}; + +//! Watch list type. +typedef bk_lib::left_right_sequence WatchList; +inline void releaseVec(WatchList& w) { w.clear(true); } + +/////////////////////////////////////////////////////////////////////////////// +// Assignment +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +//! Type for storing reasons for variable assignments together with additional data. +/*! + * \note On 32-bit systems additional data is stored in the high-word of antecedents. + */ +struct ReasonStore32 : PodVector::type { + uint32 data(uint32 v) const { return decode((*this)[v]);} + void setData(uint32 v, uint32 data) { encode((*this)[v], data); } + static void encode(Antecedent& a, uint32 data) { + a.asUint() = (uint64(data)<<32) | static_cast(a.asUint()); + } + static uint32 decode(const Antecedent& a) { + return static_cast(a.asUint()>>32); + } + struct value_type { + value_type(const Antecedent& a, uint32 d) : ante_(a) { + if (d != UINT32_MAX) { encode(ante_, d); assert(data() == d && ante_.type() == Antecedent::Generic); } + } + const Antecedent& ante() const { return ante_; } + uint32 data() const { return ante_.type() == Antecedent::Generic ? decode(ante_) : UINT32_MAX; } + Antecedent ante_; + }; +}; + +//! Type for storing reasons for variable assignments together with additional data. +/* + * \note On 64-bit systems additional data is stored in a separate container. + */ +struct ReasonStore64 : PodVector::type { + uint32 dataSize() const { return (uint32)data_.size(); } + void dataResize(uint32 nv) { if (nv > dataSize()) data_.resize(nv, UINT32_MAX); } + uint32 data(uint32 v) const { return v < dataSize() ? data_[v] : UINT32_MAX; } + void setData(uint32 v, uint32 data) { dataResize(v+1); data_[v] = data; } + VarVec data_; + struct value_type : std::pair { + value_type(const Antecedent& a, uint32 d) : std::pair(a, d) {} + const Antecedent& ante() const { return first; } + uint32 data() const { return second; } + }; +}; + +//! A set of configurable values for a variable. +/*! + * Beside its currently assigned value, a variable + * can also have a user, saved, preferred, and default value. + * These values are used in sign selection to determine the signed literal + * of a variable to be assign first. + * During sign selection, the values form a hierarchy: + * user > saved > preferred > current sign score of heuristic > default value + */ +struct ValueSet { + ValueSet() : rep(0) {} + enum Value { user_value = 0x03u, saved_value = 0x0Cu, pref_value = 0x30u, def_value = 0xC0u }; + bool sign() const { return (right_most_bit(rep) & 0xAAu) != 0; } + bool empty() const { return rep == 0; } + bool has(Value v) const { return (rep & v) != 0; } + bool has(uint32 f)const { return (rep & f) != 0; } + ValueRep get(Value v) const { return static_cast((rep & v) / right_most_bit(static_cast(v))); } + void set(Value which, ValueRep to) { rep &= ~which; rep |= (to * right_most_bit(static_cast(which))); } + void save(ValueRep x) { rep &= ~saved_value; rep |= (x << 2); } + uint8 rep; +}; + +//! Stores assignment related information. +/*! + * For each variable v, the class stores + * - v's current value (value_free if unassigned) + * - the decision level on which v was assign (only valid if value(v) != value_free) + * - the reason why v is in the assignment (only valid if value(v) != value_free) + * - (optionally) some additional data associated with the reason + * . + * Furthermore, the class stores the sequences of assignments as a set of + * true literals in its trail-member. + */ +class Assignment { +public: + typedef PodVector::type AssignVec; + typedef PodVector::type PrefVec; + typedef bk_lib::detail::if_then_else< + sizeof(Constraint*)==sizeof(uint64) + , ReasonStore64 + , ReasonStore32>::type ReasonVec; + typedef ReasonVec::value_type ReasonWithData; + Assignment() : front(0), elims_(0), units_(0) { } + LitVec trail; // assignment sequence + uint32 front; // and "propagation queue" + bool qEmpty() const { return front == static_cast(trail.size()); } + uint32 qSize() const { return static_cast(trail.size() - front); } + Literal qPop() { return trail[front++]; } + void qReset() { front = static_cast(trail.size()); } + + //! Number of variables in the three-valued assignment. + uint32 numVars() const { return (uint32)assign_.size(); } + //! Number of assigned variables. + uint32 assigned() const { return (uint32)trail.size(); } + //! Number of free variables. + uint32 free() const { return numVars() - (assigned()+elims_); } + //! Returns the largest possible decision level. + uint32 maxLevel() const { return (1u<<28)-2; } + //! Returns v's value in the three-valued assignment. + ValueRep value(Var v) const { return ValueRep(assign_[v] & 3u); } + //! Returns the decision level on which v was assigned if value(v) != value_free. + uint32 level(Var v) const { return assign_[v] >> 4u; } + //! Returns true if v was not eliminated from the assignment. + bool valid(Var v) const { return (assign_[v] & elim_mask) != elim_mask; } + //! Returns the set of preferred values of v. + const ValueSet pref(Var v) const { return v < pref_.size() ? pref_[v] : ValueSet(); } + //! Returns the reason for v being assigned if value(v) != value_free. + const Antecedent& reason(Var v)const { return reason_[v]; } + //! Returns the reason data associated with v. + uint32 data(Var v) const { return reason_.data(v); } + + void reserve(uint32 n) { + assign_.reserve(n); + reason_.reserve(n); + } + //! Resize to nv variables. + void resize(uint32 nv) { + assign_.resize(nv); + reason_.resize(nv); + } + //! Adds a var to assignment - initially the new var is unassigned. + Var addVar() { + assign_.push_back(0); + reason_.push_back(0); + return numVars()-1; + } + //! Allocates space for storing preferred values for all variables. + void requestPrefs() { + if (pref_.size() != assign_.size()) { pref_.resize(assign_.size()); } + } + //! Eliminates v from the assignment. + void eliminate(Var v) { + assert(value(v) == value_free && "Can not eliminate assigned var!\n"); + if (valid(v)) { assign_[v] = elim_mask|value_true; ++elims_; } + } + //! Assigns p.var() on level lev to the value that makes p true and stores x as reason for the assignment. + /*! + * \return true if the assignment is consistent. False, otherwise. + * \post If true is returned, p is in trail. Otherwise, ~p is. + */ + bool assign(Literal p, uint32 lev, const Antecedent& x) { + const Var v = p.var(); + const ValueRep val = value(v); + if (val == value_free) { + assert(valid(v)); + assign_[v] = (lev<<4) + trueValue(p); + reason_[v] = x; + trail.push_back(p); + return true; + } + return val == trueValue(p); + } + bool assign(Literal p, uint32 lev, Constraint* c, uint32 data) { + const Var v = p.var(); + const ValueRep val = value(v); + if (val == value_free) { + assert(valid(v)); + assign_[v] = (lev<<4) + trueValue(p); + reason_[v] = c; + reason_.setData(v, data); + trail.push_back(p); + return true; + } + return val == trueValue(p); + } + //! Undos all assignments in the range trail[first, last). + /*! + * \param first First assignment to be undone. + * \param save If true, previous assignment of a var is saved before it is undone. + */ + void undoTrail(LitVec::size_type first, bool save) { + if (!save) { popUntil<&Assignment::clear>(trail[first]); } + else { requestPrefs(); popUntil<&Assignment::saveAndClear>(trail[first]); } + qReset(); + } + //! Undos the last assignment. + void undoLast() { clear(trail.back().var()); trail.pop_back(); } + //! Returns the last assignment as a true literal. + Literal last() const { return trail.back(); } + Literal&last() { return trail.back(); } + /*! + * \name Implementation functions + * Low-level implementation functions. Use with care and only if you + * know what you are doing! + */ + //@{ + uint32 units() const { return units_; } + bool seen(Var v, uint8 m) const { return (assign_[v] & (m<<2)) != 0; } + void setSeen(Var v, uint8 m) { assign_[v] |= (m<<2); } + void clearSeen(Var v) { assign_[v] &= ~uint32(12); } + void clearValue(Var v) { assign_[v] &= ~uint32(3); } + void setValue(Var v, ValueRep val) { + assert(value(v) == val || value(v) == value_free); + assign_[v] |= val; + } + void setReason(Var v, const Antecedent& a) { reason_[v] = a; } + void setData(Var v, uint32 data) { reason_.setData(v, data); } + void setPref(Var v, ValueSet::Value which, ValueRep to) { pref_[v].set(which, to); } + void copyAssignment(Assignment& o) const { o.assign_ = assign_; } + bool markUnits() { while (units_ != front) { setSeen(trail[units_++].var(), 3u); } return true; } + void setUnits(uint32 ts) { units_ = ts; } + void resetPrefs() { pref_.assign(pref_.size(), ValueSet()); } + void clear(Var v) { assign_[v] = 0; } + void saveAndClear(Var v) { pref_[v].save(value(v)); clear(v); } + //@} +private: + static const uint32 elim_mask = uint32(0xFFFFFFF0u); + Assignment(const Assignment&); + Assignment& operator=(const Assignment&); + template + void popUntil(Literal stop) { + Literal p; + do { + p = trail.back(); trail.pop_back(); + (this->*op)(p.var()); + } while (p != stop); + } + AssignVec assign_; // for each var: three-valued assignment + ReasonVec reason_; // for each var: reason for being assigned (+ optional data) + PrefVec pref_; // for each var: set of preferred values + uint32 elims_; // number of variables that were eliminated from the assignment + uint32 units_; // number of marked top-level assignments +}; + +//! Stores information about a literal that is implied on an earlier level than the current decision level. +struct ImpliedLiteral { + typedef Assignment::ReasonWithData AnteInfo; + ImpliedLiteral(Literal a_lit, uint32 a_level, const Antecedent& a_ante, uint32 a_data = UINT32_MAX) + : lit(a_lit) + , level(a_level) + , ante(a_ante, a_data) { + } + Literal lit; /**< The implied literal */ + uint32 level; /**< The earliest decision level on which lit is implied */ + AnteInfo ante; /**< The reason why lit is implied on decision-level level */ +}; +//! A type for storing ImpliedLiteral objects. +struct ImpliedList { + typedef PodVector::type VecType; + typedef VecType::const_iterator iterator; + ImpliedList() : level(0), front(0) {} + //! Searches for an entry

in list. Returns 0 if none is found. + ImpliedLiteral* find(Literal p) { + for (VecType::size_type i = 0, end = lits.size(); i != end; ++i) { + if (lits[i].lit == p) { return &lits[i]; } + } + return 0; + } + //! Adds a new object to the list. + void add(uint32 dl, const ImpliedLiteral& n) { + if (dl > level) { level = dl; } + lits.push_back(n); + } + //! Returns true if list contains entries that must be reassigned on current dl. + bool active(uint32 dl) const { return dl < level && front != lits.size(); } + //! Reassigns all literals that are still implied. + bool assign(Solver& s); + iterator begin() const { return lits.begin(); } + iterator end() const { return lits.end(); } + VecType lits; // current set of (out-of-order) implied literals + uint32 level; // highest dl on which lits must be reassigned + uint32 front; // current starting position in lits +}; +//@} +} +#endif diff --git a/libclasp/clasp/statistics.h b/libclasp/clasp/statistics.h new file mode 100644 index 0000000..d66e3bb --- /dev/null +++ b/libclasp/clasp/statistics.h @@ -0,0 +1,301 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +//! \file +//! \brief Types and functions for accessing statistics. +#ifndef CLASP_STATISTICS_H_INCLUDED +#define CLASP_STATISTICS_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif +#include +#include +#include +#include +namespace Clasp { + +template +double _getValue(const T* v) { return static_cast(*v); } + +//! Discriminated union representing either a single statistic value or a composite. +class StatisticObject { +public: + typedef Potassco::Statistics_t Type; + struct Hasher { std::size_t operator()(const StatisticObject& o) const { return o.hash(); } }; + //! Creates an empty (invalid) object. + StatisticObject(); + //! Creates a Value object - static_cast(*obj) shall be valid. + template + static StatisticObject value(const T* obj) { + return value(obj); + } + //! Creates a mapped Value object: f(obj) -> double + template + static StatisticObject value(const T* obj) { + return StatisticObject(obj, registerValue()); + } + //! Creates a Map object. + /*! + * The following expression shall be valid: + * obj->size(): shall return the number of keys in obj + * obj->key(i): shall return the i'th key of this object (i >= 0). + * obj->at(const char* k): shall return the StatisticObject under the given key. + * If k is invalid, shall either throw an exception or return an empty object. + */ + template + static StatisticObject map(const T* obj) { + return StatisticObject(obj, registerMap()); + } + //! Creates an Array object. + /*! + * The following expression shall be valid: + * obj->size(): shall return the size of the array. + * obj->at(i): shall return the StatisticObject under the given key i >= 0. + * If k is invalid, shall either throw an exception or return an empty object. + */ + template + static StatisticObject array(const T* obj) { + return StatisticObject(obj, registerArray()); + } + //! Returns the type of this object. + Type type() const; + //! Returns whether this object is empty. + bool empty() const; + //! Returns the number of children of this object or 0 if this is not a composite object. + uint32 size() const; + + /*! + * \name Map + * \pre type() == Map + */ + //@{ + //! Returns the i'th key of this map. + /*! + * \pre i < size() + */ + const char* key(uint32 i) const; + //! Returns the object under the given key. + /*! + * \pre k in key([0..size())) + */ + StatisticObject at(const char* k) const; + //@} + + //! Returns the object at the given index. + /*! + * \pre Type() == Array + * \pre i < size() + */ + StatisticObject operator[](uint32 i) const; + + //! Returns the value of this object. + /*! + * \pre type() == Value + */ + double value() const; + + bool operator==(const StatisticObject& rhs) const { + return this->handle_ == rhs.handle_; + } + bool operator<(const StatisticObject& rhs) const { + return this->handle_ < rhs.handle_; + } + std::size_t hash() const; + uint64 toRep() const; + static StatisticObject fromRep(uint64); +private: + struct I { + typedef const void* ObjPtr; + explicit I(Type t) : type(t) {} + Type type; + }; + struct V : I { + V(double(*v)(ObjPtr)) : I(Potassco::Statistics_t::Value), value(v) {} + double(*value)(ObjPtr); + }; + struct A : I { + A(uint32(*sz)(ObjPtr), StatisticObject(*a)(ObjPtr, uint32)) : I(Potassco::Statistics_t::Array), size(sz), at(a) {} + uint32(*size)(ObjPtr); + StatisticObject(*at)(ObjPtr, uint32); + }; + struct M : I { + M(uint32(*sz)(ObjPtr), StatisticObject(*a)(ObjPtr, const char*), const char* (*k)(ObjPtr, uint32)) : I(Potassco::Statistics_t::Map), size(sz), at(a), key(k) {} + uint32(*size)(ObjPtr); + StatisticObject(*at)(ObjPtr, const char*); + const char* (*key)(ObjPtr, uint32); + }; + static uint32 registerType(const I* vtab) { + types_.push_back(vtab); + return static_cast(types_.size() - 1); + } + template + static uint32 registerValue(); + template + static uint32 registerMap(); + template + static uint32 registerArray(); + StatisticObject(const void* obj, uint32 type); + + typedef PodVector::type RegVec; + const void* self() const; + const I* tid() const; + static RegVec types_; + uint64 handle_; +}; + +template +uint32 StatisticObject::registerArray() { + static struct Array_T : A { + Array_T() : A(&Array_T::size, &Array_T::at) {} + static uint32 size(ObjPtr obj) { return toU32(static_cast(obj)->size()); } + static StatisticObject at(ObjPtr obj, uint32 i) { return static_cast(obj)->at(i); } + } vtab_s; + static uint32 id = registerType(&vtab_s); + return id; +} +template +uint32 StatisticObject::registerMap() { + static struct Map_T : M { + Map_T() : M(&Map_T::size, &Map_T::at, &Map_T::key) {} + static inline const T* cast(ObjPtr obj) { return static_cast(obj); } + static uint32 size(ObjPtr obj) { return cast(obj)->size(); } + static StatisticObject at(ObjPtr obj, const char* k) { return cast(obj)->at(k); } + static const char* key(ObjPtr obj, uint32 i) { return cast(obj)->key(i); } + } vtab_s; + static uint32 id = registerType(&vtab_s); + return id; +} + +template +uint32 StatisticObject::registerValue() { + static struct Value_T : V { + Value_T() : V(&Value_T::value) {} + static double value(ObjPtr obj) { return f(static_cast(obj)); } + } vtab_s; + static uint32 id = StatisticObject::registerType(&vtab_s); + return id; +} +//! A type that maps string keys to statistic objects. +class StatsMap { +public: + // StatisticObject + uint32 size() const { return sizeVec(keys_); } + const char* key(uint32 i) const { return keys_.at(i).first; } + StatisticObject at(const char* k) const; + // Own interface + const StatisticObject* find(const char* k) const; + bool add(const char* k, const StatisticObject&); + StatisticObject toStats() const { return StatisticObject::map(this); } +private: + typedef PodVector >::type MapType; + MapType keys_; +}; +//! An array of statistic objects. +template +class StatsVec : private PodVector::type { +public: + StatsVec() : own_(true) {} + ~StatsVec() { + if (own_) { for (iterator it = this->begin(), end = this->end(); it != end; ++it) { delete *it; } } + } + typedef typename PodVector::type base_type; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::iterator iterator; + using base_type::size; + using base_type::operator[]; + using base_type::begin; + using base_type::end; + void growTo(uint32 newSize) { if (newSize > size()) this->resize(newSize); } + void reset() { for (iterator it = this->begin(), end = this->end(); it != end; ++it) { (*it)->reset(); } } + StatisticObject at(uint32 i) const { return get_(this->base_type::at(i), bk_lib::detail::int2type()); } + StatisticObject toStats() const { return StatisticObject::array(this); } + void acquire() { own_ = true; } + void release() { own_ = false; } +private: + static StatisticObject get_(const T* ptr, bk_lib::detail::int2type) { return StatisticObject::map(ptr); } + static StatisticObject get_(const T* ptr, bk_lib::detail::int2type) { return StatisticObject::array(ptr); } + static StatisticObject get_(const T* ptr, bk_lib::detail::int2type) { return StatisticObject::value(ptr); } + StatsVec(const StatsVec&); + StatsVec& operator=(const StatsVec&); + bool own_; +}; + +//! A class for traversing and querying statistics. +/*! + * \ingroup clingo + */ +class ClaspStatistics : public Potassco::AbstractStatistics { +public: + typedef Potassco::Statistics_t Type; + ClaspStatistics(); + ~ClaspStatistics(); + // Base interface + virtual Key_t root() const; + virtual Type type(Key_t key) const; + virtual size_t size(Key_t key) const; + virtual Key_t at(Key_t arrK, size_t index) const; + virtual const char* key(Key_t mapK, size_t i) const; + virtual Key_t get(Key_t mapK, const char* key) const; + virtual double value(Key_t key) const; + + // Register interface + Key_t setRoot(const StatisticObject&); + bool removeStat(const StatisticObject&, bool recurse); + bool removeStat(Key_t k, bool recurse); + void update(); + StatisticObject findObject(Key_t root, const char* path, Key_t* track = 0) const; + StatisticObject getObject(Key_t k) const; +private: + ClaspStatistics(const ClaspStatistics&); + ClaspStatistics& operator=(const ClaspStatistics&); + Key_t root_; + struct Impl; + Impl* impl_; +}; + +struct SolverStats; +struct JumpStats; +struct ExtendedStats; +struct ProblemStats; + +//! Interface for visiting statistics. +/*! + * \ingroup facade + */ +class StatsVisitor { +public: + enum Operation { Enter, Leave } ; + virtual ~StatsVisitor(); + // compound + virtual bool visitGenerator(Operation op); // default: return true + virtual bool visitThreads(Operation op); // default: return true + virtual bool visitTester(Operation op); // default: return true + virtual bool visitHccs(Operation op); // default: return true + + // leafs + virtual void visitThread(uint32, const SolverStats& stats); + virtual void visitHcc(uint32, const ProblemStats& p, const SolverStats& s); + virtual void visitLogicProgramStats(const Asp::LpStats& stats) = 0; + virtual void visitProblemStats(const ProblemStats& stats) = 0; + virtual void visitSolverStats(const SolverStats& stats) = 0; +}; + +} +#endif diff --git a/libclasp/clasp/unfounded_check.h b/libclasp/clasp/unfounded_check.h new file mode 100644 index 0000000..875b5f2 --- /dev/null +++ b/libclasp/clasp/unfounded_check.h @@ -0,0 +1,306 @@ +// +// Copyright (c) 2010, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_UNFOUNDED_CHECK_H_INCLUDED +#define CLASP_UNFOUNDED_CHECK_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif +#include +#include +#include +#include +namespace Clasp { +class LoopFormula; + +//! Clasp's default unfounded set checker. +/*! + * \ingroup propagator + * Searches for unfounded atoms by checking the positive dependency graph (PDG) + * + * Basic Idea: + * - For each (non-false) atom a, let source(a) be a body B in body(a) that provides an external support for a + * - If no such B exists, a must be false + * - If source(a) becomes false and a is not false: + * - Let Q = {}; + * - add a to Q + * - For each B' s.th B' is not external to Q + * - add { a' | source(a') = B } to Q + * - Try to find new sources for all atoms a in Q + */ +class DefaultUnfoundedCheck : public PostPropagator { +public: + typedef Asp::PrgDepGraph DependencyGraph; + typedef DependencyGraph::NodeId NodeId; + typedef DependencyGraph::BodyNode BodyNode; + typedef DependencyGraph::AtomNode AtomNode; + typedef const DependencyGraph* ConstGraphPtr; + typedef DependencyGraph* GraphPtr; + //! Defines the supported reasons for explaining assignments. + enum ReasonStrategy { + common_reason = LoopReason_t::Explicit, /*!< one reason for each unfounded set but one clause for each atom */ + only_reason = LoopReason_t::Implicit, /*!< store only the reason but don't learn a nogood */ + distinct_reason, /*!< distinct reason and clause for each unfounded atom */ + shared_reason, /*!< one shared loop formula for each unfounded set */ + no_reason, /*!< do no compute reasons for unfounded sets (only valid if learning is disabled!) */ + }; + + explicit DefaultUnfoundedCheck(DependencyGraph& graph, ReasonStrategy st = common_reason); + ~DefaultUnfoundedCheck(); + + ReasonStrategy reasonStrategy() const { return strategy_; } + void setReasonStrategy(ReasonStrategy rs); + + ConstGraphPtr graph() const { return graph_; } + uint32 nodes() const { return static_cast(atoms_.size() + bodies_.size()); } + + // base interface + uint32 priority() const { return uint32(priority_reserved_ufs); } + bool init(Solver&); + void reset(); + bool propagateFixpoint(Solver& s, PostPropagator* ctx); + bool isModel(Solver& s); + bool valid(Solver& s); + bool simplify(Solver& s, bool); + void destroy(Solver* s, bool detach); +private: + DefaultUnfoundedCheck(const DefaultUnfoundedCheck&); + DefaultUnfoundedCheck& operator=(const DefaultUnfoundedCheck&); + enum UfsType { + ufs_none, + ufs_poly, + ufs_non_poly + }; + enum WatchType { + watch_source_false = 0, + watch_head_false = 1, + watch_head_true = 2, + watch_subgoal_false= 3, + }; + // data for each body + struct BodyData { + BodyData() : watches(0), picked(0) {} + uint32 watches : 31; // how many atoms watch this body as source? + uint32 picked : 1; // flag used in computeReason() + uint32 lower_or_ext; // unsourced preds or index of extended body + }; + struct BodyPtr { + BodyPtr(const BodyNode* n, uint32 i) : node(n), id(i) {} + const BodyNode* node; + uint32 id; + }; + // data for extended bodies + struct ExtData { + ExtData(weight_t bound, uint32 preds) : lower(bound), slack(-bound) { + for (uint32 i = 0; i != flagSize(preds); ++i) { flags[i] = 0; } + } + bool addToWs(uint32 idx, weight_t w) { + const uint32 fIdx = (idx / 32); + const uint32 m = (1u << (idx & 31)); + assert((flags[fIdx] & m) == 0); + flags[fIdx] |= m; + return (lower -= w) <= 0; + } + bool inWs(uint32 idx) const { + const uint32 fIdx = (idx / 32); + const uint32 m = (1u << (idx & 31)); + return (flags[fIdx] & m) != 0; + } + void removeFromWs(uint32 idx, weight_t w) { + if (inWs(idx)) { + lower += w; + flags[(idx / 32)] &= ~(uint32(1) << (idx & 31)); + } + } + static uint32 flagSize(uint32 preds) { return (preds+31)/32; } + weight_t lower; + weight_t slack; +CLASP_WARNING_BEGIN_RELAXED + uint32 flags[0]; +CLASP_WARNING_END_RELAXED + }; + // data for each atom + struct AtomData { + AtomData() : source(nill_source), todo(0), ufs(0), validS(0) {} + // returns the body that is currently watched as possible source + NodeId watch() const { return source; } + // returns true if atom has currently a source, i.e. a body that can still define it + bool hasSource() const { return validS; } + // mark source as invalid but keep the watch + void markSourceInvalid() { validS = 0; } + // restore validity of source + void resurrectSource() { validS = 1; } + // sets b as source for this atom + void setSource(NodeId b) { + source = b; + validS = 1; + } + static const uint32 nill_source = (uint32(1) << 29)-1; + uint32 source : 29; // id of body currently watched as source + uint32 todo : 1; // in todo-queue? + uint32 ufs : 1; // in ufs-queue? + uint32 validS : 1; // is source valid? + }; + // Watch-structure used to update extended bodies affected by literal assignments + struct ExtWatch { + NodeId bodyId; + uint32 data; + }; + // Minimality checker for disjunctive logic programs. + struct MinimalityCheck { + typedef SolveParams::FwdCheck FwdCheck; + explicit MinimalityCheck(const FwdCheck& fwd); + bool partialCheck(uint32 level); + void schedNext(uint32 level, bool ok); + FwdCheck fwd; + uint32 high; + uint32 low; + uint32 next; + uint32 scc; + }; + // ------------------------------------------------------------------------------------------- + // constraint interface + PropResult propagate(Solver&, Literal, uint32& data) { + uint32 index = data >> 2; + uint32 type = (data & 3u); + if (type != watch_source_false || bodies_[index].watches) { + invalidQ_.push_back(data); + } + return PropResult(true, true); + } + void reason(Solver& s, Literal, LitVec&); + // ------------------------------------------------------------------------------------------- + // initialization + BodyPtr getBody(NodeId bId) const { return BodyPtr(&graph_->getBody(bId), bId); } + void initBody(const BodyPtr& n); + void initExtBody(const BodyPtr& n); + void initSuccessors(const BodyPtr& n, weight_t lower); + void addWatch(Literal, uint32 data, WatchType type); + void addExtWatch(Literal p, const BodyPtr& n, uint32 data); + struct InitExtWatches { + void operator()(Literal p, uint32 idx, bool ext) const { + extra->slack += B->node->pred_weight(idx, ext); + self->addExtWatch(~p, *B, (idx<<1)+uint32(ext)); + if (ext && !self->solver_->isFalse(p)) { + extra->addToWs(idx, B->node->pred_weight(idx, true)); + } + } + DefaultUnfoundedCheck* self; + const BodyPtr* B; + ExtData* extra; + }; + struct RemExtWatches { + void operator()(Literal p, uint32, bool) const { s->removeWatch(~p, self); } + Constraint* self; + Solver* s; + }; + // ------------------------------------------------------------------------------------------- + // propagating source pointers + void propagateSource(); + struct AddSource { // an atom in a body has a new source, check if body is now a valid source + explicit AddSource(DefaultUnfoundedCheck* u) : self(u) {} + // normal body + void operator()(NodeId bId) const { + BodyPtr n(self->getBody(bId)); + if (--self->bodies_[bId].lower_or_ext == 0 && !self->solver_->isFalse(n.node->lit)) { self->forwardSource(n); } + } + // extended body + void operator()(NodeId bId, uint32 idx) const; + DefaultUnfoundedCheck* self; + }; + struct RemoveSource {// an atom in a body has lost its source, check if body is no longer a valid source + explicit RemoveSource(DefaultUnfoundedCheck* u, bool add = false) : self(u), addTodo(add) {} + // normal body + void operator()(NodeId bId) const { + if (++self->bodies_[bId].lower_or_ext == 1 && self->bodies_[bId].watches != 0) { + self->forwardUnsource(self->getBody(bId), addTodo); + } + } + // extended body + void operator()(NodeId bId, uint32 idx) const; + DefaultUnfoundedCheck* self; + bool addTodo; + }; + void setSource(NodeId atom, const BodyPtr& b); + void removeSource(NodeId bodyId); + void forwardSource(const BodyPtr& n); + void forwardUnsource(const BodyPtr& n, bool add); + void updateSource(AtomData& atom, const BodyPtr& n); + // ------------------------------------------------------------------------------------------- + // finding & propagating unfounded sets + void updateAssignment(Solver& s); + bool findSource(NodeId atom); + bool isValidSource(const BodyPtr&); + void addUnsourced(const BodyPtr&); + bool falsifyUfs(UfsType t); + bool assertAtom(Literal a, UfsType t); + void computeReason(UfsType t); + void addIfReason(const BodyPtr&, uint32 uScc); + bool isExternal(const BodyPtr&, weight_t& slack) const; + void addDeltaReason(const BodyPtr& body, uint32 uScc); + void addReasonLit(Literal); + void createLoopFormula(); + struct AddReasonLit { + void operator()(Literal p, NodeId id, bool ext) const { + if (self->solver_->isFalse(p) && slack >= 0) { + slack -= node->pred_weight(id, ext); + self->addReasonLit(p); + } + } + DefaultUnfoundedCheck* self; + const BodyNode* node; + mutable weight_t slack; + }; + UfsType findUfs(Solver& s, bool checkNonHcf); + UfsType findNonHcfUfs(Solver& s); + // ------------------------------------------------------------------------------------------- + bool pushTodo(NodeId at) { return (atoms_[at].todo == 0 && (todo_.push(at), atoms_[at].todo = 1) != 0); } + bool pushUfs(NodeId at) { return (atoms_[at].ufs == 0 && (ufs_.push(at), atoms_[at].ufs = 1) != 0); } + void resetTodo() { while (!todo_.empty()){ atoms_[todo_.pop_ret()].todo = 0; } todo_.clear(); } + void resetUfs() { while (!ufs_.empty()) { atoms_[ufs_.pop_ret()].ufs = 0; } ufs_.clear(); } + // ------------------------------------------------------------------------------------------- + typedef PodVector::type AtomVec; + typedef PodVector::type BodyVec; + typedef PodVector::type ExtVec; + typedef PodVector::type WatchVec; + typedef PodQueue IdQueue; + typedef SingleOwnerPtr MiniPtr; + // ------------------------------------------------------------------------------------------- + Solver* solver_; // my solver + GraphPtr graph_; // PBADG + MiniPtr mini_; // minimality checker (only for DLPs) + AtomVec atoms_; // data for each atom + BodyVec bodies_; // data for each body + IdQueue todo_; // ids of atoms that recently lost their source + IdQueue ufs_; // ids of atoms that are unfounded wrt the current assignment (limited to one scc) + VarVec invalidQ_; // ids of invalid elements to be processed + VarVec sourceQ_; // source-pointer propagation queue + ExtVec extended_; // data for each extended body + WatchVec watches_; // watches for handling choice-, cardinality- and weight rules + VarVec pickedExt_; // extended bodies visited during reason computation + LitVec loopAtoms_; // only used if strategy_ == shared_reason + LitVec activeClause_;// activeClause_[0] is the current unfounded atom + LitVec* reasons_; // only used if strategy_ == only_reason. reasons_[v] reason why v is unfounded + ConstraintInfo info_; // info on active clause + ReasonStrategy strategy_; // what kind of reasons to compute? +}; +} +#endif diff --git a/libclasp/clasp/util/atomic.h b/libclasp/clasp/util/atomic.h new file mode 100644 index 0000000..dc6dfc3 --- /dev/null +++ b/libclasp/clasp/util/atomic.h @@ -0,0 +1,128 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_UTIL_ATOMIC_H_INCLUDED +#define CLASP_UTIL_ATOMIC_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif +/*! + * \file + * \brief Atomic types suitable for the active thread configuration. + * + * \note If libclasp is not configured with thread support, + * types from this file are not necessarily atomic and must not be accessed + * from multiple threads. + */ + +namespace Clasp { + //! Possible libclasp thread configurations. + enum ThreadConfig { + clasp_single_threaded = 0, + clasp_multi_threaded = 1 + }; + //! Type selector for selecting atomic type based on active thread configuration. + template (WITH_THREADS)> + struct Atomic_t; + + //! Selects a type that is not necessarily atomic and therefore not thread-safe. + template + struct Atomic_t { + typedef struct Plain { + T operator=(T nv) { return (val = nv); } + operator T () const { return val; } + operator T&() { return val; } + T compare_and_swap(T nVal, T eVal) { + if (val == eVal) { val = nVal; } else { eVal = val; } + return eVal; + } + T fetch_and_store(T nVal) { + T p = val; + val = nVal; + return p; + } + T val; + } type; + }; +} + +#if WITH_THREADS +/*! + * \def NS_ATOMIC + * Namespace containing the underlying atomic type. + * Can be either std or tbb depending on whether support for + * C++11 threads is enabled. + */ +#if !defined(CLASP_USE_STD_THREAD) +#include +#define NS_ATOMIC tbb +#else +#include +#define NS_ATOMIC std +#endif +namespace Clasp { namespace mt { + //! Atomic type with sequentially consistent loads and stores. + template + class atomic : private NS_ATOMIC::atomic { + public: + typedef NS_ATOMIC::atomic native_type; + native_type& native() { return *this; } + + T operator=(T value) { return native_type::operator=(value); } + operator T() const { return native_type::operator T(); } + + using native_type::operator+=; + using native_type::operator-=; + using native_type::operator++; + using native_type::operator--; +#if defined(CLASP_USE_STD_THREAD) + T compare_and_swap(T new_value, T comparand) { + native_type::compare_exchange_strong(comparand, new_value); + return comparand; + } + T fetch_and_store(T value) { return native_type::exchange(value); } + T fetch_and_or(T value) { return native_type::fetch_or(value); } + T fetch_and_and(T value) { return native_type::fetch_and(value); } +#else + using native_type::compare_and_swap; + using native_type::fetch_and_store; + T fetch_and_or(T value) { + T x; + do { x = this->load(); } while (this->compare_and_swap(x|value, x) != x); + return x; + } + T fetch_and_and(T value) { + T x; + do { x = this->load(); } while (this->compare_and_swap(x&value, x) != x); + return x; + } +#endif + }; +}} +namespace Clasp { + //! Selects an atomic ype suitable for multi-threading. + template + struct Atomic_t { + typedef Clasp::mt::atomic type; + }; +} +#undef NS_ATOMIC +#endif +#endif diff --git a/libclasp/clasp/util/hash_map.h b/libclasp/clasp/util/hash_map.h new file mode 100644 index 0000000..97540ab --- /dev/null +++ b/libclasp/clasp/util/hash_map.h @@ -0,0 +1,77 @@ +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_HASH_MAP_H_INCLUDED +#define CLASP_HASH_MAP_H_INCLUDED +#include +#include +#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER > 1500) || (defined(_LIBCPP_VERSION)) +#include +#include +#define HASH_NS std +#else +#if defined(_MSC_VER) +#include +#include +#else +#include +#include +#endif +#define HASH_NS std::tr1 +#endif + +namespace Clasp { + //! Selector for a hash (multi) map. + /*! + * \tparam K Key type of the hash map. + * \tparam V Value type of the hash map. + * \tparam H Hash function for hashing keys. + * \tparam E Comparison function for checking equality of keys. + * \note Can be replaced with std::unordered_map/unordered_multimap once we switch to C++11 + */ + template, class E = std::equal_to, class A = std::allocator< std::pair > > + struct HashMap_t { + typedef HASH_NS::unordered_map map_type; + typedef HASH_NS::unordered_multimap multi_map_type; + }; + //! Selector for a hash (multi) set. + template, class E = std::equal_to, class A = std::allocator< K > > + struct HashSet_t { + typedef HASH_NS::unordered_set set_type; + typedef HASH_NS::unordered_multiset multi_set_type; + }; + +//! Hasher for strings. +/*! + * \see http://research.microsoft.com/en-us/people/palarson/ + */ +struct StrHash { + std::size_t operator()(const char* str) const { + std::size_t h = 0; + for (const char* s = str; *s; ++s) { + h = h * 101 + static_cast(*s); + } + return h; + } +}; +//! Comparison function for C-strings to be used with hash map/set. +struct StrEq { + bool operator()(const char* lhs, const char* rhs) const { return std::strcmp(lhs, rhs) == 0; } +}; + +} +#undef HASH_NS +#endif diff --git a/libclasp/clasp/util/indexed_priority_queue.h b/libclasp/clasp/util/indexed_priority_queue.h new file mode 100644 index 0000000..1cc3ff9 --- /dev/null +++ b/libclasp/clasp/util/indexed_priority_queue.h @@ -0,0 +1,216 @@ +// +// Copyright (c) 2006-2007, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef BK_LIB_INDEXED_PRIORITY_QUEUE_H_INCLUDED +#define BK_LIB_INDEXED_PRIORITY_QUEUE_H_INCLUDED + +#ifdef _MSC_VER +#pragma warning (disable : 4267) +#pragma warning (disable : 4244) +#pragma once +#endif + +#include +#include "pod_vector.h" +namespace bk_lib { namespace detail { + +typedef std::size_t key_type; +const key_type noKey = static_cast(-1); +inline key_type heap_root() { return 0; } +inline key_type heap_left(std::size_t i) { return (i<<1)+1; } +inline key_type heap_right(std::size_t i) { return (i+1)<<1; } +inline key_type heap_parent(std::size_t i) { return (i-1)>>1; } + +} + +// Note: Uses a Max-Heap! +template < + class Cmp // sort-predicate - if Cmp(k1, k2) == true, n1 has higher priority than n2 +> +class indexed_priority_queue { +public: + typedef detail::key_type key_type; + typedef pod_vector index_container_type; + typedef std::size_t size_type; + typedef Cmp compare_type; + + explicit indexed_priority_queue( const compare_type& c = compare_type() ); + indexed_priority_queue(const indexed_priority_queue& other); + + indexed_priority_queue& operator=(const indexed_priority_queue& other) { + indices_ = other.indices_; + heap_ = other.heap_; + compare_ = other.compare_; + return *this; + } + + const compare_type& key_compare() const { + return compare_; + } + + bool empty() const { + return heap_.empty(); + } + void reserve(size_type n) { + indices_.reserve(n); + } + + void push(key_type k) { + assert( !is_in_queue(k) ); + if ((key_type)indices_.size() <= k) { + if (indices_.capacity() <= k) { indices_.reserve(((k+1)*3)>>1); } + indices_.resize(k+1, detail::noKey); + } + indices_[k] = (key_type)heap_.size(); + heap_.push_back(k); + siftup(indices_[k]); + } + + void pop() { + assert(!empty()); + key_type x = heap_[0]; + heap_[0] = heap_.back(); + indices_[heap_[0]] = 0; + indices_[x] = detail::noKey; + heap_.pop_back(); + if (heap_.size() > 1) {siftdown(0);} + } + + void clear() { + heap_.clear(); + indices_.clear(); + } + + template + void swapMem(indexed_priority_queue& o) { + clear(); + o.clear(); + heap_.swap(o.heap_); + indices_.swap(o.indices_); + } + size_type size( ) const { + return heap_.size(); + } + + key_type top() const { + assert(!empty()); + return heap_[0]; + } + + void update(key_type k) { + if (!is_in_queue(k)) { + push(k); + } + else { + siftup(indices_[k]); + siftdown(indices_[k]); + } + } + // call if priority of k has increased + void increase(key_type k) { + assert(is_in_queue(k)); + siftup(indices_[k]); + } + // call if priority of k has decreased + void decrease(key_type k) { + assert(is_in_queue(k)); + siftdown(indices_[k]); + } + + bool is_in_queue(key_type k) const { + assert(valid_key(k)); + return k < (key_type)indices_.size() && indices_[k] != detail::noKey; + } + + void remove(key_type k) { + if (is_in_queue(k)) { + key_type kInHeap = indices_[k]; + heap_[kInHeap] = heap_.back(); + indices_[heap_.back()] = kInHeap; + heap_.pop_back(); + indices_[k] = detail::noKey; + if (heap_.size() > 1 && kInHeap != (key_type)heap_.size()) { + siftup(kInHeap); + siftdown(kInHeap); + } + } + } +private: + template + friend class indexed_priority_queue; + bool valid_key(key_type k) const { + return k != detail::noKey; + } + index_container_type indices_; + index_container_type heap_; + compare_type compare_; + void siftup(key_type n) { + using namespace detail; + key_type x = heap_[n]; + key_type p = heap_parent(n); + while (n != 0 && compare_(x, heap_[p])){ + heap_[n] = heap_[p]; + indices_[heap_[n]] = n; + n = p; + p = heap_parent(n); + } + heap_[n] = x; + indices_[x] = n; + } + + void siftdown(key_type n) { + using namespace detail; + key_type x = heap_[n]; + while (heap_left(n) < (key_type)heap_.size()){ + key_type child = smaller_child(n); + if (!compare_(heap_[child], x)) { + break; + } + heap_[n] = heap_[child]; + indices_[heap_[n]] = n; + n = child; + } + heap_[n] = x; + indices_[x] = n; + } + + key_type smaller_child(size_type n) const { + using namespace detail; + return heap_right(n) < (key_type)heap_.size() && compare_(heap_[heap_right(n)], heap_[heap_left(n)]) + ? heap_right(n) + : heap_left(n); + } +}; + +template +indexed_priority_queue::indexed_priority_queue( const compare_type& c ) + : indices_() + , heap_() + , compare_(c) { +} + +template +indexed_priority_queue::indexed_priority_queue(const indexed_priority_queue& other) + : indices_(other.indices_) + , heap_(other.heap_) + , compare_(other.compare_) { +} + +} +#endif diff --git a/libclasp/clasp/util/left_right_sequence.h b/libclasp/clasp/util/left_right_sequence.h new file mode 100644 index 0000000..67d542f --- /dev/null +++ b/libclasp/clasp/util/left_right_sequence.h @@ -0,0 +1,350 @@ +// +// Copyright (c) 2010, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef BK_LIB_LEFT_RIGHT_SEQUENCE_INCLUDED +#define BK_LIB_LEFT_RIGHT_SEQUENCE_INCLUDED +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning (disable : 4200) +#endif +#include "type_manip.h" +#include +#include +#include +namespace bk_lib { namespace detail { + +// base class for left_right_sequence +// see below +template +class left_right_rep { +public: + typedef L left_type; + typedef R right_type; + typedef unsigned int size_type; + typedef L* left_iterator; + typedef const L* const_left_iterator; + typedef std::reverse_iterator right_iterator; + typedef std::reverse_iterator const_right_iterator; + + typedef typename bk_lib::detail::align_of::type left_align_type; + typedef typename bk_lib::detail::align_of::type right_align_type; +///@cond + typedef typename bk_lib::detail::if_then_else< + sizeof(left_type) >= sizeof(right_type), + left_type, + right_type>::type max_type; + typedef typename bk_lib::detail::if_then_else< + sizeof(left_align_type) >= sizeof(right_align_type), + left_align_type, + right_align_type>::type align_type; +///@endcond + left_right_rep() : buf_(0), cap_(0), free_(0), left_(0), right_(0) {} + + bool empty() const { return left_ == 0 && right_ == cap_; } + size_type left_size() const { return left_/sizeof(left_type); } + size_type right_size() const { return (cap_-right_)/sizeof(right_type); } + size_type size() const { return left_size() + right_size(); } + size_type left_capacity() const { return (cap_ / sizeof(left_type)); } + size_type right_capacity()const { return (cap_ / sizeof(right_type)); } + const_left_iterator left_begin() const { return const_left_iterator(reinterpret_cast(begin())); } + const_left_iterator left_end() const { return const_left_iterator(reinterpret_cast(buf_+left_)); } + left_iterator left_begin() { return left_iterator(reinterpret_cast(begin())); } + left_iterator left_end() { return left_iterator(reinterpret_cast(buf_+left_)); } + const_right_iterator right_begin()const { return const_right_iterator(reinterpret_cast(end())); } + const_right_iterator right_end() const { return const_right_iterator(reinterpret_cast(buf_+right_)); } + right_iterator right_begin() { return right_iterator(reinterpret_cast(end())); } + right_iterator right_end() { return right_iterator(reinterpret_cast(buf_+right_)); } + const left_type& left(size_type i)const { return *(left_begin()+i); } + left_type& left(size_type i) { return *(left_begin()+i); } + + void clear(bool releaseMem = false) { + if (releaseMem) { + release(); + buf_ = 0; + cap_ = 0; + free_ = 0; + } + left_ = 0; + right_= cap_; + } + void push_left(const left_type& x) { + if ((left_ + sizeof(left_type)) > right_) { + realloc(); + } + new (left())left_type(x); + left_ += sizeof(left_type); + } + + void push_right(const right_type& x) { + if ( (left_ + sizeof(right_type)) > right_ ) { + realloc(); + } + right_ -= sizeof(right_type); + new (right()) right_type(x); + } + void pop_left() { + assert(left_size() != 0); + left_ -= sizeof(left_type); + } + void pop_right() { + assert(right_size() != 0); + right_ += sizeof(right_type); + } + + void erase_left(left_iterator it) { + if (it != left_end()) { + left_iterator x = it++; + std::memmove(x, it, (left_end()-it)*sizeof(left_type)); + left_ -= sizeof(left_type); + } + } + void erase_left_unordered(left_iterator it) { + if (it != left_end()) { + left_ -= sizeof(left_type); + *it = *reinterpret_cast(left()); + } + } + void erase_right(right_iterator it) { + if (it != right_end()) { + right_type* r = (++it).base(); + right_type* b = reinterpret_cast(right()); + assert(r >= b); + std::memmove(b+1, b, (r-b)*sizeof(right_type)); + right_ += sizeof(right_type); + } + } + void erase_right_unordered(right_iterator it) { + if (it != right_end()) { + *it = *reinterpret_cast(right()); + right_+= sizeof(right_type); + } + } + void shrink_left(left_iterator it) { + left_ = static_cast((it - left_begin())*sizeof(left_type)); + } + void shrink_right(right_iterator it) { + buf_type* x = reinterpret_cast(it.base()); + right_ = static_cast(x - begin()); + } + enum { block_size = ((sizeof(max_type)+(sizeof(align_type)-1)) / sizeof(align_type)) * sizeof(align_type) }; +protected: + left_right_rep(const left_right_rep&) { } + left_right_rep& operator=(const left_right_rep&) { return *this; } + typedef unsigned char buf_type; + buf_type* begin() { return buf_; } + const buf_type* begin()const { return buf_; } + buf_type* end() { return buf_+cap_; } + const buf_type* end() const { return buf_+cap_; } + buf_type* left() { return buf_+left_; } + buf_type* right() { return buf_+right_; } + size_type capacity()const { return cap_ / block_size; } + size_type raw_size()const { return left_ + (cap_-right_); } + void release() { if (free_ != 0) { ::operator delete(buf_); } } + void realloc(); + buf_type* buf_; + size_type cap_ : 31; + size_type free_: 1; + size_type left_; + size_type right_; +}; + +template +void left_right_rep::realloc() { + size_type new_cap = ((capacity()*3)>>1) * block_size; + size_type min_cap = 4 * block_size; + if (new_cap < min_cap) new_cap = min_cap; + buf_type* temp = (buf_type*)::operator new(new_cap*sizeof(buf_type)); + // copy left + std::memcpy(temp, begin(), left_size()*sizeof(L)); + // copy right + size_type r = cap_ - right_; + std::memcpy(temp+(new_cap-r), right(), right_size() * sizeof(R)); + // swap + release(); + buf_ = temp; + cap_ = new_cap; + free_ = 1; + right_ = new_cap - r; +} + +// always store sequence in heap-allocated buffer +template +struct no_inline_buffer : public left_right_rep { + typedef typename left_right_rep::buf_type buf_type; + enum { inline_raw_cap = 0 }; + buf_type* extra() { return 0; } +}; + +// store small sequences directly inside of object +template +struct with_inline_buffer : public left_right_rep { + typedef typename left_right_rep::buf_type buf_type; + typedef typename left_right_rep::align_type align_type; + enum { inline_raw_cap = cap }; + buf_type* extra() { return rep_.mem; } + union X { + align_type align; + buf_type mem[inline_raw_cap]; + } rep_; +}; + +// select proper base class for left_right_sequence based +// on parameter i +template +struct select_base { +private: + typedef unsigned char buf_type; + typedef left_right_rep base_type; + typedef typename base_type::size_type size_type; + typedef typename base_type::align_type align_type; + typedef no_inline_buffer no_extra_type; + typedef with_inline_buffer with_extra_type; + + enum { padding = sizeof(with_extra_type) - (sizeof(no_extra_type)+sizeof(align_type)) }; + enum { size_with_pad = sizeof(no_extra_type) + padding }; + enum { store_extra = (i > size_with_pad) && (i - size_with_pad) >= base_type::block_size }; + enum { inline_raw_cap = store_extra ? ((i - size_with_pad)/base_type::block_size)*base_type::block_size : 0 }; +public: + typedef typename if_then_else< + store_extra!=0, + with_inline_buffer, + no_inline_buffer >::type type; +}; + + +} // bk_lib::detail + +//! Stores two sequences in one contiguous memory block +/*! + * The left sequence grows from left to right, while the + * right sequence grows from right to left. On overlap, the + * memory block is automatically extended. + * + * \param L value type of left sequence + * \param R value type of right sequence + * \param i max size on stack + * \pre L and R can be copied with memcpy (i.e. have trivial copy constructor and trivial destructor) + */ +template +class left_right_sequence : public bk_lib::detail::select_base::type { +public: + typedef typename bk_lib::detail::select_base::type base_type; + typedef typename base_type::left_type left_type; + typedef typename base_type::right_type right_type; + typedef typename base_type::size_type size_type; + typedef typename base_type::align_type align_type; + typedef typename base_type::max_type max_type; + typedef typename base_type::buf_type buf_type; + + typedef typename base_type::left_iterator left_iterator; + typedef typename base_type::const_left_iterator const_left_iterator; + typedef typename base_type::right_iterator right_iterator; + typedef typename base_type::const_right_iterator const_right_iterator; + + left_right_sequence() { + this->buf_ = this->extra(); + this->cap_ = base_type::inline_raw_cap; + this->free_ = 0; + this->left_ = 0; + this->right_= base_type::inline_raw_cap; + } + left_right_sequence(const left_right_sequence& other); + ~left_right_sequence() { this->release(); } + left_right_sequence& operator=(const left_right_sequence&); + + void try_shrink() { + if (this->raw_size() <= base_type::inline_raw_cap && this->buf_ != this->extra()) { + buf_type* e = this->extra(); + size_type c = base_type::inline_raw_cap; + size_type r = c - (this->right_size()*sizeof(right_type)); + std::memcpy(e, this->begin(), this->left_size() * sizeof(left_type)); + std::memcpy(e+r, this->right(), this->right_size()* sizeof(right_type)); + this->release(); + this->buf_ = e; + this->cap_ = c; + this->free_ = 0; + this->right_= r; + } + } + void move(left_right_sequence& other) { + this->clear(true); + if (other.raw_size() <= base_type::inline_raw_cap) { + copy(other); + other.clear(true); + } + else { + this->buf_ = other.buf_; + this->cap_ = other.cap_; + this->free_ = other.free_; + this->left_ = other.left_; + this->right_ = other.right_; + other.buf_ = other.extra(); + other.cap_ = base_type::inline_raw_cap; + other.free_ = 0; + other.left_ = 0; + other.right_= base_type::inline_raw_cap; + } + } +private: + void copy(const left_right_sequence&); +}; + +template +void left_right_sequence::copy(const left_right_sequence& other) { + size_type os = other.raw_size(); + if ( os <= base_type::inline_raw_cap ) { + this->buf_ = this->extra(); + this->cap_ = base_type::inline_raw_cap; + this->free_= 0; + } + else { + os = ((os + (base_type::block_size-1)) / base_type::block_size) * base_type::block_size; + this->buf_ = (buf_type*)::operator new(os*sizeof(buf_type)); + this->cap_ = os; + this->free_= 1; + } + this->left_ = other.left_; + this->right_= this->cap_ - (other.right_size()*sizeof(right_type)); + std::memcpy(this->begin(), other.begin(), other.left_size()*sizeof(left_type)); + std::memcpy(this->right(), const_cast(other).right(), other.right_size()*sizeof(right_type)); +} + +template +left_right_sequence::left_right_sequence(const left_right_sequence& other) : base_type(other) { + copy(other); +} + +template +left_right_sequence& left_right_sequence::operator=(const left_right_sequence& other) { + if (this != &other) { + this->release(); + copy(other); + } + return *this; +} + + +} // namespace bk_lib + + +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif + diff --git a/libclasp/clasp/util/misc_types.h b/libclasp/clasp/util/misc_types.h new file mode 100644 index 0000000..0635114 --- /dev/null +++ b/libclasp/clasp/util/misc_types.h @@ -0,0 +1,431 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_UTIL_MISC_TYPES_H_INCLUDED +#define CLASP_UTIL_MISC_TYPES_H_INCLUDED + +#include +#include // std::pair +#include // std::unary_function, std::binary_function +#include +#include +/*! + * \file + * \brief Some utility types and functions. + */ +namespace Clasp { + +/*! + * \defgroup misc Miscellaneous + * \brief Miscellaneous and Internal Stuff not specific to clasp. + */ +//@{ + +template +inline T bit_mask(unsigned n) { return static_cast(1) << n; } +//! Returns whether bit n is set in x. +template +inline bool test_bit(T x, unsigned n) { return (x & bit_mask(n)) != 0; } +template +inline T clear_bit(T x, unsigned n) { return x & ~bit_mask(n); } +template +inline T set_bit(T x, unsigned n) { return x | bit_mask(n); } +template +inline T toggle_bit(T x, unsigned n) { return x ^ bit_mask(n); } +template +inline T& store_clear_bit(T& x, unsigned n) { return (x &= ~bit_mask(n)); } +template +inline T& store_set_bit(T& x, unsigned n) { return (x |= bit_mask(n)); } +template +inline T& store_toggle_bit(T& x, unsigned n) { return (x ^= bit_mask(n)); } +template +inline T right_most_bit(T x) { return x & (-x); } + +inline uint32 log2(uint32 x) { + uint32 ln = 0; + if (x & 0xFFFF0000u) { x >>= 16; ln |= 16; } + if (x & 0xFF00u ) { x >>= 8; ln |= 8; } + if (x & 0xF0u ) { x >>= 4; ln |= 4; } + if (x & 0xCu ) { x >>= 2; ln |= 2; } + if (x & 0x2u ) {/*x>>=1*/; ln |= 1; } + return ln; +} + +//! Computes n choose k. +inline uint64 choose(unsigned n, unsigned k) { + if (k == 0) return 1; + if (k > n) return 0; + if (2 * k > n) { return choose(n, n-k);} + uint64 res = n; + for (unsigned i = 2 ; i <= k; ++i) { + res *= (n + 1 - i); + res /= i; + } + return res; +} +inline double ratio(uint64 x, uint64 y) { return y ? static_cast(x) / static_cast(y) : 0; } +inline double percent(uint64 x, uint64 y) { return ratio(x, y) * 100.0; } + +//! A very simple but fast Pseudo-random number generator. +/*! + * \note This class is a replacement for the standard rand-function. It is provided + * in order to get reproducible random numbers among different compilers. + */ +class RNG { +public: + explicit RNG(uint32 seed = 1) : seed_(seed) {} + + //! Sets the starting point for random-number generation. + /*! + * The function sets the starting point for generating a series of pseudorandom integers. + * To reinitialize the generator, use 1 as the seed argument. Any other value for seed + * sets the generator to a random starting point. Calling rand() before any call to srand() + * generates the same sequence as calling srand() with seed passed as 1. + */ + void srand(uint32 seed) { seed_ = seed; } + + //! Generates a pseudorandom number + /*! + * The rand function returns a pseudorandom integer in the range 0 to 32767 + * Use the srand function to seed the pseudorandom-number generator before calling rand. + */ + uint32 rand() { + return( ((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff ); + } + + //! random floating point number in the range [0, 1.0) + double drand() { + return this->rand()/static_cast(0x8000u); + } + + //! random number in the range [0, max) + unsigned irand(unsigned max) { + return static_cast(drand() * max); + } + + uint32 seed() const { return seed_; } + + uint32 operator()(unsigned max) { return irand(max); } + uint32 operator()() { return rand(); } +private: + uint32 seed_; +}; + +//! Updates the given exponential moving average with the given sample. +/*! + * Computes ema = currentEma + ((double(sample) - currentEma)*alpha); + */ +template +inline double exponentialMovingAverage(double currentEma, T sample, double alpha) { + return (static_cast(sample) * alpha) + (currentEma * (1.0 - alpha)); +} +//! Updates the given moving average with the given sample. +template +inline double cumulativeMovingAverage(double currentAvg, T sample, uint64 numSeen) { + return (static_cast(sample) + (currentAvg * numSeen)) / static_cast(numSeen + 1); +} + +//! An unary operator function that calls p->destroy(). +struct DestroyObject { + template void operator()(T* p) const { if (p) p->destroy(); } +}; +//! An unary operator function that calls delete p. +struct DeleteObject { + template void operator()(T* p) const { delete p; } +}; +//! An unary operator function that calls p->release(). +struct ReleaseObject { + template void operator()(T* p) const { if (p) p->release(); } +}; +//! An unary operator function that returns whether its argument is 0. +struct IsNull { + template bool operator()(const T& p) const { return p == 0; } +}; + +//! A predicate that checks whether a std::pair contains a certain value. +template +struct PairContains { + PairContains(const T& p) : p_(p) {} + bool operator()(const std::pair& s) const { + return s.first == p_ || s.second == p_; + } + T p_; +}; + +//! Removes from the container c the first occurrence of a value v for which p(v) returns true. +/*! + * \pre C is a container that provides back() and pop_back() + * \note Removal is implemented by replacing the element to be removed with + * the back()-element followed by a call to pop_back(). + */ +template +void remove_first_if(C& cont, const P& p) { + for (typename C::iterator it = cont.begin(), end = cont.end(); it != end; ++it) { + if (p(*it)) { + *it = cont.back(); + cont.pop_back(); + return; + } + } +} + +//! An unary operator function that simply returns its argument. +template +struct identity : std::unary_function{ + T& operator()(T& x) const { return x; } + const T& operator()(const T& x) const { return x; } +}; + + +//! An unary operator function that returns the first value of a std::pair. +template +struct select1st : std::unary_function { + typename P::first_type& operator()(P& x) const { + return x.first; + } + const typename P::first_type& operator()(const P& x) const { + return x.first; + } +}; + +//! An unary operator function that returns the second value of a std::pair. +template +struct select2nd : std::unary_function { + typename P::second_type& operator()(P& x) const { + return x.second; + } + const typename P::second_type& operator()(const P& x) const { + return x.second; + } +}; + +//! An unary operator function that returns Op1(Op2(x)). +template +struct compose_1 : public std::unary_function< + typename OP2::argument_type, + typename OP1::result_type> { + compose_1(const OP1& op1, const OP2& op2) + : op1_(op1) + , op2_(op2) {} + + typename OP1::result_type operator()(const typename OP2::argument_type& x) const { + return op1_(op2_(x)); + } +protected: + OP1 op1_; + OP2 op2_; +}; + +/*! + * A template helper function used to construct objects of type compose_1, + * where the component types are based on the data types passed as parameters. + */ +template +inline compose_1 compose1(const OP1& op1, const OP2& op2) { + return compose_1(op1, op2); +} + +//! An unary operator function that returns OP1(OP2(x), OP3(x)). +template +struct compose_2_1 : public std::unary_function< + typename OP2::argument_type, + typename OP1::result_type> { + compose_2_1(const OP1& op1, const OP2& op2, const OP3& op3) + : op1_(op1) + , op2_(op2) + , op3_(op3) {} + + typename OP1::result_type operator()(const typename OP2::argument_type& x) const { + return op1_(op2_(x), op3_(x)); + } +protected: + OP1 op1_; + OP2 op2_; + OP3 op3_; +}; + +/*! + * A template helper function used to construct objects of type compose_2_1, + * where the component types are based on the data types passed as parameters. + */ +template +inline compose_2_1 compose2(const OP1& op1, const OP2& op2, const OP3& op3) { + return compose_2_1(op1, op2, op3); +} + + +//! A binary operator function that returns OP1(OP2(x), OP3(y)). +template +struct compose_2_2 : public std::binary_function< + typename OP2::argument_type, + typename OP3::argument_type, + typename OP1::result_type> { + compose_2_2(const OP1& op1 = OP1(), const OP2& op2 = OP2(), const OP3& op3 = OP3()) + : op1_(op1) + , op2_(op2) + , op3_(op3) {} + + typename OP1::result_type operator()(const typename OP2::argument_type& x, const typename OP3::argument_type& y) const { + return op1_(op2_(x), op3_(y)); + } +protected: + OP1 op1_; + OP2 op2_; + OP3 op3_; +}; + +/*! + * A template helper function used to construct objects of type compose_2_2, + * where the component types are based on the data types passed as parameters. + */ +template +inline compose_2_2 compose22(const OP1& op1, const OP2& op2, const OP3& op3) { + return compose_2_2(op1, op2, op3); +} + +//! TODO: replace with std::is_sorted once we switch to C++11 +template +bool isSorted(ForwardIterator first, ForwardIterator last, Compare comp) { + if (first != last) { + for (ForwardIterator n = first; ++n != last; ++first) { + if (comp(*n, *first)) return false; + } + } + return true; +} + +//! Possible ownership operations. +struct Ownership_t { + enum Type { Retain = 0, Acquire = 1 }; +}; +//! A smart pointer that optionally owns its pointee. +template +class SingleOwnerPtr { +public: + SingleOwnerPtr() : ptr_(0) {} + explicit SingleOwnerPtr(T* ptr, Ownership_t::Type t = Ownership_t::Acquire) + : ptr_(uintp(ptr) | uintp(t == Ownership_t::Acquire)) { + } + ~SingleOwnerPtr() { *this = 0; } + bool is_owner() const { return test_bit(ptr_, 0); } + T* get() const { return (T*)clear_bit(ptr_, 0); } + T& operator*() const { return *get(); } + T* operator->() const { return get(); } + SingleOwnerPtr& operator=(T* ptr) { reset(ptr); return *this; } + void swap(SingleOwnerPtr& o) { std::swap(ptr_, o.ptr_); } + T* release() { store_clear_bit(ptr_, 0); return get(); } + T* acquire() { store_set_bit(ptr_, 0); return get(); } + void reset(T* x) { + if (x != get() && is_owner()) { D deleter; deleter(release()); } + ptr_ = set_bit(uintp(x),0); + } +private: + SingleOwnerPtr(const SingleOwnerPtr&); + SingleOwnerPtr& operator=(const SingleOwnerPtr&); + uintp ptr_; +}; +template +class FlaggedPtr { +public: + FlaggedPtr() : ptr_(0) {} + explicit FlaggedPtr(T* ptr, bool sf = false) : ptr_(uintp(ptr)) { if (sf) flag(); } + bool flagged() const { return test_bit(ptr_, 0); } + T* get() const { return (T*)clear_bit(ptr_, 0); } + T& operator*() const { return *get(); } + T* operator->() const { return get(); } + void swap(FlaggedPtr& o) { std::swap(ptr_, o.ptr_); } + void flag() { store_set_bit(ptr_, 0); } + void unflag() { store_clear_bit(ptr_, 0); } +private: + uintp ptr_; +}; +template +inline FlaggedPtr make_flagged(T* ptr, bool setFlag) { return FlaggedPtr(ptr, setFlag); } + +//! A (numerical) range represented by a low and a high value. +template +struct Range { + Range(T x, T y) : lo(x), hi(y) { if (x > y) { hi = x; lo = y; } } + T clamp(T val) const { + if (val < lo) return lo; + if (val > hi) return hi; + return val; + } + T lo; + T hi; +}; +template +inline bool operator==(const Range& lhs, const Range& rhs) { + return lhs.lo == rhs.lo && lhs.hi == rhs.hi; +} +//! An iterator type for iterating over a range of numerical values. +template +struct num_iterator : std::iterator { + explicit num_iterator(const T& val) : val_(val) {} + typedef typename std::iterator::value_type value_type; + typedef typename std::iterator::difference_type difference_type; + bool operator==(const num_iterator& rhs) const { return val_ == rhs.val_; } + bool operator!=(const num_iterator& rhs) const { return val_ != rhs.val_; } + bool operator<=(const num_iterator& rhs) const { return val_ <= rhs.val_; } + bool operator< (const num_iterator& rhs) const { return val_ < rhs.val_; } + bool operator>=(const num_iterator& rhs) const { return val_ >= rhs.val_; } + bool operator> (const num_iterator& rhs) const { return val_ > rhs.val_; } + value_type operator*() const { return val_; } + T const* operator->() const { return &val_; } + num_iterator& operator++() { ++val_; return *this; } + num_iterator& operator++(int) { num_iterator t(*this); ++*this; return t; } + num_iterator& operator--() { --val_; return *this; } + num_iterator& operator--(int) { num_iterator t(*this); --*this; return t; } + num_iterator& operator+=(difference_type n) { val_ += n; return *this; } + num_iterator& operator-=(difference_type n) { val_ -= n; return *this; } + num_iterator operator+(difference_type n) const { return num_iterator(static_cast(val_ + n)); } + num_iterator operator-(difference_type n) const { return num_iterator(static_cast(val_ - n)); } + value_type operator[](difference_type n)const { return val_ + n; } + friend num_iterator operator+(difference_type n, num_iterator it) { return num_iterator(it.val_ + n); } +private: + T val_; +}; +//@} + +//! Base class for library events. +struct Event { + //! Set of known event sources. + enum Subsystem { subsystem_facade = 0, subsystem_load = 1, subsystem_prepare = 2, subsystem_solve = 3 }; + //! Possible verbosity levels. + enum Verbosity { verbosity_quiet = 0, verbosity_low = 1, verbosity_high = 2, verbosity_max = 3 }; + explicit Event(Subsystem sys, uint32 evId, Verbosity verbosity) : system(sys), verb(verbosity), op(0), id(evId) {} + uint32 system : 2; //!< One of Event::Subsystem - subsystem that produced the event. + uint32 verb : 2; //!< One of Event::Verbosity - the verbosity level of this event. + uint32 op : 8; //!< Operation that triggered the event. + uint32 id : 16;//!< Type id of event. + static uint32 nextId(); +}; +//! CRTP-base class for events of type T that registers an id for type T. +template +struct Event_t : Event { + Event_t(Subsystem sys, Verbosity verb) : Event(sys, id_s, verb) {} + static const uint32 id_s; +}; +template const uint32 Event_t::id_s = Event::nextId(); + +template const ToType* event_cast(const EvType& ev) { return ev.id == ToType::id_s ? static_cast(&ev) : 0; } + +} +#endif diff --git a/libclasp/clasp/util/multi_queue.h b/libclasp/clasp/util/multi_queue.h new file mode 100644 index 0000000..1f07d88 --- /dev/null +++ b/libclasp/clasp/util/multi_queue.h @@ -0,0 +1,256 @@ +// +// Copyright (c) 2010-2012, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_MULIT_QUEUE_H_INCLUDED +#define CLASP_MULIT_QUEUE_H_INCLUDED + +#include +#include + +namespace Clasp { namespace mt { namespace Detail { + +struct RawNode; +typedef Clasp::Atomic_t::type SafeNodePtr; +struct RawNode { + SafeNodePtr next; +}; +// Lock-free stack that is NOT ABA-safe by itself +struct RawStack { + RawStack() { top = static_cast(0); } + RawNode* tryPop() { + RawNode* n = 0, *next = 0; + do { + if ((n = top) == 0) { return 0; } + // NOTE: + // it is the caller's job to guarantee that n is safe + // and n->next is ABA-safe at this point. + next = n->next; + } while (top.compare_and_swap(next, n) != n); + return n; + } + void push(RawNode* n) { + RawNode* assumedTop; + do { + assumedTop = top; + n->next = assumedTop; + } while (top.compare_and_swap(n, assumedTop) != assumedTop); + } + SafeNodePtr top; +}; +struct DefaultDeleter { + template + void operator()(T& obj) const { + (void)obj; + obj.~T(); + } +}; +} + +//! A (base) class for distributing items between n different threads. +/*! + * Logically, the class maintains n queues, one for each + * involved thread. Threads must register themselves by + * calling addThread(). The returned handle has then + * to be used for publishing and consuming items. + */ +template +class MultiQueue { +protected: + typedef Detail::RawNode RawNode; + typedef Clasp::Atomic_t::type SafeInt; + struct Node : Detail::RawNode { + explicit Node(uint32 rc, const T& d) : data(d) { next = 0; refs = rc; } + SafeInt refs; + T data; + }; +public: + typedef Detail::RawNode* ThreadId; + //! creates a new object for at most m threads + explicit MultiQueue(uint32 m, const Deleter& d = Deleter()) : maxQ_(m), deleter_(d) { + head_.next = 0; + tail_ = &head_; + } + uint32 maxThreads() const { return maxQ_; } + void reserve(uint32 c) { + struct NodeHead : RawNode { SafeInt refs; }; + for (uint32 i = 0; i != c; ++i) { + free_.push(new (::operator new(sizeof(Node))) NodeHead()); + } + } + //! destroys the object and all unconsumed items + ~MultiQueue() { + for (Detail::RawNode* x = head_.next; x ; ) { + Node* n = toNode(x); + x = x->next; + deleter_(n->data); + ::operator delete(n); + } + for (Detail::RawNode* x; (x = free_.tryPop()) != 0; ) { + ::operator delete(toNode(x)); + } + } + //! adds a new thread to the object + /*! + * \note Shall be called at most m times + * \return A handle identifying the new thread + */ + ThreadId addThread() { + return &head_; + } + bool hasItems(ThreadId& cId) const { return cId != tail_; } + + //! tries to consume an item + /*! + * \pre cId was initially obtained via a call to addThread() + * \note tryConsume() is thread-safe w.r.t different ThreadIds + */ + bool tryConsume(ThreadId& cId, T& out) { + if (cId != tail_) { + RawNode* n = cId; + cId = cId->next; + assert(cId != 0 && "MultiQueue is corrupted!"); + release(n); + out = toNode(cId)->data; + return true; + } + return false; + } + //! pops an item from the queue associated with the given thread + /*! + * \pre hasItems(cId) == true + */ + void pop(ThreadId& cId) { + assert(hasItems(cId) && "Cannot pop from empty queue!"); + RawNode* n = cId; + cId = cId->next; + release(n); + } +protected: + //! publishes a new item + /*! + * \note the function is *not* thread-safe, i.e. + * it must not be called concurrently + */ + void unsafePublish(const T& in, const ThreadId&) { unsafePublish(in); } + void unsafePublish(const T& in) { publishRelaxed(allocate(maxQ_, in)); } + + //! concurrency-safe version of unsafePublish + void publish(const T& in, const ThreadId&) { + Node* newNode = allocate(maxQ_, in); + RawNode* assumedTail, *assumedNext; + do { + assumedTail = tail_; + assumedNext = assumedTail->next; + if (assumedTail != tail_) { + // tail has changed - try again + continue; + } + if (assumedNext != 0) { + // someone has added a new node but has not yet + // moved the tail - assist him and start over + tail_.compare_and_swap(assumedNext, assumedTail); + continue; + } + } while (assumedTail->next.compare_and_swap(newNode, 0) != 0); + // Now that we managed to link a new node to what we think is the current tail + // we try to update the tail. If the tail is still what we think it is, + // it is moved - otherwise some other thread already did that for us. + tail_.compare_and_swap(newNode, assumedTail); + } + + //! Non-atomically adds n to the global queue + void publishRelaxed(Node* n) { + static_cast(tail_)->next = n; + tail_ = n; + } + uint32 maxQ() const { return maxQ_; } + Node* allocate(uint32 maxR, const T& in) { + // If the queue is used correctly, the raw stack is ABA-safe at this point. + // The ref-counting in the queue makes sure that a node cannot be added back + // to the stack while another thread is still in tryPop() - that thread had + // not yet the chance to decrease the node's ref count. + if (Node* n = toNode(free_.tryPop())) { + n->next = 0; + n->refs = maxR; + new (&n->data)T(in); + return n; + } + return new (::operator new(sizeof(Node))) Node(maxR, in); + } +private: + MultiQueue(const MultiQueue&); + MultiQueue& operator=(const MultiQueue&); + Node*toNode(Detail::RawNode* x) const { return static_cast(x); } + void release(Detail::RawNode* n) { + if (n != &head_ && --toNode(n)->refs == 0) { + head_.next = static_cast(n->next); + deleter_(toNode(n)->data); + free_.push(n); + } + } + RawNode head_; + Detail::SafeNodePtr tail_; + Detail::RawStack free_; + const uint32 maxQ_; + Deleter deleter_; +}; + +//! Unbounded non-intrusive lock-free multi-producer single consumer queue. +/*! + * Based on Dmitriy Vyukov's MPSC queue: + * http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue + */ +class MPSCPtrQueue { +public: + typedef Detail::RawNode RawNode; + struct Node : RawNode { void* data; }; + typedef Clasp::Atomic_t::type SafeNodePtr; + Node* toNode(RawNode* n) const { return static_cast(n); } + MPSCPtrQueue() {} + void init(Node* sent) { + sent->next = 0; + sent->data = 0; + head_ = sent; + tail_ = sent; + } + bool empty() const { return !static_cast(tail_->next); } + void push(Node* n) { + n->next = 0; + Node* p = head_.fetch_and_store(n); + p->next = n; + } + Node* pop() { + Node* t = tail_; + Node* n = toNode(t->next); + if (!n) { return 0; } + tail_ = n; + t->data = n->data; + n->data = 0; + return t; + } +private: + MPSCPtrQueue(const MPSCPtrQueue&); + MPSCPtrQueue& operator=(const MPSCPtrQueue&); + SafeNodePtr head_; // producers + char pad_[64 - sizeof(Node*)]; + Node* tail_; // consumer +}; + +} } // end namespace Clasp::mt +#endif diff --git a/libclasp/clasp/util/mutex.h b/libclasp/clasp/util/mutex.h new file mode 100644 index 0000000..c0cbbf7 --- /dev/null +++ b/libclasp/clasp/util/mutex.h @@ -0,0 +1,88 @@ +// +// Copyright (c) 2012, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_UTIL_MUTEX_H_INCLUDED +#define CLASP_UTIL_MUTEX_H_INCLUDED + +#if !defined(CLASP_USE_STD_THREAD) +#if _WIN32||_WIN64 +#define WIN32_LEAN_AND_MEAN // exclude APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets. +#define NOMINMAX // do not let windows.h define macros min and max +#endif +#include +#include +#if defined(TBB_IMPLEMENT_CPP0X) +#define RESTORE_TBB_IMPLEMENT_CPP0X TBB_IMPLEMENT_CPP0X +#undef TBB_IMPLEMENT_CPP0X +#endif +#define TBB_IMPLEMENT_CPP0X 0 +#include +#undef TBB_IMPLEMENT_CPP0X +#if defined(RESTORE_TBB_IMPLEMENT_CPP0X) +#define TBB_IMPLEMENT_CPP0X RESTORE_TBB_IMPLEMENT_CPP0X +#undef RESTORE_TBB_IMPLEMENT_CPP0X +#endif +#define NS_MUTEX tbb +#define NS_COMPAT tbb::interface5 +#else +#include +#include +#define NS_MUTEX std +#define NS_COMPAT std +#endif +namespace Clasp { namespace mt { + using NS_MUTEX::mutex; + using NS_COMPAT::lock_guard; + using NS_COMPAT::unique_lock; + using NS_COMPAT::swap; + using NS_COMPAT::defer_lock_t; + struct condition_variable : private NS_COMPAT::condition_variable { + typedef NS_COMPAT::condition_variable base_type; + using base_type::notify_one; + using base_type::notify_all; + using base_type::wait; + using base_type::native_handle; + + bool wait_for(unique_lock& lock, double timeInSecs); + }; +#if !defined(CLASP_USE_STD_THREAD) + // Due to a bug in the computation of the wait time in older tbb versions + // wait_for might fail with eid_condvar_wait_failed. + // See: http://software.intel.com/en-us/forums/topic/280012 + // Ignore the error and retry the wait - the computed wait time will be valid, eventually. + inline bool condition_variable::wait_for(unique_lock& lock, double s) { + if (s < 0) { throw std::logic_error("invalid wait time"); } + for (;;) { + try { return base_type::wait_for(lock, tbb::tick_count::interval_t(s)) == NS_COMPAT::no_timeout; } + catch (const std::runtime_error&) {} + } + } +#else + inline bool condition_variable::wait_for(unique_lock& lock, double s) { + return base_type::wait_for(lock, std::chrono::duration_cast(std::chrono::duration(s))) + == std::cv_status::no_timeout; + } +#endif +}} + +#undef NS_MUTEX +#undef NS_COMPAT + +#endif diff --git a/libclasp/clasp/util/platform.h b/libclasp/clasp/util/platform.h new file mode 100644 index 0000000..d9662dc --- /dev/null +++ b/libclasp/clasp/util/platform.h @@ -0,0 +1,212 @@ +// +// Copyright (c) 2006-2012, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +//! \file +//! \brief Global and platform-dependent stuff. +#ifndef CLASP_PLATFORM_H_INCLUDED +#define CLASP_PLATFORM_H_INCLUDED +#ifdef _MSC_VER +#pragma once +#endif +#if !defined(WITH_THREADS) +#error Invalid thread configuration - use WITH_THREADS=0 for single-threaded or WITH_THREADS=1 for multi-threaded version of libclasp! +#endif + +#define STRING2(x) #x +#define STRING(x) STRING2(x) + +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#define CLASP_PRAGMA_TODO(X) __pragma(message(__FILE__ "(" STRING(__LINE__) ") : TODO: " X)) +#define FUNC_NAME __FUNCTION__ +#define CLASP_WARNING_BEGIN_RELAXED \ + __pragma(warning(push))\ + __pragma(warning (disable : 4200)) + +#define CLASP_WARNING_END_RELAXED \ + __pragma(warning(pop)) + +#include +#if _MSC_VER >= 1600 +#include +#endif +typedef UINT8 uint8; +typedef UINT16 uint16; +typedef INT16 int16; +typedef INT32 int32; +typedef UINT32 uint32; +typedef UINT64 uint64; +typedef INT64 int64; +typedef UINT_PTR uintp; +typedef INT16 int16; +#define PRIu64 "llu" +#define PRId64 "lld" +#elif defined(__GNUC__) && __GNUC__ >= 3 +#define FUNC_NAME __PRETTY_FUNCTION__ +#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS +#endif +#include +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef int16_t int16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef uint64_t uint64; +typedef int64_t int64; +typedef uintptr_t uintp; +#define APPLY_PRAGMA(x) _Pragma (#x) +#define CLASP_PRAGMA_TODO(x) APPLY_PRAGMA(message ("TODO: " #x)) +#else +#error unknown compiler or platform. Please add typedefs manually. +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (~uint32(0)) +#endif +#ifndef UINT64_MAX +#define UINT64_MAX (~uint64(0)) +#endif +#ifndef INT64_MAX +#define INT64_MAX ((int64)(UINT64_MAX >> 1)) +#endif +#ifndef UINTP_MAX +#define UINTP_MAX (~uintp(0)) +#endif +#ifndef INT16_MAX +#define INT16_MAX (0x7fff) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-INT16_MAX - 1) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef FUNC_NAME +#define FUNC_NAME __FILE__ +#endif + + +template +bool aligned(void* mem) { + uintp x = reinterpret_cast(mem); +#if (_MSC_VER >= 1300) + return (x & (__alignof(T)-1)) == 0; +#elif defined(__GNUC__) + return (x & (__alignof__(T)-1)) == 0; +#else + struct AL { char x; T y; }; + return (x & (sizeof(AL)-sizeof(T))) == 0; +#endif +} + +#if !defined(CLASP_WARNING_BEGIN_RELAXED) +# undef CLASP_WARNING_END_RELAXED +# if defined(__clang__) +# define CLASP_WARNING_BEGIN_RELAXED \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wzero-length-array\"") +# define CLASP_WARNING_END_RELAXED _Pragma("clang diagnostic pop") +# elif defined(__GNUC__) +# define CLASP_WARNING_BEGIN_RELAXED \ + _Pragma("GCC diagnostic push")\ + _Pragma("GCC diagnostic ignored \"-Wpragmas\"")\ + _Pragma("GCC diagnostic ignored \"-Wpedantic\"")\ + _Pragma("GCC diagnostic ignored \"-pedantic\"") +# define CLASP_WARNING_END_RELAXED _Pragma("GCC diagnostic pop") +# else +# define CLASP_WARNING_BEGIN_RELAXED +# define CLASP_WARNING_END_RELAXED +# endif +#endif + +#if !defined(CLASP_HAS_STATIC_ASSERT) +# if defined(__cplusplus) && __cplusplus >= 201103L +# define CLASP_HAS_STATIC_ASSERT 1 +# elif defined(static_assert) +# define CLASP_HAS_STATIC_ASSERT 1 +# elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define CLASP_HAS_STATIC_ASSERT 1 +# else +# define CLASP_HAS_STATIC_ASSERT 0 +# endif +#endif + +#if !defined(CLASP_HAS_STATIC_ASSERT) || CLASP_HAS_STATIC_ASSERT == 0 +template struct static_assertion; +template <> struct static_assertion {}; +#ifndef __GNUC__ +#define static_assert(x, message) typedef bool clasp_static_assertion[sizeof(static_assertion< (x) >)] +#else +#define static_assert(x, message) typedef bool clasp_static_assertion[sizeof(static_assertion< (x) >)] __attribute__((__unused__)) +#endif +#endif +#include +#include +extern const char* clasp_format(char* buf, unsigned size, const char* m, ...); +class ClaspStringBuffer { +public: + ClaspStringBuffer() { fix_[0] = 0; buf_ = pos_ = fix_; end_ = buf_ + sizeof(fix_); } + ~ClaspStringBuffer(); + const char* c_str() const { return buf_; } + operator const char*() const { return c_str(); } + ClaspStringBuffer& appendFormat(const char* fmt, ...); + ClaspStringBuffer& append(const char* str); + size_t size() const { return static_cast(pos_ - buf_); } +private: + ClaspStringBuffer(const ClaspStringBuffer&); + ClaspStringBuffer& operator=(const ClaspStringBuffer&); + bool grow(size_t nItems); + char* buf_; + char* pos_; + char* end_; + char fix_[512]; +}; + +#define CLASP_FAIL_IF(exp, ...) \ + (void)( (!(exp)) || (throw std::logic_error(ClaspStringBuffer().appendFormat(__VA_ARGS__).c_str()), 0)) + +#ifndef CLASP_NO_ASSERT_CONTRACT + +#define CLASP_ASSERT_CONTRACT_MSG(exp, msg) \ + (void)( (!!(exp)) || (throw std::logic_error(ClaspStringBuffer().appendFormat("%s@%d: contract violated: %s", FUNC_NAME, __LINE__, (msg)).c_str()), 0)) + +#else +#include +#define CLASP_ASSERT_CONTRACT_MSG(exp, msg) assert((exp) && ((msg),true)) +#endif + +#define CLASP_ASSERT_CONTRACT(exp) CLASP_ASSERT_CONTRACT_MSG(exp, #exp) + +#if !defined(CLASP_ENABLE_PRAGMA_TODO) || CLASP_ENABLE_PRAGMA_TODO==0 +#undef CLASP_PRAGMA_TODO +#define CLASP_PRAGMA_TODO(X) +#endif + +#if _WIN32||_WIN64 +#include +inline void* alignedAlloc(size_t size, size_t align) { return _aligned_malloc(size, align); } +inline void alignedFree(void* p) { _aligned_free(p); } +#else +inline void* alignedAlloc(size_t size, size_t align) { + void* result = 0; + return posix_memalign(&result, align, size) == 0 ? result : static_cast(0); +} +inline void alignedFree(void* p) { free(p); } +#endif + +#endif diff --git a/libclasp/clasp/util/pod_vector.h b/libclasp/clasp/util/pod_vector.h new file mode 100644 index 0000000..2387d84 --- /dev/null +++ b/libclasp/clasp/util/pod_vector.h @@ -0,0 +1,558 @@ +// +// Copyright (c) 2006-2010, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef BK_LIB_POD_VECTOR_H_INCLUDED +#define BK_LIB_POD_VECTOR_H_INCLUDED +#include "type_manip.h" +#include +#include +#include +#include +#include +#include +namespace bk_lib { namespace detail { + template + void fill(T* first, T* last, const T& x) { + assert(first <= last); + switch ((last - first) & 7u) + { + case 0: + while (first != last) + { + new(first++) T(x); + case 7: new(first++) T(x); + case 6: new(first++) T(x); + case 5: new(first++) T(x); + case 4: new(first++) T(x); + case 3: new(first++) T(x); + case 2: new(first++) T(x); + case 1: new(first++) T(x); + assert(first <= last); + } + } + } + template + void copy(Iter first, Iter last, std::size_t s, T* out) { + switch (s & 7u) + { + case 0: + while (first != last) + { + new(out++) T(*first++); + case 7: new(out++) T(*first++); + case 6: new(out++) T(*first++); + case 5: new(out++) T(*first++); + case 4: new(out++) T(*first++); + case 3: new(out++) T(*first++); + case 2: new(out++) T(*first++); + case 1: new(out++) T(*first++); + } + } + } + template + struct Fill { + Fill(const T& val) : val_(val) {} + void operator()(T* first, std::size_t n) const { detail::fill(first, first + n, val_); } + const T& val_; + private: Fill& operator=(const Fill&); + }; + template + struct Copy { + Copy(Iter first, Iter last) : first_(first), last_(last) {} + template + void operator()(T* out, std::size_t n) const { detail::copy(first_, last_, n, out); } + Iter first_; + Iter last_; + }; + template + struct Memcpy { + Memcpy(const T* first) : first_(first) {} + void operator()(T* out, std::size_t n) const { + std::memcpy(out, first_, n*sizeof(T)); + } + const T* first_; + }; + typedef char yes_type; + typedef char (&no_type)[2]; + template + struct IterType { + static yes_type isPtr(const volatile void*); + static no_type isPtr(...); + static yes_type isLong(int64); + static no_type isLong(...); + static T& makeT(); + enum { ptr = sizeof(isPtr(makeT())) == sizeof(yes_type) }; + enum { num = sizeof(isLong(makeT())) == sizeof(yes_type) }; + enum { value = ptr ? 1 : num ? 2 : 0 }; + }; + +} // end namespace bk_lib::detail + +//! A std::vector-replacement for POD-Types. +/*! + * \pre T is a POD-Type + * \see http://www.comeaucomputing.com/techtalk/#pod for a description of POD-Types. + * \note Does not call any destructors and uses std::memcpy to copy/move elements + * \note On LP64-machines size and capacity are represented as unsigned integers (instead of e.g. std::size_t) + */ +template > +class pod_vector { +public: + // types: + typedef pod_vector this_type;//not standard + typedef Allocator allocator_type; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename Allocator::pointer iterator; + typedef typename Allocator::const_pointer const_iterator; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef T value_type; + typedef typename detail::if_then_else< + sizeof(typename Allocator::size_type)<=sizeof(unsigned int), + typename Allocator::size_type, + unsigned int>::type size_type; + typedef typename detail::if_then_else< + sizeof(typename Allocator::difference_type)<=sizeof(int), + typename Allocator::difference_type, + int>::type difference_type; + // ctors + //! constructs an empty pod_vector. + /*! + * \post size() == capacity() == 0 + */ + pod_vector() : ebo_(0, allocator_type()) { } + + //! constructs an empty pod_vector that uses a copy of a for memory allocations. + /*! + * \post size() == capacity() == 0 + */ + explicit pod_vector(const allocator_type& a) : ebo_(0, a) { } + + //! constructs a pod_vector containing n copies of value. + /*! + * \post size() == n + */ + explicit pod_vector(size_type n, const T& value = T(), const allocator_type& a = allocator_type()) + : ebo_(n, a) { + detail::fill(ebo_.buf, ebo_.buf + n, value); + ebo_.size = n; + } + + //! constructs a pod_vector equal to the range [first, last). + /*! + * \post size() = distance between first and last. + */ + template + pod_vector(Iter first, Iter last, const allocator_type& a = allocator_type(), typename detail::disable_if::num>::type* = 0) + : ebo_(0, a) { + insert_range(end(), first, last, typename std::iterator_traits::iterator_category()); + } + + //! creates a copy of other + /*! + * \post size() == other.size() && capacity() == other.size() + */ + pod_vector(const pod_vector& other) : ebo_(other.size(), other.get_allocator()) { + std::memcpy(ebo_.buf, other.begin(), other.size()*sizeof(T)); + ebo_.size = other.size(); + } + + pod_vector& operator=(const pod_vector& other) { + if (this != &other) { + assign(other.begin(), other.end()); + } + return *this; + } + + //! frees all memory allocated by this pod_vector. + /*! + * \note Won't call any destructors, because PODs don't have those. + */ + ~pod_vector() { } + + /** @name inspectors + * inspector-functions + */ + //@{ + + //! returns the number of elements currently stored in this pod_vector. + size_type size() const { return ebo_.size; } + //! size of the largest possible pod_vector + size_type max_size() const { + typename allocator_type::size_type x = get_allocator().max_size(); + std::size_t y = size_type(-1)/sizeof(T); + return static_cast(std::min(std::size_t(x), y)); + } + //! returns the total number of elements this pod_vector can hold without requiring reallocation. + size_type capacity() const { return ebo_.cap; } + //! returns size() == 0 + bool empty() const { return ebo_.size == 0; } + + const_iterator begin() const { return ebo_.buf; } + const_iterator end() const { return ebo_.buf+ebo_.size;} + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + iterator begin() { return ebo_.buf; } + iterator end() { return ebo_.buf+ebo_.size; } + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + + //! returns a copy of the allocator used by this pod_vector + allocator_type get_allocator() const { return ebo_; } + + //@} + /** @name elemacc + * element access + */ + //@{ + + //! returns a reference to the element at position n + /*! + * \pre n < size() + */ + reference operator[](size_type n) { + assert(n < size()); + return ebo_.buf[n]; + } + + //! returns a reference-to-const to the element at position n + /*! + * \pre n < size() + */ + const_reference operator[](size_type n) const { + assert(n < size()); + return ebo_.buf[n]; + } + + //! same as operator[] but throws std::out_of_range if pre-condition is not met. + const_reference at(size_type n) const { + if (n < size()) return ebo_.buf[n]; + throw std::out_of_range("pod_vector::at"); + } + //! same as operator[] but throws std::out_of_range if pre-condition is not met. + reference at(size_type n) { + if (n < size()) return ebo_.buf[n]; + throw std::out_of_range("pod_vector::at"); + } + + //! equivalent to *begin() + reference front() { assert(!empty()); return *ebo_.buf; } + //! equivalent to *begin() + const_reference front() const { assert(!empty()); return *ebo_.buf; } + + //! equivalent to *--end() + reference back() { assert(!empty()); return ebo_.buf[ebo_.size-1]; } + + //! equivalent to *--end() + const_reference back() const { assert(!empty()); return ebo_.buf[ebo_.size-1]; } + + //@} + /** @name mutators + * mutator functions + */ + //@{ + + //! erases all elements in the range [begin(), end) + /*! + * \post size() == 0 + */ + void clear() { ebo_.size = 0; } + + void assign(size_type n, const T& val) { + clear(); + insert(end(), n, val); + } + + template + void assign(Iter first, Iter last) { + clear(); + insert(end(), first, last); + } + + //! erases the element pointed to by pos. + /*! + * \pre pos != end() && !empty() + * \return an iterator pointing to the element following pos (before that element was erased) + * of end() if no such element exists. + * + * \note invalidates all iterators and references referring to elements after pos. + */ + iterator erase(iterator pos) { + assert(!empty() && pos != end()); + erase(pos, pos + 1); + return pos; + } + + //! erases the elements in the range [first, last) + /*! + * \pre [first, last) must be a valid range. + */ + iterator erase(iterator first, iterator last) { + if (end() - last > 0) { + std::memmove(first, last, (end() - last) * sizeof(T)); + } + ebo_.size -= static_cast(last - first); + return first; + } + + //! adjusts the size of this pod_vector to ns. + /*! + * resize is equivalent to: + * if ns > size insert(end(), ns - size(), val) + * if ns < size erase(begin() + ns, end()) + * + * \post size() == ns + */ + void resize(size_type ns, const T& val = T()) { + if (ns > size()) { + ns <= capacity() ? detail::fill(end(), end()+(ns-size()), val) : append_realloc(ns-size(), val); + } + ebo_.size = ns; + } + + //! reallocates storage if necessary but never changes the size() of this pod_vector. + /*! + * \note if n is <= capacity() reserve is a noop. Otherwise a reallocation takes place + * and capacity() >= n after reserve returned. + * \note reallocation invalidates all references, pointers and iterators referring to + * elements in this pod_vectror. + * + * \note when reallocation occurs elements are copied from the old storage using memcpy. + */ + void reserve(size_type n) { + if (n > capacity()) { + T* temp = ebo_.allocate(n); + std::memcpy(temp, ebo_.buf, size()*sizeof(T)); + ebo_.release(); + ebo_.buf = temp; + ebo_.cap = n; + } + } + + void swap(pod_vector& other) { + std::swap(ebo_.buf, other.ebo_.buf); + std::swap(ebo_.size, other.ebo_.size); + std::swap(ebo_.cap, other.ebo_.cap); + } + + //! equivalent to insert(end(), x); + void push_back(const T& x) { + if (size() < capacity()) { + new ((ebo_.buf+ebo_.size++)) T(x); + } + else { + append_realloc(1, x); + } + } + + //! equivalent to erase(--end()); + /*! + * \pre !empty() + */ + void pop_back() { + assert(!empty()); + --ebo_.size; + } + + //! inserts a copy of val before pos. + /*! + * \pre pos is a valid iterator. + * \return an iterator pointing to the copy of val that was inserted. + * \note if size() + 1 > capacity() reallocation occurs. Otherwise iterators and + * references referring to elements before pos remain valid. + * + */ + iterator insert(iterator pos, const T& val) { + return insert(pos, (size_type)1, val); + } + + //! inserts n copies of val before pos. + /*! + * \pre pos is a valid iterator. + */ + iterator insert(iterator pos, size_type n, const T& val) { + size_type off = static_cast(pos-begin()); + insert_impl(pos, n, detail::Fill(val)); + return ebo_.buf + off; + } + + //! inserts copies of elements in the range [first, last) before pos. + /*! + * \pre first and last are not iterators into this pod_vector. + * \pre pos is a valid iterator. + * \note if first and last are pointers, memcpy is used to insert the elements + * in the range [first, last) into this container. + * + */ + template + void insert(iterator pos, Iter first, Iter last, typename detail::disable_if::num>::type* = 0) { + insert_range(pos, first, last, typename std::iterator_traits::iterator_category()); + } + + + /** @name nonstd + * Non-standard interface + */ + //@{ + + //! adjusts the size of this pod_vector to ns. + /*! + * In contrast to pod_vector::resize this function does not + * initializes new elements in case ns > size(). + * This reflects the behaviour of built-in arrays of pod-types. + * \note + * Any access to an unitialized element is illegal unless it is accessed + * in order to assign a new value. + */ + void resize_no_init(size_type ns) { + reserve(ns); + ebo_.size = ns; + } + //@} +private: + size_type grow_size(size_type n) { + size_type new_cap = size() + n; + assert(new_cap > size() && "pod_vector: max size exceeded!"); + assert(new_cap > capacity()); + if (new_cap < 4) new_cap = 1 << (new_cap+1); + size_type x = (capacity()*3)>>1; + if (new_cap < x) new_cap = x; + return new_cap; + } + void append_realloc(size_type n, const T& x) { + size_type new_cap = grow_size(n); + pointer temp = ebo_.allocate(new_cap); + std::memcpy(temp, ebo_.buf, size()*sizeof(T)); + detail::fill(temp+size(), temp+size()+n, x); + ebo_.release(); + ebo_.buf = temp; + ebo_.cap = new_cap; + ebo_.size+= n; + } + void move_right(iterator pos, size_type n) { + assert( (pos || n == 0) && (ebo_.eos() - pos) >= (int)n); + std::memmove(pos + n, pos, (end() - pos) * sizeof(T)); + } + template + void insert_range(iterator pos, It first, It last, std::random_access_iterator_tag, + typename detail::disable_if::value == 0 && detail::same_type::value == 0>::type* = 0) { + assert( (first < begin() || first >= end()) && "pod_vec::insert(): Precondition violated!"); + typename allocator_type::difference_type diff = std::distance(first, last); + assert(diff == 0 || (static_cast(size()+diff) > size() && "pod_vector: max size exceeded!")); + insert_impl(pos, static_cast(diff), detail::Memcpy(first)); + } + template + void insert_range(iterator pos, It first, It last, std::forward_iterator_tag) { + typename allocator_type::difference_type diff = std::distance(first, last); + assert(diff == 0 || (static_cast(size()+diff) > size() && "pod_vector: max size exceeded!")); + insert_impl(pos, static_cast(diff), detail::Copy(first, last)); + } + template + void insert_range(iterator pos, Iter first, Iter last, std::input_iterator_tag) { + pod_vector temp; + while (first != last) temp.push_back(*first++); + insert(pos, temp.begin(), temp.end()); + } + + // NOTE: template parameter ST should always equal size_type + // and is only needed to workaround an internal compiler error + // in gcc 3.4.3 + template + void insert_impl(iterator pos, ST n, const P& pred) { + assert(n == 0 || (size()+n) > size() ); + if (size()+n <= capacity()) { + move_right(pos, n); + pred(pos, n); + ebo_.size += n; + } + else { + size_type new_cap = grow_size(n); + pointer temp = ebo_.allocate(new_cap); + size_type prefix = static_cast(pos-begin()); + // copy prefix + std::memcpy(temp, begin(), prefix*sizeof(T)); + // insert new stuff + pred(temp+prefix, n); + // copy suffix + std::memcpy(temp+prefix+n, pos, (end()-pos)*sizeof(T)); + ebo_.release(); + ebo_.buf = temp; + ebo_.size+= n; + ebo_.cap = new_cap; + } + } + struct ebo : public Allocator { // empty-base-optimization + typedef typename this_type::size_type size_type; + typedef typename this_type::allocator_type A; + pointer buf; // pointer to array + size_type size; // current size (used elements) + size_type cap; // max size before regrow + ebo(size_type n, const Allocator& a) : Allocator(a), buf(0), size(0), cap(n) { + if (n > 0) { buf = A::allocate(n); } + } + ~ebo() { release(); } + void release() { if (buf) A::deallocate(buf, cap); } + T* eos() const { return buf + cap; } + } ebo_; +}; + +template +inline bool operator==(const pod_vector& lhs, const pod_vector& rhs) { + return lhs.size() == rhs.size() + && std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +inline bool operator!=(const pod_vector& lhs, const pod_vector& rhs) { + return ! (lhs == rhs); +} + +template +inline bool operator<(const pod_vector& lhs, const pod_vector& rhs) { + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +template +inline bool operator>(const pod_vector& lhs, const pod_vector& rhs) { + return rhs < lhs; +} + +template +inline bool operator<=(const pod_vector& lhs, const pod_vector& rhs) { + return !(rhs < lhs); +} + +template +inline bool operator>=(const pod_vector& lhs, const pod_vector& rhs) { + return !(lhs < rhs); +} + +template +inline void swap(pod_vector& lhs, pod_vector& rhs) { + lhs.swap(rhs); +} + +} + +#endif + diff --git a/libclasp/clasp/util/thread.h b/libclasp/clasp/util/thread.h new file mode 100644 index 0000000..7edd2df --- /dev/null +++ b/libclasp/clasp/util/thread.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_UTIL_THREAD_H_INCLUDED +#define CLASP_UTIL_THREAD_H_INCLUDED + +#if !defined(CLASP_USE_STD_THREAD) + +#if _WIN32||_WIN64 +#define WIN32_LEAN_AND_MEAN // exclude APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets. +#define NOMINMAX // do not let windows.h define macros min and max +#endif +#include +namespace Clasp { namespace mt { + typedef tbb::tbb_thread thread; + namespace this_thread { using tbb::this_tbb_thread::yield; } +}} + +#else +#include +namespace Clasp { namespace mt { + using std::thread; + namespace this_thread { using std::this_thread::yield; } +}} + +#endif +#endif diff --git a/libclasp/clasp/util/timer.h b/libclasp/clasp/util/timer.h new file mode 100644 index 0000000..29e36a9 --- /dev/null +++ b/libclasp/clasp/util/timer.h @@ -0,0 +1,72 @@ +// +// Copyright (c) 2006-2012, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#ifndef CLASP_TIMER_H_INCLUDED +#define CLASP_TIMER_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif +/*! + * \file + * \brief Defines various types for getting absolute times. + */ +namespace Clasp { + +//! A type for getting the current process time. +struct ProcessTime { + static double getTime(); +}; +//! A type for getting the current thread time. +struct ThreadTime { + static double getTime(); +}; +//! A tpe for getting the current wall-clock time. +struct RealTime { + static double getTime(); +}; +//! A class for measuring elapsed time. +/*! + * \tparam TimeType must provide a single static function + * TimeType::getTime() returning an absolute time. + */ +template +class Timer { +public: + Timer() : start_(0), split_(0), total_(0) {} + + void start() { start_ = TimeType::getTime(); } + void stop() { split(TimeType::getTime()); } + void reset() { *this = Timer(); } + //! Same as stop(), start(); + void lap() { double t; split(t = TimeType::getTime()); start_ = t; } + //! Returns the elapsed time (in seconds) for last start-stop cycle. + double elapsed() const { return split_; } + //! Returns the total elapsed time for all start-stop cycles. + double total() const { return total_; } +private: + void split(double t) { total_ += (split_ = t-start_); } + double start_; + double split_; + double total_; +}; + +} +#endif diff --git a/libclasp/clasp/util/type_manip.h b/libclasp/clasp/util/type_manip.h new file mode 100644 index 0000000..59b5b7c --- /dev/null +++ b/libclasp/clasp/util/type_manip.h @@ -0,0 +1,137 @@ +// +// Copyright (c) 2010, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef BK_LIB_TYPE_MANIP_H_INCLUDED +#define BK_LIB_TYPE_MANIP_H_INCLUDED +namespace bk_lib { namespace detail { +#if (_MSC_VER >= 1300) +#define ALIGNOF(PARAM) (__alignof(PARAM)) +#elif defined(__GNUC__) +#define ALIGNOF(PARAM) (__alignof__(PARAM)) +#else +template +struct align_helper { char x; T y; }; +#define ALIGNOF(T) (sizeof(align_helper)-sizeof(T)) +#endif + + +// if b then if_type else else_type +template +struct if_then_else; + +template +struct if_then_else { typedef if_type type; }; +template +struct if_then_else { typedef else_type type; }; + +// 1 if T == U, else 0 +template struct same_type { enum { value = 0 }; }; +template struct same_type { enum { value = 1 }; }; + +template struct disable_if { typedef bool type; }; +template <> struct disable_if { }; + +// not in list - marks end of type list +struct nil_type {}; + +// list of types - terminated by nil_type +template +struct type_list { + typedef head head_type; + typedef tail tail_type; +}; + +// generates a type lits with up to 18 elements +template < + typename T1 = nil_type, typename T2 = nil_type, typename T3 = nil_type, + typename T4 = nil_type, typename T5 = nil_type, typename T6 = nil_type, + typename T7 = nil_type, typename T8 = nil_type, typename T9 = nil_type, + typename T10 = nil_type, typename T11 = nil_type, typename T12 = nil_type, + typename T13 = nil_type, typename T14 = nil_type, typename T15 = nil_type, + typename T16 = nil_type, typename T17 = nil_type, typename T18 = nil_type +> +struct generate_type_list { + typedef typename generate_type_list::type tail_type; + typedef type_list type; +}; + +template <> +struct generate_type_list<> { typedef nil_type type; }; + +// maps an integer constant to a type +template +struct int2type { enum { value = i }; }; +typedef int2type<0> false_type; +typedef int2type<1> true_type; + +// declared but not defined +struct unknown_type; + +// finds the element in the type list TList that +// has the same alignment as X or X if no such element exists +template +struct max_align; + +// IF ALIGNOF(X) == ALIGNOF(H) then H +// ELSE max_align +template +struct max_align_aux; + +// Base case: ALIGNOF(X) == ALIGNOF(H) +template +struct max_align_aux { + typedef H type; +}; + +// Recursive case +template +struct max_align_aux { + typedef typename max_align::type type; +}; + +template +struct max_align { + typedef X type; +}; + +template +struct max_align > { +private: + enum { x_align = ALIGNOF(X) }; + enum { h_align = ALIGNOF(H) }; +public: + typedef typename max_align_aux(x_align) == static_cast(h_align), X, H, T>::type type; + enum { value = sizeof(type) }; +}; + +// computes alignment size (::value) and type (::type) of T +template +struct align_of { + typedef generate_type_list::type align_list; + typedef typename max_align::type type; + enum { value = max_align::value }; +}; + +#undef ALIGNOF + +}} +#endif + diff --git a/libclasp/clasp/weight_constraint.h b/libclasp/clasp/weight_constraint.h new file mode 100644 index 0000000..ec0f9fa --- /dev/null +++ b/libclasp/clasp/weight_constraint.h @@ -0,0 +1,229 @@ +// +// Copyright (c) 2006-2011, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef CLASP_SMODELS_CONSTRAINTS_H_INCLUDED +#define CLASP_SMODELS_CONSTRAINTS_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#endif + +#include + +namespace Clasp { + +//! Primitive representation of weight constraint literals in normal form. +struct WeightLitsRep { + //! Transforms the given literals to the normal form expected by WeightConstraint. + /*! + * The function simplifies lits and bound by removing assigned and + * merging duplicate/complementary literals. Furthermore, negative weights and + * their literals are inverted, bound is updated accordingly, and literals + * are sorted by decreasing weight. + */ + static WeightLitsRep create(Solver& s, WeightLitVec& lits, weight_t bound); + //! Propagates the constraint W == *this. + /*! + * If *this is always satisfied (bound <= 0) or unsatisfied (bound > reach), + * the function forward propagates W. Otherwise, if W is not free, it assigns + * (and removes) literals from *this that must hold. + */ + bool propagate(Solver& s, Literal W); + bool sat() const { return bound <= 0; } + bool unsat() const { return reach < bound; } + bool open() const { return bound > 0 && bound <= reach;} + bool hasWeights() const { return size && lits[0].second > 1; } + WeightLiteral* lits; /*!< Literals sorted by decreasing weight. */ + uint32 size; /*!< Number of literals in lits. */ + weight_t bound; /*!< Rhs of linear constraint. */ + weight_t reach; /*!< Sum of weights of lits. */ +}; + +//! Class implementing smodels-like cardinality- and weight constraints. +/*! + * \ingroup constraint + * This class represents a constraint of type W == w1*x1 ... wn*xn >= B, + * where W and each xi are literals and B and each wi are strictly positive integers. + * + * The class is used to represent smodels-like weight constraint, i.e. + * the body of a basic weight rule. In this case W is the literal associated with the body. + * A cardinality constraint is handled like a weight constraint where all weights are equal to 1. + * + * Given a WeightConstraint with bound \p B and set of literals \p L, + * - let \p sumTrue be the sum of the weights of all literals \p l in \p L that are currently true, + * - \p sumReach be the sum of the weights of all literals \p l in \p L that are currently not false, and + * - \p U be the set of literals \p l in \p L that are currently unassigned + * . + * the class implements the following four inference rules: + * - \b FTB: If \p sumTrue >= \p B: assign \p W to true. + * - \b BFB: If \p W is false: set false all literals \p l in \p U for which \p sumTrue + weight(\p l) >= \p B. + * - \b FFB: If \p sumReach < \p B: assign \p W to false. + * - \b BTB: If \p W is true: set true all literals \p l in \p U for which \p sumReach - weight(\p l) < \p B. + * . + */ +class WeightConstraint : public Constraint { +public: + //! Flags controlling weight constraint creation. + enum CreationFlags { + create_explicit = 1u, //!< Force creation of explicit constraint even if size/bound is small. + create_no_add = 3u, //!< Do not add constraint to solver db. + create_sat = 4u, //!< Force creation even if constraint is always satisfied. + create_no_freeze = 8u, //!< Do not freeze variables in constraint. + create_no_share =16u, //!< Do not allow sharing of literals between threads. + create_eq_bound =32u, //!< Create equality instead of greater-or-equal constraint. + create_only_btb =64u, //!< Only create FFB_BTB constraint. + create_only_bfb =128u,//!< Only create FTB_BFB constraint. + }; + //! Type used to communicate result of create(). + class CPair { + public: + CPair() { con[0] = con[1] = 0; } + bool ok() const { return con[0] != (WeightConstraint*)0x1 && con[1] != (WeightConstraint*)0x1; } + WeightConstraint* first() const { return con[0]; } + WeightConstraint* second()const { return con[1]; } + private: + friend class WeightConstraint; + WeightConstraint* con[2]; + }; + //! Creates a new weight constraint from the given weight literals. + /*! + * If the right hand side of the weight constraint is initially true/false (FTB/FFB), + * W is assigned appropriately but no constraint is created. Otherwise, + * the new weight constraint is added to s unless creationFlags contains create_no_add. + * + * \param s Solver in which the new constraint is to be used. + * \param W The literal that is associated with the constraint. + * \param lits The literals of the weight constraint. + * \param bound The lower bound of the weight constraint. + * \param creationFlags Set of CreationFlags to apply. + * \note Cardinality constraint are represented as weight constraints with all weights equal to 1. + * \note If creationFlags contains create_eq_bound, a constraint W == (lits == bound) is created that + * is represented by up to two weight constraints. + */ + static CPair create(Solver& s, Literal W, WeightLitVec& lits, weight_t bound, uint32 creationFlags = 0); + + //! Low level creation function. + /*! + * \note flag create_eq_bound is ignored by this function, that is, this function always creates + * a single >= constraint. + */ + static CPair create(Solver& s, Literal W, WeightLitsRep& rep, uint32 flags); + // constraint interface + Constraint* cloneAttach(Solver&); + bool simplify(Solver& s, bool = false); + void destroy(Solver*, bool); + PropResult propagate(Solver& s, Literal p, uint32& data); + void reason(Solver&, Literal p, LitVec& lits); + bool minimize(Solver& s, Literal p, CCMinRecursive* r); + void undoLevel(Solver& s); + uint32 estimateComplexity(const Solver& s) const; + /*! + * Logically, we distinguish two constraints: + * - FFB_BTB for handling forward false body and backward true body and + * - FTB_BFB for handling forward true body and backward false body. + * . + * Physically, we store the literals in one array: ~W=1, l0=w0,...,ln-1=wn-1. + */ + enum ActiveConstraint { + FFB_BTB = 0, //!< (\p SumW - \p B)+1 [~W=1, l0=w0,..., ln-1=wn-1] + FTB_BFB = 1, //!< \p B [ W=1,~l0=w0,...,~ln-1=wn-1] + }; + /*! + * Returns the i'th literal of constraint c, i.e. + * - li, iff c == FFB_BTB + * - ~li, iff c == FTB_BFB. + */ + Literal lit(uint32 i, ActiveConstraint c) const { return Literal::fromId( lits_->lit(i).id() ^ c ); } + //! Returns the weight of the i'th literal or 1 if constraint is a cardinality constraint. + weight_t weight(uint32 i) const { return lits_->weight(i); } + //! Returns the number of literals in this constraint (including W). + uint32 size() const { return lits_->size(); } + //! Returns false if constraint is a cardinality constraint. + bool isWeight() const { return lits_->weights(); } + // Returns the index of next literal to look at during backward propagation. + uint32 getBpIndex() const { return !isWeight() ? 1 : undo_[0].data>>1; } +private: + static WeightConstraint* doCreate(Solver& s, Literal W, WeightLitsRep& rep, uint32 flags); + bool integrateRoot(Solver& s); + struct WL { + WL(uint32 s, bool shared, bool w); + bool shareable() const { return rc != 0; } + bool unique() const { return rc == 0 || refCount() == 1; } + bool weights() const { return w != 0; } + uint32 size() const { return sz; } + Literal lit(uint32 i) const { return lits[(i<> 2; } + ActiveConstraint constraint() const { return static_cast((data&2) != 0); } + uint32 data; + }; + // Is literal idx contained as reason lit in the undo stack? + bool litSeen(uint32 idx) const { return (undo_[idx].data & 1) != 0; } + // Mark/unmark literal idx. + void toggleLitSeen(uint32 idx) { undo_[idx].data ^= 1; } + // Add watch for idx'th literal of c to the solver. + void addWatch(Solver& s, uint32 idx, ActiveConstraint c); + // Updates bound_[c] and adds an undo watch to the solver if necessary. + // Then adds the literal at position idx to the reason set (and the undo stack). + void updateConstraint(Solver& s, uint32 idx, ActiveConstraint c); + // Returns the starting index of the undo stack. + uint32 undoStart() const { return isWeight(); } + UndoInfo undoTop() const { assert(up_ != undoStart()); return undo_[up_-1]; } + // Returns the decision level of the last assigned literal + // or 0 if no literal was assigned yet. + uint32 highestUndoLevel(Solver&) const; + void setBpIndex(uint32 n); + WL* lits_; // literals of constraint + uint32 up_ : 27; // undo position; [undoStart(), up_) is the undo stack + uint32 ownsLit_: 1; // owns lits_? + uint32 active_ : 2; // which of the two sub-constraints is currently unit? + uint32 watched_: 2; // which constraint is watched (3 both, 2 ignore, FTB_BFB, FFB_BTB) + weight_t bound_[2]; // FFB_BTB: (sumW-bound)+1 / FTB_BFB: bound +CLASP_WARNING_BEGIN_RELAXED + UndoInfo undo_[0]; // undo stack + seen flag for each literal +CLASP_WARNING_END_RELAXED +}; +} + +#endif diff --git a/libclasp/libclasp.vcxproj b/libclasp/libclasp.vcxproj new file mode 100644 index 0000000..17c345b --- /dev/null +++ b/libclasp/libclasp.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {05763642-11D3-4442-A0E3-FF1705E0E552} + v4.5.2 + ManagedCProj + libclasp + 8.1 + + + + DynamicLibrary + true + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + Use + + + + + + + + Level3 + Disabled + _DEBUG;%(PreprocessorDefinitions) + Use + + + + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + Use + + + + + + + + Level3 + NDEBUG;%(PreprocessorDefinitions) + Use + + + + + + + + + \ No newline at end of file diff --git a/libclasp/libclasp.vcxproj.filters b/libclasp/libclasp.vcxproj.filters new file mode 100644 index 0000000..998b006 --- /dev/null +++ b/libclasp/libclasp.vcxproj.filters @@ -0,0 +1,254 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {ed564288-a14c-4fe7-aa0c-ba30ca050a34} + + + {a5009718-9718-4cc4-a296-401681ad54c8} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\cli + + + Header Files\cli + + + Header Files\cli + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + + + Header Files\cli + + + Header Files\cli + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/libclasp/src/asp_preprocessor.cpp b/libclasp/src/asp_preprocessor.cpp new file mode 100644 index 0000000..2334f70 --- /dev/null +++ b/libclasp/src/asp_preprocessor.cpp @@ -0,0 +1,540 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +namespace Clasp { namespace Asp { +///////////////////////////////////////////////////////////////////////////////////////// +// simple preprocessing +// +// Simplifies the program by computing max consequences. +// Then assign variables to non-trivial supported bodies and atoms. +///////////////////////////////////////////////////////////////////////////////////////// +bool Preprocessor::preprocessSimple() { + if (!prg_->propagate(true)) { return false; } + uint32 startVar = prg_->ctx()->numVars() + 1; + // start with initially supported bodies + VarVec& supported = prg_->getSupportedBodies(true); + VarVec unitBodies; + for (VarVec::size_type i = 0; i != supported.size(); ++i) { + // set up body + PrgBody* b = prg_->getBody(supported[i]); + if (!b->simplify(*prg_, false)) { return false; } + if (b->var() < startVar) { + if (b->size() != 1) { b->assignVar(*prg_); } + else { unitBodies.push_back(supported[i]); } + } + // add all heads of b to the "upper"-closure and + // remove any false/removed atoms from head + if (!addHeadsToUpper(b) || !b->simplifyHeads(*prg_, true)) { + return false; + } + } + for (VarVec::const_iterator it = unitBodies.begin(), end = unitBodies.end(); it != end; ++it) { + prg_->getBody(*it)->assignVar(*prg_); + } + return prg_->propagate(); +} + +bool Preprocessor::addHeadToUpper(PrgHead* head, PrgEdge support) { + assert(head->relevant() && !head->inUpper()); + head->simplifySupports(*prg_, false); + head->assignVar(*prg_, support, eq()); + head->clearSupports(); + head->setInUpper(true); + if (head->isAtom()) { + return propagateAtomVar(static_cast(head), support); + } + // add all unseen atoms of disjunction to upper + PrgDisj* d = static_cast(head); + support = PrgEdge::newEdge(*d, PrgEdge::Choice); + bool ok = true; + for (PrgDisj::atom_iterator it = d->begin(), end = d->end(); it != end && ok; ++it) { + PrgAtom* at = prg_->getAtom(*it); + if (!at->relevant()) { continue; } + if (!at->inUpper()) { ok = addHeadToUpper(at, support); } + at->addSupport(support); + } + return ok; +} +///////////////////////////////////////////////////////////////////////////////////////// +// equivalence preprocessing +// +// Computes max consequences and minimizes the number of necessary variables +// by computing equivalence-classes. +///////////////////////////////////////////////////////////////////////////////////////// +bool Preprocessor::preprocessEq(uint32 maxIters) { + uint32 startVar = prg_->ctx()->numVars(); + ValueRep res = value_true; + pass_ = 0; + maxPass_ = maxIters; + HeadRange atoms = HeadRange(prg_->atom_begin() + prg_->startAtom(), prg_->atom_end()); + bodyInfo_.resize( prg_->numBodies() + 1 ); + do { + if (++pass_ > 1) { + for (HeadIter it = prg_->atom_begin(), end = atoms.second; it != end; ) { + while (it != atoms.first){ (*it)->setInUpper(false); ++it; } + while (it != end) { (*it)->clearLiteral(false); (*it)->setInUpper(false); ++it; } + } + for (HeadIter it = prg_->disj_begin(), end = prg_->disj_end(); it != end; ++it) { + (*it)->clearLiteral(false); + (*it)->setInUpper(false); + } + prg_->ctx()->popVars(prg_->ctx()->numVars() - startVar); + litToNode_.clear(); + } + VarVec& supported = prg_->getSupportedBodies(true); + if (!classifyProgram(supported)) { return false; } + res = simplifyClassifiedProgram(atoms, pass_ != maxPass_, supported); + } while (res == value_free && pass_ != maxPass_); + return res != value_false; +} + +// Computes necessary equivalence-classes starting from the supported bodies +// of a program. +bool Preprocessor::classifyProgram(const VarVec& supported) { + Var bodyId; PrgBody* body; + VarVec::size_type index = 0; + follow_.clear(); + if (!prg_->propagate(true)) { return false; } + for (VarVec::size_type i = 0;;) { + while ( (bodyId = nextBodyId(index)) != varMax ) { + body = addBodyVar(bodyId); + if (prg_->hasConflict()) { return false; } + if (!addHeadsToUpper(body)) { return false; } + } + follow_.clear(); + index = 0; + // select next unclassified supported body + for (; i < supported.size(); ++i) { + bodyId = supported[i]; + body = prg_->getBody(bodyId); + if (bodyInfo_[bodyId].bSeen == 0 && body->relevant()) { + follow_.push_back(bodyId); + break; + } + else if (!body->relevant() && body->hasVar()) { + body->clearLiteral(false); + } + } + if (follow_.empty()) break; + } + return !prg_->hasConflict(); +} + +ValueRep Preprocessor::simplifyClassifiedProgram(const HeadRange& atoms, bool more, VarVec& supported) { + ValueRep res = value_true, simp; + if (!prg_->propagate()) { return value_false; } + supported.clear(); + // simplify supports + for (uint32 i = 0; i != prg_->numBodies(); ++i) { + PrgBody* b = prg_->getBody(i); + if (bodyInfo_[i].bSeen == 0 || !b->relevant()) { + // !bodyInfo_[i].bSeen: body is unsupported + // !b->relevant() : body is eq to other body or was derived to false + // In either case, body is no longer relevant and can be ignored. + b->clearLiteral(true); + b->markRemoved(); + } + else if ( (simp = simplifyBody(b, more, supported)) != value_true ) { + if (simp == value_false) { return simp; } + res = value_free; + } + } + if (!prg_->propagate()) { return value_false; } + PrgEdge noSup = PrgEdge::noEdge(); + for (LogicProgram::VarIter it = prg_->unfreeze_begin(), end = prg_->unfreeze_end(); it != end; ++it) { + PrgAtom* a = prg_->getAtom(*it); + ValueRep v = a->value(); + if (!a->simplifySupports(*prg_, true)){ return value_false; } + else if (!a->inUpper() && v != value_false){ + if (!prg_->assignValue(a, value_false, noSup)){ return value_false; } + if (more && a->hasDep(PrgAtom::dep_all)) { res = value_free; } + } + } + if (!prg_->propagate()) { return value_false; } + bool strong = more && res == value_true; + HeadRange heads[2] = { HeadRange(prg_->disj_begin(), prg_->disj_end()), atoms }; + for (const HeadRange* range = heads, *endR = heads+2; range != endR; ++range) { + for (HeadIter it = range->first, end = range->second; it != end; ++it) { + PrgHead* head = *it; + if ((simp = simplifyHead(head, strong)) != value_true) { + if (simp == value_false){ return simp; } + else if (strong) { strong = false; res = value_free; } + } + } + } + if (!prg_->propagate()) { res = value_false; } + return res; +} + +// associates a variable with the body if necessary +PrgBody* Preprocessor::addBodyVar(Var bodyId) { + // make sure we don't add an irrelevant body + PrgBody* body = prg_->getBody(bodyId); + assert((body->isSupported() && !body->eq()) || body->hasVar()); + body->clearLiteral(false); // clear var in case we are iterating + bodyInfo_[bodyId].bSeen = 1; // mark as seen, so we don't classify the body again + bool known = bodyInfo_[bodyId].known == body->size(); + uint32 eqId; + if (!body->simplifyBody(*prg_, known, &eqId) || !body->simplifyHeads(*prg_, false)) { + prg_->setConflict(); + return body; + } + if (superfluous(body)) { + body->markRemoved(); + return body; + } + if (eqId == bodyId) { + // The body is unique + body->assignVar(*prg_); + PrgAtom* aEq = body->size() == 1 ? prg_->getAtom(body->goal(0).var()) : 0; + if (!known) { body->markDirty(); } + else if (aEq && aEq->var() == body->var()){ + // Body is equivalent to an atom or its negation + // Check if the atom is itself equivalent to a body. + // If so, the body is equivalent to the atom's body. + PrgBody* r = 0; // possible eq-body + uint32 rId = varMax; + if (body->goal(0).sign()) { + Var dualAtom = getRootAtom(body->literal()); + aEq = dualAtom != varMax ? prg_->getAtom(dualAtom) : 0; + } + if (aEq && aEq->supports() && aEq->supps_begin()->isBody()) { + rId = aEq->supps_begin()->node(); + r = prg_->getBody(rId); + if (r && r->var() == aEq->var()) { + mergeEqBodies(body, rId, false); + } + } + } + } + else { + // body is eq to eq body + mergeEqBodies(body, eqId, true); + } + return body; +} + +// Adds all heads of body to the upper closure if not yet present and +// associates variables with the heads if necessary. +// The body b is the supported body that provides a support for the heads. +// RETURN: true if no conflict +// POST : the addition of atoms to the closure was propagated +bool Preprocessor::addHeadsToUpper(PrgBody* body) { + PrgHead* head; + PrgEdge support; + bool ok = !prg_->hasConflict(); + int dirty= 0; + for (PrgBody::head_iterator it = body->heads_begin(), end = body->heads_end(); it != end && ok; ++it) { + head = prg_->getHead(*it); + support= PrgEdge::newEdge(*body, it->type()); + if (head->relevant() && head->value() != value_false) { + if (body->value() == value_true && head->isAtom()) { + // Since b is true, it is always a valid support for head, head can never become unfounded. + // So ignore it during SCC check and unfounded set computation. + head->setIgnoreScc(true); + if (support.isNormal() && head->isAtom()) { + ok = propagateAtomValue(static_cast(head), value_true, support); + } + } + if (!head->inUpper()) { + // first time we see this head - assign var... + ok = addHeadToUpper(head, support); + } + else if (head->supports() && head->supps_begin()->isNormal()) { + PrgEdge source = *head->supps_begin(); + assert(source.isBody()); + if (prg_->getBody(source.node())->var() == body->var()) { + // Check if we really need a new variable for head. + head->markDirty(); + } + } + head->addSupport(support, PrgHead::no_simplify); + } + dirty += (head->eq() || head->value() == value_false); + } + if (dirty) { + // remove eq atoms from head + prg_->getBody(body->id())->markHeadsDirty(); + } + return ok; +} + +// Propagates that a was added to the "upper"-closure. +// If atom a has a truth-value or is eq to a', we'll remove +// it from all bodies. If there is an atom x, s.th. a.lit == ~x.lit, we mark all +// bodies containing both a and x for simplification in order to detect +// duplicates/contradictory body-literals. +// In case that a == a', we also mark all bodies containing a +// for head simplification in order to detect rules like: a' :- a,B. and a' :- B,not a. +bool Preprocessor::propagateAtomVar(PrgAtom* a, PrgEdge source) { + const Var aId = a->id(); + PrgAtom* comp = 0; + ValueRep value = a->value(); + bool fullEq = eq(); + bool removeAtom = value == value_true || value == value_false; + bool removeNeg = removeAtom || value == value_weak_true; + Literal aLit = a->literal(); + if (fullEq) { + if (getRootAtom(aLit) == varMax) { + setRootAtom(aLit, aId); + } + else if (prg_->mergeEqAtoms(a, getRootAtom(aLit))) { + assert(source.isBody()); + removeAtom = true; + removeNeg = true; + value = a->value(); + PrgBody* B = prg_->getBody(source.node()); + a->setEqGoal(posLit(a->id())); + // set positive eq goal - replace if a == {not a'}, replace a with not a' in bodies + if (getRootAtom(~aLit) != varMax && B->literal() == aLit && B->size() == 1 && B->goal(0).sign()) { + a->setEqGoal(negLit(getRootAtom(~aLit))); + } + a->clearLiteral(true); // equivalent atoms don't need vars + } + else { return false; } + } + if (getRootAtom(~aLit) != varMax) { + PrgAtom* negA = prg_->getAtom(getRootAtom(~aLit)); + assert(aLit == ~negA->literal()); + // propagate any truth-value to complementary eq-class + ValueRep cv = value_free; + uint32 mark = 0; + if (value != value_free && (cv = (value_false | (value^value_true))) != negA->value()) { + mark = 1; + if (!propagateAtomValue(negA, cv, PrgEdge::noEdge())) { + return false; + } + } + if ( !removeAtom ) { + for (PrgAtom::dep_iterator it = (comp=negA)->deps_begin(); it != comp->deps_end(); ++it) { + bodyInfo_[it->var()].mBody = 1; + if (mark) { prg_->getBody(it->var())->markDirty(); } + } + } + } + for (PrgAtom::dep_iterator it = a->deps_begin(), end = a->deps_end(); it != end; ++it) { + Var bodyId = it->var(); + PrgBody* bn = prg_->getBody(bodyId); + if (bn->relevant()) { + bool wasSup = bn->isSupported(); + bool isSup = wasSup || (value != value_false && !it->sign() && bn->propagateSupported(aId)); + bool seen = false; + bool dirty = removeAtom || (removeNeg && it->sign()); + if (fullEq) { + seen = bodyInfo_[bodyId].bSeen != 0; + dirty |= bodyInfo_[bodyId].mBody == 1; + if (++bodyInfo_[bodyId].known == bn->size() && !seen && isSup) { + follow_.push_back( bodyId ); + seen = true; + } + } + if (!seen && isSup && !wasSup) { + prg_->getSupportedBodies(false).push_back(bodyId); + } + if (dirty) { + bn->markDirty(); + if (a->eq()) { + bn->markHeadsDirty(); + } + } + } + } + if (removeAtom) { a->clearDeps(PrgAtom::dep_all); } + else if (removeNeg) { a->clearDeps(PrgAtom::dep_neg); } + if (comp) { + for (PrgAtom::dep_iterator it = comp->deps_begin(), end = comp->deps_end(); it != end; ++it) { + bodyInfo_[it->var()].mBody = 0; + } + } + return true; +} + +// Propagates the assignment of val to a. +bool Preprocessor::propagateAtomValue(PrgAtom* atom, ValueRep val, PrgEdge sup) { + // No backpropagation possible because supports are not yet fully established. + return prg_->assignValue(atom, val, sup) && prg_->propagate(false); +} + +bool Preprocessor::mergeEqBodies(PrgBody* body, Var rootId, bool equalLits) { + PrgBody* root = prg_->mergeEqBodies(body, rootId, equalLits, false); + if (root && root != body && bodyInfo_[root->id()].bSeen == 0) { + // If root is not yet classified, we can ignore body. + // The heads of body are added to the "upper"-closure + // once root is eventually classified. + body->clearHeads(); + body->markRemoved(); + } + return root != 0; +} + +bool Preprocessor::hasRootLiteral(PrgBody* body) const { + return body->size() >= 1 + && getRootAtom(body->literal()) == varMax + && getRootAtom(~body->literal())== varMax; +} + +// Pre: body is simplified! +bool Preprocessor::superfluous(PrgBody* body) const { + if (!body->relevant()) { return true; } + if (!body->inRule()) { + if (body->value() == value_free) { return true; } + if (body->bound() <= 0) { return true; } + if (body->size() == 1) { + // unit constraint + ValueRep exp = body->value() ^ (int)body->goal(0).sign(); + ValueRep got = prg_->getAtom(body->goal(0).var())->value(); + assert(got != value_free || !prg_->options().backprop); + return got != value_free && (got&value_true) == (exp&value_true); + } + } + return false; +} + +// Simplify the classified body with the given id. +// Return: +// value_false : conflict +// value_true : ok +// value_weak_true: ok but program should be reclassified +ValueRep Preprocessor::simplifyBody(PrgBody* b, bool reclass, VarVec& supported) { + assert(b->relevant() && bodyInfo_[b->id()].bSeen == 1); + bodyInfo_[b->id()].bSeen = 0; + bodyInfo_[b->id()].known = 0; + bool hadHeads = b->hasHeads(); + bool hasRoot = hasRootLiteral(b); + uint32 eqId = b->id(); + if (!b->simplify(*prg_, true, &eqId)) { + return value_false; + } + ValueRep ret = value_true; + if (reclass) { + if (hadHeads && b->value() == value_false) { + assert(b->hasHeads() == false); + // New false body. If it was derived to false, we can ignore the body. + // Otherwise, we have a new integrity constraint. + if (!b->relevant()) { + b->clearLiteral(true); + } + } + else if (b->var() != 0 && superfluous(b)) { + // Body is no longer needed. All heads are either superfluous or equivalent + // to other atoms. + // Reclassify only if var is not used + if (getRootAtom(b->literal()) == varMax) { ret = value_weak_true; } + b->clearLiteral(true); + b->markRemoved(); + } + else if (b->value() == value_true && b->var() != 0) { + // New fact body + for (PrgBody::head_iterator it = b->heads_begin(), end = b->heads_end(); it != end; ++it) { + if (it->isNormal() && prg_->getHead(*it)->var() != 0) { + ret = value_weak_true; + break; + } + } + b->markDirty(); + } + } + if (b->relevant() && eqId != b->id() && (reclass || prg_->getBody(eqId)->var() == b->var())) { + // Body is now eq to some other body - reclassify if body var is not needed + Var bVar = b->var(); + prg_->mergeEqBodies(b, eqId, true, true); + if (hasRoot && bVar != b->var()) { + ret = value_weak_true; + } + } + if (b->relevant() && b->resetSupported()) { + supported.push_back(b->id()); + } + return ret; +} + +// Simplify the classified head h. +// Update list of bodies defining this head and check +// if atom or disjunction has a distinct var although it is eq to some body. +// Return: +// value_false : conflict +// value_true : ok +// value_weak_true: ok but atom should be reclassified +ValueRep Preprocessor::simplifyHead(PrgHead* h, bool more) { + if (!h->hasVar() || !h->relevant()) { + // unsupported or eq + h->clearLiteral(false); + h->markRemoved(); + h->clearSupports(); + h->setInUpper(false); + return value_true; + } + assert(h->inUpper()); + ValueRep v = h->value(); + ValueRep ret = value_true; + PrgEdge support = h->supports() ? *h->supps_begin() : PrgEdge::noEdge(); + uint32 numSuppLits= 0; + if (!h->simplifySupports(*prg_, true, &numSuppLits)) { + return value_false; + } + if (v != h->value() && (h->value() == value_false || (h->value() == value_true && h->var() != 0))) { + ret = value_weak_true; + } + if (more) { + if (numSuppLits == 0 && h->hasVar()) { + // unsupported head does not need a variable + ret = value_weak_true; + } + else if (h->supports() > 0 && h->supps_begin()->rep != support.rep) { + // support for head has changed + ret = value_weak_true; + } + else if ((support.isNormal() && h->supports() == 1) || (h->supports() > 1 && numSuppLits == 1 && h->isAtom())) { + assert(support.isBody()); + PrgBody* supBody = prg_->getBody(support.node()); + if (supBody->literal() != h->literal()) { + if (h->supports() > 1) { + // atom is equivalent to one of its bodies + EdgeVec temp(h->supps_begin(), h->supps_end()); + h->clearSupports(); + support = temp[0]; + for (EdgeIterator it = temp.begin(), end = temp.end(); it != end; ++it) { + assert(!it->isDisj()); + PrgBody* B = prg_->getBody(it->node()); + if (it->isNormal() && B->size() == 1 && B->goal(0).sign()) { + support = *it; + } + B->removeHead(h, it->type()); + } + supBody = prg_->getBody(support.node()); + supBody->addHead(h, support.type()); + if (!supBody->simplifyHeads(*prg_, true)) { + return value_false; + } + } + ret = value_weak_true; + if (h->value() == value_weak_true || h->value() == value_true) { + supBody->assignValue(h->value()); + supBody->propagateValue(*prg_, true); + } + } + } + } + return ret; +} + +} } diff --git a/libclasp/src/cb_enumerator.cpp b/libclasp/src/cb_enumerator.cpp new file mode 100644 index 0000000..8279756 --- /dev/null +++ b/libclasp/src/cb_enumerator.cpp @@ -0,0 +1,349 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#if WITH_THREADS +#include +#define ACQUIRE_LOCK(m) while ( (m).fetch_and_store(1) != 0 ) Clasp::mt::this_thread::yield() +#define RELEASE_LOCK(m) (m) = 0 +#else +#define ACQUIRE_LOCK(m) +#define RELEASE_LOCK(m) +#endif +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// CBConsequences::SharedConstraint +///////////////////////////////////////////////////////////////////////////////////////// +class CBConsequences::SharedConstraint { +public: + SharedConstraint() : current(0) { mutex = 0; } + SharedLiterals* fetch_if_neq(SharedLiterals* last) const { + ACQUIRE_LOCK(mutex); + SharedLiterals* ret = last != current ? current->share() : 0; + RELEASE_LOCK(mutex); + return ret; + } + void release(SharedLiterals* newLits) { + ACQUIRE_LOCK(mutex); + SharedLiterals* old = current; + current = newLits; + RELEASE_LOCK(mutex); + if (old) { old->release(); } + } + SharedLiterals* current; + typedef Clasp::Atomic_t::type MutexType; + mutable MutexType mutex; +}; +#undef ACQUIRE_LOCK +#undef RELEASE_LOCK +///////////////////////////////////////////////////////////////////////////////////////// +// CBConsequences::CBFinder +///////////////////////////////////////////////////////////////////////////////////////// +class CBConsequences::CBFinder : public EnumerationConstraint { +public: + typedef CBConsequences::SharedConstraint SharedCon; + typedef Solver::ConstraintDB ConstraintDB; + typedef SharedLiterals SharedLits; + explicit CBFinder(SharedCon* sh) : EnumerationConstraint(), shared(sh), last(0) {} + ConPtr clone() { return new CBFinder(shared); } + void doCommitModel(Enumerator& ctx, Solver& s) { static_cast(ctx).addCurrent(s, current, s.model, rootLevel()); } + void destroy(Solver* s, bool detach); + bool doUpdate(Solver& s); + void pushLocked(Solver& s, ClauseHead* h); + LitVec current; + SharedCon* shared; + SharedLits* last; + ConstraintDB locked; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// CBConsequences::QueryFinder +///////////////////////////////////////////////////////////////////////////////////////// +class CBConsequences::QueryFinder : public EnumerationConstraint{ +public: + class State { + public: + State(Model& m, uint32 nVars) : model_(&m) { + refs_ = 1; + size_ = nVars; + value_ = new ValueType[nVars]; + for (uint32 i = 0; i != nVars; ++i) { value_[i] = 0; } + } + State* share() { ++refs_; return this; } + void release() { if (--refs_ == 0) delete this; } + uint32 size() const { return size_; } + bool open(Literal p) const { return (value_[p.var()] & Model::estMask(p)) != 0; } + void setModel(Clasp::ValueVec& m, bool update) { + m.assign(value_, value_ + size_); + if (update) { model_->values = &m; model_->up = 1; } + } + void push(Literal p) { value_[p.var()] = Model::estMask(p)|trueValue(p);} + void pop(Literal p) { value_[p.var()] = 0; } + void fix(Literal p) { value_[p.var()] = trueValue(p); } + private: + ~State() { delete [] value_; } + typedef Clasp::Atomic_t::type ValueType; + typedef Clasp::Atomic_t::type SizeType; + typedef ValueType* ValueVec; + ValueVec value_; + Model* model_; + uint32 size_; + SizeType refs_; + }; + explicit QueryFinder(const LitVec& c, Model& m, uint32 nVars) : EnumerationConstraint(), open_(c), state_(new State(m, nVars)), query_(lit_false()), level_(0), dirty_(false) { + state_->push(query_); + } + explicit QueryFinder(const LitVec& c, State* st) : EnumerationConstraint(), open_(c), state_(st), query_(lit_false()), level_(0), dirty_(false) { + } + ~QueryFinder() { state_->release(); } + ConPtr clone() { return new QueryFinder(open_, state_->share()); } + bool hasQuery() const { return query_ != lit_false(); } + bool doUpdate(Solver& s); + void doCommitModel(Enumerator&, Solver&); + void doCommitUnsat(Enumerator&, Solver&); + void updateUpper(Solver& s, uint32 rl, ValueVec& mOut); + void updateLower(Solver& s, uint32 rl, ValueVec& mOut); + bool selectOpen(Solver& s, Literal& q); + void reason(Solver& s, Literal p, LitVec& out) { + for (uint32 i = 1, end = s.level(p.var()); i <= end; ++i) { + Literal q = s.decision(i); + if (q != p) { out.push_back(q); } + } + } + bool popQuery(Solver& s) { + if (!hasQuery() || s.rootLevel() == level_ || s.value(query_.var()) == value_free) { + return s.popRootLevel(0); + } + return s.popRootLevel((s.rootLevel() - level_) + 1); + } + LitVec open_; + State* state_; + Literal query_; + uint32 level_; + bool dirty_; +}; +// Reduce the overestimate by computing c = c \cap M, +// where M is the current model stored in s. +void CBConsequences::QueryFinder::updateUpper(Solver& s, uint32 root, ValueVec& mOut) { + LitVec::iterator j = open_.begin(); + for (LitVec::iterator it = j, end = open_.end(); it != end; ++it) { + if (!state_->open(*it)) { continue; } + else if (!s.isTrue(*it)) { state_->pop(*it); } + else if (s.level(it->var()) > root) { *j++ = *it; } + else { state_->fix(*it); } + } + open_.erase(j, open_.end()); + state_->setModel(mOut, dirty_ = false); +} +// Adds facts to (under) estimate. +void CBConsequences::QueryFinder::updateLower(Solver& s, uint32 rl, ValueVec& mOut) { + LitVec::iterator j = open_.begin(); + for (LitVec::iterator it = j, end = open_.end(); it != end; ++it) { + ValueRep val = s.value(it->var()); + if (val != value_free && s.level(it->var()) > rl) { + val = value_free; + } + if (!state_->open(*it)) { continue; } + else if (val == value_free) { *j++ = *it; } + else if (s.isTrue(*it)) { state_->fix(*it); } + else { state_->pop(*it); } + } + if (j != open_.end()) { dirty_ = true; } + open_.erase(j, open_.end()); + state_->setModel(mOut, dirty_); + dirty_ = false; +} +bool CBConsequences::QueryFinder::selectOpen(Solver& s, Literal& q) { + for (LitVec::size_type i = 0, end = open_.size();; --end, open_.pop_back()) { + for (; i != end && s.value(open_[i].var()) == value_free && state_->open(open_[i]); ++i) { ; } + if (i == end) { break; } + q = open_[i]; + open_[i] = open_.back(); + if (s.isTrue(q)) { state_->fix(q); } + else { state_->pop(q); } + dirty_ = true; + } + if (open_.empty()) { return false; } + q = s.heuristic()->selectRange(s, &open_[0], &open_[0] + open_.size()); + return true; +} +// solve(~query) produced a model - query is not a cautious consequence, update overstimate +void CBConsequences::QueryFinder::doCommitModel(Enumerator&, Solver& s) { + if (!hasQuery() && state_->open(query_)) { + // init state to first model + for (LitVec::iterator it = open_.begin(), end = open_.end(); it != end; ++it) { + if (s.isTrue(*it)) { state_->push(*it); } + } + } + state_->pop(query_); + updateUpper(s, level_, s.model); + query_.flag(); +} +// solve(~query) failed - query is a cautious consequence +void CBConsequences::QueryFinder::doCommitUnsat(Enumerator&, Solver& s) { + bool commit = !disjointPath() && s.hasConflict() && !s.hasStopConflict() && hasQuery(); + popQuery(s); + if (commit) { + state_->fix(query_); + query_.flag(); + } + updateLower(s, level_, s.model); +} +bool CBConsequences::QueryFinder::doUpdate(Solver& s) { + bool newQ = query_.flagged() || !state_->open(query_); + if (newQ || s.value(query_.var()) == value_free) { // query was SAT/UNSAT or solved by other thread + if (!popQuery(s)) { return false; } + assert(s.decisionLevel() == s.rootLevel()); + level_ = s.rootLevel(); + return newQ && !selectOpen(s, query_) ? s.force(query_ = lit_false(), this) : s.pushRoot(~query_); + } + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// CBConsequences +///////////////////////////////////////////////////////////////////////////////////////// +CBConsequences::CBConsequences(Type type, Algo algo) + : Enumerator() + , shared_(0) + , type_(type) + , algo_(algo) { + if (type_ != Cautious) { algo_ = Default; } +} + +Enumerator* EnumOptions::createConsEnumerator(const EnumOptions& opts) { + return new CBConsequences(opts.enumMode == enum_brave ? CBConsequences::Brave : CBConsequences::Cautious, opts.enumMode != enum_query ? CBConsequences::Default : CBConsequences::Query); +} +CBConsequences::~CBConsequences() { + delete shared_; +} +bool CBConsequences::supportsSplitting(const SharedContext& problem) const { + return algo_ == Default && Enumerator::supportsSplitting(problem); +} +int CBConsequences::unsatType() const { + return algo_ == Default ? Enumerator::unsatType() : Enumerator::unsat_sync; +} +EnumerationConstraint* CBConsequences::doInit(SharedContext& ctx, SharedMinimizeData* m, int) { + cons_.clear(); + const OutputTable& out = ctx.output; + if (out.projectMode() == OutputTable::project_output) { + for (OutputTable::pred_iterator it = out.pred_begin(), end = out.pred_end(); it != end; ++it) { + addLit(ctx, it->cond); + } + for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) { + addLit(ctx, posLit(*it)); + } + } + else { + for (OutputTable::lit_iterator it = out.proj_begin(), end = out.proj_end(); it != end; ++it) { + addLit(ctx, *it); + } + } + // init M to either cons or {} depending on whether we compute cautious or brave cons. + const uint32 fMask = (type_ == Cautious && algo_ != Query); + const uint32 vMask = (type_ == Cautious) ? 3u : 0u; + for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) { + it->rep() |= fMask; + ctx.unmark(it->var()); + if (!ctx.varInfo(it->var()).nant()) { + ctx.master()->setPref(it->var(), ValueSet::def_value, static_cast(trueValue(*it) ^ vMask)); + } + } + delete shared_; shared_ = 0; + setIgnoreSymmetric(true); + if (m && m->optimize() && algo_ == Query) { + ctx.warn("Query algorithm does not support optimization!"); + algo_ = Default; + } + if (type_ != Cautious || algo_ != Query) { + shared_ = ctx.concurrency() > 1 ? new SharedConstraint() : 0; + return new CBFinder(shared_); + } + return new QueryFinder(cons_, model(), ctx.numVars() + 1); +} +void CBConsequences::addLit(SharedContext& ctx, Literal p) { + if (!ctx.marked(p) && !ctx.eliminated(p.var())) { + cons_.push_back(p); + ctx.setFrozen(p.var(), true); + ctx.mark(p); + } +} +void CBConsequences::addCurrent(Solver& s, LitVec& con, ValueVec& m, uint32 root) { + con.assign(1, ~s.sharedContext()->stepLiteral()); + // reset state of relevant variables + for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) { + m[it->var()] = 0; + } + // let M be all lits p with p.watch() == true + for (LitVec::iterator it = cons_.begin(), end = cons_.end(); it != end; ++it) { + Literal& p = *it; + uint32 dl = s.level(p.var()); + uint32 ost = dl > root ? Model::estMask(p) : 0; + if (type_ == Brave) { + // brave: extend M with true literals and force a literal not in M to true + if (p.flagged() || s.isTrue(p)) { p.flag(); ost = 0; } + else if (dl) { con.push_back(p); } + } + else if (type_ == Cautious) { + // cautious: intersect M with true literals and force a literal in M to false + if (!p.flagged() || s.isFalse(p)) { p.unflag(); ost = 0; } + else if (dl) { con.push_back(~p); } + } + // set output state + if (p.flagged()) { ost |= trueValue(p); } + m[p.var()] |= ost; + } + if (shared_) { + shared_->release(SharedLiterals::newShareable(con, Constraint_t::Other, 1)); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// CBConsequences::CBFinder implementation +///////////////////////////////////////////////////////////////////////////////////////// +void CBConsequences::CBFinder::destroy(Solver* s, bool detach) { + Clasp::destroyDB(locked, s, detach); + if (last) { + last->release(); + } + EnumerationConstraint::destroy(s, detach); +} +void CBConsequences::CBFinder::pushLocked(Solver& s, ClauseHead* c) { + for (ClauseHead* h; !locked.empty() && !(h = static_cast(locked.back()))->locked(s);) { + h->destroy(&s, true); + locked.pop_back(); + } + locked.push_back(c); +} +bool CBConsequences::CBFinder::doUpdate(Solver& s) { + ClauseCreator::Result ret; + uint32 flags = ClauseCreator::clause_explicit|ClauseCreator::clause_no_add; + if (!shared) { + ret = !current.empty() ? ClauseCreator::create(s, current, flags, ConstraintInfo(Constraint_t::Other)) : ClauseCreator::Result(); + } + else if (SharedLiterals* x = shared->fetch_if_neq(last)) { + if (last) { last->release(); } + last = x; + ret = ClauseCreator::integrate(s, x, flags | ClauseCreator::clause_no_release); + } + if (ret.local) { pushLocked(s, ret.local); } + current.clear(); + return ret.ok(); +} +} diff --git a/libclasp/src/clasp_facade.cpp b/libclasp/src/clasp_facade.cpp new file mode 100644 index 0000000..17a6d47 --- /dev/null +++ b/libclasp/src/clasp_facade.cpp @@ -0,0 +1,1053 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if WITH_THREADS +#include +#endif +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspConfig +///////////////////////////////////////////////////////////////////////////////////////// +struct ClaspConfig::Impl { + struct ConfiguratorProxy { + enum { OnceBit = 62, AcquireBit = 61 }; + ConfiguratorProxy(Configurator* c, Ownership_t::Type own, bool once) : cfg(reinterpret_cast(c)), set(0) { + if (once) { store_set_bit(cfg, OnceBit); } + if (own == Ownership_t::Acquire) { store_set_bit(cfg, AcquireBit); } + assert(ptr() == c); + } + bool addPost(Solver& s) { + CLASP_FAIL_IF(s.id() > 63, "invalid solver id!"); + if (test_bit(set, s.id())) { return true; } + if (test_bit(cfg, OnceBit)) { store_set_bit(set, s.id()); } + return this->ptr()->addPost(s); + } + void prepare(SharedContext& ctx) { + if (ctx.concurrency() < 64) { + set &= (bit_mask(ctx.concurrency()) - 1); + } + ptr()->prepare(ctx); + } + void destroy() { if (test_bit(cfg, AcquireBit)) { delete ptr(); } } + Configurator* ptr() const { + static const uint64 ptrMask = ~(bit_mask(OnceBit) | bit_mask(AcquireBit)); + return reinterpret_cast(static_cast(cfg & ptrMask)); + } + uint64 cfg; + uint64 set; + }; + typedef PodVector::type PPVec; + Impl() { acycSet = 0; } + ~Impl() { reset(); } + void reset(); + void prepare(SharedContext& ctx); + bool addPost(Solver& s, const SolverParams& opts); + void add(Configurator* c, Ownership_t::Type t, bool once) { pp.push_back(ConfiguratorProxy(c, t, once)); } + PPVec pp; + uint64 acycSet; +#if WITH_THREADS + Clasp::mt::mutex mutex; +#endif +}; +void ClaspConfig::Impl::reset() { + for (; !pp.empty(); pp.pop_back()) { pp.back().destroy(); } +} + +void ClaspConfig::Impl::prepare(SharedContext& ctx) { + if (ctx.concurrency() < 64) { + acycSet &= (bit_mask(ctx.concurrency()) - 1); + } + for (PPVec::iterator it = pp.begin(), end = pp.end(); it != end; ++it) { + it->prepare(ctx); + } +} +bool ClaspConfig::Impl::addPost(Solver& s, const SolverParams& opts) { +#if WITH_THREADS +#define LOCKED() for (Clasp::mt::unique_lock lock(mutex); lock.owns_lock(); lock.unlock()) +#else +#define LOCKED() +#endif + CLASP_FAIL_IF(s.sharedContext() == 0, "Solver not attached!"); + if (s.sharedContext()->sccGraph.get()) { + if (DefaultUnfoundedCheck* pp = static_cast(s.getPost(PostPropagator::priority_reserved_ufs))) { + pp->setReasonStrategy(static_cast(opts.loopRep)); + } + else if (!s.addPost(new DefaultUnfoundedCheck(*s.sharedContext()->sccGraph, static_cast(opts.loopRep)))) { + return false; + } + } + if (s.sharedContext()->extGraph.get()) { + bool addAcyc = false; + // protect access to acycSet + LOCKED() { addAcyc = !test_bit(acycSet, s.id()) && store_set_bit(acycSet, s.id()); } + if (addAcyc && !s.addPost(new AcyclicityCheck(s.sharedContext()->extGraph.get()))) { + return false; + } + } + for (PPVec::iterator it = pp.begin(), end = pp.end(); it != end; ++it) { + // protect call to user code + LOCKED() { if (!it->addPost(s)) { return false; } } + } + return true; +#undef LOCKED +} + +ClaspConfig::ClaspConfig() : tester_(0), impl_(new Impl()) {} +ClaspConfig::~ClaspConfig() { + delete impl_; + delete tester_; +} + +void ClaspConfig::reset() { + if (tester_) { tester_->reset(); } + impl_->reset(); + BasicSatConfig::reset(); + solve = SolveOptions(); + asp = AspOptions(); +} + +BasicSatConfig* ClaspConfig::addTesterConfig() { + if (!tester_) { tester_ = new BasicSatConfig(); } + return tester_; +} + +void ClaspConfig::prepare(SharedContext& ctx) { + BasicSatConfig::prepare(ctx); + uint32 numS = solve.numSolver(); + if (numS > solve.supportedSolvers()) { + ctx.warn("Too many solvers."); + numS = solve.supportedSolvers(); + } + if (numS > solve.recommendedSolvers()) { + ctx.warn(ClaspStringBuffer().appendFormat("Oversubscription: #Threads=%u exceeds logical CPUs=%u.", numS, solve.recommendedSolvers())); + } + for (uint32 i = 0; i != numS; ++i) { + if (solver(i).heuId == Heuristic_t::Domain) { + parse.enableHeuristic(); + break; + } + } + solve.setSolvers(numS); + if (std::abs(static_cast(solve.numModels)) != 1 || !solve.models()) { + ctx.setPreserveModels(true); + } + ctx.setConcurrency(solve.numSolver(), SharedContext::resize_resize); + impl_->prepare(ctx); +} + +Configuration* ClaspConfig::config(const char* n) { + return (n && std::strcmp(n, "tester") == 0) ? testerConfig() : BasicSatConfig::config(n); +} + +void ClaspConfig::addConfigurator(Configurator* c, Ownership_t::Type t, bool once) { + impl_->add(c, t, once); +} + +bool ClaspConfig::addPost(Solver& s) const { + return impl_->addPost(s, solver(s.id())) && BasicSatConfig::addPost(s); +} + +ClaspConfig::Configurator::~Configurator() {} +void ClaspConfig::Configurator::prepare(SharedContext&) {} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspFacade::SolveData/SolveStrategy/AsyncResult +///////////////////////////////////////////////////////////////////////////////////////// +struct ClaspFacade::SolveStrategy { +public: + enum { SIGCANCEL = 9 }; + enum State { state_start = 0, state_running = 1, state_result = 2, state_model = 3, state_done = 6 }; + SolveStrategy() { state = signal = 0; nrefs = 1; facade = 0; algo = 0; handler = 0; aTop = 0; } + virtual ~SolveStrategy(){} + bool running() const { return (state & state_running) != 0; } + bool hasResult()const { return (state & state_result) != 0; } + bool interrupt(int sig) { + if (!running()) { return false; } + if (!signal) { signal = sig; } + return cancel(sig); + } + void solve(ClaspFacade& f, const LitVec& a, SolveAlgorithm* algo, EventHandler* h) { + this->facade = &f; + this->algo = algo; + this->handler = h; + this->aTop = (uint32)f.assume_.size(); + this->state = 0; + this->signal = 0; + f.assume_.insert(f.assume_.end(), a.begin(), a.end()); + if (!isSentinel(f.ctx.stepLiteral())) { + f.assume_.push_back(f.ctx.stepLiteral()); + } + preSolve(); + this->state = state_running; + facade->interrupt(0); // handle pending interrupts + doSolve(); + } + void detach(State end, bool more) { + facade->assume_.resize(aTop); + facade->stopStep(signal, !more); + if (handler) { handler->onEvent(StepReady(facade->summary())); } + state = end; + } + bool attach() { + CLASP_FAIL_IF(!running(), "invalid call to attach!"); + if (!signal && !facade->ctx.master()->hasConflict()) { + facade->step_.solveTime = facade->step_.unsatTime = RealTime::getTime(); + return true; + } + facade->ctx.report(Event::subsystem_solve); + return false; + } + bool startGen() { + if (!attach()) { + detach(state_done, facade->ok()); + return false; + } + algo->start(facade->ctx, facade->assume_, facade); + return true; + } + void stopGen() { + if (running()) { + algo->stop(); + detach(state_done, algo->more()); + } + } + virtual void release() {} + virtual bool cancel(int){ return algo->interrupt(); } + ClaspFacade* facade; + SolveAlgorithm* algo; + EventHandler* handler; + typedef Clasp::Atomic_t::type SafeIntType; + SafeIntType state; + SafeIntType signal; + SafeIntType nrefs; // Facade + #(Async)Result objects + uint32 aTop; +protected: + void runAlgo(State end); + virtual void preSolve() {} + virtual void doSolve() = 0; +}; +struct ClaspFacade::SolveData { + struct CostArray { + CostArray() : data(0) {} + ~CostArray() { while (!refs.empty()) { delete refs.back(); refs.pop_back(); } } + struct LevelRef { + LevelRef(const CostArray* a, uint32 l) : arr(a), at(l) {} + static double value(const LevelRef* ref) { + CLASP_FAIL_IF(ref->at >= ref->arr->size(), "expired key"); + return static_cast(ref->arr->data->costs->at(ref->at)); + } + const CostArray* arr; + uint32 at; + }; + typedef PodVector::type ElemVec; + uint32 size() const { + return data && data->costs ? sizeVec(*data->costs) : 0; + } + StatisticObject at(uint32 i) const { + CLASP_FAIL_IF(i >= size(), "invalid key"); + while (i >= refs.size()) { refs.push_back(new LevelRef(this, sizeVec(refs))); } + return StatisticObject::value(refs[i]); + } + const Model* data; + mutable ElemVec refs; + }; + typedef SingleOwnerPtr AlgoPtr; + typedef SingleOwnerPtr EnumPtr; + typedef Clasp::Atomic_t::type SafeIntType; + SolveData() : en(0), algo(0), active(0), prepared(false), interruptible(false) { qSig = 0; } + ~SolveData() { reset(); } + void init(SolveAlgorithm* algo, Enumerator* en) { + this->en = en; + this->algo = algo; + this->algo->setEnumerator(*en); + if (interruptible) { + this->algo->enableInterrupts(); + } + } + void reset() { + if (active) { active->interrupt(SolveStrategy::SIGCANCEL); active->release(); active = 0; } + if (algo.get()){ algo->resetSolve(); } + if (en.get()) { en->reset(); } + prepared = false; + } + void prepareEnum(SharedContext& ctx, int64 numM, EnumOptions::OptMode opt, EnumMode mode) { + CLASP_FAIL_IF(active, "Solve operation still active"); + if (ctx.ok() && !ctx.frozen() && !prepared) { + if (mode == enum_volatile && ctx.solveMode() == SharedContext::solve_multi) { + ctx.requestStepVar(); + } + int lim = en->init(ctx, opt, (int)Range(-1, INT_MAX).clamp(numM)); + if (lim == 0 || numM < 0) { + numM = lim; + } + algo->setEnumLimit(numM ? static_cast(numM) : UINT64_MAX); + costs.data = lastModel(); + prepared = true; + } + } + bool update(const Solver& s, const Model& m) { return !active->handler || active->handler->onModel(s, m); } + bool interrupt(int sig) { + if (solving()) { return active->interrupt(sig); } + if (!qSig && sig != SolveStrategy::SIGCANCEL) { qSig = sig; } + return false; + } + bool solving() const { return active && active->running(); } + const Model* lastModel() const { return en.get() ? &en->lastModel() : 0; } + const SharedMinimizeData* minimizer() const { return en.get() ? en->minimizer() : 0; } + Enumerator* enumerator()const { return en.get(); } + int modelType() const { return en.get() ? en->modelType() : 0; } + EnumPtr en; + AlgoPtr algo; + SolveStrategy* active; + CostArray costs; + SafeIntType qSig; + bool prepared; + bool interruptible; +}; +void ClaspFacade::SolveStrategy::runAlgo(State done) { + struct OnExit { + OnExit(SolveStrategy* s, int st) : self(s), endState(st), more(true) {} + ~OnExit() { + self->detach(static_cast(endState), more); + } + SolveStrategy* self; + int endState; + bool more; + } scope(this, done); + scope.more = attach() ? algo->solve(facade->ctx, facade->assume_, facade) : facade->ctx.ok(); +} + +#if WITH_THREADS +struct ClaspFacade::AsyncSolve : public SolveStrategy, public EventHandler { + enum { ASYNC_ERROR = 128 }; + static EventHandler* asyncModelHandler() { return reinterpret_cast(0x1); } + AsyncSolve() { } + bool hasError() const { + return (result.flags & uint8(ASYNC_ERROR)) != 0u; + } + virtual void preSolve() { + if (handler == AsyncSolve::asyncModelHandler()) { handler = this; } + algo->enableInterrupts(); + result = facade->result(); + } + virtual void doSolve() { + // start solve in worker thread + Clasp::mt::thread(std::mem_fun(&AsyncSolve::threadMain), this).swap(task); + } + virtual bool cancel(int sig) { + if (!SolveStrategy::cancel(sig)) return false; + if (sig == SIGCANCEL) { + wait(); + join(); + } + return true; + } + void threadMain() { + uint8 err = 0; + try { runAlgo(state_running); } + catch (...) { err = uint8(ASYNC_ERROR); } + { + mt::unique_lock lock(this->mqMutex); + result = facade->result(); + result.flags |= err; + state = state_done; + } + mqCond.notify_one(); + } + virtual void release() { + if (--nrefs == 1) { interrupt(SIGCANCEL); } + else if (nrefs == 0) { join(); delete this; } + } + bool next() { + if (state != state_model) { return false; } + mt::unique_lock lock(mqMutex); + if (state != state_model) { return false; } + state = state_running; + mqCond.notify_one(); + return true; + } + bool wait(double s = -1.0) { + if (state == state_start) { return false; } + if (signal != 0) { next(); } + for (mt::unique_lock lock(mqMutex); !hasResult(); ) { + if (s < 0.0) { mqCond.wait(lock); } + else { + mqCond.wait_for(lock, s); + if (!hasResult()) { return false; } + } + } + if (state == state_done && join()) { + // Just in case other AsyncSolve objects are waiting on the computation. + // This should not happen but there is some existing code that uses + // an AsyncSolve object in a separate thread for cancellation. + mqCond.notify_all(); + } + return true; + } + bool onModel(const Solver&, const Model&) { + const Result sat = {Result::SAT, 0}; + mt::unique_lock lock(mqMutex); + state = state_model; + result= sat; + mqCond.notify_one(); + while (state == state_model && signal == 0) { mqCond.wait(lock); } + return signal == 0; + } + bool join() { if (task.joinable()) { task.join(); return true; } return false; } + Clasp::mt::thread task; // async solving thread + Clasp::mt::mutex mqMutex;// protects mqCond + Clasp::mt::condition_variable mqCond; // for iterating over models one by one + Result result; // result of async operation +}; +ClaspFacade::AsyncResult::AsyncResult(SolveData& x) : state_(static_cast(x.active)) { ++state_->nrefs; } +ClaspFacade::AsyncResult::~AsyncResult() { state_->release(); } +ClaspFacade::AsyncResult::AsyncResult(const AsyncResult& x) : state_(x.state_) { ++state_->nrefs; } +int ClaspFacade::AsyncResult::interrupted() const { return state_->signal; } +bool ClaspFacade::AsyncResult::error() const { return ready() && state_->hasError(); } +bool ClaspFacade::AsyncResult::ready() const { return state_->hasResult(); } +bool ClaspFacade::AsyncResult::ready(Result& r) const { if (ready()) { r = get(); return true; } return false; } +bool ClaspFacade::AsyncResult::running() const { return state_->running(); } +void ClaspFacade::AsyncResult::wait() const { state_->wait(-1.0); } +bool ClaspFacade::AsyncResult::waitFor(double sec) const { return state_->wait(sec); } +bool ClaspFacade::AsyncResult::next() const { return state_->next(); } +bool ClaspFacade::AsyncResult::cancel() const { return state_->interrupt(AsyncSolve::SIGCANCEL); } +ClaspFacade::Result ClaspFacade::AsyncResult::get() const { + state_->wait(); + if (!state_->hasError()) { return state_->result; } + throw std::runtime_error("Async operation failed!"); +} +bool ClaspFacade::AsyncResult::end() const { + // first running() handles case where iterator is outdated (state was reset to start) + // second running() is used to distinguish models from final result (summary) + return !running() || !get().sat() || !running(); +} +const Model& ClaspFacade::AsyncResult::model() const { + CLASP_FAIL_IF(state_->state != AsyncSolve::state_model, "Invalid iterator access!"); + return const_cast(state_->algo)->enumerator()->lastModel(); +} +#endif +ClaspFacade::ModelGenerator::ModelGenerator(SolveStrategy& impl) : impl_(&impl) { + ++impl_->nrefs; +} +ClaspFacade::ModelGenerator::ModelGenerator(const ModelGenerator& o) : impl_(o.impl_) { + ++impl_->nrefs; +} +ClaspFacade::ModelGenerator::~ModelGenerator() { + impl_->release(); +} +bool ClaspFacade::ModelGenerator::next() const { + if (!impl_->running()) { + return false; + } + if (impl_->state != SolveStrategy::state_model && !impl_->startGen()) { + return false; + } + if (!impl_->algo->next()) { + impl_->stopGen(); + return false; + } + impl_->state = SolveStrategy::state_model; + return true; +} +const Model& ClaspFacade::ModelGenerator::model() const { + CLASP_FAIL_IF(!impl_->hasResult(), "Invalid iterator access!"); + return impl_->facade->enumerator()->lastModel(); +} +ClaspFacade::Result ClaspFacade::ModelGenerator::result() const { + CLASP_FAIL_IF(!impl_->hasResult(), "Invalid iterator access!"); + return impl_->facade->result(); +} +void ClaspFacade::ModelGenerator::stop() const { + impl_->stopGen(); +} +ClaspFacade::ModelGenerator ClaspFacade::startSolve(const LitVec& a) { + prepare(); + struct MG : public SolveStrategy { + virtual void doSolve() { } + virtual void release() { + switch (--nrefs) { + case 1: stopGen(); break; + case 0: delete this; break; + default: break; + } + } + }; + solve_->active = new MG(); + solve_->active->solve(*this, a, solve_->algo.get(), 0); + return ModelGenerator(*solve_->active); +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspFacade::Statistics +///////////////////////////////////////////////////////////////////////////////////////// +namespace { +struct KV { const char* key; StatisticObject(*get)(const ClaspFacade::Summary*); }; +template +StatisticObject _getT(const ClaspFacade::Summary* x) { return StatisticObject::value(&static_cast((x->*time))); } +template +StatisticObject _getM(const ClaspFacade::Summary* x) { return StatisticObject::value(&static_cast((x->*model))); } +static const KV sumKeys_s[] = { + {"total" , _getT<&ClaspFacade::Summary::totalTime>}, + {"cpu" , _getT<&ClaspFacade::Summary::cpuTime>}, + {"solve" , _getT<&ClaspFacade::Summary::solveTime>}, + {"unsat" , _getT<&ClaspFacade::Summary::unsatTime>}, + {"sat" , _getT<&ClaspFacade::Summary::satTime>}, + {"enumerated", _getM<&ClaspFacade::Summary::numEnum>}, + {"optimal" , _getM<&ClaspFacade::Summary::numOptimal>}, +}; +struct SummaryStats { + SummaryStats() : stats_(0), range_(0,0) {} + void bind(const ClaspFacade::Summary& x, Range32 r) { + stats_ = &x; + range_ = r; + } + uint32 size() const { return range_.hi - range_.lo; } + const char* key(uint32 i) const { return i < size() ? sumKeys_s[i + range_.lo].key : throw std::out_of_range("SummaryStats::key()"); } + StatisticObject at(const char* key) const { + for (const KV* x = sumKeys_s + range_.lo, *end = sumKeys_s + range_.hi; x != end; ++x) { + if (std::strcmp(x->key, key) == 0) { return x->get(stats_); } + } + throw std::out_of_range("SummaryStats::at()"); + } + StatisticObject toStats() const { return StatisticObject::map(this); } + const ClaspFacade::Summary* stats_; + Range32 range_; +}; + +double _getConcurrency(const SharedContext* ctx) { return ctx->concurrency(); } +double _getResult(const SolveResult* r) { return static_cast(r->operator Clasp::SolveResult::Base()); } +double _getSignal(const SolveResult* r) { return static_cast(r->signal); } +double _getExhausted(const SolveResult* r) { return static_cast(r->exhausted()); } +} +struct ClaspFacade::Statistics { + Statistics(ClaspFacade& f) : self_(&f), tester_(0), level_(0), clingo_(0) {} + ~Statistics() { delete clingo_; delete solvers_.multi; } + void start(uint32 level); + void initLevel(uint32 level); + void end(); + void addTo(StatsMap& solving, StatsMap* accu) const; + void accept(StatsVisitor& out, bool final) const; + bool incremental() const { return self_->incremental(); } + Potassco::AbstractStatistics* getClingo(); + typedef StatsVec SolverVec; + typedef SingleOwnerPtr LpStatsPtr; + typedef PrgDepGraph::NonHcfStats TesterStats; + ClaspFacade* self_; + LpStatsPtr lp_; // level 0 and asp + SolverStats solvers_; // level 0 + SolverVec solver_; // level > 1 + SolverVec accu_; // level > 1 and incremental + TesterStats* tester_; // level > 0 and nonhcfs + uint32 level_; // active stats level + // For clingo stats interface + class ClingoView : public ClaspStatistics { + public: + explicit ClingoView(const ClaspFacade& f); + void update(const Statistics& s); + private: + struct StepStats { + SummaryStats times; + SummaryStats models; + void bind(const ClaspFacade::Summary& x) { + times.bind(x, Range32(0, 5)); + models.bind(x, Range32(5, 7)); + } + void addTo(StatsMap& summary) { + summary.add("times", times.toStats()); + summary.add("models", models.toStats()); + } + }; + StatsMap keys_; + StatsMap problem_; + StatsMap solving_; + struct Summary : StatsMap { StepStats step; } summary_; + struct Accu : StatsMap { StepStats step; StatsMap solving_; }; + typedef SingleOwnerPtr AccuPtr; + AccuPtr accu_; + }* clingo_; // new clingo stats interface; +}; +void ClaspFacade::Statistics::initLevel(uint32 level) { + if (level_ < level) { + if (incremental() && !solvers_.multi) { solvers_.multi = new SolverStats(); } + level_ = level; + } + if (self_->isAsp() && !lp_.get()) { + lp_ = new Asp::LpStats(); + } + if (self_->ctx.sccGraph.get() && self_->ctx.sccGraph->numNonHcfs() && !tester_) { + tester_ = self_->ctx.sccGraph->nonHcfStats(); + } +} +void ClaspFacade::Statistics::start(uint32 level) { + // cleanup previous state + solvers_.reset(); + solver_.reset(); + if (tester_) { tester_->startStep(self_->config()->testerConfig() ? self_->config()->testerConfig()->context().stats : 0); } + // init next step + initLevel(level); + if (lp_.get() && self_->step_.lpStep()) { + lp_->accu(*self_->step_.lpStep()); + } + if (level > 1 && solver_.size() < self_->ctx.concurrency()) { + uint32 sz = sizeVec(solver_); + solver_.growTo(self_->ctx.concurrency()); + for (const bool inc = incremental() && (accu_.growTo(sizeVec(solver_)), true); sz != sizeVec(solver_); ++sz) { + if (!inc) { solver_[sz] = &self_->ctx.solverStats(sz); } + else { (solver_[sz] = new SolverStats())->multi = (accu_[sz] = new SolverStats()); } + } + if (!incremental()) { solver_.release(); } + } +} +void ClaspFacade::Statistics::end() { + self_->ctx.accuStats(solvers_); // compute solvers = sum(solver[1], ... , solver[n]) + solvers_.flush(); + for (uint32 i = incremental() ? 0 : sizeVec(solver_), end = sizeVec(solver_); i != end && self_->ctx.hasSolver(i); ++i) { + solver_[i]->accu(self_->ctx.solverStats(i), true); + solver_[i]->flush(); + } + if (tester_) { tester_->endStep(); } + if (clingo_) { clingo_->update(*this); } +} +void ClaspFacade::Statistics::addTo(StatsMap& solving, StatsMap* accu) const { + solvers_.addTo("solvers", solving, accu); + if (solver_.size()) { solving.add("solver", solver_.toStats()); } + if (accu && accu_.size()) { accu->add("solver", accu_.toStats()); } +} +void ClaspFacade::Statistics::accept(StatsVisitor& out, bool final) const { + final = final && solvers_.multi; + if (out.visitGenerator(StatsVisitor::Enter)) { + out.visitSolverStats(final ? *solvers_.multi : solvers_); + if (lp_.get()) { out.visitLogicProgramStats(*lp_); } + out.visitProblemStats(self_->ctx.stats()); + const SolverVec& solver = final ? accu_ : solver_; + const uint32 nThreads = final ? (uint32)accu_.size() : self_->ctx.concurrency(); + const uint32 nSolver = (uint32)solver.size(); + if (nThreads > 1 && nSolver > 1 && out.visitThreads(StatsVisitor::Enter)) { + for (uint32 i = 0, end = std::min(nSolver, nThreads); i != end; ++i) { + out.visitThread(i, *solver[i]); + } + out.visitThreads(StatsVisitor::Leave); + } + out.visitGenerator(StatsVisitor::Leave); + } + if (tester_ && out.visitTester(StatsVisitor::Enter)) { + tester_->accept(out, final); + out.visitTester(StatsVisitor::Leave); + } +} +Potassco::AbstractStatistics* ClaspFacade::Statistics::getClingo() { + if (!clingo_) { + clingo_ = new ClingoView(*this->self_); + clingo_->update(*this); + } + return clingo_; +} +ClaspFacade::Statistics::ClingoView::ClingoView(const ClaspFacade& f) { + summary_.add("call" , StatisticObject::value(&f.step_.step)); + summary_.add("result" , StatisticObject::value(&f.step_.result)); + summary_.add("signal" , StatisticObject::value(&f.step_.result)); + summary_.add("exhausted" , StatisticObject::value(&f.step_.result)); + summary_.add("costs" , StatisticObject::array(&f.solve_->costs)); + summary_.add("concurrency", StatisticObject::value(&f.ctx)); + summary_.step.bind(f.step_); + summary_.step.addTo(summary_); + if (f.step_.lpStats()) { + problem_.add("lp", StatisticObject::map(f.step_.lpStats())); + if (f.incremental()) { problem_.add("lpStep", StatisticObject::map(f.step_.lpStep())); } + } + problem_.add("generator", StatisticObject::map(&f.ctx.stats())); + keys_.add("problem", problem_.toStats()); + keys_.add("solving", solving_.toStats()); + keys_.add("summary", summary_.toStats()); + if (f.incremental()) { + accu_ = new Accu(); + accu_->step.bind(*f.accu_.get()); + } + setRoot(keys_.toStats()); +} +void ClaspFacade::Statistics::ClingoView::update(const ClaspFacade::Statistics& stats) { + if (stats.level_ > 0 && accu_.get() && keys_.add("accu", accu_->toStats())) { + accu_->step.addTo(*accu_); + accu_->add("solving", accu_->solving_.toStats()); + } + stats.addTo(solving_, stats.level_ > 0 && accu_.get() ? &accu_->solving_ : 0); + if (stats.tester_) { + stats.tester_->addTo(problem_, solving_, stats.level_ > 0 && accu_.get() ? &accu_->solving_ : 0); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspFacade +///////////////////////////////////////////////////////////////////////////////////////// +ClaspFacade::ClaspFacade() : config_(0) { step_.init(*this); } +ClaspFacade::~ClaspFacade() {} +bool ClaspFacade::prepared() const { + return solve_.get() && solve_->prepared; +} +bool ClaspFacade::solving() const { + return solve_.get() && solve_->solving(); +} +bool ClaspFacade::solved() const { + return step_.totalTime >= 0; +} +bool ClaspFacade::interrupted() const { + return result().interrupted(); +} +bool ClaspFacade::incremental() const { + return accu_.get() != 0; +} +ProblemType ClaspFacade::detectProblemType(std::istream& str) { + return Clasp::detectProblemType(str); +} +const ClaspFacade::Summary& ClaspFacade::summary(bool accu) const { + return accu && accu_.get() && accu_->step ? *accu_ : step_; +} + +void ClaspFacade::discardProblem() { + config_ = 0; + builder_ = 0; + stats_ = 0; + solve_ = 0; + accu_ = 0; + step_.init(*this); + if (ctx.frozen() || ctx.numVars()) { ctx.reset(); } +} +void ClaspFacade::init(ClaspConfig& config, bool discard) { + if (discard) { discardProblem(); } + ctx.setConfiguration(0, Ownership_t::Retain); // force reload of configuration once done + config_ = &config; + if (config_->solve.enumMode == EnumOptions::enum_dom_record) { + if (config_->solver(0).heuId != Heuristic_t::Domain) { + ctx.warn("Reasoning mode requires domain heuristic and is ignored!"); + config_->solve.enumMode = EnumOptions::enum_auto; + } + else if ((config_->solver(0).heuristic.domPref & HeuParams::pref_show) != 0) { + ctx.setPreserveShown(true); + } + } + SolveData::EnumPtr e(config.solve.createEnumerator(config.solve)); + if (e.get() == 0) { e = EnumOptions::nullEnumerator(); } + if (config.solve.numSolver() > 1 && !e->supportsParallel()) { + ctx.warn("Selected reasoning mode implies #Threads=1."); + config.solve.setSolvers(1); + } + ctx.setConfiguration(&config, Ownership_t::Retain); // prepare and apply config + if (program() && type_ == Problem_t::Asp) { + Asp::LogicProgram* p = static_cast(program()); + p->setOptions(config.asp); + p->setNonHcfConfiguration(config.testerConfig()); + } + if (!solve_.get()) { solve_ = new SolveData(); } + SolveData::AlgoPtr a(config.solve.createSolveObject()); + solve_->init(a.release(), e.release()); + if (discard) { startStep(0); } +} + +void ClaspFacade::initBuilder(ProgramBuilder* in) { + builder_ = in; + assume_.clear(); + builder_->startProgram(ctx); +} +ProgramBuilder& ClaspFacade::start(ClaspConfig& config, ProblemType t) { + if (t == Problem_t::Sat) { return startSat(config); } + else if (t == Problem_t::Pb) { return startPB(config); } + else if (t == Problem_t::Asp) { return startAsp(config); } + else { throw std::domain_error("Unknown problem type!"); } +} + +ProgramBuilder& ClaspFacade::start(ClaspConfig& config, std::istream& str) { + ProgramParser& p = start(config, detectProblemType(str)).parser(); + CLASP_FAIL_IF(!p.accept(str, config_->parse), "Auto detection failed!"); + if (p.incremental()) { enableProgramUpdates(); } + return *program(); +} + +SatBuilder& ClaspFacade::startSat(ClaspConfig& config) { + init(config, true); + initBuilder(new SatBuilder(config.solve.maxSat)); + type_ = Problem_t::Sat; + return static_cast(*builder_.get()); +} + +PBBuilder& ClaspFacade::startPB(ClaspConfig& config) { + init(config, true); + initBuilder(new PBBuilder()); + type_ = Problem_t::Sat; + return static_cast(*builder_.get()); +} + +Asp::LogicProgram& ClaspFacade::startAsp(ClaspConfig& config, bool enableUpdates) { + init(config, true); + Asp::LogicProgram* p = new Asp::LogicProgram(); + initBuilder(p); + p->setOptions(config.asp); + p->setNonHcfConfiguration(config.testerConfig()); + type_ = Problem_t::Asp; + if (enableUpdates) { enableProgramUpdates(); } + return *p; +} + +bool ClaspFacade::enableProgramUpdates() { + CLASP_ASSERT_CONTRACT_MSG(program(), "Program was already released!"); + CLASP_ASSERT_CONTRACT(!solving() && !program()->frozen()); + if (!accu_.get()) { + builder_->updateProgram(); + ctx.setSolveMode(SharedContext::solve_multi); + enableSolveInterrupts(); + accu_ = new Summary(); + accu_->init(*this); + accu_->step = UINT32_MAX; + } + return isAsp(); // currently only ASP supports program updates +} +void ClaspFacade::enableSolveInterrupts() { + CLASP_ASSERT_CONTRACT_MSG(!solving() , "Solving is already active!"); + CLASP_ASSERT_CONTRACT_MSG(solve_.get(), "Active program required!"); + if (!solve_->interruptible) { + solve_->interruptible = true; + solve_->algo->enableInterrupts(); + } +} + +void ClaspFacade::startStep(uint32 n) { + step_.init(*this); + step_.totalTime = -RealTime::getTime(); + step_.cpuTime = -ProcessTime::getTime(); + step_.step = n; + if (!stats_.get()) { stats_ = new Statistics(*this); } + ctx.report(StepStart(*this)); +} + +ClaspFacade::Result ClaspFacade::stopStep(int signal, bool complete) { + if (!solved()) { + double t = RealTime::getTime(); + step_.totalTime += t; + step_.cpuTime += ProcessTime::getTime(); + if (step_.solveTime) { + step_.solveTime = t - step_.solveTime; + step_.unsatTime = complete ? t - step_.unsatTime : 0; + } + Result res = {uint8(0), uint8(signal)}; + if (complete) { res.flags = uint8(step_.numEnum ? Result::SAT : Result::UNSAT) | Result::EXT_EXHAUST; } + else { res.flags = uint8(step_.numEnum ? Result::SAT : Result::UNKNOWN); } + if (signal) { res.flags|= uint8(Result::EXT_INTERRUPT); } + step_.result = res; + if (res.sat() && step_.model()->opt && !step_.numOptimal) { + step_.numOptimal = 1; + } + updateStats(); + ctx.report(StepReady(step_)); + } + return result(); +} + +void ClaspFacade::updateStats() { + if (stats_.get()) { + stats_->end(); + } + if (accu_.get() && accu_->step != step_.step) { + accu_->totalTime += step_.totalTime; + accu_->cpuTime += step_.cpuTime; + accu_->solveTime += step_.solveTime; + accu_->unsatTime += step_.unsatTime; + accu_->satTime += step_.satTime; + accu_->numEnum += step_.numEnum; + accu_->numOptimal += step_.numOptimal; + // no aggregation + accu_->step = step_.step; + accu_->result = step_.result; + } +} + +bool ClaspFacade::interrupt(int signal) { + return solve_.get() && (signal || (signal = solve_->qSig.fetch_and_store(0)) != 0) && solve_->interrupt(signal); +} + +const ClaspFacade::Summary& ClaspFacade::shutdown() { + if (solve_.get()) { + solve_->interrupt(SolveStrategy::SIGCANCEL); + stopStep(solving() ? solve_->active->signal : solve_->qSig, !ok()); + } + return summary(true); +} + +bool ClaspFacade::read() { + CLASP_ASSERT_CONTRACT(solve_.get()); + if (!program() || interrupted()) { return false; } + ProgramParser& p = program()->parser(); + if (!p.isOpen() || (solved() && !update().ok())) { return false; } + CLASP_FAIL_IF(!p.parse(), "Invalid input stream!"); + if (!p.more()) { p.reset(); } + return true; +} +void ClaspFacade::prepare(EnumMode enumMode) { + CLASP_ASSERT_CONTRACT(solve_.get() && !solving()); + EnumOptions& en = config_->solve; + if (solved()) { + doUpdate(0, false, SIG_DFL); + solve_->prepareEnum(ctx, en.numModels, en.optMode, enumMode); + ctx.endInit(); + } + if (prepared()) { return; } + SharedMinimizeData* m = 0; + ProgramBuilder* prg = program(); + if (prg && prg->endProgram()) { + assume_.clear(); + prg->getAssumptions(assume_); + prg->getWeakBounds(en.optBound); + } + stats_->start(uint32(config_->context().stats)); + if (en.optMode != MinimizeMode_t::ignore && (m = ctx.minimize()) != 0) { + if (!m->setMode(en.optMode, en.optBound)) { + assume_.push_back(lit_false()); + } + if (en.optMode == MinimizeMode_t::enumerate && en.optBound.empty()) { + ctx.warn("opt-mode=enum: no bound given, optimize statement ignored."); + } + } + CLASP_ASSERT_CONTRACT(!ctx.ok() || !ctx.frozen()); + solve_->prepareEnum(ctx, en.numModels, en.optMode, enumMode); + if (!accu_.get()) { builder_ = 0; } + else if (isAsp()) { static_cast(builder_.get())->dispose(false); } + if (!builder_.get() && !ctx.heuristic.empty()) { + bool keepDom = false; + for (uint32 i = 0; i != config_->solve.numSolver() && !keepDom; ++i) { + keepDom = config_->solver(i).heuId == Heuristic_t::Domain; + } + if (!keepDom) { ctx.heuristic.reset(); } + } + if (ctx.ok()) { ctx.endInit(); } +} + +ClaspFacade::Result ClaspFacade::solve(EventHandler* handler, const LitVec& a) { + prepare(); + struct SyncSolve : public SolveStrategy { + SyncSolve(SolveData& s) : x(&s) { x->active = this; } + ~SyncSolve() { x->active = 0; } + virtual void doSolve() { runAlgo(state_done); } + SolveData* x; + } syncSolve(*solve_); + syncSolve.solve(*this, a, solve_->algo.get(), handler); + return result(); +} +#if WITH_THREADS +ClaspFacade::AsyncResult ClaspFacade::solveAsync(EventHandler* handler, const LitVec& a) { + prepare(); + solve_->active = new AsyncSolve(); + solve_->active->solve(*this, a, solve_->algo.get(), handler); + return AsyncResult(*solve_); +} +ClaspFacade::AsyncResult ClaspFacade::startSolveAsync(const LitVec& a) { + return solveAsync(AsyncSolve::asyncModelHandler(), a); +} +#endif + +ProgramBuilder& ClaspFacade::update(bool updateConfig, void (*sigAct)(int)) { + CLASP_ASSERT_CONTRACT(config_ && program() && !solving()); + doUpdate(program(), updateConfig, sigAct); + return *program(); +} +ProgramBuilder& ClaspFacade::update(bool updateConfig) { + return update(updateConfig, SIG_DFL); +} + +void ClaspFacade::doUpdate(ProgramBuilder* p, bool updateConfig, void(*sigAct)(int)) { + if (updateConfig) { + init(*config_, false); + } + if (solved()) { + startStep(step() + 1); + } + if (p && p->frozen()) { + p->updateProgram(); + } + if (ctx.frozen()) { + ctx.unfreeze(); + } + solve_->reset(); + int sig = sigAct == SIG_DFL ? 0 : solve_->qSig.fetch_and_store(0); + if (sig && sigAct != SIG_IGN) { sigAct(sig); } +} + +bool ClaspFacade::onModel(const Solver& s, const Model& m) { + step_.unsatTime = RealTime::getTime(); + if (++step_.numEnum == 1) { step_.satTime = step_.unsatTime - step_.solveTime; } + if (m.opt) { ++step_.numOptimal; } + return solve_->update(s, m); +} +Enumerator* ClaspFacade::enumerator() const { return solve_.get() ? solve_->enumerator() : 0; } +Potassco::AbstractStatistics* ClaspFacade::getStats() const { + CLASP_FAIL_IF(!config_ || !solved(), "statistics not (yet) available"); + return stats_->getClingo(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspFacade::Summary +///////////////////////////////////////////////////////////////////////////////////////// +void ClaspFacade::Summary::init(ClaspFacade& f) { std::memset(this, 0, sizeof(Summary)); facade = &f;} +const Model* ClaspFacade::Summary::model() const { return facade->solve_.get() ? facade->solve_->lastModel() : 0; } +const SumVec* ClaspFacade::Summary::costs()const { return model() ? model()->costs : 0; } +uint64 ClaspFacade::Summary::optimal() const { return facade->step_.numOptimal; } +bool ClaspFacade::Summary::optimize() const { + if (const Enumerator* e = facade->enumerator()){ + return e->optimize() || e->lastModel().opt; + } + return false; +} +const Asp::LpStats* ClaspFacade::Summary::lpStep() const { + return facade->isAsp() ? &static_cast(facade->program())->stats : 0; +} +const Asp::LpStats* ClaspFacade::Summary::lpStats() const { + return facade->stats_.get() ? facade->stats_->lp_.get() : lpStep(); +} +const char* ClaspFacade::Summary::consequences() const { + const Model* m = model(); + return m && m->consequences() ? modelType(*m) : 0; +} + +bool ClaspFacade::Summary::hasLower() const { + const SharedMinimizeData* m = optimize() ? facade->enumerator()->minimizer() : 0; + return m && m->lower(0) != 0; +} +SumVec ClaspFacade::Summary::lower() const { + if (hasLower()) { + const SharedMinimizeData* m = facade->enumerator()->minimizer(); + SumVec ret(m->numRules()); + for (uint32 i = 0; i != m->numRules(); ++i) { + ret[i] = m->lower(i) + m->adjust(i); + } + return ret; + } + return SumVec(); +} +void ClaspFacade::Summary::accept(StatsVisitor& out) const { + if (facade->solved()) { facade->stats_->accept(out, this == facade->accu_.get()); } +} + +} + diff --git a/libclasp/src/clasp_options.cpp b/libclasp/src/clasp_options.cpp new file mode 100644 index 0000000..f2a15d0 --- /dev/null +++ b/libclasp/src/clasp_options.cpp @@ -0,0 +1,1008 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma warning (disable : 4996) +#pragma warning (disable : 4290) // C++ exception specification ignored +#endif +///////////////////////////////////////////////////////////////////////////////////////// +// Helper MACROS +///////////////////////////////////////////////////////////////////////////////////////// +#define SET(x, v) ( ((x)=(v)) == (v) ) +#define SET_LEQ(x, v, m) ( ((v)<=(m)) && SET((x), (v)) ) +#define SET_GEQ(x, v, m) ( ((v)>=(m)) && SET((x), (v)) ) +#define SET_OR_FILL(x, v) ( SET((x),(v)) || ((x) = 0, (x) = ~(x),true) ) +#define SET_OR_ZERO(x,v) ( SET((x),(v)) || SET((x),uint32(0)) ) +#define SET_R(x, v, lo, hi) ( ((lo)<=(v)) && ((v)<=(hi)) && SET((x), (v)) ) +///////////////////////////////////////////////////////////////////////////////////////// +// Primitive types/functions for string <-> T conversions +///////////////////////////////////////////////////////////////////////////////////////// +namespace bk_lib { +static const struct OffType {} off = {}; +static int xconvert(const char* x, const OffType&, const char** errPos, int) { + bool temp = true; + const char* n = x; + if (xconvert(n, temp, &n, 0) && !temp) { x = n; } + if (errPos) { *errPos = x; } + return int(temp == false); +} +static std::string& xconvert(std::string& out, const OffType&) { return out.append("no"); } + +template +static int xconvert(const char* x, pod_vector& out, const char** errPos, int sep) { + if (sep == 0) { sep = def_sep; } + std::size_t sz = out.size(); + std::size_t t = convert_seq(x, out.max_size() - sz, std::back_inserter(out), static_cast(sep), errPos); + if (!t) { out.resize(sz); } + return static_cast(t); +} +template +static std::string& xconvert(std::string& out, const pod_vector& x) { return xconvert(out, x.begin(), x.end()); } + +static std::size_t findEnumValImpl(const char* value, int& out, const char* k1, int v1, va_list args) { + std::size_t kLen = std::strlen(k1); + std::size_t vLen = std::strlen(value); + if (const char* x = std::strchr(value, ',')) { + vLen = x - value; + } + if (vLen == kLen && strncasecmp(value, k1, kLen) == 0) { out = v1; return kLen; } + while (const char* key = va_arg(args, const char *)) { + int val = va_arg(args, int); + kLen = std::strlen(key); + if (vLen == kLen && strncasecmp(value, key, kLen) == 0) { out = val; return kLen; } + } + return 0; +} +template +static int findEnumVal(const char* value, T& out, const char** errPos, const char* k1, int v1, ...) { + va_list args; + va_start(args, v1); + int temp; + std::size_t p = bk_lib::findEnumValImpl(value, temp, k1, v1, args); + va_end(args); + if (errPos) { *errPos = value + p; } + if (p) { out = static_cast(temp); } + return p != 0; +} +static const char* enumToString(int x, const char* k1, int v1, ...) { + va_list args; + va_start(args, v1); + const char* res = x == v1 ? k1 : 0; + if (res == 0) { + while (const char* key = va_arg(args, const char *)) { + int val = va_arg(args, int); + if (x == val) { res = key; break; } + } + } + va_end(args); + return res ? res : ""; +} +struct ArgString { + ArgString(const char* x) : in(x) { } + ~ArgString() throw (std::logic_error) { CLASP_FAIL_IF(ok() && *in && !off(), "Unused argument!"); } + bool ok() const { return in != 0; } + bool off() const { return ok() && stringTo(in, bk_lib::off); } + bool empty() const { return ok() && !*in; } + operator void*()const { return (void*)in; } + char peek() const { return ok() ? *in : 0; } + template + ArgString& get(T& x) { + if (ok()) { + const char* next = in + (*in == ','); + in = xconvert(next, x, &next, 0) != 0 ? next : 0; + } + return *this; + } + const char* in; + template + struct Opt_t { + Opt_t(T& x) : obj(&x) {} + T* obj; + }; +}; +template +inline ArgString::Opt_t opt(T& x) { return ArgString::Opt_t(x); } +template +inline ArgString& operator>>(ArgString& arg, T& x) { return arg.get(x); } +template +inline ArgString& operator>>(ArgString& arg, const ArgString::Opt_t& x) { return !arg.empty() ? arg.get(*x.obj) : arg; } + +struct StringBuilder { + StringBuilder(std::string& o) : out(&o) {} + template + StringBuilder& _add(const T& x) { + if (!out->empty()) { out->append(1, ','); } + xconvert(*out, x); + return *this; + } + operator bool() const { return out != 0; } + std::string* out; +}; +template +inline StringBuilder& operator<<(StringBuilder& str, const T& val) { return str ? str._add(val) : str; } + +} +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Enum mappings for clasp types +///////////////////////////////////////////////////////////////////////////////////////// +#define MAP(x, y) static_cast(x), static_cast(y) +#define DEFINE_ENUM_MAPPING(X, ...) \ +static int xconvert(const char* x, X& out, const char** errPos, int) {\ + return bk_lib::findEnumVal(x, out, errPos, __VA_ARGS__, MAP(0,0)); \ +}\ +static std::string& xconvert(std::string& out, X x) { \ + return out.append(bk_lib::enumToString(static_cast(x), __VA_ARGS__, MAP(0,0))); \ +} +#define OPTION(k, e, a, d, ...) a +#define CLASP_CONTEXT_OPTIONS +#define CLASP_GLOBAL_OPTIONS +#define CLASP_SOLVE_OPTIONS +#define CLASP_ASP_OPTIONS +#define CLASP_SOLVER_OPTIONS +#define CLASP_SEARCH_OPTIONS +#define ARG_EXT(a, X) X +#define ARG(a) +#define NO_ARG +#include +namespace Cli { +DEFINE_ENUM_MAPPING(ConfigKey, \ + MAP("auto", config_default), MAP("frumpy", config_frumpy), MAP("jumpy", config_jumpy), \ + MAP("tweety", config_tweety) , MAP("handy" , config_handy) ,\ + MAP("crafty", config_crafty) , MAP("trendy", config_trendy), MAP("many", config_many)) +} +#undef MAP +#undef DEFINE_ENUM_MAPPING +///////////////////////////////////////////////////////////////////////////////////////// +// Conversion functions for complex clasp types +///////////////////////////////////////////////////////////////////////////////////////// +static int xconvert(const char* x, ScheduleStrategy& out, const char** errPos, int e) { + using bk_lib::xconvert; + if (!x) { return 0; } + const char* next = std::strchr(x, ','); + uint32 base = 0; + int tok = 1; + if (errPos) { *errPos = x; } + if (!next || !xconvert(next+1, base, &next, e) || base == 0) { return 0; } + if (strncasecmp(x, "f,", 2) == 0 || strncasecmp(x, "fixed,", 6) == 0){ + out = ScheduleStrategy::fixed(base); + } + else if (strncasecmp(x, "l,", 2) == 0 || strncasecmp(x, "luby,", 5) == 0) { + uint32 lim = 0; + if (*next == ',' && !xconvert(next+1, lim, &next, e)) { return 0; } + out = ScheduleStrategy::luby(base, lim); + } + else if (strncmp(x, "+,", 2) == 0 || strncasecmp(x, "add,", 4) == 0) { + std::pair arg(0, 0); + if (*next != ',' || !xconvert(next+1, arg, &next, e)) { return 0; } + out = ScheduleStrategy::arith(base, arg.first, arg.second); + } + else if (strncmp(x, "x,", 2) == 0 || strncmp(x, "*,", 2) == 0 || strncasecmp(x, "d,", 2) == 0) { + std::pair arg(0, 0); + if (*next != ',' || !xconvert(next+1, arg, &next, e)) { return 0; } + if (strncasecmp(x, "d", 1) == 0 && arg.first > 0.0) { out = ScheduleStrategy(ScheduleStrategy::User, base, arg.first, arg.second); } + else if (strncasecmp(x, "d", 1) != 0 && arg.first >= 1.0){ out = ScheduleStrategy::geom(base, arg.first, arg.second); } + else { return 0; } + } + else { next = x; tok = 0; } + if (errPos) { *errPos = next; } + return tok; +} +static std::string& xconvert(std::string& out, const ScheduleStrategy& sched) { + using bk_lib::xconvert; + if (sched.defaulted()){ return xconvert(out, ScheduleStrategy()); } + if (sched.disabled()) { return out.append("0"); } + std::size_t t = out.size(); + out.append("f,"); + xconvert(out, sched.base); + switch (sched.type) { + case ScheduleStrategy::Geometric: + out[t] = 'x'; + return xconvert(out.append(1, ','), std::make_pair((double)sched.grow, sched.len)); + case ScheduleStrategy::Arithmetic: + if (sched.grow) { out[t] = '+'; return xconvert(out.append(1, ','), std::make_pair((uint32)sched.grow, sched.len)); } + else { out[t] = 'f'; return out; } + case ScheduleStrategy::Luby: + out[t] = 'l'; + if (sched.len) { return xconvert(out.append(1, ','), sched.len); } + else { return out; } + case ScheduleStrategy::User: + out[t] = 'd'; + return xconvert(out.append(1, ','), std::make_pair((double)sched.grow, sched.len)); + default: CLASP_FAIL_IF(true, "xconvert(ScheduleStrategy): unknown type"); + } +} +namespace Asp { using Clasp::xconvert; } +namespace mt { using Clasp::xconvert; } +namespace Cli { +///////////////////////////////////////////////////////////////////////////////////////// +// Option -> Key mapping +///////////////////////////////////////////////////////////////////////////////////////// +/// \cond +// Valid option keys. +enum OptionKey { + detail__before_options = -1, + meta_config = 0, +#define CLASP_CONTEXT_OPTIONS GRP(option_category_nodes_end, option_category_context_begin), +#define CLASP_GLOBAL_OPTIONS GRP(option_category_context_end, option_category_global_begin), +#define CLASP_SOLVER_OPTIONS GRP(option_category_global_end, option_category_solver_begin), +#define CLASP_SEARCH_OPTIONS GRP(option_category_solver_end, option_category_search_begin), +#define CLASP_ASP_OPTIONS GRP(option_category_search_end, option_category_asp_begin), +#define CLASP_SOLVE_OPTIONS GRP(option_category_asp_end, option_category_solve_begin), +#define OPTION(k,e,...) opt_##k, +#define GROUP_BEGIN(X) X +#define GRP(X, Y) X, Y = X, detail__before_##Y = X - 1 +#include +#undef GRP + option_category_solve_end, + detail__num_options = option_category_solve_end, + meta_tester = detail__num_options +}; +static inline bool isOption(int k) { return k >= option_category_nodes_end && k < detail__num_options; } +static inline bool isGlobalOption(int k) { return k >= option_category_global_begin && k < option_category_global_end; } +static inline bool isTesterOption(int k) { return k >= option_category_nodes_end && k < option_category_search_end && !isGlobalOption(k); } +static inline bool isSolverOption(int k) { return k >= option_category_solver_begin && k < option_category_search_end; } +#if WITH_THREADS +#define MANY_DESC " many : Use default portfolio to configure solver(s)\n" +#define MANY_ARG "|many" +#else +#define MANY_DESC +#define MANY_ARG "" +#endif +#define KEY_INIT_DESC(desc) \ +desc " : {auto|frumpy|jumpy|tweety|handy|crafty|trendy" MANY_ARG "|}\n" \ +" auto : Select configuration based on problem type\n" \ +" frumpy: Use conservative defaults\n" \ +" jumpy : Use aggressive defaults\n" \ +" tweety: Use defaults geared towards asp problems\n" \ +" handy : Use defaults geared towards large problems\n" \ +" crafty: Use defaults geared towards crafted problems\n" \ +" trendy: Use defaults geared towards industrial problems\n" \ + MANY_DESC \ +" : Use configuration file to configure solver(s)" + +struct NodeKey { + const char* name; + const char* desc; + int16 skBegin; + int16 skEnd; + uint32 numSubkeys() const { return static_cast( skEnd - skBegin ); } +}; +enum { key_leaf = 0, key_solver = -1, key_asp = -2, key_solve = -3, key_tester = -4, key_root = -5 }; +// nodes_g[-k]: entry for key k +static const NodeKey nodes_g[] = { +/* 0: config */ {"configuration", KEY_INIT_DESC("Initializes this configuration\n"), 0,0}, +/* 1: */ {"solver", "Solver Options", option_category_solver_begin, option_category_search_end}, +/* 2: */ {"asp" , "Asp Options" , option_category_asp_begin, option_category_asp_end}, +/* 3: */ {"solve" , "Solve Options" , option_category_solve_begin, option_category_solve_end}, +/* 4: */ {"tester", "Tester Options", key_solver, option_category_context_end}, +/* 5: */ {"" , "Options" , key_tester, option_category_global_end} +}; +static uint32 makeKeyHandle(int16 kId, uint32 mode, uint32 sId) { + assert(sId <= 255 && mode <= 255); + return (mode << 24) | (sId << 16) | static_cast(kId); +} +static int16 decodeKey(uint32 key) { return static_cast(static_cast(key)); } +static uint8 decodeMode(uint32 key) { return static_cast( (key >> 24) ); } +static uint8 decodeSolver(uint32 key){ return static_cast( (key >> 16) ); } +static bool isValidId(int16 id) { return id >= key_root && id < detail__num_options; } +static bool isLeafId(int16 id) { return id >= key_leaf && id < detail__num_options; } +const ClaspCliConfig::KeyType ClaspCliConfig::KEY_INVALID = static_cast(-1); +const ClaspCliConfig::KeyType ClaspCliConfig::KEY_ROOT = makeKeyHandle(key_root, 0, 0); +const ClaspCliConfig::KeyType ClaspCliConfig::KEY_SOLVER = makeKeyHandle(key_solver, 0, 0); +const ClaspCliConfig::KeyType ClaspCliConfig::KEY_TESTER = makeKeyHandle(key_tester, ClaspCliConfig::mode_tester, 0); + +struct Name2Id { + const char* name; int key; + bool operator<(const Name2Id& rhs) const { return std::strcmp(name, rhs.name) < 0; } +}; +static Name2Id options_g[detail__num_options+1] = { + {"configuration", meta_config}, +#define OPTION(k, e, ...) { #k, opt_##k }, +#define CLASP_CONTEXT_OPTIONS +#define CLASP_GLOBAL_OPTIONS +#define CLASP_SOLVER_OPTIONS +#define CLASP_SEARCH_OPTIONS +#define CLASP_ASP_OPTIONS +#define CLASP_SOLVE_OPTIONS +#include + {"tester" , meta_tester} +}; +struct ClaspCliConfig::OptIndex { + OptIndex(Name2Id* first, Name2Id* last) { + std::sort(begin = first, end = last); + } + Name2Id* find(const char* name) const { + Name2Id temp = { name, 0 }; + Name2Id* it = std::lower_bound(begin, end, temp); + if (it != end && std::strcmp(it->name, name) == 0) { return it; } + return 0; + } + Name2Id* begin; + Name2Id* end; +}; +ClaspCliConfig::OptIndex ClaspCliConfig::index_g(options_g, options_g + detail__num_options+1); +/// \endcond +///////////////////////////////////////////////////////////////////////////////////////// +// Interface to ProgramOptions +///////////////////////////////////////////////////////////////////////////////////////// +// Converts option key to command-line option name. +static void keyToCliName(std::string& out, const char* n, const char* ext) { + out.clear(); + for (const char* x; (x = std::strchr(n, '_')) != 0; n = ++x) { + out.append(n, x-n); + out.append(1, '-'); + } + out.append(n).append(ext); +} +// Converts command-line option name to option key. +static void cliNameToKey(std::string& out, const char* n) { + out.clear(); + for (const char* x; (x = std::strchr(n, '-')) != 0; n = ++x) { + out.append(n, x-n); + out.append(1, '_'); + } + out.append(n); +} +// Type for storing one command-line option. +class ClaspCliConfig::ProgOption : public ProgramOptions::Value { +public: + ProgOption(ClaspCliConfig& c, int o) : ProgramOptions::Value(0), config_(&c), option_(o) {} + bool doParse(const std::string& opt, const std::string& value) { + int ret = isOption(option_) ? config_->setActive(option_, value.c_str()) : config_->setAppOpt(option_, value.c_str()); + if (ret == -1) { throw ProgramOptions::UnknownOption(config_->isGenerator() ? "" : "", opt); } + return ret > 0; + } + int option() const { return option_; } +private: + ClaspCliConfig* config_; + int option_; +}; + +// Adapter for parsing a command string. +struct ClaspCliConfig::ParseContext : public ProgramOptions::ParseContext { + typedef ProgramOptions::SharedOptPtr OptPtr; + ParseContext(ClaspCliConfig& x, const char* c, const ParsedOpts* ex, bool allowMeta, ParsedOpts* o) + : self(&x), config(c), exclude(ex), out(o), meta(allowMeta) { seen[0] = seen[1] = 0; } + OptPtr getOption(const char* name, FindType ft); + OptPtr getOption(int, const char* key) { throw ProgramOptions::UnknownOption(config, key); } + void addValue(const OptPtr& key, const std::string& value); + uint64 seen[2]; + std::string temp; + ClaspCliConfig* self; + const char* config; + const ParsedOpts* exclude; + ParsedOpts* out; + bool meta; +}; +void ClaspCliConfig::ParseContext::addValue(const OptPtr& key, const std::string& value) { + using namespace ProgramOptions; + if (exclude->count(key->name()) == 0) { + ProgOption* v = static_cast(key->value()); + Value::State s= v->state(); + int id = v->option(); + uint64& xs = seen[id/64]; + uint64 m = static_cast(1u) << (id & 63); + if ((xs & m) != 0 && !v->isComposing()){ throw ValueError(config, ValueError::multiple_occurences, key->name(), value); } + if (!v->parse(key->name(), value, s)) { throw ValueError(config, ValueError::invalid_value, key->name(), value); } + if (out) { out->add(key->name()); } + xs |= m; + } +} +ProgramOptions::SharedOptPtr ClaspCliConfig::ParseContext::getOption(const char* cmdName, FindType ft) { + Options::option_iterator end = self->opts_->end(), it = end; + if (ft == OptionContext::find_alias) { + char a = cmdName[*cmdName == '-']; + for (it = self->opts_->begin(); it != end && it->get()->alias() != a; ++it) { ; } + } + else { + Name2Id key = { cmdName, -2 }; + if (std::strchr(cmdName, '-') != 0) { cliNameToKey(temp, cmdName); key.name = temp.c_str(); } + Name2Id* pos = std::lower_bound(self->index_g.begin, self->index_g.end, key); + if (pos != self->index_g.end) { + std::size_t len = std::strlen(key.name); + int cmp = std::strncmp(key.name, pos->name, len); + bool found = cmp == 0 && !*(pos->name+len); + if (!found && cmp == 0 && (ft & OptionContext::find_prefix) != 0) { + Name2Id* next = pos + 1; + cmp = next != self->index_g.end ? std::strncmp(key.name, next->name, len) : -1; + found = cmp != 0; + if (!found) { throw ProgramOptions::AmbiguousOption(config, cmdName, ""); } + } + if (found) { it = self->opts_->begin() + pos->key; } + } + assert(it == end || static_cast(it->get()->value())->option() == pos->key); + } + if (it != end && (meta || isOption(static_cast(it->get()->value())->option()))) { + return *it; + } + throw ProgramOptions::UnknownOption(config, cmdName); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Default Configs +///////////////////////////////////////////////////////////////////////////////////////// +ConfigIter ClaspCliConfig::getConfig(ConfigKey k) { + switch(k) { + #define CONFIG(id, n,c,s,p) case config_##n: return ConfigIter("/[" #n "]\0/\0/" s " " c "\0"); + #define CLASP_CLI_DEFAULT_CONFIGS + #define CLASP_CLI_AUX_CONFIGS + #include + case config_many: + #define CONFIG(id,n,c,s,p) "/[solver." #id "]\0/\0/" c " " p "\0" + #define CLASP_CLI_DEFAULT_CONFIGS + #define CLASP_CLI_AUX_CONFIGS + return ConfigIter( + #include + ); + case config_default: return ConfigIter("/default\0/\0/\0"); + default : throw std::logic_error(ClaspStringBuffer().appendFormat("Invalid config key '%d'", (int)k).c_str()); + } +} +ConfigIter ClaspCliConfig::getConfig(uint8 key, std::string& tempMem) { + CLASP_FAIL_IF(key > (config_max_value + 1), "Invalid key!"); + if (key < config_max_value) { return getConfig(static_cast(key)); } + tempMem.clear(); + loadConfig(tempMem, config_[key - config_max_value].c_str()); + return ConfigIter(tempMem.data()); +} +static inline const char* skipWs(const char* x) { + while (*x == ' ' || *x == '\t') { ++x; } + return x; +} +static inline const char* getIdent(const char* x, std::string& to) { + for (x = skipWs(x); std::strchr(" \t:()[]", *x) == 0; ++x) { to += *x; } + return x; +} +static inline bool matchSep(const char*& x, char c) { + if (*(x = skipWs(x)) == c) { ++x; return true; } + return false; +} + +bool ClaspCliConfig::appendConfig(std::string& to, const std::string& line) { + std::size_t sz = to.size(); + const char* x = skipWs(line.c_str()); + const bool p = matchSep(x, '['); + to.append("/[", 2); + // match name in optional square brackets + bool ok = matchSep(x = getIdent(x, to), ']') == p; + to.append("]\0/", 3); + // match optional base in parentheses followed by start of option list + if (ok && (!matchSep(x, '(') || matchSep((x = getIdent(x, to)), ')')) && matchSep(x, ':')) { + to.append("\0/", 2); + to.append(skipWs(x)); + to.erase(to.find_last_not_of(" \t") + 1); + to.append(1, '\0'); + return true; + } + to.resize(sz); + return false; +} +bool ClaspCliConfig::loadConfig(std::string& to, const char* name) { + std::ifstream file(name); + CLASP_FAIL_IF(!file, "Could not open config file '%s'", name); + uint32 lineNum= 0; + for (std::string line, cont; std::getline(file, line); ) { + ++lineNum; + line.erase(0, line.find_first_not_of(" \t")); + if (line.empty() || line[0] == '#') { continue; } + if (*line.rbegin() == '\\') { *line.rbegin() = ' '; cont += line; continue; } + if (!cont.empty()) { cont += line; cont.swap(line); cont.clear(); } + CLASP_FAIL_IF(!appendConfig(to, line), "'%s@%u': Invalid configuration", name, lineNum); + } + to.append(1, '\0'); + return true; +} +const char* ClaspCliConfig::getDefaults(ProblemType t) { + if (t == Problem_t::Asp){ return "--configuration=tweety"; } + else { return "--configuration=trendy"; } +} +ConfigIter::ConfigIter(const char* x) : base_(x) {} +const char* ConfigIter::name() const { return base_ + 1; } +const char* ConfigIter::base() const { return base_ + std::strlen(base_) + 2; } +const char* ConfigIter::args() const { const char* x = base(); return x + std::strlen(x) + 2; } +bool ConfigIter::valid()const { return *base_ != 0; } +bool ConfigIter::next() { + base_ = args(); + base_+= std::strlen(base_) + 1; + return valid(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspCliConfig +///////////////////////////////////////////////////////////////////////////////////////// +ClaspCliConfig::ScopedSet::ScopedSet(ClaspCliConfig& s, uint8 mode, uint32 sId) : self(&s) { + if (sId) { mode |= mode_solver; } + s.cliId = static_cast(sId); + s.cliMode = mode; +} +ClaspCliConfig::ScopedSet::~ScopedSet() { self->cliId = self->cliMode = 0; } +ClaspCliConfig::RawConfig::RawConfig(const char* name) { + raw.append(1, '/').append(name ? name : "").append("\0/\0/", 4); +} +void ClaspCliConfig::RawConfig::addArg(const char* arg) { + *raw.rbegin() = ' '; + raw.append(arg ? arg : "").append(1, '\0'); +} +void ClaspCliConfig::RawConfig::addArg(const std::string& arg) { addArg(arg.c_str()); } +ClaspCliConfig::ClaspCliConfig() { + initTester_ = true; + static_assert( + (option_category_context_begin< option_category_solver_begin) && + (option_category_solver_begin < option_category_search_begin) && + (option_category_search_begin < option_category_asp_begin) && + (option_category_asp_begin < option_category_solve_begin) && + (option_category_solve_begin < option_category_solve_end), "unexpected option order"); +} +ClaspCliConfig::~ClaspCliConfig() {} +void ClaspCliConfig::reset() { + config_[0] = config_[1] = ""; + initTester_ = true; + ClaspConfig::reset(); +} + +void ClaspCliConfig::prepare(SharedContext& ctx) { + if (testerConfig()) { + // Force init + ClaspCliConfig::config("tester"); + } + ClaspConfig::prepare(ctx); +} +Configuration* ClaspCliConfig::config(const char* n) { + if (n && std::strcmp(n, "tester") == 0) { + if (!testerConfig() || (!testerConfig()->hasConfig && initTester_)) { + setAppOpt(meta_tester, "--config=auto"); + initTester_ = false; + } + return testerConfig(); + } + return ClaspConfig::config(n); +} + +ClaspCliConfig::ProgOption* ClaspCliConfig::createOption(int o) { return new ProgOption(*this, o); } + +void ClaspCliConfig::createOptions() { + if (opts_.get()) { return; } + opts_ = new Options(); + using namespace ProgramOptions; + opts_->addOptions()("configuration", createOption(meta_config)->defaultsTo("auto")->state(Value::value_defaulted), KEY_INIT_DESC("Configure default configuration [%D]\n")); + std::string cmdName; +#define CLASP_CONTEXT_OPTIONS +#define CLASP_GLOBAL_OPTIONS +#define CLASP_SOLVE_OPTIONS +#define CLASP_ASP_OPTIONS +#define CLASP_SOLVER_OPTIONS +#define CLASP_SEARCH_OPTIONS +#define OPTION(k, e, a, d, ...) keyToCliName(cmdName, #k, e); opts_->addOptions()(cmdName.c_str(),static_cast( createOption(opt_##k)a ), d); +#define ARG(a) ->a +#define ARG_EXT(a, X) ARG(a) +#define NO_ARG +#include + opts_->addOptions()("tester", createOption(meta_tester)->arg(""), "Pass (quoted) string of %A to tester"); +} +void ClaspCliConfig::addOptions(OptionContext& root) { + createOptions(); + using namespace ProgramOptions; + OptionGroup configOpts("Clasp.Config Options"); + OptionGroup solving("Clasp.Solving Options"); + OptionGroup asp("Clasp.ASP Options"); + OptionGroup search("Clasp.Search Options", ProgramOptions::desc_level_e1); + OptionGroup lookback("Clasp.Lookback Options", ProgramOptions::desc_level_e1); + configOpts.addOption(*opts_->begin()); + configOpts.addOption(*(opts_->end()-1)); + for (Options::option_iterator it = opts_->begin() + 1, end = opts_->end() - 1; it != end; ++it) { + int oId = static_cast(it->get()->value())->option(); + if (oId < option_category_global_end) { configOpts.addOption(*it); } + else if (oId < opt_no_lookback) { search.addOption(*it); } + else if (oId < option_category_solver_end) { lookback.addOption(*it); } + else if (oId < opt_restarts) { search.addOption(*it); } + else if (oId < option_category_search_end) { lookback.addOption(*it); } + else if (oId < option_category_asp_end) { asp.addOption(*it); } + else { solving.addOption(*it); } + } + root.add(configOpts).add(solving).add(asp).add(search).add(lookback); + root.addAlias("number", root.find("models")); // remove on next version +} +bool ClaspCliConfig::assignDefaults(const ProgramOptions::ParsedOptions& exclude) { + for (Options::option_iterator it = opts_->begin(), end = opts_->end(); it != end; ++it) { + const ProgramOptions::Option& o = **it; + CLASP_FAIL_IF(exclude.count(o.name()) == 0 && !o.assignDefault(), "Option '%s': invalid default value '%s'\n", o.name().c_str(), o.value()->defaultsTo()); + } + return true; +} +void ClaspCliConfig::releaseOptions() { + opts_ = 0; +} +bool ClaspCliConfig::match(const char*& path, const char* what) const { + std::size_t wLen = std::strlen(what); + if (strncmp(path, what, wLen) != 0 || (path[wLen] && path[wLen++] != '.')) { + return false; + } + path += wLen; + return true; +} +ClaspCliConfig::KeyType ClaspCliConfig::getKey(KeyType k, const char* path) const { + int16 id = decodeKey(k); + if (!isValidId(id) || !path || !*path || (*path == '.' && !*++path)) { + return k; + } + if (isLeafId(id)){ return KEY_INVALID; } + const NodeKey& x = nodes_g[-id]; + for (int16 sk = x.skBegin; sk != x.skEnd && sk < 0; ++sk) { + NodeKey sub = nodes_g[-sk]; + if (match(path, sub.name)) { + KeyType ret = makeKeyHandle(sk, (sk == key_tester ? mode_tester : 0) | decodeMode(k), 0); + if (!*path) { return ret; } + return getKey(ret, path); + } + } + uint8 mode = decodeMode(k); + if (id == key_solver) { + uint32 solverId; + if ((mode & mode_solver) == 0 && *path != '.' && bk_lib::xconvert(path, solverId, &path, 0) == 1) { + return getKey(makeKeyHandle(id, mode | mode_solver, std::min(solverId, (uint32)uint8(-1))), path); + } + mode |= mode_solver; + } + const Name2Id* opt = index_g.find(path); + // remaining name must be a valid option in our subkey range + if (!opt || opt->key < x.skBegin || opt->key >= x.skEnd) { + return KEY_INVALID; + } + return makeKeyHandle(static_cast(opt->key), mode, decodeSolver(k)); +} + +ClaspCliConfig::KeyType ClaspCliConfig::getArrKey(KeyType k, unsigned i) const { + int16 id = decodeKey(k); + if (id != key_solver || (decodeMode(k) & mode_solver) != 0 || i >= solve.supportedSolvers()) { return KEY_INVALID; } + return makeKeyHandle(id, decodeMode(k) | mode_solver, i); +} +int ClaspCliConfig::getKeyInfo(KeyType k, int* nSubkeys, int* arrLen, const char** help, int* nValues) const { + int16 id = decodeKey(k); + int ret = 0; + if (!isValidId(id)){ return -1; } + if (isLeafId(id)){ + if (nSubkeys && ++ret) { *nSubkeys = 0; } + if (arrLen && ++ret) { *arrLen = -1; } + if (nValues && ++ret) { *nValues = static_cast( (decodeMode(k) & mode_tester) == 0 || testerConfig() != 0 ); } + if (help && ++ret) { getActive(id, 0, help, 0); } + return ret; + } + const NodeKey& x = nodes_g[-id]; + if (nSubkeys && ++ret) { *nSubkeys = x.numSubkeys(); } + if (nValues && ++ret) { *nValues = -1; } + if (help && ++ret) { *help = x.desc; } + if (arrLen && ++ret) { + *arrLen = -1; + if (id == key_solver && (decodeMode(k) & mode_solver) == 0) { + const UserConfig* c = (decodeMode(k) & mode_tester) == 0 ? this : testerConfig(); + *arrLen = c ? (int)c->numSolver() : 0; + } + } + return ret; +} +bool ClaspCliConfig::isLeafKey(KeyType k) { return isLeafId(decodeKey(k)); } +const char* ClaspCliConfig::getSubkey(KeyType k, uint32 i) const { + int16 id = decodeKey(k); + if (!isValidId(id) || isLeafId(id)) { return 0; } + const NodeKey& nk = nodes_g[-id]; + if (i >= nk.numSubkeys()) { return 0; } + int sk = nk.skBegin + static_cast(i); + if (sk < key_leaf) { return nodes_g[-sk].name; } + const char* opt = 0; + getActive(sk, 0, 0, &opt); + return opt; +} +int ClaspCliConfig::getValue(KeyType key, std::string& out) const { + int16 id = decodeKey(key); + if (!isLeafId(id)) { return -1; } + try { + int ret = ScopedSet(const_cast(*this), decodeMode(key), decodeSolver(key))->getActive(id, &out, 0, 0); + return ret > 0 ? static_cast(out.length()) : ret; + } + catch (...) { return -2; } +} +int ClaspCliConfig::getValue(KeyType key, char* buffer, std::size_t bufSize) const { + std::string temp; + int ret = getValue(key, temp); + if (ret <= 0) { return ret; } + if (buffer && bufSize) { + std::size_t n = temp.length() >= bufSize ? bufSize - 1 : temp.length(); + std::memcpy(buffer, temp.c_str(), n * sizeof(char)); + buffer[n] = 0; + } + return static_cast(temp.length()); +} +std::string ClaspCliConfig::getValue(const char* path) const { + std::string temp; + CLASP_FAIL_IF(getValue(getKey(KEY_ROOT, path), temp) <= 0, "Invalid key: '%s'", path); + return temp; +} +bool ClaspCliConfig::hasValue(const char* path) const { + int nVals; + return getKeyInfo(getKey(KEY_ROOT, path), 0, 0, 0, &nVals) == 1 && nVals > 0; +} + +int ClaspCliConfig::setValue(KeyType key, const char* value) { + int16 id = decodeKey(key); + if (!isLeafId(id)) { return -1; } + if ((decodeMode(key) & mode_tester) != 0) { + addTesterConfig(); + initTester_ = false; + } + ScopedSet scope(*this, decodeMode(key), decodeSolver(key)); + try { return setActive(id, value); } + catch (...) { return -2; } +} + +bool ClaspCliConfig::setValue(const char* path, const char* value) { + int ret = setValue(getKey(KEY_ROOT, path), value); + CLASP_FAIL_IF(ret < 0, (ret == -1 ? "Invalid or incomplete key: '%s'" : "Value error in key: '%s'"), path); + return ret != 0; +} + +int ClaspCliConfig::applyActive(int o, const char* _val_, std::string* _val_out_, const char** _desc_out_, const char** _name_out_) { + UserConfig* active = this->active(); + uint32 sId = cliId; + SolverOpts* solver = 0; + SearchOpts* search = 0; + ContextParams* ctxOpts= active; + if (_name_out_) { *_name_out_ = 0; } + if (_val_ || _val_out_) { + if (!active || (active == testerConfig() && !isTesterOption(o)) || ((cliMode & mode_solver) != 0 && !isSolverOption(o))) { + o = (cliMode & mode_relaxed) != 0 ? detail__before_options : detail__num_options; + } + else if (isSolverOption(o)) { + solver = &active->addSolver(sId); + search = &active->addSearch(sId); + } + } + if (!isOption(o)) { + return o == detail__before_options ? int(_val_ != 0) : -1; + } + // action & helper macros used in get/set + using bk_lib::xconvert; using bk_lib::off; using bk_lib::opt; + using bk_lib::stringTo; using bk_lib::toString; + #define ITE(c, a, b) (!!(c) ? (a) : (b)) + #define FUN(x) for (bk_lib::ArgString x = _val_;;) + #define STORE(obj) { return stringTo((_val_), obj); } + #define STORE_LEQ(x, y) { unsigned __n; return stringTo(_val_, __n) && SET_LEQ(x, __n, y); } + #define STORE_FLAG(x) { bool __b; return stringTo(_val_, __b) && SET(x, static_cast(__b)); } + #define STORE_OR_FILL(x) { unsigned __n; return stringTo(_val_, __n) && SET_OR_FILL(x, __n); } + #define GET_FUN(x) bk_lib::StringBuilder x(*_val_out_); if (!x);else + #define GET(...) *_val_out_ = toString( __VA_ARGS__ ) + #define GET_IF(c, ...) *_val_out_ = ITE((c), toString(__VA_ARGS__), toString(off)) + switch(static_cast(o)) { + default: return -1; + #define OPTION(k, e, a, d, x, v) \ + case opt_##k:\ + if (_name_out_){ *_name_out_ = #k ; }\ + if (_val_) try { x ; }catch(...) {return 0;}\ + if (_val_out_) { v ; }\ + if (_desc_out_){ *_desc_out_ = d; }\ + return 1; + #define CLASP_CONTEXT_OPTIONS (*ctxOpts) + #define CLASP_GLOBAL_OPTIONS (*this) + #define CLASP_ASP_OPTIONS asp + #define CLASP_SOLVE_OPTIONS solve + #define CLASP_SOLVER_OPTIONS (*solver) + #define CLASP_SEARCH_OPTIONS (*search) + #define CLASP_SEARCH_RESTART_OPTIONS search->restart + #define CLASP_SEARCH_REDUCE_OPTIONS search->reduce + #include + } + #undef FUN + #undef STORE + #undef STORE_LEQ + #undef STORE_FLAG + #undef STORE_OR_FILL + #undef GET_IF + #undef GET + #undef ITE +} + +int ClaspCliConfig::setActive(int id, const char* setVal) { + if (isOption(id)) { return applyActive(id, setVal ? setVal : "", 0, 0, 0); } + else if (id == meta_config){ + int sz = setAppOpt(id, setVal); + if (sz <= 0) { return 0; } + std::string m; + UserConfig* act = active(); + ConfigIter it = getConfig(act->cliConfig, m); + act->hasConfig = 0; + cliMode |= mode_relaxed; + act->resize(1, 1); + for (uint32 sId = 0; it.valid(); it.next()) { + act->addSolver(sId); + act->addSearch(sId); + cliId = static_cast(sId); + if (!setConfig(it, false, ParsedOpts(), 0)){ return 0; } + if (++sId == static_cast(sz)) { break; } + cliMode |= mode_solver; + } + if (sz < 65 && static_cast(sz) > act->numSolver()) { + for (uint32 sId = act->numSolver(), mod = sId, end = static_cast(sz); sId != end; ++sId) { + SolverParams& solver = act->addSolver(sId); + SolveParams& search = act->addSearch(sId); + (solver = act->solver(sId % mod)).setId(sId); + search = act->search(sId % mod); + } + } + return static_cast((act->hasConfig = 1) == 1); + } + else { return -1; } +} + +int ClaspCliConfig::getActive(int o, std::string* val, const char** desc, const char** opt) const { + if (isOption(o)) { return const_cast(*this).applyActive(o, 0, val, desc, opt); } + else if (!active()) { return -1; } + else if (o == meta_config){ + const NodeKey& n = nodes_g[-o]; + if (val) { + uint8 k = (ConfigKey)active()->cliConfig; + if (k < config_max_value) { xconvert(*val, static_cast(k)); } + else { val->append(config_[!isGenerator()]); } + } + if (desc) { *desc = n.desc; } + if (opt) { *opt = n.name; } + return 1; + } + else { return -1; } +} +int ClaspCliConfig::setAppOpt(int o, const char* _val_) { + if (o == meta_config) { + std::pair defC(config_default, INT_MAX); + if (bk_lib::stringTo(_val_, defC)){ active()->cliConfig = (uint8)defC.first; } + else { + CLASP_FAIL_IF(!std::ifstream(_val_).is_open(), "Could not open config file '%s'", _val_); + config_[!isGenerator()] = _val_; active()->cliConfig = config_max_value + !isGenerator(); + } + return Range(0, INT_MAX).clamp(defC.second); + } + else if (o == meta_tester && isGenerator()) { + addTesterConfig(); + initTester_ = false; + RawConfig config(""); + config.addArg(_val_); + ParsedOpts ex; + bool ret = ScopedSet(*this, mode_tester)->setConfig(config.iterator(), true, ParsedOpts(), &ex); + return ret && finalizeAppConfig(testerConfig(), finalizeParsed(testerConfig(), ex, ex), Problem_t::Asp, true); + } + return -1; // invalid option +} +bool ClaspCliConfig::setAppDefaults(UserConfig* active, uint32 sId, const ParsedOpts& cmdLine, ProblemType t) { + ScopedSet temp(*this, (active == this ? 0 : mode_tester) | mode_relaxed, sId); + if (sId == 0 && t != Problem_t::Asp && cmdLine.count("sat-prepro") == 0) { + setActive(opt_sat_prepro, "2,20,25,120"); + } + if (active->addSolver(sId).search == SolverParams::no_learning) { + if (cmdLine.count("heuristic") == 0) { setActive(opt_heuristic, "unit"); } + if (cmdLine.count("lookahead") == 0) { setActive(opt_lookahead, "atom"); } + if (cmdLine.count("deletion") == 0) { setActive(opt_deletion, "no"); } + if (cmdLine.count("restarts") == 0) { setActive(opt_restarts, "no"); } + } + return true; +} + +bool ClaspCliConfig::setConfig(const ConfigIter& config, bool allowMeta, const ParsedOpts& exclude, ParsedOpts* out) { + createOptions(); + ParseContext ctx(*this, config.name(), &exclude, allowMeta, out); + ProgramOptions::parseCommandString(config.args(), ctx, ProgramOptions::command_line_allow_flag_value); + return true; +} + +bool ClaspCliConfig::validate() { + UserConfiguration* arr[3] = { this, testerConfig(), 0 }; + UserConfiguration** c = arr; + char ctx[80]; + do { + for (uint32 i = 0; i != (*c)->numSolver(); ++i) { + Clasp::Cli::validate(clasp_format(ctx, 80, "<%s>.%u", *c == this ? "":"", i), (*c)->solver(i), (*c)->search(i)); + } + } while (*++c); + return true; +} + +bool ClaspCliConfig::finalize(const ParsedOpts& x, ProblemType t, bool defs) { + ParsedOpts temp; + return finalizeAppConfig(this, finalizeParsed(this, x, temp), t, defs); +} + +void ClaspCliConfig::addDisabled(ParsedOpts& parsed) { + finalizeParsed(this, parsed, parsed); +} + +const ClaspCliConfig::ParsedOpts& ClaspCliConfig::finalizeParsed(UserConfig* active, const ParsedOpts& parsed, ParsedOpts& exclude) const { + bool copied = &parsed == &exclude; + if (active->search(0).reduce.fReduce() == 0 && parsed.count("deletion") != 0) { + if (!copied) { exclude = parsed; copied = true; } + exclude.add("del-cfl"); + exclude.add("del-max"); + exclude.add("del-grow"); + } + return !copied ? parsed : exclude; +} + +bool ClaspCliConfig::finalizeAppConfig(UserConfig* active, const ParsedOpts& parsed, ProblemType t, bool defs) { + if (defs && !setAppDefaults(active, 0, parsed, t)) { return false; } + SolverParams defSolver = active->solver(0); + SolveParams defSearch = active->search(0); + if (active->hasConfig) { return true; } + uint8 c = active->cliConfig; + if (c == config_many && solve.numSolver() == 1) { c = config_default; } + if (c == config_default) { + if (defSolver.search == SolverParams::no_learning) { c = config_nolearn; } + else if (active == testerConfig()) { c = config_tester_default; } + else if (solve.numSolver() == 1 || !solve.defaultPortfolio()) { c = t == Problem_t::Asp ? (uint8)config_asp_default : (uint8)config_sat_default; } + else { c = config_many; } + } + std::string m; + ConfigIter conf = getConfig(c, m); + uint8 mode = (active == testerConfig() ? mode_tester : 0) | mode_relaxed; + uint32 portSize = 0; + const char* ctx = active == testerConfig() ? "" : ""; + char buf[80]; + for (uint32 i = 0; i != solve.numSolver() && conf.valid(); ++i) { + SolverParams& solver = (active->addSolver(i) = defSolver).setId(i); + SolveParams& search = (active->addSearch(i) = defSearch); + ConfigKey baseK = config_default; + CLASP_FAIL_IF(*conf.base() && !bk_lib::stringTo(conf.base(), baseK), "%s.%s: '%s': Invalid base config!", ctx, conf.name(), conf.base()); + if (baseK != config_default && !ScopedSet(*this, mode|mode_solver, i)->setConfig(getConfig(baseK), false, parsed, 0)) { + return false; + } + if (!ScopedSet(*this, mode, i)->setConfig(conf, false, parsed, 0)) { + return false; + } + Clasp::Cli::validate(clasp_format(buf, 80, "%s.%s", ctx, conf.name()), solver, search); + ++portSize; + conf.next(); + mode |= mode_solver; + } + active->hasConfig = 1; + return true; +} + +bool ClaspCliConfig::setAppConfig(const RawConfig& config, ProblemType t) { + ProgramOptions::ParsedOptions exclude; + reset(); + return setConfig(config.iterator(), true, exclude, &exclude) && assignDefaults(exclude) && finalize(exclude, t, true); +} + +void validate(const char* ctx, const SolverParams& solver, const SolveParams& search) { + if (!ctx) { ctx = ""; } + const ReduceParams& reduce = search.reduce; + if (solver.search == SolverParams::no_learning) { + CLASP_FAIL_IF(Heuristic_t::isLookback(solver.heuId), "'%s': Heuristic requires lookback strategy!", ctx); + CLASP_FAIL_IF(!search.restart.sched.disabled() && !search.restart.sched.defaulted(), "'%s': 'no-lookback': restart options disabled!", ctx); + CLASP_FAIL_IF(!reduce.cflSched.disabled() || (!reduce.growSched.disabled() && !reduce.growSched.defaulted()) || search.reduce.fReduce() != 0, "'%s': 'no-lookback': deletion options disabled!", ctx); + } + bool hasSched = !reduce.cflSched.disabled() || !reduce.growSched.disabled() || reduce.maxRange != UINT32_MAX; + CLASP_FAIL_IF(hasSched && reduce.fReduce() == 0.0f && !reduce.growSched.defaulted(), "'%s': 'no-deletion': deletion strategies disabled!", ctx); + CLASP_FAIL_IF(!hasSched && reduce.fReduce() != 0.0f && !reduce.growSched.defaulted(), "'%s': 'deletion': deletion strategy required!", ctx); +} +}} diff --git a/libclasp/src/clasp_output.cpp b/libclasp/src/clasp_output.cpp new file mode 100644 index 0000000..6cb26b9 --- /dev/null +++ b/libclasp/src/clasp_output.cpp @@ -0,0 +1,1143 @@ +// +// Copyright (c) 2009-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(_WIN32) +#include +#elif !defined(SIGALRM) +#define SIGALRM 14 +#endif +#ifdef _MSC_VER +#include +#define CLASP_ISNAN(x) (_isnan(x) != 0) +#pragma warning (disable : 4996) +#elif defined(__cplusplus) && __cplusplus >= 201103L +#include +#define CLASP_ISNAN(x) std::isnan(x) +#else +#include +#define CLASP_ISNAN(x) isnan(x) +#endif +inline bool isNan(double d) { return CLASP_ISNAN(d); } +#undef CLASP_ISNAN +namespace Clasp { namespace Cli { +///////////////////////////////////////////////////////////////////////////////////////// +// Event formatting +///////////////////////////////////////////////////////////////////////////////////////// +static void null_term_copy(const char* in, int inSize, char* buf, uint32 bufSize) { + if (!in || !buf || !bufSize) return; + uint32 n = inSize < 0 ? static_cast(0) : std::min(bufSize-1, static_cast(inSize)); + std::memcpy(buf, in, n); + buf[n] = 0; +} +void format(const Clasp::BasicSolveEvent& ev, char* out, uint32 outSize) { + char buf[1024]; int n; + const Solver& s = *ev.solver; + n = sprintf(buf, "%2u:%c|%7u/%-7u|%8u/%-8u|%10" PRIu64"/%-6.3f|%8" PRId64"/%-10" PRId64"|" + , s.id() + , static_cast(ev.op) + , s.numFreeVars() + , (s.decisionLevel() > 0 ? s.levelStart(1) : s.numAssignedVars()) + , s.numConstraints() + , s.numLearntConstraints() + , s.stats.conflicts + , s.stats.conflicts/std::max(1.0,double(s.stats.choices)) + , ev.cLimit <= (UINT32_MAX) ? (int64)ev.cLimit:-1 + , ev.lLimit != (UINT32_MAX) ? (int64)ev.lLimit:-1 + ); + null_term_copy(buf, n, out, outSize); +} +void format(const Clasp::SolveTestEvent& ev, char* out, uint32 outSize) { + char buf[1024]; int n; + char ct = ev.partial ? 'P' : 'F'; + if (ev.result == -1) { n = sprintf(buf, "%2u:%c| HC: %-5u %-60s|", ev.solver->id(), ct, ev.hcc, "..."); } + else { + n = sprintf(buf, "%2u:%c| HC: %-5u %-4s|%8u/%-8u|%10" PRIu64"/%-6.3f| T: %-15.3f|", ev.solver->id(), ct, ev.hcc, (ev.result == 1 ? "OK" : "FAIL") + , ev.solver->numConstraints() + , ev.solver->numLearntConstraints() + , ev.conflicts() + , ev.conflicts()/std::max(1.0,double(ev.choices())) + , ev.time + ); + } + null_term_copy(buf, n, out, outSize); +} +#if WITH_THREADS +void format(const Clasp::mt::MessageEvent& ev, char* out, uint32 outSize) { + typedef Clasp::mt::MessageEvent EV; + char buf[1024]; int n; + if (ev.op != EV::completed) { n = sprintf(buf, "%2u:X| %-15s %-53s |", ev.solver->id(), ev.msg, ev.op == EV::sent ? "sent" : "received"); } + else { n = sprintf(buf, "%2u:X| %-15s %-35s in %13.3fs |", ev.solver->id(), ev.msg, "completed", ev.time); } + null_term_copy(buf, n, out, outSize); +} +#endif +///////////////////////////////////////////////////////////////////////////////////////// +// Output +///////////////////////////////////////////////////////////////////////////////////////// +Output::Output(uint32 verb) : summary_(0), verbose_(0) { + std::memset(quiet_, 0, sizeof(quiet_)); + setCallQuiet(print_no); + setVerbosity(verb); + clearModel(); +} +Output::~Output() {} +void Output::setVerbosity(uint32 verb) { + Event::Verbosity x = (Event::Verbosity)std::min(verbose_ = verb, (uint32)Event::verbosity_max); + EventHandler::setVerbosity(Event::subsystem_facade , x); + EventHandler::setVerbosity(Event::subsystem_load , x); + EventHandler::setVerbosity(Event::subsystem_prepare, x); + EventHandler::setVerbosity(Event::subsystem_solve , x); +} +void Output::setModelQuiet(PrintLevel model){ quiet_[0] = static_cast(model); } +void Output::setOptQuiet(PrintLevel opt) { quiet_[1] = static_cast(opt); } +void Output::setCallQuiet(PrintLevel call) { quiet_[2] = static_cast(call); } + +void Output::saveModel(const Model& m) { + saved_ = m; + const SumVec* costs = m.costs ? &(costs_ = *m.costs) : 0; + const ValueVec* vals = &(vals_ = *m.values); + saved_.values = vals; + saved_.costs = costs; +} + +void Output::onEvent(const Event& ev) { + typedef ClaspFacade::StepStart StepStart; + typedef ClaspFacade::StepReady StepReady; + if (const StepStart* start = event_cast(ev)) { + startStep(*start->facade); + } + else if (const StepReady* ready = event_cast(ev)) { + stopStep(*ready->summary); + } +} +bool Output::onModel(const Solver& s, const Model& m) { + if (modelQ() == print_all || optQ() == print_all) { + printModel(s.outputTable(), m, print_all); + } + if (modelQ() == print_best || optQ() == print_best) { + if (m.opt == 1 && !m.consequences()) { printModel(s.outputTable(), m, print_best); clearModel(); } + else { saveModel(m); } + } + return true; +} +bool Output::onUnsat(const Solver& s, const Model& m) { + if (m.ctx) { + const LowerBound* lower = m.ctx->optimize() && s.lower.bound > 0 ? &s.lower : 0; + const Model* prevModel = m.num ? &m : 0; + if (modelQ() == print_all || optQ() == print_all) { + printUnsat(s.outputTable(), lower, prevModel); + } + } + return true; +} +void Output::startStep(const ClaspFacade&) { clearModel(); summary_ = 0; } +void Output::stopStep(const ClaspFacade::Summary& s){ + if (getModel()) { + if (s.model()){ + saved_.opt = s.model()->opt; + saved_.def = s.model()->def; + } + printModel(s.ctx().output, *getModel(), print_best); + clearModel(); + } + else if (modelQ() == print_all && s.model() && s.model()->up && !s.model()->def) { + printModel(s.ctx().output, *s.model(), print_all); + } + if (callQ() == print_all) { + printSummary(s, false); + if (stats(s)) { printStatistics(s, false); } + } + else if (callQ() == print_best) { + summary_ = &s; + } +} +void Output::shutdown(const ClaspFacade::Summary& summary) { + if (summary_) { + printSummary(*summary_, false); + if (stats(summary)) { printStatistics(*summary_, false); } + } + printSummary(summary, true); + if (stats(summary)) { printStatistics(summary, true); } + shutdown(); +} +// Returns the number of consequences and estimates in m. +// For a model m with m.consequences and a return value ret: +// - ret.first is the number of definite consequences +// - ret.second is the number of remaining possible consequences +Output::UPair Output::numCons(const OutputTable& out, const Model& m) const { + uint32 low = 0, up = 0; + if (out.projectMode() == OutputTable::project_output) { + low += out.numFacts(); + for (OutputTable::pred_iterator it = out.pred_begin(); it != out.pred_end(); ++it) { + low += m.isDef(it->cond); + up += m.isEst(it->cond); + } + for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) { + Literal p = posLit(*it); + low += m.isDef(p); + up += m.isEst(p); + } + } + else { + for (OutputTable::lit_iterator it = out.proj_begin(), end = out.proj_end(); it != end; ++it) { + low += m.isDef(*it); + up += m.isEst(*it); + } + } + return UPair(low, m.def ? 0 : up); +} + +// Prints shown symbols in model. +// The functions prints +// - true literals in definite answer, followed by +// - true literals in current estimate if m.consequences() +void Output::printWitness(const OutputTable& out, const Model& m, uintp data) { + for (OutputTable::fact_iterator it = out.fact_begin(); it != out.fact_end(); ++it) { + data = doPrint(OutPair(*it, lit_true()), data); + } + for (const char* x = out.theory ? out.theory->first(m) : 0; x; x = out.theory->next()) { + data = doPrint(OutPair(x, lit_true()), data); + } + const bool onlyD = m.type != Model::Cautious || m.def; + for (bool D = true;; D = !D) { + for (OutputTable::pred_iterator it = out.pred_begin(); it != out.pred_end(); ++it) { + if (m.isTrue(it->cond) && (onlyD || m.isDef(it->cond) == D)) { + data = doPrint(OutPair(it->name, lit_true()), data); + } + } + if (out.vars_begin() != out.vars_end()) { + const bool showNeg = !m.consequences(); + if (out.projectMode() == OutputTable::project_output || !out.filter("_")) { + for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) { + Literal p = posLit(*it); + if ((showNeg || m.isTrue(p)) && (onlyD || m.isDef(p) == D)) { + data = doPrint(OutPair(static_cast(0), m.isTrue(p) ? p : ~p), data); + } + } + } + else { + for (OutputTable::lit_iterator it = out.proj_begin(), end = out.proj_end(); it != end; ++it) { + if ((showNeg || m.isTrue(*it)) && (onlyD || m.isDef(*it) == D)) { + data = doPrint(OutPair(static_cast(0), m.isTrue(*it) ? *it : ~*it), data); + } + } + } + } + if (D == onlyD) { return; } + } +} +void Output::printUnsat(const OutputTable&, const LowerBound*, const Model*) {} +uintp Output::doPrint(const OutPair&, UPtr x) { return x; } +bool Output::stats(const ClaspFacade::Summary& summary) const { + return summary.facade->config()->context().stats != 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// JsonOutput +///////////////////////////////////////////////////////////////////////////////////////// +JsonOutput::JsonOutput(uint32 v) : Output(std::min(v, uint32(1))), open_("") { + objStack_.reserve(10); +} +JsonOutput::~JsonOutput() { JsonOutput::shutdown(); } +void JsonOutput::run(const char* solver, const char* version, const std::string* iBeg, const std::string* iEnd) { + if (indent() == 0) { + open_ = ""; + JsonOutput::pushObject(); + } + printKeyValue("Solver", std::string(solver).append(" version ").append(version).c_str()); + pushObject("Input", type_array); + printf("%-*s", indent(), " "); + for (const char* sep = ""; iBeg != iEnd; ++iBeg, sep = ",") { + printString(iBeg->c_str(), sep); + } + popObject(); + pushObject("Call", type_array); +} +void JsonOutput::shutdown(const ClaspFacade::Summary& summary) { + while (!objStack_.empty() && *objStack_.rbegin() == '[') { + popObject(); + } + Output::shutdown(summary); +} + +void JsonOutput::shutdown() { + if (!objStack_.empty()) { + do { popObject(); } while (!objStack_.empty()); + printf("\n"); + } + fflush(stdout); +} +void JsonOutput::startStep(const ClaspFacade& f) { + Output::startStep(f); + pushObject(0, type_object); +} +void JsonOutput::stopStep(const ClaspFacade::Summary& s) { + assert(!objStack_.empty()); + Output::stopStep(s); + while (popObject() != '{') { ; } +} + +bool JsonOutput::visitThreads(Operation op) { + if (op == Enter) { pushObject("Thread", type_array); } + else if (op == Leave) { popObject(); } + return true; +} +bool JsonOutput::visitTester(Operation op) { + if (op == Enter) { pushObject("Tester"); } + else if (op == Leave) { popObject(); } + return true; +} +bool JsonOutput::visitHccs(Operation op) { + if (op == Enter) { pushObject("HCC", type_array); } + else if (op == Leave) { popObject(); } + return true; +} +void JsonOutput::visitThread(uint32, const SolverStats& stats) { + pushObject(0, type_object); + JsonOutput::visitSolverStats(stats); + popObject(); +} +void JsonOutput::visitHcc(uint32, const ProblemStats& p, const SolverStats& s) { + pushObject(0, type_object); + JsonOutput::visitProblemStats(p); + JsonOutput::visitSolverStats(s); + popObject(); +} + +void JsonOutput::visitSolverStats(const SolverStats& stats) { + printCoreStats(stats); + if (stats.extra) { + printExtStats(*stats.extra, objStack_.size() == 2); + printJumpStats(stats.extra->jumps); + } +} + +void JsonOutput::printCoreStats(const CoreStats& st) { + pushObject("Core"); + printKeyValue("Choices" , st.choices); + printKeyValue("Conflicts" , st.conflicts); + printKeyValue("Backtracks" , st.backtracks()); + printKeyValue("Backjumps" , st.backjumps()); + printKeyValue("Restarts" , st.restarts); + printKeyValue("RestartAvg" , st.avgRestart()); + printKeyValue("RestartLast", st.lastRestart); + popObject(); // Core +} + +void JsonOutput::printExtStats(const ExtendedStats& stx, bool generator) { + pushObject("More"); + printKeyValue("CPU", stx.cpuTime); + printKeyValue("Models", stx.models); + if (stx.domChoices) { + printKeyValue("DomChoices", stx.domChoices); + } + if (stx.hccTests) { + pushObject("StabTests"); + printKeyValue("Sum", stx.hccTests); + printKeyValue("Full", stx.hccTests - stx.hccPartial); + printKeyValue("Partial", stx.hccPartial); + popObject(); + } + if (stx.models) { + printKeyValue("AvgModel", stx.avgModel()); + } + printKeyValue("Splits", stx.splits); + printKeyValue("Problems", stx.gps); + printKeyValue("AvgGPLength", stx.avgGp()); + pushObject("Lemma"); + printKeyValue("Sum", stx.lemmas()); + printKeyValue("Deleted" , stx.deleted); + pushObject("Type", type_array); + const char* names[] = {"Short", "Conflict", "Loop", "Other"}; + for (int i = Constraint_t::Static; i <= Constraint_t::Other; ++i) { + pushObject(); + printKeyValue("Type", names[i]); + if (i == 0) { + printKeyValue("Sum", stx.binary+stx.ternary); + printKeyValue("Ratio", percent(stx.binary+stx.ternary, stx.lemmas())); + printKeyValue("Binary", stx.binary); + printKeyValue("Ternary", stx.ternary); + } + else { + printKeyValue("Sum", stx.lemmas(ConstraintType(i))); + printKeyValue("AvgLen", stx.avgLen(ConstraintType(i))); + } + popObject(); + } + popObject(); + popObject(); // Lemma + if (stx.distributed || stx.integrated) { + pushObject("Distribution"); + printKeyValue("Distributed", stx.distributed); + printKeyValue("Ratio", stx.distRatio()); + printKeyValue("AvgLbd", stx.avgDistLbd()); + popObject(); + pushObject("Integration"); + printKeyValue("Integrated", stx.integrated); + printKeyValue("Units", stx.intImps); + printKeyValue("AvgJump", stx.avgIntJump()); + if (generator) { printKeyValue("Ratio", stx.intRatio()); } + popObject(); + } + popObject(); // More +} +void JsonOutput::printJumpStats(const JumpStats& st) { + pushObject("Jumps"); + printKeyValue("Sum", st.jumps); + printKeyValue("Max", st.maxJump); + printKeyValue("MaxExec", st.maxJumpEx); + printKeyValue("Avg", st.avgJump()); + printKeyValue("AvgExec", st.avgJumpEx()); + printKeyValue("Levels", st.jumpSum); + printKeyValue("LevelsExec", st.jumped()); + pushObject("Bounded"); + printKeyValue("Sum", st.bounded); + printKeyValue("Max", st.maxBound); + printKeyValue("Avg", st.avgBound()); + printKeyValue("Levels", st.boundSum); + popObject(); + popObject(); +} +void JsonOutput::visitLogicProgramStats(const Asp::LpStats& lp) { + using namespace Asp; + pushObject("LP"); + pushObject("Rules"); + printKeyValue("Original", lp.rules[0].sum()); + printKeyValue("Final", lp.rules[1].sum()); + for (uint32 i = 0; i != RuleStats::numKeys(); ++i) { + if (i != RuleStats::Normal && lp.rules[0][i]) { + pushObject(RuleStats::toStr(i)); + printKeyValue("Original", lp.rules[0][i]); + printKeyValue("Final", lp.rules[1][i]); + popObject(); + } + } + popObject(); // Rules + printKeyValue("Atoms", lp.atoms); + if (lp.auxAtoms) { printKeyValue("AuxAtoms", lp.auxAtoms); } + if (lp.disjunctions[0]) { + pushObject("Disjunctions"); + printKeyValue("Original", lp.disjunctions[0]); + printKeyValue("Final", lp.disjunctions[1]); + popObject(); + } + pushObject("Bodies"); + printKeyValue("Original", lp.bodies[0].sum()); + printKeyValue("Final" , lp.bodies[1].sum()); + for (uint32 i = 1; i != BodyStats::numKeys(); ++i) { + if (lp.bodies[0][i]) { + pushObject(BodyStats::toStr(i)); + printKeyValue("Original", lp.bodies[0][i]); + printKeyValue("Final", lp.bodies[1][i]); + popObject(); + } + } + popObject(); + if (lp.sccs == 0) { printKeyValue("Tight", "yes"); } + else if (lp.sccs == PrgNode::noScc) { printKeyValue("Tight", "N/A"); } + else { + printKeyValue("Tight", "no"); + printKeyValue("SCCs", lp.sccs); + printKeyValue("NonHcfs", lp.nonHcfs); + printKeyValue("UfsNodes", lp.ufsNodes); + printKeyValue("NonHcfGammas", lp.gammas); + } + pushObject("Equivalences"); + printKeyValue("Sum", lp.eqs()); + printKeyValue("Atom", lp.eqs(Var_t::Atom)); + printKeyValue("Body", lp.eqs(Var_t::Body)); + printKeyValue("Other", lp.eqs(Var_t::Hybrid)); + popObject(); + popObject(); // LP +} +void JsonOutput::visitProblemStats(const ProblemStats& p) { + pushObject("Problem"); + printKeyValue("Variables", p.vars.num); + printKeyValue("Eliminated", p.vars.eliminated); + printKeyValue("Frozen", p.vars.frozen); + pushObject("Constraints"); + uint32 sum = p.numConstraints(); + printKeyValue("Sum", sum); + printKeyValue("Binary", p.constraints.binary); + printKeyValue("Ternary", p.constraints.ternary); + popObject(); // Constraints + printKeyValue("AcycEdges", p.acycEdges); + popObject(); // PS +} + +void JsonOutput::printKey(const char* k) { + printf("%s%-*s\"%s\": ", open_, indent(), " ", k); + open_ = ",\n"; +} + +void JsonOutput::printString(const char* v, const char* sep) { + assert(v); + const uint32 BUF_SIZE = 1024; + char buf[BUF_SIZE]; + uint32 n = 0; + buf[n++] = '"'; + while (*v) { + if (*v != '\\' && *v != '"') { buf[n++] = *v++; } + else if (*v == '"' || !strchr("\"\\/\b\f\n\r\t", v[1])) { buf[n++] = '\\'; buf[n++] = *v++; } + else { buf[n++] = v[0]; buf[n++] = v[1]; v += 2; } + if (n > BUF_SIZE - 2) { buf[n] = 0; printf("%s%s", sep, buf); n = 0; sep = ""; } + } + buf[n] = 0; + printf("%s%s\"", sep, buf); +} + +void JsonOutput::printKeyValue(const char* k, const char* v) { + printf("%s%-*s\"%s\": ", open_, indent(), " ", k); + printString(v,""); + open_ = ",\n"; +} +void JsonOutput::printKeyValue(const char* k, uint64 v) { + printf("%s%-*s\"%s\": %" PRIu64, open_, indent(), " ", k, v); + open_ = ",\n"; +} +void JsonOutput::printKeyValue(const char* k, uint32 v) { return printKeyValue(k, uint64(v)); } +void JsonOutput::printKeyValue(const char* k, double v) { + if (!isNan(v)) { printf("%s%-*s\"%s\": %.3f", open_, indent(), " ", k, v); } + else { printf("%s%-*s\"%s\": %s", open_, indent(), " ", k, "null"); } + open_ = ",\n"; +} + +void JsonOutput::pushObject(const char* k, ObjType t) { + if (k) { + printKey(k); + } + else { + printf("%s%-*.*s", open_, indent(), indent(), " "); + } + char o = t == type_object ? '{' : '['; + objStack_ += o; + printf("%c\n", o); + open_ = ""; +} +char JsonOutput::popObject() { + assert(!objStack_.empty()); + char o = *objStack_.rbegin(); + objStack_.erase(objStack_.size()-1); + printf("\n%-*.*s%c", indent(), indent(), " ", o == '{' ? '}' : ']'); + open_ = ",\n"; + return o; +} +void JsonOutput::startModel() { + if (!hasWitness()) { + pushObject("Witnesses", type_array); + } + pushObject(); +} +uintp JsonOutput::doPrint(const OutPair& out, uintp data) { + const char* sep = reinterpret_cast(data); + if (out.first){ printString(out.first, sep); } + else { printf("%s%d", sep, out.second.sign() ? -static_cast(out.second.var()) : static_cast(out.second.var())); } + return reinterpret_cast(", "); +} +void JsonOutput::printModel(const OutputTable& out, const Model& m, PrintLevel x) { + uint32 hasModel = (x == modelQ()); + if (hasModel) { + startModel(); + pushObject("Value", type_array); + printf("%-*s", indent(), " "); + printWitness(out, m, reinterpret_cast("")); + popObject(); + if (m.consequences() && x == optQ()) { + printCons(numCons(out, m)); + } + } + if (x == optQ()) { + if (m.consequences() && !hasModel++) { + startModel(); + printCons(numCons(out, m)); + } + if (m.costs) { + if (!hasModel++) { startModel(); } + printCosts(*m.costs); + } + } + if (hasModel) { popObject(); } +} +void JsonOutput::printCosts(const SumVec& opt, const char* name) { + pushObject(name, type_array); + printf("%-*s", indent(), " "); + const char* sep = ""; + for (SumVec::const_iterator it = opt.begin(), end = opt.end(); it != end; ++it) { + printf("%s%" PRId64, sep, *it); + sep = ", "; + } + popObject(); +} +void JsonOutput::printCons(const UPair& cons) { + pushObject("Consequences"); + printKeyValue("True", cons.first); + printKeyValue("Open", cons.second); + popObject(); +} + +void JsonOutput::printSummary(const ClaspFacade::Summary& run, bool final) { + if (hasWitness()) { popObject(); } + const char* res = "UNKNOWN"; + if (run.unsat()) { res = "UNSATISFIABLE"; } + else if (run.sat()) { res = !run.optimum() ? "SATISFIABLE" : "OPTIMUM FOUND"; } + printKeyValue("Result", res); + if (verbosity()) { + if (run.result.interrupted()){ printKeyValue(run.result.signal != SIGALRM ? "INTERRUPTED" : "TIME LIMIT", uint32(1)); } + pushObject("Models"); + printKeyValue("Number", run.numEnum); + printKeyValue("More" , run.complete() ? "no" : "yes"); + if (run.sat()) { + if (run.consequences()){ + printKeyValue(run.consequences(), run.complete() ? "yes":"unknown"); + printCons(numCons(run.ctx().output, *run.model())); + } + if (run.optimize()) { + printKeyValue("Optimum", run.optimum()?"yes":"unknown"); + printKeyValue("Optimal", run.optimal()); + printCosts(*run.costs()); + } + } + popObject(); + if (run.hasLower() && !run.optimum()) { + pushObject("Bounds"); + printCosts(run.lower(), "Lower"); + printCosts(run.costs() ? *run.costs() : SumVec(), "Upper"); + popObject(); + } + if (final) { printKeyValue("Calls", run.step + 1); } + pushObject("Time"); + printKeyValue("Total", run.totalTime); + printKeyValue("Solve", run.solveTime); + printKeyValue("Model", run.satTime); + printKeyValue("Unsat", run.unsatTime); + printKeyValue("CPU" , run.cpuTime); + popObject(); // Time + if (run.ctx().concurrency() > 1) { + printKeyValue("Threads", run.ctx().concurrency()); + printKeyValue("Winner", run.ctx().winner()); + } + } +} +void JsonOutput::printStatistics(const ClaspFacade::Summary& summary, bool) { + if (hasWitness()) { popObject(); } + pushObject("Stats", type_object); + summary.accept(*this); + popObject(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// TextOutput +///////////////////////////////////////////////////////////////////////////////////////// +#define printKeyValue(k, fmt, value) printf("%s%-*s: " fmt, format[cat_comment], width_, (k), (value)) +#define printLN(cat, fmt, ...) printf("%s" fmt "\n", format[cat], __VA_ARGS__) +#define printBR(cat) printf("%s\n", format[cat]) +#define printKey(k) printf("%s%-*s: ", format[cat_comment], width_, (k)) +const char* const rowSep = "----------------------------------------------------------------------------|"; +const char* const finalSep = "=============================== Accumulation ===============================|"; + +static inline std::string prettify(const std::string& str) { + if (str.size() < 40) return str; + std::string t("..."); + t.append(str.end()-38, str.end()); + return t; +} +TextOutput::TextOutput(uint32 verbosity, Format f, const char* catAtom, char ifs) : Output(verbosity), stTime_(0.0), state_(0) { + result[res_unknonw] = "UNKNOWN"; + result[res_sat] = "SATISFIABLE"; + result[res_unsat] = "UNSATISFIABLE"; + result[res_opt] = "OPTIMUM FOUND"; + format[cat_comment] = ""; + format[cat_value] = ""; + format[cat_objective] = "Optimization: "; + format[cat_result] = ""; + format[cat_value_term] = ""; + format[cat_atom_name] = "%s"; + format[cat_atom_var] = "-%d"; + if (f == format_aspcomp) { + format[cat_comment] = "% "; + format[cat_value] = "ANSWER\n"; + format[cat_objective] = "COST "; + format[cat_atom_name] = "%s."; + result[res_sat] = ""; + result[res_unsat] = "INCONSISTENT"; + result[res_opt] = "OPTIMUM"; + setModelQuiet(print_best); + setOptQuiet(print_best); + } + else if (f == format_sat09 || f == format_pb09) { + format[cat_comment] = "c "; + format[cat_value] = "v "; + format[cat_objective] = "o "; + format[cat_result] = "s "; + format[cat_value_term]= "0"; + if (f == format_pb09) { + format[cat_value_term]= ""; + format[cat_atom_var] = "-x%d"; + setModelQuiet(print_best); + } + } + if (catAtom && *catAtom) { + char f = 0; + for (const char* x = catAtom; *x; ++x) { + CLASP_FAIL_IF(*x == '\n', "cat_atom: Invalid format string - new line not allowed!"); + if (*x == '%') { + CLASP_FAIL_IF(!*++x, "cat_atom: Invalid format string - missing format specifier!"); + if (*x != '%') { + CLASP_FAIL_IF(f, "cat_atom: Invalid format string - too many arguments!"); + CLASP_FAIL_IF(std::strchr("sd0", *x) == 0, "cat_atom: Invalid format string - invalid format specifier!"); + f = *x; + } + } + } + if (f == '0') { + std::size_t len = std::strlen(catAtom); + fmt_.reserve((len * 2) + 2); + fmt_.append(catAtom).append(1, '\0').append(1, '-').append(catAtom); + std::string::size_type p = fmt_.find("%0") + 1; + fmt_[p] = 's'; + fmt_[len + 2 + p] = 'd'; + format[cat_atom_name] = fmt_.c_str(); + format[cat_atom_var] = fmt_.c_str() + len + 1; + } + else { + format[f == 's' ? cat_atom_name : cat_atom_var] = catAtom; + } + } + CLASP_FAIL_IF(*format[cat_atom_var] != '-' , "cat_atom: Invalid format string - must start with '-'!"); + ifs_[0] = ifs; + ifs_[1] = 0; + width_ = 13+(int)strlen(format[cat_comment]); + ev_ = -1; +} +TextOutput::~TextOutput() {} + +void TextOutput::comment(uint32 v, const char* fmt, ...) const { + if (verbosity() >= v) { + printf("%s", format[cat_comment]); + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); + fflush(stdout); + } +} + +void TextOutput::run(const char* solver, const char* version, const std::string* begInput, const std::string* endInput) { + if (!version) version = ""; + if (solver) comment(1, "%s version %s\n", solver, version); + if (begInput != endInput) { + comment(1, "Reading from %s%s\n", prettify(*begInput).c_str(), (endInput - begInput) > 1 ? " ..." : ""); + } +} +void TextOutput::shutdown() {} +void TextOutput::printSummary(const ClaspFacade::Summary& run, bool final) { + if (final && callQ() != print_no){ + comment(1, "%s\n", finalSep); + } + const char* res = result[res_unknonw]; + if (run.unsat()) { res = result[res_unsat]; } + else if (run.sat()) { res = !run.optimum() ? result[res_sat] : result[res_opt]; } + if (std::strlen(res)) { printLN(cat_result, "%s", res); } + if (verbosity() || stats(run)) { + printBR(cat_comment); + if (run.result.interrupted()){ printKeyValue((run.result.signal != SIGALRM ? "INTERRUPTED" : "TIME LIMIT"), "%u\n", uint32(1)); } + const char* const moreStr = run.complete() ? "" : "+"; + printKey("Models"); + printf("%" PRIu64 "%s\n", run.numEnum, moreStr); + if (run.sat()) { + if (run.consequences()) { printLN(cat_comment, " %-*s: %s", width_-2, run.consequences(), (run.complete()?"yes":"unknown")); } + if (run.costs()) { printKeyValue(" Optimum", "%s\n", run.optimum()?"yes":"unknown"); } + if (run.optimize()) { + if (run.optimal() > 1){ printKeyValue(" Optimal", "%" PRIu64"\n", run.optimal()); } + printKey("Optimization"); + printCosts(*run.costs()); + printf("\n"); + } + if (run.consequences()) { + printKey("Consequences"); + printf("%u%s\n", numCons(run.ctx().output, *run.model()).first, moreStr); + } + } + if (run.hasLower() && !run.optimum()) { + printKey("Bounds"); + printBounds(run.lower(), run.costs() ? *run.costs() : SumVec()); + printf("\n"); + } + if (final) { printKeyValue("Calls", "%u\n", run.step + 1); } + printKey("Time"); + printf("%.3fs (Solving: %.2fs 1st Model: %.2fs Unsat: %.2fs)\n" + , run.totalTime + , run.solveTime + , run.satTime + , run.unsatTime); + printKeyValue("CPU Time", "%.3fs\n", run.cpuTime); + if (run.ctx().concurrency() > 1) { + printKeyValue("Threads", "%-8u", run.ctx().concurrency()); + printf(" (Winner: %u)\n", run.ctx().winner()); + } + } +} +void TextOutput::printStatistics(const ClaspFacade::Summary& run, bool) { + printBR(cat_comment); + accu_ = true; + run.accept(*this); +} +void TextOutput::startStep(const ClaspFacade& f) { + Output::startStep(f); + if (callQ() != print_no) { comment(1, "%s\n", rowSep); comment(2, "%-13s: %d\n", "Call", f.step()+1); } +} +void TextOutput::onEvent(const Event& ev) { + typedef SatElite::Progress SatPre; + if (ev.verb <= verbosity()) { + if (ev.system == 0) { setState(0,0,0); } + else if (ev.system == state_) { + if (ev.system == Event::subsystem_solve) { printSolveProgress(ev); } + else if (const SatPre* sat = event_cast(ev)){ + if (sat->op != SatElite::Progress::event_algorithm) { comment(2, "Sat-Prepro : %c: %8u/%-8u\r", (char)sat->op, sat->cur, sat->max); } + else if (sat->cur!= sat->max) { + setState(0,0,0); comment(2, "Sat-Prepro :\r"); + state_ = Event::subsystem_prepare; + } + else { + SatPreprocessor* p = sat->self; + double tEnd = RealTime::getTime(); + comment(2, "Sat-Prepro : %.3f (ClRemoved: %u ClAdded: %u LitsStr: %u)\n", tEnd - stTime_, p->stats.clRemoved, p->stats.clAdded, p->stats.litsRemoved); + state_ = 0; + } + } + } + else if (const LogEvent* log = event_cast(ev)) { + setState(ev.system, ev.verb, log->msg); + } + } + Output::onEvent(ev); +} + +void TextOutput::setState(uint32 state, uint32 verb, const char* m) { + if (state != state_ && verb <= verbosity()) { + double tEnd = RealTime::getTime(); + if (state_ == Event::subsystem_solve) { comment(2, "%s\n", rowSep); line_ = 20; } + else if (state_ != Event::subsystem_facade){ printf("%.3f\n", tEnd - stTime_); } + stTime_ = tEnd; + state_ = state; + ev_ = -1; + if (state_ == Event::subsystem_load) { comment(2, "%-13s: ", m ? m : "Reading"); } + else if (state_ == Event::subsystem_prepare){ comment(2, "%-13s: ", m ? m : "Preprocessing"); } + else if (state_ == Event::subsystem_solve) { comment(1, "Solving...\n"); line_ = 0; } + } +} + +void TextOutput::printSolveProgress(const Event& ev) { + if (ev.id == SolveTestEvent::id_s && (verbosity() & 4) == 0) { return; } + if (ev.id == BasicSolveEvent::id_s && (verbosity() & 1) == 0) { return; } + char lEnd = '\n'; + char line[128]; + if (const BasicSolveEvent* be = event_cast(ev)) { Clasp::Cli::format(*be, line, 128); } + else if (const SolveTestEvent* te = event_cast(ev) ) { Clasp::Cli::format(*te, line, 128); lEnd= te->result == -1 ? '\r' : '\n'; } +#if WITH_THREADS + else if (const mt::MessageEvent*me = event_cast(ev)){ Clasp::Cli::format(*me, line, 128); } +#endif + else if (const LogEvent* log = event_cast(ev)) { + clasp_format(line, sizeof(line), "[Solving+%.3fs]", RealTime::getTime() - stTime_); + printLN(cat_comment, "%2u:L| %-30s %-38s |", log->solver->id(), line, log->msg); + return; + } + else { return; } + bool newEvent = ((uint32)ev_.fetch_and_store(static_cast(ev.id))) != ev.id; + if ((lEnd == '\n' && --line_ == 0) || newEvent) { + if (line_ <= 0) { + line_ = 20; + if (verbosity() > 1 && (verbosity() & 1) != 0) { + printf("%s%s\n" + "%sID:T Vars Constraints State Limits |\n" + "%s #free/#fixed #problem/#learnt #conflicts/ratio #conflict/#learnt |\n" + "%s%s\n", format[cat_comment], rowSep, format[cat_comment], format[cat_comment], format[cat_comment], rowSep); + } + else if (verbosity() > 1) { + printf("%s%s\n" + "%sID:T Info Info Info |\n" + "%s%s\n", format[cat_comment], rowSep, format[cat_comment], format[cat_comment], rowSep); + } + } + else { printLN(cat_comment, "%s", rowSep); } + } + printf("%s%s%c", format[cat_comment], line, lEnd); + fflush(stdout); +} + +const char* TextOutput::fieldSeparator() const { return ifs_; } +int TextOutput::printSep(CategoryKey k) const { + return printf("%s%s", fieldSeparator(), *fieldSeparator() != '\n' ? "" : format[k]); +} +uintp TextOutput::doPrint(const OutPair& s, UPtr data) { + uint32& accu = reinterpret_cast(data)->first; + uint32& maxLine = reinterpret_cast(data)->second; + if (accu < maxLine) { accu += printSep(cat_value); } + else if (!maxLine) { maxLine = s.first || *fieldSeparator() != ' ' ? UINT32_MAX : 70; } + else { printf("\n%s", format[cat_value]); accu = 0; } + if (s.first){ accu += printf(format[cat_atom_name], s.first); } + else { accu += printf(format[cat_atom_var] + !s.second.sign(), static_cast(s.second.var())); } + return data; +} +void TextOutput::printValues(const OutputTable& out, const Model& m) { + printf("%s", format[cat_value]); + UPair data; + printWitness(out, m, reinterpret_cast(&data)); + if (*format[cat_value_term]) { + printSep(cat_value); + printf("%s", format[cat_value_term]); + } + printf("\n"); +} +void TextOutput::printMeta(const OutputTable& out, const Model& m) { + if (m.consequences()) { + UPair cons = numCons(out, m); + printLN(cat_comment, "Consequences: [%u;%u]", cons.first, cons.first + cons.second); + } + if (m.costs) { + printf("%s", format[cat_objective]); + printCosts(*m.costs); + printf("\n"); + } +} +void TextOutput::printModel(const OutputTable& out, const Model& m, PrintLevel x) { + if (x == modelQ()) { + comment(1, "%s: %" PRIu64"\n", !m.up ? "Answer" : "Update", m.num); + printValues(out, m); + } + if (x == optQ()) { + printMeta(out, m); + } + fflush(stdout); +} +void TextOutput::printUnsat(const OutputTable& out, const LowerBound* lower, const Model* prevModel) { + if (lower && optQ() == print_all) { + const SumVec* costs = prevModel ? prevModel->costs : 0; + printf("%s%-12s: ", format[cat_comment], "Progression"); + if (costs && costs->size() > lower->level) { + const char* next = *fieldSeparator() != '\n' ? "" : format[cat_comment]; + for (uint32 i = 0; i != lower->level; ++i) { + printf("%" PRId64 "%s%s", (*costs)[i], fieldSeparator(), next); + } + wsum_t ub = (*costs)[lower->level]; + int w = 1; for (wsum_t x = ub; x > 9; ++w) { x /= 10; } + printf("[%*" PRId64 ";%" PRId64 "] (Error: %g)", w, lower->bound, ub, double(ub - lower->bound)/double(lower->bound)); + } + else { + printf("[%" PRId64 ";inf]", lower->bound); + } + printf("\n"); + } + if (prevModel && prevModel->up && optQ() == print_all) { + printMeta(out, *prevModel); + } + fflush(stdout); +} + +void TextOutput::printBounds(const SumVec& lower, const SumVec& upper) const { + for (uint32 i = 0, uMax = upper.size(), lMax = lower.size(), end = std::max(uMax, lMax), seps = end; i != end; ++i) { + if (i >= uMax) { + printf("[%" PRId64";*]", lower[i]); + } + else if (i >= lMax || lower[i] == upper[i]) { + printf("%" PRId64, upper[i]); + } + else { + printf("[%" PRId64";%" PRId64"]", lower[i], upper[i]); + } + if (--seps) { printSep(cat_objective); } + } +} + +void TextOutput::printCosts(const SumVec& costs) const { + if (!costs.empty()) { + printf("%" PRId64, costs[0]); + for (uint32 i = 1, end = (uint32)costs.size(); i != end; ++i) { + printSep(cat_objective); + printf("%" PRId64, costs[i]); + } + } +} +bool TextOutput::startSection(const char* n) const { + printLN(cat_comment, "============ %s Stats ============", n); + printBR(cat_comment); + return true; +} +void TextOutput::startObject(const char* n, uint32 i) const { + printLN(cat_comment, "[%s %u]", n, i); + printBR(cat_comment); +} +bool TextOutput::visitThreads(Operation op) { + accu_ = false; + return op != Enter || startSection("Thread"); +} +bool TextOutput::visitTester(Operation op) { + accu_ = false; + return op != Enter || startSection("Tester"); +} +void TextOutput::visitThread(uint32 i, const SolverStats& stats) { + startObject("Thread", i); + TextOutput::visitSolverStats(stats); +} +void TextOutput::visitHcc(uint32 i, const ProblemStats& p, const SolverStats& s) { + startObject("HCC", i); + TextOutput::visitProblemStats(p); + TextOutput::visitSolverStats(s); +} +void TextOutput::visitLogicProgramStats(const Asp::LpStats& lp) { + using namespace Asp; + uint32 rFinal = lp.rules[1].sum(), rOriginal = lp.rules[0].sum(); + printKeyValue("Rules", "%-8u", rFinal); + if (rFinal != rOriginal) { + printf(" (Original: %u)", rOriginal); + } + printf("\n"); + char buf[80]; + for (uint32 i = 0; i != RuleStats::numKeys(); ++i) { + if (i == RuleStats::Normal) { continue; } + if (uint32 r = lp.rules[0][i]) { + printKeyValue(clasp_format(buf, 80, " %s", RuleStats::toStr(i)), "%-8u", lp.rules[1][i]); + if (r != lp.rules[1][i]) { printf(" (Original: %u)", r); } + printf("\n"); + } + } + printKeyValue("Atoms", "%-8u", lp.atoms); + if (lp.auxAtoms) { + printf(" (Original: %u Auxiliary: %u)", lp.atoms-lp.auxAtoms, lp.auxAtoms); + } + printf("\n"); + if (lp.disjunctions[0]) { + printKeyValue("Disjunctions", "%-8u", lp.disjunctions[1]); + printf(" (Original: %u)\n", lp.disjunctions[0]); + } + uint32 bFinal = lp.bodies[1].sum(), bOriginal = lp.bodies[0].sum(); + printKeyValue("Bodies", "%-8u", bFinal); + if (bFinal != bOriginal) { + printf(" (Original: %u)", bOriginal); + } + printf("\n"); + for (uint32 i = 1; i != BodyStats::numKeys(); ++i) { + if (uint32 b = lp.bodies[0][i]) { + printKeyValue(clasp_format(buf, 80, " %s", BodyStats::toStr(i)), "%-8u", lp.bodies[1][i]); + if (b != lp.bodies[1][i]) { printf(" (Original: %u)", b); } + printf("\n"); + } + } + if (lp.eqs() > 0) { + printKeyValue("Equivalences", "%-8u", lp.eqs()); + printf(" (Atom=Atom: %u Body=Body: %u Other: %u)\n" + , lp.eqs(Var_t::Atom) + , lp.eqs(Var_t::Body) + , lp.eqs(Var_t::Hybrid)); + } + printKey("Tight"); + if (lp.sccs == 0) { printf("Yes"); } + else if (lp.sccs != PrgNode::noScc) { printf("%-8s (SCCs: %u Non-Hcfs: %u Nodes: %u Gammas: %u)", "No", lp.sccs, lp.nonHcfs, lp.ufsNodes, lp.gammas); } + else { printf("N/A"); } + printf("\n"); +} +void TextOutput::visitProblemStats(const ProblemStats& ps) { + uint32 sum = ps.numConstraints(); + printKeyValue("Variables", "%-8u", ps.vars.num); + printf(" (Eliminated: %4u Frozen: %4u)\n", ps.vars.eliminated, ps.vars.frozen); + printKeyValue("Constraints", "%-8u", sum); + printf(" (Binary: %5.1f%% Ternary: %5.1f%% Other: %5.1f%%)\n" + , percent(ps.constraints.binary, sum) + , percent(ps.constraints.ternary, sum) + , percent(ps.constraints.other, sum)); + if (ps.acycEdges) { + printKeyValue("Acyc-Edges", "%-8u\n", ps.acycEdges); + } + printBR(cat_comment); +} +void TextOutput::visitSolverStats(const Clasp::SolverStats& st) { + printStats(st); + printBR(cat_comment); +} +void TextOutput::printStats(const Clasp::SolverStats& st) const { + if (!accu_ && st.extra) { + printKeyValue("CPU Time", "%.3fs\n", st.extra->cpuTime); + printKeyValue("Models", "%" PRIu64"\n", st.extra->models); + } + printKeyValue("Choices", "%-8" PRIu64, st.choices); + if (st.extra && st.extra->domChoices) { printf(" (Domain: %" PRIu64")", st.extra->domChoices); } + printf("\n"); + printKeyValue("Conflicts", "%-8" PRIu64"", st.conflicts); + printf(" (Analyzed: %" PRIu64")\n", st.backjumps()); + printKeyValue("Restarts", "%-8" PRIu64"", st.restarts); + if (st.restarts) { + printf(" (Average: %.2f Last: %" PRIu64")", st.avgRestart(), st.lastRestart); + } + printf("\n"); + if (!st.extra) return; + const ExtendedStats& stx = *st.extra; + if (stx.hccTests) { + printKeyValue("Stab. Tests", "%-8" PRIu64, stx.hccTests); + printf(" (Full: %" PRIu64" Partial: %" PRIu64")\n", stx.hccTests - stx.hccPartial, stx.hccPartial); + } + if (stx.models) { + printKeyValue("Model-Level", "%-8.1f\n", stx.avgModel()); + } + printKeyValue("Problems", "%-8" PRIu64, (uint64)stx.gps); + printf(" (Average Length: %.2f Splits: %" PRIu64")\n", stx.avgGp(), (uint64)stx.splits); + uint64 sum = stx.lemmas(); + printKeyValue("Lemmas", "%-8" PRIu64, sum); + printf(" (Deleted: %" PRIu64")\n", stx.deleted); + printKeyValue(" Binary", "%-8" PRIu64, uint64(stx.binary)); + printf(" (Ratio: %6.2f%%)\n", percent(stx.binary, sum)); + printKeyValue(" Ternary", "%-8" PRIu64, uint64(stx.ternary)); + printf(" (Ratio: %6.2f%%)\n", percent(stx.ternary, sum)); + const char* names[] = {" Conflict", " Loop", " Other"}; + for (int i = 0; i != sizeof(names)/sizeof(names[0]); ++i) { + ConstraintType type = static_cast(i+1); + printKeyValue(names[i], "%-8" PRIu64, stx.lemmas(type)); + printf(" (Average Length: %6.1f Ratio: %6.2f%%) \n", stx.avgLen(type), percent(stx.lemmas(type), sum)); + } + if (stx.distributed || stx.integrated) { + printKeyValue(" Distributed", "%-8" PRIu64, stx.distributed); + printf(" (Ratio: %6.2f%% Average LBD: %.2f) \n", stx.distRatio()*100.0, stx.avgDistLbd()); + printKeyValue(" Integrated", "%-8" PRIu64, stx.integrated); + if (accu_) { printf(" (Ratio: %6.2f%% ", stx.intRatio()*100.0); } + else { printf(" ("); } + printf("Unit: %" PRIu64" Average Jumps: %.2f)\n", stx.intImps, stx.avgIntJump()); + } + printJumps(stx.jumps); +} +void TextOutput::printJumps(const JumpStats& st) const { + printKeyValue("Backjumps", "%-8" PRIu64, st.jumps); + printf(" (Average: %5.2f Max: %3u Sum: %6" PRIu64")\n", st.avgJump(), st.maxJump, st.jumpSum); + printKeyValue(" Executed", "%-8" PRIu64, st.jumps-st.bounded); + printf(" (Average: %5.2f Max: %3u Sum: %6" PRIu64" Ratio: %6.2f%%)\n", st.avgJumpEx(), st.maxJumpEx, st.jumped(), st.jumpedRatio()*100.0); + printKeyValue(" Bounded", "%-8" PRIu64, st.bounded); + printf(" (Average: %5.2f Max: %3u Sum: %6" PRIu64" Ratio: %6.2f%%)\n", st.avgBound(), st.maxBound, st.boundSum, 100.0 - (st.jumpedRatio()*100.0)); +} + +#undef printKeyValue +#undef printKey +#undef printLN +#undef printBR +}} diff --git a/libclasp/src/clause.cpp b/libclasp/src/clause.cpp new file mode 100644 index 0000000..ad32f4e --- /dev/null +++ b/libclasp/src/clause.cpp @@ -0,0 +1,1073 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include + +namespace Clasp { namespace Detail { +struct GreaterLevel { + GreaterLevel(const Solver& s) : solver_(s) {} + bool operator()(const Literal& p1, const Literal& p2) const { + assert(solver_.value(p1.var()) != value_free && solver_.value(p2.var()) != value_free); + return solver_.level(p1.var()) > solver_.level(p2.var()); + } +private: + GreaterLevel& operator=(const GreaterLevel&); + const Solver& solver_; +}; + +struct Sink { + explicit Sink(SharedLiterals* c) : clause(c) {} + ~Sink() { if (clause) clause->release(); } + SharedLiterals* clause; +}; + +void* alloc(uint32 size) { + CLASP_PRAGMA_TODO("replace with CACHE_LINE_ALIGNED alloc") + return ::operator new(size); +} +void free(void* mem) { + ::operator delete(mem); +} + +} // namespace Detail + +///////////////////////////////////////////////////////////////////////////////////////// +// SharedLiterals +///////////////////////////////////////////////////////////////////////////////////////// +SharedLiterals* SharedLiterals::newShareable(const Literal* lits, uint32 size, ConstraintType t, uint32 numRefs) { + void* m = Detail::alloc(sizeof(SharedLiterals)+(size*sizeof(Literal))); + return new (m) SharedLiterals(lits, size, t, numRefs); +} + +SharedLiterals::SharedLiterals(const Literal* a_lits, uint32 size, ConstraintType t, uint32 refs) + : size_type_( (size << 2) + t ) { + refCount_ = std::max(uint32(1),refs); + std::memcpy(lits_, a_lits, size*sizeof(Literal)); +} + +uint32 SharedLiterals::simplify(Solver& s) { + bool removeFalse = unique(); + uint32 newSize = 0; + Literal* r = lits_; + Literal* e = lits_+size(); + ValueRep v; + for (Literal* c = r; r != e; ++r) { + if ( (v = s.value(r->var())) == value_free ) { + if (c != r) *c = *r; + ++c; ++newSize; + } + else if (v == trueValue(*r)) { + newSize = 0; break; + } + else if (!removeFalse) ++c; + } + if (removeFalse && newSize != size()) { + size_type_ = (newSize << 2) | (size_type_ & uint32(3)); + } + return newSize; +} + +void SharedLiterals::release(uint32 n) { + if ((refCount_ -= n) == 0) { + this->~SharedLiterals(); + Detail::free(this); + } +} +SharedLiterals* SharedLiterals::share() { + ++refCount_; + return this; +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClauseCreator +///////////////////////////////////////////////////////////////////////////////////////// +ClauseCreator::ClauseCreator(Solver* s) + : solver_(s) + , flags_(0){ +} + +ClauseCreator& ClauseCreator::start(ConstraintType t) { + assert(solver_ && (solver_->decisionLevel() == 0 || t != Constraint_t::Static)); + literals_.clear(); + extra_ = ConstraintInfo(t); + return *this; +} + +uint32 ClauseCreator::watchOrder(const Solver& s, Literal p) { + ValueRep value_p = s.value(p.var()); + // DL+1, if isFree(p) + // DL(p), if isFalse(p) + // ~DL(p),if isTrue(p) + uint32 abstr_p = value_p == value_free ? s.decisionLevel()+1 : s.level(p.var()) ^ -(value_p==trueValue(p)); + assert(abstr_p > 0 || (s.isFalse(p) && s.level(p.var()) == 0)); + return abstr_p; +} + +ClauseRep ClauseCreator::prepare(Solver& s, const Literal* in, uint32 inSize, const ConstraintInfo& e, uint32 flags, Literal* out, uint32 outMax) { + assert(out && outMax > 2); + ClauseRep ret = ClauseRep::prepared(out, 0, e); + uint32 abst_w1 = 0, abst_w2 = 0; + bool simplify = ((flags & clause_force_simplify) != 0) && inSize > 2 && outMax >= inSize; + Literal tag = ~s.tagLiteral(); + Var vMax = 0; + for (uint32 i = 0, j = 0, MAX_OUT = outMax - 1; i != inSize; ++i) { + Literal p = in[i]; + uint32 abst_p = watchOrder(s, p); + if ((abst_p + 1) > 1 && (!simplify || !s.seen(p.var()))) { + out[j] = p; + if (p == tag) { ret.info.setTagged(true); } + if (p.var() > vMax) { vMax = p.var();} + if (simplify) { s.markSeen(p); } + if (abst_p > abst_w1) { std::swap(abst_p, abst_w1); std::swap(out[0], out[j]); } + if (abst_p > abst_w2) { std::swap(abst_p, abst_w2); std::swap(out[1], out[j]); } + if (j != MAX_OUT) { ++j; } + ++ret.size; + } + else if (abst_p == UINT32_MAX || (simplify && abst_p && s.seen(~p))) { + abst_w1 = UINT32_MAX; + break; + } + } + if (simplify) { + for (uint32 x = 0, end = ret.size; x != end; ++x) { s.clearSeen(out[x].var()); } + } + if (abst_w1 == UINT32_MAX || (abst_w2 && out[0].var() == out[1].var())) { + out[0] = abst_w1 == UINT32_MAX || out[0] == ~out[1] ? lit_true() : out[0]; + ret.size = 1; + } + ret.info.setAux(s.auxVar(vMax)); + return ret; +} + + +ClauseRep ClauseCreator::prepare(Solver& s, LitVec& lits, uint32 flags, const ConstraintInfo& info) { + if (lits.empty()) { lits.push_back(lit_false()); } + if ((flags & clause_no_prepare) == 0 || (flags & clause_force_simplify) != 0) { + ClauseRep x = prepare(s, &lits[0], (uint32)lits.size(), info, flags, &lits[0]); + shrinkVecTo(lits, x.size); + return x; + } + return ClauseRep::prepared(&lits[0], (uint32)lits.size(), info); +} + +ClauseRep ClauseCreator::prepare(bool forceSimplify) { + return prepare(*solver_, literals_, forceSimplify ? clause_force_simplify : 0, extra_); +} + +ClauseCreator::Status ClauseCreator::status(const Solver& s, const Literal* clause_begin, const Literal* clause_end) { + if (clause_end <= clause_begin) { return status_empty; } + Literal temp[3]; + ClauseRep x = prepare(const_cast(s), clause_begin, uint32(clause_end - clause_begin), ConstraintInfo(), 0, temp, 3); + return status(s, x); +} + +ClauseCreator::Status ClauseCreator::status(const Solver& s, const ClauseRep& c) { + uint32 dl = s.decisionLevel(); + uint32 fw = c.size ? watchOrder(s, c.lits[0]) : 0; + if (fw == UINT32_MAX) { return status_subsumed; } + uint32 sw = c.size > 1 ? watchOrder(s, c.lits[1]) : 0; + uint32 st = status_open; + if (fw > varMax) { st|= status_sat; fw = ~fw; } + else if (fw <= dl) { st|= (fw ? status_unsat : status_empty); } + if (sw <= dl && fw > sw){ st|= status_unit; } + return static_cast(st); +} + +bool ClauseCreator::ignoreClause(const Solver& s, const ClauseRep& c, Status st, uint32 flags) { + uint32 x = (st & (status_sat|status_unsat)); + if (x == status_open) { return false; } + if (x == status_unsat) { return st != status_empty && (flags & clause_not_conflict) != 0; } + return st == status_subsumed || (st == status_sat && ( (flags & clause_not_sat) != 0 || ((flags & clause_not_root_sat) != 0 && s.level(c.lits[0].var()) <= s.rootLevel()))); +} + +ClauseCreator::Result ClauseCreator::end(uint32 flags) { + assert(solver_); + flags |= flags_; + return ClauseCreator::create_prepared(*solver_, prepare(*solver_, literals_, flags, extra_), flags); +} + +ClauseHead* ClauseCreator::newProblemClause(Solver& s, const ClauseRep& clause, uint32 flags) { + ClauseHead* ret; + Solver::WatchInitMode wMode = s.watchInitMode(); + if (flags&clause_watch_first){ wMode = SolverStrategies::watch_first;} + else if (flags&clause_watch_rand) { wMode = SolverStrategies::watch_rand; } + else if (flags&clause_watch_least){ wMode = SolverStrategies::watch_least;} + if (clause.size > 2 && wMode != SolverStrategies::watch_first) { + uint32 fw = 0, sw = 1; + if (wMode == SolverStrategies::watch_rand) { + fw = s.rng.irand(clause.size); + do { sw = s.rng.irand(clause.size); } while (sw == fw); + } + else if (wMode == SolverStrategies::watch_least) { + uint32 cw1 = s.numWatches(~clause.lits[0]); + uint32 cw2 = s.numWatches(~clause.lits[1]); + if (cw1 > cw2) { std::swap(fw, sw); std::swap(cw1, cw2); } + for (uint32 i = 2; i != clause.size && cw2; ++i) { + uint32 p = i; + uint32 cwp = s.numWatches(~clause.lits[i]); + if (cwp < cw1) { std::swap(cwp, cw1); std::swap(fw, p); } + if (cwp < cw2) { std::swap(cwp, cw2); std::swap(sw, p); } + } + } + std::swap(clause.lits[0], clause.lits[fw]); + std::swap(clause.lits[1], clause.lits[sw]); + } + if (clause.size <= Clause::MAX_SHORT_LEN || !s.sharedContext()->physicalShareProblem()) { + ret = Clause::newClause(s, clause); + } + else { + ret = Clause::newShared(s, SharedLiterals::newShareable(clause.lits, clause.size, clause.info.type(), 1), clause.info, clause.lits, false); + } + if ( (flags & clause_no_add) == 0 ) { + assert(!clause.info.aux()); + s.add(ret); + } + return ret; +} + +ClauseHead* ClauseCreator::newLearntClause(Solver& s, const ClauseRep& clause, uint32 flags) { + ClauseHead* ret; + Detail::Sink sharedPtr(0); + sharedPtr.clause = s.distribute(clause.lits, clause.size, clause.info); + if (clause.size <= Clause::MAX_SHORT_LEN || sharedPtr.clause == 0) { + if (!s.isFalse(clause.lits[1]) || clause.size < s.compressLimit()) { + ret = Clause::newClause(s, clause); + } + else { + ret = Clause::newContractedClause(s, clause, 2, true); + } + } + else { + ret = Clause::newShared(s, sharedPtr.clause, clause.info, clause.lits, false); + sharedPtr.clause = 0; + } + if ( (flags & clause_no_add) == 0 ) { + s.addLearnt(ret, clause.size, clause.info.type()); + } + return ret; +} + +ClauseHead* ClauseCreator::newUnshared(Solver& s, SharedLiterals* clause, const Literal* w, const ConstraintInfo& e) { + LitVec temp; temp.reserve(clause->size()); + temp.assign(w, w+2); + for (const Literal* x = clause->begin(), *end = clause->end(); x != end; ++x) { + if (watchOrder(s, *x) > 0 && *x != temp[0] && *x != temp[1]) { + temp.push_back(*x); + } + } + return Clause::newClause(s, ClauseRep::prepared(&temp[0], (uint32)temp.size(), e)); +} + +ClauseCreator::Result ClauseCreator::create_prepared(Solver& s, const ClauseRep& clause, uint32 flags) { + assert(s.decisionLevel() == 0 || (clause.info.learnt() && clause.prep)); + Status x = status(s, clause); + if (ignoreClause(s, clause, x, flags)){ + return Result(0, x); + } + if (clause.size > 1) { + Result ret(0, x); + if (!clause.info.learnt() && s.satPrepro() && !s.sharedContext()->frozen()) { + return Result(0, s.satPrepro()->addClause(clause.lits, clause.size) ? x : status_unsat); + } + if ((flags & clause_no_heuristic) == 0) { s.heuristic()->newConstraint(s, clause.lits, clause.size, clause.info.type()); } + if (clause.size > 3 || (flags&clause_explicit) != 0 || !s.allowImplicit(clause)) { + ret.local = clause.info.learnt() ? newLearntClause(s, clause, flags) : newProblemClause(s, clause, flags); + } + else { + // add implicit short rep + s.add(clause); + } + if ((x & (status_unit|status_unsat)) != 0) { + Antecedent ante(ret.local); + if (!ret.local){ ante = clause.size == 3 ? Antecedent(~clause.lits[1], ~clause.lits[2]) : Antecedent(~clause.lits[1]); } + ret.status = s.force(clause.lits[0], s.level(clause.lits[1].var()), ante) ? status_unit : status_unsat; + } + return ret; + } + s.add(clause); + return Result(0, !s.hasConflict() ? status_unit : status_unsat); +} + +ClauseCreator::Result ClauseCreator::create(Solver& s, LitVec& lits, uint32 flags, const ConstraintInfo& extra) { + return create_prepared(s, prepare(s, lits, flags, extra), flags); +} + +ClauseCreator::Result ClauseCreator::create(Solver& s, const ClauseRep& rep, uint32 flags) { + return create_prepared(s, (rep.prep == 0 && (flags & clause_no_prepare) == 0 + ? prepare(s, rep.lits, rep.size, rep.info, flags, rep.lits) + : ClauseRep::prepared(rep.lits, rep.size, rep.info)), flags); +} + +ClauseCreator::Result ClauseCreator::integrate(Solver& s, SharedLiterals* clause, uint32 modeFlags, ConstraintType t) { + assert(!s.hasConflict() && "ClauseCreator::integrate() - precondition violated!"); + Detail::Sink shared( (modeFlags & clause_no_release) == 0 ? clause : 0); + // determine state of clause + Literal temp[Clause::MAX_SHORT_LEN]; temp[0] = temp[1] = lit_false(); + ClauseRep x = prepare(s, clause->begin(), clause->size(), ConstraintInfo(t), 0, temp, Clause::MAX_SHORT_LEN); + uint32 impSize = (modeFlags & clause_explicit) != 0 || !s.allowImplicit(x) ? 1 : 3; + Status xs = status(s, x); + if (ignoreClause(s, x, xs, modeFlags)) { + return Result(0, xs); + } + Result result(0, xs); + if ((modeFlags & clause_no_heuristic) == 0) { s.heuristic()->newConstraint(s, clause->begin(), clause->size(), t); } + if (x.size > Clause::MAX_SHORT_LEN && s.sharedContext()->physicalShare(t)) { + result.local = Clause::newShared(s, clause, x.info, temp, shared.clause == 0); + shared.clause = 0; + } + else if (x.size > impSize) { + result.local = x.size <= Clause::MAX_SHORT_LEN ? Clause::newClause(s, x) : newUnshared(s, clause, temp, x.info); + } + else { + // unary clause or implicitly shared via binary/ternary implication graph; + // only check for implication/conflict but do not create + // a local representation for the clause + s.stats.addLearnt(x.size, x.info.type()); + modeFlags |= clause_no_add; + } + if ((modeFlags & clause_no_add) == 0) { s.addLearnt(result.local, x.size, x.info.type()); } + if ((xs & (status_unit|status_unsat)) != 0) { + Antecedent ante = result.local ? Antecedent(result.local) : Antecedent(~temp[1], ~temp[2]); + uint32 impLevel = s.level(temp[1].var()); + result.status = s.force(temp[0], impLevel, ante) ? status_unit : status_unsat; + if (result.local && (modeFlags & clause_int_lbd) != 0) { + uint32 lbd = s.countLevels(clause->begin(), clause->end()); + result.local->resetScore(makeScore(x.info.activity(), lbd)); + } + } + return result; +} +ClauseCreator::Result ClauseCreator::integrate(Solver& s, SharedLiterals* clause, uint32 modeFlags) { + return integrate(s, clause, modeFlags, clause->type()); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Clause +///////////////////////////////////////////////////////////////////////////////////////// +void* Clause::alloc(Solver& s, uint32 lits, bool learnt) { + if (lits <= Clause::MAX_SHORT_LEN) { + if (learnt) { s.addLearntBytes(32); } + return s.allocSmall(); + } + uint32 extra = std::max((uint32)ClauseHead::HEAD_LITS, lits) - ClauseHead::HEAD_LITS; + uint32 bytes = sizeof(Clause) + (extra)*sizeof(Literal); + if (learnt) { s.addLearntBytes(bytes); } + return Detail::alloc(bytes); +} + +ClauseHead* Clause::newClause(void* mem, Solver& s, const ClauseRep& rep) { + assert(rep.size >= 2 && mem); + return new (mem) Clause(s, rep); +} + +ClauseHead* Clause::newShared(Solver& s, SharedLiterals* shared_lits, const InfoType& e, const Literal* lits, bool addRef) { + return mt::SharedLitsClause::newClause(s, shared_lits, e, lits, addRef); +} + +ClauseHead* Clause::newContractedClause(Solver& s, const ClauseRep& rep, uint32 tailStart, bool extend) { + assert(rep.size >= 2); + if (extend) { std::stable_sort(rep.lits+tailStart, rep.lits+rep.size, Detail::GreaterLevel(s)); } + return new (alloc(s, rep.size, rep.info.learnt())) Clause(s, rep, tailStart, extend); +} +void ClauseHead::Local::init(uint32 sz) { + std::memset(mem, 0, sizeof(mem)); + if (sz > ClauseHead::MAX_SHORT_LEN) { mem[0] = (sz << 3) + 1; } + assert(isSmall() == (sz <= ClauseHead::MAX_SHORT_LEN)); +} +Clause::Clause(Solver& s, const ClauseRep& rep, uint32 tail, bool extend) + : ClauseHead(rep.info) { + assert(tail >= rep.size || s.isFalse(rep.lits[tail])); + local_.init(rep.size); + if (!isSmall()) { + // copy literals + std::memcpy(head_, rep.lits, rep.size*sizeof(Literal)); + tail = std::max(tail, (uint32)ClauseHead::HEAD_LITS); + if (tail < rep.size) { // contracted clause + head_[rep.size-1].flag(); // mark last literal of clause + Literal t = head_[tail]; + if (s.level(t.var()) > 0) { + local_.markContracted(); + if (extend) { + s.addUndoWatch(s.level(t.var()), this); + } + } + local_.setSize(tail); + } + } + else { + std::memcpy(head_, rep.lits, std::min(rep.size, (uint32)ClauseHead::HEAD_LITS)*sizeof(Literal)); + small()[0] = rep.size > ClauseHead::HEAD_LITS ? rep.lits[ClauseHead::HEAD_LITS] : lit_false(); + small()[1] = rep.size > ClauseHead::HEAD_LITS+1 ? rep.lits[ClauseHead::HEAD_LITS+1] : lit_false(); + assert(isSmall() && Clause::size() == rep.size); + } + attach(s); +} + +Clause::Clause(Solver& s, const Clause& other) : ClauseHead(other.info_) { + uint32 oSize = other.size(); + local_.init(oSize); + if (!isSmall()) { std::memcpy(head_, other.head_, oSize*sizeof(Literal)); } + else if (other.isSmall()) { std::memcpy(&local_, &other.local_, (ClauseHead::MAX_SHORT_LEN+1)*sizeof(Literal)); } + else { // this is small, other is not + std::memcpy(head_, other.head_, ClauseHead::HEAD_LITS*sizeof(Literal)); + std::memcpy(&local_, other.head_+ClauseHead::HEAD_LITS, 2*sizeof(Literal)); + } + attach(s); +} + +Constraint* Clause::cloneAttach(Solver& other) { + assert(!learnt()); + return new (alloc(other, Clause::size(), false)) Clause(other, *this); +} +Literal* Clause::small() { return static_cast(static_cast(&local_)); } +bool Clause::contracted() const { return local_.contracted(); } +bool Clause::isSmall() const { return local_.isSmall(); } +bool Clause::strengthened() const { return local_.strengthened(); } +void Clause::destroy(Solver* s, bool detachFirst) { + if (s) { + if (detachFirst) { Clause::detach(*s); } + if (learnt()) { s->freeLearntBytes(computeAllocSize()); } + } + void* mem = static_cast(this); + bool small = isSmall(); + this->~Clause(); + if (!small) { Detail::free(mem); } + else if (s) { s->freeSmall(mem); } +} + +void Clause::detach(Solver& s) { + if (contracted()) { + Literal* eoc = end(); + if (s.isFalse(*eoc) && s.level(eoc->var()) != 0) { + s.removeUndoWatch(s.level(eoc->var()), this); + } + } + ClauseHead::detach(s); +} + +uint32 Clause::computeAllocSize() const { + if (isSmall()) { return 32; } + uint32 rt = sizeof(Clause) - (ClauseHead::HEAD_LITS*sizeof(Literal)); + uint32 sz = local_.size(); + uint32 nw = contracted() + strengthened(); + if (nw != 0u) { + const Literal* eoc = head_ + sz; + do { nw -= eoc++->flagged(); } while (nw); + sz = static_cast(eoc - head_); + } + return rt + (sz*sizeof(Literal)); +} + +bool Clause::updateWatch(Solver& s, uint32 pos) { + Literal* it; + if (!isSmall()) { + for (Literal* begin = head_ + ClauseHead::HEAD_LITS, *end = this->end(), *first = begin + local_.mem[1];;) { + for (it = first; it < end; ++it) { + if (!s.isFalse(*it)) { + std::swap(*it, head_[pos]); + local_.mem[1] = static_cast(++it - begin); + return true; + } + } + if (first == begin) { break; } + end = first; + first = begin; + } + } + else if (!s.isFalse(*(it = this->small())) || !s.isFalse(*++it)) { + std::swap(head_[pos], *it); + return true; + } + return false; +} +Clause::LitRange Clause::tail() { + if (!isSmall()) { return LitRange(head_+ClauseHead::HEAD_LITS, end()); } + Literal* tBeg = small(), *tEnd = tBeg; + if (*tEnd != lit_false()) ++tEnd; + if (*tEnd != lit_false()) ++tEnd; + return LitRange(tBeg, tEnd); +} +void Clause::reason(Solver& s, Literal p, LitVec& out) { + out.push_back(~head_[p == head_[0]]); + if (!isSentinel(head_[2])) { + out.push_back(~head_[2]); + LitRange t = tail(); + for (const Literal* r = t.first; r != t.second; ++r) { + out.push_back(~*r); + } + if (contracted()) { + const Literal* r = t.second; + do { out.push_back(~*r); } while (!r++->flagged()); + } + } + if (learnt()) { + s.updateOnReason(info_.score(), p, out); + } +} + +bool Clause::minimize(Solver& s, Literal p, CCMinRecursive* rec) { + s.updateOnMinimize(info_.score()); + uint32 other = p == head_[0]; + if (!s.ccMinimize(~head_[other], rec) || !s.ccMinimize(~head_[2], rec)) { return false; } + LitRange t = tail(); + for (const Literal* r = t.first; r != t.second; ++r) { + if (!s.ccMinimize(~*r, rec)) { return false; } + } + if (contracted()) { + do { + if (!s.ccMinimize(~*t.second, rec)) { return false; } + } while (!t.second++->flagged()); + } + return true; +} + +bool Clause::isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN) { + uint32 other = p == head_[0]; + if (!isRevLit(s, head_[other], maxL) || !isRevLit(s, head_[2], maxL)) { return false; } + uint32 notSeen = !s.seen(head_[other].var()) + !s.seen(head_[2].var()); + LitRange t = tail(); + for (const Literal* r = t.first; r != t.second && notSeen <= maxN; ++r) { + if (!isRevLit(s, *r, maxL)) { return false; } + notSeen += !s.seen(r->var()); + } + if (contracted()) { + const Literal* r = t.second; + do { notSeen += !s.seen(r->var()); } while (notSeen <= maxN && !r++->flagged()); + } + return notSeen <= maxN; +} + +bool Clause::simplify(Solver& s, bool reinit) { + assert(s.decisionLevel() == 0 && s.queueSize() == 0); + if (ClauseHead::satisfied(s)) { + detach(s); + return true; + } + LitRange t = tail(); + Literal* it= t.first - !isSmall(), *j; + // skip free literals + while (it != t.second && s.value(it->var()) == value_free) { ++it; } + // copy remaining free literals + for (j = it; it != t.second; ++it) { + if (s.value(it->var()) == value_free) { *j++ = *it; } + else if (s.isTrue(*it)) { Clause::detach(s); return true;} + } + // replace any false lits with sentinels + for (Literal* r = j; r != t.second; ++r) { *r = lit_false(); } + if (!isSmall()) { + uint32 size = std::max((uint32)ClauseHead::HEAD_LITS, static_cast(j-head_)); + local_.setSize(size); + local_.clearIdx(); + if (j != t.second && learnt() && !strengthened()) { + // mark last literal so that we can recompute alloc size later + t.second[-1].flag(); + local_.markStrengthened(); + } + if (reinit && size > 3) { + detach(s); + std::random_shuffle(head_, j, s.rng); + attach(s); + } + } + else if (s.isFalse(head_[2])) { + head_[2] = t.first[0]; + t.first[0] = t.first[1]; + t.first[1] = lit_false(); + --j; + } + return j <= t.first && ClauseHead::toImplication(s); +} + +uint32 Clause::isOpen(const Solver& s, const TypeSet& x, LitVec& freeLits) { + if (!x.inSet(ClauseHead::type()) || ClauseHead::satisfied(s)) { + return 0; + } + assert(s.queueSize() == 0 && "Watches might be false!"); + freeLits.push_back(head_[0]); + freeLits.push_back(head_[1]); + if (!s.isFalse(head_[2])) freeLits.push_back(head_[2]); + ValueRep v; + LitRange t = tail(); + for (Literal* r = t.first; r != t.second; ++r) { + if ( (v = s.value(r->var())) == value_free) { + freeLits.push_back(*r); + } + else if (v == trueValue(*r)) { + std::swap(head_[2], *r); + return 0; + } + } + return ClauseHead::type(); +} + +void Clause::undoLevel(Solver& s) { + assert(!isSmall()); + uint32 t = local_.size(); + uint32 ul = s.jumpLevel(); + Literal* r = head_+t; + while (!r->flagged() && (s.value(r->var()) == value_free || s.level(r->var()) > ul)) { + ++t; + ++r; + } + if (r->flagged() || s.level(r->var()) == 0) { + r->unflag(); + t += !isSentinel(*r); + local_.clearContracted(); + } + else { + s.addUndoWatch(s.level(r->var()), this); + } + local_.setSize(t); +} + +void Clause::toLits(LitVec& out) const { + out.insert(out.end(), head_, (head_+ClauseHead::HEAD_LITS)-isSentinel(head_[2])); + LitRange t = const_cast(*this).tail(); + if (contracted()) { while (!t.second++->flagged()) {;} } + out.insert(out.end(), t.first, t.second); +} + +ClauseHead::BoolPair Clause::strengthen(Solver& s, Literal p, bool toShort) { + LitRange t = tail(); + Literal* eoh= head_+ClauseHead::HEAD_LITS; + Literal* eot= t.second; + Literal* it = std::find(head_, eoh, p); + BoolPair ret(false, false); + if (it != eoh) { + if (it != head_+2) { // update watch + *it = head_[2]; + s.removeWatch(~p, this); + Literal* best = it, *n; + for (n = t.first; n != eot && s.isFalse(*best); ++n) { + if (!s.isFalse(*n) || s.level(n->var()) > s.level(best->var())) { + best = n; + } + } + std::swap(*it, *best); + s.addWatch(~*it, ClauseWatch(this)); + it = head_+2; + } + // replace cache literal with literal from tail + if ((*it = *t.first) != lit_false()) { + eot = removeFromTail(s, t.first, eot); + } + ret.first = true; + } + else if ((it = std::find(t.first, eot, p)) != eot) { + eot = removeFromTail(s, it, eot); + ret.first = true; + } + else if (contracted()) { + for (; *it != p && !it->flagged(); ++it) { ; } + ret.first = *it == p; + eot = *it == p ? removeFromTail(s, it, eot) : it + 1; + } + if (ret.first && ~p == s.tagLiteral()) { + clearTagged(); + } + ret.second = toShort && eot == t.first && toImplication(s); + return ret; +} + +Literal* Clause::removeFromTail(Solver& s, Literal* it, Literal* end) { + assert(it != end || contracted()); + if (!contracted()) { + *it = *--end; + *end = lit_false(); + if (!isSmall()) { + local_.setSize(local_.size()-1); + local_.clearIdx(); + } + } + else { + uint32 uLev = s.level(end->var()); + Literal* j = it; + while ( !j->flagged() ) { *j++ = *++it; } + *j = lit_false(); + uint32 nLev = s.level(end->var()); + if (uLev != nLev && s.removeUndoWatch(uLev, this) && nLev != 0) { + s.addUndoWatch(nLev, this); + } + if (j != end) { (j-1)->flag(); } + else { local_.clearContracted(); } + end = j; + } + if (learnt() && !isSmall() && !strengthened()) { + end->flag(); + local_.markStrengthened(); + } + return end; +} +uint32 Clause::size() const { + LitRange t = const_cast(*this).tail(); + return !isSentinel(head_[2]) + ? 3u + static_cast(t.second - t.first) + : 2u; +} +///////////////////////////////////////////////////////////////////////////////////////// +// mt::SharedLitsClause +///////////////////////////////////////////////////////////////////////////////////////// +namespace mt { +ClauseHead* SharedLitsClause::newClause(Solver& s, SharedLiterals* shared_lits, const InfoType& e, const Literal* lits, bool addRef) { + return new (s.allocSmall()) SharedLitsClause(s, shared_lits, lits, e, addRef); +} + +SharedLitsClause::SharedLitsClause(Solver& s, SharedLiterals* shared_lits, const Literal* w, const InfoType& e, bool addRef) + : ClauseHead(e) { + static_assert(sizeof(SharedLitsClause) <= 32, "Unsupported Padding"); + shared_ = addRef ? shared_lits->share() : shared_lits; + std::memcpy(head_, w, std::min((uint32)ClauseHead::HEAD_LITS, shared_lits->size())*sizeof(Literal)); + attach(s); + if (learnt()) { s.addLearntBytes(32); } +} + +Constraint* SharedLitsClause::cloneAttach(Solver& other) { + return SharedLitsClause::newClause(other, shared_, InfoType(this->type()), head_); +} + +bool SharedLitsClause::updateWatch(Solver& s, uint32 pos) { + Literal other = head_[1^pos]; + for (const Literal* r = shared_->begin(), *end = shared_->end(); r != end; ++r) { + // at this point we know that head_[2] is false so we only need to check + // that we do not watch the other watched literal twice! + if (!s.isFalse(*r) && *r != other) { + head_[pos] = *r; // replace watch + // try to replace cache literal + switch( std::min(static_cast(8), static_cast(end-r)) ) { + case 8: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + case 7: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + case 6: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + case 5: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + case 4: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + case 3: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + case 2: if (!s.isFalse(*++r) && *r != other) { head_[2] = *r; return true; } + default: return true; + } + } + } + return false; +} + +void SharedLitsClause::reason(Solver& s, Literal p, LitVec& out) { + for (const Literal* r = shared_->begin(), *end = shared_->end(); r != end; ++r) { + assert(s.isFalse(*r) || *r == p); + if (*r != p) { out.push_back(~*r); } + } + if (learnt()) { + s.updateOnReason(info_.score(), p, out); + } +} + +bool SharedLitsClause::minimize(Solver& s, Literal p, CCMinRecursive* rec) { + s.updateOnMinimize(info_.score()); + for (const Literal* r = shared_->begin(), *end = shared_->end(); r != end; ++r) { + if (*r != p && !s.ccMinimize(~*r, rec)) { return false; } + } + return true; +} + +bool SharedLitsClause::isReverseReason(const Solver& s, Literal p, uint32 maxL, uint32 maxN) { + uint32 notSeen = 0; + for (const Literal* r = shared_->begin(), *end = shared_->end(); r != end; ++r) { + if (*r == p) continue; + if (!isRevLit(s, *r, maxL)) return false; + if (!s.seen(r->var()) && ++notSeen > maxN) return false; + } + return true; +} + +bool SharedLitsClause::simplify(Solver& s, bool reinit) { + if (ClauseHead::satisfied(s)) { + detach(s); + return true; + } + uint32 optSize = shared_->simplify(s); + if (optSize == 0) { + detach(s); + return true; + } + else if (optSize <= Clause::MAX_SHORT_LEN) { + Literal lits[Clause::MAX_SHORT_LEN]; + Literal* j = lits; + for (const Literal* r = shared_->begin(), *e = shared_->end(); r != e; ++r) { + if (!s.isFalse(*r)) *j++ = *r; + } + // safe extra data + InfoType myInfo = info_; + // detach & destroy but do not release memory + detach(s); + SharedLitsClause::destroy(0, false); + // construct short clause in "this" + ClauseHead* h = Clause::newClause(this, s, ClauseRep::prepared(lits, static_cast(j-lits), myInfo)); + return h->simplify(s, reinit); + } + else if (s.isFalse(head_[2])) { + // try to replace cache lit with non-false literal + for (const Literal* r = shared_->begin(), *e = shared_->end(); r != e; ++r) { + if (!s.isFalse(*r) && std::find(head_, head_+2, *r) == head_+2) { + head_[2] = *r; + break; + } + } + } + return false; +} + +void SharedLitsClause::destroy(Solver* s, bool detachFirst) { + if (s) { + if (detachFirst) { ClauseHead::detach(*s); } + if (learnt()) { s->freeLearntBytes(32); } + } + shared_->release(); + void* mem = this; + this->~SharedLitsClause(); + if (s) { s->freeSmall(mem); } +} + +uint32 SharedLitsClause::isOpen(const Solver& s, const TypeSet& x, LitVec& freeLits) { + if (!x.inSet(ClauseHead::type()) || ClauseHead::satisfied(s)) { + return 0; + } + Literal* head = head_; + ValueRep v; + for (const Literal* r = shared_->begin(), *end = shared_->end(); r != end; ++r) { + if ( (v = s.value(r->var())) == value_free ) { + freeLits.push_back(*r); + } + else if (v == trueValue(*r)) { + head[2] = *r; // remember as cache literal + return 0; + } + } + return ClauseHead::type(); +} + +void SharedLitsClause::toLits(LitVec& out) const { + out.insert(out.end(), shared_->begin(), shared_->end()); +} + +ClauseHead::BoolPair SharedLitsClause::strengthen(Solver&, Literal, bool) { + return BoolPair(false, false); +} + +uint32 SharedLitsClause::size() const { return shared_->size(); } +} // end namespace mt + +///////////////////////////////////////////////////////////////////////////////////////// +// LoopFormula +///////////////////////////////////////////////////////////////////////////////////////// +LoopFormula* LoopFormula::newLoopFormula(Solver& s, const ClauseRep& c1, const Literal* atoms, uint32 nAtoms, bool heu) { + uint32 bytes = sizeof(LoopFormula) + (c1.size + nAtoms + 2) * sizeof(Literal); + void* mem = Detail::alloc(bytes); + s.addLearntBytes(bytes); + return new (mem)LoopFormula(s, c1, atoms, nAtoms, heu); +} +LoopFormula::LoopFormula(Solver& s, const ClauseRep& c1, const Literal* atoms, uint32 nAtoms, bool heu) { + act_ = c1.info.score(); + lits_[0] = lit_true(); // Starting sentinel + std::memcpy(lits_ + 1, c1.lits, c1.size * sizeof(Literal)); + lits_[end_ = c1.size + 1] = lit_true(); // Ending sentinel + s.addWatch(~lits_[2], this, (2 << 1) + 1); + lits_[2].flag(); + size_ = c1.size + nAtoms + 2; + str_ = 0; + xPos_ = 1; + other_ = 1; + for (uint32 i = 0, x = end_ + 1; i != nAtoms; ++i, ++x) { + act_.bumpActivity(); + s.addWatch(~(lits_[x] = atoms[i]), this, (1 << 1) + 1); + if (heu) { + lits_[1] = atoms[i]; + s.heuristic()->newConstraint(s, lits_ + 1, c1.size, Constraint_t::Loop); + } + } + (lits_[1] = c1.lits[0]).flag(); +} +void LoopFormula::destroy(Solver* s, bool detach) { + if (s) { + if (detach) { this->detach(*s); } + if (str_) { while (lits_[size_++].rep() != 3u) { ; } } + s->freeLearntBytes(sizeof(LoopFormula) + (size_ * sizeof(Literal))); + } + void* mem = static_cast(this); + this->~LoopFormula(); + Detail::free(mem); +} +void LoopFormula::detach(Solver& s) { + for (Literal* it = begin() + xPos_; !isSentinel(*it); ++it) { + if (it->flagged()) { s.removeWatch(~*it, this); it->unflag(); } + } + for (Literal* it = xBegin(), *end = xEnd(); it != end; ++it) { + s.removeWatch(~*it, this); + } +} +bool LoopFormula::otherIsSat(const Solver& s) { + if (other_ != xPos_) { return s.isTrue(lits_[other_]); } + if (!s.isTrue(lits_[other_])) { return false; } + for (Literal* it = xBegin(), *end = xEnd(); it != end; ++it) { + if (!s.isTrue(*it)) { + if (lits_[xPos_].flagged()){ (lits_[xPos_] = *it).flag(); } + else { lits_[xPos_] = *it; } + return false; + } + } + return true; +} +Constraint::PropResult LoopFormula::propagate(Solver& s, Literal p, uint32& data) { + if (otherIsSat(s)) { // already satisfied? + return PropResult(true, true); + } + uint32 idx = data >> 1; + Literal* w = lits_ + idx; + bool head = idx == xPos_; + if (head) { // p is one of the atoms - move to active part + p = ~p; + if (*w != p && s.isFalse(*w)) { return PropResult(true, true); } + if (!w->flagged()) { *w = p; return PropResult(true, true); } + (*w = p).flag(); + } + for (int bounds = 0, dir = ((data & 1) << 1) - 1;;) { + // search non-false literal - sentinels guarantee termination + for (w += dir; s.isFalse(*w); w += dir) {;} + if (!isSentinel(*w)) { + uint32 nIdx = static_cast(w - lits_); + // other watched literal? + if (w->flagged()) { other_ = nIdx; continue; } + // replace watch + lits_[idx].unflag(); + w->flag(); + // add new watch only w is not one of the atoms + // and keep previous watch if p is one of the atoms + if (nIdx != xPos_) { s.addWatch(~*w, this, (nIdx << 1) + (dir==1)); } + return PropResult(true, head); + } + else if (++bounds == 1) { + w = lits_ + idx; // Halfway through, restart search, but + dir *= -1; // this time walk in the opposite direction. + data ^= 1; // Save new direction of watch + } + else { // clause is unit + bool ok = s.force(lits_[other_], this); + if (other_ == xPos_ && ok) { // all lits in inactive part are implied + for (Literal* it = xBegin(), *end = xEnd(); it != end && (ok = s.force(*it, this)) == true; ++it) { ; } + } + return PropResult(ok, true); + } + } +} +void LoopFormula::reason(Solver& s, Literal p, LitVec& lits) { + // p = body: all literals in active clause + // p = atom: only bodies + for (Literal* it = begin() + (other_ == xPos_); !isSentinel(*it); ++it) { + if (*it != p) { lits.push_back(~*it); } + } + s.updateOnReason(act_, p, lits); +} +bool LoopFormula::minimize(Solver& s, Literal p, CCMinRecursive* rec) { + s.updateOnMinimize(act_); + for (Literal* it = begin() + (other_ == xPos_); !isSentinel(*it); ++it) { + if (*it != p && !s.ccMinimize(~*it, rec)) { return false; } + } + return true; +} +uint32 LoopFormula::size() const { + return size_ - (2 + xPos_); +} +bool LoopFormula::locked(const Solver& s) const { + if (other_ != xPos_ || !s.isTrue(lits_[other_])) { + return s.isTrue(lits_[other_]) && s.reason(lits_[other_]) == this; + } + LoopFormula& self = const_cast(*this); + for (const Literal* it = self.xBegin(), *end = self.xEnd(); it != end; ++it) { + if (s.isTrue(*it) && s.reason(*it) == this) { return true; } + } + return false; +} +uint32 LoopFormula::isOpen(const Solver& s, const TypeSet& xs, LitVec& freeLits) { + if (!xs.inSet(Constraint_t::Loop) || otherIsSat(s)) { + return 0; + } + for (Literal* it = begin() + xPos_; !isSentinel(*it); ++it) { + if (s.value(it->var()) == value_free) { freeLits.push_back(*it); } + else if (s.isTrue(*it)) { other_ = static_cast(it-lits_); return 0; } + } + for (Literal* it = xBegin(), *end = xEnd(); it != end; ++it) { + if (s.value(it->var()) == value_free) { freeLits.push_back(*it); } + } + return Constraint_t::Loop; +} +bool LoopFormula::simplify(Solver& s, bool) { + if (otherIsSat(s) || (other_ != xPos_ && (other_ = xPos_) != 0 && otherIsSat(s))) { + detach(s); + return true; + } + Literal* it = begin(), *j, *end = xEnd(); + while (s.value(it->var()) == value_free) { ++it; } + if (!isSentinel(*(j=it))) { + // simplify active clause + if (*it == lits_[xPos_]){ xPos_ = 0; } + for (GenericWatch* w; !isSentinel(*it); ++it) { + if (s.value(it->var()) == value_free) { + if (it->flagged() && (w = s.getWatch(~*it, this)) != 0) { + w->data = (static_cast(j - lits_) << 1) + (w->data&1); + } + *j++ = *it; + } + else if (s.isTrue(*it)) { detach(s); return true; } + else { assert(!it->flagged() && "Constraint not propagated!"); } + } + *j = lit_true(); + end_ = static_cast(j - lits_); + } + // simplify extra part + for (++it, ++j; it != end; ++it) { + if (s.value(it->var()) == value_free && xPos_) { *j++ = *it; } + else { s.removeWatch(~*it, this); } + } + bool isClause = static_cast(j - xBegin()) == 1; + if (isClause) { --j; } + if (j != end) { // size changed? + if (!str_) { (end-1)->rep() = 3u; str_ = 1u; } + if (isClause){ + assert(xPos_ && *j == lits_[xPos_]); + if (!lits_[xPos_].flagged()) { s.removeWatch(~*j, this); } + xPos_ = 0; + } + size_ = static_cast((end = j) - lits_); + } + assert(!isClause || xPos_ == 0); + other_ = xPos_ + 1; + ClauseRep act = ClauseRep::create(begin(), end_ - 1, Constraint_t::Loop); + if (act.isImp() && s.allowImplicit(act)) { + detach(s); + ClauseCreator::Result res; + for (it = xBegin(); it != end && res.ok() && !res.local; ++it) { + lits_[xPos_] = *it; + res = ClauseCreator::create(s, act, ClauseCreator::clause_no_add); + CLASP_FAIL_IF(lits_[xPos_] != *it, "LOOP MUST NOT CONTAIN ASSIGNED VARS!"); + } + if (!xPos_) { res = ClauseCreator::create(s, act, ClauseCreator::clause_no_add); } + CLASP_FAIL_IF(!res.ok() || res.local, "LOOP MUST NOT CONTAIN AUX VARS!"); + return true; + } + return false; +} + +} diff --git a/libclasp/src/clingo.cpp b/libclasp/src/clingo.cpp new file mode 100644 index 0000000..7b9df28 --- /dev/null +++ b/libclasp/src/clingo.cpp @@ -0,0 +1,280 @@ +// +// Copyright (c) 2015-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +namespace Clasp { namespace { + template + struct Scoped { + Scoped(L* lock, O* obj, const OP& op = OP()) : lock_(lock), obj_(obj), op_(op) { if (lock) (lock->*enter)(); } + ~Scoped() { if (lock_) (lock_->*exit)(); } + O* operator->() const { op_(); return obj_; } + L* lock_; + O* obj_; + OP op_; + }; + struct Nop { void operator()() const {} }; + struct Inc { Inc(LitVec::size_type& e) : epoch_(&e) {} void operator()() const { ++*epoch_; } LitVec::size_type* epoch_; }; + typedef Scoped ScopedLock; + typedef Scoped ScopedUnlock; +} +ClingoPropagatorLock::~ClingoPropagatorLock() {} +///////////////////////////////////////////////////////////////////////////////////////// +// ClingoPropagator::Control +///////////////////////////////////////////////////////////////////////////////////////// +class ClingoPropagator::Control : public Potassco::AbstractSolver, Potassco::AbstractAssignment { +public: + Control(ClingoPropagator& ctx, Solver& s, uint32 st = 0u) : ctx_(&ctx), s_(&s), state_(st | state_ctrl) {} + const AbstractAssignment& assignment() const { return *this; } + // AbstractAssignment + virtual bool hasConflict() const { return s_->hasConflict(); } + virtual uint32_t level() const { return s_->decisionLevel(); } + virtual bool hasLit(Lit_t lit) const { return s_->validVar(decodeVar(lit)); } + virtual Value_t value(Lit_t lit) const { + CLASP_ASSERT_CONTRACT_MSG(Control::hasLit(lit), "Invalid literal"); + switch (s_->value(decodeVar(lit))) { + default: return Value_t::Free; + case value_true: return lit >= 0 ? Value_t::True : Value_t::False; + case value_false: return lit >= 0 ? Value_t::False : Value_t::True; + } + } + virtual uint32_t level(Lit_t lit) const { return Control::value(lit) != Potassco::Value_t::Free ? s_->level(decodeVar(lit)) : UINT32_MAX; } + virtual Lit_t decision(uint32_t dl) const { + CLASP_ASSERT_CONTRACT_MSG(dl <= s_->decisionLevel(), "Invalid decision level"); + return encodeLit(dl ? s_->decision(dl) : lit_true()); + } + + // Potassco::AbstractSolver + virtual Potassco::Id_t id() const { return s_->id(); } + virtual bool addClause(const Potassco::LitSpan& clause, Potassco::Clause_t prop); + virtual bool propagate(); + virtual Lit addVariable(); + virtual bool hasWatch(Lit lit) const; + virtual void addWatch(Lit lit); + virtual void removeWatch(Lit lit); +protected: + typedef ClingoPropagator::State State; + ClingoPropagator* ctx_; + Solver* s_; + uint32 state_; +}; +bool ClingoPropagator::Control::addClause(const Potassco::LitSpan& clause, Potassco::Clause_t prop) { + CLASP_ASSERT_CONTRACT_MSG(!s_->hasConflict(), "Invalid addClause() on conflicting assignment"); + ScopedUnlock pp(ctx_->lock_, ctx_); + pp->toClause(*s_, clause, prop); + return pp->addClause(*s_, state_); +} +bool ClingoPropagator::Control::propagate() { + ScopedUnlock unlocked(ctx_->lock_, ctx_); + if (s_->hasConflict()) { return false; } + if (s_->queueSize() == 0) { return true; } + ClingoPropagator::size_t epoch = ctx_->epoch_; + return (state_ & state_prop) != 0u && s_->propagateUntil(unlocked.obj_) && epoch == ctx_->epoch_; +} +Potassco::Lit_t ClingoPropagator::Control::addVariable() { + CLASP_ASSERT_CONTRACT_MSG(!s_->hasConflict(), "Invalid addVariable() on conflicting assignment"); + ScopedUnlock unlocked(ctx_->lock_, ctx_); + return encodeLit(posLit(s_->pushAuxVar())); +} +bool ClingoPropagator::Control::hasWatch(Lit_t lit) const { + ScopedUnlock unlocked(ctx_->lock_, ctx_); + return Control::hasLit(lit) && s_->hasWatch(decodeLit(lit), ctx_); +} +void ClingoPropagator::Control::addWatch(Lit_t lit) { + ScopedUnlock unlocked(ctx_->lock_, ctx_); + CLASP_ASSERT_CONTRACT_MSG(Control::hasLit(lit), "Invalid literal"); + Literal p = decodeLit(lit); + if (!s_->hasWatch(p, ctx_)) { + s_->addWatch(p, ctx_); + } +} +void ClingoPropagator::Control::removeWatch(Lit_t lit) { + ScopedUnlock unlocked(ctx_->lock_, ctx_); + if (Control::hasLit(lit)) { + s_->removeWatch(decodeLit(lit), ctx_); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClingoPropagator +///////////////////////////////////////////////////////////////////////////////////////// +// flags for clauses from propagator +static const uint32 ccFlags_s[2] = { + /* 0: learnt */ Clasp::ClauseCreator::clause_not_sat | Clasp::ClauseCreator::clause_int_lbd, + /* 1: static */ ClauseCreator::clause_no_add | ClauseCreator::clause_explicit +}; +ClingoPropagator::ClingoPropagator(const LitVec& watches, Potassco::AbstractPropagator& cb, ClingoPropagatorLock* ctrl) + : watches_(watches) + , call_(&cb) + , lock_(ctrl) + , init_(0), prop_(0), epoch_(0), level_(0) { +} +uint32 ClingoPropagator::priority() const { return static_cast(priority_class_general); } + +void ClingoPropagator::destroy(Solver* s, bool detach) { + destroyDB(db_, s, detach); + PostPropagator::destroy(s, detach); +} + +bool ClingoPropagator::init(Solver& s) { + CLASP_ASSERT_CONTRACT_MSG(init_ <= watches_.size(), "Invalid watch list update"); + uint32 ignore = 0; + for (size_t max = watches_.size(); init_ != max; ++init_) { + Literal p = watches_[init_]; + if (s.value(p.var()) == value_free || s.level(p.var()) > s.rootLevel()) { + s.addWatch(p, this, toU32(init_)); + } + else if (s.isTrue(p)) { + ClingoPropagator::propagate(s, p, ignore); + } + } + return true; +} + +Constraint::PropResult ClingoPropagator::propagate(Solver& s, Literal p, uint32&) { + uint32 dl = s.decisionLevel(); + CLASP_ASSERT_CONTRACT_MSG(dl >= level_, "Stack property violated"); + if (dl != level_) { // remember start of new decision level + s.addUndoWatch(level_ = dl, this); + undo_.push_back(static_cast(trail_.size())); + } + trail_.push_back(encodeLit(p)); + return PropResult(true, true); +} +void ClingoPropagator::undoLevel(Solver& s) { + CLASP_ASSERT_CONTRACT_MSG(s.decisionLevel() == level_, "Invalid undo"); + uint32 beg = undo_.back(); + undo_.pop_back(); + if (prop_ > beg) { + Potassco::LitSpan change = Potassco::toSpan(&trail_[0] + beg, prop_ - beg); + ScopedLock(lock_, call_, Inc(epoch_))->undo(Control(*this, s), change); + prop_ = beg; + } + trail_.resize(beg); + level_ = !trail_.empty() ? s.level(decodeLit(trail_.back()).var()) : 0; +} +bool ClingoPropagator::propagateFixpoint(Clasp::Solver& s, Clasp::PostPropagator*) { + CLASP_ASSERT_CONTRACT_MSG(prop_ <= trail_.size(), "Invalid propagate"); + for (Control ctrl(*this, s, state_prop); prop_ != trail_.size();) { + Potassco::LitSpan change = Potassco::toSpan(&trail_[0] + prop_, trail_.size() - prop_); + prop_ = static_cast(trail_.size()); + ScopedLock(lock_, call_, Inc(epoch_))->propagate(ctrl, change); + if (!addClause(s, state_prop) || (s.queueSize() && !s.propagateUntil(this))) { + return false; + } + } + return true; +} + +void ClingoPropagator::toClause(Solver& s, const Potassco::LitSpan& clause, Potassco::Clause_t prop) { + CLASP_ASSERT_CONTRACT_MSG(todo_.empty(), "Assignment not propagated"); + Literal max; + LitVec& mem = todo_.mem; + for (const Potassco::Lit_t* it = Potassco::begin(clause); it != Potassco::end(clause); ++it) { + Literal p = decodeLit(*it); + if (max < p) { max = p; } + mem.push_back(p); + } + if (aux_ < max) { aux_ = max; } + if ((Potassco::Clause_t::isVolatile(prop) || s.auxVar(max.var())) && !isSentinel(s.sharedContext()->stepLiteral())) { + mem.push_back(~s.sharedContext()->stepLiteral()); + } + todo_.clause = ClauseCreator::prepare(s, mem, Clasp::ClauseCreator::clause_force_simplify, Constraint_t::Other); + todo_.flags = ccFlags_s[int(Potassco::Clause_t::isStatic(prop))]; +} +bool ClingoPropagator::addClause(Solver& s, uint32 st) { + if (s.hasConflict()) { todo_.clear(); return false; } + if (todo_.empty()) { return true; } + const ClauseRep& clause = todo_.clause; + Literal first = clause.size > 0 ? clause.lits[0] : lit_false(); + uint32 impLevel = clause.size > 1 ? ClauseCreator::watchOrder(s, clause.lits[1]) : 0; + if (impLevel < s.decisionLevel() && s.isUndoLevel()) { + if ((st & state_ctrl) != 0u) { return false; } + if ((st & state_prop) != 0u) { ClingoPropagator::reset(); cancelPropagation(); } + s.undoUntil(impLevel); + } + bool local = (todo_.flags & ClauseCreator::clause_no_add) != 0; + if (!s.isFalse(first) || local || s.force(first, this)) { + ClauseCreator::Result res = ClauseCreator::create(s, clause, todo_.flags); + if (res.local && local) { db_.push_back(res.local); } + } + todo_.clear(); + return !s.hasConflict(); +} + +void ClingoPropagator::reason(Solver&, Literal p, LitVec& r) { + if (!todo_.empty() && todo_.mem[0] == p) { + for (LitVec::const_iterator it = todo_.mem.begin() + 1, end = todo_.mem.end(); it != end; ++it) { + r.push_back(~*it); + } + } +} + +bool ClingoPropagator::simplify(Solver& s, bool) { + if (!s.validVar(aux_.var())) { + ClauseDB::size_type i, j, end = db_.size(); + LitVec cc; + Var last = s.numVars(); + aux_ = lit_true(); + for (i = j = 0; i != end; ++i) { + db_[j++] = db_[i]; + ClauseHead* c = db_[i]->clause(); + if (c && c->aux()) { + cc.clear(); + c->toLits(cc); + Literal x = *std::max_element(cc.begin(), cc.end()); + if (x.var() > last) { + c->destroy(&s, true); + --j; + } + else if (aux_ < x) { aux_ = x; } + } + } + db_.erase(db_.begin()+j, db_.end()); + } + simplifyDB(s, db_, false); + return false; +} + +bool ClingoPropagator::isModel(Solver& s) { + CLASP_ASSERT_CONTRACT_MSG(prop_ == trail_.size(), "Assignment not propagated"); + Control ctrl(*this, s); + ScopedLock(lock_, call_, Inc(epoch_))->check(ctrl); + return addClause(s, 0u) && s.numFreeVars() == 0 && s.queueSize() == 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClingoPropagatorInit +///////////////////////////////////////////////////////////////////////////////////////// +ClingoPropagatorInit::ClingoPropagatorInit(Potassco::AbstractPropagator& cb, ClingoPropagatorLock* lock) : prop_(&cb), lock_(lock) {} +ClingoPropagatorInit::~ClingoPropagatorInit() {} +void ClingoPropagatorInit::prepare(SharedContext&) {} +bool ClingoPropagatorInit::addPost(Solver& s) { return s.addPost(new ClingoPropagator(watches_, *prop_, lock_)); } +Potassco::Lit_t ClingoPropagatorInit::addWatch(Literal lit) { + uint32 const word = lit.id() / 32; + uint32 const bit = lit.id() & 31; + if (word >= seen_.size()) { seen_.resize(word + 1, 0); } + if (!test_bit(seen_[word], bit)) { + watches_.push_back(lit); + store_set_bit(seen_[word], bit); + } + return encodeLit(lit); +} +} diff --git a/libclasp/src/constraint.cpp b/libclasp/src/constraint.cpp new file mode 100644 index 0000000..bca2ef7 --- /dev/null +++ b/libclasp/src/constraint.cpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Constraint +///////////////////////////////////////////////////////////////////////////////////////// +Constraint::Constraint() {} +Constraint::~Constraint() {} +void Constraint::destroy(Solver*, bool) { delete this; } +ConstraintType Constraint::type() const { return Constraint_t::Static; } +bool Constraint::simplify(Solver&, bool) { return false; } +void Constraint::undoLevel(Solver&) {} +uint32 Constraint::estimateComplexity(const Solver&) const { return 1; } +bool Constraint::valid(Solver&) { return true; } +ClauseHead* Constraint::clause() { return 0; } +void Constraint::decreaseActivity() {} +void Constraint::resetActivity() {} +ConstraintScore Constraint::activity() const { return makeScore(); } +bool Constraint::locked(const Solver&) const { return true; } +uint32 Constraint::isOpen(const Solver&, const TypeSet&, LitVec&) { return 0; } +///////////////////////////////////////////////////////////////////////////////////////// +// PostPropagator +///////////////////////////////////////////////////////////////////////////////////////// +PostPropagator::PostPropagator() : next(0) {} +PostPropagator::~PostPropagator() {} +bool PostPropagator::init(Solver&) { return true; } +void PostPropagator::reset() {} +bool PostPropagator::isModel(Solver& s) { return valid(s); } +void PostPropagator::reason(Solver&, Literal, LitVec&) {} +Constraint::PropResult PostPropagator::propagate(Solver&, Literal, uint32&) { + return PropResult(true, false); +} +void PostPropagator::cancelPropagation() { + for (PostPropagator* n = this->next; n; n = n->next) { n->reset(); } +} +MessageHandler::MessageHandler() {} +///////////////////////////////////////////////////////////////////////////////////////// +// PropagatorList +///////////////////////////////////////////////////////////////////////////////////////// +PropagatorList::PropagatorList() : head_(0) {} +PropagatorList::~PropagatorList() { clear(); } +void PropagatorList::clear() { + for (PostPropagator* r = head_; r;) { + PostPropagator* t = r; + r = r->next; + t->destroy(); + } + head_ = 0; +} +void PropagatorList::add(PostPropagator* p) { + CLASP_ASSERT_CONTRACT_MSG(p && p->next == 0, "Invalid post propagator"); + uint32 prio = p->priority(); + for (PostPropagator** r = head(), *x;; r = &x->next) { + if ((x = *r) == 0 || prio < (uint32)x->priority()) { + p->next = x; + *r = p; + break; + } + } +} +void PropagatorList::remove(PostPropagator* p) { + CLASP_ASSERT_CONTRACT_MSG(p, "Invalid post propagator"); + for (PostPropagator** r = head(), *x; *r; r = &x->next) { + if ((x = *r) == p) { + *r = x->next; + p->next = 0; + break; + } + } +} +PostPropagator* PropagatorList::find(uint32 prio) const { + for (PostPropagator* x = head_; x; x = x->next) { + uint32 xp = x->priority(); + if (xp >= prio) { return xp == prio ? x : 0; } + } + return 0; +} +} diff --git a/libclasp/src/dependency_graph.cpp b/libclasp/src/dependency_graph.cpp new file mode 100644 index 0000000..2e9eaeb --- /dev/null +++ b/libclasp/src/dependency_graph.cpp @@ -0,0 +1,1064 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +namespace Clasp { +SolveTestEvent::SolveTestEvent(const Solver& s, uint32 a_hcc, bool part) + : SolveEvent(s, Event::verbosity_max) + , result(-1), hcc(a_hcc), partial(part) { + confDelta = s.stats.conflicts; + choiceDelta = s.stats.choices; + time = 0.0; +} +uint64 SolveTestEvent::choices() const { + return solver->stats.choices - choiceDelta; +} +uint64 SolveTestEvent::conflicts() const { + return solver->stats.conflicts - confDelta; +} +namespace Asp { +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgDepGraph +///////////////////////////////////////////////////////////////////////////////////////// +PrgDepGraph::PrgDepGraph(NonHcfMapType m) { + // add sentinal atom needed for disjunctions + createAtom(lit_false(), PrgNode::noScc); + VarVec adj; adj.push_back(idMax); + initAtom(sentinel_atom, 0, adj, 0); + seenComponents_ = 0; + mapType_ = (uint32)m; + stats_ = 0; +} + +PrgDepGraph::~PrgDepGraph() { + for (AtomVec::size_type i = 0; i != atoms_.size(); ++i) { + delete [] atoms_[i].adj_; + } + for (AtomVec::size_type i = 0; i != bodies_.size(); ++i) { + delete [] bodies_[i].adj_; + } + delete stats_; + while (!components_.empty()) { + delete components_.back(); + components_.pop_back(); + } +} +bool PrgDepGraph::relevantPrgAtom(const Solver& s, PrgAtom* a) const { + return !a->ignoreScc() && a->inUpper() && a->scc() != PrgNode::noScc && !s.isFalse(a->literal()); +} +bool PrgDepGraph::relevantPrgBody(const Solver& s, PrgBody* b) const { + return !s.isFalse(b->literal()); +} + +// Creates a positive-body-atom-dependency graph (PBADG) +// The PBADG contains a node for each atom A of a non-trivial SCC and +// a node for each body B, s.th. there is a non-trivially connected atom A with +// B in body(A). +// Pre : b->seen() = 1 for all new and relevant bodies b +// Post: b->seen() = 0 for all bodies that were added to the PBADG +void PrgDepGraph::addSccs(LogicProgram& prg, const AtomList& sccAtoms, const NonHcfSet& nonHcfs) { + // Pass 1: Create graph atom nodes and estimate number of bodies + atoms_.reserve(atoms_.size() + sccAtoms.size()); + AtomList::size_type numBodies = 0; + SharedContext& ctx = *prg.ctx(); + for (AtomList::size_type i = 0, end = sccAtoms.size(); i != end; ++i) { + PrgAtom* a = sccAtoms[i]; + if (relevantPrgAtom(*ctx.master(), a)) { + // add graph atom node and store link between program node and graph node for later lookup + a->resetId(createAtom(a->literal(), a->scc()), true); + // atom is defined by more than just a bunch of clauses + ctx.setFrozen(a->var(), true); + numBodies += a->supports(); + } + } + // Pass 2: Init atom nodes and create body nodes + VarVec adj, ext; + bodies_.reserve(bodies_.size() + numBodies/2); + PrgBody* prgBody; PrgDisj* prgDis; + for (AtomList::size_type i = 0, end = sccAtoms.size(); i != end; ++i) { + PrgAtom* a = sccAtoms[i]; + if (relevantPrgAtom(*ctx.master(), a)) { + uint32 prop = 0; + for (PrgAtom::sup_iterator it = a->supps_begin(), endIt = a->supps_end(); it != endIt; ++it) { + assert(it->isBody() || it->isDisj()); + NodeId bId= PrgNode::noNode; + if (it->isBody() && !it->isGamma()) { + prgBody = prg.getBody(it->node()); + bId = relevantPrgBody(*ctx.master(), prgBody) ? addBody(prg, prgBody) : PrgNode::noNode; + } + else if (it->isDisj()) { + prgDis = prg.getDisj(it->node()); + bId = addDisj(prg, prgDis); + prop |= AtomNode::property_in_disj; + } + if (bId != PrgNode::noNode) { + if (!bodies_[bId].seen()) { + bodies_[bId].seen(true); + adj.push_back(bId); + } + if (it->isChoice()) { + // mark atom as in choice + prop |= AtomNode::property_in_choice; + } + } + } + uint32 nPred= (uint32)adj.size(); + for (PrgAtom::dep_iterator it = a->deps_begin(), endIt = a->deps_end(); it != endIt; ++it) { + if (!it->sign()) { + prgBody = prg.getBody(it->var()); + if (relevantPrgBody(*ctx.master(), prgBody) && prgBody->scc(prg) == a->scc()) { + NodeId bodyId = addBody(prg, prgBody); + if (!bodies_[bodyId].extended()) { + adj.push_back(bodyId); + } + else { + ext.push_back(bodyId); + ext.push_back(bodies_[bodyId].get_pred_idx(a->id())); + assert(bodies_[bodyId].get_pred(ext.back()) == a->id()); + prop |= AtomNode::property_in_ext; + } + } + } + } + if (!ext.empty()) { + adj.push_back(idMax); + adj.insert(adj.end(), ext.begin(), ext.end()); + } + adj.push_back(idMax); + initAtom(a->id(), prop, adj, nPred); + adj.clear(); ext.clear(); + } + } + if (nonHcfs.size() != 0 && stats_ == 0 && nonHcfs.config && nonHcfs.config->context().stats) { + stats_ = enableNonHcfStats(nonHcfs.config->context().stats, prg.isIncremental()); + } + // "update" existing non-hcf components + for (NonHcfIter it = nonHcfBegin(), end = nonHcfEnd(); it != end; ++it) { + (*it)->update(ctx); + } + // add new non-hcf components + uint32 hcc = seenComponents_; + for (NonHcfSet::const_iterator it = nonHcfs.begin() + seenComponents_, end = nonHcfs.end(); it != end; ++it, ++hcc) { + addNonHcf(hcc, ctx, nonHcfs.config, *it); + } + seenComponents_ = nonHcfs.size(); +} + +uint32 PrgDepGraph::createAtom(Literal lit, uint32 aScc) { + NodeId id = (uint32)atoms_.size(); + atoms_.push_back(AtomNode()); + AtomNode& ua = atoms_.back(); + ua.lit = lit; + ua.scc = aScc; + return id; +} + +void PrgDepGraph::initAtom(uint32 id, uint32 prop, const VarVec& adj, uint32 numPreds) { + AtomNode& ua = atoms_[id]; + ua.setProperties(prop); + ua.adj_ = new NodeId[adj.size()]; + ua.sep_ = ua.adj_ + numPreds; + NodeId* sExt = ua.adj_; + NodeId* sSame= sExt + numPreds; + uint32 aScc = ua.scc; + for (VarVec::const_iterator it = adj.begin(), end = adj.begin()+numPreds; it != end; ++it) { + BodyNode& bn = bodies_[*it]; + if (bn.scc != aScc) { *sExt++ = *it; } + else { *--sSame= *it; } + bn.seen(false); + } + std::reverse(sSame, ua.adj_ + numPreds); + std::copy(adj.begin()+numPreds, adj.end(), ua.sep_); +} + +uint32 PrgDepGraph::createBody(PrgBody* b, uint32 bScc) { + NodeId id = (uint32)bodies_.size(); + bodies_.push_back(BodyNode(b, bScc)); + return id; +} + +// Creates and initializes a body node for the given body b. +uint32 PrgDepGraph::addBody(const LogicProgram& prg, PrgBody* b) { + if (b->seen()) { // first time we see this body - + VarVec preds, atHeads; + uint32 bScc = b->scc(prg); + NodeId bId = createBody(b, bScc); + addPreds(prg, b, bScc, preds); + addHeads(prg, b, atHeads); + initBody(bId, preds, atHeads); + b->resetId(bId, false); + prg.ctx()->setFrozen(b->var(), true); + } + return b->id(); +} + +// Adds all relevant predecessors of b to preds. +// The returned list looks like this: +// [[B], a1, [w1], ..., aj, [wj], idMax, l1, [w1], ..., lk, [wk], idMax], where +// B is the bound of b (only for card/weight rules), +// ai is a positive predecessor from bScc, +// wi is the weight of ai (only for weight rules), and +// li is a literal of a subgoal from some other scc (only for cardinality/weight rules) +void PrgDepGraph::addPreds(const LogicProgram& prg, PrgBody* b, uint32 bScc, VarVec& preds) const { + if (bScc == PrgNode::noScc) { preds.clear(); return; } + const bool weights = b->type() == Body_t::Sum; + for (uint32 i = 0; i != b->size() && !b->goal(i).sign(); ++i) { + PrgAtom* pred = prg.getAtom(b->goal(i).var()); + if (relevantPrgAtom(*prg.ctx()->master(), pred) && pred->scc() == bScc) { + preds.push_back( pred->id() ); + if (weights) { preds.push_back(b->weight(i)); } + } + } + if (b->type() != Body_t::Normal) { + preds.insert(preds.begin(), b->bound()); + preds.push_back(idMax); + for (uint32 n = 0; n != b->size(); ++n) { + PrgAtom* pred = prg.getAtom(b->goal(n).var()); + bool ext = b->goal(n).sign() || pred->scc() != bScc; + Literal lit = b->goal(n).sign() ? ~pred->literal() : pred->literal(); + if (ext && !prg.ctx()->master()->isFalse(lit)) { + preds.push_back(lit.rep()); + if (weights) { preds.push_back(b->weight(n)); } + } + } + } + preds.push_back(idMax); +} + +// Splits the heads of b into atoms and disjunctions. +// Disjunctions are flattened to sentinel-enclose datom-lists. +uint32 PrgDepGraph::addHeads(const LogicProgram& prg, PrgBody* b, VarVec& heads) const { + for (PrgBody::head_iterator it = b->heads_begin(), end = b->heads_end(); it != end; ++it) { + if (it->isAtom() && !it->isGamma()) { + PrgAtom* a = prg.getAtom(it->node()); + if (relevantPrgAtom(*prg.ctx()->master(), a)) { + heads.push_back(a->id()); + } + } + else if (it->isDisj()) { + assert(prg.getDisj(it->node())->inUpper() && prg.getDisj(it->node())->supports() == 1); + PrgDisj* d = prg.getDisj(it->node()); + // flatten disjunction and enclose in sentinels + heads.push_back(sentinel_atom); + getAtoms(prg, d, heads); + heads.push_back(sentinel_atom); + } + } + return sizeVec(heads); +} + +// Adds the atoms from the given disjunction to atoms and returns the disjunction's scc. +uint32 PrgDepGraph::getAtoms(const LogicProgram& prg, PrgDisj* d, VarVec& atoms) const { + uint32 scc = PrgNode::noScc; + for (PrgDisj::atom_iterator it = d->begin(), end = d->end(); it != end; ++it) { + PrgAtom* a = prg.getAtom(*it); + if (relevantPrgAtom(*prg.ctx()->master(), a)) { + assert(scc == PrgNode::noScc || scc == a->scc()); + atoms.push_back(a->id()); + scc = a->scc(); + } + } + return scc; +} + +// Initializes preds and succs lists of the body node with the given id. +void PrgDepGraph::initBody(uint32 id, const VarVec& preds, const VarVec& atHeads) { + BodyNode* bn = &bodies_[id]; + uint32 nSuccs= sizeVec(atHeads); + bn->adj_ = new NodeId[nSuccs + preds.size()]; + bn->sep_ = bn->adj_ + nSuccs; + NodeId* sSame= bn->adj_; + NodeId* sExt = sSame + nSuccs; + uint32 bScc = bn->scc; + uint32 hScc = PrgNode::noScc; + uint32 disj = 0; + for (VarVec::const_iterator it = atHeads.begin(), end = atHeads.end(); it != end;) { + if (*it) { + hScc = getAtom(*it).scc; + if (hScc == bScc) { *sSame++ = *it++; } + else { *--sExt = *it++; } + } + else { + hScc = getAtom(it[1]).scc; ++disj; + if (hScc == bScc) { *sSame++ = *it++; while ( (*sSame++ = *it++) ) { ; } } + else { *--sExt = *it++; while ( (*--sExt = *it++) ) { ; } } + } + } + std::copy(preds.begin(), preds.end(), bn->sep_); + bn->sep_ += bn->extended(); + if (disj) { bodies_[id].data |= BodyNode::flag_has_delta; } +} + +uint32 PrgDepGraph::addDisj(const LogicProgram& prg, PrgDisj* d) { + assert(d->inUpper() && d->supports() == 1); + if (d->seen()) { // first time we see this disjunction + PrgBody* prgBody = prg.getBody(d->supps_begin()->node()); + uint32 bId = PrgNode::noNode; + if (relevantPrgBody(*prg.ctx()->master(), prgBody)) { + bId = addBody(prg, prgBody); + } + d->resetId(bId, false); + } + return d->id(); +} + +void PrgDepGraph::addNonHcf(uint32 id, SharedContext& ctx, Configuration* config, uint32 scc) { + VarVec sccAtoms, sccBodies; + // get all atoms from scc + for (uint32 i = 0; i != numAtoms(); ++i) { + if (getAtom(i).scc == scc) { + sccAtoms.push_back(i); + atoms_[i].set(AtomNode::property_in_non_hcf); + } + } + // get all bodies defining an atom in scc + const Solver& generator = *ctx.master(); (void)generator; + for (uint32 i = 0; i != sccAtoms.size(); ++i) { + const AtomNode& a = getAtom(sccAtoms[i]); + for (const NodeId* bodyIt = a.bodies_begin(), *bodyEnd = a.bodies_end(); bodyIt != bodyEnd; ++bodyIt) { + BodyNode& B = bodies_[*bodyIt]; + if (!B.seen()) { + assert(generator.value(B.lit.var()) != value_free || !generator.seen(B.lit)); + sccBodies.push_back(*bodyIt); + B.seen(true); + } + } + } + for (uint32 i = 0; i != sccBodies.size(); ++i) { bodies_[sccBodies[i]].seen(false); } + components_.push_back( new NonHcfComponent(id, *this, ctx, config, scc, sccAtoms, sccBodies) ); + if (stats_) { stats_->addHcc(*components_.back()); } +} +void PrgDepGraph::simplify(const Solver& s) { + const bool shared = s.sharedContext()->isShared(); + ComponentVec::iterator j = components_.begin(); + for (ComponentVec::iterator it = components_.begin(), end = components_.end(); it != end; ++it) { + bool ok = (*it)->simplify(s); + if (!shared) { + if (ok) { *j++ = *it; } + else { + if (stats_) { stats_->removeHcc(**it); } + delete *it; + } + } + } + if (!shared) { components_.erase(j, components_.end()); } +} +PrgDepGraph::NonHcfStats* PrgDepGraph::enableNonHcfStats(uint32 level, bool inc) { + if (!stats_) { stats_ = new NonHcfStats(*this, level, inc); } + return stats_; +} +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgDepGraph::NonHcfComponent::ComponentMap +///////////////////////////////////////////////////////////////////////////////////////// +class PrgDepGraph::NonHcfComponent::ComponentMap { +public: + ComponentMap() { static_assert(sizeof(Mapping) == sizeof(uint64), "Invalid padding!"); } + struct Mapping { + explicit Mapping(NodeId id) : node(id), var(0), ext(0) { } + uint32 node; // node id in dep-graph of generator program P + uint32 var : 30; // var in tester solver + uint32 ext : 2; // additional data + // Atom + bool disj() const { return ext != 0u; } + bool hasTp() const { return ext == 2u; } + Literal up() const { return posLit(var); } + Literal hp() const { assert(disj()); return posLit(var + 1); } + Literal tp() const { assert(disj()); return posLit((var + 2)*uint32(hasTp())); } + // Body + Literal fb() const { return Literal(var, (ext & 1u) != 0u); } + bool eq() const { return ext != 0u; } + bool operator<(const Mapping& other) const { return node < other.node; } + }; + typedef PrgDepGraph SccGraph; + typedef PodVector::type NodeMap; + typedef NodeMap::iterator MapIt; + typedef NodeMap::const_iterator MapIt_c; + typedef std::pair MapRange; + void addVars(Solver& generator, const SccGraph& dep, const VarVec& atoms, const VarVec& bodies, SharedContext& out); + void addAtomConstraints(SharedContext& out); + void addBodyConstraints(const Solver& generator, const SccGraph& dep, uint32 scc, SharedContext& out); + void mapGeneratorAssignment(const Solver& generator, const SccGraph& dep, LitVec& out) const; + void mapTesterModel(const Solver& tester, VarVec& out) const; + bool simplify(const Solver& generator, const SccGraph& dep, Solver& tester); + MapRange atoms() const { return MapRange(mapping.begin(), mapping.begin() + numAtoms); } + MapRange bodies()const { return MapRange(mapping.begin() + numAtoms, mapping.end()); } + MapIt_c findAtom(NodeId nodeId) const { return std::lower_bound(mapping.begin(), mapping.begin()+numAtoms, Mapping(nodeId)); } + NodeMap mapping; // maps nodes of P to literals in C; + uint32 numAtoms;// number of atoms +}; +// Adds necessary variables for all atoms and bodies to the component program. +// Input-Vars: (set via assumptions) +// tp: for each atom p in a proper disjunctive head, tp is true iff p is true in P +// fb: for each body b, fb is true iff b is false in P +// Aux-Var: (derived) +// hp: for each atom p in a proper disjunctive head, hp is true iff tp and ~up +// Output: (unfounded sets) +// up: for each atom p, up is true iff a is unfounded w.r.t the assignment of P. +void PrgDepGraph::NonHcfComponent::ComponentMap::addVars(Solver& generator, const SccGraph& dep, const VarVec& atoms, const VarVec& bodies, SharedContext& comp) { + assert(generator.decisionLevel() == 0); + mapping.reserve(atoms.size() + bodies.size()); + const PrgDepGraph::NonHcfMapType mt = dep.nonHcfMapType(); + for (VarVec::const_iterator it = atoms.begin(), end = atoms.end(); it != end; ++it) { + const AtomNode& at = dep.getAtom(*it); + Literal gen = at.lit; + if (generator.isFalse(gen)) { continue; } + Mapping map(*it); + // up [ hp [tp] ] + map.var = comp.addVar(Var_t::Atom); // up + map.ext = (mt == PrgDepGraph::map_old || at.inDisjunctive()); + comp.setFrozen(map.var, true); + if (map.ext) { + comp.addVar(Var_t::Atom); // hp + if (!generator.isTrue(gen)) { // tp + comp.setFrozen(comp.addVar(Var_t::Atom), true); + ++map.ext; + } + } + mapping.push_back(map); + } + numAtoms = (uint32)mapping.size(); + std::stable_sort(mapping.begin(), mapping.end()); + // add necessary vars for bodies + for (VarVec::const_iterator it = bodies.begin(), end = bodies.end(); it != end; ++it) { + Literal gen = dep.getBody(*it).lit; + if (generator.isFalse(gen)) { continue; } + Mapping map(*it); + if (!generator.seen(gen) && !generator.isTrue(gen)) { + map.var = comp.addVar(Var_t::Atom); + comp.setFrozen(map.var, true); + generator.markSeen(gen); + } + else if (generator.isTrue(gen)) { + map.ext = 1u; + } + else { + map.ext = 2u; + for (MapRange r = this->bodies(); r.first != r.second;) { + --r.second; + if (dep.getBody(r.second->node).lit == gen) { + map.var = r.second->var; + break; + } + } + } + assert(map.var <= comp.numVars() && (map.var || map.ext == 1u)); + mapping.push_back(map); + } + for (MapRange r = this->bodies(); r.first != r.second; ++r.first) { + if (!r.first->eq()) { + Var v = dep.getBody(r.first->node).lit.var(); + generator.clearSeen(v); + } + } +} + +// Adds constraints stemming from the given atoms to the component program. +// 1. [up(a0) v ... v up(an-1)], where +// - ai is an atom in P from the given atom set, and +// - up(ai) is the corresponding output-atom in the component program C. +// 2. For each atom ai in atom set occurring in a proper disjunction, [hp(ai) <=> tp(ai), ~up(ai)], where +// tp(ai), hp(ai), up(ai) are the input, aux, and output atoms in C. +void PrgDepGraph::NonHcfComponent::ComponentMap::addAtomConstraints(SharedContext& comp) { + ClauseCreator cc1(comp.master()), cc2(comp.master()); + cc1.addDefaultFlags(ClauseCreator::clause_force_simplify); + cc1.start(); + for (MapRange r = atoms(); r.first != r.second; ++r.first) { + const Mapping& m = *r.first; + cc1.add(m.up()); + if (m.disj()) { + cc2.start().add(~m.tp()).add(m.up()).add(m.hp()).end(); // [~tp v up v hp] + cc2.start().add(~m.hp()).add(m.tp()).end(); // [~hp v tp] + cc2.start().add(~m.hp()).add(~m.up()).end(); // [~hp v ~up] + } + } + cc1.end(); +} + +// Adds constraints stemming from the given bodies to the component program. +// For each atom ai and rule a0 | ai | ...| an :- B, s.th. B in bodies +// [~up(ai) v fb(B) V hp(aj), j != i V up(p), p in B+ ^ C], where +// hp(ai), up(ai) are the aux and output atoms of ai in C. +void PrgDepGraph::NonHcfComponent::ComponentMap::addBodyConstraints(const Solver& generator, const SccGraph& dep, uint32 scc, SharedContext& comp) { + ClauseCreator cc(comp.master()); + cc.addDefaultFlags(ClauseCreator::clause_force_simplify); + ClauseCreator dc(comp.master()); + MapIt j = mapping.begin() + numAtoms; + for (MapRange r = bodies(); r.first != r.second; ++r.first) { + const BodyNode& B = dep.getBody(r.first->node); + if (generator.isFalse(B.lit)) { continue; } + if (B.extended()) { throw std::runtime_error("Extended bodies not supported - use '--trans-ext=weight'"); } + for (const NodeId* hIt = B.heads_begin(), *hEnd = B.heads_end(); hIt != hEnd; ++hIt) { + uint32 hScc = *hIt ? dep.getAtom(*hIt).scc : dep.getAtom(hIt[1]).scc; + if (hScc != scc) { + // the head is not relevant to this non-hcf - skip it + if (!*hIt) { do { ++hIt; } while (*hIt); } + continue; + } + // [fb(B) v ~up(a) V hp(o) for all o != a in B.disHead V up(b) for each b in B+ ^ C] + cc.start().add(r.first->fb()); + if (B.scc == scc) { // add subgoals from same scc + for (const NodeId* aIt = B.preds(); *aIt != idMax; ++aIt) { + MapIt_c atMapped = findAtom(*aIt); + cc.add(atMapped->up()); + } + } + if (*hIt) { // normal head + MapIt_c atMapped = findAtom(*hIt); + assert(atMapped != atoms().second); + cc.add(~atMapped->up()); + cc.end(); + } + else { // disjunctive head + const NodeId* dHead = ++hIt; + for (; *hIt; ++hIt) { + dc.start(); + dc = cc; + MapIt_c atMapped = findAtom(*hIt); + dc.add(~atMapped->up()); + for (const NodeId* other = dHead; *other; ++other) { + if (*other != *hIt) { + assert(dep.getAtom(*other).scc == scc); + atMapped = findAtom(*other); + dc.add(atMapped->hp()); + } + } + dc.end(); + } + } + } + if (!r.first->eq()) { *j++ = *r.first; } + } + mapping.erase(j, mapping.end()); +} + +// Maps the generator assignment given in s to a list of tester assumptions. +void PrgDepGraph::NonHcfComponent::ComponentMap::mapGeneratorAssignment(const Solver& s, const SccGraph& dep, LitVec& assume) const { + Literal gen; + assume.clear(); assume.reserve(mapping.size()); + for (MapRange r = atoms(); r.first != r.second; ++r.first) { + const Mapping& at = *r.first; + gen = dep.getAtom(at.node).lit; + if (at.hasTp()) { + assume.push_back(at.tp() ^ (!s.isTrue(gen))); + } + if (s.isFalse(gen)) { assume.push_back(~at.up()); } + } + for (MapRange r = bodies(); r.first != r.second; ++r.first) { + gen = dep.getBody(r.first->node).lit; + assume.push_back(r.first->fb() ^ (!s.isFalse(gen))); + } +} +// Maps the tester model given in s back to a list of unfounded atoms in the generator. +void PrgDepGraph::NonHcfComponent::ComponentMap::mapTesterModel(const Solver& s, VarVec& out) const { + assert(s.numFreeVars() == 0); + out.clear(); + for (MapRange r = atoms(); r.first != r.second; ++r.first) { + if (s.isTrue(r.first->up())) { + out.push_back(r.first->node); + } + } +} +bool PrgDepGraph::NonHcfComponent::ComponentMap::simplify(const Solver& generator, const SccGraph& dep, Solver& tester) { + if (!tester.popRootLevel(UINT32_MAX)) { return false; } + if (tester.sharedContext()->isShared() && (tester.sharedContext()->allowImplicit(Constraint_t::Conflict) || tester.sharedContext()->distributor.get())) { + // Simplification not safe: top-level assignments of threads are + // not necessarily synchronised at this point and clauses simplified + // with top-level assignment of this thread might not (yet) be valid + // wrt possible assumptions in other threads. + return true; + } + const bool rem = !tester.sharedContext()->isShared(); + MapIt j = rem ? mapping.begin() : mapping.end(); + for (MapIt_c it = mapping.begin(), aEnd = it + numAtoms, end = mapping.end(); it != end; ++it) { + const Mapping& m = *it; + const bool atom = it < aEnd; + Literal g = atom ? dep.getAtom(m.node).lit : dep.getBody(m.node).lit; + if (generator.topValue(g.var()) == value_free) { + if (rem) { *j++ = m; } + continue; + } + bool isFalse = generator.isFalse(g); + bool ok = atom || tester.force(isFalse ? m.fb() : ~m.fb()); + if (atom) { + if (!isFalse){ ok = !m.hasTp() || tester.force(m.tp()); if (rem) { *j++ = m; } } + else { ok = tester.force(~m.up()) && (!m.hasTp() || tester.force(~m.tp())); numAtoms -= (ok && rem); } + } + if (!ok) { + if (rem) { j = std::copy(it, end, j); } + break; + } + } + mapping.erase(j, mapping.end()); + return tester.simplify(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgDepGraph::NonHcfComponent +///////////////////////////////////////////////////////////////////////////////////////// +PrgDepGraph::NonHcfComponent::NonHcfComponent(uint32 id, const PrgDepGraph& dep, SharedContext& genCtx, Configuration* c, uint32 scc, const VarVec& atoms, const VarVec& bodies) + : dep_(&dep) + , prg_(new SharedContext()) + , comp_(new ComponentMap()) + , id_(id) + , scc_(scc) { + Solver& generator = *genCtx.master(); + prg_->setConcurrency(genCtx.concurrency(), SharedContext::resize_reserve); + prg_->setConfiguration(c, Ownership_t::Retain); + comp_->addVars(generator, dep, atoms, bodies, *prg_); + prg_->startAddConstraints(); + comp_->addAtomConstraints(*prg_); + comp_->addBodyConstraints(generator, dep, scc, *prg_); + prg_->endInit(true); +} + +PrgDepGraph::NonHcfComponent::~NonHcfComponent() { + delete prg_; + delete comp_; +} + +void PrgDepGraph::NonHcfComponent::update(const SharedContext& generator) { + for (uint32 i = 0; generator.hasSolver(i); ++i) { + if (!prg_->hasSolver(i)) { prg_->attach(prg_->pushSolver()); } + else { prg_->initStats(*prg_->solver(i)); } + } +} + +void PrgDepGraph::NonHcfComponent::assumptionsFromAssignment(const Solver& s, LitVec& assume) const { + comp_->mapGeneratorAssignment(s, *dep_, assume); +} + +bool PrgDepGraph::NonHcfComponent::test(const Solver& generator, const LitVec& assume, VarVec& unfoundedOut) const { + assert(generator.id() < prg_->concurrency() && "Invalid id!"); + // Forwards to message handler of generator so that messages are + // handled during long running tests. + struct Tester : MessageHandler { + Tester(Solver& s, MessageHandler* gen) : solver(&s), generator(gen) { if (gen) { s.addPost(this); } } + ~Tester() { if (generator) { solver->removePost(this); } } + bool handleMessages() { return generator->handleMessages(); } + bool propagateFixpoint(Solver&, PostPropagator*) { return Tester::handleMessages() || !terminate(); } + bool terminate() { solver->setStopConflict(); return true; } + int test(const LitVec& assume) { + return int(BasicSolve(*solver).satisfiable(assume, solver->stats.choices == 0) == false); + } + Solver* solver; + MessageHandler* generator; + } tester(*prg_->solver(generator.id()), static_cast(generator.getPost(PostPropagator::priority_reserved_msg))); + SolveTestEvent ev(*tester.solver, id_, generator.numFreeVars() != 0); + tester.solver->stats.addTest(ev.partial); + generator.sharedContext()->report(ev); + ev.time = ThreadTime::getTime(); + if ((ev.result = tester.test(assume)) == 0) { + tester.solver->stats.addModel(tester.solver->decisionLevel()); + comp_->mapTesterModel(*tester.solver, unfoundedOut); + } + ev.time = ThreadTime::getTime() - ev.time; + tester.solver->stats.addCpuTime(ev.time); + generator.sharedContext()->report(ev); + return ev.result != 0; +} +bool PrgDepGraph::NonHcfComponent::simplify(const Solver& s) const { + return comp_->simplify(s, *dep_, *prg_->solver(s.id())); +} +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgDepGraph::NonHcfStats +///////////////////////////////////////////////////////////////////////////////////////// +struct PrgDepGraph::NonHcfStats::Data { + typedef StatsVec ProblemVec; + typedef StatsVec SolverVec; + struct ComponentStats { + ProblemVec problem; + SolverVec solvers; + SolverVec accu; + }; + Data(uint32 level, bool inc) : components(level > 1 ? new ComponentStats : 0) { + if (inc) { solvers.multi = new SolverStats(); } + } + ~Data() { delete components; delete solvers.multi; } + void addHcc(const NonHcfComponent& c) { + assert(components); + ProblemVec& hcc = components->problem; + SolverVec& solver = components->solvers; + SolverVec* accu = solvers.multi ? &components->accu : 0; + uint32 id = c.id(); + if (id >= hcc.size()) { + hcc.growTo(id + 1); + solver.growTo(id + 1); + if (accu) { accu->growTo(id + 1); } + } + if (!hcc[id]) { + hcc[id] = new ProblemStats(c.ctx().stats()); + solver[id] = new SolverStats(); + if (accu) { (*accu)[id] = new SolverStats(); solver[id]->multi = (*accu)[id]; } + } + } + void updateHcc(const NonHcfComponent& c) { + c.ctx().accuStats(solvers); + if (components && c.id() < components->solvers.size()) { + CLASP_FAIL_IF(!components->solvers[c.id()], "component not added to stats!"); + c.ctx().accuStats(*components->solvers[c.id()]); + components->solvers[c.id()]->flush(); + } + } + ProblemStats hccs; + SolverStats solvers; + ComponentStats* components; +}; +PrgDepGraph::NonHcfStats::NonHcfStats(PrgDepGraph& g, uint32 l, bool inc) : graph_(&g), data_(new Data(l, inc)) { + for (NonHcfIter it = g.nonHcfBegin(), end = g.nonHcfEnd(); it != end; ++it) { + addHcc(**it); + } +} +PrgDepGraph::NonHcfStats::~NonHcfStats() { delete data_; } +void PrgDepGraph::NonHcfStats::accept(StatsVisitor& out, bool final) const { + if (!data_->solvers.multi) { final = false; } + out.visitProblemStats(data_->hccs); + out.visitSolverStats(final ? *data_->solvers.multi : data_->solvers); + if (data_->components && out.visitHccs(StatsVisitor::Enter)) { + const Data::SolverVec& solver = final ? data_->components->accu : data_->components->solvers; + const Data::ProblemVec& hcc = data_->components->problem; + for (uint32 i = 0, end = sizeVec(hcc); i != end; ++i) { + out.visitHcc(i, *hcc[i], *solver[i]); + } + out.visitHccs(StatsVisitor::Leave); + } +} +void PrgDepGraph::NonHcfStats::startStep(uint32 statsLevel) { + data_->solvers.reset(); + if (data_->components) { data_->components->solvers.reset(); } + if (statsLevel > 1 && !data_->components) { + data_->components = new Data::ComponentStats(); + for (NonHcfIter it = graph_->nonHcfBegin(), end = graph_->nonHcfEnd(); it != end; ++it) { + data_->addHcc(**it); + } + } +} +void PrgDepGraph::NonHcfStats::endStep() { + for (NonHcfIter it = graph_->nonHcfBegin(), end = graph_->nonHcfEnd(); it != end; ++it) { + data_->updateHcc(**it); + } + data_->solvers.flush(); +} +void PrgDepGraph::NonHcfStats::addHcc(const NonHcfComponent& c) { + data_->hccs.accu(c.ctx().stats()); + if (data_->components) { data_->addHcc(c); } +} +void PrgDepGraph::NonHcfStats::removeHcc(const NonHcfComponent& c) { + data_->updateHcc(c); +} +void PrgDepGraph::NonHcfStats::addTo(StatsMap& problem, StatsMap& solving, StatsMap* accu) const { + data_->solvers.addTo("hccs", solving, accu); + problem.add("hccs", StatisticObject::map(&data_->hccs)); + if (data_->components) { + problem.add("hcc", data_->components->problem.toStats()); + solving.add("hcc", data_->components->solvers.toStats()); + if (accu) { accu->add("hcc", data_->components->accu.toStats()); } + } +} +} // namespace Asp +///////////////////////////////////////////////////////////////////////////////////////// +// class ExtDepGraph +///////////////////////////////////////////////////////////////////////////////////////// +ExtDepGraph::ExtDepGraph(uint32) : maxNode_(0), comEdge_(0), genCnt_(0) {} +ExtDepGraph::~ExtDepGraph(){} +void ExtDepGraph::addEdge(Literal lit, uint32 startNode, uint32 endNode) { + CLASP_FAIL_IF(!fwdArcs_.empty() && fwdArcs_.back().tail() == UINT32_MAX, "ExtDepGraph::update() not called!"); + fwdArcs_.push_back(Arc::create(lit, startNode, endNode)); + maxNode_ = std::max(std::max(startNode, endNode)+uint32(1), maxNode_); + if (comEdge_ && std::min(startNode, endNode) < nodes_.size()) { + invArcs_.clear(); + comEdge_ = 0; + ++genCnt_; + } +} +bool ExtDepGraph::frozen() const { + return !fwdArcs_.empty() && fwdArcs_.back().tail() == UINT32_MAX; +} +void ExtDepGraph::update() { + if (frozen()) { + fwdArcs_.pop_back(); + } +} +uint32 ExtDepGraph::finalize(SharedContext& ctx) { + if (frozen()) { + return comEdge_; + } + // sort by end node + std::sort(fwdArcs_.begin() + comEdge_, fwdArcs_.end(), CmpArc<1>()); + invArcs_.reserve(fwdArcs_.size()); + Node sent = { UINT32_MAX, UINT32_MAX }; + nodes_.resize(maxNode_, sent); + for (ArcVec::const_iterator it = fwdArcs_.begin() + comEdge_, end = fwdArcs_.end(); it != end;) { + uint32 node = it->head(); + CLASP_FAIL_IF(comEdge_ && nodes_[node].invOff != UINT32_MAX, "ExtDepGraph: invalid incremental update!"); + Inv inv; + nodes_[node].invOff = (uint32)invArcs_.size(); + do { + inv.lit = it->lit; + inv.rep = static_cast(it->tail() << 1) | 1u; + invArcs_.push_back(inv); + ctx.setFrozen(it->lit.var(), true); + } while (++it != end && it->head() == node); + invArcs_.back().rep ^= 1u; + } + // sort by start node + std::sort(fwdArcs_.begin() + comEdge_, fwdArcs_.end(), CmpArc<0>()); + for (ArcVec::const_iterator it = fwdArcs_.begin() + comEdge_, end = fwdArcs_.end(); it != end;) { + uint32 node = it->tail(); + CLASP_FAIL_IF(comEdge_ && nodes_[node].fwdOff != UINT32_MAX, "ExtDepGraph: invalid incremental update!"); + nodes_[node].fwdOff = static_cast(it - fwdArcs_.begin()); + it = std::lower_bound(it, end, node + 1, CmpArc<0>()); + } + comEdge_ = (uint32)fwdArcs_.size(); + fwdArcs_.push_back(Arc::create(lit_false(), UINT32_MAX, UINT32_MAX)); + return comEdge_; +} +uint64 ExtDepGraph::attach(Solver& s, Constraint& p, uint64 genId) { + uint32 count = static_cast(genId >> 32); + uint32 edges = static_cast(genId); + uint32 update= count == genCnt_ ? 0 : edges; + GenericWatch* w; + for (uint32 i = (count == genCnt_ ? edges : 0), eId, end = comEdge_; i < end; ++i) { + const Arc& a = fwdArcs_[i]; + if (a.head() != a.tail()) { + if (s.topValue(a.lit.var()) == value_free) { + if (!update || (w = s.getWatch(a.lit, &p)) == 0) { + s.addWatch(a.lit, &p, i); + } + else { + w->data = i; + --update; + } + } + else if (s.isTrue(a.lit)) { + p.propagate(s, a.lit, (eId = i)); + } + } + else if (!s.force(~a.lit)) { + break; + } + } + return (static_cast(genCnt_) << 32) | comEdge_; +} +void ExtDepGraph::detach(Solver* s, Constraint& p) { + if (s) { + for (ArcVec::size_type i = fwdArcs_.size(); i--; ) { + s->removeWatch(fwdArcs_[i].lit, &p); + } + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// class AcyclicityCheck +///////////////////////////////////////////////////////////////////////////////////////// +struct AcyclicityCheck::ReasonStore { + typedef PodVector::type NogoodMap; + NogoodMap db; + void getReason(Literal p, LitVec& out) { + if (const LitVec* r = db[p.var()]) { + out.insert(out.end(), r->begin(), r->end()); + } + } + void setReason(Literal p, LitVec::const_iterator first, LitVec::const_iterator end) { + Var v = p.var(); + if (v >= db.size()) { db.resize(v+1, 0); } + if (db[v] == 0) { db[v] = new LitVec(first, end); } + else { db[v]->assign(first, end); } + } + ~ReasonStore() { + std::for_each(db.begin(), db.end(), DeleteObject()); + } +}; +AcyclicityCheck::AcyclicityCheck(DependencyGraph* graph) : graph_(graph), solver_(0), nogoods_(0), strat_(bit_mask(config_bit)), tagCnt_(0), genId_(0) { +} +AcyclicityCheck::~AcyclicityCheck() { + delete nogoods_; +} + +void AcyclicityCheck::setStrategy(Strategy p) { + strat_ = p; +} +void AcyclicityCheck::setStrategy(const SolverParams& p) { + if (p.acycFwd) { setStrategy(prop_fwd); } + else { setStrategy(p.loopRep == LoopReason_t::Implicit ? prop_full_imp : prop_full); } + store_set_bit(strat_, config_bit); +} + +bool AcyclicityCheck::init(Solver& s) { + if (!graph_) { graph_ = s.sharedContext()->extGraph.get(); } + if (!graph_) { return true; } + if (test_bit(strat_, config_bit)) { + setStrategy(s.sharedContext()->configuration()->solver(s.id())); + } + tags_.resize(graph_->nodes(), 0); + parent_.resize(graph_->nodes()); + todo_.clear(); + solver_ = &s; + tagCnt_ = 0; + genId_ = graph_->attach(s, *this, genId_); + return true; +} + +uint32 AcyclicityCheck::startSearch() { + if (++tagCnt_ != 0) { return tagCnt_; } + const uint32 last = tagCnt_ - 1; + for (Var v = 0; v != tags_.size(); ++v) { + tags_[v] = tags_[v] == last; + } + return tagCnt_ = 2; +} +void AcyclicityCheck::setReason(Literal p, LitVec::const_iterator first, LitVec::const_iterator end) { + if (!nogoods_) { nogoods_ = new ReasonStore(); } + nogoods_->setReason(p, first, end); +} +void AcyclicityCheck::addClauseLit(Solver& s, Literal p) { + assert(s.isFalse(p)); + uint32 dl = s.level(p.var()); + if (dl && !s.seen(p)) { + s.markSeen(p); + s.markLevel(dl); + reason_.push_back(p); + } +} + +void AcyclicityCheck::reset() { + todo_.clear(); + reason_.clear(); +} + +bool AcyclicityCheck::valid(Solver& s) { + if (todo_.empty()) { return true; } + return AcyclicityCheck::propagateFixpoint(s, 0); +} +bool AcyclicityCheck::isModel(Solver& s) { + return AcyclicityCheck::valid(s); +} + +void AcyclicityCheck::destroy(Solver* s, bool detach) { + if (s && detach) { + s->removePost(this); + } + if (graph_) { + graph_->detach(detach ? s : 0, *this); + } + PostPropagator::destroy(s, detach); +} +void AcyclicityCheck::reason(Solver&, Literal p, LitVec& out) { + if (!reason_.empty() && reason_[0] == p) { + out.insert(out.end(), reason_.begin()+1, reason_.end()); + } + else if (nogoods_) { + nogoods_->getReason(p, out); + } +} + +bool AcyclicityCheck::propagateFixpoint(Solver& s, PostPropagator*) { + for (Arc x; !todo_.empty();) { + x = todo_.pop_ret(); + if (!dfsForward(s, x) || (strategy() != prop_fwd && !dfsBackward(s, x))) { + return false; + } + } + todo_.clear(); + return true; +} +bool AcyclicityCheck::dfsForward(Solver& s, const Arc& root) { + const uint32 tag = startSearch(); + nStack_.clear(); + pushVisit(root.head(), tag); + for (Var node, next; !nStack_.empty();) { + node = nStack_.back(); + nStack_.pop_back(); + for (const Arc* a = graph_->fwdBegin(node); a; a = graph_->fwdNext(a)) { + if (s.isTrue(a->lit)) { + next = a->head(); + if (next == root.tail()) { + setParent(next, Parent::create(a->lit, node)); + reason_.assign(1, ~root.lit); + for (Var n0 = next; n0 != root.head();) { + Parent parent = parent_[n0]; + assert(s.isTrue(parent.lit)); + reason_.push_back(parent.lit); + n0 = parent.node; + } + return s.force(~root.lit, this); + } + else if (!visited(next, tag)) { + setParent(next, Parent::create(a->lit, node)); + pushVisit(next, tag); + } + } + } + } + return true; +} +bool AcyclicityCheck::dfsBackward(Solver& s, const Arc& root) { + const uint32 tag = startSearch(); + const uint32 fwd = tag - 1; + nStack_.clear(); + pushVisit(root.tail(), tag); + for (Var node, next; !nStack_.empty(); ) { + node = nStack_.back(); + nStack_.pop_back(); + for (const Inv* a = graph_->invBegin(node); a; a = graph_->invNext(a)) { + ValueRep val = s.value(a->lit.var()); + if (val == falseValue(a->lit) || visited(next = a->tail(), tag)) { continue; } + if (visited(next, fwd)) { // a->lit would complete a cycle - force to false + assert(val == value_free || s.level(a->lit.var()) == s.decisionLevel()); + reason_.assign(1, ~a->lit); + addClauseLit(s, ~root.lit); + for (Var n = next; n != root.head(); ) { + Parent parent = parent_[n]; + assert(s.isTrue(parent.lit) && visited(parent.node, fwd)); + addClauseLit(s, ~parent.lit); + n = parent.node; + } + for (Var n = node; n != root.tail(); ) { + Parent parent = parent_[n]; + assert(s.isTrue(parent.lit)&& visited(parent.node, tag)); + addClauseLit(s, ~parent.lit); + n = parent.node; + } + if (val == value_free && strategy() == prop_full) { + ConstraintInfo info(Constraint_t::Loop); + s.finalizeConflictClause(reason_, info, 0); + ClauseCreator::create(s, reason_, ClauseCreator::clause_no_prepare, info); + } + else { + for (uint32 i = 1; i != reason_.size(); ++i) { + s.clearSeen(reason_[i].var()); + reason_[i] = ~reason_[i]; + } + if (!s.force(~a->lit, this)) { return false; } + setReason(~a->lit, reason_.begin()+1, reason_.end()); + } + assert(s.isFalse(a->lit)); + if (!s.propagateUntil(this)) { return false; } + } + else if (val != value_free) { // follow true edge backward + setParent(next, Parent::create(a->lit, node)); + pushVisit(next, tag); + } + } + } + return true; +} +} + diff --git a/libclasp/src/enumerator.cpp b/libclasp/src/enumerator.cpp new file mode 100644 index 0000000..777fa5e --- /dev/null +++ b/libclasp/src/enumerator.cpp @@ -0,0 +1,307 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Enumerator - Shared Queue / Thread Queue +///////////////////////////////////////////////////////////////////////////////////////// +class Enumerator::SharedQueue : public mt::MultiQueue { +public: + typedef mt::MultiQueue BaseType; + explicit SharedQueue(uint32 m) : BaseType(m, releaseLits) { reserve(m + 1); } + bool pushRelaxed(SharedLiterals* clause) { unsafePublish(clause); return true; } + static void releaseLits(SharedLiterals* x){ x->release(); } +}; +class Enumerator::ThreadQueue { +public: + explicit ThreadQueue(SharedQueue& q) : queue_(&q) { tail_ = q.addThread(); } + bool pop(SharedLiterals*& out){ return queue_->tryConsume(tail_, out); } + ThreadQueue* clone() { return new ThreadQueue(*queue_); } +private: + Enumerator::SharedQueue* queue_; + Enumerator::SharedQueue::ThreadId tail_; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// EnumerationConstraint +///////////////////////////////////////////////////////////////////////////////////////// +EnumerationConstraint::EnumerationConstraint() : mini_(0), flags_(0), root_(0) { + setDisjoint(false); +} +EnumerationConstraint::~EnumerationConstraint() { } +void EnumerationConstraint::init(Solver& s, SharedMinimizeData* m, QueuePtr p) { + mini_ = 0; + queue_= p; + if (m) { + const SolverParams* c = s.sharedContext()->configuration() ? &s.sharedContext()->configuration()->solver(s.id()) : 0; + MinimizeMode_t::Strategy st = c ? static_cast(c->optStrat) : MinimizeMode_t::opt_bb; + mini_ = m->attach(s, st, c ? c->optParam : 0u); + if (c && (c->optHeu & MinimizeMode_t::heu_sign) != 0) { + for (const WeightLiteral* it = m->lits; !isSentinel(it->first); ++it) { + s.setPref(it->first.var(), ValueSet::pref_value, falseValue(it->first)); + } + } + if (c && (c->optHeu & MinimizeMode_t::heu_model) != 0) { flags_ |= uint32(flag_model_heuristic); } + else { flags_ &= ~uint32(flag_model_heuristic);} + } +} +bool EnumerationConstraint::valid(Solver& s) { return !optimize() || mini_->valid(s); } +void EnumerationConstraint::add(Constraint* c) { if (c) { nogoods_.push_back(c); } } +bool EnumerationConstraint::integrateBound(Solver& s){ return !mini_ || mini_->integrate(s); } +bool EnumerationConstraint::optimize() const { return mini_ && mini_->shared()->optimize(); } +void EnumerationConstraint::setDisjoint(bool x) { + if (x) { flags_ |= uint32(flag_path_disjoint); } + else { flags_ &= ~uint32(flag_path_disjoint); } +} +Constraint* EnumerationConstraint::cloneAttach(Solver& s) { + EnumerationConstraint* c = clone(); + CLASP_FAIL_IF(c == 0, "Cloning not supported by Enumerator"); + c->init(s, mini_ ? const_cast(mini_->shared()) : 0, queue_.get() ? queue_->clone() : 0); + return c; +} +void EnumerationConstraint::end(Solver& s) { + if (mini_) { mini_->relax(s, disjointPath()); } + flags_ = 0; + next_.clear(); + if (s.rootLevel() > root_) { s.popRootLevel(s.rootLevel() - root_); } +} +bool EnumerationConstraint::start(Solver& s, const LitVec& path, bool disjoint) { + flags_ = 0; + root_ = s.rootLevel(); + setDisjoint(disjoint); + if (s.pushRoot(path) && s.pushRoot(s.sharedContext()->stepLiteral())) { + integrateBound(s); + return true; + } + return false; +} +bool EnumerationConstraint::update(Solver& s) { + ValueRep st = state(); + if (st == value_true) { + if (s.restartOnModel()) { s.undoUntil(0); } + if (optimize()) { s.strengthenConditional(); } + } + else if (st == value_false && !s.pushRoot(next_)) { + if (!s.hasConflict()) { s.setStopConflict(); } + return false; + } + flags_ &= uint32(clear_state_mask); + next_.clear(); + do { + if (!s.hasConflict() && doUpdate(s) && integrateBound(s) && integrateNogoods(s)) { + if (st == value_true) { modelHeuristic(s); } + return true; + } + } while (st != value_free && s.hasConflict() && s.resolveConflict()); + return false; +} +bool EnumerationConstraint::integrateNogoods(Solver& s) { + if (!queue_.get() || s.hasConflict()) { return !s.hasConflict(); } + const uint32 f = ClauseCreator::clause_no_add | ClauseCreator::clause_no_release | ClauseCreator::clause_explicit; + for (SharedLiterals* clause; queue_->pop(clause); ) { + ClauseCreator::Result res = ClauseCreator::integrate(s, clause, f); + if (res.local) { add(res.local);} + if (!res.ok()) { return false; } + } + return true; +} +void EnumerationConstraint::destroy(Solver* s, bool x) { + if (mini_) { mini_->destroy(s, x); mini_ = 0; } + queue_ = 0; + Clasp::destroyDB(nogoods_, s, x); + Constraint::destroy(s, x); +} +bool EnumerationConstraint::simplify(Solver& s, bool reinit) { + if (mini_) { mini_->simplify(s, reinit); } + simplifyDB(s, nogoods_, reinit); + return false; +} + +bool EnumerationConstraint::commitModel(Enumerator& ctx, Solver& s) { + if (state() == value_true) { return !next_.empty() && (s.satPrepro()->extendModel(s.model, next_), true); } + if (mini_ && !mini_->handleModel(s)){ return false; } + if (!ctx.tentative()) { doCommitModel(ctx, s); } + next_ = s.symmetric(); + flags_|= value_true; + return true; +} +bool EnumerationConstraint::commitUnsat(Enumerator& ctx, Solver& s) { + next_.clear(); + flags_ |= value_false; + if (mini_) { + mini_->handleUnsat(s, !disjointPath(), next_); + } + if (!ctx.tentative()) { + doCommitUnsat(ctx, s); + } + return !s.hasConflict() || s.decisionLevel() != s.rootLevel(); +} +void EnumerationConstraint::modelHeuristic(Solver& s) { + const bool full = (flags_ & uint32(flag_model_heuristic)) != 0; + const bool heuristic = full || (s.queueSize() == 0 && s.decisionLevel() == s.rootLevel()); + if (optimize() && heuristic && s.propagate()) { + for (const WeightLiteral* w = mini_->shared()->lits; !isSentinel(w->first); ++w) { + if (s.value(w->first.var()) == value_free) { + s.assume(~w->first); + if (!full || !s.propagate()) { break; } + } + } + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// Enumerator +///////////////////////////////////////////////////////////////////////////////////////// +void Model::reset() { std::memset(this, 0, sizeof(Model)); } +Enumerator::Enumerator() : mini_(0), queue_(0) { model_.reset(); } +Enumerator::~Enumerator() { delete queue_; } +void Enumerator::setDisjoint(Solver& s, bool b)const { constraint(s)->setDisjoint(b); } +void Enumerator::setIgnoreSymmetric(bool b) { model_.sym = static_cast(b == false); } +void Enumerator::end(Solver& s) const { constraint(s)->end(s); } +void Enumerator::doReset() {} +void Enumerator::reset() { + if (mini_) { mini_ = 0; } + if (queue_){ delete queue_; queue_ = 0; } + model_.reset(); + model_.ctx = this; + model_.sym = 1; + model_.type = uint32(modelType()); + model_.sId = 0; + doReset(); +} +int Enumerator::init(SharedContext& ctx, OptMode oMode, int limit) { + ctx.master()->setEnumerationConstraint(0); + reset(); + if (oMode != MinimizeMode_t::ignore){ mini_ = ctx.minimize(); } + limit = limit >= 0 ? limit : 1 - int(exhaustive()); + if (limit != 1) { ctx.setPreserveModels(true); } + queue_ = new SharedQueue(ctx.concurrency()); + ConPtr c = doInit(ctx, mini_, limit); + bool cons = model_.consequences(); + if (tentative()) { model_.type = Model::Sat; } + else if (cons && optimize()) { ctx.warn("Optimization: Consequences may depend on enumeration order."); } + c->init(*ctx.master(), mini_, new ThreadQueue(*queue_)); + ctx.master()->setEnumerationConstraint(c); + return limit; +} +Enumerator::ConPtr Enumerator::constraint(const Solver& s) const { + return static_cast(s.enumerationConstraint()); +} +bool Enumerator::start(Solver& s, const LitVec& path, bool disjointPath) const { + return constraint(s)->start(s, path, disjointPath); +} +ValueRep Enumerator::commit(Solver& s) { + if (s.hasConflict() && s.decisionLevel() == s.rootLevel()) { return commitUnsat(s) ? value_free : value_false; } + else if (s.numFreeVars() == 0 && s.queueSize() == 0 && !s.hasConflict()){ return commitModel(s) ? value_true : value_free; } + return value_free; +} +bool Enumerator::commitModel(Solver& s) { + assert(s.numFreeVars() == 0 && !s.hasConflict() && s.queueSize() == 0 && constraint(s)); + if (constraint(s)->commitModel(*this, s)) { + s.stats.addModel(s.decisionLevel()); + ++model_.num; + model_.sId = s.id(); + model_.values = &s.model; + model_.costs = 0; + model_.up = 0; + if (minimizer()) { + costs_.resize(minimizer()->numRules()); + std::transform(minimizer()->adjust(), minimizer()->adjust()+costs_.size(), minimizer()->sum(), costs_.begin(), std::plus()); + model_.costs = &costs_; + } + return true; + } + return false; +} +bool Enumerator::commitSymmetric(Solver& s){ return model_.sym && !optimize() && commitModel(s); } +bool Enumerator::commitUnsat(Solver& s) { return constraint(s)->commitUnsat(*this, s); } +bool Enumerator::commitClause(const LitVec& clause) const { + return queue_ && queue_->pushRelaxed(SharedLiterals::newShareable(clause, Constraint_t::Other)); +} +bool Enumerator::commitComplete() { + if (enumerated()) { + if (tentative()) { + mini_->markOptimal(); + model_.opt = 1; + model_.num = 0; + model_.type= uint32(modelType()); + return false; + } + else if (model_.consequences() || (!model_.opt && optimize())) { + model_.opt = uint32(optimize()); + model_.def = uint32(model_.consequences()); + model_.num = 1; + } + } + return true; +} +bool Enumerator::update(Solver& s) const { + return constraint(s)->update(s); +} +bool Enumerator::supportsSplitting(const SharedContext& ctx) const { + if (!optimize()) { return true; } + const Configuration* config = ctx.configuration(); + bool ok = true; + for (uint32 i = 0; i != ctx.concurrency() && ok; ++i) { + if (ctx.hasSolver(i) && constraint(*ctx.solver(i))){ ok = constraint(*ctx.solver(i))->minimizer()->supportsSplitting(); } + else if (config && i < config->numSolver()) { ok = MinimizeMode_t::supportsSplitting(static_cast(config->solver(i).optStrat)); } + } + return ok; +} +int Enumerator::unsatType() const { + return !optimize() ? unsat_stop : unsat_cont; +} +Model& Enumerator::model() { + return model_; +} +///////////////////////////////////////////////////////////////////////////////////////// +// EnumOptions +///////////////////////////////////////////////////////////////////////////////////////// +Enumerator* EnumOptions::createEnumerator(const EnumOptions& opts) { + if (opts.models()) { return createModelEnumerator(opts);} + else if (opts.consequences()){ return createConsEnumerator(opts); } + else { return nullEnumerator(); } +} +Enumerator* EnumOptions::nullEnumerator() { + struct NullEnum : Enumerator { + ConPtr doInit(SharedContext&, SharedMinimizeData*, int) { + struct Constraint : public EnumerationConstraint { + Constraint() : EnumerationConstraint() {} + ConPtr clone() { return new Constraint(); } + bool doUpdate(Solver&){ return true; } + }; + return new Constraint(); + } + }; + return new NullEnum; +} + +const char* modelType(const Model& m) { + switch (m.type) { + case Model::Sat : return "Model"; + case Model::Brave : return "Brave"; + case Model::Cautious: return "Cautious"; + case Model::User : return "User"; + default: return 0; + } +} + +} diff --git a/libclasp/src/heuristics.cpp b/libclasp/src/heuristics.cpp new file mode 100644 index 0000000..ecf6255 --- /dev/null +++ b/libclasp/src/heuristics.cpp @@ -0,0 +1,951 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Lookback selection strategies +///////////////////////////////////////////////////////////////////////////////////////// +uint32 momsScore(const Solver& s, Var v) { + uint32 sc; + if (s.sharedContext()->numBinary()) { + uint32 s1 = s.estimateBCP(posLit(v), 0) - 1; + uint32 s2 = s.estimateBCP(negLit(v), 0) - 1; + sc = ((s1 * s2)<<10) + (s1 + s2); + } + else { + // problem does not contain binary constraints - fall back to counting watches + uint32 s1 = s.numWatches(posLit(v)); + uint32 s2 = s.numWatches(negLit(v)); + sc = ((s1 * s2)<<10) + (s1 + s2); + } + return sc; +} +static void addOther(TypeSet& t, uint32 other) { + if (other != HeuParams::other_no) { t.addSet(Constraint_t::Loop); } + if (other == HeuParams::other_all) { t.addSet(Constraint_t::Other); } +} +///////////////////////////////////////////////////////////////////////////////////////// +// Berkmin selection strategy +///////////////////////////////////////////////////////////////////////////////////////// +#define BERK_NUM_CANDIDATES 5 +#define BERK_CACHE_GROW 2.0 +#define BERK_MAX_MOMS_VARS 9999 +#define BERK_MAX_MOMS_DECS 50 +#define BERK_MAX_DECAY 65534 + +ClaspBerkmin::ClaspBerkmin(const HeuParams& params) + : topConflict_(UINT32_MAX) + , topOther_(UINT32_MAX) + , front_(1) + , cacheSize_(5) + , numVsids_(0) { + ClaspBerkmin::setConfig(params); +} + +void ClaspBerkmin::setConfig(const HeuParams& params) { + maxBerkmin_ = params.param == 0 ? UINT32_MAX : params.param; + order_.nant = params.nant != 0; + order_.huang = params.huang != 0; + order_.resScore = params.score == HeuParams::score_auto ? static_cast(HeuParams::score_multi_set) : params.score; + addOther(types_ = TypeSet(), params.other); + if (params.moms) { types_.addSet(Constraint_t::Static); } +} + +Var ClaspBerkmin::getMostActiveFreeVar(const Solver& s) { + ++numVsids_; + // first: check for a cache hit + for (Pos end = cache_.end(); cacheFront_ != end; ++cacheFront_) { + if (s.value(*cacheFront_) == value_free) { + return *cacheFront_; + } + } + // Second: cache miss - refill cache with most active vars + if (!cache_.empty() && cacheSize_ < s.numFreeVars()/10) { + cacheSize_ = static_cast( (cacheSize_*BERK_CACHE_GROW) + .5 ); + } + cache_.clear(); + Order::Compare comp(&order_); + // Pre: At least one unassigned var! + for (; s.value( front_ ) != value_free; ++front_) {;} + Var v = front_; + LitVec::size_type cs = std::min(cacheSize_, s.numFreeVars()); + for (;;) { // add first cs free variables to cache + cache_.push_back(v); + std::push_heap(cache_.begin(), cache_.end(), comp); + if (cache_.size() == cs) break; + while ( s.value(++v) != value_free ) {;} // skip over assigned vars + } + for (v = (cs == cacheSize_ ? v+1 : s.numVars()+1); v <= s.numVars(); ++v) { + // replace vars with low activity + if (s.value(v) == value_free && comp(v, cache_[0])) { + std::pop_heap(cache_.begin(), cache_.end(), comp); + cache_.back() = v; + std::push_heap(cache_.begin(), cache_.end(), comp); + } + } + std::sort_heap(cache_.begin(), cache_.end(), comp); + return *(cacheFront_ = cache_.begin()); +} + +Var ClaspBerkmin::getTopMoms(const Solver& s) { + // Pre: At least one unassigned var! + for (; s.value( front_ ) != value_free; ++front_) {;} + Var var = front_; + uint32 ms = momsScore(s, var); + uint32 ls = 0; + for (Var v = var+1; v <= s.numProblemVars(); ++v) { + if (s.value(v) == value_free && (ls = momsScore(s, v)) > ms) { + var = v; + ms = ls; + } + } + if (++numVsids_ >= BERK_MAX_MOMS_DECS || ms < 2) { + // Scores are not relevant or too many moms-based decisions + // - disable MOMS + hasActivities(true); + } + return var; +} + +void ClaspBerkmin::startInit(const Solver& s) { + if (order_.score.empty()) { + rng_.srand(s.rng.seed()); + } + order_.score.resize(s.numVars()+1); + initHuang(order_.huang); + + cache_.clear(); + cacheSize_ = 5; + cacheFront_ = cache_.end(); + + freeLits_.clear(); + freeOtherLits_.clear(); + topConflict_ = topOther_ = (uint32)-1; + + front_ = 1; + numVsids_ = 0; +} + +void ClaspBerkmin::endInit(Solver& s) { + if (initHuang()) { + const bool clearScore = types_.inSet(Constraint_t::Static); + // initialize preferred values of vars + cache_.clear(); + for (Var v = 1; v <= s.numVars(); ++v) { + order_.decayedScore(v); + if (order_.occ(v) != 0 && s.pref(v).get(ValueSet::saved_value) == value_free) { + s.setPref(v, ValueSet::saved_value, order_.occ(v) > 0 ? value_true : value_false); + } + if (clearScore) order_.score[v] = HScore(order_.decay); + else cache_.push_back(v); + } + initHuang(false); + } + if (!types_.inSet(Constraint_t::Static) || s.numFreeVars() > BERK_MAX_MOMS_VARS) { + hasActivities(true); + } + std::stable_sort(cache_.begin(), cache_.end(), Order::Compare(&order_)); + cacheFront_ = cache_.begin(); +} + +void ClaspBerkmin::updateVar(const Solver& s, Var v, uint32 n) { + if (s.validVar(v)) { growVecTo(order_.score, v+n); } + front_ = 1; + cache_.clear(); + cacheFront_ = cache_.end(); +} + +void ClaspBerkmin::newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t) { + if (t == Constraint_t::Conflict) { hasActivities(true); } + if ((t == Constraint_t::Conflict && order_.resScore == HeuParams::score_min) + || (t == Constraint_t::Static && order_.huang)) { + for (const Literal* x = first, *end = first+size; x != end; ++x) { + order_.inc(*x, s.varInfo(x->var()).nant()); + } + } + if (t != Constraint_t::Static && !order_.huang) { + for (const Literal* x = first, *end = first+size; x != end; ++x) { order_.incOcc(*x); } + } +} + +void ClaspBerkmin::updateReason(const Solver& s, const LitVec& lits, Literal r) { + if (order_.resScore > HeuParams::score_min) { + const bool ms = order_.resScore == HeuParams::score_multi_set; + for (LitVec::size_type i = 0, e = lits.size(); i != e; ++i) { + if (ms || !s.seen(lits[i])) { order_.inc(~lits[i], s.varInfo(lits[i].var()).nant()); } + } + } + if ((order_.resScore & 1u) != 0 && !isSentinel(r)) { + order_.inc(r, s.varInfo(r.var()).nant()); + } +} + +bool ClaspBerkmin::bump(const Solver& s, const WeightLitVec& lits, double adj) { + for (WeightLitVec::const_iterator it = lits.begin(), end = lits.end(); it != end; ++it) { + if (!order_.nant || s.varInfo(it->first.var()).nant()) { + uint32 xf = order_.decayedScore(it->first.var()) + static_cast(it->second*adj); + order_.score[it->first.var()].act = (uint16)std::min(xf, UINT32_MAX>>16); + } + } + return true; +} + +void ClaspBerkmin::undoUntil(const Solver&, LitVec::size_type) { + topConflict_ = topOther_ = static_cast(-1); + front_ = 1; + cache_.clear(); + cacheFront_ = cache_.end(); + if (cacheSize_ > 5 && numVsids_ > 0 && (numVsids_*3) < cacheSize_) { + cacheSize_ = static_cast(cacheSize_/BERK_CACHE_GROW); + } + numVsids_ = 0; +} + +bool ClaspBerkmin::hasTopUnsat(Solver& s) { + topConflict_ = std::min(s.numLearntConstraints(), topConflict_); + topOther_ = std::min(s.numLearntConstraints(), topOther_); + assert(topConflict_ <= topOther_); + freeOtherLits_.clear(); + freeLits_.clear(); + TypeSet ts = types_; + if (ts.m > 1) { + while (topOther_ > topConflict_) { + if (s.getLearnt(topOther_-1).isOpen(s, ts, freeLits_) != 0) { + freeLits_.swap(freeOtherLits_); + ts.m = 0; + break; + } + --topOther_; + freeLits_.clear(); + } + } + ts.addSet(Constraint_t::Conflict); + uint32 stopAt = topConflict_ < maxBerkmin_ ? 0 : topConflict_ - maxBerkmin_; + while (topConflict_ != stopAt) { + uint32 x = s.getLearnt(topConflict_-1).isOpen(s, ts, freeLits_); + if (x != 0) { + if (x == Constraint_t::Conflict) { break; } + topOther_ = topConflict_; + freeLits_.swap(freeOtherLits_); + ts.m = 0; + ts.addSet(Constraint_t::Conflict); + } + --topConflict_; + freeLits_.clear(); + } + if (freeOtherLits_.empty()) topOther_ = topConflict_; + if (freeLits_.empty()) freeOtherLits_.swap(freeLits_); + return !freeLits_.empty(); +} + +Literal ClaspBerkmin::doSelect(Solver& s) { + const uint32 decayMask = order_.huang ? 127 : 511; + if ( ((s.stats.choices + 1)&decayMask) == 0 ) { + if ((order_.decay += (1+!order_.huang)) == BERK_MAX_DECAY) { + order_.resetDecay(); + } + } + if (hasTopUnsat(s)) { // Berkmin based decision + assert(!freeLits_.empty()); + Literal x = selectRange(s, &freeLits_[0], &freeLits_[0]+freeLits_.size()); + return selectLiteral(s, x.var(), false); + } + else if (hasActivities()) { // Vsids based decision + return selectLiteral(s, getMostActiveFreeVar(s), true); + } + else { // Moms based decision + return selectLiteral(s, getTopMoms(s), true); + } +} + +Literal ClaspBerkmin::selectRange(Solver& s, const Literal* first, const Literal* last) { + Literal candidates[BERK_NUM_CANDIDATES]; + candidates[0] = *first; + uint32 c = 1; + uint32 ms = static_cast(-1); + uint32 ls = 0; + for (++first; first != last; ++first) { + Var v = first->var(); + assert(s.value(v) == value_free); + int cmp = order_.compare(v, candidates[0].var()); + if (cmp > 0) { + candidates[0] = *first; + c = 1; + ms = static_cast(-1); + } + else if (cmp == 0) { + if (ms == static_cast(-1)) ms = momsScore(s, candidates[0].var()); + if ( (ls = momsScore(s,v)) > ms) { + candidates[0] = *first; + c = 1; + ms = ls; + } + else if (ls == ms && c != BERK_NUM_CANDIDATES) { + candidates[c++] = *first; + } + } + } + return c == 1 ? candidates[0] : candidates[rng_.irand(c)]; +} + +Literal ClaspBerkmin::selectLiteral(Solver& s, Var v, bool vsids) const { + ValueSet pref = s.pref(v); + int signScore = order_.occ(v); + if (order_.huang && std::abs(signScore) > 32 && !pref.has(ValueSet::user_value)) { + return Literal(v, signScore < 0); + } + // compute expensive sign score only if necessary + if (vsids && !pref.has(ValueSet::user_value | ValueSet::pref_value | ValueSet::saved_value)) { + int32 w0 = (int32)s.estimateBCP(posLit(v), 5); + int32 w1 = (int32)s.estimateBCP(negLit(v), 5); + if (w1 != 1 || w0 != w1) { signScore = w0 - w1; } + } + return DecisionHeuristic::selectLiteral(s, v, signScore); +} + +void ClaspBerkmin::Order::resetDecay() { + for (Scores::size_type i = 1, end = score.size(); i < end; ++i) { + decayedScore(i); + score[i].dec = 0; + } + decay = 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspVmtf selection strategy +///////////////////////////////////////////////////////////////////////////////////////// +ClaspVmtf::ClaspVmtf(const HeuParams& params) : decay_(0) { + ClaspVmtf::setConfig(params); +} + +void ClaspVmtf::setConfig(const HeuParams& params) { + nMove_ = params.param ? std::max(params.param, uint32(2)) : 8u; + scType_ = params.score != HeuParams::score_auto ? params.score : static_cast(HeuParams::score_min); + nant_ = params.nant != 0; + addOther(types_ = TypeSet(), params.other != HeuParams::other_auto ? params.other : static_cast(HeuParams::other_no)); + if (params.moms) { types_.addSet(Constraint_t::Static); } + if (scType_ == HeuParams::score_min) { types_.addSet(Constraint_t::Conflict); } +} + +void ClaspVmtf::startInit(const Solver& s) { + score_.resize(s.numVars()+1, VarInfo(vars_.end())); +} + +void ClaspVmtf::endInit(Solver& s) { + bool moms = types_.inSet(Constraint_t::Static); + for (Var v = 1; v <= s.numVars(); ++v) { + if (s.value(v) == value_free && score_[v].pos_ == vars_.end()) { + score_[v].activity(decay_); + if (moms) { + score_[v].activity_ = momsScore(s, v); + score_[v].decay_ = decay_+1; + } + score_[v].pos_ = vars_.insert(vars_.end(), v); + } + } + if (moms) { + vars_.sort(LessLevel(s, score_)); + for (VarList::iterator it = vars_.begin(), end = vars_.end(); it != end; ++it) { + if (score_[*it].decay_ != decay_) { + score_[*it].activity_ = 0; + score_[*it].decay_ = decay_; + } + } + } + front_ = vars_.begin(); +} + +void ClaspVmtf::updateVar(const Solver& s, Var v, uint32 n) { + if (s.validVar(v)) { + growVecTo(score_, v+n, VarInfo(vars_.end())); + for (uint32 end = v+n; v != end; ++v) { + if (score_[v].pos_ == vars_.end()) { score_[v].pos_ = vars_.insert(vars_.end(), v); } + else { front_ = vars_.begin(); } + } + } + else if (v < score_.size()) { + if ((v + n) > score_.size()) { n = score_.size() - v; } + for (uint32 x = v + n; x-- != v; ) { + if (score_[x].pos_ != vars_.end()) { + vars_.erase(score_[x].pos_); + score_[x].pos_ = vars_.end(); + } + } + } +} + +void ClaspVmtf::simplify(const Solver& s, LitVec::size_type i) { + for (; i < s.numAssignedVars(); ++i) { + if (score_[s.trail()[i].var()].pos_ != vars_.end()) { + vars_.erase(score_[s.trail()[i].var()].pos_); + score_[s.trail()[i].var()].pos_ = vars_.end(); + } + } + front_ = vars_.begin(); +} + +void ClaspVmtf::newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t) { + if (t != Constraint_t::Static) { + LessLevel comp(s, score_); + const bool upAct = types_.inSet(t); + const VarVec::size_type mtf = t == Constraint_t::Conflict ? nMove_ : (nMove_*uint32(upAct))/2; + for (LitVec::size_type i = 0; i < size; ++i, ++first) { + Var v = first->var(); + score_[v].occ_ += 1 - (((int)first->sign())<<1); + if (upAct) { ++score_[v].activity(decay_); } + if (mtf && (!nant_ || s.varInfo(v).nant())){ + if (mtf_.size() < mtf) { + mtf_.push_back(v); + std::push_heap(mtf_.begin(), mtf_.end(), comp); + } + else if (comp(v, mtf_[0])) { + assert(s.level(v) <= s.level(mtf_[0])); + std::pop_heap(mtf_.begin(), mtf_.end(), comp); + mtf_.back() = v; + std::push_heap(mtf_.begin(), mtf_.end(), comp); + } + } + } + for (VarVec::size_type i = 0; i != mtf_.size(); ++i) { + Var v = mtf_[i]; + if (score_[v].pos_ != vars_.end()) { + vars_.splice(vars_.begin(), vars_, score_[v].pos_); + } + } + mtf_.clear(); + front_ = vars_.begin(); + } +} + +void ClaspVmtf::undoUntil(const Solver&, LitVec::size_type) { + front_ = vars_.begin(); +} + +void ClaspVmtf::updateReason(const Solver& s, const LitVec& lits, Literal r) { + if (scType_ > HeuParams::score_min) { + const bool ms = scType_ == HeuParams::score_multi_set; + const uint32 D = decay_; + for (LitVec::size_type i = 0, e = lits.size(); i != e; ++i) { + if (ms || !s.seen(lits[i])) { ++score_[lits[i].var()].activity(D); } + } + } + if (scType_ & 1u) { ++score_[r.var()].activity(decay_); } +} + +bool ClaspVmtf::bump(const Solver&, const WeightLitVec& lits, double adj) { + for (WeightLitVec::const_iterator it = lits.begin(), end = lits.end(); it != end; ++it) { + score_[it->first.var()].activity(decay_) += static_cast(it->second*adj); + } + return true; +} + +Literal ClaspVmtf::doSelect(Solver& s) { + decay_ += ((s.stats.choices + 1) & 511) == 0; + for (; s.value(*front_) != value_free; ++front_) {;} + Literal c; + if (s.numFreeVars() > 1) { + VarList::iterator v2 = front_; + uint32 distance = 0; + do { + ++v2; + ++distance; + } while (s.value(*v2) != value_free); + c = (score_[*front_].activity(decay_) + (distance<<1)+ 3) > score_[*v2].activity(decay_) + ? selectLiteral(s, *front_, score_[*front_].occ_) + : selectLiteral(s, *v2, score_[*v2].occ_); + } + else { + c = selectLiteral(s, *front_, score_[*front_].occ_); + } + return c; +} + +Literal ClaspVmtf::selectRange(Solver&, const Literal* first, const Literal* last) { + Literal best = *first; + for (++first; first != last; ++first) { + if (score_[first->var()].activity(decay_) > score_[best.var()].activity(decay_)) { + best = *first; + } + } + return best; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspVsids selection strategy +///////////////////////////////////////////////////////////////////////////////////////// +static double initDecay(uint32 p) { + double m = static_cast(p ? p : 0.95); + while (m > 1.0) { m /= 10.0; } + return m; +} + +template +ClaspVsids_t::ClaspVsids_t(const HeuParams& params) + : vars_(CmpScore(score_)) + , inc_(1.0) + , acids_(false) { + ClaspVsids_t::setConfig(params); +} + +template +void ClaspVsids_t::setConfig(const HeuParams& params) { + addOther(types_ = TypeSet(), params.other != HeuParams::other_auto ? params.other : static_cast(HeuParams::other_no)); + scType_ = params.score != HeuParams::score_auto ? params.score : static_cast(HeuParams::score_min); + decay_ = Decay(params.decay.init ? initDecay(params.decay.init) : 0.0, initDecay(params.param), params.decay.bump, params.decay.freq); + acids_ = params.acids != 0; + nant_ = params.nant != 0; + if (params.moms) { types_.addSet(Constraint_t::Static); } + if (scType_ == HeuParams::score_min) { types_.addSet(Constraint_t::Conflict); } +} + +template +void ClaspVsids_t::startInit(const Solver& s) { + score_.resize(s.numVars()+1); + occ_.resize(s.numVars()+1); + vars_.reserve(s.numVars() + 1); +} + +template +void ClaspVsids_t::endInit(Solver& s) { + vars_.clear(); + initScores(s, types_.inSet(Constraint_t::Static)); + double mx = 0; + for (Var v = 1; v <= s.numVars(); ++v) { + if (s.value(v) != value_free) { continue; } + mx = std::max(mx, score_[v].get()); + if (!vars_.is_in_queue(v)) { vars_.push(v); } + } + if (acids_ && mx > inc_) { + inc_ = std::ceil(mx); + } +} +template +void ClaspVsids_t::updateVarActivity(const Solver& s, Var v, double f) { + if (!nant_ || s.varInfo(v).nant()) { + double o = score_[v].get(), n; + f = ScoreType::applyFactor(score_, v, f); + if (!acids_) { n = o + (f * inc_); } + else if (f == 1.0) { n = (o + inc_) / 2.0; } + else if (f != 0.0) { n = std::max( (o + inc_ + f) / 2.0, f + o ); } + else { return; } + score_[v].set(n); + if (n > 1e100) { normalize(); } + if (vars_.is_in_queue(v)) { + if (n >= o) { vars_.increase(v); } + else { vars_.decrease(v); } + } + } +} +template +void ClaspVsids_t::updateVar(const Solver& s, Var v, uint32 n) { + if (s.validVar(v)) { + growVecTo(score_, v+n); + growVecTo(occ_, v+n); + for (uint32 end = v+n; v != end; ++v) { vars_.update(v); } + } + else { + for (uint32 end = v+n; v != end; ++v) { vars_.remove(v); } + } +} +template +void ClaspVsids_t::initScores(Solver& s, bool moms) { + if (!moms) { return; } + double maxS = 0.0, ms; + for (Var v = 1; v <= s.numVars(); ++v) { + if (s.value(v) == value_free && score_[v].get() == 0.0 && (ms = (double)momsScore(s, v)) != 0.0) { + maxS = std::max(maxS, ms); + score_[v].set(-ms); + } + } + for (Var v = 1; v <= s.numVars(); ++v) { + double d = score_[v].get(); + if (d < 0) { + d *= -1.0; + d /= maxS; + score_[v].set(d); + } + } +} +template +void ClaspVsids_t::simplify(const Solver& s, LitVec::size_type i) { + for (; i < s.numAssignedVars(); ++i) { + vars_.remove(s.trail()[i].var()); + } +} + +template +void ClaspVsids_t::normalize() { + const double min = std::numeric_limits::min(); + const double minD = min * 1e100; + inc_ *= 1e-100; + for (LitVec::size_type i = 0; i != score_.size(); ++i) { + double d = score_[i].get(); + if (d > 0) { + // keep relative ordering but + // actively avoid denormals + d += minD; + d *= 1e-100; + } + score_[i].set(d); + } +} +template +void ClaspVsids_t::newConstraint(const Solver& s, const Literal* first, LitVec::size_type size, ConstraintType t) { + if (t != Constraint_t::Static) { + const bool upAct = types_.inSet(t); + for (LitVec::size_type i = 0; i < size; ++i, ++first) { + incOcc(*first); + if (upAct) { + updateVarActivity(s, first->var()); + } + } + if (t == Constraint_t::Conflict) { + if (decay_.next && --decay_.next == 0 && decay_.lo < decay_.hi) { + decay_.lo += decay_.bump / 100.0; + decay_.next = decay_.freq; + decay_.df = 1.0 / decay_.lo; + } + if (!acids_) { inc_ *= decay_.df; } + else { inc_ += 1.0; } + } + } +} +template +void ClaspVsids_t::updateReason(const Solver& s, const LitVec& lits, Literal r) { + if (scType_ > HeuParams::score_min) { + const bool ms = scType_ == HeuParams::score_multi_set; + for (LitVec::size_type i = 0, end = lits.size(); i != end; ++i) { + if (ms || !s.seen(lits[i])) { updateVarActivity(s, lits[i].var()); } + } + } + if ((scType_ & 1u) != 0 && r.var() != 0) { updateVarActivity(s, r.var()); } +} +template +bool ClaspVsids_t::bump(const Solver& s, const WeightLitVec& lits, double adj) { + double mf = 1.0, f; + for (WeightLitVec::const_iterator it = lits.begin(), end = lits.end(); it != end; ++it) { + updateVarActivity(s, it->first.var(), (f = it->second*adj)); + if (acids_ && f > mf) { mf = f; } + } + if (acids_ && mf > 1.0) { + inc_ = std::ceil(mf + inc_); + } + return true; +} +template +void ClaspVsids_t::undoUntil(const Solver& s , LitVec::size_type st) { + const LitVec& a = s.trail(); + for (; st < a.size(); ++st) { + if (!vars_.is_in_queue(a[st].var())) { + vars_.push(a[st].var()); + } + } +} +template +Literal ClaspVsids_t::doSelect(Solver& s) { + while ( s.value(vars_.top()) != value_free ) { + vars_.pop(); + } + return selectLiteral(s, vars_.top(), occ(vars_.top())); +} +template +Literal ClaspVsids_t::selectRange(Solver&, const Literal* first, const Literal* last) { + Literal best = *first; + for (++first; first != last; ++first) { + if (vars_.key_compare()(first->var(), best.var())) { + best = *first; + } + } + return best; +} +template class ClaspVsids_t; + +///////////////////////////////////////////////////////////////////////////////////////// +// DomainHeuristic selection strategy +///////////////////////////////////////////////////////////////////////////////////////// +DomainHeuristic::DomainHeuristic(const HeuParams& params) : ClaspVsids_t(params), domSeen_(0), defMax_(0), defMod_(0), defPref_(0) { + frames_.push_back(Frame(0,DomAction::UNDO_NIL)); + setDefaultMod(static_cast(params.domMod), params.domPref); +} +DomainHeuristic::~DomainHeuristic() {} + +void DomainHeuristic::setConfig(const HeuParams& params) { + ClaspVsids_t::setConfig(params); + setDefaultMod(static_cast(params.domMod), params.domPref); +} +void DomainHeuristic::setDefaultMod(HeuParams::DomMod mod, uint32 prefSet) { + defMod_ = (uint16)mod; + defPref_= prefSet; +} +void DomainHeuristic::detach(Solver& s) { + if (!actions_.empty()) { + for (DomainTable::iterator it = s.sharedContext()->heuristic.begin(), end = s.sharedContext()->heuristic.end(); it != end; ++it) { + if (it->hasCondition()) { + s.removeWatch(it->cond(), this); + } + } + } + while (frames_.back().dl != 0) { + s.removeUndoWatch(frames_.back().dl, this); + frames_.pop_back(); + } + Var end = std::min(static_cast(score_.size()), static_cast(s.numVars() + 1)); + for (Var v = 1; v != end; ++v) { + if (score_[v].sign) { s.setPref(v, ValueSet::user_value, value_free); } + } + actions_.clear(); + prios_.clear(); + domSeen_ = 0; + defMax_ = 0; +} +void DomainHeuristic::startInit(const Solver& s) { + BaseType::startInit(s); + domSeen_ = std::min(domSeen_, s.sharedContext()->heuristic.size()); +} +void DomainHeuristic::initScores(Solver& s, bool moms) { + const DomainTable& domTab = s.sharedContext()->heuristic; + BaseType::initScores(s, moms); + uint32 nKey = (uint32)prios_.size(); + if (defMax_) { + defMax_ = std::min(defMax_, s.numVars()) + 1; + for (Var v = 1; v != defMax_; ++v) { + if (score_[v].domP >= nKey) { + bool sign = score_[v].sign; + score_[v] = DomScore(score_[v].value); + if (sign) { s.setPref(v, ValueSet::user_value, value_free); } + } + } + defMax_ = 0; + } + if (domSeen_ < domTab.size()) { + // apply new domain modifications + VarScoreVec saved; + Literal lastW = lit_true(); + uint32 dKey = nKey; + for (DomainTable::iterator it = domTab.begin() + domSeen_, end = domTab.end(); it != end; ++it) { + if (s.topValue(it->var()) != value_free || s.isFalse(it->cond())) { + continue; + } + if (score_[it->var()].domP >= nKey){ + score_[it->var()].setDom(nKey++); + prios_.push_back(DomPrio()); + prios_.back().clear(); + } + uint32 k = addDomAction(*it, s, saved, lastW); + if (k > dKey) { dKey = k; } + } + for (VarScoreVec::value_type x; !saved.empty(); saved.pop_back()) { + x = saved.back(); + score_[x.first].value += x.second; + score_[x.first].init = 0; + } + if (!actions_.empty()) { + actions_.back().next = 0; + } + if ((nKey - dKey) > dKey && s.sharedContext()->solveMode() == SharedContext::solve_once) { + PrioVec(prios_.begin(), prios_.begin()+dKey).swap(prios_); + } + domSeen_ = domTab.size(); + } + // apply default modification + if (defMod_) { + typedef HeuParams Dom; + MinimizeConstraint* m = s.enumerationConstraint() ? static_cast(s.enumerationConstraint())->minimizer() : 0; + const uint32 prefSet = defPref_, graphSet = Dom::pref_scc | Dom::pref_hcc | Dom::pref_disj; + const uint32 userKey = nKey, graphKey = userKey + 1, minKey = userKey + 2, showKey = userKey + 3; + if ((prefSet & Dom::pref_show) != 0) { + const OutputTable& out = s.outputTable(); + for (OutputTable::pred_iterator it = out.pred_begin(), end = out.pred_end(); it != end; ++it) { + addDefAction(s, it->cond, Dom::pref_show, showKey); + } + for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) { + addDefAction(s, posLit(*it), Dom::pref_show, showKey); + } + } + if ((prefSet & Dom::pref_min) != 0 && m) { + weight_t w = -1; + int16 x = Dom::pref_show; + for (const WeightLiteral* it = m->shared()->lits; !isSentinel(it->first); ++it) { + if (x > 4 && it->second != w) { + --x; + w = it->second; + } + addDefAction(s, it->first, x, minKey); + } + } + if ((prefSet & graphSet) != 0 && s.sharedContext()->sccGraph.get()) { + for (uint32 i = 0; i != s.sharedContext()->sccGraph->numAtoms(); ++i) { + const PrgDepGraph::AtomNode& a = s.sharedContext()->sccGraph->getAtom(i); + int16 lev = 0; + if ((prefSet & Dom::pref_disj) != 0 && a.inDisjunctive()){ lev = 3; } + else if ((prefSet & Dom::pref_hcc) != 0 && a.inNonHcf()) { lev = 2; } + else if ((prefSet & Dom::pref_scc) != 0) { lev = 1; } + addDefAction(s, a.lit, lev, graphKey); + } + } + if (!prefSet) { + for (Var v = 1, end = s.numVars() + 1; v != end; ++v) { + if ((s.varInfo(v).type() & Var_t::Atom) != 0) { addDefAction(s, posLit(v), 1, userKey); } + } + } + } + if (&s == s.sharedContext()->master() && domTab.domRec) { + LitVec& min = *domTab.domRec; + for (Var v = 1, end = s.numVars() + 1; v != end; ++v) { + if (score_[v].sign && score_[v].level > 0 && s.value(v) == value_free) { + ValueRep val = s.pref(v).get(ValueSet::user_value); + if (val != value_false) { min.push_back(negLit(v)); } + if (val != value_true) { min.push_back(posLit(v)); } + } + } + } +} + +uint32 DomainHeuristic::addDomAction(const DomMod& e, Solver& s, VarScoreVec& initOut, Literal& lastW) { + if (e.comp()) { + DomMod level(e.var(), DomModType::Level, e.bias(), e.prio(), e.cond()); + DomMod sign(e.var(), DomModType::Sign, e.type() == DomModType::True ? 1 : -1, e.prio(), e.cond()); + uint32 k1 = addDomAction(level, s, initOut, lastW); + uint32 k2 = addDomAction(sign, s, initOut, lastW); + return std::max(k1, k2); + } + bool isStatic = !e.hasCondition() || s.topValue(e.cond().var()) == trueValue(e.cond()); + uint16& sPrio = prio(e.var(), e.type()); + if (e.prio() < sPrio || (!isStatic && e.type() == DomModType::Init)) { + return 0; + } + if (e.type() == DomModType::Init) { + if (score_[e.var()].init == 0) { + initOut.push_back(std::make_pair(e.var(), score_[e.var()].value)); + score_[e.var()].init = 1; + } + score_[e.var()].value = e.bias(); + return 0; + } + DomAction a = { e.var(), (uint32)e.type(), DomAction::UNDO_NIL, uint32(0), e.bias(), e.prio() }; + if (a.mod == DomModType::Sign && a.bias != 0) { + a.bias = a.bias > 0 ? value_true : value_false; + } + CLASP_FAIL_IF(e.type() != a.mod, "Invalid dom modifier!"); + if (isStatic) { + applyAction(s, a, sPrio); + score_[e.var()].sign |= static_cast(e.type() == DomModType::Sign); + return 0; + } + if (e.cond() != lastW) { + s.addWatch(lastW = e.cond(), this, (uint32)actions_.size()); + } + else { + actions_.back().next = 1; + } + actions_.push_back(a); + return score_[e.var()].domP + 1; +} + +void DomainHeuristic::addDefAction(Solver& s, Literal x, int16 lev, uint32 domKey) { + if (s.value(x.var()) != value_free || score_[x.var()].domP < domKey) { return; } + const bool signMod = defMod_ < HeuParams::mod_init && ((defMod_ & HeuParams::mod_init) != 0); + const bool valMod = defMod_ >= HeuParams::mod_init || ((defMod_ & HeuParams::mod_level)!= 0); + if (score_[x.var()].domP > domKey && lev && valMod) { + if (defMod_ < HeuParams::mod_init) { score_[x.var()].level += lev; } + else if (defMod_ == HeuParams::mod_init) { score_[x.var()].value += (lev*100); } + else if (defMod_ == HeuParams::mod_factor) { + int16 f = 1; + while (lev >>= 2) { ++f; } + score_[x.var()].factor += f; + } + } + if (signMod && score_[x.var()].sign == 0) { + s.setPref(x.var(), ValueSet::user_value, (defMod_ & HeuParams::mod_spos) != 0 ? trueValue(x) : falseValue(x)); + score_[x.var()].sign = 1; + } + if (x.var() > defMax_) { + defMax_ = x.var(); + } + score_[x.var()].setDom(domKey); +} + + +Literal DomainHeuristic::doSelect(Solver& s) { + Literal x = BaseType::doSelect(s); + s.stats.addDomChoice(score_[x.var()].isDom()); + return x; +} + +Constraint::PropResult DomainHeuristic::propagate(Solver& s, Literal, uint32& aId) { + uint32 n = aId; + uint32 D = s.decisionLevel(); + do { + DomAction& a = actions_[n]; + uint16& prio = this->prio(a.var, a.mod); + if (s.value(a.var) == value_free && a.prio >= prio) { + applyAction(s, a, prio); + if (D != frames_.back().dl) { + s.addUndoWatch(D, this); + frames_.push_back(Frame(D, DomAction::UNDO_NIL)); + } + pushUndo(frames_.back().head, n); + } + } while (actions_[n++].next); + return PropResult(true, true); +} + +void DomainHeuristic::applyAction(Solver& s, DomAction& a, uint16& gPrio) { + std::swap(gPrio, a.prio); + switch (a.mod) { + default: assert(false); break; + case DomModType::Factor: std::swap(score_[a.var].factor, a.bias); break; + case DomModType::Level: + std::swap(score_[a.var].level, a.bias); + if (vars_.is_in_queue(a.var)) { vars_.update(a.var); } + break; + case DomModType::Sign: + int16 old = s.pref(a.var).get(ValueSet::user_value); + s.setPref(a.var, ValueSet::user_value, ValueRep(a.bias)); + a.bias = old; + break; + } +} +void DomainHeuristic::pushUndo(uint32& head, uint32 actionId) { + actions_[actionId].undo = head; + head = actionId; +} + +void DomainHeuristic::undoLevel(Solver& s) { + while (frames_.back().dl >= s.decisionLevel()) { + for (uint32 n = frames_.back().head; n != DomAction::UNDO_NIL;) { + DomAction& a = actions_[n]; + n = a.undo; + applyAction(s, a, prio(a.var, a.mod)); + } + frames_.pop_back(); + } +} +template class ClaspVsids_t; +} diff --git a/libclasp/src/logic_program.cpp b/libclasp/src/logic_program.cpp new file mode 100644 index 0000000..0e93691 --- /dev/null +++ b/libclasp/src/logic_program.cpp @@ -0,0 +1,2071 @@ +// +// Copyright (c) 2013-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace Clasp { namespace Asp { +///////////////////////////////////////////////////////////////////////////////////////// +// Statistics +///////////////////////////////////////////////////////////////////////////////////////// +#define RK(x) RuleStats::x +const char* RuleStats::toStr(int k) { + CLASP_FAIL_IF(k < 0 || uint32(k) > numKeys(), "Invalid key"); + switch (k) { + case Normal : return "Normal"; + case Choice : return "Choice"; + case Minimize : return "Minimize"; + case Acyc : return "Acyc"; + case Heuristic: return "Heuristic"; + default: return "None"; + } +} +uint32 RuleStats::sum() const { + return std::accumulate(key, key + numKeys(), uint32(0)); +} +const char* BodyStats::toStr(int t) { + CLASP_FAIL_IF(t < 0 || uint32(t) >= numKeys(), "Invalid body type!"); + switch (t) { + default : return "Normal"; + case Body_t::Count: return "Count"; + case Body_t::Sum : return "Sum"; + } +} +uint32 BodyStats::sum() const { + return std::accumulate(key, key + numKeys(), uint32(0)); +} + +namespace { +template +double sumBodies(const LpStats* self) { return self->bodies[i].sum(); } +template +double sumRules(const LpStats* self) { return self->rules[i].sum(); } +double sumEqs(const LpStats* self) { return self->eqs(); } +} +#define LP_STATS( APPLY ) \ + APPLY("atoms" , VALUE(atoms)) \ + APPLY("atoms_aux" , VALUE(auxAtoms)) \ + APPLY("disjunctions" , VALUE(disjunctions[0])) \ + APPLY("disjunctions_non_hcf", VALUE(disjunctions[1])) \ + APPLY("bodies" , FUNC(sumBodies<0>)) \ + APPLY("bodies_tr" , FUNC(sumBodies<1>)) \ + APPLY("sum_bodies" , VALUE(bodies[0][Body_t::Sum])) \ + APPLY("sum_bodies_tr" , VALUE(bodies[1][Body_t::Sum])) \ + APPLY("count_bodies" , VALUE(bodies[0][Body_t::Count]))\ + APPLY("count_bodies_tr" , VALUE(bodies[1][Body_t::Count]))\ + APPLY("sccs" , VALUE(sccs)) \ + APPLY("sccs_non_hcf" , VALUE(nonHcfs)) \ + APPLY("gammas" , VALUE(gammas)) \ + APPLY("ufs_nodes" , VALUE(ufsNodes)) \ + APPLY("rules" , FUNC(sumRules<0>)) \ + APPLY("rules_normal" , VALUE(rules[0][RK(Normal)])) \ + APPLY("rules_choice" , VALUE(rules[0][RK(Choice)])) \ + APPLY("rules_minimize" , VALUE(rules[0][RK(Minimize)])) \ + APPLY("rules_acyc" , VALUE(rules[0][RK(Acyc)])) \ + APPLY("rules_heuristic" , VALUE(rules[0][RK(Heuristic)]))\ + APPLY("rules_tr" , FUNC(sumRules<1>)) \ + APPLY("rules_tr_normal" , VALUE(rules[1][RK(Normal)])) \ + APPLY("rules_tr_choice" , VALUE(rules[1][RK(Choice)])) \ + APPLY("rules_tr_minimize" , VALUE(rules[1][RK(Minimize)])) \ + APPLY("rules_tr_acyc" , VALUE(rules[1][RK(Acyc)])) \ + APPLY("rules_tr_heuristic" , VALUE(rules[1][RK(Heuristic)]))\ + APPLY("eqs" , FUNC(sumEqs)) \ + APPLY("eqs_atom" , VALUE(eqs_[Var_t::Atom-1])) \ + APPLY("eqs_body" , VALUE(eqs_[Var_t::Body-1])) \ + APPLY("eqs_other" , VALUE(eqs_[Var_t::Hybrid-1])) + +void LpStats::reset() { + std::memset(this, 0, sizeof(LpStats)); +} + +void LpStats::accu(const LpStats& o) { + atoms += o.atoms; + auxAtoms += o.auxAtoms; + ufsNodes += o.ufsNodes; + if (sccs == PrgNode::noScc || o.sccs == PrgNode::noScc) { + sccs = o.sccs; + nonHcfs = o.nonHcfs; + } + else { + sccs += o.sccs; + nonHcfs+= o.nonHcfs; + } + for (int i = 0; i != 2; ++i) { + disjunctions[i] += o.disjunctions[i]; + for (uint32 k = 0; k != BodyStats::numKeys(); ++k) { + bodies[i][k] += o.bodies[i][k]; + } + for (uint32 k = 0; k != RuleStats::numKeys(); ++k) { + rules[i][k] += o.rules[i][k]; + } + } + for (int i = 0; i != sizeof(eqs_)/sizeof(eqs_[0]); ++i) { + eqs_[i] += o.eqs_[i]; + } +} + +static const char* lpStats_s[] = { +#define KEY(x, y) x, + LP_STATS(KEY) +#undef KEY + "lp" +}; +uint32 LpStats::size() { + return (sizeof(lpStats_s)/sizeof(const char*))-1; +} +const char* LpStats::key(uint32 i) { + return i < size() ? lpStats_s[i] : throw std::out_of_range("LpStats::key"); +} +StatisticObject LpStats::at(const char* k) const { +#define MAP_IF(x, A) if (std::strcmp(k, x) == 0) return A; +#define VALUE(X) StatisticObject::value(&(X)) +#define FUNC(F) StatisticObject::value(this) + LP_STATS(MAP_IF) +#undef VALUE +#undef FUNC +#undef MAP_IF + throw std::out_of_range("LpStats::at"); +} +#undef LP_STATS +///////////////////////////////////////////////////////////////////////////////////////// +// class LogicProgram +///////////////////////////////////////////////////////////////////////////////////////// +static PrgAtom trueAtom_g(0, false); +static const uint32 falseId = PrgNode::noNode; +static const uint32 bodyId = PrgNode::noNode + 1; +static bool init_trueAtom_g = (trueAtom_g.setEq(0), true); +inline bool isAtom(Id_t uid) { return Potassco::atom(Potassco::lit(uid)) < bodyId; } +inline bool isBody(Id_t uid) { return Potassco::atom(Potassco::lit(uid)) >= bodyId; } +inline Id_t nodeId(Id_t uid) { return Potassco::atom(Potassco::lit(uid)) - (isAtom(uid) ? 0 : bodyId); } +inline bool signId(Id_t uid) { return Potassco::lit(uid) < 0; } + +namespace { +typedef std::pair AtomVal; +inline uint32 encodeExternal(Atom_t a, Potassco::Value_t value) { + return (a << 2) | static_cast(value); +} +inline AtomVal decodeExternal(uint32 x) { + return AtomVal(x >> 2, static_cast(x & 3u)); +} +struct LessBodySize { + LessBodySize(const BodyList& bl) : bodies_(&bl) {} + bool operator()(Id_t b1, Id_t b2 ) const { + return (*bodies_)[b1]->size() < (*bodies_)[b2]->size() + || ((*bodies_)[b1]->size() == (*bodies_)[b2]->size() && (*bodies_)[b1]->type() < (*bodies_)[b2]->type()); + } +private: + const BodyList* bodies_; +}; +// Adds nogoods representing this node to the solver. +template +bool toConstraint(NT* node, const LogicProgram& prg, ClauseCreator& c) { + if (node->value() != value_free && !prg.ctx()->addUnary(node->trueLit())) { + return false; + } + return !node->relevant() || node->addConstraints(prg, c); +} +} + +LogicProgram::LogicProgram() : theory_(0), input_(1, UINT32_MAX), auxData_(0), incData_(0) { + CLASP_FAIL_IF(!init_trueAtom_g, "invalid static init"); +} +LogicProgram::~LogicProgram() { dispose(true); } +LogicProgram::Incremental::Incremental() : startScc(0) {} +void LogicProgram::dispose(bool force) { + // remove rules + std::for_each(bodies_.begin(), bodies_.end(), DestroyObject()); + std::for_each(disjunctions_.begin(), disjunctions_.end(), DestroyObject()); + std::for_each(extended_.begin(), extended_.end(), DeleteObject()); + std::for_each(minimize_.begin(), minimize_.end(), DeleteObject()); + PodVector::destruct(show_); + delete auxData_; auxData_ = 0; + MinList().swap(minimize_); + RuleList().swap(extended_); + BodyList().swap(bodies_); + DisjList().swap(disjunctions_); + bodyIndex_.clear(); + disjIndex_.clear(); + VarVec().swap(initialSupp_); + if (theory_) { + theory_->reset(); + } + if (force || !incData_) { + deleteAtoms(0); + AtomList().swap(atoms_); + AtomState().swap(atomState_); + delete theory_; + delete incData_; + VarVec().swap(propQ_); + stats.reset(); + } + rule_.clear(); +} +void LogicProgram::deleteAtoms(uint32 start) { + for (AtomList::const_iterator it = atoms_.begin() + start, end = atoms_.end(); it != end; ++it) { + if (*it != &trueAtom_g) { delete *it; } + } +} +bool LogicProgram::doStartProgram() { + dispose(true); + // atom 0 is always true + PrgAtom* trueAt = new PrgAtom(0, false); + atoms_.push_back(trueAt); + trueAt->assignValue(value_true); + trueAt->setInUpper(true); + trueAt->setLiteral(lit_true()); + atomState_.set(0, AtomState::fact_flag); + incData_ = 0; + auxData_ = new Aux(); + input_ = AtomRange(1, UINT32_MAX); + statsId_ = 0; + return true; +} +void LogicProgram::setOptions(const AspOptions& opts) { + opts_ = opts; + if (opts.suppMod) { opts_.noSCC = 1; } + if (opts.suppMod && ctx() && ctx()->sccGraph.get()) { + ctx()->warn("'supp-models' ignored for non-tight programs."); + opts_.suppMod = 0; + opts_.noSCC = 0; + } +} +ProgramParser* LogicProgram::doCreateParser() { + return new AspParser(*this); +} +bool LogicProgram::doUpdateProgram() { + if (!incData_) { incData_ = new Incremental(); } + if (!frozen()) { return true; } + // delete bodies/disjunctions... + dispose(false); + setFrozen(false); + auxData_ = new Aux(); + if (theory_) { theory_->update(); } + incData_->unfreeze.clear(); + input_.hi = std::min(input_.hi, endAtom()); + // reset prop queue and add supported atoms from previous steps + // {ai | ai in P}. + PrgBody* support = input_.hi > 1 ? getTrueBody() : 0; + propQ_.clear(); + for (Atom_t i = 1, end = startAuxAtom(); i != end; ++i) { + if (getRootId(i) >= end) { + // atom is equivalent to some aux atom - make i the new root + uint32 r = getRootId(i); + std::swap(atoms_[i], atoms_[r]); + atoms_[r]->setEq(i); + } + // remove dangling references + PrgAtom* a = atoms_[i]; + a->clearSupports(); + a->clearDeps(PrgAtom::dep_all); + a->setIgnoreScc(false); + if (a->relevant() || a->frozen()) { + ValueRep v = a->value(); + a->setValue(value_free); + a->resetId(i, !a->frozen()); + if (ctx()->master()->value(a->var()) != value_free && !a->frozen()) { + v = ctx()->master()->isTrue(a->literal()) ? value_true : value_false; + } + if (v != value_free) { assignValue(a, v, PrgEdge::noEdge()); } + if (!a->frozen() && a->value() != value_false) { + a->setIgnoreScc(true); + support->addHead(a, PrgEdge::GammaChoice); + } + } + else if (a->removed() || (!a->eq() && a->value() == value_false)) { + a->resetId(i, true); + a->setValue(value_false); + atomState_.set(i, AtomState::false_flag); + } + } + // delete any introduced aux atoms + // this is safe because aux atoms are never part of the input program + // it is necessary in order to free their ids, i.e. the id of an aux atom + // from step I might be needed for a program atom in step I+1 + deleteAtoms(startAuxAtom()); + atoms_.erase(atoms_.begin()+startAuxAtom(), atoms_.end()); + uint32 nAtoms = (uint32)atoms_.size(); + atomState_.resize(nAtoms); + input_ = AtomRange(nAtoms, UINT32_MAX); + stats.reset(); + statsId_ = 0; + return true; +} +bool LogicProgram::doEndProgram() { + if (!frozen() && ctx()->ok()) { + prepareProgram(!opts_.noSCC); + addConstraints(); + addDomRules(); + addAcycConstraint(); + } + return ctx()->ok(); +} + +bool LogicProgram::clone(SharedContext& oCtx) { + assert(frozen()); + if (&oCtx == ctx()) { + return true; + } + for (Var v = oCtx.numVars() + 1; ctx()->validVar(v); ++v) { + oCtx.addVar(Var_t::Atom, ctx()->varInfo(v).rep); + } + SharedContext* t = ctx(); + setCtx(&oCtx); + bool ok = addConstraints(); + if (ok) { + oCtx.output = ctx()->output; + oCtx.heuristic = t->heuristic; + } + setCtx(t); + return ok; +} + +void LogicProgram::addMinimize() { + CLASP_ASSERT_CONTRACT(frozen()); + for (MinList::iterator it = minimize_.begin(), end = minimize_.end(); it != end; ++it) { + const LpWLitVec& lits = (*it)->lits; + const weight_t prio = (*it)->prio; + for (LpWLitVec::const_iterator xIt = lits.begin(), xEnd = lits.end(); xIt != xEnd; ++xIt) { + addMinLit(prio, WeightLiteral(getLiteral(Potassco::id(xIt->lit)), xIt->weight)); + } + // Make sure minimize constraint is not empty + if (lits.empty()) addMinLit(prio, WeightLiteral(lit_false(), 1)); + } +} +static void outRule(Potassco::AbstractProgram& out, const Rule& r) { + if (r.normal()) { out.rule(r.ht, r.head, r.cond); } + else { out.rule(r.ht, r.head, r.agg.bound, r.agg.lits); } +} + +void LogicProgram::accept(Potassco::AbstractProgram& out) { + if (!ok()) { + out.rule(Head_t::Disjunctive, Potassco::toSpan(), Potassco::toSpan()); + return; + } + // visit external directives + for (VarVec::const_iterator it = auxData_->external.begin(), end = auxData_->external.end(); it != end; ++it) { + AtomVal x = decodeExternal(*it); + out.external(x.first, x.second); + } + // visit eq- and assigned atoms + for (Atom_t i = startAtom(); i < atoms_.size(); ++i) { + if (atoms_[i]->eq()) { + Potassco::AtomSpan head = Potassco::toSpan(&i, 1); + Potassco::Lit_t body = Potassco::lit(getRootId(i)); + if (isFact(Potassco::atom(body))) { + out.rule(Head_t::Disjunctive, head, Potassco::toSpan()); + } + else if (inProgram(Potassco::atom(body))) { + out.rule(Head_t::Disjunctive, head, Potassco::toSpan(&body, 1)); + } + } + else if (!atomState_.isFact(i) && atoms_[i]->value() != value_free) { + Potassco::AtomSpan head = Potassco::toSpan(); + Potassco::Lit_t body = Potassco::neg(i); + if (atoms_[i]->value() != value_false) { + out.rule(Head_t::Disjunctive, head, Potassco::toSpan(&body, 1)); + } + else if (inProgram(i)) { + body = Potassco::neg(body); + out.rule(Head_t::Disjunctive, head, Potassco::toSpan(&body, 1)); + } + } + } + // visit program rules + const bool simp = frozen(); + using Potassco::Lit_t; + VarVec choice; + for (BodyList::iterator bIt = bodies_.begin(); bIt != bodies_.end(); ++bIt) { + rule_.clear(); + choice.clear(); + Atom_t head; + Lit_t auxB; + PrgBody* b = *bIt; + if (b->relevant() && (b->inRule() || b->value() == value_false) && b->toData(*this, rule_)) { + if (b->value() == value_false) { + outRule(out, rule_.rule()); + continue; + } + uint32 numDis = 0; + Rule r = rule_.rule(); + for (PrgBody::head_iterator hIt = b->heads_begin(); hIt != b->heads_end(); ++hIt) { + if (hIt->isGamma() || (simp && !getHead(*hIt)->hasVar())) { continue; } + if (hIt->isAtom() && hIt->node() && inProgram(hIt->node())) { + if (hIt->isNormal()) { r.head = Potassco::toSpan(&(head = hIt->node()), 1); outRule(out, r); } + else if (hIt->isChoice()) { choice.push_back(hIt->node()); } + if (simp && getRootAtom(hIt->node())->var() == b->var() && !r.normal()) { + // replace complex body with head atom + auxB = Potassco::lit(hIt->node()); + if (getRootAtom(hIt->node())->literal() != b->literal()) { auxB *= -1; } + r.bt = Body_t::Normal; + r.cond = Potassco::toSpan(&auxB, 1); + } + } + else if (hIt->isDisj()) { ++numDis; } + } + if (!choice.empty()) { + r.head = Potassco::toSpan(choice); + r.ht = Head_t::Choice; + outRule(out, r); + } + for (PrgBody::head_iterator hIt = b->heads_begin(); hIt != b->heads_end() && numDis; ++hIt) { + if (hIt->isDisj()) { + PrgDisj* d = getDisj(hIt->node()); + r.head = Potassco::toSpan(d->begin(), d->size()); + r.ht = Head_t::Disjunctive; + outRule(out, r); + --numDis; + } + } + } + } + LpWLitVec wlits; + for (MinList::iterator it = minimize_.begin(), end = minimize_.end(); it != end; ++it) { + Potassco::WeightLitSpan ws = Potassco::toSpan((*it)->lits); + for (const Potassco::WeightLit_t* x = Potassco::begin(ws), *xEnd = Potassco::end(ws); x != xEnd; ++x) { + if (x->weight == 0 || !inProgram(Potassco::atom(*x))) { // simplify literals + wlits.assign(Potassco::begin(ws), x); + for (; x != xEnd; ++x) { + if (x->weight != 0 && (x->weight < 0 || x->lit < 0 || inProgram(Potassco::atom(*x)))) { + wlits.push_back(*x); + } + } + ws = Potassco::toSpan(wlits); + break; + } + } + out.minimize((*it)->prio, ws); + } + Potassco::LitVec lits; + // visit output directives + for (ShowVec::const_iterator it = show_.begin(); it != show_.end(); ++it) { + if (extractCondition(it->first, lits)) { + out.output(Potassco::toSpan(it->second.c_str(), std::strlen(it->second.c_str())), Potassco::toSpan(lits)); + } + } + // visit projection directives + if (!auxData_->project.empty()) { + out.project(auxData_->project.back() ? Potassco::toSpan(auxData_->project) : Potassco::toSpan()); + } + // visit assumptions + if (!auxData_->assume.empty()) { + out.assume(Potassco::toSpan(auxData_->assume)); + } + // visit heuristics + if (!auxData_->dom.empty()) { + for (DomRules::const_iterator it = auxData_->dom.begin(), end = auxData_->dom.end(); it != end; ++it) { + if (extractCondition(it->cond, lits)) { + out.heuristic(it->atom, static_cast(it->type), it->bias, it->prio, Potassco::toSpan(lits)); + } + } + } + // visit acyc edges + if (!auxData_->acyc.empty()) { + for (AcycRules::const_iterator it = auxData_->acyc.begin(), end = auxData_->acyc.end(); it != end; ++it) { + if (extractCondition(it->cond, lits)) { + out.acycEdge(it->node[0], it->node[1], Potassco::toSpan(lits)); + } + } + } + if (theory_ && theory_->numAtoms()) { + struct This : public Potassco::TheoryData::Visitor { + This(const Asp::LogicProgram& p, Potassco::AbstractProgram& o, Potassco::LitVec& c) : self(&p), out(&o), cond(&c) {} + virtual void visit(const Potassco::TheoryData& data, Potassco::Id_t termId, const Potassco::TheoryTerm& t) { + if (!addSeen(termId, 1)) { return; } + data.accept(t, *this); + Potassco::print(*out, termId, t); + } + virtual void visit(const Potassco::TheoryData& data, Potassco::Id_t elemId, const Potassco::TheoryElement& e) { + if (!addSeen(elemId, 2)) { return; } + data.accept(e, *this); + cond->clear(); + if (e.condition()) { self->extractCondition(e.condition(), *cond); } + out->theoryElement(elemId, e.terms(), Potassco::toSpan(*cond)); + } + virtual void visit(const Potassco::TheoryData& data, const Potassco::TheoryAtom& a) { + data.accept(a, *this); + Potassco::print(*out, a); + const Atom_t id = a.atom(); + if (self->validAtom(id) && self->atomState_.isSet(id, AtomState::false_flag) && !self->inProgram(id)) { + Potassco::Lit_t x = Potassco::lit(id); + out->rule(Head_t::Disjunctive, Potassco::toSpan(), Potassco::toSpan(&x, 1)); + } + } + bool addSeen(Potassco::Id_t id, unsigned char n) { + if (id >= seen.size()) { seen.resize(id + 1, 0); } + unsigned char old = seen[id]; + return (seen[id] |= n) != old; + } + typedef PodVector::type IdSet; + const Asp::LogicProgram* self; + Potassco::AbstractProgram* out; + Potassco::LitVec* cond; + IdSet seen; + } self(*this, out, lits); + theory_->accept(self); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// Program mutating functions +///////////////////////////////////////////////////////////////////////////////////////// +#define check_not_frozen() CLASP_ASSERT_CONTRACT_MSG(!frozen(), "Can't update frozen program!") +#define check_modular(x, atomId) (void)( (!!(x)) || (throw RedefinitionError((atomId), this->findName((atomId))), 0)) +RedefinitionError::RedefinitionError(unsigned atomId, const char* name) + : std::logic_error(ClaspStringBuffer().appendFormat("redefinition of atom <'%s',%u>", name && *name ? name : "_", atomId).c_str()) { +} + +Atom_t LogicProgram::newAtom() { + check_not_frozen(); + Atom_t id = static_cast(atoms_.size()); + atoms_.push_back( new PrgAtom(id) ); + return id; +} +Id_t LogicProgram::newCondition(const Potassco::LitSpan& cond) { + check_not_frozen(); + SRule meta; + if (simplifyNormal(Head_t::Disjunctive, Potassco::toSpan(), cond, rule_, meta)) { + Rule r = rule_.rule(); + if (r.cond.size == 0) { return 0; } + if (r.cond.size == 1) { return Potassco::id(r.cond[0]); } + PrgBody* b = getBodyFor(r, meta); + b->markFrozen(); + return static_cast(Clasp::Asp::bodyId | b->id()); + } + return static_cast(Clasp::Asp::falseId); +} +LogicProgram& LogicProgram::addOutput(const ConstString& str, const Potassco::LitSpan& cond) { + if (!ctx()->output.filter(str)) { + CLASP_FAIL_IF(cond.size == 1 && Potassco::atom(cond[0]) >= bodyId, "Atom out of bounds"); + show_.push_back(ShowPair(cond.size == 1 ? Potassco::id(cond[0]) : newCondition(cond), str)); + } + return *this; +} +LogicProgram& LogicProgram::addOutput(const ConstString& str, Id_t id) { + if (!ctx()->output.filter(str) && id != falseId) { + show_.push_back(ShowPair(id, str)); + } + return *this; +} + +LogicProgram& LogicProgram::addProject(const Potassco::AtomSpan& atoms) { + check_not_frozen(); + VarVec& pro = auxData_->project; + if (!Potassco::empty(atoms)) { + if (!pro.empty() && pro.back() == 0) { pro.pop_back(); } + pro.insert(pro.end(), Potassco::begin(atoms), Potassco::end(atoms)); + } + else if (pro.empty()) { + pro.push_back(0); + } + return *this; +} + +TheoryData& LogicProgram::theoryData() { + if (!theory_) { theory_ = new TheoryData(); } + return *theory_; +} + +void LogicProgram::pushFrozen(PrgAtom* atom, ValueRep value) { + if (!atom->frozen()) { frozen_.push_back(atom->id()); } + atom->markFrozen(value); +} + +LogicProgram& LogicProgram::addExternal(Atom_t atomId, Potassco::Value_t value) { + check_not_frozen(); + PrgAtom* a = resize(atomId); + if (a->supports() == 0 && (isNew(a->id()) || a->frozen())) { + ValueRep fv = static_cast(value); + if (value == Potassco::Value_t::Release) { + // add dummy edge - will be removed once we update the set of frozen atoms + a->addSupport(PrgEdge::noEdge()); + fv = value_free; + } + pushFrozen(a, fv); + auxData_->external.push_back(encodeExternal(a->id(), value)); + } + return *this; +} + +LogicProgram& LogicProgram::freeze(Atom_t atomId, ValueRep value) { + CLASP_ASSERT_CONTRACT(value < value_weak_true); + return addExternal(atomId, static_cast(value)); +} + +LogicProgram& LogicProgram::unfreeze(Atom_t atomId) { + return addExternal(atomId, Potassco::Value_t::Release); +} +void LogicProgram::setMaxInputAtom(uint32 n) { + check_not_frozen(); + resize(n++); + CLASP_ASSERT_CONTRACT_MSG(n >= startAtom(), "invalid input range"); + input_.hi = n; +} +Atom_t LogicProgram::startAuxAtom() const { + return validAtom(input_.hi) ? input_.hi : (uint32)atoms_.size(); +} +bool LogicProgram::supportsSmodels() const { + if (incData_ || theory_) { return false; } + if (!auxData_->dom.empty()) { return false; } + if (!auxData_->acyc.empty()) { return false; } + if (!auxData_->assume.empty()) { return false; } + if (!auxData_->project.empty()) { return false; } + for (ShowVec::const_iterator it = show_.begin(), end = show_.end(); it != end; ++it) { + Potassco::Lit_t lit = Potassco::lit(it->first); + if (lit <= 0 || static_cast(lit) >= bodyId) { return false; } + } + return true; +} + +bool LogicProgram::isExternal(Atom_t aId) const { + if (!aId || !validAtom(aId)) { return false; } + PrgAtom* a = getRootAtom(aId); + return a->frozen() && (a->supports() == 0 || frozen()); +} +bool LogicProgram::isFact(Atom_t aId) const { + return validAtom(aId) && (atomState_.isFact(aId) || atomState_.isFact(getRootId(aId))); +} +bool LogicProgram::isDefined(Atom_t aId) const { + if (!validAtom(aId) || getAtom(aId)->removed()) { + return false; + } + PrgAtom* a = getAtom(aId); + return isFact(aId) || (a->relevant() && a->supports() && !isExternal(aId)); +} +bool LogicProgram::inProgram(Atom_t id) const { + if (PrgAtom* a = (validAtom(id) ? getAtom(id) : 0)) { + return a->relevant() && (a->supports() || a->frozen() || !isNew(id)); + } + return false; +} +LogicProgram& LogicProgram::addAssumption(const Potassco::LitSpan& lits) { + auxData_->assume.insert(auxData_->assume.end(), Potassco::begin(lits), Potassco::end(lits)); + return *this; +} + +LogicProgram& LogicProgram::addAcycEdge(uint32 n1, uint32 n2, Id_t condId) { + if (condId != falseId) { + AcycArc arc = { condId, {n1, n2} }; + auxData_->acyc.push_back(arc); + } + upStat(RK(Acyc), 1); + return *this; +} + +LogicProgram& LogicProgram::addDomHeuristic(Atom_t atom, DomModType t, int bias, unsigned prio) { + return addDomHeuristic(atom, t, bias, prio, Potassco::toSpan()); +} +LogicProgram& LogicProgram::addDomHeuristic(Atom_t atom, DomModType type, int bias, unsigned prio, Id_t cond) { + static_assert(sizeof(DomRule) == sizeof(uint32[3]), "Invalid DomRule size"); + if (cond != falseId) { + auxData_->dom.push_back(DomRule()); + DomRule& x = auxData_->dom.back(); + x.atom = atom; + x.type = type; + x.cond = cond; + x.bias = (int16)Range(INT16_MIN, INT16_MAX).clamp(bias); + x.prio = (uint16)Range(unsigned(0), unsigned(~uint16(0)) ).clamp(prio); + } + upStat(RK(Heuristic), 1); + return *this; +} +LogicProgram& LogicProgram::addRule(const Rule& rule) { + check_not_frozen(); + SRule meta; + if (simplifyRule(rule, rule_, meta)) { + Rule sRule = rule_.rule(); + upStat(sRule.ht); + if (handleNatively(sRule)) { // and can be handled natively + addRule(sRule, meta); + } + else { + upStat(sRule.bt); + if (Potassco::size(sRule.head) <= 1 && transformNoAux(sRule)) { + // rule transformation does not require aux atoms - do it now + int oId = statsId_; + statsId_ = 1; + RuleTransform tm(*this); + upStat(sRule.bt, -1); + upStat(rule.ht, -1); + tm.transform(sRule, RuleTransform::strategy_select_no_aux); + statsId_ = oId; + } + else { + // make sure we have all head atoms + for (Potassco::AtomSpan::iterator it = Potassco::begin(sRule.head), end = Potassco::end(sRule.head); it != end; ++it) { + resize(*it); + } + extended_.push_back(new RuleBuilder(rule_)); + } + } + } + rule_.clear(); + return *this; +} + +LogicProgram& LogicProgram::addRule(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body) { + return addRule(Rule::normal(ht, head, body)); +} +LogicProgram& LogicProgram::addRule(Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& lits) { + return addRule(Rule::sum(ht, head, bound, lits)); +} +LogicProgram& LogicProgram::addRule(Potassco::RuleBuilder& rb) { + LogicProgramAdapter prg(*this); + rb.end(&prg); + return *this; +} +LogicProgram& LogicProgram::addMinimize(weight_t prio, const Potassco::WeightLitSpan& lits) { + SingleOwnerPtr n(new Min()); + n->prio = prio; + MinList::iterator it = std::lower_bound(minimize_.begin(), minimize_.end(), n.get(), CmpMin()); + if (it == minimize_.end() || (*it)->prio != prio) { + n->lits.assign(Potassco::begin(lits), Potassco::end(lits)); + minimize_.insert(it, n.get()); + n.release(); + upStat(RuleStats::Minimize); + } + else { + (*it)->lits.insert((*it)->lits.end(), Potassco::begin(lits), Potassco::end(lits)); + } + return *this; +} +#undef check_not_frozen +///////////////////////////////////////////////////////////////////////////////////////// +// Query functions +///////////////////////////////////////////////////////////////////////////////////////// +bool LogicProgram::isFact(PrgAtom* a) const { + uint32 eqId = getRootId(a->id()); + if (atomState_.isFact(eqId)) { + return true; + } + if (a->value() == value_true) { + for (PrgAtom::sup_iterator it = a->supps_begin(), end = a->supps_end(); it != end; ++it) { + if (it->isBody() && it->isNormal() && getBody(it->node())->bound() == 0) { + return true; + } + } + } + return false; +} +Literal LogicProgram::getLiteral(Id_t id) const { + Literal out = lit_false(); + Potassco::Id_t nId = nodeId(id); + if (isAtom(id) && validAtom(nId)) { + out = getRootAtom(nId)->literal(); + } + else if (isBody(id)) { + CLASP_FAIL_IF(!validBody(nId), "Invalid condition"); + out = getBody(getEqBody(nId))->literal(); + } + return out ^ signId(id); +} +Literal LogicProgram::getDomLiteral(Atom_t atomId) const { + IndexMap::const_iterator it = domEqIndex_.find(atomId); + return it == domEqIndex_.end() ? getLiteral(atomId) : posLit(it->second); +} + +void LogicProgram::doGetAssumptions(LitVec& out) const { + for (VarVec::const_iterator it = frozen_.begin(), end = frozen_.end(); it != end; ++it) { + Literal lit = getRootAtom(*it)->assumption(); + if (lit != lit_true()) { out.push_back( lit ); } + } + for (Potassco::LitVec::const_iterator it = auxData_->assume.begin(), end = auxData_->assume.end(); it != end; ++it) { + out.push_back(getLiteral(Potassco::id(*it))); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// Program definition - private +///////////////////////////////////////////////////////////////////////////////////////// +void LogicProgram::addRule(const Rule& r, const SRule& meta) { + if (Potassco::size(r.head) <= 1 && r.ht == Head_t::Disjunctive) { + if (Potassco::empty(r.head)) { addIntegrity(r, meta); return; } + else if (r.normal() && r.cond.size == 0) { addFact(r.head); return; } + } + PrgBody* b = getBodyFor(r, meta); + // only a non-false body can define atoms + if (b->value() != value_false) { + bool const disjunctive = Potassco::size(r.head) > 1 && r.ht == Head_t::Disjunctive; + const EdgeType t = r.ht == Head_t::Disjunctive ? PrgEdge::Normal : PrgEdge::Choice; + uint32 headHash = 0; + bool ignoreScc = opts_.noSCC || b->size() == 0; + for (Potassco::AtomSpan::iterator it = Potassco::begin(r.head), end = Potassco::end(r.head); it != end; ++it) { + PrgAtom* a = resize(*it); + check_modular(isNew(*it) || a->frozen() || a->value() == value_false, *it); + if (!disjunctive) { + // Note: b->heads may now contain duplicates. They are removed in PrgBody::simplifyHeads. + b->addHead(a, t); + if (ignoreScc) { a->setIgnoreScc(ignoreScc); } + } + else { + headHash += hashLit(posLit(*it)); + atomState_.addToHead(*it); + } + } + if (disjunctive) { + PrgDisj* d = getDisjFor(r.head, headHash); + b->addHead(d, t); + } + } +} +void LogicProgram::addFact(const Potassco::AtomSpan& head) { + PrgBody* tb = 0; + for (Potassco::AtomSpan::iterator it = Potassco::begin(head), end = Potassco::end(head); it != end; ++it) { + PrgAtom* a = resize(*it); + check_modular(isNew(*it) || a->frozen() || a->value() == value_false, *it); + if (*it != a->id() || atomState_.isFact(*it)) { continue; } + a->setIgnoreScc(true); + atomState_.set(*it, AtomState::fact_flag); + if (!a->hasDep(PrgAtom::dep_all) && !a->frozen()) { + if (!a->assignValue(value_true) || !a->propagateValue(*this, false)) { + setConflict(); + } + for (PrgAtom::sup_iterator bIt = a->supps_begin(), bEnd = a->supps_end(); bIt != bEnd; ++bIt) { + if (bIt->isBody()) { getBody(bIt->node())->markHeadsDirty(); } + else if (bIt->isDisj()) { getDisj(bIt->node())->markDirty(); } + } + atoms_[*it] = &trueAtom_g; + delete a; + } + else { + if (!tb) tb = getTrueBody(); + tb->addHead(a, PrgEdge::Normal); + assignValue(a, value_true, PrgEdge::newEdge(*tb, PrgEdge::Normal)); + } + } +} +void LogicProgram::addIntegrity(const Rule& r, const SRule& meta) { + if (r.sum() || r.cond.size != 1 || meta.bid != varMax) { + PrgBody* B = getBodyFor(r, meta); + if (!B->assignValue(value_false) || !B->propagateValue(*this, true)) { + setConflict(); + } + } + else { + PrgAtom* a = resize(Potassco::atom(r.cond[0])); + ValueRep v = r.cond[0] > 0 ? value_false : value_weak_true; + assignValue(a, v, PrgEdge::noEdge()); + } +} +bool LogicProgram::assignValue(PrgAtom* a, ValueRep v, PrgEdge reason) { + if (a->eq()) { a = getRootAtom(a->id()); } + ValueRep old = a->value(); + if (old == value_weak_true && v != value_weak_true) old = value_free; + if (!a->assignValue(v)) { setConflict(); return false; } + if (old == value_free) { propQ_.push_back(a->id()); } + if (v == value_false) { + atomState_.set(a->id(), AtomState::false_flag); + } + else if (v == value_true && reason.isBody() && reason.isNormal() && getBody(reason.node())->bound() == 0) { + atomState_.set(a->id(), AtomState::fact_flag); + } + return true; +} +bool LogicProgram::assignValue(PrgHead* h, ValueRep v, PrgEdge reason) { + return !h->isAtom() || assignValue(static_cast(h), v, reason); +} + +bool LogicProgram::handleNatively(const Rule& r) const { + ExtendedRuleMode m = opts_.erMode; + if (m == mode_native || (r.normal() && r.ht == Head_t::Disjunctive)) { + return true; + } + else if (m == mode_transform_integ || m == mode_transform_scc || m == mode_transform_nhcf) { + return true; + } + else if (m == mode_transform) { + return false; + } + else if (m == mode_transform_dynamic) { + return r.normal() || transformNoAux(r) == false; + } + else if (m == mode_transform_choice) { + return r.ht != Head_t::Choice; + } + else if (m == mode_transform_card) { + return r.bt != Body_t::Count; + } + else if (m == mode_transform_weight) { + return r.normal(); + } + assert(false && "unhandled extended rule mode"); + return true; +} + +bool LogicProgram::transformNoAux(const Rule& r) const { + return r.ht == Head_t::Disjunctive && r.sum() && (r.agg.bound == 1 || (Potassco::size(r.agg.lits) <= 6 && choose(toU32(Potassco::size(r.agg.lits)), r.agg.bound) <= 15)); +} + +void LogicProgram::transformExtended() { + uint32 a = numAtoms(); + RuleTransform tm(*this); + for (RuleList::size_type i = 0; i != extended_.size(); ++i) { + Rule r = extended_[i]->rule(); + upStat(r.ht, -1); + upStat(r.bt, -1); + if (r.normal() || (r.ht == Head_t::Disjunctive && Potassco::size(r.head) < 2)) { + tm.transform(r); + } + else { + using Potassco::Lit_t; + Atom_t aux = newAtom(); + Lit_t auxB = Potassco::lit(aux); + Rule rAux1 = r; // aux :- body + rAux1.ht = Head_t::Disjunctive; + rAux1.head = Potassco::toSpan(&aux, 1); + Rule rAux2 = Rule::normal(r.ht, r.head, Potassco::toSpan(&auxB, 1)); // head :- auxB + if (handleNatively(rAux1)) { addRule(rAux1); } + else { + RuleTransform::Strategy st = transformNoAux(rAux1) ? RuleTransform::strategy_select_no_aux : RuleTransform::strategy_default; + tm.transform(rAux1, st); + } + if (handleNatively(rAux2)) { addRule(rAux2); } + else { tm.transform(rAux2); } + } + delete extended_[i]; + } + extended_.clear(); + incTrAux(numAtoms() - a); +} + +void LogicProgram::transformIntegrity(uint32 nAtoms, uint32 maxAux) { + if (stats.bodies[1][Body_t::Count] == 0) { return; } + // find all constraint rules that are integrity constraints + BodyList integrity; + for (uint32 i = 0, end = static_cast(bodies_.size()); i != end; ++i) { + PrgBody* b = bodies_[i]; + if (b->relevant() && b->type() == Body_t::Count && b->value() == value_false) { + integrity.push_back(b); + } + } + if (!integrity.empty() && (integrity.size() == 1 || (nAtoms/double(bodies_.size()) > 0.5 && integrity.size() / double(bodies_.size()) < 0.01))) { + uint32 aux = static_cast(atoms_.size()); + RuleTransform tr(*this); + RuleBuilder temp; + // transform integrity constraints + for (BodyList::size_type i = 0; i != integrity.size(); ++i) { + PrgBody* b = integrity[i]; + uint32 est = b->bound()*( b->sumW()-b->bound() ); + if (est > maxAux) { + // reached limit on aux atoms - stop transformation + break; + } + if (b->toData(*this, temp) && temp.bodyType() != Body_t::Normal) { + maxAux -= est; + // transform rule + setFrozen(false); + upStat(Head_t::Disjunctive, -1); + upStat(Body_t::Count, -1); + tr.transform(Rule::sum(Head_t::Disjunctive, Potassco::toSpan(), temp.bound(), Potassco::toSpan(temp.sum(), temp.bodySize()))); + setFrozen(true); + // propagate integrity condition to new rules + propagate(true); + b->markRemoved(); + } + temp.clear(); + } + // create vars for new atoms/bodies + for (uint32 i = aux; i != atoms_.size(); ++i) { + PrgAtom* a = atoms_[i]; + for (PrgAtom::sup_iterator it = a->supps_begin(); it != a->supps_end(); ++it) { + PrgBody* nb = bodies_[it->node()]; + assert(nb->value() != value_false); + nb->assignVar(*this); + } + a->assignVar(*this, a->supports() ? *a->supps_begin() : PrgEdge::noEdge()); + } + incTrAux(static_cast(atoms_.size()) - aux); + } +} + +void LogicProgram::prepareExternals() { + if (auxData_->external.empty()) { return; } + VarVec& external = auxData_->external; + VarVec::iterator j = external.begin(); + for (VarVec::const_iterator it = j, end = external.end(); it != end; ++it) { + Atom_t id = getRootId(decodeExternal(*it).first); + const PrgAtom* atom = getAtom(id); + if (!atomState_.inHead(id) && (atom->supports() == 0 || *atom->supps_begin() == PrgEdge::noEdge())) { + Potassco::Value_t value = atom->supports() == 0 ? static_cast(atom->freezeValue()) : Potassco::Value_t::Release; + atomState_.addToHead(id); + *j++ = encodeExternal(id, value); + } + } + for (VarVec::const_iterator it = external.begin(), end = external.end(); it != end; ++it) { + atomState_.clearRule(decodeExternal(*it).first); + } +} +void LogicProgram::updateFrozenAtoms() { + if (frozen_.empty()) { return; } + PrgBody* support = 0; + VarVec::iterator j = frozen_.begin(); + for (VarVec::const_iterator it = j, end = frozen_.end(); it != end; ++it) { + Id_t id = getRootId(*it); + PrgAtom* a = getAtom(id); + assert(a->frozen()); + a->resetId(id, false); + if (a->supports() == 0) { + assert(a->relevant()); + CLASP_ASSERT_CONTRACT_MSG(id < startAuxAtom(), "frozen atom shall be an input atom"); + if (!support) { support = getTrueBody(); } + a->setIgnoreScc(true); + support->addHead(a, PrgEdge::GammaChoice); + *j++ = id; // still frozen + } + else { + a->clearFrozen(); + if (*a->supps_begin() == PrgEdge::noEdge()) { + // remove dummy edge added in unfreeze() + a->removeSupport(PrgEdge::noEdge()); + } + if (!isNew(id) && incData_) { + // add to unfreeze so that we can later perform completion + incData_->unfreeze.push_back(id); + } + } + } + frozen_.erase(j, frozen_.end()); +} + +void LogicProgram::prepareProgram(bool checkSccs) { + assert(!frozen()); + uint32 nAtoms = (input_.hi = std::min(input_.hi, endAtom())); + stats.auxAtoms += endAtom() - nAtoms; + for (uint32 i = 0; i != RuleStats::numKeys(); ++i) { + stats.rules[1][i] += stats.rules[0][i]; + } + for (uint32 i = 0; i != BodyStats::numKeys(); ++i) { + stats.bodies[1][i] += stats.bodies[0][i]; + } + statsId_ = 1; + transformExtended(); + prepareExternals(); + freezeTheory(); + updateFrozenAtoms(); + PrgAtom* suppAtom = 0; + if (opts_.suppMod) { + VarVec h; + suppAtom = getAtom(newAtom()); + h.assign(1, suppAtom->id()); + addRule(Head_t::Choice, Potassco::toSpan(h), Potassco::toSpan()); + Potassco::Lit_t body = Potassco::lit(suppAtom->id()); + h.clear(); + for (Atom_t v = startAtom(), end = suppAtom->id(); v != end; ++v) { + if (atoms_[v]->supports() != 0) { h.push_back(v); } + } + addRule(Head_t::Choice, Potassco::toSpan(h), Potassco::toSpan(&body, 1)); + } + setFrozen(true); + Preprocessor p; + if (hasConflict() || !propagate(true) || !p.preprocess(*this, opts_.iters != 0 ? Preprocessor::full_eq : Preprocessor::no_eq, opts_.iters, opts_.dfOrder != 0)) { + setConflict(); + return; + } + if (suppAtom && (!assignValue(suppAtom, value_false, PrgEdge::noEdge()) || !propagate(true))) { + setConflict(); + return; + } + if (opts_.erMode == mode_transform_integ || opts_.erMode == mode_transform_dynamic) { + nAtoms -= startAtom(); + transformIntegrity(nAtoms, std::min(uint32(15000), nAtoms*2)); + } + addMinimize(); + uint32 sccs = 0; + if (checkSccs) { + uint32 startScc = incData_ ? incData_->startScc : 0; + SccChecker c(*this, auxData_->scc, startScc); + sccs = c.sccs(); + stats.sccs = (sccs-startScc); + if (incData_) { incData_->startScc = c.sccs(); } + if (!disjunctions_.empty() || (opts_.erMode == mode_transform_scc && sccs)) { + // reset node ids changed by scc checking + for (uint32 i = 0; i != bodies_.size(); ++i) { + if (getBody(i)->relevant()) { getBody(i)->resetId(i, true); } + } + for (uint32 i = 0; i != atoms_.size(); ++i) { + if (getAtom(i)->relevant()) { getAtom(i)->resetId(i, true); } + } + } + } + else { stats.sccs = PrgNode::noScc; } + finalizeDisjunctions(p, sccs); + prepareComponents(); + prepareOutputTable(); + if (theory_) { + TFilter f = { this }; + theory_->filter(f); + } + stats.atoms = static_cast(atoms_.size()) - startAtom(); + bodyIndex_.clear(); + disjIndex_.clear(); +} +void LogicProgram::freezeTheory() { + if (theory_) { + for (TheoryData::atom_iterator it = theory_->currBegin(), end = theory_->end(); it != end; ++it) { + const Potassco::TheoryAtom& a = **it; + if (isFact(a.atom()) || !isNew(a.atom())) { continue; } + PrgAtom* atom = resize(a.atom()); + if (!atom->frozen() && atom->supports() == 0 && atom->relevant()) { + pushFrozen(atom, value_free); + } + } + } +} +bool LogicProgram::TFilter::operator()(const Potassco::TheoryAtom& a) const { + Atom_t id = a.atom(); + if (self->getLiteral(id) != lit_false() && self->getRootAtom(id)->value() != value_false) { + self->ctx()->setFrozen(self->getLiteral(id).var(), true); + return false; + } + PrgAtom* at = self->getRootAtom(id); + return !at->frozen(); +} +struct LogicProgram::DlpTr : public RuleTransform::ProgramAdapter { + DlpTr(LogicProgram* x, EdgeType et) : self(x), type(et), scc(0) {} + Atom_t newAtom() { + CLASP_FAIL_IF(type == PrgEdge::Gamma, "shifting must not introduce new atoms!"); + Atom_t x = self->newAtom(); + PrgAtom* a = self->getAtom(x); + self->auxData_->scc.push_back(a); + a->setScc(scc); + a->setSeen(true); + atoms.push_back(x); + return x; + } + virtual void addRule(const Rule& r) { + SRule meta; + if (!self->simplifyRule(r, rule, meta)) { return; } + bool gamma = type == PrgEdge::Gamma; + Rule rs = rule.rule(); + PrgAtom* a = self->getAtom(rs.head[0]); + PrgBody* B = self->assignBodyFor(rs, meta, type, gamma); + if (B->value() != value_false && !B->hasHead(a, PrgEdge::Normal)) { + B->addHead(a, type); + self->stats.gammas += uint32(gamma); + } + } + LogicProgram* self; + EdgeType type; + uint32 scc; + VarVec atoms; + RuleBuilder rule; +}; + +// replace disjunctions with gamma (shifted) and delta (component-shifted) rules +void LogicProgram::finalizeDisjunctions(Preprocessor& p, uint32 numSccs) { + if (disjunctions_.empty()) { return; } + VarVec head; BodyList supports; + disjIndex_.clear(); + SccMap sccMap; + sccMap.resize(numSccs, 0); + enum SccFlag { seen_scc = 1u, is_scc_non_hcf = 128u }; + // replace disjunctions with shifted rules and non-hcf-disjunctions + DisjList disj; disj.swap(disjunctions_); + setFrozen(false); + uint32 shifted = 0; + stats.nonHcfs = uint32(nonHcfs_.size()); + Literal bot = lit_false(); + DlpTr tr(this, PrgEdge::Gamma); + RuleTransform shifter(tr); + Potassco::LitVec rb; + VarVec rh; + for (uint32 id = 0, maxId = sizeVec(disj); id != maxId; ++id) { + PrgDisj* d = disj[id]; + Literal dx = d->inUpper() ? d->literal() : bot; + d->resetId(id, true); // id changed during scc checking + PrgEdge e = PrgEdge::newEdge(*d, PrgEdge::Choice); + // remove from program and + // replace with shifted rules or component-shifted disjunction + head.clear(); supports.clear(); + for (PrgDisj::atom_iterator it = d->begin(), end = d->end(); it != end; ++it) { + uint32 aId = *it; + PrgAtom* at = getAtom(aId); + at->removeSupport(e); + if (dx == bot) { continue; } + if (at->eq()) { + at = getAtom(aId = getRootId(aId)); + } + if (isFact(at)){ + dx = bot; + continue; + } + if (at->inUpper()) { + head.push_back(aId); + if (at->scc() != PrgNode::noScc){ sccMap[at->scc()] = seen_scc; } + } + } + EdgeVec temp; + d->clearSupports(temp); + for (EdgeVec::iterator it = temp.begin(), end = temp.end(); it != end; ++it) { + PrgBody* b = getBody(it->node()); + if (b->relevant() && b->value() != value_false) { supports.push_back(b); } + b->removeHead(d, PrgEdge::Normal); + } + d->destroy(); + // create shortcut for supports to avoid duplications during shifting + Literal supportLit = dx != bot ? getEqAtomLit(dx, supports, p, sccMap) : dx; + // create shifted rules and split disjunctions into non-hcf components + for (VarVec::iterator hIt = head.begin(), hEnd = head.end(); hIt != hEnd; ++hIt) { + uint32 scc = getAtom(*hIt)->scc(); + if (scc == PrgNode::noScc || (sccMap[scc] & seen_scc) != 0) { + if (scc != PrgNode::noScc) { sccMap[scc] &= ~seen_scc; } + else { scc = UINT32_MAX; } + rh.assign(1, *hIt); + rb.clear(); + if (supportLit.var() != 0) { rb.push_back(toInt(supportLit)); } + else if (supportLit.sign()){ continue; } + for (VarVec::iterator oIt = head.begin(); oIt != hEnd; ++oIt) { + if (oIt != hIt) { + if (getAtom(*oIt)->scc() == scc) { rh.push_back(*oIt); } + else { rb.push_back(Potassco::neg(*oIt)); } + } + } + SRule meta; + if (!simplifyRule(Rule::normal(Head_t::Disjunctive, Potassco::toSpan(rh), Potassco::toSpan(rb)), rule_, meta)) { + continue; + } + Rule sr = rule_.rule(); + PrgBody* B = assignBodyFor(sr, meta, PrgEdge::Normal, true); + if (B->value() != value_false && Potassco::size(sr.head) == 1) { + ++shifted; + B->addHead(getAtom(sr.head[0]), PrgEdge::Normal); + } + else if (B->value() != value_false && Potassco::size(sr.head) > 1) { + PrgDisj* x = getDisjFor(sr.head, 0); + B->addHead(x, PrgEdge::Normal); + x->assignVar(*this, *x->supps_begin()); + x->setInUpper(true); + x->setSeen(true); + if ((sccMap[scc] & is_scc_non_hcf) == 0) { + sccMap[scc] |= is_scc_non_hcf; + nonHcfs_.add(scc); + } + if (!options().noGamma) { + shifter.transform(sr); + } + else { + // only add support edge + for (PrgDisj::atom_iterator a = x->begin(), end = x->end(); a != end; ++a) { + B->addHead(getAtom(*a), PrgEdge::GammaChoice); + } + } + } + } + } + } + if (!disjunctions_.empty() && nonHcfs_.config == 0) { + nonHcfs_.config = ctx()->configuration()->config("tester"); + } + upStat(RK(Normal), shifted); + stats.nonHcfs = uint32(nonHcfs_.size()) - stats.nonHcfs; + rh.clear(); + setFrozen(true); +} +// optionally transform extended rules in sccs +void LogicProgram::prepareComponents() { + int trRec = opts_.erMode == mode_transform_scc; + // HACK: force transformation of extended rules in non-hcf components + // REMOVE this once minimality check supports aggregates + if (!disjunctions_.empty() && trRec != 1) { + trRec = 2; + } + if (trRec != 0) { + DlpTr tr(this, PrgEdge::Normal); + RuleTransform trans(tr); + RuleBuilder temp; + setFrozen(false); + EdgeVec heads; + // find recursive aggregates + for (uint32 bIdx = 0, bEnd = numBodies(); bIdx != bEnd; ++bIdx) { + PrgBody* B = bodies_[bIdx]; + if (B->type() == Body_t::Normal || !B->hasVar() || B->value() == value_false) { continue; } // not aggregate or not relevant + tr.scc = B->scc(*this); + if (tr.scc == PrgNode::noScc || (trRec == 2 && !nonHcfs_.find(tr.scc))) { continue; } // not recursive + // transform all rules a :- B, where scc(a) == scc(B): + heads.clear(); + for (PrgBody::head_iterator hIt = B->heads_begin(), hEnd = B->heads_end(); hIt != hEnd; ++hIt) { + assert(hIt->isAtom()); + if (getAtom(hIt->node())->scc() == tr.scc) { heads.push_back(*hIt); } + } + if (heads.empty()) { continue; } + using Potassco::Lit_t; + Head_t ht = !isChoice(heads[0].type()) ? Head_t::Disjunctive : Head_t::Choice; + Atom_t h = heads[0].node(); + Lit_t aux = 0; + if (heads.size() > 1) { // more than one head, make body eq to some new aux atom + ht = Head_t::Disjunctive; + h = tr.newAtom(); + aux = Potassco::lit(h); + } + temp.clear(); + if (!B->toData(*this, temp) || temp.bodyType() == Body_t::Normal) { + B->simplify(*this, true, 0); + continue; + } + trans.transform(Rule::sum(ht, Potassco::toSpan(&h, 1), temp.bound(), Potassco::toSpan(temp.sum(), temp.bodySize()))); + for (EdgeVec::const_iterator hIt = heads.begin(); hIt != heads.end(); ++hIt) { + B->removeHead(getAtom(hIt->node()), hIt->type()); + if (h != hIt->node()) { + ht = !isChoice(hIt->type()) ? Head_t::Disjunctive : Head_t::Choice; + h = hIt->node(); + tr.addRule(Rule::normal(ht, Potassco::toSpan(&h, 1), Potassco::toSpan(&aux, 1))); + } + } + } + incTrAux(sizeVec(tr.atoms)); + while (!tr.atoms.empty()) { + PrgAtom* ax = getAtom(tr.atoms.back()); + tr.atoms.pop_back(); + if (ax->supports()) { + ax->setInUpper(true); + ax->assignVar(*this, *ax->supps_begin()); + } + else { assignValue(ax, value_false, PrgEdge::noEdge()); } + } + setFrozen(true); + } +} +void LogicProgram::prepareOutputTable() { + OutputTable& out = ctx()->output; + // add new output predicates in program order to output table + std::stable_sort(show_.begin(), show_.end(), compose22(std::less(), select1st(), select1st())); + for (ShowVec::iterator it = show_.begin(), end = show_.end(); it != end; ++it) { + Literal lit = getLiteral(it->first); + bool isAtom = it->first < startAuxAtom(); + if (!isSentinel(lit)) { out.add(it->second, lit, it->first); if (isAtom) ctx()->setOutput(lit.var(), true); } + else if (lit == lit_true()) { out.add(it->second); } + } + if (!auxData_->project.empty()) { + for (VarVec::const_iterator it = auxData_->project.begin(), end = auxData_->project.end(); it != end; ++it) { + out.addProject(getLiteral(*it)); + } + } +} +// add (completion) nogoods +bool LogicProgram::addConstraints() { + ClauseCreator gc(ctx()->master()); + if (options().iters == 0) { + gc.addDefaultFlags(ClauseCreator::clause_force_simplify); + } + ctx()->startAddConstraints(); + // handle initial conflict, if any + if (!ctx()->ok() || !ctx()->addUnary(getTrueAtom()->trueLit())) { + return false; + } + if (options().noGamma && !disjunctions_.empty()) { + // add "rule" nogoods for disjunctions + for (DisjList::const_iterator it = disjunctions_.begin(); it != disjunctions_.end(); ++it) { + gc.start().add(~(*it)->literal()); + for (PrgDisj::atom_iterator a = (*it)->begin(); a != (*it)->end(); ++a) { + gc.add(getAtom(*a)->literal()); + } + if (!gc.end()) { return false; } + } + } + // add bodies from this step + for (BodyList::const_iterator it = bodies_.begin(); it != bodies_.end(); ++it) { + if (!toConstraint((*it), *this, gc)) { return false; } + } + // add atoms thawed in this step + for (VarIter it = unfreeze_begin(), end = unfreeze_end(); it != end; ++it) { + if (!toConstraint(getAtom(*it), *this, gc)) { return false; } + } + // add atoms from this step + const bool freezeAll = incData_ && ctx()->satPrepro.get() != 0; + const uint32 hiAtom = startAuxAtom(); + uint32 id = startAtom(); + for (AtomList::const_iterator it = atoms_.begin()+startAtom(), end = atoms_.end(); it != end; ++it, ++id) { + if (!toConstraint(*it, *this, gc)) { return false; } + if (id < hiAtom && (*it)->hasVar()){ + if (freezeAll) { ctx()->setFrozen((*it)->var(), true); } + ctx()->setInput((*it)->var(), true); + } + } + if (!auxData_->scc.empty()) { + if (ctx()->sccGraph.get() == 0) { + ctx()->sccGraph = new PrgDepGraph(static_cast(opts_.oldMap == 0)); + } + uint32 oldNodes = ctx()->sccGraph->nodes(); + ctx()->sccGraph->addSccs(*this, auxData_->scc, nonHcfs_); + stats.ufsNodes = ctx()->sccGraph->nodes()-oldNodes; + } + return true; +} +void LogicProgram::addDomRules() { + if (auxData_->dom.empty()) { return; } + VarVec domVec; + EqVec eqVec; + DomRules& doms = auxData_->dom; + Solver const& s = *ctx()->master(); + // mark any previous domain atoms so that we can decide + // whether existing variables can be used for the atoms in doms + if (incData_) { + domVec.swap(incData_->doms); + for (VarVec::const_iterator it = domVec.begin(); it != domVec.end(); ++it) { + if (s.value(*it) == value_free) { ctx()->mark(posLit(*it)); } + } + } + DomRules::iterator j; + IndexMap::const_iterator eq; + DomRule r; + for (DomRules::iterator it = (j = doms.begin()), end = doms.end(); it != end; ++it) { + Literal cond = getLiteral(it->cond); + Literal slit = getLiteral(it->atom); + Var svar = slit.var(); + if (s.isFalse(cond) || s.value(svar) != value_free) { continue; } + if (s.isTrue(cond)) { it->cond = 0; cond = lit_true(); } + // check if atom is the root for its var + if (!atomState_.isSet(it->atom, AtomState::dom_flag)) { + if (!ctx()->marked(posLit(svar))) { + // var(it->atom) is not yet used - make it->atom its root + ctx()->mark(posLit(svar)); + atomState_.set(it->atom, AtomState::dom_flag); + domVec.push_back(svar); + } + else if ((eq = domEqIndex_.find(it->atom)) != domEqIndex_.end()) { + // var(it->atom) is used but we already created a new var for it->atom + slit = posLit(svar = eq->second); + } + else { + // var(it->atom) is used - introduce new aux var and make it eq to lit(atom) + Eq n = { ctx()->addVar(Var_t::Atom, VarInfo::Nant), slit }; + eqVec.push_back(n); + svar = n.var; + slit = posLit(svar); + domEqIndex_.insert(IndexMap::value_type(static_cast(it->atom), svar)); + } + } + *j++ = (r = *it); + if (slit.sign()) { + if (r.type == DomModType::Sign) { r.bias = r.bias != 0 ? -r.bias : 0; } + else if (r.type == DomModType::True) { r.type = DomModType::False; } + else if (r.type == DomModType::False) { r.type = DomModType::True; } + } + ctx()->heuristic.add(svar, static_cast(r.type), r.bias, r.prio, cond); + } + if (j != doms.end()) { + upStat(RK(Heuristic), -static_cast(doms.end() - j)); + doms.erase(j, doms.end()); + } + // cleanup var flags + for (VarVec::const_iterator it = domVec.begin(); it != domVec.end(); ++it) { + ctx()->unmark(*it); + } + if (incData_) { + incData_->doms.swap(domVec); + } + if (!eqVec.empty()) { + ctx()->startAddConstraints(); + for (EqVec::const_iterator it = eqVec.begin(), end = eqVec.end(); it != end; ++it) { + // it->var == it->lit + ctx()->addBinary(~it->lit, posLit(it->var)); + ctx()->addBinary( it->lit, negLit(it->var)); + } + } +} + +void LogicProgram::addAcycConstraint() { + AcycRules& acyc = auxData_->acyc; + if (acyc.empty()) { return; } + SharedContext& ctx = *this->ctx(); + ExtDepGraph* graph = ctx.extGraph.get(); + const Solver& s = *ctx.master(); + if (graph) { graph->update(); } + else { ctx.extGraph = (graph = new ExtDepGraph()); } + for (AcycRules::const_iterator it = acyc.begin(), end = acyc.end(); it != end; ++it) { + Literal lit = getLiteral(it->cond); + if (!s.isFalse(lit)) { + graph->addEdge(lit, it->node[0], it->node[1]); + } + else { + upStat(RK(Acyc), -1); + } + } + if (graph->finalize(ctx) == 0) { ctx.extGraph = 0; } +} +#undef check_modular +///////////////////////////////////////////////////////////////////////////////////////// +// misc/helper functions +///////////////////////////////////////////////////////////////////////////////////////// +PrgAtom* LogicProgram::resize(Atom_t atomId) { + while (atoms_.size() <= AtomList::size_type(atomId)) { + newAtom(); + } + return getRootAtom(atomId); +} + +bool LogicProgram::propagate(bool backprop) { + assert(frozen()); + bool oldB = opts_.backprop != 0; + opts_.backprop = backprop; + for (VarVec::size_type i = 0; i != propQ_.size(); ++i) { + PrgAtom* a = getAtom(propQ_[i]); + if (!a->relevant()) { continue; } + if (!a->propagateValue(*this, backprop)) { + setConflict(); + return false; + } + if (a->hasVar() && a->id() < startAtom() && !ctx()->addUnary(a->trueLit())) { + setConflict(); + return false; + } + } + opts_.backprop = oldB; + propQ_.clear(); + return true; +} +ValueRep LogicProgram::litVal(const PrgAtom* a, bool pos) const { + if (a->value() != value_free || !a->relevant()) { + bool vSign = a->value() == value_false || !a->relevant(); + if (vSign == pos) { return value_false; } + return a->value() != value_weak_true ? value_true : value_free; + } + return value_free; +} + +// Simplifies the given normal rule H :- l1, ..., ln +// - removes true and duplicate literals from body: {T,a,b,a} -> {a, b}. +// - checks for contradictions and false literals in body: {a, not a} -> F +// - checks for satisfied head and removes false atoms from head +// POST: if true out contains the simplified normal rule. +bool LogicProgram::simplifyNormal(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body, RuleBuilder& out, SRule& meta) { + out.clear(); + out.startBody(); + meta = SRule(); + bool ok = true; + for (Potassco::LitSpan::iterator it = Potassco::begin(body), end = Potassco::end(body); it != end; ++it) { + CLASP_FAIL_IF(Potassco::atom(*it) >= bodyId, "Atom out of bounds"); + PrgAtom* a = resize(Potassco::atom(*it)); + Literal p = Literal(a->id(), *it < 0);// replace any eq atoms + ValueRep v = litVal(a, !p.sign()); + if (v == value_false || atomState_.inBody(~p)) { + ok = false; + break; + } + else if (v != value_true && !atomState_.inBody(p)) { + atomState_.addToBody(p); + out.addGoal(toInt(p)); + meta.pos += !p.sign(); + meta.hash += hashLit(p); + } + } + uint32_t bs = out.bodySize(); + meta.bid = ok ? findBody(meta.hash, Body_t::Normal, bs) : varMax; + ok = ok && pushHead(ht, head, 0, out); + for (const Potassco::Lit_t* it = out.body(); bs--;) { + atomState_.clearRule(Potassco::atom(*it++)); + } + return ok; +} + +struct IsLit { + IsLit(Potassco::Lit_t x) : lhs(x) {} + template + bool operator()(const P& rhs) const { return lhs == Potassco::lit(rhs); } + Potassco::Lit_t lhs; +}; + +// Simplifies the given sum rule: H :- lb { l1 = w1 ... ln = wn }. +// - removes assigned literals and updates lb accordingly +// - removes literals li with weight wi = 0 +// - reduces weights wi > bound() to bound +// - merges duplicate literals in sum, i.e. lb {a=w1, b=w2, a=w3} -> lb {a=w1+w3, b=w2} +// - checks for contradiction, i.e. sum contains both p and not p and both are needed +// - replaces sum with count if all weights are equal +// - replaces sum with normal body if all literals must be true for the sum to be satisfied +// POST: if true out contains the simplified rule. +bool LogicProgram::simplifySum(Head_t ht, const Potassco::AtomSpan& head, const Potassco::Sum_t& body, RuleBuilder& out, SRule& meta) { + meta = SRule(); + weight_t bound = body.bound, maxW = 1, minW = CLASP_WEIGHT_T_MAX, sumW = 0, dirty = 0; + out.clear(); + out.startSum(bound); + for (Potassco::WeightLitSpan::iterator it = Potassco::begin(body.lits), end = Potassco::end(body.lits); it != end && bound > 0; ++it) { + CLASP_ASSERT_CONTRACT_MSG(it->weight >= 0, "Non-negative weight expected!"); + CLASP_FAIL_IF(Potassco::atom(*it) >= bodyId, "Atom out of bounds"); + if (it->weight == 0) continue; // skip irrelevant lits + PrgAtom* a = resize(Potassco::atom(*it)); + Literal p = Literal(a->id(), Potassco::lit(*it) < 0);// replace any eq atoms + ValueRep v = litVal(a, !p.sign()); + weight_t w = Potassco::weight(*it); + if (v == value_true) { bound -= w; } + else if (v != value_false) { + CLASP_ASSERT_CONTRACT_MSG((CLASP_WEIGHT_T_MAX-sumW)>= w, "Integer overflow!"); + sumW += w; + if (!atomState_.inBody(p)) { + atomState_.addToBody(p); + out.addGoal(toInt(p), w); + meta.pos += !p.sign(); + meta.hash += hashLit(p); + } + else { // Merge duplicate lits + w = (std::find_if(out.sum(), out.sum() + out.bodySize(), IsLit(Potassco::lit(*it)))->weight += w); + ++dirty; + } + if (w > maxW) { maxW = w; } + if (w < minW) { minW = w; } + dirty += static_cast(atomState_.inBody(~p)); + } + } + weight_t sumR = sumW; + if (bound > 0 && (dirty || maxW > bound)) { + sumR = 0, minW = CLASP_WEIGHT_T_MAX; + for (Potassco::WeightLit_t* it = out.sum(), *end = out.sum() + out.bodySize(); it != end; ++it) { + Literal p = toLit(it->lit); + weight_t w = it->weight; + if (w > bound) { sumW -= (w - bound); it->weight = (maxW = w = bound); } + if (w < minW) { minW = w; } + sumR += w; + if (p.sign() && atomState_.inBody(~p)) { + // body contains p and ~p: we can achieve at most max(weight(p), weight(~p)) + sumR -= std::min(w, std::find_if(out.sum(), end, IsLit(Potassco::neg(it->lit)))->weight); + } + } + } + out.setBound(bound); + if (bound <= 0 || sumR < bound) { + for (const Potassco::WeightLit_t* it = out.sum(), *end = out.sum() + out.bodySize(); it != end; ++it) { atomState_.clearRule(Potassco::atom(*it)); } + return bound <= 0 && simplifyNormal(ht, head, Potassco::toSpan(), out, meta); + } + else if ((sumW - minW) < bound) { + out.weaken(Body_t::Normal); + meta.bid = findBody(meta.hash, Body_t::Normal, out.bodySize()); + bool ok = pushHead(ht, head, 0, out); + for (const Potassco::Lit_t* it = out.body(), *end = it + out.bodySize(); it != end; ++it) { + atomState_.clearRule(Potassco::atom(*it)); + } + return ok; + } + else if (minW == maxW) { + out.weaken(Body_t::Count, maxW != 1); + bound = out.bound(); + } + meta.bid = findBody(meta.hash, out.bodyType(), out.bodySize(), out.bound(), out.sum()); + bool ok = pushHead(ht, head, sumW - out.bound(), out); + for (const Potassco::WeightLit_t* it = out.sum(), *end = it + out.bodySize(); it != end; ++it) { + atomState_.clearRule(Potassco::atom(*it)); + } + return ok; +} + +// Pushes the given rule head to the body given in out. +// Pre: Body literals are marked and lits is != 0 if body is a sum. +bool LogicProgram::pushHead(Head_t ht, const Potassco::AtomSpan& head, weight_t slack, RuleBuilder& out) { + const uint8 ignoreMask = AtomState::false_flag|AtomState::head_flag; + uint32 hs = 0; + bool sat = false, sum = out.bodyType() == Body_t::Sum; + out.start(ht); + for (Potassco::AtomSpan::iterator it = Potassco::begin(head), end = Potassco::end(head); it != end; ++it) { + if (!atomState_.isSet(*it, AtomState::simp_mask)) { + out.addHead(*it); + atomState_.addToHead(*it); + ++hs; + } + else if (!atomState_.isSet(*it, ignoreMask)) { // h occurs in B+ and/or B- or is true + weight_t wp = weight_t(atomState_.inBody(posLit(*it))), wn = weight_t(atomState_.inBody(negLit(*it))); + if (wp && sum) { wp = std::find_if(out.sum(), out.sum() + out.bodySize(), IsLit(Potassco::lit(*it)))->weight; } + if (wn && sum) { wn = std::find_if(out.sum(), out.sum() + out.bodySize(), IsLit(Potassco::neg(*it)))->weight; } + if (atomState_.isFact(*it) || wp > slack) { sat = true; } + else if (wn <= slack) { + out.addHead(*it); + atomState_.addToHead(*it); + ++hs; + } + } + } + for (const Atom_t* it = out.head(), *end = it + hs; it != end; ++it) { + atomState_.clearRule(*it); + } + return !sat || (ht == Head_t::Choice && hs); +} + +bool LogicProgram::simplifyRule(const Rule& r, Potassco::RuleBuilder& out, SRule& meta) { + return r.normal() + ? simplifyNormal(r.ht, r.head, r.cond, out, meta) + : simplifySum(r.ht, r.head, r.agg, out, meta); +} +// create new atom aux representing supports, i.e. +// aux == S1 v ... v Sn +Literal LogicProgram::getEqAtomLit(Literal lit, const BodyList& supports, Preprocessor& p, const SccMap& sccMap) { + if (supports.empty() || lit == lit_false()) { return lit_false(); } + if (supports.size() == 1 && supports[0]->size() < 2) { + return supports[0]->size() == 0 ? lit_true() : supports[0]->goal(0); + } + if (p.getRootAtom(lit) != varMax) { return posLit(p.getRootAtom(lit)); } + incTrAux(1); + Atom_t auxV = newAtom(); + PrgAtom* aux = getAtom(auxV); + uint32 scc = PrgNode::noScc; + aux->setLiteral(lit); + aux->setSeen(true); + p.setRootAtom(aux->literal(), auxV); + for (BodyList::const_iterator sIt = supports.begin(); sIt != supports.end(); ++sIt) { + PrgBody* b = *sIt; + if (b->relevant() && b->value() != value_false) { + for (uint32 g = 0; scc == PrgNode::noScc && g != b->size() && !b->goal(g).sign(); ++g) { + uint32 aScc = getAtom(b->goal(g).var())->scc(); + if (aScc != PrgNode::noScc && (sccMap[aScc] & 1u)) { scc = aScc; } + } + b->addHead(aux, PrgEdge::Normal); + if (b->value() != aux->value()) { assignValue(aux, b->value(), PrgEdge::newEdge(*b, PrgEdge::Normal)); } + aux->setInUpper(true); + } + } + if (!aux->inUpper()) { + aux->setValue(value_false); + return lit_false(); + } + else if (scc != PrgNode::noScc) { + aux->setScc(scc); + auxData_->scc.push_back(aux); + } + return posLit(auxV); +} + +PrgBody* LogicProgram::getBodyFor(const Rule& r, const SRule& meta, bool addDeps) { + if (meta.bid < bodies_.size()) { + return getBody(meta.bid); + } + // no corresponding body exists, create a new object + PrgBody* b = PrgBody::create(*this, numBodies(), r, meta.pos, addDeps); + bodyIndex_.insert(IndexMap::value_type(meta.hash, b->id())); + bodies_.push_back(b); + if (b->isSupported()) { + initialSupp_.push_back(b->id()); + } + upStat(r.bt); + return b; +} +PrgBody* LogicProgram::getTrueBody() { + uint32 id = findBody(0, Body_t::Normal, 0); + if (id < bodies_.size()) { + return getBody(id); + } + return getBodyFor(Rule::normal(Head_t::Choice, Potassco::toSpan(), Potassco::toSpan()), SRule()); +} +PrgBody* LogicProgram::assignBodyFor(const Rule& r, const SRule& meta, EdgeType depEdge, bool simpStrong) { + PrgBody* b = getBodyFor(r, meta, depEdge != PrgEdge::Gamma); + if (!b->hasVar() && !b->seen()) { + uint32 eqId; + b->markDirty(); + b->simplify(*this, simpStrong, &eqId); + if (eqId != b->id()) { + assert(b->id() == bodies_.size()-1); + removeBody(b, meta.hash); + bodies_.pop_back(); + if (depEdge != PrgEdge::Gamma) { + for (uint32 i = 0; i != b->size(); ++i) { + getAtom(b->goal(i).var())->removeDep(b->id(), !b->goal(i).sign()); + } + } + b->destroy(); + b = bodies_[eqId]; + } + } + b->setSeen(true); + b->assignVar(*this); + return b; +} + +bool LogicProgram::equalLits(const PrgBody& b, const WeightLitSpan& lits) const { + WeightLitSpan::iterator lBeg = Potassco::begin(lits), lEnd = Potassco::end(lits); + for (uint32 i = 0, end = b.size(); i != end; ++i) { + Potassco::WeightLit_t wl = { toInt(b.goal(i)), b.weight(i) }; + if (!std::binary_search(lBeg, lEnd, wl)) { return false; } + } + return true; +} + +// Pre: all literals in body are marked. +uint32 LogicProgram::findBody(uint32 hash, Body_t type, uint32 size, weight_t bound, Potassco::WeightLit_t* sum) { + IndexRange bodies = bodyIndex_.equal_range(hash); + bool sorted = false; + if (type == Body_t::Normal) { bound = static_cast(size); } + for (IndexIter it = bodies.first; it != bodies.second; ++it) { + const PrgBody& b = *getBody(it->second); + if (!checkBody(b, type, size, bound) || !atomState_.inBody(b.goals_begin(), b.goals_end())) { + continue; + } + else if (!b.hasWeights()) { + return b.id(); + } + else if (sum) { + if (!sorted) { + std::sort(sum, sum + size); + sorted = true; + } + if (equalLits(b, Potassco::toSpan(sum, size))) { return b.id(); } + } + } + return varMax; +} + +uint32 LogicProgram::findEqBody(const PrgBody* b, uint32 hash) { + IndexRange bodies = bodyIndex_.equal_range(hash); + if (bodies.first == bodies.second) { return varMax; } + uint32 eqId = varMax, n = 0; + for (IndexIter it = bodies.first; it != bodies.second && eqId == varMax; ++it) { + const PrgBody& rhs = *getBody(it->second); + if (!checkBody(rhs, b->type(), b->size(), b->bound())) { continue; } + else if (b->size() == 0) { eqId = rhs.id(); } + else if (b->size() == 1) { eqId = b->goal(0) == rhs.goal(0) && b->weight(0) == rhs.weight(0) ? rhs.id() : varMax; } + else { + if (++n == 1) { std::for_each(b->goals_begin(), b->goals_end(), std::bind1st(std::mem_fun(&AtomState::addToBody), &atomState_)); } + if (!atomState_.inBody(rhs.goals_begin(), rhs.goals_end())) { continue; } + else if (!b->hasWeights()) { eqId = rhs.id(); } + else { + if (n == 1 || rule_.bodySize() == 0) { + rule_.clear(); + if (!b->toData(*this, rule_) || rule_.bodyType() != Body_t::Sum) { + rule_.clear(); + continue; + } + std::sort(rule_.sum(), rule_.sum() + rule_.bodySize()); + } + if (equalLits(rhs, Potassco::toSpan(rule_.sum(), rule_.bodySize()))) { eqId = rhs.id(); } + } + } + } + if (n) { + rule_.clear(); + std::for_each(b->goals_begin(), b->goals_end(), std::bind1st(std::mem_fun(&AtomState::clearBody), &atomState_)); + } + return eqId; +} + +PrgDisj* LogicProgram::getDisjFor(const Potassco::AtomSpan& head, uint32 headHash) { + PrgDisj* d = 0; + if (headHash) { + LogicProgram::IndexRange eqRange = disjIndex_.equal_range(headHash); + for (; eqRange.first != eqRange.second; ++eqRange.first) { + PrgDisj& o = *disjunctions_[eqRange.first->second]; + if (o.relevant() && o.size() == Potassco::size(head) && atomState_.allMarked(o.begin(), o.end(), AtomState::head_flag)) { + assert(o.id() == eqRange.first->second); + d = &o; + break; + } + } + for (Potassco::AtomSpan::iterator it = Potassco::begin(head), end = Potassco::end(head); it != end; ++it) { + atomState_.clearRule(*it); + } + } + if (!d) { + // no corresponding disjunction exists, create a new object + // and link it to all atoms + ++stats.disjunctions[statsId_]; + d = PrgDisj::create((uint32)disjunctions_.size(), head); + disjunctions_.push_back(d); + PrgEdge edge = PrgEdge::newEdge(*d, PrgEdge::Choice); + for (Potassco::AtomSpan::iterator it = Potassco::begin(head), end = Potassco::end(head); it != end; ++it) { + getAtom(*it)->addSupport(edge); + } + if (headHash) { + disjIndex_.insert(IndexMap::value_type(headHash, d->id())); + } + } + return d; +} + +// body has changed - update index +uint32 LogicProgram::update(PrgBody* body, uint32 oldHash, uint32 newHash) { + uint32 id = removeBody(body, oldHash); + if (body->relevant()) { + uint32 eqId = findEqBody(body, newHash); + if (eqId == varMax) { + // No equivalent body found. + // Add new entry to index + bodyIndex_.insert(IndexMap::value_type(newHash, id)); + } + return eqId; + } + return varMax; +} + +// body b has changed - remove old entry from body node index +uint32 LogicProgram::removeBody(PrgBody* b, uint32 hash) { + IndexRange ra = bodyIndex_.equal_range(hash); + uint32 id = b->id(); + for (; ra.first != ra.second; ++ra.first) { + if (bodies_[ra.first->second] == b) { + id = ra.first->second; + bodyIndex_.erase(ra.first); + break; + } + } + return id; +} + +PrgAtom* LogicProgram::mergeEqAtoms(PrgAtom* a, Id_t rootId) { + PrgAtom* root = getAtom(rootId = getRootId(rootId)); + ValueRep mv = getMergeValue(a, root); + assert(!a->eq() && !root->eq() && !a->frozen()); + if (a->ignoreScc()) { root->setIgnoreScc(true); } + if (mv != a->value() && !assignValue(a, mv, PrgEdge::noEdge())) { return 0; } + if (mv != root->value() && !assignValue(root, mv, PrgEdge::noEdge())){ return 0; } + a->setEq(rootId); + incEqs(Var_t::Atom); + return root; +} + +// returns whether posSize(root) <= posSize(body) +bool LogicProgram::positiveLoopSafe(PrgBody* body, PrgBody* root) const { + uint32 i = 0, end = std::min(body->size(), root->size()); + while (i != end && body->goal(i).sign() == root->goal(i).sign()) { ++i; } + return i == root->size() || root->goal(i).sign(); +} + +PrgBody* LogicProgram::mergeEqBodies(PrgBody* b, Id_t rootId, bool hashEq, bool atomsAssigned) { + PrgBody* root = getBody(rootId = getEqNode(bodies_, rootId)); + bool bp = options().backprop != 0; + if (b == root) { return root; } + assert(!b->eq() && !root->eq() && (hashEq || b->literal() == root->literal())); + if (!b->simplifyHeads(*this, atomsAssigned) || (b->value() != root->value() && (!mergeValue(b, root) || !root->propagateValue(*this, bp) || !b->propagateValue(*this, bp)))) { + setConflict(); + return 0; + } + if (hashEq || positiveLoopSafe(b, root)) { + b->setLiteral(root->literal()); + if (!root->mergeHeads(*this, *b, atomsAssigned, !hashEq)) { + setConflict(); + return 0; + } + incEqs(Var_t::Body); + b->setEq(rootId); + return root; + } + return b; +} + +const char* LogicProgram::findName(Atom_t x) const { + for (OutputTable::pred_iterator it = ctx()->output.pred_begin(), end = ctx()->output.pred_end(); it != end; ++it) { + if (it->user == x) { return it->name; } + } + for (ShowVec::const_iterator it = show_.begin(), end = show_.end(); it != end; ++it) { + if (it->first == x){ return it->second; } + } + return ""; +} +VarVec& LogicProgram::getSupportedBodies(bool sorted) { + if (sorted) { + std::stable_sort(initialSupp_.begin(), initialSupp_.end(), LessBodySize(bodies_)); + } + return initialSupp_; +} + +Atom_t LogicProgram::falseAtom() { + Atom_t aFalse = 0; + for (Var i = 1; i < atoms_.size() && !aFalse; ++i) { + if (atoms_[i]->value() == value_false || atomState_.isSet(i, AtomState::false_flag)) { + aFalse = i; + } + } + if (!aFalse) { + bool s = frozen(); + setFrozen(false); + aFalse = newAtom(); + assignValue(getAtom(aFalse), value_false, PrgEdge::noEdge()); + setFrozen(s); + } + return aFalse; +} + +bool LogicProgram::extractCondition(Id_t id, Potassco::LitVec& out) const { + out.clear(); + if (id == Clasp::Asp::falseId || (frozen() && getLiteral(id) == lit_false())) { return false; } + if (!id || isAtom(id)) { + out.assign(id != 0, Potassco::lit(id)); + return true; + } + Id_t bId = nodeId(id); + CLASP_FAIL_IF(!validBody(bId), "Invalid literal"); + const PrgBody* B = getBody(getEqBody(bId)); + out.reserve(B->size()); + for (PrgBody::goal_iterator it = B->goals_begin(), end = B->goals_end(); it != end; ++it) { + out.push_back( toInt(*it) ); + } + return true; +} +#undef RT +///////////////////////////////////////////////////////////////////////////////////////// +// class LogicProgramAdapter +///////////////////////////////////////////////////////////////////////////////////////// +LogicProgramAdapter::LogicProgramAdapter(LogicProgram& prg) : lp_(&prg), inc_(false) {} +void LogicProgramAdapter::initProgram(bool inc) { + inc_ = inc; +} +void LogicProgramAdapter::beginStep() { + if (inc_ || lp_->frozen()) { lp_->updateProgram(); } +} +void LogicProgramAdapter::endStep() { + +} +void LogicProgramAdapter::rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body) { + lp_->addRule(ht, head, body); +} +void LogicProgramAdapter::rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body) { + lp_->addRule(ht, head, bound, body); +} +void LogicProgramAdapter::minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits) { + lp_->addMinimize(prio, lits); +} +void LogicProgramAdapter::project(const Potassco::AtomSpan& atoms) { + lp_->addProject(atoms); +} +void LogicProgramAdapter::output(const Potassco::StringSpan& str, const Potassco::LitSpan& cond) { + lp_->addOutput(ConstString(str), cond); +} +void LogicProgramAdapter::external(Potassco::Atom_t a, Potassco::Value_t v) { + lp_->addExternal(a, v); +} +void LogicProgramAdapter::assume(const Potassco::LitSpan& lits) { + lp_->addAssumption(lits); +} +void LogicProgramAdapter::heuristic(Potassco::Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, const Potassco::LitSpan& cond) { + lp_->addDomHeuristic(a, t, bias, prio, cond); +} +void LogicProgramAdapter::acycEdge(int s, int t, const Potassco::LitSpan& cond) { + lp_->addAcycEdge(static_cast(s), static_cast(t), cond); +} +void LogicProgramAdapter::theoryTerm(Potassco::Id_t termId, int number) { + lp_->theoryData().addTerm(termId, number); +} +void LogicProgramAdapter::theoryTerm(Potassco::Id_t termId, const Potassco::StringSpan& name) { + lp_->theoryData().addTerm(termId, name); +} +void LogicProgramAdapter::theoryTerm(Potassco::Id_t termId, int cId, const Potassco::IdSpan& args) { + if (cId >= 0) { lp_->theoryData().addTerm(termId, static_cast(cId), args); } + else { lp_->theoryData().addTerm(termId, static_cast(cId), args); } +} +void LogicProgramAdapter::theoryElement(Potassco::Id_t elementId, const Potassco::IdSpan& terms, const Potassco::LitSpan& cond) { + lp_->theoryData().addElement(elementId, terms, lp_->newCondition(cond)); +} +void LogicProgramAdapter::theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements) { + lp_->theoryData().addAtom(atomOrZero, termId, elements); +} +void LogicProgramAdapter::theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements, Potassco::Id_t op, Potassco::Id_t rhs) { + lp_->theoryData().addAtom(atomOrZero, termId, elements, op, rhs); +} +} } // end namespace Asp + diff --git a/libclasp/src/logic_program_types.cpp b/libclasp/src/logic_program_types.cpp new file mode 100644 index 0000000..1be23ca --- /dev/null +++ b/libclasp/src/logic_program_types.cpp @@ -0,0 +1,1397 @@ +// +// Copyright (c) 2006-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include + +namespace Clasp { +namespace Asp { +static_assert((bk_lib::detail::same_type::value), "unexpected weight type"); +static_assert((bk_lib::detail::same_type::value) , "unexpected atom type"); +static_assert((bk_lib::detail::same_type::value) , "unexpected id type"); +static_assert((bk_lib::detail::same_type::value) , "unexpected literal type"); +static_assert((bk_lib::detail::same_type::value) , "unexpected weight type"); +///////////////////////////////////////////////////////////////////////////////////////// +// class RuleTransform +// +// class for transforming extended rules to normal rules +///////////////////////////////////////////////////////////////////////////////////////// +struct RuleTransform::Impl { + Impl() : adapt_(0), prg_(0) { } + struct TodoItem { + TodoItem(uint32 i, weight_t w, Atom_t v) : idx(i), bound(w), head(v) {} + uint32 idx; + weight_t bound; + Atom_t head; + }; + struct CmpW { + template + bool operator()(const P& lhs, const P& rhs) const { + return Potassco::weight(lhs) > Potassco::weight(rhs); + } + }; + typedef PodQueue TodoQueue; + typedef Potassco::LitVec LitVec; + typedef Potassco::WLitVec WLitVec; + ProgramAdapter* adapt_; + LogicProgram* prg_; + LitVec lits_; + WLitVec agg_; + SumVec sumR_; + VarVec aux_; + TodoQueue todo_; + weight_t bound_; + Atom_t newAtom() const { return prg_ ? prg_->newAtom() : adapt_->newAtom(); } + uint32 addRule(const Rule& r) const { + if (prg_){ prg_->addRule(r); } + else { adapt_->addRule(r); } + return 1; + } + uint32 addRule(Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& b) const { + return addRule(Rule::normal(ht, head, b)); + } + uint32 addRule(Atom_t h, const Potassco::LitSpan& b) const { + return addRule(Head_t::Disjunctive, Potassco::toSpan(&h, static_cast(h != 0)), b); + } + uint32 transform(Atom_t head, weight_t bound, const Potassco::WeightLitSpan& lits, Strategy s); + uint32 transformSelect(Atom_t head); + uint32 transformSplit(Atom_t head); + uint32 transformChoice(const Potassco::AtomSpan& r); + uint32 transformDisjunction(const Potassco::AtomSpan& r); + uint32 addRule(Atom_t head, bool add, uint32 idx, weight_t bound); + Atom_t getAuxVar(uint32 idx, weight_t bound) { + assert(bound > 0 && idx < agg_.size()); + uint32 k = static_cast(bound - 1); + if (aux_[k] == 0) { + todo_.push(TodoItem(idx, bound, aux_[k] = newAtom())); + } + return aux_[k]; + } +}; + +RuleTransform::RuleTransform(ProgramAdapter& prg) : impl_(new Impl()) { + impl_->adapt_ = &prg; +} +RuleTransform::RuleTransform(LogicProgram& prg) : impl_(new Impl()) { + impl_->prg_ = &prg; +} +RuleTransform::~RuleTransform() { + delete impl_; +} + +uint32 RuleTransform::transform(const Rule& r, Strategy s) { + if (r.sum()) { + Atom_t h = !Potassco::empty(r.head) ? r.head[0] : 0; + bool aux = r.ht == Head_t::Choice || size(r.head) > 1; + if (aux) { + h = impl_->newAtom(); + Potassco::Lit_t bl = Potassco::lit(h); + impl_->addRule(r.ht, r.head, Potassco::toSpan(&bl, 1)); + } + return uint32(aux) + impl_->transform(h, r.agg.bound, r.agg.lits, s); + } + else if (size(r.head) > static_cast(r.ht == Head_t::Disjunctive)) { + impl_->lits_.clear(); + uint32 nAux = (size(r.cond) > 1) && (size(r.head) > 1); + if (nAux) { + // make body eq to a new aux atom + Atom_t auxB = impl_->newAtom(); + impl_->addRule(auxB, r.cond); + impl_->lits_.push_back(Potassco::lit(auxB)); + } + else { + impl_->lits_.assign(begin(r.cond), end(r.cond)); + } + return nAux + (r.ht == Head_t::Choice ? impl_->transformChoice(r.head) : impl_->transformDisjunction(r.head)); + } + return impl_->addRule(r); +} + +// A choice rule {h1,...hn} :- BODY is replaced with: +// h1 :- BODY, not aux1. +// aux1 :- not h1. +// ... +// hn :- BODY, not auxN. +// auxN :- not hn. +uint32 RuleTransform::Impl::transformChoice(const Potassco::AtomSpan& atoms) { + uint32 nRule = 0; + Potassco::Lit_t bLit = 0; + Potassco::LitSpan bAux = Potassco::toSpan(&bLit, 1); + Atom_t hAux; + for (Potassco::AtomSpan::iterator it = Potassco::begin(atoms), end = Potassco::end(atoms); it != end; ++it) { + hAux = newAtom(); + bLit = Potassco::neg(*it); + lits_.push_back(Potassco::neg(hAux)); + nRule += addRule(*it, Potassco::toSpan(lits_)); + nRule += addRule(hAux, bAux); + lits_.pop_back(); + } + return nRule; +} + +// A disjunctive rule h1|...|hn :- BODY is replaced with: +// hi :- BODY, {not hj | 1 <= j != i <= n}. +uint32 RuleTransform::Impl::transformDisjunction(const Potassco::AtomSpan& atoms) { + uint32 bIdx = sizeVec(lits_); + for (Potassco::AtomSpan::iterator it = Potassco::begin(atoms) + 1, end = Potassco::end(atoms); it != end; ++it) { + lits_.push_back(Potassco::neg(*it)); + } + uint32 nRule = 0; + for (Potassco::AtomSpan::iterator it = Potassco::begin(atoms), end = Potassco::end(atoms);;) { + nRule += addRule(*it, Potassco::toSpan(lits_)); + if (++it == end) { break; } + lits_[bIdx++] = Potassco::neg(*(it-1)); + } + return nRule; +} + +uint32 RuleTransform::Impl::transform(Atom_t head, weight_t bound, const Potassco::WeightLitSpan& wlits, Strategy s) { + bound_ = bound; + agg_.assign(begin(wlits), end(wlits)); + if (!isSorted(agg_.begin(), agg_.end(), CmpW())) { + std::stable_sort(agg_.begin(), agg_.end(), CmpW()); + } + wsum_t sum = 0; + sumR_.resize(agg_.size()); + for (WLitVec::size_type i = agg_.size(); i--;) { + agg_[i].weight = std::min(agg_[i].weight, bound_); + sumR_[i] = (sum += agg_[i].weight); + CLASP_FAIL_IF(agg_[i].weight < 0 || sum > CLASP_WEIGHT_T_MAX, "invalid weight rule"); + } + if (bound_ > sum) { return 0; } + else if (bound_ <= 0) { return addRule(head, Potassco::toSpan()); } + else if ((sum - agg_.back().weight) < bound_) { // normal rule + lits_.clear(); + for (WLitVec::const_iterator it = agg_.begin(), end = agg_.end(); it != end; ++it) { + lits_.push_back(lit(*it)); + } + return addRule(head, Potassco::toSpan(lits_)); + } + else { + return ((s == strategy_select_no_aux || (sum < 6 && s == strategy_default)) + ? transformSelect(head) + : transformSplit(head)); + } +} + +// Exponential transformation of cardinality and weight constraint. +// Creates minimal subsets, no aux atoms. +// E.g. a rule h = 2 {a,b,c,d} is translated into the following six rules: +// h :- a, b. +// h :- a, c. +// h :- a, d. +// h :- b, c. +// h :- b, d. +// h :- c, d. +uint32 RuleTransform::Impl::transformSelect(Atom_t h) { + lits_.clear(); + uint32 nRule = 0; + wsum_t cw = 0; + assert(sumR_[0] >= bound_ && cw < bound_); + aux_.clear(); + for (uint32 it = 0, end = (uint32)agg_.size();;) { + while (cw < bound_) { + cw += Potassco::weight(agg_[it]); + lits_.push_back(Potassco::lit(agg_[it])); + aux_.push_back(it++); + } + nRule += addRule(h, Potassco::toSpan(lits_)); + do { + if (aux_.empty()) { return nRule; } + it = aux_.back(); + aux_.pop_back(); + lits_.pop_back(); + cw -= Potassco::weight(agg_[it]); + } while (++it == end || (cw + sumR_[it]) < bound_); + } +} +// Quadratic transformation of cardinality and weight constraint. +// Introduces aux atoms. +// E.g. a rule h = 2 {a,b,c,d} is translated into the following eight rules: +// h :- a, aux_1_1. +// h :- aux_1_2. +// aux_1_1 :- b. +// aux_1_1 :- aux_2_1. +// aux_1_2 :- b, aux_2_1. +// aux_1_2 :- c, d. +// aux_2_1 :- c. +// aux_2_1 :- d. +uint32 RuleTransform::Impl::transformSplit(Atom_t h) { + const weight_t bound = bound_; + uint32 nRule = 0; + uint32 level = 0; + aux_.resize(bound, 0); + todo_.clear(); + todo_.push(TodoItem(0, bound, h)); + while (!todo_.empty()) { + TodoItem i = todo_.pop_ret(); + if (i.idx > level) { + // We are about to start a new level of the tree - reset aux_ + level = i.idx; + aux_.assign(bound, 0); + } + // For a todo item i with head h and lit x = agg_[i.idx] create at most two rules: + // r1: h :- x, aux(i.idx+1, i.bound-weight(x)) + // r2: h :- aux(i.idx+1, i.bound). + // The first rule r1 represents the case where x is true, while + // the second rule encodes the case where the literal is false. + nRule += addRule(i.head, true, i.idx, i.bound - agg_[i.idx].weight); + nRule += addRule(i.head, false, i.idx, i.bound); + } + return nRule; +} + +// Creates a rule head :- agg_[idx], aux(idx+1, bound) or head :- aux(idx+1, bound) or depending on add. +uint32 RuleTransform::Impl::addRule(Atom_t head, bool add, uint32 bIdx, weight_t bound) { + const weight_t minW = agg_.back().weight; + const wsum_t maxW = sumR_[bIdx + 1]; + if (bound <= 0) { + assert(add); + lits_.assign(1, agg_[bIdx].lit); + return addRule(head, Potassco::toSpan(lits_)); + } + if ((maxW - minW) < bound) { + // remaining literals are all needed to satisfy bound + bIdx += static_cast(!add); + if (maxW >= bound) { + lits_.clear(); + for (; bIdx != agg_.size(); ++bIdx) { lits_.push_back(agg_[bIdx].lit); } + return addRule(head, Potassco::toSpan(lits_)); + } + return 0; + } + lits_.clear(); + if (add) { lits_.push_back(agg_[bIdx].lit); } + lits_.push_back(Potassco::lit(getAuxVar(bIdx + 1, bound))); + return addRule(head, Potassco::toSpan(lits_)); +} +///////////////////////////////////////////////////////////////////////////////////////// +// class SccChecker +// +// SCC/cycle checking +///////////////////////////////////////////////////////////////////////////////////////// +SccChecker::SccChecker(LogicProgram& prg, AtomList& sccAtoms, uint32 startScc) + : prg_(&prg), sccAtoms_(&sccAtoms), count_(0), sccs_(startScc) { + for (uint32 i = 0; i != prg.numAtoms(); ++i) { + visit(prg.getAtom(i)); + } + for (uint32 i = 0; i != prg.numBodies(); ++i) { + visit(prg.getBody(i)); + } +} + +void SccChecker::visitDfs(PrgNode* node, NodeType t) { + if (!prg_ || !doVisit(node)) { + return; + } + callStack_.clear(); + nodeStack_.clear(); + count_ = 0; + addCall(node, t, 0); + while (!callStack_.empty()) { + Call c = callStack_.back(); + callStack_.pop_back(); + if (!recurse(c)) { + node = unpackNode(c.node); + if (c.min < node->id()) { + node->resetId( c.min, true ); + } + else if (c.node == nodeStack_.back()) { + // node is trivially-connected; all such nodes are in the same Pseudo-SCC + if (isNode(nodeStack_.back(), PrgNode::Atom)) { + static_cast(node)->setScc(PrgNode::noScc); + } + node->resetId(PrgNode::noNode, true); + nodeStack_.pop_back(); + } + else { // non-trivial SCC + PrgNode* succVertex; + do { + succVertex = unpackNode(nodeStack_.back()); + if (isNode(nodeStack_.back(), PrgNode::Atom)) { + static_cast(succVertex)->setScc(sccs_); + sccAtoms_->push_back(static_cast(succVertex)); + } + nodeStack_.pop_back(); + succVertex->resetId(PrgNode::noNode, true); + } while (succVertex != node); + ++sccs_; + } + } + } +} + +bool SccChecker::recurse(Call& c) { + PrgNode* n = unpackNode(c.node); + if (!n->seen()) { + nodeStack_.push_back(c.node); + c.min = count_++; + n->resetId(c.min, true); + } + if (isNode(c.node, PrgNode::Body)) { + PrgBody* b = static_cast(n); + PrgHead* h = 0; NodeType t; + for (PrgBody::head_iterator it = b->heads_begin() + c.next, end = b->heads_end(); it != end; ++it) { + if (it->isAtom()){ h = prg_->getAtom(it->node()); t = PrgNode::Atom; } + else { h = prg_->getDisj(it->node()); t = PrgNode::Disj; } + if (doVisit(h, false) && onNode(h, t, c, static_cast(it-b->heads_begin()))) { + return true; + } + } + } + else if (isNode(c.node, PrgNode::Atom)) { + PrgAtom* a = static_cast(n); + for (PrgAtom::dep_iterator it = a->deps_begin() + c.next, end = a->deps_end(); it != end; ++it) { + if (it->sign()) continue; + PrgBody* bn = prg_->getBody(it->var()); + if (doVisit(bn, false) && onNode(bn, PrgNode::Body, c, static_cast(it-a->deps_begin()))) { + return true; + } + } + } + else if (isNode(c.node, PrgNode::Disj)) { + PrgDisj* d = static_cast(n); + for (PrgDisj::atom_iterator it = d->begin() + c.next, end = d->end(); it != end; ++it) { + PrgAtom* a = prg_->getAtom(*it); + if (doVisit(a, false) && onNode(a, PrgNode::Atom, c, static_cast(it-d->begin()))) { + return true; + } + } + } + return false; +} + +bool SccChecker::onNode(PrgNode* n, NodeType t, Call& c, uint32 data) { + if (!n->seen()) { + Call rec = {c.node, c.min, data}; + callStack_.push_back(rec); + addCall(n, t, 0); + return true; + } + if (n->id() < c.min) { + c.min = n->id(); + } + return false; +} +///////////////////////////////////////////////////////////////////////////////////////// +PrgNode::PrgNode(uint32 id, bool checkScc) + : litId_(noLit), noScc_(uint32(!checkScc)), id_(id), val_(value_free), eq_(0), seen_(0) { + static_assert(sizeof(PrgNode) == sizeof(uint64), "Unsupported Alignment"); + CLASP_FAIL_IF(id_ != id, "Id out of range"); +} +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgHead +///////////////////////////////////////////////////////////////////////////////////////// +PrgHead::PrgHead(uint32 id, NodeType t, uint32 data, bool checkScc) + : PrgNode(id, checkScc) + , data_(data), upper_(0), dirty_(0), freeze_(0), isAtom_(t == PrgNode::Atom) { + struct X { uint64 x; EdgeVec y; uint32 z; }; + static_assert(sizeof(PrgHead) == sizeof(X), "Unsupported Alignment"); +} +// Adds the node with given id as a support to this head +// and marks the head as dirty so that any duplicates/false/eq +// supports are removed once simplify() is called. +void PrgHead::addSupport(PrgEdge r, Simplify s) { + supports_.push_back(r); + if (s == force_simplify) { dirty_ = (supports_.size() > 1); } +} +// Removes the given node from the set of supports of this head. +void PrgHead::removeSupport(PrgEdge r) { + if (relevant()) { + supports_.erase(std::remove(supports_.begin(), supports_.end(), r), supports_.end()); + } + dirty_ = 1; +} + +void PrgHead::clearSupports() { + supports_.clear(); + upper_ = 0; + dirty_ = 0; +} +// Simplifies the set of predecessors supporting this head. +// Removes false/eq supports and returns the number of +// different supporting literals in numDiffSupps. +bool PrgHead::simplifySupports(LogicProgram& prg, bool strong, uint32* numDiffSupps) { + uint32 numLits = supports(); + uint32 choices = 0; + if (dirty_ == 1) { + dirty_ = 0; + numLits = 0; + SharedContext& ctx = *prg.ctx(); + EdgeVec::iterator it,n,j= supports_.begin(); + for (it = supports_.begin(); it != supports_.end(); ++it) { + PrgNode* x = prg.getSupp(*it); + if (x->relevant() && x->value() != value_false && (!strong || x->hasVar())) { + if (!x->seen()) { *j++ = *it; x->setSeen(true); } + else if (!choices) { continue; } + else { + for (n = supports_.begin(); n != it && n->node() != it->node(); ++n) {;} + if (*it < *n) { *n = *it; } + else { continue; } + } + choices += (it->isBody() && it->isChoice()); + if (strong && !ctx.marked(x->literal())) { + ++numLits; + ctx.mark(x->literal()); + } + } + } + supports_.erase(j, supports_.end()); + uint32 dis = 0; + choices = 0; + for (it = supports_.begin(); it != supports_.end(); ++it) { + PrgNode* x = prg.getSupp(*it); + x->setSeen(false); + if (strong && ctx.marked(x->literal())) { ctx.unmark(x->var()); } + if (it->isChoice()) { + ++choices; + dis += it->isDisj(); + } + } + numLits += choices; + } + if (numDiffSupps) { *numDiffSupps = numLits; } + return supports() > 0 || prg.assignValue(this, value_false, PrgEdge::noEdge()); +} + +// Assigns a variable to this head. +// No support: no var and value false +// More than one support or type not normal or no eq: new var +// Exactly one support that is normal: use that +void PrgHead::assignVar(LogicProgram& prg, PrgEdge support, bool allowEq) { + if (hasVar() || !relevant()) { return; } + uint32 numS = supports(); + if (numS == 0 && support == PrgEdge::noEdge()) { + prg.assignValue(this, value_false, support); + } + else { + PrgNode* sup = prg.getSupp(support); + bool newVar = numS > 1 || (!allowEq && Var_t::isAtom(prg.ctx()->varInfo(sup->var()).type())); + if (support.isNormal() && sup->hasVar() && (!newVar || sup->value() == value_true)) { + // head is equivalent to sup + setLiteral(sup->literal()); + prg.ctx()->setVarEq(var(), true); + prg.incEqs(Var_t::Hybrid); + } + else { + setLiteral(posLit(prg.ctx()->addVar(Var_t::Atom, 0))); + } + } +} + +// Backpropagates the value of this head to its supports. +bool PrgHead::backpropagate(LogicProgram& prg, ValueRep val, bool bpFull) { + bool ok = true; + if (val == value_false) { + // a false head can't have supports + EdgeVec temp; temp.swap(supports_); + markDirty(); + for (EdgeIterator it = temp.begin(), end = temp.end(); it != end && ok; ++it) { + if (it->isBody()) { + ok = prg.getBody(it->node())->propagateAssigned(prg, this, it->type()); + } + else { assert(it->isDisj()); + ok = prg.getDisj(it->node())->propagateAssigned(prg, this, it->type()); + } + } + } + else if (val != value_free && supports() == 1 && bpFull) { + // head must be true and only has one support, thus the only support must + // be true, too. + PrgBody* b = 0; + if (supports_[0].isBody()) { + b = prg.getBody(supports_[0].node()); + } + else if (supports_[0].isDisj()) { + PrgDisj* d = prg.getDisj(supports_[0].node()); + if (d->supports() == 1) { b = prg.getBody(d->supps_begin()->node()); } + } + ok = !b || b->value() == val || (b->assignValue(val) && b->propagateValue(prg, bpFull)); + } + return ok; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgAtom +///////////////////////////////////////////////////////////////////////////////////////// +PrgAtom::PrgAtom(uint32 id, bool checkScc) + : PrgHead(id, PrgNode::Atom, PrgNode::noScc, checkScc) { + static_assert(sizeof(PrgAtom) == sizeof(PrgHead) + sizeof(LitVec), "Unsupported Alignment"); +} + +void PrgAtom::setEqGoal(Literal x) { + if (eq()) { + data_ = x.sign() ? x.var() : noScc; + } +} +Literal PrgAtom::eqGoal(bool sign) const { + if (!eq() || sign || data_ == noScc) { + return Literal(id(), sign); + } + return negLit(data_); +} + +// Adds a dependency between this atom and the body with +// the given id. If pos is true, atom appears positively +// in body, otherwise negatively. +void PrgAtom::addDep(Var bodyId, bool pos) { + deps_.push_back(Literal(bodyId, !pos)); +} + +// Removes a dependency between this atom and the body with +// the given id. If pos is true, atom appears positively +// in body, otherwise negatively. +void PrgAtom::removeDep(Var bodyId, bool pos) { + LitVec::iterator it = std::find(deps_.begin(), deps_.end(), Literal(bodyId, !pos)); + if (it != deps_.end()) { deps_.erase(it); } +} + +// Removes the subset of dependencies given by d +void PrgAtom::clearDeps(Dependency d) { + if (d == dep_all) { + deps_.clear(); + } + else { + bool sign = d == dep_neg; + LitVec::iterator j = deps_.begin(); + for (LitVec::iterator it = deps_.begin(), end = deps_.end(); it != end; ++it) { + if (it->sign() != sign) { *j++ = *it; } + } + deps_.erase(j, deps_.end()); + } +} + +bool PrgAtom::hasDep(Dependency d) const { + if (d == dep_all) { return !deps_.empty(); } + for (LitVec::const_iterator it = deps_.begin(), end = deps_.end(); it != end; ++it) { + if (static_cast(it->sign()) == d) { return true; } + } + return false; +} + +bool PrgAtom::inDisj() const { + for (EdgeIterator it= supports_.begin(), end = supports_.end(); it != end; ++it) { + if (it->isDisj()) { return true; } + } + return false; +} + +// Propagates the value of this atom to its depending bodies +// and, if backpropagation is enabled, to its supporting bodies/disjunctions. +// PRE: value() != value_free +bool PrgAtom::propagateValue(LogicProgram& prg, bool backprop) { + ValueRep val = value(); + assert(val != value_free); + // propagate value forward + Literal dep = posLit(id()); + for (dep_iterator it = deps_.begin(), end = deps_end(); it != end; ++it) { + if (!prg.getBody(it->var())->propagateAssigned(prg, dep ^ it->sign(), val)) { + return false; + } + } + if (inDisj() && prg.isFact(this)) { + // - atom is true, thus all disjunctive rules containing it are superfluous + EdgeVec temp; temp.swap(supports_); + EdgeVec::iterator j = temp.begin(); + EdgeType t = PrgEdge::Choice; + for (EdgeIterator it= temp.begin(), end = temp.end(); it != end; ++it) { + if (!it->isDisj()) { *j++ = *it; } + else if (!prg.getDisj(it->node())->propagateAssigned(prg, this, t)){ return false; } + } + temp.erase(j, temp.end()); + supports_.swap(temp); + } + return backpropagate(prg, val, backprop); +} + +// Adds the atom-oriented nogoods for this atom in form of clauses. +// Adds the support clause [~a S1...Sn] (where each Si is a supporting node of a) +// representing the tableau-rules BTA and FFA. +// Furthermore, adds the clause [a ~Bj] representing tableau-rules FTA and BFA +// if Bj supports a via a "normal" edge. +bool PrgAtom::addConstraints(const LogicProgram& prg, ClauseCreator& gc) { + SharedContext& ctx = *prg.ctx(); + EdgeVec::iterator j = supports_.begin(); + bool nant = false; + gc.start().add(~literal()); + for (EdgeVec::iterator it = supports_.begin(); it != supports_.end(); ++it) { + PrgNode* n = prg.getSupp(*it); + Literal B = n->literal(); + // consider only bodies which are part of the simplified program, i.e. + // are associated with a variable in the solver. + if (n->relevant() && n->hasVar()) { + *j++ = *it; + nant = nant || it->isChoice(); + if (!it->isDisj()) { gc.add(B); } + if (it->isNormal() && !ctx.addBinary(literal(), ~B)) { // FTA/BFA + return false; + } + } + } + supports_.erase(j, supports_.end()); + if (nant || hasDep(PrgAtom::dep_neg)) { ctx.setNant(var(), true); } + return gc.end(ClauseCreator::clause_force_simplify); +} +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgBody +///////////////////////////////////////////////////////////////////////////////////////// +PrgBody::PrgBody(uint32 id, LogicProgram& prg, const Potassco::LitSpan& lits, uint32 pos, bool addDeps) + : PrgNode(id, true) { + init(Body_t::Normal, toU32(Potassco::size(lits))); + Norm* c = new (data_)Norm(); + unsupp_ = pos; + // store B+ followed by B- + Literal* p[2] = {c->lits, c->lits + pos}; + for (Potassco::LitSpan::iterator it = Potassco::begin(lits), end = Potassco::end(lits); it != end; ++it) { + CLASP_ASSERT_CONTRACT_MSG(*it != 0, "body not simplified"); + Literal*& n = p[*it < 0]; + *n = toLit(*it); + if (addDeps) { prg.getAtom(n->var())->addDep(id, !n->sign()); } + ++n; + } +} + +PrgBody::PrgBody(uint32 id, LogicProgram& prg, const Potassco::Sum_t& sum, bool hasWeights, uint32 pos, bool addDeps) + : PrgNode(id, true) { + init(hasWeights ? Body_t::Sum : Body_t::Count, toU32(Potassco::size(sum.lits))); + Agg* a = new (data_) Agg(); + if (!hasWeights) { + a->bound = sum.bound; + unsupp_ = sum.bound - static_cast(size_ - pos); + } + else { + a->sum = SumData::create(size_, sum.bound, 0); + unsupp_ = sum.bound; + } + // store B+ followed by B- followed by optional weights + Literal* base = a->lits; + Literal* p[2] = {base, base + pos}; + weight_t* weights = hasWeights ? a->sum->weights : 0; + for (Potassco::WeightLitSpan::iterator it = Potassco::begin(sum.lits), end = Potassco::end(sum.lits); it != end; ++it) { + CLASP_ASSERT_CONTRACT_MSG(it->lit != 0 && it->weight > 0, "body not simplified"); + Literal*& n = p[it->lit < 0]; + *n = toLit(Potassco::lit(*it)); + if (weights) { weights[n - base] = it->weight; a->sum->sumW += it->weight; if (n->sign()) { unsupp_ -= it->weight; } } + if (addDeps) { prg.getAtom(n->var())->addDep(id, !n->sign()); } + ++n; + } +} +void PrgBody::init(Body_t t, uint32 sz) { + size_ = sz, head_ = 0, type_ = t, sBody_ = 0, sHead_ = 0, freeze_ = 0; +} +PrgBody* PrgBody::create(LogicProgram& prg, uint32 id, const Rule& r, uint32 pos, bool addDeps) { + static_assert(sizeof(PrgBody) == 24 && sizeof(Agg) == sizeof(void*), "unexpected alignment"); + PrgBody* ret = 0; + if (r.normal()) { + size_t bytes = sizeof(PrgBody) + (Potassco::size(r.cond) * sizeof(Literal)); + ret = new (::operator new(bytes)) PrgBody(id, prg, r.cond, pos, addDeps); + } + else { + const Potassco::Sum_t& sum = r.agg; + size_t bytes = sizeof(PrgBody) + (Potassco::size(r.agg.lits) * sizeof(Literal)) + sizeof(Agg); + ret = new (::operator new(bytes)) PrgBody(id, prg, sum, r.bt == Body_t::Sum, pos, addDeps); + CLASP_ASSERT_CONTRACT_MSG(ret->bound() > 0 && ret->sumW() > ret->bound(), "body not simplified"); + } + if (ret->bound() == 0) { + ret->assignValue(value_true); + ret->markDirty(); + } + return ret; +} + +PrgBody::~PrgBody() { + clearHeads(); + if (hasWeights()) { + sumData()->destroy(); + } +} + +void PrgBody::destroy() { + this->~PrgBody(); + ::operator delete(this); +} + +PrgBody::SumData* PrgBody::SumData::create(uint32 size, weight_t b, weight_t s) { + uint32 bytes = sizeof(SumData) + (size * sizeof(weight_t)); + SumData* ret = new (::operator new(bytes)) SumData(); + ret->bound = b; + ret->sumW = s; + return ret; +} +void PrgBody::SumData::destroy() { + ::operator delete(this); +} + +uint32 PrgBody::findLit(const LogicProgram& prg, Literal p) const { + for (const Literal* it = goals_begin(), *end = it + size(); it != end; ++it) { + Literal x = prg.getAtom(it->var())->literal(); + if (it->sign()) x = ~x; + if (x == p) return static_cast(it - goals_begin()); + } + return varMax; +} + +// Sets the unsupported counter back to +// bound() - negWeight() +bool PrgBody::resetSupported() { + unsupp_ = bound(); + for (uint32 x = size(); x && goal(--x).sign(); ) { + unsupp_ -= weight(x); + } + return isSupported(); +} + +// Removes all heads from this body *without* notifying them +void PrgBody::clearHeads() { + if (!isSmallHead()) { delete largeHead(); } + head_ = 0; +} + +// Makes h a head-successor of this body and adds this +// body as a support for h. +void PrgBody::addHead(PrgHead* h, EdgeType t) { + assert(relevant() && h->relevant()); + PrgEdge fwdEdge = PrgEdge::newEdge(*h, t); + PrgEdge bwdEdge = PrgEdge::newEdge(*this, t); + uint32 numHeads= static_cast(heads_end() - heads_begin()); + uint32 numSupps= h->supports(); + bool dup = false; + if (numHeads && numSupps && std::min(numHeads, numSupps) < 10) { + if (numSupps < numHeads) { dup = std::find(h->supps_begin(), h->supps_end(), bwdEdge) != h->supps_end(); } + else { dup = std::find(heads_begin(), heads_end(), fwdEdge) != heads_end(); } + } + if (dup) { return; } + addHead(fwdEdge); + h->addSupport(bwdEdge); + // mark head-set as dirty + if (head_ > 1) { sHead_ = 1; } +} + +void PrgBody::addHead(PrgEdge h) { + if (head_ < 2u) { smallHead()[head_++] = h; } + else if (!isSmallHead()){ largeHead()->push_back(h); } + else { + EdgeVec* t = new EdgeVec(heads_begin(), heads_end()); + headData_.ext = t; + head_ = 3u; + t->push_back(h); + } +} + +void PrgBody::removeHead(PrgHead* h, EdgeType t) { + PrgEdge x = PrgEdge::newEdge(*h, t); + if (eraseHead(x)) { + h->removeSupport(PrgEdge::newEdge(*this, t)); // also remove back edge + } +} + +bool PrgBody::hasHead(PrgHead* h, EdgeType t) const { + if (!hasHeads()) { return false; } + PrgEdge x = PrgEdge::newEdge(*h, t); + head_iterator it = sHead_ != 0 || isSmallHead() ? std::find(heads_begin(), heads_end(), x) : std::lower_bound(heads_begin(), heads_end(), x); + return it != heads_end() && *it == x; +} + +bool PrgBody::eraseHead(PrgEdge h) { + PrgEdge* it = const_cast(std::find(heads_begin(), heads_end(), h)); + if (it == heads_end()) { return false; } + else if (isSmallHead()) { *it = smallHead()[1]; --head_; } + else { largeHead()->erase(it); } + return true; +} + +bool PrgBody::toData(const LogicProgram& prg, Potassco::RuleBuilder& out) const { + Body_t bt = type(); + weight_t sum = 0, bound = this->bound(); + bt == Body_t::Normal ? out.startBody() : out.startSum(bound); + for (uint32 i = 0, end = size(); i != end; ++i) { + Potassco::WeightLit_t wl = {toInt(goal(i)), weight(i)}; + if (!prg.frozen() || prg.inProgram(Potassco::atom(wl))) { + out.addGoal(wl); + sum += wl.weight; + } + else if (wl.lit < 0) { bound -= weight(i); } + else if (bt == Body_t::Normal) { return false; } + } + if (bt != Body_t::Normal) { + out.setBound(bound); + if (bound <= 0 || bound >= sum) { + if (bound > sum) { return false; } + else if (bound <= 0) { out.clearBody(); } + else { out.weaken(Body_t::Normal); } + } + } + return true; +} + +// Simplifies the body by removing assigned atoms & replacing eq atoms. +// Checks whether simplified body must be false (CONTRA) or is +// structurally equivalent to some other body. +// prg The program containing this body +// strong If true, treats atoms that have no variable associated as false. +// eqId The id of a body in prg that is equivalent to this body +bool PrgBody::simplifyBody(LogicProgram& prg, bool strong, uint32* eqId) { + if (eqId) { *eqId = id(); } + if (sBody_ == 0) { return true; } + // update body - compute old hash value + SharedContext& ctx = *prg.ctx(); + uint32 oldHash = 0; + weight_t bound = this->bound(); + weight_t w = 1, *jw = hasWeights() ? sumData()->weights : 0; + Literal* lits = goals_begin(); + Literal* j = lits; + AtomState& todo = prg.atomState(); + Var a; + bool mark, isEq; + int todos = 0; + for (Literal* it = j, *end = j + size(); it != end; ++it) { + a = it->var(); + isEq = a != prg.getRootId(a); + oldHash+= hashLit(*it); + if (isEq) { + prg.getAtom(a)->removeDep(id(), !it->sign()); // remove old edge + *it = prg.getAtom(a)->eqGoal(it->sign()); // replace with eq goal + a = it->var(); // and check it + } + Literal aLit = it->sign() ? ~prg.getAtom(a)->literal() : prg.getAtom(a)->literal(); + ValueRep v = prg.getAtom(a)->value(); + mark = strong || prg.getAtom(a)->hasVar(); + if (strong && !prg.getAtom(a)->hasVar()) { + v = value_false; + } + if (v == value_weak_true && it->sign()) { + v = value_true; + } + if (v == value_true || v == value_false) { // truth value is known - remove subgoal + if (v == trueValue(*it)) { + // subgoal is true: decrease necessary lower bound + bound -= weight(uint32(it - lits)); + } + prg.getAtom(a)->removeDep(id(), !it->sign()); + } + else if (!mark || !ctx.marked(aLit)) { + if (mark) { ctx.mark(aLit); } + if (isEq) { // remember to add edge for new goal later + todo.addToBody(Literal(*it)); + ++todos; + } + *j++ = *it; // copy literal and optionally weight + if (jw) { *jw++ = weight(uint32(it - lits)); } + } + else { // body contains aLit more than once + if (type() != Body_t::Normal) { // merge subgoal + if (!jw) { + SumData* sum = SumData::create(size(), this->bound(), this->sumW()); + std::fill_n(sum->weights, size(), w = 1); + aggData().sum = sum; + type_ = Body_t::Sum; + jw = sum->weights + (it - lits); + } + else { w = weight(uint32(it - lits)); } + uint32 pos = findLit(prg, aLit); + sumData()->weights[pos] += w; + } + else { // ignore if normal + --bound; + if (!isEq) { // remove edge + if (todo.inBody(*it)) { todo.clearBody(*it); --todos; } + else { prg.getAtom(it->var())->removeDep(id(), !it->sign()); } + } + } + } + } + // unmark atoms, compute new hash value, + // and restore pos | neg partition in case + // we changed some positive goals to negative ones + size_ = j - lits; + if (jw) jw = sumData()->weights; + uint32 newHash = 0; + weight_t sumW = 0, reachW = 0; + for (uint32 p = 0, n = size_, i, h; p < n;) { + if (!lits[p].sign()) { h = hashLit(lits[i = p++]); } + else if (lits[n-1].sign()) { h = hashLit(lits[i = --n]); } + else /* restore pos|neg order */ { + std::swap(lits[p], lits[n-1]); + if (jw) { std::swap(jw[p], jw[n-1]); } + continue; + } + a = lits[i].var(); + if (todos && todo.inBody(lits[i])) { + prg.getAtom(a)->addDep(id(), !lits[i].sign()); + todo.clearBody(lits[i]); + --todos; + } + Var v = prg.getAtom(a)->var(); + w = !jw ? 1 : jw[i]; + sumW += w; + reachW += w; + if (ctx.marked(posLit(v)) && ctx.marked(negLit(v))) { + // body contains aLit and ~aLit + if (!hasWeights()) { reachW -= 1; } + else { + Literal other = prg.getAtom(a)->literal() ^ !goal(i).sign(); + uint32 pos = findLit(prg, other); + assert(pos != varMax && pos != i); + reachW -= std::min(w, jw[pos]); + } + } + ctx.unmark( v ); + newHash += h; + } + bool ok = normalize(prg, bound, sumW, reachW, newHash); + if (ok) { + Var xId = id(); + if (oldHash != newHash) { + xId = prg.update(this, oldHash, newHash); + } + if (eqId) { *eqId = xId != varMax ? xId : id(); } + } + if (strong) sBody_ = 0; + return ok && (value() == value_free || propagateValue(prg)); +} + +bool PrgBody::normalize(const LogicProgram& prg, weight_t bound, weight_t sumW, weight_t reachW, uint32& hashOut) { + Body_t nt = (sumW == bound || size() == 1) ? Body_t::Normal : type(); + bool ok = true; + if (sumW >= bound && type() != Body_t::Normal) { + if (hasWeights()) { + sumData()->bound = bound; + sumData()->sumW = sumW; + } + else { + aggData().bound = bound; + } + } + if (bound <= 0) { + for (uint32 i = 0, myId = id(); i != size_; ++i) { + prg.getAtom(goal(i).var())->removeDep(myId, !goal(i).sign()); + } + size_ = 0; hashOut = 0, unsupp_ = 0; + nt = Body_t::Normal; + ok = assignValue(value_true); + } + else if (reachW < bound) { + ok = assignValue(value_false); + sHead_ = 1; + markRemoved(); + } + if (nt != type()) { + assert(nt == Body_t::Normal); + Literal* from = aggData().lits; + if (hasWeights()) { + sumData()->destroy(); + } + Literal* to = (new (data_)Norm())->lits; + std::copy(from, from+size(), to); + type_ = nt; + } + return ok; +} + +// Marks the set of heads in rs and removes +// any duplicate heads. +void PrgBody::prepareSimplifyHeads(LogicProgram& prg, AtomState& rs) { + head_iterator end = heads_end(); + uint32 size = 0; + for (PrgEdge* j = const_cast(heads_begin()); j != end;) { + if (!rs.inHead(*j)) { + rs.addToHead(*j); + ++j; ++size; + } + else { + prg.getHead(*j)->markDirty(); + *j = *--end; + } + } + if (isSmallHead()) { head_ = size; } + else { shrinkVecTo(*largeHead(), size); } +} + +// Simplifies the heads of this body wrt target. +// Removes superfluous/eq/unsupported heads and checks for self-blocking +// situations. +// PRE: prepareSimplifyHeads was called +bool PrgBody::simplifyHeadsImpl(LogicProgram& prg, PrgBody& target, AtomState& rs, bool strong) { + PrgHead* cur; + PrgEdge* j = const_cast(heads_begin()); + uint32 newSize = 0; + bool merge = this != ⌖ + bool block = value() == value_false || (merge && target.value() == value_false); + for (head_iterator it = heads_begin(), end = heads_end(); it != end; ++it) { + cur = prg.getHead(*it); + block= block || target.blockedHead(*it, rs); + if (!cur->relevant() || (strong && !cur->hasVar()) + || block || target.superfluousHead(prg, cur, *it, rs) || cur->value() == value_false) { + // remove superfluous and unsupported heads + cur->removeSupport(PrgEdge::newEdge(*this, it->type())); + rs.clearHead(*it); + block = block || (cur->value() == value_false && it->type() == PrgEdge::Normal); + } + else { + *j++ = *it; + ++newSize; + if (merge) { target.addHead(cur, it->type()); } + } + } + if (isSmallHead()) { head_ = newSize; } + else { shrinkVecTo(*largeHead(), newSize); } + return !block; +} + +bool PrgBody::simplifyHeads(LogicProgram& prg, bool strong) { + if (sHead_ == 0) { return true; } + return PrgBody::mergeHeads(prg, *this, strong); +} + +bool PrgBody::mergeHeads(LogicProgram& prg, PrgBody& heads, bool strong, bool simplify) { + AtomState& rs = prg.atomState(); + bool ok = true; + assert((this == &heads || heads.sHead_ == 0) && "Heads to merge not simplified!"); + if (simplify || &heads == this) { + // mark the body literals so that we can easily detect superfluous atoms + // and selfblocking situations. + for (const Literal* it = goals_begin(), *end = it + size(); it != end; ++it) { + rs.addToBody(*it); + } + // remove duplicate/superfluous heads & check for blocked atoms + prepareSimplifyHeads(prg, rs); + if (this == &heads) { + ok = simplifyHeadsImpl(prg, *this, rs, strong); + } + else { + heads.prepareSimplifyHeads(prg, rs); + if (!simplifyHeadsImpl(prg, *this, rs, strong) && !assignValue(value_false)) { + clearRule(rs); + return false; + } + ok = heads.simplifyHeadsImpl(prg, *this, rs, strong); + if (!ok && (!heads.assignValue(value_false) || !heads.propagateValue(prg, false))) { + clearRule(rs); + return false; + } + } + // clear temporary flags & reestablish ordering + std::sort(const_cast(heads_begin()), const_cast(heads_end())); + clearRule(rs); + sHead_ = 0; + } + else if (relevant()) { + for (head_iterator it = heads.heads_begin(), end = heads.heads_end(); it != end; ++it) { + PrgHead* h = prg.getHead(*it); + if (h->relevant()) { addHead(h, it->type()); } + } + } + return ok || (assignValue(value_false) && propagateValue(prg)); +} + +// Checks whether the head is superfluous w.r.t this body, i.e. +// - is needed to satisfy the body +// - it appears in the body and is a choice +// - it is a disjunction and one of the atoms is needed to satisfy the body +bool PrgBody::superfluousHead(const LogicProgram& prg, const PrgHead* head, PrgEdge it, const AtomState& rs) const { + if (it.isAtom()) { + // the head is an atom + uint32 atomId = it.node(); + weight_t w = 1; + if (rs.inBody(posLit(atomId))) { + if (hasWeights()) { + const Literal* lits = aggData().lits; + const Literal* x = std::find(lits, lits + size(), posLit(atomId)); + assert(x != lits + size()); + w = sumData()->weights[ x - lits ]; + } + if (it.isChoice() || (sumW() - w) < bound()) { + return true; + } + } + return it.isChoice() && (rs.inBody(negLit(atomId)) || rs.inHead(atomId)); + } + else { assert(it.isDisj()); + // check each contained atom + const PrgDisj* dis = static_cast(head); + for (PrgDisj::atom_iterator aIt = dis->begin(), aEnd = dis->end(); aIt != aEnd; ++aIt) { + if (rs.inBody(posLit(*aIt)) || rs.inHead(*aIt)) { + return true; + } + if (prg.isFact(prg.getAtom(*aIt))) { + return true; + } + } + // check for subsumption + if (prg.options().iters == LogicProgram::AspOptions::MAX_EQ_ITERS) { + for (head_iterator hIt = heads_begin(), hEnd = heads_end(); hIt != hEnd; ++hIt) { + if (hIt->isDisj() && prg.getDisj(hIt->node())->size() < dis->size()) { + const PrgDisj* other = prg.getDisj(hIt->node()); + for (PrgDisj::atom_iterator a = other->begin(), aEnd = other->end(); a != aEnd && other; ++a) { + if (std::find(dis->begin(), dis->end(), *a) == dis->end()) { + other = 0; + } + } + if (other && other->size() > 0) { + return true; + } + } + } + } + } + return false; +} + +// Checks whether the rule it.node() :- *this is selfblocking, i.e. +// from TB follows conflict +bool PrgBody::blockedHead(PrgEdge it, const AtomState& rs) const { + if (it.isAtom() && it.isNormal() && rs.inBody(negLit(it.node()))) { + weight_t w = 1; + if (hasWeights()) { + const Literal* lits = aggData().lits; + const Literal* x = std::find(lits, lits + size(), negLit(it.node())); + assert(x != lits + size()); + w = sumData()->weights[ x - lits ]; + } + return (sumW() - w) < bound(); + } + return false; +} + +void PrgBody::assignVar(LogicProgram& prg) { + if (hasVar() || !relevant()) { return; } + uint32 size = this->size(); + if (size == 0 || value() == value_true) { + setLiteral(lit_true()); + } + else if (size == 1 && prg.getAtom(goal(0).var())->hasVar()) { + Literal x = prg.getAtom(goal(0).var())->literal(); + setLiteral(goal(0).sign() ? ~x : x); + prg.ctx()->setVarEq(var(), true); + prg.incEqs(Var_t::Hybrid); + } + else if (value() != value_false) { + setLiteral(posLit(prg.ctx()->addVar(Var_t::Body, 0))); + } + else { + setLiteral(lit_false()); + } +} + +bool PrgBody::propagateSupported(Var v) { + weight_t w = 1; + if (hasWeights()) { + uint32 pos = (uint32)std::distance(goals_begin(), std::find(goals_begin(), goals_end(), posLit(v))); + w = weight(pos); + } + return (unsupp_ -= w) <= 0; +} + +bool PrgBody::propagateAssigned(LogicProgram& prg, Literal p, ValueRep v) { + if (!relevant()) return true; + assert(std::find(goals_begin(), goals_end(), p) != goals_end()); + markDirty(); + ValueRep x = v == value_weak_true ? value_true : v; + weight_t w = 1; // TODO: find weight of p for weight rule + if (x == falseValue(p) && (sumW() - w) < bound() && value() != value_false) { + return assignValue(value_false) && propagateValue(prg); + } + else if (x == trueValue(p) && (bound() - w) <= 0 && value() != value_weak_true) { + return assignValue(value_weak_true) && propagateValue(prg); + } + return true; +} + +bool PrgBody::propagateAssigned(LogicProgram& prg, PrgHead* h, EdgeType t) { + if (!relevant()) return true; + markHeadsDirty(); + if (h->value() == value_false && eraseHead(PrgEdge::newEdge(*h, t)) && t == PrgEdge::Normal) { + return value() == value_false || (assignValue(value_false) && propagateValue(prg)); + } + return true; +} + +bool PrgBody::propagateValue(LogicProgram& prg, bool backprop) { + ValueRep val = value(); + assert(value() != value_free); + // propagate value forward + for (head_iterator h = heads_begin(), end = heads_end(); h != end; ++h) { + PrgHead* head = prg.getHead(*h); + PrgEdge supp = PrgEdge::newEdge(*this, h->type()); + if (val == value_false) { + head->removeSupport(supp); + } + else if (!h->isChoice() && head->value() != val && !prg.assignValue(head, val, supp)) { + return false; + } + } + if (val == value_false) { clearHeads(); } + // propagate value backward + if (backprop && relevant()) { + const uint32 W = hasWeights(); + weight_t MAX_W = 1; + weight_t* wPos = W == 0 ? &MAX_W : sumData()->weights; + MAX_W = *std::max_element(wPos, wPos + (size() * W)); + weight_t bound = value()==value_false ? this->bound() : (sumW() - this->bound())+1; + if (MAX_W >= bound) { + ValueRep goalVal; + for (const Literal* it = goals_begin(), *end = goals_end(); it != end; ++it) { + if ((bound - *wPos) <= 0) { + if (!it->sign()) { goalVal = val; } + else { goalVal = val == value_false ? value_weak_true : value_false; } + if (!prg.assignValue(prg.getAtom(it->var()), goalVal, PrgEdge::noEdge())) { + return false; + } + } + wPos += W; + } + } + } + return true; +} +bool PrgBody::propagateValue(LogicProgram& prg) { + return propagateValue(prg, prg.options().backprop != 0); +} + +// Adds nogoods for the tableau-rules FFB and BTB as well as FTB, BFB. +// For normal bodies, clauses are used, i.e: +// FFB and BTB: +// - a binary clause [~b s] for every positive subgoal of b +// - a binary clause [~b ~n] for every negative subgoal of b +// FTB and BFB: +// - a clause [b ~s1...~sn n1..nn] where si is a positive and ni a negative subgoal +// For count/sum bodies, a weight constraint is created +bool PrgBody::addConstraints(const LogicProgram& prg, ClauseCreator& gc) { + if (type() == Body_t::Normal) { + bool taut= false; + Literal negB= ~literal(); + gc.start().add(literal()); + for (const Literal* it = goals_begin(), *end = goals_end(); it != end; ++it) { + Literal li = prg.getAtom(it->var())->literal() ^ it->sign(); + if (li == literal()) { taut = true; continue; } + if (!prg.ctx()->addBinary(negB, li)) { // [~B li] + return false; + } + if (li.var() != negB.var()) { gc.add(~li); } // [B v ~l1 v ... v ~ln] + } + return taut || gc.end(); + } + WeightLitVec lits; + for (uint32 i = 0, end = size_; i != end; ++i) { + Literal eq = prg.getAtom(goal(i).var())->literal() ^ goal(i).sign(); + lits.push_back(WeightLiteral(eq, weight(i))); + } + return WeightConstraint::create(*prg.ctx()->master(), literal(), lits, bound()).ok(); +} + +// Returns the SCC of body B, i.e. +// - scc if exist atom a in B.heads(), a' in B+, s.th. a.scc == a'.scc +// - noScc otherwise +uint32 PrgBody::scc(const LogicProgram& prg) const { + uint64 sccMask = 0; + uint32 end = size(); + uint32 scc = PrgNode::noScc; + bool large = false; + for (uint32 i = 0; i != end; ++i) { + if (goal(i).sign()) { + end = i; + break; + } + else if ((scc = prg.getAtom(goal(i).var())->scc()) != PrgNode::noScc) { + sccMask |= uint64(1) << (scc & 63); + large |= scc > 63; + } + } + if (sccMask != 0) { + PrgDisj::atom_iterator aIt = 0, aEnd = 0; + Var head; + for (head_iterator h = heads_begin(), hEnd = heads_end(); h != hEnd; ++h) { + if (h->isAtom()) { head = h->node(); aIt = &head, aEnd = aIt + 1; } + else { PrgDisj* d = prg.getDisj(h->node()); aIt = d->begin(), aEnd = d->end(); } + for (; aIt != aEnd; ++aIt) { + scc = prg.getAtom(*aIt)->scc(); + if (scc != PrgNode::noScc && (sccMask & (uint64(1) << (scc&63))) != 0) { + if (!large) { return scc; } + for (uint32 j = 0; j != end; ++j) { + if (scc == prg.getAtom(goal(j).var())->scc()) { return scc; } + } + } + } + } + } + return PrgNode::noScc; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// class PrgDisj +// +// Head of a disjunctive rule +///////////////////////////////////////////////////////////////////////////////////////// +PrgDisj* PrgDisj::create(uint32 id, const Potassco::AtomSpan& head) { + void* m = ::operator new(sizeof(PrgDisj) + (Potassco::size(head)*sizeof(Var))); + return new (m) PrgDisj(id, head); +} + +PrgDisj::PrgDisj(uint32 id, const Potassco::AtomSpan& head) : PrgHead(id, PrgNode::Disj, (uint32)Potassco::size(head)) { + std::copy(Potassco::begin(head), Potassco::end(head), atoms_); + std::sort(atoms_, atoms_+size()); +} +PrgDisj::~PrgDisj() {} +void PrgDisj::destroy() { + this->~PrgDisj(); + ::operator delete(this); +} + +void PrgDisj::detach(LogicProgram& prg) { + PrgEdge edge = PrgEdge::newEdge(*this, PrgEdge::Choice); + for (atom_iterator it = begin(), end = this->end(); it != end; ++it) { + prg.getAtom(*it)->removeSupport(edge); + } + EdgeVec temp; temp.swap(supports_); + for (PrgDisj::sup_iterator it = temp.begin(), end = temp.end(); it != end; ++it) { + prg.getBody(it->node())->removeHead(this, PrgEdge::Normal); + } + setInUpper(false); + markRemoved(); +} + +bool PrgDisj::propagateAssigned(LogicProgram& prg, PrgHead* head, EdgeType t) { + assert(head->isAtom() && t == PrgEdge::Choice); + if (prg.isFact(static_cast(head)) || head->value() == value_false) { + atom_iterator it = std::find(begin(), end(), head->id()); + if (it != end()) { + if (head->value() == value_true) { detach(prg); } + else if (head->value() == value_false){ + head->removeSupport(PrgEdge::newEdge(*this, t)); + std::copy(it+1, end(), const_cast(it)); + if (--data_ == 1) { + PrgAtom* last = prg.getAtom(*begin()); + EdgeVec temp; + clearSupports(temp); + for (EdgeVec::const_iterator it = temp.begin(), end = temp.end(); it != end; ++it) { + prg.getBody(it->node())->removeHead(this, PrgEdge::Normal); + prg.getBody(it->node())->addHead(last, PrgEdge::Normal); + } + detach(prg); + } + } + } + } + return true; +} +} } diff --git a/libclasp/src/lookahead.cpp b/libclasp/src/lookahead.cpp new file mode 100644 index 0000000..5478827 --- /dev/null +++ b/libclasp/src/lookahead.cpp @@ -0,0 +1,392 @@ +// +// Copyright (c) 2009, 2012 Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Lookahead scoring +///////////////////////////////////////////////////////////////////////////////////////// +uint32 ScoreLook::countNant(const Solver& s, const Literal* b, const Literal *e) const { + uint32 sc = 1; + for (; b != e; ++b) { sc += s.varInfo(b->var()).nant(); } + return sc; +} +void ScoreLook::scoreLits(const Solver& s, const Literal* b, const Literal *e) { + assert(b < e); + uint32 sc = !nant ? uint32(e-b) : countNant(s, b, e); + Var v = b->var(); + assert(validVar(v)); + score[v].setScore(*b, sc); + if (addDeps) { + if ((score[v].testedBoth() || mode == score_max) && greater(v, best)) { + best = v; + } + for (; b != e; ++b) { + v = b->var(); + if (validVar(v) && (s.varInfo(v).type() & types) != 0) { + if (!score[v].seen()) { deps.push_back(v); } + score[v].setDepScore(*b, sc); + score[v].setSeen(*b); + } + } + } +} +void ScoreLook::clearDeps() { + for (VarVec::size_type i = 0, end = deps.size(); i != end; ++i) { + score[deps[i]].clear(); + } + deps.clear(); + best = 0; +} +bool ScoreLook::greater(Var lhs, Var rhs) const { + uint32 rhsMax, rhsMin; + score[rhs].score(rhsMax, rhsMin); + return mode == score_max + ? greaterMax(lhs, rhsMax) + : greaterMaxMin(lhs, rhsMax, rhsMin); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Lookahead propagator +///////////////////////////////////////////////////////////////////////////////////////// +Lookahead::Lookahead(const Params& p) + : nodes_(2, LitNode(lit_true())) + , last_(head_id) // circular list + , pos_(head_id) // lookahead start pos + , top_(uint32(-2)) + , limit_(p.lim) { + head()->next = head_id; + undo()->next = UINT32_MAX; + if (p.type != Var_t::Hybrid) { + score.mode = ScoreLook::score_max_min; + } + else { + score.mode = ScoreLook::score_max; + } + score.types = p.type; + if (p.topLevelImps) { head()->lit.flag(); } + score.nant = p.restrictNant; +} + +Lookahead::~Lookahead() {} + +void Lookahead::detach(Solver& s) { + s.removePost(this); + while (saved_.size()>1) { + s.removeUndoWatch(uint32(saved_.size()-1), this); + saved_.pop_back(); + } +} +void Lookahead::destroy(Solver* s, bool detach) { + if (s && detach) { Lookahead::detach(*s); } + PostPropagator::destroy(s, detach); +} + +uint32 Lookahead::priority() const { return priority_reserved_look; } + +void Lookahead::clear() { + score.clearDeps(); + while (!saved_.empty()) { + if (saved_.back() != UINT32_MAX) { + splice(saved_.back()); + } + saved_.pop_back(); + } + LookList(2, *head()).swap(nodes_); + head()->next = head_id; + undo()->next = UINT32_MAX; + last_ = head_id; + top_ = UINT32_MAX; +} + +bool Lookahead::init(Solver& s) { + ScoreLook& sc = score; + sc.clearDeps(); + Var start = (uint32)sc.score.size(); + sc.score.resize(s.numVars()+1); + const VarType types= sc.types; + const bool uniform = types != Var_t::Hybrid; + uint32 add = 0; + uint32 nants = 0; + for (Var v = start; v <= s.numVars(); ++v) { + if (s.value(v) == value_free && (s.varInfo(v).type() & types) != 0 ) { + ++add; + nants += s.varInfo(v).nant(); + } + } + nodes_.reserve(nodes_.size() + add); + for (Var v = start; v <= s.numVars(); ++v) { + if (s.value(v) == value_free && (s.varInfo(v).type() & types) != 0 ) { + append(Literal(v, s.varInfo(v).preferredSign()), uniform || s.varInfo(v).type() == Var_t::Hybrid); + } + } + if (add && score.nant) { + score.nant = add != nants && nants != 0; + } + return true; +} + +void Lookahead::append(Literal p, bool testBoth) { + node(last_)->next = static_cast(nodes_.size()); + nodes_.push_back(LitNode(p)); + last_ = node(last_)->next; + node(last_)->next = head_id; + // remember to also test ~p by setting watched-flag + if (testBoth) { node(last_)->lit.flag(); } +} + +// test p and optionally ~p if necessary +bool Lookahead::test(Solver& s, Literal p) { + return (score.score[p.var()].seen(p) || s.test(p, this)) + && (!p.flagged() || score.score[p.var()].seen(~p) || s.test(~p, this)) + && (imps_.empty() || checkImps(s, p)); +} + +bool Lookahead::checkImps(Solver& s, Literal p) { + assert(!imps_.empty()); + bool ok = true; + if (score.score[p.var()].testedBoth()) { + for (LitVec::const_iterator it = imps_.begin(), end = imps_.end(); it != end && ok; ++it) { + ok = s.force(*it, lit_true()); + } + } + imps_.clear(); + return ok && (s.queueSize() == 0 || s.propagateUntil(this)); +} + +// failed-literal detection - stop on failed-literal +bool Lookahead::propagateLevel(Solver& s) { + assert(!s.hasConflict()); + saved_.resize(s.decisionLevel()+1, UINT32_MAX); + uint32 undoId = saved_[s.decisionLevel()]; + if (undoId == UINT32_MAX) { + undoId = undo_id; + if (s.decisionLevel() != 0) { + s.addUndoWatch(s.decisionLevel(), this); + } + } + score.clearDeps(); + score.addDeps = true; + Literal p = node(pos_)->lit; + bool ok = s.value(p.var()) != value_free || test(s, p); + for (LitNode* r = node(pos_); r->next != pos_ && ok; ) { + p = node(r->next)->lit; + if (s.value(p.var()) == value_free) { + if (test(s, p)) { r = node(r->next); } + else { pos_= r->next; ok = false; } + } + else if (r->next != last_ && r->next != head_id) { + // unlink from candidate list + NodeId t = r->next; + r->next = node(t)->next; + // append to undo list + LitNode* u = node(undoId); + node(t)->next = u->next; + u->next = t; + undoId = t; + } + else { r = node(r->next); } // keep iterators valid; never unlink last node and dummy head + } + saved_.back() = undoId; + return ok; +} + +bool Lookahead::propagateFixpoint(Solver& s, PostPropagator* ctx) { + if ((empty() || top_ == s.numAssignedVars()) && !score.deps.empty()) { + // nothing to lookahead + return true; + } + bool ok = true; + uint32 dl; + for (dl = s.decisionLevel(); !propagateLevel(s); dl = s.decisionLevel()) { + // some literal failed + // resolve and propagate conflict + assert(s.decisionLevel() >= dl); + if (!s.resolveConflict() || !s.propagateUntil(this)) { + ok = false; + score.clearDeps(); + break; + } + } + if (dl == 0 && ok) { + // remember top-level size - no need to redo lookahead + // on level 0 unless we learn a new implication + assert(s.queueSize() == 0); + top_ = s.numAssignedVars(); + LitVec().swap(imps_); + } + if (!ctx && limit_ && --limit_ == 0) { + this->destroy(&s, true); + } + return ok; +} + +// splice list [undo_.next, ul] back into candidate list +void Lookahead::splice(NodeId ul) { + assert(ul != UINT32_MAX); + if (ul != undo_id) { + assert(undo()->next != UINT32_MAX); + // unlink from undo list + LitNode* ulNode= node(ul); + NodeId first = undo()->next; + undo()->next = ulNode->next; + // splice into look-list + ulNode->next = head()->next; + head()->next = first; + } +} + +void Lookahead::undoLevel(Solver& s) { + if (s.decisionLevel() == saved_.size()) { + cancelPropagation(); + const LitVec& a = s.trail(); + score.scoreLits(s, &a[0]+s.levelStart(s.decisionLevel()), &a[0]+a.size()); + if (s.decisionLevel() == static_cast(head()->lit.flagged())) { + const Literal* b = &a[0]+s.levelStart(s.decisionLevel()); + if (b->flagged()) { + // remember current DL for b + uint32 dist = static_cast(((&a[0]+a.size()) - b)); + imps_.assign(b+1, b + std::min(dist, uint32(2048))); + } + else if (score.score[b->var()].testedBoth()) { + // all true lits in imps_ follow from both *b and ~*b + // and are therefore implied + LitVec::iterator j = imps_.begin(); + for (LitVec::iterator it = imps_.begin(), end = imps_.end(); it != end; ++it) { + if (s.isTrue(*it)) { *j++ = *it; } + } + imps_.erase(j, imps_.end()); + } + } + } + else { + assert(saved_.size() >= s.decisionLevel()+1); + saved_.resize(s.decisionLevel()+1); + NodeId n = saved_.back(); + saved_.pop_back(); + splice(n); + assert(node(last_)->next == head_id); + score.clearDeps(); + } +} + +Literal Lookahead::heuristic(Solver& s) { + if (s.value(score.best) != value_free) { + // no candidate available + return lit_true(); + } + ScoreLook& sc = score; + Literal choice= Literal(sc.best, sc.score[sc.best].prefSign()); + if (!sc.deps.empty() && sc.mode == ScoreLook::score_max_min) { + // compute heuristic values for candidates skipped during last lookahead + uint32 min, max; + sc.score[sc.best].score(max, min); + sc.addDeps = false; + bool ok = true; + LitVec::size_type i = 0; + do { + Var v = sc.deps[i]; + VarScore& vs = sc.score[v]; + if (s.value(v) == value_free) { + uint32 vMin, vMax; + vs.score(vMax, vMin); + if (vMin == 0 || vMin > min || (vMin == min && vMax > max)) { + uint32 neg = vs.score(negLit(v)) > 0 ? vs.score(negLit(v)) : max+1; + uint32 pos = vs.score(posLit(v)) > 0 ? vs.score(posLit(v)) : max+1; + if (!vs.tested(negLit(v))) { + ok = ok && s.test(negLit(v), this); + neg = vs.score(negLit(v)); + } + if ((neg > min || (neg == min && pos > max)) && !vs.tested(posLit(v))) { + ok = ok && s.test(posLit(v), this); + } + } + if (vs.testedBoth() && sc.greaterMaxMin(v, max, min)) { + vs.score(max, min); + choice = Literal(v, vs.prefSign()); + } + } + } while (++i != sc.deps.size() && ok); + if (!ok) { + // One of the candidates failed. Since none of them failed + // during previous propagation, this indicates that + // either some post propagator has wrong priority or + // parallel solving is active and a stop conflict was set. + // Since we can't resolve the problem here, we simply return the + // literal that caused the conflict + assert(s.hasConflict()); + return lit_false(); + } + } + return choice; +} +///////////////////////////////////////////////////////////////////////////////////////// +// Lookahead heuristic +///////////////////////////////////////////////////////////////////////////////////////// +UnitHeuristic::UnitHeuristic() { } +void UnitHeuristic::endInit(Solver& s) { + Lookahead* look = static_cast(s.getPost(Lookahead::priority_reserved_look)); + if (!look) { s.addPost(new Lookahead(Var_t::Atom)); } +} +Literal UnitHeuristic::doSelect(Solver& s) { + Lookahead* look = static_cast(s.getPost(Lookahead::priority_reserved_look)); + Literal x = look ? look->heuristic(s) : lit_true(); + if (x != lit_true()) { return x; } + return SelectFirst::doSelect(s); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Restricted Lookahead heuristic - lookahead and heuristic for a limited number of ops +///////////////////////////////////////////////////////////////////////////////////////// +class Restricted : public UnitHeuristic { +public: + typedef LitVec::size_type size_t; + typedef ConstraintType con_t; + Restricted(DecisionHeuristic* other) + : UnitHeuristic() + , other_(other) { + } + Literal doSelect(Solver& s) { + Lookahead* look = static_cast(s.getPost(Lookahead::priority_reserved_look)); + if (look && !look->hasLimit()) { look = 0; } + Literal x = look ? look->heuristic(s) : lit_true(); + if (x == lit_true()) { x = other_->doSelect(s); } + if (!look) { s.setHeuristic(other_.release(), Ownership_t::Acquire); } + return x; + } + // heuristic interface - forward to other + void startInit(const Solver& s) { other_->startInit(s); } + void endInit(Solver& s) { other_->endInit(s); } + void setConfig(const HeuParams& p) { other_->setConfig(p); } + void detach(Solver& s) { if (other_.is_owner()) { other_->detach(s); } } + void simplify(const Solver& s, size_t st) { other_->simplify(s, st); } + void undoUntil(const Solver& s, size_t st){ other_->undoUntil(s, st); } + void updateReason(const Solver& s, const LitVec& x, Literal r) { other_->updateReason(s, x, r); } + bool bump(const Solver& s, const WeightLitVec& w, double d) { return other_->bump(s, w, d); } + void newConstraint(const Solver& s, const Literal* p, size_t sz, con_t t) { other_->newConstraint(s, p, sz, t); } + void updateVar(const Solver& s, Var v, uint32 n) { other_->updateVar(s, v, n); } + Literal selectRange(Solver& s, const Literal* f, const Literal* l) { return other_->selectRange(s, f, l); } +private: + typedef SingleOwnerPtr HeuPtr; + HeuPtr other_; +}; + +UnitHeuristic* UnitHeuristic::restricted(DecisionHeuristic* other) { + return new Restricted(other); +} +} diff --git a/libclasp/src/minimize_constraint.cpp b/libclasp/src/minimize_constraint.cpp new file mode 100644 index 0000000..77a9371 --- /dev/null +++ b/libclasp/src/minimize_constraint.cpp @@ -0,0 +1,1370 @@ +// +// Copyright (c) 2010-2015, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// SharedMinimizeData +///////////////////////////////////////////////////////////////////////////////////////// +SharedMinimizeData::SharedMinimizeData(const SumVec& lhsAdjust, MinimizeMode m) : mode_(m) { + adjust_ = lhsAdjust; + lower_ = new LowerType[adjust_.size()]; + count_ = 1; + resetBounds(); + setMode(MinimizeMode_t::optimize); +} +SharedMinimizeData::~SharedMinimizeData() { + delete[] lower_; +} + +void SharedMinimizeData::destroy() const { + this->~SharedMinimizeData(); + ::operator delete(const_cast(this)); +} + +void SharedMinimizeData::resetBounds() { + gCount_ = 0; + optGen_ = 0; + std::fill_n(lower_, numRules(), wsum_t(0)); + up_[0].assign(numRules(), maxBound()); + up_[1].assign(numRules(), maxBound()); + const WeightLiteral* lit = lits; + for (weight_t wPos = 0, end = (weight_t)weights.size(), x; wPos != end; wPos = x+1) { + assert(weights[wPos].weight >= 0); + for (x = wPos; weights[x].next; ) { // compound weight - check for negative + if (weights[++x].weight < 0) { + while (lit->second != wPos) { ++lit; } + for (const WeightLiteral* t = lit; t->second == wPos; ++t) { + lower_[weights[x].level] += weights[x].weight; + } + } + } + } +} + +bool SharedMinimizeData::setMode(MinimizeMode m, const wsum_t* bound, uint32 boundSize) { + mode_ = m; + if (boundSize && bound) { + SumVec& opt = up_[0]; + bool ok = false; + gCount_ = 0; + optGen_ = 0; + boundSize = std::min(boundSize, numRules()); + for (uint32 i = 0, end = boundSize; i != end; ++i) { + wsum_t B = bound[i], a = adjust(i); + B = a >= 0 || (maxBound() + a) >= B ? B - a : maxBound(); + wsum_t d = B - lower_[i]; + if (d < 0 && !ok) { return false; } + opt[i] = B; + ok = ok || d > 0; + } + for (uint32 i = boundSize, end = (uint32)opt.size(); i != end; ++i) { opt[i] = maxBound(); } + } + return true; +} + +MinimizeConstraint* SharedMinimizeData::attach(Solver& s, MinimizeMode_t::Strategy strat, uint32 param, bool addRef) { + if (addRef) this->share(); + MinimizeConstraint* ret; + if (strat == MinimizeMode_t::opt_bb || mode() == MinimizeMode_t::enumerate) { + ret = new DefaultMinimize(this, param); + } + else { + ret = new UncoreMinimize(this, param); + } + ret->attach(s); + return ret; +} + +const SumVec* SharedMinimizeData::setOptimum(const wsum_t* newOpt) { + if (optGen_) { return up_ + (optGen_&1u); } + uint32 g = gCount_; + uint32 n = 1u - (g & 1u); + SumVec& U = up_[n]; + U.assign(newOpt, newOpt + numRules()); + assert(mode() != MinimizeMode_t::enumerate || n == 1); + if (mode() != MinimizeMode_t::enumerate) { + if (++g == 0) { g = 2; } + gCount_ = g; + } + return &U; +} +void SharedMinimizeData::setLower(uint32 lev, wsum_t low) { + lower_[lev] = low; +} +wsum_t SharedMinimizeData::incLower(uint32 at, wsum_t low){ + for (wsum_t stored;;) { + if ((stored = lower(at)) >= low) { + return stored; + } + if (lower_[at].compare_and_swap(low, stored) == stored) { + return low; + } + } +} +wsum_t SharedMinimizeData::lower(uint32 lev) const { + return lower_[lev]; +} +wsum_t SharedMinimizeData::optimum(uint32 lev) const { + wsum_t o = sum(lev); + return o + (o != maxBound() ? adjust(lev) : 0); +} +void SharedMinimizeData::markOptimal() { + optGen_ = generation(); +} +void SharedMinimizeData::sub(wsum_t* lhs, const LevelWeight* w, uint32& aLev) const { + if (w->level < aLev) { aLev = w->level; } + do { lhs[w->level] -= w->weight; } while (w++->next); +} +bool SharedMinimizeData::imp(wsum_t* lhs, const LevelWeight* w, const wsum_t* rhs, uint32& lev) const { + assert(lev <= w->level && std::equal(lhs, lhs+lev, rhs)); + while (lev != w->level && lhs[lev] == rhs[lev]) { ++lev; } + for (uint32 i = lev, end = numRules(); i != end; ++i) { + wsum_t temp = lhs[i]; + if (i == w->level) { temp += w->weight; if (w->next) ++w; } + if (temp != rhs[i]){ return temp > rhs[i]; } + } + return false; +} +///////////////////////////////////////////////////////////////////////////////////////// +// MinimizeConstraint +///////////////////////////////////////////////////////////////////////////////////////// +MinimizeConstraint::MinimizeConstraint(SharedData* d) : shared_(d) {} + +MinimizeConstraint::~MinimizeConstraint() { + assert(shared_ == 0 && "MinimizeConstraint not destroyed!"); +} +bool MinimizeConstraint::prepare(Solver& s, bool useTag) { + CLASP_ASSERT_CONTRACT_MSG(!s.isFalse(tag_), "Tag literal must not be false!"); + if (useTag && tag_ == lit_true()) { tag_ = posLit(s.pushTagVar(false)); } + if (s.isTrue(tag_) || s.hasConflict()){ return !s.hasConflict(); } + return useTag ? s.pushRoot(tag_) : s.force(tag_, 0); +} +void MinimizeConstraint::destroy(Solver* s, bool d) { + shared_->release(); + shared_ = 0; + Constraint::destroy(s, d); +} +void MinimizeConstraint::reportLower(Solver& s, uint32 lev, wsum_t low) const { + s.lower.level = lev; + s.lower.bound = low + shared_->adjust(lev); +} +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultMinimize +///////////////////////////////////////////////////////////////////////////////////////// +union DefaultMinimize::UndoInfo { + UndoInfo() : rep(0) {} + struct { + uint32 idx : 30; // index of literal on stack + uint32 newDL : 1; // first literal of new DL? + uint32 idxSeen: 1; // literal with idx already propagated? + } data; + uint32 rep; + uint32 index() const { return data.idx; } + bool newDL() const { return data.newDL != 0u; } +}; +DefaultMinimize::DefaultMinimize(SharedData* d, uint32 strat) + : MinimizeConstraint(d) + , bounds_(0) + , pos_(d->lits) + , undo_(0) + , undoTop_(0) + , size_(d->numRules()) { + step_.type = strat & 3u; + if (step_.type == MinimizeMode_t::bb_step_hier && d->numRules() == 1) { + step_.type = 0; + } +} + +DefaultMinimize::~DefaultMinimize() { + delete [] bounds_; + delete [] undo_; +} + +void DefaultMinimize::destroy(Solver* s, bool detach) { + if (s && detach) { + for (const WeightLiteral* it = shared_->lits; !isSentinel(it->first); ++it) { + s->removeWatch(it->first, this); + } + for (uint32 dl = 0; (dl = lastUndoLevel(*s)) != 0; ) { + s->removeUndoWatch(dl, this); + DefaultMinimize::undoLevel(*s); + } + } + MinimizeConstraint::destroy(s, detach); +} + +bool DefaultMinimize::attach(Solver& s) { + assert(s.decisionLevel() == 0 && !bounds_); + uint32 numL = 0; + VarVec up; + for (const WeightLiteral* it = shared_->lits; !isSentinel(it->first); ++it, ++numL) { + if (s.value(it->first.var()) == value_free) { + s.addWatch(it->first, this, numL); + } + else if (s.isTrue(it->first)) { + up.push_back(numL); + } + } + bounds_ = new wsum_t[(numRules() * (3 + uint32(step_.type != 0)))]; // upper, sum, temp, lower + std::fill(this->opt(), this->sum(), SharedData::maxBound()); + std::fill(this->sum(), this->end(), wsum_t(0)); + stepInit(0); + // [0,numL+1) : undo stack + // [numL+1, numL*2): pos stack + undo_ = new UndoInfo[(numL*2)+1]; + undoTop_ = 0; + posTop_ = numL+1; + actLev_ = 0; + for (WeightVec::size_type i = 0; i != up.size(); ++i) { + DefaultMinimize::propagate(s, shared_->lits[up[i]].first, up[i]); + } + return true; +} + +// Returns the numerical highest decision level watched by this constraint. +uint32 DefaultMinimize::lastUndoLevel(const Solver& s) const { + return undoTop_ != 0 + ? s.level(shared_->lits[undo_[undoTop_-1].index()].first.var()) + : 0; +} +bool DefaultMinimize::litSeen(uint32 i) const { return undo_[i].data.idxSeen != 0; } + +// Pushes the literal at index idx onto the undo stack +// and marks it as seen; if literal is first in current level +// adds a new undo watch. +void DefaultMinimize::pushUndo(Solver& s, uint32 idx) { + assert(idx >= static_cast(pos_ - shared_->lits)); + undo_[undoTop_].data.idx = idx; + undo_[undoTop_].data.newDL= 0; + if (lastUndoLevel(s) != s.decisionLevel()) { + // remember current "look at" position and start + // a new decision level on the undo stack + undo_[posTop_++].data.idx = static_cast(pos_-shared_->lits); + s.addUndoWatch(s.decisionLevel(), this); + undo_[undoTop_].data.newDL = 1; + } + undo_[idx].data.idxSeen = 1; + ++undoTop_; +} +///////////////////////////////////////////////////////////////////////////////////////// +// MinimizeConstraint - arithmetic strategy implementation +// +// For now we use a simple "switch-on-type" approach. +// In the future, if new strategies emerge, we may want to use a strategy hierarchy. +///////////////////////////////////////////////////////////////////////////////////////// +#define STRATEGY(x) shared_->x +// set *lhs = *rhs, where lhs != rhs +void DefaultMinimize::assign(wsum_t* lhs, wsum_t* rhs) const { + std::memcpy(lhs, rhs, size_*sizeof(wsum_t)); +} +// returns lhs > rhs +bool DefaultMinimize::greater(wsum_t* lhs, wsum_t* rhs, uint32 len, uint32& aLev) const { + while (*lhs == *rhs && --len) { ++lhs, ++rhs; ++aLev; } + return *lhs > *rhs; +} +///////////////////////////////////////////////////////////////////////////////////////// +Constraint::PropResult DefaultMinimize::propagate(Solver& s, Literal, uint32& data) { + pushUndo(s, data); + STRATEGY(add(sum(), shared_->lits[data])); + return PropResult(propagateImpl(s, propagate_new_sum), true); +} + +// Computes the set of literals implying p and returns +// the highest decision level of that set. +// PRE: p is implied on highest undo level +uint32 DefaultMinimize::computeImplicationSet(const Solver& s, const WeightLiteral& p, uint32& undoPos) { + wsum_t* temp = this->temp(), *opt = this->opt(); + uint32 up = undoTop_, lev = actLev_; + uint32 minLevel = std::max(s.level(tag_.var()), s.level(s.sharedContext()->stepLiteral().var())); + // start from current sum + assign(temp, sum()); + // start with full set + for (UndoInfo u; up != 0; --up) { + u = undo_[up-1]; + // subtract last element from set + STRATEGY(sub(temp, shared_->lits[u.index()], lev)); + if (!STRATEGY(imp(temp, p, opt, lev))) { + // p is no longer implied after we removed last literal, + // hence [0, up) implies p @ level of last literal + undoPos = up; + return std::max(s.level(shared_->lits[u.index()].first.var()), minLevel); + } + } + undoPos = 0; + return minLevel; +} + +bool DefaultMinimize::propagateImpl(Solver& s, PropMode m) { + Iter it = pos_; + uint32 idx = static_cast(it - shared_->lits); + uint32 DL = s.decisionLevel(); + // current implication level or "unknown" if + // we propagate a new optimum + uint32 impLevel = DL + (m == propagate_new_opt); + weight_t lastW = -1; + uint32 undoPos = undoTop_; + bool ok = true; + actLev_ = std::min(actLev_, shared_->level(idx)); + for (wsum_t* sum= this->sum(), *opt = this->opt(); ok && !isSentinel(it->first); ++it, ++idx) { + // skip propagated/false literals + if (litSeen(idx) || (m == propagate_new_sum && s.isFalse(it->first))) { + continue; + } + if (lastW != it->second) { + // check if the current weight is implied + if (!STRATEGY(imp(sum, *it, opt, actLev_))) { + // all good - current optimum is safe + pos_ = it; + return true; + } + // compute implication set and level of current weight + if (m == propagate_new_opt) { + impLevel = computeImplicationSet(s, *it, undoPos); + } + lastW = it->second; + } + assert(active()); + // force implied literals + if (!s.isFalse(it->first) || (impLevel < DL && s.level(it->first.var()) > impLevel)) { + if (impLevel != DL) { DL = s.undoUntil(impLevel, Solver::undo_pop_bt_level); } + ok = s.force(~it->first, impLevel, this, undoPos); + } + } + return ok; +} + +// pops free literals from the undo stack and decreases current sum +void DefaultMinimize::undoLevel(Solver&) { + assert(undoTop_ != 0 && posTop_ > undoTop_); + uint32 up = undoTop_; + uint32 idx = undo_[--posTop_].index(); + for (wsum_t* sum = this->sum();;) { + UndoInfo& u = undo_[--up]; + undo_[u.index()].data.idxSeen = 0; + STRATEGY(sub(sum, shared_->lits[u.index()], actLev_)); + if (u.newDL()) { break; } + } + undoTop_ = up; + Iter temp= shared_->lits + idx; + if (temp < pos_) { + pos_ = temp; + actLev_ = std::min(actLev_, shared_->level(idx)); + } +} + +// computes the reason for p - +// all literals that were propagated before p +void DefaultMinimize::reason(Solver& s, Literal p, LitVec& lits) { + assert(s.isTrue(tag_)); + uint32 stop = s.reasonData(p); + Literal x = s.sharedContext()->stepLiteral(); + assert(stop <= undoTop_); + if (!isSentinel(x) && s.isTrue(x)) { lits.push_back(x); } + if (s.level(tag_.var())) { lits.push_back(tag_); } + for (uint32 i = 0; i != stop; ++i) { + UndoInfo u = undo_[i]; + x = shared_->lits[u.index()].first; + lits.push_back(x); + } +} + +bool DefaultMinimize::minimize(Solver& s, Literal p, CCMinRecursive* rec) { + assert(s.isTrue(tag_)); + uint32 stop = s.reasonData(p); + Literal x = s.sharedContext()->stepLiteral(); + assert(stop <= undoTop_); + if (!s.ccMinimize(x, rec) || !s.ccMinimize(tag_, rec)) { return false; } + for (uint32 i = 0; i != stop; ++i) { + UndoInfo u = undo_[i]; + x = shared_->lits[u.index()].first; + if (!s.ccMinimize(x, rec)) { + return false; + } + } + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultMinimize - bound management +///////////////////////////////////////////////////////////////////////////////////////// +// Stores the current sum as the shared optimum. +void DefaultMinimize::commitUpperBound(const Solver&) { + shared_->setOptimum(sum()); + if (step_.type == MinimizeMode_t::bb_step_inc) { step_.size *= 2; } +} +bool DefaultMinimize::commitLowerBound(Solver& s, bool upShared) { + bool act = active() && shared_->checkNext(); + bool more = step_.lev < size_ && (step_.size > 1 || step_.lev != size_-1); + if (act && step_.type && step_.lev < size_) { + uint32 x = step_.lev; + wsum_t L = opt()[x] + 1; + if (upShared) { + wsum_t sv = shared_->incLower(x, L); + if (sv == L) { reportLower(s, x, sv); } + else { L = sv; } + } + stepLow()= L; + if (step_.type == MinimizeMode_t::bb_step_inc){ step_.size = 1; } + } + return more; +} +bool DefaultMinimize::handleUnsat(Solver& s, bool up, LitVec& out) { + bool more = shared_->optimize() && commitLowerBound(s, up); + uint32 dl = s.isTrue(tag_) ? s.level(tag_.var()) : 0; + relaxBound(false); + if (more && dl && dl <= s.rootLevel()) { + s.popRootLevel(s.rootLevel()-dl, &out); // pop and remember new path + return s.popRootLevel(1); // pop tag - disable constraint + } + return false; +} + +// Disables the minimize constraint by clearing its upper bound. +bool DefaultMinimize::relaxBound(bool full) { + if (active()) { std::fill(opt(), opt()+size_, SharedData::maxBound()); } + pos_ = shared_->lits; + actLev_ = 0; + if (full || !shared_->optimize()) { stepInit(0); } + return true; +} + +void DefaultMinimize::stepInit(uint32 n) { + step_.size = uint32(step_.type != MinimizeMode_t::bb_step_dec); + if (step_.type) { step_.lev = n; if (n != size_) stepLow() = 0-shared_->maxBound(); } + else { step_.lev = shared_->maxLevel(); } +} + +// Integrates new (tentative) bounds from the ones stored in the shared data object. +bool DefaultMinimize::integrateBound(Solver& s) { + bool useTag = shared_->optimize() && (step_.type != 0 || shared_->mode() == MinimizeMode_t::enumOpt); + if (!prepare(s, useTag)) { return false; } + if (useTag && s.level(tag_.var()) == 0) { + step_.type = 0; + stepInit(0); + } + if ((active() && !shared_->checkNext())) { return !s.hasConflict(); } + WeightLiteral min(lit_true(), shared_->weights.empty() ? uint32(0) : (uint32)shared_->weights.size()-1); + while (!s.hasConflict() && updateBounds(shared_->checkNext())) { + uint32 x = 0; + uint32 dl= s.decisionLevel() + 1; + if (!STRATEGY(imp(sum(), min, opt(), actLev_)) || (dl = computeImplicationSet(s, min, x)) > s.rootLevel()) { + for (--dl; !s.hasConflict() || s.resolveConflict(); ) { + if (s.undoUntil(dl, Solver::undo_pop_bt_level) > dl){ s.backtrack(); } + else if (propagateImpl(s, propagate_new_opt)) { return true; } + } + } + if (!shared_->checkNext()) { + break; + } + if (!step_.type) { ++step_.lev; } + else { stepLow() = ++opt()[step_.lev]; } + } + relaxBound(false); + if (!s.hasConflict()) { + s.undoUntil(0); + s.setStopConflict(); + } + return false; +} + +// Loads bounds from the shared data object and (optionally) applies +// the current step to get the next tentative bound to check. +bool DefaultMinimize::updateBounds(bool applyStep) { + for (;;) { + const uint32 seq = shared_->generation(); + const wsum_t* upper = shared_->upper(); + wsum_t* myLow = step_.type ? end() : 0; + wsum_t* bound = opt(); + uint32 appLev= applyStep ? step_.lev : size_; + for (uint32 i = 0; i != size_; ++i) { + wsum_t U = upper[i], B = bound[i]; + if (i != appLev) { + wsum_t L = shared_->lower(i); + if (myLow) { + if (i > step_.lev || L > myLow[i]) { myLow[i] = L; } + else { L = myLow[i]; } + } + if (i > appLev) { bound[i] = SharedData::maxBound(); } + else if (U >= L) { bound[i] = U; } + else { stepInit(size_); return false; } + continue; + } + if (step_.type) { + wsum_t L = (stepLow() = std::max(myLow[i], shared_->lower(i))); + if (U < L) { // path exhausted? + stepInit(size_); + return false; + } + if (B < L) { // tentative bound too strong? + return false; + } + if (B < U) { // existing step? + assert(std::count(bound+i+1, bound+size_, SharedData::maxBound()) == int(size_ - (i+1))); + return true; + } + if (U == L) {// done with current level? + bound[i] = U; + stepInit(++appLev); + continue; + } + assert(U > L && B > L); + wsum_t diff = U - L; + uint32 half = static_cast( (diff>>1) | (diff&1) ); + if (step_.type == MinimizeMode_t::bb_step_inc) { + step_.size = std::min(step_.size, half); + } + else if (step_.type == MinimizeMode_t::bb_step_dec) { + if (!step_.size) { step_.size = static_cast(diff); } + else { step_.size = half; } + } + } + assert(step_.size != 0); + bound[i] = U - step_.size; + actLev_ = 0; + pos_ = shared_->lits; + } + if (seq == shared_->generation()) { break; } + } + return step_.lev != size_ || !applyStep; +} +#undef STRATEGY +///////////////////////////////////////////////////////////////////////////////////////// +// MinimizeBuilder +///////////////////////////////////////////////////////////////////////////////////////// +MinimizeBuilder::MinimizeBuilder() { } +void MinimizeBuilder::clear() { + LitVec().swap(lits_); +} +bool MinimizeBuilder::empty() const { + return lits_.empty(); +} +MinimizeBuilder& MinimizeBuilder::add(weight_t prio, const WeightLitVec& lits) { + for (WeightLitVec::const_iterator it = lits.begin(), end = lits.end(); it != end; ++it) { + add(prio, *it); + } + return *this; +} +MinimizeBuilder& MinimizeBuilder::add(weight_t prio, WeightLiteral lit) { + lits_.push_back(MLit(lit, prio)); + return *this; +} +MinimizeBuilder& MinimizeBuilder::add(weight_t prio, weight_t w) { + lits_.push_back(MLit(WeightLiteral(lit_true(), w), prio)); + return *this; +} +MinimizeBuilder& MinimizeBuilder::add(const SharedData& con) { + if (con.numRules() == 1) { + const weight_t P = !con.prios.empty() ? con.prios[0] : 0; + for (const WeightLiteral* it = con.lits; !isSentinel(it->first); ++it) { add(P, *it); } + } + else { + for (const WeightLiteral* it = con.lits; !isSentinel(it->first); ++it) { + const SharedData::LevelWeight* w = &con.weights[it->second]; + do { + add( w->level < con.prios.size() ? con.prios[w->level] : -static_cast(w->level), WeightLiteral(it->first, w->weight) ); + } while (w++->next); + } + } + for (uint32 i = 0; i != con.numRules(); ++i) { + if (wsum_t w = con.adjust(i)) { + const weight_t P = i < con.prios.size() ? con.prios[i] : -static_cast(i); + while (w < CLASP_WEIGHT_T_MIN) { add(P, CLASP_WEIGHT_T_MIN); w -= CLASP_WEIGHT_T_MIN; } + while (w > CLASP_WEIGHT_T_MAX) { add(P, CLASP_WEIGHT_T_MAX); w -= CLASP_WEIGHT_T_MAX; } + add(P, static_cast(w)); + } + } + return *this; +} +// Comparator for preparing levels: compare (prio, var, weight) +bool MinimizeBuilder::CmpPrio::operator()(const MLit& lhs, const MLit& rhs) const { + if (lhs.prio != rhs.prio) { return lhs.prio > rhs.prio; } + if (lhs.lit.var() != rhs.lit.var()) { return lhs.lit < rhs.lit; } + return lhs.weight > rhs.weight; +} +// Comparator for merging levels: compare (var, level, weight) +bool MinimizeBuilder::CmpLit::operator()(const MLit& lhs, const MLit& rhs) const { + if (lhs.lit.var() != rhs.lit.var()) { return lhs.lit < rhs.lit; } + if (lhs.prio != rhs.prio) { return lhs.prio < rhs.prio; } + return lhs.weight > rhs.weight; +} +// Comparator for sorting literals by final weight +bool MinimizeBuilder::CmpWeight::operator()(const MLit& lhs, const MLit& rhs) const { + if (!weights) { return lhs.weight > rhs.weight; } + const SharedData::LevelWeight* wLhs = &(*weights)[lhs.weight]; + const SharedData::LevelWeight* wRhs = &(*weights)[rhs.weight]; + for (;; ++wLhs, ++wRhs) { + if (wLhs->level != wRhs->level) { return wLhs->level < wRhs->level; } + if (wLhs->weight != wRhs->weight){ return wLhs->weight > wRhs->weight; } + if (!wLhs->next) { return wRhs->next && (++wRhs)->weight < 0; } + if (!wRhs->next) { ++wLhs; break; } + } + return wLhs->weight > 0; +} + +// Replaces integer priorities with increasing levels and merges duplicate/complementary literals. +void MinimizeBuilder::prepareLevels(const Solver& s, SumVec& adjust, WeightVec& prios) { + // group first by decreasing priorities and then by variables + std::stable_sort(lits_.begin(), lits_.end(), CmpPrio()); + prios.clear(); adjust.clear(); + // assign levels and simplify lits + LitVec::iterator j = lits_.begin(); + for (LitVec::const_iterator it = lits_.begin(), end = lits_.end(); it != end;) { + const weight_t P = it->prio, L = static_cast(prios.size()); + wsum_t R = 0; + for (LitVec::const_iterator k; it != end && it->prio == P; it = k) { + Literal x(it->lit); // make literal unique wrt this level + wsum_t w = it->weight; + for (k = it + 1; k != end && k->lit.var() == x.var() && k->prio == P; ++k) { + if (k->lit == x){ w += k->weight; } + else { w -= k->weight; R += k->weight; } + } + if (w < 0){ + R += w; + x = ~x; + w = -w; + } + if (w && s.value(x.var()) == value_free) { + CLASP_FAIL_IF(static_cast(w) != w, "MinimizeBuilder: weight too large!"); + *j++ = MLit(WeightLiteral(x, static_cast(w)), L); + } + else if (s.isTrue(x)) { R += w; } + } + prios.push_back(P); + adjust.push_back(R); + } + lits_.erase(j, lits_.end()); +} + +void MinimizeBuilder::mergeLevels(SumVec& adjust, SharedData::WeightVec& weights) { + // group first by variables and then by increasing levels + std::stable_sort(lits_.begin(), lits_.end(), CmpLit()); + LitVec::iterator j = lits_.begin(); + weights.clear(); weights.reserve(lits_.size()); + for (LitVec::const_iterator it = lits_.begin(), end = lits_.end(), k; it != end; it = k) { + // handle first occurrence of var + assert(it->weight > 0 && "most important occurrence of lit must have positive weight"); + weight_t wpos = (weight_t)weights.size(); + weights.push_back(SharedData::LevelWeight(it->prio, it->weight)); + // handle remaining occurrences with lower prios + for (k = it + 1; k != end && k->lit.var() == it->lit.var(); ++k) { + assert(k->prio > it->prio && "levels not prepared!"); + weights.back().next = 1; + weights.push_back(SharedData::LevelWeight(k->prio, k->weight)); + if (k->lit.sign() != it->lit.sign()) { + adjust[k->prio] += k->weight; + weights.back().weight = -k->weight; + } + } + (*j = *it).weight = wpos; + ++j; + } + lits_.erase(j, lits_.end()); +} + +MinimizeBuilder::SharedData* MinimizeBuilder::createShared(SharedContext& ctx, const SumVec& adjust, const CmpWeight& cmp) { + const uint32 nLits = static_cast(lits_.size()); + SharedData* ret = new (::operator new(sizeof(SharedData) + ((nLits + 1)*sizeof(WeightLiteral)))) SharedData(adjust); + // sort literals by decreasing weight + std::stable_sort(lits_.begin(), lits_.end(), cmp); + uint32 last = 0; + weight_t wIdx = 0; + for (uint32 i = 0; i != nLits; ++i) { + WeightLiteral x(lits_[i].lit, lits_[i].weight); + ctx.setFrozen(x.first.var(), true); + ret->lits[i] = x; + if (!cmp.weights) { continue; } + if (!i || cmp(lits_[last], lits_[i])) { + last = i; + wIdx = (weight_t)ret->weights.size(); + for (const SharedData::LevelWeight* w = &(*cmp.weights)[x.second];; ++w) { + ret->weights.push_back(*w); + if (!w->next) { break; } + } + } + ret->lits[i].second = wIdx; + } + ret->lits[nLits] = WeightLiteral(lit_true(), (weight_t)ret->weights.size()); + if (cmp.weights) { + ret->weights.push_back(SharedData::LevelWeight((uint32)adjust.size()-1, 0)); + } + ret->resetBounds(); + return ret; +} + +MinimizeBuilder::SharedData* MinimizeBuilder::build(SharedContext& ctx) { + CLASP_ASSERT_CONTRACT(ctx.ok() && !ctx.frozen()); + ctx.master()->propagate(); + if (empty()) { return 0; } + typedef SharedData::WeightVec FlatVec; + WeightVec prios; + SumVec adjust; + FlatVec weights; + CmpWeight cmp(0); + prepareLevels(*ctx.master(), adjust, prios); + if (prios.size() > 1) { + mergeLevels(adjust, weights); + cmp.weights = &weights; + } + else if (prios.empty()) { + prios.assign(1, 0); + adjust.assign(1, 0); + } + SharedData* ret = createShared(ctx, adjust, cmp); + ret->prios.swap(prios); + clear(); + return ret; +} +///////////////////////////////////////////////////////////////////////////////////////// +// UncoreMinimize +///////////////////////////////////////////////////////////////////////////////////////// +UncoreMinimize::UncoreMinimize(SharedMinimizeData* d, uint32 strat) + : MinimizeConstraint(d) + , enum_(0) + , sum_(new wsum_t[d->numRules()]) + , auxInit_(UINT32_MAX) + , auxAdd_(0) + , freeOpen_(0) + , options_(0) { + options_ = strat & 15u; +} +void UncoreMinimize::init() { + releaseLits(); + fix_.clear(); + eRoot_ = 0; + aTop_ = 0; + upper_ = shared_->upper(0); + lower_ = 0; + gen_ = 0; + level_ = 0; + valid_ = 0; + sat_ = 0; + pre_ = 0; + path_ = 1; + next_ = 0; + init_ = 1; + actW_ = 1; + nextW_ = 0; +} +bool UncoreMinimize::attach(Solver& s) { + init(); + initRoot(s); + auxInit_ = UINT32_MAX; + auxAdd_ = 0; + if (s.sharedContext()->concurrency() > 1 && shared_->mode() == MinimizeMode_t::enumOpt) { + enum_ = new DefaultMinimize(shared_->share(), 0); + enum_->attach(s); + enum_->relaxBound(true); + } + return true; +} +// Detaches the constraint and all cores from s and removes +// any introduced aux vars. +void UncoreMinimize::detach(Solver* s, bool b) { + releaseLits(); + if (s && auxAdd_ && s->numAuxVars() == (auxInit_ + auxAdd_)) { + s->popAuxVar(auxAdd_, &closed_); + auxInit_ = UINT32_MAX; + auxAdd_ = 0; + } + Clasp::destroyDB(closed_, s, b); + fix_.clear(); +} +// Destroys this object and optionally detaches it from the given solver. +void UncoreMinimize::destroy(Solver* s, bool b) { + detach(s, b); + delete [] sum_; + if (enum_) { enum_->destroy(s, b); enum_ = 0; } + MinimizeConstraint::destroy(s, b); +} +Constraint::PropResult UncoreMinimize::propagate(Solver&, Literal, uint32&) { + return PropResult(true, true); +} +bool UncoreMinimize::simplify(Solver& s, bool) { + if (s.decisionLevel() == 0) { simplifyDB(s, closed_, false); } + return false; +} +void UncoreMinimize::reason(Solver& s, Literal, LitVec& out) { + uint32 r = initRoot(s); + for (uint32 i = 1; i <= r; ++i) { + out.push_back(s.decision(i)); + } +} + +// Integrates any new information from this constraint into s. +bool UncoreMinimize::integrate(Solver& s) { + assert(!s.isFalse(tag_)); + bool useTag = (shared_->mode() == MinimizeMode_t::enumOpt) || s.sharedContext()->concurrency() > 1; + if (!prepare(s, useTag)) { + return false; + } + if (enum_ && !shared_->optimize() && !enum_->integrateBound(s)) { + return false; + } + for (uint32 gGen = shared_->generation(); gGen != gen_; ) { + gen_ = gGen; + upper_ = shared_->upper(level_); + gGen = shared_->generation(); + valid_ = 0; + } + return pushPath(s); +} + +// Initializes the next optimization level to look at. +bool UncoreMinimize::initLevel(Solver& s) { + initRoot(s); + sat_ = 0; + pre_ = 0; + path_ = 1; + init_ = 0; + sum_[0]= -1; + actW_ = 1; + nextW_ = 0; + if (!fixLevel(s)) { + return false; + } + for (LitVec::const_iterator it = fix_.begin(), end = fix_.end(); it != end; ++it) { + if (!s.force(*it, eRoot_, this)) { return false; } + } + if (!shared_->optimize()) { + next_ = 0; + level_ = shared_->maxLevel(); + lower_ = shared_->lower(level_); + upper_ = shared_->upper(level_); + return true; + } + weight_t maxW = 1; + for (uint32 level = (level_ + next_), n = 1; level <= shared_->maxLevel() && assume_.empty(); ++level) { + level_ = level; + lower_ = 0; + upper_ = shared_->upper(level_); + for (const WeightLiteral* it = shared_->lits; !isSentinel(it->first); ++it) { + if (weight_t w = shared_->weight(*it, level_)){ + Literal x = it->first; + if (w < 0) { + lower_ += w; + w = -w; + x = ~x; + } + if (s.value(x.var()) == value_free || s.level(x.var()) > eRoot_) { + addLit(x, w); + if (w > maxW){ maxW = w; } + } + else if (s.isTrue(x)) { + lower_ += w; + } + } + } + if (n == 1) { + if (lower_ > upper_){ next_ = 1; break; } + else if (lower_ < upper_){ next_ = (n = 0); } + else { + n = shared_->checkNext() || level != shared_->maxLevel(); + next_ = n; + while (!assume_.empty()) { + fixLit(s, assume_.back().lit); + assume_.pop_back(); + } + litData_.clear(); + assume_.clear(); + maxW = 1; + } + } + } + pre_ = (options_ & MinimizeMode_t::usc_preprocess) != 0u; + actW_ = (options_ & MinimizeMode_t::usc_stratify) != 0u ? maxW : 1; + valid_= (pre_ == 0 && maxW == 1); + if (next_ && !s.hasConflict()) { + s.force(~tag_, Antecedent(0)); + next_ = 0; + pre_ = 0; + } + if (auxInit_ == UINT32_MAX) { + auxInit_ = s.numAuxVars(); + } + return !s.hasConflict(); +} + +UncoreMinimize::LitData& UncoreMinimize::addLit(Literal p, weight_t w) { + assert(w > 0); + litData_.push_back(LitData(w, true, 0)); + assume_.push_back(LitPair(~p, sizeVec(litData_))); + if (nextW_ && w > nextW_) { + nextW_ = w; + } + return litData_.back(); +} + +// Pushes the active assumptions from the active optimization level to +// the root path. +bool UncoreMinimize::pushPath(Solver& s) { + bool ok = !s.hasConflict() && !sat_ && (!path_ || (!next_ && !init_) || initLevel(s)); + bool path = path_ != 0; + while (path) { + uint32 j = 0; + nextW_ = 0; + path_ = uint32(path = false); + ok = ok && s.simplify() && s.propagate(); + initRoot(s); + assert(s.queueSize() == 0); + for (uint32 i = 0, end = sizeVec(assume_), dl; i != end; ++i) { + LitData& x = getData(assume_[i].id); + if (x.assume) { + assume_[j++] = assume_[i]; + Literal lit = assume_[i].lit; + weight_t w = x.weight; + if (w < actW_) { + nextW_ = std::max(nextW_, w); + continue; + } + else if (!ok || s.isTrue(lit)) { continue; } + else if ((lower_ + w) > upper_){ + ok = fixLit(s, lit); + path = true; + x.assume = 0; + x.weight = 0; + if (hasCore(x)) { closeCore(s, x, false); } + --j; + } + else if (s.value(lit.var()) == value_free) { + ok = path || s.pushRoot(lit); + aTop_ = s.rootLevel(); + } + else if (s.level(lit.var()) > eRoot_) { + todo_.push_back(LitPair(~lit, assume_[i].id)); + ok = s.force(lit, Antecedent(0)); + } + else { + LitPair core(~lit, assume_[i].id); + dl = s.decisionLevel(); + ok = addCore(s, &core, 1, x.weight); + end = sizeVec(assume_); + path = path || (ok && s.decisionLevel() != dl); + --j; + } + } + } + shrinkVecTo(assume_, j); + CLASP_FAIL_IF(!sat_ && s.decisionLevel() != s.rootLevel(), "pushPath must be called on root level (%u:%u)", s.rootLevel(), s.decisionLevel()); + } + if (sat_ || (ok && !validLowerBound())) { + ok = false; + sat_ = 1; + s.setStopConflict(); + } + return ok; +} + +// Removes invalid assumptions from the root path. +bool UncoreMinimize::popPath(Solver& s, uint32 dl, LitVec& out) { + CLASP_ASSERT_CONTRACT(dl <= aTop_ && eRoot_ <= aTop_ && "You must not mess with my root level!"); + if (dl < eRoot_) { dl = eRoot_; } + if (s.rootLevel() > aTop_) { + // remember any assumptions added after us and + // force removal of our assumptions because we want + // them nicely arranged one after another + s.popRootLevel(s.rootLevel() - aTop_, &out, true); + dl = eRoot_; + path_ = 1; + CLASP_FAIL_IF(true, "TODO: splitting not yet supported!"); + } + return s.popRootLevel(s.rootLevel() - (aTop_ = dl)); +} + +bool UncoreMinimize::relax(Solver& s, bool reset) { + if (sat_ && !reset) { + // commit cores of last model + s.setStopConflict(); + LitVec ignore; + handleUnsat(s, false, ignore); + } + if ((reset && shared_->optimize()) || !assume_.empty() || level_ != shared_->maxLevel() || next_) { + detach(&s, true); + init(); + } + else { + releaseLits(); + } + if (!shared_->optimize()) { + gen_ = shared_->generation(); + next_ = 0; + valid_= 1; + } + init_ = 1; + sat_ = 0; + assert(assume_.empty()); + return !enum_ || enum_->relax(s, reset); +} + +// Computes the costs of the current assignment. +wsum_t* UncoreMinimize::computeSum(Solver& s) const { + std::fill_n(sum_, shared_->numRules(), wsum_t(0)); + for (const WeightLiteral* it = shared_->lits; !isSentinel(it->first); ++it) { + if (s.isTrue(it->first)) { shared_->add(sum_, *it); } + } + return sum_; +} + +void UncoreMinimize::setLower(wsum_t x) { + if (!pre_ && x > lower_ && nextW_ == 0) { + fprintf(stderr, "*** WARNING: Fixing lower bound (%u - %u)\n", (uint32)lower_, (uint32)x); + lower_ = x; + } +} + +// Checks whether the current assignment in s is valid w.r.t the +// bound stored in the shared data object. +bool UncoreMinimize::valid(Solver& s) { + if (shared_->upper(level_) == SharedData::maxBound()){ return true; } + if (gen_ == shared_->generation() && valid_ == 1) { return true; } + if (sum_[0] < 0) { computeSum(s); } + const wsum_t* rhs; + uint32 end = shared_->numRules(); + wsum_t cmp = 0; + do { + gen_ = shared_->generation(); + rhs = shared_->upper(); + upper_= rhs[level_]; + for (uint32 i = level_; i != end && (cmp = sum_[i]-rhs[i]) == 0; ++i) { ; } + } while (gen_ != shared_->generation()); + wsum_t low = sum_[level_]; + if (s.numFreeVars() != 0) { sum_[0] = -1; } + if (cmp < wsum_t(!shared_->checkNext())) { + valid_ = s.numFreeVars() == 0; + return true; + } + valid_ = 0; + sat_ = 1; + setLower(low); + s.setStopConflict(); + return false; +} +// Sets the current sum as the current shared optimum. +bool UncoreMinimize::handleModel(Solver& s) { + if (!valid(s)) { return false; } + if (sum_[0] < 0){ computeSum(s);} + shared_->setOptimum(sum_); + sat_ = shared_->checkNext(); + gen_ = shared_->generation(); + upper_= shared_->upper(level_); + valid_= 1; + if (sat_) { setLower(sum_[level_]); } + return true; +} + +// Tries to recover from either a model or a root-level conflict. +bool UncoreMinimize::handleUnsat(Solver& s, bool up, LitVec& out) { + assert(s.hasConflict()); + if (enum_) { enum_->relaxBound(true); } + path_ = 1; + sum_[0] = -1; + do { + if (sat_ == 0) { + if (s.hasStopConflict()) { return false; } + weight_t mw; + uint32 cs = analyze(s, mw, out); + if (!cs) { + todo_.clear(); + return false; + } + if (pre_ == 0) { + addCore(s, &todo_[0], cs, mw); + todo_.clear(); + } + else { // preprocessing: remove assumptions and remember core + todo_.push_back(LitPair(lit_true(), 0)); // null-terminate core + lower_ += mw; + for(LitSet::iterator it = todo_.end() - (cs + 1); it->id; ++it) { + getData(it->id).assume = 0; + } + } + sat_ = !validLowerBound(); + if (up && shared_->incLower(level_, lower_) == lower_) { + reportLower(s, level_, lower_); + } + } + else { + s.clearStopConflict(); + popPath(s, 0, out); + sat_ = 0; + for (LitSet::iterator it = todo_.begin(), end = todo_.end(), cs; (cs = it) != end; ++it) { + weight_t w = std::numeric_limits::max(); + while (it->id) { w = std::min(w, getData(it->id).weight); ++it; } + lower_ -= w; + if (!addCore(s, &*cs, uint32(it - cs), w)) { break; } + } + wsum_t cmp = (lower_ - upper_); + if (cmp >= 0) { + fixLevel(s); + if (cmp > 0) { s.hasConflict() || s.force(~tag_, Antecedent(0)); } + else { next_ = level_ != shared_->maxLevel() || shared_->checkNext(); } + } + if (pre_) { + LitSet().swap(todo_); + pre_ = 0; + } + if (nextW_) { + actW_ = nextW_; + valid_= 0; + pre_ = (options_ & MinimizeMode_t::usc_preprocess) != 0u; + } + } + } while (sat_ || s.hasConflict() || (next_ && out.empty() && !initLevel(s))); + return true; +} + +// Analyzes the current root level conflict and stores the set of our assumptions +// that caused the conflict in todo_. +uint32 UncoreMinimize::analyze(Solver& s, weight_t& minW, LitVec& poppedOther) { + uint32 cs = 0; + uint32 minDL = s.decisionLevel(); + minW = std::numeric_limits::max(); + if (!todo_.empty() && todo_.back().id) { + cs = 1; + minW = getData(todo_.back().id).weight; + minDL= s.level(todo_.back().lit.var()); + } + if (s.decisionLevel() <= eRoot_) { + return cs; + } + conflict_.clear(); + s.resolveToCore(conflict_); + for (LitVec::const_iterator it = conflict_.begin(), end = conflict_.end(); it != end; ++it) { + s.markSeen(*it); + } + // map marked root decisions back to our assumptions + Literal p; + uint32 roots = (uint32)conflict_.size(), dl; + for (LitSet::iterator it = assume_.begin(), end = assume_.end(); it != end && roots; ++it) { + if (s.seen(p = it->lit) && (dl = s.level(p.var())) > eRoot_ && dl <= aTop_) { + assert(p == s.decision(dl) && getData(it->id).assume); + if (dl < minDL) { minDL = dl; } + minW = std::min(getData(it->id).weight, minW); + todo_.push_back(LitPair(~p, it->id)); + ++cs; + s.clearSeen(p.var()); + --roots; + } + } + popPath(s, minDL - (minDL != 0), poppedOther); + if (roots) { // clear remaining levels - can only happen if someone messed with our assumptions + for (LitVec::const_iterator it = conflict_.begin(), end = conflict_.end(); it != end; ++it) { s.clearSeen(it->var()); } + } + return cs; +} + +// Eliminates the given core by adding suitable constraints to the solver. +bool UncoreMinimize::addCore(Solver& s, const LitPair* lits, uint32 cs, weight_t w) { + assert(s.decisionLevel() == s.rootLevel()); + assert(w && cs); + // apply weight and check for subcores + lower_ += w; + for (uint32 i = 0; i != cs; ++i) { + LitData& x = getData(lits[i].id); + if ( (x.weight -= w) <= 0) { + x.assume = 0; + x.weight = 0; + } + else if (pre_ && !x.assume) { + x.assume = 1; + assume_.push_back(LitPair(~lits[i].lit, lits[i].id)); + } + if (x.weight == 0 && hasCore(x)) { + Core& core = getCore(x); + temp_.start(core.bound + 1); + for (uint32 k = 0, end = core.size(); k != end; ++k) { + Literal p = core.at(k); + while (s.topValue(p.var()) != s.value(p.var()) && s.rootLevel() > eRoot_) { + s.popRootLevel(s.rootLevel() - std::max(s.level(p.var())-1, eRoot_)); + aTop_ = std::min(aTop_, s.rootLevel()); + } + temp_.add(s, p); + } + weight_t cw = core.weight; + if (!closeCore(s, x, temp_.bound <= 1) || !addOllCon(s, temp_, cw)) { + return false; + } + } + } + // add new core + return (options_ & MinimizeMode_t::usc_clauses) == 0u + ? addOll(s, lits, cs, w) + : addPmr(s, lits, cs, w); +} +bool UncoreMinimize::addOll(Solver& s, const LitPair* lits, uint32 size, weight_t w) { + temp_.start(2); + for (uint32 i = 0; i != size; ++i) { temp_.add(s, lits[i].lit); } + if (!temp_.unsat()) { + return addOllCon(s, temp_, w); + } + Literal fix = !temp_.lits.empty() ? temp_.lits[0].first : lits[0].lit; + return temp_.bound < 2 || fixLit(s, fix); +} +bool UncoreMinimize::addPmr(Solver& s, const LitPair* lits, uint32 size, weight_t w) { + if (size == 1) { + return fixLit(s, lits[0].lit); + } + uint32 i = size - 1; + Literal bp = lits[i].lit; + while (--i != 0) { + Literal an = lits[i].lit; + Literal bn = posLit(s.pushAuxVar()); + Literal cn = posLit(s.pushAuxVar()); + auxAdd_ += 2; + addLit(cn, w); + if (!addPmrCon(comp_disj, s, bn, an, bp)) { return false; } + if (!addPmrCon(comp_conj, s, cn, an, bp)) { return false; } + bp = bn; + } + Literal an = lits[i].lit; + Literal cn = posLit(s.pushAuxVar()); + ++auxAdd_; + addLit(cn, w); + return addPmrCon(comp_conj, s, cn, an, bp); +} +bool UncoreMinimize::addPmrCon(CompType c, Solver& s, Literal head, Literal body1, Literal body2) { + typedef ClauseCreator::Result Result; + const uint32 flags = ClauseCreator::clause_explicit | ClauseCreator::clause_not_root_sat | ClauseCreator::clause_no_add; + const bool sign = c == comp_conj; + uint32 first = 0, last = 3; + if ((options_ & MinimizeMode_t::usc_imp_only) != 0u) { + first = c == comp_disj; + last = first + (1 + (c == comp_disj)); + } + Literal temp[3][3] = { + { (~head)^ sign, body1 ^ sign, body2 ^ sign }, + { head ^ sign, (~body1)^ sign, lit_false() }, + { head ^ sign, (~body2)^ sign, lit_false() } + }; + for (uint32 i = first, sz = 3; i != last; ++i) { + Result res = ClauseCreator::create(s, ClauseRep::create(temp[i], sz, Constraint_t::Other), flags); + if (res.local) { closed_.push_back(res.local); } + if (!res.ok()) { return false; } + sz = 2; + } + return true; +} +bool UncoreMinimize::addOllCon(Solver& s, const WCTemp& wc, weight_t weight) { + typedef WeightConstraint::CPair ResPair; + weight_t B = wc.bound; + if (B <= 0) { + // constraint is sat and hence conflicting w.r.t new assumption - + // relax core + lower_ += ((1-B)*weight); + B = 1; + } + if (static_cast(B) > static_cast(wc.lits.size())) { + // constraint is unsat and hence the new assumption is trivially satisfied + return true; + } + // create new var for this core + Var newAux = s.pushAuxVar(); + ++auxAdd_; + LitData& x = addLit(negLit(newAux), weight); + WeightLitsRep rep = {&const_cast(wc).lits[0], (uint32)wc.lits.size(), B, (weight_t)wc.lits.size()}; + uint32 fset = WeightConstraint::create_explicit | WeightConstraint::create_no_add | WeightConstraint::create_no_freeze | WeightConstraint::create_no_share; + if ((options_ & MinimizeMode_t::usc_imp_only) != 0u) { fset |= WeightConstraint::create_only_bfb; } + ResPair res = WeightConstraint::create(s, negLit(newAux), rep, fset); + if (res.ok() && res.first()) { + x.coreId = allocCore(res.first(), B, weight, rep.bound != rep.reach); + } + return !s.hasConflict(); +} + + +// Computes the solver's initial root level, i.e. all assumptions that are not from us. +uint32 UncoreMinimize::initRoot(Solver& s) { + if (eRoot_ == aTop_ && !s.hasStopConflict()) { + eRoot_ = s.rootLevel(); + aTop_ = eRoot_; + } + return eRoot_; +} + +// Assigns p at the solver's initial root level. +bool UncoreMinimize::fixLit(Solver& s, Literal p) { + assert(s.decisionLevel() >= eRoot_); + if (s.decisionLevel() > eRoot_ && (!s.isTrue(p) || s.level(p.var()) > eRoot_)) { + // go back to root level + s.popRootLevel(s.rootLevel() - eRoot_); + aTop_ = s.rootLevel(); + } + if (eRoot_ && s.topValue(p.var()) != trueValue(p)) { fix_.push_back(p); } + return !s.hasConflict() && s.force(p, this); +} +// Fixes any remaining assumptions of the active optimization level. +bool UncoreMinimize::fixLevel(Solver& s) { + for (LitSet::iterator it = assume_.begin(), end = assume_.end(); it != end; ++it) { + if (getData(it->id).assume) { fixLit(s, it->lit); } + } + releaseLits(); + return !s.hasConflict(); +} +void UncoreMinimize::releaseLits() { + // remaining cores are no longer open - move to closed list + for (CoreTable::iterator it = open_.begin(), end = open_.end(); it != end; ++it) { + if (it->con) { closed_.push_back(it->con); } + } + open_.clear(); + litData_.clear(); + assume_.clear(); + todo_.clear(); + freeOpen_ = 0; +} + +uint32 UncoreMinimize::allocCore(WeightConstraint* con, weight_t bound, weight_t weight, bool open) { + if (!open) { + closed_.push_back(con); + return 0; + } + if (freeOpen_) { // pop next slot from free list + assert(open_[freeOpen_-1].con == 0); + uint32 id = freeOpen_; + freeOpen_ = static_cast(open_[id-1].bound); + open_[id-1] = Core(con, bound, weight); + return id; + } + open_.push_back(Core(con, bound, weight)); + return static_cast(open_.size()); +} +bool UncoreMinimize::closeCore(Solver& s, LitData& x, bool sat) { + if (uint32 coreId = x.coreId) { + Core& core = open_[coreId-1]; + x.coreId = 0; + // close by moving to closed list + if (!sat) { closed_.push_back(core.con); } + else { fixLit(s, core.tag()); core.con->destroy(&s, true); } + // link slot to free list + core = Core(0, 0, static_cast(freeOpen_)); + freeOpen_ = coreId; + } + return !s.hasConflict(); +} +uint32 UncoreMinimize::Core::size() const { return con->size() - 1; } +Literal UncoreMinimize::Core::at(uint32 i) const { return con->lit(i+1, WeightConstraint::FFB_BTB); } +Literal UncoreMinimize::Core::tag() const { return con->lit(0, WeightConstraint::FTB_BFB); } +void UncoreMinimize::WCTemp::add(Solver& s, Literal p) { + if (s.topValue(p.var()) == value_free) { lits.push_back(WeightLiteral(p, 1)); } + else if (s.isTrue(p)) { --bound; } +} + +} // end namespaces Clasp diff --git a/libclasp/src/model_enumerators.cpp b/libclasp/src/model_enumerators.cpp new file mode 100644 index 0000000..3843301 --- /dev/null +++ b/libclasp/src/model_enumerators.cpp @@ -0,0 +1,313 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +namespace Clasp { +class ModelEnumerator::ModelFinder : public EnumerationConstraint { +protected: + explicit ModelFinder() : EnumerationConstraint() {} + bool hasModel() const { return !solution.empty(); } + LitVec solution; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// strategy_record +///////////////////////////////////////////////////////////////////////////////////////// +class ModelEnumerator::RecordFinder : public ModelFinder { +public: + explicit RecordFinder(const LitVec* d) : ModelFinder(), dom(d) { } + ConPtr clone() { return new RecordFinder(dom); } + void doCommitModel(Enumerator& ctx, Solver& s); + bool doUpdate(Solver& s); + const LitVec* dom; +}; + +bool ModelEnumerator::RecordFinder::doUpdate(Solver& s) { + if (hasModel()) { + ConstraintInfo e(Constraint_t::Other); + ClauseCreator::Result ret = ClauseCreator::create(s, solution, ClauseCreator::clause_no_add, e); + solution.clear(); + if (ret.local) { add(ret.local);} + if (!ret.ok()) { return false; } + } + return true; +} + +void ModelEnumerator::RecordFinder::doCommitModel(Enumerator& en, Solver& s) { + ModelEnumerator& ctx = static_cast(en); + assert(solution.empty() && "Update not called!"); + solution.clear(); + if (dom && dom->empty()) { + if (en.lastModel().num == 0) { s.sharedContext()->warn("domRec ignored: no domain atoms found!"); } + dom = 0; + } + if (ctx.trivial() && !dom) { + return; + } + else if (!dom && !ctx.projectionEnabled()) { + for (uint32 x = s.decisionLevel(); x != 0; --x) { + Literal d = s.decision(x); + if (!s.auxVar(d.var())) { solution.push_back(~d); } + else if (d != s.tagLiteral()) { + // Todo: set of vars could be reduced to those having the aux var in their reason set. + const LitVec& tr = s.trail(); + const uint32 end= x != s.decisionLevel() ? s.levelStart(x+1) : (uint32)tr.size(); + for (uint32 n = s.levelStart(x)+1; n != end; ++n) { + if (!s.auxVar(tr[n].var())) { solution.push_back(~tr[n]); } + } + } + } + } + else if (!dom) { + for (Var i = 1, end = s.numProblemVars(); i <= end; ++i) { + if (ctx.project(i)) { + solution.push_back(~s.trueLit(i)); + } + } + solution.push_back(~s.sharedContext()->stepLiteral()); + } + else { + const bool project = ctx.projectionEnabled(); + for (LitVec::const_iterator it = dom->begin(), end = dom->end(); it != end; ++it) { + if (s.isTrue(*it) && (!project || ctx.project(it->var()))) { solution.push_back(~*it); } + } + solution.push_back(~s.sharedContext()->stepLiteral()); + } + if (solution.empty()) { solution.push_back(lit_false()); } + if (s.sharedContext()->concurrency() > 1) { + // parallel solving active - share solution nogood with other solvers + en.commitClause(solution); + solution.clear(); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// strategy_backtrack +///////////////////////////////////////////////////////////////////////////////////////// +class ModelEnumerator::BacktrackFinder : public ModelFinder { +public: + explicit BacktrackFinder(uint32 projOpts) : ModelFinder(), opts(projOpts) {} + // EnumerationConstraint interface + ConPtr clone() { return new BacktrackFinder(opts); } + void doCommitModel(Enumerator& ctx, Solver& s); + bool doUpdate(Solver& s); + // Constraint interface + PropResult propagate(Solver&, Literal, uint32&); + void reason(Solver& s, Literal p, LitVec& x){ + for (uint32 i = 1, end = s.level(p.var()); i <= end; ++i) { + x.push_back(s.decision(i)); + } + } + bool simplify(Solver& s, bool reinit) { + for (ProjectDB::iterator it = projNogoods.begin(), end = projNogoods.end(); it != end; ++it) { + if (it->second && it->second->simplify(s, false)) { + s.removeWatch(it->first, this); + it->second->destroy(&s, false); + it->second = 0; + } + } + while (!projNogoods.empty() && projNogoods.back().second == 0) { projNogoods.pop_back(); } + return ModelFinder::simplify(s, reinit); + } + void destroy(Solver* s, bool detach) { + while (!projNogoods.empty()) { + NogoodPair x = projNogoods.back(); + if (x.second) { + if (s) { s->removeWatch(x.first, this); } + x.second->destroy(s, detach); + } + projNogoods.pop_back(); + } + ModelFinder::destroy(s, detach); + } + typedef std::pair NogoodPair; + typedef PodVector::type ProjectDB; + ProjectDB projNogoods; + uint32 opts; +}; + +Constraint::PropResult ModelEnumerator::BacktrackFinder::propagate(Solver& s, Literal, uint32& pos) { + assert(pos < projNogoods.size() && projNogoods[pos].second != 0); + ClauseHead* c = static_cast(projNogoods[pos].second); + if (!c->locked(s)) { + c->destroy(&s, true); + projNogoods[pos].second = (c = 0); + while (!projNogoods.empty() && !projNogoods.back().second) { + projNogoods.pop_back(); + } + } + return PropResult(true, c != 0); +} +bool ModelEnumerator::BacktrackFinder::doUpdate(Solver& s) { + if (hasModel()) { + bool ok = true; + uint32 sp = (opts & ModelEnumerator::project_save_progress) != 0 ? Solver::undo_save_phases : 0; + s.undoUntil(s.backtrackLevel(), sp|Solver::undo_pop_bt_level); + ClauseRep rep = ClauseCreator::prepare(s, solution, 0, Constraint_t::Conflict); + if (rep.size == 0 || s.isFalse(rep.lits[0])) { // The decision stack is already ordered. + ok = s.backtrack(); + } + else if (rep.size == 1 || s.isFalse(rep.lits[1])) { // The projection nogood is unit. Force the single remaining literal from the current DL. + ok = s.force(rep.lits[0], this); + } + else if (!s.isTrue(rep.lits[0])) { // Shorten the projection nogood by assuming one of its literals to false. + uint32 f = static_cast(std::stable_partition(rep.lits+2, rep.lits+rep.size, std::not1(std::bind1st(std::mem_fun(&Solver::isFalse), &s))) - rep.lits); + Literal x = (opts & ModelEnumerator::project_use_heuristic) != 0 ? s.heuristic()->selectRange(s, rep.lits, rep.lits+f) : rep.lits[0]; + Constraint* c = Clause::newContractedClause(s, rep, f, true); + CLASP_FAIL_IF(!c, "Invalid constraint!"); + s.assume(~x); + // Remember that we must backtrack the current decision + // level in order to guarantee a different projected solution. + s.setBacktrackLevel(s.decisionLevel(), Solver::undo_pop_proj_level); + // Attach nogood to the current decision literal. + // Once we backtrack to x, the then obsolete nogood is destroyed + // keeping the number of projection nogoods linear in the number of (projection) atoms. + s.addWatch(x, this, (uint32)projNogoods.size()); + projNogoods.push_back(NogoodPair(x, c)); + ok = true; + } + solution.clear(); + return ok; + } + if (optimize() || s.sharedContext()->concurrency() == 1 || disjointPath()) { + return true; + } + s.setStopConflict(); + return false; +} + +void ModelEnumerator::BacktrackFinder::doCommitModel(Enumerator& ctx, Solver& s) { + ModelEnumerator& en = static_cast(ctx); + uint32 dl = s.decisionLevel(); + solution.assign(1, dl ? ~s.decision(dl) : lit_false()); + if (en.projectionEnabled()) { + // Remember the current projected assignment as a nogood. + solution.clear(); + for (Var i = 1, end = s.numProblemVars(); i <= end; ++i) { + if (en.project(i)) { + solution.push_back(~s.trueLit(i)); + } + } + // Tag solution + solution.push_back(~s.sharedContext()->stepLiteral()); + // Remember initial decisions that are projection vars. + for (dl = s.rootLevel(); dl < s.decisionLevel(); ++dl) { + if (!en.project(s.decision(dl+1).var())) { break; } + } + s.setBacktrackLevel(dl, Solver::undo_pop_proj_level); + } + else { + s.setBacktrackLevel(dl); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// class ModelEnumerator +///////////////////////////////////////////////////////////////////////////////////////// +ModelEnumerator::ModelEnumerator(Strategy st) + : Enumerator() + , options_(st) { +} + +Enumerator* EnumOptions::createModelEnumerator(const EnumOptions& opts) { + ModelEnumerator* e = new ModelEnumerator(); + ModelEnumerator::Strategy s = ModelEnumerator::strategy_auto; + if (opts.enumMode && opts.models()) { + s = opts.enumMode == enum_bt ? ModelEnumerator::strategy_backtrack : ModelEnumerator::strategy_record; + } + e->setStrategy(s, opts.project | (opts.enumMode == enum_dom_record ? ModelEnumerator::project_dom_lits : 0)); + return e; +} + +ModelEnumerator::~ModelEnumerator() {} + +void ModelEnumerator::setStrategy(Strategy st, uint32 projection, char f) { + options_ = (static_cast(f) << 24) | uint32(st) | ((projection & 15u) << 4u); + if ((projection & 7u) != 0) { + options_ |= uint32(project_enable_simple) << 4u; + } + if (st == strategy_auto) { + options_ |= detect_strategy_flag; + } +} + +EnumerationConstraint* ModelEnumerator::doInit(SharedContext& ctx, SharedMinimizeData* opt, int numModels) { + initProjection(ctx); + uint32 st = strategy(); + if (detectStrategy() || (ctx.concurrency() > 1 && !ModelEnumerator::supportsParallel())) { + st = 0; + } + bool optOne = opt && opt->mode() == MinimizeMode_t::optimize; + bool trivial = optOne || std::abs(numModels) == 1; + if (optOne && projectionEnabled()) { + for (const WeightLiteral* it = minimizer()->lits; !isSentinel(it->first) && trivial; ++it) { + trivial = project(it->first.var()); + } + if (!trivial) { ctx.warn("Projection: Optimization may depend on enumeration order."); } + } + if (st == strategy_auto) { st = trivial || (projectionEnabled() && ctx.concurrency() > 1) ? strategy_record : strategy_backtrack; } + if (trivial) { st |= trivial_flag; } + options_ &= ~uint32(strategy_opts_mask); + options_ |= st; + const LitVec* dom = (projectOpts() & project_dom_lits) != 0 ? (ctx.heuristic.domRec = &domRec_) : 0; + EnumerationConstraint* c = st == strategy_backtrack + ? static_cast(new BacktrackFinder(projectOpts())) + : static_cast(new RecordFinder(dom)); + if (projectionEnabled()) { setIgnoreSymmetric(true); } + return c; +} + +void ModelEnumerator::initProjection(SharedContext& ctx) { + project_.clear(); + if (!projectionEnabled()) { return; } + const OutputTable& out = ctx.output; + char const filter = static_cast(options_ >> 24); + if (out.projectMode() == OutputTable::project_output) { + // Mark all relevant output variables. + for (OutputTable::pred_iterator it = out.pred_begin(), end = out.pred_end(); it != end; ++it) { + if (*it->name != filter) { addProject(ctx, it->cond.var()); } + } + for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) { + addProject(ctx, *it); + } + } + else { + // Mark explicitly requested variables only. + for (OutputTable::lit_iterator it = out.proj_begin(), end = out.proj_end(); it != end; ++it) { + addProject(ctx, it->var()); + } + } + domRec_.clear(); +} + +void ModelEnumerator::addProject(SharedContext& ctx, Var v) { + const uint32 wIdx = v / 32; + const uint32 bIdx = v & 31; + if (wIdx >= project_.size()) { project_.resize(wIdx + 1, 0); } + store_set_bit(project_[wIdx], bIdx); + ctx.setFrozen(v, true); +} +bool ModelEnumerator::project(Var v) const { + const uint32 wIdx = v / 32; + const uint32 bIdx = v & 31; + return wIdx < project_.size() && test_bit(project_[wIdx], bIdx); +} + +} diff --git a/libclasp/src/parallel_solve.cpp b/libclasp/src/parallel_solve.cpp new file mode 100644 index 0000000..2621c53 --- /dev/null +++ b/libclasp/src/parallel_solve.cpp @@ -0,0 +1,1170 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#if WITH_THREADS +#include +#include +#include +#include +#include +#include +#include +namespace Clasp { namespace mt { +///////////////////////////////////////////////////////////////////////////////////////// +// BarrierSemaphore +///////////////////////////////////////////////////////////////////////////////////////// +// A combination of a barrier and a semaphore +class BarrierSemaphore { +public: + explicit BarrierSemaphore(int counter = 0, int maxParties = 1) : counter_(counter), active_(maxParties) {} + // Initializes this object + // PRE: no thread is blocked on the semaphore + // (i.e. internal counter is >= 0) + // NOTE: not thread-safe + void unsafe_init(int counter = 0, int maxParties = 1) { + counter_ = counter; + active_ = maxParties; + } + // Returns the current semaphore counter. + int counter() { lock_guard lock(semMutex_); return counter_; } + // Returns the number of parties required to trip this barrier. + int parties() { lock_guard lock(semMutex_); return active_; } + // Returns true if all parties are waiting at the barrier + bool active() { lock_guard lock(semMutex_); return unsafe_active(); } + + // barrier interface + + // Increases the barrier count, i.e. the number of + // parties required to trip this barrier. + void addParty() { + lock_guard lock(semMutex_); + ++active_; + } + // Decreases the barrier count and resets the barrier + // if reset is true. + // PRE: the thread does not itself wait on the barrier + void removeParty(bool reset) { + unique_lock lock(semMutex_); + assert(active_ > 0); + --active_; + if (reset) { unsafe_reset(0); } + else if (unsafe_active()) { counter_ = -active_; lock.unlock(); semCond_.notify_one(); } + } + // Waits until all parties have arrived, i.e. called wait. + // Exactly one of the parties will receive a return value of true, + // the others will receive a value of false. + // Applications shall use this value to designate one thread as the + // leader that will eventually reset the barrier thereby unblocking the other threads. + bool wait() { + unique_lock lock(semMutex_); + if (--counter_ >= 0) { counter_ = -1; } + return unsafe_wait(lock); + } + // Resets the barrier and unblocks any waiting threads. + void reset(uint32 semCount = 0) { + lock_guard lock(semMutex_); + unsafe_reset(semCount); + } + // semaphore interface + + // Decrement the semaphore's counter. + // If the counter is zero or less prior to the call + // the calling thread is suspended. + // Returns false to signal that all but the calling thread + // are currently blocked. + bool down() { + unique_lock lock(semMutex_); + return down(lock); + } + // LOW-LEVEL version of down + bool down(unique_lock& m) { + assert(m.owns_lock()); + if (--counter_ >= 0) { return true; } + return !unsafe_wait(m); + } + // Increments the semaphore's counter and resumes + // one thread which has called down() if the counter + // was less than zero prior to the call. + void up() { + unique_lock lock(semMutex_); + up(lock); + } + // LOW-LEVEL version of up + void up(unique_lock& m, bool transferLock = true) { + assert(m.owns_lock()); + if (++counter_ < 1) { + if (transferLock) { m.unlock(); } + semCond_.notify_one(); + } + } + mutex& toMutex() { return semMutex_; } +private: + BarrierSemaphore(const BarrierSemaphore&); + BarrierSemaphore& operator=(const BarrierSemaphore&); + typedef condition_variable cv; + bool unsafe_active() const { return -counter_ >= active_; } + void unsafe_reset(uint32 semCount) { + int prev = counter_; + counter_ = semCount; + if (prev < 0) { semCond_.notify_all(); } + } + // Returns true for the leader, else false + bool unsafe_wait(unique_lock& lock) { + assert(counter_ < 0); + // don't put the last thread to sleep! + if (!unsafe_active()) { + semCond_.wait(lock); + } + return unsafe_active(); + } + cv semCond_; // waiting threads + mutex semMutex_; // mutex for updating counter + int counter_; // semaphore's counter + int active_; // number of active threads +}; +///////////////////////////////////////////////////////////////////////////////////////// +// ParallelSolve::Impl +///////////////////////////////////////////////////////////////////////////////////////// +struct ParallelSolve::SharedData { + typedef PodQueue Queue; + enum MsgFlag { + terminate_flag = 1u, sync_flag = 2u, split_flag = 4u, + restart_flag = 8u, complete_flag = 16u, + interrupt_flag = 32u, // set on terminate from outside + allow_split_flag = 64u, // set if splitting mode is active + forbid_restart_flag = 128u,// set if restarts are no longer allowed + cancel_restart_flag = 256u,// set if current restart request was cancelled by some thread + restart_abandoned_flag= 512u,// set to signal that threads must not give up their gp + }; + enum Message { + msg_terminate = (terminate_flag), + msg_interrupt = (terminate_flag | interrupt_flag), + msg_sync_restart = (sync_flag | restart_flag), + msg_split = split_flag + }; + struct Generator { + enum State { start = 0, search = 1, model = 2, done = 3 }; + Generator() : state(start) {} + mutex genM; + condition_variable cond; + State waitWhile(State st) { + State r; + for (unique_lock lock(genM); (r = state) == st;) { cond.wait(lock); } + return r; + } + void pushModel() { + notify(model); + waitWhile(model); + } + void notify(State st) { + unique_lock lock(genM); + state = st; + cond.notify_one(); + } + State state; + }; + SharedData() : path(0) { reset(0); control = 0; } + void reset(SharedContext* a_ctx) { + clearQueue(); + syncT.reset(); + workSem.unsafe_init(0, a_ctx ? a_ctx->concurrency() : 0); + globalR.reset(); + maxConflict = globalR.current(); + error = 0; + initVec = 0; + ctx = a_ctx; + path = 0; + nextId = 1; + workReq = 0; + restartReq = 0; + generator = 0; + } + void clearQueue() { + while (!workQ.empty()) { delete workQ.pop_ret(); } + workQ.clear(); + } + const LitVec* requestWork(const Solver& s) { + const uint64 m(uint64(1) << s.id()); + if ((initVec & m) == m) { + if (!allowSplit()) { + // portfolio mode - all solvers can start with initial path + initVec -= m; + return path; + } + else if (initVec.fetch_and_store(0) != 0) { + // splitting mode - only one solver must start with initial path + return path; + } + } + if (!allowSplit()) { return 0; } + // try to get work from split + ctx->report(MessageEvent(s, "SPLIT", MessageEvent::sent)); + const uint32 flags = uint32(terminate_flag) | uint32(sync_flag); + for (unique_lock lock(workSem.toMutex());;) { + if (!workQ.empty()) { + const LitVec* res = workQ.pop_ret(); + if (workQ.empty()) { workQ.clear(); } + return res; + } + postMessage(SharedData::msg_split, false); + if (!workSem.down(lock) || hasControl(flags)) { + return 0; + } + } + } + void pushWork(const LitVec* v) { + unique_lock lock(workSem.toMutex()); + workQ.push(v); + workSem.up(lock); + } + // MESSAGES + bool postMessage(Message m, bool notify); + bool hasMessage() const { return (control & uint32(7)) != 0; } + bool synchronize() const { return (control & uint32(sync_flag)) != 0; } + bool terminate() const { return (control & uint32(terminate_flag)) != 0; } + bool split() const { return (control & uint32(split_flag)) != 0; } + void aboutToSplit() { if (--workReq == 0) updateSplitFlag(); } + void updateSplitFlag(); + // CONTROL FLAGS + bool hasControl(uint32 f) const { return (control & f) != 0; } + bool interrupt() const { return hasControl(interrupt_flag);} + bool complete() const { return hasControl(complete_flag); } + bool restart() const { return hasControl(restart_flag); } + bool allowSplit() const { return hasControl(allow_split_flag); } + bool allowRestart() const { return !hasControl(forbid_restart_flag); } + bool setControl(uint32 flags) { return (control.fetch_and_or(flags) & flags) != flags; } + bool clearControl(uint32 flags) { return (control.fetch_and_and(~flags) & flags) == flags; } + typedef SingleOwnerPtr GeneratorPtr; + ScheduleStrategy globalR; // global restart strategy + uint64 maxConflict; // current restart limit + uint64 error; // bitmask of erroneous solvers + SharedContext* ctx; // shared context object + const LitVec* path; // initial guiding path - typically empty + atomic initVec; // vector of initial gp - represented as bitset + GeneratorPtr generator; // optional data for model generation + Timer syncT; // thread sync time + mutex modelM; // model-mutex + BarrierSemaphore workSem; // work-semaphore + Queue workQ; // work-queue (must be protected by workSem) + uint32 nextId; // next solver id to use + LowerBound lower_; // last reported lower bound (if any) + atomic workReq; // > 0: someone needs work + atomic restartReq; // == numThreads(): restart + atomic control; // set of active message flags + atomic modCount; // coounter for synchronizing models +}; + +// post message to all threads +bool ParallelSolve::SharedData::postMessage(Message m, bool notifyWaiting) { + if (m == msg_split) { + if (++workReq == 1) { updateSplitFlag(); } + return true; + } + else if (setControl(m)) { + // control message - notify all if requested + if (notifyWaiting) workSem.reset(); + if ((uint32(m) & uint32(sync_flag|terminate_flag)) != 0) { + syncT.reset(); + syncT.start(); + } + return true; + } + return false; +} + +void ParallelSolve::SharedData::updateSplitFlag() { + for (bool splitF;;) { + splitF = (workReq > 0); + if (split() == splitF) return; + if (splitF) control.fetch_and_or(uint32(split_flag)); + else control.fetch_and_and(~uint32(split_flag)); + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// ParallelSolve +///////////////////////////////////////////////////////////////////////////////////////// +ParallelSolve::ParallelSolve(const ParallelSolveOptions& opts) + : SolveAlgorithm(opts.limit) + , shared_(new SharedData) + , thread_(0) + , distribution_(opts.distribute) + , maxRestarts_(0) + , intGrace_(1024) + , intTopo_(opts.integrate.topo) + , intFlags_(ClauseCreator::clause_not_root_sat | ClauseCreator::clause_no_add) + , modeSplit_(opts.algorithm.mode == ParallelSolveOptions::Algorithm::mode_split) { + setRestarts(opts.restarts.maxR, opts.restarts.sched); + setIntegrate(opts.integrate.grace, opts.integrate.filter); +} + +ParallelSolve::~ParallelSolve() { + if (shared_->nextId > 1) { + // algorithm was not started but there may be active threads - + // force orderly shutdown + ParallelSolve::doInterrupt(); + shared_->workSem.removeParty(true); + joinThreads(); + } + destroyThread(masterId); + delete shared_; +} + +bool ParallelSolve::beginSolve(SharedContext& ctx, const LitVec& path) { + assert(ctx.concurrency() && "Illegal number of threads"); + if (shared_->terminate()) { return false; } + shared_->reset(&ctx); + if (!enumerator().supportsParallel() && numThreads() > 1) { + ctx.warn("Selected reasoning mode implies #Threads=1."); + shared_->workSem.unsafe_init(1); + modeSplit_ = false; + ctx.setConcurrency(1, SharedContext::resize_reserve); + } + shared_->setControl(modeSplit_ ? SharedData::allow_split_flag : SharedData::forbid_restart_flag); + shared_->modCount = uint32(enumerator().optimize()); + shared_->path = &path; + if (distribution_.types != 0 && ctx.distributor.get() == 0 && numThreads() > 1) { + if (distribution_.mode == ParallelSolveOptions::Distribution::mode_local) { + ctx.distributor.reset(new mt::LocalDistribution(distribution_, ctx.concurrency(), intTopo_)); + } + else { + ctx.distributor.reset(new mt::GlobalDistribution(distribution_, ctx.concurrency(), intTopo_)); + } + } + shared_->setControl(SharedData::sync_flag); // force initial sync with all threads + shared_->syncT.start(); + reportProgress(MessageEvent(*ctx.master(), "SYNC", MessageEvent::sent)); + assert(ctx.master()->id() == masterId); + allocThread(masterId, *ctx.master(), ctx.configuration()->search(masterId)); + for (uint32 i = 1; i != ctx.concurrency(); ++i) { + uint32 id = shared_->nextId++; + allocThread(id, *ctx.solver(id), ctx.configuration()->search(id)); + // start in new thread + Clasp::mt::thread x(std::mem_fun(&ParallelSolve::solveParallel), this, id); + thread_[id]->setThread(x); + } + return true; +} + +void ParallelSolve::setIntegrate(uint32 grace, uint8 filter) { + typedef ParallelSolveOptions::Integration Dist; + intGrace_ = grace; + intFlags_ = ClauseCreator::clause_no_add; + if (filter == Dist::filter_heuristic) { store_set_bit(intFlags_, 31); } + if (filter != Dist::filter_no) { intFlags_ |= ClauseCreator::clause_not_root_sat; } + if (filter == Dist::filter_sat) { intFlags_ |= ClauseCreator::clause_not_sat; } +} + +void ParallelSolve::setRestarts(uint32 maxR, const ScheduleStrategy& rs) { + maxRestarts_ = maxR; + shared_->globalR = maxR ? rs : ScheduleStrategy::none(); + shared_->maxConflict = shared_->globalR.current(); +} + +uint32 ParallelSolve::numThreads() const { return shared_->workSem.parties(); } + +void ParallelSolve::allocThread(uint32 id, Solver& s, const SolveParams& p) { + if (!thread_) { + uint32 n = numThreads(); + thread_ = new ParallelHandler*[n]; + std::fill(thread_, thread_+n, static_cast(0)); + } + size_t sz = ((sizeof(ParallelHandler)+63) / 64) * 64; + thread_[id] = new (alignedAlloc(sz, 64)) ParallelHandler(*this, s, p); +} + +void ParallelSolve::destroyThread(uint32 id) { + if (thread_ && thread_[id]) { + assert(!thread_[id]->joinable() && "Shutdown not completed!"); + thread_[id]->~ParallelHandler(); + alignedFree(thread_[id]); + thread_[id] = 0; + if (id == masterId) { + delete [] thread_; + thread_ = 0; + } + } +} + +inline void ParallelSolve::reportProgress(const Event& ev) const { + return shared_->ctx->report(ev); +} +inline void ParallelSolve::reportProgress(const Solver& s, const char* msg) const { + return shared_->ctx->report(msg, &s); +} + +// joins with and destroys all active threads +void ParallelSolve::joinThreads() { + int ec = thread_[masterId]->error(); + uint32 winner = thread_[masterId]->winner() ? uint32(masterId) : UINT32_MAX; + shared_->error= ec ? 1 : 0; + for (uint32 i = 1, end = shared_->nextId; i != end; ++i) { + if (thread_[i]->join() != 0) { + shared_->error |= uint64(1) << i; + ec = std::max(ec, thread_[i]->error()); + } + if (thread_[i]->winner() && i < winner) { + winner = i; + } + Solver* s = &thread_[i]->solver(); + reportProgress(*s, "joined"); + destroyThread(i); + reportProgress(*s, "destroyed"); + } + if (shared_->complete()) { + enumerator().commitComplete(); + } + // detach master only after all client threads are done + thread_[masterId]->detach(*shared_->ctx, shared_->interrupt()); + thread_[masterId]->setError(!shared_->interrupt() ? thread_[masterId]->error() : ec); + shared_->ctx->setWinner(winner); + shared_->nextId = 1; + shared_->syncT.stop(); + reportProgress(MessageEvent(*shared_->ctx->master(), "TERMINATE", MessageEvent::completed, shared_->syncT.total())); +} + +void ParallelSolve::doStart(SharedContext& ctx, const LitVec& assume) { + if (beginSolve(ctx, assume)) { + // start computation in new thread + shared_->generator = new SharedData::Generator(); + Clasp::mt::thread x(std::mem_fun(&ParallelSolve::solveParallel), this, static_cast(masterId)); + thread_[masterId]->setThread(x); + } +} +int ParallelSolve::doNext(int) { + CLASP_FAIL_IF(!shared_->generator.get(), "Invalid operation"); + int s = shared_->generator->state; + if (s != SharedData::Generator::done) { + shared_->generator->notify(SharedData::Generator::search); + if ((s = shared_->generator->waitWhile(SharedData::Generator::search)) == SharedData::Generator::model) { + return value_true; + } + } + return shared_->complete() ? value_false : value_free; +} +void ParallelSolve::doStop() { + if (shared_->nextId <= 1) { return; } + reportProgress(*shared_->ctx->master(), "joining with other threads"); + if (shared_->generator.get()) { + shared_->setControl(SharedData::terminate_flag); + shared_->generator->notify(SharedData::Generator::done); + thread_[masterId]->join(); + } + joinThreads(); + int err = thread_[masterId]->error(); + destroyThread(masterId); + shared_->generator = 0; + shared_->ctx->distributor.reset(0); + switch(err) { + case error_none : break; + case error_oom : throw std::bad_alloc(); + case error_runtime: throw std::runtime_error("RUNTIME ERROR!"); + default: throw std::runtime_error("UNKNOWN ERROR!"); + } +} + +// Entry point for master solver +bool ParallelSolve::doSolve(SharedContext& ctx, const LitVec& path) { + if (beginSolve(ctx, path)) { + solveParallel(masterId); + ParallelSolve::doStop(); + } + return !shared_->complete(); +} + +// main solve loop executed by all threads +void ParallelSolve::solveParallel(uint32 id) { + Solver& s = thread_[id]->solver(); + const SolveParams& p= thread_[id]->params(); + SolverStats agg; + PathPtr a(0); + if (id == masterId && shared_->generator.get()) { + shared_->generator->waitWhile(SharedData::Generator::start); + } + try { + // establish solver<->handler connection and attach to shared context + // should this fail because of an initial conflict, we'll terminate + // in requestWork. + thread_[id]->attach(*shared_->ctx); + BasicSolve solve(s, p, limits()); + agg.enable(s.stats); + for (GpType t; requestWork(s, a); solve.reset()) { + agg.accu(s.stats); + s.stats.reset(); + thread_[id]->setGpType(t = ((a.is_owner() || modeSplit_) ? gp_split : gp_fixed)); + if (enumerator().start(s, *a, a.is_owner()) && thread_[id]->solveGP(solve, t, shared_->maxConflict) == value_free) { + terminate(s, false); + } + s.clearStopConflict(); + s.undoUntil(0); + enumerator().end(s); + } + } + catch (const std::bad_alloc&) { exception(id,a,error_oom, "ERROR: std::bad_alloc" ); } + catch (const std::exception& e){ exception(id,a,error_runtime, e.what()); } + catch (...) { exception(id,a,error_other, "ERROR: unknown"); } + assert(shared_->terminate() || thread_[id]->error() != error_none); + // this thread is leaving + shared_->workSem.removeParty(shared_->terminate()); + // update stats + s.stats.accu(agg); + if (id != masterId) { + // remove solver<->handler connection and detach from shared context + // note: since detach can change the problem, we must not yet detach the master + // because some client might still be in the middle of an attach operation + thread_[id]->detach(*shared_->ctx, shared_->interrupt()); + s.stats.addCpuTime(ThreadTime::getTime()); + } + else if (shared_->generator.get()) { + shared_->generator->notify(SharedData::Generator::done); + } +} + +void ParallelSolve::exception(uint32 id, PathPtr& path, ErrorCode e, const char* what) { + try { + reportProgress(thread_[id]->solver(), what); + thread_[id]->setError(e); + if (id == masterId || shared_->workSem.active()) { + ParallelSolve::doInterrupt(); + return; + } + else if (path.get() && shared_->allowSplit()) { + shared_->workQ.push(path.release()); + shared_->workSem.up(); + } + reportProgress(thread_[id]->solver(), "Thread failed and was removed."); + } + catch(...) { ParallelSolve::doInterrupt(); } +} + +// forced termination from outside +bool ParallelSolve::doInterrupt() { + // do not notify blocked threads to avoid possible + // deadlock in semaphore! + shared_->postMessage(SharedData::msg_interrupt, false); + return true; +} + +// tries to get new work for the given solver +bool ParallelSolve::requestWork(Solver& s, PathPtr& out) { + const LitVec* a = 0; + for (int popped = 0; !shared_->terminate();) { + // only clear path and stop conflict - we don't propagate() here + // because we would then have to handle any eventual conflicts + if (++popped == 1 && !s.popRootLevel(s.rootLevel())) { + // s has a real top-level conflict - problem is unsat + terminate(s, true); + } + else if (shared_->synchronize()) { + // a synchronize request is active - we are fine with + // this but did not yet had a chance to react on it + waitOnSync(s); + } + else if (a || (a = shared_->requestWork(s)) != 0) { + assert(s.decisionLevel() == 0); + // got new work from work-queue + out = a; + // do not take over ownership of initial gp! + if (a == shared_->path) { out.release(); } + // propagate any new facts before starting new work + if (s.simplify()) { return true; } + // s now has a conflict - either an artifical stop conflict + // or a real conflict - we'll handle it in the next iteration + // via the call to popRootLevel() + popped = 0; + } + else if (!shared_->allowSplit() || !shared_->synchronize()) { + // no work left - quitting time? + terminate(s, true); + } + } + return false; +} + +// terminated from inside of algorithm +// check if there is more to do +void ParallelSolve::terminate(Solver& s, bool complete) { + if (!shared_->terminate()) { + if (enumerator().tentative() && complete) { + if (shared_->setControl(SharedData::sync_flag|SharedData::complete_flag)) { + thread_[s.id()]->setWinner(); + reportProgress(MessageEvent(s, "SYNC", MessageEvent::sent)); + } + } + else { + reportProgress(MessageEvent(s, "TERMINATE", MessageEvent::sent)); + shared_->postMessage(SharedData::msg_terminate, true); + thread_[s.id()]->setWinner(); + if (complete) { shared_->setControl(SharedData::complete_flag); } + } + } +} + +// handles an active synchronization request +// returns true to signal that s should restart otherwise false +bool ParallelSolve::waitOnSync(Solver& s) { + if (!thread_[s.id()]->handleRestartMessage()) { + shared_->setControl(SharedData::cancel_restart_flag); + } + bool hasPath = thread_[s.id()]->hasPath(); + bool tentative= enumerator().tentative(); + if (shared_->workSem.wait()) { + // last man standing - complete synchronization request + shared_->workReq = 0; + shared_->restartReq = 0; + bool restart = shared_->hasControl(SharedData::restart_flag); + bool init = true; + if (restart) { + init = shared_->allowRestart() && !shared_->hasControl(SharedData::cancel_restart_flag); + if (init) { shared_->globalR.next(); } + shared_->maxConflict = shared_->allowRestart() && shared_->globalR.idx < maxRestarts_ + ? shared_->globalR.current() + : UINT64_MAX; + } + else if (shared_->maxConflict != UINT64_MAX && !shared_->allowRestart()) { + shared_->maxConflict = UINT64_MAX; + } + if (init) { initQueue(); } + else { shared_->setControl(SharedData::restart_abandoned_flag); } + if (tentative && shared_->complete()) { + if (enumerator().commitComplete()) { shared_->setControl(SharedData::terminate_flag); } + else { shared_->modCount = uint32(0); shared_->clearControl(SharedData::complete_flag); } + } + shared_->clearControl(SharedData::msg_split | SharedData::msg_sync_restart | SharedData::restart_abandoned_flag | SharedData::cancel_restart_flag); + shared_->syncT.lap(); + reportProgress(MessageEvent(s, "SYNC", MessageEvent::completed, shared_->syncT.elapsed())); + // wake up all blocked threads + shared_->workSem.reset(); + } + return shared_->terminate() || (hasPath && !shared_->hasControl(SharedData::restart_abandoned_flag)); +} + +// If guiding path scheme is active only one +// thread can start with gp (typically empty) and this +// thread must then split up search-space dynamically. +// Otherwise, all threads can start with initial gp +// TODO: +// heuristic for initial splits? +void ParallelSolve::initQueue() { + shared_->clearQueue(); + if (shared_->allowSplit() && modeSplit_ && !enumerator().supportsSplitting(*shared_->ctx)) { + shared_->ctx->warn("Selected strategies imply Mode=compete."); + shared_->clearControl(SharedData::allow_split_flag); + shared_->setControl(SharedData::forbid_restart_flag); + modeSplit_ = false; + } + shared_->initVec = UINT64_MAX; + assert(shared_->allowSplit() || shared_->hasControl(SharedData::forbid_restart_flag)); +} + +// adds work to the work-queue +void ParallelSolve::pushWork(LitVec* v) { + assert(v); + shared_->pushWork(v); +} + +// called whenever some solver proved unsat +bool ParallelSolve::commitUnsat(Solver& s) { + const int supUnsat = enumerator().unsatType(); + if (supUnsat == Enumerator::unsat_stop || shared_->terminate() || shared_->synchronize()) { + return false; + } + unique_lock lock(shared_->modelM, defer_lock_t()); + if (supUnsat == Enumerator::unsat_sync) { + lock.lock(); + } + bool result = enumerator().commitUnsat(s); + if (lock.owns_lock()) { + lock.unlock(); + } + if (!thread_[s.id()]->disjointPath()) { + if (result) { + ++shared_->modCount; + if (s.lower.bound > 0) { + lock.lock(); + if (s.lower.bound > shared_->lower_.bound || s.lower.level > shared_->lower_.level) { + shared_->lower_ = s.lower; + reportUnsat(s); + } + lock.unlock(); + } + } + else { terminate(s, true); } + } + return result; +} + +// called whenever some solver has found a model +bool ParallelSolve::commitModel(Solver& s) { + // grab lock - models must be processed sequentially + // in order to simplify printing and to avoid duplicates + // in all non-trivial enumeration modes + bool stop = false; + {lock_guard lock(shared_->modelM); + // first check if the model is still valid once all + // information is integrated into the solver + if (thread_[s.id()]->isModel(s) && (stop=shared_->terminate()) == false && enumerator().commitModel(s)) { + if (enumerator().lastModel().num == 1 && !enumerator().supportsRestarts()) { + // switch to backtracking based splitting algorithm + // the solver's gp will act as the root for splitting and is + // from now on disjoint from all other gps + shared_->setControl(SharedData::forbid_restart_flag | SharedData::allow_split_flag); + thread_[s.id()]->setGpType(gp_split); + enumerator().setDisjoint(s, true); + } + ++shared_->modCount; + if (shared_->generator.get()) { + shared_->generator->pushModel(); + } + else if ((stop = !reportModel(s)) == true) { + // must be called while holding the lock - otherwise + // we have a race condition with solvers that + // are currently blocking on the mutex and we could enumerate + // more models than requested by the user + terminate(s, !moreModels(s)); + } + }} + return !stop; +} + +uint64 ParallelSolve::hasErrors() const { + return shared_->error; +} +bool ParallelSolve::interrupted() const { + return shared_->interrupt(); +} +void ParallelSolve::resetSolve() { + shared_->control = 0; +} +void ParallelSolve::enableInterrupts() {} +// updates s with new messages and uses s to create a new guiding path +// if necessary and possible +bool ParallelSolve::handleMessages(Solver& s) { + // check if there are new messages for s + if (!shared_->hasMessage()) { + // nothing to do + return true; + } + ParallelHandler* h = thread_[s.id()]; + if (shared_->terminate()) { + reportProgress(MessageEvent(s, "TERMINATE", MessageEvent::received)); + h->handleTerminateMessage(); + s.setStopConflict(); + return false; + } + if (shared_->synchronize()) { + reportProgress(MessageEvent(s, "SYNC", MessageEvent::received)); + if (waitOnSync(s)) { + s.setStopConflict(); + return false; + } + return true; + } + if (h->disjointPath() && s.splittable() && shared_->workReq > 0) { + // First declare split request as handled + // and only then do the actual split. + // This way, we minimize the chance for + // "over"-splitting, i.e. one split request handled + // by more than one thread. + shared_->aboutToSplit(); + reportProgress(MessageEvent(s, "SPLIT", MessageEvent::received)); + h->handleSplitMessage(); + enumerator().setDisjoint(s, true); + } + return true; +} + +bool ParallelSolve::integrateModels(Solver& s, uint32& upCount) { + uint32 gCount = shared_->modCount; + return gCount == upCount || (enumerator().update(s) && (upCount = gCount) == gCount); +} + +void ParallelSolve::requestRestart() { + if (shared_->allowRestart() && ++shared_->restartReq == numThreads()) { + shared_->postMessage(SharedData::msg_sync_restart, true); + } +} + +SolveAlgorithm* ParallelSolveOptions::createSolveObject() const { + return numSolver() > 1 ? new ParallelSolve(*this) : BasicSolveOptions::createSolveObject(); +} +//////////////////////////////////////////////////////////////////////////////////// +// ParallelHandler +///////////////////////////////////////////////////////////////////////////////////////// +ParallelHandler::ParallelHandler(ParallelSolve& ctrl, Solver& s, const SolveParams& p) + : MessageHandler() + , ctrl_(&ctrl) + , solver_(&s) + , params_(&p) + , received_(0) + , recEnd_(0) + , intEnd_(0) + , error_(0) + , win_(0) + , up_(0) { + this->next = this; +} + +ParallelHandler::~ParallelHandler() { clearDB(0); delete [] received_; } + +// adds this as post propagator to its solver and attaches the solver to ctx. +bool ParallelHandler::attach(SharedContext& ctx) { + assert(solver_ && params_); + gp_.reset(); + error_ = 0; + win_ = 0; + up_ = 0; + act_ = 0; + next = 0; + if (!received_ && ctx.distributor.get()) { + received_ = new SharedLiterals*[RECEIVE_BUFFER_SIZE]; + } + ctx.report("attach", solver_); + solver_->addPost(this); + return ctx.attach(solver_->id()); +} + +// removes this from the list of post propagators of its solver and detaches the solver from ctx. +void ParallelHandler::detach(SharedContext& ctx, bool) { + handleTerminateMessage(); + ctx.report("detach", solver_); + if (solver_->sharedContext() == &ctx) { + clearDB(!error() ? solver_ : 0); + ctx.report("detached db", solver_); + ctx.detach(*solver_, error() != 0); + ctx.report("detached ctx", solver_); + } +} + +void ParallelHandler::clearDB(Solver* s) { + for (ClauseDB::iterator it = integrated_.begin(), end = integrated_.end(); it != end; ++it) { + ClauseHead* c = static_cast(*it); + if (s) { s->addLearnt(c, c->size(), Constraint_t::Other); } + else { c->destroy(); } + } + integrated_.clear(); + intEnd_= 0; + for (uint32 i = 0; i != recEnd_; ++i) { received_[i]->release(); } + recEnd_= 0; +} + +ValueRep ParallelHandler::solveGP(BasicSolve& solve, GpType t, uint64 restart) { + ValueRep res = value_free; + bool term= false; + Solver& s = solve.solver(); + gp_.reset(restart, t); + assert(act_ == 0); + do { + ctrl_->integrateModels(s, gp_.modCount); + up_ = act_ = 1; // activate enumerator and bounds + res = solve.solve(); + up_ = act_ = 0; // de-activate enumerator and bounds + if (res == value_true) { term = !ctrl_->commitModel(s); } + else if (res == value_false) { term = !ctrl_->commitUnsat(s); solve.reset(term); gp_.reset(restart, gp_.type); } + } while (!term && res != value_free); + return res; +} + +// detach from solver, i.e. ignore any further messages +void ParallelHandler::handleTerminateMessage() { + if (this->next != this) { + // mark removed propagator by creating "self-loop" + solver_->removePost(this); + this->next = this; + } +} + +// split-off new guiding path and add it to solve object +void ParallelHandler::handleSplitMessage() { + assert(solver_ && "ParallelHandler::handleSplitMessage(): not attached!"); + assert(solver_->splittable()); + Solver& s = *solver_; + SingleOwnerPtr newPath(new LitVec()); + s.split(*newPath); + ctrl_->pushWork(newPath.release()); +} + +bool ParallelHandler::handleRestartMessage() { + // TODO + // we may want to implement some heuristic, like + // computing a local var order. + return true; +} + +bool ParallelHandler::simplify(Solver& s, bool sh) { + ClauseDB::size_type i, j, end = integrated_.size(); + for (i = j = 0; i != end; ++i) { + Constraint* c = integrated_[i]; + if (c->simplify(s, sh)) { + c->destroy(&s, false); + intEnd_ -= (i < intEnd_); + } + else { + integrated_[j++] = c; + } + } + shrinkVecTo(integrated_, j); + if (intEnd_ > sizeVec(integrated_)) intEnd_ = sizeVec(integrated_); + return false; +} + +bool ParallelHandler::propagateFixpoint(Solver& s, PostPropagator* ctx) { + // Check for messages and integrate any new information from + // models/lemma exchange but only if path is setup. + // Skip updates if called from other post propagator so that we do not + // disturb any active propagation. + if (int up = (ctx == 0 && up_ != 0)) { + up_ ^= (uint32)s.updateMode(); + up += (act_ == 0 || (up_ && (s.stats.choices & 63) != 0)); + if (s.stats.conflicts >= gp_.restart) { ctrl_->requestRestart(); gp_.restart *= 2; } + for (uint32 cDL = s.decisionLevel();;) { + bool ok = ctrl_->handleMessages(s) && (up > 1 ? integrate(s) : ctrl_->integrateModels(s, gp_.modCount)); + if (!ok) { return false; } + if (cDL != s.decisionLevel()) { // cancel active propagation on cDL + cancelPropagation(); + cDL = s.decisionLevel(); + } + if (!s.queueSize()) { if (++up == 3) return true; } + else if (!s.propagateUntil(this)){ return false; } + } + } + return ctrl_->handleMessages(s); +} + +// checks whether s still has a model once all +// information from previously found models were integrated +bool ParallelHandler::isModel(Solver& s) { + assert(s.numFreeVars() == 0); + // either no unprocessed updates or still a model after + // updates were integrated + return ctrl_->integrateModels(s, gp_.modCount) + && s.numFreeVars() == 0 + && s.queueSize() == 0; +} +bool ParallelHandler::integrate(Solver& s) { + uint32 rec = recEnd_ + s.receive(received_ + recEnd_, RECEIVE_BUFFER_SIZE - recEnd_); + if (!rec) { return true; } + ClauseCreator::Result ret; + uint32 dl = s.decisionLevel(), added = 0, i = 0; + uint32 intFlags = ctrl_->integrateFlags(); + recEnd_ = 0; + if (params_->reduce.strategy.glue != 0) { + intFlags |= ClauseCreator::clause_int_lbd; + } + do { + ret = ClauseCreator::integrate(s, received_[i++], intFlags, Constraint_t::Other); + added += ret.status != ClauseCreator::status_subsumed; + if (ret.local) { add(ret.local); } + if (ret.unit()){ s.stats.addIntegratedAsserting(dl, s.decisionLevel()); dl = s.decisionLevel(); } + if (!ret.ok()) { while (i != rec) { received_[recEnd_++] = received_[i++]; } } + } while (i != rec); + s.stats.addIntegrated(added); + return !s.hasConflict(); +} + +void ParallelHandler::add(ClauseHead* h) { + if (intEnd_ < integrated_.size()) { + ClauseHead* o = (ClauseHead*)integrated_[intEnd_]; + integrated_[intEnd_] = h; + assert(o); + if (!ctrl_->integrateUseHeuristic() || o->locked(*solver_) || o->activity().activity() > 0) { + solver_->addLearnt(o, o->size(), Constraint_t::Other); + } + else { + o->destroy(solver_, true); + solver_->stats.removeIntegrated(); + } + } + else { + integrated_.push_back(h); + } + if (++intEnd_ >= ctrl_->integrateGrace()) { + intEnd_ = 0; + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// Distribution +///////////////////////////////////////////////////////////////////////////////////////// +uint64 ParallelSolveOptions::initPeerMask(uint32 id, Integration::Topology topo, uint32 maxT) { + if (topo == Integration::topo_all) { return Distributor::initSet(maxT) ^ Distributor::mask(id); } + if (topo == Integration::topo_ring){ + uint32 prev = id > 0 ? id - 1 : maxT - 1; + uint32 next = (id + 1) % maxT; + return Distributor::mask(prev) | Distributor::mask(next); + } + bool ext = topo == Integration::topo_cubex; + uint32 n = maxT; + uint32 k = 1; + for (uint32 i = n / 2; i > 0; i /= 2, k *= 2) { } + uint64 res = 0, x = 1; + for (uint32 m = 1; m <= k; m *= 2) { + uint32 i = m ^ id; + if (i < n) { res |= (x << i); } + else if (ext && k != m) { res |= (x << (i^k)); } + } + if (ext) { + uint32 s = k ^ id; + for(uint32 m = 1; m < k && s >= n; m *= 2) { + uint32 i = m ^ s; + if (i < n) { res |= (x << i); } + } + } + assert( (res & (x<(topo); + queue_ = new Queue(maxT); + threadId_ = (ThreadInfo*)alignedAlloc((maxT * sizeof(ThreadInfo)), 64); + for (uint32 i = 0; i != maxT; ++i) { + new (&threadId_[i]) ThreadInfo; + threadId_[i].id = queue_->addThread(); + threadId_[i].peerMask = ParallelSolveOptions::initPeerMask(i, t, maxT); + } +} +GlobalDistribution::~GlobalDistribution() { + static_assert(sizeof(ThreadInfo) == 64, "Invalid size"); + release(); +} +void GlobalDistribution::release() { + if (queue_) { + for (uint32 i = 0; i != queue_->maxThreads(); ++i) { + Queue::ThreadId& id = getThreadId(i); + for (ClausePair n; queue_->tryConsume(id, n); ) { + if (n.sender != i) { n.lits->release(); } + } + threadId_[i].~ThreadInfo(); + } + delete queue_; + queue_ = 0; + alignedFree(threadId_); + } +} +void GlobalDistribution::publish(const Solver& s, SharedLiterals* n) { + assert(n->refCount() >= (queue_->maxThreads()-1)); + queue_->publish(ClausePair(s.id(), n), getThreadId(s.id())); +} +uint32 GlobalDistribution::receive(const Solver& in, SharedLiterals** out, uint32 maxn) { + uint32 r = 0; + Queue::ThreadId& id = getThreadId(in.id()); + uint64 peers = getPeerMask(in.id()); + for (ClausePair n; r != maxn && queue_->tryConsume(id, n); ) { + if (n.sender != in.id()) { + if (inSet(peers, n.sender)) { out[r++] = n.lits; } + else if (n.lits->size() == 1){ out[r++] = n.lits; } + else { n.lits->release(); } + } + } + return r; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// LocalDistribution +///////////////////////////////////////////////////////////////////////////////////////// +LocalDistribution::LocalDistribution(const Policy& p, uint32 maxT, uint32 topo) : Distributor(p), thread_(0), numThread_(0) { + typedef ParallelSolveOptions::Integration::Topology Topology; + assert(maxT <= ParallelSolveOptions::supportedSolvers()); + Topology t = static_cast(topo); + thread_ = new ThreadData*[numThread_ = maxT]; + size_t sz = ((sizeof(ThreadData) + 63) / 64) * 64; + for (uint32 i = 0; i != maxT; ++i) { + ThreadData* ti = new (alignedAlloc(sz, 64)) ThreadData; + ti->received.init(&ti->sentinal); + ti->peers = ParallelSolveOptions::initPeerMask(i, t, maxT); + ti->free = 0; + thread_[i]= ti; + } +} +LocalDistribution::~LocalDistribution() { + while (numThread_) { + ThreadData* ti = thread_[--numThread_]; + thread_[numThread_] = 0; + for (QNode* n; (n = ti->received.pop()) != 0; ) { + static_cast(n->data)->release(); + } + ti->~ThreadData(); + alignedFree(ti); + } + for (MPSCPtrQueue::RawNode* n; (n = blocks_.tryPop()) != 0; ) { + alignedFree(n); + } + delete [] thread_; +} + +void LocalDistribution::freeNode(uint32 tId, QNode* n) const { + if (n != &thread_[tId]->sentinal) { + n->next = thread_[tId]->free; + thread_[tId]->free = n; + } +} + +LocalDistribution::QNode* LocalDistribution::allocNode(uint32 tId, SharedLiterals* clause) { + for (ThreadData* td = thread_[tId];;) { + if (QNode* n = td->free) { + td->free = static_cast(static_cast(n->next)); + n->data = clause; + return n; + } + // alloc a new block of node; + const uint32 nNodes = 128; + QNode* raw = (QNode*)alignedAlloc(sizeof(QNode) * nNodes, 64); + // add nodes [1, nNodes) to free list + for (uint32 i = 1; i != nNodes-1; ++i) { + raw[i].next = &raw[i+1]; + } + raw[nNodes-1].next = 0; + td->free = &raw[1]; + // use first node to link to block list + blocks_.push(raw); + } +} + +void LocalDistribution::publish(const Solver& s, SharedLiterals* n) { + assert(n->refCount() >= (numThread_-1)); + uint32 sender = s.id(); + uint32 size = n->size(); + uint32 decRef = 0; + for (uint32 i = 0; i != numThread_; ++i) { + if (i == sender) { continue; } + if (size > 1 && !inSet(thread_[i]->peers, sender)) { ++decRef; } + else { + QNode* node = allocNode(sender, n); + thread_[i]->received.push(node); + } + } + if (decRef) { n->release(decRef); } +} +uint32 LocalDistribution::receive(const Solver& in, SharedLiterals** out, uint32 maxn) { + MPSCPtrQueue& q = thread_[in.id()]->received; + QNode* n = 0; + uint32 r = 0; + while (r != maxn && (n = q.pop()) != 0) { + out[r++] = static_cast(n->data); + freeNode(in.id(), n); + } + return r; +} + +} } // namespace Clasp::mt + +#endif diff --git a/libclasp/src/parser.cpp b/libclasp/src/parser.cpp new file mode 100644 index 0000000..a75bf4d --- /dev/null +++ b/libclasp/src/parser.cpp @@ -0,0 +1,511 @@ +// +// Copyright (c) Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _MSC_VER +#pragma warning (disable : 4996) +#endif +const char* clasp_format(char* buf, unsigned size, const char* fmt, ...) { + if (!size) return buf; + *buf = 0; + va_list args; + va_start(args, fmt); + int r = vsnprintf(buf, size, fmt, args); + if (r < 0 || unsigned(r) >= size) { buf[size-1] = 0; } + va_end(args); + return buf; +} +ClaspStringBuffer& ClaspStringBuffer::append(const char* str) { + size_t cap = static_cast(end_ - pos_); + size_t len = std::strlen(str); + if (len < cap || grow(len)) { + std::memcpy(pos_, str, len + 1); + pos_ += len; + } + else { + std::memcpy(pos_, str, cap); + (pos_ = end_)[-1] = 0; + } + return *this; +} +ClaspStringBuffer& ClaspStringBuffer::appendFormat(const char* fmt, ...) { + for (;;) { + va_list args; + va_start(args, fmt); + size_t cap = static_cast(end_ - pos_); + int res = cap ? vsnprintf(pos_, cap, fmt, args) : 0; + va_end(args); + if (res < 0 || size_t(res) >= cap) { // overflow - grow buffer + if (!grow(res > 0 ? size_t(res) : cap + 1)) { + (pos_ = end_)[-1] = 0; // out of memory - truncate and return + return *this; + } + } + else { + pos_ += res; + return *this; + } + } +} +bool ClaspStringBuffer::grow(size_t n) { + size_t nc = static_cast(end_ - buf_) * 2; + size_t ns = static_cast(pos_ - buf_) + n + 1; + if (nc < ns) { nc = ns; } + if (char* nb = (char*)std::realloc(buf_ == fix_ ? 0 : buf_, nc)) { + if (buf_ == fix_) { + std::memcpy(nb, fix_, sizeof(fix_)); + } + pos_ = nb + (pos_ - buf_); + end_ = nb + nc; + buf_ = nb; + return true; + } + return false; +} +ClaspStringBuffer::~ClaspStringBuffer() { + if (buf_ != fix_) { std::free(buf_); } +} +namespace Clasp { +using Potassco::ParseError; +ProblemType detectProblemType(std::istream& in) { + std::istream::int_type x = std::char_traits::eof(); + while (in && (x = in.peek()) != std::char_traits::eof() ) { + char c = static_cast(x); + if (c == ' ' || c == '\t') { in.get(); continue; } + if (AspParser::accept(c)) { return Problem_t::Asp; } + if (DimacsReader::accept(c)){ return Problem_t::Sat; } + if (OpbReader::accept(c)) { return Problem_t::Pb; } + break; + } + char msg[] = "'c': unrecognized input format"; + msg[1] = (char)(unsigned char)x; + in && x != std::char_traits::eof() + ? throw ParseError(1, msg) + : throw ParseError(0, "bad input stream"); +} +///////////////////////////////////////////////////////////////////////////////////////// +// ProgramParser +///////////////////////////////////////////////////////////////////////////////////////// +ProgramParser::ProgramParser() : strat_(0) {} +ProgramParser::~ProgramParser() {} +bool ProgramParser::accept(std::istream& str, const ParserOptions& o) { + if ((strat_ = doAccept(str, o)) != 0) { + strat_->setMaxVar(VAR_MAX); + return true; + } + return false; +} +bool ProgramParser::isOpen() const { + return strat_ != 0; +} +bool ProgramParser::incremental() const { + return strat_ && strat_->incremental(); +} +bool ProgramParser::parse() { + return strat_ && strat_->parse(); +} +bool ProgramParser::more() { + return strat_ && strat_->more(); +} +void ProgramParser::reset() { + if (strat_) { strat_->reset(); } + strat_ = 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// AspParser::SmAdapter +// +// Callback interface for smodels parser +///////////////////////////////////////////////////////////////////////////////////////// +struct AspParser::SmAdapter : public Asp::LogicProgramAdapter, public Potassco::AtomTable { + typedef Clasp::HashMap_t::map_type StrMap; + typedef SingleOwnerPtr StrMapPtr; + SmAdapter(Asp::LogicProgram& prg) : Asp::LogicProgramAdapter(prg) {} + void endStep() { + Asp::LogicProgramAdapter::endStep(); + if (inc_ && lp_->ctx()->hasMinimize()) { + lp_->ctx()->removeMinimize(); + } + if (!inc_) { atoms_ = 0; } + } + void add(Potassco::Atom_t id, const Potassco::StringSpan& name, bool output) { + ConstString n(name); + if (atoms_.get()) { atoms_->insert(StrMap::value_type(n, id)); } + if (output) { lp_->addOutput(n, id); } + } + Potassco::Atom_t find(const Potassco::StringSpan& name) { + if (!atoms_.get()) { return 0; } + ConstString n(name); + StrMap::iterator it = atoms_->find(n); + return it != atoms_->end() ? it->second : 0; + } + StrMapPtr atoms_; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// AspParser +///////////////////////////////////////////////////////////////////////////////////////// +AspParser::AspParser(Asp::LogicProgram& prg) + : lp_(&prg) + , in_(0) + , out_(0) {} +AspParser::~AspParser() { + delete in_; + delete out_; +} +bool AspParser::accept(char c) { return Potassco::BufferedStream::isDigit(c) || c == 'a'; } + +AspParser::StrategyType* AspParser::doAccept(std::istream& str, const ParserOptions& o) { + delete in_; + delete out_; + if (Potassco::BufferedStream::isDigit((char)str.peek())) { + out_ = new SmAdapter(*lp_); + Potassco::SmodelsInput::Options so; + so.enableClaspExt(); + if (o.isEnabled(ParserOptions::parse_heuristic)) { + so.convertHeuristic(); + static_cast(out_)->atoms_ = new AspParser::SmAdapter::StrMap(); + } + if (o.isEnabled(ParserOptions::parse_acyc_edge)) { + so.convertEdges(); + } + in_ = new Potassco::SmodelsInput(*out_, so, static_cast(out_)); + } + else { + out_ = new Asp::LogicProgramAdapter(*lp_); + in_ = new Potassco::AspifInput(*out_); + } + return in_->accept(str) ? in_ : 0; +} + +void AspParser::write(Asp::LogicProgram& prg, std::ostream& os) { + write(prg, os, prg.supportsSmodels() ? format_smodels : format_aspif); +} +void AspParser::write(Asp::LogicProgram& prg, std::ostream& os, Format f) { + using namespace Potassco; + SingleOwnerPtr out; + if (f == format_aspif) { + out.reset(new Potassco::AspifOutput(os)); + } + else { + out.reset(new Potassco::SmodelsOutput(os, true, prg.falseAtom())); + } + if (prg.startAtom() == 1) { out->initProgram(prg.isIncremental()); } + out->beginStep(); + prg.accept(*out); + out->endStep(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// clasp specific extensions for Dimacs/OPB +///////////////////////////////////////////////////////////////////////////////////////// +SatReader::SatReader() {} +bool SatReader::skipLines(char c) { + while (peek(true) == c) { skipLine(); } + return true; +} +Literal SatReader::matchLit(Var max) { + for (char c; (c = stream()->peek()) == ' ' || c == '\t';) { stream()->get(); } + bool sign = stream()->peek() == '-'; + if (sign) { stream()->get(); } + if (stream()->peek() == 'x') { stream()->get(); } + int64 id; + require(stream()->match(id) && id >= 0 && id <= (int64)max, "identifier expected"); + return Literal(static_cast(id), sign); +} +void SatReader::parseGraph(uint32 maxVar, const char* pre, ExtDepGraph& graph) { + int maxNode = matchPos("graph: positive number of nodes expected"); + while (match(pre)) { + if (match("node ")) { skipLine(); } + else if (match("arc ")) { + Literal lit = matchLit(maxVar); + Var beg = matchPos(maxNode, "graph: invalid start node"); + Var end = matchPos(maxNode, "graph: invalid end node"); + graph.addEdge(lit, beg, end); + } + else if (match("endgraph")) { return; } + else { break; } + } + require(false, "graph: endgraph expected"); +} +void SatReader::parseProject(uint32 maxVar, SharedContext& ctx) { + for (unsigned n = this->line(); (stream()->skipWs(), this->line() == n);) { + Literal x = matchLit(maxVar); + if (x == lit_true()) break; + require(!x.sign(), "project: positive literal expected"); + ctx.output.addProject(x); + } +} +void SatReader::parseAssume(uint32 maxVar) { + for (unsigned n = this->line(); (stream()->skipWs(), this->line() == n);) { + Literal x = matchLit(maxVar); + if (x == lit_true()) { break; } + addAssumption(x); + } +} +void SatReader::parseHeuristic(uint32 maxVar, SharedContext& ctx) { + using Potassco::Heuristic_t; + Heuristic_t type = static_cast(matchPos(Heuristic_t::eMax, "heuristic: modifier expected")); + Literal atom = matchLit(maxVar); + require(!atom.sign(), "heuristic: positive literal expected"); + int16 bias = (int16)matchInt(INT16_MIN, INT16_MAX, "heuristic: bias expected"); + uint16 prio = (uint16)matchPos(UINT16_MAX, "heuristic: priority expected"); + ctx.heuristic.add(atom.var(), type, bias, prio, matchLit(maxVar)); +} +void SatReader::parseOutput(uint32 maxVar, SharedContext& ctx) { + if (match("range ")) { + Literal lo = matchLit(maxVar); + Literal hi = matchLit(maxVar); + require(lo.var() <= hi.var(), "output: invalid range"); + ctx.output.setVarRange(Range32(lo.var(), hi.var() + 1)); + } + else { + Literal cond = matchLit(maxVar); + while (peek(false) == ' ') { stream()->get(); } + std::string name; + for (char c; (c = stream()->get()) != '\n' && c;) { name += c; } + name.erase(name.find_last_not_of(" \t")+1); + ctx.output.add(ConstString(Potassco::toSpan(name)), cond); + } +} +void SatReader::parseExt(const char* pre, uint32 maxVar, SharedContext& ctx) { + const bool acyc = options.isEnabled(ParserOptions::parse_acyc_edge); + const bool minw = options.isEnabled(ParserOptions::parse_minimize); + const bool proj = options.isEnabled(ParserOptions::parse_project); + const bool heur = options.isEnabled(ParserOptions::parse_heuristic); + const bool assu = options.isEnabled(ParserOptions::parse_assume); + uint32 outp = options.isEnabled(ParserOptions::parse_output); + for (ExtDepGraph* g = 0; match(pre);) { + if (acyc && match("graph ")) { + require(g == 0, "graph: only one graph supported"); + g = ctx.extGraph.get(); + if (!g) { ctx.extGraph = (g = new ExtDepGraph()); } + else { g->update(); } + parseGraph(maxVar, pre, *g); + g->finalize(ctx); + } + else if (minw && match("minweight ")) { + WeightLitVec min; + for (int lit, weight, max = static_cast(maxVar); (lit = matchInt(-max, max)) != 0;) { + weight = matchInt(CLASP_WEIGHT_T_MIN, CLASP_WEIGHT_T_MAX, "minweight: weight expected"); + min.push_back(WeightLiteral(toLit(lit), weight)); + } + addObjective(min); + } + else if (proj && match("project ")) { parseProject(maxVar, ctx); } + else if (heur && match("heuristic ")) { parseHeuristic(maxVar, ctx); } + else if (assu && match("assume ")) { parseAssume(maxVar); } + else if (outp && match("output ")) { + if (outp++ == 1) { ctx.output.setVarRange(Range32(0, 0)); } + parseOutput(maxVar, ctx); + } + else { skipLine(); } + } +} + +SatParser::SatParser(SatBuilder& prg) : reader_(new DimacsReader(prg)) {} +SatParser::SatParser(PBBuilder& prg) : reader_(new OpbReader(prg)) {} +SatParser::~SatParser() { delete reader_; } +ProgramParser::StrategyType* SatParser::doAccept(std::istream& str, const ParserOptions& o) { + reader_->options = o; + return reader_->accept(str) ? reader_ : 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// DimacsReader +///////////////////////////////////////////////////////////////////////////////////////// +DimacsReader::DimacsReader(SatBuilder& prg) : program_(&prg) {} + +// Parses the p line: p [w]cnf #vars #clauses [max clause weight] +bool DimacsReader::doAttach(bool& inc) { + inc = false; + if (!accept(peek(false))) { return false; } + skipLines('c'); + require(match("p "), "missing problem line"); + wcnf_ = match("w"); + require(match("cnf ", false), "unrecognized format, [w]cnf expected"); + numVar_ = matchPos(ProgramParser::VAR_MAX, "#vars expected"); + uint32 numC = matchPos("#clauses expected"); + wsum_t cw = 0; + while (stream()->peek() == ' ') { stream()->get(); }; + if (wcnf_ && peek(false) != '\n'){ stream()->match(cw); } + while (stream()->peek() == ' ') { stream()->get(); }; + require(stream()->get() == '\n', "invalid extra characters in problem line"); + program_->prepareProblem(numVar_, cw, numC); + if (options.ext != 0) { + parseExt("c ", numVar_, *program_->ctx()); + } + return true; +} +bool DimacsReader::doParse() { + LitVec cc; + const bool wcnf = wcnf_; + wsum_t cw = 0; + const int maxV = static_cast(numVar_ + 1); + while (skipLines('c') && peek(true)) { + cc.clear(); + if (wcnf) { require(stream()->match(cw) && cw > 0, "wcnf: positive clause weight expected"); } + for (int lit; (lit = matchInt(-maxV, maxV, "invalid variable in clause")) != 0;) { + cc.push_back(toLit(lit)); + } + program_->addClause(cc, cw); + } + require(!more(), "unrecognized format"); + return true; +} +void DimacsReader::addObjective(const WeightLitVec& vec) { + program_->addObjective(vec); +} +void DimacsReader::addAssumption(Literal x) { + program_->addAssumption(x); +} +///////////////////////////////////////////////////////////////////////////////////////// +// OpbReader +///////////////////////////////////////////////////////////////////////////////////////// +OpbReader::OpbReader(PBBuilder& prg) : program_(&prg) {} + +void OpbReader::addObjective(const WeightLitVec& vec) { + program_->addObjective(vec); +} +void OpbReader::addAssumption(Literal x) { + program_->addAssumption(x); +} + +// * #variable= int #constraint= int [#product= int sizeproduct= int] [#soft= int mincost= int maxcost= int sumcost= int] +// where [] indicate optional parts, i.e. +// LIN-PBO: * #variable= int #constraint= int +// NLC-PBO: * #variable= int #constraint= int #product= int sizeproduct= int +// LIN-WBO: * #variable= int #constraint= int #soft= int mincost= int maxcost= int sumcost= int +// NLC-WBO: * #variable= int #constraint= int #product= int sizeproduct= int #soft= int mincost= int maxcost= int sumcost= int +bool OpbReader::doAttach(bool& inc) { + inc = false; + if (!accept(peek(false))) { return false; } + require(match("* #variable="), "missing problem line '* #variable='"); + unsigned numV = matchPos(ProgramParser::VAR_MAX, "number of vars expected"); + require(match("#constraint="), "bad problem line: missing '#constraint='"); + unsigned numC = matchPos("number of constraints expected"); + unsigned numProd = 0, sizeProd = 0, numSoft = 0; + minCost_ = 0, maxCost_ = 0; + if (match("#product=")) { // NLC instance + numProd = matchPos(); + require(match("sizeproduct="), "'sizeproduct=' expected"); + sizeProd= matchPos(); + (void)sizeProd; + } + if (match("#soft=")) { // WBO instance + numSoft = matchPos(); + require(match("mincost="), "'mincost=' expected"); + minCost_= (weight_t)matchPos(CLASP_WEIGHT_T_MAX, "invalid min costs"); + require(match("maxcost="), "'maxcost=' expected"); + maxCost_= (weight_t)matchPos(CLASP_WEIGHT_T_MAX, "invalid max costs"); + require(match("sumcost="), "'sumcost=' expected"); + wsum_t sum; + require(stream()->match(sum) && sum > 0, "positive integer expected"); + } + program_->prepareProblem(numV, numProd, numSoft, numC); + return true; +} +bool OpbReader::doParse() { + if (options.ext && options.ext != ParserOptions::parse_minimize) { + options.ext &= ~uint8(ParserOptions::parse_minimize); + parseExt("* ", program_->numVars() + 1, *program_->ctx()); + } + skipLines('*'); + parseOptObjective(); + for (;;) { + skipLines('*'); + if (!more()) { return true; } + parseConstraint(); + } +} +// ::= "min:" ";" +// OR +// ::= "soft:" [] ";" +void OpbReader::parseOptObjective() { + if (match("min:")) { + parseSum(); + program_->addObjective(active_.lits); + } + else if (match("soft:")) { + wsum_t softCost; + require(stream()->match(softCost) && softCost > 0, "positive integer expected"); + require(match(";"), "semicolon missing after constraint"); + program_->setSoftBound(softCost); + } +} + +// ::= ";" +// OR +// ::= "[" "]" +void OpbReader::parseConstraint() { + weight_t cost = 0; + if (match("[")) { + cost = matchInt(minCost_, maxCost_, "invalid soft constraint cost"); + require(match("]"), "invalid soft constraint"); + } + parseSum(); + active_.eq = match("="); + require(active_.eq || match(">=", false), "relational operator expected"); + active_.bound = matchInt(CLASP_WEIGHT_T_MIN, CLASP_WEIGHT_T_MAX, "invalid coefficient on rhs of constraint"); + require(match(";"), "semicolon missing after constraint"); + program_->addConstraint(active_.lits, active_.bound, active_.eq, cost); +} + +// ::= | +// ::= +void OpbReader::parseSum() { + active_.lits.clear(); + while (!match(";")) { + int coeff = matchInt(INT_MIN+1, INT_MAX, "coefficient expected"); + parseTerm(); + Literal x = active_.term.size() == 1 ? active_.term[0] : program_->addProduct(active_.term); + active_.lits.push_back(WeightLiteral(x, coeff)); + char p = peek(true); + if (p == '>' || p == '=') break; + } +} +// ::= +// OR +// ::= | + +void OpbReader::parseTerm() { + active_.term.clear(); + char peek; + do { + match("*"); // optionally + bool sign = match("~"); // optionally + require(match("x"), "identifier expected"); + Var var = matchAtom(); + require(var <= program_->numVars() + 1, "identifier out of range"); + active_.term.push_back(Literal(var, sign)); + peek = this->peek(true); + } while (peek == '*' || peek == '~' || peek == 'x'); +} + +} diff --git a/libclasp/src/program_builder.cpp b/libclasp/src/program_builder.cpp new file mode 100644 index 0000000..fec4681 --- /dev/null +++ b/libclasp/src/program_builder.cpp @@ -0,0 +1,375 @@ +// +// Copyright (c) 2006-2016 Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +namespace Clasp { + +///////////////////////////////////////////////////////////////////////////////////////// +// class ProgramBuilder +///////////////////////////////////////////////////////////////////////////////////////// +ProgramBuilder::ProgramBuilder() : ctx_(0), frozen_(true) {} +ProgramBuilder::~ProgramBuilder() {} +bool ProgramBuilder::ok() const { return ctx_ && ctx_->ok(); } +bool ProgramBuilder::startProgram(SharedContext& ctx) { + ctx.report(Event::subsystem_load); + ctx_ = &ctx; + frozen_ = ctx.frozen(); + return ctx_->ok() && doStartProgram(); +} +bool ProgramBuilder::updateProgram() { + CLASP_ASSERT_CONTRACT_MSG(ctx_, "startProgram() not called!"); + bool up = frozen(); + bool ok = ctx_->ok() && ctx_->unfreeze() && doUpdateProgram() && (ctx_->setSolveMode(SharedContext::solve_multi), true); + frozen_ = ctx_->frozen(); + if (up && !frozen()){ ctx_->report(Event::subsystem_load); } + return ok; +} +bool ProgramBuilder::endProgram() { + CLASP_ASSERT_CONTRACT_MSG(ctx_, "startProgram() not called!"); + bool ok = ctx_->ok(); + if (ok && !frozen_) { + ctx_->report(Event::subsystem_prepare); + ok = doEndProgram(); + frozen_ = true; + } + return ok; +} +void ProgramBuilder::getAssumptions(LitVec& out) const { + CLASP_ASSERT_CONTRACT(ctx_ && frozen()); + doGetAssumptions(out); +} +void ProgramBuilder::getWeakBounds(SumVec& out) const { + CLASP_ASSERT_CONTRACT(ctx_ && frozen()); + doGetWeakBounds(out); +} +ProgramParser& ProgramBuilder::parser() { + if (!parser_.get()) { + parser_.reset(doCreateParser()); + } + return *parser_; +} +bool ProgramBuilder::parseProgram(std::istream& input) { + CLASP_ASSERT_CONTRACT(ctx_ && !frozen()); + ProgramParser& p = parser(); + CLASP_FAIL_IF(!p.accept(input), "unrecognized input format"); + return p.parse(); +} +void ProgramBuilder::addMinLit(weight_t prio, WeightLiteral x) { + ctx_->addMinimize(x, prio); +} +void ProgramBuilder::markOutputVariables() const { + const OutputTable& out = ctx_->output; + for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) { + ctx_->setOutput(*it, true); + } + for (OutputTable::pred_iterator it = out.pred_begin(), end = out.pred_end(); it != end; ++it) { + ctx_->setOutput(it->cond.var(), true); + } +} +void ProgramBuilder::doGetWeakBounds(SumVec&) const {} +///////////////////////////////////////////////////////////////////////////////////////// +// class SatBuilder +///////////////////////////////////////////////////////////////////////////////////////// +SatBuilder::SatBuilder(bool maxSat) : ProgramBuilder(), hardWeight_(0), vars_(0), pos_(0), maxSat_(maxSat) {} +bool SatBuilder::markAssigned() { + if (pos_ == ctx()->master()->trail().size()) { return true; } + bool ok = ctx()->ok() && ctx()->master()->propagate(); + for (const LitVec& trail = ctx()->master()->trail(); pos_ < trail.size(); ++pos_) { + markLit(~trail[pos_]); + } + return ok; +} +void SatBuilder::prepareProblem(uint32 numVars, wsum_t cw, uint32 clauseHint) { + CLASP_ASSERT_CONTRACT_MSG(ctx(), "startProgram() not called!"); + Var start = ctx()->addVars(numVars, Var_t::Atom, VarInfo::Input | VarInfo::Nant); + ctx()->output.setVarRange(Range32(start, start + numVars)); + ctx()->startAddConstraints(std::min(clauseHint, uint32(10000))); + varState_.resize(start + numVars); + vars_ = ctx()->numVars(); + hardWeight_ = cw; + markAssigned(); +} +bool SatBuilder::addObjective(const WeightLitVec& min) { + for (WeightLitVec::const_iterator it = min.begin(), end = min.end(); it != end; ++it) { + addMinLit(0, *it); + varState_[it->first.var()] |= (falseValue(it->first) << 2u); + } + return ctx()->ok(); +} +void SatBuilder::addProject(Var v) { + ctx()->output.addProject(posLit(v)); +} +void SatBuilder::addAssumption(Literal x) { + assume_.push_back(x); +} +bool SatBuilder::addClause(LitVec& clause, wsum_t cw) { + if (!ctx()->ok() || satisfied(clause)) { return ctx()->ok(); } + CLASP_ASSERT_CONTRACT_MSG(cw >= 0 && (cw <= std::numeric_limits::max() || cw == hardWeight_), "Clause weight out of bounds!"); + if (cw == 0 && maxSat_){ cw = 1; } + if (cw == hardWeight_) { + return ClauseCreator::create(*ctx()->master(), clause, Constraint_t::Static).ok() && markAssigned(); + } + else { + // Store weight, relaxtion var, and (optionally) clause + softClauses_.push_back(Literal::fromRep((uint32)cw)); + if (clause.size() > 1){ softClauses_.push_back(posLit(++vars_)); softClauses_.insert(softClauses_.end(), clause.begin(), clause.end()); } + else if (!clause.empty()) { softClauses_.push_back(~clause.back()); } + else { softClauses_.push_back(lit_true()); } + softClauses_.back().flag(); // mark end of clause + } + return true; +} +bool SatBuilder::satisfied(LitVec& cc) { + bool sat = false; + LitVec::iterator j = cc.begin(); + for (LitVec::const_iterator it = cc.begin(), end = cc.end(); it != end; ++it) { + Literal x = *it; + uint32 m = 1+x.sign(); + uint32 n = uint32(varState_[it->var()] & 3u) + m; + if (n == m) { varState_[it->var()] |= m; x.unflag(); *j++ = x; } + else if (n == 3u){ sat = true; break; } + } + cc.erase(j, cc.end()); + for (LitVec::const_iterator it = cc.begin(), end = cc.end(); it != end; ++it) { + if (!sat) { varState_[it->var()] |= (varState_[it->var()] & 3u) << 2; } + varState_[it->var()] &= ~3u; + } + return sat; +} +bool SatBuilder::doStartProgram() { + vars_ = ctx()->numVars(); + pos_ = 0; + assume_.clear(); + return markAssigned(); +} +ProgramParser* SatBuilder::doCreateParser() { + return new SatParser(*this); +} +bool SatBuilder::doEndProgram() { + bool ok = ctx()->ok(); + if (!softClauses_.empty() && ok) { + ctx()->setPreserveModels(true); + uint32 softVars = vars_ - ctx()->numVars(); + ctx()->addVars(softVars, Var_t::Atom, VarInfo::Nant); + ctx()->startAddConstraints(); + LitVec cc; + for (LitVec::const_iterator it = softClauses_.begin(), end = softClauses_.end(); it != end && ok; ++it) { + weight_t w = (weight_t)it->rep(); + Literal relax = *++it; + if (!relax.flagged()) { + cc.assign(1, relax); + do { cc.push_back(*++it); } while (!cc.back().flagged()); + cc.back().unflag(); + ok = ClauseCreator::create(*ctx()->master(), cc, Constraint_t::Static).ok(); + } + addMinLit(0, WeightLiteral(relax.unflag(), w)); + } + LitVec().swap(softClauses_); + } + if (ok) { + const uint32 seen = 12; + const bool elim = !ctx()->preserveModels(); + for (Var v = 1; v != (Var)varState_.size() && ok; ++v) { + uint32 m = varState_[v]; + if ( (m & seen) != seen ) { + if (m) { ctx()->setNant(v, false); ctx()->master()->setPref(v, ValueSet::def_value, ValueRep(m >> 2)); } + else if (elim){ ctx()->eliminate(v); } + } + } + markOutputVariables(); + } + return ok; +} +///////////////////////////////////////////////////////////////////////////////////////// +// class PBBuilder +///////////////////////////////////////////////////////////////////////////////////////// +PBBuilder::PBBuilder() : auxVar_(1) {} +void PBBuilder::prepareProblem(uint32 numVars, uint32 numProd, uint32 numSoft, uint32 numCons) { + CLASP_ASSERT_CONTRACT_MSG(ctx(), "startProgram() not called!"); + Var out = ctx()->addVars(numVars, Var_t::Atom, VarInfo::Nant | VarInfo::Input); + auxVar_ = ctx()->addVars(numProd + numSoft, Var_t::Atom, VarInfo::Nant); + endVar_ = auxVar_ + numProd + numSoft; + ctx()->output.setVarRange(Range32(out, out + numVars)); + ctx()->startAddConstraints(numCons); +} +uint32 PBBuilder::getAuxVar() { + CLASP_ASSERT_CONTRACT_MSG(ctx()->validVar(auxVar_), "Variables out of bounds"); + return auxVar_++; +} +bool PBBuilder::addConstraint(WeightLitVec& lits, weight_t bound, bool eq, weight_t cw) { + if (!ctx()->ok()) { return false; } + Var eqVar = 0; + if (cw > 0) { // soft constraint + if (lits.size() != 1) { + eqVar = getAuxVar(); + addMinLit(0, WeightLiteral(negLit(eqVar), cw)); + } + else { + if (lits[0].second < 0) { bound += (lits[0].second = -lits[0].second); lits[0].first = ~lits[0].first; } + if (lits[0].second < bound){ lits[0].first = lit_false(); } + addMinLit(0, WeightLiteral(~lits[0].first, cw)); + return true; + } + } + return WeightConstraint::create(*ctx()->master(), posLit(eqVar), lits, bound, !eq ? 0 : WeightConstraint::create_eq_bound).ok(); +} + +bool PBBuilder::addObjective(const WeightLitVec& min) { + for (WeightLitVec::const_iterator it = min.begin(), end = min.end(); it != end; ++it) { + addMinLit(0, *it); + } + return ctx()->ok(); +} +void PBBuilder::addProject(Var v) { + ctx()->output.addProject(posLit(v)); +} +void PBBuilder::addAssumption(Literal x) { + assume_.push_back(x); +} +bool PBBuilder::setSoftBound(wsum_t b) { + if (b > 0) { soft_ = b-1; } + return true; +} + +void PBBuilder::doGetWeakBounds(SumVec& out) const { + if (soft_ != std::numeric_limits::max()) { + if (out.empty()) { out.push_back(soft_); } + else if (out[0] > soft_){ out[0] = soft_; } + } +} + +Literal PBBuilder::addProduct(LitVec& lits) { + if (!ctx()->ok()) { return lit_false(); } + prod_.lits.reserve(lits.size() + 1); + if (productSubsumed(lits, prod_)){ + return lits[0]; + } + Literal& eq = products_[prod_]; + if (eq != lit_true()) { + return eq; + } + eq = posLit(getAuxVar()); + addProductConstraints(eq, lits); + return eq; +} +bool PBBuilder::productSubsumed(LitVec& lits, PKey& prod) { + Literal last = lit_true(); + LitVec::iterator j = lits.begin(); + Solver& s = *ctx()->master(); + uint32 abst = 0; + prod.lits.assign(1, lit_true()); // room for abst + for (LitVec::const_iterator it = lits.begin(), end = lits.end(); it != end; ++it) { + if (s.isFalse(*it) || ~*it == last) { // product is always false + lits.assign(1, lit_false()); + return true; + } + else if (last.var() > it->var()) { // not sorted - redo with sorted product + std::sort(lits.begin(), lits.end()); + return productSubsumed(lits, prod); + } + else if (!s.isTrue(*it) && last != *it) { + prod.lits.push_back(*it); + abst += hashLit(*it); + last = *it; + *j++ = last; + } + } + prod.lits[0].rep() = abst; + lits.erase(j, lits.end()); + if (lits.empty()) { lits.assign(1, lit_true()); } + return lits.size() < 2; +} +void PBBuilder::addProductConstraints(Literal eqLit, LitVec& lits) { + Solver& s = *ctx()->master(); + assert(s.value(eqLit.var()) == value_free); + bool ok = ctx()->ok(); + for (LitVec::iterator it = lits.begin(), end = lits.end(); it != end && ok; ++it) { + assert(s.value(it->var()) == value_free); + ok = ctx()->addBinary(~eqLit, *it); + *it = ~*it; + } + lits.push_back(eqLit); + if (ok) { ClauseCreator::create(s, lits, ClauseCreator::clause_no_prepare); } +} + +bool PBBuilder::doStartProgram() { + auxVar_ = ctx()->numVars() + 1; + soft_ = std::numeric_limits::max(); + assume_.clear(); + return true; +} +bool PBBuilder::doEndProgram() { + while (auxVar_ != endVar_) { + if (!ctx()->addUnary(negLit(getAuxVar()))) { return false; } + } + markOutputVariables(); + return true; +} +ProgramParser* PBBuilder::doCreateParser() { + return new SatParser(*this); +} +///////////////////////////////////////////////////////////////////////////////////////// +// class BasicProgramAdapter +///////////////////////////////////////////////////////////////////////////////////////// +BasicProgramAdapter::BasicProgramAdapter(ProgramBuilder& prg) : prg_(&prg), inc_(false) { + int t = prg_->type(); + CLASP_FAIL_IF(t != Problem_t::Sat && t != Problem_t::Pb, "unknown program type"); +} +void BasicProgramAdapter::initProgram(bool inc) { inc_ = inc; } +void BasicProgramAdapter::beginStep() { if (inc_ || prg_->frozen()) { prg_->updateProgram(); } } + +void BasicProgramAdapter::rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body) { + using namespace Potassco; + CLASP_FAIL_IF(ht != Head_t::Disjunctive || !empty(head), "unsupported rule type"); + if (prg_->type() == Problem_t::Sat) { + clause_.clear(); + for (LitSpan::iterator it = begin(body), end = Potassco::end(body); it != end; ++it) { clause_.push_back(~toLit(*it)); } + static_cast(*prg_).addClause(clause_); + } + else { + constraint_.clear(); + for (LitSpan::iterator it = begin(body), end = Potassco::end(body); it != end; ++it) { constraint_.push_back(WeightLiteral(~toLit(*it), 1)); } + static_cast(*prg_).addConstraint(constraint_, 1); + } +} +void BasicProgramAdapter::rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body) { + using namespace Potassco; + CLASP_FAIL_IF(ht != Head_t::Disjunctive || !empty(head) || prg_->type() == Problem_t::Sat, "unsupported rule type"); + constraint_.clear(); + Potassco::Weight_t sum = 0; + for (WeightLitSpan::iterator it = begin(body), end = Potassco::end(body); it != end; ++it) { + constraint_.push_back(WeightLiteral(~toLit(it->lit), it->weight)); + sum += it->weight; + } + static_cast(*prg_).addConstraint(constraint_, (sum - bound) + 1); +} +void BasicProgramAdapter::minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits) { + CLASP_FAIL_IF(prio != 0 || prg_->type() == Problem_t::Sat, "unsupported rule type"); + using namespace Potassco; + constraint_.clear(); + for (WeightLitSpan::iterator it = begin(lits), end = Potassco::end(lits); it != end; ++it) { constraint_.push_back(WeightLiteral(toLit(it->lit), it->weight)); } + static_cast(*prg_).addObjective(constraint_); +} +} diff --git a/libclasp/src/satelite.cpp b/libclasp/src/satelite.cpp new file mode 100644 index 0000000..93d9ff5 --- /dev/null +++ b/libclasp/src/satelite.cpp @@ -0,0 +1,618 @@ +// +// Copyright (c) 2006-2010, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include + +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// SatElite preprocessing +// +///////////////////////////////////////////////////////////////////////////////////////// +SatElite::SatElite() + : occurs_(0) + , elimHeap_(LessOccCost(occurs_)) + , qFront_(0) + , facts_(0) { +} + +SatElite::~SatElite() { + SatElite::doCleanUp(); +} + +void SatElite::reportProgress(Progress::EventOp id, uint32 curr, uint32 max) { + ctx_->report(Progress(this, id, curr, max)); +} + +Clasp::SatPreprocessor* SatElite::clone() { + SatElite* cp = new SatElite(); + return cp; +} + +void SatElite::doCleanUp() { + delete [] occurs_; occurs_ = 0; + ClauseList().swap(resCands_); + VarVec().swap(occT_[pos]); + VarVec().swap(occT_[neg]); + LitVec().swap(resolvent_); + VarVec().swap(queue_); + elimHeap_.clear(); + qFront_ = facts_ = 0; +} + +SatPreprocessor::Clause* SatElite::popSubQueue() { + if (Clause* c = clause( queue_[qFront_++] )) { + c->setInQ(false); + return c; + } + return 0; +} + +void SatElite::addToSubQueue(uint32 clauseId) { + assert(clause(clauseId) != 0); + if (!clause(clauseId)->inQ()) { + queue_.push_back(clauseId); + clause(clauseId)->setInQ(true); + } +} + +void SatElite::attach(uint32 clauseId, bool initialClause) { + Clause& c = *clause(clauseId); + c.abstraction() = 0; + for (uint32 i = 0; i != c.size(); ++i) { + Var v = c[i].var(); + occurs_[v].add(clauseId, c[i].sign()); + occurs_[v].unmark(); + c.abstraction() |= Clause::abstractLit(c[i]); + if (elimHeap_.is_in_queue(v)) { + elimHeap_.decrease(v); + } + else if (initialClause) { + updateHeap(v); + } + } + occurs_[c[0].var()].addWatch(clauseId); + addToSubQueue(clauseId); + stats.clAdded += !initialClause; +} + +void SatElite::detach(uint32 id) { + Clause& c = *clause(id); + occurs_[c[0].var()].removeWatch(id); + for (uint32 i = 0; i != c.size(); ++i) { + Var v = c[i].var(); + occurs_[v].remove(id, c[i].sign(), false); + updateHeap(v); + } + destroyClause(id); +} + +void SatElite::bceVeRemove(uint32 id, bool freeId, Var ev, bool blocked) { + Clause& c = *clause(id); + occurs_[c[0].var()].removeWatch(id); + uint32 pos = 0; + for (uint32 i = 0; i != c.size(); ++i) { + Var v = c[i].var(); + if (v != ev) { + occurs_[v].remove(id, c[i].sign(), freeId); + updateHeap(v); + } + else { + occurs_[ev].remove(id, c[i].sign(), false); + pos = i; + } + } + std::swap(c[0], c[pos]); + c.setMarked(blocked); + eliminateClause(id); +} + +bool SatElite::initPreprocess(Options& opts) { + reportProgress(Progress::event_algorithm, 0,100); + opts_ = &opts; + occurs_ = new OccurList[ctx_->numVars()+1]; + qFront_ = 0; + occurs_[0].bce = (opts.type == Options::sat_pre_full); + return true; +} +bool SatElite::doPreprocess() { + // 1. add clauses to occur lists + for (uint32 i = 0, end = numClauses(); i != end; ++i) { + attach(i, true); + } + // 2. remove subsumed clauses, eliminate vars by clause distribution + timeout_ = opts_->limTime ? time(0) + opts_->limTime : std::numeric_limits::max(); + for (uint32 i = 0, end = opts_->limIters ? opts_->limIters : UINT32_MAX; queue_.size()+elimHeap_.size() > 0; ++i) { + if (!backwardSubsume()) { return false; } + if (timeout() || i == end){ break; } + if (!eliminateVars()) { return false; } + } + reportProgress(Progress::event_algorithm, 100,100); + return true; +} + +// (Destructive) unit propagation on clauses. +// Removes satisfied clauses and shortens clauses w.r.t. false literals. +// Pre: Assignment is propagated w.r.t other non-clause constraints +// Post: Assignment is fully propagated and no clause contains an assigned literal +bool SatElite::propagateFacts() { + Solver* s = ctx_->master(); + assert(s->queueSize() == 0); + while (facts_ != s->numAssignedVars()) { + Literal l = s->trail()[facts_++]; + OccurList& ov = occurs_[l.var()]; + ClRange cls = occurs_[l.var()].clauseRange(); + for (ClIter x = cls.first; x != cls.second; ++x) { + if (clause(x->var()) == 0) { continue; } + else if (x->sign() == l.sign()) { detach(x->var()); } + else if (!strengthenClause(x->var(), ~l)){ return false; } + } + ov.clear(); + ov.mark(!l.sign()); + } + assert(s->queueSize() == 0); + return true; +} + +// Backward subsumption and self-subsumption resolution until fixpoint +bool SatElite::backwardSubsume() { + if (!propagateFacts()) return false; + while (qFront_ != queue_.size()) { + if ((qFront_ & 8191) == 0) { + if (timeout()) break; + if (queue_.size() > 1000) reportProgress(Progress::event_subsumption, qFront_, queue_.size()); + } + if (peekSubQueue() == 0) { ++qFront_; continue; } + Clause& c = *popSubQueue(); + // Try to minimize effort by testing against the var in c that occurs least often; + Literal best = c[0]; + for (uint32 i = 1; i < c.size(); ++i) { + if (occurs_[c[i].var()].numOcc() < occurs_[best.var()].numOcc()) { + best = c[i]; + } + } + // Test against all clauses containing best + ClWList& cls = occurs_[best.var()].refs; + Literal res = lit_false(); + uint32 j = 0; + // must use index access because cls might change! + for (uint32 i = 0, end = cls.left_size(); i != end; ++i) { + Literal cl = cls.left(i); + uint32 otherId = cl.var(); + Clause* other = clause(otherId); + if (other && other!= &c && (res = subsumes(c, *other, best.sign()==cl.sign()?lit_true():best)) != lit_false()) { + if (res == lit_true()) { + // other is subsumed - remove it + detach(otherId); + other = 0; + } + else { + // self-subsumption resolution; other is subsumed by c\{res} U {~res} + // remove ~res from other, add it to subQ so that we can check if it now subsumes c + res = ~res; + occurs_[res.var()].remove(otherId, res.sign(), res.var() != best.var()); + updateHeap(res.var()); + if (!strengthenClause(otherId, res)) { return false; } + if (res.var() == best.var() || !clause(otherId)) { other = 0; } + } + } + if (other && j++ != i) { cls.left(j-1) = cl; } + } + cls.shrink_left(cls.left_begin()+j); + occurs_[best.var()].dirty = 0; + assert(occurs_[best.var()].numOcc() == (uint32)cls.left_size()); + if (!propagateFacts()) return false; + } + queue_.clear(); + qFront_ = 0; + return true; +} + +// checks if 'c' subsumes 'other', and at the same time, if it can be used to +// simplify 'other' by subsumption resolution. +// Return: +// - lit_false() - No subsumption or simplification +// - lit_true() - 'c' subsumes 'other' +// - l - The literal l can be deleted from 'other' +Literal SatElite::subsumes(const Clause& c, const Clause& other, Literal res) const { + if (other.size() < c.size() || (c.abstraction() & ~other.abstraction()) != 0) { + return lit_false(); + } + if (c.size() < 10 || other.size() < 10) { + for (uint32 i = 0; i != c.size(); ++i) { + for (uint32 j = 0; j != other.size(); ++j) { + if (c[i].var() == other[j].var()) { + if (c[i].sign() == other[j].sign()) { goto found; } + else if (res != lit_true() && res!=c[i]) { return lit_false(); } + res = c[i]; + goto found; + } + } + return lit_false(); + found:; + } + } + else { + markAll(&other[0], other.size()); + for (uint32 i = 0; i != c.size(); ++i) { + if (occurs_[c[i].var()].litMark == 0) { res = lit_false(); break; } + if (occurs_[c[i].var()].marked(!c[i].sign())) { + if (res != lit_true()&&res!=c[i]) { res = lit_false(); break; } + res = c[i]; + } + } + unmarkAll(&other[0], other.size()); + } + return res; +} + +uint32 SatElite::findUnmarkedLit(const Clause& c, uint32 x) const { + for (; x != c.size() && occurs_[c[x].var()].marked(c[x].sign()); ++x) + ; + return x; +} + +// checks if 'cl' is subsumed by one of the existing clauses and at the same time +// strengthens 'cl' if possible. +// Return: +// - true - 'cl' is subsumed +// - false - 'cl' is not subsumed but may itself subsume other clauses +// Pre: All literals of l are marked, i.e. +// for each literal l in cl, occurs_[l.var()].marked(l.sign()) == true +bool SatElite::subsumed(LitVec& cl) { + Literal l; + uint32 x = 0; + uint32 str = 0; + LitVec::size_type j = 0; + for (LitVec::size_type i = 0; i != cl.size(); ++i) { + l = cl[i]; + if (occurs_[l.var()].litMark == 0) { --str; continue; } + ClWList& cls = occurs_[l.var()].refs; // right: all clauses watching either l or ~l + WIter wj = cls.right_begin(); + for (WIter w = wj, end = cls.right_end(); w != end; ++w) { + Clause& c = *clause(*w); + if (c[0] == l) { + if ( (x = findUnmarkedLit(c, 1)) == c.size() ) { + while (w != end) { *wj++ = *w++; } + cls.shrink_right( wj ); + return true; + } + c[0] = c[x]; + c[x] = l; + occurs_[c[0].var()].addWatch(*w); + if (occurs_[c[0].var()].litMark != 0 && findUnmarkedLit(c, x+1) == c.size()) { + occurs_[c[0].var()].unmark(); // no longer part of cl + ++str; + } + } + else if ( findUnmarkedLit(c, 1) == c.size() ) { + occurs_[l.var()].unmark(); // no longer part of cl + while (w != end) { *wj++ = *w++; } + cls.shrink_right( wj ); + goto removeLit; + } + else { *wj++ = *w; } + } + cls.shrink_right(wj); + if (j++ != i) { cl[j-1] = cl[i]; } +removeLit:; + } + cl.erase(cl.begin()+j, cl.end()); + if (str > 0) { + for (LitVec::size_type i = 0; i != cl.size();) { + if (occurs_[cl[i].var()].litMark == 0) { + cl[i] = cl.back(); + cl.pop_back(); + if (--str == 0) break; + } + else { ++i; } + } + } + return false; +} + +// Pre: c contains l +// Pre: c was already removed from l's occur-list +bool SatElite::strengthenClause(uint32 clauseId, Literal l) { + Clause& c = *clause(clauseId); + if (c[0] == l) { + occurs_[c[0].var()].removeWatch(clauseId); + // Note: Clause::strengthen shifts literals after l to the left. Thus + // c[1] will be c[0] after strengthen + occurs_[c[1].var()].addWatch(clauseId); + } + ++stats.litsRemoved; + c.strengthen(l); + if (c.size() == 1) { + Literal unit = c[0]; + detach(clauseId); + return ctx_->addUnary(unit) && ctx_->master()->propagate(); + } + addToSubQueue(clauseId); + return true; +} + +// Split occurrences of v into pos and neg and +// mark all clauses containing v +SatElite::ClRange SatElite::splitOcc(Var v, bool mark) { + ClRange cls = occurs_[v].clauseRange(); + occurs_[v].dirty = 0; + occT_[pos].clear(); occT_[neg].clear(); + ClIter j = cls.first; + for (ClIter x = j; x != cls.second; ++x) { + if (Clause* c = clause(x->var())) { + assert(c->marked() == false); + c->setMarked(mark); + int sign = (int)x->sign(); + occT_[sign].push_back(x->var()); + if (j != x) *j = *x; + ++j; + } + } + occurs_[v].refs.shrink_left(j); + return occurs_[v].clauseRange(); +} + +void SatElite::markAll(const Literal* lits, uint32 size) const { + for (uint32 i = 0; i != size; ++i) { + occurs_[lits[i].var()].mark(lits[i].sign()); + } +} +void SatElite::unmarkAll(const Literal* lits, uint32 size) const { + for (uint32 i = 0; i != size; ++i) { + occurs_[lits[i].var()].unmark(); + } +} + +// Run variable and/or blocked clause elimination on var v. +// If the number of non-trivial resolvents is <= maxCnt, +// v is eliminated by clause distribution. If bce is enabled, +// clauses blocked on a literal of v are removed. +bool SatElite::bceVe(Var v, uint32 maxCnt) { + Solver* s = ctx_->master(); + if (s->value(v) != value_free) return true; + assert(!ctx_->varInfo(v).frozen() && !ctx_->eliminated(v)); + resCands_.clear(); + // distribute clauses on v + // check if number of clauses decreases if we'd eliminate v + uint32 bce = opts_->bce(); + ClRange cls = splitOcc(v, bce > 1); + uint32 cnt = 0; + uint32 markMax = ((uint32)occT_[neg].size() * (bce>1)); + uint32 blocked = 0; + bool stop = false; + Clause* lhs, *rhs; + for (VarVec::const_iterator i = occT_[pos].begin(); i != occT_[pos].end() && !stop; ++i) { + lhs = clause(*i); + markAll(&(*lhs)[0], lhs->size()); + lhs->setMarked(bce != 0); + for (VarVec::const_iterator j = occT_[neg].begin(); j != occT_[neg].end(); ++j) { + if (!trivialResolvent(*(rhs = clause(*j)), v)) { + markMax -= rhs->marked(); + rhs->setMarked(false); // not blocked on v + lhs->setMarked(false); // not blocked on v + if (++cnt <= maxCnt) { + resCands_.push_back(lhs); + resCands_.push_back(rhs); + } + else if (!markMax) { + stop = (bce == 0); + break; + } + } + } + unmarkAll(&(*lhs)[0], lhs->size()); + if (lhs->marked()) { + occT_[pos][blocked++] = *i; + } + } + if (cnt <= maxCnt) { + // eliminate v by clause distribution + ctx_->eliminate(v); // mark var as eliminated + // remove old clauses, store them in the elimination table so that + // (partial) models can be extended. + for (ClIter it = cls.first; it != cls.second; ++it) { + // reuse first cnt ids for resolvents + if (clause(it->var())) { + bool freeId = (cnt && cnt--); + bceVeRemove(it->var(), freeId, v, false); + } + } + // add non trivial resolvents + assert( resCands_.size() % 2 == 0 ); + ClIter it = cls.first; + for (VarVec::size_type i = 0; i != resCands_.size(); i+=2, ++it) { + if (!addResolvent(it->var(), *resCands_[i], *resCands_[i+1])) { + return false; + } + } + assert(occurs_[v].numOcc() == 0); + // release memory + occurs_[v].clear(); + } + else if ( (blocked + markMax) > 0 ) { + // remove blocked clauses + for (uint32 i = 0; i != blocked; ++i) { + bceVeRemove(occT_[pos][i], false, v, true); + } + for (VarVec::const_iterator it = occT_[neg].begin(); markMax; ++it) { + if ( (rhs = clause(*it))->marked() ) { + bceVeRemove(*it, false, v, true); + --markMax; + } + } + } + return opts_->limIters != 0 || backwardSubsume(); +} + +bool SatElite::bce() { + uint32 ops = 0; + for (ClWList& bce= occurs_[0].refs; bce.right_size() != 0; ++ops) { + Var v = *(bce.right_end()-1); + bce.pop_right(); + occurs_[v].bce=0; + if ((ops & 1023) == 0) { + if (timeout()) { bce.clear(); return true; } + if ((ops & 8191) == 0) { reportProgress(Progress::event_bce, ops, 1+bce.size()); } + } + if (!cutoff(v) && !bceVe(v, 0)) { return false; } + } + return true; +} + +bool SatElite::eliminateVars() { + Var v = 0; + uint32 occ = 0; + if (!bce()) return false; + for (uint32 ops = 0; !elimHeap_.empty(); ++ops) { + v = elimHeap_.top(); elimHeap_.pop(); + occ = occurs_[v].numOcc(); + if ((ops & 1023) == 0) { + if (timeout()) { elimHeap_.clear(); return true; } + if ((ops & 8191) == 0) { reportProgress(Progress::event_var_elim, ops, 1+elimHeap_.size()); } + } + if (!cutoff(v) && !bceVe(v, occ)) { + return false; + } + } + return opts_->limIters != 0 || bce(); +} + +// returns true if the result of resolving c1 (implicitly given) and c2 on v yields a tautologous clause +bool SatElite::trivialResolvent(const Clause& c2, Var v) const { + for (uint32 i = 0, end = c2.size(); i != end; ++i) { + Literal x = c2[i]; + if (occurs_[x.var()].marked(!x.sign()) && x.var() != v) { + return true; + } + } + return false; +} + +// Pre: lhs and rhs can be resolved on lhs[0].var() +// Pre: trivialResolvent(lhs, rhs, lhs[0].var()) == false +bool SatElite::addResolvent(uint32 id, const Clause& lhs, const Clause& rhs) { + resolvent_.clear(); + Solver* s = ctx_->master(); + assert(lhs[0] == ~rhs[0]); + uint32 i, end; + Literal l; + for (i = 1, end = lhs.size(); i != end; ++i) { + l = lhs[i]; + if (!s->isFalse(l)) { + if (s->isTrue(l)) goto unmark; + occurs_[l.var()].mark(l.sign()); + resolvent_.push_back(l); + } + } + for (i = 1, end = rhs.size(); i != end; ++i) { + l = rhs[i]; + if (!s->isFalse(l) && !occurs_[l.var()].marked(l.sign())) { + if (s->isTrue(l)) goto unmark; + occurs_[l.var()].mark(l.sign()); + resolvent_.push_back(l); + } + } + if (!subsumed(resolvent_)) { + if (resolvent_.empty()) { + return s->force(negLit(0)); + } + if (resolvent_.size()==1) { + occurs_[resolvent_[0].var()].unmark(); + return s->force(resolvent_[0]) && s->propagate() && propagateFacts(); + } + setClause(id, resolvent_); + attach(id, false); + return true; + } +unmark: + if (!resolvent_.empty()) { + unmarkAll(&resolvent_[0], resolvent_.size()); + } + return true; +} + +// extends the model given in assign by the vars that were eliminated +void SatElite::doExtendModel(ValueVec& m, LitVec& unconstr) { + if (!elimTop_) return; + const ValueRep value_eliminated = 4u; + // compute values of eliminated vars / blocked literals by "unit propagating" + // eliminated/blocked clauses in reverse order + uint32 uv = 0; + uint32 us = unconstr.size(); + Clause* r = elimTop_; + do { + Literal x = (*r)[0]; + Var last = x.var(); + bool check = true; + if (!r->marked()) { + // eliminated var - compute the implied value + m[last] = value_eliminated; + } + if (uv != us && unconstr[uv].var() == last) { + // last is unconstraint w.r.t the current model - + // set remembered value + check = false; + m[last] = trueValue(unconstr[uv]); + ++uv; + } + do { + Clause& c = *r; + if (m[x.var()] != trueValue(x) && check) { + for (uint32 i = 1, end = c.size(); i != end; ++i) { + ValueRep vi = m[c[i].var()] & 3u; + if (vi != falseValue(c[i])) { + x = c[i]; + break; + } + } + if (x == c[0]) { + // all lits != x are false + // clause is unit or conflicting + assert(c.marked() || m[x.var()] != falseValue(x)); + m[x.var()] = trueValue(x); + check = false; + } + } + r = r->next(); + } while (r && (x = (*r)[0]).var() == last); + if (m[last] == value_eliminated) { + // last seems unconstraint w.r.t the model + m[last] |= value_true; + unconstr.push_back(posLit(last)); + } + } while (r); + // check whether newly added unconstraint vars are really unconstraint w.r.t the model + // or if they are implied by some blocked clause. + LitVec::iterator j = unconstr.begin()+us; + for (LitVec::iterator it = j, end = unconstr.end(); it != end; ++it) { + if ((m[it->var()] & value_eliminated) != 0) { + // var is unconstraint - assign to true and remember it + // so that we can later enumerate the model containing ~var + m[it->var()] = value_true; + *j++ = *it; + } + } + unconstr.erase(j, unconstr.end()); +} +SatPreprocessor* SatPreParams::create(const SatPreParams& opts) { + if (opts.type != 0) { return new SatElite(); } + return 0; +} +} diff --git a/libclasp/src/shared_context.cpp b/libclasp/src/shared_context.cpp new file mode 100644 index 0000000..31be805 --- /dev/null +++ b/libclasp/src/shared_context.cpp @@ -0,0 +1,1121 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +#include +#if WITH_THREADS +#include +#endif +namespace Clasp { +#define PS_STATS( APPLY ) \ + APPLY(vars , VALUE(vars.num)) \ + APPLY(vars_eliminated , VALUE(vars.eliminated)) \ + APPLY(vars_frozen , VALUE(vars.frozen)) \ + APPLY(constraints , VALUE(constraints.other)) \ + APPLY(constraints_binary , VALUE(constraints.binary)) \ + APPLY(constraints_ternary, VALUE(constraints.ternary)) \ + APPLY(acyc_edges , VALUE(acycEdges)) \ + APPLY(complexity , VALUE(complexity)) + +static const char* const stats_s[] = { +#define KEY(X,Y) #X, + PS_STATS(KEY) +#undef KEY + "ctx" +}; +uint32 ProblemStats::size() { return (sizeof(stats_s)/sizeof(stats_s[0])) - 1; } +const char* ProblemStats::key(uint32 i) { return i < size() ? stats_s[i] : throw std::out_of_range("ProblemStats::key"); } +StatisticObject ProblemStats::at(const char* key) const { +#define VALUE(X) StatisticObject::value(&X) +#define APPLY(x, y) if (std::strcmp(key, #x) == 0) return y; + PS_STATS(APPLY) + throw std::out_of_range("ProblemStats::at"); +#undef VALUE +#undef APPLY +} +#undef PS_STATS +///////////////////////////////////////////////////////////////////////////////////////// +// EventHandler +///////////////////////////////////////////////////////////////////////////////////////// +uint32 Event::nextId() { static uint32 id = 0; return id++; } +EventHandler::EventHandler(Event::Verbosity verbosity) : verb_(0), sys_(0){ + if (uint32 x = verbosity) { + uint32 r = (x | (x<<4) | (x<<8) | (x<<12)); + verb_ = static_cast(r); + } +} +EventHandler::~EventHandler() {} +void EventHandler::setVerbosity(Event::Subsystem sys, Event::Verbosity verb) { + uint32 s = (uint32(sys)<(r); +} +bool EventHandler::setActive(Event::Subsystem sys) { + if (sys == static_cast(sys_)) { return false; } + sys_ = static_cast(sys); + return true; +} +Event::Subsystem EventHandler::active() const { + return static_cast(sys_); +} +///////////////////////////////////////////////////////////////////////////////////////// +// ShortImplicationsGraph::ImplicationList +///////////////////////////////////////////////////////////////////////////////////////// +#if WITH_THREADS +ShortImplicationsGraph::Block::Block() { + for (int i = 0; i != block_cap; ++i) { data[i] = lit_true(); } + size_lock = 0; + next = 0; +} +void ShortImplicationsGraph::Block::addUnlock(uint32 lockedSize, const Literal* x, uint32 xs) { + std::copy(x, x+xs, data+lockedSize); + size_lock = ((lockedSize+xs) << 1); +} +bool ShortImplicationsGraph::Block::tryLock(uint32& size) { + uint32 s = size_lock; + if ((s & 1) == 0 && size_lock.compare_and_swap(s | 1, s) == s) { + size = s >> 1; + return true; + } + return false; +} + +#define FOR_EACH_LEARNT(x, Y) \ + for (Block* b = (x).learnt; b ; b = b->next) \ + for (const Literal* Y = b->begin(), *endof = b->end(); Y != endof; Y += 2 - Y->flagged()) + + +ShortImplicationsGraph::ImplicationList::~ImplicationList() { + clear(true); +} + +void ShortImplicationsGraph::ImplicationList::clear(bool b) { + ImpListBase::clear(b); + for (Block* x = learnt; x; ) { + Block* t = x; + x = x->next; + delete t; + } + learnt = 0; +} +void ShortImplicationsGraph::ImplicationList::simplifyLearnt(const Solver& s) { + Block* x = learnt; + learnt = 0; + while (x) { + for (const Literal* Y = x->begin(), *endof = x->end(); Y != endof; Y += 2 - Y->flagged()) { + Literal p = Y[0], q = !Y->flagged() ? Y[1] : lit_false(); + if (!s.isTrue(p) && !s.isTrue(q)) { + addLearnt(p, q); + } + } + Block* t = x; + x = x->next; + delete t; + } +} +void ShortImplicationsGraph::ImplicationList::addLearnt(Literal p, Literal q) { + Literal nc[2] = {p, q}; + uint32 ns = 1 + !isSentinel(q); + if (ns == 1) { nc[0].flag(); } + for (Block* x;;) { + x = learnt; + if (x) { + uint32 lockedSize; + if (x->tryLock(lockedSize)) { + if ( (lockedSize + ns) <= Block::block_cap ) { + x->addUnlock(lockedSize, nc, ns); + } + else { + Block* t = new Block(); + t->addUnlock(0, nc, ns); + t->next = x; // x is full and remains locked forever + x = learnt= t; // publish new block - unlocks x and learnt + } + return; + } + else { + Clasp::mt::this_thread::yield(); + } + } + else { + x = new Block(); + if (learnt.compare_and_swap(x, 0) != 0) { + delete x; + } + } + } +} + +bool ShortImplicationsGraph::ImplicationList::hasLearnt(Literal q, Literal r) const { + const bool binary = isSentinel(r); + FOR_EACH_LEARNT(*this, imp) { + if (imp[0] == q || imp[0] == r) { + // binary clause subsumes new bin/tern clause + if (imp->flagged()) { return true; } + // existing ternary clause subsumes new tern clause + if (!binary && (imp[1] == q || imp[1] == r)) { return true; } + } + } + return false; +} + +void ShortImplicationsGraph::ImplicationList::move(ImplicationList& other) { + ImpListBase::move(other); + delete static_cast(learnt); + learnt = static_cast(other.learnt); + other.learnt = 0; +} +#endif +///////////////////////////////////////////////////////////////////////////////////////// +// ShortImplicationsGraph +///////////////////////////////////////////////////////////////////////////////////////// +ShortImplicationsGraph::ShortImplicationsGraph() { + bin_[0] = bin_[1] = 0; + tern_[0] = tern_[1] = 0; + shared_ = false; +} +ShortImplicationsGraph::~ShortImplicationsGraph() { + PodVector::destruct(graph_); +} +void ShortImplicationsGraph::resize(uint32 nodes) { + if (nodes <= graph_.size()) { + while (graph_.size() != nodes) { + graph_.back().clear(true); + graph_.pop_back(); + } + } + else if (graph_.capacity() >= nodes) { + graph_.resize(nodes); + } + else { + ImpLists temp; temp.resize(nodes); + for (ImpLists::size_type i = 0; i != graph_.size(); ++i) { + temp[i].move(graph_[i]); + } + graph_.swap(temp); + } +} + +uint32 ShortImplicationsGraph::numEdges(Literal p) const { return graph_[p.id()].size(); } + +bool ShortImplicationsGraph::add(ImpType t, bool learnt, const Literal* lits) { + uint32& stats= (t == ternary_imp ? tern_ : bin_)[learnt]; + Literal p = lits[0], q = lits[1], r = (t == ternary_imp ? lits[2] : lit_false()); + p.unflag(), q.unflag(), r.unflag(); + if (!shared_) { + if (learnt) { p.flag(), q.flag(), r.flag(); } + if (t == binary_imp) { + getList(~p).push_left(q); + getList(~q).push_left(p); + } + else { + getList(~p).push_right(std::make_pair(q, r)); + getList(~q).push_right(std::make_pair(p, r)); + getList(~r).push_right(std::make_pair(p, q)); + } + ++stats; + return true; + } +#if WITH_THREADS + else if (learnt && !getList(~p).hasLearnt(q, r)) { + getList(~p).addLearnt(q, r); + getList(~q).addLearnt(p, r); + if (t == ternary_imp) { + getList(~r).addLearnt(p, q); + } + ++stats; + return true; + } +#endif + return false; +} + +void ShortImplicationsGraph::remove_bin(ImplicationList& w, Literal p) { + w.erase_left_unordered(std::find(w.left_begin(), w.left_end(), p)); + w.try_shrink(); +} +void ShortImplicationsGraph::remove_tern(ImplicationList& w, Literal p) { + w.erase_right_unordered(std::find_if(w.right_begin(), w.right_end(), PairContains(p))); + w.try_shrink(); +} + +// Removes all binary clauses containing p - those are now SAT. +// Binary clauses containing ~p are unit and therefore likewise SAT. Those +// are removed when their second literal is processed. +// +// Ternary clauses containing p are SAT and therefore removed. +// Ternary clauses containing ~p are now either binary or SAT. Those that +// are SAT are removed when the satisfied literal is processed. +// All conditional binary-clauses are replaced with real binary clauses. +// Note: clauses containing p watch ~p. Those containing ~p watch p. +void ShortImplicationsGraph::removeTrue(const Solver& s, Literal p) { + assert(!shared_); + typedef ImplicationList SWL; + SWL& negPList = graph_[(~p).id()]; + SWL& pList = graph_[ (p).id()]; + // remove every binary clause containing p -> clause is satisfied + for (SWL::left_iterator it = negPList.left_begin(), end = negPList.left_end(); it != end; ++it) { + --bin_[it->flagged()]; + remove_bin(graph_[(~*it).id()], p); + } + // remove every ternary clause containing p -> clause is satisfied + for (SWL::right_iterator it = negPList.right_begin(), end = negPList.right_end(); it != end; ++it) { + --tern_[it->first.flagged()]; + remove_tern(graph_[ (~it->first).id() ], p); + remove_tern(graph_[ (~it->second).id() ], p); + } +#if WITH_THREADS + FOR_EACH_LEARNT(negPList, imp) { + graph_[(~imp[0]).id()].simplifyLearnt(s); + if (!imp->flagged()){ + --tern_[1]; + graph_[(~imp[1]).id()].simplifyLearnt(s); + } + if (imp->flagged()) { --bin_[1]; } + } +#endif + // transform ternary clauses containing ~p to binary clause + for (SWL::right_iterator it = pList.right_begin(), end = pList.right_end(); it != end; ++it) { + Literal q = it->first; + Literal r = it->second; + --tern_[q.flagged()]; + remove_tern(graph_[(~q).id()], ~p); + remove_tern(graph_[(~r).id()], ~p); + if (s.value(q.var()) == value_free && s.value(r.var()) == value_free) { + // clause is binary on dl 0 + Literal imp[2] = {q,r}; + add(binary_imp, false, imp); + } + // else: clause is SAT and removed when the satisfied literal is processed + } + graph_[(~p).id()].clear(true); + graph_[ (p).id()].clear(true); +} +#undef FOR_EACH_LEARNT +struct ShortImplicationsGraph::Propagate { + Propagate(Solver& a_s) : s(&a_s) {} + bool unary(Literal p, Literal x) const { return s->isTrue(x) || s->force(x, Antecedent(p)); } + bool binary(Literal p, Literal x, Literal y) const { + ValueRep vx = s->value(x.var()), vy; + if (vx != trueValue(x) && (vy=s->value(y.var())) != trueValue(y) && vx + vy) { + return vx != 0 ? s->force(y, Antecedent(p, ~x)) : s->force(x, Antecedent(p, ~y)); + } + return true; + } + Solver* s; +}; +struct ShortImplicationsGraph::ReverseArc { + ReverseArc(const Solver& a_s, uint32 m, Antecedent& o) : s(&a_s), out(&o), maxL(m) {} + bool unary(Literal, Literal x) const { + if (!isRevLit(*s, x, maxL)) { return true; } + *out = Antecedent(~x); + return false; + } + bool binary(Literal, Literal x, Literal y) const { + if (!isRevLit(*s, x, maxL) || !isRevLit(*s, y, maxL)) { return true; } + *out = Antecedent(~x, ~y); + return false; + } + const Solver* s; Antecedent* out; uint32 maxL; +}; +bool ShortImplicationsGraph::propagate(Solver& s, Literal p) const { return forEach(p, Propagate(s)); } +bool ShortImplicationsGraph::reverseArc(const Solver& s, Literal p, uint32 maxLev, Antecedent& out) const { return !forEach(p, ReverseArc(s, maxLev, out)); } +bool ShortImplicationsGraph::propagateBin(Assignment& out, Literal p, uint32 level) const { + const ImplicationList& x = graph_[p.id()]; + Antecedent ante(p); + for (ImplicationList::const_left_iterator it = x.left_begin(), end = x.left_end(); it != end; ++it) { + if (!out.assign(*it, level, p)) { return false; } + } + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// SatPreprocessor +///////////////////////////////////////////////////////////////////////////////////////// +SatPreprocessor::SatPreprocessor() : ctx_(0), opts_(0), elimTop_(0), seen_(1,1) {} +SatPreprocessor::~SatPreprocessor() { + discardClauses(true); +} +void SatPreprocessor::discardClauses(bool full) { + for (ClauseList::size_type i = 0; i != clauses_.size(); ++i) { + if (clauses_[i]) { clauses_[i]->destroy(); } + } + ClauseList().swap(clauses_); + if (Clause* r = (full ? elimTop_ : 0)) { + do { + Clause* t = r; + r = r->next(); + t->destroy(); + } while (r); + elimTop_ = 0; + } + if (full) { seen_ = Range32(1,1); } +} +void SatPreprocessor::cleanUp(bool full) { + if (ctx_) { seen_.hi = ctx_->numVars() + 1; } + doCleanUp(); + discardClauses(full); +} + +bool SatPreprocessor::addClause(const Literal* lits, uint32 size) { + if (size > 1) { + clauses_.push_back( Clause::newClause(lits, size) ); + } + else if (size == 1) { + units_.push_back(lits[0]); + } + else { + return false; + } + return true; +} + +void SatPreprocessor::freezeSeen() { + if (!ctx_->validVar(seen_.lo)) { seen_.lo = 1; } + if (!ctx_->validVar(seen_.hi)) { seen_.hi = ctx_->numVars() + 1; } + for (Var v = seen_.lo; v != seen_.hi; ++v) { + if (!ctx_->eliminated(v)) { ctx_->setFrozen(v, true); } + } + seen_.lo = seen_.hi; +} + +bool SatPreprocessor::preprocess(SharedContext& ctx, Options& opts) { + ctx_ = &ctx; + opts_ = &opts; + Solver* s = ctx_->master(); + struct OnExit { + SharedContext* ctx; + SatPreprocessor* self; + SatPreprocessor* rest; + OnExit(SatPreprocessor* s, SharedContext* c) : ctx(c), self(s), rest(0) { + if (ctx && ctx->satPrepro.get() == s) { rest = ctx->satPrepro.release(); } + } + ~OnExit() { + if (self) self->cleanUp(); + if (rest) ctx->satPrepro.reset(rest); + } + } onExit(this, &ctx); + for (LitVec::const_iterator it = units_.begin(), end = units_.end(); it != end; ++it) { + if (!ctx.addUnary(*it)) return false; + } + units_.clear(); + // skip preprocessing if other constraints are UNSAT + if (!s->propagate()) return false; + if (ctx.preserveModels()) { + opts.disableBce(); + } + if (ctx.preserveShown()) { + for (OutputTable::pred_iterator it = ctx.output.pred_begin(), end = ctx.output.pred_end(); it != end; ++it) { + ctx.setFrozen(it->cond.var(), true); + } + for (OutputTable::range_iterator it = ctx.output.vars_begin(), end = ctx.output.vars_end(); it != end; ++it) { + ctx.setFrozen(*it, true); + } + } + // preprocess only if not too many vars are frozen or not too many clauses + bool limFrozen = false; + if (opts.limFrozen != 0 && ctx_->stats().vars.frozen) { + uint32 varFrozen = ctx_->stats().vars.frozen; + for (LitVec::const_iterator it = s->trail().begin(), end = s->trail().end(); it != end; ++it) { + varFrozen -= (ctx_->varInfo(it->var()).frozen()); + } + limFrozen = ((varFrozen / double(s->numFreeVars())) * 100.0) > double(opts.limFrozen); + } + // 1. remove SAT-clauses, strengthen clauses w.r.t false literals, attach + if (opts.type != 0 && !opts.clauseLimit(numClauses()) && !limFrozen && initPreprocess(opts)) { + ClauseList::size_type j = 0; + for (ClauseList::size_type i = 0; i != clauses_.size(); ++i) { + Clause* c = clauses_[i]; assert(c); + clauses_[i] = 0; + c->simplify(*s); + Literal x = (*c)[0]; + if (s->value(x.var()) == value_free) { + clauses_[j++] = c; + } + else { + c->destroy(); + if (!ctx.addUnary(x)) { return false; } + } + } + clauses_.erase(clauses_.begin()+j, clauses_.end()); + // 2. run preprocessing + freezeSeen(); + if (!s->propagate() || !doPreprocess()) { + return false; + } + } + // simplify other constraints w.r.t any newly derived top-level facts + if (!s->simplify()) return false; + // 3. move preprocessed clauses to ctx + for (ClauseList::size_type i = 0; i != clauses_.size(); ++i) { + if (Clause* c = clauses_[i]) { + if (!ClauseCreator::create(*s, ClauseRep::create(&(*c)[0], c->size()), 0)) { + return false; + } + clauses_[i] = 0; + c->destroy(); + } + } + ClauseList().swap(clauses_); + return true; +} +bool SatPreprocessor::preprocess(SharedContext& ctx) { + SatPreParams opts = ctx.configuration()->context().satPre; + return preprocess(ctx, opts); +} +void SatPreprocessor::extendModel(ValueVec& m, LitVec& open) { + if (!open.empty()) { + // flip last unconstraint variable to get "next" model + open.back() = ~open.back(); + } + doExtendModel(m, open); + // remove unconstraint vars already flipped + while (!open.empty() && open.back().sign()) { + open.pop_back(); + } +} +SatPreprocessor::Clause* SatPreprocessor::Clause::newClause(const Literal* lits, uint32 size) { + assert(size > 0); + void* mem = ::operator new( sizeof(Clause) + (size-1)*sizeof(Literal) ); + return new (mem) Clause(lits, size); +} +SatPreprocessor::Clause::Clause(const Literal* lits, uint32 size) : size_(size), inQ_(0), marked_(0) { + std::memcpy(lits_, lits, size*sizeof(Literal)); +} +void SatPreprocessor::Clause::strengthen(Literal p) { + uint64 a = 0; + uint32 i, end; + for (i = 0; lits_[i] != p; ++i) { a |= Clause::abstractLit(lits_[i]); } + for (end = size_-1; i < end; ++i) { lits_[i] = lits_[i+1]; a |= Clause::abstractLit(lits_[i]); } + --size_; + data_.abstr = a; +} +void SatPreprocessor::Clause::simplify(Solver& s) { + uint32 i; + for (i = 0; i != size_ && s.value(lits_[i].var()) == value_free; ++i) {;} + if (i == size_) { return; } + else if (s.isTrue(lits_[i])){ std::swap(lits_[i], lits_[0]); return; } + uint32 j = i++; + for (; i != size_; ++i) { + if (s.isTrue(lits_[i])) { std::swap(lits_[i], lits_[0]); return; } + if (!s.isFalse(lits_[i])) { lits_[j++] = lits_[i]; } + } + size_ = j; +} +void SatPreprocessor::Clause::destroy() { + void* mem = this; + this->~Clause(); + ::operator delete(mem); +} +///////////////////////////////////////////////////////////////////////////////////////// +// ConstString +///////////////////////////////////////////////////////////////////////////////////////// +struct StrRef { + typedef Atomic_t::type RefCount; + static uint64 lit(const char* str) { + if (!str) str = ""; + return set_bit(static_cast(reinterpret_cast(str)), 63); + } + static uint64 create(const char* str, std::size_t len) { + char* mem = (char*)malloc(sizeof(RefCount) + len + 1); + RefCount* p = new (mem) RefCount(); + std::memcpy(mem + sizeof(RefCount), str, len); + mem[sizeof(RefCount) + len] = 0; + *p = 1; + return static_cast(reinterpret_cast(mem)); + } + static RefCount* asShared(uint64 ref) { + return !test_bit(ref, 63) ? reinterpret_cast(static_cast(ref)) : 0; + } + static uint64 share(uint64 ref) { + if (RefCount* p = asShared(ref)) { ++*p; } + return ref; + } + static uint64 release(uint64 ref) { + RefCount* p = asShared(ref); + if (p && !--*p) { + p->~RefCount(); + free((void*)p); + } + return 0; + } + static const char* get(uint64 ref) { + return reinterpret_cast(static_cast( + !test_bit(ref, 63) + ? ref + sizeof(RefCount) + : clear_bit(ref, 63))); + } +}; +ConstString::ConstString(const char* str, Ownership_t::Type o) : ref_(str && *str && o == Ownership_t::Acquire ? StrRef::create(str, std::strlen(str)) : StrRef::lit(str)) {} +ConstString::ConstString(const StrView& str) : ref_(str.size ? StrRef::create(str.first, str.size) : StrRef::lit("")) {} +ConstString::ConstString(const ConstString& other) : ref_(StrRef::share(other.ref_)) { } +ConstString::~ConstString() { StrRef::release(ref_); } +void ConstString::swap(ConstString& rhs) { std::swap(ref_, rhs.ref_); } +ConstString& ConstString::operator=(const ConstString& rhs) { + ConstString temp(rhs); + swap(temp); + return *this; +} +const char* ConstString::c_str() const { return StrRef::get(ref_); } +///////////////////////////////////////////////////////////////////////////////////////// +// OutputTable +///////////////////////////////////////////////////////////////////////////////////////// +OutputTable::OutputTable() : theory(0), vars_(0, 0), hide_(0) {} +OutputTable::~OutputTable() { + PodVector::destruct(facts_); + PodVector::destruct(preds_); +} + +void OutputTable::setFilter(char c) { + hide_ = c; +} +bool OutputTable::filter(const NameType& n) const { + char c = *n; + return c == hide_ || !c; +} +bool OutputTable::add(const NameType& fact) { + if (!filter(fact)) { + facts_.push_back(fact); + return true; + } + return false; +} + +bool OutputTable::add(const NameType& n, Literal c, uint32 u) { + if (!filter(n)) { + PredType p = {n, c, u}; + preds_.push_back(p); + return true; + } + return false; +} + +void OutputTable::setVarRange(const RangeType& r) { + CLASP_ASSERT_CONTRACT(r.lo <= r.hi); + vars_ = r; +} +void OutputTable::addProject(Literal x) { + proj_.push_back(x); +} + +uint32 OutputTable::size() const { + return numFacts() + numPreds() + numVars(); +} +OutputTable::Theory::~Theory() {} +///////////////////////////////////////////////////////////////////////////////////////// +// DomainTable +///////////////////////////////////////////////////////////////////////////////////////// +DomainTable::ValueType::ValueType(Var v, DomModType t, int16 bias, uint16 prio, Literal cond) + : cond_(cond.id()) + , comp_(t == DomModType::True || t == DomModType::False) + , var_(v) + , type_(uint32(t) <= 3u ? t : uint32(t == DomModType::False)) + , bias_(bias) + , prio_(prio) { +} +DomModType DomainTable::ValueType::type() const { return static_cast(comp_ == 0 ? type_ : uint32(DomModType::True + type_)); } +DomainTable::DomainTable() : domRec(0), seen_(0) {} +void DomainTable::add(Var v, DomModType t, int16 b, uint16 p, Literal c) { + if (c != lit_false() && (t != DomModType::Init || c == lit_true())) { + entries_.push_back(ValueType(v, t, b, p, c)); + } +} +uint32 DomainTable::simplify() { + if (seen_ >= size()) { return size(); } + std::stable_sort(entries_.begin() + seen_, entries_.end(), cmp); + DomVec::iterator j = entries_.begin() + seen_; + for (DomVec::const_iterator it = j, end = entries_.end(), n; it != end; it = n) { + Var v = it->var(); + Literal c = it->cond(); + for (n = it + 1; n != end && n->var() == v && n->cond() == c; ) { ++n; } + if ((n - it) == 1) { + *j++ = *it; + } + else { + static_assert(DomModType::Level == 0 && DomModType::Sign == 1 && DomModType::True == 4, "check enumeration constants"); + enum { n_simp = 4u }; + int const mod_level = DomModType::Level, mod_sign = DomModType::Sign; + int16 const NO_BIAS = INT16_MAX; + uint16 prio[n_simp] ={0, 0, 0, 0}; + int16 bias[n_simp] ={NO_BIAS, NO_BIAS, NO_BIAS, NO_BIAS}; + for (; it != n; ++it) { + if (!it->comp() && it->prio() >= prio[it->type()]) { + bias[it->type()] = it->bias(); + prio[it->type()] = it->prio(); + } + else if (it->comp()) { + if (it->prio() >= prio[mod_level]) { + bias[mod_level] = it->bias(); + prio[mod_level] = it->prio(); + } + if (it->prio() >= prio[mod_sign]) { + bias[mod_sign] = it->type() == DomModType::True ? 1 : -1; + prio[mod_sign] = it->prio(); + } + } + } + int s = 0; + if (bias[mod_level] != NO_BIAS && bias[mod_sign] != NO_BIAS && bias[mod_sign] && prio[mod_level] == prio[mod_sign]) { + *j++ = ValueType(v, bias[mod_sign] > 0 ? DomModType::True : DomModType::False, bias[mod_level], prio[mod_level], c); + s = mod_sign + 1; + } + for (int t = s; t != n_simp; ++t) { + if (bias[t] != NO_BIAS) { + *j++ = ValueType(v, static_cast(t), bias[t], prio[t], c); + } + } + } + } + entries_.erase(j, entries_.end()); + if (entries_.capacity() > static_cast(entries_.size() * 1.75)) { + DomVec(entries_).swap(entries_); + } + return (seen_ = size()); +} +void DomainTable::reset() { + DomVec().swap(entries_); + domRec = 0; +} +bool DomainTable::empty() const { return entries_.empty(); } +uint32 DomainTable::size() const { return static_cast(entries_.size()); } +DomainTable::iterator DomainTable::begin() const { return entries_.begin(); } +DomainTable::iterator DomainTable::end() const { return entries_.end(); } +///////////////////////////////////////////////////////////////////////////////////////// +// SharedContext::Minimize +///////////////////////////////////////////////////////////////////////////////////////// +struct SharedContext::Minimize { + typedef SingleOwnerPtr ProductPtr; + void add(weight_t p, const WeightLiteral& lit) { + builder.add(p, lit); + } + bool reset() const { + if (product.get()) { product->resetBounds(); } + return true; + } + SharedMinimizeData* get(SharedContext& ctx) { + if (builder.empty()) { return product.get(); } + if (product.get()) { + builder.add(*product); + product = 0; + } + return (product = builder.build(ctx)).get(); + } + MinimizeBuilder builder; + ProductPtr product; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// SharedContext +///////////////////////////////////////////////////////////////////////////////////////// +static BasicSatConfig config_def_s; +SharedContext::SharedContext() + : mini_(0), progress_(0), lastTopLevel_(0) { + // sentinel always present + setFrozen(addVar(Var_t::Atom, 0), true); + stats_.vars.num = 0; + config_ = &config_def_s; + config_.release(); + pushSolver(); +} + +bool SharedContext::ok() const { return master()->decisionLevel() || !master()->hasConflict() || master()->hasStopConflict(); } +void SharedContext::enableStats(uint32 lev) { + if (lev > 0) { master()->stats.enableExtended(); } +} +SharedContext::~SharedContext() { + while (!solvers_.empty()) { delete solvers_.back(); solvers_.pop_back(); } + delete mini_; +} + +void SharedContext::reset() { + this->~SharedContext(); + new (this) SharedContext(); +} + +void SharedContext::setConcurrency(uint32 n, ResizeMode mode) { + if (n <= 1) { share_.count = 1; } + else { share_.count = n; solvers_.reserve(n); } + while (solvers_.size() < share_.count && (mode & resize_push) != 0u) { + pushSolver(); + } + while (solvers_.size() > share_.count && (mode & resize_pop) != 0u) { + delete solvers_.back(); + solvers_.pop_back(); + } + if ((share_.shareM & ContextParams::share_auto) != 0) { + setShareMode(ContextParams::share_auto); + } +} + +void SharedContext::setShareMode(ContextParams::ShareMode m) { + if ( (share_.shareM = static_cast(m)) == ContextParams::share_auto && share_.count > 1) { + share_.shareM |= static_cast(ContextParams::share_all); + } +} +void SharedContext::setShortMode(ContextParams::ShortMode m) { + share_.shortM = static_cast(m); +} + +void SharedContext::setPreproMode(uint32 m, bool b) { + share_.satPreM &= ~m; + if (b) { share_.satPreM |= m; } +} + +Solver& SharedContext::pushSolver() { + uint32 id = (uint32)solvers_.size(); + share_.count = std::max(share_.count, id + 1); + Solver* s = new Solver(this, id); + solvers_.push_back(s); + return *s; +} + +void SharedContext::setConfiguration(Configuration* c, Ownership_t::Type ownership) { + bool own = ownership == Ownership_t::Acquire; + if (c == 0) { c = &config_def_s; own = false; } + report(Event::subsystem_facade); + if (config_.get() != c) { + config_ = c; + if (!own) config_.release(); + config_->prepare(*this); + const ContextParams& opts = config_->context(); + setShareMode(static_cast(opts.shareMode)); + setShortMode(static_cast(opts.shortMode)); + share_.seed = opts.seed; + if (satPrepro.get() == 0 && opts.satPre.type != SatPreParams::sat_pre_no) { + satPrepro.reset(SatPreParams::create(opts.satPre)); + } + enableStats(opts.stats); + // force update on next call to Solver::startInit() + for (uint32 i = 0; i != solvers_.size(); ++i) { + solvers_[i]->resetConfig(); + } + } + else if (own != config_.is_owner()) { + if (own) config_.acquire(); + else config_.release(); + } +} + +bool SharedContext::unfreeze() { + if (frozen()) { + share_.frozen = 0; + share_.winner = 0; + heuristic.domRec = 0; + btig_.markShared(false); + return master()->popRootLevel(master()->rootLevel()) + && btig_.propagate(*master(), lit_true()) // any newly learnt facts + && unfreezeStep() + && (!mini_ || mini_->reset()); + } + return true; +} + +bool SharedContext::unfreezeStep() { + Var tag = step_.var(); + for (SolverVec::size_type i = solvers_.size(); i--;) { + Solver& s = *solvers_[i]; + share_.frozen = i > 0; + if (!s.validVar(tag)) { continue; } + s.endStep(lastTopLevel_, configuration()->solver(s.id())); + } + if (tag) { + varInfo_[tag] = VarInfo(); + step_ = lit_false(); + popVars(1); + ++stats_.vars.num; + } + return !master()->hasConflict(); +} + +Var SharedContext::addVars(uint32 nVars, VarType t, uint8 flags) { + flags &= ~3u; + flags |= VarInfo::flags(t); + varInfo_.insert(varInfo_.end(), nVars, VarInfo(flags)); + stats_.vars.num += nVars; + return static_cast(varInfo_.size() - nVars); +} + +void SharedContext::popVars(uint32 nVars) { + CLASP_ASSERT_CONTRACT_MSG(!frozen(), "Cannot pop vars from frozen program"); + CLASP_FAIL_IF(nVars > numVars(), "Invalid parameter"); + uint32 newVars = numVars() - nVars; + uint32 comVars = master()->numVars(); + if (newVars >= comVars) { + // vars not yet committed + varInfo_.erase(varInfo_.end() - nVars, varInfo_.end()); + stats_.vars.num -= nVars; + } + else { + for (Var v = numVars(); v && nVars; --nVars, --v) { + stats_.vars.eliminated -= eliminated(v); + stats_.vars.frozen -= varInfo(v).frozen(); + --stats_.vars.num; + varInfo_.pop_back(); + } + btig_.resize((numVars()+1)<<1); + for (SolverVec::size_type i = solvers_.size(); i--;) { + solvers_[i]->updateVars(); + } + lastTopLevel_ = std::min(lastTopLevel_, master()->assign_.front); + } +} + +void SharedContext::setSolveMode(SolveMode m) { share_.solveM = m; } +void SharedContext::requestStepVar() { if (step_ == lit_true()) { step_ = lit_false(); } } +void SharedContext::setFrozen(Var v, bool b) { + assert(validVar(v)); + if (v && b != varInfo_[v].has(VarInfo::Frozen)) { + varInfo_[v].toggle(VarInfo::Frozen); + b ? ++stats_.vars.frozen : --stats_.vars.frozen; + } +} + +bool SharedContext::eliminated(Var v) const { + assert(validVar(v)); + return !master()->assign_.valid(v); +} + +void SharedContext::eliminate(Var v) { + assert(validVar(v) && !frozen() && master()->decisionLevel() == 0); + if (!eliminated(v)) { + ++stats_.vars.eliminated; + // eliminate var from assignment - no longer a decision variable! + master()->assign_.eliminate(v); + } +} + +Literal SharedContext::addStepLit() { + VarInfo nv; nv.set(VarInfo::Frozen); + varInfo_.push_back(nv); + btig_.resize((numVars() + 1) << 1); + return posLit(master()->pushAuxVar()); +} +Solver& SharedContext::startAddConstraints(uint32 constraintGuess) { + if (!unfreeze()) { return *master(); } + btig_.resize((numVars() + 1 + uint32(step_ == lit_false() || solveMode() == solve_multi))<<1); + master()->startInit(constraintGuess, configuration()->solver(0)); + return *master(); +} +bool SharedContext::addUnary(Literal x) { + CLASP_ASSERT_CONTRACT(!frozen() || !isShared()); + return master()->force(x); +} +bool SharedContext::addBinary(Literal x, Literal y) { + CLASP_ASSERT_CONTRACT(allowImplicit(Constraint_t::Static)); + Literal lits[2] = {x, y}; + return ClauseCreator::create(*master(), ClauseRep(lits, 2), ClauseCreator::clause_force_simplify); +} +bool SharedContext::addTernary(Literal x, Literal y, Literal z) { + CLASP_ASSERT_CONTRACT(allowImplicit(Constraint_t::Static)); + Literal lits[3] = {x, y, z}; + return ClauseCreator::create(*master(), ClauseRep(lits, 3), ClauseCreator::clause_force_simplify); +} +void SharedContext::add(Constraint* c) { + CLASP_ASSERT_CONTRACT(!frozen()); + master()->add(c); +} +void SharedContext::addMinimize(WeightLiteral x, weight_t p) { + if (!mini_) { mini_ = new Minimize(); } + mini_->add(p, x); +} +bool SharedContext::hasMinimize() const { + return mini_ != 0; +} +void SharedContext::removeMinimize() { + delete mini_; + mini_ = 0; +} +SharedMinimizeData* SharedContext::minimize() { + return mini_ ? mini_->get(*this) : 0; +} +int SharedContext::addImp(ImpGraph::ImpType t, const Literal* lits, ConstraintType ct) { + if (!allowImplicit(ct)) { return -1; } + bool learnt = ct != Constraint_t::Static; + if (!learnt && !frozen() && satPrepro.get()) { + satPrepro->addClause(lits, static_cast(t)); + return 1; + } + return int(btig_.add(t, learnt, lits)); +} + +uint32 SharedContext::numConstraints() const { return numBinary() + numTernary() + sizeVec(master()->constraints_); } + +bool SharedContext::endInit(bool attachAll) { + assert(!frozen()); + report(Event::subsystem_prepare); + initStats(*master()); + heuristic.simplify(); + SatPrePtr temp; + satPrepro.swap(temp); + bool ok = !master()->hasConflict() && master()->preparePost() && (!temp.get() || temp->preprocess(*this)) && master()->endInit(); + satPrepro.swap(temp); + master()->dbIdx_ = (uint32)master()->constraints_.size(); + lastTopLevel_ = (uint32)master()->assign_.front; + stats_.constraints.other = sizeVec(master()->constraints_); + stats_.constraints.binary = btig_.numBinary(); + stats_.constraints.ternary= btig_.numTernary(); + stats_.acycEdges = extGraph.get() ? extGraph->edges() : 0; + stats_.complexity = std::max(stats_.complexity, problemComplexity()); + if (ok && step_ == lit_false()) { + step_ = addStepLit(); + } + btig_.markShared(concurrency() > 1); + share_.frozen = 1; + for (uint32 i = ok && attachAll ? 1 : concurrency(); i != concurrency(); ++i) { + if (!hasSolver(i)) { pushSolver(); } + if (!attach(i)) { ok = false; break; } + } + return ok || (detach(*master(), false), master()->setStopConflict(), false); +} + +bool SharedContext::attach(Solver& other) { + assert(frozen() && other.shared_ == this); + if (other.validVar(step_.var())) { + if (!other.popRootLevel(other.rootLevel())){ return false; } + if (&other == master()) { return true; } + } + initStats(other); + // 1. clone vars & assignment + Var lastVar = other.numVars(); + other.startInit(static_cast(master()->constraints_.size()), configuration()->solver(other.id())); + Antecedent null; + for (LitVec::size_type i = 0, end = master()->trail().size(); i != end; ++i) { + if (!other.force(master()->trail()[i], null)) { return false; } + } + for (Var v = satPrepro.get() ? lastVar+1 : varMax, end = master()->numVars(); v <= end; ++v) { + if (eliminated(v) && other.value(v) == value_free) { + other.assign_.eliminate(v); + } + } + if (other.constraints_.empty()) { other.lastSimp_ = master()->lastSimp_; } + // 2. clone & attach constraints + if (!other.cloneDB(master()->constraints_)) { + return false; + } + Constraint* c = master()->enumerationConstraint(); + other.setEnumerationConstraint( c ? c->cloneAttach(other) : 0 ); + // 3. endInit + return (other.preparePost() && other.endInit()) || (detach(other, false), false); +} + +void SharedContext::detach(Solver& s, bool reset) { + assert(s.shared_ == this); + if (reset) { s.reset(); } + s.setEnumerationConstraint(0); + s.popAuxVar(); +} +void SharedContext::initStats(Solver& s) const { + s.stats.enable(master()->stats); + s.stats.reset(); +} +SolverStats& SharedContext::solverStats(uint32 sId) const { + CLASP_FAIL_IF(!hasSolver(sId), "solver id out of range"); + return solver(sId)->stats; +} +const SolverStats& SharedContext::accuStats(SolverStats& out) const { + for (uint32 i = 0; i != solvers_.size(); ++i) { + out.accu(solvers_[i]->stats, true); + } + return out; +} +void SharedContext::warn(const char* what) const { + if (progress_) { + progress_->dispatch(LogEvent(progress_->active(), Event::verbosity_quiet, LogEvent::Warning, 0, what)); + } +} +void SharedContext::report(const char* what, const Solver* s) const { + if (progress_) { + progress_->dispatch(LogEvent(progress_->active(), Event::verbosity_high, LogEvent::Message, s, what)); + } +} +void SharedContext::report(Event::Subsystem sys) const { + if (progress_ && progress_->setActive(sys)) { + const char* m = ""; + Event::Verbosity v = Event::verbosity_high; + switch(sys) { + default: return; + case Event::subsystem_load: m = "Reading"; break; + case Event::subsystem_prepare: m = "Preprocessing"; break; + case Event::subsystem_solve: m = "Solving"; v = Event::verbosity_low; break; + } + progress_->onEvent(LogEvent(sys, v, LogEvent::Message, 0, m)); + } +} +void SharedContext::simplify(bool shuffle) { + Solver::ConstraintDB& db = master()->constraints_; + if (concurrency() == 1 || master()->dbIdx_ == 0) { + Clasp::simplifyDB(*master(), db, shuffle); + } + else { + uint32 rem = 0; + for (Solver::ConstraintDB::size_type i = 0, end = db.size(); i != end; ++i) { + Constraint* c = db[i]; + if (c->simplify(*master(), shuffle)) { c->destroy(master(), false); db[i] = 0; ++rem; } + } + if (rem) { + for (SolverVec::size_type s = 1; s != solvers_.size(); ++s) { + Solver& x = *solvers_[s]; + CLASP_FAIL_IF(x.dbIdx_ > db.size(), "Invalid DB idx!"); + if (x.dbIdx_ == db.size()) { x.dbIdx_ -= rem; } + else if (x.dbIdx_ != 0) { x.dbIdx_ -= (uint32)std::count_if(db.begin(), db.begin()+x.dbIdx_, IsNull()); } + } + db.erase(std::remove_if(db.begin(), db.end(), IsNull()), db.end()); + } + } + master()->dbIdx_ = sizeVec(db); +} +void SharedContext::removeConstraint(uint32 idx, bool detach) { + Solver::ConstraintDB& db = master()->constraints_; + CLASP_ASSERT_CONTRACT(idx < db.size()); + Constraint* c = db[idx]; + for (SolverVec::size_type s = 1; s != solvers_.size(); ++s) { + Solver& x = *solvers_[s]; + x.dbIdx_ -= (idx < x.dbIdx_); + } + db.erase(db.begin()+idx); + master()->dbIdx_ = sizeVec(db); + c->destroy(master(), detach); +} + +void SharedContext::simplifyShort(const Solver& s, Literal p) { + if (!isShared() && p.id() < btig_.size()) { btig_.removeTrue(s, p); } +} + +uint32 SharedContext::problemComplexity() const { + if (isExtended()) { + uint32 r = numBinary() + numTernary(); + for (uint32 i = 0; i != master()->constraints_.size(); ++i) { + r += master()->constraints_[i]->estimateComplexity(*master()); + } + return r; + } + return numConstraints(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Distributor +///////////////////////////////////////////////////////////////////////////////////////// +Distributor::Distributor(const Policy& p) : policy_(p) {} +Distributor::~Distributor() {} + +} diff --git a/libclasp/src/solve_algorithms.cpp b/libclasp/src/solve_algorithms.cpp new file mode 100644 index 0000000..748369f --- /dev/null +++ b/libclasp/src/solve_algorithms.cpp @@ -0,0 +1,433 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// Basic solve +///////////////////////////////////////////////////////////////////////////////////////// +struct BasicSolve::State { + typedef BasicSolveEvent EventType; + typedef SingleOwnerPtr BlockPtr; + State(Solver& s, const SolveParams& p); + ValueRep solve(Solver& s, const SolveParams& p, SolveLimits* lim); + uint64 dbGrowNext; + double dbMax; + double dbHigh; + ScheduleStrategy dbRed; + BlockPtr rsBlock; + uint32 nRestart; + uint32 nGrow; + uint32 dbRedInit; + uint32 dbPinned; + uint32 rsShuffle; +}; + +BasicSolve::BasicSolve(Solver& s, const SolveLimits& lim) : solver_(&s), params_(&s.searchConfig()), limits_(lim), state_(0) {} +BasicSolve::BasicSolve(Solver& s, const SolveParams& p, const SolveLimits& lim) + : solver_(&s) + , params_(&p) + , limits_(lim) + , state_(0) { +} + +BasicSolve::~BasicSolve(){ delete state_; } +void BasicSolve::reset(bool reinit) { + if (!state_ || reinit) { + delete state_; + state_ = 0; + } + else { + state_->~State(); + new (state_) State(*solver_, *params_); + } +} +void BasicSolve::reset(Solver& s, const SolveParams& p, const SolveLimits& lim) { + solver_ = &s; + params_ = &p; + limits_ = lim; + reset(true); +} + +ValueRep BasicSolve::solve() { + if (limits_.reached()) { return value_free; } + if (!state_ && !params_->randomize(*solver_)){ return value_false; } + if (!state_) { state_ = new State(*solver_, *params_); } + return state_->solve(*solver_, *params_, hasLimit() ? &limits_ : 0); +} + +bool BasicSolve::satisfiable(const LitVec& path, bool init) { + if (!solver_->clearAssumptions() || !solver_->pushRoot(path)){ return false; } + if (init && !params_->randomize(*solver_)) { return false; } + State temp(*solver_, *params_); + return temp.solve(*solver_, *params_, 0) == value_true; +} + +bool BasicSolve::assume(const LitVec& path) { + return solver_->pushRoot(path); +} + +BasicSolve::State::State(Solver& s, const SolveParams& p) { + Range32 dbLim= p.reduce.sizeInit(*s.sharedContext()); + dbGrowNext = p.reduce.growSched.current(); + dbMax = dbLim.lo; + dbHigh = dbLim.hi; + dbRed = p.reduce.cflSched; + nRestart = 0; + nGrow = 0; + dbRedInit = p.reduce.cflInit(*s.sharedContext()); + dbPinned = 0; + rsShuffle = p.restart.shuffle; + if (dbLim.lo < s.numLearntConstraints()) { + dbMax = std::min(dbHigh, double(s.numLearntConstraints() + p.reduce.initRange.lo)); + } + if (dbRedInit && dbRed.type != ScheduleStrategy::Luby) { + if (dbRedInit < dbRed.base) { + dbRedInit = std::min(dbRed.base, std::max(dbRedInit,(uint32)5000)); + dbRed.grow = dbRedInit != dbRed.base ? std::min(dbRed.grow, dbRedInit/2.0f) : dbRed.grow; + dbRed.base = dbRedInit; + } + dbRedInit = 0; + } + if (p.restart.dynamic()) { + s.stats.enableLimit(p.restart.sched.base); + s.stats.limit->reset(); + } + if (p.restart.blockScale > 0.0f && p.restart.blockWindow > 0) { + rsBlock.reset(new BlockLimit(p.restart.blockWindow, p.restart.blockScale)); + rsBlock->inc = std::max(p.restart.sched.base, uint32(50)); + rsBlock->next = std::max(p.restart.blockWindow, p.restart.blockFirst); + } + s.stats.lastRestart = s.stats.analyzed; +} + +ValueRep BasicSolve::State::solve(Solver& s, const SolveParams& p, SolveLimits* lim) { + assert(!lim || !lim->reached()); + if (s.hasConflict() && s.decisionLevel() == s.rootLevel()) { + return value_false; + } + struct ConflictLimits { + uint64 reduce; // current reduce limit + uint64 grow; // current limit for next growth operation + uint64 restart; // current restart limit + uint64 global; // current global limit + uint64 min() const { return std::min(std::min(reduce, grow), std::min(restart, global)); } + void update(uint64 x) { reduce -= x; grow -= x; restart -= x; global -= x; } + }; + WeightLitVec inDegree; + SearchLimits sLimit; + ScheduleStrategy rs = p.restart.sched; + ScheduleStrategy dbGrow = p.reduce.growSched; + Solver::DBInfo db = {0,0,dbPinned}; + ValueRep result = value_free; + ConflictLimits cLimit = {dbRed.current() + dbRedInit, dbGrowNext, UINT64_MAX, lim ? lim->conflicts : UINT64_MAX}; + uint64 limRestarts = lim ? lim->restarts : UINT64_MAX; + if (!dbGrow.disabled()) { dbGrow.advanceTo(nGrow); } + if (nRestart == UINT32_MAX && p.restart.update() == RestartParams::seq_disable) { + sLimit = SearchLimits(); + } + else if (p.restart.dynamic() && s.stats.limit) { + if (!nRestart) { s.stats.limit->init((float)p.restart.sched.grow, DynamicLimit::lbd_limit); } + sLimit.restart.dynamic = s.stats.limit; + sLimit.restart.conflicts = s.stats.limit->adjust.limit - std::min(s.stats.limit->adjust.samples, s.stats.limit->adjust.limit - 1); + } + else { + rs.advanceTo(!rs.disabled() ? nRestart : 0); + sLimit.restart.conflicts = rs.current(); + } + sLimit.restart.local = p.restart.local(); + sLimit.restart.block = rsBlock.get(); + if (p.reduce.memMax) { + sLimit.memory = static_cast(p.reduce.memMax)<<20; + } + uint64 n = 0; + for (EventType progress(s, EventType::event_restart, 0, 0); cLimit.global; ) { + cLimit.restart = !p.restart.local() ? sLimit.restart.conflicts : UINT64_MAX; + sLimit.used = 0; + sLimit.learnts = (uint32)std::min(dbMax + (db.pinned*p.reduce.strategy.noGlue), dbHigh); + sLimit.conflicts = cLimit.min(); assert(sLimit.conflicts); + progress.cLimit = sLimit.conflicts; + progress.lLimit = sLimit.learnts; + if (progress.op) { s.sharedContext()->report(progress); progress.op = (uint32)EventType::event_none; } + result = s.search(sLimit, p.randProb); + cLimit.update(n = std::min(sLimit.used, sLimit.conflicts)); // number of conflicts in this iteration + if (result != value_free) { + progress.op = static_cast(EventType::event_exit); + if (result == value_true && p.restart.update() != RestartParams::seq_continue) { + if (p.restart.update() == RestartParams::seq_repeat) { nRestart = 0; } + else if (p.restart.update() == RestartParams::seq_disable){ nRestart = UINT32_MAX; } + } + if (!dbGrow.disabled()) { dbGrowNext = std::max(cLimit.grow, uint64(1)); } + s.sharedContext()->report(progress); + break; + } + if (s.restartReached(sLimit)) { + // restart reached - do restart + ++nRestart; + if (p.restart.counterRestart && (nRestart % p.restart.counterRestart) == 0 ) { + inDegree.clear(); + s.heuristic()->bump(s, inDegree, p.restart.counterBump / (double)s.inDegree(inDegree)); + } + if (sLimit.restart.dynamic) { + n = sLimit.restart.dynamic->runLen(); + sLimit.restart.conflicts = sLimit.restart.dynamic->restart(rs.len ? rs.len : UINT32_MAX, (float)rs.grow); + } + else { + sLimit.restart.conflicts = n = rs.next(); + } + s.restart(); + if (p.reduce.strategy.fRestart){ db = s.reduceLearnts(p.reduce.fRestart(), p.reduce.strategy); } + if (nRestart == rsShuffle) { rsShuffle+= p.restart.shuffleNext; s.shuffleOnNextSimplify();} + if (--limRestarts == 0) { break; } + s.stats.lastRestart = s.stats.analyzed; + progress.op = (uint32)EventType::event_restart; + } + else if (!p.restart.local()) { + sLimit.restart.conflicts -= std::min(n, sLimit.restart.conflicts); + } + if (cLimit.reduce == 0 || s.reduceReached(sLimit)) { + // reduction reached - remove learnt constraints + db = s.reduceLearnts(p.reduce.fReduce(), p.reduce.strategy); + cLimit.reduce = dbRedInit + (cLimit.reduce == 0 ? dbRed.next() : dbRed.current()); + progress.op = std::max(progress.op, (uint32)EventType::event_deletion); + if (s.reduceReached(sLimit) || db.pinned >= dbMax) { + ReduceStrategy t; t.algo = 2; t.score = 2; t.glue = 0; + db.pinned /= 2; + db.size = s.reduceLearnts(0.5f, t).size; + if (db.size >= sLimit.learnts) { dbMax = std::min(dbMax + std::max(100.0, s.numLearntConstraints()/10.0), dbHigh); } + } + } + if (cLimit.grow == 0 || (dbGrow.defaulted() && progress.op == (uint32)EventType::event_restart)) { + // grow sched reached - increase max db size + if (cLimit.grow == 0) { cLimit.grow = n = dbGrow.next(); ++nGrow; } + if ((s.numLearntConstraints() + n) > dbMax){ dbMax *= p.reduce.fGrow; progress.op = std::max(progress.op, (uint32)EventType::event_grow); } + if (dbMax > dbHigh) { dbMax = dbHigh; cLimit.grow = UINT64_MAX; dbGrow = ScheduleStrategy::none(); } + } + } + dbPinned = db.pinned; + s.stats.lastRestart = s.stats.analyzed - s.stats.lastRestart; + if (lim) { + if (lim->conflicts != UINT64_MAX) { lim->conflicts = cLimit.global; } + if (lim->restarts != UINT64_MAX) { lim->restarts = limRestarts; } + } + return result; +} +///////////////////////////////////////////////////////////////////////////////////////// +// SolveAlgorithm +///////////////////////////////////////////////////////////////////////////////////////// +SolveAlgorithm::SolveAlgorithm(const SolveLimits& lim) : limits_(lim), ctx_(0), enum_(0), onModel_(0), enumLimit_(UINT64_MAX), time_(0.0), last_(0) { +} +SolveAlgorithm::~SolveAlgorithm() {} +void SolveAlgorithm::setEnumerator(Enumerator& e) { + enum_.reset(&e); + enum_.release(); +} +const Model& SolveAlgorithm::model() const { + return enum_->lastModel(); +} +bool SolveAlgorithm::interrupt() { + return doInterrupt(); +} +bool SolveAlgorithm::attach(SharedContext& ctx, ModelHandler* onModel) { + CLASP_FAIL_IF(ctx_, "SolveAlgorithm is already running!"); + if (!ctx.frozen()) { ctx.endInit(); } + ctx.report(Event::subsystem_solve); + if (ctx.master()->hasConflict() || !limits_.conflicts || interrupted()) { + last_ = !ctx.ok() ? value_false : value_free; + return false; + } + ctx_ = &ctx; + time_ = ThreadTime::getTime(); + onModel_ = onModel; + last_ = value_free; + if (!enum_.get()) { enum_ = EnumOptions::nullEnumerator(); } + return true; +} +void SolveAlgorithm::detach() { + if (ctx_) { + ctx_->master()->stats.addCpuTime(ThreadTime::getTime() - time_); + onModel_ = 0; + ctx_ = 0; + path_ = 0; + } +} + +bool SolveAlgorithm::solve(SharedContext& ctx, const LitVec& assume, ModelHandler* onModel) { + struct Scoped { + Scoped(SolveAlgorithm* s) : self(s) {} + ~Scoped() { self->detach(); } + bool solve(const LitVec& assume) { + if (self->maxModels() != UINT64_MAX) { + if (self->enumerator().optimize() && !self->enumerator().tentative()) { + self->ctx().warn("#models not 0: optimality of last model not guaranteed."); + } + if (self->enumerator().lastModel().consequences()) { + self->ctx().warn("#models not 0: last model may not cover consequences."); + } + } + self->path_.reset(&assume); + self->path_.release(); + return self->doSolve(self->ctx(), assume); + } + SolveAlgorithm* self; + }; + return attach(ctx, onModel) ? Scoped(this).solve(assume) : ctx.ok(); +} + +void SolveAlgorithm::start(SharedContext& ctx, const LitVec& assume, ModelHandler* onModel) { + if (attach(ctx, onModel)) { + doStart(ctx, *(path_ = new LitVec(assume))); + } +} +bool SolveAlgorithm::next() { + if (!ctx_) { return false; } + if (last_ == value_true) { + if (!enum_->tentative() && model().num >= enumLimit_) { + stop(); + return false; + } + if (!enum_->commitSymmetric(*ctx_->solver(model().sId))) { + last_ = value_free; + } + } + if (last_ == value_true || (last_ = doNext(last_)) == value_true) { + Solver& s = *ctx_->solver(model().sId); + if (onModel_) { onModel_->onModel(s, model()); } + ctx_->report(s, model()); + return true; + } + stop(); + return false; +} +bool SolveAlgorithm::more() { + return last_ != value_false; +} +void SolveAlgorithm::stop() { + if (ctx_) { + doStop(); + detach(); + } +} +bool SolveAlgorithm::reportModel(Solver& s) const { + for (const Model& m = enum_->lastModel();;) { + bool r1 = !onModel_ || onModel_->onModel(s, m); + bool r2 = s.sharedContext()->report(s, m); + bool res= r1 && r2 && (enumLimit_ > m.num || enum_->tentative()); + if (!res || (res = !interrupted()) == false || !enum_->commitSymmetric(s)) { return res; } + } +} +bool SolveAlgorithm::reportUnsat(Solver& s) const { + const Model& m = enum_->lastModel(); + EventHandler* h = s.sharedContext()->eventHandler(); + bool r1 = !onModel_ || onModel_->onUnsat(s, m); + bool r2 = !h || h->onUnsat(s, m); + return r1 && r2; +} +bool SolveAlgorithm::moreModels(const Solver& s) const { + return s.decisionLevel() != 0 || !s.symmetric().empty() || (!s.sharedContext()->preserveModels() && s.sharedContext()->numEliminatedVars()); +} +void SolveAlgorithm::doStart(SharedContext&, const LitVec&) { + throw std::logic_error("Iterative model generation not supported by this algorithm!"); +} +int SolveAlgorithm::doNext(int) { + throw std::logic_error("Iterative model generation not supported by this algorithm!"); +} +void SolveAlgorithm::doStop() {} +///////////////////////////////////////////////////////////////////////////////////////// +// SequentialSolve +///////////////////////////////////////////////////////////////////////////////////////// +namespace { +struct InterruptHandler : public MessageHandler { + InterruptHandler(Solver* s, volatile int* t) : solver(s), term(t) { + if (s && t) { s->addPost(this); } + } + ~InterruptHandler() { if (solver) { solver->removePost(this); solver = 0; } } + bool handleMessages(){ return !*term || (solver->setStopConflict(), false); } + bool propagateFixpoint(Solver&, PostPropagator*){ return InterruptHandler::handleMessages(); } + Solver* solver; + volatile int* term; +}; +} +SequentialSolve::SequentialSolve(const SolveLimits& limit) + : SolveAlgorithm(limit) + , solve_(0) + , term_(-1) { +} +void SequentialSolve::resetSolve() { if (term_ > 0) { term_ = 0; } } +bool SequentialSolve::doInterrupt() { return term_ >= 0 && ++term_ != 0; } +void SequentialSolve::enableInterrupts() { if (term_ < 0) { term_ = 0; } } +bool SequentialSolve::interrupted() const{ return term_ > 0; } +void SequentialSolve::doStart(SharedContext& ctx, const LitVec& gp) { + solve_.reset(new BasicSolve(*ctx.master(), ctx.configuration()->search(0), limits())); + if (!enumerator().start(solve_->solver(), gp)) { SequentialSolve::doStop(); } +} +int SequentialSolve::doNext(int last) { + if (term_ > 0 || !solve_.get()) { return solve_.get() ? value_free : value_false; } + Solver& s = solve_->solver(); + for (InterruptHandler term(term_ == 0 ? &s : (Solver*)0, &term_);;) { + if (last != value_free) { enumerator().update(s); } + last = solve_->solve(); + if (last != value_true) { + if (last == value_free || term_ > 0) { return value_free; } + else if (enumerator().commitUnsat(s)) { reportUnsat(s); solve_->reset(); } + else if (enumerator().commitComplete()) { break; } + else { + enumerator().end(s); + if (!enumerator().start(s, path())) { break; } + last = value_free; + } + } + else if (enumerator().commitModel(s)) { break; } + } + return last; +} +void SequentialSolve::doStop() { + if (solve_.get()) { + enumerator().end(solve_->solver()); + ctx().detach(solve_->solver()); + solve_ = 0; + } +} +bool SequentialSolve::doSolve(SharedContext& ctx, const LitVec& gp) { + BasicSolve solve(*ctx.master(), ctx.configuration()->search(0), limits()); + // Add assumptions - if this fails, the problem is unsat + // under the current assumptions but not necessarily unsat. + Solver& s = solve.solver(); + bool more = !interrupted() && ctx.attach(s) && enumerator().start(s, gp); + for (InterruptHandler term(term_ == 0 ? &s : (Solver*)0, &term_); more; solve.reset()) { + ValueRep res; + while ((res = solve.solve()) == value_true && (!enumerator().commitModel(s) || reportModel(s))) { + enumerator().update(s); + } + if (res != value_false) { more = (res == value_free || moreModels(s)); break; } + else if (interrupted()) { more = true; break; } + else if (enumerator().commitUnsat(s)) { reportUnsat(s); enumerator().update(s); } + else if (enumerator().commitComplete()){ more = false; break; } + else { enumerator().end(s); more = enumerator().start(s, gp); } + } + enumerator().end(s); + ctx.detach(s); + return more; +} +} diff --git a/libclasp/src/solver.cpp b/libclasp/src/solver.cpp new file mode 100644 index 0000000..366a304 --- /dev/null +++ b/libclasp/src/solver.cpp @@ -0,0 +1,1845 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +namespace Clasp { +namespace { + typedef HashSet_t::set_type ConstraintSet; + struct InSet { + bool operator()(Constraint* c) const { return set->find(c) != set->end(); } + bool operator()(const ClauseWatch& w) const { return (*this)(w.head); } + bool operator()(const GenericWatch&w) const { return (*this)(w.con); } + const ConstraintSet* set; + }; +} +DecisionHeuristic::~DecisionHeuristic() {} +///////////////////////////////////////////////////////////////////////////////////////// +// CCMinRecursive +///////////////////////////////////////////////////////////////////////////////////////// +struct CCMinRecursive { + enum State { state_open = 0, state_removable = 1, state_poison = 2 }; + uint32 encodeState(State st) const { return open + uint32(st); } + State decodeState(uint32 epoch) const { return epoch <= open ? state_open : static_cast(epoch - open); } + void push(Literal p) { todo.push_back(p); } + Literal pop() { Literal p = todo.back(); todo.pop_back(); return p; } + LitVec todo; + uint32 open; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// SelectFirst selection strategy +///////////////////////////////////////////////////////////////////////////////////////// +// selects the first free literal +Literal SelectFirst::doSelect(Solver& s) { + for (Var i = 1; i <= s.numVars(); ++i) { + if (s.value(i) == value_free) { + return selectLiteral(s, i, 0); + } + } + assert(!"SelectFirst::doSelect() - precondition violated!\n"); + return Literal(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Dirty list +///////////////////////////////////////////////////////////////////////////////////////// +struct Solver::Dirty { + static const std::size_t min_size = static_cast(4); + Dirty() : last(0) {} + bool add(Literal p, WatchList& wl, Constraint* c) { + if (wl.right_size() <= min_size) { return false; } + uintp o = wl.left_size() > 0 ? reinterpret_cast(wl.left_begin()->head) : 0; + if (add(wl.right_begin()->con, o, c)) { dirty.push_left(p); } + return true; + } + bool add(Literal p, WatchList& wl, ClauseHead* c) { + if (wl.left_size() <= min_size) { return false; } + uintp o = wl.right_size() > 0 ? reinterpret_cast(wl.right_begin()->con) : 0; + if (add(wl.left_begin()->head, o, c)) { dirty.push_left(p); } + return true; + } + bool add(uint32 dl, ConstraintDB& wl, Constraint* c) { + if (wl.size() <= min_size) { return false; } + if (add(wl[0], 0, c)) { dirty.push_right(dl); } + return true; + } + template + bool add(T*& list, uintp other, Constraint* c) { + other |= reinterpret_cast(list); + list = reinterpret_cast( set_bit(reinterpret_cast(list), 0) ); + if (c != last) { cons.insert(last = c); } + return !test_bit(other, 0); + } + template + bool test_and_clear(T*& x) const { + uintp old = reinterpret_cast(x); + return test_bit(old, 0) && (x = reinterpret_cast(clear_bit(old, 0))) != 0; + } + void cleanup(Watches& watches, DecisionLevels& levels) { + InSet inCons = { &cons }; + for (DirtyList::left_iterator it = dirty.left_begin(), end = dirty.left_end(); it != end; ++it) { + WatchList& wl = watches[it->id()]; + if (wl.left_size() && test_and_clear(wl.left_begin()->head)) { wl.shrink_left(std::remove_if(wl.left_begin(), wl.left_end(), inCons)); } + if (wl.right_size()&& test_and_clear(wl.right_begin()->con)) { wl.shrink_right(std::remove_if(wl.right_begin(), wl.right_end(), inCons)); } + } + ConstraintDB* db = 0; + for (DirtyList::right_iterator it = dirty.right_begin(), end = dirty.right_end(); it != end; ++it) { + if (*it < levels.size() && !(db = levels[*it].undo)->empty() && test_and_clear(*db->begin())) { + db->erase(std::remove_if(db->begin(), db->end(), inCons), db->end()); + } + } + dirty.clear(); + cons.clear(); + last = 0; + } + typedef bk_lib::left_right_sequence DirtyList; + DirtyList dirty; + ConstraintSet cons; + Constraint* last; +}; +///////////////////////////////////////////////////////////////////////////////////////// +// Solver: Construction/Destruction/Setup +///////////////////////////////////////////////////////////////////////////////////////// +#define FOR_EACH_POST(x, head) \ + for (PostPropagator** __r__ = (head), *x; (x = *__r__) != 0; __r__ = (x == *__r__) ? &x->next : __r__) + +static PostPropagator* sent_list; +Solver::Solver(SharedContext* ctx, uint32 id) + : shared_(ctx) + , ccMin_(0) + , postHead_(&sent_list) + , undoHead_(0) + , enum_(0) + , memUse_(0) + , lazyRem_(0) + , ccInfo_(Constraint_t::Conflict) + , dbIdx_(0) + , lastSimp_(0) + , shufSimp_(0) + , initPost_(0){ + Var sentVar = assign_.addVar(); + assign_.setValue(sentVar, value_true); + markSeen(sentVar); + strategy_.id = id; +} + +Solver::~Solver() { + freeMem(); +} + +void Solver::freeMem() { + std::for_each( constraints_.begin(), constraints_.end(), DestroyObject()); + std::for_each( learnts_.begin(), learnts_.end(), DestroyObject() ); + constraints_.clear(); + learnts_.clear(); + post_.clear(); + if (enum_) { enum_->destroy(); } + heuristic_.reset(0); + PodVector::destruct(watches_); + // free undo lists + // first those still in use + for (DecisionLevels::size_type i = 0; i != levels_.size(); ++i) { + delete levels_[i].undo; + } + // then those in the free list + for (ConstraintDB* x = undoHead_; x; ) { + ConstraintDB* t = x; + x = (ConstraintDB*)x->front(); + delete t; + } + delete ccMin_; + ccMin_ = 0; + memUse_ = 0; +} + +SatPreprocessor* Solver::satPrepro() const { return shared_->satPrepro.get(); } +const SolveParams& Solver::searchConfig() const { return shared_->configuration()->search(id()); } + +void Solver::reset() { + SharedContext* myCtx = shared_; + uint32 myId = strategy_.id; + this->~Solver(); + new (this) Solver(myCtx, myId); +} +void Solver::setHeuristic(DecisionHeuristic* h, Ownership_t::Type t) { + CLASP_ASSERT_CONTRACT_MSG(h, "Heuristic must not be null"); + resetHeuristic(); + heuristic_.reset(h); + if (t == Ownership_t::Retain) { heuristic_.release(); } +} +void Solver::resetHeuristic() { + if (heuristic_.get()) { heuristic_->detach(*this); } + heuristic_ = 0; +} +void Solver::resetConfig() { + if (strategy_.hasConfig) { + if (PostPropagator* pp = getPost(PostPropagator::priority_reserved_look)) { pp->destroy(this, true); } + delete ccMin_; + ccMin_ = 0; + } + strategy_.hasConfig = 0; +} +void Solver::startInit(uint32 numConsGuess, const SolverParams& params) { + assert(!lazyRem_ && decisionLevel() == 0); + if (watches_.empty()) { + assign_.trail.reserve(shared_->numVars() + 2); + watches_.reserve((shared_->numVars() + 2)<<1); + assign_.reserve(shared_->numVars() + 2); + } + updateVars(); + // pre-allocate some memory + constraints_.reserve(numConsGuess/2); + levels_.reserve(25); + if (undoHead_ == 0) { + for (uint32 i = 0; i != 25; ++i) { + undoFree(new ConstraintDB(10)); + } + } + if (!popRootLevel(rootLevel())) { return; } + if (!strategy_.hasConfig) { + uint32 id = this->id(); + uint32 hId = strategy_.heuId; // remember active heuristic + strategy_ = params; + strategy_.id = id; // keep id + strategy_.hasConfig = 1; // strategy is now "up to date" + if (!params.ccMinRec) { delete ccMin_; ccMin_ = 0; } + else if (!ccMin_) { ccMin_ = new CCMinRecursive; } + if (id == params.id || !shared_->seedSolvers()) { + rng.srand(params.seed); + } + else { + RNG x(14182940); for (uint32 i = 0; i != id; ++i) { x.rand(); } + rng.srand(x.seed()); + } + if (hId != params.heuId) { // heuristic has changed + resetHeuristic(); + } + else if (heuristic_.get() != 0 && heuristic_.is_owner()) { + heuristic_->setConfig(params.heuristic); + } + } + if (heuristic_.get() == 0) { + heuristic_.reset(shared_->configuration()->heuristic(id())); + } + postHead_ = &sent_list; // disable post propagators during setup + initPost_ = 0; // defer calls to PostPropagator::init() + heuristic_->startInit(*this); +} + +void Solver::updateVars() { + if (numVars() > shared_->numVars()) { + popVars(numVars() - shared_->numVars(), false, 0); + } + else { + assign_.resize(shared_->numVars() + 1); + watches_.resize(assign_.numVars()<<1); + } +} + +bool Solver::cloneDB(const ConstraintDB& db) { + assert(!hasConflict()); + while (dbIdx_ < (uint32)db.size() && !hasConflict()) { + if (Constraint* c = db[dbIdx_++]->cloneAttach(*this)) { + constraints_.push_back(c); + } + } + return !hasConflict(); +} +bool Solver::preparePost() { + if (hasConflict()) { return false; } + if (initPost_ == 0){ + initPost_ = 1; + FOR_EACH_POST(x, post_.head()) { + if (!x->init(*this)) { return false; } + } + } + return shared_->configuration()->addPost(*this); +} + +bool Solver::endInit() { + if (hasConflict()) { return false; } + heuristic_->endInit(*this); + if (strategy_.signFix) { + for (Var v = 1; v <= numVars(); ++v) { + Literal x = DecisionHeuristic::selectLiteral(*this, v, 0); + setPref(v, ValueSet::user_value, x.sign() ? value_false : value_true); + } + } + postHead_ = post_.head(); // enable all post propagators + return propagate() && simplify(); +} + +bool Solver::endStep(uint32 top, const SolverParams& params) { + if (!popRootLevel(rootLevel())) { return false; } + popAuxVar(); + Literal x = shared_->stepLiteral(); + top = std::min(top, (uint32)lastSimp_); + if (PostPropagator* pp = getPost(PostPropagator::priority_reserved_look)) { + pp->destroy(this, true); + } + if ((value(x.var()) != value_free || force(~x)) && simplify() && this != shared_->master() && shared_->ok()) { + Solver& m = *shared_->master(); + for (uint32 end = (uint32)assign_.trail.size(); top < end; ++top) { + Literal u = assign_.trail[top]; + if (u.var() != x.var() && !m.force(u)) { break; } + } + } + if (params.forgetLearnts()) { reduceLearnts(1.0f); } + if (params.forgetHeuristic()) { resetHeuristic(); } + if (params.forgetSigns()) { resetPrefs(); } + if (params.forgetActivities()){ resetLearntActivities(); } + return true; +} + +void Solver::add(Constraint* c) { + constraints_.push_back(c); +} +bool Solver::add(const ClauseRep& c, bool isNew) { + typedef ShortImplicationsGraph::ImpType ImpType; + if (c.prep == 0) { + return ClauseCreator::create(*this, c, ClauseCreator::clause_force_simplify).ok(); + } + int added = 0; + if (c.size > 1) { + if (allowImplicit(c)) { added = shared_->addImp(static_cast(c.size), c.lits, c.info.type()); } + else { return ClauseCreator::create(*this, c, ClauseCreator::clause_explicit).ok(); } + } + else { + Literal u = c.size ? c.lits[0] : lit_false(); + uint32 ts= sizeVec(trail()); + force(u); + added = int(ts != trail().size()); + } + if (added > 0 && isNew && c.info.learnt()) { + stats.addLearnt(c.size, c.info.type()); + distribute(c.lits, c.size, c.info); + } + return !hasConflict(); +} +bool Solver::addPost(PostPropagator* p, bool init) { + post_.add(p); + return !init || p->init(*this); +} +bool Solver::addPost(PostPropagator* p) { return addPost(p, initPost_ != 0); } +void Solver::removePost(PostPropagator* p){ post_.remove(p); } +PostPropagator* Solver::getPost(uint32 prio) const { return post_.find(prio); } +uint32 Solver::receive(SharedLiterals** out, uint32 maxOut) const { + if (shared_->distributor.get()) { + return shared_->distributor->receive(*this, out, maxOut); + } + return 0; +} +SharedLiterals* Solver::distribute(const Literal* lits, uint32 size, const ConstraintInfo& extra) { + if (shared_->distributor.get() && !extra.aux() && (size <= 3 || shared_->distributor->isCandidate(size, extra.lbd(), extra.type()))) { + uint32 initialRefs = shared_->concurrency() - (size <= Clause::MAX_SHORT_LEN || !shared_->physicalShare(extra.type())); + SharedLiterals* x = SharedLiterals::newShareable(lits, size, extra.type(), initialRefs); + shared_->distributor->publish(*this, x); + stats.addDistributed(extra.lbd(), extra.type()); + return initialRefs == shared_->concurrency() ? x : 0; + } + return 0; +} +void Solver::setEnumerationConstraint(Constraint* c) { + if (enum_) enum_->destroy(this, true); + enum_ = c; +} + +uint32 Solver::numConstraints() const { + return static_cast(constraints_.size()) + + (shared_ ? shared_->numBinary()+shared_->numTernary() : 0); +} + +Var Solver::pushAuxVar() { + assert(!lazyRem_); + Var aux = assign_.addVar(); + setPref(aux, ValueSet::def_value, value_false); + watches_.insert(watches_.end(), 2, WatchList()); + if (heuristic_.get()) { heuristic_->updateVar(*this, aux, 1); } + return aux; +} +void Solver::popAuxVar(uint32 num, ConstraintDB* auxCons) { + num = numVars() >= shared_->numVars() ? std::min(numVars() - shared_->numVars(), num) : 0; + if (!num) { return; } + shared_->report("removing aux vars", this); + Dirty dirty; + lazyRem_ = &dirty; + popVars(num, true, auxCons); + lazyRem_ = 0; + shared_->report("removing aux watches", this); + dirty.cleanup(watches_, levels_); +} +Literal Solver::popVars(uint32 num, bool popLearnt, ConstraintDB* popAux) { + Literal pop = posLit(assign_.numVars() - num); + uint32 dl = decisionLevel() + 1; + for (ImpliedList::iterator it = impliedLits_.begin(); it != impliedLits_.end(); ++it) { + if (!(it->lit < pop)) { dl = std::min(dl, it->level); } + } + for (Var v = pop.var(), end = pop.var()+num; v != end; ++v) { + if (value(v) != value_free) { dl = std::min(dl, level(v)); } + } + // 1. remove aux vars from assignment and watch lists + if (dl > rootLevel()) { + undoUntil(dl-1, undo_pop_proj_level); + } + else { + popRootLevel((rootLevel() - dl) + 1); + if (dl == 0) { // top-level has aux vars - cleanup manually + uint32 j = shared_->numUnary(), units = assign_.units(); + for (uint32 i = j, end = sizeVec(assign_.trail); i != end; ++i) { + if (assign_.trail[i] < pop) { assign_.trail[j++] = assign_.trail[i]; } + else { + units -= (i < units); + assign_.front -= (i < assign_.front); + lastSimp_ -= (i < lastSimp_); + } + } + shrinkVecTo(assign_.trail, j); + assign_.setUnits(units); + } + } + for (uint32 n = num; n--;) { + watches_.back().clear(true); + watches_.pop_back(); + watches_.back().clear(true); + watches_.pop_back(); + } + // 2. remove learnt constraints over aux + if (popLearnt) { + shared_->report("removing aux constraints", this); + ConstraintDB::size_type i, j, end = learnts_.size(); + LitVec cc; + for (i = j = 0; i != end; ++i) { + learnts_[j++] = learnts_[i]; + ClauseHead* c = learnts_[i]->clause(); + if (c && c->aux()) { + cc.clear(); + c->toLits(cc); + if (std::find_if(cc.begin(), cc.end(), std::not1(std::bind2nd(std::less(), pop))) != cc.end()) { + c->destroy(this, true); + --j; + } + } + } + learnts_.erase(learnts_.begin()+j, learnts_.end()); + } + if (popAux) { destroyDB(*popAux); } + // 3. remove vars from solver and heuristic + assign_.resize(assign_.numVars()-num); + if (!validVar(tag_.var())) { tag_ = lit_true(); } + if (heuristic_.get()) { + heuristic_->updateVar(*this, pop.var(), num); + } + return pop; +} + +bool Solver::pushRoot(const LitVec& path) { + // make sure we are on the current root level + if (!popRootLevel(0) || !simplify() || !propagate()) { return false; } + // push path + stats.addPath(path.size()); + for (LitVec::const_iterator it = path.begin(), end = path.end(); it != end; ++it) { + if (!pushRoot(*it)) { return false; } + } + ccInfo_.setActivity(1); + return true; +} + +bool Solver::pushRoot(Literal x) { + if (hasConflict()) { return false; } + if (decisionLevel()!= rootLevel()) { popRootLevel(0); } + if (queueSize() && !propagate()) { return false; } + if (value(x.var()) != value_free) { return isTrue(x);} + assume(x); --stats.choices; + pushRootLevel(); + return propagate(); +} + +bool Solver::popRootLevel(uint32 n, LitVec* popped, bool aux) { + clearStopConflict(); + uint32 newRoot = levels_.root - std::min(n, rootLevel()); + if (popped && newRoot < rootLevel()) { + for (uint32 i = newRoot+1; i <= rootLevel(); ++i) { + Literal x = decision(i); + if (aux || !auxVar(x.var())) { popped->push_back(x); } + } + } + levels_.root = newRoot; + levels_.flip = rootLevel(); + levels_.mode = 0; + impliedLits_.front = 0; + bool tagActive = isTrue(tagLiteral()); + // go back to new root level and re-assert still implied literals + undoUntil(rootLevel(), undo_pop_proj_level); + if (tagActive && !isTrue(tagLiteral())) { + removeConditional(); + } + return !hasConflict(); +} + +bool Solver::clearAssumptions() { + return popRootLevel(rootLevel()) + && simplify(); +} + +void Solver::clearStopConflict() { + if (hasStopConflict()) { + levels_.root = conflict_[1].rep(); + levels_.flip = conflict_[2].rep(); + assign_.front = conflict_[3].rep(); + conflict_.clear(); + } +} + +void Solver::setStopConflict() { + if (!hasConflict()) { + // we use the nogood {FALSE} to represent the unrecoverable conflict - + // note that {FALSE} can otherwise never be a violated nogood because + // TRUE is always true in every solver + conflict_.push_back(lit_false()); + // remember the current root-level + conflict_.push_back(Literal::fromRep(rootLevel())); + // remember the current bt-level + conflict_.push_back(Literal::fromRep(backtrackLevel())); + // remember the current propagation queue + conflict_.push_back(Literal::fromRep(assign_.front)); + } + // artificially increase root level - + // this way, the solver is prevented from resolving the conflict + pushRootLevel(decisionLevel()); +} + +void Solver::copyGuidingPath(LitVec& gpOut) { + uint32 aux = rootLevel()+1; + gpOut.clear(); + for (uint32 i = 1, end = rootLevel()+1; i != end; ++i) { + Literal x = decision(i); + if (!auxVar(x.var())) { gpOut.push_back(x); } + else if (i < aux) { aux = i; } + } + for (ImpliedList::iterator it = impliedLits_.begin(); it != impliedLits_.end(); ++it) { + if (it->level <= rootLevel() && (it->ante.ante().isNull() || it->level < aux) && !auxVar(it->lit.var())) { + gpOut.push_back(it->lit); + } + } +} +bool Solver::splittable() const { + if (decisionLevel() == rootLevel() || frozenLevel(rootLevel()+1)) { return false; } + if (numAuxVars()) { // check if gp would contain solver local aux var + uint32 minAux = rootLevel() + 2; + for (uint32 i = 1; i != minAux; ++i) { + if (auxVar(decision(i).var()) && decision(i) != tag_) { return false; } + } + for (ImpliedList::iterator it = impliedLits_.begin(); it != impliedLits_.end(); ++it) { + if (it->ante.ante().isNull() && it->level < minAux && auxVar(it->lit.var()) && it->lit != tag_) { return false; } + } + } + return true; +} +bool Solver::split(LitVec& out) { + if (!splittable()) { return false; } + copyGuidingPath(out); + pushRootLevel(); + out.push_back(~decision(rootLevel())); + stats.addSplit(); + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// Solver: Watch management +//////////////////////////////////////////////////////////////////////////////////////// +uint32 Solver::numWatches(Literal p) const { + assert( validVar(p.var()) ); + if (!validWatch(p)) return 0; + uint32 n = static_cast(watches_[p.id()].size()); + if (!auxVar(p.var())){ + n += shared_->shortImplications().numEdges(p); + } + return n; +} + +bool Solver::hasWatch(Literal p, Constraint* c) const { + if (!validWatch(p)) return false; + const WatchList& pList = watches_[p.id()]; + return std::find_if(pList.right_begin(), pList.right_end(), GenericWatch::EqConstraint(c)) != pList.right_end(); +} + +bool Solver::hasWatch(Literal p, ClauseHead* h) const { + if (!validWatch(p)) return false; + const WatchList& pList = watches_[p.id()]; + return std::find_if(pList.left_begin(), pList.left_end(), ClauseWatch::EqHead(h)) != pList.left_end(); +} + +GenericWatch* Solver::getWatch(Literal p, Constraint* c) const { + if (!validWatch(p)) return 0; + const WatchList& pList = watches_[p.id()]; + WatchList::const_right_iterator it = std::find_if(pList.right_begin(), pList.right_end(), GenericWatch::EqConstraint(c)); + return it != pList.right_end() + ? &const_cast(*it) + : 0; +} + +void Solver::removeWatch(const Literal& p, Constraint* c) { + if (!validWatch(p)) { return; } + WatchList& pList = watches_[p.id()]; + if (!lazyRem_ || !lazyRem_->add(p, pList, c)) { + pList.erase_right(std::find_if(pList.right_begin(), pList.right_end(), GenericWatch::EqConstraint(c))); + } +} + +void Solver::removeWatch(const Literal& p, ClauseHead* h) { + if (!validWatch(p)) { return; } + WatchList& pList = watches_[p.id()]; + if (!lazyRem_ || !lazyRem_->add(p, pList, h)) { + pList.erase_left(std::find_if(pList.left_begin(), pList.left_end(), ClauseWatch::EqHead(h))); + } +} + +bool Solver::removeUndoWatch(uint32 dl, Constraint* c) { + assert(dl != 0 && dl <= decisionLevel() ); + if (levels_[dl-1].undo) { + ConstraintDB& uList = *levels_[dl-1].undo; + if (!lazyRem_ || !lazyRem_->add(dl - 1, uList, c)) { + ConstraintDB::iterator it = std::find(uList.begin(), uList.end(), c); + if (it != uList.end()) { + *it = uList.back(); + uList.pop_back(); + return true; + } + } + } + return false; +} +void Solver::destroyDB(ConstraintDB& db) { + if (!db.empty()) { + Dirty dirty; + if (!lazyRem_) { lazyRem_ = &dirty; } + for (ConstraintDB::const_iterator it = db.begin(), end = db.end(); it != end; ++it) { + (*it)->destroy(this, true); + } + db.clear(); + if (lazyRem_ == &dirty) { + lazyRem_ = 0; + dirty.cleanup(watches_, levels_); + } + } +} +///////////////////////////////////////////////////////////////////////////////////////// +// Solver: Basic DPLL-functions +//////////////////////////////////////////////////////////////////////////////////////// + +// removes all satisfied binary and ternary clauses as well +// as all constraints for which Constraint::simplify returned true. +bool Solver::simplify() { + if (decisionLevel() != 0) return true; + if (hasConflict()) return false; + if (lastSimp_ != (uint32)assign_.trail.size()) { + uint32 old = lastSimp_; + if (!simplifySAT()) { return false; } + assert(lastSimp_ == (uint32)assign_.trail.size()); + heuristic_->simplify(*this, old); + } + if (shufSimp_) { simplifySAT(); } + return true; +} +Var Solver::pushTagVar(bool pushToRoot) { + if (isSentinel(tag_)) { tag_ = posLit(pushAuxVar()); } + if (pushToRoot) { pushRoot(tag_); } + return tag_.var(); +} +void Solver::removeConditional() { + Literal p = ~tagLiteral(); + if (!isSentinel(p)) { + ConstraintDB::size_type i, j, end = learnts_.size(); + for (i = j = 0; i != end; ++i) { + ClauseHead* c = learnts_[i]->clause(); + if (!c || !c->tagged()) { + learnts_[j++] = learnts_[i]; + } + else { + c->destroy(this, true); + } + } + learnts_.erase(learnts_.begin()+j, learnts_.end()); + } +} + +void Solver::strengthenConditional() { + Literal p = ~tagLiteral(); + if (!isSentinel(p)) { + ConstraintDB::size_type i, j, end = learnts_.size(); + for (i = j = 0; i != end; ++i) { + ClauseHead* c = learnts_[i]->clause(); + if (!c || !c->tagged() || !c->strengthen(*this, p, true).second) { + learnts_[j++] = learnts_[i]; + } + else { + assert((decisionLevel() == rootLevel() || !c->locked(*this)) && "Solver::strengthenConditional(): must not remove locked constraint!"); + c->destroy(this, false); + } + } + learnts_.erase(learnts_.begin()+j, learnts_.end()); + } +} + +bool Solver::simplifySAT() { + if (queueSize() > 0 && !propagate()) { + return false; + } + assert(assign_.qEmpty()); + assign_.front = lastSimp_; + lastSimp_ = (uint32)assign_.trail.size(); + for (Literal p; !assign_.qEmpty(); ) { + p = assign_.qPop(); + releaseVec(watches_[p.id()]); + releaseVec(watches_[(~p).id()]); + shared_->simplifyShort(*this, p); + } + bool shuffle = shufSimp_ != 0; + shufSimp_ = 0; + if (shuffle) { + std::random_shuffle(constraints_.begin(), constraints_.end(), rng); + std::random_shuffle(learnts_.begin(), learnts_.end(), rng); + } + if (isMaster()) { shared_->simplify(shuffle); } + else { simplifyDB(*this, constraints_, shuffle); } + simplifyDB(*this, learnts_, shuffle); + FOR_EACH_POST(x, postHead_) { + if (x->simplify(*this, shuffle)) { + post_.remove(x); + x->destroy(this, false); + } + } + if (enum_ && enum_->simplify(*this, shuffle)) { + enum_->destroy(this, false); + enum_ = 0; + } + return true; +} + +void Solver::setConflict(Literal p, const Antecedent& a, uint32 data) { + ++stats.conflicts; + conflict_.push_back(~p); + if (searchMode() != SolverStrategies::no_learning && !a.isNull()) { + if (data == UINT32_MAX) { + a.reason(*this, p, conflict_); + } + else { + // temporarily replace old data with new data + uint32 saved = assign_.data(p.var()); + assign_.setData(p.var(), data); + // extract conflict using new data + a.reason(*this, p, conflict_); + // restore old data + assign_.setData(p.var(), saved); + } + } +} +bool Solver::force(const ImpliedLiteral& p) { + // Already implied? + if (isTrue(p.lit)) { + if (level(p.lit.var()) <= p.level) { return true; } + if (ImpliedLiteral* x = impliedLits_.find(p.lit)) { + if (x->level > p.level) { + *x = p; + setReason(p.lit, p.ante.ante(), p.ante.data()); + } + return true; + } + } + if (undoUntil(p.level) != p.level) { + // Logically the implication is on level p.level. + // Store enough information so that p can be re-assigned once we backtrack. + impliedLits_.add(decisionLevel(), p); + } + return (isTrue(p.lit) && setReason(p.lit, p.ante.ante(), p.ante.data())) || force(p.lit, p.ante.ante(), p.ante.data()); +} + +bool Solver::assume(const Literal& p) { + if (value(p.var()) == value_free) { + assert(decisionLevel() != assign_.maxLevel()); + ++stats.choices; + levels_.push_back(DLevel(numAssignedVars(), 0)); + return assign_.assign(p, decisionLevel(), Antecedent()); + } + return isTrue(p); +} + +void Solver::cancelPropagation() { + assign_.qReset(); + for (PostPropagator* r = *postHead_; r; r = r->next) { r->reset(); } +} + +bool Solver::propagate() { + if (unitPropagate() && postPropagate(0)) { + assert(queueSize() == 0); + return true; + } + cancelPropagation(); + return false; +} + +bool Solver::propagateUntil(PostPropagator* p) { + assert((!p || *postHead_) && "OP not allowed during init!"); + return unitPropagate() && (p == *postHead_ || postPropagate(p)); +} + +Constraint::PropResult ClauseHead::propagate(Solver& s, Literal p, uint32&) { + Literal* head = head_; + uint32 wLit = (head[1] == ~p); // pos of false watched literal + if (s.isTrue(head[1-wLit])) { + return Constraint::PropResult(true, true); + } + else if (!s.isFalse(head[2])) { + assert(!isSentinel(head[2]) && "Invalid ClauseHead!"); + head[wLit] = head[2]; + head[2] = ~p; + s.addWatch(~head[wLit], ClauseWatch(this)); + return Constraint::PropResult(true, false); + } + else if (updateWatch(s, wLit)) { + assert(!s.isFalse(head_[wLit])); + s.addWatch(~head[wLit], ClauseWatch(this)); + return Constraint::PropResult(true, false); + } + return PropResult(s.force(head_[1^wLit], this), true); +} + +bool Solver::unitPropagate() { + assert(!hasConflict()); + Literal p, q, r; + uint32 idx, ignore, DL = decisionLevel(); + const ShortImplicationsGraph& btig = shared_->shortImplications(); + const uint32 maxIdx = btig.size(); + while ( !assign_.qEmpty() ) { + p = assign_.qPop(); + idx = p.id(); + WatchList& wl = watches_[idx]; + // first: short clause BCP + if (idx < maxIdx && !btig.propagate(*this, p)) { + return false; + } + // second: clause BCP + if (wl.left_size() != 0) { + WatchList::left_iterator it, end, j = wl.left_begin(); + Constraint::PropResult res; + for (it = wl.left_begin(), end = wl.left_end(); it != end; ) { + ClauseWatch& w = *it++; + res = w.head->ClauseHead::propagate(*this, p, ignore); + if (res.keepWatch) { + *j++ = w; + } + if (!res.ok) { + wl.shrink_left(std::copy(it, end, j)); + return false; + } + } + wl.shrink_left(j); + } + // third: general constraint BCP + if (wl.right_size() != 0) { + WatchList::right_iterator it, end, j = wl.right_begin(); + Constraint::PropResult res; + for (it = wl.right_begin(), end = wl.right_end(); it != end; ) { + GenericWatch& w = *it++; + res = w.propagate(*this, p); + if (res.keepWatch) { + *j++ = w; + } + if (!res.ok) { + wl.shrink_right(std::copy(it, end, j)); + return false; + } + } + wl.shrink_right(j); + } + } + return DL || assign_.markUnits(); +} + +bool Solver::postPropagate(PostPropagator* stop) { + for (PostPropagator** r = postHead_, *t; *r != stop;) { + t = *r; + if (!t->propagateFixpoint(*this, stop)) { return false; } + assert(queueSize() == 0); + if (t == *r) { r = &t->next; } + // else: t was removed during propagate + } + return true; +} + +bool Solver::test(Literal p, PostPropagator* c) { + assert(value(p.var()) == value_free && !hasConflict()); + assume(p); --stats.choices; + uint32 pLevel = decisionLevel(); + freezeLevel(pLevel); // can't split-off this level + if (propagateUntil(c)) { + assert(decisionLevel() == pLevel && "Invalid PostPropagators"); + if (c) c->undoLevel(*this); + undoUntil(pLevel-1); + return true; + } + assert(decisionLevel() == pLevel && "Invalid PostPropagators"); + unfreezeLevel(pLevel); + cancelPropagation(); + return false; +} + +bool Solver::resolveConflict() { + assert(hasConflict()); + if (decisionLevel() > rootLevel()) { + if (decisionLevel() != backtrackLevel() && searchMode() != SolverStrategies::no_learning) { + uint32 uipLevel = analyzeConflict(); + stats.addConflict(decisionLevel(), uipLevel, backtrackLevel(), ccInfo_.lbd()); + if (shared_->reportMode()) { + sharedContext()->report(NewConflictEvent(*this, cc_, ccInfo_)); + } + undoUntil( uipLevel ); + return ClauseCreator::create(*this, cc_, ClauseCreator::clause_no_prepare, ccInfo_); + } + else { + return backtrack(); + } + } + return false; +} + +bool Solver::backtrack() { + Literal lastChoiceInverted; + do { + if (decisionLevel() == rootLevel()) { + setStopConflict(); + return false; + } + lastChoiceInverted = ~decision(decisionLevel()); + undoUntil(decisionLevel() - 1, undo_pop_proj_level); + setBacktrackLevel(decisionLevel(), undo_pop_bt_level); + } while (hasConflict() || !force(lastChoiceInverted, 0)); + // remember flipped literal for copyGuidingPath() + impliedLits_.add(decisionLevel(), ImpliedLiteral(lastChoiceInverted, decisionLevel(), 0)); + return true; +} + +bool ImpliedList::assign(Solver& s) { + assert(front <= lits.size()); + bool ok = !s.hasConflict(); + const uint32 DL = s.decisionLevel(); + VecType::iterator j = lits.begin() + front; + for (VecType::iterator it = j, end = lits.end(); it != end; ++it) { + if(it->level <= DL) { + ok = ok && s.force(it->lit, it->ante.ante(), it->ante.data()); + if (it->level < DL || it->ante.ante().isNull()) { *j++ = *it; } + } + } + lits.erase(j, lits.end()); + level = DL * uint32(!lits.empty()); + front = level > s.rootLevel() ? front : sizeVec(lits); + return ok; +} +bool Solver::isUndoLevel() const { + return decisionLevel() > backtrackLevel(); +} +uint32 Solver::undoUntilImpl(uint32 level, bool forceSave) { + level = std::max( level, backtrackLevel() ); + if (level >= decisionLevel()) { return decisionLevel(); } + uint32& n = (levels_.jump = decisionLevel() - level); + bool sp = forceSave || (strategy_.saveProgress > 0 && ((uint32)strategy_.saveProgress) <= n); + bool ok = conflict_.empty() && levels_.back().freeze == 0; + conflict_.clear(); + heuristic_->undoUntil( *this, levels_[level].trailPos); + undoLevel(sp && ok); + while (--n) { undoLevel(sp); } + return level; +} +uint32 Solver::undoUntil(uint32 level, uint32 mode) { + assert(backtrackLevel() >= rootLevel()); + if (level < backtrackLevel() && mode >= levels_.mode) { + levels_.flip = std::max(rootLevel(), level); + } + level = undoUntilImpl(level, (mode & undo_save_phases) != 0); + if (impliedLits_.active(level)) { + impliedLits_.assign(*this); + } + return level; +} +uint32 Solver::estimateBCP(const Literal& p, int rd) const { + if (value(p.var()) != value_free) return 0; + LitVec::size_type first = assign_.assigned(); + LitVec::size_type i = first; + Solver& self = const_cast(*this); + self.assign_.setValue(p.var(), trueValue(p)); + self.assign_.trail.push_back(p); + const ShortImplicationsGraph& btig = shared_->shortImplications(); + const uint32 maxIdx = btig.size(); + do { + Literal x = assign_.trail[i++]; + if (x.id() < maxIdx && !btig.propagateBin(self.assign_, x, 0)) { + break; + } + } while (i < assign_.assigned() && rd-- != 0); + i = assign_.assigned()-first; + while (self.assign_.assigned() != first) { + self.assign_.undoLast(); + } + return (uint32)i; +} + +uint32 Solver::inDegree(WeightLitVec& out) { + if (decisionLevel() == 0) { return 1; } + assert(!hasConflict()); + out.reserve((numAssignedVars()-levelStart(1))/10); + uint32 maxIn = 1; + uint32 i = sizeVec(assign_.trail), stop = levelStart(1); + for (LitVec temp; i-- != stop; ) { + Literal x = assign_.trail[i]; + uint32 xLev = assign_.level(x.var()); + uint32 xIn = 0; + Antecedent xAnte = assign_.reason(x.var()); + if (!xAnte.isNull() && xAnte.type() != Antecedent::Binary) { + xAnte.reason(*this, x, temp); + for (LitVec::const_iterator it = temp.begin(); it != temp.end(); ++it) { + xIn += level(it->var()) != xLev; + } + if (xIn) { + out.push_back(WeightLiteral(x, xIn)); + maxIn = std::max(xIn, maxIn); + } + temp.clear(); + } + } + return maxIn; +} +///////////////////////////////////////////////////////////////////////////////////////// +// Solver: Private helper functions +//////////////////////////////////////////////////////////////////////////////////////// +Solver::ConstraintDB* Solver::allocUndo(Constraint* c) { + if (undoHead_ == 0) { + return new ConstraintDB(1, c); + } + assert(undoHead_->size() == 1); + ConstraintDB* r = undoHead_; + undoHead_ = (ConstraintDB*)undoHead_->front(); + r->clear(); + r->push_back(c); + return r; +} +void Solver::undoFree(ConstraintDB* x) { + // maintain a single-linked list of undo lists + x->clear(); + x->push_back((Constraint*)undoHead_); + undoHead_ = x; +} +// removes the current decision level +void Solver::undoLevel(bool sp) { + assert(decisionLevel() != 0 && levels_.back().trailPos != assign_.trail.size() && "Decision Level must not be empty"); + assign_.undoTrail(levels_.back().trailPos, sp); + if (levels_.back().undo) { + const ConstraintDB& undoList = *levels_.back().undo; + for (ConstraintDB::size_type i = 0, end = undoList.size(); i != end; ++i) { + undoList[i]->undoLevel(*this); + } + undoFree(levels_.back().undo); + } + levels_.pop_back(); +} + +inline ClauseHead* clause(const Antecedent& ante) { + return ante.isNull() || ante.type() != Antecedent::Generic ? 0 : ante.constraint()->clause(); +} + +bool Solver::resolveToFlagged(const LitVec& in, uint8 vf, LitVec& out, uint32& outLbd) const { + return const_cast(*this).resolveToFlagged(in, vf, out, outLbd); +} +bool Solver::resolveToFlagged(const LitVec& in, const uint8 vf, LitVec& out, uint32& outLbd) { + const LitVec& trail = assign_.trail; + const LitVec* rhs = ∈ + LitVec temp; out.clear(); + bool ok = true, first = true; + for (LitVec::size_type tp = trail.size(), resolve = 0;; first = false) { + Literal p; Var v; + for (LitVec::const_iterator it = rhs->begin(), end = rhs->end(); it != end; ++it) { + p = *it ^ first; v = p.var(); + if (!seen(v)) { + markSeen(v); + if (varInfo(v).hasAll(vf)) { markLevel(level(v)); out.push_back(~p); } + else if (!reason(p).isNull()) { ++resolve; } + else { clearSeen(v); ok = false; break; } + } + } + if (resolve-- == 0) { break; } + // find next literal to resolve + while (!seen(trail[--tp]) || varInfo(trail[tp].var()).hasAll(vf)) { ; } + clearSeen((p = trail[tp]).var()); + reason(p, temp); + rhs = &temp; + } + LitVec::size_type outSize = out.size(); + if (ok && !first) { + uint32 old = strategy_.ccMinKeepAct; + strategy_.ccMinKeepAct = 1; + uint32 antes = SolverStrategies::all_antes; + if (ccMin_) { ccMinRecurseInit(*ccMin_); } + for (LitVec::size_type i = 0; i != outSize;) { + if (!ccRemovable(~out[i], antes-1, ccMin_)) { ++i; } + else { + std::swap(out[i], out.back()); + --outSize; + } + } + strategy_.ccMinKeepAct = old; + } + outLbd = 0; + for (uint32 i = 0, dl, root = 0; i != outSize; ++i) { + Var v = out[i].var(); + dl = level(v); + clearSeen(v); + if (dl && hasLevel(dl)) { + unmarkLevel(dl); + outLbd += (dl > rootLevel()) || (++root == 1); + } + } + for (Var v; outSize != out.size(); out.pop_back()) { + clearSeen(v = out.back().var()); + unmarkLevel(level(v)); + } + return ok; +} +void Solver::resolveToCore(LitVec& out) { + CLASP_ASSERT_CONTRACT_MSG(hasConflict() && !hasStopConflict(), "Function requires valid conflict"); + cc_.clear(); + std::swap(cc_, conflict_); + if (searchMode() == SolverStrategies::no_learning) { + for (uint32 i = 1, end = decisionLevel() + 1; i != end; ++i) { cc_.push_back(decision(i)); } + } + const LitVec& trail = assign_.trail; + const LitVec* r = &cc_; + // resolve all-last uip + for (uint32 marked = 0, tPos = (uint32)trail.size();; r = &conflict_) { + for (LitVec::const_iterator it = r->begin(), end = r->end(); it != end; ++it) { + if (!seen(it->var())) { + assert(level(it->var()) <= decisionLevel()); + markSeen(it->var()); + ++marked; + } + } + if (marked-- == 0) { break; } + // search for the last marked literal + while (!seen(trail[--tPos].var())) { ; } + Literal p = trail[tPos]; + uint32 dl = level(p.var()); + assert(dl); + clearSeen(p.var()); + conflict_.clear(); + if (!reason(p).isNull()) { reason(p).reason(*this, p, conflict_); } + else if (p == decision(dl)) { out.push_back(p); } + } + // restore original conflict + std::swap(cc_, conflict_); +} + +// computes the First-UIP clause and stores it in cc_, where cc_[0] is the asserting literal (inverted UIP) +// and cc_[1] is a literal from the asserting level (if > 0) +// RETURN: asserting level of the derived conflict clause +uint32 Solver::analyzeConflict() { + // must be called here, because we unassign vars during analyzeConflict + heuristic_->undoUntil( *this, levels_.back().trailPos ); + uint32 onLevel = 0; // number of literals from the current DL in resolvent + uint32 resSize = 0; // size of current resolvent + Literal p; // literal to be resolved out next + cc_.assign(1, p); // will later be replaced with asserting literal + Antecedent lhs, rhs, last; // resolve operands + const bool doOtfs = strategy_.otfs > 0; + for (bumpAct_.clear();;) { + uint32 lhsSize = resSize; + uint32 rhsSize = 0; + heuristic_->updateReason(*this, conflict_, p); + for (LitVec::size_type i = 0; i != conflict_.size(); ++i) { + Literal& q = conflict_[i]; + uint32 cl = level(q.var()); + rhsSize += (cl != 0); + if (!seen(q.var())) { + ++resSize; + assert(isTrue(q) && "Invalid literal in reason set!"); + assert(cl > 0 && "Top-Level implication not marked!"); + markSeen(q.var()); + if (cl == decisionLevel()) { + ++onLevel; + } + else { + cc_.push_back(~q); + markLevel(cl); + } + } + } + if (resSize != lhsSize) { lhs = 0; } + if (rhsSize != resSize) { rhs = 0; } + if (doOtfs && (!rhs.isNull() || !lhs.isNull())) { + // resolvent subsumes rhs and possibly also lhs + otfs(lhs, rhs, p, onLevel == 1); + } + assert(onLevel > 0 && "CONFLICT MUST BE ANALYZED ON CONFLICT LEVEL!"); + // search for the last assigned literal that needs to be analyzed... + while (!seen(assign_.last().var())) { + assign_.undoLast(); + } + p = assign_.last(); + rhs = reason(p); + clearSeen(p.var()); + if (--onLevel == 0) { + break; + } + --resSize; // p will be resolved out next + last = rhs; + reason(p, conflict_); + } + cc_[0] = ~p; // store the 1-UIP + assert(decisionLevel() == level(cc_[0].var())); + ClauseHead* lastRes = 0; + if (strategy_.otfs > 1 || !lhs.isNull()) { + if (!lhs.isNull()) { + lastRes = clause(lhs); + } + else if (cc_.size() <= (conflict_.size()+1)) { + lastRes = clause(last); + } + } + if (strategy_.bumpVarAct && reason(p).learnt()) { + bumpAct_.push_back(WeightLiteral(p, reason(p).constraint()->activity().lbd())); + } + return simplifyConflictClause(cc_, ccInfo_, lastRes); +} + +void Solver::otfs(Antecedent& lhs, const Antecedent& rhs, Literal p, bool final) { + ClauseHead* cLhs = clause(lhs), *cRhs = clause(rhs); + ClauseHead::BoolPair x; + if (cLhs) { + x = cLhs->strengthen(*this, ~p, !final); + if (!x.first || x.second) { + cLhs = !x.first ? 0 : otfsRemove(cLhs, 0); + } + } + lhs = cLhs; + if (cRhs) { + x = cRhs->strengthen(*this, p, !final); + if (!x.first || (x.second && otfsRemove(cRhs, 0) == 0)) { + if (x.first && reason(p) == cRhs) { setReason(p, 0); } + cRhs = 0; + } + if (cLhs && cRhs) { + // lhs and rhs are now equal - only one of them is needed + if (!cLhs->learnt()) { + std::swap(cLhs, cRhs); + } + otfsRemove(cLhs, 0); + } + lhs = cRhs; + } +} + +ClauseHead* Solver::otfsRemove(ClauseHead* c, const LitVec* newC) { + bool remStatic = !newC || (newC->size() <= 3 && shared_->allowImplicit(Constraint_t::Conflict)); + if (c->learnt() || remStatic) { + ConstraintDB& db = (c->learnt() ? learnts_ : constraints_); + ConstraintDB::iterator it; + if ((it = std::find(db.begin(), db.end(), c)) != db.end()) { + if (isMaster() && &db == &constraints_) { + shared_->removeConstraint(static_cast(it - db.begin()), true); + } + else { + db.erase(it); + c->destroy(this, true); + } + c = 0; + } + } + return c; +} + +// minimizes the conflict clause in cc w.r.t selected strategies. +// PRE: +// - cc is a valid conflict clause and cc[0] is the UIP-literal +// - all literals in cc except cc[0] are marked +// - all decision levels of literals in cc are marked +// - rhs is 0 or a clause that might be subsumed by cc +// RETURN: finalizeConflictClause(cc, info) +uint32 Solver::simplifyConflictClause(LitVec& cc, ConstraintInfo& info, ClauseHead* rhs) { + // 1. remove redundant literals from conflict clause + temp_.clear(); + uint32 onAssert = ccMinimize(cc, temp_, strategy_.ccMinAntes, ccMin_); + uint32 jl = cc.size() > 1 ? level(cc[1].var()) : 0; + // clear seen flags of removed literals - keep levels marked + for (LitVec::size_type x = 0, stop = temp_.size(); x != stop; ++x) { + clearSeen(temp_[x].var()); + } + // 2. check for inverse arcs + if (onAssert == 1 && strategy_.reverseArcs > 0) { + uint32 maxN = (uint32)strategy_.reverseArcs; + if (maxN > 2) maxN = UINT32_MAX; + else if (maxN > 1) maxN = static_cast(cc.size() / 2); + markSeen(cc[0].var()); + Antecedent ante = ccHasReverseArc(cc[1], jl, maxN); + if (!ante.isNull()) { + // resolve with inverse arc + conflict_.clear(); + ante.reason(*this, ~cc[1], conflict_); + ccResolve(cc, 1, conflict_); + } + clearSeen(cc[0].var()); + } + // 3. check if final clause subsumes rhs + if (rhs) { + conflict_.clear(); + rhs->toLits(conflict_); + uint32 open = (uint32)cc.size(); + markSeen(cc[0].var()); + for (LitVec::const_iterator it = conflict_.begin(), end = conflict_.end(); it != end && open; ++it) { + // NOTE: at this point the DB might not be fully simplified, + // e.g. because of mt or lookahead, hence we must explicitly + // check for literals assigned on DL 0 + open -= level(it->var()) > 0 && seen(it->var()); + } + rhs = open ? 0 : otfsRemove(rhs, &cc); + if (rhs) { // rhs is subsumed by cc but could not be removed. + // TODO: we could reuse rhs instead of learning cc + // but this would complicate the calling code. + ClauseHead::BoolPair r(true, false); + if (cc_.size() < conflict_.size()) { + // For now, we only try to strengthen rhs. + for (LitVec::const_iterator it = conflict_.begin(), end = conflict_.end(); it != end && r.first; ++it) { + if (!seen(it->var()) || level(it->var()) == 0) { + r = rhs->strengthen(*this, *it, false); + } + } + if (!r.first) { rhs = 0; } + } + } + clearSeen(cc[0].var()); + } + // 4. finalize + uint32 repMode = cc.size() < std::max(strategy_.compress, decisionLevel()+1) ? 0 : strategy_.ccRepMode; + jl = finalizeConflictClause(cc, info, repMode); + // 5. bump vars implied by learnt constraints with small lbd + if (!bumpAct_.empty()) { + WeightLitVec::iterator j = bumpAct_.begin(); + weight_t newLbd = info.lbd(); + for (WeightLitVec::iterator it = bumpAct_.begin(), end = bumpAct_.end(); it != end; ++it) { + if (it->second < newLbd) { + it->second = 1 + (it->second <= 2); + *j++ = *it; + } + } + bumpAct_.erase(j, bumpAct_.end()); + heuristic_->bump(*this, bumpAct_, 1.0); + } + bumpAct_.clear(); + // 6. clear level flags of redundant literals + for (LitVec::size_type x = 0, stop = temp_.size(); x != stop; ++x) { + unmarkLevel(level(temp_[x].var())); + } + temp_.clear(); + return jl; +} + +// conflict clause minimization +// PRE: +// - cc is an asserting clause and cc[0] is the asserting literal +// - all literals in cc are marked as seen +// - if ccMin != 0, all decision levels of literals in cc are marked +// POST: +// - redundant literals were added to removed +// - if (cc.size() > 1): cc[1] is a literal from the asserting level +// RETURN +// - the number of literals from the asserting level +uint32 Solver::ccMinimize(LitVec& cc, LitVec& removed, uint32 antes, CCMinRecursive* ccMin) { + if (ccMin) { ccMinRecurseInit(*ccMin); } + // skip the asserting literal + LitVec::size_type j = 1; + uint32 assertLevel = 0; + uint32 assertPos = 1; + uint32 onAssert = 0; + uint32 varLevel = 0; + for (LitVec::size_type i = 1; i != cc.size(); ++i) { + if (antes == 0 || !ccRemovable(~cc[i], antes-1, ccMin)) { + if ( (varLevel = level(cc[i].var())) > assertLevel ) { + assertLevel = varLevel; + assertPos = static_cast(j); + onAssert = 0; + } + onAssert += (varLevel == assertLevel); + cc[j++] = cc[i]; + } + else { + removed.push_back(cc[i]); + } + } + cc.erase(cc.begin()+j, cc.end()); + if (assertPos != 1) { + std::swap(cc[1], cc[assertPos]); + } + return onAssert; +} +void Solver::ccMinRecurseInit(CCMinRecursive& ccMin) { + ccMin.open = incEpoch(numVars() + 1, 2) - 2; +} +bool Solver::ccMinRecurse(CCMinRecursive& ccMin, Literal p) const { + CCMinRecursive::State st = ccMin.decodeState(epoch_[p.var()]); + if (st == CCMinRecursive::state_poison) { return false; } + if (st == CCMinRecursive::state_open) { ccMin.push(p.unflag()); } + return true; +} + +// returns true if p is redundant in current conflict clause +bool Solver::ccRemovable(Literal p, uint32 antes, CCMinRecursive* ccMin) { + const Antecedent& ante = reason(p); + if (ante.isNull() || !(antes <= (uint32)ante.type())) { + return false; + } + if (!ccMin) { return ante.minimize(*this, p, 0); } + // recursive minimization + assert(ccMin->todo.empty()); + CCMinRecursive::State dfsState = CCMinRecursive::state_removable; + ccMin->push(p.unflag()); + for (Literal x;; ) { + x = ccMin->pop(); + assert(!seen(x.var()) || x == p); + if (x.flagged()) { + if (x == p) return dfsState == CCMinRecursive::state_removable; + epoch_[x.var()] = ccMin->encodeState(dfsState); + } + else if (dfsState != CCMinRecursive::state_poison) { + CCMinRecursive::State temp = ccMin->decodeState(epoch_[x.var()]); + if (temp == CCMinRecursive::state_open) { + assert(value(x.var()) != value_free && hasLevel(level(x.var()))); + ccMin->push(x.flag()); + const Antecedent& next = reason(x); + if (next.isNull() || !(antes <= (uint32)next.type()) || !next.minimize(*this, x, ccMin)) { + dfsState = CCMinRecursive::state_poison; + } + } + else if (temp == CCMinRecursive::state_poison) { + dfsState = temp; + } + } + } +} + +// checks whether there is a valid "inverse arc" for the given literal p that can be used +// to resolve p out of the current conflict clause +// PRE: +// - all literals in the current conflict clause are marked +// - p is a literal of the current conflict clause and level(p) == maxLevel +// RETURN +// - An antecedent that is an "inverse arc" for p or null if no such antecedent exists. +Antecedent Solver::ccHasReverseArc(Literal p, uint32 maxLevel, uint32 maxNew) { + assert(seen(p.var()) && isFalse(p) && level(p.var()) == maxLevel); + const ShortImplicationsGraph& btig = shared_->shortImplications(); + Antecedent ante; + if (p.id() < btig.size() && btig.reverseArc(*this, p, maxLevel, ante)) { return ante; } + WatchList& wl = watches_[p.id()]; + for (WatchList::left_iterator it = wl.left_begin(), end = wl.left_end(); it != end; ++it) { + if (it->head->isReverseReason(*this, ~p, maxLevel, maxNew)) { + return it->head; + } + } + return ante; +} + +// removes cc[pos] by resolving cc with reason +void Solver::ccResolve(LitVec& cc, uint32 pos, const LitVec& reason) { + heuristic_->updateReason(*this, reason, cc[pos]); + Literal x; + for (LitVec::size_type i = 0; i != reason.size(); ++i) { + x = reason[i]; + assert(isTrue(x)); + if (!seen(x.var())) { + markLevel(level(x.var())); + cc.push_back(~x); + } + } + clearSeen(cc[pos].var()); + unmarkLevel(level(cc[pos].var())); + cc[pos] = cc.back(); + cc.pop_back(); +} + +// computes asserting level and lbd of cc and clears flags. +// POST: +// - literals and decision levels in cc are no longer marked +// - if cc.size() > 1: cc[1] is a literal from the asserting level +// RETURN: asserting level of conflict clause. +uint32 Solver::finalizeConflictClause(LitVec& cc, ConstraintInfo& info, uint32 ccRepMode) { + // 2. clear flags and compute lbd + uint32 lbd = 1; + uint32 onRoot = 0; + uint32 varLevel = 0; + uint32 assertLevel = 0; + uint32 assertPos = 1; + uint32 maxVar = cc[0].var(); + Literal tagLit = ~tagLiteral(); + bool tagged = false; + for (LitVec::size_type i = 1; i != cc.size(); ++i) { + Var v = cc[i].var(); + clearSeen(v); + if (cc[i] == tagLit) { tagged = true; } + if (v > maxVar) { maxVar = v; } + if ( (varLevel = level(v)) > assertLevel ) { + assertLevel = varLevel; + assertPos = static_cast(i); + } + if (hasLevel(varLevel)) { + unmarkLevel(varLevel); + lbd += (varLevel > rootLevel()) || (++onRoot == 1); + } + } + if (assertPos != 1) { std::swap(cc[1], cc[assertPos]); } + if (ccRepMode == SolverStrategies::cc_rep_dynamic) { + ccRepMode = double(lbd)/double(decisionLevel()) > .66 ? SolverStrategies::cc_rep_decision : SolverStrategies::cc_rep_uip; + } + if (ccRepMode) { + maxVar = cc[0].var(), tagged = false, lbd = 1; + if (ccRepMode == SolverStrategies::cc_rep_decision) { + // replace cc with decision sequence + cc.resize(assertLevel+1); + for (uint32 i = assertLevel; i;){ + Literal x = ~decision(i--); + cc[lbd++] = x; + if (x == tagLit) { tagged = true; } + if (x.var() > maxVar){ maxVar = x.var(); } + } + } + else { + // replace cc with all uip clause + uint32 marked = sizeVec(cc) - 1; + while (cc.size() > 1) { markSeen(~cc.back()); cc.pop_back(); } + for (LitVec::const_iterator tr = assign_.trail.end(), next, stop; marked;) { + while (!seen(*--tr)) { ; } + bool n = --marked != 0 && !reason(*tr).isNull(); + clearSeen(tr->var()); + if (n) { for (next = tr, stop = assign_.trail.begin() + levelStart(level(tr->var())); next-- != stop && !seen(*next);) { ; } } + if (!n || level(next->var()) != level(tr->var())) { + cc.push_back(~*tr); + if (tr->var() == tagLit.var()){ tagged = true; } + if (tr->var() > maxVar) { maxVar = tr->var(); } + } + else { + for (reason(*tr, conflict_); !conflict_.empty(); conflict_.pop_back()) { + if (!seen(conflict_.back())) { ++marked; markSeen(conflict_.back()); } + } + } + } + lbd = sizeVec(cc); + } + } + info.setScore(makeScore(ccInfo_.activity(), lbd)); + info.setTagged(tagged); + info.setAux(auxVar(maxVar)); + return assertLevel; +} + +// (inefficient) default implementation +bool Constraint::minimize(Solver& s, Literal p, CCMinRecursive* rec) { + LitVec temp; + reason(s, p, temp); + for (LitVec::size_type i = 0; i != temp.size(); ++i) { + if (!s.ccMinimize(temp[i], rec)) { + return false; + } + } + return true; +} + +// Selects next branching literal +bool Solver::decideNextBranch(double f) { + if (f <= 0.0 || rng.drand() >= f || numFreeVars() == 0) { + return heuristic_->select(*this); + } + // select randomly + Literal choice; + uint32 maxVar = numVars() + 1; + for (uint32 v = rng.irand(maxVar);;) { + if (value(v) == value_free) { + choice = heuristic_->selectLiteral(*this, v, 0); + break; + } + if (++v == maxVar) { v = 1; } + } + return assume(choice); +} +void Solver::resetLearntActivities() { + for (ConstraintDB::size_type i = 0, end = learnts_.size(); i != end; ++i) { + learnts_[i]->resetActivity(); + } +} +// Removes up to remFrac% of the learnt nogoods but +// keeps those that are locked or are highly active. +Solver::DBInfo Solver::reduceLearnts(float remFrac, const ReduceStrategy& rs) { + uint32 oldS = numLearntConstraints(); + uint32 remM = static_cast(oldS * std::max(0.0f, remFrac)); + DBInfo r = {0,0,0}; + CmpScore cmp(learnts_, (ReduceStrategy::Score)rs.score, rs.glue, rs.protect); + if (remM >= oldS || !remM || rs.algo == ReduceStrategy::reduce_sort) { + r = reduceSortInPlace(remM, cmp, false); + } + else if (rs.algo == ReduceStrategy::reduce_stable) { r = reduceSort(remM, cmp); } + else if (rs.algo == ReduceStrategy::reduce_heap) { r = reduceSortInPlace(remM, cmp, true);} + else { r = reduceLinear(remM, cmp); } + stats.addDeleted(oldS - r.size); + shrinkVecTo(learnts_, r.size); + return r; +} +// Removes up to maxR of the learnt nogoods. +// Keeps those that are locked or have a high activity and +// does not reorder learnts_. +Solver::DBInfo Solver::reduceLinear(uint32 maxR, const CmpScore& sc) { + // compute average activity + uint64 scoreSum = 0; + for (LitVec::size_type i = 0; i != learnts_.size(); ++i) { + scoreSum += sc.score(learnts_[i]->activity()); + } + double avgAct = (scoreSum / (double) numLearntConstraints()); + // constraints with socre > 1.5 times the average are "active" + double scoreThresh = avgAct * 1.5; + double scoreMax = (double)sc.score(makeScore(Clasp::ACT_MAX, 1)); + if (scoreThresh > scoreMax) { + scoreThresh = (scoreMax + (scoreSum / (double) numLearntConstraints())) / 2.0; + } + // remove up to maxR constraints but keep "active" and locked once + DBInfo res = {0,0,0}; + typedef ConstraintScore ScoreType; + for (LitVec::size_type i = 0; i != learnts_.size(); ++i) { + Constraint* c = learnts_[i]; + ScoreType a = c->activity(); + bool isLocked = c->locked(*this); + bool isGlue = sc.score(a) > scoreThresh || sc.isGlue(a); + if (maxR == 0 || isLocked || isGlue || sc.isFrozen(a)) { + res.pinned += isGlue; + res.locked += isLocked; + learnts_[res.size++] = c; + c->decreaseActivity(); + } + else { + --maxR; + c->destroy(this, true); + } + } + return res; +} + +// Sorts learnt constraints by score and removes the +// maxR constraints with the lowest score without +// reordering learnts_. +Solver::DBInfo Solver::reduceSort(uint32 maxR, const CmpScore& sc) { + typedef PodVector::type HeapType; + DBInfo res = {0,0,0}; + HeapType heap; + heap.reserve(maxR = std::min(maxR, (uint32)learnts_.size())); + bool isGlue, isLocked; + for (LitVec::size_type i = 0; i != learnts_.size(); ++i) { + Constraint* c = learnts_[i]; + CmpScore::ViewPair vp(toU32(i), c->activity()); + res.pinned += (isGlue = sc.isGlue(vp.second)); + res.locked += (isLocked = c->locked(*this)); + if (!isLocked && !isGlue && !sc.isFrozen(vp.second)) { + if (maxR) { // populate heap with first maxR constraints + heap.push_back(vp); + if (--maxR == 0) { std::make_heap(heap.begin(), heap.end(), sc); } + } + else if (sc(vp, heap[0])) { // replace max element in heap + std::pop_heap(heap.begin(), heap.end(), sc); + heap.back() = vp; + std::push_heap(heap.begin(), heap.end(), sc); + } + } + } + // Remove all constraints in heap - those are "inactive". + for (HeapType::const_iterator it = heap.begin(), end = heap.end(); it != end; ++it) { + learnts_[it->first]->destroy(this, true); + learnts_[it->first] = 0; + } + // Cleanup db and decrease activity of remaining constraints. + uint32 j = 0; + for (LitVec::size_type i = 0; i != learnts_.size(); ++i) { + if (Constraint* c = learnts_[i]) { + c->decreaseActivity(); + learnts_[j++] = c; + } + } + res.size = j; + return res; +} + +// Sorts the learnt db by score and removes the first +// maxR constraints (those with the lowest score). +Solver::DBInfo Solver::reduceSortInPlace(uint32 maxR, const CmpScore& sc, bool partial) { + DBInfo res = {0,0,0}; + ConstraintDB::iterator nEnd = learnts_.begin(); + maxR = std::min(maxR, (uint32)learnts_.size()); + bool isGlue, isLocked; + typedef ConstraintScore ScoreType; + if (!partial) { + // sort whole db and remove first maxR constraints + if (maxR && maxR != learnts_.size()) std::stable_sort(learnts_.begin(), learnts_.end(), sc); + for (ConstraintDB::iterator it = learnts_.begin(), end = learnts_.end(); it != end; ++it) { + Constraint* c = *it; + ScoreType a = c->activity(); + res.pinned += (isGlue = sc.isGlue(a)); + res.locked += (isLocked = c->locked(*this)); + if (!maxR || isLocked || isGlue || sc.isFrozen(a)) { + c->decreaseActivity(); + *nEnd++ = c; + } + else { + c->destroy(this, true); + --maxR; + } + } + } + else { + ConstraintDB::iterator hBeg = learnts_.begin(); + ConstraintDB::iterator hEnd = learnts_.begin(); + for (ConstraintDB::iterator it = learnts_.begin(), end = learnts_.end(); it != end; ++it) { + Constraint* c = *it; + ScoreType a = c->activity(); + res.pinned += (isGlue = sc.isGlue(a)); + res.locked += (isLocked = c->locked(*this)); + if (isLocked || isGlue || sc.isFrozen(a)) { continue; } + else if (maxR) { + *it = *hEnd; + *hEnd++ = c; + if (--maxR == 0) { std::make_heap(hBeg, hEnd, sc); } + } + else if (sc(c, learnts_[0])) { + std::pop_heap(hBeg, hEnd, sc); + *it = *(hEnd-1); + *(hEnd-1)= c; + std::push_heap(hBeg, hEnd, sc); + } + } + // remove all constraints in heap + for (ConstraintDB::iterator it = hBeg; it != hEnd; ++it) { + (*it)->destroy(this, true); + } + // copy remaining constraints down + for (ConstraintDB::iterator it = hEnd, end = learnts_.end(); it != end; ++it) { + Constraint* c = *it; + c->decreaseActivity(); + *nEnd++ = c; + } + } + res.size = static_cast(std::distance(learnts_.begin(), nEnd)); + return res; +} +uint32 Solver::incEpoch(uint32 size, uint32 n) { + if (size > epoch_.size()) { epoch_.resize(size, 0u); } + if ((UINT32_MAX - epoch_[0]) < n) { epoch_.assign(epoch_.size(), 0u); } + return epoch_[0] += n; +} +uint32 Solver::countLevels(const Literal* first, const Literal* last, uint32 maxLevel) { + if (maxLevel < 2) { return uint32(maxLevel && first != last); } + CLASP_FAIL_IF(ccMin_ && !ccMin_->todo.empty(), "Must not be called during minimization!"); + uint32 n = 0; + for (uint32 epoch = incEpoch(sizeVec(levels_) + 1); first != last; ++first) { + assert(value(first->var()) != value_free); + uint32& levEpoch = epoch_[level(first->var())]; + if (levEpoch != epoch) { + levEpoch = epoch; + if (++n == maxLevel) { break; } + } + } + return n; +} + +void Solver::updateBranch(uint32 n) { + int32 dl = (int32)decisionLevel(), xl = static_cast(cflStamp_.size())-1; + if (xl > dl) { do { n += cflStamp_.back(); cflStamp_.pop_back(); } while (--xl != dl); } + else if (dl > xl) { cflStamp_.insert(cflStamp_.end(), dl - xl, 0); } + cflStamp_.back() += n; +} +bool Solver::reduceReached(const SearchLimits& limits) const { + return numLearntConstraints() > limits.learnts || memUse_ > limits.memory; +} +bool Solver::restartReached(const SearchLimits& limits) const { + uint64 n = !limits.restart.local || cflStamp_.empty() ? limits.used : cflStamp_.back(); + return n >= limits.restart.conflicts || (limits.restart.dynamic && limits.restart.dynamic->reached()); +} +///////////////////////////////////////////////////////////////////////////////////////// +// The basic DPLL-like search-function +///////////////////////////////////////////////////////////////////////////////////////// +ValueRep Solver::search(SearchLimits& limit, double rf) { + assert(!isFalse(tagLiteral())); + SearchLimits::BlockPtr block = limit.restart.block; + rf = std::max(0.0, std::min(1.0, rf)); + lower.reset(); + if (limit.restart.local && decisionLevel() == rootLevel()) { cflStamp_.assign(decisionLevel()+1, 0); } + do { + for (bool conflict = hasConflict() || !propagate() || !simplify(), local = limit.restart.local;;) { + if (conflict) { + uint32 n = 1, ts; + do { + if (block && block->push(ts = numAssignedVars()) && ts > block->scaled()) { + if (limit.restart.dynamic) { limit.restart.dynamic->resetRun(); } + else { limit.restart.conflicts += block->inc; } + block->next = block->n + block->inc; + } + } while (resolveConflict() && !propagate() && (++n, true)); + limit.used += n; + if (local) { updateBranch(n); } + if (hasConflict() || (decisionLevel() == 0 && !simplify())) { return value_false; } + if (numFreeVars()) { + if (limit.used >= limit.conflicts) { return value_free; } + if (restartReached(limit)) { return value_free; } + if (reduceReached(limit)) { return value_free; } + } + } + if (decideNextBranch(rf)) { conflict = !propagate(); } + else { break; } + } + } while (!isModel()); + temp_.clear(); + model.clear(); model.reserve(numVars()+1); + for (Var v = 0; v <= numVars(); ++v) { model.push_back(value(v)); } + if (satPrepro()) { satPrepro()->extendModel(model, temp_); } + return value_true; +} +ValueRep Solver::search(uint64 maxC, uint32 maxL, bool local, double rp) { + SearchLimits limit; + limit.restart.conflicts = maxC; + limit.restart.local = local; + limit.learnts = maxL; + return search(limit, rp); +} +bool Solver::isModel() { + if (hasConflict()) { return false; } + FOR_EACH_POST(x, post_.head()) { + if (!x->isModel(*this)) { return false; } + } + return !enumerationConstraint() || enumerationConstraint()->valid(*this); +} +///////////////////////////////////////////////////////////////////////////////////////// +// Free functions +///////////////////////////////////////////////////////////////////////////////////////// +void destroyDB(Solver::ConstraintDB& db, Solver* s, bool detach) { + if (s && detach) { + s->destroyDB(db); + return; + } + while (!db.empty()) { + db.back()->destroy(s, detach); + db.pop_back(); + } +} +} diff --git a/libclasp/src/solver_strategies.cpp b/libclasp/src/solver_strategies.cpp new file mode 100644 index 0000000..41026cc --- /dev/null +++ b/libclasp/src/solver_strategies.cpp @@ -0,0 +1,310 @@ +// +// Copyright (c) Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// SolverStrategies / SolverParams +///////////////////////////////////////////////////////////////////////////////////////// +SolverStrategies::SolverStrategies() { + struct X { uint32 z[2]; }; + static_assert(sizeof(SolverStrategies) == sizeof(X), "Unsupported Padding"); + std::memset(this, 0, sizeof(SolverStrategies)); + ccMinAntes = all_antes; + initWatches= SolverStrategies::watch_rand; + search = use_learning; +} +void SolverStrategies::prepare() { + if (search == SolverStrategies::no_learning) { + compress = 0; + saveProgress= 0; + reverseArcs = 0; + otfs = 0; + updateLbd = 0; + ccMinAntes = SolverStrategies::no_antes; + bumpVarAct = 0; + } +} +HeuParams::HeuParams() { + std::memset(this, 0, sizeof(HeuParams)); + other = other_auto; + moms = 1; +} +SolverParams::SolverParams() { + struct X { uint32 strat[2]; uint32 self[4]; }; + static_assert(sizeof(SolverParams) == sizeof(X), "Unsupported Padding"); + std::memset(&seed, 0, sizeof(uint32)*2); + seed = RNG().seed(); +} +uint32 SolverParams::prepare() { + uint32 res = 0; + if (search == SolverStrategies::no_learning && Heuristic_t::isLookback(heuId)) { + heuId = Heuristic_t::None; + res |= 1; + } + if (heuId == Heuristic_t::Unit) { + if (!Lookahead::isType(lookType)) { res |= 2; lookType = Var_t::Atom; } + lookOps = 0; + } + if (heuId != Heuristic_t::Domain && (heuristic.domPref || heuristic.domMod)) { + res |= 4; + heuristic.domPref= 0; + heuristic.domMod = 0; + } + SolverStrategies::prepare(); + return res; +} +///////////////////////////////////////////////////////////////////////////////////////// +// ScheduleStrategy +///////////////////////////////////////////////////////////////////////////////////////// +double growR(uint32 idx, double g) { return pow(g, (double)idx); } +double addR(uint32 idx, double a) { return a * idx; } +uint32 lubyR(uint32 idx) { + uint32 i = idx + 1; + while ((i & (i+1)) != 0) { + i -= ((1u << log2(i)) - 1); + } + return (i+1)>>1; +} +ScheduleStrategy::ScheduleStrategy(Type t, uint32 b, double up, uint32 lim) + : base(b), type(t), idx(0), len(lim), grow(0.0) { + if (t == Geometric) { grow = static_cast(std::max(1.0, up)); } + else if (t == Arithmetic) { grow = static_cast(std::max(0.0, up)); } + else if (t == User) { grow = static_cast(std::max(0.0, up)); } + else if (t == Luby && lim){ len = std::max(uint32(2), (static_cast(std::pow(2.0, std::ceil(log(double(lim))/log(2.0)))) - 1)*2); } +} + +uint64 ScheduleStrategy::current() const { + enum { t_add = ScheduleStrategy::Arithmetic, t_luby = ScheduleStrategy::Luby }; + if (base == 0) return UINT64_MAX; + else if (type == t_add) return static_cast(addR(idx, grow) + base); + else if (type == t_luby)return static_cast(lubyR(idx)) * base; + uint64 x = static_cast(growR(idx, grow) * base); + return x + !x; +} +uint64 ScheduleStrategy::next() { + if (++idx != len) { return current(); } + // length reached or overflow + len = (len + !!idx) << uint32(type == Luby); + idx = 0; + return current(); +} +void ScheduleStrategy::advanceTo(uint32 n) { + if (!len || n < len) { + idx = n; + return; + } + if (type != Luby) { + double dLen = len; + uint32 x = uint32(sqrt(dLen * (4.0 * dLen - 4.0) + 8.0 * double(n+1))-2*dLen+1)/2; + idx = n - uint32(x*dLen+double(x-1.0)*x/2.0); + len += x; + return; + } + while (n >= len) { + n -= len++; + len *= 2; + } + idx = n; +} +///////////////////////////////////////////////////////////////////////////////////////// +// RestartParams +///////////////////////////////////////////////////////////////////////////////////////// +RestartParams::RestartParams() + : sched() + , blockScale(1.4f), blockWindow(0), blockFirst(0) + , counterRestart(0), counterBump(9973) + , shuffle(0), shuffleNext(0) + , upRestart(0), cntLocal(0), dynRestart(0) { + static_assert(sizeof(RestartParams) == sizeof(ScheduleStrategy) + (3 * sizeof(uint32)) + sizeof(float), "Invalid structure alignment"); +} +void RestartParams::disable() { + std::memset(this, 0, sizeof(RestartParams)); + sched = ScheduleStrategy::none(); +} +uint32 RestartParams::prepare(bool withLookback) { + if (!withLookback || sched.disabled()) { + disable(); + } + return 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// ReduceParams +///////////////////////////////////////////////////////////////////////////////////////// +uint32 ReduceParams::getLimit(uint32 base, double f, const Range32& r) { + base = (f != 0.0 ? (uint32)std::min(base*f, double(UINT32_MAX)) : UINT32_MAX); + return r.clamp( base ); +} +uint32 ReduceParams::getBase(const SharedContext& ctx) const { + uint32 st = strategy.estimate != ReduceStrategy::est_dynamic || ctx.isExtended() ? strategy.estimate : (uint32)ReduceStrategy::est_num_constraints; + switch(st) { + default: + case ReduceStrategy::est_dynamic : { + uint32 m = std::min(ctx.stats().vars.num, ctx.stats().numConstraints()); + uint32 M = std::max(ctx.stats().vars.num, ctx.stats().numConstraints()); + return M > (m * 10) ? M : m; + } + case ReduceStrategy::est_con_complexity : return ctx.stats().complexity; + case ReduceStrategy::est_num_constraints: return ctx.stats().numConstraints(); + case ReduceStrategy::est_num_vars : return ctx.stats().vars.num; + } +} +void ReduceParams::disable() { + cflSched = ScheduleStrategy::none(); + growSched = ScheduleStrategy::none(); + strategy.fReduce = 0; + fGrow = 0.0f; fInit = 0.0f; fMax = 0.0f; + initRange = Range(UINT32_MAX, UINT32_MAX); + maxRange = UINT32_MAX; + memMax = 0; +} +Range32 ReduceParams::sizeInit(const SharedContext& ctx) const { + if (!growSched.disabled() || growSched.defaulted()) { + uint32 base = getBase(ctx); + uint32 lo = std::min(getLimit(base, fInit, initRange), maxRange); + uint32 hi = getLimit(base, fMax, Range32(lo, maxRange)); + return Range32(lo, hi); + } + return Range32(maxRange, maxRange); +} +uint32 ReduceParams::cflInit(const SharedContext& ctx) const { + return cflSched.disabled() ? 0 : getLimit(getBase(ctx), fInit, initRange); +} +uint32 ReduceParams::prepare(bool withLookback) { + if (!withLookback || fReduce() == 0.0f) { + disable(); + return 0; + } + if (cflSched.defaulted() && growSched.disabled() && !growSched.defaulted()) { + cflSched = ScheduleStrategy::arith(4000, 600); + } + if (fMax != 0.0f) { fMax = std::max(fMax, fInit); } + return 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// SolveParams +///////////////////////////////////////////////////////////////////////////////////////// +SolveParams::SolveParams() + : randRuns(0u), randConf(0u) + , randProb(0.0f) { +} +uint32 SolveParams::prepare(bool withLookback) { + return restart.prepare(withLookback) | reduce.prepare(withLookback); +} +bool SolveParams::randomize(Solver& s) const { + for (uint32 r = 0, c = randConf; r != randRuns && c; ++r) { + if (s.search(c, UINT32_MAX, false, 1.0) != value_free) { return !s.hasConflict(); } + s.undoUntil(0); + } + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// Configurations +///////////////////////////////////////////////////////////////////////////////////////// +Configuration::~Configuration() {} +Configuration* Configuration::config(const char* n) { + return !n || !*n || ((*n == '.' || *n == '/') && !n[1]) ? this : 0; +} +bool UserConfiguration::addPost(Solver& s) const { + const SolverOpts& x = solver(s.id()); + bool ok = true; + if (Lookahead::isType(x.lookType)) { + PostPropagator* pp = s.getPost(PostPropagator::priority_reserved_look); + if (pp) { pp->destroy(&s, true); } + Lookahead::Params p(static_cast(x.lookType)); + p.nant(x.heuristic.nant != 0); + p.limit(x.lookOps); + ok = s.addPost(new Lookahead(p)); + } + return ok; +} +BasicSatConfig::BasicSatConfig() { + solver_.push_back(SolverParams()); + search_.push_back(SolveParams()); + heu_ = 0; +} +void BasicSatConfig::prepare(SharedContext& ctx) { + uint32 warn = 0; + for (uint32 i = 0, end = solver_.size(), mod = search_.size(); i != end; ++i) { + warn |= solver_[i].prepare(); + warn |= search_[i%mod].prepare(solver_[i].search != SolverStrategies::no_learning); + if (solver_[i].updateLbd == 0 && search_[i%mod].reduce.strategy.protect) { warn |= 8; } + } + if ((warn & 1) != 0) { ctx.warn("Selected heuristic requires lookback strategy!"); } + if ((warn & 2) != 0) { ctx.warn("Heuristic 'Unit' implies lookahead. Using 'atom'."); } + if ((warn & 4) != 0) { ctx.warn("Domain options require heuristic 'Domain'!"); } + if ((warn & 8) != 0) { ctx.warn("Deletion protection requires LBD updates, which are off!"); } +} +DecisionHeuristic* BasicSatConfig::heuristic(uint32 i) const { + const SolverParams& p = BasicSatConfig::solver(i); + Heuristic_t::Type hId = static_cast(p.heuId); + if (hId == Heuristic_t::Default && p.search == SolverStrategies::use_learning) hId = Heuristic_t::Berkmin; + CLASP_FAIL_IF(p.search != SolverStrategies::use_learning && Heuristic_t::isLookback(hId), "Selected heuristic requires lookback!"); + DecisionHeuristic* h = 0; + if (heu_) { h = heu_(hId, p.heuristic); } + if (!h) { h = Heuristic_t::create(hId, p.heuristic); } + if (Lookahead::isType(p.lookType) && p.lookOps > 0 && hId != Heuristic_t::Unit) { + h = UnitHeuristic::restricted(h); + } + return h; +} +SolverParams& BasicSatConfig::addSolver(uint32 i) { + while (i >= solver_.size()) { + solver_.push_back(SolverParams().setId(static_cast(solver_.size()))); + } + return solver_[i]; +} +SolveParams& BasicSatConfig::addSearch(uint32 i) { + if (i >= search_.size()) { search_.resize(i+1); } + return search_[i]; +} + +void BasicSatConfig::reset() { + static_cast(*this) = ContextParams(); + BasicSatConfig::resize(1, 1); + solver_[0] = SolverParams(); + search_[0] = SolveParams(); +} +void BasicSatConfig::resize(uint32 solver, uint32 search) { + solver_.resize(solver); + search_.resize(search); +} +void BasicSatConfig::setHeuristicCreator(HeuristicCreator hc) { + heu_ = hc; +} +///////////////////////////////////////////////////////////////////////////////////////// +// Heuristics +///////////////////////////////////////////////////////////////////////////////////////// +DecisionHeuristic* Heuristic_t::create(Type id, const HeuParams& p) { + if (id == Berkmin) { return new ClaspBerkmin(p); } + if (id == Vmtf) { return new ClaspVmtf(p); } + if (id == Unit) { return new UnitHeuristic(); } + if (id == Vsids) { return new ClaspVsids(p); } + if (id == Domain) { return new DomainHeuristic(p); } + CLASP_FAIL_IF(id != Default && id != None, "Unknown heuristic id!"); + return new SelectFirst(); +} + +ModelHandler::~ModelHandler() {} +bool ModelHandler::onUnsat(const Solver&, const Model&) { return true; } +} diff --git a/libclasp/src/solver_types.cpp b/libclasp/src/solver_types.cpp new file mode 100644 index 0000000..fcdf54c --- /dev/null +++ b/libclasp/src/solver_types.cpp @@ -0,0 +1,303 @@ +// +// Copyright (c) 2006-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +namespace Clasp { +/////////////////////////////////////////////////////////////////////////////// +// SearchLimits +/////////////////////////////////////////////////////////////////////////////// +SearchLimits::SearchLimits() { + std::memset(this, 0, sizeof(SearchLimits)); + restart.conflicts = UINT64_MAX; + conflicts = UINT64_MAX; + memory = UINT64_MAX; + learnts = UINT32_MAX; +} +///////////////////////////////////////////////////////////////////////////////////////// +// DynamicLimit +///////////////////////////////////////////////////////////////////////////////////////// +DynamicLimit* DynamicLimit::create(uint32 size) { + CLASP_FAIL_IF(size == 0, "size must be > 0"); + void* m = ::operator new(sizeof(DynamicLimit) + (size*sizeof(uint32))); + return new (m)DynamicLimit(size); +} +DynamicLimit::DynamicLimit(uint32 sz) : cap_(sz), pos_(0), num_(0) { + std::memset(&global, 0, sizeof(global)); + init(0.7f, lbd_limit); +} +void DynamicLimit::init(float k, Type t, uint32 uLimit) { + resetRun(); + std::memset(&adjust, 0, sizeof(adjust)); + adjust.limit = uLimit; + adjust.rk = k; + adjust.type = t; +} +void DynamicLimit::destroy() { + this->~DynamicLimit(); + ::operator delete(this); +} +void DynamicLimit::resetRun() { + sum_[0] = sum_[1] = pos_ = num_ = 0; +} +void DynamicLimit::reset() { + std::memset(&global, 0, sizeof(global)); + resetRun(); +} +void DynamicLimit::update(uint32 dl, uint32 lbd) { + // update global avg + ++adjust.samples; + ++global.samples; + global.sum[lbd_limit] += lbd; + global.sum[level_limit] += dl; + // update moving avg + sum_[lbd_limit] += lbd; + sum_[level_limit] += dl; + if (++num_ > cap_) { + sum_[lbd_limit] -= (buffer_[pos_] & 127u); + sum_[level_limit] -= (buffer_[pos_] >> 7u); + } + buffer_[pos_++] = ((dl << 7) + lbd); + if (pos_ == cap_) { pos_ = 0; } +} +uint32 DynamicLimit::restart(uint32 maxLBD, float k) { + ++adjust.restarts; + if (adjust.samples >= adjust.limit) { + Type nt = global.avg(lbd_limit) > maxLBD ? level_limit : lbd_limit; + if (nt == adjust.type) { + double rLen = adjust.avgRestart(); + bool sx = num_ >= adjust.limit; + float rk = adjust.rk; + uint32 uLim = adjust.limit; + if (rLen >= 16000.0) { rk += 0.1f; uLim = 16000; } + else if (sx) { rk += 0.05f; uLim = std::max(uint32(16000), uLim-10000); } + else if (rLen >= 4000.0) { rk += 0.05f; } + else if (rLen >= 1000.0) { uLim += 10000u; } + else if (rk > k) { rk -= 0.05f; } + init(rk, nt, uLim); + } + else { init(k, nt); } + } + else { resetRun(); } + return adjust.limit; +} +BlockLimit::BlockLimit(uint32 windowSize, double R) + : ema(0.0), alpha(2.0/(windowSize+1)) + , next(windowSize), inc(50), n(0) + , span(windowSize) + , r(static_cast(R)) {} + +///////////////////////////////////////////////////////////////////////////////////////// +// Statistics +///////////////////////////////////////////////////////////////////////////////////////// +#define NO_ARG +#define CLASP_STAT_ACCU(m, k, a, accu) accu; +#define CLASP_STAT_KEY(m, k, a, accu) k, +#define CLASP_STAT_GET(m, k, a, accu) if (std::strcmp(key, k) == 0) { return a; } +#define CLASP_DEFINE_ISTATS_COMMON(T, STATS, name) \ + static const char* const T ## _s[] = { STATS(CLASP_STAT_KEY, NO_ARG, NO_ARG) name };\ + uint32 T::size() { return (sizeof(T ## _s)/sizeof(T ## _s[0]))-1; } \ + const char* T::key(uint32 i) { return i < size() ? T ## _s[i] : throw std::out_of_range(#T "::key"); } \ + void T::accu(const T& o) { STATS(CLASP_STAT_ACCU, (*this), o);} +///////////////////////////////////////////////////////////////////////////////////////// +// CoreStats +///////////////////////////////////////////////////////////////////////////////////////// +CLASP_DEFINE_ISTATS_COMMON(CoreStats, CLASP_CORE_STATS, "core") +StatisticObject CoreStats::at(const char* key) const { +#define VALUE(X) StatisticObject::value(&X) + CLASP_CORE_STATS(CLASP_STAT_GET, NO_ARG, NO_ARG); +#undef VALUE + throw std::out_of_range("CoreStats::at"); +} +void CoreStats::reset() { std::memset(this, 0, sizeof(*this)); } +///////////////////////////////////////////////////////////////////////////////////////// +// JumpStats +///////////////////////////////////////////////////////////////////////////////////////// +#define MAX_MEM(X, Y) X = std::max((X), (Y)) +CLASP_DEFINE_ISTATS_COMMON(JumpStats, CLASP_JUMP_STATS, "jumps") +#undef MAX_MEM +StatisticObject JumpStats::at(const char* key) const { +#define VALUE(X) StatisticObject::value(&X) + CLASP_JUMP_STATS(CLASP_STAT_GET, NO_ARG, NO_ARG); +#undef VALUE + throw std::out_of_range("JumpStats::at"); +} +void JumpStats::reset() { std::memset(this, 0, sizeof(*this)); } +///////////////////////////////////////////////////////////////////////////////////////// +// ExtendedStats +///////////////////////////////////////////////////////////////////////////////////////// +CLASP_DEFINE_ISTATS_COMMON(ExtendedStats, CLASP_EXTENDED_STATS, "extra") +namespace { +double _lemmas(const ExtendedStats* self) { return static_cast(self->lemmas()); } +double _learntLits(const ExtendedStats* self) { return static_cast(self->learntLits()); } +} +StatisticObject ExtendedStats::at(const char* key) const { +#define VALUE(X) StatisticObject::value(&X) +#define MEM_FUN(X) StatisticObject::value(this) +#define MAP(X) StatisticObject::map(&X) + CLASP_EXTENDED_STATS(CLASP_STAT_GET, NO_ARG, NO_ARG); +#undef VALUE +#undef MEM_FUN +#undef MAP + throw std::out_of_range("ExtendedStats::at"); +} +void ExtendedStats::reset() { + std::memset(this, 0, sizeof(ExtendedStats) - sizeof(JumpStats)); + jumps.reset(); +} +///////////////////////////////////////////////////////////////////////////////////////// +// SolverStats +///////////////////////////////////////////////////////////////////////////////////////// +SolverStats::SolverStats() : limit(0), extra(0), multi(0) {} +SolverStats::SolverStats(const SolverStats& o) : CoreStats(o), limit(0), extra(0), multi(0) { + if (o.extra && enableExtended()) { extra->accu(*o.extra); } +} +SolverStats::~SolverStats() { + delete extra; + if (limit) limit->destroy(); +} +bool SolverStats::enableExtended() { + return extra != 0 || (extra = new (std::nothrow) ExtendedStats()) != 0; +} +void SolverStats::enableLimit(uint32 size) { + if (limit && limit->window() != size) { limit->destroy(); limit = 0; } + if (!limit) { limit = DynamicLimit::create(size); } +} +void SolverStats::reset() { + CoreStats::reset(); + if (limit) limit->reset(); + if (extra) extra->reset(); +} +void SolverStats::accu(const SolverStats& o) { + CoreStats::accu(o); + if (extra && o.extra) extra->accu(*o.extra); +} +void SolverStats::accu(const SolverStats& o, bool enableRhs) { + if (enableRhs) { enable(o); } + accu(o); +} +void SolverStats::flush() const { + if (multi) { + multi->enable(*this); + multi->accu(*this); + multi->flush(); + } +} +void SolverStats::swapStats(SolverStats& o) { + std::swap(static_cast(*this), static_cast(o)); + std::swap(extra, o.extra); +} +uint32 SolverStats::size() const { + return CoreStats::size() + (extra != 0); +} +const char* SolverStats::key(uint32 i) const { + if (i >= size()) { throw std::out_of_range("SolverStats::key"); } + return i < CoreStats::size() ? CoreStats::key(i) : "extra"; +} +template +static bool matchPath(const char*& path, const char (&key)[n]) { + std::size_t kLen = n-1; + return std::strncmp(path, key, kLen) == 0 && (!path[kLen] || path[kLen++] == '.') && (path += kLen) != 0; +} +StatisticObject SolverStats::at(const char* k) const { + if (extra && matchPath(k, "extra")) { + return !*k ? StatisticObject::map(extra) : extra->at(k); + } + else { + return CoreStats::at(k); + } +} +void SolverStats::addTo(const char* key, StatsMap& solving, StatsMap* accu) const { + solving.add(key, StatisticObject::map(this)); + if (accu && this->multi) { multi->addTo(key, *accu, 0); } +} +#undef NO_ARG +#undef CLASP_STAT_ACCU +#undef CLASP_STAT_KEY +#undef CLASP_STAT_GET +#undef CLASP_DEFINE_ISTATS_COMMON +///////////////////////////////////////////////////////////////////////////////////////// +// ClauseHead +///////////////////////////////////////////////////////////////////////////////////////// +ClauseHead::ClauseHead(const InfoType& init) : info_(init){ + static_assert(sizeof(ClauseHead)<=32, "Unsupported Alignment"); + head_[2] = lit_false(); +} +void ClauseHead::resetScore(ScoreType sc) { + info_.setScore(sc); +} +void ClauseHead::attach(Solver& s) { + assert(head_[0] != head_[1] && head_[1] != head_[2]); + s.addWatch(~head_[0], ClauseWatch(this)); + s.addWatch(~head_[1], ClauseWatch(this)); +} + +void ClauseHead::detach(Solver& s) { + s.removeWatch(~head_[0], this); + s.removeWatch(~head_[1], this); +} + +bool ClauseHead::locked(const Solver& s) const { + return (s.isTrue(head_[0]) && s.reason(head_[0]) == this) + || (s.isTrue(head_[1]) && s.reason(head_[1]) == this); +} + +bool ClauseHead::satisfied(const Solver& s) const { + return s.isTrue(head_[0]) || s.isTrue(head_[1]) || s.isTrue(head_[2]); +} + +bool ClauseHead::toImplication(Solver& s) { + uint32 sz = isSentinel(head_[1]) ? 1 : 2 + (!s.isFalse(head_[2]) || s.level(head_[2].var()) > 0); + ClauseRep rep = ClauseRep::create(head_, sz, InfoType(ClauseHead::type()).setLbd(2).setTagged(tagged())); + bool implicit = s.allowImplicit(rep); + bool locked = ClauseHead::locked(s) && s.decisionLevel() > 0; + rep.prep = 1; + if ((locked || !implicit) && sz > 1) { return false; } + s.add(rep, false); + detach(s); + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// SmallClauseAlloc +///////////////////////////////////////////////////////////////////////////////////////// +SmallClauseAlloc::SmallClauseAlloc() : blocks_(0), freeList_(0) { } +SmallClauseAlloc::~SmallClauseAlloc() { + Block* r = blocks_; + while (r) { + Block* t = r; + r = r->next; + ::operator delete(t); + } +} + +void SmallClauseAlloc::allocBlock() { + Block* r = (Block*)::operator new(sizeof(Block)); + for (uint32 i = 0; i < Block::num_chunks-1; ++i) { + r->chunk[i].next = &r->chunk[i+1]; + } + r->chunk[Block::num_chunks-1].next = freeList_; + freeList_ = r->chunk; + r->next = blocks_; + blocks_ = r; +} + +} diff --git a/libclasp/src/statistics.cpp b/libclasp/src/statistics.cpp new file mode 100644 index 0000000..692595c --- /dev/null +++ b/libclasp/src/statistics.cpp @@ -0,0 +1,265 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// StatisticObject +///////////////////////////////////////////////////////////////////////////////////////// +StatisticObject::RegVec StatisticObject::types_; +StatisticObject::StatisticObject() : handle_(0) {} +StatisticObject::StatisticObject(const void* obj, uint32 type) { + handle_ = static_cast(type) << 48; + handle_ |= static_cast(reinterpret_cast(obj)); +} +const void* StatisticObject::self() const { + static const uint64 ptrMask = bit_mask(48) - 1; + return reinterpret_cast(static_cast(handle_ & ptrMask)); +} +const StatisticObject::I* StatisticObject::tid() const { + return types_.at(static_cast(handle_ >> 48)); +} +StatisticObject::Type StatisticObject::type() const { + return !empty() ? tid()->type : Potassco::Statistics_t::Empty; +} +bool StatisticObject::empty() const { + return handle_ == 0; +} +uint32 StatisticObject::size() const { + switch (type()) { + default: throw std::logic_error("invalid object"); + case Potassco::Statistics_t::Value: return 0; + case Potassco::Statistics_t::Map: return static_cast(tid())->size(self()); + case Potassco::Statistics_t::Array: return static_cast(tid())->size(self()); + } +} +const char* StatisticObject::key(uint32 i) const { + CLASP_FAIL_IF(type() != Potassco::Statistics_t::Map, "type error"); + return static_cast(tid())->key(self(), i); +} +static inline StatisticObject check(StatisticObject o) { + if (!o.empty()) { return o; } + throw std::out_of_range("StatisticObject"); +} +StatisticObject StatisticObject::at(const char* k) const { + CLASP_FAIL_IF(type() != Potassco::Statistics_t::Map, "type error"); + return check(static_cast(tid())->at(self(), k)); +} +StatisticObject StatisticObject::operator[](uint32 i) const { + CLASP_FAIL_IF(type() != Potassco::Statistics_t::Array, "type error"); + return check(static_cast(tid())->at(self(), i)); +} +double StatisticObject::value() const { + CLASP_FAIL_IF(type() != Potassco::Statistics_t::Value, "type error"); + return static_cast(tid())->value(self()); +} +std::size_t StatisticObject::hash() const { + typedef Clasp::HashSet_t::set_type::hasher Hasher; + return Hasher()(toRep()); +} +uint64 StatisticObject::toRep() const { + return handle_; +} +StatisticObject StatisticObject::fromRep(uint64 x) { + if (!x) { return StatisticObject(0, 0); } + StatisticObject r; + r.handle_ = x; + CLASP_FAIL_IF(r.tid() == 0 || (reinterpret_cast(r.self()) & 3u) != 0, "invalid key"); + return r; +} +///////////////////////////////////////////////////////////////////////////////////////// +// ClaspStatistics +///////////////////////////////////////////////////////////////////////////////////////// +struct ClaspStatistics::Impl { + typedef Clasp::HashMap_t::map_type RegMap; + Impl() : gc_(0), rem_(0) {} + Key_t add(const StatisticObject& o) { + uint64 k = o.toRep(); + map_[k] = gc_; + return k; + } + bool remove(const StatisticObject& o) { + std::size_t rem = map_.erase(o.toRep()); + return rem != 0; + } + StatisticObject get(Key_t k) const { + RegMap::const_iterator it = map_.find(k); + if (it != map_.end() && it->second == gc_) { + return StatisticObject::fromRep(k); + } + throw std::logic_error("invalid key"); + } + void update(const StatisticObject& root) { + ++gc_; + rem_ += (sizeVec(map_) - visit(root)); + if (rem_ > (map_.size() >> 1)) { + for (RegMap::iterator it = map_.begin(), end = map_.end(); it != end;) { + if (it->second == gc_) { ++it; } + else { it = map_.erase(it); } + } + rem_ = 0; + } + } + uint32 visit(const StatisticObject& obj) { + uint32 count = 0; + RegMap::iterator it = map_.find(obj.toRep()); + if (obj.empty() || it == map_.end()) { return count; } + it->second = gc_; + ++count; + switch (obj.type()) { + case Potassco::Statistics_t::Map: + for (uint32 i = 0, end = obj.size(); i != end; ++i) { count += visit(obj.at(obj.key(i))); } + break; + case Potassco::Statistics_t::Array: + for (uint32 i = 0, end = obj.size(); i != end; ++i) { count += visit(obj[i]); } + break; + default: break; + } + return count; + } + RegMap map_; + uint32 gc_; + uint32 rem_; +}; + +ClaspStatistics::ClaspStatistics() : root_(0), impl_(new Impl()) {} +ClaspStatistics::~ClaspStatistics() { + delete impl_; +} +StatisticObject ClaspStatistics::getObject(Key_t k) const { + return impl_->get(k); +} +ClaspStatistics::Key_t ClaspStatistics::root() const { + return root_; +} +Potassco::Statistics_t ClaspStatistics::type(Key_t key) const { + return getObject(key).type(); +} +size_t ClaspStatistics::size(Key_t key) const { + return getObject(key).size(); +} +ClaspStatistics::Key_t ClaspStatistics::at(Key_t arrK, size_t index) const { + return impl_->add(getObject(arrK)[toU32(index)]); +} +const char* ClaspStatistics::key(Key_t mapK, size_t i) const { + return getObject(mapK).key(toU32(i)); +} +ClaspStatistics::Key_t ClaspStatistics::get(Key_t key, const char* path) const { + return impl_->add(!std::strchr(path, '.') + ? getObject(key).at(path) + : findObject(key, path)); +} +double ClaspStatistics::value(Key_t key) const { + return getObject(key).value(); +} +ClaspStatistics::Key_t ClaspStatistics::setRoot(const StatisticObject& obj) { + return root_ = impl_->add(obj); +} +bool ClaspStatistics::removeStat(const StatisticObject& obj, bool recurse) { + bool ret = impl_->remove(obj); + if (ret && recurse) { + if (obj.type() == Potassco::Statistics_t::Map) { + for (uint32 i = 0, end = obj.size(); i != end; ++i) { + removeStat(obj.at(obj.key(i)), true); + } + } + else if (obj.type() == Potassco::Statistics_t::Array) { + for (uint32 i = 0, end = obj.size(); i != end; ++i) { + removeStat(obj[i], true); + } + } + } + return ret; +} +bool ClaspStatistics::removeStat(Key_t k, bool recurse) { + try { return removeStat(impl_->get(k), recurse); } + catch (const std::logic_error&) { return false; } +} +void ClaspStatistics::update() { + if (root_) { impl_->update(getObject(root_)); } +} +StatisticObject ClaspStatistics::findObject(Key_t root, const char* path, Key_t* res) const { + StatisticObject o = getObject(root); + StatisticObject::Type t = o.type(); + char temp[1024]; const char* top, *parent = path; + for (int pos; path && *path;) { + top = path; + if ((path = std::strchr(path, '.')) != 0) { + std::size_t len = static_cast(path++ - top); + CLASP_FAIL_IF(len >= 1024, "invalid key"); + top = (const char*)std::memcpy(temp, top, len); + temp[len] = 0; + } + if (t == Potassco::Statistics_t::Map) { o = o.at(top); } + else if (t == Potassco::Statistics_t::Array && Potassco::match(top, pos) && pos >= 0) { + o = o[uint32(pos)]; + } + else { + throw std::out_of_range(ClaspStringBuffer().appendFormat("invalid path: '%s' at key '%s'", parent, top).c_str()); + } + t = o.type(); + } + if (res) { *res = impl_->add(o); } + return o; +} + +StatisticObject StatsMap::at(const char* k) const { + if (const StatisticObject* o = find(k)) { return *o; } + throw std::out_of_range(ClaspStringBuffer().appendFormat("StatsMap::at with key '%s'", k).c_str()); +} +const StatisticObject* StatsMap::find(const char* k) const { + for (MapType::const_iterator it = keys_.begin(), end = keys_.end(); it != end; ++it) { + if (std::strcmp(it->first, k) == 0) { return &it->second; } + } + return 0; +} +bool StatsMap::add(const char* k, const StatisticObject& o) { + return !find(k) && (keys_.push_back(MapType::value_type(k, o)), true); +} +///////////////////////////////////////////////////////////////////////////////////////// +// StatsVisitor +///////////////////////////////////////////////////////////////////////////////////////// +StatsVisitor::~StatsVisitor() {} +bool StatsVisitor::visitGenerator(Operation) { + return true; +} +bool StatsVisitor::visitThreads(Operation) { + return true; +} +bool StatsVisitor::visitTester(Operation) { + return true; +} +bool StatsVisitor::visitHccs(Operation) { + return true; +} +void StatsVisitor::visitHcc(uint32, const ProblemStats& p, const SolverStats& s) { + visitProblemStats(p); + visitSolverStats(s); +} +void StatsVisitor::visitThread(uint32, const SolverStats& stats) { + visitSolverStats(stats); +} + +} + diff --git a/libclasp/src/timer.cpp b/libclasp/src/timer.cpp new file mode 100644 index 0000000..5767b24 --- /dev/null +++ b/libclasp/src/timer.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2006-2012, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN // exclude APIs such as Cryptography, DDE, RPC, Shell, and Windows Sockets. +#define NOMINMAX // do not let windows.h define macros min and max +#include // GetProcessTimes, GetCurrentProcess, FILETIME +#define TICKS_PER_SEC 10000000 + +namespace Clasp { + +double RealTime::getTime() { + union Convert { + FILETIME time; + __int64 asUint; + } now; + GetSystemTimeAsFileTime(&now.time); + return static_cast(now.asUint/static_cast(TICKS_PER_SEC)); +} + +double ProcessTime::getTime() { + FILETIME ignoreStart, ignoreExit; + union Convert { + FILETIME time; + __int64 asUint; + } user, system; + GetProcessTimes(GetCurrentProcess(), &ignoreStart, &ignoreExit, &user.time, &system.time); + return (user.asUint + system.asUint) / double(TICKS_PER_SEC); +} + +double ThreadTime::getTime() { + FILETIME ignoreStart, ignoreExit; + union Convert { + FILETIME time; + __int64 asUint; + } user, system; + GetThreadTimes(GetCurrentThread(), &ignoreStart, &ignoreExit, &user.time, &system.time); + return (user.asUint + system.asUint) / double(TICKS_PER_SEC); +} + +} +#else +#include // times() +#include // gettimeofday() +#include // sysconf() +#include // getrusage +#include +#ifdef __APPLE__ +#include +#include +#endif +namespace Clasp { + +double RealTime::getTime() { + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) + static_cast(now.tv_usec / 1000000.0); +} + +double ProcessTime::getTime() { + struct tms nowTimes; + times(&nowTimes); + return (nowTimes.tms_utime + nowTimes.tms_stime) / double(sysconf(_SC_CLK_TCK)); +} +double ThreadTime::getTime() { + double res = std::numeric_limits::quiet_NaN(); +#if defined(RUSAGE_THREAD) + int who = RUSAGE_THREAD; + struct rusage usage; + getrusage(who, &usage); + res = (static_cast(usage.ru_utime.tv_sec) + static_cast(usage.ru_utime.tv_usec / 1000000.0)) + + (static_cast(usage.ru_stime.tv_sec) + static_cast(usage.ru_stime.tv_usec / 1000000.0)); +#elif __APPLE__ + struct thread_basic_info t_info; + mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; + if (thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)&t_info, &t_info_count) == KERN_SUCCESS) { + time_value_add(&t_info.user_time, &t_info.system_time); + res = static_cast(t_info.user_time.seconds) + static_cast(t_info.user_time.microseconds / static_cast(TIME_MICROS_MAX)); + } +#endif + return res; +} + +} +#endif + diff --git a/libclasp/src/unfounded_check.cpp b/libclasp/src/unfounded_check.cpp new file mode 100644 index 0000000..22cb1fd --- /dev/null +++ b/libclasp/src/unfounded_check.cpp @@ -0,0 +1,784 @@ +// +// Copyright (c) 2010-2016, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#include +#include +#include +#include +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultUnfoundedCheck - Construction/Destruction +///////////////////////////////////////////////////////////////////////////////////////// +// Choice rules are handled like normal rules with one exception: +// Since BFA does not apply to choice rules, we manually trigger the removal of source pointers +// whenever an atom sourced by a choice rule becomes false. +// +// The major problems with card/weight-rules are: +// 1. subgoals can circularly depend on the body +// 2. subgoal false -> body false, does not hold +// +// Regarding the first point, consider: {b}. a:- 1{a,b}. +// Since b is external to 1{a,b}, the body is a valid source for a. Therefore, 1{a,b} can source a. +// After a's source pointer is set to 1{a,b}, both subgoals of 1{a,b} have a source. Nevertheless, +// we must not count a because it (circularly) depends on the body. I.e. as soon as b +// becomes false, a is unfounded, because the loop {a} no longer has external bodies. +// +// The second point means that we have to watch *all* subgoals because we +// may need to trigger source pointer removal whenever one of the subgoals becomes false. +// Consider: {a,b,c}. t :- 2 {b,t,x}. x :- t,c. x :- a. +// Now assume {t,c} is true and a becomes false. In this case, both x and t lose their +// source pointer and we get the (conflicting) unfounded set {x, t}. +// Further assume that after some backtracking we have that both {t,c} and a +// become false. Therefore x is false, too. Since we do not update source pointers on +// conflicts, x and t still have no source. Thus no removal of source pointers is triggered. +// If we would not watch x in 2 {b,t,x}, we could not add t to the todo queue and +// we would therefore miss the unfounded set {t}. +// +// The implementation for extended bodies works as follows: +// - It distinguishes between internal literals, those that are in the same SCC as B +// and external literals, those that are not. +// - Let W(l) be the weight of literal l in B and W(WS) be the sum of W(l) for each l in a set WS. +// - The goal is to maintain a set WS of literals l, s.th l in Body and hasSource(l) AND W(WS) >= bound. +// - Initially WS contains all non-false external literals of B. +// - Whenever one of the internal literals of B becomes sourced, it is added to WS +// *only if* W(WS) < bound. In that case, it is guaranteed that the literal +// currently does not circularly depend on the body. +// - As soon as W(WS) >= bound, we declare the body as valid source for its heads. +// - Whenever one of the literals l in WS loses its source, it is removed from WS. +// If l is an external literal, new valid external literals are searched and added to WS +// until the source condition holds again. +// - If the condition cannot be restored, the body is marked as invalid source. + +DefaultUnfoundedCheck::DefaultUnfoundedCheck(DependencyGraph& g, ReasonStrategy st) + : solver_(0) + , graph_(&g) + , mini_(0) + , reasons_(0) + , strategy_(st) { + mini_.release(); +} +DefaultUnfoundedCheck::~DefaultUnfoundedCheck() { + for (ExtVec::size_type i = 0; i != extended_.size(); ++i) { + ::operator delete(extended_[i]); + } + delete [] reasons_; +} +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultUnfoundedCheck - Initialization +///////////////////////////////////////////////////////////////////////////////////////// +void DefaultUnfoundedCheck::addWatch(Literal p, uint32 data, WatchType type) { + assert(data < varMax); + solver_->addWatch(p, this, static_cast((data << 2) | type)); +} + +void DefaultUnfoundedCheck::setReasonStrategy(ReasonStrategy rs) { + strategy_ = rs; + if (strategy_ == only_reason && solver_ && !reasons_) { + reasons_ = new LitVec[solver_->numVars()]; + } +} +// inits unfounded set checker with graph, i.e. +// - creates data objects for bodies and atoms +// - adds necessary watches to the solver +// - initializes source pointers +bool DefaultUnfoundedCheck::init(Solver& s) { + assert(!solver_ || solver_ == &s); + delete[] reasons_; + reasons_ = 0; + solver_ = &s; + setReasonStrategy(s.searchMode() != SolverStrategies::no_learning ? strategy_ : no_reason); + // process any leftovers from previous steps + while (findUfs(s, false) != ufs_none) { + while (!ufs_.empty()) { + if (!s.force(~graph_->getAtom(ufs_.front()).lit, 0)) { return false; } + atoms_[ufs_.pop_ret()].ufs = 0; + } + } + AtomVec::size_type startAtom = atoms_.size(); + // set up new atoms + atoms_.resize(graph_->numAtoms()); + AtomData& sentinel = atoms_[DependencyGraph::sentinel_atom]; + sentinel.resurrectSource(); + sentinel.todo = 1; + sentinel.ufs = 1; + // set up new bodies + for (uint32 i = (uint32)bodies_.size(); i != graph_->numBodies(); ++i) { + bodies_.push_back(BodyData()); + BodyPtr n(getBody(i)); + if (!n.node->extended()) { + initBody(n); + } + else { + initExtBody(n); + } + // when a body becomes false, it can no longer be used as source + addWatch(~n.node->lit, n.id, watch_source_false); + } + // check for initially unfounded atoms + propagateSource(); + for (AtomVec::size_type i = startAtom, end = atoms_.size(); i != end; ++i) { + const AtomNode& a = graph_->getAtom(NodeId(i)); + if (!atoms_[i].hasSource() && !solver_->force(~a.lit, 0)) { + return false; + } + if (a.inChoice()) { + addWatch(~a.lit, NodeId(i), watch_head_false); + } + } + if (graph_->numNonHcfs() != 0) { + mini_ = new MinimalityCheck(s.searchConfig().fwdCheck); + if (const uint32 sd = mini_->fwd.signDef) { + for (AtomVec::size_type i = startAtom, end = atoms_.size(); i != end; ++i) { + const AtomNode& a = graph_->getAtom(NodeId(i)); + if (a.inDisjunctive() && solver_->value(a.lit.var()) == value_free) { + ValueRep v = falseValue(a.lit); + if (sd == SolverStrategies::sign_pos || (sd == SolverStrategies::sign_rnd && (i & 1) != 0)) { + v ^= static_cast(3u); + } + solver_->setPref(a.lit.var(), ValueSet::def_value, v); + } + } + } + } + return true; +} + +// initializes a "normal" body, i.e. a body where lower(B) == size(B) +void DefaultUnfoundedCheck::initBody(const BodyPtr& n) { + assert(n.id < bodies_.size()); + BodyData& data = bodies_[n.id]; + // initialize lower to the number of predecessors from same scc that currently + // have no source. Once lower is 0, the body can source successors in its scc + data.lower_or_ext = n.node->num_preds(); + initSuccessors(n, data.lower_or_ext); +} + +// initializes an "extended" body, i.e. a count/sum +// creates & populates WS and adds watches to all subgoals +void DefaultUnfoundedCheck::initExtBody(const BodyPtr& n) { + assert(n.id < bodies_.size() && n.node->extended()); + BodyData& data = bodies_[n.id]; + uint32 preds = n.node->num_preds(); + ExtData* extra = new (::operator new(sizeof(ExtData) + (ExtData::flagSize(preds)*sizeof(uint32)))) ExtData(n.node->ext_bound(), preds); + + InitExtWatches addWatches = { this, &n, extra }; + graph_->visitBodyLiterals(*n.node, addWatches); + + data.lower_or_ext = (uint32)extended_.size(); + extended_.push_back(extra); + initSuccessors(n, extra->lower); +} + +// set n as source for its heads if possible and necessary +void DefaultUnfoundedCheck::initSuccessors(const BodyPtr& n, weight_t lower) { + if (!solver_->isFalse(n.node->lit)) { + for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end(); ++x) { + const AtomNode& a = graph_->getAtom(*x); + if (a.scc != n.node->scc || lower <= 0) { + setSource(*x, n); + } + } + } +} + +// watches needed to implement extended rules +void DefaultUnfoundedCheck::addExtWatch(Literal p, const BodyPtr& B, uint32 data) { + addWatch(p, static_cast(watches_.size()), watch_subgoal_false); + ExtWatch w = { B.id, data }; + watches_.push_back(w); +} +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultUnfoundedCheck - Base interface +///////////////////////////////////////////////////////////////////////////////////////// +void DefaultUnfoundedCheck::reason(Solver&, Literal p, LitVec& r) { + LitVec::const_iterator it, end; + if (!activeClause_.empty() && activeClause_[0] == p) { + it = activeClause_.begin()+1; + end = activeClause_.end(); + } + else { + assert(strategy_ == only_reason && reasons_); + it = reasons_[p.var()-1].begin(); + end = reasons_[p.var()-1].end(); + } + for (; it != end; ++it) r.push_back( ~*it ); +} + +bool DefaultUnfoundedCheck::propagateFixpoint(Solver& s, PostPropagator* ctx) { + bool checkMin = ctx == 0 && mini_.get() && mini_->partialCheck(s.decisionLevel()); + for (UfsType t; (t = findUfs(s, checkMin)) != ufs_none; ) { + if (!falsifyUfs(t)) { + resetTodo(); + return false; + } + } + return true; +} + +void DefaultUnfoundedCheck::reset() { + assert(loopAtoms_.empty() && sourceQ_.empty() && ufs_.empty() && todo_.empty()); + // remember assignments from top-level - + // the reset may come from a stop request and we might + // want to continue later + if (solver_->decisionLevel()) { + invalidQ_.clear(); + } +} +bool DefaultUnfoundedCheck::valid(Solver& s) { + if (!mini_.get() || findNonHcfUfs(s) == ufs_none) { return true; } + falsifyUfs(ufs_non_poly); + return false; +} +bool DefaultUnfoundedCheck::isModel(Solver& s) { + return DefaultUnfoundedCheck::valid(s); +} +bool DefaultUnfoundedCheck::simplify(Solver& s, bool) { + graph_->simplify(s); + if (mini_.get()) { mini_->scc = 0; } + return false; +} +void DefaultUnfoundedCheck::destroy(Solver* s, bool detach) { + if (s && detach) { + s->removePost(this); + for (uint32 i = 0; i != (uint32)bodies_.size(); ++i) { + BodyPtr n(getBody(i)); + s->removeWatch(~n.node->lit, this); + if (n.node->extended()) { + RemExtWatches remW = { static_cast(this), s }; + graph_->visitBodyLiterals(*n.node, remW); + } + } + for (AtomVec::size_type i = 0, end = atoms_.size(); i != end; ++i) { + const AtomNode& a = graph_->getAtom(NodeId(i)); + if (a.inChoice()) { s->removeWatch(~a.lit, this); } + } + } + PostPropagator::destroy(s, detach); +} +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultUnfoundedCheck - source pointer propagation +///////////////////////////////////////////////////////////////////////////////////////// +// propagates recently set source pointers within one strong component. +void DefaultUnfoundedCheck::propagateSource() { + for (LitVec::size_type i = 0; i < sourceQ_.size(); ++i) { + NodeId atom = sourceQ_[i]; + if (atoms_[atom].hasSource()) { + // propagate a newly added source-pointer + graph_->getAtom(atom).visitSuccessors(AddSource(this)); + } + else { + graph_->getAtom(atom).visitSuccessors(RemoveSource(this)); + } + } + sourceQ_.clear(); +} + +// replaces current source of atom with n +void DefaultUnfoundedCheck::updateSource(AtomData& atom, const BodyPtr& n) { + if (atom.watch() != AtomData::nill_source) { + --bodies_[atom.watch()].watches; + } + atom.setSource(n.id); + ++bodies_[n.id].watches; +} + +// an atom in extended body n has a new source, check if n is now a valid source +void DefaultUnfoundedCheck::AddSource::operator()(NodeId bodyId, uint32 idx) const { + BodyPtr n(self->getBody(bodyId)); + ExtData* ext = self->extended_[self->bodies_[bodyId].lower_or_ext]; + if (ext->lower > 0 || self->bodies_[n.id].watches == 0) { + // currently not a source - safely add pred to our watch set + ext->addToWs(idx, n.node->pred_weight(idx, false)); + } + if (!self->solver_->isFalse(n.node->lit) && ext->lower <= 0) { + // valid source - propagate to heads + self->forwardSource(n); + } +} +// an atom in extended body n has lost its source, check if n is no longer a valid source +void DefaultUnfoundedCheck::RemoveSource::operator()(NodeId bodyId, uint32 idx) const { + BodyPtr n(self->getBody(bodyId)); + ExtData* ext = self->extended_[self->bodies_[bodyId].lower_or_ext]; + ext->removeFromWs(idx, n.node->pred_weight(idx, false)); + if (ext->lower > 0 && self->bodies_[n.id].watches > 0) { + // extended bodies don't always become false if a predecessor becomes false + // eagerly enqueue all successors watching this body + self->forwardUnsource(n, true); + } +} + +// n is a valid source again, forward propagate this information to its heads +void DefaultUnfoundedCheck::forwardSource(const BodyPtr& n) { + for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end(); ++x) { + setSource(*x, n); + } +} + +// n is no longer a valid source, forward propagate this information to its heads +void DefaultUnfoundedCheck::forwardUnsource(const BodyPtr& n, bool add) { + for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end() && graph_->getAtom(*x).scc == n.node->scc; ++x) { + if (atoms_[*x].hasSource() && atoms_[*x].watch() == n.id) { + atoms_[*x].markSourceInvalid(); + sourceQ_.push_back(*x); + } + if (add && atoms_[*x].watch() == n.id) { + pushTodo(*x); + } + } +} + +// sets body as source for head if necessary. +// PRE: value(body) != value_false +// POST: source(head) != 0 +void DefaultUnfoundedCheck::setSource(NodeId head, const BodyPtr& body) { + assert(!solver_->isFalse(body.node->lit)); + // For normal rules from not false B follows not false head, but + // for choice rules this is not the case. Therefore, the + // check for isFalse(head) is needed so that we do not inadvertantly + // source a head that is currently false. + if (!atoms_[head].hasSource() && !solver_->isFalse(graph_->getAtom(head).lit)) { + updateSource(atoms_[head], body); + sourceQ_.push_back(head); + } +} + +// This function is called for each body that became invalid during propagation. +// Heads having the body as source have their source invalidated and are added +// to the todo queue. Furthermore, source pointer removal is propagated forward +void DefaultUnfoundedCheck::removeSource(NodeId bodyId) { + const BodyNode& body = graph_->getBody(bodyId); + for (const NodeId* x = body.heads_begin(); x != body.heads_end(); ++x) { + if (atoms_[*x].watch() == bodyId) { + if (atoms_[*x].hasSource()) { + atoms_[*x].markSourceInvalid(); + sourceQ_.push_back(*x); + } + pushTodo(*x); + } + } + propagateSource(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultUnfoundedCheck - Finding & propagating unfounded sets +///////////////////////////////////////////////////////////////////////////////////////// +void DefaultUnfoundedCheck::updateAssignment(Solver& s) { + assert(sourceQ_.empty() && ufs_.empty() && pickedExt_.empty()); + for (VarVec::const_iterator it = invalidQ_.begin(), end = invalidQ_.end(); it != end; ++it) { + uint32 index = (*it) >> 2; + uint32 type = (*it) & 3u; + if (type == watch_source_false) { + // a body became false - update atoms having the body as source + removeSource(index); + } + else if (type == watch_head_false) { + // an atom in the head of a choice rule became false + // normally head false -> body false and hence the head has its source autmatically removed + // for choice rules we must force source removal explicity + if (atoms_[index].hasSource() && !s.isFalse(graph_->getBody(atoms_[index].watch()).lit)) { + atoms_[index].markSourceInvalid(); + graph_->getAtom(index).visitSuccessors(RemoveSource(this, true)); + propagateSource(); + } + } + else if (type == watch_head_true) { + // TODO: approx. ufs for disjunctive lp + } + else if (type == watch_subgoal_false) { // a literal p relevant to an extended body became false + assert(index < watches_.size()); + const ExtWatch& w = watches_[index]; + const BodyNode& body = graph_->getBody(w.bodyId); + ExtData* ext = extended_[bodies_[w.bodyId].lower_or_ext]; + ext->removeFromWs(w.data>>1, body.pred_weight(w.data>>1, test_bit(w.data, 0) != 0)); + if (ext->lower > 0 && bodies_[w.bodyId].watches && !bodies_[w.bodyId].picked && !s.isFalse(body.lit)) { + // The body is not a valid source but at least one head atom + // still depends on it: mark body as invalid source + removeSource(w.bodyId); + pickedExt_.push_back(w.bodyId); + bodies_[w.bodyId].picked = 1; + } + } + } + for (VarVec::size_type i = 0, end = pickedExt_.size(); i != end; ++i) { + bodies_[pickedExt_[i]].picked = 0; + } + pickedExt_.clear(); + invalidQ_.clear(); +} + +DefaultUnfoundedCheck::UfsType DefaultUnfoundedCheck::findUfs(Solver& s, bool checkMin) { + // first: remove all sources that were recently falsified + updateAssignment(s); + // second: try to re-establish sources. + while (!todo_.empty()) { + NodeId head = todo_.pop_ret(); + atoms_[head].todo = 0; + if (!atoms_[head].hasSource() && !s.isFalse(graph_->getAtom(head).lit) && !findSource(head)) { + return ufs_poly; // found an unfounded set - contained in unfounded_ + } + assert(sourceQ_.empty()); + } + todo_.clear(); + return !checkMin ? ufs_none : findNonHcfUfs(s); +} + +// searches a new source for the atom node head. +// If a new source is found the function returns true. +// Otherwise the function returns false and unfounded_ contains head +// as well as atoms with no source that circularly depend on head. +bool DefaultUnfoundedCheck::findSource(NodeId headId) { + assert(ufs_.empty() && invalidQ_.empty()); + const NodeId* bodyIt, *bodyEnd; + uint32 newSource = 0; + pushUfs(headId); // unfounded, unless we find a new source + while (!ufs_.empty()) { + headId = ufs_.pop_ret(); // still marked and in vector! + AtomData& head = atoms_[headId]; + if (!head.hasSource()) { + const AtomNode& headNode = graph_->getAtom(headId); + for (bodyIt = headNode.bodies_begin(), bodyEnd = headNode.bodies_end(); bodyIt != bodyEnd; ++bodyIt) { + BodyPtr bodyNode(getBody(*bodyIt)); + if (!solver_->isFalse(bodyNode.node->lit)) { + if (bodyNode.node->scc != headNode.scc || isValidSource(bodyNode)) { + head.ufs = 0; // found a new source, + setSource(headId, bodyNode);// set the new source + propagateSource(); // and propagate it forward + ++newSource; + break; + } + else { addUnsourced(bodyNode); } + } + } + if (!head.hasSource()) { // still no source - check again once we are done + invalidQ_.push_back(headId); + } + } + else { // head has a source and is thus not unfounded + ++newSource; + head.ufs = 0; + } + } // while unfounded_.emtpy() == false + ufs_.rewind(); + if (newSource != 0) { + // some atoms in unfounded_ have a new source + // clear queue and check possible candidates for atoms that are still unfounded + uint32 visited = sizeVec(ufs_.vec); + ufs_.clear(); + if (visited != newSource) { + // add elements that are still unfounded + for (VarVec::iterator it = invalidQ_.begin(), end = invalidQ_.end(); it != end; ++it) { + if ( (atoms_[*it].ufs = (1u - atoms_[*it].validS)) == 1 ) { ufs_.push(*it); } + } + } + } + invalidQ_.clear(); + return ufs_.empty(); +} + +// checks whether the body can source its heads +bool DefaultUnfoundedCheck::isValidSource(const BodyPtr& n) { + if (!n.node->extended()) { + return bodies_[n.id].lower_or_ext == 0; + } + ExtData* ext = extended_[bodies_[n.id].lower_or_ext]; + if (ext->lower > 0) { + // Since n is currently not a source, + // we here know that no literal with a source can depend on this body. + // Hence, we can safely add all those literals to WS. + + // We check all internal literals here because there may be atoms + // that were sourced *after* we established the watch set. + const uint32 inc = n.node->pred_inc(); + const NodeId* x = n.node->preds(); + uint32 p = 0; + for (; *x != idMax; x += inc, ++p) { + if (atoms_[*x].hasSource() && !ext->inWs(p) && !solver_->isFalse(graph_->getAtom(*x).lit)) { + ext->addToWs(p, n.node->pred_weight(p, false)); + } + } + // We check all external literals here because we do not update + // the body on backtracking. Therefore some external literals that were false + // may now be true/free. + for (++x; *x != idMax; x += inc, ++p) { + if (!solver_->isFalse(Literal::fromRep(*x)) && !ext->inWs(p)) { + ext->addToWs(p, n.node->pred_weight(p, true)); + } + } + } + return ext->lower <= 0; +} + +// enqueues all predecessors of this body that currently lack a source +// PRE: isValidSource(n) == false +void DefaultUnfoundedCheck::addUnsourced(const BodyPtr& n) { + const uint32 inc = n.node->pred_inc(); + for (const NodeId* x = n.node->preds(); *x != idMax; x += inc) { + if (!atoms_[*x].hasSource() && !solver_->isFalse(graph_->getAtom(*x).lit)) { + pushUfs(*x); + } + } +} + +// falsifies the atoms one by one from the unfounded set stored in unfounded_ +bool DefaultUnfoundedCheck::falsifyUfs(UfsType t) { + activeClause_.clear(); + for (uint32 rDL = 0; !ufs_.empty(); ) { + Literal a = graph_->getAtom(ufs_.front()).lit; + if (!solver_->isFalse(a) && !(assertAtom(a, t) && solver_->propagateUntil(this))) { + if (t == ufs_non_poly) { + mini_->schedNext(solver_->decisionLevel(), false); + } + break; + } + assert(solver_->isFalse(a)); + atoms_[ufs_.pop_ret()].ufs = 0; + if (ufs_.qFront == 1) { rDL = solver_->decisionLevel(); } + else if (solver_->decisionLevel() != rDL){ break; /* atoms may no longer be unfounded after backtracking */ } + } + if (!loopAtoms_.empty()) { + createLoopFormula(); + } + resetUfs(); + activeClause_.clear(); + return !solver_->hasConflict(); +} + +// asserts an unfounded atom using the selected reason strategy +bool DefaultUnfoundedCheck::assertAtom(Literal a, UfsType t) { + if (solver_->isTrue(a) || strategy_ == distinct_reason || activeClause_.empty()) { + // Conflict, first atom of unfounded set, or distinct reason for each atom requested - + // compute reason for a being unfounded. + // We must flush any not yet created loop formula here - the + // atoms in loopAtoms_ depend on the current reason which is about to be replaced. + if (!loopAtoms_.empty()) { + createLoopFormula(); + } + activeClause_.assign(1, ~a); + computeReason(t); + } + activeClause_[0] = ~a; + bool noClause = solver_->isTrue(a) || strategy_ == no_reason || strategy_ == only_reason || (strategy_ == shared_reason && activeClause_.size() > 3); + if (noClause) { + if (!solver_->force(~a, this)) { return false; } + if (strategy_ == only_reason) { reasons_[a.var()-1].assign(activeClause_.begin()+1, activeClause_.end()); } + else if (strategy_ != no_reason){ loopAtoms_.push_back(~a); } + return true; + } + else { // learn nogood and assert ~a + return ClauseCreator::create(*solver_, activeClause_, ClauseCreator::clause_no_prepare, info_).ok(); + } +} +void DefaultUnfoundedCheck::createLoopFormula() { + assert(activeClause_.size() > 3 && !loopAtoms_.empty()); + Antecedent ante; + activeClause_[0] = loopAtoms_[0]; + if (loopAtoms_.size() == 1) { + ante = ClauseCreator::create(*solver_, activeClause_, ClauseCreator::clause_no_prepare, info_).local; + } + else { + ante = LoopFormula::newLoopFormula(*solver_ + , ClauseRep::prepared(&activeClause_[0], (uint32)activeClause_.size(), info_) + , &loopAtoms_[0], (uint32)loopAtoms_.size()); + solver_->addLearnt(ante.constraint(), uint32(loopAtoms_.size() + activeClause_.size()), Constraint_t::Loop); + } + do { + assert(solver_->isTrue(loopAtoms_.back()) && solver_->reason(loopAtoms_.back()) == this); + solver_->setReason(loopAtoms_.back(), ante); + loopAtoms_.pop_back(); + } while (!loopAtoms_.empty()); +} + +// computes the reason why a set of atoms is unfounded +void DefaultUnfoundedCheck::computeReason(UfsType t) { + if (strategy_ == no_reason) { return; } + uint32 ufsScc = graph_->getAtom(ufs_.front()).scc; + for (VarVec::size_type i = ufs_.qFront; i != ufs_.vec.size(); ++i) { + const AtomNode& atom = graph_->getAtom(ufs_.vec[i]); + if (!solver_->isFalse(atom.lit)) { + assert(atom.scc == ufsScc); + for (const NodeId* x = atom.bodies_begin(); x != atom.bodies_end(); ++x) { + BodyPtr body(getBody(*x)); + if (t == ufs_poly || !body.node->delta()){ addIfReason(body, ufsScc); } + else { addDeltaReason(body, ufsScc); } + } + } + } + for (VarVec::size_type i = 0; i != pickedExt_.size(); ++i) { bodies_[pickedExt_[i]].picked = 0; } + pickedExt_.clear(); + info_ = ConstraintInfo(Constraint_t::Loop); + uint32 rc = !solver_->isFalse(activeClause_[0]) && activeClause_.size() > 100 && activeClause_.size() > (solver_->decisionLevel() * 10); + uint32 dl = solver_->finalizeConflictClause(activeClause_, info_, rc); + uint32 cDL= solver_->decisionLevel(); + assert((t == ufs_non_poly || dl == cDL) && "Loop nogood must contain a literal from current DL!"); + if (dl < cDL && solver_->isUndoLevel()) { + // cancel active propagation on cDL + cancelPropagation(); + invalidQ_.clear(); + solver_->undoUntil(dl); + } +} +// check whether n is external to the current unfounded set, i.e. +// does not depend on the atoms from the unfounded set +bool DefaultUnfoundedCheck::isExternal(const BodyPtr& n, weight_t& S) const { +#define IN_UFS(id) ( (atoms_[(id)].ufs) && !solver_->isFalse(graph_->getAtom((id)).lit) ) + if (!n.node->sum()) { + for (const NodeId* x = n.node->preds(); *x != idMax && S >= 0; ++x) { + if (IN_UFS(*x)) { S -= 1; } + } + } + else { + for (const NodeId* x = n.node->preds(); *x != idMax && S >= 0; x+=2) { + if (IN_UFS(*x)) { S -= static_cast(x[1]); } + } + } + return S >= 0; +#undef IN_UFS +} + +// check if n is part of the reason for the current unfounded set +void DefaultUnfoundedCheck::addIfReason(const BodyPtr& n, uint32 uScc) { + bool inF = solver_->isFalse(n.node->lit); + weight_t S; + if (!n.node->extended() || n.node->scc != uScc) { + if (inF && !solver_->seen(n.node->lit) && (n.node->scc != uScc || isExternal(n, (S=0)))) { + addReasonLit(n.node->lit); + } + } + else if (bodies_[n.id].picked == 0) { + if (isExternal(n, S = extended_[bodies_[n.id].lower_or_ext]->slack)) { + AddReasonLit addFalseLits = { this, n.node, S }; + if (inF) { addReasonLit(n.node->lit); } + else { graph_->visitBodyLiterals(*n.node, addFalseLits); } + } + bodies_[n.id].picked = 1; + pickedExt_.push_back(n.id); + } +} + +void DefaultUnfoundedCheck::addDeltaReason(const BodyPtr& n, uint32 uScc) { + if (bodies_[n.id].picked != 0) return; + uint32 bodyAbst = solver_->isFalse(n.node->lit) ? solver_->level(n.node->lit.var()) : solver_->decisionLevel() + 1; + for (const NodeId* x = n.node->heads_begin(); x != n.node->heads_end(); ++x) { + if (*x != DependencyGraph::sentinel_atom) { // normal head + if (graph_->getAtom(*x).scc == uScc) { + addIfReason(n, uScc); + } + continue; + } + else { // disjunctive head + uint32 reasonAbst= bodyAbst; + Literal reasonLit = n.node->lit; + bool inUfs = false; + Literal aLit; + for (++x; *x; ++x) { + if (atoms_[*x].ufs == 1) { + inUfs = true; + } + else if (solver_->isTrue(aLit = graph_->getAtom(*x).lit) && solver_->level(aLit.var()) < reasonAbst) { + reasonLit = ~aLit; + reasonAbst = solver_->level(reasonLit.var()); + } + } + if (inUfs && reasonAbst && reasonAbst <= solver_->decisionLevel()) { + addReasonLit(reasonLit); + } + } + } + bodies_[n.id].picked = 1; + pickedExt_.push_back(n.id); +} + +void DefaultUnfoundedCheck::addReasonLit(Literal p) { + if (!solver_->seen(p)) { + solver_->markSeen(p); + solver_->markLevel(solver_->level(p.var())); + activeClause_.push_back(p); + if (solver_->level(p.var()) > solver_->level(activeClause_[1].var())) { + std::swap(activeClause_[1], activeClause_.back()); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// DefaultUnfoundedCheck - Minimality check for disjunctive logic programs +///////////////////////////////////////////////////////////////////////////////////////// +DefaultUnfoundedCheck::UfsType DefaultUnfoundedCheck::findNonHcfUfs(Solver& s) { + assert(invalidQ_.empty() && loopAtoms_.empty()); + typedef DependencyGraph::NonHcfIter HccIter; + HccIter hIt = graph_->nonHcfBegin() + mini_->scc; + HccIter hEnd = graph_->nonHcfEnd(); + for (uint32 checks = graph_->numNonHcfs(); checks--;) { + s.stats.addTest(s.numFreeVars() != 0); + (*hIt)->assumptionsFromAssignment(s, loopAtoms_); + if (!(*hIt)->test(s, loopAtoms_, invalidQ_) || s.hasConflict()) { + uint32 pos = 0, minDL = UINT32_MAX; + for (VarVec::const_iterator it = invalidQ_.begin(), end = invalidQ_.end(); it != end; ++it) { + if (s.isTrue(graph_->getAtom(*it).lit) && s.level(graph_->getAtom(*it).lit.var()) < minDL) { + minDL = s.level(graph_->getAtom(*it).lit.var()); + pos = (uint32)ufs_.vec.size(); + } + pushUfs(*it); + } + if (pos) { + std::swap(ufs_.vec.front(), ufs_.vec[pos]); + } + invalidQ_.clear(); + loopAtoms_.clear(); + mini_->scc = static_cast(hIt - graph_->nonHcfBegin()); + return ufs_non_poly; + } + if (++hIt == hEnd) { hIt = graph_->nonHcfBegin(); } + loopAtoms_.clear(); + } + mini_->schedNext(s.decisionLevel(), true); + return ufs_none; +} + +DefaultUnfoundedCheck::MinimalityCheck::MinimalityCheck(const FwdCheck& afwd) : fwd(afwd), high(UINT32_MAX), low(0), next(0), scc(0) { + if (fwd.highPct > 100) { fwd.highPct = 100; } + if (fwd.highStep == 0) { fwd.highStep = ~fwd.highStep; } + high = fwd.highStep; +} + +bool DefaultUnfoundedCheck::MinimalityCheck::partialCheck(uint32 level) { + if (level < low) { + next -= (low - level); + low = level; + } + return !next || next == level; +} + +void DefaultUnfoundedCheck::MinimalityCheck::schedNext(uint32 level, bool ok) { + low = 0; + next = UINT32_MAX; + if (!ok) { + high = level; + next = 0; + } + else if (fwd.highPct != 0) { + double p = fwd.highPct / 100.0; + high = std::max(high, level); + low = level; + if (low >= high) { + high += fwd.highStep; + } + next = low + (uint32)std::ceil((high - low) * p); + } +} +} diff --git a/libclasp/src/weight_constraint.cpp b/libclasp/src/weight_constraint.cpp new file mode 100644 index 0000000..cc98de8 --- /dev/null +++ b/libclasp/src/weight_constraint.cpp @@ -0,0 +1,596 @@ +// +// Copyright (c) 2006-2011, Benjamin Kaufmann +// +// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// + +#include +#include +#include +#include +#include + +namespace Clasp { +///////////////////////////////////////////////////////////////////////////////////////// +// WeightLitsRep +///////////////////////////////////////////////////////////////////////////////////////// +// Removes assigned and merges duplicate/complementary literals. +// return: achievable weight +// post : lits is sorted by decreasing weights +WeightLitsRep WeightLitsRep::create(Solver& s, WeightLitVec& lits, weight_t bound) { + // Step 1: remove assigned/superfluous literals and merge duplicate/complementary ones + LitVec::size_type j = 0, other; + const weight_t MAX_W= std::numeric_limits::max(); + for (LitVec::size_type i = 0; i != lits.size(); ++i) { + Literal x = lits[i].first.unflag(); + if (lits[i].second != 0 && s.topValue(x.var()) == value_free) { + if (lits[i].second < 0) { + lits[i].second = -lits[i].second; + lits[i].first = x = ~lits[i].first; + CLASP_ASSERT_CONTRACT_MSG(bound < 0 || (MAX_W-bound) >= lits[i].second, "bound out of range"); + bound += lits[i].second; + } + if (!s.seen(x.var())) { // first time we see x, keep and mark x + if (i != j) lits[j] = lits[i]; + s.markSeen(x); + ++j; + } + else if (!s.seen(~x)) { // multi-occurrences of x, merge + for (other = 0; other != j && lits[other].first != x; ++other) { ; } + lits[other].second += lits[i].second; + } + else { // complementary literals ~x x + for (other = 0; other != j && lits[other].first != ~x; ++other) { ; } + bound -= lits[i].second; // decrease by min(w(~x), w(x)) ; assume w(~x) > w(x) + lits[other].second -= lits[i].second; // keep ~x, + if (lits[other].second < 0) { // actually, w(x) > w(~x), + lits[other].first = x; // replace ~x with x + lits[other].second = -lits[other].second; + s.clearSeen(x.var()); + s.markSeen(x); + bound += lits[other].second; // and correct the bound + } + else if (lits[other].second == 0) { // w(~x) == w(x) - drop both lits + s.clearSeen(x.var()); + std::memmove(&lits[0]+other, &lits[0]+other+1, (j-other-1)*sizeof(lits[other])); + --j; + } + } + } + else if (s.isTrue(x)) { bound -= lits[i].second; } + } + lits.erase(lits.begin()+j, lits.end()); + // Step 2: compute min,max, achievable weight and clear flags set in step 1 + weight_t sumW = 0; + weight_t minW = MAX_W, maxW = 1; + weight_t B = std::max(bound, 1); + for (LitVec::size_type i = 0; i != lits.size(); ++i) { + assert(lits[i].second > 0); + s.clearSeen(lits[i].first.var()); + if (lits[i].second > maxW) { maxW = lits[i].second = std::min(lits[i].second, B); } + if (lits[i].second < minW) { minW = lits[i].second; } + CLASP_ASSERT_CONTRACT_MSG((MAX_W - sumW) >= lits[i].second, "Sum of weights out of range"); + sumW += lits[i].second; + } + // Step 3: sort by decreasing weight + if (maxW != minW) { + std::stable_sort(lits.begin(), lits.end(), compose22( + std::greater(), + select2nd(), + select2nd())); + } + else if (minW != 1) { + // disguised cardinality constraint + bound = (bound+(minW-1))/minW; + sumW = (sumW+(minW-1))/minW; + for (LitVec::size_type i = 0; i != lits.size(); ++i) { lits[i].second = 1; } + } + WeightLitsRep result = { !lits.empty() ? &lits[0] : 0, (uint32)lits.size(), bound, sumW }; + return result; +} + +// Propagates top-level assignment. +bool WeightLitsRep::propagate(Solver& s, Literal W) { + if (sat()) { return s.force(W); } // trivially SAT + else if (unsat()){ return s.force(~W);} // trivially UNSAT + else if (s.topValue(W.var()) == value_free) { + return true; + } + // backward propagate + bool bpTrue = s.isTrue(W); + weight_t B = bpTrue ? (reach-bound)+1 : bound; + while (lits->second >= B) { + reach -= lits->second; + if (!s.force(bpTrue ? lits->first : ~lits->first, 0)) { return false; } + if ((bpTrue && (bound -= lits->second) <= 0) || --size == 0) { return true; } + ++lits; + } + if (lits->second > 1 && lits->second == lits[size-1].second) { + B = lits->second; + bound = (bound + (B-1)) / B; + reach = (reach + (B-1)) / B; + for (uint32 i = 0; i != size && lits[i].second != 1; ++i) { lits[i].second = 1; } + } + return true; +} +///////////////////////////////////////////////////////////////////////////////////////// +// WeightConstraint::WL +///////////////////////////////////////////////////////////////////////////////////////// +typedef Clasp::Atomic_t::type RCType; +WeightConstraint::WL::WL(uint32 s, bool shared, bool hasW) : sz(s), rc(shared), w(hasW) { } +uint8* WeightConstraint::WL::address() { return reinterpret_cast(this) - (sizeof(uint32) * rc); } +WeightConstraint::WL* WeightConstraint::WL::clone(){ + if (shareable()) { + ++*reinterpret_cast(address()); + return this; + } + else { + uint32 litSize = (size() << uint32(weights()))*sizeof(Literal); + WL* x = new (::operator new(sizeof(WL) + litSize)) WL(size(), false, weights()); + std::memcpy(x->lits, this->lits, litSize); + return x; + } +} +void WeightConstraint::WL::release() { + unsigned char* x = address(); + if (!shareable() || --*reinterpret_cast(x) == 0) { + ::operator delete(x); + } +} +uint32 WeightConstraint::WL::refCount() const { + assert(shareable()); + return *reinterpret_cast(const_cast(this)->address()); +} +///////////////////////////////////////////////////////////////////////////////////////// +// WeightConstraint +///////////////////////////////////////////////////////////////////////////////////////// +WeightConstraint::CPair WeightConstraint::create(Solver& s, Literal W, WeightLitVec& lits, weight_t bound, uint32 flags) { + bool const eq = (flags & create_eq_bound) != 0; + WeightLitsRep rep = WeightLitsRep::create(s, lits, bound + static_cast(eq)); + CPair res; + if (eq) { + res.con[1] = WeightConstraint::doCreate(s, ~W, rep, flags); + rep.bound -= 1; + if (!res.ok()) { return res; } + // redo coefficient reduction + for (unsigned i = 0; i != rep.size && rep.lits[i].second > rep.bound; ++i) { + rep.reach -= rep.lits[i].second; + rep.reach += (rep.lits[i].second = rep.bound); + } + } + res.con[0] = WeightConstraint::doCreate(s, W, rep, flags); + return res; +} +WeightConstraint::CPair WeightConstraint::create(Solver& s, Literal W, WeightLitsRep& rep, uint32 flags) { + CPair res; + res.con[0] = doCreate(s, W, rep, flags); + return res; +} + +WeightConstraint* WeightConstraint::doCreate(Solver& s, Literal W, WeightLitsRep& rep, uint32 flags) { + WeightConstraint* conflict = (WeightConstraint*)0x1; + bool addSat = (flags&create_sat) != 0 && rep.size; + if (!rep.propagate(s, W)) { return conflict; } + if (rep.unsat() || (rep.sat() && !addSat)){ return 0; } + if ((rep.bound == 1 || rep.bound == rep.reach) && (flags & create_explicit) == 0) { + LitVec clause; clause.reserve(1 + rep.size); + Literal bin[2]; + bool disj = rep.bound == 1; // con == disjunction or con == conjunction + bool sat = false; + clause.push_back(W ^ disj); + for (LitVec::size_type i = 0; i != rep.size; ++i) { + bin[0] = ~clause[0]; + bin[1] = rep.lits[i].first ^ disj; + if (bin[0] != ~bin[1]) { + if (bin[0] != bin[1]) { clause.push_back(~bin[1]); } + if (!s.add(ClauseRep::create(bin, 2))){ return conflict; } + } + else { sat = true; } + } + return (sat || ClauseCreator::create(s, clause, 0)) ? 0 : conflict; + } + assert(rep.open() || (rep.sat() && addSat)); + uint32 act = 3u; + if (flags & (create_only_btb|create_only_bfb)) { + act = ((flags & (create_only_btb|create_only_bfb)) / create_only_btb) - 1u; + act += (act == 2u); + } + if (!s.sharedContext()->physicalShareProblem()) { flags |= create_no_share; } + if (s.sharedContext()->frozen()) { flags |= (create_no_freeze|create_no_share); } + bool hasW = rep.hasWeights(); + uint32 size = 1 + rep.size; + uint32 nb = sizeof(WeightConstraint) + (size+uint32(hasW))*sizeof(UndoInfo); + uint32 wls = sizeof(WL) + (size << uint32(hasW))*sizeof(Literal); + void* m = 0; + WL* sL = 0; + if ((flags & create_no_share) != 0) { + nb = ((nb + 3) / 4)*4; + m = ::operator new (nb + wls); + sL = new (reinterpret_cast(m)+nb) WL(size, false, hasW); + } + else { + static_assert(sizeof(RCType) == sizeof(uint32), "Invalid size!"); + m = ::operator new(nb); + uint8* t = (uint8*)::operator new(wls + sizeof(uint32)); + *(new (t) RCType) = 1; + sL = new (t+sizeof(uint32)) WL(size, true, hasW); + } + assert(m && (reinterpret_cast(m) & 7u) == 0); + SharedContext* ctx = (flags & create_no_freeze) == 0 ? const_cast(s.sharedContext()) : 0; + WeightConstraint* c = new (m) WeightConstraint(s, ctx, W, rep, sL, act); + if (!c->integrateRoot(s)) { + c->destroy(&s, true); + return conflict; + } + if ((flags & create_no_add) == 0) { s.add(c); } + return c; +} +WeightConstraint::WeightConstraint(Solver& s, SharedContext* ctx, Literal W, const WeightLitsRep& rep, WL* out, uint32 act) { + typedef unsigned char Byte_t; + const bool hasW = rep.hasWeights(); + lits_ = out; + active_ = act; + ownsLit_ = !out->shareable(); + Literal* p = lits_->lits; + Literal* h = new (reinterpret_cast(undo_)) Literal(W); + weight_t w = 1; + bound_[FFB_BTB] = (rep.reach-rep.bound)+1; // ffb-btb + bound_[FTB_BFB] = rep.bound; // ftb-bfb + *p++ = ~W; // store constraint literal + if (hasW) *p++ = Literal::fromRep(w); // and weight if necessary + if (ctx) ctx->setFrozen(W.var(), true); // exempt from variable elimination + if (s.topValue(W.var()) != value_free) { // only one direction is relevant + active_ = FFB_BTB+s.isFalse(W); + } + watched_ = 3u - (active_ != 3u || ctx == 0); + WeightLiteral*x = rep.lits; + for (uint32 sz = rep.size, j = 1; sz--; ++j, ++x) { + h = new (h + 1) Literal(x->first); + *p++ = x->first; // store constraint literal + w = x->second; // followed by weight + if (hasW) *p++= Literal::fromRep(w); // if necessary + addWatch(s, j, FTB_BFB); // watches lits[idx] + addWatch(s, j, FFB_BTB); // watches ~lits[idx] + if (ctx) ctx->setFrozen(h->var(), true); // exempt from variable elimination + } + // init heuristic + h -= rep.size; + uint32 off = active_ != NOT_ACTIVE; + assert((void*)h == (void*)undo_); + s.heuristic()->newConstraint(s, h+off, rep.size+(1-off), Constraint_t::Static); + // init undo stack + up_ = undoStart(); // undo stack is initially empty + undo_[0].data = 0; + undo_[up_].data = 0; + setBpIndex(1); // where to start back propagation + if (s.topValue(W.var()) == value_free){ + addWatch(s, 0, FTB_BFB); // watch con in both phases + addWatch(s, 0, FFB_BTB); // in order to allow for backpropagation + } + else { + uint32 d = active_; // propagate con + WeightConstraint::propagate(s, ~lit(0, (ActiveConstraint)active_), d); + } +} + +WeightConstraint::WeightConstraint(Solver& s, const WeightConstraint& other) { + typedef unsigned char Byte_t; + lits_ = other.lits_->clone(); + ownsLit_ = 0; + Literal* heu = new (reinterpret_cast(undo_))Literal(~lits_->lit(0)); + bound_[0] = other.bound_[0]; + bound_[1] = other.bound_[1]; + active_ = other.active_; + watched_ = other.watched_; + if (active_ == NOT_ACTIVE && s.value(heu->var()) == value_free) { + addWatch(s, 0, FTB_BFB); // watch con in both phases + addWatch(s, 0, FFB_BTB); // in order to allow for backpropagation + } + for (uint32 i = 1, end = size(); i < end; ++i) { + heu = new (heu + 1) Literal(lits_->lit(i)); + if (s.value(heu->var()) == value_free) { + addWatch(s, i, FTB_BFB); // watches lits[i] + addWatch(s, i, FFB_BTB); // watches ~lits[i] + } + } + // Initialize heuristic with literals (no weights) in constraint. + uint32 off = active_ != NOT_ACTIVE; + heu -= (size() - 1); + assert((void*)heu == (void*)undo_); + s.heuristic()->newConstraint(s, heu+off, size()-off, Constraint_t::Static); + // Init undo stack + std::memcpy(undo_, other.undo_, sizeof(UndoInfo)*(size()+isWeight())); + up_ = other.up_; +} + +WeightConstraint::~WeightConstraint() {} +Constraint* WeightConstraint::cloneAttach(Solver& other) { + void* m = ::operator new(sizeof(WeightConstraint) + (size()+isWeight())*sizeof(UndoInfo)); + return new (m) WeightConstraint(other, *this); +} + +bool WeightConstraint::integrateRoot(Solver& s) { + if (!s.decisionLevel() || highestUndoLevel(s) >= s.rootLevel() || s.hasConflict()) { return !s.hasConflict(); } + // check if constraint has assigned literals + uint32 low = s.decisionLevel(), vDL; + uint32 np = 0; + for (uint32 i = 0, end = size(); i != end; ++i) { + Var v = lits_->var(i); + if (s.value(v) != value_free && (vDL = s.level(v)) != 0) { + ++np; + s.markSeen(v); + low = std::min(low, vDL); + } + } + // propagate assigned literals in assignment order + const LitVec& trail = s.trail(); + const uint32 end = sizeVec(trail) - s.queueSize(); + GenericWatch* w = 0; + for (uint32 i = s.levelStart(low); i != end && np; ++i) { + Literal p = trail[i]; + if (s.seen(p) && np--) { + s.clearSeen(p.var()); + if (!s.hasConflict() && (w = s.getWatch(trail[i], this)) != 0) { + w->propagate(s, p); + } + } + } + for (uint32 i = end; i != trail.size() && np; ++i) { + if (s.seen(trail[i].var())) { --np; s.clearSeen(trail[i].var()); } + } + return !s.hasConflict(); +} +void WeightConstraint::addWatch(Solver& s, uint32 idx, ActiveConstraint c) { + // Add watch only if c is relevant. + if (uint32(c^1) != active_) { + // Use LSB to store the constraint that watches the literal. + s.addWatch(~lit(idx, c), this, (idx<<1)+c); + } +} + +void WeightConstraint::destroy(Solver* s, bool detach) { + if (s && detach) { + for (uint32 i = 0, end = size(); i != end; ++i) { + s->removeWatch( lits_->lit(i), this ); + s->removeWatch(~lits_->lit(i), this ); + } + for (uint32 last = 0, dl; (dl = highestUndoLevel(*s)) != 0; --up_) { + if (dl != last) { s->removeUndoWatch(last = dl, this); } + } + } + if (ownsLit_ == 0) { lits_->release(); } + void* mem = static_cast(this); + this->~WeightConstraint(); + ::operator delete(mem); +} + +void WeightConstraint::setBpIndex(uint32 n){ + if (isWeight()) undo_[0].data = (n<<1)+(undo_[0].data&1); +} + +// Returns the numerical highest decision level watched by this constraint. +uint32 WeightConstraint::highestUndoLevel(Solver& s) const { + return up_ != undoStart() + ? s.level(lits_->var(undoTop().idx())) + : 0; +} + +// Updates the bound of sub-constraint c and adds the literal at index idx to the +// undo stack. If the current decision level is not watched, an undo watch is added +// so that the bound can be adjusted once the solver backtracks. +void WeightConstraint::updateConstraint(Solver& s, uint32 idx, ActiveConstraint c) { + bound_[c] -= weight(idx); + if (highestUndoLevel(s) != s.decisionLevel()) { + s.addUndoWatch(s.decisionLevel(), this); + } + undo_[up_].data = (idx<<2) + (c<<1) + (undo_[up_].data & 1); + ++up_; + assert(!litSeen(idx)); + toggleLitSeen(idx); +} + +// Since clasp uses an eager assignment strategy where literals are assigned as soon +// as they are added to the propagation queue, we distinguish processed from unprocessed literals. +// Processed literals are those for which propagate was already called and the corresponding bound +// was updated; they are flagged in updateConstraint(). +// Unprocessed literals are either free or were not yet propagated. During propagation +// we treat all unprocessed literals as free. This way, conflicts are detected early. +// Consider: x :- 3 [a=3, b=2, c=1,d=1] and PropQ: b, ~Body, c. +// Initially b, ~Body, c are unprocessed and the bound is 3. +// Step 1: propagate(b) : b is marked as processed and bound is reduced to 1. +// Now, although we already know that the body is false, we do not backpropagate yet +// because the body is unprocessed. Deferring backpropagation until the body is processed +// makes reason computation easier. +// Step 2: propagate(~Body): ~body is marked as processed and bound is reduced to 0. +// Since the body is now part of our reason set, we can start backpropagation. +// First we assign the unprocessed and free literal ~a. Literal ~b is skipped, because +// its complementary literal was already successfully processed. Finally, we force +// the unprocessed but false literal ~c to true. This will generate a conflict and +// propagation is stopped. Without the distinction between processed and unprocessed +// lits we would have to skip ~c. We would then have to manually trigger the conflict +// {b, ~Body, c} in step 3, when propagate(c) sets the bound to -1. +Constraint::PropResult WeightConstraint::propagate(Solver& s, Literal, uint32& d) { + // determine the affected constraint and its body literal + ActiveConstraint c = (ActiveConstraint)(d&1); + const uint32 idx = d >> 1; + Literal body = lit(0, c); + if ( uint32(c^1) == active_ || s.isTrue(body) ) { + // the other constraint is active or this constraint is already satisfied; + // nothing to do + return PropResult(true, true); + } + if (idx == 0 && s.decisionLevel() == s.rootLevel() && watched_ == 3u) { + watched_ = c; + for (uint32 i = 1, end = size(); i != end; ++i) { + s.removeWatch(lit(i, c), this); + } + } + // the constraint is not yet satisfied; update it and + // check if we can now propagate any literals. + updateConstraint(s, idx, c); + if (bound_[c] <= 0 || (isWeight() && litSeen(0))) { + uint32 reasonData = !isWeight() ? UINT32_MAX : up_; + if (!litSeen(0)) { + // forward propagate constraint to true + active_ = c; + return PropResult(s.force(body, this, reasonData), true); + } + else { + // backward propagate false constraint + uint32 n = getBpIndex(); + for (const uint32 end = size(); n != end && (bound_[c] - weight(n)) < 0; ++n) { + if (!litSeen(n)) { + active_ = c; + Literal x = lit(n, c); + if (!s.force(x, this, reasonData)) { + return PropResult(false, true); + } + } + } + assert(n == 1 || n == size() || isWeight()); + setBpIndex(n); + } + } + return PropResult(true, true); +} + +// Builds the reason for p from the undo stack of this constraint. +// The reason will only contain literals that were processed by the +// active sub-constraint. +void WeightConstraint::reason(Solver& s, Literal p, LitVec& r) { + assert(active_ != NOT_ACTIVE); + Literal x; + uint32 stop = !isWeight() ? up_ : s.reasonData(p); + assert(stop <= up_); + for (uint32 i = undoStart(); i != stop; ++i) { + UndoInfo u = undo_[i]; + // Consider only lits that are relevant to the active constraint + if (u.constraint() == (ActiveConstraint)active_) { + x = lit(u.idx(), u.constraint()); + r.push_back( ~x ); + } + } +} + +bool WeightConstraint::minimize(Solver& s, Literal p, CCMinRecursive* rec) { + assert(active_ != NOT_ACTIVE); + Literal x; + uint32 stop = !isWeight() ? up_ : s.reasonData(p); + assert(stop <= up_); + for (uint32 i = undoStart(); i != stop; ++i) { + UndoInfo u = undo_[i]; + // Consider only lits that are relevant to the active constraint + if (u.constraint() == (ActiveConstraint)active_) { + x = lit(u.idx(), u.constraint()); + if (!s.ccMinimize(~x, rec)) { + return false; + } + } + } + return true; +} + +// undoes processed assignments +void WeightConstraint::undoLevel(Solver& s) { + setBpIndex(1); + for (UndoInfo u; up_ != undoStart() && s.value(lits_->var((u=undoTop()).idx())) == value_free;) { + assert(litSeen(u.idx())); + toggleLitSeen(u.idx()); + bound_[u.constraint()] += weight(u.idx()); + --up_; + } + if (!litSeen(0)) { + active_ = NOT_ACTIVE; + if (watched_ < 2u) { + ActiveConstraint other = static_cast(watched_^1); + for (uint32 i = 1, end = size(); i != end; ++i) { + addWatch(s, i, other); + } + watched_ = 3u; + } + } +} + +bool WeightConstraint::simplify(Solver& s, bool) { + if (bound_[0] <= 0 || bound_[1] <= 0) { + for (uint32 i = 0, end = size(); i != end; ++i) { + s.removeWatch( lits_->lit(i), this ); + s.removeWatch(~lits_->lit(i), this ); + } + return true; + } + else if (s.value(lits_->var(0)) != value_free && (active_ == NOT_ACTIVE || isWeight())) { + if (active_ == NOT_ACTIVE) { + Literal W = ~lits_->lit(0); + active_ = FFB_BTB+s.isFalse(W); + } + for (uint32 i = 0, end = size(); i != end; ++i) { + s.removeWatch(lit(i, (ActiveConstraint)active_), this); + } + } + if (lits_->unique() && size() > 4 && (up_ - undoStart()) > size()/2) { + Literal* lits = lits_->lits; + const uint32 inc = 1 + lits_->weights(); + uint32 end = lits_->size()*inc; + uint32 i, j, idx = 1; + // find first assigned literal - must be there otherwise undo stack would be empty + for (i = inc; s.value(lits[i].var()) == value_free; i += inc) { + assert(!litSeen(idx)); + ++idx; + } + // move unassigned literals down + // update watches because indices have changed + for (j = i, i += inc; i != end; i += inc) { + if (s.value(lits[i].var()) == value_free) { + lits[j] = lits[i]; + if (lits_->weights()) { lits[j+1] = lits[i+1]; } + undo_[idx].data = 0; + assert(!litSeen(idx)); + if (Clasp::GenericWatch* w = s.getWatch(lits[i], this)) { + w->data = (idx<<1) + 1; + } + if (Clasp::GenericWatch* w = s.getWatch(~lits[i], this)) { + w->data = (idx<<1) + 0; + } + j += inc; + ++idx; + } + else { + s.removeWatch(lits[i], this); + s.removeWatch(~lits[i], this); + } + } + // clear undo stack & update to new size + up_ = undoStart(); + setBpIndex(1); + lits_->sz = idx; + } + return false; +} + +uint32 WeightConstraint::estimateComplexity(const Solver& s) const { + weight_t B = std::min(bound_[0], bound_[1]); + uint32 r = 2; + for (uint32 i = 1; i != size() && B > 0; ++i) { + if (s.value(lits_->var(i)) == value_free) { + ++r; + B -= weight(i); + } + } + return r; +} +} diff --git a/libclingo/clingo/clingocontrol.hh b/libclingo/clingo/clingocontrol.hh new file mode 100644 index 0000000..be318fb --- /dev/null +++ b/libclingo/clingo/clingocontrol.hh @@ -0,0 +1,417 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Benjamin Kaufmann +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_CLINGOCONTROL_HH +#define _GRINGO_CLINGOCONTROL_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// {{{1 declaration of ClaspAPIBackend + +class ClingoControl; +class ClaspAPIBackend : public Gringo::Backend { +public: + ClaspAPIBackend(ClingoControl& ctl) : ctl_(ctl) { } + ClaspAPIBackend(const ClaspAPIBackend&) = delete; + ClaspAPIBackend& operator=(const ClaspAPIBackend&) = delete; + void initProgram(bool incremental) override; + void beginStep() override; + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body) override; + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body) override; + void minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits) override; + void project(const Potassco::AtomSpan& atoms) override; + void output(const Potassco::StringSpan& str, const Potassco::LitSpan& condition) override; + void external(Potassco::Atom_t a, Potassco::Value_t v) override; + void assume(const Potassco::LitSpan& lits) override; + void heuristic(Potassco::Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, const Potassco::LitSpan& condition) override; + void acycEdge(int s, int t, const Potassco::LitSpan& condition) override; + void theoryTerm(Potassco::Id_t termId, int number) override; + void theoryTerm(Potassco::Id_t termId, const Potassco::StringSpan& name) override; + void theoryTerm(Potassco::Id_t termId, int cId, const Potassco::IdSpan& args) override; + void theoryElement(Potassco::Id_t elementId, const Potassco::IdSpan& terms, const Potassco::LitSpan& cond) override; + void theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements) override; + void theoryAtom(Potassco::Id_t atomOrZero, Potassco::Id_t termId, const Potassco::IdSpan& elements, Potassco::Id_t op, Potassco::Id_t rhs) override; + void endStep() override; + ~ClaspAPIBackend() noexcept override; +private: + Clasp::Asp::LogicProgram *prg(); + ClingoControl& ctl_; +}; + +// {{{1 declaration of ClingoOptions + +struct ClingoOptions { + using Foobar = std::vector; + ProgramOptions::StringSeq defines; + Gringo::Output::OutputOptions outputOptions; + Gringo::Output::OutputFormat outputFormat = Gringo::Output::OutputFormat::INTERMEDIATE; + bool verbose = false; + bool wNoOperationUndefined = false; + bool wNoAtomUndef = false; + bool wNoFileIncluded = false; + bool wNoVariableUnbounded = false; + bool wNoGlobalVariable = false; + bool wNoOther = false; + bool rewriteMinimize = false; + bool keepFacts = false; + Foobar foobar; +}; + +inline void enableAll(ClingoOptions& out, bool enable) { + out.wNoAtomUndef = !enable; + out.wNoFileIncluded = !enable; + out.wNoOperationUndefined = !enable; + out.wNoVariableUnbounded = !enable; + out.wNoGlobalVariable = !enable; + out.wNoOther = !enable; +} + +inline bool parseWarning(const std::string& str, ClingoOptions& out) { + if (str == "none") { enableAll(out, false); return true; } + if (str == "all") { enableAll(out, true); return true; } + if (str == "no-atom-undefined") { out.wNoAtomUndef = true; return true; } + if (str == "atom-undefined") { out.wNoAtomUndef = false; return true; } + if (str == "no-file-included") { out.wNoFileIncluded = true; return true; } + if (str == "file-included") { out.wNoFileIncluded = false; return true; } + if (str == "no-operation-undefined") { out.wNoOperationUndefined = true; return true; } + if (str == "operation-undefined") { out.wNoOperationUndefined = false; return true; } + if (str == "no-variable-unbounded") { out.wNoVariableUnbounded = true; return true; } + if (str == "variable-unbounded") { out.wNoVariableUnbounded = false; return true; } + if (str == "no-global-variable") { out.wNoGlobalVariable = true; return true; } + if (str == "global-variable") { out.wNoGlobalVariable = false; return true; } + if (str == "no-other") { out.wNoOther = true; return true; } + if (str == "other") { out.wNoOther = false; return true; } + return false; +} + +inline std::vector split(std::string const &source, char const *delimiter = " ", bool keepEmpty = false) { + std::vector results; + size_t prev = 0; + size_t next = 0; + while ((next = source.find_first_of(delimiter, prev)) != std::string::npos) { + if (keepEmpty || (next - prev != 0)) { results.push_back(source.substr(prev, next - prev)); } + prev = next + 1; + } + if (prev < source.size()) { results.push_back(source.substr(prev)); } + return results; +} + +static inline bool parseFoobar(const std::string& str, ClingoOptions::Foobar& foobar) { + for (auto &x : split(str, ",")) { + auto y = split(x, "/"); + if (y.size() != 2) { return false; } + unsigned a; + if (!bk_lib::string_cast(y[1], a)) { return false; } + bool sign = !y[0].empty() && y[0][0] == '-'; + if (sign) { y[0] = y[0].substr(1); } + foobar.emplace_back(y[0].c_str(), a, sign); + } + return true; +} + +// {{{1 declaration of ClingoSolveFuture + +Gringo::SolveResult convert(Clasp::ClaspFacade::Result res); +#if WITH_THREADS +struct ClingoSolveFuture : Gringo::SolveFuture { + ClingoSolveFuture(Clasp::ClaspFacade::AsyncResult const &res); + // async + Gringo::SolveResult get() override; + void wait() override; + bool wait(double timeout) override; + void cancel() override; + + void reset(Clasp::ClaspFacade::AsyncResult res); + + Clasp::ClaspFacade::AsyncResult future; + Gringo::SolveResult ret = {Gringo::SolveResult::Unknown, false, false}; + bool done = false; +}; +#endif + +// {{{1 declaration of ClingoControl +class ClingoPropagateInit : public Gringo::PropagateInit { +public: + using Lit_t = Potassco::Lit_t; + ClingoPropagateInit(Gringo::Control &c, Clasp::ClingoPropagatorInit &p) : c_(c), p_(p) { } + Gringo::TheoryData const &theory() const override { return c_.theory(); } + Gringo::SymbolicAtoms &getDomain() override { return c_.getDomain(); } + Lit_t mapLit(Lit_t lit) override; + int threads() override; + void addWatch(Lit_t lit) override { p_.addWatch(Clasp::decodeLit(lit)); } +private: + Gringo::Control &c_; + Clasp::ClingoPropagatorInit &p_; +}; + +class ClingoPropagatorLock : public Clasp::ClingoPropagatorLock { +public: + ClingoPropagatorLock() : seq_(0) {} + void lock() override { if (mut_) mut_->lock(); } + void unlock() override { if (mut_) mut_->unlock(); } + ClingoPropagatorLock* add(bool seq) { + if (seq) { ++seq_; return this; } + return 0; + } + void init(unsigned nThreads) { + if (nThreads < 2 || !seq_) { mut_ = nullptr; } + else if (!mut_.get()) { mut_ = Gringo::gringo_make_unique(); } + } +private: + using OptLock = std::unique_ptr; + OptLock mut_; + unsigned seq_; +}; + +class ClingoSolveIter; +class ClingoControl : public clingo_control, private Gringo::ConfigProxy, private Gringo::SymbolicAtoms { +public: + using StringVec = std::vector; + using ExternalVec = std::vector>; + using StringSeq = ProgramOptions::StringSeq; + using PostGroundFunc = std::function; + using PreSolveFunc = std::function; + enum class ConfigUpdate { KEEP, REPLACE }; + + ClingoControl(Gringo::Scripts &scripts, bool clingoMode, Clasp::ClaspFacade *clasp, Clasp::Cli::ClaspCliConfig &claspConfig, PostGroundFunc pgf, PreSolveFunc psf, Gringo::Logger::Printer printer, unsigned messageLimit); + ~ClingoControl() noexcept override; + void prepare(Gringo::Control::ModelHandler mh, Gringo::Control::FinishHandler fh); + void commitExternals(); + void parse(); + void parse(const StringSeq& files, const ClingoOptions& opts, Clasp::Asp::LogicProgram* out, bool addStdIn = true); + void main(); + bool onModel(Clasp::Model const &m); + void onFinish(Clasp::ClaspFacade::Result ret); + bool update(); + + Clasp::LitVec toClaspAssumptions(Gringo::Control::Assumptions &&ass) const; + + virtual void postGround(Clasp::ProgramBuilder& prg) { if (pgf_) { pgf_(prg); } } + virtual void prePrepare(Clasp::ClaspFacade& ) { } + virtual void preSolve(Clasp::ClaspFacade& clasp) { if (psf_) { psf_(clasp);} } + virtual void postSolve(Clasp::ClaspFacade& ) { } + virtual void addToModel(Clasp::Model const&, bool /*complement*/, Gringo::SymVec& ) { } + + // {{{2 SymbolicAtoms interface + + Gringo::SymbolicAtomIter begin(Gringo::Sig sig) const override; + Gringo::SymbolicAtomIter begin() const override; + Gringo::SymbolicAtomIter end() const override; + bool eq(Gringo::SymbolicAtomIter it, Gringo::SymbolicAtomIter jt) const override; + Gringo::SymbolicAtomIter lookup(Gringo::Symbol atom) const override; + size_t length() const override; + std::vector signatures() const override; + Gringo::Symbol atom(Gringo::SymbolicAtomIter it) const override; + Potassco::Lit_t literal(Gringo::SymbolicAtomIter it) const override; + bool fact(Gringo::SymbolicAtomIter it) const override; + bool external(Gringo::SymbolicAtomIter it) const override; + Gringo::SymbolicAtomIter next(Gringo::SymbolicAtomIter it) override; + bool valid(Gringo::SymbolicAtomIter it) const override; + + // {{{2 ConfigProxy interface + + bool hasSubKey(unsigned key, char const *name, unsigned* subKey = nullptr) override; + unsigned getSubKey(unsigned key, char const *name) override; + unsigned getArrKey(unsigned key, unsigned idx) override; + void getKeyInfo(unsigned key, int* nSubkeys = 0, int* arrLen = 0, const char** help = 0, int* nValues = 0) const override; + const char* getSubKeyName(unsigned key, unsigned idx) const override; + bool getKeyValue(unsigned key, std::string &value) override; + void setKeyValue(unsigned key, const char *val) override; + unsigned getRootKey() override; + + // {{{2 Control interface + + Gringo::SymbolicAtoms &getDomain() override; + void ground(Gringo::Control::GroundVec const &vec, Gringo::Context *ctx) override; + void add(std::string const &name, Gringo::FWStringVec const ¶ms, std::string const &part) override; + void load(std::string const &filename) override; + Gringo::SolveResult solve(ModelHandler h, Assumptions &&ass) override; + bool blocked() override; + std::string str(); + void assignExternal(Gringo::Symbol ext, Potassco::Value_t) override; + Gringo::Symbol getConst(std::string const &name) override; + Potassco::AbstractStatistics *statistics() override; + Gringo::ConfigProxy &getConf() override; + void useEnumAssumption(bool enable) override; + bool useEnumAssumption() override; + void cleanupDomains() override; + Gringo::SolveIter *solveIter(Assumptions &&ass) override; + Gringo::SolveFuture *solveAsync(ModelHandler mh, FinishHandler fh, Assumptions &&ass) override; + Gringo::TheoryData const &theory() const override { return out_->data.theoryInterface(); } + void registerPropagator(Gringo::UProp p, bool sequential) override; + void interrupt() override; + void *claspFacade() override; + Gringo::Backend *backend() override; + Potassco::Atom_t addProgramAtom() override; + Gringo::Logger &logger() override { return logger_; } + void beginAdd() override { parse(); } + void add(clingo_ast_statement_t const &stm) override { Gringo::Input::parseStatement(*pb_, logger_, stm); } + void endAdd() override { defs_.init(logger_); parsed = true; } + void registerObserver(Gringo::UBackend obs) override { out_->registerObserver(std::move(obs)); } + + // }}}2 + + std::unique_ptr out_; + Gringo::Scripts &scripts_; + Gringo::Input::Program prg_; + Gringo::Defines defs_; + std::unique_ptr pb_; + std::unique_ptr parser_; + ModelHandler modelHandler_; + FinishHandler finishHandler_; + Clasp::ClaspFacade *clasp_ = nullptr; + Clasp::Cli::ClaspCliConfig &claspConfig_; + PostGroundFunc pgf_; + PreSolveFunc psf_; + std::unique_ptr data_; + std::vector props_; + std::vector> propagators_; + ClingoPropagatorLock propLock_; + Gringo::Logger logger_; +#if WITH_THREADS + std::unique_ptr solveFuture_; +#endif + std::unique_ptr solveIter_; + bool enableEnumAssupmption_ = true; + bool clingoMode_; + bool verbose_ = false; + bool parsed = false; + bool grounded = false; + bool incremental_ = true; + bool configUpdate_ = false; + bool initialized_ = false; +}; + +// {{{1 declaration of ClingoModel + +class ClingoModel : public Gringo::Model { +public: + ClingoModel(ClingoControl &ctl, Clasp::Model const *model = nullptr) + : ctl_(ctl), model_(model) { } + void reset(Clasp::Model const &m) { model_ = &m; } + bool contains(Gringo::Symbol atom) const override { + auto atm = out().find(atom); + return atm.second && atm.first->hasUid() && model_->isTrue(lp().getLiteral(atm.first->uid())); + } + Gringo::SymSpan atoms(unsigned atomset) const override { + atms_ = out().atoms(atomset, [this](unsigned uid) { return model_->isTrue(lp().getLiteral(uid)); }); + if (atomset & clingo_show_type_extra){ + ctl_.addToModel(*model_, (atomset & clingo_show_type_complement) != 0, atms_); + } + return Potassco::toSpan(atms_); + } + Gringo::Int64Vec optimization() const override { + return model_->costs ? Gringo::Int64Vec(model_->costs->begin(), model_->costs->end()) : Gringo::Int64Vec(); + } + void addClause(LitVec const &lits) const override { + Clasp::LitVec claspLits; + for (auto &x : lits) { + auto atom = out().find(x.first); + if (atom.second && atom.first->hasUid()) { + Clasp::Literal lit = lp().getLiteral(atom.first->uid()); + claspLits.push_back(x.second ? lit : ~lit); + } + else if (!x.second) { return; } + } + claspLits.push_back(~ctx().stepLiteral()); + model_->ctx->commitClause(claspLits); + } + Gringo::ModelType type() const override { + if (model_->type & Clasp::Model::Brave) { return Gringo::ModelType::BraveConsequences; } + if (model_->type & Clasp::Model::Cautious) { return Gringo::ModelType::CautiousConsequences; } + return Gringo::ModelType::StableModel; + } + uint64_t number() const override { return model_->num; } + Potassco::Id_t threadId() const override { return model_->sId; } + bool optimality_proven() const override { return model_->opt; } +private: + Clasp::Asp::LogicProgram const &lp() const { return *static_cast(ctl_.clasp_->program()); }; + Gringo::Output::OutputBase const &out() const { return *ctl_.out_; }; + Clasp::SharedContext const &ctx() const { return ctl_.clasp_->ctx; }; + ClingoControl &ctl_; + Clasp::Model const *model_; + mutable Gringo::SymVec atms_; +}; + +// {{{1 declaration of ClingoSolveIter + +class ClingoSolveIter : public Gringo::SolveIter { +public: + ClingoSolveIter(ClingoControl &ctl, Clasp::LitVec const &ass); + + Gringo::Model const *next() override; + void close() override; + Gringo::SolveResult get() override; + +private: + Clasp::ClaspFacade::ModelGenerator future_; + ClingoModel model_; +}; + +// {{{1 declaration of ClingoLib + +class ClingoLib : public Clasp::EventHandler, public ClingoControl { + using StringVec = std::vector; +public: + ClingoLib(Gringo::Scripts &scripts, int argc, char const * const *argv, Gringo::Logger::Printer printer, unsigned messageLimit); + ~ClingoLib() override; +protected: + void initOptions(ProgramOptions::OptionContext& root); + static bool parsePositional(const std::string& s, std::string& out); + // ------------------------------------------------------------------------------------------- + // Event handler + void onEvent(const Clasp::Event& ev) override; + bool onModel(const Clasp::Solver& s, const Clasp::Model& m) override; +private: + ClingoLib(const ClingoLib&); + ClingoLib& operator=(const ClingoLib&); + ClingoOptions grOpts_; + Clasp::Cli::ClaspCliConfig claspConfig_; + Clasp::ClaspFacade clasp_; +}; + +// {{{1 declaration of DefaultGringoModule + +struct DefaultGringoModule : Gringo::GringoModule { + DefaultGringoModule(); + Gringo::Control *newControl(int argc, char const * const *argv, Gringo::Logger::Printer printer, unsigned messageLimit) override; + Gringo::Symbol parseValue(std::string const &str, Gringo::Logger::Printer printer, unsigned messageLimit) override; + Gringo::Input::GroundTermParser parser; + Gringo::Scripts scripts; +}; + +// }}}1 + +#endif // _GRINGO_CLINGOCONTROL_HH diff --git a/libclingo/src/clingocontrol.cc b/libclingo/src/clingocontrol.cc new file mode 100644 index 0000000..57b6032 --- /dev/null +++ b/libclingo/src/clingocontrol.cc @@ -0,0 +1,789 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Benjamin Kaufmann +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "clingo/clingocontrol.hh" +#include +#include "clasp/solver.h" +#include +#include +#include +#include "clingo.hh" + +// {{{1 definition of ClaspAPIBackend + +void ClaspAPIBackend::initProgram(bool) { } + +void ClaspAPIBackend::endStep() { } + +void ClaspAPIBackend::beginStep() { } + +void ClaspAPIBackend::rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body) { + if (auto p = prg()) { p->addRule(ht, head, body); } +} + +void ClaspAPIBackend::rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Potassco::Weight_t bound, const Potassco::WeightLitSpan& body) { + if (auto p = prg()) { p->addRule(ht, head, bound, body); } +} + +void ClaspAPIBackend::minimize(Potassco::Weight_t prio, const Potassco::WeightLitSpan& lits) { + if (auto p = prg()) { p->addMinimize(prio, lits); } +} + +void ClaspAPIBackend::project(const Potassco::AtomSpan& atoms) { + if (auto p = prg()) { p->addProject(atoms); } +} + +void ClaspAPIBackend::output(const Potassco::StringSpan& str, const Potassco::LitSpan& condition) { + if (auto p = prg()) { p->addOutput(str, condition); } +} + +void ClaspAPIBackend::acycEdge(int s, int t, const Potassco::LitSpan& condition) { + if (auto p = prg()) { p->addAcycEdge(s, t, condition); } +} + +void ClaspAPIBackend::heuristic(Potassco::Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, const Potassco::LitSpan& condition) { + if (auto p = prg()) { p->addDomHeuristic(a, t, bias, prio, condition); } +} + +void ClaspAPIBackend::assume(const Potassco::LitSpan& lits) { + if (auto p = prg()) { p->addAssumption(lits); } +} + +void ClaspAPIBackend::external(Potassco::Atom_t a, Potassco::Value_t v) { + if (auto p = prg()) { + switch (v) { + case Potassco::Value_t::False: { p->freeze(a, Clasp::value_false); break; } + case Potassco::Value_t::True: { p->freeze(a, Clasp::value_true); break; } + case Potassco::Value_t::Free: { p->freeze(a, Clasp::value_free); break; } + case Potassco::Value_t::Release: { p->unfreeze(a); break; } + } + } +} + +void ClaspAPIBackend::theoryTerm(Potassco::Id_t, int) { } + +void ClaspAPIBackend::theoryTerm(Potassco::Id_t, const Potassco::StringSpan&) { } + +void ClaspAPIBackend::theoryTerm(Potassco::Id_t, int, const Potassco::IdSpan&) { } + +void ClaspAPIBackend::theoryElement(Potassco::Id_t e, const Potassco::IdSpan&, const Potassco::LitSpan& cond) { + if (auto p = prg()) { + Potassco::TheoryElement const &elem = p->theoryData().getElement(e); + if (elem.condition() == Potassco::TheoryData::COND_DEFERRED) { p->theoryData().setCondition(e, p->newCondition(cond)); } + } +} + +void ClaspAPIBackend::theoryAtom(Potassco::Id_t, Potassco::Id_t, const Potassco::IdSpan&) { } + +void ClaspAPIBackend::theoryAtom(Potassco::Id_t, Potassco::Id_t, const Potassco::IdSpan&, Potassco::Id_t, Potassco::Id_t){ } + +Clasp::Asp::LogicProgram *ClaspAPIBackend::prg() { + return ctl_.update() ? static_cast(ctl_.clasp_->program()) : nullptr; +} + +ClaspAPIBackend::~ClaspAPIBackend() noexcept = default; + +// {{{1 definition of ClingoControl + +#define LOG if (verbose_) std::cerr +ClingoControl::ClingoControl(Gringo::Scripts &scripts, bool clingoMode, Clasp::ClaspFacade *clasp, Clasp::Cli::ClaspCliConfig &claspConfig, PostGroundFunc pgf, PreSolveFunc psf, Gringo::Logger::Printer printer, unsigned messageLimit) +: scripts_(scripts) +, clasp_(clasp) +, claspConfig_(claspConfig) +, pgf_(pgf) +, psf_(psf) +, logger_(printer, messageLimit) +, clingoMode_(clingoMode) { } + +void ClingoControl::parse() { + if (!parser_->empty()) { + parser_->parse(logger_); + defs_.init(logger_); + parsed = true; + } + if (logger_.hasError()) { + throw std::runtime_error("parsing failed"); + } +} + +Potassco::Lit_t ClingoPropagateInit::mapLit(Lit_t lit) { + const auto& prg = static_cast(*static_cast(c_).clasp_->program()); + return Clasp::encodeLit(prg.getLiteral(lit)); +} + +int ClingoPropagateInit::threads() { + return static_cast(c_).clasp_->ctx.concurrency(); +} + +void ClingoControl::parse(const StringSeq& files, const ClingoOptions& opts, Clasp::Asp::LogicProgram* claspOut, bool addStdIn) { + using namespace Gringo; + logger_.enable(clingo_warning_operation_undefined, !opts.wNoOperationUndefined); + logger_.enable(clingo_warning_atom_undefined, !opts.wNoAtomUndef); + logger_.enable(clingo_warning_variable_unbounded, !opts.wNoVariableUnbounded); + logger_.enable(clingo_warning_file_included, !opts.wNoFileIncluded); + logger_.enable(clingo_warning_global_variable, !opts.wNoGlobalVariable); + logger_.enable(clingo_warning_other, !opts.wNoOther); + verbose_ = opts.verbose; + Output::OutputPredicates outPreds; + for (auto &x : opts.foobar) { + outPreds.emplace_back(Location("",1,1,"", 1,1), x, false); + } + if (claspOut) { + out_ = gringo_make_unique(claspOut->theoryData(), std::move(outPreds), gringo_make_unique(*this), opts.outputOptions); + } + else { + data_ = gringo_make_unique(); + out_ = gringo_make_unique(*data_, std::move(outPreds), std::cout, opts.outputFormat, opts.outputOptions); + } + out_->keepFacts = opts.keepFacts; + pb_ = gringo_make_unique(scripts_, prg_, *out_, defs_, opts.rewriteMinimize); + parser_ = gringo_make_unique(*pb_); + for (auto &x : opts.defines) { + LOG << "define: " << x << std::endl; + parser_->parseDefine(x, logger_); + } + for (auto x : files) { + LOG << "file: " << x << std::endl; + parser_->pushFile(std::move(x), logger_); + } + if (files.empty() && addStdIn) { + LOG << "reading from stdin" << std::endl; + parser_->pushFile("-", logger_); + } + parse(); +} + +bool ClingoControl::update() { + if (clingoMode_) { + clasp_->update(configUpdate_); + configUpdate_ = false; + if (!clasp_->ok()) { return false; } + } + if (!grounded) { + if (!initialized_) { + out_->init(incremental_); + initialized_ = true; + } + out_->beginStep(); + grounded = true; + } + return true; +} + +void ClingoControl::ground(Gringo::Control::GroundVec const &parts, Gringo::Context *context) { + if (!update()) { return; } + if (parsed) { + LOG << "************** parsed program **************" << std::endl << prg_; + prg_.rewrite(defs_, logger_); + LOG << "************* rewritten program ************" << std::endl << prg_; + prg_.check(logger_); + if (logger_.hasError()) { + throw std::runtime_error("grounding stopped because of errors"); + } + parsed = false; + } + if (!parts.empty()) { + Gringo::Ground::Parameters params; + for (auto &x : parts) { params.add(x.first, Gringo::SymVec(x.second)); } + auto gPrg = prg_.toGround(out_->data, logger_); + LOG << "*********** intermediate program ***********" << std::endl << gPrg << std::endl; + LOG << "************* grounded program *************" << std::endl; + auto exit = Gringo::onExit([this]{ scripts_.context = nullptr; }); + scripts_.context = context; + gPrg.ground(params, scripts_, *out_, false, logger_); + } +} + +void ClingoControl::main() { + if (scripts_.callable("main")) { + incremental_ = true; + clasp_->enableProgramUpdates(); + scripts_.main(*this); + } + else { + incremental_ = false; + claspConfig_.releaseOptions(); + Gringo::Control::GroundVec parts; + parts.emplace_back("base", Gringo::SymVec{}); + ground(parts, nullptr); + solve(nullptr, {}); + } +} +bool ClingoControl::onModel(Clasp::Model const &m) { + if (!modelHandler_) { return true; } + std::lock_guard lock(propLock_); + return modelHandler_(ClingoModel(*this, &m)); +} +void ClingoControl::onFinish(Clasp::ClaspFacade::Result ret) { + if (finishHandler_) { + finishHandler_(convert(ret)); + finishHandler_ = nullptr; + } + modelHandler_ = nullptr; +} +Gringo::Symbol ClingoControl::getConst(std::string const &name) { + auto ret = defs_.defs().find(name.c_str()); + if (ret != defs_.defs().end()) { + bool undefined = false; + Gringo::Symbol val = std::get<2>(ret->second)->eval(undefined, logger_); + if (!undefined) { return val; } + } + return Gringo::Symbol(); +} +void ClingoControl::add(std::string const &name, Gringo::FWStringVec const ¶ms, std::string const &part) { + Gringo::Location loc("", 1, 1, "", 1, 1); + Gringo::Input::IdVec idVec; + for (auto &x : params) { idVec.emplace_back(loc, x); } + parser_->pushBlock(name, std::move(idVec), part, logger_); + parse(); +} +void ClingoControl::load(std::string const &filename) { + parser_->pushFile(std::string(filename), logger_); + parse(); +} +bool ClingoControl::hasSubKey(unsigned key, char const *name, unsigned* subKey) { + *subKey = claspConfig_.getKey(key, name); + return *subKey != Clasp::Cli::ClaspCliConfig::KEY_INVALID; +} +unsigned ClingoControl::getSubKey(unsigned key, char const *name) { + unsigned ret = claspConfig_.getKey(key, name); + if (ret == Clasp::Cli::ClaspCliConfig::KEY_INVALID) { + throw std::runtime_error("invalid key"); + } + return ret; +} +unsigned ClingoControl::getArrKey(unsigned key, unsigned idx) { + unsigned ret = claspConfig_.getArrKey(key, idx); + if (ret == Clasp::Cli::ClaspCliConfig::KEY_INVALID) { + throw std::runtime_error("invalid key"); + } + return ret; +} +void ClingoControl::getKeyInfo(unsigned key, int* nSubkeys, int* arrLen, const char** help, int* nValues) const { + if (claspConfig_.getKeyInfo(key, nSubkeys, arrLen, help, nValues) < 0) { + throw std::runtime_error("could not get key info"); + } +} +const char* ClingoControl::getSubKeyName(unsigned key, unsigned idx) const { + char const *ret = claspConfig_.getSubkey(key, idx); + if (!ret) { + throw std::runtime_error("could not get subkey"); + } + return ret; +} +bool ClingoControl::getKeyValue(unsigned key, std::string &value) { + int ret = claspConfig_.getValue(key, value); + if (ret < -1) { + throw std::runtime_error("could not get option value"); + } + return ret >= 0; +} +void ClingoControl::setKeyValue(unsigned key, const char *val) { + configUpdate_ = true; + if (claspConfig_.setValue(key, val) <= 0) { + throw std::runtime_error("could not set option value"); + } +} +unsigned ClingoControl::getRootKey() { + return Clasp::Cli::ClaspCliConfig::KEY_ROOT; +} +Gringo::ConfigProxy &ClingoControl::getConf() { + return *this; +} +Gringo::SolveIter *ClingoControl::solveIter(Assumptions &&ass) { + prepare(nullptr, nullptr); + auto a = toClaspAssumptions(std::move(ass)); + solveIter_ = Gringo::gringo_make_unique(*this, a); + return solveIter_.get(); +} +Gringo::SolveFuture *ClingoControl::solveAsync(ModelHandler mh, FinishHandler fh, Assumptions &&ass) { + if (!clingoMode_) { throw std::runtime_error("solveAsync is not supported in gringo gringo mode"); } +#if WITH_THREADS + prepare(mh, fh); + auto a = toClaspAssumptions(std::move(ass)); + solveFuture_ = Gringo::gringo_make_unique(clasp_->solveAsync(nullptr, a)); + return solveFuture_.get(); +#else + (void)mh; + (void)fh; + (void)ass; + throw std::runtime_error("solveAsync requires clingo to be build with thread support"); +#endif +} +void ClingoControl::interrupt() { + clasp_->interrupt(30); +} +bool ClingoControl::blocked() { + return clasp_->solving(); +} +void ClingoControl::prepare(Gringo::Control::ModelHandler mh, Gringo::Control::FinishHandler fh) { + if (update()) { out_->endStep(true, logger_); } + grounded = false; + if (clingoMode_) { +#if WITH_THREADS + solveFuture_ = nullptr; +#endif + solveIter_ = nullptr; + finishHandler_ = fh; + modelHandler_ = mh; + Clasp::ProgramBuilder *prg = clasp_->program(); + postGround(*prg); + if (!propagators_.empty()) { + clasp_->program()->endProgram(); + for (auto&& pp : propagators_) { + ClingoPropagateInit i(*this, *pp); + static_cast(pp->propagator())->init(i); + } + propLock_.init(clasp_->ctx.concurrency()); + } + prePrepare(*clasp_); + clasp_->prepare(enableEnumAssupmption_ ? Clasp::ClaspFacade::enum_volatile : Clasp::ClaspFacade::enum_static); + preSolve(*clasp_); + } + if (data_) { data_->reset(); } + out_->reset(); +} + +Clasp::LitVec ClingoControl::toClaspAssumptions(Gringo::Control::Assumptions &&ass) const { + Clasp::LitVec outAss; + if (!clingoMode_ || !clasp_->program()) { return outAss; } + const Clasp::Asp::LogicProgram* prg = static_cast(clasp_->program()); + for (auto &x : ass) { + auto atm = out_->find(x.first); + if (atm.second && atm.first->hasUid()) { + Clasp::Literal lit = prg->getLiteral(atm.first->uid()); + outAss.push_back(x.second ? lit : ~lit); + } + else if (x.second) { + outAss.push_back(Clasp::lit_false()); + break; + } + } + return outAss; +} + +Gringo::SolveResult ClingoControl::solve(ModelHandler h, Assumptions &&ass) { + prepare(h, nullptr); + auto ret = clingoMode_ ? convert(clasp_->solve(nullptr, toClaspAssumptions(std::move(ass)))) : Gringo::SolveResult(Gringo::SolveResult::Unknown, false, false); + postSolve(*clasp_); + return ret; +} + +void *ClingoControl::claspFacade() { + return clasp_; +} + +void ClingoControl::registerPropagator(std::unique_ptr p, bool sequential) { + propagators_.emplace_back(Gringo::gringo_make_unique(*p, propLock_.add(sequential))); + claspConfig_.addConfigurator(propagators_.back().get(), Clasp::Ownership_t::Retain); + props_.emplace_back(std::move(p)); +} + +void ClingoControl::cleanupDomains() { + out_->endStep(false, logger_); + if (clingoMode_) { + Clasp::Asp::LogicProgram &prg = static_cast(*clasp_->program()); + prg.endProgram(); + Clasp::Solver &solver = *clasp_->ctx.master(); + auto assignment = [&prg, &solver](unsigned uid) { + Clasp::Literal lit = prg.getLiteral(uid); + Potassco::Value_t truth = Potassco::Value_t::Free; + if (solver.isTrue(lit)) { truth = Potassco::Value_t::True; } + else if (solver.isFalse(lit)) { truth = Potassco::Value_t::False; } + return std::make_pair(prg.isExternal(uid), truth); + }; + auto stats = out_->simplify(assignment); + LOG << stats.first << " atom" << (stats.first == 1 ? "" : "s") << " became facts" << std::endl; + LOG << stats.second << " atom" << (stats.second == 1 ? "" : "s") << " deleted" << std::endl; + } +} + +std::string ClingoControl::str() { + return "[object:IncrementalControl]"; +} + +void ClingoControl::assignExternal(Gringo::Symbol ext, Potassco::Value_t val) { + if (update()) { + auto atm = out_->find(ext); + if (atm.second && atm.first->hasUid()) { + Gringo::Id_t offset = atm.first - atm.second->begin(); + Gringo::Output::External external(Gringo::Output::LiteralId{Gringo::NAF::POS, Gringo::Output::AtomType::Predicate, offset, atm.second->domainOffset()}, val); + out_->output(external); + } + } +} + +Potassco::AbstractStatistics *ClingoControl::statistics() { + return clasp_->getStats(); +} + +void ClingoControl::useEnumAssumption(bool enable) { + enableEnumAssupmption_ = enable; +} +bool ClingoControl::useEnumAssumption() { + return enableEnumAssupmption_; +} + +Gringo::SymbolicAtoms &ClingoControl::getDomain() { + if (clingoMode_) { return *this; } + else { + throw std::runtime_error("domain introspection only supported in clingo mode"); + } +} + +namespace { + +union SymbolicAtomOffset { + SymbolicAtomOffset(clingo_symbolic_atom_iterator_t repr) + : repr(repr) { } + SymbolicAtomOffset(uint32_t domain_offset, bool domain_advance, uint32_t atom_offset, bool atom_advance) + : data{domain_offset, domain_advance, atom_offset, atom_advance} { } + clingo_symbolic_atom_iterator_t repr; + struct { + clingo_symbolic_atom_iterator_t domain_offset : 31; + clingo_symbolic_atom_iterator_t domain_advance : 1; + clingo_symbolic_atom_iterator_t atom_offset : 31; + clingo_symbolic_atom_iterator_t atom_advance : 1; + } data; +}; + +bool operator==(SymbolicAtomOffset const &a, SymbolicAtomOffset const &b) { + return a.data.domain_offset == b.data.domain_offset && a.data.atom_offset == b.data.atom_offset; +} + +SymbolicAtomOffset &toOffset(clingo_symbolic_atom_iterator_t &it) { + return reinterpret_cast(it); +} + +bool skipDomain(Gringo::Sig sig) { return sig.name().startsWith("#"); } + +Gringo::SymbolicAtomIter init(Gringo::Output::OutputBase &out, uint32_t domainOffset, bool advance) { + SymbolicAtomOffset it(domainOffset, advance, 0, false); + for (auto domIt = out.predDoms().begin() + domainOffset, domIe = out.predDoms().end(); domIt != domIe; ++domIt, ++it.data.domain_offset) { + auto &dom = **domIt; + if (!skipDomain(dom) && dom.size() > 0) { return it.repr; } + if (!it.data.domain_advance) { break; } + } + it.data.domain_offset = out.predDoms().size(); + return it.repr; +} + +void advance(Gringo::Output::OutputBase &out, Gringo::SymbolicAtomIter &it) { + auto &off = toOffset(it).data; + auto domIt = out.predDoms().begin() + off.domain_offset; + auto domIe = out.predDoms().end(); + auto elemIt = (*domIt)->begin() + off.atom_offset; + auto elemIe = (*domIt)->end(); + ++elemIt; ++off.atom_offset; + while (elemIt == elemIe) { + off.atom_offset = 0; + if (!off.domain_advance) { + off.domain_offset = out.predDoms().size(); + return; + } + ++domIt; ++off.domain_offset; + if (domIt == domIe) { return; } + if (!skipDomain(**domIt)) { + elemIt = (*domIt)->begin(); + elemIe = (*domIt)->end(); + } + } +} + +Gringo::Output::PredicateAtom &domainElem(Gringo::Output::PredDomMap &map, Gringo::SymbolicAtomIter it) { + auto &off = toOffset(it).data; + return (*map[off.domain_offset])[off.atom_offset]; +} + +} // namespace + +Gringo::Symbol ClingoControl::atom(Gringo::SymbolicAtomIter it) const { + return domainElem(out_->predDoms(), it); +} + +Potassco::Lit_t ClingoControl::literal(Gringo::SymbolicAtomIter it) const { + auto &elem = domainElem(out_->predDoms(), it); + return elem.hasUid() ? elem.uid() : 0; +} + +bool ClingoControl::fact(Gringo::SymbolicAtomIter it) const { + return domainElem(out_->predDoms(), it).fact(); +} + +bool ClingoControl::external(Gringo::SymbolicAtomIter it) const { + auto &elem = domainElem(out_->predDoms(), it); + return elem.hasUid() && elem.isExternal() && static_cast(clasp_->program())->isExternal(elem.uid()); +} + +Gringo::SymbolicAtomIter ClingoControl::next(Gringo::SymbolicAtomIter it) { + advance(*out_, it); + return it; +} + +bool ClingoControl::valid(Gringo::SymbolicAtomIter it) const { + auto &off = toOffset(it).data; + return off.domain_offset < out_->predDoms().size() && off.atom_offset < out_->predDoms()[off.domain_offset]->size(); +} + +std::vector ClingoControl::signatures() const { + std::vector ret; + for (auto &dom : out_->predDoms()) { + if (!skipDomain(*dom)) { ret.emplace_back(*dom); } + } + return ret; +} + +Gringo::SymbolicAtomIter ClingoControl::begin(Gringo::Sig sig) const { + return init(*out_, out_->predDoms().offset(out_->predDoms().find(sig)), false); +} + +Gringo::SymbolicAtomIter ClingoControl::begin() const { + return init(*out_, 0, true); +} + +Gringo::SymbolicAtomIter ClingoControl::end() const { + return SymbolicAtomOffset{out_->predDoms().size(), false, 0, false}.repr; +} + +bool ClingoControl::eq(Gringo::SymbolicAtomIter it, Gringo::SymbolicAtomIter jt) const { + return toOffset(it) == toOffset(jt); +} + +Gringo::SymbolicAtomIter ClingoControl::lookup(Gringo::Symbol atom) const { + if (atom.hasSig()) { + auto it = out_->predDoms().find(atom.sig()); + if (it != out_->predDoms().end()) { + auto jt = (*it)->find(atom); + if (jt != (*it)->end()) { + return SymbolicAtomOffset(out_->predDoms().offset(it), true, jt - (*it)->begin(), true).repr; + } + } + } + return SymbolicAtomOffset(out_->predDoms().size(), true, 0, true).repr; +} + +size_t ClingoControl::length() const { + size_t ret = 0; + for (auto &dom : out_->predDoms()) { + if (!skipDomain(*dom)) { + ret += dom->size(); + } + } + return ret; +} + +Gringo::Backend *ClingoControl::backend() { return out_->backend(); } +Potassco::Atom_t ClingoControl::addProgramAtom() { return out_->data.newAtom(); } + +ClingoControl::~ClingoControl() noexcept = default; + +// {{{1 definition of ClingoSolveIter + +ClingoSolveIter::ClingoSolveIter(ClingoControl &ctl, Clasp::LitVec const &ass) +: future_(ctl.clasp_->startSolve(ass)) +, model_(ctl) { } + +Gringo::Model const *ClingoSolveIter::next() { + if (future_.next()) { + model_.reset(future_.model()); + return &model_; + } + else { return nullptr; } +} + +void ClingoSolveIter::close() { + future_.stop(); +} + +Gringo::SolveResult ClingoSolveIter::get() { + return convert(future_.result()); +} + +// {{{1 definition of ClingoSolveFuture + +Gringo::SolveResult convert(Clasp::ClaspFacade::Result res) { + if (res.interrupted() && res.signal == SIGINT) { + throw std::runtime_error("solving stopped by signal"); + } + Gringo::SolveResult::Satisfiabily sat = Gringo::SolveResult::Satisfiable; + switch (res) { + case Clasp::ClaspFacade::Result::SAT: { sat = Gringo::SolveResult::Satisfiable; break; } + case Clasp::ClaspFacade::Result::UNSAT: { sat = Gringo::SolveResult::Unsatisfiable; break; } + case Clasp::ClaspFacade::Result::UNKNOWN: { sat = Gringo::SolveResult::Unknown; break; } + } + return {sat, res.exhausted(), res.interrupted()}; +} + +#if WITH_THREADS +ClingoSolveFuture::ClingoSolveFuture(Clasp::ClaspFacade::AsyncResult const &res) + : future(res) { } +Gringo::SolveResult ClingoSolveFuture::get() { + if (!done) { + done = true; + ret = convert(future.get()); + } + return ret; +} +void ClingoSolveFuture::wait() { get(); } +bool ClingoSolveFuture::wait(double timeout) { + if (!done) { + if (timeout == 0 ? !future.ready() : !future.waitFor(timeout)) { return false; } + wait(); + } + return true; +} +void ClingoSolveFuture::cancel() { future.cancel(); } +#endif + +// {{{1 definition of ClingoLib + +ClingoLib::ClingoLib(Gringo::Scripts &scripts, int argc, char const * const *argv, Gringo::Logger::Printer printer, unsigned messageLimit) + : ClingoControl(scripts, true, &clasp_, claspConfig_, nullptr, nullptr, printer, messageLimit) { + using namespace ProgramOptions; + OptionContext allOpts(""); + initOptions(allOpts); + ParsedValues values = parseCommandArray(argv, argc, allOpts, false, parsePositional); + ParsedOptions parsed; + parsed.assign(values); + allOpts.assignDefaults(parsed); + claspConfig_.finalize(parsed, Clasp::Problem_t::Asp, true); + clasp_.ctx.setEventHandler(this); + Clasp::Asp::LogicProgram* lp = &clasp_.startAsp(claspConfig_, true); + parse({}, grOpts_, lp, false); +} + + +static bool parseConst(const std::string& str, std::vector& out) { + out.push_back(str); + return true; +} + +void ClingoLib::initOptions(ProgramOptions::OptionContext& root) { + using namespace ProgramOptions; + grOpts_.defines.clear(); + grOpts_.verbose = false; + OptionGroup gringo("Gringo Options"); + gringo.addOptions() + ("verbose,V" , flag(grOpts_.verbose = false), "Enable verbose output") + ("const,c" , storeTo(grOpts_.defines, parseConst)->composing()->arg("="), "Replace term occurences of with ") + ("output-debug", storeTo(grOpts_.outputOptions.debug = Gringo::Output::OutputDebug::NONE, values() + ("none", Gringo::Output::OutputDebug::NONE) + ("text", Gringo::Output::OutputDebug::TEXT) + ("translate", Gringo::Output::OutputDebug::TRANSLATE) + ("all", Gringo::Output::OutputDebug::ALL)), "Print debug information during output:\n" + " none : no additional info\n" + " text : print rules as plain text (prefix %%)\n" + " translate: print translated rules as plain text (prefix %%%%)\n" + " all : combines text and translate") + ("warn,W" , storeTo(grOpts_, parseWarning)->arg("")->composing(), "Enable/disable warnings:\n" + " none: disable all warnings\n" + " all: enable all warnings\n" + " [no-]atom-undefined: a :- b.\n" + " [no-]file-included: #include \"a.lp\". #include \"a.lp\".\n" + " [no-]operation-undefined: p(1/0).\n" + " [no-]variable-unbounded: $x > 10.\n" + " [no-]global-variable: :- #count { X } = 1, X = 1.\n" + " [no-]other: clasp related and uncategorized warnings") + ("rewrite-minimize" , flag(grOpts_.rewriteMinimize = false), "Rewrite minimize constraints into rules") + ("keep-facts" , flag(grOpts_.keepFacts = false), "Do not remove facts from normal rules") + ; + root.add(gringo); + claspConfig_.addOptions(root); +} + +bool ClingoLib::onModel(Clasp::Solver const&, Clasp::Model const& m) { + return ClingoControl::onModel(m); +} +void ClingoLib::onEvent(Clasp::Event const& ev) { +#if WITH_THREADS + Clasp::ClaspFacade::StepReady const *r = Clasp::event_cast(ev); + if (r && finishHandler_) { onFinish(r->summary->result); } +#endif + const Clasp::LogEvent* log = Clasp::event_cast(ev); + if (log && log->isWarning()) { logger_.print(clingo_warning_other, log->msg); } +} +bool ClingoLib::parsePositional(const std::string& t, std::string& out) { + int num; + if (bk_lib::string_cast(t, num)) { + out = "number"; + return true; + } + return false; +} +ClingoLib::~ClingoLib() { + // TODO: can be removed after bennies next update... +#if WITH_THREADS + solveFuture_ = nullptr; +#endif + solveIter_ = nullptr; + clasp_.shutdown(); +} + +// {{{1 definition of DefaultGringoModule + +DefaultGringoModule::DefaultGringoModule() +: scripts(*this) { } + +Gringo::Control *DefaultGringoModule::newControl(int argc, char const * const*argv, Gringo::Logger::Printer printer, unsigned messageLimit) { + return new ClingoLib(scripts, argc, argv, printer, messageLimit); +} + +Gringo::Symbol DefaultGringoModule::parseValue(std::string const &str, Gringo::Logger::Printer printer, unsigned messageLimit) { + Gringo::Logger logger(printer, messageLimit); + return parser.parse(str, logger); +} + +extern "C" bool clingo_control_new(char const *const * args, size_t n, clingo_logger_t *logger, void *data, unsigned message_limit, clingo_control_t **ctl) { + GRINGO_CLINGO_TRY { + static std::mutex mut; + static DefaultGringoModule mod; + std::lock_guard grd(mut); + *ctl = mod.newControl(n, args, logger ? [logger, data](clingo_warning_t code, char const *msg) { logger(code, msg, data); } : Gringo::Logger::Printer(nullptr), message_limit); + } + GRINGO_CLINGO_CATCH; +} + +struct Clingo::Control::Impl { + Impl(Logger logger) + : ctl(nullptr) + , logger(logger) { } + Impl(clingo_control_t *ctl) + : ctl(ctl) { } + ~Impl() noexcept { + if (ctl) { clingo_control_free(ctl); } + } + operator clingo_control_t *() { return ctl; } + clingo_control_t *ctl; + Logger logger; + ModelCallback mh; + FinishCallback fh; +}; + +Clingo::Control::Control(StringSpan args, Logger logger, unsigned message_limit) +: impl_(new Clingo::Control::Impl(logger)) +{ + Gringo::handleCError(clingo_control_new(args.begin(), args.size(), [](clingo_warning_t code, char const *msg, void *data) { + try { (*static_cast(data))(static_cast(code), msg); } + catch (...) { } + }, &impl_->logger, message_limit, &impl_->ctl)); +} + +// }}}1 diff --git a/libclingo/tests/ast.cc b/libclingo/tests/ast.cc new file mode 100644 index 0000000..2fd3c44 --- /dev/null +++ b/libclingo/tests/ast.cc @@ -0,0 +1,285 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests.hh" +#include +#include + +namespace Clingo { namespace Test { + +namespace { + +struct CB { + CB(std::string &ret) + : ret(ret) { ret.clear(); } + void operator()(AST::Statement &&x) { + std::ostringstream oss; + oss << x; + if (first) { + REQUIRE(oss.str() == "#program base."); + first = false; + } + else { + if (!ret.empty()) { ret+= "\n"; } + ret+= oss.str(); + } + } + bool first = true; + std::string &ret; +}; + +std::string parse(char const *prg) { + std::string ret; + parse_program(prg, CB(ret)); + return ret; +} + +ModelVec solve(char const *prg, PartSpan parts = {{"base", {}}}) { + MessageVec messages; + ModelVec models; + Control ctl{{"0"}, [&messages](WarningCode code, char const *msg) { messages.emplace_back(code, msg); }, 20}; + ctl.with_builder([prg](ProgramBuilder &b){ + parse_program(prg, [&b](AST::Statement const &stm) { b.add(stm); }); + }); + ctl.ground(parts); + ctl.solve(MCB(models)); + return models; +} + +using StringVec = std::vector; +StringVec parse_theory(char const *prg, char const *theory) { + MessageVec messages; + ModelVec models; + Control ctl{{"0"}, [&messages](WarningCode code, char const *msg) { messages.emplace_back(code, msg); }, 20}; + ctl.with_builder([prg, theory](ProgramBuilder &b){ + parse_program(theory, [&b](AST::Statement const &stm) { b.add(stm); }); + parse_program(prg, [&b](AST::Statement const &stm) { b.add(stm); }); + }); + ctl.ground({{"base", {}}}); + StringVec ret; + for (auto x : ctl.theory_atoms()) { + std::ostringstream oss; + oss << x; + ret.emplace_back(oss.str()); + } + return ret; +} + +} // namespace + +TEST_CASE("parse-ast", "[clingo]") { + SECTION("statement") { + REQUIRE(parse("a.") == "a."); + REQUIRE(parse("a:-b.") == "a :- b."); + REQUIRE(parse("#const a=10.") == "#const a = 10. [default]"); + REQUIRE(parse("#show a/1.") == "#show a/1."); + REQUIRE(parse("#show $a/1.") == "#show $a/1."); + REQUIRE(parse("#show a : b.") == "#show a : b."); + REQUIRE(parse("#show $a : b.") == "#show $a : b."); + REQUIRE(parse("#show $a : b.") == "#show $a : b."); + REQUIRE(parse("#minimize{ 1:b }.") == ":~ b. [1@0]"); + REQUIRE(parse("#script (python) 42 #end.") == "#script (python) 42 #end."); + REQUIRE(parse("#program p(k).") == "#program p(k)."); + REQUIRE(parse("#external p(k).") == "#external p(k)."); + REQUIRE(parse("#external p(k) : a, b.") == "#external p(k) : a; b."); + REQUIRE(parse("#edge (u,v) : a, b.") == "#edge (u,v) : a; b."); + REQUIRE(parse("#heuristic a : b, c. [L@P,level]") == "#heuristic a : b; c. [L@P,level]"); + REQUIRE(parse("#project a : b.") == "#project a : b."); + REQUIRE(parse("#project a/2.") == "#project a/2."); + REQUIRE(parse("#theory x {}.") == "#theory x {\n}."); + } + SECTION("theory definition") { + REQUIRE(parse("#theory x { t { ++ : 1, unary } }.") == "#theory x {\n" " t {\n" " ++ : 1, unary\n" " }\n" "}."); + REQUIRE(parse("#theory x { &a/0 : t, any }.") == "#theory x {\n &a/0 : t, any\n}."); + REQUIRE(parse("#theory x { &a/0 : t, {+, -}, u, any }.") == "#theory x {\n &a/0 : t, { +, - }, u, any\n}."); + } + SECTION("body literal") { + REQUIRE(parse(":-a.") == "#false :- a."); + REQUIRE(parse(":-not a.") == "#false :- not a."); + REQUIRE(parse(":-not not a.") == "#false :- not not a."); + REQUIRE(parse(":-a:b.") == "#false :- a : b."); + REQUIRE(parse(":-a:b,c;d.") == "#false :- a : b, c; d."); + REQUIRE(parse(":-1{a:b,c;e}2.") == "#false :- 1 <= { a : b, c; e : } <= 2."); + REQUIRE(parse(":-{a:b,c;e}2.") == "#false :- 2 >= { a : b, c; e : }."); + REQUIRE(parse(":-1#min{1,2:b,c;1:e}2.") == "#false :- 1 <= #min { 1,2 : b, c; 1 : e } <= 2."); + REQUIRE(parse(":-&p { 1 : a,b; 2 : c }.") == "#false :- &p { 1 : a,b; 2 : c }."); + REQUIRE(parse(":-#disjoint {1,2:$x:a,b}.") == "#false :- #disjoint { 1,2 : 1$*$x : a,b }."); + } + SECTION("head literal") { + REQUIRE(parse("a.") == "a."); + REQUIRE(parse("a:b.") == "a : b."); + REQUIRE(parse("a:b,c;d.") == "d : ; a : b, c."); + REQUIRE(parse("1{a:b,c;e}2.") == "1 <= { a : b, c; e : } <= 2."); + REQUIRE(parse("{a:b,c;e}2.") == "2 >= { a : b, c; e : }."); + REQUIRE(parse("1#min{1,2:h:b,c;1:e}2.") == "1 <= #min { 1,2 : h : b, c; 1 : e : } <= 2."); + REQUIRE(parse("&p { 1 : a,b; 2 : c }.") == "&p { 1 : a,b; 2 : c }."); + REQUIRE(parse("&p { 1 : a,b; 2 : c } ** 33.") == "&p { 1 : a,b; 2 : c } ** 33."); + } + SECTION("literal") { + REQUIRE(parse("#true.") == "#true."); + REQUIRE(parse("#false.") == "#false."); + REQUIRE(parse("a.") == "a."); + REQUIRE(parse("not a.") == "not a."); + REQUIRE(parse("not not a.") == "not not a."); + REQUIRE(parse("1 != 3.") == "1!=3."); + REQUIRE(parse("1 $< 2 $< 3.") == "1$<2$<3."); + REQUIRE(parse("1 $< 2 $< 3.") == "1$<2$<3."); + } + SECTION("terms") { + REQUIRE(parse("p(a).") == "p(a)."); + REQUIRE(parse("p(X).") == "p(X)."); + REQUIRE(parse("p(-a).") == "p(-a)."); + REQUIRE(parse("p(~a).") == "p(~a)."); + REQUIRE(parse("p(|a|).") == "p(|a|)."); + REQUIRE(parse("p((a+b)).") == "p((a+b))."); + REQUIRE(parse("p((a-b)).") == "p((a-b))."); + REQUIRE(parse("p((a*b)).") == "p((a*b))."); + REQUIRE(parse("p((a/b)).") == "p((a/b))."); + REQUIRE(parse("p((a\\b)).") == "p((a\\b))."); + REQUIRE(parse("p((a?b)).") == "p((a?b))."); + REQUIRE(parse("p((a^b)).") == "p((a^b))."); + REQUIRE(parse("p(a..b).") == "p((a..b))."); + REQUIRE(parse("p((),(1,),f(),f(1,2)).") == "p((),(1,),f,f(1,2))."); + REQUIRE(parse("p(a;b).") == "(p(a);p(b))."); + REQUIRE(parse("p((a,;b)).") == "p(((a,);b))."); + REQUIRE(parse("1 $+ 3 $* $x $+ 7 $< 2 $< 3.") == "1$+3$*$x$+7$<2$<3."); + } + SECTION("theory terms") { + REQUIRE(parse("&p{ } !! a.") == "&p { } !! a."); + REQUIRE(parse("&p{ } !! X.") == "&p { } !! X."); + REQUIRE(parse("&p{ } !! [].") == "&p { } !! []."); + REQUIRE(parse("&p{ } !! [1].") == "&p { } !! [1]."); + REQUIRE(parse("&p{ } !! [1,2].") == "&p { } !! [1,2]."); + REQUIRE(parse("&p{ } !! ().") == "&p { } !! ()."); + REQUIRE(parse("&p{ } !! (a).") == "&p { } !! a."); + REQUIRE(parse("&p{ } !! (a,).") == "&p { } !! (a,)."); + REQUIRE(parse("&p{ } !! {}.") == "&p { } !! {}."); + REQUIRE(parse("&p{ } !! f().") == "&p { } !! f."); + REQUIRE(parse("&p{ } !! f(a,1).") == "&p { } !! f(a,1)."); + REQUIRE(parse("&p{ } !! 1 + (x + y * z).") == "&p { } !! (1 + (x + y * z))."); + } +} + +TEST_CASE("add-ast", "[clingo]") { + SECTION("statement") { + REQUIRE(solve("a.") == ModelVec({{Id("a")}})); + REQUIRE(solve("a. c. b :- a, c.") == ModelVec({{Id("a"), Id("b"), Id("c")}})); + REQUIRE(solve("#const a=10. p(a).") == ModelVec({{Function("p", {Number(10)})}})); + REQUIRE(solve("a. b. #show a/0.") == ModelVec({{Id("a")}})); + REQUIRE(solve("$a$=1. $b$=2. #show $a/0.") == ModelVec({{Function("$", {Id("a"), Number(1)})}})); + REQUIRE(solve("a. #show b : a.") == ModelVec({{Id("a"), Id("b")}})); + REQUIRE(solve("$a$=1. $b$=2. #show. #show $a.") == ModelVec({{Function("$", {Id("a"), Number(1)})}})); + REQUIRE(solve("#minimize{ 1:b; 2:a }. {a;b}. :- not a, not b.") == ModelVec({{Id("b")}})); +#ifdef WITH_LUA + // NOTE: at the moment it is not possible to add additional script code - it is simply ignored + REQUIRE(solve("#script (lua) function x() return 32; end #end. p(@x()).") == ModelVec({SymbolVector{}})); +#endif + REQUIRE(solve("#edge (u,v) : a. #edge (v,u) : b. {a;b}.") == ModelVec({{}, {Id("a")}, {Id("b")}})); + REQUIRE(solve("#theory x {}.") == ModelVec({SymbolVector{}})); + // these just test parsing... + REQUIRE(solve("#external a.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("#heuristic a : b, c. [1@2,level]") == ModelVec({SymbolVector{}})); + REQUIRE(solve("#project a.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("#project a/0.") == ModelVec({SymbolVector{}})); + } + SECTION("body literal") { + REQUIRE(solve("{a}. :-a.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("{a}. :-not a.") == ModelVec({{Id("a")}})); + REQUIRE(solve("{a}. :-not not a.") == ModelVec({SymbolVector{}})); + REQUIRE(solve(":-a:b.") == ModelVec({})); + REQUIRE(solve(":-0{a:b;c}1. {a;b;c}.") == ModelVec({{Id("a"), Id("b"), Id("c")}})); + REQUIRE(solve(":-0#min{1,2:a,b;2:c}2. {a;b;c}.") == ModelVec({{}, {Id("a")}, {Id("b")}})); + auto c = [](char const *name, int value) { return Function("$", {Id(name), Number(value)}); }; + REQUIRE(solve("1 $<= $x $<= 2. 1 $<= $y $<= 2. :- #disjoint {1:$x; 2:$y}.") == ModelVec({{c("x", 1), c("y", 1)}, {c("x", 2), c("y", 2)}})); + } + SECTION("head literal") { + REQUIRE(solve("a.") == ModelVec({{Id("a")}})); + REQUIRE(solve("not a.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("not not a.") == ModelVec({})); + REQUIRE(solve("a:b;c.{b}.") == ModelVec({{Id("a"), Id("b")}, {Id("b"), Id("c")}, {Id("c")}})); + REQUIRE(solve("1{a:b;b}2.") == ModelVec({{Id("a"), Id("b")}, {Id("b")}})); + REQUIRE(solve("#min{1,2:a;2:c}1.") == ModelVec({{Id("a")}, {Id("a"), Id("c")}})); + } + SECTION("literal") { + REQUIRE(solve("a.") == ModelVec({{Id("a")}})); + REQUIRE(solve("1=1.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("1!=1.") == ModelVec({})); + REQUIRE(solve("#true.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("#false.") == ModelVec({})); + REQUIRE(solve("1 $< 2 $< 3.") == ModelVec({SymbolVector{}})); + REQUIRE(solve("2 $< 3 $< 1.") == ModelVec({})); + } + SECTION("terms") { + auto t = [](char const *s) { return ModelVec({{parse_term(s)}}); }; + auto tt = [](std::initializer_list l) { + SymbolVector ret; + for (auto &s : l) { ret.emplace_back(parse_term(s)); } + return ModelVec{ret}; + }; + REQUIRE(solve("p(a).") == t("p(a)")); + REQUIRE(solve("p(X) :- X=a.") == t("p(a)")); + REQUIRE(solve("p(-1).") == t("p(-1)")); + REQUIRE(solve("p(|1|).") == t("p(|1|)")); + REQUIRE(solve("p((3+2)).") == t("p(5)")); + REQUIRE(solve("p((3-2)).") == t("p(1)")); + REQUIRE(solve("p((3*2)).") == t("p(6)")); + REQUIRE(solve("p((7/2)).") == t("p(3)")); + REQUIRE(solve("p((7\\2)).") == t("p(1)")); + REQUIRE(solve("p((7?2)).") == t("p(7)")); + REQUIRE(solve("p((7^2)).") == t("p(5)")); + REQUIRE(solve("p(3..3).") == t("p(3)")); + REQUIRE(solve("p(a;b).") == tt({"p(a)", "p(b)"})); + REQUIRE(solve("p((),(1,),f(),f(1,2)).") == t("p((),(1,),f,f(1,2))")); + REQUIRE(solve("p((a,;b)).") == tt({"p(b)", "p((a,))"})); + REQUIRE(solve("12 $< 1 $+ 3 $* $x $+ 7 $< 17. 0 $<= x $<= 4.") == ModelVec({{Function("$", {Id("x"), Number(2)})}})); + } + SECTION("theory") { + char const *theory = R"( +#theory x { + t { + * : 1, binary, left; + ^ : 2, binary, right; + - : 3, unary + }; + &a/0 : t, directive; + &b/0 : t, {=}, t, any +}. +)"; + REQUIRE(parse("&p{ } !! 1 + (x + y * z).") == "&p { } !! (1 + (x + y * z))."); + REQUIRE(parse_theory("&a{}.", theory) == StringVec({"&a{}"})); + REQUIRE(parse_theory("&a{1,2,3:a,b}. {a;b}.", theory) == StringVec({"&a{1,2,3: a,b}"})); + REQUIRE(parse_theory("&b{} = a.", theory) == StringVec({"&b{}=a"})); + REQUIRE(parse_theory("&b{} = X:-X=1.", theory) == StringVec({"&b{}=1"})); + REQUIRE(parse_theory("&b{} = [].", theory) == StringVec({"&b{}=[]"})); + REQUIRE(parse_theory("&b{} = [1].", theory) == StringVec({"&b{}=[1]"})); + REQUIRE(parse_theory("&b{} = [1,2].", theory) == StringVec({"&b{}=[1,2]"})); + REQUIRE(parse_theory("&b{} = ().", theory) == StringVec({"&b{}=()"})); + REQUIRE(parse_theory("&b{} = (a).", theory) == StringVec({"&b{}=a"})); + REQUIRE(parse_theory("&b{} = (a,).", theory) == StringVec({"&b{}=(a,)"})); + REQUIRE(parse_theory("&b{} = {}.", theory) == StringVec({"&b{}={}"})); + REQUIRE(parse_theory("&b{} = f().", theory) == StringVec({"&b{}=f()"})); + REQUIRE(parse_theory("&b{} = f(a,1).", theory) == StringVec({"&b{}=f(a,1)"})); + REQUIRE(parse_theory("&b{} = a*x.", theory) == StringVec({"&b{}=(a*x)"})); + REQUIRE(parse_theory("&b{} = -a*x*y^z^u.", theory) == StringVec({"&b{}=(((-a)*x)*(y^(z^u)))"})); + REQUIRE(parse_theory("&b{} = -(a*x*y^z^u).", theory) == StringVec({"&b{}=(-((a*x)*(y^(z^u))))"})); + } +} + +} } // namespace Test Clingo diff --git a/libclingo/tests/catch.hpp b/libclingo/tests/catch.hpp new file mode 100644 index 0000000..879fc5b --- /dev/null +++ b/libclingo/tests/catch.hpp @@ -0,0 +1,10509 @@ +/* + * Catch v1.5.6 + * Generated: 2016-06-09 19:20:41.460328 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#ifdef __cplusplus + +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + namespace{ \ + struct TestName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( nullptr, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + CATCH_AUTO_PTR( IStream const ) m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.2.4 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include +#include +#include + +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CLARA_PLATFORM_WINDOWS +#endif + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + inline std::vector argsToVector( int argc, char const* const* const argv ) { + std::vector args( static_cast( argc ) ); + for( std::size_t i = 0; i < static_cast( argc ); ++i ) + args[i] = argv[i]; + + return args; + } + + class Parser { + enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; + Mode mode; + std::size_t from; + bool inQuotes; + public: + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + Parser() : mode( None ), from( 0 ), inQuotes( false ){} + + void parseIntoTokens( std::vector const& args, std::vector& tokens ) { + const std::string doubleDash = "--"; + for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) + parseIntoTokens( args[i], tokens); + } + + void parseIntoTokens( std::string const& arg, std::vector& tokens ) { + for( std::size_t i = 0; i <= arg.size(); ++i ) { + char c = arg[i]; + if( c == '"' ) + inQuotes = !inQuotes; + mode = handleMode( i, c, arg, tokens ); + } + } + Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + switch( mode ) { + case None: return handleNone( i, c ); + case MaybeShortOpt: return handleMaybeShortOpt( i, c ); + case ShortOpt: + case LongOpt: + case SlashOpt: return handleOpt( i, c, arg, tokens ); + case Positional: return handlePositional( i, c, arg, tokens ); + default: throw std::logic_error( "Unknown mode" ); + } + } + + Mode handleNone( std::size_t i, char c ) { + if( inQuotes ) { + from = i; + return Positional; + } + switch( c ) { + case '-': return MaybeShortOpt; +#ifdef CLARA_PLATFORM_WINDOWS + case '/': from = i+1; return SlashOpt; +#endif + default: from = i; return Positional; + } + } + Mode handleMaybeShortOpt( std::size_t i, char c ) { + switch( c ) { + case '-': from = i+1; return LongOpt; + default: from = i; return ShortOpt; + } + } + Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) + return mode; + + std::string optName = arg.substr( from, i-from ); + if( mode == ShortOpt ) + for( std::size_t j = 0; j < optName.size(); ++j ) + tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); + else if( mode == SlashOpt && optName.size() == 1 ) + tokens.push_back( Token( Token::ShortOpt, optName ) ); + else + tokens.push_back( Token( Token::LongOpt, optName ) ); + return None; + } + Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) + return mode; + + std::string data = arg.substr( from, i-from ); + tokens.push_back( Token( Token::Positional, data ) ); + return None; + } + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( std::vector const& args ) const { + ConfigT config; + parseInto( args, config ); + return config; + } + + std::vector parseInto( std::vector const& args, ConfigT& config ) const { + std::string processName = args[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( args, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.set( config, "true" ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + class MultipleReporters; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map > FactoryMap; + typedef std::vector > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = static_cast( childTracker ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = static_cast( childTracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* const* const argv ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef CATCH_CPP14_OR_GREATER +#include +#endif + +namespace Catch { + + struct RandomNumberGenerator { + typedef int result_type; + + result_type operator()( result_type n ) const { return std::rand() % n; } + +#ifdef CATCH_CPP14_OR_GREATER + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return 1000000; } + result_type operator()() const { return std::rand() % max(); } +#endif + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; +#ifdef CATCH_CPP14_OR_GREATER + std::shuffle( vector.begin(), vector.end(), rng ); +#else + std::random_shuffle( vector.begin(), vector.end(), rng ); +#endif + } + }; + + inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ) { + std::ostringstream ss; + + ss << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + + throw std::runtime_error(ss.str()); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector const& getAllTests() const { + return m_functions; + } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 5, 6, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } + + virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + return this; + } + +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = existingReporter->tryAsMulti(); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/libclingo/tests/clingo.cc b/libclingo/tests/clingo.cc new file mode 100644 index 0000000..d8dd0b9 --- /dev/null +++ b/libclingo/tests/clingo.cc @@ -0,0 +1,534 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests.hh" +#include +#include + +namespace Clingo { namespace Test { + +TEST_CASE("parse_term", "[clingo]") { + MessageVec messages; + Logger logger = [&messages](WarningCode code, char const *msg) { messages.emplace_back(code, msg); }; + REQUIRE(parse_term("10+1").number() == 11); + REQUIRE_THROWS(parse_term("10+", logger)); + //REQUIRE(messages == (MessageVec{{WarningCode::Runtime, ":1:5: error: syntax error, unexpected \n"}})); + messages.clear(); + REQUIRE_THROWS(parse_term("10+a", logger)); + REQUIRE(messages.size() == 0); +} + +class Observer : public GroundProgramObserver { +public: + Observer(std::vector &trail) + : trail_(trail) { } + + void init_program(bool incremental) override { + trail_.emplace_back(incremental ? "IP: incremental" : "IP"); + } + void begin_step() override { + trail_.emplace_back("BS"); + } + void end_step() override { + trail_.emplace_back("ES"); + } + + void rule(bool choice, AtomSpan head, LiteralSpan body) override { + std::ostringstream out; + out << "R: "; + if (choice) { out << "{"; } + bool comma = false; + for (auto &h : head) { + if (comma) { out << (choice ? "," : "|"); } + else { comma = true; } + out << h; + } + if (choice) { out << "}"; } + out << ":-"; + comma = false; + for (auto &b : body) { + if (comma) { out << ","; } + else { comma = true; } + if (b > 0) { out << b; } + else { out << "~" << -b; } + } + trail_.emplace_back(out.str()); + } +private: + std::vector &trail_; +}; + +TEST_CASE("solving", "[clingo]") { + SECTION("with control") { + MessageVec messages; + ModelVec models; + Control ctl{{"0"}, [&messages](WarningCode code, char const *msg) { messages.emplace_back(code, msg); }, 20}; + SECTION("solve") { + static int n = 0; + if (++n < 3) { // workaround for some bug with catch + SECTION("add") { ctl.add("base", {}, "{a}."); } + SECTION("load") { + struct Temp { + Temp() : file(std::tmpnam(temp)) { } + ~Temp() { if (file) { std::remove(temp); } } + char temp[L_tmpnam]; + char *file; + } t; + REQUIRE(t.file != nullptr); + std::ofstream(t.file) << "{a}.\n"; + ctl.load(t.file); + } + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models == ModelVec({{},{Id("a")}})); + REQUIRE(messages.empty()); + } + } + SECTION("statistics") { + ctl.add("pigeon", {"p", "h"}, "1 {p(P,H) : P=1..p}1 :- H=1..h." + "1 {p(P,H) : H=1..h}1 :- P=1..p."); + ctl.ground({{"pigeon", {Number(6), Number(5)}}}); + auto conf = ctl.configuration(); + conf["stats"] = "2"; + REQUIRE(ctl.solve(MCB(models)).is_unsatisfiable()); + std::vector keys_root; + auto stats = ctl.statistics(); + std::copy(stats.keys().begin(), stats.keys().end(), std::back_inserter(keys_root)); + std::sort(keys_root.begin(), keys_root.end()); + std::vector keys_check = { "accu", "problem", "solving", "summary" }; + REQUIRE(keys_root == keys_check); + auto solving = stats["solving"]; + REQUIRE(solving["solver"].type() == StatisticsType::Array); + REQUIRE(solving["solvers"].type() == StatisticsType::Map); + REQUIRE(stats["summary.times.cpu"].type() == StatisticsType::Value); + REQUIRE(stats["summary.times.cpu"] >= 0.0); + REQUIRE(solving["solver"].size() == 1); + REQUIRE(solving["solver"][size_t(0)]["conflicts"] > 0); + int nloop = 0; + for (auto s : stats["solving.solver"]) { + REQUIRE(s["conflicts"] > 0); + ++nloop; + } + REQUIRE(nloop == 1); + } + SECTION("configuration") { + auto conf = ctl.configuration(); + std::vector keys_root; + std::copy(conf.keys().begin(), conf.keys().end(), std::back_inserter(keys_root)); + std::sort(keys_root.begin(), keys_root.end()); + std::vector keys_check = { "asp", "configuration", "learn_explicit", "parse_ext", "sat_prepro", "share", "solve", "solver", "stats", "tester" }; + REQUIRE(keys_root == keys_check); + REQUIRE(conf["solve"]["models"].is_value()); + conf["solve"]["models"] = "2"; + REQUIRE(conf["solve"].decription() == S("Solve Options")); + REQUIRE(conf["solve"]["models"].is_assigned()); + REQUIRE(conf["solve"]["models"].value() == "2"); + REQUIRE(conf["solver"].is_array()); + REQUIRE(conf["solver"].size() == 1); + int nloop = 0; + for (auto s : conf["solver"]) { + s["heuristic"] = "berkmin,100"; + ++nloop; + } + REQUIRE(nloop == 1); + CHECK(conf["solver"][size_t(0)]["heuristic"].value() == "berkmin,100"); + CHECK(conf["solver"]["heuristic"].value() == "berkmin,100"); + ctl.add("base", {}, "{a; b; c}."); + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() == 2); + } + SECTION("backend") { + // NOTE: ground has to be called before using the backend + auto backend = ctl.backend(); + literal_t a = backend.add_atom(), b = backend.add_atom(); + backend.rule(true, {atom_t(a)}, {}); + backend.rule(false, {atom_t(b)}, {-a}); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{},{}})); + backend.assume({a}); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{}})); + backend.minimize(1, {{a,1},{b,1}}); + ctl.solve(MCB(models)); + REQUIRE(ctl.statistics()["summary.costs"].size() == 1); + REQUIRE(ctl.statistics()["summary.costs"][size_t(0)] == 1); + REQUIRE(ctl.statistics()["summary.call"] == 2); + // Note: I don't have a good idea how to test this one + // void heuristic(atom_t atom, HeuristicType type, int bias, unsigned priority, LitSpan condition); + } + SECTION("backend-project") { + ctl.configuration()["solve.project"] = "1"; + auto backend = ctl.backend(); + atom_t a = backend.add_atom(), b = backend.add_atom(); + backend.rule(true, {a, b}, {}); + backend.project({a}); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{},{}})); + } + SECTION("backend-external") { + auto backend = ctl.backend(); + atom_t a = backend.add_atom(); + backend.external(a, ExternalType::Free); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{},{}})); + backend.external(a, ExternalType::Release); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{}})); + } + SECTION("backend-acyc") { + auto backend = ctl.backend(); + atom_t a = backend.add_atom(), b = backend.add_atom(); + backend.rule(true, {a, b}, {}); + backend.acyc_edge(1, 2, {literal_t(a)}); + backend.acyc_edge(2, 1, {literal_t(b)}); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{},{},{}})); + } + SECTION("backend-weight-rule") { + auto backend = ctl.backend(); + atom_t a = backend.add_atom(), b = backend.add_atom(); + backend.rule(true, {a, b}, {}); + backend.weight_rule(false, {}, 1, {{literal_t(a),1}, {literal_t(b),1}}); + ctl.solve(MCB(models)); + REQUIRE(models == (ModelVec{{}})); + } + SECTION("optimize") { + ctl.add("base", {}, "2 {a; b; c; d}.\n" + ":- a, b.\n" + ":- a, c.\n" + "#minimize {2@2:a; 3@2:b; 4@2:c; 5@2:d}.\n" + "#minimize {3@1:a; 4@1:b; 5@1:c; 2@1:d}.\n"); + ctl.ground({{"base", {}}}); + SymbolVector model; + CostVector optimum; + REQUIRE(ctl.solve([&optimum, &model](Model m) { + model = m.symbols(); + optimum = m.cost(); + return true; + }).is_satisfiable()); + REQUIRE(model == SymbolVector({ Id("a"), Id("d") })); + REQUIRE(optimum == (CostVector{7,5})); + REQUIRE(messages.empty()); + } +#if defined(WITH_THREADS) && WITH_THREADS == 1 + SECTION("async") { + ctl.add("base", {}, "{a}."); + ctl.ground({{"base", {}}}); + auto async = ctl.solve_async(MCB(models)); + REQUIRE(async.get().is_satisfiable()); + REQUIRE(models == ModelVec({{},{Id("a")}})); + REQUIRE(messages.empty()); + } +#endif + SECTION("model") { + ctl.add("base", {}, "a. $x $= 1. #show b."); + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve([](Model m) { + REQUIRE(m.type() == ModelType::StableModel); + REQUIRE(m.symbols(ShowType::Atoms) == (SymbolVector{Id("a")})); + REQUIRE(m.symbols(ShowType::Terms) == (SymbolVector{Id("b")})); + REQUIRE(m.symbols(ShowType::CSP) == (SymbolVector{Function("$", {Id("x"), Number(1)})})); + REQUIRE(m.symbols(ShowType::Shown) == (SymbolVector{Function("$", {Id("x"), Number(1)}), Id("a"), Id("b")})); + REQUIRE(m.symbols(ShowType::Atoms | ShowType::Complement).size() == 0); + REQUIRE( m.contains(Id("a"))); + REQUIRE(!m.contains(Id("b"))); + return true; + }).is_satisfiable()); + REQUIRE(messages.empty()); + } + SECTION("model-add-clause") { + ctl.add("base", {}, "1{a;b}1."); + ctl.ground({{"base", {}}}); + int n = 0; + auto ret = ctl.solve([&n](Model m) { + REQUIRE(m.type() == ModelType::StableModel); + REQUIRE(m.context().thread_id() == 0); + ++n; + char const *name = m.contains(Id("a")) ? "b" : "a"; + m.context().add_clause({{Id(name), false}}); + return true; + }); + REQUIRE(ret.is_satisfiable()); + REQUIRE(n == 1); + REQUIRE(messages.empty()); + } + SECTION("model-cautious") { + ctl.configuration()["solve.enum_mode"] = "cautious"; + ctl.add("base", {}, "a."); + ctl.ground({{"base", {}}}); + int n = 0; + auto ret = ctl.solve([&n](Model m) { + REQUIRE(m.type() == ModelType::CautiousConsequences); + REQUIRE(m.context().thread_id() == 0); + ++n; + return true; + }); + REQUIRE(ret.is_satisfiable()); + REQUIRE(n == 1); + REQUIRE(messages.empty()); + } + SECTION("model-cost") { + ctl.configuration()["solve.opt_mode"] = "optN"; + ctl.add("base", {}, "{a}. #minimize { 1:a }."); + ctl.ground({{"base", {}}}); + int n = 0; + auto ret = ctl.solve([&n](Model m) { + REQUIRE(m.type() == ModelType::StableModel); + REQUIRE(m.context().thread_id() == 0); + if (m.optimality_proven()) { + REQUIRE(m.number() == 1); + REQUIRE(m.cost() == (CostVector{0})); + ++n; + } + return true; + }); + REQUIRE(ret.is_satisfiable()); + REQUIRE(n == 1); + REQUIRE(messages.empty()); + } + SECTION("assumptions") { + ctl.add("base", {}, "{a;b;c}."); + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve(MCB(models), {{Id("a"), false}, {Id("b"), true}}).is_satisfiable()); + REQUIRE(models == (ModelVec{{Id("a")}, {Id("a"), Id("c")}})); + REQUIRE(messages.empty()); + } + SECTION("theory-atoms") { + char const *theory = + "#theory t {\n" + " group {\n" + " + : 4, unary;\n" + " - : 4, unary;\n" + " ^ : 3, binary, right;\n" + " * : 2, binary, left;\n" + " + : 1, binary, left;\n" + " - : 1, binary, left\n" + " };\n" + " &a/0 : group, head;\n" + " &b/0 : group, {=}, group, directive\n" + "}.\n" + "{p; q}.\n" + "&a { 1,[1,a],f(1) : p, q }.\n"; + ctl.add("base", {}, theory); + ctl.ground({{"base", {}}}); + auto atoms = ctl.theory_atoms(); + REQUIRE(atoms.size() == 1); + int count = 0; + for (auto atom : atoms) { + ++count; + REQUIRE(atom.to_string() == "&a{1,[1,a],f(1): p,q}"); + REQUIRE(!atom.has_guard()); + REQUIRE(atom.term().type() == TheoryTermType::Symbol); + REQUIRE(atom.term().name() == S("a")); + REQUIRE(atom.elements().size() == 1); + REQUIRE(atom.literal() > 0); + for (auto elem : atom.elements()) { + ++count; + REQUIRE(elem.condition_id() > 0); + REQUIRE(elem.tuple().size() == 3); + auto it = elem.tuple().begin(); + REQUIRE(it->type() == TheoryTermType::Number); + REQUIRE(it->number() == 1); + ++it; + REQUIRE(it->type() == TheoryTermType::List); + REQUIRE(it->arguments().size() == 2); + auto jt = it->arguments().begin(); + REQUIRE(jt->type() == TheoryTermType::Number); + REQUIRE((*++jt).type() == TheoryTermType::Symbol); + ++it; + REQUIRE(it->type() == TheoryTermType::Function); + REQUIRE(it->name() == S("f")); + REQUIRE(elem.condition().size() == 2); + auto kt = elem.condition().begin(); + REQUIRE(*kt++ > 0); + REQUIRE(*kt++ > 0); + REQUIRE(kt == elem.condition().end()); + } + } + REQUIRE(count == 2); + REQUIRE(ctl.solve(MCB(models), {{Id("p"), false}, {Id("q"), false}}).is_satisfiable()); + REQUIRE(models == ModelVec({{Id("p"), Id("q")}})); + REQUIRE(atoms.size() == 0); + ctl.add("next", {}, "&b {} = 42."); + ctl.ground({{"next", {}}}); + REQUIRE(atoms.size() == 1); + auto atom = *atoms.begin(); + REQUIRE(atom.term().name() == S("b")); + REQUIRE(atom.has_guard()); + REQUIRE(atom.guard().first == S("=")); + REQUIRE(atom.guard().second.number() == 42); + REQUIRE(atom.literal() == 0); + } + SECTION("symbolic atoms") { + ctl.add("base", {}, "p(1). {p(2)}. #external p(3). q."); + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(messages.empty()); + auto atoms = ctl.symbolic_atoms(); + Symbol p1 = Function("p", {Number(1)}), p2 = Function("p", {Number(2)}), p3 = Function("p", {Number(3)}), q = Id("q"); + REQUIRE( atoms.find(p1)->is_fact()); REQUIRE(!atoms.find(p1)->is_external()); + REQUIRE(!atoms.find(p2)->is_fact()); REQUIRE(!atoms.find(p2)->is_external()); + REQUIRE(!atoms.find(p3)->is_fact()); REQUIRE( atoms.find(p3)->is_external()); + REQUIRE(atoms.length() == 4); + SymbolVector symbols; + for (auto atom : atoms) { symbols.emplace_back(atom.symbol()); } + std::sort(symbols.begin(), symbols.end()); + REQUIRE(symbols == SymbolVector({q, p1, p2, p3})); + symbols.clear(); + for (auto it = atoms.begin(Signature("p", 1)); it; ++it) { symbols.emplace_back(it->symbol()); } + std::sort(symbols.begin(), symbols.end()); + REQUIRE(symbols == SymbolVector({p1, p2, p3})); + } + SECTION("incremental") { + ctl.add("base", {}, "#external query(0)."); + ctl.add("acid", {"k"}, "#external query(k)."); + ctl.ground({{"base", {}}}); + ctl.assign_external(Function("query", {Number(0)}), TruthValue::True); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models == (ModelVec{{Function("query", {Number(0)})}})); + REQUIRE(messages.empty()); + + ctl.ground({{"acid", {Number(1)}}}); + ctl.release_external(Function("query", {Number(0)})); + ctl.assign_external(Function("query", {Number(1)}), TruthValue::Free); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models == (ModelVec{{}, {Function("query", {Number(1)})}})); + REQUIRE(messages.empty()); + } + SECTION("solve_iter") { + static int n = 0; + if (++n < 3) { // workaround for some bug with catch + ctl.add("base", {}, "a."); + ctl.ground({{"base", {}}}); + { + auto iter = ctl.solve_iteratively(); + MCB mcb(models); + SECTION("c++") { for (auto m : iter) { mcb(m); }; } + SECTION("java") { while (Model m = iter.next()) { mcb(m); }; } + REQUIRE(models == ModelVec{{Id("a")}}); + REQUIRE(iter.get().is_satisfiable()); + } + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models == ModelVec{{Id("a")}}); + REQUIRE(messages.empty()); + } + } + SECTION("logging") { + ctl.add("base", {}, "a(1+a)."); + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models == ModelVec{{}}); + REQUIRE(messages == MessageVec({{WarningCode::OperationUndefined, ":1:3-6: info: operation undefined:\n (1+a)\n"}})); + } + SECTION("use_enumeration_assumption") { + ctl.add("base", {}, "{p;q}."); + ctl.ground({{"base", {}}}); + ctl.use_enumeration_assumption(false); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() == 4); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() <= 4); + } + SECTION("use_enumeration_assumption") { + ctl.add("base", {}, "{p;q}."); + ctl.ground({{"base", {}}}); + ctl.use_enumeration_assumption(false); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() == 4); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() <= 4); + } + SECTION("cleanup") { + ctl.add("base", {}, "{a}. :- a."); + ctl.ground({{"base", {}}}); + auto dom = ctl.symbolic_atoms(); + REQUIRE(dom.find(Id("a")) != dom.end()); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() == 1); + ctl.cleanup(); + REQUIRE(dom.find(Id("a")) == dom.end()); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models.size() == 1); + } + SECTION("const") { + ctl.add("base", {}, "#const a=10."); + REQUIRE(ctl.has_const("a")); + REQUIRE(!ctl.has_const("b")); + REQUIRE(ctl.get_const("a") == Number(10)); + REQUIRE(ctl.get_const("b") == Id("b")); + } +#if defined(WITH_THREADS) && WITH_THREADS == 1 + SECTION("async and cancel") { + static int n = 0; + if (++n < 3) { // workaround for some bug with catch + ctl.add("pigeon", {"p", "h"}, "1 {p(P,H) : P=1..p}1 :- H=1..h." + "1 {p(P,H) : H=1..h}1 :- P=1..p."); + ctl.ground({{"pigeon", {Number(21), Number(20)}}}); + int fcalled = 0; + SolveResult fret; + FinishCallback fh = [&fret, &fcalled](SolveResult ret) { ++fcalled; fret = ret; }; + auto async = ctl.solve_async(nullptr, fh); + REQUIRE(!async.wait(0.01)); + SECTION("interrupt") { ctl.interrupt(); } + SECTION("cancel") { async.cancel(); } + auto ret = async.get(); + REQUIRE((ret.is_unknown() && ret.is_interrupted())); + REQUIRE(fcalled == 1); + REQUIRE(fret == ret); + } + } +#endif + SECTION("ground callback") { + ctl.add("base", {}, "a(@f(X)):- X=1..2. b(@f())."); + ctl.ground({{"base", {}}}, [&messages](Location loc, char const *name, SymbolSpan args, SymbolSpanCallback report) { + if (strcmp(name, "f") == 0 && args.size() == 1) { + Symbol front = *args.begin(); + report({Number(front.number() + 1), Number(front.number() + 10)}); + report({Number(front.number() + 20)}); + } + else { + std::ostringstream oss; + oss << "invalid call: " << name << "/" << args.size() << " at " << loc; + messages.emplace_back(WarningCode::OperationUndefined, oss.str()); + } + }); + REQUIRE(ctl.solve(MCB(models)).is_satisfiable()); + REQUIRE(models == ModelVec({{Function("a", {Number(2)}), Function("a", {Number(3)}), Function("a", {Number(11)}), Function("a", {Number(12)}), Function("a", {Number(21)}), Function("a", {Number(22)})}})); + REQUIRE(messages == MessageVec({{WarningCode::OperationUndefined, "invalid call: f/0 at :1:22-26"}})); + } + SECTION("ground callback fail") { + ctl.add("base", {}, "a(@f())."); + REQUIRE_THROWS_AS(ctl.ground({{"base", {}}}, [](Location, char const *, SymbolSpan, SymbolSpanCallback) { throw std::runtime_error("fail"); }), std::runtime_error); + } + SECTION("ground program observer") { + std::vector trail; + Observer obs(trail); + ctl.register_observer(obs); + ctl.add("base", {}, "a :- not a."); + ctl.ground({{"base", {}}}); + REQUIRE(ctl.solve(MCB(models)).is_unsatisfiable()); + REQUIRE(models == ModelVec({})); + REQUIRE(trail == std::vector({"IP: incremental", "BS", "R: 1:-~1", "ES"})); + } + } +} + +} } // namespace Test Clingo diff --git a/libclingo/tests/main.cc b/libclingo/tests/main.cc new file mode 100644 index 0000000..6a9d9b1 --- /dev/null +++ b/libclingo/tests/main.cc @@ -0,0 +1,22 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/libclingo/tests/propagator.cc b/libclingo/tests/propagator.cc new file mode 100644 index 0000000..2740374 --- /dev/null +++ b/libclingo/tests/propagator.cc @@ -0,0 +1,643 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests.hh" +#include +#include +#include +#include + +#include + +namespace Clingo { namespace Test { + +template +std::ostream &operator<<(std::ostream &out, std::unordered_map const &map); +template +std::ostream &operator<<(std::ostream &out, std::vector const &vec); +template +std::ostream &operator<<(std::ostream &out, std::pair const &pair); + +template +std::ostream &operator<<(std::ostream &out, std::vector const &vec) { + out << "{"; + for (auto &x : vec) { out << " " << x; } + out << " }"; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::unordered_map const &map) { + using T = std::pair; + std::vector vec; + vec.assign(map.begin(), map.end()); + std::sort(vec.begin(), vec.end(), [](T const &a, T const &b) { return a.first < b.first; }); + out << vec; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::pair const &pair) { + out << "( " << pair.first << " " << pair.second << " )"; + return out; +} + +class SequenceMiningPropagator : public Propagator { +private: + // {{{2 data + + struct TrailItem { + TrailItem(uint32_t dl, int si) + : decision_level(dl) + , stack_index(si) { } + uint32_t decision_level; + int stack_index; + }; + struct PatternItem { + PatternItem() + : PatternItem(0, 0) { } + PatternItem(int lit, int idx) + : literal(lit) + , item_index(idx) { } + operator bool() const { return literal != 0; } + literal_t literal; + int item_index; + }; + enum class IndexType { SequenceIndex, PatternIndex }; + class StackItem { + public: + StackItem(IndexType type, int idx) + : pattern_or_sequence_index_(type == IndexType::PatternIndex ? idx : -idx - 1) { } + IndexType type() const { return pattern_or_sequence_index_ >= 0 ? IndexType::PatternIndex : IndexType::SequenceIndex; } + int pattern_index() const { return pattern_or_sequence_index_; } + int sequence_index() const { return -pattern_or_sequence_index_ - 1; } + private: + int pattern_or_sequence_index_; + }; + struct State { + State(int pat_len, int seq_len) { + pattern.resize(pat_len, {0, 0}); + seq_active.resize(seq_len, true); + } + std::vector seq_active; + std::vector stack; + std::vector trail; + std::vector pattern; + int pattern_assigned = 0; + }; + struct SequenceAtoms { + SequenceAtoms() + : literal(0) { } + int literal; + std::vector items; + friend std::ostream &operator<<(std::ostream &out, SequenceAtoms const &a) { + out << "(" << a.literal << " " << a.items << ")"; + return out; + } + }; + struct PatternAtom { + PatternAtom(int pidx, int iidx) + : pattern_index(pidx) + , item_index(iidx) { } + int pattern_index; + int item_index; + friend std::ostream &operator<<(std::ostream &out, PatternAtom const &a) { + out << "(" << a.pattern_index << " " << a.item_index << ")"; + return out; + } + }; + + std::vector states_; + std::vector sequence_atoms_; + std::unordered_map> pattern_atoms_; + std::vector> occurrence_list_; + std::unordered_map item_map_; + int pattern_length_ = 0; + + // {{{2 initialization + + template + void reserve(T &vec, size_t s, typename T::value_type v = typename T::value_type()) { + if (s >= vec.size()) { vec.resize(s + 1, v); } + } + + int map_item(std::string &&item) { + auto &ret = *item_map_.emplace(std::move(item), item_map_.size()).first; + return ret.second; + } + + void add_sequence_atom(PropagateInit &init, int sid, TheoryAtom const &atom) { + reserve(sequence_atoms_, sid); + assert(sequence_atoms_[sid].literal == 0 && sequence_atoms_[sid].items.empty()); + sequence_atoms_[sid].literal = init.solver_literal(atom.literal()); + for (auto elem : atom.elements()) { + int index = elem.tuple()[0].number(); + assert(index >= 0); + int item = map_item(elem.tuple()[1].to_string()); + reserve(sequence_atoms_[sid].items, index, -1); + sequence_atoms_[sid].items[index] = item; + } + } + + void add_pattern_atoms(PropagateInit &init, TheoryAtom const &atom) { + for (auto elem : atom.elements()) { + literal_t lit = init.solver_literal(elem.condition_id()); + auto args = elem.tuple(); + int index = args[0].number(); + assert(index >= 0); + int item = map_item(args[1].to_string()); + auto ret = pattern_atoms_.emplace(lit, std::vector{}); + if (ret.second) { init.add_watch(lit); } + ret.first->second.emplace_back(index, item); + pattern_length_ = std::max(pattern_length_, index + 1); + } + } + + void initialize_occurrence_lists() { + for (auto &item : item_map_) { + occurrence_list_.emplace_back(); + } + int sid = 0; + std::unordered_set seen; + for (auto &seq : sequence_atoms_) { + for (auto &item : seq.items) { + assert(item >= 0); + if (seen.emplace(item).second) { occurrence_list_[item].emplace_back(sid); } + } + seen.clear(); + ++sid; + } + } + + void initialize_states(PropagateInit &init) { + for (int i = 0; i < init.number_of_threads(); ++i) { states_.emplace_back(pattern_length_, sequence_atoms_.size()); } + } + + // {{{2 propagation + + bool propagate_sequence_literal(State &state, PropagateControl &ctl, int sid, literal_t lit) { + state.seq_active[sid] = false; + state.stack.emplace_back(IndexType::SequenceIndex, sid); + if (!ctl.assignment().is_true(lit)) { + std::vector klaus; + klaus.reserve(1 + pattern_length_); + klaus.emplace_back(lit); + for (auto &pat : state.pattern) { + if (pat.literal != 0) { klaus.emplace_back(-pat.literal); } + } + return ctl.add_clause(klaus) && ctl.propagate(); + } + return true; + } + + bool propagate_sequence(State &state, PropagateControl &ctl, int sid, SequenceAtoms &atoms) { + if (state.pattern_assigned < pattern_length_ && ctl.assignment().is_false(atoms.literal)) { + return true; + } + auto it = atoms.items.begin(), ie = atoms.items.end(); + for (auto &pat : state.pattern) { + while (true) { + if (it == ie) { return propagate_sequence_literal(state, ctl, sid, -atoms.literal); } + ++it; + if (pat.literal == 0 || *(it-1) == pat.item_index) { break; } + } + } + return state.pattern_assigned < pattern_length_ || propagate_sequence_literal(state, ctl, sid, atoms.literal); + } + + // }}}2 +public: + SequenceMiningPropagator() { } + + void init(PropagateInit &init) override { + for (auto atom : init.theory_atoms()) { + auto term = atom.term(); + auto args = term.arguments(); + if (std::strcmp(term.name(), "seq") == 0 && args.size() == 1) { add_sequence_atom(init, args[0].number(), atom); } + else if (std::strcmp(term.name(), "pat") == 0 && args.empty()) { add_pattern_atoms(init, atom); } + } + initialize_occurrence_lists(); + initialize_states(init); + } + + void propagate(PropagateControl &ctl, LiteralSpan changes) override { + auto &state = states_[ctl.thread_id()]; + uint32_t dl = ctl.assignment().decision_level(); + if (state.trail.size() == 0 || state.trail.back().decision_level < dl) { + state.trail.emplace_back(dl, state.stack.size()); + } + for (auto &lit : changes) { + for (auto &pat_atom : pattern_atoms_[lit]) { + auto &pat = state.pattern[pat_atom.pattern_index]; + if (pat) { + // this case should not occur if the pattern is generated properly + auto old = pat.literal; + assert(ctl.assignment().is_true(old)); + ctl.add_clause({-lit, -old}) && ctl.propagate(); + return; + + } + else { + state.stack.emplace_back(IndexType::PatternIndex, pat_atom.pattern_index); + ++state.pattern_assigned; + pat = {lit, pat_atom.item_index}; + for (auto &sid : occurrence_list_[pat_atom.item_index]) { + if (state.seq_active[sid] && !propagate_sequence(state, ctl, sid, sequence_atoms_[sid])) { + return; + } + } + } + } + } + } + + void undo(PropagateControl const &ctl , LiteralSpan) override { + auto &state = states_[ctl.thread_id()]; + int sid = state.trail.back().stack_index; + auto ib = state.stack.begin() + sid, ie = state.stack.end(); + for (auto it = ib; it != ie; ++it) { + if (it->type() == IndexType::PatternIndex) { + state.pattern[it->pattern_index()] = {}; + --state.pattern_assigned; + } + else { + state.seq_active[it->sequence_index()] = true; + } + } + state.stack.erase(ib, ie); + state.trail.pop_back(); + } + +}; + +constexpr char const * const sequence_mining_encoding = R"( +#show pat/2. + +#theory seq { + term { }; + &seq/1 : term, body; + &pat/0 : term, directive +}. + +1 { pat(P,I) : seq(_,_,I) } 1 :- P = 0..(n-1). + +&pat { P,I : pat(P,I) }. +sup(U) :- &seq(U) { P,I : seq(U,P,I) }, seq(U,_,_). + +#maximize { 1,U : sup(U) }. + +% abaca +seq(0,0,a). +seq(0,1,b). +seq(0,2,a). +seq(0,3,c). +seq(0,4,a). + +% abdca +seq(1,0,a). +seq(1,1,b). +seq(1,2,d). +seq(1,3,c). +seq(1,4,a). + +% aedca +seq(2,0,a). +seq(2,1,e). +seq(2,2,d). +seq(2,3,c). +seq(2,4,a). +)"; + +class PigeonPropagator : public Propagator { +public: + void init(PropagateInit &init) override { + unsigned nHole = 0, nPig = 0, nWatch = 0, p, h; + state_.clear(); + p2h_[0] = 0; + for (auto it = init.symbolic_atoms().begin(Signature("place", 2)), ie = init.symbolic_atoms().end(); it != ie; ++it) { + literal_t lit = init.solver_literal(it->literal()); + p = it->symbol().arguments()[0].number(); + h = it->symbol().arguments()[1].number(); + p2h_[lit] = h; + init.add_watch(lit); + nHole = std::max(h, nHole); + nPig = std::max(p, nPig); + ++nWatch; + } + assert(p2h_[0] == 0); + for (unsigned i = 0, end = init.number_of_threads(); i != end; ++i) { + state_.emplace_back(nHole + 1, 0); + assert(state_.back().size() == nHole + 1); + } + } + void propagate(PropagateControl &ctl, LiteralSpan changes) override { + assert(ctl.thread_id() < state_.size()); + Hole2Lit& holes = state_[ctl.thread_id()]; + for (literal_t lit : changes) { + literal_t& prev = holes[ p2h_[lit] ]; + if (prev == 0) { prev = lit; } + else { + if (!ctl.add_clause({-lit, -prev}) || !ctl.propagate()) { + return; + } + assert(false); + } + } + } + void undo(PropagateControl const &ctl, LiteralSpan undo) override { + assert(ctl.thread_id() < state_.size()); + Hole2Lit& holes = state_[ctl.thread_id()]; + for (literal_t lit : undo) { + unsigned hole = p2h_[lit]; + if (holes[hole] == lit) { + holes[hole] = 0; + } + } + } +private: + using Lit2Hole = std::unordered_map; + using Hole2Lit = std::vector; + using State = std::vector; + + Lit2Hole p2h_; + State state_; +}; + +class TestAssignment : public Propagator { +public: + void init(PropagateInit &init) override { + a_ = init.solver_literal(init.symbolic_atoms().find(Id("a"))->literal()); + b_ = init.solver_literal(init.symbolic_atoms().find(Id("b"))->literal()); + c_ = init.solver_literal(init.symbolic_atoms().find(Id("c"))->literal()); + init.add_watch(a_); + init.add_watch(b_); + } + void propagate(PropagateControl &ctl, LiteralSpan changes) override { + auto ass = ctl.assignment(); + count_+= changes.size(); + REQUIRE(ass.is_fixed(c_)); + REQUIRE(!ass.is_fixed(a_)); + REQUIRE(!ass.is_fixed(b_)); + REQUIRE(!ass.has_conflict()); + REQUIRE(ass.has_literal(a_)); + REQUIRE(ass.has_literal(b_)); + REQUIRE(!ass.has_literal(1000)); + auto decision = ass.decision(ass.decision_level()); + REQUIRE(ass.level(decision) == ass.decision_level()); + if (count_ == 1) { + int a = changes[0]; + REQUIRE(changes.size() == 1); + REQUIRE(!ass.is_fixed(a_)); + REQUIRE(ass.is_true(a)); + REQUIRE(ass.truth_value(a) == TruthValue::True); + REQUIRE((ass.is_true(a_) ^ ass.is_true(b_))); + REQUIRE(ass.level(a) == ass.decision_level()); + } + if (count_ == 2) { + REQUIRE(!ass.is_fixed(a_)); + REQUIRE(!ass.is_fixed(b_)); + REQUIRE(ass.is_true(a_)); + REQUIRE(ass.is_true(b_)); + } + } + void undo(PropagateControl const &, LiteralSpan undo) override { + count_-= undo.size(); + } +private: + literal_t a_; + literal_t b_; + literal_t c_; + int count_ = 0; +}; + +class TestAddClause : public Propagator { +public: + void init(PropagateInit &init) override { + a_ = init.solver_literal(init.symbolic_atoms().find(Id("a"))->literal()); + b_ = init.solver_literal(init.symbolic_atoms().find(Id("b"))->literal()); + init.add_watch(a_); + init.add_watch(b_); + } + void propagate(PropagateControl &ctl, LiteralSpan changes) override { + count_+= changes.size(); + REQUIRE_FALSE((enable && count_ == 2 && ctl.add_clause({-a_, -b_}, type) && ctl.propagate())); + } + void undo(PropagateControl const &, LiteralSpan undo) override { + count_-= undo.size(); + } +public: + ClauseType type = ClauseType::Learnt; + bool enable = true; +private: + literal_t a_; + literal_t b_; + int count_ = 0; +}; + +class TestException : public Propagator { +public: + void check(PropagateControl &) override { + throw std::runtime_error("the answer is 42"); + } +}; + +TEST_CASE("propagator", "[clingo][propagator]") { + MessageVec messages; + ModelVec models; + Logger logger = [&messages](WarningCode code, char const *msg) { messages.emplace_back(code, msg); }; + Control ctl{{"0"}, logger, 20}; + SECTION("pigeon") { + PigeonPropagator p; + ctl.register_propagator(p); + ctl.add("pigeon", {"h", "p"}, "1 { place(P,H) : H = 1..h } 1 :- P = 1..p."); + auto place = [](int p, int h) { return Function("place", {Number(p), Number(h)}); }; + SECTION("unsat") { + ctl.ground({{"pigeon", {Number(5), Number(6)}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models.empty()); + } + SECTION("sat") { + ctl.ground({{"pigeon", {Number(2), Number(2)}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models == ModelVec({{place(1,1), place(2,2)}, {place(1,2), place(2,1)}})); + } + } + SECTION("assignment") { + TestAssignment p; + ctl.register_propagator(p, false); + ctl.add("base", {}, "{a; b}. c."); + ctl.ground({{"base", {}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models.size() == 4); + } + SECTION("exception") { + TestException p; + ctl.register_propagator(p, false); + ctl.add("base", {}, "{a}."); + ctl.ground({{"base", {}}}, nullptr); + try { + ctl.solve(MCB(models)); + FAIL("solve must throw"); + } + catch (std::runtime_error const &e) { REQUIRE(e.what() == S("the answer is 42")); } + } +#if defined(WITH_THREADS) && WITH_THREADS == 1 + SECTION("exception-t2") { + ctl.configuration()["solve.parallel_mode"] = "2"; + TestException p; + ctl.register_propagator(p, false); + ctl.add("base", {}, "{a}."); + ctl.ground({{"base", {}}}, nullptr); + try { + ctl.solve(MCB(models)); + FAIL("solve must throw"); + } + catch (std::runtime_error const &e) { + // NOTE: in the multithreaded case a runtime error is thrown after the last thread died + REQUIRE(e.what() == S("RUNTIME ERROR!")); + } + } +#endif + SECTION("add_clause") { + TestAddClause p; + ctl.register_propagator(p, false); + SECTION("learnt") { + p.type = ClauseType::Learnt; + ctl.add("base", {}, "{a; b}."); + ctl.ground({{"base", {}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models.size() == 3); + p.enable = false; + ctl.solve(MCB(models)); + REQUIRE(models.size() >= 3); + } + SECTION("static") { + p.type = ClauseType::Static; + ctl.add("base", {}, "{a; b}."); + ctl.ground({{"base", {}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models.size() == 3); + p.enable = false; + ctl.solve(MCB(models)); + REQUIRE(models.size() == 3); + } + SECTION("volatile") { + p.type = ClauseType::Volatile; + ctl.add("base", {}, "{a; b}."); + ctl.ground({{"base", {}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models.size() == 3); + p.enable = false; + ctl.solve(MCB(models)); + REQUIRE(models.size() == 4); + } + SECTION("volatile static") { + p.type = ClauseType::VolatileStatic; + ctl.add("base", {}, "{a; b}."); + ctl.ground({{"base", {}}}, nullptr); + ctl.solve(MCB(models)); + REQUIRE(models.size() == 3); + p.enable = false; + ctl.solve(MCB(models)); + REQUIRE(models.size() == 4); + } + } +} + +TEST_CASE("propgator-sequence-mining", "[clingo][propagator]") { + MessageVec messages; + ModelVec models; + Logger logger = [&messages](WarningCode code, char const *msg) { messages.emplace_back(code, msg); }; +#if defined(WITH_THREADS) && WITH_THREADS == 1 + Control ctl{{"-t14"}, logger, 20}; +#else + Control ctl{{}, logger, 20}; +#endif + SECTION("sequence mining") { + ctl.configuration()["solve"]["opt_mode"] = "optN"; + SequenceMiningPropagator p; + ctl.register_propagator(p, false); + ctl.add("base", {"n"}, sequence_mining_encoding); + int n = 5; + ctl.ground({{"base", {Number(n)}}}, nullptr); + // NOTE: maps and sets are not necessary + // this also works with vectors + sorting avoiding node based containers + // :- not sup(U), seq(U,_,_), n == 0. + if (n == 0) { + std::map> grouped; + for (auto it = ctl.symbolic_atoms().begin({"seq", 3}), ie = ctl.symbolic_atoms().end(); it != ie; ++it) { + grouped[it->symbol().arguments().front()].emplace_back(it->literal()); + } + for (auto &elem : grouped) { + auto atom = ctl.backend().add_atom(); + for (auto &lit : elem.second) { + ctl.backend().rule(false, {atom}, {lit}); + } + ctl.backend().rule(false, {}, {-ctl.symbolic_atoms()[Function("sup", {elem.first})].literal(), literal_t(atom)}); + } + } + // :- sup(U), pat(_,I), not seq(U,_,I). + std::map> grouped_pat; + std::unordered_set grouped_seq; + for (auto it = ctl.symbolic_atoms().begin({"pat", 2}), ie = ctl.symbolic_atoms().end(); it != ie; ++it) { + grouped_pat[it->symbol().arguments()[1]].emplace_back(it->literal()); + } + for (auto it = ctl.symbolic_atoms().begin({"seq", 3}), ie = ctl.symbolic_atoms().end(); it != ie; ++it) { + grouped_seq.emplace(Function("", {it->symbol().arguments()[0], it->symbol().arguments()[2]})); + } + std::map projected_pat; + for (auto &pat : grouped_pat) { + auto atom = ctl.backend().add_atom(); + for (auto &lit : pat.second) { + ctl.backend().rule(false, {atom}, {lit}); + } + projected_pat.emplace(pat.first, atom); + } + for (auto it = ctl.symbolic_atoms().begin({"sup", 1}), ie = ctl.symbolic_atoms().end(); it != ie; ++it) { + for (auto &pat : projected_pat) { + if (grouped_seq.find(Function("", {it->symbol().arguments().front(), pat.first})) == grouped_seq.end()) { + ctl.backend().rule(false, {}, {it->literal(), literal_t(pat.second)}); + } + } + } + int64_t optimum = std::numeric_limits::max(); + ctl.solve([&models, &optimum](Model m) { + int64_t opt = m.cost()[0]; + if (opt == optimum) { + models.emplace_back(); + for (auto sym : m.symbols(ShowType::Shown)) { + models.back().emplace_back(sym); + } + std::sort(models.back().begin(), models.back().end()); + } + else { optimum = opt; } + return true; + }); + std::sort(models.begin(), models.end()); + auto pat = [](int num, char const *item) { return Function("pat", {Number(num), Id(item)}); }; + ModelVec solution = { + { pat(0,"a"), pat(1,"b"), pat(2,"a"), pat(3,"c"), pat(4,"a") }, + { pat(0,"a"), pat(1,"b"), pat(2,"d"), pat(3,"c"), pat(4,"a") }, + { pat(0,"a"), pat(1,"e"), pat(2,"d"), pat(3,"c"), pat(4,"a") } }; + REQUIRE(models == solution); + } +} + +} } // namespace Test Clingo diff --git a/libclingo/tests/symbol.cc b/libclingo/tests/symbol.cc new file mode 100644 index 0000000..00f06bf --- /dev/null +++ b/libclingo/tests/symbol.cc @@ -0,0 +1,106 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests.hh" +#include +#include + +namespace Clingo { namespace Test { + +TEST_CASE("symbol", "[clingo]") { + SECTION("signature") { + Signature a("a", 2, false); + Signature b("a", 2, false); + Signature c("a", 2, true); + REQUIRE(a.name() == S("a")); + REQUIRE(a.arity() == 2); + REQUIRE(a.negative()); + REQUIRE(!a.positive()); + REQUIRE(b == a); + REQUIRE(c != a); + REQUIRE(c < a); + REQUIRE(c <= a); + REQUIRE(a <= b); + REQUIRE_FALSE(a <= c); + REQUIRE(a > c); + REQUIRE(a >= c); + REQUIRE(a >= b); + REQUIRE_FALSE(c >= a); + REQUIRE(c.hash() != a.hash()); + REQUIRE(b.hash() == a.hash()); + } + SECTION("symbol") { + std::vector args; + // numbers + auto sym = Number(42); + REQUIRE(42 == sym.number()); + args.emplace_back(sym); + // inf + sym = Infimum(); + REQUIRE(SymbolType::Infimum == sym.type()); + args.emplace_back(sym); + // sup + sym = Supremum(); + REQUIRE(SymbolType::Supremum == sym.type()); + args.emplace_back(sym); + // str + sym = String("x"); + REQUIRE(S("x") == sym.string()); + args.emplace_back(sym); + // id + sym = Id("x", false); + REQUIRE(SymbolType::Function == sym.type()); + REQUIRE(sym.is_negative()); + REQUIRE(!sym.is_positive()); + REQUIRE(S("x") == sym.name()); + args.emplace_back(sym); + // fun + sym = Function("f", args); + REQUIRE(SymbolType::Function == sym.type()); + REQUIRE(!sym.is_negative()); + REQUIRE(S("f") == sym.name()); + REQUIRE("f(42,#inf,#sup,\"x\",-x)" == sym.to_string()); + REQUIRE((args.size() == sym.arguments().size() && std::equal(args.begin(), args.end(), sym.arguments().begin()))); + try { sym.number(); } + catch (std::exception const &e) { REQUIRE(e.what() == S("unexpected")); } + // comparison + auto a = Number(1), b = Number(2); + REQUIRE(a < b); + REQUIRE_FALSE(a < a); + REQUIRE_FALSE(b < a); + REQUIRE(b > a); + REQUIRE_FALSE(a > a); + REQUIRE_FALSE(a > b); + REQUIRE(a <= a); + REQUIRE(a <= b); + REQUIRE_FALSE(b <= a); + REQUIRE(a >= a); + REQUIRE(b >= a); + REQUIRE_FALSE(a >= b); + REQUIRE(a == a); + REQUIRE_FALSE(a == b); + REQUIRE(a != b); + REQUIRE_FALSE(a != a); + REQUIRE(a.hash() == a.hash()); + REQUIRE(a.hash() != b.hash()); + } +} + +} } // namespace Test Clingo diff --git a/libclingo/tests/tests.hh b/libclingo/tests/tests.hh new file mode 100644 index 0000000..f042a47 --- /dev/null +++ b/libclingo/tests/tests.hh @@ -0,0 +1,56 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "clingo.hh" +#include "catch.hpp" + +namespace Clingo { namespace Test { + +using S = std::string; +using ModelVec = std::vector; +using MessageVec = std::vector>; + +struct MCB { + MCB(ModelVec &models) : models(models) { + models.clear(); + } + bool operator()(Model m) { + models.emplace_back(); + for (auto sym : m.symbols(ShowType::Shown)) { + models.back().emplace_back(sym); + } + std::sort(models.back().begin(), models.back().end()); + return true; + } + ~MCB() { + std::sort(models.begin(), models.end()); + } + ModelVec ⊧ +}; + +class LCB { +public: + LCB(MessageVec &messages) : messages_(messages) { } + void operator()(WarningCode code, char const *msg) { messages_.emplace_back(code, msg); } +private: + MessageVec &messages_; +}; + +} } // namespace Test Clingo diff --git a/libclingo/tests/variant.cc b/libclingo/tests/variant.cc new file mode 100644 index 0000000..c4cace8 --- /dev/null +++ b/libclingo/tests/variant.cc @@ -0,0 +1,75 @@ +#include "tests.hh" +#include +#include + +namespace Clingo { namespace Test { + +using V = Variant>; + +struct D { + D(std::string &r) : r(r) { r = "not called"; } + void visit(int &x) { + r = std::to_string(x); + } + void visit(std::string &x) { + r = x; + } + void visit(std::unique_ptr &x) { + r = std::to_string(*x); + } + std::string &r; +}; + +struct DA { + int visit(int const &x, int y) { + return y + 1 + x; + } + int visit(std::string const &, int y) { + return y + 2; + } + int visit(std::unique_ptr const &, int y) { + return y + 3; + } +}; + +TEST_CASE("visitor", "[clingo]") { + V x{10}; + REQUIRE(x.is()); + REQUIRE(x.accept(DA(), 3) == 14); + REQUIRE(!x.is()); + REQUIRE(x.get() == 10); + std::string s = "s1"; + x = static_cast(s); + REQUIRE(x.get() == "s1"); + x = s; + REQUIRE(x.get() == "s1"); + x = std::move(s); + REQUIRE(x.get() == "s1"); + s = "s2"; + REQUIRE(V{s}.get() == "s2"); + REQUIRE(V{static_cast(s)}.get() == "s2"); + REQUIRE(V{std::move(s)}.get() == "s2"); + + V y = x; + REQUIRE(y.get() == "s1"); + x = y; + REQUIRE(x.get() == "s1"); + +#if (__clang__ || __GNUC__ >= 5) + std::string r; + y.accept(D(r)); + REQUIRE(r == "s1"); + x.accept(D(r)); + REQUIRE(r == "s1"); + REQUIRE(x.accept(DA(), 3) == 5); + + x = V::make>(nullptr); + REQUIRE(!x.get>()); + + x.swap(y); + REQUIRE(!y.get>()); + REQUIRE(x.get() == "s1"); +#endif +} + +} } // namespace Test Clingo diff --git a/libgringo/clingo.h b/libgringo/clingo.h new file mode 100644 index 0000000..0cbb98b --- /dev/null +++ b/libgringo/clingo.h @@ -0,0 +1,3254 @@ +// {{{ GPL License + +// This file is part of gringo---a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +//! @file clingo.h +//! Single header containing the whole clingo API. +//! +//! @author Roland Kaminski + +//! @mainpage Clingo C API +//! This API provides functions to ground and solve logic programs. +//! +//! The documentation is structured into different modules. +//! To get an overview, checkout the [Modules](modules.html) page. +//! To get started, take a look at the documentation of the @ref Control module. +//! +//! The source code of clingo is available on [github.com/potassco/clingo](https://github.com/potassco/clingo). +//! +//! For information about the syntax and semantics of the clingo language, +//! take a look the [Potassco Guide](http://sourceforge.net/projects/potassco/files/guide/). +//! +//! @note Each module comes with an example highlighting key functionality. +//! The example should be studied along with the module documentation. + +#ifndef CLINGO_H +#define CLINGO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#if defined _WIN32 || defined __CYGWIN__ +# define CLINGO_WIN +#endif +#ifdef CLINGO_WIN +# ifdef CLINGO_BUILD_LIBRARY +# define CLINGO_VISIBILITY_DEFAULT __declspec (dllexport) +# else +# define CLINGO_VISIBILITY_DEFAULT __declspec (dllimport) +# endif +# define CLINGO_VISIBILITY_PRIVATE +#else +# if __GNUC__ >= 4 +# define CLINGO_VISIBILITY_DEFAULT __attribute__ ((visibility ("default"))) +# define CLINGO_VISIBILITY_PRIVATE __attribute__ ((visibility ("hidden"))) +# else +# define CLINGO_VISIBILITY_DEFAULT +# define CLINGO_VISIBILITY_PRIVATE +# endif +#endif + +// {{{1 basic types and error/warning handling + +//! @example version.c +//! The example shows how to get version information. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! $ ./version +//! Hello, this is clingo version... +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup BasicTypes Basic Data Types and Functions +//! Data types and functions used throughout all modules and version information. +//! +//! For an example, see @ref version.c. + +//! @addtogroup BasicTypes +//! @{ + +//! Major version number. +#define CLINGO_VERSION_MAJOR 5 +//! Minor version number. +#define CLINGO_VERSION_MINOR 0 +//! Revision number. +#define CLINGO_VERSION_REVISION 0 +//! String representation of version. +#define CLINGO_VERSION #CLINGO_VERSION_MAJOR "." #CLINGO_VERSION_MINOR "." #CLINGO_VERSION_REVISION + +//! Signed integer type used for aspif and solver literals. +typedef int32_t clingo_literal_t; +//! Unsigned integer type used for aspif atoms. +typedef uint32_t clingo_atom_t; +//! Unsigned integer type used in various places. +typedef uint32_t clingo_id_t; +//! Signed integer type for weights in sum aggregates and minimize constraints. +typedef int32_t clingo_weight_t; + +//! Enumeration of error codes. +//! +//! @note Errors can only be recovered from if explicitly mentioned; most +//! functions do not provide strong exception guarantees. This means that in +//! case of errors associated objects cannot be used further. If such an +//! object has a free function, this function can and should still be called. +enum clingo_error { + clingo_error_success = 0, //!< successful API calls + clingo_error_runtime = 1, //!< errors only detectable at runtime like invalid input + clingo_error_logic = 2, //!< wrong usage of the clingo API + clingo_error_bad_alloc = 3, //!< memory could not be allocated + clingo_error_unknown = 4 //!< errors unrelated to clingo +}; +//! Corresponding type to ::clingo_error. +typedef int clingo_error_t; +//! Convert error code into string. +CLINGO_VISIBILITY_DEFAULT char const *clingo_error_string(clingo_error_t code); +//! Get the last error code set by a clingo API call. +//! @note Each thread has its own local error code. +//! @return error code +CLINGO_VISIBILITY_DEFAULT clingo_error_t clingo_error_code(); +//! Get the last error message set if an API call fails. +//! @note Each thread has its own local error message. +//! @return error message or NULL +CLINGO_VISIBILITY_DEFAULT char const *clingo_error_message(); +//! Set a custom error code and message in the active thread. +//! @param[in] code the error code +//! @param[in] message the error message +CLINGO_VISIBILITY_DEFAULT void clingo_set_error(clingo_error_t code, char const *message); + +//! Enumeration of warning codes. +enum clingo_warning { + clingo_warning_operation_undefined = 0, //!< undefined arithmetic operation or weight of aggregate + clingo_warning_runtime_error = 1, //!< to report multiple errors; a corresponding runtime error is raised later + clingo_warning_atom_undefined = 2, //!< undefined atom in program + clingo_warning_file_included = 3, //!< same file included multiple times + clingo_warning_variable_unbounded = 4, //!< CSP variable with unbounded domain + clingo_warning_global_variable = 5, //!< global variable in tuple of aggregate element + clingo_warning_other = 6, //!< other kinds of warnings +}; +//! Corresponding type to ::clingo_warning. +typedef int clingo_warning_t; +//! Convert warning code into string. +CLINGO_VISIBILITY_DEFAULT char const *clingo_warning_string(clingo_warning_t code); +//! Callback to intercept warning messages. +//! +//! @param[in] code associated warning code +//! @param[in] message warning message +//! @param[in] data user data for callback +//! +//! @see clingo_control_new() +//! @see clingo_parse_term() +//! @see clingo_parse_program() +typedef void clingo_logger_t(clingo_warning_t code, char const *message, void *data); + +//! Obtain the clingo version. +//! +//! @param[out] major major version number +//! @param[out] minor minor version number +//! @param[out] revision revision number +CLINGO_VISIBILITY_DEFAULT void clingo_version(int *major, int *minor, int *revision); + +//! Represents three-valued truth values. +enum clingo_truth_value { + clingo_truth_value_free = 0, //!< no truth value + clingo_truth_value_true = 1, //!< true + clingo_truth_value_false = 2 //!< false +}; +//! Corresponding type to ::clingo_truth_value. +typedef int clingo_truth_value_t; + +//! Represents a source code location marking its beginnig and end. +//! +//! @note Not all locations refer to physical files. +//! By convention, such locations use a name put in angular brackets as filename. +typedef struct clingo_location { + char const *begin_file; //!< the file where the location begins + char const *end_file; //!< the file where the location ends + size_t begin_line; //!< the line where the location begins + size_t end_line; //!< the line where the location ends + size_t begin_column; //!< the column where the location begins + size_t end_column; //!< the column where the location ends +} clingo_location_t; + +//! @} + +// {{{1 signature and symbols + +//! @example symbol.c +//! The example shows how to create and inspect symbols. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! $ ./symbol 0 +//! the hash of 42 is 281474976710698 +//! the hash of x is 562949963481760 +//! the hash of x(42,x) is 1407374893613792 +//! 42 is equal to 42 +//! 42 is not equal to x +//! 42 is less than x +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup Symbols Symbols +//! Working with (evaluated) ground terms and related functions. +//! +//! @note All functions in this module are thread-safe. +//! +//! For an example, see @ref symbol.c. + +//! @addtogroup Symbols +//! @{ + +//! Represents a predicate signature. +//! +//! Signatures have a name and an arity, and can be positive or negative (to +//! represent classical negation). +typedef uint64_t clingo_signature_t; + +//! @name Signature Functions +//! @{ + +//! Create a new signature. +//! +//! @param[in] name name of the signature +//! @param[in] arity arity of the signature +//! @param[in] positive false if the signature has a classical negation sign +//! @param[out] signature the resulting signature +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_signature_create(char const *name, uint32_t arity, bool positive, clingo_signature_t *signature); +//! Get the name of a signature. +//! +//! @param[in] signature the target signature +//! @return the name of the signature +CLINGO_VISIBILITY_DEFAULT char const *clingo_signature_name(clingo_signature_t signature); +//! Get the arity of a signature. +//! +//! @param[in] signature the target signature +//! @return the arity of the signature +CLINGO_VISIBILITY_DEFAULT uint32_t clingo_signature_arity(clingo_signature_t signature); +//! Whether the signature is positive (is not classically negated). +//! +//! @param[in] signature the target signature +//! @return whether the signature has no sign +CLINGO_VISIBILITY_DEFAULT bool clingo_signature_is_positive(clingo_signature_t signature); +//! Whether the signature is negative (is classically negated). +//! +//! @param[in] signature the target signature +//! @return whether the signature has a sign +CLINGO_VISIBILITY_DEFAULT bool clingo_signature_is_negative(clingo_signature_t signature); +//! Check if two signatures are equal. +//! +//! @param[in] a first signature +//! @param[in] b second signature +//! @return whether a == b +CLINGO_VISIBILITY_DEFAULT bool clingo_signature_is_equal_to(clingo_signature_t a, clingo_signature_t b); +//! Check if a signature is less than another signature. +//! +//! Signatures are compared first by sign (unsigned < signed), then by arity, +//! then by name. +//! +//! @param[in] a first signature +//! @param[in] b second signature +//! @return whether a < b +CLINGO_VISIBILITY_DEFAULT bool clingo_signature_is_less_than(clingo_signature_t a, clingo_signature_t b); +//! Calculate a hash code of a signature. +//! +//! @param[in] signature the target signature +//! @return the hash code of the signature +CLINGO_VISIBILITY_DEFAULT size_t clingo_signature_hash(clingo_signature_t signature); + +//! @} + +//! Enumeration of available symbol types. +enum clingo_symbol_type { + clingo_symbol_type_infimum = 0, //!< the \#inf symbol + clingo_symbol_type_number = 1, //!< a numeric symbol, e.g., `1` + clingo_symbol_type_string = 4, //!< a string symbol, e.g., `"a"` + clingo_symbol_type_function = 5, //!< a numeric symbol, e.g., `c`, `(1, "a")`, or `f(1,"a")` + clingo_symbol_type_supremum = 7 //!< the \#sup symbol +}; +//! Corresponding type to ::clingo_symbol_type. +typedef int clingo_symbol_type_t; + +//! Represents a symbol. +//! +//! This includes numbers, strings, functions (including constants when +//! arguments are empty and tuples when the name is empty), \#inf and \#sup. +typedef uint64_t clingo_symbol_t; + +//! Represents a symbolic literal. +typedef struct clingo_symbolic_literal { + clingo_symbol_t symbol; //!< the associated symbol (must be a function) + bool positive; //!< whether the literal has a sign +} clingo_symbolic_literal_t; + +//! @name Symbol Construction Functions +//! @{ + +//! Construct a symbol representing a number. +//! +//! @param[in] number the number +//! @param[out] symbol the resulting symbol +CLINGO_VISIBILITY_DEFAULT void clingo_symbol_create_number(int number, clingo_symbol_t *symbol); +//! Construct a symbol representing \#sup. +//! +//! @param[out] symbol the resulting symbol +CLINGO_VISIBILITY_DEFAULT void clingo_symbol_create_supremum(clingo_symbol_t *symbol); +//! Construct a symbol representing \#inf. +//! +//! @param[out] symbol the resulting symbol +CLINGO_VISIBILITY_DEFAULT void clingo_symbol_create_infimum(clingo_symbol_t *symbol); +//! Construct a symbol representing a string. +//! +//! @param[in] string the string +//! @param[out] symbol the resulting symbol +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_create_string(char const *string, clingo_symbol_t *symbol); +//! Construct a symbol representing an id. +//! +//! @note This is just a shortcut for clingo_symbol_create_function() with +//! empty arguments. +//! +//! @param[in] name the name +//! @param[in] positive whether the symbol has a classical negation sign +//! @param[out] symbol the resulting symbol +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_create_id(char const *name, bool positive, clingo_symbol_t *symbol); +//! Construct a symbol representing a function or tuple. +//! +//! @note To create tuples, the empty string has to be used as name. +//! +//! @param[in] name the name of the function +//! @param[in] arguments the arguments of the function +//! @param[in] arguments_size the number of arguments +//! @param[in] positive whether the symbol has a classical negation sign +//! @param[out] symbol the resulting symbol +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_create_function(char const *name, clingo_symbol_t const *arguments, size_t arguments_size, bool positive, clingo_symbol_t *symbol); + +//! @} + +//! @name Symbol Inspection Functions +//! @{ + +//! Get the number of a symbol. +//! +//! @param[in] symbol the target symbol +//! @param[out] number the resulting number +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if symbol is not of type ::clingo_symbol_type_number +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_number(clingo_symbol_t symbol, int *number); +//! Get the name of a symbol. +//! +//! @param[in] symbol the target symbol +//! @param[out] name the resulting name +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if symbol is not of type ::clingo_symbol_type_function +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_name(clingo_symbol_t symbol, char const **name); +//! Get the string of a symbol. +//! +//! @param[in] symbol the target symbol +//! @param[out] string the resulting string +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if symbol is not of type ::clingo_symbol_type_string +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_string(clingo_symbol_t symbol, char const **string); +//! Check if a function is positive (does not have a sign). +//! +//! @param[in] symbol the target symbol +//! @param[out] positive the result +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if symbol is not of type ::clingo_symbol_type_function +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_is_positive(clingo_symbol_t symbol, bool *positive); +//! Check if a function is negative (has a sign). +//! +//! @param[in] symbol the target symbol +//! @param[out] negative the result +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if symbol is not of type ::clingo_symbol_type_function +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_is_negative(clingo_symbol_t symbol, bool *negative); +//! Get the arguments of a symbol. +//! +//! @param[in] symbol the target symbol +//! @param[out] arguments the resulting arguments +//! @param[out] arguments_size the number of arguments +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if symbol is not of type ::clingo_symbol_type_function +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_arguments(clingo_symbol_t symbol, clingo_symbol_t const **arguments, size_t *arguments_size); +//! Get the type of a symbol. +//! +//! @param[in] symbol the target symbol +//! @return the type of the symbol +CLINGO_VISIBILITY_DEFAULT clingo_symbol_type_t clingo_symbol_type(clingo_symbol_t symbol); +//! Get the size of the string representation of a symbol (including the terminating 0). +//! +//! @param[in] symbol the target symbol +//! @param[out] size the resulting size +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_to_string_size(clingo_symbol_t symbol, size_t *size); +//! Get the string representation of a symbol. +//! +//! @param[in] symbol the target symbol +//! @param[out] string the resulting string +//! @param[in] size the size of the string +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! +//! @see clingo_symbol_to_string_size() +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_to_string(clingo_symbol_t symbol, char *string, size_t size); + +//! @} + +//! @name Symbol Comparison Functions +//! @{ + +//! Check if two symbols are equal. +//! +//! @param[in] a first symbol +//! @param[in] b second symbol +//! @return whether a == b +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_is_equal_to(clingo_symbol_t a, clingo_symbol_t b); +//! Check if a symbol is less than another symbol. +//! +//! Symbols are first compared by type. If the types are equal, the values are +//! compared (where strings are compared using strcmp). Functions are first +//! compared by signature and then lexicographically by arguments. +//! +//! @param[in] a first symbol +//! @param[in] b second symbol +//! @return whether a < b +CLINGO_VISIBILITY_DEFAULT bool clingo_symbol_is_less_than(clingo_symbol_t a, clingo_symbol_t b); +//! Calculate a hash code of a symbol. +//! +//! @param[in] symbol the target symbol +//! @return the hash code of the symbol +CLINGO_VISIBILITY_DEFAULT size_t clingo_symbol_hash(clingo_symbol_t symbol); + +//! @} + +//! Internalize a string. +//! +//! This functions takes a string as input and returns an equal unique string +//! that is (at the moment) not freed until the program is closed. All strings +//! returned from clingo API functions are internalized and must not be freed. +//! +//! @param[in] string the string to internalize +//! @param[out] result the internalized string +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_add_string(char const *string, char const **result); +//! Parse a term in string form. +//! +//! The result of this function is a symbol. The input term can contain +//! unevaluated functions, which are evaluated during parsing. +//! +//! @param[in] string the string to parse +//! @param[in] logger optional logger to report warnings during parsing +//! @param[in] logger_data user data for the logger +//! @param[in] message_limit maximum number of times to call the logger +//! @param[out] symbol the resulting symbol +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if parsing fails +CLINGO_VISIBILITY_DEFAULT bool clingo_parse_term(char const *string, clingo_logger_t *logger, void *logger_data, unsigned message_limit, clingo_symbol_t *symbol); + +//! @} + +// {{{1 model and solve control + +//! @example model.c +//! The example shows how to inspect a model. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! $ ./model 0 +//! Stable model: +//! shown: c +//! atoms: b +//! terms: c +//! ~atoms: a +//! Stable model: +//! shown: a +//! atoms: a +//! terms: +//! ~atoms: b +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup Model Model Inspection +//! Inspection of models and a high-level interface to add constraints during solving. +//! +//! For an example, see @ref model.c. +//! @ingroup Control + +//! @addtogroup Model +//! @{ + +//! Object to add clauses during search. +typedef struct clingo_solve_control clingo_solve_control_t; + +//! Object representing a model. +typedef struct clingo_model clingo_model_t; + +//! Enumeration for the different model types. +enum clingo_model_type { + clingo_model_type_stable_model = 0, //!< The model represents a stable model. + clingo_model_type_brave_consequences = 1, //!< The model represents a set of brave consequences. + clingo_model_type_cautious_consequences = 2 //!< The model represents a set of cautious consequences. +}; +//! Corresponding type to ::clingo_model_type. +typedef int clingo_model_type_t; + +//! Enumeration of bit flags to select symbols in models. +enum clingo_show_type { + clingo_show_type_csp = 1, //!< Select CSP assignments. + clingo_show_type_shown = 2, //!< Select shown atoms and terms. + clingo_show_type_atoms = 4, //!< Select all atoms. + clingo_show_type_terms = 8, //!< Select all terms. + clingo_show_type_extra = 16, //!< Select symbols added by extensions. + clingo_show_type_all = 31, //!< Select everything. + clingo_show_type_complement = 32 //!< Select false instead of true atoms (::clingo_show_type_atoms) or terms (::clingo_show_type_terms). +}; +//! Corresponding type to ::clingo_show_type. +typedef unsigned clingo_show_type_bitset_t; + +//! @name Functions for Inspecting Models +//! @{ + +//! Get the type of the model. +//! +//! @param[in] model the target +//! @param[out] type the type of the model +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_model_type(clingo_model_t *model, clingo_model_type_t *type); +//! Get the running number of the model. +//! +//! @param[in] model the target +//! @param[out] number the number of the model +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_model_number(clingo_model_t *model, uint64_t *number); +//! Get the number of symbols of the selected types in the model. +//! +//! @param[in] model the target +//! @param[in] show which symbols to select +//! @param[out] size the number symbols +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_model_symbols_size(clingo_model_t *model, clingo_show_type_bitset_t show, size_t *size); +//! Get the symbols of the selected types in the model. +//! +//! @note CSP assignments are represented using functions with name "$" +//! where the first argument is the name of the CSP variable and the second one its +//! value. +//! +//! @param[in] model the target +//! @param[in] show which symbols to select +//! @param[out] symbols the resulting symbols +//! @param[in] size the number of selected symbols +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if the size is too small +//! +//! @see clingo_model_symbols_size() +CLINGO_VISIBILITY_DEFAULT bool clingo_model_symbols(clingo_model_t *model, clingo_show_type_bitset_t show, clingo_symbol_t *symbols, size_t size); +//! Constant time lookup to test whether an atom is in a model. +//! +//! @param[in] model the target +//! @param[in] atom the atom to lookup +//! @param[out] contained whether the atom is contained +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_model_contains(clingo_model_t *model, clingo_symbol_t atom, bool *contained); +//! Get the number of cost values of a model. +//! +//! @param[in] model the target +//! @param[out] size the number of costs +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_model_cost_size(clingo_model_t *model, size_t *size); +//! Get the cost vector of a model. +//! +//! @param[in] model the target +//! @param[out] costs the resulting costs +//! @param[in] size the number of costs +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if the size is too small +//! +//! @see clingo_model_cost_size() +//! @see clingo_model_optimality_proven() +CLINGO_VISIBILITY_DEFAULT bool clingo_model_cost(clingo_model_t *model, int64_t *costs, size_t size); +//! Whether the optimality of a model has been proven. +//! +//! @param[in] model the target +//! @param[out] proven whether the optimality has been proven +//! @return whether the call was successful +//! +//! @see clingo_model_cost() +CLINGO_VISIBILITY_DEFAULT bool clingo_model_optimality_proven(clingo_model_t *model, bool *proven); +//! @} + +//! @name Functions for Adding Clauses +//! @{ + +//! Get the associated solve control object of a model. +//! +//! This object allows for adding clauses during model enumeration. +//! @param[in] model the target +//! @param[out] control the resulting solve control object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_model_context(clingo_model_t *model, clingo_solve_control_t **control); +//! Get the id of the solver thread that found the model. +//! +//! @param[in] control the target +//! @param[out] id the resulting thread id +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_control_thread_id(clingo_solve_control_t *control, clingo_id_t *id); +//! Add a clause that applies to the current solving step during model +//! enumeration. +//! +//! @note The @ref Propagator module provides a more sophisticated +//! interface to add clauses - even on partial assignments. +//! +//! @param[in] control the target +//! @param[in] clause array of literals representing the clause +//! @param[in] size the size of the literal array +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if adding the clause fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_control_add_clause(clingo_solve_control_t *control, clingo_symbolic_literal_t const *clause, size_t size); +//! @} + +//! @} + +// {{{1 solve result + +// NOTE: documented in Control Module +enum clingo_solve_result { + clingo_solve_result_satisfiable = 1, + clingo_solve_result_unsatisfiable = 2, + clingo_solve_result_exhausted = 4, + clingo_solve_result_interrupted = 8 +}; +typedef unsigned clingo_solve_result_bitset_t; + + +// {{{1 solve iter + +//! @example solve-iteratively.c +//! The example shows how to iteratively enumerate models. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! ./solve-iteratively 0 +//! Model: a +//! Model: b +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup SolveIter Iterative Solving +//! Iterative enumeration of models (without using callbacks). +//! +//! Clingo provides two additional ways to handle solving: @ref SolveIter and @ref SolveAsync. +//! With iterative solving, models are enumerated one by one by calling @ref clingo_solve_iteratively_next() and @ref clingo_solve_iteratively_get() in a loop. +//! +//! For an example, see @ref solve-iteratively.c. +//! @ingroup Control + +//! @addtogroup SolveIter +//! @{ + +//! Search handle to enumerate models iteratively. +//! +//! @see clingo_control_solve_iteratively() +typedef struct clingo_solve_iteratively clingo_solve_iteratively_t; +//! Get the next model. +//! +//! @param[in] handle the target +//! @param[out] model the next model +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_iteratively_next(clingo_solve_iteratively_t *handle, clingo_model_t **model); +//! Get the solve result. +//! +//! @param[in] handle the target +//! @param[out] result the solve result +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_iteratively_get(clingo_solve_iteratively_t *handle, clingo_solve_result_bitset_t *result); +//! Closes an active search. +//! +//! There must be no function calls on the associated control object until this function has been called. +//! +//! @param[in] handle the target +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_iteratively_close(clingo_solve_iteratively_t *handle); + +//! @} + +// {{{1 solve async + +//! @example solve-async.c +//! The example shows how to solve in the background. +//! +//! ## Output (approximately) ## +//! +//! ~~~~~~~~~~~~ +//! ./solve-async 0 +//! pi = 3. +//! 1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 +//! 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647 +//! 0938446095 5058223172 5359408128 4811174502 8410270193 8521105559 +//! 6446229489 5493038196 4428810975 6659334461 2847564823 3786783165 +//! 2712019091 4564856692 3460348610 4543266482 1339360726 0249141273 +//! 7245870066 0631558817 4881520920 9628292540 9171536436 7892590360 +//! 0113305305 4882046652 1384146951 9415116094 3305727036 5759591953 +//! 0921861173 8193261179 3105118548 0744623799 6274956735 1885752724 +//! 8912279381 8301194912 ... +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup SolveAsync Asynchronous Solving +//! Solve in the background and notify about new models. +//! +//! Clingo provides two additional ways to handle solving: @ref SolveIter and @ref SolveAsync. +//! With asynchronous solving, the solving process is executed in the background, +//! and each newly found model is signalled via a @link ::clingo_model_callback_t model callback@endlink. +//! +//! For an example, see @ref solve-async.c. +//! @ingroup Control + +//! @addtogroup SolveAsync +//! @{ + +//! Search handle to an asynchronous solve call. +//! +//! @see clingo_control_solve_async() +typedef struct clingo_solve_async clingo_solve_async_t; +//! Get the solve result. +//! +//! Blocks until the search is completed. +//! +//! @param[in] handle the target +//! @param[out] result the solve result +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_async_get(clingo_solve_async_t *handle, clingo_solve_result_bitset_t *result); +//! Wait for the specified amount of time to check if the search has finished. +//! +//! If the time is set to zero, this function can be used to poll if the search +//! is still running. +//! +//! @param[in] handle the target +//! @param[in] timeout the maximum time to wait +//! @param[out] result whether the search is still running +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_async_wait(clingo_solve_async_t *handle, double timeout, bool *result); +//! Stop the running search. +//! +//! Blocks until the search is stopped. +//! +//! @param[in] handle the target +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +CLINGO_VISIBILITY_DEFAULT bool clingo_solve_async_cancel(clingo_solve_async_t *handle); + +//! @} + +// {{{1 symbolic atoms + +//! @example symbolic-atoms.c +//! The example shows how to iterate over symbolic atoms. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! ./symbolic-atoms 0 +//! Symbolic atoms: +//! b +//! c, external +//! a, fact +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup SymbolicAtoms Symbolic Atom Inspection +//! Inspection of atoms occurring in ground logic programs. +//! +//! For an example, see @ref symbolic-atoms.c. +//! @ingroup Control + +//! @addtogroup SymbolicAtoms +//! @{ + +//! Object to inspect symbolic atoms in a program---the relevant Herbrand base +//! gringo uses to instantiate programs. +//! +//! @see clingo_control_symbolic_atoms() +typedef struct clingo_symbolic_atoms clingo_symbolic_atoms_t; +//! Object to iterate over symbolic atoms. +//! +//! Such an iterator either points to a symbolic atom within a sequence of +//! symbolic atoms or to the end of the sequence. +//! +//! @note Iterators are valid as long as the underlying sequence is not modified. +//! Operations that can change this sequence are ::clingo_control_ground(), +//! ::clingo_control_cleanup(), and functions that modify the underlying +//! non-ground program. +typedef uint64_t clingo_symbolic_atom_iterator_t; +//! Get the number of different atoms occurring in a logic program. +//! +//! @param[in] atoms the target +//! @param[out] size the number of atoms +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_size(clingo_symbolic_atoms_t *atoms, size_t *size); +//! Get a forward iterator to the beginning of the sequence of all symbolic +//! atoms optionally restricted to a given signature. +//! +//! @param[in] atoms the target +//! @param[in] signature optional signature +//! @param[out] iterator the resulting iterator +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_begin(clingo_symbolic_atoms_t *atoms, clingo_signature_t const *signature, clingo_symbolic_atom_iterator_t *iterator); +//! Iterator pointing to the end of the sequence of symbolic atoms. +//! +//! @param[in] atoms the target +//! @param[out] iterator the resulting iterator +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_end(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t *iterator); +//! Find a symbolic atom given its symbolic representation. +//! +//! @param[in] atoms the target +//! @param[in] symbol the symbol to lookup +//! @param[out] iterator iterator pointing to the symbolic atom or to the end +//! of the sequence if no corresponding atom is found +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_find(clingo_symbolic_atoms_t *atoms, clingo_symbol_t symbol, clingo_symbolic_atom_iterator_t *iterator); +//! Check if two iterators point to the same element (or end of the sequence). +//! +//! @param[in] atoms the target +//! @param[in] a the first iterator +//! @param[in] b the second iterator +//! @param[out] equal whether the two iterators are equal +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_iterator_is_equal_to(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t a, clingo_symbolic_atom_iterator_t b, bool *equal); +//! Get the symbolic representation of an atom. +//! +//! @param[in] atoms the target +//! @param[in] iterator iterator to the atom +//! @param[out] symbol the resulting symbol +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_symbol(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t iterator, clingo_symbol_t *symbol); +//! Check whether an atom is a fact. +//! +//! @note This does not determine if an atom is a cautious consequence. The +//! grounding or solving component's simplifications can only detect this in +//! some cases. +//! +//! @param[in] atoms the target +//! @param[in] iterator iterator to the atom +//! @param[out] fact whether the atom is a fact +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_is_fact(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t iterator, bool *fact); +//! Check whether an atom is external. +//! +//! An atom is external if it has been defined using an external directive and +//! has not been released or defined by a rule. +//! +//! @param[in] atoms the target +//! @param[in] iterator iterator to the atom +//! @param[out] external whether the atom is a external +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_is_external(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t iterator, bool *external); +//! Returns the (numeric) aspif literal corresponding to the given symbolic atom. +//! +//! Such a literal can be mapped to a solver literal (see the \ref Propagator +//! module) or be used in rules in aspif format (see the \ref ProgramBuilder +//! module). +//! +//! @param[in] atoms the target +//! @param[in] iterator iterator to the atom +//! @param[out] literal the associated literal +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_literal(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t iterator, clingo_literal_t *literal); +//! Get the number of different predicate signatures used in the program. +//! +//! @param[in] atoms the target +//! @param[out] size the number of signatures +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_signatures_size(clingo_symbolic_atoms_t *atoms, size_t *size); +//! Get the predicate signatures occurring in a logic program. +//! +//! @param[in] atoms the target +//! @param[out] signatures the resulting signatures +//! @param[in] size the number of signatures +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if the size is too small +//! +//! @see clingo_symbolic_atoms_signatures_size() +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_signatures(clingo_symbolic_atoms_t *atoms, clingo_signature_t *signatures, size_t size); +//! Get an iterator to the next element in the sequence of symbolic atoms. +//! +//! @param[in] atoms the target +//! @param[in] iterator the current iterator +//! @param[out] next the succeeding iterator +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_next(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t iterator, clingo_symbolic_atom_iterator_t *next); +//! Check whether the given iterator points to some element with the sequence +//! of symbolic atoms or to the end of the sequence. +//! +//! @param[in] atoms the target +//! @param[in] iterator the iterator +//! @param[out] valid whether the iterator points to some element within the +//! sequence +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_symbolic_atoms_is_valid(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t iterator, bool *valid); + +//! @} + +// {{{1 theory atoms + +//! @example theory-atoms.c +//! The example shows how to inspect and use theory atoms. +//! +//! @verbatim@endverbatim +//! +//! This is a very simple example that uses the @link ProgramBuilder backend@endlink to let theory atoms affect answer sets. +//! In general, the backend can be used to implement a custom theory by translating it to a logic program. +//! On the other hand, a @link Propagator propagator@endlink can be used to implement a custom theory without adding any constraints in advance. +//! Or both approaches can be combined. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! ./theory-atoms 0 +//! number of grounded theory atoms: 2 +//! theory atom b/1 has a guard: true +//! Model: y +//! Model: x y +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup TheoryAtoms Theory Atom Inspection +//! Inspection of theory atoms occurring in ground logic programs. +//! @ingroup Control +//! +//! During grounding, theory atoms get consecutive numbers starting with zero. +//! The total number of theory atoms can be obtained using clingo_theory_atoms_size(). +//! +//! @attention +//! All structural information about theory atoms, elements, and terms is reset after @link clingo_control_solve() solving@endlink. +//! If afterward fresh theory atoms are @link clingo_control_ground() grounded@endlink, previously used ids are reused. +//! +//! For an example, see @ref theory-atoms.c. + +//! @addtogroup TheoryAtoms +//! @{ + +//! Enumeration of theory term types. +enum clingo_theory_term_type { + clingo_theory_term_type_tuple, //!< a tuple term, e.g., `(1,2,3)` + clingo_theory_term_type_list, //!< a list term, e.g., `[1,2,3]` + clingo_theory_term_type_set, //!< a set term, e.g., `{1,2,3}` + clingo_theory_term_type_function, //!< a function term, e.g., `f(1,2,3)` + clingo_theory_term_type_number, //!< a number term, e.g., `42` + clingo_theory_term_type_symbol //!< a symbol term, e.g., `c` +}; +//! Corresponding type to ::clingo_theory_term_type. +typedef int clingo_theory_term_type_t; + +//! Container that stores theory atoms, elements, and terms (see @ref clingo_control_theory_atoms()). +typedef struct clingo_theory_atoms clingo_theory_atoms_t; + +//! @name Theory Term Inspection +//! @{ + +//! Get the type of the given theory term. +//! +//! @param[in] atoms container where the term is stored +//! @param[in] term id of the term +//! @param[out] type the resulting type +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_term_type(clingo_theory_atoms_t *atoms, clingo_id_t term, clingo_theory_term_type_t *type); +//! Get the number of the given numeric theory term. +//! +//! @pre The term must be of type ::clingo_theory_term_type_number. +//! @param[in] atoms container where the term is stored +//! @param[in] term id of the term +//! @param[out] number the resulting number +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_term_number(clingo_theory_atoms_t *atoms, clingo_id_t term, int *number); +//! Get the name of the given constant or function theory term. +//! +//! @pre The term must be of type ::clingo_theory_term_type_function or ::clingo_theory_term_type_symbol. +//! @param[in] atoms container where the term is stored +//! @param[in] term id of the term +//! @param[out] name the resulting name +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_term_name(clingo_theory_atoms_t *atoms, clingo_id_t term, char const **name); +//! Get the arguments of the given function theory term. +//! +//! @pre The term must be of type ::clingo_theory_term_type_function. +//! @param[in] atoms container where the term is stored +//! @param[in] term id of the term +//! @param[out] arguments the resulting arguments in form of an array of term ids +//! @param[out] size the number of arguments +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_term_arguments(clingo_theory_atoms_t *atoms, clingo_id_t term, clingo_id_t const **arguments, size_t *size); +//! Get the size of the string representation of the given theory term (including the terminating 0). +//! +//! @param[in] atoms container where the term is stored +//! @param[in] term id of the term +//! @param[out] size the resulting size +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_term_to_string_size(clingo_theory_atoms_t *atoms, clingo_id_t term, size_t *size); +//! Get the string representation of the given theory term. +//! +//! @param[in] atoms container where the term is stored +//! @param[in] term id of the term +//! @param[out] string the resulting string +//! @param[in] size the size of the string +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if the size is too small +//! - ::clingo_error_bad_alloc +//! +//! @see clingo_theory_atoms_term_to_string_size() +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_term_to_string(clingo_theory_atoms_t *atoms, clingo_id_t term, char *string, size_t size); +//! @} + +//! @name Theory Element Inspection +//! @{ + +//! Get the tuple (array of theory terms) of the given theory element. +//! +//! @param[in] atoms container where the element is stored +//! @param[in] element id of the element +//! @param[out] tuple the resulting array of term ids +//! @param[out] size the number of term ids +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_element_tuple(clingo_theory_atoms_t *atoms, clingo_id_t element, clingo_id_t const **tuple, size_t *size); +//! Get the condition (array of aspif literals) of the given theory element. +//! +//! @param[in] atoms container where the element is stored +//! @param[in] element id of the element +//! @param[out] condition the resulting array of aspif literals +//! @param[out] size the number of term literals +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_element_condition(clingo_theory_atoms_t *atoms, clingo_id_t element, clingo_literal_t const **condition, size_t *size); +//! Get the id of the condition of the given theory element. +//! +//! @note +//! This id can be mapped to a solver literal using clingo_propagate_init_solver_literal(). +//! This id is not (necessarily) an aspif literal; +//! to get aspif literals use clingo_theory_atoms_element_condition(). +//! +//! @param[in] atoms container where the element is stored +//! @param[in] element id of the element +//! @param[out] condition the resulting condition id +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_element_condition_id(clingo_theory_atoms_t *atoms, clingo_id_t element, clingo_literal_t *condition); +//! Get the size of the string representation of the given theory element (including the terminating 0). +//! +//! @param[in] atoms container where the element is stored +//! @param[in] element id of the element +//! @param[out] size the resulting size +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_element_to_string_size(clingo_theory_atoms_t *atoms, clingo_id_t element, size_t *size); +//! Get the string representation of the given theory element. +//! +//! @param[in] atoms container where the element is stored +//! @param[in] element id of the element +//! @param[out] string the resulting string +//! @param[in] size the size of the string +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if the size is too small +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_element_to_string(clingo_theory_atoms_t *atoms, clingo_id_t element, char *string, size_t size); +//! @} + +//! @name Theory Atom Inspection +//! @{ + +//! Get the total number of theory atoms. +//! +//! @param[in] atoms the target +//! @param[out] size the resulting number +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_size(clingo_theory_atoms_t *atoms, size_t *size); +//! Get the theory term associated with the theory atom. +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the atom +//! @param[out] term the resulting term id +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_term(clingo_theory_atoms_t *atoms, clingo_id_t atom, clingo_id_t *term); +//! Get the theory elements associated with the theory atom. +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the atom +//! @param[out] elements the resulting array of elements +//! @param[out] size the number of elements +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_elements(clingo_theory_atoms_t *atoms, clingo_id_t atom, clingo_id_t const **elements, size_t *size); +//! Whether the theory atom has a guard. +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the atom +//! @param[out] has_guard whether the theory atom has a guard +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_has_guard(clingo_theory_atoms_t *atoms, clingo_id_t atom, bool *has_guard); +//! Get the guard consisting of a theory operator and a theory term of the given theory atom. +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the atom +//! @param[out] connective the resulting theory operator +//! @param[out] term the resulting term +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_guard(clingo_theory_atoms_t *atoms, clingo_id_t atom, char const **connective, clingo_id_t *term); +//! Get the aspif literal associated with the given theory atom. +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the atom +//! @param[out] literal the resulting literal +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_literal(clingo_theory_atoms_t *atoms, clingo_id_t atom, clingo_literal_t *literal); +//! Get the size of the string representation of the given theory atom (including the terminating 0). +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the element +//! @param[out] size the resulting size +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_to_string_size(clingo_theory_atoms_t *atoms, clingo_id_t atom, size_t *size); +//! Get the string representation of the given theory atom. +//! +//! @param[in] atoms container where the atom is stored +//! @param[in] atom id of the element +//! @param[out] string the resulting string +//! @param[in] size the size of the string +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if the size is too small +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_theory_atoms_atom_to_string(clingo_theory_atoms_t *atoms, clingo_id_t atom, char *string, size_t size); +//! @} + +//! @} + +// {{{1 propagator + +//! @example propagator.c +//! The example shows how to write a simple propagator for the pigeon hole problem. For +//! a detailed description of what is implemented here and some background, take a look at the following paper: +//! +//! http://www.cs.uni-potsdam.de/wv/pdfformat/gekakaosscwa16b.pdf +//! +//! ## Output ## +//! +//! The output is empty because the pigeon hole problem is unsatisfiable. +//! +//! ## Code ## + +//! @defgroup Propagator Theory Propagation +//! Extend the search with propagators for arbitrary theories. +//! +//! For an example, see @ref propagator.c. +//! @ingroup Control + +//! @addtogroup Propagator +//! @{ + +//! Object to initialize a used-defined propagator before each solving step. +//! +//! Each @link SymbolicAtoms symbolic@endlink or @link TheoryAtoms theory atom@endlink is uniquely associated with an aspif atom in form of a positive integer (@ref ::clingo_literal_t). +//! Aspif literals additionally are signed to represent default negation. +//! Furthermore, there are non-zero integer solver literals (also represented using @ref ::clingo_literal_t). +//! There is a surjective mapping from program atoms to solver literals. +//! +//! All methods called during propagation use solver literals whereas clingo_symbolic_atoms_literal() and clingo_theory_atoms_atom_literal() return program literals. +//! The function clingo_propagate_init_solver_literal() can be used to map program literals or @link clingo_theory_atoms_element_condition_id() condition ids@endlink to solver literals. +typedef struct clingo_propagate_init clingo_propagate_init_t; + +//! @name Initialization Functions +//! @{ + +//! Map the given program literal or condition id to its solver literal. +//! +//! @param[in] init the target +//! @param[in] aspif_literal the aspif literal to map +//! @param[out] solver_literal the resulting solver literal +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_init_solver_literal(clingo_propagate_init_t *init, clingo_literal_t aspif_literal, clingo_literal_t *solver_literal); +//! Add a watch for the solver literal in the given phase. +//! +//! @param[in] init the target +//! @param[out] solver_literal the solver literal +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_init_add_watch(clingo_propagate_init_t *init, clingo_literal_t solver_literal); +//! Get an object to inspect the symbolic atoms. +//! +//! @param[in] init the target +//! @param[out] atoms the resulting object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_init_symbolic_atoms(clingo_propagate_init_t *init, clingo_symbolic_atoms_t **atoms); +//! Get an object to inspect the theory atoms. +//! +//! @param[in] init the target +//! @param[out] atoms the resulting object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_init_theory_atoms(clingo_propagate_init_t *init, clingo_theory_atoms_t **atoms); +//! Get the number of threads used in subsequent solving. +//! +//! @param[in] init the target +//! @return the number of threads +//! @see clingo_propagate_control_thread_id() +CLINGO_VISIBILITY_DEFAULT int clingo_propagate_init_number_of_threads(clingo_propagate_init_t *init); + +//! @} + +//! Represents a (partial) assignment of a particular solver. +//! +//! An assignment assigns truth values to a set of literals. +//! A literal is assigned to either @link clingo_assignment_truth_value() true or false, or is unassigned@endlink. +//! Furthermore, each assigned literal is associated with a @link clingo_assignment_level() decision level@endlink. +//! There is exactly one @link clingo_assignment_decision() decision literal@endlink for each decision level greater than zero. +//! Assignments to all other literals on the same level are consequences implied by the current and possibly previous decisions. +//! Assignments on level zero are immediate consequences of the current program. +//! Decision levels are consecutive numbers starting with zero up to and including the @link clingo_assignment_decision_level() current decision level@endlink. +typedef struct clingo_assignment clingo_assignment_t; + +//! @name Assignment Functions +//! @{ + +//! Get the current decision level. +//! +//! @param[in] assignment the target assignment +//! @return the decision level +CLINGO_VISIBILITY_DEFAULT uint32_t clingo_assignment_decision_level(clingo_assignment_t *assignment); +//! Check if the given assignment is conflicting. +//! +//! @param[in] assignment the target assignment +//! @return whether the assignment is conflicting +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_has_conflict(clingo_assignment_t *assignment); +//! Check if the given literal is part of a (partial) assignment. +//! +//! @param[in] assignment the target assignment +//! @param[in] literal the literal +//! @return whether the literal is valid +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_has_literal(clingo_assignment_t *assignment, clingo_literal_t literal); +//! Determine the decision level of a given literal. +//! +//! @param[in] assignment the target assignment +//! @param[in] literal the literal +//! @param[out] level the resulting level +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_level(clingo_assignment_t *assignment, clingo_literal_t literal, uint32_t *level); +//! Determine the decision literal given a decision level. +//! +//! @param[in] assignment the target assignment +//! @param[in] level the level +//! @param[out] literal the resulting literal +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_decision(clingo_assignment_t *assignment, uint32_t level, clingo_literal_t *literal); +//! Check if a literal has a fixed truth value. +//! +//! @param[in] assignment the target assignment +//! @param[in] literal the literal +//! @param[out] is_fixed whether the literal is fixed +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_is_fixed(clingo_assignment_t *assignment, clingo_literal_t literal, bool *is_fixed); +//! Check if a literal is true. +//! +//! @param[in] assignment the target assignment +//! @param[in] literal the literal +//! @param[out] is_true whether the literal is true +//! @return whether the call was successful +//! @see clingo_assignment_truth_value() +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_is_true(clingo_assignment_t *assignment, clingo_literal_t literal, bool *is_true); +//! Check if a literal has a fixed truth value. +//! +//! @param[in] assignment the target assignment +//! @param[in] literal the literal +//! @param[out] is_false whether the literal is false +//! @return whether the call was successful +//! @see clingo_assignment_truth_value() +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_is_false(clingo_assignment_t *assignment, clingo_literal_t literal, bool *is_false); +//! Determine the truth value of a given literal. +//! +//! @param[in] assignment the target assignment +//! @param[in] literal the literal +//! @param[out] value the resulting truth value +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_assignment_truth_value(clingo_assignment_t *assignment, clingo_literal_t literal, clingo_truth_value_t *value); + +//! @} + +//! Enumeration of clause types determining the lifetime of a clause. +//! +//! Clauses in the solver are either cleaned up based on a configurable deletion policy or at the end of a solving step. +//! The values of this enumeration determine if a clause is subject to one of the above deletion strategies. +enum clingo_clause_type { + clingo_clause_type_learnt = 0, //!< clause is subject to the solvers deletion policy + clingo_clause_type_static = 1, //!< clause is not subject to the solvers deletion policy + clingo_clause_type_volatile = 2, //!< like ::clingo_clause_type_learnt but the clause is deleted after a solving step + clingo_clause_type_volatile_static = 3 //!< like ::clingo_clause_type_static but the clause is deleted after a solving step +}; +//! Corresponding type to ::clingo_clause_type. +typedef int clingo_clause_type_t; + +//! This object can be used to add clauses and propagate literals while solving. +typedef struct clingo_propagate_control clingo_propagate_control_t; + +//! @name Propagation Functions +//! @{ + +//! Get the id of the underlying solver thread. +//! +//! Thread ids are consecutive numbers starting with zero. +//! +//! @param[in] control the target +//! @return the thread id +CLINGO_VISIBILITY_DEFAULT clingo_id_t clingo_propagate_control_thread_id(clingo_propagate_control_t *control); +//! Get the assignment associated with the underlying solver. +//! +//! @param[in] control the target +//! @return the assignment +CLINGO_VISIBILITY_DEFAULT clingo_assignment_t *clingo_propagate_control_assignment(clingo_propagate_control_t *control); +//! Adds a new volatile literal to the underlying solver thread. +//! +//! @attention The literal is only valid within the current solving step and solver thread. +//! All volatile literals and clauses involving a volatile literal are deleted after the current search. +//! +//! @param[in] control the target +//! @param[out] result the (positive) solver literal +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_logic if the assignment is conflicting +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_control_add_literal(clingo_propagate_control_t *control, clingo_literal_t *result); +//! Add a watch for the solver literal in the given phase. +//! +//! @note Unlike @ref clingo_propagate_init_add_watch() this does not add a watch to all solver threads but just the current one. +//! +//! @param[in] control the target +//! @param[in] literal the literal to watch +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_logic if the literal is invalid +//! @see clingo_propagate_control_remove_watch() +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_control_add_watch(clingo_propagate_control_t *control, clingo_literal_t literal); +//! Check whether a literal is watched in the current solver thread. +//! +//! @param[in] control the target +//! @param[in] literal the literal to check +//! +//! @return whether the literal is watched +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_control_has_watch(clingo_propagate_control_t *control, clingo_literal_t literal); +//! Removes the watch (if any) for the given solver literal. +//! +//! @note Similar to @ref clingo_propagate_init_add_watch() this just removes the watch in the current solver thread. +//! +//! @param[in] control the target +//! @param[in] literal the literal to remove +CLINGO_VISIBILITY_DEFAULT void clingo_propagate_control_remove_watch(clingo_propagate_control_t *control, clingo_literal_t literal); +//! Add the given clause to the solver. +//! +//! This method sets its result to false if the current propagation must be stopped for the solver to backtrack. +//! +//! @attention No further calls on the control object or functions on the assignment should be called when the result of this method is false. +//! +//! @param[in] control the target +//! @param[in] clause the clause to add +//! @param[in] size the size of the clause +//! @param[in] type the clause type determining its lifetime +//! @param[out] result result indicating whether propagation has to be stopped +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_control_add_clause(clingo_propagate_control_t *control, clingo_literal_t const *clause, size_t size, clingo_clause_type_t type, bool *result); +//! Propagate implied literals (resulting from added clauses). +//! +//! This method sets its result to false if the current propagation must be stopped for the solver to backtrack. +//! +//! @attention No further calls on the control object or functions on the assignment should be called when the result of this method is false. +//! +//! @param[in] control the target +//! @param[out] result result indicating whether propagation has to be stopped +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_propagate_control_propagate(clingo_propagate_control_t *control, bool *result); + +//! @} + +//! Typedef for @ref ::clingo_propagator::init(). +typedef bool (*clingo_propagator_init_callback_t) (clingo_propagate_init_t *, void *); + +//! Typedef for @ref ::clingo_propagator::propagate(). +typedef bool (*clingo_propagator_propagate_callback_t) (clingo_propagate_control_t *, clingo_literal_t const *, size_t, void *); + +//! Typedef for @ref ::clingo_propagator::undo(). +typedef bool (*clingo_propagator_undo_callback_t) (clingo_propagate_control_t *, clingo_literal_t const *, size_t, void *); + +//! Typedef for @ref ::clingo_propagator::check(). +typedef bool (*clingo_propagator_check_callback_t) (clingo_propagate_control_t *, void *); + +//! An instance of this struct has to be registered with a solver to implement a custom propagator. +//! +//! Not all callbacks have to be implemented and can be set to NULL if not needed. +//! @see Propagator +typedef struct clingo_propagator { + //! This function is called once before each solving step. + //! It is used to map relevant program literals to solver literals, add watches for solver literals, and initialize the data structures used during propagation. + //! + //! @note This is the last point to access symbolic and theory atoms. + //! Once the search has started, they are no longer accessible. + //! + //! @param[in] control control object for the target solver + //! @param[in] data user data for the callback + //! @return whether the call was successful + //! @see ::clingo_propagator_init_callback_t + bool (*init) (clingo_propagate_init_t *control, void *data); + //! Can be used to propagate solver literals given a @link clingo_assignment_t partial assignment@endlink. + //! + //! Called during propagation with a non-empty array of @link clingo_propagate_init_add_watch() watched solver literals@endlink + //! that have been assigned to true since the last call to either propagate, undo, (or the start of the search) - the change set. + //! Only watched solver literals are contained in the change set. + //! Each literal in the change set is true w.r.t. the current @link clingo_assignment_t assignment@endlink. + //! @ref clingo_propagate_control_add_clause() can be used to add clauses. + //! If a clause is unit resulting, it can be propagated using @ref clingo_propagate_control_propagate(). + //! If the result of either of the two methods is false, the propagate function must return immediately. + //! + //! The following snippet shows how to use the methods to add clauses and propagate consequences within the callback. + //! The important point is to return true (true to indicate there was no error) if the result of either of the methods is false. + //! ~~~~~~~~~~~~~~~{.c} + //! bool result; + //! clingo_literal_t clause[] = { ... }; + //! + //! // add a clause + //! if (!clingo_propagate_control_add_clause(control, clause, clingo_clause_type_learnt, &result) { return false; } + //! if (!result) { return true; } + //! // propagate its consequences + //! if (!clingo_propagate_control_propagate(control, &result) { return false; } + //! if (!result) { return true; } + //! + //! // add further clauses and propagate them + //! ... + //! + //! return true; + //! ~~~~~~~~~~~~~~~ + //! + //! @note + //! This function can be called from different solving threads. + //! Each thread has its own assignment and id, which can be obtained using @ref clingo_propagate_control_thread_id(). + //! + //! @param[in] control control object for the target solver + //! @param[in] changes the change set + //! @param[in] size the size of the change set + //! @param[in] data user data for the callback + //! @return whether the call was successful + //! @see ::clingo_propagator_propagate_callback_t + bool (*propagate) (clingo_propagate_control_t *control, clingo_literal_t const *changes, size_t size, void *data); + //! Called whenever a solver undoes assignments to watched solver literals. + //! + //! This callback is meant to update assignment dependent state in the propagator. + //! + //! @note No clauses must be propagated in this callback. + //! + //! @param[in] control control object for the target solver + //! @param[in] changes the change set + //! @param[in] size the size of the change set + //! @param[in] data user data for the callback + //! @see ::clingo_propagator_undo_callback_t + bool (*undo) (clingo_propagate_control_t *control, clingo_literal_t const *changes, size_t size, void *data); + //! This function is similar to @ref clingo_propagate_control_propagate() but is only called on total assignments without a change set. + //! + //! @note This function is called even if no watches have been added. + //! @param[in] control control object for the target solver + //! @param[in] data user data for the callback + //! @return whether the call was successful + //! @see ::clingo_propagator_check_callback_t + bool (*check) (clingo_propagate_control_t *control, void *data); +} clingo_propagator_t; + +//! @} + +// {{{1 backend + +//! @example backend.c +//! The example shows how to used the backend to extend a grounded program. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! ./backend 0 +//! Model: a b +//! Model: a b c +//! Model: +//! Model: a +//! Model: b +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup ProgramBuilder Program Building +//! Add non-ground program representations (ASTs) to logic programs or extend the ground (aspif) program. +//! @ingroup Control +//! +//! For an example about ground logic programs, see @ref backend.c. +//! For an example about non-ground logic programs, see @ref ast.c and the @ref AST module. + +//! @addtogroup ProgramBuilder +//! @{ + +//! Enumeration of different heuristic modifiers. +//! @ingroup ProgramInspection +enum clingo_heuristic_type { + clingo_heuristic_type_level = 0, //!< set the level of an atom + clingo_heuristic_type_sign = 1, //!< configure which sign to chose for an atom + clingo_heuristic_type_factor = 2, //!< modify VSIDS factor of an atom + clingo_heuristic_type_init = 3, //!< modify the initial VSIDS score of an atom + clingo_heuristic_type_true = 4, //!< set the level of an atom and choose a positive sign + clingo_heuristic_type_false = 5 //!< set the level of an atom and choose a negative sign +}; +//! Corresponding type to ::clingo_heuristic_type. +//! @ingroup ProgramInspection +typedef int clingo_heuristic_type_t; + +//! Enumeration of different external statements. +//! @ingroup ProgramInspection +enum clingo_external_type { + clingo_external_type_free = 0, //!< allow an external to be assigned freely + clingo_external_type_true = 1, //!< assign an external to true + clingo_external_type_false = 2, //!< assign an external to false + clingo_external_type_release = 3, //!< no longer treat an atom as external +}; +//! Corresponding type to ::clingo_external_type. +//! @ingroup ProgramInspection +typedef int clingo_external_type_t; + +//! A Literal with an associated weight. +//! @ingroup ProgramInspection +typedef struct clingo_weighted_literal { + clingo_literal_t literal; + clingo_weight_t weight; +} clingo_weighted_literal_t; + +//! Handle to the backend to add directives in aspif format. +typedef struct clingo_backend clingo_backend_t; + +//! Add a rule to the program. +//! +//! @param[in] backend the target backend +//! @param[in] choice determines if the head is a choice or a disjunction +//! @param[in] head the head atoms +//! @param[in] head_size the number of atoms in the head +//! @param[in] body the body literals +//! @param[in] body_size the number of literals in the body +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_rule(clingo_backend_t *backend, bool choice, clingo_atom_t const *head, size_t head_size, clingo_literal_t const *body, size_t body_size); +//! Add a weight rule to the program. +//! +//! @attention All weights and the lower bound must be positive. +//! @param[in] backend the target backend +//! @param[in] choice determines if the head is a choice or a disjunction +//! @param[in] head the head atoms +//! @param[in] head_size the number of atoms in the head +//! @param[in] lower_bound the lower bound of the weight rule +//! @param[in] body the weighted body literals +//! @param[in] body_size the number of weighted literals in the body +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_weight_rule(clingo_backend_t *backend, bool choice, clingo_atom_t const *head, size_t head_size, clingo_weight_t lower_bound, clingo_weighted_literal_t const *body, size_t body_size); +//! Add a minimize constraint (or weak constraint) to the program. +//! +//! @param[in] backend the target backend +//! @param[in] priority the priority of the constraint +//! @param[in] literals the weighted literals whose sum to minimize +//! @param[in] size the number of weighted literals +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_minimize(clingo_backend_t *backend, clingo_weight_t priority, clingo_weighted_literal_t const* literals, size_t size); +//! Add a projection directive. +//! +//! @param[in] backend the target backend +//! @param[in] atoms the atoms to project on +//! @param[in] size the number of atoms +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_project(clingo_backend_t *backend, clingo_atom_t const *atoms, size_t size); +//! Add an external statement. +//! +//! @param[in] backend the target backend +//! @param[in] atom the external atom +//! @param[in] type the type of the external statement +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_external(clingo_backend_t *backend, clingo_atom_t atom, clingo_external_type_t type); +//! Add an assumption directive. +//! +//! @param[in] backend the target backend +//! @param[in] literals the literals to assume (positive literals are true and negative literals false for the next solve call) +//! @param[in] size the number of atoms +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_assume(clingo_backend_t *backend, clingo_literal_t const *literals, size_t size); +//! Add an heuristic directive. +//! +//! @param[in] backend the target backend +//! @param[in] atom the target atom +//! @param[in] type the type of the heuristic modification +//! @param[in] bias the heuristic bias +//! @param[in] priority the heuristic priority +//! @param[in] condition the condition under which to apply the heuristic modification +//! @param[in] size the number of atoms in the condition +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_heuristic(clingo_backend_t *backend, clingo_atom_t atom, clingo_heuristic_type_t type, int bias, unsigned priority, clingo_literal_t const *condition, size_t size); +//! Add an edge directive. +//! +//! @param[in] backend the target backend +//! @param[in] node_u the start vertex of the edge +//! @param[in] node_v the end vertex of the edge +//! @param[in] condition the condition under which the edge is part of the graph +//! @param[in] size the number of atoms in the condition +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_acyc_edge(clingo_backend_t *backend, int node_u, int node_v, clingo_literal_t const *condition, size_t size); +//! Get a fresh atom to be used in aspif directives. +//! +//! @param[in] backend the target backend +//! @param[out] atom the resulting atom +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_backend_add_atom(clingo_backend_t *backend, clingo_atom_t *atom); + +//! @} + +// {{{1 configuration + +//! @example configuration.c +//! The example shows how to configure the solver. +//! +//! @note It is also possible to loop over all configuration entries. +//! This can be done in a similar fashion as in the @ref statistics.c example. +//! But note that, unlike with statistics entries, a configuration entry can have more than one type. +//! +//! ## Output ## +//! +//! ~~~~~~~~ +//! ./configuration +//! Model: a +//! Model: b +//! ~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup Configuration Solver Configuration +//! Configuration of search and enumeration algorithms. +//! +//! Entries in a configuration are organized hierarchically. +//! Subentries are either accessed by name for map entries or by offset for array entries. +//! Value entries have a string value that can be inspected or modified. +//! +//! For an example, see @ref configuration.c. +//! @ingroup Control + +//! @addtogroup Configuration +//! @{ + +//! Enumeration for entries of the configuration. +enum clingo_configuration_type { + clingo_configuration_type_value = 1, //!< the entry is a (string) value + clingo_configuration_type_array = 2, //!< the entry is an array + clingo_configuration_type_map = 4 //!< the entry is a map +}; +//! Bitset for values of type ::clingo_configuration_type. +typedef unsigned clingo_configuration_type_bitset_t; + +//! Handle for to the solver configuration. +typedef struct clingo_configuration clingo_configuration_t; + +//! Get the root key of the configuration. +//! +//! @param[in] configuration the target configuration +//! @param[out] key the root key +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_root(clingo_configuration_t *configuration, clingo_id_t *key); +//! Get the type of a key. +//! +//! @note The type is bitset, an entry can have multiple (but at least one) type. +//! +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] type the resulting type +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_type(clingo_configuration_t *configuration, clingo_id_t key, clingo_configuration_type_bitset_t *type); +//! Get the description of an entry. +//! +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] description the description +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_description(clingo_configuration_t *configuration, clingo_id_t key, char const **description); + +//! @name Functions to access arrays +//! @{ + +//! Get the size of an array entry. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_array. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] size the resulting size +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_array_size(clingo_configuration_t *configuration, clingo_id_t key, size_t *size); +//! Get the subkey at the given offset of an array entry. +//! +//! @note Some array entries, like fore example the solver configuration, can be accessed past there actual size to add subentries. +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_array. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[in] offset the offset in the array +//! @param[out] subkey the resulting subkey +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_array_at(clingo_configuration_t *configuration, clingo_id_t key, size_t offset, clingo_id_t *subkey); +//! @} + +//! @name Functions to access maps +//! @{ + +//! Get the number of subkeys of a map entry. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_map. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] size the resulting number +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_map_size(clingo_configuration_t *configuration, clingo_id_t key, size_t* size); +//! Get the name associated with the offset-th subkey. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_map. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[in] offset the offset of the name +//! @param[out] name the resulting name +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_map_subkey_name(clingo_configuration_t *configuration, clingo_id_t key, size_t offset, char const **name); +//! Lookup a subkey under the given name. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_map. +//! @note Multiple levels can be looked up by concatenating keys with a period. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[in] name the name to lookup the subkey +//! @param[out] subkey the resulting subkey +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_map_at(clingo_configuration_t *configuration, clingo_id_t key, char const *name, clingo_id_t* subkey); +//! @} + +//! @name Functions to access values +//! @{ + +//! Check whether a entry has a value. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_value. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] assigned whether the entry has a value +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_value_is_assigned(clingo_configuration_t *configuration, clingo_id_t key, bool *assigned); +//! Get the size of the string value of the given entry. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_value. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] size the resulting size +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_value_get_size(clingo_configuration_t *configuration, clingo_id_t key, size_t *size); +//! Get the string value of the given entry. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_value. +//! @pre The given size must be larger or equal to size of the value. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[out] value the resulting string value +//! @param[in] size the size of the given char array +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_value_get(clingo_configuration_t *configuration, clingo_id_t key, char *value, size_t size); +//! Set the value of an entry. +//! +//! @pre The @link clingo_configuration_type() type@endlink of the entry must be @ref ::clingo_configuration_type_value. +//! @param[in] configuration the target configuration +//! @param[in] key the key +//! @param[in] value the value to set +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_configuration_value_set(clingo_configuration_t *configuration, clingo_id_t key, char const *value); +//! @} + +//! @} + +// {{{1 statistics + +//! @example statistics.c +//! The example shows how to inspect statistics. +//! +//! ## Output ## +//! +//! ~~~~~~~~ +//! ./statistics 0 +//! Model: a +//! Model: b +//! problem: +//! lp: +//! atoms: +//! 2 +//! atoms_aux: +//! 0 +//! ... +//! solving: +//! ... +//! summary: +//! ... +//! accu: +//! times: +//! ... +//! models: +//! ... +//! solving: +//! ... +//! ~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup Statistics Statistics +//! Inspect search and problem statistics. +//! +//! @ingroup Control +//! For an example, see @ref statistics.c. + +//! @addtogroup Statistics +//! @{ + +//! Enumeration for entries of the statistics. +enum clingo_statistics_type { + clingo_statistics_type_empty = 0, //!< the entry is invalid (has neither of the types below) + clingo_statistics_type_value = 1, //!< the entry is a (string) value + clingo_statistics_type_array = 2, //!< the entry is an array + clingo_statistics_type_map = 3 //!< the entry is a map +}; +//! Corresponding type to ::clingo_solve_result. +typedef int clingo_statistics_type_t; + +//! Handle for to the solver statistics. +typedef struct clingo_statistic clingo_statistics_t; + +//! Get the root key of the statistics. +//! +//! @param[in] statistics the target statistics +//! @param[out] key the root key +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_root(clingo_statistics_t *statistics, uint64_t *key); +//! Get the type of a key. +//! +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[out] type the resulting type +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_type(clingo_statistics_t *statistics, uint64_t key, clingo_statistics_type_t *type); + +//! @name Functions to access arrays +//! @{ + +//! Get the size of an array entry. +//! +//! @pre The @link clingo_statistics_type() type@endlink of the entry must be @ref ::clingo_statistics_type_array. +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[out] size the resulting size +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_array_size(clingo_statistics_t *statistics, uint64_t key, size_t *size); +//! Get the subkey at the given offset of an array entry. +//! +//! @pre The @link clingo_statistics_type() type@endlink of the entry must be @ref ::clingo_statistics_type_array. +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[in] offset the offset in the array +//! @param[out] subkey the resulting subkey +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_array_at(clingo_statistics_t *statistics, uint64_t key, size_t offset, uint64_t *subkey); +//! @} + +//! @name Functions to access maps +//! @{ + +//! Get the number of subkeys of a map entry. +//! +//! @pre The @link clingo_statistics_type() type@endlink of the entry must be @ref ::clingo_statistics_type_map. +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[out] size the resulting number +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_map_size(clingo_statistics_t *statistics, uint64_t key, size_t *size); +//! Get the name associated with the offset-th subkey. +//! +//! @pre The @link clingo_statistics_type() type@endlink of the entry must be @ref ::clingo_statistics_type_map. +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[in] offset the offset of the name +//! @param[out] name the resulting name +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_map_subkey_name(clingo_statistics_t *statistics, uint64_t key, size_t offset, char const **name); +//! Lookup a subkey under the given name. +//! +//! @pre The @link clingo_statistics_type() type@endlink of the entry must be @ref ::clingo_statistics_type_map. +//! @note Multiple levels can be looked up by concatenating keys with a period. +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[in] name the name to lookup the subkey +//! @param[out] subkey the resulting subkey +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_map_at(clingo_statistics_t *statistics, uint64_t key, char const *name, uint64_t *subkey); +//! @} + +//! @name Functions to inspect values +//! @{ + +//! Get the value of the given entry. +//! +//! @pre The @link clingo_statistics_type() type@endlink of the entry must be @ref ::clingo_statistics_type_value. +//! @param[in] statistics the target statistics +//! @param[in] key the key +//! @param[out] value the resulting value +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_statistics_value_get(clingo_statistics_t *statistics, uint64_t key, double *value); +//! @} + +//! @} + +// {{{1 ast + +//! @example ast.c +//! The example shows how to rewrite a non-ground logic program. +//! +//! ## Output ## +//! +//! ~~~~~~~~ +//! ./ast 0 +//! Solving with enable = false... +//! Model: +//! Solving with enable = true... +//! Model: enable a +//! Model: enable b +//! Solving with enable = false... +//! Model: +//! ~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup AST Abstract Syntax Trees +//! Functions and data structures to work with program ASTs. +//! +//! @warning There might still be changes to this part of the API and there is not much documentation yet. +//! In its current form the interface is rather large +//! but has the advantage that the structure of a logic program is (hopefully) self-explanatory. +//! The API could also be much reduced by, for example, just providing one node type as done in [clingo's python API](https://potassco.org/clingo/python-api/current/clingo.html). +//! [Feedback would be very welcome!](https://github.com/potassco/clingo/issues) +//! +//! For an example, see @ref ast.c. + +//! @addtogroup AST +//! @{ + +enum clingo_ast_comparison_operator { + clingo_ast_comparison_operator_greater_than = 0, + clingo_ast_comparison_operator_less_than = 1, + clingo_ast_comparison_operator_less_equal = 2, + clingo_ast_comparison_operator_greater_equal = 3, + clingo_ast_comparison_operator_not_equal = 4, + clingo_ast_comparison_operator_equal = 5 +}; +typedef int clingo_ast_comparison_operator_t; + +enum clingo_ast_sign { + clingo_ast_sign_none = 0, + clingo_ast_sign_negation = 1, + clingo_ast_sign_double_negation = 2 +}; +typedef int clingo_ast_sign_t; + +// {{{2 terms + +enum clingo_ast_term_type { + clingo_ast_term_type_symbol = 0, + clingo_ast_term_type_variable = 1, + clingo_ast_term_type_unary_operation = 2, + clingo_ast_term_type_binary_operation = 3, + clingo_ast_term_type_interval = 4, + clingo_ast_term_type_function = 5, + clingo_ast_term_type_external_function = 6, + clingo_ast_term_type_pool = 7 +}; +typedef int clingo_ast_term_type_t; + +typedef struct clingo_ast_unary_operation clingo_ast_unary_operation_t; +typedef struct clingo_ast_binary_operation clingo_ast_binary_operation_t; +typedef struct clingo_ast_interval clingo_ast_interval_t; +typedef struct clingo_ast_function clingo_ast_function_t; +typedef struct clingo_ast_pool clingo_ast_pool_t; +typedef struct clingo_ast_term { + clingo_location_t location; + clingo_ast_term_type_t type; + union { + clingo_symbol_t symbol; + char const *variable; + clingo_ast_unary_operation_t const *unary_operation; + clingo_ast_binary_operation_t const *binary_operation; + clingo_ast_interval_t const *interval; + clingo_ast_function_t const *function; + clingo_ast_function_t const *external_function; + clingo_ast_pool_t const *pool; + }; +} clingo_ast_term_t; + +// unary operation + +enum clingo_ast_unary_operator { + clingo_ast_unary_operator_minus = 0, + clingo_ast_unary_operator_negation = 1, + clingo_ast_unary_operator_absolute = 2 +}; +typedef int clingo_ast_unary_operator_t; + +struct clingo_ast_unary_operation { + clingo_ast_unary_operator_t unary_operator; + clingo_ast_term_t argument; +}; + +// binary operation + +enum clingo_ast_binary_operator { + clingo_ast_binary_operator_xor = 0, + clingo_ast_binary_operator_or = 1, + clingo_ast_binary_operator_and = 2, + clingo_ast_binary_operator_plus = 3, + clingo_ast_binary_operator_minus = 4, + clingo_ast_binary_operator_multiplication = 5, + clingo_ast_binary_operator_division = 6, + clingo_ast_binary_operator_modulo = 7 + +}; +typedef int clingo_ast_binary_operator_t; + +struct clingo_ast_binary_operation { + clingo_ast_binary_operator_t binary_operator; + clingo_ast_term_t left; + clingo_ast_term_t right; +}; + +// interval + +struct clingo_ast_interval { + clingo_ast_term_t left; + clingo_ast_term_t right; +}; + +// function + +struct clingo_ast_function { + char const *name; + clingo_ast_term_t *arguments; + size_t size; +}; + +// pool + +struct clingo_ast_pool { + clingo_ast_term_t *arguments; + size_t size; +}; + +// {{{2 csp + +typedef struct clingo_ast_csp_product_term { + clingo_location_t location; + clingo_ast_term_t coefficient; + clingo_ast_term_t const *variable; +} clingo_ast_csp_product_term_t; + +typedef struct clingo_ast_csp_sum_term { + clingo_location_t location; + clingo_ast_csp_product_term_t *terms; + size_t size; +} clingo_ast_csp_sum_term_t; + +typedef struct clingo_ast_csp_guard { + clingo_ast_comparison_operator_t comparison; + clingo_ast_csp_sum_term_t term; +} clingo_ast_csp_guard_t; + +typedef struct clingo_ast_csp_literal { + clingo_ast_csp_sum_term_t term; + clingo_ast_csp_guard_t const *guards; + // NOTE: size must be at least one + size_t size; +} clingo_ast_csp_literal_t; + +// {{{2 ids + +typedef struct clingo_ast_id { + clingo_location_t location; + char const *id; +} clingo_ast_id_t; + +// {{{2 literals + +typedef struct clingo_ast_comparison { + clingo_ast_comparison_operator_t comparison; + clingo_ast_term_t left; + clingo_ast_term_t right; +} clingo_ast_comparison_t; + +enum clingo_ast_literal_type { + clingo_ast_literal_type_boolean = 0, + clingo_ast_literal_type_symbolic = 1, + clingo_ast_literal_type_comparison = 2, + clingo_ast_literal_type_csp = 3 +}; +typedef int clingo_ast_literal_type_t; + +typedef struct clingo_ast_literal { + clingo_location_t location; + clingo_ast_sign_t sign; + clingo_ast_literal_type_t type; + union { + bool boolean; + clingo_ast_term_t const *symbol; + clingo_ast_comparison_t const *comparison; + clingo_ast_csp_literal_t const *csp_literal; + }; +} clingo_ast_literal_t; + +// {{{2 aggregates + +enum clingo_ast_aggregate_function { + clingo_ast_aggregate_function_count = 0, + clingo_ast_aggregate_function_sum = 1, + clingo_ast_aggregate_function_sump = 2, + clingo_ast_aggregate_function_min = 3, + clingo_ast_aggregate_function_max = 4 +}; +typedef int clingo_ast_aggregate_function_t; + +typedef struct clingo_ast_aggregate_guard { + clingo_ast_comparison_operator_t comparison; + clingo_ast_term_t term; +} clingo_ast_aggregate_guard_t; + +typedef struct clingo_ast_conditional_literal { + clingo_ast_literal_t literal; + clingo_ast_literal_t const *condition; + size_t size; +} clingo_ast_conditional_literal_t; + +// lparse-style aggregate + +typedef struct clingo_ast_aggregate { + clingo_ast_conditional_literal_t const *elements; + size_t size; + clingo_ast_aggregate_guard_t const *left_guard; + clingo_ast_aggregate_guard_t const *right_guard; +} clingo_ast_aggregate_t; + +// body aggregate + +typedef struct clingo_ast_body_aggregate_element { + clingo_ast_term_t *tuple; + size_t tuple_size; + clingo_ast_literal_t const *condition; + size_t condition_size; +} clingo_ast_body_aggregate_element_t; + +typedef struct clingo_ast_body_aggregate { + clingo_ast_aggregate_function_t function; + clingo_ast_body_aggregate_element_t const *elements; + size_t size; + clingo_ast_aggregate_guard_t const *left_guard; + clingo_ast_aggregate_guard_t const *right_guard; +} clingo_ast_body_aggregate_t; + +// head aggregate + +typedef struct clingo_ast_head_aggregate_element { + clingo_ast_term_t const *tuple; + size_t tuple_size; + clingo_ast_conditional_literal_t conditional_literal; +} clingo_ast_head_aggregate_element_t; + +typedef struct clingo_ast_head_aggregate { + clingo_ast_aggregate_function_t function; + clingo_ast_head_aggregate_element_t const *elements; + size_t size; + clingo_ast_aggregate_guard_t const *left_guard; + clingo_ast_aggregate_guard_t const *right_guard; +} clingo_ast_head_aggregate_t; + +// disjunction + +typedef struct clingo_ast_disjunction { + clingo_ast_conditional_literal_t const *elements; + size_t size; +} clingo_ast_disjunction_t; + +// disjoint + +typedef struct clingo_ast_disjoint_element { + clingo_location_t location; + clingo_ast_term_t const *tuple; + size_t tuple_size; + clingo_ast_csp_sum_term_t term; + clingo_ast_literal_t const *condition; + size_t condition_size; +} clingo_ast_disjoint_element_t; + +typedef struct clingo_ast_disjoint { + clingo_ast_disjoint_element_t const *elements; + size_t size; +} clingo_ast_disjoint_t; + +// {{{2 theory atom + +enum clingo_ast_theory_term_type { + clingo_ast_theory_term_type_symbol = 0, + clingo_ast_theory_term_type_variable = 1, + clingo_ast_theory_term_type_tuple = 2, + clingo_ast_theory_term_type_list = 3, + clingo_ast_theory_term_type_set = 4, + clingo_ast_theory_term_type_function = 5, + clingo_ast_theory_term_type_unparsed_term = 6 +}; +typedef int clingo_ast_theory_term_type_t; + +typedef struct clingo_ast_theory_function clingo_ast_theory_function_t; +typedef struct clingo_ast_theory_term_array clingo_ast_theory_term_array_t; +typedef struct clingo_ast_theory_unparsed_term clingo_ast_theory_unparsed_term_t; + +typedef struct clingo_ast_theory_term { + clingo_location_t location; + clingo_ast_theory_term_type_t type; + union { + clingo_symbol_t symbol; + char const *variable; + clingo_ast_theory_term_array_t const *tuple; + clingo_ast_theory_term_array_t const *list; + clingo_ast_theory_term_array_t const *set; + clingo_ast_theory_function_t const *function; + clingo_ast_theory_unparsed_term_t const *unparsed_term; + }; +} clingo_ast_theory_term_t; + +struct clingo_ast_theory_term_array { + clingo_ast_theory_term_t const *terms; + size_t size; +}; + +struct clingo_ast_theory_function { + char const *name; + clingo_ast_theory_term_t const *arguments; + size_t size; +}; + +typedef struct clingo_ast_theory_unparsed_term_element { + char const *const *operators; + size_t size; + clingo_ast_theory_term_t term; +} clingo_ast_theory_unparsed_term_element_t; + +struct clingo_ast_theory_unparsed_term { + clingo_ast_theory_unparsed_term_element_t const *elements; + size_t size; +}; + +typedef struct clingo_ast_theory_atom_element { + clingo_ast_theory_term_t const *tuple; + size_t tuple_size; + clingo_ast_literal_t const *condition; + size_t condition_size; +} clingo_ast_theory_atom_element_t; + +typedef struct clingo_ast_theory_guard { + char const *operator_name; + clingo_ast_theory_term_t term; +} clingo_ast_theory_guard_t; + +typedef struct clingo_ast_theory_atom { + clingo_ast_term_t term; + clingo_ast_theory_atom_element_t const *elements; + size_t size; + clingo_ast_theory_guard_t const *guard; +} clingo_ast_theory_atom_t; + +// {{{2 head literals + +enum clingo_ast_head_literal_type { + clingo_ast_head_literal_type_literal = 0, + clingo_ast_head_literal_type_disjunction = 1, + clingo_ast_head_literal_type_aggregate = 2, + clingo_ast_head_literal_type_head_aggregate = 3, + clingo_ast_head_literal_type_theory_atom = 4 +}; +typedef int clingo_ast_head_literal_type_t; + +typedef struct clingo_ast_head_literal { + clingo_location_t location; + clingo_ast_head_literal_type_t type; + union { + clingo_ast_literal_t const *literal; + clingo_ast_disjunction_t const *disjunction; + clingo_ast_aggregate_t const *aggregate; + clingo_ast_head_aggregate_t const *head_aggregate; + clingo_ast_theory_atom_t const *theory_atom; + }; +} clingo_ast_head_literal_t; + +// {{{2 body literals + +enum clingo_ast_body_literal_type { + clingo_ast_body_literal_type_literal = 0, + clingo_ast_body_literal_type_conditional = 1, + clingo_ast_body_literal_type_aggregate = 2, + clingo_ast_body_literal_type_body_aggregate = 3, + clingo_ast_body_literal_type_theory_atom = 4, + clingo_ast_body_literal_type_disjoint = 5 +}; +typedef int clingo_ast_body_literal_type_t; + +typedef struct clingo_ast_body_literal { + clingo_location_t location; + clingo_ast_sign_t sign; + clingo_ast_body_literal_type_t type; + union { + clingo_ast_literal_t const *literal; + // Note: conditional literals must not have signs!!! + clingo_ast_conditional_literal_t const *conditional; + clingo_ast_aggregate_t const *aggregate; + clingo_ast_body_aggregate_t const *body_aggregate; + clingo_ast_theory_atom_t const *theory_atom; + clingo_ast_disjoint_t const *disjoint; + }; +} clingo_ast_body_literal_t; + +// {{{2 theory definitions + +enum clingo_ast_theory_operator_type { + clingo_ast_theory_operator_type_unary = 0, + clingo_ast_theory_operator_type_binary_left = 1, + clingo_ast_theory_operator_type_binary_right = 2 +}; +typedef int clingo_ast_theory_operator_type_t; + +typedef struct clingo_ast_theory_operator_definition { + clingo_location_t location; + char const *name; + unsigned priority; + clingo_ast_theory_operator_type_t type; +} clingo_ast_theory_operator_definition_t; + +typedef struct clingo_ast_theory_term_definition { + clingo_location_t location; + char const *name; + clingo_ast_theory_operator_definition_t const *operators; + size_t size; +} clingo_ast_theory_term_definition_t; + +typedef struct clingo_ast_theory_guard_definition { + char const *term; + char const *const *operators; + size_t size; +} clingo_ast_theory_guard_definition_t; + +enum clingo_ast_theory_atom_definition_type { + clingo_ast_theory_atom_definition_type_head = 0, + clingo_ast_theory_atom_definition_type_body = 1, + clingo_ast_theory_atom_definition_type_any = 2, + clingo_ast_theory_atom_definition_type_directive = 3, +}; +typedef int clingo_ast_theory_atom_definition_type_t; + +typedef struct clingo_ast_theory_atom_definition { + clingo_location_t location; + clingo_ast_theory_atom_definition_type_t type; + char const *name; + unsigned arity; + char const *elements; + clingo_ast_theory_guard_definition_t const *guard; +} clingo_ast_theory_atom_definition_t; + +typedef struct clingo_ast_theory_definition { + char const *name; + clingo_ast_theory_term_definition_t const *terms; + size_t terms_size; + clingo_ast_theory_atom_definition_t const *atoms; + size_t atoms_size; +} clingo_ast_theory_definition_t; + +// {{{2 statements + +// rule + +typedef struct clingo_ast_rule { + clingo_ast_head_literal_t head; + clingo_ast_body_literal_t const *body; + size_t size; +} clingo_ast_rule_t; + +// definition + +typedef struct clingo_ast_definition { + char const *name; + clingo_ast_term_t value; + bool is_default; +} clingo_ast_definition_t; + +// show + +typedef struct clingo_ast_show_signature { + clingo_signature_t signature; + bool csp; +} clingo_ast_show_signature_t; + +typedef struct clingo_ast_show_term { + clingo_ast_term_t term; + clingo_ast_body_literal_t const *body; + size_t size; + bool csp; +} clingo_ast_show_term_t; + +// minimize + +typedef struct clingo_ast_minimize { + clingo_ast_term_t weight; + clingo_ast_term_t priority; + clingo_ast_term_t const *tuple; + size_t tuple_size; + clingo_ast_body_literal_t const *body; + size_t body_size; +} clingo_ast_minimize_t; + +// script + +enum clingo_ast_script_type { + clingo_ast_script_type_lua = 0, + clingo_ast_script_type_python = 1 +}; +typedef int clingo_ast_script_type_t; + +typedef struct clingo_ast_script { + clingo_ast_script_type_t type; + char const *code; +} clingo_ast_script_t; + +// program + +typedef struct clingo_ast_program { + char const *name; + clingo_ast_id_t const *parameters; + size_t size; +} clingo_ast_program_t; + +// external + +typedef struct clingo_ast_external { + clingo_ast_term_t atom; + clingo_ast_body_literal_t const *body; + size_t size; +} clingo_ast_external_t; + +// edge + +typedef struct clingo_ast_edge { + clingo_ast_term_t u; + clingo_ast_term_t v; + clingo_ast_body_literal_t const *body; + size_t size; +} clingo_ast_edge_t; + +// heuristic + +typedef struct clingo_ast_heuristic { + clingo_ast_term_t atom; + clingo_ast_body_literal_t const *body; + size_t size; + clingo_ast_term_t bias; + clingo_ast_term_t priority; + clingo_ast_term_t modifier; +} clingo_ast_heuristic_t; + +// project + +typedef struct clingo_ast_project { + clingo_ast_term_t atom; + clingo_ast_body_literal_t const *body; + size_t size; +} clingo_ast_project_t; + +// statement + +enum clingo_ast_statement_type { + clingo_ast_statement_type_rule = 0, + clingo_ast_statement_type_const = 1, + clingo_ast_statement_type_show_signature = 2, + clingo_ast_statement_type_show_term = 3, + clingo_ast_statement_type_minimize = 4, + clingo_ast_statement_type_script = 5, + clingo_ast_statement_type_program = 6, + clingo_ast_statement_type_external = 7, + clingo_ast_statement_type_edge = 8, + clingo_ast_statement_type_heuristic = 9, + clingo_ast_statement_type_project_atom = 10, + clingo_ast_statement_type_project_atom_signature = 11, + clingo_ast_statement_type_theory_definition = 12 +}; +typedef int clingo_ast_statement_type_t; + +typedef struct clingo_ast_statement { + clingo_location_t location; + clingo_ast_statement_type_t type; + union { + clingo_ast_rule_t const *rule; + clingo_ast_definition_t const *definition; + clingo_ast_show_signature_t const *show_signature; + clingo_ast_show_term_t const *show_term; + clingo_ast_minimize_t const *minimize; + clingo_ast_script_t const *script; + clingo_ast_program_t const *program; + clingo_ast_external_t const *external; + clingo_ast_edge_t const *edge; + clingo_ast_heuristic_t const *heuristic; + clingo_ast_project_t const *project_atom; + clingo_signature_t project_signature; + clingo_ast_theory_definition_t const *theory_definition; + }; +} clingo_ast_statement_t; + +// }}}2 + +typedef bool clingo_ast_callback_t (clingo_ast_statement_t const *, void *); +//! Parse the given program and return an abstract syntax tree for each statement via a callback. +//! +//! @param[in] program the program in gringo syntax +//! @param[in] callback the callback reporting statements +//! @param[in] callback_data user data for the callback +//! @param[in] logger callback to report messages during parsing +//! @param[in] logger_data user data for the logger +//! @param[in] message_limit the maximum number of times the logger is called +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if parsing fails +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_parse_program(char const *program, clingo_ast_callback_t *callback, void *callback_data, clingo_logger_t *logger, void *logger_data, unsigned message_limit); + +//! @} + +// {{{1 program builder + +//! @addtogroup ProgramBuilder +//! @{ + +//! Object to build non-ground programs. +typedef struct clingo_program_builder clingo_program_builder_t; + +//! Begin building a program. +//! +//! @param builder the target program builder +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_program_builder_begin(clingo_program_builder_t *builder); +//! Adds a statement to the program. +//! +//! @attention @ref clingo_program_builder_begin() must be called before adding statements and @ref clingo_program_builder_end() must be called after all statements have been added. +//! @param builder the target program builder +//! @param statement the statement to add +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime for statements of invalid form +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_program_builder_add(clingo_program_builder_t *builder, clingo_ast_statement_t const *statement); +//! End building a program. +//! +//! @param builder the target program builder +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_program_builder_end(clingo_program_builder_t *builder); + +//! @} + +// {{{1 ground program observer + +//! @defgroup ProgramInspection Program Inspection +//! Functions and data structures to inspect programs. +//! @ingroup Control + +//! @addtogroup ProgramInspection +//! @{ + +//! An instance of this struct has to be registered with a solver to observe ground directives as they are passed to the solver. +//! +//! @note This interface is closely modeled after the aspif format. +//! For more information please refer to the specification of the aspif format. +//! +//! Not all callbacks have to be implemented and can be set to NULL if not needed. +//! If one of the callbacks in the struct fails, grounding is stopped. +//! If a non-recoverable clingo API call fails, a callback must return false. +//! Otherwise ::clingo_error_unknown should be set and false returned. +//! +//! @see clingo_control_register_observer() +typedef struct clingo_ground_program_observer { + //! Called once in the beginning. + //! + //! If the incremental flag is true, there can be multiple calls to @ref clingo_control_solve(). + //! + //! @param[in] incremental whether the program is incremental + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*init_program)(bool incremental, void *data); + //! Marks the beginning of a block of directives passed to the solver. + //! + //! @see @ref end_step + //! + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*begin_step)(void *data); + //! Marks the end of a block of directives passed to the solver. + //! + //! This function is called before solving starts. + //! + //! @see @ref begin_step + //! + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*end_step)(void *data); + + //! Observe rules passed to the solver. + //! + //! @param[in] choice determines if the head is a choice or a disjunction + //! @param[in] head the head atoms + //! @param[in] head_size the number of atoms in the head + //! @param[in] body the body literals + //! @param[in] body_size the number of literals in the body + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*rule)(bool choice, clingo_atom_t const *head, size_t head_size, clingo_literal_t const *body, size_t body_size, void *data); + //! Observe weight rules passed to the solver. + //! + //! @param[in] choice determines if the head is a choice or a disjunction + //! @param[in] head the head atoms + //! @param[in] head_size the number of atoms in the head + //! @param[in] lower_bound the lower bound of the weight rule + //! @param[in] body the weighted body literals + //! @param[in] body_size the number of weighted literals in the body + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*weight_rule)(bool choice, clingo_atom_t const *head, size_t head_size, clingo_weight_t lower_bound, clingo_weighted_literal_t const *body, size_t body_size, void *data); + //! Observe minimize constraints (or weak constraints) passed to the soler. + //! + //! @param[in] priority the priority of the constraint + //! @param[in] literals the weighted literals whose sum to minimize + //! @param[in] size the number of weighted literals + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*minimize)(clingo_weight_t priority, clingo_weighted_literal_t const* literals, size_t size, void *data); + //! Observe projection directives passed to the solver. + //! + //! @param[in] atoms the atoms to project on + //! @param[in] size the number of atoms + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*project)(clingo_atom_t const *atoms, size_t size, void *data); + //! Observe external statements passed to the solver. + //! + //! @param[in] atom the external atom + //! @param[in] type the type of the external statement + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*external)(clingo_atom_t atom, clingo_external_type_t type, void *data); + //! Observe assumption directives passed to the solver. + //! + //! @param[in] literals the literals to assume (positive literals are true and negative literals false for the next solve call) + //! @param[in] size the number of atoms + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*assume)(clingo_literal_t const *literals, size_t size, void *data); + //! Observe heuristic directives passed to the solver. + //! + //! @param[in] atom the target atom + //! @param[in] type the type of the heuristic modification + //! @param[in] bias the heuristic bias + //! @param[in] priority the heuristic priority + //! @param[in] condition the condition under which to apply the heuristic modification + //! @param[in] size the number of atoms in the condition + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*heuristic)(clingo_atom_t atom, clingo_heuristic_type_t type, int bias, unsigned priority, clingo_literal_t const *condition, size_t size, void *data); + //! Observe edge directives passed to the solver. + //! + //! @param[in] node_u the start vertex of the edge + //! @param[in] node_v the end vertex of the edge + //! @param[in] condition the condition under which the edge is part of the graph + //! @param[in] size the number of atoms in the condition + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*acyc_edge)(int node_u, int node_v, clingo_literal_t const *condition, size_t size, void *data); + + //! Observe numeric theory terms. + //! + //! @param[in] term_id the id of the term + //! @param[in] number the value of the term + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*theory_term_number)(clingo_id_t term_id, int number, void *data); + //! Observe string theory terms. + //! + //! @param[in] term_id the id of the term + //! @param[in] name the value of the term + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*theory_term_string)(clingo_id_t term_id, char const *name, void *data); + //! Observe compound theory terms. + //! + //! The name_id_or_type gives the type of the compound term: + //! - if it is -1, then it is a tuple + //! - if it is -2, then it is a set + //! - if it is -3, then it is a list + //! - otherwise, it is a function and name_id_or_type refers to the id of the name (in form of a string term) + //! + //! @param[in] term_id the id of the term + //! @param[in] name_id_or_type the name or type of the term + //! @param[in] arguments the arguments of the term + //! @param[in] size the number of arguments + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*theory_term_compound)(clingo_id_t term_id, int name_id_or_type, clingo_id_t const *arguments, size_t size, void *data); + //! Observe theory elements. + //! + //! @param element_id the id of the element + //! @param terms the term tuple of the element + //! @param terms_size the number of terms in the tuple + //! @param condition the condition of the elemnt + //! @param condition_size the number of literals in the condition + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*theory_element)(clingo_id_t element_id, clingo_id_t const *terms, size_t terms_size, clingo_literal_t const *condition, size_t condition_size, void *data); + //! Observe theory atoms without guard. + //! + //! @param[in] atom_id_or_zero the id of the atom or zero for directives + //! @param[in] term_id the term associated with the atom + //! @param[in] elements the elements of the atom + //! @param[in] size the number of elements + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*theory_atom)(clingo_id_t atom_id_or_zero, clingo_id_t term_id, clingo_id_t const *elements, size_t size, void *data); + //! Observe theory atoms with guard. + //! + //! @param[in] atom_id_or_zero the id of the atom or zero for directives + //! @param[in] term_id the term associated with the atom + //! @param[in] elements the elements of the atom + //! @param[in] size the number of elements + //! @param[in] operator_id the id of the operator (a string term) + //! @param[in] right_hand_side_id the id of the term on the right hand side of the atom + //! @param[in] data user data for the callback + //! @return whether the call was successful + bool (*theory_atom_with_guard)(clingo_id_t atom_id_or_zero, clingo_id_t term_id, clingo_id_t const *elements, size_t size, clingo_id_t operator_id, clingo_id_t right_hand_side_id, void *data); +} clingo_ground_program_observer_t; + +// @} + +// {{{1 control + +//! @example control.c +//! The example shows how to ground and solve a simple logic program, and print +//! its answer sets. +//! +//! ## Output ## +//! +//! ~~~~~~~~~~~~ +//! ./control 0 +//! Model: a +//! Model: b +//! ~~~~~~~~~~~~ +//! +//! ## Code ## + +//! @defgroup Control Grounding and Solving +//! Functions to control the grounding and solving process. +//! +//! For an example, see @ref control.c. + +//! @addtogroup Control +//! @{ + +//! @enum clingo_solve_result +//! Enumeration of bit masks for solve call results. +//! +//! @note Neither ::clingo_solve_result_satisfiable nor +//! ::clingo_solve_result_exhausted is set if the search is interrupted and no +//! model was found. +//! +//! @var clingo_solve_result::clingo_solve_result_satisfiable +//! The last solve call found a solution. +//! @var clingo_solve_result::clingo_solve_result_unsatisfiable +//! The last solve call did not find a solution. +//! @var clingo_solve_result::clingo_solve_result_exhausted +//! The last solve call completely exhausted the search space. +//! @var clingo_solve_result::clingo_solve_result_interrupted +//! The last solve call was interrupted. +//! +//! @see clingo_control_interrupt() + +//! @typedef clingo_solve_result_bitset_t +//! Corresponding type to ::clingo_solve_result. + +//! Control object holding grounding and solving state. +typedef struct clingo_control clingo_control_t; + +//! Struct used to specify the program parts that have to be grounded. +//! +//! Programs may be structured into parts, which can be grounded independently with ::clingo_control_ground. +//! Program parts are mainly interesting for incremental grounding and multi-shot solving. +//! For single-shot solving, program parts are not needed. +//! +//! @note Parts of a logic program without an explicit \#program +//! specification are by default put into a program called `base` without +//! arguments. +//! +//! @see clingo_control_ground() +typedef struct clingo_part { + char const *name; //!< name of the program part + clingo_symbol_t const *params; //!< array of parameters + size_t size; //!< number of parameters +} clingo_part_t; + +//! Callback function to inject symbols. +//! +//! @param symbols array of symbols +//! @param symbols_size size of the symbol array +//! @param data user data of the callback +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! @see ::clingo_ground_callback_t +typedef bool clingo_symbol_callback_t (clingo_symbol_t const *symbols, size_t symbols_size, void *data); + +//! Callback function to implement external functions. +//! +//! If an external function of form \@name(parameters) occurs in a logic program, +//! then this function is called with its location, name, parameters, and a callback to inject symbols as arguments. +//! The callback can be called multiple times; all symbols passed are injected. +//! +//! If a (non-recoverable) clingo API function fails in this callback, for example, the symbol callback, the callback must return false. +//! In case of errors not related to clingo, this function can set error ::clingo_error_unknown and return false to stop grounding with an error. +//! +//! @param[in] location location from which the external function was called +//! @param[in] name name of the called external function +//! @param[in] arguments arguments of the called external function +//! @param[in] arguments_size number of arguments +//! @param[in] data user data of the callback +//! @param[in] symbol_callback function to inject symbols +//! @param[in] symbol_callback_data user data for the symbol callback +//! (must be passed untouched) +//! @return whether the call was successful +//! @see clingo_control_ground() +//! +//! The following example implements the external function \@f() returning 42. +//! ~~~~~~~~~~~~~~~{.c} +//! bool +//! ground_callback(clingo_location_t location, +//! char const *name, +//! clingo_symbol_t const *arguments, +//! size_t arguments_size, +//! void *data, +//! clingo_symbol_callback_t *symbol_callback, +//! void *symbol_callback_data) { +//! if (strcmp(name, "f") == 0 && arguments_size == 0) { +//! clingo_symbol_t sym; +//! clingo_symbol_create_number(42, &sym); +//! return symbol_callback(&sym, 1, symbol_callback_data); +//! } +//! clingo_set_error(clingo_error_runtime, "function not found"); +//! return false; +//! } +//! ~~~~~~~~~~~~~~~ +typedef bool clingo_ground_callback_t (clingo_location_t location, char const *name, clingo_symbol_t const *arguments, size_t arguments_size, void *data, clingo_symbol_callback_t *symbol_callback, void *symbol_callback_data); + +//! Callback function to intercept models. +//! +//! The model callback is invoked once for each model found by clingo (@link SolveAsync asynchronously@endlink). +//! +//! If a (non-recoverable) clingo API function fails in this callback, the function must return false. +//! In case of errors not related to clingo, the function can set error code ::clingo_error_unknown can be set and return false to stop solving with an error. +//! +//! @param[in] model the current model +//! @param[in] data user data of the callback +//! @param[out] goon whether to continue search +//! @return whether the call was successful +//! +//! @see clingo_control_solve() +//! @see clingo_control_solve_async() +typedef bool clingo_model_callback_t (clingo_model_t *model, void *data, bool *goon); + +//! Callback function called at the end of an asynchronous solve operation. +//! +//! If a (non-recoverable) clingo API function fails in this callback, it must return false. +//! In case of errors not related to clingo, set error code ::clingo_error_unknown and return false to stop solving with an error. +//! +//! @param[in] result result of the solve call +//! @param[in] data user data of the callback +//! @return whether the call was successful +//! +//! @see clingo_control_solve_async() +typedef bool clingo_finish_callback_t (clingo_solve_result_bitset_t result, void *data); + +//! Create a new control object. +//! +//! A control object has to be freed using clingo_control_free(). +//! +//! @note Only gringo options (without \-\-output) and clasp's options are supported as arguments, +//! except basic options such as \-\-help. +//! Furthermore, a control object is blocked while a search call is active; +//! you must not call any member function during search. +//! +//! If the logger is NULL, messages are printed to stderr. +//! +//! @param[in] arguments C string array of command line arguments +//! @param[in] arguments_size size of the arguments array +//! @param[in] logger callback functions for warnings and info messages +//! @param[in] logger_data user data for the logger callback +//! @param[in] message_limit maximum number of times the logger callback is called +//! @param[out] control resulting control object +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if argument parsing fails +CLINGO_VISIBILITY_DEFAULT bool clingo_control_new(char const *const * arguments, size_t arguments_size, clingo_logger_t *logger, void *logger_data, unsigned message_limit, clingo_control_t **control); + +//! Free a control object created with clingo_control_new(). +//! @param[in] control the target +CLINGO_VISIBILITY_DEFAULT void clingo_control_free(clingo_control_t *control); + +//! @name Grounding Functions +//! @{ + +//! Extend the logic program with a program in a file. +//! +//! @param[in] control the target +//! @param[in] file path to the file +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if parsing or checking fails +CLINGO_VISIBILITY_DEFAULT bool clingo_control_load(clingo_control_t *control, char const *file); + +//! Extend the logic program with the given non-ground logic program in string form. +//! +//! This function puts the given program into a block of form: \#program name(parameters). +//! +//! After extending the logic program, the corresponding program parts are typically grounded with ::clingo_control_ground. +//! +//! @param[in] control the target +//! @param[in] name name of the program block +//! @param[in] parameters string array of parameters of the program block +//! @param[in] parameters_size number of parameters +//! @param[in] program string representation of the program +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if parsing fails +CLINGO_VISIBILITY_DEFAULT bool clingo_control_add(clingo_control_t *control, char const *name, char const * const * parameters, size_t parameters_size, char const *program); + +//! Ground the selected @link ::clingo_part parts @endlink of the current (non-ground) logic program. +//! +//! After grounding, logic programs can be solved with ::clingo_control_solve. +//! +//! @note Parts of a logic program without an explicit \#program +//! specification are by default put into a program called `base` without +//! arguments. +//! +//! @param[in] control the target +//! @param[in] parts array of parts to ground +//! @param[in] parts_size size of the parts array +//! @param[in] ground_callback callback to implement external functions +//! @param[in] ground_callback_data user data for ground_callback +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - error code of ground callback +//! +//! @see clingo_part +CLINGO_VISIBILITY_DEFAULT bool clingo_control_ground(clingo_control_t *control, clingo_part_t const *parts, size_t parts_size, clingo_ground_callback_t *ground_callback, void *ground_callback_data); + +//! @} + +//! @name Solving Functions +//! @{ + +//! Solve the currently @link ::clingo_control_ground grounded @endlink logic program. +//! +//! @param[in] control the target +//! @param[in] model_callback optional callback to intercept models +//! @param[in] model_callback_data user data for model callback +//! @param[in] assumptions array of assumptions to solve under +//! @param[in] assumptions_size number of assumptions +//! @param[out] result the result of the search +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving fails +//! - error code of model callback +CLINGO_VISIBILITY_DEFAULT bool clingo_control_solve(clingo_control_t *control, clingo_model_callback_t *model_callback, void *model_callback_data, clingo_symbolic_literal_t const * assumptions, size_t assumptions_size, clingo_solve_result_bitset_t *result); +//! Solve the currently @link ::clingo_control_ground grounded @endlink logic program enumerating models iteratively. +//! +//! See the @ref SolveIter module for more information. +//! +//! @param[in] control the target +//! @param[in] assumptions array of assumptions to solve under +//! @param[in] assumptions_size number of assumptions +//! @param[out] handle handle to the current search to enumerate models +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving could not be started +CLINGO_VISIBILITY_DEFAULT bool clingo_control_solve_iteratively(clingo_control_t *control, clingo_symbolic_literal_t const *assumptions, size_t assumptions_size, clingo_solve_iteratively_t **handle); +//! Solve the currently @link ::clingo_control_ground grounded @endlink logic program asynchronously in the background. +//! +//! See the @ref SolveAsync module for more information. +//! +//! @param[in] control the target +//! @param[in] model_callback optional callback to intercept models +//! @param[in] model_callback_data user data for model callback +//! @param[in] finish_callback optional callback called just before the end of the search +//! @param[in] finish_callback_data user data for finish callback +//! @param[in] assumptions array of assumptions to solve under +//! @param[in] assumptions_size number of assumptions +//! @param[out] handle handle to the current search +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +//! - ::clingo_error_runtime if solving could not be started +CLINGO_VISIBILITY_DEFAULT bool clingo_control_solve_async(clingo_control_t *control, clingo_model_callback_t *model_callback, void *model_callback_data, clingo_finish_callback_t *finish_callback, void *finish_callback_data, clingo_symbolic_literal_t const * assumptions, size_t assumptions_size, clingo_solve_async_t **handle); +//! Clean up the domains of clingo's grounding component using the solving +//! component's top level assignment. +//! +//! This function removes atoms from domains that are false and marks atoms as +//! facts that are true. With multi-shot solving, this can result in smaller +//! groundings because less rules have to be instantiated and more +//! simplifications can be applied. +//! +//! @param[in] control the target +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_control_cleanup(clingo_control_t *control); +//! Assign a truth value to an external atom. +//! +//! If the atom does not exist or is not external, this is a noop. +//! +//! @param[in] control the target +//! @param[in] atom atom to assign +//! @param[in] value the truth value +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_control_assign_external(clingo_control_t *control, clingo_symbol_t atom, clingo_truth_value_t value); +//! Release an external atom. +//! +//! After this call, an external atom is no longer external and subject to +//! program simplifications. If the atom does not exist or is not external, +//! this is a noop. +//! +//! @param[in] control the target +//! @param[in] atom atom to release +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_control_release_external(clingo_control_t *control, clingo_symbol_t atom); +//! Register a custom propagator with the control object. +//! +//! If the sequential flag is set to true, the propagator is called +//! sequentially when solving with multiple threads. +//! +//! See the @ref Propagator module for more information. +//! +//! @param[in] control the target +//! @param[in] propagator the propagator +//! @param[in] data user data passed to the propagator functions +//! @param[in] sequential whether the propagator should be called sequentially +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_control_register_propagator(clingo_control_t *control, clingo_propagator_t propagator, void *data, bool sequential); +//! Get a statistics object to inspect solver statistics. +//! +//! Statistics are updated after a solve call. +//! +//! See the @ref Statistics module for more information. +//! +//! @attention +//! The level of detail of the statistics depends on the stats option +//! (which can be set using @ref Configuration module or passed as an option when @link clingo_control_new creating the control object@endlink). +//! The default level zero only provides basic statistics, +//! level one provides extended and accumulated statistics, +//! and level two provides per-thread statistics. +//! +//! @param[in] control the target +//! @param[out] statistics the statistics object +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_control_statistics(clingo_control_t *control, clingo_statistics_t **statistics); +//! Interrupt the active solve call (or the following solve call right at the beginning). +//! +//! @param[in] control the target +CLINGO_VISIBILITY_DEFAULT void clingo_control_interrupt(clingo_control_t *control); +//! Get low-level access to clasp. +//! +//! @attention +//! This function is intended for experimental use only and not part of the stable API. +//! +//! This function may return a nullptr. +//! Otherwise, the returned pointer can be casted to a ClaspFacade pointer. +//! +//! @param[in] control the target +//! @param[out] clasp pointer to the ClaspFacade object (may be nullptr) +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_clasp_facade(clingo_control_t *control, void **clasp); + +//! @} + +//! @name Configuration Functions +//! @{ + +//! Get a configuration object to change the solver configuration. +//! +//! See the @ref Configuration module for more information. +//! +//! @param[in] control the target +//! @param[out] configuration the configuration object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_configuration(clingo_control_t *control, clingo_configuration_t **configuration); +//! Configure how learnt constraints are handled during enumeration. +//! +//! If the enumeration assumption is enabled, then all information learnt from +//! the solver's various enumeration modes is removed after a solve call. This +//! includes enumeration of cautious or brave consequences, enumeration of +//! answer sets with or without projection, or finding optimal models, as well +//! as clauses added with clingo_solve_control_add_clause(). +//! +//! @attention For practical purposes, this option is only interesting for single-shot solving +//! or before the last solve call to squeeze out a tiny bit of performance. +//! Initially, the enumeration assumption is enabled. +//! +//! @param[in] control the target +//! @param[in] enable whether to enable the assumption +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_use_enumeration_assumption(clingo_control_t *control, bool enable); +//! @} + +//! @name Program Inspection Functions +//! @{ + +//! Return the symbol for a constant definition of form: \#const name = symbol. +//! +//! @param[in] control the target +//! @param[in] name the name of the constant +//! @param[out] symbol the resulting symbol +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_get_const(clingo_control_t *control, char const *name, clingo_symbol_t *symbol); +//! Check if there is a constant definition for the given constant. +//! +//! @param[in] control the target +//! @param[in] name the name of the constant +//! @param[out] exists whether a matching constant definition exists +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_runtime if constant definition does not exist +//! +//! @see clingo_control_get_const() +CLINGO_VISIBILITY_DEFAULT bool clingo_control_has_const(clingo_control_t *control, char const *name, bool *exists); +//! Get an object to inspect symbolic atoms (the relevant Herbrand base) used +//! for grounding. +//! +//! See the @ref SymbolicAtoms module for more information. +//! +//! @param[in] control the target +//! @param[out] atoms the symbolic atoms object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_symbolic_atoms(clingo_control_t *control, clingo_symbolic_atoms_t **atoms); +//! Get an object to inspect theory atoms that occur in the grounding. +//! +//! See the @ref TheoryAtoms module for more information. +//! +//! @param[in] control the target +//! @param[out] atoms the theory atoms object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_theory_atoms(clingo_control_t *control, clingo_theory_atoms_t **atoms); +//! Register a program observer with the control object. +//! +//! @param[in] control the target +//! @param[in] observer the observer to register +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_register_observer(clingo_control_t *control, clingo_ground_program_observer_t observer, void *data); +//! @} + +//! @name Program Modification Functions +//! @{ + +//! Get an object to add ground directives to the program. +//! +//! See the @ref ProgramBuilder module for more information. +//! +//! @param[in] control the target +//! @param[out] backend the backend object +//! @return whether the call was successful; might set one of the following error codes: +//! - ::clingo_error_bad_alloc +CLINGO_VISIBILITY_DEFAULT bool clingo_control_backend(clingo_control_t *control, clingo_backend_t **backend); +//! Get an object to add non-ground directives to the program. +//! +//! See the @ref ProgramBuilder module for more information. +//! +//! @param[in] control the target +//! @param[out] builder the program builder object +//! @return whether the call was successful +CLINGO_VISIBILITY_DEFAULT bool clingo_control_program_builder(clingo_control_t *control, clingo_program_builder_t **builder); +//! @} + +//! @} + +// }}}1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libgringo/clingo.hh b/libgringo/clingo.hh new file mode 100644 index 0000000..24a2b9c --- /dev/null +++ b/libgringo/clingo.hh @@ -0,0 +1,2079 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef CLINGO_HH +#define CLINGO_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Clingo { + +// {{{1 basic types + +// consider using upper case +using literal_t = clingo_literal_t; +using id_t = clingo_id_t; +using weight_t = clingo_weight_t; +using atom_t = clingo_atom_t; + +enum class TruthValue { + Free = clingo_truth_value_free, + True = clingo_truth_value_true, + False = clingo_truth_value_false +}; + +inline std::ostream &operator<<(std::ostream &out, TruthValue tv) { + switch (tv) { + case TruthValue::Free: { out << "Free"; break; } + case TruthValue::True: { out << "True"; break; } + case TruthValue::False: { out << "False"; break; } + } + return out; +} + +// {{{1 variant + +namespace Detail { + +template +struct TypeInList : std::false_type { }; + +template +struct TypeInList : std::true_type { }; + +template +struct TypeInList : TypeInList { }; + +template +struct VariantHolder; + +template +struct VariantHolder { + bool check_type() const { return type_ == 0; } + void emplace() { } + void emplace2() { } + void copy(VariantHolder const &) { } + void destroy() { + type_ = 0; + data_ = nullptr; + } + void print(std::ostream &) const { } + void swap(VariantHolder &other) { + std::swap(type_, other.type_); + std::swap(data_, other.data_); + } + template + typename std::enable_if::value>::type copy_if_possible(void *src) { + data_ = new V(*static_cast(src)); + } + template + typename std::enable_if::value>::type copy_if_possible(void *) { + throw std::runtime_error("variant not copyable"); + } + unsigned type_ = 0; + void *data_ = nullptr; +}; + +template +struct VariantHolder : VariantHolder{ + using Helper = VariantHolder; + using Helper::check_type; + using Helper::emplace; + using Helper::emplace2; + using Helper::data_; + using Helper::type_; + bool check_type(T *) const { return type_ == n; } + template + void emplace(T *, Args&& ...x) { + data_ = new T{std::forward(x)...}; + type_ = n; + } + // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467 + template + void emplace2(T *, Args&& ...x) { + data_ = new T(std::forward(x)...); + type_ = n; + } + void copy(VariantHolder const &src) { + if (src.type_ == n) { + Helper::template copy_if_possible(src.data_); + type_ = src.type_; + } + Helper::copy(src); + } + // NOTE: workaround for visual studio (C++14 can also simply use auto) +# define GRINGO_VARIANT_RET(Type) decltype(std::declval().visit(std::declval(), std::declval()...)) + template + using Ret_ = GRINGO_VARIANT_RET(T); + template + using ConstRet_ = GRINGO_VARIANT_RET(T const); + // non-const + template + auto accept_(V &&visitor, Args &&... args) -> GRINGO_VARIANT_RET(T) { + static_assert(std::is_same, typename Helper::template Ret_>::value, ""); + return n == type_ + ? visitor.visit(*static_cast(data_), std::forward(args)...) + : Helper::template accept(std::forward(visitor), std::forward(args)...); + } + template + auto accept_(V &&visitor, Args &&... args) -> GRINGO_VARIANT_RET(T) { + assert(n == type_); + return visitor.visit(*static_cast(data_), std::forward(args)...); + } + template + auto accept(V &&visitor, Args &&... args) -> GRINGO_VARIANT_RET(T) { + return accept_(std::forward(visitor), std::forward(args)...); + } + // const + template + auto accept_(V &&visitor, Args &&... args) const -> GRINGO_VARIANT_RET(T const) { + static_assert(std::is_same, typename Helper::template ConstRet_>::value, ""); + return n == type_ + ? visitor.visit(*static_cast(data_), std::forward(args)...) + : Helper::template accept(std::forward(visitor), std::forward(args)...); + } + template + auto accept_(V &&visitor, Args &&... args) const -> GRINGO_VARIANT_RET(T const) { + assert(n == type_); + return visitor.visit(*static_cast(data_), std::forward(args)...); + } + template + auto accept(V &&visitor, Args &&... args) const -> GRINGO_VARIANT_RET(T const) { + return accept_(std::forward(visitor), std::forward(args)...); + } +# undef GRINGO_VARIANT_RET + void destroy() { + if (n == type_) { delete static_cast(data_); } + Helper::destroy(); + } + void print(std::ostream &out) const { + if (n == type_) { out << *static_cast(data_); } + Helper::print(out); + } +}; + +} // Detail + +template +class Optional { +public: + Optional() { } + Optional(T const &x) : data_(new T(x)) { } + Optional(T &x) : data_(new T(x)) { } + Optional(T &&x) : data_(new T(std::move(x))) { } + template + Optional(Args&&... x) : data_(new T{std::forward(x)...}) { } + Optional(Optional &&opt) : data_(opt.data_.release()) { } + Optional(Optional const &opt) : data_(opt ? new T(*opt.get()) : nullptr) { } + Optional &operator=(T const &x) { + clear(); + data_.reset(new T(x)); + } + Optional &operator=(T &x) { + clear(); + data_.reset(new T(x)); + } + Optional &operator=(T &&x) { + clear(); + data_.reset(new T(std::move(x))); + } + Optional &operator=(Optional &&opt) { + data_ = std::move(opt.data_); + } + Optional &operator=(Optional const &opt) { + clear(); + data_.reset(opt ? new T(*opt.get()) : nullptr); + } + T *get() { return data_.get(); } + T const *get() const { return data_.get(); } + T *operator->() { return get(); } + T const *operator->() const { return get(); } + template + void emplace(Args&&... x) { + clear(); + data_(new T{std::forward(x)...}); + } + void clear() { data_.reset(nullptr); } + explicit operator bool() const { return data_.get() != nullptr; } +private: + std::unique_ptr data_; +}; + +template +class Variant { + using Holder = Detail::VariantHolder<1, T...>; +public: + Variant(Variant const &other) : Variant(other.data_) { } + Variant(Variant &&other) { data_.swap(other.data_); } + template + Variant(U &&u, typename std::enable_if::value>::type * = nullptr) { emplace2(std::forward(u)); } + template + Variant(U &u, typename std::enable_if::value>::type * = nullptr) { emplace2(u); } + template + Variant(U const &u, typename std::enable_if::value>::type * = nullptr) { emplace2(u); } + template + static Variant make(Args&& ...args) { + Variant x; + x.data_.emplace(static_cast(nullptr), std::forward(args)...); + return std::move(x); + } + ~Variant() { data_.destroy(); } + Variant &operator=(Variant const &other) { return *this = other.data_; } + Variant &operator=(Variant &&other) { return *this = std::move(other.data_); } + template + typename std::enable_if::value, Variant>::type &operator=(U &&u) { + emplace2(std::forward(u)); + return *this; + } + template + typename std::enable_if::value, Variant>::type &operator=(U &u) { + emplace2(u); + return *this; + } + template + typename std::enable_if::value, Variant>::type &operator=(U const &u) { + emplace2(u); + return *this; + } + template + U &get() { + if (!data_.check_type(static_cast(nullptr))) { throw std::bad_cast(); } + return *static_cast(data_.data_); + } + template + U const &get() const { + if (!data_.check_type(static_cast(nullptr))) { throw std::bad_cast(); } + return *static_cast(data_.data_); + } + template + void emplace(Args&& ...args) { + Variant x; + x.data_.emplace(static_cast(nullptr), std::forward(args)...); + data_.swap(x.data_); + } + template + bool is() const { return data_.check_type(static_cast(nullptr)); } + void swap(Variant &other) { data_.swap(other.data_); } + template + typename Holder::template Ret_ accept(V &&visitor, Args &&... args) { + return data_.accept(std::forward(visitor), std::forward(args)...); + } + template + typename Holder::template ConstRet_ accept(V &&visitor, Args &&... args) const { + return data_.accept(std::forward(visitor), std::forward(args)...); + } + friend std::ostream &operator<<(std::ostream &out, Variant const &x) { + x.data_.print(out); + return out; + } + +private: + Variant() { } + Variant(Holder const &data) { + data_.copy(data); + } + Variant &operator=(Holder const &data) { + Variant x(data); + data_.swap(x.data_); + return *this; + } + Variant &operator=(Holder &&data) { + data_.swap(data); + data.destroy(); + return *this; + } + template + void emplace2(Args&& ...args) { + Variant x; + x.data_.emplace2(static_cast(nullptr), std::forward(args)...); + data_.swap(x.data_); + } + +private: + Holder data_; +}; + +// {{{1 span + +template +class IteratorRange { +public: + using reference = typename Iterator::reference; + using difference_type = typename Iterator::difference_type; + IteratorRange(Iterator begin, Iterator end) + : begin_(begin) + , end_(end) { } + reference operator[](difference_type n) { + auto it = begin_; + std::advance(it, n); + return *it; + } + difference_type size() { return std::distance(begin_, end_); } + bool empty() { return begin_ == end_; } + Iterator begin() { return begin_; } + Iterator end() { return end_; } +private: + Iterator begin_; + Iterator end_; +}; + +template +class ValuePointer { +public: + ValuePointer(T value) : value_(value) { } + T &operator*() { return value_; } + T *operator->() { return &value_; } +private: + T value_; +}; + +template +struct ToIterator { + T const *operator()(T const *x) const { return x; } +}; + +template > +class Span : private I { +public: + using IteratorType = typename std::result_of::type; + using ReferenceType = decltype(*std::declval()); + Span(I to_it = I()) + : Span(nullptr, size_t(0), to_it) { } + template + Span(U const *begin, size_t size) + : Span(static_cast(begin), size) { } + Span(T const *begin, size_t size, I to_it = I()) + : Span(begin, begin + size, to_it) { } + Span(std::initializer_list c, I to_it = I()) + : Span(c.size() > 0 ? &*c.begin() : nullptr, c.size(), to_it) { } + template + Span(U const &c, I to_it = I()) + : Span(c.size() > 0 ? &*c.begin() : nullptr, c.size(), to_it) { } + Span(T const *begin, T const *end, I to_it = I()) + : I(to_it) + , begin_(begin) + , end_(end) { } + IteratorType begin() const { return I::operator()(begin_); } + IteratorType end() const { return I::operator()(end_); } + ReferenceType operator[](size_t offset) const { return *(begin() + offset); } + ReferenceType front() const { return *begin(); } + ReferenceType back() const { return *I::operator()(end_-1); } + size_t size() const { return end_ - begin_; } + bool empty() const { return begin_ == end_; } +private: + T const *begin_; + T const *end_; +}; + +template +bool equal_range(T const &a, U const &b) { + using namespace std; + return a.size() == b.size() && std::equal(begin(a), end(a), begin(b)); +} + +template +bool operator==(Span span, V const &v) { return equal_range(span, v); } +template +bool operator==(V const &v, Span span) { return equal_range(span, v); } + +template +std::ostream &operator<<(std::ostream &out, Span span) { + out << "{"; + bool comma = false; + for (auto &x : span) { + if (comma) { out << ", "; } + else { out << " "; } + out << x; + comma = true; + } + out << " }"; + return out; +} + +// {{{1 signature + +class CLINGO_VISIBILITY_DEFAULT Signature { +public: + explicit Signature(clingo_signature_t sig) + : sig_(sig) { } + Signature(char const *name, uint32_t arity, bool positive = true); + char const *name() const; + uint32_t arity() const; + bool positive() const; + bool negative() const; + size_t hash() const; + + clingo_signature_t const &to_c() const { return sig_; } + clingo_signature_t &to_c() { return sig_; } +private: + clingo_signature_t sig_; +}; + +inline std::ostream &operator<<(std::ostream &out, Signature sig) { + out << (sig.negative() ? "-" : "") << sig.name() << "/" << sig.arity(); + return out; +} +CLINGO_VISIBILITY_DEFAULT bool operator==(Signature a, Signature b); +CLINGO_VISIBILITY_DEFAULT bool operator!=(Signature a, Signature b); +CLINGO_VISIBILITY_DEFAULT bool operator< (Signature a, Signature b); +CLINGO_VISIBILITY_DEFAULT bool operator<=(Signature a, Signature b); +CLINGO_VISIBILITY_DEFAULT bool operator> (Signature a, Signature b); +CLINGO_VISIBILITY_DEFAULT bool operator>=(Signature a, Signature b); + +} namespace std { + +template<> +struct hash { + size_t operator()(Clingo::Signature sig) const { return sig.hash(); } +}; + +} namespace Clingo { + +// {{{1 symbol + +enum class SymbolType : clingo_symbol_type_t { + Infimum = clingo_symbol_type_infimum, + Number = clingo_symbol_type_number, + String = clingo_symbol_type_string, + Function = clingo_symbol_type_function, + Supremum = clingo_symbol_type_supremum +}; + +class Symbol; +using SymbolSpan = Span; +using SymbolVector = std::vector; + +class CLINGO_VISIBILITY_DEFAULT Symbol { +public: + Symbol(); + explicit Symbol(clingo_symbol_t); + int number() const; + char const *name() const; + char const *string() const; + bool is_positive() const; + bool is_negative() const; + SymbolSpan arguments() const; + SymbolType type() const; + std::string to_string() const; + size_t hash() const; + clingo_symbol_t &to_c() { return sym_; } + clingo_symbol_t const &to_c() const { return sym_; } +private: + clingo_symbol_t sym_; +}; + +CLINGO_VISIBILITY_DEFAULT Symbol Number(int num); +CLINGO_VISIBILITY_DEFAULT Symbol Supremum(); +CLINGO_VISIBILITY_DEFAULT Symbol Infimum(); +CLINGO_VISIBILITY_DEFAULT Symbol String(char const *str); +CLINGO_VISIBILITY_DEFAULT Symbol Id(char const *str, bool positive = true); +CLINGO_VISIBILITY_DEFAULT Symbol Function(char const *name, SymbolSpan args, bool positive = true); + +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Symbol sym); +CLINGO_VISIBILITY_DEFAULT bool operator==(Symbol a, Symbol b); +CLINGO_VISIBILITY_DEFAULT bool operator!=(Symbol a, Symbol b); +CLINGO_VISIBILITY_DEFAULT bool operator< (Symbol a, Symbol b); +CLINGO_VISIBILITY_DEFAULT bool operator<=(Symbol a, Symbol b); +CLINGO_VISIBILITY_DEFAULT bool operator> (Symbol a, Symbol b); +CLINGO_VISIBILITY_DEFAULT bool operator>=(Symbol a, Symbol b); + +} namespace std { + +template<> +struct hash { + size_t operator()(Clingo::Symbol sym) const { return sym.hash(); } +}; + +} namespace Clingo { + +// {{{1 symbolic atoms + +class CLINGO_VISIBILITY_DEFAULT SymbolicAtom { + friend class SymbolicAtomIterator; +public: + explicit SymbolicAtom(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t range) + : atoms_(atoms) + , range_(range) { } + Symbol symbol() const; + literal_t literal() const; + bool is_fact() const; + bool is_external() const; + clingo_symbolic_atom_iterator_t to_c() const { return range_; } +private: + clingo_symbolic_atoms_t *atoms_; + clingo_symbolic_atom_iterator_t range_; +}; + +class CLINGO_VISIBILITY_DEFAULT SymbolicAtomIterator : private SymbolicAtom, public std::iterator { +public: + explicit SymbolicAtomIterator(clingo_symbolic_atoms_t *atoms, clingo_symbolic_atom_iterator_t range) + : SymbolicAtom{atoms, range} { } + SymbolicAtom &operator*() { return *this; } + SymbolicAtom *operator->() { return this; } + SymbolicAtomIterator &operator++(); + SymbolicAtomIterator operator++ (int) { + auto range = range_; + ++(*this); + return SymbolicAtomIterator{atoms_, range}; + } + bool operator==(SymbolicAtomIterator it) const; + bool operator!=(SymbolicAtomIterator it) const { return !(*this == it); } + explicit operator bool() const; + clingo_symbolic_atom_iterator_t to_c() const { return range_; } +}; + +class CLINGO_VISIBILITY_DEFAULT SymbolicAtoms { +public: + explicit SymbolicAtoms(clingo_symbolic_atoms_t *atoms) + : atoms_(atoms) { } + SymbolicAtomIterator begin() const; + SymbolicAtomIterator begin(Signature sig) const; + SymbolicAtomIterator end() const; + SymbolicAtomIterator find(Symbol atom) const; + std::vector signatures() const; + size_t length() const; + clingo_symbolic_atoms_t* to_c() const { return atoms_; } + SymbolicAtom operator[](Symbol atom) { return *find(atom); } +private: + clingo_symbolic_atoms_t *atoms_; +}; + +// {{{1 theory atoms + +enum class TheoryTermType : clingo_theory_term_type_t { + Tuple = clingo_theory_term_type_tuple, + List = clingo_theory_term_type_list, + Set = clingo_theory_term_type_set, + Function = clingo_theory_term_type_function, + Number = clingo_theory_term_type_number, + Symbol = clingo_theory_term_type_symbol +}; + +template +class TheoryIterator : public std::iterator { +public: + using base = std::iterator; + using difference_type = typename base::difference_type; + explicit TheoryIterator(clingo_theory_atoms_t *atoms, clingo_id_t const* id) + : elem_(atoms) + , id_(id) { } + TheoryIterator& operator++() { ++id_; return *this; } + TheoryIterator operator++(int) { + TheoryIterator t(*this); + ++*this; + return t; + } + TheoryIterator& operator--() { --id_; return *this; } + TheoryIterator operator--(int) { + TheoryIterator t(*this); + --*this; + return t; + } + TheoryIterator& operator+=(difference_type n) { id_ += n; return *this; } + TheoryIterator& operator-=(difference_type n) { id_ -= n; return *this; } + friend TheoryIterator operator+(TheoryIterator it, difference_type n) { return TheoryIterator{it.atoms(), it.id_ + n}; } + friend TheoryIterator operator+(difference_type n, TheoryIterator it) { return TheoryIterator{it.atoms(), it.id_ + n}; } + friend TheoryIterator operator-(TheoryIterator it, difference_type n) { return TheoryIterator{it.atoms(), it.id_ - n}; } + friend difference_type operator-(TheoryIterator a, TheoryIterator b) { return a.id_ - b.id_; } + T operator*() { return elem_ = *id_; } + T *operator->() { return &(elem_ = *id_); } + friend void swap(TheoryIterator& lhs, TheoryIterator& rhs) { + std::swap(lhs.id_, rhs.id_); + std::swap(lhs.elem_, rhs.elem_); + } + friend bool operator==(const TheoryIterator& lhs, const TheoryIterator& rhs) { return lhs.id_ == rhs.id_; } + friend bool operator!=(const TheoryIterator& lhs, const TheoryIterator& rhs) { return !(lhs == rhs); } + friend bool operator< (TheoryIterator lhs, TheoryIterator rhs) { return lhs.id_ < rhs.id_; } + friend bool operator> (TheoryIterator lhs, TheoryIterator rhs) { return rhs < lhs; } + friend bool operator<=(TheoryIterator lhs, TheoryIterator rhs) { return !(lhs > rhs); } + friend bool operator>=(TheoryIterator lhs, TheoryIterator rhs) { return !(lhs < rhs); } +private: + clingo_theory_atoms_t *&atoms() { return elem_.atoms_; } +private: + T elem_; + clingo_id_t const *id_; +}; + +template +class ToTheoryIterator { +public: + explicit ToTheoryIterator(clingo_theory_atoms_t *atoms) + : atoms_(atoms) { } + T operator ()(clingo_id_t const *id) const { + return T{atoms_, id}; + } +private: + clingo_theory_atoms_t *atoms_; +}; + +class TheoryTerm; +using TheoryTermIterator = TheoryIterator; +using TheoryTermSpan = Span>; + +class CLINGO_VISIBILITY_DEFAULT TheoryTerm { + friend class TheoryIterator; +public: + explicit TheoryTerm(clingo_theory_atoms_t *atoms, clingo_id_t id) + : atoms_(atoms) + , id_(id) { } + TheoryTermType type() const; + int number() const; + char const *name() const; + TheoryTermSpan arguments() const; + clingo_id_t to_c() const { return id_; } + std::string to_string() const; +private: + TheoryTerm(clingo_theory_atoms_t *atoms) + : TheoryTerm(atoms, 0) { } + TheoryTerm &operator=(clingo_id_t id) { + id_ = id; + return *this; + } +private: + clingo_theory_atoms_t *atoms_; + clingo_id_t id_; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryTerm term); + +class TheoryElement; +using TheoryElementIterator = TheoryIterator; +using TheoryElementSpan = Span>; +using LiteralSpan = Span; + +class CLINGO_VISIBILITY_DEFAULT TheoryElement { + friend class TheoryIterator; +public: + explicit TheoryElement(clingo_theory_atoms_t *atoms, clingo_id_t id) + : atoms_(atoms) + , id_(id) { } + TheoryTermSpan tuple() const; + LiteralSpan condition() const; + literal_t condition_id() const; + std::string to_string() const; + clingo_id_t to_c() const { return id_; } +private: + TheoryElement(clingo_theory_atoms_t *atoms) + : TheoryElement(atoms, 0) { } + TheoryElement &operator=(clingo_id_t id) { + id_ = id; + return *this; + } +private: + clingo_theory_atoms_t *atoms_; + clingo_id_t id_; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryElement term); + +class CLINGO_VISIBILITY_DEFAULT TheoryAtom { + friend class TheoryAtomIterator; +public: + explicit TheoryAtom(clingo_theory_atoms_t *atoms, clingo_id_t id) + : atoms_(atoms) + , id_(id) { } + TheoryElementSpan elements() const; + TheoryTerm term() const; + bool has_guard() const; + literal_t literal() const; + std::pair guard() const; + std::string to_string() const; + clingo_id_t to_c() const { return id_; } +private: + TheoryAtom(clingo_theory_atoms_t *atoms) + : TheoryAtom(atoms, 0) { } + TheoryAtom &operator=(clingo_id_t id) { + id_ = id; + return *this; + } +private: + clingo_theory_atoms_t *atoms_; + clingo_id_t id_; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryAtom term); + +class CLINGO_VISIBILITY_DEFAULT TheoryAtomIterator : private TheoryAtom, public std::iterator { +public: + explicit TheoryAtomIterator(clingo_theory_atoms_t *atoms, clingo_id_t id) + : TheoryAtom{atoms, id} { } + TheoryAtomIterator& operator++() { ++id_; return *this; } + TheoryAtomIterator operator++(int) { + auto t = *this; + ++*this; + return t; + } + TheoryAtomIterator& operator--() { --id_; return *this; } + TheoryAtomIterator operator--(int) { + auto t = *this; + --*this; + return t; + } + TheoryAtomIterator& operator+=(difference_type n) { id_ += static_cast(n); return *this; } + TheoryAtomIterator& operator-=(difference_type n) { id_ -= static_cast(n); return *this; } + friend TheoryAtomIterator operator+(TheoryAtomIterator it, difference_type n) { return TheoryAtomIterator{it.atoms(), clingo_id_t(it.id() + n)}; } + friend TheoryAtomIterator operator+(difference_type n, TheoryAtomIterator it) { return TheoryAtomIterator{it.atoms(), clingo_id_t(it.id() + n)}; } + friend TheoryAtomIterator operator-(TheoryAtomIterator it, difference_type n) { return TheoryAtomIterator{it.atoms(), clingo_id_t(it.id() - n)}; } + friend difference_type operator-(TheoryAtomIterator a, TheoryAtomIterator b) { return a.id() - b.id(); } + TheoryAtom operator*() { return *this; } + TheoryAtom *operator->() { return this; } + friend void swap(TheoryAtomIterator& lhs, TheoryAtomIterator& rhs) { + std::swap(lhs.atoms(), rhs.atoms()); + std::swap(lhs.id(), rhs.id()); + } + friend bool operator==(TheoryAtomIterator lhs, TheoryAtomIterator rhs) { return lhs.atoms() == rhs.atoms() && lhs.id() == rhs.id(); } + friend bool operator!=(TheoryAtomIterator lhs, TheoryAtomIterator rhs) { return !(lhs == rhs); } + friend bool operator< (TheoryAtomIterator lhs, TheoryAtomIterator rhs) { assert(lhs.atoms() == rhs.atoms()); return (lhs.id() + 1) < (rhs.id() + 1); } + friend bool operator> (TheoryAtomIterator lhs, TheoryAtomIterator rhs) { return rhs < lhs; } + friend bool operator<=(TheoryAtomIterator lhs, TheoryAtomIterator rhs) { return !(lhs > rhs); } + friend bool operator>=(TheoryAtomIterator lhs, TheoryAtomIterator rhs) { return !(lhs < rhs); } +private: + clingo_theory_atoms_t *&atoms() { return atoms_; } + clingo_id_t &id() { return id_; } +}; + +class CLINGO_VISIBILITY_DEFAULT TheoryAtoms { +public: + explicit TheoryAtoms(clingo_theory_atoms_t *atoms) + : atoms_(atoms) { } + TheoryAtomIterator begin() const; + TheoryAtomIterator end() const; + size_t size() const; + clingo_theory_atoms_t *to_c() const { return atoms_; } +private: + clingo_theory_atoms_t *atoms_; +}; + +// {{{1 propagate init + +class CLINGO_VISIBILITY_DEFAULT PropagateInit { +public: + explicit PropagateInit(clingo_propagate_init_t *init) + : init_(init) { } + literal_t solver_literal(literal_t lit) const; + void add_watch(literal_t lit); + int number_of_threads() const; + SymbolicAtoms symbolic_atoms() const; + TheoryAtoms theory_atoms() const; + clingo_propagate_init_t *to_c() const { return init_; } +private: + clingo_propagate_init_t *init_; +}; + +// {{{1 assignment + +class CLINGO_VISIBILITY_DEFAULT Assignment { +public: + explicit Assignment(clingo_assignment_t *ass) + : ass_(ass) { } + bool has_conflict() const; + uint32_t decision_level() const; + bool has_literal(literal_t lit) const; + TruthValue truth_value(literal_t lit) const; + uint32_t level(literal_t lit) const; + literal_t decision(uint32_t level) const; + bool is_fixed(literal_t lit) const; + bool is_true(literal_t lit) const; + bool is_false(literal_t lit) const; + clingo_assignment_t *to_c() const { return ass_; } +private: + clingo_assignment_t *ass_; +}; + +// {{{1 propagate control + +enum class ClauseType : clingo_clause_type_t { + Learnt = clingo_clause_type_learnt, + Static = clingo_clause_type_static, + Volatile = clingo_clause_type_volatile, + VolatileStatic = clingo_clause_type_volatile_static +}; + +inline std::ostream &operator<<(std::ostream &out, ClauseType t) { + switch (t) { + case ClauseType::Learnt: { out << "Learnt"; break; } + case ClauseType::Static: { out << "Static"; break; } + case ClauseType::Volatile: { out << "Volatile"; break; } + case ClauseType::VolatileStatic: { out << "VolatileStatic"; break; } + } + return out; +} + +class CLINGO_VISIBILITY_DEFAULT PropagateControl { +public: + explicit PropagateControl(clingo_propagate_control_t *ctl) + : ctl_(ctl) { } + id_t thread_id() const; + Assignment assignment() const; + literal_t add_literal(); + void add_watch(literal_t literal); + bool has_watch(literal_t literal) const; + void remove_watch(literal_t literal); + bool add_clause(LiteralSpan clause, ClauseType type = ClauseType::Learnt); + bool propagate(); + clingo_propagate_control_t *to_c() const { return ctl_; } +private: + clingo_propagate_control_t *ctl_; +}; + +// {{{1 propagator + +class CLINGO_VISIBILITY_DEFAULT Propagator { +public: + virtual void init(PropagateInit &init); + virtual void propagate(PropagateControl &ctl, LiteralSpan changes); + virtual void undo(PropagateControl const &ctl, LiteralSpan changes); + virtual void check(PropagateControl &ctl); + virtual ~Propagator() noexcept = default; +}; + +// {{{1 ground program observer + +using IdSpan = Span; +using AtomSpan = Span; + +class CLINGO_VISIBILITY_DEFAULT WeightedLiteral { +public: + WeightedLiteral(clingo_literal_t lit, clingo_weight_t weight) + : wlit_{lit, weight} { } + explicit WeightedLiteral(clingo_weighted_literal_t wlit) + : wlit_(wlit) { } + literal_t literal() const { return wlit_.literal; } + weight_t weight() const { return wlit_.weight; } + clingo_weighted_literal_t const &to_c() const { return wlit_; } + clingo_weighted_literal_t &to_c() { return wlit_; } +private: + clingo_weighted_literal_t wlit_; +}; +using WeightedLiteralSpan = Span; + +enum class HeuristicType : clingo_heuristic_type_t { + Level = clingo_heuristic_type_level, + Sign = clingo_heuristic_type_sign, + Factor = clingo_heuristic_type_factor, + Init = clingo_heuristic_type_init, + True = clingo_heuristic_type_true, + False = clingo_heuristic_type_false +}; + +inline std::ostream &operator<<(std::ostream &out, HeuristicType t) { + switch (t) { + case HeuristicType::Level: { out << "Level"; break; } + case HeuristicType::Sign: { out << "Sign"; break; } + case HeuristicType::Factor: { out << "Factor"; break; } + case HeuristicType::Init: { out << "Init"; break; } + case HeuristicType::True: { out << "True"; break; } + case HeuristicType::False: { out << "False"; break; } + } + return out; +} + +enum class ExternalType { + Free = clingo_external_type_free, + True = clingo_external_type_true, + False = clingo_external_type_false, + Release = clingo_external_type_release +}; + +inline std::ostream &operator<<(std::ostream &out, ExternalType t) { + switch (t) { + case ExternalType::Free: { out << "Free"; break; } + case ExternalType::True: { out << "True"; break; } + case ExternalType::False: { out << "False"; break; } + case ExternalType::Release: { out << "Release"; break; } + } + return out; +} + +class CLINGO_VISIBILITY_DEFAULT GroundProgramObserver { +public: + virtual void init_program(bool incremental); + virtual void begin_step(); + virtual void end_step(); + + virtual void rule(bool choice, AtomSpan head, LiteralSpan body); + virtual void weight_rule(bool choice, AtomSpan head, weight_t lower_bound, WeightedLiteralSpan body); + virtual void minimize(weight_t priority, WeightedLiteralSpan literals); + virtual void project(AtomSpan atoms); + virtual void external(atom_t atom, ExternalType type); + virtual void assume(LiteralSpan literals); + virtual void heuristic(atom_t atom, HeuristicType type, int bias, unsigned priority, LiteralSpan condition); + virtual void acyc_edge(int node_u, int node_v, LiteralSpan condition); + + virtual void theory_term_number(id_t term_id, int number); + virtual void theory_term_string(id_t term_id, char const *name); + virtual void theory_term_compound(id_t term_id, int name_id_or_type, IdSpan arguments); + virtual void theory_element(id_t element_id, IdSpan terms, LiteralSpan condition); + virtual void theory_atom(id_t atom_id_or_zero, id_t term_id, IdSpan elements); + virtual void theory_atom_with_guard(id_t atom_id_or_zero, id_t term_id, IdSpan elements, id_t operator_id, id_t right_hand_side_id); +}; + +inline void GroundProgramObserver::init_program(bool) { } +inline void GroundProgramObserver::begin_step() { } +inline void GroundProgramObserver::end_step() { } + +inline void GroundProgramObserver::rule(bool, AtomSpan, LiteralSpan) { } +inline void GroundProgramObserver::weight_rule(bool, AtomSpan, weight_t, WeightedLiteralSpan) { } +inline void GroundProgramObserver::minimize(weight_t, WeightedLiteralSpan) { } +inline void GroundProgramObserver::project(AtomSpan) { } +inline void GroundProgramObserver::external(atom_t, ExternalType) { } +inline void GroundProgramObserver::assume(LiteralSpan) { } +inline void GroundProgramObserver::heuristic(atom_t, HeuristicType, int, unsigned, LiteralSpan) { } +inline void GroundProgramObserver::acyc_edge(int, int, LiteralSpan) { } + +inline void GroundProgramObserver::theory_term_number(id_t, int) { } +inline void GroundProgramObserver::theory_term_string(id_t, char const *) { } +inline void GroundProgramObserver::theory_term_compound(id_t, int, IdSpan) { } +inline void GroundProgramObserver::theory_element(id_t, IdSpan, LiteralSpan) { } +inline void GroundProgramObserver::theory_atom(id_t, id_t, IdSpan) { } +inline void GroundProgramObserver::theory_atom_with_guard(id_t, id_t, IdSpan, id_t, id_t) { } + +// {{{1 symbolic literal + +class CLINGO_VISIBILITY_DEFAULT SymbolicLiteral { +public: + SymbolicLiteral(Symbol sym, bool sign) + : sym_{sym.to_c(), sign} { } + explicit SymbolicLiteral(clingo_symbolic_literal_t sym) + : sym_(sym) { } + Symbol symbol() const { return Symbol(sym_.symbol); } + bool is_positive() const { return sym_.positive; } + bool is_negative() const { return !sym_.positive; } + clingo_symbolic_literal_t &to_c() { return sym_; } + clingo_symbolic_literal_t const &to_c() const { return sym_; } +private: + clingo_symbolic_literal_t sym_; +}; + +using SymbolicLiteralSpan = Span; + +inline std::ostream &operator<<(std::ostream &out, SymbolicLiteral sym) { + if (sym.is_negative()) { out << "~"; } + out << sym.symbol(); + return out; +} +inline bool operator==(SymbolicLiteral a, SymbolicLiteral b) { return a.is_negative() == b.is_negative() && a.symbol() == b.symbol(); } +inline bool operator!=(SymbolicLiteral a, SymbolicLiteral b) { return !(a == b); } +inline bool operator< (SymbolicLiteral a, SymbolicLiteral b) { + if (a.is_negative() != b.is_negative()) { return a.is_negative() < b.is_negative(); } + return a.symbol() < b.symbol(); +} +inline bool operator<=(SymbolicLiteral a, SymbolicLiteral b) { return !(b < a); } +inline bool operator> (SymbolicLiteral a, SymbolicLiteral b) { return (b < a); } +inline bool operator>=(SymbolicLiteral a, SymbolicLiteral b) { return !(a < b); } + +// {{{1 solve control + +class CLINGO_VISIBILITY_DEFAULT SolveControl { +public: + explicit SolveControl(clingo_solve_control_t *ctl) + : ctl_(ctl) { } + void add_clause(SymbolicLiteralSpan clause); + id_t thread_id() const; + clingo_solve_control_t *to_c() const { return ctl_; } +private: + clingo_solve_control_t *ctl_; +}; + +// {{{1 model + +enum class ModelType : clingo_model_type_t { + StableModel = clingo_model_type_stable_model, + BraveConsequences = clingo_model_type_brave_consequences, + CautiousConsequences = clingo_model_type_cautious_consequences +}; + +class CLINGO_VISIBILITY_DEFAULT ShowType { +public: + enum Type : clingo_show_type_bitset_t { + CSP = clingo_show_type_csp, + Shown = clingo_show_type_shown, + Atoms = clingo_show_type_atoms, + Terms = clingo_show_type_terms, + Theory = clingo_show_type_extra, + All = clingo_show_type_all, + Complement = clingo_show_type_complement + }; + ShowType(clingo_show_type_bitset_t type) : type_(type) { } + operator clingo_show_type_bitset_t() const { return type_; } +private: + clingo_show_type_bitset_t type_; +}; + +using CostVector = std::vector; + +class CLINGO_VISIBILITY_DEFAULT Model { +public: + explicit Model(clingo_model_t *model); + bool contains(Symbol atom) const; + bool optimality_proven() const; + CostVector cost() const; + SymbolVector symbols(ShowType show = ShowType::Shown) const; + SolveControl context() const; + ModelType type() const; + uint64_t number() const; + explicit operator bool() const { return model_ != nullptr; } + clingo_model_t *to_c() const { return model_; } +private: + clingo_model_t *model_; +}; + +inline std::ostream &operator<<(std::ostream &out, Model m) { + out << SymbolSpan(m.symbols(ShowType::Shown)); + return out; +} + +// {{{1 solve result + +class CLINGO_VISIBILITY_DEFAULT SolveResult { +public: + SolveResult() : res_(0) { } + explicit SolveResult(clingo_solve_result_bitset_t res) + : res_(res) { } + bool is_satisfiable() const { return res_ & clingo_solve_result_satisfiable; } + bool is_unsatisfiable() const { return (res_ & clingo_solve_result_unsatisfiable) != 0; } + bool is_unknown() const { return (res_ & 3) == 0; } + bool is_exhausted() const { return (res_ & clingo_solve_result_exhausted) != 0; } + bool is_interrupted() const { return (res_ & clingo_solve_result_interrupted) != 0; } + clingo_solve_result_bitset_t &to_c() { return res_; } + clingo_solve_result_bitset_t const &to_c() const { return res_; } + friend bool operator==(SolveResult a, SolveResult b) { return a.res_ == b.res_; } + friend bool operator!=(SolveResult a, SolveResult b) { return a.res_ != b.res_; } +private: + clingo_solve_result_bitset_t res_; +}; + +inline std::ostream &operator<<(std::ostream &out, SolveResult res) { + if (res.is_satisfiable()) { + out << "SATISFIABLE"; + if (!res.is_exhausted()) { out << "+"; } + } + else if (res.is_unsatisfiable()) { out << "UNSATISFIABLE"; } + else { out << "UNKNOWN"; } + if (res.is_interrupted()) { out << "/INTERRUPTED"; } + return out; +} + +// {{{1 solve iteratively + +class CLINGO_VISIBILITY_DEFAULT SolveIteratively { +public: + SolveIteratively(); + explicit SolveIteratively(clingo_solve_iteratively_t *it); + SolveIteratively(SolveIteratively &&it); + SolveIteratively(SolveIteratively const &) = delete; + SolveIteratively &operator=(SolveIteratively &&it); + SolveIteratively &operator=(SolveIteratively const &) = delete; + clingo_solve_iteratively_t *to_c() const { return iter_; } + Model next(); + SolveResult get(); + void close(); + ~SolveIteratively() { close(); } +private: + clingo_solve_iteratively_t *iter_; +}; + +class CLINGO_VISIBILITY_DEFAULT ModelIterator : public std::iterator { +public: + explicit ModelIterator(SolveIteratively &iter) + : iter_(&iter) + , model_(nullptr) { model_ = iter_->next(); } + ModelIterator() + : iter_(nullptr) + , model_(nullptr) { } + ModelIterator &operator++() { + model_ = iter_->next(); + return *this; + } + // Warning: the resulting iterator should not be used + // because its model is no longer valid + ModelIterator operator++(int) { + ModelIterator t = *this; + ++*this; + return t; + } + Model &operator*() { return model_; } + Model *operator->() { return &**this; } + friend bool operator==(ModelIterator a, ModelIterator b) { + return a.model_.to_c() == b.model_.to_c(); + } + friend bool operator!=(ModelIterator a, ModelIterator b) { return !(a == b); } +private: + SolveIteratively *iter_; + Model model_; +}; + +inline ModelIterator begin(SolveIteratively &it) { return ModelIterator(it); } +inline ModelIterator end(SolveIteratively &) { return ModelIterator(); } + +// {{{1 solve async + +class CLINGO_VISIBILITY_DEFAULT SolveAsync { +public: + explicit SolveAsync(clingo_solve_async_t *async) + : async_(async) { } + void cancel(); + SolveResult get(); + bool wait(double timeout = std::numeric_limits::infinity()); + clingo_solve_async_t *to_c() const { return async_; } +private: + clingo_solve_async_t *async_; +}; + +// {{{1 location + +class CLINGO_VISIBILITY_DEFAULT Location : public clingo_location_t { +public: + explicit Location(clingo_location_t loc) : clingo_location_t(loc) { } + Location(char const *begin_file, char const *end_file, size_t begin_line, size_t end_line, size_t begin_column, size_t end_column) + : clingo_location_t{begin_file, end_file, begin_line, end_line, begin_column, end_column} { } + char const *begin_file() const { return clingo_location_t::begin_file; } + char const *end_file() const { return clingo_location_t::end_file; } + size_t begin_line() const { return clingo_location_t::begin_line; } + size_t end_line() const { return clingo_location_t::end_line; } + size_t begin_column() const { return clingo_location_t::begin_column; } + size_t end_column() const { return clingo_location_t::end_column; } +}; + +inline std::ostream &operator<<(std::ostream &out, Location loc) { + out << loc.begin_file() << ":" << loc.begin_line() << ":" << loc.begin_column(); + bool dash = true; + bool eq = std::strcmp(loc.begin_file(), loc.end_file()) == 0; + if (!eq) { out << (dash ? "-" : ":") << loc.begin_file(); dash = false; } + eq = eq && (loc.begin_line() == loc.end_line()); + if (!eq) { out << (dash ? "-" : ":") << loc.begin_line(); dash = false; } + eq = eq && (loc.begin_column() == loc.end_column()); + if (!eq) { out << (dash ? "-" : ":") << loc.end_column(); dash = false; } + return out; +} + +// {{{1 ast + +namespace AST { + +enum class ComparisonOperator : clingo_ast_comparison_operator_t { + GreaterThan = clingo_ast_comparison_operator_greater_than, + LessThan = clingo_ast_comparison_operator_less_than, + LessEqual = clingo_ast_comparison_operator_less_equal, + GreaterEqual = clingo_ast_comparison_operator_greater_equal, + NotEqual = clingo_ast_comparison_operator_not_equal, + Equal = clingo_ast_comparison_operator_equal +}; + +inline std::ostream &operator<<(std::ostream &out, ComparisonOperator op) { + switch (op) { + case ComparisonOperator::GreaterThan: { out << ">"; break; } + case ComparisonOperator::LessThan: { out << "<"; break; } + case ComparisonOperator::LessEqual: { out << "<="; break; } + case ComparisonOperator::GreaterEqual: { out << ">="; break; } + case ComparisonOperator::NotEqual: { out << "!="; break; } + case ComparisonOperator::Equal: { out << "="; break; } + } + return out; +} + +enum class Sign : clingo_ast_sign_t { + None = clingo_ast_sign_none, + Negation = clingo_ast_sign_negation, + DoubleNegation = clingo_ast_sign_double_negation +}; + +inline std::ostream &operator<<(std::ostream &out, Sign op) { + switch (op) { + case Sign::None: { out << ""; break; } + case Sign::Negation: { out << "not "; break; } + case Sign::DoubleNegation: { out << "not not "; break; } + } + return out; +} + +// {{{2 terms + +// variable + +struct Variable; +struct UnaryOperation; +struct BinaryOperation; +struct Interval; +struct Function; +struct Pool; + +struct Term { + Location location; + Variant data; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Term const &term); + +// Variable + +struct Variable { + char const *name; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Variable const &x); + +// unary operation + +enum UnaryOperator : clingo_ast_unary_operator_t { + Absolute = clingo_ast_unary_operator_absolute, + Minus = clingo_ast_unary_operator_minus, + Negation = clingo_ast_unary_operator_negation +}; + +inline char const *left_hand_side(UnaryOperator op) { + switch (op) { + case UnaryOperator::Absolute: { return "|"; } + case UnaryOperator::Minus: { return "-"; } + case UnaryOperator::Negation: { return "~"; } + } + return ""; +} + +inline char const *right_hand_side(UnaryOperator op) { + switch (op) { + case UnaryOperator::Absolute: { return "|"; } + case UnaryOperator::Minus: { return ""; } + case UnaryOperator::Negation: { return ""; } + } + return ""; +} + +struct UnaryOperation { + UnaryOperator unary_operator; + Term argument; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, UnaryOperation const &x); + +// binary operation + +enum class BinaryOperator : clingo_ast_binary_operator_t { + XOr = clingo_ast_binary_operator_xor, + Or = clingo_ast_binary_operator_or, + And = clingo_ast_binary_operator_and, + Plus = clingo_ast_binary_operator_plus, + Minus = clingo_ast_binary_operator_minus, + Multiplication = clingo_ast_binary_operator_multiplication, + Division = clingo_ast_binary_operator_division, + Modulo = clingo_ast_binary_operator_modulo +}; + +inline std::ostream &operator<<(std::ostream &out, BinaryOperator op) { + switch (op) { + case BinaryOperator::XOr: { out << "^"; break; } + case BinaryOperator::Or: { out << "?"; break; } + case BinaryOperator::And: { out << "&"; break; } + case BinaryOperator::Plus: { out << "+"; break; } + case BinaryOperator::Minus: { out << "-"; break; } + case BinaryOperator::Multiplication: { out << "*"; break; } + case BinaryOperator::Division: { out << "/"; break; } + case BinaryOperator::Modulo: { out << "\\"; break; } + } + return out; +} + +struct BinaryOperation { + BinaryOperator binary_operator; + Term left; + Term right; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, BinaryOperation const &x); + +// interval + +struct Interval { + Term left; + Term right; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Interval const &x); + +// function + +struct Function { + char const *name; + std::vector arguments; + bool external; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Function const &x); + +// pool + +struct Pool { + std::vector arguments; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Pool const &x); + +// {{{2 csp + +struct CSPProduct { + Location location; + Term coefficient; + Optional variable; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, CSPProduct const &x); + +struct CSPSum { + Location location; + std::vector terms; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, CSPSum const &x); + +struct CSPGuard { + ComparisonOperator comparison; + CSPSum term; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, CSPGuard const &x); + +struct CSPLiteral { + CSPSum term; + std::vector guards; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, CSPLiteral const &x); + +// {{{2 ids + +struct Id { + Location location; + char const *id; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Id const &x); + +// {{{2 literals + +struct Comparison { + ComparisonOperator comparison; + Term left; + Term right; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Comparison const &x); + +struct Boolean { + bool value; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Boolean const &x); + +struct Literal { + Location location; + Sign sign; + Variant data; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Literal const &x); + +// {{{2 aggregates + +enum class AggregateFunction : clingo_ast_aggregate_function_t { + Count = clingo_ast_aggregate_function_count, + Sum = clingo_ast_aggregate_function_sum, + SumPlus = clingo_ast_aggregate_function_sump, + Min = clingo_ast_aggregate_function_min, + Max = clingo_ast_aggregate_function_max +}; + +inline std::ostream &operator<<(std::ostream &out, AggregateFunction op) { + switch (op) { + case AggregateFunction::Count: { out << "#count"; break; } + case AggregateFunction::Sum: { out << "#sum"; break; } + case AggregateFunction::SumPlus: { out << "#sum+"; break; } + case AggregateFunction::Min: { out << "#min"; break; } + case AggregateFunction::Max: { out << "#max"; break; } + } + return out; +} + +struct AggregateGuard { + ComparisonOperator comparison; + Term term; +}; + +struct ConditionalLiteral { + Literal literal; + std::vector condition; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, ConditionalLiteral const &x); + +// lparse-style aggregate + +struct Aggregate { + std::vector elements; + Optional left_guard; + Optional right_guard; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Aggregate const &x); + +// body aggregate + +struct BodyAggregateElement { + std::vector tuple; + std::vector condition; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, BodyAggregateElement const &x); + +struct BodyAggregate { + AggregateFunction function; + std::vector elements; + Optional left_guard; + Optional right_guard; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, BodyAggregate const &x); + +// head aggregate + +struct HeadAggregateElement { + std::vector tuple; + ConditionalLiteral condition; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, HeadAggregateElement const &x); + +struct HeadAggregate { + AggregateFunction function; + std::vector elements; + Optional left_guard; + Optional right_guard; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, HeadAggregate const &x); + +// disjunction + +struct Disjunction { + std::vector elements; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Disjunction const &x); + +// disjoint + +struct DisjointElement { + Location location; + std::vector tuple; + CSPSum term; + std::vector condition; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, DisjointElement const &x); + +struct Disjoint { + std::vector elements; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Disjoint const &x); + +// {{{2 theory atom + +enum class TheoryTermSequenceType : int { + Tuple = 0, + List = 1, + Set = 2 +}; +inline char const *left_hand_side(TheoryTermSequenceType x) { + switch (x) { + case TheoryTermSequenceType::Tuple: { return "("; } + case TheoryTermSequenceType::List: { return "["; } + case TheoryTermSequenceType::Set: { return "{"; } + } + return ""; +} +inline char const *right_hand_side(TheoryTermSequenceType x) { + switch (x) { + case TheoryTermSequenceType::Tuple: { return ")"; } + case TheoryTermSequenceType::List: { return "]"; } + case TheoryTermSequenceType::Set: { return "}"; } + } + return ""; +} + +struct TheoryFunction; +struct TheoryTermSequence; +struct TheoryUnparsedTerm; + +struct TheoryTerm { + Location location; + Variant data; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryTerm const &x); + +struct TheoryTermSequence { + TheoryTermSequenceType type; + std::vector terms; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryTermSequence const &x); + +struct TheoryFunction { + char const *name; + std::vector arguments; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryFunction const &x); + +struct TheoryUnparsedTermElement { + std::vector operators; + TheoryTerm term; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryUnparsedTermElement const &x); + +struct TheoryUnparsedTerm { + std::vector elements; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryUnparsedTerm const &x); + +struct TheoryAtomElement { + std::vector tuple; + std::vector condition; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryAtomElement const &x); + +struct TheoryGuard { + char const *operator_name; + TheoryTerm term; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryGuard const &x); + +struct TheoryAtom { + Term term; + std::vector elements; + Optional guard; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryAtom const &x); + +// {{{2 head literals + +struct HeadLiteral { + Location location; + Variant data; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, HeadLiteral const &x); + +// {{{2 body literals + +struct BodyLiteral { + Location location; + Sign sign; + Variant data; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, BodyLiteral const &x); + +// {{{2 theory definitions + +enum class TheoryOperatorType : clingo_ast_theory_operator_type_t { + Unary = clingo_ast_theory_operator_type_unary, + BinaryLeft = clingo_ast_theory_operator_type_binary_left, + BinaryRight = clingo_ast_theory_operator_type_binary_right +}; + +inline std::ostream &operator<<(std::ostream &out, TheoryOperatorType op) { + switch (op) { + case TheoryOperatorType::Unary: { out << "unary"; break; } + case TheoryOperatorType::BinaryLeft: { out << "binary, left"; break; } + case TheoryOperatorType::BinaryRight: { out << "binary, right"; break; } + } + return out; +} + +struct TheoryOperatorDefinition { + Location location; + char const *name; + unsigned priority; + TheoryOperatorType type; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryOperatorDefinition const &x); + +struct TheoryTermDefinition { + Location location; + char const *name; + std::vector operators; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryTermDefinition const &x); + +struct TheoryGuardDefinition { + char const *term; + std::vector operators; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryGuardDefinition const &x); + +enum class TheoryAtomDefinitionType : clingo_ast_theory_atom_definition_type_t { + Head = clingo_ast_theory_atom_definition_type_head, + Body = clingo_ast_theory_atom_definition_type_body, + Any = clingo_ast_theory_atom_definition_type_any, + Directive = clingo_ast_theory_atom_definition_type_directive +}; + +inline std::ostream &operator<<(std::ostream &out, TheoryAtomDefinitionType op) { + switch (op) { + case TheoryAtomDefinitionType::Head: { out << "head"; break; } + case TheoryAtomDefinitionType::Body: { out << "body"; break; } + case TheoryAtomDefinitionType::Any: { out << "any"; break; } + case TheoryAtomDefinitionType::Directive: { out << "directive"; break; } + } + return out; +} + +struct TheoryAtomDefinition { + Location location; + TheoryAtomDefinitionType type; + char const *name; + unsigned arity; + char const *elements; + Optional guard; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryAtomDefinition const &x); + +struct TheoryDefinition { + char const *name; + std::vector terms; + std::vector atoms; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, TheoryDefinition const &x); + +// {{{2 statements + +// rule + +struct Rule { + HeadLiteral head; + std::vector body; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Rule const &x); + +// definition + +struct Definition { + char const *name; + Term value; + bool is_default; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Definition const &x); + +// show + +struct ShowSignature { + Signature signature; + bool csp; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, ShowSignature const &x); + +struct ShowTerm { + Term term; + std::vector body; + bool csp; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, ShowTerm const &x); + +// minimize + +struct Minimize { + Term weight; + Term priority; + std::vector tuple; + std::vector body; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Minimize const &x); + +// script + +enum class ScriptType : clingo_ast_script_type_t { + Lua = clingo_ast_script_type_lua, + Python = clingo_ast_script_type_python +}; + +inline std::ostream &operator<<(std::ostream &out, ScriptType op) { + switch (op) { + case ScriptType::Lua: { out << "lua"; break; } + case ScriptType::Python: { out << "python"; break; } + } + return out; +} + +struct Script { + ScriptType type; + char const *code; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Script const &x); + +// program + +struct Program { + char const *name; + std::vector parameters; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Program const &x); + +// external + +struct External { + Term atom; + std::vector body; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, External const &x); + +// edge + +struct Edge { + Term u; + Term v; + std::vector body; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Edge const &x); + +// heuristic + +struct Heuristic { + Term atom; + std::vector body; + Term bias; + Term priority; + Term modifier; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Heuristic const &x); + +// project + +struct ProjectAtom { + Term atom; + std::vector body; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, ProjectAtom const &x); + +struct ProjectSignature { + Signature signature; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, ProjectSignature const &x); + +// statement + +struct Statement { + Location location; + Variant data; +}; +CLINGO_VISIBILITY_DEFAULT std::ostream &operator<<(std::ostream &out, Statement const &x); + +} // namespace AST + +// {{{1 backend + +class CLINGO_VISIBILITY_DEFAULT Backend { +public: + explicit Backend(clingo_backend_t *backend) + : backend_(backend) { } + void rule(bool choice, AtomSpan head, LiteralSpan body); + void weight_rule(bool choice, AtomSpan head, weight_t lower, WeightedLiteralSpan body); + void minimize(weight_t prio, WeightedLiteralSpan body); + void project(AtomSpan atoms); + void external(atom_t atom, ExternalType type); + void assume(LiteralSpan lits); + void heuristic(atom_t atom, HeuristicType type, int bias, unsigned priority, LiteralSpan condition); + void acyc_edge(int node_u, int node_v, LiteralSpan condition); + atom_t add_atom(); + clingo_backend_t *to_c() const { return backend_; } +private: + clingo_backend_t *backend_; +}; + +// {{{1 statistics + +template +class KeyIterator : public std::iterator, char const *> { +public: + explicit KeyIterator(T const *map, size_t index = 0) + : map_(map) + , index_(index) { } + KeyIterator& operator++() { ++index_; return *this; } + KeyIterator operator++(int) { + KeyIterator t(*this); + ++*this; + return t; + } + KeyIterator& operator--() { --index_; return *this; } + KeyIterator operator--(int) { + KeyIterator t(*this); + --*this; + return t; + } + KeyIterator& operator+=(difference_type n) { index_ += n; return *this; } + KeyIterator& operator-=(difference_type n) { index_ -= n; return *this; } + friend KeyIterator operator+(KeyIterator it, difference_type n) { return KeyIterator{it.map_, it.index_ + n}; } + friend KeyIterator operator+(difference_type n, KeyIterator it) { return KeyIterator{it.map_, it.index_ + n}; } + friend KeyIterator operator-(KeyIterator it, difference_type n) { return KeyIterator{it.map_, it.index_ - n}; } + friend difference_type operator-(KeyIterator a, KeyIterator b) { return a.index_ - b.index_; } + reference operator*() { return map_->key_name(index_); } + pointer operator->() { return pointer(**this); } + friend void swap(KeyIterator& lhs, KeyIterator& rhs) { + std::swap(lhs.map_, rhs.map_); + std::swap(lhs.index_, rhs.index_); + } + friend bool operator==(const KeyIterator& lhs, const KeyIterator& rhs) { return lhs.index_ == rhs.index_; } + friend bool operator!=(const KeyIterator& lhs, const KeyIterator& rhs) { return !(lhs == rhs); } + friend bool operator< (KeyIterator lhs, KeyIterator rhs) { return (lhs.index_ + 1) < (rhs.index_ + 1); } + friend bool operator> (KeyIterator lhs, KeyIterator rhs) { return rhs < lhs; } + friend bool operator<=(KeyIterator lhs, KeyIterator rhs) { return !(lhs > rhs); } + friend bool operator>=(KeyIterator lhs, KeyIterator rhs) { return !(lhs < rhs); } +private: + T const *map_; + size_t index_; +}; + +template +class ArrayIterator : public std::iterator, T> { +public: + using base = std::iterator, T>; + using difference_type = typename base::difference_type; + using reference = typename base::reference; + using pointer = typename base::pointer; + explicit ArrayIterator(P arr, size_t index = 0) + : arr_(arr) + , index_(index) { } + ArrayIterator& operator++() { ++index_; return *this; } + ArrayIterator operator++(int) { + ArrayIterator t(*this); + ++*this; + return t; + } + ArrayIterator& operator--() { --index_; return *this; } + ArrayIterator operator--(int) { + ArrayIterator t(*this); + --*this; + return t; + } + ArrayIterator& operator+=(difference_type n) { index_ += n; return *this; } + ArrayIterator& operator-=(difference_type n) { index_ -= n; return *this; } + friend ArrayIterator operator+(ArrayIterator it, difference_type n) { return ArrayIterator{it.arr_, it.index_ + n}; } + friend ArrayIterator operator+(difference_type n, ArrayIterator it) { return ArrayIterator{it.arr_, it.index_ + n}; } + friend ArrayIterator operator-(ArrayIterator it, difference_type n) { return ArrayIterator{it.arr_, it.index_ - n}; } + friend difference_type operator-(ArrayIterator a, ArrayIterator b) { return a.index_ - b.index_; } + reference operator*() { return (*arr_)[index_]; } + pointer operator->() { return pointer(**this); } + friend void swap(ArrayIterator& lhs, ArrayIterator& rhs) { + std::swap(lhs.arr_, rhs.arr_); + std::swap(lhs.index_, rhs.index_); + } + friend bool operator==(const ArrayIterator& lhs, const ArrayIterator& rhs) { return lhs.index_ == rhs.index_; } + friend bool operator!=(const ArrayIterator& lhs, const ArrayIterator& rhs) { return !(lhs == rhs); } + friend bool operator< (ArrayIterator lhs, ArrayIterator rhs) { return (lhs.index_ + 1) < (rhs.index_ + 1); } + friend bool operator> (ArrayIterator lhs, ArrayIterator rhs) { return rhs < lhs; } + friend bool operator<=(ArrayIterator lhs, ArrayIterator rhs) { return !(lhs > rhs); } + friend bool operator>=(ArrayIterator lhs, ArrayIterator rhs) { return !(lhs < rhs); } +private: + P arr_; + size_t index_; +}; + +enum class StatisticsType : clingo_statistics_type_t { + Value = clingo_statistics_type_value, + Array = clingo_statistics_type_array, + Map = clingo_statistics_type_map +}; + +class Statistics; +using StatisticsKeyIterator = KeyIterator; +using StatisticsArrayIterator = ArrayIterator; +using StatisticsKeyRange = IteratorRange; + +class CLINGO_VISIBILITY_DEFAULT Statistics { + friend class KeyIterator; +public: + explicit Statistics(clingo_statistics_t *stats, uint64_t key) + : stats_(stats) + , key_(key) { } + // generic + StatisticsType type() const; + // arrays + size_t size() const; + Statistics operator[](size_t index) const; + Statistics at(size_t index) const { return operator[](index); } + StatisticsArrayIterator begin() const; + StatisticsArrayIterator end() const; + // maps + Statistics operator[](char const *name) const; + Statistics get(char const *name) { return operator[](name); } + StatisticsKeyRange keys() const; + // leafs + double value() const; + operator double() const { return value(); } + clingo_statistics_t *to_c() const { return stats_; } +private: + char const *key_name(size_t index) const; + clingo_statistics_t *stats_; + uint64_t key_; +}; + +// {{{1 configuration + +class Configuration; +using ConfigurationArrayIterator = ArrayIterator; +using ConfigurationKeyIterator = KeyIterator; +using ConfigurationKeyRange = IteratorRange; + +class CLINGO_VISIBILITY_DEFAULT Configuration { + friend class KeyIterator; +public: + explicit Configuration(clingo_configuration_t *conf, clingo_id_t key) + : conf_(conf) + , key_(key) { } + // arrays + bool is_array() const; + Configuration operator[](size_t index); + Configuration at(size_t index) { return operator[](index); } + ConfigurationArrayIterator begin(); + ConfigurationArrayIterator end(); + size_t size() const; + bool empty() const; + // maps + bool is_map() const; + Configuration operator[](char const *name); + Configuration get(char const *name) { return operator[](name); } + ConfigurationKeyRange keys() const; + // values + bool is_value() const; + bool is_assigned() const; + std::string value() const; + operator std::string() const { return value(); } + Configuration &operator=(char const *value); + // generic + char const *decription() const; + clingo_configuration_t *to_c() const { return conf_; } +private: + char const *key_name(size_t index) const; + clingo_configuration_t *conf_; + unsigned key_; +}; + +// {{{1 program builder + +class CLINGO_VISIBILITY_DEFAULT ProgramBuilder { +public: + explicit ProgramBuilder(clingo_program_builder_t *builder) + : builder_(builder) { } + void begin(); + void add(AST::Statement const &stm); + void end(); + clingo_program_builder_t *to_c() const { return builder_; } +private: + clingo_program_builder_t *builder_; + +}; + +// {{{1 control + +class CLINGO_VISIBILITY_DEFAULT Part { +public: + Part(char const *name, SymbolSpan params) + : part_{name, reinterpret_cast(params.begin()), params.size()} { } + explicit Part(clingo_part_t part) + : part_(part) { } + char const *name() const { return part_.name; } + SymbolSpan params() const { return {reinterpret_cast(part_.params), part_.size}; } + clingo_part_t const &to_c() const { return part_; } + clingo_part_t &to_c() { return part_; } +private: + clingo_part_t part_; +}; +using SymbolSpanCallback = std::function; +using PartSpan = Span; +using GroundCallback = std::function; +using StringSpan = Span; +using ModelCallback = std::function; +using FinishCallback = std::function; + +enum class ErrorCode : clingo_error_t { + Runtime = clingo_error_runtime, + Logic = clingo_error_logic, + BadAlloc = clingo_error_bad_alloc, + Unknown = clingo_error_unknown, +}; + +inline std::ostream &operator<<(std::ostream &out, ErrorCode code) { + out << clingo_error_string(static_cast(code)); + return out; +} + +enum class WarningCode : clingo_warning_t { + OperationUndefined = clingo_warning_operation_undefined, + RuntimeError = clingo_warning_runtime_error, + AtomUndefined = clingo_warning_atom_undefined, + FileIncluded = clingo_warning_file_included, + VariableUnbounded = clingo_warning_variable_unbounded, + GlobalVariable = clingo_warning_global_variable, + Other = clingo_warning_other, +}; + +using Logger = std::function; + +inline std::ostream &operator<<(std::ostream &out, WarningCode code) { + out << clingo_warning_string(static_cast(code)); + return out; +} + +class CLINGO_VISIBILITY_DEFAULT Control { + struct Impl; +public: + Control(StringSpan args = {}, Logger logger = nullptr, unsigned message_limit = 20); + explicit Control(clingo_control_t *ctl); + Control(Control &&c); + Control(Control const &) = delete; + Control &operator=(Control &&c); + Control &operator=(Control const &c) = delete; + ~Control() noexcept; + void add(char const *name, StringSpan params, char const *part); + void ground(PartSpan parts, GroundCallback cb = nullptr); + SolveResult solve(ModelCallback mh = nullptr, SymbolicLiteralSpan assumptions = {}); + SolveIteratively solve_iteratively(SymbolicLiteralSpan assumptions = {}); + void assign_external(Symbol atom, TruthValue value); + void release_external(Symbol atom); + SymbolicAtoms symbolic_atoms() const; + TheoryAtoms theory_atoms() const; + void register_propagator(Propagator &propagator, bool sequential = false); + void register_observer(GroundProgramObserver &observer); + void cleanup(); + bool has_const(char const *name) const; + Symbol get_const(char const *name) const; + void interrupt() noexcept; + void *claspFacade(); + void load(char const *file); + SolveAsync solve_async(ModelCallback mh = nullptr, FinishCallback fh = nullptr, SymbolicLiteralSpan assumptions = {}); + void use_enumeration_assumption(bool value); + Backend backend(); + ProgramBuilder builder(); + template + void with_builder(F f) { + ProgramBuilder b = builder(); + b.begin(); + f(b); + b.end(); + } + Configuration configuration(); + Statistics statistics() const; + clingo_control_t *to_c() const; +private: + Impl *impl_; +}; + +// {{{1 global functions + +using StatementCallback = std::function; + +CLINGO_VISIBILITY_DEFAULT void parse_program(char const *program, StatementCallback cb, Logger logger = nullptr, unsigned message_limit = 20); +CLINGO_VISIBILITY_DEFAULT Symbol parse_term(char const *str, Logger logger = nullptr, unsigned message_limit = 20); +CLINGO_VISIBILITY_DEFAULT char const *add_string(char const *str); + +// }}}1 + +} + +#endif diff --git a/libgringo/gringo/backend.hh b/libgringo/gringo/backend.hh new file mode 100644 index 0000000..8821562 --- /dev/null +++ b/libgringo/gringo/backend.hh @@ -0,0 +1,60 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_BACKEND_HH +#define _GRINGO_BACKEND_HH + +#include +#include + +namespace Gringo { + +// {{{1 declaration of Backend + +using GetTheoryAtomCondition = std::function (Potassco::Id_t)>; +using BackendAtomVec = std::vector; +using BackendLitVec = std::vector; +using BackendLitWeightVec = std::vector; +using Backend = Potassco::AbstractProgram; +using UBackend = std::unique_ptr; + +void output(Potassco::TheoryData const &data, Potassco::AbstractProgram &out, GetTheoryAtomCondition cond); + +inline void outputRule(Backend &out, bool choice, Potassco::AtomSpan head, Potassco::LitSpan body) { + out.rule(choice ? Potassco::Head_t::Choice : Potassco::Head_t::Disjunctive, head, body); +} + +inline void outputRule(Backend &out, bool choice, BackendAtomVec const &head, BackendLitVec const &body) { + outputRule(out, choice, Potassco::toSpan(head), Potassco::toSpan(body)); +} + +inline void outputRule(Backend &out, bool choice, Potassco::AtomSpan head, Potassco::Weight_t lower, Potassco::WeightLitSpan body) { + out.rule(choice ? Potassco::Head_t::Choice : Potassco::Head_t::Disjunctive, head, lower, body); +} + +inline void outputRule(Backend &out, bool choice, BackendAtomVec const &head, Potassco::Weight_t lower, BackendLitWeightVec const &body) { + outputRule(out, choice, Potassco::toSpan(head), lower, Potassco::toSpan(body)); +} + +// }}}1 + +} // namespace Gringo + +#endif // _GRINGO_BACKEND_HH diff --git a/libgringo/gringo/backtrace.hh b/libgringo/gringo/backtrace.hh new file mode 100644 index 0000000..7fe5478 --- /dev/null +++ b/libgringo/gringo/backtrace.hh @@ -0,0 +1,119 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_BACKTRACE_HH +#define _GRINGO_BACKTRACE_HH + +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO: given a little time this could be cleaned up +// to remove the ugly fixed size strings +// anyway this is just debug code... + +namespace Gringo { + +inline const char* getExecutableName() { + static char* exe = 0; + if (!exe) { + char link[4096]; + static char _exe[4096]; + _exe[0] = '\0'; + snprintf(link, sizeof(link), "/proc/%d/exe", getpid()); + readlink(link, _exe, sizeof(link)); + exe = _exe; + } + return exe; +} + +inline int getFileAndLine (unw_word_t addr, char *file, int *line) { + char buf[4096]; + static std::unordered_map cache; + std::string &s = cache[addr]; + if (!s.empty()) { + strncpy(buf, s.c_str(), sizeof(buf)); + } + else { + snprintf (buf, sizeof(buf), "/home/wv/bin/linux/64/binutils-2.23.1/bin/addr2line -C -e %s -f -i %lx", getExecutableName(), addr); + FILE* f = popen (buf, "r"); + if (f == NULL) { + perror (buf); + return 0; + } + fgets (buf, sizeof(buf), f); + fgets (buf, sizeof(buf), f); + pclose(f); + s = buf; + const char *pref = "/home/kaminski/svn/wv/Programming/gringo/trunk/"; + if (strncmp(pref, s.c_str(), strlen(pref)) == 0) { + s = buf + strlen(pref); + strncpy(buf, s.c_str(), sizeof(buf)); + } + } + if (buf[0] != '?') { + char *p = buf; + while (*p != ':') { p++; } + *p++ = 0; + strncpy (file , buf, 4096); + sscanf (p,"%d", line); + } + else { + strncpy (file,"unkown", 4096); + *line = 0; + } + return 1; +} + +inline void showBacktrace (void) { + char name[4096]; + int status; + unw_cursor_t cursor; unw_context_t uc; + unw_word_t ip, sp, offp; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + + while (unw_step(&cursor) > 0) { + char file[4096]; + int line = 0; + + name[0] = '\0'; + unw_get_proc_name(&cursor, name, sizeof(name), &offp); + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + if (strcmp(name, "__libc_start_main") == 0 || strcmp(name, "_start") == 0) { continue; } + + char *realname = abi::__cxa_demangle(name, 0, 0, &status); + getFileAndLine((long)ip, file, &line); + printf("%s in %s:%d\n", !status ? realname : name, file, line); + free(realname); + } +} + +} // namespace Gringo + +#endif // _GRINGO_BACKTRACE_HH diff --git a/libgringo/gringo/base.hh b/libgringo/gringo/base.hh new file mode 100644 index 0000000..cb6c4e9 --- /dev/null +++ b/libgringo/gringo/base.hh @@ -0,0 +1,280 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_BASE_HH +#define _GRINGO_BASE_HH + +#include +#include +#include + +namespace Gringo { + +// {{{1 declaration of TheoryAtomType + +enum class TheoryAtomType { Head, Body, Any, Directive }; +std::ostream &operator<<(std::ostream &out, TheoryAtomType type); + +// {{{1 declaration of TheoryOperatorType + +enum class TheoryOperatorType { Unary, BinaryLeft, BinaryRight }; +std::ostream &operator<<(std::ostream &out, TheoryOperatorType type); + +// {{{1 declaration of NAF + +enum class NAF { POS = 0, NOT = 1, NOTNOT = 2 }; +std::ostream &operator<<(std::ostream &out, NAF naf); +NAF inv(NAF naf); + +enum class RECNAF { POS, NOT, NOTNOT, RECNOT }; +RECNAF recnaf(NAF naf, bool recursive); +std::ostream &operator<<(std::ostream &out, RECNAF naf); + +// {{{1 declaration of Relation + +enum class Relation : unsigned { GT, LT, LEQ, GEQ, NEQ, EQ }; + +Relation inv(Relation rel); +Relation neg(Relation rel); + +std::ostream &operator<<(std::ostream &out, Relation rel); + +// {{{1 declaration of AggregateFunction + +enum class AggregateFunction { COUNT, SUM, SUMP, MIN, MAX }; + +std::ostream &operator<<(std::ostream &out, AggregateFunction fun); + +// {{{1 declaration of Bound + +struct Bound; +typedef std::vector BoundVec; + +struct Bound { + Bound(Relation rel, UTerm &&bound); + Bound(Bound &&bound) noexcept; + Bound& operator=(Bound &&) noexcept; + size_t hash() const; + bool operator==(Bound const &other) const; + //! Unpool the terms in the bound. + BoundVec unpool(); + //! Simplify the terms in the bound. + //! \pre Must be called after unpool. + bool simplify(SimplifyState &state, Logger &log); + //! Rewrite arithmetics. + //! \pre Must be called after assignLevels. + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen); + + Relation rel; + UTerm bound; +}; + +// }}}1 + +// {{{1 definition of TheoryAtomType + +inline std::ostream &operator<<(std::ostream &out, TheoryAtomType type) { + switch (type) { + case TheoryAtomType::Head: { out << "head"; break; } + case TheoryAtomType::Body: { out << "body"; break; } + case TheoryAtomType::Any: { out << "any"; break; } + case TheoryAtomType::Directive: { out << "directive"; break; } + } + return out; +} + +// {{{1 definition of TheoryOperatorType + +inline std::ostream &operator<<(std::ostream &out, TheoryOperatorType type) { + switch (type) { + case TheoryOperatorType::Unary: { out << "unary"; break; } + case TheoryOperatorType::BinaryLeft: { out << "binary,left"; break; } + case TheoryOperatorType::BinaryRight: { out << "binary,right"; break; } + } + return out; +} + +// {{{1 definition of NAF + +inline NAF inv(NAF naf) { + switch (naf) { + case NAF::NOTNOT: { return NAF::NOT; } + case NAF::NOT: { return NAF::NOTNOT; } + case NAF::POS: { return NAF::NOT; } + } + assert(false); + return NAF::POS; +} + +inline std::ostream &operator<<(std::ostream &out, NAF naf) { + switch (naf) { + case NAF::NOTNOT: { out << "not "; } + case NAF::NOT: { out << "not "; } + case NAF::POS: { } + } + return out; +} + +inline std::ostream &operator<<(std::ostream &out, RECNAF naf) { + switch (naf) { + case RECNAF::NOTNOT: { out << "not "; } + case RECNAF::RECNOT: + case RECNAF::NOT: { out << "not "; } + case RECNAF::POS: { } + } + return out; +} + +inline RECNAF recnaf(NAF naf, bool recursive) { + switch (naf) { + case NAF::POS: { return RECNAF::POS; } + case NAF::NOT: { return recursive ? RECNAF::RECNOT : RECNAF::NOT; } + case NAF::NOTNOT: { return recursive ? RECNAF::NOTNOT : RECNAF::POS; } + } + return RECNAF::POS; +} + +// {{{1 definition of Relation + +inline std::ostream &operator<<(std::ostream &out, Relation rel) { + switch (rel) { + case Relation::GT: { out << ">"; break; } + case Relation::LT: { out << "<"; break; } + case Relation::LEQ: { out << "<="; break; } + case Relation::GEQ: { out << ">="; break; } + case Relation::NEQ: { out << "!="; break; } + case Relation::EQ: { out << "="; break; } + } + return out; +} + +inline Relation inv(Relation rel) { + switch (rel) { + case Relation::NEQ: { return Relation::NEQ; } + case Relation::GEQ: { return Relation::LEQ; } + case Relation::LEQ: { return Relation::GEQ; } + case Relation::EQ: { return Relation::EQ; } + case Relation::LT: { return Relation::GT; } + case Relation::GT: { return Relation::LT; } + } + assert(false); + return Relation(-1); +} + +inline Relation neg(Relation rel) { + switch (rel) { + case Relation::NEQ: { return Relation::EQ; } + case Relation::GEQ: { return Relation::LT; } + case Relation::LEQ: { return Relation::GT; } + case Relation::EQ: { return Relation::NEQ; } + case Relation::LT: { return Relation::GEQ; } + case Relation::GT: { return Relation::LEQ; } + } + assert(false); + return Relation(-1); +} + +// {{{1 definition of AggregateFunction + +inline std::ostream &operator<<(std::ostream &out, AggregateFunction fun) { + switch (fun) { + case AggregateFunction::MIN: { out << "#min"; break; } + case AggregateFunction::MAX: { out << "#max"; break; } + case AggregateFunction::SUM: { out << "#sum"; break; } + case AggregateFunction::SUMP: { out << "#sum+"; break; } + case AggregateFunction::COUNT: { out << "#count"; break; } + } + return out; +} + +// {{{1 definition of Bound + +inline Bound::Bound(Relation rel, UTerm &&bound) + : rel(rel) + , bound(std::move(bound)) { } + +inline size_t Bound::hash() const { + return get_value_hash(size_t(rel), bound); +} + +inline bool Bound::operator==(Bound const &other) const { + return rel == other.rel && is_value_equal_to(bound, other.bound); +} + +inline Bound::Bound(Bound &&) noexcept = default; + +inline Bound& Bound::operator=(Bound &&) noexcept = default; + +inline BoundVec Bound::unpool() { + BoundVec pool; + auto f = [&](UTerm &&x) { pool.emplace_back(rel, std::move(x)); }; + Term::unpool(bound, Gringo::unpool, f); + return pool; +} + +inline bool Bound::simplify(SimplifyState &state, Logger &log) { + return !bound->simplify(state, false, false, log).update(bound).undefined(); +} + +inline void Bound::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + // NOTE: this replaces all arithmetics to ensure that all terms in bounds are defined when evaluating + Term::replace(bound, bound->rewriteArithmetics(arith, auxGen, true)); +} + +template <> +struct clone { + Bound operator()(Bound const &bound) const { + return Bound(bound.rel, get_clone(bound.bound)); + } +}; + +// }}}1 + +} // namespace Gringo + +namespace std { + +// {{{1 definition of hash + +template <> +struct hash { + size_t operator()(Gringo::Bound const &x) const { return x.hash(); } +}; + +// {{{1 definition of hash + +template <> +struct hash { + size_t operator()(Gringo::Relation const &x) const { return static_cast(x); } +}; + +// {{{1 definition of hash + +template <> +struct hash { + size_t operator()(Gringo::NAF const &x) const { return static_cast(x); } +}; + +// }}}1 + +} // namespace std + +#endif // _GRINGO_BASE_HH + diff --git a/libgringo/gringo/bug.hh b/libgringo/gringo/bug.hh new file mode 100644 index 0000000..ba8dbb1 --- /dev/null +++ b/libgringo/gringo/bug.hh @@ -0,0 +1,81 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef __GRINGO_MINGW_H +#define __GRINGO_MINGW_H + +#include + +// Note 1: harmless because I don't have any throwing move constructors +// Note 2: should be first include + +#undef _GLIBCXX_MAKE_MOVE_ITERATOR +#undef _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR + +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) std::make_move_iterator(_Iter) + +#ifdef MISSING_STD_TO_STRING + +#include + +namespace std { + +inline string to_string(int x) { + ostringstream ss; + ss << x; + return ss.str(); +} + +inline string to_string(unsigned x) { + ostringstream ss; + ss << x; + return ss.str(); +} + +inline string to_string(long x) { + ostringstream ss; + ss << x; + return ss.str(); +} + +inline string to_string(unsigned long x) { + ostringstream ss; + ss << x; + return ss.str(); +} + +inline string to_string(long long x) { + ostringstream ss; + ss << x; + return ss.str(); +} + +inline string to_string(unsigned long long x) { + ostringstream ss; + ss << x; + return ss.str(); +} + +} // namespace std + +#endif // MISSING_STD_TO_STRING + +#endif // __GRINGO_MINGW_H diff --git a/libgringo/gringo/clonable.hh b/libgringo/gringo/clonable.hh new file mode 100644 index 0000000..a198c02 --- /dev/null +++ b/libgringo/gringo/clonable.hh @@ -0,0 +1,50 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_CLONABLE_HH +#define _GRINGO_CLONABLE_HH + +namespace Gringo { + +// {{{ declaration of Clonable + +template +class Clonable { +public: + virtual Base *clone() const = 0; + virtual ~Clonable() { } +}; + +// }}} + +} // namespace Gringo + +#define GRINGO_CALL_CLONE(T) \ +namespace Gringo { \ +template <> \ +struct clone { \ + inline T operator()(T const &x) const { \ + return x.clone(); \ + } \ +}; \ +} + +#endif // _GRINGO_CLONABLE_HH + diff --git a/libgringo/gringo/comparable.hh b/libgringo/gringo/comparable.hh new file mode 100644 index 0000000..ad8ba92 --- /dev/null +++ b/libgringo/gringo/comparable.hh @@ -0,0 +1,42 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_COMPARABLE_HH +#define _GRINGO_COMPARABLE_HH + +namespace Gringo { + +// {{{ declaration of Comparable + +template +class Comparable { +public: + virtual bool operator==(Base const &other) const = 0; + virtual bool operator!=(Base const &other) const { return !(*this == other); } + virtual ~Comparable() { } +}; + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_COMPARABLE_HH + + diff --git a/libgringo/gringo/control.hh b/libgringo/gringo/control.hh new file mode 100644 index 0000000..6338d6f --- /dev/null +++ b/libgringo/gringo/control.hh @@ -0,0 +1,284 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_CONTROL_HH +#define _GRINGO_CONTROL_HH + +#include +#include +#include +#include +#include +#include +#include + +namespace Gringo { + +// {{{1 declaration of SolveResult + +class SolveResult { +public: + enum Satisfiabily : unsigned { Unknown=0, Satisfiable=1, Unsatisfiable=2 }; + SolveResult(Satisfiabily status, bool exhausted, bool interrupted) + : repr_(static_cast(status) | (exhausted << 2) | (interrupted << 3)) { } + SolveResult(unsigned repr) + : repr_(repr) { } + Satisfiabily satisfiable() const { return static_cast(repr_ & 3); } + bool exhausted() const { return (repr_ >> 2) & 1; } + bool interrupted() const { return (repr_ >> 3) & 1; } + operator unsigned() const { return repr_; } +private: + unsigned repr_; +}; + +// {{{1 declaration of Context + +struct Context { + virtual bool callable(String name) const = 0; + virtual SymVec call(Location const &loc, String name, SymSpan args) = 0; + virtual ~Context() noexcept = default; +}; + +// {{{1 declaration of Model + +enum class ModelType : clingo_model_type_t { + StableModel = clingo_model_type_stable_model, + BraveConsequences = clingo_model_type_brave_consequences, + CautiousConsequences = clingo_model_type_cautious_consequences +}; +using Model = clingo_model; +using Int64Vec = std::vector; + +} // namespace Gringo + +using ShowType = clingo_show_type_bitset_t; +struct clingo_model { + using LitVec = std::vector>; + virtual bool contains(Gringo::Symbol atom) const = 0; + virtual Gringo::SymSpan atoms(ShowType showset) const = 0; + virtual Gringo::Int64Vec optimization() const = 0; + virtual bool optimality_proven() const = 0; + virtual void addClause(LitVec const &lits) const = 0; + virtual uint64_t number() const = 0; + virtual Potassco::Id_t threadId() const = 0; + virtual Gringo::ModelType type() const = 0; + virtual ~clingo_model() { } +}; + +namespace Gringo { + +// {{{1 declaration of SolveFuture + +struct SolveFuture { + virtual SolveResult get() = 0; + virtual void wait() = 0; + virtual bool wait(double timeout) = 0; + virtual void cancel() = 0; + virtual ~SolveFuture() { } +}; + +// {{{1 declaration of SolveIter + +struct SolveIter { + virtual Model const *next() = 0; + virtual void close() = 0; + virtual SolveResult get() = 0; + virtual ~SolveIter() { } +}; + +// {{{1 declaration of ConfigProxy + +struct ConfigProxy { + virtual bool hasSubKey(unsigned key, char const *name, unsigned* subKey = nullptr) = 0; + virtual unsigned getSubKey(unsigned key, char const *name) = 0; + virtual unsigned getArrKey(unsigned key, unsigned idx) = 0; + virtual void getKeyInfo(unsigned key, int* nSubkeys = 0, int* arrLen = 0, const char** help = 0, int* nValues = 0) const = 0; + virtual const char* getSubKeyName(unsigned key, unsigned idx) const = 0; + virtual bool getKeyValue(unsigned key, std::string &value) = 0; + virtual void setKeyValue(unsigned key, const char *val) = 0; + virtual unsigned getRootKey() = 0; +}; + +// {{{1 declaration of SymbolicAtoms + +using Control = clingo_control; +using SymbolicAtoms = clingo_symbolic_atoms; +using SymbolicAtomIter = clingo_symbolic_atom_iterator_t; + +} // namespace Gringo + +struct clingo_symbolic_atoms { + virtual Gringo::Symbol atom(Gringo::SymbolicAtomIter it) const = 0; + virtual Potassco::Lit_t literal(Gringo::SymbolicAtomIter it) const = 0; + virtual bool fact(Gringo::SymbolicAtomIter it) const = 0; + virtual bool external(Gringo::SymbolicAtomIter it) const = 0; + virtual Gringo::SymbolicAtomIter next(Gringo::SymbolicAtomIter it) = 0; + virtual bool valid(Gringo::SymbolicAtomIter it) const = 0; + virtual Gringo::SymbolicAtomIter begin(Gringo::Sig sig) const = 0; + virtual Gringo::SymbolicAtomIter begin() const = 0; + virtual Gringo::SymbolicAtomIter lookup(Gringo::Symbol atom) const = 0; + virtual bool eq(Gringo::SymbolicAtomIter it, Gringo::SymbolicAtomIter jt) const = 0; + virtual Gringo::SymbolicAtomIter end() const = 0; + virtual std::vector signatures() const = 0; + virtual size_t length() const = 0; + virtual ~clingo_symbolic_atoms() noexcept = default; +}; + +namespace Gringo { + +using TheoryData = clingo_theory_atoms; + +} // namespace Gringo + +struct clingo_theory_atoms { + enum class TermType { + Tuple = clingo_theory_term_type_tuple, + List = clingo_theory_term_type_list, + Set = clingo_theory_term_type_set, + Function = clingo_theory_term_type_function, + Number = clingo_theory_term_type_number, + Symbol = clingo_theory_term_type_symbol + }; + enum class AtomType { + Head, + Body, + Directive + }; + virtual TermType termType(Gringo::Id_t) const = 0; + virtual int termNum(Gringo::Id_t value) const = 0; + virtual char const *termName(Gringo::Id_t value) const = 0; + virtual Potassco::IdSpan termArgs(Gringo::Id_t value) const = 0; + virtual Potassco::IdSpan elemTuple(Gringo::Id_t value) const = 0; + // This shall map to ids of literals in aspif format. + virtual Potassco::LitSpan elemCond(Gringo::Id_t value) const = 0; + virtual Gringo::Lit_t elemCondLit(Gringo::Id_t value) const = 0; + virtual Potassco::IdSpan atomElems(Gringo::Id_t value) const = 0; + virtual Potassco::Id_t atomTerm(Gringo::Id_t value) const = 0; + virtual bool atomHasGuard(Gringo::Id_t value) const = 0; + virtual Potassco::Lit_t atomLit(Gringo::Id_t value) const = 0; + virtual std::pair atomGuard(Gringo::Id_t value) const = 0; + virtual Potassco::Id_t numAtoms() const = 0; + virtual std::string termStr(Gringo::Id_t value) const = 0; + virtual std::string elemStr(Gringo::Id_t value) const = 0; + virtual std::string atomStr(Gringo::Id_t value) const = 0; + virtual ~clingo_theory_atoms() noexcept = default; +}; + +namespace Gringo { + +// {{{1 declaration of Propagator + +using PropagateControl = clingo_propagate_control; +using PropagateInit = clingo_propagate_init; + +} // namespace Gringo + +struct clingo_propagate_init { + virtual Gringo::TheoryData const &theory() const = 0; + virtual Gringo::SymbolicAtoms &getDomain() = 0; + virtual Gringo::Lit_t mapLit(Gringo::Lit_t lit) = 0; + virtual void addWatch(Gringo::Lit_t lit) = 0; + virtual int threads() = 0; + virtual ~clingo_propagate_init() noexcept = default; +}; + +namespace Gringo { + +struct Propagator : Potassco::AbstractPropagator { + virtual ~Propagator() noexcept = default; + virtual void init(Gringo::PropagateInit &init) = 0; +}; +using UProp = std::unique_ptr; + +// {{{1 declaration of Control + +using FWStringVec = std::vector; +using Control = clingo_control; + +} // namespace Gringo + +struct clingo_control { + using ModelHandler = std::function; + using FinishHandler = std::function; + using Assumptions = std::vector>; + using GroundVec = std::vector>; + using NewControlFunc = Gringo::Control* (*)(int, char const **); + using FreeControlFunc = void (*)(Gringo::Control *); + + virtual Gringo::ConfigProxy &getConf() = 0; + virtual Gringo::SymbolicAtoms &getDomain() = 0; + + virtual void ground(GroundVec const &vec, Gringo::Context *context) = 0; + virtual Gringo::SolveResult solve(ModelHandler h, Assumptions &&assumptions) = 0; + virtual Gringo::SolveFuture *solveAsync(ModelHandler mh, FinishHandler fh, Assumptions &&assumptions) = 0; + virtual Gringo::SolveIter *solveIter(Assumptions &&assumptions) = 0; + virtual void interrupt() = 0; + virtual void *claspFacade() = 0; + virtual void add(std::string const &name, Gringo::FWStringVec const ¶ms, std::string const &part) = 0; + virtual void load(std::string const &filename) = 0; + virtual Gringo::Symbol getConst(std::string const &name) = 0; + virtual bool blocked() = 0; + virtual void assignExternal(Gringo::Symbol ext, Potassco::Value_t val) = 0; + virtual Potassco::AbstractStatistics *statistics() = 0; + virtual void useEnumAssumption(bool enable) = 0; + virtual bool useEnumAssumption() = 0; + virtual void cleanupDomains() = 0; + virtual Gringo::TheoryData const &theory() const = 0; + virtual void registerPropagator(std::unique_ptr p, bool sequential) = 0; + virtual void registerObserver(std::unique_ptr program) = 0; + virtual Potassco::Atom_t addProgramAtom() = 0; + virtual Gringo::Backend *backend() = 0; + virtual Gringo::Logger &logger() = 0; + virtual void beginAdd() = 0; + virtual void add(clingo_ast_statement_t const &stm) = 0; + virtual void endAdd() = 0; + virtual ~clingo_control() noexcept = default; +}; + +namespace Gringo { + +// {{{1 declaration of GringoModule + +struct GringoModule { + virtual Gringo::Control *newControl(int argc, char const * const *argv, Gringo::Logger::Printer p, unsigned messageLimit) = 0; + virtual Gringo::Symbol parseValue(std::string const &repr, Gringo::Logger::Printer p, unsigned messageLimit) = 0; + virtual ~GringoModule() noexcept = default; +}; + +// {{{1 declaration of ClingoError + +struct ClingoError : std::exception { }; + +void inline clingo_expect(bool expr) { + if (!expr) { throw std::runtime_error("unexpected"); } +} + +void handleCError(bool ret, std::exception_ptr *exc = nullptr); +void handleCXXError(); + +#define GRINGO_CLINGO_TRY try +#define GRINGO_CLINGO_CATCH catch (...) { Gringo::handleCXXError(); return false; } return true + +// }}}1 + +} // namespace Gringo + +#endif // _GRINGO_CONTROL_HH + diff --git a/libgringo/gringo/domain.hh b/libgringo/gringo/domain.hh new file mode 100644 index 0000000..c257665 --- /dev/null +++ b/libgringo/gringo/domain.hh @@ -0,0 +1,601 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_DOMAIN_HH +#define _GRINGO_DOMAIN_HH + +#include +#include +#include +#include +#include + +namespace Gringo { + +// {{{ declaration of BinderType + +enum class BinderType { NEW, OLD, ALL }; + +inline std::ostream &operator<<(std::ostream &out, BinderType x) { + switch (x) { + case BinderType::NEW: { out << "NEW"; break; } + case BinderType::OLD: { out << "OLD"; break; } + case BinderType::ALL: { out << "ALL"; break; } + } + return out; +} + + +// }}} +// {{{ declaration of IndexUpdater + +class IndexUpdater { +public: + // Updates the index with fresh atoms from the domain. + // First traverses the atoms in the domain skipping undefined atoms and + // afterwards traversing undefined atoms that have been defined later. + virtual bool update() = 0; + virtual ~IndexUpdater() { } +}; + +using SValVec = std::vector; + +// }}} +// {{{ declaration of BindIndex + +template +class BindIndexEntry { +public: + struct Hash { + size_t operator()(BindIndexEntry const &e) const { return e.hash(); }; + size_t operator()(SymVec const &e) const { return hash_range(e.begin(), e.end()); }; + }; + using SizeType = typename Domain::SizeType; + using DataVec = std::vector; + BindIndexEntry(SymVec const &bound) + : end_(0) + , reserved_(1) + , data_(nullptr) + , begin_(nullptr) { + data_ = reinterpret_cast(malloc(sizeof(uint64_t) * bound.size() + sizeof(SizeType))); + if (!data_) { throw std::bad_alloc(); } + begin_ = reinterpret_cast(data_ + bound.size()); + uint64_t *it = data_; + for (auto &sym : bound) { *it++ = sym.rep(); } + } + BindIndexEntry(BindIndexEntry const &) = delete; + BindIndexEntry(BindIndexEntry &&e) + : end_(0) + , reserved_(0) + , data_(nullptr) + , begin_(nullptr) { *this = std::move(e); } + BindIndexEntry &operator=(BindIndexEntry const &) = delete; + BindIndexEntry &operator=(BindIndexEntry &&e) { + std::swap(data_, e.data_); + std::swap(begin_, e.begin_); + std::swap(end_, e.end_); + std::swap(reserved_, e.reserved_); + return *this; + } + ~BindIndexEntry() { free(data_); } + SizeType const *begin() const { return begin_; } + SizeType const *end() const { return begin_ + end_; } + void push(SizeType x) { + assert(reserved_ > 0 && end_ <= reserved_); + if (end_ == reserved_) { + size_t bound = reinterpret_cast(begin_) - data_; + size_t oldsize = sizeof(uint64_t) * bound + sizeof(SizeType) * end_; + size_t size = oldsize + sizeof(SizeType) * end_; + if (size < oldsize) { throw std::runtime_error("size limit exceeded"); } + uint64_t *ret = reinterpret_cast(realloc(data_, size)); + if (!ret) { throw std::bad_alloc(); } + reserved_ = 2 * end_; + if (data_ != ret) { + data_ = ret; + begin_ = reinterpret_cast(data_ + bound); + } + } + begin_[end_++] = x; + } + size_t hash() const { + return hash_range(data_, reinterpret_cast(begin_)); + } + bool operator==(BindIndexEntry const &x) const { + return std::equal(x.data_, reinterpret_cast(x.begin_), data_, [](uint64_t a, uint64_t b) { return a == b; }); + } + bool operator==(SymVec const &vec) const { + return std::equal(vec.begin(), vec.end(), data_, [](Symbol const &a, uint64_t b) { return a.rep() == b; }); + } +private: + Id_t end_; + Id_t reserved_; + uint64_t* data_; + SizeType* begin_; +}; + +// An index for a positive literal occurrence +// with at least one variable bound and one variable unbound. +template +class BindIndex : public IndexUpdater { +public: + using SizeType = typename Domain::SizeType; + using OffsetVec = std::vector; + using Iterator = SizeType const *; + using Entry = BindIndexEntry; + using Index = UniqueVec; + + struct OffsetRange { + bool next(Id_t &offset, Term const &repr, BindIndex &idx) { + if (current != end) { + offset = *current++; + repr.match(idx.domain_[offset]); + return true; + } + return false; + } + Iterator current; + Iterator end; + }; + + BindIndex(Domain &domain, SValVec &&bound, UTerm &&repr) + : repr_(std::move(repr)) + , domain_(domain) + , bound_(std::move(bound)) { + assert(!bound_.empty()); + } + + bool update() override { + return domain_.update([this](SizeType offset) { add(offset); }, *repr_, imported_, importedDelayed_); + } + + // Returns a range of offsets corresponding to atoms that match the given bound variables. + OffsetRange lookup(SValVec const &bound, BinderType type, Logger &) { + boundVals_.clear(); + for (auto &&x : bound) { boundVals_.emplace_back(*x); } + auto it(data_.find(boundVals_)); + if (it != data_.end()) { + auto cmp = [this](SizeType a, SizeType gen) { return domain_[a].generation() < gen; }; + switch (type) { + case BinderType::NEW: { return { std::lower_bound(it->begin(), it->end(), domain_.generation(), cmp), it->end() }; } + case BinderType::OLD: { return { it->begin(), std::lower_bound(it->begin(), it->end(), domain_.generation(), cmp) }; } + case BinderType::ALL: { return { it->begin(), it->end() }; } + } + } + return { nullptr, nullptr }; + } + + // The equality and hash functions are used to prevent adding structurally equivalent indices twice. + bool operator==(BindIndex const &x) const { + return *repr_ == *x.repr_; + } + + size_t hash() const { + return repr_->hash(); + } + + virtual ~BindIndex() noexcept = default; + +private: + // Adds an atom given by its offset to the index. + // Assumes that the atom matches and has not been added previously. + void add(Id_t offset) { + boundVals_.clear(); + for (auto &y : bound_) { boundVals_.emplace_back(*y); } + auto jt = data_.findPush(boundVals_, boundVals_).first; + jt->push(offset); + } + +private: + UTerm const repr_; + Domain &domain_; + SValVec bound_; + SymVec boundVals_; + Index data_; + Id_t imported_ = 0; + Id_t importedDelayed_ = 0; +}; + +// }}} +// {{{ declaration of FullIndex + +// An index for a positive literal occurrence with all literals unbound. +// The matches are represented as ranges. +// This means a literal of form p(X,Y) where both X and Y are unbound has an index with just one range. +template +class FullIndex : public IndexUpdater { +public: + using SizeType = typename Domain::SizeType; + using IntervalVec = std::vector>; + using Iterator = typename IntervalVec::iterator; + + struct OffsetRange { + bool next(SizeType &offset, Term const &repr, FullIndex &idx) { + // For Old and All atoms, iterate forward until the atoms in the index are exceeded. + // For Old atoms stop early if the atoms do not belong to previous generations anymore. + if (type != BinderType::NEW) { + if (rangeOffset == idx.index_.size()) { + return false; + } + if (intervalOffset == idx.index_[rangeOffset].second) { + ++rangeOffset; + if (rangeOffset == idx.index_.size()) { + return false; + } + intervalOffset = idx.index_[rangeOffset].first; + } + offset = intervalOffset++; + auto &atom = idx.domain_[offset]; + if (type == BinderType::OLD && atom.generation() >= idx.domain_.generation()) { + rangeOffset = static_cast(idx.index_.size()); + return false; + } + } + // For New atoms iterate backward until the atoms do not belong to the current generation anymore. + else { + if (rangeOffset == 0) { + return false; + } + if (intervalOffset == idx.index_[rangeOffset - 1].first) { + --rangeOffset; + if (rangeOffset == 0) { + return false; + } + intervalOffset = idx.index_[rangeOffset-1].second; + } + offset = --intervalOffset; + auto &atom = idx.domain_[offset]; + if (atom.generation() < idx.domain_.generation()) { + rangeOffset = 0; + return false; + } + } + repr.match(idx.domain_[offset]); + return true; + } + BinderType type; + SizeType rangeOffset; + SizeType intervalOffset; + }; + + // This index can be initialized to skip some atoms in a domain. + // The number of skipped atoms are part of the equality and hash comparisons of the index. + // This is used to implement projection in the incremental case. + FullIndex(Domain &domain, UTerm &&repr, Id_t imported) + : repr_(std::move(repr)) + , domain_(domain) + , imported_(imported) + , initialImport_(imported) { } + + // Returns a range of offsets corresponding to matching atoms. + OffsetRange lookup(BinderType type, Logger &) { + switch (type) { + case BinderType::OLD: + case BinderType::ALL: { return { type, 0, !index_.empty() ? index_.front().first : 0 }; } + case BinderType::NEW: { return { type, static_cast(index_.size()), !index_.empty() ? index_.back().second : 0 }; } + } + throw std::logic_error("cannot happen"); + } + + bool update() override { + return domain_.update([this](SizeType offset) { add(offset); return true; }, *repr_, imported_, importedDelayed_); + } + + bool operator==(FullIndex const &x) const { + return *repr_ == *x.repr_ && initialImport_ == x.initialImport_; + } + + size_t hash() const { + return get_value_hash(repr_, initialImport_); + } + + virtual ~FullIndex() noexcept = default; + +private: + // Adds an atom offset to the index. + // The offset is merged into the last interval if possible. + // Maintains the generation order by always inserting at the end. + void add(SizeType offset) { + if (!index_.empty() && index_.back().second == offset) { + index_.back().second++; + } + else { + index_.emplace_back(offset, offset + 1); + } + } + +private: + UTerm repr_; + Domain &domain_; + IntervalVec index_; + Id_t imported_; + Id_t importedDelayed_ = 0; + Id_t initialImport_; +}; + +// }}} +// {{{ declaration of Domain + +class Domain { +public: + virtual void init() = 0; + virtual void enqueue() = 0; + virtual bool dequeue() = 0; + virtual bool isEnqueued() const = 0; + // Advances the domain to the next generation. + // Returns true if there are fresh atoms that have to be incorporated into the indices. + virtual void nextGeneration() = 0; + virtual void setDomainOffset(Id_t offset) = 0; + virtual Id_t domainOffset() const = 0; + + virtual ~Domain() { } +}; +using UDom = std::unique_ptr; +using UDomVec = std::vector; + +// }}} +// {{{ declaration of AbstractDomain + +template +class AbstractDomain : public Domain { +public: + using Atom = T; + using Atoms = UniqueVec, EqualToKey>; + using BindIndex = Gringo::BindIndex; + using FullIndex = Gringo::FullIndex; + using BindIndices = std::unordered_set>; + using FullIndices = std::unordered_set>; + using AtomVec = typename Atoms::Vec; + using Iterator = typename AtomVec::iterator; + using ConstIterator = typename AtomVec::const_iterator; + using SizeType = typename Atoms::SizeType; + using OffsetVec = std::vector; + + AbstractDomain() = default; + AbstractDomain(AbstractDomain const &) = delete; + AbstractDomain(AbstractDomain &&) = delete; + + // All indices that use a domain have to be registered with it. + BindIndex &add(SValVec &&bound, UTerm &&repr) { + auto ret(indices_.emplace(*this, std::move(bound), std::move(repr))); + auto &idx = const_cast(*ret.first); + idx.update(); + return idx; + } + + FullIndex &add(UTerm &&repr, Id_t imported) { + auto ret(fullIndices_.emplace(*this, std::move(repr), imported)); + auto &idx = const_cast(*ret.first); + idx.update(); + return idx; + } + + // Function to lookup negative literals or non-recursive atoms. + bool lookup(SizeType &offset, Term const &repr, RECNAF naf, Logger &log) { + bool undefined = false; + switch (naf) { + case RECNAF::POS: { + // Note: intended for non-recursive case only + auto it = atoms_.find(repr.eval(undefined, log)); + if (!undefined && it != atoms_.end() && it->defined()) { + offset = static_cast(it - begin()); + return true; + } + break; + } + case RECNAF::NOT: { + auto it = atoms_.find(repr.eval(undefined, log)); + if (!undefined && it != atoms_.end()) { + if (!it->fact()) { + offset = static_cast(it - begin()); + return true; + } + } + else if (!undefined) { + // This can only happen if literals are used negatively and non-recursively. + // Example: a :- not b. + offset = std::numeric_limits::max(); + return true; + } + break; + } + case RECNAF::RECNOT: { + auto it = reserve(repr.eval(undefined, log)); + if (!undefined && !it->fact()) { + offset = static_cast(it - begin()); + return true; + } + break; + } + case RECNAF::NOTNOT: { + // Note: intended for recursive case only + auto it = reserve(repr.eval(undefined, log)); + if (!undefined) { + offset = static_cast(it - begin()); + return true; + } + break; + } + } + offset = std::numeric_limits::max(); + return false; + } + + // Function to lookup recursive atoms. + bool lookup(SizeType &offset, Term const &repr, BinderType type, Logger &log) { + // Note: intended for recursive case only + bool undefined = false; + auto it = atoms_.find(repr.eval(undefined, log)); + if (!undefined && it != atoms_.end() && it->defined()) { + switch (type) { + case BinderType::OLD: { + if (it->generation() < generation_) { + offset = static_cast(it - begin()); + return true; + } + break; + } + case BinderType::ALL: { + if (it->generation() <= generation_) { + offset = static_cast(it - begin()); + return true; + } + break; + } + case BinderType::NEW: { + if (it->generation() == generation_) { + offset = static_cast(it - begin()); + return true; + } + break; + } + } + } + offset = std::numeric_limits::max(); + return false; + } + + // Loops over all atoms that might have to be imported into an index. + // Already seen atoms are indicated with the two offset parameters. + // Returns true if a maching atom was falls. + // Furthermore, accepts a callback f that receives the offset of a matching atom. + // If the callback returns false the search for matching atoms is stopped and the function returns true. + template + bool update(F f, Term const &repr, SizeType &imported, SizeType &importedDelayed) { + bool ret = false; + for (auto it(atoms_.begin() + imported), ie(atoms_.end()); it < ie; ++it, ++imported) { + if (it->defined()) { + if (!it->delayed() && repr.match(*it)) { + ret = true; + f(imported); + } + } + else { it->markDelayed(); } + } + for (auto it(delayed_.begin() + importedDelayed), ie(delayed_.end()); it < ie; ++it) { + auto &atom = operator[](*it); + if (repr.match(atom)) { + ret = true; + f(*it); + } + } + importedDelayed = static_cast(delayed_.size()); + return ret; + } + + void clear() { + atoms_.clear(); + indices_.clear(); + fullIndices_.clear(); + generation_ = 0; + } + void reset() { + indices_.clear(); + fullIndices_.clear(); + } + + // Returns the current generation. + // The generation corresponds to the number of grounding iterations + // the domain was involved in. + SizeType generation() const { return generation_; } + // Resevers an atom for a recursive negative literal. + // This does not set a generation. + Iterator reserve(Symbol x) { return atoms_.findPush(x, x).first; } + // Defines (adds) an atom setting its generation. + std::pair define(Symbol value) { + auto ret = atoms_.findPush(value, value); + if (ret.second) { + ret.first->setGeneration(generation() + 1); + } + else if (!ret.first->defined()) { + ret.second = true; + ret.first->setGeneration(generation() + 1); + if (ret.first->delayed()) { + delayed_.emplace_back(ret.first - begin()); + } + } + return ret; + } + void define(SizeType offset) { + auto &atm = operator[](offset); + if (!atm.defined()) { + atm.setGeneration(generation() + 1); + if (atm.delayed()) { + delayed_.emplace_back(offset); + } + } + } + // Sets the generation of the domain and all atoms back to zero. + void init() override { + generation_ = 0; + for (auto it = begin() + initOffset_, ie = end(); it != ie; ++it) { + if (it->defined()) { it->setGeneration(0); } + else { it->markDelayed(); } + } + initOffset_ = atoms_.size(); + for (auto it = delayed_.begin() + initDelayedOffset_, ie = delayed_.end(); it != ie; ++it) { + operator[](*it).setGeneration(0); + } + initDelayedOffset_ = static_cast(delayed_.size()); + } + // A domain is enqueued for two grounding iterations. + // This gives atoms a chance to go from state Open -> New -> Old. + void enqueue() override { enqueued_ = 2; } + bool dequeue() override { + --enqueued_; + assert(0 <= enqueued_ && enqueued_ <= 2); + return enqueued_ > 0; + } + bool isEnqueued() const override { return enqueued_ > 0; } + void nextGeneration() override { ++generation_; } + OffsetVec &delayed() { return delayed_; } + Iterator find(Symbol x) { return atoms_.find(x); } + ConstIterator find(Symbol x) const { return atoms_.find(x); } + Id_t size() const { return atoms_.size(); } + Iterator begin() { return atoms_.begin(); } + Iterator end() { return atoms_.end(); } + ConstIterator begin() const { return atoms_.begin(); } + ConstIterator end() const { return atoms_.end(); } + Atom &operator[](Id_t x) { return atoms_[x]; } + void setDomainOffset(Id_t offset) override { domainOffset_ = offset; } + Id_t domainOffset() const override { return domainOffset_; } + + virtual ~AbstractDomain() noexcept { } +protected: + void hide(Iterator it) { atoms_.hide(it); } + +protected: + BindIndices indices_; + FullIndices fullIndices_; + Atoms atoms_; + OffsetVec delayed_; + Id_t enqueued_ = 0; + Id_t generation_ = 0; + Id_t initOffset_ = 0; + Id_t initDelayedOffset_ = 0; + Id_t domainOffset_ = InvalidId; +}; + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_DOMAIN_HH + + diff --git a/libgringo/gringo/graph.hh b/libgringo/gringo/graph.hh new file mode 100644 index 0000000..688de88 --- /dev/null +++ b/libgringo/gringo/graph.hh @@ -0,0 +1,159 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GRAPH_HH +#define _GRINGO_GRAPH_HH + +#include +#include + +namespace Gringo { + +// {{{ declaration of Graph + +template +class Graph { +public: + struct Node; + typedef std::vector NodeVec; + typedef std::vector SCCVec; + struct Node { + friend class Graph; + template + Node(unsigned phase, U &&...x); + Node(Node const &) = delete; + void insertEdge(Node &n); + typename NodeVec::const_iterator begin() const; + typename NodeVec::const_iterator end() const; + + T data; + private: + NodeVec edges_; + unsigned visited_; + typename NodeVec::iterator finished_; + }; + + Graph(); + Graph(Graph &&g); + Graph(Graph const &) = delete; + Graph &operator=(Graph &&) = default; + Graph &operator=(Graph const &) = delete; + SCCVec tarjan(); + template + Node &insertNode(U &&...x); +private: + unsigned nphase() { return phase_ == 0 ? 1 : 0; } + typedef std::forward_list NodeList; + NodeList nodes_; + unsigned phase_ = 0; +}; + +// }}} + +// {{{ definition of Graph::Node + +template +template +Graph::Node::Node(unsigned phase, U &&...data) + : data(std::forward(data)...) + , visited_(phase) { } + +template +void Graph::Node::insertEdge(Node &n) { + edges_.emplace_back(&n); +} + +template +typename Graph::NodeVec::const_iterator Graph::Node::begin() const { + return edges_.begin(); +} + +template +typename Graph::NodeVec::const_iterator Graph::Node::end() const { + return edges_.end(); +} + +// }}} +// {{{ definition of Graph + +template +Graph::Graph() = default; + +template +Graph::Graph(Graph &&) = default; + +template +template +typename Graph::Node &Graph::insertNode(U &&... x) { + nodes_.emplace_front(nphase(), std::forward(x)...); + return nodes_.front(); +} + +template +typename Graph::SCCVec Graph::tarjan() { + SCCVec sccs; + NodeVec stack; + NodeVec trail; + for (auto &x : nodes_) { + if (x.visited_ == nphase()) { + unsigned index = 1; + auto push = [&stack, &trail, &index](Node &x) { + x.visited_ = ++index; + x.finished_ = x.edges_.begin(); + stack.emplace_back(&x); + trail.emplace_back(&x); + }; + push(x); + while (!stack.empty()) { + auto &y = stack.back(); + auto end = y->edges_.end(); + for (; y->finished_ != end && (*y->finished_)->visited_ != nphase(); ++y->finished_) { } + if (y->finished_ != end) { push(**y->finished_++); } + else { + stack.pop_back(); + bool root = true; + for (auto &z : y->edges_) { + if (z->visited_ != phase_ && z->visited_ < y->visited_) { + root = false; + y->visited_ = z->visited_; + } + } + if (root) { + sccs.emplace_back(); + do { + sccs.back().emplace_back(trail.back()); + trail.back()->visited_ = phase_; + trail.pop_back(); + } + while (sccs.back().back() != y); + } + } + } + } + } + phase_ = nphase(); + return std::move(sccs); +} + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_GRAPH_HH diff --git a/libgringo/gringo/ground/binders.hh b/libgringo/gringo/ground/binders.hh new file mode 100644 index 0000000..120bc26 --- /dev/null +++ b/libgringo/gringo/ground/binders.hh @@ -0,0 +1,204 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_BINDERS_HH +#define _GRINGO_GROUND_BINDERS_HH + +#include +#include + +namespace Gringo { namespace Ground { + +// {{{ definition of PosBinder + +template +struct PosBinder : Binder { + using IndexType = typename std::remove_reference::type; + using Match = typename IndexType::SizeType; + using MatchRng = typename IndexType::OffsetRange; + using Lookup = std::tuple; + PosBinder(UTerm &&repr, Match &result, Index &&index, BinderType type, LookupArgs&&... args) + : repr(std::move(repr)) + , result(result) + , index(std::forward(index), std::forward(args)...) + , type(type) { } + + template < int... I> struct lookup; + template struct lookup : lookup { }; + template < int... I> struct lookup<0, I...> { + MatchRng operator()(std::tuple &index, BinderType type, Logger &log) { + return std::get<0>(index).lookup(std::get(index)..., type, log); + } + }; + + IndexUpdater *getUpdater() override { return &std::get<0>(index); } + void match(Logger &log) override { current = lookup()(index, type, log); } + bool next() override { return current.next(result, *repr, std::get<0>(index)); } + void print(std::ostream &out) const override { out << *repr << "@" << type; } + virtual ~PosBinder() { } + + UTerm repr; // problematic + Match &result; + Lookup index; + MatchRng current; + BinderType type; +}; + +// }}} +// {{{ definition of Matcher + +template +struct Matcher : Binder { + using DomainType = AbstractDomain; + using Match = typename DomainType::SizeType; + + Matcher(Match &result, DomainType &domain, Term const &repr, RECNAF naf) + : result(result) + , domain(domain) + , repr(repr) + , naf(naf) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + firstMatch = domain.lookup(result, repr, naf, log); + } + bool next() override { + bool ret = firstMatch; + firstMatch = false; + return ret; + } + void print(std::ostream &out) const override { + out << naf << repr << "[" << domain.generation() << "/" << domain.size() << "]" << "@ALL"; + } + virtual ~Matcher() { } + + Match &result; + DomainType &domain; + Term const &repr; + RECNAF naf; + bool firstMatch; +}; + +// }}} +// {{{ definition of PosMatcher + +template +struct PosMatcher : Binder, IndexUpdater { + using DomainType = AbstractDomain; + using Match = typename DomainType::SizeType; + + PosMatcher(Match &result, DomainType &domain, UTerm &&repr, BinderType type) + : result(result) + , domain(domain) + , repr(std::move(repr)) + , type(type) { } + IndexUpdater *getUpdater() override { return type == BinderType::NEW ? this : nullptr; } + void match(Logger &log) override { + firstMatch = domain.lookup(result, *repr, type, log); + } + bool next() override { + bool ret = firstMatch; + firstMatch = false; + return ret; + } + bool update() override { return domain.update([](unsigned) { }, *repr, imported, importedDelayed); } + void print(std::ostream &out) const override { out << *repr << "[" << domain.generation() << "/" << domain.size() << "]" << "@" << type; } + virtual ~PosMatcher() { }; + + Match &result; + DomainType &domain; + UTerm repr; + BinderType type; + unsigned imported = 0; + unsigned importedDelayed = 0; + bool firstMatch = false; +}; + +// }}} +// {{{ definition of make_binder + +// Note: does not (quite) work this way +// but it should be enough to make imported part of the key of full_indices + +template +inline UIdx make_binder(AbstractDomain &domain, NAF naf, Term const &repr, typename AbstractDomain::SizeType &elem, BinderType type, bool recursive, Term::VarSet &bound, int imported) { + using DomainType = AbstractDomain; + using PredicateMatcher = Matcher; + using PosPredicateMatcher = PosMatcher; + using PosPredicateBinder = PosBinder; + using FullPredicateBinder = PosBinder; + if (naf == NAF::POS) { + UTerm predClone(repr.clone()); + VarTermBoundVec occs; + predClone->collect(occs, false); + bool hasUnbound = false; + for (auto &x : occs) { + if ((x.first->bindRef = bound.find(x.first->name) == bound.end())) { + hasUnbound = true; + } + } + if (hasUnbound) { + Term::VarSet occBoundSet; + VarTermVec occBound; + for (auto &x : occs) { + if (x.first->bindRef) { x.first->bindRef = bound.emplace(x.first->name).second; } + else if (occBoundSet.emplace(x.first->name).second) { occBound.emplace_back(*x.first); } + } + Term::RenameMap rename; + UTerm idxClone(predClone->renameVars(rename)); + SValVec predBound, idxBound; + for (VarTerm &x : occBound) { + auto it(rename.find(x.name)); + predBound.emplace_back(x.ref); + idxBound.emplace_back(it->second.second); + } + Term::VarSet empty; + idxClone->bind(empty); + if (occBound.empty()) { + auto &idx(domain.add(std::move(idxClone), imported)); + return gringo_make_unique(std::move(predClone), elem, idx, type); + } + else { + assert(imported == 0); + auto &idx(domain.add(std::move(idxBound), std::move(idxClone))); + return gringo_make_unique(std::move(predClone), elem, idx, type, std::move(predBound)); + } + } + else if (recursive) { + assert(imported == 0); + Term::VarSet empty; + predClone->bind(empty); + return gringo_make_unique(elem, domain, std::move(predClone), type); + } + else { + assert(imported == 0); + return gringo_make_unique(elem, domain, repr, RECNAF::POS); + } + } + else { + assert(imported == 0); + return gringo_make_unique(elem, domain, repr, recnaf(naf, recursive)); + } +} + +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_BINDERS_HH diff --git a/libgringo/gringo/ground/dependency.hh b/libgringo/gringo/ground/dependency.hh new file mode 100644 index 0000000..33147be --- /dev/null +++ b/libgringo/gringo/ground/dependency.hh @@ -0,0 +1,296 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_DEPENDENCY_HH +#define _GRINGO_GROUND_DEPENDENCY_HH + +#include +#include +#include + +namespace Gringo { namespace Ground { + +// {{{ declaration of Lookup + +template +struct Lookup { + typedef std::unordered_multimap SigLookup; + typedef std::unordered_multimap, value_equal_to> Occurrences; + typedef typename Occurrences::iterator iterator; + //! Adds an occurrence associated with a term. + //! If there is already an occurrence with a structurally equivalent term, + //! then the method returns true. Otherwise, the method returns false and + //! the freshly inserted occurrence is associated with the (representative) + //! term already present. + bool add(GTerm &term, Occ &&occ); + template + void match(Symbol x, Callback const &c); + template + void unify(GTerm &x, Callback const &c); + ~Lookup(); + +private: + template + void unify(GTerm &x, SigLookup &y, Callback const &c); + + SigLookup terms; + SigLookup constTerms; +public: + Occurrences occs; +}; + +// }}} +// {{{ declaration of BodyOccurrence + +using LocSet = std::set; +using SigSet = UniqueVec; +using UndefVec = std::vector>; + +enum class OccurrenceType { POSITIVELY_STRATIFIED, STRATIFIED, UNSTRATIFIED }; +template +class BodyOccurrence { +public: + using DefinedBy = std::vector>; + virtual UGTerm getRepr() const = 0; + virtual bool isPositive() const = 0; + virtual bool isNegative() const = 0; + virtual void setType(OccurrenceType x) = 0; + virtual OccurrenceType getType() const = 0; + virtual DefinedBy &definedBy() = 0; + virtual void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const = 0; + virtual ~BodyOccurrence() { } +}; + +// }}} +// {{{ declaration of Dependency + +template +struct Dependency { + struct Node; + typedef std::vector NodeVec; + typedef std::tuple*, NodeVec, bool> Depend; + typedef std::pair Provide; + typedef Ground::Lookup Lookup; + typedef Graph G; + typedef std::vector,bool>> ComponentVec; + struct Node { + Node(Stm &&stm, bool normal) : stm(std::forward(stm)), normal(normal) { } + + Stm stm; + bool normal; + std::vector depend; + typename G::Node *graphNode = nullptr; + unsigned negSCC = 0; + unsigned posSCC = 0; + }; + + Node &add(Stm &&stm, bool normal); + void depends(Node& n, BodyOccurrence &occ, bool forceNegative = false); + void provides(Node& n, HeadOcc &occ, UGTerm &&term); + ComponentVec analyze(); + + UGTermVec terms; + Lookup depend; + std::forward_list nodes; + std::vector, UGTerm>> heads; +}; + +// }}} + +// {{{ definition of Lookup + +template +bool Lookup::add(GTerm &term, Occ &&x) { + auto it = occs.find(&term); + if (it == occs.end()) { + if (term.eval().first) { constTerms.emplace(term.sig(), &term); } + else { terms.emplace(term.sig(), &term); } + occs.emplace(&term, std::forward(x)); + return true; + } + else { + occs.emplace_hint(it, it->first, std::forward(x)); + return false; + } +} + +template +template +void Lookup::match(Symbol x, Callback const &c) { + if (x.type() == SymbolType::Fun) { + auto ir(terms.equal_range(x.sig())); + for (auto it = ir.first; it != ir.second; ++it) { + if (it->second->match(x)) { + auto rng(occs.equal_range(it->second)); + assert(rng.first != rng.second); + c(rng.first, rng.second); + } + it->second->reset(); + } + GValTerm y(x); + auto rng(occs.equal_range(&y)); + if (rng.first != rng.second) { c(rng.first, rng.second); } + } +} + +template +template +void Lookup::unify(GTerm &x, SigLookup &y, Callback const &c) { + auto ir(y.equal_range(x.sig())); + for (auto it = ir.first; it != ir.second; ++it) { + if (it->second->unify(x)) { + auto rng(occs.equal_range(it->second)); + assert(rng.first != rng.second); + c(rng.first, rng.second); + } + it->second->reset(); + x.reset(); + } +} + +template +template +void Lookup::unify(GTerm &x, Callback const &c) { + auto r = x.eval(); + if (r.first) { match(r.second, c); } + else { + unify(x, terms, c); + unify(x, constTerms, c); + } +} + +template +Lookup::~Lookup() { } + +// }}} +// {{{ definition of Dependency + +template +typename Dependency::Node &Dependency::add(Stm &&stm, bool normal) { + nodes.emplace_front(std::forward(stm), normal); + return nodes.front(); +} + +template +void Dependency::depends(Node& n, BodyOccurrence &occ, bool forceNegative) { + //std::cerr << *n.stm << " depends on " << *occ.getRepr() << (occ.isPositive() ? " pos" : "") << (forceNegative || occ.isNegative() ? " neg" : "") << std::endl; + terms.emplace_back(occ.getRepr()); + depend.add(*terms.back(), Provide(&n, n.depend.size())); + n.depend.emplace_back(&occ, NodeVec(), forceNegative); + occ.definedBy().clear(); +} + +template +void Dependency::provides(Node& n, HeadOcc& occ, UGTerm &&term) { + //std::cerr << *n.stm << " provides " << *term << std::endl; + heads.emplace_back(&n, occ, std::move(term)); +} + +template +typename Dependency::ComponentVec Dependency::analyze() { + // initialize nodes + for (auto &x : heads) { + auto f = [&x](typename Lookup::iterator begin, typename Lookup::iterator end) -> void { + for (auto it = begin; it != end; ++it) { + auto &dep(it->second.first->depend[it->second.second]); + std::get<1>(dep).emplace_back(std::get<0>(x)); + std::get<0>(dep)->definedBy().emplace_back(std::get<1>(x)); + } + }; + depend.unify(*std::get<2>(x), f); + } + heads.clear(); + // build dependency graph + G g; + for (auto &x : nodes) { x.graphNode = &g.insertNode(&x); } + for (auto &x : nodes) { + for (auto &y : x.depend) { + for (auto &z : std::get<1>(y)) { x.graphNode->insertEdge(*z->graphNode); } + } + } + std::vector positive; + ComponentVec components; + positive.push_back(true); + for (auto &scc : g.tarjan()) { + // dependency analysis + unsigned negSCC = positive.size(); + for (auto &graphNode : scc) { graphNode->data->negSCC = negSCC; } + positive.push_back(true); + for (auto &graphNode : scc) { + positive.back() = positive.back() && graphNode->data->normal; + for (auto &x : graphNode->data->depend) { + for (auto &y : std::get<1>(x)) { + positive.back() = positive.back() && (y->negSCC != negSCC ? positive[y->negSCC] : std::get<0>(x)->isPositive() && !std::get<2>(x)); + } + } + } + // build positive dependency graph + G gg; + for (auto &graphNode : scc) { graphNode->data->graphNode = &gg.insertNode(graphNode->data); } + for (auto &graphNode : scc) { + for (auto &x : graphNode->data->depend) { + if (!std::get<0>(x)->isNegative()) { + for (auto &y : std::get<1>(x)) { + if (y->negSCC == negSCC) { graphNode->data->graphNode->insertEdge(*y->graphNode); } + } + } + } + } + unsigned posSCC = 0; + auto posSccs(gg.tarjan()); + for (auto &scc : posSccs) { + // positive dependency analysis + for (auto &graphNode : scc) { graphNode->data->posSCC = posSCC; } + posSCC++; + } + posSCC = 0; + for (auto &scc : posSccs) { + components.emplace_back(); + for (auto &graphNode : scc) { + for (auto &x : graphNode->data->depend) { + OccurrenceType t = OccurrenceType::POSITIVELY_STRATIFIED; + for (auto &y : std::get<1>(x)) { + if (y->negSCC != negSCC) { + if (t == OccurrenceType::POSITIVELY_STRATIFIED && !positive[y->negSCC]) { t = OccurrenceType::STRATIFIED; } + } + else if (y->posSCC < posSCC) { + assert(y->negSCC == negSCC); + if (t == OccurrenceType::POSITIVELY_STRATIFIED) { t = OccurrenceType::STRATIFIED; } + } + else { + t = OccurrenceType::UNSTRATIFIED; + break; + } + } + std::get<0>(x)->setType(t); + } + components.back().second = positive.back(); + components.back().first.emplace_back(std::move(graphNode->data->stm)); + } + posSCC++; + } + } + return components; +} +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_DEPENDENCY_HH diff --git a/libgringo/gringo/ground/instantiation.hh b/libgringo/gringo/ground/instantiation.hh new file mode 100644 index 0000000..4acf25d --- /dev/null +++ b/libgringo/gringo/ground/instantiation.hh @@ -0,0 +1,126 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_INSTANTIATION_HH +#define _GRINGO_GROUND_INSTANTIATION_HH + +#include + +namespace Gringo { namespace Ground { + +// {{{ declaration of Queue + +struct Instantiator; +struct Queue { + void process(Output::OutputBase &out, Logger &log); + void enqueue(Instantiator &inst); + void enqueue(Domain &inst); + ~Queue(); + + using QueueDec = std::vector>; + using DomainVec = std::vector>; + QueueDec current; + std::array queues; + DomainVec domains; +}; + +// }}} +// {{{ declaration of Binder + +struct Binder : Printable { + virtual IndexUpdater *getUpdater() = 0; + virtual void match(Logger &log) = 0; + virtual bool next() = 0; + virtual ~Binder() { } +}; +using UIdx = std::unique_ptr; + +// }}} +// {{{ declaration if SolutionCallback + +class SolutionCallback { +public: + virtual void report(Output::OutputBase &out, Logger &log) = 0; + virtual void propagate(Queue &queue) = 0; + virtual void printHead(std::ostream &out) const = 0; + virtual unsigned priority() const { return 0; } + virtual ~SolutionCallback() noexcept = default; +}; + +// }}} +// {{{ declaration of SolutionBinder + +struct SolutionBinder : public Binder { + IndexUpdater *getUpdater() override; + void match(Logger &log) override; + bool next() override; + void print(std::ostream &out) const override; + virtual ~SolutionBinder(); +}; + +// }}} +// {{{ declaration of BackjumpBinder + +struct BackjumpBinder { + typedef std::vector DependVec; + + BackjumpBinder(UIdx &&index, DependVec &&depends); + BackjumpBinder(BackjumpBinder &&x) noexcept; + void match(Logger &log); + bool next(); + bool first(Logger &log); + void print(std::ostream &out) const; + ~BackjumpBinder(); + + UIdx index; + DependVec depends; + bool backjumpable = false; +}; +inline std::ostream &operator<<(std::ostream &out, BackjumpBinder &x) { x.print(out); return out; } + +// }}} +// {{{ declaration of Instantiator + +struct Instantiator { + using DependVec = BackjumpBinder::DependVec; + + Instantiator(SolutionCallback &callback); + Instantiator(Instantiator &&x) = default; + Instantiator &operator=(Instantiator &&x) = default; + void add(UIdx &&index, DependVec &&depends); + void finalize(DependVec &&depends); + void enqueue(Queue &queue); + void instantiate(Output::OutputBase &out, Logger &log); + void print(std::ostream &out) const; + unsigned priority() const; + ~Instantiator() noexcept; + + SolutionCallback *callback; + std::vector binders; + bool enqueued = false; +}; +using InstVec = std::vector; +inline std::ostream &operator<<(std::ostream &out, Instantiator &x) { x.print(out); return out; } + +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_INSTANTIATION_HH diff --git a/libgringo/gringo/ground/literal.hh b/libgringo/gringo/ground/literal.hh new file mode 100644 index 0000000..6249180 --- /dev/null +++ b/libgringo/gringo/ground/literal.hh @@ -0,0 +1,62 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_LITERAL_HH +#define _GRINGO_GROUND_LITERAL_HH + +#include +#include +#include + +namespace Gringo { namespace Ground { + +// {{{ declaration of HeadOccurrence + +class HeadOccurrence { +public: + virtual void defines(IndexUpdater &update, Instantiator *inst) = 0; + virtual ~HeadOccurrence() { } +}; + +// }}} + +// {{{ declaration of Literal + +using BodyOcc = BodyOccurrence; +class Literal : public Printable { +public: + using Score = double; + virtual bool auxiliary() const = 0; + virtual bool isRecursive() const = 0; + virtual UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) = 0; + virtual BodyOcc *occurrence() = 0; + virtual void collect(VarTermBoundVec &vars) const = 0; + virtual void collectImportant(Term::VarSet &vars); + virtual std::pair toOutput(Logger &log) = 0; + virtual Score score(Term::VarSet const &bound, Logger &log) = 0; + virtual ~Literal() { } +}; + +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_LITERAL_HH + diff --git a/libgringo/gringo/ground/literals.hh b/libgringo/gringo/ground/literals.hh new file mode 100644 index 0000000..f1f9c44 --- /dev/null +++ b/libgringo/gringo/ground/literals.hh @@ -0,0 +1,184 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_LITERALS_HH +#define _GRINGO_GROUND_LITERALS_HH + +#include +#include +#include + +namespace Gringo { namespace Ground { + +inline double estimate(unsigned size, Term const &term, Term::VarSet const &bound) { + Term::VarSet vars; + term.collect(vars); + bool found = false; + for (auto &x : vars) { + if (bound.find(x) != bound.end()) { + found = true; + break; + } + } + return term.estimate(size, bound) + !found * 10000000; +} + +// {{{ declaration of RangeLiteral + +using RangeLiteralShared = std::pair; +struct RangeLiteral : Literal { + RangeLiteral(UTerm &&assign, UTerm &&left, UTerm &&right); + void print(std::ostream &out) const override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + std::pair toOutput(Logger &log) override; + Score score(Term::VarSet const &bound, Logger &log) override; + bool auxiliary() const override { return true; } + virtual ~RangeLiteral(); + + UTerm assign; + RangeLiteralShared range; +}; + +// }}} +// {{{ declaration of ScriptLiteral + +using ScriptLiteralShared = std::pair; +struct ScriptLiteral : Literal { + ScriptLiteral(UTerm &&assign, String name, UTermVec &&args); + void print(std::ostream &out) const override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + std::pair toOutput(Logger &log) override; + Score score(Term::VarSet const &bound, Logger &log) override; + bool auxiliary() const override { return true; } + virtual ~ScriptLiteral(); + + UTerm assign; + ScriptLiteralShared shared; +}; + +// }}} +// {{{ declaration of RelationLiteral + +using RelationShared = std::tuple; +struct RelationLiteral : Literal { + RelationLiteral(Relation rel, UTerm &&left, UTerm &&right); + void print(std::ostream &out) const override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + std::pair toOutput(Logger &log) override; + Score score(Term::VarSet const &bound, Logger &log) override; + bool auxiliary() const override { return true; } + virtual ~RelationLiteral(); + + RelationShared shared; +}; + +// }}} +// {{{ declaration of PredicateLiteral + +struct PredicateLiteral : Literal, BodyOcc { + PredicateLiteral(bool auxiliary, PredicateDomain &domain, NAF naf, UTerm &&repr); + void print(std::ostream &out) const override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + DefinedBy &definedBy() override; + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + std::pair toOutput(Logger &log) override; + Score score(Term::VarSet const &bound, Logger &log) override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + bool auxiliary() const override { return auxiliary_; } + virtual ~PredicateLiteral(); + + OccurrenceType type = OccurrenceType::POSITIVELY_STRATIFIED; + bool auxiliary_; + UTerm repr; + DefinedBy defs; + PredicateDomain &domain; + Potassco::Id_t offset = 0; + NAF naf; + +}; + +struct ProjectionLiteral : PredicateLiteral { + ProjectionLiteral(bool auxiliary, PredicateDomain &dom, UTerm &&repr, bool initialized); + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + virtual ~ProjectionLiteral(); + bool initialized_; +}; + +// }}} +// {{{ declaration of CSPLiteral + +struct ExternalBodyOcc : BodyOcc { + ExternalBodyOcc(); + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + virtual ~ExternalBodyOcc(); + DefinedBy defs; +}; + +using CSPLiteralShared = std::tuple; +class CSPLiteral : public Literal { +public: + CSPLiteral(DomainData &data, bool auxiliary, Relation rel, CSPAddTerm &&left, CSPAddTerm &&right); + void print(std::ostream &out) const override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collectImportant(Term::VarSet &vars) override; + void collect(VarTermBoundVec &vars) const override; + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + std::pair toOutput(Logger &log) override; + Score score(Term::VarSet const &bound, Logger &log) override; + bool auxiliary() const override { return auxiliary_; } + virtual ~CSPLiteral() noexcept; + +private: + DomainData &data_; + CSPLiteralShared terms_; + ExternalBodyOcc ext_; + bool auxiliary_; +}; + +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_LITERALS_HH + + diff --git a/libgringo/gringo/ground/program.hh b/libgringo/gringo/ground/program.hh new file mode 100644 index 0000000..03df158 --- /dev/null +++ b/libgringo/gringo/ground/program.hh @@ -0,0 +1,68 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_PROGRAM_HH +#define _GRINGO_GROUND_PROGRAM_HH + +#include + +namespace Gringo { namespace Ground { + +// {{{ declaration of Program + +using IdVec = std::vector>; +using SEdb = std::shared_ptr>; +using SEdbVec = std::vector; +using SymVecSet = std::set; +using ParamSet = std::map; + +struct Parameters { + Parameters(); + void add(String name, SymVec &&args); + bool find(Sig sig) const; + ParamSet::const_iterator begin() const; + ParamSet::const_iterator end() const; + bool empty() const; + void clear(); + ~Parameters(); + ParamSet params; +}; + +struct Program { + using ClassicalNegationVec = std::vector>; + + Program(SEdbVec &&edb, Statement::Dep::ComponentVec &&stms, ClassicalNegationVec &&negate); + void linearize(Scripts &scripts, Logger &log); + void ground(Parameters const ¶ms, Scripts &scripts, Output::OutputBase &out, bool finalize, Logger &log); + void ground(Scripts &scripts, Output::OutputBase &out, Logger &log); + + SEdbVec edb; + bool linearized = false; + Statement::Dep::ComponentVec stms; + ClassicalNegationVec negate; +}; + +std::ostream &operator<<(std::ostream &out, Program const &x); + +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_PROGRAM_HH diff --git a/libgringo/gringo/ground/statement.hh b/libgringo/gringo/ground/statement.hh new file mode 100644 index 0000000..6cae522 --- /dev/null +++ b/libgringo/gringo/ground/statement.hh @@ -0,0 +1,46 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_STATEMENT_HH +#define _GRINGO_GROUND_STATEMENT_HH + +#include +#include + +namespace Gringo { namespace Ground { + +// {{{ declaration of Statement + +class Statement : public Printable { +public: + using Dep = Dependency; + virtual bool isNormal() const = 0; + virtual void analyze(Dep::Node &node, Dep &dep) = 0; + virtual void startLinearize(bool active) = 0; + virtual void linearize(Scripts &scripts, bool positive, Logger &log) = 0; + virtual void enqueue(Queue &q) = 0; + virtual ~Statement() { } +}; + +// }}} + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_STATEMENT_HH diff --git a/libgringo/gringo/ground/statements.hh b/libgringo/gringo/ground/statements.hh new file mode 100644 index 0000000..5b26c65 --- /dev/null +++ b/libgringo/gringo/ground/statements.hh @@ -0,0 +1,1274 @@ +// {{{ GPL License + +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_STATEMENTS_HH +#define _GRINGO_GROUND_STATEMENTS_HH + +#include +#include +#include +#include +#include + +namespace Gringo { namespace Ground { + +// {{{1 declaration of HeadDefinition + +class HeadDefinition : private HeadOccurrence { +public: + using OffsetMap = std::unordered_map; + using RInstVec = std::vector>; + using EnqueueVec = std::vector>; + + HeadDefinition(UTerm &&repr, Domain *domain); + HeadDefinition(HeadDefinition &&) = default; + virtual ~HeadDefinition() noexcept; + void collectImportant(Term::VarSet &vars); + void enqueue(Queue &queue); + operator bool () const { return static_cast(repr_); } + Domain &dom() { assert(domain_); return *domain_; } + UTerm const &domRepr() const { return repr_; } + void init() { + if (domain_) { domain_->init(); } + } + void setActive(bool active) { active_ = active; } + void analyze(Statement::Dep::Node &node, Statement::Dep &dep) { + if (repr_) { + dep.provides(node, *this, repr_->gterm()); + } + } +private: + // {{{2 HeadOccurrence interface + virtual void defines(IndexUpdater &update, Instantiator *inst) override; + /// }}}2 + +private: + UTerm repr_; + Domain *domain_; + OffsetMap offsets_; + EnqueueVec enqueueVec_; + bool active_ = false; +}; + +// {{{1 declaration of AbstractStatement + +class AbstractStatement : public Statement, protected SolutionCallback { +public: + AbstractStatement(UTerm &&repr, Domain *domain, ULitVec &&lits); + virtual ~AbstractStatement() noexcept; + // This function returns true if all non-auxiliary literals are non-recursive. + // The accumulation rule can use this function to mark complete rules as output recursive. + // Note that only the complete rule should set the recursive flag to false. + // Until that point all atoms should be marked as recursive to correctly capture negative recursion. + // This has to be done this way because with negative recursion, + // the complete rule might appear in a later component; + // the complete rule is guaranteed to appear after or together with an accumulation statemnt + // because of its positive dependency to them. + // TODO: This function should only consider positive recursion. + // To do this, the literal interface has to be extended. + virtual bool isOutputRecursive() const; + virtual void collectImportant(Term::VarSet &vars); + virtual void printBody(std::ostream &out) const; + // {{{2 Statement interface + bool isNormal() const override; // false by default + void analyze(Dep::Node &node, Dep &dep) override; + void startLinearize(bool active) override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + void enqueue(Queue &q) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +protected: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; + void propagate(Queue &queue) override; + // }}}2 + +protected: + HeadDefinition def_; + ULitVec lits_; + InstVec insts_; +}; + +// }}}1 + +// Statements + +// {{{1 declaration of Rule + +enum class RuleType : unsigned short { External, Disjunctive, Choice }; + +class Rule : public Statement, protected SolutionCallback { +public: + using HeadVec = std::vector>; + using HeadDefVec = std::vector; + Rule(HeadVec &&heads, ULitVec &&lits, RuleType type_); + virtual ~Rule() noexcept; + // {{{2 Statement interface + bool isNormal() const override; + void analyze(Dep::Node &node, Dep &dep) override; + void startLinearize(bool active) override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + void enqueue(Queue &q) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +protected: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + void printHead(std::ostream &out) const override; + void propagate(Queue &queue) override; + // }}}2 + +protected: + HeadDefVec defs_; + ULitVec lits_; + InstVec insts_; + RuleType type_; +}; + +// {{{1 declaration of ExternalRule + +class ExternalRule : public Statement { +public: + ExternalRule(); + virtual ~ExternalRule() noexcept; + + // {{{2 Statement Interface + virtual bool isNormal() const; + virtual void analyze(Dep::Node &node, Dep &dep); + virtual void startLinearize(bool active); + virtual void linearize(Scripts &scripts, bool positive, Logger &log); + virtual void enqueue(Queue &q); + // {{{2 Printable interface + virtual void print(std::ostream &out) const; + // }}}2 + +private: + HeadDefinition def_; +}; + +// }}}1 + +// {{{1 declaration of ShowStatement + +class ShowStatement : public AbstractStatement { +public: + ShowStatement(UTerm &&term, bool csp, ULitVec &&body); + virtual ~ShowStatement() noexcept; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + void printHead(std::ostream &out) const override; + // }}}2 + +private: + UTerm term_; + bool csp_; +}; + +// {{{1 declaration of EdgeStatement + +class EdgeStatement : public AbstractStatement { +public: + EdgeStatement(UTerm &&u, UTerm &&v, ULitVec &&body); + virtual ~EdgeStatement() noexcept; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + void printHead(std::ostream &out) const override; + // }}}2 + +private: + UTerm u_; + UTerm v_; +}; + +// {{{1 declaration of ProjectStatement + +class ProjectStatement : public AbstractStatement { +public: + ProjectStatement(UTerm &&atom, ULitVec &&body); + virtual ~ProjectStatement() noexcept; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + void printHead(std::ostream &out) const override; + // }}}2 + +private: + UTerm atom_; +}; + +// {{{1 declaration of HeuristicStatement + +class HeuristicStatement : public AbstractStatement { +public: + HeuristicStatement(UTerm &&atom, UTerm &&value, UTerm &&bias, UTerm &&mod, ULitVec &&body); + virtual ~HeuristicStatement() noexcept; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + void printHead(std::ostream &out) const override; + // }}}2 + +private: + UTerm atom_; + UTerm value_; + UTerm priority_; + UTerm mod_; +}; + +// {{{1 declaration of WeakConstraint + +class WeakConstraint : public AbstractStatement { +public: + WeakConstraint(UTermVec &&tuple, ULitVec &&body); + virtual ~WeakConstraint() noexcept; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + void printHead(std::ostream &out) const override; + // }}}2 + +private: + UTermVec tuple_; +}; + +// }}}1 + +// Body Aggregates + +// {{{1 declaration of BodyAggregateAccumulate + +using Output::BodyAggregateAtom; +using Output::BodyAggregateDomain; +class BodyAggregateComplete; + +class BodyAggregateAccumulate : public AbstractStatement { +public: + BodyAggregateAccumulate(BodyAggregateComplete &complete, UTermVec &&tuple, ULitVec &&lits); + virtual ~BodyAggregateAccumulate() noexcept; + void printHead(std::ostream &out) const override; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{3 Statement interface + bool isNormal() const override { return true; } + void linearize(Scripts &scripts, bool positive, Logger &log) override; + // }}}2 + +private: + // {{{2 SolutionCallback interface (w/o printHead) + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + BodyAggregateComplete &complete_; + UTermVec tuple_; +}; + +// {{{1 declaration of BodyAggregateComplete + +class BodyAggregateComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using AccumulateDomainVec = std::vector>; + using TodoVec = std::vector; + + BodyAggregateComplete(DomainData &data, UTerm &&repr, AggregateFunction fun, BoundVec &&bounds); + virtual ~BodyAggregateComplete() noexcept; + BodyAggregateDomain &dom() { return static_cast(def_.dom()); } + void enqueue(BodyAggregateDomain::Iterator atom); + UTerm const &accuRepr() const { return accuRepr_; } + UTerm const &domRepr() const { return def_.domRepr(); } + AggregateFunction fun() const { return fun_; } + void addAccuDom(BodyAggregateAccumulate &accu) { accuDoms_.emplace_back(accu); } + BoundVec const &bounds() const { return bounds_; } + bool monotone() const { return monotone_; } + void setOutputRecursive() { outputRecursive_ = true; } + + // {{{2 Statement interface + bool isNormal() const override; // return false -> this one creates choices + void analyze(Dep::Node &node, Dep &dep) override; // use accuDoms to build the dependency... + void startLinearize(bool active) override; // noop because single instantiator + void linearize(Scripts &scripts, bool positive, Logger &log) override; // noop because single instantiator + void enqueue(Queue &q) override; // enqueue the single instantiator + // {{{2 Printable interface + void print(std::ostream &out) const override; // #complete { h1, ..., hn } :- accu1,... , accun. + // }}}2 + +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; // #complete { h1, ..., hn } + void propagate(Queue &queue) override; // enqueue based on accuDoms + void report(Output::OutputBase &out, Logger &log) override; // loop over headDom here + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + +private: + AccumulateDomainVec accuDoms_; + HeadDefinition def_; + UTerm accuRepr_; + AggregateFunction fun_; + BoundVec bounds_; + TodoVec todo_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; + DefinedBy defBy_; + Instantiator inst_; + bool monotone_ = true; + bool outputRecursive_ = false; +}; + +// {{{1 declaration of BodyAggregateLiteral + +class BodyAggregateLiteral : public Literal, private BodyOcc { +public: + BodyAggregateLiteral(BodyAggregateComplete &complete, NAF naf); + virtual ~BodyAggregateLiteral() noexcept; + + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return false; } // by construction + // }}}2 + +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + BodyAggregateComplete &complete_; + DefinedBy defs_; + Potassco::Id_t offset_ = 0; + NAF naf_; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; +}; + +// }}}1 + +// {{{1 declaration of AssignmentAggregateAccumulate + +using Output::AssignmentAggregateAtom; +using Output::AssignmentAggregateData; +using Output::AssignmentAggregateDomain; +class AssignmentAggregateComplete; + +class AssignmentAggregateAccumulate : public AbstractStatement { +public: + AssignmentAggregateAccumulate(AssignmentAggregateComplete &complete, UTermVec &&tuple, ULitVec &&lits); + virtual ~AssignmentAggregateAccumulate() noexcept; + void printHead(std::ostream &out) const override; + + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Statement interface + virtual bool isNormal() const override { return true; } + void linearize(Scripts &scripts, bool positive, Logger &log) override; + // }}}2 + +private: + // {{{2 SolutionCallback interface (w/o printHead) + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + AssignmentAggregateComplete &complete_; + UTermVec tuple_; +}; + +// {{{1 declaration of AssignmentAggregateComplete + +class AssignmentAggregateComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using AccumulateDomainVec = std::vector>; + using TodoVec = std::vector; + + AssignmentAggregateComplete(DomainData &data, UTerm &&repr, UTerm &&dataRepr, AggregateFunction fun); + AssignmentAggregateDomain &dom() { return static_cast(def_.dom()); } + virtual ~AssignmentAggregateComplete() noexcept; + UTerm const &dataRepr() const { return dataRepr_; } + UTerm const &domRepr() const { return def_.domRepr(); } + AggregateFunction fun() const { return fun_; } + void enqueue(Id_t dataId); + void addAccuDom(AssignmentAggregateAccumulate &accu) { accuDoms_.emplace_back(accu); } + void setOutputRecursive() { outputRecursive_ = true; } + // {{{2 Statement interface + bool isNormal() const override; // return false -> this one creates choices + void analyze(Dep::Node &node, Dep &dep) override; // use accuDoms to build the dependency... + void startLinearize(bool active) override; // noop because single instantiator + void linearize(Scripts &scripts, bool positive, Logger &log) override; // noop because single instantiator + void enqueue(Queue &q) override; // enqueue the single instantiator + // {{{2 Printable interface + void print(std::ostream &out) const override; // #complete { h1, ..., hn } :- accu1,... , accun. + // }}}2 + +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; // #complete { h1, ..., hn } + void propagate(Queue &queue) override; // enqueue based on accuDoms + void report(Output::OutputBase &out, Logger &log) override; // loop over headDom here + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + +private: + AccumulateDomainVec accuDoms_; + HeadDefinition def_; + UTerm dataRepr_; + AggregateFunction fun_; + TodoVec todo_; + DefinedBy defBy_; + Instantiator inst_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; + bool outputRecursive_ = false; +}; + +// {{{1 declaration of AssignmentAggregateLiteral + +class AssignmentAggregateLiteral : public Literal, private BodyOcc { +public: + AssignmentAggregateLiteral(AssignmentAggregateComplete &complete); + virtual ~AssignmentAggregateLiteral() noexcept; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return false; } // by construction + // }}}2 + +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + AssignmentAggregateComplete &complete_; + DefinedBy defs_; + Id_t offset_ = InvalidId; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; +}; + +// }}}1 + +// {{{1 declaration of ConjunctionAccumulateEmpty + +// The following classes correspond to the rules indicated below. +// empty :- body. % to handle the empty case +// accu :- empty, cond. % accumulation of conditon (blocks if condition is a fact and no head available yet) +// accu :- empty, cond, head. % accumulation of head (blocks if no condition available yet, unblocks if there is a head and the condition is fact) +// aggr :- accu. % complete rule (let's through unblocked conjunctions) +// head :- aggr, body. % literal + +using Output::ConjunctionAtom; +using Output::ConjunctionDomain; +class ConjunctionComplete; + +class ConjunctionAccumulateEmpty : public AbstractStatement { +public: + ConjunctionAccumulateEmpty(ConjunctionComplete &complete, ULitVec &&lits); + virtual ~ConjunctionAccumulateEmpty() noexcept; + // {{{2 Statement interface + bool isNormal() const override; + // }}}2 + +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + ConjunctionComplete &complete_; +}; + +// {{{1 declaration of ConjunctionAccumulateCond + +class ConjunctionAccumulateCond : public AbstractStatement { +public: + ConjunctionAccumulateCond(ConjunctionComplete &complete, ULitVec &&lits); + virtual ~ConjunctionAccumulateCond() noexcept; + // {{{2 Statement interface + bool isNormal() const override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + ConjunctionComplete &complete_; +}; + +// {{{1 declaration of ConjunctionAccumulateHead + +class ConjunctionAccumulateHead : public AbstractStatement { +public: + ConjunctionAccumulateHead(ConjunctionComplete &complete, ULitVec &&lits); + virtual ~ConjunctionAccumulateHead() noexcept; + // {{{2 Statement interface + bool isNormal() const override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + // }}}2 + +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + ConjunctionComplete &complete_; +}; + +// {{{1 declaration of ConjunctionComplete + +class ConjunctionComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using TodoVec = std::vector; + ConjunctionComplete(DomainData &data, UTerm &&repr, UTermVec &&local); + virtual ~ConjunctionComplete() noexcept; + UTerm condRepr() const; + UTerm headRepr() const; + UTerm accuRepr() const; + UTerm emptyRepr() const; + UTerm const &domRepr() const { return def_.domRepr(); } + ConjunctionDomain &dom() { return static_cast(def_.dom()); } + PredicateDomain &emptyDom() { return domEmpty_; } + PredicateDomain &condDom() { return domCond_; } + void reportEmpty(Logger &log); + void reportCond(DomainData &data, Symbol cond, Output::LitVec &lits, Logger &log); + void reportHead(DomainData &data, Symbol cond, Output::LitVec &lits, Logger &log); + void setCondRecursive() { condRecursive_ = true; } + void setHeadRecursive() { headRecursive_ = true; } + // {{{2 Statement interface + bool isNormal() const override; + void analyze(Dep::Node &node, Dep &dep) override; + void startLinearize(bool active) override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + void enqueue(Queue &q) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 + +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; + void propagate(Queue &queue) override; + void report(Output::OutputBase &out, Logger &log) override; + unsigned priority() const override { return 1; } + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + template + void reportOther(F f, Logger &log); + +private: + HeadDefinition def_; // condtional literal + PredicateDomain domEmpty_; + PredicateDomain domCond_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; + DefinedBy defBy_; + Instantiator inst_; // dummy instantiator + TodoVec todo_; // contains literals that might have to be exported + UTermVec local_; // local variables in condition + bool condRecursive_ = false; + bool headRecursive_ = false; +}; + +// {{{1 declaration of ConjunctionLiteral + +class ConjunctionLiteral : public Literal, private BodyOcc { +public: + ConjunctionLiteral(ConjunctionComplete &complete); + virtual ~ConjunctionLiteral() noexcept; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return false; } // by construction + // }}}2 + +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + ConjunctionComplete &complete_; + DefinedBy defs_; + Id_t offset_; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; +}; + +// }}}1 + +// {{{1 declaration of DisjointAccumulate + +using Output::DisjointAtom; +using Output::DisjointDomain; +class DisjointComplete; + +class DisjointAccumulate : public AbstractStatement { +public: + DisjointAccumulate(DisjointComplete &complete, ULitVec &&lits); + DisjointAccumulate(DisjointComplete &complete, UTermVec &&tuple, CSPAddTerm &&value, ULitVec &&lits); + void printHead(std::ostream &out) const override; + virtual ~DisjointAccumulate() noexcept; + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Statement interface + bool isNormal() const override { return true; } + void linearize(Scripts &scripts, bool positive, Logger &log) override; +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + DisjointComplete &complete_; + UTermVec tuple_; + CSPAddTerm value_; + bool neutral_ = true; +}; + +// {{{1 declaration of DisjointComplete + +class DisjointComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using AccuVec = std::vector>; + using TodoVec = std::vector; + + DisjointComplete(DomainData &data, UTerm &&repr); + virtual ~DisjointComplete() noexcept; + + DisjointDomain &dom() { return static_cast(def_.dom()); } + void enqueue(DisjointDomain::Iterator atom); + UTerm const &accuRepr() const { return accuRepr_; } + UTerm const &domRepr() const { return def_.domRepr(); } + void addAccuDom(DisjointAccumulate &accu) { accuDoms_.emplace_back(accu); } + void setOutputRecursive() { outputRecursive_ = true; } + + // {{{2 Statement interface + bool isNormal() const override; + void analyze(Dep::Node &node, Dep &dep) override; + void startLinearize(bool active) override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + void enqueue(Queue &q) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; + void propagate(Queue &queue) override; + void report(Output::OutputBase &out, Logger &log) override; + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + +private: + AccuVec accuDoms_; + HeadDefinition def_; + UTerm accuRepr_; + TodoVec todo_; + DefinedBy defBy_; + Instantiator inst_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; + bool outputRecursive_ = false; +}; + +// {{{1 declaration of DisjointLiteral + +class DisjointLiteral : public Literal, private BodyOcc { +public: + DisjointLiteral(DisjointComplete &complete, NAF naf); + virtual ~DisjointLiteral() noexcept; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return false; } // by construction + // }}}2 +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + DisjointComplete &complete_; + DefinedBy defs_; + Id_t offset_ = InvalidId; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; + NAF naf_; +}; + +// }}}1 + +// {{{1 declaration of TheoryAccumulate + +using Output::TheoryAtom; +using Output::TheoryDomain; +class TheoryComplete; + +class TheoryAccumulate : public AbstractStatement { +public: + TheoryAccumulate(TheoryComplete &complete, ULitVec &&lits); + TheoryAccumulate(TheoryComplete &complete, Output::UTheoryTermVec &&tuple, ULitVec &&lits); + virtual ~TheoryAccumulate() noexcept; + void printHead(std::ostream &out) const override; + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 Statement interface + bool isNormal() const override { return true; } + void linearize(Scripts &scripts, bool positive, Logger &log) override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + TheoryComplete &complete_; + Output::UTheoryTermVec tuple_; + bool neutral_ = true; +}; + +// {{{1 declaration of TheoryComplete + +class TheoryComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using AccuVec = std::vector>; + using TodoVec = std::vector; + + TheoryComplete(DomainData &data, UTerm &&repr, TheoryAtomType type, UTerm &&name); + TheoryComplete(DomainData &data, UTerm &&repr, TheoryAtomType type, UTerm &&name, String op, Output::UTheoryTerm &&guard); + virtual ~TheoryComplete() noexcept; + TheoryDomain &dom() { return static_cast(def_.dom()); } + void enqueue(TheoryDomain::Iterator atom); + UTerm const &accuRepr() const { return accuRepr_; } + UTerm const &domRepr() const { return def_.domRepr(); } + void addAccuDom(TheoryAccumulate &accu) { accuDoms_.emplace_back(accu); } + void setOutputRecursive() { outputRecursive_ = true; } + UTerm const &name() const { return name_; } + Output::UTheoryTerm const &guard() const { return guard_; } + bool hasGuard() const { return static_cast(guard_); } + String op() const { return op_; } + TheoryAtomType type() const { return type_; } + // {{{2 Statement interface + bool isNormal() const override; + void analyze(Dep::Node &node, Dep &dep) override; + void startLinearize(bool active) override; + void linearize(Scripts &scripts, bool positive, Logger &log) override; + void enqueue(Queue &q) override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; + void propagate(Queue &queue) override; + void report(Output::OutputBase &out, Logger &log) override; + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + +private: + AccuVec accuDoms_; + HeadDefinition def_; + UTerm accuRepr_; + TodoVec todo_; + String op_; + Output::UTheoryTerm guard_; + UTerm name_; + DefinedBy defBy_; + Instantiator inst_; + TheoryAtomType type_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; + bool outputRecursive_ = false; +}; + +// {{{1 declaration of TheoryLiteral + +class TheoryLiteral : public Literal, private BodyOcc { +public: + TheoryLiteral(TheoryComplete &complete, NAF naf, bool auxiliary); + virtual ~TheoryLiteral() noexcept; + TheoryAtomType type() const { return complete_.type(); } + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return auxiliary_; } + // }}}2 +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + TheoryComplete &complete_; + DefinedBy defs_; + NAF naf_; + Id_t offset_; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; + bool auxiliary_; +}; + +// {{{1 declaration of TheoryRule + +class TheoryRule : public AbstractStatement { +public: + TheoryRule(TheoryLiteral &lit, ULitVec &&lits); + virtual ~TheoryRule() noexcept; + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + TheoryLiteral &lit_; +}; + +// }}}1 + +// Head Aggregates + +// {{{1 declaration of HeadAggregateComplete + +using Output::HeadAggregateAtom; +using Output::HeadAggregateDomain; +class HeadAggregateAccumulate; + +class HeadAggregateComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using TodoVec = std::vector; + using AccumulateDomainVec = std::vector>; + + HeadAggregateComplete(DomainData &data, UTerm &&repr, AggregateFunction fun, BoundVec &&bounds); + virtual ~HeadAggregateComplete() noexcept; + + HeadAggregateDomain &dom(); + UTerm const &domRepr() const { return repr_; } + AggregateFunction fun() const { return fun_; } + BoundVec const &bounds() const { return bounds_; } + void enqueue(HeadAggregateDomain::Iterator atom); + void addAccuDom(HeadAggregateAccumulate &accu) { accuDoms_.emplace_back(accu); } + // {{{3 Statement interface + bool isNormal() const override; // return false -> this one creates choices + void analyze(Dep::Node &node, Dep &dep) override; // use accuDoms to build the dependency... + void startLinearize(bool active) override; // noop because single instantiator + void linearize(Scripts &scripts, bool positive, Logger &log) override; // noop because single instantiator + void enqueue(Queue &q) override; // enqueue the single instantiator + // {{{2 Printable interface + void print(std::ostream &out) const override; // #complete { h1, ..., hn } :- accu1,... , accun. + // }}}2 +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; // #complete { h1, ..., hn } + void propagate(Queue &queue) override; // enqueue based on accuDoms + void report(Output::OutputBase &out, Logger &log) override; // loop over headDom here + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + +private: + UTerm repr_; + HeadAggregateDomain &domain_; + AccumulateDomainVec accuDoms_; + Instantiator inst_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; + DefinedBy defBy_; + AggregateFunction fun_; + BoundVec bounds_; + TodoVec todo_; +}; + +// {{{1 declaration of HeadAggregateRule + +class HeadAggregateRule : public AbstractStatement { +public: + HeadAggregateRule(HeadAggregateComplete &complete, ULitVec &&lits); + virtual ~HeadAggregateRule() noexcept; + + // {{{2 Printable interface + void print(std::ostream &out) const override; + // }}}2 + +private: + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + HeadAggregateComplete &complete_; +}; + +// {{{1 declaration of HeadAggregateLiteral + +class HeadAggregateLiteral : public Literal, private BodyOcc { +public: + HeadAggregateLiteral(HeadAggregateComplete &complete); + virtual ~HeadAggregateLiteral() noexcept; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return true; } // by construction + // }}}2 +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + HeadAggregateComplete &complete_; + DefinedBy defs_; + Potassco::Id_t offset_ = 0; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; +}; + +// {{{1 declaration of HeadAggregateAccumulate + +class HeadAggregateAccumulate : public AbstractStatement { +public: + HeadAggregateAccumulate(HeadAggregateComplete &complete, UTermVec &&tuple, PredicateDomain *predDom, UTerm &&predRepr, ULitVec &&lits); + virtual ~HeadAggregateAccumulate() noexcept; + HeadDefinition &predDef() { return predDef_; } + HeadDefinition const &predDef() const { return predDef_; } + UTermVec const &tuple() const { return tuple_; } + void printHead(std::ostream &out) const override; + // {{{2 AbstractStatement interface + void collectImportant(Term::VarSet &vars) override; + // }}}2 + +private: + // {{{2 SolutionCallback interface (w/o printHead) + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + HeadAggregateComplete &complete_; + HeadDefinition predDef_; + UTermVec tuple_; +}; + +// }}}1 + +// {{{1 declaration of DisjunctionComplete + +// Example: +// p(1..3,X) : q(X,Y,G); r(1..10,Z) : s(Z,G) :- t(G,H). +// Domains: +// DisjunctionLiteral: #d(G) +// Condition 1: #c1(X,G) +// Condition 2: #c2(Z,G) +// Pseudo Rules: +// #d(G) :- t(G,H). +// #c1(X,G) :- q(X,Y,G), #d(G). +// #c2(Z,G) :- r(Z,G), #d(G). +// p(R,X) :- R = 1..10, #c1(X,G). +// p(R,Z) :- R = 1..10, #c2(Z,G). +// Notes: +// - Given that the "head condition" never contains predicate literals (it can +// just contain ranges), the grounding of the ranges is done within the +// accumulation rule. This way no auxiliary domains are introduced. +// TODO: +// - If there are no conditions, there is no need for accumulation rules altogether. + +using Output::DisjunctionAtom; +using Output::DisjunctionDomain; + +class DisjunctionAccumulate; +class DisjunctionComplete : public Statement, private SolutionCallback, private BodyOcc { +public: + using TodoVec = std::vector; + using AccumulateVec = std::vector>; + DisjunctionComplete(DomainData &data, UTerm &&repr); + virtual ~DisjunctionComplete() noexcept; + DisjunctionDomain &dom() { return domain_; } + UTerm const &domRepr() const { return repr_; } + void addAccu(DisjunctionAccumulate &accu) { accu_.emplace_back(accu); } + void enqueue(DisjunctionDomain::Iterator atom); + // {{{2 Statement interface + bool isNormal() const override; // return false -> this one creates choices + void analyze(Dep::Node &node, Dep &dep) override; // use accuDoms to build the dependency... + void startLinearize(bool active) override; // noop because single instantiator + void linearize(Scripts &scripts, bool positive, Logger &log) override; // noop because single instantiator + void enqueue(Queue &q) override; // enqueue the single instantiator + // {{{2 Printable interface + void print(std::ostream &out) const override; // #complete { h1, ..., hn } :- accu1,... , accun. + // }}}2 + +private: + // {{{2 SolutionCallback interface + void printHead(std::ostream &out) const override; // #complete { h1, ..., hn } + void propagate(Queue &queue) override; // enqueue based on accuDoms + void report(Output::OutputBase &out, Logger &log) override; // loop over headDom here + unsigned priority() const override { return 1; } + // {{{2 BodyOcc interface + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + DefinedBy &definedBy() override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const override; + // }}}2 + +private: + UTerm repr_; + DisjunctionDomain &domain_; + DefinedBy defBy_; + Instantiator inst_; + TodoVec todo_; + AccumulateVec accu_; + OccurrenceType occType_ = OccurrenceType::STRATIFIED; +}; + +// {{{1 declaration of DisjunctionLiteral + +class DisjunctionLiteral : public Literal, private BodyOcc { +public: + DisjunctionLiteral(DisjunctionComplete &complete); + virtual ~DisjunctionLiteral() noexcept; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Literal interface + UIdx index(Scripts &scripts, BinderType type, Term::VarSet &bound) override; + bool isRecursive() const override; + BodyOcc *occurrence() override; + void collect(VarTermBoundVec &vars) const override; + Score score(Term::VarSet const &bound, Logger &log) override; + std::pair toOutput(Logger &log) override; + bool auxiliary() const override { return true; } // by construction + // }}}2 +private: + // {{{2 BodyOcc interface + DefinedBy &definedBy() override; + UGTerm getRepr() const override; + bool isPositive() const override; + bool isNegative() const override; + void setType(OccurrenceType x) override; + OccurrenceType getType() const override; + void checkDefined(LocSet &done, SigSet const &edb, UndefVec &) const override; + // }}}2 + +private: + DisjunctionComplete &complete_; + DefinedBy defs_; + Potassco::Id_t offset_ = 0; + OccurrenceType type_ = OccurrenceType::POSITIVELY_STRATIFIED; +}; + +// {{{1 declaration of DisjunctionRule + +class DisjunctionRule : public AbstractStatement { +public: + DisjunctionRule(DisjunctionComplete &complete, ULitVec &&lits); + virtual ~DisjunctionRule() noexcept; + // {{{2 Statement interface + bool isNormal() const override; + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + DisjunctionComplete &complete_; +}; + +// {{{1 declaration of DisjunctionAccumulate + +class DisjunctionAccumulate; +class DisjunctionAccumulateHead : public SolutionCallback { +public: + DisjunctionAccumulateHead(DisjunctionAccumulate &accu) : accu_(accu) { } + void report(Output::OutputBase &out, Logger &log) override; + void propagate(Queue &) override { } + void printHead(std::ostream &out) const override; + virtual ~DisjunctionAccumulateHead() noexcept = default; +private: + DisjunctionAccumulate &accu_; +}; + +class DisjunctionAccumulate : public AbstractStatement { + friend class DisjunctionAccumulateHead; +public: + DisjunctionAccumulate(DisjunctionComplete &complete, PredicateDomain *predDom, UTerm &&predRepr, ULitVec &&headCond, UTerm &&elemRepr, ULitVec &&lits); + virtual ~DisjunctionAccumulate() noexcept; + HeadDefinition &predDef() { return predDef_; } + void printPred(std::ostream &out) const; + void analyze(Dep::Node &node, Dep &dep) override; + void collectImportant(Term::VarSet &vars) override; +private: + void reportHead(Output::OutputBase &out, Logger &log); + void linearize(Scripts &scripts, bool positive, Logger &log) override; + // {{{2 SolutionCallback interface + void report(Output::OutputBase &out, Logger &log) override; + // }}}2 + +private: + DisjunctionComplete &complete_; + UTerm elemRepr_; + HeadDefinition predDef_; + ULitVec headCond_; + DisjunctionAccumulateHead accuHead_; + Instantiator instHead_; +}; + +// }}}1 + +} } // namespace Ground Gringo + +#endif // _GRINGO_GROUND_STATEMENTS_HH diff --git a/libgringo/gringo/ground/types.hh b/libgringo/gringo/ground/types.hh new file mode 100644 index 0000000..aad9397 --- /dev/null +++ b/libgringo/gringo/ground/types.hh @@ -0,0 +1,41 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_TYPES_HH +#define _GRINGO_GROUND_TYPES_HH + +#include + +namespace Gringo { namespace Ground { + +class Statement; +class Literal; +using ULit = std::unique_ptr; +using ULitVec = std::vector; +using Gringo::Output::PredicateDomain; +using Gringo::Output::PredDomMap; +using Gringo::Output::DomainData; +using UStm = std::unique_ptr; +using UStmVec = std::vector; + +} } // namespace Input Gringo + +#endif // _GRINGO_GROUND_TYPES_HH + diff --git a/libgringo/gringo/hash_set.hh b/libgringo/gringo/hash_set.hh new file mode 100644 index 0000000..958bd35 --- /dev/null +++ b/libgringo/gringo/hash_set.hh @@ -0,0 +1,615 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_HASH_SET_HH +#define _GRINGO_HASH_SET_HH + +#include +#include +#include +#include +#include +#include +#include + +// This shoud really be benchmarked on a large set of problems. +// I would expect double hashing to be more robust but slower than linear probing. +// Also the load factor should be benchmarked. +// The internet says 70% is good but I am using 80% at the moment. +// Double hashing is supposed to work with especially high load factors. +#define GRINGO_PROBE_LINEAR + +namespace Gringo { + +template +struct HashSetLiterals { + static constexpr Value deleted = std::numeric_limits::max() - 1; + static constexpr Value open = std::numeric_limits::max(); +}; + +template +constexpr Value HashSetLiterals::deleted; + +template +constexpr Value HashSetLiterals::open; + +template > +class HashSet { +public: + using ValueType = Value; + using SizeType = uint32_t; + using TableType = std::unique_ptr; + + // at least n value can be inserted without reallocation + // and the container is larger by a constant factor c > 1 than c*r + HashSet(SizeType n = 0, SizeType r = 0) : size_(0), reserved_(0) { + if (n > 0) { + reserved_ = grow_(n, r); + table_.reset(new ValueType[reserved_]); + std::fill(table_.get(), table_.get() + reserved_, Literals::open); + } + } +#ifdef GRINGO_PROBE_LINEAR + double loadMax() const { return 0.7; } +#else + double loadMax() const { return 0.8; } +#endif + double load() const { return static_cast(size()) / reserved_; } + SizeType size() const { return size_; } + bool empty() const { return size_ == 0; } + void clear() { + std::fill(table_.get(), table_.get() + reserved(), Literals::open); + size_ = 0; + } + void swap(HashSet &other) { + std::swap(table_, other.table_); + std::swap(reserved_, other.reserved_); + std::swap(size_, other.size_); + } + SizeType reserved() const { return reserved_; } + SizeType maxSize() const { return maxPrime(); } + bool reserveNeedsRebuild(SizeType n) const { + if (n <= 11) { return n > reserved(); } + else { + double load = double(n) / reserved_; + return (load > loadMax() && reserved_ < maxSize()) || n > maxSize(); + } + } + template + void reserve(Hasher const &hasher, EqualTo const &equalTo, SizeType n) { + if (reserveNeedsRebuild(n)) { + SizeType rOld = reserved_; + SizeType rNew = grow_(n, reserved_); + assert(rOld < rNew); + if (table_) { + TableType table(new ValueType[rNew]); + reserved_ = rNew; + std::fill(table.get(), table.get() + reserved_, Literals::open); + std::swap(table, table_); + for (auto it = table.get(), ie = table.get() + rOld; it != ie; ++it) { + if (!(*it == Literals::open) && !(*it == Literals::deleted)) { insert_(hasher, equalTo, std::move(*it)); } + } + } + else { + table_.reset(new ValueType[rNew]); + reserved_ = rNew; + std::fill(table_.get(), table_.get() + reserved_, Literals::open); + } + } + } + template + ValueType* find(Hasher const &hasher, EqualTo const &equalTo, Args const&... val) { + auto ret = !empty() ? find_(hasher, equalTo, val...) : std::make_pair(nullptr, false); + return ret.second ? ret.first : nullptr; + } + template + std::pair insert(Hasher const &hasher, EqualTo const &equalTo, T &&val) { + reserve(hasher, equalTo, size() + 1); + assert(size() < reserved()); + auto ret = insert_(hasher, equalTo, std::forward(val)); + if (ret.second) { + ++size_; + } + return ret; + } + ValueType &at(SizeType offset) { return table_[offset]; } + ValueType const &at(SizeType offset) const { return table_[offset]; } + SizeType offset(ValueType &val) const { return static_cast(&val - table_.get()); } + template + bool erase(Hasher const &hasher, EqualTo const &equalTo, Args const&... val) { + if (auto ret = find(hasher, equalTo, val...)) { + *ret = Literals::deleted; + --size_; + return true; + } + return false; + } + void eraseRef(SizeType &ref) { + ref = Literals::deleted; + --size_; + } +private: + SizeType grow_(SizeType n, SizeType r) { + if (n > maxSize()) { throw std::overflow_error("container size exceeded"); } + if (n > 11) { n = std::min(static_cast(std::max(n / loadMax() + 1.0, r * 2.0)), maxSize()); } + return n < 4 ? n : nextPrime(n); + } +#ifdef GRINGO_PROBE_LINEAR + template + SizeType hash_(Hasher const &hasher, Args const &... val) { + size_t seed = hasher(val...); + return hash_mix(seed) % reserved(); + } + template + std::pair find_(Hasher const &hasher, EqualTo const &equalTo, Args&&... val) { + ValueType *first = nullptr; + for (SizeType pos = hash_(hasher, val...), end = reserved();;) { + for (SizeType i = pos; i < end; ++i) { + if (table_[i] == Literals::open) { + if (!first) { first = &table_[i]; } + return {first, false}; + } + else if (table_[i] == Literals::deleted) { + if (!first) { first = &table_[i]; } + continue; + } + else if (equalTo(table_[i], val...)) { + return {&table_[i], true}; + } + } + if (pos > 0) { + end = pos; + pos = 0; + } + else { break; } + } + return {first, false}; + } +#else + // Double hashing + template + std::pair hash_(Hasher const &hasher, Args const &... val) { + size_t seed = hasher(val...); + SizeType r = reserved(); + //if (r > 1) { return {seed % r, 1 + (hash_mix(seed) % (r - 1))}; } + if (r > 1) { return {hash_mix(seed) % r, 1 + (seed % (r-1))}; } + return {0, 1}; + } + template + std::pair find_(Hasher const &hasher, EqualTo const &equalTo, Args&&... val) { + ValueType *first = nullptr; + auto h = hash_(hasher, val...); + for (SizeType i = 0, e = reserved(); i < e; ++i, h.first = (h.first + h.second) % e) { + if (table_[h.first] == Literals::open) { + if (!first) { first = &table_[h.first]; } + return {first, false}; + } + else if (table_[h.first] == Literals::deleted) { + if (!first) { first = &table_[h.first]; } + continue; + } + else if (equalTo(table_[h.first], val...)) { + return {&table_[h.first], true}; + } + } + return {first, false}; + } +#endif + template + std::pair insert_(Hasher const &hasher, EqualTo const &equalTo, T &&val) { + assert(size() < reserved()); + auto ret = find_(hasher, equalTo, val); + if (!ret.second) { + assert(ret.first); + *ret.first = std::forward(val); + } + return {*ret.first, !ret.second}; + } +private: + SizeType size_; + SizeType reserved_; + TableType table_; +}; + +struct CallHash { + template + size_t operator()(T const &x) const { + return x.hash(); + } +}; + +struct EqualTo { + template + size_t operator()(T const &a, U const &b) const { + return a == b; + } +}; + +template +struct Cast { + template + T const &operator()(U const &x) const { + return static_cast(x); + } +}; + +template +struct First { + template + T const &operator()(U const &x) const { + return std::get<0>(x); + } +}; + +template , typename Hash=std::hash> +struct HashKey : private Get, private Hash { + // Note: to support lookup with key + size_t operator()(T const &x) const { + return Hash::operator()(x); + } + template + size_t operator()(U const &x) const { + return Hash::operator()(Get::operator()(x)); + } +}; + +template , typename EqualTo=std::equal_to> +struct EqualToKey : private Get, private EqualTo { + // Note: to support lookup with key + template + bool operator()(U const &a, T const &b) const { + return EqualTo::operator()(Get::operator()(a), b); + } + template + bool operator()(U const &a, U const &b) const { + return EqualTo::operator()(Get::operator()(a), Get::operator()(b)); + } +}; + +template > +using HashFirst = HashKey,Hash>; + +template > +using EqualToFirst = EqualToKey,EqualTo>; + +template , typename EqualTo=std::equal_to> +class UniqueVec : private Hash, private EqualTo { +public: + using SizeType = unsigned; + using Vec = std::vector; + using Set = HashSet; + using ValueType = Value; + using Iterator = typename Vec::iterator; + using ConstIterator = typename Vec::const_iterator; + + template + std::pair findPush(T const &key, A&&... args) { + SizeType offset = static_cast(vec_.size()); + auto res = set_.insert( + [this, offset, &key](SizeType a) { return a != offset ? Hash::operator()(vec_[a]) : Hash::operator()(key); }, + [this, offset, &key](SizeType a, SizeType b) { return b != offset ? a == b : EqualTo::operator()(vec_[a], key); }, + offset); + if (res.second) { + vec_.emplace_back(std::forward(args)...); + } + return {vec_.begin() + res.first, res.second}; + } + std::pair push(Value &&val) { + SizeType offset = static_cast(vec_.size()); + auto res = set_.insert( + [this, offset, &val](SizeType a) { return a != offset ? Hash::operator()(vec_[a]) : Hash::operator()(val); }, + [this, offset, &val](SizeType a, SizeType b) { return b != offset ? a == b : EqualTo::operator()(vec_[a], val); }, + offset); + if (res.second) { + vec_.push_back(std::forward(val)); + } + return {vec_.begin() + res.first, res.second}; + } + SizeType offset(ConstIterator it) const { + return static_cast(it - begin()); + } + template + std::pair push(A&&... args) { + return push(Value(std::forward(args)...)); + } + template + Iterator find(U const &val) { + SizeType offset = static_cast(vec_.size()); + auto res = set_.find( + [this, offset, &val](SizeType a) { return a != offset ? Hash::operator()(vec_[a]) : Hash::operator()(val); }, + [this, offset, &val](SizeType a, SizeType b) { return b != offset ? a == b : EqualTo::operator()(vec_[a], val); }, + offset); + return res ? vec_.begin() + *res : vec_.end(); + } + template + ConstIterator find(U const &val) const { + return const_cast(this)->find(val); + } + void pop() { + assert(!vec_.empty()); + set_.erase( + [this](SizeType a) { return Hash::operator()(vec_[a]); }, + [this](SizeType a, SizeType b) { return a == b; }, + vec_.size() - 1); + vec_.pop_back(); + } + Value &back() { return vec_.back(); } + Value const &back() const { return vec_.back(); } + Value &front() { return vec_.front(); } + Value const &front() const { return vec_.front(); } + void rebuild() { + set_.clear(); + for (SizeType i = 0, e = static_cast(vec_.size()); i != e; ++i) { + set_.insert( + [this](SizeType a) { return Hash::operator()(vec_[a]); }, + [](SizeType, SizeType) { return false; }, + i); + } + } + void reserve(SizeType size) { + vec_.reserve(size); + set_.reserve( + [this](SizeType a) { return Hash::operator()(vec_[a]); }, + [](SizeType, SizeType) { return false; }, + size); + } + template + void erase(F f) { + vec_.erase(std::remove_if(vec_.begin(), vec_.end(), f), vec_.end()); + rebuild(); + } + // This function keeps an element in the vector but deletes it from the set. + // Note that it is inserted again after the next call to rebuild, erase or sort. + // It is best not to use this function! + void hide(Iterator it) { + SizeType offset = static_cast(it - begin()); + set_.erase( + [this](SizeType a) { return Hash::operator()(vec_[a]); }, + [](SizeType a, SizeType b) { return a == b; }, + offset); + } + template + void sort(F f = std::less()) { + std::sort(vec_.begin(), vec_.end(), f); + rebuild(); + } + Iterator begin() { return vec_.begin(); } + Iterator end() { return vec_.end(); } + ConstIterator begin() const { return vec_.begin(); } + ConstIterator end() const { return vec_.end(); } + SizeType size() const { return static_cast(vec_.size()); } + bool empty() const { return vec_.empty(); } + void clear() { + vec_.clear(); + set_.clear(); + } + ValueType &at(SizeType offset) { return vec_.at(offset); } + ValueType const &at(SizeType offset) const { return vec_.at(offset); } + ValueType &operator[](SizeType offset) { return vec_[offset]; } + ValueType const &operator[](SizeType offset) const { return vec_[offset]; } + +private: + Vec vec_; + Set set_; +}; + +template +class IteratorRange { +public: + using Iterrator = It; + using ReferenceType = decltype(*std::declval()); + using ValueType = typename std::remove_reference::type; + template + IteratorRange(T &&t) + : begin_(std::begin(t)) + , end_(std::end(t)) { } + IteratorRange(It a, It b) + : begin_(a) + , end_(b) { } + It begin() const { return begin_; } + It end() const { return end_; } + template + ReferenceType front() { return *begin(); } + ReferenceType const front() const { return *begin(); } + ReferenceType back() { return *(end()-1); } + ReferenceType const back() const { *(end()-1); } + bool empty() const { return begin_ == end_; } + size_t size() const { return std::distance(begin_, end_); } + ReferenceType operator[](size_t p) { return *(begin_ + p); } + ReferenceType const operator[](size_t p) const { return *(begin_ + p); } +private: + It begin_; + It end_; +}; +template +typename IteratorRange::Iterrator begin(IteratorRange rng) { + return rng.begin(); +} + +template +typename IteratorRange::Iterrator end(IteratorRange rng) { + return rng.end(); +} + +template +IteratorRange make_range(It a, It b) { + return IteratorRange(a, b); +} + +template +auto make_range(T &&c) -> IteratorRange { + using namespace std; + return IteratorRange(begin(c), end(c)); +} + +template , typename EqualTo=std::equal_to> +class UniqueVecVec : private Hash, private EqualTo { +public: + using SizeType = unsigned; + using Vec = std::vector; + using ValueType = Value; + using Iterator = typename Vec::iterator; + using ConstIterator = typename Vec::const_iterator; + + template + std::pair push(It ib, SizeType size) { + auto &d = data(size); + SizeType offset = size > 0 ? static_cast(d.values.size()) / size : 0; + auto ret = d.set.insert( + [this, offset, &d, ib, size](SizeType a) { + auto it = d.values.begin() + size_t(a) * size; + return a == offset ? hash_range(ib, ib + size, hasher()) : hash_range(it, it + size, hasher()); + }, + [this, offset, &d, ib, size](SizeType a, SizeType b) { + auto it = d.values.begin() + size_t(a) * size; + return b == offset ? std::equal(it, it + size, ib, equalTo()) : a == b; + }, + offset); + if (ret.second) { + d.values.insert(d.values.end(), ib, ib + size); + } + return ret; + } + template + std::pair push(It ib, It ie) { + return push(ib, std::distance(ie, ib)); + } + std::pair push(Vec const &val) { + return push(val.begin(), static_cast(val.size())); + } + std::pair push(std::initializer_list val) { + return push(val.begin(), val.size()); + } + template + std::pair find(It it, SizeType size) const { + auto &d = data(size); + SizeType offset = size > 0 ? d.values.size() / size : 0; + auto res = d.set.find( + [this, offset, &d, it, size](SizeType a) { + auto jt = d.values.begin() + size_t(a) * size; + return a == offset ? hash_range(it, it + size, hasher()) : hash_range(jt, jt + size, hasher()); + }, + [this, offset, &d, it, size](SizeType a, SizeType b) { + auto jt = d.values.begin() + size_t(a) * size; + return b == offset ? std::equal(it, it + size, jt, equalTo()) : a == b; + }, + offset); + return {res ? *res : 0, static_cast(res)}; + } + template + std::pair find(It ib, It ie) const { + return find(ib, std::distance(ie, ib)); + } + std::pair find(Vec const &val) const { + return find(val.begin(), val.size()); + } + std::pair find(std::initializer_list val) const { + return find(val.begin(), val.size()); + } + Iterator at(SizeType offset, SizeType size) { + return data(size).values.begin() + size_t(offset) * size; + } + Iterator const &at(SizeType offset, SizeType size) const { + return data(size).values.begin() + size_t(offset) * size;; + } + template + void erase(F f) { + auto eraseBySize = [this,f](SizeType size, Data &d) { + if (size > 0) { + auto jt = d.values.begin(); + for (auto it = jt, ie = d.values.end(); it != ie; it+= size) { + if (!f(it, it + size)) { + if (it != jt) { std::move(it, it+size, jt); } + jt += size; + } + } + d.values.erase(jt, d.values.end()); + d.set.clear(); + for (SizeType i = 0, e = d.values.size() / size; i != e; ++i) { + d.set.insert( + [this, &d, size](SizeType a) { + auto it = d.values.begin() + size_t(a) * size; + return hash_range(it, it + size, hasher()); + }, + [](SizeType, SizeType) { return false; }, + i); + } + } + else if (!d.set.empty() && f(d.values.begin(), d.values.begin())) { + d.set.clear(); + } + }; + SizeType size = 0;; + for (auto &d : small_) { + eraseBySize(size, d); + ++size; + } + for (auto it = big_.begin(), ie = big_.end(); it != ie; ++it) { + eraseBySize(it->first, it->second); + } + big_.erase([](typename BigMap::ValueType const &d) { return d.second.set.empty(); }); + } + void clear() { + for (auto &d : small_) { + d.values.clear(); + d.set.clear(); + } + big_.clear(); + } + bool empty() const { + for (auto &d : small_) { + if (!d.set.empty()) { return false; } + } + for (auto &d : big_) { + if (!d.second.set.empty()) { return false; } + } + return true; + + } + Hash hasher() const { return *this; } + EqualTo equalTo() const { return *this; } + +private: + using Set = HashSet; + struct Data { + Set set; + Vec values; + }; + using SmallVec = std::array; + using BigMap = UniqueVec, HashFirst, EqualToFirst>; + Data &data(SizeType size) { + if (size < small) { return small_[size]; } + else { + auto ret = big_.find(size); + if (ret != big_.end()) { return ret->second; } + else { return big_.push(size, Data()).first->second; } + } + } + Data const &data(SizeType size) const { + return const_cast(this)->data(size); + } + + BigMap big_; + SmallVec small_; +}; + +} // namespace Gringo + +#endif // _GRINGO_HASH_SET_HH diff --git a/libgringo/gringo/hashable.hh b/libgringo/gringo/hashable.hh new file mode 100644 index 0000000..e049032 --- /dev/null +++ b/libgringo/gringo/hashable.hh @@ -0,0 +1,68 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_HASHABLE_HH +#define _GRINGO_HASHABLE_HH + +#include +#include +#include +#include + +#define GRINGO_HASH(T) namespace std { template <> struct hash : hash { }; } +#define GRINGO_CALL_HASH(T) namespace std { template <> struct hash { size_t operator()(T const &x) const { return x.hash(); } }; } + +namespace Gringo { + +// {{{ declaration of Hashable + +class Hashable { +public: + virtual size_t hash() const = 0; + virtual ~Hashable() { } +}; + +// }}} +// {{{ definition of call_hash + +template +struct call_hash { + size_t operator()(T const &x) const { return x.hash(); } +}; + +// }}} + +} // namespace Gringo + +namespace std { + +// {{{ definition of hash + +template <> +struct hash { + size_t operator()(Gringo::Hashable const &x) const { return x.hash(); } +}; + +// }}} + +} // namespace std + +#endif // _GRINGO_HASHABLE_HH + diff --git a/libgringo/gringo/indexed.hh b/libgringo/gringo/indexed.hh new file mode 100644 index 0000000..f8b1eb2 --- /dev/null +++ b/libgringo/gringo/indexed.hh @@ -0,0 +1,95 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef GRINGO_INDEXED_HH +#define GRINGO_INDEXED_HH + +#include + +namespace Gringo { + +// {{{ declaration of Indexed + +template +struct Indexed { +public: + using ValueType = T; + using IndexType = R; + template + IndexType emplace(Args&&... args); + IndexType insert(ValueType &&value); + ValueType erase(IndexType uid); + ValueType &operator[](IndexType uid); +private: + std::vector values_; + std::vector free_; +}; + +// }}} + +// {{{ defintion of Indexed + +template +template +typename Indexed::IndexType Indexed::emplace(Args&&... args) { + if (free_.empty()) { + values_.emplace_back(std::forward(args)...); + return IndexType(values_.size() - 1); + } + else { + IndexType uid = free_.back(); + values_[uid] = ValueType(std::forward(args)...); + free_.pop_back(); + return uid; + } +} + +template +typename Indexed::IndexType Indexed::insert(ValueType &&value) { + if (free_.empty()) { + values_.push_back(std::move(value)); + return IndexType(values_.size() - 1); + } + else { + IndexType uid = free_.back(); + values_[uid] = std::move(value); + free_.pop_back(); + return uid; + } +} + +template +typename Indexed::ValueType Indexed::erase(IndexType uid) { + ValueType val(std::move(values_[uid])); + if (uid + 1 == values_.size()) { values_.pop_back(); } + else { free_.push_back(uid); } + return val; +} + +template +typename Indexed::ValueType &Indexed::operator[](typename Indexed::IndexType uid) { + return values_[uid]; +} + +// }}} + +} // namespace Gringo + +#endif // GRINGO_INDEXED_HH diff --git a/libgringo/gringo/input/aggregate.hh b/libgringo/gringo/input/aggregate.hh new file mode 100644 index 0000000..c86b8fd --- /dev/null +++ b/libgringo/gringo/input/aggregate.hh @@ -0,0 +1,209 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_AGGREGATE_HH +#define _GRINGO_INPUT_AGGREGATE_HH + +#include +#include +#include +#include + +namespace Gringo { + +namespace Ground { +enum class RuleType : unsigned short; +using ULitVec = std::vector; +class Statement; +using UStm = std::unique_ptr; +using UStmVec = std::vector; +} + +namespace Input { + +// {{{ declaration of auxiliary types + +using CondLit = std::pair; +using CondLitVec = std::vector; +using BodyAggrElem = std::pair; +using BodyAggrElemVec = std::vector; + +using HeadAggrElem = std::tuple; +using HeadAggrElemVec = std::vector; + +struct BodyAggregate; +using UBodyAggr = std::unique_ptr; +using UBodyAggrVec = std::vector; + +struct HeadAggregate; +using UHeadAggr = std::unique_ptr; +using UHeadAggrVec = std::vector; + +// }}} + +// {{{ declaration of AssignLevel + +struct AssignLevel { + typedef std::unordered_map BoundSet; + + void add(VarTermBoundVec &vars); + AssignLevel &subLevel(); + void assignLevels(); + void assignLevels(unsigned level, BoundSet const &bound); + virtual ~AssignLevel(); + + std::list childs; + std::unordered_map> occurr; +}; + +// }}} +// {{{ declaration of CheckLevel + +struct CheckLevel { + struct Ent { + bool operator<(Ent const &) const; + }; + using SC = SafetyChecker; + using VarMap = std::unordered_map; + + CheckLevel(Location const &loc, Printable const &p); + CheckLevel(CheckLevel &&); + SC::VarNode &var(VarTerm &var); + void check(Logger &log); + ~CheckLevel(); + + Location loc; + Printable const &p; + SC dep; + SC::EntNode *current = 0; + VarMap vars; +}; +using ChkLvlVec = std::vector; +void addVars(ChkLvlVec &levels, VarTermBoundVec &vars); + +// }}} +// {{{ declaration of ToGroundArg + +using CreateLit = std::function; +using CreateStm = std::function; +using CreateStmVec = std::vector; +using CreateBody = std::pair; +using CreateBodyVec = std::vector; +using CreateHead = CreateStm; + +struct ToGroundArg { + ToGroundArg(unsigned &auxNames, DomainData &domains); + String newId(bool increment = true); + UTermVec getGlobal(VarTermBoundVec const &vars); + UTermVec getLocal(VarTermBoundVec const &vars); + UTerm newId(UTermVec &&global, Location const &loc, bool increment = true); + template + UTerm newId(T const &x) { + VarTermBoundVec vars; + x.collect(vars); + return newId(getGlobal(vars), x.loc()); + } + ~ToGroundArg(); + + unsigned &auxNames; + DomainData &domains; +}; + +// }}} + +// {{{ declaration of BodyAggregate + +struct BodyAggregate : Printable, Hashable, Locatable, Clonable, Comparable { + //! Removes RawTheoryTerms from TheoryLiterals + virtual void initTheory(TheoryDefs &def, Logger &log) { (void)def; (void)log; }; + virtual unsigned projectScore() const { return 2; } + //! Unpool the aggregate and aggregate elements. + virtual void unpool(UBodyAggrVec &x, bool beforeRewrite) = 0; + //! Simplify the aggregate and aggregate elements. + //! \pre Must be called after unpool. + virtual bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) = 0; + //! Assign levels to variables using the VarCollector. + //! \pre Must be called after simplify. + virtual void assignLevels(AssignLevel &lvl) = 0; + virtual void check(ChkLvlVec &lvl, Logger &log) const = 0; + //! Rewrite arithmetics. + //! \pre Requires variables assigned to levels. + virtual void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) = 0; + //! Rewrite aggregates. + //! Separates assignment aggregates from ordinary bounds, and + //! transforms literal aggregates into tuple aggregates. + //! Returns false iff the aggregates must be removed. + //! Argument aggr contains the rewritten aggregates. + virtual bool rewriteAggregates(UBodyAggrVec &aggr) = 0; + //! Returns true if the aggregate is an assignment aggregate. + //! \note Does not consider relation literals. + virtual void removeAssignment() = 0; + virtual bool isAssignment() const = 0; + //! Collects all variables occuring in the aggregate. + //! Occurrences bound by the aggregate are marked as such + //! (occurrences bound in nested scopes are not marked). + virtual void collect(VarTermBoundVec &vars) const = 0; + virtual bool hasPool(bool beforeRewrite) const = 0; + virtual void replace(Defines &dx) = 0; + virtual CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const = 0; + virtual ~BodyAggregate() { } +}; + +// }}} + +// {{{ declaration of HeadAggregate + +struct HeadAggregate : Printable, Hashable, Locatable, Clonable, Comparable { + //! Removes RawTheoryTerms from TheoryLiterals + virtual void initTheory(TheoryDefs &def, bool hasBody, Logger &log) { (void)def; (void)hasBody; (void)log; } + virtual bool isPredicate() const { return false; } + //! Unpool the aggregate and aggregate elements. + virtual void unpool(UHeadAggrVec &x, bool beforeRewrite) = 0; + //! Simplify the aggregate and aggregate elements. + //! \pre Must be called after unpool. + virtual bool simplify(Projections &project, SimplifyState &state, Logger &log) = 0; + //! Assign levels to variables using the VarCollector. + //! \pre Must be called after simplify. + virtual void assignLevels(AssignLevel &lvl) = 0; + virtual void check(ChkLvlVec &lvl, Logger &log) const = 0; + //! Rewrite arithmetics. + //! \pre Requires variables assigned to levels. + virtual void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) = 0; + virtual UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) = 0; + //! Collects all variables occuring in the aggregate. + //! Occurrences bound by the aggregate are marked as such + //! (occurrences bound in nested scopes are not marked). + virtual void collect(VarTermBoundVec &vars) const = 0; + virtual bool hasPool(bool beforeRewrite) const = 0; + virtual void replace(Defines &dx) = 0; + virtual CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const = 0; + virtual Symbol isEDB() const; + virtual void getNeg(std::function f) const = 0; + virtual ~HeadAggregate() { } +}; + +// }}} + +} } // namespace Input Gringo + +GRINGO_HASH(Gringo::Input::BodyAggregate) +GRINGO_HASH(Gringo::Input::HeadAggregate) + +#endif // _GRINGO_INPUT_AGGREGATE_HH diff --git a/libgringo/gringo/input/aggregates.hh b/libgringo/gringo/input/aggregates.hh new file mode 100644 index 0000000..a5f0915 --- /dev/null +++ b/libgringo/gringo/input/aggregates.hh @@ -0,0 +1,452 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_AGGREGATES_HH +#define _GRINGO_INPUT_AGGREGATES_HH + +#include +#include + +namespace Gringo { namespace Input { + +// {{{1 declaration of TupleBodyAggregate + +struct TupleBodyAggregate : BodyAggregate { + TupleBodyAggregate(NAF naf, bool removedAssignment, bool translated, AggregateFunction fun, BoundVec &&bounds, BodyAggrElemVec &&elems); // NOTE: private + TupleBodyAggregate(NAF naf, AggregateFunction fun, BoundVec &&bounds, BodyAggrElemVec &&elems); + bool rewriteAggregates(UBodyAggrVec &aggr) override; + bool isAssignment() const override; + void removeAssignment() override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(BodyAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + TupleBodyAggregate *clone() const override; + void unpool(UBodyAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const override; + virtual ~TupleBodyAggregate(); + + NAF naf; + bool removedAssignment = false; + bool translated = false; + AggregateFunction fun; + BoundVec bounds; + BodyAggrElemVec elems; +}; + +// {{{1 declaration of LitBodyAggregate + +struct LitBodyAggregate : BodyAggregate { + LitBodyAggregate(NAF naf, AggregateFunction fun, BoundVec &&bounds, CondLitVec &&elems); + bool rewriteAggregates(UBodyAggrVec &aggr) override; + bool isAssignment() const override; + void removeAssignment() override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(BodyAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + LitBodyAggregate *clone() const override; + void unpool(UBodyAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const override; + virtual ~LitBodyAggregate(); + + NAF naf; + AggregateFunction fun; + BoundVec bounds; + CondLitVec elems; +}; + +// {{{1 declaration of Conjunction + +struct Conjunction : BodyAggregate { + using ULitVecVec = std::vector; + using Elem = std::pair; + using ElemVec = std::vector; + + Conjunction(ULit &&head, ULitVec &&cond); + Conjunction(ElemVec &&elems); + bool rewriteAggregates(UBodyAggrVec &aggr) override; + bool isAssignment() const override; + void removeAssignment() override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(BodyAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + Conjunction *clone() const override; + void unpool(UBodyAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const override; + virtual ~Conjunction(); + + ElemVec elems; +}; + +// {{{1 declaration of SimpleBodyLiteral + +struct SimpleBodyLiteral : BodyAggregate { + SimpleBodyLiteral(ULit &&lit); + unsigned projectScore() const override { return lit->projectScore(); } + Location const &loc() const override; + void loc(Location const &loc) override; + bool rewriteAggregates(UBodyAggrVec &aggr) override; + void removeAssignment() override; + bool isAssignment() const override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(BodyAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + SimpleBodyLiteral *clone() const override; + void unpool(UBodyAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const override; + virtual ~SimpleBodyLiteral(); + + ULit lit; +}; + +// {{{1 declaration of DisjointAggregate + +struct CSPElem { + CSPElem(Location const &loc, UTermVec &&tuple, CSPAddTerm &&value, ULitVec &&cond); + CSPElem(CSPElem &&x); + CSPElem &operator=(CSPElem &&x); + ~CSPElem(); + void print(std::ostream &out) const; + CSPElem clone() const; + size_t hash() const; bool operator==(CSPElem const &other) const; + + Location loc; + UTermVec tuple; + CSPAddTerm value; + ULitVec cond; +}; + +inline std::ostream &operator<<(std::ostream &out, CSPElem const &x) { + x.print(out); + return out; +} + +using CSPElemVec = std::vector; + +struct DisjointAggregate : BodyAggregate { + DisjointAggregate(NAF naf, CSPElemVec &&elems); + bool rewriteAggregates(UBodyAggrVec &aggr) override; + bool isAssignment() const override; + void removeAssignment() override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(BodyAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + DisjointAggregate *clone() const override; + void unpool(UBodyAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const override; + virtual ~DisjointAggregate(); + + NAF naf; + CSPElemVec elems; +}; + +// }}}1 + +// {{{1 declaration of TupleHeadAggregate + +struct TupleHeadAggregate : HeadAggregate { + TupleHeadAggregate(AggregateFunction fun, bool translated, BoundVec &&bounds, HeadAggrElemVec &&elems); // NOTE: private + TupleHeadAggregate(AggregateFunction fun, BoundVec &&bounds, HeadAggrElemVec &&elems); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + TupleHeadAggregate *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + void getNeg(std::function f) const override; + virtual ~TupleHeadAggregate(); + + AggregateFunction fun; + bool translated; + BoundVec bounds; + HeadAggrElemVec elems; +}; + +// {{{1 declaration of LitHeadAggregate + +struct LitHeadAggregate : HeadAggregate { + LitHeadAggregate(AggregateFunction fun, BoundVec &&bounds, CondLitVec &&elems); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + LitHeadAggregate *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~LitHeadAggregate(); + + AggregateFunction fun; + BoundVec bounds; + CondLitVec elems; +}; + +// {{{1 declaration of Disjunction + +struct Disjunction : HeadAggregate { + using Head = std::pair; + using HeadVec = std::vector; + using Elem = std::pair; + using ElemVec = std::vector; + + Disjunction(CondLitVec &&elems); + Disjunction(ElemVec &&elems); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + Disjunction *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~Disjunction(); + + ElemVec elems; +}; + +// {{{1 declaration of SimpleHeadLiteral + +struct SimpleHeadLiteral : HeadAggregate { + SimpleHeadLiteral(ULit &&lit); + virtual bool isPredicate() const override { return true; } + Location const &loc() const override; + void loc(Location const &loc) override; + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + SimpleHeadLiteral *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &dx) override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + Symbol isEDB() const override; + void getNeg(std::function f) const override; + virtual ~SimpleHeadLiteral(); + + ULit lit; +}; + +// }}}1 +// {{{1 declaration of MinimizeHeadLiteral + +struct MinimizeHeadLiteral : HeadAggregate { + MinimizeHeadLiteral(UTerm &&weight, UTerm &&priority, UTermVec &&tuple); + MinimizeHeadLiteral(UTermVec &&tuple); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + MinimizeHeadLiteral *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &x) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~MinimizeHeadLiteral(); + +private: + Term &weight() const; + Term &priority() const; + + UTermVec tuple_; +}; + +// }}}1 +// {{{1 declaration of EdgeHeadAtom + +struct EdgeHeadAtom : HeadAggregate { + EdgeHeadAtom(UTerm &&u, UTerm &&v); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + EdgeHeadAtom *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &x) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~EdgeHeadAtom(); + +private: + UTerm u_; + UTerm v_; +}; + +// {{{1 declaration of ProjectHeadAtom + +struct ProjectHeadAtom : HeadAggregate { + ProjectHeadAtom(UTerm &&atom); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + ProjectHeadAtom *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &x) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~ProjectHeadAtom(); + +private: + UTerm atom_; +}; + +// {{{1 declaration of HeuristicHeadAtom + +struct HeuristicHeadAtom : HeadAggregate { + HeuristicHeadAtom(UTerm &&atom, UTerm &&bias, UTerm &&priority, UTerm &&mod); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + HeuristicHeadAtom *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &x) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~HeuristicHeadAtom(); + +private: + UTerm atom_; + UTerm value_; + UTerm priority_; + UTerm mod_; +}; + +// {{{1 declaration of ShowHeadLiteral + +struct ShowHeadLiteral : HeadAggregate { + ShowHeadLiteral(UTerm &&term, bool csp); + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + bool operator==(HeadAggregate const &other) const override; + void print(std::ostream &out) const override; + size_t hash() const override; + ShowHeadLiteral *clone() const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &x) override; + void getNeg(std::function f) const override; + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + virtual ~ShowHeadLiteral(); + +private: + UTerm term_; + bool csp_; +}; + +// }}}1 + +} } // namespace Input Gringo + +GRINGO_CALL_HASH(Gringo::Input::CSPElem) +GRINGO_CALL_CLONE(Gringo::Input::CSPElem) + +#endif // _GRINGO_INPUT_AGGREGATES_HH + diff --git a/libgringo/gringo/input/groundtermparser.hh b/libgringo/gringo/input/groundtermparser.hh new file mode 100644 index 0000000..c47763f --- /dev/null +++ b/libgringo/gringo/input/groundtermparser.hh @@ -0,0 +1,65 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_GROUNDTERMPARSER_HH +#define _GRINGO_INPUT_GROUNDTERMPARSER_HH + +#include +#include +#include +#include + +namespace Gringo { namespace Input { + +// {{{ declaration of GroundTermParser + +class GroundTermParser : private LexerState { + using IndexedTerms = Indexed; +public: + GroundTermParser(); + Symbol parse(std::string const &str, Logger &log); + ~GroundTermParser(); + // NOTE: only to be used durning parsing (actually it would be better to hide this behind a private interface) + Logger &logger() { assert(log_); return *log_; } + void parseError(std::string const &message, Logger &log); + void lexerError(StringSpan token, Logger &log); + int lex(void *pValue, Logger &log); + + Symbol term(BinOp op, Symbol a, Symbol b); + Symbol term(UnOp op, Symbol a); + unsigned terms(); + unsigned terms(unsigned uid, Symbol a); + SymVec terms(unsigned uid); + Symbol tuple(unsigned uid, bool forceTuple); + + Symbol value; +private: + int lex_impl(void *pValue, Logger &log); + + IndexedTerms terms_; + Logger *log_ = nullptr; + bool undefined_; +}; + +// }}} + +} } // namespace Input Gringo + +#endif // _GRINGO_INPUT_GROUNDTERMPARSER_HH diff --git a/libgringo/gringo/input/literal.hh b/libgringo/gringo/input/literal.hh new file mode 100644 index 0000000..f8c03ec --- /dev/null +++ b/libgringo/gringo/input/literal.hh @@ -0,0 +1,95 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_LITERAL_HH +#define _GRINGO_INPUT_LITERAL_HH + +#include +#include +#include + +namespace Gringo { namespace Input { + +// {{{ declaration of Literal + +struct Projection { + Projection(UTerm &&projected, UTerm &&project); + Projection(Projection &&); + Projection &operator=(Projection &&); + ~Projection(); + operator Term const &() const; + + UTerm projected; + UTerm project; + bool done = false; +}; + +struct Projections { + using ProjectionMap = UniqueVec, std::equal_to>; + + Projections(); + Projections(Projections &&x); + ProjectionMap::Iterator begin(); + ProjectionMap::Iterator end(); + ~Projections(); + UTerm add(Term &term); + + ProjectionMap proj; +}; + +struct Literal : Printable, Hashable, Locatable, Comparable, Clonable { + using AssignVec = std::vector>; + + virtual unsigned projectScore() const { return 2; } + //! Removes all occurrences of PoolTerm instances. + //! Returns all unpooled incarnations of the literal. + //! \note The literal becomes unusable after the method returns. + //! \post The returned pool does not contain PoolTerm instances. + virtual ULitVec unpool(bool beforeRewrite) const = 0; + //! Simplifies the literal. + //! Flag positional=true indicates that anonymous variables in this literal can be projected. + //! Flag singleton=true disables projections for positive predicate literals (e.g., in non-monotone aggregates) + virtual bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) = 0; + //! Collects variables. + //! \pre Must be called after simplify to properly account for bound variables. + virtual void collect(VarTermBoundVec &vars, bool bound) const = 0; + //! Removes non-invertible arithmetics. + //! \note This method will not be called for head literals. + virtual void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) = 0; + virtual void toTuple(UTermVec &tuple, int &id) = 0; + virtual Symbol isEDB() const; + virtual bool hasPool(bool beforeRewrite) const = 0; + virtual void replace(Defines &dx) = 0; + virtual Ground::ULit toGround(DomainData &x, bool auxiliary) const = 0; + virtual ULit shift(bool negate) = 0; + virtual UTerm headRepr() const = 0; + virtual bool auxiliary() const = 0; + virtual void auxiliary(bool auxiliary) = 0; + virtual void getNeg(std::function f) const = 0; + virtual ~Literal() { } +}; + +// }}} + +} } // namespace Input Gringo + +GRINGO_HASH(Gringo::Input::Literal) + +#endif // _GRINGO_INPUT_LITERAL_HH diff --git a/libgringo/gringo/input/literals.hh b/libgringo/gringo/input/literals.hh new file mode 100644 index 0000000..ee4e89a --- /dev/null +++ b/libgringo/gringo/input/literals.hh @@ -0,0 +1,226 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_LITERALS_HH +#define _GRINGO_INPUT_LITERALS_HH + +#include +#include + +namespace Gringo { namespace Input { + +// {{{1 declaration of PredicateLiteral + +struct PredicateLiteral : Literal { + PredicateLiteral(NAF naf, UTerm &&repr, bool auxiliary = false); + unsigned projectScore() const override; + void collect(VarTermBoundVec &vars, bool bound) const override; + void toTuple(UTermVec &tuple, int &id) override; + PredicateLiteral *clone() const override; + void print(std::ostream &out) const override; + bool operator==(Literal const &other) const override; + size_t hash() const override; + bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) override; + ULitVec unpool(bool beforeRewrite) const override; + Symbol isEDB() const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + ULit shift(bool negate) override; + UTerm headRepr() const override; + bool auxiliary() const override { return auxiliary_; } + void auxiliary(bool auxiliary) override { auxiliary_ = auxiliary; } + void getNeg(std::function f) const override; + virtual ~PredicateLiteral(); + + NAF naf; + bool auxiliary_; + UTerm repr; +}; + +struct ProjectionLiteral : PredicateLiteral { + ProjectionLiteral(UTerm &&repr); + ProjectionLiteral *clone() const override; + ULitVec unpool(bool beforeRewrite) const override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + ULit shift(bool negate) override; + virtual ~ProjectionLiteral(); + mutable bool initialized_; +}; + +// }}} +// {{{ declaration of RelationLiteral + +struct RelationLiteral : Literal { + RelationLiteral(Relation rel, UTerm &&left, UTerm &&right); + unsigned projectScore() const override; + void collect(VarTermBoundVec &vars, bool bound) const override; + void toTuple(UTermVec &tuple, int &id) override; + RelationLiteral *clone() const override; + void print(std::ostream &out) const override; + bool operator==(Literal const &other) const override; + size_t hash() const override; + bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) override; + ULitVec unpool(bool beforeRewrite) const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + UTerm headRepr() const override; + ULit shift(bool negate) override; + bool auxiliary() const override { return true; } + void auxiliary(bool) override { } + virtual ~RelationLiteral(); + static ULit make(Term::ArithmeticsMap::value_type::value_type &x); + static ULit make(Literal::AssignVec::value_type &x); + void getNeg(std::function) const override { } + + Relation rel; + UTerm left; + UTerm right; +}; + +// }}} +// {{{ declaration of RangeLiteral + +struct RangeLiteral : Literal { + RangeLiteral(UTerm &&assign, UTerm &&lower, UTerm &&upper); + void collect(VarTermBoundVec &vars, bool bound) const override; + void toTuple(UTermVec &tuple, int &id) override; + RangeLiteral *clone() const override; + void print(std::ostream &out) const override; + bool operator==(Literal const &other) const override; + size_t hash() const override; + bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) override; + ULitVec unpool(bool beforeRewrite) const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + ULit shift(bool negate) override; + UTerm headRepr() const override; + bool auxiliary() const override { return true; } + void auxiliary(bool) override { } + virtual ~RangeLiteral(); + static ULit make(SimplifyState::DotsMap::value_type &dots); + void getNeg(std::function) const override { } + + UTerm assign; + UTerm lower; + UTerm upper; +}; + +// }}} +// {{{ declaration of ScriptLiteral + +struct ScriptLiteral : Literal { + ScriptLiteral(UTerm &&assign, String name, UTermVec &&args); + void collect(VarTermBoundVec &vars, bool bound) const override; + void toTuple(UTermVec &tuple, int &id) override; + ScriptLiteral *clone() const override; + void print(std::ostream &out) const override; + bool operator==(Literal const &other) const override; + size_t hash() const override; + bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) override; + ULitVec unpool(bool beforeRewrite) const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + ULit shift(bool negate) override; + UTerm headRepr() const override; + bool auxiliary() const override { return true; } + void auxiliary(bool) override { } + virtual ~ScriptLiteral(); + static ULit make(SimplifyState::ScriptMap::value_type &script); + void getNeg(std::function) const override { } + + UTerm assign; + String name; + UTermVec args; +}; + +// }}} +// {{{ declaration of FalseLiteral + +struct FalseLiteral : Literal { + FalseLiteral(); + unsigned projectScore() const override { return 0; } + void collect(VarTermBoundVec &vars, bool bound) const override; + void toTuple(UTermVec &tuple, int &id) override; + FalseLiteral *clone() const override; + void print(std::ostream &out) const override; + bool operator==(Literal const &other) const override; + size_t hash() const override; + bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) override; + ULitVec unpool(bool beforeRewrite) const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + ULit shift(bool negate) override; + UTerm headRepr() const override; + bool auxiliary() const override { return true; } + void auxiliary(bool) override { } + void getNeg(std::function) const override { } + virtual ~FalseLiteral(); +}; + +// }}} +// {{{ declaration of CSPLiteral + +struct CSPLiteral : Literal { + using Terms = std::vector; + + CSPLiteral(Relation rel, CSPAddTerm &&left, CSPAddTerm &&right); + CSPLiteral(Terms &&terms); + void append(Relation rel, CSPAddTerm &&x); + + void collect(VarTermBoundVec &vars, bool bound) const override; + void toTuple(UTermVec &tuple, int &id) override; + CSPLiteral *clone() const override; + void print(std::ostream &out) const override; + bool operator==(Literal const &other) const override; + size_t hash() const override; + bool simplify(Logger &log, Projections &project, SimplifyState &state, bool positional = true, bool singleton = false) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) override; + ULitVec unpool(bool beforeRewrite) const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + Ground::ULit toGround(DomainData &x, bool auxiliary) const override; + ULit shift(bool negate) override; + UTerm headRepr() const override; + bool auxiliary() const override { return auxiliary_; } + void auxiliary(bool auxiliary) override { auxiliary_ = auxiliary; } + void getNeg(std::function) const override { } + virtual ~CSPLiteral(); + + Terms terms; + bool auxiliary_ = false; +}; +using UCSPLit = std::unique_ptr; + +// }}} + +} } // namespace Input Gringo + +#endif // _GRINGO_INPUT_LITERALS_HH + diff --git a/libgringo/gringo/input/nongroundparser.hh b/libgringo/gringo/input/nongroundparser.hh new file mode 100644 index 0000000..56efd04 --- /dev/null +++ b/libgringo/gringo/input/nongroundparser.hh @@ -0,0 +1,103 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_NONGROUNDPARSER_HH +#define _GRINGO_INPUT_NONGROUNDPARSER_HH + +#include +#include +#include +#include +#include + +namespace Gringo { namespace Input { + +// {{{ declaration of NonGroundParser + +using StringVec = std::vector; +using ProgramVec = std::vector>; + +enum class TheoryLexing { Disabled, Theory, Definition }; + +class NonGroundParser : private LexerState>> { +private: + enum Condition { yyccomment, yycblockcomment, yycpython, yyclua, yycnormal, yyctheory, yycdefinition }; +public: + NonGroundParser(INongroundProgramBuilder &pb); + void parseError(Location const &loc, std::string const &token); + void pushFile(std::string &&filename, Logger &log); + void pushStream(std::string &&name, std::unique_ptr, Logger &log); + void pushBlock(std::string const &name, IdVec const &vec, std::string const &block, Logger &log); + int lex(void *pValue, Location &loc); + bool parseDefine(std::string const &define, Logger &log); + bool parse(Logger &log); + bool empty() { return LexerState::empty(); } + void include(String file, Location const &loc, bool include, Logger &log); + void theoryLexing(TheoryLexing mode); + INongroundProgramBuilder &builder(); + // Note: only to be used during parsing + Logger &logger() { assert(log_); return *log_; } + // {{{ aggregate helper functions + BoundVecUid boundvec(Relation ra, TermUid ta, Relation rb, TermUid tb); + unsigned aggregate(AggregateFunction fun, bool choice, unsigned elems, BoundVecUid bounds); + unsigned aggregate(TheoryAtomUid atom); + HdLitUid headaggregate(Location const &loc, unsigned hdaggr); + BdLitVecUid bodyaggregate(BdLitVecUid body, Location const &loc, NAF naf, unsigned bdaggr); + // }}} + ~NonGroundParser(); + +private: + int lex_impl(void *pValue, Location &loc); + void lexerError(StringSpan token); + bool push(std::string const &filename, bool include = false); + bool push(std::string const &file, std::unique_ptr in); + void pop(); + void _init(); + void condition(Condition cond); + using LexerState>>::start; + void start(Location &loc); + Condition condition() const; + String filename() const; + +private: + std::set filenames_; + bool incmodeIncluded_ = false; + TheoryLexing theoryLexing_ = TheoryLexing::Disabled; + String not_; + INongroundProgramBuilder &pb_; + struct Aggr + { + AggregateFunction fun; + unsigned choice; + unsigned elems; + BoundVecUid bounds; + }; + Indexed _aggregates; + int _startSymbol; + Condition condition_ = yycnormal; + String _filename; + Logger *log_ = nullptr; +}; + +// }}} + +} } // namespace Input Gringo + +#endif // _GRINGO_INPUT_NONGROUNDPARSER_HH diff --git a/libgringo/gringo/input/program.hh b/libgringo/gringo/input/program.hh new file mode 100644 index 0000000..a5681a8 --- /dev/null +++ b/libgringo/gringo/input/program.hh @@ -0,0 +1,88 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_PROGRAM_HH +#define _GRINGO_INPUT_PROGRAM_HH + +#include +#include +#include +#include + +namespace Gringo { namespace Input { + +// {{{ declaration of Program + +using IdVec = Ground::IdVec; + +struct Block { + Block(Location const &loc, String name, IdVec &¶ms); + Block(Block&&); + Block &operator=(Block &&); + ~Block(); + + Term const &sig() const; + operator Term const &() const; + + Location loc; + String name; + IdVec params; + SymVec addedEdb; + Ground::SEdb edb; + UStmVec addedStms; + UStmVec stms; +}; +using BlockMap = UniqueVec, EqualToKey>; + +class Program { +public: + Program(); + Program(Program &&x); + void begin(Location const &loc, String name, IdVec &¶ms); + void add(UStm &&stm); + void add(TheoryDef &&def, Logger &log); + void rewrite(Defines &defs, Logger &log); + void check(Logger &log); + void print(std::ostream &out) const; + Ground::Program toGround(DomainData &domains, Logger &log); + ~Program(); + +private: + void rewriteDots(); + void rewriteArithmetics(); + void unpool(); + + unsigned auxNames_ = 0; + Ground::LocSet locs_; + Ground::SigSet sigs_; + BlockMap blocks_; + Block *current_; + Projections project_; + UStmVec stms_; + TheoryDefs theoryDefs_; +}; + +std::ostream &operator<<(std::ostream &out, Program const &p); + +// }}} + +} } // namespace Input Gringo + +#endif //_GRINGO_INPUT_PROGRAM_HH diff --git a/libgringo/gringo/input/programbuilder.hh b/libgringo/gringo/input/programbuilder.hh new file mode 100644 index 0000000..0e0d3e4 --- /dev/null +++ b/libgringo/gringo/input/programbuilder.hh @@ -0,0 +1,653 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_PROGRAMBUILDER_HH +#define _GRINGO_INPUT_PROGRAMBUILDER_HH + +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace Gringo { + +struct Scripts; +struct CSPMulTerm; +struct CSPAddTerm; +class TheoryOpDef; +class TheoryTermDef; +class TheoryAtomDef; +class TheoryDef; + +namespace Input { + +class Program; +struct Statement; +struct BodyAggregate; +struct HeadAggregate; +struct Literal; +struct CSPLiteral; +struct CSPElem; +class TheoryElement; +class TheoryAtom; + +} // namespace Input + +namespace Output { + +class TheoryTerm; +class RawTheoryTerm; +class OutputBase; +using UTheoryTerm = std::unique_ptr; + +} } // namespace Output Gringo + +namespace Gringo { namespace Input { + +// {{{1 declaration of unique ids of program elements + +enum IdVecUid : unsigned { }; +enum CSPAddTermUid : unsigned { }; +enum CSPMulTermUid : unsigned { }; +enum CSPLitUid : unsigned { }; +enum TermUid : unsigned { }; +enum TermVecUid : unsigned { }; +enum TermVecVecUid : unsigned { }; +enum LitUid : unsigned { }; +enum LitVecUid : unsigned { }; +enum CondLitVecUid : unsigned { }; +enum BdAggrElemVecUid : unsigned { }; +enum HdAggrElemVecUid : unsigned { }; +enum HdLitUid : unsigned { }; +enum BdLitVecUid : unsigned { }; +enum BoundVecUid : unsigned { }; +enum CSPElemVecUid : unsigned { }; +enum TheoryOpVecUid : unsigned { }; +enum TheoryTermUid : unsigned { }; +enum TheoryOptermUid : unsigned { }; +enum TheoryOptermVecUid : unsigned { }; +enum TheoryElemVecUid : unsigned { }; +enum TheoryAtomUid : unsigned { }; +enum TheoryOpDefUid : unsigned { }; +enum TheoryOpDefVecUid : unsigned { }; +enum TheoryTermDefUid : unsigned { }; +enum TheoryAtomDefUid : unsigned { }; +enum TheoryDefVecUid : unsigned { }; + +// {{{1 declaration of INongroundProgramBuilder + +class INongroundProgramBuilder { +public: + TermUid predRep(Location const &loc, bool neg, String name, TermVecVecUid tvvUid) { + TermUid t = term(loc, name, tvvUid, false); + if (neg) { t = term(loc, UnOp::NEG, t); } + return t; + } + // {{{2 terms + virtual TermUid term(Location const &loc, Symbol val) = 0; // constant + virtual TermUid term(Location const &loc, String name) = 0; // variable + virtual TermUid term(Location const &loc, UnOp op, TermUid a) = 0; // unary operation + virtual TermUid term(Location const &loc, UnOp op, TermVecUid a) = 0; // unary operation + virtual TermUid term(Location const &loc, BinOp op, TermUid a, TermUid b) = 0; // binary operation + virtual TermUid term(Location const &loc, TermUid a, TermUid b) = 0; // dots + virtual TermUid term(Location const &loc, String name, TermVecVecUid b, bool lua) = 0; // function or lua function + virtual TermUid term(Location const &loc, TermVecUid args, bool forceTuple) = 0; // a tuple term (or simply a term) + virtual TermUid pool(Location const &loc, TermVecUid args) = 0; // a pool term + // {{{2 csp + virtual CSPMulTermUid cspmulterm(Location const &loc, TermUid coe, TermUid var) = 0; + virtual CSPMulTermUid cspmulterm(Location const &loc, TermUid coe) = 0; + virtual CSPAddTermUid cspaddterm(Location const &loc, CSPAddTermUid a, CSPMulTermUid b, bool add) = 0; + virtual CSPAddTermUid cspaddterm(Location const &loc, CSPMulTermUid a) = 0; + virtual LitUid csplit(CSPLitUid a) = 0; + virtual CSPLitUid csplit(Location const &loc, CSPLitUid a, Relation rel, CSPAddTermUid b) = 0; + virtual CSPLitUid csplit(Location const &loc, CSPAddTermUid a, Relation rel, CSPAddTermUid b) = 0; + // {{{2 id vectors + virtual IdVecUid idvec() = 0; + virtual IdVecUid idvec(IdVecUid uid, Location const &loc, String id) = 0; + // {{{2 term vectors + virtual TermVecUid termvec() = 0; + virtual TermVecUid termvec(TermVecUid uid, TermUid term) = 0; + // {{{2 term vector vectors + virtual TermVecVecUid termvecvec() = 0; + virtual TermVecVecUid termvecvec(TermVecVecUid uid, TermVecUid termvecUid) = 0; + // {{{2 literals + virtual LitUid boollit(Location const &loc, bool type) = 0; + virtual LitUid predlit(Location const &loc, NAF naf, TermUid atom) = 0; + virtual LitUid rellit(Location const &loc, Relation rel, TermUid termUidLeft, TermUid termUidRight) = 0; + // {{{2 literal vectors + virtual LitVecUid litvec() = 0; + virtual LitVecUid litvec(LitVecUid uid, LitUid literalUid) = 0; + // {{{2 conditional literals + virtual CondLitVecUid condlitvec() = 0; + virtual CondLitVecUid condlitvec(CondLitVecUid uid, LitUid lit, LitVecUid litvec) = 0; + // {{{2 body aggregate elements + virtual BdAggrElemVecUid bodyaggrelemvec() = 0; + virtual BdAggrElemVecUid bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) = 0; + // {{{2 head aggregate elements + virtual HdAggrElemVecUid headaggrelemvec() = 0; + virtual HdAggrElemVecUid headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid lit, LitVecUid litvec) = 0; + // {{{2 bounds + virtual BoundVecUid boundvec() = 0; + virtual BoundVecUid boundvec(BoundVecUid uid, Relation rel, TermUid term) = 0; + // {{{2 heads + virtual HdLitUid headlit(LitUid lit) = 0; + virtual HdLitUid headaggr(Location const &loc, TheoryAtomUid atom) = 0; + virtual HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, HdAggrElemVecUid headaggrelemvec) = 0; + virtual HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid headaggrelemvec) = 0; + virtual HdLitUid disjunction(Location const &loc, CondLitVecUid condlitvec) = 0; + // {{{2 bodies + virtual BdLitVecUid body() = 0; + virtual BdLitVecUid bodylit(BdLitVecUid body, LitUid bodylit) = 0; + virtual BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, TheoryAtomUid atom) = 0; + virtual BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) = 0; + virtual BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid bodyaggrelemvec) = 0; + virtual BdLitVecUid conjunction(BdLitVecUid body, Location const &loc, LitUid head, LitVecUid litvec) = 0; + virtual BdLitVecUid disjoint(BdLitVecUid body, Location const &loc, NAF naf, CSPElemVecUid elem) = 0; + // {{{2 csp constraint elements + virtual CSPElemVecUid cspelemvec() = 0; + virtual CSPElemVecUid cspelemvec(CSPElemVecUid uid, Location const &loc, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) = 0; + // {{{2 statements + virtual void rule(Location const &loc, HdLitUid head) = 0; + virtual void rule(Location const &loc, HdLitUid head, BdLitVecUid body) = 0; + virtual void define(Location const &loc, String name, TermUid value, bool defaultDef, Logger &log) = 0; + virtual void optimize(Location const &loc, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) = 0; + virtual void showsig(Location const &loc, Sig, bool csp) = 0; + virtual void show(Location const &loc, TermUid t, BdLitVecUid body, bool csp) = 0; + virtual void python(Location const &loc, String code) = 0; + virtual void lua(Location const &loc, String code) = 0; + virtual void block(Location const &loc, String name, IdVecUid args) = 0; + virtual void external(Location const &loc, TermUid head, BdLitVecUid body) = 0; + virtual void edge(Location const &loc, TermVecVecUid edges, BdLitVecUid body) = 0; + virtual void heuristic(Location const &loc, TermUid termUid, BdLitVecUid body, TermUid a, TermUid b, TermUid mod) = 0; + virtual void project(Location const &loc, TermUid termUid, BdLitVecUid body) = 0; + virtual void project(Location const &loc, Sig sig) = 0; + // {{{2 theory atoms + + virtual TheoryTermUid theorytermset(Location const &loc, TheoryOptermVecUid args) = 0; + virtual TheoryTermUid theoryoptermlist(Location const &loc, TheoryOptermVecUid args) = 0; + virtual TheoryTermUid theorytermopterm(Location const &loc, TheoryOptermUid opterm) = 0; + virtual TheoryTermUid theorytermtuple(Location const &loc, TheoryOptermVecUid args) = 0; + virtual TheoryTermUid theorytermfun(Location const &loc, String name, TheoryOptermVecUid args) = 0; + virtual TheoryTermUid theorytermvalue(Location const &loc, Symbol val) = 0; + virtual TheoryTermUid theorytermvar(Location const &loc, String var) = 0; + + virtual TheoryOptermUid theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) = 0; + virtual TheoryOptermUid theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) = 0; + + virtual TheoryOpVecUid theoryops() = 0; + virtual TheoryOpVecUid theoryops(TheoryOpVecUid ops, String op) = 0; + + virtual TheoryOptermVecUid theoryopterms() = 0; + virtual TheoryOptermVecUid theoryopterms(TheoryOptermVecUid opterms, Location const &loc, TheoryOptermUid opterm) = 0; + virtual TheoryOptermVecUid theoryopterms(Location const &loc, TheoryOptermUid opterm, TheoryOptermVecUid opterms) = 0; + + virtual TheoryElemVecUid theoryelems() = 0; + virtual TheoryElemVecUid theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) = 0; + + virtual TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems) = 0; + virtual TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &loc, TheoryOptermUid opterm) = 0; + + // {{{2 theory definitions + + virtual TheoryOpDefUid theoryopdef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) = 0; + virtual TheoryOpDefVecUid theoryopdefs() = 0; + virtual TheoryOpDefVecUid theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) = 0; + + virtual TheoryTermDefUid theorytermdef(Location const &loc, String name, TheoryOpDefVecUid defs, Logger &log) = 0; + virtual TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type) = 0; + virtual TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) = 0; + + virtual TheoryDefVecUid theorydefs() = 0; + virtual TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) = 0; + virtual TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) = 0; + + virtual void theorydef(Location const &loc, String name, TheoryDefVecUid defs, Logger &log) = 0; + + // }}}2 + + virtual ~INongroundProgramBuilder() { } +}; + +// {{{1 declaration of NongroundProgramBuilder + +using UCSPLit = std::unique_ptr; +using ULit = std::unique_ptr; +using ULitVec = std::vector; +using UHeadAggr = std::unique_ptr; +using UBodyAggr = std::unique_ptr; +using UStm = std::unique_ptr; +using BoundVec = std::vector; +using BodyAggrElem = std::pair; +using BodyAggrElemVec = std::vector; +using CondLit = std::pair; +using CondLitVec = std::vector; +using HeadAggrElem = std::tuple; +using HeadAggrElemVec = std::vector; +using UBodyAggrVec = std::vector; +using CSPElemVec = std::vector; +using IdVec = std::vector>; + +class NongroundProgramBuilder : public INongroundProgramBuilder { +public: + NongroundProgramBuilder(Scripts &scripts, Program &prg, Output::OutputBase &out, Defines &defs, bool rewriteMinimize = false); + // {{{2 terms + TermUid term(Location const &loc, Symbol val) override; // constant + TermUid term(Location const &loc, String name) override; // variable + TermUid term(Location const &loc, UnOp op, TermUid a) override; // unary operation + TermUid term(Location const &loc, UnOp op, TermVecUid a) override; // unary operation + TermUid term(Location const &loc, BinOp op, TermUid a, TermUid b) override; // binary operation + TermUid term(Location const &loc, TermUid a, TermUid b) override; // assignment + TermUid term(Location const &loc, String name, TermVecVecUid b, bool lua) override;// function or lua function + TermUid term(Location const &loc, TermVecUid args, bool forceTuple) override; // a tuple term (or simply a term) + TermUid pool(Location const &loc, TermVecUid args) override; // a pool term + + // {{{2 term vectors + TermVecUid termvec() override; + TermVecUid termvec(TermVecUid uid, TermUid term) override; + // {{{2 id vectors + IdVecUid idvec() override; + IdVecUid idvec(IdVecUid uid, Location const &loc, String id) override; + // {{{2 csp + CSPMulTermUid cspmulterm(Location const &loc, TermUid coe, TermUid var) override; + CSPMulTermUid cspmulterm(Location const &loc, TermUid coe) override; + CSPAddTermUid cspaddterm(Location const &loc, CSPAddTermUid a, CSPMulTermUid b, bool add) override; + CSPAddTermUid cspaddterm(Location const &loc, CSPMulTermUid a) override; + LitUid csplit(CSPLitUid a) override; + CSPLitUid csplit(Location const &loc, CSPLitUid a, Relation rel, CSPAddTermUid b) override; + CSPLitUid csplit(Location const &loc, CSPAddTermUid a, Relation rel, CSPAddTermUid b) override; + // {{{2 term vector vectors + TermVecVecUid termvecvec() override; + TermVecVecUid termvecvec(TermVecVecUid uid, TermVecUid termvecUid) override; + // {{{2 literals + LitUid boollit(Location const &loc, bool type) override; + LitUid predlit(Location const &loc, NAF naf, TermUid term) override; + LitUid rellit(Location const &loc, Relation rel, TermUid termUidLeft, TermUid termUidRight) override; + // {{{2 literal vectors + LitVecUid litvec() override; + LitVecUid litvec(LitVecUid uid, LitUid literalUid) override; + // {{{2 conditional literal vectors + CondLitVecUid condlitvec() override; + CondLitVecUid condlitvec(CondLitVecUid uid, LitUid lit, LitVecUid litvec) override; + // {{{2 body aggregate elements + BdAggrElemVecUid bodyaggrelemvec() override; + BdAggrElemVecUid bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) override; + // {{{2 head aggregate elements + HdAggrElemVecUid headaggrelemvec() override; + HdAggrElemVecUid headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid lit, LitVecUid litvec) override; + // {{{2 bounds + BoundVecUid boundvec() override; + BoundVecUid boundvec(BoundVecUid uid, Relation rel, TermUid term) override; + // {{{2 heads + HdLitUid headlit(LitUid lit) override; + HdLitUid headaggr(Location const &loc, TheoryAtomUid atom) override; + HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, HdAggrElemVecUid headaggrelemvec) override; + HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid headaggrelemvec) override; + HdLitUid disjunction(Location const &loc, CondLitVecUid condlitvec) override; + // {{{2 bodies + BdLitVecUid body() override; + BdLitVecUid bodylit(BdLitVecUid body, LitUid bodylit) override; + BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, TheoryAtomUid atom) override; + BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) override; + BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid bodyaggrelemvec) override; + BdLitVecUid conjunction(BdLitVecUid body, Location const &loc, LitUid head, LitVecUid litvec) override; + BdLitVecUid disjoint(BdLitVecUid body, Location const &loc, NAF naf, CSPElemVecUid elem) override; + // {{{2 csp constraint elements + CSPElemVecUid cspelemvec() override; + CSPElemVecUid cspelemvec(CSPElemVecUid uid, Location const &loc, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) override; + // {{{2 statements + void rule(Location const &loc, HdLitUid head) override; + void rule(Location const &loc, HdLitUid head, BdLitVecUid body) override; + void define(Location const &loc, String name, TermUid value, bool defaultDef, Logger &log) override; + void optimize(Location const &loc, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) override; + void showsig(Location const &loc, Sig sig, bool csp) override; + void show(Location const &loc, TermUid t, BdLitVecUid body, bool csp) override; + void python(Location const &loc, String code) override; + void lua(Location const &loc, String code) override; + void block(Location const &loc, String name, IdVecUid args) override; + void external(Location const &loc, TermUid head, BdLitVecUid body) override; + void edge(Location const &loc, TermVecVecUid edges, BdLitVecUid body) override; + void heuristic(Location const &loc, TermUid termUid, BdLitVecUid body, TermUid a, TermUid b, TermUid mod) override; + void project(Location const &loc, TermUid termUid, BdLitVecUid body) override; + void project(Location const &loc, Sig sig) override; + // }}}2 + // {{{2 theory atoms + TheoryTermUid theorytermset(Location const &loc, TheoryOptermVecUid args) override; + TheoryTermUid theoryoptermlist(Location const &loc, TheoryOptermVecUid args) override; + TheoryTermUid theorytermopterm(Location const &loc, TheoryOptermUid opterm) override; + TheoryTermUid theorytermtuple(Location const &loc, TheoryOptermVecUid args) override; + TheoryTermUid theorytermfun(Location const &loc, String name, TheoryOptermVecUid args) override; + TheoryTermUid theorytermvalue(Location const &loc, Symbol val) override; + TheoryTermUid theorytermvar(Location const &loc, String var) override; + + TheoryOptermUid theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) override; + TheoryOptermUid theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) override; + + TheoryOpVecUid theoryops() override; + TheoryOpVecUid theoryops(TheoryOpVecUid ops, String op) override; + + TheoryOptermVecUid theoryopterms() override; + TheoryOptermVecUid theoryopterms(TheoryOptermVecUid opterms, Location const &loc, TheoryOptermUid opterm) override; + TheoryOptermVecUid theoryopterms(Location const &loc, TheoryOptermUid opterm, TheoryOptermVecUid opterms) override; + + TheoryElemVecUid theoryelems() override; + TheoryElemVecUid theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) override; + + TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems) override; + TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &loc, TheoryOptermUid opterm) override; + + // {{{2 theory definitions + + TheoryOpDefUid theoryopdef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) override; + TheoryOpDefVecUid theoryopdefs() override; + TheoryOpDefVecUid theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) override; + + TheoryTermDefUid theorytermdef(Location const &loc, String name, TheoryOpDefVecUid defs, Logger &log) override; + TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type) override; + TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) override; + + TheoryDefVecUid theorydefs() override; + TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) override; + TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) override; + + void theorydef(Location const &loc, String name, TheoryDefVecUid defs, Logger &log) override; + + // }}}2 + virtual ~NongroundProgramBuilder(); + +private: + using Terms = Indexed; + using TermVecs = Indexed; + using TermVecVecs = Indexed; + using IdVecs = Indexed; + using Lits = Indexed; + using LitVecs = Indexed; + using BodyAggrElemVecs = Indexed; + using CondLitVecs = Indexed; + using HeadAggrElemVecs = Indexed; + using Bodies = Indexed; + using Heads = Indexed; + using CSPLits = Indexed; + using CSPAddTerms = Indexed; + using CSPMulTerms = Indexed; + using CSPElems = Indexed; + using Statements = std::vector; + using Bounds = Indexed; + using VarVals = std::unordered_map; + + using TheoryOpVecs = Indexed, TheoryOpVecUid>; + using TheoryTerms = Indexed; + using RawTheoryTerms = Indexed; + using RawTheoryTermVecs = Indexed, TheoryOptermVecUid>; + using TheoryElementVecs = Indexed, TheoryElemVecUid>; + using TheoryAtoms = Indexed; + + using TheoryOpDefs = Indexed; + using TheoryOpDefVecs = Indexed, TheoryOpDefVecUid>; + using TheoryTermDefs = Indexed; + using TheoryAtomDefs = Indexed; + using TheoryDefVecs = Indexed, std::vector>, TheoryDefVecUid>; + + Terms terms_; + TermVecs termvecs_; + TermVecVecs termvecvecs_; + IdVecs idvecs_; + Lits lits_; + LitVecs litvecs_; + BodyAggrElemVecs bodyaggrelemvecs_; + HeadAggrElemVecs headaggrelemvecs_; + CondLitVecs condlitvecs_; + Bounds bounds_; + Bodies bodies_; + Heads heads_; + VarVals vals_; + CSPLits csplits_; + CSPAddTerms cspaddterms_; + CSPMulTerms cspmulterms_; + CSPElems cspelems_; + TheoryOpVecs theoryOpVecs_; + TheoryTerms theoryTerms_; + RawTheoryTerms theoryOpterms_; + RawTheoryTermVecs theoryOptermVecs_; + TheoryElementVecs theoryElems_; + TheoryAtoms theoryAtoms_; + TheoryOpDefs theoryOpDefs_; + TheoryOpDefVecs theoryOpDefVecs_; + TheoryTermDefs theoryTermDefs_; + TheoryAtomDefs theoryAtomDefs_; + TheoryDefVecs theoryDefVecs_; + Scripts &scripts_; + Program &prg_; + Output::OutputBase &out; + Defines &defs_; + bool rewriteMinimize_; +}; + +// {{{1 declaration of ASTBuilder + +class ASTBuilder : public Gringo::Input::INongroundProgramBuilder { +public: + using Callback = std::function; + ASTBuilder(Callback cb); + virtual ~ASTBuilder() noexcept; + + // {{{2 terms + TermUid term(Location const &loc, Symbol val) override; + TermUid term(Location const &loc, String name) override; + TermUid term(Location const &loc, UnOp op, TermUid a) override; + TermUid term(Location const &loc, UnOp op, TermVecUid a) override; + TermUid term(Location const &loc, BinOp op, TermUid a, TermUid b) override; + TermUid term(Location const &loc, TermUid a, TermUid b) override; + TermUid term(Location const &loc, String name, TermVecVecUid a, bool lua) override; + TermUid term(Location const &loc, TermVecUid a, bool forceTuple) override; + TermUid pool(Location const &loc, TermVecUid a) override; + // {{{2 csp + CSPMulTermUid cspmulterm(Location const &loc, TermUid coe, TermUid var) override; + CSPMulTermUid cspmulterm(Location const &loc, TermUid coe) override; + CSPAddTermUid cspaddterm(Location const &loc, CSPAddTermUid a, CSPMulTermUid b, bool add) override; + CSPAddTermUid cspaddterm(Location const &, CSPMulTermUid b) override; + CSPLitUid csplit(Location const &loc, CSPLitUid a, Relation rel, CSPAddTermUid b) override; + CSPLitUid csplit(Location const &loc, CSPAddTermUid a, Relation rel, CSPAddTermUid b) override; + // {{{2 id vectors + IdVecUid idvec() override; + IdVecUid idvec(IdVecUid uid, Location const &loc, String id) override; + // {{{2 term vectors + TermVecUid termvec() override; + TermVecUid termvec(TermVecUid uid, TermUid termUid) override; + // {{{2 term vector vectors + TermVecVecUid termvecvec() override; + TermVecVecUid termvecvec(TermVecVecUid uid, TermVecUid termvecUid) override; + // {{{2 literals + LitUid boollit(Location const &loc, bool type) override; + LitUid predlit(Location const &loc, NAF naf, TermUid term) override; + LitUid rellit(Location const &loc, Relation rel, TermUid termUidLeft, TermUid termUidRight) override; + LitUid csplit(CSPLitUid a) override; + // {{{2 literal vectors + LitVecUid litvec() override; + LitVecUid litvec(LitVecUid uid, LitUid literalUid) override; + // {{{2 conditional literals + CondLitVecUid condlitvec() override; + CondLitVecUid condlitvec(CondLitVecUid uid, LitUid litUid, LitVecUid litvecUid) override; + // {{{2 body aggregate elements + BdAggrElemVecUid bodyaggrelemvec() override; + BdAggrElemVecUid bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) override; + // {{{2 head aggregate elements + HdAggrElemVecUid headaggrelemvec() override; + HdAggrElemVecUid headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid lit, LitVecUid litvec) override; + // {{{2 bounds + BoundVecUid boundvec() override; + BoundVecUid boundvec(BoundVecUid uid, Relation rel, TermUid term) override; + // {{{2 heads + HdLitUid headlit(LitUid litUid) override; + HdLitUid headaggr(Location const &loc, TheoryAtomUid atomUid) override; + HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, HdAggrElemVecUid headaggrelemvec) override; + HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid headaggrelemvec) override; + HdLitUid disjunction(Location const &loc, CondLitVecUid condlitvec) override; + // {{{2 bodies + BdLitVecUid body() override; + BdLitVecUid bodylit(BdLitVecUid body, LitUid bodylit) override; + BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, TheoryAtomUid atomUid) override; + BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) override; + BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid bodyaggrelemvec) override; + BdLitVecUid conjunction(BdLitVecUid body, Location const &loc, LitUid head, LitVecUid litvec) override; + BdLitVecUid disjoint(BdLitVecUid body, Location const &loc, NAF naf, CSPElemVecUid elem) override; + // {{{2 csp constraint elements + CSPElemVecUid cspelemvec() override; + CSPElemVecUid cspelemvec(CSPElemVecUid uid, Location const &loc, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) override; + // {{{2 statements + void rule(Location const &loc, HdLitUid head) override; + void rule(Location const &loc, HdLitUid head, BdLitVecUid body) override; + void define(Location const &loc, String name, TermUid value, bool defaultDef, Logger &log) override; + void optimize(Location const &loc, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) override; + void showsig(Location const &loc, Sig sig, bool csp) override; + void show(Location const &loc, TermUid t, BdLitVecUid body, bool csp) override; + void python(Location const &loc, String code) override; + void lua(Location const &loc, String code) override; + void block(Location const &loc, String name, IdVecUid args) override; + void external(Location const &loc, TermUid head, BdLitVecUid body) override; + void edge(Location const &loc, TermVecVecUid edges, BdLitVecUid body) override; + void heuristic(Location const &loc, TermUid termUid, BdLitVecUid body, TermUid a, TermUid b, TermUid mod) override; + void project(Location const &loc, TermUid termUid, BdLitVecUid body) override; + void project(Location const &loc, Sig sig) override; + // {{{2 theory atoms + TheoryTermUid theorytermset(Location const &loc, TheoryOptermVecUid args) override; + TheoryTermUid theoryoptermlist(Location const &loc, TheoryOptermVecUid args) override; + TheoryTermUid theorytermtuple(Location const &loc, TheoryOptermVecUid args) override; + TheoryTermUid theorytermopterm(Location const &loc, TheoryOptermUid opterm) override; + TheoryTermUid theorytermfun(Location const &loc, String name, TheoryOptermVecUid args) override; + TheoryTermUid theorytermvalue(Location const &loc, Symbol val) override; + TheoryTermUid theorytermvar(Location const &loc, String var) override; + TheoryOptermUid theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) override; + TheoryOptermUid theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) override; + TheoryOpVecUid theoryops() override; + TheoryOpVecUid theoryops(TheoryOpVecUid ops, String op) override; + TheoryOptermVecUid theoryopterms() override; + TheoryOptermVecUid theoryopterms(TheoryOptermVecUid opterms, Location const &loc, TheoryOptermUid opterm) override; + TheoryOptermVecUid theoryopterms(Location const &loc, TheoryOptermUid opterm, TheoryOptermVecUid opterms) override; + TheoryElemVecUid theoryelems() override; + TheoryElemVecUid theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) override; + TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems) override; + TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &loc, TheoryOptermUid opterm) override; + // {{{2 theory definitions + TheoryOpDefUid theoryopdef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) override; + TheoryOpDefVecUid theoryopdefs() override; + TheoryOpDefVecUid theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) override; + TheoryTermDefUid theorytermdef(Location const &loc, String name, TheoryOpDefVecUid defs, Logger &log) override; + TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type) override; + TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) override; + TheoryDefVecUid theorydefs() override; + TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) override; + TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) override; + void theorydef(Location const &loc, String name, TheoryDefVecUid defs, Logger &log) override; + // }}}2 + +private: + using TermVec = std::vector; + using TermVecVec = std::vector; + + TermUid pool_(Location const &loc, TermVec &&vec); + clingo_ast_term_t fun_(Location const &loc, String name, TermVec &&vec, bool external); + TheoryTermUid theorytermarr_(Location const &loc, TheoryOptermVecUid args, clingo_ast_theory_term_type_t type); + clingo_ast_theory_unparsed_term_element_t opterm_(TheoryOpVecUid ops, TheoryTermUid term); + clingo_ast_theory_term_t opterm_(Location const &loc, TheoryOptermUid opterm); + template + T *create_(); + template + T *create_(T x); + template + T *createArray_(size_t size); + template + T *createArray_(std::vector const &vec); + + void statement_(Location loc, clingo_ast_statement_type_t type, clingo_ast_statement_t &stm); + void clear_() noexcept; + + using Terms = Indexed; + using TermVecs = Indexed; + using TermVecVecs = Indexed; + using CSPAddTerms = Indexed>, CSPAddTermUid>; + using CSPMulTerms = Indexed; + using CSPLits = Indexed>>, CSPLitUid>; + using IdVecs = Indexed, IdVecUid>; + using Lits = Indexed; + using LitVecs = Indexed, LitVecUid>; + using CondLitVecs = Indexed, CondLitVecUid>; + using BodyAggrElemVecs = Indexed, BdAggrElemVecUid>; + using HeadAggrElemVecs = Indexed, HdAggrElemVecUid>; + using Bounds = Indexed, BoundVecUid>; + using Bodies = Indexed, BdLitVecUid>; + using Heads = Indexed; + using TheoryAtoms = Indexed; + using CSPElems = Indexed, CSPElemVecUid>; + using TheoryOpVecs = Indexed, TheoryOpVecUid>; + using TheoryTerms = Indexed; + using RawTheoryTerms = Indexed, TheoryOptermUid>; + using RawTheoryTermVecs = Indexed, TheoryOptermVecUid>; + using TheoryElementVecs = Indexed, TheoryElemVecUid>; + using TheoryOpDefs = Indexed; + using TheoryOpDefVecs = Indexed, TheoryOpDefVecUid>; + using TheoryTermDefs = Indexed; + using TheoryAtomDefs = Indexed; + using TheoryDefVecs = Indexed, std::vector>, TheoryDefVecUid>; + + Callback cb_; + Terms terms_; + TermVecs termvecs_; + TermVecVecs termvecvecs_; + CSPAddTerms cspaddterms_; + CSPMulTerms cspmulterms_; + CSPLits csplits_; + IdVecs idvecs_; + Lits lits_; + LitVecs litvecs_; + CondLitVecs condlitvecs_; + BodyAggrElemVecs bodyaggrelemvecs_; + HeadAggrElemVecs headaggrelemvecs_; + Bounds bounds_; + Bodies bodies_; + Heads heads_; + TheoryAtoms theoryAtoms_; + CSPElems cspelems_; + TheoryOpVecs theoryOpVecs_; + TheoryTerms theoryTerms_; + RawTheoryTerms theoryOpterms_; + RawTheoryTermVecs theoryOptermVecs_; + TheoryElementVecs theoryElems_; + TheoryOpDefs theoryOpDefs_; + TheoryOpDefVecs theoryOpDefVecs_; + TheoryTermDefs theoryTermDefs_; + TheoryAtomDefs theoryAtomDefs_; + TheoryDefVecs theoryDefVecs_; + std::vector data_; + std::vector arrdata_; +}; + +void parseStatement(INongroundProgramBuilder &prg, Logger &log, clingo_ast_statement_t const &stm); + +// }}}1 + +} } // namespace Input Gringo + +#endif // _GRINGO_PROGRAMBUILDER_HH diff --git a/libgringo/gringo/input/statement.hh b/libgringo/gringo/input/statement.hh new file mode 100644 index 0000000..dba81a4 --- /dev/null +++ b/libgringo/gringo/input/statement.hh @@ -0,0 +1,58 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_STATEMENT_HH +#define _GRINGO_INPUT_STATEMENT_HH + +#include +#include + +namespace Gringo { namespace Input { + +// {{{ declaration of Statement + +enum class StatementType { RULE, EXTERNAL, WEAKCONSTRAINT }; + +struct Statement : Printable, Locatable { + Statement(UHeadAggr &&head, UBodyAggrVec &&body, StatementType type); + virtual UStmVec unpool(bool beforeRewrite); + virtual bool rewrite1(Projections &project, Logger &log); + virtual void rewrite2(); + virtual Symbol isEDB() const; + virtual void print(std::ostream &out) const; + virtual bool hasPool(bool beforeRewrite) const; + virtual void check(Logger &log) const; + virtual void replace(Defines &dx); + virtual void toGround(ToGroundArg &x, Ground::UStmVec &stms) const; + virtual void add(ULit &&lit); + virtual void initTheory(TheoryDefs &def, Logger &log); + virtual void getNeg(std::function f) const; + virtual ~Statement(); + + UHeadAggr head; + UBodyAggrVec body; + StatementType type; +}; + +// }}} + +} } // namespace Input Gringo + +#endif // _GRINGO_INPUT_STATEMENT_HH diff --git a/libgringo/gringo/input/theory.hh b/libgringo/gringo/input/theory.hh new file mode 100644 index 0000000..40dd1ff --- /dev/null +++ b/libgringo/gringo/input/theory.hh @@ -0,0 +1,189 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_THEORY_HH +#define _GRINGO_INPUT_THEORY_HH + +#include +#include +#include + +namespace Gringo { + +namespace Ground { + +class TheoryAccumulate; +class TheoryComplete; +class TheoryLiteral; + +} // namespace Ground + +namespace Input { + +// {{{1 declaration of TheoryElement + +class TheoryElement; +using TheoryElementVec = std::vector; +class TheoryElement { +public: + TheoryElement(TheoryElement &&); + TheoryElement &operator=(TheoryElement &&); + TheoryElement(Output::UTheoryTermVec &&tuple, ULitVec &&cond); + ~TheoryElement() noexcept; + TheoryElement clone() const; + void print(std::ostream &out) const; + bool operator==(TheoryElement const &other) const; + size_t hash() const; + void unpool(TheoryElementVec &elems, bool beforeRewrite); + bool hasPool(bool beforeRewrite) const; + void replace(Defines &x); + void collect(VarTermBoundVec &vars) const; + void assignLevels(AssignLevel &lvl); + void check(Location const &loc, Printable const &p, ChkLvlVec &levels, Logger &log) const; + bool simplify(Projections &project, SimplifyState &state, Logger &log); + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen); + void initTheory(Output::TheoryParser &p, Logger &log); + std::unique_ptr toGround(ToGroundArg &x, Ground::TheoryComplete &completeRef, Ground::ULitVec &&lits) const; + +private: + Output::UTheoryTermVec tuple_; + ULitVec cond_; +}; +inline std::ostream &operator<<(std::ostream &out, TheoryElement const &elem) { elem.print(out); return out; } + +// {{{1 declaration of TheoryAtom + +class TheoryAtom { +public: + TheoryAtom(TheoryAtom &&); + TheoryAtom &operator=(TheoryAtom &&); + // Note: name must be a term that (after unpooling) has a signature + TheoryAtom(UTerm &&name, TheoryElementVec &&elems); + TheoryAtom(UTerm &&name, TheoryElementVec &&elems, String op, Output::UTheoryTerm &&guard, TheoryAtomType type = TheoryAtomType::Any); + ~TheoryAtom() noexcept; + TheoryAtom clone() const; + bool operator==(TheoryAtom const &other) const; + void print(std::ostream &out) const; + bool hasGuard() const; + size_t hash() const; + template + void unpool(T f, bool beforeRewrite); + bool hasPool(bool beforeRewrite) const; + void replace(Defines &x); + void collect(VarTermBoundVec &vars) const; + void assignLevels(AssignLevel &lvl); + void check(Location const &loc, Printable const &p, ChkLvlVec &levels, Logger &log) const; + bool simplify(Projections &project, SimplifyState &state, Logger &log); + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen); + void initTheory(Location const &loc, TheoryDefs &def, bool inBody, bool hasBody, Logger &log); + TheoryAtomType type() const { return type_; } + CreateBody toGroundBody(ToGroundArg &x, Ground::UStmVec &stms, NAF naf, UTerm &&id) const; + CreateHead toGroundHead() const; + +private: + UTerm name_; + TheoryElementVec elems_; + String op_; + Output::UTheoryTerm guard_; + TheoryAtomType type_ = TheoryAtomType::Any; +}; +inline std::ostream &operator<<(std::ostream &out, TheoryAtom const &atom) { atom.print(out); return out; } + +// {{{1 declaration of BodyTheoryLiteral + +class BodyTheoryLiteral : public BodyAggregate { +public: + BodyTheoryLiteral(NAF naf, TheoryAtom &&atom, bool rewritten = false); + virtual ~BodyTheoryLiteral() noexcept; + // {{{2 BodyAggregate interface + void unpool(UBodyAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) override; + bool rewriteAggregates(UBodyAggrVec &aggr) override; + void removeAssignment() override; + bool isAssignment() const override; + void collect(VarTermBoundVec &vars) const override; + bool hasPool(bool beforeRewrite) const override; + void replace(Defines &dx) override; + CreateBody toGround(ToGroundArg &x, Ground::UStmVec &stms) const override; + void initTheory(TheoryDefs &def, Logger &log) override; + // {{{2 Hashable + size_t hash() const override; + // {{{2 Printable + void print(std::ostream &out) const override; + // {{{2 Clonable + BodyTheoryLiteral *clone() const override; + // {{{2 Comparable interface + bool operator==(BodyAggregate const &other) const override; + // }}}2 + +private: + TheoryAtom atom_; + NAF naf_; + bool rewritten_; +}; + +// }}}1 + +// {{{1 declaration of HeadTheoryLiteral + +class HeadTheoryLiteral : public HeadAggregate { +public: + HeadTheoryLiteral(TheoryAtom &&atom, bool rewritten = false); + virtual ~HeadTheoryLiteral() noexcept; + // {{{2 HeadAggregate interface + CreateHead toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType type) const override; + UHeadAggr rewriteAggregates(UBodyAggrVec &aggr) override; + void collect(VarTermBoundVec &vars) const override; + void unpool(UHeadAggrVec &x, bool beforeRewrite) override; + bool simplify(Projections &project, SimplifyState &state, Logger &log) override; + void assignLevels(AssignLevel &lvl) override; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) override; + bool hasPool(bool beforeRewrite) const override; + void check(ChkLvlVec &lvl, Logger &log) const override; + void replace(Defines &x) override; + void getNeg(std::function f) const override; + void initTheory(TheoryDefs &def, bool hasBody, Logger &log) override; + // {{{2 Hashable + size_t hash() const override; + // {{{2 Printable + void print(std::ostream &out) const override; + // {{{2 Clonable + // precondition: must not be called after rewriteAggregates + HeadTheoryLiteral *clone() const override; + // {{{2 Comparable interface + bool operator==(HeadAggregate const &other) const override; + // }}}2 + +private: + TheoryAtom atom_; + bool rewritten_; +}; + +} } // namespace Gringo Input + +GRINGO_CALL_HASH(Gringo::Input::TheoryAtom) +GRINGO_CALL_HASH(Gringo::Input::TheoryElement) +GRINGO_CALL_CLONE(Gringo::Input::TheoryElement) +GRINGO_CALL_CLONE(Gringo::Input::TheoryAtom) + +#endif // _GRINGO_INPUT_THEORY_HH diff --git a/libgringo/gringo/input/types.hh b/libgringo/gringo/input/types.hh new file mode 100644 index 0000000..be64ecc --- /dev/null +++ b/libgringo/gringo/input/types.hh @@ -0,0 +1,52 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INPUT_TYPES_HH +#define _GRINGO_INPUT_TYPES_HH + +#include + +namespace Gringo { namespace Input { + +using Gringo::Output::PredicateDomain; +using Gringo::Output::PredDomMap; +using Gringo::Output::DomainData; + +struct ToGroundArg; +struct Projections; + +struct Literal; +using ULit = std::unique_ptr; +using ULitVec = std::vector; + +struct Statement; +using UStm = std::unique_ptr; +using UStmVec = std::vector; + +struct BodyAggregate; +using UBodyAggr = std::unique_ptr; + +struct HeadAggregate; +using UHeadAggr = std::unique_ptr; +using UBodyAggrVec = std::vector; + +} } // namespace Input Gringo + +#endif // _GRINGO_INPUT_TYPES_HH diff --git a/libgringo/gringo/intervals.hh b/libgringo/gringo/intervals.hh new file mode 100644 index 0000000..1c6f42f --- /dev/null +++ b/libgringo/gringo/intervals.hh @@ -0,0 +1,370 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_INTERVALS_HH +#define _GRINGO_INTERVALS_HH + +#include +#include +#include + +namespace Gringo { + +// NOTE: refactor this is almost the same as interval_set ... + +template +struct IntervalSet { + // Notes: read < as before with gap (except if bounds of same type are compared) + using Value = T; + struct RBound; + struct LBound { + LBound &operator=(RBound const &x) { + bound = x.bound; + inclusive = !x.inclusive; + return *this; + } + Value bound; + bool inclusive; + bool operator<(LBound const &x) const { return bound < x.bound || (!(x.bound < bound) && inclusive && !x.inclusive ); } + bool operator<=(LBound const &x) const { return bound < x.bound || (!(x.bound < bound) && (inclusive || !x.inclusive)); } + bool operator<(RBound const &x) const { return bound < x.bound || (!(x.bound < bound) && inclusive && x.inclusive ); } + }; + struct RBound { + RBound &operator=(LBound const &x) { + bound = x.bound; + inclusive = !x.inclusive; + return *this; + } + Value bound; + bool inclusive; + bool operator<(RBound const &x) const { return bound < x.bound || (!(x.bound < bound) && !inclusive && x.inclusive ); } + bool operator<=(RBound const &x) const { return bound < x.bound || (!(x.bound < bound) && (!inclusive || x.inclusive)); } + bool operator<(LBound const &x) const { return bound < x.bound || (!(x.bound < bound) && !inclusive && !x.inclusive ); } + }; + struct Interval { + bool contains(T const &x) const { return !(x < *this) && !(*this < x); } + bool empty() const { return !(left < right); } + bool operator<(Interval const &x) const { return right < x.left; } + LBound left; + RBound right; + }; + using IntervalVec = std::vector; + using const_iterator = typename IntervalVec::const_iterator; + + IntervalSet(std::initializer_list list) { + for (auto &x : list) { add(x); } + } + IntervalSet(Interval const &x) { add(x); } + IntervalSet(Value const &a, bool ta, Value const &b, bool tb) { add({{a, ta}, {b, tb}}); } + IntervalSet(IntervalSet &&) = default; + IntervalSet(IntervalSet const &) = default; + IntervalSet() = default; + IntervalSet &operator=(IntervalSet const &) = default; + IntervalSet &operator=(IntervalSet &&) = default; + ~IntervalSet() = default; + + void add(Interval const &x) { + if (!x.empty()) { + auto it = std::lower_bound(vec.begin(), vec.end(), x); + if (it == vec.end()) { vec.emplace_back(x); } + else { + auto jt = std::upper_bound(it, vec.end(), x); + if (it == jt) { vec.emplace(it, x); } + else { + it->left = std::min(x.left, it->left); + it->right = std::max(x.right, (jt-1)->right); + vec.erase(it+1, jt); + } + } + } + } + void remove(Interval const &x) { + if (!x.empty()) { + auto it = std::lower_bound(vec.begin(), vec.end(), x); + if (it != vec.end()) { + auto jt = std::upper_bound(it, vec.end(), x); + if (it+1 == jt) { + Interval r; + r.left = x.right; + r.right = it->right; + it->right = x.left; + if (it->empty()) { + if (r.empty()) { vec.erase(it); } + else { *it = r; } + } + else if (!r.empty()) { vec.emplace(it+1, r); } + } + else if (it != jt) { + it->right = x.left; + (jt-1)->left = x.right; + vec.erase(it + !it->empty(), jt - !(jt-1)->empty()); + } + } + } + } + bool contains(Interval const &x) const { + if (x.empty()) { return true; } + for (auto &y : vec) { + if (x.right <= y.right) { return y.left <= x.left; } + } + return false; + } + bool intersects(Interval const &x) const { + if (!x.empty()) { + for (auto &y : vec) { + if (x.left < y.right) { return y.left < x.right; } + } + } + return false; + } + bool empty() const { return vec.empty(); } + size_t size() const { return vec.size(); } + Interval const &front() const { return vec.front(); } + Interval const &back() const { return vec.back(); } + void clear() { return vec.clear(); } + void add(Value const &a, bool ta, Value const &b, bool tb) { add({{a, ta}, {b, tb}}); } + const_iterator begin() const { return vec.begin(); } + const_iterator end() const { return vec.end(); } + void remove(Value const &a, bool ta, Value const &b, bool tb) { return remove({{a, ta}, {b, tb}}); } + + IntervalSet intersect(IntervalSet const &set) const { + auto it = vec.begin(); + IntervalSet intersection; + for (auto &x : set.vec) { + for (; it != vec.end() && it->right < x.left; ++it) { } + for (; it != vec.end() && it->right <= x.right; ++it) { + intersection.vec.emplace_back(Interval{std::max(it->left, x.left), it->right}); + } + if (it != vec.end() && it->left < x.right) { + intersection.vec.emplace_back(Interval{std::max(it->left, x.left), x.right}); + } + } + return intersection; + } + + IntervalSet difference(IntervalSet const &set) const { + auto it = set.vec.begin(); + IntervalSet difference; + for (auto &x : vec) { + Interval current = x; + for (; it != set.vec.end() && it->right < current.left; ++it) { } + for (; it != set.vec.end() && it->right <= current.right; ++it) { + if (current.left < it->left) { + difference.vec.emplace_back(current); + difference.vec.back().right = it->left; + } + current.left = it->right; + } + if (it != set.vec.end() && it->left < current.right) { + current.right = it->left; + } + if (current.left < current.right) { + difference.vec.emplace_back(current); + } + } + return difference; + } + + IntervalVec vec; +}; + +template +bool operator<(T const &a, typename IntervalSet::Interval const &b) { + return a < b.left.bound || (!(b.left.bound < a) && !b.left.inclusive); +} + +template +bool operator<(typename IntervalSet::Interval const &a, T const &b) { + return a.right.bound < b || (!(b < a.right.bound) && !a.right.inclusive); +} + +template +class enum_interval_set { +public: + using value_type = T; + +private: + struct Interval { + Interval(value_type left, value_type right) + : left(left) + , right(right) { } + bool contains(value_type const &x) const { return !(x < left) && x < right; } + bool empty() const { return !(left < right); } + bool operator<(Interval const &x) const { return right < x.left; } + T left; + T right; + }; + using interval_vec = std::vector; + +public: + class const_iterator : public std::iterator { + friend class enum_interval_set; + using iterator = std::iterator; + public: + const_iterator() = default; + const_iterator(const_iterator const &x) = default; + + const_iterator& operator=(const const_iterator&) = default; + bool operator==(const_iterator const &x) const { return current == x.current; } + bool operator!=(const_iterator const &x) const { return current != x.current; } + + const_iterator& operator++() { + ++current; + if (!(current < rng->right)) { + ++rng; + if (rng != set->end()) { current = rng->left; } + } + return *this; + } + const_iterator operator++(int) { + const_iterator x = *this; + ++(*this); + return x; + } + const_iterator& operator--() { + --current; + if (rng == set->end()) { --rng; } + if (current < rng->left) { + if (rng != set->begin()) { + --rng; + current = rng->right; + --current; + } + } + return *this; + } + const_iterator operator--(int) { + const_iterator x = *this; + --(*this); + return x; + } + + value_type operator*() const { return current; } + typename iterator::pointer operator->() const { return ¤t; } + + private: + const_iterator(value_type const ¤t, typename interval_vec::const_iterator const &rng, interval_vec const &set) + : current(current) + , rng(rng) + , set(&set) { } + value_type current; + typename interval_vec::const_iterator rng; + interval_vec const *set; + }; + + enum_interval_set() = default; + enum_interval_set(enum_interval_set const &x) = default; + enum_interval_set(enum_interval_set &&x) = default; + void add(value_type const &a, value_type const &b) { return add(Interval(a, b)); } + void remove(value_type const &a, value_type const &b) { return remove(Interval(a, b)); } + void intersect(enum_interval_set const &set) { + auto it = vec.begin(); + interval_vec intersection; + for (auto &x : set.vec) { + // Note: that could be a call to lower bound too ... + for (; it != vec.end() && it->right <= x.left; ++it) { } + for (; it != vec.end() && it->right <= x.right; ++it) { + intersection.emplace_back(std::max(it->left, x.left), it->right); + } + if (it != vec.end() && it->left < x.right) { + intersection.emplace_back(std::max(it->left, x.left), x.right); + } + } + std::swap(intersection, vec); + } + bool contains(value_type const &a, value_type const &b) const { return contains(Interval(a, b)); } + bool intersects(value_type const &a, value_type const &b) const { return intersects(Interval(a, b)); } + bool empty() const { return vec.empty(); } + void clear() { return vec.clear(); } + value_type front() const { return vec.front().left; } + value_type back() const { auto ret = vec.back().right; --ret; return ret; } + const_iterator begin() const { return const_iterator(empty() ? value_type() : vec.front().left, vec.begin(), vec); } + const_iterator end() const { return const_iterator(empty() ? value_type() : vec.back().right, vec.end(), vec); } + +private: + void add(Interval const &x) { + if (!x.empty()) { + auto it = std::lower_bound(vec.begin(), vec.end(), x); + if (it == vec.end()) { vec.emplace_back(x); } + else { + auto jt = std::upper_bound(it, vec.end(), x); + if (it == jt) { vec.emplace(it, x); } + else { + it->left = std::min(x.left, it->left); + it->right = std::max(x.right, (jt-1)->right); + vec.erase(it+1, jt); + } + } + } + } + void remove(Interval const &x) { + if (!x.empty()) { + auto it = std::lower_bound(vec.begin(), vec.end(), x); + if (it != vec.end()) { + auto jt = std::upper_bound(it, vec.end(), x); + if (it+1 == jt) { + Interval r(x.right, it->right); + it->right = x.left; + if (it->empty()) { + if (r.empty()) { vec.erase(it); } + else { *it = r; } + } + else if (!r.empty()) { vec.emplace(it+1, r); } + } + else if (it != jt) { + it->right = x.left; + (jt-1)->left = x.right; + vec.erase(it + !it->empty(), jt - !(jt-1)->empty()); + } + } + } + } + bool contains(Interval const &x) const { + if (x.empty()) { return true; } + for (auto &y : vec) { + if (!(y.right < x.right)) { return !(x.left < y.left); } + } + return false; + } + bool intersects(Interval const &x) const { + if (!x.empty()) { + for (auto &y : vec) { + if (x.left < y.right) { return y.left < x.right; } + } + } + return false; + } + + std::vector vec; +}; + +} // namespace Gringo + +namespace std { + +template +typename Gringo::IntervalSet::const_iterator begin(Gringo::IntervalSet const &x) { return x.begin(); } + +template +typename Gringo::IntervalSet::const_iterator end(Gringo::IntervalSet const &x) { return x.end(); } + +} // namespace std + +#endif // _GRINGO_INTERVALS_HH diff --git a/libgringo/gringo/lexerstate.hh b/libgringo/gringo/lexerstate.hh new file mode 100644 index 0000000..3e105bb --- /dev/null +++ b/libgringo/gringo/lexerstate.hh @@ -0,0 +1,331 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_LEXERSTATE_HH +#define _GRINGO_LEXERSTATE_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Gringo { + +using Potassco::StringSpan; + +// {{{ declaration of LexerState + +template +class LexerState { +private: + struct State; + +public: + using Data = T; + LexerState(); + void start(); + bool eof() const; + bool push(char const *file, T &&data); + bool push(std::unique_ptr in, T &&data); + void pop(); + bool empty() const; + StringSpan string(int start = 0, int end = 0); + void step(char s); + void step(); + int integer() const; + int line() const; + int column() const; + T const &data() const; + char *&cursor(); + char *&marker(); + char *&ctxmarker(); + char const *limit() const; + void fill(size_t n); + void seek(int offset); +private: + State const &state() const; + State &state(); +private: + std::vector states_; +}; + +// }}} +// {{{ declaration of LexerState::State + +template +struct LexerState::State { + State(T &&data); + State(State &&); + void fill(size_t n); + void step(); + void start(); + ~State(); + + std::unique_ptr in_; + T data_; + size_t bufmin_; + size_t bufsize_; + char *buffer_; + char *start_; + char *offset_; + char *cursor_; + char *limit_; + char *marker_; + char *ctxmarker_; + char *eof_; + int line_; + bool newline_; +}; + +// }}} + +// {{{ defintion of LexerState::State + +template +LexerState::State::State(T &&data) + : data_(std::forward(data)) + , bufmin_(4096), bufsize_(0) + , buffer_(0), start_(0), offset_(0) + , cursor_(0), limit_(0), marker_(0) + , ctxmarker_(0), eof_(0), line_(1) + , newline_(false) { } + +template +LexerState::State::State(State &&x) + : data_(std::forward(x.data_)) + , bufmin_(x.bufmin_), bufsize_(x.bufsize_) + , buffer_(0), start_(x.start_), offset_(x.offset_) + , cursor_(x.cursor_), limit_(x.limit_), marker_(x.marker_) + , ctxmarker_(x.ctxmarker_), eof_(x.eof_), line_(x.line_) + , newline_(x.newline_) { + std::swap(x.in_, in_); + std::swap(x.buffer_, buffer_); +} + +template +void LexerState::State::fill(size_t n) { + if (eof_) return; + if (start_ > buffer_) { + size_t shift = start_ - buffer_; + memmove(buffer_, start_, limit_ - start_); + start_ = buffer_; + offset_ -= shift; + marker_ -= shift; + ctxmarker_-= shift; + limit_ -= shift; + cursor_ -= shift; + } + size_t inc = n < bufmin_ ? bufmin_ : n; + if (bufsize_ < inc + (limit_ - buffer_)) { + bufsize_ = inc + (limit_ - buffer_); + char *buf = (char*)realloc(buffer_, bufsize_ * sizeof(char)); + start_ = buf + (start_ - buffer_); + cursor_ = buf + (cursor_ - buffer_); + limit_ = buf + (limit_ - buffer_); + marker_ = buf + (marker_ - buffer_); + ctxmarker_ = buf + (ctxmarker_ - buffer_); + offset_ = buf + (offset_ - buffer_); + buffer_ = buf; + } + in_->read(limit_, inc); + size_t read = size_t(in_->gcount()); + limit_+= read; + if (read > 0) { + newline_ = *(limit_ - 1) == '\n'; + } + // make sure the last line is newline terminated + if (read < inc && !newline_) { + newline_ = true; + ++read; + *limit_++ = '\n'; + } + if (read < inc) { + eof_ = limit_; + *eof_++ = '\n'; + } +} + +template +void LexerState::State::step() { + offset_ = cursor_; + line_++; +} + +template +void LexerState::State::start() { + start_ = cursor_; +} + +template +LexerState::State::~State() { + if(buffer_) free(buffer_); +} + +// }}} +// {{{ defintion of LexerState + +template +LexerState::LexerState() = default; + +template +void LexerState::start() { + state().start(); +} + +template +bool LexerState::eof() const { + return state().cursor_ == state().eof_; +} + +template +bool LexerState::push(std::unique_ptr in, T &&data) { + states_.emplace_back(std::forward(data)); + state().in_ = std::move(in); + return true; +} + +template +bool LexerState::push(char const *file, T &&data) { + if (strcmp(file, "-") == 0) { + states_.emplace_back(std::forward(data)); + state().in_.reset(new std::istream(std::cin.rdbuf(0))); + return true; + } + else { + std::unique_ptr ifs(new std::ifstream(file)); + if (ifs->is_open()) { + states_.emplace_back(std::forward(data)); + state().in_.reset(ifs.release()); + return true; + } + else { return false; } + } +} + +template +void LexerState::pop() { + states_.pop_back(); +} + +template +bool LexerState::empty() const { + return states_.empty(); +} + +template +StringSpan LexerState::string(int start, int end) { + auto b = state().start_ + start; + auto e = state().cursor_ - end; + return {b, static_cast(e - b)}; +} + +template +void LexerState::step(char s) { + for (char *c = state().start_; c != state().cursor_; c++) { + if (*c == s) { step(); } + } +} + +template +void LexerState::step() { + state().step(); +} + +template +int LexerState::integer() const { + int r = 0; + int s = 0; + if(*state().start_ == '-') s = 1; + for(char *i = state().start_ + s; i != state().cursor_; i++) { + r *= 10; + r += *i - '0'; + } + return s ? -r : r; +} + +template +int LexerState::line() const { + return state().line_; +} + +template +int LexerState::column() const { + return static_cast(state().cursor_ - state().offset_ + 1); +} + +template +T const &LexerState::data() const { + return state().data_; +} + +template +char *&LexerState::cursor() { + return state().cursor_; +} + +template +char *&LexerState::marker() { + return state().marker_; +} + +template +char *&LexerState::ctxmarker() { + return state().ctxmarker_; +} + +template +char const *LexerState::limit() const { + return state().limit_; +} + +template +void LexerState::fill(size_t n) { + state().fill(n); +} + +template +typename LexerState::State const &LexerState::state() const { + assert(!empty()); + return states_.back(); +} + +template +typename LexerState::State &LexerState::state() { + assert(!empty()); + return states_.back(); +} + +template +void LexerState::seek(int offset) { + state().cursor_ = state().start_ + offset; + state().ctxmarker_ = state().cursor_; +} + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_LEXERSTATE_HH diff --git a/libgringo/gringo/locatable.hh b/libgringo/gringo/locatable.hh new file mode 100644 index 0000000..b9c4a72 --- /dev/null +++ b/libgringo/gringo/locatable.hh @@ -0,0 +1,153 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_LOCATABLE_HH +#define _GRINGO_LOCATABLE_HH + +#include +#include + +namespace Gringo { + +// {{{ declaration of Location + +struct Location { + Location(String beginFilename, unsigned beginLine, unsigned beginColumn, String endFilename, unsigned endLine, unsigned endColumn); + //Location(Location const &loc); + //Location(Location &&loc); + + String beginFilename; + String endFilename; + unsigned beginLine; + unsigned endLine; + unsigned beginColumn; + unsigned endColumn; + + Location operator+(Location const &other) const; + bool operator<(Location const &other) const; +}; + +std::ostream &operator<<(std::ostream &out, Location const &loc); + +// }}} +// {{{ declaration of Locatable + +class Locatable { +public: + virtual Location const &loc() const = 0; + virtual void loc(Location const &loc) = 0; + virtual ~Locatable() { } +}; + +// }}} +// {{{ declaration of LocatableClass + +template +class LocatableClass : public T { +public: + template + LocatableClass(Location const &loc, Args&&... args); + virtual void loc(Location const &loc) final; + virtual Location const &loc() const final; + virtual ~LocatableClass(); +private: + Location loc_; +}; + +// }}} +// {{{ declaration of make_locatable + +template +std::unique_ptr make_locatable(Location const &loc, Args&&... args); + +// }}} + +// {{{ defintion of Location + +inline Location::Location(String beginFilename, unsigned beginLine, unsigned beginColumn, String endFilename, unsigned endLine, unsigned endColumn) + : beginFilename(beginFilename) + , endFilename(endFilename) + , beginLine(beginLine) + , endLine(endLine) + , beginColumn(beginColumn) + , endColumn(endColumn) { } + +inline Location Location::operator+(Location const &other) const { + return Location(beginFilename, beginLine, beginColumn, other.endFilename, other.endLine, other.endColumn); +} + +inline bool Location::operator<(Location const &x) const { + if (beginFilename != x.beginFilename) { return beginFilename < x.beginFilename; } + if (endFilename != x.endFilename) { return endFilename < x.endFilename; } + if (beginLine != x.beginLine) { return beginLine < x.beginLine; } + if (endLine != x.endLine) { return endLine < x.endLine; } + if (beginColumn != x.beginColumn) { return beginColumn < x.beginColumn; } + return endColumn < x.endColumn; +} + +inline std::ostream &operator<<(std::ostream &out, Location const &loc) { + out << loc.beginFilename << ":" << loc.beginLine << ":" << loc.beginColumn; + if (loc.beginFilename != loc.endFilename) { + out << "-" << loc.endFilename << ":" << loc.endLine << ":" << loc.endColumn; + } + else if(loc.beginLine != loc.endLine) { + out << "-" << loc.endLine << ":" << loc.endColumn; + } + else if (loc.beginColumn != loc.endColumn) { + out << "-" << loc.endColumn; + } + return out; +} + +// }}} +// {{{ defintion of LocatableClass + +template +template +LocatableClass::LocatableClass(Location const &loc, Args&&... args) + : T(std::forward(args)...) + , loc_(loc) { } + +template +Location const &LocatableClass::loc() const { + return loc_; +} + +template +void LocatableClass::loc(Location const &loc) { + loc_ = loc; +} + +template +LocatableClass::~LocatableClass() { } + +// }}} +// {{{ defintion of make_locatable + +template +std::unique_ptr make_locatable(Location const &loc, Args&&... args) { + return gringo_make_unique>(loc, std::forward(args)...); +} + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_LOCATABLE_HH diff --git a/libgringo/gringo/logger.hh b/libgringo/gringo/logger.hh new file mode 100644 index 0000000..ba8e401 --- /dev/null +++ b/libgringo/gringo/logger.hh @@ -0,0 +1,127 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_REPORT_HH +#define _GRINGO_REPORT_HH + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace Gringo { + +// {{{1 declaration of GringoError + +class GringoError : public std::runtime_error { +public: + GringoError(char const *msg) : std::runtime_error(msg) { } +}; + +class MessageLimitError : public std::runtime_error { +public: + MessageLimitError(char const *msg) : std::runtime_error(msg) { } +}; + +// {{{1 declaration of Logger + +using Warnings = clingo_warning; +using Errors = clingo_error; + +class Logger { +public: + using Printer = std::function; + Logger(Printer p = nullptr, unsigned limit = 20) + : p_(p) + , limit_(limit) { } + bool check(Errors id); + bool check(Warnings id); + bool hasError() const; + void enable(Warnings id, bool enable); + void print(clingo_warning_t code, char const *msg); + ~Logger(); +private: + Printer p_; + unsigned limit_; + std::bitset disabled_; + bool error_ = false; +}; + +// }}}1 + +// {{{1 definition of Logger + +inline bool Logger::check(Errors) { + if (!limit_ && error_) { throw MessageLimitError("too many messages."); } + if (limit_) { --limit_; } + error_ = true; + return true; +} + +inline bool Logger::check(Warnings id) { + if (!limit_ && error_) { throw MessageLimitError("too many messages."); } + return !disabled_[id] && limit_ && (--limit_, true); +} + +inline bool Logger::hasError() const { + return error_; +} + +inline void Logger::enable(Warnings id, bool enabled) { + disabled_[id] = !enabled; +} + +inline void Logger::print(clingo_warning_t code, char const *msg) { + if (p_) { p_(code, msg); } + else { + fprintf(stderr, "%s\n", msg); + fflush(stderr); + } +} + +inline Logger::~Logger() { } + +// {{{1 definition of Report + +class Report { +public: + Report(Logger &p, clingo_warning_t code) : p_(p), code_(code) { } + ~Report() { p_.print(code_, out.str().c_str()); } + std::ostringstream out; +private: + Logger &p_; + clingo_warning_t code_; +}; + +// }}}1 + +} // namespace GRINGO + +#define GRINGO_REPORT(p, id) \ +if (!(p).check(id)) { } \ +else Gringo::Report(p, id).out + +#endif // _GRINGO_REPORT_HH + diff --git a/libgringo/gringo/lua.hh b/libgringo/gringo/lua.hh new file mode 100644 index 0000000..274f38c --- /dev/null +++ b/libgringo/gringo/lua.hh @@ -0,0 +1,49 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_LUA_HH +#define _GRINGO_LUA_HH + +#include +#include +#include + +struct lua_State; + +namespace Gringo { + +struct LuaImpl; +struct Lua { + Lua(GringoModule &module); + bool exec(Location const &loc, String name); + SymVec call(Location const &loc, String name, SymSpan args, Logger &log); + bool callable(String name); + void main(Control &ctl); + static void initlib(lua_State *L, GringoModule &module); + ~Lua(); + + std::unique_ptr impl; +}; + +} // namespace Gringo + +#endif // _GRINGO_LUA_HH + + diff --git a/libgringo/gringo/output/aggregates.hh b/libgringo/gringo/output/aggregates.hh new file mode 100644 index 0000000..564bfcf --- /dev/null +++ b/libgringo/gringo/output/aggregates.hh @@ -0,0 +1,94 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_AGGREGATES_HH +#define _GRINGO_OUTPUT_AGGREGATES_HH + +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +struct TupleId; +using BodyAggregateElements = UniqueVec, HashFirst, EqualToFirst>; +using HeadFormula = std::vector>; +using HeadAggregateElements = UniqueVec, HashFirst, EqualToFirst>; +using DisjunctiveBounds = IntervalSet; +using Interval = DisjunctiveBounds::Interval; +using ConjunctiveBounds = std::vector>; +using PlainBounds = std::vector>; +using LitValVec = std::vector>; +using LitUintVec = std::vector>; + +struct AggregateAnalyzer { + enum Monotonicity { MONOTONE, ANTIMONOTONE, CONVEX, NONMONOTONE }; + enum WeightType { MIXED, POSITIVE, NEGATIVE }; + enum Truth { True, False, Open }; + using ConjunctiveBounds = std::vector>; + + AggregateAnalyzer(DomainData &data, NAF naf, DisjunctiveBounds const &disjunctiveBounds, AggregateFunction fun, Interval range, BodyAggregateElements const &elems); + void print(std::ostream &out); + LitValVec translateElems(DomainData &data, Translator &x, AggregateFunction fun, BodyAggregateElements const &bdElems, bool incomplete); + + Monotonicity monotonicity; + WeightType weightType; + Truth truth; + ConjunctiveBounds bounds; + Interval range; +}; + +inline Symbol getNeutral(AggregateFunction fun) { + switch (fun) { + case AggregateFunction::COUNT: + case AggregateFunction::SUMP: + case AggregateFunction::SUM: { return Symbol::createNum(0); } + case AggregateFunction::MIN: { return Symbol::createSup(); } + case AggregateFunction::MAX: { return Symbol::createInf(); } + } + assert(false); + return {}; +} + +LiteralId getEqualClause(DomainData &data, Translator &x, std::pair clause, bool conjunctive, bool equivalence); +LiteralId getEqualFormula(DomainData &data, Translator &x, Formula const &formula, bool conjunctive, bool equivalence); +LiteralId getEqualAggregate(DomainData &data, Translator &x, AggregateFunction fun, NAF naf, DisjunctiveBounds const &bounds, Interval const &range, BodyAggregateElements const &bdElems, bool recursive); + +class MinMaxTranslator { +public: + LiteralId translate(DomainData &data, Translator &x, AggregateAnalyzer &res, bool isMin, LitValVec &&elems, bool incomplete); +}; + +struct SumTranslator { + SumTranslator() { } + void addLiteral(DomainData &data, LiteralId const &lit, Potassco::Weight_t weight, bool recursive); + void translate(DomainData &data, Translator &x, LiteralId const &head, Potassco::Weight_t bound, LitUintVec const &litsPosRec, LitUintVec const &litsNegRec, LitUintVec const &litsPosStrat, LitUintVec const &litsNegStrat); + LiteralId translate(DomainData &data, Translator &x, ConjunctiveBounds &bounds, bool convex, bool invert); + + LitUintVec litsPosRec; + LitUintVec litsNegRec; + LitUintVec litsPosStrat; + LitUintVec litsNegStrat; +}; + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_AGGREGATES_HH diff --git a/libgringo/gringo/output/backends.hh b/libgringo/gringo/output/backends.hh new file mode 100644 index 0000000..e6e7e78 --- /dev/null +++ b/libgringo/gringo/output/backends.hh @@ -0,0 +1,46 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_BACKENDS_HH +#define _GRINGO_OUTPUT_BACKENDS_HH + +#include +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +class SmodelsFormatBackend : public Potassco::SmodelsConvert { +public: + SmodelsFormatBackend(std::ostream& os) + : Potassco::SmodelsConvert(out_, true) + , out_(os, true, 0) { } +private: + Potassco::SmodelsOutput out_; +}; + +using IntermediateFormatBackend = Potassco::AspifOutput; + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_BACKENDS_HH + diff --git a/libgringo/gringo/output/literal.hh b/libgringo/gringo/output/literal.hh new file mode 100644 index 0000000..5144bcb --- /dev/null +++ b/libgringo/gringo/output/literal.hh @@ -0,0 +1,204 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_LITERAL_HH +#define _GRINGO_OUTPUT_LITERAL_HH + +#include +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 declaration of PrintPlain + +struct PrintPlain { + void printTerm(Potassco::Id_t x); + void printElem(Potassco::Id_t x); + DomainData &domain; + std::ostream &stream; +}; + +template +PrintPlain &operator<<(PrintPlain &out, T const &x) { + out.stream << x; + return out; +} + +// {{{1 declaration of LiteralId + +enum class AtomType : uint32_t { + BodyAggregate, + AssignmentAggregate, + HeadAggregate, + Disjunction, + Conjunction, + LinearConstraint, + Disjoint, + Theory, + Predicate, + Aux + // TODO: consider a hidden predicate domain for internal purposes +}; + +class LiteralId { +public: + explicit LiteralId(uint64_t repr) + : repr_(repr) { } + LiteralId() + : repr_(std::numeric_limits::max()) { } + LiteralId(NAF sign, AtomType type, Potassco::Id_t offset, Potassco::Id_t domain) + : data_{static_cast(sign), static_cast(type), domain, offset} { } + Potassco::Id_t offset() const { return data_.offset; } + Potassco::Id_t domain() const { return data_.domain; } + AtomType type() const { return static_cast(data_.type); } + NAF sign() const { return static_cast(data_.sign); } + bool invertible() const { return sign() != NAF::POS; } + LiteralId negate() const { return LiteralId(inv(sign()), type(), offset(), domain()); } + bool operator==(LiteralId const &other) const { return repr_ == other.repr_; } + bool operator<(LiteralId const &other) const { return repr_ < other.repr_; } + uint64_t repr() const { return repr_; } + bool valid() const { return repr_ != std::numeric_limits::max(); } + LiteralId withSign(NAF naf) const { return {naf, type(), offset(), domain()}; } + LiteralId withOffset(Id_t offset) const { return {sign(), type(), offset, domain()}; } + operator bool() const { return valid(); } + +private: + struct Data { + uint64_t sign : 2; + uint64_t type : 6; + uint64_t domain : 24; + uint64_t offset : 32; + }; + union { + Data data_; + uint64_t repr_; + }; +}; +using LitVec = std::vector; + +// {{{1 declaration of Literal + +class Mapping { +private: + using Value = std::pair, Id_t>; // (range, offset) + using Map = std::vector; +public: + void add(Id_t oldOffset, Id_t newOffset) { + if (map_.empty() || map_.back().first.second < oldOffset) { + map_.emplace_back(std::make_pair(oldOffset, oldOffset+1), newOffset); + } + else { + assert(map_.back().first.second == oldOffset); + ++map_.back().first.second; + } + } + Id_t get(Id_t oldOffset) { + auto it = std::upper_bound(map_.begin(), map_.end(), oldOffset, [](Id_t offset, Value const &val) { return offset < val.first.second; }); + return (it == map_.end() || oldOffset < it->first.first) ? InvalidId : it->second + (oldOffset - it->first.first); + } + Id_t bound(Id_t oldOffset) { + auto it = std::upper_bound(map_.begin(), map_.end(), oldOffset, [](Id_t offset, Value const &val) { return offset < val.first.second; }); + if (it != map_.end() && oldOffset >= it->first.first) { + return it->second + (oldOffset - it->first.first); + } + if (it == map_.begin() && (it == map_.end() || oldOffset < it->first.first)) { + return 0; + } + return (it-1)->second + ((it-1)->first.second - (it-1)->first.first); + } +private: + Map map_; +}; +using Mappings = std::vector; + +class Literal { +public: + // Shall return true if the literal was defined in a previous step. + // Modularity guarantees that there is no cycle involing atoms from + // the current step through such a literal. + virtual bool isAtomFromPreviousStep() const; + // Shall return true for all literals that can be used in the head of a rule. + virtual bool isHeadAtom() const; + // Translates the literal into a literal suitable to be output by a Backend. + virtual LiteralId translate(Translator &x) = 0; + // Compact representation for the literal. + // A literal can be restored from this representation using the DomainData class. + virtual LiteralId toId() const = 0; + // Prints the literal in plain text format. + virtual void printPlain(PrintPlain out) const = 0; + // Shall return if the literal cannot be output at this point of time. + // Such literals are stored in a list and output once their definition is complete. + virtual bool isIncomplete() const; + // Associates an incomplete literals with a delayd literal. + // The return flag indicates that a fresh delayed literal has been added. + // The literal might copy its sign into the delayed literal. + // In this case the sign is stripped from the original literal. + virtual std::pair delayedLit(); + virtual bool isBound(Symbol &value, bool negate) const; + virtual void updateBound(std::vector &bounds, bool negate) const; + virtual bool needsSemicolon() const; + virtual bool isPositive() const; + // Maps true and false literals to a unique literal and remaps the offsets of predicate literals. + virtual LiteralId simplify(Mappings &mappings, AssignmentLookup lookup) const; + virtual bool isTrue(IsTrueLookup) const; + virtual Lit_t uid() const = 0; + virtual ~Literal() { } +}; + +// returns true if all literals in lits are true +bool isTrueClause(DomainData &data, LitVec &lits, IsTrueLookup lookup); + +// {{{1 declaration of TupleId + +struct TupleId { + Id_t offset; + Id_t size; +}; +inline bool operator==(TupleId a, TupleId b) { + return a.offset == b.offset && a.size == b.size; +} +inline bool operator<(TupleId a, TupleId b) { + if (a.offset != b.offset) { return a.offset < b.offset; } + return a.size < b.size; +} + +// }}}1 + +} } // namespace Output Gringo + +namespace std { + +template <> +struct hash : private std::hash { + size_t operator()(Gringo::Output::LiteralId const &lit) const { + return std::hash::operator()(lit.repr()); + } +}; + +template <> +struct hash { + size_t operator()(Gringo::Output::TupleId t) const { return Gringo::get_value_hash(t.offset, t.size); } +}; + +} // namespace std + +#endif // _GRINGO_OUTPUT_LITERAL_HH + diff --git a/libgringo/gringo/output/literals.hh b/libgringo/gringo/output/literals.hh new file mode 100644 index 0000000..2fc1100 --- /dev/null +++ b/libgringo/gringo/output/literals.hh @@ -0,0 +1,1328 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_LITERALS_HH +#define _GRINGO_OUTPUT_LITERALS_HH + +#include +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 declaration of PredicateAtom + +struct PredicateAtom { +public: + // {{{2 Atom interface + + // Constructs a valid atom without uid and generation. + PredicateAtom(Symbol value) + : value_(value) + , uid_(0) + , fact_(false) + , generation_(0) + , external_(false) + , delayed_(false) { } + + // Functions that have to be implemented by all atoms. + + // Atoms can be marked as facts. + // Atoms that are not monotone (like some aggregate atoms) are not considered + // monotone in the recursive case because their fact status can still change + // during grounding + bool fact() const { return fact_; } + // Defined and undefined atoms are distinguished. + // Only recursion through negative literals can lead to undefined atoms. + // Such atoms must not be imported in indices. + // They can be defined later though, in which case they have to be imported. + // Example: a :- not b. b :- not a. + bool defined() const { + return generation_ > 0; + } + // The generation of the atom. This value is used by indices to determine + // what is new and old. + Id_t generation() const { + assert(defined()); + return generation_ - 1; + } + void setGeneration(unsigned x) { + generation_ = x + 1; + } + void markDelayed() { + delayed_ = 1; + } + bool delayed() const { + return delayed_; + } + // Returns the value associated with the atom. + operator Symbol const &() const { + return value_; + } + // }}}2 + + // The functions below are not necessary for domain elements. + // This are additional functions in symbolic atoms. + + void setFact(bool x) { + fact_ = x; + } + // These functions are used to handle external atoms. + // The sole reason for this function is to workaround a problem with libclasp, + // which might find equivalences between external and non-external atoms. + // In such a case it is not possible to determine which atom is the external + // one using the clasp API. Note that the external status is never unset; + // only the solver knows about this. + bool isExternal() const { + return external_; + } + void setExternal(bool x) { + external_ = x; + } + // The uid of an atom is used in various outputs. + bool hasUid() const { + return uid_ > 0; + } + void setUid(unsigned x) { + assert(!hasUid()); + uid_ = x + 1; + } + void resetUid(unsigned x) { + assert(hasUid()); + uid_ = x + 1; + } + Id_t uid() const { + assert(hasUid()); + return uid_ - 1; + } + void unmarkDelayed() { + delayed_ = 0; + } +private: + Symbol value_; + uint32_t uid_ : 31; + uint32_t fact_ : 1; + uint32_t generation_ : 30; + uint32_t external_ : 1; + uint32_t delayed_ : 1; +}; + +// {{{1 declaration of TheoryAtom + +using TheoryElementVec = std::vector; + +class TheoryAtom { +public: + TheoryAtom(TheoryAtom &&) = default; + TheoryAtom(TheoryAtom const &) = default; + TheoryAtom &operator=(TheoryAtom &&) = default; + TheoryAtom &operator=(TheoryAtom const &) = default; + ~TheoryAtom() noexcept = default; + // {{{2 Atom interface + TheoryAtom(Symbol value) + : value_(value) + , enqueued_(false) + , delayed_(false) + , recursive_(true) + , initialized_(false) + , translated_(false) + , simplified_(false) { } + bool fact() const { return false; } + bool defined() const { return generation_ > 0; } + Id_t generation() const { assert(defined()); return generation_ - 1; } + void setGeneration(unsigned x) { generation_ = x + 1; } + void markDelayed() { delayed_ = 1; } + bool delayed() const { return delayed_; } + operator Symbol const &() const { return value_; } + // }}}2 + bool initialized() { return initialized_; } + void init(TheoryAtomType type, Id_t name, Id_t op, Id_t guard) { + initialized_ = true; + type_ = type; + name_ = name; + op_ = op; + guard_ = guard; + } + void setRecursive(bool recursive) { recursive_ = recursive; } + bool recursive() const { return recursive_; } + TheoryAtomType type() const { return type_; } + Id_t name() const { return name_; } + Id_t op() const { return op_; } + Id_t guard() const { return guard_; } + bool hasGuard() const { return guard_ != InvalidId; } + TheoryElementVec const &elems() const { return elems_; } + void setEnqueued(bool enqueued) { enqueued_ = enqueued; } + bool enqueued() const { return enqueued_; } + bool translated() const { return translated_; } + void setTranslated() { translated_ = true; } + LiteralId lit() const { return lit_; } + void setLit(LiteralId lit) { lit_ = lit; } + void accumulate(Id_t elemId) { elems_.emplace_back(elemId); } + void simplify(TheoryData const &data); +private: + Symbol value_; + LiteralId lit_; + TheoryElementVec elems_; + Id_t name_ = InvalidId; + Id_t op_ = InvalidId; + Id_t guard_ = InvalidId; + Id_t generation_ = 0; + TheoryAtomType type_; + uint8_t enqueued_ : 1; + uint8_t delayed_ : 1; + uint8_t recursive_ : 1; + uint8_t initialized_ : 1; + uint8_t translated_ : 1; + uint8_t simplified_ : 1; +}; + +// {{{1 declaration of functions to work with aggregates + +int clamp(int64_t x); +bool neutral(SymVec const &tuple, AggregateFunction fun, Location const &loc, Logger &log); +int toInt(IntervalSet::LBound const &x); +int toInt(IntervalSet::RBound const &x); +Symbol getWeight(AggregateFunction fun, SymVec const &x); +Symbol getWeight(AggregateFunction fun, IteratorRange rng); + +// {{{1 declaration of AggregateAtomRange + +union ValInt { + ValInt() { } + ValInt(ValInt const &b) : rep(b.rep) { } + Symbol val; + int64_t num; + uint64_t rep; +}; + +struct AggregateAtomRange { + void init(AggregateFunction fun, DisjunctiveBounds &&bounds); + void accumulate(SymVec const &tuple, bool fact, bool remove); + Interval range() const; + PlainBounds plainBounds(); + bool satisfiable() const { return bounds.intersects(range()); } + bool fact() const { return bounds.contains(range()); } + int64_t &intMin() { return min.num; } + int64_t &intMax() { return max.num; } + Symbol &valMin() { return min.val; } + Symbol &valMax() { return max.val; } + int64_t const &intMin() const { return min.num; } + int64_t const &intMax() const { return max.num; } + Symbol const &valMin() const { return min.val; } + Symbol const &valMax() const { return max.val; } + + AggregateFunction fun = AggregateFunction::COUNT; + DisjunctiveBounds bounds; + ValInt min; + ValInt max; +}; + +// {{{1 declaration of BodyAggregateAtom + +struct BodyAggregateElements_ { +private: + class TupleOffset; + class ClauseOffset; + +public: + void accumulate(DomainData &data, TupleId tuple, LitVec &lits, bool &inserted, bool &fact, bool &remove); + // NOTE: expensive (linear) + BodyAggregateElements elems() const; + +private: + std::pair insertTuple(uint64_t to); + template + void visitClause(F f); + +private: + HashSet tuples_; + std::vector conditions_; +}; + +class BodyAggregateAtom { +public: + BodyAggregateAtom(BodyAggregateAtom &&) = default; + BodyAggregateAtom(BodyAggregateAtom const &) = delete; + BodyAggregateAtom &operator=(BodyAggregateAtom &&) = default; + BodyAggregateAtom &operator=(BodyAggregateAtom const &) = delete; + ~BodyAggregateAtom() noexcept; + // {{{2 Atom interface + BodyAggregateAtom(Symbol value) : data_(gringo_make_unique(value)) { } + bool fact() const { return data_->fact && (data_->monotone || !data_->recursive); } + bool defined() const { return data_->generation > 0; } + unsigned generation() const { assert(defined()); return data_->generation - 1; } + void setGeneration(unsigned x) { data_->generation = x + 1; } + void markDelayed() { data_->delayed = 1; } + bool delayed() const { return data_->delayed; } + operator Symbol const &() const { return data_->value; } + // }}}2 + void setRecursive(bool recursive) { data_->recursive = recursive; } + void init(AggregateFunction fun, DisjunctiveBounds &&bounds, bool monotone); + void accumulate(DomainData &data, Location const &loc, SymVec const &tuple, LitVec &cond, Logger &log); + Interval range() const { return data_->range.range(); } + AggregateFunction fun() const { return data_->range.fun; } + DisjunctiveBounds const &bounds() const { return data_->range.bounds; } + PlainBounds plainBounds() { return data_->range.plainBounds(); } + bool recursive() const { return data_->recursive; } + BodyAggregateElements elems() const; + LiteralId lit() const { return data_->lit; } + void setLit(LiteralId lit) { data_->lit = lit; } + bool satisfiable() const { return data_->range.satisfiable(); } + void setEnqueued(bool enqueued) { data_->enqueued = enqueued; } + bool enqueued() const { return data_->enqueued; } + bool initialized() const { return data_->initialized; } + bool translated() const { return data_->translated; } + void setTranslated() { data_->translated = true; } + +private: + struct Data { + Data(Symbol value) + : value(value) + , monotone(false) + , recursive(true) + , fact(false) + , enqueued(false) + , initialized(false) + , delayed(false) + , translated(false) { } + + Symbol value; + BodyAggregateElements_ elems; + AggregateAtomRange range; + // This is the literal resulting from the translation of the aggregate. + // Note that this literal includes the sign of the underlying literal. + // This is possible with the current implemention, + // because each aggregate atom in a domain corresponds one-to-one to a literal. + LiteralId lit; + // The generation is 0 if undefined > 1 if defined. + Id_t generation = 0; + // Only monotone aggregates can be facts in the recursive case. + uint8_t monotone : 1; + uint8_t recursive : 1; + uint8_t fact : 1; + uint8_t enqueued : 1; + uint8_t initialized : 1; + uint8_t delayed : 1; + uint8_t translated : 1; + }; + std::unique_ptr data_; +}; + +// {{{1 declaration of AssignmentAggregateAtom + +class AssignmentAggregateData { +public: + using Values = std::vector; + AssignmentAggregateData(Symbol value, AggregateFunction fun) + : value_(value) + , fun_(fun) { values_.emplace_back(getNeutral(fun)); } + AssignmentAggregateData(AssignmentAggregateData &&) = default; + AssignmentAggregateData(AssignmentAggregateData const &) = default; + AssignmentAggregateData &operator=(AssignmentAggregateData &&) = default; + AssignmentAggregateData &operator=(AssignmentAggregateData const &) = default; + ~AssignmentAggregateData() noexcept = default; + operator Symbol const &() const { return value_; } + void accumulate(DomainData &data, Location const &loc, SymVec const &tuple, LitVec &cond, Logger &log); + BodyAggregateElements const &elems() const { return elems_; } + void setEnqueued(bool enqueued) { enqueued_ = enqueued; } + bool enqueued() const { return enqueued_; } + AggregateFunction fun() const { return fun_; } + // Note: expensive!!! + Values values() const; + Interval range() const; + +private: + Symbol value_; + BodyAggregateElements elems_; + Values values_; + AggregateFunction fun_; + bool enqueued_ = false; +}; + +class AssignmentAggregateAtom { +public: + AssignmentAggregateAtom(AssignmentAggregateAtom &&) = default; + AssignmentAggregateAtom(AssignmentAggregateAtom const &) = default; + AssignmentAggregateAtom &operator=(AssignmentAggregateAtom &&) = default; + AssignmentAggregateAtom &operator=(AssignmentAggregateAtom const &) = default; + ~AssignmentAggregateAtom() noexcept = default; + // {{{2 Atom interface + AssignmentAggregateAtom(Symbol value) + : value_(value) + , fact_(false) + , delayed_(false) + , translated_(false) + { } + bool fact() const { return fact_ && !recursive_; } + bool defined() const { return generation_ > 0; } + unsigned generation() const { assert(defined()); return generation_ - 1; } + void setGeneration(unsigned x) { generation_ = x + 1; } + void markDelayed() { delayed_ = 1; } + bool delayed() const { return delayed_; } + operator Symbol const &() const { return value_; } + // }}}2 + void setFact(bool fact) { fact_ = fact; } + void setRecursive(bool recursive) { recursive_ = recursive; } + void init(AggregateFunction fun, DisjunctiveBounds &&bounds, bool monotone); + bool recursive() const { return recursive_; } + LiteralId lit() const { return lit_; } + void setLit(LiteralId lit) { lit_ = lit; } + void setData(Id_t offset) { data_ = offset; } + Id_t data() const { return data_; } + bool translated() const { return translated_; } + void setTranslated() { translated_ = true; } + +private: + Symbol value_; + Symbol bound_; + LiteralId lit_; + // The generation is 0 if undefined > 1 if defined. + Id_t generation_ = 0; + Id_t data_ = InvalidId; + uint8_t recursive_ : 1; + uint8_t fact_ : 1; + uint8_t delayed_ : 1; + uint8_t translated_ : 1; +}; + +// {{{1 declaration of ConjunctionAtom + +class ConjunctionElement { +public: + ConjunctionElement(Symbol value) + : value_(value) { } + ConjunctionElement(ConjunctionElement &&) = default; + ConjunctionElement(ConjunctionElement const &) = default; + ConjunctionElement &operator=(ConjunctionElement &&) = default; + ConjunctionElement &operator=(ConjunctionElement const &) = default; + ~ConjunctionElement() noexcept = default; + + operator Symbol const & () const { return value_; } + bool needsSemicolon() const; + bool isSimple(DomainData &data) const; + void print(PrintPlain out) const; + void accumulateCond(DomainData &data, LitVec &cond, Id_t &blocked, Id_t &fact); + void accumulateHead(DomainData &data, LitVec &cond, Id_t &blocked, Id_t &fact); + Formula const &heads() const { return heads_; } + Formula const &bodies() const { return bodies_; } + +private: + Symbol value_; + Formula heads_; + Formula bodies_; +}; + +inline PrintPlain &operator<<(PrintPlain &out, ConjunctionElement const &x) { + x.print(out); + return out; +} + +class ConjunctionAtom { +public: + using Elements = UniqueVec, std::equal_to>; + ConjunctionAtom(ConjunctionAtom &&) = default; + ConjunctionAtom(ConjunctionAtom const &) = default; + ConjunctionAtom &operator=(ConjunctionAtom &&) = default; + ConjunctionAtom &operator=(ConjunctionAtom const &) = default; + ~ConjunctionAtom() noexcept = default; + // {{{2 Atom interface + ConjunctionAtom(Symbol value) + : value_(value) + , condRecursive_(true) + , headRecursive_(true) + , delayed_(false) + , enqueued_(false) + , translated_(false) + { } + bool fact() const { return fact_ == 0 && !condRecursive_; } + bool defined() const { return generation_ > 0; } + unsigned generation() const { assert(defined()); return generation_ - 1; } + void setGeneration(unsigned x) { generation_ = x + 1; } + void markDelayed() { delayed_ = 1; } + bool delayed() const { return delayed_; } + operator Symbol const &() const { return value_; } + // }}}2 + LiteralId lit() const { return lit_; } + void setLit(LiteralId lit) { lit_ = lit; } + bool blocked() const { return blocked_ > 0; } + Elements const &elems() const { return elems_; } + void setEnqueued(bool enqueued) { enqueued_ = enqueued; } + bool enqueued() const { return enqueued_; } + void accumulateCond(DomainData &data, Symbol elem, LitVec &cond); + void accumulateHead(DomainData &data, Symbol elem, LitVec &cond); + void init(bool headRecursive, bool condRecursive); + bool recursive() const; + bool nonmonotone() const; + bool translated() const { return translated_; } + void setTranslated() { translated_ = true; } + +private: + Elements elems_; + Symbol value_; + LiteralId lit_; + // The generation is 0 if undefined > 1 if defined. + Id_t generation_ = 0; + Id_t blocked_ = 0; + Id_t fact_ = 0; + uint8_t condRecursive_ : 1; + uint8_t headRecursive_ : 1; + uint8_t delayed_ : 1; + uint8_t enqueued_ : 1; + uint8_t translated_ : 1; +}; + +// {{{1 declaration of DisjointAtom + +class DisjointElement { +public: + DisjointElement(CSPGroundAdd &&value, int fixed, ClauseId cond); + DisjointElement(DisjointElement &&) noexcept = default; + DisjointElement &operator=(DisjointElement &&) noexcept = default; + ~DisjointElement() noexcept = default; + + void printPlain(PrintPlain out) const; + CSPGroundAdd const &value() const { return value_; } + ClauseId const &cond() const { return cond_; } + int fixed() const { return fixed_; } +private: + CSPGroundAdd value_; + ClauseId cond_; + int fixed_; +}; + +using DisjointElemVec = std::vector; +using DisjointElemSet = UniqueVec, HashFirst, EqualToFirst>; + +class DisjointAtom { +public: + DisjointAtom(DisjointAtom &&) = default; + DisjointAtom(DisjointAtom const &) = default; + DisjointAtom &operator=(DisjointAtom &&) noexcept = default; + DisjointAtom &operator=(DisjointAtom const &) = default; + ~DisjointAtom() noexcept = default; + // {{{2 Atom interface + DisjointAtom(Symbol value) + : value_(value) + , generation_(0) + , delayed_(false) + , enqueued_(false) + , recursive_(true) + , translated_(false) { } + bool fact() const { return !recursive_ && elems_.size() <= 1; } + bool defined() const { return generation_ > 0; } + Id_t generation() const { assert(defined()); return generation_ - 1; } + void setGeneration(unsigned x) { generation_ = x + 1; } + void markDelayed() { delayed_ = 1; } + bool delayed() const { return delayed_; } + operator Symbol const &() const { return value_; } + // }}}2 + void init(bool recursive) { recursive_ = recursive; } + bool recursive() const { return recursive_; } + void setEnqueued(bool enqueued) { enqueued_ = enqueued; } + bool enqueued() const { return enqueued_; } + void accumulate(DomainData &data, SymVec const &tuple, CSPGroundAdd &&value, int fixed, LitVec const &lits); + bool translated() const { return translated_; } + void setTranslated() { translated_ = true; } + LiteralId lit() const { return lit_; } + void setLit(LiteralId lit) { lit_ = lit; } + DisjointElemSet const &elems() const { return elems_; } + bool translate(DomainData &data, Translator &x, Logger &log); + +private: + Symbol value_; + DisjointElemSet elems_; + LiteralId lit_; + Id_t generation_ = 0; + uint8_t delayed_ : 1; + uint8_t enqueued_ : 1; + uint8_t recursive_ : 1; + uint8_t translated_ : 1; +}; + +// {{{1 declaration of DisjunctionAtom + +class DisjunctionElement { +public: + DisjunctionElement(Symbol value) + : value_(value) { } + DisjunctionElement(DisjunctionElement &&) = default; + DisjunctionElement(DisjunctionElement const &) = default; + DisjunctionElement &operator=(DisjunctionElement &&) = default; + DisjunctionElement &operator=(DisjunctionElement const &) = default; + ~DisjunctionElement() noexcept = default; + + operator Symbol const & () const { return value_; } + void print(PrintPlain out) const; + void accumulateCond(DomainData &data, LitVec &cond, Id_t &fact); + void accumulateHead(DomainData &data, LitVec &cond, Id_t &fact); + bool bodyIsTrue() const; + bool bodyIsFalse() const; + bool headIsTrue() const; + bool headIsFalse() const; + Formula const &heads() const { return heads_; } + Formula const &bodies() const { return bodies_; } + +private: + Symbol value_; + Formula heads_; + Formula bodies_; +}; + +inline PrintPlain &operator<<(PrintPlain &out, DisjunctionElement const &x) { + x.print(out); + return out; +} + +class DisjunctionAtom { +public: + using Elements = UniqueVec, std::equal_to>; + DisjunctionAtom(DisjunctionAtom &&) = default; + DisjunctionAtom(DisjunctionAtom const &) = default; + DisjunctionAtom &operator=(DisjunctionAtom &&) = default; + DisjunctionAtom &operator=(DisjunctionAtom const &) = default; + ~DisjunctionAtom() noexcept = default; + // {{{2 Atom interface + DisjunctionAtom(Symbol value) + : value_(value) + , bodyFact_(false) + , recursive_(true) + , delayed_(false) + , enqueued_(false) + , translated_(false) + { } + // This function could be used to indicate that the head literal. + // occurs in a rule with an empty body. + bool fact() const { return bodyFact_; } + // This function indicates that the disjunction contains a fact + // and, hence, does not derive anything. + bool defined() const { return generation_ > 0; } + unsigned generation() const { assert(defined()); return generation_ - 1; } + void setGeneration(unsigned x) { generation_ = x + 1; } + void markDelayed() { delayed_ = 1; } + bool delayed() const { return delayed_; } + operator Symbol const &() const { return value_; } + // }}}2 + void setFact(bool fact) { bodyFact_ = fact; } + bool headFact() const { return headFact_ > 0 && !recursive_; } + LiteralId lit() const { return lit_; } + void setLit(LiteralId lit) { lit_ = lit; } + Elements const &elems() const { return elems_; } + void setEnqueued(bool enqueued) { enqueued_ = enqueued; } + bool enqueued() const { return enqueued_; } + void accumulateCond(DomainData &data, Symbol elem, LitVec &cond); + void accumulateHead(DomainData &data, Symbol elem, LitVec &cond); + void init(bool recursive) { recursive_ = recursive; } + bool recursive() const { return recursive_; } + void simplify(bool &headFact); + bool translated() const { return translated_; } + void setTranslated() { translated_ = true; } + +private: + Elements elems_; + Symbol value_; + LiteralId lit_; + // The generation is 0 if undefined > 1 if defined. + Id_t generation_ = 0; + Id_t headFact_ = 0; + uint8_t bodyFact_ : 1; + uint8_t recursive_ : 1; + uint8_t delayed_ : 1; + uint8_t enqueued_ : 1; + uint8_t translated_ : 1; +}; + +// {{{1 declaration of HeadAggregateAtom + +class HeadAggregateAtom { +public: + HeadAggregateAtom(HeadAggregateAtom &&) = default; + HeadAggregateAtom(HeadAggregateAtom const &) = default; + HeadAggregateAtom &operator=(HeadAggregateAtom &&) = default; + HeadAggregateAtom &operator=(HeadAggregateAtom const &) = default; + ~HeadAggregateAtom() noexcept = default; + // {{{2 Atom interface + HeadAggregateAtom(Symbol value) + : value_(value) + , recursive_(true) + , fact_(false) + , enqueued_(false) + , initialized_(false) + , delayed_(false) + , translated_(false) { } + // This function could be used to indicate that the head literal. + // occurs in a rule with an empty body. + bool fact() const { return false; } + bool defined() const { return generation_ > 0; } + unsigned generation() const { assert(defined()); return generation_ - 1; } + void setGeneration(unsigned x) { generation_ = x + 1; } + void markDelayed() { delayed_ = 1; } + bool delayed() const { return delayed_; } + operator Symbol const &() const { return value_; } + // }}}2 + // This function indicates that the bounds of the aggregate are tivially satisfied. + // (There is not really a need for it at the moment because, unlike with disjunctions, + // no simplifications can be performed with this information.) + bool headFact() const { return fact_ && !recursive_; } + void setRecursive(bool recursive) { recursive_ = recursive; } + void init(AggregateFunction fun, DisjunctiveBounds &&bounds); + void accumulate(DomainData &data, Location const &loc, SymVec const &tuple, LiteralId head, LitVec &cond, Logger &log); + Interval range() const { return range_.range(); } + AggregateFunction fun() const { return range_.fun; } + DisjunctiveBounds const &bounds() const { return range_.bounds; } + PlainBounds plainBounds() { return range_.plainBounds(); } + bool recursive() const { return recursive_; } + HeadAggregateElements const &elems() const { return elems_; } + bool satisfiable() const { return range_.satisfiable(); } + void setEnqueued(bool enqueued) { enqueued_ = enqueued; } + bool enqueued() const { return enqueued_; } + bool initialized() const { return initialized_; } + bool translated() const { return translated_; } + void setTranslated() { translated_ = true; } + LiteralId lit() const { return lit_; } + void setLit(LiteralId lit) { lit_ = lit; } +private: + Symbol value_; + LiteralId lit_; + HeadAggregateElements elems_; + AggregateAtomRange range_; + Id_t generation_ = 0; + uint8_t recursive_ : 1; + uint8_t fact_ : 1; + uint8_t enqueued_ : 1; + uint8_t initialized_ : 1; + uint8_t delayed_ : 1; + uint8_t translated_ : 1; +}; + +// }}}1 + +// {{{1 declaration of PredicateDomain + +class PredicateDomain : public AbstractDomain { +public: + explicit PredicateDomain(Sig sig) + : sig_(sig) { } + + using AbstractDomain::define; + // Defines (adds) an atom setting its generation and fact status. + // Returns a tuple indicating its postion, wheather it was inserted, and wheather it was a fact before. + std::tuple define(Symbol x, bool fact) { + auto ret = define(x); + bool wasfact = !ret.second && ret.first->fact(); + if (fact) { ret.first->setFact(true); } + return std::forward_as_tuple(ret.first, ret.second, wasfact); + } + + // This offset divides elements added at the current and previous incremental steps. + // It is used to only output newly inserted atoms, for projection, and classical negation. + SizeType incOffset() const { + return incOffset_; + } + + void incNext() { + // It is necessary to hide undefined literals because they should not interfere + // with future definitions of the same atom. + // In fact, they could be completely removed from the domain. + // This cannot be done here but the cleanup function of the output, + // will remove such atoms. + for (auto it = begin() + incOffset(), ie = end(); it != ie; ++it) { + if (!it->defined()) { hide(it); } + } + incOffset_ = size(); + } + + // This offset keeps track of atoms already added to the output table. + // TODO: maybe this can be merged with incNext. + SizeType showOffset() const { + return showOffset_; + } + + void showNext() { + showOffset_ = size(); + } + + void clear() { + AbstractDomain::clear(); + incOffset_ = 0; + showOffset_ = 0; + } + + Sig const &sig() const { + return sig_; + } + + operator Sig const &() const { + return sig_; + } + + std::pair cleanup(AssignmentLookup assignment, Mapping &map) { + Id_t facts = 0; + Id_t deleted = 0; + Id_t oldOffset = 0; + Id_t newOffset = 0; + reset(); + //std::cerr << "cleaning " << *sig_ << std::endl; + atoms_.erase([&](PredicateAtom &atom) { + atom.setGeneration(0); + atom.unmarkDelayed(); + if (!atom.defined()) { + ++deleted; + ++oldOffset; + return true; + } + if (atom.hasUid()) { + auto value = assignment(atom.uid()); + if (!value.first) { + switch (value.second) { + case Potassco::Value_t::True: { + // NOTE: externals cannot become facts here + // because they might get new definitions while grounding + // because there is no distinction between true and weak true + // these definitions might be skipped if a weak true external + // is made a fact here + if (!atom.fact()) { ++facts; } + atom.setFact(true); + break; + } + case Potassco::Value_t::False: { + ++deleted; + ++oldOffset; + return true; + } + default: { break; } + } + } + } + //std::cerr << " mapping " << static_cast(atom) << " from " << oldOffset << " to " << newOffset << std::endl; + map.add(oldOffset, newOffset); + ++oldOffset; + ++newOffset; + return false; + }); + /* + std::cerr << "remaining atoms: "; + for (auto &atom : atoms_) { + std::cerr << " " << static_cast(atom) << "=" << (atoms_.find(static_cast(atom)) != atoms_.end()) << "/" << atom.generation() << "/" << atom.defined() << "/" << atom.delayed(); + } + std::cerr << std::endl; + */ + delayed_.clear(); + generation_ = 1; + initOffset_ = atoms_.size(); + initDelayedOffset_ = 0; + incOffset_ = map.bound(incOffset_); + showOffset_ = map.bound(showOffset_); + return {facts, deleted}; + } +private: + Sig sig_; + SizeType incOffset_ = 0; + SizeType showOffset_ = 0; +}; +using UPredDom = std::unique_ptr; + +struct UPredDomHash : std::hash { + using std::hash::operator(); + size_t operator()(UPredDom const &dom) const { + return std::hash::operator()(*dom); + } +}; + +struct UPredDomEqualTo : private std::equal_to { + bool operator()(UPredDom const &a, Sig const &b) const { + return std::equal_to::operator()(*a, b); + } + bool operator()(UPredDom const &a, UPredDom const &b) const { + return std::equal_to::operator()(*a, *b); + } +}; + +using PredDomMap = UniqueVec, UPredDomHash, UPredDomEqualTo>; + +// {{{1 declaration of TheoryDomain + +class TheoryDomain : public AbstractDomain { +public: +private: +}; + +// {{{1 declaration of BodyAggregateDomain + +class BodyAggregateDomain : public AbstractDomain { +public: +private: +}; + +// {{{1 declaration of AssignmentAggregateDomain + +class AssignmentAggregateDomain : public AbstractDomain { +private: + using Data = UniqueVec, EqualToKey>; +public: + Id_t data(Symbol value, AggregateFunction fun) { + auto ret = data_.findPush(value, value, fun); + return data_.offset(ret.first); + } + AssignmentAggregateData &data(Id_t offset) { return data_[offset]; } + AssignmentAggregateData const &data(Id_t offset) const { return data_[offset]; } +private: + Data data_; +}; + +// {{{1 declaration of ConjunctionDomain + +class ConjunctionDomain : public AbstractDomain { +public: +private: +}; +// {{{1 declaration of DisjointDomain + +class DisjointDomain : public AbstractDomain { +public: +private: +}; +// {{{1 declaration of DisjunctionDomain + +class DisjunctionDomain : public AbstractDomain { +public: +private: +}; +// {{{1 declaration of HeadAggregateDomain + +class HeadAggregateDomain : public AbstractDomain { +public: +private: +}; + +// }}}1 + +// {{{1 declaration of AuxLiteral + +class AuxLiteral : public Literal { +public: + AuxLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + bool isPositive() const override { return id_.sign() == NAF::POS; } + bool isHeadAtom() const override; + LiteralId simplify(Mappings &mappings, AssignmentLookup lookup) const override; + bool isTrue(IsTrueLookup) const override; + virtual ~AuxLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of PredicateLiteral + +class PredicateLiteral : public Literal { +public: + PredicateLiteral(DomainData &data, LiteralId id); + bool isAtomFromPreviousStep() const override; + bool isHeadAtom() const override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + Lit_t uid() const override; + bool isPositive() const override { return id_.sign() == NAF::POS; } + LiteralId simplify(Mappings &mappings, AssignmentLookup lookup) const override; + bool isTrue(IsTrueLookup) const override; + virtual ~PredicateLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of TheoryLiteral + +class TheoryLiteral : public Literal { +public: + TheoryLiteral(DomainData &data, LiteralId id); + bool isHeadAtom() const override; + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + virtual ~TheoryLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of CSPLiteral + +class CSPLiteral : public Literal { +public: + CSPLiteral(DomainData &data, LiteralId id); + CSPGroundLit const &atom() const; + bool isBound(Symbol &value, bool negate) const override; + void updateBound(std::vector &bounds, bool negate) const override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + LiteralId toId() const override { return id_; } + LiteralId translate(Translator &x) override; + Lit_t uid() const override; + virtual ~CSPLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of BodyAggregateLiteral + +class BodyAggregateLiteral : public Literal { +public: + BodyAggregateLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + BodyAggregateDomain &dom() const; + virtual ~BodyAggregateLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of AssignmentAggregateLiteral + +class AssignmentAggregateLiteral : public Literal { +public: + AssignmentAggregateLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + AssignmentAggregateDomain &dom() const; + virtual ~AssignmentAggregateLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of ConjunctionLiteral + +class ConjunctionLiteral : public Literal { +public: + ConjunctionLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + bool needsSemicolon() const override; + ConjunctionDomain &dom() const; + virtual ~ConjunctionLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of DisjointLiteral + +class DisjointLiteral : public Literal { +public: + DisjointLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + DisjointDomain &dom() const; + virtual ~DisjointLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of DisjunctionLiteral + +class DisjunctionLiteral : public Literal { +public: + DisjunctionLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + DisjunctionDomain &dom() const; + bool isBound(Symbol &value, bool negate) const override; + void updateBound(std::vector &bound, bool negate) const override; + virtual ~DisjunctionLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// {{{1 declaration of HeadAggregateLiteral + +class HeadAggregateLiteral : public Literal { +public: + HeadAggregateLiteral(DomainData &data, LiteralId id); + LiteralId toId() const override; + LiteralId translate(Translator &x) override; + bool isHeadAtom() const override { return true; } + void printPlain(PrintPlain out) const override; + bool isIncomplete() const override; + Lit_t uid() const override; + std::pairdelayedLit() override; + HeadAggregateDomain &dom() const; + virtual ~HeadAggregateLiteral() noexcept; + +private: + DomainData &data_; + LiteralId id_; +}; + +// }}}1 + +// {{{1 declaration of DomainData + +class DomainData : private Gringo::TheoryData { + using Tuples = UniqueVecVec<2, Symbol>; + using Clauses = UniqueVecVec<2, LiteralId>; + using Formulas = UniqueVecVec<2, std::pair, value_hash>>; + using CSPAtoms = UniqueVec>; +public: + DomainData(Potassco::TheoryData &theory) + : theory_(theory) { } + DomainData(DomainData &&) = default; + DomainData& operator=(DomainData&&) = delete; + ~DomainData() noexcept = default; + + PredicateDomain &add(Sig const &sig) { + auto it(predDomains_.find(sig)); + if (it == predDomains_.end()) { + it = predDomains_.push(gringo_make_unique(sig)).first; + it->get()->setDomainOffset(predDomains_.offset(it)); + } + return **it; + } + PredDomMap &predDoms() { return predDomains_; } + PredDomMap const &predDoms() const { return predDomains_; } + PredicateDomain &predDom(Id_t offset) { return *predDomains_[offset]; } + PredicateDomain const &predDom(Id_t offset) const { return *predDomains_[offset]; } + template + D &add(Args &&... args) { + domains_.emplace_back(gringo_make_unique(std::forward(args)...)); + domains_.back()->setDomainOffset(static_cast(domains_.size() - 1)); + return static_cast(*domains_.back()); + } + template + D &getDom(Id_t offset) { return static_cast(*domains_[offset]); } + template + D const &getDom(Id_t offset) const { return static_cast(*domains_[offset]); } + template + auto getAtom(Id_t dom, Id_t offset) -> decltype(std::declval()[offset]) { + return getDom(dom)[offset]; + } + template + auto getAtom(Id_t dom, Id_t offset) const -> decltype(std::declval()[offset]) { + return getDom(dom)[offset]; + } + template + auto getAtom(LiteralId lit) -> decltype(std::declval()[lit.offset()]) { + return getDom(lit.domain())[lit.offset()]; + } + template + auto getAtom(LiteralId lit) const -> decltype(std::declval()[lit.offset()]) { + return getDom(lit.domain())[lit.offset()]; + } + Potassco::Atom_t newAtom() { return ++atoms_; } + LiteralId newAux(NAF naf = NAF::POS) { return {naf, Gringo::Output::AtomType::Aux, newAtom(), 0}; } + LiteralId newDelayed(NAF naf = NAF::POS) { return {naf, Gringo::Output::AtomType::Aux, newAtom(), 1}; } + LiteralId getTrueLit() { + if (!trueLit_.valid()) { trueLit_ = newAux(NAF::NOT); } + return trueLit_; + } + Gringo::Output::TheoryData &theory() { return theory_; } + Gringo::Output::TheoryData const &theory() const { return theory_; } + TupleId tuple(SymVec const &cond) { + return {tuples_.push(cond).first, static_cast(cond.size())}; + } + IteratorRange tuple(TupleId pos) { + auto it = tuples_.at(pos.offset, pos.size); + return {it, it + pos.size}; + } + std::pair clause(LitVec &cond) { + sort_unique(cond); + return {clauses_.push(cond).first, cond.size()}; + } + std::pair clause(LitVec &&cond) { return clause(cond); } + IteratorRange clause(std::pair pos) { return clause(pos.first, pos.second); } + IteratorRange clause(Id_t id, Id_t size) { + auto it = clauses_.at(id, size); + return {it, it + size}; + } + std::pair formula(Formula &&lits) { + sort_unique(lits); + return {formulas_.push(lits).first, lits.size()}; + } + IteratorRange formula(Id_t id, Id_t size) { + auto it = formulas_.at(id, size); + return {it, it + size}; + } + CSPGroundLit const &cspAtom(Id_t offset) { + return cspAtoms_[offset]; + } + Id_t cspAtom(CSPGroundLit &&lit) { + auto ret = cspAtoms_.push(std::move(lit)); + return cspAtoms_.offset(ret.first); + } + IteratorRange formula(std::pair pos) { return formula(pos.first, pos.second); } + // This should be called before grounding a new step + // to get rid of unnecessary temporary data. + void reset() { + theory_.reset(); + clauses_.clear(); + formulas_.clear(); + domains_.clear(); + } + bool canSimplify() const { + return domains_.empty() && clauses_.empty() && formulas_.empty() && theory_.empty(); + } + Gringo::TheoryData const &theoryInterface() const { + return *this; + } + BackendAtomVec &tempAtoms() { + hd_.clear(); + return hd_; + } + BackendLitVec &tempLits() { + bd_.clear(); + return bd_; + } + BackendLitWeightVec &tempWLits() { + wb_.clear(); + return wb_; + } + +private: + Gringo::TheoryData::TermType termType(Id_t) const override; + int termNum(Id_t value) const override; + char const *termName(Id_t value) const override; + Potassco::IdSpan termArgs(Id_t value) const override; + Potassco::IdSpan elemTuple(Id_t value) const override; + Potassco::LitSpan elemCond(Id_t value) const override; + Potassco::Lit_t elemCondLit(Id_t value) const override; + Potassco::IdSpan atomElems(Id_t value) const override; + Potassco::Id_t atomTerm(Id_t value) const override; + bool atomHasGuard(Id_t value) const override; + Potassco::Lit_t atomLit(Id_t value) const override; + std::pair atomGuard(Id_t value) const override; + Potassco::Id_t numAtoms() const override; + std::string termStr(Id_t value) const override; + std::string elemStr(Id_t value) const override; + std::string atomStr(Id_t value) const override; + +private: + BackendAtomVec hd_; + BackendLitVec bd_; + BackendLitWeightVec wb_; + std::vector tempLits_; + Gringo::Output::TheoryData theory_; + PredDomMap predDomains_; + UDomVec domains_; + Potassco::Atom_t atoms_ = 0; + Clauses clauses_; + Tuples tuples_; + Formulas formulas_; + CSPAtoms cspAtoms_; + LiteralId trueLit_; +}; + +template +auto call(DomainData &data, LiteralId lit, M m, Args&&... args) -> decltype((std::declval()->*m)(std::forward(args)...)) { + assert(lit.valid()); + switch (lit.type()) { + case AtomType::Aux: { + AuxLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::Predicate: { + PredicateLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::BodyAggregate: { + BodyAggregateLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::HeadAggregate: { + HeadAggregateLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::AssignmentAggregate: { + AssignmentAggregateLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::Conjunction: { + ConjunctionLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::LinearConstraint: { + CSPLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::Disjunction: { + DisjunctionLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::Disjoint: { + DisjointLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + case AtomType::Theory: { + TheoryLiteral x(data, lit); + return (x.*m)(std::forward(args)...); + } + } + throw std::logic_error("cannot happen"); +} + +// }}}1 + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_LITERALS_HH + diff --git a/libgringo/gringo/output/output.hh b/libgringo/gringo/output/output.hh new file mode 100644 index 0000000..d51b068 --- /dev/null +++ b/libgringo/gringo/output/output.hh @@ -0,0 +1,107 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_OUTPUT_HH +#define _GRINGO_OUTPUT_OUTPUT_HH + +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +class TranslatorOutput : public AbstractOutput { +public: + TranslatorOutput(UAbstractOutput &&out); + void output(DomainData &data, Statement &stm) override; +private: + Translator trans_; +}; + +class TextOutput : public AbstractOutput { +public: + TextOutput(std::string prefix, std::ostream &stream, UAbstractOutput &&out = nullptr); + void output(DomainData &data, Statement &stm) override; +private: + std::string prefix_; + std::ostream &stream_; + UAbstractOutput out_; +}; + +class BackendOutput : public AbstractOutput { +public: + BackendOutput(UBackend &&out); + void output(DomainData &data, Statement &stm) override; +private: + UBackend out_; +}; + +struct OutputOptions { + OutputDebug debug = OutputDebug::NONE; + bool reifySCCs = false; + bool reifySteps = false; +}; + +class OutputBase { +public: + OutputBase(Potassco::TheoryData &data, OutputPredicates &&outPreds, std::ostream &out, OutputFormat format = OutputFormat::INTERMEDIATE, OutputOptions opts = OutputOptions()); + OutputBase(Potassco::TheoryData &data, OutputPredicates &&outPreds, UBackend &&out, OutputOptions opts = OutputOptions()); + OutputBase(Potassco::TheoryData &data, OutputPredicates &&outPreds, UAbstractOutput &&out); + + std::pair simplify(AssignmentLookup assignment); + void incremental(); + void output(Statement &x); + void flush(); + void init(bool incremental); + void beginStep(); + void endStep(bool solve, Logger &log); + void checkOutPreds(Logger &log); + SymVec atoms(unsigned atomset, IsTrueLookup lookup) const; + std::pair find(Symbol val); + std::pair find(Symbol val) const; + PredDomMap &predDoms() { return data.predDoms(); } + PredDomMap const &predDoms() const { return data.predDoms(); } + Rule &tempRule(bool choice) { return tempRule_.reset(choice); } + SymVec &tempVals() { tempVals_.clear(); return tempVals_; } + LitVec &tempLits() { tempLits_.clear(); return tempLits_; } + Backend *backend(); + void registerObserver(std::unique_ptr prg); + void reset(); +private: + UAbstractOutput fromFormat(std::ostream &out, OutputFormat format, OutputOptions opts); + UAbstractOutput fromBackend(UBackend &&out, OutputOptions opts); + +public: + SymVec tempVals_; + LitVec tempLits_; + Rule tempRule_; + LitVec delayed_; + OutputPredicates outPreds; + DomainData data; + OutputPredicates outPredsForce; + UAbstractOutput out_; + bool keepFacts = false; +}; + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_OUTPUT_HH + diff --git a/libgringo/gringo/output/statement.hh b/libgringo/gringo/output/statement.hh new file mode 100644 index 0000000..44648c1 --- /dev/null +++ b/libgringo/gringo/output/statement.hh @@ -0,0 +1,64 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_STATEMENT_HH +#define _GRINGO_OUTPUT_STATEMENT_HH + +#include +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 declaration of AbstractOutput + +class AbstractOutput { +public: + virtual void output(DomainData &data, Statement &stm) = 0; + virtual ~AbstractOutput() noexcept = default; +}; +using UAbstractOutput = std::unique_ptr; + +// {{{1 declaration of Statement + +void replaceDelayed(DomainData &data, LiteralId &lit, LitVec &delayed); +void replaceDelayed(DomainData &data, LitVec &lits, LitVec &delayed); +void translate(DomainData &data, Translator &x, LiteralId &lit); +void translate(DomainData &data, Translator &x, LitVec &lits); + +class Statement { +public: + virtual ~Statement() noexcept = default; + virtual void output(DomainData &data, UBackend &out) const = 0; + virtual void print(PrintPlain out, char const *prefix = "") const = 0; + virtual void translate(DomainData &data, Translator &trans) = 0; + virtual void replaceDelayed(DomainData &data, LitVec &delayed) = 0; + // convenience function + void passTo(DomainData &data, AbstractOutput &out) { out.output(data, *this); } +}; + +// }}}1 + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_STATEMENT_HH + diff --git a/libgringo/gringo/output/statements.hh b/libgringo/gringo/output/statements.hh new file mode 100644 index 0000000..171b5a8 --- /dev/null +++ b/libgringo/gringo/output/statements.hh @@ -0,0 +1,493 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_STATEMENTS_HH +#define _GRINGO_OUTPUT_STATEMENTS_HH + +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 declaration of Rule + +class Rule : public Statement { +public: + Rule(bool choice = false); + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + void replaceDelayed(DomainData &data, LitVec &delayed) override; + Rule &reset(bool choice); + Rule &addHead(LiteralId lit); + Rule &addBody(LiteralId lit); + template + Rule &addBody(T const &t) { + for (auto &x : t) { body_.emplace_back(x); } + return *this; + } + template + Rule &addHead(T const &t) { + for (auto &x : t) { head_.emplace_back(x); } + return *this; + } + Rule &negatePrevious(DomainData &data); + size_t numHeads() const { return head_.size(); } + LitVec const &heads() const { return head_; } + LitVec const &body() const { return body_; } + virtual ~Rule(); + +private: + bool choice_; + LitVec head_; + LitVec body_; +}; + +// {{{1 declaration of External + +class External : public Statement { +public: + External(LiteralId head, Potassco::Value_t type); + void replaceDelayed(DomainData &data, LitVec &delayed) override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + void output(DomainData &data, UBackend &out) const override; + virtual ~External(); + +private: + LiteralId head_; + Potassco::Value_t type_; +}; + +// }}}1 +// {{{1 declaration of ShowStatement + +class ShowStatement : public Statement { +public: + ShowStatement(Symbol term, bool csp, LitVec const &body); + void replaceDelayed(DomainData &data, LitVec &delayed) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + virtual ~ShowStatement() noexcept = default; + +private: + Symbol term_; + LitVec body_; + bool csp_; +}; + +// {{{1 declaration of ProjectStatement + +class ProjectStatement : public Statement { +public: + ProjectStatement(LiteralId atom); + void replaceDelayed(DomainData &data, LitVec &delayed) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + virtual ~ProjectStatement() noexcept = default; + +private: + LiteralId atom_; +}; + +// {{{1 declaration of HeuristicStatement + +class HeuristicStatement : public Statement { +public: + HeuristicStatement(LiteralId atom, int value, int priority, Potassco::Heuristic_t mod, LitVec const &body); + void replaceDelayed(DomainData &data, LitVec &delayed) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + virtual ~HeuristicStatement() noexcept = default; + +private: + LiteralId atom_; + int value_; + int priority_; + Potassco::Heuristic_t mod_; + LitVec body_; +}; + +// {{{1 declaration of EdgeStatement + +class EdgeStatement : public Statement { +public: + EdgeStatement(Symbol u, Symbol v, LitVec const &body); + void replaceDelayed(DomainData &data, LitVec &delayed) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + virtual ~EdgeStatement() noexcept = default; + +private: + Symbol u_; + Symbol v_; + Id_t uidU_; + Id_t uidV_; + LitVec body_; +}; + +// {{{1 declaration of WeakConstraint + +class WeakConstraint : public Statement { +public: + WeakConstraint(SymVec tuple, LitVec const &lits) + : tuple_(tuple) + , lits_(lits) { } + void translate(DomainData &data, Translator &x) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void replaceDelayed(DomainData &data, LitVec &delayed) override; + virtual ~WeakConstraint() noexcept = default; + +private: + SymVec tuple_; + LitVec lits_; +}; + +// {{{1 declaration of TheoryDirective + +class TheoryDirective : public Statement { +public: + TheoryDirective(LiteralId theoryLit); + void translate(DomainData &data, Translator &x) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void replaceDelayed(DomainData &data, LitVec &delayed) override; + virtual ~TheoryDirective() noexcept = default; + +private: + LiteralId theoryLit_; +}; + +// }}}1 + +// Translation + +// {{{1 declaration of Translator + +// {{{2 declaration of Bound + +struct Bound { + using ConstIterator = enum_interval_set::const_iterator; + using AtomVec = std::vector>; + Bound(Symbol var) + : modified(true) + , var(var) { + range_.add(std::numeric_limits::min(), std::numeric_limits::max()); + } + operator Symbol const & () const { return var; } + bool init(DomainData &data, Translator &x, Logger &log); + int getLower(int coef) const { + if (range_.empty()) { return 0; } + return coef * (coef < 0 ? range_.back() : range_.front()); + } + int getUpper(int coef) const { + if (range_.empty()) { return -coef; } + return coef * (coef < 0 ? range_.front() : range_.back()); + } + void remove(int l, int r) { + range_.remove(l, r); + modified = true; + } + void add(int l, int r) { + range_.add(l, r); + modified = true; + } + void clear() { + range_.clear(); + modified = true; + } + void intersect(enum_interval_set &x) { + range_.intersect(x); + modified = true; + } + ConstIterator begin() const { return range_.begin(); } + ConstIterator end() const { return range_.end(); } + + bool modified; + Symbol var; + + AtomVec atoms; + enum_interval_set range_; +}; + +// {{{2 declaration of LinearConstraint + +struct LinearConstraint { + struct State { + using Coef = CoefVarVec::value_type; + State(Bound &bound, Coef &coef) + : bound(bound) + , coef(coef.first) { reset(); } + int upper() { return bound.getUpper(coef); } + int lower() { return bound.getLower(coef); } + bool valid() { return atom != (coef < 0 ? bound.atoms.begin() : bound.atoms.end()); } + void next(int total, int &ret) { + if (coef < 0) { + --atom; + --current; + auto it = current; + --it; + ret = total + coef * (*it); + } + else { + ++atom; + ++current; + ret = total + coef * (*current); + } + } + void reset() { + current = coef < 0 ? bound.end() : bound.begin(); + atom = coef < 0 ? bound.atoms.end() : bound.atoms.begin(); + } + Bound &bound; + Bound::ConstIterator current; + Bound::AtomVec::iterator atom; + int coef; + }; + using StateVec = std::vector; + struct Generate { + using AuxVec = std::vector; + Generate(LinearConstraint &cons, DomainData &data, Translator &trans) + : cons(cons) + , data(data) + , trans(trans) { } + bool init(); + int getBound() { return cons.bound; } + void generate(StateVec::iterator it, int current, int remainder); + StateVec states; + LinearConstraint &cons; + DomainData &data; + Translator &trans; + AuxVec aux; + }; + LinearConstraint(Potassco::Atom_t atom, CoefVarVec &&coefs, int bound) + : atom(atom) + , coefs(std::move(coefs)) + , bound(bound) { } + bool translate(DomainData &data, Translator &x); + Potassco::Atom_t atom; + CoefVarVec coefs; + int bound; +}; + +// }}}2 + +class Translator { +private: + struct OutputEntry { + OutputEntry(Symbol term, LiteralId cond) + : term(term) + , cond(cond) { } + Symbol term; + LiteralId cond; + operator const Symbol&() const { return term; } + }; + struct TodoOutputEntry { + TodoOutputEntry(Symbol term, Formula &&cond) + : term(term) + , cond(std::move(cond)) { } + operator const Symbol&() const { return term; } + Symbol term; + Formula cond; + }; + struct OutputTable { + using Table = UniqueVec, std::equal_to>; + using Todo = UniqueVec, std::equal_to>; + Table table; + Todo todo; + }; +public: + using TupleLit = std::pair; + using MinimizeList = std::vector; + using BoundMap = UniqueVec, EqualToKey>; + using ConstraintVec = std::vector; + using DisjointConsVec = std::vector; + using ProjectionVec = std::vector>; + using TupleLitMap = UniqueVec, EqualToFirst>; + + Translator(UAbstractOutput &&out); + void addMinimize(TupleId tuple, LiteralId cond); + void addBounds(Symbol value, std::vector bounds); + BoundMap::Iterator addBound(Symbol x); + Bound &findBound(Symbol x); + void addLinearConstraint(Potassco::Atom_t head, CoefVarVec &&vars, int bound); + void addDisjointConstraint(DomainData &data, LiteralId lit); + void atoms(DomainData &data, unsigned atomset, IsTrueLookup isTrue, SymVec &atoms, OutputPredicates const &outPreds); + void translate(DomainData &data, OutputPredicates const &outPreds, Logger &log); + void output(DomainData &data, Statement &x); + void simplify(DomainData &data, Mappings &mappings, AssignmentLookup assignment); + void showTerm(DomainData &data, Symbol term, bool csp, LitVec &&cond); + LiteralId removeNotNot(DomainData &data, LiteralId lit); + unsigned nodeUid(Symbol v); + // These are used to cache literals of translated formulas. + // The clauses and formuals are tied to clauses and formulas in DomainData. + // Hence, they have to be deleted after each step. + LiteralId clause(ClauseId id, bool conjunctive, bool equivalence); + void clause(LiteralId lit, ClauseId id, bool conjunctive, bool equivalence); + void reset() { clauses_.clear(); } + + ~Translator(); +private: + LitVec updateCond(DomainData &data, OutputTable::Table &table, OutputTable::Todo::ValueType &todo); + void showAtom(DomainData &data, PredDomMap::Iterator it); + void showValue(DomainData &data, Symbol value, LitVec const &cond); + void showValue(DomainData &data, Bound const &bound, LitVec const &cond); + void addLowerBound(Symbol x, int bound); + void addUpperBound(Symbol x, int bound); + bool showBound(OutputPredicates const &outPreds, Bound const &bound); + void translateMinimize(DomainData &data); + void outputSymbols(DomainData &data, OutputPredicates const &outPreds, Logger &log); + bool showSig(OutputPredicates const &outPreds, Sig sig, bool csp); + void showCsp(Bound const &bound, IsTrueLookup isTrue, SymVec &atoms); + + OutputTable termOutput_; + OutputTable cspOutput_; + MinimizeList minimize_; // stores minimize constraint for current step + TupleLitMap tuples_; // to incrementally extend minimize constraint + BoundMap boundMap_; + ConstraintVec constraints_; + DisjointConsVec disjointCons_; + HashSet seenSigs_; + BoundMap::SizeType incBoundOffset_ = 0; + UAbstractOutput out_; + UniqueVec nodeUids_; + struct ClauseKey { + uint64_t offset : 32; + uint64_t size : 30; + uint64_t conjunctive : 1; + uint64_t equivalence : 1; + uint64_t literal; + + uint64_t lower() const { + return static_cast(offset) << 32 | size << 2 | conjunctive << 1 | equivalence; + } + size_t hash() const { + return std::hash()(lower()); + } + bool operator==(ClauseKey const &other) const { + return lower() == other.lower(); + } + }; + struct ClauseKeyLiterals { + static constexpr ClauseKey open = { 0xffffffff, 0x3fffffff, 1, 1, std::numeric_limits::max() }; + static constexpr ClauseKey deleted = { 0xffffffff, 0x3fffffff, 1, 1, std::numeric_limits::max() - 1 }; + }; + HashSet clauses_; +}; + +// {{{1 declaration of Minimize + +class Minimize : public Statement { +public: + using LitWeightVec = std::vector>; + Minimize(int priority); + Minimize &add(LiteralId lit, Potassco::Weight_t weight); + void translate(DomainData &data, Translator &x) override; + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void replaceDelayed(DomainData &data, LitVec &delayed) override; + virtual ~Minimize(); + +private: + int priority_; + LitWeightVec lits_; +}; + + +// {{{1 declaration of Symtab + +class Symtab : public Statement { +public: + Symtab(Symbol symbol, LitVec &&body); + Symtab(Symbol symbol, int value, LitVec &&body); + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + void replaceDelayed(DomainData &data, LitVec &delayed) override; + virtual ~Symtab(); + +private: + Symbol symbol_; + int value_; + bool csp_; + LitVec body_; +}; + +// {{{1 declaration of WeightRule + +class WeightRule : public Statement { +public: + WeightRule(LiteralId head, Potassco::Weight_t lower, LitUintVec &&body); + void output(DomainData &data, UBackend &out) const override; + void print(PrintPlain out, char const *prefix) const override; + void translate(DomainData &data, Translator &trans) override; + void replaceDelayed(DomainData &data, LitVec &delayed) override; + virtual ~WeightRule(); + +private: + LiteralId head_; + LitUintVec body_; + Potassco::Weight_t lower_; +}; + +// }}}1 + +// Helpers + +// {{{1 definition of BackendStatement + +template +class BackendStatement : public Statement { +public: + BackendStatement(T const &lambda) + : lambda_(lambda) + { } + void output(DomainData &data, UBackend &out) const override { lambda_(data, out); } + void print(PrintPlain, char const *) const override { } + void translate(DomainData &data, Translator &trans) override { + trans.output(data, *this); + } + void replaceDelayed(DomainData &, LitVec &) override { } + virtual ~BackendStatement() { } +private: + T const &lambda_; +}; + +template +void backendLambda(DomainData &data, AbstractOutput &out, T const &lambda) { + BackendStatement(lambda).passTo(data, out); +} + +template +void backendLambda(DomainData &data, Translator &trans, T const &lambda) { + BackendStatement bs(lambda); + trans.output(data, bs); +} + +// }}}1 + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_STATEMENTS_HH diff --git a/libgringo/gringo/output/theory.hh b/libgringo/gringo/output/theory.hh new file mode 100644 index 0000000..b882217 --- /dev/null +++ b/libgringo/gringo/output/theory.hh @@ -0,0 +1,287 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_THEORY_HH +#define _GRINGO_OUTPUT_THEORY_HH + +#include +#include +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +class LiteralId; +using LitVec = std::vector; +using Gringo::StringVec; +using Gringo::GetName; + +// {{{1 declaration of TheoryData + +class TheoryData { + using TIdSet = HashSet; + using AtomSet = HashSet; + using ConditionVec = std::vector; + using PrintLit = std::function; +public: + TheoryData(Potassco::TheoryData &data); + ~TheoryData() noexcept; + Potassco::Id_t addTerm(int number); + Potassco::Id_t addTerm(char const *name); + Potassco::Id_t addTerm(Potassco::Id_t funcSym, Potassco::IdSpan const& terms); + Potassco::Id_t addTerm(Potassco::Tuple_t type, Potassco::IdSpan const& terms); + Potassco::Id_t addTerm(Symbol value); + Potassco::Id_t addElem(Potassco::IdSpan const &tuple, LitVec &&cond); + std::pair addAtom(std::function newAtom, Potassco::Id_t termId, Potassco::IdSpan const &elems); + std::pair addAtom(std::function newAtom, Potassco::Id_t termId, Potassco::IdSpan const &elems, Potassco::Id_t op, Potassco::Id_t rhs); + void printTerm(std::ostream &out, Potassco::Id_t termId) const; + void printElem(std::ostream &out, Potassco::Id_t elemId, PrintLit printLit) const; + bool empty() const; + LitVec const &getCondition(Potassco::Id_t elemId) const; + LitVec &getCondition(Potassco::Id_t elemId); + Potassco::TheoryData const &data() const; + void setCondition(Potassco::Id_t elementId, Potassco::Id_t newCond); + bool hasConditions() const; + void reset(); + Potassco::TheoryAtom const &getAtom(Id_t offset) const { return **(data_.begin() + offset); } + +private: + template + Potassco::Id_t addTerm_(Args ...args); + template + std::pair addAtom_(std::function newAtom, Args ...args); +private: + TIdSet terms_; + TIdSet elems_; + AtomSet atoms_; + Potassco::TheoryData &data_; + ConditionVec conditions_; +}; + +// {{{1 declaration of TheoryTerm + +class TheoryParser; +class TheoryTerm; +using UTheoryTerm = std::unique_ptr; +using UTheoryTermVec = std::vector; +class TheoryTerm : public Hashable, public Comparable, public Printable, public Clonable { +public: + virtual Potassco::Id_t eval(TheoryData &data, Logger &log) const = 0; + virtual void collect(VarTermBoundVec &vars) = 0; + virtual void replace(Defines &defs) = 0; + virtual UTheoryTerm initTheory(TheoryParser &p, Logger &log) = 0; + virtual ~TheoryTerm() { } +}; + +// {{{1 declaration of RawTheoryTerm + +class RawTheoryTerm : public TheoryTerm { +public: + using ElemVec = std::vector>; +public: + RawTheoryTerm(); + RawTheoryTerm(ElemVec &&elems); + RawTheoryTerm(RawTheoryTerm &&); + RawTheoryTerm &operator=(RawTheoryTerm &&); + void append(StringVec &&ops, UTheoryTerm &&term); + virtual ~RawTheoryTerm() noexcept; + // {{{2 TheoryTerm interface + Potassco::Id_t eval(TheoryData &data, Logger &log) const override; + void collect(VarTermBoundVec &vars) override; + void replace(Defines &defs) override; + UTheoryTerm initTheory(TheoryParser &p, Logger &log) override; + // {{{2 Hashable interface + size_t hash() const override; + // {{{2 Comparable interface + bool operator==(TheoryTerm const &other) const override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Clonable interface + RawTheoryTerm *clone() const override; + // }}}2 +private: + ElemVec elems_; +}; + +class TheoryParser { + enum TokenType { Op, Id }; + struct Elem { + Elem(String op, bool unary); + Elem(UTheoryTerm &&term); + Elem(Elem &&elem); + ~Elem() noexcept; + TokenType tokenType; + union { + std::pair op; + UTheoryTerm term; + }; + }; + using Stack = std::vector; +public: + TheoryParser(Location const &loc, TheoryTermDef const &def); + UTheoryTerm parse(RawTheoryTerm::ElemVec && elems, Logger &log); + ~TheoryParser() noexcept; +private: + void reduce(); + bool check(String op); +private: + Location loc_; + TheoryTermDef const &def_; + Stack stack_; +}; + +// {{{1 declaration of UnaryTheoryTerm + +class UnaryTheoryTerm : public TheoryTerm { +public: + UnaryTheoryTerm(String op, UTheoryTerm &&arg); + virtual ~UnaryTheoryTerm() noexcept; + // {{{2 TheoryTerm interface + Potassco::Id_t eval(TheoryData &data, Logger &log) const override; + void collect(VarTermBoundVec &vars) override; + void replace(Defines &defs) override; + UTheoryTerm initTheory(TheoryParser &p, Logger &log) override; + // {{{2 Hashable interface + size_t hash() const override; + // {{{2 Comparable interface + bool operator==(TheoryTerm const &other) const override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Clonable interface + UnaryTheoryTerm *clone() const override; + // }}}2 +private: + UTheoryTerm arg_; + String op_; +}; + +// {{{1 declaration of BinaryTheoryTerm + +class BinaryTheoryTerm : public TheoryTerm { +public: + BinaryTheoryTerm(UTheoryTerm &&left, String op, UTheoryTerm &&right); + virtual ~BinaryTheoryTerm() noexcept; + // {{{2 TheoryTerm interface + Potassco::Id_t eval(TheoryData &data, Logger &log) const override; + void collect(VarTermBoundVec &vars) override; + void replace(Defines &defs) override; + UTheoryTerm initTheory(TheoryParser &p, Logger &log) override; + // {{{2 Hashable interface + size_t hash() const override; + // {{{2 Comparable interface + bool operator==(TheoryTerm const &other) const override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Clonable interface + BinaryTheoryTerm *clone() const override; + // }}}2 +private: + UTheoryTerm left_; + UTheoryTerm right_; + String op_; +}; + +// {{{1 declaration of TupleTheoryTerm + +class TupleTheoryTerm : public TheoryTerm { +public: + using Type = Potassco::Tuple_t; +public: + TupleTheoryTerm(Type type, UTheoryTermVec &&args); + virtual ~TupleTheoryTerm() noexcept; + // {{{2 TheoryTerm interface + Potassco::Id_t eval(TheoryData &data, Logger &log) const override; + void collect(VarTermBoundVec &vars) override; + void replace(Defines &defs) override; + UTheoryTerm initTheory(TheoryParser &p, Logger &log) override; + // {{{2 Hashable interface + size_t hash() const override; + // {{{2 Comparable interface + bool operator==(TheoryTerm const &other) const override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Clonable interface + TupleTheoryTerm *clone() const override; + // }}}2 +private: + UTheoryTermVec args_; + Type type_; +}; + +// {{{1 declaration of FunctionTheoryTerm + +class FunctionTheoryTerm : public TheoryTerm { +public: + FunctionTheoryTerm(String name, UTheoryTermVec &&args); + virtual ~FunctionTheoryTerm() noexcept; + // {{{2 TheoryTerm interface + Potassco::Id_t eval(TheoryData &data, Logger &log) const override; + void collect(VarTermBoundVec &vars) override; + void replace(Defines &defs) override; + UTheoryTerm initTheory(TheoryParser &p, Logger &log) override; + // {{{2 Hashable interface + size_t hash() const override; + // {{{2 Comparable interface + bool operator==(TheoryTerm const &other) const override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Clonable interface + FunctionTheoryTerm *clone() const override; + // }}}2 +private: + UTheoryTermVec args_; + String name_; +}; + +// }}}1 +// {{{1 declaration of TermTheoryTerm + +class TermTheoryTerm : public TheoryTerm { +public: + TermTheoryTerm(UTerm &&term); + virtual ~TermTheoryTerm() noexcept; + // {{{2 TheoryTerm interface + Potassco::Id_t eval(TheoryData &data, Logger &log) const override; + void collect(VarTermBoundVec &vars) override; + void replace(Defines &defs) override; + UTheoryTerm initTheory(TheoryParser &p, Logger &log) override; + // {{{2 Hashable interface + size_t hash() const override; + // {{{2 Comparable interface + bool operator==(TheoryTerm const &other) const override; + // {{{2 Printable interface + void print(std::ostream &out) const override; + // {{{2 Clonable interface + TermTheoryTerm *clone() const override; + // }}}2 +private: + UTerm term_; +}; + +// }}}1 + +} } // namespace Output Gringo + +GRINGO_CALL_HASH(Gringo::Output::TheoryTerm) + +#endif // _GRINGO_OUTPUT_THEORY_HH + diff --git a/libgringo/gringo/output/types.hh b/libgringo/gringo/output/types.hh new file mode 100644 index 0000000..94ebd9e --- /dev/null +++ b/libgringo/gringo/output/types.hh @@ -0,0 +1,59 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_TYPES_HH +#define _GRINGO_OUTPUT_TYPES_HH + +#include +#include + +namespace Gringo { namespace Output { + +class Translator; +class TheoryData; +class PredicateDomain; +class LiteralId; +class DisjointElement; +class Statement; +struct AuxAtom; +struct PrintPlain; +class DomainData; +class OutputBase; + +using LitVec = std::vector; +using ClauseId = std::pair; +using FormulaId = std::pair; +using Formula = std::vector; +using CSPBound = std::pair; +using AssignmentLookup = std::function(unsigned)>; // (isExternal, truthValue) +using IsTrueLookup = std::function; +using OutputPredicates = std::vector>; +using CoefVarVec = std::vector>; + +struct UPredDomHash; +struct UPredDomEqualTo; +using PredDomMap = UniqueVec, UPredDomHash, UPredDomEqualTo>; + +enum class OutputDebug { NONE, TEXT, TRANSLATE, ALL }; +enum class OutputFormat { TEXT, INTERMEDIATE, SMODELS, REIFY }; + +} } // namespace Output Gringo + +#endif // _GRINGO_OUTPUT_TYPES_HH diff --git a/libgringo/gringo/primes.hh b/libgringo/gringo/primes.hh new file mode 100644 index 0000000..dff8e41 --- /dev/null +++ b/libgringo/gringo/primes.hh @@ -0,0 +1,43 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_PRIMES_HH +#define _GRINGO_PRIMES_HH + +#include +#include + +namespace Gringo { + +template +T constexpr maxPrime(); + +template <> +inline constexpr uint32_t maxPrime() { return 0xfffffffb; } + +template <> +inline constexpr uint64_t maxPrime() { return 0xffffffffffffffc5; } + +uint32_t nextPrime(uint32_t n); +uint64_t nextPrime(uint64_t n); + +} // namspace Gringo + +#endif diff --git a/libgringo/gringo/printable.hh b/libgringo/gringo/printable.hh new file mode 100644 index 0000000..80723d8 --- /dev/null +++ b/libgringo/gringo/printable.hh @@ -0,0 +1,46 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_PRINTABLE_HH +#define _GRINGO_PRINTABLE_HH + +#include + +namespace Gringo { + +// {{{ defintion of Printable + +class Printable { +public: + virtual void print(std::ostream &out) const = 0; + virtual ~Printable() { } +}; + +inline std::ostream &operator<<(std::ostream &out, Printable const &x) { + x.print(out); + return out; +} + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_PRINTABLE_HH + diff --git a/libgringo/gringo/python.hh b/libgringo/gringo/python.hh new file mode 100644 index 0000000..7ea77a7 --- /dev/null +++ b/libgringo/gringo/python.hh @@ -0,0 +1,45 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_PYTHON_HH +#define _GRINGO_PYTHON_HH + +#include +#include +#include + +namespace Gringo { + +struct PythonImpl; +struct Python { + Python(GringoModule &module); + bool exec(Location const &loc, String code); + SymVec call(Location const &loc, String name, SymSpan args, Logger &log); + bool callable(String name); + void main(Control &ctl); + static void *initlib(GringoModule &gringo); + ~Python(); + + static std::unique_ptr impl; +}; + +} // namespace Gringo + +#endif // _GRINGO_PYTHON_HH diff --git a/libgringo/gringo/safetycheck.hh b/libgringo/gringo/safetycheck.hh new file mode 100644 index 0000000..3fea7cb --- /dev/null +++ b/libgringo/gringo/safetycheck.hh @@ -0,0 +1,186 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_SAFETYCHECK_HH +#define _GRINGO_SAFETYCHECK_HH + +#include +#include +#include + +namespace Gringo { + +// {{{ declaration of SafetyChecker + +template +struct SafetyChecker { + struct EntNode; + struct VarNode { + template + VarNode(T&&... args); + bool bound = false; + std::vector provides; + Var data; + }; + + struct EntNode { + template + EntNode(T&&... args); + std::vector provides; + unsigned depends = 0; + Ent data; + }; + + typedef std::vector EntVec; + typedef std::vector VarVec; + + SafetyChecker(); + SafetyChecker(SafetyChecker const &) = delete; + SafetyChecker(SafetyChecker &&x); + + template + VarNode &insertVar(T&&... args); + template + EntNode &insertEnt(T&&... args); + + //! Edge (x, y) implies that y depends on x being bound. + //! E.g., variable x occurs on the rhs of assignment y. + void insertEdge(VarNode &x, EntNode &y); + //! Edge (x, y) implies that y is bound by x. + //! E.g., variable y occurs in a positive body element x. + void insertEdge(EntNode &x, VarNode &y); + + void init(EntVec &open); + void propagate(EntNode *x, EntVec &open, VarVec *bound = nullptr); + template > + EntVec order(Pred pred = Pred()); + VarVec open(); + + std::forward_list entNodes_; + std::forward_list varNodes_; +}; + +// }}} + +// {{{ definition of SafetyChecker::VarNode + +template +template +SafetyChecker::VarNode::VarNode(T&&... args) + : data(std::forward(args)...) +{ +} + +// }}} +// {{{ definition of SafetyChecker::EntNode + +template +template +SafetyChecker::EntNode::EntNode(T&&... args) + : data(std::forward(args)...) +{ +} + +// }}} +// {{{ definition of SafetyChecker + +template +SafetyChecker::SafetyChecker() = default; + +template +SafetyChecker::SafetyChecker(SafetyChecker &&) = default; + +template +void SafetyChecker::insertEdge(VarNode &x, EntNode &y) { + x.provides.emplace_back(&y); + y.depends++; +} + +template +void SafetyChecker::insertEdge(EntNode &x, VarNode &y) { + x.provides.emplace_back(&y); +} + +template +template +typename SafetyChecker::VarNode &SafetyChecker::insertVar(T&&... args) { + varNodes_.emplace_front(std::forward(args)...); + return varNodes_.front(); +} + +template +template +typename SafetyChecker::EntNode &SafetyChecker::insertEnt(T&&... args) { + entNodes_.emplace_front(std::forward(args)...); + return entNodes_.front(); +} + +template +template +typename SafetyChecker::EntVec SafetyChecker::order(Pred pred) { + EntVec open; + init(open); + std::vector done; + while (!open.empty()) { + for (auto it = open.begin(), end = open.end() - 1; it != end; ++it) { + if (pred((*it)->data, open.back()->data)) { std::swap(open.back(), *it); } + } + auto x = open.back(); + open.pop_back(); + propagate(x, open); + done.emplace_back(x); + } + return done; +} + +template +void SafetyChecker::init(EntVec &open) { + for (auto &x : entNodes_) { + if (!x.depends) { open.emplace_back(&x); } + } +} + +template +void SafetyChecker::propagate(EntNode *x, EntVec &open, VarVec *bound) { + for (auto &y : x->provides) { + if (!y->bound) { + y->bound = true; + if (bound) { bound->emplace_back(y); } + for (auto &z : y->provides) { + if (!--z->depends) { open.emplace_back(z); } + } + } + } +} + +template +typename SafetyChecker::VarVec SafetyChecker::open() { + VarVec open; + for (auto &x : varNodes_) { + if (!x.bound) { open.emplace_back(&x); } + } + return open; +} + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_SAFETYCHECK_HH diff --git a/libgringo/gringo/scripts.hh b/libgringo/gringo/scripts.hh new file mode 100644 index 0000000..e90b98f --- /dev/null +++ b/libgringo/gringo/scripts.hh @@ -0,0 +1,58 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_SCRIPTS_HH +#define _GRINGO_SCRIPTS_HH + +#include +#include + +namespace Gringo { + +template +struct ScopeExit { + ScopeExit(T &&exit) : exit(std::forward(exit)) { } + ~ScopeExit() { exit(); } + T exit; +}; + +template +ScopeExit onExit(T &&exit) { + return ScopeExit(std::forward(exit)); +} + +struct Scripts { + Scripts(GringoModule &module); + bool pyExec(Location const &loc, String code); + bool luaExec(Location const &loc, String code); + bool callable(String name); + SymVec call(Location const &loc, String name, SymSpan args, Logger &log); + void main(Control &ctl); + ~Scripts(); + + Context *context = nullptr; + Python py; + Lua lua; +}; + +} // namespace Gringo + +#endif // _GRINGO_SCRIPTS_HH + diff --git a/libgringo/gringo/symbol.hh b/libgringo/gringo/symbol.hh new file mode 100644 index 0000000..cbcb3a9 --- /dev/null +++ b/libgringo/gringo/symbol.hh @@ -0,0 +1,298 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_VALUE_HH +#define _GRINGO_VALUE_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Gringo { + +// {{{1 declaration of String (flyweight) + +using StringSpan = Potassco::StringSpan; + +class String { +public: + String(StringSpan str); + String(char const *str); + const char *c_str() const { return str_; } + bool empty() const; + size_t length() { return std::strlen(str_); } + bool startsWith(char const *prefix) const { + return std::strncmp(prefix, str_, strlen(prefix)) == 0; + } + size_t hash() const; + static uintptr_t toRep(String s); + static String fromRep(uintptr_t t); +private: + String(uintptr_t); + char const *str_; +}; + +inline bool operator==(String a, String b) { return std::strcmp(a.c_str(), b.c_str()) == 0; } +inline bool operator!=(String a, String b) { return std::strcmp(a.c_str(), b.c_str()) != 0; } +inline bool operator< (String a, String b) { return std::strcmp(a.c_str(), b.c_str()) < 0; } +inline bool operator> (String a, String b) { return std::strcmp(a.c_str(), b.c_str()) > 0; } +inline bool operator<=(String a, String b) { return std::strcmp(a.c_str(), b.c_str()) <= 0; } +inline bool operator>=(String a, String b) { return std::strcmp(a.c_str(), b.c_str()) >= 0; } + +inline bool operator==(String a, char const *b) { return std::strcmp(a.c_str(), b) == 0; } +inline bool operator!=(String a, char const *b) { return std::strcmp(a.c_str(), b) != 0; } +inline bool operator< (String a, char const *b) { return std::strcmp(a.c_str(), b) < 0; } +inline bool operator> (String a, char const *b) { return std::strcmp(a.c_str(), b) > 0; } +inline bool operator<=(String a, char const *b) { return std::strcmp(a.c_str(), b) <= 0; } +inline bool operator>=(String a, char const *b) { return std::strcmp(a.c_str(), b) >= 0; } + +inline bool operator==(char const *a, String b) { return std::strcmp(a, b.c_str()) == 0; } +inline bool operator!=(char const *a, String b) { return std::strcmp(a, b.c_str()) != 0; } +inline bool operator< (char const *a, String b) { return std::strcmp(a, b.c_str()) < 0; } +inline bool operator> (char const *a, String b) { return std::strcmp(a, b.c_str()) > 0; } +inline bool operator<=(char const *a, String b) { return std::strcmp(a, b.c_str()) <= 0; } +inline bool operator>=(char const *a, String b) { return std::strcmp(a, b.c_str()) >= 0; } + +inline std::ostream &operator<<(std::ostream &out, String x) { + out << x.c_str(); + return out; +} + +// {{{1 declaration of Signature (flyweight) + +class Sig { +public: + Sig(String name, uint32_t arity, bool sign); + explicit Sig(clingo_signature_t rep) : rep_(rep) { } + String name() const; + Sig flipSign() const; + uint32_t arity() const; + bool sign() const; + size_t hash() const; + uint64_t const &rep() const { return rep_; } + bool match(String n, uint32_t a, bool s = false) const { + return name() == n && arity() == a && sign() == s; + } + bool match(char const *n, uint32_t a, bool s = false) const { + return name() == n && arity() == a && sign() == s; + } + bool operator==(Sig s) const; + bool operator!=(Sig s) const; + bool operator<(Sig s) const; + bool operator>(Sig s) const; + bool operator<=(Sig s) const; + bool operator>=(Sig s) const; +private: + clingo_signature_t rep_; +}; + +inline std::ostream &operator<<(std::ostream &out, Sig x) { + if (x.sign()) { out << "-"; } + out << x.name() << "/" << x.arity(); + return out; +} + +// {{{1 declaration of Symbol (flyweight) + +enum class SymbolType : uint8_t { + Inf = clingo_symbol_type_infimum, + Num = clingo_symbol_type_number, + Str = clingo_symbol_type_string, + Fun = clingo_symbol_type_function, + Special = clingo_symbol_type_supremum-1, + Sup = clingo_symbol_type_supremum +}; +inline std::ostream &operator<<(std::ostream &out, SymbolType sym) { + switch (sym) { + case SymbolType::Inf: { out << "Inf"; break; } + case SymbolType::Num: { out << "Num"; break; } + case SymbolType::Str: { out << "Str"; break; } + case SymbolType::Fun: { out << "Fun"; break; } + case SymbolType::Special: { out << "Special"; break; } + case SymbolType::Sup: { out << "Sup"; break; } + } + return out; +} + +class Symbol; +using SymVec = std::vector; +using SymSpan = Potassco::Span; +using IdSymMap = std::unordered_map; + +class Symbol { +public: + // construction + Symbol(); // createSpecial + explicit Symbol(clingo_symbol_t sym) : rep_(sym) { }; + static Symbol createId(String val, bool sign = false); + static Symbol createStr(String val); + static Symbol createNum(int num); + static Symbol createInf(); + static Symbol createSup(); + static Symbol createTuple(SymSpan val); + static Symbol createTuple(SymVec const &val) { return createTuple(Potassco::toSpan(val)); } + static Symbol createFun(String name, SymSpan val, bool sign = false); + static Symbol createFun(String name, SymVec const &val, bool sign = false) { return createFun(name, Potassco::toSpan(val), sign); } + + // value retrieval + SymbolType type() const; + int num() const; + String string() const; + Sig sig() const; + bool hasSig() const; + uint32_t arity() const { return sig().arity(); } + String name() const; + SymSpan args() const; + bool sign() const; + + // modifying values + Symbol replace(IdSymMap const &rep) const; + Symbol flipSign() const; + + // comparison + size_t hash() const; + bool operator==(Symbol const &other) const; + bool operator!=(Symbol const &other) const; + bool operator<(Symbol const &other) const; + bool operator>(Symbol const &other) const; + bool operator<=(Symbol const &other) const; + bool operator>=(Symbol const &other) const; + + // ouput + void print(std::ostream& out) const; + + uint64_t const &rep () const { return rep_; } +private: + clingo_symbol_t rep_; +}; + +inline std::ostream& operator<<(std::ostream& out, Symbol sym) { + sym.print(out); + return out; +} + +// {{{1 definition of quote/unquote + +inline std::string quote(StringSpan str) { + std::string res; + for (auto c : str) { + switch (c) { + case '\n': { + res.push_back('\\'); + res.push_back('n'); + break; + } + case '\\': { + res.push_back('\\'); + res.push_back('\\'); + break; + } + case '"': { + res.push_back('\\'); + res.push_back('"'); + break; + } + default: { + res.push_back(c); + break; + } + } + } + return res; +} +inline std::string quote(char const *str) { + return quote({str, strlen(str)}); +} + +inline std::string unquote(StringSpan str) { + std::string res; + bool slash = false; + for (auto c : str) { + if (slash) { + switch (c) { + case 'n': { + res.push_back('\n'); + break; + } + case '\\': { + res.push_back('\\'); + break; + } + case '"': { + res.push_back('"'); + break; + } + default: { + assert(false); + break; + } + } + slash = false; + } + else if (c == '\\') { slash = true; } + else { res.push_back(c); } + } + return res; +} + +inline std::string unquote(char const *str) { + return unquote({str, strlen(str)}); +} + +// }}}1 + +} // namespace Gringo + +namespace std { + +// {{{1 definition of hash functions + +template<> +struct hash { + size_t operator()(Gringo::String const &str) const { return str.hash(); } +}; + +template<> +struct hash { + size_t operator()(Gringo::Sig const &sig) const { return sig.hash(); } +}; + +template<> +struct hash { + size_t operator()(Gringo::Symbol const &sym) const { return sym.hash(); } +}; + +// }}}1 + +} // namespace std + +#endif // _GRINGO_VALUE_HH + diff --git a/libgringo/gringo/term.hh b/libgringo/gringo/term.hh new file mode 100644 index 0000000..c336e1e --- /dev/null +++ b/libgringo/gringo/term.hh @@ -0,0 +1,826 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TERM_HH +#define _GRINGO_TERM_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Gringo { + +// {{{ declaration of UnOp and BinOp + +enum class BinOp : int { XOR, OR, AND, ADD, SUB, MUL, DIV, MOD, POW }; +enum class UnOp : int { NEG, NOT, ABS }; + +int eval(UnOp op, int x); +int eval(BinOp op, int x, int y); + +std::ostream &operator<<(std::ostream &out, BinOp op); +std::ostream &operator<<(std::ostream &out, UnOp op); + +// }}} + + // {{{ declaration of Defines + +struct Term; +using UTerm = std::unique_ptr; +class Defines { +public: + using DefMap = std::unordered_map>; + + Defines(); + Defines(Defines &&x); + //! Add a define. + //! Default defintions will not overwrite existing definitions and can be overwritten by other defines. + void add(Location const &loc, String name, UTerm &&value, bool defaultDef, Logger &log); + //! Evaluates layered definitions and checks for cycles. + void init(Logger &log); + bool empty() const; + void apply(Symbol x, Symbol &retVal, UTerm &retTerm, bool replace); + DefMap const &defs() const; + ~Defines(); + +private: + std::unordered_map> defs_; +}; + +// }}} + +// {{{ declaration of GTerm + +struct GRef; +struct GTerm; +struct GVarTerm; +struct GFunctionTerm; +struct GLinearTerm; +using UGTerm = std::unique_ptr; +using UGFunTerm = std::unique_ptr; +struct GTerm : Printable, Hashable, Comparable { + using EvalResult = std::pair; + virtual Sig sig() const = 0; + virtual EvalResult eval() const = 0; + virtual bool occurs(GRef &x) const = 0; + virtual void reset() = 0; + virtual bool match(Symbol const &x) = 0; + virtual bool unify(GTerm &x) = 0; + virtual bool unify(GFunctionTerm &x) = 0; + virtual bool unify(GLinearTerm &x) = 0; + virtual bool unify(GVarTerm &x) = 0; + virtual ~GTerm() { } +}; +using UGTermVec = std::vector; +using SGRef = std::shared_ptr; + +// }}} +// {{{ declaration of Term + +struct LinearTerm; +struct VarTerm; +struct ValTerm; +using UTermVec = std::vector; +using UTermVecVec = std::vector; +using VarTermVec = std::vector>; +using VarTermBoundVec = std::vector>; +using VarTermSet = std::unordered_set, value_hash>, value_equal_to>>; + +struct AuxGen { + AuxGen() + : auxNum(std::make_shared(0)) { } + AuxGen(AuxGen const &) = default; + AuxGen(AuxGen &&) = default; + String uniqueName(char const *prefix); + UTerm uniqueVar(Location const &loc, unsigned level, const char *prefix); + + std::shared_ptr auxNum; +}; + +struct SimplifyState { + //! Type that stores for each rewritten DotsTerm the associated variable and the lower and upper bound. + using DotsMap = std::vector>; + using ScriptMap = std::vector>; + SimplifyState(SimplifyState &state) + : gen(state.gen) { } + SimplifyState() { } + SimplifyState(SimplifyState const &) = delete; + SimplifyState(SimplifyState &&) = default; + + std::unique_ptr createDots(Location const &loc, UTerm &&left, UTerm &&right); + std::unique_ptr createScript(Location const &loc, String name, UTermVec &&args); + + DotsMap dots; + ScriptMap scripts; + AuxGen gen; +}; + +struct Term : public Printable, public Hashable, public Locatable, public Comparable, public Clonable { + //! Return value of Term::project (replace, projected, project). + //! replace: projected variables are stripped, null if untouched + //! projected: term with variables renamed, projected if null + //! project: term with variables renamed, never null + using ProjectRet = std::tuple; + using SVal = std::shared_ptr; + using VarSet = std::unordered_set; + using RenameMap = std::unordered_map>; + using ReferenceMap = std::unordered_map, value_equal_to>; + //! Type that stores for each rewritten arithmetic term (UnopTerm, BinopTerm, LuaTerm) the associated variable and the term itself. + //! The indices of the vector correspond to the level of the term. + using ArithmeticsMap = std::vector, value_equal_to>>; + //! The invertibility of a term. This may either be + //! - CONSTANT for terms that do not contain variables, + //! - INVERTIBLE for invertible terms (e.g. -X, 1+X, f(X,Y+Z)) + //! - NOT_INVERTIBLE for terms that are not invertible (e.g. arithmetic operations with two unknowns) + enum Invertibility { CONSTANT = 0, INVERTIBLE = 1, NOT_INVERTIBLE = 2 }; + //! Whether the term contains a VarTerm. + virtual bool hasVar() const = 0; + virtual unsigned projectScore() const = 0; + //! Rename the outermost term. + //! \pre the term must either be a function term or value term holding an identifier. + //! \note unnecessary; can be deleted + virtual void rename(String name) = 0; + //! Removes all occurrences of PoolTerm instances. + //! Returns all unpooled incarnations of the term. + //! \note The term becomes unusable after the method returns. + //! \post The pool does not contain PoolTerm instances. + virtual void unpool(UTermVec &x) const = 0; + //! Somewhat complex result type of simplify. + struct SimplifyRet; + //! Removes all occurrences of DotsTerm instances, simplifies the term and sets the invertibility. + //! To reduce the number of cases in later algorithms moves invertible terms to the left: + //! - 1+X -> X+1 + //! - (1+(1-X)) -> ((-X)+1)+1 + //! Replaces undefined arithmetic operations with 0: + //! - f(X)+0 -> 0 + //! \note The term is unusable if the method returned a non-zero replacement term. + //! \pre Must be called after unpool. + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log) = 0; + //! Removes anonymous variables in projectable positions (in outermost function symbols) from a term. + //! The first element of the return value is a replacement term for the current term, + //! which might be null if the term does not have to be replace.. + //! The second and third can be used to create a projection rule + //! where the second is the head and the third is the body element. + //! \pre Must be called after simplify. + //! \code{.cpp} + //! num = 0; sig = base; lit = q(X,_) + //! (lit', projected, project) = lit.project(&sig, num) + //! assert(lit' == #p_q(base,X,#p)) + //! assert(projected == #p_q(base,#X1,#p)) + //! assert(project == #p_q(base,#X1,#Y2)) + //! \endcode + virtual ProjectRet project(bool rename, AuxGen &gen) = 0; + //! Obtain the type of a term. + //! \pre Must be called after simplify. + //! Whether evaluation of a term is guaranteed to not produce numeric values. + //! This means that the term is either a non-numeric constant or a function symbol. + virtual bool isNotNumeric() const = 0; + virtual bool isNotFunction() const = 0; + //! Obtain the invertibility of a term. + //! \pre Must be called after simplify. + virtual Invertibility getInvertibility() const = 0; + //! Evaluates the term to a value. + //! \pre Must be called after simplify. + virtual Symbol eval(bool &undefined, Logger &log) const = 0; + //! Returns true if the term evaluates to zero. + //! \pre Must be called after simplify. + //! \pre Term is ground or + bool isZero(Logger &log) const; + //! Collects variables in Terms. + //! \pre Must be called after simplify and project to properly account for bound variables. + // TODO: the way I am using these it would be nice to have a visitor for variables + // and implement the functions below using the visitor + virtual void collect(VarTermBoundVec &vars, bool bound) const = 0; + virtual void collect(VarTermSet &vars) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const = 0; + virtual void collectIds(VarSet &vars) const = 0; + //! Returns the nesting level of a term. + //! That is the largest level of a nested variable or zero for ground terms. + //! \pre Must be called after assignLevel. + virtual unsigned getLevel() const = 0; + //! Removes non-invertible arithmetics. + //! \note The term is unusable if the method returned a non-zero replacement term. + //! \pre Must be called after assignLevel. + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined = false) = 0; + virtual bool match(Symbol const &val) const = 0; + bool bind(VarSet &bound); + virtual Sig getSig() const = 0; + virtual UTerm renameVars(RenameMap &names) const = 0; + SGRef _newRef(RenameMap &names, ReferenceMap &refs) const; + UGTerm gterm() const; + virtual UGFunTerm gfunterm(RenameMap &names, ReferenceMap &refs) const; + virtual bool hasPool() const = 0; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const = 0; + virtual UTerm replace(Defines &defs, bool replace) = 0; + virtual double estimate(double size, VarSet const &bound) const = 0; + virtual Symbol isEDB() const = 0; + virtual int toNum(bool &undefined, Logger &log); + virtual bool isAtom() const { return false; } + + virtual ~Term() { } + + //! Inserts a term into arith creating a new unique variable if necessary. + static UTerm insert(ArithmeticsMap &arith, AuxGen &auxGen, UTerm &&term, bool eq = false); + + //! Set dst to src if src is non-zero. + template + static void replace(std::unique_ptr &dst, std::unique_ptr &&src); + template + void replace(std::unique_ptr &dst, std::unique_ptr &&src, std::unique_ptr &&alt); + + //! Unpools a, calling g on each obtained element. + template + static void unpool(A const &a, UnpoolA const &fA, Callback const &g); + //! Unpools a and b, calculates cross product, calling g on each obtained tuple. + template + static void unpool(A const &a, B const &b, UnpoolA const &fA, UnpoolB const &fB, Callback const &g); + //! Iterates of [begin, end] unpooling with f, calculates cross product, calling g on each obtained tuple. + template + static void unpool(It const &begin, It const &end, Unpool const &f, Callback const &g); + //! Unpools each element of vec using f, and move the union of all pools back to f. + template + static void unpoolJoin(Vec &vec, Unpool const &f); +}; + +UTermVec unpool(UTerm const &x); + +struct LinearTerm; +struct Term::SimplifyRet { + enum Type { UNTOUCHED, CONSTANT, LINEAR, REPLACE, UNDEFINED }; + SimplifyRet(SimplifyRet const &) = delete; + SimplifyRet(SimplifyRet &&x); + //! Reference to untouched term. + SimplifyRet(Term &x, bool project); + //! Indicate replacement with linear term. + SimplifyRet(std::unique_ptr &&x); + //! Indicate replacement with arbitrary term. + SimplifyRet(UTerm &&x); + //! Indicate replacement with value. + SimplifyRet(Symbol const &x); + //! Indicate undefined term + SimplifyRet(); + bool notNumeric() const; + bool notFunction() const; + bool constant() const; + bool isZero() const; + bool undefined() const; + LinearTerm &lin(); + SimplifyRet &update(UTerm &x); + ~SimplifyRet(); + Type type; + bool project = false; + union { + Symbol val; + Term *term; + }; +}; + +// }}} + +// {{{ declaration of GRef + +struct GRef { + enum Type { EMPTY, VALUE, TERM }; + GRef(UTerm &&name); + operator bool() const; + void reset(); + GRef &operator=(Symbol const &x); + GRef &operator=(GTerm &x); + bool occurs(GRef &x) const; + bool match(Symbol const &x); + template + bool unify(T &x); + + Type type; + UTerm name; + // Note: these two could be put into a union + Symbol value; + GTerm *term; +}; +using SGRef = std::shared_ptr; + +// }}} +// {{{ declaration of GValTerm + +struct GValTerm : GTerm { + GValTerm(Symbol val); + virtual bool operator==(GTerm const &other) const; + virtual size_t hash() const; + virtual void print(std::ostream &out) const; + virtual Sig sig() const; + virtual EvalResult eval() const; + virtual bool occurs(GRef &x) const; + virtual void reset(); + virtual bool match(Symbol const &x); + virtual bool unify(GTerm &x); + virtual bool unify(GFunctionTerm &x); + virtual bool unify(GLinearTerm &x); + virtual bool unify(GVarTerm &x); + virtual ~GValTerm(); + + Symbol val; +}; + +// }}} +// {{{ declaration of GFunctionTerm + +struct GFunctionTerm : GTerm { + GFunctionTerm(String name, UGTermVec &&args); + GFunctionTerm(GFunctionTerm const &x, bool sign); + virtual bool operator==(GTerm const &other) const; + virtual size_t hash() const; + virtual void print(std::ostream &out) const; + virtual Sig sig() const; + virtual EvalResult eval() const; + virtual bool occurs(GRef &x) const; + virtual void reset(); + virtual bool match(Symbol const &x); + virtual bool unify(GTerm &x); + virtual bool unify(GFunctionTerm &x); + virtual bool unify(GLinearTerm &x); + virtual bool unify(GVarTerm &x); + virtual ~GFunctionTerm(); + + bool sign; + String name; + UGTermVec args; +}; + +// }}} +// {{{ declaration of GLinearTerm + +struct GLinearTerm : GTerm { + GLinearTerm(SGRef ref, int m, int n); + virtual bool operator==(GTerm const &other) const; + virtual size_t hash() const; + virtual void print(std::ostream &out) const; + virtual Sig sig() const; + virtual EvalResult eval() const; + virtual bool occurs(GRef &x) const; + virtual void reset(); + virtual bool match(Symbol const &x); + virtual bool unify(GTerm &x); + virtual bool unify(GFunctionTerm &x); + virtual bool unify(GLinearTerm &x); + virtual bool unify(GVarTerm &x); + virtual ~GLinearTerm(); + + SGRef ref; + int m; + int n; +}; + +// }}} +// {{{ declaration of GVarTerm + +struct GVarTerm : GTerm { + GVarTerm(SGRef ref); + virtual bool operator==(GTerm const &other) const; + virtual size_t hash() const; + virtual void print(std::ostream &out) const; + virtual Sig sig() const; + virtual EvalResult eval() const; + virtual bool occurs(GRef &x) const; + virtual void reset(); + virtual bool match(Symbol const &x); + virtual bool unify(GTerm &x); + virtual bool unify(GFunctionTerm &x); + virtual bool unify(GLinearTerm &x); + virtual bool unify(GVarTerm &x); + virtual ~GVarTerm(); + + SGRef ref; +}; + +// }}} + +// {{{ declaration of PoolTerm + +struct PoolTerm : public Term { + PoolTerm(UTermVec &&terms); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual PoolTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual bool isAtom() const; + virtual ~PoolTerm(); + + UTermVec args; +}; + +// }}} +// {{{ declaration of ValTerm + +struct ValTerm : public Term { + ValTerm(Symbol value); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual ValTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual bool isAtom() const; + virtual ~ValTerm(); + + Symbol value; +}; + +// }}} +// {{{ declaration of VarTerm + +struct VarTerm : Term { + VarTerm(String name, SVal ref, unsigned level = 0, bool bindRef = false); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual VarTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual ~VarTerm(); + + String name; + SVal ref; + bool bindRef; + unsigned level; +}; + +// }}} +// {{{ declaration of UnOpTerm + +struct UnOpTerm : public Term { + UnOpTerm(UnOp op, UTerm &&arg); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual UGFunTerm gfunterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual UnOpTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual bool isAtom() const; + virtual ~UnOpTerm(); + + UnOp const op; + UTerm arg; +}; + +// }}} +// {{{ declaration of BinOpTerm + +struct BinOpTerm : public Term { + BinOpTerm(BinOp op, UTerm &&left, UTerm &&right); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual BinOpTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual ~BinOpTerm(); + + BinOp op; + UTerm left; + UTerm right; +}; + +// }}} +// {{{ declaration of DotsTerm + +struct DotsTerm : public Term { + DotsTerm(UTerm &&left, UTerm &&right); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual DotsTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual ~DotsTerm(); + + UTerm left; + UTerm right; +}; + +// }}} +// {{{ declaration of LuaTerm + +struct LuaTerm : public Term { + LuaTerm(String name, UTermVec &&args); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual LuaTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual ~LuaTerm(); + + String const name; + UTermVec args; +}; + +// }}} +// {{{ declaration of FunctionTerm + +struct FunctionTerm : public Term { + FunctionTerm(String name, UTermVec &&args); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual UGFunTerm gfunterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual FunctionTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual bool isAtom() const; + virtual ~FunctionTerm(); + + String name; + UTermVec args; + mutable SymVec cache; +}; + +// }}} +// {{{ declaration of LinearTerm + +// TODO: if it holds a var it can as well use its location +struct LinearTerm : Term { + using UVarTerm = std::unique_ptr; + LinearTerm(VarTerm const &var, int m, int n); + LinearTerm(UVarTerm &&var, int m, int n); + virtual unsigned projectScore() const; + virtual void rename(String name); + virtual SimplifyRet simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &log); + virtual ProjectRet project(bool rename, AuxGen &gen); + virtual bool hasVar() const; + virtual void collect(VarTermBoundVec &vars, bool bound) const; + virtual void collect(VarSet &vars, unsigned minLevel = 0, unsigned maxLevel = std::numeric_limits::max()) const; + virtual Symbol eval(bool &undefined, Logger &log) const; + virtual bool match(Symbol const &val) const; + virtual Sig getSig() const; + virtual UTerm renameVars(RenameMap &names) const; + virtual UGTerm gterm(RenameMap &names, ReferenceMap &refs) const; + virtual unsigned getLevel() const; + virtual bool isNotNumeric() const; + virtual bool isNotFunction() const; + virtual Invertibility getInvertibility() const; + virtual void print(std::ostream &out) const; + virtual void unpool(UTermVec &x) const; + virtual UTerm rewriteArithmetics(ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined); + virtual bool operator==(Term const &other) const; + virtual size_t hash() const; + virtual LinearTerm *clone() const; + virtual bool hasPool() const; + virtual void collectIds(VarSet &vars) const; + virtual UTerm replace(Defines &defs, bool replace = true); + virtual double estimate(double size, VarSet const &bound) const; + virtual Symbol isEDB() const; + virtual ~LinearTerm(); + + UVarTerm var; + int m; + int n; +}; + +// }}} + +// {{{ definition of Term and auxiliary functions + +// TODO: ugly + +template +void Term::replace(std::unique_ptr &dst, std::unique_ptr &&src) { + if (src) { dst = std::move(src); } +} + +template +void Term::unpool(A const &a, UnpoolA const &fA, Callback const &g) { + for (auto &termA : fA(a)) { g(std::move(termA)); } +} + +template +void Term::unpool(A const &a, B const &b, UnpoolA const &fA, UnpoolB const &fB, Callback const &g) { + auto poolB(fB(b)); + for (auto &termA : fA(a)) { + for (auto &termB : poolB) { g(get_clone(termA), get_clone(termB)); } + } +} + +template +void Term::unpool(It const &begin, It const &end, TermUnpool const &f, Callback const &g) { + using R = decltype(f(*begin)); + std::vector pools; + for (auto it = begin; it != end; ++it) { pools.emplace_back(f(*it)); } + cross_product(pools); + for (auto &pooled : pools) { g(std::move(pooled)); } +} + +template +void Term::unpoolJoin(Vec &vec, TermUnpool const &f) { + Vec join; + for (auto &x : vec) { + auto pool(f(x)); + std::move(pool.begin(), pool.end(), std::back_inserter(join)); + } + vec = std::move(join); +} + +// }}} + +} // namespace Gringo + +GRINGO_HASH(Gringo::Term) +GRINGO_HASH(Gringo::VarTerm) +GRINGO_HASH(Gringo::GTerm) + +#endif // _GRINGO_TERM_HH diff --git a/libgringo/gringo/terms.hh b/libgringo/gringo/terms.hh new file mode 100644 index 0000000..d40fb63 --- /dev/null +++ b/libgringo/gringo/terms.hh @@ -0,0 +1,269 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TERMS_HH +#define _GRINGO_TERMS_HH + +#include +#include +#include +#include +#include +#include + +namespace Gringo { + +using StringVec = std::vector; +template +struct GetName { + using result_type = String; + String operator()(T const &x) const { + return x.name(); + } +}; + +// {{{1 TheoryOpDef + +class TheoryOpDef { +public: + using Key = std::pair; + struct GetKey { + Key operator()(TheoryOpDef const &x) const { + return x.key(); + } + }; +public: + TheoryOpDef(Location const &loc, String op, unsigned priority, TheoryOperatorType type); + TheoryOpDef(TheoryOpDef &&); + ~TheoryOpDef() noexcept; + TheoryOpDef &operator=(TheoryOpDef &&); + String op() const; + Key key() const; + Location const &loc() const; + void print(std::ostream &out) const; + unsigned priority() const; + TheoryOperatorType type() const; +private: + Location loc_; + String op_; + unsigned priority_; + TheoryOperatorType type_; +}; +using TheoryOpDefs = UniqueVec>, EqualToKey>; +inline std::ostream &operator<<(std::ostream &out, TheoryOpDef const &def) { + def.print(out); + return out; +} + +// {{{1 TheoryTermDef + +class TheoryTermDef { +public: + TheoryTermDef(Location const &loc, String name); + TheoryTermDef(TheoryTermDef &&); + ~TheoryTermDef() noexcept; + TheoryTermDef &operator=(TheoryTermDef &&); + void addOpDef(TheoryOpDef &&def, Logger &log); + String name() const; + Location const &loc() const; + void print(std::ostream &out) const; + // returns (priority, flag) where flag is true if the binary operator is left associative + std::pair getPrioAndAssoc(String op) const; + unsigned getPrio(String op, bool unary) const; + bool hasOp(String op, bool unary) const; +private: + Location loc_; + String name_; + TheoryOpDefs opDefs_; +}; +using TheoryTermDefs = UniqueVec>, EqualToKey>>; +inline std::ostream &operator<<(std::ostream &out, TheoryTermDef const &def) { + def.print(out); + return out; +} + +// {{{1 TheoryAtomDef + +class TheoryAtomDef { +public: + using Key = Sig; + struct GetKey { + Key operator()(TheoryAtomDef const &x) const { + return x.sig(); + } + }; +public: + TheoryAtomDef(Location const &loc, String name, unsigned arity, String elemDef, TheoryAtomType type); + TheoryAtomDef(Location const &loc, String name, unsigned arity, String elemDef, TheoryAtomType type, StringVec &&ops, String guardDef); + TheoryAtomDef(TheoryAtomDef &&); + ~TheoryAtomDef() noexcept; + TheoryAtomDef &operator=(TheoryAtomDef &&); + Sig sig() const; + bool hasGuard() const; + TheoryAtomType type() const; + StringVec const &ops() const; + Location const &loc() const; + String elemDef() const; + String guardDef() const; + void print(std::ostream &out) const; +private: + Location loc_; + Sig sig_; + String elemDef_; + String guardDef_; + StringVec ops_; + TheoryAtomType type_; +}; +using TheoryAtomDefs = UniqueVec>, EqualToKey>; +inline std::ostream &operator<<(std::ostream &out, TheoryAtomDef const &def) { + def.print(out); + return out; +} + +// {{{1 TheoryDef + +class TheoryDef { +public: + TheoryDef(Location const &loc, String name); + TheoryDef(TheoryDef &&); + ~TheoryDef() noexcept; + TheoryDef &operator=(TheoryDef &&); + String name() const; + void addAtomDef(TheoryAtomDef &&def, Logger &log); + void addTermDef(TheoryTermDef &&def, Logger &log); + TheoryAtomDef const *getAtomDef(Sig name) const; + TheoryTermDef const *getTermDef(String name) const; + TheoryAtomDefs const &atomDefs() const; + Location const &loc() const; + void print(std::ostream &out) const; +private: + Location loc_; + TheoryTermDefs termDefs_; + TheoryAtomDefs atomDefs_; + String name_; +}; +using TheoryDefs = UniqueVec>, EqualToKey>>; +inline std::ostream &operator<<(std::ostream &out, TheoryDef const &def) { + def.print(out); + return out; +} +// }}}1 + +// {{{1 declaration of CSPMulTerm + +struct CSPMulTerm { + CSPMulTerm(UTerm &&var, UTerm &&coe); + CSPMulTerm(CSPMulTerm &&x); + CSPMulTerm &operator=(CSPMulTerm &&x); + void collect(VarTermBoundVec &vars) const; + void collect(VarTermSet &vars) const; + void replace(Defines &x); + bool operator==(CSPMulTerm const &x) const; + bool simplify(SimplifyState &state, Logger &log); + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen); + size_t hash() const; + bool hasPool() const; + std::vector unpool() const; + ~CSPMulTerm(); + + UTerm var; + UTerm coe; +}; + +std::ostream &operator<<(std::ostream &out, CSPMulTerm const &x); + +template <> +struct clone { + CSPMulTerm operator()(CSPMulTerm const &x) const; +}; + +// {{{1 declaration of CSPAddTerm + +using CSPGroundAdd = std::vector>; +using CSPGroundLit = std::tuple; + +struct CSPAddTerm { + using Terms = std::vector; + + CSPAddTerm(CSPMulTerm &&x); + CSPAddTerm(CSPAddTerm &&x); + CSPAddTerm(Terms &&terms); + CSPAddTerm &operator=(CSPAddTerm &&x); + void append(CSPMulTerm &&x); + bool simplify(SimplifyState &state, Logger &log); + void collect(VarTermBoundVec &vars) const; + void collect(VarTermSet &vars) const; + void replace(Defines &x); + bool operator==(CSPAddTerm const &x) const; + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen); + std::vector unpool() const; + size_t hash() const; + bool hasPool() const; + void toGround(CSPGroundLit &ground, bool invert, Logger &log) const; + bool checkEval(Logger &log) const; + ~CSPAddTerm(); + + Terms terms; +}; + +std::ostream &operator<<(std::ostream &out, CSPAddTerm const &x); + +template <> +struct clone { + CSPAddTerm operator()(CSPAddTerm const &x) const; +}; + +// {{{1 declaration of CSPRelTerm + +struct CSPRelTerm { + CSPRelTerm(CSPRelTerm &&x); + CSPRelTerm(Relation rel, CSPAddTerm &&x); + CSPRelTerm &operator=(CSPRelTerm &&x); + void collect(VarTermBoundVec &vars) const; + void collect(VarTermSet &vars) const; + void replace(Defines &x); + bool operator==(CSPRelTerm const &x) const; + bool simplify(SimplifyState &state, Logger &log); + void rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen); + size_t hash() const; + bool hasPool() const; + std::vector unpool() const; + ~CSPRelTerm(); + + Relation rel; + CSPAddTerm term; +}; + +std::ostream &operator<<(std::ostream &out, CSPRelTerm const &x); + +template <> +struct clone { + CSPRelTerm operator()(CSPRelTerm const &x) const; +}; + +// }}}1 + +} // namespace Gringo + +GRINGO_CALL_HASH(Gringo::CSPRelTerm) +GRINGO_CALL_HASH(Gringo::CSPMulTerm) +GRINGO_CALL_HASH(Gringo::CSPAddTerm) + +#endif // _GRINGO_TERMS_HH diff --git a/libgringo/gringo/types.hh b/libgringo/gringo/types.hh new file mode 100644 index 0000000..f725b45 --- /dev/null +++ b/libgringo/gringo/types.hh @@ -0,0 +1,39 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TYPES_HH +#define _GRINGO_TYPES_HH + +#include +#include + +namespace Gringo { + +struct Scripts; +using Atom_t = Potassco::Atom_t; +using Weight_t = Potassco::Weight_t; +using Lit_t = Potassco::Lit_t; +using Id_t = Potassco::Id_t; + +static constexpr Id_t InvalidId = std::numeric_limits::max(); + +} // namespace Gringo + +#endif // _GRINGO_TYPES_HH diff --git a/libgringo/gringo/utility.hh b/libgringo/gringo/utility.hh new file mode 100644 index 0000000..0bf7b30 --- /dev/null +++ b/libgringo/gringo/utility.hh @@ -0,0 +1,745 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_UTILITY_HH +#define _GRINGO_UTILITY_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Gringo { + +using Potassco::StringSpan; + +// {{{1 declaration of single_owner_ptr + +template +class single_owner_ptr { +public: + single_owner_ptr() + : ptr_(0) { } + explicit single_owner_ptr(T* ptr, bool owner) + : ptr_(uintptr_t(ptr) | (owner && ptr)) { } + single_owner_ptr(single_owner_ptr &&p) + : ptr_(p.ptr_) { + p.release(); + } + single_owner_ptr(std::unique_ptr&& p) + : single_owner_ptr(p.release(), true) { } + single_owner_ptr(const single_owner_ptr&) = delete; + ~single_owner_ptr() { + if (is_owner()) { + delete get(); + } + } + single_owner_ptr& operator=(single_owner_ptr&& p) { + bool owner = p.is_owner(); + reset(p.release(), owner); + return *this; + } + single_owner_ptr& operator=(const single_owner_ptr&) = delete; + bool is_owner() const { + return ptr_ & 1; + } + T* get() const { + return (T*)(ptr_ & ~1); + } + T& operator*() const { + return *get(); + } + T* operator->() const { + return get(); + } + T* release() { + ptr_ = uintptr_t(get()); + return (T*)ptr_; + } + void reset(T* ptr, bool owner) { + if (is_owner() && ptr != get()) { + delete get(); + } + ptr_ = uintptr_t(ptr) | uintptr_t(owner); + } + void swap(single_owner_ptr& p) { + std::swap(ptr_, p.ptr_); + } +private: + uintptr_t ptr_; +}; + +template +single_owner_ptr make_single_owner(Args&& ...args) { + return single_owner_ptr(new T(std::forward(args)...), true); +} + +// {{{ declaration of gringo_make_unique + +template +std::unique_ptr gringo_make_unique(Args&& ...args); + +// {{{1 declaration of helpers to perform comparisons + +template +struct value_equal_to { + bool operator()(T const &a, T const &b) const; +}; + +template +struct value_equal_to { + bool operator()(T const *a, T const *b) const; +}; + +template +struct value_equal_to> { + bool operator()(std::unique_ptr const &a, std::unique_ptr const &b) const; +}; + +template +struct value_equal_to> { + bool operator()(single_owner_ptr const &a, single_owner_ptr const &b) const; +}; + +template +struct value_equal_to> { + bool operator()(std::reference_wrapper const &a, std::reference_wrapper const &b) const; +}; + +template +struct value_equal_to> { + bool operator()(std::pair const &a, std::pair const &b) const; +}; + +template +struct value_equal_to> { + bool operator()(std::tuple const &a, std::tuple const &b) const; +}; + +template +struct value_equal_to> { + bool operator()(std::vector const &a, std::vector const &b) const; +}; + +template +bool is_value_equal_to(T const &a, T const &b); + +// {{{1 declaration of helpers to calculate hashes + +template +T hash_mix(T const &v); + +template +void hash_combine(U& seed, T const &v); + +template +void hash_combine(U& seed, T const &v, H h); + +template +size_t hash_range(T begin, T end); + +template +size_t hash_range(T begin, T end, H h); + +template +struct value_hash { + size_t operator()(T const &x) const; +}; + +template +struct value_hash { + size_t operator()(T const *x) const; +}; + +template +struct value_hash> { + size_t operator()(std::unique_ptr const &p) const; +}; + +template +struct value_hash> { + size_t operator()(single_owner_ptr const &p) const; +}; + +template +struct value_hash> { + size_t operator()(std::reference_wrapper const &x) const; +}; + +template +struct value_hash> { + size_t operator()(std::pair const &v) const; +}; + +template +struct value_hash> { + size_t operator()(std::tuple const &x) const; +}; + +template +struct value_hash> { + size_t operator()(std::vector const &v) const; +}; + +template +inline size_t get_value_hash(T const &x); + +template +inline size_t get_value_hash(T const &x, U const &y, V const &... args); + +inline size_t strhash(char const *x); +inline size_t strhash(StringSpan x); + +// {{{1 declaration of helpers to perform clone copies + +template +struct clone { + T operator()(T const &x) const; +}; + +template +struct clone { + T *operator()(T *x) const; +}; + +template +struct clone> { + std::unique_ptr operator()(std::unique_ptr const &x) const; +}; + +template +struct clone> { + single_owner_ptr operator()(single_owner_ptr const &x) const; +}; + +template +struct clone> { + std::tuple operator()(std::tuple const &x) const; +}; + +template +struct clone> { + std::pair operator()(std::pair const &x) const; +}; + +template +struct clone> { + std::vector operator()(std::vector const &x) const; +}; + +template +T get_clone(T const &x); + +// {{{1 declaration of algorithms + +template +void print_comma(S &out, T const &x, const char *sep, U const &f); + +template +void print_comma(S &out, T const &x, const char *sep); + +template +void cross_product(std::vector> &vec); + +template +void erase_if(Map &m, Pred p); + +template +void sort_unique(T &vec, Less less) { + using E = decltype(*vec.begin()); + std::sort(vec.begin(), vec.end(), less); + vec.erase(std::unique(vec.begin(), vec.end(), [less](E const &a, E const &b) { return !less(a,b) && !less(b,a); }), vec.end()); +} + +template +void sort_unique(T &vec) { + sort_unique(vec, std::less::type>()); +} + +// {{{1 custom streams + +class CountBuf : public std::streambuf { +public: + CountBuf() = default; + size_t count() const { return static_cast(count_); } +protected: + int_type overflow(int_type ch) override { + count_++; + return ch; + } + std::streamsize xsputn(const char_type*, std::streamsize count) override { + count_ += count; + return count; + } +private: + std::streamsize count_ = 0; +}; + +class CountStream : public std::ostream { +public: + CountStream() : std::ostream(&buf_) { + exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); + } + size_t count() const { return buf_.count(); } +private: + CountBuf buf_; +}; + +class ArrayBuf : public std::streambuf { +public: + ArrayBuf(char *begin, size_t size) { + setg(begin, begin, begin + size); + setp(begin, begin + size); + } + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) override { + if (dir == std::ios_base::cur) { off += offset(which); } + else if (dir == std::ios_base::end) { off = size() - off; } + return seekpos(off, which); + } + pos_type seekpos(pos_type off, std::ios_base::openmode which) override { + if (off >= 0 && off <= size()) { + if (which & std::ios_base::in) { gbump(static_cast(off - offset(which))); } + else { pbump(static_cast(off - offset(which))); } + return off; + } + return std::streambuf::seekpos(off, which); + } +private: + off_type size() const { return egptr() - eback(); } + off_type offset(std::ios_base::openmode which) const { + return (which & std::ios_base::out) + ? pptr() - pbase() + : gptr() - eback(); + } +}; + +class ArrayStream : public std::iostream { +public: + ArrayStream(char *begin, size_t size) + : std::iostream(&buf_) + , buf_(begin, size) { + exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); + } +private: + ArrayBuf buf_; +}; + +// }}}1 + +// {{{ definition of gringo_make_unique + +template +std::unique_ptr gringo_make_unique(Args&& ...args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +// }}} +// {{{ definition of helpers to perform comparisons + +template +bool value_equal_to::operator()(T const &a, T const &b) const { + return std::equal_to()(a, b); +} + +template +bool value_equal_to::operator()(T const *a, T const *b) const { + return is_value_equal_to(*a, *b); +} + +template +bool value_equal_to>::operator()(std::unique_ptr const &a, std::unique_ptr const &b) const { + assert(a && b); + return is_value_equal_to(*a, *b); +} + +template +bool value_equal_to>::operator()(single_owner_ptr const &a, single_owner_ptr const &b) const { + assert(a && b); + return is_value_equal_to(*a, *b); +} + +template +bool value_equal_to>::operator()(std::reference_wrapper const &a, std::reference_wrapper const &b) const { + return is_value_equal_to(a.get(), b.get()); +} + +template +bool value_equal_to>::operator()(std::pair const &a, std::pair const &b) const { + return is_value_equal_to(a.first, b.first) && is_value_equal_to(a.second, b.second); +} + +namespace detail { + template + struct equal { + template + bool operator()(std::tuple const &a, std::tuple const &b) const { + return is_value_equal_to(std::get(a), std::get(b)) && equal()(a, b); + } + }; + template <> + struct equal<0> { + template + bool operator()(std::tuple const &, std::tuple const &) const { + return true; + } + }; +} + +template +bool value_equal_to>::operator()(std::tuple const &a, std::tuple const &b) const { + return detail::equal()(a, b); +} + +template +bool value_equal_to>::operator()(std::vector const &a, std::vector const &b) const { + if (a.size() != b.size()) { return false; } + for (auto i = a.begin(), j = b.begin(), end = a.end(); i != end; ++i, ++j) + { + if (!is_value_equal_to(*i, *j)) { return false; } + } + return true; +} + +template +inline bool is_value_equal_to(T const &a, T const &b) { + return value_equal_to()(a, b); +} + +// }}} +// {{{ definition of helpers to calculate hashes + +namespace Detail { + +// Note: the following functions have been taken from MurmurHash3 +// see: https://code.google.com/p/smhasher/ +inline uint32_t hash_mix(uint32_t h) { + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +inline uint64_t hash_mix(uint64_t h) { + h ^= h >> 33; + h *= 0xff51afd7ed558ccd; + h ^= h >> 33; + h *= 0xc4ceb9fe1a85ec53; + h ^= h >> 33; + return h; +} + +template +inline void hash_combine(uint64_t& seed, T const &v, H h) { + seed*= 0x87c37b91114253d5; + seed = (seed >> 31) | (seed << 33); + seed*= 0x4cf5ad432745937f; + seed^= h(v); + seed = (seed >> 27) | (seed << 37); + seed = seed * 5 + 0x52dce729; +} + +template +inline void hash_combine(uint32_t& seed, T const &v, H h) { + seed*= 0xcc9e2d51; + seed = (seed >> 17) | (seed << 15); + seed*= 0x1b873593; + seed^= h(v); + seed = (seed >> 19) | (seed << 13); + seed = seed * 5 + 0xe6546b64; +} + +template struct Select; +template <> struct Select<4> { using Type = uint32_t; }; +template <> struct Select<8> { using Type = uint64_t; }; + +} + +template +void hash_combine(U& seed, T const &v) { + Detail::hash_combine(reinterpret_cast::Type&>(seed), v, std::hash()); +} + +template +void hash_combine(U& seed, T const &v, H h) { + Detail::hash_combine(reinterpret_cast::Type&>(seed), v, h); +} + +template +T hash_mix(T const &v) { + return Detail::hash_mix(static_cast::Type>(v)); +} + +template +size_t hash_range(T begin, T end) { + return hash_range(begin, end, std::hash::type>::type>()); +} + +template +size_t hash_range(T begin, T end, H h) { + size_t seed = 0; + for (auto it = begin; it != end; ++it) { + hash_combine(seed, *it, h); + } + return seed; +} + +template +inline size_t value_hash::operator()(T const &x) const { + return std::hash()(x); +} + +template +size_t value_hash::operator()(T const *x) const { + return get_value_hash(*x); +} + +template +size_t value_hash>::operator()(std::unique_ptr const &p) const { + assert(p); + return get_value_hash(*p); +} + +template +size_t value_hash>::operator()(single_owner_ptr const &p) const { + assert(p); + return get_value_hash(*p); +} + +template +size_t value_hash>::operator()(std::reference_wrapper const &x) const { + return get_value_hash(x.get()); +} + +template +size_t value_hash>::operator()(std::pair const &v) const { + size_t seed = 1; + hash_combine(seed, get_value_hash(v.first)); + hash_combine(seed, get_value_hash(v.second)); + return seed; +} + +namespace detail { + template + struct hash { + template + size_t operator()(std::tuple const &x) const { + size_t seed = get_value_hash(std::get(x)); + hash_combine(seed, hash()(x)); + return seed; + } + }; + template <> + struct hash<0> { + template + size_t operator()(std::tuple const &) const { + return 2; + } + }; +} + +template +inline size_t value_hash>::operator()(std::tuple const &x) const { + return detail::hash()(x); +} + +template +inline size_t value_hash>::operator()(std::vector const &v) const { + size_t seed = 3; + for (auto const &x : v) { + hash_combine(seed, get_value_hash(x)); + } + return seed; +} + +template +inline size_t get_value_hash(T const &x) { + return value_hash()(x); +} + +template +inline size_t get_value_hash(T const &x, U const &y, V const &... args) { + size_t seed = value_hash()(x); + hash_combine(seed, get_value_hash(y, args...)); + return seed; +} + +inline size_t strhash(char const *x) { + size_t seed = 0; + for ( ; *x; ++x) { hash_combine(seed, *x); } + return seed; +} + +inline size_t strhash(StringSpan x) { + size_t seed = 0; + for (auto &c : x) { hash_combine(seed, c); } + return seed; +} + +// }}} +// {{{ definition of helpers to perform clone copies + +template +inline T clone::operator()(T const &x) const { + return x; +} + +template +inline T *clone::operator()(T *x) const { + assert(x); + return x->clone(); +} + +template +inline std::unique_ptr clone>::operator()(std::unique_ptr const &x) const { + T *y(get_clone(x.get())); + assert(x.get() != y); + return std::unique_ptr(y); +} + +template +inline single_owner_ptr clone>::operator()(single_owner_ptr const &x) const { + T *y(get_clone(x.get())); + assert(x.get() != y); + return single_owner_ptr(y, true); +} + +template +inline std::pair clone>::operator()(std::pair const &x) const { + return std::make_pair(get_clone(x.first), get_clone(x.second)); +} + +namespace detail { + template + struct seq { }; + + template + struct gens : gens { }; + + template + struct gens<0, S...> { + typedef seq type; + }; + + template + std::tuple clone(const std::tuple &x, seq) { + return std::tuple { get_clone(std::get(x))... }; + } +} + +template +std::tuple clone>::operator()(std::tuple const &x) const { + return detail::clone(x, typename detail::gens::type()); +} + +template +inline std::vector clone>::operator()(std::vector const &x) const { + std::vector res; + res.reserve(x.size()); + for (auto &y : x) { res.emplace_back(get_clone(y)); } + return res; +} + +template +T get_clone(T const &x) { + return clone()(x); +} + +// }}} +// {{{ definition of algorithms + +template +void print_comma(S &out, T const &x, const char *sep, U const &f) { + using std::begin; + using std::end; + auto it(begin(x)), ie(end(x)); + if (it != ie) { + f(out, *it); + for (++it; it != ie; ++it) { out << sep; f(out, *it); } + } +} + +template +void print_comma(S &out, T const &x, const char *sep) { + using namespace std; + auto it(begin(x)), ie(end(x)); + if (it != ie) { + out << *it; + for (++it; it != ie; ++it) { out << sep << *it; } + } +} + +template +inline void cross_product(std::vector> &vec) { + size_t size = 1; + for (auto &x : vec) { + size_t n = x.size(); + if (n == 0) { + vec.clear(); + return; + } + size *= n; + } + std::vector> res; + res.reserve(size); + res.emplace_back(); + res.back().reserve(vec.size()); + for (auto &x : vec) { + auto it = res.begin(); + for (auto lt = x.begin(), mt = x.end() - 1; lt != mt; ++lt) { + auto jt = it; + it = res.end(); + auto kt = jt; + for (; kt != it; ++kt) { res.emplace_back(get_clone(*kt)); } + for (kt = jt; kt != it - 1; ++kt) { kt->emplace_back(get_clone(*lt)); } + kt->emplace_back(std::move(*lt)); + } + for (auto kt = res.end() - 1; it != kt; ++it) { it->emplace_back(get_clone(x.back())); } + it->emplace_back(std::move(x.back())); + } + vec = std::move(res); +} + +template +void erase_if(Map &m, Pred p) { + using namespace std; + for (auto it = begin(m), ie = end(m); it != ie; ) { + if (p(*it)) { + it = m.erase(it); + } + else { + ++it; + } + } +} + +// }}} + +} // namespace Gringo + +#endif // _GRINGO_UTILITY_HH diff --git a/libgringo/gringo/version.hh b/libgringo/gringo/version.hh new file mode 100644 index 0000000..0e8cad3 --- /dev/null +++ b/libgringo/gringo/version.hh @@ -0,0 +1,29 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_VERSION_HH +#define _GRINGO_VERSION_HH + +#define GRINGO_VERSION "5.1.0" +#define GRINGO_VERSION_MAJOR 5 +#define GRINGO_VERSION_MINOR 1 +#define GRINGO_VERSION_REVISION 0 + +#endif // _GRINGO_VERSION_HH diff --git a/libgringo/src/backend.cc b/libgringo/src/backend.cc new file mode 100644 index 0000000..8b49e8b --- /dev/null +++ b/libgringo/src/backend.cc @@ -0,0 +1,74 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/backend.hh" +#include "potassco/theory_data.h" +#include + +namespace Gringo { + +namespace { + +class TheoryVisitor : public Potassco::TheoryData::Visitor { +public: + TheoryVisitor(Potassco::AbstractProgram &out, GetTheoryAtomCondition &cond) + : out_(out) + , cond_(cond) { } + +private: + void visit(Potassco::TheoryData const &data, Potassco::Id_t termId, Potassco::TheoryTerm const &t) override { + if (addSeen(tSeen_, termId)) { // only visit once + // visit any subterms then print + data.accept(t, *this); + Potassco::print(out_, termId, t); + } + } + void visit(Potassco::TheoryData const &data, Potassco::Id_t elemId, Potassco::TheoryElement const &e) override { + if (addSeen(eSeen_, elemId)) { // only visit once + // visit terms then print element + data.accept(e, *this); + out_.theoryElement(elemId, e.terms(), Potassco::toSpan(cond_(elemId))); + } + } + void visit(Potassco::TheoryData const &data, Potassco::TheoryAtom const &a) override { + // visit elements then print atom + data.accept(a, *this); + Potassco::print(out_, a); + } + bool addSeen(std::vector& vec, Potassco::Id_t id) const { + if (vec.size() <= id) { vec.resize(id + 1, false); } + bool seen = vec[id]; + if (!seen) { vec[id] = true; } + return !seen; + } + Potassco::AbstractProgram &out_; + GetTheoryAtomCondition &cond_; + std::vector tSeen_; + std::vector eSeen_; +}; + +} // namespace + +void output(Potassco::TheoryData const &data, Potassco::AbstractProgram &out, GetTheoryAtomCondition cond) { + TheoryVisitor visitor(out, cond); + data.accept(visitor); +} + +} // namespace Output Gringo diff --git a/libgringo/src/control.cc b/libgringo/src/control.cc new file mode 100644 index 0000000..67c6691 --- /dev/null +++ b/libgringo/src/control.cc @@ -0,0 +1,3792 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + +#include +#include +#include +#include +#include +#ifdef GRINGO_NO_THREAD_LOCAL +# include +# include +#endif + +namespace Gringo { + +// {{{1 error handling + +namespace { + +clingo_solve_result_bitset_t convert(SolveResult r) { + return static_cast(r.satisfiable()) | + static_cast(r.interrupted()) * static_cast(clingo_solve_result_interrupted) | + static_cast(r.exhausted()) * static_cast(clingo_solve_result_exhausted); +} + +template +std::string to_string(S size, P print, Args ...args) { + std::vector ret; + size_t n; + handleCError(size(std::forward(args)..., &n)); + ret.resize(n); + handleCError(print(std::forward(args)..., ret.data(), n)); + return std::string(ret.begin(), ret.end()-1); +} + +template +size_t print_size(F f) { + Gringo::CountStream cs; + f(cs); + cs.flush(); + return cs.count() + 1; +} + +template +void print(char *ret, size_t n, F f) { + Gringo::ArrayStream as(ret, n); + f(as); + as << '\0'; + as.flush(); +} + +#ifndef GRINGO_NO_THREAD_LOCAL + thread_local std::exception_ptr g_lastException; + thread_local std::string g_lastMessage; + thread_local clingo_error_t g_lastCode; +#else + struct TLData { + std::exception_ptr lastException; + std::string lastMessage; + clingo_error_t lastCode; + }; + std::mutex g_tLMut; + std::unordered_map g_tLData; + std::exception_ptr &tLlastException() { + std::lock_guard lock(g_tLMut); + return g_tLData[std::this_thread::get_id()].lastException; + } + std::string &tLlastMessage() { + std::lock_guard lock(g_tLMut); + return g_tLData[std::this_thread::get_id()].lastMessage; + } + clingo_error_t &tLlastCode() { + std::lock_guard lock(g_tLMut); + return g_tLData[std::this_thread::get_id()].lastCode; + } + #define g_lastException (tLlastException()) + #define g_lastMessage (tLlastMessage()) + #define g_lastCode (tLlastCode()) +#endif + +} // namespace + +void handleCError(bool ret, std::exception_ptr *exc) { + if (!ret) { + if (exc && *exc) { std::rethrow_exception(*exc); } + char const *msg = clingo_error_message(); + if (!msg) { msg = "no message"; } + switch (static_cast(clingo_error_code())) { + case clingo_error_runtime: { throw std::runtime_error(msg); } + case clingo_error_logic: { throw std::logic_error(msg); } + case clingo_error_bad_alloc: { throw std::bad_alloc(); } + case clingo_error_unknown: { throw std::logic_error(msg); } + case clingo_error_success: { break; } + } + } +} + +void handleCXXError() { + try { throw; } + catch (Gringo::GringoError const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_runtime; return; } + // Note: a ClingoError is throw after an exception is set or a user error is thrown so either + // - g_lastException is already set, or + // - there was a user error (currently not associated to an error message) + catch (Gringo::ClingoError const &) { return; } + catch (Gringo::MessageLimitError const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_runtime; return; } + catch (std::bad_alloc const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_bad_alloc; return; } + catch (std::runtime_error const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_runtime; return; } + catch (std::logic_error const &) { g_lastException = std::current_exception(); g_lastCode = clingo_error_logic; return; } + g_lastCode = clingo_error_unknown; +} + +// }}}1 + +} // namespace Gringo + +using namespace Gringo; + +namespace Clingo { + +// c++ interface + +// {{{1 signature + +Signature::Signature(char const *name, uint32_t arity, bool positive) { + handleCError(clingo_signature_create(name, arity, positive, &sig_)); +} + +char const *Signature::name() const { + return clingo_signature_name(sig_); +} + +uint32_t Signature::arity() const { + return clingo_signature_arity(sig_); +} + +bool Signature::positive() const { + return clingo_signature_is_positive(sig_); +} + +bool Signature::negative() const { + return clingo_signature_is_negative(sig_); +} + +size_t Signature::hash() const { + return clingo_signature_hash(sig_); +} + +bool operator==(Signature a, Signature b) { return clingo_signature_is_equal_to(a.to_c(), b.to_c()); } +bool operator!=(Signature a, Signature b) { return !clingo_signature_is_equal_to(a.to_c(), b.to_c()); } +bool operator< (Signature a, Signature b) { return clingo_signature_is_less_than(a.to_c(), b.to_c()); } +bool operator<=(Signature a, Signature b) { return !clingo_signature_is_less_than(b.to_c(), a.to_c()); } +bool operator> (Signature a, Signature b) { return clingo_signature_is_less_than(b.to_c(), a.to_c()); } +bool operator>=(Signature a, Signature b) { return !clingo_signature_is_less_than(a.to_c(), b.to_c()); } + +// {{{1 symbol + +Symbol::Symbol() { + clingo_symbol_create_number(0, &sym_); +} + +Symbol::Symbol(clingo_symbol_t sym) +: sym_(sym) { } + +Symbol Number(int num) { + clingo_symbol_t sym; + clingo_symbol_create_number(num, &sym); + return Symbol(sym); +} + +Symbol Supremum() { + clingo_symbol_t sym; + clingo_symbol_create_supremum(&sym); + return Symbol(sym); +} + +Symbol Infimum() { + clingo_symbol_t sym; + clingo_symbol_create_infimum(&sym); + return Symbol(sym); +} + +Symbol String(char const *str) { + clingo_symbol_t sym; + handleCError(clingo_symbol_create_string(str, &sym)); + return Symbol(sym); +} + +Symbol Id(char const *id, bool positive) { + clingo_symbol_t sym; + handleCError(clingo_symbol_create_id(id, positive, &sym)); + return Symbol(sym); +} + +Symbol Function(char const *name, SymbolSpan args, bool positive) { + clingo_symbol_t sym; + handleCError(clingo_symbol_create_function(name, reinterpret_cast(args.begin()), args.size(), positive, &sym)); + return Symbol(sym); +} + +int Symbol::number() const { + int ret; + handleCError(clingo_symbol_number(sym_, &ret)); + return ret; +} + +char const *Symbol::name() const { + char const *ret; + handleCError(clingo_symbol_name(sym_, &ret)); + return ret; +} + +char const *Symbol::string() const { + char const *ret; + handleCError(clingo_symbol_string(sym_, &ret)); + return ret; +} + +bool Symbol::is_positive() const { + bool ret; + handleCError(clingo_symbol_is_positive(sym_, &ret)); + return ret; +} + +bool Symbol::is_negative() const { + bool ret; + handleCError(clingo_symbol_is_negative(sym_, &ret)); + return ret; +} + +SymbolSpan Symbol::arguments() const { + clingo_symbol_t const *ret; + size_t n; + handleCError(clingo_symbol_arguments(sym_, &ret, &n)); + return {reinterpret_cast(ret), n}; +} + +SymbolType Symbol::type() const { + return static_cast(clingo_symbol_type(sym_)); +} + +#define CLINGO_CALLBACK_TRY try +#define CLINGO_CALLBACK_CATCH(ref) catch (...){ (ref) = std::current_exception(); return false; } return true + +std::string Symbol::to_string() const { + return ::to_string(clingo_symbol_to_string_size, clingo_symbol_to_string, sym_); +} + +size_t Symbol::hash() const { + return clingo_symbol_hash(sym_); +} + +std::ostream &operator<<(std::ostream &out, Symbol sym) { + out << sym.to_string(); + return out; +} + +bool operator==(Symbol a, Symbol b) { return clingo_symbol_is_equal_to(a.to_c(), b.to_c()); } +bool operator!=(Symbol a, Symbol b) { return !clingo_symbol_is_equal_to(a.to_c(), b.to_c()); } +bool operator< (Symbol a, Symbol b) { return clingo_symbol_is_less_than(a.to_c(), b.to_c()); } +bool operator<=(Symbol a, Symbol b) { return !clingo_symbol_is_less_than(b.to_c(), a.to_c()); } +bool operator> (Symbol a, Symbol b) { return clingo_symbol_is_less_than(b.to_c(), a.to_c()); } +bool operator>=(Symbol a, Symbol b) { return !clingo_symbol_is_less_than(a.to_c(), b.to_c()); } + +// {{{1 symbolic atoms + +Symbol SymbolicAtom::symbol() const { + clingo_symbol_t ret; + clingo_symbolic_atoms_symbol(atoms_, range_, &ret); + return Symbol(ret); +} + +clingo_literal_t SymbolicAtom::literal() const { + clingo_literal_t ret; + clingo_symbolic_atoms_literal(atoms_, range_, &ret); + return ret; +} + +bool SymbolicAtom::is_fact() const { + bool ret; + clingo_symbolic_atoms_is_fact(atoms_, range_, &ret); + return ret; +} + +bool SymbolicAtom::is_external() const { + bool ret; + clingo_symbolic_atoms_is_external(atoms_, range_, &ret); + return ret; +} + +SymbolicAtomIterator &SymbolicAtomIterator::operator++() { + clingo_symbolic_atom_iterator_t range; + handleCError(clingo_symbolic_atoms_next(atoms_, range_, &range)); + range_ = range; + return *this; +} + +SymbolicAtomIterator::operator bool() const { + bool ret; + handleCError(clingo_symbolic_atoms_is_valid(atoms_, range_, &ret)); + return ret; +} + +bool SymbolicAtomIterator::operator==(SymbolicAtomIterator it) const { + bool ret = atoms_ == it.atoms_; + if (ret) { handleCError(clingo_symbolic_atoms_iterator_is_equal_to(atoms_, range_, it.range_, &ret)); } + return ret; +} + +SymbolicAtomIterator SymbolicAtoms::begin() const { + clingo_symbolic_atom_iterator_t it; + handleCError(clingo_symbolic_atoms_begin(atoms_, nullptr, &it)); + return SymbolicAtomIterator{atoms_, it}; +} + +SymbolicAtomIterator SymbolicAtoms::begin(Signature sig) const { + clingo_symbolic_atom_iterator_t it; + handleCError(clingo_symbolic_atoms_begin(atoms_, &sig.to_c(), &it)); + return SymbolicAtomIterator{atoms_, it}; +} + +SymbolicAtomIterator SymbolicAtoms::end() const { + clingo_symbolic_atom_iterator_t it; + handleCError(clingo_symbolic_atoms_end(atoms_, &it)); + return SymbolicAtomIterator{atoms_, it}; +} + +SymbolicAtomIterator SymbolicAtoms::find(Symbol atom) const { + clingo_symbolic_atom_iterator_t it; + handleCError(clingo_symbolic_atoms_find(atoms_, atom.to_c(), &it)); + return SymbolicAtomIterator{atoms_, it}; +} + +std::vector SymbolicAtoms::signatures() const { + size_t n; + clingo_symbolic_atoms_signatures_size(atoms_, &n); + Signature sig("", 0); + std::vector ret; + ret.resize(n, sig); + handleCError(clingo_symbolic_atoms_signatures(atoms_, reinterpret_cast(ret.data()), n)); + return ret; +} + +size_t SymbolicAtoms::length() const { + size_t ret; + handleCError(clingo_symbolic_atoms_size(atoms_, &ret)); + return ret; +} + +// {{{1 theory atoms + +TheoryTermType TheoryTerm::type() const { + clingo_theory_term_type_t ret; + handleCError(clingo_theory_atoms_term_type(atoms_, id_, &ret)); + return static_cast(ret); +} + +int TheoryTerm::number() const { + int ret; + handleCError(clingo_theory_atoms_term_number(atoms_, id_, &ret)); + return ret; +} + +char const *TheoryTerm::name() const { + char const *ret; + handleCError(clingo_theory_atoms_term_name(atoms_, id_, &ret)); + return ret; +} + +TheoryTermSpan TheoryTerm::arguments() const { + clingo_id_t const *ret; + size_t n; + handleCError(clingo_theory_atoms_term_arguments(atoms_, id_, &ret, &n)); + return {ret, n, ToTheoryIterator{atoms_}}; +} + +std::ostream &operator<<(std::ostream &out, TheoryTerm term) { + out << term.to_string(); + return out; +} + +std::string TheoryTerm::to_string() const { + return ::to_string(clingo_theory_atoms_term_to_string_size, clingo_theory_atoms_term_to_string, atoms_, id_); +} + + +TheoryTermSpan TheoryElement::tuple() const { + clingo_id_t const *ret; + size_t n; + handleCError(clingo_theory_atoms_element_tuple(atoms_, id_, &ret, &n)); + return {ret, n, ToTheoryIterator{atoms_}}; +} + +LiteralSpan TheoryElement::condition() const { + clingo_literal_t const *ret; + size_t n; + handleCError(clingo_theory_atoms_element_condition(atoms_, id_, &ret, &n)); + return {ret, n}; +} + +literal_t TheoryElement::condition_id() const { + clingo_literal_t ret; + handleCError(clingo_theory_atoms_element_condition_id(atoms_, id_, &ret)); + return ret; +} + +std::string TheoryElement::to_string() const { + return ::to_string(clingo_theory_atoms_element_to_string_size, clingo_theory_atoms_element_to_string, atoms_, id_); +} + +std::ostream &operator<<(std::ostream &out, TheoryElement term) { + out << term.to_string(); + return out; +} + +TheoryElementSpan TheoryAtom::elements() const { + clingo_id_t const *ret; + size_t n; + handleCError(clingo_theory_atoms_atom_elements(atoms_, id_, &ret, &n)); + return {ret, n, ToTheoryIterator{atoms_}}; +} + +TheoryTerm TheoryAtom::term() const { + clingo_id_t ret; + handleCError(clingo_theory_atoms_atom_term(atoms_, id_, &ret)); + return TheoryTerm{atoms_, ret}; +} + +bool TheoryAtom::has_guard() const { + bool ret; + handleCError(clingo_theory_atoms_atom_has_guard(atoms_, id_, &ret)); + return ret; +} + +literal_t TheoryAtom::literal() const { + clingo_literal_t ret; + handleCError(clingo_theory_atoms_atom_literal(atoms_, id_, &ret)); + return ret; +} + +std::pair TheoryAtom::guard() const { + char const *name; + clingo_id_t term; + handleCError(clingo_theory_atoms_atom_guard(atoms_, id_, &name, &term)); + return {name, TheoryTerm{atoms_, term}}; +} + +std::string TheoryAtom::to_string() const { + return ::to_string(clingo_theory_atoms_atom_to_string_size, clingo_theory_atoms_atom_to_string, atoms_, id_); +} + +std::ostream &operator<<(std::ostream &out, TheoryAtom term) { + out << term.to_string(); + return out; +} + +TheoryAtomIterator TheoryAtoms::begin() const { + return TheoryAtomIterator{atoms_, 0}; +} + +TheoryAtomIterator TheoryAtoms::end() const { + return TheoryAtomIterator{atoms_, clingo_id_t(size())}; +} + +size_t TheoryAtoms::size() const { + size_t ret; + handleCError(clingo_theory_atoms_size(atoms_, &ret)); + return ret; +} + +// {{{1 assignment + +bool Assignment::has_conflict() const { + return clingo_assignment_has_conflict(ass_); +} + +uint32_t Assignment::decision_level() const { + return clingo_assignment_decision_level(ass_); +} + +bool Assignment::has_literal(literal_t lit) const { + return clingo_assignment_has_literal(ass_, lit); +} + +TruthValue Assignment::truth_value(literal_t lit) const { + clingo_truth_value_t ret; + handleCError(clingo_assignment_truth_value(ass_, lit, &ret)); + return static_cast(ret); +} + +uint32_t Assignment::level(literal_t lit) const { + uint32_t ret; + handleCError(clingo_assignment_level(ass_, lit, &ret)); + return ret; +} + +literal_t Assignment::decision(uint32_t level) const { + literal_t ret; + handleCError(clingo_assignment_decision(ass_, level, &ret)); + return ret; +} + +bool Assignment::is_fixed(literal_t lit) const { + bool ret; + handleCError(clingo_assignment_is_fixed(ass_, lit, &ret)); + return ret; +} + +bool Assignment::is_true(literal_t lit) const { + bool ret; + handleCError(clingo_assignment_is_true(ass_, lit, &ret)); + return ret; +} + +bool Assignment::is_false(literal_t lit) const { + bool ret; + handleCError(clingo_assignment_is_false(ass_, lit, &ret)); + return ret; +} + +// {{{1 propagate init + +literal_t PropagateInit::solver_literal(literal_t lit) const { + literal_t ret; + handleCError(clingo_propagate_init_solver_literal(init_, lit, &ret)); + return ret; +} + +void PropagateInit::add_watch(literal_t lit) { + handleCError(clingo_propagate_init_add_watch(init_, lit)); +} + +int PropagateInit::number_of_threads() const { + return clingo_propagate_init_number_of_threads(init_); +} + +SymbolicAtoms PropagateInit::symbolic_atoms() const { + clingo_symbolic_atoms_t *ret; + handleCError(clingo_propagate_init_symbolic_atoms(init_, &ret)); + return SymbolicAtoms{ret}; +} + +TheoryAtoms PropagateInit::theory_atoms() const { + clingo_theory_atoms_t *ret; + handleCError(clingo_propagate_init_theory_atoms(init_, &ret)); + return TheoryAtoms{ret}; +} + +// {{{1 propagate control + +id_t PropagateControl::thread_id() const { + return clingo_propagate_control_thread_id(ctl_); +} + +Assignment PropagateControl::assignment() const { + return Assignment{clingo_propagate_control_assignment(ctl_)}; +} + +literal_t PropagateControl::add_literal() { + clingo_literal_t ret; + handleCError(clingo_propagate_control_add_literal(ctl_, &ret)); + return ret; +} + +void PropagateControl::add_watch(literal_t literal) { + handleCError(clingo_propagate_control_add_watch(ctl_, literal)); +} + +bool PropagateControl::has_watch(literal_t literal) const { + return clingo_propagate_control_has_watch(ctl_, literal); +} + +void PropagateControl::remove_watch(literal_t literal) { + clingo_propagate_control_remove_watch(ctl_, literal); +} + +bool PropagateControl::add_clause(LiteralSpan clause, ClauseType type) { + bool ret; + handleCError(clingo_propagate_control_add_clause(ctl_, clause.begin(), clause.size(), static_cast(type), &ret)); + return ret; +} + +bool PropagateControl::propagate() { + bool ret; + handleCError(clingo_propagate_control_propagate(ctl_, &ret)); + return ret; +} + +// {{{1 propagator + +void Propagator::init(PropagateInit &) { } +void Propagator::propagate(PropagateControl &, LiteralSpan) { } +void Propagator::undo(PropagateControl const &, LiteralSpan) { } +void Propagator::check(PropagateControl &) { } + +// {{{1 solve control + +void SolveControl::add_clause(SymbolicLiteralSpan clause) { + handleCError(clingo_solve_control_add_clause(ctl_, reinterpret_cast(clause.begin()), clause.size())); +} + +id_t SolveControl::thread_id() const { + id_t ret; + handleCError(clingo_solve_control_thread_id(ctl_, &ret)); + return ret; +} + +// {{{1 model + +Model::Model(clingo_model_t *model) +: model_(model) { } + +bool Model::contains(Symbol atom) const { + bool ret; + handleCError(clingo_model_contains(model_, atom.to_c(), &ret)); + return ret; +} + +CostVector Model::cost() const { + CostVector ret; + size_t n; + handleCError(clingo_model_cost_size(model_, &n)); + ret.resize(n); + handleCError(clingo_model_cost(model_, ret.data(), n)); + return ret; +} + +SymbolVector Model::symbols(ShowType show) const { + SymbolVector ret; + size_t n; + handleCError(clingo_model_symbols_size(model_, show, &n)); + ret.resize(n); + handleCError(clingo_model_symbols(model_, show, reinterpret_cast(ret.data()), n)); + return ret; +} + +uint64_t Model::number() const { + uint64_t ret; + handleCError(clingo_model_number(model_, &ret)); + return ret; +} + +bool Model::optimality_proven() const { + bool ret; + handleCError(clingo_model_optimality_proven(model_, &ret)); + return ret; +} + +SolveControl Model::context() const { + clingo_solve_control_t *ret; + handleCError(clingo_model_context(model_, &ret)); + return SolveControl{ret}; +} + +ModelType Model::type() const { + clingo_model_type_t ret; + handleCError(clingo_model_type(model_, &ret)); + return static_cast(ret); +} + +// {{{1 solve iter + +SolveIteratively::SolveIteratively() +: iter_(nullptr) { } + +SolveIteratively::SolveIteratively(clingo_solve_iteratively_t *it) +: iter_(it) { } + +SolveIteratively::SolveIteratively(SolveIteratively &&it) +: iter_(nullptr) { std::swap(iter_, it.iter_); } + +SolveIteratively &SolveIteratively::operator=(SolveIteratively &&it) { + std::swap(iter_, it.iter_); + return *this; +} + +Model SolveIteratively::next() { + clingo_model_t *m = nullptr; + if (iter_) { handleCError(clingo_solve_iteratively_next(iter_, &m)); } + return Model{m}; +} + +SolveResult SolveIteratively::get() { + clingo_solve_result_bitset_t ret = 0; + if (iter_) { handleCError(clingo_solve_iteratively_get(iter_, &ret)); } + return SolveResult{ret}; +} + +void SolveIteratively::close() { + if (iter_) { + clingo_solve_iteratively_close(iter_); + iter_ = nullptr; + } +} + +// {{{1 solve async + +void SolveAsync::cancel() { + handleCError(clingo_solve_async_cancel(async_)); +} + +SolveResult SolveAsync::get() { + clingo_solve_result_bitset_t ret; + handleCError(clingo_solve_async_get(async_, &ret)); + return SolveResult{ret}; +} + +bool SolveAsync::wait(double timeout) { + bool ret; + handleCError(clingo_solve_async_wait(async_, timeout, &ret)); + return ret; +} + +// {{{1 backend + +void Backend::rule(bool choice, AtomSpan head, LiteralSpan body) { + handleCError(clingo_backend_rule(backend_, choice, head.begin(), head.size(), body.begin(), body.size())); +} + +void Backend::weight_rule(bool choice, AtomSpan head, weight_t lower, WeightedLiteralSpan body) { + handleCError(clingo_backend_weight_rule(backend_, choice, head.begin(), head.size(), lower, reinterpret_cast(body.begin()), body.size())); +} + +void Backend::minimize(weight_t prio, WeightedLiteralSpan body) { + handleCError(clingo_backend_minimize(backend_, prio, reinterpret_cast(body.begin()), body.size())); +} + +void Backend::project(AtomSpan atoms) { + handleCError(clingo_backend_project(backend_, atoms.begin(), atoms.size())); +} + +void Backend::external(atom_t atom, ExternalType type) { + handleCError(clingo_backend_external(backend_, atom, static_cast(type))); +} + +void Backend::assume(LiteralSpan lits) { + handleCError(clingo_backend_assume(backend_, lits.begin(), lits.size())); +} + +void Backend::heuristic(atom_t atom, HeuristicType type, int bias, unsigned priority, LiteralSpan condition) { + handleCError(clingo_backend_heuristic(backend_, atom, static_cast(type), bias, priority, condition.begin(), condition.size())); +} + +void Backend::acyc_edge(int node_u, int node_v, LiteralSpan condition) { + handleCError(clingo_backend_acyc_edge(backend_, node_u, node_v, condition.begin(), condition.size())); +} + +atom_t Backend::add_atom() { + clingo_atom_t ret; + handleCError(clingo_backend_add_atom(backend_, &ret)); + return ret; +} + +// {{{1 statistics + +StatisticsType Statistics::type() const { + clingo_statistics_type_t ret; + handleCError(clingo_statistics_type(stats_, key_, &ret)); + return StatisticsType(ret); +} + +size_t Statistics::size() const { + size_t ret; + handleCError(clingo_statistics_array_size(stats_, key_, &ret)); + return ret; +} + +Statistics Statistics::operator[](size_t index) const { + uint64_t ret; + handleCError(clingo_statistics_array_at(stats_, key_, index, &ret)); + return Statistics{stats_, ret}; +} + +StatisticsArrayIterator Statistics::begin() const { + return StatisticsArrayIterator{this, 0}; +} + +StatisticsArrayIterator Statistics::end() const { + return StatisticsArrayIterator{this, size()}; +} + +Statistics Statistics::operator[](char const *name) const { + uint64_t ret; + handleCError(clingo_statistics_map_at(stats_, key_, name, &ret)); + return Statistics{stats_, ret}; +} + +StatisticsKeyRange Statistics::keys() const { + size_t ret; + handleCError(clingo_statistics_map_size(stats_, key_, &ret)); + return StatisticsKeyRange{ StatisticsKeyIterator{this, 0}, StatisticsKeyIterator{this, ret} }; +} + +double Statistics::value() const { + double ret; + handleCError(clingo_statistics_value_get(stats_, key_, &ret)); + return ret; +} + +char const *Statistics::key_name(size_t index) const { + char const *ret; + handleCError(clingo_statistics_map_subkey_name(stats_, key_, index, &ret)); + return ret; +} + +// {{{1 configuration + +Configuration Configuration::operator[](size_t index) { + unsigned ret; + handleCError(clingo_configuration_array_at(conf_, key_, index, &ret)); + return Configuration{conf_, ret}; +} + +ConfigurationArrayIterator Configuration::begin() { + return ConfigurationArrayIterator{this, 0}; +} + +ConfigurationArrayIterator Configuration::end() { + return ConfigurationArrayIterator{this, size()}; +} + +size_t Configuration::size() const { + size_t n; + handleCError(clingo_configuration_array_size(conf_, key_, &n)); + return n; +} + +bool Configuration::empty() const { + return size() == 0; +} + +Configuration Configuration::operator[](char const *name) { + clingo_id_t ret; + handleCError(clingo_configuration_map_at(conf_, key_, name, &ret)); + return Configuration{conf_, ret}; +} + +ConfigurationKeyRange Configuration::keys() const { + size_t n; + handleCError(clingo_configuration_map_size(conf_, key_, &n)); + return ConfigurationKeyRange{ ConfigurationKeyIterator{this, size_t(0)}, ConfigurationKeyIterator{this, size_t(n)} }; +} + +bool Configuration::is_value() const { + clingo_configuration_type_bitset_t type; + handleCError(clingo_configuration_type(conf_, key_, &type)); + return type & clingo_configuration_type_value; +} + +bool Configuration::is_array() const { + clingo_configuration_type_bitset_t type; + handleCError(clingo_configuration_type(conf_, key_, &type)); + return (type & clingo_configuration_type_array) != 0; +} + +bool Configuration::is_map() const { + clingo_configuration_type_bitset_t type; + handleCError(clingo_configuration_type(conf_, key_, &type)); + return (type & clingo_configuration_type_map) != 0; +} + +bool Configuration::is_assigned() const { + bool ret; + handleCError(clingo_configuration_value_is_assigned(conf_, key_, &ret)); + return ret; +} + +std::string Configuration::value() const { + size_t n; + handleCError(clingo_configuration_value_get_size(conf_, key_, &n)); + std::vector ret(n); + handleCError(clingo_configuration_value_get(conf_, key_, ret.data(), n)); + return std::string(ret.begin(), ret.end() - 1); +} + +Configuration &Configuration::operator=(char const *value) { + handleCError(clingo_configuration_value_set(conf_, key_, value)); + return *this; +} + +char const *Configuration::decription() const { + char const *ret; + handleCError(clingo_configuration_description(conf_, key_, &ret)); + return ret; +} + +char const *Configuration::key_name(size_t index) const { + char const *ret; + handleCError(clingo_configuration_map_subkey_name(conf_, key_, index, &ret)); + return ret; +} + +// {{{1 program builder + +namespace AST { namespace { + +struct ASTToC { + // {{{2 term + + clingo_ast_id_t convId(Id const &id) { + return {id.location, id.id}; + } + + struct TermTag {}; + + clingo_ast_term_t visit(Symbol const &x, TermTag) { + clingo_ast_term_t ret; + ret.type = clingo_ast_term_type_symbol; + ret.symbol = x.to_c(); + return ret; + } + clingo_ast_term_t visit(Variable const &x, TermTag) { + clingo_ast_term_t ret; + ret.type = clingo_ast_term_type_variable; + ret.variable = x.name; + return ret; + } + clingo_ast_term_t visit(UnaryOperation const &x, TermTag) { + auto unary_operation = create_(); + unary_operation->unary_operator = static_cast(x.unary_operator); + unary_operation->argument = convTerm(x.argument); + clingo_ast_term_t ret; + ret.type = clingo_ast_term_type_unary_operation; + ret.unary_operation = unary_operation; + return ret; + } + clingo_ast_term_t visit(BinaryOperation const &x, TermTag) { + auto binary_operation = create_(); + binary_operation->binary_operator = static_cast(x.binary_operator); + binary_operation->left = convTerm(x.left); + binary_operation->right = convTerm(x.right); + clingo_ast_term_t ret; + ret.type = clingo_ast_term_type_binary_operation; + ret.binary_operation = binary_operation; + return ret; + } + clingo_ast_term_t visit(Interval const &x, TermTag) { + auto interval = create_(); + interval->left = convTerm(x.left); + interval->right = convTerm(x.right); + clingo_ast_term_t ret; + ret.type = clingo_ast_term_type_interval; + ret.interval = interval; + return ret; + } + clingo_ast_term_t visit(Function const &x, TermTag) { + auto function = create_(); + function->name = x.name; + function->arguments = convTermVec(x.arguments); + function->size = x.arguments.size(); + clingo_ast_term_t ret; + ret.type = x.external ? clingo_ast_term_type_external_function : clingo_ast_term_type_function; + ret.function = function; + return ret; + } + clingo_ast_term_t visit(Pool const &x, TermTag) { + auto pool = create_(); + pool->arguments = convTermVec(x.arguments); + pool->size = x.arguments.size(); + clingo_ast_term_t ret; + ret.type = clingo_ast_term_type_pool; + ret.pool = pool; + return ret; + } + clingo_ast_term_t convTerm(Term const &x) { + auto ret = x.data.accept(*this, TermTag{}); + ret.location = x.location; + return ret; + } + clingo_ast_term_t *convTerm(Optional const &x) { + return x ? create_(convTerm(*x.get())) : nullptr; + } + clingo_ast_term_t *convTermVec(std::vector const &x) { + return createArray_(x, static_cast(&ASTToC::convTerm)); + } + + clingo_ast_csp_product_term_t convCSPProduct(CSPProduct const &x) { + clingo_ast_csp_product_term_t ret; + ret.location = x.location; + ret.variable = convTerm(x.variable); + ret.coefficient = convTerm(x.coefficient); + return ret; + } + clingo_ast_csp_sum_term_t convCSPAdd(CSPSum const &x) { + clingo_ast_csp_sum_term_t ret; + ret.location = x.location; + ret.terms = createArray_(x.terms, &ASTToC::convCSPProduct); + ret.size = x.terms.size(); + return ret; + } + + clingo_ast_theory_unparsed_term_element_t convTheoryUnparsedTermElement(TheoryUnparsedTermElement const &x) { + clingo_ast_theory_unparsed_term_element_t ret; + ret.term = convTheoryTerm(x.term); + ret.operators = createArray_(x.operators, &ASTToC::identity); + ret.size = x.operators.size(); + return ret; + } + + struct TheoryTermTag { }; + + clingo_ast_theory_term_t visit(Symbol const &term, TheoryTermTag) { + clingo_ast_theory_term_t ret; + ret.type = clingo_ast_theory_term_type_symbol; + ret.symbol = term.to_c(); + return ret; + } + clingo_ast_theory_term_t visit(Variable const &term, TheoryTermTag) { + clingo_ast_theory_term_t ret; + ret.type = clingo_ast_theory_term_type_variable; + ret.variable = term.name; + return ret; + } + clingo_ast_theory_term_t visit(TheoryTermSequence const &term, TheoryTermTag) { + auto sequence = create_(); + sequence->terms = convTheoryTermVec(term.terms); + sequence->size = term.terms.size(); + clingo_ast_theory_term_t ret; + switch (term.type) { + case TheoryTermSequenceType::Set: { ret.type = clingo_ast_theory_term_type_set; break; } + case TheoryTermSequenceType::List: { ret.type = clingo_ast_theory_term_type_list; break; } + case TheoryTermSequenceType::Tuple: { ret.type = clingo_ast_theory_term_type_tuple; break; } + } + ret.set = sequence; + return ret; + } + clingo_ast_theory_term_t visit(TheoryFunction const &term, TheoryTermTag) { + auto function = create_(); + function->name = term.name; + function->arguments = convTheoryTermVec(term.arguments); + function->size = term.arguments.size(); + clingo_ast_theory_term_t ret; + ret.type = clingo_ast_theory_term_type_function; + ret.function = function; + return ret; + } + clingo_ast_theory_term_t visit(TheoryUnparsedTerm const &term, TheoryTermTag) { + auto unparsed_term = create_(); + unparsed_term->elements = createArray_(term.elements, &ASTToC::convTheoryUnparsedTermElement); + unparsed_term->size = term.elements.size(); + clingo_ast_theory_term_t ret; + ret.type = clingo_ast_theory_term_type_unparsed_term; + ret.unparsed_term = unparsed_term; + return ret; + } + clingo_ast_theory_term_t convTheoryTerm(TheoryTerm const &x) { + auto ret = x.data.accept(*this, TheoryTermTag{}); + ret.location = x.location; + return ret; + } + clingo_ast_theory_term_t *convTheoryTermVec(std::vector const &x) { + return createArray_(x, &ASTToC::convTheoryTerm); + } + + // {{{2 literal + + clingo_ast_csp_guard_t convCSPGuard(CSPGuard const &x) { + clingo_ast_csp_guard_t ret; + ret.comparison = static_cast(x.comparison); + ret.term = convCSPAdd(x.term); + return ret; + } + + clingo_ast_literal_t visit(Boolean const &x) { + clingo_ast_literal_t ret; + ret.type = clingo_ast_literal_type_boolean; + ret.boolean = x.value; + return ret; + } + clingo_ast_literal_t visit(Term const &x) { + clingo_ast_literal_t ret; + ret.type = clingo_ast_literal_type_symbolic; + ret.symbol = create_(convTerm(x)); + return ret; + } + clingo_ast_literal_t visit(Comparison const &x) { + auto comparison = create_(); + comparison->comparison = static_cast(x.comparison); + comparison->left = convTerm(x.left); + comparison->right = convTerm(x.right); + clingo_ast_literal_t ret; + ret.type = clingo_ast_literal_type_comparison; + ret.comparison = comparison; + return ret; + } + clingo_ast_literal_t visit(CSPLiteral const &x) { + auto csp = create_(); + csp->term = convCSPAdd(x.term); + csp->guards = createArray_(x.guards, &ASTToC::convCSPGuard); + csp->size = x.guards.size(); + clingo_ast_literal_t ret; + ret.type = clingo_ast_literal_type_csp; + ret.csp_literal = csp; + return ret; + } + clingo_ast_literal_t convLiteral(Literal const &x) { + auto ret = x.data.accept(*this); + ret.sign = static_cast(x.sign); + ret.location = x.location; + return ret; + } + clingo_ast_literal_t *convLiteralVec(std::vector const &x) { + return createArray_(x, &ASTToC::convLiteral); + } + + // {{{2 aggregates + + clingo_ast_aggregate_guard_t *convAggregateGuard(Optional const &guard) { + return guard + ? create_({static_cast(guard->comparison), convTerm(guard->term)}) + : nullptr; + } + + clingo_ast_conditional_literal_t convConditionalLiteral(ConditionalLiteral const &x) { + clingo_ast_conditional_literal_t ret; + ret.literal = convLiteral(x.literal); + ret.condition = convLiteralVec(x.condition); + ret.size = x.condition.size(); + return ret; + } + + clingo_ast_theory_guard_t *convTheoryGuard(Optional const &x) { + return x + ? create_({x->operator_name, convTheoryTerm(x->term)}) + : nullptr; + } + + clingo_ast_theory_atom_element_t convTheoryAtomElement(TheoryAtomElement const &x) { + clingo_ast_theory_atom_element_t ret; + ret.tuple = convTheoryTermVec(x.tuple); + ret.tuple_size = x.tuple.size(); + ret.condition = convLiteralVec(x.condition); + ret.condition_size = x.condition.size(); + return ret; + } + + clingo_ast_body_aggregate_element_t convBodyAggregateElement(BodyAggregateElement const &x) { + clingo_ast_body_aggregate_element_t ret; + ret.tuple = convTermVec(x.tuple); + ret.tuple_size = x.tuple.size(); + ret.condition = convLiteralVec(x.condition); + ret.condition_size = x.condition.size(); + return ret; + } + + clingo_ast_head_aggregate_element_t convHeadAggregateElement(HeadAggregateElement const &x) { + clingo_ast_head_aggregate_element_t ret; + ret.tuple = convTermVec(x.tuple); + ret.tuple_size = x.tuple.size(); + ret.conditional_literal = convConditionalLiteral(x.condition); + return ret; + } + + clingo_ast_aggregate_t convAggregate(Aggregate const &x) { + clingo_ast_aggregate_t ret; + ret.left_guard = convAggregateGuard(x.left_guard); + ret.right_guard = convAggregateGuard(x.right_guard); + ret.size = x.elements.size(); + ret.elements = createArray_(x.elements, &ASTToC::convConditionalLiteral); + return ret; + } + + clingo_ast_theory_atom_t convTheoryAtom(TheoryAtom const &x) { + clingo_ast_theory_atom_t ret; + ret.term = convTerm(x.term); + ret.guard = convTheoryGuard(x.guard); + ret.elements = createArray_(x.elements, &ASTToC::convTheoryAtomElement); + ret.size = x.elements.size(); + return ret; + } + + clingo_ast_disjoint_element_t convDisjointElement(DisjointElement const &x) { + clingo_ast_disjoint_element_t ret; + ret.location = x.location; + ret.tuple = convTermVec(x.tuple); + ret.tuple_size = x.tuple.size(); + ret.term = convCSPAdd(x.term); + ret.condition = convLiteralVec(x.condition); + ret.condition_size = x.condition.size(); + return ret; + } + + // {{{2 head literal + + struct HeadLiteralTag { }; + + clingo_ast_head_literal_t visit(Literal const &x, HeadLiteralTag) { + clingo_ast_head_literal_t ret; + ret.type = clingo_ast_head_literal_type_literal; + ret.literal = create_(convLiteral(x)); + return ret; + } + clingo_ast_head_literal_t visit(Disjunction const &x, HeadLiteralTag) { + auto disjunction = create_(); + disjunction->size = x.elements.size(); + disjunction->elements = createArray_(x.elements, &ASTToC::convConditionalLiteral); + clingo_ast_head_literal_t ret; + ret.type = clingo_ast_head_literal_type_disjunction; + ret.disjunction = disjunction; + return ret; + } + clingo_ast_head_literal_t visit(Aggregate const &x, HeadLiteralTag) { + clingo_ast_head_literal_t ret; + ret.type = clingo_ast_head_literal_type_aggregate; + ret.aggregate = create_(convAggregate(x)); + return ret; + } + clingo_ast_head_literal_t visit(HeadAggregate const &x, HeadLiteralTag) { + auto head_aggregate = create_(); + head_aggregate->left_guard = convAggregateGuard(x.left_guard); + head_aggregate->right_guard = convAggregateGuard(x.right_guard); + head_aggregate->function = static_cast(x.function); + head_aggregate->size = x.elements.size(); + head_aggregate->elements = createArray_(x.elements, &ASTToC::convHeadAggregateElement); + clingo_ast_head_literal_t ret; + ret.type = clingo_ast_head_literal_type_head_aggregate; + ret.head_aggregate = head_aggregate; + return ret; + } + clingo_ast_head_literal_t visit(TheoryAtom const &x, HeadLiteralTag) { + clingo_ast_head_literal_t ret; + ret.type = clingo_ast_head_literal_type_theory_atom; + ret.theory_atom = create_(convTheoryAtom(x)); + return ret; + } + clingo_ast_head_literal_t convHeadLiteral(HeadLiteral const &lit) { + auto ret = lit.data.accept(*this, HeadLiteralTag{}); + ret.location = lit.location; + return ret; + } + + // {{{2 body literal + + struct BodyLiteralTag { }; + + clingo_ast_body_literal_t visit(Literal const &x, BodyLiteralTag) { + clingo_ast_body_literal_t ret; + ret.type = clingo_ast_body_literal_type_literal; + ret.literal = create_(convLiteral(x)); + return ret; + } + clingo_ast_body_literal_t visit(ConditionalLiteral const &x, BodyLiteralTag) { + clingo_ast_body_literal_t ret; + ret.type = clingo_ast_body_literal_type_conditional; + ret.conditional = create_(convConditionalLiteral(x)); + return ret; + } + clingo_ast_body_literal_t visit(Aggregate const &x, BodyLiteralTag) { + clingo_ast_body_literal_t ret; + ret.type = clingo_ast_body_literal_type_aggregate; + ret.aggregate = create_(convAggregate(x)); + return ret; + } + clingo_ast_body_literal_t visit(BodyAggregate const &x, BodyLiteralTag) { + auto body_aggregate = create_(); + body_aggregate->left_guard = convAggregateGuard(x.left_guard); + body_aggregate->right_guard = convAggregateGuard(x.right_guard); + body_aggregate->function = static_cast(x.function); + body_aggregate->size = x.elements.size(); + body_aggregate->elements = createArray_(x.elements, &ASTToC::convBodyAggregateElement); + clingo_ast_body_literal_t ret; + ret.type = clingo_ast_body_literal_type_body_aggregate; + ret.body_aggregate = body_aggregate; + return ret; + } + clingo_ast_body_literal_t visit(TheoryAtom const &x, BodyLiteralTag) { + clingo_ast_body_literal_t ret; + ret.type = clingo_ast_body_literal_type_theory_atom; + ret.theory_atom = create_(convTheoryAtom(x)); + return ret; + } + clingo_ast_body_literal_t visit(Disjoint const &x, BodyLiteralTag) { + auto disjoint = create_(); + disjoint->size = x.elements.size(); + disjoint->elements = createArray_(x.elements, &ASTToC::convDisjointElement); + clingo_ast_body_literal_t ret; + ret.type = clingo_ast_body_literal_type_disjoint; + ret.disjoint = disjoint; + return ret; + } + + clingo_ast_body_literal_t convBodyLiteral(BodyLiteral const &x) { + auto ret = x.data.accept(*this, BodyLiteralTag{}); + ret.sign = static_cast(x.sign); + ret.location = x.location; + return ret; + } + + clingo_ast_body_literal_t* convBodyLiteralVec(std::vector const &x) { + return createArray_(x, &ASTToC::convBodyLiteral); + } + + // {{{2 theory definitions + + clingo_ast_theory_operator_definition_t convTheoryOperatorDefinition(TheoryOperatorDefinition const &x) { + clingo_ast_theory_operator_definition_t ret; + ret.type = static_cast(x.type); + ret.priority = x.priority; + ret.location = x.location; + ret.name = x.name; + return ret; + } + + clingo_ast_theory_term_definition_t convTheoryTermDefinition(TheoryTermDefinition const &x) { + clingo_ast_theory_term_definition_t ret; + ret.name = x.name; + ret.location = x.location; + ret.operators = createArray_(x.operators, &ASTToC::convTheoryOperatorDefinition); + ret.size = x.operators.size(); + return ret; + } + + clingo_ast_theory_guard_definition_t convTheoryGuardDefinition(TheoryGuardDefinition const &x) { + clingo_ast_theory_guard_definition_t ret; + ret.term = x.term; + ret.operators = createArray_(x.operators, &ASTToC::identity); + ret.size = x.operators.size(); + return ret; + } + + clingo_ast_theory_atom_definition_t convTheoryAtomDefinition(TheoryAtomDefinition const &x) { + clingo_ast_theory_atom_definition_t ret; + ret.name = x.name; + ret.arity = x.arity; + ret.location = x.location; + ret.type = static_cast(x.type); + ret.elements = x.elements; + ret.guard = x.guard ? create_(convTheoryGuardDefinition(*x.guard.get())) : nullptr; + return ret; + } + + // {{{2 statement + + clingo_ast_statement_t visit(Rule const &x) { + auto *rule = create_(); + rule->head = convHeadLiteral(x.head); + rule->size = x.body.size(); + rule->body = convBodyLiteralVec(x.body); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_rule; + ret.rule = rule; + return ret; + } + clingo_ast_statement_t visit(Definition const &x) { + auto *definition = create_(); + definition->is_default = x.is_default; + definition->name = x.name; + definition->value = convTerm(x.value); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_const; + ret.definition = definition; + return ret; + } + clingo_ast_statement_t visit(ShowSignature const &x) { + auto *show_signature = create_(); + show_signature->csp = x.csp; + show_signature->signature = x.signature.to_c(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_show_signature; + ret.show_signature = show_signature; + return ret; + } + clingo_ast_statement_t visit(ShowTerm const &x) { + auto *show_term = create_(); + show_term->csp = x.csp; + show_term->term = convTerm(x.term); + show_term->body = convBodyLiteralVec(x.body); + show_term->size = x.body.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_show_term; + ret.show_term = show_term; + return ret; + } + clingo_ast_statement_t visit(Minimize const &x) { + auto *minimize = create_(); + minimize->weight = convTerm(x.weight); + minimize->priority = convTerm(x.priority); + minimize->tuple = convTermVec(x.tuple); + minimize->tuple_size = x.tuple.size(); + minimize->body = convBodyLiteralVec(x.body); + minimize->body_size = x.body.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_minimize; + ret.minimize = minimize; + return ret; + } + clingo_ast_statement_t visit(Script const &x) { + auto *script = create_(); + script->type = static_cast(x.type); + script->code = x.code; + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_script; + ret.script = script; + return ret; + } + clingo_ast_statement_t visit(Program const &x) { + auto *program = create_(); + program->name = x.name; + program->parameters = createArray_(x.parameters, &ASTToC::convId); + program->size = x.parameters.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_program; + ret.program = program; + return ret; + } + clingo_ast_statement_t visit(External const &x) { + auto *external = create_(); + external->atom = convTerm(x.atom); + external->body = convBodyLiteralVec(x.body); + external->size = x.body.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_external; + ret.external = external; + return ret; + } + clingo_ast_statement_t visit(Edge const &x) { + auto *edge = create_(); + edge->u = convTerm(x.u); + edge->v = convTerm(x.v); + edge->body = convBodyLiteralVec(x.body); + edge->size = x.body.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_edge; + ret.edge = edge; + return ret; + } + clingo_ast_statement_t visit(Heuristic const &x) { + auto *heuristic = create_(); + heuristic->atom = convTerm(x.atom); + heuristic->bias = convTerm(x.bias); + heuristic->priority = convTerm(x.priority); + heuristic->modifier = convTerm(x.modifier); + heuristic->body = convBodyLiteralVec(x.body); + heuristic->size = x.body.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_heuristic; + ret.heuristic = heuristic; + return ret; + } + clingo_ast_statement_t visit(ProjectAtom const &x) { + auto *project = create_(); + project->atom = convTerm(x.atom); + project->body = convBodyLiteralVec(x.body); + project->size = x.body.size(); + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_project_atom; + ret.project_atom = project; + return ret; + } + clingo_ast_statement_t visit(ProjectSignature const &x) { + clingo_ast_statement_t ret; + ret.type = clingo_ast_statement_type_project_atom_signature; + ret.project_signature = x.signature.to_c(); + return ret; + } + clingo_ast_statement_t visit(TheoryDefinition const &x) { + auto *theory_definition = create_(); + theory_definition->name = x.name; +theory_definition->terms = createArray_(x.terms, &ASTToC::convTheoryTermDefinition); +theory_definition->terms_size = x.terms.size(); +theory_definition->atoms = createArray_(x.atoms, &ASTToC::convTheoryAtomDefinition); +theory_definition->atoms_size = x.atoms.size(); +clingo_ast_statement_t ret; +ret.type = clingo_ast_statement_type_theory_definition; +ret.theory_definition = theory_definition; +return ret; + } + + // {{{2 aux + + template + T identity(T t) { return t; } + + template + T *create_() { + data_.emplace_back(operator new(sizeof(T))); + return reinterpret_cast(data_.back()); + } + template + T *create_(T x) { + auto *r = create_(); + *r = x; + return r; + } + template + T *createArray_(size_t size) { + arrdata_.emplace_back(operator new[](sizeof(T) * size)); + return reinterpret_cast(arrdata_.back()); + } + template + auto createArray_(std::vector const &vec, F f) -> decltype((this->*f)(std::declval()))* { + using U = decltype((this->*f)(std::declval())); + auto r = createArray_(vec.size()), jt = r; + for (auto it = vec.begin(), ie = vec.end(); it != ie; ++it, ++jt) { *jt = (this->*f)(*it); } + return r; + } + + ~ASTToC() noexcept { + for (auto &x : data_) { operator delete(x); } + for (auto &x : arrdata_) { operator delete[](x); } + data_.clear(); + arrdata_.clear(); + } + + std::vector data_; + std::vector arrdata_; + + // }}}2 +}; + +} } // namespace AST + +void ProgramBuilder::begin() { + handleCError(clingo_program_builder_begin(builder_)); +} + +void ProgramBuilder::add(AST::Statement const &stm) { + AST::ASTToC a; + auto x = stm.data.accept(a); + x.location = stm.location; + handleCError(clingo_program_builder_add(builder_, &x)); +} + +void ProgramBuilder::end() { + handleCError(clingo_program_builder_end(builder_)); +} + +// {{{1 control + +struct Control::Impl { + Impl(Logger logger) + : ctl(nullptr) + , logger(logger) { } + Impl(clingo_control_t *ctl) + : ctl(ctl) { } + ~Impl() noexcept { + if (ctl) { clingo_control_free(ctl); } + } + operator clingo_control_t *() { return ctl; } + clingo_control_t *ctl; + Logger logger; + ModelCallback mh; + FinishCallback fh; +}; + +Control::Control(clingo_control_t *ctl) + : impl_(new Impl(ctl)) { } + +Control::Control(Control &&c) + : impl_(nullptr) { + std::swap(impl_, c.impl_); +} + +Control &Control::operator=(Control &&c) { + delete impl_; + impl_ = nullptr; + std::swap(impl_, c.impl_); + return *this; +} + +Control::~Control() noexcept { + delete impl_; +} + +void Control::add(char const *name, StringSpan params, char const *part) { + handleCError(clingo_control_add(*impl_, name, params.begin(), params.size(), part)); +} + +void Control::ground(PartSpan parts, GroundCallback cb) { + using Data = std::pair; + Data data(cb, nullptr); + handleCError(clingo_control_ground(*impl_, reinterpret_cast(parts.begin()), parts.size(), + [](clingo_location_t loc, char const *name, clingo_symbol_t const *args, size_t n, void *data, clingo_symbol_callback_t *cb, void *cbdata) -> bool { + auto &d = *static_cast(data); + CLINGO_CALLBACK_TRY { + if (d.first) { + struct Ret : std::exception { }; + try { + d.first(Location(loc), name, {reinterpret_cast(args), n}, [cb, cbdata](SymbolSpan symret) { + if (!cb(reinterpret_cast(symret.begin()), symret.size(), cbdata)) { throw Ret(); } + }); + } + catch (Ret e) { return false; } + } + } + CLINGO_CALLBACK_CATCH(d.second); + }, &data), &data.second); +} + +clingo_control_t *Control::to_c() const { return *impl_; } + +SolveResult Control::solve(ModelCallback mh, SymbolicLiteralSpan assumptions) { + clingo_solve_result_bitset_t ret; + using Data = std::pair; + Data data(mh, nullptr); + handleCError(clingo_control_solve(*impl_, [](clingo_model_t *m, void *data, bool *ret) -> bool { + auto &d = *static_cast(data); + CLINGO_CALLBACK_TRY { *ret = !d.first || d.first(Model(m)); } + CLINGO_CALLBACK_CATCH(d.second); + }, &data, reinterpret_cast(assumptions.begin()), assumptions.size(), &ret)); + return SolveResult{ret}; +} + +SolveIteratively Control::solve_iteratively(SymbolicLiteralSpan assumptions) { + clingo_solve_iteratively_t *it; + handleCError(clingo_control_solve_iteratively(*impl_, reinterpret_cast(assumptions.begin()), assumptions.size(), &it)); + return SolveIteratively{it}; +} + +void Control::assign_external(Symbol atom, TruthValue value) { + handleCError(clingo_control_assign_external(*impl_, atom.to_c(), static_cast(value))); +} + +void Control::release_external(Symbol atom) { + handleCError(clingo_control_release_external(*impl_, atom.to_c())); +} + +SymbolicAtoms Control::symbolic_atoms() const { + clingo_symbolic_atoms_t *ret; + handleCError(clingo_control_symbolic_atoms(*impl_, &ret)); + return SymbolicAtoms{ret}; +} + +TheoryAtoms Control::theory_atoms() const { + clingo_theory_atoms_t *ret; + clingo_control_theory_atoms(*impl_, &ret); + return TheoryAtoms{ret}; +} + +namespace { + +// NOTE: this sets exceptions in the running (propagation) thread(s) +// CAVEATS: +// exceptions during propagation are not rethrown +// they are thrown as new exceptions (with the same error message if available) +// clasp gobbles exceptions in the multithreaded case +static bool g_init(clingo_propagate_init_t *ctl, Propagator *p) { + GRINGO_CLINGO_TRY { + PropagateInit pi(ctl); + p->init(pi); + } + GRINGO_CLINGO_CATCH; +} + +static bool g_propagate(clingo_propagate_control_t *ctl, clingo_literal_t const *changes, size_t n, Propagator *p) { + GRINGO_CLINGO_TRY { + PropagateControl pc(ctl); + p->propagate(pc, {changes, n}); + } + GRINGO_CLINGO_CATCH; +} + +static bool g_undo(clingo_propagate_control_t *ctl, clingo_literal_t const *changes, size_t n, Propagator *p) { + GRINGO_CLINGO_TRY { + PropagateControl pc(ctl); + p->undo(pc, {changes, n}); + } + GRINGO_CLINGO_CATCH; +} + +static bool g_check(clingo_propagate_control_t *ctl, Propagator *p) { + GRINGO_CLINGO_TRY { + PropagateControl pc(ctl); + p->check(pc); + } + GRINGO_CLINGO_CATCH; +} + +static clingo_propagator_t g_propagator = { + reinterpret_cast(g_init), + reinterpret_cast(g_propagate), + reinterpret_cast(g_undo), + reinterpret_cast(g_check) +}; + +} + +void Control::register_propagator(Propagator &propagator, bool sequential) { + handleCError(clingo_control_register_propagator(*impl_, g_propagator, &propagator, sequential)); +} + +namespace { + +bool g_init_program(bool incremental, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->init_program(incremental); } + GRINGO_CLINGO_CATCH; +} +bool g_begin_step(GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->begin_step(); } + GRINGO_CLINGO_CATCH; +} +bool g_end_step(GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->end_step(); } + GRINGO_CLINGO_CATCH; +} + +bool g_rule(bool choice, clingo_atom_t const *head, size_t head_size, clingo_literal_t const *body, size_t body_size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->rule(choice, AtomSpan(head, head_size), LiteralSpan(body, body_size)); } + GRINGO_CLINGO_CATCH; +} +bool g_weight_rule(bool choice, clingo_atom_t const *head, size_t head_size, clingo_weight_t lower_bound, clingo_weighted_literal_t const *body, size_t body_size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->weight_rule(choice, AtomSpan(head, head_size), lower_bound, WeightedLiteralSpan(reinterpret_cast(body), body_size)); } + GRINGO_CLINGO_CATCH; +} +bool g_minimize(clingo_weight_t priority, clingo_weighted_literal_t const* literals, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->minimize(priority, WeightedLiteralSpan(reinterpret_cast(literals), size)); } + GRINGO_CLINGO_CATCH; +} +bool g_project(clingo_atom_t const *atoms, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->project(AtomSpan(atoms, size)); } + GRINGO_CLINGO_CATCH; +} +bool g_external(clingo_atom_t atom, clingo_external_type_t type, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->external(atom, static_cast(type)); } + GRINGO_CLINGO_CATCH; +} +bool g_assume(clingo_literal_t const *literals, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->assume(LiteralSpan(literals, size)); } + GRINGO_CLINGO_CATCH; +} +bool g_heuristic(clingo_atom_t atom, clingo_heuristic_type_t type, int bias, unsigned priority, clingo_literal_t const *condition, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->heuristic(atom, static_cast(type), bias, priority, LiteralSpan(condition, size)); } + GRINGO_CLINGO_CATCH; +} +bool g_acyc_edge(int node_u, int node_v, clingo_literal_t const *condition, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->acyc_edge(node_u, node_v, LiteralSpan(condition, size)); } + GRINGO_CLINGO_CATCH; +} + +bool g_theory_term_number(clingo_id_t term_id, int number, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->theory_term_number(term_id, number); } + GRINGO_CLINGO_CATCH; +} +bool g_theory_term_string(clingo_id_t term_id, char const *name, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->theory_term_string(term_id, name); } + GRINGO_CLINGO_CATCH; +} +bool g_theory_term_compound(clingo_id_t term_id, int name_id_or_type, clingo_id_t const *arguments, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->theory_term_compound(term_id, name_id_or_type, IdSpan(arguments, size)); } + GRINGO_CLINGO_CATCH; +} +bool g_theory_element(clingo_id_t element_id, clingo_id_t const *terms, size_t terms_size, clingo_literal_t const *condition, size_t condition_size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->theory_element(element_id, IdSpan(terms, terms_size), LiteralSpan(condition, condition_size)); } + GRINGO_CLINGO_CATCH; +} +bool g_theory_atom(clingo_id_t atom_id_or_zero, clingo_id_t term_id, clingo_id_t const *elements, size_t size, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->theory_atom(atom_id_or_zero, term_id, IdSpan(elements, size)); } + GRINGO_CLINGO_CATCH; +} +bool g_theory_atom_with_guard(clingo_id_t atom_id_or_zero, clingo_id_t term_id, clingo_id_t const *elements, size_t size, clingo_id_t operator_id, clingo_id_t right_hand_side_id, GroundProgramObserver *self) { + GRINGO_CLINGO_TRY { self->theory_atom_with_guard(atom_id_or_zero, term_id, IdSpan(elements, size), operator_id, right_hand_side_id); } + GRINGO_CLINGO_CATCH; +} + +static clingo_ground_program_observer_t g_observer = { + reinterpret_cast(g_init_program), + reinterpret_cast(g_begin_step), + reinterpret_cast(g_end_step), + reinterpret_cast(g_rule), + reinterpret_cast(g_weight_rule), + reinterpret_cast(g_minimize), + reinterpret_cast(g_project), + reinterpret_cast(g_external), + reinterpret_cast(g_assume), + reinterpret_cast(g_heuristic), + reinterpret_cast(g_acyc_edge), + reinterpret_cast(g_theory_term_number), + reinterpret_cast(g_theory_term_string), + reinterpret_cast(g_theory_term_compound), + reinterpret_cast(g_theory_element), + reinterpret_cast(g_theory_atom), + reinterpret_cast(g_theory_atom_with_guard) +}; + +} // namespace + +void Control::register_observer(GroundProgramObserver &observer) { + handleCError(clingo_control_register_observer(*impl_, g_observer, &observer)); +} + +void Control::cleanup() { + handleCError(clingo_control_cleanup(*impl_)); +} + +bool Control::has_const(char const *name) const { + bool ret; + handleCError(clingo_control_has_const(*impl_, name, &ret)); + return ret; +} + +Symbol Control::get_const(char const *name) const { + clingo_symbol_t ret; + handleCError(clingo_control_get_const(*impl_, name, &ret)); + return Symbol(ret); +} + +void Control::interrupt() noexcept { + clingo_control_interrupt(*impl_); +} + +void *Control::claspFacade() { + void *ret; + handleCError(clingo_control_clasp_facade(impl_->ctl, &ret)); + return ret; +} + +void Control::load(char const *file) { + handleCError(clingo_control_load(*impl_, file)); +} + +SolveAsync Control::solve_async(ModelCallback mh, FinishCallback fh, SymbolicLiteralSpan assumptions) { + clingo_solve_async_t *ret; + impl_->mh = std::move(mh); + impl_->fh = std::move(fh); + handleCError(clingo_control_solve_async(*impl_, [](clingo_model_t *m, void *data, bool *ret) -> bool { + GRINGO_CLINGO_TRY { + auto &mh = *static_cast(data); + *ret = !mh || mh(Model{m}); + } + GRINGO_CLINGO_CATCH; + }, &impl_->mh, [](clingo_solve_result_bitset_t res, void *data) -> bool { + GRINGO_CLINGO_TRY { + auto &fh = *static_cast(data); + if (fh) { fh(SolveResult{res}); } + } + GRINGO_CLINGO_CATCH; + }, &impl_->fh, reinterpret_cast(assumptions.begin()), assumptions.size(), &ret)); + return SolveAsync{ret}; +} + +void Control::use_enumeration_assumption(bool value) { + handleCError(clingo_control_use_enumeration_assumption(*impl_, value)); +} + +Backend Control::backend() { + clingo_backend_t *ret; + handleCError(clingo_control_backend(*impl_, &ret)); + return Backend{ret}; +} + +Configuration Control::configuration() { + clingo_configuration_t *conf; + handleCError(clingo_control_configuration(*impl_, &conf)); + unsigned key; + handleCError(clingo_configuration_root(conf, &key)); + return Configuration{conf, key}; +} + +Statistics Control::statistics() const { + clingo_statistics_t *stats; + handleCError(clingo_control_statistics(const_cast(impl_->ctl), &stats)); + uint64_t key; + handleCError(clingo_statistics_root(stats, &key)); + return Statistics{stats, key}; +} + +ProgramBuilder Control::builder() { + clingo_program_builder_t *ret; + handleCError(clingo_control_program_builder(impl_->ctl, &ret)); + return ProgramBuilder{ret}; +} + +// {{{1 global functions + +Symbol parse_term(char const *str, Logger logger, unsigned message_limit) { + clingo_symbol_t ret; + handleCError(clingo_parse_term(str, [](clingo_warning_t code, char const *msg, void *data) { + try { (*static_cast(data))(static_cast(code), msg); } + catch (...) { } + }, &logger, message_limit, &ret)); + return Symbol(ret); +} + +char const *add_string(char const *str) { + char const *ret; + handleCError(clingo_add_string(str, &ret)); + return ret; +} + +namespace AST { + +namespace { + +template +struct PrintWrapper { + T const &vec; + char const *pre; + char const *sep; + char const *post; + bool empty; + friend std::ostream &operator<<(std::ostream &out, PrintWrapper x) { + using namespace std; + auto it = std::begin(x.vec), ie = std::end(x.vec); + if (it != ie) { + out << x.pre; + out << *it; + for (++it; it != ie; ++it) { + out << x.sep << *it; + } + out << x.post; + } + else if (x.empty) { + out << x.pre; + out << x.post; + } + return out; + } +}; + + +template +PrintWrapper print(T const &vec, char const *pre, char const *sep, char const *post, bool empty) { + return {vec, pre, sep, post, empty}; +} + +PrintWrapper> print_body(std::vector const &vec, char const *pre = " : ") { + return print(vec, vec.empty() ? "" : pre, "; ", ".", true); +} + +// {{{2 C -> C++ + +#define ARR(in, out) \ +std::vector conv ## out ## Vec(in const *arr, size_t size) { \ + std::vector ret; \ + for (auto it = arr, ie = arr + size; it != ie; ++it) { \ + ret.emplace_back(conv ## out(*it)); \ + } \ + return ret; \ +} + +// {{{3 terms + +Id convId(clingo_ast_id_t const &id) { + return {Location(id.location), id.id}; +} +ARR(clingo_ast_id_t, Id) + +Term convTerm(clingo_ast_term_t const &term); +ARR(clingo_ast_term_t, Term) + +Term convTerm(clingo_ast_term_t const &term) { + switch (static_cast(term.type)) { + case clingo_ast_term_type_symbol: { + return {Location{term.location}, Symbol{term.symbol}}; + } + case clingo_ast_term_type_variable: { + return {Location{term.location}, Variable{term.variable}}; + } + case clingo_ast_term_type_unary_operation: { + auto &op = *term.unary_operation; + return {Location{term.location}, UnaryOperation{static_cast(op.unary_operator), convTerm(op.argument)}}; + } + case clingo_ast_term_type_binary_operation: { + auto &op = *term.binary_operation; + return {Location{term.location}, BinaryOperation{static_cast(op.binary_operator), convTerm(op.left), convTerm(op.right)}}; + } + case clingo_ast_term_type_interval: { + auto &x = *term.interval; + return {Location{term.location}, Interval{convTerm(x.left), convTerm(x.right)}}; + } + case clingo_ast_term_type_function: { + auto &x = *term.function; + return {Location{term.location}, Function{x.name, convTermVec(x.arguments, x.size), false}}; + } + case clingo_ast_term_type_external_function: { + auto &x = *term.external_function; + return {Location{term.location}, Function{x.name, convTermVec(x.arguments, x.size), true}}; + } + case clingo_ast_term_type_pool: { + auto &x = *term.pool; + return {Location{term.location}, Pool{convTermVec(x.arguments, x.size)}}; + } + } + throw std::logic_error("cannot happen"); +} + +Optional convTerm(clingo_ast_term_t const *term) { + return term ? Optional{convTerm(*term)} : Optional{}; +} + +// csp + +CSPProduct convCSPProduct(clingo_ast_csp_product_term const &term) { + return {Location{term.location}, convTerm(term.coefficient), convTerm(term.variable)}; +} +ARR(clingo_ast_csp_product_term, CSPProduct) + +CSPSum convCSPAdd(clingo_ast_csp_sum_term_t const &term) { + return {Location{term.location}, convCSPProductVec(term.terms, term.size)}; +} + +// theory + +TheoryTerm convTheoryTerm(clingo_ast_theory_term_t const &term); +ARR(clingo_ast_theory_term_t, TheoryTerm) + +TheoryUnparsedTermElement convTheoryUnparsedTermElement(clingo_ast_theory_unparsed_term_element_t const &term) { + return {std::vector{term.operators, term.operators + term.size}, convTheoryTerm(term.term)}; +} +ARR(clingo_ast_theory_unparsed_term_element_t, TheoryUnparsedTermElement) + +TheoryTerm convTheoryTerm(clingo_ast_theory_term_t const &term) { + switch (static_cast(term.type)) { + case clingo_ast_theory_term_type_symbol: { + return {Location{term.location}, Symbol{term.symbol}}; + } + case clingo_ast_theory_term_type_variable: { + return {Location{term.location}, Variable{term.variable}}; + } + case clingo_ast_theory_term_type_list: { + auto &x = *term.list; + return {Location{term.location}, TheoryTermSequence{TheoryTermSequenceType::List, convTheoryTermVec(x.terms, x.size)}}; + } + case clingo_ast_theory_term_type_set: { + auto &x = *term.list; + return {Location{term.location}, TheoryTermSequence{TheoryTermSequenceType::Set, convTheoryTermVec(x.terms, x.size)}}; + } + case clingo_ast_theory_term_type_tuple: { + auto &x = *term.list; + return {Location{term.location}, TheoryTermSequence{TheoryTermSequenceType::Tuple, convTheoryTermVec(x.terms, x.size)}}; + } + case clingo_ast_theory_term_type_function: { + auto &x = *term.function; + return {Location{term.location}, TheoryFunction{x.name, convTheoryTermVec(x.arguments, x.size)}}; + } + case clingo_ast_theory_term_type_unparsed_term: { + auto &x = *term.unparsed_term; + return {Location{term.location}, TheoryUnparsedTerm{convTheoryUnparsedTermElementVec(x.elements, x.size)}}; + } + } + throw std::logic_error("cannot happen"); +} + +// {{{3 literal + +CSPGuard convCSPGuard(clingo_ast_csp_guard_t const &guard) { + return {static_cast(guard.comparison), convCSPAdd(guard.term)}; +} +ARR(clingo_ast_csp_guard_t, CSPGuard) + +Literal convLiteral(clingo_ast_literal_t const &lit) { + switch (static_cast(lit.type)) { + case clingo_ast_literal_type_boolean: { + return {Location(lit.location), static_cast(lit.sign), Boolean{lit.boolean}}; + } + case clingo_ast_literal_type_symbolic: { + return {Location(lit.location), static_cast(lit.sign), convTerm(*lit.symbol)}; + } + case clingo_ast_literal_type_comparison: { + auto &c = *lit.comparison; + return {Location(lit.location), static_cast(lit.sign), Comparison{static_cast(c.comparison), convTerm(c.left), convTerm(c.right)}}; + } + case clingo_ast_literal_type_csp: { + auto &c = *lit.csp_literal; + return {Location(lit.location), static_cast(lit.sign), CSPLiteral{convCSPAdd(c.term), convCSPGuardVec(c.guards, c.size)}}; + } + } + throw std::logic_error("cannot happen"); +} +ARR(clingo_ast_literal_t, Literal) + +// {{{3 aggregates + +Optional convAggregateGuard(clingo_ast_aggregate_guard_t const *guard) { + return guard + ? Optional{AggregateGuard{static_cast(guard->comparison), convTerm(guard->term)}} + : Optional{}; +} + +ConditionalLiteral convConditionalLiteral(clingo_ast_conditional_literal_t const &lit) { + return {convLiteral(lit.literal), convLiteralVec(lit.condition, lit.size)}; +} +ARR(clingo_ast_conditional_literal_t, ConditionalLiteral) + +Aggregate convAggregate(clingo_ast_aggregate_t const &aggr) { + return {convConditionalLiteralVec(aggr.elements, aggr.size), convAggregateGuard(aggr.left_guard), convAggregateGuard(aggr.right_guard)}; +} + +// theory atom + +Optional convTheoryGuard(clingo_ast_theory_guard_t const *guard) { + return guard + ? Optional{TheoryGuard{guard->operator_name, convTheoryTerm(guard->term)}} + : Optional{}; +} + +TheoryAtomElement convTheoryAtomElement(clingo_ast_theory_atom_element_t const &elem) { + return {convTheoryTermVec(elem.tuple, elem.tuple_size), convLiteralVec(elem.condition, elem.condition_size)}; +} +ARR(clingo_ast_theory_atom_element_t, TheoryAtomElement) + +TheoryAtom convTheoryAtom(clingo_ast_theory_atom_t const &atom) { + return {convTerm(atom.term), convTheoryAtomElementVec(atom.elements, atom.size), convTheoryGuard(atom.guard)}; +} + +// disjoint + +DisjointElement convDisjointElement(clingo_ast_disjoint_element_t const &elem) { + return {Location{elem.location}, convTermVec(elem.tuple, elem.tuple_size), convCSPAdd(elem.term), convLiteralVec(elem.condition, elem.condition_size)}; +} +ARR(clingo_ast_disjoint_element_t, DisjointElement) + +// head aggregates + +HeadAggregateElement convHeadAggregateElement(clingo_ast_head_aggregate_element_t const &elem) { + return {convTermVec(elem.tuple, elem.tuple_size), convConditionalLiteral(elem.conditional_literal)}; +} +ARR(clingo_ast_head_aggregate_element_t, HeadAggregateElement) + +// body aggregates + +BodyAggregateElement convBodyAggregateElement(clingo_ast_body_aggregate_element_t const &elem) { + return {convTermVec(elem.tuple, elem.tuple_size), convLiteralVec(elem.condition, elem.condition_size)}; +} +ARR(clingo_ast_body_aggregate_element_t, BodyAggregateElement) + +// {{{3 head literal + +HeadLiteral convHeadLiteral(clingo_ast_head_literal_t const &head) { + switch (static_cast(head.type)) { + case clingo_ast_head_literal_type_literal: { + return {Location{head.location}, convLiteral(*head.literal)}; + } + case clingo_ast_head_literal_type_disjunction: { + auto &d = *head.disjunction; + return {Location{head.location}, Disjunction{convConditionalLiteralVec(d.elements, d.size)}}; + } + case clingo_ast_head_literal_type_aggregate: { + return {Location{head.location}, convAggregate(*head.aggregate)}; + } + case clingo_ast_head_literal_type_head_aggregate: { + auto &a = *head.head_aggregate; + return {Location{head.location}, HeadAggregate{static_cast(a.function), convHeadAggregateElementVec(a.elements, a.size), convAggregateGuard(a.left_guard), convAggregateGuard(a.right_guard)}}; + } + case clingo_ast_head_literal_type_theory_atom: { + return {Location{head.location}, convTheoryAtom(*head.theory_atom)}; + } + } + throw std::logic_error("cannot happen"); +} + +// {{{3 body literal + +BodyLiteral convBodyLiteral(clingo_ast_body_literal_t const &body) { + switch (static_cast(body.type)) { + case clingo_ast_body_literal_type_literal: { + return {Location{body.location}, static_cast(body.sign), convLiteral(*body.literal)}; + } + case clingo_ast_body_literal_type_conditional: { + return {Location{body.location}, static_cast(body.sign), convConditionalLiteral(*body.conditional)}; + } + case clingo_ast_body_literal_type_aggregate: { + return {Location{body.location}, static_cast(body.sign), convAggregate(*body.aggregate)}; + } + case clingo_ast_body_literal_type_body_aggregate: { + auto &a = *body.body_aggregate; + return {Location{body.location}, static_cast(body.sign), BodyAggregate{static_cast(a.function), convBodyAggregateElementVec(a.elements, a.size), convAggregateGuard(a.left_guard), convAggregateGuard(a.right_guard)}}; + } + case clingo_ast_body_literal_type_theory_atom: { + return {Location{body.location}, static_cast(body.sign), convTheoryAtom(*body.theory_atom)}; + } + case clingo_ast_body_literal_type_disjoint: { + auto &d = *body.disjoint; + return {Location{body.location}, static_cast(body.sign), Disjoint{convDisjointElementVec(d.elements, d.size)}}; + } + } + throw std::logic_error("cannot happen"); +} +ARR(clingo_ast_body_literal_t, BodyLiteral) + +// {{{3 statement + +TheoryOperatorDefinition convTheoryOperatorDefinition(clingo_ast_theory_operator_definition_t const &def) { + return {Location{def.location}, def.name, def.priority, static_cast(def.type)}; +} +ARR(clingo_ast_theory_operator_definition_t, TheoryOperatorDefinition) + +Optional convTheoryGuardDefinition(clingo_ast_theory_guard_definition_t const *def) { + return def + ? Optional{def->term, std::vector{def->operators, def->operators + def->size}} + : Optional{}; +} + +TheoryTermDefinition convTheoryTermDefinition(clingo_ast_theory_term_definition_t const &def) { + return {Location{def.location}, def.name, convTheoryOperatorDefinitionVec(def.operators, def.size)}; + std::vector operators; +} +ARR(clingo_ast_theory_term_definition_t, TheoryTermDefinition) + +TheoryAtomDefinition convTheoryAtomDefinition(clingo_ast_theory_atom_definition_t const &def) { + return {Location{def.location}, static_cast(def.type), def.name, def.arity, def.elements, convTheoryGuardDefinition(def.guard)}; +} +ARR(clingo_ast_theory_atom_definition_t, TheoryAtomDefinition) + +void convStatement(clingo_ast_statement_t const *stm, StatementCallback &cb) { + switch (static_cast(stm->type)) { + case clingo_ast_statement_type_rule: { + cb({Location(stm->location), Rule{convHeadLiteral(stm->rule->head), convBodyLiteralVec(stm->rule->body, stm->rule->size)}}); + break; + } + case clingo_ast_statement_type_const: { + cb({Location(stm->location), Definition{stm->definition->name, convTerm(stm->definition->value), stm->definition->is_default}}); + break; + } + case clingo_ast_statement_type_show_signature: { + cb({Location(stm->location), ShowSignature{Signature(stm->show_signature->signature), stm->show_signature->csp}}); + break; + } + case clingo_ast_statement_type_show_term: { + cb({Location(stm->location), ShowTerm{convTerm(stm->show_term->term), convBodyLiteralVec(stm->show_term->body, stm->show_term->size), stm->show_term->csp}}); + break; + } + case clingo_ast_statement_type_minimize: { + auto &min = *stm->minimize; + cb({Location(stm->location), Minimize{convTerm(min.weight), convTerm(min.priority), convTermVec(min.tuple, min.tuple_size), convBodyLiteralVec(min.body, min.body_size)}}); + break; + } + case clingo_ast_statement_type_script: { + cb({Location(stm->location), Script{static_cast(stm->script->type), stm->script->code}}); + break; + } + case clingo_ast_statement_type_program: { + cb({Location(stm->location), Program{stm->program->name, convIdVec(stm->program->parameters, stm->program->size)}}); + break; + } + case clingo_ast_statement_type_external: { + cb({Location(stm->location), External{convTerm(stm->external->atom), convBodyLiteralVec(stm->external->body, stm->external->size)}}); + break; + } + case clingo_ast_statement_type_edge: { + cb({Location(stm->location), Edge{convTerm(stm->edge->u), convTerm(stm->edge->v), convBodyLiteralVec(stm->edge->body, stm->edge->size)}}); + break; + } + case clingo_ast_statement_type_heuristic: { + auto &heu = *stm->heuristic; + cb({Location(stm->location), Heuristic{convTerm(heu.atom), convBodyLiteralVec(heu.body, heu.size), convTerm(heu.bias), convTerm(heu.priority), convTerm(heu.modifier)}}); + break; + } + case clingo_ast_statement_type_project_atom: { + cb({Location(stm->location), ProjectAtom{convTerm(stm->project_atom->atom), convBodyLiteralVec(stm->project_atom->body, stm->project_atom->size)}}); + break; + } + case clingo_ast_statement_type_project_atom_signature: { + cb({Location(stm->location), ProjectSignature{Signature(stm->project_signature)}}); + break; + } + case clingo_ast_statement_type_theory_definition: { + auto &def = *stm->theory_definition; + cb({Location(stm->location), TheoryDefinition{def.name, convTheoryTermDefinitionVec(def.terms, def.terms_size), convTheoryAtomDefinitionVec(def.atoms, def.atoms_size)}}); + break; + } + } +} + +#undef ARR + +// }}}3 + +// }}}2 + +} // namespace + +// {{{2 printing + +// {{{3 statement + +std::ostream &operator<<(std::ostream &out, TheoryDefinition const &x) { + out << "#theory " << x.name << " {\n"; + bool comma = false; + for (auto &y : x.terms) { + if (comma) { out << ";\n"; } + else { comma = true; } + out << " " << y.name << " {\n" << print(y.operators, " ", ";\n", "\n", true) << " }"; + } + for (auto &y : x.atoms) { + if (comma) { out << ";\n"; } + else { comma = true; } + out << " " << y; + } + if (comma) { out << "\n"; } + out << "}."; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryAtomDefinition const &x) { + out << "&" << x.name << "/" << x.arity << " : " << x.elements; + if (x.guard) { out << ", " << *x.guard.get(); } + out << ", " << x.type; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryGuardDefinition const &x) { + out << "{ " << print(x.operators, "", ", ", "", false) << " }, " << x.term; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryTermDefinition const &x) { + out << x.name << " {\n" << print(x.operators, " ", ";\n", "\n", true) << "}"; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryOperatorDefinition const &x) { + out << x.name << " : " << x.priority << ", " << x.type; + return out; +} + +std::ostream &operator<<(std::ostream &out, BodyLiteral const &x) { + out << x.sign << x.data; + return out; +} + +std::ostream &operator<<(std::ostream &out, HeadLiteral const &x) { + out << x.data; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryAtom const &x) { + out << "&" << x.term << " { " << print(x.elements, "", "; ", "", false) << " }"; + if (x.guard) { out << " " << *x.guard.get(); } + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryGuard const &x) { + out << x.operator_name << " " << x.term; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryAtomElement const &x) { + out << print(x.tuple, "", ",", "", false) << " : " << print(x.condition, "", ",", "", false); + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryUnparsedTermElement const &x) { + out << print(x.operators, " ", " ", " ", false) << x.term; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryFunction const &x) { + out << x.name << print(x.arguments, "(", ",", ")", !x.arguments.empty()); + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryTermSequence const &x) { + bool tc = x.terms.size() == 1 && x.type == TheoryTermSequenceType::Tuple; + out << print(x.terms, left_hand_side(x.type), ",", "", true); + if (tc) { out << ",)"; } + else { out << right_hand_side(x.type); } + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryTerm const &x) { + out << x.data; + return out; +} + +std::ostream &operator<<(std::ostream &out, TheoryUnparsedTerm const &x) { + if (x.elements.size() > 1) { out << "("; } + out << print(x.elements, "", "", "", false); + if (x.elements.size() > 1) { out << ")"; } + return out; +} + +std::ostream &operator<<(std::ostream &out, Disjoint const &x) { + out << "#disjoint { " << print(x.elements, "", "; ", "", false) << " }"; + return out; +} + +std::ostream &operator<<(std::ostream &out, DisjointElement const &x) { + out << print(x.tuple, "", ",", "", false) << " : " << x.term << " : " << print(x.condition, "", ",", "", false); + return out; +} + +std::ostream &operator<<(std::ostream &out, Disjunction const &x) { + out << print(x.elements, "", "; ", "", false); + return out; +} + +std::ostream &operator<<(std::ostream &out, HeadAggregate const &x) { + if (x.left_guard) { out << x.left_guard->term << " " << x.left_guard->comparison << " "; } + out << x.function << " { " << print(x.elements, "", "; ", "", false) << " }"; + if (x.right_guard) { out << " " << x.right_guard->comparison << " " << x.right_guard->term; } + return out; +} + +std::ostream &operator<<(std::ostream &out, HeadAggregateElement const &x) { + out << print(x.tuple, "", ",", "", false) << " : " << x.condition; + return out; +} + +std::ostream &operator<<(std::ostream &out, BodyAggregate const &x) { + if (x.left_guard) { out << x.left_guard->term << " " << x.left_guard->comparison << " "; } + out << x.function << " { " << print(x.elements, "", "; ", "", false) << " }"; + if (x.right_guard) { out << " " << x.right_guard->comparison << " " << x.right_guard->term; } + return out; +} + +std::ostream &operator<<(std::ostream &out, BodyAggregateElement const &x) { + out << print(x.tuple, "", ",", "", false) << " : " << print(x.condition, "", ", ", "", false); + return out; +} + +std::ostream &operator<<(std::ostream &out, Aggregate const &x) { + if (x.left_guard) { out << x.left_guard->term << " " << x.left_guard->comparison << " "; } + out << "{ " << print(x.elements, "", "; ", "", false) << " }"; + if (x.right_guard) { out << " " << x.right_guard->comparison << " " << x.right_guard->term; } + return out; +} + +std::ostream &operator<<(std::ostream &out, ConditionalLiteral const &x) { + out << x.literal << print(x.condition, " : ", ", ", "", true); + return out; +} + +std::ostream &operator<<(std::ostream &out, Literal const &x) { + out << x.sign << x.data; + return out; +} + +std::ostream &operator<<(std::ostream &out, Boolean const &x) { + out << (x.value ? "#true" : "#false"); + return out; +} + +std::ostream &operator<<(std::ostream &out, Comparison const &x) { + out << x.left << x.comparison << x.right; + return out; +} + +std::ostream &operator<<(std::ostream &out, Id const &x) { + out << x.id; + return out; +} + +std::ostream &operator<<(std::ostream &out, CSPLiteral const &x) { + out << x.term; + for (auto &y : x.guards) { out << y; } + return out; +} + +std::ostream &operator<<(std::ostream &out, CSPGuard const &x) { + out << "$" << x.comparison << x.term; + return out; +} + +std::ostream &operator<<(std::ostream &out, CSPSum const &x) { + if (x.terms.empty()) { out << "0"; } + else { out << print(x.terms, "", "$+", "", false); } + return out; +} + +std::ostream &operator<<(std::ostream &out, CSPProduct const &x) { + if (x.variable) { out << x.coefficient << "$*$" << *x.variable.get(); } + else { out << x.coefficient; } + return out; +} + +std::ostream &operator<<(std::ostream &out, Pool const &x) { + // NOTE: there is no representation for an empty pool + if (x.arguments.empty()) { out << "(1/0)"; } + else { out << print(x.arguments, "(", ";", ")", true); } + return out; +} + +std::ostream &operator<<(std::ostream &out, Function const &x) { + bool tc = x.name[0] == '\0' && x.arguments.size() == 1; + bool ey = x.name[0] == '\0' || !x.arguments.empty(); + out << (x.external ? "@" : "") << x.name << print(x.arguments, "(", ",", tc ? ",)" : ")", ey); + return out; +} + +std::ostream &operator<<(std::ostream &out, Interval const &x) { + out << "(" << x.left << ".." << x.right << ")"; + return out; +} + +std::ostream &operator<<(std::ostream &out, BinaryOperation const &x) { + out << "(" << x.left << x.binary_operator << x.right << ")"; + return out; +} + +std::ostream &operator<<(std::ostream &out, UnaryOperation const &x) { + out << left_hand_side(x.unary_operator) << x.argument << right_hand_side(x.unary_operator); + return out; +} + +std::ostream &operator<<(std::ostream &out, Variable const &x) { + out << x.name; + return out; +} + +std::ostream &operator<<(std::ostream &out, Term const &x) { + out << x.data; + return out; +} + +std::ostream &operator<<(std::ostream &out, Rule const &x) { + out << x.head << print_body(x.body, " :- "); + return out; +} + +std::ostream &operator<<(std::ostream &out, Definition const &x) { + out << "#const " << x.name << " = " << x.value << "."; + if (x.is_default) { out << " [default]"; } + return out; +} + +std::ostream &operator<<(std::ostream &out, ShowSignature const &x) { + out << "#show " << (x.csp ? "$" : "") << x.signature << "."; + return out; +} + +std::ostream &operator<<(std::ostream &out, ShowTerm const &x) { + out << "#show " << (x.csp ? "$" : "") << x.term << print_body(x.body); + return out; +} + +std::ostream &operator<<(std::ostream &out, Minimize const &x) { + out << print_body(x.body, ":~ ") << " [" << x.weight << "@" << x.priority << print(x.tuple, ",", ",", "", false) << "]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, Script const &x) { + std::string s = x.code; + if (!s.empty() && s.back() == '\n') { + s.back() = '.'; + } + out << s; + return out; +} + +std::ostream &operator<<(std::ostream &out, Program const &x) { + out << "#program " << x.name << print(x.parameters, "(", ",", ")", false) << "."; + return out; +} + +std::ostream &operator<<(std::ostream &out, External const &x) { + out << "#external " << x.atom << print_body(x.body); + return out; +} + +std::ostream &operator<<(std::ostream &out, Edge const &x) { + out << "#edge (" << x.u << "," << x.v << ")" << print_body(x.body); + return out; +} + +std::ostream &operator<<(std::ostream &out, Heuristic const &x) { + out << "#heuristic " << x.atom << print_body(x.body) << " [" << x.bias<< "@" << x.priority << "," << x.modifier << "]"; + return out; +} + +std::ostream &operator<<(std::ostream &out, ProjectAtom const &x) { + out << "#project " << x.atom << print_body(x.body); + return out; +} + +std::ostream &operator<<(std::ostream &out, ProjectSignature const &x) { + out << "#project " << x.signature << "."; + return out; +} + +std::ostream &operator<<(std::ostream &out, Statement const &x) { + out << x.data; + return out; +} +// }}}3 + +// }}}2 + +} // namespace AST + +void parse_program(char const *program, StatementCallback cb, Logger logger, unsigned message_limit) { + using Data = std::pair; + Data data(cb, nullptr); + handleCError(clingo_parse_program(program, [](clingo_ast_statement_t const *stm, void *data) -> bool { + auto &d = *static_cast(data); + CLINGO_CALLBACK_TRY { AST::convStatement(stm, d.first); } + CLINGO_CALLBACK_CATCH(d.second); + }, &data, [](clingo_warning_t code, char const *msg, void *data) { + try { (*static_cast(data))(static_cast(code), msg); } + catch (...) { } + }, &logger, message_limit)); +} + +// }}}1 + +} // namespace Clingo + +// c interface + +// {{{1 error handling + +extern "C" void clingo_set_error(clingo_error_t code, char const *message) { + g_lastCode = code; + try { g_lastException = std::make_exception_ptr(std::runtime_error(message)); } + catch (...) { g_lastException = nullptr; } +} +extern "C" char const *clingo_error_message() { + if (g_lastException) { + try { std::rethrow_exception(g_lastException); } + catch (std::bad_alloc const &) { return "bad_alloc"; } + catch (std::exception const &e) { + g_lastMessage = e.what(); + return g_lastMessage.c_str(); + } + } + return nullptr; +} + +extern "C" clingo_error_t clingo_error_code() { + return g_lastCode; +} + +extern "C" char const *clingo_error_string(clingo_error_t code) { + switch (static_cast(code)) { + case clingo_error_success: { return "success"; } + case clingo_error_runtime: { return "runtime error"; } + case clingo_error_bad_alloc: { return "bad allocation"; } + case clingo_error_logic: { return "logic error"; } + case clingo_error_unknown: { return "unknown error"; } + } + return nullptr; +} + +extern "C" char const *clingo_warning_string(clingo_warning_t code) { + switch (static_cast(code)) { + case clingo_warning_operation_undefined: { return "operation undefined"; } + case clingo_warning_runtime_error: { return "runtime errer"; } + case clingo_warning_atom_undefined: { return "atom undefined"; } + case clingo_warning_file_included: { return "file included"; } + case clingo_warning_variable_unbounded: { return "variable unbounded"; } + case clingo_warning_global_variable: { return "global variable"; } + case clingo_warning_other: { return "other"; } + } + return "unknown message code"; +} + +// {{{1 signature + +extern "C" bool clingo_signature_create(char const *name, uint32_t arity, bool positive, clingo_signature_t *ret) { + GRINGO_CLINGO_TRY { + *ret = Sig(name, arity, !positive).rep(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" char const *clingo_signature_name(clingo_signature_t sig) { + return Sig(sig).name().c_str(); +} + +extern "C" uint32_t clingo_signature_arity(clingo_signature_t sig) { + return Sig(sig).arity(); +} + +extern "C" bool clingo_signature_is_negative(clingo_signature_t sig) { + return Sig(sig).sign(); +} + +extern "C" bool clingo_signature_is_positive(clingo_signature_t sig) { + return !Sig(sig).sign(); +} + +extern "C" size_t clingo_signature_hash(clingo_signature_t sig) { + return Sig(sig).hash(); +} + +extern "C" bool clingo_signature_is_equal_to(clingo_signature_t a, clingo_signature_t b) { + return Sig(a) == Sig(b); +} + +extern "C" bool clingo_signature_is_less_than(clingo_signature_t a, clingo_signature_t b) { + return Sig(a) < Sig(b); +} + + +// {{{1 value + +extern "C" void clingo_symbol_create_number(int num, clingo_symbol_t *val) { + *val = Symbol::createNum(num).rep(); +} + +extern "C" void clingo_symbol_create_supremum(clingo_symbol_t *val) { + *val = Symbol::createSup().rep(); +} + +extern "C" void clingo_symbol_create_infimum(clingo_symbol_t *val) { + *val = Symbol::createInf().rep(); +} + +extern "C" bool clingo_symbol_create_string(char const *str, clingo_symbol_t *val) { + GRINGO_CLINGO_TRY { + *val = Symbol::createStr(str).rep(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_create_id(char const *id, bool positive, clingo_symbol_t *val) { + GRINGO_CLINGO_TRY { + *val = Symbol::createId(id, !positive).rep(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_create_function(char const *name, clingo_symbol_t const *args, size_t n, bool positive, clingo_symbol_t *val) { + GRINGO_CLINGO_TRY { + *val = Symbol::createFun(name, SymSpan{reinterpret_cast(args), n}, !positive).rep(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_number(clingo_symbol_t val, int *num) { + GRINGO_CLINGO_TRY { + clingo_expect(Symbol(val).type() == SymbolType::Num); + *num = Symbol(val).num(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_name(clingo_symbol_t val, char const **name) { + GRINGO_CLINGO_TRY { + clingo_expect(Symbol(val).type() == SymbolType::Fun); + *name = Symbol(val).name().c_str(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_string(clingo_symbol_t val, char const **str) { + GRINGO_CLINGO_TRY { + clingo_expect(Symbol(val).type() == SymbolType::Str); + *str = Symbol(val).string().c_str(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_is_negative(clingo_symbol_t val, bool *sign) { + GRINGO_CLINGO_TRY { + clingo_expect(Symbol(val).type() == SymbolType::Fun); + *sign = Symbol(val).sign(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_is_positive(clingo_symbol_t val, bool *sign) { + GRINGO_CLINGO_TRY { + clingo_expect(Symbol(val).type() == SymbolType::Fun); + *sign = !Symbol(val).sign(); + } GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_arguments(clingo_symbol_t val, clingo_symbol_t const **args, size_t *n) { + GRINGO_CLINGO_TRY { + clingo_expect(Symbol(val).type() == SymbolType::Fun); + auto ret = Symbol(val).args(); + *args = reinterpret_cast(ret.first); + *n = ret.size; + } GRINGO_CLINGO_CATCH; +} + +extern "C" clingo_symbol_type_t clingo_symbol_type(clingo_symbol_t val) { + return static_cast(Symbol(val).type()); +} + +extern "C" bool clingo_symbol_to_string_size(clingo_symbol_t val, size_t *n) { + GRINGO_CLINGO_TRY { *n = print_size([&val](std::ostream &out) { Symbol(val).print(out); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_to_string(clingo_symbol_t val, char *ret, size_t n) { + GRINGO_CLINGO_TRY { print(ret, n, [&val](std::ostream &out) { Symbol(val).print(out); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbol_is_equal_to(clingo_symbol_t a, clingo_symbol_t b) { + return Symbol(a) == Symbol(b); +} + +extern "C" bool clingo_symbol_is_less_than(clingo_symbol_t a, clingo_symbol_t b) { + return Symbol(a) < Symbol(b); +} + +extern "C" size_t clingo_symbol_hash(clingo_symbol_t sym) { + return Symbol(sym).hash(); +} + +// {{{1 symbolic atoms + +extern "C" bool clingo_symbolic_atoms_begin(clingo_symbolic_atoms_t *dom, clingo_signature_t const *sig, clingo_symbolic_atom_iterator_t *ret) { + GRINGO_CLINGO_TRY { *ret = sig ? dom->begin(Sig(*sig)) : dom->begin(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_end(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t *ret) { + GRINGO_CLINGO_TRY { *ret = dom->end(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_find(clingo_symbolic_atoms_t *dom, clingo_symbol_t atom, clingo_symbolic_atom_iterator_t *ret) { + GRINGO_CLINGO_TRY { *ret = dom->lookup(Symbol(atom)); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_iterator_is_equal_to(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t it, clingo_symbolic_atom_iterator_t jt, bool *ret) { + GRINGO_CLINGO_TRY { *ret = dom->eq(it, jt); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_signatures_size(clingo_symbolic_atoms_t *dom, size_t *n) { + GRINGO_CLINGO_TRY { + // TODO: implement matching C++ functions ... + auto sigs = dom->signatures(); + *n = sigs.size(); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_signatures(clingo_symbolic_atoms_t *dom, clingo_signature_t *ret, size_t n) { + GRINGO_CLINGO_TRY { + // TODO: implement matching C++ functions ... + auto sigs = dom->signatures(); + if (n < sigs.size()) { throw std::length_error("not enough space"); } + for (auto &sig : sigs) { *ret++ = sig.rep(); } + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_size(clingo_symbolic_atoms_t *dom, size_t *size) { + GRINGO_CLINGO_TRY { *size = dom->length(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_symbol(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t atm, clingo_symbol_t *sym) { + GRINGO_CLINGO_TRY { *sym = dom->atom(atm).rep(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_literal(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t atm, clingo_literal_t *lit) { + GRINGO_CLINGO_TRY { *lit = dom->literal(atm); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_is_fact(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t atm, bool *fact) { + GRINGO_CLINGO_TRY { *fact = dom->fact(atm); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_is_external(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t atm, bool *external) { + GRINGO_CLINGO_TRY { *external = dom->external(atm); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_next(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t atm, clingo_symbolic_atom_iterator_t *next) { + GRINGO_CLINGO_TRY { *next = dom->next(atm); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_symbolic_atoms_is_valid(clingo_symbolic_atoms_t *dom, clingo_symbolic_atom_iterator_t atm, bool *valid) { + GRINGO_CLINGO_TRY { *valid = dom->valid(atm); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 theory atoms + +extern "C" bool clingo_theory_atoms_term_type(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_theory_term_type_t *ret) { + GRINGO_CLINGO_TRY { *ret = static_cast(atoms->termType(value)); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_term_number(clingo_theory_atoms_t *atoms, clingo_id_t value, int *ret) { + GRINGO_CLINGO_TRY { *ret = atoms->termNum(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_term_name(clingo_theory_atoms_t *atoms, clingo_id_t value, char const **ret) { + GRINGO_CLINGO_TRY { *ret = atoms->termName(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_term_arguments(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_id_t const **ret, size_t *n) { + GRINGO_CLINGO_TRY { + auto span = atoms->termArgs(value); + *ret = span.first; + *n = span.size; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_element_tuple(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_id_t const **ret, size_t *n) { + GRINGO_CLINGO_TRY { + auto span = atoms->elemTuple(value); + *ret = span.first; + *n = span.size; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_element_condition(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_literal_t const **ret, size_t *n) { + GRINGO_CLINGO_TRY { + auto span = atoms->elemCond(value); + *ret = span.first; + *n = span.size; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_element_condition_id(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_literal_t *ret) { + GRINGO_CLINGO_TRY { *ret = atoms->elemCondLit(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_elements(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_id_t const **ret, size_t *n) { + GRINGO_CLINGO_TRY { + auto span = atoms->atomElems(value); + *ret = span.first; + *n = span.size; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_term(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_id_t *ret) { + GRINGO_CLINGO_TRY { *ret = atoms->atomTerm(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_has_guard(clingo_theory_atoms_t *atoms, clingo_id_t value, bool *ret) { + GRINGO_CLINGO_TRY { *ret = atoms->atomHasGuard(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_literal(clingo_theory_atoms_t *atoms, clingo_id_t value, clingo_literal_t *ret) { + GRINGO_CLINGO_TRY { *ret = atoms->atomLit(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_guard(clingo_theory_atoms_t *atoms, clingo_id_t value, char const **ret_op, clingo_id_t *ret_term) { + GRINGO_CLINGO_TRY { + auto guard = atoms->atomGuard(value); + *ret_op = guard.first; + *ret_term = guard.second; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_size(clingo_theory_atoms_t *atoms, size_t *ret) { + GRINGO_CLINGO_TRY { *ret = atoms->numAtoms(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_term_to_string_size(clingo_theory_atoms_t *atoms, clingo_id_t value, size_t *n) { + GRINGO_CLINGO_TRY { *n = print_size([atoms, value](std::ostream &out) { out << atoms->termStr(value); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_term_to_string(clingo_theory_atoms_t *atoms, clingo_id_t value, char *ret, size_t n) { + GRINGO_CLINGO_TRY { print(ret, n, [atoms, value](std::ostream &out) { out << atoms->termStr(value); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_element_to_string_size(clingo_theory_atoms_t *atoms, clingo_id_t value, size_t *n) { + GRINGO_CLINGO_TRY { *n = print_size([atoms, value](std::ostream &out) { out << atoms->elemStr(value); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_element_to_string(clingo_theory_atoms_t *atoms, clingo_id_t value, char *ret, size_t n) { + GRINGO_CLINGO_TRY { print(ret, n, [atoms, value](std::ostream &out) { out << atoms->elemStr(value); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_to_string_size(clingo_theory_atoms_t *atoms, clingo_id_t value, size_t *n) { + GRINGO_CLINGO_TRY { *n = print_size([atoms, value](std::ostream &out) { out << atoms->atomStr(value); }); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_theory_atoms_atom_to_string(clingo_theory_atoms_t *atoms, clingo_id_t value, char *ret, size_t n) { + GRINGO_CLINGO_TRY { print(ret, n, [atoms, value](std::ostream &out) { out << atoms->atomStr(value); }); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 propagate init + +extern "C" bool clingo_propagate_init_solver_literal(clingo_propagate_init_t *init, clingo_literal_t lit, clingo_literal_t *ret) { + GRINGO_CLINGO_TRY { *ret = init->mapLit(lit); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_propagate_init_add_watch(clingo_propagate_init_t *init, clingo_literal_t lit) { + GRINGO_CLINGO_TRY { init->addWatch(lit); } + GRINGO_CLINGO_CATCH; +} + +extern "C" int clingo_propagate_init_number_of_threads(clingo_propagate_init_t *init) { + return init->threads(); +} + +extern "C" bool clingo_propagate_init_symbolic_atoms(clingo_propagate_init_t *init, clingo_symbolic_atoms_t **ret) { + GRINGO_CLINGO_TRY { *ret = &init->getDomain(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_propagate_init_theory_atoms(clingo_propagate_init_t *init, clingo_theory_atoms_t **ret) { + GRINGO_CLINGO_TRY { *ret = const_cast(&init->theory()); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 assignment + +struct clingo_assignment : public Potassco::AbstractAssignment { }; + +extern "C" bool clingo_assignment_has_conflict(clingo_assignment_t *ass) { + return ass->hasConflict(); +} + +extern "C" uint32_t clingo_assignment_decision_level(clingo_assignment_t *ass) { + return ass->level(); +} + +extern "C" bool clingo_assignment_has_literal(clingo_assignment_t *ass, clingo_literal_t lit) { + return ass->hasLit(lit); +} + +extern "C" bool clingo_assignment_truth_value(clingo_assignment_t *ass, clingo_literal_t lit, clingo_truth_value_t *ret) { + GRINGO_CLINGO_TRY { *ret = ass->value(lit); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_assignment_level(clingo_assignment_t *ass, clingo_literal_t lit, uint32_t *ret) { + GRINGO_CLINGO_TRY { *ret = ass->level(lit); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_assignment_decision(clingo_assignment_t *ass, uint32_t level, clingo_literal_t *ret) { + GRINGO_CLINGO_TRY { *ret = ass->decision(level); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_assignment_is_fixed(clingo_assignment_t *ass, clingo_literal_t lit, bool *ret) { + GRINGO_CLINGO_TRY { *ret = ass->isFixed(lit); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_assignment_is_true(clingo_assignment_t *ass, clingo_literal_t lit, bool *ret) { + GRINGO_CLINGO_TRY { *ret = ass->isTrue(lit); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_assignment_is_false(clingo_assignment_t *ass, clingo_literal_t lit, bool *ret) { + GRINGO_CLINGO_TRY { *ret = ass->isFalse(lit); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 propagate control + +struct clingo_propagate_control : Potassco::AbstractSolver { }; + +extern "C" clingo_id_t clingo_propagate_control_thread_id(clingo_propagate_control_t *ctl) { + return ctl->id(); +} + +extern "C" clingo_assignment_t *clingo_propagate_control_assignment(clingo_propagate_control_t *ctl) { + return const_cast(static_cast(&ctl->assignment())); +} + +extern "C" bool clingo_propagate_control_add_clause(clingo_propagate_control_t *ctl, clingo_literal_t const *clause, size_t n, clingo_clause_type_t prop, bool *ret) { + GRINGO_CLINGO_TRY { *ret = ctl->addClause({clause, n}, Potassco::Clause_t(prop)); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_propagate_control_propagate(clingo_propagate_control_t *ctl, bool *ret) { + GRINGO_CLINGO_TRY { *ret = ctl->propagate(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_propagate_control_add_literal(clingo_propagate_control_t *control, clingo_literal_t *result) { + GRINGO_CLINGO_TRY { *result = control->addVariable(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_propagate_control_add_watch(clingo_propagate_control_t *control, clingo_literal_t literal) { + GRINGO_CLINGO_TRY { control->addWatch(literal); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_propagate_control_has_watch(clingo_propagate_control_t *control, clingo_literal_t literal) { + return control->hasWatch(literal); +} + +extern "C" void clingo_propagate_control_remove_watch(clingo_propagate_control_t *control, clingo_literal_t literal) { + control->removeWatch(literal); +} + +// {{{1 model + +struct clingo_solve_control : clingo_model { }; + +extern "C" bool clingo_solve_control_thread_id(clingo_solve_control_t *ctl, clingo_id_t *ret) { + GRINGO_CLINGO_TRY { *ret = ctl->threadId(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_solve_control_add_clause(clingo_solve_control_t *ctl, clingo_symbolic_literal_t const *clause, size_t n) { + GRINGO_CLINGO_TRY { + // TODO: unnecessary copying + Gringo::Model::LitVec lits; + for (auto it = clause, ie = it + n; it != ie; ++it) { lits.emplace_back(Symbol(it->symbol), it->positive); } + ctl->addClause(lits); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_contains(clingo_model_t *m, clingo_symbol_t atom, bool *ret) { + GRINGO_CLINGO_TRY { *ret = m->contains(Symbol(atom)); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_symbols_size(clingo_model_t *m, clingo_show_type_bitset_t show, size_t *n) { + GRINGO_CLINGO_TRY { + // TODO: implement matching C++ functions ... + SymSpan atoms = m->atoms(show); + *n = atoms.size; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_symbols(clingo_model_t *m, clingo_show_type_bitset_t show, clingo_symbol_t *ret, size_t n) { + GRINGO_CLINGO_TRY { + // TODO: implement matching C++ functions ... + SymSpan atoms = m->atoms(show); + if (n < atoms.size) { throw std::length_error("not enough space"); } + for (auto it = atoms.first, ie = it + atoms.size; it != ie; ++it) { *ret++ = it->rep(); } + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_optimality_proven(clingo_model_t *m, bool *proven) { + GRINGO_CLINGO_TRY { *proven = m->optimality_proven(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_cost_size(clingo_model_t *m, size_t *n) { + GRINGO_CLINGO_TRY { + // TODO: implement matching C++ functions ... + auto opt = m->optimization(); + *n = opt.size(); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_cost(clingo_model_t *m, int64_t *ret, size_t n) { + GRINGO_CLINGO_TRY { + // TODO: implement matching C++ functions ... + auto opt = m->optimization(); + if (n < opt.size()) { throw std::length_error("not enough space"); } + std::copy(opt.begin(), opt.end(), ret); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_context(clingo_model_t *m, clingo_solve_control_t **ret) { + GRINGO_CLINGO_TRY { *ret = static_cast(m); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_number(clingo_model_t *m, uint64_t *n) { + GRINGO_CLINGO_TRY { *n = m->number(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_model_type(clingo_model_t *m, clingo_model_type_t *ret) { + GRINGO_CLINGO_TRY { *ret = static_cast(m->type()); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 solve iter + +struct clingo_solve_iteratively : SolveIter { }; + +extern "C" bool clingo_solve_iteratively_next(clingo_solve_iteratively_t *it, clingo_model **m) { + GRINGO_CLINGO_TRY { *m = static_cast(const_cast(it->next())); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_solve_iteratively_get(clingo_solve_iteratively_t *it, clingo_solve_result_bitset_t *ret) { + GRINGO_CLINGO_TRY { *ret = convert(it->get().satisfiable()); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_solve_iteratively_close(clingo_solve_iteratively_t *it) { + GRINGO_CLINGO_TRY { it->close(); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 solve async + +struct clingo_solve_async : SolveFuture { }; + +extern "C" bool clingo_solve_async_cancel(clingo_solve_async_t *async) { + GRINGO_CLINGO_TRY { async->cancel(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_solve_async_get(clingo_solve_async_t *async, clingo_solve_result_bitset_t *ret) { + GRINGO_CLINGO_TRY { *ret = async->get(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_solve_async_wait(clingo_solve_async_t *async, double timeout, bool *ret) { + GRINGO_CLINGO_TRY { *ret = async->wait(timeout); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 configuration + +struct clingo_configuration : ConfigProxy { }; + +extern "C" bool clingo_configuration_type(clingo_configuration_t *conf, clingo_id_t key, clingo_configuration_type_bitset_t *ret) { + GRINGO_CLINGO_TRY { + int map_size, array_size, value_size; + conf->getKeyInfo(key, &map_size, &array_size, nullptr, &value_size); + *ret = 0; + if (map_size >= 0) { *ret |= clingo_configuration_type_map; } + if (array_size >= 0) { *ret |= clingo_configuration_type_array; } + if (value_size >= 0) { *ret |= clingo_configuration_type_value; } + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_map_at(clingo_configuration_t *conf, clingo_id_t key, char const *name, clingo_id_t* subkey) { + GRINGO_CLINGO_TRY { *subkey = conf->getSubKey(key, name); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_map_subkey_name(clingo_configuration_t *conf, clingo_id_t key, size_t index, char const **name) { + GRINGO_CLINGO_TRY { *name = conf->getSubKeyName(key, index); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_map_size(clingo_configuration_t *conf, clingo_id_t key, size_t* ret) { + GRINGO_CLINGO_TRY { + int n; + conf->getKeyInfo(key, &n, nullptr, nullptr, nullptr); + if (n < 0) { throw std::runtime_error("not an array"); } + *ret = n; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_array_at(clingo_configuration_t *conf, clingo_id_t key, size_t idx, clingo_id_t *ret) { + GRINGO_CLINGO_TRY { *ret = conf->getArrKey(key, idx); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_array_size(clingo_configuration_t *conf, clingo_id_t key, size_t *ret) { + GRINGO_CLINGO_TRY { + int n; + conf->getKeyInfo(key, nullptr, &n, nullptr, nullptr); + if (n < 0) { throw std::runtime_error("not an array"); } + *ret = n; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_root(clingo_configuration_t *conf, clingo_id_t *ret) { + GRINGO_CLINGO_TRY { *ret = conf->getRootKey(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_description(clingo_configuration_t *conf, clingo_id_t key, char const **ret) { + GRINGO_CLINGO_TRY { + conf->getKeyInfo(key, nullptr, nullptr, ret, nullptr); + if (!ret) { throw std::runtime_error("no description"); } + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_value_get_size(clingo_configuration_t *conf, clingo_id_t key, size_t *n) { + GRINGO_CLINGO_TRY { + std::string value; + conf->getKeyValue(key, value); + *n = value.size() + 1; + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_value_get(clingo_configuration_t *conf, clingo_id_t key, char *ret, size_t n) { + GRINGO_CLINGO_TRY { + std::string value; + conf->getKeyValue(key, value); + if (n < value.size() + 1) { throw std::length_error("not enough space"); } + std::strcpy(ret, value.c_str()); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_value_set(clingo_configuration_t *conf, clingo_id_t key, const char *val) { + GRINGO_CLINGO_TRY { conf->setKeyValue(key, val); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_configuration_value_is_assigned(clingo_configuration_t *conf, clingo_id_t key, bool *ret) { + GRINGO_CLINGO_TRY { + int n = 0; + conf->getKeyInfo(key, nullptr, nullptr, nullptr, &n); + if (n < 0) { throw std::runtime_error("not a value"); } + *ret = n > 0; + } + GRINGO_CLINGO_CATCH; +} + +// {{{1 statistics + +struct clingo_statistic : public Potassco::AbstractStatistics { }; + +extern "C" bool clingo_statistics_root(clingo_statistics_t *stats, uint64_t *ret) { + GRINGO_CLINGO_TRY { *ret = stats->root(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_type(clingo_statistics_t *stats, uint64_t key, clingo_statistics_type_t *ret) { + GRINGO_CLINGO_TRY { *ret = stats->type(key); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_array_size(clingo_statistics_t *stats, uint64_t key, size_t *ret) { + GRINGO_CLINGO_TRY { *ret = stats->size(key); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_array_at(clingo_statistics_t *stats, uint64_t key, size_t index, uint64_t *ret) { + GRINGO_CLINGO_TRY { *ret = stats->at(key, index); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_map_size(clingo_statistics_t *stats, uint64_t key, size_t *n) { + GRINGO_CLINGO_TRY { *n = stats->size(key); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_map_subkey_name(clingo_statistics_t *stats, uint64_t key, size_t index, char const **name) { + GRINGO_CLINGO_TRY { *name = stats->key(key, index); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_map_at(clingo_statistics_t *stats, uint64_t key, char const *name, uint64_t *ret) { + GRINGO_CLINGO_TRY { *ret = stats->get(key, name); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_statistics_value_get(clingo_statistics_t *stats, uint64_t key, double *value) { + GRINGO_CLINGO_TRY { *value = stats->value(key); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 global functions + +extern "C" bool clingo_parse_term(char const *str, clingo_logger_t *logger, void *data, unsigned message_limit, clingo_symbol_t *ret) { + GRINGO_CLINGO_TRY { + Gringo::Input::GroundTermParser parser; + Gringo::Logger::Printer printer; + if (logger) { + printer = [logger, data](clingo_warning_t code, char const *msg) { logger(code, msg, data); }; + } + Gringo::Logger log(printer, message_limit); + Symbol sym = parser.parse(str, log); + if (sym.type() == SymbolType::Special) { throw std::runtime_error("parsing failed"); } + *ret = sym.rep(); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_parse_program(char const *program, clingo_ast_callback_t *cb, void *cb_data, clingo_logger_t *logger, void *logger_data, unsigned message_limit) { + GRINGO_CLINGO_TRY { + Input::ASTBuilder builder([cb, cb_data](clingo_ast_statement_t const &stm) { handleCError(cb(&stm, cb_data)); }); + Input::NonGroundParser parser(builder); + Logger::Printer printer; + if (logger) { printer = [logger, logger_data](clingo_warning_t cond, char const *msg) { logger(cond, msg, logger_data); }; } + Logger log(printer, message_limit); + parser.pushStream("", Gringo::gringo_make_unique(program), log); + parser.parse(log); + if (log.hasError()) { throw std::runtime_error("syntax error"); } + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_add_string(char const *str, char const **ret) { + GRINGO_CLINGO_TRY { *ret = String(str).c_str(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" void clingo_version(int *major, int *minor, int *revision) { + *major = CLINGO_VERSION_MAJOR; + *minor = CLINGO_VERSION_MINOR; + *revision = CLINGO_VERSION_REVISION; +} + +// {{{1 backend + +struct clingo_backend : clingo_control_t { }; + +extern "C" bool clingo_backend_rule(clingo_backend_t *backend, bool choice, clingo_atom_t const *head, size_t head_n, clingo_literal_t const *body, size_t body_n) { + GRINGO_CLINGO_TRY { outputRule(*backend->backend(), choice, {head, head_n}, {body, body_n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_weight_rule(clingo_backend_t *backend, bool choice, clingo_atom_t const *head, size_t head_n, clingo_weight_t lower, clingo_weighted_literal_t const *body, size_t body_n) { + GRINGO_CLINGO_TRY { outputRule(*backend->backend(), choice, {head, head_n}, lower, {reinterpret_cast(body), body_n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_minimize(clingo_backend_t *backend, clingo_weight_t prio, clingo_weighted_literal_t const* lits, size_t lits_n) { + GRINGO_CLINGO_TRY { backend->backend()->minimize(prio, {reinterpret_cast(lits), lits_n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_project(clingo_backend_t *backend, clingo_atom_t const *atoms, size_t n) { + GRINGO_CLINGO_TRY { backend->backend()->project({atoms, n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_external(clingo_backend_t *backend, clingo_atom_t atom, clingo_external_type_t v) { + GRINGO_CLINGO_TRY { backend->backend()->external(atom, Potassco::Value_t(v)); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_assume(clingo_backend_t *backend, clingo_literal_t const *literals, size_t n) { + GRINGO_CLINGO_TRY { backend->backend()->assume({literals, n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_heuristic(clingo_backend_t *backend, clingo_atom_t atom, clingo_heuristic_type_t type, int bias, unsigned priority, clingo_literal_t const *condition, size_t condition_n) { + GRINGO_CLINGO_TRY { backend->backend()->heuristic(atom, Potassco::Heuristic_t(type), bias, priority, {condition, condition_n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_acyc_edge(clingo_backend_t *backend, int node_u, int node_v, clingo_literal_t const *condition, size_t condition_n) { + GRINGO_CLINGO_TRY { backend->backend()->acycEdge(node_u, node_v, {condition, condition_n}); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_backend_add_atom(clingo_backend_t *backend, clingo_atom_t *ret) { + GRINGO_CLINGO_TRY { *ret = backend->addProgramAtom(); } + GRINGO_CLINGO_CATCH; +} + +// {{{1 control + +struct clingo_program_builder : clingo_control_t { }; +bool clingo_program_builder_begin(clingo_program_builder_t *bld) { + GRINGO_CLINGO_TRY { bld->beginAdd(); } + GRINGO_CLINGO_CATCH; +} + +bool clingo_program_builder_add(clingo_program_builder_t *bld, clingo_ast_statement_t const *stm) { + GRINGO_CLINGO_TRY { bld->add(*stm); } + GRINGO_CLINGO_CATCH; +} + +bool clingo_program_builder_end(clingo_program_builder_t *bld) { + GRINGO_CLINGO_TRY { bld->endAdd(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" void clingo_control_free(clingo_control_t *ctl) { + delete ctl; +} + +extern "C" bool clingo_control_add(clingo_control_t *ctl, char const *name, char const * const *params, size_t n, char const *part) { + GRINGO_CLINGO_TRY { + FWStringVec p; + for (char const * const *it = params, * const *ie = it + n; it != ie; ++it) { + p.emplace_back(*it); + } + ctl->add(name, p, part); + } + GRINGO_CLINGO_CATCH; +} + +namespace { + +struct ClingoContext : Context { + ClingoContext(clingo_control_t *ctl, clingo_ground_callback_t *cb, void *data) + : ctl(ctl) + , cb(cb) + , data(data) {} + + bool callable(String) const override { + return cb != nullptr; + } + + SymVec call(Location const &loc, String name, SymSpan args) override { + assert(cb); + clingo_location_t loc_c{loc.beginFilename.c_str(), loc.endFilename.c_str(), loc.beginLine, loc.endLine, loc.beginColumn, loc.endColumn}; + auto ret = cb(loc_c, name.c_str(), reinterpret_cast(args.first), args.size, data, [](clingo_symbol_t const * ret_c, size_t n, void *data) -> bool { + auto t = static_cast(data); + GRINGO_CLINGO_TRY { + for (auto it = ret_c, ie = it + n; it != ie; ++it) { + t->ret.emplace_back(Symbol(*it)); + } + } GRINGO_CLINGO_CATCH; + }, this); + if (!ret) { throw ClingoError(); } + return std::move(this->ret); + } + virtual ~ClingoContext() noexcept = default; + + clingo_control_t *ctl; + clingo_ground_callback_t *cb; + void *data; + SymVec ret; +}; + +} + +extern "C" bool clingo_control_ground(clingo_control_t *ctl, clingo_part_t const * vec, size_t n, clingo_ground_callback_t *cb, void *data) { + GRINGO_CLINGO_TRY { + Control::GroundVec gv; + gv.reserve(n); + for (auto it = vec, ie = it + n; it != ie; ++it) { + SymVec params; + params.reserve(it->size); + for (auto jt = it->params, je = jt + it->size; jt != je; ++jt) { + params.emplace_back(Symbol(*jt)); + } + gv.emplace_back(it->name, params); + } + ClingoContext cctx(ctl, cb, data); + ctl->ground(gv, cb ? &cctx : nullptr); + } GRINGO_CLINGO_CATCH; +} + +namespace { + +Control::Assumptions toAss(clingo_symbolic_literal_t const * assumptions, size_t n) { + Control::Assumptions ass; + for (auto it = assumptions, ie = it + n; it != ie; ++it) { + ass.emplace_back(static_cast(it->symbol), !it->positive); + } + return ass; +} + +} + +extern "C" bool clingo_control_solve(clingo_control_t *ctl, clingo_model_callback_t *model_handler, void *data, clingo_symbolic_literal_t const *assumptions, size_t n, clingo_solve_result_bitset_t *ret) { + GRINGO_CLINGO_TRY { + *ret = static_cast(ctl->solve([model_handler, data](Model const &m) { + bool goon = true; + if (model_handler && !model_handler(static_cast(const_cast(&m)), data, &goon)) { throw ClingoError(); } + return goon; + }, toAss(assumptions, n))); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_solve_iteratively(clingo_control_t *ctl, clingo_symbolic_literal_t const *assumptions, size_t n, clingo_solve_iteratively_t **it) { + GRINGO_CLINGO_TRY { *it = static_cast(ctl->solveIter(toAss(assumptions, n))); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_assign_external(clingo_control_t *ctl, clingo_symbol_t atom, clingo_truth_value_t value) { + GRINGO_CLINGO_TRY { ctl->assignExternal(Symbol(atom), static_cast(value)); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_release_external(clingo_control_t *ctl, clingo_symbol_t atom) { + GRINGO_CLINGO_TRY { ctl->assignExternal(Symbol(atom), Potassco::Value_t::Release); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_program_builder(clingo_control_t *ctl, clingo_program_builder_t **ret) { + GRINGO_CLINGO_TRY { *ret = static_cast(ctl); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_symbolic_atoms(clingo_control_t *ctl, clingo_symbolic_atoms_t **ret) { + GRINGO_CLINGO_TRY { *ret = &ctl->getDomain(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_theory_atoms(clingo_control_t *ctl, clingo_theory_atoms_t **ret) { + GRINGO_CLINGO_TRY { *ret = const_cast(&ctl->theory()); } + GRINGO_CLINGO_CATCH; +} + +namespace { + +class ClingoPropagator : public Gringo::Propagator { +public: + ClingoPropagator(clingo_propagator_t prop, void *data) + : prop_(prop) + , data_(data) { } + void init(Gringo::PropagateInit &init) override { + if (prop_.init && !prop_.init(&init, data_)) { throw ClingoError(); } + } + + void propagate(Potassco::AbstractSolver& solver, const ChangeList& changes) override { + if (prop_.propagate && !prop_.propagate(static_cast(&solver), changes.first, changes.size, data_)) { throw ClingoError(); } + } + + void undo(const Potassco::AbstractSolver& solver, const ChangeList& undo) override { + if (prop_.undo && !prop_.undo(static_cast(&const_cast(solver)), undo.first, undo.size, data_)) { throw ClingoError(); } + } + + void check(Potassco::AbstractSolver& solver) override { + if (prop_.check && !prop_.check(static_cast(&solver), data_)) { throw ClingoError(); } + } +private: + clingo_propagator_t prop_; + void *data_; +}; + +} // namespace + +extern "C" bool clingo_control_register_propagator(clingo_control_t *ctl, clingo_propagator_t propagator, void *data, bool sequential) { + GRINGO_CLINGO_TRY { ctl->registerPropagator(gringo_make_unique(propagator, data), sequential); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_cleanup(clingo_control_t *ctl) { + GRINGO_CLINGO_TRY { ctl->cleanupDomains(); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_has_const(clingo_control_t *ctl, char const *name, bool *ret) { + GRINGO_CLINGO_TRY { + auto sym = ctl->getConst(name); + *ret = sym.type() != SymbolType::Special; + + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_get_const(clingo_control_t *ctl, char const *name, clingo_symbol_t *ret) { + GRINGO_CLINGO_TRY { + auto sym = ctl->getConst(name); + *ret = sym.type() != SymbolType::Special ? sym.rep() : Symbol::createId(name).rep(); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" void clingo_control_interrupt(clingo_control_t *ctl) { + ctl->interrupt(); +} + +extern "C" bool clingo_control_load(clingo_control_t *ctl, char const *file) { + GRINGO_CLINGO_TRY { ctl->load(file); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_solve_async(clingo_control_t *ctl, clingo_model_callback_t *mh, void *mh_data, clingo_finish_callback_t *fh, void *fh_data, clingo_symbolic_literal_t const * assumptions, size_t n, clingo_solve_async_t **ret) { + GRINGO_CLINGO_TRY { + clingo_control::Assumptions ass; + for (auto it = assumptions, ie = assumptions + n; it != ie; ++it) { + ass.emplace_back(Symbol(it->symbol), it->positive); + } + *ret = static_cast(ctl->solveAsync( + [mh, mh_data](Gringo::Model const &m) { + bool result = true; + if (mh && !mh(&const_cast(m), mh_data, &result)) { throw ClingoError(); } + return result; + }, [fh, fh_data](Gringo::SolveResult ret) { + if (fh && !fh(ret, fh_data)) { throw ClingoError(); } + }, std::move(ass))); + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_use_enumeration_assumption(clingo_control_t *ctl, bool value) { + GRINGO_CLINGO_TRY { ctl->useEnumAssumption(value); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_backend(clingo_control_t *ctl, clingo_backend_t **ret) { + GRINGO_CLINGO_TRY { + if (ctl->backend()) { *ret = static_cast(ctl); } + else { throw std::runtime_error("backend not available"); } + } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_configuration(clingo_control_t *ctl, clingo_configuration_t **conf) { + GRINGO_CLINGO_TRY { *conf = static_cast(&ctl->getConf()); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_statistics(clingo_control_t *ctl, clingo_statistics_t **stats) { + GRINGO_CLINGO_TRY { *stats = static_cast(ctl->statistics()); } + GRINGO_CLINGO_CATCH; +} + +extern "C" bool clingo_control_clasp_facade(clingo_control_t *ctl, void **clasp) { + GRINGO_CLINGO_TRY { *clasp = ctl->claspFacade(); } + GRINGO_CLINGO_CATCH; +} + +namespace { + +class Observer : public Potassco::AbstractProgram { +public: + Observer(clingo_ground_program_observer_t obs, void *data) : obs_(obs), data_(data) { } + ~Observer() override = default; + + void initProgram(bool incremental) override { + call(obs_.init_program, incremental); + } + void beginStep() override { + call(obs_.begin_step); + } + void endStep() override { + call(obs_.end_step); + } + + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, const Potassco::LitSpan& body) override { + call(obs_.rule, ht == Potassco::Head_t::Choice, head.first, head.size, body.first, body.size); + } + void rule(Potassco::Head_t ht, const Potassco::AtomSpan& head, Weight_t bound, const Potassco::WeightLitSpan& body) override { + call(obs_.weight_rule, ht == Potassco::Head_t::Choice, head.first, bound, head.size, reinterpret_cast(body.first), body.size); + } + void minimize(Weight_t prio, const Potassco::WeightLitSpan& lits) override { + call(obs_.minimize, prio, reinterpret_cast(lits.first), lits.size); + } + + void project(const Potassco::AtomSpan& atoms) override { + call(obs_.project, atoms.first, atoms.size); + } + void output(const StringSpan&str, const Potassco::LitSpan& condition) override { + (void)str; + (void)condition; + } + void external(Atom_t a, Potassco::Value_t v) override { + call(obs_.external, a, v); + } + void assume(const Potassco::LitSpan& lits) override { + call(obs_.assume, lits.first, lits.size); + } + void heuristic(Atom_t a, Potassco::Heuristic_t t, int bias, unsigned prio, const Potassco::LitSpan& condition) override { + call(obs_.heuristic, a, t, bias, prio, condition.first, condition.size); + } + void acycEdge(int s, int t, const Potassco::LitSpan& condition) override { + call(obs_.acyc_edge, s, t, condition.first, condition.size); + } + + void theoryTerm(Id_t termId, int number) override { + call(obs_.theory_term_number, termId, number); + } + void theoryTerm(Id_t termId, const StringSpan& name) override { + std::string s{name.first, name.size}; + call(obs_.theory_term_string, termId, s.c_str()); + } + void theoryTerm(Id_t termId, int cId, const Potassco::IdSpan& args) override { + call(obs_.theory_term_compound, termId, cId, args.first, args.size); + } + void theoryElement(Id_t elementId, const Potassco::IdSpan& terms, const Potassco::LitSpan& cond) override { + call(obs_.theory_element, elementId, terms.first, terms.size, cond.first, cond.size); + } + void theoryAtom(Id_t atomOrZero, Id_t termId, const Potassco::IdSpan& elements) override { + call(obs_.theory_atom, atomOrZero, termId, elements.first, elements.size); + } + void theoryAtom(Id_t atomOrZero, Id_t termId, const Potassco::IdSpan& elements, Id_t op, Id_t rhs) override { + call(obs_.theory_atom_with_guard, atomOrZero, termId, elements.first, elements.size, op, rhs); + } +private: + template + void call(CB *cb, Args&&... args) { + if (cb && !(*cb)(std::forward(args)..., data_)) { throw Gringo::ClingoError(); } + } +private: + clingo_ground_program_observer_t obs_; + void *data_; +}; + +} // namespace + +extern "C" bool clingo_control_register_observer(clingo_control_t *control, clingo_ground_program_observer_t observer, void *data) { + GRINGO_CLINGO_TRY { control->registerObserver(gringo_make_unique(observer, data)); } + GRINGO_CLINGO_CATCH; +} + +// }}}1 + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + diff --git a/libgringo/src/ground/instantiation.cc b/libgringo/src/ground/instantiation.cc new file mode 100644 index 0000000..d4c26f6 --- /dev/null +++ b/libgringo/src/ground/instantiation.cc @@ -0,0 +1,165 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include + +#define DEBUG_INSTANTIATION 0 + +namespace Gringo { namespace Ground { + +// {{{ definition of SolutionBinder + +IndexUpdater *SolutionBinder::getUpdater() { return nullptr; } +void SolutionBinder::match(Logger &) { } +bool SolutionBinder::next() { return false; } +void SolutionBinder::print(std::ostream &out) const { out << "#end"; } +SolutionBinder::~SolutionBinder() { } + +// }}} +// {{{ definition of BackjumpBinder + +BackjumpBinder::BackjumpBinder(UIdx &&index, DependVec &&depends) + : index(std::move(index)) + , depends(std::move(depends)) { } +BackjumpBinder::BackjumpBinder(BackjumpBinder &&) noexcept = default; +void BackjumpBinder::match(Logger &log) { index->match(log); } +bool BackjumpBinder::next() { return index->next(); } +bool BackjumpBinder::first(Logger &log) { + index->match(log); + return next(); +} +void BackjumpBinder::print(std::ostream &out) const { + out << *index; + out << ":["; + print_comma(out, depends, ","); + out << "]"; +} +BackjumpBinder::~BackjumpBinder() { } + +// }}} +// {{{ definition of Instantiator + +Instantiator::Instantiator(SolutionCallback &callback) + : callback(&callback) { } +void Instantiator::add(UIdx &&index, DependVec &&depends) { + binders.emplace_back(std::move(index), std::move(depends)); +} +void Instantiator::finalize(DependVec &&depends) { + binders.emplace_back(gringo_make_unique(), std::move(depends)); +} +void Instantiator::enqueue(Queue &queue) { queue.enqueue(*this); } +void Instantiator::instantiate(Output::OutputBase &out, Logger &log) { +#if DEBUG_INSTANTIATION > 0 + std::cerr << " instantiate: " << *this << std::endl; +#endif + auto ie = binders.rend(), it = ie - 1, ib = binders.rbegin(); + it->match(log); + do { +#if DEBUG_INSTANTIATION > 1 + std::cerr << " start at: " << *it << std::endl; +#endif + it->backjumpable = true; + if (it->next()) { + for (--it; it->first(log); --it) { it->backjumpable = true; } +#if DEBUG_INSTANTIATION > 1 + std::cerr << " advanced to: " << *it << std::endl; +#endif + } + if (it == ib) { callback->report(out, log); } + for (auto &x : it->depends) { binders[x].backjumpable = false; } + for (++it; it != ie && it->backjumpable; ++it) { } +#if DEBUG_INSTANTIATION > 1 + std::cerr << " backfumped to: "; + if (it != ie) { it->print(std::cerr); } + else { std::cerr << "the head :)"; } + std::cerr << std::endl; +#endif + } + while (it != ie); +} +void Instantiator::print(std::ostream &out) const { + using namespace std::placeholders; + // Note: consider adding something to callback + callback->printHead(out); + out << " <~ "; + print_comma(out, binders, " , ", std::bind(&BackjumpBinder::print, _2, _1)); + out << "."; +} +unsigned Instantiator::priority() const { + return callback->priority(); +} +Instantiator::~Instantiator() noexcept = default; + +// }}} +// {{{ definition of Queue + +void Queue::process(Output::OutputBase &out, Logger &log) { + bool empty; + do { + empty = true; + for (auto &queue : queues) { + if (!queue.empty()) { +#if DEBUG_INSTANTIATION > 0 + std::cerr << "************start step" << std::endl; +#endif + queue.swap(current); + for (Instantiator &x : current) { + x.instantiate(out, log); + x.enqueued = false; + } + for (Instantiator &x : current) { x.callback->propagate(*this); } + current.clear(); + // OPEN -> NEW, NEW -> OLD + auto jt = std::remove_if(domains.begin(), domains.end(), [](Domain &x) -> bool { + x.nextGeneration(); + return !x.dequeue(); + }); + domains.erase(jt, domains.end()); + empty = false; + break; + } + } + } + while (!empty); + // NEW -> OLD + for (Domain &x : domains) { + x.nextGeneration(); + if (x.dequeue()) { assert(false); } + } + domains.clear(); +} +void Queue::enqueue(Instantiator &inst) { + if (!inst.enqueued) { + queues[inst.priority()].emplace_back(inst); + inst.enqueued = true; + } +} +void Queue::enqueue(Domain &x) { + if (!x.isEnqueued()) { + domains.emplace_back(x); + } + x.enqueue(); +} +Queue::~Queue() { } + +// }}} + +} } // namespace Ground Gringo diff --git a/libgringo/src/ground/literals.cc b/libgringo/src/ground/literals.cc new file mode 100644 index 0000000..9a21e84 --- /dev/null +++ b/libgringo/src/ground/literals.cc @@ -0,0 +1,492 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/literals.hh" +#include "gringo/ground/binders.hh" +#include "gringo/ground/types.hh" +#include "gringo/logger.hh" +#include "gringo/scripts.hh" +#include +#include + +namespace Gringo { namespace Ground { + +namespace { + +// {{{ declaration of RangeBinder + +struct RangeBinder : Binder { + RangeBinder(UTerm &&assign, RangeLiteralShared &range) + : assign(std::move(assign)) + , range(range) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + bool undefined = false; + Symbol l{range.first->eval(undefined, log)}, r{range.second->eval(undefined, log)}; + if (!undefined && l.type() == SymbolType::Num && r.type() == SymbolType::Num) { + current = l.num(); + end = r.num(); + } + else { + if (!undefined) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << (range.first->loc() + range.second->loc()) << ": info: interval undefined:\n" + << " " << *range.first << ".." << *range.second << "\n"; + } + current = 1; + end = 0; + } + } + bool next() override { + // Note: if assign does not match it is not a variable and will not match at all + // if assign is just a number, then this is handled in the corresponding Binder + return current <= end && assign->match(Symbol::createNum(current++)); + } + void print(std::ostream &out) const override { out << *assign << "=" << *range.first << ".." << *range.second; } + virtual ~RangeBinder() { } + + UTerm assign; + RangeLiteralShared ⦥ + int current = 0; + int end = 0; + +}; + +// }}} +// {{{ declaration of RangeMatcher + +struct RangeMatcher : Binder { + RangeMatcher(Term &assign, RangeLiteralShared &range) + : assign(assign) + , range(range) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + bool undefined = false; + Symbol l{range.first->eval(undefined, log)}, r{range.second->eval(undefined, log)}, a{assign.eval(undefined, log)}; + if (!undefined && l.type() == SymbolType::Num && r.type() == SymbolType::Num) { + firstMatch = a.type() == SymbolType::Num && l.num() <= a.num() && a.num() <= r.num(); + } + else { + if (!undefined) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << (range.first->loc() + range.second->loc()) << ": info: interval undefined:\n" + << " " << *range.first << ".." << *range.second << "\n"; + } + firstMatch = false; + } + } + bool next() override { + bool m = firstMatch; + firstMatch = false; + return m; + } + void print(std::ostream &out) const override { out << assign << "=" << *range.first << ".." << *range.second; } + Term &assign; + RangeLiteralShared ⦥ + bool firstMatch = false; +}; + +// }}} + +// {{{ declaration of ScriptBinder + +struct ScriptBinder : Binder { + ScriptBinder(Scripts &scripts, UTerm &&assign, ScriptLiteralShared &shared) + : scripts(scripts) + , assign(std::move(assign)) + , shared(shared) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + SymVec args; + bool undefined = false; + for (auto &x : std::get<1>(shared)) { args.emplace_back(x->eval(undefined, log)); } + if (!undefined) { + matches = scripts.call(assign->loc(), std::get<0>(shared), Potassco::toSpan(args), log); + } + else { matches = {}; } + current = matches.begin(); + } + bool next() override { + while (current != matches.end()) { + if (assign->match(*current++)) { return true; } + } + return false; + } + void print(std::ostream &out) const override { + out << *assign << "=" << std::get<0>(shared) << "("; + print_comma(out, std::get<1>(shared), ",", [](std::ostream &out, UTerm const &term) { out << *term; }); + out << ")"; + } + virtual ~ScriptBinder() { } + + Scripts &scripts; + UTerm assign; + ScriptLiteralShared &shared; + SymVec matches; + SymVec::iterator current; +}; + +// }}} + +// {{{ declaration of RelationMatcher + +struct RelationMatcher : Binder { + RelationMatcher(RelationShared &shared) + : shared(shared) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + bool undefined = false; + Symbol l(std::get<1>(shared)->eval(undefined, log)); + if (undefined) { firstMatch = false; return; } + Symbol r(std::get<2>(shared)->eval(undefined, log)); + if (undefined) { firstMatch = false; return; } + switch (std::get<0>(shared)) { + case Relation::GT: { firstMatch = l > r; break; } + case Relation::LT: { firstMatch = l < r; break; } + case Relation::GEQ: { firstMatch = l >= r; break; } + case Relation::LEQ: { firstMatch = l <= r; break; } + case Relation::NEQ: { firstMatch = l != r; break; } + case Relation::EQ: { firstMatch = l == r; break; } + } + } + bool next() override { + bool ret = firstMatch; + firstMatch = false; + return ret; + } + void print(std::ostream &out) const override { out << *std::get<1>(shared) << std::get<0>(shared) << *std::get<2>(shared); } + virtual ~RelationMatcher() { } + + RelationShared &shared; + bool firstMatch = false; +}; + +// }}} +// {{{ declaration of AssignBinder + +struct AssignBinder : Binder { + AssignBinder(UTerm &&lhs, Term &rhs) + : lhs(std::move(lhs)) + , rhs(rhs) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + bool undefined = false; + Symbol valRhs = rhs.eval(undefined, log); + if (!undefined) { + firstMatch = lhs->match(valRhs); + } + else { firstMatch = false; } + } + bool next() override { + bool ret = firstMatch; + firstMatch = false; + return ret; + } + void print(std::ostream &out) const override { out << *lhs << "=" << rhs; } + UTerm lhs; + Term &rhs; + bool firstMatch = false; +}; + + +// }}} + + // {{{ declaration of CSPLiteralMatcher + +struct CSPLiteralMatcher : Binder { + CSPLiteralMatcher(CSPLiteralShared &terms) + : terms(terms) { } + IndexUpdater *getUpdater() override { return nullptr; } + void match(Logger &log) override { + firstMatch = std::get<1>(terms).checkEval(log) && std::get<2>(terms).checkEval(log); + } + bool next() override { + bool ret = firstMatch; + firstMatch = false; + return ret; + } + void print(std::ostream &out) const override { out << std::get<1>(terms) << std::get<0>(terms) << std::get<2>(terms); } + virtual ~CSPLiteralMatcher() { } + + CSPLiteralShared &terms; + bool firstMatch = false; +}; + +// }}} + +} // namespace + +// {{{ definition of PredicateLiteral::BodyOccurrence + +UGTerm PredicateLiteral::getRepr() const { return repr->gterm(); } +bool PredicateLiteral::isPositive() const { return naf == NAF::POS; } +bool PredicateLiteral::isNegative() const { return naf != NAF::POS; } +void PredicateLiteral::setType(OccurrenceType x) { type = x; } +OccurrenceType PredicateLiteral::getType() const { return type; } +BodyOcc::DefinedBy &PredicateLiteral::definedBy() { return defs; } +void PredicateLiteral::checkDefined(LocSet &done, SigSet const &edb, UndefVec &undef) const { + if (!auxiliary_ && defs.empty() && done.find(repr->loc()) == done.end() && edb.find(repr->getSig()) == edb.end()) { + // accumulate warnings in array of printables .. + done.insert(repr->loc()); + undef.emplace_back(repr->loc(), repr.get()); + } +} + +ExternalBodyOcc::ExternalBodyOcc() { } +UGTerm ExternalBodyOcc::getRepr() const { return gringo_make_unique(Symbol::createId("#external")); } +bool ExternalBodyOcc::isPositive() const { return false; } +bool ExternalBodyOcc::isNegative() const { return false; } +void ExternalBodyOcc::setType(OccurrenceType) { } +OccurrenceType ExternalBodyOcc::getType() const { return OccurrenceType::STRATIFIED; } +BodyOcc::DefinedBy &ExternalBodyOcc::definedBy() { return defs; } +void ExternalBodyOcc::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } +ExternalBodyOcc::~ExternalBodyOcc() { } + +// }}} + +// {{{ definition of *Literal::*Literal + +RangeLiteral::RangeLiteral(UTerm &&assign, UTerm &&lower, UTerm &&upper) +: assign(std::move(assign)) +, range(std::move(lower), std::move(upper)) { } + +ScriptLiteral::ScriptLiteral(UTerm &&assign, String name, UTermVec &&args) +: assign(std::move(assign)) +, shared(name, std::move(args)) { } + +RelationLiteral::RelationLiteral(Relation rel, UTerm &&left, UTerm &&right) +: shared(rel, std::move(left), std::move(right)) { } + +PredicateLiteral::PredicateLiteral(bool auxiliary, PredicateDomain &domain, NAF naf, UTerm &&repr) +: auxiliary_(auxiliary) +, repr(std::move(repr)) +, domain(domain) +, naf(naf) { } + +ProjectionLiteral::ProjectionLiteral(bool auxiliary, PredicateDomain &domain, UTerm &&repr, bool initialized) +: PredicateLiteral(auxiliary, domain, NAF::POS, std::move(repr)) +, initialized_(initialized) { } + +// }}} +// {{{ definition of *Literal::print + +void RangeLiteral::print(std::ostream &out) const { out << *assign << "=" << *range.first << ".." << *range.second; } +void ScriptLiteral::print(std::ostream &out) const { + out << *assign << "=" << std::get<0>(shared) << "("; + print_comma(out, std::get<1>(shared), ",", [](std::ostream &out, UTerm const &term) { out << *term; }); + out << ")"; +} +void RelationLiteral::print(std::ostream &out) const { out << *std::get<1>(shared) << std::get<0>(shared) << *std::get<2>(shared); } +void PredicateLiteral::print(std::ostream &out) const { + if (auxiliary()) { out << "["; } + out << naf << *repr; + switch (type) { + case OccurrenceType::POSITIVELY_STRATIFIED: { break; } + case OccurrenceType::STRATIFIED: { out << "!"; break; } + case OccurrenceType::UNSTRATIFIED: { out << "?"; break; } + } + if (auxiliary()) { out << "]"; } +} + +// }}} +// {{{ definition of *Literal::isRecursive + +bool RangeLiteral::isRecursive() const { return false; } +bool ScriptLiteral::isRecursive() const { return false; } +bool RelationLiteral::isRecursive() const { return false; } +bool PredicateLiteral::isRecursive() const { return type == OccurrenceType::UNSTRATIFIED; } + +// }}} +// {{{ definition of *Literal::occurrence + +BodyOcc *RangeLiteral::occurrence() { return nullptr; } +BodyOcc *ScriptLiteral::occurrence() { return nullptr; } +BodyOcc *RelationLiteral::occurrence() { return nullptr; } +BodyOcc *PredicateLiteral::occurrence() { return this; } + +// }}} +// {{{ definition of *Literal::collect + +void RangeLiteral::collect(VarTermBoundVec &vars) const { + assign->collect(vars, true); + range.first->collect(vars, false); + range.second->collect(vars, false); +} +void ScriptLiteral::collect(VarTermBoundVec &vars) const { + assign->collect(vars, true); + for (auto &x : std::get<1>(shared)) { x->collect(vars, false); } +} +void RelationLiteral::collect(VarTermBoundVec &vars) const { + std::get<1>(shared)->collect(vars, std::get<0>(shared) == Relation::EQ); + std::get<2>(shared)->collect(vars, false); +} +void PredicateLiteral::collect(VarTermBoundVec &vars) const { repr->collect(vars, naf == NAF::POS); } + +// }}} +// {{{ definition of Literal::collectImportant + +void Literal::collectImportant(Term::VarSet &vars) { + auto occ(occurrence()); + if (occ && occ->getType() != OccurrenceType::POSITIVELY_STRATIFIED) { + VarTermBoundVec x; + collect(x); + for (auto &occ : x) { vars.emplace(occ.first->name); } + } +} + +// }}} +// {{{ definition of *Literal::index + +UIdx RangeLiteral::index(Scripts &, BinderType, Term::VarSet &bound) { + if (assign->bind(bound)) { return gringo_make_unique(get_clone(assign), range); } + else { return gringo_make_unique(*assign, range); } +} +UIdx ScriptLiteral::index(Scripts &scripts, BinderType, Term::VarSet &bound) { + UTerm clone(assign->clone()); + clone->bind(bound); + return gringo_make_unique(scripts, std::move(clone), shared); +} +UIdx RelationLiteral::index(Scripts &, BinderType, Term::VarSet &bound) { + if (std::get<0>(shared) == Relation::EQ) { + UTerm clone(std::get<1>(shared)->clone()); + VarTermVec occBound; + if (clone->bind(bound)) { return gringo_make_unique(std::move(clone), *std::get<2>(shared)); } + } + return gringo_make_unique(shared); +} +UIdx PredicateLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(domain, naf, *repr, offset, type, isRecursive(), bound, 0); +} +UIdx ProjectionLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + assert(bound.empty()); + assert(type == BinderType::ALL || type == BinderType::NEW); + return make_binder(domain, naf, *repr, offset, type, isRecursive(), bound, initialized_ ? domain.incOffset() : 0); +} + +// }}} +// {{{ definition of *Literal::score + +Literal::Score RangeLiteral::score(Term::VarSet const &, Logger &log) { + if (range.first->getInvertibility() == Term::CONSTANT && range.second->getInvertibility() == Term::CONSTANT) { + bool undefined = false; + Symbol l(range.first->eval(undefined, log)); + Symbol r(range.second->eval(undefined, log)); + return (l.type() == SymbolType::Num && r.type() == SymbolType::Num) ? r.num() - l.num() : -1; + } + return 0; +} +Literal::Score ScriptLiteral::score(Term::VarSet const &, Logger &) { + return 0; +} +Literal::Score RelationLiteral::score(Term::VarSet const &, Logger &) { + return -1; +} +Literal::Score PredicateLiteral::score(Term::VarSet const &bound, Logger &) { + return naf == NAF::POS ? estimate(domain.size(), *repr, bound) : 0; +} + +// }}} +// {{{ definition of *Literal::toOutput + +std::pair RangeLiteral::toOutput(Logger &) { return {Output::LiteralId(), true}; } +std::pair ScriptLiteral::toOutput(Logger &) { return {Output::LiteralId(), true}; } +std::pair RelationLiteral::toOutput(Logger &) { return {Output::LiteralId(), true}; } +std::pair PredicateLiteral::toOutput(Logger &) { + if (offset == InvalidId) { + assert(naf == NAF::NOT); + return {Output::LiteralId(), true}; + } + auto &atom = domain[offset]; + if (static_cast(atom).name().startsWith("#inc_")) { + return {Output::LiteralId(), true}; + } + switch (naf) { + case NAF::POS: + case NAF::NOTNOT: { return {Output::LiteralId{naf, Output::AtomType::Predicate, offset, domain.domainOffset()}, atom.fact()}; } + case NAF::NOT: { return {Output::LiteralId{naf, Output::AtomType::Predicate, offset, domain.domainOffset()}, false}; } + } + assert(false); + return {Output::LiteralId(),true}; +} + +// }}} +// {{{ definition of *Literal::~*Literal + +RangeLiteral::~RangeLiteral() { } +ScriptLiteral::~ScriptLiteral() { } +RelationLiteral::~RelationLiteral() { } +PredicateLiteral::~PredicateLiteral() { } +ProjectionLiteral::~ProjectionLiteral() { } + +// }}} + +// {{{1 definition of CSPLiteral + +CSPLiteral::CSPLiteral(DomainData &data, bool auxiliary, Relation rel, CSPAddTerm &&left, CSPAddTerm &&right) +: data_(data) +, terms_(rel, std::move(left), std::move(right)) +, auxiliary_(auxiliary) +{ } + +void CSPLiteral::print(std::ostream &out) const { + if (auxiliary()) { out << "["; } + out << std::get<1>(terms_) << std::get<0>(terms_) << std::get<2>(terms_); + if (auxiliary()) { out << "]"; } +} + +bool CSPLiteral::isRecursive() const { return false; } + +BodyOcc *CSPLiteral::occurrence() { return &ext_; } + +void CSPLiteral::collect(VarTermBoundVec &vars) const { + std::get<1>(terms_).collect(vars); + std::get<2>(terms_).collect(vars); +} + +void CSPLiteral::collectImportant(Term::VarSet &vars) { + VarTermBoundVec x; + collect(x); + for (auto &occ : x) { vars.emplace(occ.first->name); } +} + +UIdx CSPLiteral::index(Scripts &, BinderType, Term::VarSet &) { + // NOTE: if the literal is auxiliary it can simply always match + return gringo_make_unique(terms_); +} + +Literal::Score CSPLiteral::score(Term::VarSet const &, Logger &) { + return std::numeric_limits::infinity(); +} + +std::pair CSPLiteral::toOutput(Logger &log) { + if (auxiliary()) { return {Output::LiteralId(),true}; } + CSPGroundLit add; + std::get<0>(add) = std::get<0>(terms_); + std::get<1>(terms_).toGround(add, false, log); + std::get<2>(terms_).toGround(add, true, log); + return {Output::LiteralId{NAF::POS, Output::AtomType::LinearConstraint, data_.cspAtom(std::move(add)), 0}, false}; +} + +CSPLiteral::~CSPLiteral() noexcept = default; + +// }}}1 + +} } // namespace Ground Gringo + diff --git a/libgringo/src/ground/program.cc b/libgringo/src/ground/program.cc new file mode 100644 index 0000000..f58a58d --- /dev/null +++ b/libgringo/src/ground/program.cc @@ -0,0 +1,165 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/program.hh" +#include "gringo/output/output.hh" + +#define DEBUG_INSTANTIATION 0 + +namespace Gringo { namespace Ground { + +// {{{ definition of Parameters + +Parameters::Parameters() = default; +Parameters::~Parameters() { } +void Parameters::add(String name, SymVec &&args) { + params[Sig((std::string("#inc_") + name.c_str()).c_str(), static_cast(args.size()), false)].emplace(std::move(args)); +} +bool Parameters::find(Sig sig) const { + auto it = params.find(sig); + return it != params.end() && !it->second.empty(); +} +ParamSet::const_iterator Parameters::begin() const { return params.begin(); } +ParamSet::const_iterator Parameters::end() const { return params.end(); } +bool Parameters::empty() const { return params.empty(); } +void Parameters::clear() { params.clear(); } + +// }}} +// {{{ definition of Program + +Program::Program(SEdbVec &&edb, Statement::Dep::ComponentVec &&stms, ClassicalNegationVec &&negate) + : edb(std::move(edb)) + , stms(std::move(stms)) + , negate(std::move(negate)) { } + +std::ostream &operator<<(std::ostream &out, Program const &p) { + bool comma = false; + for (auto &component : p.stms) { + if (comma) { out << "\n"; } + else { comma = true; } + out << "%" << (component.second ? " positive" : "") << " component"; + for (auto &stm : component.first) { out << "\n" << *stm; } + } + return out; +} + +void Program::linearize(Scripts &scripts, Logger &log) { + for (auto &x : stms) { + for (auto &y : x.first) { y->startLinearize(true); } + for (auto &y : x.first) { y->linearize(scripts, x.second, log); } + for (auto &y : x.first) { y->startLinearize(false); } + } + linearized = true; +} + +void Program::ground(Scripts &scripts, Output::OutputBase &out, Logger &log) { + Parameters params; + params.add("base", SymVec({})); + ground(params, scripts, out, true, log); +} + +void Program::ground(Parameters const ¶ms, Scripts &scripts, Output::OutputBase &out, bool finalize, Logger &log) { + for (auto &dom : out.predDoms()) { + auto name = dom->sig().name(); + if (name.startsWith("#p_")) { + // The idea here is to assign a fresh uid to each projection atom. + // Furthermore, the fresh atom is derived by the old atom. + // This prevents redefinition errors from projections. + for (auto &atom : *dom) { + if (!atom.fact() && atom.hasUid() && atom.defined()) { + Output::Rule &rule = out.tempRule(false);; + Atom_t oldUid = atom.uid(); + Atom_t newUid = out.data.newAtom(); + rule.addHead(Output::LiteralId{NAF::POS, Output::AtomType::Aux, newUid, dom->domainOffset()}); + rule.addBody(Output::LiteralId{NAF::POS, Output::AtomType::Aux, oldUid, dom->domainOffset()}); + out.output(rule); + atom.resetUid(newUid); + } + } + } + else if (name.startsWith("#inc_")) { + // clear incremental domains + dom->clear(); + } + dom->incNext(); + } + out.checkOutPreds(log); + for (auto &x : edb) { + if (params.find(std::get<0>(*x)->getSig())) { + for (auto &z : std::get<1>(*x)) { + auto it(out.predDoms().find(z.sig())); + assert(it != out.predDoms().end()); + auto ret((*it)->define(z, true)); + if (!std::get<2>(ret)) { + Potassco::Id_t offset = static_cast(std::get<0>(ret) - (*it)->begin()); + Potassco::Id_t domain = static_cast(it - out.predDoms().begin()); + out.output(out.tempRule(false).addHead({NAF::POS, Output::AtomType::Predicate, offset, domain})); + } + } + } + } + for (auto &p : params) { + auto base = out.predDoms().find(p.first); + if (base != out.predDoms().end()) { + for (auto &args : p.second) { + if (args.size() == 0) { (*base)->define(Symbol::createId(p.first.name()), true); } + else { (*base)->define(Symbol::createFun(p.first.name(), Potassco::toSpan(args)), true); } + } + } + } + for (auto &x : out.predDoms()) { x->nextGeneration(); } + Queue q; + for (auto &x : stms) { + if (!linearized) { + for (auto &y : x.first) { y->startLinearize(true); } + for (auto &y : x.first) { y->linearize(scripts, x.second, log); } + for (auto &y : x.first) { y->startLinearize(false); } + } +#if DEBUG_INSTANTIATION > 0 + std::cerr << "============= component ===========" << std::endl; +#endif + for (auto &y : x.first) { +#if DEBUG_INSTANTIATION > 0 + std::cerr << " enqueue: " << *y << std::endl; +#endif + y->enqueue(q); + } + q.process(out, log); + } + for (auto &x : negate) { + for (auto neg(x.second.begin() + x.second.incOffset()), ie(x.second.end()); neg != ie; ++neg) { + Symbol v = static_cast(*neg).flipSign(); + auto pos(x.first.find(v)); + if (pos != x.first.end() && pos->defined()) { + out.output(out + .tempRule(false) + .addBody({NAF::POS, Output::AtomType::Predicate, static_cast(pos - x.first.begin()), x.first.domainOffset()}) + .addBody({NAF::POS, Output::AtomType::Predicate, static_cast(neg - x.second.begin()), x.second.domainOffset()})); + } + } + } + out.flush(); + if (finalize) { out.endStep(true, log); } + linearized = true; +} + +// }}} + +} } // namespace Ground Gringo diff --git a/libgringo/src/ground/statements.cc b/libgringo/src/ground/statements.cc new file mode 100644 index 0000000..17bbf6e --- /dev/null +++ b/libgringo/src/ground/statements.cc @@ -0,0 +1,2654 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/statements.hh" +#include "gringo/safetycheck.hh" +#include "gringo/output/literals.hh" +#include "gringo/output/output.hh" +#include "gringo/ground/binders.hh" +#include "gringo/logger.hh" +#include + +namespace Gringo { namespace Ground { + +// FIXME: too much c&p similarities in the implementations below + +// {{{1 Helpers + +namespace { + +// {{{2 definition of _initBounds + +Output::DisjunctiveBounds _initBounds(BoundVec const &bounds, Logger &log) { + Output::DisjunctiveBounds set; + set.add({{Symbol::createInf(),true}, {Symbol::createSup(),true}}); + for (auto &x : bounds) { + bool undefined = false; + Symbol v(x.bound->eval(undefined, log)); + assert(!undefined); + switch (x.rel) { + case Relation::GEQ: { set.remove({{Symbol::createInf(),true},{v,false} }); break; } + case Relation::GT: { set.remove({{Symbol::createInf(),true},{v,true} }); break; } + case Relation::LEQ: { set.remove({{v,false}, {Symbol::createSup(),true}}); break; } + case Relation::LT: { set.remove({{v,true}, {Symbol::createSup(),true}}); break; } + case Relation::NEQ: { set.remove({{v,true}, {v,true} }); break; } + case Relation::EQ: { + set.remove({{v,false}, {Symbol::createSup(),true}}); + set.remove({{Symbol::createInf(),true},{v,false} }); + break; + } + } + } + return set; +} + +// {{{2 definition of _linearize (Note: could be moved into AbstractStatement) + +struct Ent { + Ent(BinderType type, Literal &lit) : type(type), lit(lit) { } + std::vector depends; + std::vector vars; + BinderType type; + Literal &lit; +}; +using SC = SafetyChecker; + +InstVec _linearize(Logger &log, Scripts &scripts, bool positive, SolutionCallback &cb, Term::VarSet &&important, ULitVec const &lits, Term::VarSet boundInitially = Term::VarSet()) { + InstVec insts; + std::vector rec; + std::vector>> todo{1}; + unsigned i{0}; + for (auto &x : lits) { + todo.back().emplace_back(BinderType::ALL, x.get()); + if (x->isRecursive() && x->occurrence() && !x->occurrence()->isNegative()) { rec.emplace_back(i); } + ++i; + } + todo.reserve(std::max(std::vector::size_type(1), rec.size())); + insts.reserve(todo.capacity()); // Note: preserve references + for (auto i : rec) { + todo.back()[i].first = BinderType::NEW; + if (i != rec.back()) { + todo.emplace_back(todo.back()); + todo.back()[i].first = BinderType::OLD; + } + } + if (!positive) { + for (auto &lit : lits) { + if (!lit->auxiliary()) { lit->collectImportant(important); } + } + } + for (auto &x : todo) { + Term::VarSet bound = boundInitially; + insts.emplace_back(cb); + SC s; + std::unordered_map varMap; + std::vector>> boundBy; + for (auto &lit : x) { + auto &entNode(s.insertEnt(lit.first, *lit.second)); + VarTermBoundVec vars; + lit.second->collect(vars); + for (auto &occ : vars) { + if (bound.find(occ.first->name) == bound.end()) { + auto &varNode(varMap[occ.first->name]); + if (!varNode) { + varNode = &s.insertVar(boundBy.size()); + boundBy.emplace_back(occ.first->name, std::vector{}); + } + if (occ.second) { s.insertEdge(entNode, *varNode); } + else { s.insertEdge(*varNode, entNode); } + entNode.data.vars.emplace_back(varNode->data); + } + } + } + Instantiator::DependVec depend; + unsigned uid = 0; + auto pred = [&bound, &log](Ent const &x, Ent const &y) -> bool { + double sx(x.lit.score(bound, log)); + double sy(y.lit.score(bound, log)); + //std::cerr << " " << x.lit << "@" << sx << " < " << y.lit << "@" << sy << " with " << bound.size() << std::endl; + if (sx < 0 || sy < 0) { return sx < sy; } + if ((x.type == BinderType::NEW || y.type == BinderType::NEW) && x.type != y.type) { return x.type < y.type; } + return sx < sy; + }; + + SC::EntVec open; + s.init(open); + while (!open.empty()) { + for (auto it = open.begin(), end = open.end() - 1; it != end; ++it) { + if (pred((*it)->data, open.back()->data)) { std::swap(open.back(), *it); } + } + auto y = open.back(); + for (auto &var : y->data.vars) { + auto &bb(boundBy[var]); + if (bound.find(bb.first) == bound.end()) { + bb.second.emplace_back(uid); + if ((depend.empty() || depend.back() != uid) && important.find(bb.first) != important.end()) { depend.emplace_back(uid); } + } + else { y->data.depends.insert(y->data.depends.end(), bb.second.begin(), bb.second.end()); } + } + auto index(y->data.lit.index(scripts, y->data.type, bound)); + if (auto update = index->getUpdater()) { + if (BodyOcc *occ = y->data.lit.occurrence()) { + for (HeadOccurrence &x : occ->definedBy()) { x.defines(*update, y->data.type == BinderType::NEW ? &insts.back() : nullptr); } + } + } + std::sort(y->data.depends.begin(), y->data.depends.end()); + y->data.depends.erase(std::unique(y->data.depends.begin(), y->data.depends.end()), y->data.depends.end()); + insts.back().add(std::move(index), std::move(y->data.depends)); + uid++; + open.pop_back(); + s.propagate(y, open); + } + insts.back().finalize(std::move(depend)); + } + return insts; +} + +// {{{2 definition of completeRepr_ + +UTerm completeRepr_(UTerm const &repr) { + UTermVec ret; + ret.emplace_back(get_clone(repr)); + return make_locatable(repr->loc(), String{"#complete"}, std::move(ret)); +} + +// {{{2 definition of BindOnce + +struct BindOnce : Binder, IndexUpdater { + IndexUpdater *getUpdater() override { return this; } + bool update() override { return true; } + void match(Logger &) override { once = true; } + bool next() override { + bool ret = once; + once = false; + return ret; + } + void print(std::ostream &out) const override { out << "#once"; } + bool once; +}; + +// {{{2 operator << + +template +std::ostream &operator <<(std::ostream &out, std::unique_ptr const &x) { + out << *x; + return out; +} + +template +std::ostream &operator <<(std::ostream &out, std::vector const &x) { + if (!x.empty()) { + for (auto it = x.begin(), ie = x.end(); ; ) { + out << *it; + if (++it != ie) { out << ","; } + else { break; } + } + } + return out; +} +std::ostream &operator <<(std::ostream &out, OccurrenceType x) { + switch (x) { + case OccurrenceType::POSITIVELY_STRATIFIED: { break; } + case OccurrenceType::STRATIFIED: { out << "!"; break; } + case OccurrenceType::UNSTRATIFIED: { out << "?"; break; } + } + return out; +} + +// }}}2 + +} // namespace + +// }}}1 +// {{{1 definition of HeadDefinition + +HeadDefinition::HeadDefinition(UTerm &&repr, Domain *domain) +: repr_(std::move(repr)) +, domain_(domain) { } + +void HeadDefinition::defines(IndexUpdater &update, Instantiator *inst) { + auto ret(offsets_.emplace(&update, enqueueVec_.size())); + if (ret.second) { enqueueVec_.emplace_back(&update, RInstVec{}); } + if (active_ && inst) { enqueueVec_[ret.first->second].second.emplace_back(*inst); } +} + +void HeadDefinition::enqueue(Queue &queue) { + if (domain_) { queue.enqueue(*domain_); } + for (auto &x : enqueueVec_) { + if (x.first->update()) { + for (Instantiator &y : x.second) { y.enqueue(queue); } + } + } +} + +void HeadDefinition::collectImportant(Term::VarSet &vars) { + if (repr_) { + VarTermBoundVec x; + repr_->collect(x, false); + for (auto &occ : x) { vars.emplace(occ.first->name); } + } +} + +HeadDefinition::~HeadDefinition() noexcept = default; + +//{{{1 definition of AbstractStatement + +AbstractStatement::AbstractStatement(UTerm &&repr, Domain *domain, ULitVec &&lits) +: def_(std::move(repr), domain) +, lits_(std::move(lits)) { } + +AbstractStatement::~AbstractStatement() noexcept = default; + +bool AbstractStatement::isOutputRecursive() const { + for (auto &x : lits_) { + // TODO: only postive literals are relevant here! + if (!x->auxiliary() && x->isRecursive()) { + return true; + } + } + return false; +} + +bool AbstractStatement::isNormal() const { return false; } + +void AbstractStatement::analyze(Dep::Node &node, Dep &dep) { + def_.analyze(node, dep); + for (auto &x : lits_) { + auto occ(x->occurrence()); + if (occ) { dep.depends(node, *occ, false); } + } +} + +void AbstractStatement::startLinearize(bool active) { + def_.setActive(active); + if (active) { insts_.clear(); } +} + +void AbstractStatement::collectImportant(Term::VarSet &vars) { + def_.collectImportant(vars); +} +void AbstractStatement::linearize(Scripts &scripts, bool positive, Logger &log) { + Term::VarSet important; + collectImportant(important); + insts_ = _linearize(log, scripts, positive, *this, std::move(important), lits_); +} + +void AbstractStatement::enqueue(Queue &q) { + def_.init(); + for (auto &x : insts_) { x.enqueue(q); } +} + +void AbstractStatement::printHead(std::ostream &out) const { + if (def_) { out << *def_.domRepr(); } + else { out << "#false"; } +} +void AbstractStatement::printBody(std::ostream &out) const { + out << lits_; +} + +void AbstractStatement::print(std::ostream &out) const { + printHead(out); + if (!lits_.empty()) { + out << ":-"; + printBody(out); + } + out << "."; +} + +void AbstractStatement::propagate(Queue &queue) { + def_.enqueue(queue); +} + +//}}}1 + +// Statements + +// {{{1 definition of ExternalRule + +ExternalRule::ExternalRule() +: def_(make_locatable(Location("#external", 1, 1, "#external", 1, 1), Symbol::createId("#external")), nullptr) { } + +bool ExternalRule::isNormal() const { return false; } + +void ExternalRule::analyze(Dep::Node &node, Dep &dep) { + def_.analyze(node, dep); +} + +void ExternalRule::startLinearize(bool active) { + def_.setActive(active); +} + +void ExternalRule::linearize(Scripts &, bool, Logger &) { } + +void ExternalRule::enqueue(Queue &) { } + +void ExternalRule::print(std::ostream &out) const { + out << "#external."; +} + +ExternalRule::~ExternalRule() noexcept = default; + +//{{{1 definition of Rule + +Rule::Rule(HeadVec &&heads, ULitVec &&lits, RuleType type) +: lits_(std::move(lits)) +, type_(type) { + defs_.reserve(heads.size()); + for (auto &head : heads) { + assert(head.first && head.second); + defs_.emplace_back(std::move(head.first), head.second); + } +} + +Rule::~Rule() noexcept = default; + +void Rule::report(Output::OutputBase &out, Logger &log) { + if (type_ == RuleType::External) { + for (auto &def : defs_) { + bool undefined = false; + Symbol val(def.domRepr()->eval(undefined, log)); + if (!undefined) { + auto &dom = static_cast(def.dom()); + auto ret = dom.define(val, false); + Potassco::Id_t offset = static_cast(std::get<0>(ret) - dom.begin()); + std::get<0>(ret)->setExternal(true); + Output::External external({NAF::POS, Output::AtomType::Predicate, offset, dom.domainOffset()}, Potassco::Value_t::False); + out.output(external); + } + } + } + else { + bool choice = type_ == RuleType::Choice; + Output::Rule &rule(out.tempRule(choice)); + bool fact = true; + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto ret = x->toOutput(log); + if (ret.first.valid() && (out.keepFacts || !ret.second)) { + rule.addBody(ret.first); + } + if (!ret.second) { fact = false; } + } + for (auto &def : defs_) { + bool undefined = false; + Symbol val = def.domRepr()->eval(undefined, log); + if (undefined) { + if (choice) { continue; } + else { return; } + } + auto &dom = static_cast(def.dom()); + auto ret(dom.define(val)); + if (!ret.first->fact()) { + Potassco::Id_t offset = static_cast(ret.first - dom.begin()); + rule.addHead({NAF::POS, Output::AtomType::Predicate, offset, dom.domainOffset()}); + } + else if (!choice) { return; } + } + if (choice && rule.numHeads() == 0) { return; } + if (!choice && fact && rule.numHeads() == 1) { + Output::LiteralId head = rule.heads().front(); + auto &dom = *out.predDoms()[head.domain()]; + dom[head.offset()].setFact(true); + } + out.output(rule); + } +} + +bool Rule::isNormal() const { + return defs_.size() == 1 && type_ == RuleType::Disjunctive; +} + +void Rule::analyze(Dep::Node &node, Dep &dep) { + for (auto &def : defs_) { def.analyze(node, dep); } + for (auto &x : lits_) { + auto occ(x->occurrence()); + if (occ) { dep.depends(node, *occ, false); } + } +} + +void Rule::startLinearize(bool active) { + for (auto &def : defs_) { def.setActive(active); } + if (active) { insts_.clear(); } +} + +void Rule::linearize(Scripts &scripts, bool positive, Logger &log) { + Term::VarSet important; + for (auto &def : defs_) { def.collectImportant(important); } + insts_ = _linearize(log, scripts, positive, *this, std::move(important), lits_); +} + +void Rule::enqueue(Queue &q) { + for (auto &def : defs_) { def.init(); } + for (auto &x : insts_) { x.enqueue(q); } +} + +void Rule::printHead(std::ostream &out) const { + if (type_ == RuleType::External) { out << "#external "; } + if (type_ == RuleType::Choice) { out << "{"; } + if (type_ == RuleType::Disjunctive && defs_.empty()) { out << "#false"; } + bool sep = false; + for (auto &def : defs_) { + if (sep) { out << ";"; } + else { sep = true; } + out << *def.domRepr(); + } + if (type_ == RuleType::Choice) { out << "}"; } +} + +void Rule::print(std::ostream &out) const { + printHead(out); + if (!lits_.empty()) { + out << (type_ == RuleType::External ? ":" : ":-"); + out << lits_; + } + out << "."; +} + +void Rule::propagate(Queue &queue) { + for (auto &def : defs_) { def.enqueue(queue); } +} + +// }}}1 + +// {{{1 definition of ShowStatement + +ShowStatement::ShowStatement(UTerm &&term, bool csp, ULitVec &&lits) +: AbstractStatement(nullptr, nullptr, std::move(lits)) +, term_(std::move(term)) +, csp_(csp) { } + +void ShowStatement::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol term = term_->eval(undefined, log); + if (!undefined) { + Output::LitVec &cond = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { cond.emplace_back(lit.first); } + } + Output::ShowStatement ss(term, csp_, cond); + out.output(ss); + } + else { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << term_->loc() << ": info: tuple ignored:\n" + << " " << term << "\n"; + } +} + +void ShowStatement::collectImportant(Term::VarSet &vars) { + term_->collect(vars); +} + +void ShowStatement::printHead(std::ostream &out) const { + out << "#show "; + out << *term_; +} + +void ShowStatement::print(std::ostream &out) const { + printHead(out); + out << ":" << lits_ << "."; +} + +ShowStatement::~ShowStatement() noexcept = default; + +// {{{1 definition of EdgeStatement + +EdgeStatement::EdgeStatement(UTerm &&u, UTerm &&v, ULitVec &&lits) +: AbstractStatement(nullptr, nullptr, std::move(lits)) +, u_(std::move(u)) +, v_(std::move(v)) +{ } + +void EdgeStatement::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol u = u_->eval(undefined, log); + if (undefined) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << u_->loc() << ": info: edge ignored\n"; + return; + } + Symbol v = v_->eval(undefined, log); + if (undefined) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << v_->loc() << ": info: edge ignored\n"; + return; + } + Output::LitVec &cond = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { cond.emplace_back(lit.first); } + } + Output::EdgeStatement es(u, v, cond); + out.output(es); +} + +void EdgeStatement::collectImportant(Term::VarSet &vars) { + u_->collect(vars); + v_->collect(vars); +} + +void EdgeStatement::printHead(std::ostream &out) const { + out << "#edge (" << *u_ << "," << *v_ << ")"; +} + +void EdgeStatement::print(std::ostream &out) const { + printHead(out); + out << ":" << lits_ << "."; +} + +EdgeStatement::~EdgeStatement() noexcept = default; + +// {{{1 definition of ProjectStatement + +ProjectStatement::ProjectStatement(UTerm &&atom, ULitVec &&lits) +: AbstractStatement(nullptr, nullptr, std::move(lits)) +, atom_(std::move(atom)) +{ } + +void ProjectStatement::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol term = atom_->eval(undefined, log); + assert(!undefined && term.hasSig()); + auto domain = out.data.predDoms().find(term.sig()); + assert(domain != out.data.predDoms().end()); + auto atom = (*domain)->find(term); + Id_t offset = atom - (*domain)->begin(); + Output::ProjectStatement ps(Output::LiteralId{NAF::POS, Output::AtomType::Predicate, offset, (*domain)->domainOffset()}); + out.output(ps); +} + +void ProjectStatement::collectImportant(Term::VarSet &vars) { + atom_->collect(vars); +} + +void ProjectStatement::printHead(std::ostream &out) const { + out << "#project "; + out << *atom_; +} + +void ProjectStatement::print(std::ostream &out) const { + printHead(out); + out << ":" << lits_ << "."; +} + +ProjectStatement::~ProjectStatement() noexcept = default; + +// {{{1 definition of HeuristicStatement + +HeuristicStatement::HeuristicStatement(UTerm &&atom, UTerm &&value, UTerm &&bias, UTerm &&mod, ULitVec &&body) +: AbstractStatement(nullptr, nullptr, std::move(body)) +, atom_(std::move(atom)) +, value_(std::move(value)) +, priority_(std::move(bias)) +, mod_(std::move(mod)) +{ } + +void HeuristicStatement::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + // determine atom + Symbol term = atom_->eval(undefined, log); + assert(!undefined && term.hasSig()); + auto domain = out.data.predDoms().find(term.sig()); + assert(domain != out.data.predDoms().end()); + auto atom = (*domain)->find(term); + assert (atom != (*domain)->end()); + // check value + Symbol value = value_->eval(undefined, log); + if (undefined || value.type() != SymbolType::Num) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << value_->loc() << ": info: heuristic directive ignored\n"; + return; + } + // check priority + Symbol priority = priority_->eval(undefined, log); + if (undefined || priority.type() != SymbolType::Num || priority.num() < 0) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << priority_->loc() << ": info: heuristic directive ignored\n"; + return; + } + // check modifier + Symbol mod = mod_->eval(undefined, log); + if (undefined) { mod = Symbol::createId(""); } + Potassco::Heuristic_t heuMod; + if (mod == Symbol::createId("true")) { heuMod = Potassco::Heuristic_t::True; } + else if (mod == Symbol::createId("false")) { heuMod = Potassco::Heuristic_t::False; } + else if (mod == Symbol::createId("level")) { heuMod = Potassco::Heuristic_t::Level; } + else if (mod == Symbol::createId("factor")) { heuMod = Potassco::Heuristic_t::Factor; } + else if (mod == Symbol::createId("init")) { heuMod = Potassco::Heuristic_t::Init; } + else if (mod == Symbol::createId("sign")) { heuMod = Potassco::Heuristic_t::Sign; } + else { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << mod_->loc() << ": info: heuristic directive ignored\n"; + return; + } + // TODO: this loop appears far too often... + Output::LitVec &cond = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { cond.emplace_back(lit.first); } + } + Id_t offset = atom - (*domain)->begin(); + auto atomId = Output::LiteralId{NAF::POS, Output::AtomType::Predicate, offset, (*domain)->domainOffset()}; + Output::HeuristicStatement hs(atomId, value.num(), priority.num(), heuMod, cond); + out.output(hs); +} + +void HeuristicStatement::collectImportant(Term::VarSet &vars) { + atom_->collect(vars); + value_->collect(vars); + priority_->collect(vars); + mod_->collect(vars); +} + +void HeuristicStatement::printHead(std::ostream &out) const { + out << "#heuristic "; + out << *atom_ << "[" << *value_ << "@" << *priority_ << "," << *mod_ << "]"; +} + +void HeuristicStatement::print(std::ostream &out) const { + printHead(out); + out << ":" << lits_ << "."; +} + +HeuristicStatement::~HeuristicStatement() noexcept = default; + +// {{{1 definition of WeakConstraint + +WeakConstraint::WeakConstraint(UTermVec &&tuple, ULitVec &&lits) +: AbstractStatement(nullptr, nullptr, std::move(lits)) +, tuple_(std::move(tuple)) { } + +void WeakConstraint::report(Output::OutputBase &out, Logger &log) { + SymVec &tempVals = out.tempVals(); + bool undefined = false; + for (auto &x : tuple_) { tempVals.emplace_back(x->eval(undefined, log)); } + if (!undefined && tempVals[0].type() == SymbolType::Num && tempVals[1].type() == SymbolType::Num) { + Output::LitVec &tempLits = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { tempLits.emplace_back(lit.first); } + } + Output::WeakConstraint min(tempVals, tempLits); + out.output(min); + } + else if (!undefined) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << tuple_.front()->loc() << ": info: tuple ignored:\n" + << " " << out.tempVals_.front() << "@" << out.tempVals_[1] << "\n"; + } +} + +void WeakConstraint::collectImportant(Term::VarSet &vars) { + for (auto &x : tuple_) { x->collect(vars); } +} + +void WeakConstraint::printHead(std::ostream &out) const { + assert(tuple_.size() > 1); + out << "["; + out << tuple_.front() << "@" << tuple_[1]; + for (auto it(tuple_.begin() + 2), ie(tuple_.end()); it != ie; ++it) { out << "," << *it; } + out << "]"; +} + +void WeakConstraint::print(std::ostream &out) const { + out << ":~" << lits_ << "."; + printHead(out); +} + +WeakConstraint::~WeakConstraint() noexcept = default; + +// }}}1 + +// Body Aggregates + +// {{{1 definition of BodyAggregateComplete + +BodyAggregateComplete::BodyAggregateComplete(DomainData &data, UTerm &&repr, AggregateFunction fun, BoundVec &&bounds) +: def_(std::move(repr), &data.add()) +, accuRepr_(completeRepr_(def_.domRepr())) +, fun_(fun) +, bounds_(std::move(bounds)) +, inst_(*this) { + switch (fun) { + case AggregateFunction::COUNT: + case AggregateFunction::SUMP: + case AggregateFunction::MAX: { + for (auto &x : bounds_) { + if (x.rel != Relation::GT && x.rel != Relation::GEQ) { monotone_ = false; break; } + } + break; + } + case AggregateFunction::MIN: { + for (auto &x : bounds_) { + if (x.rel != Relation::LT && x.rel != Relation::LEQ) { monotone_ = false; break; } + } + break; + } + default: { monotone_ = false; break; } + } +} + +bool BodyAggregateComplete::isNormal() const { + return true; +} + +void BodyAggregateComplete::analyze(Dep::Node &node, Dep &dep) { + dep.depends(node, *this); + def_.analyze(node, dep); +} + +void BodyAggregateComplete::startLinearize(bool active) { + def_.setActive(active); + if (active) { inst_ = Instantiator(*this); } +} + +void BodyAggregateComplete::linearize(Scripts &, bool, Logger &) { + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} + +void BodyAggregateComplete::enqueue(Queue &q) { + def_.init(); + q.enqueue(inst_); +} + +void BodyAggregateComplete::printHead(std::ostream &out) const { + out << *def_.domRepr(); +} + +void BodyAggregateComplete::propagate(Queue &queue) { + def_.enqueue(queue); +} + +void BodyAggregateComplete::report(Output::OutputBase &, Logger &) { + auto &dom = this->dom(); + for (auto &offset : todo_) { + auto &atm = dom[offset]; + assert(offset < dom.size()); + if (atm.satisfiable()) { dom.define(offset); } + atm.setRecursive(outputRecursive_); + atm.setEnqueued(false); + } + todo_.clear(); +} + +void BodyAggregateComplete::print(std::ostream &out) const { + printHead(out); + out << ":-"; + print_comma(out, accuDoms_, ",", [this](std::ostream &out, BodyAggregateAccumulate const &x) -> void { x.printHead(out); out << occType_; }); + out << "."; +} + +UGTerm BodyAggregateComplete::getRepr() const { + return accuRepr_->gterm(); +} + +bool BodyAggregateComplete::isPositive() const { + return true; +} + +bool BodyAggregateComplete::isNegative() const { + return false; +} + +void BodyAggregateComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType BodyAggregateComplete::getType() const { + return occType_; +} + +BodyAggregateComplete::DefinedBy &BodyAggregateComplete::definedBy() { + return defBy_; +} + +void BodyAggregateComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +void BodyAggregateComplete::enqueue(BodyAggregateDomain::Iterator atom) { + if (!atom->defined() && !atom->enqueued()) { + atom->setEnqueued(true); + todo_.emplace_back(atom - dom().begin()); + } +} + +BodyAggregateComplete::~BodyAggregateComplete() noexcept = default; + +// {{{1 definition of BodyAggregateAccumulate + +BodyAggregateAccumulate::BodyAggregateAccumulate(BodyAggregateComplete &complete, UTermVec &&tuple, ULitVec &&lits) +: AbstractStatement(get_clone(complete.accuRepr()), nullptr, std::move(lits)) +, complete_(complete) +, tuple_(std::move(tuple)) {} + +BodyAggregateAccumulate::~BodyAggregateAccumulate() noexcept = default; + +void BodyAggregateAccumulate::collectImportant(Term::VarSet &vars) { + VarTermBoundVec bound; + def_.domRepr()->collect(bound, false); + for (auto &x : tuple_) { x->collect(bound, false); } + for (auto &x : bound) { vars.emplace(x.first->name); } +} + +void BodyAggregateAccumulate::report(Output::OutputBase &out, Logger &log) { + auto &vals = out.tempVals(); + bool undefined = false; + for (auto &x : tuple_) { vals.emplace_back(x->eval(undefined, log)); } + Symbol repr(complete_.domRepr()->eval(undefined, log)); + if (!undefined) { + auto &tempLits = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { tempLits.emplace_back(lit.first); } + } + auto &dom = complete_.dom(); + auto atom = dom.reserve(repr); + if (!atom->initialized()) { + atom->init(complete_.fun(), _initBounds(complete_.bounds(), log), complete_.monotone()); + } + atom->accumulate(out.data, tuple_.empty() ? def_.domRepr()->loc() : tuple_.front()->loc(), vals, tempLits, log); + complete_.enqueue(atom); + } +} + +void BodyAggregateAccumulate::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + if (isOutputRecursive()) { complete_.setOutputRecursive(); } +} + +void BodyAggregateAccumulate::printHead(std::ostream &out) const { + out << "#accu(" << *complete_.domRepr() << ",tuple(" << tuple_ << "))"; +} + +// {{{1 definition of BodyAggregateLiteral + +BodyAggregateLiteral::BodyAggregateLiteral(BodyAggregateComplete &complete, NAF naf) +: complete_(complete) +, naf_(naf) { } + +BodyAggregateLiteral::~BodyAggregateLiteral() noexcept = default; + +UGTerm BodyAggregateLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool BodyAggregateLiteral::isPositive() const { + return naf_ == NAF::POS && complete_.monotone(); +} + +bool BodyAggregateLiteral::isNegative() const { + return naf_ != NAF::POS; +} + +void BodyAggregateLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType BodyAggregateLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &BodyAggregateLiteral::definedBy() { + return defs_; +} + +void BodyAggregateLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + +void BodyAggregateLiteral::print(std::ostream &out) const { + out << naf_; + auto it = std::begin(complete_.bounds()), ie = std::end(complete_.bounds()); + if (it != ie) { + it->bound->print(out); + out << inv(it->rel); + ++it; + } + out << complete_.fun() << "{" << *complete_.domRepr() << type_ << "}"; + if (it != ie) { + out << it->rel; + it->bound->print(out); + } +} + +bool BodyAggregateLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *BodyAggregateLiteral::occurrence() { + return this; +} + +void BodyAggregateLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, naf_ == NAF::POS); +} + +UIdx BodyAggregateLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), naf_, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score BodyAggregateLiteral::score(Term::VarSet const &bound, Logger &) { + return naf_ == NAF::POS ? estimate(complete_.dom().size(), *complete_.domRepr(), bound) : 0; +} + +std::pair BodyAggregateLiteral::toOutput(Logger &) { + if (offset_ == std::numeric_limits::max()) { + assert(naf_ == NAF::NOT); + return {Output::LiteralId(), true}; + } + auto &dom = complete_.dom(); + auto &atm = dom[offset_]; + switch (naf_) { + case NAF::POS: + case NAF::NOTNOT: { + return atm.fact() + ? std::make_pair(Output::LiteralId(), true) + : std::make_pair(Output::LiteralId{naf_, Output::AtomType::BodyAggregate, offset_, dom.domainOffset()}, false); + } + case NAF::NOT: { + return !atm.recursive() && !atm.satisfiable() + ? std::make_pair(Output::LiteralId(), true) + : std::make_pair(Output::LiteralId{naf_, Output::AtomType::BodyAggregate, offset_, dom.domainOffset()}, false); + } + } + assert(false); + return {Output::LiteralId(),true}; +} + +// }}}1 + +// {{{1 definition of AssignmentAggregateComplete + +AssignmentAggregateComplete::AssignmentAggregateComplete(DomainData &data, UTerm &&repr, UTerm &&dataRepr, AggregateFunction fun) +: def_(std::move(repr), &data.add()) +, dataRepr_(std::move(dataRepr)) +, fun_(fun) +, inst_(*this) { +} + +bool AssignmentAggregateComplete::isNormal() const { + return true; +} + +void AssignmentAggregateComplete::analyze(Dep::Node &node, Dep &dep) { + dep.depends(node, *this); + def_.analyze(node, dep); +} + +void AssignmentAggregateComplete::startLinearize(bool active) { + def_.setActive(active); + if (active) { inst_ = Instantiator(*this); } +} + +void AssignmentAggregateComplete::linearize(Scripts &, bool, Logger &) { + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} + +void AssignmentAggregateComplete::enqueue(Queue &q) { + def_.init(); + q.enqueue(inst_); +} + +void AssignmentAggregateComplete::printHead(std::ostream &out) const { + out << *def_.domRepr(); +} + +void AssignmentAggregateComplete::propagate(Queue &queue) { + def_.enqueue(queue); +} + +void AssignmentAggregateComplete::report(Output::OutputBase &out, Logger &) { + for (auto &dataOffset : todo_) { + auto &dom = this->dom(); + auto &data = dom.data(dataOffset); + auto values = data.values(); + + SymVec &atmArgs = out.tempVals(); + Symbol dataVal(data); + if (dataVal.type() == SymbolType::Fun) { + atmArgs.assign(begin(dataVal.args()), end(dataVal.args())); + } + atmArgs.emplace_back(); + for (auto &y : values) { + atmArgs.back() = y; + auto ret = dom.define(Symbol::createFun(dataVal.name(), Potassco::toSpan(atmArgs))); + if (values.size() == 1) { ret.first->setFact(true); } + std::get<0>(ret)->setData(dataOffset); + std::get<0>(ret)->setRecursive(outputRecursive_); + } + data.setEnqueued(false); + } + todo_.clear(); +} + +void AssignmentAggregateComplete::print(std::ostream &out) const { + printHead(out); + out << ":-"; + print_comma(out, accuDoms_, ";", [this](std::ostream &out, AssignmentAggregateAccumulate const &x) -> void { x.printHead(out); out << occType_; }); + out << "."; +} + +UGTerm AssignmentAggregateComplete::getRepr() const { + return dataRepr_->gterm(); +} + +bool AssignmentAggregateComplete::isPositive() const { + return true; +} + +bool AssignmentAggregateComplete::isNegative() const { + return false; +} + +void AssignmentAggregateComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType AssignmentAggregateComplete::getType() const { + return occType_; +} + +AssignmentAggregateComplete::DefinedBy &AssignmentAggregateComplete::definedBy() { + return defBy_; +} + +void AssignmentAggregateComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +void AssignmentAggregateComplete::enqueue(Id_t dataId) { + auto &data = dom().data(dataId); + if (!data.enqueued()) { + data.setEnqueued(true); + todo_.emplace_back(dataId); + } +} + +AssignmentAggregateComplete::~AssignmentAggregateComplete() noexcept = default; + +// {{{1 Definition of AssignmentAggregateAccumulate + +AssignmentAggregateAccumulate::AssignmentAggregateAccumulate(AssignmentAggregateComplete &complete, UTermVec &&tuple, ULitVec &&lits) +: AbstractStatement(get_clone(complete.dataRepr()), nullptr, std::move(lits)) +, complete_(complete) +, tuple_(std::move(tuple)) { } + +AssignmentAggregateAccumulate::~AssignmentAggregateAccumulate() noexcept = default; + +void AssignmentAggregateAccumulate::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + if (isOutputRecursive()) { complete_.setOutputRecursive(); } +} + +void AssignmentAggregateAccumulate::collectImportant(Term::VarSet &vars) { + VarTermBoundVec bound; + def_.domRepr()->collect(bound, false); + for (auto &x : tuple_) { x->collect(bound, false); } + for (auto &x : bound) { vars.emplace(x.first->name); } +} + +void AssignmentAggregateAccumulate::report(Output::OutputBase &out, Logger &log) { + auto &tempVals = out.tempVals(); + bool undefined = false; + for (auto &x : tuple_) { tempVals.emplace_back(x->eval(undefined, log)); } + Symbol dataRepr(complete_.dataRepr()->eval(undefined, log)); + if (undefined) { return; } + auto &tempLits = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { tempLits.emplace_back(lit.first); } + } + auto &dom = complete_.dom(); + auto dataId = dom.data(dataRepr, complete_.fun()); + auto &data = dom.data(dataId); + data.accumulate(out.data, tuple_.empty() ? def_.domRepr()->loc() : tuple_.front()->loc(), tempVals, tempLits, log); + complete_.enqueue(dataId); +} + +void AssignmentAggregateAccumulate::printHead(std::ostream &out) const { + out << "#accu(" << *complete_.domRepr() << ",tuple(" << tuple_ << "))"; +} + +// {{{1 Definition of AssignmentAggregateLiteral + +AssignmentAggregateLiteral::AssignmentAggregateLiteral(AssignmentAggregateComplete &complete) +: complete_(complete) { } + +AssignmentAggregateLiteral::~AssignmentAggregateLiteral() noexcept = default; + +UGTerm AssignmentAggregateLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool AssignmentAggregateLiteral::isPositive() const { + return false; +} + +bool AssignmentAggregateLiteral::isNegative() const { + return false; +} + +void AssignmentAggregateLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType AssignmentAggregateLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &AssignmentAggregateLiteral::definedBy() { + return defs_; +} + +void AssignmentAggregateLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +void AssignmentAggregateLiteral::print(std::ostream &out) const { + out << static_cast(*complete_.domRepr()).args.back() << "=" << complete_.fun() << "{" << *complete_.domRepr() << "}" << type_; +} + +bool AssignmentAggregateLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *AssignmentAggregateLiteral::occurrence() { + return this; +} + +void AssignmentAggregateLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, true); +} + +UIdx AssignmentAggregateLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), NAF::POS, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score AssignmentAggregateLiteral::score(Term::VarSet const &bound, Logger &) { + return estimate(complete_.dom().size(), *complete_.domRepr(), bound); +} + +std::pair AssignmentAggregateLiteral::toOutput(Logger &) { + assert(offset_ != InvalidId); + auto &atm = complete_.dom()[offset_]; + return atm.fact() + ? std::make_pair(Output::LiteralId(), true) + : std::make_pair(Output::LiteralId{NAF::POS, Output::AtomType::AssignmentAggregate, offset_, complete_.dom().domainOffset()}, false); +} + +///}}}1 + +// {{{1 definition of ConjunctionLiteral + +ConjunctionLiteral::ConjunctionLiteral(ConjunctionComplete &complete) +: complete_(complete) { } + +ConjunctionLiteral::~ConjunctionLiteral() noexcept = default; + +UGTerm ConjunctionLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool ConjunctionLiteral::isPositive() const { + return true; +} + +bool ConjunctionLiteral::isNegative() const { + return false; +} + +void ConjunctionLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType ConjunctionLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &ConjunctionLiteral::definedBy() { + return defs_; +} + +void ConjunctionLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +void ConjunctionLiteral::print(std::ostream &out) const { + out << *complete_.domRepr() << type_; +} + +bool ConjunctionLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *ConjunctionLiteral::occurrence() { + return this; +} + +void ConjunctionLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, true); +} + +UIdx ConjunctionLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), NAF::POS, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score ConjunctionLiteral::score(Term::VarSet const &bound, Logger &) { + return estimate(complete_.dom().size(), *complete_.domRepr(), bound); +} + +std::pair ConjunctionLiteral::toOutput(Logger &) { + assert(offset_ != InvalidId); + auto &atm = complete_.dom()[offset_]; + return atm.fact() + ? std::make_pair(Output::LiteralId(), true) + : std::make_pair(Output::LiteralId{NAF::POS, Output::AtomType::Conjunction, offset_, complete_.dom().domainOffset()}, false); +} + +// {{{1 definition of ConjunctionAccumulateEmpty + +ConjunctionAccumulateEmpty::ConjunctionAccumulateEmpty(ConjunctionComplete &complete, ULitVec &&lits) +: AbstractStatement(complete.emptyRepr(), &complete.emptyDom(), std::move(lits)) +, complete_(complete) { } + +ConjunctionAccumulateEmpty::~ConjunctionAccumulateEmpty() noexcept = default; + +bool ConjunctionAccumulateEmpty::isNormal() const { + return true; +} + +void ConjunctionAccumulateEmpty::report(Output::OutputBase &, Logger &log) { + complete_.reportEmpty(log); + bool undefined = false; + complete_.emptyDom().define(def_.domRepr()->eval(undefined, log), false); + assert(!undefined); +} + +// {{{1 definition of ConjunctionAccumulateCond + +ConjunctionAccumulateCond::ConjunctionAccumulateCond(ConjunctionComplete &complete, ULitVec &&lits) +: AbstractStatement(complete.condRepr(), &complete.condDom(), std::move(lits)) +, complete_(complete) { + lits_.emplace_back(gringo_make_unique(true, complete_.emptyDom(), NAF::POS, complete.emptyRepr())); +} + +ConjunctionAccumulateCond::~ConjunctionAccumulateCond() noexcept = default; + +void ConjunctionAccumulateCond::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + if (isOutputRecursive()) { complete_.setCondRecursive(); } +} + +bool ConjunctionAccumulateCond::isNormal() const { + return true; +} + +void ConjunctionAccumulateCond::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol condRepr(def_.domRepr()->eval(undefined, log)); + assert(!undefined); + + Output::LitVec &cond = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto y = x->toOutput(log); + if (!y.second) { cond.emplace_back(y.first); } + } + complete_.condDom().define(condRepr, cond.empty()); + complete_.reportCond(out.data, condRepr.args()[2], cond, log); +} + +// {{{1 definition of ConjunctionAccumulateHead + +ConjunctionAccumulateHead::ConjunctionAccumulateHead(ConjunctionComplete &complete, ULitVec &&lits) +: AbstractStatement(complete.headRepr(), nullptr, std::move(lits)) +, complete_(complete) { + lits_.emplace_back(gringo_make_unique(true, complete_.condDom(), NAF::POS, complete.condRepr())); +} + +ConjunctionAccumulateHead::~ConjunctionAccumulateHead() noexcept = default; + +void ConjunctionAccumulateHead::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + if (isOutputRecursive()) { complete_.setHeadRecursive(); } +} + +bool ConjunctionAccumulateHead::isNormal() const { + return true; +} + +void ConjunctionAccumulateHead::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol condRepr(def_.domRepr()->eval(undefined, log)); + assert(!undefined); + + Output::LitVec head; + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto y = x->toOutput(log); + if (!y.second) { head.emplace_back(y.first); } + } + + complete_.reportHead(out.data, condRepr.args()[2], head, log); +} + +// {{{1 definition of ConjunctionComplete + +ConjunctionComplete::ConjunctionComplete(DomainData &data, UTerm &&repr, UTermVec &&local) +: def_(std::move(repr), &data.add()) +, domEmpty_(def_.domRepr()->getSig()) // Note: any sig will do +, domCond_(def_.domRepr()->getSig()) // Note: any sig will do +, inst_(*this) +, local_(std::move(local)) { } + +UTerm ConjunctionComplete::emptyRepr() const { + UTermVec args; + args.emplace_back(make_locatable(def_.domRepr()->loc(), Symbol::createId("empty"))); + args.emplace_back(get_clone(def_.domRepr())); + args.emplace_back(make_locatable(def_.domRepr()->loc(), "", UTermVec())); + return make_locatable(def_.domRepr()->loc(), "#accu", std::move(args)); +} + +UTerm ConjunctionComplete::condRepr() const { + UTermVec args; + args.emplace_back(make_locatable(def_.domRepr()->loc(), Symbol::createId("cond"))); + args.emplace_back(get_clone(def_.domRepr())); + args.emplace_back(make_locatable(def_.domRepr()->loc(), "", get_clone(local_))); + return make_locatable(def_.domRepr()->loc(), "#accu", std::move(args)); +} + +UTerm ConjunctionComplete::headRepr() const { + UTermVec args; + args.emplace_back(make_locatable(def_.domRepr()->loc(), Symbol::createId("head"))); + args.emplace_back(get_clone(def_.domRepr())); + args.emplace_back(make_locatable(def_.domRepr()->loc(), "", get_clone(local_))); + return make_locatable(def_.domRepr()->loc(), "#accu", std::move(args)); +} + +UTerm ConjunctionComplete::accuRepr() const { + UTermVec args; + args.emplace_back(make_locatable(def_.domRepr()->loc(), "#Any1", std::make_shared(Symbol::createNum(0)))); + args.emplace_back(get_clone(def_.domRepr())); + args.emplace_back(make_locatable(def_.domRepr()->loc(), "#Any2", std::make_shared(Symbol::createNum(0)))); + return make_locatable(def_.domRepr()->loc(), "#accu", std::move(args)); +} + +bool ConjunctionComplete::isNormal() const { + return true; +} + +void ConjunctionComplete::analyze(Dep::Node &node, Dep &dep){ + dep.depends(node, *this); + def_.analyze(node, dep); +} + +void ConjunctionComplete::startLinearize(bool active){ + def_.setActive(active); + if (active) { inst_ = Instantiator(*this); } +} + +void ConjunctionComplete::linearize(Scripts &, bool, Logger &){ + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} + +void ConjunctionComplete::enqueue(Queue &q){ + def_.init(); + q.enqueue(inst_); +} + +void ConjunctionComplete::printHead(std::ostream &out) const{ + out << *def_.domRepr(); +} + +void ConjunctionComplete::propagate(Queue &queue) { + def_.enqueue(queue); +} + +template +void ConjunctionComplete::reportOther(F f, Logger &log) { + bool undefined = false; + auto atom = dom().reserve(domRepr()->eval(undefined, log)); + assert(!undefined); + f(atom); + if (!atom->blocked() && !atom->defined() && !atom->enqueued()) { + atom->setEnqueued(true); + todo_.emplace_back(atom - dom().begin()); + } +} + +void ConjunctionComplete::reportEmpty(Logger &log) { + reportOther([](ConjunctionDomain::Iterator) { }, log); +} + +void ConjunctionComplete::reportCond(DomainData &data, Symbol cond, Output::LitVec &lits, Logger &log) { + reportOther([&](ConjunctionDomain::Iterator atom) { atom->accumulateCond(data, cond, lits); }, log); +} + +void ConjunctionComplete::reportHead(DomainData &data, Symbol cond, Output::LitVec &lits, Logger &log) { + reportOther([&](ConjunctionDomain::Iterator atom) { atom->accumulateHead(data, cond, lits); }, log); +} + +void ConjunctionComplete::report(Output::OutputBase &, Logger &) { + // NOTE: this code relies on priority set to 1! + // NOTE about handling incompleteness: + // - if both the condition and the head are stratified + // then the conjunction is complete + // - if the condition is stratified but the head is recursive, + // then the conjunction is complete if all heads are fact + for (auto &offset : todo_) { + auto &atom = dom()[offset]; + if (!atom.blocked()) { + dom().define(offset); + atom.init(headRecursive_, condRecursive_); + } + atom.setEnqueued(false); + } + todo_.clear(); +} + +void ConjunctionComplete::print(std::ostream &out) const{ + printHead(out); + out << ":-" << *accuRepr(); +} + +UGTerm ConjunctionComplete::getRepr() const { + return accuRepr()->gterm(); +} + +bool ConjunctionComplete::isPositive() const { + return true; +} + +bool ConjunctionComplete::isNegative() const { + return false; +} + +void ConjunctionComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType ConjunctionComplete::getType() const { + return occType_; +} + +ConjunctionComplete::DefinedBy &ConjunctionComplete::definedBy() { + return defBy_; +} + +void ConjunctionComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + +ConjunctionComplete::~ConjunctionComplete() noexcept = default; + +// }}}1 + +// {{{1 definition of DisjointComplete + +DisjointComplete::DisjointComplete(DomainData &data, UTerm &&repr) +: def_(std::move(repr), &data.add()) +, accuRepr_(completeRepr_(def_.domRepr())) +, inst_(*this) { } + +bool DisjointComplete::isNormal() const { + return false; +} +void DisjointComplete::analyze(Dep::Node &node, Dep &dep) { + dep.depends(node, *this); + def_.analyze(node, dep); +} +void DisjointComplete::startLinearize(bool active) { + def_.setActive(active); + if (active) { inst_ = Instantiator(*this); } +} +void DisjointComplete::linearize(Scripts &, bool, Logger &) { + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} +void DisjointComplete::enqueue(Queue &q) { + def_.init(); + q.enqueue(inst_); +} +void DisjointComplete::printHead(std::ostream &out) const { + out << *def_.domRepr(); +} +void DisjointComplete::propagate(Queue &queue) { + def_.enqueue(queue); +} +void DisjointComplete::report(Output::OutputBase &, Logger &) { + for (auto &x : todo_) { + dom()[x].init(outputRecursive_); + dom().define(x); + } + todo_.clear(); +} + + +void DisjointComplete::enqueue(DisjointDomain::Iterator atom) { + if (!atom->enqueued() && !atom->defined()) { + todo_.emplace_back(atom - dom().begin()); + atom->setEnqueued(true); + } +} + +void DisjointComplete::print(std::ostream &out) const { + printHead(out); + out << ":-"; + print_comma(out, accuDoms_, ",", [](std::ostream &out, DisjointAccumulate const &x) { x.printHead(out); }); + out << "."; +} + +UGTerm DisjointComplete::getRepr() const { + return accuRepr_->gterm(); +} + +bool DisjointComplete::isPositive() const { + return true; +} + +bool DisjointComplete::isNegative() const { + return false; +} + +void DisjointComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType DisjointComplete::getType() const { + return occType_; +} + +DisjointComplete::DefinedBy &DisjointComplete::definedBy() { + return defBy_; +} + +void DisjointComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +DisjointComplete::~DisjointComplete() noexcept = default; + +// {{{1 definition of DisjointAccumulate + +DisjointAccumulate::DisjointAccumulate(DisjointComplete &complete, ULitVec &&lits) + : AbstractStatement(get_clone(complete.accuRepr()), nullptr, std::move(lits)) + , complete_(complete) + , value_({}) + , neutral_(true) { } + +DisjointAccumulate::DisjointAccumulate(DisjointComplete &complete, UTermVec &&tuple, CSPAddTerm &&value, ULitVec &&lits) + : AbstractStatement(get_clone(complete.accuRepr()), nullptr, std::move(lits)) + , complete_(complete) + , tuple_(std::move(tuple)) + , value_(std::move(value)) + , neutral_(false) { } + +DisjointAccumulate::~DisjointAccumulate() noexcept = default; + +void DisjointAccumulate::collectImportant(Term::VarSet &vars) { + VarTermBoundVec bound; + def_.domRepr()->collect(bound, false); + value_.collect(bound); + for (auto &x : tuple_) { x->collect(bound, false); } + for (auto &x : bound) { vars.emplace(x.first->name); } +} + +void DisjointAccumulate::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + if (isOutputRecursive()) { complete_.setOutputRecursive(); } +} + +void DisjointAccumulate::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol repr(complete_.domRepr()->eval(undefined, log)); + assert(!undefined); + auto atom = complete_.dom().reserve(repr); + if (!neutral_) { + auto &tempVals = out.tempVals(); + for (auto &x : tuple_) { tempVals.emplace_back(x->eval(undefined, log)); } + if (!undefined && value_.checkEval(log)) { + CSPGroundLit gVal(Relation::EQ, {}, 0); + value_.toGround(gVal, false, log); + Output::LitVec &outLits = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { outLits.emplace_back(lit.first); } + } + atom->accumulate(out.data, tempVals, std::move(std::get<1>(gVal)), -std::get<2>(gVal), outLits); + } + } + complete_.enqueue(atom); +} + +void DisjointAccumulate::printHead(std::ostream &out) const { + out << "#accu(" << *complete_.domRepr() << ","; + if (!value_.terms.empty()) { + out << value_; + } else { + out << "#neutral"; + } + if (!tuple_.empty()) { + out << ",tuple(" << tuple_ << ")"; + } + out << ")"; +} + +// {{{1 definition of DisjointLiteral + +DisjointLiteral::DisjointLiteral(DisjointComplete &complete, NAF naf) +: complete_(complete) +, naf_(naf) { +} + +DisjointLiteral::~DisjointLiteral() noexcept = default; + +UGTerm DisjointLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool DisjointLiteral::isPositive() const { + return false; +} + +bool DisjointLiteral::isNegative() const { + return naf_ != NAF::POS; +} + +void DisjointLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType DisjointLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &DisjointLiteral::definedBy() { + return defs_; +} + +void DisjointLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +void DisjointLiteral::print(std::ostream &out) const { + out << naf_ << "#disjoint{" << *complete_.domRepr() << type_ << "}"; +} + +bool DisjointLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *DisjointLiteral::occurrence() { + return this; +} + +void DisjointLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, naf_ == NAF::POS); +} + +UIdx DisjointLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), naf_, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score DisjointLiteral::score(Term::VarSet const &bound, Logger &) { + return naf_ == NAF::POS ? estimate(complete_.dom().size(), *complete_.domRepr(), bound) : 0; +} + +std::pair DisjointLiteral::toOutput(Logger &) { + if (offset_ == InvalidId) { + assert(naf_ == NAF::NOT); + return {Output::LiteralId(), true}; + } + auto &dom = complete_.dom(); + auto &atm = dom[offset_]; + return atm.fact() && naf_ != NAF::NOT + ? std::make_pair(Output::LiteralId(), true) + : std::make_pair(Output::LiteralId{naf_, Output::AtomType::Disjoint, offset_, dom.domainOffset()}, false); +} + +// }}}1 + +// {{{1 definition of TheoryComplete + +TheoryComplete::TheoryComplete(DomainData &data, UTerm &&repr, TheoryAtomType type, UTerm &&name) +: def_(std::move(repr), &data.add()) +, accuRepr_(completeRepr_(def_.domRepr())) +, op_("") +, name_(std::move(name)) +, inst_(*this) +, type_(type) { } + +TheoryComplete::TheoryComplete(DomainData &data, UTerm &&repr, TheoryAtomType type, UTerm &&name, String op, Output::UTheoryTerm &&guard) +: def_(std::move(repr), &data.add()) +, accuRepr_(completeRepr_(def_.domRepr())) +, op_(op) +, guard_(std::move(guard)) +, name_(std::move(name)) +, inst_(*this) +, type_(type) { } + +bool TheoryComplete::isNormal() const { + return false; +} + +void TheoryComplete::analyze(Dep::Node &node, Dep &dep) { + dep.depends(node, *this); + def_.analyze(node, dep); +} + +void TheoryComplete::startLinearize(bool active) { + def_.setActive(active); + if (active) { inst_ = Instantiator(*this); } +} + +void TheoryComplete::linearize(Scripts &, bool, Logger &) { + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} + +void TheoryComplete::enqueue(Queue &q) { + def_.init(); + q.enqueue(inst_); +} + +void TheoryComplete::enqueue(TheoryDomain::Iterator atom) { + if (!atom->enqueued() && !atom->defined()) { + todo_.emplace_back(atom - dom().begin()); + atom->setEnqueued(true); + } +} + +void TheoryComplete::printHead(std::ostream &out) const { + out << *def_.domRepr(); + if (guard_) { + out << op_; + guard_->print(out); + } +} + +void TheoryComplete::propagate(Queue &queue) { + def_.enqueue(queue); +} + +void TheoryComplete::report(Output::OutputBase &, Logger &) { + for (auto &x : todo_) { + auto &atm = dom()[x]; + dom().define(x); + atm.setEnqueued(false); + atm.setRecursive(outputRecursive_); + } + todo_.clear(); +} + +void TheoryComplete::print(std::ostream &out) const { + printHead(out); + out << ":-"; + print_comma(out, accuDoms_, ",", [](std::ostream &out, TheoryAccumulate const &x) { x.printHead(out); }); + out << "."; +} + +UGTerm TheoryComplete::getRepr() const { + return accuRepr_->gterm(); +} + +bool TheoryComplete::isPositive() const { + return true; +} + +bool TheoryComplete::isNegative() const { + return false; +} + +void TheoryComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType TheoryComplete::getType() const { + return occType_; +} + +TheoryComplete::DefinedBy &TheoryComplete::definedBy() { + return defBy_; +} + +void TheoryComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +TheoryComplete::~TheoryComplete() noexcept = default; + +// {{{1 definition of TheoryAccumulate + +TheoryAccumulate::TheoryAccumulate(TheoryComplete &complete, ULitVec &&lits) + : AbstractStatement(get_clone(complete.accuRepr()), nullptr, std::move(lits)) + , complete_(complete) + , neutral_(true) { } + +TheoryAccumulate::TheoryAccumulate(TheoryComplete &complete, Output::UTheoryTermVec &&tuple, ULitVec &&lits) + : AbstractStatement(get_clone(complete.accuRepr()), nullptr, std::move(lits)) + , complete_(complete) + , tuple_(std::move(tuple)) + , neutral_(false) { } + +TheoryAccumulate::~TheoryAccumulate() noexcept = default; + +void TheoryAccumulate::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + if (isOutputRecursive()) { complete_.setOutputRecursive(); } +} + +void TheoryAccumulate::collectImportant(Term::VarSet &vars) { + VarTermBoundVec bound; + def_.domRepr()->collect(bound, false); + for (auto &x : tuple_) { x->collect(bound); } + for (auto &x : bound) { vars.emplace(x.first->name); } +} + +void TheoryAccumulate::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol repr(complete_.domRepr()->eval(undefined, log)); + Symbol name(complete_.name()->eval(undefined, log)); + if (!undefined) { + auto atom = complete_.dom().reserve(repr); + if (!atom->initialized()) { + Id_t n = out.data.theory().addTerm(name); + Id_t g = complete_.hasGuard() ? complete_.guard()->eval(out.data.theory(), log) : InvalidId; + Id_t o = complete_.hasGuard() ? out.data.theory().addTerm(complete_.op().c_str()) : InvalidId; + atom->init(complete_.type(), n, o, g); + } + if (!neutral_) { + std::vector outTuple; + for (auto &x : tuple_) { + outTuple.emplace_back(x->eval(out.data.theory(), log)); + } + Output::LitVec outLits; + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { outLits.emplace_back(lit.first); } + } + auto elemId = out.data.theory().addElem(Potassco::toSpan(outTuple), std::move(outLits)); + atom->accumulate(elemId); + } + complete_.enqueue(atom); + } +} + +void TheoryAccumulate::printHead(std::ostream &out) const { + out << "#accu(" << *complete_.domRepr() << ","; + if (!tuple_.empty()) { + out << "tuple(" << tuple_ << ")"; + } + else { + out << "#neutral"; + } + out << ")"; +} + +// {{{1 definition of TheoryLiteral + +TheoryLiteral::TheoryLiteral(TheoryComplete &complete, NAF naf, bool auxiliary) +: complete_(complete) +, naf_(naf) +, auxiliary_(auxiliary) { } + +TheoryLiteral::~TheoryLiteral() noexcept = default; + +UGTerm TheoryLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool TheoryLiteral::isPositive() const { + return false; +} + +bool TheoryLiteral::isNegative() const { + return naf_ != NAF::POS; +} + +void TheoryLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType TheoryLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &TheoryLiteral::definedBy() { + return defs_; +} + +void TheoryLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { +} + +void TheoryLiteral::print(std::ostream &out) const { + out << naf_ << "&"; + complete_.name()->print(out); + out << " {" << *complete_.domRepr() << type_ << "}"; + if (complete_.hasGuard()) { + out << complete_.op(); + complete_.guard()->print(out); + } +} + +bool TheoryLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *TheoryLiteral::occurrence() { + return this; +} + +void TheoryLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, naf_ == NAF::POS); +} + +UIdx TheoryLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), naf_, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score TheoryLiteral::score(Term::VarSet const &bound, Logger &) { + return naf_ == NAF::POS ? estimate(complete_.dom().size(), *complete_.domRepr(), bound) : 0; +} + +std::pair TheoryLiteral::toOutput(Logger &) { + if (offset_ == std::numeric_limits::max()) { + assert(naf_ == NAF::NOT); + return {Output::LiteralId(), true}; + } + auto &dom = complete_.dom(); + return std::make_pair(Output::LiteralId{naf_, Output::AtomType::Theory, offset_, dom.domainOffset()}, false); +} + +// {{{1 definition of TheoryRule + +TheoryRule::TheoryRule(TheoryLiteral &lit, ULitVec &&lits) + : AbstractStatement(nullptr, nullptr, std::move(lits)) + , lit_(lit) { } + +TheoryRule::~TheoryRule() noexcept = default; + +void TheoryRule::collectImportant(Term::VarSet &vars) { + lit_.collectImportant(vars); +} + +void TheoryRule::report(Output::OutputBase &out, Logger &log) { + if (lit_.type() == TheoryAtomType::Directive) { + Output::TheoryDirective td(lit_.toOutput(log).first); + out.output(td); + } + else { + Output::Rule rule; + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto ret = x->toOutput(log); + if (ret.first && (out.keepFacts || !ret.second)) { + rule.addBody(ret.first); + } + } + rule.addHead(lit_.toOutput(log).first); + out.output(rule); + } +} + +void TheoryRule::printHead(std::ostream &out) const { + lit_.print(out); +} + +// }}}1 + +// Head Aggregates + +// {{{1 definition of HeadAggregateRule + +HeadAggregateRule::HeadAggregateRule(HeadAggregateComplete &complete, ULitVec &&lits) +: AbstractStatement(get_clone(complete.domRepr()), &complete.dom(), std::move(lits)) +, complete_(complete) { } + +HeadAggregateRule::~HeadAggregateRule() noexcept = default; + +void HeadAggregateRule::report(Output::OutputBase &out, Logger &log) { + Output::Rule &rule(out.tempRule(false)); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto ret = x->toOutput(log); + if (ret.first.valid() && (out.keepFacts || !ret.second)) { + rule.addBody(ret.first); + } + } + + auto &dom = complete_.dom(); + bool undefined = false; + auto ret(dom.define(def_.domRepr()->eval(undefined, log))); + if (!ret.first->initialized()) { + ret.first->init(complete_.fun(), _initBounds(complete_.bounds(), log)); + } + // Note: init bounds and all that stuff should be done here + assert(!undefined); + Id_t offset = ret.first - dom.begin(); + rule.addHead(Output::LiteralId{NAF::POS, Output::AtomType::HeadAggregate, offset, dom.domainOffset()}); + out.output(rule); +} + +void HeadAggregateRule::print(std::ostream &out) const { + auto it(complete_.bounds().begin()), ie(complete_.bounds().end()); + if (it != ie) { + out << *it->bound; + out << inv(it->rel); + ++it; + } + out << complete_.fun() << "(" << *def_.domRepr() << ")"; + for (; it != ie; ++it) { + out << it->rel; + out << *it->bound; + } + if (!lits_.empty()) { + out << ":-"; + auto g = [](std::ostream &out, ULit const &x) { if (x) { out << *x; } else { out << "#null?"; } }; + print_comma(out, lits_, ",", g); + } + out << "."; +} + +// {{{1 definition of HeadAggregateAccumulate + +HeadAggregateAccumulate::HeadAggregateAccumulate(HeadAggregateComplete &complete, UTermVec &&tuple, PredicateDomain *predDom, UTerm &&predRepr, ULitVec &&lits) +: AbstractStatement(completeRepr_(complete.domRepr()), nullptr, std::move(lits)) +, complete_(complete) +, predDef_(std::move(predRepr), predDom) +, tuple_(std::move(tuple)) { } + +HeadAggregateAccumulate::~HeadAggregateAccumulate() noexcept = default; + +void HeadAggregateAccumulate::collectImportant(Term::VarSet &vars) { + VarTermBoundVec bound; + def_.domRepr()->collect(bound, false); + predDef_.collectImportant(vars); + for (auto &x : tuple_) { x->collect(bound, false); } + for (auto &x : bound) { vars.emplace(x.first->name); } +} + +void HeadAggregateAccumulate::report(Output::OutputBase &out, Logger &log) { + auto &vals = out.tempVals(); + bool undefined = false; + for (auto &x : tuple_) { vals.emplace_back(x->eval(undefined, log)); } + if (undefined) { return; } + Symbol predVal(predDef_ ? predDef_.domRepr()->eval(undefined, log) : Symbol()); + if (undefined) { return; } + auto &tempLits = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { tempLits.emplace_back(lit.first); } + } + Symbol headVal(complete_.domRepr()->eval(undefined, log)); + assert(!undefined); + auto &dom = complete_.dom(); + auto atm = dom.find(headVal); + assert(atm != dom.end()); + Output::LiteralId lit; + if (predDef_) { + auto &predDom = static_cast(predDef_.dom()); + auto predAtm = predDom.reserve(predVal); + if (!predAtm->fact()) { + lit = Output::LiteralId(NAF::POS, Output::AtomType::Predicate, predAtm - predDom.begin(), predDom.domainOffset()); + } + } + atm->accumulate(out.data, tuple_.empty() ? def_.domRepr()->loc() : tuple_.front()->loc(), vals, lit, tempLits, log); + complete_.enqueue(atm); +} + +void HeadAggregateAccumulate::printHead(std::ostream &out) const { + out << "#accu(" << *complete_.domRepr() << ","; + if (predDef_) { + out << *predDef_.domRepr() << ",tuple(" << tuple_ << ")"; + } + else { out << "#true"; } + out << ")"; +} + +// {{{1 definition of HeadAggregateComplete + +HeadAggregateComplete::HeadAggregateComplete(DomainData &data, UTerm &&repr, AggregateFunction fun, BoundVec &&bounds) +: repr_(std::move(repr)) +, domain_(data.add()) +, inst_(*this) +, fun_(fun) +, bounds_(std::move(bounds)) { } + +void HeadAggregateComplete::enqueue(HeadAggregateDomain::Iterator atm) { + if (!atm->enqueued()) { + todo_.emplace_back(atm - dom().begin()); + atm->setEnqueued(true); + } +} + +bool HeadAggregateComplete::isNormal() const { return false; } + +void HeadAggregateComplete::analyze(Dep::Node &node, Dep &dep) { + for (HeadAggregateAccumulate &x : accuDoms_) { + x.predDef().analyze(node, dep); + } + dep.depends(node, *this); +} +void HeadAggregateComplete::startLinearize(bool active) { + for (HeadAggregateAccumulate &x : accuDoms_) { + x.predDef().setActive(active); + } + if (active) { inst_ = Instantiator(*this); } +} +void HeadAggregateComplete::linearize(Scripts &, bool, Logger &) { + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} +void HeadAggregateComplete::enqueue(Queue &q) { + for (HeadAggregateAccumulate &x : accuDoms_) { + if (x.predDef()) { x.predDef().init(); } + } + q.enqueue(inst_); +} +void HeadAggregateComplete::printHead(std::ostream &out) const { + auto it(bounds_.begin()), ie(bounds_.end()); + if (it != ie) { + out << *it->bound; + out << inv(it->rel); + ++it; + } + out << fun_ << "{"; + print_comma(out, accuDoms_, ";", [](std::ostream &out, HeadAggregateAccumulate const &x) -> void { + out << x.tuple(); + out << ":"; + if (x.predDef()) { + out << x.predDef().domRepr(); + } else { + out << "#true"; + } + out << ":"; + x.printHead(out); + }); + + out << "}"; + for (; it != ie; ++it) { + out << it->rel; + out << *it->bound; + } +} +void HeadAggregateComplete::propagate(Queue &queue) { + for (HeadAggregateAccumulate &x : accuDoms_) { + if (x.predDef()) { x.predDef().enqueue(queue); } + } +} +void HeadAggregateComplete::print(std::ostream &out) const { + printHead(out); + out << ":-" << repr_ << occType_ << "."; +} +void HeadAggregateComplete::report(Output::OutputBase &out, Logger &) { + for (auto &x : todo_) { + auto &atm = dom()[x]; + if (atm.satisfiable()) { + // Note: this is not as lazy at is could be + // in the recursive case this would define atoms more that once ... + for (auto &elem : atm.elems()) { + for (auto &cond : elem.second) { + if (cond.first) { out.data.predDoms()[cond.first.domain()]->define(cond.first.offset()); } + } + } + } + atm.setEnqueued(false); + } + todo_.clear(); +} + +UGTerm HeadAggregateComplete::getRepr() const { + return completeRepr_(repr_)->gterm(); +} + +bool HeadAggregateComplete::isPositive() const { + return true; +} + +bool HeadAggregateComplete::isNegative() const { + return false; +} + +void HeadAggregateComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType HeadAggregateComplete::getType() const { + return occType_; +} + +HeadAggregateComplete::DefinedBy &HeadAggregateComplete::definedBy() { + return defBy_; +} + +HeadAggregateDomain &HeadAggregateComplete::dom() { + return domain_; +} + +void HeadAggregateComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + +HeadAggregateComplete::~HeadAggregateComplete() noexcept = default; + +// {{{1 definition of HeadAggregateLiteral + +HeadAggregateLiteral::HeadAggregateLiteral(HeadAggregateComplete &complete) +: complete_(complete) { } + +HeadAggregateLiteral::~HeadAggregateLiteral() noexcept = default; + +UGTerm HeadAggregateLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool HeadAggregateLiteral::isPositive() const { + return true; +} + +bool HeadAggregateLiteral::isNegative() const { + return false; +} + +void HeadAggregateLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType HeadAggregateLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &HeadAggregateLiteral::definedBy() { + return defs_; +} + +void HeadAggregateLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + +void HeadAggregateLiteral::print(std::ostream &out) const { + out << *complete_.domRepr() << type_; +} + +bool HeadAggregateLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *HeadAggregateLiteral::occurrence() { + return this; +} + +void HeadAggregateLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, true); +} + +UIdx HeadAggregateLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), NAF::POS, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score HeadAggregateLiteral::score(Term::VarSet const &bound, Logger &) { + return estimate(complete_.dom().size(), *complete_.domRepr(), bound); +} + +std::pair HeadAggregateLiteral::toOutput(Logger &) { + return {Output::LiteralId{}, true}; +} + +// }}}1 + +// {{{1 definition of DisjunctionRule + +DisjunctionRule::DisjunctionRule(DisjunctionComplete &complete, ULitVec &&lits) +: AbstractStatement(get_clone(complete.domRepr()), &complete.dom(), std::move(lits)) +, complete_(complete) { +} + +bool DisjunctionRule::isNormal() const { + return false; +} + +DisjunctionRule::~DisjunctionRule() noexcept = default; + +void DisjunctionRule::report(Output::OutputBase &out, Logger &log) { + Output::Rule &rule(out.tempRule(false)); + bool fact = true; + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto ret = x->toOutput(log); + if (ret.first.valid() && (out.keepFacts || !ret.second)) { + rule.addBody(ret.first); + if (!ret.second) { fact = false; } + } + } + auto &dom = complete_.dom(); + bool undefined = false; + auto ret(dom.define(def_.domRepr()->eval(undefined, log))); + if (fact) { ret.first->setFact(true); } + assert(!undefined); + complete_.enqueue(ret.first); + Id_t offset = ret.first - dom.begin(); + rule.addHead(Output::LiteralId{NAF::POS, Output::AtomType::Disjunction, offset, dom.domainOffset()}); + out.output(rule); +} + +// {{{1 definition of DisjunctionLiteral + +DisjunctionLiteral::DisjunctionLiteral(DisjunctionComplete &complete) +: complete_(complete) { } + +DisjunctionLiteral::~DisjunctionLiteral() noexcept = default; + +UGTerm DisjunctionLiteral::getRepr() const { + return complete_.domRepr()->gterm(); +} + +bool DisjunctionLiteral::isPositive() const { + return true; +} + +bool DisjunctionLiteral::isNegative() const { + return false; +} + +void DisjunctionLiteral::setType(OccurrenceType x) { + type_ = x; +} + +OccurrenceType DisjunctionLiteral::getType() const { + return type_; +} + +BodyOcc::DefinedBy &DisjunctionLiteral::definedBy() { + return defs_; +} + +void DisjunctionLiteral::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + +void DisjunctionLiteral::print(std::ostream &out) const { + out << "[" << *complete_.domRepr() << type_ << "]"; +} + +bool DisjunctionLiteral::isRecursive() const { + return type_ == OccurrenceType::UNSTRATIFIED; +} + +BodyOcc *DisjunctionLiteral::occurrence() { + return this; +} + +void DisjunctionLiteral::collect(VarTermBoundVec &vars) const { + complete_.domRepr()->collect(vars, true); +} + +UIdx DisjunctionLiteral::index(Scripts &, BinderType type, Term::VarSet &bound) { + return make_binder(complete_.dom(), NAF::POS, *complete_.domRepr(), offset_, type, isRecursive(), bound, 0); +} + +Literal::Score DisjunctionLiteral::score(Term::VarSet const &bound, Logger &) { + return estimate(complete_.dom().size(), *complete_.domRepr(), bound); +} + +std::pair DisjunctionLiteral::toOutput(Logger &) { + return {Output::LiteralId{}, true}; +} + +// {{{1 definition of DisjunctionComplete + +DisjunctionComplete::DisjunctionComplete(DomainData &data, UTerm &&repr) +: repr_(std::move(repr)) +, domain_(data.add()) +, inst_(*this) { } + +bool DisjunctionComplete::isNormal() const { + return true; +} + +void DisjunctionComplete::analyze(Dep::Node &node, Dep &dep) { + dep.depends(node, *this); + for (DisjunctionAccumulate &accu : accu_) { accu.predDef().analyze(node, dep); } +} + +void DisjunctionComplete::startLinearize(bool active) { + for (DisjunctionAccumulate &accu : accu_) { + accu.predDef().setActive(active); + } + if (active) { inst_ = Instantiator(*this); } +} + +void DisjunctionComplete::linearize(Scripts &, bool, Logger &) { + auto binder = gringo_make_unique(); + for (HeadOccurrence &x : defBy_) { x.defines(*binder->getUpdater(), &inst_); } + inst_.add(std::move(binder), Instantiator::DependVec{}); + inst_.finalize(Instantiator::DependVec{}); +} + +void DisjunctionComplete::enqueue(Queue &q) { + for (DisjunctionAccumulate &x : accu_) { + x.predDef().init(); + } + q.enqueue(inst_); +} + +void DisjunctionComplete::printHead(std::ostream &out) const { + bool comma = false; + for (DisjunctionAccumulate &accu : accu_) { + if (comma) { out << ";"; } + comma = true; + accu.printPred(out); + } +} + +void DisjunctionComplete::propagate(Queue &queue) { + for (DisjunctionAccumulate &accu : accu_) { + accu.predDef().enqueue(queue); + } +} + +void DisjunctionComplete::enqueue(DisjunctionDomain::Iterator atom) { + if (!atom->enqueued()) { + atom->setEnqueued(true); + todo_.emplace_back(atom - dom().begin()); + } +} + +void DisjunctionComplete::report(Output::OutputBase &out, Logger &) { + for (auto &offset : todo_) { + auto &atm = dom()[offset]; + atm.init(occType_ == OccurrenceType::UNSTRATIFIED); + // Note: it is complete wrong to use the fact method of the atom interface like this + // this just works because the disjunction literal is auxiliary and never negative + // this method should be renamed!!! + if (!atm.headFact()) { + // Note: this is not as lazy at is could be + // in the recursive case this would define atoms more that once ... + for (auto &elem : atm.elems()) { + for (auto &clauseId : elem.heads()) { + for (auto &lit : out.data.clause(clauseId)) { + // Note: for singleton disjunctions with empty bodies facts could be derived here + // (it wouldn't even be that difficult) + if (lit.sign() == NAF::POS && lit.type() == Gringo::Output::AtomType::Predicate) { + out.data.predDoms()[lit.domain()]->define(lit.offset()); + } + } + } + } + } + } +} + +void DisjunctionComplete::print(std::ostream &out) const{ + printHead(out); + out << ":-" << *completeRepr_(repr_) << occType_; +} + +UGTerm DisjunctionComplete::getRepr() const { + return completeRepr_(repr_)->gterm(); +} + +bool DisjunctionComplete::isPositive() const { + return true; +} + +bool DisjunctionComplete::isNegative() const { + return false; +} + +void DisjunctionComplete::setType(OccurrenceType x) { + occType_ = x; +} + +OccurrenceType DisjunctionComplete::getType() const { + return occType_; +} + +DisjunctionComplete::DefinedBy &DisjunctionComplete::definedBy() { + return defBy_; +} + +void DisjunctionComplete::checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + +DisjunctionComplete::~DisjunctionComplete() noexcept = default; + +// {{{1 definition of DisjunctionAccumulate + +void DisjunctionAccumulateHead::report(Output::OutputBase &out, Logger &log) { + accu_.reportHead(out, log); +} +void DisjunctionAccumulateHead::printHead(std::ostream &out) const { + if (accu_.predDef()) { + out << *accu_.predDef().domRepr(); + } + else { out << "#false"; } +} + +DisjunctionAccumulate::DisjunctionAccumulate(DisjunctionComplete &complete, PredicateDomain *predDom, UTerm &&predRepr, ULitVec &&headCond, UTerm &&elemRepr, ULitVec &&lits) +: AbstractStatement(completeRepr_(complete.domRepr()), nullptr, std::move(lits)) +, complete_(complete) +, elemRepr_(std::move(elemRepr)) +, predDef_(std::move(predRepr), predDom) +, headCond_(std::move(headCond)) +, accuHead_(*this) +, instHead_(accuHead_) { + complete_.addAccu(*this); + lits_.emplace_back(gringo_make_unique(complete_)); +} + +DisjunctionAccumulate::~DisjunctionAccumulate() noexcept = default; + +void DisjunctionAccumulate::analyze(Dep::Node &node, Dep &dep) { + AbstractStatement::analyze(node, dep); + for (auto &x : headCond_) { + auto occ(x->occurrence()); + if (occ) { dep.depends(node, *occ, false); } + } +} + +void DisjunctionAccumulate::linearize(Scripts &scripts, bool positive, Logger &log) { + AbstractStatement::linearize(scripts, positive, log); + Term::VarSet important; + if (predDef_) { predDef_.collectImportant(important); } + Term::VarSet boundInitially; + // Note: this performs a nested instantiation + // to do this, the linearization is initialized with the variables bound by the outer instantiator + // by construction, there cannot be positive recursive literals in it + elemRepr_->collect(boundInitially); + complete_.domRepr()->collect(boundInitially); + InstVec insts = _linearize(log, scripts, positive, accuHead_, std::move(important), headCond_, boundInitially); + assert(insts.size() == 1); + instHead_ = std::move(insts.front()); +} + +void DisjunctionAccumulate::collectImportant(Term::VarSet &vars) { + predDef_.collectImportant(vars); + AbstractStatement::collectImportant(vars); + for (auto &x : headCond_) { x->collectImportant(vars); } +} + +void DisjunctionAccumulate::printPred(std::ostream &out) const { + if (predDef_) { out << *predDef_.domRepr(); } + else { out << "#false"; } + bool sep = false; + for (auto &x : headCond_) { + out << (sep ? "," : ":"); + sep = true; + x->print(out); + } +} + +void DisjunctionAccumulate::reportHead(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol predRepr; + if (predDef_) { predRepr = predDef_.domRepr()->eval(undefined, log); } + if (undefined) { return; } + Symbol domRepr(complete_.domRepr()->eval(undefined, log)); + Symbol elemRepr(elemRepr_->eval(undefined, log)); + assert(!undefined); + auto &dom = complete_.dom(); + auto atm = dom.find(domRepr); + assert(atm != dom.end()); + auto &tempLits = out.tempLits(); + for (auto &x : headCond_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { tempLits.emplace_back(lit.first.negate()); } + } + if (predDef_) { + auto &predDom = static_cast(predDef_.dom()); + auto predAtm = predDom.reserve(predRepr); + if (predAtm->fact()) { return; } + tempLits.emplace_back(Output::LiteralId(NAF::POS, Output::AtomType::Predicate, predAtm - predDom.begin(), predDom.domainOffset())); + } + complete_.enqueue(atm); + atm->accumulateHead(out.data, elemRepr, tempLits); +} + +void DisjunctionAccumulate::report(Output::OutputBase &out, Logger &log) { + bool undefined = false; + Symbol domRepr(complete_.domRepr()->eval(undefined, log)); + Symbol elemRepr(elemRepr_->eval(undefined, log)); + assert(!undefined); + auto &tempLits = out.tempLits(); + for (auto &x : lits_) { + if (x->auxiliary()) { continue; } + auto lit = x->toOutput(log); + if (!lit.second) { tempLits.emplace_back(lit.first); } + } + auto &dom = complete_.dom(); + auto atm = dom.find(domRepr); + assert(atm != dom.end()); + atm->accumulateCond(out.data, elemRepr, tempLits); + instHead_.instantiate(out, log); +} + +// }}}1 + +} } // namespace Ground Gringo + diff --git a/libgringo/src/input/aggregate.cc b/libgringo/src/input/aggregate.cc new file mode 100644 index 0000000..22459ab --- /dev/null +++ b/libgringo/src/input/aggregate.cc @@ -0,0 +1,125 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/bug.hh" +#include "gringo/logger.hh" +#include "gringo/input/aggregate.hh" + +namespace Gringo { namespace Input { + +// {{{ definition of AssignLevel + +void AssignLevel::add(VarTermBoundVec &vars) { + for (auto &occ : vars) { occurr[occ.first->name].emplace_back(occ.first); } +} +AssignLevel &AssignLevel::subLevel() { + childs.emplace_front(); + return childs.front(); +} +void AssignLevel::assignLevels() { + BoundSet bound; + assignLevels(0, bound); +} +void AssignLevel::assignLevels(unsigned level, BoundSet const &parent) { + BoundSet bound(parent); + for (auto &occs : occurr) { + auto ret = bound.emplace(occs.first, level); + for (auto &occ : occs.second) { occ->level = ret.first->second; } + } + for (auto &child : childs) { child.assignLevels(level + 1, bound); } +} +AssignLevel::~AssignLevel() { } + +// }}} +// {{{ definition of CheckLevel + +bool CheckLevel::Ent::operator<(Ent const &) const { return false; } +CheckLevel::CheckLevel(Location const &loc, Printable const &p) : loc(loc), p(p) { } +CheckLevel::CheckLevel(CheckLevel &&) = default; +CheckLevel::SC::VarNode &CheckLevel::var(VarTerm &var) { + auto &node = vars[var.name]; + if (!node) { node = &dep.insertVar(&var); } + return *node; +} +void CheckLevel::check(Logger &log) { + dep.order(); + auto vars(dep.open()); + if (!vars.empty()) { + auto cmp = [](SC::VarNode const *x, SC::VarNode const *y) -> bool{ + if (x->data->name != y->data->name) { return x->data->name < y->data->name; } + return x->data->loc() < y->data->loc(); + }; + std::sort(vars.begin(), vars.end(), cmp); + std::ostringstream msg; + msg << loc << ": error: unsafe variables in:\n " << p << "\n"; + for (auto &x : vars) { msg << x->data->loc() << ": note: '" << x->data->name << "' is unsafe\n"; } + GRINGO_REPORT(log, clingo_error_runtime) << msg.str(); + } +} +CheckLevel::~CheckLevel() { } + +void addVars(ChkLvlVec &levels, VarTermBoundVec &vars) { + for (auto &x: vars) { + auto &lvl(levels[x.first->level]); + bool bind = x.second && levels.size() == x.first->level + 1; + if (bind) { lvl.dep.insertEdge(*lvl.current, lvl.var(*x.first)); } + else { lvl.dep.insertEdge(lvl.var(*x.first), *lvl.current); } + } +} + +// }}} +// {{{ declaration of ToGroundArg + +ToGroundArg::ToGroundArg(unsigned &auxNames, DomainData &domains) + : auxNames(auxNames) + , domains(domains) { } +String ToGroundArg::newId(bool increment) { + auxNames+= increment; + return ("#d" + std::to_string(auxNames-increment)).c_str(); +} +UTermVec ToGroundArg::getGlobal(VarTermBoundVec const &vars) { + std::unordered_set seen; + UTermVec global; + for (auto &occ : vars) { + if (occ.first->level == 0 && seen.emplace(occ.first->name).second) { + global.emplace_back(occ.first->clone()); + } + } + return global; +} +UTermVec ToGroundArg::getLocal(VarTermBoundVec const &vars) { + std::unordered_set seen; + UTermVec local; + for (auto &occ : vars) { + if (occ.first->level != 0 && seen.emplace(occ.first->name).second) { + local.emplace_back(occ.first->clone()); + } + } + return local; +} +UTerm ToGroundArg::newId(UTermVec &&global, Location const &loc, bool increment) { + if (!global.empty()) { return make_locatable(loc, newId(increment), std::move(global)); } + else { return make_locatable(loc, Symbol::createId(newId(increment))); } +} +ToGroundArg::~ToGroundArg() { } + +// }}} + +} } // namespace Input Gringo diff --git a/libgringo/src/input/aggregates.cc b/libgringo/src/input/aggregates.cc new file mode 100644 index 0000000..a77d5d9 --- /dev/null +++ b/libgringo/src/input/aggregates.cc @@ -0,0 +1,2237 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/bug.hh" +#include "gringo/input/aggregates.hh" +#include "gringo/input/literals.hh" +#include "gringo/ground/statements.hh" +#include "gringo/ground/literals.hh" +#include "gringo/logger.hh" + +namespace Gringo { namespace Input { + +namespace { + +// {{{ definition of auxiliary functions + +template +void _print(std::ostream &out, AggregateFunction fun, T const &x, U const &y, V const &f) { + auto it = std::begin(x), ie = std::end(x); + if (it != ie) { + it->bound->print(out); + out << inv(it->rel); + ++it; + } + out << fun << "{"; + print_comma(out, y, ";", f); + out << "}"; + for (; it != ie; ++it) { + out << it->rel; + it->bound->print(out); + } +} + +auto _printCond = [](std::ostream &out, CondLit const &x) { + using namespace std::placeholders; + x.first->print(out); + out << ":"; + print_comma(out, x.second, ",", std::bind(&Literal::print, _2, _1)); +}; + +std::function _unpool_lit(bool beforeRewrite) { + return [beforeRewrite](ULit const &x) { return x->unpool(beforeRewrite); }; +} +auto _unpool_bound = [](Bound &x) { return x.unpool(); }; + +void _add(ChkLvlVec &levels, ULit const &lit, bool bind) { + VarTermBoundVec vars; + levels.back().current = &levels.back().dep.insertEnt(); + lit->collect(vars, bind); + addVars(levels, vars); +} + +void _add(ChkLvlVec &levels, UTermVec const &terms, CSPAddTerm const *term = nullptr) { + VarTermBoundVec vars; + levels.back().current = &levels.back().dep.insertEnt(); + for (auto &x : terms) { x->collect(vars, false); } + if (term) { term->collect(vars); } + addVars(levels, vars); +} + +void _add(ChkLvlVec &levels, ULitVec const &cond) { + for (auto &x : cond) { _add(levels, x, true); } +} + +template +void _aggr(ChkLvlVec &levels, BoundVec const &bounds, T const &f, bool bind) { + bool assign = false; + CheckLevel::SC::EntNode *depend = 0; + for (auto &y : bounds) { + if (bind && y.rel == Relation::EQ) { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + y.bound->collect(vars, true); + addVars(levels, vars); + f(); + assign = true; + } + else { + if (!depend) { depend = &levels.back().dep.insertEnt(); } + levels.back().current = depend; + VarTermBoundVec vars; + y.bound->collect(vars, false); + addVars(levels, vars); + } + } + if (!depend && !assign) { depend = &levels.back().dep.insertEnt(); } + if (depend) { + levels.back().current = depend; + f(); + } +} + +void warnGlobal(VarTermBoundVec &vars, bool warn, Logger &log) { + if (warn) { + auto ib = vars.begin(), ie = vars.end(); + ie = std::remove_if(ib, ie, [](VarTermBoundVec::value_type const &a) { return a.first->level > 0; }); + std::sort(ib, ie, [](VarTermBoundVec::value_type const &a, VarTermBoundVec::value_type const &b) { return a.first->name < b.first->name; }); + ie = std::unique(ib, ie, [](VarTermBoundVec::value_type const &a, VarTermBoundVec::value_type const &b) { return a.first->name == b.first->name; }); + for (auto it = ib; it != ie; ++it) { + GRINGO_REPORT(log, clingo_warning_global_variable) + << it->first->loc() << ": info: global variable in tuple of aggregate element:\n" + << " " << it->first->name << "\n" + ; + } + } +} + +// }}}1 + +} // namespace + +// {{{1 definition of TupleBodyAggregate + +TupleBodyAggregate::TupleBodyAggregate(NAF naf, AggregateFunction fun, BoundVec &&bounds, BodyAggrElemVec &&elems) + : TupleBodyAggregate(naf, false, false, fun, std::move(bounds), std::move(elems)) { } + +TupleBodyAggregate::TupleBodyAggregate(NAF naf, bool removedAssignment, bool translated, AggregateFunction fun, BoundVec &&bounds, BodyAggrElemVec &&elems) + : naf(naf) + , removedAssignment(removedAssignment) + , translated(translated) + , fun(fun) + , bounds(std::move(bounds)) + , elems(std::move(elems)) { } + +TupleBodyAggregate::~TupleBodyAggregate() { } + +void TupleBodyAggregate::print(std::ostream &out) const { + auto f = [](std::ostream &out, BodyAggrElem const &y) { + using namespace std::placeholders; + print_comma(out, y.first, ",", std::bind(&Term::print, _2, _1)); + out << ":"; + print_comma(out, y.second, ",", std::bind(&Literal::print, _2, _1)); + }; + out << naf; + _print(out, fun, bounds, elems, f); +} + +size_t TupleBodyAggregate::hash() const { + return get_value_hash(typeid(TupleBodyAggregate).hash_code(), size_t(naf), size_t(fun), bounds, elems); +} + +bool TupleBodyAggregate::operator==(BodyAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && naf == t->naf && fun == t->fun && is_value_equal_to(bounds, t->bounds) && is_value_equal_to(elems, t->elems); +} + +TupleBodyAggregate *TupleBodyAggregate::clone() const { + return make_locatable(loc(), naf, removedAssignment, translated, fun, get_clone(bounds), get_clone(elems)).release(); +} + +void TupleBodyAggregate::unpool(UBodyAggrVec &x, bool beforeRewrite) { + BodyAggrElemVec e; + for (auto &elem : elems) { + auto f = [&](UTermVec &&x) { + e.emplace_back(std::move(x), get_clone(elem.second)); + }; + Term::unpool(elem.first.begin(), elem.first.end(), Gringo::unpool, f); + } + elems = std::move(e); + e.clear(); + for (auto &elem : elems) { + if (beforeRewrite) { + auto f = [&](ULitVec &&y) { e.emplace_back(get_clone(elem.first), std::move(y)); }; + Term::unpool(elem.second.begin(), elem.second.end(), _unpool_lit(beforeRewrite), f); + } + else { + Term::unpoolJoin(elem.second, _unpool_lit(beforeRewrite)); + e.emplace_back(std::move(elem)); + } + } + auto f = [&](BoundVec &&y) { x.emplace_back(make_locatable(loc(), naf, removedAssignment, translated, fun, std::move(y), get_clone(e))); }; + Term::unpool(bounds.begin(), bounds.end(), _unpool_bound, f); +} + +void TupleBodyAggregate::collect(VarTermBoundVec &vars) const { + for (auto &bound : bounds) { bound.bound->collect(vars, bound.rel == Relation::EQ && naf == NAF::POS); } + for (auto &elem : elems) { + for (auto &term : std::get<0>(elem)) { term->collect(vars, false); } + for (auto &lit : std::get<1>(elem)) { lit->collect(vars, false); } + } +} + +bool TupleBodyAggregate::rewriteAggregates(UBodyAggrVec &aggr) { + BoundVec assign; + auto jt(bounds.begin()); + for (auto it = jt, ie = bounds.end(); it != ie; ++it) { + if (it->rel == Relation::EQ && naf == NAF::POS) { assign.emplace_back(std::move(*it)); } + else { + if (it != jt) { *jt = std::move(*it); } + ++jt; + } + } + bounds.erase(jt, bounds.end()); + bool skip = bounds.empty() && !assign.empty(); + for (auto it = assign.begin(), ie = assign.end() - skip; it != ie; ++it) { + BoundVec bound; + bound.emplace_back(std::move(*it)); + aggr.emplace_back(make_locatable(loc(), naf, removedAssignment, translated, fun, std::move(bound), get_clone(elems))); + } + if (skip) { bounds.emplace_back(std::move(assign.back())); } + return !bounds.empty(); +} + +bool TupleBodyAggregate::simplify(Projections &project, SimplifyState &state, bool, Logger &log) { + for (auto &bound : bounds) { + if (!bound.simplify(state, log)) { return false; } + } + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](BodyAggrElemVec::value_type &elem) { + SimplifyState elemState(state); + for (auto &term : std::get<0>(elem)) { + if (term->simplify(elemState, false, false, log).update(term).undefined()) { return true; } + } + for (auto &lit : std::get<1>(elem)) { + // NOTE: projection disabled with singelton=true + if (!lit->simplify(log, project, elemState, true, true)) { return true; } + } + for (auto &dot : elemState.dots) { std::get<1>(elem).emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { std::get<1>(elem).emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void TupleBodyAggregate::rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &, AuxGen &auxGen) { + for (auto &bound : bounds) { bound.rewriteArithmetics(arith, auxGen); } + for (auto &elem : elems) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : std::get<1>(elem)) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { std::get<1>(elem).emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { std::get<1>(elem).emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void TupleBodyAggregate::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + for (auto &bound : bounds) { bound.bound->collect(vars, false); } + lvl.add(vars); + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + for (auto &term : std::get<0>(elem)) { term->collect(vars, false); } + for (auto &lit : std::get<1>(elem)) { lit->collect(vars, false); } + local.add(vars); + } +} + +void TupleBodyAggregate::check(ChkLvlVec &levels, Logger &log) const { + auto f = [&]() { + VarTermBoundVec vars; + for (auto &y : elems) { + levels.emplace_back(loc(), *this); + _add(levels, y.first); + _add(levels, y.second); + levels.back().check(log); + levels.pop_back(); + for (auto &term : y.first) { term->collect(vars, false); } + } + warnGlobal(vars, !translated, log); + }; + return _aggr(levels, bounds, f, naf == NAF::POS); +} + +bool TupleBodyAggregate::hasPool(bool beforeRewrite) const { + for (auto &bound : bounds) { if (bound.bound->hasPool()) { return true; } } + for (auto &elem : elems) { + for (auto &term : elem.first) { if (term->hasPool()) { return true; } } + for (auto &lit : elem.second) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void TupleBodyAggregate::replace(Defines &x) { + for (auto &bound : bounds) { Term::replace(bound.bound, bound.bound->replace(x, true)); } + for (auto &elem : elems) { + for (auto &y : elem.first) { Term::replace(y, y->replace(x, true)); } + for (auto &y : elem.second) { y->replace(x); } + } +} + +CreateBody TupleBodyAggregate::toGround(ToGroundArg &x, Ground::UStmVec &stms) const { + if (!isAssignment()) { + stms.emplace_back(gringo_make_unique(x.domains, x.newId(*this), fun, get_clone(bounds))); + auto &completeRef = static_cast(*stms.back()); + CreateStmVec split; + split.emplace_back([&completeRef, this](Ground::ULitVec &&lits) -> Ground::UStm { + UTermVec tuple; + tuple.emplace_back(make_locatable(loc(), Symbol())); + // Note: should this become a function? + UTerm neutral; + switch (fun) { + case AggregateFunction::MIN: { neutral = make_locatable(loc(), Symbol::createSup()); break; } + case AggregateFunction::MAX: { neutral = make_locatable(loc(), Symbol::createInf()); break; } + default: { neutral = make_locatable(loc(), Symbol::createNum(0)); break; } + } + for (auto &y : bounds) { lits.emplace_back(gringo_make_unique(y.rel, get_clone(neutral), get_clone(y.bound))); } + auto ret = gringo_make_unique(completeRef, get_clone(tuple), std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + for (auto &y : elems) { + split.emplace_back([this,&completeRef,&y,&x](Ground::ULitVec &&lits) -> Ground::UStm { + for (auto &z : y.second) { lits.emplace_back(z->toGround(x.domains, false)); } + auto ret = gringo_make_unique(completeRef, get_clone(y.first), std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + } + return CreateBody([&completeRef, this](Ground::ULitVec &lits, bool primary, bool) { + if (primary) { lits.emplace_back(gringo_make_unique(completeRef, naf)); } + }, std::move(split)); + } + else { + assert(bounds.size() == 1 && naf == NAF::POS); + VarTermBoundVec vars; + for (auto &y : elems) { + for (auto &z : y.first) { z->collect(vars, false); } + for (auto &z : y.second) { z->collect(vars, false); } + } + UTermVec global(x.getGlobal(vars)); + global.emplace_back(get_clone(bounds.front().bound)); + UTermVec globalSpecial(x.getGlobal(vars)); + UTerm repr(x.newId(std::move(global), loc(), false)); + UTerm dataRepr(x.newId(std::move(globalSpecial), loc())); + + stms.emplace_back(gringo_make_unique(x.domains, get_clone(repr), get_clone(dataRepr), fun)); + auto &completeRef = static_cast(*stms.back()); + // NOTE: for assignment aggregates this does not make much sense + // the empty aggregate always matches and hence the elements + // should be grounded without auxLits + CreateStmVec split; + split.emplace_back([&completeRef, this](Ground::ULitVec &&lits) -> Ground::UStm { + UTermVec tuple; + tuple.emplace_back(make_locatable(loc(), Symbol())); + auto ret = gringo_make_unique(completeRef, get_clone(tuple), std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + for (auto &y : elems) { + split.emplace_back([this,&completeRef,&y,&x](Ground::ULitVec &&lits) -> Ground::UStm { + for (auto &z : y.second) { lits.emplace_back(z->toGround(x.domains, false)); } + auto ret = gringo_make_unique(completeRef, get_clone(y.first), std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + } + return CreateBody([&completeRef, this](Ground::ULitVec &lits, bool primary, bool) { + if (primary) { lits.emplace_back(gringo_make_unique(completeRef)); } + }, std::move(split)); + } +} + +bool TupleBodyAggregate::isAssignment() const { return !removedAssignment && bounds.size() == 1 && naf == NAF::POS && bounds.front().rel == Relation::EQ && bounds.front().bound->getInvertibility() == Term::INVERTIBLE; } + +void TupleBodyAggregate::removeAssignment() { + assert (isAssignment()); + removedAssignment = true; +} + +// {{{1 definition of LitBodyAggregate + +LitBodyAggregate::LitBodyAggregate(NAF naf, AggregateFunction fun, BoundVec &&bounds, CondLitVec &&elems) + : naf(naf) + , fun(fun) + , bounds(std::move(bounds)) + , elems(std::move(elems)) { } + +LitBodyAggregate::~LitBodyAggregate() { } + +void LitBodyAggregate::print(std::ostream &out) const { + out << naf; + _print(out, fun, bounds, elems, _printCond); +} + +size_t LitBodyAggregate::hash() const { + return get_value_hash(typeid(LitBodyAggregate).hash_code(), size_t(naf), size_t(fun), bounds, elems); +} + +bool LitBodyAggregate::operator==(BodyAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && naf == t->naf && fun == t->fun && is_value_equal_to(bounds, t->bounds) && is_value_equal_to(elems, t->elems); +} + +LitBodyAggregate *LitBodyAggregate::clone() const { + return make_locatable(loc(), naf, fun, get_clone(bounds), get_clone(elems)).release(); +} + +void LitBodyAggregate::unpool(UBodyAggrVec &x, bool beforeRewrite) { + CondLitVec e; + for (auto &elem : elems) { + auto f = [&](ULit &&y) { e.emplace_back(std::move(y), get_clone(elem.second)); }; + Term::unpool(elem.first, _unpool_lit(beforeRewrite), f); + } + elems = std::move(e); + e.clear(); + for (auto &elem : elems) { + if (beforeRewrite) { + auto f = [&](ULitVec &&y) { e.emplace_back(get_clone(elem.first), std::move(y)); }; + Term::unpool(elem.second.begin(), elem.second.end(), _unpool_lit(beforeRewrite), f); + } + else { + Term::unpoolJoin(elem.second, _unpool_lit(beforeRewrite)); + e.emplace_back(std::move(elem)); + } + } + auto f = [&](BoundVec &&y) { x.emplace_back(make_locatable(loc(), naf, fun, std::move(y), get_clone(e))); }; + Term::unpool(bounds.begin(), bounds.end(), _unpool_bound, f); +} + +void LitBodyAggregate::collect(VarTermBoundVec &vars) const { + for (auto &bound : bounds) { bound.bound->collect(vars, bound.rel == Relation::EQ && naf == NAF::POS); } + for (auto &elem : elems) { + elem.first->collect(vars, false); + for (auto &lit : elem.second) { lit->collect(vars, false); } + } +} + +bool LitBodyAggregate::rewriteAggregates(UBodyAggrVec &aggr) { + int id = 0; + BodyAggrElemVec elems; + for (auto &x : this->elems) { + UTermVec tuple; + x.first->toTuple(tuple, id); + ULitVec lits(std::move(x.second)); + lits.emplace_back(std::move(x.first)); + elems.emplace_back(std::move(tuple), std::move(lits)); + } + UBodyAggr x(make_locatable(loc(), naf, false, true, fun, std::move(bounds), std::move(elems))); + if (x->rewriteAggregates(aggr)) { aggr.emplace_back(std::move(x)); } + return false; +} + +bool LitBodyAggregate::simplify(Projections &project, SimplifyState &state, bool, Logger &log) { + for (auto &bound : bounds) { + if (!bound.simplify(state, log)) { return false; } + } + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](CondLitVec::value_type &elem) { + SimplifyState elemState(state); + if (!std::get<0>(elem)->simplify(log, project, elemState, true, true)) { return true; } + for (auto &lit : std::get<1>(elem)) { + // NOTE: projection disabled with singelton=true + if (!lit->simplify(log, project, elemState, true, true)) { return true; } + } + for (auto &dot : elemState.dots) { std::get<1>(elem).emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { std::get<1>(elem).emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void LitBodyAggregate::rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &, AuxGen &auxGen) { + for (auto &bound : bounds) { bound.rewriteArithmetics(arith, auxGen); } + for (auto &elem : elems) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : std::get<1>(elem)) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { std::get<1>(elem).emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { std::get<1>(elem).emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void LitBodyAggregate::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + for (auto &bound : bounds) { bound.bound->collect(vars, false); } + lvl.add(vars); + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + std::get<0>(elem)->collect(vars, false); + for (auto &lit : std::get<1>(elem)) { lit->collect(vars, false); } + local.add(vars); + } +} + +void LitBodyAggregate::check(ChkLvlVec &levels, Logger &log) const { + auto f = [&]() { + for (auto &y : elems) { + levels.emplace_back(loc(), *this); + _add(levels, y.first, false); + _add(levels, y.second); + levels.back().check(log); + levels.pop_back(); + } + }; + _aggr(levels, bounds, f, naf == NAF::POS); +} + +bool LitBodyAggregate::hasPool(bool beforeRewrite) const { + for (auto &bound : bounds) { if (bound.bound->hasPool()) { return true; } } + for (auto &elem : elems) { + if (elem.first->hasPool(beforeRewrite)) { return true; } + for (auto &lit : elem.second) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void LitBodyAggregate::replace(Defines &x) { + for (auto &bound : bounds) { Term::replace(bound.bound, bound.bound->replace(x, true)); } + for (auto &elem : elems) { + elem.first->replace(x); + for (auto &y : elem.second) { y->replace(x); } + } +} + +CreateBody LitBodyAggregate::toGround(ToGroundArg &, Ground::UStmVec &) const { + throw std::logic_error("Aggregate::rewriteAggregates must be called before LitAggregate::toGround"); +} + +bool LitBodyAggregate::isAssignment() const { return false; } + +void LitBodyAggregate::removeAssignment() { } + +// {{{1 definition of Conjunction + +Conjunction::Conjunction(ULit &&head, ULitVec &&cond) { + elems.emplace_back(ULitVecVec(), std::move(cond)); + elems.back().first.emplace_back(); + elems.back().first.back().emplace_back(std::move(head)); +} + +Conjunction::Conjunction(ElemVec &&elems) +: elems(std::move(elems)) { } + +Conjunction::~Conjunction() { } + +void Conjunction::print(std::ostream &out) const { + auto f = [](std::ostream &out, Elem const &y) { + using namespace std::placeholders; + print_comma(out, y.first, "|", [](std::ostream &out, ULitVec const &z) { + print_comma(out, z, "&", std::bind(&Literal::print, _2, _1)); + }); + out << ":"; + print_comma(out, y.second, ",", std::bind(&Literal::print, _2, _1)); + }; + print_comma(out, elems, ";", f); +} + +size_t Conjunction::hash() const { + return get_value_hash(typeid(Conjunction).hash_code(), elems); +} + +bool Conjunction::operator==(BodyAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(elems, t->elems); +} + +Conjunction *Conjunction::clone() const { + return make_locatable(loc(), get_clone(elems)).release(); +} + +void Conjunction::unpool(UBodyAggrVec &x, bool beforeRewrite) { + ElemVec e; + for (auto &elem : elems) { + if (beforeRewrite) { + ULitVecVec heads; + for (auto &head : elem.first) { + auto g = [&](ULitVec &&z) { heads.emplace_back(std::move(z)); }; + Term::unpool(head.begin(), head.end(), _unpool_lit(beforeRewrite), g); + } + elem.first = std::move(heads); + auto f = [&](ULitVec &&y) { e.emplace_back(get_clone(elem.first), std::move(y)); }; + Term::unpool(elem.second.begin(), elem.second.end(), _unpool_lit(beforeRewrite), f); + } + else { + for (auto &head : elem.first) { + Term::unpoolJoin(head, _unpool_lit(beforeRewrite)); + } + Term::unpoolJoin(elem.second, _unpool_lit(beforeRewrite)); + e.emplace_back(std::move(elem)); + } + } + x.emplace_back(make_locatable(loc(), std::move(e))); +} + +void Conjunction::collect(VarTermBoundVec &vars) const { + for (auto &elem : elems) { + for (auto &disj : elem.first) { + for (auto &lit : disj) { lit->collect(vars, false); } + } + for (auto &lit : elem.second) { lit->collect(vars, false); } + } +} + +bool Conjunction::rewriteAggregates(UBodyAggrVec &x) { + while (elems.size() > 1) { + ElemVec vec; + vec.emplace_back(std::move(elems.back())); + x.emplace_back(make_locatable(loc(), std::move(vec))); + elems.pop_back(); + } + return !elems.empty(); +} + +bool Conjunction::simplify(Projections &project, SimplifyState &state, bool, Logger &log) { + for (auto &elem : elems) { + elem.first.erase(std::remove_if(elem.first.begin(), elem.first.end(), [&](ULitVec &clause) { + SimplifyState elemState(state); + for (auto &lit : clause) { + if (!lit->simplify(log, project, elemState)) { return true; } + } + for (auto &dot : elemState.dots) { clause.emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { clause.emplace_back(ScriptLiteral::make(script)); } + return false; + }), elem.first.end()); + } + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](ElemVec::value_type &elem) { + SimplifyState elemState(state); + for (auto &lit : elem.second) { + // NOTE: projection disabled with singelton=true + if (!lit->simplify(log, project, elemState, true, true)) { return true; } + } + for (auto &dot : elemState.dots) { elem.second.emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { elem.second.emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void Conjunction::rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &, AuxGen &auxGen) { + for (auto &elem : elems) { + for (auto &y : elem.first) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &z : y) { + z->rewriteArithmetics(arith, assign, auxGen); + } + for (auto &z : arith.back()) { y.emplace_back(RelationLiteral::make(z)); } + for (auto &z : assign) { y.emplace_back(RelationLiteral::make(z)); } + arith.pop_back(); + } + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : elem.second) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { elem.second.emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { elem.second.emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void Conjunction::assignLevels(AssignLevel &lvl) { + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + for (auto &disj : elem.first) { + for (auto &lit : disj) { + lit->collect(vars, false); + } + } + for (auto &lit : elem.second) { lit->collect(vars, false); } + local.add(vars); + } +} + +void Conjunction::check(ChkLvlVec &levels, Logger &log) const { + levels.back().current = &levels.back().dep.insertEnt(); + for (auto &elem : elems) { + levels.emplace_back(loc(), *this); + _add(levels, elem.second); + // check safety of condition + levels.back().check(log); + levels.pop_back(); + for (auto &disj : elem.first) { + levels.emplace_back(loc(), *this); + _add(levels, disj); + _add(levels, elem.second); + // check safty of head it can contain pure variables! + levels.back().check(log); + levels.pop_back(); + } + } +} + +bool Conjunction::hasPool(bool beforeRewrite) const { + for (auto &elem : elems) { + for (auto &disj : elem.first) { + for (auto &lit : disj) { + if (lit->hasPool(beforeRewrite)) { return true; } + } + } + for (auto &lit : elem.second) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void Conjunction::replace(Defines &x) { + for (auto &elem : elems) { + for (auto &y : elem.first) { + for (auto &z : y) { z->replace(x); } + } + for (auto &y : elem.second) { y->replace(x); } + } +} + +CreateBody Conjunction::toGround(ToGroundArg &x, Ground::UStmVec &stms) const { + assert(elems.size() == 1); + + UTermVec local; + std::unordered_set seen; + VarTermBoundVec varsHead; + VarTermBoundVec varsBody; + for (auto &x : elems.front().first) { + for (auto &y : x) { y->collect(varsHead, false); } + } + for (auto &x : elems.front().second) { x->collect(varsBody, false); } + for (auto &occ : varsBody) { + if (occ.first->level != 0) { + seen.emplace(occ.first->name); + } + } + for (auto &occ : varsHead) { + if (occ.first->level != 0 && seen.find(occ.first->name) != seen.end()) { + local.emplace_back(occ.first->clone()); + } + } + stms.emplace_back(gringo_make_unique(x.domains, x.newId(*this), std::move(local))); + auto &completeRef = static_cast(*stms.back()); + + Ground::ULitVec condLits; + for (auto &y : elems.front().second) { condLits.emplace_back(y->toGround(x.domains, false)); } + stms.emplace_back(gringo_make_unique(completeRef, std::move(condLits))); + + for (auto &y : elems.front().first) { + Ground::ULitVec headLits; + for (auto &z : y) { + headLits.emplace_back(z->toGround(x.domains, false)); + } + stms.emplace_back(gringo_make_unique(completeRef, std::move(headLits))); + } + + CreateStmVec split; + split.emplace_back([&completeRef](Ground::ULitVec &&lits) -> Ground::UStm { + auto ret = gringo_make_unique(completeRef, std::move(lits)); + return std::move(ret); + }); + + return CreateBody([&completeRef](Ground::ULitVec &lits, bool primary, bool) { + if (primary) { lits.emplace_back(gringo_make_unique(completeRef)); } + }, std::move(split)); +} + +bool Conjunction::isAssignment() const { return false; } + +void Conjunction::removeAssignment() { } + +// {{{1 definition of SimpleBodyLiteral + +SimpleBodyLiteral::SimpleBodyLiteral(ULit &&lit) + : lit(std::move(lit)) { } + +Location const &SimpleBodyLiteral::loc() const { return lit->loc(); } + +void SimpleBodyLiteral::loc(Location const &loc) { lit->loc(loc); } + +SimpleBodyLiteral::~SimpleBodyLiteral() { } + +void SimpleBodyLiteral::print(std::ostream &out) const { lit->print(out); } + +size_t SimpleBodyLiteral::hash() const { + return get_value_hash(typeid(SimpleBodyLiteral).hash_code(), lit); +} + +bool SimpleBodyLiteral::operator==(BodyAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(lit, t->lit); +} + +SimpleBodyLiteral *SimpleBodyLiteral::clone() const { + return gringo_make_unique(get_clone(lit)).release(); +} + +void SimpleBodyLiteral::unpool(UBodyAggrVec &x, bool beforeRewrite) { + for (auto &y : lit->unpool(beforeRewrite)) { x.emplace_back(gringo_make_unique(std::move(y))); } +} + +void SimpleBodyLiteral::collect(VarTermBoundVec &vars) const { lit->collect(vars, true); } + +bool SimpleBodyLiteral::rewriteAggregates(UBodyAggrVec &) { return true; } + +bool SimpleBodyLiteral::simplify(Projections &project, SimplifyState &state, bool singleton, Logger &log) { + return lit->simplify(log, project, state, true, singleton); +} + +void SimpleBodyLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &assign, AuxGen &auxGen) { + lit->rewriteArithmetics(arith, assign, auxGen); +} + +void SimpleBodyLiteral::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + lit->collect(vars, false); + lvl.add(vars); +} + +void SimpleBodyLiteral::check(ChkLvlVec &levels, Logger &) const { + levels.back().current = &levels.back().dep.insertEnt(); + _add(levels, lit, true); +} + +bool SimpleBodyLiteral::hasPool(bool beforeRewrite) const { + return lit->hasPool(beforeRewrite); +} + +void SimpleBodyLiteral::replace(Defines &x) { + lit->replace(x); +} + +CreateBody SimpleBodyLiteral::toGround(ToGroundArg &x, Ground::UStmVec &) const { + return {[&](Ground::ULitVec &lits, bool, bool auxiliary) -> void { + lits.emplace_back(lit->toGround(x.domains, auxiliary)); + }, CreateStmVec()}; +} + +bool SimpleBodyLiteral::isAssignment() const { return false; } + +void SimpleBodyLiteral::removeAssignment() { } + +// }}}1 + +// {{{1 definition of HeadAggregate + +Symbol HeadAggregate::isEDB() const { return Symbol(); } + +// {{{1 definition of TupleHeadAggregate + +TupleHeadAggregate::TupleHeadAggregate(AggregateFunction fun, BoundVec &&bounds, HeadAggrElemVec &&elems) + : TupleHeadAggregate(fun, false, std::move(bounds), std::move(elems)) { } + +TupleHeadAggregate::TupleHeadAggregate(AggregateFunction fun, bool translated, BoundVec &&bounds, HeadAggrElemVec &&elems) + : fun(fun) + , translated(translated) + , bounds(std::move(bounds)) + , elems(std::move(elems)) { } + +TupleHeadAggregate::~TupleHeadAggregate() { } + +void TupleHeadAggregate::print(std::ostream &out) const { + auto f = [](std::ostream &out, HeadAggrElem const &y) { + using namespace std::placeholders; + print_comma(out, std::get<0>(y), ",", std::bind(&Term::print, _2, _1)); + out << ":"; + std::get<1>(y)->print(out); + out << ":"; + print_comma(out, std::get<2>(y), ",", std::bind(&Literal::print, _2, _1)); + }; + _print(out, fun, bounds, elems, f); +} + +size_t TupleHeadAggregate::hash() const { + return get_value_hash(typeid(TupleHeadAggregate).hash_code(), size_t(fun), bounds, elems); +} + +bool TupleHeadAggregate::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && fun == t->fun && is_value_equal_to(bounds, t->bounds) && is_value_equal_to(elems, t->elems); +} + +TupleHeadAggregate *TupleHeadAggregate::clone() const { + return make_locatable(loc(), fun, translated, get_clone(bounds), get_clone(elems)).release(); +} + +void TupleHeadAggregate::unpool(UHeadAggrVec &x, bool beforeRewrite) { + HeadAggrElemVec e; + for (auto &elem : elems) { + auto f = [&](UTermVec &&y) { e.emplace_back(std::move(y), get_clone(std::get<1>(elem)), get_clone(std::get<2>(elem))); }; + Term::unpool(std::get<0>(elem).begin(), std::get<0>(elem).end(), Gringo::unpool, f); + } + elems.clear(); + for (auto &elem : e) { + auto f = [&](ULit &&y) { elems.emplace_back(get_clone(std::get<0>(elem)), std::move(y), get_clone(std::get<2>(elem))); }; + Term::unpool(std::get<1>(elem), _unpool_lit(beforeRewrite), f); + } + e.clear(); + for (auto &elem : elems) { + if (beforeRewrite) { + auto f = [&](ULitVec &&y) { e.emplace_back(get_clone(std::get<0>(elem)), get_clone(std::get<1>(elem)), std::move(y)); }; + Term::unpool(std::get<2>(elem).begin(), std::get<2>(elem).end(), _unpool_lit(beforeRewrite), f); + } + else { + Term::unpoolJoin(std::get<2>(elem), _unpool_lit(beforeRewrite)); + e.emplace_back(std::move(elem)); + } + } + auto f = [&](BoundVec &&y) { x.emplace_back(make_locatable(loc(), fun, translated, std::move(y), get_clone(e))); }; + Term::unpool(bounds.begin(), bounds.end(), _unpool_bound, f); +} + +void TupleHeadAggregate::collect(VarTermBoundVec &vars) const { + for (auto &bound : bounds) { bound.bound->collect(vars, false); } + for (auto &elem : elems) { + for (auto &term : std::get<0>(elem)) { term->collect(vars, false); } + std::get<1>(elem)->collect(vars, false); + for (auto &lit : std::get<2>(elem)) { lit->collect(vars, false); } + } +} + +UHeadAggr TupleHeadAggregate::rewriteAggregates(UBodyAggrVec &body) { + for (auto &x : elems) { + if (ULit shifted = std::get<1>(x)->shift(false)) { + // NOTE: FalseLiteral is a bad name + std::get<1>(x) = make_locatable(std::get<1>(x)->loc()); + std::get<2>(x).emplace_back(std::move(shifted)); + } + } + if (elems.size() == 1 && bounds.empty()) { + auto &elem = elems.front(); + // Note: to handle undefinedness in tuples + bool weight = fun == AggregateFunction::SUM || fun == AggregateFunction::SUMP; + auto &tuple = std::get<0>(elem); + Location l = tuple.empty() ? loc() : tuple.front()->loc(); + for (auto &term : tuple) { + // NOTE: there could be special predicates for is_integer and is_defined + UTerm first = get_clone(term); + if (weight) { + first = make_locatable(l, BinOp::ADD, std::move(first), make_locatable(l, Symbol::createNum(0))); + weight = false; + } + body.emplace_back(gringo_make_unique(make_locatable(l, Relation::LEQ, std::move(first), std::move(term)))); + } + tuple.clear(); + tuple.emplace_back(make_locatable(l, Symbol::createNum(0))); + for (auto &lit : std::get<2>(elem)) { + body.emplace_back(gringo_make_unique(std::move(lit))); + } + std::get<2>(elem).clear(); + } + return nullptr; +} + +bool TupleHeadAggregate::simplify(Projections &project, SimplifyState &state, Logger &log) { + for (auto &bound : bounds) { + if (!bound.simplify(state, log)) { return false; } + } + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](HeadAggrElemVec::value_type &elem) { + SimplifyState elemState(state); + for (auto &term : std::get<0>(elem)) { + if (term->simplify(elemState, false, false, log).update(term).undefined()) { return true; } + } + if (!std::get<1>(elem)->simplify(log, project, elemState, false)) { + return true; + } + for (auto &lit : std::get<2>(elem)) { + if (!lit->simplify(log, project, elemState)) { return true; } + } + for (auto &dot : elemState.dots) { std::get<2>(elem).emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { std::get<2>(elem).emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void TupleHeadAggregate::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + for (auto &bound : bounds) { bound.rewriteArithmetics(arith, auxGen); } + for (auto &elem : elems) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : std::get<2>(elem)) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { std::get<2>(elem).emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { std::get<2>(elem).emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void TupleHeadAggregate::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + for (auto &bound : bounds) { bound.bound->collect(vars, false); } + lvl.add(vars); + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + for (auto &term : std::get<0>(elem)) { term->collect(vars, false); } + std::get<1>(elem)->collect(vars, false); + for (auto &lit : std::get<2>(elem)) { lit->collect(vars, false); } + local.add(vars); + } +} + +void TupleHeadAggregate::check(ChkLvlVec &levels, Logger &log) const { + auto f = [&]() { + VarTermBoundVec vars; + for (auto &y : elems) { + levels.emplace_back(loc(), *this); + _add(levels, std::get<0>(y)); + _add(levels, std::get<1>(y), false); + _add(levels, std::get<2>(y)); + levels.back().check(log); + levels.pop_back(); + for (auto &term : std::get<0>(y)) { term->collect(vars, false); } + } + warnGlobal(vars, !translated, log); + }; + _aggr(levels, bounds, f, false); +} + +bool TupleHeadAggregate::hasPool(bool beforeRewrite) const { + for (auto &bound : bounds) { if (bound.bound->hasPool()) { return true; } } + for (auto &elem : elems) { + for (auto &term : std::get<0>(elem)) { if (term->hasPool()) { return true; } } + if (std::get<1>(elem)->hasPool(beforeRewrite)) { return true; } + for (auto &lit : std::get<2>(elem)) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void TupleHeadAggregate::replace(Defines &x) { + for (auto &bound : bounds) { Term::replace(bound.bound, bound.bound->replace(x, true)); } + for (auto &elem : elems) { + for (auto &y : std::get<0>(elem)) { Term::replace(y, y->replace(x, true)); } + std::get<1>(elem)->replace(x); + for (auto &y : std::get<2>(elem)) { y->replace(x); } + } +} + +CreateHead TupleHeadAggregate::toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType) const { + bool isSimple = bounds.empty(); + if (isSimple) { + for (auto &elem : elems) { + if (!std::get<2>(elem).empty()) { isSimple = false; break; } + } + } + if (isSimple) { + DomainData &data = x.domains; + return CreateHead([&](Ground::ULitVec &&lits) { + Ground::Rule::HeadVec heads; + for (auto &elem : elems) { + if (UTerm headRepr = std::get<1>(elem)->headRepr()) { + PredicateDomain *headDom = &data.add(headRepr->getSig()); + heads.emplace_back(std::move(headRepr), headDom); + } + } + return gringo_make_unique(std::move(heads), std::move(lits), Ground::RuleType::Choice); + }); + } + else { + stms.emplace_back(gringo_make_unique(x.domains, x.newId(*this), fun, get_clone(bounds))); + auto &completeRef = static_cast(*stms.back()); + for (auto &y : elems) { + Ground::ULitVec lits; + for (auto &z : std::get<2>(y)) { lits.emplace_back(z->toGround(x.domains, false)); } + lits.emplace_back(gringo_make_unique(completeRef)); + UTerm headRep(std::get<1>(y)->headRepr()); + PredicateDomain *predDom = headRep ? &x.domains.add(headRep->getSig()) : nullptr; + auto ret = gringo_make_unique(completeRef, get_clone(std::get<0>(y)), predDom, std::move(headRep), std::move(lits)); + completeRef.addAccuDom(*ret); + stms.emplace_back(std::move(ret)); + } + return CreateHead([&completeRef](Ground::ULitVec &&lits) { return gringo_make_unique(completeRef, std::move(lits)); }); + } +} + +void TupleHeadAggregate::getNeg(std::function f) const { + for (auto &x : elems) { std::get<1>(x)->getNeg(f); } +} + +// {{{1 definition of LitHeadAggregate + +LitHeadAggregate::LitHeadAggregate(AggregateFunction fun, BoundVec &&bounds, CondLitVec &&elems) + : fun(fun) + , bounds(std::move(bounds)) + , elems(std::move(elems)) { } + +LitHeadAggregate::~LitHeadAggregate() { } + +void LitHeadAggregate::print(std::ostream &out) const { + _print(out, fun, bounds, elems, _printCond); +} + +size_t LitHeadAggregate::hash() const { + return get_value_hash(typeid(LitHeadAggregate).hash_code(), size_t(fun), bounds, elems); +} + +bool LitHeadAggregate::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && fun == t->fun && is_value_equal_to(bounds, t->bounds) && is_value_equal_to(elems, t->elems); +} + +LitHeadAggregate *LitHeadAggregate::clone() const { + return make_locatable(loc(), fun, get_clone(bounds), get_clone(elems)).release(); +} + +void LitHeadAggregate::unpool(UHeadAggrVec &x, bool beforeRewrite) { + CondLitVec e; + for (auto &elem : elems) { + auto f = [&](ULit &&y) { e.emplace_back(std::move(y), get_clone(elem.second)); }; + Term::unpool(elem.first, _unpool_lit(beforeRewrite), f); + } + elems.clear(); + for (auto &elem : e) { + if (beforeRewrite) { + auto f = [&](ULitVec &&y) { elems.emplace_back(get_clone(elem.first), std::move(y)); }; + Term::unpool(elem.second.begin(), elem.second.end(), _unpool_lit(beforeRewrite), f); + } + else { + Term::unpoolJoin(elem.second, _unpool_lit(beforeRewrite)); + elems.emplace_back(std::move(elem)); + } + } + e.clear(); + auto f = [&](BoundVec &&y) { x.emplace_back(make_locatable(loc(), fun, std::move(y), get_clone(elems))); }; + Term::unpool(bounds.begin(), bounds.end(), _unpool_bound, f); +} + +void LitHeadAggregate::collect(VarTermBoundVec &vars) const { + for (auto &bound : bounds) { bound.bound->collect(vars, false); } + for (auto &elem : elems) { + elem.first->collect(vars, false); + for (auto &lit : elem.second) { lit->collect(vars, false); } + } +} + +UHeadAggr LitHeadAggregate::rewriteAggregates(UBodyAggrVec &aggr) { + int id = 0; + HeadAggrElemVec elems; + for (auto &x : this->elems) { + UTermVec tuple; + x.first->toTuple(tuple, id); + elems.emplace_back(std::move(tuple), std::move(x.first), std::move(x.second)); + } + UHeadAggr x(make_locatable(loc(), fun, true, std::move(bounds), std::move(elems))); + Term::replace(x, x->rewriteAggregates(aggr)); + return x; +} + +bool LitHeadAggregate::simplify(Projections &project, SimplifyState &state, Logger &log) { + for (auto &bound : bounds) { + if (!bound.simplify(state, log)) { return false; } + } + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](CondLitVec::value_type &elem) { + SimplifyState elemState(state); + if (!std::get<0>(elem)->simplify(log, project, elemState, false)) { return true; } + for (auto &lit : std::get<1>(elem)) { + if (!lit->simplify(log, project, elemState)) { return true; } + } + for (auto &dot : elemState.dots) { std::get<1>(elem).emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { std::get<1>(elem).emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void LitHeadAggregate::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + for (auto &bound : bounds) { bound.rewriteArithmetics(arith, auxGen); } + for (auto &elem : elems) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : std::get<1>(elem)) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { std::get<1>(elem).emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { std::get<1>(elem).emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void LitHeadAggregate::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + for (auto &bound : bounds) { bound.bound->collect(vars, false); } + lvl.add(vars); + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + std::get<0>(elem)->collect(vars, false); + for (auto &lit : std::get<1>(elem)) { lit->collect(vars, false); } + local.add(vars); + } +} + +void LitHeadAggregate::check(ChkLvlVec &levels, Logger &log) const { + auto f = [&]() { + for (auto &y : elems) { + levels.emplace_back(loc(), *this); + _add(levels, y.first, false); + _add(levels, y.second); + levels.back().check(log); + levels.pop_back(); + } + }; + _aggr(levels, bounds, f, false); +} + +bool LitHeadAggregate::hasPool(bool beforeRewrite) const { + for (auto &bound : bounds) { if (bound.bound->hasPool()) { return true; } } + for (auto &elem : elems) { + if (elem.first->hasPool(beforeRewrite)) { return true; } + for (auto &lit : elem.second) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void LitHeadAggregate::replace(Defines &x) { + for (auto &bound : bounds) { Term::replace(bound.bound, bound.bound->replace(x, true)); } + for (auto &elem : elems) { + elem.first->replace(x); + for (auto &y : elem.second) { y->replace(x); } + } +} + +void LitHeadAggregate::getNeg(std::function f) const { + for (auto &x : elems) { x.first->getNeg(f); } +} + +CreateHead LitHeadAggregate::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + throw std::logic_error("Aggregate::rewriteAggregates must be called before LitAggregate::toGround"); +} + +// {{{1 definition of Disjunction + +Disjunction::Disjunction(CondLitVec &&elems) { + for (auto &x : elems) { + this->elems.emplace_back(); + this->elems.back().second = std::move(x.second); + this->elems.back().first.emplace_back(); + this->elems.back().first.back().first = std::move(x.first); + } +} + +Disjunction::Disjunction(ElemVec &&elems) +: elems(std::move(elems)) { } + +Disjunction::~Disjunction() { } + +void Disjunction::print(std::ostream &out) const { + auto f = [](std::ostream &out, Elem const &y) { + using namespace std::placeholders; + print_comma(out, y.first, "&", [](std::ostream &out, Head const &z) { + out << *z.first << ":"; + print_comma(out, z.second, ",", std::bind(&Literal::print, _2, _1)); + }); + out << ":"; + print_comma(out, y.second, ",", std::bind(&Literal::print, _2, _1)); + }; + print_comma(out, elems, ";", f); +} + +size_t Disjunction::hash() const { + return get_value_hash(typeid(Disjunction).hash_code(), elems); +} + +bool Disjunction::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(elems, t->elems); +} + +Disjunction *Disjunction::clone() const { + return make_locatable(loc(), get_clone(elems)).release(); +} + +void Disjunction::unpool(UHeadAggrVec &x, bool beforeRewrite) { + ElemVec e; + for (auto &elem : elems) { + if (beforeRewrite) { + HeadVec heads; + for (auto &head : elem.first) { + for (auto &lit : head.first->unpool(beforeRewrite)) { + Term::unpool(head.second.begin(), head.second.end(), _unpool_lit(beforeRewrite), [&](ULitVec &&expand) { + heads.emplace_back(get_clone(lit), std::move(expand)); + }); + } + } + elem.first = std::move(heads); + auto f = [&](ULitVec &&y) { e.emplace_back(get_clone(elem.first), std::move(y)); }; + Term::unpool(elem.second.begin(), elem.second.end(), _unpool_lit(beforeRewrite), f); + } + else { + HeadVec heads; + for (auto &head : elem.first) { + Term::unpoolJoin(head.second, _unpool_lit(beforeRewrite)); + for (auto &lit : head.first->unpool(beforeRewrite)) { + heads.emplace_back(std::move(lit), get_clone(head.second)); + } + } + elem.first = std::move(heads); + Term::unpoolJoin(elem.second, _unpool_lit(beforeRewrite)); + e.emplace_back(std::move(elem)); + } + } + x.emplace_back(make_locatable(loc(), std::move(e))); +} + +void Disjunction::collect(VarTermBoundVec &vars) const { + for (auto &elem : elems) { + for (auto &head : elem.first) { + head.first->collect(vars, false); + for (auto &lit : head.second) { lit->collect(vars, false); } + } + for (auto &lit : elem.second) { lit->collect(vars, false); } + } +} + +UHeadAggr Disjunction::rewriteAggregates(UBodyAggrVec &body) { + for (auto &elem : this->elems) { + for (auto &head : elem.first) { + if (ULit shifted = head.first->shift(true)) { + head.first = make_locatable(head.first->loc()); + head.second.emplace_back(std::move(shifted)); + } + } + if (elem.second.empty() && elem.first.size() == 1) { + auto &head = elem.first.front(); + for (auto &lit : head.second) { body.emplace_back(make_locatable(loc(), std::move(lit))); } + head.second.clear(); + } + } + return nullptr; +} + +bool Disjunction::simplify(Projections &project, SimplifyState &state, Logger &log) { + for (auto &elem : elems) { + elem.first.erase(std::remove_if(elem.first.begin(), elem.first.end(), [&](Head &head) { + SimplifyState elemState(state); + if (!head.first->simplify(log, project, elemState)) { return true; } + for (auto &lit : head.second) { + if (!lit->simplify(log, project, elemState)) { return true; } + } + for (auto &dot : elemState.dots) { head.second.emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { head.second.emplace_back(ScriptLiteral::make(script)); } + return false; + }), elem.first.end()); + } + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](ElemVec::value_type &elem) -> bool { + SimplifyState elemState(state); + for (auto &lit : elem.second) { + if (!lit->simplify(log, project, elemState)) { return true; } + } + for (auto &dot : elemState.dots) { elem.second.emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { elem.second.emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void Disjunction::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + for (auto &elem : elems) { + for (auto &head : elems) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : head.second) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { head.second.emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { head.second.emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : elem.second) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { elem.second.emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { elem.second.emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void Disjunction::assignLevels(AssignLevel &lvl) { + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + for (auto &head : elem.first) { + head.first->collect(vars, false); + for (auto &lit : head.second) { lit->collect(vars, false); } + } + for (auto &lit : elem.second) { lit->collect(vars, false); } + local.add(vars); + } +} + +void Disjunction::check(ChkLvlVec &levels, Logger &log) const { + levels.back().current = &levels.back().dep.insertEnt(); + for (auto &y : elems) { + levels.emplace_back(loc(), *this); + _add(levels, y.second); + // check condition first + // (although by construction it cannot happen that something in expand binds something in condition) + levels.back().check(log); + levels.pop_back(); + for (auto &head : y.first) { + levels.emplace_back(loc(), *this); + _add(levels, head.first, false); + _add(levels, head.second); + _add(levels, y.second); + levels.back().check(log); + levels.pop_back(); + } + } +} + +bool Disjunction::hasPool(bool beforeRewrite) const { + for (auto &elem : elems) { + for (auto &head : elem.first) { + if (head.first->hasPool(beforeRewrite)) { return true; } + for (auto &lit : head.second) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + for (auto &lit : elem.second) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void Disjunction::replace(Defines &x) { + for (auto &elem : elems) { + for (auto &head : elem.first) { + head.first->replace(x); + for (auto &y : elem.second) { y->replace(x); } + } + for (auto &y : elem.second) { y->replace(x); } + } +} + +void Disjunction::getNeg(std::function f) const { + for (auto &x : elems) { + for (auto &y : x.first) { y.first->getNeg(f); } + } +} + +CreateHead Disjunction::toGround(ToGroundArg &x, Ground::UStmVec &stms, Ground::RuleType) const { + bool isSimple = true; + for (auto &y : elems) { + if (y.first.size() > 1 || !y.second.empty()) { isSimple = false; break; } + } + if (isSimple) { + DomainData &data = x.domains; + return CreateHead([&](Ground::ULitVec &&lits) { + Ground::Rule::HeadVec heads; + for (auto &elem : elems) { + for (auto &head : elem.first) { + if (UTerm headRepr = head.first->headRepr()) { + PredicateDomain *headDom = &data.add(headRepr->getSig()); + heads.emplace_back(std::move(headRepr), headDom); + } + } + } + return gringo_make_unique(std::move(heads), std::move(lits), Ground::RuleType::Disjunctive); + }); + } + else { + stms.emplace_back(gringo_make_unique(x.domains, x.newId(*this))); + auto &complete = static_cast(*stms.back()); + for (auto &y : elems) { + UTermVec elemVars; + std::unordered_set seen; + VarTermBoundVec vars; + for (auto &x : y.second) { x->collect(vars, false); } + for (auto &occ : vars) { + if (occ.first->level != 0) { seen.emplace(occ.first->name); } + } + vars.clear(); + for (auto &head : y.first) { + head.first->collect(vars, false); + for (auto &x : head.second) { x->collect(vars, false); } + } + for (auto &occ : vars) { + if (occ.first->level != 0 && seen.find(occ.first->name) != seen.end()) { + elemVars.emplace_back(occ.first->clone()); + seen.emplace(occ.first->name); + } + } + UTerm elemRepr = x.newId(std::move(elemVars), loc(), true); + if (y.first.empty()) { + Ground::ULitVec elemCond; + for (auto &z : y.second) { elemCond.emplace_back(z->toGround(x.domains, false)); } + Ground::ULitVec headCond; + headCond.emplace_back(make_locatable(loc(), Relation::NEQ, make_locatable(loc(), Symbol::createNum(0)), make_locatable(loc(), Symbol::createNum(0)))->toGround(x.domains, true)); + stms.emplace_back(gringo_make_unique(complete, nullptr, nullptr, std::move(headCond), std::move(elemRepr), std::move(elemCond))); + } + else { + for (auto &head : y.first) { + Ground::ULitVec elemCond; + for (auto &z : y.second) { elemCond.emplace_back(z->toGround(x.domains, false)); } + Ground::ULitVec headCond; + for (auto &z : head.second) { headCond.emplace_back(z->toGround(x.domains, false)); } + UTerm headRepr = head.first->headRepr(); + PredicateDomain *headDom = headRepr ? &x.domains.add(headRepr->getSig()) : nullptr; + stms.emplace_back(gringo_make_unique(complete, headDom, std::move(headRepr), std::move(headCond), get_clone(elemRepr), std::move(elemCond))); + } + } + } + return CreateHead([&](Ground::ULitVec &&lits) { return gringo_make_unique(complete, std::move(lits)); }); + } +} + +// {{{1 definition of SimpleHeadLiteral + +SimpleHeadLiteral::SimpleHeadLiteral(ULit &&lit) + : lit(std::move(lit)) { } + +Location const &SimpleHeadLiteral::loc() const { return lit->loc(); } + +void SimpleHeadLiteral::loc(Location const &loc) { lit->loc(loc); } + +SimpleHeadLiteral::~SimpleHeadLiteral() { } + +void SimpleHeadLiteral::print(std::ostream &out) const { lit->print(out); } + +size_t SimpleHeadLiteral::hash() const { + return get_value_hash(typeid(SimpleHeadLiteral).hash_code(), lit); +} + +bool SimpleHeadLiteral::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(lit, t->lit); +} + +SimpleHeadLiteral *SimpleHeadLiteral::clone() const { + return gringo_make_unique(get_clone(lit)).release(); +} + +void SimpleHeadLiteral::unpool(UHeadAggrVec &x, bool beforeRewrite) { + for (auto &y : lit->unpool(beforeRewrite)) { x.emplace_back(gringo_make_unique(std::move(y))); } +} + +void SimpleHeadLiteral::collect(VarTermBoundVec &vars) const { lit->collect(vars, true); } + +UHeadAggr SimpleHeadLiteral::rewriteAggregates(UBodyAggrVec &aggr) { + ULit shifted(lit->shift(true)); + if (shifted) { + aggr.emplace_back(gringo_make_unique(std::move(shifted))); + return gringo_make_unique(make_locatable(lit->loc())); + } + return nullptr; +} + +bool SimpleHeadLiteral::simplify(Projections &project, SimplifyState &state, Logger &log) { + return lit->simplify(log, project, state, false); +} + +void SimpleHeadLiteral::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &) { + // Note: nothing to do +} + +void SimpleHeadLiteral::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + lit->collect(vars, false); + lvl.add(vars); +} + +Symbol SimpleHeadLiteral::isEDB() const { return lit->isEDB(); } + +void SimpleHeadLiteral::check(ChkLvlVec &levels, Logger &) const { + _add(levels, lit, false); +} + +bool SimpleHeadLiteral::hasPool(bool beforeRewrite) const { + return lit->hasPool(beforeRewrite); +} + +void SimpleHeadLiteral::replace(Defines &x) { + lit->replace(x); +} + +void SimpleHeadLiteral::getNeg(std::function f) const { + lit->getNeg(f); +} + +CreateHead SimpleHeadLiteral::toGround(ToGroundArg &x, Ground::UStmVec &, Ground::RuleType type) const { + return + {[this, &x, type](Ground::ULitVec &&lits) -> Ground::UStm { + Ground::Rule::HeadVec heads; + if (UTerm headRepr = lit->headRepr()) { + Sig sig(headRepr->getSig()); + heads.emplace_back(std::move(headRepr), &x.domains.add(sig)); + } + return gringo_make_unique(std::move(heads), std::move(lits), type); + }}; +} + +// {{{1 definition of DisjointAggregate + +CSPElem::CSPElem(Location const &loc, UTermVec &&tuple, CSPAddTerm &&value, ULitVec &&cond) + : loc(loc) + , tuple(std::move(tuple)) + , value(std::move(value)) + , cond(std::move(cond)) { } +CSPElem::CSPElem(CSPElem &&) = default; +CSPElem &CSPElem::operator=(CSPElem &&) = default; +CSPElem::~CSPElem() { } +void CSPElem::print(std::ostream &out) const { + using namespace std::placeholders; + print_comma(out, tuple, ",", std::bind(&Term::print, _2, _1)); + out << ":" << value; + if (!cond.empty()) { + out << ":"; + print_comma(out, cond, ",", std::bind(&Literal::print, _2, _1)); + } +} +size_t CSPElem::hash() const { + return get_value_hash(tuple, value, cond); +} +CSPElem CSPElem::clone() const { + return {loc, get_clone(tuple), get_clone(value), get_clone(cond)}; +} +bool CSPElem::operator==(CSPElem const &x) const { + return is_value_equal_to(tuple, x.tuple) && is_value_equal_to(value, x.value) && is_value_equal_to(cond, x.cond); +} + +DisjointAggregate::DisjointAggregate(NAF naf, CSPElemVec &&elems) + : naf(naf) + , elems(std::move(elems)) { } + +DisjointAggregate::~DisjointAggregate() { } + +void DisjointAggregate::print(std::ostream &out) const { + out << naf << "#disjoint{"; + print_comma(out, elems, ";"); + out << "}"; +} + +size_t DisjointAggregate::hash() const { + return get_value_hash(typeid(DisjointAggregate).hash_code(), elems); +} + +bool DisjointAggregate::operator==(BodyAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(elems, t->elems); +} + +DisjointAggregate *DisjointAggregate::clone() const { + return make_locatable(loc(), naf, get_clone(elems)).release(); +} + +void DisjointAggregate::unpool(UBodyAggrVec &x, bool beforeRewrite) { + CSPElemVec e; + for (auto &elem : elems) { + auto f = [&](UTermVec &&y) { e.emplace_back(elem.loc, std::move(y), get_clone(elem.value), get_clone(elem.cond)); }; + Term::unpool(elem.tuple.begin(), elem.tuple.end(), Gringo::unpool, f); + } + elems.clear(); + for (auto &elem : e) { + for (auto &y : elem.value.unpool()) { + elems.emplace_back(elem.loc, get_clone(elem.tuple), std::move(y), get_clone(elem.cond)); + } + } + e.clear(); + for (auto &elem : elems) { + if (beforeRewrite) { + auto f = [&](ULitVec &&cond) { e.emplace_back(elem.loc, get_clone(elem.tuple), get_clone(elem.value), std::move(cond)); }; + Term::unpool(elem.cond.begin(), elem.cond.end(), _unpool_lit(beforeRewrite), f); + } + else { + Term::unpoolJoin(elem.cond, _unpool_lit(beforeRewrite)); + e.emplace_back(std::move(elem)); + } + } + + x.emplace_back(make_locatable(loc(), naf, std::move(e))); +} + +void DisjointAggregate::collect(VarTermBoundVec &vars) const { + for (auto &elem : elems) { + for (auto &term : elem.tuple) { term->collect(vars, false); } + elem.value.collect(vars); + for (auto &lit : elem.cond) { lit->collect(vars, false); } + } +} + +bool DisjointAggregate::rewriteAggregates(UBodyAggrVec &) { return true; } + +bool DisjointAggregate::simplify(Projections &project, SimplifyState &state, bool, Logger &log) { + elems.erase(std::remove_if(elems.begin(), elems.end(), [&](CSPElemVec::value_type &elem) { + SimplifyState elemState(state); + for (auto &term : elem.tuple) { + if (term->simplify(elemState, false, false, log).update(term).undefined()) { return true; } + } + if (!elem.value.simplify(elemState, log)) { return true; } + for (auto &lit : elem.cond) { + if (!lit->simplify(log, project, elemState)) { return true; } + } + for (auto &dot : elemState.dots) { elem.cond.emplace_back(RangeLiteral::make(dot)); } + for (auto &script : elemState.scripts) { elem.cond.emplace_back(ScriptLiteral::make(script)); } + return false; + }), elems.end()); + return true; +} + +void DisjointAggregate::rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &, AuxGen &auxGen) { + for (auto &elem : elems) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &y : elem.cond) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { elem.cond.emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { elem.cond.emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); + } +} + +void DisjointAggregate::assignLevels(AssignLevel &lvl) { + for (auto &elem : elems) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + for (auto &term : elem.tuple) { term->collect(vars, false); } + elem.value.collect(vars); + for (auto &lit : elem.cond) { lit->collect(vars, false); } + local.add(vars); + } +} + +void DisjointAggregate::check(ChkLvlVec &levels, Logger &log) const { + auto f = [&]() { + for (auto &y : elems) { + levels.emplace_back(loc(), *this); + _add(levels, y.tuple, &y.value); + _add(levels, y.cond); + levels.back().check(log); + levels.pop_back(); + } + }; + _aggr(levels, {}, f, false); +} + +bool DisjointAggregate::hasPool(bool beforeRewrite) const { + for (auto &elem : elems) { + for (auto &term : elem.tuple) { if (term->hasPool()) { return true; } } + if (elem.value.hasPool()) { return true; } + for (auto &lit : elem.cond) { if (lit->hasPool(beforeRewrite)) { return true; } } + } + return false; +} + +void DisjointAggregate::replace(Defines &x) { + for (auto &elem : elems) { + for (auto &y : elem.tuple) { y->replace(x, true); } + elem.value.replace(x); + for (auto &y : elem.cond) { y->replace(x); } + } +} + +CreateBody DisjointAggregate::toGround(ToGroundArg &x, Ground::UStmVec &stms) const { + stms.emplace_back(gringo_make_unique(x.domains, x.newId(*this))); + auto &completeRef = static_cast(*stms.back()); + CreateStmVec split; + split.emplace_back([&completeRef, this](Ground::ULitVec &&lits) -> Ground::UStm { + auto ret = gringo_make_unique(completeRef, std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + for (auto &y : elems) { + split.emplace_back([this,&completeRef,&y,&x](Ground::ULitVec &&lits) -> Ground::UStm { + for (auto &z : y.cond) { lits.emplace_back(z->toGround(x.domains, false)); } + auto ret = gringo_make_unique(completeRef, get_clone(y.tuple), get_clone(y.value), std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + } + return CreateBody([&completeRef, this](Ground::ULitVec &lits, bool primary, bool) { + if (primary) { lits.emplace_back(gringo_make_unique(completeRef, naf)); } + }, std::move(split)); +} + +bool DisjointAggregate::isAssignment() const { return false; } + +void DisjointAggregate::removeAssignment() { } + +// {{{1 definition of MinimizeHeadLiteral + +MinimizeHeadLiteral::MinimizeHeadLiteral(UTerm &&weight, UTerm &&priority, UTermVec &&tuple) +: tuple_(std::move(tuple)) { + tuple_.emplace_back(std::move(weight)); + tuple_.emplace_back(std::move(priority)); + std::rotate(tuple_.begin(), tuple_.end() - 2, tuple_.end()); +} + +MinimizeHeadLiteral::MinimizeHeadLiteral(UTermVec &&tuple) +: tuple_(std::move(tuple)) { + assert(tuple_.size() >= 2); +} + +MinimizeHeadLiteral::~MinimizeHeadLiteral() { } + +void MinimizeHeadLiteral::print(std::ostream &out) const { + out << "["; + weight().print(out); + out << "@"; + priority().print(out); + for (auto it = tuple_.begin() + 2, ie = tuple_.end(); it != ie; ++it) { + out << ","; + (*it)->print(out); + } + out << "]"; +} + +size_t MinimizeHeadLiteral::hash() const { + return get_value_hash(typeid(MinimizeHeadLiteral).hash_code(), tuple_); +} + +bool MinimizeHeadLiteral::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(tuple_, t->tuple_); +} + +MinimizeHeadLiteral *MinimizeHeadLiteral::clone() const { + return make_locatable(loc(), get_clone(tuple_)).release(); +} + +void MinimizeHeadLiteral::unpool(UHeadAggrVec &x, bool beforeRewrite) { + assert(beforeRewrite); (void)beforeRewrite; + auto f = [&](UTermVec &&tuple) { x.emplace_back(make_locatable(loc(), std::move(tuple))); }; + Term::unpool(tuple_.begin(), tuple_.end(), Gringo::unpool, f); +} + +void MinimizeHeadLiteral::collect(VarTermBoundVec &vars) const { + for (auto &term : tuple_) { + term->collect(vars, false); + } +} + +UHeadAggr MinimizeHeadLiteral::rewriteAggregates(UBodyAggrVec &) { + return nullptr; +} + +bool MinimizeHeadLiteral::simplify(Projections &, SimplifyState &state, Logger &log) { + for (auto &term : tuple_) { + if (term->simplify(state, false, false, log).update(term).undefined()) { + return false; + } + } + return true; +} + +void MinimizeHeadLiteral::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &) { + // Note: nothing to do +} + +void MinimizeHeadLiteral::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + for (auto &term : tuple_) { + term->collect(vars, false); + } + lvl.add(vars); +} + +void MinimizeHeadLiteral::check(ChkLvlVec &levels, Logger &) const { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + collect(vars); + addVars(levels, vars); +} + +bool MinimizeHeadLiteral::hasPool(bool beforeRewrite) const { + if (beforeRewrite) { + for (auto &term : tuple_) { + if (term->hasPool()) { + return true; + } + } + } + return false; +} + +void MinimizeHeadLiteral::replace(Defines &x) { + for (auto &term : tuple_) { + Term::replace(term, term->replace(x, true)); + } +} + +CreateHead MinimizeHeadLiteral::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + return CreateHead([&](Ground::ULitVec &&lits) { + return gringo_make_unique(get_clone(tuple_), std::move(lits)); + }); +} + +Term &MinimizeHeadLiteral::weight() const { + return *tuple_[0]; +} + +Term &MinimizeHeadLiteral::priority() const { + return *tuple_[1]; +} + +void MinimizeHeadLiteral::getNeg(std::function) const { } + +// {{{1 definition of EdgeHeadAtom + +EdgeHeadAtom::EdgeHeadAtom(UTerm &&u, UTerm &&v) +: u_(std::move(u)) +, v_(std::move(v)) +{ } + +EdgeHeadAtom::~EdgeHeadAtom() { } + +void EdgeHeadAtom::print(std::ostream &out) const { + out << "#edge(" << *u_ << "," << *v_ << ")"; +} + +size_t EdgeHeadAtom::hash() const { + return get_value_hash(typeid(EdgeHeadAtom).hash_code(), u_, v_); +} + +bool EdgeHeadAtom::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(u_, t->u_) && is_value_equal_to(v_, t->v_);; +} + +EdgeHeadAtom *EdgeHeadAtom::clone() const { + return make_locatable(loc(), get_clone(u_), get_clone(v_)).release(); +} + +void EdgeHeadAtom::unpool(UHeadAggrVec &x, bool beforeRewrite) { + if (beforeRewrite) { + for (auto &u : Gringo::unpool(u_)) { + for (auto &v : Gringo::unpool(v_)) { + x.emplace_back(make_locatable(loc(), get_clone(u), std::move(v))); + } + } + } + else { + x.emplace_back(this->clone()); + } +} + +void EdgeHeadAtom::collect(VarTermBoundVec &vars) const { + u_->collect(vars, false); + v_->collect(vars, false); +} + +UHeadAggr EdgeHeadAtom::rewriteAggregates(UBodyAggrVec &) { + return nullptr; +} + +bool EdgeHeadAtom::simplify(Projections &, SimplifyState &state, Logger &log) { + return !u_->simplify(state, false, false, log).update(u_).undefined() && + !v_->simplify(state, false, false, log).update(v_).undefined(); +} + +void EdgeHeadAtom::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &) { + // Note: nothing to do +} + +void EdgeHeadAtom::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + collect(vars); + lvl.add(vars); +} + +void EdgeHeadAtom::check(ChkLvlVec &levels, Logger &) const { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + collect(vars); + addVars(levels, vars); +} + +bool EdgeHeadAtom::hasPool(bool beforeRewrite) const { + return beforeRewrite && (u_->hasPool() || v_->hasPool()); +} + +void EdgeHeadAtom::replace(Defines &x) { + Term::replace(u_, u_->replace(x, true)); + Term::replace(v_, v_->replace(x, true)); +} + +CreateHead EdgeHeadAtom::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + return CreateHead([&](Ground::ULitVec &&lits) { + return gringo_make_unique(get_clone(u_), get_clone(v_), std::move(lits)); + }); +} + +void EdgeHeadAtom::getNeg(std::function) const { } + +// {{{1 definition of ProjectHeadAtom + +ProjectHeadAtom::ProjectHeadAtom(UTerm &&atom) +: atom_(std::move(atom)) +{ } + +ProjectHeadAtom::~ProjectHeadAtom() { } + +void ProjectHeadAtom::print(std::ostream &out) const { + out << "#project " << *atom_; +} + +size_t ProjectHeadAtom::hash() const { + return get_value_hash(typeid(ProjectHeadAtom).hash_code(), atom_); +} + +bool ProjectHeadAtom::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(atom_, t->atom_); +} + +ProjectHeadAtom *ProjectHeadAtom::clone() const { + return make_locatable(loc(), get_clone(atom_)).release(); +} + +void ProjectHeadAtom::unpool(UHeadAggrVec &x, bool beforeRewrite) { + if (beforeRewrite) { + for (auto &atom : Gringo::unpool(atom_)) { + x.emplace_back(make_locatable(loc(), std::move(atom))); + } + } + else { + x.emplace_back(clone()); + } +} + +void ProjectHeadAtom::collect(VarTermBoundVec &vars) const { + atom_->collect(vars, false); +} + +UHeadAggr ProjectHeadAtom::rewriteAggregates(UBodyAggrVec &body) { + body.emplace_back(gringo_make_unique(make_locatable(atom_->loc(), NAF::POS, get_clone(atom_), true))); + return nullptr; +} + +bool ProjectHeadAtom::simplify(Projections &, SimplifyState &state, Logger &log) { + return !atom_->simplify(state, false, false, log).update(atom_).undefined(); +} + +void ProjectHeadAtom::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxgen) { + atom_->rewriteArithmetics(arith, auxgen); +} + +void ProjectHeadAtom::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + collect(vars); + lvl.add(vars); +} + +void ProjectHeadAtom::check(ChkLvlVec &levels, Logger &) const { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + collect(vars); + addVars(levels, vars); +} + +bool ProjectHeadAtom::hasPool(bool beforeRewrite) const { + return beforeRewrite && atom_->hasPool(); +} + +void ProjectHeadAtom::replace(Defines &x) { + atom_->replace(x, false); +} + +CreateHead ProjectHeadAtom::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + return CreateHead([&](Ground::ULitVec &&lits) { + return gringo_make_unique(get_clone(atom_), std::move(lits)); + }); +} + +void ProjectHeadAtom::getNeg(std::function) const { } + +// {{{1 definition of HeuristicHeadAtom + +HeuristicHeadAtom::HeuristicHeadAtom(UTerm &&atom, UTerm &&bias, UTerm &&priority, UTerm &&mod) +: atom_(std::move(atom)) +, value_(std::move(bias)) +, priority_(std::move(priority)) +, mod_(std::move(mod)) +{ } + +HeuristicHeadAtom::~HeuristicHeadAtom() { } + +void HeuristicHeadAtom::print(std::ostream &out) const { + out << "#heuristic " << *atom_ << "[" << *value_ << "@" << *priority_ << "," << *mod_ << "]"; +} + +size_t HeuristicHeadAtom::hash() const { + return get_value_hash(typeid(HeuristicHeadAtom).hash_code(), atom_, value_, priority_, mod_); +} + +bool HeuristicHeadAtom::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && + is_value_equal_to(atom_, t->atom_) && + is_value_equal_to(value_, t->value_) && + is_value_equal_to(priority_, t->priority_) && + is_value_equal_to(mod_, t->mod_); +} + +HeuristicHeadAtom *HeuristicHeadAtom::clone() const { + return make_locatable(loc(), get_clone(atom_), get_clone(value_), get_clone(priority_), get_clone(mod_)).release(); +} + +void HeuristicHeadAtom::unpool(UHeadAggrVec &x, bool beforeRewrite) { + if (beforeRewrite) { + for (auto &atom : Gringo::unpool(atom_)) { + for (auto &bias : Gringo::unpool(value_)) { + for (auto &priority : Gringo::unpool(priority_)) { + for (auto &mod : Gringo::unpool(mod_)) { + x.emplace_back(make_locatable(loc(), get_clone(atom), get_clone(bias), std::move(priority), get_clone(mod))); + } + } + } + } + } + else { + x.emplace_back(clone()); + } +} + +void HeuristicHeadAtom::collect(VarTermBoundVec &vars) const { + atom_->collect(vars, false); + value_->collect(vars, false); + priority_->collect(vars, false); + mod_->collect(vars, false); +} + +UHeadAggr HeuristicHeadAtom::rewriteAggregates(UBodyAggrVec &body) { + body.emplace_back(gringo_make_unique(make_locatable(atom_->loc(), NAF::POS, get_clone(atom_), true))); + return nullptr; +} + +bool HeuristicHeadAtom::simplify(Projections &, SimplifyState &state, Logger &log) { + return + !atom_->simplify(state, false, false, log).update(atom_).undefined() && + !value_->simplify(state, false, false, log).update(value_).undefined() && + !priority_->simplify(state, false, false, log).update(priority_).undefined() && + !mod_->simplify(state, false, false, log).update(mod_).undefined(); +} + +void HeuristicHeadAtom::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxgen) { + atom_->rewriteArithmetics(arith, auxgen); +} + +void HeuristicHeadAtom::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + collect(vars); + lvl.add(vars); +} + +void HeuristicHeadAtom::check(ChkLvlVec &levels, Logger &) const { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + collect(vars); + addVars(levels, vars); +} + +bool HeuristicHeadAtom::hasPool(bool beforeRewrite) const { + return beforeRewrite && (atom_->hasPool() || value_->hasPool() || priority_->hasPool()); +} + +void HeuristicHeadAtom::replace(Defines &x) { + Term::replace(atom_, atom_->replace(x, false)); + Term::replace(value_, value_->replace(x, true)); + Term::replace(priority_, priority_->replace(x, true)); + Term::replace(mod_, mod_->replace(x, true)); +} + +CreateHead HeuristicHeadAtom::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + return CreateHead([&](Ground::ULitVec &&lits) { + return gringo_make_unique(get_clone(atom_), get_clone(value_), get_clone(priority_), get_clone(mod_), std::move(lits)); + }); +} + +void HeuristicHeadAtom::getNeg(std::function) const { } + +// {{{1 definition of ShowHeadLiteral + +ShowHeadLiteral::ShowHeadLiteral(UTerm &&term, bool csp) +: term_(std::move(term)) +, csp_(csp) +{ } + +ShowHeadLiteral::~ShowHeadLiteral() { } + +void ShowHeadLiteral::print(std::ostream &out) const { + out << "#show " << (csp_ ? "$" : "") << *term_; +} + +size_t ShowHeadLiteral::hash() const { + return get_value_hash(typeid(ShowHeadLiteral).hash_code(), term_, csp_); +} + +bool ShowHeadLiteral::operator==(HeadAggregate const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(term_, t->term_) && is_value_equal_to(csp_, t->csp_);; +} + +ShowHeadLiteral *ShowHeadLiteral::clone() const { + return make_locatable(loc(), get_clone(term_), csp_).release(); +} + +void ShowHeadLiteral::unpool(UHeadAggrVec &x, bool beforeRewrite) { + if (beforeRewrite) { + for (auto &term : Gringo::unpool(term_)) { + x.emplace_back(make_locatable(loc(), std::move(term), csp_)); + } + } +} + +void ShowHeadLiteral::collect(VarTermBoundVec &vars) const { + term_->collect(vars, false); +} + +UHeadAggr ShowHeadLiteral::rewriteAggregates(UBodyAggrVec &) { + return nullptr; +} + +bool ShowHeadLiteral::simplify(Projections &, SimplifyState &state, Logger &log) { + return !term_->simplify(state, false, false, log).update(term_).undefined(); +} + +void ShowHeadLiteral::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &) { + // Note: nothing to do +} + +void ShowHeadLiteral::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + collect(vars); + lvl.add(vars); +} + +void ShowHeadLiteral::check(ChkLvlVec &levels, Logger &) const { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + collect(vars); + addVars(levels, vars); +} + +bool ShowHeadLiteral::hasPool(bool beforeRewrite) const { + return beforeRewrite && term_->hasPool(); +} + +void ShowHeadLiteral::replace(Defines &x) { + Term::replace(term_, term_->replace(x, true)); +} + +CreateHead ShowHeadLiteral::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + return CreateHead([&](Ground::ULitVec &&lits) { + return gringo_make_unique(get_clone(term_), csp_, std::move(lits)); + }); +} + +void ShowHeadLiteral::getNeg(std::function) const { } + +// }}}1 + +} } // namespace Input Gringo + diff --git a/libgringo/src/input/groundtermgrammar.yy b/libgringo/src/input/groundtermgrammar.yy new file mode 100644 index 0000000..54624a0 --- /dev/null +++ b/libgringo/src/input/groundtermgrammar.yy @@ -0,0 +1,149 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +%require "2.5" +%define namespace "Gringo::Input::GroundTermGrammar" +%name-prefix "GringoGroundTermGrammar_" +%error-verbose +%locations // NOTE: different behavior for location-less parsers for different bison versions +%defines +%parse-param { Gringo::Input::GroundTermParser *lexer } +%lex-param { Gringo::Input::GroundTermParser *lexer } +%skeleton "lalr1.cc" +//%define parse.trace +//%debug + +// {{{1 auxiliary code + +%{ + +#include "gringo/term.hh" +#include "gringo/input/groundtermparser.hh" +#include + +using namespace Gringo; +using namespace Gringo::Input; + +int GringoGroundTermGrammar_lex(void *value, void *, GroundTermParser *lexer) { + return lexer->lex(value, lexer->logger()); +} + +%} + +%code { + +void GroundTermGrammar::parser::error(GroundTermGrammar::parser::location_type const &, std::string const &msg) { + lexer->parseError(msg, lexer->logger()); +} + +} + +// {{{1 nonterminals +%union { + char const * str; + int num; + unsigned uid; + clingo_symbol_t value; +} + +// {{{1 terminals + +%token + ADD "+" + AND "&" + BNOT "~" + COMMA "," + END 0 "" + LPAREN "(" + MOD "\\" + MUL "*" + POW "**" + QUESTION "?" + RPAREN ")" + SLASH "/" + SUB "-" + XOR "^" + VBAR "|" + SUPREMUM "#sup" + INFIMUM "#inf" + +%token + NUMBER "" + +%token + IDENTIFIER "" + STRING "" + +// {{{1 operator precedence and associativity + +%left XOR +%left QUESTION +%left AND +%left ADD SUB +%left MUL SLASH MOD +%right POW +%left UMINUS UBNOT + +%type term +%type nterms terms + +// }}}1 + +%% + +// {{{1 the parser + +start : term[r] { lexer->value = Symbol($r); }; + +term + : term[a] XOR term[b] { $$ = lexer->term(BinOp::XOR, Symbol($a), Symbol($b)).rep(); } + | term[a] QUESTION term[b] { $$ = lexer->term(BinOp::OR, Symbol($a), Symbol($b)).rep(); } + | term[a] AND term[b] { $$ = lexer->term(BinOp::AND, Symbol($a), Symbol($b)).rep(); } + | term[a] ADD term[b] { $$ = lexer->term(BinOp::ADD, Symbol($a), Symbol($b)).rep(); } + | term[a] SUB term[b] { $$ = lexer->term(BinOp::SUB, Symbol($a), Symbol($b)).rep(); } + | term[a] MUL term[b] { $$ = lexer->term(BinOp::MUL, Symbol($a), Symbol($b)).rep(); } + | term[a] SLASH term[b] { $$ = lexer->term(BinOp::DIV, Symbol($a), Symbol($b)).rep(); } + | term[a] MOD term[b] { $$ = lexer->term(BinOp::MOD, Symbol($a), Symbol($b)).rep(); } + | term[a] POW term[b] { $$ = lexer->term(BinOp::POW, Symbol($a), Symbol($b)).rep(); } + | SUB term[a] %prec UMINUS { $$ = lexer->term(UnOp::NEG, Symbol($a)).rep(); } + | BNOT term[a] %prec UBNOT { $$ = lexer->term(UnOp::NOT, Symbol($a)).rep(); } + | LPAREN RPAREN { $$ = Symbol::createTuple(Potassco::toSpan()).rep(); } + | LPAREN COMMA RPAREN { $$ = Symbol::createTuple(Potassco::toSpan()).rep(); } + | LPAREN nterms[a] RPAREN { $$ = lexer->tuple($a, false).rep(); } + | LPAREN nterms[a] COMMA RPAREN { $$ = lexer->tuple($a, true).rep(); } + | IDENTIFIER[a] LPAREN terms[b] RPAREN { $$ = Symbol::createFun($a, Potassco::toSpan(lexer->terms($b))).rep(); } + | VBAR term[a] VBAR { $$ = lexer->term(UnOp::ABS, Symbol($a)).rep(); } + | IDENTIFIER[a] { $$ = Symbol::createId($a).rep(); } + | NUMBER[a] { $$ = Symbol::createNum($a).rep(); } + | STRING[a] { $$ = Symbol::createStr($a).rep(); } + | INFIMUM[a] { $$ = Symbol::createInf().rep(); } + | SUPREMUM[a] { $$ = Symbol::createSup().rep(); } + ; + +nterms + : term[a] { $$ = lexer->terms(lexer->terms(), Symbol($a)); } + | nterms[a] COMMA term[b] { $$ = lexer->terms($a, Symbol($b)); } + ; + +terms + : nterms[a] { $$ = $a; } + | { $$ = lexer->terms(); } + ; + diff --git a/libgringo/src/input/groundtermlexer.xh b/libgringo/src/input/groundtermlexer.xh new file mode 100644 index 0000000..228061c --- /dev/null +++ b/libgringo/src/input/groundtermlexer.xh @@ -0,0 +1,76 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#define YYCTYPE char +#define YYCURSOR cursor() +#define YYLIMIT limit() +#define YYMARKER marker() +#define YYCTXMARKER ctxmarker() +#define YYFILL(n) {fill(n);} + +/*!re2c + NUMBER = "0"|([1-9][0-9]*); + ANY = [\000-\377]; + WS = [\t\r ]*; + NL = "\n"; + IDENTIFIER = "_"*[a-z]['A-Za-z0-9_]*; + STRING = "\"" ([^\\"\n]|"\\\""|"\\\\"|"\\n")* "\""; + WSNL = [\t\r\n ]*; +*/ + +int Gringo::Input::GroundTermParser::lex_impl(void *pValue, Logger &log) { +start: + start(); + auto &value = *static_cast(pValue); + /*!re2c + WS { goto start; } + NL { if(eof()) return 0; step(); goto start; } + "#inf"("imum")? { return GroundTermGrammar::parser::token::INFIMUM; } + "#sup"("remum")? { return GroundTermGrammar::parser::token::SUPREMUM; } + + IDENTIFIER { value.str = String(string()).c_str(); return GroundTermGrammar::parser::token::IDENTIFIER; } + NUMBER { value.num = integer(); return GroundTermGrammar::parser::token::NUMBER; } + STRING { value.str = String(unquote(string(1, 1)).c_str()).c_str(); return GroundTermGrammar::parser::token::STRING; } + + "(" { return GroundTermGrammar::parser::token::LPAREN; } + ")" { return GroundTermGrammar::parser::token::RPAREN; } + "+" { return GroundTermGrammar::parser::token::ADD; } + "-" { return GroundTermGrammar::parser::token::SUB; } + "**" { return GroundTermGrammar::parser::token::POW; } + "\\" { return GroundTermGrammar::parser::token::MOD; } + "*" { return GroundTermGrammar::parser::token::MUL; } + "/" { return GroundTermGrammar::parser::token::SLASH; } + "&" { return GroundTermGrammar::parser::token::AND; } + "^" { return GroundTermGrammar::parser::token::XOR; } + "~" { return GroundTermGrammar::parser::token::BNOT; } + "?" { return GroundTermGrammar::parser::token::QUESTION; } + "," { return GroundTermGrammar::parser::token::COMMA; } + "|" { return GroundTermGrammar::parser::token::VBAR; } + ANY { lexerError(string(), log); goto start; } + */ + assert(false); + return 0; +} + +#undef YYCTYPE +#undef YYCURSOR +#undef YYLIMIT +#undef YYMARKER +#undef YYFILL diff --git a/libgringo/src/input/groundtermparser.cc b/libgringo/src/input/groundtermparser.cc new file mode 100644 index 0000000..6f7ba65 --- /dev/null +++ b/libgringo/src/input/groundtermparser.cc @@ -0,0 +1,109 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/groundtermparser.hh" +#include "input/groundtermgrammar/grammar.hh" +#include "gringo/logger.hh" + +namespace Gringo { namespace Input { + +GroundTermParser::GroundTermParser() { } +Symbol GroundTermParser::parse(std::string const &str, Logger &log) { + log_ = &log; + undefined_ = false; + while (!empty()) { pop(); } + push(gringo_make_unique(str), 0); + GroundTermGrammar::parser parser(this); + parser.parse(); + return undefined_ ? Symbol() : value; +} + +Symbol GroundTermParser::term(BinOp op, Symbol a, Symbol b) { + if (a.type() == SymbolType::Num && b.type() == SymbolType::Num && (op != BinOp::DIV || b.num() != 0)) { + return Symbol::createNum(Gringo::eval(op, a.num(), b.num())); + } + undefined_ = true; + return Symbol::createNum(0); +} + +Symbol GroundTermParser::term(UnOp op, Symbol a) { + if (a.type() == SymbolType::Num) { + int num = a.num(); + switch (op) { + case UnOp::NEG: { return Symbol::createNum(-num); } + case UnOp::ABS: { return Symbol::createNum(std::abs(num)); } + case UnOp::NOT: { return Symbol::createNum(~num); } + } + assert(false); + } + else if (op == UnOp::NEG && a.type() == SymbolType::Fun) { + return a.flipSign(); + } + undefined_ = true; + return Symbol::createNum(0); +} + +unsigned GroundTermParser::terms() { + return terms_.emplace(); +} + +Symbol GroundTermParser::tuple(unsigned uid, bool forceTuple) { + SymVec args(terms_.erase(uid)); + if (!forceTuple && args.size() == 1) { + return args.front(); + } + else { + return Symbol::createTuple(Potassco::toSpan(args)); + } +} + +unsigned GroundTermParser::terms(unsigned uid, Symbol a) { + terms_[uid].emplace_back(a); + return uid; +} + +SymVec GroundTermParser::terms(unsigned uid) { + return terms_.erase(uid); +} + +void GroundTermParser::parseError(std::string const &message, Logger &) { + Location loc("", line(), column(), "", line(), column()); + std::ostringstream oss; + oss << loc << ": " << "error: " << message << "\n"; + throw GringoError(oss.str().c_str()); +} + +void GroundTermParser::lexerError(StringSpan token, Logger &) { + Location loc("", line(), column(), "", line(), column()); + std::ostringstream oss; + oss << loc << ": " << "error: unexpected token:\n" + << std::string(token.first, token.size) << "\n"; + throw GringoError(oss.str().c_str()); +} + +int GroundTermParser::lex(void *pValue, Logger &log) { + return lex_impl(pValue, log); +} + +GroundTermParser::~GroundTermParser() { } + +} } + +#include "input/groundtermlexer.hh" diff --git a/libgringo/src/input/literal.cc b/libgringo/src/input/literal.cc new file mode 100644 index 0000000..1c1785e --- /dev/null +++ b/libgringo/src/input/literal.cc @@ -0,0 +1,63 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/literal.hh" + +namespace Gringo { namespace Input { + +// {{{ definition of Projection + +Projection::Projection(UTerm &&projected, UTerm &&project) +: projected(std::move(projected)) +, project(std::move(project)) { } + +Projection::Projection(Projection &&) = default; +Projection &Projection::operator=(Projection &&) = default; + +Projection::~Projection() = default; + +Projection::operator Term const &() const { return *projected; } + +// }}} +// {{{ definition of Projections + +Projections::Projections() = default; + +Projections::Projections(Projections &&) = default; + +Projections::~Projections() = default; + +Projections::ProjectionMap::Iterator Projections::begin() { + return proj.begin(); +} +Projections::ProjectionMap::Iterator Projections::end() { + return proj.end(); +} + +UTerm Projections::add(Term &term) { + AuxGen gen; + auto ret(term.project(true, gen)); + proj.push(std::move(std::get<1>(ret)), std::move(std::get<2>(ret))); + return std::move(std::get<0>(ret)); +} + +// }}} + +} } // namespace Input Gringo diff --git a/libgringo/src/input/literals.cc b/libgringo/src/input/literals.cc new file mode 100644 index 0000000..e02e855 --- /dev/null +++ b/libgringo/src/input/literals.cc @@ -0,0 +1,503 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/literals.hh" +#include "gringo/ground/literals.hh" +#include "gringo/output/output.hh" +#include "gringo/utility.hh" + +namespace Gringo { namespace Input { + +// {{{1 definition of Literal::projectScore + +unsigned PredicateLiteral::projectScore() const { + return 1 + repr->projectScore(); +} +unsigned RelationLiteral::projectScore() const { + return left->projectScore() + right->projectScore(); +} + +// {{{1 definition of Literal::print + +inline void PredicateLiteral::print(std::ostream &out) const { + if (auxiliary()) { out << "["; } + out << naf << *repr; + if (auxiliary()) { out << "]"; } +} +inline void RelationLiteral::print(std::ostream &out) const { out << *left << rel << *right; } +inline void RangeLiteral::print(std::ostream &out) const { out << "#range(" << *assign << "," << *lower << "," << *upper << ")"; } +inline void FalseLiteral::print(std::ostream &out) const { out << "#false"; } +inline void ScriptLiteral::print(std::ostream &out) const { + out << "#script(" << *assign << "," << name << "("; + print_comma(out, args, ",", [](std::ostream &out, UTerm const &term) { out << *term; }); + out << ")"; +} +inline void CSPLiteral::print(std::ostream &out) const { + assert(!terms.empty()); + if (auxiliary()) { out << "["; } + out << terms.front().term; + for (auto it = terms.begin() + 1, ie = terms.end(); it != ie; ++it) { out << *it; } + if (auxiliary()) { out << "]"; } +} + +// {{{1 definition of Literal::clone + +PredicateLiteral *PredicateLiteral::clone() const { + return make_locatable(loc(), naf, get_clone(repr)).release(); +} +ProjectionLiteral *ProjectionLiteral::clone() const { + throw std::logic_error("ProjectionLiteral::clone must not be called!!!"); +} +RelationLiteral *RelationLiteral::clone() const { + return make_locatable(loc(), rel, get_clone(left), get_clone(right)).release(); +} +RangeLiteral *RangeLiteral::clone() const { + return make_locatable(loc(), get_clone(assign), get_clone(lower), get_clone(upper)).release(); +} +FalseLiteral *FalseLiteral::clone() const { + return make_locatable(loc()).release(); +} +ScriptLiteral *ScriptLiteral::clone() const { + return make_locatable(loc(), get_clone(assign), name, get_clone(args)).release(); +} +CSPLiteral *CSPLiteral::clone() const { + return make_locatable(loc(), get_clone(terms)).release(); +} + +// {{{1 definition of Literal::simplify + +bool PredicateLiteral::simplify(Logger &log, Projections &project, SimplifyState &state, bool positional, bool singleton) { + if (singleton && positional && naf == NAF::POS) { + positional = false; + } + auto ret(repr->simplify(state, positional, false, log)); + ret.update(repr); + if (ret.undefined()) { return false; } + if (repr->simplify(state, positional, false, log).update(repr).project) { + auto rep(project.add(*repr)); + Term::replace(repr, std::move(rep)); + } + return true; +} +bool RelationLiteral::simplify(Logger &log, Projections &, SimplifyState &state, bool, bool) { + if (left->simplify(state, false, false, log).update(left).undefined()) { return false; } + if (right->simplify(state, false, false, log).update(right).undefined()) { return false; } + return true; +} +bool RangeLiteral::simplify(Logger &, Projections &, SimplifyState &, bool, bool) { + throw std::logic_error("RangeLiteral::simplify should never be called if used properly"); +} +bool FalseLiteral::simplify(Logger &, Projections &, SimplifyState &, bool, bool) { return true; } +bool ScriptLiteral::simplify(Logger &, Projections &, SimplifyState &, bool, bool) { + throw std::logic_error("ScriptLiteral::simplify should never be called if used properly"); +} +bool CSPLiteral::simplify(Logger &log, Projections &, SimplifyState &state, bool, bool) { + for (auto &x : terms) { + if (!x.simplify(state, log)) { return false; }; + } + return true; +} + +// {{{1 definition of Literal::collect + +void PredicateLiteral::collect(VarTermBoundVec &vars, bool bound) const { + repr->collect(vars, bound && naf == NAF::POS); +} +void RelationLiteral::collect(VarTermBoundVec &vars, bool bound) const { + left->collect(vars, bound && rel == Relation::EQ); + right->collect(vars, false); +} +void RangeLiteral::collect(VarTermBoundVec &vars, bool bound) const { + assign->collect(vars, bound); + lower->collect(vars, false); + upper->collect(vars, false); +} +void FalseLiteral::collect(VarTermBoundVec &, bool) const { } +void ScriptLiteral::collect(VarTermBoundVec &vars, bool bound) const { + assign->collect(vars, bound); + for (auto &x : args) { x->collect(vars, false); } +} +void CSPLiteral::collect(VarTermBoundVec &vars, bool) const { + for (auto &x : terms) { x.collect(vars); } +} + +// {{{1 definition of Literal::operator== + +inline bool PredicateLiteral::operator==(Literal const &x) const { + auto t = dynamic_cast(&x); + return t && naf == t->naf && is_value_equal_to(repr, t->repr) && (auxiliary_ == t->auxiliary_); +} +inline bool RelationLiteral::operator==(Literal const &x) const { + auto t = dynamic_cast(&x); + return t && rel == t->rel && is_value_equal_to(left, t->left) && is_value_equal_to(right, t->right); +} +inline bool RangeLiteral::operator==(Literal const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(assign, t->assign) && is_value_equal_to(lower, t->lower) && is_value_equal_to(upper, t->upper); +} +inline bool FalseLiteral::operator==(Literal const &x) const { + return dynamic_cast(&x) != nullptr; +} +inline bool ScriptLiteral::operator==(Literal const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(assign, t->assign) && name == t->name && is_value_equal_to(args, t->args); +} +inline bool CSPLiteral::operator==(Literal const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(terms, t->terms) && (auxiliary_ == t->auxiliary_); +} + +// {{{1 definition of Literal::rewriteArithmetics + +void PredicateLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &, AuxGen &auxGen) { + if (naf == NAF::POS) { Term::replace(repr, repr->rewriteArithmetics(arith, auxGen)); } +} +void RelationLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &assign, AuxGen &auxGen) { + if (rel == Relation::EQ) { + if (right->hasVar()) { + assign.emplace_back(get_clone(right), get_clone(left)); + Term::replace(assign.back().first, assign.back().first->rewriteArithmetics(arith, auxGen)); + } + Term::replace(left, left->rewriteArithmetics(arith, auxGen)); + } +} +void RangeLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &, AuxGen &auxGen) { + Term::replace(this->assign, this->assign->rewriteArithmetics(arith, auxGen)); +} +void FalseLiteral::rewriteArithmetics(Term::ArithmeticsMap &, AssignVec &, AuxGen &) { } +void ScriptLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &, AuxGen &auxGen) { + Term::replace(this->assign, this->assign->rewriteArithmetics(arith, auxGen)); +} +void CSPLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, AssignVec &, AuxGen &auxGen) { + for (auto &x : terms) { x.rewriteArithmetics(arith, auxGen); } +} + +// {{{1 definition of Literal::hash + +inline size_t PredicateLiteral::hash() const { + return get_value_hash(typeid(PredicateLiteral).hash_code(), size_t(naf), repr); +} +inline size_t RelationLiteral::hash() const { + return get_value_hash(typeid(RelationLiteral).hash_code(), size_t(rel), left, right); +} +inline size_t RangeLiteral::hash() const { + return get_value_hash(typeid(RangeLiteral).hash_code(), assign, lower, upper); +} +inline size_t FalseLiteral::hash() const { + return get_value_hash(typeid(FalseLiteral).hash_code()); +} +inline size_t ScriptLiteral::hash() const { + return get_value_hash(typeid(RangeLiteral).hash_code(), assign, name, args); +} +inline size_t CSPLiteral::hash() const { + return get_value_hash(typeid(CSPLiteral).hash_code(), terms); +} + +// {{{1 definition of Literal::unpool + +ULitVec PredicateLiteral::unpool(bool) const { + ULitVec value; + auto f = [&](UTerm &&y){ value.emplace_back(make_locatable(loc(), naf, std::move(y))); }; + Term::unpool(repr, Gringo::unpool, f); + return value; +} +ULitVec ProjectionLiteral::unpool(bool) const { + throw std::logic_error("ProjectionLiteral::unpool must not be called!!!"); +} +ULitVec RelationLiteral::unpool(bool) const { + ULitVec value; + auto f = [&](UTerm &&l, UTerm &&r) { value.emplace_back(make_locatable(loc(), rel, std::move(l), std::move(r))); }; + Term::unpool(left, right, Gringo::unpool, Gringo::unpool, f); + return value; +} +ULitVec RangeLiteral::unpool(bool) const { + ULitVec value; + value.emplace_back(ULit(clone())); + return value; +} +ULitVec FalseLiteral::unpool(bool) const { + ULitVec value; + value.emplace_back(ULit(clone())); + return value; +} +ULitVec ScriptLiteral::unpool(bool) const { + ULitVec value; + value.emplace_back(ULit(clone())); + return value; +} +ULitVec CSPLiteral::unpool(bool beforeRewrite) const { + using namespace std::placeholders; + ULitVec value; + auto f = [&](Terms &&args) { value.emplace_back(make_locatable(loc(), std::move(args))); }; + auto unpoolLit = [&](CSPLiteral const &x) { Term::unpool(x.terms.begin(), x.terms.end(), std::bind(&CSPRelTerm::unpool, _1), f); }; + if (!beforeRewrite) { + for (auto it = terms.begin() + 1, ie = terms.end(); it != ie; ++it) { + unpoolLit(*make_locatable(loc(), it->rel, get_clone((it-1)->term), get_clone(it->term))); + } + } + else { unpoolLit(*this); } + return value; +} + +// {{{1 definition of Literal::toTuple + +void PredicateLiteral::toTuple(UTermVec &tuple, int &) { + int id = 0; + switch (naf) { + case NAF::POS: { id = 0; break; } + case NAF::NOT: { id = 1; break; } + case NAF::NOTNOT: { id = 2; break; } + } + tuple.emplace_back(make_locatable(loc(), Symbol::createNum(id))); + tuple.emplace_back(get_clone(repr)); +} +void RelationLiteral::toTuple(UTermVec &tuple, int &id) { + tuple.emplace_back(make_locatable(loc(), Symbol::createNum(id+3))); + tuple.emplace_back(get_clone(left)); + tuple.emplace_back(get_clone(right)); + id++; +} +void RangeLiteral::toTuple(UTermVec &, int &) { + throw std::logic_error("RangeLiteral::toTuple should never be called if used properly"); +} +void FalseLiteral::toTuple(UTermVec &tuple, int &id) { + tuple.emplace_back(make_locatable(loc(), Symbol::createNum(id+3))); + id++; +} +void ScriptLiteral::toTuple(UTermVec &, int &) { + throw std::logic_error("ScriptLiteral::toTuple should never be called if used properly"); +} +void CSPLiteral::toTuple(UTermVec &tuple, int &id) { + VarTermSet vars; + for (auto &x : terms) { x.collect(vars); } + tuple.emplace_back(make_locatable(loc(), Symbol::createNum(id+3))); + for (auto &x : vars) { tuple.emplace_back(UTerm(x.get().clone())); } + id++; +} + +// {{{1 definition of Literal::isEDB + +Symbol Literal::isEDB() const { return {}; } +Symbol PredicateLiteral::isEDB() const { return naf == NAF::POS ? repr->isEDB() : Symbol(); } + +// {{{1 definition of Literal::hasPool + +inline bool PredicateLiteral::hasPool(bool) const { return repr->hasPool(); } +inline bool RelationLiteral::hasPool(bool) const { return left->hasPool() || right->hasPool(); } +inline bool RangeLiteral::hasPool(bool) const { return false; } +inline bool FalseLiteral::hasPool(bool) const { return false; } +inline bool ScriptLiteral::hasPool(bool) const { return false; } +inline bool CSPLiteral::hasPool(bool beforeRewrite) const { + if (beforeRewrite) { + for (auto &x : terms) { + if (x.hasPool()) { return true; } + } + return false; + } + else { return terms.size() > 2; } +} + +// {{{1 definition of Literal::replace + +inline void PredicateLiteral::replace(Defines &x) { Term::replace(repr, repr->replace(x, false)); } +inline void RelationLiteral::replace(Defines &x) { + Term::replace(left, left->replace(x, true)); + Term::replace(right, right->replace(x, true)); +} +inline void RangeLiteral::replace(Defines &x) { + Term::replace(assign, assign->replace(x, true)); + Term::replace(lower, lower->replace(x, true)); + Term::replace(upper, upper->replace(x, true)); +} +inline void FalseLiteral::replace(Defines &) { } +inline void ScriptLiteral::replace(Defines &x) { + Term::replace(assign, assign->replace(x, true)); + for (auto &y : args) { Term::replace(y, y->replace(x, true)); } +} +inline void CSPLiteral::replace(Defines &x) { + for (auto &y : terms) { y.replace(x); } +} + +// {{{1 definition of Literal::toGround + +inline Ground::ULit PredicateLiteral::toGround(DomainData &x, bool auxiliary) const { + return gringo_make_unique(auxiliary_ || auxiliary, x.add(repr->getSig()), naf, get_clone(repr)); +} +inline Ground::ULit ProjectionLiteral::toGround(DomainData &x, bool auxiliary) const { + bool initialized = initialized_; + initialized_ = true; + return gringo_make_unique(auxiliary_ || auxiliary, x.add(repr->getSig()), get_clone(repr), initialized); +} +inline Ground::ULit RelationLiteral::toGround(DomainData &, bool) const { + return gringo_make_unique(rel, get_clone(left), get_clone(right)); +} +inline Ground::ULit RangeLiteral::toGround(DomainData &, bool) const { + return gringo_make_unique(get_clone(assign), get_clone(lower), get_clone(upper)); +} +inline Ground::ULit FalseLiteral::toGround(DomainData &, bool) const { + throw std::logic_error("FalseLiteral::toGround: must not happen"); +} +inline Ground::ULit ScriptLiteral::toGround(DomainData &, bool) const { + return gringo_make_unique(get_clone(assign), name, get_clone(args)); +} +inline Ground::ULit CSPLiteral::toGround(DomainData &data, bool auxiliary) const { + assert(terms.size() == 2); + return gringo_make_unique(data, auxiliary_ || auxiliary, terms[1].rel, get_clone(terms[0].term), get_clone(terms[1].term)); +} + +// {{{1 definition of Literal::shift + +ULit PredicateLiteral::shift(bool negate) { + if (naf == NAF::POS) { return nullptr; } + else { + NAF inv = (naf == NAF::NOT) == negate ? NAF::NOTNOT : NAF::NOT; + return make_locatable(loc(), inv, std::move(repr)); + } +} +ULit ProjectionLiteral::shift(bool) { + throw std::logic_error("ProjectionLiteral::shift must not be called!!!"); +} +ULit RelationLiteral::shift(bool negate) { + return make_locatable(loc(), negate ? neg(rel) : rel, std::move(left), std::move(right)); +} +ULit RangeLiteral::shift(bool) { throw std::logic_error("RangeLiteral::shift should never be called if used properly"); } +ULit FalseLiteral::shift(bool) { return nullptr; } +ULit ScriptLiteral::shift(bool) { throw std::logic_error("ScriptLiteral::shift should never be called if used properly"); } +ULit CSPLiteral::shift(bool negate) { + if (negate) { + assert(terms.size() == 2); + return make_locatable(loc(), neg(terms[1].rel), std::move(terms[0].term), std::move(terms[1].term)); + } + else { return make_locatable(loc(), std::move(terms)); } +} + +// {{{1 definition of Literal::headRepr + +UTerm PredicateLiteral::headRepr() const { + assert(naf == NAF::POS); + return get_clone(repr); +} +UTerm RelationLiteral::headRepr() const { + throw std::logic_error("RelationLiteral::toTuple should never be called if used properly"); +} +UTerm RangeLiteral::headRepr() const { + throw std::logic_error("RangeLiteral::toTuple should never be called if used properly"); +} +UTerm FalseLiteral::headRepr() const { + return nullptr; +} +UTerm ScriptLiteral::headRepr() const { + throw std::logic_error("ScriptLiteral::toTuple should never be called if used properly"); +} +UTerm CSPLiteral::headRepr() const { + throw std::logic_error("CSPLiteral::toTuple should never be called if used properly"); +} + +// }}}1 + +// {{{1 definition of PredicateLiteral + +PredicateLiteral::PredicateLiteral(NAF naf, UTerm &&repr, bool auxiliary) +: naf(naf) +, auxiliary_(auxiliary) +, repr(std::move(repr)) { + assert(this->repr->isAtom()); +} + +void PredicateLiteral::getNeg(std::function f) const { + Sig sig(repr->getSig()); + if (sig.sign()) { f(sig); } +} + +PredicateLiteral::~PredicateLiteral() { } + +// {{{1 definition of ProjectionLiteral + +ProjectionLiteral::ProjectionLiteral(UTerm &&repr) + : PredicateLiteral(NAF::POS, std::move(repr)), initialized_(false) { } + +ProjectionLiteral::~ProjectionLiteral() { } + +// {{{1 definition of RelationLiteral + +RelationLiteral::RelationLiteral(Relation rel, UTerm &&left, UTerm &&right) + : rel(rel) + , left(std::move(left)) + , right(std::move(right)) { } + +ULit RelationLiteral::make(Term::ArithmeticsMap::value_type::value_type &x) { + Location loc(x.first->loc()); + return make_locatable(loc, Relation::EQ, std::move(x.second), get_clone(x.first)); +} + +ULit RelationLiteral::make(Literal::AssignVec::value_type &x) { + Location loc(x.first->loc() + x.second->loc()); + return make_locatable(loc, Relation::EQ, std::move(x.first), get_clone(x.second)); +} + +RelationLiteral::~RelationLiteral() { } + +// {{{1 definition of RangeLiteral + +RangeLiteral::RangeLiteral(UTerm &&assign, UTerm &&lower, UTerm &&upper) + : assign(std::move(assign)) + , lower(std::move(lower)) + , upper(std::move(upper)) { } + +ULit RangeLiteral::make(SimplifyState::DotsMap::value_type &dot) { + Location loc(std::get<0>(dot)->loc()); + return make_locatable(loc, std::move(std::get<0>(dot)), std::move(std::get<1>(dot)), std::move(std::get<2>(dot))); +} + +RangeLiteral::~RangeLiteral() { } + +// {{{1 definition of FalseLiteral + +FalseLiteral::FalseLiteral() { } +FalseLiteral::~FalseLiteral() { } + +// {{{1 definition of ScriptLiteral + +ScriptLiteral::ScriptLiteral(UTerm &&assign, String name, UTermVec &&args) + : assign(std::move(assign)) + , name(name) + , args(std::move(args)) { } + +ULit ScriptLiteral::make(SimplifyState::ScriptMap::value_type &script) { + Location loc(std::get<0>(script)->loc()); + return make_locatable(loc, std::move(std::get<0>(script)), std::move(std::get<1>(script)), std::move(std::get<2>(script))); +} + +ScriptLiteral::~ScriptLiteral() { } + +// {{{1 definition of CSPLiteral + +CSPLiteral::CSPLiteral(Relation rel, CSPAddTerm &&left, CSPAddTerm &&right) { + terms.emplace_back(rel, std::move(left)); + terms.emplace_back(rel, std::move(right)); +} +void CSPLiteral::append(Relation rel, CSPAddTerm &&x) { terms.emplace_back(rel, std::move(x)); } +CSPLiteral::CSPLiteral(Terms &&terms) : terms(std::move(terms)) { } +CSPLiteral::~CSPLiteral() { } + +// }}}1 + +} } // namespace Input Gringo + diff --git a/libgringo/src/input/nongroundgrammar.yy b/libgringo/src/input/nongroundgrammar.yy new file mode 100644 index 0000000..c9b70aa --- /dev/null +++ b/libgringo/src/input/nongroundgrammar.yy @@ -0,0 +1,1013 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +// {{{1 preamble +%require "2.5" +//%define api.namespace {Gringo::Input::NonGroundGrammar} +%define namespace "Gringo::Input::NonGroundGrammar" +//%define api.prefix {GringoNonGroundGrammar_} +%name-prefix "GringoNonGroundGrammar_" +//%define parse.error verbose +%error-verbose +//%define api.location.type {DefaultLocation} +%define location_type "DefaultLocation" +%locations +%defines +%parse-param { Gringo::Input::NonGroundParser *lexer } +%lex-param { Gringo::Input::NonGroundParser *lexer } +%skeleton "lalr1.cc" +//%define parse.trace +//%debug + +// {{{1 auxiliary code + +%code requires +{ + #include "gringo/input/programbuilder.hh" + #include "potassco/basic_types.h" + + namespace Gringo { namespace Input { class NonGroundParser; } } + + struct DefaultLocation : Gringo::Location { + DefaultLocation() : Location("", 0, 0, "", 0, 0) { } + }; + +} + +%{ + +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/programbuilder.hh" +#include + +#define BUILDER (lexer->builder()) +#define LOGGER (lexer->logger()) +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (N) { \ + (Current).beginFilename = YYRHSLOC (Rhs, 1).beginFilename; \ + (Current).beginLine = YYRHSLOC (Rhs, 1).beginLine; \ + (Current).beginColumn = YYRHSLOC (Rhs, 1).beginColumn; \ + (Current).endFilename = YYRHSLOC (Rhs, N).endFilename; \ + (Current).endLine = YYRHSLOC (Rhs, N).endLine; \ + (Current).endColumn = YYRHSLOC (Rhs, N).endColumn; \ + } \ + else { \ + (Current).beginFilename = YYRHSLOC (Rhs, 0).endFilename; \ + (Current).beginLine = YYRHSLOC (Rhs, 0).endLine; \ + (Current).beginColumn = YYRHSLOC (Rhs, 0).endColumn; \ + (Current).endFilename = YYRHSLOC (Rhs, 0).endFilename; \ + (Current).endLine = YYRHSLOC (Rhs, 0).endLine; \ + (Current).endColumn = YYRHSLOC (Rhs, 0).endColumn; \ + } \ + } \ + while (false) + +using namespace Gringo; +using namespace Gringo::Input; + +int GringoNonGroundGrammar_lex(void *value, Gringo::Location* loc, NonGroundParser *lexer) { + return lexer->lex(value, *loc); +} + +%} + +%code { + +void NonGroundGrammar::parser::error(DefaultLocation const &l, std::string const &msg) { + lexer->parseError(l, msg); +} + +} + +// {{{1 nonterminals + +// {{{2 union type for stack elements +%union +{ + IdVecUid idlist; + CSPLitUid csplit; + CSPAddTermUid cspaddterm; + CSPMulTermUid cspmulterm; + CSPElemVecUid cspelemvec; + TermUid term; + TermVecUid termvec; + TermVecVecUid termvecvec; + LitVecUid litvec; + LitUid lit; + BdAggrElemVecUid bodyaggrelemvec; + CondLitVecUid condlitlist; + HdAggrElemVecUid headaggrelemvec; + BoundVecUid bounds; + BdLitVecUid body; + HdLitUid head; + Relation rel; + AggregateFunction fun; + struct { + NAF first; + CSPElemVecUid second; + } disjoint; + struct { + uintptr_t first; + unsigned second; + } pair; + struct { + TermVecUid first; + LitVecUid second; + } bodyaggrelem; + struct { + LitUid first; + LitVecUid second; + } lbodyaggrelem; + struct { + AggregateFunction fun; + unsigned choice : 1; + unsigned elems : 31; + } aggr; + struct { + Relation rel; + TermUid term; + } bound; + struct { + TermUid first; + TermUid second; + } termpair; + unsigned uid; + uintptr_t str; + int num; + Potassco::Heuristic_t::E heu; + TheoryOpVecUid theoryOps; + TheoryTermUid theoryTerm; + TheoryOptermUid theoryOpterm; + TheoryOptermVecUid theoryOpterms; + TheoryElemVecUid theoryElems; + struct { + TheoryOptermVecUid first; + LitVecUid second; + } theoryElem; + TheoryAtomUid theoryAtom; + TheoryOpDefUid theoryOpDef; + TheoryOpDefVecUid theoryOpDefs; + TheoryTermDefUid theoryTermDef; + TheoryAtomDefUid theoryAtomDef; + TheoryDefVecUid theoryDefs; + TheoryAtomType theoryAtomType; +} + +// }}}2 + +// TODO: improve naming scheme +%type constterm term tuple theory_atom_name atom +%type termvec ntermvec consttermvec unaryargvec optimizetuple tuplevec tuplevec_sem +%type argvec constargvec binaryargvec +%type literal +%type litvec nlitvec optcondition noptcondition +%type bodyaggrelem +%type altbodyaggrelem conjunction +%type bodyaggrelemvec +%type altbodyaggrelemvec altheadaggrelemvec disjunctionsep disjunction +%type headaggrelemvec +%type cspelemvec ncspelemvec +%type upper +%type bodycomma bodydot bodyconddot optimizelitvec optimizecond +%type head +%type lubodyaggregate luheadaggregate +%type identifier theory_definition_identifier +%type aggregatefunction +%type bodyaggregate headaggregate +%type cmp csp_rel +%type optimizeweight +%type csp_mul_term +%type csp_add_term +%type csp_literal +%type disjoint +%type idlist nidlist +%type theory_op_list theory_operator_list theory_operator_nlist +%type theory_term +%type theory_opterm +%type theory_opterm_list theory_opterm_nlist +%type theory_atom_element +%type theory_atom_element_list theory_atom_element_nlist +%type theory_atom +%type theory_term_definition +%type theory_atom_definition +%type theory_operator_definition +%type theory_operator_definition_nlist theory_operator_definiton_list +%type theory_definition_nlist theory_definition_list +%type theory_atom_type + +// {{{1 terminals + +%token + ADD "+" + AND "&" + EQ "=" + AT "@" + BASE "#base" + BNOT "~" + COLON ":" + COMMA "," + CONST "#const" + COUNT "#count" + CSP "$" + CSP_ADD "$+" + CSP_SUB "$-" + CSP_MUL "$*" + CSP_LEQ "$<=" + CSP_LT "$<" + CSP_GT "$>" + CSP_GEQ "$>=" + CSP_EQ "$=" + CSP_NEQ "$!=" + CUMULATIVE "#cumulative" + DISJOINT "#disjoint" + DOT "." + DOTS ".." + END 0 "" + EXTERNAL "#external" + FALSE "#false" + FORGET "#forget" + GEQ ">=" + GT ">" + IF ":-" + INCLUDE "#include" + INFIMUM "#inf" + LBRACE "{" + LBRACK "[" + LEQ "<=" + LPAREN "(" + LT "<" + MAX "#max" + MAXIMIZE "#maximize" + MIN "#min" + MINIMIZE "#minimize" + MOD "\\" + MUL "*" + NEQ "!=" + POW "**" + QUESTION "?" + RBRACE "}" + RBRACK "]" + RPAREN ")" + SEM ";" + SHOW "#show" + EDGE "#edge" + PROJECT "#project" + HEURISTIC "#heuristic" + SHOWSIG "#showsig" + SLASH "/" + SUB "-" + SUM "#sum" + SUMP "#sum+" + SUPREMUM "#sup" + TRUE "#true" + BLOCK "#program" + UBNOT + UMINUS + VBAR "|" + VOLATILE "#volatile" + WIF ":~" + XOR "^" + PARSE_LP "" + PARSE_DEF "" + ANY "any" + UNARY "unary" + BINARY "binary" + LEFT "left" + RIGHT "right" + HEAD "head" + BODY "body" + DIRECTIVE "directive" + THEORY "#theory" + + +%token + NUMBER "" + +%token + ANONYMOUS "" + IDENTIFIER "" + PYTHON "" + LUA "" + STRING "" + VARIABLE "" + THEORY_OP "" + NOT "not" + +// {{{2 operator precedence and associativity + +%left DOTS +%left XOR +%left QUESTION +%left AND +%left ADD SUB +%left MUL SLASH MOD +%right POW +%left UMINUS UBNOT + +// }}}1 + +%% + +// {{{1 logic program and global definitions + +start + : PARSE_LP program + | PARSE_DEF define + ; + +program + : program statement + | + ; + +// Note: skip until the next "." in case of an error and switch back to normal lexing + +statement + : error disable_theory_lexing DOT + ; + +identifier + : IDENTIFIER[a] { $$ = $a; } + ; + +// {{{1 terms +// {{{2 constterms are terms without variables and pooling operators + +constterm + : constterm[a] XOR constterm[b] { $$ = BUILDER.term(@$, BinOp::XOR, $a, $b); } + | constterm[a] QUESTION constterm[b] { $$ = BUILDER.term(@$, BinOp::OR, $a, $b); } + | constterm[a] AND constterm[b] { $$ = BUILDER.term(@$, BinOp::AND, $a, $b); } + | constterm[a] ADD constterm[b] { $$ = BUILDER.term(@$, BinOp::ADD, $a, $b); } + | constterm[a] SUB constterm[b] { $$ = BUILDER.term(@$, BinOp::SUB, $a, $b); } + | constterm[a] MUL constterm[b] { $$ = BUILDER.term(@$, BinOp::MUL, $a, $b); } + | constterm[a] SLASH constterm[b] { $$ = BUILDER.term(@$, BinOp::DIV, $a, $b); } + | constterm[a] MOD constterm[b] { $$ = BUILDER.term(@$, BinOp::MOD, $a, $b); } + | constterm[a] POW constterm[b] { $$ = BUILDER.term(@$, BinOp::POW, $a, $b); } + | SUB constterm[a] %prec UMINUS { $$ = BUILDER.term(@$, UnOp::NEG, $a); } + | BNOT constterm[a] %prec UBNOT { $$ = BUILDER.term(@$, UnOp::NOT, $a); } + | LPAREN RPAREN { $$ = BUILDER.term(@$, BUILDER.termvec(), false); } + | LPAREN COMMA RPAREN { $$ = BUILDER.term(@$, BUILDER.termvec(), true); } + | LPAREN consttermvec[a] RPAREN { $$ = BUILDER.term(@$, $a, false); } + | LPAREN consttermvec[a] COMMA RPAREN { $$ = BUILDER.term(@$, $a, true); } + | identifier[a] LPAREN constargvec[b] RPAREN { $$ = BUILDER.term(@$, String::fromRep($a), $b, false); } + | AT[l] identifier[a] LPAREN constargvec[b] RPAREN { $$ = BUILDER.term(@$, String::fromRep($a), $b, true); } + | VBAR[l] constterm[a] VBAR { $$ = BUILDER.term(@$, UnOp::ABS, $a); } + | identifier[a] { $$ = BUILDER.term(@$, Symbol::createId(String::fromRep($a))); } + | NUMBER[a] { $$ = BUILDER.term(@$, Symbol::createNum($a)); } + | STRING[a] { $$ = BUILDER.term(@$, Symbol::createStr(String::fromRep($a))); } + | INFIMUM[a] { $$ = BUILDER.term(@$, Symbol::createInf()); } + | SUPREMUM[a] { $$ = BUILDER.term(@$, Symbol::createSup()); } + ; + +// {{{2 arguments lists for functions in constant terms + +consttermvec + : constterm[a] { $$ = BUILDER.termvec(BUILDER.termvec(), $a); } + | consttermvec[a] COMMA constterm[b] { $$ = BUILDER.termvec($a, $b); } + ; + +constargvec + : consttermvec[a] { $$ = BUILDER.termvecvec(BUILDER.termvecvec(), $a); } + | { $$ = BUILDER.termvecvec(); } + ; + +// {{{2 terms including variables + +term + : term[a] DOTS term[b] { $$ = BUILDER.term(@$, $a, $b); } + | term[a] XOR term[b] { $$ = BUILDER.term(@$, BinOp::XOR, $a, $b); } + | term[a] QUESTION term[b] { $$ = BUILDER.term(@$, BinOp::OR, $a, $b); } + | term[a] AND term[b] { $$ = BUILDER.term(@$, BinOp::AND, $a, $b); } + | term[a] ADD term[b] { $$ = BUILDER.term(@$, BinOp::ADD, $a, $b); } + | term[a] SUB term[b] { $$ = BUILDER.term(@$, BinOp::SUB, $a, $b); } + | term[a] MUL term[b] { $$ = BUILDER.term(@$, BinOp::MUL, $a, $b); } + | term[a] SLASH term[b] { $$ = BUILDER.term(@$, BinOp::DIV, $a, $b); } + | term[a] MOD term[b] { $$ = BUILDER.term(@$, BinOp::MOD, $a, $b); } + | term[a] POW term[b] { $$ = BUILDER.term(@$, BinOp::POW, $a, $b); } + | SUB term[a] %prec UMINUS { $$ = BUILDER.term(@$, UnOp::NEG, $a); } + | BNOT term[a] %prec UBNOT { $$ = BUILDER.term(@$, UnOp::NOT, $a); } + | LPAREN tuplevec[a] RPAREN { $$ = BUILDER.pool(@$, $a); } + | identifier[a] LPAREN argvec[b] RPAREN { $$ = BUILDER.term(@$, String::fromRep($a), $b, false); } + | AT identifier[a] LPAREN argvec[b] RPAREN { $$ = BUILDER.term(@$, String::fromRep($a), $b, true); } + | VBAR unaryargvec[a] VBAR { $$ = BUILDER.term(@$, UnOp::ABS, $a); } + | identifier[a] { $$ = BUILDER.term(@$, Symbol::createId(String::fromRep($a))); } + | NUMBER[a] { $$ = BUILDER.term(@$, Symbol::createNum($a)); } + | STRING[a] { $$ = BUILDER.term(@$, Symbol::createStr(String::fromRep($a))); } + | INFIMUM[a] { $$ = BUILDER.term(@$, Symbol::createInf()); } + | SUPREMUM[a] { $$ = BUILDER.term(@$, Symbol::createSup()); } + | VARIABLE[a] { $$ = BUILDER.term(@$, String::fromRep($a)); } + | ANONYMOUS[a] { $$ = BUILDER.term(@$, String("_")); } + ; + +// {{{2 argument lists for unary operations + +unaryargvec + : term[a] { $$ = BUILDER.termvec(BUILDER.termvec(), $a); } + | unaryargvec[a] SEM term[b] { $$ = BUILDER.termvec($a, $b); } + ; + +// {{{2 argument lists for functions + +ntermvec + : term[a] { $$ = BUILDER.termvec(BUILDER.termvec(), $a); } + | ntermvec[a] COMMA term[b] { $$ = BUILDER.termvec($a, $b); } + ; + +termvec + : ntermvec[a] { $$ = $a; } + | { $$ = BUILDER.termvec(); } + ; + +tuple + : ntermvec[a] COMMA { $$ = BUILDER.term(@$, $a, true); } + | ntermvec[a] { $$ = BUILDER.term(@$, $a, false); } + | COMMA { $$ = BUILDER.term(@$, BUILDER.termvec(), true); } + | { $$ = BUILDER.term(@$, BUILDER.termvec(), false); } + +tuplevec_sem + : tuple[b] SEM { $$ = BUILDER.termvec(BUILDER.termvec(), $b); } + | tuplevec_sem[a] tuple[b] SEM { $$ = BUILDER.termvec($a, $b); } + +tuplevec + : tuple[b] { $$ = BUILDER.termvec(BUILDER.termvec(), $b); } + | tuplevec_sem[a] tuple[b] { $$ = BUILDER.termvec($a, $b); } + +argvec + : termvec[b] { $$ = BUILDER.termvecvec(BUILDER.termvecvec(), $b); } + | argvec[a] SEM termvec[b] { $$ = BUILDER.termvecvec($a, $b); } + ; + +binaryargvec + : term[a] COMMA term[b] { $$ = BUILDER.termvecvec(BUILDER.termvecvec(), BUILDER.termvec(BUILDER.termvec(BUILDER.termvec(), $a), $b)); } + | binaryargvec[vec] SEM term[a] COMMA term[b] { $$ = BUILDER.termvecvec($vec, BUILDER.termvec(BUILDER.termvec(BUILDER.termvec(), $a), $b)); } + ; + +// TODO: I might have to create tuples differently +// parse a tuple as a list of terms +// each term is either a tuple or a term -> which afterwards is turned into a pool! + +// {{{1 literals + +cmp + : GT { $$ = Relation::GT; } + | LT { $$ = Relation::LT; } + | GEQ { $$ = Relation::GEQ; } + | LEQ { $$ = Relation::LEQ; } + | EQ { $$ = Relation::EQ; } + | NEQ { $$ = Relation::NEQ; } + ; + +atom + : identifier[id] { $$ = BUILDER.predRep(@$, false, String::fromRep($id), BUILDER.termvecvec(BUILDER.termvecvec(), BUILDER.termvec())); } + | identifier[id] LPAREN argvec[tvv] RPAREN[r] { $$ = BUILDER.predRep(@$, false, String::fromRep($id), $tvv); } + | SUB identifier[id] { $$ = BUILDER.predRep(@$, true, String::fromRep($id), BUILDER.termvecvec(BUILDER.termvecvec(), BUILDER.termvec())); } + | SUB identifier[id] LPAREN argvec[tvv] RPAREN[r] { $$ = BUILDER.predRep(@$, true, String::fromRep($id), $tvv); } + ; + +literal + : TRUE { $$ = BUILDER.boollit(@$, true); } + | NOT TRUE { $$ = BUILDER.boollit(@$, false); } + | NOT NOT TRUE { $$ = BUILDER.boollit(@$, true); } + | FALSE { $$ = BUILDER.boollit(@$, false); } + | NOT FALSE { $$ = BUILDER.boollit(@$, true); } + | NOT NOT FALSE { $$ = BUILDER.boollit(@$, false); } + | atom[a] { $$ = BUILDER.predlit(@$, NAF::POS, $a); } + | NOT atom[a] { $$ = BUILDER.predlit(@$, NAF::NOT, $a); } + | NOT NOT atom[a] { $$ = BUILDER.predlit(@$, NAF::NOTNOT, $a); } + | term[l] cmp[rel] term[r] { $$ = BUILDER.rellit(@$, $rel, $l, $r); } + | NOT term[l] cmp[rel] term[r] { $$ = BUILDER.rellit(@$, neg($rel), $l, $r); } + | NOT NOT term[l] cmp[rel] term[r] { $$ = BUILDER.rellit(@$, $rel, $l, $r); } + | csp_literal[lit] { $$ = BUILDER.csplit($lit); } + ; + +csp_mul_term + : CSP term[var] CSP_MUL term[coe] { $$ = BUILDER.cspmulterm(@$, $coe, $var); } + | term[coe] CSP_MUL CSP term[var] { $$ = BUILDER.cspmulterm(@$, $coe, $var); } + | CSP term[var] { $$ = BUILDER.cspmulterm(@$, BUILDER.term(@$, Symbol::createNum(1)), $var); } + | term[coe] { $$ = BUILDER.cspmulterm(@$, $coe); } + ; + +csp_add_term + : csp_add_term[add] CSP_ADD csp_mul_term[mul] { $$ = BUILDER.cspaddterm(@$, $add, $mul, true); } + | csp_add_term[add] CSP_SUB csp_mul_term[mul] { $$ = BUILDER.cspaddterm(@$, $add, $mul, false); } + | csp_mul_term[mul] { $$ = BUILDER.cspaddterm(@$, $mul); } + ; + +csp_rel + : CSP_GT { $$ = Relation::GT; } + | CSP_LT { $$ = Relation::LT; } + | CSP_GEQ { $$ = Relation::GEQ; } + | CSP_LEQ { $$ = Relation::LEQ; } + | CSP_EQ { $$ = Relation::EQ; } + | CSP_NEQ { $$ = Relation::NEQ; } + ; + +csp_literal + : csp_literal[lit] csp_rel[rel] csp_add_term[b] { $$ = BUILDER.csplit(@$, $lit, $rel, $b); } + | csp_add_term[a] csp_rel[rel] csp_add_term[b] { $$ = BUILDER.csplit(@$, $a, $rel, $b); } + ; + +// {{{1 aggregates + +// {{{2 auxiliary rules + +nlitvec + : literal[lit] { $$ = BUILDER.litvec(BUILDER.litvec(), $lit); } + | nlitvec[vec] COMMA literal[lit] { $$ = BUILDER.litvec($vec, $lit); } + ; + +litvec + : nlitvec[vec] { $$ = $vec; } + | { $$ = BUILDER.litvec(); } + ; + +optcondition + : COLON litvec[vec] { $$ = $vec; } + | { $$ = BUILDER.litvec(); } + ; + +noptcondition + : COLON nlitvec[vec] { $$ = $vec; } + | { $$ = BUILDER.litvec(); } + ; + +aggregatefunction + : SUM { $$ = AggregateFunction::SUM; } + | SUMP { $$ = AggregateFunction::SUMP; } + | MIN { $$ = AggregateFunction::MIN; } + | MAX { $$ = AggregateFunction::MAX; } + | COUNT { $$ = AggregateFunction::COUNT; } + ; + +// {{{2 body aggregate elements + +bodyaggrelem + : COLON litvec[cond] { $$ = { BUILDER.termvec(), $cond }; } + | ntermvec[args] optcondition[cond] { $$ = { $args, $cond }; } + ; + +bodyaggrelemvec + : bodyaggrelem[elem] { $$ = BUILDER.bodyaggrelemvec(BUILDER.bodyaggrelemvec(), $elem.first, $elem.second); } + | bodyaggrelemvec[vec] SEM bodyaggrelem[elem] { $$ = BUILDER.bodyaggrelemvec($vec, $elem.first, $elem.second); } + ; + +// Note: alternative syntax (without weight) + +altbodyaggrelem + : literal[lit] optcondition[cond] { $$ = { $lit, $cond }; } + ; + +altbodyaggrelemvec + : altbodyaggrelem[elem] { $$ = BUILDER.condlitvec(BUILDER.condlitvec(), $elem.first, $elem.second); } + | altbodyaggrelemvec[vec] SEM altbodyaggrelem[elem] { $$ = BUILDER.condlitvec($vec, $elem.first, $elem.second); } + ; + +// {{{2 body aggregates + +bodyaggregate + : LBRACE RBRACE { $$ = { AggregateFunction::COUNT, true, BUILDER.condlitvec() }; } + | LBRACE altbodyaggrelemvec[elems] RBRACE { $$ = { AggregateFunction::COUNT, true, $elems }; } + | aggregatefunction[fun] LBRACE RBRACE { $$ = { $fun, false, BUILDER.bodyaggrelemvec() }; } + | aggregatefunction[fun] LBRACE bodyaggrelemvec[elems] RBRACE { $$ = { $fun, false, $elems }; } + ; + +upper + : term[t] { $$ = { Relation::LEQ, $t }; } + | cmp[rel] term[t] { $$ = { $rel, $t }; } + | { $$ = { Relation::LEQ, TermUid(-1) }; } + ; + +lubodyaggregate + : term[l] bodyaggregate[a] upper[u] { $$ = lexer->aggregate($a.fun, $a.choice, $a.elems, lexer->boundvec(Relation::LEQ, $l, $u.rel, $u.term)); } + | term[l] cmp[rel] bodyaggregate[a] upper[u] { $$ = lexer->aggregate($a.fun, $a.choice, $a.elems, lexer->boundvec($rel, $l, $u.rel, $u.term)); } + | bodyaggregate[a] upper[u] { $$ = lexer->aggregate($a.fun, $a.choice, $a.elems, lexer->boundvec(Relation::LEQ, TermUid(-1), $u.rel, $u.term)); } + | theory_atom[atom] { $$ = lexer->aggregate($atom); } + ; + +// {{{2 head aggregate elements + +headaggrelemvec + : headaggrelemvec[vec] SEM termvec[tuple] COLON literal[head] optcondition[cond] { $$ = BUILDER.headaggrelemvec($vec, $tuple, $head, $cond); } + | termvec[tuple] COLON literal[head] optcondition[cond] { $$ = BUILDER.headaggrelemvec(BUILDER.headaggrelemvec(), $tuple, $head, $cond); } + ; + +altheadaggrelemvec + : literal[lit] optcondition[cond] { $$ = BUILDER.condlitvec(BUILDER.condlitvec(), $lit, $cond); } + | altheadaggrelemvec[vec] SEM literal[lit] optcondition[cond] { $$ = BUILDER.condlitvec($vec, $lit, $cond); } + ; + +// {{{2 head aggregates + +headaggregate + : aggregatefunction[fun] LBRACE RBRACE { $$ = { $fun, false, BUILDER.headaggrelemvec() }; } + | aggregatefunction[fun] LBRACE headaggrelemvec[elems] RBRACE { $$ = { $fun, false, $elems }; } + | LBRACE RBRACE { $$ = { AggregateFunction::COUNT, true, BUILDER.condlitvec()}; } + | LBRACE altheadaggrelemvec[elems] RBRACE { $$ = { AggregateFunction::COUNT, true, $elems}; } + ; + +luheadaggregate + : term[l] headaggregate[a] upper[u] { $$ = lexer->aggregate($a.fun, $a.choice, $a.elems, lexer->boundvec(Relation::LEQ, $l, $u.rel, $u.term)); } + | term[l] cmp[rel] headaggregate[a] upper[u] { $$ = lexer->aggregate($a.fun, $a.choice, $a.elems, lexer->boundvec($rel, $l, $u.rel, $u.term)); } + | headaggregate[a] upper[u] { $$ = lexer->aggregate($a.fun, $a.choice, $a.elems, lexer->boundvec(Relation::LEQ, TermUid(-1), $u.rel, $u.term)); } + | theory_atom[atom] { $$ = lexer->aggregate($atom); } + ; + +// {{{2 disjoint aggregate + +ncspelemvec + : termvec[tuple] COLON csp_add_term[add] optcondition[cond] { $$ = BUILDER.cspelemvec(BUILDER.cspelemvec(), @$, $tuple, $add, $cond); } + | cspelemvec[vec] SEM termvec[tuple] COLON csp_add_term[add] optcondition[cond] { $$ = BUILDER.cspelemvec($vec, @$, $tuple, $add, $cond); } + ; + +cspelemvec + : ncspelemvec[vec] { $$ = $vec; } + | { $$ = BUILDER.cspelemvec(); } + ; + +disjoint + : DISJOINT LBRACE cspelemvec[elems] RBRACE { $$ = { NAF::POS, $elems }; } + | NOT DISJOINT LBRACE cspelemvec[elems] RBRACE { $$ = { NAF::NOT, $elems }; } + | NOT NOT DISJOINT LBRACE cspelemvec[elems] RBRACE { $$ = { NAF::NOTNOT, $elems }; } + ; + +///}}} +// {{{2 conjunctions + +conjunction + : literal[lit] COLON litvec[cond] { $$ = { $lit, $cond }; } + ; + +// }}} +// {{{2 disjunctions + +dsym + : SEM + | VBAR + ; + +disjunctionsep + : disjunctionsep[vec] literal[lit] COMMA { $$ = BUILDER.condlitvec($vec, $lit, BUILDER.litvec()); } + | disjunctionsep[vec] literal[lit] noptcondition[cond] dsym { $$ = BUILDER.condlitvec($vec, $lit, $cond); } + | { $$ = BUILDER.condlitvec(); } + ; + +// Note: for simplicity appending first condlit here +disjunction + : literal[lit] COMMA disjunctionsep[vec] literal[clit] noptcondition[ccond] { $$ = BUILDER.condlitvec(BUILDER.condlitvec($vec, $clit, $ccond), $lit, BUILDER.litvec()); } + | literal[lit] dsym disjunctionsep[vec] literal[clit] noptcondition[ccond] { $$ = BUILDER.condlitvec(BUILDER.condlitvec($vec, $clit, $ccond), $lit, BUILDER.litvec()); } + | literal[lit] COLON nlitvec[cond] dsym disjunctionsep[vec] literal[clit] noptcondition[ccond] { $$ = BUILDER.condlitvec(BUILDER.condlitvec($vec, $clit, $ccond), $lit, $cond); } + | literal[clit] COLON nlitvec[ccond] { $$ = BUILDER.condlitvec(BUILDER.condlitvec(), $clit, $ccond); } + ; + +// {{{1 statements +// {{{2 rules + +bodycomma + : bodycomma[body] literal[lit] COMMA { $$ = BUILDER.bodylit($body, $lit); } + | bodycomma[body] literal[lit] SEM { $$ = BUILDER.bodylit($body, $lit); } + | bodycomma[body] lubodyaggregate[aggr] COMMA { $$ = lexer->bodyaggregate($body, @aggr, NAF::POS, $aggr); } + | bodycomma[body] lubodyaggregate[aggr] SEM { $$ = lexer->bodyaggregate($body, @aggr, NAF::POS, $aggr); } + | bodycomma[body] NOT[l] lubodyaggregate[aggr] COMMA { $$ = lexer->bodyaggregate($body, @aggr + @l, NAF::NOT, $aggr); } + | bodycomma[body] NOT[l] lubodyaggregate[aggr] SEM { $$ = lexer->bodyaggregate($body, @aggr + @l, NAF::NOT, $aggr); } + | bodycomma[body] NOT[l] NOT lubodyaggregate[aggr] COMMA { $$ = lexer->bodyaggregate($body, @aggr + @l, NAF::NOTNOT, $aggr); } + | bodycomma[body] NOT[l] NOT lubodyaggregate[aggr] SEM { $$ = lexer->bodyaggregate($body, @aggr + @l, NAF::NOTNOT, $aggr); } + | bodycomma[body] conjunction[conj] SEM { $$ = BUILDER.conjunction($body, @conj, $conj.first, $conj.second); } + | bodycomma[body] disjoint[cons] SEM { $$ = BUILDER.disjoint($body, @cons, $cons.first, $cons.second); } + | { $$ = BUILDER.body(); } + ; + +bodydot + : bodycomma[body] literal[lit] DOT { $$ = BUILDER.bodylit($body, $lit); } + | bodycomma[body] lubodyaggregate[aggr] DOT { $$ = lexer->bodyaggregate($body, @aggr, NAF::POS, $aggr); } + | bodycomma[body] NOT[l] lubodyaggregate[aggr] DOT { $$ = lexer->bodyaggregate($body, @aggr + @l, NAF::NOT, $aggr); } + | bodycomma[body] NOT[l] NOT lubodyaggregate[aggr] DOT { $$ = lexer->bodyaggregate($body, @aggr + @l, NAF::NOTNOT, $aggr); } + | bodycomma[body] conjunction[conj] DOT { $$ = BUILDER.conjunction($body, @conj, $conj.first, $conj.second); } + | bodycomma[body] disjoint[cons] DOT { $$ = BUILDER.disjoint($body, @cons, $cons.first, $cons.second); } + ; + +bodyconddot + : DOT { $$ = BUILDER.body(); } + | COLON DOT { $$ = BUILDER.body(); } + | COLON bodydot[body] { $$ = $body; } + +head + : literal[lit] { $$ = BUILDER.headlit($lit); } + | disjunction[elems] { $$ = BUILDER.disjunction(@$, $elems); } + | luheadaggregate[aggr] { $$ = lexer->headaggregate(@$, $aggr); } + ; + +statement + : head[hd] DOT { BUILDER.rule(@$, $hd); } + | head[hd] IF DOT { BUILDER.rule(@$, $hd); } + | head[hd] IF bodydot[bd] { BUILDER.rule(@$, $hd, $bd); } + | IF bodydot[bd] { BUILDER.rule(@$, BUILDER.headlit(BUILDER.boollit(@$, false)), $bd); } + | IF DOT { BUILDER.rule(@$, BUILDER.headlit(BUILDER.boollit(@$, false)), BUILDER.body()); } + ; + +// {{{2 CSP + +statement + : disjoint[hd] IF bodydot[body] { BUILDER.rule(@$, BUILDER.headlit(BUILDER.boollit(@hd, false)), BUILDER.disjoint($body, @hd, inv($hd.first), $hd.second)); } + | disjoint[hd] IF DOT { BUILDER.rule(@$, BUILDER.headlit(BUILDER.boollit(@hd, false)), BUILDER.disjoint(BUILDER.body(), @hd, inv($hd.first), $hd.second)); } + | disjoint[hd] DOT { BUILDER.rule(@$, BUILDER.headlit(BUILDER.boollit(@hd, false)), BUILDER.disjoint(BUILDER.body(), @hd, inv($hd.first), $hd.second)); } + ; + +// {{{2 optimization + +optimizetuple + : COMMA ntermvec[vec] { $$ = $vec; } + | { $$ = BUILDER.termvec(); } + ; + +optimizeweight + : term[w] AT term[p] { $$ = {$w, $p}; } + | term[w] { $$ = {$w, BUILDER.term(@$, Symbol::createNum(0))}; } + ; + +optimizelitvec + : literal[lit] { $$ = BUILDER.bodylit(BUILDER.body(), $lit); } + | optimizelitvec[bd] COMMA literal[lit] { $$ = BUILDER.bodylit($bd, $lit); } + ; + +optimizecond + : COLON optimizelitvec[bd] { $$ = $bd; } + | COLON { $$ = BUILDER.body(); } + | { $$ = BUILDER.body(); } + ; + +statement + : WIF bodydot[bd] LBRACK optimizeweight[w] optimizetuple[t] RBRACK { BUILDER.optimize(@$, $w.first, $w.second, $t, $bd); } + | WIF DOT LBRACK optimizeweight[w] optimizetuple[t] RBRACK { BUILDER.optimize(@$, $w.first, $w.second, $t, BUILDER.body()); } + ; + +maxelemlist + : optimizeweight[w] optimizetuple[t] optimizecond[bd] { BUILDER.optimize(@$, BUILDER.term(@w, UnOp::NEG, $w.first), $w.second, $t, $bd); } + | maxelemlist SEM optimizeweight[w] optimizetuple[t] optimizecond[bd] { BUILDER.optimize(@$, BUILDER.term(@w, UnOp::NEG, $w.first), $w.second, $t, $bd); } + ; + +minelemlist + : optimizeweight[w] optimizetuple[t] optimizecond[bd] { BUILDER.optimize(@$, $w.first, $w.second, $t, $bd); } + | minelemlist SEM optimizeweight[w] optimizetuple[t] optimizecond[bd] { BUILDER.optimize(@$, $w.first, $w.second, $t, $bd); } + ; + +statement + : MINIMIZE LBRACE RBRACE DOT + | MAXIMIZE LBRACE RBRACE DOT + | MINIMIZE LBRACE minelemlist RBRACE DOT + | MAXIMIZE LBRACE maxelemlist RBRACE DOT + ; + +// {{{2 visibility + +statement + : SHOWSIG identifier[id] SLASH NUMBER[num] DOT { BUILDER.showsig(@$, Sig(String::fromRep($id), $num, false), false); } + | SHOWSIG SUB identifier[id] SLASH NUMBER[num] DOT { BUILDER.showsig(@$, Sig(String::fromRep($id), $num, true), false); } + | SHOW DOT { BUILDER.showsig(@$, Sig("", 0, false), false); } + | SHOW term[t] COLON bodydot[bd] { BUILDER.show(@$, $t, $bd, false); } + | SHOW term[t] DOT { BUILDER.show(@$, $t, BUILDER.body(), false); } + | SHOWSIG CSP identifier[id] SLASH NUMBER[num] DOT { BUILDER.showsig(@$, Sig(String::fromRep($id), $num, false), true); } + | SHOW CSP term[t] COLON bodydot[bd] { BUILDER.show(@$, $t, $bd, true); } + | SHOW CSP term[t] DOT { BUILDER.show(@$, $t, BUILDER.body(), true); } + ; + +// {{{2 acyclicity + +statement + : EDGE LPAREN binaryargvec[args] RPAREN bodyconddot[body] { BUILDER.edge(@$, $args, $body); } + ; + +// {{{2 heuristic + +statement + : HEURISTIC atom[a] bodyconddot[body] LBRACK term[t] AT term[p] COMMA term[mod] RBRACK { BUILDER.heuristic(@$, $a, $body, $t, $p, $mod); } + | HEURISTIC atom[a] bodyconddot[body] LBRACK term[t] COMMA term[mod] RBRACK { BUILDER.heuristic(@$, $a, $body, $t, BUILDER.term(@$, Symbol::createNum(0)), $mod); } + ; + +// {{{2 project + +statement + : PROJECT identifier[name] SLASH NUMBER[arity] DOT { BUILDER.project(@$, Sig(String::fromRep($name), $arity, false)); } + | PROJECT SUB identifier[name] SLASH NUMBER[arity] DOT { BUILDER.project(@$, Sig(String::fromRep($name), $arity, true)); } + | PROJECT atom[a] bodyconddot[body] { BUILDER.project(@$, $a, $body); } + ; + +// {{{2 constants + +define + : identifier[uid] EQ constterm[rhs] { BUILDER.define(@$, String::fromRep($uid), $rhs, false, LOGGER); } + ; + +statement + : CONST identifier[uid] EQ constterm[rhs] DOT { BUILDER.define(@$, String::fromRep($uid), $rhs, true, LOGGER); } + ; + +// {{{2 scripts + +statement + : PYTHON[code] DOT { BUILDER.python(@$, String::fromRep($code)); } + | LUA[code] DOT { BUILDER.lua(@$, String::fromRep($code)); } + ; + +// {{{2 include + +statement + : INCLUDE STRING[file] DOT { lexer->include(String::fromRep($file), @$, false, LOGGER); } + | INCLUDE LT identifier[file] GT DOT { lexer->include(String::fromRep($file), @$, true, LOGGER); } + ; + +// {{{2 blocks + +nidlist + : nidlist[list] COMMA identifier[id] { $$ = BUILDER.idvec($list, @id, String::fromRep($id)); } + | identifier[id] { $$ = BUILDER.idvec(BUILDER.idvec(), @id, String::fromRep($id)); } + ; + +idlist + : { $$ = BUILDER.idvec(); } + | nidlist[list] { $$ = $list; } + ; + +statement + : BLOCK identifier[name] LPAREN idlist[args] RPAREN DOT { BUILDER.block(@$, String::fromRep($name), $args); } + | BLOCK identifier[name] DOT { BUILDER.block(@$, String::fromRep($name), BUILDER.idvec()); } + ; + +// {{{2 external + +statement + : EXTERNAL atom[hd] COLON bodydot[bd] { BUILDER.external(@$, $hd, $bd); } + | EXTERNAL atom[hd] COLON DOT { BUILDER.external(@$, $hd, BUILDER.body()); } + | EXTERNAL atom[hd] DOT { BUILDER.external(@$, $hd, BUILDER.body()); } + ; + +// {{{1 theory + +// {{{2 theory atoms + +theory_op_list + : theory_op_list[ops] THEORY_OP[op] { $$ = BUILDER.theoryops($ops, String::fromRep($op)); } + | THEORY_OP[op] { $$ = BUILDER.theoryops(BUILDER.theoryops(), String::fromRep($op)); } + ; + +theory_term + : LBRACE theory_opterm_list[list] RBRACE { $$ = BUILDER.theorytermset(@$, $list); } + | LBRACK theory_opterm_list[list] RBRACK { $$ = BUILDER.theoryoptermlist(@$, $list); } + | LPAREN RPAREN { $$ = BUILDER.theorytermtuple(@$, BUILDER.theoryopterms()); } + | LPAREN theory_opterm[term] RPAREN { $$ = BUILDER.theorytermopterm(@$, $term); } + | LPAREN theory_opterm[opterm] COMMA RPAREN { $$ = BUILDER.theorytermtuple(@$, BUILDER.theoryopterms(BUILDER.theoryopterms(), @opterm, $opterm)); } + | LPAREN theory_opterm[opterm] COMMA theory_opterm_nlist[list] RPAREN { $$ = BUILDER.theorytermtuple(@$, BUILDER.theoryopterms(@opterm, $opterm, $list)); } + | identifier[id] LPAREN theory_opterm_list[list] RPAREN { $$ = BUILDER.theorytermfun(@$, String::fromRep($id), $list); } + | identifier[id] { $$ = BUILDER.theorytermvalue(@$, Symbol::createId(String::fromRep($id))); } + | NUMBER[num] { $$ = BUILDER.theorytermvalue(@$, Symbol::createNum($num)); } + | STRING[str] { $$ = BUILDER.theorytermvalue(@$, Symbol::createStr(String::fromRep($str))); } + | INFIMUM { $$ = BUILDER.theorytermvalue(@$, Symbol::createInf()); } + | SUPREMUM { $$ = BUILDER.theorytermvalue(@$, Symbol::createSup()); } + | VARIABLE[var] { $$ = BUILDER.theorytermvar(@$, String::fromRep($var)); } + ; + +theory_opterm + : theory_opterm[opterm] theory_op_list[ops] theory_term[term] { $$ = BUILDER.theoryopterm($opterm, $ops, $term); } + | theory_op_list[ops] theory_term[term] { $$ = BUILDER.theoryopterm($ops, $term); } + | theory_term[term] { $$ = BUILDER.theoryopterm(BUILDER.theoryops(), $term); } + ; + +theory_opterm_nlist + : theory_opterm_nlist[list] COMMA theory_opterm[opterm] { $$ = BUILDER.theoryopterms($list, @opterm, $opterm); } + | theory_opterm[opterm] { $$ = BUILDER.theoryopterms(BUILDER.theoryopterms(), @opterm, $opterm); } + ; + +theory_opterm_list + : theory_opterm_nlist[list] { $$ = $list; } + | { $$ = BUILDER.theoryopterms(); } + ; + +theory_atom_element + : theory_opterm_nlist[list] disable_theory_lexing optcondition[cond] { $$ = { $list, $cond }; } + | disable_theory_lexing COLON litvec[cond] { $$ = { BUILDER.theoryopterms(), $cond }; } + ; + +theory_atom_element_nlist + : theory_atom_element_nlist[list] enable_theory_lexing SEM theory_atom_element[elem] { $$ = BUILDER.theoryelems($list, $elem.first, $elem.second); } + | theory_atom_element[elem] { $$ = BUILDER.theoryelems(BUILDER.theoryelems(), $elem.first, $elem.second); } + ; + +theory_atom_element_list + : theory_atom_element_nlist[list] { $$ = $list; } + | { $$ = BUILDER.theoryelems(); } + ; + +theory_atom_name + : identifier[id] { $$ = BUILDER.term(@$, String::fromRep($id), BUILDER.termvecvec(BUILDER.termvecvec(), BUILDER.termvec()), false); } + | identifier[id] LPAREN argvec[tvv] RPAREN[r] { $$ = BUILDER.term(@$, String::fromRep($id), $tvv, false); } + +theory_atom + : AND theory_atom_name[name] enable_theory_lexing LBRACE theory_atom_element_list[elems] enable_theory_lexing RBRACE disable_theory_lexing { $$ = BUILDER.theoryatom($name, $elems); } + | AND theory_atom_name[name] enable_theory_lexing LBRACE theory_atom_element_list[elems] enable_theory_lexing RBRACE THEORY_OP[op] theory_opterm[opterm] disable_theory_lexing { $$ = BUILDER.theoryatom($name, $elems, String::fromRep($op), @opterm, $opterm); } + ; + +// {{{2 theory definition + +theory_operator_nlist + : THEORY_OP[op] { $$ = BUILDER.theoryops(BUILDER.theoryops(), String::fromRep($op)); } + | theory_operator_nlist[ops] COMMA THEORY_OP[op] { $$ = BUILDER.theoryops($ops, String::fromRep($op)); } + ; + +theory_operator_list + : theory_operator_nlist[ops] { $$ = $ops; } + | { $$ = BUILDER.theoryops(); } + ; + +theory_operator_definition + : THEORY_OP[op] enable_theory_definition_lexing COLON NUMBER[arity] COMMA UNARY { $$ = BUILDER.theoryopdef(@$, String::fromRep($op), $arity, TheoryOperatorType::Unary); } + | THEORY_OP[op] enable_theory_definition_lexing COLON NUMBER[arity] COMMA BINARY COMMA LEFT { $$ = BUILDER.theoryopdef(@$, String::fromRep($op), $arity, TheoryOperatorType::BinaryLeft); } + | THEORY_OP[op] enable_theory_definition_lexing COLON NUMBER[arity] COMMA BINARY COMMA RIGHT { $$ = BUILDER.theoryopdef(@$, String::fromRep($op), $arity, TheoryOperatorType::BinaryRight); } + ; + +theory_operator_definition_nlist + : theory_operator_definition[def] { $$ = BUILDER.theoryopdefs(BUILDER.theoryopdefs(), $def); } + | theory_operator_definition_nlist[defs] enable_theory_lexing SEM theory_operator_definition[def] { $$ = BUILDER.theoryopdefs($defs, $def); } + ; + +theory_operator_definiton_list + : theory_operator_definition_nlist[defs] { $$ = $defs; } + | { $$ = BUILDER.theoryopdefs(); } + ; + +theory_definition_identifier + : identifier[id] { $$ = $id; } + | LEFT { $$ = String::toRep("left"); } + | RIGHT { $$ = String::toRep("right"); } + | UNARY { $$ = String::toRep("unary"); } + | BINARY { $$ = String::toRep("binary"); } + | HEAD { $$ = String::toRep("head"); } + | BODY { $$ = String::toRep("body"); } + | ANY { $$ = String::toRep("any"); } + | DIRECTIVE { $$ = String::toRep("directive"); } + ; + +theory_term_definition + : theory_definition_identifier[name] enable_theory_lexing LBRACE theory_operator_definiton_list[ops] enable_theory_definition_lexing RBRACE { $$ = BUILDER.theorytermdef(@$, String::fromRep($name), $ops, LOGGER); } + ; + +theory_atom_type + : HEAD { $$ = TheoryAtomType::Head; } + | BODY { $$ = TheoryAtomType::Body; } + | ANY { $$ = TheoryAtomType::Any; } + | DIRECTIVE { $$ = TheoryAtomType::Directive; } + ; + +theory_atom_definition + : AND theory_definition_identifier[name] SLASH NUMBER[arity] COLON theory_definition_identifier[termdef] COMMA + enable_theory_lexing LBRACE theory_operator_list[ops] enable_theory_definition_lexing RBRACE COMMA theory_definition_identifier[guarddef] COMMA theory_atom_type[type] { $$ = BUILDER.theoryatomdef(@$, String::fromRep($name), $arity, String::fromRep($termdef), $type, $ops, String::fromRep($guarddef)); } + | AND theory_definition_identifier[name] SLASH NUMBER[arity] COLON theory_definition_identifier[termdef] COMMA theory_atom_type[type] { $$ = BUILDER.theoryatomdef(@$, String::fromRep($name), $arity, String::fromRep($termdef), $type); } + ; + +theory_definition_nlist + : theory_definition_list[defs] SEM theory_atom_definition[def] { $$ = BUILDER.theorydefs($defs, $def); } + | theory_definition_list[defs] SEM theory_term_definition[def] { $$ = BUILDER.theorydefs($defs, $def); } + | theory_atom_definition[def] { $$ = BUILDER.theorydefs(BUILDER.theorydefs(), $def); } + | theory_term_definition[def] { $$ = BUILDER.theorydefs(BUILDER.theorydefs(), $def); } + ; + +theory_definition_list + : theory_definition_nlist[defs] { $$ = $defs; } + | { $$ = BUILDER.theorydefs(); } + ; + +statement + : THEORY identifier[name] enable_theory_definition_lexing LBRACE theory_definition_list[defs] RBRACE disable_theory_lexing DOT { BUILDER.theorydef(@$, String::fromRep($name), $defs, LOGGER); } + ; + +// {{{2 lexing + +enable_theory_lexing + : { lexer->theoryLexing(TheoryLexing::Theory); } + ; + +enable_theory_definition_lexing + : { lexer->theoryLexing(TheoryLexing::Definition); } + ; + +disable_theory_lexing + : { lexer->theoryLexing(TheoryLexing::Disabled); } + ; + +// }}}1 diff --git a/libgringo/src/input/nongroundlexer.xch b/libgringo/src/input/nongroundlexer.xch new file mode 100644 index 0000000..b79525e --- /dev/null +++ b/libgringo/src/input/nongroundlexer.xch @@ -0,0 +1,219 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#define YYCTYPE char +#define YYCURSOR cursor() +#define YYLIMIT limit() +#define YYMARKER marker() +#define YYFILL(n) {fill(n);} +#define YYCTXMARKER ctxmarker() +#define YYGETCONDITION condition +#define YYSETCONDITION condition + +// Note: THEORYOP is also used in output/backends.cc +/*!re2c + re2c:cond:goto = "continue;"; + + NUMBER = "0"|([1-9][0-9]*); + ANY = [\000-\377]; + WS = [\t\r ]*; + NL = "\n"; + IDENTIFIER = "_"*[a-z]['A-Za-z0-9_]*; + VARIABLE = "_"*[A-Z]['A-Za-z0-9_]*; + ANONYMOUS = "_"; + STRING = "\"" ([^\\"\n]|"\\\""|"\\\\"|"\\n")* "\""; + WSNL = [\t\r\n ]*; + SIG = WSNL ([-$])? WSNL IDENTIFIER WSNL "/" WSNL NUMBER WSNL "."; + PYTHON = "#script" WS* "(" WS* "python" WS* ")"; + LUA = "#script" WS* "(" WS* "lua" WS* ")"; + THEORYOP = [/!<=>+\-*\\?&@|:;~\^\.]+; + SUP = "#sup"("remum")?; + INF = "#inf"("imum")?; + KEYWORD = "#" [a-zA-Z0-9_]*; +*/ + +int Gringo::Input::NonGroundParser::lex_impl(void *pValue, Location &loc) { + int bc = 0; + auto &value = *static_cast(pValue); + start(loc); + for (;;) { + /*!re2c + WS { start(loc); continue; } + NL { if(eof()) return 0; step(); start(loc); continue; } + INF { return NonGroundGrammar::parser::token::INFIMUM; } + SUP { return NonGroundGrammar::parser::token::SUPREMUM; } + PYTHON :=> python + LUA :=> lua + "#include" { return NonGroundGrammar::parser::token::INCLUDE; } + "#edge" { return NonGroundGrammar::parser::token::EDGE; } + "#heuristic" { return NonGroundGrammar::parser::token::HEURISTIC; } + "#project" { return NonGroundGrammar::parser::token::PROJECT; } + "#show" { return NonGroundGrammar::parser::token::SHOW; } + "#show"/SIG { return NonGroundGrammar::parser::token::SHOWSIG; } + "#const" { return NonGroundGrammar::parser::token::CONST; } + "#minimi"[zs]"e" { return NonGroundGrammar::parser::token::MINIMIZE; } + "#maximi"[zs]"e" { return NonGroundGrammar::parser::token::MAXIMIZE; } + "#program" { return NonGroundGrammar::parser::token::BLOCK; } + "#external" { return NonGroundGrammar::parser::token::EXTERNAL; } + "left" { return NonGroundGrammar::parser::token::LEFT; } + "right" { return NonGroundGrammar::parser::token::RIGHT; } + "head" { return NonGroundGrammar::parser::token::HEAD; } + "body" { return NonGroundGrammar::parser::token::BODY; } + "any" { return NonGroundGrammar::parser::token::ANY; } + "binary" { return NonGroundGrammar::parser::token::BINARY; } + "unary" { return NonGroundGrammar::parser::token::UNARY; } + "directive" { return NonGroundGrammar::parser::token::DIRECTIVE; } + + "not" { value.str = String::toRep(not_); return NonGroundGrammar::parser::token::NOT; } + ANONYMOUS { return NonGroundGrammar::parser::token::ANONYMOUS; } + IDENTIFIER { value.str = String::toRep(string()); return NonGroundGrammar::parser::token::IDENTIFIER; } + NUMBER { value.num = integer(); return NonGroundGrammar::parser::token::NUMBER; } + VARIABLE { value.str = String::toRep(string()); return NonGroundGrammar::parser::token::VARIABLE; } + STRING { value.str = String::toRep(unquote(string(1, 1)).c_str()); return NonGroundGrammar::parser::token::STRING; } + + "#true" { return NonGroundGrammar::parser::token::TRUE; } + "#false" { return NonGroundGrammar::parser::token::FALSE; } + "#sum" { return NonGroundGrammar::parser::token::SUM; } + "#sum+" { return NonGroundGrammar::parser::token::SUMP; } + "#count" { return NonGroundGrammar::parser::token::COUNT; } + "#min" { return NonGroundGrammar::parser::token::MIN; } + "#max" { return NonGroundGrammar::parser::token::MAX; } + "#disjoint" { return NonGroundGrammar::parser::token::DISJOINT; } + "#theory" { return NonGroundGrammar::parser::token::THEORY; } + ";" { return NonGroundGrammar::parser::token::SEM; } + ".." { return NonGroundGrammar::parser::token::DOTS; } + "." { return NonGroundGrammar::parser::token::DOT; } + ":" { return NonGroundGrammar::parser::token::COLON; } + ":-" { return NonGroundGrammar::parser::token::IF; } + ":~" { return NonGroundGrammar::parser::token::WIF; } + "," { return NonGroundGrammar::parser::token::COMMA; } + "|" { return NonGroundGrammar::parser::token::VBAR; } + "[" { return NonGroundGrammar::parser::token::LBRACK; } + "]" { return NonGroundGrammar::parser::token::RBRACK; } + "(" { return NonGroundGrammar::parser::token::LPAREN; } + ")" { return NonGroundGrammar::parser::token::RPAREN; } + "{" { return NonGroundGrammar::parser::token::LBRACE; } + "}" { return NonGroundGrammar::parser::token::RBRACE; } + "+" { return NonGroundGrammar::parser::token::ADD; } + "-" { return NonGroundGrammar::parser::token::SUB; } + "**" { return NonGroundGrammar::parser::token::POW; } + "\\" { return NonGroundGrammar::parser::token::MOD; } + "*" { return NonGroundGrammar::parser::token::MUL; } + ">" { return NonGroundGrammar::parser::token::GT; } + "<" { return NonGroundGrammar::parser::token::LT; } + ">=" { return NonGroundGrammar::parser::token::GEQ; } + "<=" { return NonGroundGrammar::parser::token::LEQ; } + "==" { return NonGroundGrammar::parser::token::EQ; } + "!=" { return NonGroundGrammar::parser::token::NEQ; } + "<>" { return NonGroundGrammar::parser::token::NEQ; } + "=" { return NonGroundGrammar::parser::token::EQ; } + "/" { return NonGroundGrammar::parser::token::SLASH; } + "@" { return NonGroundGrammar::parser::token::AT; } + "&" { return NonGroundGrammar::parser::token::AND; } + "^" { return NonGroundGrammar::parser::token::XOR; } + "~" { return NonGroundGrammar::parser::token::BNOT; } + "?" { return NonGroundGrammar::parser::token::QUESTION; } + "$" { return NonGroundGrammar::parser::token::CSP; } + "$+" { return NonGroundGrammar::parser::token::CSP_ADD; } + "$-" { return NonGroundGrammar::parser::token::CSP_SUB; } + "$*" { return NonGroundGrammar::parser::token::CSP_MUL; } + "$<=" { return NonGroundGrammar::parser::token::CSP_LEQ; } + "$<" { return NonGroundGrammar::parser::token::CSP_LT; } + "$>=" { return NonGroundGrammar::parser::token::CSP_GEQ; } + "$>" { return NonGroundGrammar::parser::token::CSP_GT; } + "$==" { return NonGroundGrammar::parser::token::CSP_EQ; } + "$=" { return NonGroundGrammar::parser::token::CSP_EQ; } + "$!=" { return NonGroundGrammar::parser::token::CSP_NEQ; } + "$<>" { return NonGroundGrammar::parser::token::CSP_NEQ; } + THEORYOP { value.str = String::toRep(string()); return NonGroundGrammar::parser::token::THEORY_OP; } + "%*" => blockcomment { bc++; continue; } + "%" :=> comment + "#!" :=> comment + KEYWORD { lexerError(string()); continue; } + ANY { lexerError(string()); continue; } + + "#end" => normal { + auto span = string(); + std::string s(span.first, span.first + span.size); + s.push_back('\n'); + value.str = String::toRep(s.c_str()); + return NonGroundGrammar::parser::token::PYTHON; + } + NL { + if(eof()) { + lexerError(Potassco::toSpan("", 5)); + return 0; + } + step(); + continue; + } + ANY { continue; } + + "#end" => normal { + auto span = string(0,4); + std::string s(span.first, span.first + span.size); + s.erase(0, s.find(')') + 1); + value.str = String::toRep(s.c_str()); + return NonGroundGrammar::parser::token::LUA; + } + NL { + if(eof()) { + lexerError(Potassco::toSpan("", 5)); + return 0; + } + step(); + continue; + } + ANY { continue; } + + "*%" { if(--bc == 0) { condition(yycnormal); start(loc); } continue; } + "%*" { bc++; continue; } + "%" :=> comment + NL { if(eof()) { lexerError(Potassco::toSpan("", 5)); return 0; } step(); continue; } + ANY { continue; } + + NL { + if(eof()) { + if(bc > 0) { lexerError(Potassco::toSpan("", 5)); } + return 0; + } + step(); + if (bc > 0) { condition(yycblockcomment); } + else { + condition(yycnormal); + start(loc); + } + continue; + } + ANY { continue; } + */ + } + assert(false); + return 0; +} + +#undef YYCTYPE +#undef YYCURSOR +#undef YYLIMIT +#undef YYMARKER +#undef YYFILL +#undef YYCTXMARKER +#undef YYGETCONDITION +#undef YYSETCONDITION diff --git a/libgringo/src/input/nongroundparser.cc b/libgringo/src/input/nongroundparser.cc new file mode 100644 index 0000000..71ab4cb --- /dev/null +++ b/libgringo/src/input/nongroundparser.cc @@ -0,0 +1,391 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#ifdef __USE_GNU +# include +# include +# include +#endif +#include "gringo/input/nongroundparser.hh" +#include "gringo/lexerstate.hh" +#include "gringo/symbol.hh" +#include "gringo/logger.hh" +#include "input/nongroundgrammar/grammar.hh" +#include +#include +#include +#include +#include +#include + + +namespace Gringo { namespace Input { + +namespace { + +struct Free { + void operator ()(char *ptr) { free(ptr); } +}; + +template +void report_included(T const &loc, char const *filename, Logger &log) { + GRINGO_REPORT(log, clingo_warning_file_included) << loc << ": warning: already included file:\n" + << " " << filename << "\n"; +} + +template +void report_not_found(T const &loc, char const *filename, Logger &log) { + GRINGO_REPORT(log, clingo_error_runtime) << loc << ": error: file could not be opened:\n" + << " " << filename << "\n"; +} + +// NOTE: is there a better way? +#ifdef __USE_GNU + +std::string check_file(std::string const &filename) { + if (filename == "-") { return filename; } + struct stat sb; + if (stat(filename.c_str(), &sb) != -1) { + if ((sb.st_mode & S_IFMT) == S_IFIFO) { + return filename; + } + else { + std::unique_ptr x(canonicalize_file_name(filename.c_str())); + if (x) { return x.get(); } + } + } + return ""; +} + +std::pair check_file(std::string const &filename, std::string const &source) { + struct stat sb; + if (stat(filename.c_str(), &sb) != -1) { + if ((sb.st_mode & S_IFMT) == S_IFIFO) { + return {filename, filename}; + } + else { + std::unique_ptr x(canonicalize_file_name(filename.c_str())); + if (x) { return {x.get(), filename}; } + } + } + else if (filename.compare(0, 1, "/", 1) != 0) { + std::unique_ptr x(strdup(source.c_str())); + std::string path = dirname(x.get()); + path.push_back('/'); + path.append(filename); + if (stat(path.c_str(), &sb) != -1) { + if ((sb.st_mode & S_IFMT) == S_IFIFO) { + return {path, path}; + } + else { + x.reset(canonicalize_file_name(path.c_str())); + if (x) { return {x.get(), path}; } + } + } + } + return {"", ""}; +} + +#else + +std::string check_file(std::string const &filename) { + if (filename == "-" && std::cin.good()) { + return filename; + } + if (std::ifstream(filename).good()) { + return filename; + } + return ""; +} + +std::pair check_file(std::string const &filename, std::string const &source) { + if (std::ifstream(filename).good()) { + return {filename, filename}; + } + else { +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + const char *SLASH = "/\\"; +#else + const char *SLASH = "/"; +#endif + size_t slash = source.find_last_of(SLASH); + if (slash != std::string::npos) { + std::string path = source.substr(0, slash + 1); + path.append(filename); + if (std::ifstream(path).good()) { + return {path, path}; + } + } + } + return {"", ""}; +} + +#endif + +} + +// {{{ defintion of NonGroundParser + +NonGroundParser::NonGroundParser(INongroundProgramBuilder &pb) + : not_("not") + , pb_(pb) + , _startSymbol(0) + , _filename("") { } + +void NonGroundParser::parseError(Location const &loc, std::string const &msg) { + GRINGO_REPORT(*log_, clingo_error_runtime) << loc << ": error: " << msg << "\n"; +} + +void NonGroundParser::lexerError(StringSpan token) { + GRINGO_REPORT(*log_, clingo_error_runtime) << filename() << ":" << line() << ":" << column() << ": error: lexer error, unexpected " << std::string(token.first, token.first + token.size) << "\n"; +} + +bool NonGroundParser::push(std::string const &filename, bool include) { + return (include && !empty()) ? + LexerState::push(filename.c_str(), {filename.c_str(), LexerState::data().second}) : + LexerState::push(filename.c_str(), {filename.c_str(), {"base", {}}}); +} + +bool NonGroundParser::push(std::string const &filename, std::unique_ptr in) { + return LexerState::push(std::move(in), {filename.c_str(), {"base", {}}}); +} + +void NonGroundParser::pop() { LexerState::pop(); } + +String NonGroundParser::filename() const { return LexerState::data().first; } + +void NonGroundParser::pushFile(std::string &&file, Logger &log) { + auto checked = check_file(file); + if (!checked.empty() && !filenames_.insert(checked).second) { + report_included("", file.c_str(), log); + } + else if (checked.empty() || !push(file)) { + report_not_found("", file.c_str(), log); + } +} + +void NonGroundParser::pushStream(std::string &&file, std::unique_ptr in, Logger &log) { + auto res = filenames_.insert(std::move(file)); + if (!res.second) { + report_included("", res.first->c_str(), log); + } + else if (!push(*res.first, std::move(in))) { + report_not_found("", res.first->c_str(), log); + } +} + +void NonGroundParser::pushBlock(std::string const &name, IdVec const &vec, std::string const &block, Logger &) { + LexerState::push(gringo_make_unique(block), {"", {name.c_str(), vec}}); +} + +void NonGroundParser::_init() { + if (!empty()) { + Location loc(filename(), 1, 1, filename(), 1, 1); + IdVecUid params = pb_.idvec(); + for (auto &x : data().second.second) { params = pb_.idvec(params, x.first, x.second); } + pb_.block(loc, data().second.first, params); + } +} + +int NonGroundParser::lex(void *pValue, Location &loc) { + if (_startSymbol) { + auto ret = _startSymbol; + _startSymbol = 0; + return ret; + } + while (!empty()) { + int minor = lex_impl(pValue, loc); + loc.endFilename = filename(); + loc.endLine = line(); + loc.endColumn = column(); + if (minor) { return minor; } + else { + pop(); + _init(); + } + } + return 0; +} + +void NonGroundParser::include(String file, Location const &loc, bool inbuilt, Logger &log) { + if (inbuilt) { + if (file == "incmode") { + if (incmodeIncluded_) { + report_included(loc, "", log); + } + else { + push("", gringo_make_unique(R"( +#script (lua) + +function get(val, default) + if val ~= nil then + return val + else + return default + end +end + +function main(prg) + local imin = get(prg:get_const("imin"), clingo.Number(0)) + local imax = prg:get_const("imax") + local istop = get(prg:get_const("istop"), clingo.String("SAT")) + + local step, ret = 0, None + while (imax == nil or step < imax.number) and + (step == 0 or step < imin.number or ( + (istop.string == "SAT" and not ret.satisfiable) or + (istop.string == "UNSAT" and not ret.unsatisfiable) or + (istop.string == "UNKNOWN" and not ret.unknown))) do + local parts = {} + table.insert(parts, {"check", {step}}) + if step > 0 then + prg:release_external(clingo.Function("query", {step-1})) + prg:cleanup() + table.insert(parts, {"step", {step}}) + else + table.insert(parts, {"base", {}}) + end + prg:ground(parts) + prg:assign_external(clingo.Function("query", {step}), true) + ret, step = prg:solve(), step+1 + end +end + +#end. + +#program check(t). +#external query(t). +)")); + incmodeIncluded_ = true; + } + } + else { + report_not_found(loc, (std::string("<") + file.c_str() + ">").c_str(), log); + } + } + else { + auto paths = check_file(file.c_str(), loc.beginFilename.c_str()); + if (!paths.first.empty() && !filenames_.insert(paths.first).second) { + report_included(loc, file.c_str(), log); + } + else if (paths.first.empty() || !push(paths.second, true)) { + report_not_found(loc, file.c_str(), log); + } + } +} + +bool NonGroundParser::parseDefine(std::string const &define, Logger &log) { + log_ = &log; + pushStream("<" + define + ">", gringo_make_unique(define), log); + _startSymbol = NonGroundGrammar::parser::token::PARSE_DEF; + NonGroundGrammar::parser parser(this); + auto ret = parser.parse(); + filenames_.clear(); + return ret == 0; +} + +void NonGroundParser::theoryLexing(TheoryLexing mode) { + theoryLexing_ = mode; +} + +void NonGroundParser::condition(Condition cond) { + assert(condition_ != yyctheory); + condition_ = cond; +} + +NonGroundParser::Condition NonGroundParser::condition() const { + if (condition_ == yycnormal) { + switch (theoryLexing_) { + case TheoryLexing::Disabled: { return yycnormal; } + case TheoryLexing::Theory: { return yyctheory; } + case TheoryLexing::Definition: { return yycdefinition; } + } + } + return condition_; +} + +void NonGroundParser::start(Location &loc) { + start(); + loc.beginFilename = filename(); + loc.beginLine = line(); + loc.beginColumn = column(); +} + +bool NonGroundParser::parse(Logger &log) { + log_ = &log; + condition(yycnormal); + theoryLexing_ = TheoryLexing::Disabled; + _startSymbol = NonGroundGrammar::parser::token::PARSE_LP; + if (empty()) { return true; } + NonGroundGrammar::parser parser(this); + _init(); + auto ret = parser.parse(); + filenames_.clear(); + return ret == 0; +} + +INongroundProgramBuilder &NonGroundParser::builder() { return pb_; } + +unsigned NonGroundParser::aggregate(AggregateFunction fun, bool choice, unsigned elems, BoundVecUid bounds) { + return _aggregates.insert({fun, choice, elems, bounds}); +} + +unsigned NonGroundParser::aggregate(TheoryAtomUid atom) { + return _aggregates.insert({AggregateFunction::COUNT, 2, atom, static_cast(0)}); +} + +HdLitUid NonGroundParser::headaggregate(Location const &loc, unsigned hdaggr) { + auto aggr = _aggregates.erase(hdaggr); + switch (aggr.choice) { + case 1: return builder().headaggr(loc, aggr.fun, aggr.bounds, CondLitVecUid(aggr.elems)); + case 2: return builder().headaggr(loc, static_cast(aggr.elems)); + default: return builder().headaggr(loc, aggr.fun, aggr.bounds, HdAggrElemVecUid(aggr.elems)); + } +} + +BdLitVecUid NonGroundParser::bodyaggregate(BdLitVecUid body, Location const &loc, NAF naf, unsigned bdaggr) { + auto aggr = _aggregates.erase(bdaggr); + switch (aggr.choice) { + case 1: return builder().bodyaggr(body, loc, naf, aggr.fun, aggr.bounds, CondLitVecUid(aggr.elems)); + case 2: return builder().bodyaggr(body, loc, naf, static_cast(aggr.elems)); + default: return builder().bodyaggr(body, loc, naf, aggr.fun, aggr.bounds, BdAggrElemVecUid(aggr.elems)); + } +} + +BoundVecUid NonGroundParser::boundvec(Relation ra, TermUid ta, Relation rb, TermUid tb) { + auto bound(builder().boundvec()); + auto undef = TermUid(-1); + if (ta != undef) { builder().boundvec(bound, inv(ra), ta); } + if (tb != undef) { builder().boundvec(bound, rb, tb); } + return bound; +} + +NonGroundParser::~NonGroundParser() { } + +// }}} + +} } // namespace Input Gringo + +#include "input/nongroundlexer.hh" + diff --git a/libgringo/src/input/program.cc b/libgringo/src/input/program.cc new file mode 100644 index 0000000..cf16180 --- /dev/null +++ b/libgringo/src/input/program.cc @@ -0,0 +1,263 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/program.hh" +#include "gringo/input/literals.hh" +#include "gringo/input/aggregates.hh" +#include "gringo/ground/literal.hh" +#include "gringo/ground/statements.hh" +#include "gringo/term.hh" +#include "gringo/logger.hh" +#include "gringo/graph.hh" +#include "gringo/safetycheck.hh" + +namespace Gringo { namespace Input { + +// {{{ definition of Block + +Block::Block(Location const &loc, String name, IdVec &¶ms) + : loc(loc) + , name(name) + , params(std::move(params)) + , edb(std::make_shared(nullptr, SymVec())) { + UTermVec args; + for (auto ¶m : this->params) { args.emplace_back(make_locatable(param.first, Symbol::createId(param.second))); } + if (args.empty()) { std::get<0>(*edb) = make_locatable(loc, Symbol::createId(name)); } + else { std::get<0>(*edb) = make_locatable(loc, name, std::move(args)); } +} + +Block::Block(Block&&) = default; +Block &Block::operator=(Block&&) = default; +Block::~Block() = default; + +Term const &Block::sig() const { + return *std::get<0>(*edb); +} +Block::operator Term const &() const { return sig(); } + +// }}} +// {{{ definition of Program + +Program::Program() { + begin(Location("", 1, 1, "", 1, 1), "base", IdVec({})); +} + +Program::Program(Program &&) = default; + +void Program::begin(Location const &loc, String name, IdVec &¶ms) { + current_ = &*blocks_.push(loc, (std::string("#inc_") + name.c_str()).c_str(), std::move(params)).first; +} + +void Program::add(UStm &&stm) { + current_->addedEdb.emplace_back(stm->isEDB()); + if (current_->addedEdb.back().type() == SymbolType::Special) { + current_->addedStms.emplace_back(std::move(stm)); + current_->addedEdb.pop_back(); + } +} + +void Program::add(TheoryDef &&def, Logger &log) { + auto it = theoryDefs_.find(def.name()); + if (it == theoryDefs_.end()) { + theoryDefs_.push(std::move(def)); + } + else { + GRINGO_REPORT(log, clingo_error_runtime) + << def.loc() << ": error: redefinition of theory:" << "\n" + << " " << def.name() << "\n" + << it->loc() << ": note: theory first defined here\n"; + } + +} + +void Program::rewrite(Defines &defs, Logger &log) { + for (auto &block : blocks_) { + // {{{3 replacing definitions + Defines incDefs; + + UTermVec args; + AuxGen gen; + for (auto ¶m : block.params) { + args.emplace_back(gen.uniqueVar(param.first, 0, "#Inc")); + incDefs.add(param.first, param.second, get_clone(args.back()), false, log); + } + sigs_.push(Sig(block.name, static_cast(args.size()), false)); + UTerm blockTerm(args.empty() + ? (UTerm)make_locatable(block.loc, Symbol::createId(block.name)) + : make_locatable(block.loc, block.name, get_clone(args))); + incDefs.init(log); + + for (auto &fact : block.addedEdb) { sigs_.push(fact.sig()); } + auto replace = [&](Defines &defs, Symbol fact) -> Symbol { + if (defs.empty() || fact.type() == SymbolType::Special) { return fact; } + UTerm rt; + Symbol rv; + defs.apply(fact, rv, rt, false); + if (rt) { + Location loc{rt->loc()}; + block.addedStms.emplace_back(make_locatable(loc, gringo_make_unique(make_locatable(loc, NAF::POS, std::move(rt))), UBodyAggrVec{}, StatementType::RULE)); + return Symbol(); + } + else if (rv.type() != SymbolType::Special) { return rv; } + else { return fact; } + }; + if (!defs.empty() || !incDefs.empty()) { + for (auto &fact : block.addedEdb) { + Symbol rv = replace(incDefs, replace(defs, fact)); + if (rv.type() != SymbolType::Special) { std::get<1>(*block.edb).emplace_back(rv); } + } + block.addedEdb.clear(); + } + else if (std::get<1>(*block.edb).empty()) { std::swap(std::get<1>(*block.edb), block.addedEdb); } + else { std::copy(block.addedEdb.begin(), block.addedEdb.end(), std::back_inserter(std::get<1>(*block.edb))); } + // {{{3 rewriting + auto rewrite2 = [&](UStm &x) -> void { + std::get<1>(*block.edb).emplace_back(x->isEDB()); + if (std::get<1>(*block.edb).back().type() == SymbolType::Special) { + x->add(make_locatable(block.loc, NAF::POS, get_clone(blockTerm), true)); + x->rewrite2(); + block.stms.emplace_back(std::move(x)); + std::get<1>(*block.edb).pop_back(); + } + else { sigs_.push(std::get<1>(*block.edb).back().sig()); } + }; + auto rewrite1 = [&](UStm &x) -> void { + x->initTheory(theoryDefs_, log); + if (x->rewrite1(project_, log)) { + if (x->hasPool(false)) { for (auto &y : x->unpool(false)) { rewrite2(y); } } + else { rewrite2(x); } + } + }; + for (auto &x : block.addedStms) { + x->replace(defs); + x->replace(incDefs); + if (x->hasPool(true)) { for (auto &y : x->unpool(true)) { rewrite1(y); } } + else { rewrite1(x); } + } + block.addedStms.clear(); + // }}}3 + } + // {{{3 projection + for (auto &x : project_) { + if (!x.done) { + Location loc(x.project->loc()); + UBodyAggrVec body; + body.emplace_back(gringo_make_unique(make_locatable(loc, get_clone(x.project)))); + stms_.emplace_back(make_locatable( + loc, + gringo_make_unique(make_locatable(loc, NAF::POS, get_clone(x.projected))), + std::move(body), StatementType::RULE)); + x.done = true; + } + } + // }}}3 +} + +void Program::check(Logger &log) { + for (auto &block : blocks_) { + for (auto &stm : block.stms) { stm->check(log); } + } + std::unordered_map seenSigs; + for (auto &def : theoryDefs_) { + for (auto &atomDef : def.atomDefs()) { + auto seenSig = seenSigs.emplace(atomDef.sig(), atomDef.loc()); + if (!seenSig.second) { + GRINGO_REPORT(log, clingo_error_runtime) + << atomDef.loc() << ": error: multiple definitions for theory atom:" << "\n" + << " " << atomDef.sig() << "\n" + << seenSig.first->second << ": note: first defined here\n"; + } + } + } +} + +void Program::print(std::ostream &out) const { + for (auto &def : theoryDefs_) { + out << def << "\n"; + } + for (auto &block : blocks_) { + for (auto &x : block.addedEdb) { out << x << "." << "\n"; } + for (auto &x : std::get<1>(*block.edb)) { out << x << "." << "\n"; } + for (auto &x : block.addedStms) { out << *x << "\n"; } + for (auto &x : block.stms) { out << *x << "\n"; } + } + for (auto &x : stms_) { out << *x << "\n"; } +} + +Ground::Program Program::toGround(DomainData &domains, Logger &log) { + HashSet neg; + Ground::Program::ClassicalNegationVec negate; + auto gn = [&neg, &negate, &domains](Sig x) { + if (neg.insert(std::hash(), std::equal_to(), x.rep()).second) { + negate.emplace_back(domains.add(x.flipSign()), domains.add(x)); + } + }; + Ground::UStmVec stms; + stms.emplace_back(make_locatable(Location("#external", 1, 1, "#external", 1, 1))); + ToGroundArg arg(auxNames_, domains); + Ground::SEdbVec edb; + for (auto &block : blocks_) { + for (auto &x : block.edb->second) { + auto sig = x.sig(); + if (sig.sign()) { gn(sig); } + } + edb.emplace_back(block.edb); + for (auto &x : block.stms) { + x->getNeg(gn); + x->toGround(arg, stms); + } + } + for (auto &x : stms_) { + x->getNeg(gn); + x->toGround(arg, stms); + } + Ground::Statement::Dep dep; + for (auto &x : stms) { + bool normal(x->isNormal()); + auto &node(dep.add(std::move(x), normal)); + node.stm->analyze(node, dep); + } + Ground::Program prg(std::move(edb), dep.analyze(), std::move(negate)); + for (auto &sig : sigs_) { + domains.add(sig); + } + Ground::UndefVec undef; + for (auto &x : dep.depend.occs) { + for (auto &y : x.second.first->depend) { (*std::get<0>(y)).checkDefined(locs_, sigs_, undef); } + } + std::sort(undef.begin(), undef.end(), [](Ground::UndefVec::value_type const &a, Ground::UndefVec::value_type const &b) { return a.first < b.first; }); + for (auto &x : undef) { + GRINGO_REPORT(log, clingo_warning_atom_undefined) + << x.first << ": info: atom does not occur in any rule head:\n" + << " " << *x.second << "\n"; + } + return prg; +} + +Program::~Program() { } + +std::ostream &operator<<(std::ostream &out, Program const &p) { + p.print(out); + return out; +} + +// }}} + +} } // namespace Input Gringo diff --git a/libgringo/src/input/programbuilder.cc b/libgringo/src/input/programbuilder.cc new file mode 100644 index 0000000..532b9cc --- /dev/null +++ b/libgringo/src/input/programbuilder.cc @@ -0,0 +1,1935 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/programbuilder.hh" +#include "gringo/input/literals.hh" +#include "gringo/input/aggregates.hh" +#include "gringo/input/program.hh" +#include "gringo/input/theory.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +namespace Gringo { namespace Input { + +// {{{1 definition of NongroundProgramBuilder + +NongroundProgramBuilder::NongroundProgramBuilder(Scripts &scripts, Program &prg, Output::OutputBase &out, Defines &defs, bool rewriteMinimize) +: scripts_(scripts) +, prg_(prg) +, out(out) +, defs_(defs) +, rewriteMinimize_(rewriteMinimize) { } + +// {{{2 terms + +TermUid NongroundProgramBuilder::term(Location const &loc, Symbol val) { + return terms_.insert(make_locatable(loc, val)); +} + +TermUid NongroundProgramBuilder::term(Location const &loc, String name) { + if (name == "_") { return terms_.insert(make_locatable(loc, name, nullptr)); } + else { + auto &ret(vals_[name]); + if (!ret) { ret = std::make_shared(); } + return terms_.insert(make_locatable(loc, name, ret)); + } +} + +TermUid NongroundProgramBuilder::term(Location const &loc, UnOp op, TermUid a) { + return term(loc, op, termvec(termvec(), a)); +} + +TermUid NongroundProgramBuilder::term(Location const &loc, UnOp op, TermVecUid a) { + UTermVec vec(termvecs_.erase(a)); + if (vec.size() == 1) { return terms_.insert(make_locatable(loc, op, std::move(vec.front()))); } + else { + UTermVec pool; + for (auto &terms : vec) { pool.emplace_back(make_locatable(loc, op, std::move(terms))); } + return terms_.insert(make_locatable(loc, std::move(pool))); + } +} + +TermUid NongroundProgramBuilder::term(Location const &loc, BinOp op, TermUid a, TermUid b) { + return terms_.insert(make_locatable(loc, op, terms_.erase(a), terms_.erase(b))); +} + +TermUid NongroundProgramBuilder::term(Location const &loc, TermUid a, TermUid b) { + return terms_.insert(make_locatable(loc, terms_.erase(a), terms_.erase(b))); +} + +TermUid NongroundProgramBuilder::term(Location const &loc, String name, TermVecVecUid a, bool lua) { + assert(name != ""); + auto create = [&lua, &name, &loc](UTermVec &&vec) -> UTerm { + // lua terms + if (lua) { return make_locatable(loc, name, std::move(vec)); } + // constant symbols + else if (vec.empty()) { return make_locatable(loc, Symbol::createId(name)); } + // function terms + else { return make_locatable(loc, name, std::move(vec)); } + }; + TermVecVecs::ValueType vec(termvecvecs_.erase(a)); + // no pooling + if (vec.size() == 1) { return terms_.insert(create(std::move(vec.front()))); } + // pooling + else { + UTermVec pool; + for (auto &terms : vec) { pool.emplace_back(create(std::move(terms))); } + return terms_.insert(make_locatable(loc, std::move(pool))); + } +} + +TermUid NongroundProgramBuilder::term(Location const &loc, TermVecUid args, bool forceTuple) { + UTermVec a(termvecs_.erase(args)); + UTerm ret(!forceTuple && a.size() == 1 ? std::move(a.front()) : make_locatable(loc, "", std::move(a))); + return terms_.insert(std::move(ret)); +} + +TermUid NongroundProgramBuilder::pool(Location const &loc, TermVecUid args) { + return terms_.insert(make_locatable(loc, termvecs_.erase(args))); +} + +// {{{2 id vectors + +IdVecUid NongroundProgramBuilder::idvec() { + return idvecs_.emplace(); +} +IdVecUid NongroundProgramBuilder::idvec(IdVecUid uid, Location const &loc, String id) { + idvecs_[uid].emplace_back(loc, id); + return uid; +} + +// {{{2 csp + +CSPMulTermUid NongroundProgramBuilder::cspmulterm(Location const &, TermUid coe, TermUid var) { + return cspmulterms_.emplace(terms_.erase(var), terms_.erase(coe)); +} +CSPMulTermUid NongroundProgramBuilder::cspmulterm(Location const &, TermUid coe) { + return cspmulterms_.emplace(nullptr, terms_.erase(coe)); +} +CSPAddTermUid NongroundProgramBuilder::cspaddterm(Location const &loc, CSPAddTermUid a, CSPMulTermUid b, bool add) { + if (add) { + cspaddterms_[a].append(cspmulterms_.erase(b)); + } + else { + CSPMulTerm mul(cspmulterms_.erase(b)); + mul.coe = make_locatable(loc, UnOp::NEG, std::move(mul.coe)); + cspaddterms_[a].append(std::move(mul)); + } + + return a; +} +CSPAddTermUid NongroundProgramBuilder::cspaddterm(Location const &, CSPMulTermUid a) { + return cspaddterms_.emplace(cspmulterms_.erase(a)); +} +LitUid NongroundProgramBuilder::csplit(CSPLitUid a) { + return lits_.emplace(csplits_.erase(a)); +} +CSPLitUid NongroundProgramBuilder::csplit(Location const &loc, CSPLitUid a, Relation rel, CSPAddTermUid b) { + csplits_[a]->append(rel, cspaddterms_.erase(b)); + csplits_[a]->loc(csplits_[a]->loc() + loc); + return a; +} +CSPLitUid NongroundProgramBuilder::csplit(Location const &loc, CSPAddTermUid a, Relation rel, CSPAddTermUid b) { + return csplits_.insert(make_locatable(loc, rel, cspaddterms_.erase(a), cspaddterms_.erase(b))); +} + +// {{{2 termvecs + +TermVecUid NongroundProgramBuilder::termvec() { + return termvecs_.emplace(); +} + +TermVecUid NongroundProgramBuilder::termvec(TermVecUid uid, TermUid term) { + termvecs_[uid].emplace_back(terms_.erase(term)); + return uid; +} + +// {{{2 termvecvecs + +TermVecVecUid NongroundProgramBuilder::termvecvec() { + return termvecvecs_.emplace(); +} + +TermVecVecUid NongroundProgramBuilder::termvecvec(TermVecVecUid uid, TermVecUid termvecUid) { + termvecvecs_[uid].emplace_back(termvecs_.erase(termvecUid)); + return uid; +} + +// {{{2 literals + +LitUid NongroundProgramBuilder::boollit(Location const &loc, bool type) { + return rellit(loc, type ? Relation::EQ : Relation::NEQ, term(loc, Symbol::createNum(0)), term(loc, Symbol::createNum(0))); +} + +LitUid NongroundProgramBuilder::predlit(Location const &loc, NAF naf, TermUid term) { + return lits_.insert(make_locatable(loc, naf, terms_.erase(term))); +} + +LitUid NongroundProgramBuilder::rellit(Location const &loc, Relation rel, TermUid termUidLeft, TermUid termUidRight) { + return lits_.insert(make_locatable(loc, rel, terms_.erase(termUidLeft), terms_.erase(termUidRight))); +} + +// {{{2 literal vectors + +LitVecUid NongroundProgramBuilder::litvec() { + return litvecs_.emplace(); +} + +LitVecUid NongroundProgramBuilder::litvec(LitVecUid uid, LitUid literalUid) { + litvecs_[uid].emplace_back(lits_.erase(literalUid)); + return uid; +} + +// {{{2 body aggregate element vectors + +BdAggrElemVecUid NongroundProgramBuilder::bodyaggrelemvec() { + return bodyaggrelemvecs_.emplace(); +} + +BdAggrElemVecUid NongroundProgramBuilder::bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) { + bodyaggrelemvecs_[uid].emplace_back(termvecs_.erase(termvec), litvecs_.erase(litvec)); + return uid; +} + +CondLitVecUid NongroundProgramBuilder::condlitvec() { + return condlitvecs_.emplace(); +} + +CondLitVecUid NongroundProgramBuilder::condlitvec(CondLitVecUid uid, LitUid lit, LitVecUid litvec) { + condlitvecs_[uid].emplace_back(lits_.erase(lit), litvecs_.erase(litvec)); + return uid; +} + +// {{{2 head aggregate element vectors + +HdAggrElemVecUid NongroundProgramBuilder::headaggrelemvec() { + return headaggrelemvecs_.emplace(); +} + +HdAggrElemVecUid NongroundProgramBuilder::headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid lit, LitVecUid litvec) { + headaggrelemvecs_[uid].emplace_back(termvecs_.erase(termvec), lits_.erase(lit), litvecs_.erase(litvec)); + return uid; +} + +// {{{2 bounds + +BoundVecUid NongroundProgramBuilder::boundvec() { + return bounds_.emplace(); +} + +BoundVecUid NongroundProgramBuilder::boundvec(BoundVecUid uid, Relation rel, TermUid term) { + bounds_[uid].emplace_back(rel, terms_.erase(term)); + return uid; +} + +// {{{2 rule bodies + +BdLitVecUid NongroundProgramBuilder::body() { + return bodies_.emplace(); +} + +BdLitVecUid NongroundProgramBuilder::bodylit(BdLitVecUid body, LitUid bodylit) { + bodies_[body].push_back(gringo_make_unique(lits_.erase(bodylit))); + return body; +} + +BdLitVecUid NongroundProgramBuilder::bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) { + bodies_[body].push_back(make_locatable(loc, naf, fun, bounds_.erase(bounds), bodyaggrelemvecs_.erase(bodyaggrelemvec))); + return body; +} + +BdLitVecUid NongroundProgramBuilder::bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid condlitvecuid) { + bodies_[body].push_back(make_locatable(loc, naf, fun, bounds_.erase(bounds), condlitvecs_.erase(condlitvecuid))); + return body; +} + +BdLitVecUid NongroundProgramBuilder::conjunction(BdLitVecUid body, Location const &loc, LitUid head, LitVecUid litvec) { + bodies_[body].push_back(make_locatable(loc, lits_.erase(head), litvecs_.erase(litvec))); + return body; +} + +BdLitVecUid NongroundProgramBuilder::disjoint(BdLitVecUid body, Location const &loc, NAF naf, CSPElemVecUid elem) { + bodies_[body].push_back(make_locatable(loc, naf, cspelems_.erase(elem))); + return body; +} + + +// {{{2 rule heads + +HdLitUid NongroundProgramBuilder::headlit(LitUid lit) { + return heads_.insert(gringo_make_unique(lits_.erase(lit))); +} + +HdLitUid NongroundProgramBuilder::headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, HdAggrElemVecUid headaggrelemvec) { + return heads_.insert(make_locatable(loc, fun, bounds_.erase(bounds), headaggrelemvecs_.erase(headaggrelemvec))); +} + +HdLitUid NongroundProgramBuilder::headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid condlitvec) { + return heads_.insert(make_locatable(loc, fun, bounds_.erase(bounds), condlitvecs_.erase(condlitvec))); +} + +HdLitUid NongroundProgramBuilder::disjunction(Location const &loc, CondLitVecUid condlitvec) { + return heads_.insert(make_locatable(loc, condlitvecs_.erase(condlitvec))); +} + +// {{{2 csp constraint elements + +CSPElemVecUid NongroundProgramBuilder::cspelemvec() { + return cspelems_.emplace(); +} + +CSPElemVecUid NongroundProgramBuilder::cspelemvec(CSPElemVecUid uid, Location const &loc, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) { + cspelems_[uid].emplace_back(loc, termvecs_.erase(termvec), cspaddterms_.erase(addterm), litvecs_.erase(litvec)); + return uid; +} + +// {{{2 statements + +void NongroundProgramBuilder::rule(Location const &loc, HdLitUid head) { + rule(loc, head, body()); +} + +void NongroundProgramBuilder::rule(Location const &loc, HdLitUid head, BdLitVecUid body) { + prg_.add(make_locatable(loc, heads_.erase(head), bodies_.erase(body), StatementType::RULE)); +} + +void NongroundProgramBuilder::define(Location const &loc, String name, TermUid value, bool defaultDef, Logger &log) { + defs_.add(loc, name, terms_.erase(value), defaultDef, log); +} + +void NongroundProgramBuilder::optimize(Location const &loc, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) { + if (rewriteMinimize_) { + auto argsUid = termvec(termvec(termvec(), priority), weight); + termvec(argsUid, term(loc, cond, true)); + auto predUid = predlit(loc, NAF::POS, term(loc, "_criteria", termvecvec(termvecvec(), argsUid), false)); + rule(loc, headlit(predUid), body); + out.outPredsForce.emplace_back(loc, Sig("_criteria", 3, false), false); + } + else { + prg_.add(make_locatable(loc, make_locatable(loc, terms_.erase(weight), terms_.erase(priority), termvecs_.erase(cond)), bodies_.erase(body), StatementType::WEAKCONSTRAINT)); + } +} + +void NongroundProgramBuilder::showsig(Location const &loc, Sig sig, bool csp) { + out.outPreds.emplace_back(loc, sig, csp); +} + +void NongroundProgramBuilder::show(Location const &loc, TermUid t, BdLitVecUid body, bool csp) { + prg_.add(make_locatable(loc, make_locatable(loc, terms_.erase(t), csp), bodies_.erase(body), StatementType::RULE)); +} + +void NongroundProgramBuilder::lua(Location const &loc, String code) { + scripts_.luaExec(loc, code); +} + +void NongroundProgramBuilder::python(Location const &loc, String code) { + scripts_.pyExec(loc, code); +} + +void NongroundProgramBuilder::block(Location const &loc, String name, IdVecUid args) { + prg_.begin(loc, name, idvecs_.erase(args)); +} + +void NongroundProgramBuilder::external(Location const &loc, TermUid head, BdLitVecUid body) { + prg_.add(make_locatable(loc, heads_.erase(headlit(predlit(loc, NAF::POS, head))), bodies_.erase(body), StatementType::EXTERNAL)); +} + +void NongroundProgramBuilder::edge(Location const &loc, TermVecVecUid edgesUid, BdLitVecUid body) { + auto edges = termvecvecs_.erase(edgesUid); + for (auto it = edges.begin(), end = edges.end(), last = end-1; it != end; ++it) { + prg_.add(make_locatable( + loc, + make_locatable( + loc, + std::move(it->front()), + std::move(it->back()) + ), + it == last ? bodies_.erase(body) : get_clone(bodies_[body]), + StatementType::RULE + )); + } +} + +void NongroundProgramBuilder::heuristic(Location const &loc, TermUid termUid, BdLitVecUid body, TermUid a, TermUid b, TermUid mod) { + prg_.add(make_locatable(loc, make_locatable(loc, terms_.erase(termUid), terms_.erase(a), terms_.erase(b), terms_.erase(mod)), bodies_.erase(body), StatementType::RULE)); +} + +void NongroundProgramBuilder::project(Location const &loc, TermUid termUid, BdLitVecUid body) { + prg_.add(make_locatable(loc, make_locatable(loc, terms_.erase(termUid)), bodies_.erase(body), StatementType::RULE)); +} + +void NongroundProgramBuilder::project(Location const &loc, Sig sig) { + Sig s = sig; + auto tv = termvec(); + for (unsigned i = 0; i < s.arity(); ++i) { + std::ostringstream ss; + ss << "X" << i; + tv = termvec(tv, term(loc, ss.str().c_str())); + } + project(loc, predRep(loc, s.sign(), s.name(), termvecvec(termvecvec(), tv)), body()); +} + +// {{{2 theory + +TheoryTermUid NongroundProgramBuilder::theorytermset(Location const &loc, TheoryOptermVecUid args) { + (void)loc; + return theoryTerms_.emplace(gringo_make_unique(Output::TupleTheoryTerm::Type::Brace, theoryOptermVecs_.erase(args))); +} + +TheoryTermUid NongroundProgramBuilder::theoryoptermlist(Location const &loc, TheoryOptermVecUid args) { + (void)loc; + return theoryTerms_.emplace(gringo_make_unique(Output::TupleTheoryTerm::Type::Bracket, theoryOptermVecs_.erase(args))); +} + +TheoryTermUid NongroundProgramBuilder::theorytermtuple(Location const &loc, TheoryOptermVecUid args) { + (void)loc; + return theoryTerms_.emplace(gringo_make_unique(Output::TupleTheoryTerm::Type::Paren, theoryOptermVecs_.erase(args))); +} + +TheoryTermUid NongroundProgramBuilder::theorytermopterm(Location const &loc, TheoryOptermUid opterm) { + (void)loc; + return theoryTerms_.emplace(gringo_make_unique(theoryOpterms_.erase(opterm))); +} + +TheoryTermUid NongroundProgramBuilder::theorytermfun(Location const &loc, String name, TheoryOptermVecUid args) { + (void)loc; + return theoryTerms_.emplace(gringo_make_unique(name, theoryOptermVecs_.erase(args))); +} + +TheoryTermUid NongroundProgramBuilder::theorytermvalue(Location const &loc, Symbol val) { + return theoryTerms_.emplace(gringo_make_unique(make_locatable(loc, val))); +} + +TheoryTermUid NongroundProgramBuilder::theorytermvar(Location const &loc, String var) { + auto &ret(vals_[var]); + if (!ret) { ret = std::make_shared(); } + return theoryTerms_.emplace(gringo_make_unique(make_locatable(loc, var, ret))); +} + +TheoryOptermUid NongroundProgramBuilder::theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) { + auto ret = theoryOpterms_.emplace(); + theoryOpterms_[ret].append(theoryOpVecs_.erase(ops), theoryTerms_.erase(term)); + return ret; +} + +TheoryOptermUid NongroundProgramBuilder::theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) { + theoryOpterms_[opterm].append(theoryOpVecs_.erase(ops), theoryTerms_.erase(term)); + return opterm; +} + +TheoryOpVecUid NongroundProgramBuilder::theoryops() { + return theoryOpVecs_.emplace(); +} + +TheoryOpVecUid NongroundProgramBuilder::theoryops(TheoryOpVecUid ops, String op) { + theoryOpVecs_[ops].emplace_back(op); + return ops; +} + +TheoryOptermVecUid NongroundProgramBuilder::theoryopterms() { + return theoryOptermVecs_.emplace(); +} +TheoryOptermVecUid NongroundProgramBuilder::theoryopterms(TheoryOptermVecUid opterms, Location const &, TheoryOptermUid opterm) { + theoryOptermVecs_[opterms].emplace_back(gringo_make_unique(theoryOpterms_.erase(opterm))); + return opterms; +} +TheoryOptermVecUid NongroundProgramBuilder::theoryopterms(Location const &, TheoryOptermUid opterm, TheoryOptermVecUid opterms) { + theoryOptermVecs_[opterms].insert(theoryOptermVecs_[opterms].begin(), gringo_make_unique(theoryOpterms_.erase(opterm))); + return opterms; +} + +TheoryElemVecUid NongroundProgramBuilder::theoryelems() { + return theoryElems_.emplace(); +} +TheoryElemVecUid NongroundProgramBuilder::theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) { + theoryElems_[elems].emplace_back(theoryOptermVecs_.erase(opterms), litvecs_.erase(cond)); + return elems; +} + +TheoryAtomUid NongroundProgramBuilder::theoryatom(TermUid term, TheoryElemVecUid elems) { + return theoryAtoms_.emplace(terms_.erase(term), theoryElems_.erase(elems)); +} +TheoryAtomUid NongroundProgramBuilder::theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &, TheoryOptermUid opterm) { + return theoryAtoms_.emplace(terms_.erase(term), theoryElems_.erase(elems), op, gringo_make_unique(theoryOpterms_.erase(opterm))); +} + +BdLitVecUid NongroundProgramBuilder::bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, TheoryAtomUid atom) { + bodies_[body].emplace_back(make_locatable(loc, naf, theoryAtoms_.erase(atom))); + return body; +} + +HdLitUid NongroundProgramBuilder::headaggr(Location const &loc, TheoryAtomUid atom) { + return heads_.emplace(make_locatable(loc, theoryAtoms_.erase(atom))); +} + +// {{{2 theory definitions + +TheoryOpDefUid NongroundProgramBuilder::theoryopdef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) { + return theoryOpDefs_.emplace(loc, op, priority, type); +} + +TheoryOpDefVecUid NongroundProgramBuilder::theoryopdefs() { + return theoryOpDefVecs_.emplace(); +} + +TheoryOpDefVecUid NongroundProgramBuilder::theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) { + theoryOpDefVecs_[defs].emplace_back(theoryOpDefs_.erase(def)); + return defs; +} + +TheoryTermDefUid NongroundProgramBuilder::theorytermdef(Location const &loc, String name, TheoryOpDefVecUid defs, Logger &log) { + TheoryTermDef def(loc, name); + for (auto &opDef : theoryOpDefVecs_.erase(defs)) { + def.addOpDef(std::move(opDef), log); + } + return theoryTermDefs_.emplace(std::move(def)); +} + +TheoryAtomDefUid NongroundProgramBuilder::theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type) { + return theoryAtomDefs_.emplace(loc, name, arity, termDef, type); +} + +TheoryAtomDefUid NongroundProgramBuilder::theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) { + return theoryAtomDefs_.emplace(loc, name, arity, termDef, type, theoryOpVecs_.erase(ops), guardDef); +} + +TheoryDefVecUid NongroundProgramBuilder::theorydefs() { + return theoryDefVecs_.emplace(); +} + +TheoryDefVecUid NongroundProgramBuilder::theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) { + theoryDefVecs_[defs].first.emplace_back(theoryTermDefs_.erase(def)); + return defs; +} + +TheoryDefVecUid NongroundProgramBuilder::theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) { + theoryDefVecs_[defs].second.emplace_back(theoryAtomDefs_.erase(def)); + return defs; +} + +void NongroundProgramBuilder::theorydef(Location const &loc, String name, TheoryDefVecUid defs, Logger &log) { + TheoryDef def(loc, name); + auto defsVec = theoryDefVecs_.erase(defs); + for (auto &termDef : defsVec.first) { + def.addTermDef(std::move(termDef), log); + } + for (auto &atomDef : defsVec.second) { + def.addAtomDef(std::move(atomDef), log); + } + prg_.add(std::move(def), log); +} + +// }}}2 + +NongroundProgramBuilder::~NongroundProgramBuilder() { } + +// {{{1 definition of ASTBuilder + +clingo_location convertLoc(Location const &loc) { + return clingo_location { + loc.beginFilename.c_str(), loc.endFilename.c_str(), + loc.beginLine, loc.endLine, + loc.beginColumn, loc.endColumn + }; +} + +Location convertLoc(clingo_location loc) { + return {loc.begin_file, static_cast(loc.begin_line), static_cast(loc.begin_column) + ,loc.end_file, static_cast(loc.end_line), static_cast(loc.end_column)}; +} + +template +T *ASTBuilder::create_() { + data_.emplace_back(operator new(sizeof(T))); + return reinterpret_cast(data_.back()); +} +template +T *ASTBuilder::create_(T x) { + auto *r = create_(); + *r = x; + return r; +} +template +T *ASTBuilder::createArray_(size_t size) { + arrdata_.emplace_back(operator new[](sizeof(T) * size)); + return reinterpret_cast(arrdata_.back()); +} +template +T *ASTBuilder::createArray_(std::vector const &vec) { + auto *r = createArray_(vec.size()); + std::copy(vec.begin(), vec.end(), reinterpret_cast(r)); + return r; +} + +void ASTBuilder::clear_() noexcept { + for (auto &x : data_) { operator delete(x); } + for (auto &x : arrdata_) { operator delete[](x); } + data_.clear(); + arrdata_.clear(); +} + +void ASTBuilder::statement_(Location loc, clingo_ast_statement_type_t type, clingo_ast_statement_t &stm) { + stm.location = convertLoc(loc); + stm.type = type; + cb_(stm); + clear_(); +} + +ASTBuilder::ASTBuilder(Callback cb) : cb_(cb) { } +ASTBuilder::~ASTBuilder() noexcept { + clear_(); +} + +// {{{2 terms + +TermUid ASTBuilder::term(Location const &loc, Symbol val) { + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_term_type_symbol; + term.symbol = val.rep(); + return terms_.insert(std::move(term)); +} + +TermUid ASTBuilder::term(Location const &loc, String name) { + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_term_type_variable; + term.variable = name.c_str(); + return terms_.insert(std::move(term)); +} + +TermUid ASTBuilder::term(Location const &loc, UnOp op, TermUid a) { + auto unop = create_(); + unop->unary_operator = static_cast(op); + unop->argument = terms_.erase(a); + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_term_type_unary_operation; + term.unary_operation = unop; + return terms_.insert(std::move(term)); +} + +TermUid ASTBuilder::pool_(Location const &loc, TermVec &&vec) { + if (vec.size() == 1) { + return terms_.insert(std::move(vec.front())); + } + else { + auto pool = create_(); + pool->size = vec.size(); + pool->arguments = createArray_(vec); + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_term_type_pool; + term.pool = pool; + return terms_.insert(std::move(term)); + } +} + +TermUid ASTBuilder::term(Location const &loc, UnOp op, TermVecUid a) { + return term(loc, op, pool_(loc, termvecs_.erase(a))); +} + +TermUid ASTBuilder::term(Location const &loc, BinOp op, TermUid a, TermUid b) { + auto *binop = create_(); + binop->binary_operator = static_cast(op); + binop->left = terms_.erase(a); + binop->right = terms_.erase(b); + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_term_type_binary_operation; + term.binary_operation = binop; + return terms_.insert(std::move(term)); +} + +TermUid ASTBuilder::term(Location const &loc, TermUid a, TermUid b) { + auto interval = create_(); + interval->left = terms_.erase(a); + interval->right = terms_.erase(b); + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_term_type_interval; + term.interval = interval; + return terms_.insert(std::move(term)); +} + +clingo_ast_term_t ASTBuilder::fun_(Location const &loc, String name, TermVec &&vec, bool external) { + auto fun = create_(); + fun->name = name.c_str(); + fun->size = vec.size(); + fun->arguments = createArray_(vec); + clingo_ast_term_t term; + term.location = convertLoc(loc); + term.type = external ? clingo_ast_term_type_external_function : clingo_ast_term_type_function; + term.function = fun; + return term; +} + +TermUid ASTBuilder::term(Location const &loc, String name, TermVecVecUid a, bool lua) { + TermVec pool; + for (auto &args : termvecvecs_.erase(a)) { + pool.emplace_back(fun_(loc, name, std::move(args), lua)); + } + return pool_(loc, std::move(pool)); +} + +TermUid ASTBuilder::term(Location const &loc, TermVecUid a, bool forceTuple) { + return terms_.insert((termvecs_[a].size() == 1 && !forceTuple) + ? std::move(termvecs_.erase(a).front()) + : fun_(loc, "", termvecs_.erase(a), false)); +} + +TermUid ASTBuilder::pool(Location const &loc, TermVecUid a) { + return pool_(loc, termvecs_.erase(a)); +} + +// {{{2 csp + +CSPMulTermUid ASTBuilder::cspmulterm(Location const &loc, TermUid coe, TermUid var) { + clingo_ast_csp_product_term_t term; + term.location = convertLoc(loc); + term.coefficient = terms_.erase(coe); + term.variable = create_(terms_.erase(var)); + return cspmulterms_.insert(std::move(term)); +} + +CSPMulTermUid ASTBuilder::cspmulterm(Location const &loc, TermUid coe) { + clingo_ast_csp_product_term_t term; + term.location = convertLoc(loc); + term.coefficient = terms_.erase(coe); + term.variable = nullptr; + return cspmulterms_.insert(std::move(term)); +} + +CSPAddTermUid ASTBuilder::cspaddterm(Location const &loc, CSPAddTermUid a, CSPMulTermUid b, bool add) { + auto &addterm = cspaddterms_[a]; + addterm.first = loc; + addterm.second.emplace_back(cspmulterms_.erase(b)); + if (!add) { + auto unop = create_(); + unop->unary_operator = clingo_ast_unary_operator_minus; + unop->argument = addterm.second.back().coefficient; + clingo_ast_term_t term; + term.type = clingo_ast_term_type_unary_operation; + term.location = addterm.second.back().coefficient.location; + term.unary_operation = unop; + addterm.second.back().coefficient = term; + } + return a; +} + +CSPAddTermUid ASTBuilder::cspaddterm(Location const &loc, CSPMulTermUid b) { + return cspaddterms_.emplace(loc, std::initializer_list{cspmulterms_.erase(b)}); +} + +CSPLitUid ASTBuilder::csplit(Location const &loc, CSPLitUid a, Relation rel, CSPAddTermUid b) { + auto &lit = csplits_[a]; + auto rep = cspaddterms_.erase(b); + clingo_ast_csp_sum_term_t term; + term.size = rep.second.size(); + term.location = convertLoc(rep.first); + term.terms = createArray_(rep.second); + lit.first = loc; + lit.second.emplace_back(rel, std::move(term)); + return a; +} + +CSPLitUid ASTBuilder::csplit(Location const &loc, CSPAddTermUid a, Relation rel, CSPAddTermUid b) { + auto repa = cspaddterms_.erase(a), repb = cspaddterms_.erase(b); + clingo_ast_csp_sum_term terma, termb; + terma.location = convertLoc(repa.first); + terma.size = repa.second.size(); + terma.terms = createArray_(repa.second); + termb.location = convertLoc(repb.first); + termb.size = repb.second.size(); + termb.terms = createArray_(repb.second); + CSPLits::ValueType vec = { loc, {{rel, terma}, {rel, termb}} }; + return csplits_.insert(std::move(vec)); +} + +// {{{2 id vectors + +IdVecUid ASTBuilder::idvec() { + return idvecs_.emplace(); +} + +IdVecUid ASTBuilder::idvec(IdVecUid uid, Location const &loc, String id) { + idvecs_[uid].emplace_back(clingo_ast_id_t{convertLoc(loc), id.c_str()}); + return uid; +} + +// {{{2 term vectors +TermVecUid ASTBuilder::termvec() { + return termvecs_.emplace(); +} + +TermVecUid ASTBuilder::termvec(TermVecUid uid, TermUid termUid) { + termvecs_[uid].emplace_back(terms_.erase(termUid)); + return uid; +} + +// {{{2 term vector vectors +TermVecVecUid ASTBuilder::termvecvec() { + return termvecvecs_.emplace(); +} + +TermVecVecUid ASTBuilder::termvecvec(TermVecVecUid uid, TermVecUid termvecUid) { + termvecvecs_[uid].emplace_back(termvecs_.erase(termvecUid)); + return uid; +} + +// {{{2 literals + +LitUid ASTBuilder::boollit(Location const &loc, bool type) { + clingo_ast_literal_t lit; + lit.location = convertLoc(loc); + lit.sign = clingo_ast_sign_none; + lit.type = clingo_ast_literal_type_boolean; + lit.boolean = type; + return lits_.insert(std::move(lit)); +} + +LitUid ASTBuilder::predlit(Location const &loc, NAF naf, TermUid termUid) { + clingo_ast_literal_t lit; + lit.location = convertLoc(loc); + lit.sign = static_cast(naf); + lit.type = clingo_ast_literal_type_symbolic; + lit.symbol = create_(terms_.erase(termUid)); + return lits_.insert(std::move(lit)); +} + +LitUid ASTBuilder::rellit(Location const &loc, Relation rel, TermUid termUidLeft, TermUid termUidRight) { + auto comp = create_(); + comp->comparison = static_cast(rel); + comp->left = terms_.erase(termUidLeft); + comp->right = terms_.erase(termUidRight); + clingo_ast_literal_t lit; + lit.location = convertLoc(loc); + lit.sign = clingo_ast_sign_none; + lit.type = clingo_ast_literal_type_comparison; + lit.comparison = comp; + return lits_.insert(std::move(lit)); +} + +LitUid ASTBuilder::csplit(CSPLitUid a) { + auto rep = csplits_.erase(a); + assert(rep.second.size() > 1); + auto guards = createArray_(rep.second.size()-1); + auto guardsit = guards; + for (auto it = rep.second.begin() + 1, ie = rep.second.end(); it != ie; ++it, ++guardsit) { + guardsit->comparison = static_cast(it->first); + guardsit->term = it->second; + } + auto csp = create_(); + csp->term = rep.second.front().second; + csp->size = rep.second.size() - 1; + csp->guards = guards; + clingo_ast_literal_t lit; + lit.location = convertLoc(rep.first); + lit.sign = clingo_ast_sign_none; + lit.type = clingo_ast_literal_type_csp; + lit.csp_literal = csp; + return lits_.insert(std::move(lit)); +} + +// {{{2 literal vectors + +LitVecUid ASTBuilder::litvec() { + return litvecs_.emplace(); +} + +LitVecUid ASTBuilder::litvec(LitVecUid uid, LitUid literalUid) { + litvecs_[uid].emplace_back(lits_.erase(literalUid)); + return uid; +} + +// {{{2 conditional literals + +CondLitVecUid ASTBuilder::condlitvec() { + return condlitvecs_.emplace(); +} + +CondLitVecUid ASTBuilder::condlitvec(CondLitVecUid uid, LitUid litUid, LitVecUid litvecUid) { + auto cond = litvecs_.erase(litvecUid); + clingo_ast_conditional_literal_t lit; + lit.size = cond.size(); + lit.condition = createArray_(cond); + lit.literal = lits_.erase(litUid); + condlitvecs_[uid].emplace_back(lit); + return uid; +} + +// {{{2 body aggregate elements + +BdAggrElemVecUid ASTBuilder::bodyaggrelemvec() { + return bodyaggrelemvecs_.emplace(); +} + +BdAggrElemVecUid ASTBuilder::bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) { + clingo_ast_body_aggregate_element_t elem; + auto cond = litvecs_.erase(litvec); + auto tuple = termvecs_.erase(termvec); + elem.condition_size = cond.size(); + elem.condition = createArray_(cond); + elem.tuple_size = tuple.size(); + elem.tuple = createArray_(tuple); + bodyaggrelemvecs_[uid].emplace_back(elem); + return uid; +} + +// {{{2 head aggregate elements + +HdAggrElemVecUid ASTBuilder::headaggrelemvec() { + return headaggrelemvecs_.emplace(); +} + +HdAggrElemVecUid ASTBuilder::headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid litUid, LitVecUid litvec) { + clingo_ast_head_aggregate_element_t elem; + auto cond = litvecs_.erase(litvec); + clingo_ast_conditional_literal_t lit; + lit.size = cond.size(); + lit.condition = createArray_(cond); + lit.literal = lits_.erase(litUid); + auto tuple = termvecs_.erase(termvec); + elem.conditional_literal = lit; + elem.tuple_size = tuple.size(); + elem.tuple = createArray_(tuple); + headaggrelemvecs_[uid].emplace_back(elem); + return uid; +} + +// {{{2 bounds + +BoundVecUid ASTBuilder::boundvec() { + return bounds_.emplace(); +} + +BoundVecUid ASTBuilder::boundvec(BoundVecUid uid, Relation rel, TermUid term) { + clingo_ast_aggregate_guard_t guard; + guard.term = terms_.erase(term); + guard.comparison = static_cast(rel); + bounds_[uid].emplace_back(guard); + return uid; +} + +// {{{2 heads + +HdLitUid ASTBuilder::headlit(LitUid litUid) { + clingo_ast_head_literal_t head; + head.type = clingo_ast_head_literal_type_literal; + head.literal = create_(lits_.erase(litUid)); + head.location = head.literal->location; + return heads_.insert(std::move(head)); +} + +HdLitUid ASTBuilder::headaggr(Location const &loc, TheoryAtomUid atomUid) { + clingo_ast_head_literal_t head; + head.location = convertLoc(loc); + head.type = clingo_ast_head_literal_type_theory_atom; + head.theory_atom = create_(theoryAtoms_.erase(atomUid)); + return heads_.insert(std::move(head)); +} + +HdLitUid ASTBuilder::headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, HdAggrElemVecUid headaggrelemvec) { + auto guards = bounds_.erase(bounds); + auto elems = headaggrelemvecs_.erase(headaggrelemvec); + assert(guards.size() < 3); + if (!guards.empty()) { + guards.front().comparison = static_cast(inv(static_cast(guards.front().comparison))); + } + clingo_ast_head_aggregate_t aggr; + aggr.function = static_cast(fun); + aggr.size = elems.size(); + aggr.elements = createArray_(elems); + aggr.left_guard = guards.size() > 0 ? create_(guards[0]) : nullptr; + aggr.right_guard = guards.size() > 1 ? create_(guards[1]) : nullptr; + clingo_ast_head_literal_t head; + head.location = convertLoc(loc); + head.type = clingo_ast_head_literal_type_head_aggregate; + head.head_aggregate = create_(aggr); + return heads_.insert(std::move(head)); +} + +HdLitUid ASTBuilder::headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid headaggrelemvec) { + (void)fun; + assert(fun == AggregateFunction::COUNT); + auto guards = bounds_.erase(bounds); + auto elems = condlitvecs_.erase(headaggrelemvec); + assert(guards.size() < 3); + if (!guards.empty()) { + guards.front().comparison = static_cast(inv(static_cast(guards.front().comparison))); + } + clingo_ast_aggregate_t aggr; + aggr.size = elems.size(); + aggr.elements = createArray_(elems); + aggr.left_guard = guards.size() > 0 ? create_(guards[0]) : nullptr; + aggr.right_guard = guards.size() > 1 ? create_(guards[1]) : nullptr; + clingo_ast_head_literal_t head; + head.location = convertLoc(loc); + head.type = clingo_ast_head_literal_type_aggregate; + head.aggregate = create_(aggr); + return heads_.insert(std::move(head)); +} + +HdLitUid ASTBuilder::disjunction(Location const &loc, CondLitVecUid condlitvec) { + auto elems = condlitvecs_.erase(condlitvec); + clingo_ast_disjunction_t disj; + disj.size = elems.size(); + disj.elements = createArray_(elems); + clingo_ast_head_literal_t head; + head.location = convertLoc(loc); + head.type = clingo_ast_head_literal_type_disjunction; + head.disjunction = create_(disj); + return heads_.insert(std::move(head)); +} + +// {{{2 bodies + +BdLitVecUid ASTBuilder::body() { + return bodies_.emplace(); +} + +BdLitVecUid ASTBuilder::bodylit(BdLitVecUid body, LitUid bodylit) { + auto lit = lits_.erase(bodylit); + clingo_ast_body_literal_t bd; + bd.location = lit.location; + bd.sign = static_cast(clingo_ast_sign_none); + bd.type = clingo_ast_body_literal_type_literal;; + bd.literal = create_(lit); + bodies_[body].emplace_back(bd); + return body; +} + +BdLitVecUid ASTBuilder::bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, TheoryAtomUid atomUid) { + clingo_ast_body_literal_t bd; + bd.location = convertLoc(loc); + bd.sign = static_cast(naf); + bd.type = clingo_ast_body_literal_type_theory_atom;; + bd.theory_atom = create_(theoryAtoms_.erase(atomUid)); + bodies_[body].emplace_back(bd); + return body; +} + +BdLitVecUid ASTBuilder::bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) { + auto guards = bounds_.erase(bounds); + auto elems = bodyaggrelemvecs_.erase(bodyaggrelemvec); + assert(guards.size() < 3); + if (!guards.empty()) { + guards.front().comparison = static_cast(inv(static_cast(guards.front().comparison))); + } + clingo_ast_body_aggregate_t aggr; + aggr.function = static_cast(fun); + aggr.size = elems.size(); + aggr.elements = createArray_(elems); + aggr.left_guard = guards.size() > 0 ? create_(guards[0]) : nullptr; + aggr.right_guard = guards.size() > 1 ? create_(guards[1]) : nullptr; + clingo_ast_body_literal_t bd; + bd.location = convertLoc(loc); + bd.sign = static_cast(naf); + bd.type = clingo_ast_body_literal_type_body_aggregate; + bd.body_aggregate = create_(aggr); + bodies_[body].emplace_back(bd); + return body; +} + +BdLitVecUid ASTBuilder::bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid bodyaggrelemvec) { + (void)fun; + assert(fun == AggregateFunction::COUNT); + auto guards = bounds_.erase(bounds); + auto elems = condlitvecs_.erase(bodyaggrelemvec); + assert(guards.size() < 3); + if (!guards.empty()) { + guards.front().comparison = static_cast(inv(static_cast(guards.front().comparison))); + } + clingo_ast_aggregate_t aggr; + aggr.size = elems.size(); + aggr.elements = createArray_(elems); + aggr.left_guard = guards.size() > 0 ? create_(guards[0]) : nullptr; + aggr.right_guard = guards.size() > 1 ? create_(guards[1]) : nullptr; + clingo_ast_body_literal_t bd; + bd.location = convertLoc(loc); + bd.sign = static_cast(naf); + bd.type = clingo_ast_body_literal_type_aggregate; + bd.aggregate = create_(aggr); + bodies_[body].emplace_back(bd); + return body; +} + +BdLitVecUid ASTBuilder::conjunction(BdLitVecUid body, Location const &loc, LitUid head, LitVecUid litvec) { + auto cond = litvecs_.erase(litvec); + clingo_ast_conditional_literal_t lit; + lit.literal = lits_.erase(head); + lit.size = cond.size(); + lit.condition = createArray_(cond); + clingo_ast_body_literal_t bd; + bd.location = convertLoc(loc); + bd.sign = clingo_ast_sign_none; + bd.type = clingo_ast_body_literal_type_conditional; + bd.conditional = create_(lit); + bodies_[body].emplace_back(bd); + return body; +} + +BdLitVecUid ASTBuilder::disjoint(BdLitVecUid body, Location const &loc, NAF naf, CSPElemVecUid elem) { + auto elems = cspelems_.erase(elem); + clingo_ast_disjoint_t disj; + disj.size = elems.size(); + disj.elements = createArray_(elems); + clingo_ast_body_literal_t bd; + bd.location = convertLoc(loc); + bd.sign = static_cast(naf); + bd.type = clingo_ast_body_literal_type_disjoint; + bd.disjoint = create_(disj); + bodies_[body].emplace_back(bd); + return body; +} + +// {{{2 csp constraint elements + +CSPElemVecUid ASTBuilder::cspelemvec() { + return cspelems_.emplace(); +} + +CSPElemVecUid ASTBuilder::cspelemvec(CSPElemVecUid uid, Location const &loc, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) { + auto tuple = termvecs_.erase(termvec); + auto rep = cspaddterms_.erase(addterm); + auto cond = litvecs_.erase(litvec); + clingo_ast_csp_sum_term_t term; + term.size = rep.second.size(); + term.location = convertLoc(rep.first); + term.terms = createArray_(rep.second); + clingo_ast_disjoint_element_t elem; + elem.term = term; + elem.location = convertLoc(loc); + elem.tuple = createArray_(tuple); + elem.tuple_size = tuple.size(); + elem.condition = createArray_(cond); + elem.condition_size = cond.size(); + cspelems_[uid].emplace_back(elem); + return uid; +} + +// {{{2 statements + +void ASTBuilder::rule(Location const &loc, HdLitUid head) { + rule(loc, head, body()); +} + +void ASTBuilder::rule(Location const &loc, HdLitUid head, BdLitVecUid body) { + auto lits = bodies_.erase(body); + clingo_ast_rule_t rule; + rule.head = heads_.erase(head); + rule.size = lits.size(); + rule.body = createArray_(lits); + clingo_ast_statement stm; + stm.rule = create_(rule); + statement_(loc, clingo_ast_statement_type_rule, stm); +} + +void ASTBuilder::define(Location const &loc, String name, TermUid value, bool defaultDef, Logger &) { + clingo_ast_definition_t def; + def.name = name.c_str(); + def.value = terms_.erase(value); + def.is_default = defaultDef; + clingo_ast_statement stm; + stm.definition = create_(def); + statement_(loc, clingo_ast_statement_type_const, stm); +} + +void ASTBuilder::optimize(Location const &loc, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) { + auto bd = bodies_.erase(body); + auto tuple = termvecs_.erase(cond); + clingo_ast_minimize_t min; + min.weight = terms_.erase(weight); + min.priority = terms_.erase(priority); + min.body_size = bd.size(); + min.body = createArray_(bd); + min.tuple_size = tuple.size(); + min.tuple = createArray_(tuple); + clingo_ast_statement stm; + stm.minimize = create_(min); + statement_(loc, clingo_ast_statement_type_minimize, stm); +} + +void ASTBuilder::showsig(Location const &loc, Sig sig, bool csp) { + clingo_ast_show_signature_t show; + show.signature = sig.rep(); + show.csp = csp; + clingo_ast_statement stm; + stm.show_signature = create_(show); + statement_(loc, clingo_ast_statement_type_show_signature, stm); +} + +void ASTBuilder::show(Location const &loc, TermUid t, BdLitVecUid body, bool csp) { + auto bd = bodies_.erase(body); + clingo_ast_show_term_t show; + show.term = terms_.erase(t); + show.csp = csp; + show.body = createArray_(bd); + show.size = bd.size(); + clingo_ast_statement stm; + stm.show_term = create_(show); + statement_(loc, clingo_ast_statement_type_show_term, stm); +} + +void ASTBuilder::python(Location const &loc, String code) { + clingo_ast_script_t script; + script.code = code.c_str(); + script.type = clingo_ast_script_type_python; + clingo_ast_statement stm; + stm.script = create_(script); + statement_(loc, clingo_ast_statement_type_script, stm); +} + +void ASTBuilder::lua(Location const &loc, String code) { + clingo_ast_script_t script; + script.code = code.c_str(); + script.type = clingo_ast_script_type_lua; + clingo_ast_statement stm; + stm.script = create_(script); + statement_(loc, clingo_ast_statement_type_script, stm); +} + +void ASTBuilder::block(Location const &loc, String name, IdVecUid args) { + auto params = idvecs_.erase(args); + clingo_ast_program_t program; + program.name = name.c_str(); + program.parameters = createArray_(params); + program.size = params.size(); + clingo_ast_statement stm; + stm.program = create_(program); + statement_(loc, clingo_ast_statement_type_program, stm); +} + +void ASTBuilder::external(Location const &loc, TermUid head, BdLitVecUid body) { + auto bd = bodies_.erase(body); + clingo_ast_external_t ext; + ext.atom = terms_.erase(head); + ext.body = createArray_(bd); + ext.size = bd.size(); + clingo_ast_statement stm; + stm.external = create_(ext); + statement_(loc, clingo_ast_statement_type_external, stm); +} + +void ASTBuilder::edge(Location const &loc, TermVecVecUid edges, BdLitVecUid body) { + auto bd = bodies_.erase(body); + for (auto &x : termvecvecs_.erase(edges)) { + assert(x.size() == 2); + clingo_ast_edge_t edge; + edge.u = x[0]; + edge.v = x[1]; + edge.size = bd.size(); + edge.body = createArray_(bd); + clingo_ast_statement stm; + stm.location = convertLoc(loc); + stm.type = clingo_ast_statement_type_edge; + stm.edge = create_(edge); + cb_(stm); + } + clear_(); +} + +void ASTBuilder::heuristic(Location const &loc, TermUid termUid, BdLitVecUid body, TermUid a, TermUid b, TermUid mod) { + auto bd = bodies_.erase(body); + clingo_ast_heuristic_t heu; + heu.atom = terms_.erase(termUid); + heu.bias = terms_.erase(a); + heu.priority = terms_.erase(b); + heu.modifier = terms_.erase(mod); + heu.body = createArray_(bd); + heu.size = bd.size(); + clingo_ast_statement stm; + stm.heuristic = create_(heu); + statement_(loc, clingo_ast_statement_type_heuristic, stm); +} + +void ASTBuilder::project(Location const &loc, TermUid termUid, BdLitVecUid body) { + auto bd = bodies_.erase(body); + clingo_ast_project_t proj; + proj.size = bd.size(); + proj.body = createArray_(bd); + proj.atom = terms_.erase(termUid); + clingo_ast_statement stm; + stm.project_atom = create_(proj); + statement_(loc, clingo_ast_statement_type_project_atom, stm); +} + +void ASTBuilder::project(Location const &loc, Sig sig) { + clingo_ast_statement stm; + stm.project_signature = sig.rep(); + statement_(loc, clingo_ast_statement_type_project_atom_signature, stm); +} + +// {{{2 theory atoms + +TheoryTermUid ASTBuilder::theorytermarr_(Location const &loc, TheoryOptermVecUid args, clingo_ast_theory_term_type_t type) { + auto a = theoryOptermVecs_.erase(args); + clingo_ast_theory_term_array_t arr; + arr.size = a.size(); + arr.terms = createArray_(a); + clingo_ast_theory_term_t term; + term.type = type; + term.location = convertLoc(loc); + term.set = create_(arr); + return theoryTerms_.insert(std::move(term)); +} + +TheoryTermUid ASTBuilder::theorytermset(Location const &loc, TheoryOptermVecUid args) { + return theorytermarr_(loc, args, clingo_ast_theory_term_type_set); +} + +TheoryTermUid ASTBuilder::theoryoptermlist(Location const &loc, TheoryOptermVecUid args) { + return theorytermarr_(loc, args, clingo_ast_theory_term_type_list); +} + +TheoryTermUid ASTBuilder::theorytermtuple(Location const &loc, TheoryOptermVecUid args) { + return theorytermarr_(loc, args, clingo_ast_theory_term_type_tuple); +} + +clingo_ast_theory_term_t ASTBuilder::opterm_(Location const &loc, TheoryOptermUid opterm) { + auto terms = theoryOpterms_.erase(opterm); + clingo_ast_theory_unparsed_term arr; + arr.size = terms.size(); + arr.elements = createArray_(terms); + clingo_ast_theory_term_t term; + term.location = convertLoc(loc); + term.type = clingo_ast_theory_term_type_unparsed_term; + term.unparsed_term = create_(arr); + return term; +} + +TheoryTermUid ASTBuilder::theorytermopterm(Location const &loc, TheoryOptermUid opterm) { + return theoryTerms_.insert(opterm_(loc, opterm)); +} + +TheoryTermUid ASTBuilder::theorytermfun(Location const &loc, String name, TheoryOptermVecUid args) { + auto a = theoryOptermVecs_.erase(args); + clingo_ast_theory_function_t fun; + fun.name = name.c_str(); + fun.size = a.size(); + fun.arguments = createArray_(a); + clingo_ast_theory_term_t term; + term.type = clingo_ast_theory_term_type_function; + term.location = convertLoc(loc); + term.function = create_(fun); + return theoryTerms_.insert(std::move(term)); +} + +TheoryTermUid ASTBuilder::theorytermvalue(Location const &loc, Symbol val) { + clingo_ast_theory_term_t term; + term.type = clingo_ast_theory_term_type_symbol; + term.location = convertLoc(loc); + term.symbol = val.rep(); + return theoryTerms_.insert(std::move(term)); +} + +TheoryTermUid ASTBuilder::theorytermvar(Location const &loc, String var) { + clingo_ast_theory_term_t term; + term.type = clingo_ast_theory_term_type_variable; + term.location = convertLoc(loc); + term.variable = var.c_str(); + return theoryTerms_.insert(std::move(term)); +} + +clingo_ast_theory_unparsed_term_element_t ASTBuilder::opterm_(TheoryOpVecUid ops, TheoryTermUid term) { + auto o = theoryOpVecs_.erase(ops); + clingo_ast_theory_unparsed_term_element_t t; + t.size = o.size(); + t.operators = createArray_(o); + t.term = theoryTerms_.erase(term); + return t; +} + +TheoryOptermUid ASTBuilder::theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) { + return theoryOpterms_.insert({opterm_(ops, term)}); +} + +TheoryOptermUid ASTBuilder::theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) { + theoryOpterms_[opterm].emplace_back(opterm_(ops, term)); + return opterm; +} + +TheoryOpVecUid ASTBuilder::theoryops() { + return theoryOpVecs_.emplace(); +} + +TheoryOpVecUid ASTBuilder::theoryops(TheoryOpVecUid ops, String op) { + theoryOpVecs_[ops].emplace_back(op.c_str()); + return ops; +} + +TheoryOptermVecUid ASTBuilder::theoryopterms() { + return theoryOptermVecs_.emplace(); +} + +TheoryOptermVecUid ASTBuilder::theoryopterms(TheoryOptermVecUid opterms, Location const &loc, TheoryOptermUid opterm) { + theoryOptermVecs_[opterms].emplace_back(opterm_(loc, opterm)); + return opterms; +} + +TheoryOptermVecUid ASTBuilder::theoryopterms(Location const &loc, TheoryOptermUid opterm, TheoryOptermVecUid opterms) { + theoryOptermVecs_[opterms].emplace(theoryOptermVecs_[opterms].begin(), opterm_(loc, opterm)); + return opterms; +} + +TheoryElemVecUid ASTBuilder::theoryelems() { + return theoryElems_.emplace(); +} + +TheoryElemVecUid ASTBuilder::theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) { + auto ops = theoryOptermVecs_.erase(opterms); + auto cnd = litvecs_.erase(cond); + clingo_ast_theory_atom_element_t elem; + elem.tuple_size = ops.size(); + elem.tuple = createArray_(ops); + elem.condition_size = cnd.size(); + elem.condition = createArray_(cnd); + theoryElems_[elems].emplace_back(elem); + return elems; +} + +TheoryAtomUid ASTBuilder::theoryatom(TermUid term, TheoryElemVecUid elems) { + auto elms = theoryElems_.erase(elems); + clingo_ast_theory_atom_t atom; + atom.term = terms_.erase(term); + atom.elements = createArray_(elms); + atom.size = elms.size(); + atom.guard = nullptr; + return theoryAtoms_.insert(std::move(atom)); +} + +TheoryAtomUid ASTBuilder::theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &loc, TheoryOptermUid opterm) { + auto elms = theoryElems_.erase(elems); + clingo_ast_theory_guard_t guard; + guard.term = opterm_(loc, opterm); + guard.operator_name = op.c_str(); + clingo_ast_theory_atom_t atom; + atom.term = terms_.erase(term); + atom.elements = createArray_(elms); + atom.size = elms.size(); + atom.guard = create_(guard); + return theoryAtoms_.insert(std::move(atom)); +} + +// {{{2 theory definitions + +TheoryOpDefUid ASTBuilder::theoryopdef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) { + clingo_ast_theory_operator_definition_t def; + def.location = convertLoc(loc); + def.priority = priority; + def.name = op.c_str(); + def.type = static_cast(type); + return theoryOpDefs_.insert(std::move(def)); +} + +TheoryOpDefVecUid ASTBuilder::theoryopdefs() { + return theoryOpDefVecs_.emplace(); +} + +TheoryOpDefVecUid ASTBuilder::theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) { + theoryOpDefVecs_[defs].emplace_back(theoryOpDefs_.erase(def)); + return defs; +} + +TheoryTermDefUid ASTBuilder::theorytermdef(Location const &loc, String name, TheoryOpDefVecUid defs, Logger &) { + auto dfs = theoryOpDefVecs_.erase(defs); + clingo_ast_theory_term_definition_t def; + def.location = convertLoc(loc); + def.name = name.c_str(); + def.operators = createArray_(dfs); + def.size = dfs.size(); + return theoryTermDefs_.insert(std::move(def)); +} + +TheoryAtomDefUid ASTBuilder::theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type) { + clingo_ast_theory_atom_definition_t def; + def.location = convertLoc(loc); + def.name = name.c_str(); + def.arity = arity; + def.elements = termDef.c_str(); + def.type = static_cast(type); + def.guard = nullptr; + return theoryAtomDefs_.insert(std::move(def)); +} + +TheoryAtomDefUid ASTBuilder::theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) { + auto o = theoryOpVecs_.erase(ops); + clingo_ast_theory_guard_definition_t guard; + guard.term = guardDef.c_str(); + guard.operators = createArray_(o); + guard.size = o.size(); + clingo_ast_theory_atom_definition_t def; + def.location = convertLoc(loc); + def.name = name.c_str(); + def.arity = arity; + def.elements = termDef.c_str(); + def.type = static_cast(type); + def.guard = create_(guard); + return theoryAtomDefs_.insert(std::move(def)); +} + +TheoryDefVecUid ASTBuilder::theorydefs() { + return theoryDefVecs_.emplace(); +} + +TheoryDefVecUid ASTBuilder::theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) { + theoryDefVecs_[defs].first.emplace_back(theoryTermDefs_.erase(def)); + return defs; +} + +TheoryDefVecUid ASTBuilder::theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) { + theoryDefVecs_[defs].second.emplace_back(theoryAtomDefs_.erase(def)); + return defs; +} + +void ASTBuilder::theorydef(Location const &loc, String name, TheoryDefVecUid defs, Logger &) { + auto d = theoryDefVecs_.erase(defs); + clingo_ast_theory_definition_t def; + def.name = name.c_str(); + def.terms_size = d.first.size(); + def.terms = createArray_(d.first); + def.atoms_size = d.second.size(); + def.atoms = createArray_(d.second); + clingo_ast_statement stm; + stm.theory_definition = create_(def); + statement_(loc, clingo_ast_statement_type_theory_definition, stm); +} + +// }}}2 + +// {{{1 ast parsing + +namespace { + +struct ASTParser { +public: + ASTParser(Logger &log, INongroundProgramBuilder &prg) + : log_(log), prg_(prg) { } + + // {{{2 statement + + void parse(clingo_ast_statement_t const &stm) { + switch (static_cast(stm.type)) { + case clingo_ast_statement_type_rule: { + auto &y = *stm.rule; + return prg_.rule(parseLocation(stm.location), parseHeadLiteral(y.head), parseBodyLiteralVec(y.body, y.size)); + } + case clingo_ast_statement_type_const: { + auto &y = *stm.definition; + return prg_.define(parseLocation(stm.location), y.name, parseTerm(y.value), y.is_default, log_); + } + case clingo_ast_statement_type_show_signature: { + auto &y = *stm.show_signature; + return prg_.showsig(parseLocation(stm.location), Sig(y.signature), y.csp); + } + case clingo_ast_statement_type_show_term: { + auto &y = *stm.show_term; + return prg_.show(parseLocation(stm.location), parseTerm(y.term), parseBodyLiteralVec(y.body, y.size), y.csp); + } + case clingo_ast_statement_type_minimize: { + auto &y = *stm.minimize; + return prg_.optimize(parseLocation(stm.location), parseTerm(y.weight), parseTerm(y.priority), parseTermVec(y.tuple, y.tuple_size), parseBodyLiteralVec(y.body, y.body_size)); + } + case clingo_ast_statement_type_script: { + auto &y = *stm.script; + switch (y.type) { + case clingo_ast_script_type_python: { return prg_.python(parseLocation(stm.location), y.code); } + case clingo_ast_script_type_lua: { return prg_.lua(parseLocation(stm.location), y.code); } + } + break; + } + case clingo_ast_statement_type_program: { + auto &y = *stm.program; + return prg_.block(parseLocation(stm.location), y.name, parseIdVec(y.parameters, y.size)); + } + case clingo_ast_statement_type_external: { + auto &y = *stm.external; + return prg_.external(parseLocation(stm.location), parseTerm(y.atom), parseBodyLiteralVec(y.body, y.size)); + } + case clingo_ast_statement_type_edge: { + auto &y = *stm.edge; + return prg_.edge(parseLocation(stm.location), prg_.termvecvec(prg_.termvecvec(), prg_.termvec(prg_.termvec(prg_.termvec(), parseTerm(y.u)), parseTerm(y.v))), parseBodyLiteralVec(y.body, y.size)); + } + case clingo_ast_statement_type_heuristic: { + auto &y = *stm.heuristic; + return prg_.heuristic(parseLocation(stm.location), parseTerm(y.atom), parseBodyLiteralVec(y.body, y.size), parseTerm(y.bias), parseTerm(y.priority), parseTerm(y.modifier)); + } + case clingo_ast_statement_type_project_atom: { + auto &y = *stm.project_atom; + return prg_.project(parseLocation(stm.location), parseTerm(y.atom), parseBodyLiteralVec(y.body, y.size)); + } + case clingo_ast_statement_type_project_atom_signature: { + return prg_.project(parseLocation(stm.location), Sig(stm.project_signature)); + } + case clingo_ast_statement_type_theory_definition: { + auto &y = *stm.theory_definition; + return prg_.theorydef(parseLocation(stm.location), y.name, parseTheoryAtomDefinitionVec(parseTheoryTermDefinitionVec(y.terms, y.terms_size), y.atoms, y.atoms_size), log_); + } + } + } + +private: +#define ARR(type, f, g) \ + auto g ## Vec(type const *x, size_t size) -> decltype(std::declval().f()) { \ + return g ## Vec(prg_.f(), x, size);\ + } \ + auto g ## Vec(decltype(std::declval().f()) ret, type const *x, size_t size) -> decltype(std::declval().f()) { \ + for (auto it = x, ie = it + size; it != ie; ++it) { \ + prg_.f(ret, g(*it)); \ + } \ + return ret; \ + } + + bool require_(bool cond, char const *message) { + if (!cond) { fail_(message); } + return false; + } + + template + T fail_(char const *message) { + throw std::runtime_error(message); + } + + Location parseLocation(clingo_location_t const &loc) { + return Location(loc.begin_file, loc.begin_line, loc.begin_column, loc.end_file, loc.end_line, loc.end_column); + } + + // {{{2 terms + + IdVecUid parseIdVec(clingo_ast_id_t const *x, size_t size) { + auto ret = prg_.idvec(); + for (auto it = x, ie = it + size; it != ie; ++it) { + prg_.idvec(ret, parseLocation(it->location), it->id); + } + return ret; + } + + TermUid parseTerm(clingo_ast_term_t const &x) { + switch (static_cast(x.type)) { + case clingo_ast_term_type_symbol: { + return prg_.term(parseLocation(x.location), Symbol(x.symbol)); + } + case clingo_ast_term_type_variable: { + return prg_.term(parseLocation(x.location), x.variable); + } + case clingo_ast_term_type_unary_operation: { + auto &y = *x.unary_operation; + return prg_.term(parseLocation(x.location), static_cast(y.unary_operator), parseTerm(y.argument)); + } + case clingo_ast_term_type_binary_operation: { + auto &y = *x.binary_operation; + return prg_.term(parseLocation(x.location), static_cast(y.binary_operator), parseTerm(y.left), parseTerm(y.right)); + } + case clingo_ast_term_type_interval: { + auto &y = *x.interval; + return prg_.term(parseLocation(x.location), parseTerm(y.left), parseTerm(y.right)); + } + case clingo_ast_term_type_function: + case clingo_ast_term_type_external_function: { + auto &y = *x.function; + require_(y.name[0] != '\0' || x.type != clingo_ast_term_type_external_function, "external functions must have a name"); + return y.name[0] != '\0' + ? prg_.term(parseLocation(x.location), y.name, prg_.termvecvec(prg_.termvecvec(), parseTermVec(y.arguments, y.size)), x.type == clingo_ast_term_type_external_function) + : prg_.term(parseLocation(x.location), parseTermVec(y.arguments, y.size), true); + } + case clingo_ast_term_type_pool: { + auto &y = *x.pool; + return prg_.pool(parseLocation(x.location), parseTermVec(y.arguments, y.size)); + } + } + return static_cast(0); + } + ARR(clingo_ast_term_t, termvec, parseTerm) + + CSPMulTermUid parseCSPMulTerm(clingo_ast_csp_product_term_t const &x) { + return x.variable + ? prg_.cspmulterm(parseLocation(x.location), parseTerm(x.coefficient), parseTerm(*x.variable)) + : prg_.cspmulterm(parseLocation(x.location), parseTerm(x.coefficient)); + } + + CSPAddTermUid parseCSPAddTerm(clingo_ast_csp_sum_term_t const &x) { + require_(x.size > 0, "csp sums terms must not be empty"); + auto it = x.terms, ie = it + x.size; + auto ret = prg_.cspaddterm(parseLocation(x.location), parseCSPMulTerm(*it)); + for (++it; it != ie; ++it) { + ret = prg_.cspaddterm(parseLocation(x.location), ret, parseCSPMulTerm(*it), true); + } + return ret; + } + + TheoryTermUid parseTheoryTerm(clingo_ast_theory_term_t const &x) { + switch (static_cast(x.type)) { + case clingo_ast_theory_term_type_symbol: { + return prg_.theorytermvalue(parseLocation(x.location), Symbol(x.symbol)); + } + case clingo_ast_theory_term_type_variable: { + return prg_.theorytermvar(parseLocation(x.location), x.variable); + } + case clingo_ast_theory_term_type_tuple: { + auto y = *x.tuple; + return prg_.theorytermtuple(parseLocation(x.location), parseTheoryOptermVec(y.terms, y.size)); + } + case clingo_ast_theory_term_type_list: { + auto y = *x.list; + return prg_.theoryoptermlist(parseLocation(x.location), parseTheoryOptermVec(y.terms, y.size)); + } + case clingo_ast_theory_term_type_set: { + auto y = *x.set; + return prg_.theorytermset(parseLocation(x.location), parseTheoryOptermVec(y.terms, y.size)); + } + case clingo_ast_theory_term_type_function: { + auto y = *x.function; + return prg_.theorytermfun(parseLocation(x.location), y.name, parseTheoryOptermVec(y.arguments, y.size)); + } + case clingo_ast_theory_term_type_unparsed_term: { + return prg_.theorytermopterm(parseLocation(x.location), parseTheoryOpterm(*x.unparsed_term)); + } + } + return static_cast(0); + } + + TheoryOptermUid parseTheoryOpterm(clingo_ast_theory_unparsed_term_t const &x) { + require_(x.size > 0, "unparsed term arrays must not be empty"); + auto it = x.elements, ie = it + x.size; + auto ret = prg_.theoryopterm(parseTheoryOpVec(it->operators, it->size), parseTheoryTerm(it->term)); + for (++it; it != ie; ++it) { + require_(it->size > 0, "at least one operator necessary on right-hand-side of unparsed theory term"); + ret = prg_.theoryopterm(ret, parseTheoryOpVec(it->operators, it->size), parseTheoryTerm(it->term)); + } + return ret; + } + + TheoryOptermUid parseTheoryOpterm(clingo_ast_theory_term_t const &x) { + return (x.type == clingo_ast_theory_term_type_unparsed_term) + ? parseTheoryOpterm(*x.unparsed_term) + : prg_.theoryopterm(prg_.theoryops(), parseTheoryTerm(x)); + } + TheoryOptermVecUid parseTheoryOptermVec(clingo_ast_theory_term_t const *vec, size_t size) { + auto ret = prg_.theoryopterms(); + for (auto it = vec, ie = it + size; it != ie; ++it) { + ret = prg_.theoryopterms(ret, parseLocation(it->location), parseTheoryOpterm(*it)); + } + return ret; + } + + // {{{2 literals + + NAF parseSign(enum clingo_ast_sign a, enum clingo_ast_sign b = clingo_ast_sign_none) { + switch (a) { + case clingo_ast_sign_none: { return static_cast(b); } + case clingo_ast_sign_negation: { return static_cast(b == clingo_ast_sign_negation ? clingo_ast_sign_double_negation : clingo_ast_sign_negation); } + case clingo_ast_sign_double_negation: { return static_cast(b == clingo_ast_sign_negation ? clingo_ast_sign_negation : clingo_ast_sign_double_negation); } + } + return static_cast(clingo_ast_sign_none); + } + + LitUid parseLiteral(clingo_ast_literal_t const &x, enum clingo_ast_sign extraSign = clingo_ast_sign_none) { + switch (static_cast(x.type)) { + case clingo_ast_literal_type_boolean: { + return prg_.boollit(parseLocation(x.location), extraSign != clingo_ast_sign_negation ? x.boolean : !x.boolean); + } + case clingo_ast_literal_type_symbolic: { + return prg_.predlit(parseLocation(x.location), parseSign(static_cast(x.sign), extraSign), parseTerm(*x.symbol)); + } + case clingo_ast_literal_type_comparison: { + auto &y = *x.comparison; + Relation rel = static_cast(y.comparison); + if (extraSign == clingo_ast_sign_negation) { rel = neg(rel); } + if (x.sign == clingo_ast_sign_negation) { rel = neg(rel); } + return prg_.rellit(parseLocation(x.location), rel, parseTerm(y.left), parseTerm(y.right)); + } + case clingo_ast_literal_type_csp: { + auto &y = *x.csp_literal; + require_(x.sign == clingo_ast_sign_none && extraSign == clingo_ast_sign_none, "csp literals must not have signs"); + require_(y.size > 0, "csp literals need at least one guard"); + auto it = y.guards, ie = it + y.size; + auto ret = prg_.csplit(parseLocation(x.location), parseCSPAddTerm(y.term), static_cast(it->comparison), parseCSPAddTerm(it->term)); + for (++it; it != ie; ++it) { + ret = prg_.csplit(parseLocation(x.location), ret, static_cast(it->comparison), parseCSPAddTerm(it->term)); + } + return prg_.csplit(ret); + } + } + return static_cast(0); + } + ARR(clingo_ast_literal_t, litvec, parseLiteral) + + // {{{2 aggregates + + BoundVecUid parseBounds(clingo_ast_aggregate_guard_t const *left, clingo_ast_aggregate_guard_t const *right) { + auto ret = prg_.boundvec(); + if (left) { ret = prg_.boundvec(ret, inv(static_cast(left->comparison)), parseTerm(left->term)); } + if (right) { ret = prg_.boundvec(ret, static_cast(right->comparison), parseTerm(right->term)); } + return ret; + } + + CondLitVecUid parseCondLitVec(clingo_ast_conditional_literal_t const *vec, size_t size) { + auto ret = prg_.condlitvec(); + for (auto it = vec, ie = it + size; it != ie; ++it) { + ret = prg_.condlitvec(ret, parseLiteral(it->literal), parseLiteralVec(it->condition, it->size)); + } + return ret; + } + + HdAggrElemVecUid parseHdAggrElemVec(clingo_ast_head_aggregate_element_t const *vec, size_t size) { + auto ret = prg_.headaggrelemvec(); + for (auto it = vec, ie = it + size; it != ie; ++it) { + auto x = it->conditional_literal; + ret = prg_.headaggrelemvec(ret, parseTermVec(it->tuple, it->tuple_size), parseLiteral(x.literal), parseLiteralVec(x.condition, x.size)); + } + return ret; + } + + BdAggrElemVecUid parseBdAggrElemVec(clingo_ast_body_aggregate_element_t const *vec, size_t size) { + auto ret = prg_.bodyaggrelemvec(); + for (auto it = vec, ie = it + size; it != ie; ++it) { + ret = prg_.bodyaggrelemvec(ret, parseTermVec(it->tuple, it->tuple_size), parseLiteralVec(it->condition, it->condition_size)); + } + return ret; + } + + TheoryElemVecUid parseTheoryElemVec(clingo_ast_theory_atom_element_t const *vec, size_t size) { + auto ret = prg_.theoryelems(); + for (auto it = vec, ie = it + size; it != ie; ++it) { + ret = prg_.theoryelems(ret, parseTheoryOptermVec(it->tuple, it->tuple_size), parseLiteralVec(it->condition, it->condition_size)); + } + return ret; + } + + CSPElemVecUid parseCSPElemVec(clingo_ast_disjoint_element_t const *vec, size_t size) { + auto ret = prg_.cspelemvec(); + for (auto it = vec, ie = it + size; it != ie; ++it) { + ret = prg_.cspelemvec(ret, parseLocation(it->location), parseTermVec(it->tuple, it->tuple_size), parseCSPAddTerm(it->term), parseLiteralVec(it->condition, it->condition_size)); + } + return ret; + } + + // {{{2 heads + + HdLitUid parseHeadLiteral(clingo_ast_head_literal_t const &x) { + switch (static_cast(x.type)) { + case clingo_ast_head_literal_type_literal: { + return prg_.headlit(parseLiteral(*x.literal)); + } + case clingo_ast_head_literal_type_disjunction: { + auto &y = *x.disjunction; + return prg_.disjunction(parseLocation(x.location), parseCondLitVec(y.elements, y.size)); + } + case clingo_ast_head_literal_type_aggregate: { + auto &y = *x.aggregate; + return prg_.headaggr(parseLocation(x.location), AggregateFunction::COUNT, parseBounds(y.left_guard, y.right_guard), parseCondLitVec(y.elements, y.size)); + } + case clingo_ast_head_literal_type_head_aggregate: { + auto &y = *x.head_aggregate; + return prg_.headaggr(parseLocation(x.location), static_cast(y.function), parseBounds(y.left_guard, y.right_guard), parseHdAggrElemVec(y.elements, y.size)); + } + case clingo_ast_head_literal_type_theory_atom: { + auto &y = *x.theory_atom; + return y.guard + ? prg_.headaggr(parseLocation(x.location), prg_.theoryatom(parseTerm(y.term), parseTheoryElemVec(y.elements, y.size), y.guard->operator_name, parseLocation(x.location), parseTheoryOpterm(y.guard->term))) + : prg_.headaggr(parseLocation(x.location), prg_.theoryatom(parseTerm(y.term), parseTheoryElemVec(y.elements, y.size))); + } + } + return static_cast(0); + } + + // {{{2 bodies + + BdLitVecUid parseBodyLiteralVec(clingo_ast_body_literal_t const *lit, size_t size) { + auto ret = prg_.body(); + for (auto it = lit, ie = lit + size; it != ie; ++it) { + switch (static_cast(it->type)) { + case clingo_ast_body_literal_type_literal: { + ret = prg_.bodylit(ret, parseLiteral(*it->literal, static_cast(it->sign))); + break; + } + case clingo_ast_body_literal_type_conditional: { + require_(static_cast(it->sign) == NAF::POS, "conditional literals must hot have a sign"); + auto &y = *it->conditional; + ret = prg_.conjunction(ret, parseLocation(it->location), parseLiteral(y.literal), parseLiteralVec(y.condition, y.size)); + break; + } + case clingo_ast_body_literal_type_aggregate: { + auto &y = *it->aggregate; + ret = prg_.bodyaggr(ret, parseLocation(it->location), static_cast(it->sign), AggregateFunction::COUNT, parseBounds(y.left_guard, y.right_guard), parseCondLitVec(y.elements, y.size)); + break; + } + case clingo_ast_body_literal_type_body_aggregate: { + auto &y = *it->body_aggregate; + ret = prg_.bodyaggr(ret, parseLocation(it->location), static_cast(it->sign), static_cast(y.function), parseBounds(y.left_guard, y.right_guard), parseBdAggrElemVec(y.elements, y.size)); + break; + } + case clingo_ast_body_literal_type_theory_atom: { + auto &y = *it->theory_atom; + ret = y.guard + ? prg_.bodyaggr(ret, parseLocation(it->location), static_cast(it->sign), prg_.theoryatom(parseTerm(y.term), parseTheoryElemVec(y.elements, y.size), y.guard->operator_name, parseLocation(it->location), parseTheoryOpterm(y.guard->term))) + : prg_.bodyaggr(ret, parseLocation(it->location), static_cast(it->sign), prg_.theoryatom(parseTerm(y.term), parseTheoryElemVec(y.elements, y.size))); + break; + } + case clingo_ast_body_literal_type_disjoint: { + auto &y = *it->disjoint; + ret = prg_.disjoint(ret, parseLocation(it->location), static_cast(it->sign), parseCSPElemVec(y.elements, y.size)); + break; + } + } + } + return ret; + } + + // {{{2 theory definitions + + String parseTheoryOp(char const *str) { return str; } + ARR(char const *, theoryops, parseTheoryOp) + + TheoryOpDefUid parseTheoryOpDef(clingo_ast_theory_operator_definition_t const &x) { + return prg_.theoryopdef(parseLocation(x.location), x.name, x.priority, static_cast(x.type)); + } + ARR(clingo_ast_theory_operator_definition_t, theoryopdefs, parseTheoryOpDef) + + TheoryAtomDefUid parseTheoryAtomDefinition(clingo_ast_theory_atom_definition_t const &x) { + return x.guard + ? prg_.theoryatomdef(parseLocation(x.location), x.name, x.arity, x.elements, static_cast(x.type), parseTheoryOpVec(x.guard->operators, x.guard->size), x.guard->term) + : prg_.theoryatomdef(parseLocation(x.location), x.name, x.arity, x.elements, static_cast(x.type)); + } + ARR(clingo_ast_theory_atom_definition_t, theorydefs, parseTheoryAtomDefinition) + + TheoryTermDefUid parseTheoryTermDefinition(clingo_ast_theory_term_definition_t const &x) { + return prg_.theorytermdef(parseLocation(x.location), x.name, parseTheoryOpDefVec(x.operators, x.size), log_); + } + ARR(clingo_ast_theory_term_definition_t, theorydefs, parseTheoryTermDefinition) + + // }}}2 +#undef ARR +private: + Logger &log_; + INongroundProgramBuilder &prg_; +}; + +} + +void parseStatement(INongroundProgramBuilder &prg, Logger &log, clingo_ast_statement_t const &stm) { + ASTParser p(log, prg); + p.parse(stm); +} + +// }}}1 + +} } // namespace Input Gringo + diff --git a/libgringo/src/input/statement.cc b/libgringo/src/input/statement.cc new file mode 100644 index 0000000..ae7d98c --- /dev/null +++ b/libgringo/src/input/statement.cc @@ -0,0 +1,320 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/bug.hh" +#include "gringo/input/statement.hh" +#include "gringo/input/literals.hh" +#include "gringo/input/aggregates.hh" +#include "gringo/ground/statements.hh" +#include "gringo/safetycheck.hh" + +#include + +namespace Gringo { namespace Input { + +// {{{ definition of Statement::Statement + +Statement::Statement(UHeadAggr &&head, UBodyAggrVec &&body, StatementType type) + : head(std::move(head)) + , body(std::move(body)) + , type(type) { } + +// }}} + +void Statement::initTheory(TheoryDefs &def, Logger &log) { + head->initTheory(def, !body.empty(), log); + for (auto &lit : body) { + lit->initTheory(def, log); + } +} +void Statement::getNeg(std::function f) const { + head->getNeg(f); +} + +// {{{ definition of Statement::add + +void Statement::add(ULit &&lit) { + Location loc(lit->loc()); + body.emplace_back(make_locatable(loc, std::move(lit))); +} + +// }}} +// {{{ definition of Statement::print + +void Statement::print(std::ostream &out) const { + if (type != StatementType::WEAKCONSTRAINT) { + if (type == StatementType::EXTERNAL) { out << "#external "; } + if (head) { out << *head; } + if (!body.empty()) { + out << (type == StatementType::EXTERNAL ? ":" : ":-"); + auto f = [](std::ostream &out, UBodyAggr const &x) { out << *x; }; + print_comma(out, body, ";", f); + } + out << "."; + } + else { + out << ":~"; + print_comma(out, body, ";", [](std::ostream &out, UBodyAggr const &x) { out << *x; }); + out << "."; + head->print(out); + } +} + +// }}} +// {{{ definition of Statement::isEDB + +Symbol Statement::isEDB() const { return type == StatementType::RULE && body.empty() ? head->isEDB() : Symbol(); } + +// }}} +// {{{ definition of Statement::unpool + +UStmVec Statement::unpool(bool beforeRewrite) { + std::vector bodies; + if (beforeRewrite) { + Term::unpool(body.begin(), body.end(), + [] (UBodyAggr &x) -> UBodyAggrVec { + UBodyAggrVec body; + x->unpool(body, true); + return body; + }, [&bodies](UBodyAggrVec &&x) { bodies.push_back(std::move(x)); }); + } + else { + bodies.emplace_back(); + for (auto &y : body) { + y->unpool(bodies.back(), beforeRewrite); + } + } + UHeadAggrVec heads; + head->unpool(heads, beforeRewrite); + UStmVec x; + for (auto &body : bodies) { + for (auto &head : heads) { + x.emplace_back(make_locatable(loc(), get_clone(head), get_clone(body), type)); + } + } + return x; +} + +// }}} +// {{{ definition of Statement::hasPool + +bool Statement::hasPool(bool beforeRewrite) const { + for (auto &x : body) { if (x->hasPool(beforeRewrite)) { return true; } } + return head->hasPool(beforeRewrite); +} + +// }}} +// {{{ definition of Statement::rewrite1 + +bool Statement::rewrite1(Projections &project, Logger &log) { + SimplifyState state; + if (!head->simplify(project, state, log)) { return false; } + bool singleton = std::accumulate(body.begin(), body.end(), 0, [](unsigned x, UBodyAggr const &y){ return x + y->projectScore(); }) == 1 && head->isPredicate(); + for (auto &y : body) { + if (!y->simplify(project, state, singleton, log)) { return false; } + } + for (auto &y : state.dots) { body.emplace_back(gringo_make_unique(RangeLiteral::make(y))); } + for (auto &y : state.scripts) { body.emplace_back(gringo_make_unique(ScriptLiteral::make(y))); } + return true; +} + +// }}} +// {{{ definition of Statement::rewrite2 + +namespace { + +void _rewriteAggregates(UBodyAggrVec &body) { + UBodyAggrVec aggr; + auto jt = body.begin(); + for (auto it = jt, ie = body.end(); it != ie; ++it) { + if ((*it)->rewriteAggregates(aggr)) { + if (it != jt) { *jt = std::move(*it); } + ++jt; + } + } + body.erase(jt, body.end()); + std::move(aggr.begin(), aggr.end(), std::back_inserter(body)); +} + +// TODO: this code has to be adjusted +// the toGround code then has to take an additional argument +// to only create aggregate literals up to an index +// EXAMPLE: +// h :- B, { c1 }, { c2 }. +// a1 :- B*, c1. % accumulation rule +// a2 :- B*, a1*, c2. % accumulation rule +// % TODO: add complete rules... +// h :- B, a1, a2. +// + +void _rewriteAssignments(UBodyAggrVec &body) { + using LitDep = SafetyChecker; + using VarMap = std::unordered_map; + LitDep dep; + VarMap map; + for (auto &y : body) { + auto &ent = dep.insertEnt(std::move(y)); + VarTermBoundVec vars; + ent.data->collect(vars); + for (auto &occ : vars) { + if (occ.first->level == 0) { + auto &var(map[occ.first->name]); + if (!var) { var = &dep.insertVar(occ.first); } + if (occ.second) { dep.insertEdge(ent, *var); } + else { dep.insertEdge(*var, ent); } + } + } + } + LitDep::VarVec bound; + LitDep::EntVec open; + open.reserve(body.size()); // Note: keeps iterators valid + body.clear(); + dep.init(open); + UBodyAggrVec sorted; + for (auto it = open.begin(); it != open.end(); ) { + LitDep::EntVec assign; + for (; it != open.end(); ++it) { + if (!(*it)->data->isAssignment()) { + dep.propagate(*it, open, &bound); + sorted.emplace_back(std::move((*it)->data)); + } + else { assign.emplace_back(*it); } + } + LitDep::EntVec nextAssign; + while (!assign.empty()) { + for (auto &x : assign) { + bool allBound = true; + for (auto &y : x->provides) { + if (!y->bound) { + allBound = false; + break; + } + } + if (!allBound) { nextAssign.emplace_back(x); } + else { + x->data->removeAssignment(); + dep.propagate(x, open, &bound); + sorted.emplace_back(std::move(x->data)); + } + } + if (!nextAssign.empty()) { + dep.propagate(nextAssign.back(), open, &bound); + sorted.emplace_back(std::move(nextAssign.back()->data)); + nextAssign.pop_back(); + } + assign = std::move(nextAssign); + } + } + for (auto &x : dep.entNodes_) { + if (x.depends > 0) { sorted.emplace_back(std::move(x.data)); } + } + // dep.entNodes_; + body = std::move(sorted); +} + +} // namespace + +void Statement::rewrite2() { + AuxGen auxGen; + { // rewrite aggregates + Term::replace(head, head->rewriteAggregates(body)); + _rewriteAggregates(body); + } + { // assign levels + AssignLevel c; + head->assignLevels(c); + for (auto &y : body) { y->assignLevels(c); } + c.assignLevels(); + } + { // rewrite arithmetics + Term::ArithmeticsMap arith; + Literal::AssignVec assign; + arith.emplace_back(); + head->rewriteArithmetics(arith, auxGen); + for (auto &y : body) { y->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { body.emplace_back(gringo_make_unique(RelationLiteral::make(y))); } + for (auto &y : assign) { body.emplace_back(gringo_make_unique(RelationLiteral::make(y))); } + arith.pop_back(); + } + _rewriteAssignments(body); +} + +// }}} +// {{{ definition of Statement::check + +void Statement::check(Logger &log) const { + ChkLvlVec levels; + levels.emplace_back(loc(), *this); + head->check(levels, log); + for (auto &y : body) { y->check(levels, log); } + levels.back().check(log); +} + +// }}} +// {{{ definition of Statement::replace + +void Statement::replace(Defines &x) { + head->replace(x); + for (auto &y : body) { y->replace(x); } +} + +// }}} +// {{{ definition of Statement::toGround + +namespace { + +void toGround(CreateHead &&head, UBodyAggrVec const &body, ToGroundArg &x, Ground::UStmVec &stms) { + CreateBodyVec createVec; + for (auto &y : body) { createVec.emplace_back(y->toGround(x, stms)); } + Ground::ULitVec lits; + for (auto current = createVec.begin(), end = createVec.end(); current != end; ++current) { + current->first(lits, true, false); + for (auto &z : current->second) { + Ground::ULitVec splitLits; + for (auto it = createVec.begin(); it != end; ++it) { + if (it != current) { it->first(splitLits, it < current, true); } + } + stms.emplace_back(z(std::move(splitLits))); + } + } + stms.emplace_back(head(std::move(lits))); +} + +} // namespace + +void Statement::toGround(ToGroundArg &x, Ground::UStmVec &stms) const { + Ground::RuleType t = Ground::RuleType::Disjunctive; + switch (type) { + case StatementType::EXTERNAL: { t = Ground::RuleType::External; break; } + case StatementType::WEAKCONSTRAINT: // t is ignored later + case StatementType::RULE: { t = Ground::RuleType::Disjunctive; break; } + } + Gringo::Input::toGround(head->toGround(x, stms, t), body, x, stms); +} + +// }}} +// {{{ definition of Statement::~Statement + +Statement::~Statement() { } + +// }}} + +} } // namespace Input Gringo + diff --git a/libgringo/src/input/theory.cc b/libgringo/src/input/theory.cc new file mode 100644 index 0000000..6cd6f22 --- /dev/null +++ b/libgringo/src/input/theory.cc @@ -0,0 +1,574 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include +#include +#include + +namespace Gringo { namespace Input { + +// {{{1 definition of TheoryElement + +TheoryElement::TheoryElement(Output::UTheoryTermVec &&tuple, ULitVec &&cond) +: tuple_(std::move(tuple)) +, cond_(std::move(cond)) +{ } + +TheoryElement::TheoryElement(TheoryElement &&) = default; + +TheoryElement &TheoryElement::operator=(TheoryElement &&) = default; + +TheoryElement::~TheoryElement() noexcept = default; + +bool TheoryElement::operator==(TheoryElement const &other) const { + return is_value_equal_to(tuple_, other.tuple_) && is_value_equal_to(cond_, other.cond_); +} + +void TheoryElement::print(std::ostream &out) const { + if (tuple_.empty() && cond_.empty()) { + out << " : "; + } + else { + print_comma(out, tuple_, ",", [](std::ostream &out, Output::UTheoryTerm const &term) { term->print(out); }); + if (!cond_.empty()) { + out << ": "; + print_comma(out, cond_, ",", [](std::ostream &out, ULit const &lit) { lit->print(out); }); + } + } +} + +size_t TheoryElement::hash() const { + return get_value_hash(tuple_, cond_); +} + +void TheoryElement::unpool(TheoryElementVec &elems, bool beforeRewrite) { + Term::unpool(cond_.begin(), cond_.end(), [beforeRewrite](ULit &lit) { + return lit->unpool(beforeRewrite); + }, [&](ULitVec &&cond) { + elems.emplace_back(get_clone(tuple_), std::move(cond)); + }); +} + +TheoryElement TheoryElement::clone() const { + return {get_clone(tuple_), get_clone(cond_)}; +} + +bool TheoryElement::hasPool(bool beforeRewrite) const { + for (auto &lit : cond_) { + if (lit->hasPool(beforeRewrite)) { return true; } + } + return false; +} + +void TheoryElement::replace(Defines &x) { + for (auto &term : tuple_) { + term->replace(x); + } + for (auto &lit : cond_) { + lit->replace(x); + } +} + +void TheoryElement::collect(VarTermBoundVec &vars) const { + for (auto &term : tuple_) { term->collect(vars); } + for (auto &lit : cond_) { lit->collect(vars, false); } +} + +void TheoryElement::assignLevels(AssignLevel &lvl) { + AssignLevel &local(lvl.subLevel()); + VarTermBoundVec vars; + for (auto &term : tuple_) { term->collect(vars); } + for (auto &lit : cond_) { lit->collect(vars, true); } + local.add(vars); +} + +void TheoryElement::check(Location const &loc, Printable const &p, ChkLvlVec &levels, Logger &log) const { + levels.emplace_back(loc, p); + for (auto &lit : cond_) { + levels.back().current = &levels.back().dep.insertEnt(); + VarTermBoundVec vars; + lit->collect(vars, true); + addVars(levels, vars); + } + VarTermBoundVec vars; + levels.back().current = &levels.back().dep.insertEnt(); + for (auto &term : tuple_) { + term->collect(vars); + } + addVars(levels, vars); + levels.back().check(log); + levels.pop_back(); +} + +bool TheoryElement::simplify(Projections &project, SimplifyState &state, Logger &log) { + for (auto &lit : cond_) { + if (!lit->simplify(log, project, state, true, true)) { + return false; + } + } + for (auto &dot : state.dots) { cond_.emplace_back(RangeLiteral::make(dot)); } + for (auto &script : state.scripts) { cond_.emplace_back(ScriptLiteral::make(script)); } + return true; +} + +void TheoryElement::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + Literal::AssignVec assign; + arith.emplace_back(); + for (auto &lit : cond_) { lit->rewriteArithmetics(arith, assign, auxGen); } + for (auto &y : arith.back()) { cond_.emplace_back(RelationLiteral::make(y)); } + for (auto &y : assign) { cond_.emplace_back(RelationLiteral::make(y)); } + arith.pop_back(); +} + +void TheoryElement::initTheory(Output::TheoryParser &p, Logger &log) { + for (auto &term : tuple_) { + Term::replace(term, term->initTheory(p, log)); + } +} + +std::unique_ptr TheoryElement::toGround(ToGroundArg &x, Ground::TheoryComplete &completeRef, Ground::ULitVec &&lits) const { + for (auto &z : cond_) { lits.emplace_back(z->toGround(x.domains, false)); } + return gringo_make_unique(completeRef, get_clone(tuple_), std::move(lits)); +} + +// {{{1 definition of TheoryAtom + +TheoryAtom::TheoryAtom(UTerm &&name, TheoryElementVec &&elems) +: name_(std::move(name)) +, elems_(std::move(elems)) +, op_("") +, guard_(nullptr) +{ } + +TheoryAtom::TheoryAtom(TheoryAtom &&) = default; + +TheoryAtom &TheoryAtom::operator=(TheoryAtom &&) = default; + +TheoryAtom::TheoryAtom(UTerm &&name, TheoryElementVec &&elems, String op, Output::UTheoryTerm &&guard, TheoryAtomType type) +: name_(std::move(name)) +, elems_(std::move(elems)) +, op_(op) +, guard_(std::move(guard)) +, type_(type) +{ } + +TheoryAtom TheoryAtom::clone() const { + return { get_clone(name_), get_clone(elems_), op_, hasGuard() ? get_clone(guard_) : nullptr, type_ }; +} + +bool TheoryAtom::hasGuard() const { + return static_cast(guard_); +} + +bool TheoryAtom::operator==(TheoryAtom const &other) const { + bool ret = is_value_equal_to(name_, other.name_) && is_value_equal_to(elems_, other.elems_) && hasGuard() == other.hasGuard(); + if (ret && hasGuard()) { + ret = op_ == other.op_ && is_value_equal_to(guard_, other.guard_); + } + return ret; +} + +void TheoryAtom::print(std::ostream &out) const { + out << "&"; + name_->print(out); + out << "{"; + print_comma(out, elems_, ";"); + out << "}"; + if (hasGuard()) { + out << op_; + guard_->print(out); + } +} + +size_t TheoryAtom::hash() const { + size_t hash = get_value_hash(name_, elems_); + if (hasGuard()) { + hash = get_value_hash(hash, op_, guard_); + } + return hash; +} + +template +void TheoryAtom::unpool(T f, bool beforeRewrite) { + TheoryElementVec elems; + for (auto &elem : elems_) { + elem.unpool(elems, beforeRewrite); + } + UTermVec names; + name_->unpool(names); + for (auto &name : names) { + f(TheoryAtom(std::move(name), get_clone(elems), op_, guard_ ? get_clone(guard_) : nullptr)); + } +} + +bool TheoryAtom::hasPool(bool beforeRewrite) const { + if (beforeRewrite && name_->hasPool()) { return true; } + for (auto &elem : elems_) { + if (elem.hasPool(beforeRewrite)) { return true; } + } + return false; +} + +void TheoryAtom::replace(Defines &x) { + Term::replace(name_, name_->replace(x, true)); + for (auto &elem : elems_) { + elem.replace(x); + } + if (hasGuard()) { guard_->replace(x); } +} + +void TheoryAtom::collect(VarTermBoundVec &vars) const { + name_->collect(vars, false); + if (hasGuard()) { guard_->collect(vars); } + for (auto &elem : elems_) { elem.collect(vars); } +} + +void TheoryAtom::assignLevels(AssignLevel &lvl) { + VarTermBoundVec vars; + name_->collect(vars, false); + if (hasGuard()) { guard_->collect(vars); } + lvl.add(vars); + for (auto &elem : elems_) { + elem.assignLevels(lvl); + } +} + +void TheoryAtom::check(Location const &loc, Printable const &p, ChkLvlVec &levels, Logger &log) const { + levels.back().current = &levels.back().dep.insertEnt(); + + VarTermBoundVec vars; + name_->collect(vars, false); + if (hasGuard()) { guard_->collect(vars); } + addVars(levels, vars); + + for (auto &elem : elems_) { + elem.check(loc, p, levels, log); + } +} + +bool TheoryAtom::simplify(Projections &project, SimplifyState &state, Logger &log) { + if (name_->simplify(state, false, false, log).update(name_).undefined()) { + return false; + } + for (auto &elem : elems_) { + SimplifyState elemState(state); + if (!elem.simplify(project, elemState, log)) { + return false; + } + } + return true; +} + +void TheoryAtom::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + for (auto &elem : elems_) { + elem.rewriteArithmetics(arith, auxGen); + } +} + +void TheoryAtom::initTheory(Location const &loc, TheoryDefs &defs, bool inBody, bool hasBody, Logger &log) { + Sig sig = name_->getSig(); + for (auto &def : defs) { + if (auto atomDef = def.getAtomDef(sig)) { + type_ = atomDef->type(); + if (inBody) { + if (type_ == TheoryAtomType::Head) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: theory body atom used in head:" << "\n" + << " " << sig << "\n"; + return; + } + else if (type_ == TheoryAtomType::Directive) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: theory directive used in body:" << "\n" + << " " << sig << "\n"; + return; + } + } + else { + if (type_ == TheoryAtomType::Body) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: theory head atom used in body:" << "\n" + << " " << sig << "\n"; + return; + } + if (type_ == TheoryAtomType::Directive && hasBody) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: theory directive used with body:" << "\n" + << " " << sig << "\n"; + return; + } + } + if (inBody) { + type_ = TheoryAtomType::Body; + } + else if (type_ != TheoryAtomType::Directive) { + type_ = TheoryAtomType::Head; + } + if (auto termDef = def.getTermDef(atomDef->elemDef())) { + Output::TheoryParser p(loc, *termDef); + for (auto &elem : elems_) { + elem.initTheory(p, log); + } + } + else { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: missing definition for term:" << "\n" + << " " << atomDef->elemDef() << "\n"; + } + if (hasGuard()) { + if (!atomDef->hasGuard()) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: unexpected guard:" << "\n" + << " " << sig << "\n"; + } + else if (auto termDef = def.getTermDef(atomDef->guardDef())) { + if (std::find(atomDef->ops().begin(), atomDef->ops().end(), op_) != atomDef->ops().end()) { + Output::TheoryParser p(loc, *termDef); + Term::replace(guard_, guard_->initTheory(p, log)); + } + else { + std::stringstream ss; + print_comma(ss, atomDef->ops(), ","); + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: unexpected operator:" << "\n" + << " " << op_ << "\n" + << loc << ": note: expected one of:\n" + << " " << ss.str() << "\n"; + } + } + else { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: missing definition for term:" << "\n" + << " " << atomDef->guardDef() << "\n"; + } + } + return; + } + } + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: no definition found for theory atom:" << "\n" + << " " << sig << "\n"; +} + +CreateHead TheoryAtom::toGroundHead() const { + return CreateHead([&](Ground::ULitVec &&lits) { + for (auto &x : lits) { + auto lit = dynamic_cast(x.get()); + if (lit && lit->auxiliary()) { + return gringo_make_unique(*lit, std::move(lits)); + } + } + throw std::logic_error("must not happen"); + }); +} + +CreateBody TheoryAtom::toGroundBody(ToGroundArg &x, Ground::UStmVec &stms, NAF naf, UTerm &&id) const { + if (hasGuard()) { + stms.emplace_back(gringo_make_unique(x.domains, std::move(id), type_, get_clone(name_), op_, get_clone(guard_))); + } + else { + stms.emplace_back(gringo_make_unique(x.domains, std::move(id), type_, get_clone(name_))); + } + auto &completeRef = static_cast(*stms.back()); + CreateStmVec split; + split.emplace_back([&completeRef, this](Ground::ULitVec &&lits) -> Ground::UStm { + auto ret = gringo_make_unique(completeRef, std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + for (auto &y : elems_) { + split.emplace_back([this,&completeRef,&y,&x](Ground::ULitVec &&lits) -> Ground::UStm { + auto ret = y.toGround(x, completeRef, std::move(lits)); + completeRef.addAccuDom(*ret); + return std::move(ret); + }); + } + bool aux1 = type_ != TheoryAtomType::Body; + return CreateBody([this, &completeRef, naf, aux1](Ground::ULitVec &lits, bool primary, bool aux2) { + if (primary) { + auto ret = gringo_make_unique(completeRef, naf, aux1 || aux2); + lits.emplace_back(std::move(ret)); + } + }, std::move(split)); +} + +TheoryAtom::~TheoryAtom() noexcept = default; + +// {{{1 definition of HeadTheoryLiteral + +HeadTheoryLiteral::HeadTheoryLiteral(TheoryAtom &&atom, bool rewritten) +: atom_(std::move(atom)) +, rewritten_(rewritten) +{ } + +HeadTheoryLiteral::~HeadTheoryLiteral() noexcept = default; + +CreateHead HeadTheoryLiteral::toGround(ToGroundArg &, Ground::UStmVec &, Ground::RuleType) const { + return atom_.toGroundHead(); +} + +UHeadAggr HeadTheoryLiteral::rewriteAggregates(UBodyAggrVec &lits) { + rewritten_ = true; + auto lit = make_locatable(loc(), NAF::POS, atom_.clone(), rewritten_); + lits.emplace_back(std::move(lit)); + return nullptr; +} + +void HeadTheoryLiteral::collect(VarTermBoundVec &vars) const { + atom_.collect(vars); +} + +void HeadTheoryLiteral::unpool(UHeadAggrVec &x, bool beforeRewrite) { + atom_.unpool([&](TheoryAtom &&atom) { x.emplace_back(make_locatable(loc(), std::move(atom))); }, beforeRewrite); +} + +bool HeadTheoryLiteral::simplify(Projections &project, SimplifyState &state, Logger &log) { + return atom_.simplify(project, state, log); +} + +void HeadTheoryLiteral::assignLevels(AssignLevel &lvl) { + atom_.assignLevels(lvl); +} + +void HeadTheoryLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + atom_.rewriteArithmetics(arith, auxGen); +} + +bool HeadTheoryLiteral::hasPool(bool beforeRewrite) const { + return atom_.hasPool(beforeRewrite); +} + +void HeadTheoryLiteral::check(ChkLvlVec &lvl, Logger &log) const { + atom_.check(loc(), *this, lvl, log); +} + +void HeadTheoryLiteral::replace(Defines &x) { + atom_.replace(x); +} + +size_t HeadTheoryLiteral::hash() const { + return atom_.hash(); +} + +void HeadTheoryLiteral::print(std::ostream &out) const { + if (rewritten_) { out << "#false"; } + else { atom_.print(out); } +} + +HeadTheoryLiteral *HeadTheoryLiteral::clone() const { + auto ret = make_locatable(loc(), get_clone(atom_), rewritten_).release(); + return ret; +} + +bool HeadTheoryLiteral::operator==(HeadAggregate const &other) const { + auto t = dynamic_cast(&other); + return t && atom_ == t->atom_; +} + +void HeadTheoryLiteral::initTheory(TheoryDefs &defs, bool hasBody, Logger &log) { + atom_.initTheory(loc(), defs, false, hasBody, log); +} + +void HeadTheoryLiteral::getNeg(std::function) const { } + +// {{{1 definition of BodyTheoryLiteral + +BodyTheoryLiteral::BodyTheoryLiteral(NAF naf, TheoryAtom &&atom, bool rewritten) +: atom_(std::move(atom)) +, naf_(naf) +, rewritten_(rewritten) +{ } + +BodyTheoryLiteral::~BodyTheoryLiteral() noexcept = default; + +void BodyTheoryLiteral::unpool(UBodyAggrVec &x, bool beforeRewrite) { + atom_.unpool([&](TheoryAtom &&atom) { x.emplace_back(make_locatable(loc(), naf_, std::move(atom))); }, beforeRewrite); +} + +bool BodyTheoryLiteral::simplify(Projections &project, SimplifyState &state, bool, Logger &log) { + return atom_.simplify(project, state, log); +} + +void BodyTheoryLiteral::assignLevels(AssignLevel &lvl) { + atom_.assignLevels(lvl); +} + +void BodyTheoryLiteral::check(ChkLvlVec &lvl, Logger &log) const { + atom_.check(loc(), *this, lvl, log); +} + +void BodyTheoryLiteral::rewriteArithmetics(Term::ArithmeticsMap &arith, Literal::AssignVec &, AuxGen &auxGen) { + atom_.rewriteArithmetics(arith, auxGen); +} + +bool BodyTheoryLiteral::rewriteAggregates(UBodyAggrVec &) { + return true; +} + +void BodyTheoryLiteral::removeAssignment() { +} + +bool BodyTheoryLiteral::isAssignment() const { + return false; +} + +void BodyTheoryLiteral::collect(VarTermBoundVec &vars) const { + atom_.collect(vars); +} + +bool BodyTheoryLiteral::hasPool(bool beforeRewrite) const { + return atom_.hasPool(beforeRewrite); +} + +void BodyTheoryLiteral::replace(Defines &x) { + atom_.replace(x); +} + +CreateBody BodyTheoryLiteral::toGround(ToGroundArg &x, Ground::UStmVec &stms) const { + return atom_.toGroundBody(x, stms, naf_, x.newId(*this)); +} + +size_t BodyTheoryLiteral::hash() const { + return get_value_hash(typeid(BodyTheoryLiteral).hash_code(), naf_, atom_); +} + +void BodyTheoryLiteral::print(std::ostream &out) const { + if (rewritten_) { out << "not " << atom_; } + else { out << naf_ << atom_; } +} + +BodyTheoryLiteral *BodyTheoryLiteral::clone() const { + return make_locatable(loc(), naf_, get_clone(atom_), rewritten_).release(); +} + +bool BodyTheoryLiteral::operator==(BodyAggregate const &other) const { + auto t = dynamic_cast(&other); + return t && naf_ == t->naf_ && atom_ == t->atom_; +} + +void BodyTheoryLiteral::initTheory(TheoryDefs &defs, Logger &log) { + atom_.initTheory(loc(), defs, true, true, log); +} + +// }}}1 + +} } // namespace Gringo Input + diff --git a/libgringo/src/lua.cc b/libgringo/src/lua.cc new file mode 100644 index 0000000..23634cc --- /dev/null +++ b/libgringo/src/lua.cc @@ -0,0 +1,2752 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifdef WITH_LUA + +#include "gringo/lua.hh" +#include "gringo/version.hh" +#include "gringo/logger.hh" +#include "gringo/control.hh" +#include "potassco/clingo.h" + +#include +#include + +namespace Gringo { + +namespace { + +// {{{1 auxiliary functions + +#define VALUE_CMP(TYPE) \ +static int eq##TYPE(lua_State *L) { \ + Symbol *a = static_cast(luaL_checkudata(L, 1, "clingo."#TYPE)); \ + Symbol *b = static_cast(luaL_checkudata(L, 2, "clingo."#TYPE)); \ + lua_pushboolean(L, *a == *b); \ + return 1; \ +} \ +static int lt##TYPE(lua_State *L) { \ + Symbol *a = static_cast(luaL_checkudata(L, 1, "clingo."#TYPE)); \ + Symbol *b = static_cast(luaL_checkudata(L, 2, "clingo."#TYPE)); \ + lua_pushboolean(L, *a < *b); \ + return 1; \ +} \ +static int le##TYPE(lua_State *L) { \ + Symbol *a = static_cast(luaL_checkudata(L, 1, "clingo."#TYPE)); \ + Symbol *b = static_cast(luaL_checkudata(L, 2, "clingo."#TYPE)); \ + lua_pushboolean(L, *a <= *b); \ + return 1; \ +} + +template +auto protect(lua_State *L, T f) -> decltype(f()) { + try { return f(); } + catch (std::exception const &e) { luaL_error(L, e.what()); } + catch (...) { luaL_error(L, "unknown error"); } + throw std::logic_error("cannot happen"); +} +#define PROTECT(E) (protect(L, [&]{ return (E); })) + +struct Any { + struct PlaceHolder { + virtual ~PlaceHolder() { }; + }; + template + struct Holder : public PlaceHolder { + Holder(T const &value) : value(value) { } + Holder(T&& value) : value(std::forward(value)) { } + T value; + }; + Any() : content(nullptr) { } + Any(Any &&other) : content(nullptr) { std::swap(content, other.content); } + template + Any(T const &value) : content(new Holder(value)) { } + template + Any(T &&value) : content(new Holder::type>(std::forward(value))) { } + ~Any() { delete content; } + + Any &operator=(Any &&other) { + std::swap(content, other.content); + return *this; + } + + template + T *get() { + auto x = dynamic_cast*>(content); + return x ? &x->value : nullptr; + } + template + T const *get() const { + auto x = dynamic_cast*>(content); + return x ? &x->value : nullptr; + } + bool empty() const { return !content; } + + PlaceHolder *content = nullptr; +}; + +struct AnyWrap { + template + static T *new_(lua_State *L, Args... args) { + void *data = lua_newuserdata(L, sizeof(Gringo::Any)); + Gringo::Any *ret = new (data) Any(); + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + protect(L, [&] { *ret = Any(T(std::forward(args)...)) ; }); + return ret->get(); + } + template + static T *get(lua_State *L, int index) { + auto *self = (Gringo::Any*)luaL_checkudata(L, index, typeName); + return protect(L, [self]() { return self->get(); }); + } + static int gc(lua_State *L) { + Any* del = (Any*)lua_touserdata(L, 1); + del->~Any(); + return 0; + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo._Any"; +}; + +constexpr char const *AnyWrap::typeName; + +luaL_Reg const AnyWrap::meta[] = { + {"__gc", gc}, + {nullptr, nullptr} +}; + +Symbol luaToVal(lua_State *L, int idx) { + int type = lua_type(L, idx); + switch(type) { + case LUA_TSTRING: { + char const *name = lua_tostring(L, idx); + return protect(L, [name]() { return Symbol::createStr(name); }); + } + case LUA_TNUMBER: { + int num = lua_tointeger(L, idx); + return Symbol::createNum(num); + } + case LUA_TUSERDATA: { + bool check = false; + if (lua_getmetatable(L, idx)) { // +1 + lua_getfield(L, LUA_REGISTRYINDEX, "clingo.Symbol"); // +1 + check = lua_rawequal(L, -1, -2); + lua_pop(L, 2); // -2 + } + if (check) { return *(Symbol*)lua_touserdata(L, idx); } + } + default: { luaL_error(L, "cannot convert to value"); } + } + return {}; +} + +#if LUA_VERSION_NUM < 502 + +int lua_absindex(lua_State *L, int idx) { + return (idx < 0) ? lua_gettop(L) + idx + 1 : idx; +} + +// size_t lua_len(lua_State *L, int index) { +// return lua_objlen(L, index); +// } + +// size_t lua_rawlen(lua_State *L, int index) { +// return lua_objlen(L, index); +// } + +#endif + +static int luaPushKwArg(lua_State *L, int index, int pos, char const *name, bool optional) { + index = lua_absindex(L, index); + lua_pushinteger(L, pos); + lua_gettable(L, index); + if (!lua_isnil(L, -1)) { + if (name) { + lua_getfield(L, index, name); + if (!lua_isnil(L, -1)) { + lua_pop(L, 2); + return luaL_error(L, "argument #%d also given by keyword %s", pos, name); + } + lua_pop(L, 1); + } + } + else if (name) { + lua_pop(L, 1); + lua_getfield(L, index, name); + } + if (!optional && lua_isnil(L, -1)) { + return name ? luaL_error(L, "argument %s (#%d) missing", name, pos) : luaL_error(L, "argument #%d missing", pos); + } + return 1; +} + +template +void luaToCpp(lua_State *L, int index, std::pair &x); + +void luaToCpp(lua_State *L, int index, Potassco::WeightLit_t &x); + +template +void luaToCpp(lua_State *L, int index, std::vector &x); + +void luaToCpp(lua_State *L, int index, bool &x) { + x = lua_toboolean(L, index); +} + +template +void luaToCpp(lua_State *L, int index, T &x, typename std::enable_if::value>::type* = nullptr) { + if (lua_type(L, index) != LUA_TNUMBER) { + luaL_error(L, "number expected"); + } + x = lua_tonumber(L, index); +} + +template +void luaToCpp(lua_State *L, int index, std::vector &x) { + index = lua_absindex(L, index); + if (lua_type(L, index) != LUA_TTABLE) { + luaL_error(L, "table expected"); + } + lua_pushnil(L); + while (lua_next(L, index) != 0) { + auto &y = protect(L, [&x]() -> T& { x.emplace_back(); return x.back(); }); + luaToCpp(L, -1, y); + lua_pop(L, 1); + } +} + +template +void luaToCpp(lua_State *L, int index, std::pair &x) { + index = lua_absindex(L, index); + if (lua_type(L, index) != LUA_TTABLE) { + luaL_error(L, "table expected"); + } + lua_pushnil(L); + if (lua_next(L, index) != 0) { + luaToCpp(L, -1, x.first); + lua_pop(L, 1); + } + else { + luaL_error(L, "tuple expected"); + } + if (lua_next(L, index) != 0) { + luaToCpp(L, -1, x.second); + lua_pop(L, 1); + } + else { + luaL_error(L, "tuple expected"); + } + if (lua_next(L, index) != 0) { + luaL_error(L, "tuple expected"); + } +} + +void luaToCpp(lua_State *L, int index, Potassco::WeightLit_t &x) { + std::pair y{x.lit, x.weight}; + luaToCpp(L, index, y); +} + +SymVec *luaToVals(lua_State *L, int idx) { + idx = lua_absindex(L, idx); + luaL_checktype(L, idx, LUA_TTABLE); + SymVec *vals = AnyWrap::new_(L); + lua_pushnil(L); + while (lua_next(L, idx) != 0) { + Symbol val = luaToVal(L, -1); + protect(L, [val,&vals](){ vals->push_back(val); }); + lua_pop(L, 1); + } + lua_replace(L, idx); + return vals; +} + +bool handleError(lua_State *L, Location const &loc, int code, char const *desc, Logger *log) { + switch (code) { + case LUA_ERRRUN: + case LUA_ERRERR: + case LUA_ERRSYNTAX: { + std::string s(lua_tostring(L, -1)); + lua_pop(L, 1); + std::ostringstream msg; + msg << loc << ": " << (log ? "info" : "error") << ": " << desc << ":\n" + << (code == LUA_ERRSYNTAX ? " SyntaxError: " : " RuntimeError: ") + << s << "\n" + ; + if (!log) { throw GringoError(msg.str().c_str()); } + else { + GRINGO_REPORT(*log, clingo_warning_operation_undefined) << msg.str(); + return false; + } + } + case LUA_ERRMEM: { + std::stringstream msg; + msg << loc << ": error: lua interpreter ran out of memory" << "\n"; + throw GringoError(msg.str().c_str()); + } + } + return true; +} + +static int luaTraceback (lua_State *L); + +// {{{1 lua C functions + +using LuaCallArgs = std::tuple; + +static int luaTraceback (lua_State *L) { + if (!lua_isstring(L, 1)) { return 1; } + lua_getglobal(L, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); + lua_pushinteger(L, 2); + lua_call(L, 2, 1); + lua_getglobal(L, "string"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "gsub"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_pushvalue(L, -3); + lua_pushliteral(L, "\t"); + lua_pushliteral(L, " "); + lua_call(L, 3, 1); + return 1; +} + +int luaCall(lua_State *L); + +void lua_regMeta(lua_State *L, char const *name, luaL_Reg const * funs, lua_CFunction indexfun = nullptr, lua_CFunction newindexfun = nullptr) { +#if LUA_VERSION_NUM < 502 + luaL_newmetatable(L, name); + luaL_register(L, 0, funs); +#else + luaL_newmetatable(L, name); + luaL_setfuncs(L, funs, 0); +#endif + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, -2); + lua_rawset(L, -3); + lua_pushliteral(L, "__index"); + if (indexfun) { + lua_pushcfunction(L, indexfun); + } + else { + lua_pushvalue(L, -2); + } + lua_rawset(L, -3); + if (newindexfun) { + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, newindexfun); + lua_rawset(L, -3); + } +} + +// {{{1 wrap SolveResult + +struct SolveResult { + static int new_(lua_State *L, Gringo::SolveResult res) { + *(Gringo::SolveResult*)lua_newuserdata(L, sizeof(Gringo::SolveResult)) = res; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + return 1; + } + static int satisfiable(lua_State *L) { + Gringo::SolveResult &res = *(Gringo::SolveResult*)luaL_checkudata(L, 1, typeName); + switch (res.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { lua_pushboolean(L, true); return 1; } + case Gringo::SolveResult::Unsatisfiable: { lua_pushboolean(L, false); return 1; } + case Gringo::SolveResult::Unknown: { lua_pushnil(L); return 1; } + } + return luaL_error(L, "must not happen"); + } + static int unsatisfiable(lua_State *L) { + Gringo::SolveResult &res = *(Gringo::SolveResult*)luaL_checkudata(L, 1, typeName); + switch (res.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { lua_pushboolean(L, false); return 1; } + case Gringo::SolveResult::Unsatisfiable: { lua_pushboolean(L, true); return 1; } + case Gringo::SolveResult::Unknown: { lua_pushnil(L); return 1; } + } + return luaL_error(L, "must not happen"); + } + static int unknown(lua_State *L) { + Gringo::SolveResult &res = *(Gringo::SolveResult*)luaL_checkudata(L, 1, typeName); + switch (res.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { lua_pushboolean(L, false); return 1; } + case Gringo::SolveResult::Unsatisfiable: { lua_pushboolean(L, false); return 1; } + case Gringo::SolveResult::Unknown: { lua_pushboolean(L, true); return 1; } + } + return luaL_error(L, "must not happen"); + } + static int exhausted(lua_State *L) { + Gringo::SolveResult &res = *(Gringo::SolveResult*)luaL_checkudata(L, 1, typeName); + lua_pushboolean(L, res.exhausted()); + return 1; + } + static int interrupted(lua_State *L) { + Gringo::SolveResult &res = *(Gringo::SolveResult*)luaL_checkudata(L, 1, typeName); + lua_pushboolean(L, res.interrupted()); + return 1; + } + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "satisfiable") == 0) { return satisfiable(L); } + else if (strcmp(name, "unsatisfiable") == 0) { return unsatisfiable(L); } + else if (strcmp(name, "unknown") == 0) { return unknown(L); } + else if (strcmp(name, "exhausted") == 0) { return exhausted(L); } + else if (strcmp(name, "interrupted") == 0) { return interrupted(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + static int toString(lua_State *L) { + Gringo::SolveResult &res = *(Gringo::SolveResult*)luaL_checkudata(L, 1, typeName); + switch (res.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { lua_pushstring(L, "SAT"); return 1; } + case Gringo::SolveResult::Unsatisfiable: { lua_pushstring(L, "UNSAT"); return 1; } + case Gringo::SolveResult::Unknown: { lua_pushstring(L, "UNKNOWN"); return 1; } + } + return luaL_error(L, "must not happen"); + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.SolveResult"; +}; + +constexpr char const *SolveResult::typeName; + +luaL_Reg const SolveResult::meta[] = { + {"__tostring", toString}, + {nullptr, nullptr} +}; + +// {{{1 Object + +template +struct Object { + template + static int new_(lua_State *L, Args&&... args) { + new (lua_newuserdata(L, sizeof(T))) T(std::forward(args)...); + luaL_getmetatable(L, T::typeName); + lua_setmetatable(L, -2); + return 1; + } + + static void reg(lua_State *L) { + lua_regMeta(L, T::typeName, T::meta, T::index, T::newIndex); + } + + static T *self(lua_State* L) { + return (T*)luaL_checkudata(L, 1, T::typeName); + } + + static int eq(lua_State *L) { + T *a = static_cast(luaL_checkudata(L, 1, T::typeName)); + T *b = static_cast(luaL_checkudata(L, 2, T::typeName)); + lua_pushboolean(L, *a == *b); + return 1; + } + static int lt(lua_State *L) { + T *a = static_cast(luaL_checkudata(L, 1, T::typeName)); + T *b = static_cast(luaL_checkudata(L, 2, T::typeName)); + lua_pushboolean(L, *a < *b); + return 1; + } + static int le(lua_State *L) { + T *a = static_cast(luaL_checkudata(L, 1, T::typeName)); + T *b = static_cast(luaL_checkudata(L, 2, T::typeName)); + lua_pushboolean(L, *a <= *b); + return 1; + } + static constexpr luaL_Reg const meta[] = {{nullptr, nullptr}}; + static constexpr lua_CFunction const index = nullptr; + static constexpr lua_CFunction const newIndex = nullptr; +}; + +template +constexpr luaL_Reg const Object::meta[]; +template +constexpr lua_CFunction const Object::index; +template +constexpr lua_CFunction const Object::newIndex; + +// {{{1 wrap TheoryTerm + +struct TheoryTermType { + using Type = Gringo::TheoryData::TermType; + static int addToRegistry(lua_State *L) { + lua_createtable(L, 0, 6); + for (auto t : { Type::Function, Type::Number, Type::Symbol, Type::Tuple, Type::List, Type::Set }) { + *(Type*)lua_newuserdata(L, sizeof(Type)) = t; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, field_(t)); + } + lua_setfield(L, -2, "TheoryTermType"); + return 0; + } + static char const *field_(Type t) { + switch (t) { + case Type::Function: { return "Function"; } + case Type::Number: { return "Number"; } + case Type::Symbol: { return "Symbol"; } + case Type::Tuple: { return "Tuple"; } + case Type::List: { return "List"; } + case Type::Set: { return "Set"; } + } + return ""; + } + static int new_(lua_State *L, Type t) { + lua_getfield(L, LUA_REGISTRYINDEX, "clingo"); + lua_getfield(L, -1, "TheoryTermType"); + lua_replace(L, -2); + lua_getfield(L, -1, field_(t)); + lua_replace(L, -2); + return 1; + } + static int eq(lua_State *L) { + Type *a = static_cast(luaL_checkudata(L, 1, typeName)); + Type *b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, *a == *b); + return 1; + } + static int lt(lua_State *L) { + Type *a = static_cast(luaL_checkudata(L, 1, typeName)); + Type *b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, *a < *b); + return 1; + } + static int le(lua_State *L) { + Type *a = static_cast(luaL_checkudata(L, 1, typeName)); + Type *b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, *a <= *b); + return 1; + } + static int toString(lua_State *L) { + lua_pushstring(L, field_(*(Type*)luaL_checkudata(L, 1, typeName))); + return 1; + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.TheoryTermType"; +}; + +constexpr char const *TheoryTermType::typeName; + +luaL_Reg const TheoryTermType::meta[] = { + {"__eq", eq}, + {"__lt", lt}, + {"__le", le}, + {"__tostring", toString}, + { nullptr, nullptr } +}; + +struct TheoryTerm { + using Data = std::pair; + static int new_(lua_State *L, Gringo::TheoryData const *data, Id_t value) { + new (lua_newuserdata(L, sizeof(Data))) Data{data, value}; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + return 1; + } + static int name(lua_State *L) { + auto self = (Data*)luaL_checkudata(L, 1, typeName); + lua_pushstring(L, protect(L, [self](){ return self->first->termName(self->second); })); + return 1; + } + static int number(lua_State *L) { + auto self = (Data*)luaL_checkudata(L, 1, typeName); + lua_pushnumber(L, protect(L, [self](){ return self->first->termNum(self->second); })); + return 1; + } + static int args(lua_State *L) { + auto self = (Data*)luaL_checkudata(L, 1, typeName); + auto args = self->first->termArgs(self->second); + lua_createtable(L, args.size, 0); + int i = 1; + for (auto &x : args) { + new_(L, self->first, x); + lua_rawseti(L, -2, i++); + } + return 1; + } + static int toString(lua_State *L) { + auto self = (Data*)luaL_checkudata(L, 1, typeName); + auto *str = AnyWrap::new_(L); + lua_pushstring(L, protect(L, [self, str]() { return (*str = self->first->termStr(self->second)).c_str(); })); + return 1; + } + static int type(lua_State *L) { + auto self = (Data*)luaL_checkudata(L, 1, typeName); + return TheoryTermType::new_(L, protect(L, [self]() { return self->first->termType(self->second); })); + } + static int eq(lua_State *L) { + auto a = static_cast(luaL_checkudata(L, 1, typeName)); + auto b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, a->second == b->second); + return 1; + } + static int lt(lua_State *L) { + auto a = static_cast(luaL_checkudata(L, 1, typeName)); + auto b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, a->second < b->second); + return 1; + } + static int le(lua_State *L) { + auto a = static_cast(luaL_checkudata(L, 1, typeName)); + auto b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, a->second <= b->second); + return 1; + } + static int index(lua_State *L) { + char const *field = luaL_checkstring(L, 2); + if (strcmp(field, "type") == 0) { return type(L); } + else if (strcmp(field, "name") == 0) { return name(L); } + else if (strcmp(field, "arguments") == 0) { return args(L); } + else if (strcmp(field, "number") == 0) { return number(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, field); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + static constexpr char const *typeName = "clingo.TheoryTerm"; + static luaL_Reg const meta[]; +}; + +constexpr char const *TheoryTerm::typeName; +luaL_Reg const TheoryTerm::meta[] = { + {"__tostring", toString}, + {"__eq", eq}, + {"__lt", lt}, + {"__le", le}, + {nullptr, nullptr} +}; + +// {{{1 wrap TheoryElement + +struct TheoryElement : Object { + TheoryElement(Gringo::TheoryData const *data, Id_t idx) : data(data) , idx(idx) { } + Gringo::TheoryData const *data; + Id_t idx; + + static int terms(lua_State *L) { + auto self = Object::self(L); + auto args = protect(L, [self]() { return self->data->elemTuple(self->idx); }); + lua_createtable(L, args.size, 0); + int i = 1; + for (auto &x : args) { + TheoryTerm::new_(L, self->data, x); + lua_rawseti(L, -2, i++); + } + return 1; + } + + static int condition(lua_State *L) { + auto self = Object::self(L); + auto args = protect(L, [self]() { return self->data->elemCond(self->idx); }); + lua_createtable(L, args.size, 0); + int i = 1; + for (auto &x : args) { + lua_pushnumber(L, x); + lua_rawseti(L, -2, i++); + } + return 1; + } + + static int conditionId(lua_State *L) { + auto self = Object::self(L); + lua_pushnumber(L, protect(L, [self]() { return self->data->elemCondLit(self->idx); })); + return 1; + } + + static int toString(lua_State *L) { + auto self = Object::self(L); + std::string *rep = AnyWrap::new_(L); + lua_pushstring(L, protect(L, [self, rep]() { return (*rep = self->data->elemStr(self->idx)).c_str(); })); + return 1; + } + + static int index(lua_State *L) { + char const *field = luaL_checkstring(L, 2); + if (strcmp(field, "terms") == 0) { return terms(L); } + else if (strcmp(field, "condition") == 0) { return condition(L); } + else if (strcmp(field, "condition_id") == 0) { return conditionId(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, field); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", field); + } + } + + static constexpr char const *typeName = "clingo.TheoryElement"; + static luaL_Reg const meta[]; +}; +bool operator< (TheoryElement const &a, TheoryElement const &b) { return a.idx < b.idx; } +bool operator<=(TheoryElement const &a, TheoryElement const &b) { return a.idx <= b.idx; } +bool operator==(TheoryElement const &a, TheoryElement const &b) { return a.idx == b.idx; } + +constexpr char const *TheoryElement::typeName; +luaL_Reg const TheoryElement::meta[] = { + {"__tostring", toString}, + {"__eq", eq}, + {"__lt", lt}, + {"__le", le}, + {nullptr, nullptr} +}; + +// {{{1 wrap TheoryAtom + +struct TheoryAtom : Object { + TheoryAtom(Gringo::TheoryData const *data, Id_t idx) : data(data) , idx(idx) { } + Gringo::TheoryData const *data; + Id_t idx; + + static int elements(lua_State *L) { + auto self = Object::self(L); + auto args = protect(L, [self]() { return self->data->atomElems(self->idx); }); + lua_createtable(L, args.size, 0); + int i = 1; + for (auto &x : args) { + TheoryElement::new_(L, self->data, x); + lua_rawseti(L, -2, i++); + } + return 1; + } + + static int term(lua_State *L) { + auto self = Object::self(L); + return TheoryTerm::new_(L, self->data, protect(L, [self]() { return self->data->atomTerm(self->idx); })); + } + + static int literal(lua_State *L) { + auto self = Object::self(L); + lua_pushnumber(L, protect(L, [self]() { return self->data->atomLit(self->idx); })); + return 1; + } + + static int guard(lua_State *L) { + auto self = Object::self(L); + if (!protect(L, [self](){ return self->data->atomHasGuard(self->idx); })) { + lua_pushnil(L); + return 1; + } + lua_createtable(L, 2, 0); + auto guard = protect(L, [self](){ return self->data->atomGuard(self->idx); }); + lua_pushstring(L, guard.first); + lua_rawseti(L, -2, 1); + TheoryTerm::new_(L, self->data, guard.second); + lua_rawseti(L, -2, 2); + return 1; + } + + static int toString(lua_State *L) { + auto self = Object::self(L); + std::string *rep = AnyWrap::new_(L); + lua_pushstring(L, protect(L, [self, rep]() { return (*rep = self->data->atomStr(self->idx)).c_str(); })); + return 1; + } + + static int index(lua_State *L) { + char const *field = luaL_checkstring(L, 2); + if (strcmp(field, "elements") == 0) { return elements(L); } + else if (strcmp(field, "term") == 0) { return term(L); } + else if (strcmp(field, "guard") == 0) { return guard(L); } + else if (strcmp(field, "literal") == 0) { return literal(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, field); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", field); + } + } + + static constexpr char const *typeName = "clingo.TheoryAtom"; + static luaL_Reg const meta[]; +}; + +bool operator< (TheoryAtom const &a, TheoryAtom const &b) { return a.idx < b.idx; } +bool operator<=(TheoryAtom const &a, TheoryAtom const &b) { return a.idx <= b.idx; } +bool operator==(TheoryAtom const &a, TheoryAtom const &b) { return a.idx == b.idx; } + +constexpr char const *TheoryAtom::typeName; +luaL_Reg const TheoryAtom::meta[] = { + {"__tostring", toString}, + {"__eq", eq}, + {"__lt", lt}, + {"__le", le}, + {nullptr, nullptr} +}; +// {{{1 wrap TheoryIter + +struct TheoryIter { + static int iter(lua_State *L, Gringo::TheoryData const *data) { + lua_pushlightuserdata(L, (void*)data); + lua_pushnumber(L, 0); + lua_pushcclosure(L, iter_, 2); + return 1; + } + + static int iter_(lua_State *L) { + auto data = (Gringo::TheoryData const *)lua_topointer(L, lua_upvalueindex(1)); + Id_t idx = lua_tointeger(L, lua_upvalueindex(2)); + if (idx < data->numAtoms()) { + lua_pushnumber(L, idx + 1); + lua_replace(L, lua_upvalueindex(2)); + TheoryAtom::new_(L, data, idx); + } + else { lua_pushnil(L); } + return 1; + } +}; + +// {{{1 wrap Term + +struct SymbolType { + enum Type { Number, String, Function, Inf, Sup }; + static int addToRegistry(lua_State *L) { + lua_createtable(L, 0, 5); + *(Type*)lua_newuserdata(L, sizeof(Type)) = Number; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "Number"); + *(Type*)lua_newuserdata(L, sizeof(Type)) = String; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "String"); + *(Type*)lua_newuserdata(L, sizeof(Type)) = Function; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "Function"); + *(Type*)lua_newuserdata(L, sizeof(Type)) = Inf; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "Infimum"); + *(Type*)lua_newuserdata(L, sizeof(Type)) = Sup; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "Supremum"); + lua_setfield(L, -2, "SymbolType"); + return 0; + } + static int eq(lua_State *L) { + Type *a = static_cast(luaL_checkudata(L, 1, typeName)); + Type *b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, *a == *b); + return 1; + } + static int lt(lua_State *L) { + Type *a = static_cast(luaL_checkudata(L, 1, typeName)); + Type *b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, *a < *b); + return 1; + } + static int le(lua_State *L) { + Type *a = static_cast(luaL_checkudata(L, 1, typeName)); + Type *b = static_cast(luaL_checkudata(L, 2, typeName)); + lua_pushboolean(L, *a <= *b); + return 1; + } + static int toString(lua_State *L) { + switch (*(Type*)luaL_checkudata(L, 1, typeName)) { + case Number: { lua_pushstring(L, "Number"); break; } + case String: { lua_pushstring(L, "String"); break; } + case Function: { lua_pushstring(L, "Function"); break; } + case Inf: { lua_pushstring(L, "Infimum"); break; } + case Sup: { lua_pushstring(L, "Supremum"); break; } + } + return 1; + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.SymbolType"; +}; + +constexpr char const *SymbolType::typeName; + +luaL_Reg const SymbolType::meta[] = { + {"__eq", eq}, + {"__lt", lt}, + {"__le", le}, + {"__tostring", toString}, + { nullptr, nullptr } +}; + +struct Term { + static int new_(lua_State *L, Symbol v) { + if (v.type() == Gringo::SymbolType::Sup) { + lua_getfield(L, LUA_REGISTRYINDEX, "clingo"); + lua_getfield(L, -1, "Supremum"); + lua_replace(L, -2); + } + else if (v.type() == Gringo::SymbolType::Inf) { + lua_getfield(L, LUA_REGISTRYINDEX, "clingo"); + lua_getfield(L, -1, "Infimum"); + lua_replace(L, -2); + } + else { + *(Symbol*)lua_newuserdata(L, sizeof(Symbol)) = v; + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + } + return 1; + } + static int addToRegistry(lua_State *L) { + *(Symbol*)lua_newuserdata(L, sizeof(Symbol)) = Symbol::createSup(); + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "Supremum"); + *(Symbol*)lua_newuserdata(L, sizeof(Symbol)) = Symbol::createInf(); + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "Infimum"); + return 0; + } + static int newFun(lua_State *L) { + char const *name = luaL_checklstring(L, 1, nullptr); + bool sign = false; + if (!lua_isnone(L, 3) && !lua_isnil(L, 3)) { + sign = !lua_toboolean(L, 3); + } + if (name[0] == '\0' && sign) { luaL_argerror(L, 2, "tuples must not have signs"); } + if (lua_isnoneornil(L, 2)) { + return new_(L, protect(L, [name, sign](){ return Symbol::createId(name, sign); })); + } + else { + SymVec *vals = luaToVals(L, 2); + return new_(L, protect(L, [name, sign, vals](){ return vals->empty() && name[0] != '\0' ? Symbol::createId(name, sign) : Symbol::createFun(name, Potassco::toSpan(*vals), sign); })); + } + } + static int newTuple(lua_State *L) { + lua_pushstring(L, ""); + lua_insert(L, 1); + return newFun(L); + } + static int newNumber(lua_State *L) { + return Term::new_(L, Symbol::createNum(luaL_checkinteger(L, 1))); + } + static int newString(lua_State *L) { + return Term::new_(L, Symbol::createStr(luaL_checkstring(L, 1))); + } + VALUE_CMP(Symbol) + static int name(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + if (val.type() == Gringo::SymbolType::Fun) { + lua_pushstring(L, protect(L, [val]() { return val.name().c_str(); })); + } + else { + lua_pushnil(L); + } + return 1; + } + static int string(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + if (val.type() == Gringo::SymbolType::Str) { + lua_pushstring(L, protect(L, [val]() { return val.string().c_str(); })); + } + else { + lua_pushnil(L); + } + return 1; + } + static int number(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + if (val.type() == Gringo::SymbolType::Num) { + lua_pushnumber(L, protect(L, [val]() { return val.num(); })); + } + else { + lua_pushnil(L); + } + return 1; + } + static int negative(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + if (val.type() == Gringo::SymbolType::Fun) { + lua_pushboolean(L, protect(L, [val]() { return val.sign(); })); + } + else { + lua_pushnil(L); + } + return 1; + } + static int positive(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + if (val.type() == Gringo::SymbolType::Fun) { + lua_pushboolean(L, protect(L, [val]() { return !val.sign(); })); + } + else { + lua_pushnil(L); + } + return 1; + } + static int args(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + if (val.type() == Gringo::SymbolType::Fun) { + lua_createtable(L, val.args().size, 0); + int i = 1; + for (auto &x : val.args()) { + Term::new_(L, x); + lua_rawseti(L, -2, i++); + } + } + else { + lua_pushnil(L); + } + return 1; + } + static int toString(lua_State *L) { + std::string *rep = AnyWrap::new_(L); + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + lua_pushstring(L, protect(L, [val, rep]() { + std::ostringstream oss; + oss << val; + *rep = oss.str(); + return rep->c_str(); + })); + return 1; + } + static int type(lua_State *L) { + Symbol val = *(Symbol*)luaL_checkudata(L, 1, typeName); + lua_getfield(L, LUA_REGISTRYINDEX, "clingo"); + lua_getfield(L, -1, "SymbolType"); + char const *field = ""; + switch (val.type()) { + case Gringo::SymbolType::Str: { field = "String"; break; } + case Gringo::SymbolType::Num: { field = "Number"; break; } + case Gringo::SymbolType::Inf: { field = "Infimum"; break; } + case Gringo::SymbolType::Sup: { field = "Supremum"; break; } + case Gringo::SymbolType::Fun: { field = "Function"; break; } + case Gringo::SymbolType::Special: { luaL_error(L, "must not happen"); } + } + lua_getfield(L, -1, field); + return 1; + } + static int index(lua_State *L) { + char const *field = luaL_checkstring(L, 2); + if (strcmp(field, "positive") == 0) { return positive(L); } + else if (strcmp(field, "negative") == 0) { return negative(L); } + else if (strcmp(field, "arguments") == 0) { return args(L); } + else if (strcmp(field, "name") == 0) { return name(L); } + else if (strcmp(field, "string") == 0) { return string(L); } + else if (strcmp(field, "number") == 0) { return number(L); } + else if (strcmp(field, "type") == 0) { return type(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, field); + return 1; + } + } + static constexpr char const *typeName = "clingo.Symbol"; + static luaL_Reg const meta[]; +}; + +constexpr char const *Term::typeName; +luaL_Reg const Term::meta[] = { + {"__tostring", toString}, + {"__eq", eqSymbol}, + {"__lt", ltSymbol}, + {"__le", leSymbol}, + {nullptr, nullptr} +}; + +int luaCall(lua_State *L) { + auto &args = *(LuaCallArgs*)lua_touserdata(L, 1); + bool hasContext = !lua_isnil(L, 2); + if (hasContext) { + lua_getfield(L, 2, std::get<0>(args)); + lua_pushvalue(L, 2); + } + else { lua_getglobal(L, std::get<0>(args)); } + for (auto &x : std::get<1>(args)) { Term::new_(L, x); } + lua_call(L, std::get<1>(args).size + hasContext, 1); + if (lua_type(L, -1) == LUA_TTABLE) { + lua_pushnil(L); + while (lua_next(L, -2)) { + Symbol val = luaToVal(L, -1); + protect(L, [val, &args]() { std::get<2>(args).emplace_back(val); }); + lua_pop(L, 1); + } + } + else { + Symbol val = luaToVal(L, -1); + protect(L, [val, &args]() { std::get<2>(args).emplace_back(val); }); + } + return 0; +} + +// {{{1 wrap SolveControl + +struct SolveControl { + static int getClause(lua_State *L, bool invert) { + Model const *& model = *(Model const **)luaL_checkudata(L, 1, typeName); + Gringo::Model::LitVec *lits = AnyWrap::new_(L); + luaL_checktype(L, 2, LUA_TTABLE); + lua_pushnil(L); + while (lua_next(L, 2)) { + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnil(L); + if (!lua_next(L, -2)) { luaL_error(L, "atom/boolean pair expected"); } + Symbol atom = luaToVal(L, -1); + lua_pop(L, 1); + if (!lua_next(L, -2)) { luaL_error(L, "atom/boolean pair expected"); } + bool truth = lua_toboolean(L, -1); + lua_pop(L, 1); + if (lua_next(L, -2)) { luaL_error(L, "atom/boolean pair expected"); } + protect(L, [invert, atom, truth, lits](){ lits->emplace_back(atom, truth ^ invert); }); + lua_pop(L, 1); + } + protect(L, [model, lits](){ model->addClause(*lits); }); + return 0; + } + static int add_clause(lua_State *L) { + return getClause(L, false); + } + static int add_nogood(lua_State *L) { + return getClause(L, true); + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.SolveControl"; +}; + +constexpr char const *SolveControl::typeName; + +luaL_Reg const SolveControl::meta[] = { + {"add_clause", add_clause}, + {"add_nogood", add_nogood}, + {nullptr, nullptr} +}; + +// {{{1 wrap Model + +struct Model { + static int contains(lua_State *L) { + Gringo::Model const *& model = *(Gringo::Model const **)luaL_checkudata(L, 1, typeName); + Symbol val = luaToVal(L, 2); + lua_pushboolean(L, protect(L, [val, model]() { return model->contains(val); })); + return 1; + } + static int atoms(lua_State *L) { + Gringo::Model const *& model = *(Gringo::Model const **)luaL_checkudata(L, 1, typeName); + unsigned atomset = 0; + luaL_checktype(L, 2, LUA_TTABLE); + lua_getfield(L, 2, "atoms"); + if (lua_toboolean(L, -1)) { atomset |= clingo_show_type_atoms; } + lua_pop(L, 1); + lua_getfield(L, 2, "shown"); + if (lua_toboolean(L, -1)) { atomset |= clingo_show_type_shown; } + lua_pop(L, 1); + lua_getfield(L, 2, "terms"); + if (lua_toboolean(L, -1)) { atomset |= clingo_show_type_terms; } + lua_pop(L, 1); + lua_getfield(L, 2, "csp"); + if (lua_toboolean(L, -1)) { atomset |= clingo_show_type_csp; } + lua_pop(L, 1); + lua_getfield(L, 2, "extra"); + if (lua_toboolean(L, -1)) { atomset |= clingo_show_type_extra; } + lua_pop(L, 1); + lua_getfield(L, 2, "complement"); + if (lua_toboolean(L, -1)) { atomset |= clingo_show_type_complement; } + lua_pop(L, 1); + SymSpan atoms = protect(L, [&model, atomset]() { return model->atoms(atomset); }); + lua_createtable(L, atoms.size, 0); + int i = 1; + for (auto x : atoms) { + Term::new_(L, x); + lua_rawseti(L, -2, i++); + } + return 1; + } + static int cost(lua_State *L) { + Gringo::Model const *& model = *(Gringo::Model const **)luaL_checkudata(L, 1, typeName); + Int64Vec *values = AnyWrap::new_(L); + protect(L, [&model, values]() { *values = model->optimization(); }); + lua_createtable(L, values->size(), 0); + int i = 1; + for (auto x : *values) { + lua_pushinteger(L, x); + lua_rawseti(L, -2, i++); + } + return 1; + } + static int toString(lua_State *L) { + Gringo::Model const *& model = *(Gringo::Model const **)luaL_checkudata(L, 1, typeName); + std::string *rep = AnyWrap::new_(L); + lua_pushstring(L, protect(L, [model, rep]() { + auto printAtom = [](std::ostream &out, Symbol val) { + auto sig = val.sig(); + if (val.type() == Gringo::SymbolType::Fun && sig.name() == "$" && sig.arity() == 2 && !sig.sign()) { + auto args = val.args().first; + out << args[0] << "=" << args[1]; + } + else { out << val; } + }; + std::ostringstream oss; + print_comma(oss, model->atoms(clingo_show_type_shown), " ", printAtom); + *rep = oss.str(); + return rep->c_str(); + })); + return 1; + } + static int context(lua_State *L) { + auto &model = *(Gringo::Model const **)luaL_checkudata(L, 1, typeName); + *(Gringo::Model const **)lua_newuserdata(L, sizeof(Gringo::Model*)) = model; + luaL_getmetatable(L, SolveControl::typeName); + lua_setmetatable(L, -2); + return 1; + } + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "cost") == 0) { + return cost(L); + } + else if (strcmp(name, "context") == 0) { + return context(L); + } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return 1; + } + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.Model"; +}; + +constexpr char const *Model::typeName; +luaL_Reg const Model::meta[] = { + {"__tostring", toString}, + {"symbols", atoms}, + {"contains", contains}, + {nullptr, nullptr} +}; + +// {{{1 wrap Statistics + +int newStatistics(lua_State *L, Potassco::AbstractStatistics const *stats, Potassco::AbstractStatistics::Key_t key) { + switch (protect(L, [stats, key]{ return stats->type(key); })) { + case Potassco::Statistics_t::Value: { + lua_pushnumber(L, PROTECT(stats->value(key))); + return 1; + } + case Potassco::Statistics_t::Array: { + lua_newtable(L); // stack + 1 + for (size_t i = 0, e = PROTECT(stats->size(key)); i != e; ++i) { + newStatistics(L, stats, PROTECT(stats->at(key, i))); // stack + 2 + lua_rawseti(L, -2, i+1); // stack + 1 + } + return 1; + } + case Potassco::Statistics_t::Map: { + lua_newtable(L); // stack + 1 + for (size_t i = 0, e = PROTECT(stats->size(key)); i != e; ++i) { + auto name = PROTECT(stats->key(key, i)); + lua_pushstring(L, name); // stack + 2 + newStatistics(L, stats, PROTECT(stats->get(key, name))); // stack + 3 + lua_rawset(L, -3); // stack + 1 + } + return 1; + } + default: { + return luaL_error(L, "cannot happen"); + } + } +} + +// {{{1 wrap SolveFuture + +struct SolveFuture { + static int get(lua_State *L) { + Gringo::SolveFuture *& future = *(Gringo::SolveFuture **)luaL_checkudata(L, 1, typeName); + SolveResult::new_(L, protect(L, [future]() { return future->get(); })); + return 1; + } + static int wait(lua_State *L) { + Gringo::SolveFuture *& future = *(Gringo::SolveFuture **)luaL_checkudata(L, 1, typeName); + if (lua_isnone(L, 2) == 0) { + double timeout = luaL_checknumber(L, 2); + lua_pushboolean(L, protect(L, [future, timeout]() { return future->wait(timeout); })); + return 1; + } + else { + protect(L, [future]() { future->wait(); }); + return 0; + } + } + static int cancel(lua_State *L) { + Gringo::SolveFuture *& future = *(Gringo::SolveFuture **)luaL_checkudata(L, 1, typeName); + protect(L, [future]() { future->cancel(); }); + return 0; + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.SolveFuture"; +}; + +constexpr char const *SolveFuture::typeName; +luaL_Reg const SolveFuture::meta[] = { + {"get", get}, + {"wait", wait}, + {"cancel", cancel}, + {nullptr, nullptr} +}; + +// {{{1 wrap SolveIter + +struct SolveIter { + static int close(lua_State *L) { + Gringo::SolveIter *& iter = *(Gringo::SolveIter **)luaL_checkudata(L, 1, typeName); + protect(L, [iter]() { iter->close(); }); + return 0; + } + static int next(lua_State *L) { + Gringo::SolveIter *& iter = *(Gringo::SolveIter **)luaL_checkudata(L, lua_upvalueindex(1), typeName); + Gringo::Model const *m = protect(L, [iter]() { return iter->next(); }); + if (m) { + *(Gringo::Model const **)lua_newuserdata(L, sizeof(Gringo::Model*)) = m; + luaL_getmetatable(L, Model::typeName); + lua_setmetatable(L, -2); + } + else { lua_pushnil(L); } + return 1; + } + static int iter(lua_State *L) { + luaL_checkudata(L, 1, typeName); + lua_pushvalue(L,1); + lua_pushcclosure(L, next, 1); + return 1; + } + static int get(lua_State *L) { + Gringo::SolveIter *& iter = *(Gringo::SolveIter **)luaL_checkudata(L, 1, typeName); + SolveResult::new_(L, PROTECT(iter->get())); + return 1; + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.SolveIter"; +}; + +constexpr char const *SolveIter::typeName; +luaL_Reg const SolveIter::meta[] = { + {"iter", iter}, + {"close", close}, + {"get", get}, + {nullptr, nullptr} +}; + +// {{{1 wrap Configuration + +struct Configuration { + unsigned key; + int nSubkeys; + int arrLen; + int nValues; + char const* help; + Gringo::ConfigProxy *proxy; + + static int new_(lua_State *L, unsigned key, Gringo::ConfigProxy &proxy) { + Configuration &self = *(Configuration*)lua_newuserdata(L, sizeof(Configuration)); + self.proxy = &proxy; + self.key = key; + protect(L, [&self] { self.proxy->getKeyInfo(self.key, &self.nSubkeys, &self.arrLen, &self.help, &self.nValues); }); + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + return 1; + } + + static int keys(lua_State *L) { + auto &self = *(Configuration *)luaL_checkudata(L, 1, typeName); + if (self.nSubkeys < 0) { return 0; } + else { + lua_createtable(L, self.nSubkeys, 0); + for (int i = 0; i < self.nSubkeys; ++i) { + char const *key = protect(L, [&self, i] { return self.proxy->getSubKeyName(self.key, i); }); + lua_pushstring(L, key); + lua_rawseti(L, -2, i+1); + } + return 1; + } + } + + static int index(lua_State *L) { + auto &self = *(Configuration *)luaL_checkudata(L, 1, typeName); + char const *name = luaL_checkstring(L, 2); + if (strcmp("keys", name) == 0) { return keys(L); } + bool desc = strncmp("__desc_", name, 7) == 0; + if (desc) { name += 7; } + unsigned key; + bool hasSubKey = PROTECT(self.proxy->hasSubKey(self.key, name, &key)); + if (hasSubKey) { + new_(L, key, *self.proxy); + auto &sub = *(Configuration *)lua_touserdata(L, -1); + if (desc) { + lua_pushstring(L, sub.help); + return 1; + } + else if (sub.nValues < 0) { return 1; } + else { + std::string *value = AnyWrap::new_(L); + bool ret = PROTECT(sub.proxy->getKeyValue(sub.key, *value)); + if (ret) { + lua_pushstring(L, value->c_str()); + return 1; + } + return 0; + } + } + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return 1; + } + + static int newindex(lua_State *L) { + auto &self = *(Configuration *)luaL_checkudata(L, 1, typeName); + char const *name = luaL_checkstring(L, 2); + unsigned key; + bool hasSubKey = protect(L, [self, name, &key] { return self.proxy->hasSubKey(self.key, name, &key); }); + if (hasSubKey) { + const char *value = lua_tostring(L, 3); + protect(L, [self, key, value]() { self.proxy->setKeyValue(key, value); }); + lua_pushstring(L, value); + return 1; + } + return luaL_error(L, "unknown field: %s", name); + } + + static int next(lua_State *L) { + auto &self = *(Configuration *)luaL_checkudata(L, lua_upvalueindex(1), typeName); + int index = luaL_checkinteger(L, lua_upvalueindex(2)); + lua_pushnumber(L, index + 1); + lua_replace(L, lua_upvalueindex(2)); + if (index < self.arrLen) { + unsigned key = protect(L, [&self, index]() { return self.proxy->getArrKey(self.key, index); }); + return new_(L, key, *self.proxy); + } + else { + lua_pushnil(L); + return 1; + } + } + + static int iter(lua_State *L) { + luaL_checkudata(L, 1, typeName); + lua_pushvalue(L, 1); + lua_pushnumber(L, 0); + lua_pushcclosure(L, next, 2); + return 1; + } + + static int len(lua_State *L) { + auto &self = *(Configuration *)luaL_checkudata(L, 1, typeName); + lua_pushnumber(L, self.arrLen); + return 1; + } + static luaL_Reg const meta[]; + static constexpr char const *typeName = "clingo.Configuration"; +}; + +constexpr char const *Configuration::typeName; +luaL_Reg const Configuration::meta[] = { + {"__len", len}, + {"iter", iter}, + {nullptr, nullptr} +}; + +// {{{1 wrap SymbolicAtom + +struct SymbolicAtom { + Gringo::SymbolicAtoms &atoms; + Gringo::SymbolicAtomIter range; + static luaL_Reg const meta[]; + SymbolicAtom(Gringo::SymbolicAtoms &atoms, Gringo::SymbolicAtomIter range) + : atoms(atoms) + , range(range) { } + static constexpr const char *typeName = "clingo.SymbolicAtom"; + static int new_(lua_State *L, Gringo::SymbolicAtoms &atoms, Gringo::SymbolicAtomIter range) { + auto self = (SymbolicAtom*)lua_newuserdata(L, sizeof(SymbolicAtom)); + new (self) SymbolicAtom(atoms, range); + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + return 1; + } + static int symbol(lua_State *L) { + auto self = (SymbolicAtom *)luaL_checkudata(L, 1, typeName); + Symbol atom = protect(L, [self](){ return self->atoms.atom(self->range); }); + Term::new_(L, atom); + return 1; + } + static int literal(lua_State *L) { + auto self = (SymbolicAtom *)luaL_checkudata(L, 1, typeName); + auto lit = protect(L, [self](){ return self->atoms.literal(self->range); }); + lua_pushinteger(L, lit); + return 1; + } + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "is_fact") == 0) { return is_fact(L); } + else if (strcmp(name, "is_external") == 0) { return is_external(L); } + else if (strcmp(name, "symbol") == 0) { return symbol(L); } + else if (strcmp(name, "literal") == 0) { return literal(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + static int is_fact(lua_State *L) { + auto self = (SymbolicAtom *)luaL_checkudata(L, 1, typeName); + bool ret = protect(L, [self](){ return self->atoms.fact(self->range); }); + lua_pushboolean(L, ret); + return 1; + } + static int is_external(lua_State *L) { + auto self = (SymbolicAtom *)luaL_checkudata(L, 1, typeName); + bool ret = protect(L, [self](){ return self->atoms.external(self->range); }); + lua_pushboolean(L, ret); + return 1; + } +}; + +constexpr const char *SymbolicAtom::typeName; + +luaL_Reg const SymbolicAtom::meta[] = { + {nullptr, nullptr} +}; + +// {{{1 wrap SymbolicAtoms + +struct SymbolicAtoms { + Gringo::SymbolicAtoms &atoms; + static luaL_Reg const meta[]; + + SymbolicAtoms(Gringo::SymbolicAtoms &atoms) : atoms(atoms) { } + + static constexpr const char *typeName = "clingo.SymbolicAtoms"; + + static SymbolicAtoms &get_self(lua_State *L) { + return *(SymbolicAtoms*)luaL_checkudata(L, 1, typeName); + } + + static int symbolicAtomIter(lua_State *L) { + auto current = (SymbolicAtom *)luaL_checkudata(L, lua_upvalueindex(1), SymbolicAtom::typeName); + if (current->atoms.valid(current->range)) { + lua_pushvalue(L, lua_upvalueindex(1)); // +1 + auto next = protect(L, [current]() { return current->atoms.next(current->range); }); + SymbolicAtom::new_(L, current->atoms, next); // +1 + lua_replace(L, lua_upvalueindex(1)); // -1 + } + else { lua_pushnil(L); } // +1 + return 1; + } + + static int new_(lua_State *L, Gringo::SymbolicAtoms &atoms) { + auto self = (SymbolicAtoms*)lua_newuserdata(L, sizeof(SymbolicAtoms)); + new (self) SymbolicAtoms(atoms); + luaL_getmetatable(L, typeName); + lua_setmetatable(L, -2); + return 1; + } + + static int len(lua_State *L) { + auto &self = get_self(L); + int ret = protect(L, [&self]() { return self.atoms.length(); }); + lua_pushinteger(L, ret); + return 1; + } + + static int iter(lua_State *L) { + auto &self = get_self(L); + auto range = protect(L, [&self]() { return self.atoms.begin(); }); + SymbolicAtom::new_(L, self.atoms, range); // +1 + lua_pushcclosure(L, symbolicAtomIter, 1); // +0 + return 1; + } + + static int lookup(lua_State *L) { + auto &self = get_self(L); + Gringo::Symbol atom = luaToVal(L, 2); + auto range = protect(L, [self, atom]() { return self.atoms.lookup(atom); }); + if (self.atoms.valid(range)) { SymbolicAtom::new_(L, self.atoms, range); } + else { lua_pushnil(L); } // +1 + return 1; + } + + static int by_signature(lua_State *L) { + auto &self = get_self(L); + char const *name = luaL_checkstring(L, 2); + int arity = luaL_checkinteger(L, 3); + bool positive = lua_isnone(L, 4) || lua_toboolean(L, 4); + auto range = protect(L, [&self, name, arity, positive]() { return self.atoms.begin(Sig(name, arity, !positive)); }); + SymbolicAtom::new_(L, self.atoms, range); // +1 + lua_pushcclosure(L, symbolicAtomIter, 1); // +0 + return 1; + } + + static int signatures(lua_State *L) { + auto &self = get_self(L); + auto ret = AnyWrap::new_>(L); // +1 + *ret = protect(L, [&self]() { return self.atoms.signatures(); }); + lua_createtable(L, ret->size(), 0); // +1 + int i = 1; + for (auto &sig : *ret) { + lua_createtable(L, 3, 0); // +1 + lua_pushstring(L, sig.name().c_str()); // +1 + lua_rawseti(L, -2, 1); // -1 + lua_pushinteger(L, sig.arity()); // +1 + lua_rawseti(L, -2, 2); // -1 + lua_pushboolean(L, !sig.sign()); // +1 + lua_rawseti(L, -2, 3); // -1 + lua_rawseti(L, -2, i); // -1 + ++i; + } + lua_replace(L, -2); // -1 + return 1; + } + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "signatures") == 0) { return signatures(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } +}; + +constexpr const char *SymbolicAtoms::typeName; + +luaL_Reg const SymbolicAtoms::meta[] = { + {"__len", len}, + {"iter", iter}, + {"lookup", lookup}, + {"by_signature", by_signature}, + {nullptr, nullptr} +}; + +// {{{1 wrap wrap Backend +struct Backend : Object { + Gringo::Control &ctl; + Gringo::Backend &backend; + + Backend(Gringo::Control &ctl, Gringo::Backend &backend) : ctl(ctl), backend(backend) { } + + static constexpr const char *typeName = "clingo.Backend"; + static luaL_Reg const meta[]; + + static int addAtom(lua_State *L) { + auto self = Object::self(L); + auto atom = protect(L, [self](){ return self->ctl.addProgramAtom(); }); + lua_pushinteger(L, atom); + return 1; + } + + static int addRule(lua_State *L) { + auto *self = Object::self(L); + auto *head = AnyWrap::new_(L); + auto *body = AnyWrap::new_(L); + bool choice = false; + luaL_checktype(L, 2, LUA_TTABLE); + luaPushKwArg(L, 2, 1, "head", false); + luaToCpp(L, -1, *head); + lua_pop(L, 1); + luaPushKwArg(L, 2, 2, "body", true); + if (!lua_isnil(L, -1)) { luaToCpp(L, -1, *body); } + lua_pop(L, 1); + luaPushKwArg(L, 2, 3, "choice", true); + luaToCpp(L, -1, choice); + lua_pop(L, 1); + protect(L, [self, choice, head, body](){ + Gringo::outputRule(self->backend, choice, *head, *body); + }); + return 0; + } + + static int addWeightRule(lua_State *L) { + auto *self = Object::self(L); + auto *head = AnyWrap::new_(L); + Weight_t lower; + auto *body = AnyWrap::new_(L); + bool choice = false; + luaL_checktype(L, 2, LUA_TTABLE); + luaPushKwArg(L, 2, 1, "head", false); + luaToCpp(L, -1, *head); + lua_pop(L, 1); + luaPushKwArg(L, 2, 2, "lower", false); + luaToCpp(L, -1, lower); + lua_pop(L, 1); + luaPushKwArg(L, 2, 3, "body", false); + luaToCpp(L, -1, *body); + lua_pop(L, 1); + luaPushKwArg(L, 2, 4, "choice", true); + luaToCpp(L, -1, choice); + lua_pop(L, 1); + protect(L, [self, choice, head, lower, body](){ + Gringo::outputRule(self->backend, choice, *head, lower, *body); + }); + return 0; + } +}; + +luaL_Reg const Backend::meta[] = { + {"add_atom", addAtom}, + {"add_rule", addRule}, + {"add_weight_rule", addWeightRule}, + {nullptr, nullptr} +}; + +// {{{1 wrap ControlWrap + +struct LuaClear { + LuaClear(lua_State *L) : L(L), n(lua_gettop(L)) { } + ~LuaClear() { lua_settop(L, n); } + lua_State *L; + int n; +}; + +struct LuaContext : Gringo::Context { + LuaContext(lua_State *L, Logger &log, int idx) + : L(L) + , log(log) + , idx(idx) { } + + bool callable(String name) const override { + if (!L || !idx) { return false; } + LuaClear lc(L); + lua_getfield(L, idx, name.c_str()); + return lua_type(L, -1) == LUA_TFUNCTION; + } + + SymVec call(Location const &loc, String name, SymSpan args) override { + assert(L); + LuaClear lc(L); + LuaCallArgs arg(name.c_str(), args, {}); + lua_pushcfunction(L, luaTraceback); + lua_pushcfunction(L, luaCall); + lua_pushlightuserdata(L, (void*)&arg); + lua_pushvalue(L, idx); + int ret = lua_pcall(L, 2, 0, -4); + if (!handleError(L, loc, ret, "operation undefined", &log)) { return {}; } + return std::move(std::get<2>(arg)); + } + + virtual ~LuaContext() noexcept = default; + + lua_State *L; + Logger &log; + int idx; +}; + +struct ControlWrap { + static GringoModule *module; + Control &ctl; + bool free; + ControlWrap(Control &ctl, bool free) : ctl(ctl), free(free) { } + static ControlWrap &get_self(lua_State *L) { + void *p = nullptr; + if (lua_istable(L, 1)) { + lua_rawgeti(L, 1, 1); // +1 + p = lua_touserdata(L, -1); + if (p) { + if (lua_getmetatable(L, 1)) { // +1 + luaL_getmetatable(L, typeName); // +1 + if (!lua_rawequal(L, -1, -2)) { p = nullptr; } + lua_pop(L, 2); // -2 + } + else { p = nullptr; } + } + lua_pop(L, 1); // -1 + } + if (!p) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", typeName, luaL_typename(L, 1)); + luaL_argerror(L, 1, msg); + } + return *(ControlWrap*)p; + } + static void checkBlocked(lua_State *L, Control &ctl, char const *function) { + if (protect(L, [&ctl]() { return ctl.blocked(); })) { luaL_error(L, "Control.%s must not be called during solve call", function); } + } + static int ground(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "ground"); + luaL_checktype(L, 2, LUA_TTABLE); + LuaContext ctx{ L, ctl.logger(), !lua_isnone(L, 3) && !lua_isnil(L, 3) ? 3 : 0 }; + if (ctx.idx) { luaL_checktype(L, ctx.idx, LUA_TTABLE); } + Control::GroundVec *vec = AnyWrap::new_(L); + lua_pushnil(L); + while (lua_next(L, 2) != 0) { + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnil(L); + if (!lua_next(L, -2)) { luaL_error(L, "tuple of name and arguments expected"); } + char const *name = luaL_checkstring(L, -1); + lua_pop(L, 1); + if (!lua_next(L, -2)) { luaL_error(L, "tuple of name and arguments expected"); } + SymVec *args = luaToVals(L, -1); + protect(L, [name, args, vec](){ vec->emplace_back(name, *args); }); + lua_pop(L, 1); + if (lua_next(L, -2)) { luaL_error(L, "tuple of name and arguments expected"); } + lua_pop(L, 1); + } + protect(L, [&ctl, vec, &ctx]() { ctl.ground(*vec, ctx.idx ? &ctx : nullptr); }); + return 0; + } + static int add(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "add"); + char const *name = luaL_checkstring(L, 2); + luaL_checktype(L, 3, LUA_TTABLE); + char const *prg = luaL_checkstring(L, 4); + FWStringVec *vals = AnyWrap::new_(L); + lua_pushnil(L); + while (lua_next(L, 3) != 0) { + char const *val = luaL_checkstring(L, -1); + protect(L, [val,&vals](){ vals->push_back(val); }); + lua_pop(L, 1); + } + protect(L, [&ctl, name, vals, prg]() { ctl.add(name, *vals, prg); }); + return 0; + } + static int load(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "load"); + char const *filename = luaL_checkstring(L, 2); + protect(L, [&ctl, filename]() { ctl.load(filename); }); + return 0; + } + static int get_const(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "get_const"); + char const *name = luaL_checkstring(L, 2); + Symbol ret = protect(L, [&ctl, name]() { return ctl.getConst(name); }); + if (ret.type() == Gringo::SymbolType::Special) { lua_pushnil(L); } + else { Term::new_(L, ret); } + return 1; + } + + static Control::Assumptions *getAssumptions(lua_State *L, int assIdx) { + Control::Assumptions *ass = AnyWrap::new_(L); + if (assIdx) { + assIdx = lua_absindex(L, assIdx); + luaL_checktype(L, assIdx, LUA_TTABLE); + lua_pushnil(L); + while (lua_next(L, assIdx)) { + luaL_checktype(L, -1, LUA_TTABLE); + lua_pushnil(L); + if (!lua_next(L, -2)) { luaL_error(L, "atom/boolean pair expected"); } + Symbol atom = luaToVal(L, -1); + lua_pop(L, 1); + if (!lua_next(L, -2)) { luaL_error(L, "atom/boolean pair expected"); } + bool truth = lua_toboolean(L, -1); + lua_pop(L, 1); + if (lua_next(L, -2)) { luaL_error(L, "atom/boolean pair expected"); } + protect(L, [atom, truth, ass](){ ass->emplace_back(atom, truth); }); + lua_pop(L, 1); + } + lua_replace(L, assIdx); + } + return ass; + } + + static int solve(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "solve"); + lua_pushstring(L, "statistics"); + lua_pushnil(L); + lua_rawset(L, 1); + int mhIndex = !lua_isnone(L, 2) && !lua_isnil(L, 2) ? 2 : 0; + int assIdx = !lua_isnone(L, 3) && !lua_isnil(L, 3) ? 3 : 0; + Gringo::Model const **model = nullptr; + int mIndex = 0; + if (mhIndex) { + model = (Gringo::Model const **)lua_newuserdata(L, sizeof(Gringo::Model*)); + luaL_getmetatable(L, Model::typeName); + lua_setmetatable(L, -2); + mIndex = lua_gettop(L); + } + Control::Assumptions *ass = getAssumptions(L, assIdx); + SolveResult::new_(L, protect(L, [L, &ctl, model, ass, mhIndex, mIndex]() { + return (int)ctl.solve(!model ? Control::ModelHandler(nullptr) : [L, model, mhIndex, mIndex](Gringo::Model const &m) -> bool { + LuaClear lc(L); + lua_pushcfunction(L, luaTraceback); + lua_pushvalue(L, mhIndex); + lua_pushvalue(L, mIndex); + *model = &m; + int code = lua_pcall(L, 1, 1, -3); + Location loc("", 1, 1, "", 1, 1); + handleError(L, loc, code, "error in model callback", nullptr); + return lua_type(L, -1) == LUA_TNIL || lua_toboolean(L, -1); + }, std::move(*ass)); + })); + return 1; + } + static int cleanup(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "cleanup"); + protect(L, [&ctl]() { ctl.cleanupDomains(); }); + return 0; + } + static int solve_async(lua_State *L) { + return luaL_error(L, "asynchronous solving not supported"); + } + static int solve_iter(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "solve_iter"); + lua_pushstring(L, "statistics"); + lua_pushnil(L); + lua_rawset(L, 1); + int assIdx = !lua_isnone(L, 2) && !lua_isnil(L, 2) ? 2 : 0; + Control::Assumptions *ass = getAssumptions(L, assIdx); + auto &iter = *(Gringo::SolveIter **)lua_newuserdata(L, sizeof(Gringo::SolveIter*)); + iter = protect(L, [&ctl, ass]() { return ctl.solveIter(std::move(*ass)); }); + luaL_getmetatable(L, SolveIter::typeName); + lua_setmetatable(L, -2); + return 1; + } + static int assign_external(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "assign_external"); + Symbol atom = luaToVal(L, 2); + luaL_checkany(L, 3); + Potassco::Value_t truth; + if (lua_isnil (L, 3)) { truth = Potassco::Value_t::Free; } + else { + luaL_checktype(L, 3, LUA_TBOOLEAN); + truth = lua_toboolean(L, 3) ? Potassco::Value_t::True : Potassco::Value_t::False; + } + protect(L, [&ctl, atom, truth]() { ctl.assignExternal(atom, truth); }); + return 0; + } + static int release_external(lua_State *L) { + auto &ctl = get_self(L).ctl; + checkBlocked(L, ctl, "release_external"); + Symbol atom = luaToVal(L, 2); + protect(L, [&ctl, atom]() { ctl.assignExternal(atom, Potassco::Value_t::Release); }); + return 0; + } + static int interrupt(lua_State *L) { + get_self(L).ctl.interrupt(); + return 0; + } + static int newindex(lua_State *L) { + auto &ctl = get_self(L).ctl; + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "use_enumeration_assumption") == 0) { + bool enabled = lua_toboolean(L, 3); + checkBlocked(L, ctl, "use_enumeration_assumption"); + protect(L, [&ctl, enabled]() { ctl.useEnumAssumption(enabled); }); + return 0; + } + return luaL_error(L, "unknown field: %s", name); + } + + static int index(lua_State *L) { + auto &ctl = get_self(L).ctl; + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "use_enumeration_assumption") == 0) { + bool enabled = protect(L, [&ctl]() { return ctl.useEnumAssumption(); }); + lua_pushboolean(L, enabled); // stack +1 + return 1; + } + else if (strcmp(name, "statistics") == 0) { + checkBlocked(L, ctl, "statistics"); + lua_pushstring(L, "statistics"); // stack +1 + lua_rawget(L, 1); // stack +0 + if (lua_isnil(L, -1)) { + auto stats = protect(L, [&ctl](){ return ctl.statistics(); }); + lua_pop(L, 1); // stack -1 + newStatistics(L, stats, stats->root()); // stack +0 + lua_pushstring(L, "statistics"); // stack +1 + lua_pushvalue(L, -2); // stack +1 + lua_rawset(L, 1); // stack -2 + } + return 1; + } + else if (strcmp(name, "configuration") == 0) { + checkBlocked(L, ctl, "configuration"); + Gringo::ConfigProxy *proxy; + unsigned key; + protect(L, [&ctl, &proxy, &key]() -> void { + proxy = &ctl.getConf(); + key = proxy->getRootKey(); + }); + return Configuration::new_(L, key, *proxy); + } + else if (strcmp(name, "symbolic_atoms") == 0) { + checkBlocked(L, ctl, "symbolic_atoms"); + auto &proxy = protect(L, [&ctl]() -> Gringo::SymbolicAtoms& { return ctl.getDomain(); }); + return SymbolicAtoms::new_(L, proxy); + } + else if (strcmp(name, "theory_atoms") == 0) { + checkBlocked(L, ctl, "theory_atoms"); + return TheoryIter::iter(L, &ctl.theory()); + } + else if (strcmp(name, "backend") == 0) { + checkBlocked(L, ctl, "backend"); + auto *backend = protect(L, [&ctl](){ return ctl.backend(); }); + if (!backend) { return luaL_error(L, "backend not available"); } + return Backend::new_(L, ctl, *backend); + } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + static int newControl(lua_State *L) { + bool hasArg = !lua_isnone(L, 1); + std::vector *args = AnyWrap::new_>(L); + if (hasArg) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); + while (lua_next(L, 1) != 0) { + char const *arg = luaL_checkstring(L, -1); + protect(L, [arg, &args](){ args->push_back(arg); }); + lua_pop(L, 1); + } + } + std::vector *cargs = AnyWrap::new_>(L); + for (auto &arg : *args) { + protect(L, [&arg, &cargs](){ cargs->push_back(arg.c_str()); }); + } + return newControl(L, [cargs](void *mem){ new (mem) ControlWrap(*module->newControl(cargs->size(), cargs->data(), nullptr, 20), true); }); + } + template + static int newControl(lua_State *L, F f) { + lua_newtable(L); // +1 + auto self = (Gringo::ControlWrap*)lua_newuserdata(L, sizeof(ControlWrap)); // +1 + lua_rawseti(L, -2, 1); // -1 + protect(L, [self, f]() { f(self); }); + luaL_getmetatable(L, typeName); // +1 + lua_setmetatable(L, -2); // -1 + return 1; + } + static int gc(lua_State *L) { + auto &self = get_self(L); + if (self.free) { delete &self.ctl; } + return 0; + } + static int registerPropagator(lua_State *L); + static luaL_Reg meta[]; + static constexpr char const *typeName = "clingo.Control"; +}; + +constexpr char const *ControlWrap::typeName; +GringoModule *ControlWrap::module = nullptr; +luaL_Reg ControlWrap::meta[] = { + {"ground", ground}, + {"add", add}, + {"load", load}, + {"solve", solve}, + {"cleanup", cleanup}, + {"solve_async", solve_async}, + {"solve_iter", solve_iter}, + {"get_const", get_const}, + {"assign_external", assign_external}, + {"release_external", release_external}, + {"interrupt", interrupt}, + {"register_propagator", registerPropagator}, + {"__gc", gc}, + {nullptr, nullptr} +}; + +int luaMain(lua_State *L) { + auto ctl = (Control*)lua_touserdata(L, 1); + lua_getglobal(L, "main"); + ControlWrap::newControl(L, [ctl](void *mem) { new (mem) ControlWrap(*ctl, false); }); + lua_call(L, 1, 0); + return 0; +} + +// {{{1 wrap PropagateInit + +struct PropagateInit : Object { + lua_State *T; + Gringo::PropagateInit *init; + PropagateInit(lua_State *T, Gringo::PropagateInit *init) : T(T), init(init) { } + + static int mapLit(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + lua_pushnumber(L, protect(L, [self, lit]() { return self->init->mapLit(lit); })); + return 1; + } + + static int numThreads(lua_State *L) { + auto self = Object::self(L); + lua_pushnumber(L, protect(L, [self]() { return self->init->threads(); })); + return 1; + } + static int addWatch(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + protect(L, [self, lit]() { self->init->addWatch(lit); }); + return 0; + } + + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "theory_atoms") == 0) { return TheoryIter::iter(L, &self(L)->init->theory()); } + else if (strcmp(name, "symbolic_atoms") == 0) { return SymbolicAtoms::new_(L, self(L)->init->getDomain()); } + else if (strcmp(name, "threads") == 0) { return numThreads(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + + static int setState(lua_State *L) { + auto self = Object::self(L); + int id = luaL_checknumber(L, 2); + luaL_checkany(L, 3); + if (id < 1 || id > (int)self->init->threads()) { + luaL_error(L, "invalid solver thread id %d", id); + } + lua_xmove(L, self->T, 1); + lua_rawseti(self->T, 2, id); + return 0; + } + + static constexpr char const *typeName = "clingo.PropagateInit"; + static luaL_Reg const meta[]; +}; + +constexpr char const *PropagateInit::typeName; +luaL_Reg const PropagateInit::meta[] = { + {"solver_literal", mapLit}, + {"add_watch", addWatch}, + {"set_state", setState}, + {nullptr, nullptr} +}; + +// {{{1 wrap Assignment + +struct Assignment : Object { + Assignment(Potassco::AbstractAssignment const *ass) : ass(*ass) { } + Potassco::AbstractAssignment const &ass; + + static int hasConflict(lua_State *L) { + auto self = Object::self(L); + lua_pushboolean(L, protect(L, [self]() { return self->ass.hasConflict(); })); + return 1; + } + + static int decisionLevel(lua_State *L) { + auto self = Object::self(L); + lua_pushinteger(L, protect(L, [self]() { return self->ass.level(); })); + return 1; + } + + static int hasLit(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + lua_pushboolean(L, protect(L, [self,lit]() { return self->ass.hasLit(lit); })); + return 1; + } + + static int level(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + lua_pushinteger(L, protect(L, [self,lit]() { return self->ass.level(lit); })); + return 1; + } + + static int decision(lua_State *L) { + auto self = Object::self(L); + int level = luaL_checkinteger(L, 2); + lua_pushinteger(L, protect(L, [self,level]() { return self->ass.decision(level); })); + return 1; + } + + static int isFixed(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + lua_pushboolean(L, protect(L, [self,lit]() { return self->ass.isFixed(lit); })); + return 1; + } + + static int isTrue(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + lua_pushboolean(L, protect(L, [self,lit]() { return self->ass.isTrue(lit); })); + return 1; + } + + static int value(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + auto val = protect(L, [self, lit]() { return self->ass.value(lit); }); + if (val == Potassco::Value_t::Free) { lua_pushnil(L); } + else { lua_pushboolean(L, val == Potassco::Value_t::True); } + lua_pushboolean(L, val); + return 1; + } + + static int isFalse(lua_State *L) { + auto self = Object::self(L); + int lit = luaL_checkinteger(L, 2); + lua_pushboolean(L, protect(L, [self,lit]() { return self->ass.isFalse(lit); })); + return 1; + } + + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "has_conflict") == 0) { return hasConflict(L); } + if (strcmp(name, "decision_level") == 0) { return decisionLevel(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + + static constexpr char const *typeName = "clingo.Assignment"; + static luaL_Reg const meta[]; +}; + +constexpr char const *Assignment::typeName; +luaL_Reg const Assignment::meta[] = { + {"has_lit", hasLit}, + {"value", value}, + {"level", level}, + {"is_fixed", isFixed}, + {"is_true", isTrue}, + {"is_false", isFalse}, + {"decision", decision}, + {nullptr, nullptr} +}; + +// {{{1 wrap PropagateControl + +struct PropagateControl : Object { + PropagateControl(Potassco::AbstractSolver* ctl) : ctl(ctl) { } + Potassco::AbstractSolver* ctl; + + static int id(lua_State *L) { + auto self = Object::self(L); + lua_pushinteger(L, protect(L, [self]() { return self->ctl->id() + 1; })); + return 1; + } + + static int assignment(lua_State *L) { + auto self = Object::self(L); + Assignment::new_(L, protect(L, [self]() { return &self->ctl->assignment(); })); + return 1; + } + + static int addClauseOrNogood(lua_State *L, bool invert) { + auto self = Object::self(L); + lua_pushinteger(L, 1); // +1 + lua_gettable(L, 2); // +0 + luaL_checktype(L, -1, LUA_TTABLE); // +0 + int lits_index = lua_gettop(L); + auto lits = AnyWrap::new_>(L); // +1 + lua_pushnil(L); // +1 + while (lua_next(L, -3)) { // -1 + int lit = luaL_checkinteger(L, -1); // +0 + protect(L, [lits, lit](){ lits->emplace_back(lit); }); + lua_pop(L, 1); + } + unsigned type = 0; + lua_getfield(L, 2, "tag"); // +1 + if (lua_toboolean(L, -1)) { + type |= Potassco::Clause_t::Volatile; + } + lua_pop(L, 1); // -1 + lua_getfield(L, 2, "lock"); // +1 + if (lua_toboolean(L, -1)) { + type |= Potassco::Clause_t::Static; + } + lua_pop(L, 1); // -1 + lua_pushboolean(L, protect(L, [self, lits, type, invert]() { // +1 + if (invert) { + for (auto &lit : *lits) { lit = -lit; } + } + return self->ctl->addClause(Potassco::toSpan(*lits), static_cast(type)); + })); + lua_replace(L, lits_index); + lua_settop(L, lits_index); + return 1; + } + + static int addLiteral(lua_State *L) { + auto self = Object::self(L); + lua_pushnumber(L, protect(L, [self](){ return self->ctl->addVariable(); })); + return 1; + } + + static int addWatch(lua_State *L) { + auto self = Object::self(L); + auto lit = luaL_checkinteger(L, 1); + protect(L, [self, lit](){ self->ctl->addWatch(static_cast(lit)); }); + return 0; + } + + static int removeWatch(lua_State *L) { + auto self = Object::self(L); + auto lit = luaL_checkinteger(L, 1); + protect(L, [self, lit](){ self->ctl->removeWatch(static_cast(lit)); }); + return 0; + } + + static int hasWatch(lua_State *L) { + auto self = Object::self(L); + auto lit = luaL_checkinteger(L, 1); + auto ret = protect(L, [self, lit](){ return self->ctl->hasWatch(static_cast(lit)); }); + lua_pushboolean(L, ret); + return 1; + } + + static int addClause(lua_State *L) { + return addClauseOrNogood(L, false); + } + + static int addNogood(lua_State *L) { + return addClauseOrNogood(L, true); + } + + static int propagate(lua_State *L) { + auto self = Object::self(L); + lua_pushboolean(L, protect(L, [self]() { return self->ctl->propagate(); })); + return 1; + } + + static int index(lua_State *L) { + char const *name = luaL_checkstring(L, 2); + if (strcmp(name, "thread_id") == 0) { return id(L); } + if (strcmp(name, "assignment") == 0) { return assignment(L); } + else { + lua_getmetatable(L, 1); + lua_getfield(L, -1, name); + return !lua_isnil(L, -1) ? 1 : luaL_error(L, "unknown field: %s", name); + } + } + + static constexpr char const *typeName = "clingo.PropagateControl"; + static luaL_Reg const meta[]; +}; + +constexpr char const *PropagateControl::typeName; +luaL_Reg const PropagateControl::meta[] = { + {"add_literal", addLiteral}, + {"add_watch", addWatch}, + {"has_watch", hasWatch}, + {"remove_watch", removeWatch}, + {"add_clause", addClause}, + {"add_nogood", addNogood}, + {"propagate", propagate}, + {nullptr, nullptr} +}; + +// }}} +// {{{1 wrap Propagator + +class Propagator : public Gringo::Propagator { +public: + enum Indices : int { PropagatorIndex=1, StateIndex=2, ThreadIndex=3 }; + Propagator(lua_State *L, lua_State *T) : L(L), T(T) { } + static int init_(lua_State *L) { + auto *self = (Propagator*)lua_touserdata(L, 1); + auto *init = (Gringo::PropagateInit*)lua_touserdata(L, 2); + while (self->threads.size() < static_cast(init->threads())) { + self->threads.emplace_back(lua_newthread(L)); + lua_xmove(L, self->T, 1); + lua_rawseti(self->T, ThreadIndex, self->threads.size()); + } + lua_pushvalue(self->T, PropagatorIndex); // +1 + lua_xmove(self->T, L, 1); // +0 + lua_getfield(L, -1, "init"); // +1 + if (!lua_isnil(L, -1)) { + lua_insert(L, -2); + PropagateInit::new_(L, self->T, init); // +1 + lua_call(L, 2, 0); // -3 + } + else { lua_pop(L, 2); } // -2 + return 0; + } + void init(Gringo::PropagateInit &init) override { + threads.reserve(init.threads()); + if (!lua_checkstack(L, 4)) { throw std::runtime_error("lua stack size exceeded"); } + lua_pushcfunction(L, luaTraceback); + lua_pushcfunction(L, init_); + lua_pushlightuserdata(L, this); + lua_pushlightuserdata(L, &init); + auto ret = lua_pcall(L, 2, 0, -4); + if (ret != 0) { + Location loc("", 1, 1, "", 1, 1); + handleError(L, loc, ret, "initializing the propagator failed", nullptr); + } + } + static int getChanges(lua_State *L, Potassco::LitSpan const *changes) { + lua_newtable(L); + int m = changes->size; + for (int i = 0; i < m; ++i) { + lua_pushinteger(L, *(changes->first + i)); + lua_rawseti(L, -2, i+1); + } + return 1; + } + static int getState(lua_State *L, lua_State *T, Potassco::Id_t id) { + lua_rawgeti(T, StateIndex, id+1); + lua_xmove(T, L, 1); + return 1; + } + static int propagate_(lua_State *L) { + auto *self = static_cast(lua_touserdata(L, 1)); + auto *solver = static_cast(lua_touserdata(L, 2)); + auto *changes = static_cast(lua_touserdata(L, 3)); + lua_pushvalue(self->T, PropagatorIndex); // +1 + lua_xmove(self->T, L, 1); // +0 + lua_getfield(L, -1, "propagate"); // +1 + if (!lua_isnil(L, -1)) { + lua_insert(L, -2); + PropagateControl::new_(L, solver); // +1 + getChanges(L, changes); // +1 + getState(L, self->T, solver->id()); // +1 + lua_call(L, 4, 0); // -5 + } + else { + lua_pop(L, 2); // -2 + } + return 0; + } + void propagate(Potassco::AbstractSolver &solver, Potassco::LitSpan const &changes) override { + lua_State *L = threads[solver.id()]; + if (!lua_checkstack(L, 5)) { throw std::runtime_error("lua stack size exceeded"); } + LuaClear ll(T), lt(L); + lua_pushcfunction(L, luaTraceback); + lua_pushcfunction(L, propagate_); + lua_pushlightuserdata(L, this); + lua_pushlightuserdata(L, &solver); + lua_pushlightuserdata(L, &const_cast(changes)); + auto ret = lua_pcall(L, 3, 0, -5); + if (ret != 0) { + Location loc("", 1, 1, "", 1, 1); + handleError(L, loc, ret, "propagate failed", nullptr); + } + } + static int undo_(lua_State *L) { + auto *self = static_cast(lua_touserdata(L, 1)); + auto *solver = static_cast(lua_touserdata(L, 2)); + auto *changes = static_cast(lua_touserdata(L, 3)); + lua_pushvalue(self->T, PropagatorIndex); // +1 + lua_xmove(self->T, L, 1); // +0 + lua_getfield(L, -1, "undo"); // +1 + if (!lua_isnil(L, -1)) { + lua_insert(L, -2); + lua_pushnumber(L, solver->id()); // +1 + Assignment::new_(L, &solver->assignment()); // +1 + getChanges(L, changes); // +1 + getState(L, self->T, solver->id()); // +1 + lua_call(L, 5, 0); // -6 + } + else { + lua_pop(L, 2); // -2 + } + return 0; + } + void undo(Potassco::AbstractSolver const &solver, Potassco::LitSpan const &changes) override { + lua_State *L = threads[solver.id()]; + if (!lua_checkstack(L, 5)) { throw std::runtime_error("lua stack size exceeded"); } + LuaClear ll(T), lt(L); + lua_pushcfunction(L, luaTraceback); + lua_pushcfunction(L, undo_); + lua_pushlightuserdata(L, this); + lua_pushlightuserdata(L, &const_cast(solver)); + lua_pushlightuserdata(L, &const_cast(changes)); + auto ret = lua_pcall(L, 3, 0, -5); + if (ret != 0) { + Location loc("", 1, 1, "", 1, 1); + handleError(L, loc, ret, "undo failed", nullptr); + } + } + static int check_(lua_State *L) { + auto *self = static_cast(lua_touserdata(L, 1)); + auto *solver = static_cast(lua_touserdata(L, 2)); + lua_pushvalue(self->T, PropagatorIndex); // +1 + lua_xmove(self->T, L, 1); // +0 + lua_getfield(L, -1, "check"); // +1 + if (!lua_isnil(L, -1)) { + lua_insert(L, -2); // -1 + PropagateControl::new_(L, solver); // +1 + getState(L, self->T, solver->id()); // +1 + lua_call(L, 3, 0); // -4 + } + else { + lua_pop(L, 2); // -2 + } + return 0; + } + void check(Potassco::AbstractSolver &solver) override { + lua_State *L = threads[solver.id()]; + if (!lua_checkstack(L, 4)) { throw std::runtime_error("lua stack size exceeded"); } + LuaClear ll(T), lt(L); + lua_pushcfunction(L, luaTraceback); + lua_pushcfunction(L, check_); + lua_pushlightuserdata(L, this); + lua_pushlightuserdata(L, &solver); + auto ret = lua_pcall(L, 2, 0, -4); + if (ret != 0) { + Location loc("", 1, 1, "", 1, 1); + handleError(L, loc, ret, "check failed", nullptr); + } + } + virtual ~Propagator() noexcept = default; +private: + lua_State *L; + // global data for the executions stacks below + // (something similar could be achieved using the registry index + luaL_(un)ref) + lua_State *T; + // execution threads for progagators (executed in lock step) + std::vector threads; +}; + +int ControlWrap::registerPropagator(lua_State *L) { + auto &self = get_self(L); + lua_pushstring(L, "propagators"); // +1 + lua_rawget(L, 1); // +0 + if (lua_isnil(L, -1)) { + lua_pop(L, 1); // -1 + lua_newtable(L); // +1 + lua_pushstring(L, "propagators"); // +1 + lua_pushvalue(L, -2); // +1 + lua_rawset(L, 1); // -2 + } + auto *T = lua_newthread(L); // +1 + luaL_ref(L, -2); // -1 + lua_pop(L, 1); // -1 + lua_pushvalue(L, 2); // +1 + lua_xmove(L, T, 1); // -1 + lua_newtable(T); + lua_newtable(T); + protect(L, [L, T, &self]() { self.ctl.registerPropagator(gringo_make_unique(L, T), true); }); + return 0; +} + +// {{{1 wrap module functions + +int parseTerm(lua_State *L) { + char const *str = luaL_checkstring(L, 1); + Symbol val = protect(L, [str]() { return ControlWrap::module->parseValue(str, nullptr, 20); }); + if (val.type() == Gringo::SymbolType::Special) { lua_pushnil(L); } + else { Term::new_(L, val); } + return 1; +} + + +// {{{1 clingo library + +int luaopen_clingo(lua_State* L) { + static luaL_Reg clingoLib[] = { + {"Function", Term::newFun}, + {"Tuple", Term::newTuple}, + {"Number", Term::newNumber}, + {"String", Term::newString}, + {"Control", ControlWrap::newControl}, + {"parse_term", parseTerm}, + {nullptr, nullptr} + }; + + lua_regMeta(L, Term::typeName, Term::meta, Term::index); + lua_regMeta(L, SymbolType::typeName, SymbolType::meta); + lua_regMeta(L, Model::typeName, Model::meta, Model::index); + lua_regMeta(L, SolveControl::typeName, SolveControl::meta); + lua_regMeta(L, SolveFuture::typeName, SolveFuture::meta); + lua_regMeta(L, SolveIter::typeName, SolveIter::meta); + lua_regMeta(L, ControlWrap::typeName, ControlWrap::meta, ControlWrap::index, ControlWrap::newindex); + lua_regMeta(L, Configuration::typeName, Configuration::meta, Configuration::index, Configuration::newindex); + lua_regMeta(L, SolveResult::typeName, SolveResult::meta, SolveResult::index); + lua_regMeta(L, SymbolicAtoms::typeName, SymbolicAtoms::meta, SymbolicAtoms::index); + lua_regMeta(L, SymbolicAtom::typeName, SymbolicAtom::meta, SymbolicAtom::index); + lua_regMeta(L, AnyWrap::typeName, AnyWrap::meta); + lua_regMeta(L, TheoryTermType::typeName, TheoryTermType::meta); + lua_regMeta(L, TheoryTerm::typeName, TheoryTerm::meta, TheoryTerm::index); + TheoryElement::reg(L); + TheoryAtom::reg(L); + PropagateInit::reg(L); + PropagateControl::reg(L); + Assignment::reg(L); + Backend::reg(L); + +#if LUA_VERSION_NUM < 502 + luaL_register(L, "clingo", clingoLib); +#else + luaL_newlib(L, clingoLib); +#endif + + lua_pushstring(L, GRINGO_VERSION); + lua_setfield(L, -2, "__version__"); + + SymbolType::addToRegistry(L); + Term::addToRegistry(L); + TheoryTermType::addToRegistry(L); + + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "clingo"); + + return 1; +} + +int luarequire_clingo(lua_State *L) { + luaL_openlibs(L); +#if LUA_VERSION_NUM < 502 + lua_pushcfunction(L, luaopen_clingo); + lua_call(L, 0, 1); +#else + luaL_requiref(L, "clingo", luaopen_clingo, true); +#endif + return 1; +} + +// }}}1 + +} // namespace + +// {{{1 definition of LuaImpl + +struct LuaImpl { + LuaImpl() : L(luaL_newstate()) { + if (!L) { throw std::runtime_error("could not open lua state"); } + int n = lua_gettop(L); + lua_pushcfunction(L, luaTraceback); + lua_pushcfunction(L, luarequire_clingo); + int ret = lua_pcall(L, 0, 0, -2); + Location loc("", 1, 1, "", 1, 1); + handleError(L, loc, ret, "running lua script failed", nullptr); + lua_settop(L, n); + } + ~LuaImpl() { + if (L) { lua_close(L); } + } + lua_State *L; +}; + +// {{{1 definition of Lua + +Lua::Lua(GringoModule &module) { + ControlWrap::module = &module; +} + +bool Lua::exec(Location const &loc, String code) { + if (!impl) { impl = gringo_make_unique(); } + LuaClear lc(impl->L); + std::stringstream oss; + oss << loc; + lua_pushcfunction(impl->L, luaTraceback); + int ret = luaL_loadbuffer(impl->L, code.c_str(), code.length(), oss.str().c_str()); + handleError(impl->L, loc, ret, "parsing lua script failed", nullptr); + ret = lua_pcall(impl->L, 0, 0, -2); + handleError(impl->L, loc, ret, "running lua script failed", nullptr); + return true; +} + +SymVec Lua::call(Location const &loc, String name, SymSpan args, Logger &log) { + assert(impl); + LuaClear lc(impl->L); + LuaCallArgs arg(name.c_str(), args, {}); + lua_pushcfunction(impl->L, luaTraceback); + lua_pushcfunction(impl->L, luaCall); + lua_pushlightuserdata(impl->L, (void*)&arg); + lua_pushnil(impl->L); + int ret = lua_pcall(impl->L, 2, 0, -4); + if (!handleError(impl->L, loc, ret, "operation undefined", &log)) { return {}; } + return std::move(std::get<2>(arg)); +} + +bool Lua::callable(String name) { + if (!impl) { return false; } + LuaClear lc(impl->L); + lua_getglobal(impl->L, name.c_str()); + bool ret = lua_type(impl->L, -1) == LUA_TFUNCTION; + return ret; +} + +void Lua::main(Control &ctl) { + assert(impl); + LuaClear lc(impl->L); + lua_pushcfunction(impl->L, luaTraceback); + lua_pushcfunction(impl->L, luaMain); + lua_pushlightuserdata(impl->L, (void*)&ctl); + switch (lua_pcall(impl->L, 1, 0, -3)) { + case LUA_ERRRUN: + case LUA_ERRERR: { + Location loc("", 1, 1, "", 1, 1); + std::ostringstream oss; + oss << loc << ": " << "error: executing main function failed:\n" + << " RuntimeError: " << lua_tostring(impl->L, -1) << "\n" + ; + lua_pop(impl->L, 1); + throw GringoError(oss.str().c_str()); + } + case LUA_ERRMEM: { throw std::runtime_error("lua interpreter ran out of memory"); } + } +} +void Lua::initlib(lua_State *L, GringoModule &module) { + ControlWrap::module = &module; + luarequire_clingo(L); +} +Lua::~Lua() = default; + +// }}}1 + +} // namespace Gringo + +#else // WITH_LUA + +#include "gringo/lua.hh" +#include "gringo/logger.hh" + +namespace Gringo { + +// {{{1 definition of LuaImpl + +struct LuaImpl { }; + +// {{{1 definition of Lua + +Lua::Lua(Gringo::GringoModule &) { } +bool Lua::exec(Location const &loc, String) { + std::ostringstream oss; + oss << loc << ": error: clingo has been build without lua support\n"; + throw GringoError(oss.str().c_str()); +} +bool Lua::callable(String) { + return false; +} +SymVec Lua::call(Location const &, String, SymSpan, Logger &) { + return {}; +} +void Lua::main(Control &) { } +void Lua::initlib(lua_State *, Gringo::GringoModule &) { + throw std::runtime_error("clingo lib has been build without lua support"); +} +Lua::~Lua() = default; + +// }}}1 + +} // namespace Gringo + +#endif // WITH_LUA + diff --git a/libgringo/src/output/aggregates.cc b/libgringo/src/output/aggregates.cc new file mode 100644 index 0000000..aadfbec --- /dev/null +++ b/libgringo/src/output/aggregates.cc @@ -0,0 +1,440 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 definition of AggregateAnalyzer + +void AggregateAnalyzer::print(std::ostream &out) { + auto printInterval = [&](Interval const &x) { + out << (x.left.inclusive ? "[" : "("); + out << x.left.bound; + out << ","; + out << x.right.bound; + out << (x.right.inclusive ? "]" : ")"); + }; + out << "analyze result: " << std::endl; + out << " range: "; + printInterval(range); + std::cerr << std::endl; + std::cerr << " bounds:" << std::endl; + for (auto &x : bounds) { + out << " "; + printInterval(x.first); + out << " "; + printInterval(x.second); + out << std::endl; + } + out << " monotonicity: "; + switch (monotonicity) { + case Monotonicity::MONOTONE: { out << "monotone"; break; } + case Monotonicity::ANTIMONOTONE: { out << "antimonotone"; break; } + case Monotonicity::CONVEX: { out << "convex"; break; } + case Monotonicity::NONMONOTONE: { out << "nonmonotone"; break; } + } + out << std::endl; + out << " weights: "; + switch (weightType) { + case WeightType::POSITIVE: { out << "positive"; break; } + case WeightType::NEGATIVE: { out << "negative"; break; } + case WeightType::MIXED: { out << "mixed"; break; } + } + out << std::endl; + out << " truth: "; + switch (truth) { + case Truth::True: { out << "true"; break; } + case Truth::Open: { out << "open"; break; } + case Truth::False: { out << "false"; break; } + } + out << std::endl; +} + +AggregateAnalyzer::AggregateAnalyzer(DomainData &data, NAF naf, DisjunctiveBounds const &disjunctiveBounds, AggregateFunction fun, Interval range, BodyAggregateElements const &elems) +: range(range) { + // NOTE: considers everything that is fixed in a reduct as ANTIMONOTONE + weightType = POSITIVE; + IntervalSet numBounds; + for (auto &y : disjunctiveBounds) { + Interval x = y; + if (!x.right.inclusive && x.right.bound.type() == SymbolType::Num) { + x.right.inclusive = true; + x.right.bound = Symbol::createNum(x.right.bound.num() - 1); + } + if (!x.left.inclusive && x.left.bound.type() == SymbolType::Num) { + x.left.inclusive = true; + x.left.bound = Symbol::createNum(x.left.bound.num() + 1); + } + numBounds.add(x); + } + IntervalSet complement(IntervalSet(range).difference(numBounds)); + bool nonMonotone = false; + for (auto &y : complement) { + Interval x = y; + if (x.right.inclusive && x.right.bound.type() == SymbolType::Num) { + x.right.inclusive = false; + x.right.bound = Symbol::createNum(x.right.bound.num() + 1); + } + if (x.left.inclusive && x.left.bound.type() == SymbolType::Num) { + x.left.inclusive = false; + x.left.bound = Symbol::createNum(x.left.bound.num() - 1); + } + IntervalSet::Interval a, b; + a.left = range.left; + a.right = x.left; + b.left = x.right; + b.right = range.right; + if (a.empty() && b.empty()) { + truth = False; + monotonicity = ANTIMONOTONE; + bounds.clear(); + bounds.emplace_back(a, b); + return; + } + bounds.emplace_back(a, b); + if (!a.empty() && !b.empty()) { + nonMonotone = true; + } + } + if (bounds.empty()) { + truth = True; + monotonicity = MONOTONE; + } + else { + truth = Open; + bool hasPositive = false; + bool hasPositiveWeight = false; + bool hasNegativeWeight = false; + for (auto &x : elems) { + bool hasPositiveLiteral = false; + for (auto &y : x.second) { + for (auto &z : data.clause(y)) { + if (z.sign() == NAF::POS) { + hasPositive = true; + hasPositiveLiteral = true; + break; + } + } + auto tuple = data.tuple(x.first); + if (hasPositiveLiteral && !tuple.empty() && tuple.front().type() == SymbolType::Num) { + if (tuple.front().num() < 0) { hasNegativeWeight = true; } + if (tuple.front().num() > 0) { hasPositiveWeight = true; } + } + } + } + if (fun == AggregateFunction::SUM) { + if (hasNegativeWeight && hasPositiveWeight) { + weightType = MIXED; + nonMonotone = true; + } + if (hasNegativeWeight && !hasPositiveWeight) { + weightType = NEGATIVE; + } + } + if (naf != NAF::POS || !hasPositive) { monotonicity = ANTIMONOTONE; } + else if (nonMonotone) { monotonicity = NONMONOTONE; } + else if (bounds.size() == 1) { + bool flip = fun == AggregateFunction::MIN || (fun == AggregateFunction::SUM && weightType == NEGATIVE); + if (bounds.front().first.empty()) { flip = !flip; } + monotonicity = flip ? MONOTONE : ANTIMONOTONE;; + } + else { + monotonicity = CONVEX; + } + } +} + +LitValVec AggregateAnalyzer::translateElems(DomainData &data, Translator &x, AggregateFunction fun, BodyAggregateElements const &bdElems, bool incomplete) { + LitValVec elems; + for (auto &y : bdElems) { + Symbol weight(getWeight(fun, data.tuple(y.first))); + LiteralId lit = getEqualFormula(data, x, y.second, false, monotonicity == AggregateAnalyzer::NONMONOTONE && incomplete); + elems.emplace_back(std::move(lit), weight); + } + + return elems; +} + +// {{{1 definition of MinMaxTranslator + +LiteralId MinMaxTranslator::translate(DomainData &data, Translator &x, AggregateAnalyzer &res, bool isMin, LitValVec &&elems, bool incomplete) { + // NOTE: passing the elems vec as a list of weighted formulas + // could be exploited to add fewer disjunctions than translateElems adds at the moment + // (same goes for sum aggregates) + LitVec conjunction; + for (auto &bound : res.bounds) { + // translation overview (min): + // |--A--| B |--C--| + // (B => A) + // note that B is true if C is empty! + // if not incomplete or not nonmonotone: + // (~B | A) + bool hasAntecedent = isMin ? !bound.second.empty() : !bound.first.empty(); + LitVec antecedent; + LitVec consequent; + for (auto &elem : elems) { + if (res.range.contains(elem.second)) { + if (bound.first.contains(elem.second)) { + if (isMin) { consequent.emplace_back(elem.first); } + } + else if (bound.second.contains(elem.second)) { + if (!isMin) { consequent.emplace_back(elem.first); } + } + else { + if (hasAntecedent) { antecedent.emplace_back(elem.first); } + } + } + } + if (hasAntecedent) { + assert(!antecedent.empty()); + if (consequent.empty()) { + for (auto &lit : antecedent) { conjunction.emplace_back(lit.negate()); } + } + else { + if (incomplete && res.monotonicity == AggregateAnalyzer::NONMONOTONE) { + // (a | b | c => x | y | z) => q + // is equivalent to + // a | b | c <=> a1. + // x | y | z => a2. + // a2 => q + // ~a1 => q + // ~~a2 => a1 | q + LiteralId q = data.newAux(); + LiteralId a1 = getEqualClause(data, x, data.clause(std::move(antecedent)), false, true); + LiteralId a2 = getEqualClause(data, x, data.clause(std::move(consequent)), false, false); + Rule().addHead(q).addBody(a2).translate(data, x); + Rule().addHead(q).addBody(a1.negate()).translate(data, x); + Rule().addHead(q).addHead(a1).addBody(a2.negate().negate()).translate(data, x); + conjunction.emplace_back(q); + } + else { + LiteralId aux = data.newAux(); + for (auto &lit : consequent) { Rule().addHead(aux).addBody(lit).translate(data, x); } + Rule negated; + for (auto &lit : antecedent) { negated.addBody(lit.negate()); } + negated.addHead(aux).translate(data, x); + conjunction.emplace_back(aux); + } + } + } + else { + assert(!consequent.empty()); + conjunction.emplace_back(getEqualClause(data, x, data.clause(std::move(consequent)), false, false)); + } + } + LiteralId ret = getEqualClause(data, x, data.clause(std::move(conjunction)), true, false); + return call(data, ret, &Literal::translate, x); +} + +// {{{1 definition of SumTranslator + +void SumTranslator::addLiteral(DomainData &data, LiteralId const &lit, Potassco::Weight_t weight, bool recursive) { + if (weight > 0) { + if (!recursive || lit.invertible() || call(data, lit, &Literal::isAtomFromPreviousStep)) { + litsPosStrat.emplace_back(get_clone(lit), weight); + } + else { + litsPosRec.emplace_back(get_clone(lit), weight); + } + } + else if (weight < 0) { + if (!recursive || lit.invertible() || call(data, lit, &Literal::isAtomFromPreviousStep)) { + litsNegStrat.emplace_back(get_clone(lit), -weight); + } + else { + litsNegRec.emplace_back(get_clone(lit), -weight); + } + } +} + +void SumTranslator::translate(DomainData &data, Translator &x, LiteralId const &head, Potassco::Weight_t bound, LitUintVec const &litsPosRec, LitUintVec const &litsNegRec, LitUintVec const &litsPosStrat, LitUintVec const &litsNegStrat) { + LitUintVec elems; + for (auto &wLit : litsPosRec) { elems.emplace_back(get_clone(wLit.first), wLit.second); } + for (auto &wLit : litsPosStrat) { elems.emplace_back(get_clone(wLit.first), wLit.second); } + for (auto &wLit : litsNegStrat) { + bound+= wLit.second; + elems.emplace_back(wLit.first.negate(), wLit.second); + } + for (auto &wLit : litsNegRec) { + bound+= wLit.second; + LiteralId aux = data.newAux(); + elems.emplace_back(get_clone(aux), wLit.second); + Rule().addHead(aux).addBody(wLit.first.negate()).translate(data, x); + Rule().addHead(aux).addBody(head).translate(data, x); + Rule().addHead(aux).addHead(wLit.first).addHead(head.negate()).translate(data, x); + } + WeightRule(head, bound, std::move(elems)).translate(data, x); +} + +LiteralId SumTranslator::translate(DomainData &data, Translator &x, ConjunctiveBounds &bounds, bool convex, bool invert) { + LitVec clause; + for (auto &bound : bounds) { + assert(!bound.first.empty() || !bound.second.empty()); + LiteralId pos, neg; + if (!bound.second.empty()) { + if (invert && convex) { + if (!neg) { neg = data.newAux(); } + Potassco::Weight_t lower = 1 - bound.second.left.bound.num(); + translate(data, x, neg, lower, litsNegRec, litsPosRec, litsNegStrat, litsPosStrat); + } + else { + if (!pos) { pos = data.newAux(); } + Potassco::Weight_t lower = bound.second.left.bound.num(); + translate(data, x, pos, lower, litsPosRec, litsNegRec, litsPosStrat, litsNegStrat); + } + } + if (!bound.first.empty()) { + if (!invert && convex) { + if (!neg) { neg = data.newAux(); } + Potassco::Weight_t lower = 1 + bound.first.right.bound.num(); + translate(data, x, neg, lower, litsPosRec, litsNegRec, litsPosStrat, litsNegStrat); + } + else { + if (!pos) { pos = data.newAux(); } + Potassco::Weight_t lower = -bound.first.right.bound.num(); + translate(data, x, pos, lower, litsNegRec, litsPosRec, litsNegStrat, litsPosStrat); + } + } + LitVec disjunction; + if (pos) { disjunction.emplace_back(std::move(pos)); } + if (neg) { disjunction.emplace_back(neg.negate()); } + clause.emplace_back(getEqualClause(data, x, data.clause(std::move(disjunction)), false, false)); + } + auto ret = getEqualClause(data, x, data.clause(std::move(clause)), true, false); + return call(data, ret, &Literal::translate, x); +} + +// {{{1 definition of translation functions + +namespace { + +LiteralId getEqualClause(DomainData &data, Translator &x, IteratorRange clause, bool conjunctive, bool equivalence) { + if (clause.empty()) { + return conjunctive ? data.getTrueLit() : data.getTrueLit().negate(); + } + else if (clause.size() == 1) { + LiteralId lit = clause.front(); + if (equivalence && call(data, clause.front(), &Literal::isAtomFromPreviousStep)) { + lit = lit.negate(); + lit = lit.negate(); + } + return std::move(clause.front()); + } + else { + LiteralId aux = data.newAux(); + if (conjunctive) { + if (equivalence) { + for (auto &lit : clause) { + Rule().addHead(lit).addBody(aux).negatePrevious(data).translate(data, x); + } + } + Rule().addHead(aux).addBody(clause).translate(data, x); + } + else { + for (auto &lit : clause) { Rule().addHead(aux).addBody(lit).translate(data, x); } + if (equivalence) { + Rule().addHead(clause).addBody(aux).negatePrevious(data).translate(data, x); + } + } + return aux; + } +} + +} // namespace + +LiteralId getEqualClause(DomainData &data, Translator &x, std::pair id, bool conjunctive, bool equivalence) { + if (id.second > 1) { + auto ret = x.clause(id, conjunctive, equivalence); + if (!ret) { + ret = getEqualClause(data, x, data.clause(id), conjunctive, equivalence); + x.clause(ret, id, conjunctive, equivalence); + } + return ret; + } + else { + return getEqualClause(data, x, data.clause(id), conjunctive, equivalence); + } +} + +LiteralId getEqualFormula(DomainData &data, Translator &x, Formula const &formula, bool conjunctive, bool equivalence) { + LitVec disjunction; + for (auto &conjunction : formula) { + disjunction.emplace_back(getEqualClause(data, x, data.clause(conjunction), !conjunctive, equivalence)); + } + return getEqualClause(data, x, data.clause(std::move(disjunction)), conjunctive, equivalence); +} + +LiteralId getEqualAggregate(DomainData &data, Translator &x, AggregateFunction fun, NAF naf, DisjunctiveBounds const &bounds, Interval const &range, BodyAggregateElements const &bdElems, bool recursive) { + AggregateAnalyzer res(data, naf, bounds, fun, range, bdElems); + //res.print(std::cerr); + LiteralId aux; + if (res.truth == AggregateAnalyzer::True) { + aux = data.getTrueLit(); + } + else if (res.truth == AggregateAnalyzer::False) { + aux = data.getTrueLit().negate(); + } + else { + recursive = res.monotonicity == AggregateAnalyzer::NONMONOTONE && recursive; + LitValVec elems = res.translateElems(data, x, fun, bdElems, recursive); + if (elems.size() == 1) { + bool hasElem = bounds.contains({{elems.front().second, true}, {elems.front().second, true}}); + bool hasEmpty = bounds.contains({{getNeutral(fun), true}, {getNeutral(fun), true}}); + if (hasElem && hasEmpty) { aux = data.getTrueLit(); } + else if (hasElem) { aux = std::move(elems.front().first); } + else if (hasEmpty) { aux = elems.front().first.negate(); } + else { aux = data.getTrueLit().negate(); } + } + else { + switch (fun) { + case AggregateFunction::COUNT: + case AggregateFunction::SUMP: + case AggregateFunction::SUM: { + SumTranslator trans; + for (auto &elem : elems) { + trans.addLiteral(data, elem.first, elem.second.num(), recursive); + } + aux = trans.translate(data, x, res.bounds, !recursive, res.weightType == AggregateAnalyzer::NEGATIVE); + break; + } + case AggregateFunction::MIN: + case AggregateFunction::MAX: { + MinMaxTranslator trans; + aux = trans.translate(data, x, res, fun == AggregateFunction::MIN, std::move(elems), recursive); + break; + } + } + } + } + switch (naf) { + case NAF::NOTNOT: + aux = aux.negate(); + case NAF::NOT: + aux = aux.negate(); + default: + return call(data, aux, &Literal::translate, x); + } +} + +// }}}1 + +} } // namespace Output Gringo diff --git a/libgringo/src/output/literal.cc b/libgringo/src/output/literal.cc new file mode 100644 index 0000000..7a2016f --- /dev/null +++ b/libgringo/src/output/literal.cc @@ -0,0 +1,63 @@ +#include +#include +#include + +namespace Gringo { namespace Output { + +void PrintPlain::printElem(Potassco::Id_t x) { + domain.theory().printElem(stream, x, [this](std::ostream &, LiteralId const &lit){ call(domain, lit, &Literal::printPlain, *this); }); +} + +void PrintPlain::printTerm(Potassco::Id_t x) { + domain.theory().printTerm(stream, x); +} + +bool isTrueClause(DomainData &data, LitVec &lits, IsTrueLookup lookup) { + for (auto &lit : lits) { + if (!call(data, lit, &Literal::isTrue, lookup)) { + return false; + } + } + return true; +} + +bool Literal::isAtomFromPreviousStep() const { + return false; +} + +bool Literal::isHeadAtom() const { + return false; +} + +bool Literal::isIncomplete() const { + return false; +} + +std::pair Literal::delayedLit() { + throw std::logic_error("Literal::hasDelayedOffset: not implemented"); +} + +bool Literal::isBound(Symbol &, bool) const { + return false; +} + +void Literal::updateBound(std::vector &, bool) const { +} + +bool Literal::needsSemicolon() const { + return false; +} + +bool Literal::isPositive() const { + return true; +} + +LiteralId Literal::simplify(Mappings &, AssignmentLookup) const { + throw std::logic_error("Literal::simplify: not implemented"); +} + +bool Literal::isTrue(IsTrueLookup) const { + throw std::logic_error("Literal::isTrue: not implemented"); +} + +} } // namespace Output Gringo diff --git a/libgringo/src/output/literals.cc b/libgringo/src/output/literals.cc new file mode 100644 index 0000000..076dae1 --- /dev/null +++ b/libgringo/src/output/literals.cc @@ -0,0 +1,1844 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 definition of functions to work with BodyAggregates + +namespace { + +void printLit(PrintPlain out, LiteralId lit) { + call(out.domain, lit, &Literal::printPlain, out); +} + +void printCond(PrintPlain out, TupleId tuple, Formula::value_type cond) { + print_comma(out, out.domain.tuple(tuple), ","); + out << ":"; + auto rng = out.domain.clause(cond.first, cond.second); + print_comma(out, rng, ",", [](PrintPlain out, LiteralId lit) { printLit(out, lit); }); +} + +void printCond(PrintPlain out, TupleId tuple, HeadFormula::value_type const &cond) { + print_comma(out, out.domain.tuple(tuple), ","); + out << ":"; + if (cond.first.valid()) { printLit(out, cond.first); } + else { out << "#true"; } + if (cond.second.second > 0) { + out << ":"; + auto rng = out.domain.clause(cond.second.first, cond.second.second); + print_comma(out, rng, ",", [](PrintPlain out, LiteralId lit) { printLit(out, lit); }); + } +} + +void printBodyElem(PrintPlain out, BodyAggregateElements::ValueType const &x) { + if (x.second.empty()) { print_comma(out, out.domain.tuple(x.first), ","); } + else { print_comma(out, x.second, ";", [&x](PrintPlain out, Formula::value_type cond) { printCond(out, x.first, cond); }); } +} + +void printHeadElem(PrintPlain out, HeadAggregateElements::ValueType const &x) { + print_comma(out, x.second, ";", [&x](PrintPlain out, HeadFormula::value_type const &cond) { printCond(out, x.first, cond); }); +} + +template +void makeFalse(DomainData &data, Translator &trans, NAF naf, Atom &atm) { + LiteralId atomlit; + switch (naf) { + case NAF::POS: { atomlit = data.getTrueLit().negate(); break; } + case NAF::NOT: { atomlit = data.getTrueLit(); break; } + case NAF::NOTNOT: { atomlit = data.getTrueLit().negate(); break; } + } + auto lit = atm.lit(); + if (lit) { + assert(lit.sign() == NAF::POS); + Rule().addHead(lit).addBody(atomlit).translate(data, trans); + } + else { atm.setLit(atomlit); } +} + +} // namespace + +int clamp(int64_t x) { + if (x > std::numeric_limits::max()) { return std::numeric_limits::max(); } + if (x < std::numeric_limits::min()) { return std::numeric_limits::min(); } + return int(x); +} + +bool defined(SymVec const &tuple, AggregateFunction fun, Location const &loc, Logger &log) { + if (tuple.empty()) { + if (fun == AggregateFunction::COUNT) { return true; } + else { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: empty tuple ignored\n"; + return false; + } + } + if (tuple.front().type() == SymbolType::Special) { return true; } + switch (fun) { + case AggregateFunction::MIN: + case AggregateFunction::MAX: + case AggregateFunction::COUNT: { return true; } + case AggregateFunction::SUM: + case AggregateFunction::SUMP: { + if (tuple.front().type() == SymbolType::Num) { return true; } + else { + std::ostringstream s; + print_comma(s, tuple, ","); + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: tuple ignored:\n" + << " " << s.str() << "\n"; + return false; + } + } + } + return true; +} + + +bool neutral(SymVec const &tuple, AggregateFunction fun, Location const &loc, Logger &log) { + if (tuple.empty()) { + if (fun == AggregateFunction::COUNT) { return false; } + else { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: empty tuple ignored\n"; + return true; + } + } + else if (tuple.front().type() != SymbolType::Special) { + bool ret = true; + switch (fun) { + case AggregateFunction::MIN: { return tuple.front() == Symbol::createSup(); } + case AggregateFunction::MAX: { return tuple.front() == Symbol::createInf(); } + case AggregateFunction::COUNT: { return false; } + case AggregateFunction::SUM: { ret = tuple.front().type() != SymbolType::Num || tuple.front() == Symbol::createNum(0); break; } + case AggregateFunction::SUMP: { ret = tuple.front().type() != SymbolType::Num || tuple.front() <= Symbol::createNum(0); break; } + } + if (ret && tuple.front() != Symbol::createNum(0)) { + std::ostringstream s; + print_comma(s, tuple, ","); + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: tuple ignored:\n" + << " " << s.str() << "\n"; + } + return ret; + } + return true; +} + +int toInt(IntervalSet::LBound const &x) { + if (x.bound.type() == SymbolType::Num) { + return x.inclusive ? x.bound.num() : x.bound.num() + 1; + } + else { + if (x.bound < Symbol::createNum(0)) { return std::numeric_limits::min(); } + else { return std::numeric_limits::max(); } + } +} + +int toInt(IntervalSet::RBound const &x) { + if (x.bound.type() == SymbolType::Num) { + return x.inclusive ? x.bound.num() : x.bound.num() - 1; + } + else { + if (x.bound < Symbol::createNum(0)) { return std::numeric_limits::min(); } + else { return std::numeric_limits::max(); } + } +} + +Symbol getWeight(AggregateFunction fun, SymVec const &x) { + return fun == AggregateFunction::COUNT ? Symbol::createNum(1) : x.front(); +} + +Symbol getWeight(AggregateFunction fun, IteratorRange rng) { + return fun == AggregateFunction::COUNT ? Symbol::createNum(1) : rng.front(); +} + +// {{{1 definition of AggregateAtomRange + +void AggregateAtomRange::init(AggregateFunction fun, DisjunctiveBounds &&bounds) { + switch (fun) { + case AggregateFunction::MIN: { + valMin() = Symbol::createSup(); + valMax() = Symbol::createSup(); + break; + } + case AggregateFunction::MAX: { + valMin() = Symbol::createInf(); + valMax() = Symbol::createInf(); + break; + } + default: { + intMin() = 0; + intMax() = 0; + break; + } + } + this->fun = fun; + this->bounds = std::move(bounds); +} + +Interval AggregateAtomRange::range() const { + if (fun != AggregateFunction::MIN && fun != AggregateFunction::MAX) { + return {{Symbol::createNum(clamp(intMin())), true}, {Symbol::createNum(clamp(intMax())), true}}; + } + else { return {{valMin(), true}, {valMax(), true}}; } +} + +PlainBounds AggregateAtomRange::plainBounds() { + // There are 3 cases: + // (a) disjunctive bounds are open to the left: > or >= + // (b) disjunctive bounds are open to the right: < or <= + // (c) < and > follow each other: != + // Case (c) can furthermore correspond to one or two != occurrences. + PlainBounds cBounds; + auto rng = range(); + for (auto part : bounds) { + if (rng.left < part.left) { + // (a) + if (cBounds.empty()) { + cBounds.emplace_back(part.left.inclusive ? Relation::GEQ : Relation::GT, part.left.bound); + } + // (c) + else { + assert(cBounds.back().first == Relation::LT || cBounds.back().first == Relation::LEQ); + Symbol left = cBounds.back().second; + if (cBounds.back().first == Relation::LEQ) { + assert(left.type() == SymbolType::Num); + left = Symbol::createNum(left.num() + 1); + } + Symbol right = part.left.bound; + if (part.left.inclusive) { + assert(right.type() == SymbolType::Num); + right = Symbol::createNum(right.num() - 1); + } + cBounds.back() = {Relation::NEQ, left}; + if (left != right) { + cBounds.back() = {Relation::NEQ, right}; + } + } + } + if (part.right < rng.right) { + // (b) + cBounds.emplace_back(part.right.inclusive ? Relation::LEQ : Relation::LT, part.right.bound); + } + } + assert(cBounds.size() < 3); + return cBounds; + +} + +void AggregateAtomRange::accumulate(SymVec const &tuple, bool fact, bool remove) { + switch (fun) { + case AggregateFunction::MIN: { + Symbol val = tuple.front(); + if (fact) { valMax() = std::min(valMax(), val); } + valMin() = std::min(valMin(), val); + break; + } + case AggregateFunction::MAX: { + Symbol val = tuple.front(); + if (fact) { valMin() = std::max(valMin(), val); } + valMax() = std::max(valMax(), val); + break; + } + default: { + int64_t val = fun == AggregateFunction::COUNT ? 1 : tuple.front().num(); + if (fact) { + if (remove) { + if (val < 0) { intMax()+= val; } + else { intMin()+= val; } + } + else { + intMin()+= val; + intMax()+= val; + } + } + else { + if (val < 0) { intMin()+= val; } + else { intMax()+= val; } + } + break; + } + } +} + +// {{{1 definition of BodyAggregateAtom + +class BodyAggregateElements_::TupleOffset { +public: + TupleOffset(Id_t offset, Id_t size, bool fact) + : repr_(fact | (static_cast(size) << 1) | (static_cast(offset) << 32)) { } + TupleOffset(uint64_t repr) + : repr_(repr) { } + bool fact() const { return repr_ & 1; } + Id_t size() const { return static_cast(repr_) >> 1; } + Id_t offset() const { return static_cast(repr_ >> 32); } + uint64_t repr() const { return repr_; } + operator uint64_t() const { return repr(); } +private: + uint64_t repr_; +}; + +class BodyAggregateElements_::ClauseOffset { +public: + ClauseOffset(Id_t offset, Id_t size) + : repr_(std::max(size-1, Id_t(3)) | (offset << 2)) { + assert(size > 0); + } + ClauseOffset(uint32_t repr) + : repr_(repr) { } + Id_t size() const { return (repr_ & 3) < 3 ? (repr_ & 3) + 1 : InvalidId; } + Id_t offset() const { return static_cast(repr_ >> 2); } + uint32_t repr() const { return repr_; } + operator uint32_t() const { return repr(); } +private: + uint32_t repr_; +}; + +std::pair BodyAggregateElements_::insertTuple(uint64_t to) { + return tuples_.insert( + [](uint64_t a) { return std::hash()(a >> 1); }, + [](uint64_t a, uint64_t b){ return (a >> 1) == (b >> 1); }, + to); +} + +template +void BodyAggregateElements_::visitClause(F f) { + for (auto it = conditions_.begin(), ie = conditions_.end(); it != ie; ) { + auto &to = *it++; + Id_t size = 0; + Id_t offset = 0; + if (to & 1) { + ClauseOffset co(*it++); + offset = co.offset(); + size = co.size(); + if (size == InvalidId) { size = *it++; } + } + f(to, ClauseId(offset, size)); + } +} + +void BodyAggregateElements_::accumulate(DomainData &data, TupleId tuple, LitVec &lits, bool &inserted, bool &fact, bool &remove) { + if (tuples_.reserveNeedsRebuild(tuples_.size() + 1)) { + // remap tuple offsets if rebuild is necessary + HashSet tuples(tuples_.size() + 1, tuples_.reserved()); + tuples.swap(tuples_); + assert(tuples.reserved() < tuples_.reserved()); + visitClause([&](uint32_t &to, ClauseId) { + to = (tuples_.offset(insertTuple(tuples.at(to >> 1)).first) << 1) | (to & 1); + }); + } + TupleOffset newTO(tuple.offset, tuple.size, lits.empty()); + auto ret = insertTuple(newTO); + inserted = ret.second; + remove = false; + if (!inserted) { + TupleOffset oldTO = ret.first; + if (!oldTO.fact() && newTO.fact()) { + ret.first = newTO; + remove = true; + } + else { newTO = oldTO; } + } + fact = newTO.fact(); + if (!fact || inserted || remove) { + auto clause = data.clause(std::move(lits)); + auto size = clause.second; + conditions_.emplace_back((tuples_.offset(ret.first) << 1) | (size > 0)); + if (size > 0) { + ClauseOffset co(clause.first, size); + conditions_.emplace_back(co); + if (co.size() == InvalidId) { conditions_.emplace_back(size); } + } + } +} +BodyAggregateElements BodyAggregateElements_::elems() const { + BodyAggregateElements elems; + const_cast(this)->visitClause([&](uint32_t const &to, ClauseId cond) { + TupleOffset fo(tuples_.at(to >> 1)); + TupleId tuple{fo.offset(), fo.size()}; + auto ret = elems.push(std::piecewise_construct, std::forward_as_tuple(tuple), std::forward_as_tuple()); + if (fo.fact()) { ret.first->second.clear(); } + ret.first->second.emplace_back(cond); + }); + return elems; +} + +void BodyAggregateAtom::init(AggregateFunction fun, DisjunctiveBounds &&bounds, bool monotone) { + data_->range.init(fun, std::move(bounds)); + data_->fact = data_->range.fact(); + data_->monotone = monotone; + data_->initialized = true; +} + +BodyAggregateElements BodyAggregateAtom::elems() const { + return data_->elems.elems(); +} + +void BodyAggregateAtom::accumulate(DomainData &data, Location const &loc, SymVec const &tuple, LitVec &lits, Logger &log) { + if (neutral(tuple, data_->range.fun, loc, log)) { return; } + bool inserted, fact, remove; + data_->elems.accumulate(data, data.tuple(tuple), lits, inserted, fact, remove); + if (!fact || inserted || remove) { + data_->range.accumulate(tuple, fact, remove); + data_->fact = data_->range.fact(); + } +} + +BodyAggregateAtom::~BodyAggregateAtom() noexcept = default; + +// {{{1 definition of AssignmentAggregateAtom + +void AssignmentAggregateData::accumulate(DomainData &data, Location const &loc, SymVec const &tuple, LitVec &lits, Logger &log) { + if (neutral(tuple, fun_, loc, log)) { return; } + auto ret(elems_.push(std::piecewise_construct, std::forward_as_tuple(data.tuple(tuple)), std::forward_as_tuple())); + auto &elem = ret.first->second; + // the tuple was fact + if (elem.size() == 1 && elem.front().second == 0) { return; } + bool fact = false; + bool remove = false; + if (lits.empty()) { + elem.clear(); + fact = true; + remove = !ret.second; + } + elem.emplace_back(data.clause(lits)); + if (!ret.second && !remove) { return; } + switch (fun_) { + case AggregateFunction::MIN: { + Symbol val = tuple.front(); + if (fact) { + values_.erase(std::remove_if(values_.begin() + 1, values_.end(), [val](Symbol x) { return x >= val; }), values_.end()); + if (values_.front() > val) { values_.front() = val; } + } + else if (values_.front() > val) { values_.push_back(val); } + break; + } + case AggregateFunction::MAX: { + Symbol val = tuple.front(); + if (fact) { + values_.erase(std::remove_if(values_.begin() + 1, values_.end(), [val](Symbol x) { return x <= val; }), values_.end()); + if (values_.front() < val) { values_.front() = val; } + } + else if (values_.front() < val) { values_.push_back(val); } + break; + } + default: { + Symbol val = fun_ == AggregateFunction::COUNT ? Symbol::createNum(1) : tuple.front(); + if (fact) { + if (remove) { values_.erase(std::find(values_.begin() + 1, values_.end(), val)); } + values_.front() = Symbol::createNum(values_.front().num() + val.num()); + } + else { values_.push_back(val); } + break; + } + } +} + +AssignmentAggregateData::Values AssignmentAggregateData::values() const { + switch (fun_) { + case AggregateFunction::MIN: + case AggregateFunction::MAX: { + Values values = values_; + sort_unique(values); + return values; + } + default: { + UniqueVec values; + auto it = values_.begin(); + values.push(*it++); + for (auto ie = values_.end(); it != ie; ++it) { + for (Id_t jt = 0, je = values.size(); jt != je; ++jt) { values.push(Symbol::createNum(values[jt].num() + it->num())); } + } + return {values.begin(), values.end()}; + } + } +} + +Interval AssignmentAggregateData::range() const { + switch (fun_) { + case AggregateFunction::MAX: + case AggregateFunction::MIN: { + Symbol valMin = values_.front(); + Symbol valMax = valMin; + for (auto it = values_.begin() + 1, ie = values_.end(); it != ie; ++it) { + valMin = std::min(valMin, *it); + valMax = std::max(valMax, *it); + } + return Interval{{valMin,true},{valMax,true}}; + } + default: { + int64_t intMin = values_.front().num(); + int64_t intMax = intMin; + for (auto it = values_.begin() + 1, ie = values_.end(); it != ie; ++it) { + int val = it->num(); + if (val < 0) { intMin+= val; } + else { intMax+= val; } + } + // NOTE: nonsense, proper handling is not achieved like this... + return {{Symbol::createNum(clamp(intMin)), true}, {Symbol::createNum(clamp(intMax)), true}}; + } + } +} + +// {{{1 definition of ConjunctionAtom + +// Example: +// H :- p(G), q(G,X,Y) : r(G,X,Z). +// global variables: G +// local variables : X, Y, Z +// value of the conjunction: c(G) +// value of the element : e(X) +// disjunction of bodies is spanned by Z +// disjunction of heads is spanned by Y + +bool ConjunctionElement::isSimple(DomainData &data) const { + return (heads_.empty() && bodies_.size() == 1 && bodies_.front().second == 1 && data.clause(bodies_.front()).front().invertible()) || + (bodies_.size() == 1 && bodies_.front().second == 0 && heads_.size() <= 1); +} + +bool ConjunctionElement::needsSemicolon() const { + return !bodies_.empty() && bodies_.front().second > 0; +} + +void ConjunctionElement::print(PrintPlain out) const { + using namespace std::placeholders; + if (bodies_.empty()) { + out << "#true"; + } + else { + if (heads_.empty()) { + out << "#false"; + } + else { + auto pc = [](PrintPlain out, ClauseId id) { + if (id.second == 0) { + out << "#true"; + } + else { + print_comma(out, out.domain.clause(id), "&", printLit); + } + }; + print_comma(out, heads_, "|", pc); + } + if (bodies_.front().second > 0) { + out << ":"; + auto pc = [](PrintPlain out, ClauseId id) { + if (id.second == 0) { + out << "#true"; + } + else { + print_comma(out, out.domain.clause(id), ",", printLit); + } + }; + print_comma(out, bodies_, "|", pc); + } + } +} +void ConjunctionElement::accumulateCond(DomainData &data, LitVec &lits, Id_t &blocked, Id_t &fact) { + if (bodies_.empty()) { + // there can only be a head if there is at least one body + assert(heads_.empty()); + ++fact; + } + if (bodies_.size() != 1 || bodies_.front().second > 0) { + if (lits.empty()) { + bodies_.clear(); + if (heads_.empty()) { ++blocked; } + } + bodies_.emplace_back(data.clause(lits)); + } +} + +void ConjunctionElement::accumulateHead(DomainData &data, LitVec &lits, Id_t &blocked, Id_t &fact) { + // NOTE: returns true for newly satisfiable elements + if (heads_.empty() && bodies_.size() == 1 && bodies_.front().second == 0) { + assert(blocked > 0); + --blocked; + } + if (heads_.size() != 1 || heads_.front().second > 0) { + if (lits.empty()) { + heads_.clear(); + assert(fact > 0); + --fact; + } + heads_.emplace_back(data.clause(lits)); + } +} + +void ConjunctionAtom::accumulateCond(DomainData &data, Symbol elem, LitVec &lits) { + elems_.findPush(elem, elem).first->accumulateCond(data, lits, blocked_, fact_); +} + +void ConjunctionAtom::accumulateHead(DomainData &data, Symbol elem, LitVec &lits) { + elems_.findPush(elem, elem).first->accumulateHead(data, lits, blocked_, fact_); +} + +bool ConjunctionAtom::recursive() const { + return (headRecursive_ || condRecursive_) && !fact(); +} + +bool ConjunctionAtom::nonmonotone() const { + return !fact() && condRecursive_; +} + +void ConjunctionAtom::init(bool headRecursive, bool condRecursive) { + headRecursive_ = headRecursive; + condRecursive_ = condRecursive; +} + +// {{{1 definition of DisjointAtom + +DisjointElement::DisjointElement(CSPGroundAdd &&value, int fixed, ClauseId cond) +: value_(std::move(value)) +, cond_(cond) +, fixed_(fixed) { } + +void DisjointElement::printPlain(PrintPlain out) const { + if (value_.empty()) { out << fixed_; } + else { + auto print_add = [](PrintPlain out, CSPGroundAdd::value_type const &z) { + if (z.first == 1) { out << "$" << z.second; } + else { out << z.first << "$*$" << z.second; } + }; + print_comma(out, value_, "$+", print_add); + if (fixed_ > 0) { out << "$+" << fixed_; } + else if (fixed_ < 0) { out << "$-" << -fixed_; } + } + if (cond_.second > 0) { + out << ":"; + print_comma(out, out.domain.clause(cond_), ",", [](PrintPlain out, LiteralId lit) { printLit(out, lit); }); + } +} + +void DisjointAtom::accumulate(DomainData &data, SymVec const &tuple, CSPGroundAdd &&value, int fixed, LitVec const &lits) { + auto elem = elems_.push(std::piecewise_construct, std::forward_as_tuple(data.tuple(tuple)), std::forward_as_tuple()); + elem.first->second.emplace_back(std::move(value), fixed, data.clause(get_clone(lits))); +} + +bool DisjointAtom::translate(DomainData &data, Translator &x, Logger &log) { + std::set values; + std::vector> layers; + for (auto &elem : elems_) { + layers.emplace_back(); + auto ¤t = layers.back(); + auto encodeSingle = [&data, ¤t, &x, &values](ClauseId cond, int coef, Symbol var, int fixed) -> void { + auto &bound = x.findBound(var); + auto it = bound.atoms.begin() + 1; + for(auto i : bound) { + auto &aux = current[i*coef + fixed]; + if (!aux) { aux = data.newAux(); } + Rule rule; + if (cond.second > 0) { rule.addBody(getEqualClause(data, x, cond, true, false)); } + if ((it-1)->second) { rule.addBody(LiteralId{NAF::NOT, AtomType::Aux, (it-1)->second, 0}); } + if (it != bound.atoms.end()) { rule.addBody(LiteralId{NAF::POS, AtomType::Aux, it->second, 0}); } + rule.addHead(aux).translate(data, x); + values.insert(i*coef + fixed); + ++it; + } + }; + for (auto &condVal : elem.second) { + switch(condVal.value().size()) { + case 0: { + auto &aux = current[condVal.fixed()]; + if (!aux) { aux = data.newAux(); } + Rule().addHead(aux).addBody(getEqualClause(data, x, condVal.cond(), true, false)).translate(data, x); + values.insert(condVal.fixed()); + break; + } + case 1: { + encodeSingle(condVal.cond(), condVal.value().front().first, condVal.value().front().second, condVal.fixed()); + break; + } + default: { + // create a bound possibly with holes + auto b = x.addBound(Symbol::createId(("#aux" + std::to_string(data.newAtom())).c_str())); + b->clear(); + std::set values; + values.emplace(0); + for (auto &mul : condVal.value()) { + std::set nextValues; + for (auto i : x.findBound(mul.second)) { + for (auto j : values) { nextValues.emplace(j + i * mul.first); } + } + values = std::move(nextValues); + } + for (auto i : values) { b->add(i, i+1); } + b->init(data, x, log); + + // create a new variable with the respective bound + // b = value + fixed + // b - value = fixed + // aux :- b - value <= fixed - 1 + // aux :- value - b <= -fixed - 1 + // :- aux. + LiteralId aux = data.newAux(); + auto value = condVal.value(); + value.emplace_back(-1, b->var); + x.addLinearConstraint(aux, get_clone(value), -condVal.fixed()-1); + for (auto &add : value) { add.first *= -1; } + x.addLinearConstraint(aux, std::move(value), condVal.fixed()-1); + Rule().addBody(aux).translate(data, x); + // then proceed as in case one + encodeSingle(condVal.cond(), 1, b->var, 0); + break; + } + } + } + } + LitVec checks; + for (auto &value : values) { + LitUintVec card; + for (auto &layer : layers) { + auto it = layer.find(value); + if (it != layer.end()) { card.emplace_back(it->second, 1); } + } + LiteralId aux = data.newAux(); + checks.emplace_back(aux.negate()); + WeightRule wr(std::move(aux), 2, std::move(card)); + x.output(data, wr); + } + Rule().addHead(lit()).addBody(std::move(checks)).translate(data, x); + return true; +} + + +// {{{1 definition of DisjunctionAtom + +// Example: +// p(1..10,X) : q(X,Y,G) :- r(G). +// global variables: G +// local variables : X, Y +// value of the disjunction: c(G) +// value of the element : e(X) +// disjunction of bodies is spanned by Y +// conjunction of heads is spanned by 1..10 + +void DisjunctionElement::print(PrintPlain out) const { + using namespace std::placeholders; + if (bodies_.empty()) { + out << "#false"; + } + else { + if (heads_.empty()) { + out << "#true"; + } + else { + auto pc = [](PrintPlain out, ClauseId id) { + if (id.second == 0) { + out << "#false"; + } + else { + print_comma(out, out.domain.clause(id), "|", printLit); + } + }; + print_comma(out, heads_, "&", pc); + } + if (bodies_.front().second > 0) { + out << ":"; + auto pc = [](PrintPlain out, ClauseId id) { + if (id.second == 0) { + out << "#true"; + } + else { + print_comma(out, out.domain.clause(id), "&", printLit); + } + }; + print_comma(out, bodies_, "|", pc); + } + } +} + +// Note: this are general functions on formulas +bool DisjunctionElement::bodyIsTrue() const { + return bodies_.size() == 1 && bodies_.front().second == 0; +} + +bool DisjunctionElement::headIsTrue() const { + return heads_.empty(); +} + +bool DisjunctionElement::bodyIsFalse() const { + return bodies_.empty(); +} + +bool DisjunctionElement::headIsFalse() const { + return heads_.size() == 1 && heads_.front().second == 0; +} + +void DisjunctionElement::accumulateCond(DomainData &data, LitVec &lits, Id_t &fact) { + if (!bodyIsTrue()) { + if (lits.empty()) { + bodies_.clear(); + if (headIsTrue()) { ++fact; } + } + bodies_.emplace_back(data.clause(lits)); + } +} + +void DisjunctionElement::accumulateHead(DomainData &data, LitVec &lits, Id_t &fact) { + if (!headIsFalse()) { + if (bodyIsTrue() && headIsTrue()) { --fact; } + if (lits.empty()) { heads_.clear(); } + heads_.emplace_back(data.clause(lits)); + } +} + +void DisjunctionAtom::simplify(bool &headFact) { + headFact_ = 0; + elems_.erase([this](DisjunctionElement &elem) { + if (elem.headIsTrue() && elem.bodyIsTrue()) { ++headFact_; } + return elem.bodyIsFalse() || elem.headIsFalse(); + }); + headFact = headFact_ > 0; +} + +void DisjunctionAtom::accumulateCond(DomainData &data, Symbol elem, LitVec &lits) { + elems_.findPush(elem, elem).first->accumulateCond(data, lits, headFact_); +} + +void DisjunctionAtom::accumulateHead(DomainData &data, Symbol elem, LitVec &lits) { + elems_.findPush(elem, elem).first->accumulateHead(data, lits, headFact_); +} + +// {{{1 declaration of TheoryAtom + +void TheoryAtom::simplify(TheoryData const &) { + if (!simplified_) { + // NOTE: tuples with non-factual conditions can be removed if there + // is an element with the same tuple and a factual condition + std::sort(elems_.begin(), elems_.end()); + elems_.erase(std::unique(elems_.begin(), elems_.end()), elems_.end()); + elems_.shrink_to_fit(); + simplified_ = true; + } +} + +// {{{1 definition of HeadAggregateAtom + +void HeadAggregateAtom::init(AggregateFunction fun, DisjunctiveBounds &&bounds) { + range_.init(fun, std::move(bounds)); + fact_ = range_.fact(); + initialized_ = true; +} + +void HeadAggregateAtom::accumulate(DomainData &data, Location const &loc, SymVec const &tuple, LiteralId head, LitVec &lits, Logger &log) { + // Elements are grouped by their tuples. + // Each tuple is associated with a vector of pairs of head literals and a condition. + // If the head is a fact, this is represented with an invalid literal. + // If a tuple is a fact, this is represented with the first element of the vector being having an invalid head and an empty condition. + if (!Gringo::Output::defined(tuple, range_.fun, loc, log)) { return; } + auto ret(elems_.push(std::piecewise_construct, std::forward_as_tuple(data.tuple(tuple)), std::forward_as_tuple())); + auto &elem = ret.first->second; + bool fact = lits.empty() && !head.valid(); + bool wasFact = !elem.empty() && !elem.front().first.valid() && elem.front().second.second == 0; + if (wasFact && fact) { return; } + elem.emplace_back(head, data.clause(lits)); + bool remove = false; + if (fact) { + std::swap(elem.front(), elem.back()); + remove = !ret.second; + } + if ((!ret.second && !remove) || neutral(tuple, range_.fun, loc, log)) { return; } + range_.accumulate(tuple, fact, remove); + fact_ = range_.fact(); +} + +// }}}1 + +// {{{1 definition of AuxLiteral + +AuxLiteral::AuxLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +bool AuxLiteral::isHeadAtom() const { return id_.sign() == NAF::POS; } + +LiteralId AuxLiteral::translate(Translator &trans) { + return id_.sign() != NAF::NOTNOT ? id_ : trans.removeNotNot(data_, id_); +} + +void AuxLiteral::printPlain(PrintPlain out) const { out << id_.sign() << (id_.domain() == 0 ? "#aux" : "#delayed") << "(" << id_.offset() << ")"; } + +bool AuxLiteral::isIncomplete() const { return false; } + +int AuxLiteral::uid() const { + switch (id_.sign()) { + case NAF::POS: { return +static_cast(id_.offset()); } + case NAF::NOT: { return -static_cast(id_.offset()); } + case NAF::NOTNOT: { throw std::logic_error("AuxLiteral::uid: translate must be called before!"); } + } + throw std::logic_error("AuxLiteral::uid: must not happen"); +} + +LiteralId AuxLiteral::simplify(Mappings &, AssignmentLookup assignment) const { + auto value = assignment(id_.offset()); + if (value.second == Potassco::Value_t::Free) { return id_; } + auto ret = data_.getTrueLit(); + if (value.second == Potassco::Value_t::False) { ret = ret.negate(); } + if (id_.sign() == NAF::NOT){ ret = ret.negate(); } + return id_; +} + +bool AuxLiteral::isTrue(IsTrueLookup lookup) const { + assert(id_.offset() > 0); + return (id_.sign() == NAF::NOT) ^ lookup(id_.offset()); +} + +LiteralId AuxLiteral::toId() const { + return id_; +} + +AuxLiteral::~AuxLiteral() noexcept = default; + +// {{{1 definition of PredicateLiteral + +PredicateLiteral::PredicateLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +bool PredicateLiteral::isHeadAtom() const { + return id_.sign() == NAF::POS; +} + +bool PredicateLiteral::isAtomFromPreviousStep() const { + auto &domain = *data_.predDoms()[id_.domain()]; + return id_.offset() < domain.incOffset(); +} + +void PredicateLiteral::printPlain(PrintPlain out) const { + auto &atom = data_.predDoms()[id_.domain()]->operator[](id_.offset()); + out << id_.sign() << static_cast(atom); +} + +bool PredicateLiteral::isIncomplete() const { return false; } + +LiteralId PredicateLiteral::toId() const { + return id_; +} + +LiteralId PredicateLiteral::translate(Translator &trans) { + return id_.sign() != NAF::NOTNOT ? id_ : trans.removeNotNot(data_, id_); +} + +int PredicateLiteral::uid() const { + auto &atom = data_.predDoms()[id_.domain()]->operator[](id_.offset()); + if (!atom.hasUid()) { atom.setUid(data_.newAtom()); } + switch (id_.sign()) { + case NAF::POS: { return +static_cast(atom.uid()); } + case NAF::NOT: { return -static_cast(atom.uid()); } + case NAF::NOTNOT: { throw std::logic_error("PredicateLiteral::uid: translate must be called before!"); } + } + assert(false); + return 0; +} + +LiteralId PredicateLiteral::simplify(Mappings &mappings, AssignmentLookup assignment) const { + auto offset = mappings[id_.domain()].get(id_.offset()); + if (offset == InvalidId) { + auto ret = data_.getTrueLit(); + if (id_.sign() != NAF::NOT){ ret = ret.negate(); } + return ret; + } + else { + auto &atom = data_.predDoms()[id_.domain()]->operator[](offset); + if (!atom.defined()) { return data_.getTrueLit().negate(); } + if (atom.hasUid()) { + auto value = assignment(atom.uid()); + if (value.second != Potassco::Value_t::Free) { + auto ret = data_.getTrueLit(); + if (value.second == Potassco::Value_t::False) { ret = ret.negate(); } + if (id_.sign() == NAF::NOT){ ret = ret.negate(); } + return ret; + } + } + return id_.withOffset(offset); + } +} + +bool PredicateLiteral::isTrue(IsTrueLookup lookup) const { + auto &atom = data_.predDoms()[id_.domain()]->operator[](id_.offset()); + assert(atom.hasUid()); + return (id_.sign() == NAF::NOT) ^ lookup(atom.uid()); +} + +PredicateLiteral::~PredicateLiteral() noexcept = default; + +// {{{1 definition of TheoryLiteral + +TheoryLiteral::TheoryLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +void TheoryLiteral::printPlain(PrintPlain out) const { + auto &atm = data_.getAtom(id_); + if (atm.defined()) { + atm.simplify(data_.theory()); + out << id_.sign(); + out << "&"; + out.printTerm(atm.name()); + out << "{"; + print_comma(out, atm.elems(), "; ", [](PrintPlain out, Potassco::Id_t elemId) { out.printElem(elemId); }); + out << "}"; + if (atm.hasGuard()) { + out.printTerm(atm.op()); + out << "("; + out.printTerm(atm.guard()); + out << ")"; + } + } + else { out << (id_.sign() == NAF::NOT ? "#true" : "#false"); } +} + +bool TheoryLiteral::isHeadAtom() const { + auto &atm = data_.getAtom(id_); + return atm.defined() && atm.type() != TheoryAtomType::Body; +} + +bool TheoryLiteral::isIncomplete() const { + return data_.getAtom(id_).recursive(); +} + +std::pair TheoryLiteral::delayedLit() { + auto &atm = data_.getAtom(id_); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {atm.lit().withSign(id_.sign()), !found}; +} + +LiteralId TheoryLiteral::toId() const { + return id_; +} + +LiteralId TheoryLiteral::translate(Translator &trans) { + auto &atm = data_.getAtom(id_); + if (!atm.translated()) { + atm.setTranslated(); + if (atm.defined()) { + atm.simplify(data_.theory()); + for (auto &elemId : atm.elems()) { + auto &cond = data_.theory().getCondition(elemId); + Gringo::Output::translate(data_, trans, cond); + } + auto newAtom = [&]() -> Atom_t { + if (atm.type() == TheoryAtomType::Directive) { return 0; } + if (!atm.lit()) { atm.setLit(data_.newAux()); } + assert(atm.lit().type() == AtomType::Aux); + return atm.lit().offset(); + }; + TheoryData &data = data_.theory(); + auto ret = atm.hasGuard() + ? data.addAtom(newAtom, atm.name(), Potassco::toSpan(atm.elems()), atm.op(), atm.guard()) + : data.addAtom(newAtom, atm.name(), Potassco::toSpan(atm.elems())); + if (ret.first.atom() != 0) { + // assign the literal of the theory atom + if (!atm.lit()) { atm.setLit({NAF::POS, AtomType::Aux, ret.first.atom(), 0}); } + // connect the theory atom with an existing one + else if (ret.first.atom() != atm.lit().offset()) { + LiteralId head = atm.lit(); + LiteralId body{NAF::POS, AtomType::Aux, ret.first.atom(), 0}; + if (atm.type() == TheoryAtomType::Head) { std::swap(head, body); } + Rule().addHead(head).addBody(body).translate(data_, trans); + } + } + } + else { makeFalse(data_, trans, id_.sign(), atm); } + } + auto lit = atm.lit(); + return !lit ? lit : trans.removeNotNot(data_, lit.withSign(id_.sign())); +} + +int TheoryLiteral::uid() const { throw std::logic_error("TheoryLiteral::uid: translate must be called before!"); } + +TheoryLiteral::~TheoryLiteral() noexcept = default; + +// {{{1 definition of CSPLiteral + +CSPLiteral::CSPLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +CSPGroundLit const &CSPLiteral::atom() const { + return data_.cspAtom(id_.offset()); + +} +void CSPLiteral::printPlain(PrintPlain out) const { + auto &atm = atom(); + out << id_.sign(); + if (!std::get<1>(atm).empty()) { + auto f = [](PrintPlain out, std::pair mul) { out << mul.first << "$*$" << mul.second; }; + print_comma(out, std::get<1>(atm), "$+", f); + } + else { out << 0; } + out << "$" << std::get<0>(atm); + out << std::get<2>(atm); +} + +bool CSPLiteral::isIncomplete() const { + return false; +} + +bool CSPLiteral::isBound(Symbol &value, bool negate) const { + auto &atm = atom(); + Relation rel = std::get<0>(atm); + if (id_.sign() == NAF::NOT) { negate = !negate; } + if (negate) { rel = neg(rel); } + if (std::get<1>(atm).size() != 1) { return false; } + if (rel == Relation::NEQ) { return false; } + if (value.type() == SymbolType::Special) { value = std::get<1>(atm).front().second; } + return value == std::get<1>(atm).front().second; +} + +void CSPLiteral::updateBound(std::vector &bounds, bool negate) const { + auto &atm = atom(); + bounds.emplace_back(std::numeric_limits::min(), std::numeric_limits::max()-1); + auto &bound = bounds.back(); + Relation rel = std::get<0>(atm); + if (id_.sign() == NAF::NOT) { negate = !negate; } + if (negate) { rel = neg(rel); } + int coef = std::get<1>(atm).front().first; + int fixed = std::get<2>(atm); + if (coef < 0) { + coef = -coef; + fixed = -fixed; + rel = inv(rel); + } + switch (rel) { + case Relation::LT: { fixed--; } + case Relation::LEQ: { + fixed /= coef; + bound.second = std::min(bound.second, fixed); + break; + } + case Relation::GT: { fixed++; } + case Relation::GEQ: { + fixed = (fixed+coef-1) / coef; + bound.first = std::max(bound.first, fixed); + break; + } + case Relation::EQ: { + if (fixed % coef == 0) { + fixed /= coef; + bound.first = std::max(bound.first, fixed); + bound.second = std::min(bound.second, fixed); + } + else { + bound.first = 0; + bound.second = -1; + } + break; + } + case Relation::NEQ: { assert(false); } + } +} + +LiteralId CSPLiteral::translate(Translator &x) { + // NOTE: consider replacing this with a theory atom + auto &atm = atom(); + auto term = std::get<1>(atm); + Relation rel = std::get<0>(atm); + if (id_.sign() == NAF::NOT) { rel = neg(rel); } + int bound = std::get<2>(atm); + auto addInv = [&x](Atom_t aux, CoefVarVec &&vars, int bound) { + for (auto &x : vars) { x.first *= -1; } + x.addLinearConstraint(aux, std::move(vars), -bound); + }; + Atom_t aux = data_.newAtom(); + switch (rel) { + case Relation::EQ: + case Relation::NEQ: { + x.addLinearConstraint(aux, CoefVarVec(term), bound-1); + addInv(aux, std::move(term), bound + 1); + return LiteralId{rel != Relation::NEQ ? NAF::NOT : NAF::POS, AtomType::Aux, aux, 0}; + } + case Relation::LT: { bound--; } + case Relation::LEQ: { + x.addLinearConstraint(aux, std::move(term), bound); + return LiteralId{NAF::POS, AtomType::Aux, aux, 0}; + } + case Relation::GT: { bound++; } + case Relation::GEQ: { + addInv(aux, std::move(term), bound); + return LiteralId{NAF::POS, AtomType::Aux, aux, 0}; + } + } + assert(false); + throw std::logic_error("cannot happen"); +} + +int CSPLiteral::uid() const { + throw std::logic_error("CSPLiteral::uid must not be called"); +} + +CSPLiteral::~CSPLiteral() noexcept = default; + +// {{{1 definition of BodyAggregateLiteral + +BodyAggregateLiteral::BodyAggregateLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +void BodyAggregateLiteral::printPlain(PrintPlain out) const { + auto &dom = data_.getDom(id_.domain()); + auto &atm = dom[id_.offset()]; + if (atm.defined()) { + auto bounds = atm.plainBounds(); + out << id_.sign(); + auto it = bounds.begin(), ie = bounds.end(); + if (it != ie) { out << it->second << inv(it->first); ++it; } + out << atm.fun() << "{"; + print_comma(out, atm.elems(), ";", printBodyElem); + out << "}"; + for (; it != ie; ++it) { out << it->first << it->second; } + } + else { + out << (id_.sign() == NAF::NOT ? "#true" : "#false"); + } +} + +LiteralId BodyAggregateLiteral::toId() const { + return id_; +} + +LiteralId BodyAggregateLiteral::translate(Translator &x) { + auto &dom = data_.getDom(id_.domain()); + auto &atm = dom[id_.offset()]; + if (!atm.translated()) { + atm.setTranslated(); + if (atm.defined()) { + auto aggrLit = getEqualAggregate(data_, x, atm.fun(), id_.sign(), atm.bounds(), atm.range(), atm.elems(), atm.recursive()); + auto lit = atm.lit(); + if (lit) { Rule().addHead(lit).addBody(aggrLit).translate(data_, x); } + else { atm.setLit(aggrLit); } + } + else { makeFalse(data_, x, id_.sign(), atm); } + } + return atm.lit(); +} +int BodyAggregateLiteral::uid() const { + throw std::logic_error("BodyAggregateLiteral::uid must be called after BodyAggregateLiteral::translate"); +} + +bool BodyAggregateLiteral::isIncomplete() const { + return data_.getAtom(id_.domain(), id_.offset()).recursive(); +} + +std::pair BodyAggregateLiteral::delayedLit() { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {atm.lit(), !found}; +} + +BodyAggregateLiteral::~BodyAggregateLiteral() noexcept = default; + +// {{{1 definition of AssignmentAggregateLiteral + +AssignmentAggregateLiteral::AssignmentAggregateLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { + assert(id_.sign() == NAF::POS); +} + +AssignmentAggregateDomain &AssignmentAggregateLiteral::dom() const { + return data_.getDom(id_.domain()); +} + +void AssignmentAggregateLiteral::printPlain(PrintPlain out) const { + auto &dom = this->dom(); + auto &atm = dom[id_.offset()]; + auto &data = dom.data(atm.data()); + Symbol repr = atm; + out << id_.sign(); + out << data.fun() << "{"; + print_comma(out, data.elems(), ";", printBodyElem); + auto args = repr.args(); + out << "}=" << args.first[args.size - 1]; +} + +LiteralId AssignmentAggregateLiteral::toId() const { + return id_; +} + +LiteralId AssignmentAggregateLiteral::translate(Translator &x) { + auto &dom = this->dom(); + auto &atm = dom[id_.offset()]; + auto &data = dom.data(atm.data()); + if (!atm.translated()) { + atm.setTranslated(); + assert(atm.defined()); + // NOTE: for assignment aggregates with many values a better translation could be implemented + Symbol repr = atm; + DisjunctiveBounds bounds; + auto args = repr.args(); + auto back = args.first[args.size - 1]; + bounds.add(back, true, back, true); + auto aggrLit = getEqualAggregate(data_, x, data.fun(), id_.sign(), bounds, data.range(), data.elems(), atm.recursive()); + auto lit = atm.lit(); + if (lit) { Rule().addHead(lit).addBody(aggrLit).translate(data_, x); } + else { atm.setLit(aggrLit); } + } + return atm.lit(); +} +int AssignmentAggregateLiteral::uid() const { + throw std::logic_error("AssignmentAggregateLiteral::uid must be called after AssignmentAggregateLiteral::translate"); +} + +bool AssignmentAggregateLiteral::isIncomplete() const { + return dom()[id_.offset()].recursive(); +} + +std::pair AssignmentAggregateLiteral::delayedLit() { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {atm.lit(), !found}; +} + +AssignmentAggregateLiteral::~AssignmentAggregateLiteral() noexcept = default; + +// {{{1 definition of DisjunctionLiteral + +DisjunctionLiteral::DisjunctionLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +LiteralId DisjunctionLiteral::toId() const { + return id_; +} + +void DisjunctionLiteral::printPlain(PrintPlain out) const { + auto &atm = dom()[id_.offset()]; + if (!atm.elems().empty()) { print_comma(out, atm.elems(), ";"); } + else { out << "#false"; } +} + +bool DisjunctionLiteral::isBound(Symbol &value, bool negate) const { + assert(!negate); + auto &atm = dom()[id_.offset()]; + for (auto &y : atm.elems()) { + if (y.bodies().size() != 1 && y.bodies().front().second > 0) { return false; } + for (auto &z : y.heads()) { + if (z.second != 1) { return false; } + for (auto &u : data_.clause(z)) { + if (!call(data_, u, &Literal::isBound, value, negate)) { return false; } + } + } + } + return true; +} + +void DisjunctionLiteral::updateBound(std::vector &bounds, bool negate) const { + assert(!negate); + auto &atm = dom()[id_.offset()]; + for (auto &y : atm.elems()) { + for (auto &z : y.heads()) { + for (auto &u : data_.clause(z)) { + call(data_, u, &Literal::updateBound, bounds, negate); + } + } + } +} + +LiteralId DisjunctionLiteral::translate(Translator &x) { + auto &atm = dom()[id_.offset()]; + if (!atm.translated()) { + atm.setTranslated(); + if (!atm.lit()) { atm.setLit(data_.newAux()); } + Symbol value; + if (atm.fact() && isBound(value, false) && value.type() != SymbolType::Special) { + std::vector bounds; + updateBound(bounds, false); + x.addBounds(value, bounds); + return atm.lit(); + } + bool headFact; + atm.simplify(headFact); + if (headFact) { return atm.lit(); } + Rule dj; + dj.addBody(atm.lit()); + for (auto &elem : atm.elems()) { + assert (!elem.bodies().empty()); + LiteralId cond; // cond :- elem.bodies() + if (!elem.bodyIsTrue()) { cond = getEqualFormula(data_, x, elem.bodies(), false, false); } + if (elem.heads().empty()) { + assert(cond); + // head is a fact + dj.addBody(cond.negate()); + } + else if (elem.heads().size() == 1) { + auto headClause = data_.clause(elem.heads().front()); + if (cond) { + LiteralId headAtom = data_.newAux(); + for (auto &lit : headClause) { + Rule().addHead(headAtom).addBody(lit).addBody(cond).translate(data_, x); + } + Rule().addHead(headClause).addBody(cond).addBody(headAtom).translate(data_, x); + Rule().addBody(cond.negate()).addBody(headAtom).translate(data_, x); + dj.addHead(headAtom); + } + else { + // the head literals can be pushed directly into djHead + dj.addHead(headClause.front()); + } + } + else { + LiteralId conjunctionAtom = data_.newAux(); + Rule conjunction; + for (auto &headId : elem.heads()) { + auto head = data_.clause(headId); + if (head.size() == 1) { + Rule().addHead(head.front()).addBody(conjunctionAtom).translate(data_, x); + conjunction.addBody(head.front()); + } + else { + LiteralId disjunctionAtom = data_.newAux(); + Rule().addHead(head).addBody(disjunctionAtom).translate(data_, x); + for (auto &lit : head) { + Rule().addHead(disjunctionAtom).addBody(lit).translate(data_, x); + } + conjunction.addBody(disjunctionAtom); + } + } + conjunction.addHead(conjunctionAtom).translate(data_, x); + if (cond) { + LiteralId headAtom = data_.newAux(); + Rule().addHead(headAtom).addBody(conjunctionAtom).addBody(cond).translate(data_, x); + Rule().addHead(conjunctionAtom).addBody(headAtom).addBody(cond).translate(data_, x); + Rule().addBody(cond.negate()).addBody(headAtom).translate(data_, x); + dj.addHead(headAtom); + } + else { + dj.addHead(conjunctionAtom); + } + } + } + dj.translate(data_, x); + } + return atm.lit(); +} + +Lit_t DisjunctionLiteral::uid() const { + throw std::logic_error("DisjunctionLiteral::uid: must be called before DisjunctionLiteral::translate"); +} + +bool DisjunctionLiteral::isIncomplete() const { + return dom()[id_.offset()].recursive(); +} + +DisjunctionDomain &DisjunctionLiteral::dom() const { + return data_.getDom(id_.domain()); +} + +std::pair DisjunctionLiteral::delayedLit() { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {atm.lit(), !found}; +} + +DisjunctionLiteral::~DisjunctionLiteral() noexcept = default; + +// {{{1 definition of ConjunctionLiteral + +ConjunctionLiteral::ConjunctionLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +LiteralId ConjunctionLiteral::toId() const { + return id_; +} + +void ConjunctionLiteral::printPlain(PrintPlain out) const { + auto &atm = dom()[id_.offset()]; + if (!atm.elems().empty()) { + int sep = 0; + for (auto &x : atm.elems()) { + switch (sep) { + case 1: { out << ","; break; } + case 2: { out << ";"; break; } + } + out << x; + sep = static_cast(x.needsSemicolon()) + 1; + } + } + else { out << "#true"; } +} + +LiteralId ConjunctionLiteral::translate(Translator &x) { + auto &atm = dom()[id_.offset()]; + if (!atm.translated()) { + atm.setTranslated(); + LitVec bd; + for (auto &y : atm.elems()) { + if ((y.heads().size() == 1 && y.heads().front().second == 0) || y.bodies().empty()) { + // this part of the conditional literal is a fact + continue; + } + else if (y.isSimple(data_)) { + if (y.bodies().size() == 1 && y.bodies().front().second == 0) { + assert(y.heads().size() <= 1); + if (y.heads().empty()) { + if (!atm.lit()) { atm.setLit(data_.newAux()); } + return atm.lit(); + } + else { bd.emplace_back(data_.clause(y.heads().front()).front()); } + } + else { bd.emplace_back(data_.clause(y.bodies().front()).front().negate()); } + } + else { + LiteralId aux = data_.newAux(); + LiteralId auxHead = data_.newAux(); + for (auto &head : y.heads()) { + // auxHead :- y.head. + Rule().addHead(auxHead).addBody(data_.clause(head)).translate(data_, x); + Rule().addHead(aux).addBody(auxHead).translate(data_, x); + } + // chk <=> body. + LiteralId chk = getEqualFormula(data_, x, y.bodies(), false, atm.nonmonotone() && !y.heads().empty()); + Rule().addHead(aux).addBody(chk.negate()).translate(data_, x); + if (atm.nonmonotone() && !y.heads().empty()) { + // aux | chk | ~x.first. + Rule().addHead(aux).addHead(chk).addHead(auxHead.negate()).translate(data_, x); + } + // body += aux + bd.emplace_back(aux); + } + } + // bdLit :- body. + if (bd.size() == 1 && !atm.lit()) { + bd.front() = call(data_, bd.front(), &Literal::translate, x); + atm.setLit(bd.front()); + } + else { + if (!atm.lit()) { atm.setLit(data_.newAux()); } + Rule().addHead(atm.lit()).addBody(bd).translate(data_, x); + } + } + return atm.lit(); +} + +Lit_t ConjunctionLiteral::uid() const { + throw std::logic_error("ConjunctionLiteral::uid: must be called before ConjunctionLiteral::translate"); +} + +bool ConjunctionLiteral::isIncomplete() const { + return dom()[id_.offset()].recursive(); +} + +ConjunctionDomain &ConjunctionLiteral::dom() const { + return data_.getDom(id_.domain()); +} + +std::pair ConjunctionLiteral::delayedLit() { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {atm.lit(), !found}; +} + +bool ConjunctionLiteral::needsSemicolon() const { + auto &atm = dom()[id_.offset()]; + return !atm.elems().empty() && atm.elems().back().needsSemicolon(); +} + +ConjunctionLiteral::~ConjunctionLiteral() noexcept = default; + +// {{{1 definition of DisjointLiteral + +DisjointLiteral::DisjointLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +DisjointDomain &DisjointLiteral::dom() const { + return data_.getDom(id_.domain()); +} + +void DisjointLiteral::printPlain(PrintPlain out) const { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + if (atm.defined()) { + auto print_elems = [](PrintPlain out, DisjointElemSet::ValueType const &x) { + print_comma(out, out.domain.tuple(x.first), ","); + out << ":"; + using namespace std::placeholders; + print_comma(out, x.second, ",", std::bind(&DisjointElement::printPlain, _2, _1)); + }; + out << id_.sign(); + out << "#disjoint{"; + print_comma(out, atm.elems(), ";", print_elems); + out << "}"; + } + else { + out << (id_.sign() == NAF::NOT ? "#true" : "#false"); + } +} + +LiteralId DisjointLiteral::toId() const { + return id_; +} + +LiteralId DisjointLiteral::translate(Translator &x) { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + if (!atm.translated()) { + atm.setTranslated(); + if (atm.defined()) { + if (!atm.lit()) { atm.setLit(data_.newAux()); } + x.addDisjointConstraint(data_, id_); + } + else { makeFalse(data_, x, id_.sign(), atm); } + } + return id_.sign() != NAF::NOT ? atm.lit() : atm.lit().negate(); +} + +int DisjointLiteral::uid() const { + throw std::logic_error("DisjointLiteral::uid must be called after DisjointLiteral::translate"); +} + +bool DisjointLiteral::isIncomplete() const { + return data_.getAtom(id_.domain(), id_.offset()).recursive(); +} + +std::pair DisjointLiteral::delayedLit() { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {id_.sign() != NAF::NOT ? atm.lit() : atm.lit().negate(), !found}; +} + +DisjointLiteral::~DisjointLiteral() noexcept = default; + +// {{{1 definition of HeadAggregateLiteral + +HeadAggregateLiteral::HeadAggregateLiteral(DomainData &data, LiteralId id) +: data_(data) +, id_(id) { } + +LiteralId HeadAggregateLiteral::toId() const { + return id_; +} + +LiteralId HeadAggregateLiteral::translate(Translator &x) { + auto &atm = dom()[id_.offset()]; + if (!atm.translated()) { + atm.setTranslated(); + if (!atm.lit()) { atm.setLit(data_.newAux()); } + auto range(atm.range()); + if (!atm.satisfiable()) { + Rule().addBody(atm.lit()).translate(data_, x); + return atm.lit(); + } + using GroupedByCond = std::vector>>; + GroupedByCond groupedByCond; + for (auto &y : atm.elems()) { + for (auto &z : y.second) { groupedByCond.emplace_back(z.second, std::make_pair(y.first, z.first)); } + } + sort_unique(groupedByCond); + BodyAggregateElements bdElems; + for (auto it = groupedByCond.begin(), ie = groupedByCond.end(); it != ie; ) { + auto condId = it->first; + LiteralId condLit; + if (condId.second > 0) { + // c :- C. + condLit = getEqualClause(data_, x, condId, true, false); + } + Rule choice(true); + do { + // { heads } :- c, b. + LiteralId head = it->second.second; + if (head) { choice.addHead(head); } + // e :- h, c. + auto bdElem = bdElems.push(std::piecewise_construct, std::forward_as_tuple(it->second.first), std::forward_as_tuple()); + LitVec cond; + if (condLit) { cond.emplace_back(condLit); } + if (head) { cond.emplace_back(head); } + bdElem.first->second.emplace_back(data_.clause(cond)); + ++it; + } + while (it != ie && it->first == condId); + if (choice.numHeads() > 0) { + choice.addBody(atm.lit()); + if (condLit) { choice.addBody(condLit); } + choice.translate(data_, x); + } + } + // :- b, not aggr. + if (!atm.bounds().contains(range)) { + LiteralId aggr = getEqualAggregate(data_, x, atm.fun(), NAF::NOT, atm.bounds(), range, bdElems, false); + Rule check; + check.addBody(atm.lit()); + check.addBody(aggr).translate(data_, x); + } + } + return atm.lit(); +} + +void HeadAggregateLiteral::printPlain(PrintPlain out) const { + auto &atm = dom()[id_.offset()]; + auto bounds = atm.plainBounds(); + out << id_.sign(); + auto it = bounds.begin(), ie = bounds.end(); + if (it != ie) { out << it->second << inv(it->first); ++it; } + out << atm.fun() << "{"; + print_comma(out, atm.elems(), ";", printHeadElem); + out << "}"; + for (; it != ie; ++it) { out << it->first << it->second; } +} + +bool HeadAggregateLiteral::isIncomplete() const { + return true; +} + +HeadAggregateDomain &HeadAggregateLiteral::dom() const { + return data_.getDom(id_.domain()); +} + +int HeadAggregateLiteral::uid() const { + throw std::logic_error("HeadAggregateLiteral::uid must be called after BodyAggregateLiteral::translate"); +} + +std::pair HeadAggregateLiteral::delayedLit() { + auto &atm = data_.getAtom(id_.domain(), id_.offset()); + bool found = atm.lit(); + if (!found) { atm.setLit(data_.newDelayed()); } + return {atm.lit(), !found}; +} + +HeadAggregateLiteral::~HeadAggregateLiteral() noexcept = default; + +// {{{1 definition of DomainData + +Gringo::TheoryData::TermType DomainData::termType(Id_t value) const { + auto &term = theory_.data().getTerm(value); + switch (term.type()) { + case Potassco::Theory_t::Number: { return Gringo::TheoryData::TermType::Number; } + case Potassco::Theory_t::Symbol: { return Gringo::TheoryData::TermType::Symbol; } + case Potassco::Theory_t::Compound: { + if (term.isFunction()) { return Gringo::TheoryData::TermType::Function; } + switch (term.tuple()) { + case Potassco::Tuple_t::Paren: { return Gringo::TheoryData::TermType::Tuple; } + case Potassco::Tuple_t::Bracket: { return Gringo::TheoryData::TermType::List; } + case Potassco::Tuple_t::Brace: { return Gringo::TheoryData::TermType::Set; } + } + return Gringo::TheoryData::TermType::Number; + } + } + throw std::logic_error("must not happen"); +} + +int DomainData::termNum(Id_t value) const { + return theory_.data().getTerm(value).number(); +} + +char const *DomainData::termName(Id_t value) const { + if (theory_.data().getTerm(value).isFunction()) { + return theory_.data().getTerm(theory_.data().getTerm(value).function()).symbol(); + } + return theory_.data().getTerm(value).symbol(); +} + +Potassco::IdSpan DomainData::termArgs(Id_t value) const { + return theory_.data().getTerm(value).terms(); +} + +Potassco::IdSpan DomainData::elemTuple(Id_t value) const { + return theory_.data().getElement(value).terms(); +} + +Potassco::LitSpan DomainData::elemCond(Id_t value) const { + auto &data = const_cast(*this); + data.tempLits_.clear(); + for (auto &lit : theory_.getCondition(value)) { + data.tempLits_.emplace_back(call(data, lit, &Literal::uid)); + } + return Potassco::toSpan(data.tempLits_); +} + +Potassco::Lit_t DomainData::elemCondLit(Id_t value) const { + return theory_.data().getElement(value).condition(); +} + +Potassco::IdSpan DomainData::atomElems(Id_t value) const { + return theory_.getAtom(value).elements(); +} + +Potassco::Id_t DomainData::atomTerm(Id_t value) const { + return theory_.getAtom(value).term(); +} + +bool DomainData::atomHasGuard(Id_t value) const { + return theory_.getAtom(value).guard(); +} + +Potassco::Lit_t DomainData::atomLit(Id_t value) const { + return theory_.getAtom(value).atom(); +} + +std::pair DomainData::atomGuard(Id_t value) const { + return {termName(*theory_.getAtom(value).guard()), *theory_.getAtom(value).rhs()}; +} + +Potassco::Id_t DomainData::numAtoms() const { + return theory_.data().numAtoms(); +} + +std::string DomainData::termStr(Id_t value) const { + std::ostringstream oss; + theory_.printTerm(oss, value); + return oss.str(); +} + +std::string DomainData::elemStr(Id_t value) const { + std::ostringstream oss; + auto &data = const_cast(*this); + theory_.printElem(oss, value, [&data](std::ostream &out, LiteralId lit) { call(data, lit, &Literal::printPlain, PrintPlain{data, out}); }); + return oss.str(); +} + +std::string DomainData::atomStr(Id_t value) const { + std::ostringstream oss; + oss << "&"; + auto &atom = theory_.getAtom(value); + theory_.printTerm(oss, atom.term()); + oss << "{"; + bool comma = false; + for (auto &elem : atom.elements()) { + if (comma) { oss << ";"; } + else { comma = true; } + auto &data = const_cast(*this); + theory_.printElem(oss, elem, [&data](std::ostream &out, LiteralId lit) { call(data, lit, &Literal::printPlain, PrintPlain{data, out}); }); + } + oss << "}"; + if (atom.guard()) { + theory_.printTerm(oss, *atom.guard()); + theory_.printTerm(oss, *atom.rhs()); + } + return oss.str(); + +} + +// }}}1 + +} } // namespace Output Gringo diff --git a/libgringo/src/output/output.cc b/libgringo/src/output/output.cc new file mode 100644 index 0000000..264e959 --- /dev/null +++ b/libgringo/src/output/output.cc @@ -0,0 +1,446 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/output/output.hh" +#include "gringo/logger.hh" +#include "gringo/output/aggregates.hh" +#include "gringo/output/backends.hh" +#include "reify/program.hh" +#include + +namespace Gringo { namespace Output { + +// {{{1 internal functions and classes + +namespace { + +// {{{2 definition of DelayedStatement + +class DelayedStatement : public Statement { +public: + DelayedStatement(LiteralId lit) + : lit_(lit) + { } + void output(DomainData &, UBackend &) const override { } + void print(PrintPlain out, char const *prefix) const override { + auto lit = call(out.domain, lit_, &Literal::delayedLit).first; + out << prefix; + call(out.domain, lit, &Literal::printPlain, out); + out << " <=> "; + call(out.domain, lit_, &Literal::printPlain, out); + out << "\n"; + } + void translate(DomainData &data, Translator &trans) override { + trans.output(data, *this); + call(data, lit_, &Literal::translate, trans); + } + void replaceDelayed(DomainData &, LitVec &) override { } + virtual ~DelayedStatement() noexcept = default; +private: + LiteralId lit_; +}; + +// {{{2 definition of TranslateStatement + +template +class TranslateStatement : public Statement { +public: + TranslateStatement(T const &lambda) + : lambda_(lambda) + { } + void output(DomainData &, UBackend &) const override { } + void print(PrintPlain, char const *) const override { } + void translate(DomainData &data, Translator &trans) override { + trans.output(data, *this); + lambda_(data, trans); + } + void replaceDelayed(DomainData &, LitVec &) override { } + virtual ~TranslateStatement() { } +private: + T const &lambda_; +}; + +template +void translateLambda(DomainData &data, AbstractOutput &out, T const &lambda) { + TranslateStatement(lambda).passTo(data, out); +} + +// {{{2 definition of EndStepStatement + +class EndStepStatement : public Statement { +public: + EndStepStatement(OutputPredicates const &outPreds, bool solve, Logger &log) + : outPreds_(outPreds), log_(log), solve_(solve) { } + void output(DomainData &, UBackend &out) const override { + if (solve_) { + out->endStep(); + } + } + void print(PrintPlain out, char const *prefix) const override { + for (auto &x : outPreds_) { + if (std::get<1>(x).match("", 0)) { out << prefix << "#show.\n"; } + else { out << prefix << "#show " << (std::get<2>(x) ? "$" : "") << std::get<1>(x) << ".\n"; } + } + } + void translate(DomainData &data, Translator &trans) override { + trans.translate(data, outPreds_, log_); + trans.output(data, *this); + } + void replaceDelayed(DomainData &, LitVec &) override { } + virtual ~EndStepStatement() { } +private: + OutputPredicates const &outPreds_; + Logger &log_; + bool solve_; +}; + +// }}}2 + +} // namespace + +// {{{1 definition of TranslatorOutput + +TranslatorOutput::TranslatorOutput(UAbstractOutput &&out) +: trans_(std::move(out)) { } + +void TranslatorOutput::output(DomainData &data, Statement &stm) { + stm.translate(data, trans_); +} + +// {{{1 definition of TextOutput + +TextOutput::TextOutput(std::string prefix, std::ostream &stream, UAbstractOutput &&out) +: prefix_(prefix) +, stream_(stream) +, out_(std::move(out)) { } + +void TextOutput::TextOutput::output(DomainData &data, Statement &stm) { + stm.print({data, stream_}, prefix_.c_str()); + if (out_) { + out_->output(data, stm); + } +} + +// {{{1 definition of BackendOutput + +BackendOutput::BackendOutput(UBackend &&out) +: out_(std::move(out)) { } + +void BackendOutput::output(DomainData &data, Statement &stm) { + stm.output(data, out_); +} + +// {{{1 definition of OutputBase + +OutputBase::OutputBase(Potassco::TheoryData &data, OutputPredicates &&outPreds, std::ostream &out, OutputFormat format, OutputOptions opts) +: outPreds(std::move(outPreds)) +, data(data) +, out_(fromFormat(out, format, opts)) +{ } + +OutputBase::OutputBase(Potassco::TheoryData &data, OutputPredicates &&outPreds, UBackend &&out, OutputOptions opts) +: outPreds(std::move(outPreds)) +, data(data) +, out_(fromBackend(std::move(out), opts)) +{ } + +OutputBase::OutputBase(Potassco::TheoryData &data, OutputPredicates &&outPreds, UAbstractOutput &&out) +: outPreds(std::move(outPreds)) +, data(data) +, out_(std::move(out)) +{ } + +UAbstractOutput OutputBase::fromFormat(std::ostream &stream, OutputFormat format, OutputOptions opts) { + if (format == OutputFormat::TEXT) { + UAbstractOutput out; + out = gringo_make_unique("", stream); + if (opts.debug == OutputDebug::TEXT) { + out = gringo_make_unique("% ", std::cerr, std::move(out)); + } + return out; + } + else { + UBackend backend; + switch (format) { + case OutputFormat::REIFY: { + backend = gringo_make_unique(stream, opts.reifySCCs, opts.reifySteps); + break; + } + case OutputFormat::INTERMEDIATE: { + backend = gringo_make_unique(stream); + break; + } + case OutputFormat::SMODELS: { + backend = gringo_make_unique(stream); + break; + } + case OutputFormat::TEXT: { + throw std::logic_error("cannot happen"); + } + } + return fromBackend(std::move(backend), opts); + } +} + +UAbstractOutput OutputBase::fromBackend(UBackend &&backend, OutputOptions opts) { + UAbstractOutput out; + out = gringo_make_unique(std::move(backend)); + if (opts.debug == OutputDebug::TRANSLATE || opts.debug == OutputDebug::ALL) { + out = gringo_make_unique("%% ", std::cerr, std::move(out)); + } + out = gringo_make_unique(std::move(out)); + if (opts.debug == OutputDebug::TEXT || opts.debug == OutputDebug::ALL) { + out = gringo_make_unique("% ", std::cerr, std::move(out)); + } + return out; +} + +void OutputBase::init(bool incremental) { + backendLambda(data, *out_, [incremental](DomainData &, UBackend &out) { out->initProgram(incremental); }); +} + +void OutputBase::output(Statement &x) { + x.replaceDelayed(data, delayed_); + out_->output(data, x); +} + +void OutputBase::flush() { + for (auto &lit : delayed_) { DelayedStatement(lit).passTo(data, *out_); } + delayed_.clear(); + backendLambda(data, *out_, [](DomainData &data, UBackend &out) { + auto getCond = [&data](Id_t elem) { + TheoryData &td = data.theory(); + BackendLitVec bc; + for (auto &lit : td.getCondition(elem)) { + bc.emplace_back(call(data, lit, &Literal::uid)); + } + return bc; + }; + Gringo::output(data.theory().data(), *out, getCond); + }); +} + +void OutputBase::beginStep() { + backendLambda(data, *out_, [](DomainData &, UBackend &out) { out->beginStep(); }); +} + +void OutputBase::endStep(bool solve, Logger &log) { + if (!outPreds.empty()) { + std::move(outPredsForce.begin(), outPredsForce.end(), std::back_inserter(outPreds)); + outPredsForce.clear(); + } + EndStepStatement(outPreds, solve, log).passTo(data, *out_); + // TODO: get rid of such things #d domains should be stored somewhere else + std::set rm; + for (auto &x : predDoms()) { + if (x->sig().name().startsWith("#d")) { + rm.emplace(x->sig()); + } + } + if (!rm.empty()) { + predDoms().erase([&rm](UPredDom const &dom) { + return rm.find(dom->sig()) != rm.end(); + }); + } +} + +void OutputBase::reset() { + data.reset(); + translateLambda(data, *out_, [](DomainData &, Translator &x) { x.reset(); }); +} + +void OutputBase::checkOutPreds(Logger &log) { + auto le = [](OutputPredicates::value_type const &x, OutputPredicates::value_type const &y) -> bool { + if (std::get<1>(x) != std::get<1>(y)) { return std::get<1>(x) < std::get<1>(y); } + return std::get<2>(x) < std::get<2>(y); + }; + auto eq = [](OutputPredicates::value_type const &x, OutputPredicates::value_type const &y) { + return std::get<1>(x) == std::get<1>(y) && std::get<2>(x) == std::get<2>(y); + }; + std::sort(outPreds.begin(), outPreds.end(), le); + outPreds.erase(std::unique(outPreds.begin(), outPreds.end(), eq), outPreds.end()); + for (auto &x : outPreds) { + if (!std::get<1>(x).match("", 0) && !std::get<2>(x)) { + auto it(predDoms().find(std::get<1>(x))); + if (it == predDoms().end()) { + GRINGO_REPORT(log, clingo_warning_atom_undefined) + << std::get<0>(x) << ": info: no atoms over signature occur in program:\n" + << " " << std::get<1>(x) << "\n"; + } + } + } +} + +SymVec OutputBase::atoms(unsigned atomset, IsTrueLookup isTrue) const { + SymVec atoms; + translateLambda(const_cast(data), *out_, [&](DomainData &data, Translator &trans) { + trans.atoms(data, atomset, isTrue, atoms, outPreds); + }); + return atoms; +} + +std::pair OutputBase::find(Symbol val) const { + return const_cast(this)->find(val); +} + +std::pair OutputBase::find(Symbol val) { + if (val.type() == SymbolType::Fun) { + auto it = predDoms().find(val.sig()); + if (it != predDoms().end()) { + auto jt = (*it)->find(val); + if (jt != (*it)->end() && jt->defined()) { + return {jt, it->get()}; + } + } + } + return {PredicateDomain::Iterator(), nullptr}; +} + +std::pair OutputBase::simplify(AssignmentLookup assignment) { + Id_t facts = 0; + Id_t deleted = 0; + if (true) { + if (data.canSimplify()) { + std::vector mappings; + for (auto &dom : data.predDoms()) { + mappings.emplace_back(); + auto ret = dom->cleanup(assignment, mappings.back()); + facts+= ret.first; + deleted+= ret.second; + } + translateLambda(data, *out_, [&](DomainData &data, Translator &trans) { trans.simplify(data, mappings, assignment); }); + } + } + return {facts, deleted}; +} + +Backend *OutputBase::backend() { + Backend *backend = nullptr; + backendLambda(data, *out_, [&backend](DomainData &, UBackend &out) { backend = out.get(); }); + return backend; +} + +namespace { + +class BackendTee : public Potassco::AbstractProgram { +public: + using Head_t = Potassco::Head_t; + using Value_t = Potassco::Value_t; + using Heuristic_t = Potassco::Heuristic_t; + using IdSpan = Potassco::IdSpan; + using AtomSpan = Potassco::AtomSpan; + using LitSpan = Potassco::LitSpan; + using WeightLitSpan = Potassco::WeightLitSpan; + + BackendTee(UBackend a, UBackend b) : a_(std::move(a)), b_(std::move(b)) { } + ~BackendTee() override = default; + + void initProgram(bool incremental) override { + a_->initProgram(incremental); + b_->initProgram(incremental); + } + void beginStep() override { + a_->beginStep(); + b_->beginStep(); + } + void endStep() override { + a_->endStep(); + b_->endStep(); + } + + void rule(Head_t ht, const AtomSpan& head, const LitSpan& body) override { + a_->rule(ht, head, body); + b_->rule(ht, head, body); + } + void rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) override { + a_->rule(ht, head, bound, body); + b_->rule(ht, head, bound, body); + } + void minimize(Weight_t prio, const WeightLitSpan& lits) override { + a_->minimize(prio, lits); + b_->minimize(prio, lits); + } + + void project(const AtomSpan& atoms) override { + a_->project(atoms); + b_->project(atoms); + } + void output(const StringSpan& str, const LitSpan& condition) override { + a_->output(str, condition); + b_->output(str, condition); + } + void external(Atom_t a, Value_t v) override { + a_->external(a, v); + b_->external(a, v); + } + void assume(const LitSpan& lits) override { + a_->assume(lits); + b_->assume(lits); + } + void heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& condition) override { + a_->heuristic(a, t, bias, prio, condition); + b_->heuristic(a, t, bias, prio, condition); + } + void acycEdge(int s, int t, const LitSpan& condition) override { + a_->acycEdge(s, t, condition); + b_->acycEdge(s, t, condition); + } + + void theoryTerm(Id_t termId, int number) override { + a_->theoryTerm(termId, number); + b_->theoryTerm(termId, number); + } + void theoryTerm(Id_t termId, const StringSpan& name) override { + a_->theoryTerm(termId, name); + b_->theoryTerm(termId, name); + } + void theoryTerm(Id_t termId, int cId, const IdSpan& args) override { + a_->theoryTerm(termId, cId, args); + b_->theoryTerm(termId, cId, args); + } + void theoryElement(Id_t elementId, const IdSpan& terms, const LitSpan& cond) override { + a_->theoryElement(elementId, terms, cond); + b_->theoryElement(elementId, terms, cond); + } + void theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements) override { + a_->theoryAtom(atomOrZero, termId, elements); + b_->theoryAtom(atomOrZero, termId, elements); + } + void theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements, Id_t op, Id_t rhs) override { + a_->theoryAtom(atomOrZero, termId, elements, op, rhs); + b_->theoryAtom(atomOrZero, termId, elements, op, rhs); + } + +private: + UBackend a_; + UBackend b_; +}; + +} // namespace + +void OutputBase::registerObserver(UBackend prg) { + backendLambda(data, *out_, [&prg](DomainData &, UBackend &out) { + if (prg) { out = gringo_make_unique(std::move(prg), std::move(out)); } + }); +} + +// }}}1 + +} } // namespace Output Gringo diff --git a/libgringo/src/output/statement.cc b/libgringo/src/output/statement.cc new file mode 100644 index 0000000..826d261 --- /dev/null +++ b/libgringo/src/output/statement.cc @@ -0,0 +1,55 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/output/statement.hh" +#include "gringo/output/literals.hh" + +namespace Gringo { namespace Output { + +void replaceDelayed(DomainData &data, LiteralId &lit, LitVec &delayed) { + if (call(data, lit, &Literal::isIncomplete)) { + auto ret = call(data, lit, &Literal::delayedLit); + assert(ret.first.type() == AtomType::Aux); + if (ret.second) { + if (ret.first.sign() != NAF::POS) { + assert(ret.first.sign() == lit.sign()); + delayed.emplace_back(lit.withSign(NAF::POS)); + } + else { delayed.emplace_back(lit); } + } + lit = ret.first; + } +} +void replaceDelayed(DomainData &data, LitVec &lits, LitVec &delayed) { + for (auto &lit : lits) { replaceDelayed(data, lit, delayed); } +} + +void translate(DomainData &data, Translator &x, LiteralId &lit) { + lit = call(data, lit, &Literal::translate, x); +} + +void translate(DomainData &data, Translator &x, LitVec &lits) { + for (auto &lit : lits) { + translate(data, x, lit); + } +} + +} } // namespace Output Gringo + diff --git a/libgringo/src/output/statements.cc b/libgringo/src/output/statements.cc new file mode 100644 index 0000000..a413114 --- /dev/null +++ b/libgringo/src/output/statements.cc @@ -0,0 +1,967 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include +#include +#include +#include + +namespace Gringo { namespace Output { + +// {{{1 definition of helpers to print interval sets + +namespace Debug { + +std::ostream &operator<<(std::ostream &out, IntervalSet::LBound const &x) { + out << (x.inclusive ? "[" : "(") << x.bound; + return out; +} + +std::ostream &operator<<(std::ostream &out, IntervalSet::RBound const &x) { + out << x.bound << (x.inclusive ? "]" : ")"); + return out; +} + +std::ostream &operator<<(std::ostream &out, IntervalSet::Interval const &x) { + out << x.left << "," << x.right; + return out; +} + +std::ostream &operator<<(std::ostream &out, IntervalSet const &x) { + out << "{"; + print_comma(out, x.vec, ",", [](std::ostream &out, IntervalSet::Interval const &x) { out << x; }); + out << "}"; + return out; +} + +} // namespace Debug + +namespace { + +void printPlainBody(PrintPlain out, LitVec const &body) { + int sep = 0; + for (auto &x : body) { + switch (sep) { + case 1: { out << ","; break; } + case 2: { out << ";"; break; } + } + call(out.domain, x, &Literal::printPlain, out); + sep = call(out.domain, x, &Literal::needsSemicolon) + 1; + } +} + +void printPlainHead(PrintPlain out, LitVec const &body, bool choice) { + bool sep = false; + if (choice) { out << "{"; } + for (auto &x : body) { + if (sep) { out << ";"; } + call(out.domain, x, &Literal::printPlain, out); + sep = true; + } + if (choice) { out << "}"; } +} + +bool updateBound(DomainData &data, LitVec const &head, LitVec const &body, Translator &trans) { + Symbol value; + for (auto &y : head) { + if (!call(data, y, &Literal::isBound, value, false)) { return false; } + } + for (auto &y : body) { + if (!call(data, y, &Literal::isBound, value, true)) { return false; } + } + if (value.type() == SymbolType::Special) { return false; } + std::vector bounds; + for (auto &y : body) { + call(data, y, &Literal::updateBound, bounds, true); + } + trans.addBounds(value, bounds); + return true; +} + +} // namespace + + +// }}}1 + +// {{{1 definition of Rule + +Rule::Rule(bool choice) +: choice_(choice) { } + +Rule &Rule::reset(bool choice) { + choice_ = choice; + head_.clear(); + body_.clear(); + return *this; +} + +Rule &Rule::addHead(LiteralId lit) { + head_.emplace_back(lit); + return *this; +} + +Rule &Rule::addBody(LiteralId lit) { + body_.emplace_back(lit); + return *this; +} + +Rule &Rule::negatePrevious(DomainData &data) { + for (auto &lit : head_) { + if (call(data, lit, &Literal::isAtomFromPreviousStep)) { + lit = lit.negate(); + lit = lit.negate(); + } + } + return *this; +} + +void Rule::print(PrintPlain out, char const *prefix) const { + out << prefix; + printPlainHead(out, head_, choice_); + if (!body_.empty() || head_.empty()) { out << ":-"; } + printPlainBody(out, body_); + out << ".\n"; +} + +void Rule::translate(DomainData &data, Translator &x) { + head_.erase(std::remove_if(head_.begin(), head_.end(), [&](LiteralId &lit) { + if (!call(data, lit, &Literal::isHeadAtom)) { + if (!choice_) { body_.emplace_back(lit.negate()); } + return true; + } + return false; + }), head_.end()); + if (!updateBound(data, head_, body_, x)) { + Gringo::Output::translate(data, x, head_); + Gringo::Output::translate(data, x, body_); + x.output(data, *this); + } +} +void Rule::output(DomainData &data, UBackend &out) const { + BackendAtomVec &hd = data.tempAtoms(); + for (auto &x : head_) { + Potassco::Lit_t lit = call(data, x, &Literal::uid); + assert(lit > 0); + hd.emplace_back(static_cast(lit)); + } + BackendLitVec &bd = data.tempLits(); + for (auto &x : body_) { bd.emplace_back(call(data, x, &Literal::uid)); } + outputRule(*out, choice_, hd, bd); +} + +void Rule::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, head_, delayed); + Gringo::Output::replaceDelayed(data, body_, delayed); +} + +Rule::~Rule() { } + +// {{{1 definition of External + +External::External(LiteralId head, Potassco::Value_t type) +: head_(head) +, type_(type) { } + +void External::print(PrintPlain out, char const *prefix) const { + out << prefix << "#external "; + call(out.domain, head_, &Literal::printPlain, out); + switch (type_) { + case Potassco::Value_t::False: { out << ".\n"; break; } + case Potassco::Value_t::True: { out << "=true.\n"; break; } + case Potassco::Value_t::Free: { out << "=free.\n"; break; } + case Potassco::Value_t::Release: { out << "=release.\n"; break; } + } +} + +void External::translate(DomainData &data, Translator &x) { + x.output(data, *this); +} + +void External::output(DomainData &data, UBackend &out) const { + Atom_t head = call(data, head_, &Literal::uid); + out->external(head, type_); +} + +void External::replaceDelayed(DomainData &data, LitVec &) { + (void)data; + assert(!call(data, head_, &Literal::isIncomplete)); +} + +External::~External() { } + +// {{{1 definition of ShowStatement + +ShowStatement::ShowStatement(Symbol term, bool csp, LitVec const &body) +: term_(term) +, body_(body) +, csp_(csp) { } + +void ShowStatement::print(PrintPlain out, char const *prefix) const { + out << prefix; + out << "#show " << (csp_ ? "$" : "") << term_; + if (!body_.empty()) { out << ":"; } + printPlainBody(out, body_); + out << ".\n"; +} + +void ShowStatement::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, body_, delayed); +} + +void ShowStatement::translate(DomainData &data, Translator &x) { + Gringo::Output::translate(data, x, body_); + x.showTerm(data, term_, csp_, std::move(body_)); +} + +void ShowStatement::output(DomainData &, UBackend &) const { + // Show statements are taken care of in the translator. +} + +// {{{1 definition of ProjectStatement + +ProjectStatement::ProjectStatement(LiteralId atom) +: atom_(atom) { + assert(atom.sign() == NAF::POS); + assert(atom.type() == AtomType::Predicate); +} + +void ProjectStatement::print(PrintPlain out, char const *prefix) const { + out << prefix << "#project "; + call(out.domain, atom_, &Literal::printPlain, out); + out << ".\n"; +} + +void ProjectStatement::translate(DomainData &data, Translator &x) { + x.output(data, *this); +} + +void ProjectStatement::output(DomainData &data, UBackend &out) const { + BackendAtomVec atoms; + atoms.emplace_back(call(data, atom_, &Literal::uid)); + out->project(Potassco::toSpan(atoms)); +} + +void ProjectStatement::replaceDelayed(DomainData &, LitVec &) { +} + +// {{{1 definition of HeuristicStatement + +HeuristicStatement::HeuristicStatement(LiteralId atom, int value, int priority, Potassco::Heuristic_t mod, LitVec const &body) +: atom_(atom) +, value_(value) +, priority_(priority) +, mod_(mod) +, body_(body) { + assert(atom.sign() == NAF::POS); + assert(atom.type() == AtomType::Predicate); +} + +void HeuristicStatement::print(PrintPlain out, char const *prefix) const { + out << prefix << "#heuristic "; + call(out.domain, atom_, &Literal::printPlain, out); + if (!body_.empty()) { out << ":"; } + printPlainBody(out, body_); + out << ".[" << value_ << "@" << priority_ << "," << toString(mod_) << "]\n"; +} + +void HeuristicStatement::translate(DomainData &data, Translator &x) { + Gringo::Output::translate(data, x, body_); + x.output(data, *this); +} + +void HeuristicStatement::output(DomainData &data, UBackend &out) const { + auto uid = call(data, atom_, &Literal::uid); + BackendLitVec bd; + for (auto &lit : body_) { + bd.emplace_back(call(data, lit, &Literal::uid)); + } + out->heuristic(uid, mod_, value_, priority_, Potassco::toSpan(bd)); +} + +void HeuristicStatement::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, body_, delayed); +} + +// {{{1 definition of EdgeStatement + +EdgeStatement::EdgeStatement(Symbol u, Symbol v, LitVec const &body) +: u_(u) +, v_(v) +, uidU_(0) +, uidV_(0) +, body_(body) +{ } + +void EdgeStatement::print(PrintPlain out, char const *prefix) const { + out << prefix; + out << "#edge(" << u_ << "," << v_ << ")"; + if (!body_.empty()) { out << ":"; } + printPlainBody(out, body_); + out << ".\n"; +} + +void EdgeStatement::translate(DomainData &data, Translator &x) { + Gringo::Output::translate(data, x, body_); + uidU_ = x.nodeUid(u_); + uidV_ = x.nodeUid(v_); + x.output(data, *this); +} + +void EdgeStatement::output(DomainData &data, UBackend &out) const { + BackendLitVec bd; + for (auto &x : body_) { bd.emplace_back(call(data, x, &Literal::uid)); } + out->acycEdge(uidU_, uidV_, Potassco::toSpan(bd)); +} + +void EdgeStatement::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, body_, delayed); +} + +// {{{1 definition of TheoryDirective + +TheoryDirective::TheoryDirective(LiteralId theoryLit) +: theoryLit_(theoryLit) { + assert(theoryLit_.type() == AtomType::Theory); +} + +void TheoryDirective::print(PrintPlain out, char const *prefix) const { + out << prefix; + call(out.domain, theoryLit_, &Literal::printPlain, out); + out << ".\n"; +} + +void TheoryDirective::translate(DomainData &data, Translator &x) { + x.output(data, *this); + assert(!data.getAtom(theoryLit_).recursive() && data.getAtom(theoryLit_).type() == TheoryAtomType::Directive); + call(data, theoryLit_, &Literal::translate, x); +} + +void TheoryDirective::output(DomainData &, UBackend &) const { + // Note: taken care of in translate +} + +void TheoryDirective::replaceDelayed(DomainData &, LitVec &) { +} + +// {{{1 definition of Minimize + +void WeakConstraint::translate(DomainData &data, Translator &x) { + for (auto &z : lits_) { z = call(data, z, &Literal::translate, x); } + x.addMinimize(data.tuple(tuple_), getEqualClause(data, x, data.clause(std::move(lits_)), true, false)); +} + +void WeakConstraint::print(PrintPlain out, char const *prefix) const { + out << prefix; + out << ":~"; + printPlainBody(out, lits_); + out << ".["; + auto it(tuple_.begin()); + out << *it++ << "@"; + out << *it++; + for (auto ie(tuple_.end()); it != ie; ++it) { out << "," << *it; } + out << "]\n"; +} + +void WeakConstraint::output(DomainData &, UBackend &) const { + throw std::logic_error("WeakConstraint::output: must not be called"); +} + +void WeakConstraint::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, lits_, delayed); +} + +// }}} + + +// {{{1 definition of Bound + +bool Bound::init(DomainData &data, Translator &x, Logger &log) { + if (modified) { + modified = false; + if (range_.empty()) { Rule().translate(data, x); } + else { + if (range_.front() == std::numeric_limits::min() || range_.back()+1 == std::numeric_limits::max()) { + if (range_.front() != std::numeric_limits::min()) { range_.remove(range_.front()+1, std::numeric_limits::max()); } + else if (range_.back()+1 != std::numeric_limits::max()) { range_.remove(std::numeric_limits::min(), range_.back()); } + else { range_.clear(), range_.add(0, 1); } + GRINGO_REPORT(log, clingo_warning_variable_unbounded) + << "warning: unbounded constraint variable:\n" + << " domain of '" << var << "' is set to [" << range_.front() << "," << range_.back() << "]\n" + ; + } + if (atoms.empty()) { + auto assign = [&](Potassco::Atom_t a, Potassco::Atom_t b) { + if (b) { + Rule rule(true); + if (a) { rule.addBody({NAF::POS, AtomType::Aux, a, 0}); } + rule.addHead({NAF::POS, AtomType::Aux, b, 0}).translate(data, x); + } + }; + for (auto y : range_) { + if (y == range_.front()) { atoms.emplace_back(y, 0); } + else { atoms.emplace_back(y, data.newAtom()); } + } + for (auto jt = atoms.begin() + 1; jt != atoms.end(); ++jt) { assign(jt->second, (jt-1)->second); } + assign(0, atoms.back().second); + } + else { // incremental update of bounds + AtomVec next; + int l = range_.front(), r = range_.back(); + for (auto jt = atoms.begin() + 1; jt != atoms.end(); ++jt) { + int w = (jt - 1)->first; + if (w < l) { Rule().addBody({NAF::POS, AtomType::Aux, jt->second, 0}).translate(data, x); } + else if (w >= r) { + Rule().addBody({NAF::NOT, AtomType::Aux, jt->second, 0}).translate(data, x); + if (w == r) { next.emplace_back(*(jt - 1)); } + } + else if (!range_.contains(w, w + 1)) { Rule().addBody({NAF::NOT, AtomType::Aux, (jt-1)->second, 0}).addBody({NAF::POS, AtomType::Aux, jt->second, 0}).translate(data, x); } + else { next.emplace_back(*(jt - 1)); } + } + if (atoms.back().first <= r) { next.emplace_back(atoms.back()); } + next.front().second = 0; + atoms = std::move(next); + } + } + } + return !range_.empty(); +} + +// {{{1 definition of LinearConstraint + +void LinearConstraint::Generate::generate(StateVec::iterator it, int current, int remainder) { + if (current + remainder > getBound()) { + if (it == states.end()) { + assert(remainder == 0); + aux.emplace_back(data.newAtom()); + for (auto &x : states) { + if (x.atom != x.bound.atoms.end() && x.atom->second) { + Rule() + .addHead({NAF::POS, AtomType::Aux, aux.back(), 0}) + .addBody({x.coef < 0 ? NAF::NOT : NAF::POS, AtomType::Aux, x.atom->second, 0}) + .translate(data, trans); + } + } + } + else { + remainder -= it->upper() - it->lower(); + int total = current - it->lower(); + for (it->reset(); it->valid(); it->next(total, current)) { + generate(it+1, current, remainder); + if (current > getBound()) { break; } + } + } + } +} + +bool LinearConstraint::Generate::init() { + int current = 0; + int remainder = 0; + for (auto &y : cons.coefs) { + states.emplace_back(trans.findBound(y.second), y); + current += states.back().lower(); + remainder += states.back().upper() - states.back().lower(); + } + if (current <= getBound()) { + generate(states.begin(), current, remainder); + Rule rule; + for (auto &x : aux) { rule.addBody({NAF::POS, AtomType::Aux, x, 0}); } + rule.addHead({NAF::POS, AtomType::Aux, cons.atom, 0}).translate(data, trans); + } + return current <= cons.bound; +} + +bool LinearConstraint::translate(DomainData &data, Translator &x) { + Generate gen(*this, data, x); + return gen.init(); +} + +// }}}1 + +// {{{1 definition of Translator + +Translator::Translator(UAbstractOutput &&out) +: out_(std::move(out)) +{ } + +Translator::BoundMap::Iterator Translator::addBound(Symbol x) { + auto it = boundMap_.find(x); + return it != boundMap_.end() ? it : boundMap_.push(x).first; +} + +Bound &Translator::findBound(Symbol x) { + auto it = boundMap_.find(x); + assert(it != boundMap_.end()); + return *it; +} + +void Translator::addLowerBound(Symbol x, int bound) { + auto &y = *addBound(x); + y.remove(std::numeric_limits::min(), bound); +} + +void Translator::addUpperBound(Symbol x, int bound) { + auto &y = *addBound(x); + y.remove(bound+1, std::numeric_limits::max()); +} + +void Translator::addBounds(Symbol value, std::vector bounds) { + std::map> boundUnion; + for (auto &x : bounds) { + boundUnion[value].add(x.first, x.second+1); + } + for (auto &x : boundUnion) { + auto &z = *addBound(x.first); + z.intersect(x.second); + } +} +void Translator::addLinearConstraint(Potassco::Atom_t head, CoefVarVec &&vars, int bound) { + for (auto &x : vars) { addBound(x.second); } + constraints_.emplace_back(head, std::move(vars), bound); +} +void Translator::addDisjointConstraint(DomainData &data, LiteralId lit) { + auto &atm = data.getAtom(lit.domain(), lit.offset()); + for (auto &x : atm.elems()) { + for (auto &y : x.second) { + for (auto z : y.value()) { addBound(z.second); } + } + } + disjointCons_.emplace_back(lit); +} +void Translator::addMinimize(TupleId tuple, LiteralId cond) { + minimize_.emplace_back(tuple, cond); +} +void Translator::translate(DomainData &data, OutputPredicates const &outPreds, Logger &log) { + for (auto &x : boundMap_) { + if (!x.init(data, *this, log)) { return; } + } + for (auto &lit : disjointCons_) { + auto &atm = data.getAtom(lit.domain(), lit.offset()); + atm.translate(data, *this, log); + } + for (auto &x : constraints_) { x.translate(data, *this); } + disjointCons_.clear(); + constraints_.clear(); + translateMinimize(data); + outputSymbols(data, outPreds, log); +} + +bool Translator::showBound(OutputPredicates const &outPreds, Bound const &bound) { + return outPreds.empty() || (bound.var.type() == SymbolType::Fun && showSig(outPreds, bound.var.sig(), true)); +} + +void Translator::outputSymbols(DomainData &data, OutputPredicates const &outPreds, Logger &log) { + { // show csp varibles + for (auto it = boundMap_.begin() + incBoundOffset_, ie = boundMap_.end(); it != ie; ++it, ++incBoundOffset_) { + if (it->var.type() == SymbolType::Fun) { seenSigs_.insert(std::hash(), std::equal_to(), it->var.sig().rep()); } + if (showBound(outPreds, *it)) { showValue(data, *it, LitVec{}); } + } + } + // check for signatures that did not occur in the program + for (auto &x : outPreds) { + if (!std::get<1>(x).match("", 0, false) && std::get<2>(x)) { + auto it(seenSigs_.find(std::hash(), std::equal_to(), std::get<1>(x).rep())); + if (!it) { + GRINGO_REPORT(log, clingo_warning_atom_undefined) + << std::get<0>(x) << ": info: no constraint variables over signature occur in program:\n" + << " $" << std::get<1>(x) << "\n"; + seenSigs_.insert(std::hash(), std::equal_to(), std::get<1>(x).rep()); + } + } + } + // show what was requested + if (!outPreds.empty()) { + for (auto &x : outPreds) { + if (!std::get<2>(x)) { + auto it(data.predDoms().find(std::get<1>(x))); + if (it != data.predDoms().end()) { + showAtom(data, it); + } + } + } + } + // show everything non-internal + else { + for (auto it = data.predDoms().begin(), ie = data.predDoms().end(); it != ie; ++it) { + Sig sig = **it; + auto name(sig.name()); + if (!name.startsWith("#")) { showAtom(data, it); } + } + } + // show terms + for (auto &todo : termOutput_.todo) { + if (todo.cond.empty()) { continue; } + showValue(data, todo.term, updateCond(data, termOutput_.table, todo)); + } + termOutput_.todo.clear(); + // show csp variables + for (auto &todo : cspOutput_.todo) { + auto bound = boundMap_.find(todo.term); + if (bound == boundMap_.end()) { + // TODO: clingo_warning_atom_undefined??? + GRINGO_REPORT(log, clingo_warning_atom_undefined) + << "info: constraint variable does not occur in program:\n" + << " $" << todo.term << "\n"; + continue; + } + if (todo.cond.empty() || showBound(outPreds, *bound)) { continue; } + showValue(data, *bound, updateCond(data, cspOutput_.table, todo)); + } + cspOutput_.todo.clear(); +} + +LitVec Translator::updateCond(DomainData &data, OutputTable::Table &table, OutputTable::Todo::ValueType &todo) { + LiteralId excludeOldCond; + auto entry = table.push(todo.term, LiteralId{}); + if (!entry.second) { + LiteralId oldCond = entry.first->cond; + LiteralId newCond = getEqualFormula(data, *this, todo.cond, false, false); + LiteralId includeOldCond = getEqualClause(data, *this, data.clause(LitVec{oldCond, newCond}), false, false); + excludeOldCond = getEqualClause(data, *this, data.clause(LitVec{oldCond.negate(), newCond}), true, false); + entry.first->cond = includeOldCond; + } + else { + excludeOldCond = getEqualFormula(data, *this, todo.cond, false, false); + entry.first->cond = excludeOldCond; + } + return {excludeOldCond}; +} + +bool Translator::showSig(OutputPredicates const &outPreds, Sig sig, bool csp) { + if (outPreds.empty()) { return true; } + auto le = [](OutputPredicates::value_type const &x, OutputPredicates::value_type const &y) -> bool { + if (std::get<1>(x) != std::get<1>(y)) { return std::get<1>(x) < std::get<1>(y); } + return std::get<2>(x) < std::get<2>(y); + }; + static Location loc("",1,1,"",1,1); + return std::binary_search(outPreds.begin(), outPreds.end(), OutputPredicates::value_type(loc, sig, csp), le); +} + +void Translator::showCsp(Bound const &bound, IsTrueLookup isTrue, SymVec &atoms) { + assert(!bound.atoms.empty()); + int prev = bound.atoms.front().first; + for (auto it = bound.atoms.begin()+1; it != bound.atoms.end() && !isTrue(it->second); ++it) { prev = it->first; } + atoms.emplace_back(Symbol::createFun("$", Potassco::toSpan(SymVec{bound.var, Symbol::createNum(prev)}))); +} + +void Translator::atoms(DomainData &data, unsigned atomset, IsTrueLookup isTrue, SymVec &atoms, OutputPredicates const &outPreds) { + auto isComp = [isTrue, atomset](unsigned x) { return (atomset & clingo_show_type_complement) ? !isTrue(x) : isTrue(x); }; + if (atomset & (clingo_show_type_csp | clingo_show_type_shown)) { + for (auto &x : boundMap_) { + if (atomset & clingo_show_type_csp || (atomset & clingo_show_type_shown && showBound(outPreds, x))) { showCsp(x, isTrue, atoms); } + } + } + if (atomset & (clingo_show_type_atoms | clingo_show_type_shown)) { + for (auto &x : data.predDoms()) { + Sig sig = *x; + auto name = sig.name(); + if (((atomset & clingo_show_type_atoms || (atomset & clingo_show_type_shown && showSig(outPreds, sig, false))) && !name.empty() && !name.startsWith("#"))) { + for (auto &y: *x) { + if (y.defined() && y.hasUid() && isComp(y.uid())) { atoms.emplace_back(y); } + } + } + } + } + if (atomset & clingo_show_type_shown) { + for (auto &entry : cspOutput_.table) { + auto bound = boundMap_.find(entry.term); + if (bound != boundMap_.end() && !showBound(outPreds, *bound) && call(data, entry.cond, &Literal::isTrue, isComp)) { + showCsp(*bound, isTrue, atoms); + } + } + } + if (atomset & (clingo_show_type_terms | clingo_show_type_shown)) { + for (auto &entry : termOutput_.table) { + if (isComp(call(data, entry.cond, &Literal::uid))) { + atoms.emplace_back(entry.term); + } + } + } +} + +void Translator::simplify(DomainData &data, Mappings &mappings, AssignmentLookup assignment) { + minimize_.erase(std::remove_if(minimize_.begin(), minimize_.end(), [&](MinimizeList::value_type &elem) { + elem.second = call(data, elem.second, &Literal::simplify, mappings, assignment); + return elem.second != data.getTrueLit().negate(); + }), minimize_.end()); + tuples_.erase([&](TupleLitMap::ValueType &elem) { + elem.second = call(data, elem.second, &Literal::simplify, mappings, assignment); + return elem.second != data.getTrueLit().negate(); + }); + termOutput_.table.erase([&](OutputTable::Table::ValueType &elem) { + elem.cond = call(data, elem.cond, &Literal::simplify, mappings, assignment); + return elem.cond != data.getTrueLit().negate(); + }); + cspOutput_.table.erase([&](OutputTable::Table::ValueType &elem) { + elem.cond = call(data, elem.cond, &Literal::simplify, mappings, assignment); + return elem.cond != data.getTrueLit().negate(); + }); +} + +void Translator::output(DomainData &data, Statement &stm) { + out_->output(data, stm); +} + +void Translator::showAtom(DomainData &data, PredDomMap::Iterator it) { + for (auto jt = (*it)->begin() + (*it)->showOffset(), je = (*it)->end(); jt != je; ++jt) { + if (jt->defined()) { + LitVec cond; + if (!jt->fact()) { + Potassco::Id_t domain = it - data.predDoms().begin(); + Potassco::Id_t offset = jt - (*it)->begin(); + cond.emplace_back(NAF::POS, AtomType::Predicate, offset, domain); + } + showValue(data, *jt, cond); + } + } + (*it)->showNext(); +} + +void Translator::showValue(DomainData &data, Symbol value, LitVec const &cond) { + Symtab(value, get_clone(cond)).translate(data, *this); +} + +void Translator::showValue(DomainData &data, Bound const &bound, LitVec const &cond) { + if (bound.var.type() != SymbolType::Fun || !bound.var.name().startsWith("#")) { + auto assign = [&](int i, Potassco::Atom_t a, Potassco::Atom_t b) { + LitVec body = get_clone(cond); + if (a) { body.emplace_back(NAF::POS, AtomType::Aux, a, 0); } + if (b) { body.emplace_back(NAF::NOT, AtomType::Aux, b, 0); } + Symtab(bound.var, i, std::move(body)).translate(data, *this); + }; + auto it = bound.begin(); + for (auto jt = bound.atoms.begin() + 1; jt != bound.atoms.end(); ++jt) { assign(*it++, jt->second, (jt-1)->second); } + assign(*it++, 0, bound.atoms.back().second); + } +} + +void Translator::translateMinimize(DomainData &data) { + sort_unique(minimize_, [&data](TupleLit const &a, TupleLit const &b) { + auto aa = data.tuple(a.first), ab = data.tuple(b.first); + if (aa[1] != ab[1]) { return aa[1] < ab[1]; } + return a < b; + }); + for (auto it = minimize_.begin(), iE = minimize_.end(); it != iE;) { + int priority = data.tuple(it->first)[1].num(); + Minimize lm(priority); + do { + LitVec condLits; + auto tuple = it->first; + do { + condLits.emplace_back(it++->second); + } + while (it != iE && it->first == tuple); + int weight(data.tuple(tuple).front().num()); + // Note: extends the minimize constraint incrementally + auto ret = tuples_.push(tuple, LiteralId{}); + if (!ret.second) { + lm.add(ret.first->second, -weight); + condLits.emplace_back(ret.first->second); + } + LiteralId lit = getEqualClause(data, *this, data.clause(std::move(condLits)), false, false); + ret.first->second = lit; + lm.add(lit, weight); + } + while (it != iE && data.tuple(it->first)[1].num() == priority); + out_->output(data, lm); + } + minimize_.clear(); +} + +void Translator::showTerm(DomainData &data, Symbol term, bool csp, LitVec &&cond) { + if (csp) { + cspOutput_.todo.push(term, Formula{}).first->cond.emplace_back(data.clause(std::move(cond))); + } + else { + termOutput_.todo.push(term, Formula{}).first->cond.emplace_back(data.clause(std::move(cond))); + } +} + +unsigned Translator::nodeUid(Symbol v) { + return nodeUids_.offset(nodeUids_.push(v).first); +} + +LiteralId Translator::removeNotNot(DomainData &data, LiteralId lit) { + if (lit.sign() == NAF::NOTNOT) { + LiteralId aux = data.newAux(); + Rule().addHead(aux).addBody(lit.negate()).translate(data, *this); + return aux.negate(); + } + return lit; +} + +constexpr Translator::ClauseKey Translator::ClauseKeyLiterals::open; +constexpr Translator::ClauseKey Translator::ClauseKeyLiterals::deleted; + +LiteralId Translator::clause(ClauseId id, bool conjunctive, bool equivalence) { + auto ret = clauses_.find( + [](ClauseKey const &a) { return a.hash(); }, + [](ClauseKey const &a, ClauseKey const &b) { return a == b; }, + ClauseKey{ id.first, id.second, conjunctive, equivalence, LiteralId().repr() }); + return ret ? LiteralId{ret->literal} : LiteralId{}; +} + +void Translator::clause(LiteralId lit, ClauseId id, bool conjunctive, bool equivalence) { + auto ret = clauses_.insert( + [](ClauseKey const &a) { return a.hash(); }, + [](ClauseKey const &a, ClauseKey const &b) { return a == b; }, + ClauseKey{ id.first, id.second, conjunctive, equivalence, lit.repr() }); + (void)ret; + assert(ret.second); +} + +Translator::~Translator() { } + +// }}}1 + +// {{{1 definition of Symtab + +Symtab::Symtab(Symbol symbol, LitVec &&body) +: symbol_(symbol) +, value_(0) +, csp_(false) +, body_(std::move(body)) { } + +Symtab::Symtab(Symbol symbol, int value, LitVec &&body) +: symbol_(symbol) +, value_(value) +, csp_(true) +, body_(std::move(body)) { } + +void Symtab::print(PrintPlain out, char const *prefix) const { + out << prefix << "#show " << symbol_; + if (csp_) { out << "=" << value_; } + if (!body_.empty()) { out << ":"; } + printPlainBody(out, body_); + out << ".\n"; +} + +void Symtab::translate(DomainData &data, Translator &x) { + for (auto &y : body_) { y = call(data, y, &Literal::translate, x); } + x.output(data, *this); +} + +void Symtab::output(DomainData &data, UBackend &out) const { + BackendLitVec &bd = data.tempLits(); + for (auto &x : body_) { bd.emplace_back(call(data, x, &Literal::uid)); } + std::ostringstream oss; + oss << symbol_; + if (csp_) { oss << "=" << value_; } + out->output(Potassco::toSpan(oss.str()), Potassco::toSpan(bd)); +} + +void Symtab::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, body_, delayed); +} + +Symtab::~Symtab() { } + +// {{{1 definition of Minimize + +Minimize::Minimize(int priority) +: priority_(priority) { } + +Minimize &Minimize::add(LiteralId lit, Potassco::Weight_t weight) { + lits_.emplace_back(lit, weight); + return *this; +} + +void Minimize::translate(DomainData &data, Translator &x) { + for (auto &y : lits_) { y.first = call(data, y.first, &Literal::translate, x); } + x.output(data, *this); +} + +void Minimize::print(PrintPlain out, char const *prefix) const { + int i = 0; + out << prefix << "#minimize{"; + auto f = [&i, this](PrintPlain &out, LitWeightVec::value_type const &x) { + out << x.second << "@" << priority_ << "," << i++ << ":"; + call(out.domain, x.first, &Literal::printPlain, out); + }; + print_comma(out, lits_, ";", f); + out << "}.\n"; +} + +void Minimize::output(DomainData &data, UBackend &x) const { + BackendLitWeightVec &body = data.tempWLits(); + for (auto &y : lits_) { + body.push_back({call(data, y.first, &Literal::uid), y.second}); + } + x->minimize(priority_, Potassco::toSpan(body)); +} + +void Minimize::replaceDelayed(DomainData &data, LitVec &delayed) { + for (auto &x : lits_) { Gringo::Output::replaceDelayed(data, x.first, delayed); } +} + +Minimize::~Minimize() { } + +// {{{1 definition of WeightRule + +WeightRule::WeightRule(LiteralId head, Potassco::Weight_t lower, LitUintVec &&body) +: head_(head) +, body_(std::move(body)) +, lower_(lower) { } + +void WeightRule::print(PrintPlain out, char const *prefix) const { + out << prefix; + call(out.domain, head_, &Literal::printPlain, out); + out << ":-" << lower_ << "{"; + if (!body_.empty()) { + auto it(body_.begin()), ie(body_.end()); + call(out.domain, it->first, &Literal::printPlain, out); + out << "=" << it->second; + for (++it; it != ie; ++it) { + out << ","; + call(out.domain, it->first, &Literal::printPlain, out); + out << "=" << it->second; + } + } + out << "}.\n"; +} + +void WeightRule::translate(DomainData &data, Translator &x) { + head_ = call(data, head_, &Literal::translate, x); + if (!call(data, head_, &Literal::isHeadAtom)) { + LiteralId aux = data.newAux(); + Rule().addHead(head_).addBody(aux).translate(data, x); + head_ = aux; + } + for (auto &y : body_) { y.first = call(data, y.first, &Literal::translate, x); } + x.output(data, *this); +} + +void WeightRule::output(DomainData &data, UBackend &out) const { + BackendLitWeightVec lits; + for (auto &x : body_) { lits.push_back({call(data, x.first, &Literal::uid), static_cast(x.second)}); } + BackendAtomVec heads({static_cast(call(data, head_, &Literal::uid))}); + outputRule(*out, false, heads, lower_, lits); +} + +void WeightRule::replaceDelayed(DomainData &data, LitVec &delayed) { + Gringo::Output::replaceDelayed(data, head_, delayed); + for (auto &x : body_) { Gringo::Output::replaceDelayed(data, x.first, delayed); } +} + +WeightRule::~WeightRule() { } + +// }}}1 + +} } // namespace Output Gringo diff --git a/libgringo/src/output/theory.cc b/libgringo/src/output/theory.cc new file mode 100644 index 0000000..41ed19a --- /dev/null +++ b/libgringo/src/output/theory.cc @@ -0,0 +1,756 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/output/theory.hh" +#include "gringo/output/literal.hh" +#include "gringo/logger.hh" +#include + +namespace Gringo { namespace Output { + +namespace { + +// {{{1 definition of comparison operators + +bool termEqual(Potassco::TheoryTerm const &term, int number) { + return term.type() == Potassco::Theory_t::Number && term.number() == number; +} + +bool termEqual(Potassco::TheoryTerm const &term, char const *symbol) { + return term.type() == Potassco::Theory_t::Symbol && strcmp(term.symbol(), symbol) == 0; +} + +bool termEqual(Potassco::TheoryTerm const &term, Potassco::Tuple_t type, Potassco::IdSpan const &terms) { + return term.type() == Potassco::Theory_t::Compound && term.isTuple() && term.tuple() == type && term.size() == terms.size && std::equal(term.begin(), term.end(), Potassco::begin(terms)); +} + +bool termEqual(Potassco::TheoryTerm const &term, Potassco::Id_t name, Potassco::IdSpan const &terms) { + return term.type() == Potassco::Theory_t::Compound && term.isFunction() && term.function() == name && term.size() == terms.size && std::equal(term.begin(), term.end(), Potassco::begin(terms)); +} + +bool elementEqual(Potassco::TheoryElement const &a, LitVec const &condA, Potassco::IdSpan const &tuple, LitVec const &condB) { + return is_value_equal_to(condA, condB) && a.size() == tuple.size && std::equal(a.begin(), a.end(), Potassco::begin(tuple)); +} + +bool atomEqual(Potassco::TheoryAtom const &a, Potassco::Id_t termId, Potassco::IdSpan const &elems) { + return !a.guard() && a.term() == termId && a.size() == elems.size && std::equal(a.begin(), a.end(), Potassco::begin(elems)); +} + +bool atomEqual(Potassco::TheoryAtom const &a, Potassco::Id_t termId, Potassco::IdSpan const &elems, Potassco::Id_t guard, Potassco::Id_t rhs) { + return a.guard() && *a.guard() == guard && *a.rhs() == rhs && a.term() == termId && a.size() == elems.size && std::equal(a.begin(), a.end(), Potassco::begin(elems)); +} + +bool atomEqual(Potassco::TheoryAtom const &a, Potassco::TheoryAtom const &b) { + return b.guard() + ? atomEqual(a, b.term(), b.elements(), *b.guard(), *b.rhs()) + : atomEqual(a, b.term(), b.elements()); +} + +// }}}1 +// {{{1 definition of hash functions + +size_t termHash(int number) { + return Gringo::get_value_hash(static_cast(Potassco::Theory_t::Number), number); +} + +size_t termHash(char const *symbol) { + return Gringo::get_value_hash(static_cast(Potassco::Theory_t::Symbol), strhash(symbol)); +} + +size_t termHash(Potassco::Id_t name, Potassco::IdSpan const &terms) { + size_t seed = Gringo::get_value_hash(static_cast(Potassco::Theory_t::Compound), name); + for (auto&& t : terms) { + Gringo::hash_combine(seed, t); + } + return seed; +} + +size_t termHash(Potassco::Tuple_t type, Potassco::IdSpan const &terms) { + size_t seed = Gringo::get_value_hash(static_cast(Potassco::Theory_t::Compound), static_cast(type)); + for (auto&& t : terms) { + Gringo::hash_combine(seed, t); + } + return seed; +} + +size_t termHash(Potassco::TheoryTerm const &term) { + switch (term.type()) { + case Potassco::Theory_t::Number: { return termHash(term.number()); } + case Potassco::Theory_t::Symbol: { return termHash(term.symbol()); } + case Potassco::Theory_t::Compound: { return term.isTuple() ? termHash(term.tuple(), term.terms()) : termHash(term.function(), term.terms()); } + } + assert(false); + return 0; +} + +size_t elementHash(Potassco::IdSpan const &tuple, LitVec const &cond) { + size_t seed = get_value_hash(cond); + for (auto&& t : tuple) { Gringo::hash_combine(seed, t); } + return seed; +} + +size_t elementHash(Potassco::TheoryElement const &elem, LitVec const &cond) { + return elementHash(elem.terms(), cond); +} + +size_t atomHash(Potassco::Id_t termId, Potassco::IdSpan const &elems) { + size_t seed = 0; + Gringo::hash_combine(seed, termId); + for (auto&& t : elems) { + Gringo::hash_combine(seed, t); + } + return seed; +} + +size_t atomHash(Potassco::Id_t termId, Potassco::IdSpan const &elems, Potassco::Id_t guard, Potassco::Id_t rhs) { + size_t seed = atomHash(termId, elems); + Gringo::hash_combine(seed, guard); + Gringo::hash_combine(seed, rhs); + return seed; +} + +size_t atomHash(Potassco::TheoryAtom const &atom) { + return atom.guard() + ? atomHash(atom.term(), atom.elements(), *atom.guard(), *atom.rhs()) + : atomHash(atom.term(), atom.elements()); +} + +// }}}1 + +} // namespace + +// {{{1 definition of TheoryParser + +TheoryParser::Elem::Elem(String op, bool unary) +: tokenType(Op) +, op(op, unary) { } + +TheoryParser::Elem::Elem(UTheoryTerm &&term) +: tokenType(Id) +, term(std::move(term)) {} + +TheoryParser::Elem::Elem(Elem &&elem) +: tokenType(elem.tokenType) { + if (elem.tokenType == Id) { + new (&term) UTheoryTerm(std::move(elem.term)); + } + else { + new (&op) std::pair(std::move(elem.op)); + } +} + +TheoryParser::Elem::~Elem() noexcept { + if (tokenType == Id) { + term.~UTheoryTerm(); + } + else { + op.~pair(); + } +} + +TheoryParser::TheoryParser(Location const &loc, TheoryTermDef const &def) +: loc_(loc) +, def_(def) { } + +bool TheoryParser::check(String op) { + if (stack_.size() < 2) { return false; } + assert(stack_.back().tokenType == Id); + auto current = def_.getPrioAndAssoc(op); + auto previous = def_.getPrio(stack_[stack_.size() - 2].op.first, stack_[stack_.size() - 2].op.second); + return previous > current.first || (previous == current.first && current.second); +} + +void TheoryParser::reduce() { + assert(stack_.back().tokenType == Id); + auto b = std::move(stack_.back().term); + stack_.pop_back(); + assert(stack_.back().tokenType == Op); + auto op = stack_.back().op; + stack_.pop_back(); + if (!op.second) { + assert(stack_.back().tokenType == Id); + auto a = std::move(stack_.back().term); + stack_.pop_back(); + stack_.emplace_back(gringo_make_unique(std::move(a), op.first, std::move(b))); + } + else { + stack_.emplace_back(gringo_make_unique(op.first, std::move(b))); + } +} + +UTheoryTerm TheoryParser::parse(RawTheoryTerm::ElemVec &&elems, Logger &log) { + stack_.clear(); + bool unary = true; + for (auto &elem : elems) { + for (auto &op : elem.first) { + if (!def_.hasOp(op, unary)) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc_ << ": error: missing definition for operator:" << "\n" + << " " << op << "\n"; + } + while (!unary && check(op)) { + reduce(); + } + stack_.emplace_back(op, unary); + unary = true; + } + stack_.emplace_back(std::move(elem.second)); + unary = false; + } + while (stack_.size() > 1) { + reduce(); + } + return std::move(stack_.front().term); +} + +TheoryParser::~TheoryParser() noexcept = default; + +// {{{1 definition of RawTheoryTerm + +RawTheoryTerm::RawTheoryTerm() { } + +RawTheoryTerm::RawTheoryTerm(ElemVec &&elems) +: elems_(std::move(elems)) { } + +RawTheoryTerm::RawTheoryTerm(RawTheoryTerm &&) = default; + +RawTheoryTerm &RawTheoryTerm::operator=(RawTheoryTerm &&) = default; + +RawTheoryTerm::~RawTheoryTerm() noexcept = default; + +void RawTheoryTerm::append(FWStringVec &&ops, UTheoryTerm &&term) { + assert(elems_.empty() || !ops.empty()); + elems_.emplace_back(std::move(ops), std::move(term)); +} + +size_t RawTheoryTerm::hash() const { + return get_value_hash(typeid(RawTheoryTerm).hash_code(), elems_); +} + +bool RawTheoryTerm::operator==(TheoryTerm const &other) const { + auto t = dynamic_cast(&other); + return t && is_value_equal_to(elems_, t->elems_); +} + +void RawTheoryTerm::print(std::ostream &out) const { + out << "("; + print_comma(out, elems_, ",", [](std::ostream &out, ElemVec::value_type const &elem) { + print_comma(out, elem.first, " "); + out << *elem.second; + }); + out << ")"; +} + +RawTheoryTerm *RawTheoryTerm::clone() const { + return gringo_make_unique(get_clone(elems_)).release(); +} + +Potassco::Id_t RawTheoryTerm::eval(TheoryData &, Logger &) const { + throw std::logic_error("RawTheoryTerm::eval must not be called!"); +} + +void RawTheoryTerm::collect(VarTermBoundVec &vars) { + for (auto &elem : elems_) { + elem.second->collect(vars); + } +} + +void RawTheoryTerm::replace(Defines &defs) { + for (auto &elem : elems_) { + elem.second->replace(defs); + } +} + +UTheoryTerm RawTheoryTerm::initTheory(TheoryParser &p, Logger &log) { + for (auto &elem : elems_) { + Term::replace(elem.second, elem.second->initTheory(p, log)); + } + return p.parse(std::move(elems_), log); +} + +// {{{1 definition of UnaryTheoryTerm + +UnaryTheoryTerm::UnaryTheoryTerm(String op, UTheoryTerm &&arg) +: arg_(std::move(arg)) +, op_(std::move(op)) +{ } + +UnaryTheoryTerm::~UnaryTheoryTerm() noexcept = default; + +size_t UnaryTheoryTerm::hash() const { + return get_value_hash(typeid(UnaryTheoryTerm).hash_code(), arg_, op_); +} + +bool UnaryTheoryTerm::operator==(TheoryTerm const &other) const { + auto t = dynamic_cast(&other); + return t && is_value_equal_to(arg_, t->arg_) && op_ == t->op_; +} + +void UnaryTheoryTerm::print(std::ostream &out) const { + out << "(" << op_ << *arg_ << ")"; +} + +UnaryTheoryTerm *UnaryTheoryTerm::clone() const { + return gringo_make_unique(op_, get_clone(arg_)).release(); +} + +Potassco::Id_t UnaryTheoryTerm::eval(TheoryData &data, Logger &log) const { + auto op = data.addTerm(op_.c_str()); + Potassco::Id_t args[] = { arg_->eval(data, log) }; + return data.addTerm(op, Potassco::toSpan(args, 1)); +} + +void UnaryTheoryTerm::collect(VarTermBoundVec &vars) { + arg_->collect(vars); +} + +void UnaryTheoryTerm::replace(Defines &defs) { + arg_->replace(defs); +} + +UTheoryTerm UnaryTheoryTerm::initTheory(TheoryParser &p, Logger &log) { + Term::replace(arg_, arg_->initTheory(p, log)); + return nullptr; +} + +// {{{1 definition of BinaryTheoryTerm + +BinaryTheoryTerm::BinaryTheoryTerm(UTheoryTerm &&left, String op, UTheoryTerm &&right) +: left_(std::move(left)) +, right_(std::move(right)) +, op_(op) +{ } + +BinaryTheoryTerm::~BinaryTheoryTerm() noexcept = default; + +size_t BinaryTheoryTerm::hash() const { + return get_value_hash(typeid(BinaryTheoryTerm).hash_code(), left_, right_, op_); +} + +bool BinaryTheoryTerm::operator==(TheoryTerm const &other) const { + auto t = dynamic_cast(&other); + return t && is_value_equal_to(left_, t->left_) && is_value_equal_to(right_, t->right_) && op_ == t->op_; +} + +void BinaryTheoryTerm::print(std::ostream &out) const { + out << "(" << *left_ << op_ << *right_ << ")"; +} + +BinaryTheoryTerm *BinaryTheoryTerm::clone() const { + return gringo_make_unique(get_clone(left_), op_, get_clone(right_)).release(); +} + +Potassco::Id_t BinaryTheoryTerm::eval(TheoryData &data, Logger &log) const { + auto op = data.addTerm(op_.c_str()); + Potassco::Id_t args[] = { left_->eval(data, log), right_->eval(data, log) }; + return data.addTerm(op, Potassco::toSpan(args, 2)); +} + +void BinaryTheoryTerm::collect(VarTermBoundVec &vars) { + left_->collect(vars); + right_->collect(vars); +} + +void BinaryTheoryTerm::replace(Defines &defs) { + left_->replace(defs); + right_->replace(defs); +} + +UTheoryTerm BinaryTheoryTerm::initTheory(TheoryParser &p, Logger &log) { + Term::replace(left_, left_->initTheory(p, log)); + Term::replace(right_, right_->initTheory(p, log)); + return nullptr; +} + +// {{{1 definition of TupleTheoryTerm + +TupleTheoryTerm::TupleTheoryTerm(Type type, UTheoryTermVec &&args) +: args_(std::move(args)) +, type_(type) +{ } + +TupleTheoryTerm::~TupleTheoryTerm() noexcept = default; + +size_t TupleTheoryTerm::hash() const { + return get_value_hash(typeid(TupleTheoryTerm).hash_code(), static_cast(type_), args_); +} + +bool TupleTheoryTerm::operator==(TheoryTerm const &other) const { + auto t = dynamic_cast(&other); + return t && is_value_equal_to(args_, t->args_) && type_ == t->type_; +} + +void TupleTheoryTerm::print(std::ostream &out) const { + auto parens = Potassco::toString(type_); + out << parens[0]; + print_comma(out, args_, ",", [](std::ostream &out, UTheoryTerm const &term) { out << *term; }); + if (args_.size() == 1 && type_ == Potassco::Tuple_t::Paren) { out << ","; } + out << parens[1]; +} + +TupleTheoryTerm *TupleTheoryTerm::clone() const { + return gringo_make_unique(type_, get_clone(args_)).release(); +} + +Potassco::Id_t TupleTheoryTerm::eval(TheoryData &data, Logger &log) const { + std::vector args; + for (auto &arg : args_) { + args.emplace_back(arg->eval(data, log)); + } + return data.addTerm(type_, Potassco::toSpan(args)); +} + +void TupleTheoryTerm::collect(VarTermBoundVec &vars) { + for (auto &term : args_) { + term->collect(vars); + } +} + +void TupleTheoryTerm::replace(Defines &defs) { + for (auto &term : args_) { + term->replace(defs); + } +} + +UTheoryTerm TupleTheoryTerm::initTheory(TheoryParser &p, Logger &log) { + for (auto &term : args_) { + Term::replace(term, term->initTheory(p, log)); + } + return nullptr; +} + +// {{{1 definition of FunctionTheoryTerm + +FunctionTheoryTerm::FunctionTheoryTerm(String name, UTheoryTermVec &&args) +: args_(std::move(args)) +, name_(name) +{ } + +FunctionTheoryTerm::~FunctionTheoryTerm() noexcept = default; + +size_t FunctionTheoryTerm::hash() const { + return get_value_hash(typeid(FunctionTheoryTerm).hash_code(), name_, args_); +} + +bool FunctionTheoryTerm::operator==(TheoryTerm const &other) const { + auto t = dynamic_cast(&other); + return t && is_value_equal_to(args_, t->args_) && name_ == t->name_; +} + +void FunctionTheoryTerm::print(std::ostream &out) const { + out << name_ << "("; + print_comma(out, args_, ",", [](std::ostream &out, UTheoryTerm const &term) { out << *term; }); + out << ")"; +} + +FunctionTheoryTerm *FunctionTheoryTerm::clone() const { + return gringo_make_unique(name_, get_clone(args_)).release(); +} + +Potassco::Id_t FunctionTheoryTerm::eval(TheoryData &data, Logger &log) const { + auto name = data.addTerm(name_.c_str()); + std::vector args; + for (auto &arg : args_) { + args.emplace_back(arg->eval(data, log)); + } + return data.addTerm(name, Potassco::toSpan(args)); +} + +void FunctionTheoryTerm::collect(VarTermBoundVec &vars) { + for (auto &term : args_) { + term->collect(vars); + } +} + +void FunctionTheoryTerm::replace(Defines &defs) { + for (auto &term : args_) { + term->replace(defs); + } +} + +UTheoryTerm FunctionTheoryTerm::initTheory(TheoryParser &p, Logger &log) { + for (auto &term : args_) { + Term::replace(term, term->initTheory(p, log)); + } + return nullptr; +} + +// {{{1 definition of TermTheoryTerm + +TermTheoryTerm::TermTheoryTerm(UTerm &&term) +: term_(std::move(term)) { + assert(dynamic_cast(term_.get()) || dynamic_cast(term_.get())); +} + +TermTheoryTerm::~TermTheoryTerm() noexcept = default; + +size_t TermTheoryTerm::hash() const { + return get_value_hash(typeid(TermTheoryTerm).hash_code(), term_); +} + +bool TermTheoryTerm::operator==(TheoryTerm const &other) const { + auto t = dynamic_cast(&other); + return t && is_value_equal_to(term_, t->term_); +} + +void TermTheoryTerm::print(std::ostream &out) const { + out << "(" << *term_ << ")"; +} + +TermTheoryTerm *TermTheoryTerm::clone() const { + return gringo_make_unique(get_clone(term_)).release(); +} + +Potassco::Id_t TermTheoryTerm::eval(TheoryData &data, Logger &log) const { + bool undefined = false; + return data.addTerm(term_->eval(undefined, log)); +} + +void TermTheoryTerm::collect(VarTermBoundVec &vars) { + term_->collect(vars, false); +} + +void TermTheoryTerm::replace(Defines &defs) { + Term::replace(term_, term_->replace(defs, true)); +} + +UTheoryTerm TermTheoryTerm::initTheory(TheoryParser &, Logger &) { + return nullptr; +} + +// {{{1 definition of TheoryData + +TheoryData::TheoryData(Potassco::TheoryData &data) +: data_(data) +{ } + +TheoryData::~TheoryData() noexcept = default; + +template +Potassco::Id_t TheoryData::addTerm_(Args ...args) { + auto size = terms_.size(); + auto ret = terms_.insert([&](Potassco::Id_t const &a) { + assert(a != std::numeric_limits::max()); + return a == size ? termHash(args...) : termHash(data_.getTerm(a)); + }, [&](Potassco::Id_t const &a, Potassco::Id_t const &b) { + assert(a < size); + return b == size ? termEqual(data_.getTerm(a), args...) : a == b; + }, size); + if (ret.second) { data_.addTerm(size, args...); } + return ret.first; +} + +Potassco::Id_t TheoryData::addTerm(int number) { + return addTerm_(number); +} + +Potassco::Id_t TheoryData::addTerm(char const *name) { + return addTerm_(name); +} + +Potassco::Id_t TheoryData::addTerm(Potassco::Id_t funcSym, Potassco::IdSpan const& terms) { + return addTerm_(funcSym, terms); +} + +Potassco::Id_t TheoryData::addTerm(Potassco::Tuple_t type, Potassco::IdSpan const& terms) { + return addTerm_(type, terms); +} + +Potassco::Id_t TheoryData::addTerm(Symbol value) { + switch (value.type()) { + case SymbolType::Num: { + auto num = value.num(); + if (num < 0) { + auto f = addTerm("-"); + auto ret = addTerm(-num); + Potassco::Id_t args[] = { ret }; + return addTerm(f, Potassco::toSpan(args, 1)); + } + else { + return addTerm(num); + } + } + case SymbolType::Str: { + std::string s; + s.push_back('"'); + s.append(quote(value.string().c_str())); + s.push_back('"'); + return addTerm(s.c_str()); + } + case SymbolType::Sup: { + return addTerm("#sup"); + } + case SymbolType::Inf: { + return addTerm("#inf"); + } + case SymbolType::Fun: { + std::vector args; + for (auto &arg : value.args()) { + args.emplace_back(addTerm(arg)); + } + if (value.name().empty()) { + return addTerm(Potassco::Tuple_t::Paren, Potassco::toSpan(args)); + } + else { + Potassco::Id_t name = addTerm(value.name().c_str()); + auto ret = args.empty() + ? addTerm(value.name().c_str()) + : addTerm(name, Potassco::toSpan(args)); + if (value.sign()) { + Potassco::Id_t f = addTerm("-"); + ret = addTerm(f, Potassco::toSpan(&ret, 1)); + } + return ret; + } + } + case SymbolType::Special: { + assert(false); + break; + } + } + assert(false); + return 0; +} + +Potassco::Id_t TheoryData::addElem(Potassco::IdSpan const &tuple, LitVec &&cond) { + assert(conditions_.size() == elems_.size()); + auto size = elems_.size(); + auto ret = elems_.insert([&](Potassco::Id_t const &a) { + assert(a != std::numeric_limits::max()); + return a == size ? elementHash(tuple, cond) : elementHash(data_.getElement(a), conditions_[a]); + }, [&](Potassco::Id_t const &a, Potassco::Id_t const &b) { + assert(a < size); + return b == size ? elementEqual(data_.getElement(a), conditions_[a], tuple, cond) : a == b; + }, conditions_.size()); + if (ret.second) { + data_.addElement(size, tuple, cond.empty() ? 0 : Potassco::TheoryData::COND_DEFERRED); + conditions_.emplace_back(std::move(cond)); + } + return ret.first; +} + +template +std::pair TheoryData::addAtom_(std::function newAtom, Args ...args) { + auto **ret = reinterpret_cast(atoms_.find([&]() { + return atomHash(args...); + }, [&](uintptr_t a) { + return atomEqual(*reinterpret_cast(a), args...); + })); + if (!ret) { + auto &atom = data_.addAtom(newAtom(), args...); + atoms_.insert([&](uintptr_t a) { + return atomHash(*reinterpret_cast(a)); + }, [&](uintptr_t a, uintptr_t b) { + return atomEqual(*reinterpret_cast(a), *reinterpret_cast(b)); + }, reinterpret_cast(&atom)); + return {atom, true}; + } + return {**ret, false}; +} + +std::pair TheoryData::addAtom(std::function newAtom, Potassco::Id_t termId, Potassco::IdSpan const &elems) { + return addAtom_(newAtom, termId, elems); +} + +std::pair TheoryData::addAtom(std::function newAtom, Potassco::Id_t termId, Potassco::IdSpan const &elems, Potassco::Id_t op, Potassco::Id_t rhs) { + return addAtom_(newAtom, termId, elems, op, rhs); +} + +void TheoryData::printTerm(std::ostream &out, Potassco::Id_t termId) const { + auto &term = data_.getTerm(termId); + switch (term.type()) { + case Potassco::Theory_t::Number: { + if (term.number() < 0) { out << "("; } + out << term.number(); + if (term.number() < 0) { out << ")"; } + break; + } + case Potassco::Theory_t::Symbol: { out << term.symbol(); break; } + case Potassco::Theory_t::Compound: { + auto parens = Potassco::toString(term.isTuple() ? term.tuple() : Potassco::Tuple_t::Paren); + bool isOp = false; + if (term.isFunction()) { + auto &name = data_.getTerm(term.function()); + char buf[2] = { *name.symbol(), 0 }; + isOp = term.size() <= 2 && std::strpbrk(buf, "/!<=>+-*\\?&@|:;~^."); + if (!isOp) { printTerm(out, term.function()); } + } + out << parens[0]; + if (isOp && term.size() <= 1) { + printTerm(out, term.function()); + } + print_comma(out, term, isOp ? data_.getTerm(term.function()).symbol() : ",", [this](std::ostream &out, Potassco::Id_t termId){ printTerm(out, termId); }); + if (term.isTuple() && term.tuple() == Potassco::Tuple_t::Paren && term.size() == 1) { out << ","; } + out << parens[1]; + break; + } + } +} + +void TheoryData::printElem(std::ostream &out, Potassco::Id_t elemId, PrintLit printLit) const { + auto &elem = data_.getElement(elemId); + auto &cond = getCondition(elemId); + print_comma(out, elem, ",", [this](std::ostream &out, Potassco::Id_t termId){ printTerm(out, termId); }); + if (elem.size() == 0 && cond.empty()) { + out << ": "; + } + else if (!cond.empty()) { + out << ": "; + print_comma(out, cond, ",", [this, &printLit](std::ostream &out, LiteralId const &lit){ printLit(out, lit); }); + } +} + +bool TheoryData::empty() const { + return data_.numAtoms() == 0; +} + +Potassco::TheoryData const &TheoryData::data() const { + return data_; +} + +LitVec &TheoryData::getCondition(Potassco::Id_t elemId) { + assert(elemId < conditions_.size()); + return conditions_[elemId]; +} + +LitVec const &TheoryData::getCondition(Potassco::Id_t elemId) const { + assert(elemId < conditions_.size()); + return conditions_[elemId]; +} + +void TheoryData::setCondition(Potassco::Id_t elementId, Potassco::Id_t newCond) { + data_.setCondition(elementId, newCond); +} + +void TheoryData::reset() { + TIdSet().swap(terms_); + TIdSet().swap(elems_); + AtomSet().swap(atoms_); + ConditionVec().swap(conditions_); +} + +bool TheoryData::hasConditions() const { + return !conditions_.empty(); +} + + +// }}}1 + +} } // namspace Gringo diff --git a/libgringo/src/primes.cc b/libgringo/src/primes.cc new file mode 100644 index 0000000..1ddae5c --- /dev/null +++ b/libgringo/src/primes.cc @@ -0,0 +1,192 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/primes.hh" +#include +#include +#include +#include + +namespace Gringo { + +// Note: all of this is really unnecessary. +// Probe devision is completly sufficient for realistic container sizes. :) +namespace { + +uint32_t mulmod(uint32_t a, uint32_t b, uint32_t m) { + return (static_cast(a) * b) % m; +} + +#ifdef GRINGO_NEXTPRIME64 +# if defined(__SIZEOF_INT128__) +inline uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) { + return (static_cast<__uint128_t>(a) * b) % m; +} +# else +// https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication#Russian_peasant_multiplication +uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) { + uint64_t res = 0; + if (b < a) { std::swap(a, b); } + if (b >= m) { b = (m > std::numeric_limits::max() >> 1) ? b - m : b % m; } + while (a != 0) { + if (a & 1) { + if (b >= m - res) { res -= m; } + res += b; + } + a >>= 1; + uint64_t t = b; + if (b >= m - b) { t -= m; } + b += t; + } + return res; +} +# endif +#endif + +// https://en.wikipedia.org/wiki/Modular_exponentiation +template +T modpow(T b, T e, T m) { + if (m == 1) { return 0; } + T r = 1; + if (b >= m) { b = b % m; } + while (e > 0) { + if ((e & 1) == 1) { r = mulmod(r, b, m); } + e = e >> 1; + b = mulmod(b, b, m); + } + return r; +} + +// https://stackoverflow.com/questions/4475996/given-prime-number-n-compute-the-next-prime +template +bool isPrimeProbe(T x) { // Note: this one makes assumptions about the numbers generated by next prime + for (T i : { 0x7, 0xb, 0xd, 0x11, 0x13, 0x17, 0x1d }) { + T q = x / i; + if (q < i) { return true; } + if (x == q * i) { return false; } + } + for (T i = 31;;) { + for (T a : {0x6, 0x4, 0x2, 0x4, 0x2, 0x4, 0x6, 0x2}) { + T q = x / i; + if (q < i) { return true; } + if (x == q * i) { return false; } + i+= a; + } + } + return true; +} + +// https://miller-rabin.appspot.com/ +static std::initializer_list a32s1 = { 0x36e8934f }; +static std::initializer_list a32s2 = { 0x11724a, 0x8c16d95c }; +static std::initializer_list a32s3 = { 0x2, 0x7, 0x3d }; +std::initializer_list test(uint32_t n) { + if (n < 0xbff5) { return a32s1; } + if (n < 0x157571b9) { return a32s2; } + return a32s3; +} +#ifdef GRINGO_NEXTPRIME64 +static std::initializer_list a64s1 = { 0x81b33f22efdceaa9 }; +static std::initializer_list a64s2 = { 0x4e69b6552d, 0x223f5bb83fc553 }; +static std::initializer_list a64s3 = { 0x2, 0x7, 0x3d }; +static std::initializer_list a64s4 = { 0x3ab4f88ff0cc7c80, 0xcbee4cdf120c10aa, 0xe6f1343b0edca8e7 }; +static std::initializer_list a64s5 = { 0x2, 0x810c207b08bf, 0x10a42595b01d3765, 0x99fd2b545eab5322 }; +static std::initializer_list a64s6 = { 0x2, 0x3c1c7396f6d, 0x2142e2e3f22de5c, 0x297105b6b7b29dd, 0x370eb221a5f176dd }; +static std::initializer_list a64s7 = { 0x2, 0x70722e8f5cd0, 0x20cd6bd5ace2d1, 0x9bbc940c751630, 0xa90404784bfcb4d, 0x1189b3f265c2b0c7 }; +static std::initializer_list a64s8 = { 0x2, 0x3, 0x5, 0x7, 0xb, 0xd, 0x11, 0x13, 0x17, 0x1d, 0x1f, 0x25 }; +std::initializer_list test(uint64_t n) { + if (n < 0x5361b) { return a64s1; } + if (n < 0x3e9de64d) { return a64s2; } + if (n < 0x11baa74c5) { return a64s3; } + if (n < 0x518dafbfd1) { return a64s4; } + if (n < 0x50649b08971) { return a64s5; } + if (n < 0x1c6b470864f683) { return a64s6; } + if (n < 0x81f23f390affe89) { return a64s7; } + return a64s8; +} +#endif + +// https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Deterministic_variants_of_the_test +template +bool isPrime(T n) { + T r = 0; + T d = n - 1; + for (; (d & 1) == 0; d >>= 1, ++r) { } + for (T a : test(n)) { + assert(n != 0); + a = a % n; + if (a != 0) { + T x = modpow(a, d, n); + if (x != 1) { + for (T i = 1, s = d; i < r && x != n-1; ++i) { + s <<= 1; + x = modpow(a, s, n); + } + if (x != n-1) { return false; } + } + } + } + //assert(isPrimeProbe(n)); + return true; +} + +// https://stackoverflow.com/questions/4475996/given-prime-number-n-compute-the-next-prime +template +T nextPrime(T n) { + T l = 30; + std::initializer_list smallPrimes = { 0x2, 0x3, 0x5, 0x7, 0xb, 0xd, 0x11, 0x13, 0x17, 0x1d }; + std::initializer_list indices = { 0x1, 0x7, 0xb, 0xd, 0x11, 0x13, 0x17, 0x1d }; + if (n <= *(smallPrimes.end() - 1)) { + return *std::lower_bound(smallPrimes.begin(), smallPrimes.end(), n); + } + T k = n / l; + T i = static_cast(std::lower_bound(indices.begin(), indices.end(), n - k * l) - indices.begin()); + n = l * k + *(indices.begin() + i); + while (!isPrime(n)) { + if (++i == indices.size()) { + ++k; + i = 0; + } + n = l * k + *(indices.begin() + i); + } + return n; +} + +} // namespace + +// should this be used??? +//if ((x + 1) % 4 != 0) { return false; } + +uint32_t nextPrime(uint32_t n) { + if (n > 0xfffffffb) { throw std::overflow_error("maximum prime number exceeded"); } + return nextPrime(n); +} + +#ifdef GRINGO_NEXTPRIME64 +uint64_t nextPrime(uint64_t n) { + if (n > 0xffffffffffffffc5) { throw std::overflow_error("maximum prime number exceeded"); } + return nextPrime(n); +} +#else +uint64_t nextPrime(uint64_t) { throw std::runtime_error("support for 64bit primes not enabled"); } +#endif + +} // namspace Gringo + diff --git a/libgringo/src/python.cc b/libgringo/src/python.cc new file mode 100644 index 0000000..b565f17 --- /dev/null +++ b/libgringo/src/python.cc @@ -0,0 +1,6424 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifdef WITH_PYTHON + +#include + +#include "gringo/python.hh" +#include "gringo/version.hh" +#include "gringo/symbol.hh" +#include "gringo/locatable.hh" +#include "gringo/logger.hh" +#include "gringo/control.hh" +#include +#include + +#if PY_MAJOR_VERSION >= 3 +#define PyString_FromString PyUnicode_FromString +#if PY_MINOR_VERSION >= 3 +#define PyString_AsString PyUnicode_AsUTF8 +#else +#define PyString_AsString _PyUnicode_AsString +#endif +#define PyString_FromStringAndSize PyUnicode_FromStringAndSize +#define PyString_FromFormat PyUnicode_FromFormat +#define PyInt_FromLong PyLong_FromLong +#define PyInt_AsLong PyLong_AsLong +#define PyInt_Check PyLong_Check +#define PyString_Check PyUnicode_Check +#define OBBASE(x) (&(x)->ob_base) +#else +#define OBBASE(x) x +#endif + +#ifndef PyVarObject_HEAD_INIT + #define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, +#endif + +#ifdef COUNT_ALLOCS +// tp_allocs, tp_frees, tp_maxalloc, tp_prev, tp_next, +#define GRINGO_STRUCT_EXTRA 0, 0, 0, nullptr, nullptr, +#else +#define GRINGO_STRUCT_EXTRA +#endif + +#define PY_TRY try { +#define PY_CATCH(ret) \ +} \ +catch (std::bad_alloc const &e) { PyErr_SetString(PyExc_MemoryError, e.what()); } \ +catch (PyException const &) { } \ +catch (std::exception const &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); } \ +catch (...) { PyErr_SetString(PyExc_RuntimeError, "unknown error"); } \ +return (ret) + +namespace Gringo { + +using Id_t = uint32_t; + +namespace { + +// {{{1 workaround for gcc warnings + +#if defined(__GNUC__) && !defined(__clang__) +void incRef(PyObject *op) { + Py_INCREF(op); +} + +template +void incRef(T *object) { + incRef(reinterpret_cast(object)); +} + +#undef Py_INCREF +#define Py_INCREF(op) incRef(op) +#endif + +// }}}1 + +// {{{1 auxiliary functions and objects + +struct PyException : std::exception { }; + +struct Iter; +struct Object; +struct Reference; + +template +struct ObjectProtocoll { + // {{{2 object protocol + template + Object call(char const *name, Args &&... args); + template + Object operator()(Args &&... args); + ssize_t size(); + bool empty() { return size() == 0; } + Object getItem(Reference o); + Object getItem(char const *key); + Object getItem(int key); + void setItem(char const *key, Reference val); + void setItem(Reference key, Reference val); + Object getAttr(char const *key); + void setAttr(char const *key, Reference val); + void setAttr(Reference key, Reference val); + bool hasAttr(char const *key); + bool hasAttr(Reference key); + Object repr(); + Object str(); + bool isTrue(); + bool isInstance(Reference type); + bool isInstance(PyTypeObject &type); + Object richCompare(Reference other, int op); + Iter iter(); + friend bool operator==(Reference a, Reference b); + //friend bool operator!=(Reference a, Reference b) { + // auto ret = PyObject_RichCompareBool(a, b, Py_NE); + // if (ret < 0) { throw PyException(); } + // return ret; + //} + + // }}}2 + bool none() const; + bool valid() const; + +private: + PyObject *toPy_() const; +}; + +struct Reference : ObjectProtocoll { + Reference() : obj(nullptr) { } + template + Reference(T const &x) : obj{x.toPy()} { } + Reference(std::nullptr_t) : Reference{} { } + Reference(PyObject *obj) : obj(obj) { + if (!obj && PyErr_Occurred()) { throw PyException(); } + } + PyObject *release() { + Py_XINCREF(obj); + PyObject *ret = obj; + obj = nullptr; + return ret; + } + PyObject *toPy() const { return obj; } + PyObject *obj; +}; + +struct Object : ObjectProtocoll{ + Object() : obj(nullptr) { } + Object(std::nullptr_t) : Object() { } + template + Object(T const &x) : obj{x.toPy()} { Py_XINCREF(obj); } + Object(PyObject *obj) : obj(obj) { + if (!obj && PyErr_Occurred()) { throw PyException(); } + } + Object(Object const &other) : obj(other.toPy()) { + Py_XINCREF(obj); + } + Object(Object &&other) : obj(nullptr) { + std::swap(other.obj, obj); + } + PyObject *toPy() const { return obj; } + PyObject *release() { PyObject *ret = obj; obj = nullptr; return ret; } + Object &operator=(Object const &other) { Py_XDECREF(obj); obj = other.obj; Py_XINCREF(obj); return *this; } + Object &operator=(Object &&other) { std::swap(obj, other.obj); return *this; } + ~Object() { Py_XDECREF(obj); } + PyObject *obj; +}; + +struct Iter : Object { + Iter(Object iter) + : Object(iter) { } + Object next() { + return {PyIter_Next(toPy())}; + } +}; + +Object None() { Py_RETURN_NONE; } + +template +PyObject *ObjectProtocoll::toPy_() const { return static_cast(this)->toPy(); } + +template +template +Object ObjectProtocoll::call(char const *name, Args &&... args) { + return PyObject_CallMethodObjArgs(toPy_(), Object{PyString_FromString(name)}.toPy(), Reference(args).toPy()..., nullptr); +} +template +template +Object ObjectProtocoll::operator()(Args &&... args) { + return PyObject_CallFunctionObjArgs(toPy_(), Reference(args).toPy()..., nullptr); +} +template +ssize_t ObjectProtocoll::size() { + auto ret = PyObject_Size(toPy_()); + if (PyErr_Occurred()) { throw PyException(); } + return ret; +} +template +Object ObjectProtocoll::getItem(Reference o) { + return PyObject_GetItem(toPy_(), o.toPy()); +} +template +Object ObjectProtocoll::getItem(char const *key) { + return getItem(Object{PyString_FromString(key)}); +} +template +Object ObjectProtocoll::getItem(int key) { + return getItem(Object{PyInt_FromLong(key)}); +} +template +void ObjectProtocoll::setItem(char const *key, Reference val) { + return setItem(Object{PyString_FromString(key)}, val); +} +template +void ObjectProtocoll::setItem(Reference key, Reference val) { + if (PyObject_SetItem(toPy_(), key.toPy(), val.toPy()) < 0) { + throw PyException(); + } +} +template +Object ObjectProtocoll::getAttr(char const *key) { + return PyObject_GetAttrString(toPy_(), key); +} +template +void ObjectProtocoll::setAttr(char const *key, Reference val) { + if (PyObject_SetAttrString(toPy_(), key, val.toPy()) < 0) { + throw PyException(); + } +} +template +void ObjectProtocoll::setAttr(Reference key, Reference val) { + if (PyObject_SetAttr(toPy_(), key, val.toPy()) < 0) { + throw PyException(); + } +} +template +bool ObjectProtocoll::hasAttr(char const *key) { + int ret = PyObject_HasAttrString(toPy_(), key); + if (ret < 0) { throw PyException(); } + return ret; +} +template +bool ObjectProtocoll::hasAttr(Reference key) { + int ret = PyObject_HasAttr(toPy_(), key); + if (ret < 0) { throw PyException(); } + return ret; +} +template +Object ObjectProtocoll::repr() { return PyObject_Repr(toPy_()); } +template +Object ObjectProtocoll::str() { return PyObject_Str(toPy_()); } +template +bool ObjectProtocoll::isTrue() { + auto ret = PyObject_IsTrue(toPy_()); + if (PyErr_Occurred()) { throw PyException(); } + return ret; +} +template +bool ObjectProtocoll::isInstance(Reference type) { + auto inst = PyObject_IsInstance(toPy_(), type); + if (PyErr_Occurred()) { throw PyException(); } + return inst; +} +template +bool ObjectProtocoll::isInstance(PyTypeObject &type) { + auto inst = PyObject_IsInstance(toPy_(), reinterpret_cast(&type)); + if (PyErr_Occurred()) { throw PyException(); } + return inst; +} +template +Iter ObjectProtocoll::iter() { + return {PyObject_GetIter(toPy_())}; +} +template +Object ObjectProtocoll::richCompare(Reference other, int op) { + return PyObject_RichCompare(toPy_(), other.toPy(), op); +} +bool operator==(Reference a, Reference b) { + auto ret = PyObject_RichCompareBool(a.toPy(), b.toPy(), Py_EQ); + if (ret < 0) { throw PyException(); } + return ret; +} +bool operator!=(Object a, Object b) { + auto ret = PyObject_RichCompareBool(a.toPy(), b.toPy(), Py_NE); + if (ret < 0) { throw PyException(); } + return ret; +} + +// }}}2 +template +bool ObjectProtocoll::none() const { return toPy_() == Py_None; } +template +bool ObjectProtocoll::valid() const { return toPy_(); } + +template +struct ParsePtr { + ParsePtr(T &x) : x(x) { } + T *get() { return &x; } + T &x; +}; + +template <> +struct ParsePtr { + ParsePtr(Object &x) : x(x) { x = nullptr; } + PyObject **get() { return &x.obj; } + ~ParsePtr() { Py_XINCREF(x.obj); } + Object &x; +}; + +template <> +struct ParsePtr { + ParsePtr(Reference &x) : x(x) { } + PyObject **get() { return &x.obj; } + Reference &x; +}; + +template +void ParseTupleAndKeywords(Reference pyargs, Reference pykwds, char const *fmt, char const * const* kwds, T &...x) { + PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), fmt, const_cast(kwds), ParsePtr(x).get()...); +} + +template +struct ToFunction { + static PyObject *value(PyObject *, PyObject *params, PyObject *keywords) { + PY_TRY { return f(params, keywords).release(); } + PY_CATCH(nullptr); + }; +}; + +template +constexpr PyCFunction to_function() { return reinterpret_cast(ToFunction::value); } + +struct Tuple : Object { + template + Tuple(Args &&... args) + : Object{PyTuple_Pack(sizeof...(args), args.toPy()...)} { } +}; + +struct List : Object { + List(std::nullptr_t) + : Object{} { } + List(Object x) + : Object(x) { } + List(size_t size = 0) + : Object{PyList_New(size)} { } + void setItem(size_t i, Object x) { + if (PyList_SetItem(toPy(), i, x.release()) < 0) { throw PyException(); } + } + void append(Reference x) { + if (PyList_Append(toPy(), x.toPy()) < 0) { throw PyException(); } + } + void sort() { + if (PyList_Sort(toPy()) < 0) { throw PyException(); } + } +}; + +struct Dict : Object { + Dict() : Object{PyDict_New()} {} + Dict(Object dict) : Object{dict} {} + List keys() { return {PyDict_Keys(obj)}; } + List values() { return {PyDict_Values(obj)}; } + List items() { return {PyDict_Items(obj)}; } + void delItem(Reference name) { + if (PyDict_DelItem(obj, name.toPy()) < 0) { throw PyException(); } + } + Py_ssize_t length() { + auto ret = PyDict_Size(obj); + if (ret == -1) { throw PyException(); } + return ret; + } + bool contains(Reference key) { + auto ret = PyDict_Contains(obj, key.toPy()); + if (ret == -1) { throw PyException(); } + return ret; + } +}; + +template +Object call(Object (&f)(Reference, Reference), Args&&... args) { + return f(Tuple{std::forward(args)...}, Dict{}); +} + +template +class ValuePointer { +public: + ValuePointer(T value) : value_(value) { } + T &operator*() { return value_; } + T *operator->() { return &value_; } +private: + T value_; +}; + +class IterIterator : std::iterator, Object> { +public: + IterIterator() = default; + IterIterator(IterIterator const &) = default; + IterIterator(Iter it, Object current) + : it_(it) + , current_(current) { } + IterIterator& operator++() { current_ = it_.next(); return *this; } + IterIterator operator++(int) { + IterIterator t(*this); + ++*this; + return t; + } + reference operator*() { return current_; } + pointer operator->() { return pointer(**this); } + + friend bool operator==(IterIterator a, IterIterator b) { return a.current_.toPy() == b.current_.toPy(); } + friend bool operator!=(IterIterator a, IterIterator b) { return !(a == b); } + //friend void swap(IterIterator a, IterIterator b) { + // std::swap(a.it_, b.it_); + // std::swap(a.current_, b.current_); + //} +private: + Iter it_; + Object current_; +}; + +IterIterator begin(Iter it) { return {it, it.next()}; } +IterIterator end(Iter it) { return {it, nullptr}; } + +// NOTE: all the functions below can use execptions +// to remove all the annoying return value checking +// like in the callback there should be an exception +// that indicates that a python exception is on the stack +// this exception should simply be handled in PY_CATCH + +template +void pyToCpp(Reference pyVec, std::vector &vec); + +void pyToCpp(Reference pyBool, bool &x) { + x = pyBool.isTrue(); +} + +void pyToCpp(Reference pyStr, char const *&x) { + x = PyString_AsString(pyStr.toPy()); + if (!x) { throw PyException(); } +} + +template +void pyToCpp(Reference pyNum, T &x, typename std::enable_if::value>::type* = nullptr) { + x = PyInt_AsLong(pyNum.toPy()); + if (PyErr_Occurred()) { throw PyException(); } +} + +template +void pyToCpp(Reference pyNum, T &x, typename std::enable_if::value>::type* = nullptr) { + x = PyFloat_AsDouble(pyNum.toPy()); + if (PyErr_Occurred()) { throw PyException(); } +} + +void pyToCpp(Reference obj, Symbol &val); + +template +void pyToCpp(Reference pyPair, std::pair &x) { + auto it = pyPair.iter(); + Object pyVal = it.next(); + if (!pyVal.valid()) { throw std::runtime_error("pair expected"); } + pyToCpp(pyVal, x.first); + pyVal = it.next(); + if (!pyVal.valid()) { throw std::runtime_error("pair expected"); } + pyToCpp(pyVal, x.second); + pyVal = it.next(); + if (pyVal.valid()) { throw std::runtime_error("pair expected"); } +} + +void pyToCpp(Reference pyPair, Potassco::WeightLit_t &x) { + std::pair y{ x.lit, x.weight }; + pyToCpp(pyPair, y); +} + +template +void pyToCpp(Reference pyVec, std::vector &vec) { + for (auto x : pyVec.iter()) { + T ret; + pyToCpp(x, ret); + vec.emplace_back(std::move(ret)); + } +} + +template +T pyToCpp(Reference py) { + T ret; + pyToCpp(py, ret); + return ret; +} + +std::ostream &operator<<(std::ostream &out, Reference o) { + return out << pyToCpp(o.str()); +} + +struct PrintWrapper { + Object list; + char const *pre; + char const *sep; + char const *post; + bool empty; + friend std::ostream &operator<<(std::ostream &out, PrintWrapper x) { + auto it = x.list.iter(); + Object o = it.next(); + if (o.valid()) { + out << x.pre; + out << o; + while ((o = it.next()).valid()) { out << x.sep << o; } + out << x.post; + } + else if (x.empty) { + out << x.pre; + out << x.post; + } + return out; + } +}; + +PrintWrapper printList(Reference list, char const *pre, char const *sep, char const *post, bool empty) { + return {list, pre, sep, post, empty}; +} +PrintWrapper printBody(Reference list, char const *pre = " : ") { + return printList(list, list.empty() ? "" : pre, "; ", ".", true); +} + +Object cppToPy(Gringo::Symbol val); + +template +Object cppToPy(std::vector const &vals); +template +Object cppToPy(Potassco::Span const &span); +template +Object cppToPy(std::initializer_list l); +template +Object cppToPy(T const *arr, size_t size); + +Object cppToPy(char const *n) { return PyString_FromString(n); } +Object cppToPy(std::string const &s) { return cppToPy(s.c_str()); } +Object cppToPy(bool n) { return PyBool_FromLong(n); } +template +Object cppToPy(T n, typename std::enable_if::value>::type* = nullptr) { + return PyInt_FromLong(n); +} + +template +Object cppToPy(T n, typename std::enable_if::value>::type* = nullptr) { + return PyFloat_FromDouble(n); +} + +struct PyUnblock { + PyUnblock() : state(PyEval_SaveThread()) { } + ~PyUnblock() { PyEval_RestoreThread(state); } + PyThreadState *state; +}; +template +auto doUnblocked(T f) -> decltype(f()) { + PyUnblock b; (void)b; + return f(); +} + +struct PyBlock { + PyBlock() : state(PyGILState_Ensure()) { } + ~PyBlock() { PyGILState_Release(state); } + PyGILState_STATE state; +}; + +Object pyExec(char const *str, char const *filename, PyObject *globals, PyObject *locals = Py_None) { + if (locals == Py_None) { locals = globals; } + Object x = Py_CompileString(str, filename, Py_file_input); +#if PY_MAJOR_VERSION >= 3 + return PyEval_EvalCode(x.toPy(), globals, locals); +#else + return PyEval_EvalCode((PyCodeObject*)x.toPy(), globals, locals); +#endif +} + +#define PY_HANDLE(func, msg) \ +} \ +catch (PyException const &) { handleError(func, msg); throw std::logic_error("cannot happen"); } + +template +Object doCmp(T const &a, T const &b, int op) { + switch (op) { + case Py_LT: { return cppToPy(a < b); } + case Py_LE: { return cppToPy(a <= b); } + case Py_EQ: { return cppToPy(a == b); } + case Py_NE: { return cppToPy(a != b); } + case Py_GT: { return cppToPy(a > b); } + case Py_GE: { return cppToPy(a >= b); } + } + Py_RETURN_FALSE; +} + +std::string errorToString() { + try { + Object type, value, traceback; + PyErr_Fetch(&type.obj, &value.obj, &traceback.obj); + PyErr_NormalizeException(&type.obj, &value.obj, &traceback.obj); + Object tbModule = PyImport_ImportModule("traceback"); + Reference tbDict = PyModule_GetDict(tbModule.toPy()); + Reference tbFE = PyDict_GetItemString(tbDict.toPy(), "format_exception"); + Object ret = PyObject_CallFunctionObjArgs(tbFE.toPy(), type.toPy(), value.valid() ? value.toPy() : Py_None, traceback.valid() ? traceback.toPy() : Py_None, nullptr); + std::ostringstream oss; + for (auto line : ret.iter()) { + oss << " " << line.str(); + } + PyErr_Clear(); + return oss.str(); + } + catch (PyException const &) { + PyErr_Clear(); + return "error during error handling"; + } +} +void handleError(Location const &loc, char const *msg) { + std::ostringstream ss; + ss << loc << ": error: " << msg << ":\n" << errorToString(); + throw GringoError(ss.str().c_str()); +} + +void handleError(char const *loc, char const *msg) { + Location l(loc, 1, 1, loc, 1, 1); + handleError(l, msg); +} + +namespace PythonDetail { + +// macros + +#define CHECK_EXPRESSION(E) decltype(static_cast(E)) + +#define WRAP_FUNCTION(F) \ +template \ +struct Get_##F { \ + static constexpr std::nullptr_t value = nullptr; \ +}; \ +template \ +struct Get_##F + +#define BEGIN_PROTOCOL(F) \ +template \ +struct Get_##F { \ + static constexpr std::nullptr_t value = nullptr; \ + static constexpr bool has_protocol = false; \ +}; \ +template \ +struct Get_##F { \ + static constexpr bool has_protocol = true; + +#define NEXT_PROTOCOL(G,F) \ +}; \ +template \ +struct Get_##F { \ + static constexpr std::nullptr_t value = nullptr; \ + static constexpr bool has_protocol = Get_##G::has_protocol; \ +}; \ +template \ +struct Get_##F { \ + static constexpr bool has_protocol = true; + +#define END_PROTOCOL(G, F, T) \ +}; \ +template \ +struct Get_##F { \ + static constexpr T* value = nullptr; \ +}; \ +template \ +struct Get_##F::has_protocol>::type> { \ + static T value[]; \ +}; \ +template \ +T Get_##F::has_protocol>::type>::value[] = + +// object protocol + +WRAP_FUNCTION(tp_dealloc) { + static void value(PyObject *self) { + reinterpret_cast(self)->tp_dealloc(); + B::type.tp_free(self); + }; +}; + +WRAP_FUNCTION(tp_repr) { + static PyObject *value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->tp_repr().release(); } + PY_CATCH(nullptr); + }; +}; + +template +struct Get_tp_str : Get_tp_repr { }; + +template +struct Get_tp_str { + static PyObject *value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->tp_str().release(); } + PY_CATCH(nullptr); + }; +}; + +WRAP_FUNCTION(tp_hash) { + static long value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->tp_hash(); } + PY_CATCH(-1); + }; +}; + +WRAP_FUNCTION(tp_richcompare) { + static PyObject *value(PyObject *pySelf, PyObject *pyB, int op) { + PY_TRY { + auto self = reinterpret_cast(pySelf); + Reference b{pyB}; + if (!b.isInstance(self->type)) { + if (op == Py_EQ) { Py_RETURN_FALSE; } + else if (op == Py_NE) { Py_RETURN_TRUE; } + else { + const char *ops = "<"; + switch (op) { + case Py_LT: { ops = "<"; break; } + case Py_LE: { ops = "<="; break; } + case Py_EQ: { ops = "=="; break; } + case Py_NE: { ops = "!="; break; } + case Py_GT: { ops = ">"; break; } + case Py_GE: { ops = ">="; break; } + } + return PyErr_Format(PyExc_TypeError, "unorderable types: %s() %s %s()", self->type.tp_name, ops, pyB->ob_type->tp_name); + } + } + return self->tp_richcompare(*reinterpret_cast(pyB), op).release(); + } + PY_CATCH(nullptr); + }; +}; + +WRAP_FUNCTION(tp_iter) { + static PyObject *value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->tp_iter().release(); } + PY_CATCH(nullptr); + }; +}; + +WRAP_FUNCTION(tp_getattro) { + static PyObject *value(PyObject *self, PyObject *name) { + PY_TRY { return reinterpret_cast(self)->tp_getattro(Reference{name}).release(); } + PY_CATCH(nullptr); + }; +}; + +WRAP_FUNCTION(tp_setattro) { + static int value(PyObject *self, PyObject *name, PyObject *value) { + PY_TRY { return (reinterpret_cast(self)->tp_setattro(Reference{name}, Reference{value}), 0); } + PY_CATCH(-1); + }; +}; + +WRAP_FUNCTION(tp_iternext) { + static PyObject *value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->tp_iternext().release(); } + PY_CATCH(nullptr); + }; +}; + +// mapping protocol + +BEGIN_PROTOCOL(mp_length) + static Py_ssize_t value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->mp_length(); } + PY_CATCH(-1); + } +NEXT_PROTOCOL(mp_length, mp_subscript) + static PyObject *value(PyObject *self, PyObject *name) { + PY_TRY { return reinterpret_cast(self)->mp_subscript(Reference{name}).release(); } + PY_CATCH(nullptr); + } +NEXT_PROTOCOL(mp_subscript, mp_ass_subscript) + static int value(PyObject *self, PyObject *name, PyObject *value) { + PY_TRY { return (reinterpret_cast(self)->mp_ass_subscript(Reference{name}, Reference{value}), 0); } + PY_CATCH(-1); + } +END_PROTOCOL(mp_ass_subscript, tp_as_mapping, PyMappingMethods) {{ + Get_mp_length::value, + Get_mp_subscript::value, + Get_mp_ass_subscript::value, +}}; + +// sequence protocol + +BEGIN_PROTOCOL(sq_length) + static Py_ssize_t value(PyObject *self) { + PY_TRY { return reinterpret_cast(self)->sq_length(); } + PY_CATCH(-1); + }; +NEXT_PROTOCOL(sq_length, sq_concat) + static PyObject *value(PyObject *self, PyObject *other) { + PY_TRY { return reinterpret_cast(self)->sq_concat(Reference{other}).release(); } + PY_CATCH(nullptr); + }; +NEXT_PROTOCOL(sq_concat, sq_repeat) + static PyObject *value(PyObject *self, Py_ssize_t count) { + PY_TRY { return reinterpret_cast(self)->sq_repeat(count).release(); } + PY_CATCH(nullptr); + }; +NEXT_PROTOCOL(sq_repeat, sq_item) + static PyObject *value(PyObject *self, Py_ssize_t index) { + PY_TRY { return reinterpret_cast(self)->sq_item(index).release(); } + PY_CATCH(nullptr); + }; +NEXT_PROTOCOL(sq_item, sq_slice) + static PyObject *value(PyObject *self, Py_ssize_t left, Py_ssize_t right) { + PY_TRY { return reinterpret_cast(self)->sq_slice(left, right).release(); } + PY_CATCH(nullptr); + }; +NEXT_PROTOCOL(sq_slice, sq_ass_item) + static int value(PyObject *self, Py_ssize_t index, PyObject *value) { + PY_TRY { return (reinterpret_cast(self)->sq_ass_item(index, Reference{value}), 0); } + PY_CATCH(-1); + }; +NEXT_PROTOCOL(sq_ass_item, sq_ass_slice) + static int value(PyObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *value) { + PY_TRY { return (reinterpret_cast(self)->sq_ass_slice(left, right, Reference{value}), 0); } + PY_CATCH(-1); + }; +NEXT_PROTOCOL(sq_ass_slice, sq_contains) + static int value(PyObject *self, PyObject *value) { + PY_TRY { return reinterpret_cast(self)->sq_contains(Reference{value}); } + PY_CATCH(-1); + }; +NEXT_PROTOCOL(sq_contains, sq_inplace_concat) + static PyObject *value(PyObject *self, PyObject *other) { + PY_TRY { return reinterpret_cast(self)->sq_inplace_concat(Reference{other}); Py_XINCREF(self); return self; } + PY_CATCH(nullptr); + }; +NEXT_PROTOCOL(sq_inplace_concat, sq_inplace_repeat) + static PyObject *value(PyObject *self, Py_ssize_t count) { + PY_TRY { reinterpret_cast(self)->sq_inplace_repeat(count); Py_XINCREF(self); return self; } + PY_CATCH(nullptr); + }; +END_PROTOCOL(sq_inplace_repeat, tp_as_sequence, PySequenceMethods) {{ + Get_sq_length::value, + Get_sq_concat::value, + Get_sq_repeat::value, + Get_sq_item::value, + Get_sq_slice::value, + Get_sq_ass_item::value, + Get_sq_ass_slice::value, + Get_sq_contains::value, + Get_sq_inplace_concat::value, + Get_sq_inplace_repeat::value, +}}; + +} // namespace PythonDetail + +template +struct ObjectBase : ObjectProtocoll { + PyObject_HEAD + static PyTypeObject type; + + static constexpr initproc tp_init = nullptr; + static constexpr newfunc tp_new = nullptr; + static constexpr PyGetSetDef *tp_getset = nullptr; + static PyMethodDef tp_methods[]; + + static bool initType(Reference module) { + if (PyType_Ready(&type) < 0) { return false; } + Py_INCREF(&type); + if (PyModule_AddObject(module.toPy(), T::tp_type, (PyObject*)&type) < 0) { return false; } + return true; + } + + static T *new_() { + return new_(&type, nullptr, nullptr); + } + + static T *new_(PyTypeObject *type, PyObject *, PyObject *) { + T *self; + self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) { return nullptr; } + return self; + } + PyObject *toPy() const { return reinterpret_cast(const_cast(this)); } + +protected: + template + static getter to_getter() { return to_getter_; } + template + static setter to_setter() { return to_setter_; } + template + static PyCFunction to_function() { return to_function_; } + template + static PyCFunction to_function() { return to_function_; } + template + static PyCFunction to_function() { return to_function_; } + template + static PyCFunction to_function() { return reinterpret_cast(to_function_); } + +private: + template + static PyObject *to_getter_(PyObject *o, void *) { + PY_TRY { return (reinterpret_cast(o)->*f)().release(); } + PY_CATCH(nullptr); + } + template + static int to_setter_(PyObject *self, PyObject *value, void *) { + PY_TRY { return ((reinterpret_cast(self)->*f)(Reference{value}), 0); } + PY_CATCH(-1); + } + template + static PyObject *to_function_(PyObject *self, PyObject *) { + PY_TRY { return (reinterpret_cast(self)->*f)().release(); } + PY_CATCH(nullptr); + } + template + static PyObject *to_function_(PyObject *self, PyObject *params) { + PY_TRY { return (reinterpret_cast(self)->*f)(params).release(); } + PY_CATCH(nullptr); + } + template + static PyObject *to_function_(PyObject *self, PyObject *params, PyObject *keywords) { + PY_TRY { return (reinterpret_cast(self)->*f)(params, keywords).release(); } + PY_CATCH(nullptr); + } +}; + +template +PyMethodDef ObjectBase::tp_methods[] = {{nullptr, nullptr, 0, nullptr}}; + +template +PyTypeObject ObjectBase::type = { + PyVarObject_HEAD_INIT(nullptr, 0) + T::tp_name, // tp_name + sizeof(T), // tp_basicsize + 0, // tp_itemsize + PythonDetail::Get_tp_dealloc::value, // tp_dealloc + nullptr, // tp_print + nullptr, // tp_getattr + nullptr, // tp_setattr + nullptr, // tp_compare + PythonDetail::Get_tp_repr::value, // tp_repr + nullptr, // tp_as_number + PythonDetail::Get_tp_as_sequence::value, // tp_as_sequence + PythonDetail::Get_tp_as_mapping::value, // tp_as_mapping + PythonDetail::Get_tp_hash::value, // tp_hash + nullptr, // tp_call + PythonDetail::Get_tp_str::value, // tp_str + PythonDetail::Get_tp_getattro::value, // tp_getattro + PythonDetail::Get_tp_setattro::value, // tp_setattro + nullptr, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags + T::tp_doc, // tp_doc + nullptr, // tp_traverse + nullptr, // tp_clear + PythonDetail::Get_tp_richcompare::value, // tp_richcompare + 0, // tp_weaklistoffset + PythonDetail::Get_tp_iter::value, // tp_iter + PythonDetail::Get_tp_iternext::value, // tp_iternext + T::tp_methods, // tp_methods + nullptr, // tp_members + T::tp_getset, // tp_getset + nullptr, // tp_base + nullptr, // tp_dict + nullptr, // tp_descr_get + nullptr, // tp_descr_set + 0, // tp_dictoffset + reinterpret_cast(T::tp_init), // tp_init + nullptr, // tp_alloc + reinterpret_cast(T::tp_new), // tp_new + nullptr, // tp_free + nullptr, // tp_is_gc + nullptr, // tp_bases + nullptr, // tp_mro + nullptr, // tp_cache + nullptr, // tp_subclasses + nullptr, // tp_weaklist + nullptr, // tp_del + 0, // tp_version_tag + GRINGO_STRUCT_EXTRA +}; + +template +struct EnumType : ObjectBase { + unsigned offset; + + static bool initType(Reference module) { + return ObjectBase::initType(module) && addAttr() >= 0; + } + static PyObject *new_(unsigned offset) { + EnumType *self; + self = reinterpret_cast(ObjectBase::type.tp_alloc(&ObjectBase::type, 0)); + if (!self) { return nullptr; } + self->offset = offset; + return reinterpret_cast(self); + } + + Object tp_repr() { + return PyString_FromString(T::strings[offset]); + } + + template + static Object getAttr(U ret) { + for (unsigned i = 0; i < sizeof(T::values) / sizeof(*T::values); ++i) { + if (T::values[i] == ret) { + PyObject *res = PyDict_GetItemString(ObjectBase::type.tp_dict, T::strings[i]); + Py_XINCREF(res); + return res; + } + } + return PyErr_Format(PyExc_RuntimeError, "should not happen"); + } + static int addAttr() { + for (unsigned i = 0; i < sizeof(T::values) / sizeof(*T::values); ++i) { + Object elem(new_(i)); + if (!elem.valid()) { return -1; } + if (PyDict_SetItemString(ObjectBase::type.tp_dict, T::strings[i], elem.toPy()) < 0) { return -1; } + } + return 0; + } + + long tp_hash() { + return static_cast(offset); + } + + Object tp_richcompare(EnumType b, int op) { + return doCmp(offset, b.offset, op); + } +}; +template +auto enumValue(Reference self) -> decltype(std::declval()->values[0]) { + if (!self.isInstance(T::type)) { + throw std::runtime_error("not an enumeration object"); + } + auto *p = reinterpret_cast(self.toPy()); + return p->values[p->offset]; +} + + +// }}}1 + +// {{{1 wrap TheoryTerm + +struct TheoryTermType : EnumType { + static constexpr char const *tp_type = "TheoryTermType"; + static constexpr char const *tp_name = "clingo.TheoryTermType"; + static constexpr char const *tp_doc = +R"(Enumeration of the different types of theory terms. + +TheoryTermType objects cannot be constructed from python. Instead the +following preconstructed objects are available: + +TheoryTermType.Function -- a function theory term +TheoryTermType.Number -- a numeric theory term +TheoryTermType.Symbol -- a symbolic theory term +TheoryTermType.List -- a list theory term +TheoryTermType.Tuple -- a tuple theory term +TheoryTermType.Set -- a set theory term)"; + + static constexpr Gringo::TheoryData::TermType const values[] = { + Gringo::TheoryData::TermType::Function, + Gringo::TheoryData::TermType::Number, + Gringo::TheoryData::TermType::Symbol, + Gringo::TheoryData::TermType::List, + Gringo::TheoryData::TermType::Tuple, + Gringo::TheoryData::TermType::Set + }; + static constexpr const char * const strings[] = { + "Function", + "Number", + "Symbol", + "List", + "Tuple", + "Set" + }; +}; + +constexpr Gringo::TheoryData::TermType const TheoryTermType::values[]; +constexpr const char * const TheoryTermType::strings[]; + +struct TheoryTerm : ObjectBase { + Gringo::TheoryData const *data; + Id_t value; + static PyGetSetDef tp_getset[]; + static constexpr char const *tp_type = "TheoryTerm"; + static constexpr char const *tp_name = "clingo.TheoryTerm"; + static constexpr char const *tp_doc = +R"(TheoryTerm objects represent theory terms. + +This are read-only objects, which can be obtained from theory atoms and +elements.)"; + + static PyObject *new_(Gringo::TheoryData const *data, Id_t value) { + TheoryTerm *self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->value = value; + self->data = data; + return reinterpret_cast(self); + } + Object name() { + return PyString_FromString(data->termName(value)); + } + Object number() { + return PyInt_FromLong(data->termNum(value)); + } + Object args() { + Potassco::IdSpan span = data->termArgs(value); + Object list = PyList_New(span.size); + if (!list.valid()) { return nullptr; } + for (size_t i = 0; i < span.size; ++i) { + Object arg = new_(data, *(span.first + i)); + if (!arg.valid()) { return nullptr; } + if (PyList_SetItem(list.toPy(), i, arg.release()) < 0) { return nullptr; } + } + return list; + } + Object tp_repr() { + return PyString_FromString(data->termStr(value).c_str()); + } + Object termType() { + return TheoryTermType::getAttr(data->termType(value)); + } + long tp_hash() { + return value; + } + Object tp_richcompare(TheoryTerm &b, int op) { + return doCmp(value, b.value, op); + } +}; + +PyGetSetDef TheoryTerm::tp_getset[] = { + {(char *)"type", to_getter<&TheoryTerm::termType>(), nullptr, (char *)R"(type -> TheoryTermType + +The type of the theory term.)", nullptr}, + {(char *)"name", to_getter<&TheoryTerm::name>(), nullptr, (char *)R"(name -> str + +The name of the TheoryTerm\n(for symbols and functions).)", nullptr}, + {(char *)"arguments", to_getter<&TheoryTerm::args>(), nullptr, (char *)R"(arguments -> [Symbol] + +The arguments of the TheoryTerm (for functions, tuples, list, and sets).)", nullptr}, + {(char *)"number", to_getter<&TheoryTerm::number>(), nullptr, (char *)R"(number -> integer + +The numeric representation of the TheoryTerm (for numbers).)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap TheoryElement + +struct TheoryElement : ObjectBase { + Gringo::TheoryData const *data; + Id_t value; + static constexpr char const *tp_type = "TheoryElement"; + static constexpr char const *tp_name = "clingo.TheoryElement"; + static constexpr char const *tp_doc = +R"(TheoryElement objects represent theory elements which consist of a tuple of +terms and a set of literals.)"; + static PyGetSetDef tp_getset[]; + static PyObject *new_(Gringo::TheoryData const *data, Id_t value) { + TheoryElement *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->value = value; + self->data = data; + return reinterpret_cast(self); + } + static PyObject *terms(TheoryElement *self, void *) { + PY_TRY + Potassco::IdSpan span = self->data->elemTuple(self->value); + Object list = PyList_New(span.size); + for (size_t i = 0; i < span.size; ++i) { + Object arg = TheoryTerm::new_(self->data, *(span.first + i)); + if (PyList_SetItem(list.toPy(), i, arg.release()) < 0) { return nullptr; } + } + return list.release(); + PY_CATCH(nullptr); + } + static PyObject *condition(TheoryElement *self, void *) { + PY_TRY + Potassco::LitSpan span = self->data->elemCond(self->value); + Object list = PyList_New(span.size); + for (size_t i = 0; i < span.size; ++i) { + Object arg = PyInt_FromLong(*(span.first + i)); + if (PyList_SetItem(list.toPy(), i, arg.release()) < 0) { return nullptr; } + } + return list.release(); + PY_CATCH(nullptr); + } + static PyObject *condition_id(TheoryElement *self, void *) { + PY_TRY + return PyInt_FromLong(self->data->elemCondLit(self->value)); + PY_CATCH(nullptr); + } + Object tp_repr() { + return PyString_FromString(data->elemStr(value).c_str()); + } + long tp_hash() { + return value; + } + Object tp_richcompare(TheoryElement &b, int op) { + return doCmp(value, b.value, op); + } +}; + +PyGetSetDef TheoryElement::tp_getset[] = { + {(char *)"terms", (getter)terms, nullptr, (char *)R"(terms -> [TheoryTerm] + +The tuple of the element.)", nullptr}, + {(char *)"condition", (getter)condition, nullptr, (char *)R"(condition -> [TheoryTerm] + +The conditon of the element.)", nullptr}, + {(char *)"condition_id", (getter)condition_id, nullptr, (char *)R"(condition_id -> int + +Each condition has an id. This id can be passed to PropagateInit.solver_literal +to obtain a solver literal equivalent to the condition.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap TheoryAtom + +struct TheoryAtom : ObjectBase { + Gringo::TheoryData const *data; + Id_t value; + static PyGetSetDef tp_getset[]; + static constexpr char const *tp_type = "TheoryAtom"; + static constexpr char const *tp_name = "clingo.TheoryAtom"; + static constexpr char const *tp_doc = +R"(TheoryAtom objects represent theory atoms.)"; + static PyObject *new_(Gringo::TheoryData const *data, Id_t value) { + TheoryAtom *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->value = value; + self->data = data; + return reinterpret_cast(self); + } + static PyObject *elements(TheoryAtom *self, void *) { + PY_TRY + Potassco::IdSpan span = self->data->atomElems(self->value); + Object list = PyList_New(span.size); + for (size_t i = 0; i < span.size; ++i) { + Object arg = TheoryElement::new_(self->data, *(span.first + i)); + if (PyList_SetItem(list.toPy(), i, arg.release()) < 0) { return nullptr; } + } + return list.release(); + PY_CATCH(nullptr); + } + static PyObject *term(TheoryTerm *self, void *) { + PY_TRY + return TheoryTerm::new_(self->data, self->data->atomTerm(self->value)); + PY_CATCH(nullptr); + } + static PyObject *literal(TheoryTerm *self, void *) { + PY_TRY + return PyInt_FromLong(self->data->atomLit(self->value)); + PY_CATCH(nullptr); + } + static PyObject *guard(TheoryTerm *self, void *) { + PY_TRY + if (!self->data->atomHasGuard(self->value)) { Py_RETURN_NONE; } + std::pair guard = self->data->atomGuard(self->value); + Object tuple = PyTuple_New(2); + Object op = PyString_FromString(guard.first); + if (PyTuple_SetItem(tuple.toPy(), 0, op.release()) < 0) { return nullptr; } + Object term = TheoryTerm::new_(self->data, guard.second); + if (PyTuple_SetItem(tuple.toPy(), 1, term.release()) < 0) { return nullptr; } + return tuple.release(); + PY_CATCH(nullptr); + } + Object tp_repr() { + return PyString_FromString(data->atomStr(value).c_str()); + } + long tp_hash() { + return value; + } + Object tp_richcompare(TheoryAtom &b, int op) { + return doCmp(value, b.value, op); + } +}; + +PyGetSetDef TheoryAtom::tp_getset[] = { + {(char *)"elements", (getter)elements, nullptr, (char *)R"(elements -> [TheoryElement] + +The theory elements of the theory atom.)", nullptr}, + {(char *)"term", (getter)term, nullptr, (char *)R"(term -> TheoryTerm + +The term of the theory atom.)", nullptr}, + {(char *)"guard", (getter)guard, nullptr, (char *)R"(guard -> (str, TheoryTerm) + +The guard of the theory atom or None if the atom has no guard.)", nullptr}, + {(char *)"literal", (getter)literal, nullptr, (char *)R"(literal -> int + +The program literal associated with the theory atom.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap TheoryAtomIter + +struct TheoryAtomIter : ObjectBase { + Gringo::TheoryData const *data; + Id_t offset; + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "TheoryAtomIter"; + static constexpr char const *tp_name = "clingo.TheoryAtomIter"; + static constexpr char const *tp_doc = +R"(Object to iterate over all theory atoms.)"; + static PyObject *new_(Gringo::TheoryData const *data, Id_t offset) { + TheoryAtomIter *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->data = data; + self->offset = offset; + return reinterpret_cast(self); + } + Reference tp_iter() { return *this; } + Object get() { return TheoryAtom::new_(data, offset); } + Object tp_iternext() { + if (offset < data->numAtoms()) { + Object next = get(); + ++offset; + return next; + } else { + PyErr_SetNone(PyExc_StopIteration); + return nullptr; + } + } +}; + +PyMethodDef TheoryAtomIter::tp_methods[] = { + {"get", to_function<&TheoryAtomIter::get>(), METH_NOARGS, +R"(get(self) -> TheoryAtom)"}, + {nullptr, nullptr, 0, nullptr} +}; + +// {{{1 wrap Symbol + +struct SymbolType : EnumType { + enum Type { Number, String, Function, Inf, Sup }; + static constexpr char const *tp_type = "SymbolType"; + static constexpr char const *tp_name = "clingo.SymbolType"; + static constexpr char const *tp_doc = +R"(Enumeration of the different types of symbols. + +SymbolType objects cannot be constructed from python. Instead the following +preconstructed objects are available: + +SymbolType.Number -- a numeric symbol - e.g., 1 +SymbolType.String -- a string symbol - e.g., "a" +SymbolType.Function -- a numeric symbol - e.g., c, (1, "a"), or f(1,"a") +SymbolType.Infimum -- the #inf symbol +SymbolType.Supremum -- the #sup symbol)"; + + static constexpr Type const values[] = { Number, String, Function, Inf, Sup }; + static constexpr const char * const strings[] = { "Number", "String", "Function", "Infimum", "Supremum" }; +}; + +constexpr SymbolType::Type const SymbolType::values[]; +constexpr const char * const SymbolType::strings[]; + +struct Symbol : ObjectBase { + Gringo::Symbol val; + static PyObject *inf; + static PyObject *sup; + static PyGetSetDef tp_getset[]; + static constexpr char const *tp_type = "Symbol"; + static constexpr char const *tp_name = "clingo.Symbol"; + static constexpr char const *tp_doc = +R"(Represents a gringo symbol. + +This includes numbers, strings, functions (including constants with +len(arguments) == 0 and tuples with len(name) == 0), #inf and #sup. Symbol +objects are ordered like in gringo and their string representation corresponds +to their gringo representation. + +Note that this class does not have a constructor. Instead there are the +functions Number(), String(), and Function() to construct symbol objects or the +preconstructed symbols Infimum and Supremum.)"; + + static bool initType(Reference module) { + if (!ObjectBase::initType(module)) { return false; } + inf = type.tp_alloc(&type, 0); + if (!inf) { return false; } + reinterpret_cast(inf)->val = Gringo::Symbol::createInf(); + if (PyModule_AddObject(module.toPy(), "Infimum", inf) < 0) { return false; } + sup = type.tp_alloc(&type, 0); + reinterpret_cast(sup)->val = Gringo::Symbol::createSup(); + if (!sup) { return false; } + if (PyModule_AddObject(module.toPy(), "Supremum", sup) < 0) { return false; } + return true; + } + + static PyObject *new_(Gringo::Symbol value) { + if (value.type() == Gringo::SymbolType::Inf) { + Py_INCREF(inf); + return inf; + } + else if (value.type() == Gringo::SymbolType::Sup) { + Py_INCREF(sup); + return sup; + } + else { + Symbol *self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + new (&self->val) Gringo::Symbol(value); + return reinterpret_cast(self); + } + } + + static PyObject *new_function_(char const *name, PyObject *params, PyObject *pyPos) { + PY_TRY + auto sign = !pyToCpp(pyPos); + if (strcmp(name, "") == 0 && sign) { + PyErr_SetString(PyExc_RuntimeError, "tuples must not have signs"); + return nullptr; + } + if (params) { + SymVec vals; + pyToCpp(params, vals); + return new_(Gringo::Symbol::createFun(name, Potassco::toSpan(vals), sign)); + } + else { + return new_(Gringo::Symbol::createId(name, sign)); + } + PY_CATCH(nullptr); + } + static PyObject *new_function(PyObject *, PyObject *args, PyObject *kwds) { + PY_TRY + static char const *kwlist[] = {"name", "arguments", "positive", nullptr}; + char const *name; + PyObject *pyPos = Py_True; + PyObject *params = nullptr; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|OO", const_cast(kwlist), &name, ¶ms, &pyPos)) { return nullptr; } + return new_function_(name, params, pyPos); + PY_CATCH(nullptr); + } + static PyObject *new_tuple(PyObject *, PyObject *arg) { + return new_function_("", arg, Py_False); + } + static PyObject *new_number(PyObject *, PyObject *arg) { + PY_TRY + auto num = pyToCpp(arg); + return new_(Gringo::Symbol::createNum(num)); + PY_CATCH(nullptr); + } + static PyObject *new_string(PyObject *, PyObject *arg) { + PY_TRY + char const *str = pyToCpp(arg); + return new_(Gringo::Symbol::createStr(str)); + PY_CATCH(nullptr); + } + static PyObject *name(Symbol *self, void *) { + PY_TRY + if (self->val.type() == Gringo::SymbolType::Fun) { + return PyString_FromString(self->val.name().c_str()); + } + else { + Py_RETURN_NONE; + } + PY_CATCH(nullptr); + } + + static PyObject *string(Symbol *self, void *) { + PY_TRY + if (self->val.type() == Gringo::SymbolType::Str) { + return PyString_FromString(self->val.string().c_str()); + } + else { + Py_RETURN_NONE; + } + PY_CATCH(nullptr); + } + + static PyObject *negative(Symbol *self, void *) { + PY_TRY + if (self->val.type() == Gringo::SymbolType::Fun) { + return cppToPy(self->val.sign()).release(); + } + else { + Py_RETURN_NONE; + } + PY_CATCH(nullptr); + } + + static PyObject *positive(Symbol *self, void *) { + PY_TRY + if (self->val.type() == Gringo::SymbolType::Fun) { + return cppToPy(!self->val.sign()).release(); + } + else { + Py_RETURN_NONE; + } + PY_CATCH(nullptr); + } + + static PyObject *num(Symbol *self, void *) { + PY_TRY + if (self->val.type() == Gringo::SymbolType::Num) { + return PyInt_FromLong(self->val.num()); + } + else { + Py_RETURN_NONE; + } + PY_CATCH(nullptr); + } + + static PyObject *args(Symbol *self, void *) { + PY_TRY + if (self->val.type() == Gringo::SymbolType::Fun) { + return cppToPy(self->val.args()).release(); + } + else { + Py_RETURN_NONE; + } + PY_CATCH(nullptr); + } + + static PyObject *type_(Symbol *self, void *) { + PY_TRY + switch (self->val.type()) { + case Gringo::SymbolType::Str: { return SymbolType::getAttr(SymbolType::String).release(); } + case Gringo::SymbolType::Num: { return SymbolType::getAttr(SymbolType::Number).release(); } + case Gringo::SymbolType::Inf: { return SymbolType::getAttr(SymbolType::Inf).release(); } + case Gringo::SymbolType::Sup: { return SymbolType::getAttr(SymbolType::Sup).release(); } + case Gringo::SymbolType::Fun: { return SymbolType::getAttr(SymbolType::Function).release(); } + case Gringo::SymbolType::Special: { throw std::logic_error("must not happen"); } + } + PY_CATCH(nullptr); + } + Object tp_repr() { + std::ostringstream oss; + oss << val; + return PyString_FromString(oss.str().c_str()); + } + + long tp_hash() { + return static_cast(val.hash()); + } + + Object tp_richcompare(Symbol &b, int op) { + return doCmp(val, b.val, op); + } +}; + +PyGetSetDef Symbol::tp_getset[] = { + {(char *)"name", (getter)name, nullptr, (char *)"The name of a function.", nullptr}, + {(char *)"string", (getter)string, nullptr, (char *)"The value of a string.", nullptr}, + {(char *)"number", (getter)num, nullptr, (char *)"The value of a number.", nullptr}, + {(char *)"arguments", (getter)args, nullptr, (char *)"The arguments of a function.", nullptr}, + {(char *)"negative", (getter)negative, nullptr, (char *)"The sign of a function.", nullptr}, + {(char *)"positive", (getter)positive, nullptr, (char *)"The sign of a function.", nullptr}, + {(char *)"type", (getter)type_, nullptr, (char *)"The type of the symbol.", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +PyObject *Symbol::inf = nullptr; +PyObject *Symbol::sup = nullptr; + +// {{{1 wrap SolveResult + +struct SolveResult : ObjectBase { + Gringo::SolveResult result; + static PyGetSetDef tp_getset[]; + static constexpr char const *tp_type = "SolveResult"; + static constexpr char const *tp_name = "clingo.SolveResult"; + static constexpr char const *tp_doc = +R"(Captures the result of a solve call. + +SolveResult objects cannot be constructed from python. Instead they +are returned by the solve methods of the Control object.)"; + static PyObject *new_(Gringo::SolveResult result) { + SolveResult *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->result = result; + return reinterpret_cast(self); + } + static PyObject *satisfiable(SolveResult *self, void *) { + switch (self->result.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { Py_RETURN_TRUE; } + case Gringo::SolveResult::Unsatisfiable: { Py_RETURN_FALSE; } + case Gringo::SolveResult::Unknown: { Py_RETURN_NONE; } + } + Py_RETURN_NONE; + } + static PyObject *unsatisfiable(SolveResult *self, void *) { + switch (self->result.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { Py_RETURN_FALSE; } + case Gringo::SolveResult::Unsatisfiable: { Py_RETURN_TRUE; } + case Gringo::SolveResult::Unknown: { Py_RETURN_NONE; } + } + Py_RETURN_NONE; + } + static PyObject *unknown(SolveResult *self, void *) { + switch (self->result.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { Py_RETURN_FALSE; } + case Gringo::SolveResult::Unsatisfiable: { Py_RETURN_FALSE; } + case Gringo::SolveResult::Unknown: { Py_RETURN_TRUE; } + } + Py_RETURN_NONE; + } + static PyObject *exhausted(SolveResult *self, void *) { + return cppToPy(self->result.exhausted()).release(); + } + static PyObject *interrupted(SolveResult *self, void *) { + return cppToPy(self->result.interrupted()).release(); + } + Object tp_repr() { + switch (result.satisfiable()) { + case Gringo::SolveResult::Satisfiable: { return PyString_FromString("SAT"); } + case Gringo::SolveResult::Unsatisfiable: { return PyString_FromString("UNSAT"); } + case Gringo::SolveResult::Unknown: { return PyString_FromString("UNKNOWN"); } + } + return PyString_FromString("UNKNOWN"); + } +}; + +PyGetSetDef SolveResult::tp_getset[] = { + {(char *)"satisfiable", (getter)satisfiable, nullptr, +(char *)R"(True if the problem is satisfiable, False if the problem is +unsatisfiable, or None if the satisfiablity is not known.)", nullptr}, + {(char *)"unsatisfiable", (getter)unsatisfiable, nullptr, +(char *)R"(True if the problem is unsatisfiable, False if the problem is +satisfiable, or None if the satisfiablity is not known. + +This is equivalent to None if satisfiable is None else not satisfiable.)", nullptr}, + {(char *)"unknown", (getter)unknown, nullptr, +(char *)R"(True if the satisfiablity is not known. + +This is equivalent to satisfiable is None.)", nullptr}, + {(char *)"exhausted", (getter)exhausted, nullptr, +(char *)R"(True if the search space was exhausted.)", nullptr}, + {(char *)"interrupted", (getter)interrupted, nullptr, +(char *)R"(True if the search was interrupted.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap Statistics + +Object getStatistics(Potassco::AbstractStatistics const *stats, Potassco::AbstractStatistics::Key_t key) { + switch (stats->type(key)) { + case Potassco::Statistics_t::Value: { + return cppToPy(stats->value(key)); + } + case Potassco::Statistics_t::Array: { + size_t e = stats->size(key); + List list{e}; + for (size_t i = 0; i != e; ++i) { + list.setItem(i, getStatistics(stats, stats->at(key, i))); + } + return list; + } + case Potassco::Statistics_t::Map: { + Dict dict; + for (size_t i = 0, e = stats->size(key); i != e; ++i) { + auto name = stats->key(key, i); + dict.setItem(name, getStatistics(stats, stats->get(key, name))); + } + return dict; + } + default: { + throw std::logic_error("cannot happen"); + } + } +} + +// {{{1 wrap SolveControl + +struct SolveControl : ObjectBase { + Gringo::Model const *model; + static PyMethodDef tp_methods[]; + static constexpr char const *tp_type = "SolveControl"; + static constexpr char const *tp_name = "clingo.SolveControl"; + static constexpr char const *tp_doc = +R"(Object that allows for controlling a running search. + +Note that SolveControl objects cannot be constructed from python. Instead +they are available as properties of Model objects.)"; + + static PyObject *new_(Gringo::Model const &model) { + SolveControl *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->model = &model; + return reinterpret_cast(self); + } + + static PyObject *getClause(SolveControl *self, PyObject *pyLits, bool invert) { + PY_TRY + auto lits = pyToCpp(pyLits); + if (invert) { + for (auto &lit : lits) { lit.second = !lit.second; } + } + self->model->addClause(lits); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + + static PyObject *add_clause(SolveControl *self, PyObject *pyLits) { + return getClause(self, pyLits, false); + } + + static PyObject *add_nogood(SolveControl *self, PyObject *pyLits) { + return getClause(self, pyLits, true); + } +}; + +PyMethodDef SolveControl::tp_methods[] = { + // add_clause + {"add_clause", (PyCFunction)add_clause, METH_O, +R"(add_clause(self, lits) -> None + +Add a clause that applies to the current solving step during the search. + +Arguments: +lits -- list of literals represented as pairs of atoms and Booleans + +Note that this function can only be called in the model callback (or while +iterating when using a SolveIter).)"}, + // add_nogood + {"add_nogood", (PyCFunction)add_nogood, METH_O, +R"(add_nogood(self, lits) -> None + +Equivalent to add_clause with the literals inverted. + +Arguments: +lits -- list of pairs of Booleans and atoms representing the nogood)"}, + {nullptr, nullptr, 0, nullptr} +}; + +// {{{1 wrap Model + +struct Model : ObjectBase { + Gringo::Model const *model; + static PyMethodDef tp_methods[]; + static PyGetSetDef tp_getset[]; + + static constexpr char const *tp_type = "Model"; + static constexpr char const *tp_name = "clingo.Model"; + static constexpr char const *tp_doc = +R"(Provides access to a model during a solve call. + +The string representation of a model object is similar to the output of models +by clingo using the default output. + +Note that model objects cannot be constructed from python. Instead they are +passed as argument to a model callback (see Control.solve() and +Control.solve_async()). Furthermore, the lifetime of a model object is limited +to the scope of the callback. They must not be stored for later use in other +places like - e.g., the main function.)"; + + static PyObject *new_(Gringo::Model const &model) { + Model *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->model = &model; + return reinterpret_cast(self); + } + static PyObject *contains(Model *self, PyObject *arg) { + PY_TRY + Gringo::Symbol val; + pyToCpp(arg, val); + return cppToPy(self->model->contains(val)).release(); + PY_CATCH(nullptr); + } + static PyObject *atoms(Model *self, PyObject *pyargs, PyObject *pykwds) { + PY_TRY + unsigned atomset = 0; + static char const *kwlist[] = {"atoms", "terms", "shown", "csp", "extra", "complement", nullptr}; + PyObject *pyAtoms = Py_False, *pyTerms = Py_False, *pyShown = Py_False, *pyCSP = Py_False, *pyExtra = Py_False, *pyComp = Py_False; + if (!PyArg_ParseTupleAndKeywords(pyargs, pykwds, "|OOOOOO", const_cast(kwlist), &pyAtoms, &pyTerms, &pyShown, &pyCSP, &pyExtra, &pyComp)) { return nullptr; } + if (pyToCpp(pyAtoms)) { atomset |= clingo_show_type_atoms; } + if (pyToCpp(pyTerms)) { atomset |= clingo_show_type_terms; } + if (pyToCpp(pyShown)) { atomset |= clingo_show_type_shown; } + if (pyToCpp(pyCSP)) { atomset |= clingo_show_type_csp; } + if (pyToCpp(pyExtra)) { atomset |= clingo_show_type_extra; } + if (pyToCpp(pyComp)) { atomset |= clingo_show_type_complement; } + return cppToPy(self->model->atoms(atomset)).release(); + PY_CATCH(nullptr); + } + static PyObject *cost(Model *self, void *) { + PY_TRY + return cppToPy(self->model->optimization()).release(); + PY_CATCH(nullptr); + } + Object tp_repr() { + auto printAtom = [](std::ostream &out, Gringo::Symbol val) { + auto sig = val.sig(); + if (val.type() == Gringo::SymbolType::Fun && sig.name() == "$" && sig.arity() == 2) { + auto args = val.args().first; + out << args[0] << "=" << args[1]; + } + else { out << val; } + }; + std::ostringstream oss; + print_comma(oss, model->atoms(clingo_show_type_shown), " ", printAtom); + return cppToPy(oss.str()).release(); + } + static PyObject *getContext(Model *self, void *) { + return SolveControl::new_(*self->model); + } +}; + +PyGetSetDef Model::tp_getset[] = { + {(char *)"context", (getter)getContext, nullptr, (char*)"SolveControl object that allows for controlling the running search.", nullptr}, + {(char *)"cost", (getter)cost, nullptr, +(char *)R"(Return the list of integer cost values of the model. + +The return values correspond to clasp's cost output.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +PyMethodDef Model::tp_methods[] = { + {"symbols", (PyCFunction)atoms, METH_VARARGS | METH_KEYWORDS, +R"(symbols(self, atoms, terms, shown, csp, extra, complement) + -> list of terms + +Return the list of atoms, terms, or CSP assignments in the model. + +Keyword Arguments: +atoms -- select all atoms in the model (independent of #show statements) + (Default: False) +terms -- select all terms displayed with #show statements in the model + (Default: False) +shown -- select all atoms and terms as outputted by clingo + (Default: False) +csp -- select all csp assignments (independent of #show statements) + (Default: False) +extra -- select terms added by clingo extensions + (Default: False) +complement -- return the complement of the answer set w.r.t. to the Herbrand + base accumulated so far (does not affect csp assignments) + (Default: False) + +Note that atoms are represented using functions (Symbol objects), and that CSP +assignments are represented using functions with name "$" where the first +argument is the name of the CSP variable and the second its value.)"}, + {"contains", (PyCFunction)contains, METH_O, +R"(contains(self, a) -> bool + +Check if an atom a is contained in the model. + +The atom must be represented using a function symbol.)"}, + {nullptr, nullptr, 0, nullptr} + +}; + +// {{{1 wrap SolveFuture + +struct SolveFuture : ObjectBase { + Gringo::SolveFuture *future; + PyObject *mh; + PyObject *fh; + + static PyMethodDef tp_methods[]; + static constexpr char const *tp_type = "SolveFuture"; + static constexpr char const *tp_name = "clingo.SolveFuture"; + static constexpr char const *tp_doc = +R"(Handle for asynchronous solve calls. + +SolveFuture objects cannot be created from python. Instead they are returned by +Control.solve_async, which performs a search in the background. A SolveFuture +object can be used to wait for such a background search or cancel it. + +Functions in this object release the GIL. They are not thread-safe though. + +See Control.solve_async for an example.)"; + + static PyObject *new_(Gringo::SolveFuture &future, PyObject *mh, PyObject *fh) { + SolveFuture *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->future = &future; + self->mh = mh; + self->fh = fh; + Py_XINCREF(self->mh); + Py_XINCREF(self->fh); + return reinterpret_cast(self); + } + + void tp_dealloc() { + Py_XDECREF(mh); + Py_XDECREF(fh); + } + + static PyObject *get(SolveFuture *self, PyObject *) { + PY_TRY + return SolveResult::new_(doUnblocked([self]() { return self->future->get(); })); + PY_CATCH(nullptr); + } + + static PyObject *wait(SolveFuture *self, PyObject *args) { + PY_TRY + PyObject *timeout = nullptr; + if (!PyArg_ParseTuple(args, "|O", &timeout)) { return nullptr; } + if (!timeout) { + doUnblocked([self](){ self->future->wait(); }); + Py_RETURN_NONE; + } + else { + auto time = pyToCpp(timeout); + return cppToPy(doUnblocked([self, time](){ return self->future->wait(time); })).release(); + } + PY_CATCH(nullptr); + } + + static PyObject *cancel(SolveFuture *self, PyObject *) { + PY_TRY + doUnblocked([self](){ self->future->cancel(); }); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } +}; + +PyMethodDef SolveFuture::tp_methods[] = { + {"get", (PyCFunction)get, METH_NOARGS, +R"(get(self) -> SolveResult + +Get the result of an solve_async call. + +If the search is not completed yet, the function blocks until the result is +ready.)"}, + {"wait", (PyCFunction)wait, METH_VARARGS, +R"(wait(self, timeout) -> None or bool + +Wait for solve_async call to finish with an optional timeout. + +If a timeout is given, the function waits at most timeout seconds and returns a +Boolean indicating whether the search has finished. Otherwise, the function +blocks until the search is finished and returns nothing. + +Arguments: +timeout -- optional timeout in seconds + (permits floating point values))"}, + {"cancel", (PyCFunction)cancel, METH_NOARGS, +R"(cancel(self) -> None + +Cancel the running search. + +See Control.interrupt() for a thread-safe alternative.)"}, + {nullptr, nullptr, 0, nullptr} +}; + +// {{{1 wrap SolveIter + +struct SolveIter : ObjectBase { + Gringo::SolveIter *solve_iter; + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "SolveIter"; + static constexpr char const *tp_name = "clingo.SolveIter"; + static constexpr char const *tp_doc = +R"(Object to conveniently iterate over all models. + +During solving the GIL is released. The functions in this object are not +thread-safe though.)"; + + static PyObject *new_(Gringo::SolveIter &iter) { + SolveIter *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->solve_iter = &iter; + return reinterpret_cast(self); + } + Reference tp_iter() { return *this; } + Object get() { + return SolveResult::new_(doUnblocked([this]() { return solve_iter->get(); })); + } + Object tp_iternext() { + if (Gringo::Model const *m = doUnblocked([this]() { return solve_iter->next(); })) { + return Model::new_(*m); + } else { + PyErr_SetNone(PyExc_StopIteration); + return nullptr; + } + } + Object enter() { return Reference{*this}; } + Object exit() { + doUnblocked([this]() { return solve_iter->close(); }); + Py_RETURN_FALSE; + } +}; + +PyMethodDef SolveIter::tp_methods[] = { + {"__enter__", to_function<&SolveIter::enter>(), METH_NOARGS, +R"(__enter__(self) -> SolveIter + +Returns self.)"}, + {"get", to_function<&SolveIter::get>(), METH_NOARGS, +R"(get(self) -> SolveResult + +Return the result of the search. + +Note that this function might start a search for the next model and then return +a result accordingly. The function might be called after iteration to check if +the search has been interrupted.)"}, + {"__exit__", to_function<&SolveIter::exit>(), METH_VARARGS, +R"(__exit__(self, type, value, traceback) -> bool + +Follows python __exit__ conventions. Does not suppress exceptions. + +Stops the current search. It is necessary to call this method after each search.)"}, + {nullptr, nullptr, 0, nullptr} +}; + +// {{{1 wrap Configuration + +struct Configuration : ObjectBase { + unsigned key; + int nSubkeys; + int arrLen; + int nValues; + char const* help; + Gringo::ConfigProxy *proxy; + static PyGetSetDef tp_getset[]; + + static constexpr char const *tp_type = "Configuration"; + static constexpr char const *tp_name = "clingo.Configuration"; + static constexpr char const *tp_doc = +R"(Allows for changing the configuration of the underlying solver. + +Options are organized hierarchically. To change and inspect an option use: + + config.group.subgroup.option = "value" + value = config.group.subgroup.option + +There are also arrays of option groups that can be accessed using integer +indices: + + config.group.subgroup[0].option = "value1" + config.group.subgroup[1].option = "value2" + +To list the subgroups of an option group, use the keys member. Array option +groups, like solver, have a non-negative length and can be iterated. +Furthermore, there are meta options having key "configuration". Assigning a +meta option sets a number of related options. To get further information about +an option or option group , use property __desc_ to retrieve a +description. + +Example: + +#script (python) +import clingo + +def main(prg): + prg.conf.solve.models = 0 + prg.ground([("base", [])]) + prg.solve() + +#end. + +{a; c}. + +Expected Answer Sets: + +{ {}, {a}, {c}, {a,c} })"; + + static PyObject *new_(unsigned key, Gringo::ConfigProxy &proxy) { + PY_TRY + Object ret(type.tp_alloc(&type, 0)); + if (!ret.valid()) { return nullptr; } + Configuration *self = reinterpret_cast(ret.toPy()); + self->proxy = &proxy; + self->key = key; + self->proxy->getKeyInfo(self->key, &self->nSubkeys, &self->arrLen, &self->help, &self->nValues); + return ret.release(); + PY_CATCH(nullptr); + } + + static PyObject *keys(Configuration *self, void *) { + PY_TRY + if (self->nSubkeys < 0) { Py_RETURN_NONE; } + else { + Object list = PyList_New(self->nSubkeys); + for (int i = 0; i < self->nSubkeys; ++i) { + char const *key = self->proxy->getSubKeyName(self->key, i); + Object pyString = PyString_FromString(key); + if (PyList_SetItem(list.toPy(), i, pyString.release()) < 0) { return nullptr; } + } + return list.release(); + } + PY_CATCH(nullptr); + } + + Object tp_getattro(Reference name) { + auto current = pyToCpp(name); + bool desc = strncmp("__desc_", current, 7) == 0; + if (desc) { current += 7; } + unsigned subkey; + if (proxy->hasSubKey(key, current, &subkey)) { + Object subKey(new_(subkey, *proxy)); + Configuration *sub = reinterpret_cast(subKey.toPy()); + if (desc) { return PyString_FromString(sub->help); } + else if (sub->nValues < 0) { return subKey; } + else { + std::string value; + if (!sub->proxy->getKeyValue(sub->key, value)) { Py_RETURN_NONE; } + return PyString_FromString(value.c_str()); + } + } + return PyObject_GenericGetAttr(reinterpret_cast(this), name.toPy()); + } + + void tp_setattro(Reference name, Reference pyValue) { + char const *current = pyToCpp(name); + unsigned subkey; + if (proxy->hasSubKey(key, current, &subkey)) { + char const *value = pyToCpp(pyValue.str()); + proxy->setKeyValue(subkey, value); + } + else { + if (PyObject_GenericSetAttr(reinterpret_cast(this), name.toPy(), pyValue.toPy()) < 0) { throw PyException(); } + } + } + + Py_ssize_t sq_length() { + return arrLen; + } + + Object sq_item(Py_ssize_t index) { + if (index < 0 || index >= arrLen) { + PyErr_Format(PyExc_IndexError, "invalid index"); + return nullptr; + } + return new_(proxy->getArrKey(key, index), *proxy); + } +}; + +PyGetSetDef Configuration::tp_getset[] = { + // keys + {(char *)"keys", (getter)keys, nullptr, +(char *)R"(The list of names of sub-option groups or options. + +The list is None if the current object is not an option group.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap SymbolicAtom + +struct SymbolicAtom : public ObjectBase { + Gringo::SymbolicAtoms *atoms; + Gringo::SymbolicAtomIter range; + + static constexpr char const *tp_type = "SymbolicAtom"; + static constexpr char const *tp_name = "clingo.SymbolicAtom"; + static constexpr char const *tp_doc = "Captures a symbolic atom and provides properties to inspect its state."; + static PyGetSetDef tp_getset[]; + + static PyObject *new_(Gringo::SymbolicAtoms &atoms, Gringo::SymbolicAtomIter range) { + Object ret(type.tp_alloc(&type, 0)); + SymbolicAtom *self = reinterpret_cast(ret.toPy()); + self->atoms = &atoms; + self->range = range; + return ret.release(); + } + static PyObject *symbol(SymbolicAtom *self, void *) { + PY_TRY + return Symbol::new_(self->atoms->atom(self->range)); + PY_CATCH(nullptr); + } + static PyObject *literal(SymbolicAtom *self, void *) { + PY_TRY + return PyInt_FromLong(self->atoms->literal(self->range)); + PY_CATCH(nullptr); + } + static PyObject *is_fact(SymbolicAtom *self, void *) { + PY_TRY + return cppToPy(self->atoms->fact(self->range)).release(); + PY_CATCH(nullptr); + } + static PyObject *is_external(SymbolicAtom *self, void *) { + PY_TRY + return cppToPy(self->atoms->external(self->range)).release(); + PY_CATCH(nullptr); + } +}; + +PyGetSetDef SymbolicAtom::tp_getset[] = { + {(char *)"symbol", (getter)symbol, nullptr, (char *)R"(The representation of the atom in form of a symbol (Symbol object).)", nullptr}, + {(char *)"literal", (getter)literal, nullptr, (char *)R"(The program literal associated with the atom.)", nullptr}, + {(char *)"is_fact", (getter)is_fact, nullptr, (char *)R"(Wheather the atom is a is_fact.)", nullptr}, + {(char *)"is_external", (getter)is_external, nullptr, (char *)R"(Wheather the atom is an external atom.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr}, +}; + +// {{{1 wrap SymbolicAtomIter + +struct SymbolicAtomIter : ObjectBase { + SymbolicAtoms *atoms; + Gringo::SymbolicAtomIter range; + + static constexpr char const *tp_type = "SymbolicAtomIter"; + static constexpr char const *tp_name = "clingo.SymbolicAtomIter"; + static constexpr char const *tp_doc = "Class to iterate over symbolic atoms."; + + static PyObject *new_(Gringo::SymbolicAtoms &atoms, Gringo::SymbolicAtomIter range) { + Object ret(type.tp_alloc(&type, 0)); + SymbolicAtomIter *self = reinterpret_cast(ret.toPy()); + self->atoms = &atoms; + self->range = range; + return ret.release(); + } + Reference tp_iter() { return *this; } + Object tp_iternext() { + Gringo::SymbolicAtomIter current = range; + if (atoms->valid(current)) { + range = atoms->next(current); + return SymbolicAtom::new_(*atoms, current); + } + else { + PyErr_SetNone(PyExc_StopIteration); + return nullptr; + } + } +}; + +// {{{1 wrap SymbolicAtoms + +struct SymbolicAtoms : ObjectBase { + Gringo::SymbolicAtoms *atoms; + static PyMethodDef tp_methods[]; + static PyGetSetDef tp_getset[]; + + static constexpr char const *tp_type = "SymbolicAtoms"; + static constexpr char const *tp_name = "clingo.SymbolicAtoms"; + static constexpr char const *tp_doc = +R"(This class provides read-only access to the symbolic atoms of the grounder +(the Herbrand base). + +Example: + +p(1). +{ p(3) }. +#external p(1..3). + +q(X) :- p(X). + +#script (python) + +import clingo + +def main(prg): + prg.ground([("base", [])]) + print "universe:", len(prg.symbolic_atoms) + for x in prg.symbolic_atoms: + print x.atom, x.is_fact, x.is_external + print "p(2) is in domain:", prg.symbolic_atoms[clingo.Function("p", [3])] is not None + print "p(4) is in domain:", prg.symbolic_atoms[clingo.Function("p", [6])] is not None + print "domain of p/1:" + for x in prg.symbolic_atoms.by_signature(("p", 1)): + print x.atom, x.is_fact, x.is_external + print "signatures:", prg.symbolic_atoms.signatures + +#end. + +Expected Output: + +universe: 6 +p(1) True False +p(3) False False +p(2) False True +q(1) True False +q(3) False False +q(2) False False +p(2) is in domain: True +p(4) is in domain: False +domain of p/1: +p(1) True False +p(3) False False +p(2) False True +signatures: [('p', 1), ('q', 1)])"; + + static PyObject *new_(Gringo::SymbolicAtoms &atoms) { + Object ret(type.tp_alloc(&type, 0)); + if (!ret.valid()) { return nullptr; } + SymbolicAtoms *self = reinterpret_cast(ret.toPy()); + self->atoms = &atoms; + return ret.release(); + } + + Py_ssize_t mp_length() { + return atoms->length(); + } + + Object tp_iter() { return SymbolicAtomIter::new_(*atoms, atoms->begin()); } + + Object mp_subscript(Reference key) { + Gringo::Symbol atom; + pyToCpp(key, atom); + Gringo::SymbolicAtomIter range = atoms->lookup(atom); + if (atoms->valid(range)) { return SymbolicAtom::new_(*atoms, range); } + else { Py_RETURN_NONE; } + } + + static PyObject* by_signature(SymbolicAtoms *self, PyObject *pyargs, PyObject *pykwds) { + PY_TRY + char const *name; + int arity; + PyObject *pos = Py_True; + char const *kwlist[] = {"name", "arity", "positive"}; + if (!PyArg_ParseTupleAndKeywords(pyargs, pykwds, "si|O", const_cast(kwlist), &name, &arity, &pos)) { return nullptr; } + Gringo::SymbolicAtomIter range = self->atoms->begin(Sig(name, arity, !pyToCpp(pos))); + return SymbolicAtomIter::new_(*self->atoms, range); + PY_CATCH(nullptr); + } + + static PyObject* signatures(SymbolicAtoms *self, void *) { + PY_TRY + auto ret = self->atoms->signatures(); + Object pyRet = PyList_New(ret.size()); + int i = 0; + for (auto &sig : ret) { + Object pos = cppToPy(!sig.sign()); + Object pySig = Py_BuildValue("(siO)", sig.name().c_str(), (int)sig.arity(), pos.toPy()); + if (PyList_SetItem(pyRet.toPy(), i, pySig.release()) < 0) { return nullptr; } + ++i; + } + return pyRet.release(); + PY_CATCH(nullptr); + } +}; + +PyMethodDef SymbolicAtoms::tp_methods[] = { + {"by_signature", (PyCFunction)by_signature, METH_KEYWORDS | METH_VARARGS, +R"(by_signature(self, name, arity, positive) -> SymbolicAtomIter + +Return an iterator over the symbolic atoms with the given signature. + +Arguments: +name -- the name of the signature +arity -- the arity of the signature +positive -- the sign of the signature +)"}, + {nullptr, nullptr, 0, nullptr} +}; + +PyGetSetDef SymbolicAtoms::tp_getset[] = { + {(char *)"signatures", (getter)signatures, nullptr, (char *) +R"(The list of predicate signatures (triples of names, arities, and Booleans) +occurring in the program. A true Boolean stands for a positive signature.)" + , nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap PropagateInit + +struct PropagateInit : ObjectBase { + Gringo::PropagateInit *init; + static constexpr char const *tp_type = "PropagateInit"; + static constexpr char const *tp_name = "clingo.PropagateInit"; + static constexpr char const *tp_doc = R"( +Object that is used to initialize a propagator before each solving step. + +Each symbolic or theory atom is uniquely associated with a positive program +atom in form of a positive integer. Program literals additionally have a sign +to represent default negation. Furthermore, there are non-zero integer solver +literals. There is a surjective mapping from program atoms to solver literals. + +All methods called during propagation use solver literals whereas +SymbolicAtom.literal() and TheoryAtom.literal() return program literals. The +function PropagateInit.solver_literal() can be used to map program literals or +condition ids to solver literals.)"; + static PyMethodDef tp_methods[]; + static PyGetSetDef tp_getset[]; + + using ObjectBase::new_; + static PyObject *construct(Gringo::PropagateInit &init) { + PropagateInit *self = new_(); + self->init = &init; + return reinterpret_cast(self); + } + + static PyObject *theoryIter(PropagateInit *self, void *) { + return TheoryAtomIter::new_(&self->init->theory(), 0); + } + + static PyObject *symbolicAtoms(PropagateInit *self, void *) { + return SymbolicAtoms::new_(self->init->getDomain()); + } + + static PyObject *numThreads(PropagateInit *self, void *) { + PY_TRY + return PyInt_FromLong(self->init->threads()); + PY_CATCH(nullptr); + } + + static PyObject *mapLit(PropagateInit *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + Lit_t r = self->init->mapLit(l); + return PyInt_FromLong(r); + PY_CATCH(nullptr); + } + + static PyObject *addWatch(PropagateInit *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + self->init->addWatch(l); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } +}; + +PyMethodDef PropagateInit::tp_methods[] = { + {"add_watch", (PyCFunction)addWatch, METH_O, R"(add_watch(self, lit) -> None + +Add a watch for the solver literal in the given phase.)"}, + {"solver_literal", (PyCFunction)mapLit, METH_O, R"(solver_literal(self, lit) -> int + +Map the given program literal or condition id to its solver literal.)"}, + {nullptr, nullptr, 0, nullptr} +}; + +PyGetSetDef PropagateInit::tp_getset[] = { + {(char *)"symbolic_atoms", (getter)symbolicAtoms, nullptr, (char *)R"(The symbolic atoms captured by a SymbolicAtoms object.)", nullptr}, + {(char *)"theory_atoms", (getter)theoryIter, nullptr, (char *)R"(A TheoryAtomIter object to iterate over all theory atoms.)", nullptr}, + {(char *)"number_of_threads", (getter)numThreads, nullptr, (char *) R"(The number of solver threads used in the corresponding solve call.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap Assignment + +struct Assignment : ObjectBase { + Potassco::AbstractAssignment const *assign; + static constexpr char const *tp_type = "Assignment"; + static constexpr char const *tp_name = "clingo.Assignment"; + static constexpr char const *tp_doc = R"(Object to inspect the (parital) assignment of an associated solver. + +Assigns truth values to solver literals. Each solver literal is either true, +false, or undefined, represented by the python constants True, False, or None, +respectively.)"; + static PyMethodDef tp_methods[]; + static PyGetSetDef tp_getset[]; + + static PyObject *construct(Potassco::AbstractAssignment const &assign) { + Assignment *self = new_(); + self->assign = &assign; + return reinterpret_cast(self); + } + + static PyObject *hasConflict(Assignment *self) { + PY_TRY + return cppToPy(self->assign->hasConflict()).release(); + PY_CATCH(nullptr); + } + + static PyObject *decisionLevel(Assignment *self, void *) { + PY_TRY + return PyInt_FromLong(self->assign->level()); + PY_CATCH(nullptr); + } + + static PyObject *hasLit(Assignment *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + return cppToPy(self->assign->hasLit(l)).release(); + PY_CATCH(nullptr); + } + + static PyObject *level(Assignment *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + return PyInt_FromLong(self->assign->level(l)); + PY_CATCH(nullptr); + } + + static PyObject *decision(Assignment *self, PyObject *level) { + PY_TRY + auto l = pyToCpp(level); + return PyInt_FromLong(self->assign->decision(l)); + PY_CATCH(nullptr); + } + + static PyObject *isFixed(Assignment *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + return cppToPy(self->assign->isFixed(l)).release(); + PY_CATCH(nullptr); + } + + static PyObject *truthValue(Assignment *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + Potassco::Value_t val = self->assign->value(l); + if (val == Potassco::Value_t::False){ return cppToPy(false).release(); } + if (val == Potassco::Value_t::True) { return cppToPy(true).release(); } + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + + static PyObject *isTrue(Assignment *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + return cppToPy(self->assign->isTrue(l)).release(); + PY_CATCH(nullptr); + } + + static PyObject *isFalse(Assignment *self, PyObject *lit) { + PY_TRY + auto l = pyToCpp(lit); + return cppToPy(self->assign->isFalse(l)).release(); + PY_CATCH(nullptr); + } +}; + +PyMethodDef Assignment::tp_methods[] = { + {"has_literal", (PyCFunction)hasLit, METH_O, R"(has_literal(self, lit) -> bool + +Determine if the literal is valid in this solver.)"}, + {"value", (PyCFunction)truthValue, METH_O, R"(value(self, lit) -> bool or None + +The truth value of the given literal or None if it has none.)"}, + {"level", (PyCFunction)level, METH_O, R"(level(self, lit) -> int + +The decision level of the given literal. + +Note that the returned value is only meaningful if the literal is assigned - +i.e., value(lit) is not None.)"}, + {"is_fixed", (PyCFunction)isFixed, METH_O, R"(is_fixed(self, lit) -> bool + +Determine if the literal is assigned on the top level.)"}, + {"is_true", (PyCFunction)isTrue, METH_O, R"(is_true(self, lit) -> bool + +Determine if the literal is true.)"}, + {"is_false", (PyCFunction)isFalse, METH_O, R"(is_false(self, lit) -> bool + +Determine if the literal is false.)"}, + {"decision", (PyCFunction)decision, METH_O, R"(decision(self, level) -> int + + Return the decision literal of the given level.)"}, + {nullptr, nullptr, 0, nullptr} +}; + +PyGetSetDef Assignment::tp_getset[] = { + {(char *)"has_conflict", (getter)hasConflict, nullptr, (char *)R"(True if the current assignment is conflicting.)", nullptr}, + {(char *)"decision_level", (getter)decisionLevel, nullptr, (char *)R"(The current decision level.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap PropagateControl + +struct PropagateControl : ObjectBase { + Potassco::AbstractSolver* ctl; + static constexpr char const *tp_type = "PropagateControl"; + static constexpr char const *tp_name = "clingo.PropagateControl"; + static constexpr char const *tp_doc = "This object can be used to add clauses and propagate literals."; + static PyMethodDef tp_methods[]; + static PyGetSetDef tp_getset[]; + + using ObjectBase::new_; + static PyObject *construct(Potassco::AbstractSolver &ctl) { + PropagateControl *self = new_(); + self->ctl = &ctl; + return reinterpret_cast(self); + } + + static PyObject *id(PropagateControl *self, void *) { + return PyInt_FromLong(self->ctl->id()); + } + + static PyObject *addClauseOrNogood(PropagateControl *self, PyObject *pyargs, PyObject *pykwds, bool invert) { + PY_TRY + static char const *kwlist[] = {"clause", "tag", "lock", nullptr}; + PyObject *clause; + PyObject *pyTag = Py_False; + PyObject *pyLock = Py_False; + if (!PyArg_ParseTupleAndKeywords(pyargs, pykwds, "O|OO", const_cast(kwlist), &clause, &pyTag, &pyLock)) { return nullptr; } + auto lits = pyToCpp>(clause); + if (invert) { + for (auto &lit : lits) { lit = -lit; } + } + unsigned type = 0; + if (pyToCpp(pyTag)) { type |= Potassco::Clause_t::Volatile; } + if (pyToCpp(pyLock)) { type |= Potassco::Clause_t::Static; } + return cppToPy(doUnblocked([self, &lits, type](){ return self->ctl->addClause(Potassco::toSpan(lits), static_cast(type)); })).release(); + PY_CATCH(nullptr); + } + + static PyObject *addNogood(PropagateControl *self, PyObject *pyargs, PyObject *pykwds) { + return addClauseOrNogood(self, pyargs, pykwds, true); + } + + static PyObject *addClause(PropagateControl *self, PyObject *pyargs, PyObject *pykwds) { + return addClauseOrNogood(self, pyargs, pykwds, false); + } + + static PyObject *propagate(PropagateControl *self) { + PY_TRY + return cppToPy(doUnblocked([self](){ return self->ctl->propagate(); })).release(); + PY_CATCH(nullptr); + } + + Object add_literal() { + return cppToPy(ctl->addVariable()); + } + + Object add_watch(Reference pyLit) { + ctl->addWatch(pyToCpp(pyLit)); + return None(); + } + + Object remove_watch(Reference pyLit) { + ctl->addWatch(pyToCpp(pyLit)); + return None(); + } + + Object has_watch(Reference pyLit) { + return cppToPy(ctl->hasWatch(pyToCpp(pyLit))); + } + + static PyObject *assignment(PropagateControl *self, void *) { + return Assignment::construct(self->ctl->assignment()); + } +}; + +PyMethodDef PropagateControl::tp_methods[] = { + {"add_literal", to_function<&PropagateControl::add_literal>(), METH_NOARGS, R"(add_literal(self) -> int + +Adds a new positive volatile literal to the underlying solver thread. + +The literal is only valid within the current solving step and solver thread. +All volatile literals and clauses involving a volatile literal are deleted +after the current search.)"}, + {"add_watch", to_function<&PropagateControl::add_watch>(), METH_O, R"(add_watch(self, literal) -> None +Add a watch for the solver literal in the given phase. + +Unlike PropagateInit.add_watch() this does not add a watch to all solver +threads but just the current one. + +Arguments: +literal -- the target literal)"}, + {"has_watch", to_function<&PropagateControl::has_watch>(), METH_O, R"(has_watch(self, literal) -> bool +Check whether a literal is watched in the current solver thread. + +Arguments: +literal -- the target literal)"}, + {"remove_watch", to_function<&PropagateControl::remove_watch>(), METH_O, R"(remove_watch(self, literal) -> None +Removes the watch (if any) for the given solver literal. + +Similar to PropagateInit.add_watch() this just removes the watch in the current +solver thread. + +Arguments: +literal -- the target literal)"}, + {"add_clause", (PyCFunction)addClause, METH_KEYWORDS | METH_VARARGS, R"(add_clause(self, clause, tag, lock) -> bool + +Add the given clause to the solver. + +This method returns False if the current propagation must be stopped. + +Arguments: +clause -- sequence of solver literals + +Keyword Arguments: +tag -- clause applies only in the current solving step + (Default: False) +lock -- exclude clause from the solver's regular clause deletion policy + (Default: False))"}, + {"add_nogood", (PyCFunction)addNogood, METH_KEYWORDS | METH_VARARGS, R"(add_nogood(self, clause, tag, lock) -> bool +Equivalent to self.add_clause([-lit for lit in clause], tag, lock).)"}, + {"propagate", (PyCFunction)propagate, METH_NOARGS, R"(propagate(self) -> bool + +Propagate implied literals.)"}, + {nullptr, nullptr, 0, nullptr} +}; + +PyGetSetDef PropagateControl::tp_getset[] = { + {(char *)"thread_id", (getter)id, nullptr, (char *)R"(The numeric id of the current solver thread.)", nullptr}, + {(char *)"assignment", (getter)assignment, nullptr, (char *)R"(The partial assignment of the current solver thread.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap Propagator + +class Propagator : public Gringo::Propagator { +public: + Propagator(Reference tp) : tp_(tp) {} + void init(Gringo::PropagateInit &init) override { + PyBlock block; + PY_TRY + Object i = PropagateInit::construct(init); + Object n = PyString_FromString("init"); + Object ret = PyObject_CallMethodObjArgs(tp_.toPy(), n.toPy(), i.toPy(), nullptr); + PY_HANDLE("Propagator::init", "error during initialization") + } + void propagate(Potassco::AbstractSolver &solver, Potassco::LitSpan const &changes) override { + PyBlock block; + PY_TRY + if (!PyObject_HasAttrString(tp_.toPy(), "propagate")) { return; } + Object c = PropagateControl::construct(solver); + Object l = cppToPy(changes); + Object n = PyString_FromString("propagate"); + Object ret = PyObject_CallMethodObjArgs(tp_.toPy(), n.toPy(), c.toPy(), l.toPy(), nullptr); + PY_HANDLE("Propagator::propagate", "error during propagation") + } + void undo(Potassco::AbstractSolver const &solver, Potassco::LitSpan const &undo) override { + PyBlock block; + PY_TRY + if (!PyObject_HasAttrString(tp_.toPy(), "undo")) { return; } + Object i = PyInt_FromLong(solver.id()); + Object a = Assignment::construct(solver.assignment()); + Object l = cppToPy(undo); + Object n = PyString_FromString("undo"); + Object ret = PyObject_CallMethodObjArgs(tp_.toPy(), n.toPy(), i.toPy(), a.toPy(), l.toPy(), nullptr); + PY_HANDLE("Propagator::undo", "error during undo") + } + void check(Potassco::AbstractSolver &solver) override { + PyBlock block; + PY_TRY + if (!PyObject_HasAttrString(tp_.toPy(), "check")) { return; } + Object c = PropagateControl::construct(solver); + Object n = PyString_FromString("check"); + Object ret = PyObject_CallMethodObjArgs(tp_.toPy(), n.toPy(), c.toPy(), nullptr); + PY_HANDLE("Propagator::check", "error during check") + } + ~Propagator() noexcept = default; +private: + Object tp_; +}; + +// {{{1 wrap wrap Backend + +struct Backend : ObjectBase { + Gringo::Control *ctl; + Gringo::Backend *backend; + + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "Backend"; + static constexpr char const *tp_name = "clingo.Backend"; + static constexpr char const *tp_doc = + R"(Backend object providing a low level interface to extend a logic program." + +This class provides an interface that allows for adding statements in ASPIF +format.)"; + + static PyObject *new_(Gringo::Control &ctl) { + PY_TRY + auto *backend = ctl.backend(); + if (!backend) { + PyErr_Format(PyExc_RuntimeError, "backend not available"); + return nullptr; + } + Object ret(type.tp_alloc(&type, 0)); + Backend *self = reinterpret_cast(ret.toPy()); + self->ctl = &ctl; + self->backend = backend; + return ret.release(); + PY_CATCH(nullptr); + } + + static PyObject *addAtom(Backend *self) { + PY_TRY + return PyInt_FromLong(self->ctl->addProgramAtom()); + PY_CATCH(nullptr); + } + + static PyObject *addRule(Backend *self, PyObject *pyargs, PyObject *pykwds) { + PY_TRY + static char const *kwlist[] = {"head", "body", "choice", nullptr}; + PyObject *pyHead = nullptr; + PyObject *pyBody = nullptr; + PyObject *pyChoice = Py_False; + if (!PyArg_ParseTupleAndKeywords(pyargs, pykwds, "O|OO", const_cast(kwlist), &pyHead, &pyBody, &pyChoice)) { return nullptr; } + Gringo::BackendAtomVec head; + pyToCpp(pyHead, head); + Gringo::BackendLitVec body; + if (pyBody) { pyToCpp(pyBody, body); } + bool choice = pyToCpp(pyChoice); + Gringo::outputRule(*self->backend, choice, head, body); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + + static PyObject *addWeightRule(Backend *self, PyObject *pyargs, PyObject *pykwds) { + PY_TRY + static char const *kwlist[] = {"head", "lower", "body", "choice", nullptr}; + PyObject *pyHead = nullptr; + PyObject *pyLower = nullptr; + PyObject *pyBody = nullptr; + PyObject *pyChoice = Py_False; + if (!PyArg_ParseTupleAndKeywords(pyargs, pykwds, "OOO|O", const_cast(kwlist), &pyHead, &pyLower, &pyBody, &pyChoice)) { return nullptr; } + auto head = pyToCpp(pyHead); + auto lower = pyToCpp(pyLower); + auto body = pyToCpp(pyBody); + auto choice = pyToCpp(pyChoice); + Gringo::outputRule(*self->backend, choice, head, lower, body); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } +}; + +PyMethodDef Backend::tp_methods[] = { + // add_atom + {"add_atom", (PyCFunction)addAtom, METH_NOARGS, +R"(add_atom(self) -> Int + +Return a fresh program atom.)"}, + // add_rule + {"add_rule", (PyCFunction)addRule, METH_VARARGS | METH_KEYWORDS, +R"(add_rule(self, head, body, choice) -> None + +Add a disjuntive or choice rule to the program. + +Arguments: +head -- list of program atoms + +Keyword Arguments: +body -- list of program literals (Default: []) +choice -- whether to add a disjunctive or choice rule (Default: False) + +Integrity constraints and normal rules can be added by using an empty or +singleton head list, respectively.)"}, + // add_weight_rule + {"add_weight_rule", (PyCFunction)addWeightRule, METH_VARARGS | METH_KEYWORDS, +R"(add_weight_rule(self, head, lower, body, choice) -> None +Add a disjuntive or choice rule with one weight constraint with a lower bound +in the body to the program. + +Arguments: +head -- list of program atoms +lower -- integer for the lower bound +body -- list of pairs of program literals and weights + +Keyword Arguments: +choice -- whether to add a disjunctive or choice rule (Default: False) +)"}, + {nullptr, nullptr, 0, nullptr} +}; + +// {{{1 wrap AST + +// {{{2 Py + +// {{{3 macros + +#define CREATE1(N,a1) \ +Object create ## N(Reference pyargs, Reference pykwds) { \ + static char const *kwlist[] = {#a1, nullptr}; \ + PyObject* vals[] = { nullptr }; \ + if (!PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), "O", const_cast(kwlist), &vals[0])) { return nullptr; } \ + return AST::new_(ASTType::N, kwlist, vals); \ +} +#define CREATE2(N,a1,a2) \ +Object create ## N(Reference pyargs, Reference pykwds) { \ + static char const *kwlist[] = {#a1,#a2, nullptr}; \ + PyObject* vals[] = { nullptr, nullptr }; \ + if (!PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), "OO", const_cast(kwlist), &vals[0], &vals[1])) { return nullptr; } \ + return AST::new_(ASTType::N, kwlist, vals); \ +} +#define CREATE3(N,a1,a2,a3) \ +Object create ## N(Reference pyargs, Reference pykwds) { \ + static char const *kwlist[] = {#a1, #a2, #a3, nullptr}; \ + PyObject* vals[] = { nullptr, nullptr, nullptr }; \ + if (!PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), "OOO", const_cast(kwlist), &vals[0], &vals[1], &vals[2])) { return nullptr; } \ + return AST::new_(ASTType::N, kwlist, vals); \ +} +#define CREATE4(N,a1,a2,a3,a4) \ +Object create ## N(Reference pyargs, Reference pykwds) { \ + static char const *kwlist[] = {#a1, #a2, #a3, #a4, nullptr}; \ + PyObject* vals[] = { nullptr, nullptr, nullptr, nullptr }; \ + if (!PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), "OOOO", const_cast(kwlist), &vals[0], &vals[1], &vals[2], &vals[3])) { return nullptr; } \ + return AST::new_(ASTType::N, kwlist, vals); \ +} +#define CREATE5(N,a1,a2,a3,a4,a5) \ +Object create ## N(Reference pyargs, Reference pykwds) { \ + static char const *kwlist[] = {#a1, #a2, #a3, #a4, #a5, nullptr}; \ + PyObject* vals[] = { nullptr, nullptr, nullptr, nullptr, nullptr }; \ + if (!PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), "OOOOO", const_cast(kwlist), &vals[0], &vals[1], &vals[2], &vals[3], &vals[4])) { return nullptr; } \ + return AST::new_(ASTType::N, kwlist, vals); \ +} +#define CREATE6(N,a1,a2,a3,a4,a5,a6) \ +Object create ## N(Reference pyargs, Reference pykwds) { \ + static char const *kwlist[] = {#a1, #a2, #a3, #a4, #a5, #a6, nullptr}; \ + PyObject* vals[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; \ + if (!PyArg_ParseTupleAndKeywords(pyargs.toPy(), pykwds.toPy(), "OOOOOO", const_cast(kwlist), &vals[0], &vals[1], &vals[2], &vals[3], &vals[4], &vals[5])) { return nullptr; } \ + return AST::new_(ASTType::N, kwlist, vals); \ +} + +// {{{3 enums + +struct AggregateFunction : EnumType { + static constexpr char const *tp_type = "AggregateFunction"; + static constexpr char const *tp_name = "clingo.ast.AggregateFunction"; + static constexpr char const *tp_doc = +R"(Enumeration of aggegate functions. + +AggregateFunction.Count -- the #count function +AggregateFunction.Sum -- the #sum function +AggregateFunction.SumPlus -- the #sum+ function +AggregateFunction.Min -- the #min function +AggregateFunction.Max -- the #max function)"; + + static constexpr clingo_ast_aggregate_function_t const values[] = { + clingo_ast_aggregate_function_count, + clingo_ast_aggregate_function_sum, + clingo_ast_aggregate_function_sump, + clingo_ast_aggregate_function_min, + clingo_ast_aggregate_function_max + }; + static constexpr const char * const strings[] = { + "Count", + "Sum", + "SumPlus", + "Min", + "Max", + }; + Object tp_repr() { + switch (static_cast(values[offset])) { + case clingo_ast_aggregate_function_count: { return PyString_FromString("#count"); } + case clingo_ast_aggregate_function_sum: { return PyString_FromString("#sum"); } + case clingo_ast_aggregate_function_sump: { return PyString_FromString("#sum+"); } + case clingo_ast_aggregate_function_min: { return PyString_FromString("#min"); } + case clingo_ast_aggregate_function_max: { return PyString_FromString("#max"); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr clingo_ast_aggregate_function_t const AggregateFunction::values[]; +constexpr const char * const AggregateFunction::strings[]; + +struct ComparisonOperator : EnumType { + static constexpr char const *tp_type = "ComparisonOperator"; + static constexpr char const *tp_name = "clingo.ast.ComparisonOperator"; + static constexpr char const *tp_doc = +R"(Enumeration of comparison operators. + +ComparisonOperator.GreaterThan -- the > operator +ComparisonOperator.LessThan -- the < operator +ComparisonOperator.LessEqual -- the <= operator +ComparisonOperator.GreaterEqual -- the >= operator +ComparisonOperator.NotEqual -- the != operator +ComparisonOperator.Equal -- the = operator)"; + + static constexpr clingo_ast_comparison_operator_t const values[] = { + clingo_ast_comparison_operator_greater_than, + clingo_ast_comparison_operator_less_than, + clingo_ast_comparison_operator_less_equal, + clingo_ast_comparison_operator_greater_equal, + clingo_ast_comparison_operator_not_equal, + clingo_ast_comparison_operator_equal + }; + static constexpr const char * const strings[] = { + "GreaterThan", + "LessThan", + "LessEqual", + "GreaterEqual", + "NotEqual", + "Equal" + }; + Object tp_repr() { + switch (offset) { + case 0: { return PyString_FromString(">"); } + case 1: { return PyString_FromString("<"); } + case 2: { return PyString_FromString("<="); } + case 3: { return PyString_FromString(">="); } + case 4: { return PyString_FromString("!="); } + case 5: { return PyString_FromString("="); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr clingo_ast_comparison_operator_t const ComparisonOperator::values[]; +constexpr const char * const ComparisonOperator::strings[]; + +struct ASTType : EnumType { + enum T { + Id, + Variable, Symbol, UnaryOperation, BinaryOperation, Interval, Function, Pool, + CSPProduct, CSPSum, CSPGuard, + BooleanConstant, SymbolicAtom, Comparison, CSPLiteral, + AggregateGuard, ConditionalLiteral, Aggregate, BodyAggregateElement, BodyAggregate, HeadAggregateElement, HeadAggregate, Disjunction, DisjointElement, Disjoint, + TheorySequence, TheoryFunction, TheoryUnparsedTermElement, TheoryUnparsedTerm, TheoryGuard, TheoryAtomElement, TheoryAtom, + Literal, + TheoryOperatorDefinition, TheoryTermDefinition, TheoryGuardDefinition, TheoryAtomDefinition, TheoryDefinition, + Rule, Definition, ShowSignature, ShowTerm, Minimize, Script, Program, External, Edge, Heuristic, ProjectAtom, ProjectSignature, + }; + static constexpr char const *tp_type = "ASTType"; + static constexpr char const *tp_name = "clingo.ast.ASTType"; + static constexpr char const *tp_doc = +R"(Enumeration of ast node types.)"; + + static constexpr T const values[] = { + Id, + Variable, Symbol, UnaryOperation, BinaryOperation, Interval, Function, Pool, + CSPProduct, CSPSum, CSPGuard, + BooleanConstant, SymbolicAtom, Comparison, CSPLiteral, + AggregateGuard, ConditionalLiteral, Aggregate, BodyAggregateElement, BodyAggregate, HeadAggregateElement, HeadAggregate, Disjunction, DisjointElement, Disjoint, + TheorySequence, TheoryFunction, TheoryUnparsedTermElement, TheoryUnparsedTerm, TheoryGuard, TheoryAtomElement, TheoryAtom, + Literal, + TheoryOperatorDefinition, TheoryTermDefinition, TheoryGuardDefinition, TheoryAtomDefinition, TheoryDefinition, + Rule, Definition, ShowSignature, ShowTerm, Minimize, Script, Program, External, Edge, Heuristic, ProjectAtom, ProjectSignature, + }; + static constexpr const char * const strings[] = { + "Id", + "Variable", "Symbol", "UnaryOperation", "BinaryOperation", "Interval", "Function", "Pool", + "CSPProduct", "CSPSum", "CSPGuard", + "BooleanConstant", "SymbolicAtom", "Comparison", "CSPLiteral", + "AggregateGuard", "ConditionalLiteral", "Aggregate", "BodyAggregateElement", "BodyAggregate", "HeadAggregateElement", "HeadAggregate", "Disjunction", "DisjointElement", "Disjoint", + "TheorySequence", "TheoryFunction", "TheoryUnparsedTermElement", "TheoryUnparsedTerm", "TheoryGuard", "TheoryAtomElement", "TheoryAtom", + "Literal", + "TheoryOperatorDefinition", "TheoryTermDefinition", "TheoryGuardDefinition", "TheoryAtomDefinition", "TheoryDefinition", + "Rule", "Definition", "ShowSignature", "ShowTerm", "Minimize", "Script", "Program", "External", "Edge", "Heuristic", "ProjectAtom", "ProjectSignature", + }; +}; + +constexpr ASTType::T const ASTType::values[]; +constexpr const char * const ASTType::strings[]; + +struct Sign : EnumType { + static constexpr char const *tp_type = "Sign"; + static constexpr char const *tp_name = "clingo.ast.Sign"; + static constexpr char const *tp_doc = +R"(The available signs for literals. + +Sign.None -- +Sign.Negation -- not +Sign.DoubleNegation -- not not)"; + + static constexpr clingo_ast_sign_t const values[] = { + clingo_ast_sign_none, + clingo_ast_sign_negation, + clingo_ast_sign_double_negation + }; + static constexpr const char * const strings[] = { + "None", + "Negation", + "DoubleNegation" + }; + Object tp_repr() { + switch (offset) { + case 0: { return PyString_FromString(""); } + case 1: { return PyString_FromString("not "); } + case 2: { return PyString_FromString("not not "); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr clingo_ast_sign_t const Sign::values[]; +constexpr const char * const Sign::strings[]; + +struct UnaryOperator : EnumType { + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "UnaryOperator"; + static constexpr char const *tp_name = "clingo.ast.UnaryOperator"; + static constexpr char const *tp_doc = +R"(Enumeration of unary operators. + +UnaryOperator.Negation -- bitwise negation +UnaryOperator.Minus -- unary minus and classical negation +UnaryOperator.Absolute -- absolute value +)"; + + static constexpr clingo_ast_unary_operator_t const values[] = { + clingo_ast_unary_operator_absolute, + clingo_ast_unary_operator_minus, + clingo_ast_unary_operator_negation, + }; + static constexpr const char * const strings[] = { + "Absolute", + "Minus", + "Negation", + }; + static PyObject *leftHandSide(UnaryOperator *self) { + switch (static_cast(self->values[self->offset])) { + case clingo_ast_unary_operator_absolute: { return PyString_FromString("|"); } + case clingo_ast_unary_operator_minus: { return PyString_FromString("-"); } + case clingo_ast_unary_operator_negation: { return PyString_FromString("~"); } + } + return PyString_FromString(""); + } + static PyObject *rightHandSide(UnaryOperator *self) { + return self->values[self->offset] == clingo_ast_unary_operator_absolute + ? PyString_FromString("|") + : PyString_FromString(""); + } +}; + +PyMethodDef UnaryOperator::tp_methods[] = { + { "left_hand_side", (PyCFunction)leftHandSide, METH_NOARGS, +R"(left_hand_side(self) -> str + +Left-hand side representation of the operator.)"}, + { "right_hand_side", (PyCFunction)rightHandSide, METH_NOARGS, +R"(right_hand_side(self) -> str + +Right-hand side representation of the operator.)"}, + { nullptr, nullptr, 0, nullptr } +}; + +constexpr clingo_ast_unary_operator_t const UnaryOperator::values[]; +constexpr const char * const UnaryOperator::strings[]; + +struct BinaryOperator : EnumType { + static constexpr char const *tp_type = "BinaryOperator"; + static constexpr char const *tp_name = "clingo.ast.BinaryOperator"; + static constexpr char const *tp_doc = +R"(Enumeration of binary operators. + +BinaryOperator.XOr -- bitwise exclusive or +BinaryOperator.Or -- bitwise or +BinaryOperator.And -- bitwise and +BinaryOperator.Plus -- arithmetic addition +BinaryOperator.Minus -- arithmetic substraction +BinaryOperator.Multiplication -- arithmetic multipilcation +BinaryOperator.Division -- arithmetic division +BinaryOperator.Modulo -- arithmetic modulo +)"; + static constexpr clingo_ast_binary_operator_t const values[] = { + clingo_ast_binary_operator_xor, + clingo_ast_binary_operator_or, + clingo_ast_binary_operator_and, + clingo_ast_binary_operator_plus, + clingo_ast_binary_operator_minus, + clingo_ast_binary_operator_multiplication, + clingo_ast_binary_operator_division, + clingo_ast_binary_operator_modulo, + }; + static constexpr const char * const strings[] = { + "XOr", + "Or", + "And", + "Plus", + "Minus", + "Multiplication", + "Division", + "Modulo", + }; + Object tp_repr() { + switch (offset) { + case 0: { return PyString_FromString("^"); } + case 1: { return PyString_FromString("?"); } + case 2: { return PyString_FromString("&"); } + case 3: { return PyString_FromString("+"); } + case 4: { return PyString_FromString("-"); } + case 5: { return PyString_FromString("*"); } + case 6: { return PyString_FromString("/"); } + case 7: { return PyString_FromString("\\"); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr clingo_ast_binary_operator_t const BinaryOperator::values[]; +constexpr const char * const BinaryOperator::strings[]; + +struct TheorySequenceType : EnumType { + enum T { Set, Tuple, List }; + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "TheorySequenceType"; + static constexpr char const *tp_name = "clingo.ast.TheorySequenceType"; + static constexpr char const *tp_doc = +R"(Enumeration of theory term sequence types. + +TheorySequenceType.Tuple -- sequence enclosed in parenthesis +TheorySequenceType.List -- sequence enclosed in brackets +TheorySequenceType.Set -- sequence enclosed in braces +)"; + + static constexpr T const values[] = { + Set, + Tuple, + List, + }; + static constexpr const char * const strings[] = { + "Set", + "Tuple", + "List", + }; + static PyObject *leftHandSide(TheorySequenceType *self) { + switch (self->values[self->offset]) { + case Set: { return PyString_FromString("{"); } + case Tuple: { return PyString_FromString("("); } + case List: { return PyString_FromString("["); } + } + return PyString_FromString(""); + } + static PyObject *rightHandSide(TheorySequenceType *self) { + switch (self->values[self->offset]) { + case Set: { return PyString_FromString("}"); } + case Tuple: { return PyString_FromString(")"); } + case List: { return PyString_FromString("]"); } + } + return PyString_FromString(""); + } +}; + +PyMethodDef TheorySequenceType::tp_methods[] = { + { "left_hand_side", (PyCFunction)leftHandSide, METH_NOARGS, +R"(left_hand_side(self) -> str + +Left-hand side representation of the sequence.)"}, + { "right_hand_side", (PyCFunction)rightHandSide, METH_NOARGS, +R"(right_hand_side(self) -> str + +Right-hand side representation of the sequence.)"}, + { nullptr, nullptr, 0, nullptr } +}; + +constexpr TheorySequenceType::T const TheorySequenceType::values[]; +constexpr const char * const TheorySequenceType::strings[]; + +struct TheoryOperatorType : EnumType { + static constexpr char const *tp_type = "TheoryOperatorType"; + static constexpr char const *tp_name = "clingo.ast.TheoryOperatorType"; + static constexpr char const *tp_doc = +R"(Enumeration of operator types. + +TheoryOperatorType.Unary -- unary operator +TheoryOperatorType.BinaryLeft -- binary left associative operator +TheoryOperatorType.BinaryRight -- binary right associative operator)"; + + static constexpr clingo_ast_theory_operator_type_t const values[] = { + clingo_ast_theory_operator_type_unary, + clingo_ast_theory_operator_type_binary_left, + clingo_ast_theory_operator_type_binary_right + }; + static constexpr const char * const strings[] = { + "Unary", + "BinaryLeft", + "BinaryRight" + }; + Object tp_repr() { + switch (offset) { + case 0: { return PyString_FromString("unary"); } + case 1: { return PyString_FromString("binary, left"); } + case 2: { return PyString_FromString("binary, right"); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr clingo_ast_theory_operator_type_t const TheoryOperatorType::values[]; +constexpr const char * const TheoryOperatorType::strings[]; + +struct TheoryAtomType : EnumType { + static constexpr char const *tp_type = "TheoryAtomType"; + static constexpr char const *tp_name = "clingo.ast.TheoryAtomType"; + static constexpr char const *tp_doc = +R"(Enumeration of theory atom types. + +TheoryAtomType.Any -- atom can occur anywhere +TheoryAtomType.Body -- atom can only occur in rule bodies +TheoryAtomType.Head -- atom can only occur in rule heads +TheoryAtomType.Directive -- atom can only occrur in facts +)"; + + static constexpr clingo_ast_theory_atom_definition_type_t const values[] = { + clingo_ast_theory_atom_definition_type_any, + clingo_ast_theory_atom_definition_type_body, + clingo_ast_theory_atom_definition_type_head, + clingo_ast_theory_atom_definition_type_directive + }; + static constexpr const char * const strings[] = { + "Any", + "Body", + "Head", + "Directive" + }; + Object tp_repr() { + switch (static_cast(values[offset])) { + case clingo_ast_theory_atom_definition_type_any: { return PyString_FromString("any"); } + case clingo_ast_theory_atom_definition_type_body: { return PyString_FromString("body"); } + case clingo_ast_theory_atom_definition_type_head: { return PyString_FromString("head"); } + case clingo_ast_theory_atom_definition_type_directive: { return PyString_FromString("directive"); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr clingo_ast_theory_atom_definition_type_t const TheoryAtomType::values[]; +constexpr const char * const TheoryAtomType::strings[]; + +struct ScriptType : EnumType { + enum T { Python, Lua }; + static constexpr char const *tp_type = "ScriptType"; + static constexpr char const *tp_name = "clingo.ast.ScriptType"; + static constexpr char const *tp_doc = +R"(Enumeration of theory atom types. + +ScriptType.Python -- python code +ScriptType.Lua -- lua code +)"; + + static constexpr T const values[] = { + Python, + Lua + }; + static constexpr const char * const strings[] = { + "Python", + "Lua", + }; + Object tp_repr() { + switch (values[offset]) { + case Python: { return PyString_FromString("python"); } + case Lua: { return PyString_FromString("lua"); } + } + throw std::logic_error("cannot happen"); + } +}; + +constexpr ScriptType::T const ScriptType::values[]; +constexpr const char * const ScriptType::strings[]; + +// }}}3 + +struct AST : ObjectBase { + ASTType::T type_; + Dict fields_; + List children; + static PyMethodDef tp_methods[]; + static PyGetSetDef tp_getset[]; + static constexpr char const *tp_type = "AST"; + static constexpr char const *tp_name = "clingo.ast.AST"; + static constexpr char const *tp_doc = R"(AST(type, **arguments) -> AST + +Node in the abstract syntax tree. + +Arguments: +type -- value in the enumeration ASTType + +Additionally, the functions takes an arbitrary number of keyword arguments. +These should contain the required fields of the node but can also be set +later. + +AST nodes can be structually compared ignoring the location. + +Note that it is also possible to create AST nodes using one of the functions +provided in this module. +)"; + static PyObject *tp_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { + PY_TRY + AST *self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) { return nullptr; } + new (&self->fields_) Dict(); + new (&self->children) List(nullptr); + Reference pyType; + if (PyArg_ParseTuple(args, "O", &pyType.obj) < 0) { return nullptr; } + self->type_ = enumValue(pyType); + if (kwargs) { + for (auto item : Dict{Reference{kwargs}}.items().iter()) { + self->fields_.setItem(item.getItem(0), item.getItem(1)); + } + } + return reinterpret_cast(self); + PY_CATCH(nullptr); + } + static PyObject *new_(ASTType::T t) { + PY_TRY + AST *self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + new (&self->fields_) Dict(); + new (&self->children) List(nullptr); + self->type_ = t; + return reinterpret_cast(self); + PY_CATCH(nullptr); + } + static PyObject *new_(ASTType::T type, char const **kwlist, PyObject **vals) { + PY_TRY + Object ret = new_(type); + auto jt = vals; + for (auto it = kwlist; *it; ++it) { + ret.setAttr(*it, *jt++); + } + return ret.release(); + PY_CATCH(nullptr); + } + Object childKeys_() { + auto ret = [](std::initializer_list l) { return cppToPy(l); }; + switch (type_) { + case ASTType::Id: { return ret({ }); } + case ASTType::Variable: { return ret({ }); } + case ASTType::Symbol: { return ret({ }); } + case ASTType::UnaryOperation: { return ret({ "argument" }); } + case ASTType::BinaryOperation: { return ret({ "left", "right" }); } + case ASTType::Interval: { return ret({ "left", "right" }); } + case ASTType::Function: { return ret({ "arguments" }); } + case ASTType::Pool: { return ret({ "arguments" }); } + case ASTType::CSPProduct: { return ret({ "coefficient", "variable" }); } + case ASTType::CSPSum: { return ret({ "terms" }); } + case ASTType::CSPGuard: { return ret({ "term", "guards" }); } + case ASTType::BooleanConstant: { return ret({ }); } + case ASTType::SymbolicAtom: { return ret({ "term" }); } + case ASTType::Comparison: { return ret({ "left", "right" }); } + case ASTType::CSPLiteral: { return ret({ "term" }); } + case ASTType::AggregateGuard: { return ret({ "guards" }); } + case ASTType::ConditionalLiteral: { return ret({ "literal", "condition" }); } + case ASTType::Aggregate: { return ret({ "left_guard", "elements", "right_guard" }); } + case ASTType::BodyAggregateElement: { return ret({ "tuple", "condition" }); } + case ASTType::BodyAggregate: { return ret({ "left_guard", "elements", "right_guard" }); } + case ASTType::HeadAggregateElement: { return ret({ "tuple", "condition" }); } + case ASTType::HeadAggregate: { return ret({ "left_guard", "elements", "right_guard" }); } + case ASTType::Disjunction: { return ret({ "elements" }); } + case ASTType::DisjointElement: { return ret({ "tuple", "term", "condition" }); } + case ASTType::Disjoint: { return ret({ "elements" }); } + case ASTType::TheorySequence: { return ret({ "terms" }); } + case ASTType::TheoryFunction: { return ret({ "arguments" }); } + case ASTType::TheoryUnparsedTermElement: { return ret({ "term" }); } + case ASTType::TheoryUnparsedTerm: { return ret({ "elements" }); } + case ASTType::TheoryGuard: { return ret({ "term" }); } + case ASTType::TheoryAtomElement: { return ret({ "tuple", "condition" }); } + case ASTType::TheoryAtom: { return ret({ "term", "elements", "guard" }); } + case ASTType::Literal: { return ret({ "atom" }); } + case ASTType::TheoryOperatorDefinition: { return ret({ }); } + case ASTType::TheoryTermDefinition: { return ret({ "operators" }); } + case ASTType::TheoryGuardDefinition: { return ret({ }); } + case ASTType::TheoryAtomDefinition: { return ret({ "guard" }); } + case ASTType::TheoryDefinition: { return ret({ "terms", "atoms" }); } + case ASTType::Rule: { return ret({ "head", "body" }); } + case ASTType::Definition: { return ret({ "value" }); } + case ASTType::ShowSignature: { return ret({ }); } + case ASTType::ShowTerm: { return ret({ "term", "body" }); } + case ASTType::Minimize: { return ret({ "weight", "priority", "tuple", "body" }); } + case ASTType::Script: { return ret({ }); } + case ASTType::Program: { return ret({ "parameters" }); } + case ASTType::External: { return ret({ "atom", "body" }); } + case ASTType::Edge: { return ret({ "u", "v", "body" }); } + case ASTType::Heuristic: { return ret({ "atom", "body", "bias", "priority", "modifier" }); } + case ASTType::ProjectAtom: { return ret({ "atom", "body" }); } + case ASTType::ProjectSignature: { return ret({ }); } + } + throw std::logic_error("cannot happen"); + } + Object childKeys() { + if (!children.valid()) { children = childKeys_(); } + return children; + } + Object getType() { + return ASTType::getAttr(type_); + } + void setType(Reference value) { + type_ = enumValue(value); + } + void tp_setattro(Reference name, Reference value) { + children = nullptr; + if (PyObject_GenericSetAttr(toPy(), name.toPy(), value.toPy()) < 0) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + fields_.setItem(name, value); + } + else { throw PyException(); } + } + } + Object tp_getattro(Reference name) { + auto ret = PyDict_GetItem(fields_.toPy(), name.toPy()); + Py_XINCREF(ret); + return ret + ? ret + : PyObject_GenericGetAttr(reinterpret_cast(this), name.toPy()); + } + void tp_dealloc() { + fields_.~Dict(); + children.~List(); + } + + Object tp_repr() { + PY_TRY + std::ostringstream out; + switch (type_) { + // {{{3 term + case ASTType::Id: { return fields_.getItem("id").str(); } + case ASTType::Variable: { return fields_.getItem("name").str(); } + case ASTType::Symbol: { return fields_.getItem("symbol").str(); } + case ASTType::UnaryOperation: { + Object unop = fields_.getItem("unary_operator"); + out << unop.call("left_hand_side") << fields_.getItem("argument") << unop.call("right_hand_side"); + break; + } + case ASTType::BinaryOperation: { + out << "(" << fields_.getItem("left") << fields_.getItem("binary_operator") << fields_.getItem("right") << ")"; + break; + } + case ASTType::Interval: { + out << "(" << fields_.getItem("left") << ".." << fields_.getItem("right") << ")"; + break; + } + case ASTType::Function: { + Object name = fields_.getItem("name"), args = fields_.getItem("arguments"); + bool tc = name.size() == 0 && args.size() == 1; + bool ey = name.size() == 0 && args.empty(); + out << (fields_.getItem("external").isTrue() ? "@" : "") << name << printList(args, "(", ",", tc ? ",)" : ")", ey); + break; + } + case ASTType::Pool: { + Object args = fields_.getItem("arguments"); + if (args.empty()) { out << "(1/0)"; } + else { out << printList(args, "(", ";", ")", true); } + break; + } + case ASTType::CSPProduct: { + auto var = fields_.getItem("variable"); + auto coe = fields_.getItem("coefficient"); + if (!var.none()) { out << coe << "$*" << "$" << var; } + else { out << coe; } + break; + } + case ASTType::CSPSum: { + auto terms = fields_.getItem("terms"); + if (terms.empty()) { out << "0"; } + else { out << printList(terms, "", "$+", "", false); } + break; + } + // {{{3 literal + case ASTType::Literal: { + out << fields_.getItem("sign") << fields_.getItem("atom"); + break; + } + case ASTType::BooleanConstant: { + out << (fields_.getItem("value").isTrue() ? "#true" : "#false"); + break; + } + case ASTType::SymbolicAtom: { + out << fields_.getItem("term"); + break; + } + case ASTType::Comparison: { + out << fields_.getItem("left") << fields_.getItem("comparison") << fields_.getItem("right"); + break; + } + case ASTType::CSPGuard: { + out << "$" << fields_.getItem("comparison") << fields_.getItem("term"); + break; + } + case ASTType::CSPLiteral: { + out << fields_.getItem("term") << printList(fields_.getItem("guards"), "", "", "", false); + break; + } + // {{{3 aggregate + case ASTType::AggregateGuard: { + out << "AggregateGuard(" << fields_.getItem("comparison") << ", " << fields_.getItem("term") << ")"; + break; + } + case ASTType::ConditionalLiteral: { + out << fields_.getItem("literal") << printList(fields_.getItem("condition"), " : ", ", ", "", true); + break; + } + case ASTType::Aggregate: { + auto left = fields_.getItem("left_guard"), right = fields_.getItem("right_guard"); + if (!left.none()) { out << left.getAttr("term") << " " << left.getAttr("comparison") << " "; } + out << "{ " << printList(fields_.getItem("elements"), "", "; ", "", false) << " }"; + if (!right.none()) { out << " " << right.getAttr("comparison") << " " << right.getAttr("term"); } + break; + } + case ASTType::BodyAggregateElement: { + out << printList(fields_.getItem("tuple"), "", ",", "", false) << " : " << printList(fields_.getItem("condition"), "", ", ", "", false); + break; + } + case ASTType::BodyAggregate: { + auto left = fields_.getItem("left_guard"), right = fields_.getItem("right_guard"); + if (!left.none()) { out << left.getAttr("term") << " " << left.getAttr("comparison") << " "; } + out << fields_.getItem("function") << " { " << printList(fields_.getItem("elements"), "", "; ", "", false) << " }"; + if (!right.none()) { out << " " << right.getAttr("comparison") << " " << right.getAttr("term"); } + break; + } + case ASTType::HeadAggregateElement: { + out << printList(fields_.getItem("tuple"), "", ",", "", false) << " : " << fields_.getItem("condition"); + break; + } + case ASTType::HeadAggregate: { + auto left = fields_.getItem("left_guard"), right = fields_.getItem("right_guard"); + if (!left.none()) { out << left.getAttr("term") << " " << left.getAttr("comparison") << " "; } + out << fields_.getItem("function") << " { " << printList(fields_.getItem("elements"), "", "; ", "", false) << " }"; + if (!right.none()) { out << " " << right.getAttr("comparison") << " " << right.getAttr("term"); } + break; + } + case ASTType::Disjunction: { + out << printList(fields_.getItem("elements"), "", "; ", "", false); + break; + } + case ASTType::DisjointElement: { + out << printList(fields_.getItem("tuple"), "", ",", "", false) << " : " << fields_.getItem("term") << " : " << printList(fields_.getItem("condition"), "", ",", "", false); + break; + } + case ASTType::Disjoint: { + out << "#disjoint { " << printList(fields_.getItem("elements"), "", "; ", "", false) << " }"; + break; + } + // {{{3 theory atom + case ASTType::TheorySequence: { + auto type = fields_.getItem("sequence_type"), terms = fields_.getItem("terms"); + bool tc = terms.size() == 1 && type == TheorySequenceType::getAttr(TheorySequenceType::Tuple); + out << type.call("left_hand_side") << printList(terms, "", ",", "", true) << (tc ? "," : "") << type.call("right_hand_side"); + break; + } + case ASTType::TheoryFunction: { + auto args = fields_.getItem("arguments"); + out << fields_.getItem("name") << printList(args, "(", ",", ")", !args.empty()); + break; + } + case ASTType::TheoryUnparsedTermElement: { + out << printList(fields_.getItem("operators"), "", " ", " ", false) << fields_.getItem("term"); + break; + } + case ASTType::TheoryUnparsedTerm: { + auto elems = fields_.getItem("elements"); + bool pp = elems.size() != 1 || !elems.getItem(0).getAttr("operators").empty(); + out << (pp ? "(" : "") << printList(elems, "", " ", "", false) << (pp ? ")" : ""); + break; + } + case ASTType::TheoryGuard: { + out << fields_.getItem("operator_name") << " " << fields_.getItem("term"); + break; + } + case ASTType::TheoryAtomElement: { + out << printList(fields_.getItem("tuple"), "", ",", "", false) << " : " << printList(fields_.getItem("condition"), "", ",", "", false); + break; + } + case ASTType::TheoryAtom: { + auto guard = fields_.getItem("guard"); + out << "&" << fields_.getItem("term") << " { " << printList(fields_.getItem("elements"), "", "; ", "", false) << " }"; + if (!guard.none()) { out << " " << guard; } + break; + } + // {{{3 theory definition + case ASTType::TheoryOperatorDefinition: { + out << fields_.getItem("name") << " : " << fields_.getItem("priority") << ", " << fields_.getItem("operator_type"); + break; + } + case ASTType::TheoryTermDefinition: { + out << fields_.getItem("name") << " {\n" << printList(fields_.getItem("operators"), " ", ";\n", "\n", true) << "}"; + break; + } + case ASTType::TheoryGuardDefinition: { + out << "{ " << printList(fields_.getItem("operators"), "", ", ", "", false) << " }, " << fields_.getItem("term"); + break; + } + case ASTType::TheoryAtomDefinition: { + auto guard = fields_.getItem("guard"); + out << "&" << fields_.getItem("name") << "/" << fields_.getItem("arity") << " : " << fields_.getItem("elements"); + if (!guard.none()) { out << ", " << guard; } + out << ", " << fields_.getItem("atom_type"); + break; + } + case ASTType::TheoryDefinition: { + out << "#theory " << fields_.getItem("name") << " {\n"; + bool comma = false; + for (auto y : fields_.getItem("terms").iter()) { + if (comma) { out << ";\n"; } + else { comma = true; } + out << " " << y.getAttr("name") << " {\n" << printList(y.getAttr("operators"), " ", ";\n", "\n", true) << " }"; + } + for (auto y : fields_.getItem("atoms").iter()) { + if (comma) { out << ";\n"; } + else { comma = true; } + out << " " << y; + } + if (comma) { out << "\n"; } + out << "}."; + break; + } + // {{{3 statement + case ASTType::Rule: { + out << fields_.getItem("head") << printBody(fields_.getItem("body"), " :- "); + break; + } + case ASTType::Definition: { + out << "#const " << fields_.getItem("name") << " = " << fields_.getItem("value") << "."; + if (fields_.getItem("is_default").isTrue()) { out << " [default]"; } + break; + } + case ASTType::ShowSignature: { + out << "#show " << (fields_.getItem("csp").isTrue() ? "$" : "") << (fields_.getItem("positive").isTrue() ? "" : "-") << fields_.getItem("name") << "/" << fields_.getItem("arity") << "."; + break; + } + case ASTType::ShowTerm: { + out << "#show " << (fields_.getItem("csp").isTrue() ? "$" : "") << fields_.getItem("term") << printBody(fields_.getItem("body")); + break; + } + case ASTType::Minimize: { + out << printBody(fields_.getItem("body"), ":~ ") << " [" << fields_.getItem("weight") << "@" << fields_.getItem("priority") << printList(fields_.getItem("tuple"), ",", ",", "", false) << "]"; + break; + } + case ASTType::Script: { + std::string s = pyToCpp(fields_.getItem("code")); + if (!s.empty() && s.back() == '\n') { + s.back() = '.'; + } + out << s; + break; + } + case ASTType::Program: { + out << "#program " << fields_.getItem("name") << printList(fields_.getItem("parameters"), "(", ",", ")", false) << "."; + break; + } + case ASTType::External: { + out << "#external " << fields_.getItem("atom") << printBody(fields_.getItem("body")); + break; + } + case ASTType::Edge: { + out << "#edge (" << fields_.getItem("u") << "," << fields_.getItem("v") << ")" << printBody(fields_.getItem("body")); + break; + } + case ASTType::Heuristic: { + out << "#heuristic " << fields_.getItem("atom") << printBody(fields_.getItem("body")) << " [" << fields_.getItem("bias")<< "@" << fields_.getItem("priority") << "," << fields_.getItem("modifier") << "]"; + break; + } + case ASTType::ProjectAtom: { + out << "#project " << fields_.getItem("atom") << printBody(fields_.getItem("body")); + break; + } + case ASTType::ProjectSignature: { + out << "#project " << (fields_.getItem("positive").isTrue() ? "" : "-") << fields_.getItem("name") << "/" << fields_.getItem("arity") << "."; + break; + } + // }}}3 + } + return cppToPy(out.str()); + PY_CATCH(nullptr); + } + + List toList() { + List k; + Object loc = PyString_FromString("location"); + for (auto x : keys().iter()) { + if (x != loc) { k.append(x); } + } + k.sort(); + List ret; + ret.append(ASTType::getAttr(type_)); + for (auto x : k.iter()) { + ret.append(Tuple{x, mp_subscript(x)}); + } + return ret; + } + + Object tp_richcompare(AST &b, int op) { + return toList().richCompare(b.toList(), op); + } + + Py_ssize_t mp_length() { return fields_.length(); } + Object mp_subscript(Reference name) { return fields_.getItem(name); } + void mp_ass_subscript(Reference name, Reference value) { + if (value.valid()) { fields_.setItem(name, value); } + else { fields_.delItem(name); } + } + Object keys() { return fields_.keys(); } + Object values() { return fields_.values(); } + Object items() { return fields_.items(); } + bool sq_contains(Reference value) { return fields_.contains(value); } + Object tp_iter() { return fields_.iter(); } +}; + +PyMethodDef AST::tp_methods[] = { + {"keys", to_function<&AST::keys>(), METH_NOARGS, +R"(keys(self) -> list + +The list of keys of the AST node. +)"}, + {"values", to_function<&AST::values>(), METH_NOARGS, +R"(values(self) -> list + +The list of values of the AST node. +)"}, + {"items", to_function<&AST::items>(), METH_NOARGS, +R"(items(self) -> list + +The list of items of the AST node. +)"}, + {nullptr, nullptr, 0, nullptr} +}; + +PyGetSetDef AST::tp_getset[] = { + {(char*)"child_keys", to_getter<&AST::childKeys>(), nullptr, (char*)"List of names of all AST child nodes.", nullptr}, + {(char*)"type", to_getter<&AST::getType>(), to_setter<&AST::setType>(), (char*)"The type of the node.", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{3 terms + +CREATE2(Id, location, id) +CREATE2(Variable, location, name) +CREATE2(Symbol, location, symbol) +CREATE3(UnaryOperation, location, unary_operator, argument) +CREATE4(BinaryOperation, location, binary_operator, left, right) +CREATE3(Interval, location, left, right) +CREATE4(Function, location, name, arguments, external) +CREATE2(Pool, location, arguments) +CREATE3(CSPProduct, location, coefficient, variable) +CREATE2(CSPSum, location, terms) + +// {{{3 literals + +CREATE1(BooleanConstant, value) +CREATE1(SymbolicAtom, term) +CREATE3(Comparison, comparison, left, right) +CREATE2(CSPGuard, comparison, term) +CREATE3(CSPLiteral, location, term, guards) +CREATE3(Literal, location, sign, atom) + +// {{{3 aggregates + +CREATE2(AggregateGuard, comparison, term) +CREATE3(ConditionalLiteral, location, literal, condition) +CREATE4(Aggregate, location, left_guard, elements, right_guard) +CREATE2(BodyAggregateElement, tuple, condition) +CREATE5(BodyAggregate, location, left_guard, function, elements, right_guard) +CREATE2(HeadAggregateElement, tuple, condition) +CREATE5(HeadAggregate, location, left_guard, function, elements, right_guard) +CREATE2(Disjunction, location, elements) +CREATE4(DisjointElement, location, tuple, term, condition) +CREATE2(Disjoint, location, elements) + +// {{{3 theory atom + +CREATE3(TheorySequence, location, sequence_type, terms) +CREATE3(TheoryFunction, location, name, arguments) +CREATE2(TheoryUnparsedTermElement, operators, term) +CREATE2(TheoryUnparsedTerm, location, elements) +CREATE2(TheoryGuard, operator_name, term) +CREATE2(TheoryAtomElement, tuple, condition) +CREATE4(TheoryAtom, location, term, elements, guard) + +// {{{3 theory definitions + +CREATE4(TheoryOperatorDefinition, location, name, priority, operator_type) +CREATE3(TheoryTermDefinition, location, name, operators) +CREATE2(TheoryGuardDefinition, operators, term) +CREATE6(TheoryAtomDefinition, location, atom_type, name, arity, elements, guard) + +// {{{3 statements + +CREATE3(Rule, location, head, body) +CREATE4(Definition, location, name, value, is_default) +CREATE5(ShowSignature, location, name, arity, positive, csp) +CREATE4(ShowTerm, location, term, body, csp) +CREATE5(Minimize, location, weight, priority, tuple, body) +CREATE3(Script, location, script_type, code) +CREATE3(Program, location, name, parameters) +CREATE3(External, location, atom, body) +CREATE4(Edge, location, u, v, body) +CREATE6(Heuristic, location, atom, body, bias, priority, modifier) +CREATE3(ProjectAtom, location, atom, body) +CREATE4(ProjectSignature, location, name, arity, positive) +CREATE4(TheoryDefinition, location, name, terms, atoms) + +// }}}3 + +// {{{2 C -> Py + +// {{{3 location + +Object cppToPy(clingo_location_t const &l) { + Object dict = PyDict_New(); + auto add = [](char const *n, size_t l, size_t c) -> Object { + Object loc = PyDict_New(); + Object name = cppToPy(n); + if (PyDict_SetItemString(loc.toPy(), "filename", name.toPy()) < 0) { throw PyException(); } + Object line = cppToPy(l); + if (PyDict_SetItemString(loc.toPy(), "line", line.toPy()) < 0) { throw PyException(); } + Object column = cppToPy(c); + if (PyDict_SetItemString(loc.toPy(), "column", column.toPy()) < 0) { throw PyException(); } + return loc; + }; + Object begin = add(l.begin_file, l.begin_line, l.begin_column); + if (PyDict_SetItemString(dict.toPy(), "begin", begin.toPy()) < 0) { throw PyException(); } + Object end = add(l.end_file, l.end_line, l.end_column); + if (PyDict_SetItemString(dict.toPy(), "end", end.toPy()) < 0) { throw PyException(); } + return dict; +} + +// {{{3 terms + +Object cppToPy(clingo_ast_id_t const &id) { + return call(createId, cppToPy(id.location), cppToPy(id.id)); +} + +Object cppToPy(clingo_ast_term_t const &term) { + switch (static_cast(term.type)) { + case clingo_ast_term_type_symbol: { + return call(createSymbol, cppToPy(term.location), cppToPy(Gringo::Symbol{term.symbol})); + } + case clingo_ast_term_type_variable: { + return call(createVariable, cppToPy(term.location), cppToPy(term.variable)); + } + case clingo_ast_term_type_unary_operation: { + auto &op = *term.unary_operation; + return call(createUnaryOperation, cppToPy(term.location), UnaryOperator::getAttr(op.unary_operator), cppToPy(op.argument)); + } + case clingo_ast_term_type_binary_operation: { + auto &op = *term.binary_operation; + return call(createBinaryOperation, cppToPy(term.location), BinaryOperator::getAttr(op.binary_operator), cppToPy(op.left), cppToPy(op.right)); + } + case clingo_ast_term_type_interval: { + auto &x = *term.interval; + return call(createInterval, cppToPy(term.location), cppToPy(x.left), cppToPy(x.right)); + } + case clingo_ast_term_type_external_function: + case clingo_ast_term_type_function: { + auto &x = *term.function; + return call(createFunction, cppToPy(term.location), cppToPy(x.name), cppToPy(x.arguments, x.size), cppToPy(term.type == clingo_ast_term_type_external_function)); + } + case clingo_ast_term_type_pool: { + auto &x = *term.pool; + return call(createPool, cppToPy(term.location), cppToPy(x.arguments, x.size)); + } + } + throw std::logic_error("cannot happen"); +} + +Object cppToPy(clingo_ast_term_t const *term) { + return term ? cppToPy(*term) : None(); +} + +// csp + +Object cppToPy(clingo_ast_csp_product_term const &term) { + return call(createCSPProduct, cppToPy(term.location), cppToPy(term.coefficient), cppToPy(term.variable)); +} + +Object cppToPy(clingo_ast_csp_sum_term_t const &term) { + return call(createCSPSum, cppToPy(term.location), cppToPy(term.terms, term.size)); +} + +// theory + +Object cppToPy(clingo_ast_theory_term_t const &term); +Object cppToPy(clingo_ast_theory_unparsed_term_element_t const &term) { + return call(createTheoryUnparsedTermElement, cppToPy(term.operators, term.size), cppToPy(term.term)); +} + +Object cppToPy(clingo_ast_theory_term_t const &term) { + switch (static_cast(term.type)) { + case clingo_ast_theory_term_type_symbol: { + return call(createSymbol, cppToPy(term.location), cppToPy(Gringo::Symbol{term.symbol})); + } + case clingo_ast_theory_term_type_variable: { + return call(createVariable, cppToPy(term.location), cppToPy(term.variable)); + } + case clingo_ast_theory_term_type_list: { + auto &x = *term.list; + return call(createTheorySequence, cppToPy(term.location), TheorySequenceType::getAttr(TheorySequenceType::List), cppToPy(x.terms, x.size)); + } + case clingo_ast_theory_term_type_set: { + auto &x = *term.list; + return call(createTheorySequence, cppToPy(term.location), TheorySequenceType::getAttr(TheorySequenceType::Set), cppToPy(x.terms, x.size)); + } + case clingo_ast_theory_term_type_tuple: { + auto &x = *term.list; + return call(createTheorySequence, cppToPy(term.location), TheorySequenceType::getAttr(TheorySequenceType::Tuple), cppToPy(x.terms, x.size)); + } + case clingo_ast_theory_term_type_function: { + auto &x = *term.function; + return call(createTheoryFunction, cppToPy(term.location), cppToPy(x.name), cppToPy(x.arguments, x.size)); + } + case clingo_ast_theory_term_type_unparsed_term: { + auto &x = *term.unparsed_term; + return call(createTheoryUnparsedTerm, cppToPy(term.location), cppToPy(x.elements, x.size)); + } + } + throw std::logic_error("cannot happen"); +} + +// {{{3 literal + +Object cppToPy(clingo_ast_csp_guard_t const &guard) { + return call(createCSPGuard, ComparisonOperator::getAttr(guard.comparison), cppToPy(guard.term)); +} + +Object cppToPy(clingo_ast_literal_t const &lit) { + switch (static_cast(lit.type)) { + case clingo_ast_literal_type_boolean: { + return call(createLiteral, cppToPy(lit.location), Sign::getAttr(lit.sign), call(createBooleanConstant, cppToPy(lit.boolean))); + } + case clingo_ast_literal_type_symbolic: { + return call(createLiteral, cppToPy(lit.location), Sign::getAttr(lit.sign), call(createSymbolicAtom, cppToPy(*lit.symbol))); + } + case clingo_ast_literal_type_comparison: { + auto &c = *lit.comparison; + return call(createLiteral, cppToPy(lit.location), Sign::getAttr(lit.sign), call(createComparison, ComparisonOperator::getAttr(c.comparison), cppToPy(c.left), cppToPy(c.right))); + } + case clingo_ast_literal_type_csp: { + auto &c = *lit.csp_literal; + return call(createCSPLiteral, cppToPy(lit.location), cppToPy(c.term), cppToPy(c.guards, c.size)); + } + } + throw std::logic_error("cannot happen"); +} + +// {{{3 aggregates + +Object cppToPy(clingo_ast_aggregate_guard_t const *guard) { + return guard + ? Object{call(createAggregateGuard, ComparisonOperator::getAttr(guard->comparison), cppToPy(guard->term))} + : None(); +} + +Object cppToPy(clingo_ast_conditional_literal_t const &lit) { + clingo_location_t loc = lit.literal.location; + if (lit.size > 0) { + loc.end_file = lit.condition[lit.size-1].location.end_file; + loc.end_line = lit.condition[lit.size-1].location.end_line; + loc.end_column = lit.condition[lit.size-1].location.end_column; + } + return call(createConditionalLiteral, cppToPy(loc), cppToPy(lit.literal), cppToPy(lit.condition, lit.size)); +} + +Object cppToPy(clingo_location_t loc, clingo_ast_aggregate_t const &aggr) { + return call(createAggregate, cppToPy(loc), cppToPy(aggr.left_guard), cppToPy(aggr.elements, aggr.size), cppToPy(aggr.right_guard)); +} + +// theory atom + +Object cppToPy(clingo_ast_theory_guard_t const *guard) { + return guard + ? Object{call(createTheoryGuard, cppToPy(guard->operator_name), cppToPy(guard->term))} + : None(); +} + +Object cppToPy(clingo_ast_theory_atom_element_t const &elem) { + return call(createTheoryAtomElement, cppToPy(elem.tuple, elem.tuple_size), cppToPy(elem.condition, elem.condition_size)); +} + +Object cppToPy(clingo_location_t loc, clingo_ast_theory_atom_t const &atom) { + return call(createTheoryAtom, cppToPy(loc), cppToPy(atom.term), cppToPy(atom.elements, atom.size), cppToPy(atom.guard)); +} + +// disjoint + +Object cppToPy(clingo_ast_disjoint_element_t const &elem) { + return call(createDisjointElement, cppToPy(elem.location), cppToPy(elem.tuple, elem.tuple_size), cppToPy(elem.term), cppToPy(elem.condition, elem.condition_size)); +} + +// head aggregates + +Object cppToPy(clingo_ast_head_aggregate_element_t const &elem) { + return call(createHeadAggregateElement, cppToPy(elem.tuple, elem.tuple_size), cppToPy(elem.conditional_literal)); +} + +// body aggregates + +Object cppToPy(clingo_ast_body_aggregate_element_t const &elem) { + return call(createBodyAggregateElement, cppToPy(elem.tuple, elem.tuple_size), cppToPy(elem.condition, elem.condition_size)); +} + +// {{{3 head literal + +Object cppToPy(clingo_ast_head_literal_t const &head) { + switch (static_cast(head.type)) { + case clingo_ast_head_literal_type_literal: { + return cppToPy(*head.literal); + } + case clingo_ast_head_literal_type_disjunction: { + auto &d = *head.disjunction; + return call(createDisjunction, cppToPy(head.location), cppToPy(d.elements, d.size)); + } + case clingo_ast_head_literal_type_aggregate: { + return cppToPy(head.location, *head.aggregate); + } + case clingo_ast_head_literal_type_head_aggregate: { + auto &a = *head.head_aggregate; + return call(createHeadAggregate, cppToPy(head.location), cppToPy(a.left_guard), AggregateFunction::getAttr(a.function), cppToPy(a.elements, a.size), cppToPy(a.right_guard)); + } + case clingo_ast_head_literal_type_theory_atom: { + return cppToPy(head.location, *head.theory_atom); + } + } + throw std::logic_error("cannot happen"); +} + +// {{{3 body literal + +Object cppToPy(clingo_ast_body_literal_t const &body) { + switch (static_cast(body.type)) { + case clingo_ast_body_literal_type_literal: { + assert(body.sign == clingo_ast_sign_none); + return cppToPy(*body.literal); + } + case clingo_ast_body_literal_type_conditional: { + assert(body.sign == clingo_ast_sign_none); + return cppToPy(*body.conditional); + } + case clingo_ast_body_literal_type_aggregate: { + return call(createLiteral, cppToPy(body.location), Sign::getAttr(body.sign), cppToPy(body.location, *body.aggregate)); + } + case clingo_ast_body_literal_type_body_aggregate: { + auto &a = *body.body_aggregate; + return call(createLiteral, cppToPy(body.location), Sign::getAttr(body.sign), call(createBodyAggregate, cppToPy(body.location), cppToPy(a.left_guard), AggregateFunction::getAttr(a.function), cppToPy(a.elements, a.size), cppToPy(a.right_guard))); + } + case clingo_ast_body_literal_type_theory_atom: { + return call(createLiteral, cppToPy(body.location), Sign::getAttr(body.sign), cppToPy(body.location, *body.theory_atom)); + } + case clingo_ast_body_literal_type_disjoint: { + auto &d = *body.disjoint; + return call(createLiteral, cppToPy(body.location), Sign::getAttr(body.sign), call(createDisjoint, cppToPy(body.location), cppToPy(d.elements, d.size))); + } + } + throw std::logic_error("cannot happen"); +} + +// {{{3 statement + +Object cppToPy(clingo_ast_theory_operator_definition_t const &def) { + return call(createTheoryOperatorDefinition, cppToPy(def.location), cppToPy(def.name), cppToPy(def.priority), TheoryOperatorType::getAttr(def.type)); +} + +Object cppToPy(clingo_ast_theory_guard_definition_t const *def) { + return def + ? Object{call(createTheoryGuardDefinition, cppToPy(def->operators, def->size), cppToPy(def->term))} + : None(); +} + +Object cppToPy(clingo_ast_theory_term_definition_t const &def) { + return call(createTheoryTermDefinition, cppToPy(def.location), cppToPy(def.name), cppToPy(def.operators, def.size)); +} + +Object cppToPy(clingo_ast_theory_atom_definition_t const &def) { + return call(createTheoryAtomDefinition, cppToPy(def.location), TheoryAtomType::getAttr(def.type), cppToPy(def.name), cppToPy(def.arity), cppToPy(def.elements), cppToPy(def.guard)); +} + +Object cppToPy(clingo_ast_statement_t const &stm) { + switch (static_cast(stm.type)) { + case clingo_ast_statement_type_rule: { + return call(createRule, cppToPy(stm.location), cppToPy(stm.rule->head), cppToPy(stm.rule->body, stm.rule->size)); + } + case clingo_ast_statement_type_const: { + return call(createDefinition, cppToPy(stm.location), cppToPy(stm.definition->name), cppToPy(stm.definition->value), cppToPy(stm.definition->is_default)); + } + case clingo_ast_statement_type_show_signature: { + auto sig = Sig(stm.show_signature->signature); + return call(createShowSignature, cppToPy(stm.location), cppToPy(sig.name().c_str()), cppToPy(sig.arity()), cppToPy(!sig.sign()), cppToPy(stm.show_signature->csp)); + } + case clingo_ast_statement_type_show_term: { + return call(createShowTerm, cppToPy(stm.location), cppToPy(stm.show_term->term), cppToPy(stm.show_term->body, stm.show_term->size), cppToPy(stm.show_term->csp)); + } + case clingo_ast_statement_type_minimize: { + auto &min = *stm.minimize; + return call(createMinimize, cppToPy(stm.location), cppToPy(min.weight), cppToPy(min.priority), cppToPy(min.tuple, min.tuple_size), cppToPy(min.body, min.body_size)); + } + case clingo_ast_statement_type_script: { + return call(createScript, cppToPy(stm.location), ScriptType::getAttr(stm.script->type), cppToPy(stm.script->code)); + } + case clingo_ast_statement_type_program: { + return call(createProgram, cppToPy(stm.location), cppToPy(stm.program->name), cppToPy(stm.program->parameters, stm.program->size)); + } + case clingo_ast_statement_type_external: { + return call(createExternal, cppToPy(stm.location), call(createSymbolicAtom, cppToPy(stm.external->atom)), cppToPy(stm.external->body, stm.external->size)); + } + case clingo_ast_statement_type_edge: { + return call(createEdge, cppToPy(stm.location), cppToPy(stm.edge->u), cppToPy(stm.edge->v), cppToPy(stm.edge->body, stm.edge->size)); + } + case clingo_ast_statement_type_heuristic: { + auto &heu = *stm.heuristic; + return call(createHeuristic, cppToPy(stm.location), call(createSymbolicAtom, cppToPy(heu.atom)), cppToPy(heu.body, heu.size), cppToPy(heu.bias), cppToPy(heu.priority), cppToPy(heu.modifier)); + } + case clingo_ast_statement_type_project_atom: { + return call(createProjectAtom, cppToPy(stm.location), call(createSymbolicAtom, cppToPy(stm.project_atom->atom)), cppToPy(stm.project_atom->body, stm.project_atom->size)); + } + case clingo_ast_statement_type_project_atom_signature: { + auto sig = Sig(stm.project_signature); + return call(createProjectSignature, cppToPy(stm.location), cppToPy(sig.name().c_str()), cppToPy(sig.arity()), cppToPy(!sig.sign())); + } + case clingo_ast_statement_type_theory_definition: { + auto &def = *stm.theory_definition; + return call(createTheoryDefinition, cppToPy(stm.location), cppToPy(def.name), cppToPy(def.terms, def.terms_size), cppToPy(def.atoms, def.atoms_size)); + } + } + throw std::logic_error("cannot happen"); +} + +// TODO: consider exposing the logger to python... +Object parseProgram(Reference args, Reference kwds) { + static char const *kwlist[] = {"program", "callback", nullptr}; + Reference str, cb; + ParseTupleAndKeywords(args, kwds, "OO", kwlist, str, cb); + using Data = std::pair; + Data data{cb, std::exception_ptr()}; + handleCError(clingo_parse_program(pyToCpp(str), [](clingo_ast_statement_t const *stm, void *d) -> bool { + auto &data = *static_cast(d); + try { + data.first(cppToPy(*stm)); + return true; + } + catch (...) { + data.second = std::current_exception(); + return false; + } + }, &data, nullptr, nullptr, 20), &data.second); + return None(); +} + +// }}}3 + +// {{{2 Py -> C + +struct ASTToC { + clingo_location_t convLocation(Reference x) { + clingo_location_t ret; + Object begin = x.getItem("begin"); + Object end = x.getItem("end"); + ret.begin_file = convString(begin.getItem("filename")); + ret.begin_line = pyToCpp(begin.getItem("line")); + ret.begin_column = pyToCpp(begin.getItem("column")); + ret.end_file = convString(end.getItem("filename")); + ret.end_line = pyToCpp(end.getItem("line")); + ret.end_column = pyToCpp(end.getItem("column")); + return ret; + } + + char const *convString(Reference x) { + char const *ret; + handleCError(clingo_add_string(pyToCpp(x), &ret)); + return ret; + } + + // {{{3 term + + clingo_ast_id_t convId(Reference x) { + return {convLocation(x.getAttr("location")), convString(x.getAttr("id"))}; + } + + clingo_ast_term_t convTerm(Reference x) { + clingo_ast_term_t ret; + ret.location = convLocation(x.getAttr("location")); + switch (enumValue(x.getAttr("type"))) { + case ASTType::Variable: { + ret.type = clingo_ast_term_type_variable; + ret.variable = convString(x.getAttr("name")); + return ret; + } + case ASTType::Symbol: { + ret.type = clingo_ast_term_type_symbol; + ret.symbol = pyToCpp(x.getAttr("symbol")).rep(); + return ret; + } + case ASTType::UnaryOperation: { + auto unary_operation = create_(); + unary_operation->unary_operator = enumValue(x.getAttr("unary_operator")); + unary_operation->argument = convTerm(x.getAttr("argument")); + ret.type = clingo_ast_term_type_unary_operation; + ret.unary_operation = unary_operation; + return ret; + } + case ASTType::BinaryOperation: { + auto binary_operation = create_(); + binary_operation->binary_operator = enumValue(x.getAttr("binary_operator")); + binary_operation->left = convTerm(x.getAttr("left")); + binary_operation->right = convTerm(x.getAttr("right")); + ret.type = clingo_ast_term_type_binary_operation; + ret.binary_operation = binary_operation; + return ret; + } + case ASTType::Interval: { + auto interval = create_(); + interval->left = convTerm(x.getAttr("left")); + interval->right = convTerm(x.getAttr("right")); + ret.type = clingo_ast_term_type_interval; + ret.interval = interval; + return ret; + } + case ASTType::Function: { + auto function = create_(); + auto args = x.getAttr("arguments"); + function->name = convString(x.getAttr("name")); + function->arguments = convTermVec(args); + function->size = args.size(); + ret.type = x.getAttr("external").isTrue() ? clingo_ast_term_type_external_function : clingo_ast_term_type_function; + ret.function = function; + return ret; + } + case ASTType::Pool: { + auto pool = create_(); + auto args = x.getAttr("arguments"); + pool->arguments = convTermVec(args); + pool->size = args.size(); + ret.type = clingo_ast_term_type_pool; + ret.pool = pool; + return ret; + } + default: { + throw std::runtime_error("term expected"); + } + } + } + + clingo_ast_term_t *convTermVec(Reference x) { + return createArray_(x, &ASTToC::convTerm); + } + + clingo_ast_term_t *convTermOpt(Reference x) { + return !x.none() ? create_(convTerm(x)) : nullptr; + } + + clingo_ast_csp_product_term_t convCSPProduct(Reference x) { + clingo_ast_csp_product_term_t ret; + ret.location = convLocation(x.getAttr("location")); + ret.variable = convTermOpt(x.getAttr("variable")); + ret.coefficient = convTerm(x.getAttr("coefficient")); + return ret; + } + + clingo_ast_csp_sum_term_t convCSPAdd(Reference x) { + clingo_ast_csp_sum_term_t ret; + auto terms = x.getAttr("terms"); + ret.location = convLocation(x.getAttr("location")); + ret.terms = createArray_(terms, &ASTToC::convCSPProduct); + ret.size = terms.size(); + return ret; + } + + clingo_ast_theory_unparsed_term_element_t convTheoryUnparsedTermElement(Reference x) { + auto ops= x.getAttr("operators"); + clingo_ast_theory_unparsed_term_element_t ret; + ret.term = convTheoryTerm(x.getAttr("term")); + ret.operators = createArray_(ops, &ASTToC::convString); + ret.size = ops.size(); + return ret; + } + + clingo_ast_theory_term_t convTheoryTerm(Reference x) { + clingo_ast_theory_term_t ret; + ret.location = convLocation(x.getAttr("location")); + switch (enumValue(x.getAttr("type"))) { + case ASTType::Variable: { + ret.type = clingo_ast_theory_term_type_variable; + ret.variable = convString(x.getAttr("name")); + return ret; + } + case ASTType::Symbol: { + ret.type = clingo_ast_theory_term_type_symbol; + ret.symbol = pyToCpp(x.getAttr("symbol")).rep(); + return ret; + } + case ASTType::TheorySequence: { + auto sequence = create_(); + auto terms = x.getAttr("terms"); + sequence->terms = convTheoryTermVec(terms); + sequence->size = terms.size(); + switch (enumValue(x.getAttr("sequence_type"))) { + case TheorySequenceType::Set: { ret.type = clingo_ast_theory_term_type_set; break; } + case TheorySequenceType::List: { ret.type = clingo_ast_theory_term_type_list; break; } + case TheorySequenceType::Tuple: { ret.type = clingo_ast_theory_term_type_tuple; break; } + } + ret.set = sequence; + return ret; + } + case ASTType::TheoryFunction: { + auto function = create_(); + auto args = x.getAttr("arguments"); + function->name = convString(x.getAttr("name")); + function->arguments = convTheoryTermVec(args); + function->size = args.size(); + ret.type = clingo_ast_theory_term_type_function; + ret.function = function; + return ret; + } + case ASTType::TheoryUnparsedTerm: { + auto unparsed_term = create_(); + auto elems = x.getAttr("elements"); + unparsed_term->elements = createArray_(elems, &ASTToC::convTheoryUnparsedTermElement); + unparsed_term->size = elems.size(); + ret.type = clingo_ast_theory_term_type_unparsed_term; + ret.unparsed_term = unparsed_term; + return ret; + + } + default: { + throw std::runtime_error("theory term expected"); + } + } + return ret; + } + clingo_ast_theory_term_t *convTheoryTermVec(Reference x) { + return createArray_(x, &ASTToC::convTheoryTerm); + } + + // {{{3 literal + + clingo_ast_csp_guard_t convCSPGuard(Reference x) { + clingo_ast_csp_guard_t ret; + ret.comparison = enumValue(x.getAttr("comparison")); + ret.term = convCSPAdd(x.getAttr("term")); + return ret; + } + + clingo_ast_term_t convSymbolicAtom(Reference x) { + return convTerm(x.getAttr("term")); + } + clingo_ast_literal_t convLiteral(Reference x) { + clingo_ast_literal_t ret; + ret.location = convLocation(x.getAttr("location")); + if (enumValue(x.getAttr("type")) == ASTType::CSPLiteral) { + auto csp = create_(); + auto guards = x.getAttr("guards"); + csp->term = convCSPAdd(x.getAttr("term")); + csp->guards = createArray_(guards, &ASTToC::convCSPGuard); + csp->size = guards.size(); + ret.sign = clingo_ast_sign_none; + ret.type = clingo_ast_literal_type_csp; + ret.csp_literal = csp; + return ret; + } + auto atom = x.getAttr("atom"); + ret.sign = enumValue(x.getAttr("sign")); + switch (enumValue(atom.getAttr("type"))) { + case ASTType::BooleanConstant: { + ret.type = clingo_ast_literal_type_boolean; + ret.boolean = pyToCpp(atom.getAttr("value")); + return ret; + } + case ASTType::SymbolicAtom: { + ret.type = clingo_ast_literal_type_symbolic; + ret.symbol = create_(convSymbolicAtom(atom)); + return ret; + } + case ASTType::Comparison: { + auto comparison = create_(); + comparison->comparison = enumValue(atom.getAttr("comparison")); + comparison->left = convTerm(atom.getAttr("left")); + comparison->right = convTerm(atom.getAttr("right")); + ret.type = clingo_ast_literal_type_comparison; + ret.comparison = comparison; + return ret; + } + case ASTType::CSPLiteral: { + } + default: { + throw std::runtime_error("literal expected"); + } + } + } + clingo_ast_literal_t *convLiteralVec(Reference x) { + return createArray_(x, &ASTToC::convLiteral); + } + + // {{{3 aggregates + + clingo_ast_aggregate_guard_t *convAggregateGuardOpt(Reference x) { + return !x.none() + ? create_({enumValue(x.getAttr("comparison")), convTerm(x.getAttr("term"))}) + : nullptr; + } + + clingo_ast_conditional_literal_t convConditionalLiteral(Reference x) { + clingo_ast_conditional_literal_t ret; + auto cond = x.getAttr("condition"); + ret.literal = convLiteral(x.getAttr("literal")); + ret.condition = convLiteralVec(cond); + ret.size = cond.size(); + return ret; + } + + clingo_ast_theory_guard_t *convTheoryGuardOpt(Reference x) { + return !x.none() + ? create_({convString(x.getAttr("operator_name")), convTheoryTerm(x.getAttr("term"))}) + : nullptr; + } + + clingo_ast_theory_atom_element_t convTheoryAtomElement(Reference x) { + clingo_ast_theory_atom_element_t ret; + auto tuple = x.getAttr("tuple"), cond = x.getAttr("condition"); + ret.tuple = convTheoryTermVec(tuple); + ret.tuple_size = tuple.size(); + ret.condition = convLiteralVec(cond); + ret.condition_size = cond.size(); + return ret; + } + + clingo_ast_body_aggregate_element_t convBodyAggregateElement(Reference x) { + clingo_ast_body_aggregate_element_t ret; + auto tuple = x.getAttr("tuple"), cond = x.getAttr("condition"); + ret.tuple = convTermVec(tuple); + ret.tuple_size = tuple.size(); + ret.condition = convLiteralVec(cond); + ret.condition_size = cond.size(); + return ret; + } + + clingo_ast_head_aggregate_element_t convHeadAggregateElement(Reference x) { + clingo_ast_head_aggregate_element_t ret; + auto tuple = x.getAttr("tuple"); + ret.tuple = convTermVec(tuple); + ret.tuple_size = tuple.size(); + ret.conditional_literal = convConditionalLiteral(x.getAttr("condition")); + return ret; + } + + clingo_ast_aggregate_t convAggregate(Reference x) { + clingo_ast_aggregate_t ret; + auto elems = x.getAttr("elements"); + ret.left_guard = convAggregateGuardOpt(x.getAttr("left_guard")); + ret.right_guard = convAggregateGuardOpt(x.getAttr("right_guard")); + ret.size = elems.size(); + ret.elements = createArray_(elems, &ASTToC::convConditionalLiteral); + return ret; + } + + clingo_ast_theory_atom_t convTheoryAtom(Reference x) { + clingo_ast_theory_atom_t ret; + auto elems = x.getAttr("elements"); + ret.term = convTerm(x.getAttr("term")); + ret.guard = convTheoryGuardOpt(x.getAttr("guard")); + ret.elements = createArray_(elems, &ASTToC::convTheoryAtomElement); + ret.size = elems.size(); + return ret; + } + + clingo_ast_disjoint_element_t convDisjointElement(Reference x) { + clingo_ast_disjoint_element_t ret; + auto tuple = x.getAttr("tuple"), cond = x.getAttr("condition"); + ret.location = convLocation(x.getAttr("location")); + ret.tuple = convTermVec(tuple); + ret.tuple_size = tuple.size(); + ret.term = convCSPAdd(x.getAttr("term")); + ret.condition = convLiteralVec(cond); + ret.condition_size = cond.size(); + return ret; + } + + // {{{3 head literal + + clingo_ast_head_literal_t convHeadLiteral(Object x) { + clingo_ast_head_literal_t ret; + ret.location = convLocation(x.getAttr("location")); + switch (enumValue(x.getAttr("type"))) { + case ASTType::CSPLiteral: + case ASTType::Literal: { + ret.type = clingo_ast_head_literal_type_literal; + ret.literal = create_(convLiteral(x)); + return ret; + } + case ASTType::Aggregate: { + ret.type = clingo_ast_head_literal_type_aggregate; + ret.aggregate = create_(convAggregate(x)); + return ret; + } + case ASTType::HeadAggregate: { + auto head_aggregate = create_(); + auto elems = x.getAttr("elements"); + head_aggregate->left_guard = convAggregateGuardOpt(x.getAttr("left_guard")); + head_aggregate->right_guard = convAggregateGuardOpt(x.getAttr("right_guard")); + head_aggregate->function = enumValue(x.getAttr("function")); + head_aggregate->size = elems.size(); + head_aggregate->elements = createArray_(elems, &ASTToC::convHeadAggregateElement); + ret.type = clingo_ast_head_literal_type_head_aggregate; + ret.head_aggregate = head_aggregate; + return ret; + } + case ASTType::Disjunction: { + auto disjunction = create_(); + auto elems = x.getAttr("elements"); + disjunction->size = elems.size(); + disjunction->elements = createArray_(elems, &ASTToC::convConditionalLiteral); + ret.type = clingo_ast_head_literal_type_disjunction; + ret.disjunction = disjunction; + return ret; + } + case ASTType::TheoryAtom: { + ret.type = clingo_ast_head_literal_type_theory_atom; + ret.theory_atom = create_(convTheoryAtom(x)); + return ret; + } + default: { + throw std::runtime_error("head literal expected"); + } + } + return ret; + } + + // {{{3 body literal + + clingo_ast_body_literal_t convBodyLiteral(Object x) { + clingo_ast_body_literal_t ret; + ret.location = convLocation(x.getAttr("location")); + if (enumValue(x.getAttr("type")) == ASTType::ConditionalLiteral) { + ret.sign = clingo_ast_sign_none; + ret.type = clingo_ast_body_literal_type_conditional; + ret.conditional = create_(convConditionalLiteral(x)); + return ret; + } + else if (enumValue(x.getAttr("type")) == ASTType::CSPLiteral) { + ret.sign = clingo_ast_sign_none; + ret.type = clingo_ast_body_literal_type_literal; + ret.literal = create_(convLiteral(x)); + return ret; + } + auto atom = x.getAttr("atom"); + switch (enumValue(atom.getAttr("type"))) { + case ASTType::Aggregate: { + ret.sign = enumValue(x.getAttr("sign")); + ret.type = clingo_ast_body_literal_type_aggregate; + ret.aggregate = create_(convAggregate(atom)); + return ret; + } + case ASTType::BodyAggregate: { + auto body_aggregate = create_(); + auto elems = atom.getAttr("elements"); + body_aggregate->left_guard = convAggregateGuardOpt(atom.getAttr("left_guard")); + body_aggregate->right_guard = convAggregateGuardOpt(atom.getAttr("right_guard")); + body_aggregate->function = enumValue(atom.getAttr("function")); + body_aggregate->size = elems.size(); + body_aggregate->elements = createArray_(elems, &ASTToC::convBodyAggregateElement); + ret.sign = enumValue(x.getAttr("sign")); + ret.type = clingo_ast_body_literal_type_body_aggregate; + ret.body_aggregate = body_aggregate; + return ret; + } + case ASTType::TheoryAtom: { + ret.sign = enumValue(x.getAttr("sign")); + ret.type = clingo_ast_body_literal_type_theory_atom; + ret.theory_atom = create_(convTheoryAtom(atom)); + return ret; + } + case ASTType::Disjoint: { + auto disjoint = create_(); + auto elems = atom.getAttr("elements"); + disjoint->size = elems.size(); + disjoint->elements = createArray_(elems, &ASTToC::convDisjointElement); + ret.sign = enumValue(x.getAttr("sign")); + ret.type = clingo_ast_body_literal_type_disjoint; + ret.disjoint = disjoint; + return ret; + } + default: { + ret.sign = clingo_ast_sign_none; + ret.type = clingo_ast_body_literal_type_literal; + ret.literal = create_(convLiteral(x)); + return ret; + } + } + } + clingo_ast_body_literal_t *convBodyLiteralVec(Object x) { + return createArray_(x, &ASTToC::convBodyLiteral); + } + + // {{{3 theory definitions + + clingo_ast_theory_operator_definition_t convTheoryOperatorDefinition(Reference x) { + clingo_ast_theory_operator_definition_t ret; + ret.type = enumValue(x.getAttr("operator_type")); + ret.priority = pyToCpp(x.getAttr("priority")); + ret.location = convLocation(x.getAttr("location")); + ret.name = convString(x.getAttr("name")); + return ret; + } + + clingo_ast_theory_term_definition_t convTheoryTermDefinition(Reference x) { + clingo_ast_theory_term_definition_t ret; + auto ops = x.getAttr("operators"); + ret.name = convString(x.getAttr("name")); + ret.location = convLocation(x.getAttr("location")); + ret.operators = createArray_(ops, &ASTToC::convTheoryOperatorDefinition); + ret.size = ops.size(); + return ret; + } + + clingo_ast_theory_guard_definition_t *convTheoryGuardDefinitionOpt(Reference x) { + if (x.none()) { return nullptr; } + auto ret = create_(); + auto ops = x.getAttr("operators"); + ret->term = convString(x.getAttr("term")); + ret->operators = createArray_(ops, &ASTToC::convString); + ret->size = ops.size(); + return ret; + } + + clingo_ast_theory_atom_definition_t convTheoryAtomDefinition(Reference x) { + clingo_ast_theory_atom_definition_t ret; + auto guard = x.getAttr("guard"); + ret.name = convString(x.getAttr("name")); + ret.arity = pyToCpp(x.getAttr("arity")); + ret.location = convLocation(x.getAttr("location")); + ret.type = enumValue(x.getAttr("atom_type")); + ret.elements = convString(x.getAttr("elements")); + ret.guard = convTheoryGuardDefinitionOpt(x.getAttr("guard")); + return ret; + } + + // {{{3 statement + + clingo_ast_statement_t convStatement(Reference x) { + clingo_ast_statement_t ret; + ret.location = convLocation(x.getAttr("location")); + switch (enumValue(x.getAttr("type"))) { + case ASTType::Rule: { + auto *rule = create_(); + auto body = x.getAttr("body"); + rule->head = convHeadLiteral(x.getAttr("head")); + rule->size = body.size(); + rule->body = convBodyLiteralVec(body); + ret.type = clingo_ast_statement_type_rule; + ret.rule = rule; + return ret; + } + case ASTType::Definition: { + auto *definition = create_(); + definition->is_default = pyToCpp(x.getAttr("is_default")); + definition->name = convString(x.getAttr("name")); + definition->value = convTerm(x.getAttr("value")); + ret.type = clingo_ast_statement_type_const; + ret.definition = definition; + return ret; + } + case ASTType::ShowSignature: { + auto *show_signature = create_(); + show_signature->csp = pyToCpp(x.getAttr("csp")); + show_signature->signature = Sig(convString(x.getAttr("name")), pyToCpp(x.getAttr("arity")), !pyToCpp(x.getAttr("positive"))).rep(); + ret.type = clingo_ast_statement_type_show_signature; + ret.show_signature = show_signature; + return ret; + } + case ASTType::ShowTerm: { + auto *show_term = create_(); + auto body = x.getAttr("body"); + show_term->csp = pyToCpp(x.getAttr("csp")); + show_term->term = convTerm(x.getAttr("term")); + show_term->body = convBodyLiteralVec(body); + show_term->size = body.size(); + ret.type = clingo_ast_statement_type_show_term; + ret.show_term = show_term; + return ret; + } + case ASTType::Minimize: { + auto *minimize = create_(); + auto tuple = x.getAttr("tuple"), body = x.getAttr("body"); + minimize->weight = convTerm(x.getAttr("weight")); + minimize->priority = convTerm(x.getAttr("priority")); + minimize->tuple = convTermVec(tuple); + minimize->tuple_size = tuple.size(); + minimize->body = convBodyLiteralVec(body); + minimize->body_size = body.size(); + ret.type = clingo_ast_statement_type_minimize; + ret.minimize = minimize; + return ret; + } + case ASTType::Script: { + auto *script = create_(); + script->type = enumValue(x.getAttr("script_type")); + script->code = convString(x.getAttr("code")); + ret.type = clingo_ast_statement_type_script; + ret.script = script; + return ret; + } + case ASTType::Program: { + auto *program = create_(); + auto params = x.getAttr("parameters"); + program->name = convString(x.getAttr("name")); + program->parameters = createArray_(params, &ASTToC::convId); + program->size = params.size(); + ret.type = clingo_ast_statement_type_program; + ret.program = program; + return ret; + } + case ASTType::External: { + auto *external = create_(); + auto body = x.getAttr("body"); + external->atom = convSymbolicAtom(x.getAttr("atom")); + external->body = convBodyLiteralVec(body); + external->size = body.size(); + ret.type = clingo_ast_statement_type_external; + ret.external = external; + return ret; + } + case ASTType::Edge: { + auto *edge = create_(); + auto body = x.getAttr("body"); + edge->u = convTerm(x.getAttr("u")); + edge->v = convTerm(x.getAttr("v")); + edge->body = convBodyLiteralVec(body); + edge->size = body.size(); + ret.type = clingo_ast_statement_type_edge; + ret.edge = edge; + return ret; + } + case ASTType::Heuristic: { + auto *heuristic = create_(); + auto body = x.getAttr("body"); + heuristic->atom = convSymbolicAtom(x.getAttr("atom")); + heuristic->bias = convTerm(x.getAttr("bias")); + heuristic->priority = convTerm(x.getAttr("priority")); + heuristic->modifier = convTerm(x.getAttr("modifier")); + heuristic->body = convBodyLiteralVec(body); + heuristic->size = body.size(); + ret.type = clingo_ast_statement_type_heuristic; + ret.heuristic = heuristic; + return ret; + } + case ASTType::ProjectAtom: { + auto *project = create_(); + auto body = x.getAttr("body"); + project->atom = convSymbolicAtom(x.getAttr("atom")); + project->body = convBodyLiteralVec(body); + project->size = body.size(); + ret.type = clingo_ast_statement_type_project_atom; + ret.project_atom = project; + return ret; + } + case ASTType::ProjectSignature: { + ret.type = clingo_ast_statement_type_project_atom_signature; + ret.project_signature = Sig(convString(x.getAttr("name")), pyToCpp(x.getAttr("arity")), !pyToCpp(x.getAttr("positive"))).rep(); + return ret; + } + case ASTType::TheoryDefinition: { + auto *theory_definition = create_(); + auto terms = x.getAttr("terms"), atoms = x.getAttr("atoms"); + theory_definition->name = convString(x.getAttr("name")); + theory_definition->terms = createArray_(terms, &ASTToC::convTheoryTermDefinition); + theory_definition->terms_size = terms.size(); + theory_definition->atoms = createArray_(atoms, &ASTToC::convTheoryAtomDefinition); + theory_definition->atoms_size = atoms.size(); + ret.type = clingo_ast_statement_type_theory_definition; + ret.theory_definition = theory_definition; + return ret; + } + default: { + throw std::runtime_error("statement expected"); + } + } + } + + // {{{3 aux + + template + T *create_() { + data_.emplace_back(operator new(sizeof(T))); + return reinterpret_cast(data_.back()); + } + template + T *create_(T x) { + auto *r = create_(); + *r = x; + return r; + } + template + T *createArray_(size_t size) { + arrdata_.emplace_back(operator new[](sizeof(T) * size)); + return reinterpret_cast(arrdata_.back()); + } + template + auto createArray_(Reference vec, F f) -> decltype((this->*f)(std::declval()))* { + using U = decltype((this->*f)(std::declval())); + auto r = createArray_(vec.size()), jt = r; + for (auto x : vec.iter()) { *jt++ = (this->*f)(x); } + return r; + } + + ~ASTToC() noexcept { + for (auto &x : data_) { operator delete(x); } + for (auto &x : arrdata_) { operator delete[](x); } + data_.clear(); + arrdata_.clear(); + } + + std::vector data_; + std::vector arrdata_; + + // }}}3 +}; + +// }}}2 + +// {{{1 wrap ProgramBuilder + +struct ProgramBuilder : ObjectBase { + clingo_program_builder_t *builder; + bool locked; + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "ProgramBuilder"; + static constexpr char const *tp_name = "clingo.ProgramBuilder"; + static constexpr char const *tp_doc = +R"(Object to build non-ground programs.)"; + + static PyObject *new_(clingo_program_builder_t *builder) { + ProgramBuilder *self; + self = reinterpret_cast(type.tp_alloc(&type, 0)); + if (!self) { return nullptr; } + self->builder = builder; + self->locked = true; + return reinterpret_cast(self); + } + Object add(Reference pyStm) { + if (locked) { throw std::runtime_error("__enter__ has not been called"); } + ASTToC toc; + auto stm = toc.convStatement(pyStm); + handleCError(clingo_program_builder_add(builder, &stm)); + return None(); + } + Reference enter() { + if (!locked) { throw std::runtime_error("__enter__ already called"); } + locked = false; + handleCError(clingo_program_builder_begin(builder)); + return *this; + } + Object exit() { + if (locked) { throw std::runtime_error("__enter__ has not been called"); } + locked = true; + handleCError(clingo_program_builder_end(builder)); + return cppToPy(false); + } +}; + +PyMethodDef ProgramBuilder::tp_methods[] = { + {"__enter__", to_function<&ProgramBuilder::enter>(), METH_NOARGS, +R"(__enter__(self) -> ProgramBuilder + +Begin building a program. + +Must be called before adding statements.)"}, + {"add", to_function<&ProgramBuilder::add>(), METH_O, +R"(add(self, statement) -> None + +Adds a statement in form of an ast.AST node to the program.)"}, + {"__exit__", to_function<&ProgramBuilder::exit>(), METH_VARARGS, +R"(__exit__(self, type, value, traceback) -> bool + +Finish building a program. + +Follows python __exit__ conventions. Does not suppress exceptions. +)"}, + {nullptr, nullptr, 0, nullptr} +}; + +// {{{1 wrap Control + +void pycall(PyObject *fun, SymSpan args, SymVec &vals) { + Object params = PyTuple_New(args.size); + int i = 0; + for (auto &val : args) { + Object pyVal = Symbol::new_(val); + if (PyTuple_SetItem(params.toPy(), i, pyVal.release()) < 0) { throw PyException(); } + ++i; + } + Object ret = PyObject_Call(fun, params.toPy(), Py_None); + if (PyList_Check(ret.toPy())) { pyToCpp(ret, vals); } + else { vals.emplace_back(pyToCpp(ret)); } +} + +class PyContext : public Context { +public: + PyContext(Logger &log) + : log(log) + , ctx(nullptr) { } + bool callable(String name) const override { + return ctx && PyObject_HasAttrString(ctx, name.c_str()); + } + SymVec call(Location const &loc, String name, SymSpan args) override { + assert(ctx); + try { + Object fun = PyObject_GetAttrString(ctx, name.c_str()); + SymVec ret; + pycall(fun.toPy(), args, ret); + return ret; + } + catch (PyException const &) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: operation undefined:\n" + << errorToString() + ; + return {}; + } + } + operator bool() const { return ctx; } + virtual ~PyContext() noexcept = default; + + Logger &log; + PyObject *ctx; +}; + +struct ControlWrap : ObjectBase { + using Propagators = std::vector>; + Gringo::Control *ctl; + Gringo::Control *freeCtl; + PyObject *stats; + + static PyGetSetDef tp_getset[]; + static PyMethodDef tp_methods[]; + + static constexpr char const *tp_type = "Control"; + static constexpr char const *tp_name = "clingo.Control"; + static constexpr char const *tp_doc = + R"(Control(arguments) -> Control + +Control object for the grounding/solving process. + +Arguments: +arguments -- optional arguments to the grounder and solver (default: []). + +Note that only gringo options (without --text) and clasp's search options are +supported. Furthermore, a Control object is blocked while a search call is +active; you must not call any member function during search.)"; + + static void checkBlocked(ControlWrap *self, char const *function) { + if (self->ctl->blocked()) { + PyErr_Format(PyExc_RuntimeError, "Control.%s must not be called during solve call", function); + throw PyException(); + } + } + static PyObject *new_(Gringo::Control &ctl) { + PyObject *self = tp_new(&type, nullptr, nullptr); + if (!self) { return nullptr; } + reinterpret_cast(self)->ctl = &ctl; + return self; + } + static Gringo::GringoModule *module; + static PyObject *tp_new(PyTypeObject *type, PyObject *, PyObject *) { + ControlWrap *self; + self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) { return nullptr; } + self->ctl = nullptr; + self->freeCtl = nullptr; + self->stats = nullptr; + return reinterpret_cast(self); + } + void tp_dealloc() { + if (freeCtl) { delete freeCtl; } + ctl = freeCtl = nullptr; + Py_XDECREF(stats); + } + static int tp_init(ControlWrap *self, PyObject *pyargs, PyObject *pykwds) { + PY_TRY + static char const *kwlist[] = {"aguments", nullptr}; + PyObject *params = nullptr; + if (!PyArg_ParseTupleAndKeywords(pyargs, pykwds, "|O", const_cast(kwlist), ¶ms)) { return -1; } + std::vector args; + if (params) { + for (Object pyVal : Reference{params}.iter()) { + args.emplace_back(pyToCpp(pyVal)); + } + } + self->ctl = self->freeCtl = module->newControl(args.size(), args.data(), nullptr, 20); + return 0; + PY_CATCH(-1); + } + static PyObject *add(ControlWrap *self, PyObject *args) { + PY_TRY + checkBlocked(self, "add"); + char *name; + PyObject *pyParams; + char *part; + if (!PyArg_ParseTuple(args, "sOs", &name, &pyParams, &part)) { return nullptr; } + FWStringVec params; + for (auto pyVal : Reference{pyParams}.iter()) { + params.emplace_back(pyToCpp(pyVal)); + } + self->ctl->add(name, params, part); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *load(ControlWrap *self, PyObject *args) { + PY_TRY + checkBlocked(self, "load"); + char *filename; + if (!PyArg_ParseTuple(args, "s", &filename)) { return nullptr; } + if (!filename) { return nullptr; } + self->ctl->load(filename); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *ground(ControlWrap *self, PyObject *args, PyObject *kwds) { + PY_TRY + checkBlocked(self, "ground"); + Gringo::Control::GroundVec parts; + static char const *kwlist[] = {"parts", "context", nullptr}; + PyObject *pyParts; + PyContext context(self->ctl->logger()); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", const_cast(kwlist), &pyParts, &context.ctx)) { return nullptr; } + for (auto pyVal : Reference{pyParts}.iter()) { + Object jt = PyObject_GetIter(pyVal.toPy()); + Object pyName = PyIter_Next(jt.toPy()); + if (!pyName.valid()) { return PyErr_Format(PyExc_RuntimeError, "tuple of name and arguments expected"); } + Object pyArgs = PyIter_Next(jt.toPy()); + if (!pyArgs.valid()) { return PyErr_Format(PyExc_RuntimeError, "tuple of name and arguments expected"); } + Object pyNext = PyIter_Next(jt.toPy()); + if (pyNext.valid()) { return PyErr_Format(PyExc_RuntimeError, "tuple of name and arguments expected"); } + auto name = pyToCpp(pyName); + auto args = pyToCpp(pyArgs); + parts.emplace_back(name, args); + } + // anchor + self->ctl->ground(parts, context ? &context : nullptr); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *getConst(ControlWrap *self, PyObject *args) { + PY_TRY + checkBlocked(self, "get_const"); + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) { return nullptr; } + Gringo::Symbol val; + val = self->ctl->getConst(name); + if (val.type() == Gringo::SymbolType::Special) { Py_RETURN_NONE; } + else { return Symbol::new_(val); } + PY_CATCH(nullptr); + } + static bool on_model(Gringo::Model const &m, PyObject *mh) { + PY_TRY + Object model(Model::new_(m)); + Object ret = PyObject_CallFunction(mh, const_cast("O"), model.toPy()); + if (ret.none()) { return true; } + else { return pyToCpp(ret); } + PY_HANDLE("", "error in model callback"); + + } + static void on_finish(Gringo::SolveResult ret, PyObject *fh) { + PY_TRY + Object pyRet = SolveResult::new_(ret); + Object fhRet = PyObject_CallFunction(fh, const_cast("O"), pyRet.toPy()); + PY_HANDLE("", "error in finish callback"); + } + static bool getAssumptions(PyObject *pyAss, Gringo::Control::Assumptions &ass) { + PY_TRY + if (pyAss && pyAss != Py_None) { + Object it = PyObject_GetIter(pyAss); + if (!it.valid()) { return false; } + Object pyPair; + while ((pyPair = PyIter_Next(it.toPy())).valid()) { + Object pyPairIt = PyObject_GetIter(pyPair.toPy()); + if (!pyPairIt.valid()) { return false; } + Object pyAtom = PyIter_Next(pyPairIt.toPy()); + if (!pyAtom.valid()) { + if (!PyErr_Occurred()) { PyErr_Format(PyExc_RuntimeError, "tuple expected"); } + return false; + } + Object pyBool = PyIter_Next(pyPairIt.toPy()); + if (!pyBool.valid()) { + if (!PyErr_Occurred()) { PyErr_Format(PyExc_RuntimeError, "tuple expected"); } + return false; + } + ass.emplace_back(pyToCpp(pyAtom), pyToCpp(pyBool)); + } + if (PyErr_Occurred()) { return false; } + } + return true; + PY_CATCH(false); + } + static PyObject *solve_async(ControlWrap *self, PyObject *args, PyObject *kwds) { + PY_TRY + checkBlocked(self, "solve_async"); + Py_XDECREF(self->stats); + self->stats = nullptr; + static char const *kwlist[] = {"on_model", "on_finish", "assumptions", nullptr}; + PyObject *pyAss = nullptr, *mh = Py_None, *fh = Py_None; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", const_cast(kwlist), &mh, &fh, &pyAss)) { return nullptr; } + Gringo::Control::Assumptions ass; + if (!getAssumptions(pyAss, ass)) { return nullptr; } + Gringo::SolveFuture *future = self->ctl->solveAsync( + mh == Py_None ? Control::ModelHandler(nullptr) : [mh](Gringo::Model const &m) -> bool { PyBlock b; (void)b; return on_model(m, mh); }, + fh == Py_None ? Control::FinishHandler(nullptr) : [fh](Gringo::SolveResult ret) -> void { PyBlock b; (void)b; on_finish(ret, fh); }, + std::move(ass) + ); + return SolveFuture::new_(*future, mh, fh); + PY_CATCH(nullptr); + } + static PyObject *solve_iter(ControlWrap *self, PyObject *args, PyObject *kwds) { + PY_TRY + checkBlocked(self, "solve_iter"); + Py_XDECREF(self->stats); + self->stats = nullptr; + PyObject *pyAss = nullptr; + static char const *kwlist[] = {"assumptions", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", const_cast(kwlist), &pyAss)) { return nullptr; } + Gringo::Control::Assumptions ass; + if (!getAssumptions(pyAss, ass)) { return nullptr; } + return SolveIter::new_(*self->ctl->solveIter(std::move(ass))); + PY_CATCH(nullptr); + } + static PyObject *solve(ControlWrap *self, PyObject *args, PyObject *kwds) { + PY_TRY + checkBlocked(self, "solve"); + Py_XDECREF(self->stats); + self->stats = nullptr; + static char const *kwlist[] = {"on_model", "assumptions", nullptr}; + PyObject *mh = Py_None; + PyObject *pyAss = nullptr; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", const_cast(kwlist), &mh, &pyAss)) { return nullptr; } + Gringo::Control::Assumptions ass; + if (!getAssumptions(pyAss, ass)) { return nullptr; } + Gringo::SolveResult ret = doUnblocked([self, mh, &ass]() { + return self->ctl->solve( + mh == Py_None ? Control::ModelHandler(nullptr) : [mh](Gringo::Model const &m) { PyBlock block; return on_model(m, mh); }, + std::move(ass)); }); + return SolveResult::new_(ret); + PY_CATCH(nullptr); + } + static PyObject *cleanup(ControlWrap *self) { + PY_TRY + checkBlocked(self, "cleanup"); + self->ctl->cleanupDomains(); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *assign_external(ControlWrap *self, PyObject *args) { + PY_TRY + checkBlocked(self, "assign_external"); + PyObject *pyExt, *pyVal; + if (!PyArg_ParseTuple(args, "OO", &pyExt, &pyVal)) { return nullptr; } + Potassco::Value_t val; + if (pyVal == Py_True) { val = Potassco::Value_t::True; } + else if (pyVal == Py_False) { val = Potassco::Value_t::False; } + else if (pyVal == Py_None) { val = Potassco::Value_t::Free; } + else { + PyErr_Format(PyExc_RuntimeError, "unexpected %s() object as second argumet", pyVal->ob_type->tp_name); + return nullptr; + } + auto ext = pyToCpp(pyExt); + self->ctl->assignExternal(ext, val); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *release_external(ControlWrap *self, PyObject *args) { + PY_TRY + checkBlocked(self, "release_external"); + PyObject *pyExt; + if (!PyArg_ParseTuple(args, "O", &pyExt)) { return nullptr; } + auto ext = pyToCpp(pyExt); + self->ctl->assignExternal(ext, Potassco::Value_t::Release); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *getStats(ControlWrap *self, void *) { + PY_TRY + checkBlocked(self, "statistics"); + if (!self->stats) { + auto *stats = self->ctl->statistics(); + self->stats = getStatistics(stats, stats->root()).release(); + } + Py_XINCREF(self->stats); + return self->stats; + PY_CATCH(nullptr); + } + static int set_use_enumeration_assumption(ControlWrap *self, PyObject *pyEnable, void *) { + PY_TRY + checkBlocked(self, "use_enumeration_assumption"); + int enable = PyObject_IsTrue(pyEnable); + if (enable < 0) { return -1; } + self->ctl->useEnumAssumption(enable); + return 0; + PY_CATCH(-1); + } + static PyObject *get_use_enumeration_assumption(ControlWrap *self, void *) { + PY_TRY + return PyBool_FromLong(self->ctl->useEnumAssumption()); + PY_CATCH(nullptr); + } + static PyObject *conf(ControlWrap *self, void *) { + PY_TRY + Gringo::ConfigProxy &proxy = self->ctl->getConf(); + return Configuration::new_(proxy.getRootKey(), proxy); + PY_CATCH(nullptr); + } + static PyObject *symbolicAtoms(ControlWrap *self, void *) { + return SymbolicAtoms::new_(self->ctl->getDomain()); + } + static PyObject *theoryIter(ControlWrap *self, void *) { + PY_TRY + checkBlocked(self, "theory_atoms"); + return TheoryAtomIter::new_(&self->ctl->theory(), 0); + PY_CATCH(nullptr); + } + static PyObject *registerPropagator(ControlWrap *self, PyObject *tp) { + PY_TRY + self->ctl->registerPropagator(gringo_make_unique(tp), false); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *interrupt(ControlWrap *self) { + PY_TRY + self->ctl->interrupt(); + Py_RETURN_NONE; + PY_CATCH(nullptr); + } + static PyObject *backend(ControlWrap *self, void *) { + return Backend::new_(*self->ctl); + } + static PyObject *builder(ControlWrap *self) { + PY_TRY + return ProgramBuilder::new_(reinterpret_cast(self->ctl)); + PY_CATCH(nullptr); + } +}; + +Gringo::GringoModule *ControlWrap::module = nullptr; + +PyMethodDef ControlWrap::tp_methods[] = { + // builder + {"builder", (PyCFunction)builder, METH_NOARGS, +R"(builder(self) -> ProgramBuilder + +Return a builder to construct non-ground logic programs. + +Example: + +#script (python) + +import clingo + +def main(prg): + s = "a." + with prg.builder() as b: + clingo.parse_program(s, lambda stm: b.add(stm)) + prg.ground([("base", [])]) + prg.solve() + +#end. +)"}, + // ground + {"ground", (PyCFunction)ground, METH_KEYWORDS | METH_VARARGS, +R"(ground(self, parts, context) -> None + +Ground the given list of program parts specified by tuples of names and arguments. + +Keyword Arguments: +parts -- list of tuples of program names and program arguments to ground +context -- context object whose methods are called during grounding using + the @-syntax (if ommitted methods from the main module are used) + +Note that parts of a logic program without an explicit #program specification +are by default put into a program called base without arguments. + +Example: + +#script (python) +import clingo + +def main(prg): + parts = [] + parts.append(("p", [1])) + parts.append(("p", [2])) + prg.ground(parts) + prg.solve() + +#end. + +#program p(t). +q(t). + +Expected Answer Set: +q(1) q(2))"}, + // get_const + {"get_const", (PyCFunction)getConst, METH_VARARGS, +R"(get_const(self, name) -> Symbol + +Return the symbol for a constant definition of form: #const name = symbol.)"}, + // add + {"add", (PyCFunction)add, METH_VARARGS, +R"(add(self, name, params, program) -> None + +Extend the logic program with the given non-ground logic program in string form. + +Arguments: +name -- name of program block to add +params -- parameters of program block +program -- non-ground program as string + +Example: + +#script (python) +import clingo + +def main(prg): + prg.add("p", ["t"], "q(t).") + prg.ground([("p", [2])]) + prg.solve() + +#end. + +Expected Answer Set: +q(2))"}, + // load + {"load", (PyCFunction)load, METH_VARARGS, +R"(load(self, path) -> None + +Extend the logic program with a (non-ground) logic program in a file. + +Arguments: +path -- path to program)"}, + // solve_async + {"solve_async", (PyCFunction)solve_async, METH_KEYWORDS | METH_VARARGS, +R"(solve_async(self, on_model, on_finish, assumptions) -> SolveFuture + +Start a search process in the background and return a SolveFuture object. + +Keyword Arguments: +on_model -- optional callback for intercepting models + a Model object is passed to the callback +on_finish -- optional callback called once search has finished + a SolveResult and a Boolean indicating whether the solve call + has been canceled is passed to the callback +assumptions -- list of (atom, boolean) tuples that serve as assumptions for + the solve call, e.g. - solving under assumptions [(Function("a"), + True)] only admits answer sets that contain atom a + +Note that this function is only available in clingo with thread support +enabled. Both the on_model and the on_finish callbacks are called from another +thread. To ensure that the methods can be called, make sure to not use any +functions that block the GIL indefinitely. Furthermore, you might want to start +clingo using the --outf=3 option to disable all output from clingo. + +Example: + +#script (python) +import clingo + +def on_model(model): + print model + +def on_finish(res, canceled): + print res, canceled + +def main(prg): + prg.ground([("base", [])]) + f = prg.solve_async(on_model, on_finish) + f.wait() + +#end. + +q. + +Expected Output: +q +SAT False)"}, + // solve_iter + {"solve_iter", (PyCFunction)solve_iter, METH_KEYWORDS | METH_VARARGS, +R"(solve_iter(self, assumptions) -> SolveIter + +Return a SolveIter object, which can be used to iterate over models. + +Keyword Arguments: +assumptions -- a list of (atom, boolean) tuples that serve as assumptions for + the solve call, e.g. - solving under assumptions [(Function("a"), + True)] only admits answer sets that contain atom a + +Example: + +#script (python) +import clingo + +def main(prg): + prg.add("p", "{a;b;c}.") + prg.ground([("p", [])]) + with prg.solve_iter() as it: + for m in it: print m + +#end.)"}, + // solve + {"solve", (PyCFunction)solve, METH_KEYWORDS | METH_VARARGS, +R"(solve(self, on_model, assumptions) -> SolveResult + +Start a search process and return a SolveResult. + +Keyword Arguments: +on_model -- optional callback for intercepting models + a Model object is passed to the callback +assumptions -- a list of (atom, boolean) tuples that serve as assumptions for + the solve call, e.g. - solving under assumptions [(Function("a"), + True)] only admits answer sets that contain atom a + +Note that in gringo or in clingo with lparse or text output enabled this +function just grounds and returns a SolveResult where +SolveResult.satisfiability() is None. Furthermore, you might want to start +clingo using the --outf=3 option to disable all output from clingo. + +This function releases the GIL but it is not thread-safe. + +Take a look at Control.solve_async for an example on how to use the model +callback.)"}, + // cleanup + {"cleanup", (PyCFunction)cleanup, METH_NOARGS, +R"(cleanup(self) -> None + +Cleanup the domain used for grounding by incorporating information from the +solver. + +This function cleans up the domain used for grounding. This is done by first +simplifying the current program representation (falsifying released external +atoms). Afterwards, the top-level implications are used to either remove atoms +from the domain or mark them as facts. + +Note that any atoms falsified are completely removed from the logic program. +Hence, a definition for such an atom in a successive step introduces a fresh atom.)"}, + // assign_external + {"assign_external", (PyCFunction)assign_external, METH_VARARGS, +R"(assign_external(self, external, truth) -> None + +Assign a truth value to an external atom (represented as a function symbol). + +It is possible to assign a Boolean or None. A Boolean fixes the external to the +respective truth value; and None leaves its truth value open. + +The truth value of an external atom can be changed before each solve call. An +atom is treated as external if it has been declared using an #external +directive, and has not been forgotten by calling release_external() or defined +in a logic program with some rule. If the given atom is not external, then the +function has no effect. + +Arguments: +external -- symbol representing the external atom +truth -- bool or None indicating the truth value + +To determine whether an atom a is external, inspect the symbolic_atoms using +SolveControl.symbolic_atoms[a].is_external. See release_external() for an +example.)"}, + // release_external + {"release_external", (PyCFunction)release_external, METH_VARARGS, +R"(release_external(self, symbol) -> None + +Release an external atom represented by the given symbol. + +This function causes the corresponding atom to become permanently false if +there is no definition for the atom in the program. Otherwise, the function has +no effect. + +Example: + +#script (python) +from clingo import function + +def main(prg): + prg.ground([("base", [])]) + prg.assign_external(Function("b"), True) + prg.solve() + prg.release_external(Function("b")) + prg.solve() + +#end. + +a. +#external b. + +Expected Answer Sets: +a b +a)"}, + {"register_propagator", (PyCFunction)registerPropagator, METH_O, +R"(register_propagator(self, propagator) -> None + +Registers the given propagator with all solvers. + +Arguments: +propagator -- the propagator to register + +A propagator should be a class of the form below. Not all functions have to be +implemented and can be ommited if not needed. + +class Propagator(object) + init(self, init) -> None + This function is called once before each solving step. It is used to + map relevant program literals to solver literals, add watches for + solver literals, and initialize the data structures used during + propagation. + + Arguments: + init -- PropagateInit object + + Note that this is the last point to access theory atoms. Once the + search has started, they are no longer accessible. + + propagate(self, control, changes) -> None + Can be used to propagate solver literals given a partial assignment. + + Arguments: + control -- PropagateControl object + changes -- list of watched solver literals assigned to true + + Usage: + Called during propagation with a non-empty list of watched solver + literals that have been assigned to true since the last call to either + propagate, undo, (or the start of the search) - the change set. Only + watched solver literals are contained in the change set. Each literal + in the change set is true w.r.t. the current Assignment. + PropagateControl.add_clause can be used to add clauses. If a clause is + unit resulting, it can be propagated using + PropagateControl.propagate(). If either of the two methods returns + False, the propagate function must return immediately. + + c = ... + if not control.add_clause(c) or not control.propagate(c): + return + + Note that this function can be called from different solving threads. + Each thread has its own assignment and id, which can be obtained using + PropagateControl.id(). + + undo(self, thread_id, assign, changes) -> None + Called whenever a solver with the given id undos assignments to watched + solver literals. + + Arguments: + thread_id -- the solver thread id + changes -- list of watched solver literals whose assignment is undone + + This function is meant to update assignment dependend state in a + propagator. + + check(self, control) -> None + This function is similar to propagate but is only called on total + assignments without a change set. + + Arguments: + control -- PropagateControl object + + This function is called even if no watches have been added.)"}, + {"interrupt", (PyCFunction)interrupt, METH_NOARGS, +R"(interrupt(self) -> None + +Interrupt the active solve call. + +This function is thread-safe and can be called from a signal handler. If no +search is active the subsequent call to solve(), solve_async(), or solve_iter() +is interrupted. The SolveResult of the above solving methods can be used to +query if the search was interrupted.)"}, + {nullptr, nullptr, 0, nullptr} +}; + +PyGetSetDef ControlWrap::tp_getset[] = { + {(char*)"configuration", (getter)conf, nullptr, (char*)"Configuration object to change the configuration.", nullptr}, + {(char*)"symbolic_atoms", (getter)symbolicAtoms, nullptr, (char*)"SymbolicAtoms object to inspect the symbolic atoms.", nullptr}, + {(char*)"use_enumeration_assumption", (getter)get_use_enumeration_assumption, (setter)set_use_enumeration_assumption, +(char*)R"(Boolean determining how learnt information from enumeration modes is treated. + +If the enumeration assumption is enabled, then all information learnt from +clasp's various enumeration modes is removed after a solve call. This includes +enumeration of cautious or brave consequences, enumeration of answer sets with +or without projection, or finding optimal models; as well as clauses/nogoods +added with Model.add_clause()/Model.add_nogood(). + +Note that initially the enumeration assumption is enabled.)", nullptr}, + {(char*)"statistics", (getter)getStats, nullptr, +(char*)R"(A dictionary containing solve statistics of the last solve call. + +Contains the statistics of the last solve(), solve_async(), or solve_iter() +call. The statistics correspond to the --stats output of clingo. The detail of +the statistics depends on what level is requested on the command line. +Furthermore, you might want to start clingo using the --outf=3 option to +disable all output from clingo. + +Note that this (read-only) property is only available in clingo. + +Example: +import json +json.dumps(prg.statistics, sort_keys=True, indent=4, separators=(',', ': ')))", nullptr}, + {(char *)"theory_atoms", (getter)theoryIter, nullptr, (char *)R"(A TheoryAtomIter object, which can be used to iterate over the theory atoms.)", nullptr}, + {(char *)"backend", (getter)backend, nullptr, (char *)R"(A Backend object providing a low level interface to extend a logic program.)", nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr} +}; + +// {{{1 wrap module functions + +static PyObject *parseTerm(PyObject *, PyObject *objString) { + PY_TRY + char const *current = PyString_AsString(objString); + Gringo::Symbol value = ControlWrap::module->parseValue(current, nullptr, 20); + if (value.type() == Gringo::SymbolType::Special) { Py_RETURN_NONE; } + else { return Symbol::new_(value); } + PY_CATCH(nullptr); +} + +// {{{1 gringo module + +static PyMethodDef clingoASTModuleMethods[] = { + {"Id", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Variable", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Symbol", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"UnaryOperation", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"BinaryOperation", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Interval", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Function", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Pool", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"CSPProduct", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"CSPSum", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"CSPGuard", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"BooleanConstant", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"SymbolicAtom", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Comparison", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"CSPLiteral", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"AggregateGuard", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"ConditionalLiteral", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Aggregate", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"BodyAggregateElement", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"BodyAggregate", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"HeadAggregateElement", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"HeadAggregate", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Disjunction", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"DisjointElement", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Disjoint", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryFunction", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheorySequence", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryUnparsedTermElement", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryUnparsedTerm", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryGuard", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryAtomElement", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryAtom", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Literal", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryOperatorDefinition", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryTermDefinition", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryGuardDefinition", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryAtomDefinition", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"TheoryDefinition", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Rule", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Definition", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"ShowSignature", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"ShowTerm", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Minimize", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Script", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Program", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"External", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Edge", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"Heuristic", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"ProjectAtom", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {"ProjectSignature", to_function(), METH_VARARGS | METH_KEYWORDS, nullptr}, + {nullptr, nullptr, 0, nullptr} +}; +static char const *clingoASTModuleDoc = "The clingo.ast-" GRINGO_VERSION " module." +R"( + + +The grammar below defines valid ASTs. For each upper case identifier there is a +matching function in the module. Arguments follow in paranthesis: each having a +type given on the right-hand side of the colon. The symbols ?, *, and + are +used to denote optional arguments (None encodes abscence), list arguments, and +non-empty list arguments. + +-- Terms + +term = Symbol + ( location : Location + , symbol : clingo.Symbol + ) + | Variable + ( location : Location + , name : str + ) + | UnaryOperation + ( location : Location + , operator : UnaryOperator + , argument : term + ) + | BinaryOperation + ( location : Location + , operator : BinaryOperator + , left : term + , right : term + ) + | Interval + ( location : Location + , left : term + , right : term + ) + | Function + ( location : Location + , name : str + , arguments : term* + , external : bool + ) + | Pool + ( location : Location + , arguments : term* + ) + +csp_term = CSPSum + ( location : Location + , terms : CSPProduct + ( location : Location + , coefficient : term + , variable : term? + )* + +theory_term = Symbol + ( location : Location + , symbol : clingo.Symbol + ) + | Variable + ( location : Location + , name : str + ) + | TheoryTermSequence + ( location : Location + , sequence_type : TheorySequenceType + , terms : theory_term* + ) + | TheoryFunction + ( location : Location + , name : str + , arguments : theory_term* + ) + | TheoryUnparsedTerm + ( location : Location + , elements : TheoryUnparsedTermElement + ( operators : str* + , term : theory_term + )+ + ) + +-- Literals + +symbolic_atom = SymbolicAtom + ( term : term + ) + +literal = Literal + ( location : Location + , sign : Sign + , atom : Comparison + ( comparison : ComparisonOperator + , left : term + , right : term + ) + | BooleanConstant + ( value : bool + ) + | symbolic_atom + ) + + | CSPLiteral + ( location : Location + , term : csp_term + , guards : CSPGuard + ( comparison : ComparisonOperator + , term : csp_term + )+ + +-- Head and Body Literals + +aggregate_guard = AggregateGuard + ( comparison : ComparisonOperator + , term : term + ) + +conditional_literal = ConditionalLiteral + ( location : Location + , literal : Literal + , condition : Literal* + ) + +aggregate = Aggregate + ( location : Location + , left_guard : aggregate_guard? + , elements : conditional_literal* + , right_guard : aggregate_guard? + ) + +theory_atom = TheoryAtom + ( location : Location + , term : term + , elements : TheoryAtomElement + ( tuple : theory_term* + , condition : literal* + )* + , guard : TheoryGuard + ( operator_name : str + , term : theory_term + )? + +body_atom = aggregate + | BodyAggregate + ( location : Location + , left_guard : aggregate_guard? + , function : AggregateFunction + , elements : BodyAggregateElement + ( tuple : term* + , condition : literal* + )* + , right_guard : aggregate_guard? + ) + | Disjoint + ( location : Location + , elements : DisjointElement + ( location : Location + , tuple : term* + , term : csp_term + , condition : literal* + )* + ) + | theory_atom + +body_literal = literal + | conditional_literal + | Literal + ( location : Location + , sign : Sign + , atom : body_atom + ) + +head = literal + | aggregate + | HeadAggregate + ( location : Location + , left_guard : aggregate_guard? + , function : AggregateFunction + , elements : HeadAggregateElement + ( tuple : term* + , condition : conditional_literal + )* + , right_guard : aggregate_guard? + ) + | Disjunction + ( location : Location + , elements : conditional_literal* + ) + | theory_atom + +-- Theory Definitions + +theory = TheoryDefinition + ( location : Location + , name : str + , terms : TheoryTermDefinition + ( location : Location + , name : str + , operators : TheoryOperatorDefinition + ( location : Location + , name : str + , priority : int + , operator_type : TheoryOperatorType + )* + ) + , atoms : TheoryAtomDefinition + ( location : Location + , atom_type : TheoryAtomType + , name : str + , arity : int + , elements : str* + , guard : TheoryGuardDefinition + ( operators : str* + , term : str + )? + ) + ) + +-- Statements + +statement = Rule + ( location : Location + , head : head + , body : body_literal* + ) + | Definition + ( location : Location + , name : str + , value : term + , is_default : bool + | ShowSignature + ( location : Location + , name : str + , arity : int + , sign : bool + , csp : bool + ) + | ShowTerm + ( location : Location + , term : term + , body : body_literal* + , csp : bool + ) + | Minimize + ( location : Location + , weight : term + , priority : term + , tuple : term* + , body : body_literal* + ) + | Script + ( location : Location + , script_type : ScriptType + , code : str + ) + | Program + ( location : Location + , name : str + , parameters : Id + ( location : Location + , id : str + )* + ) + | External + ( location : Location + , atom : symbolic_atom + , body : body_literal* + ) + | Edge + ( location : Location + , u : term + , v : term + , body : body_literal* + ) + | Heuristic + ( location : Location + , atom : symbolic_atom + , body : body_literal* + , bias : term + , priority : term + , modifier : term + ) + | ProjectAtom + ( location : Location + , atom : symbolic_atom + , body : body_literal* + ) + | ProjectSignature + ( location : Location + , name : str + , arity : int + , positive : bool + ) +)"; + +static PyMethodDef clingoModuleMethods[] = { + {"parse_term", (PyCFunction)parseTerm, METH_O, +R"(parse_term(string) -> Symbol + +Parse the given string using gringo's term parser for ground terms. The +function also evaluates arithmetic functions. + +Example: + +clingo.parse_term('p(1+2)') == clingo.Function("p", [3]) +)"}, + {"parse_program", to_function(), METH_VARARGS | METH_KEYWORDS, +R"(parse_program(program, callback) -> ast.AST + +Parse the given program and return an abstract syntax tree for each statement +via a callback. + +Arguments: +program -- string representation of program +callback -- callback taking an ast as argument +)"}, + {"Function", (PyCFunction)Symbol::new_function, METH_VARARGS | METH_KEYWORDS, R"(Function(name, arguments, positive) -> Symbol + +Construct a function symbol. + +Arguments: +name -- the name of the function (empty for tuples) + +Keyword Arguments: +arguments -- the arguments in form of a list of symbols +positive -- the sign of the function (tuples must not have signs) + (Default: True) + +This includes constants and tuples. Constants have an empty argument list and +tuples have an empty name. Functions can represent classically negated atoms. +Argument positive has to be set to False to represent such atoms.)"}, + {"Tuple", (PyCFunction)Symbol::new_tuple, METH_O, R"(Tuple(arguments) -> Symbol + +Shortcut for Function("", arguments). +)"}, + {"Number", (PyCFunction)Symbol::new_number, METH_O, R"(Number(number) -> Symbol + +Construct a numeric symbol given a number.)"}, + {"String", (PyCFunction)Symbol::new_string, METH_O, R"(String(string) -> Symbol + +Construct a string symbol given a string.)"}, + {nullptr, nullptr, 0, nullptr} +}; +static char const *clingoModuleDoc = +"The clingo-" GRINGO_VERSION R"( module. + +This module provides functions and classes to work with ground terms and to +control the instantiation process. In clingo builts, additional functions to +control and inspect the solving process are available. + +Functions defined in a python script block are callable during the +instantiation process using @-syntax. The default grounding/solving process can +be customized if a main function is provided. + +Note that gringo's precomputed terms (terms without variables and interpreted +functions), called symbols in the following, are wrapped in the Symbol class. +Furthermore, strings, numbers, and tuples can be passed whereever a symbol is +expected - they are automatically converted into a Symbol object. Functions +called during the grounding process from the logic program must either return a +symbol or a sequence of symbols. If a sequence is returned, the corresponding +@-term is successively substituted by the values in the sequence. + +Static Objects: + +__version__ -- version of the clingo module ()" GRINGO_VERSION R"() +Infimum -- represents an #inf symbol +Supremum -- represents a #sup symbol + +Functions: + +Function() -- create a function symbol +Number() -- creat a number symbol +parse_program() -- parse a logic program +parse_term() -- parse ground terms +String() -- create a string symbol +Tuple() -- create a tuple symbol (shortcut) + +Classes: + +Assignment -- partial assignment of truth values to solver literals +Backend -- extend the logic program +Configuration -- modify/inspect the solver configuration +Control -- controls the grounding/solving process +Model -- provides access to a model during solve call +ProgramBuilder -- extend a non-ground logic program +PropagateControl -- controls running search in a custom propagator +PropagateInit -- object to initialize custom propagators +SolveControl -- controls running search in a model handler +SolveFuture -- handle for asynchronous solve calls +SolveIter -- handle to iterate over models +SolveResult -- result of a solve call +Symbol -- captures precomputed terms +SymbolicAtom -- captures information about a symbolic atom +SymbolicAtomIter -- iterate over symbolic atoms +SymbolicAtoms -- inspection of symbolic atoms +SymbolType -- the type of a symbol +TheoryAtom -- captures theory atoms +TheoryAtomIter -- iterate over theory atoms +TheoryElement -- captures theory elements +TheoryTerm -- captures theory terms +TheoryTermType -- the type of a theory term + +Example: + +#script (python) +import clingo +def id(x): + return x + +def seq(x, y): + return [x, y] + +def main(prg): + prg.ground([("base", [])]) + prg.solve() + +#end. + +p(@id(10)). +q(@seq(1,2)). +)"; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef clingoModule = { + PyModuleDef_HEAD_INIT, + "clingo", + clingoModuleDoc, + -1, + clingoModuleMethods, + nullptr, + nullptr, + nullptr, + nullptr +}; + +static struct PyModuleDef clingoASTModule = { + PyModuleDef_HEAD_INIT, + "clingo.ast", + clingoASTModuleDoc, + -1, + clingoASTModuleMethods, + nullptr, + nullptr, + nullptr, + nullptr +}; +#endif + +PyObject *initclingoast_() { + PY_TRY +#if PY_MAJOR_VERSION >= 3 + Object m = PyModule_Create(&clingoASTModule); + Reference{PySys_GetObject("modules")}.setItem(clingoASTModule.m_name, m); +#else + Object m = Py_InitModule3("clingo.ast", clingoASTModuleMethods, clingoASTModuleDoc); +#endif + if (!m.valid() || + !ComparisonOperator::initType(m) || !Sign::initType(m) || !AST::initType(m) || + !ASTType::initType(m) || !UnaryOperator::initType(m) || !BinaryOperator::initType(m) || + !AggregateFunction::initType(m) || !TheorySequenceType::initType(m) || !TheoryOperatorType::initType(m) || + !TheoryAtomType::initType(m) || !ScriptType::initType(m) || + false) { return nullptr; } + return m.release(); + PY_CATCH(nullptr); +} + +PyObject *initclingo_() { + PY_TRY + if (!PyEval_ThreadsInitialized()) { PyEval_InitThreads(); } +#if PY_MAJOR_VERSION >= 3 + Object m = PyModule_Create(&clingoModule); +#else + Object m = Py_InitModule3("clingo", clingoModuleMethods, clingoModuleDoc); +#endif + if (!m.valid() || + !SolveResult::initType(m) || !TheoryTermType::initType(m) || !PropagateControl::initType(m) || + !TheoryElement::initType(m) || !TheoryAtom::initType(m) || !TheoryAtomIter::initType(m) || + !Model::initType(m) || !SolveIter::initType(m) || !SolveFuture::initType(m) || + !ControlWrap::initType(m) || !Configuration::initType(m) || !SolveControl::initType(m) || + !SymbolicAtom::initType(m) || !SymbolicAtomIter::initType(m) || !SymbolicAtoms::initType(m) || + !TheoryTerm::initType(m) || !PropagateInit::initType(m) || !Assignment::initType(m) || + !SymbolType::initType(m) || !Symbol::initType(m) || !Backend::initType(m) || + !ProgramBuilder::initType(m) || + PyModule_AddStringConstant(m.toPy(), "__version__", GRINGO_VERSION) < 0 || + false) { return nullptr; } + Reference a{initclingoast_()}; + Py_XINCREF(a.toPy()); + if (PyModule_AddObject(m.toPy(), "ast", a.toPy()) < 0) { return nullptr; } + return m.release(); + PY_CATCH(nullptr); +} + +// }}}1 + +// {{{1 auxiliary functions and objects + +void pyToCpp(Reference obj, Gringo::Symbol &val) { + if (obj.isInstance(Symbol::type)) { val = reinterpret_cast(obj.toPy())->val; } + else if (PyTuple_Check(obj.toPy())) { val = Gringo::Symbol::createTuple(Potassco::toSpan(pyToCpp(obj))); } + else if (PyInt_Check(obj.toPy())) { val = Gringo::Symbol::createNum(pyToCpp(obj)); } + else if (PyString_Check(obj.toPy())) { val = Gringo::Symbol::createStr(pyToCpp(obj)); } + else { + PyErr_Format(PyExc_RuntimeError, "cannot convert to value: unexpected %s() object", obj.toPy()->ob_type->tp_name); + throw PyException(); + } +} + +Object cppToPy(Gringo::Symbol val) { + return Symbol::new_(val); +} + +template +Object cppRngToPy(T begin, T end) { + Object list = PyList_New(std::distance(begin, end)); + int i = 0; + for (auto it = begin; it != end; ++it) { + Object pyVal = cppToPy(*it); + if (PyList_SetItem(list.toPy(), i, pyVal.release()) < 0) { throw PyException(); } + ++i; + } + return list.release(); +} + +template +Object cppToPy(std::vector const &vals) { + return cppRngToPy(vals.begin(), vals.end()); +} + +template +Object cppToPy(Potassco::Span const &span) { + return cppRngToPy(span.first, span.first + span.size); +} + +template +Object cppToPy(std::initializer_list l) { + return cppRngToPy(l.begin(), l.end()); +} + +template +Object cppToPy(T const *arr, size_t size) { + List list; + for (auto it = arr, ie = arr + size; it != ie; ++it) { + list.append(cppToPy(*it)); + } + return list; +} + +// }}}1 + +} // namespace + +// {{{1 definition of PythonImpl + +struct PythonInit { + PythonInit() : selfInit(!Py_IsInitialized()) { + if (selfInit) { +#if PY_MAJOR_VERSION >= 3 + PyImport_AppendInittab("clingo", &initclingo_); +#else + PyImport_AppendInittab("clingo", []() { initclingo_(); }); +#endif + Py_Initialize(); + } + } + ~PythonInit() { + if (selfInit) { Py_Finalize(); } + } + bool selfInit; +}; + +struct PythonImpl { + PythonImpl() { + PY_TRY + if (init.selfInit) { +#if PY_MAJOR_VERSION >= 3 + static wchar_t const *argv[] = {L"clingo", 0}; + PySys_SetArgvEx(1, const_cast(argv), 0); +#else + static char const *argv[] = {"clingo", 0}; + PySys_SetArgvEx(1, const_cast(argv), 0); +#endif + } + Object clingoModule = PyImport_ImportModule("clingo"); + Object mainModule = PyImport_ImportModule("__main__"); + main = PyModule_GetDict(mainModule.toPy()); + if (!main) { throw PyException(); } + PY_HANDLE("", "could not initialize python interpreter"); + } + void exec(Location const &loc, String code) { + std::ostringstream oss; + oss << "<" << loc << ">"; + pyExec(code.c_str(), oss.str().c_str(), main); + } + bool callable(String name) { + if (!PyMapping_HasKeyString(main, const_cast(name.c_str()))) { return false; } + Object fun = PyMapping_GetItemString(main, const_cast(name.c_str())); + return PyCallable_Check(fun.toPy()); + } + void call(String name, SymSpan args, SymVec &vals) { + Object fun = PyMapping_GetItemString(main, const_cast(name.c_str())); + pycall(fun.toPy(), args, vals); + } + void call(Gringo::Control &ctl) { + Object fun = PyMapping_GetItemString(main, const_cast("main")); + Object params = PyTuple_New(1); + Object param(ControlWrap::new_(ctl)); + if (PyTuple_SetItem(params.toPy(), 0, param.release()) < 0) { throw PyException(); } + Object ret = PyObject_Call(fun.toPy(), params.toPy(), Py_None); + } + PythonInit init; + PyObject *main; +}; + +// {{{1 definition of Python + +std::unique_ptr Python::impl = nullptr; + +Python::Python(GringoModule &module) { + ControlWrap::module = &module; +} +bool Python::exec(Location const &loc, String code) { + if (!impl) { impl = gringo_make_unique(); } + PY_TRY + impl->exec(loc, code); + return true; + PY_HANDLE(loc, "parsing failed"); +} +bool Python::callable(String name) { + if (Py_IsInitialized() && !impl) { impl = gringo_make_unique(); } + try { + return impl && impl->callable(name); + } + catch (PyException const &) { + PyErr_Clear(); + return false; + } +} +SymVec Python::call(Location const &loc, String name, SymSpan args, Logger &log) { + assert(impl); + try { + SymVec vals; + impl->call(name, args, vals); + return vals; + } + catch (PyException const &) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: operation undefined:\n" + << errorToString() + ; + return {}; + } +} +void Python::main(Gringo::Control &ctl) { + assert(impl); + PY_TRY + impl->call(ctl); + PY_HANDLE("", "error while calling main function") +} +Python::~Python() = default; + +void *Python::initlib(Gringo::GringoModule &module) { + PY_TRY + ControlWrap::module = &module; + PyObject *ret = initclingo_(); + return ret; + PY_CATCH(nullptr); +} + +// }}}1 + +} // namespace Gringo + +#else // WITH_PYTHON + +#include "gringo/python.hh" +#include "gringo/symbol.hh" +#include "gringo/locatable.hh" +#include "gringo/logger.hh" + +namespace Gringo { + +// {{{1 definition of Python + +struct PythonImpl { }; + +std::unique_ptr Python::impl = nullptr; + +Python::Python(GringoModule &) { } +bool Python::exec(Location const &loc, String ) { + std::stringstream ss; + ss << loc << ": error: clingo has been build without python support\n"; + throw GringoError(ss.str().c_str()); +} +bool Python::callable(String) { + return false; +} +SymVec Python::call(Location const &, String , SymSpan, Logger &) { + return {}; +} +void Python::main(Control &) { } +Python::~Python() = default; +void *Python::initlib(Gringo::GringoModule &) { + throw std::runtime_error("clingo lib has been build without python support"); +} + +// }}}1 + +} // namespace Gringo + +#endif // WITH_PYTHON diff --git a/libgringo/src/scripts.cc b/libgringo/src/scripts.cc new file mode 100644 index 0000000..eba11b5 --- /dev/null +++ b/libgringo/src/scripts.cc @@ -0,0 +1,55 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include + +namespace Gringo { + +Scripts::Scripts(GringoModule &module) + : py(module) + , lua(module) { } + +bool Scripts::luaExec(Location const &loc, String code) { + return lua.exec(loc, code); +} +bool Scripts::pyExec(Location const &loc, String code) { + return py.exec(loc, code); +} +bool Scripts::callable(String name) { + return (context && context->callable(name)) || py.callable(name) || lua.callable(name); +} +void Scripts::main(Control &ctl) { + if (py.callable("main")) { return py.main(ctl); } + if (lua.callable("main")) { return lua.main(ctl); } +} +SymVec Scripts::call(Location const &loc, String name, SymSpan args, Logger &log) { + if (context && context->callable(name)) { return context->call(loc, name, args); } + if (py.callable(name)) { return py.call(loc, name, args, log); } + if (lua.callable(name)) { return lua.call(loc, name, args, log); } + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc << ": info: operation undefined:\n" + << " function '" << name << "' not found\n" + ; + return {}; +} +Scripts::~Scripts() = default; + +} // namespace Gringo diff --git a/libgringo/src/symbol.cc b/libgringo/src/symbol.cc new file mode 100644 index 0000000..6e642ff --- /dev/null +++ b/libgringo/src/symbol.cc @@ -0,0 +1,482 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include +#include +#include + +namespace Gringo { + +namespace { + +// {{{1 auxiliary functions + +static constexpr const uint16_t upperMax = std::numeric_limits::max(); +static constexpr const uint16_t lowerMax = 3; +uint16_t upper(uint64_t rep) { return rep >> 48; } +uint8_t lower(uint64_t rep) { return rep & 3; } +uintptr_t ptr(uint64_t rep) { return static_cast(rep & 0xFFFFFFFFFFFC); } +uint64_t combine(uint16_t u, uintptr_t ptr, uint8_t l) { + assert(l <= lowerMax); + return static_cast(u) << 48 | ptr | l; +} +uint64_t combine(uint16_t u, int32_t num) { return static_cast(u) << 48 | static_cast(static_cast(num)); } +uint64_t setUpper(uint16_t u, uint64_t rep) { return combine(u, 0, 0) | (rep & 0xFFFFFFFFFFFF); } +//uint64_t setLower(uint8_t l, uint8_t rep) { +// assert(l <= lowerMax); +// return combine(0, 0, l) | (rep & 0xFFFFFFFFFFFFFFFC); +//} + +enum class SymbolType_ : uint8_t { + Inf = clingo_symbol_type_infimum, + Num = clingo_symbol_type_number, + IdP = clingo_symbol_type_number+1, + IdN = clingo_symbol_type_number+2, + Str = clingo_symbol_type_string, + Fun = clingo_symbol_type_function, + Special = clingo_symbol_type_supremum-1, + Sup = clingo_symbol_type_supremum +}; +SymbolType_ symbolType_(uint64_t rep) { return static_cast(upper(rep)); } +template +T const *cast(uint64_t rep) { return reinterpret_cast(ptr(rep)); } +String toString(uint64_t rep) { return String::fromRep(ptr(rep)); } + +// {{{1 definition of Unique + +template +class Unique { +public: + using Type = typename T::Type; + struct Hash { + size_t operator()(Unique const &s) const { return T::hash(*s.ptr_); } + template + size_t operator()(U const &s) const { return T::hash(s); } + }; + struct Open { }; + struct Deleted { }; + struct EqualTo { + bool operator()(Unique const &a, Unique const &b) const { return a.ptr_ == b.ptr_; } + template + bool operator()(Unique const &a, U const &b) const { return T::equal(*a.ptr_, b); } + }; + struct Literals { + static constexpr Deleted deleted = {}; + static constexpr Open open = {}; + }; + Unique() = default; + template + Unique(U &&t) : ptr_(T::construct(std::forward(t))) { } + Unique(Unique &&s) noexcept { std::swap(ptr_, s.ptr_); } + Unique(Unique const &) = delete; + Unique &operator=(Unique &&s) noexcept { std::swap(ptr_, s.ptr_); return *this; } + Unique &operator=(Unique const &) = delete; + ~Unique() noexcept { + if (ptr_ && ptr_ != deleted_) { T::destroy(ptr_); } + } + Unique &operator=(Open) noexcept { + this->~Unique(); + ptr_ = nullptr; + return *this; + } + Unique &operator=(Deleted) noexcept { + this->~Unique(); + ptr_ = deleted_; + return *this; + } + bool operator==(Open) const { return ptr_ == nullptr; } + bool operator==(Deleted) const { return ptr_ == deleted_; } + template + static Type const *encode(U &&x) { + std::lock_guard g(mutex_); + return set_.insert(Hash(), EqualTo(), std::forward(x)).first.ptr_; + } +private: + using Set = HashSet; + static Set set_; + static std::mutex mutex_; + static Type const *deleted_; + Type *ptr_ = nullptr; + +}; +template +constexpr typename Unique::Deleted Unique::Literals::deleted; +template +constexpr typename Unique::Open Unique::Literals::open; +template +typename Unique::Set Unique::set_; +template +std::mutex Unique::mutex_; +// NOTE: this is just a sentinel address that is never malloced and never dereferenced +template +typename Unique::Type const *Unique::deleted_ = reinterpret_cast::Type const *>(&Unique::deleted_); + + +// {{{1 definition of UString + +struct MString { + using Type = char; + static size_t hash(char const &str) { return strhash(&str); } + static size_t hash(StringSpan str) { return strhash(str); } + static bool equal(char const &a, char const &b) { return std::strcmp(&a, &b) == 0; } + static bool equal(char const &a, StringSpan b) { return std::strncmp(&a, b.first, b.size) == 0 && (&a)[b.size] == '\0'; } + static char *construct(char const &str) { + std::unique_ptr buf{new char[std::strlen(&str) + 1]}; + std::strcpy(buf.get(), &str); + return buf.release(); + } + static char *construct(StringSpan str) { + std::unique_ptr buf{new char[str.size + 1]}; + std::memcpy(buf.get(), str.first, sizeof(char) * str.size); + buf[str.size] = '\0'; + return buf.release(); + } + static void destroy(char *str) { delete [] str; } +}; + +using UString = Unique; + +// {{{1 definition of USig + +struct MSig { + using Type = std::pair; + static size_t hash(Type const &sig) { return get_value_hash(sig); } + static bool equal(Type const &a, Type const &b) { return a == b; } + static Type *construct(Type const &sig) { return gringo_make_unique(sig).release(); } + static void destroy(Type *sig) { delete sig; } +}; +using USig = Unique; +uint64_t encodeSig(String name, uint32_t arity, bool sign) { + return arity < upperMax + ? combine(arity, String::toRep(name), sign) + : combine(upperMax, reinterpret_cast(USig::encode(MSig::Type{name, arity})), sign); +} + +// {{{1 definition of Fun + +class Fun { +public: + Sig sig() const { + return sig_; + } + SymSpan args() const { + return {args_, sig().arity()}; + } + static Fun *make(Sig sig, SymSpan args) { + auto *mem = ::operator new(sizeof(Fun) + args.size * sizeof(Symbol)); + return new(mem) Fun(sig, args); + } + bool equal(Sig sig, SymSpan args) const { + return sig_ == sig && std::equal(begin(args), end(args), args_); + } + static size_t hash(Sig sig, SymSpan args) { + return get_value_hash(sig, hash_range(begin(args), end(args))); + } + void destroy() noexcept { + this->~Fun(); + ::operator delete(this); + } +private: + ~Fun() noexcept = default; + Fun(Sig sig, SymSpan args) noexcept + : sig_(sig) { + std::memcpy(static_cast(args_), args.first, args.size * sizeof(Symbol)); + } + Sig const sig_; + Symbol args_[0]; +}; + +struct MFun { + using Type = Fun; + using Cons = std::pair; + static size_t hash(Type const &fun) { return Fun::hash(fun.sig(), fun.args()); } + static size_t hash(Cons const &fun) { return Fun::hash(fun.first, fun.second); } + static size_t cons(Type const &fun) { return fun.hash(fun.sig(), fun.args()); } + static bool equal(Type const &a, Type const &b) { return a.equal(b.sig(), b.args()); } + static bool equal(Type const &a, Cons const &b) { return a.equal(b.first, b.second); } + static Type *construct(Cons fun) { return Fun::make(fun.first, fun.second); } + static void destroy(Type *fun) { const_cast(fun)->destroy(); } +}; +using UFun = Unique; + +// }}}1 + +} // namespace + +// {{{1 definition of String + +String::String(char const *str) +: str_(UString::encode(*str)) { } + +String::String(StringSpan str) +: str_(UString::encode(str)) { } + +String::String(uintptr_t r) +: str_(reinterpret_cast(r)) { } + +bool String::empty() const { return str_[0] == '\0'; } + +size_t String::hash() const { return reinterpret_cast(str_); } +uintptr_t String::toRep(String s) { return reinterpret_cast(s.str_); } +String String::fromRep(uintptr_t t) { return String(t); } + +// {{{1 definition of Signature + +Sig::Sig(String name, uint32_t arity, bool sign) +: Sig{encodeSig(name, arity, sign)} { } + +String Sig::name() const { + uint16_t u = upper(rep()); + return u < upperMax ? toString(rep()) : cast(rep())->first; +} + +Sig Sig::flipSign() const { + return Sig(rep() ^ 1); +} + +uint32_t Sig::arity() const { + uint16_t u = upper(rep()); + return u < upperMax ? u : cast(rep())->second; +} + +bool Sig::sign() const { return lower(rep()); } + +size_t Sig::hash() const { return get_value_hash(rep()); } + +namespace { +bool less(Sig const &a, Sig const &b) { + if (a.sign() != b.sign()) { return a.sign() < b.sign(); } + if (a.arity() != b.arity()) { return a.arity() < b.arity(); } + return a.name() < b.name(); +} +} + +bool Sig::operator==(Sig s) const { return rep() == s.rep(); } +bool Sig::operator!=(Sig s) const { return rep() != s.rep(); } +bool Sig::operator<(Sig s) const { return *this != s && less(*this, s); } +bool Sig::operator>(Sig s) const { return *this != s && less(s, *this); } +bool Sig::operator<=(Sig s) const { return *this == s || less(*this, s); } +bool Sig::operator>=(Sig s) const { return *this == s || less(s, *this); } + +// {{{1 definition of Symbol + +// {{{2 construction + +Symbol::Symbol() +: Symbol(combine(static_cast(SymbolType_::Special), 0, 0)) { } + +Symbol Symbol::createInf() { + return Symbol(combine(static_cast(SymbolType_::Inf), 0, 0)); +} + +Symbol Symbol::createSup() { + return Symbol(combine(static_cast(SymbolType_::Sup), 0, 0)); +} + +Symbol Symbol::createNum(int num) { + return Symbol(combine(static_cast(SymbolType_::Num), num)); +} + +Symbol Symbol::createId(String val, bool sign) { + return Symbol(combine(static_cast(sign ? SymbolType_::IdN : SymbolType_::IdP), String::toRep(val), 0)); +} + +Symbol Symbol::createStr(String val) { + return Symbol(combine(static_cast(SymbolType_::Str), String::toRep(val), 0)); +} + +Symbol Symbol::createTuple(SymSpan args) { + return createFun("", args, false); +} + +Symbol Symbol::createFun(String name, SymSpan args, bool sign) { + return args.size != 0 + ? Symbol(combine(static_cast(SymbolType_::Fun), reinterpret_cast(UFun::encode(std::make_pair(Sig(name, args.size, sign), args))), 0)) + : createId(name, sign); +} + +// {{{2 inspection + +SymbolType Symbol::type() const { + auto t = symbolType_(rep_); + switch (t) { + case SymbolType_::IdP: { return SymbolType::Fun; } + case SymbolType_::IdN: { return SymbolType::Fun; } + default: { return static_cast(t); } + } +} + +int32_t Symbol::num() const { + assert(type() == SymbolType::Num); + return static_cast(static_cast(rep_)); +} + +String Symbol::string() const { + assert(type() == SymbolType::Str); + return toString(rep_); +} + +Sig Symbol::sig() const{ + assert(type() == SymbolType::Fun); + switch (symbolType_(rep_)) { + case SymbolType_::IdP: { return Sig(toString(rep_), 0, false); } + case SymbolType_::IdN: { return Sig(toString(rep_), 0, true); } + default: { return cast(rep_)->sig(); } + } +} + +bool Symbol::hasSig() const { + return type() == SymbolType::Fun; +} + +String Symbol::name() const { + assert(type() == SymbolType::Fun); + switch (symbolType_(rep_)) { + case SymbolType_::IdP: + case SymbolType_::IdN: { return toString(rep_); } + default: { return cast(rep_)->sig().name(); } + } +} + +SymSpan Symbol::args() const { + assert(type() == SymbolType::Fun); + switch (symbolType_(rep_)) { + case SymbolType_::IdP: + case SymbolType_::IdN: { return SymSpan{nullptr, 0}; } + default: { return cast(rep_)->args(); } + } +} +bool Symbol::sign() const { + assert(type() == SymbolType::Fun || type() == SymbolType::Num); + switch (symbolType_(rep_)) { + case SymbolType_::Num: { return num() < 0; } + case SymbolType_::IdP: { return false; } + case SymbolType_::IdN: { return true; } + default: { return cast(rep_)->sig().sign(); } + } +} + +// {{{2 modification + +Symbol Symbol::flipSign() const { + assert(type() == SymbolType::Fun || type() == SymbolType::Num); + switch (symbolType_(rep_)) { + case SymbolType_::Num: { return Symbol::createNum(-num()); } + case SymbolType_::IdP: { return Symbol(setUpper(static_cast(SymbolType_::IdN), rep_)); } + case SymbolType_::IdN: { return Symbol(setUpper(static_cast(SymbolType_::IdP), rep_)); } + default: { + auto f = cast(rep_); + auto s = f->sig(); + return createFun(s.name(), f->args(), !s.sign()); + } + } +} + +Symbol Symbol::replace(IdSymMap const &map) const { + assert(symbolType_(rep_) != SymbolType_::IdN); + switch(symbolType_(rep_)) { + case SymbolType_::Fun: { + SymVec vals; + for (auto &x : args()) { vals.emplace_back(x.replace(map)); } + return createFun(name(), Potassco::toSpan(vals)); + } + case SymbolType_::IdP: { + auto it = map.find(name()); + if (it != map.end()) { return it->second; } + } + default: { return *this; } + } +} + +// {{{2 comparison + +size_t Symbol::hash() const { return get_value_hash(rep_); } + +namespace { +bool less(Symbol const &a, Symbol const &b) { + auto ta = symbolType_(a.rep()), tb = symbolType_(b.rep()); + if (ta != tb) { return ta < tb; } + switch(ta) { + case SymbolType_::Num: { return a.num() < b.num(); } + case SymbolType_::IdN: + case SymbolType_::IdP: { return a.name() < b.name(); } + case SymbolType_::Str: { return a.string() < b.string(); } + case SymbolType_::Inf: { return false; } + case SymbolType_::Sup: { return false; } + case SymbolType_::Fun: { + auto sa = a.sig(), sb = b.sig(); + if (sa != sb) { return sa < sb; } + auto aa = a.args(), ab = b.args(); + return std::lexicographical_compare(begin(aa), end(aa), begin(ab), end(ab)); + } + case SymbolType_::Special: { return false; } + } + assert(false); + return false; +} +} + +bool Symbol::operator==(Symbol const &other) const { return rep_ == other.rep_; } +bool Symbol::operator!=(Symbol const &other) const { return rep_ != other.rep_; } + +bool Symbol::operator<(Symbol const &other) const { return (*this != other) && less(*this, other); } +bool Symbol::operator>(Symbol const &other) const { return (*this != other) && less(other, *this); } +bool Symbol::operator<=(Symbol const &other) const { return (*this == other) || less(*this, other); } +bool Symbol::operator>=(Symbol const &other) const { return (*this == other) || less(other, *this); } + +// {{{2 output + +void Symbol::print(std::ostream& out) const { + switch(symbolType_(rep_)) { + case SymbolType_::Num: { out << num(); break; } + case SymbolType_::IdN: { out << "-"; } + case SymbolType_::IdP: { + char const *n = name().c_str(); + out << (n[0] != '\0' ? n : "()"); break; + } + case SymbolType_::Str: { out << '"' << quote(string().c_str()) << '"'; break; } + case SymbolType_::Inf: { out << "#inf"; break; } + case SymbolType_::Sup: { out << "#sup"; break; } + case SymbolType_::Fun: { + auto s = sig(); + if (s.sign()) { out << "-"; } + out << s.name(); + auto a = args(); + out << "("; + if (a.size > 0) { + std::copy(begin(a), end(a) - 1, std::ostream_iterator(out, ",")); + out << *(end(a) - 1); + } + if (a.size == 1 && s.name() == "") { + out << ","; + } + out << ")"; + break; + } + case SymbolType_::Special: { out << "#special"; break; } + } +} + +// }}}2 + +// }}}1 + +} // namespace Gringo + diff --git a/libgringo/src/term.cc b/libgringo/src/term.cc new file mode 100644 index 0000000..7e1849c --- /dev/null +++ b/libgringo/src/term.cc @@ -0,0 +1,1893 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/term.hh" +#include "gringo/logger.hh" +#include "gringo/graph.hh" +#include + +namespace Gringo { + +// {{{ definition of Defines + +Defines::Defines() = default; + +Defines::Defines(Defines &&) = default; + +Defines::DefMap const &Defines::defs() const { + return defs_; +} + +void Defines::add(Location const &loc, String name, UTerm &&value, bool defaultDef, Logger &log) { + auto it = defs_.find(name); + if (it == defs_.end()) { defs_.emplace(name, make_tuple(defaultDef, loc, std::move(value))); } + else if (std::get<0>(it->second) && !defaultDef) { it->second = make_tuple(defaultDef, loc, std::move(value)); } + else if (std::get<0>(it->second) || !defaultDef) { + GRINGO_REPORT(log, clingo_error_runtime) + << loc << ": error: redefinition of constant:\n" + << " #const " << name << "=" << *value << ".\n" + << std::get<1>(it->second) << ": note: constant also defined here\n"; + } +} + +void Defines::init(Logger &log) { + using DefineGraph = Graph; + using NodeMap = std::unordered_map; + + DefineGraph graph; + NodeMap nodes; + for (auto it = defs_.begin(), end = defs_.end(); it != end; ++it) { + nodes.emplace(it->first, &graph.insertNode(it)); + } + for (auto &x : nodes) { + Term::VarSet vals; + std::get<2>(x.second->data->second)->collectIds(vals); + for (auto &y : vals) { + auto it = nodes.find(y); + if (it != nodes.end()) { x.second->insertEdge(*it->second); } + } + } + for (auto &scc : graph.tarjan()) { + if (scc.size() > 1) { + std::ostringstream msg; + msg + << std::get<1>(scc.back()->data->second) << ": error: cyclic constant definition:\n" + << " #const " << scc.back()->data->first << "=" << *std::get<2>(scc.back()->data->second) << ".\n"; + scc.pop_back(); + for (auto &x : scc) { + msg + << std::get<1>(x->data->second) << ": note: cycle involves definition:\n" + << " #const " << x->data->first << "=" << *std::get<2>(x->data->second) << ".\n"; + } + GRINGO_REPORT(log, clingo_error_runtime) << msg.str(); + } + for (auto &x : scc) { Term::replace(std::get<2>(x->data->second), std::get<2>(x->data->second)->replace(*this, true)); } + } +} + +bool Defines::empty() const { return defs_.empty(); } + +void Defines::apply(Symbol x, Symbol &retVal, UTerm &retTerm, bool replace) { + if (x.type() == SymbolType::Fun) { + if (x.sig().arity() > 0) { + SymVec args; + bool changed = true; + for (unsigned i = 0, e = x.args().size; i != e; ++i) { + UTerm rt; + args.emplace_back(); + apply(x.args()[i], args.back(), rt, true); + if (rt) { + Location loc{rt->loc()}; + UTermVec tArgs; + args.pop_back(); + for (auto &y : args) { tArgs.emplace_back(make_locatable(rt->loc(), y)); } + tArgs.emplace_back(std::move(rt)); + for (++i; i != e; ++i) { + Symbol rv; + tArgs.emplace_back(); + apply(x.args()[i], rv, tArgs.back(), true); + if (!tArgs.back()) { + if (rv.type() == SymbolType::Special) { rv = x.args()[i]; } + tArgs.back() = make_locatable(loc, rv); + } + } + retTerm = make_locatable(loc, x.name(), std::move(tArgs)); + return; + } + else if (args.back().type() == SymbolType::Special) { args.back() = x.args()[i]; } + else { changed = true; } + } + if (changed) { retVal = Symbol::createFun(x.name(), Potassco::toSpan(args)); } + } + else if (replace) { + auto it(defs_.find(x.name())); + if (it != defs_.end()) { + retVal = std::get<2>(it->second)->isEDB(); + if (retVal.type() == SymbolType::Special) { + retTerm = get_clone(std::get<2>(it->second)); + } + } + } + } +} + +Defines::~Defines() { } + +// }}} + +// {{{ definition of GRef + +GRef::GRef(UTerm &&name) + : type(EMPTY) + , name(std::move(name)) + , value(Symbol::createNum(0)) + , term(0) { } + +GRef::operator bool() const { return type != EMPTY; } + +void GRef::reset() { type = EMPTY; } + +GRef &GRef::operator=(Symbol const &x) { + type = VALUE; + value = x; + return *this; +} + +GRef &GRef::operator=(GTerm &x) { + type = TERM; + term = &x; + return *this; +} + +bool GRef::occurs(GRef &x) const { + switch (type) { + case VALUE: { return false; } + case TERM: { return term->occurs(x); } + case EMPTY: { return this == &x; } + } + assert(false); + return false; +} + +bool GRef::match(Symbol const &x) { + switch (type) { + case VALUE: { return value == x; } + case TERM: { return term->match(x); } + case EMPTY: { assert(false); } + } + return false; +} + +template +bool GRef::unify(T &x) { +switch (type) { + case VALUE: { return x.match(value); } + case TERM: { return term->unify(x); } + case EMPTY: { assert(false); } +} +return false; + +} + +// }}} + +// {{{1 definition of GValTerm + +GValTerm::GValTerm(Symbol val) : val(val) { } + +bool GValTerm::operator==(GTerm const &x) const { + auto t = dynamic_cast(&x); + return t && val == t->val; +} + +size_t GValTerm::hash() const { return get_value_hash(typeid(GValTerm).hash_code(), val); } + +void GValTerm::print(std::ostream &out) const { out << val; } + +Sig GValTerm::sig() const { return val.sig(); } + +GTerm::EvalResult GValTerm::eval() const { return EvalResult(true, val); } + +bool GValTerm::occurs(GRef &) const { return false; } + +void GValTerm::reset() { } + +bool GValTerm::match(Symbol const &x) { return val == x; } + +bool GValTerm::unify(GTerm &x) { return x.match(val); } + +bool GValTerm::unify(GFunctionTerm &x) { return x.match(val); } + +bool GValTerm::unify(GLinearTerm &x) { return x.match(val); } + +bool GValTerm::unify(GVarTerm &x) { return x.match(val); } + +GValTerm::~GValTerm() { } + +// {{{1 definition of GFunctionTerm + +GFunctionTerm::GFunctionTerm(String name, UGTermVec &&args) : sign(false), name(name), args(std::move(args)) { } + +// Note: uses structural comparisson of names of variable terms (VarTerm/LinearTerm) +bool GFunctionTerm::operator==(GTerm const &x) const { + auto t = dynamic_cast(&x); + return t && sig() == x.sig() && is_value_equal_to(args, t->args); +} + +size_t GFunctionTerm::hash() const { return get_value_hash(typeid(GFunctionTerm).hash_code(), sig(), args); } + +void GFunctionTerm::print(std::ostream &out) const { + if ((sig()).sign()) { + out << "-"; + } + out << name; + out << "("; + print_comma(out, args, ",", [](std::ostream &out, UGTerm const &x) { out << *x; }); + out << ")"; +} + +Sig GFunctionTerm::sig() const { return Sig(name, args.size(), sign); } + +GTerm::EvalResult GFunctionTerm::eval() const { return EvalResult(false, Symbol()); } + +bool GFunctionTerm::occurs(GRef &x) const { + for (auto &y : args) { + if (y->occurs(x)) { return true; } + } + return false; +} + +void GFunctionTerm::reset() { + for (auto &y : args) { y->reset(); } +} + +bool GFunctionTerm::match(Symbol const &x) { + if (x.type() != SymbolType::Fun || sig() != x.sig()) { return false; } + else { + auto i = 0; + for (auto &y : args) { + if (!y->match(x.args()[i++])) { return false; } + } + return true; + } +} + +bool GFunctionTerm::unify(GTerm &x) { return x.unify(*this); } + +bool GFunctionTerm::unify(GFunctionTerm &x) { + if (sig() != x.sig()) { return false; } + else { + for (auto it = args.begin(), jt = x.args.begin(), ie = args.end(); it != ie; ++it, ++jt) { + if (!(*it)->unify(**jt)) { return false; } + } + return true; + } +} + +bool GFunctionTerm::unify(GLinearTerm &) { return false; } + +bool GFunctionTerm::unify(GVarTerm &x) { + if (*x.ref) { return x.ref->unify(*this); } + else if (!occurs(*x.ref)) { + *x.ref = *this; + return true; + } + else { return false; } +} + +GFunctionTerm::~GFunctionTerm() { } + +// {{{1 definition of GLinearTerm + +GLinearTerm::GLinearTerm(SGRef ref, int m, int n) : ref(ref), m(m), n(n) { assert(ref); } + +bool GLinearTerm::operator==(GTerm const &x) const { + auto t = dynamic_cast(&x); + return t && *ref->name == *t->ref->name && m == t->m && n == t->n; +} + +size_t GLinearTerm::hash() const { return get_value_hash(typeid(GLinearTerm).hash_code(), ref->name, m, n); } + +void GLinearTerm::print(std::ostream &out) const { out << "(" << m << "*" << *ref->name << "+" << n << ")"; } + +Sig GLinearTerm::sig() const { throw std::logic_error("must not be called"); } + +GTerm::EvalResult GLinearTerm::eval() const { return EvalResult(false, Symbol()); } + +bool GLinearTerm::occurs(GRef &x) const { return ref->occurs(x); } + +void GLinearTerm::reset() { ref->reset(); } + +bool GLinearTerm::match(Symbol const &x) { + if (x.type() != SymbolType::Num) { return false; } + else { + int y = x.num(); + y-= n; + if (y % m != 0) { return false; } + else { + y /= m; + if (*ref) { return ref->match(Symbol::createNum(y)); } + else { + *ref = Symbol::createNum(y); + return true; + } + } + } +} + +bool GLinearTerm::unify(GTerm &x) { return x.unify(*this); } + +bool GVarTerm::unify(GFunctionTerm &x) { + if (*ref) { return ref->unify(x); } + else if (!x.occurs(*ref)) { + *ref = x; + return true; + } + else { return false; } +} + +bool GLinearTerm::unify(GLinearTerm &) { + // Note: more could be done but this would be somewhat involved + // because this would require rational numbers + // as of now this simply unifies too much + return true; +} + +bool GLinearTerm::unify(GFunctionTerm &) { return false; } + +bool GLinearTerm::unify(GVarTerm &x) { + if (*x.ref) { return x.ref->unify(*this); } + else { + // see not at: GLinearTerm::unify(GLinearTerm &x) + return true; + } +} + +GLinearTerm::~GLinearTerm() { } + +// {{{1 definition of GVarTerm + +GVarTerm::GVarTerm(SGRef ref) : ref(ref) { assert(ref); } + +bool GVarTerm::operator==(GTerm const &x) const { + auto t = dynamic_cast(&x); + return t && *ref->name == *t->ref->name; +} + +size_t GVarTerm::hash() const { return get_value_hash(typeid(GVarTerm).hash_code(), ref->name); } + +void GVarTerm::print(std::ostream &out) const { out << *ref->name; } + +Sig GVarTerm::sig() const { throw std::logic_error("must not be called"); } + +GTerm::EvalResult GVarTerm::eval() const { return EvalResult(false, Symbol()); } + +bool GVarTerm::occurs(GRef &x) const { return ref->occurs(x); } + +void GVarTerm::reset() { ref->reset(); } + +bool GVarTerm::match(Symbol const &x) { + if (*ref) { return ref->match(x); } + else { + *ref = x; + return true; + } +} + +bool GVarTerm::unify(GTerm &x) { return x.unify(*this); } + +bool GVarTerm::unify(GLinearTerm &x) { + if (*ref) { return ref->unify(x); } + else { + // see note at: GLinearTerm::unify(GLinearTerm &x) + return true; + } +} + +bool GVarTerm::unify(GVarTerm &x) { + if (*ref) { return ref->unify(x); } + else if (*x.ref) { return x.ref->unify(*this); } + else if (ref->name != x.ref->name) { + *ref = x; + return true; + } + else { return true; } +} + +GVarTerm::~GVarTerm() { } + +// }}}1 + +// {{{1 definition of operator<< for BinOp and UnOp + +int eval(UnOp op, int x) { + switch (op) { + case UnOp::NEG: { return -x; } + case UnOp::ABS: { return std::abs(x); } + case UnOp::NOT: { return ~x; } + } + assert(false); + return 0; +} + +std::ostream &operator<<(std::ostream &out, UnOp op) { + switch (op) { + case UnOp::ABS: { out << "#abs"; break; } + case UnOp::NOT: { out << "~"; break; } + case UnOp::NEG: { out << "-"; break; } + } + return out; +} + +namespace { +inline int ipow(int a, int b) { + if (b < 0) { return 0; } + else { + int r = 1; + while (b > 0) { + if(b & 1) { r *= a; } + b >>= 1; + a *= a; + } + return r; + } +} +} + +int eval(BinOp op, int x, int y) { + switch (op) { + case BinOp::XOR: { return x ^ y; } + case BinOp::OR: { return x | y; } + case BinOp::AND: { return x & y; } + case BinOp::ADD: { return x + y; } + case BinOp::SUB: { return x - y; } + case BinOp::MUL: { return x * y; } + case BinOp::MOD: { return x % y; } + case BinOp::POW: { return ipow(x, y); } + case BinOp::DIV: { + assert(y != 0 && "must be checked before call"); + return x / y; + } + } + assert(false); + return 0; +} + +int Term::toNum(bool &undefined, Logger &log) { + Symbol y(eval(undefined, log)); + if (y.type() == SymbolType::Num) { return y.num(); } + else { + undefined = true; + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc() << ": info: number expected:\n" + << " " << *this << "\n"; + return 0; + } +} + +std::ostream &operator<<(std::ostream &out, BinOp op) { + switch (op) { + case BinOp::AND: { out << "&"; break; } + case BinOp::OR: { out << "?"; break; } + case BinOp::XOR: { out << "^"; break; } + case BinOp::POW: { out << "**"; break; } + case BinOp::ADD: { out << "+"; break; } + case BinOp::SUB: { out << "-"; break; } + case BinOp::MUL: { out << "*"; break; } + case BinOp::DIV: { out << "/"; break; } + case BinOp::MOD: { out << "\\"; break; } + } + return out; +} + +// {{{1 definition of Term and auxiliary functions + +namespace { + +UTerm wrap(UTerm &&x) { + UTermVec args; + args.emplace_back(std::move(x)); + return make_locatable(args.front()->loc(), "#b", std::move(args)); +} + +} // namespace + +UTermVec unpool(UTerm const &x) { + UTermVec pool; + x->unpool(pool); + return pool; +} + +SGRef Term::_newRef(RenameMap &names, Term::ReferenceMap &refs) const { + UTerm x(renameVars(names)); + auto &ref = refs[x.get()]; + if (!ref) { ref = std::make_shared(std::move(x)); } + return ref; +} + +UGTerm Term::gterm() const { + RenameMap names; + ReferenceMap refs; + return gterm(names, refs); +} + + +UGFunTerm Term::gfunterm(RenameMap &, ReferenceMap &) const { + return nullptr; +} + +void Term::collect(VarTermSet &x) const { + VarTermBoundVec vars; + collect(vars, false); + for (auto &y : vars) { x.emplace(*y.first); } +} + + +bool Term::isZero(Logger &log) const { + bool undefined; + return getInvertibility() == Term::CONSTANT && eval(undefined, log) == Symbol::createNum(0); +} + +bool Term::bind(VarSet &bound) { + VarTermBoundVec occs; + collect(occs, false); + bool ret = false; + for (auto &x : occs) { + if ((x.first->bindRef = bound.insert(x.first->name).second)) { ret = true; } + } + return ret; +} + +UTerm Term::insert(ArithmeticsMap &arith, AuxGen &auxGen, UTerm &&term, bool eq) { + unsigned level = term->getLevel(); + assert(level < arith.size()); + auto ret = arith[level].emplace(std::move(term), nullptr); + if (ret.second) { ret.first->second = auxGen.uniqueVar(ret.first->first->loc(), level, "#Arith"); } + if (eq) { + auto ret2 = arith[level].emplace(get_clone(ret.first->second), nullptr); + if (ret2.second) { ret2.first->second = get_clone(ret.first->first); } + } + return get_clone(ret.first->second); +} + +// {{{1 definition of AuxGen + +String AuxGen::uniqueName(char const *prefix) { + return String((prefix + std::to_string((*auxNum)++)).c_str()); +} + +UTerm AuxGen::uniqueVar(Location const &loc, unsigned level, const char *prefix) { + return make_locatable(loc, uniqueName(prefix), std::make_shared(), level); +} + +// {{{1 definition of SimplifyState + +std::unique_ptr SimplifyState::createScript(Location const &loc, String name, UTermVec &&args) { + scripts.emplace_back(gen.uniqueVar(loc, 0, "#Script"), name, std::move(args)); + return make_locatable(loc, static_cast(*std::get<0>(scripts.back())), 1, 0); +} + +std::unique_ptr SimplifyState::createDots(Location const &loc, UTerm &&left, UTerm &&right) { + dots.emplace_back(gen.uniqueVar(loc, 0, "#Range"), std::move(left), std::move(right)); + return make_locatable(loc, static_cast(*std::get<0>(dots.back())), 1, 0); +} + + +// {{{1 definition of Term::SimplifyRet + +Term::SimplifyRet::SimplifyRet(SimplifyRet &&x) : type(x.type) { + switch(type) { + case LINEAR: + case REPLACE: { x.type = UNTOUCHED; } + case UNTOUCHED: { + term = x.term; + break; + } + case UNDEFINED: + case CONSTANT: { + val = x.val; + break; + } + } +} +//! Reference to untouched term. +Term::SimplifyRet::SimplifyRet(Term &x, bool project) : type(UNTOUCHED), project(project), term(&x) { } +//! Indicate replacement with linear term. +Term::SimplifyRet::SimplifyRet(std::unique_ptr &&x) : type(LINEAR), project(false), term(x.release()) { } +//! Indicate replacement with arbitrary term. +Term::SimplifyRet::SimplifyRet(UTerm &&x) : type(REPLACE), project(false), term(x.release()) { } +//! Indicate replacement with value. +Term::SimplifyRet::SimplifyRet(Symbol const &x) : type(CONSTANT), project(false), val(x) { } +Term::SimplifyRet::SimplifyRet() : type(UNDEFINED), project(false) { } +bool Term::SimplifyRet::notNumeric() const { + switch (type) { + case UNDEFINED: { return true; } + case LINEAR: { return false; } + case CONSTANT: { return val.type() != SymbolType::Num; } + case REPLACE: + case UNTOUCHED: { return term->isNotNumeric(); } + } + assert(false); + return false; +} +bool Term::SimplifyRet::constant() const { return type == CONSTANT; } +bool Term::SimplifyRet::isZero() const { return constant() && val.type() == SymbolType::Num && val.num() == 0; } +LinearTerm &Term::SimplifyRet::lin() { return static_cast(*term); } +Term::SimplifyRet &Term::SimplifyRet::update(UTerm &x) { + switch (type) { + case CONSTANT: { + x = make_locatable(x->loc(), val); + return *this; + } + case LINEAR: { + if (lin().m == 1 && lin().n == 0) { + type = UNTOUCHED; + x = std::move(lin().var); + delete term; + return *this; + } + } + case REPLACE: { + type = UNTOUCHED; + x.reset(term); + return *this; + } + case UNDEFINED: + case UNTOUCHED: { return *this; } + } + throw std::logic_error("Term::SimplifyRet::update: must not happen"); +} +bool Term::SimplifyRet::undefined() const { + return type == UNDEFINED; +} +bool Term::SimplifyRet::notFunction() const { + switch (type) { + case UNDEFINED: { return true; } + case LINEAR: { return true; } + case CONSTANT: { return val.type() != SymbolType::Fun; } + case REPLACE: + case UNTOUCHED: { return term->isNotFunction(); } + } + assert(false); + return false; +} +Term::SimplifyRet::~SimplifyRet() { + if (type == LINEAR || type == REPLACE) { delete term; } +} + +// }}}1 + +// {{{1 definition of PoolTerm + +PoolTerm::PoolTerm(UTermVec &&terms) + : args(std::move(terms)) { } + +void PoolTerm::rename(String) { + throw std::logic_error("must not be called"); +} + +unsigned PoolTerm::getLevel() const { + unsigned level = 0; + for (auto &x : args) { level = std::max(x->getLevel(), level); } + return level; +} + +unsigned PoolTerm::projectScore() const { + throw std::logic_error("Term::projectScore must be called after Term::unpool"); +} + +bool PoolTerm::isNotNumeric() const { return false; } +bool PoolTerm::isNotFunction() const { return false; } + +Term::Invertibility PoolTerm::getInvertibility() const { return Term::NOT_INVERTIBLE; } + +void PoolTerm::print(std::ostream &out) const { print_comma(out, args, ";", [](std::ostream &out, UTerm const &y) { out << *y; }); } + +Term::SimplifyRet PoolTerm::simplify(SimplifyState &, bool, bool, Logger &) { + throw std::logic_error("Term::simplify must be called after Term::unpool"); +} + +Term::ProjectRet PoolTerm::project(bool, AuxGen &) { + throw std::logic_error("Term::project must be called after Term::unpool"); +} + +bool PoolTerm::hasVar() const { + for (auto &x : args) { + if (x->hasVar()) { return true; } + } + return false; +} + +bool PoolTerm::hasPool() const { return true; } + +void PoolTerm::collect(VarTermBoundVec &vars, bool bound) const { + for (auto &y : args) { y->collect(vars, bound); } +} + +void PoolTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + for (auto &y : args) { y->collect(vars, minLevel, maxLevel); } +} + +Symbol PoolTerm::eval(bool &, Logger &) const { throw std::logic_error("Term::unpool must be called before Term::eval"); } + +bool PoolTerm::match(Symbol const &) const { throw std::logic_error("Term::unpool must be called before Term::match"); } + +void PoolTerm::unpool(UTermVec &x) const { + for (auto &t : args) { t->unpool(x); } +} + +UTerm PoolTerm::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &, bool) { + throw std::logic_error("Term::rewriteArithmetics must be called before Term::rewriteArithmetics"); +} + +bool PoolTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && is_value_equal_to(args, t->args); +} + +size_t PoolTerm::hash() const { + return get_value_hash(typeid(PoolTerm).hash_code(), args); +} + +PoolTerm *PoolTerm::clone() const { + return make_locatable(loc(), get_clone(args)).release(); +} + +Sig PoolTerm::getSig() const { assert(false); throw std::logic_error("Term::getSig must not be called on PoolTerm"); } + +UTerm PoolTerm::renameVars(RenameMap &names) const { + UTermVec args; + for (auto &x : this->args) { args.emplace_back(x->renameVars(names)); } + return make_locatable(loc(), std::move(args)); +} + +UGTerm PoolTerm::gterm(RenameMap &names, ReferenceMap &refs) const { return gringo_make_unique(_newRef(names, refs)); } + +void PoolTerm::collectIds(VarSet &x) const { + for (auto &y : args) { y->collectIds(x); } +} + +UTerm PoolTerm::replace(Defines &x, bool replace) { + for (auto &y : args) { Term::replace(y, y->replace(x, replace)); } + return nullptr; +} + +double PoolTerm::estimate(double, VarSet const &) const { + return 0; +} + +Symbol PoolTerm::isEDB() const { return {}; } + +bool PoolTerm::isAtom() const { + for (auto &x : args) { + if (!x->isAtom()) { return false; } + } + return true; +} + +PoolTerm::~PoolTerm() { } + +// {{{1 definition of ValTerm + +ValTerm::ValTerm(Symbol value) + : value(value) { } + +unsigned ValTerm::projectScore() const { + return 0; +} + +void ValTerm::rename(String x) { + value = Symbol::createId(x); +} + +unsigned ValTerm::getLevel() const { + return 0; +} + +bool ValTerm::isNotNumeric() const { return value.type() != SymbolType::Num; } +bool ValTerm::isNotFunction() const { return value.type() != SymbolType::Fun; } + +Term::Invertibility ValTerm::getInvertibility() const { return Term::CONSTANT; } + +void ValTerm::print(std::ostream &out) const { out << value; } + +Term::SimplifyRet ValTerm::simplify(SimplifyState &, bool, bool, Logger &) { return {value}; } + +Term::ProjectRet ValTerm::project(bool rename, AuxGen &) { + assert(!rename); (void)rename; + return std::make_tuple(nullptr, UTerm(clone()), UTerm(clone())); +} + +bool ValTerm::hasVar() const { + return false; +} + +bool ValTerm::hasPool() const { return false; } + +void ValTerm::collect(VarTermBoundVec &, bool) const { } + +void ValTerm::collect(VarSet &, unsigned, unsigned) const { } + +Symbol ValTerm::eval(bool &, Logger &) const { return value; } + +bool ValTerm::match(Symbol const &x) const { return value == x; } + +void ValTerm::unpool(UTermVec &x) const { + x.emplace_back(UTerm(clone())); +} + +UTerm ValTerm::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &, bool) { return nullptr; } + +bool ValTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && value == t->value; +} + +size_t ValTerm::hash() const { + return get_value_hash(typeid(ValTerm).hash_code(), value); +} + +ValTerm *ValTerm::clone() const { + return make_locatable(loc(), value).release(); +} + +Sig ValTerm::getSig() const { + if (value.type() == SymbolType::Fun) { return value.sig(); } + else { + throw std::logic_error("Term::getSig must not be called on ValTerm"); + } +} + +UTerm ValTerm::renameVars(RenameMap &) const { return UTerm(clone()); } + +UGTerm ValTerm::gterm(RenameMap &, ReferenceMap &) const { return gringo_make_unique(value); } + +void ValTerm::collectIds(VarSet &x) const { + if (value.type() == SymbolType::Fun && value.sig().arity() == 0) { x.emplace(value.name()); } +} + +UTerm ValTerm::replace(Defines &x, bool replace) { + Symbol retVal; + UTerm retTerm; + x.apply(value, retVal, retTerm, replace); + if (retVal.type() != SymbolType::Special) { value = retVal; } + else { return retTerm; } + return nullptr; +} + +double ValTerm::estimate(double, VarSet const &) const { + return 0; +} + +Symbol ValTerm::isEDB() const { return value; } + +bool ValTerm::isAtom() const { + return value.type() == SymbolType::Fun; +} + +ValTerm::~ValTerm() { } + +// {{{1 definition of VarTerm + +VarTerm::VarTerm(String name, SVal ref, unsigned level, bool bindRef) + : name(name) + , ref(ref) + , bindRef(bindRef) + , level(level) { assert(ref || name == "_"); } + +unsigned VarTerm::projectScore() const { + return 0; +} + +void VarTerm::rename(String) { + throw std::logic_error("must not be called"); +} + +unsigned VarTerm::getLevel() const { + return level; +} + +bool VarTerm::isNotNumeric() const { return false; } +bool VarTerm::isNotFunction() const { return false; } + +Term::Invertibility VarTerm::getInvertibility() const { return Term::INVERTIBLE; } + +void VarTerm::print(std::ostream &out) const { out << name; } + +Term::SimplifyRet VarTerm::simplify(SimplifyState &state, bool positional, bool arithmetic, Logger &) { + if (name == "_") { + ref = std::make_shared(); + if (positional) { return {*this, true}; } + else { name = state.gen.uniqueName("#Anon"); } + } + if (arithmetic) { return {make_locatable(loc(), *this, 1, 0)}; } + else { return {*this, false}; } +} + +Term::ProjectRet VarTerm::project(bool rename, AuxGen &auxGen) { + assert(!rename); (void)rename; + if (name == "_") { + UTerm r(make_locatable(loc(), Symbol::createId("#p"))); + UTerm x(r->clone()); + UTerm y(auxGen.uniqueVar(loc(), 0, "#P")); + return std::make_tuple(std::move(r), std::move(x), std::move(y)); + } + else { + UTerm y(auxGen.uniqueVar(loc(), 0, "#X")); + UTerm x(wrap(UTerm(y->clone()))); + return std::make_tuple(wrap(UTerm(clone())), std::move(x), std::move(y)); + } +} + +bool VarTerm::hasVar() const { return true; } + +bool VarTerm::hasPool() const { return false; } + +void VarTerm::collect(VarTermBoundVec &vars, bool bound) const { + vars.emplace_back(const_cast(this), bound); +} + +void VarTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + if (minLevel <= level && level <= maxLevel) { vars.emplace(name); } +} + +Symbol VarTerm::eval(bool &, Logger &) const { return *ref; } + +bool VarTerm::match(Symbol const &x) const { + if (bindRef) { + *ref = x; + return true; + } + else { return x == *ref; } +} + +void VarTerm::unpool(UTermVec &x) const { x.emplace_back(UTerm(clone())); } + +UTerm VarTerm::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &, bool) { return nullptr; } + +bool VarTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && name == t->name && level == t->level; +} + +size_t VarTerm::hash() const { + return get_value_hash(typeid(VarTerm).hash_code(), name, level); +} + +VarTerm *VarTerm::clone() const { + return make_locatable(loc(), name, ref, level, bindRef).release(); +} + +Sig VarTerm::getSig() const { throw std::logic_error("Term::getSig must not be called on VarTerm"); } + +UTerm VarTerm::renameVars(RenameMap &names) const { + auto ret(names.emplace(name, std::make_pair(name, nullptr))); + if (ret.second) { + ret.first->second.first = ((bindRef ? "X" : "Y") + std::to_string(names.size() - 1)).c_str(); + ret.first->second.second = std::make_shared(); + } + return make_locatable(loc(), ret.first->second.first, ret.first->second.second, 0, bindRef); +} + +UGTerm VarTerm::gterm(RenameMap &names, ReferenceMap &refs) const { return gringo_make_unique(_newRef(names, refs)); } + +void VarTerm::collectIds(VarSet &) const { } + +UTerm VarTerm::replace(Defines &, bool) { return nullptr; } + +double VarTerm::estimate(double size, VarSet const &bound) const { + return bound.find(name) == bound.end() ? size : 0.0; +} + +Symbol VarTerm::isEDB() const { return {}; } + +VarTerm::~VarTerm() { } + +// {{{1 definition of LinearTerm + +LinearTerm::LinearTerm(VarTerm const &var, int m, int n) + : var(static_cast(var.clone())) + , m(m) + , n(n) { } + +LinearTerm::LinearTerm(UVarTerm &&var, int m, int n) + : var(std::move(var)) + , m(m) + , n(n) { } + +unsigned LinearTerm::projectScore() const { + return 0; +} + +void LinearTerm::rename(String) { + throw std::logic_error("must not be called"); +} + +bool LinearTerm::hasVar() const { return true; } + +bool LinearTerm::hasPool() const { return false; } + +void LinearTerm::collect(VarTermBoundVec &vars, bool bound) const { + var->collect(vars, bound); +} + +void LinearTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + var->collect(vars, minLevel, maxLevel); +} + +unsigned LinearTerm::getLevel() const { + return var->getLevel(); +} + +bool LinearTerm::isNotNumeric() const { return false; } +bool LinearTerm::isNotFunction() const { return true; } + +Term::Invertibility LinearTerm::getInvertibility() const { return Term::INVERTIBLE; } + +void LinearTerm::print(std::ostream &out) const { out << "(" << m << "*" << *var << "+" << n << ")"; } + +Term::SimplifyRet LinearTerm::simplify(SimplifyState &, bool, bool, Logger &) { return {*this, false}; } + +Term::ProjectRet LinearTerm::project(bool rename, AuxGen &auxGen) { + assert(!rename); (void)rename; + UTerm y(auxGen.uniqueVar(loc(), 0, "#X")); + UTerm x(wrap(UTerm(y->clone()))); + return std::make_tuple(wrap(make_locatable(loc(), std::move(var), m, n)), std::move(x), std::move(y)); +} + +Symbol LinearTerm::eval(bool &undefined, Logger &log) const { + Symbol value = var->eval(undefined, log); + if (value.type() == SymbolType::Num) { return Symbol::createNum(m * value.num() + n); } + else { + undefined = true; + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc() << ": info: operation undefined:\n" + << " " << *this << "\n"; + return Symbol::createNum(0); + } +} + +bool LinearTerm::match(Symbol const &x) const { + if (x.type() == SymbolType::Num) { + assert(m != 0); + int c(x.num() - n); + if (c % m == 0) { return var->match(Symbol::createNum(c/m)); } + } + return false; +} + +void LinearTerm::unpool(UTermVec &x) const { + x.emplace_back(UTerm(clone())); +} + +UTerm LinearTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined) { + if (forceDefined) { + return Term::insert(arith, auxGen, make_locatable(loc(), *var, m, n), true); + } + return nullptr; +} + +bool LinearTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && m == t->m && n == t->n && is_value_equal_to(var, t->var); +} + +size_t LinearTerm::hash() const { + return get_value_hash(typeid(LinearTerm).hash_code(), m, n, var->hash()); +} + +LinearTerm *LinearTerm::clone() const { + return make_locatable(loc(), *var, m, n).release(); +} + +Sig LinearTerm::getSig() const { throw std::logic_error("Term::getSig must not be called on LinearTerm"); } + +UTerm LinearTerm::renameVars(RenameMap &names) const { + return make_locatable(loc(), UVarTerm(static_cast(var->renameVars(names).release())), m, n); +} + +UGTerm LinearTerm::gterm(RenameMap &names, ReferenceMap &refs) const { return gringo_make_unique(var->_newRef(names, refs), m, n); } + +void LinearTerm::collectIds(VarSet &) const { +} + +UTerm LinearTerm::replace(Defines &, bool) { + return nullptr; +} + +double LinearTerm::estimate(double size, VarSet const &bound) const { + return var->estimate(size, bound); +} + +Symbol LinearTerm::isEDB() const { return {}; } + +LinearTerm::~LinearTerm() { } + +// {{{1 definition of UnOpTerm + +// TODO: NEG has to be handled specially now - maybe I should add a new kind of term? + +UnOpTerm::UnOpTerm(UnOp op, UTerm &&arg) + : op(op) + , arg(std::move(arg)) { } + +unsigned UnOpTerm::projectScore() const { + return arg->projectScore(); +} + +void UnOpTerm::rename(String) { throw std::logic_error("must not be called"); } + +unsigned UnOpTerm::getLevel() const { return arg->getLevel(); } + +bool UnOpTerm::isNotNumeric() const { return false; } +bool UnOpTerm::isNotFunction() const { return op != UnOp::NEG; } + +Term::Invertibility UnOpTerm::getInvertibility() const { + return op == UnOp::NEG ? Term::INVERTIBLE : Term::NOT_INVERTIBLE; +} + +void UnOpTerm::print(std::ostream &out) const { + if (op == UnOp::ABS) { + out << "|" << *arg << "|"; + } + else { + // TODO: parenthesis are problematic if I want to use this term for predicates + out << "(" << op << *arg << ")"; + } +} + +Term::SimplifyRet UnOpTerm::simplify(SimplifyState &state, bool, bool arithmetic, Logger &log) { + bool multiNeg = !arithmetic && op == UnOp::NEG; + SimplifyRet ret(arg->simplify(state, false, !multiNeg, log)); + if (ret.undefined()) { + return {}; + } + else if ((multiNeg && ret.notNumeric() && ret.notFunction()) || (!multiNeg && ret.notNumeric())) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc() << ": info: operation undefined:\n" + << " " << *this << "\n"; + return {}; + } + switch (ret.type) { + case SimplifyRet::CONSTANT: { + if (ret.val.type() == SymbolType::Num) { + return {Symbol::createNum(Gringo::eval(op, ret.val.num()))}; + } + else { + assert(ret.val.type() == SymbolType::Fun); + return {ret.val.flipSign()}; + } + } + case SimplifyRet::LINEAR: { + if (op == UnOp::NEG) { + ret.lin().m *= -1; + ret.lin().n *= -1; + return ret; + } + } + default: { + ret.update(arg); + return {*this, false}; + } + } +} +Term::ProjectRet UnOpTerm::project(bool rename, AuxGen &auxGen) { + assert(!rename); (void)rename; + UTerm y(auxGen.uniqueVar(loc(), 0, "#X")); + UTerm x(wrap(UTerm(y->clone()))); + return std::make_tuple(wrap(make_locatable(loc(), op, std::move(arg))), std::move(x), std::move(y)); +} +bool UnOpTerm::hasVar() const { + return arg->hasVar(); +} +bool UnOpTerm::hasPool() const { return arg->hasPool(); } +void UnOpTerm::collect(VarTermBoundVec &vars, bool bound) const { + arg->collect(vars, bound && op == UnOp::NEG); +} +void UnOpTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + arg->collect(vars, minLevel, maxLevel); +} +Symbol UnOpTerm::eval(bool &undefined, Logger &log) const { + Symbol value = arg->eval(undefined, log); + if (value.type() == SymbolType::Num) { + int num = value.num(); + switch (op) { + case UnOp::NEG: { return Symbol::createNum(-num); } + case UnOp::ABS: { return Symbol::createNum(std::abs(num)); } + case UnOp::NOT: { return Symbol::createNum(~num); } + } + assert(false); + return Symbol::createNum(0); + } + else if (op == UnOp::NEG && value.type() == SymbolType::Fun) { + return value.flipSign(); + } + else { + undefined = true; + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc() << ": info: operation undefined:\n" + << " " << *this << "\n"; + return Symbol::createNum(0); + } +} +bool UnOpTerm::match(Symbol const &x) const { + if (op != UnOp::NEG) { + throw std::logic_error("Term::rewriteArithmetics must be called before Term::match"); + } + if (x.type() == SymbolType::Num) { + return arg->match(Symbol::createNum(-x.num())); + } + else if (x.type() == SymbolType::Fun) { + return arg->match(x.flipSign()); + } + return false; +} +void UnOpTerm::unpool(UTermVec &x) const { + auto f = [&](UTerm &&y) { x.emplace_back(make_locatable(loc(), op, std::move(y))); }; + Term::unpool(arg, Gringo::unpool, f); +} +UTerm UnOpTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined) { + if (!forceDefined && op == UnOp::NEG) { + Term::replace(arg, arg->rewriteArithmetics(arith, auxGen, false)); + return nullptr; + } + else { + return Term::insert(arith, auxGen, make_locatable(loc(), op, std::move(arg)), forceDefined && op == UnOp::NEG); + } +} +bool UnOpTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && op == t->op && is_value_equal_to(arg, t->arg); +} +size_t UnOpTerm::hash() const { + return get_value_hash(typeid(UnOpTerm).hash_code(), size_t(op), arg); +} +UnOpTerm *UnOpTerm::clone() const { + return make_locatable(loc(), op, get_clone(arg)).release(); +} +Sig UnOpTerm::getSig() const { + if (op == UnOp::NEG) { return arg->getSig().flipSign(); } + throw std::logic_error("Term::getSig must not be called on UnOpTerm"); +} +UTerm UnOpTerm::renameVars(RenameMap &names) const { return make_locatable(loc(), op, arg->renameVars(names)); } +UGTerm UnOpTerm::gterm(RenameMap &names, ReferenceMap &refs) const { + if (op == UnOp::NEG) { + UGFunTerm fun(arg->gfunterm(names, refs)); + if (fun) { + fun->sign = !fun->sign; + return std::move(fun); + } + } + return gringo_make_unique(_newRef(names, refs)); +} + +UGFunTerm UnOpTerm::gfunterm(RenameMap &names, ReferenceMap &refs) const { + if (op != UnOp::NEG) { return nullptr; } + UGFunTerm fun(arg->gfunterm(names, refs)); + if (!fun) { return nullptr; } + fun->sign = ! fun->sign; + return fun; +} + +void UnOpTerm::collectIds(VarSet &x) const { + arg->collectIds(x); +} +UTerm UnOpTerm::replace(Defines &x, bool) { + Term::replace(arg, arg->replace(x, true)); + return nullptr; +} +double UnOpTerm::estimate(double, VarSet const &) const { + return 0; +} +Symbol UnOpTerm::isEDB() const { return {}; } +bool UnOpTerm::isAtom() const { + return op == UnOp::NEG && arg->isAtom(); +} +UnOpTerm::~UnOpTerm() { } + +// {{{1 definition of BinOpTerm + +BinOpTerm::BinOpTerm(BinOp op, UTerm &&left, UTerm &&right) + : op(op) + , left(std::move(left)) + , right(std::move(right)) { } + +unsigned BinOpTerm::projectScore() const { + return left->projectScore() + right->projectScore(); +} + +void BinOpTerm::rename(String) { + throw std::logic_error("must not be called"); +} + +unsigned BinOpTerm::getLevel() const { + return std::max(left->getLevel(), right->getLevel()); +} + +bool BinOpTerm::isNotNumeric() const { return false; } +bool BinOpTerm::isNotFunction() const { return true; } + +Term::Invertibility BinOpTerm::getInvertibility() const { return Term::NOT_INVERTIBLE; } + +void BinOpTerm::print(std::ostream &out) const { + out << "(" << *left << op << *right << ")"; +} + +Term::SimplifyRet BinOpTerm::simplify(SimplifyState &state, bool, bool, Logger &log) { + auto retLeft(left->simplify(state, false, true, log)); + auto retRight(right->simplify(state, false, true, log)); + if (retLeft.undefined() || retRight.undefined()) { + return {}; + } + else if (retLeft.notNumeric() || retRight.notNumeric() || (op == BinOp::DIV && retRight.isZero())) { + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc() << ": info: operation undefined:\n" + << " " << *this << "\n"; + return {}; + } + else if (op == BinOp::MUL && (retLeft.isZero() || retRight.isZero())) { + // NOTE: keep binary operation untouched + } + else if (retLeft.type == SimplifyRet::CONSTANT && retRight.type == SimplifyRet::CONSTANT) { + return {Symbol::createNum(Gringo::eval(op, retLeft.val.num(), retRight.val.num()))}; + } + else if (retLeft.type == SimplifyRet::CONSTANT && retRight.type == SimplifyRet::LINEAR) { + if (op == BinOp::ADD) { + retRight.lin().n += retLeft.val.num(); + return retRight; + } + else if (op == BinOp::SUB) { + retRight.lin().n = retLeft.val.num() - retRight.lin().n; + retRight.lin().m = -retRight.lin().m; + return retRight; + } + else if (op == BinOp::MUL) { + retRight.lin().n *= retLeft.val.num(); + retRight.lin().m *= retLeft.val.num(); + return retRight; + } + } + else if (retLeft.type == SimplifyRet::LINEAR && retRight.type == SimplifyRet::CONSTANT) { + if (op == BinOp::ADD) { + retLeft.lin().n += retRight.val.num(); + return retLeft; + } + else if (op == BinOp::SUB) { + retLeft.lin().n-= retRight.val.num(); + return retLeft; + } + else if (op == BinOp::MUL) { + retLeft.lin().n *= retRight.val.num(); + retLeft.lin().m *= retRight.val.num(); + return retLeft; + } + } + retLeft.update(left); + retRight.update(right); + return {*this, false}; +} + +Term::ProjectRet BinOpTerm::project(bool rename, AuxGen &auxGen) { + assert(!rename); (void)rename; + UTerm y(auxGen.uniqueVar(loc(), 0, "#X")); + UTerm x(wrap(UTerm(y->clone()))); + return std::make_tuple(wrap(make_locatable(loc(), op, std::move(left), std::move(right))), std::move(x), std::move(y)); +} + +bool BinOpTerm::hasVar() const { + return left->hasVar() || right->hasVar(); +} + +bool BinOpTerm::hasPool() const { return left->hasPool() || right->hasPool(); } + +void BinOpTerm::collect(VarTermBoundVec &vars, bool) const { + left->collect(vars, false); + right->collect(vars, false); +} + +void BinOpTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + left->collect(vars, minLevel, maxLevel); + right->collect(vars, minLevel, maxLevel); +} + +Symbol BinOpTerm::eval(bool &undefined, Logger &log) const { + Symbol l(left->eval(undefined, log)); + Symbol r(right->eval(undefined, log)); + if (l.type() == SymbolType::Num && r.type() == SymbolType::Num && (op != BinOp::DIV || r.num() != 0)) { return Symbol::createNum(Gringo::eval(op, l.num(), r.num())); } + else { + undefined = true; + GRINGO_REPORT(log, clingo_warning_operation_undefined) + << loc() << ": info: operation undefined:\n" + << " " << *this << "\n"; + return Symbol::createNum(0); + } +} + +bool BinOpTerm::match(Symbol const &) const { throw std::logic_error("Term::rewriteArithmetics must be called before Term::match"); } + +void BinOpTerm::unpool(UTermVec &x) const { + auto f = [&](UTerm &&l, UTerm &&r) { x.emplace_back(make_locatable(loc(), op, std::move(l), std::move(r))); }; + Term::unpool(left, right, Gringo::unpool, Gringo::unpool, f); +} + +UTerm BinOpTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen, bool) { + return Term::insert(arith, auxGen, make_locatable(loc(), op, std::move(left), std::move(right))); +} + +bool BinOpTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && op == t->op && is_value_equal_to(left, t->left) && is_value_equal_to(right, t->right); +} + +size_t BinOpTerm::hash() const { + return get_value_hash(typeid(BinOpTerm).hash_code(), size_t(op), left, right); +} + +BinOpTerm *BinOpTerm::clone() const { + return make_locatable(loc(), op, get_clone(left), get_clone(right)).release(); +} + +Sig BinOpTerm::getSig() const { throw std::logic_error("Term::getSig must not be called on DotsTerm"); } + +UTerm BinOpTerm::renameVars(RenameMap &names) const { + UTerm term(left->renameVars(names)); + return make_locatable(loc(), op, std::move(term), right->renameVars(names)); +} + +UGTerm BinOpTerm::gterm(RenameMap &names, ReferenceMap &refs) const { return gringo_make_unique(_newRef(names, refs)); } + +void BinOpTerm::collectIds(VarSet &x) const { + left->collectIds(x); + right->collectIds(x); +} + +UTerm BinOpTerm::replace(Defines &x, bool) { + Term::replace(left, left->replace(x, true)); + Term::replace(right, right->replace(x, true)); + return nullptr; +} + +double BinOpTerm::estimate(double, VarSet const &) const { + return 0; +} + +Symbol BinOpTerm::isEDB() const { return {}; } + +BinOpTerm::~BinOpTerm() { } + +// {{{1 definition of DotsTerm + +DotsTerm::DotsTerm(UTerm &&left, UTerm &&right) + : left(std::move(left)) + , right(std::move(right)) { } + +unsigned DotsTerm::projectScore() const { + return 2; +} + +void DotsTerm::rename(String) { + throw std::logic_error("must not be called"); +} +unsigned DotsTerm::getLevel() const { + return std::max(left->getLevel(), right->getLevel()); +} + +bool DotsTerm::isNotNumeric() const { return false; } +bool DotsTerm::isNotFunction() const { return true; } + +Term::Invertibility DotsTerm::getInvertibility() const { return Term::NOT_INVERTIBLE; } + +void DotsTerm::print(std::ostream &out) const { + out << "(" << *left << ".." << *right << ")"; +} + +Term::SimplifyRet DotsTerm::simplify(SimplifyState &state, bool, bool, Logger &log) { + if (!left->simplify(state, false, false, log).update(left).undefined() && !right->simplify(state, false, false, log).update(right).undefined()) { + return { state.createDots(loc(), std::move(left), std::move(right)) }; + } + else { + return {}; + } +} + +Term::ProjectRet DotsTerm::project(bool, AuxGen &) { + throw std::logic_error("Term::project must be called after Term::simplify"); +} + +bool DotsTerm::hasVar() const { + return left->hasVar() || right->hasVar(); +} + +bool DotsTerm::hasPool() const { return left->hasPool() || right->hasPool(); } + +void DotsTerm::collect(VarTermBoundVec &vars, bool) const { + left->collect(vars, false); + right->collect(vars, false); +} + +void DotsTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + left->collect(vars, minLevel, maxLevel); + right->collect(vars, minLevel, maxLevel); +} + +Symbol DotsTerm::eval(bool &, Logger &) const { throw std::logic_error("Term::rewriteDots must be called before Term::eval"); } + +bool DotsTerm::match(Symbol const &) const { throw std::logic_error("Term::rewriteDots must be called before Term::match"); } + +void DotsTerm::unpool(UTermVec &x) const { + auto f = [&](UTerm &&l, UTerm &&r) { x.emplace_back(make_locatable(loc(), std::move(l), std::move(r))); }; + Term::unpool(left, right, Gringo::unpool, Gringo::unpool, f); +} + +UTerm DotsTerm::rewriteArithmetics(Term::ArithmeticsMap &, AuxGen &, bool) { + throw std::logic_error("Term::rewriteDots must be called before Term::rewriteArithmetics"); +} + +bool DotsTerm::operator==(Term const &) const { + // Note: each DotsTerm is associated to a unique variable + return false; +} + +size_t DotsTerm::hash() const { + return get_value_hash(typeid(DotsTerm).hash_code(), left, right); +} + +DotsTerm *DotsTerm::clone() const { + return make_locatable(loc(), get_clone(left), get_clone(right)).release(); +} + +Sig DotsTerm::getSig() const { throw std::logic_error("Term::getSig must not be called on LuaTerm"); } + +UTerm DotsTerm::renameVars(RenameMap &names) const { + UTerm term(left->renameVars(names)); + return make_locatable(loc(), std::move(term), right->renameVars(names)); +} + +UGTerm DotsTerm::gterm(RenameMap &names, ReferenceMap &refs) const { return gringo_make_unique(_newRef(names, refs)); } + +void DotsTerm::collectIds(VarSet &x) const { + left->collectIds(x); + right->collectIds(x); +} + +UTerm DotsTerm::replace(Defines &x, bool) { + Term::replace(left, left->replace(x, true)); + Term::replace(right, right->replace(x, true)); + return nullptr; +} + +double DotsTerm::estimate(double, VarSet const &) const { + return 0; +} + +Symbol DotsTerm::isEDB() const { return {}; } + +DotsTerm::~DotsTerm() { } + +// {{{1 definition of LuaTerm + +LuaTerm::LuaTerm(String name, UTermVec &&args) + : name(name) + , args(std::move(args)) { } + +unsigned LuaTerm::projectScore() const { + return 2; +} + +void LuaTerm::rename(String) { + throw std::logic_error("must not be called"); +} + +unsigned LuaTerm::getLevel() const { + unsigned level = 0; + for (auto &x : args) { level = std::max(x->getLevel(), level); } + return level; +} + +bool LuaTerm::isNotNumeric() const { return false; } +bool LuaTerm::isNotFunction() const { return false; } + +Term::Invertibility LuaTerm::getInvertibility() const { return Term::NOT_INVERTIBLE; } + +void LuaTerm::print(std::ostream &out) const { + out << "@" << name << "("; + print_comma(out, args, ",", [](std::ostream &out, UTerm const &y) { out << *y; }); + out << ")"; +} + +Term::SimplifyRet LuaTerm::simplify(SimplifyState &state, bool, bool, Logger &log) { + for (auto &arg : args) { + if (arg->simplify(state, false, false, log).update(arg).undefined()) { + return {}; + } + } + return { state.createScript(loc(), std::move(name), std::move(args)) }; +} + +Term::ProjectRet LuaTerm::project(bool rename, AuxGen &auxGen) { + assert(!rename); (void)rename; + UTerm y(auxGen.uniqueVar(loc(), 0, "#X")); + UTerm x(wrap(UTerm(y->clone()))); + return std::make_tuple(make_locatable(loc(), name, std::move(args)), std::move(x), std::move(y)); +} + +bool LuaTerm::hasVar() const { + for (auto &x : args) { + if (x->hasVar()) { return true; } + } + return false; +} + +bool LuaTerm::hasPool() const { + for (auto &x : args) { if (x->hasPool()) { return true; } } + return false; +} + +void LuaTerm::collect(VarTermBoundVec &vars, bool) const { + for (auto &y : args) { y->collect(vars, false); } +} + +void LuaTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + for (auto &y : args) { y->collect(vars, minLevel, maxLevel); } +} + +Symbol LuaTerm::eval(bool &, Logger &) const { throw std::logic_error("Term::simplify must be called before Term::eval"); } + +bool LuaTerm::match(Symbol const &) const { throw std::logic_error("Term::rewriteArithmetics must be called before Term::match"); } + +void LuaTerm::unpool(UTermVec &x) const { + auto f = [&](UTermVec &&args) { x.emplace_back(make_locatable(loc(), name, std::move(args))); }; + Term::unpool(args.begin(), args.end(), Gringo::unpool, f); +} + +UTerm LuaTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen, bool) { + return Term::insert(arith, auxGen, make_locatable(loc(), name, std::move(args))); +} + +bool LuaTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && name == t->name && is_value_equal_to(args, t->args); +} + +size_t LuaTerm::hash() const { + return get_value_hash(typeid(LuaTerm).hash_code(), name, args); +} + +LuaTerm *LuaTerm::clone() const { + return make_locatable(loc(), name, get_clone(args)).release(); +} + +Sig LuaTerm::getSig() const { return Sig(name, args.size(), false); } + +UTerm LuaTerm::renameVars(RenameMap &names) const { + UTermVec args; + for (auto &x : this->args) { args.emplace_back(x->renameVars(names)); } + return make_locatable(loc(), name, std::move(args)); +} + +UGTerm LuaTerm::gterm(RenameMap &names, ReferenceMap &refs) const { return gringo_make_unique(_newRef(names, refs)); } + +void LuaTerm::collectIds(VarSet &x) const { + for (auto &y : args) { y->collectIds(x); } +} + +UTerm LuaTerm::replace(Defines &x, bool) { + for (auto &y : args) { Term::replace(y, y->replace(x, true)); } + return nullptr; +} + +double LuaTerm::estimate(double, VarSet const &) const { + return 0; +} + +Symbol LuaTerm::isEDB() const { return {}; } + +LuaTerm::~LuaTerm() { } + +// {{{1 definition of FunctionTerm + +FunctionTerm::FunctionTerm(String name, UTermVec &&args) + : name(name) + , args(std::move(args)) { } + +unsigned FunctionTerm::projectScore() const { + unsigned ret = 0; + for (auto &x : args) { ret += x->projectScore(); } + return ret; +} + +void FunctionTerm::rename(String x) { + name = x; +} + +unsigned FunctionTerm::getLevel() const { + unsigned level = 0; + for (auto &x : args) { level = std::max(x->getLevel(), level); } + return level; +} + +bool FunctionTerm::isNotNumeric() const { return true; } +bool FunctionTerm::isNotFunction() const { return false; } + +Term::Invertibility FunctionTerm::getInvertibility() const { return Term::INVERTIBLE; } + +void FunctionTerm::print(std::ostream &out) const { + out << name << "("; + print_comma(out, args, ",", [](std::ostream &out, UTerm const &y) { out << *y; }); + if (name == "" && args.size() == 1) { + out << ","; + } + out << ")"; +} + +Term::SimplifyRet FunctionTerm::simplify(SimplifyState &state, bool positional, bool, Logger &log) { + bool constant = true; + bool projected = false; + for (auto &arg : args) { + auto ret(arg->simplify(state, positional, false, log)); + if (ret.undefined()) { + return {}; + } + constant = constant && ret.constant(); + projected = projected || ret.project; + ret.update(arg); + } + if (constant) { + bool undefined; + return {eval(undefined, log)}; + } + else { return {*this, projected}; } +} + +Term::ProjectRet FunctionTerm::project(bool rename, AuxGen &auxGen) { + UTermVec argsProjected; + UTermVec argsProject; + for (auto &arg : args) { + auto ret(arg->project(false, auxGen)); + Term::replace(arg, std::move(std::get<0>(ret))); + argsProjected.emplace_back(std::move(std::get<1>(ret))); + argsProject.emplace_back(std::move(std::get<2>(ret))); + } + String oldName = name; + if (rename) { name = String((std::string("#p_") + name.c_str()).c_str()); } + return std::make_tuple( + nullptr, + make_locatable(loc(), name, std::move(argsProjected)), + make_locatable(loc(), oldName, std::move(argsProject))); +} + +bool FunctionTerm::hasVar() const { + for (auto &x : args) { + if (x->hasVar()) { return true; } + } + return false; +} + +bool FunctionTerm::hasPool() const { + for (auto &x : args) { if (x->hasPool()) { return true; } } + return false; +} + +void FunctionTerm::collect(VarTermBoundVec &vars, bool bound) const { + for (auto &y : args) { y->collect(vars, bound); } +} + +void FunctionTerm::collect(VarSet &vars, unsigned minLevel , unsigned maxLevel) const { + for (auto &y : args) { y->collect(vars, minLevel, maxLevel); } +} + +Symbol FunctionTerm::eval(bool &undefined, Logger &log) const { + cache.clear(); + for (auto &term : args) { cache.emplace_back(term->eval(undefined, log)); } + return Symbol::createFun(name, Potassco::toSpan(cache)); +} + +bool FunctionTerm::match(Symbol const &x) const { + if (x.type() == SymbolType::Fun) { + Sig s(x.sig()); + if (!s.sign() && s.name() == name && s.arity() == args.size()) { + auto i = 0; + for (auto &term : args) { + if (!term->match(x.args()[i++])) { return false; } + } + return true; + } + } + return false; +} + +void FunctionTerm::unpool(UTermVec &x) const { + auto f = [&](UTermVec &&args) { x.emplace_back(make_locatable(loc(), name, std::move(args))); }; + Term::unpool(args.begin(), args.end(), Gringo::unpool, f); +} + +UTerm FunctionTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen, bool forceDefined) { + for (auto &arg : args) { Term::replace(arg, arg->rewriteArithmetics(arith, auxGen, forceDefined)); } + return nullptr; +} + +bool FunctionTerm::operator==(Term const &x) const { + auto t = dynamic_cast(&x); + return t && name == t->name && is_value_equal_to(args, t->args); +} + +size_t FunctionTerm::hash() const { + return get_value_hash(typeid(FunctionTerm).hash_code(), name, args); +} + +FunctionTerm *FunctionTerm::clone() const { + return make_locatable(loc(), name, get_clone(args)).release(); +} + +Sig FunctionTerm::getSig() const { return Sig(name, args.size(), false); } + +UTerm FunctionTerm::renameVars(RenameMap &names) const { + UTermVec args; + for (auto &x : this->args) { args.emplace_back(x->renameVars(names)); } + return make_locatable(loc(), name, std::move(args)); +} + +UGTerm FunctionTerm::gterm(RenameMap &names, ReferenceMap &refs) const { + return gfunterm(names, refs); +} + +UGFunTerm FunctionTerm::gfunterm(RenameMap &names, ReferenceMap &refs) const { + UGTermVec args; + for (auto &x : this->args) { args.emplace_back(x->gterm(names, refs)); } + return gringo_make_unique(name, std::move(args)); +} + +void FunctionTerm::collectIds(VarSet &x) const { + for (auto &y : args) { y->collectIds(x); } +} + +UTerm FunctionTerm::replace(Defines &x, bool) { + for (auto &y : args) { Term::replace(y, y->replace(x, true)); } + return nullptr; +} + +double FunctionTerm::estimate(double size, VarSet const &bound) const { + double ret = 0.0; + if (!args.empty()) { + double root = std::max(1.0, std::pow((name.empty() ? size : size/2.0), 1.0/args.size())); + for (auto &x : args) { ret += x->estimate(root, bound); } + ret /= args.size(); + } + return ret; +} + +Symbol FunctionTerm::isEDB() const { + cache.clear(); + for (auto &x : args) { + cache.emplace_back(x->isEDB()); + if (cache.back().type() == SymbolType::Special) { return {}; } + } + return Symbol::createFun(name, Potassco::toSpan(cache)); +} + +bool FunctionTerm::isAtom() const { + return true; +} + +FunctionTerm::~FunctionTerm() { } + +// }}}1 + +} // namespace Gringo diff --git a/libgringo/src/terms.cc b/libgringo/src/terms.cc new file mode 100644 index 0000000..f6c95a3 --- /dev/null +++ b/libgringo/src/terms.cc @@ -0,0 +1,441 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/terms.hh" +#include "gringo/logger.hh" +#include + +namespace Gringo { + +// {{{1 TheoryOpDef + +TheoryOpDef::TheoryOpDef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) +: loc_(loc) +, op_(op) +, priority_(priority) +, type_(type) { } + +TheoryOpDef::TheoryOpDef(TheoryOpDef &&) = default; + +String TheoryOpDef::op() const { + return op_; +} + +TheoryOpDef::Key TheoryOpDef::key() const { + return {op_, type_ == TheoryOperatorType::Unary}; +} + +TheoryOpDef::~TheoryOpDef() noexcept = default; + +TheoryOpDef &TheoryOpDef::operator=(TheoryOpDef &&) = default; + +Location const &TheoryOpDef::loc() const { + return loc_; +} + +void TheoryOpDef::print(std::ostream &out) const { + out << op_ << " :" << priority_ << "," << type_; +} + +unsigned TheoryOpDef::priority() const { + return priority_; +} + +TheoryOperatorType TheoryOpDef::type() const { + return type_; +} + +// {{{1 TheoryTermDef + +TheoryTermDef::TheoryTermDef(Location const &loc, String name) +: loc_(loc) +, name_(name) { } + +TheoryTermDef::TheoryTermDef(TheoryTermDef &&) = default; + +void TheoryTermDef::addOpDef(TheoryOpDef &&def, Logger &log) { + auto it = opDefs_.find(def.key()); + if (it == opDefs_.end()) { + opDefs_.push(std::move(def)); + } + else { + GRINGO_REPORT(log, clingo_error_runtime) + << def.loc() << ": error: redefinition of theory operator:" << "\n" + << " " << def.op() << "\n" + << it->loc() << ": note: operator first defined here\n"; + } +} + +String TheoryTermDef::name() const { + return name_; +} + +Location const &TheoryTermDef::loc() const { + return loc_; +} + +TheoryTermDef::~TheoryTermDef() noexcept = default; + +TheoryTermDef &TheoryTermDef::operator=(TheoryTermDef &&) = default; + +void TheoryTermDef::print(std::ostream &out) const { + out << name_ << "{"; + print_comma(out, opDefs_, ","); + out << "}"; +} + +std::pair TheoryTermDef::getPrioAndAssoc(String op) const { + auto ret = opDefs_.find(TheoryOpDef::Key{op, false}); + if (ret != opDefs_.end()) { + return {ret->priority(), ret->type() == TheoryOperatorType::BinaryLeft}; + } + else { + return {0, true}; + } +} + +bool TheoryTermDef::hasOp(String op, bool unary) const { + return opDefs_.find(TheoryOpDef::Key{op, unary}) != opDefs_.end(); +} + +unsigned TheoryTermDef::getPrio(String op, bool unary) const { + auto ret = opDefs_.find(TheoryOpDef::Key{op, unary}); + if (ret != opDefs_.end()) { + return ret->priority(); + } + else { + return 0; + } +} + +// {{{1 TheoryAtomDef + +TheoryAtomDef::TheoryAtomDef(Location const &loc, String name, unsigned arity, String elemDef, TheoryAtomType type) +: TheoryAtomDef(loc, name, arity, elemDef, type, {}, "") { } + +TheoryAtomDef::TheoryAtomDef(Location const &loc, String name, unsigned arity, String elemDef, TheoryAtomType type, StringVec &&ops, String guardDef) +: loc_(loc) +, sig_(name, arity, false) +, elemDef_(elemDef) +, guardDef_(guardDef) +, ops_(std::move(ops)) +, type_(type) { } + +TheoryAtomDef::TheoryAtomDef(TheoryAtomDef &&) = default; + +Sig TheoryAtomDef::sig() const { + return sig_; +} + +bool TheoryAtomDef::hasGuard() const { + return !ops_.empty(); +} + +TheoryAtomType TheoryAtomDef::type() const { + return type_; +} + +Location const &TheoryAtomDef::loc() const { + return loc_; +} + +StringVec const &TheoryAtomDef::ops() const { + return ops_; +} + +String TheoryAtomDef::elemDef() const { + return elemDef_; +} + +String TheoryAtomDef::guardDef() const { + assert(hasGuard()); + return guardDef_; +} + +TheoryAtomDef::~TheoryAtomDef() noexcept = default; + +TheoryAtomDef &TheoryAtomDef::operator=(TheoryAtomDef &&) = default; + +void TheoryAtomDef::print(std::ostream &out) const { + out << "&" << sig_.name() << "/" << sig_.arity() << ":" << elemDef_; + if (hasGuard()) { + out << ",{"; + print_comma(out, ops_, ","); + out << "}," << guardDef_; + } + out << "," << type_; +} + +// {{{1 TheoryDef + +TheoryDef::TheoryDef(Location const &loc, String name) +: loc_(loc) +, name_(name) { } + +TheoryDef::TheoryDef(TheoryDef &&) = default; + +String TheoryDef::name() const { + return name_; +} + +Location const &TheoryDef::loc() const { + return loc_; +} + +void TheoryDef::addAtomDef(TheoryAtomDef &&def, Logger &log) { + auto it = atomDefs_.find(def.sig()); + if (it == atomDefs_.end()) { + atomDefs_.push(std::move(def)); + } + else { + GRINGO_REPORT(log, clingo_error_runtime) + << def.loc() << ": error: redefinition of theory atom:" << "\n" + << " " << def.sig() << "\n" + << it->loc() << ": note: atom first defined here\n"; + } +} + +void TheoryDef::addTermDef(TheoryTermDef &&def, Logger &log) { + auto it = termDefs_.find(def.name()); + if (it == termDefs_.end()) { + termDefs_.push(std::move(def)); + } + else { + GRINGO_REPORT(log, clingo_error_runtime) + << def.loc() << ": error: redefinition of theory term:" << "\n" + << " " << def.name() << "\n" + << it->loc() << ": note: term first defined term\n"; + } +} + +TheoryDef::~TheoryDef() noexcept = default; + +TheoryDef &TheoryDef::operator=(TheoryDef &&) = default; + +void TheoryDef::print(std::ostream &out) const { + out << "#theory " << name_ << "{"; + if (!atomDefs_.empty() || !termDefs_.empty()) { + out << "\n"; + } + bool sep = false; + for (auto &def : termDefs_) { + if (sep) { out << ";\n"; } + else { sep = true; } + out << " " << def; + } + for (auto &def : atomDefs_) { + if (sep) { out << ";\n"; } + else { sep = true; } + out << " " << def; + } + if (sep) { + out << "\n"; + } + out << "}."; +} + +TheoryAtomDef const *TheoryDef::getAtomDef(Sig sig) const { + auto ret = atomDefs_.find(sig); + return ret != atomDefs_.end() ? &*ret : nullptr; +} + +TheoryTermDef const *TheoryDef::getTermDef(String name) const { + auto ret = termDefs_.find(name); + return ret != termDefs_.end() ? &*ret : nullptr; +} + +TheoryAtomDefs const &TheoryDef::atomDefs() const { + return atomDefs_; +} + +// }}}1 + +// {{{1 definition of CSPRelTerm + +CSPRelTerm::CSPRelTerm(CSPRelTerm &&) = default; +CSPRelTerm &CSPRelTerm::operator=(CSPRelTerm &&) = default; + +CSPRelTerm::CSPRelTerm(Relation rel, CSPAddTerm &&term) + : rel(rel) + , term(std::move(term)) { } + +void CSPRelTerm::collect(VarTermBoundVec &vars) const { term.collect(vars); } +void CSPRelTerm::collect(VarTermSet &vars) const { term.collect(vars); } +void CSPRelTerm::replace(Defines &x) { term.replace(x); } +bool CSPRelTerm::operator==(CSPRelTerm const &x) const { return rel == x.rel && term == x.term; } +bool CSPRelTerm::simplify(SimplifyState &state, Logger &log) { return term.simplify(state, log); } +void CSPRelTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { term.rewriteArithmetics(arith, auxGen); } +size_t CSPRelTerm::hash() const { return get_value_hash(size_t(rel), term); } +bool CSPRelTerm::hasPool() const { return term.hasPool(); } +std::vector CSPRelTerm::unpool() const { + std::vector ret; + for (auto &x : term.unpool()) { ret.emplace_back(rel, std::move(x)); } + return ret; +} +CSPRelTerm::~CSPRelTerm() { } +std::ostream &operator<<(std::ostream &out, CSPRelTerm const &x) { + out << "$" << x.rel << x.term; + return out; +} +CSPRelTerm clone::operator()(CSPRelTerm const &x) const { + return CSPRelTerm(x.rel, get_clone(x.term)); +} + +// {{{1 definition of CSPAddTerm + +CSPAddTerm::CSPAddTerm(CSPAddTerm &&) = default; +CSPAddTerm &CSPAddTerm::operator=(CSPAddTerm &&) = default; + +CSPAddTerm::CSPAddTerm(CSPMulTerm &&x) { terms.emplace_back(std::move(x)); } +CSPAddTerm::CSPAddTerm(Terms &&terms) : terms(std::move(terms)) { } + +void CSPAddTerm::append(CSPMulTerm &&x) { terms.emplace_back(std::move(x)); } + +void CSPAddTerm::collect(VarTermBoundVec &vars) const { + for (auto &x : terms) { x.collect(vars); } +} +void CSPAddTerm::collect(VarTermSet &vars) const { + for (auto &x : terms) { x.collect(vars); } +} +void CSPAddTerm::replace(Defines &x) { + for (auto &y : terms) { y.replace(x); } +} +bool CSPAddTerm::operator==(CSPAddTerm const &x) const { return is_value_equal_to(terms, x.terms); } +bool CSPAddTerm::simplify(SimplifyState &state, Logger &log) { + for (auto &y : terms) { + if (!y.simplify(state, log)) { return false; } + } + return true; +} +void CSPAddTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + for (auto &x : terms) { x.rewriteArithmetics(arith, auxGen); } +} +size_t CSPAddTerm::hash() const { return get_value_hash(terms); } +bool CSPAddTerm::hasPool() const { + for (auto &y : terms) { + if (y.hasPool()) { return true; } + } + return false; +} +std::vector CSPAddTerm::unpool() const { + std::vector x; + auto f = [&](Terms &&args) { x.emplace_back(std::move(args)); }; + Term::unpool(terms.begin(), terms.end(), std::bind(&CSPMulTerm::unpool, std::placeholders::_1), f); + return x; +} +void CSPAddTerm::toGround(CSPGroundLit &ground, bool invert, Logger &log) const { + bool undefined = false; + for (auto &x : terms) { + int coe = x.coe->toNum(undefined, log); + if (coe != 0) { + if (x.var) { std::get<1>(ground).emplace_back(invert ? -coe : coe, x.var->eval(undefined, log)); } + else { std::get<2>(ground) = eval(invert ? BinOp::ADD : BinOp::SUB, std::get<2>(ground), coe); } + } + } + assert(!undefined); +} + +bool CSPAddTerm::checkEval(Logger &log) const { + for (auto &x : terms) { + bool undefined = false; + x.coe->toNum(undefined, log); + if (undefined) { return false; } + if (x.var) { + x.var->eval(undefined, log); + if (undefined) { return false; } + } + } + return true; +} + +CSPAddTerm::~CSPAddTerm() { } +std::ostream &operator<<(std::ostream &out, CSPAddTerm const &x) { + print_comma(out, x.terms, "$+"); + return out; +} +CSPAddTerm clone::operator()(CSPAddTerm const &x) const { + return CSPAddTerm(get_clone(x.terms)); +} + +// {{{1 definition of CSPMulTerm + +CSPMulTerm::CSPMulTerm(CSPMulTerm &&) = default; +CSPMulTerm &CSPMulTerm::operator=(CSPMulTerm &&) = default; + +CSPMulTerm::CSPMulTerm(UTerm &&var, UTerm &&coe) + : var(std::move(var)) + , coe(std::move(coe)) { } + +void CSPMulTerm::collect(VarTermBoundVec &vars) const { + if (var) { var->collect(vars, false); } + coe->collect(vars, false); +} +void CSPMulTerm::collect(VarTermSet &vars) const { + if (var) { var->collect(vars); } + coe->collect(vars); +} +void CSPMulTerm::replace(Defines &x) { + if (var) { Term::replace(var, var->replace(x, true)); } + Term::replace(coe, coe->replace(x, true)); +} +bool CSPMulTerm::operator==(CSPMulTerm const &x) const { + if (var && x.var) { return is_value_equal_to(var, x.var) && is_value_equal_to(coe, x.coe); } + else { return !var && !x.var && is_value_equal_to(coe, x.coe); } +} +bool CSPMulTerm::simplify(SimplifyState &state, Logger &log) { + if (var && var->simplify(state, false, false, log).update(var).undefined()) { return false;} + return !coe->simplify(state, false, false, log).update(coe).undefined(); +} +void CSPMulTerm::rewriteArithmetics(Term::ArithmeticsMap &arith, AuxGen &auxGen) { + if (var) { Term::replace(var, var->rewriteArithmetics(arith, auxGen)); } + Term::replace(coe, coe->rewriteArithmetics(arith, auxGen)); +} +size_t CSPMulTerm::hash() const { + if (var) { return get_value_hash(var, coe); } + else { return get_value_hash(coe); } +} +bool CSPMulTerm::hasPool() const { + return (var && var->hasPool()) || coe->hasPool(); +} +std::vector CSPMulTerm::unpool() const { + std::vector value; + if (var) { + auto f = [&](UTerm &&a, UTerm &&b) { value.emplace_back(std::move(a), std::move(b)); }; + Term::unpool(var, coe, Gringo::unpool, Gringo::unpool, f); + } + else { + for (auto &x : Gringo::unpool(coe)) { value.emplace_back(nullptr, std::move(x)); } + } + return value; +} +CSPMulTerm::~CSPMulTerm() { } +std::ostream &operator<<(std::ostream &out, CSPMulTerm const &x) { + out << *x.coe; + if (x.var) { out << "$*$" << *x.var; }; + return out; +} +CSPMulTerm clone::operator()(CSPMulTerm const &x) const { + return CSPMulTerm(x.var ? get_clone(x.var) : nullptr, get_clone(x.coe)); +} + +// }}}1 + +} // namspace Gringo + diff --git a/libgringo/tests/catch.hpp b/libgringo/tests/catch.hpp new file mode 100644 index 0000000..7df2fd0 --- /dev/null +++ b/libgringo/tests/catch.hpp @@ -0,0 +1,10485 @@ +/* + * Catch v1.5.4 + * Generated: 2016-05-12 19:16:01.957320 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#if defined(__cplusplus) && __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +#endif + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + namespace{ \ + struct TestName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ + namespace{ \ + struct TestCaseName : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return bool( opCast( lhs ) == opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) != opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) < opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) > opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) >= opCast( rhs ) ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool( opCast( lhs ) <= opCast( rhs ) ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( nullptr, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + std::auto_ptr m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.2.4 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include +#include +#include + +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CLARA_PLATFORM_WINDOWS +#endif + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + inline std::vector argsToVector( int argc, char const* const* const argv ) { + std::vector args( static_cast( argc ) ); + for( std::size_t i = 0; i < static_cast( argc ); ++i ) + args[i] = argv[i]; + + return args; + } + + class Parser { + enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; + Mode mode; + std::size_t from; + bool inQuotes; + public: + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + Parser() : mode( None ), from( 0 ), inQuotes( false ){} + + void parseIntoTokens( std::vector const& args, std::vector& tokens ) { + const std::string doubleDash = "--"; + for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) + parseIntoTokens( args[i], tokens); + } + + void parseIntoTokens( std::string const& arg, std::vector& tokens ) { + for( std::size_t i = 0; i <= arg.size(); ++i ) { + char c = arg[i]; + if( c == '"' ) + inQuotes = !inQuotes; + mode = handleMode( i, c, arg, tokens ); + } + } + Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + switch( mode ) { + case None: return handleNone( i, c ); + case MaybeShortOpt: return handleMaybeShortOpt( i, c ); + case ShortOpt: + case LongOpt: + case SlashOpt: return handleOpt( i, c, arg, tokens ); + case Positional: return handlePositional( i, c, arg, tokens ); + default: throw std::logic_error( "Unknown mode" ); + } + } + + Mode handleNone( std::size_t i, char c ) { + if( inQuotes ) { + from = i; + return Positional; + } + switch( c ) { + case '-': return MaybeShortOpt; +#ifdef CLARA_PLATFORM_WINDOWS + case '/': from = i+1; return SlashOpt; +#endif + default: from = i; return Positional; + } + } + Mode handleMaybeShortOpt( std::size_t i, char c ) { + switch( c ) { + case '-': from = i+1; return LongOpt; + default: from = i; return ShortOpt; + } + } + Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( std::string( ":=\0", 5 ).find( c ) == std::string::npos ) + return mode; + + std::string optName = arg.substr( from, i-from ); + if( mode == ShortOpt ) + for( std::size_t j = 0; j < optName.size(); ++j ) + tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); + else if( mode == SlashOpt && optName.size() == 1 ) + tokens.push_back( Token( Token::ShortOpt, optName ) ); + else + tokens.push_back( Token( Token::LongOpt, optName ) ); + return None; + } + Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( inQuotes || std::string( "\0", 3 ).find( c ) == std::string::npos ) + return mode; + + std::string data = arg.substr( from, i-from ); + tokens.push_back( Token( Token::Positional, data ) ); + return None; + } + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( std::vector const& args ) const { + ConfigT config; + parseInto( args, config ); + return config; + } + + std::vector parseInto( std::vector const& args, ConfigT& config ) const { + std::string processName = args[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( args, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.set( config, "true" ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes|no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + class MultipleReporters; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map > FactoryMap; + typedef std::vector > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = static_cast( childTracker ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = static_cast( childTracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* const* const argv ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace Catch { + + struct LexSort { + bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ) { + std::ostringstream ss; + + ss << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + + throw std::runtime_error(ss.str()); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector const& getAllTests() const { + return m_functions; + } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 5, 4, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } + + virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + return this; + } + +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = existingReporter->tryAsMulti(); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/libgringo/tests/graph.cc b/libgringo/tests/graph.cc new file mode 100644 index 0000000..e312b63 --- /dev/null +++ b/libgringo/tests/graph.cc @@ -0,0 +1,83 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/graph.hh" +#include "gringo/utility.hh" + +#include "tests/tests.hh" + +namespace Gringo { namespace Test { + +using namespace Gringo::IO; + +namespace { + +typedef Graph G; + +std::ostream &operator<<(std::ostream &out, G::SCCVec const &x) { + auto f = [](std::ostream &out, G::NodeVec const x) { + auto f = [](std::ostream &out, G::Node const *x) { out << x->data; }; + out << "["; + print_comma(out, x, ",", f); + out << "]"; + }; + out << "["; + print_comma(out, x, ",", f); + out << "]"; + return out; +} + +std::string to_string(G::SCCVec const &x) { + std::ostringstream out; + out << x; + return out.str(); +} + +G graph(std::initializer_list> edges) +{ + G g; + std::map map; + for (auto &x : edges) { + auto &a = map[x.first]; + if (a == nullptr) { a = &g.insertNode(x.first); } + auto &b = map[x.second]; + if (b == nullptr) { b = &g.insertNode(x.second); } + a->insertEdge(*b); + } + return g; +} + +} // namespace + +TEST_CASE("graph", "[base]") { + SECTION("test_tarjan") { + REQUIRE("[[b,c],[d],[a]]" == to_string(graph({{"a","b"},{"a","d"},{"b","c"},{"c","b"},{"d","b"}}).tarjan())); + REQUIRE("[[h,i],[f,g],[d,c,b,e],[a]]" == to_string(graph({{"a","b"},{"b","c"},{"c","h"},{"c","d"},{"d","e"},{"e","f"},{"e","b"},{"e","c"},{"f","g"},{"g","f"},{"h","i"},{"i","h"}}).tarjan())); + REQUIRE("[[c,d],[a,b]]" == to_string(graph({{"a","b"},{"a","c"},{"a","d"},{"b","a"},{"c","d"},{"d","c"}}).tarjan())); + REQUIRE("[[i],[n],[r3],[r4,e,r1,p,r2,s]]" == to_string(graph({{"r1","e"},{"r2","p"},{"r2","i"},{"r3","n"},{"r3","i"},{"r4","s"},{"p","r1"},{"s","r2"},{"s","r3"},{"e","r4"}}).tarjan())); + G g{graph({{"a","b"},{"a","d"},{"b","c"},{"c","b"},{"d","b"}})}; + REQUIRE("[[b,c],[d],[a]]" == to_string(g.tarjan())); + REQUIRE("[[b,c],[d],[a]]" == to_string(g.tarjan())); + REQUIRE("[[b,c],[d],[a]]" == to_string(g.tarjan())); + } +} + +} } // namespace Test Gringo + diff --git a/libgringo/tests/ground/dependency.cc b/libgringo/tests/ground/dependency.cc new file mode 100644 index 0000000..54db2d5 --- /dev/null +++ b/libgringo/tests/ground/dependency.cc @@ -0,0 +1,209 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/dependency.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +#include + +namespace Gringo { namespace Ground { namespace Test { + +namespace { + +using namespace Gringo::Test; +using namespace Gringo::IO; + +using StringSet = std::set; +using V = Symbol; +using S = std::string; + +struct TestLookup { + typedef Lookup L; + void add(UTerm const &x) { + auto occ = x->gterm(); + auto &term = *occ; + l.add(term, std::move(occ)); + } + void matchTerm(L::iterator begin, L::iterator end) { + for (auto it = begin; it != end; ++it){ str.insert(to_string(*it->first)); } + } + std::string match(Symbol const &x) { + str.clear(); + using namespace std::placeholders; + l.match(x, std::bind(&TestLookup::matchTerm, this, _1, _2)); + return to_string(str); + } + std::string unify(UTerm const &x) { + str.clear(); + auto term(x->gterm()); + using namespace std::placeholders; + l.unify(*term, std::bind(&TestLookup::matchTerm, this, _1, _2)); + return to_string(str); + } + StringSet str; + L l; +}; + +struct TestBodyOccurrence : BodyOccurrence { + TestBodyOccurrence(unsigned num, UTerm &&term, bool positive = true) : num(num), term(std::move(term)), positive(positive) { } + virtual UGTerm getRepr() const { return term->gterm(); } + virtual bool isPositive() const { return positive; } + virtual bool isNegative() const { return !positive; } + virtual void setType(OccurrenceType x) { type = x; } + virtual OccurrenceType getType() const { return type; } + void print(std::ostream &out) const { + out << *term << "@" << num << ":"; + switch (type) { + case OccurrenceType::POSITIVELY_STRATIFIED: { out << "!"; break; } + case OccurrenceType::STRATIFIED: { out << "."; break; } + case OccurrenceType::UNSTRATIFIED: { out << "?"; break; } + } + } + virtual DefinedBy &definedBy() { return defs; } + virtual void checkDefined(LocSet &, SigSet const &, UndefVec &) const { } + virtual ~TestBodyOccurrence() { } + unsigned num; + UTerm term; + OccurrenceType type = OccurrenceType::UNSTRATIFIED; + bool positive; + DefinedBy defs; +}; + +struct TestDep { + Dependency::Node &add(S const &name, bool normal) { return dep.add(S(name), normal); } + void provides(Dependency::Node &x, UTerm &&y) { + heads.emplace_front(to_string(*y)); + dep.provides(x, heads.front(), y->gterm()); + } + void depends(Dependency::Node &x, unsigned num, UTerm &&y, bool positive = true) { + occs.emplace_front(num, std::move(y), positive); + dep.depends(x, occs.front()); + } + S analyze() { + auto sccs(dep.analyze()); + for (auto &component : sccs) { std::sort(component.first.begin(), component.first.end()); } + std::ostringstream ss; + ss << "(" << sccs << ",["; + print_comma(ss, occs, ",", [](std::ostream &out, TestBodyOccurrence const &x) { x.print(out); }); + ss << "])"; + return ss.str(); + } + + std::forward_list heads; + std::forward_list occs; + Dependency dep; +}; + +} // namespace + +TEST_CASE("ground-dependency", "[ground]") { + SECTION("match") { + TestLookup l; + l.add(fun("f", val(NUM(2)))); + REQUIRE("{f(2)}" == l.match(V::createFun("f", { NUM(2) }))); + l.add(fun("f", var("X"))); + REQUIRE("{f(Y0)}" == l.match(V::createFun("f", { NUM(1) }))); + REQUIRE("{}" == l.match(V::createFun("g", { NUM(1) }))); + l.add(fun("f", var("X"), var("X"))); + l.add(fun("f", var("X"), var("Y"))); + REQUIRE("{f(Y0,Y0),f(Y0,Y1)}" == l.match(V::createFun("f", { NUM(1), NUM(1) }))); + REQUIRE("{f(Y0,Y1)}" == l.match(V::createFun("f", { NUM(1), NUM(2) }))); + l.add(fun("g", lin("X", 3, 7))); + REQUIRE("{}" == l.match(V::createFun("g", { NUM(2) }))); + REQUIRE("{g((3*Y0+7))}" == l.match(V::createFun("g", { NUM(10) }))); + } + + SECTION("unify") { + TestLookup l; + l.add(fun("f", var("X"))); + l.add(fun("f", fun("g", var("X")))); + REQUIRE("{f(Y0),f(g(Y0))}" == l.unify(fun("f", var("Y")))); + REQUIRE("{f(Y0),f(g(Y0))}" == l.unify(fun("f", fun("g", var("X"))))); + l.add(fun("f", var("X"), var("X"))); + REQUIRE("{}" == l.unify(fun("f", var("A"), fun("f", var("A"))))); + REQUIRE("{f(Y0,Y0)}" == l.unify(fun("f", var("A"), fun("f", var("B"))))); + l.add(fun("f", val(V::createFun("g", { NUM(1) })), var("X"))); + REQUIRE("{f(Y0,Y0),f(g(1),Y0)}" == l.unify(fun("f", var("A"), val(V::createFun("g", { NUM(2) }))))); + } + + SECTION("dep1") { + TestDep dep; + auto &x(dep.add("x.", true)); + dep.provides(x, val(ID("x"))); + auto &y(dep.add("a:-b@1,x@1,y@1.", true)); + dep.provides(y, val(ID("a"))); + dep.depends(y, 1, val(ID("b"))); + dep.depends(y, 1, val(ID("x"))); + dep.depends(y, 1, val(ID("y"))); + auto &z(dep.add("b:-a@1.", true)); + dep.provides(z, val(ID("b"))); + dep.depends(z, 1, val(ID("a"))); + auto &u(dep.add("c:-a@2,b@2.", true)); + dep.provides(u, val(ID("c"))); + dep.depends(u, 2, val(ID("a"))); + dep.depends(u, 2, val(ID("b"))); + REQUIRE("([([x.],1),([a:-b@1,x@1,y@1.,b:-a@1.],1),([c:-a@2,b@2.],1)],[b@2:!,a@2:!,a@1:?,y@1:!,x@1:!,b@1:?])" == dep.analyze()); + } + + SECTION("dep2") { + TestDep dep; + auto &x(dep.add("a:-~b@1.", true)); + dep.provides(x, val(ID("a"))); + dep.depends(x, 1, val(ID("b")), false); + auto &y(dep.add("b:-~a@1,a@2.", true)); + dep.provides(y, val(ID("b"))); + dep.depends(y, 1, val(ID("a")), false); + dep.depends(y, 2, val(ID("a"))); + REQUIRE("([([a:-~b@1.],0),([b:-~a@1,a@2.],0)],[a@2:.,a@1:.,b@1:?])" == dep.analyze()); + } + + SECTION("dep3") { + TestDep dep; + auto &x(dep.add("{a}.", false)); + dep.provides(x, val(ID("a"))); + auto &y(dep.add("b:-a@1.", true)); + dep.provides(y, val(ID("b"))); + dep.depends(y, 1, val(ID("a"))); + REQUIRE("([([{a}.],0),([b:-a@1.],0)],[a@1:.])" == dep.analyze()); + } + + SECTION("dep4") { + TestDep dep; + auto &x(dep.add("a:-~b@1.", true)); + dep.provides(x, val(ID("a"))); + dep.depends(x, 1, val(ID("b")), false); + auto &y(dep.add("a:-~c@1.", true)); + dep.provides(y, val(ID("a"))); + dep.depends(y, 1, val(ID("c")), false); + + auto &b(dep.add("b:-~a@1.", true)); + dep.provides(b, val(ID("b"))); + dep.depends(b, 1, val(ID("a"))); + auto &c(dep.add("c:-~a@2.", true)); + dep.provides(c, val(ID("c"))); + dep.depends(c, 2, val(ID("a"))); + REQUIRE("([([a:-~b@1.],0),([a:-~c@1.],0),([b:-~a@1.],0),([c:-~a@2.],0)],[a@2:.,a@1:.,c@1:?,b@1:?])" == dep.analyze()); + } +} + +} } } // namespace Test Ground Gringo + diff --git a/libgringo/tests/ground/grounder_helper.hh b/libgringo/tests/ground/grounder_helper.hh new file mode 100644 index 0000000..2c3467d --- /dev/null +++ b/libgringo/tests/ground/grounder_helper.hh @@ -0,0 +1,107 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_GROUND_TEST_GROUNDER_HELPER_HH +#define _GRINGO_GROUND_TEST_GROUNDER_HELPER_HH + +#include "gringo/logger.hh" +#include "gringo/ground/dependency.hh" +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/program.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" + +#include + +namespace Gringo { namespace Ground { namespace Test { + +inline void ground(std::string const &str, Output::OutputFormat fmt, std::ostream &ss) { + Gringo::Test::TestGringoModule module; + Potassco::TheoryData td; + Output::OutputBase out(td, {}, ss, fmt); + Input::Program prg; + Defines defs; + Scripts scripts(module); + Input::NongroundProgramBuilder pb{ scripts, prg, out, defs }; + Input::NonGroundParser ngp{ pb }; + ngp.pushStream("-", gringo_make_unique(str), module.logger); + ngp.parse(module.logger); + prg.rewrite(defs, module.logger); + Ground::Program gPrg(prg.toGround(out.data, module.logger)); + gPrg.ground(scripts, out, module.logger); +} + +inline std::string groundText(std::string const &str, std::initializer_list filter = {""}) { + std::regex delayedDef("^#delayed\\(([0-9]+)\\) <=> (.*)$"); + std::regex delayedOcc("#delayed\\(([0-9]+)\\)"); + std::map delayedMap; + std::stringstream ss; + + ground(str, Output::OutputFormat::TEXT, ss); + + std::string line; + std::vector res; + ss.seekg(0, std::ios::beg); + while (std::getline(ss, line)) { + std::smatch m; + if (std::regex_match(line, m, delayedDef)) { + delayedMap[m[1]] = m[2]; + } + else if (!line.compare(0, 9, "#delayed(")) { + res.emplace_back(std::move(line)); + } + else { + for (auto &x : filter) { + if (!line.compare(0, x.size(), x)) { + res.emplace_back(std::move(line)); + break; + } + } + } + } + for (auto &x : res) { + std::string r; + auto st = x.cbegin(); + for (auto it = std::sregex_iterator(x.begin(), x.end(), delayedOcc), ie = std::sregex_iterator(); it != ie; ++it) { + std::smatch match = *it; + r.append(st, match.prefix().second); + st = match.suffix().first; + r.append(delayedMap[match[1]]); + } + r.append(st, x.cend()); + x = r; + } + std::stringstream oss; + std::sort(res.begin(), res.end()); + for (auto &x : res) { oss << x << "\n"; } + return oss.str(); +} + +inline std::string groundAspif(std::string const &str) { + std::stringstream ss; + ground(str, Output::OutputFormat::INTERMEDIATE, ss); + return ss.str(); +} + +} } } // namespace Test Ground Gringo + +#endif // _GRINGO_GROUND_TEST_GROUNDER_HELPER_HH diff --git a/libgringo/tests/ground/instantiation.cc b/libgringo/tests/ground/instantiation.cc new file mode 100644 index 0000000..aa71c76 --- /dev/null +++ b/libgringo/tests/ground/instantiation.cc @@ -0,0 +1,1119 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/program.hh" +#include "gringo/ground/program.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" + +#include + +namespace Gringo { namespace Ground { namespace Test { + +using namespace Gringo::IO; + +namespace { + +std::string ground(std::string const &str, std::initializer_list filter = {""}) { + std::regex delayedDef("^#delayed\\(([0-9]+)\\) <=> (.*)$"); + std::regex delayedOcc("#delayed\\(([0-9]+)\\)"); + std::map delayedMap; + std::stringstream ss; + + Potassco::TheoryData td; + Output::OutputBase out(td, {}, ss, Output::OutputFormat::TEXT); + Input::Program prg; + Defines defs; + Gringo::Test::TestGringoModule module; + Scripts scripts(module); + Input::NongroundProgramBuilder pb{ scripts, prg, out, defs }; + Input::NonGroundParser ngp{ pb }; + ngp.pushStream("-", gringo_make_unique(str), module); + ngp.parse(module); + prg.rewrite(defs, module); + Program gPrg(prg.toGround(out.data, module)); + gPrg.ground(scripts, out, module); + + std::string line; + std::vector res; + ss.seekg(0, std::ios::beg); + while (std::getline(ss, line)) { + std::smatch m; + if (std::regex_match(line, m, delayedDef)) { + delayedMap[m[1]] = m[2]; + } + else if (!line.compare(0, 9, "#delayed(")) { + res.emplace_back(std::move(line)); + } + else { + for (auto &x : filter) { + if (!line.compare(0, x.size(), x)) { + res.emplace_back(std::move(line)); + break; + } + } + } + } + for (auto &x : res) { + std::string r; + auto st = x.cbegin(); + for (auto it = std::sregex_iterator(x.begin(), x.end(), delayedOcc), ie = std::sregex_iterator(); it != ie; ++it) { + std::smatch match = *it; + r.append(st, match.prefix().second); + st = match.suffix().first; + r.append(delayedMap[match[1]]); + } + r.append(st, x.cend()); + x = r; + } + std::stringstream oss; + std::sort(res.begin(), res.end()); + for (auto &x : res) { oss << x << "\n"; } + for (auto &x : module.messages()) { oss << x; } + return oss.str(); +} + +std::string gbie() { + return + "char_to_digit(X,X) :- X=0..9.\n" + "digit(Y-1,Y,D) :- char(C,Y), char_to_digit(C,D), Y > 0.\n" + "sign(X, 1) :- char(p,X).\n" + "sign(X,-1) :- char(m,X).\n" + "num_1(X,Y,A) :- digit(X,Y,A), not digit(_,X,_).\n" + "num_1(X,Z,10*A+B) :- num_1(X,Y,A), digit(Y,Z,B).\n" + "num(X,Y,A) :- num_1(X,Y,A), not digit(_,Y+1,_).\n" + "par_expr(Y-1,Z+1,A) :- char(o,Y), expr(Y,Z,A), char(c,Z+1), Y >= 0.\n" + "sign_expr(Y-1,Z,A*S) :- par_expr(Y,Z,A), sign(Y,S), Y > 0.\n" + "sign_expr(Y-1,Z,A*S) :- num(Y,Z,A), sign(Y,S), Y > 0.\n" + "expr(0,Y,A) :- num(0,Y,A).\n" + "expr(X,Y,A) :- char(o,X), num(X,Y,A).\n" + "expr(X,Y,A) :- par_expr(X,Y,A).\n" + "expr(X,Y,A) :- sign_expr(X,Y,A).\n" + "expr(X,Z,A+B) :- expr(X,Y,A), sign_expr(Y,Z,B).\n" + "cmp(Y-1,A) :- char(g,Y), num(Y,_,A), Y > 0.\n" + "cmp(Y-1,A*S) :- char(g,Y), sign(Y+1,S), num(Y+1,_,A), Y > 0.\n" + "le(A,B) :- expr(0,Y,A), cmp(Y,B), A <= B.\n" + "gt(A,B) :- expr(0,Y,A), cmp(Y,B), A > B.\n"; +} + +std::string gbie1() { + return + "char(p,1).\n" "char(0,2).\n" "char(m,3).\n" "char(o,4).\n" + "char(o,5).\n" "char(6,6).\n" "char(m,7).\n" "char(7,8).\n" + "char(p,9).\n" "char(3,10).\n" "char(p,11).\n" "char(o,12).\n" + "char(4,13).\n" "char(c,14).\n" "char(c,15).\n" "char(m,16).\n" + "char(2,17).\n" "char(p,18).\n" "char(o,19).\n" "char(p,20).\n" + "char(0,21).\n" "char(c,22).\n" "char(c,23).\n" "char(p,24).\n" + "char(2,25).\n" "char(m,26).\n" "char(o,27).\n" "char(p,28).\n" + "char(1,29).\n" "char(c,30).\n" "char(g,31).\n" "char(m,32).\n" + "char(4,33).\n"; +} + +std::string gbie2() { + return + "char(o,1).\n" "char(m,2).\n" "char(o,3).\n" "char(p,4).\n" + "char(1,5).\n" "char(m,6).\n" "char(o,7).\n" "char(m,8).\n" + "char(2,9).\n" "char(c,10).\n" "char(p,11).\n" "char(7,12).\n" + "char(c,13).\n" "char(m,14).\n" "char(5,15).\n" "char(m,16).\n" + "char(o,17).\n" "char(m,18).\n" "char(4,19).\n" "char(p,20).\n" + "char(o,21).\n" "char(p,22).\n" "char(o,23).\n" "char(p,24).\n" + "char(2,25).\n" "char(c,26).\n" "char(c,27).\n" "char(c,28).\n" + "char(c,29).\n" "char(p,30).\n" "char(o,31).\n" "char(o,32).\n" + "char(m,33).\n" "char(6,34).\n" "char(p,35).\n" "char(1,36).\n" + "char(c,37).\n" "char(c,38).\n" "char(g,39).\n" "char(m,40).\n" + "char(1,41).\n" "char(6,42).\n"; +} + +std::string strategicA1() { + return + "controlled_by(1,5,2,2).\n" + "controlled_by(1,5,3,3).\n" + "controlled_by(2,6,3,5).\n" + "controlled_by(2,6,3,1).\n" + "controlled_by(3,4,1,5).\n" + "controlled_by(3,4,1,6).\n" + "controlled_by(4,2,6,6).\n" + "controlled_by(4,2,5,5).\n" + "controlled_by(5,1,1,1).\n" + "controlled_by(6,4,4,4).\n" + "produced_by(p1, 4,2).\n" + "produced_by(p2, 5,1).\n" + "produced_by(p3, 2,6).\n" + "produced_by(p4, 4,2).\n" + "produced_by(p5, 5,6).\n" + "produced_by(p6, 2,4).\n" + "produced_by(p7, 4,3).\n" + "produced_by(p8, 5,2).\n" + "produced_by(p9, 5,5).\n" + "produced_by(p10, 6,2).\n" + "produced_by(p11, 4,4).\n" + "produced_by(p12, 4,3).\n" + "produced_by(p13, 4,6).\n" + "produced_by(p14, 4,4).\n" + "produced_by(p15, 6,4).\n" + "produced_by(p16, 1,1).\n" + "produced_by(p17, 5,5).\n" + "produced_by(p18, 1,6).\n" + "produced_by(p19, 2,5).\n" + "produced_by(p20, 1,6).\n" + "produced_by(p21, 4,6).\n" + "produced_by(p22, 2,5).\n" + "produced_by(p23, 2,6).\n" + "produced_by(p24, 6,6).\n"; +} + +std::string strategicB1() { + return + "controlled_by(c1,1,(5;2;2)).\n" + "controlled_by(c2,1,(5;3;3)).\n" + "controlled_by(c3,2,(6;3;5)).\n" + "controlled_by(c4,2,(6;3;1)).\n" + "controlled_by(c5,3,(4;1;5)).\n" + "controlled_by(c6,3,(4;1;6)).\n" + "controlled_by(c7,4,(2;6;6)).\n" + "controlled_by(c8,4,(2;5;5)).\n" + "controlled_by(c9,5,(1;1;1)).\n" + "controlled_by(c10,6,(4;4;4)).\n" + "produced_by(p1, (4;2)).\n" + "produced_by(p2, (5;1)).\n" + "produced_by(p3, (2;6)).\n" + "produced_by(p4, (4;2)).\n" + "produced_by(p5, (5;6)).\n" + "produced_by(p6, (2;4)).\n" + "produced_by(p7, (4;3)).\n" + "produced_by(p8, (5;2)).\n" + "produced_by(p9, (5;5)).\n" + "produced_by(p10,(6;2)).\n" + "produced_by(p11,(4;4)).\n" + "produced_by(p12,(4;3)).\n" + "produced_by(p13,(4;6)).\n" + "produced_by(p14,(4;4)).\n" + "produced_by(p15,(6;4)).\n" + "produced_by(p16,(1;1)).\n" + "produced_by(p17,(5;5)).\n" + "produced_by(p18,(1;6)).\n" + "produced_by(p19,(2;5)).\n" + "produced_by(p20,(1;6)).\n" + "produced_by(p21,(4;6)).\n" + "produced_by(p22,(2;5)).\n" + "produced_by(p23,(2;6)).\n" + "produced_by(p24,(6;6)).\n"; +} + +} + +TEST_CASE("ground-instantiation", "[ground]") { + SECTION("instantiateRec") { + REQUIRE( + "a(0).\n" + "a(1).\n" + "a(2).\n" + "a(3).\n" + "a(4).\n" + "b(0).\n" + "b(1).\n" + "b(2).\n" + "b(3).\n" + "b(4).\n" + "c(0).\n" + "c(1).\n" + "c(2).\n" + "c(3).\n" + "c(4).\n" + "d(0).\n" + "d(1).\n" + "d(2).\n" + "d(3).\n" + "d(4).\n" + "p(0).\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "p(5).\n" == ground( + "p(0).\n" + "a(X) :- p(X), X < 5.\n" + "b(X) :- a(X).\n" + "c(X) :- b(X), a(X).\n" + "d(X) :- c(X), b(X), a(X).\n" + "p(X+1) :- a(X), b(X), c(X), d(X).\n")); + } + + SECTION("instantiate") { + REQUIRE( + "e(1,2).\n" + "e(2,1).\n" + "r(1).\n" + "r(2).\n" + "v(1).\n" == ground("v(1).e(1,2).e(2,1).r(X):-v(X).r(Y):-r(X),e(X,Y).")); + REQUIRE( + "p(1,2).\n" "p(1,3).\n" "p(1,4).\n" "p(1,5).\n" "p(1,6).\n" "p(1,7).\n" + "p(2,3).\n" "p(2,4).\n" "p(2,5).\n" "p(2,6).\n" "p(2,7).\n" + "p(3,4).\n" "p(3,5).\n" "p(3,6).\n" "p(3,7).\n" + "p(4,5).\n" "p(4,6).\n" "p(4,7).\n" + "p(5,6).\n" "p(5,7).\n" + "p(6,7).\n" == ground( + "p(1,2)." + "p(2,3)." + "p(3,4)." + "p(4,5)." + "p(5,6)." + "p(6,7)." + "p(X,Z) :- p(X,Y), p(Y,Z).")); + REQUIRE( + "x.\n" + "y.\n" + "z.\n" == ground( + "x :- y, z." + "x :- not v." + "y." + "z." + "v :- not x.")); + REQUIRE( + "p(f(1)).\n" + "p(f(2)).\n" + "p(g(1)):-not p(f(3)).\n" + "p(g(2)):-not p(f(3)).\n" == ground( + "p(f(1)).\n" + "p(f(2)).\n" + "p(Y):-p(f(X)),Y=g(X),not p(f(3)).\n")); + REQUIRE( + "p(f(1)).\n" + "p(f(2)).\n" + "p(g(1)).\n" + "p(g(2)).\n" == ground( + "p(f(1)).\n" + "p(f(2)).\n" + "p(g(X)):-p(f(X)),not p(f(3)).\n")); + REQUIRE( + "0>=#count{0,a:#true}.\n" + "a.\n" == ground( + "a.\n" + "0 { a } 0 :- a, #false : #false.\n")); + } + + SECTION("bodyaggregate") { + REQUIRE( + "company(c1).\n" "company(c2).\n" "company(c3).\n" "company(c4).\n" + "controls(c1,c2).\n" "controls(c1,c3).\n" "controls(c1,c4).\n" "controls(c3,c4).\n" + "owns(c1,c2,60).\n" "owns(c1,c3,20).\n" "owns(c2,c3,35).\n" "owns(c3,c4,51).\n" == ground( + "controls(X,Y) :- 51 #sum+ { S: owns(X,Y,S); S: owns(Z,Y,S), controls(X,Z), X != Y }, company(X), company(Y), X != Y." + "company(c1)." + "company(c2)." + "company(c3)." + "company(c4)." + "owns(c1,c2,60)." + "owns(c1,c3,20)." + "owns(c2,c3,35)." + "owns(c3,c4,51).")); + } + + SECTION("bodyaggregate2") { + REQUIRE( + "company(c1).\n" "company(c2).\n" "company(c3).\n" "company(c4).\n" + "controls(c1,c2):-#sum{60:}.\n" + "controls(c1,c3):-51<=#sum{20:;35:controls(c1,c2)}.\n" + "controls(c1,c4):-51<=#sum{51:controls(c1,c3)}.\n" + "controls(c3,c4):-#sum{51:}.\n" + "owns(c1,c2,60).\n" "owns(c1,c3,20).\n" "owns(c2,c3,35).\n" "owns(c3,c4,51).\n" == ground( + "controls(X,Y) :- 51 #sum { S: owns(X,Y,S); S: owns(Z,Y,S), controls(X,Z), X != Y }, company(X), company(Y), X != Y." + "company(c1)." + "company(c2)." + "company(c3)." + "company(c4)." + "owns(c1,c2,60)." + "owns(c1,c3,20)." + "owns(c2,c3,35)." + "owns(c3,c4,51).")); + } + + SECTION("bodyaggregate3") { + REQUIRE( + "a:-#true,not c.\n" + "c.\n" == ground( + "a :- not { c } >= 1, not c." + "b :- a, #false." + "c :- not b, {b; not b} >= 1." + )); + REQUIRE( + "a:-#false,not c.\n" + "c.\n" == ground( + "a :- not not { c } >= 1, not c." + "b :- a, #false." + "c :- not b, {b; not b} >= 1." + )); + } + + SECTION("min_fail") { + REQUIRE( + "c.\n" + "p(1):-not r(1).\n" + "p(2):-not r(2).\n" + "r(1):-not p(1).\n" + "r(2):-not p(2).\n" + "-:27:42-43: info: atom does not occur in any rule head:\n b\n" + == ground( + "p(X) :- not r(X), X=1..2.\n" + "r(X) :- not p(X), X=1..2.\n" + "c.\n" + "fmin(1) :- 1 #max {}.\n" + "fmin(1) :- not not 1 #max {}.\n" + "fmin(2) :- not #max {} 1.\n" + "fmin(3) :- #min {} 1.\n" + "fmin(3) :- not not #min {} 1.\n" + "fmin(4) :- not 1 #min {}.\n" + "fmin(5) :- not 1 #max {1:c} 2.\n" + "fmin(5) :- 1 #max {c:c} 2.\n" + "fmin(5) :- not not 1 #max {c:c} 2.\n" + "fmin(6) :- not 1 #min {1:c} 2.\n" + "fmin(6) :- 1 #min {c:c} 2.\n" + "fmin(6) :- not not 1 #min {c:c} 2.\n" + "fmin(7) :- 3 #max {2:p(1); 1:r(1)}.\n" + "fmin(7) :- not not 3 #max {2:p(1); 1:r(1)}.\n" + "fmin(8) :- #min {2:p(1); 1:r(1)} 0.\n" + "fmin(8) :- not not #min {2:p(1); 1:r(1)} 0.\n" + "fmin(9) :- not #max {2:p(1); 1:r(1)} 2.\n" + "fmin(10) :- not 0 #min {2:p(1); 1:r(1)}.\n" + "fmin(11) :- 1 #max {2:p(1); 1:r(1); 3:c} 1.\n" + "fmin(11) :- not not 1 #max {2:p(1); 1:r(1); 3:c} 1.\n" + "fmin(12) :- not 1 #max {2:p(1); 1:r(1); 3:c}.\n" + "fmin(13) :- 3 #min {2:p(1); 1:r(1); 1,c:c} 3.\n" + "fmin(13) :- not not 3 #min {2:p(1); 1:r(1); 1,c:c} 3.\n" + "fmin(14) :- not #min {2:p(1); 3:b; 1:c} 1.\n" + )); + } + + SECTION("min_true") { + REQUIRE( + "c.\n" + "p(1):-not r(1).\n" + "p(2):-not r(2).\n" + "r(1):-not p(1).\n" + "r(2):-not p(2).\n" + "tmin(1).\n" "tmin(10).\n" "tmin(11).\n" "tmin(12).\n" + "tmin(13).\n" "tmin(14).\n" "tmin(15).\n" "tmin(16).\n" + "tmin(17).\n" "tmin(18).\n" "tmin(19).\n" "tmin(2).\n" + "tmin(20).\n" "tmin(21).\n" "tmin(22).\n" "tmin(23).\n" + "tmin(24).\n" "tmin(3).\n" "tmin(4).\n" "tmin(5).\n" + "tmin(6).\n" "tmin(7).\n" "tmin(8).\n" "tmin(9).\n" + "-:26:39-40: info: atom does not occur in any rule head:\n b\n" + "-:27:39-40: info: atom does not occur in any rule head:\n b\n" + == ground( + "p(X) :- not r(X), X=1..2.\n" + "r(X) :- not p(X), X=1..2.\n" + "c.\n" + "tmin(1) :- not 1 #max {}.\n" + "tmin(2) :- #max {} 1.\n" + "tmin(3) :- not not #max {} 1.\n" + "tmin(4) :- not #min {} 1.\n" + "tmin(5) :- 1 #min {}.\n" + "tmin(6) :- not not 1 #min {}.\n" + "tmin(7) :- 1 #max {1:c} 2.\n" + "tmin(8) :- not not 1 #max {1:c} 2.\n" + "tmin(9) :- not 1 #max {c:c} 2.\n" + "tmin(10) :- 1 #min {1:c} 2.\n" + "tmin(11) :- not not 1 #min {1:c} 2.\n" + "tmin(12) :- not 1 #min {c:c} 2.\n" + "tmin(13) :- not 3 #max {2:p(1); 1:r(1)}.\n" + "tmin(14) :- not #min {2:p(1); 1:r(1)} 0.\n" + "tmin(15) :- #max {2:p(1); 1:r(1)} 2.\n" + "tmin(16) :- not not #max {2:p(1); 1:r(1)} 2.\n" + "tmin(17) :- 0 #min {2:p(1); 1:r(1)}.\n" + "tmin(18) :- not not 0 #min {2:p(1); 1:r(1)}.\n" + "tmin(19) :- not 1 #max {2:p(1); 1:r(1); 3:c} 1.\n" + "tmin(20) :- 1 #max {2:p(1); 1:r(1); 3:c}.\n" + "tmin(21) :- not not 1 #max {2:p(1); 1:r(1); 3:c}.\n" + "tmin(22) :- not 3 #min {2:p(1); 1:r(1); 1,c:c} 3.\n" + "tmin(23) :- #min {2:p(1); 3:b; 1:c} 1.\n" + "tmin(24) :- not not #min {2:p(1); 3:b; 1:c} 1.\n" + )); + } + + SECTION("min_open") { + REQUIRE( + "c.\n" + "mfmin(10):-3<=#min{2:p(1);1:r(1)}<=3.\n" + "mfmin(5):-0<=#max{2:p(1);1:r(1)}<=0.\n" + "mmin(1):-2<=#max{2:p(1);1:r(1)}.\n" + "mmin(11):-1>=#min{1:p(1);2:p(2)}.\n" + "mmin(12,1):-0>=#min{0:r(1)}.\n" + "mmin(12,2):-1>=#min{1:r(2)}.\n" + "mmin(2):-1>=#max{2:p(1);1:r(1)}.\n" + "mmin(3):-1<=#max{2:p(1);1:r(1)}<=1.\n" + "mmin(4):-1<=#max{2:p(1);1:r(1)}.\n" + "mmin(6):-2<=#min{2:p(1);1:r(1)}.\n" + "mmin(7):-1>=#min{2:p(1);1:r(1)}.\n" + "mmin(8):-1>=#min{2:p(1);1:r(1)}.\n" + "mmin(9):-2>=#min{2:p(1);1:r(1)}.\n" + "p(1):-not r(1).\n" + "p(2):-not r(2).\n" + "r(1):-not p(1).\n" + "r(2):-not p(2).\n" == + ground( + "p(X) :- not r(X), X=1..2.\n" + "r(X) :- not p(X), X=1..2.\n" + "c.\n" + "mmin(1) :- 2 #max {2:p(1); 1:r(1)}.\n" + "mmin(2) :- #max {2:p(1); 1:r(1)} 1.\n" + "mmin(3) :- 1 #max {2:p(1); 1:r(1), c} 1.\n" + "mmin(4) :- 1 #max {2:p(1); 1:r(1)} 2.\n" + "mfmin(5) :- 0 #max {2:p(1); 1:r(1)} 0.\n" + "mmin(6) :- 2 #min {2:p(1); 1:r(1)}.\n" + "mmin(7) :- #min {2:p(1); 1:r(1)} 1.\n" + "mmin(8) :- 1 #min {2:p(1); 1:r(1), c} 1.\n" + "mmin(9) :- 1 #min {2:p(1); 1:r(1)} 2.\n" + "mfmin(10) :- 3 #min {2:p(1); 1:r(1)} 3.\n" + "mmin(11) :- 1 #min {X:p(X),X=1..2} 1.\n" + "mmin(12,X) :- X-1 #min {X-1:r(X)} X-1, X=1..2.\n" + )); + } + + SECTION("assign_min") { + REQUIRE( + "p(-1).\n" + "p(-2).\n" + "p(-3).\n" + "p(0).\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "s(-3).\n" == ground( + "p(X) :- X=-3..4.\n" + "s(S) :- S=#min { X:p(X) }.\n" + )); + } + + SECTION("assign_max") { + REQUIRE( + "p(-1).\n" + "p(-2).\n" + "p(-3).\n" + "p(0).\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "s(4).\n" == ground( + "p(X) :- X=-3..4.\n" + "s(S) :- S=#max { X:p(X) }.\n" + )); + } + + SECTION("assign_sump") { + REQUIRE( + "p(-1).\n" + "p(-2).\n" + "p(-3).\n" + "p(0).\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "s(10).\n" + "-:2:19-20: info: tuple ignored:\n -3\n" + "-:2:19-20: info: tuple ignored:\n -2\n" + "-:2:19-20: info: tuple ignored:\n -1\n" + == ground( + "p(X) :- X=-3..4.\n" + "s(S) :- S=#sum+ { X:p(X) }.\n" + )); + } + + SECTION("assign_count") { + REQUIRE( + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "p(5).\n" + "p(6).\n" + "p(7).\n" + "s(1,8).\n" + "s(2,8).\n" + "s(3,8).\n" == ground( + "p(X) :- X=1..7.\n" + "s(Y,S) :- S=#count { X,a:p(X); Y,b }, Y=1..3.\n" + )); + } + + SECTION("assign_sum") { + REQUIRE( + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "p(5).\n" + "p(6).\n" + "p(7).\n" + "s(1,29).\n" + "s(2,30).\n" + "s(3,31).\n" == ground( + "p(X) :- X=1..7.\n" + "s(Y,S) :- S=#sum { X,a:p(X); Y,b }, Y=1..3.\n" + )); + REQUIRE( + "p(-1).\n" + "p(-2).\n" + "p(-3).\n" + "p(0).\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "s(4).\n" == ground( + "p(X) :- X=-3..4.\n" + "s(S) :- S=#sum { X:p(X) }.\n" + )); + } + + SECTION("rec_count") { + REQUIRE( + "edge(1,3).\n" "edge(2,3).\n" "edge(3,4).\n" "edge(3,6).\n" "edge(4,5).\n" "edge(4,6).\n" "edge(6,7).\n" "edge(6,8).\n" + "inlink(3,2).\n" "inlink(4,3).\n" "inlink(6,4).\n" + "inner(3).\n" "inner(4).\n" "inner(6).\n" + "irreducible(3,s(s(s(z)))).\n" "irreducible(3,s(s(z))).\n" "irreducible(3,s(z)).\n" "irreducible(6,s(z)).\n" + "link(1,3).\n" "link(2,3).\n" "link(3,4).\n" "link(3,6).\n" "link(4,5).\n" "link(4,6).\n" "link(6,7).\n" "link(6,8).\n" + "linked(1,3).\n" "linked(1,3,s(s(s(z)))).\n" "linked(1,3,s(s(z))).\n" "linked(1,3,s(z)).\n" "linked(1,4).\n" "linked(1,6).\n" + "linked(2,3).\n" "linked(2,3,s(s(s(z)))).\n" "linked(2,3,s(s(z))).\n" "linked(2,3,s(z)).\n" "linked(2,4).\n" "linked(2,6).\n" + "linked(3,4).\n" "linked(3,4,s(z)).\n" "linked(3,5).\n" "linked(3,5,s(s(s(z)))).\n" "linked(3,5,s(s(z))).\n" "linked(3,6).\n" + "linked(3,6,s(s(z))).\n" "linked(3,6,s(z)).\n" "linked(3,7).\n" "linked(3,7,s(s(s(z)))).\n" "linked(3,8).\n" "linked(3,8,s(s(s(z)))).\n" + "linked(4,5).\n" "linked(4,5,s(z)).\n" "linked(4,6).\n" "linked(4,6,s(z)).\n" "linked(4,7).\n" "linked(4,8).\n" "linked(6,7).\n" + "linked(6,7,s(s(z))).\n" "linked(6,7,s(z)).\n" "linked(6,8).\n" "linked(6,8,s(s(z))).\n" "linked(6,8,s(z)).\n" + "oulink(3,5).\n" "oulink(4,4).\n" "oulink(6,2).\n" + "outedge(1,3).\n" "outedge(2,3).\n" "outedge(3,5).\n" "outedge(3,7).\n" "outedge(3,8).\n" + "outvertex(1).\n" "outvertex(2).\n" "outvertex(3).\n" "outvertex(5).\n" "outvertex(7).\n" "outvertex(8).\n" + "prefer(3,0).\n" "prefer(4,1).\n" "prefer(6,2).\n" + "reduced(4,s(z)).\n" "reduced(6,s(s(z))).\n" "reduced(s(s(z))).\n" "reduced(s(z)).\n" + "reducible(4,s(z)).\n" "reducible(6,s(s(z))).\n" "unlinked(1,4,s(z)).\n" + "unlinked(1,6,s(s(z))).\n" "unlinked(1,6,s(z)).\n" "unlinked(2,4,s(z)).\n" "unlinked(2,6,s(s(z))).\n" "unlinked(2,6,s(z)).\n" + "unlinked(3,4,s(s(s(z)))).\n" "unlinked(3,4,s(s(z))).\n" "unlinked(3,5,s(z)).\n" "unlinked(3,6,s(s(s(z)))).\n" "unlinked(3,7,s(s(z))).\n" + "unlinked(3,7,s(z)).\n" "unlinked(3,8,s(s(z))).\n" "unlinked(3,8,s(z)).\n" "unlinked(4,6,s(s(z))).\n" "unlinked(4,7,s(z)).\n" "unlinked(4,8,s(z)).\n" + "unreduced(3,s(s(s(z)))).\n" "unreduced(3,s(s(z))).\n" "unreduced(3,s(z)).\n" "unreduced(4,s(z)).\n" "unreduced(6,s(s(z))).\n" "unreduced(6,s(z)).\n" + "vertex(1).\n" "vertex(2).\n" "vertex(3).\n" "vertex(4).\n" "vertex(5).\n" "vertex(6).\n" "vertex(7).\n" "vertex(8).\n" == ground( + "%%%%%%%%%%%%%%%%%%%%\n" + "% INPUT PREDICATES %\n" + "%%%%%%%%%%%%%%%%%%%%\n" + "\n" + "vertex(1). vertex(2). vertex(3). vertex(4). vertex(5). vertex(6). vertex(7). vertex(8).\n" + "edge(1,3). edge(2,3). edge(3,4). edge(3,6). edge(4,5). edge(4,6). edge(6,7). edge(6,8).\n" + "\n" + "% 1-+ 4-+-5\n" + "% | | |\n" + "% 3-+-6-+-7\n" + "% | |\n" + "% 2-+ 8\n" + "\n" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" + "% INNER VERTICES WITHOUT SELF-LOOP ARE REDUCIBLE %\n" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" + "\n" + "inner(V) :- edge(U,V), edge(V,W), not edge(V,V).\n" + "\n" + "link(U,V) :- edge(U,V), 1 #sum+{ 1 : inner(U); 1 : inner(V) }.\n" + "\n" + "linked(U,V) :- link(U,V).\n" + "linked(U,V) :- link(U,W), linked(W,V), inner(W), 1 #sum+ { 1 : inner(U); 1 : inner(V) }.\n" + "\n" + "inlink(V,N) :- inner(V), N = #sum+{ 1,U : linked(U,V), U != V }.\n" + "oulink(V,N) :- inner(V), N = #sum+{ 1,W : linked(V,W), V != W }.\n" + "\n" + "prefer(V,N) :- inner(V), N = #sum+{ 1,U : inner(U), U < V }.\n" + "\n" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" + "% ITERATIVELY REDUCE INNER VERTICES AS LONG AS SOME HAS ONE PREDECESSOR/SUCCESSOR %\n" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" + "\n" + "unreduced(V,s(z)) :- inner(V).\n" + "unreduced(V,s(I)) :- unreduced(V,I), reduced(W,I), V != W.\n" + "\n" + "linked(U,V,s(z)) :- link(U,V).\n" + "linked(U,V,s(I)) :- linked(U,W,I), linked(W,V,I), reduced(W,I).\n" + "linked(U,V,s(I)) :- linked(U,V,I), reduced(I),\n" + " 2 #sum+{ 1,a : unreduced(U,s(I)); 1,b : unreduced(V,s(I)); 1,a : not inner(U); 1,b : not inner(V) }.\n" + "\n" + "irreducible(V,I) :- unreduced(V,I), linked(V,V,I).\n" + "irreducible(V,I) :- unreduced(V,I),\n" + " 2 #sum+{ 1,U : linked(U,V,I), U != V }, 2 #sum+{ 1,W : linked(V,W,I), V != W }.\n" + "\n" + "unlinked(U,V,s(z)) :- linked(U,V), not link(U,V).\n" + "unlinked(U,V,s(I)) :- linked(U,V,I), reduced(U,I), inner(V).\n" + "unlinked(U,V,s(I)) :- linked(U,V,I), reduced(V,I), inner(U).\n" + "unlinked(U,V,s(I)) :- unlinked(U,V,I), reduced(U,J), J <= I, unreduced(V,s(I)).\n" + "unlinked(U,V,s(I)) :- unlinked(U,V,I), reduced(V,J), J <= I, unreduced(U,s(I)).\n" + "unlinked(U,V,s(I)) :- unlinked(U,V,I), reduced(W,I), U != W, V != W,\n" + " 1 #sum+{ 1 : unlinked(U,W,I); 1 : unlinked(W,V,I); 1 : not linked(U,W); 1 : not linked(W,V) }.\n" + "\n" + "reducible(V,I) :- unreduced(V,I), inlink(V,N),\n" + " N #sum+{ 1; 1,U : unlinked(U,V,I), U != V }, 1 #sum+{ 1 : unlinked(V,V,I); 1 : not linked(V,V) }.\n" + "reducible(V,I) :- unreduced(V,I), oulink(V,N),\n" + " N #sum+{ 1; 1,W : unlinked(V,W,I), V != W }, 1 #sum+{ 1 : unlinked(V,V,I); 1 : not linked(V,V) }.\n" + "\n" + "reduced(V,I) :- reducible(V,I), prefer(V,N),\n" + " N #sum+{ 1,U : irreducible(U,I), U < V; 1,W,J : reduced(W,J), W < V, J < I }.\n" + "reduced(I) :- reduced(V,I).\n" + "\n" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" + "% FINAL RESULT OF ITERATIVE REDUCTION %\n" + "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n" + "\n" + "outvertex(V) :- vertex(V), not inner(V).\n" + "outvertex(V) :- unreduced(V,I), not reduced(I).\n" + "\n" + "outedge(U,V) :- edge(U,V), not link(U,V).\n" + "outedge(U,V) :- linked(U,V,I), not reduced(I).\n")); + } + + SECTION("rec_count2") { + REQUIRE("a:-1!=#count{0,a:a}.\n" == ground("a:-{a}!=1.\n")); + } + + SECTION("rec_conj") { + REQUIRE( + "edge(2,3).\n" "edge(2,5).\n" "edge(3,1).\n" "edge(3,4).\n" + "edge(3,6).\n" "edge(7,8).\n" "edge(8,9).\n" + "input(1).\n" "input(3).\n" "input(4).\n" "input(6).\n" "input(7).\n" "input(8).\n" + "observed(5).\n" "observed(9).\n" == ground( + "% example instance\n" + "\n" + "edge(2,3).\n" + "edge(3,1). edge(3,4). edge(3,6).\n" + "edge(2,5).\n" + "edge(7,8).\n" + "edge(8,9).\n" + "\n" + "input(7).\n" + "observed(5). observed(9).\n" + "\n" + "% a vertex is an input vertex if all its outgoing edges\n" + "% lead to input vertices and the vertex itself is no observation\n" + "% example:\n" + "% edges - from left to right\n" + "% x - some vertex\n" + "% i - input vertex\n" + "% o - observation vertex\n" + "%\n" + "% i\n" + "% /\n" + "% x---i---i\n" + "% \\ \\\n" + "% o i\n" + "input(V) :- edge(U,V), input(W) : edge(V,W); not observed(V).\n" + "\n" + "% An unobserved input vertex can explain any single non-input target.\n" + "% example:\n" + "% edges - from left to right\n" + "% (i) - explicitly marked input vertex\n" + "% i - input vertex\n" + "% o - observation vertex\n" + "%\n" + "% (i)---i---o\n" + "input(V) :- input(U); edge(U,V); input(W) : edge(U,W), V != W; not observed(U), not observed(V).\n")); + } + + SECTION("conj") { + REQUIRE( + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "p(5).\n" + "p(6).\n" + "p(7).\n" + "s(1,2).\n" + "s(2,3).\n" + "s(3,4).\n" + "s(4,5).\n" + "s(5,6).\n" + "s(6,7).\n" == ground( + "p(1..7).\n" + "s(X,Z) :- p(X), #false : p(Y), X < Y, Y < Z; p(Z), X < Z.\n")); + REQUIRE( + "p(1):-not not p(1).\n" + "p(2):-not not p(2).\n" + "p(3):-not not p(3).\n" + "p(4):-not not p(4).\n" + "s(1,2):-p(2),p(1).\n" + "s(1,3):-p(3),p(1),#false:p(2).\n" + "s(1,4):-p(4),p(1),#false:p(2)|p(3).\n" + "s(2,3):-p(3),p(2).\n" + "s(2,4):-p(4),p(2),#false:p(3).\n" + "s(3,4):-p(4),p(3).\n" == ground( + "p(X) :- not not p(X), X=1..4.\n" + "s(X,Z) :- p(X), #false : p(Y), X < Y, Y < Z; p(Z), X < Z.\n")); + REQUIRE( + "p(1):-not not p(1).\n" + "p(2):-not not p(2).\n" + "p(3):-not not p(3).\n" + "p(4):-not not p(4).\n" + "s(1,2):-p(2),p(1).\n" + "s(1,3):-p(3),p(1),not p(2):p(2).\n" + "s(1,4):-p(4),p(1),not p(2):p(2);not p(3):p(3).\n" + "s(2,3):-p(3),p(2).\n" + "s(2,4):-p(4),p(2),not p(3):p(3).\n" + "s(3,4):-p(4),p(3).\n" == ground( + "p(X) :- not not p(X), X=1..4.\n" + "s(X,Z) :- p(X), not p(Y) : p(Y), X < Y, Y < Z; p(Z), X < Z.\n" + )); + } + + SECTION("meta") { + REQUIRE( + "hold(atom(p)):-hold(conjunction(0)).\n" + "hold(atom(q)):-hold(conjunction(2)).\n" + "hold(atom(r)):-hold(conjunction(2)).\n" + "hold(atom(s)):-hold(conjunction(1)).\n" + "hold(atom(t)):-hold(conjunction(0)).\n" + "hold(conjunction(0)):-hold(sum(1,0,2)).\n" + "hold(conjunction(1)):-not hold(atom(q)),not hold(atom(r)).\n" + "hold(conjunction(2)):-hold(sum(1,1,2)).\n" + "hold(conjunction(3)):-hold(atom(r)),hold(atom(q)).\n" + "hold(sum(1,0,2)):-1<=#sum{1,2:not hold(atom(t));1,1:hold(atom(s));1,0:hold(atom(r))}<=2.\n" + "hold(sum(1,1,2)):-1<=#sum{1,1:hold(atom(t));1,0:hold(atom(p))}.\n" == ground( + "wlist(0,0,pos(atom(r)),1).\n" + "wlist(0,1,pos(atom(s)),1).\n" + "wlist(0,2,neg(atom(t)),1).\n" + "set(0,pos(sum(1,0,2))).\n" + "rule(pos(atom(p)),pos(conjunction(0))).\n" + "rule(pos(atom(t)),pos(conjunction(0))).\n" + "set(1,neg(atom(q))).\n" + "set(1,neg(atom(r))).\n" + "rule(pos(atom(s)),pos(conjunction(1))).\n" + "wlist(1,0,pos(atom(p)),1).\n" + "wlist(1,1,pos(atom(t)),1).\n" + "set(2,pos(sum(1,1,2))).\n" + "rule(pos(atom(q)),pos(conjunction(2))).\n" + "rule(pos(atom(r)),pos(conjunction(2))).\n" + "set(3,pos(atom(r))).\n" + "set(3,pos(atom(q))).\n" + "rule(pos(false),pos(conjunction(3))).\n" + "scc(0,pos(atom(t))).\n" + "scc(0,pos(atom(r))).\n" + "scc(0,pos(sum(1,0,2))).\n" + "scc(0,pos(conjunction(0))).\n" + "scc(0,pos(atom(p))).\n" + "scc(0,pos(sum(1,1,2))).\n" + "scc(0,pos(conjunction(2))).\n" + "\n" + "litb(B) :- rule(_,B).\n" + "litb(E) :- litb(pos(conjunction(S))), set(S,E).\n" + "litb(E) :- eleb(sum(_,S,_)), wlist(S,_,E,_).\n" + "litb(E) :- eleb(min(_,S,_)), wlist(S,_,E,_).\n" + "litb(E) :- eleb(max(_,S,_)), wlist(S,_,E,_).\n" + "\n" + "eleb(P) :- litb(pos(P)).\n" + "eleb(N) :- litb(neg(N)).\n" + "\n" + "hold(conjunction(S)) :- eleb(conjunction(S)),\n" + " hold(P) : set(S,pos(P));\n" + " not hold(N) : set(S,neg(N)).\n" + "hold(sum(L,S,U)) :- eleb(sum(L,S,U)),\n" + " L #sum { W,Q : hold(P), wlist(S,Q,pos(P),W);\n" + " W,Q : not hold(N), wlist(S,Q,neg(N),W) } U.\n" + "hold(min(L,S,U)) :- eleb(min(L,S,U)),\n" + " L #max { W,Q : hold(P), wlist(S,Q,pos(P),W);\n" + " W,Q : not hold(N), wlist(S,Q,neg(N),W) } U.\n" + "hold(max(L,S,U)) :- eleb(max(L,S,U)),\n" + " L #min { W,Q : hold(P), wlist(S,Q,pos(P),W);\n" + " W,Q : not hold(N), wlist(S,Q,neg(N),W) } U.\n" + "\n" + "hold(atom(A)) :- rule(pos(atom(A)), pos(B)), hold(B).\n", {"hold("})); + } + + SECTION("head") { + REQUIRE( + "2<=#count{q,1:q(1);q,2:q(2);q,3:q(3);r,3:r(3);r,3:#true:not r(3);r,4:r(4);r,4:#true:not r(4);r,5:r(5);r,5:#true:not r(5)}<=4.\n" + "out(q(1)):-q(1).\n" "out(q(2)):-q(2).\n" "out(q(3)):-q(3).\n" + "out(r(3)):-r(3).\n" "out(r(4)):-r(4).\n" "out(r(5)):-r(5).\n" + "p(1).\n" "p(2).\n" "p(3).\n" "p(4).\n" "p(5).\n" == ground( + "p(1..5).\n" + "2 #count { q,X : q(X) : p(X), X <= 3; r,X : r(X) : p(X), X >= 3; r,X : not r(X) : p(X), X >= 3 } 4.\n" + "out(q(X)):-q(X).\n" + "out(r(X)):-r(X).\n")); + } + + SECTION("head2") { + REQUIRE( + "#count{0,d:d;0,e:e}.\n" + "a.\n" + "b.\n" + "c.\n" + "f:-d,e.\n" == ground( + "a.\n" + "b.\n" + "c.\n" + "{d:a;e:b}:-c.\n" + "f:-e,d.\n" + )); + REQUIRE( + "#count{0,r(a):#true}:-r(d).\n" + "#count{0,r(b):r(b)}:-r(e).\n" + "#count{0,r(e):r(e)}:-r(b).\n" + "1>=#count{0,r(b):r(b);0,r(c):r(c)}.\n" + "1>=#count{0,r(d):r(d);0,r(e):r(e)}:-r(c).\n" + "p(a,b).\n" + "p(a,c).\n" + "p(b,e).\n" + "p(c,d).\n" + "p(c,e).\n" + "p(d,a).\n" + "p(e,b).\n" + "r(a).\n" == ground( + "p(a,b).\n" + "p(a,c).\n" + "p(c,d).\n" + "p(c,e).\n" + "p(d,a).\n" + "p(b,e).\n" + "p(e,b).\n" + "\n" + "r(a).\n" + "{ r(Y) : p(X,Y) } 1 :- r(X).\n" + )); + REQUIRE( + "a.\n" + "b.\n" + "c.\n" + "e;d.\n" + "f:-d,e.\n" == ground( + "a.\n" + "b.\n" + "c.\n" + "d:a | e:b :- c.\n" + "f :- e;d.\n" + )); + REQUIRE( + "#true:-r(d).\n" + "p(a,b).\n" + "p(a,c).\n" + "p(b,e).\n" + "p(c,d).\n" + "p(c,e).\n" + "p(d,a).\n" + "p(e,b).\n" + "r(a).\n" + "r(b):-r(e).\n" + "r(b);r(c).\n" + "r(d);r(e):-r(c).\n" + "r(e):-r(b).\n" == ground( + "p(a,b).\n" + "p(a,c).\n" + "p(c,d).\n" + "p(c,e).\n" + "p(d,a).\n" + "p(b,e).\n" + "p(e,b).\n" + "\n" + "r(a).\n" + "r(Y) : p(X,Y) :- r(X).\n" + )); + } + + SECTION("disjunction") { + REQUIRE( + "out(q(1)):-q(1).\n" "out(q(2)):-q(2).\n" "out(q(3)):-q(3).\n" + "out(r(3)):-r(3).\n" "out(r(4)):-r(4).\n" "out(r(5)):-r(5).\n" + "p(1).\n" "p(2).\n" "p(3).\n" "p(4).\n" "p(5).\n" + "r(3);r(4);r(5);q(1);q(2);q(3);not r(3);not r(4);not r(5).\n" == ground( + "p(1..5).\n" + "q(X) : p(X), X <= 3; r(X) : p(X), X >= 3; not r(X) : p(X), X >= 3.\n" + "out(q(X)):-q(X).\n" + "out(r(X)):-r(X).\n")); + } + + SECTION("gbie") { + REQUIRE("gt(-3,-4).\n" == ground(gbie()+gbie1(), {"gt(", "le("})); + REQUIRE("le(-18,-16).\n" == ground(gbie()+gbie2(), {"gt(", "le("})); + } + + SECTION("strategicA") { + REQUIRE( + "strategic(1):-strategic(2),strategic(2),strategic(5).\n" + "strategic(1):-strategic(3),strategic(3),strategic(5).\n" + "strategic(1);strategic(1).\n" + "strategic(1);strategic(5).\n" + "strategic(2):-strategic(1),strategic(3),strategic(6).\n" + "strategic(2):-strategic(5),strategic(3),strategic(6).\n" + "strategic(2);strategic(4).\n" + "strategic(2);strategic(4).\n" + "strategic(2);strategic(5).\n" + "strategic(2);strategic(6).\n" + "strategic(3):-strategic(5),strategic(1),strategic(4).\n" + "strategic(3):-strategic(6),strategic(1),strategic(4).\n" + "strategic(3);strategic(4).\n" + "strategic(3);strategic(4).\n" + "strategic(4):-strategic(5),strategic(5),strategic(2).\n" + "strategic(4):-strategic(6),strategic(6),strategic(2).\n" + "strategic(4);strategic(2).\n" + "strategic(4);strategic(4).\n" + "strategic(4);strategic(4).\n" + "strategic(4);strategic(6).\n" + "strategic(5):-strategic(1),strategic(1),strategic(1).\n" + "strategic(5);strategic(2).\n" + "strategic(5);strategic(2).\n" + "strategic(5);strategic(5).\n" + "strategic(5);strategic(5).\n" + "strategic(6):-strategic(4),strategic(4),strategic(4).\n" + "strategic(6);strategic(1).\n" + "strategic(6);strategic(1).\n" + "strategic(6);strategic(2).\n" + "strategic(6);strategic(2).\n" + "strategic(6);strategic(4).\n" + "strategic(6);strategic(4).\n" + "strategic(6);strategic(5).\n" + "strategic(6);strategic(6).\n" == ground( + strategicA1() + + "strategic(X1); strategic(X2) :- produced_by(P,X1,X2).\n" + "strategic(W) :- controlled_by(W,X1,X2,X3), strategic(X1), strategic(X2), strategic(X3).\n", {"strategic("})); + } + + SECTION("strategicB") { + REQUIRE( + "strategic(1).\n" + "strategic(1):-strategic(5),strategic(2).\n" + "strategic(1):-strategic(5),strategic(3).\n" + "strategic(1);strategic(6).\n" + "strategic(1);strategic(6).\n" + "strategic(2):-strategic(6),strategic(3),strategic(1).\n" + "strategic(2):-strategic(6),strategic(3),strategic(5).\n" + "strategic(2);strategic(4).\n" + "strategic(2);strategic(5).\n" + "strategic(2);strategic(5).\n" + "strategic(2);strategic(6).\n" + "strategic(2);strategic(6).\n" + "strategic(3):-strategic(4),strategic(1),strategic(5).\n" + "strategic(3):-strategic(4),strategic(1),strategic(6).\n" + "strategic(4).\n" + "strategic(4).\n" + "strategic(4):-strategic(2),strategic(5).\n" + "strategic(4):-strategic(2),strategic(6).\n" + "strategic(4);strategic(2).\n" + "strategic(4);strategic(2).\n" + "strategic(4);strategic(3).\n" + "strategic(4);strategic(3).\n" + "strategic(4);strategic(6).\n" + "strategic(4);strategic(6).\n" + "strategic(5).\n" + "strategic(5).\n" + "strategic(5):-strategic(1).\n" + "strategic(5);strategic(1).\n" + "strategic(5);strategic(2).\n" + "strategic(5);strategic(6).\n" + "strategic(6).\n" + "strategic(6):-strategic(4).\n" + "strategic(6);strategic(2).\n" + "strategic(6);strategic(4).\n" == ground( + strategicB1() + + "strategic(X) : produced_by(P,X) :- produced_by(P,_).\n" + "strategic(X) :- controlled_by(C,X,_), strategic(Y) : controlled_by(C,X,Y).\n", {"strategic("})); + } + + SECTION("optimize") { + REQUIRE( + ":~p(1).[1@0]\n" + ":~p(2).[2@0]\n" + ":~p(3).[3@0]\n" + ":~p(4).[4@0]\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" + "{p(4)}.\n" == ground( + "{p((1..4))}." + ":~p(X).[X@0]")); + REQUIRE( + ":~p(1).[1@0]\n" + ":~p(2).[2@0]\n" + ":~p(3).[3@0]\n" + ":~p(4).[4@0]\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" + "{p(4)}.\n" == ground( + "{p((1..4))}." + "#minimize{X@0:p(X)}.")); + REQUIRE( + ":~p(1).[-1@0]\n" + ":~p(2).[-2@0]\n" + ":~p(3).[-3@0]\n" + ":~p(4).[-4@0]\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" + "{p(4)}.\n" == ground( + "{p((1..4))}." + "#maximize{X@0:p(X)}.")); + REQUIRE( + ":~.[1@1]\n" + ":~p(1),p(1).[1@1,f,g]\n" + ":~p(1).[1@0]\n" + ":~p(1).[1@2]\n" + ":~p(2),p(2).[2@2,f,g]\n" + ":~p(2).[2@0]\n" + ":~p(2).[2@2]\n" + ":~p(3),p(3).[3@3,f,g]\n" + ":~p(3).[3@0]\n" + ":~p(3).[3@2]\n" + ":~p(4),p(4).[4@4,f,g]\n" + ":~p(4).[4@0]\n" + ":~p(4).[4@2]\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" + "{p(4)}.\n" + "-:1:41-42: info: tuple ignored:\n f@f\n" + == ground( + "{p((1..4))}." + "#minimize{X:p(X); X@2:p(X); f@f; 1@1; X@X,f,g:p(X),p(X)}.")); + } + + SECTION("neg") { + REQUIRE( + "-q(1):-not not -q(1).\n" + "-q(2):-not not -q(2).\n" + "-q(3):-not not -q(3).\n" + "-q(4):-not not -q(4).\n" + ":-q(1),-q(1).\n" + ":-q(2),-q(2).\n" + ":-q(3),-q(3).\n" + ":-q(4),-q(4).\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" + "p(4).\n" + "q(1):-not not q(1).\n" + "q(2):-not not q(2).\n" + "q(3):-not not q(3).\n" + "q(4):-not not q(4).\n" == ground( + "p(1..4).\n" + "-q(X):-not not -q(X), p(X).\n" + " q(X):-not not q(X), p(X).\n")); + } + + SECTION("tuple") { + REQUIRE("p(((),())).\n" == ground("p(((),())).\n")); + } + +} + +} } } // namespace Test Ground Gringo + diff --git a/libgringo/tests/ground/literal.cc b/libgringo/tests/ground/literal.cc new file mode 100644 index 0000000..4d14df6 --- /dev/null +++ b/libgringo/tests/ground/literal.cc @@ -0,0 +1,175 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/literals.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +#include + +namespace Gringo { namespace Ground { namespace Test { + +using namespace Gringo::IO; +using namespace Gringo::Test; + +namespace { + +using S = std::string; +using V = Symbol; +template +using L = std::initializer_list; +template +using P = std::pair; +template +using U = std::unique_ptr; + +std::string evalRange(UTerm assign, UTerm l, UTerm r) { + Gringo::Test::TestGringoModule module; + Potassco::TheoryData theory; + DomainData data(theory); + Scripts scripts(module); + RangeLiteral lit(get_clone(assign), get_clone(l), get_clone(r)); + Term::VarSet bound; + UIdx idx(lit.index(scripts, BinderType::ALL, bound)); + SymVec vals; + idx->match(module.logger); + bool undefined = false; + while (idx->next()) { vals.emplace_back(assign->eval(undefined, module.logger)); } + return to_string(vals); +} + +std::string evalRelation(Relation rel, UTerm l, UTerm r) { + Gringo::Test::TestGringoModule module; + Potassco::TheoryData theory; + DomainData data(theory); + Scripts scripts(module); + Term::VarSet bound; + RelationLiteral lit(rel, get_clone(l), get_clone(r)); + UIdx idx(lit.index(scripts, BinderType::ALL, bound)); + std::vector vals; + idx->match(module.logger); + bool undefined = false; + while (idx->next()) { + vals.emplace_back(); + vals.back() += to_string(l->eval(undefined, module.logger)); + vals.back() += to_string(rel); + vals.back() += to_string(r->eval(undefined, module.logger)); + } + return to_string(vals); +} + +S evalPred(L> vals, L> bound, BinderType type, NAF naf, UTerm &&repr, bool recursive = false) { + Gringo::Test::TestGringoModule module; + Potassco::TheoryData theory; + DomainData data(theory); + Scripts scripts(module); + Term::VarSet boundSet; + for (auto &x : bound) { + U v(var(x.first.c_str())); + boundSet.emplace(x.first.c_str()); + *v->ref = x.second; + } + auto &dom = data.add(Sig("f", 2, false)); + PredicateLiteral lit(false, dom, naf, get_clone(repr)); + if (recursive) { lit.setType(OccurrenceType::UNSTRATIFIED); } + UIdx idx = lit.index(scripts, type, boundSet); + std::vector> ret; + dom.init(); + for (auto &x : vals) { + ret.emplace_back(); + for (auto &y : x) { + dom.define(y, y < NUM(0)); + } + IndexUpdater *up{idx->getUpdater()}; + if (up) { up->update(); } + dom.nextGeneration(); + idx->match(module.logger); + while (idx->next()) { + ret.back().emplace_back(); + if (lit.offset == std::numeric_limits::max()) { + ret.back().back() += "#false"; + } + else { + ret.back().back() += to_string(static_cast(dom[lit.offset])); + } + } + std::sort(ret.back().begin(), ret.back().end()); + } + return to_string(ret); +} + +}// namespace + +TEST_CASE("ground-literal", "[ground]") { + + SECTION("range") { + REQUIRE("[]" == evalRange(var("X"), val(NUM(1)), val(NUM(0)))); + REQUIRE("[1]" == evalRange(var("X"), val(NUM(1)), val(NUM(1)))); + REQUIRE("[1,2]" == evalRange(var("X"), val(NUM(1)), val(NUM(2)))); + REQUIRE("[]" == evalRange(var("X"), val(NUM(1)), val(ID("a")))); + REQUIRE("[]" == evalRange(val(NUM(0)), val(NUM(1)), val(NUM(2)))); + REQUIRE("[1]" == evalRange(val(NUM(1)), val(NUM(1)), val(NUM(2)))); + REQUIRE("[2]" == evalRange(val(NUM(2)), val(NUM(1)), val(NUM(2)))); + REQUIRE("[]" == evalRange(val(NUM(3)), val(NUM(1)), val(NUM(2)))); + } + + SECTION("relation") { + REQUIRE("[]" == evalRelation(Relation::LT, val(NUM(1)), val(NUM(1)))); + REQUIRE("[1<2]" == evalRelation(Relation::LT, val(NUM(1)), val(NUM(2)))); + REQUIRE("[1=1]" == evalRelation(Relation::EQ, var("X"), val(NUM(1)))); + REQUIRE("[f(1,g(1))=f(1,g(1))]" == evalRelation(Relation::EQ, fun("f", var("X"), fun("g", var("X"))), val(FUN("f", {NUM(1), FUN("g", {NUM(1)})})))); + REQUIRE("[]" == evalRelation(Relation::EQ, fun("f", var("X"), fun("g", var("X"))), val(FUN("f", {NUM(1), FUN("g", {NUM(2)})})))); + } + + SECTION("pred") { + // BIND + LOOKUP + POS + OLD/NEW/ALL + REQUIRE("[[f(1,1),f(1,2)],[f(1,1),f(1,2),f(1,3)]]" == evalPred({{FUN("f",{NUM(1),NUM(1)}),FUN("f",{NUM(2),NUM(2)}),FUN("f",{NUM(1),NUM(2)})},{FUN("f",{NUM(1),NUM(3)})}}, {{"X",NUM(1)}}, BinderType::ALL, NAF::POS, fun("f",var("X"),var("Y")), true)); + REQUIRE("[[],[f(1,1),f(1,2)]]" == evalPred({{FUN("f",{NUM(1),NUM(1)}),FUN("f",{NUM(2),NUM(2)}),FUN("f",{NUM(1),NUM(2)})},{FUN("f",{NUM(1),NUM(3)})}}, {{"X",NUM(1)}}, BinderType::OLD, NAF::POS, fun("f",var("X"),var("Y")), true)); + REQUIRE("[[f(1,1),f(1,2)],[f(1,3)]]" == evalPred({{FUN("f",{NUM(1),NUM(1)}),FUN("f",{NUM(2),NUM(2)}),FUN("f",{NUM(1),NUM(2)})},{FUN("f",{NUM(1),NUM(3)})}}, {{"X",NUM(1)}}, BinderType::NEW, NAF::POS, fun("f",var("X"),var("Y")), true)); + // MATCH + POS + OLD/NEW/ALL + recursive + REQUIRE("[[],[1],[1]]" == evalPred({{NUM(2)},{NUM(1)},{NUM(3)}}, {}, BinderType::ALL, NAF::POS, val(NUM(1)), true)); + REQUIRE("[[],[],[1]]" == evalPred({{NUM(2)},{NUM(1)},{NUM(3)}}, {}, BinderType::OLD, NAF::POS, val(NUM(1)), true)); + REQUIRE("[[],[1],[]]" == evalPred({{NUM(2)},{NUM(1)},{NUM(3)}}, {}, BinderType::NEW, NAF::POS, val(NUM(1)), true)); + REQUIRE("[[],[1],[1]]" == evalPred({{NUM(2)},{NUM(1)},{NUM(3)}}, {}, BinderType::ALL, NAF::POS, val(NUM(1)))); + // MATCH NOT fact/unknown + REQUIRE("[[1],[1]]" == evalPred({{NUM(1),NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOT, val(NUM(1)))); + REQUIRE("[[],[]]" == evalPred({{NUM(-1),NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOT, val(NUM(-1)))); + REQUIRE("[[1],[1]]" == evalPred({{NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOT, val(NUM(1)), true)); + REQUIRE("[[#false],[#false]]" == evalPred({{NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOT, val(NUM(1)))); + // MATCH NOTNOT fact/unknown + REQUIRE("[[1],[1]]" == evalPred({{NUM(1),NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOTNOT, val(NUM(1)))); + REQUIRE("[[-1],[-1]]" == evalPred({{NUM(-1),NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOTNOT, val(NUM(-1)))); + REQUIRE("[[1],[1]]" == evalPred({{NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOTNOT, val(NUM(1)), true)); + REQUIRE("[[],[]]" == evalPred({{NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::NOTNOT, val(NUM(1)))); + // FULL + OLD/NEW/ALL + REQUIRE("[[1,2],[1,2,3]]" == evalPred({{NUM(1),NUM(2)},{NUM(3)}}, {}, BinderType::ALL, NAF::POS, var("X"), true)); + REQUIRE("[[1,2],[3]]" == evalPred({{NUM(1),NUM(2)},{NUM(3)}}, {}, BinderType::NEW, NAF::POS, var("X"), true)); + REQUIRE("[[],[1,2]]" == evalPred({{NUM(1),NUM(2)},{NUM(3)}}, {}, BinderType::OLD, NAF::POS, var("X"), true)); + // BIND + LOOKUP + POS + OLD/NEW/ALL + REQUIRE("[[f(1,1),f(1,2)],[f(1,1),f(1,2),f(1,3)]]" == evalPred({{FUN("f",{NUM(1),NUM(1)}),FUN("f",{NUM(2),NUM(2)}),FUN("f",{NUM(1),NUM(2)})},{FUN("f",{NUM(1),NUM(3)})}}, {{"X",NUM(1)}}, BinderType::ALL, NAF::POS, fun("f",var("X"),var("Y")), true)); + REQUIRE("[[],[f(1,1),f(1,2)]]" == evalPred({{FUN("f",{NUM(1),NUM(1)}),FUN("f",{NUM(2),NUM(2)}),FUN("f",{NUM(1),NUM(2)})},{FUN("f",{NUM(1),NUM(3)})}}, {{"X",NUM(1)}}, BinderType::OLD, NAF::POS, fun("f",var("X"),var("Y")), true)); + REQUIRE("[[f(1,1),f(1,2)],[f(1,3)]]" == evalPred({{FUN("f",{NUM(1),NUM(1)}),FUN("f",{NUM(2),NUM(2)}),FUN("f",{NUM(1),NUM(2)})},{FUN("f",{NUM(1),NUM(3)})}}, {{"X",NUM(1)}}, BinderType::NEW, NAF::POS, fun("f",var("X"),var("Y")), true)); + } +} + +} } } // namespace Test Ground Gringo + diff --git a/libgringo/tests/ground/program.cc b/libgringo/tests/ground/program.cc new file mode 100644 index 0000000..d5f8eb9 --- /dev/null +++ b/libgringo/tests/ground/program.cc @@ -0,0 +1,255 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/program.hh" +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/program.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" + +namespace Gringo { namespace Ground { namespace Test { + +using namespace Gringo::IO; + +// {{{ definition of auxiliary functions + +namespace { + +typedef std::string S; + +Program parse(std::string const &str) { + Gringo::Test::TestGringoModule module; + std::ostringstream oss; + Potassco::TheoryData td; + Output::OutputBase out(td, {}, oss); + Input::Program prg; + Defines defs; + Scripts scripts(module); + Input::NongroundProgramBuilder pb{ scripts, prg, out, defs }; + Input::NonGroundParser ngp{ pb }; + ngp.pushStream("-", gringo_make_unique(str), module.logger); + ngp.parse(module.logger); + prg.rewrite(defs, module.logger); + return prg.toGround(out.data, module.logger); +} + +std::string toString(Program const &p) { + std::string str = to_string(p); + replace_all(str, ",[#inc_base]", ""); + replace_all(str, ":-[#inc_base].", "."); + replace_all(str, ":-[#inc_base],", ":-"); + replace_all(str, ":-[#inc_base];", ":-"); + return str; +} + +} // namespace + +// }}} + +TEST_CASE("ground-program", "[ground]") { + + SECTION("toGround") { + REQUIRE( + "% component\n" + "#external." == + toString(parse("p(1;2)."))); + REQUIRE( + "% component\n#external.\n" + "% positive component\n" + "p(X):-q(X)." == + toString(parse("p(X):-q(X)."))); + REQUIRE( + "% component\n#external.\n" + "% positive component\n" + "p(#Range0):-#Range0=1..2." == + toString(parse("p(1..2)."))); + REQUIRE( + "% component\n#external.\n" + "% positive component\n" + "p(X):-X=1." == + toString(parse("p(X):-X=1."))); + REQUIRE( + "% component\n#external.\n" + "% component\n" + "#false:-0=0." == + toString(parse(":-."))); + REQUIRE( + "% component\n#external.\n" + "% component\n" + "#false:-not not p." == + toString(parse("not p."))); + REQUIRE( + "% component\n#external.\n" + "% positive component\n" + "p(X,Y):-p(Y),p(X),X=Y,Y=X." == + toString(parse("p(X,Y):-X=Y,p(X),p(Y)."))); + REQUIRE( + "% component\n" + "#external.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(#special)):-[p(X,Y,Z)],0>Z.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(A)):-[p(X,Y,Z)],q(A),r(A,X).\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(B,Y)):-[p(X,Y,Z)],a(B,Y).\n" + "% positive component\n" + "#d0(Z,X,Y):-#accu(#d0(Z,X,Y),tuple(#special)),#accu(#d0(Z,X,Y),tuple(A)),#accu(#d0(Z,X,Y),tuple(B,Y)).\n" + "% positive component\n" + "x:-p(X,Y,Z),Z<#count{#d0(Z,X,Y)}." == + toString(parse("x:-p(X,Y,Z),Z<#count{A:q(A),r(A,X);B,Y:a(B,Y)}."))); + REQUIRE( + "% component\n" + "#external.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(#special)):-[p(X,Y,Z)],0=Z.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(A)):-[p(X,Y,Z)],q(A),r(A,X).\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(B,Y)):-[p(X,Y,Z)],a(B,Y).\n" + "% positive component\n" + "#d0(Z,X,Y):-#accu(#d0(Z,X,Y),tuple(#special)),#accu(#d0(Z,X,Y),tuple(A)),#accu(#d0(Z,X,Y),tuple(B,Y)).\n" + "% positive component\n" + "x:-p(X,Y,Z),Z=#count{#d0(Z,X,Y)}." == + toString(parse("x:-p(X,Y,Z),Z=#count{A:q(A),r(A,X);B,Y:a(B,Y)}."))); + REQUIRE( + "% component\n" + "#external.\n" + "% positive component\n" + "#accu(#d0(X,Y,ZZ),tuple(#special)):-[p(X,Y,Z)].\n" + "% positive component\n" + "#accu(#d0(X,Y,ZZ),tuple(A)):-[p(X,Y,Z)],q(A),r(A,X).\n" + "% positive component\n" + "#accu(#d0(X,Y,ZZ),tuple(B,Y)):-[p(X,Y,Z)],a(B,Y).\n" + "% positive component\n" + "#d0(X,Y,ZZ):-#accu(#d0(X,Y,ZZ),tuple(#special));#accu(#d0(X,Y,ZZ),tuple(A));#accu(#d0(X,Y,ZZ),tuple(B,Y)).\n" + "% positive component\n" + "x:-p(X,Y,Z),ZZ=#count{#d0(X,Y,ZZ)}." == + toString(parse("x:-p(X,Y,Z),ZZ=#count{A:q(A),r(A,X);B,Y:a(B,Y)}."))); + REQUIRE( + "% component\n" + "#external.\n" + "% component\n" + "Z<#count(#d0(Z,X,Y)):-p(X,Y,Z).\n" + "% component\n" + "#accu(#d0(Z,X,Y),q(A),tuple(A)):-r(A,X),#d0(Z,X,Y)!.\n" + "% component\n" + "#accu(#d0(Z,X,Y),x,tuple(B,Y)):-a(B,Y),#d0(Z,X,Y)!.\n" + "% component\n" + "Z<#count{A:q(A):#accu(#d0(Z,X,Y),q(A),tuple(A));B,Y:x:#accu(#d0(Z,X,Y),x,tuple(B,Y))}:-#d0(Z,X,Y)!." == + toString(parse("Z<#count{A:q(A):r(A,X);B,Y:x:a(B,Y)}:-p(X,Y,Z)."))); + REQUIRE( + "% component\n" + "#external.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(#special)):-[p(X,Y,Z)],0>Z.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(1,q(A))):-[p(X,Y,Z)],r(A,X),not q(A).\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(0,a(B,Y))):-[p(X,Y,Z)],a(B,Y).\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(3,X,1)):-[p(X,Y,Z)],q(X),X>1.\n" + "% positive component\n" + "#d0(Z,X,Y):-#accu(#d0(Z,X,Y),tuple(#special)),#accu(#d0(Z,X,Y),tuple(1,q(A))),#accu(#d0(Z,X,Y),tuple(0,a(B,Y))),#accu(#d0(Z,X,Y),tuple(3,X,1)).\n" + "% positive component\n" + "x:-p(X,Y,Z),Z<#count{#d0(Z,X,Y)}." == + toString(parse("x:-p(X,Y,Z),Z<{not q(A):r(A,X);a(B,Y);X>1:q(X)}."))); + REQUIRE( + "% component\n" + "#external.\n" + "% component\n" + "Z<#count(#d0(Z,X,Y)):-p(X,Y,Z).\n" + "% component\n" + "#accu(#d0(Z,X,Y),#true):-r(A,X),not q(A),#d0(Z,X,Y)!.\n" + "% component\n" + "#accu(#d0(Z,X,Y),a(B,Y),tuple(0,a(B,Y))):-#d0(Z,X,Y)!.\n" + "% component\n" + "#accu(#d0(Z,X,Y),#true):-q(X),X>1,#d0(Z,X,Y)!.\n" + "% component\n" + "Z<#count{1,q(A):#true:#accu(#d0(Z,X,Y),#true);0,a(B,Y):a(B,Y):#accu(#d0(Z,X,Y),a(B,Y),tuple(0,a(B,Y)));3,X,1:#true:#accu(#d0(Z,X,Y),#true)}:-#d0(Z,X,Y)!." == + toString(parse("Z<{not q(A):r(A,X);a(B,Y);X>1:q(X)}:-p(X,Y,Z)."))); + REQUIRE( + "% component\n" + "#external.\n" + "% component\n" + "#d0(Y,X):-p(X,Y,Z).\n" + "% component\n" + "#complete(#d0(Y,X)):-[#d0(Y,X)!].\n" + "% component\n" + "#complete(#d0(Y,X)):-r(A,X),[#d0(Y,X)!].\n" + "% component\n" + "a(B,Y);q(A):-#complete(#d0(Y,X))!" == + toString(parse("q(A):r(A,X);a(B,Y):-p(X,Y,Z)."))); + REQUIRE( + "% component\n" + "#external.\n" + "% component\n" + "#d0(Y,X):-p(X,Y,Z).\n" + "% component\n" + "#complete(#d0(Y,X)):-[#d0(Y,X)!].\n" + "% component\n" + "#complete(#d0(Y,X)):-q(X),[#d0(Y,X)!].\n" + "% component\n" + "#complete(#d0(Y,X)):-r(A,X),[#d0(Y,X)!].\n" + "% component\n" + "a(B,Y);#false:X<=1;#false:not not q(A):-#complete(#d0(Y,X))!" == + toString(parse("not q(A):r(A,X);a(B,Y);X>1:q(X):-p(X,Y,Z)."))); + REQUIRE( + "% component\n" + "#external.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(#special)):-[p(X,Y,Z)],0>Z.\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(A)):-[p(X,Y,Z)],q(A),r(A,X).\n" + "% positive component\n" + "#accu(#d0(Z,X,Y),tuple(B,Y)):-[p(X,Y,Z)],a(B,Y).\n" + "% positive component\n" + "#d0(Z,X,Y):-#accu(#d0(Z,X,Y),tuple(#special)),#accu(#d0(Z,X,Y),tuple(A)),#accu(#d0(Z,X,Y),tuple(B,Y)).\n" + "% positive component\n" + "x:-p(X,Y,Z),Z<#count{#d0(Z,X,Y)}." == + toString(parse("x:-p(X,Y,Z),Z<#count{A:q(A),r(A,X);B,Y:a(B,Y)}."))); + } + + SECTION("analyze") { + REQUIRE( + "% component\n#external.\n" + "% positive component\n" + "x:-x?.\n" + "% positive component\n" + "b:-a?.\n" + "a:-not y,x,b?.\n" + "% positive component\n" + "c:-b,a." == + toString(parse("x:-x.a:-b,x,not y.b:-a.c:-a,b."))); + REQUIRE( + "% component\n#external.\n" + "% positive component\n" + "x:-x?.\n" + "% component\n" + "a:-not b?.\n" + "% component\n" + "b:-x,a!,not a!." == + toString(parse("x:-x.a:-not b.b:-not a,a,x."))); + } + +} + +} } } // namespace Test Ground Gringo diff --git a/libgringo/tests/ground/theory.cc b/libgringo/tests/ground/theory.cc new file mode 100644 index 0000000..5e651cf --- /dev/null +++ b/libgringo/tests/ground/theory.cc @@ -0,0 +1,246 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "tests/ground/grounder_helper.hh" + +namespace Gringo { namespace Ground { namespace Test { + +TEST_CASE("ground-theory", "[ground]") { + + SECTION("directive") { + std::string theory = + "#theory t {" + " group { };" + " &a/0 : group, directive" + "}."; + REQUIRE( + "&a{}.\n" == + Gringo::Ground::Test::groundText( + theory + + "&a { }.")); + REQUIRE( + "&a{1; 2; 3; f(1); f(2); f(3)}.\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" == Gringo::Ground::Test::groundText(theory + + "p(1..3)." + "&a { X : p(X); f(X) : p(X) }." + )); + REQUIRE( + "&a{1: p(1); 2: p(2); 3: p(3); f(1): p(1); f(2): p(2); f(3): p(3)}.\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" == Gringo::Ground::Test::groundText(theory + + "{p(1..3)}." + "&a { X : p(X); f(X) : p(X) }." + )); + } + + SECTION("head") { + std::string theory = + "#theory t {" + " group { };" + " &a/0 : group, head" + "}."; + REQUIRE( + "&a{}.\n" == + Gringo::Ground::Test::groundText( + theory + + "&a { }.")); + REQUIRE( + "&a{1; 2; 3; f(1); f(2); f(3)}.\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" == Gringo::Ground::Test::groundText(theory + + "p(1..3)." + "&a { X : p(X); f(X) : p(X) }." + )); + REQUIRE( + "&a{1: p(1); 2: p(2); 3: p(3); f(1): p(1); f(2): p(2); f(3): p(3)}.\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" == Gringo::Ground::Test::groundText(theory + + "{p(1..3)}." + "&a { X : p(X); f(X) : p(X) }." + )); + REQUIRE( + "&a{1: p(1); 2: p(2); 3: p(3)}:-p(1).\n" + "&a{1: p(1); 2: p(2); 3: p(3)}:-p(2).\n" + "&a{1: p(1); 2: p(2); 3: p(3)}:-p(3).\n" + "p(2):-p(1).\n" + "p(3):-p(2).\n" + "{p(1)}.\n" == Gringo::Ground::Test::groundText(theory + + "{p(1)}." + "p(X+1) :- p(X), X < 3." + "&a { Y : p(Y) } :- p(X)." + )); + } + + SECTION("body") { + std::string theory = + "#theory t {" + " group { };" + " &a/0 : group, body" + "}."; + REQUIRE( + ":-&a{}.\n" == Gringo::Ground::Test::groundText( + theory + + ":-&a { }.")); + REQUIRE( + ":-&a{1; 2; 3; f(1); f(2); f(3)}.\n" + "p(1).\n" + "p(2).\n" + "p(3).\n" == Gringo::Ground::Test::groundText(theory + + "p(1..3)." + ":-&a { X : p(X); f(X) : p(X) }." + )); + REQUIRE( + ":-&a{1: p(1); 2: p(2); 3: p(3); f(1): p(1); f(2): p(2); f(3): p(3)}.\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" == Gringo::Ground::Test::groundText(theory + + "{p(1..3)}." + ":-&a { X : p(X); f(X) : p(X) }." + )); + REQUIRE( + ":-not &a{1: p(1); 2: p(2); 3: p(3)}.\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" == Gringo::Ground::Test::groundText(theory + + "{p(1..3)}." + ":-not &a { X : p(X) }." + )); + REQUIRE( + ":-not not &a{1: p(1); 2: p(2); 3: p(3)}.\n" + "{p(1)}.\n" + "{p(2)}.\n" + "{p(3)}.\n" == Gringo::Ground::Test::groundText(theory + + "{p(1..3)}." + ":-not not &a { X : p(X) }." + )); + REQUIRE( + "p(1).\n" + "p(2):-&a{1; 2: p(2); 3: p(3)}.\n" + "p(3):-&a{1; 2: p(2); 3: p(3)},p(2).\n" == Gringo::Ground::Test::groundText(theory + + "p(1)." + "p(X+1) :- p(X), X < 3, &a { Y : p(Y) }." + )); + REQUIRE( + "p(1).\n" + "p(2):-not &a{1; 2: p(2); 3: p(3)}.\n" + "p(3):-not &a{1; 2: p(2); 3: p(3)},p(2).\n" == Gringo::Ground::Test::groundText(theory + + "p(1)." + "p(X+1) :- p(X), X < 3, not &a { Y : p(Y) }." + )); + REQUIRE( + "p(1).\n" + "p(2):-not not &a{1; 2: p(2); 3: p(3)}.\n" + "p(3):-not not &a{1; 2: p(2); 3: p(3)},p(2).\n" == Gringo::Ground::Test::groundText(theory + + "p(1)." + "p(X+1) :- p(X), X < 3, not not &a { Y : p(Y) }." + )); + REQUIRE( + "&sum{height: a; height}<=(1).\n" + "&sum{height: a; height}<=(2).\n" + "&sum{height: a; height}<=(3).\n" + "dom(1,1).\n" + "dom(1,2).\n" + "dom(1,3).\n" + "dom(2,1).\n" + "dom(2,2).\n" + "dom(2,3).\n" + "{a;b}.\n" == Gringo::Ground::Test::groundText( + "#theory t {\n" + " t { };\n" + " &sum/0 : t, {<=}, t, head\n" + "}.\n" + "dom(1..2,V) :- V=1..3.\n" + "{ a; b }.\n" + "&sum{height : a; height; height} <= V :- dom(I,V).\n" + )); + } + + SECTION("guard") { + std::string theory = + "#theory t {\n" + " group { };\n" + " &a/0 : group, {=,>=}, group, head\n" + "}.\n"; + REQUIRE( + "&a{}=(1).\n" + "&a{}=(2).\n" + "&a{}=(3).\n" == Gringo::Ground::Test::groundText( + theory + + "&a { } = X :- X=1..3.")); + REQUIRE( + "&a{}>=(1).\n" + "&a{}>=(2).\n" + "&a{}>=(3).\n" == Gringo::Ground::Test::groundText( + theory + + "&a { } >= X :- X=1..3.")); + } + + SECTION("term") { + std::string theory = + "#theory t {\n" + " group {\n" + " + : 4, unary;\n" + " - : 4, unary;\n" + " ^ : 3, binary, right;\n" + " * : 2, binary, left;\n" + " + : 1, binary, left;\n" + " - : 1, binary, left\n" + " };\n" + " &a/0 : group, head\n" + "}.\n"; + REQUIRE( + "&a{: }.\n" == Gringo::Ground::Test::groundText( + theory + + "&a { : }.")); + REQUIRE( + "&a{#inf}.\n" + "&a{#sup}.\n" + "&a{(-2)}.\n" + "&a{(-c)}.\n" + "&a{(-f(c))}.\n" + "&a{(1,2)}.\n" + "&a{1}.\n" + "&a{c}.\n" + "&a{f(c)}.\n" == + Gringo::Ground::Test::groundText( + theory + + "&a { X } :- X=(1;c;f(c);-2;-f(c);-c;#sup;#inf;(1,2)).")); + REQUIRE("&a{()}.\n" == Gringo::Ground::Test::groundText(theory + "&a { () }.")); + REQUIRE("&a{(1,)}.\n" == Gringo::Ground::Test::groundText(theory + "&a { (1,) }.")); + REQUIRE("&a{(1,2)}.\n" == Gringo::Ground::Test::groundText(theory + "&a { (1,2) }.")); + REQUIRE("&a{[1,2]}.\n" == Gringo::Ground::Test::groundText(theory + "&a { [1,2] }.")); + REQUIRE("&a{{1,2}}.\n" == Gringo::Ground::Test::groundText(theory + "&a { {1,2} }.")); + REQUIRE("&a{(-1)}.\n" == Gringo::Ground::Test::groundText(theory + "&a { (-1) }.")); + REQUIRE("&a{(-(+1))}.\n" == Gringo::Ground::Test::groundText(theory + "&a { - + 1 }.")); + REQUIRE("&a{(1^(2^3))}.\n" == Gringo::Ground::Test::groundText(theory + "&a { 1^2^3 }.")); + REQUIRE("&a{((1*2)*3)}.\n" == Gringo::Ground::Test::groundText(theory + "&a { 1*2*3 }.")); + REQUIRE("&a{(1+(2*(3^4)))}.\n" == Gringo::Ground::Test::groundText(theory + "&a { 1+2*3^4 }.")); + REQUIRE("&a{(1+((-2)*((-3)^4)))}.\n" == Gringo::Ground::Test::groundText(theory + "&a { 1 + -2 * -3^4 }.")); + } +} + +} } } // namespace Test Ground Gringo + diff --git a/libgringo/tests/input/aggregate.cc b/libgringo/tests/input/aggregate.cc new file mode 100644 index 0000000..016b5de --- /dev/null +++ b/libgringo/tests/input/aggregate.cc @@ -0,0 +1,414 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/bug.hh" +#include "gringo/input/aggregate.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/input/lit_helper.hh" +#include "tests/input/aggregate_helper.hh" + +#include +#include + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::IO; + +// {{{ auxiliary functions and classes + +namespace { + +ULit lit(char const *name) { return pred(NAF::POS, val(ID(name))); } +template +ULit lit(T... name) { return pred(NAF::POS, pool(val(ID(name))...)); } + +UTerm dterm(int a, int b) { return dots(val(NUM(a)), val(NUM(b))); } +ULit dlit(int a, int b) { return pred(NAF::POS, fun("p", dterm(a, b))); } + +UTerm aterm(char const *a, char const * b) { return binop(BinOp::ADD, var(a), var(b)); } +ULit alit(char const * a, char const * b) { return pred(NAF::POS, fun("p", aterm(a, b))); } + +BoundVec bound1() { return boundvec(Relation::LT, val(NUM(3)), Relation::GT, val(NUM(1))); } +BoundVec bound2() { return boundvec(Relation::LT, pool(val(NUM(1)), val(NUM(2))), Relation::GT, pool(val(NUM(3)), val(NUM(4)))); } +BoundVec bound3() { return boundvec(Relation::LT, pool(val(NUM(1)), val(NUM(2)))); } + +BodyAggrElemVec bdvec1() { return bdelemvec(); } +BodyAggrElemVec bdvec2() { return bdelemvec(termvec(), litvec()); } +BodyAggrElemVec bdvec3() { return bdelemvec(termvec(val(NUM(1))), litvec(lit("p"))); } +BodyAggrElemVec bdvec4() { return bdelemvec(termvec(val(NUM(1)), val(NUM(2))), litvec(lit("p"), lit("q"))); } +BodyAggrElemVec bdvec5() { return bdelemvec(termvec(), litvec(), termvec(), litvec(lit("p"))); } +// with pool term +BodyAggrElemVec bdvec6() { return bdelemvec(termvec(pool(val(NUM(1)), val(NUM(2)))), litvec(pred(NAF::POS, pool(val(ID("p")), val(ID("q"))))), termvec(), litvec()); } +BodyAggrElemVec bdvec7() { return bdelemvec(termvec(pool(val(NUM(1)), val(NUM(2))), pool(val(NUM(3)), val(NUM(4)))), litvec()); } + +CondLitVec condvec1() { return condlitvec(); } +CondLitVec condvec2() { return condlitvec(lit("p"), litvec()); } +CondLitVec condvec3() { return condlitvec(lit("p"), litvec(lit("q"))); } +CondLitVec condvec4() { return condlitvec(lit("p"), litvec(lit("q"), lit("r"))); } +CondLitVec condvec5() { return condlitvec(lit("p"), litvec(), lit("q"), litvec()); } +CondLitVec condvec6() { return condlitvec(lit("p", "q"), litvec(lit("r", "s")), lit("t"), litvec()); } + +HeadAggrElemVec hdvec1() { return hdelemvec(); } +HeadAggrElemVec hdvec2() { return hdelemvec(termvec(), lit("p"), litvec()); } +HeadAggrElemVec hdvec3() { return hdelemvec(termvec(val(NUM(1))), lit("p"), litvec(lit("q"))); } +HeadAggrElemVec hdvec4() { return hdelemvec(termvec(val(NUM(1)), val(NUM(2))), lit("p"), litvec(lit("q"), lit("r"))); } +HeadAggrElemVec hdvec5() { return hdelemvec(termvec(), lit("p"), litvec(), termvec(), lit("q"), litvec(lit("r"))); } +// with pool term +HeadAggrElemVec hdvec6() { return hdelemvec(termvec(pool(val(NUM(1)), val(NUM(2)))), lit("p"), litvec(lit("q", "r")), termvec(), lit("s"), litvec()); } +HeadAggrElemVec hdvec7() { return hdelemvec(termvec(pool(val(NUM(1)), val(NUM(2))), pool(val(NUM(3)), val(NUM(4)))), lit("p"), litvec()); } +HeadAggrElemVec hdvec8() { return hdelemvec(termvec(val(NUM(1))), lit("p", "q"), litvec()); } + +std::string simplify(UBodyAggr &&x) { + Gringo::Test::TestGringoModule log; + Projections project; + SimplifyState state; + x->simplify(project, state, false, log); + return to_string(std::make_pair(std::move(x), std::move(state.dots))); +} + +std::string simplify(UHeadAggr &&x) { + Gringo::Test::TestGringoModule log; + Projections project; + SimplifyState state; + x->simplify(project, state, log); + return to_string(std::make_pair(std::move(x), std::move(state.dots))); +} + +std::string rewrite(UBodyAggr &&x) { + Literal::AssignVec assign; + Term::ArithmeticsMap arith; + arith.emplace_back(); + AuxGen gen; + AssignLevel v; + x->assignLevels(v); + v.assignLevels(); + x->rewriteArithmetics(arith, assign, gen); + return to_string(std::make_tuple(std::move(x), std::move(arith), std::move(assign))); +} + +std::string rewrite(UHeadAggr &&x) { + Term::ArithmeticsMap arith; + arith.emplace_back(); + AuxGen gen; + AssignLevel v; + x->assignLevels(v); + v.assignLevels(); + x->rewriteArithmetics(arith, gen); + return to_string(std::make_pair(std::move(x), std::move(arith))); +} + +UHeadAggrVec unpool(UHeadAggr &&x) { + UHeadAggrVec y; + x->unpool(y, true); + return y; +} + +UBodyAggrVec unpool(UBodyAggr &&x) { + UBodyAggrVec y; + x->unpool(y, true); + return y; +} + +} // namespace + +// }}} + +TEST_CASE("input-aggregate", "[input]") { + SECTION("print") { + // body tuple aggregate + REQUIRE("3>#sum{}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec1()))); + REQUIRE("not 3>#sum{}>1" == to_string(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), bdvec1()))); + REQUIRE("3>#count{}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec1()))); + REQUIRE("3>#count{:}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec2()))); + REQUIRE("3>#count{1:p}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec3()))); + REQUIRE("3>#count{1,2:p,q}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec4()))); + REQUIRE("3>#count{:;:p}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec5()))); + // body lit aggregate + REQUIRE("3>#sum{}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec1()))); + REQUIRE("not 3>#sum{}>1" == to_string(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), condvec1()))); + REQUIRE("3>#count{}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec1()))); + REQUIRE("3>#count{p:}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec2()))); + REQUIRE("3>#count{p:q}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec3()))); + REQUIRE("3>#count{p:q,r}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec4()))); + REQUIRE("3>#count{p:;q:}>1" == to_string(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec5()))); + // conjunction + REQUIRE("p:" == to_string(bdaggr(lit("p"), litvec()))); + REQUIRE("p:q" == to_string(bdaggr(lit("p"), litvec(lit("q"))))); + // head tuple aggregate + REQUIRE("3>#sum{}>1" == to_string(hdaggr(AggregateFunction::SUM, bound1(), hdvec1()))); + REQUIRE("3>#count{}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), hdvec1()))); + REQUIRE("3>#count{:p:}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), hdvec2()))); + REQUIRE("3>#count{1:p:q}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), hdvec3()))); + REQUIRE("3>#count{1,2:p:q,r}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), hdvec4()))); + REQUIRE("3>#count{:p:;:q:r}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), hdvec5()))); + // head lit aggregate + REQUIRE("3>#sum{}>1" == to_string(hdaggr(AggregateFunction::SUM, bound1(), condvec1()))); + REQUIRE("3>#count{}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), condvec1()))); + REQUIRE("3>#count{p:}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), condvec2()))); + REQUIRE("3>#count{p:q}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), condvec3()))); + REQUIRE("3>#count{p:q,r}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), condvec4()))); + REQUIRE("3>#count{p:;q:}>1" == to_string(hdaggr(AggregateFunction::COUNT, bound1(), condvec5()))); + // disjunction + REQUIRE("" == to_string(hdaggr(condvec1()))); + REQUIRE("p::" == to_string(hdaggr(condvec2()))); + REQUIRE("p::q" == to_string(hdaggr(condvec3()))); + REQUIRE("p::q,r" == to_string(hdaggr(condvec4()))); + REQUIRE("p::;q::" == to_string(hdaggr(condvec5()))); + } + + SECTION("clone") { + // body tuple aggregate + REQUIRE("3>#sum{}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec1())))); + REQUIRE("not 3>#sum{}>1" == to_string(get_clone(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), bdvec1())))); + REQUIRE("3>#count{}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec1())))); + REQUIRE("3>#count{:}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec2())))); + REQUIRE("3>#count{1:p}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec3())))); + REQUIRE("3>#count{1,2:p,q}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec4())))); + REQUIRE("3>#count{:;:p}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), bdvec5())))); + // body lit aggregate + REQUIRE("3>#sum{}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec1())))); + REQUIRE("not 3>#sum{}>1" == to_string(get_clone(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), condvec1())))); + REQUIRE("3>#count{}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec1())))); + REQUIRE("3>#count{p:}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec2())))); + REQUIRE("3>#count{p:q}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec3())))); + REQUIRE("3>#count{p:q,r}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec4())))); + REQUIRE("3>#count{p:;q:}>1" == to_string(get_clone(bdaggr(NAF::POS, AggregateFunction::COUNT, bound1(), condvec5())))); + // conjunction + REQUIRE("p:" == to_string(get_clone(bdaggr(lit("p"), litvec())))); + REQUIRE("p:q" == to_string(get_clone(bdaggr(lit("p"), litvec(lit("q")))))); + // head tuple aggregate + REQUIRE("3>#sum{}>1" == to_string(get_clone(hdaggr(AggregateFunction::SUM, bound1(), hdvec1())))); + REQUIRE("3>#count{}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), hdvec1())))); + REQUIRE("3>#count{:p:}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), hdvec2())))); + REQUIRE("3>#count{1:p:q}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), hdvec3())))); + REQUIRE("3>#count{1,2:p:q,r}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), hdvec4())))); + REQUIRE("3>#count{:p:;:q:r}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), hdvec5())))); + // head lit aggregate + REQUIRE("3>#sum{}>1" == to_string(get_clone(hdaggr(AggregateFunction::SUM, bound1(), condvec1())))); + REQUIRE("3>#count{}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), condvec1())))); + REQUIRE("3>#count{p:}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), condvec2())))); + REQUIRE("3>#count{p:q}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), condvec3())))); + REQUIRE("3>#count{p:q,r}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), condvec4())))); + REQUIRE("3>#count{p:;q:}>1" == to_string(get_clone(hdaggr(AggregateFunction::COUNT, bound1(), condvec5())))); + // disjunction + REQUIRE("" == to_string(get_clone(hdaggr(condvec1())))); + REQUIRE("p::" == to_string(get_clone(hdaggr(condvec2())))); + REQUIRE("p::q" == to_string(get_clone(hdaggr(condvec3())))); + REQUIRE("p::q,r" == to_string(get_clone(hdaggr(condvec4())))); + REQUIRE("p::;q::" == to_string(get_clone(hdaggr(condvec5())))); + } + + SECTION("hash") { + // body tuple aggregate + auto a1(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec1())); + auto a2(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec2())); + auto a3(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), bdvec1())); + auto a4(bdaggr(NAF::POS, AggregateFunction::COUNT, boundvec(), bdvec1())); + CHECK(a1->hash() == get_clone(a1)->hash()); + CHECK(a2->hash() == get_clone(a2)->hash()); + CHECK(a3->hash() == get_clone(a3)->hash()); + CHECK(a4->hash() == get_clone(a4)->hash()); + CHECK(a1->hash() != a2->hash()); + CHECK(a1->hash() != a3->hash()); + CHECK(a1->hash() != a4->hash()); + CHECK(a2->hash() != a3->hash()); + CHECK(a2->hash() != a4->hash()); + CHECK(a3->hash() != a4->hash()); + // body lit aggregate + auto b1(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec1())); + auto b2(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec2())); + auto b3(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), condvec1())); + auto b4(bdaggr(NAF::POS, AggregateFunction::COUNT, boundvec(), condvec1())); + CHECK(b1->hash() == get_clone(b1)->hash()); + CHECK(b2->hash() == get_clone(b2)->hash()); + CHECK(b3->hash() == get_clone(b3)->hash()); + CHECK(b4->hash() == get_clone(b4)->hash()); + CHECK(b1->hash() != b2->hash()); + CHECK(b1->hash() != b3->hash()); + CHECK(b1->hash() != b4->hash()); + CHECK(b2->hash() != b3->hash()); + CHECK(b2->hash() != b4->hash()); + CHECK(b3->hash() != b4->hash()); + // conjunction + auto c1(bdaggr(lit("p"), litvec())); + auto c2(bdaggr(lit("p"), litvec(lit("q")))); + CHECK(c1->hash() == get_clone(c1)->hash()); + CHECK(c2->hash() == get_clone(c2)->hash()); + CHECK(c1->hash() != c2->hash()); + // head tuple aggregate + auto d1(hdaggr(AggregateFunction::SUM, bound1(), hdvec1())); + auto d2(hdaggr(AggregateFunction::SUM, bound1(), hdvec2())); + auto d3(hdaggr(AggregateFunction::COUNT, boundvec(), hdvec1())); + CHECK(b1->hash() == get_clone(b1)->hash()); + CHECK(b2->hash() == get_clone(b2)->hash()); + CHECK(b3->hash() == get_clone(b3)->hash()); + CHECK(b1->hash() != b2->hash()); + CHECK(b1->hash() != b3->hash()); + CHECK(b2->hash() != b3->hash()); + // head lit aggregate + auto e1(hdaggr(AggregateFunction::SUM, bound1(), condvec1())); + auto e2(hdaggr(AggregateFunction::SUM, bound1(), condvec2())); + auto e3(hdaggr(AggregateFunction::COUNT, boundvec(), condvec1())); + CHECK(e1->hash() == get_clone(e1)->hash()); + CHECK(e2->hash() == get_clone(e2)->hash()); + CHECK(e3->hash() == get_clone(e3)->hash()); + CHECK(e1->hash() != e2->hash()); + CHECK(e1->hash() != e3->hash()); + CHECK(e2->hash() != e3->hash()); + // disjunction + auto f1(hdaggr(condvec1())); + auto f2(hdaggr(condvec2())); + CHECK(f1->hash() == get_clone(f1)->hash()); + CHECK(f2->hash() == get_clone(f2)->hash()); + CHECK(f1->hash() != f2->hash()); + } + + SECTION("equal") { + // body tuple aggregate + auto a1(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec1())); + auto a2(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec2())); + auto a3(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), bdvec1())); + auto a4(bdaggr(NAF::POS, AggregateFunction::COUNT, boundvec(), bdvec1())); + REQUIRE(*a1 == *get_clone(a1)); + REQUIRE(*a2 == *get_clone(a2)); + REQUIRE(*a3 == *get_clone(a3)); + REQUIRE(*a4 == *get_clone(a4)); + REQUIRE(!(*a1 == *a2)); + REQUIRE(!(*a1 == *a3)); + REQUIRE(!(*a1 == *a4)); + REQUIRE(!(*a2 == *a3)); + REQUIRE(!(*a2 == *a4)); + REQUIRE(!(*a3 == *a4)); + // body lit aggregate + auto b1(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec1())); + auto b2(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec2())); + auto b3(bdaggr(NAF::NOT, AggregateFunction::SUM, bound1(), condvec1())); + auto b4(bdaggr(NAF::POS, AggregateFunction::COUNT, boundvec(), condvec1())); + REQUIRE(*b1 == *get_clone(b1)); + REQUIRE(*b2 == *get_clone(b2)); + REQUIRE(*b3 == *get_clone(b3)); + REQUIRE(*b4 == *get_clone(b4)); + REQUIRE(!(*b1 == *b2)); + REQUIRE(!(*b1 == *b3)); + REQUIRE(!(*b1 == *b4)); + REQUIRE(!(*b2 == *b3)); + REQUIRE(!(*b2 == *b4)); + REQUIRE(!(*b3 == *b4)); + // conjunction + auto c1(bdaggr(lit("p"), litvec())); + auto c2(bdaggr(lit("p"), litvec(lit("q")))); + REQUIRE(*c1 == *get_clone(c1)); + REQUIRE(*c2 == *get_clone(c2)); + REQUIRE(!(*c1 == *c2)); + // head tuple aggregate + auto d1(hdaggr(AggregateFunction::SUM, bound1(), hdvec1())); + auto d2(hdaggr(AggregateFunction::SUM, bound1(), hdvec2())); + auto d3(hdaggr(AggregateFunction::COUNT, boundvec(), hdvec1())); + REQUIRE(*b1 == *get_clone(b1)); + REQUIRE(*b2 == *get_clone(b2)); + REQUIRE(*b3 == *get_clone(b3)); + REQUIRE(!(*b1 == *b2)); + REQUIRE(!(*b1 == *b3)); + REQUIRE(!(*b2 == *b3)); + // head lit aggregate + auto e1(hdaggr(AggregateFunction::SUM, bound1(), condvec1())); + auto e2(hdaggr(AggregateFunction::SUM, bound1(), condvec2())); + auto e3(hdaggr(AggregateFunction::COUNT, boundvec(), condvec1())); + REQUIRE(*e1 == *get_clone(e1)); + REQUIRE(*e2 == *get_clone(e2)); + REQUIRE(*e3 == *get_clone(e3)); + REQUIRE(!(*e1 == *e2)); + REQUIRE(!(*e1 == *e3)); + REQUIRE(!(*e2 == *e3)); + // disjunction + auto f1(hdaggr(condvec1())); + auto f2(hdaggr(condvec2())); + REQUIRE(*f1 == *get_clone(f1)); + REQUIRE(*f2 == *get_clone(f2)); + REQUIRE(!(*f1 == *f2)); + } + + SECTION("unpool") { + // body tuple aggregate + REQUIRE("[3>#sum{1,3:;2,3:;1,4:;2,4:}>1]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec7())))); + REQUIRE("[1>#sum{}>3,2>#sum{}>3,1>#sum{}>4,2>#sum{}>4]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound2(), bdvec1())))); + REQUIRE("[not 1>#min{}>3,not 2>#min{}>3,not 1>#min{}>4,not 2>#min{}>4]" == to_string(unpool(bdaggr(NAF::NOT, AggregateFunction::MIN, bound2(), bdvec1())))); + REQUIRE("[3>#sum{1:p;1:q;2:p;2:q;:}>1]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), bdvec6())))); + REQUIRE("[1>#sum{1:p;1:q;2:p;2:q;:},2>#sum{1:p;1:q;2:p;2:q;:}]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound3(), bdvec6())))); + // body lit aggregate + REQUIRE("[1>#sum{}>3,2>#sum{}>3,1>#sum{}>4,2>#sum{}>4]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound2(), condvec1())))); + REQUIRE("[not 1>#min{}>3,not 2>#min{}>3,not 1>#min{}>4,not 2>#min{}>4]" == to_string(unpool(bdaggr(NAF::NOT, AggregateFunction::MIN, bound2(), condvec1())))); + REQUIRE("[3>#sum{p:r;p:s;q:r;q:s;t:}>1]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound1(), condvec6())))); + REQUIRE("[1>#sum{p:r;p:s;q:r;q:s;t:},2>#sum{p:r;p:s;q:r;q:s;t:}]" == to_string(unpool(bdaggr(NAF::POS, AggregateFunction::SUM, bound3(), condvec6())))); + // conjunction + REQUIRE("[p|q:r]" == to_string(unpool(bdaggr(lit("p", "q"), litvec(lit("r")))))); + REQUIRE("[p:q;p:r]" == to_string(unpool(bdaggr(lit("p"), litvec(lit("q", "r")))))); + REQUIRE("[p|q:r;p|q:s]" == to_string(unpool(bdaggr(lit("p", "q"), litvec(lit("r", "s")))))); + // head tuple aggregate + REQUIRE("[3>#sum{1,3:p:;2,3:p:;1,4:p:;2,4:p:}>1]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound1(), hdvec7())))); + REQUIRE("[1>#sum{}>3,2>#sum{}>3,1>#sum{}>4,2>#sum{}>4]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound2(), hdvec1())))); + REQUIRE("[3>#sum{1:p:q;1:p:r;2:p:q;2:p:r;:s:}>1]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound1(), hdvec6())))); + REQUIRE("[3>#sum{1:p:;1:q:}>1]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound1(), hdvec8())))); + // head lit aggregate + REQUIRE("[1>#sum{}>3,2>#sum{}>3,1>#sum{}>4,2>#sum{}>4]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound2(), condvec1())))); + REQUIRE("[3>#sum{p:r;p:s;q:r;q:s;t:}>1]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound1(), condvec6())))); + REQUIRE("[1>#sum{p:r;p:s;q:r;q:s;t:},2>#sum{p:r;p:s;q:r;q:s;t:}]" == to_string(unpool(hdaggr(AggregateFunction::SUM, bound3(), condvec6())))); + // disjunction + REQUIRE("[p:&q::r;p:&q::s;t::]" == to_string(unpool(hdaggr(condvec6())))); + } + + SECTION("simplify") { + // body tuple aggregate + REQUIRE("(#Range0>#sum{#Range1:p(#Range2),#range(#Range1,3,4),#range(#Range2,5,6)},[(#Range0,1,2)])" == simplify(bdaggr(NAF::POS, AggregateFunction::SUM, boundvec(Relation::LT, dterm(1,2)), bdelemvec(termvec(dterm(3,4)), litvec(dlit(5,6)))))); + // body lit aggregate + REQUIRE("(#Range0>#sum{p(#Range1):p(#Range2),#range(#Range1,3,4),#range(#Range2,5,6)},[(#Range0,1,2)])" == simplify(bdaggr(NAF::POS, AggregateFunction::SUM, boundvec(Relation::LT, dterm(1,2)), condlitvec(dlit(3,4), litvec(dlit(5,6)))))); + // conjunction + REQUIRE("(p(#Range0)&#range(#Range0,1,2):p(#Range1),#range(#Range1,3,4),[])" == simplify(bdaggr(dlit(1,2), litvec(dlit(3,4))))); + // head tuple aggregate + REQUIRE("(#Range0>#sum{#Range1:p(#Range2):p(#Range3),#range(#Range1,3,4),#range(#Range2,5,6),#range(#Range3,7,8)},[(#Range0,1,2)])" == simplify(hdaggr(AggregateFunction::SUM, boundvec(Relation::LT, dterm(1,2)), hdelemvec(termvec(dterm(3,4)), dlit(5,6), litvec(dlit(7,8)))))); + // head lit aggregate + REQUIRE("(#Range0>#sum{p(#Range1):p(#Range2),#range(#Range1,3,4),#range(#Range2,5,6)},[(#Range0,1,2)])" == simplify(hdaggr(AggregateFunction::SUM, boundvec(Relation::LT, dterm(1,2)), condlitvec(dlit(3,4), litvec(dlit(5,6)))))); + // disjunction + REQUIRE("(p(#Range0):#range(#Range0,1,2):p(#Range1),#range(#Range1,3,4),[])" == simplify(hdaggr(condlitvec(dlit(1,2), litvec(dlit(3,4)))))); + } + + SECTION("rewriteArithmetics") { + // body tuple aggregate + REQUIRE("(#Arith0>#sum{(C+D):p(#Arith1),#Arith1=(E+F)},[{(A+B):#Arith0}],[])" == rewrite(bdaggr(NAF::POS, AggregateFunction::SUM, boundvec(Relation::LT, aterm("A","B")), bdelemvec(termvec(aterm("C","D")), litvec(alit("E","F")))))); + REQUIRE("(#Arith0=#sum{(C+D):p(#Arith0)},[{(A+B):#Arith0}],[])" == rewrite(bdaggr(NAF::POS, AggregateFunction::SUM, boundvec(Relation::EQ, aterm("A","B")), bdelemvec(termvec(aterm("C","D")), litvec(alit("A","B")))))); + // body lit aggregate + REQUIRE("(#Arith0>#sum{p((C+D)):p(#Arith1),#Arith1=(E+F)},[{(A+B):#Arith0}],[])" == rewrite(bdaggr(NAF::POS, AggregateFunction::SUM, boundvec(Relation::LT, aterm("A","B")), condlitvec(alit("C","D"), litvec(alit("E","F")))))); + REQUIRE("(#Arith0=#sum{p((C+D)):p(#Arith0)},[{(A+B):#Arith0}],[])" == rewrite(bdaggr(NAF::POS, AggregateFunction::SUM, boundvec(Relation::EQ, aterm("A","B")), condlitvec(alit("C","D"), litvec(alit("A","B")))))); + // conjunction + REQUIRE("(p(#Arith0)&#Arith0=(C+D):p(#Arith1),#Arith1=(E+F),[{}],[])" == rewrite(bdaggr(alit("C","D"), litvec(alit("E","F"))))); + // head tuple aggregate + REQUIRE("(#Arith0>#sum{(C+D):p((E+F)):p(#Arith1),#Arith1=(G+H)},[{(A+B):#Arith0}])" == rewrite(hdaggr(AggregateFunction::SUM, boundvec(Relation::LT, aterm("A","B")), hdelemvec(termvec(aterm("C","D")), alit("E", "F"), litvec(alit("G","H")))))); + // head lit aggregate + REQUIRE("(#Arith0>#sum{p((C+D)):p(#Arith1),#Arith1=(E+F)},[{(A+B):#Arith0}])" == rewrite(hdaggr(AggregateFunction::SUM, boundvec(Relation::LT, aterm("A","B")), condlitvec(alit("C","D"), litvec(alit("E","F")))))); + // disjunction + REQUIRE("(p((C+D))::p(#Arith0),#Arith0=(E+F),#Arith1=(E+F),#Arith1=#Arith0,[{}])" == rewrite(hdaggr(condlitvec(alit("C","D"), litvec(alit("E","F")))))); + } + +} + +} } } // namespace Test Input Gringo + diff --git a/libgringo/tests/input/aggregate_helper.hh b/libgringo/tests/input/aggregate_helper.hh new file mode 100644 index 0000000..aa4261b --- /dev/null +++ b/libgringo/tests/input/aggregate_helper.hh @@ -0,0 +1,89 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TEST_AGGREGATE_HELPER_HH +#define _GRINGO_TEST_AGGREGATE_HELPER_HH + +#include "tests/tests.hh" +#include "gringo/input/aggregates.hh" + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::Test; + +// {{{ definition of functions to create aggregates + +template +BoundVec boundvec(T&&... args) { + return init<2, BoundVec>(std::forward(args)...); +} + +template +CondLitVec condlitvec(T&&... args) { + return init<2,CondLitVec>(std::forward(args)...); +} + +template +BodyAggrElemVec bdelemvec(T&&... args) { + return init<2,BodyAggrElemVec>(std::forward(args)...); +} + +template +HeadAggrElemVec hdelemvec(T&&... args) { + return init<3,HeadAggrElemVec>(std::forward(args)...); +} + +inline UBodyAggr bdaggr(NAF naf, AggregateFunction fun, BoundVec &&bounds, BodyAggrElemVec &&elems) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, naf, fun, std::move(bounds), std::move(elems)); +} + +inline UBodyAggr bdaggr(NAF naf, AggregateFunction fun, BoundVec &&bounds, CondLitVec &&elems) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, naf, fun, std::move(bounds), std::move(elems)); +} + +inline UBodyAggr bdaggr(ULit &&lit, ULitVec &&cond) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, std::move(lit), std::move(cond)); +} + +inline UHeadAggr hdaggr(AggregateFunction fun, BoundVec &&bounds, HeadAggrElemVec &&elems) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, fun, std::move(bounds), std::move(elems)); +} + +inline UHeadAggr hdaggr(AggregateFunction fun, BoundVec &&bounds, CondLitVec &&elems) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, fun, std::move(bounds), std::move(elems)); +} + +inline UHeadAggr hdaggr(CondLitVec &&elems) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, std::move(elems)); +} + +// }}} + +} } } // namespace Test Input Gringo + +#endif // _GRINGO_TEST_AGGREGATE_HELPER_HH + + diff --git a/libgringo/tests/input/lit_helper.hh b/libgringo/tests/input/lit_helper.hh new file mode 100644 index 0000000..5dba416 --- /dev/null +++ b/libgringo/tests/input/lit_helper.hh @@ -0,0 +1,93 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TEST_LIT_HELPER_HH +#define _GRINGO_TEST_LIT_HELPER_HH + +#include "tests/tests.hh" +#include "gringo/input/literals.hh" + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::Test; + +// {{{ definition of functions to create literals + +inline CSPMulTerm cspmul(UTerm &&coe, UTerm &&var = nullptr) { + return CSPMulTerm(std::move(var), std::move(coe)); +} + +inline void cspadd(CSPAddTerm &) { } + +template +inline void cspadd(CSPAddTerm &add, CSPMulTerm &&mul, T&&... args) { + add.append(std::move(mul)); + cspadd(add, std::forward(args)...); +} + +template +inline CSPAddTerm cspadd(CSPMulTerm &&mul, T&&... args) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + CSPAddTerm add(std::move(mul)); + cspadd(add, std::forward(args)...); + return add; +} + +inline void csplit(CSPLiteral &) { } + +template +inline void csplit(CSPLiteral &lit, Relation rel, CSPAddTerm &&add, T&&... args) { + lit.append(rel, std::move(add)); + csplit(lit, std::forward(args)...); +} + +template +inline UCSPLit csplit(CSPAddTerm &&left, Relation rel, CSPAddTerm &&right, T&&... args) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + UCSPLit lit(make_locatable(loc, rel, std::move(left), std::move(right))); + csplit(*lit, std::forward(args)...); + return lit; +} + +inline ULit pred(NAF naf, UTerm &&arg) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, naf, std::move(arg)); +} + +inline ULit rel(Relation rel, UTerm &&left, UTerm &&right) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, rel, std::move(left), std::move(right)); +} + +inline ULit range(UTerm &&assign, UTerm &&lower, UTerm &&upper) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, std::move(assign), std::move(lower), std::move(upper)); +} + +template +ULitVec litvec(T&&... args) { + return init(std::forward(args)...); +} + +// }}} + +} } } // namespace Test Input Gringo + +#endif // _GRINGO_TEST_LIT_HELPER_HH diff --git a/libgringo/tests/input/literal.cc b/libgringo/tests/input/literal.cc new file mode 100644 index 0000000..e45aec6 --- /dev/null +++ b/libgringo/tests/input/literal.cc @@ -0,0 +1,171 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/input/lit_helper.hh" + +#include +#include + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::IO; + +// {{{ auxiliary functions and classes + +namespace { + +ULit rewrite(ULit &&x) { + Gringo::Test::TestGringoModule log; + Projections project; + Literal::AssignVec assign; + SimplifyState state; + Term::ArithmeticsMap arith; + x->simplify(log, project, state); + x->rewriteArithmetics(arith, assign, state.gen); + return std::move(x); +} + +} // namespace + +// }}} + +TEST_CASE("input-literal", "[input]") { + + SECTION("print") { + REQUIRE("x" == to_string(pred(NAF::POS, val(ID("x"))))); + REQUIRE("not x" == to_string(pred(NAF::NOT, val(ID("x"))))); + REQUIRE("not not x" == to_string(pred(NAF::NOTNOT, val(ID("x"))))); + REQUIRE("x=y" == to_string(rel(Relation::EQ, val(ID("x")), val(ID("y"))))); + REQUIRE("#range(x,y,z)" == to_string(range(val(ID("x")), val(ID("y")), val(ID("z"))))); + REQUIRE("1$*$x$+1$*$y$<=23$<=42" == to_string(csplit(cspadd(cspmul(val(NUM(1)), val(ID("x"))), cspmul(val(NUM(1)), val(ID("y")))), Relation::LEQ, cspadd(cspmul(val(ID("23")))), Relation::LEQ, cspadd(cspmul(val(ID("42"))))))); + } + + SECTION("clone") { + REQUIRE("x" == to_string(get_clone(pred(NAF::POS, val(ID("x")))))); + REQUIRE("not x" == to_string(get_clone(pred(NAF::NOT, val(ID("x")))))); + REQUIRE("not not x" == to_string(get_clone(pred(NAF::NOTNOT, val(ID("x")))))); + REQUIRE("x=x" == to_string(get_clone(rel(Relation::EQ, val(ID("x")), val(ID("x")))))); + REQUIRE("#range(x,y,z)" == to_string(get_clone(range(val(ID("x")), val(ID("y")), val(ID("z")))))); + REQUIRE("1$*$x$+1$*$y$<=23$<=42" == to_string(get_clone(csplit(cspadd(cspmul(val(NUM(1)), val(ID("x"))), cspmul(val(NUM(1)), val(ID("y")))), Relation::LEQ, cspadd(cspmul(val(ID("23")))), Relation::LEQ, cspadd(cspmul(val(ID("42")))))))); + } + + SECTION("hash") { + CHECK(pred(NAF::POS, val(ID("x")))->hash() == pred(NAF::POS, val(ID("x")))->hash()); + CHECK(!(pred(NAF::POS, val(ID("x")))->hash() == pred(NAF::NOT, val(ID("x")))->hash())); + CHECK(!(pred(NAF::POS, val(ID("x")))->hash() == pred(NAF::POS, val(ID("y")))->hash())); + CHECK(rel(Relation::EQ, val(ID("x")), val(ID("x")))->hash() == rel(Relation::EQ, val(ID("x")), val(ID("x")))->hash()); + CHECK(!(rel(Relation::EQ, val(ID("x")), val(ID("x")))->hash() == rel(Relation::LT, val(ID("x")), val(ID("x")))->hash())); + CHECK(!(rel(Relation::EQ, val(ID("x")), val(ID("x")))->hash() == rel(Relation::EQ, val(ID("y")), val(ID("x")))->hash())); + CHECK(!(rel(Relation::EQ, val(ID("x")), val(ID("x")))->hash() == rel(Relation::EQ, val(ID("x")), val(ID("y")))->hash())); + CHECK(range(val(ID("x")), val(ID("y")), val(ID("z")))->hash() == range(val(ID("x")), val(ID("y")), val(ID("z")))->hash()); + CHECK(!(range(val(ID("x")), val(ID("x")), val(ID("z")))->hash() == range(val(ID("x")), val(ID("y")), val(ID("z")))->hash())); + CHECK(!(range(val(ID("x")), val(ID("y")), val(ID("x")))->hash() == range(val(ID("x")), val(ID("y")), val(ID("z")))->hash())); + CHECK(!(range(val(ID("y")), val(ID("y")), val(ID("z")))->hash() == range(val(ID("x")), val(ID("y")), val(ID("z")))->hash())); + CHECK( (cspmul(val(NUM(1)), val(ID("x"))).hash() == cspmul(val(NUM(1)), val(ID("x"))).hash())); + CHECK(!(cspmul(val(NUM(1)), val(ID("x"))).hash() == cspmul(val(NUM(2)), val(ID("x"))).hash())); + CHECK(!(cspmul(val(NUM(1)), val(ID("y"))).hash() == cspmul(val(NUM(1)), val(ID("x"))).hash())); + CHECK(!(cspmul(val(NUM(1))).hash() == cspmul(val(NUM(1)), val(ID("x"))).hash())); + auto mt = [](int i) { return cspmul(val(NUM(i)), var("x")); }; + CHECK( (cspadd(mt(1), mt(2), mt(3)).hash() == cspadd(mt(1), mt(2), mt(3)).hash())); + CHECK(!(cspadd(mt(2), mt(2), mt(3)).hash() == cspadd(mt(1), mt(2), mt(3)).hash())); + CHECK(!(cspadd(mt(1), mt(3), mt(3)).hash() == cspadd(mt(1), mt(2), mt(3)).hash())); + CHECK(!(cspadd(mt(1), mt(2), mt(4)).hash() == cspadd(mt(1), mt(2), mt(3)).hash())); + auto at = [&mt](int i) { return cspadd(mt(i), mt(i+1)); }; + CHECK( (csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + CHECK(!(csplit(at(2), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + CHECK(!(csplit(at(1), Relation::LEQ, at(3), Relation::LEQ, at(3))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + CHECK(!(csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(4))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + CHECK(!(csplit(at(1), Relation::NEQ, at(2), Relation::LEQ, at(3))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + CHECK(!(csplit(at(1), Relation::LEQ, at(2), Relation::NEQ, at(3))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + CHECK(!(csplit(at(1), Relation::NEQ, at(2), Relation::LEQ, at(3))->hash() == csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3))->hash())); + } + + SECTION("equal") { + REQUIRE(is_value_equal_to(pred(NAF::POS, val(ID("x"))), pred(NAF::POS, val(ID("x"))))); + REQUIRE(!is_value_equal_to(pred(NAF::POS, val(ID("x"))), pred(NAF::NOT, val(ID("x"))))); + REQUIRE(!is_value_equal_to(pred(NAF::POS, val(ID("x"))), pred(NAF::POS, val(ID("y"))))); + REQUIRE(is_value_equal_to(rel(Relation::EQ, val(ID("x")), val(ID("x"))), rel(Relation::EQ, val(ID("x")), val(ID("x"))))); + REQUIRE(!is_value_equal_to(rel(Relation::EQ, val(ID("x")), val(ID("x"))), rel(Relation::LT, val(ID("x")), val(ID("x"))))); + REQUIRE(!is_value_equal_to(rel(Relation::EQ, val(ID("x")), val(ID("x"))), rel(Relation::EQ, val(ID("y")), val(ID("x"))))); + REQUIRE(!is_value_equal_to(rel(Relation::EQ, val(ID("x")), val(ID("x"))), rel(Relation::EQ, val(ID("x")), val(ID("y"))))); + REQUIRE(is_value_equal_to(range(val(ID("x")), val(ID("y")), val(ID("z"))), range(val(ID("x")), val(ID("y")), val(ID("z"))))); + REQUIRE(!is_value_equal_to(range(val(ID("x")), val(ID("x")), val(ID("z"))), range(val(ID("x")), val(ID("y")), val(ID("z"))))); + REQUIRE(!is_value_equal_to(range(val(ID("x")), val(ID("y")), val(ID("x"))), range(val(ID("x")), val(ID("y")), val(ID("z"))))); + REQUIRE(!is_value_equal_to(range(val(ID("y")), val(ID("y")), val(ID("z"))), range(val(ID("x")), val(ID("y")), val(ID("z"))))); + REQUIRE( (cspmul(val(NUM(1)), val(ID("x"))) == cspmul(val(NUM(1)), val(ID("x"))))); + REQUIRE(!(cspmul(val(NUM(1)), val(ID("x"))) == cspmul(val(NUM(2)), val(ID("x"))))); + REQUIRE(!(cspmul(val(NUM(1)), val(ID("y"))) == cspmul(val(NUM(1)), val(ID("x"))))); + REQUIRE(!(cspmul(val(NUM(1))) == cspmul(val(NUM(1)), val(ID("x"))))); + auto mt = [](int i) { return cspmul(val(NUM(i)), var("x")); }; + REQUIRE( (cspadd(mt(1), mt(2), mt(3)) == cspadd(mt(1), mt(2), mt(3)))); + REQUIRE(!(cspadd(mt(2), mt(2), mt(3)) == cspadd(mt(1), mt(2), mt(3)))); + REQUIRE(!(cspadd(mt(1), mt(3), mt(3)) == cspadd(mt(1), mt(2), mt(3)))); + REQUIRE(!(cspadd(mt(1), mt(2), mt(4)) == cspadd(mt(1), mt(2), mt(3)))); + auto at = [&mt](int i) { return cspadd(mt(i), mt(i+1)); }; + REQUIRE( (*csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + REQUIRE(!(*csplit(at(2), Relation::LEQ, at(2), Relation::LEQ, at(3)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + REQUIRE(!(*csplit(at(1), Relation::LEQ, at(3), Relation::LEQ, at(3)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + REQUIRE(!(*csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(4)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + REQUIRE(!(*csplit(at(1), Relation::NEQ, at(2), Relation::LEQ, at(3)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + REQUIRE(!(*csplit(at(1), Relation::LEQ, at(2), Relation::NEQ, at(3)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + REQUIRE(!(*csplit(at(1), Relation::NEQ, at(2), Relation::LEQ, at(3)) == *csplit(at(1), Relation::LEQ, at(2), Relation::LEQ, at(3)))); + } + + SECTION("unpool") { + REQUIRE("[x,y,z]" == to_string(pred(NAF::POS, pool(val(ID("x")), val(ID("y")), val(ID("z"))))->unpool(true))); + REQUIRE("[not x,not y,not z]" == to_string(pred(NAF::NOT, pool(val(ID("x")), val(ID("y")), val(ID("z"))))->unpool(true))); + REQUIRE("[a!=x,a!=y,b!=x,b!=y]" == to_string(rel(Relation::NEQ, pool(val(ID("a")), val(ID("b"))), pool(val(ID("x")), val(ID("y"))))->unpool(true))); + REQUIRE( + "[1$*$x$+1$*$y$<=23$<=42" + ",2$*$x$+1$*$y$<=23$<=42" + ",1$*$y$+1$*$y$<=23$<=42" + ",2$*$y$+1$*$y$<=23$<=42" + ",1$*$x$+1$*$y$<=23$<=43" + ",2$*$x$+1$*$y$<=23$<=43" + ",1$*$y$+1$*$y$<=23$<=43" + ",2$*$y$+1$*$y$<=23$<=43" + "]" == to_string(csplit( + cspadd( + cspmul(pool(val(NUM(1)), val(NUM(2))), pool(val(ID("x")), val(ID("y")))), + cspmul(val(NUM(1)), val(ID("y")))), + Relation::LEQ, + cspadd(cspmul(val(ID("23")))), + Relation::LEQ, + cspadd(cspmul(pool(val(ID("42")), val(NUM(43))))))->unpool(true))); + } + + SECTION("rewrite") { + REQUIRE("p(3)" == to_string(rewrite(pred(NAF::POS, fun("p", binop(BinOp::ADD, val(NUM(1)), val(NUM(2)))))))); + REQUIRE("3>7" == to_string(rewrite(rel(Relation::GT, binop(BinOp::ADD, val(NUM(1)), val(NUM(2))), binop(BinOp::ADD, val(NUM(3)), val(NUM(4))))))); + REQUIRE("3$*$5$+4$*$y$<=42" == + to_string(rewrite(csplit( + cspadd( + cspmul(binop(BinOp::ADD, val(NUM(1)), val(NUM(2))), binop(BinOp::ADD, val(NUM(2)), val(NUM(3)))), + cspmul(binop(BinOp::ADD, val(NUM(1)), val(NUM(3))), val(ID("y")))), + Relation::LEQ, + cspadd(cspmul(binop(BinOp::MUL, val(NUM(6)), val(NUM(7))))))))); + } + +} + +} } } // namespace Test Input Gringo + diff --git a/libgringo/tests/input/nongroundgrammar.cc b/libgringo/tests/input/nongroundgrammar.cc new file mode 100644 index 0000000..4cbefad --- /dev/null +++ b/libgringo/tests/input/nongroundgrammar.cc @@ -0,0 +1,1272 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/programbuilder.hh" +#include "input/nongroundgrammar/grammar.hh" +#include "gringo/symbol.hh" +#include "tests/tests.hh" + +#include +#include + +namespace Gringo { namespace Input { namespace Test { + +namespace { + +// {{{ declaration of TestNongroundProgramBuilder + +class TestNongroundProgramBuilder : public INongroundProgramBuilder { +public: + + // {{{ terms + virtual TermUid term(Location const &loc, Symbol val) override; + virtual TermUid term(Location const &loc, String name) override; + virtual TermUid term(Location const &loc, UnOp op, TermUid a) override; + virtual TermUid term(Location const &loc, UnOp op, TermVecUid a) override; + virtual TermUid term(Location const &loc, BinOp op, TermUid a, TermUid b) override; + virtual TermUid term(Location const &loc, TermUid a, TermUid b) override; + virtual TermUid term(Location const &loc, String name, TermVecVecUid b, bool lua) override; + virtual TermUid term(Location const &loc, TermVecUid args, bool forceTuple) override; + virtual TermUid pool(Location const &loc, TermVecUid args) override; + // }}} + // {{{ csp + virtual CSPMulTermUid cspmulterm(Location const &loc, TermUid coe, TermUid var) override; + virtual CSPMulTermUid cspmulterm(Location const &loc, TermUid coe) override; + virtual CSPAddTermUid cspaddterm(Location const &loc, CSPAddTermUid a, CSPMulTermUid b, bool add) override; + virtual CSPAddTermUid cspaddterm(Location const &loc, CSPMulTermUid a) override; + virtual LitUid csplit(CSPLitUid a) override; + virtual CSPLitUid csplit(Location const &loc, CSPLitUid a, Relation rel, CSPAddTermUid b) override; + virtual CSPLitUid csplit(Location const &loc, CSPAddTermUid a, Relation rel, CSPAddTermUid b) override; + // }}} + // {{{ id vectors + virtual IdVecUid idvec() override; + virtual IdVecUid idvec(IdVecUid uid, Location const &loc, String id) override; + // }}} + // {{{ term vectors + virtual TermVecUid termvec() override; + virtual TermVecUid termvec(TermVecUid uid, TermUid term) override; + // }}} + // {{{ term vector vectors + virtual TermVecVecUid termvecvec() override; + virtual TermVecVecUid termvecvec(TermVecVecUid uid, TermVecUid termvecUid) override; + // }}} + // {{{ literals + virtual LitUid boollit(Location const &loc, bool type) override; + virtual LitUid predlit(Location const &loc, NAF naf, TermUid termUid) override; + virtual LitUid rellit(Location const &loc, Relation rel, TermUid termUidLeft, TermUid termUidRight) override; + // }}} + // {{{ literal vectors + virtual LitVecUid litvec() override; + virtual LitVecUid litvec(LitVecUid uid, LitUid literalUid) override; + // }}} + // {{{ count aggregate elements (body/head) + virtual CondLitVecUid condlitvec() override; + virtual CondLitVecUid condlitvec(CondLitVecUid uid, LitUid lit, LitVecUid litvec) override; + // }}} + // {{{ body aggregate elements + virtual BdAggrElemVecUid bodyaggrelemvec() override; + virtual BdAggrElemVecUid bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) override; + // }}} + // {{{ head aggregate elements + virtual HdAggrElemVecUid headaggrelemvec() override; + virtual HdAggrElemVecUid headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid lit, LitVecUid litvec) override; + // }}} + // {{{ bounds + virtual BoundVecUid boundvec() override; + virtual BoundVecUid boundvec(BoundVecUid uid, Relation rel, TermUid term) override; + // }}} + // {{{ heads + virtual HdLitUid headlit(LitUid lit) override; + virtual HdLitUid headaggr(Location const &loc, TheoryAtomUid atom) override; + virtual HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, HdAggrElemVecUid headaggrelemvec) override; + virtual HdLitUid headaggr(Location const &loc, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid headaggrelemvec) override; + virtual HdLitUid disjunction(Location const &loc, CondLitVecUid condlitvec) override; + // }}} + // {{{ bodies + virtual BdLitVecUid body() override; + virtual BdLitVecUid bodylit(BdLitVecUid body, LitUid bodylit) override; + virtual BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, TheoryAtomUid atom) override; + virtual BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) override; + virtual BdLitVecUid bodyaggr(BdLitVecUid body, Location const &loc, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid bodyaggrelemvec) override; + virtual BdLitVecUid conjunction(BdLitVecUid body, Location const &loc, LitUid head, LitVecUid litvec) override; + virtual BdLitVecUid disjoint(BdLitVecUid body, Location const &loc, NAF naf, CSPElemVecUid elem) override; + // }}} + // {{{ csp constraint elements + virtual CSPElemVecUid cspelemvec() override; + virtual CSPElemVecUid cspelemvec(CSPElemVecUid uid, Location const &loc, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) override; + // }}} + // {{{ statements + virtual void rule(Location const &loc, HdLitUid head) override; + virtual void rule(Location const &loc, HdLitUid head, BdLitVecUid body) override; + virtual void define(Location const &loc, String name, TermUid value, bool defaultDef, Logger &log) override; + virtual void optimize(Location const &loc, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) override; + virtual void showsig(Location const &loc, Sig sig, bool csp) override; + virtual void show(Location const &loc, TermUid t, BdLitVecUid body, bool csp) override; + virtual void python(Location const &loc, String code) override; + virtual void lua(Location const &loc, String code) override; + virtual void block(Location const &loc, String name, IdVecUid args) override; + virtual void external(Location const &loc, TermUid head, BdLitVecUid body) override; + virtual void edge(Location const &loc, TermVecVecUid edges, BdLitVecUid body) override; + virtual void heuristic(Location const &loc, TermUid termUid, BdLitVecUid body, TermUid a, TermUid b, TermUid mod) override; + virtual void project(Location const &loc, TermUid termUid, BdLitVecUid body) override; + virtual void project(Location const &loc, Sig sig) override; + // }}} + // {{{ theory atoms + virtual TheoryTermUid theorytermset(Location const &loc, TheoryOptermVecUid args) override; + virtual TheoryTermUid theoryoptermlist(Location const &loc, TheoryOptermVecUid args) override; + virtual TheoryTermUid theorytermopterm(Location const &loc, TheoryOptermUid opterm) override; + virtual TheoryTermUid theorytermtuple(Location const &loc, TheoryOptermVecUid args) override; + virtual TheoryTermUid theorytermfun(Location const &loc, String name, TheoryOptermVecUid args) override; + virtual TheoryTermUid theorytermvalue(Location const &loc, Symbol val) override; + virtual TheoryTermUid theorytermvar(Location const &loc, String var) override; + + virtual TheoryOptermUid theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) override; + virtual TheoryOptermUid theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) override; + + virtual TheoryOpVecUid theoryops() override; + virtual TheoryOpVecUid theoryops(TheoryOpVecUid ops, String op) override; + + virtual TheoryOptermVecUid theoryopterms() override; + virtual TheoryOptermVecUid theoryopterms(TheoryOptermVecUid opterms, Location const &loc, TheoryOptermUid opterm) override; + virtual TheoryOptermVecUid theoryopterms(Location const &loc, TheoryOptermUid opterm, TheoryOptermVecUid opterms) override; + + virtual TheoryElemVecUid theoryelems() override; + virtual TheoryElemVecUid theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) override; + + virtual TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems) override; + virtual TheoryAtomUid theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &loc, TheoryOptermUid opterm) override; + // }}} + // {{{ theory definitions + + virtual TheoryOpDefUid theoryopdef(Location const &loc, String op, unsigned priority, TheoryOperatorType type) override; + virtual TheoryOpDefVecUid theoryopdefs() override; + virtual TheoryOpDefVecUid theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) override; + + virtual TheoryTermDefUid theorytermdef(Location const &loc, String name, TheoryOpDefVecUid defs, Logger &log) override; + virtual TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type) override; + virtual TheoryAtomDefUid theoryatomdef(Location const &loc, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) override; + + virtual TheoryDefVecUid theorydefs() override; + virtual TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) override; + virtual TheoryDefVecUid theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) override; + + virtual void theorydef(Location const &loc, String name, TheoryDefVecUid defs, Logger &log) override; + + // }}} + + std::string toString(); + + virtual ~TestNongroundProgramBuilder(); + +private: + // {{{ typedefs + using StringVec = std::vector; + using StringVecVec = std::vector; + using StringPair = std::pair; + using StringPairVec = std::vector; + using TermUidVec = std::vector; + using TermVecUidVec = std::vector; + using LitUidVec = std::vector; + + using IdVecs = Indexed; + using Terms = Indexed; + using TermVecs = Indexed; + using TermVecVecs = Indexed; + using Lits = Indexed; + using LitVecs = Indexed; + using BodyAggrElemVecs = Indexed; + using CondLitVecs = Indexed; + using HeadAggrElemVecs = Indexed; + using Bodies = Indexed; + using CSPElems = Indexed; + using Heads = Indexed; + using CSPAddTerms = Indexed; + using CSPMulTerms = Indexed; + using CSPLits = Indexed; + using Bounds = Indexed; + using Statements = std::vector; + + using TheoryOps = Indexed; + using TheoryTerms = Indexed; + using TheoryOpterms = Indexed; + using TheoryOptermVecs = Indexed; + using TheoryElemVecs = Indexed; + using TheoryAtoms = Indexed; + + using TheoryOpDefs = Indexed; + using TheoryOpDefVecs = Indexed; + using TheoryTermDefs = Indexed; + using TheoryAtomDefs = Indexed; + using TheoryDefVecs = Indexed; + + // }}} + // {{{ auxiliary functions + std::string str(); + void print(StringVec const &vec, char const *sep); + void print(StringVecVec const &vec); + void print(AggregateFunction fun, BoundVecUid boundvecuid, StringVec const &elems); + void print(NAF naf); + // }}} + // {{{ member variables + IdVecs idvecs_; + Terms terms_; + TermVecs termvecs_; + TermVecVecs termvecvecs_; + Lits lits_; + LitVecs litvecs_; + BodyAggrElemVecs bodyaggrelemvecs_; + CondLitVecs condlitvecs_; + HeadAggrElemVecs headaggrelemvecs_; + Bodies bodies_; + Heads heads_; + CSPAddTerms cspaddterms_; + CSPMulTerms cspmulterms_; + CSPLits csplits_; + CSPElems cspelems_; + Bounds bounds_; + Statements statements_; + std::stringstream current_; + + TheoryOps theoryOps_; + TheoryTerms theoryTerms_; + TheoryOpterms theoryOpterms_; + TheoryOptermVecs theoryOptermVecs_; + TheoryElemVecs theoryElemVecs_; + TheoryAtoms theoryAtoms_; + + TheoryOpDefs theoryOpDefs_; + TheoryOpDefVecs theoryOpDefVecs_; + TheoryTermDefs theoryTermDefs_; + TheoryAtomDefs theoryAtomDefs_; + TheoryDefVecs theoryDefVecs_; + // }}} +}; + +// }}} +// {{{ definition of TestNongroundProgramBuilder + +// {{{ id vectors + +IdVecUid TestNongroundProgramBuilder::idvec() { + return idvecs_.emplace(); +} + +IdVecUid TestNongroundProgramBuilder::idvec(IdVecUid uid, Location const &, String id) { + idvecs_[uid].emplace_back(id.c_str()); + return uid; +} + +// }}} +// {{{ terms + +TermUid TestNongroundProgramBuilder::term(Location const &, Symbol val) { + current_ << val; + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, String name) { + current_ << name; + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, UnOp op, TermUid a) { + if(op == UnOp::ABS) { current_ << "|"; } + else { current_ << op; } + current_ << terms_.erase(a) << (op == UnOp::ABS ? "|" : ""); + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, UnOp op, TermVecUid a) { + auto v = termvecs_.erase(a); + if(op == UnOp::ABS) { current_ << "|"; } + else { current_ << op << (v.size() > 1 ? "(" : ""); } + print(v, ";"); + if(op == UnOp::ABS) { current_ << "|"; } + else if (v.size() > 1) { current_ << ")"; } + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, BinOp op, TermUid a, TermUid b) { + current_ << "(" << terms_.erase(a) << op << terms_.erase(b) << ")"; + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, TermUid a, TermUid b) { + current_ << "(" << terms_.erase(a) << ".." << terms_.erase(b) << ")"; + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, String name, TermVecVecUid a, bool lua) { + assert(name != ""); + assert(!termvecvecs_[a].empty()); + bool nempty = lua || termvecvecs_[a].size() > 1 || !termvecvecs_[a].front().empty(); + if (lua) { current_ << "@"; } + current_ << name; + if (nempty) { current_ << "("; } + print(termvecvecs_.erase(a)); + if (nempty) { current_ << ")"; } + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::term(Location const &, TermVecUid args, bool forceTuple) { + current_ << "("; + print(termvecs_.erase(args), ","); + if (forceTuple) { current_ << ","; } + current_ << ")"; + return terms_.emplace(str()); +} + +TermUid TestNongroundProgramBuilder::pool(Location const &, TermVecUid args) { + current_ << "("; + print(termvecs_.erase(args), ";"); + current_ << ")"; + return terms_.emplace(str()); +} + +// }}} +// {{{ csp +CSPMulTermUid TestNongroundProgramBuilder::cspmulterm(Location const &, TermUid coe, TermUid var) { + current_ << terms_.erase(coe) << "$*$" << terms_.erase(var); + return cspmulterms_.emplace(str()); +} +CSPMulTermUid TestNongroundProgramBuilder::cspmulterm(Location const &, TermUid coe) { + current_ << terms_.erase(coe); + return cspmulterms_.emplace(str()); +} +CSPAddTermUid TestNongroundProgramBuilder::cspaddterm(Location const &, CSPAddTermUid a, CSPMulTermUid b, bool add) { + cspaddterms_[a] += (add ? "$+" : "$-") + cspmulterms_.erase(b); + return a; +} +CSPAddTermUid TestNongroundProgramBuilder::cspaddterm(Location const &, CSPMulTermUid a) { + current_ << cspmulterms_.erase(a); + return cspaddterms_.emplace(str()); +} +LitUid TestNongroundProgramBuilder::csplit(CSPLitUid a) { + return lits_.emplace(csplits_.erase(a)); +} +CSPLitUid TestNongroundProgramBuilder::csplit(Location const &, CSPLitUid a, Relation rel, CSPAddTermUid b) { + csplits_[a] += "$" + IO::to_string(rel) + cspaddterms_.erase(b); + return a; +} +CSPLitUid TestNongroundProgramBuilder::csplit(Location const &, CSPAddTermUid a, Relation rel, CSPAddTermUid b) { + current_ << cspaddterms_.erase(a) << "$" << rel << cspaddterms_.erase(b); + return csplits_.emplace(str()); +} +// }}} +// {{{ term vectors + +TermVecUid TestNongroundProgramBuilder::termvec() { + return termvecs_.emplace(); +} + +TermVecUid TestNongroundProgramBuilder::termvec(TermVecUid uid, TermUid term) { + termvecs_[uid].emplace_back(terms_.erase(term)); + return uid; +} + +// }}} +// {{{ term vector vectors + +TermVecVecUid TestNongroundProgramBuilder::termvecvec() { + return termvecvecs_.emplace(); +} + +TermVecVecUid TestNongroundProgramBuilder::termvecvec(TermVecVecUid uid, TermVecUid termvecUid) { + termvecvecs_[uid].push_back(termvecs_.erase(termvecUid)); + return uid; +} + +// }}} +// {{{ literals + +LitUid TestNongroundProgramBuilder::boollit(Location const &, bool type) { + return lits_.emplace(type ? "#true" : "#false"); +} + +LitUid TestNongroundProgramBuilder::predlit(Location const &, NAF naf, TermUid termUid) { + print(naf); + current_ << terms_.erase(termUid); + return lits_.emplace(str()); +} + +LitUid TestNongroundProgramBuilder::rellit(Location const &, Relation rel, TermUid termUidLeft, TermUid termUidRight) { + current_ << terms_.erase(termUidLeft) << rel << terms_.erase(termUidRight); + return lits_.emplace(str()); +} + +// }}} +// {{{ literal vectors + +LitVecUid TestNongroundProgramBuilder::litvec() { + return litvecs_.emplace(); +} + +LitVecUid TestNongroundProgramBuilder::litvec(LitVecUid uid, LitUid literalUid) { + litvecs_[uid].emplace_back(lits_.erase(literalUid)); + return uid; +} + +// }}} +// {{{ count aggregate elements (body/head) + +CondLitVecUid TestNongroundProgramBuilder::condlitvec() { + return condlitvecs_.emplace(); +} + +CondLitVecUid TestNongroundProgramBuilder::condlitvec(CondLitVecUid uid, LitUid lit, LitVecUid litvec) { + current_ << lits_.erase(lit); + current_ << ":"; + print(litvecs_.erase(litvec), ","); + condlitvecs_[uid].emplace_back(str()); + return uid; +} + +// }}} +// {{{ body aggregate elements + +BdAggrElemVecUid TestNongroundProgramBuilder::bodyaggrelemvec() { + return bodyaggrelemvecs_.emplace(); +} + +BdAggrElemVecUid TestNongroundProgramBuilder::bodyaggrelemvec(BdAggrElemVecUid uid, TermVecUid termvec, LitVecUid litvec) { + print(termvecs_.erase(termvec), ","); + current_ << ":"; + print(litvecs_.erase(litvec), ","); + bodyaggrelemvecs_[uid].emplace_back(str()); + return uid; +} + +// }}} +// {{{ head aggregate elements + +HdAggrElemVecUid TestNongroundProgramBuilder::headaggrelemvec() { + return headaggrelemvecs_.emplace(); +} + +HdAggrElemVecUid TestNongroundProgramBuilder::headaggrelemvec(HdAggrElemVecUid uid, TermVecUid termvec, LitUid lit, LitVecUid litvec) { + print(termvecs_.erase(termvec), ","); + current_ << ":" << lits_.erase(lit) << ":"; + print(litvecs_.erase(litvec), ","); + headaggrelemvecs_[uid].emplace_back(str()); + return uid; +} + +// }}} +// {{{ bounds + +BoundVecUid TestNongroundProgramBuilder::boundvec() { + return bounds_.emplace(); +} + +BoundVecUid TestNongroundProgramBuilder::boundvec(BoundVecUid uid, Relation rel, TermUid term) { + std::stringstream ss; + current_ << terms_.erase(term); + ss << rel << current_.str(); + current_ << inv(rel); + bounds_[uid].emplace_back(str(), ss.str()); + return uid; +} + +// }}} +// {{{ heads + +HdLitUid TestNongroundProgramBuilder::headlit(LitUid lit) { + return heads_.emplace(lits_.erase(lit)); +} + +HdLitUid TestNongroundProgramBuilder::headaggr(Location const &, TheoryAtomUid atom) { + return heads_.emplace(theoryAtoms_.erase(atom)); +} + +HdLitUid TestNongroundProgramBuilder::headaggr(Location const &, AggregateFunction fun, BoundVecUid boundvecuid, HdAggrElemVecUid headaggrelemvec) { + print(fun, boundvecuid, headaggrelemvecs_.erase(headaggrelemvec)); + return heads_.emplace(str()); +} + +HdLitUid TestNongroundProgramBuilder::headaggr(Location const &, AggregateFunction fun, BoundVecUid boundvecuid, CondLitVecUid headaggrelemvec) { + print(fun, boundvecuid, condlitvecs_.erase(headaggrelemvec)); + return heads_.emplace(str()); +} + +HdLitUid TestNongroundProgramBuilder::disjunction(Location const &, CondLitVecUid condlitvec) { + print(condlitvecs_.erase(condlitvec), ";"); + return heads_.emplace(str()); +} + +// }}} +// {{{ bodies + +BdLitVecUid TestNongroundProgramBuilder::body() { + return bodies_.emplace(); +} + +BdLitVecUid TestNongroundProgramBuilder::bodylit(BdLitVecUid uid, LitUid lit) { + bodies_[uid].emplace_back(lits_.erase(lit)); + return uid; +} + +BdLitVecUid TestNongroundProgramBuilder::bodyaggr(BdLitVecUid body, Location const &, NAF naf, TheoryAtomUid atom) { + print(naf); + current_ << theoryAtoms_.erase(atom); + bodies_[body].emplace_back(str()); + return body; +} + +BdLitVecUid TestNongroundProgramBuilder::bodyaggr(BdLitVecUid uid, Location const &, NAF naf, AggregateFunction fun, BoundVecUid bounds, BdAggrElemVecUid bodyaggrelemvec) { + print(naf); + print(fun, bounds, bodyaggrelemvecs_.erase(bodyaggrelemvec)); + bodies_[uid].emplace_back(str()); + return uid; +} + +BdLitVecUid TestNongroundProgramBuilder::bodyaggr(BdLitVecUid uid, Location const &, NAF naf, AggregateFunction fun, BoundVecUid bounds, CondLitVecUid bodyaggrelemvec) { + print(naf); + print(fun, bounds, condlitvecs_.erase(bodyaggrelemvec)); + bodies_[uid].emplace_back(str()); + return uid; +} + +BdLitVecUid TestNongroundProgramBuilder::conjunction(BdLitVecUid uid, Location const &, LitUid head, LitVecUid litvec) { + current_ << lits_.erase(head) << ":"; + print(litvecs_.erase(litvec), ","); + bodies_[uid].emplace_back(str()); + return uid; +} + +BdLitVecUid TestNongroundProgramBuilder::disjoint(BdLitVecUid body, Location const &, NAF naf, CSPElemVecUid elem) { + current_ << naf << "#disjoint{"; + print(cspelems_.erase(elem), ","); + current_ << "}"; + bodies_[body].emplace_back(str()); + return body; +} + +// }}} +// {{{ csp constraint elements + +CSPElemVecUid TestNongroundProgramBuilder::cspelemvec() { + return cspelems_.emplace(); +} + +CSPElemVecUid TestNongroundProgramBuilder::cspelemvec(CSPElemVecUid uid, Location const &, TermVecUid termvec, CSPAddTermUid addterm, LitVecUid litvec) { + print(termvecs_.erase(termvec), ","); + current_ << ":" << cspaddterms_.erase(addterm) << ":"; + print(litvecs_.erase(litvec), ","); + cspelems_[uid].emplace_back(str()); + return uid; +} + +// }}} +// {{{ statements + +void TestNongroundProgramBuilder::rule(Location const &, HdLitUid head) { + current_ << heads_.erase(head) << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::rule(Location const &, HdLitUid head, BdLitVecUid bodyuid) { + current_ << heads_.erase(head); + StringVec body(bodies_.erase(bodyuid)); + if (!body.empty()) { + current_ << ":-"; + print(body, ";"); + } + current_ << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::define(Location const &, String name, TermUid value, bool, Logger &) { + current_ << "#const " << name << "=" << terms_.erase(value) << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::optimize(Location const &, TermUid weight, TermUid priority, TermVecUid cond, BdLitVecUid body) { + current_ << ":~"; + StringVec bd(bodies_.erase(body)); + print(bd, ";"); + current_ << ".[" << terms_.erase(weight) << "@" << terms_.erase(priority); + StringVec cd(termvecs_.erase(cond)); + if (!cd.empty()) { + current_ << ","; + print(cd, ","); + } + current_ << "]"; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::showsig(Location const &, Sig sig, bool csp) { + current_ << "#showsig " << (csp ? "$" : "") << sig << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::show(Location const &, TermUid t, BdLitVecUid bodyuid, bool csp) { + current_ << "#show " << (csp ? "$" : "") << terms_.erase(t); + StringVec body(bodies_.erase(bodyuid)); + if (!body.empty()) { + current_ << ":"; + print(body, ";"); + } + current_ << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::python(Location const &, String code) { + current_ << code << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::lua(Location const &, String code) { + current_ << code << "."; + statements_.emplace_back(str()); +} +void TestNongroundProgramBuilder::block(Location const &, String name, IdVecUid args) { + current_ << "#program " << name << "("; + print(idvecs_.erase(args), ","); + current_ << ")."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::external(Location const &, TermUid head, BdLitVecUid bodyuid) { + current_ << "#external " << terms_.erase(head); + StringVec body(bodies_.erase(bodyuid)); + if (!body.empty()) { + current_ << ":"; + print(body, ";"); + } + current_ << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::edge(Location const &, TermVecVecUid edges, BdLitVecUid bodyuid) { + current_ << "#edge("; + print(termvecvecs_.erase(edges)); + current_ << ")"; + StringVec body(bodies_.erase(bodyuid)); + if (!body.empty()) { + current_ << ":"; + print(body, ";"); + } + current_ << "."; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::heuristic(Location const &, TermUid termUid, BdLitVecUid bodyuid, TermUid a, TermUid b, TermUid mod) { + current_ << "#heuristic " << terms_.erase(termUid); + StringVec body(bodies_.erase(bodyuid)); + if (!body.empty()) { + current_ << ":"; + print(body, ";"); + } + current_ << ".[" << terms_.erase(a) << "@" << terms_.erase(b) << "," << terms_.erase(mod) << "]"; + statements_.emplace_back(str()); +} + +void TestNongroundProgramBuilder::project(Location const &, TermUid termUid, BdLitVecUid bodyuid) { + current_ << "#project " << terms_.erase(termUid); + StringVec body(bodies_.erase(bodyuid)); + if (!body.empty()) { + current_ << ":"; + print(body, ";"); + } + current_ << "."; + statements_.emplace_back(str()); + +} + +void TestNongroundProgramBuilder::project(Location const &, Sig sig) { + current_ << "#project " << sig << "."; + statements_.emplace_back(str()); +} + +// }}} +// {{{ theory atoms + +TheoryTermUid TestNongroundProgramBuilder::theorytermset(Location const &, TheoryOptermVecUid args) { + current_ << "{"; + print(theoryOptermVecs_.erase(args), " ; "); + current_ << "}"; + return theoryTerms_.emplace(str()); +} +TheoryTermUid TestNongroundProgramBuilder::theoryoptermlist(Location const &, TheoryOptermVecUid args) { + current_ << "["; + print(theoryOptermVecs_.erase(args), " ; "); + current_ << "]"; + return theoryTerms_.emplace(str()); +} + +TheoryTermUid TestNongroundProgramBuilder::theorytermopterm(Location const &, TheoryOptermUid opterm) { + current_ << "(" << theoryOpterms_.erase(opterm) << ")"; + return theoryTerms_.emplace(str()); +} + +TheoryTermUid TestNongroundProgramBuilder::theorytermtuple(Location const &, TheoryOptermVecUid args) { + current_ << "("; + auto size = theoryOptermVecs_[args].size(); + print(theoryOptermVecs_.erase(args), ","); + if (size == 1) { current_ << ","; } + current_ << ")"; + return theoryTerms_.emplace(str()); +} + +TheoryTermUid TestNongroundProgramBuilder::theorytermfun(Location const &, String name, TheoryOptermVecUid args) { + current_ << name << "("; + print(theoryOptermVecs_.erase(args), ","); + current_ << ")"; + return theoryTerms_.emplace(str()); +} + +TheoryTermUid TestNongroundProgramBuilder::theorytermvalue(Location const &, Symbol val) { + current_ << val; + return theoryTerms_.emplace(str()); +} + +TheoryTermUid TestNongroundProgramBuilder::theorytermvar(Location const &, String var) { + current_ << var; + return theoryTerms_.emplace(str()); +} + +TheoryOptermUid TestNongroundProgramBuilder::theoryopterm(TheoryOpVecUid ops, TheoryTermUid term) { + auto to = theoryOps_.erase(ops); + print(to, " "); + if (!to.empty()) { current_ << " "; } + current_ << theoryTerms_.erase(term); + return theoryOpterms_.emplace(str()); + +} + +TheoryOptermUid TestNongroundProgramBuilder::theoryopterm(TheoryOptermUid opterm, TheoryOpVecUid ops, TheoryTermUid term) { + auto to = theoryOps_.erase(ops); + if (!to.empty()) { current_ << " "; } + print(to, " "); + current_ << " " << theoryTerms_.erase(term); + theoryOpterms_[opterm] += str(); + return opterm; +} + +TheoryOpVecUid TestNongroundProgramBuilder::theoryops() { + return theoryOps_.emplace(); +} + +TheoryOpVecUid TestNongroundProgramBuilder::theoryops(TheoryOpVecUid ops, String op) { + theoryOps_[ops].emplace_back(op.c_str()); + return ops; +} + +TheoryOptermVecUid TestNongroundProgramBuilder::theoryopterms() { + return theoryOptermVecs_.emplace(); +} + +TheoryOptermVecUid TestNongroundProgramBuilder::theoryopterms(TheoryOptermVecUid opterms, Location const &, TheoryOptermUid opterm) { + theoryOptermVecs_[opterms].emplace_back(theoryOpterms_.erase(opterm)); + return opterms; +} + +TheoryOptermVecUid TestNongroundProgramBuilder::theoryopterms(Location const &, TheoryOptermUid opterm, TheoryOptermVecUid opterms) { + theoryOptermVecs_[opterms].emplace(theoryOptermVecs_[opterms].begin(), theoryOpterms_.erase(opterm)); + return opterms; +} + +TheoryElemVecUid TestNongroundProgramBuilder::theoryelems() { + return theoryElemVecs_.emplace(); +} + +TheoryElemVecUid TestNongroundProgramBuilder::theoryelems(TheoryElemVecUid elems, TheoryOptermVecUid opterms, LitVecUid cond) { + print(theoryOptermVecs_.erase(opterms), ","); + current_ << ":"; + print(litvecs_.erase(cond), ","); + theoryElemVecs_[elems].emplace_back(str()); + return elems; +} + +TheoryAtomUid TestNongroundProgramBuilder::theoryatom(TermUid term, TheoryElemVecUid elems) { + current_ << "&" << terms_.erase(term) << "{"; + print(theoryElemVecs_.erase(elems), " ; "); + current_ << "}"; + return theoryAtoms_.emplace(str()); +} + +TheoryAtomUid TestNongroundProgramBuilder::theoryatom(TermUid term, TheoryElemVecUid elems, String op, Location const &, TheoryOptermUid opterm) { + current_ << "&" << terms_.erase(term) << "{"; + print(theoryElemVecs_.erase(elems), " ; "); + current_ << "} " << op << " " << theoryOpterms_.erase(opterm); + return theoryAtoms_.emplace(str()); +} + +// }}} +// {{{ theory definitions + +TheoryOpDefUid TestNongroundProgramBuilder::theoryopdef(Location const &, String op, unsigned priority, TheoryOperatorType type) { + current_ << op << " :" << priority << "," << type; + return theoryOpDefs_.emplace(str()); +} + +TheoryOpDefVecUid TestNongroundProgramBuilder::theoryopdefs() { + return theoryOpDefVecs_.emplace(); +} + +TheoryOpDefVecUid TestNongroundProgramBuilder::theoryopdefs(TheoryOpDefVecUid defs, TheoryOpDefUid def) { + theoryOpDefVecs_[defs].emplace_back(theoryOpDefs_.erase(def)); + return defs; +} + +TheoryTermDefUid TestNongroundProgramBuilder::theorytermdef(Location const &, String name, TheoryOpDefVecUid defs, Logger &) { + current_ << name << "{"; + print(theoryOpDefVecs_.erase(defs), ","); + current_ << "}"; + return theoryTermDefs_.emplace(str()); +} + +TheoryAtomDefUid TestNongroundProgramBuilder::theoryatomdef(Location const &, String name, unsigned arity, String termDef, TheoryAtomType type) { + current_ << "&" << name << "/" << arity << ":" << termDef << "," << type; + return theoryAtomDefs_.emplace(str()); +} + +TheoryAtomDefUid TestNongroundProgramBuilder::theoryatomdef(Location const &, String name, unsigned arity, String termDef, TheoryAtomType type, TheoryOpVecUid ops, String guardDef) { + current_ << "&" << name << "/" << arity << ":" << termDef << ",{"; + print(theoryOps_.erase(ops), ","); + current_ << "}," << guardDef << "," << type; + return theoryAtomDefs_.emplace(str()); +} + +TheoryDefVecUid TestNongroundProgramBuilder::theorydefs() { + return theoryDefVecs_.emplace(); +} + +TheoryDefVecUid TestNongroundProgramBuilder::theorydefs(TheoryDefVecUid defs, TheoryTermDefUid def) { + theoryDefVecs_[defs].emplace_back(theoryTermDefs_.erase(def)); + return defs; +} + +TheoryDefVecUid TestNongroundProgramBuilder::theorydefs(TheoryDefVecUid defs, TheoryAtomDefUid def) { + theoryDefVecs_[defs].emplace_back(theoryAtomDefs_.erase(def)); + return defs; +} + +void TestNongroundProgramBuilder::theorydef(Location const &, String name, TheoryDefVecUid defs, Logger &) { + current_ << "#theory " << name << "{"; + print(theoryDefVecs_.erase(defs), ";"); + current_ << "}."; + statements_.emplace_back(str()); +} + +// }}} +// {{{ auxiliary functions + +void TestNongroundProgramBuilder::print(AggregateFunction fun, BoundVecUid boundvecuid, StringVec const &elems) { + StringPairVec bounds(bounds_.erase(boundvecuid)); + auto it = bounds.begin(), end = bounds.end(); + if (it != end) { current_ << it->first; ++it; } + current_ << fun << "{"; + print(elems, ";"); + current_ << "}"; + for (; it != end; ++it) { current_ << it->second; } +} + +void TestNongroundProgramBuilder::print(NAF naf) { + switch (naf) { + case NAF::NOT: { current_ << "#not "; break; } + case NAF::NOTNOT: { current_ << "#not #not "; break; } + case NAF::POS: { break; } + } +} + +std::string TestNongroundProgramBuilder::str() { + std::string str(current_.str()); + current_.str(""); + return str; +} + +void TestNongroundProgramBuilder::print(StringVec const &vec, char const *sep) { + auto it = vec.begin(), end = vec.end(); + if (it != end) { + current_ << *it++; + for (; it != end; ++it) { current_ << sep << *it; } + } +} + +void TestNongroundProgramBuilder::print(StringVecVec const &vec) { + auto it = vec.begin(), end = vec.end(); + if (it != end) { + print(*it++, ","); + for (; it != end; ++it) { + current_ << ";"; + print(*it, ","); + } + } +} + +// }}} + +std::string TestNongroundProgramBuilder::toString() { + auto it = statements_.begin(), end = statements_.end(); + if (it != end) { + current_ << *it; + for (++it; it != end; ++it) { current_ << '\n' << *it; } + } + statements_.clear(); + return str(); +} + +TestNongroundProgramBuilder::~TestNongroundProgramBuilder() { } + +// }}} + +std::string parse(std::string const &str) { + Gringo::Test::TestGringoModule log; + TestNongroundProgramBuilder pb; + NonGroundParser ngp(pb); + ngp.pushStream("-", std::unique_ptr(new std::stringstream(str)), log); + ngp.parse(log); + return pb.toString(); +} + +} // namespace + +TEST_CASE("input-nongroundprogrambuilder", "[input]") { + + SECTION("term") { + // testing constants + REQUIRE("#program base().\np(x)." == parse("p(x).")); + REQUIRE("#program base().\np(1)." == parse("p(1).")); + REQUIRE("#program base().\np(\"1\")." == parse("p(\"1\").")); + REQUIRE("#program base().\np(#inf)." == parse("p(#inf).")); + REQUIRE("#program base().\np(#sup)." == parse("p(#sup).")); + REQUIRE("#program base().\np(X)." == parse("p(X).")); + REQUIRE("#program base().\np(_)." == parse("p(_).")); + // absolute + REQUIRE("#program base().\np(|1|)." == parse("p(|1|).")); + REQUIRE("#program base().\np(|1;2;3|)." == parse("p(|1;2;3|).")); + // lua function calls + REQUIRE("#program base().\np(@f())." == parse("p(@f()).")); + REQUIRE("#program base().\np(@f(1))." == parse("p(@f(1)).")); + REQUIRE("#program base().\np(@f(1,2))." == parse("p(@f(1,2)).")); + REQUIRE("#program base().\np(@f(1,2,3))." == parse("p(@f(1,2,3)).")); + REQUIRE("#program base().\np(@f(;;;1,2;3))." == parse("p(@f(;;;1,2;3)).")); + // function symbols + REQUIRE("#program base().\np(f)." == parse("p(f()).")); + REQUIRE("#program base().\np(f(1))." == parse("p(f(1)).")); + REQUIRE("#program base().\np(f(1,2))." == parse("p(f(1,2)).")); + REQUIRE("#program base().\np(f(1,2,3))." == parse("p(f(1,2,3)).")); + REQUIRE("#program base().\np(f(;;;1,2;3))." == parse("p(f(;;;1,2;3)).")); + // tuples / parenthesis + REQUIRE("#program base().\np((()))." == parse("p(()).")); + REQUIRE("#program base().\np(((1)))." == parse("p((1)).")); + REQUIRE("#program base().\np(((1,2)))." == parse("p((1,2)).")); + REQUIRE("#program base().\np(((1,2,3)))." == parse("p((1,2,3)).")); + REQUIRE("#program base().\np((();();();(1,2);(3,)))." == parse("p((;;;1,2;3,)).")); + // unary operations + REQUIRE("#program base().\np(-1)." == parse("p(-1).")); + REQUIRE("#program base().\np(~1)." == parse("p(~1).")); + // binary operations + REQUIRE("#program base().\np((1**2))." == parse("p(1**2).")); + REQUIRE("#program base().\np((1\\2))." == parse("p(1\\2).")); + REQUIRE("#program base().\np((1/2))." == parse("p(1/2).")); + REQUIRE("#program base().\np((1*2))." == parse("p(1*2).")); + REQUIRE("#program base().\np((1-2))." == parse("p(1-2).")); + REQUIRE("#program base().\np((1+2))." == parse("p(1+2).")); + REQUIRE("#program base().\np((1&2))." == parse("p(1&2).")); + REQUIRE("#program base().\np((1?2))." == parse("p(1?2).")); + REQUIRE("#program base().\np((1^2))." == parse("p(1^2).")); + REQUIRE("#program base().\np((1..2))." == parse("p(1..2).")); + // precedence + REQUIRE("#program base().\np(((1+2)+((3*4)*(5**(6**7)))))." == parse("p(1+2+3*4*5**6**7).")); + // nesting + REQUIRE("#program base().\np((f(1,(();();();(1,(x..Y));(3)),3)+p(f(1,#sup,3))))." == parse("p(f(1,(;;;1,x..Y;3),3)+p(f(1,#sup,3))).")); + } + + SECTION("atomargs") { + // identifier + REQUIRE("#program base().\np." == parse("p.")); + // identifier LPAREN argvec RPAREN + REQUIRE("#program base().\np." == parse("p().")); + REQUIRE("#program base().\np(1)." == parse("p(1).")); + REQUIRE("#program base().\np(;;;1,2;3,4)." == parse("p(;;;1,2;3,4).")); + // identifier LPAREN MUL RPAREN + REQUIRE("#program base().\np(_)." == parse("p(_).")); + // identifier LPAREN MUL cpredargvec RPAREN + REQUIRE("#program base().\np(_,1)." == parse("p(_,1).")); + REQUIRE("#program base().\np(_,1,2)." == parse("p(_,1,2).")); + REQUIRE("#program base().\np(_,1,2;2,3)." == parse("p(_,1,2;2,3).")); + // identifier LPAREN MUL spredargvec RPAREN + REQUIRE("#program base().\np(_;1)." == parse("p(_;1).")); + REQUIRE("#program base().\np(_;1,2)." == parse("p(_;1,2).")); + REQUIRE("#program base().\np(_;1,2;2,3)." == parse("p(_;1,2;2,3).")); + // identifier LPAREN argvec COMMAMUL MUL RPAREN + REQUIRE("#program base().\np(1,_)." == parse("p(1,_).")); + REQUIRE("#program base().\np(1,2,_)." == parse("p(1,2,_).")); + // identifier LPAREN argvec COMMAMUL MUL cpredargvec RPAREN + REQUIRE("#program base().\np(1,2,_,3,_;_)." == parse("p(1,2,_,3,_;_).")); + REQUIRE("#program base().\np(1,2,_,3,4,_;_)." == parse("p(1,2,_,3,4,_;_).")); + // identifier LPAREN argvec COMMAMUL MUL spredargvec RPAREN + REQUIRE("#program base().\np(1,2,_;3,_;_)." == parse("p(1,2,_;3,_;_).")); + REQUIRE("#program base().\np(1,2,_;3,4,_;_)." == parse("p(1,2,_;3,4,_;_).")); + // identifier LPAREN argvec SEMMUL MUL RPAREN + REQUIRE("#program base().\np(1;_)." == parse("p(1;_).")); + REQUIRE("#program base().\np(1,2;_)." == parse("p(1,2;_).")); + // identifier LPAREN argvec SEMMUL MUL cpredargvec RPAREN + REQUIRE("#program base().\np(1,2;_,3,_;_)." == parse("p(1,2;_,3,_;_).")); + REQUIRE("#program base().\np(1,2;_,3,4,_;_)." == parse("p(1,2;_,3,4,_;_).")); + // identifier LPAREN argvec SEMMUL MUL spredargvec RPAREN + REQUIRE("#program base().\np(1,2;_;3,_;_)." == parse("p(1,2;_;3,_;_).")); + REQUIRE("#program base().\np(1,2;_;3,4,_;_)." == parse("p(1,2;_;3,4,_;_).")); + } + + SECTION("literal") { + // TRUE + REQUIRE("#program base().\n#true." == parse("#true.")); + // FALSE + REQUIRE("#program base().\n#false." == parse("#false.")); + // atom + REQUIRE("#program base().\np." == parse("p.")); + REQUIRE("#program base().\n-p." == parse("-p.")); + // NOT atom + REQUIRE("#program base().\n#not p." == parse("not p.")); + // NOT NOT atom + REQUIRE("#program base().\n#not #not p." == parse("not not p.")); + // term cmp term + REQUIRE("#program base().\n(1+2)!=3." == parse("1+2!=3.")); + } + + SECTION("bdaggr") { + // aggregatefunction + REQUIRE("#program base().\n#false:-#count{}." == parse(":-{}.")); + REQUIRE("#program base().\n#false:-#sum{}." == parse(":-#sum{}.")); + REQUIRE("#program base().\n#false:-#sum+{}." == parse(":-#sum+{}.")); + REQUIRE("#program base().\n#false:-#min{}." == parse(":-#min{}.")); + REQUIRE("#program base().\n#false:-#max{}." == parse(":-#max{}.")); + REQUIRE("#program base().\n#false:-#count{}." == parse(":-#count{}.")); + // LBRACE altbodyaggrelemvec RBRACE + REQUIRE("#program base().\n#false:-#count{p:;p:;p:p;p:p,q}." == parse(":-{p;p:;p:p;p:p,q}.")); + // aggregatefunction LBRACE bodyaggrelemvec RBRACE + REQUIRE("#program base().\n#false:-#count{:;:p;:p,q}." == parse(":-#count{:;:p;:p,q}.")); + REQUIRE("#program base().\n#false:-#count{p:;p,q:}." == parse(":-#count{p;p,q}.")); + REQUIRE("#program base().\n#false:-#count{p:;p,q:}." == parse(":-#count{p:;p,q:}.")); + REQUIRE("#program base().\n#false:-#count{p:q,r,s}." == parse(":-#count{p:q,r,s}.")); + // test lower + REQUIRE("#program base().\n#false:-1<=#count{}." == parse(":-1{}.")); + REQUIRE("#program base().\n#false:-1<#count{}." == parse(":-1<{}.")); + REQUIRE("#program base().\n#false:-1<=#count{}." == parse(":-1<={}.")); + REQUIRE("#program base().\n#false:-1>#count{}." == parse(":-1>{}.")); + REQUIRE("#program base().\n#false:-1>=#count{}." == parse(":-1>={}.")); + REQUIRE("#program base().\n#false:-1=#count{}." == parse(":-1=={}.")); + REQUIRE("#program base().\n#false:-1=#count{}." == parse(":-1={}.")); + // test upper + REQUIRE("#program base().\n#false:-1>=#count{}." == parse(":-{}1.")); + REQUIRE("#program base().\n#false:-1<#count{}." == parse(":-{}>1.")); + REQUIRE("#program base().\n#false:-1<=#count{}." == parse(":-{}>=1.")); + REQUIRE("#program base().\n#false:-1>#count{}." == parse(":-{}<1.")); + REQUIRE("#program base().\n#false:-1>=#count{}." == parse(":-{}<=1.")); + REQUIRE("#program base().\n#false:-1=#count{}." == parse(":-{}==1.")); + REQUIRE("#program base().\n#false:-1=#count{}." == parse(":-{}=1.")); + // test both + REQUIRE("#program base().\n#false:-1<=#count{}<=2." == parse(":-1{}2.")); + REQUIRE("#program base().\n#false:-1<#count{}<2." == parse(":-1<{}<2.")); + } + + SECTION("hdaggr") { + // aggregatefunction + REQUIRE("#program base().\n#count{}." == parse("{}.")); + REQUIRE("#program base().\n#sum{}." == parse("#sum{}.")); + REQUIRE("#program base().\n#sum+{}." == parse("#sum+{}.")); + REQUIRE("#program base().\n#min{}." == parse("#min{}.")); + REQUIRE("#program base().\n#max{}." == parse("#max{}.")); + REQUIRE("#program base().\n#count{}." == parse("#count{}.")); + // LBRACE altheadaggrelemvec RBRACE + REQUIRE("#program base().\n#count{p:;p:;p:p;p:p,q}." == parse("{p;p:;p:p;p:p,q}.")); + // aggregatefunction LBRACE headaggrelemvec RBRACE + REQUIRE("#program base().\n#count{:p:;:q:r;:s:t,u}." == parse("#count{:p;:q:r;:s:t,u}.")); + REQUIRE("#program base().\n#count{p:q:;r,s:t:}." == parse("#count{p:q;r,s:t}.")); + REQUIRE("#program base().\n#count{p:q:;r,s:t:}." == parse("#count{p:q:;r,s:t:}.")); + REQUIRE("#program base().\n#count{p:q:x,y,z;r,s:t:q,w,e}." == parse("#count{p:q:x,y,z;r,s:t:q,w,e}.")); + // test lower + REQUIRE("#program base().\n1<=#count{}." == parse("1{}.")); + REQUIRE("#program base().\n1<#count{}." == parse("1<{}.")); + REQUIRE("#program base().\n1<=#count{}." == parse("1<={}.")); + REQUIRE("#program base().\n1>#count{}." == parse("1>{}.")); + REQUIRE("#program base().\n1>=#count{}." == parse("1>={}.")); + REQUIRE("#program base().\n1=#count{}." == parse("1=={}.")); + REQUIRE("#program base().\n1=#count{}." == parse("1={}.")); + // test upper + REQUIRE("#program base().\n1>=#count{}." == parse("{}1.")); + REQUIRE("#program base().\n1<#count{}." == parse("{}>1.")); + REQUIRE("#program base().\n1<=#count{}." == parse("{}>=1.")); + REQUIRE("#program base().\n1>#count{}." == parse("{}<1.")); + REQUIRE("#program base().\n1>=#count{}." == parse("{}<=1.")); + REQUIRE("#program base().\n1=#count{}." == parse("{}==1.")); + REQUIRE("#program base().\n1=#count{}." == parse("{}=1.")); + // test both + REQUIRE("#program base().\n1<=#count{}<=2." == parse("1{}2.")); + REQUIRE("#program base().\n1<#count{}<2." == parse("1<{}<2.")); + } + + SECTION("conjunction") { + REQUIRE("#program base().\n#false:-a:." == parse(":-a:.")); + REQUIRE("#program base().\n#false:-a:b." == parse(":-a:b.")); + REQUIRE("#program base().\n#false:-a:b,c." == parse(":-a:b,c.")); + REQUIRE("#program base().\n#false:-a:b,c;x." == parse(":-a:b,c;x.")); + } + + SECTION("disjunction") { + // Note: first disjunction element moves to the end (parsing related) + // literal COLON litvec + REQUIRE("#program base().\na." == parse("a.")); + REQUIRE("#program base().\na:b." == parse("a:b.")); + REQUIRE("#program base().\na:b,c." == parse("a:b,c.")); + // literal COMMA disjunctionsep literal optcondition + REQUIRE("#program base().\nb:;c:;a:." == parse("a,b,c.")); + REQUIRE("#program base().\nb:;c:;d:;a:." == parse("a,b;c;d.")); + REQUIRE("#program base().\nb:;c:d,e;a:." == parse("a,b,c:d,e.")); + REQUIRE("#program base().\nb:d,e;c:;a:." == parse("a,b:d,e;c.")); + // literal SEM disjunctionsep literal optcondition + REQUIRE("#program base().\nb:;c:;a:." == parse("a;b,c.")); + REQUIRE("#program base().\nb:;c:;d:;a:." == parse("a;b;c;d.")); + REQUIRE("#program base().\nb:;c:d,e;a:." == parse("a;b,c:d,e.")); + REQUIRE("#program base().\nb:d,e;c:;a:." == parse("a;b:d,e;c.")); + // literal COLON litvec SEM disjunctionsep literal optcondition + REQUIRE("#program base().\nc:;a:." == parse("a;c.")); + REQUIRE("#program base().\nc:;a:x." == parse("a:x;c.")); + REQUIRE("#program base().\nc:;a:x,y." == parse("a:x,y;c.")); + REQUIRE("#program base().\nb:;c:;a:x,y." == parse("a:x,y;b,c.")); + REQUIRE("#program base().\nb:;c:;d:;a:x,y." == parse("a:x,y;b;c;d.")); + REQUIRE("#program base().\nb:;c:d,e;a:x,y." == parse("a:x,y;b,c:d,e.")); + REQUIRE("#program base().\nb:d,e;c:;a:x,y." == parse("a:x,y;b:d,e;c.")); + } + + SECTION("rule") { + // body literal + REQUIRE("#program base().\n#false:-a;x." == parse(":-a,x.")); + REQUIRE("#program base().\n#false:-a;x." == parse(":-a;x.")); + REQUIRE("#program base().\n#false:-a;x." == parse(":-a,x.")); + // body aggregate + REQUIRE("#program base().\n#false:-#count{};#count{}." == parse(":-{},{}.")); + REQUIRE("#program base().\n#false:-#count{};#count{}." == parse(":-{};{}.")); + REQUIRE("#program base().\n#false:-#not #count{};#not #count{}." == parse(":-not{},not{}.")); + REQUIRE("#program base().\n#false:-#not #count{};#not #count{}." == parse(":-not{};not{}.")); + REQUIRE("#program base().\n#false:-#not #not #count{};#not #not #count{}." == parse(":-not not{},not not{}.")); + REQUIRE("#program base().\n#false:-#not #not #count{};#not #not #count{}." == parse(":-not not{};not not{}.")); + REQUIRE("#program base().\n#false:-#not #not nott<=#count{};#not #not nott<=#count{}." == parse(":-not not nott{},not not nott{}.")); + REQUIRE("#program base().\n#false:-#not #not nott<=#count{};#not #not nott<=#count{}." == parse(":-not not nott{};not not nott{}.")); + // conjunction + REQUIRE("#program base().\n#false:-a:;b:." == parse(":-a:;b:.")); + // head literal + REQUIRE("#program base().\na." == parse("a.")); + // head aggregate + REQUIRE("#program base().\n#count{}." == parse("{}.")); + REQUIRE("#program base().\nnott<=#count{}." == parse("nott{}.")); + // disjunction + REQUIRE("#program base().\nb:;a:." == parse("a,b.")); + // rules + REQUIRE("#program base().\na." == parse("a.")); + REQUIRE("#program base().\na:-b." == parse("a:-b.")); + REQUIRE("#program base().\na:-b;c." == parse("a:-b,c.")); + REQUIRE("#program base().\n#false." == parse(":-.")); + REQUIRE("#program base().\n#false:-b." == parse(":-b.")); + REQUIRE("#program base().\n#false:-b;c." == parse(":-b,c.")); + } + + SECTION("define") { + REQUIRE("#program base().\n#const a=10." == parse("#const a=10.")); + } + + SECTION("optimize") { + REQUIRE("#program base().\n:~p(X,Y).[X@Y,a]" == parse(":~ p(X,Y). [X@Y,a]")); + REQUIRE("#program base().\n:~p(X,Y);r;s.[X@0]" == parse(":~ p(X,Y),r,s. [X]")); + REQUIRE("#program base().\n:~p(X,Y);s.[X@Y,a]\n:~q(Y).[Y@f]\n:~.[1@0]" == parse("#minimize { X@Y,a : p(X,Y),s; Y@f : q(Y); 1 }.")); + REQUIRE("#program base()." == parse("#minimize { }.")); + REQUIRE("#program base().\n:~p(X,Y);r.[-X@Y,a]\n:~q(Y).[-Y@f]\n:~.[-2@0]" == parse("#maximize { X@Y,a : p(X,Y), r; Y@f : q(Y); 2 }.")); + REQUIRE("#program base()." == parse("#maximize { }.")); + } + + SECTION("show") { + REQUIRE("#program base().\n#showsig p/1." == parse("#show p/1.")); + REQUIRE("#program base().\n#showsig p/1." == parse("#show p / 1.")); + REQUIRE("#program base().\n#showsig -p/1." == parse("#show -p/1.")); + REQUIRE("#program base().\n#show (-p/-1)." == parse("#show -p/-1.")); + REQUIRE("#program base().\n#show X:p(X);1<=#count{q(X):p(X)}." == parse("#show X:p(X), 1 { q(X):p(X) }.")); + } + + SECTION("include") { +#ifndef _MSC_VER + std::ofstream("/tmp/test_include.lp") << "b.\n"; + REQUIRE("#program base().\na.\nb.\n#program base().\nc.\nd." == parse("a.\n#include \"/tmp/test_include.lp\".\nc.\nd.\n")); +#endif + } + + SECTION("csp") { + REQUIRE("#program base().\n1$<=1$*$x$<=10." == parse("1 $<= $x $<= 10.")); + REQUIRE("#program base().\n1$*$a$<=X$*$x$+8$*$X$<=10:-p(X)." == parse("1 $* $a $<= $x $* X $+ 8 $* $X $<= 10 :- p(X).")); + REQUIRE("#program base().\n#false:-a;b;not #disjoint{a:1$*$a:a,a,b:1$*$b:b}." == parse("#disjoint{a:$a:a,a; b:$b:b} :- a, b.")); + } + + SECTION("edge") { + REQUIRE("#program base().\n#edge(a,b)." == parse("#edge (a, b).")); + REQUIRE("#program base().\n#edge(a,b;e,f)." == parse("#edge (a, b;e,f):.")); + REQUIRE("#program base().\n#edge(a,b;e,f):p;q." == parse("#edge (a, b;e,f):p,q.")); + } + + SECTION("project") { + REQUIRE("#program base().\n#project a/1." == parse("#project a/1.")); + REQUIRE("#program base().\n#project -a/1." == parse("#project -a/1.")); + REQUIRE("#program base().\n#project a." == parse("#project a.")); + REQUIRE("#program base().\n#project a." == parse("#project a:.")); + REQUIRE("#program base().\n#project a:b;c." == parse("#project a:b,c.")); + } + + SECTION("heuristic") { + REQUIRE("#program base().\n#heuristic p:q.[1@2,level]" == parse("#heuristic p : q. [1@2,level]")); + REQUIRE("#program base().\n#heuristic p:q.[1@2,sign]" == parse("#heuristic p : q. [1@2,sign]")); + REQUIRE("#program base().\n#heuristic p:q.[1@2,true]" == parse("#heuristic p : q. [1@2,true]")); + REQUIRE("#program base().\n#heuristic p:q.[1@2,false]" == parse("#heuristic p : q. [1@2,false]")); + REQUIRE("#program base().\n#heuristic p:q.[1@2,factor]" == parse("#heuristic p : q. [1@2,factor]")); + REQUIRE("#program base().\n#heuristic p:q;r.[1@2,init]" == parse("#heuristic p : q,r. [1@2,init]")); + REQUIRE("#program base().\n#heuristic p.[1@0,init]" == parse("#heuristic p:. [1,init]")); + REQUIRE("#program base().\n#heuristic p.[1@0,init]" == parse("#heuristic p. [1,init]")); + } + + SECTION("theory") { + // NOTE: things would be less error prone if : and ; would not be valid theory connectives + REQUIRE("#program base().\n&x{}." == parse("&x { }.")); + REQUIRE("#program base().\n#false:-&x{}." == parse(":-&x { }.")); + REQUIRE("#program base().\n&x{} < 42." == parse("&x { } < 42.")); + REQUIRE("#program base().\n#false:-&x{} < 42." == parse(":-&x { } < 42.")); + REQUIRE("#program base().\n#false:-&x{} < 42 + 17 ^ (- 1)." == parse(":-&x { } < 42+17^(-1).")); + REQUIRE("#program base().\n#false:-&x{} < 42 + 17 ^ - 1." == parse(":-&x { } < 42+17^ -1.")); + REQUIRE("#program base().\n#false:-&x{} < 42 + 17 ^- 1." == parse(":-&x { } < 42+17^-1.")); + REQUIRE("#program base().\n&x{u,v: ; u: ; u: ; : ; :p ; :p,q}." == parse("&x { u,v; u ; u: ; : ; :p; :p,q }.")); + REQUIRE("#program base().\n&x{u: ; u: ; : ; :p ; :p,q}." == parse("&x { u ; u: ; : ; :p; :p,q }.")); + REQUIRE("#program base().\n&x{i(u + v ^ (a +- 3 * b),7 + (1,) *** (2) - () + [a ; b] ? {1 ; 2 ; 3}):}." == parse("&x { i(u+v^(a+- 3 * b),7+(1,)***(2)-()+[a,b]?{1,2,3}) }.")); + } + + SECTION("theoryDefinition") { + REQUIRE("#program base().\n#theory t{}." == parse("#theory t { }.")); + REQUIRE("#program base().\n#theory t{x{}}." == parse("#theory t { x { } }.")); + REQUIRE("#program base().\n#theory t{x{};y{}}." == parse("#theory t { x { }; y{} }.")); + REQUIRE("#program base().\n#theory t{x{++ :42,unary}}." == parse("#theory t { x { ++ : 42, unary } }.")); + REQUIRE("#program base().\n#theory t{x{++ :42,unary,** :21,binary,left,-* :1,binary,right}}." == parse("#theory t { x { ++ : 42, unary; ** : 21, binary, left; -* : 1, binary, right } }.")); + REQUIRE("#program base().\n#theory t{x{};&a/0:x,any}." == parse("#theory t { x{}; &a/0: x, any }.")); + REQUIRE("#program base().\n#theory t{x{};&a/0:x,any;&b/0:x,head;&c/0:x,body;&d/0:x,directive}." == parse("#theory t { x{}; &a/0: x, any; &b/0: x, head; &c/0: x, body; &d/0: x, directive }.")); + REQUIRE("#program base().\n#theory t{x{};&a/0:x,{+,-,++,**},x,any}." == parse("#theory t { x{}; &a/0: x, {+,-, ++, **}, x, any }.")); + } + +} + +} } } // namespace Test Input Gringo + diff --git a/libgringo/tests/input/nongroundlexer.cc b/libgringo/tests/input/nongroundlexer.cc new file mode 100644 index 0000000..ef432ff --- /dev/null +++ b/libgringo/tests/input/nongroundlexer.cc @@ -0,0 +1,91 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/programbuilder.hh" +#include "gringo/input/program.hh" +#include "gringo/output/output.hh" +#include "input/nongroundgrammar/grammar.hh" +#include "gringo/symbol.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" + +namespace Gringo { namespace Input { namespace Test { + +TEST_CASE("input-nongroundlexer", "[input]") { + Gringo::Test::TestGringoModule module; + std::ostringstream oss; + Potassco::TheoryData td; + Output::OutputBase out(td, {}, oss); + Program prg; + Defines defs; + Scripts scripts(module); + NongroundProgramBuilder pb(scripts, prg, out, defs); + NonGroundParser ngp(pb); + std::string in = + "#script (python) #end " + "%*xyz\nxyz\n*%" + "%xyz\n" + "#minimize " + "#minimise " + "#infimum " + "#inf " + ";* " + ";\n * " + "not " + "xyz " + "_xyz " + "__xyz " + "___xyz " + // TODO: check errors too: "# " + ; + ngp.pushStream("-", std::unique_ptr(new std::stringstream(in)), module.logger); + + Location loc("", 0, 0, "", 0, 0); + NonGroundGrammar::parser::semantic_type val; + + REQUIRE(int(NonGroundGrammar::parser::token::PYTHON) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::MINIMIZE) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::MINIMIZE) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::INFIMUM) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::INFIMUM) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::SEM) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::MUL) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::SEM) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::MUL) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::NOT) == ngp.lex(&val, loc)); + REQUIRE(int(NonGroundGrammar::parser::token::IDENTIFIER) == ngp.lex(&val, loc)); + REQUIRE(String("xyz") == String::fromRep(val.str)); + REQUIRE(int(NonGroundGrammar::parser::token::IDENTIFIER) == ngp.lex(&val, loc)); + REQUIRE(String("_xyz") == String::fromRep(val.str)); + REQUIRE(int(NonGroundGrammar::parser::token::IDENTIFIER) == ngp.lex(&val, loc)); + REQUIRE(String("__xyz") == String::fromRep(val.str)); + REQUIRE(int(NonGroundGrammar::parser::token::IDENTIFIER) == ngp.lex(&val, loc)); + REQUIRE(String("___xyz") == String::fromRep(val.str)); + REQUIRE(5 == loc.beginLine); + REQUIRE(23 == loc.beginColumn); + REQUIRE(0 == ngp.lex(&val, loc)); +} + +// }}} + +} } } // namespace Test Input Gringo + diff --git a/libgringo/tests/input/parse_term.cc b/libgringo/tests/input/parse_term.cc new file mode 100644 index 0000000..92ae753 --- /dev/null +++ b/libgringo/tests/input/parse_term.cc @@ -0,0 +1,64 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +#include +#include + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::Test; + +TEST_CASE("input-parse_term", "[input]") { + + SECTION("parse") { + TestGringoModule m; + REQUIRE_THROWS_AS(m.parseValue("a."), std::runtime_error); + REQUIRE(Symbol() == m.parseValue("x+y")); + REQUIRE(NUM(1) == m.parseValue("1")); + REQUIRE(NUM(-1) == m.parseValue("-1")); + REQUIRE(ID("x") == m.parseValue("x")); + REQUIRE(ID("x", true) == m.parseValue("-x")); + REQUIRE(FUN("f", {ID("x")}) == m.parseValue("f(x)")); + REQUIRE(FUN("f", {ID("x")}, true) == m.parseValue("-f(x)")); + REQUIRE(NUM(39) == m.parseValue("7?32")); + REQUIRE(NUM(5) == m.parseValue("7&13")); + REQUIRE(NUM(8) == m.parseValue("13-5")); + REQUIRE(NUM(18) == m.parseValue("13+5")); + REQUIRE(NUM(65) == m.parseValue("13*5")); + REQUIRE(NUM(3) == m.parseValue("13\\5")); + REQUIRE(NUM(2) == m.parseValue("13/5")); + REQUIRE(NUM(371293) == m.parseValue("13**5")); + REQUIRE(NUM(-2) == m.parseValue("~1")); + REQUIRE(FUN("", {}) == m.parseValue("()")); + REQUIRE(FUN("", {NUM(1)}) == m.parseValue("(1,)")); + REQUIRE(FUN("", {NUM(1),NUM(2)}) == m.parseValue("(1,2)")); + REQUIRE(NUM(2) == m.parseValue("|-2|")); + REQUIRE(STR("hallo") == m.parseValue("\"hallo\"")); + REQUIRE(INF() == m.parseValue("#inf")); + REQUIRE(SUP() == m.parseValue("#sup")); + } + +} + +} } } // namespace Test Input Gringo + diff --git a/libgringo/tests/input/program.cc b/libgringo/tests/input/program.cc new file mode 100644 index 0000000..59cff22 --- /dev/null +++ b/libgringo/tests/input/program.cc @@ -0,0 +1,230 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/programbuilder.hh" +#include "gringo/input/program.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::IO; +using namespace Gringo::Test; + +// {{{ definition of auxiliary functions + +namespace { + +struct Grounder { + Grounder() + : out(td, {}, oss) + , scripts(module) + , pb( scripts, p, out, d ) + , ngp( pb ) + { } + Gringo::Test::TestGringoModule module; + Potassco::TheoryData td; + std::ostringstream oss; + Output::OutputBase out; + Scripts scripts; + Program p; + Defines d; + NongroundProgramBuilder pb; + NonGroundParser ngp; + +}; + +std::unique_ptr parse(std::string const &str) { + std::unique_ptr g = gringo_make_unique(); + g->ngp.pushStream("-", gringo_make_unique(str), g->module); + g->ngp.parse(g->module); + return g; +} + +std::string rewrite(std::unique_ptr g) { + g->d.init(g->module); + g->p.rewrite(g->d, g->module); + auto str(to_string(g->p)); + str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); + replace_all(str, ";[#inc_base]", ""); + replace_all(str, ":-[#inc_base].", "."); + replace_all(str, ":-[#inc_base],", ":-"); + replace_all(str, ":-[#inc_base];", ":-"); + replace_all(str, "; ", ";"); + replace_all(str, "{ ", "{"); + return str; +} + +bool check(std::string const &prg, std::string const &messages = "") { + auto g = parse(prg); + g->p.rewrite(g->d, g->module); + g->p.check(g->module); + if (!messages.empty()) { + REQUIRE(messages == to_string(g->module)); + } + return g->module.messages().empty(); +} + +} // namespace + +TEST_CASE("input-program", "[input]") { + SECTION("rewrite") { + REQUIRE("p(1):-q.p(2):-q.p(3):-q.p:-q." == rewrite(parse("p(1;2;3;):-q."))); + REQUIRE("p:-q(1).p:-q(2).p:-q(3).p:-q." == rewrite(parse("p:-q(1;2;3;)."))); + REQUIRE("p(1):-q(3).p(2):-q(3).p(1):-q(4).p(2):-q(4)." == rewrite(parse("p(1;2):-q(3;4)."))); + REQUIRE("p((X+Y)):-q(#Arith0);#Arith0=(X+Y)." == rewrite(parse("p(X+Y):-q(X+Y)."))); + REQUIRE("#Arith0<=#count{(X+Y):q((X+Y)):r(#Arith0),s(#Arith1),#Arith1=(A+B)}:-t(#Arith0);#Arith0=(X+Y);1<=#count{(X+Y):u(#Arith0),v(#Arith2),#Arith2=(A+B)}." == rewrite(parse("X+Y#count{X+Y:q(X+Y):r(X+Y),s(A+B)}:-t(X+Y),1#count{X+Y:u(X+Y),v(A+B)}."))); + REQUIRE("p(#Range0):-q(#Range1);#range(#Range1,A,B);#range(#Range0,X,Y)." == rewrite(parse("p(X..Y):-q(A..B)."))); + REQUIRE("p(1):-q.p(2):-q.p(3):-q.p:-q." == rewrite(parse("p(1;2;3;):-q."))); + REQUIRE("p(Z):-p(A,B);Y=#count{0,q(B):q(B)};X=#count{0,q(A):q(A)};Z=#count{0,r(X,Y):r(X,Y)}." == rewrite(parse("p(Z):-p(A,B),X={q(A)},Y={q(B)},Z={r(X,Y)}."))); + REQUIRE("p(Z):-Z=#count{0,p(X):p(X)};Z>0." == rewrite(parse("p(Z):-Z={p(X)},Z>0."))); + REQUIRE(":~[#inc_p(#Inc0,#Inc1)];0=0.[#Inc0@0,#Inc1]" == rewrite(parse("#program p(k,t). :~ #true. [ k,t ]"))); + REQUIRE("#project p(#Arith0):-[p(#Arith0)];#Arith0=(X+X)." == rewrite(parse("#project p(X+X)."))); + REQUIRE("#project p(X):-[p(X)].#project p(Y):-[p(Y)]." == rewrite(parse("#project p(X;Y)."))); + REQUIRE("#edge(a,b).#edge(c,d)." == rewrite(parse("#edge (a,b;c,d)."))); + REQUIRE("#edge((X+X),b)." == rewrite(parse("#edge (X+X,b)."))); + REQUIRE("#edge(#Range0,b):-#range(#Range0,1,10)." == rewrite(parse("#edge (1..10,b)."))); + REQUIRE("#heuristic a(#Arith0)[1@0,sign]:-[a(#Arith0)];#Arith0=(X+X)." == rewrite(parse("#heuristic a(X+X). [1@0,sign]"))); + REQUIRE("#heuristic a[(X+X)@2,sign]:-[a]." == rewrite(parse("#heuristic a. [X+X@2,sign]"))); + REQUIRE("#heuristic a(#Range0)[2@0,sign]:-[a(#Range0)];#range(#Range0,1,2)." == rewrite(parse("#heuristic a(1..2). [2,sign]"))); + REQUIRE("#theory x{node{};&edge/1:node,head}.#false:-p(Z);not &edge((Z+Z)){(z),(Y): p(Y,#Arith1),#Arith1=(Y+Y)}." == rewrite(parse("#theory x{ node{}; &edge/1: node, head }.&edge(Z+Z) { z, Y : p(Y,Y+Y)} :- p(Z)."))); + REQUIRE("#theory x{node{};&edge/1:node,head}.#false:-p(Z);#range(#Range0,Z,Z);not &edge(#Range0){(z),(Y): p(Y,#Range1),#range(#Range1,Y,Y)}." == rewrite(parse("#theory x{ node{}; &edge/1: node, head }.&edge(Z..Z) { z, Y : p(Y,Y..Y)} :- p(Z)."))); + } + + SECTION("defines") { + REQUIRE("p(1):-q." == rewrite(parse("#const a=1.#const b=a.#const c=b.#const d=c.p(d):-q."))); + REQUIRE("p(2):-q." == rewrite(parse("#const c=a+b.#const b=a.#const a=1.p(c):-q."))); + REQUIRE("p(1,2,3)." == rewrite(parse("#const x=1.#const y=1+x.#const z=1+y.p(x,y,z)."))); + REQUIRE("a." == rewrite(parse("#const a=b.a."))); + REQUIRE("a(b)." == rewrite(parse("#const a=b.a(a)."))); + REQUIRE("#project p(2):-[p(2)]." == rewrite(parse("#project p(x).#const x=2."))); + REQUIRE("#project x:-[x]." == rewrite(parse("#project x.#const x=2."))); + REQUIRE("#edge(2,y)." == rewrite(parse("#edge(x,y).#const x=2."))); + REQUIRE("#heuristic x[2@2,sign]:-[x]." == rewrite(parse("#heuristic x. [x@x,sign]#const x=2."))); + REQUIRE("#heuristic p(2)[2@2,sign]:-[p(2)]." == rewrite(parse("#heuristic p(x). [x@x,sign]#const x=2."))); + REQUIRE("#theory x{node{};&edge/1:node,{<<},node,head}.#false:-not &edge(2){(2),(Y): p(2,Y)}<<(2)." == rewrite(parse("#theory x{ node{}; &edge/1: node, {<<}, node, head }.&edge(z) { z, Y : p(z,Y)} << z. #const z=2."))); + } + + SECTION("check") { + REQUIRE( check("p(X):-q(X).")); + REQUIRE(!check("p(X,Y,Z):-q(X).", + "[-:1:1-16: error: unsafe variables in:\n" + " p(X,Y,Z):-[#inc_base];q(X).\n" + "-:1:5-6: note: 'Y' is unsafe\n" + "-:1:7-8: note: 'Z' is unsafe\n]")); + REQUIRE( check("p(X):-p(Y),X=Y+Y.")); + REQUIRE( check("p(X):-p(Y),Y+Y=X.")); + REQUIRE(!check("p(X):-p(Y),Y!=X.")); + REQUIRE(!check("p(X):-p(Y),p(1..Y)")); + // body aggregates + REQUIRE( check("p(X):-X=#sum{Y,Z:p(Y,Z)}.")); + REQUIRE(!check("p(X):-X=#sum{Y,Z:p(Y)}.", + "[-:1:7-23: error: unsafe variables in:\n" + " X=#sum{Y,Z:p(Y)}\n" + "-:1:16-17: note: 'Z' is unsafe\n]")); + REQUIRE( check(":-p(Y),1#count{X:q(X)}Y.")); + REQUIRE( check(":-p(Y),1{p(X):q(Y)}Y.")); + REQUIRE( check(":-p(Y),p(X):q(X,Y).")); + // head aggregates + REQUIRE( check("1#count{X:p(X):q(X,Y)}Y:-r(Y).")); + REQUIRE( check("1{p(X):q(X,Y)}Y:-r(Y).")); + REQUIRE( check("p(X):q(X,Y):-r(Y).")); + REQUIRE( check("#project p(X).")); + REQUIRE(!check("#project p(X+X).")); + REQUIRE( check("#edge (x,y).")); + REQUIRE(!check("#edge (X,Y).")); + REQUIRE( check("#edge (X,Y):p(X,Y).")); + REQUIRE( check("#heuristic p(X). [2@X,sign]")); + REQUIRE(!check("#heuristic p(X). [2@Y,sign]")); + REQUIRE( check("#heuristic p(X) : p(Y). [2@Y,sign]")); + REQUIRE( check("#theory x{ node{}; &edge/1: node, head }.&edge(Z) { X, Y : p(X,Y)}:-p(Z).")); + REQUIRE( check("#theory x{ node{}; &edge/1: node, any }.&edge(Z) { X, Y : p(X,Y)}:-p(Z).")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, body }.&edge(Z) { X, Y : p(X,Y)}:-p(Z).")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, directive }.&edge(Z) { X, Y : p(X,Y)}:-p(Z).")); + REQUIRE( check("#theory x{ node{}; &edge/1: node, body }.:-&edge(Z) { X, Y : p(X,Y)},p(Z).")); + REQUIRE( check("#theory x{ node{}; &edge/1: node, any }.:-&edge(Z) { X, Y : p(X,Y)},p(Z).")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, head }.:-&edge(Z) { X, Y : p(X,Y)},p(Z).")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, directive }.:-&edge(Z) { X, Y : p(X,Y)},p(Z).")); + REQUIRE( check("#theory x{ node{}; &edge/1: node, directive }.&edge(z) { X, Y : p(X,Y)}.")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, head }.&edge(ZZ) { X, Y : p(X,Y)}:-p(Z).")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, head }.&edge(Z) { XX, Y : p(X,Y)}:-p(Z).")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, head }.&edge(Z) { XX, Y : p(X,Y)}.")); + REQUIRE(!check("#theory x{ node{}; &edge/1: node, head }.&edge(z) { XX, Y : p(X,Y)}.")); + } + + SECTION("projection") { + REQUIRE("x:-q;#p_p(#p).#p_p(#p):-p(#P0)." == rewrite(parse("x:-p(_),q."))); + REQUIRE("x:-#p_p(#p,#b(X),f);q.#p_p(#p,#b(#X1),f):-p(#P0,#X1,f)." == rewrite(parse("x:-q;p(_,X,f)."))); + REQUIRE("x:-#p_p(#p);q.y:-#p_p(#p);q.#p_p(#p):-p(#P0)." == rewrite(parse("x:-q,p(_).y:-q,p(_)."))); + REQUIRE("x:-#p_p(f(1,#p),2);q.y:-#p_p(f(#b(X),#p),g(#b(X)));q.#p_p(f(1,#p),2):-p(f(1,#P0),2).#p_p(f(#b(#X0),#p),g(#b(#X2))):-p(f(#X0,#P1),g(#X2))." == rewrite(parse("x:-q,p(f(1,_),2).y:-q,p(f(X,_),g(X))."))); + REQUIRE("x:-not #p_p(#p).#p_p(#p):-p(#P0)." == rewrite(parse("x:-not p(_)."))); + REQUIRE("x:-#p_p(#p,1);q.y:-#p_p(1,#p);q.#p_p(#p,1):-p(#P0,1).#p_p(1,#p):-p(1,#P0)." == rewrite(parse("x:-q;p(_,1).y:-q;p(1,_)."))); + // NOTE: projection disabled for now + REQUIRE("x:-1<=#count{0,y:p(#Anon0),y}." == rewrite(parse("x:-1{y:p(_)}."))); + REQUIRE("x:-1<=#count{0,y:not #p_p(#p),y}.#p_p(#p):-p(#P0)." == rewrite(parse("x:-1{y:not p(_)}."))); + REQUIRE("#project p(#Anon0):-[p(#Anon0)]." == rewrite(parse("#project p(_)."))); + REQUIRE("#edge(X,#Anon0)." == rewrite(parse("#edge (X,_)."))); + REQUIRE("#heuristic p(#Anon0)[#Anon1@#Anon2,sign]:-[p(#Anon0)]." == rewrite(parse("#heuristic p(_). [_@_,sign]"))); + REQUIRE("#theory x{node{};&edge/2:node,directive}.#false:-not &edge(#Anon0,X){(X),(Y): p(#Anon1,Y)}." == rewrite(parse("#theory x{ node{}; &edge/2: node, directive }.&edge(_,X) { X, Y : p(_,Y)}."))); + } + + SECTION("statements") { + REQUIRE("#project p:-[p]." == rewrite(parse("#project p/0."))); + REQUIRE("#project p(X0):-[p(X0)]." == rewrite(parse("#project p/1."))); + REQUIRE("#project p(X0,X1,X2):-[p(X0,X1,X2)]." == rewrite(parse("#project p/3."))); + REQUIRE("#project p:-[p]." == rewrite(parse("#project p."))); + REQUIRE("#project p(X,Y):-[p(X,Y)]." == rewrite(parse("#project p(X,Y)."))); + REQUIRE("#edge(a,b)." == rewrite(parse("#edge (a,b)."))); + REQUIRE("#heuristic a[1@2,sign]:-[a]." == rewrite(parse("#heuristic a. [1@2,sign]"))); + REQUIRE("#heuristic a[1@2,level]:-[a]." == rewrite(parse("#heuristic a. [1@2,level]"))); + REQUIRE("#heuristic a[1@0,level]:-[a];c." == rewrite(parse("#heuristic a : c. [1,level]"))); + } + + SECTION("theory") { + REQUIRE("#theory x{}." == rewrite(parse("#theory x{ }."))); + REQUIRE("#theory x{node{};&edge/0:node,directive}." == rewrite(parse("#theory x{ node{}; &edge/0: node, directive }."))); + REQUIRE("#theory x{node{};&edge/0:node,directive}.#false:-not &edge{(X),(Y): p(X,Y)}." == rewrite(parse("#theory x{ node{}; &edge/0: node, directive }.&edge { X, Y : p(X,Y)}."))); + REQUIRE("#theory x{node{};&edge/0:node,directive}.#false:-not &edge{(X),(Y): p(X,Y)}." == rewrite(parse("#theory x{ node{}; &edge/0: node, directive }.&edge { X, Y : p(X,Y)}."))); + std::string theory = + "#theory csp{\n" + " term {\n" + " < : 0,binary,left;\n" + " + : 1,binary,left;\n" + " - : 1,binary,left;\n" + " * : 2,binary,left;\n" + " / : 2,binary,left;\n" + " ^ : 3,binary,right;\n" + " - : 4,unary\n" + " };\n" + " &linear/0: term, any\n" + "}.\n"; + std::string parsed = "#theory csp{term{< :0,binary,left,+ :1,binary,left,- :1,binary,left,* :2,binary,left,/ :2,binary,left,^ :3,binary,right,- :4,unary};&linear/0:term,any}."; + REQUIRE(parsed == rewrite(parse(theory))); + REQUIRE(parsed+"#false:-not &linear{(((1)<(((2)+(3))-(((4)*(5))/((6)^((-(7))^(8))))))<(9))}." == rewrite(parse(theory + "&linear { 1 < 2+3-4*5/6^ -7^8 < 9 }."))); + } + +} + +} } } // namespace Test Input Gringo + diff --git a/libgringo/tests/input/programbuilder.cc b/libgringo/tests/input/programbuilder.cc new file mode 100644 index 0000000..c81db0a --- /dev/null +++ b/libgringo/tests/input/programbuilder.cc @@ -0,0 +1,305 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/input/programbuilder.hh" +#include "gringo/input/program.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +#include +#include + +namespace Gringo { namespace Input { namespace Test { + +using namespace Gringo::Test; + +// {{{ declaration of Builder + +struct Builder { + Builder(); + + void setUp(); + // {{{ auxiliary function + typedef std::initializer_list Lits; + typedef std::initializer_list Terms; + typedef std::initializer_list> CondLits; + typedef std::initializer_list> Bounds; + typedef std::initializer_list> BodyAggrElems; + typedef std::initializer_list> HeadAggrElems; + LitUid lit(const char *name); + LitVecUid litvec(Lits names); + TermVecUid termvec(Terms terms); + CondLitVecUid condlitvec(CondLits names); + BdAggrElemVecUid bdaggrelemvec(BodyAggrElems elems); + HdAggrElemVecUid hdaggrelemvec(HeadAggrElems elems); + BoundVecUid boundvec(Bounds bounds); + BdLitVecUid bodyaggr(NAF naf, AggregateFunction fun, Bounds, CondLits); + BdLitVecUid bodyaggr(NAF naf, AggregateFunction fun, Bounds, BodyAggrElems); + HdLitUid headaggr(AggregateFunction fun, Bounds, CondLits); + HdLitUid headaggr(AggregateFunction fun, Bounds, HeadAggrElems); + // }}} + void test_term(); + void test_literal(); + void test_bdaggr(); + void test_hdaggr(); + void test_rule(); + + Gringo::Test::TestGringoModule module; + std::ostringstream oss; + Potassco::TheoryData td; + Output::OutputBase out; + Location l; + Defines defs; + Program prg; + Scripts scripts; + NongroundProgramBuilder p; +}; + +// }}} + +using namespace Gringo::IO; + +// {{{ definition of Builder + +Builder::Builder() + : out(td, {}, oss) + , l("dummy", 1, 1, "dummy", 1, 1) + , scripts(module) + , p(scripts, prg, out, defs) { } + +void Builder::setUp() { + defs.~Defines(); + new (&defs) Defines(); + prg.~Program(); + new (&prg) Program(); + p.~NongroundProgramBuilder(); + new (&p) NongroundProgramBuilder(scripts, prg, out, defs); +} + +// {{{ auxiliary functions + +LitUid Builder::lit(const char *name) { + return p.predlit(l, NAF::POS, p.predRep(l, false, name, p.termvecvec(p.termvecvec(), p.termvec()))); +} + +LitVecUid Builder::litvec(Lits names) { + LitVecUid lits = p.litvec(); + for (auto &x : names) { lits = p.litvec(lits, lit(x)); } + return lits; +} + +TermVecUid Builder::termvec(Terms terms) { + TermVecUid vec = p.termvec(); + for (auto &x : terms) { vec = p.termvec(vec, p.term(l, NUM(x))); } + return vec; +} + +CondLitVecUid Builder::condlitvec(CondLits elems) { + CondLitVecUid vec = p.condlitvec(); + for (auto &x : elems) { p.condlitvec(vec, lit(x.first), litvec(x.second)); } + return vec; +} + +HdAggrElemVecUid Builder::hdaggrelemvec(HeadAggrElems elems) { + HdAggrElemVecUid vec = p.headaggrelemvec(); + for (auto &x : elems) { p.headaggrelemvec(vec, termvec(std::get<0>(x)), lit(std::get<1>(x)), litvec(std::get<2>(x))); } + return vec; +} + +BdAggrElemVecUid Builder::bdaggrelemvec(BodyAggrElems elems) { + BdAggrElemVecUid vec = p.bodyaggrelemvec(); + for (auto &x : elems) { p.bodyaggrelemvec(vec, termvec(x.first), litvec(x.second)); } + return vec; +} + +BoundVecUid Builder::boundvec(Bounds bounds) { + BoundVecUid vec = p.boundvec(); + for (auto &x : bounds) { vec = p.boundvec(vec, x.first, p.term(l, NUM(x.second))); } + return vec; +} + +BdLitVecUid Builder::bodyaggr(NAF naf, AggregateFunction fun, Bounds bounds, CondLits elems) { + return p.bodyaggr(p.body(), l, naf, fun, boundvec(bounds), condlitvec(elems)); +} + +BdLitVecUid Builder::bodyaggr(NAF naf, AggregateFunction fun, Bounds bounds, BodyAggrElems elems) { + return p.bodyaggr(p.body(), l, naf, fun, boundvec(bounds), bdaggrelemvec(elems)); +} + +HdLitUid Builder::headaggr(AggregateFunction fun, Bounds bounds, CondLits elems) { + return p.headaggr(l, fun, boundvec(bounds), condlitvec(elems)); +} + +HdLitUid Builder::headaggr(AggregateFunction fun, Bounds bounds, HeadAggrElems elems) { + return p.headaggr(l, fun, boundvec(bounds), hdaggrelemvec(elems)); +} + +// }}} + +void Builder::test_term() { + auto t = [&](TermUid uid) -> std::string { + p.rule(l, p.headlit(p.predlit(l, NAF::POS, p.predRep(l, false, "p", p.termvecvec(p.termvecvec(), p.termvec(p.termvec(), uid)))))); + auto s(to_string(prg)); + setUp(); + if (!s.empty()) { s.pop_back(); } + return s; + }; + REQUIRE("p(1)." == t(p.term(l, NUM(1)))); + REQUIRE("p(X)." == t(p.term(l, String("X")))); + REQUIRE("p(_)." == t(p.term(l, String("_")))); + REQUIRE("p(|1|)." == t(p.term(l, UnOp::ABS, p.term(l, NUM(1))))); + REQUIRE("p(|1|;|2|;|3|)." == t(p.term(l, UnOp::ABS, p.termvec(p.termvec(p.termvec(p.termvec(), p.term(l, NUM(1))), p.term(l, NUM(2))), p.term(l, NUM(3)))))); + REQUIRE("p((1+2))." == t(p.term(l, BinOp::ADD, p.term(l, NUM(1)), p.term(l, NUM(2))))); + REQUIRE("p((1..2))." == t(p.term(l, p.term(l, NUM(1)), p.term(l, NUM(2))))); + REQUIRE("p(f(1);f(2,3,4))." == t(p.term(l, String("f"), p.termvecvec(p.termvecvec(p.termvecvec(), p.termvec(p.termvec(), p.term(l, NUM(1)))), p.termvec(p.termvec(p.termvec(p.termvec(), p.term(l, NUM(2))), p.term(l, NUM(3))), p.term(l, NUM(4)))), false))); + REQUIRE("p(@f(1);@f(2,3,4))." == t(p.term(l, String("f"), p.termvecvec(p.termvecvec(p.termvecvec(), p.termvec(p.termvec(), p.term(l, NUM(1)))), p.termvec(p.termvec(p.termvec(p.termvec(), p.term(l, NUM(2))), p.term(l, NUM(3))), p.term(l, NUM(4)))), true))); + REQUIRE("p(1;(2,3,4))." == t(p.pool(l,p.termvec(p.termvec(p.termvec(),p.term(l, p.termvec(p.termvec(), p.term(l, NUM(1))), false)), p.term(l, p.termvec(p.termvec(p.termvec(p.termvec(), p.term(l, NUM(2))), p.term(l, NUM(3))), p.term(l, NUM(4))), false))))); + REQUIRE("p((1,);(2,3,4))." == t( + p.pool(l, + p.termvec( + p.termvec( + p.termvec(), + p.term(l, p.termvec(p.termvec(), p.term(l, NUM(1))), true)), + p.term(l, p.termvec(p.termvec(p.termvec(p.termvec(), p.term(l, NUM(2))), p.term(l, NUM(3))), p.term(l, NUM(4))), false))))); +} + +void Builder::test_literal() { + auto t = [&](LitUid uid) -> std::string { + p.rule(l, p.headlit(uid)); + auto s(to_string(prg)); + setUp(); + if (!s.empty()) { s.pop_back(); } + return s; + }; + REQUIRE("0=0." == t(p.boollit(l, true))); + REQUIRE("0!=0." == t(p.boollit(l, false))); + REQUIRE("p." == t(lit("p"))); + REQUIRE("(-p)." == t(p.predlit(l, NAF::POS, p.predRep(l, true, "p", p.termvecvec(p.termvecvec(), p.termvec()))))); + REQUIRE("not p." == t(p.predlit(l, NAF::NOT, p.predRep(l, false, "p", p.termvecvec(p.termvecvec(), p.termvec()))))); + REQUIRE("not not p." == t(p.predlit(l, NAF::NOTNOT, p.predRep(l, false, "p", p.termvecvec(p.termvecvec(), p.termvec()))))); + REQUIRE("1<2." == t(p.rellit(l, Relation::LT, p.term(l, NUM(1)), p.term(l, NUM(2))))); + REQUIRE("1>2." == t(p.rellit(l, Relation::GT, p.term(l, NUM(1)), p.term(l, NUM(2))))); +} + +void Builder::test_bdaggr() { + auto t = [&](BdLitVecUid uid) -> std::string { + p.rule(l, p.headlit(p.boollit(l, false)), uid); + auto s(to_string(prg)); + setUp(); + if (!s.empty()) { s.pop_back(); } + return s; + }; + // BodyAggrElems + REQUIRE("0!=0:-#sum{}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, BodyAggrElems({})))); + REQUIRE("0!=0:-not #sum{}." == t(bodyaggr(NAF::NOT, AggregateFunction::SUM, {}, BodyAggrElems({})))); + REQUIRE("0!=0:-not not #sum{}." == t(bodyaggr(NAF::NOTNOT, AggregateFunction::SUM, {}, BodyAggrElems({})))); + REQUIRE("0!=0:-#count{}." == t(bodyaggr(NAF::POS, AggregateFunction::COUNT, {}, BodyAggrElems({})))); + REQUIRE("0!=0:-1<#sum{}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {{Relation::GT, 1}}, BodyAggrElems({})))); + REQUIRE("0!=0:-1<#sum{}<2." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {{Relation::GT, 1},{Relation::LT, 2}}, BodyAggrElems({})))); + REQUIRE("0!=0:-1<#sum{}<2<3." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {{Relation::GT, 1},{Relation::LT, 2},{Relation::LT, 3}}, BodyAggrElems({})))); + REQUIRE("0!=0:-#sum{:}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, BodyAggrElems({ {{}, {}} })))); + REQUIRE("0!=0:-#sum{1:p}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, BodyAggrElems({ {{1}, {"p"}} })))); + REQUIRE("0!=0:-#sum{1,2:p,q}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, BodyAggrElems({ {{1, 2},{"p", "q"}} })))); + REQUIRE("0!=0:-#sum{:;:}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, BodyAggrElems({ {{},{}}, {{},{}} })))); + // CondLits + REQUIRE("0!=0:-#sum{}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, CondLits({})))); + REQUIRE("0!=0:-not #sum{}." == t(bodyaggr(NAF::NOT, AggregateFunction::SUM, {}, CondLits({})))); + REQUIRE("0!=0:-not not #sum{}." == t(bodyaggr(NAF::NOTNOT, AggregateFunction::SUM, {}, CondLits({})))); + REQUIRE("0!=0:-#count{}." == t(bodyaggr(NAF::POS, AggregateFunction::COUNT, {}, CondLits({})))); + REQUIRE("0!=0:-1<#sum{}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {{Relation::GT, 1}}, CondLits({})))); + REQUIRE("0!=0:-1<#sum{}<2." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {{Relation::GT, 1},{Relation::LT, 2}}, CondLits({})))); + REQUIRE("0!=0:-1<#sum{}<2<3." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {{Relation::GT, 1},{Relation::LT, 2},{Relation::LT, 3}}, CondLits({})))); + REQUIRE("0!=0:-#sum{p:}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, CondLits({ {"p",{}} })))); + REQUIRE("0!=0:-#sum{p:q}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, CondLits({ {"p",{"q"}} })))); + REQUIRE("0!=0:-#sum{p:q,r}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, CondLits({ {"p",{"q", "r"}} })))); + REQUIRE("0!=0:-#sum{p:;q:}." == t(bodyaggr(NAF::POS, AggregateFunction::SUM, {}, CondLits({ {"p",{}}, {"q",{}} })))); + // Conjunction + REQUIRE("0!=0:-p:." == t(p.conjunction(p.body(), l, lit("p"), litvec({})))); + REQUIRE("0!=0:-p:q." == t(p.conjunction(p.body(), l, lit("p"), litvec({"q"})))); + REQUIRE("0!=0:-p:q,r." == t(p.conjunction(p.body(), l, lit("p"), litvec({"q", "r"})))); +} + +void Builder::test_hdaggr() { + auto t = [&](HdLitUid uid) -> std::string { + p.rule(l, uid); + auto s(to_string(prg)); + setUp(); + if (!s.empty()) { s.pop_back(); } + return s; + }; + // HeadAggrElems + REQUIRE("#sum{}." == t(headaggr(AggregateFunction::SUM, {}, HeadAggrElems({})))); + REQUIRE("#count{}." == t(headaggr(AggregateFunction::COUNT, {}, HeadAggrElems({})))); + REQUIRE("1<#sum{}." == t(headaggr(AggregateFunction::SUM, {{Relation::GT, 1}}, HeadAggrElems({})))); + REQUIRE("1<#sum{}<2." == t(headaggr(AggregateFunction::SUM, {{Relation::GT, 1},{Relation::LT, 2}}, HeadAggrElems({})))); + REQUIRE("1<#sum{}<2<3." == t(headaggr(AggregateFunction::SUM, {{Relation::GT, 1},{Relation::LT, 2},{Relation::LT, 3}}, HeadAggrElems({})))); + typedef std::tuple E; + REQUIRE("#sum{:p:}." == t(headaggr(AggregateFunction::SUM, {}, HeadAggrElems({ E{{},"p",{}} })))); + REQUIRE("#sum{1:p:q}." == t(headaggr(AggregateFunction::SUM, {}, HeadAggrElems({ E{{1},"p",{"q"}} })))); + REQUIRE("#sum{1,2:p:q,r}." == t(headaggr(AggregateFunction::SUM, {}, HeadAggrElems({ E{{1,2},"p",{"q", "r"}} })))); + REQUIRE("#sum{:p:;:p:}." == t(headaggr(AggregateFunction::SUM, {}, HeadAggrElems({ E{{},"p",{}}, E{{},"p",{}} })))); + // CondLits + REQUIRE("#sum{}." == t(headaggr(AggregateFunction::SUM, {}, CondLits({})))); + REQUIRE("#count{}." == t(headaggr(AggregateFunction::COUNT, {}, CondLits({})))); + REQUIRE("1<#sum{}." == t(headaggr(AggregateFunction::SUM, {{Relation::GT,1}}, CondLits({})))); + REQUIRE("1<#sum{}<2." == t(headaggr(AggregateFunction::SUM, {{Relation::GT,1},{Relation::LT,2}}, CondLits({})))); + REQUIRE("1<#sum{}<2<3." == t(headaggr(AggregateFunction::SUM, {{Relation::GT,1},{Relation::LT,2},{Relation::LT,3}}, CondLits({})))); + REQUIRE("#sum{p:}." == t(headaggr(AggregateFunction::SUM, {}, CondLits({ {"p",{}} })))); + REQUIRE("#sum{p:q}." == t(headaggr(AggregateFunction::SUM, {}, CondLits({ {"p",{"q"}} })))); + REQUIRE("#sum{p:q,r}." == t(headaggr(AggregateFunction::SUM, {}, CondLits({ {"p",{"q","r"}} })))); + REQUIRE("#sum{p:;q:}." == t(headaggr(AggregateFunction::SUM, {}, CondLits({ {"p",{}},{"q",{}} })))); + // Disjunction + REQUIRE("p::." == t(p.disjunction(l, condlitvec({ {"p",{}} })))); + REQUIRE("p::q." == t(p.disjunction(l, condlitvec({ {"p", {"q"}} })))); + REQUIRE("p::q,r." == t(p.disjunction(l, condlitvec({ {"p",{"q","r"}} })))); + REQUIRE("p::;q::." == t(p.disjunction(l, condlitvec({ {"p",{}}, {"q",{}} })))); +} + +void Builder::test_rule() { + auto t = [&](char const *name, Lits lits) -> std::string { + BdLitVecUid vec = p.body(); + for (auto &x : lits) { vec = p.bodylit(vec, lit(x)); } + p.rule(l, p.headlit(lit(name)), vec); + auto s(to_string(prg)); + setUp(); + if (!s.empty()) { s.pop_back(); } + return s; + }; + REQUIRE("a." == t("a",{})); + REQUIRE("a:-b." == t("a",{"b"})); + REQUIRE("a:-b;c." == t("a",{"b","c"})); + REQUIRE("a:-b;c;d." == t("a",{"b","c","d"})); +} + +TEST_CASE("input-builder", "[input]") { + Builder b; + SECTION("term") { b.test_term(); } + SECTION("literal") { b.test_literal(); } + SECTION("rule") { b.test_rule(); } + SECTION("bdaggr") { b.test_bdaggr(); } + SECTION("hdaggr") { b.test_hdaggr(); } +} + +} } } // namespace Test Input Gringo + + diff --git a/libgringo/tests/intervals.cc b/libgringo/tests/intervals.cc new file mode 100644 index 0000000..17ceded --- /dev/null +++ b/libgringo/tests/intervals.cc @@ -0,0 +1,377 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/intervals.hh" +#include "gringo/utility.hh" + +#include "tests/tests.hh" + +namespace Gringo { namespace Test { + +using IS = IntervalSet; +using ES = enum_interval_set; +using LB = IS::LBound; +using RB = IS::RBound; +using IV = IS::Interval; +using S = std::string; + +namespace { + +LB lb(int x, bool y) { return {x, y}; } +RB rb(int x, bool y) { return {x, y}; } +std::string print(IS const &x) { + auto f = [](std::ostream &out, IV const &x) { + out + << (x.left.inclusive ? "[" : "(") + << x.left.bound + << "," + << x.right.bound + << (x.right.inclusive ? "]" : ")"); + }; + std::ostringstream out; + out << "{"; + print_comma(out, x.vec, ",", f); + out << "}"; + return out.str(); +} + +std::string print(ES const &x) { + std::ostringstream out; + out << "{"; + if (!x.empty()) { + int a = *x.begin(); + int b = *x.begin() - 1; + for (auto y : x) { + if (b+1 != y) { + if (a <= b) { out << "[" << a << "," << b << "],"; } + a = y; + } + b = y; + } + out << "[" << a << "," << b << "]"; + } + out << "}"; + return out.str(); +} + +} + +TEST_CASE("intervals", "[base]") { + SECTION("boundLess") { + REQUIRE(!(lb(2,true) < lb(1,true))); + REQUIRE(!(lb(2,true) < lb(1,false))); + REQUIRE(!(lb(2,false) < lb(1,true))); + REQUIRE(!(lb(2,false) < lb(1,false))); + + REQUIRE( (lb(1,true) < lb(2,true))); + REQUIRE( (lb(1,true) < lb(2,false))); + REQUIRE( (lb(1,false) < lb(2,true))); + REQUIRE( (lb(1,false) < lb(2,false))); + + REQUIRE(!(lb(1,true) < lb(1,true))); + REQUIRE( (lb(1,true) < lb(1,false))); + REQUIRE(!(lb(1,false) < lb(1,true))); + REQUIRE(!(lb(1,false) < lb(1,false))); + // same for RB + REQUIRE(!(rb(2,true) < rb(1,true))); + REQUIRE(!(rb(2,true) < rb(1,false))); + REQUIRE(!(rb(2,false) < rb(1,true))); + REQUIRE(!(rb(2,false) < rb(1,false))); + + REQUIRE( (rb(1,true) < rb(2,true))); + REQUIRE( (rb(1,true) < rb(2,false))); + REQUIRE( (rb(1,false) < rb(2,true))); + REQUIRE( (rb(1,false) < rb(2,false))); + + REQUIRE(!(rb(1,true) < rb(1,true))); + REQUIRE(!(rb(1,true) < rb(1,false))); + REQUIRE( (rb(1,false) < rb(1,true))); + REQUIRE(!(rb(1,false) < rb(1,false))); + } + + SECTION("boundLessEq") { + REQUIRE(!(lb(2,true) <= lb(1,true))); + REQUIRE(!(lb(2,true) <= lb(1,false))); + REQUIRE(!(lb(2,false) <= lb(1,true))); + REQUIRE(!(lb(2,false) <= lb(1,false))); + + REQUIRE( (lb(1,true) <= lb(2,true))); + REQUIRE( (lb(1,true) <= lb(2,false))); + REQUIRE( (lb(1,false) <= lb(2,true))); + REQUIRE( (lb(1,false) <= lb(2,false))); + + REQUIRE( (lb(1,true) <= lb(1,true))); + REQUIRE( (lb(1,true) <= lb(1,false))); + REQUIRE(!(lb(1,false) <= lb(1,true))); + REQUIRE( (lb(1,false) <= lb(1,false))); + // same for RB + REQUIRE(!(rb(2,true) <= rb(1,true))); + REQUIRE(!(rb(2,true) <= rb(1,false))); + REQUIRE(!(rb(2,false) <= rb(1,true))); + REQUIRE(!(rb(2,false) <= rb(1,false))); + + REQUIRE( (rb(1,true) <= rb(2,true))); + REQUIRE( (rb(1,true) <= rb(2,false))); + REQUIRE( (rb(1,false) <= rb(2,true))); + REQUIRE( (rb(1,false) <= rb(2,false))); + + REQUIRE( (rb(1,true) <= rb(1,true))); + REQUIRE(!(rb(1,true) <= rb(1,false))); + REQUIRE( (rb(1,false) <= rb(1,true))); + REQUIRE( (rb(1,false) <= rb(1,false))); + } + + SECTION("boundBefore") { + // before with gap + // { + // } + REQUIRE((lb(1,true) < rb(2,true))); + REQUIRE((lb(1,true) < rb(2,false))); + REQUIRE((lb(1,false) < rb(2,true))); + REQUIRE((lb(1,false) < rb(2,false))); + // [ { { + // ] - gap ) - no gap ) - no gap + REQUIRE( (lb(1,true) < rb(1,true))); + REQUIRE(!(lb(1,true) < rb(1,false))); + REQUIRE(!(lb(1,false) < rb(1,true))); + REQUIRE(!(lb(1,false) < rb(1,false))); + // { + // } + REQUIRE(!(lb(2,true) < rb(1,true))); + REQUIRE(!(lb(2,true) < rb(1,false))); + REQUIRE(!(lb(2,false) < rb(1,true))); + REQUIRE(!(lb(2,false) < rb(1,false))); + // the other way round + // } + // { + REQUIRE((rb(1,true) < lb(2,true))); + REQUIRE((rb(1,true) < lb(2,false))); + REQUIRE((rb(1,false) < lb(2,true))); + REQUIRE((rb(1,false) < lb(2,false))); + // } ] ) + // [ - no gap { - no gap ( - gap + REQUIRE(!(rb(1,true) < lb(1,true))); + REQUIRE(!(rb(1,true) < lb(1,false))); + REQUIRE(!(rb(1,false) < lb(1,true))); + REQUIRE( (rb(1,false) < lb(1,false))); + // } + // { + REQUIRE(!(rb(2,true) < lb(1,true))); + REQUIRE(!(rb(2,true) < lb(1,false))); + REQUIRE(!(rb(2,false) < lb(1,true))); + REQUIRE(!(rb(2,false) < lb(1,false))); + } + + SECTION("add") { + IS x; + x.add(1,true,1,true); + REQUIRE("{[1,1]}" == print(x)); + x.add(3,true,2,true); + REQUIRE("{[1,1]}" == print(x)); + x.add(3,true,4,false); + REQUIRE("{[1,1],[3,4)}" == print(x)); + x.add(2,false,3,false); + REQUIRE("{[1,1],(2,4)}" == print(x)); + x.add(1,false,2,false); + REQUIRE("{[1,2),(2,4)}" == print(x)); + x.add(2,true,2,true); + REQUIRE("{[1,4)}" == print(x)); + x.add(4,true,5,true); + REQUIRE("{[1,5]}" == print(x)); + x.add(8,false,9,true); + REQUIRE("{[1,5],(8,9]}" == print(x)); + x.add(11,false,12,true); + REQUIRE("{[1,5],(8,9],(11,12]}" == print(x)); + x.add(13,false,14,true); + REQUIRE("{[1,5],(8,9],(11,12],(13,14]}" == print(x)); + x.add(10,true,11,false); + REQUIRE("{[1,5],(8,9],[10,11),(11,12],(13,14]}" == print(x)); + x.add(9,true,11,true); + REQUIRE("{[1,5],(8,12],(13,14]}" == print(x)); + x.add(0,true,13,false); + REQUIRE("{[0,13),(13,14]}" == print(x)); + x.add(-1,true,42,false); + REQUIRE("{[-1,42)}" == print(x)); + x.add(42,true,43,true); + REQUIRE("{[-1,43]}" == print(x)); + } + + SECTION("remove") { + IS x; + x.add(1,true,50,true); + REQUIRE("{[1,50]}" == print(x)); + x.remove(1,true,2,true); + REQUIRE("{(2,50]}" == print(x)); + x.remove(49,false,50,true); + REQUIRE("{(2,49]}" == print(x)); + x.remove(5,true,6,false); + REQUIRE("{(2,5),[6,49]}" == print(x)); + x.remove(8,false,9,true); + REQUIRE("{(2,5),[6,8],(9,49]}" == print(x)); + IS a(x), b(x), c(x); + a.remove(2,false,13,true); + REQUIRE("{(13,49]}" == print(a)); + b.remove(4,false,8,true); + REQUIRE("{(2,4],(9,49]}" == print(b)); + c.remove(4,false,13,true); + REQUIRE("{(2,4],(13,49]}" == print(c)); + } + + SECTION("contains") { + IS x; + x.add(5,true,10,false); + x.add(1,true,4,false); + REQUIRE( x.contains({{5,true},{10,false}})); + REQUIRE(!x.contains({{5,true},{10,true}})); + REQUIRE( x.contains({{7,true},{8,true}})); + REQUIRE( x.contains({{5,false},{6,false}})); + } + + SECTION("intersects") { + IS x; + x.add(1,true,4,false); + x.add(5,true,10,false); + x.add(11,false,12,false); + REQUIRE( x.intersects({{5,true},{10,false}})); + REQUIRE( x.intersects({{5,true},{10,true}})); + REQUIRE( x.intersects({{7,true},{8,true}})); + REQUIRE(!x.intersects({{10,true},{11,true}})); + REQUIRE( x.intersects({{10,true},{12,true}})); + REQUIRE( x.intersects({{2,true},{7,true}})); + REQUIRE( x.intersects({{4,true},{7,true}})); + REQUIRE(!x.intersects({{0,true},{1,false}})); + REQUIRE( x.intersects({{0,true},{1,true}})); + REQUIRE(!x.intersects({{12,true},{13,true}})); + } + + SECTION("intersect") { + IS x, y; + x.add({{2,true},{8,false}}); + x.add({{9,false},{13,true}}); + + y.add({{1,true},{3,true}}); + y.add({{4,false},{5,true}}); + y.add({{7,true},{10,false}}); + y.add({{11,true},{12,false}}); + REQUIRE("{[2,3],(4,5],[7,8),(9,10),[11,12)}" == print(x.intersect(y))); + REQUIRE("{[2,3],(4,5],[7,8),(9,10),[11,12)}" == print(y.intersect(x))); + } + + SECTION("difference") { + IS x, y; + x.add({{2,true},{8,false}}); + x.add({{9,false},{13,true}}); + + y.add({{1,true},{3,true}}); + y.add({{4,false},{5,true}}); + y.add({{7,true},{10,false}}); + y.add({{11,true},{12,false}}); + REQUIRE("{(3,4],(5,7),[10,11),[12,13]}" == print(x.difference(y))); + REQUIRE("{[1,2),[8,9]}" == print(y.difference(x))); + } + + SECTION("enum_empty") { + ES x; + REQUIRE(x.empty()); + REQUIRE(x.begin() == x.end()); + } + + SECTION("enum_add") { + ES x; + x.add(1,2); + REQUIRE("{[1,1]}" == print(x)); + x.add(3,3); + REQUIRE("{[1,1]}" == print(x)); + x.add(3,4); + REQUIRE("{[1,1],[3,3]}" == print(x)); + x.add(2,3); + REQUIRE("{[1,3]}" == print(x)); + x.add(4,6); + REQUIRE("{[1,5]}" == print(x)); + x.add(9,10); + REQUIRE("{[1,5],[9,9]}" == print(x)); + x.add(12,13); + REQUIRE("{[1,5],[9,9],[12,12]}" == print(x)); + x.add(14,16); + REQUIRE("{[1,5],[9,9],[12,12],[14,15]}" == print(x)); + x.add(10,11); + REQUIRE("{[1,5],[9,10],[12,12],[14,15]}" == print(x)); + x.add(9,12); + REQUIRE("{[1,5],[9,12],[14,15]}" == print(x)); + x.add(0,14); + REQUIRE("{[0,15]}" == print(x)); + x.add(-1,42); + REQUIRE("{[-1,41]}" == print(x)); + x.add(42,44); + REQUIRE("{[-1,43]}" == print(x)); + } + + SECTION("enum_contains") { + ES x; + x.add(5,10); + x.add(1,4); + REQUIRE( x.contains(5,10)); + REQUIRE(!x.contains(5,11)); + REQUIRE( x.contains(7,9)); + REQUIRE( x.contains(6,6)); + } + + SECTION("enum_remove") { + ES x; + x.add(1,51); + REQUIRE("{[1,50]}" == print(x)); + x.remove(1,3); + REQUIRE("{[3,50]}" == print(x)); + x.remove(50,51); + REQUIRE("{[3,49]}" == print(x)); + x.remove(5,6); + REQUIRE("{[3,4],[6,49]}" == print(x)); + x.remove(9,10); + REQUIRE("{[3,4],[6,8],[10,49]}" == print(x)); + ES a(x), b(x), c(x); + a.remove(3,14); + REQUIRE("{[14,49]}" == print(a)); + b.remove(5,9); + REQUIRE("{[3,4],[10,49]}" == print(b)); + c.remove(5,14); + REQUIRE("{[3,4],[14,49]}" == print(c)); + } + + SECTION("enum_intersects") { + ES x; + x.add(1,3); + x.add(5,9); + x.add(12,13); + REQUIRE( x.intersects(5,9)); + REQUIRE( x.intersects(5,10)); + REQUIRE( x.intersects(7,8)); + REQUIRE(!x.intersects(10,12)); + REQUIRE( x.intersects(10,13)); + REQUIRE( x.intersects(2,7)); + REQUIRE( x.intersects(4,7)); + REQUIRE(!x.intersects(0,0)); + REQUIRE( x.intersects(0,2)); + REQUIRE(!x.intersects(13,14)); + } + +} + +} } // namespace Test Gringo + diff --git a/libgringo/tests/lua.cc b/libgringo/tests/lua.cc new file mode 100644 index 0000000..beac398 --- /dev/null +++ b/libgringo/tests/lua.cc @@ -0,0 +1,171 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifdef WITH_LUA + +#include "tests/tests.hh" +#include "gringo/lua.hh" + +namespace Gringo { namespace Test { + +namespace { + +std::string removeTrace(std::string &&s) { + auto needle = "stack traceback:\n"; + auto begin = s.find(needle); + if (begin != std::string::npos) { + begin+= strlen(needle); + auto end = begin; + while (end < s.size() && s[end] == ' ') { + auto next = s.find("\n", end); + if (next == std::string::npos) { + break; + } + else { + end = next + 1; + } + } + s.replace(begin, end - begin, " ...\n"); + } + return std::move(s); +} + +using namespace Gringo::IO; +using S = std::string; + +} // namespace + +TEST_CASE("lua", "[base][lua]") { + TestGringoModule module; + SymSpan const empty{nullptr, 0}; + SECTION("parse") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Lua lua(module); + lua.exec(loc, + "clingo = require(\"clingo\")\n" + "function get() return clingo.parse_term('1') end\n" + ); + REQUIRE("[1]" == to_string(lua.call(loc, "get", empty, module))); + lua.exec(loc, + "clingo = require(\"clingo\")\n" + "function get() return clingo.parse_term('p(2+1)') end\n" + ); + REQUIRE("[p(3)]" == to_string(lua.call(loc, "get", empty, module))); + } + + SECTION("values") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Lua lua(module); + lua.exec(loc, + "clingo = require(\"clingo\")\n" + "x = clingo.Function(\"f\", {2, 3, 4})\n" + "y = clingo.Function(\"f\", {2, 3, 4}, false)\n" + "function getX() return x end\n" + "function fail() return clingo.Function(\"g\", {{}}) end\n" + "function none() return nil end\n" + "values = {" + "clingo.Function(\"f\",{1, 2, 3})," + "clingo.Supremum," + "clingo.Infimum," + "clingo.Function(\"id\")," + "clingo.Tuple({clingo.Number(1), 2, 3})," + "123," + "clingo.String(\"abc\")," + "\"x\"," + "clingo.Tuple(x.arguments)," + "x.name," + "tostring(x.negative)," + "tostring(y.negative)," + "x," + "y," + "}\n" + "function getValues() return values end\n" + ); + REQUIRE("[f(2,3,4)]" == to_string(lua.call(loc, "getX", empty, module))); + REQUIRE("[f(1,2,3),#sup,#inf,id,(1,2,3),123,\"abc\",\"x\",(2,3,4),\"f\",\"false\",\"true\",f(2,3,4),-f(2,3,4)]" == to_string(lua.call(loc, "getValues", empty, module))); + { + REQUIRE("[]" == to_string(lua.call(loc, "none", empty, module))); + REQUIRE( + "[" + "dummy:1:1: info: operation undefined:\n" + " RuntimeError: cannot convert to value\n" + "stack traceback:\n" + " ...\n" + "]" == removeTrace(IO::to_string(module))); + } + { + module.reset(); + REQUIRE("[]" == to_string(lua.call(loc, "fail", empty, module))); + REQUIRE( + "[" + "dummy:1:1: info: operation undefined:\n" + " RuntimeError: [string \"dummy:1:1\"]:5: cannot convert to value\n" + "stack traceback:\n" + " ...\n" + "]" == removeTrace(IO::to_string(module))); + } + { + module.reset(); + try { + lua.exec(loc, "("); + FAIL("no exception"); + } + catch (GringoError const &e) { + REQUIRE( + "dummy:1:1: error: parsing lua script failed:\n" + " SyntaxError: [string \"dummy:1:1\"]:1: unexpected symbol near \n" + "" == replace_all(e.what(), "''", "")); + } + } + } + + SECTION("cmp") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Lua lua(module); + lua.exec(loc, + "clingo = require(\"clingo\")\n" + "function int(x) if x then return 1 else return 0 end end\n" + "function cmp()\n" + " return {" + "int(clingo.Function(\"a\") < clingo.Function(\"b\"))," + "int(clingo.Function(\"b\") < clingo.Function(\"a\"))," + "} end\n" + ); + REQUIRE("[1,0]" == to_string(lua.call(loc, "cmp", empty, module))); + } + + SECTION("callable") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Lua lua(module); + lua.exec(loc, + "function a() end\n" + "b = 1\n" + ); + REQUIRE(lua.callable("a")); + REQUIRE(!lua.callable("b")); + REQUIRE(!lua.callable("c")); + } + +} + +} } // namespace Test Gringo + +#endif // WITH_LUA + diff --git a/libgringo/tests/main.cc b/libgringo/tests/main.cc new file mode 100644 index 0000000..e8c1a9b --- /dev/null +++ b/libgringo/tests/main.cc @@ -0,0 +1,21 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/libgringo/tests/output/aspcomp13.cc b/libgringo/tests/output/aspcomp13.cc new file mode 100644 index 0000000..0fef9a5 --- /dev/null +++ b/libgringo/tests/output/aspcomp13.cc @@ -0,0 +1,2523 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/ground/dependency.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/output/solver_helper.hh" + +#include "gringo/input/nongroundparser.hh" + + +namespace Gringo { namespace Output { namespace Test { + +TEST_CASE("output-aspcomp2013", "[output][aspcomp]") { + +// {{{1 N01 Permutation Pattern Matching + + SECTION("aspcomp2013_01") { + // Author: Martin Lackner, Andreas Pfandler + REQUIRE( + "([[solution(1,3),solution(2,4),solution(3,2)]],[])" == + IO::to_string(solve( + "% instance\n" + "t(1,5).\n" + "t(2,3).\n" + "t(3,1).\n" + "t(4,4).\n" + "t(5,2).\n" + "p(1,2).\n" + "p(2,3).\n" + "p(3,1).\n" + "patternlength(3).\n" + "\n" + "% encoding\n" + "kval(1).\n" + "kval(N+1) :- kval(N), N < L, patternlength(L). \n" + "1 <= { subt(K,I,E) : t(I,E) } <= 1 :- kval(K), patternlength(L).\n" + ":- subt(K1,I1,_), subt(K2,I2,_), K1= I2.\n" + "solution(K,E) :- subt(K,_,E).\n" + ":- solution(K1,ET1), solution(K2,ET2), p(K1,EP1), p(K2,EP2), ET1 < ET2, EP1 >= EP2.\n", {"solution("}))); + } + +// {{{1 N02 Valves Location Problem + + SECTION("aspcomp2013_02") { + // Author: Andrea Peano + REQUIRE( + "([[valve(1,2),valve(1,4),valve(3,2),valve(4,2)]]," + "[-:63:20-21: info: global variable in tuple of aggregate element:\n X\n" + ",-:91:31-32: info: global variable in tuple of aggregate element:\n W\n" + ",-:90:22-23: info: global variable in tuple of aggregate element:\n X\n" + ",-:90:24-25: info: global variable in tuple of aggregate element:\n Y\n" + ",-:91:33-34: info: global variable in tuple of aggregate element:\n Z\n" + ",-:107:44-45: info: global variable in tuple of aggregate element:\n X\n" + ",-:107:46-47: info: global variable in tuple of aggregate element:\n Y\n" + "])" == IO::to_string(solve( + "%instance\n" + "\n" + "valves_number(4).\n" + "valves_per_pipe(1).\n" + "\n" + "junction(1). junction(2). junction(3).\n" + "junction(4). junction(5).\n" + "tank(1).\n" + "\n" + "pipe(1, 2). pipe(1, 4). pipe(2, 3). \n" + "pipe(2, 4). pipe(3, 4). pipe(3, 5).\n" + "\n" + "dem(1, 2, 57). dem(1, 4, 65). dem(2, 3, 155). \n" + "dem(2, 4, 129). dem(3, 4, 78). dem(3, 5, 200).\n" + "\n" + "%encoding\n" + "\n" + " %just some tools\n" + " %Symmetric pipe\n" + "symm_pipe(A,B):- pipe(A,B).\n" + "symm_pipe(B,A):- pipe(A,B).\n" + " %We need a lexicographic order (there may be more than one worst isolation cases)\n" + "less_ico(pipe(A,B), pipe(C,D)):- pipe(A,B), pipe(C,D), AB, valve(X,A).\n" + "\n" + " %\n" + " %A pipe adjacent to the tank is reached, when a generic pipe is broken iff there is no valve between them.\n" + "reached(pipe(A,B), broken(X,Y)):- tank(A), pipe(X,Y), pipe(A,B), not closed_valve(v(A,B), broken(X,Y)).\n" + "reached(pipe(A,B), broken(X,Y)):- tank(B), pipe(X,Y), pipe(A,B), not closed_valve(v(B,A), broken(X,Y)).\n" + "\n" + " %\n" + " %Can we recursively reach any tank??\n" + "reached(pipe(A,B), broken(X,Y)) :- adj(pipe(A,B), pipe(C,D), COM, U1, U2), %COM is not a tank! \n" + " not closed_valve(v(COM,U1), broken(X,Y)),\n" + " not closed_valve(v(COM,U2), broken(X,Y)),\n" + " reached(pipe(C,D), broken(X,Y)).\n" + "\n" + " %\n" + " %The broken pipe must be unreachable!\n" + ":- pipe(A,B), reached(pipe(A,B), broken(A,B)).\n" + "\n" + " %\n" + " % Pair-wise comparisons between delivered demand pipe isolation cases\n" + "%lower(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n" + "% #sum [ reached(pipe(A,B), broken(X,Y))=Dn: dem(A,B,Dn),\n" + "% reached(pipe(C,D), broken(W,Z))=-Dm: dem(C,D,Dm) ] 0.\n" + "%lower(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n" + "% S1 = #sum { Dn,A,B,X,Y : reached(pipe(A,B), broken(X,Y)), dem(A,B,Dn) },\n" + "% S2 = #sum { Dm,C,D,W,Z : reached(pipe(C,D), broken(W,Z)), dem(C,D,Dm) }, S1 - S2 <= 0.\n" + "lower(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n" + " #sum { Dn,A,B,X,Y : reached(pipe(A,B), broken(X,Y)), dem(A,B,Dn);\n" + " Dm,C,D,W,Z : reached(pipe(C,D), broken(W,Z)), dem(C,D,NegDm), Dm = -NegDm } <= 0.\n" + "\n" + " %\n" + " %Then the lower are...\n" + "lower_lexico(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z),\n" + " lower(pipe(X,Y), pipe(W,Z)), not lower(pipe(W,Z), pipe(X,Y)).\n" + "lower_lexico(pipe(X,Y), pipe(X,Y)) :- pipe(X,Y),\n" + " lower(pipe(X,Y), pipe(X,Y)).\n" + "lower_lexico(pipe(X,Y), pipe(W,Z)) :- pipe(X,Y), pipe(W,Z), % with the same delivered demand\n" + " lower(pipe(X,Y), pipe(W,Z)), lower(pipe(W,Z),pipe(X,Y)),\n" + " less_ico(pipe(X,Y), pipe(W,Z)).\n" + "\n" + " %\n" + " %And the worst isolation case is the one for which all lower_lexico are true\n" + "%worst(pipe(X,Y)) :- pipe(X,Y), lower_lexico(pipe(X,Y),pipe(W,Z)) : pipe(W,Z).\n" + "worst(pipe(X,Y)) :- pipe(X,Y), C = #count{ W,Z : pipe(W,Z) }, \n" + " D = #count{ X,Y,W,Z : lower_lexico(pipe(X,Y),pipe(W,Z)) , pipe(W,Z)}, C = D.\n" + "\n" + "\n" + "worst_deliv_dem(pipe(A,B), D) :- dem(A,B,D), pipe(X,Y),\n" + " reached(pipe(A,B), broken(X,Y)), worst(pipe(X,Y)).\n" + "\n" + " %\n" + " %Worst isolation case' delivered demand maximization\n" + "\n" + ":~ dem(A,B,D), not worst_deliv_dem(pipe(A,B),D). [D,A,B]\n", {"valve("}, {343}))); + } + +// {{{1 N04 Connected Maximum-density Still Life + + SECTION("aspcomp2013_04") { + // Author: Christian Drescher + REQUIRE( + "([[lives(1,1),lives(1,2),lives(2,1),lives(2,3),lives(3,2),lives(3,4),lives(4,3),lives(4,4)]," + "[lives(1,2),lives(1,3),lives(2,1),lives(2,4),lives(3,1),lives(3,4),lives(4,2),lives(4,3)]," + "[lives(1,3),lives(1,4),lives(2,2),lives(2,4),lives(3,1),lives(3,3),lives(4,1),lives(4,2)]],[])" == IO::to_string(solve( + "%instance\n" + "\n" + "size(4).\n" + "\n" + "%encoding\n" + "\n" + "% possible coordinates\n" + "value(0).\n" + "value(V) :- value(V1), V=V1+1, size(N), V1<=N.\n" + "\n" + "step(-1).\n" + "step(1).\n" + "diff(X,0) :- step(X).\n" + "diff(0,Y) :- step(Y).\n" + "diff(X,Y) :- step(X), step(Y).\n" + "\n" + "% a cell may live, except for the ones at the border\n" + "{ lives(X,Y) } <= 1 :- value(X), value(Y), X>0, Y>0, size(N), X<=N, Y<=N.\n" + "\n" + "% cells with exactly 3 neighbours must live\n" + ":- #sum { 1,DX,DY : lives(X+DX,Y+DY), diff(DX,DY) } = 3, not lives(X,Y), value(X), value(Y).\n" + "\n" + "% living cells must have 2-3 living neighbours\n" + ":- lives(X,Y), not 2 <= #sum { 1,DX,DY : lives(X+DX,Y+DY), diff(DX,DY) } <= 3, value(X), value(Y).\n" + "\n" + "% connectedness\n" + "reached(XX,YY) :- XX = #min { X : lives(X,Y), value(X), value(Y) }, YY = #min { Y : lives(XX,Y), value(Y) }.\n" + "reached(XX,YY) :- reached(X,Y), value(X), value(Y), diff(DX,DY), XX=X+DX, YY=Y+DY, lives(XX,YY).\n" + ":- lives(X,Y), not reached(X,Y), value(X), value(Y).\n" + "\n" + "% maximise living cells\n" + "%#maximise { 1 : lives(X,Y), value(X), value(Y) }.\n" + ":~ value(X),value(Y), not lives(X,Y). [1,X,Y]\n", {"lives("}, {28}))); + } + +// {{{1 N05 Graceful Graphs + + SECTION("aspcomp2013_05") { + // Author: Christian Drescher + REQUIRE( + "([[value(a,0),value(b,1),value(c,3)]," + "[value(a,0),value(b,2),value(c,3)]," + "[value(a,0),value(b,3),value(c,1)]," + "[value(a,0),value(b,3),value(c,2)]," + "[value(a,1),value(b,0),value(c,3)]," + "[value(a,1),value(b,3),value(c,0)]," + "[value(a,2),value(b,0),value(c,3)]," + "[value(a,2),value(b,3),value(c,0)]," + "[value(a,3),value(b,0),value(c,1)]," + "[value(a,3),value(b,0),value(c,2)]," + "[value(a,3),value(b,1),value(c,0)]," + "[value(a,3),value(b,2),value(c,0)]],[])" == IO::to_string(solve( + "%instance\n" + "\n" + "edge(a,b). edge(b,c). edge(c,a).\n" + "\n" + "%encoding\n" + "\n" + "% nodes and values\n" + "node(X) :- edge(X,Y).\n" + "node(Y) :- edge(X,Y).\n" + "num_edges(N) :- N = #sum { 1,X,Y : edge(X,Y) }.\n" + "num(0).\n" + "num(N) :- num(N1), N=N1+1, num_edges(E), N<=E.\n" + "\n" + "% assignment to nodes\n" + "{ value(X,N) : num(N) } = 1 :- node(X).\n" + "\n" + "% assignment to edges\n" + "{ edge_value(edge(X,Y),N) : num(N), N>0 } = 1 :- edge(X,Y).\n" + "\n" + "% relates node values with edge values\n" + ":- not edge_value(edge(X,Y),M-N), edge(X,Y), value(X,M), value(Y,N), N < M.\n" + ":- not edge_value(edge(X,Y),N-M), edge(X,Y), value(X,M), value(Y,N), N > M.\n" + "\n" + "% alldifferent values\n" + ":- value(X,N), value(Y,N), num(N), X>>>>\n" + "1 <= { unload( P,T,L,S ) : \n" + " package( P ) , \n" + " truck( T ) , \n" + " location( L ); \n" + " load( P,T,L,S ) : \n" + " package( P ) , \n" + " truck( T ) , \n" + " location( L ); \n" + " drive( T,L1,L2,S ) : \n" + " fuelcost( Fueldelta,L1,L2 ) , \n" + " truck( T );\n" + " noop(S)\n" + " } <= 1 :- step(S), S > 0.\n" + "% <<<<< GENERATE\n" + "\n" + "% unload/4, effects\n" + "at( P,L,S ) :- unload( P,T,L,S ).\n" + "del( in( P,T ),S ) :- unload( P,T,L,S ).\n" + "\n" + "% load/4, effects\n" + "del( at( P,L ),S ) :- load( P,T,L,S ).\n" + "in( P,T,S ) :- load( P,T,L,S ).\n" + "\n" + "% drive/4, effects\n" + "del( at( T,L1 ), S ) :- drive( T,L1,L2,S ).\n" + "at( T,L2,S ) :- drive( T,L1,L2,S). \n" + "del( fuel( T,Fuelpre ),S ) :- drive( T,L1,L2,S ), fuel(T, Fuelpre,S-1).\n" + "fuel( T,Fuelpost,S ) :- drive( T,L1,L2,S ), fuelcost(Fueldelta,L1,L2), fuel(T,Fuelpre,S-1), Fuelpost = Fuelpre - Fueldelta.\n" + "% <<<<< EFFECTS APPLY\n" + "% \n" + "% INERTIA >>>>>\n" + "at( O,L,S ) :- at( O,L,S-1 ), not del( at( O,L ),S ), step(S).\n" + "in( P,T,S ) :- in( P,T,S-1 ), not del( in( P,T ),S ), step(S).\n" + "fuel( T,Level,S ) :- fuel( T,Level,S-1 ), not del( fuel( T,Level) ,S ), truck( T ), step(S).\n" + "% <<<<< INERTIA\n" + "\n" + "% PRECONDITIONS CHECK >>>>>\n" + "\n" + "% unload/4, preconditions\n" + " :- unload( P,T,L,S ), not preconditions_u( P,T,L,S ).\n" + "preconditions_u( P,T,L,S ) :- step(S), at( T,L,S-1 ), in( P,T,S-1 ), package( P ), truck( T ).\n" + "\n" + "% load/4, preconditions\n" + " :- load( P,T,L,S ), not preconditions_l( P,T,L,S ).\n" + "preconditions_l( P,T,L,S ) :- step(S), at( T,L,S-1 ), at( P,L,S-1 ).\n" + "\n" + "% drive/5, preconditions\n" + " :- drive( T,L1,L2,S ), not preconditions_d( T,L1,L2,S ).\n" + "preconditions_d( T,L1,L2,S ) :- step(S), at( T,L1,S-1 ), fuel( T, Fuelpre, S-1), fuelcost(Fueldelta,L1,L2), Fuelpre - Fueldelta >= 0.\n" + "% <<<<< PRECONDITIONS HOLD\n" + "\n" + "% GOAL CHECK\n" + "\n" + "goalreached :- step(S), N = #count{ P,L,S : at(P,L,S) , goal(P,L) }, N = #count{ P,L : goal(P,L) }.\n" + ":- not goalreached.\n", {"unload(", "drive(", "load("}))); + } + +// {{{1 N08 Sokoban + + SECTION("aspcomp2013_08") { + // Author: Giovambattista Ianni, Carlos Linares López*, Hootan Nakhost* + REQUIRE( + "([[move(player_01,pos_2_2,pos_3_2,dir_right,3),move(player_01,pos_3_2,pos_2_2,dir_left,2),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)]," + "[move(player_01,pos_3_2,pos_2_2,dir_left,2),noop(3),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)]," + "[move(player_01,pos_3_2,pos_2_2,dir_left,3),noop(1),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,2)]," + "[move(player_01,pos_3_2,pos_2_2,dir_left,3),noop(2),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)]," + "[noop(1),noop(2),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,3)]," + "[noop(1),noop(3),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,2)]," + "[noop(2),noop(3),pushtogoal(player_01,stone_01,pos_2_2,pos_3_2,pos_4_2,dir_right,1)]]," + "[-:135:39-40: info: global variable in tuple of aggregate element:\n T\n])" == IO::to_string(solve( + "% instance\n" + "\n" + "player(player_01).\n" + "stone(stone_01).\n" + "isgoal(pos_4_2).\n" + "isnongoal(pos_1_1).\n" + "isnongoal(pos_1_2).\n" + "isnongoal(pos_1_3).\n" + "isnongoal(pos_2_1).\n" + "isnongoal(pos_2_2).\n" + "isnongoal(pos_2_3).\n" + "isnongoal(pos_3_1).\n" + "isnongoal(pos_3_2).\n" + "isnongoal(pos_3_3).\n" + "isnongoal(pos_4_1).\n" + "isnongoal(pos_4_3).\n" + "isnongoal(pos_5_1).\n" + "isnongoal(pos_5_2).\n" + "isnongoal(pos_5_3).\n" + "movedir(pos_2_2,pos_3_2,dir_right).\n" + "movedir(pos_3_2,pos_2_2,dir_left).\n" + "movedir(pos_3_2,pos_4_2,dir_right).\n" + "movedir(pos_4_2,pos_3_2,dir_left).\n" + "at(player_01,pos_2_2).\n" + "at(stone_01,pos_3_2).\n" + "clear(pos_4_2).\n" + "goal(stone_01).\n" + "step(1).\n" + "step(2).\n" + "step(3).\n" + "\n" + "% encoding\n" + "\n" + "%\n" + "% Sokoban domain IPC 2008\n" + "%\n" + "% Adaptment from IPC 2008 domain description by GB Ianni, using the PDDL2ASP PLASP converter\n" + "% http://www.cs.uni-potsdam.de/wv/pdfformat/gekaknsc11a.pdf \n" + "%\n" + "% \n" + "\n" + "\n" + "% GENERATE >>>>>\n" + "1 <= { pushtonongoal( P,S,Ppos,From,To,Dir,T ) : \n" + " movedir( Ppos,From,Dir ) ,\n" + " movedir( From,To,Dir ) , \n" + " isnongoal( To ) , \n" + " player( P ) , \n" + " stone( S ) , Ppos != To , Ppos != From , From != To; \n" + " move( P,From,To,Dir,T ) : \n" + " movedir( From,To,Dir ) , \n" + " player( P ) , From != To;\n" + " pushtogoal( P,S,Ppos,From,To,Dir,T ) : \n" + " movedir( Ppos,From,Dir ) , \n" + " movedir( From,To,Dir ) , \n" + " isgoal( To ) , player( P ) , stone( S ) , Ppos != To , Ppos != From , From != To;\n" + " noop(T) } <= 1 :- step(T).\n" + "\n" + "% <<<<< GENERATE\n" + "% \n" + "\n" + "% \n" + "%\n" + "% Initial state\n" + "at(P,To,0) :- at(P,To).\n" + "clear(P,0) :- clear(P).\n" + "atgoal(S,0) :- isgoal(L), stone(S), at(S,L).\n" + " \n" + "% EFFECTS APPLY >>>>>\n" + "\n" + "% push-to-nongoal/7, effects\n" + "del( at( P,Ppos ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "del( at( S,From ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "del( clear( To ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "at( P,From,Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "at( S,To,Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "clear( Ppos,Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "del( atgoal( S ),Ti ) :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "\n" + "% move/5, effects\n" + "del( at( P,From ),Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n" + "del( clear( To ),Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n" + "at( P,To,Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n" + "clear( From,Ti ) :- move( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n" + "\n" + "% push-to-goal/7, effects\n" + "del( at( P,Ppos ),Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "del( at( S,From ),Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "del( clear( To ),Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "at( P,From,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "at( S,To,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "clear( Ppos,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "atgoal( S,Ti ) :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), \n" + " stone( S ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "% <<<<< EFFECTS APPLY\n" + "% \n" + "\n" + "% \n" + "% \n" + "% INERTIA >>>>>\n" + "clear( L,Ti ) :- clear( L,Ti-1 ), not del( clear( L ),Ti ), step(Ti).\n" + "atgoal( S,Ti ) :- atgoal( S,Ti-1 ), not del( atgoal( S ),Ti ), stone( S ), step(Ti).\n" + "at( T,L,Ti ) :- at( T,L,Ti-1 ), not del( at( T,L ) ,Ti ), step(Ti).\n" + "% <<<<< INERTIA\n" + "% \n" + "\n" + "% \n" + "% \n" + "% PRECONDITIONS HOLD >>>>>\n" + "\n" + "% push-to-nongoal/6, preconditions\n" + " :- pushtonongoal( P,S,Ppos,From,To,Dir,Ti ), not preconditions_png( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To.\n" + "preconditions_png( P,S,Ppos,From,To,Dir,Ti ) :- at( P,Ppos,Ti-1 ), at( S,From,Ti-1 ), clear( To,Ti-1 ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isnongoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To, step(Ti).\n" + "\n" + "% move/4, preconditions\n" + " :- move( P,From,To,Dir,Ti ), not preconditions_m( P,From,To,Dir,Ti ), movedir( From,To,Dir ), player( P ), From != To.\n" + "preconditions_m( P,From,To,Dir,Ti ) :- at( P,From,Ti-1 ), clear( To,Ti-1 ), movedir( From,To,Dir ), movedir( From,To,Dir ), player( P ), From != To, step(Ti).\n" + "\n" + "% push-to-goal/6, preconditions\n" + " :- pushtogoal( P,S,Ppos,From,To,Dir,Ti ), not preconditions_pg( P,S,Ppos,From,To,Dir,Ti ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To, step(Ti).\n" + "preconditions_pg( P,S,Ppos,From,To,Dir,Ti ) :- at( P,Ppos,Ti-1 ), at( S,From,Ti-1 ), clear( To,Ti-1 ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), movedir( Ppos,From,Dir ), movedir( From,To,Dir ), isgoal( To ), player( P ), stone( S ), Ppos != To, Ppos != From, From != To, step(Ti).\n" + "\n" + "% <<<<< PRECONDITIONS HOLD\n" + "% \n" + "%\n" + "% Goal Reached check \n" + "%\n" + "goalreached :- step(T), N = #count{ X,T : atgoal(X,T) , goal(X) }, N = #count{ X : goal(X) }.\n" + ":- not goalreached.\n" + "\n" + "% Gringo directives to show / hide particular literals\n" + "%#hide.\n" + "%#show pushtonongoal/7.\n" + "%#show move/5.\n" + "%#show pushtogoal/7.\n" + , {"pushtonongoal(", "pushtogoal(", "move(", "noop("}))); + } + +// {{{1 N09 Ricochet Robots + + SECTION("aspcomp2013_09") { + // Author: Julius Höfler, Martin Gebser, Philipp Obermeier, Roland Kaminski, Torsten Schaub + REQUIRE( + "([[go(blue,east,1,2),go(blue,east,2),go(blue,north,-1,1),go(blue,north,1),go(blue,south,-1,3),go(blue,south,3),go(red,east,1,4),go(red,east,4),go(red,south,-1,5),go(red,south,5)]," + "[go(blue,east,1,2),go(blue,east,2),go(blue,north,-1,1),go(blue,north,1),go(blue,south,-1,4),go(blue,south,4),go(red,east,1,3),go(red,east,3),go(red,south,-1,5),go(red,south,5)]," + "[go(blue,east,1,3),go(blue,east,3),go(blue,north,-1,1),go(blue,north,1),go(blue,south,-1,4),go(blue,south,4),go(red,east,1,2),go(red,east,2),go(red,south,-1,5),go(red,south,5)]," + "[go(blue,east,1,3),go(blue,east,3),go(blue,north,-1,2),go(blue,north,2),go(blue,south,-1,4),go(blue,south,4),go(red,east,1),go(red,east,1,1),go(red,south,-1,5),go(red,south,5)]," + "[go(blue,east,1,4),go(blue,east,4),go(blue,north,-1,1),go(blue,north,1),go(red,east,1,2),go(red,east,2),go(red,north,-1,5),go(red,north,5),go(red,south,-1,3),go(red,south,3)]," + "[go(blue,east,1,4),go(blue,east,4),go(blue,north,-1,2),go(blue,north,2),go(red,east,1),go(red,east,1,1),go(red,north,-1,5),go(red,north,5),go(red,south,-1,3),go(red,south,3)]," + "[go(blue,east,1,4),go(blue,east,4),go(blue,north,-1,3),go(blue,north,3),go(red,east,1),go(red,east,1,1),go(red,north,-1,5),go(red,north,5),go(red,south,-1,2),go(red,south,2)]," + "[go(green,south,-1,3),go(green,south,3),go(green,west,1,4),go(green,west,4),go(red,east,1),go(red,east,1,1),go(red,south,-1,5),go(red,south,5),go(yellow,west,1,2),go(yellow,west,2)]," + "[go(green,south,-1,3),go(green,south,3),go(green,west,1,4),go(green,west,4),go(red,east,1,2),go(red,east,2),go(red,south,-1,5),go(red,south,5),go(yellow,west,1),go(yellow,west,1,1)]," + "[go(green,south,-1,3),go(green,south,3),go(red,east,1),go(red,east,1,1),go(red,south,-1,5),go(red,south,5),go(yellow,east,1,4),go(yellow,east,4),go(yellow,west,1,2),go(yellow,west,2)]," + "[go(green,south,-1,3),go(green,south,3),go(red,east,1,2),go(red,east,2),go(red,south,-1,5),go(red,south,5),go(yellow,east,1,4),go(yellow,east,4),go(yellow,west,1),go(yellow,west,1,1)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "dim(1). dim(2). dim(3).\n" + "dim(4). dim(5).\n" + "\n" + "pos(red, 1,1). pos(blue, 1,5).\n" + "pos(green, 5,1). pos(yellow,5,5).\n" + "\n" + "barrier(1,2,south). barrier(4,3,east).\n" + "barrier(2,5,east).\n" + "\n" + "target(red,4,4).\n" + "\n" + "length(5).\n" + "\n" + "% encoding\n" + "\n" + "dir(west, -1, 0).\n" + "dir(east, 1, 0).\n" + "dir(north, 0,-1).\n" + "dir(south, 0, 1).\n" + "\n" + "dl(west, -1).\n" + "dl(north,-1).\n" + "dl(east, 1).\n" + "dl(south, 1).\n" + "\n" + "dir(west, 1). %dir(west, row).\n" + "dir(east, 1). %dir(east, row).\n" + "dir(north, -1). %dir(north,col).\n" + "dir(south, -1). %dir(south,col).\n" + "\n" + "dir(D) :- dir(D,_).\n" + "\n" + "robot(R) :- pos(R,_,_).\n" + "\n" + "pos(R,1,I,0) :- pos(R,I,_). %pos(R,row,I,0) :- pos(R,I,_).\n" + "pos(R,-1,J,0) :- pos(R,_,J). %pos(R,col,J,0) :- pos(R,_,J).\n" + "\n" + "barrier(I+1,J,west ) :- barrier(I,J,east ), dim(I), dim(J), dim(I+1).\n" + "barrier(I,J+1,north) :- barrier(I,J,south), dim(I), dim(J), dim(J+1).\n" + "barrier(I-1,J,east ) :- barrier(I,J,west ), dim(I), dim(J), dim(I-1).\n" + "barrier(I,J-1,south) :- barrier(I,J,north), dim(I), dim(J), dim(I-1).\n" + "\n" + "conn(D,I,J) :- dir(D,-1), dir(D,_,DJ), not barrier(I,J,D), dim(I), dim(J), dim(J+DJ). %conn(D,I,J) :- dir(D,col), dir(D,_,DJ), not barrier(I,J,D), dim(I), dim(J), dim(J+DJ).\n" + "conn(D,J,I) :- dir(D,1), dir(D,DI,_), not barrier(I,J,D), dim(I), dim(J), dim(I+DI). %conn(D,J,I) :- dir(D,row), dir(D,DI,_), not barrier(I,J,D), dim(I), dim(J), dim(I+DI).\n" + "\n" + "%step(1..X) :- length(X).\n" + "step(1).\n" + "step(X+1) :- step(X), length(L), X < L. \n" + "\n" + "1 <= { selectRobot(R,T) : robot(R) } <= 1 :- step(T).\n" + "1 <= { selectDir(D,O,T) : dir(D,O) } <= 1 :- step(T).\n" + "\n" + "go(R,D,O,T) :- selectRobot(R,T), selectDir(D,O,T).\n" + "go_(R,O,T) :- go(R,_,O,T).\n" + "go(R,D,T) :- go(R,D,_,T).\n" + "\n" + "sameLine(R,D,O,RR,T) :- go(R,D,O,T), pos(R,-O,L,T-1), pos(RR,-O,L,T-1), R != RR.\n" + "blocked(R,D,O,I+DI,T) :- go(R,D,O,T), pos(R,-O,L,T-1), not conn(D,L,I), dl(D,DI), dim(I), dim(I+DI).\n" + "blocked(R,D,O,L,T) :- sameLine(R,D,O,RR,T), pos(RR,O,L,T-1).\n" + "\n" + "reachable(R,D,O,I, T) :- go(R,D,O,T), pos(R,O,I,T-1).\n" + "reachable(R,D,O,I+DI,T) :- reachable(R,D,O,I,T), not blocked(R,D,O,I+DI,T), dl(D,DI), dim(I+DI).\n" + "\n" + ":- go(R,D,O,T), pos(R,O,I,T-1), blocked(R,D,O,I+DI,T), dl(D,DI).\n" + ":- go(R,D,O,T), go(R,DD,O,T-1).\n" + "\n" + "pos(R,O,I,T) :- reachable(R,D,O,I,T), not reachable(R,D,O,I+DI,T), dl(D,DI).\n" + "pos(R,O,I,T) :- pos(R,O,I,T-1), not go_(R,O,T), step(T).\n" + "\n" + "selectDir(O,T) :- selectDir(D,O,T).\n" + "\n" + ":- target(R,I,_), not pos(R,1,I,X), length(X). %:- target(R,I,_), not pos(R,row,I,X), length(X).\n" + ":- target(R,_,J), not pos(R,-1,J,X), length(X). %:- target(R,_,J), not pos(R,col,J,X), length(X).\n", {"go("}))); + } + +// {{{1 O10 Crossing Minimization + + SECTION("aspcomp2013_10") { + // Author: Carmine Dodaro, Graeme Gange*, Peter Stuckey* + REQUIRE( + "([[position(n1,1),position(n10,4),position(n11,1),position(n12,3),position(n13,8),position(n14,9),position(n15,5),position(n16,6),position(n17,2),position(n18,7),position(n19,1),position(n2,3),position(n20,7),position(n21,2),position(n22,3),position(n23,8),position(n24,9),position(n25,5),position(n26,4),position(n27,6),position(n3,7),position(n4,2),position(n5,8),position(n6,9),position(n7,6),position(n8,4),position(n9,5)]," + "[position(n1,1),position(n10,4),position(n11,1),position(n12,3),position(n13,8),position(n14,9),position(n15,5),position(n16,6),position(n17,2),position(n18,7),position(n19,2),position(n2,3),position(n20,7),position(n21,1),position(n22,3),position(n23,8),position(n24,9),position(n25,5),position(n26,4),position(n27,6),position(n3,7),position(n4,2),position(n5,8),position(n6,9),position(n7,6),position(n8,4),position(n9,5)]," + "[position(n1,1),position(n10,4),position(n11,1),position(n12,3),position(n13,8),position(n14,9),position(n15,5),position(n16,6),position(n17,2),position(n18,7),position(n19,3),position(n2,3),position(n20,7),position(n21,1),position(n22,2),position(n23,8),position(n24,9),position(n25,5),position(n26,4),position(n27,6),position(n3,7),position(n4,2),position(n5,8),position(n6,9),position(n7,6),position(n8,4),position(n9,5)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "layers(3).\n" + "width(0,9).\n" + "in_layer(0,n1). in_layer(0,n2). in_layer(0,n3). in_layer(0,n4). in_layer(0,n5). \n" + "in_layer(0,n6). in_layer(0,n7). in_layer(0,n8). in_layer(0,n9).\n" + "width(1,9).\n" + "in_layer(1,n10). in_layer(1,n11). in_layer(1,n12). in_layer(1,n13). in_layer(1,n14).\n" + "in_layer(1,n15). in_layer(1,n16). in_layer(1,n17). in_layer(1,n18).\n" + "width(2,9).\n" + "in_layer(2,n19). in_layer(2,n20). in_layer(2,n21). in_layer(2,n22). in_layer(2,n23).\n" + "in_layer(2,n24). in_layer(2,n25). in_layer(2,n26). in_layer(2,n27).\n" + "edge(n16,n20). edge(n10,n26). edge(n17,n26). edge(n10,n25). edge(n6,n14).\n" + "edge(n7,n15). edge(n6,n13). edge(n7,n10). edge(n18,n27). edge(n18,n20).\n" + "edge(n16,n27). edge(n12,n22). edge(n8,n12). edge(n18,n25). edge(n18,n23).\n" + "edge(n9,n18). edge(n3,n13). edge(n4,n12). edge(n11,n21). edge(n13,n24).\n" + "edge(n1,n11). edge(n15,n25). edge(n11,n22). edge(n17,n25). edge(n17,n21).\n" + "edge(n12,n27). edge(n7,n13). edge(n9,n10). edge(n14,n24). edge(n16,n25).\n" + "edge(n5,n13). edge(n12,n25). \n" + "\n" + ":- not position(n1,1).\n" + ":- not position(n2,3).\n" + ":- not position(n23,8).\n" + ":- not position(n24,9).\n" + ":- not position(n26,4).\n" + ":- not position(n27,6).\n" + ":- not position(n3,7).\n" + ":- not position(n4,2).\n" + ":- position(n10,1).\n" + ":- position(n10,2).\n" + ":- position(n10,3).\n" + ":- position(n10,5).\n" + ":- position(n10,6).\n" + ":- position(n10,7).\n" + ":- position(n10,8).\n" + ":- position(n10,9).\n" + ":- position(n11,2).\n" + ":- position(n15,2).\n" + ":- position(n15,3).\n" + ":- position(n15,4).\n" + ":- position(n15,6).\n" + ":- position(n16,3).\n" + ":- position(n16,4).\n" + ":- position(n16,5).\n" + ":- position(n16,7).\n" + ":- position(n17,9).\n" + ":- position(n18,1).\n" + ":- position(n18,2).\n" + ":- position(n18,3).\n" + ":- position(n18,4).\n" + ":- position(n18,5).\n" + ":- position(n18,6).\n" + ":- position(n18,8).\n" + ":- position(n18,9).\n" + ":- position(n19,5).\n" + ":- position(n19,6).\n" + ":- position(n19,7).\n" + ":- position(n19,8).\n" + ":- position(n23,1).\n" + ":- position(n23,2).\n" + ":- position(n23,3).\n" + ":- position(n23,5).\n" + ":- position(n23,6).\n" + ":- position(n23,7).\n" + ":- position(n23,9).\n" + ":- position(n24,1).\n" + ":- position(n24,2).\n" + ":- position(n24,3).\n" + ":- position(n24,4).\n" + ":- position(n24,5).\n" + "\n" + "% encoding\n" + "\n" + "%%guess\n" + "pvalue(L,0) :- width(L,_).\n" + "pvalue(L,X+1) :- pvalue(L,X), width(L,T), X < T.\n" + "position( Node, Pos ) | not_position( Node, Pos ) :- in_layer( Layer, Node ), width( Layer, T ), Pos = P + 1, \n" + " pvalue(Layer,P), P < T.\n" + "\n" + "%%check\n" + "%a node must be assigned at most at one position.\n" + ":- position( Node1, Pos1 ), position( Node1, Pos2 ), Pos1 < Pos2.\n" + "\n" + "%two nodes of the same layer cannot be assigned at the same position.\n" + ":- in_layer( Layer1, Node1 ), in_layer( Layer1, Node2 ), position( Node1, Pos1 ), position( Node2, Pos1 ), Node1 != Node2.\n" + "\n" + "%a node must be assigned at least at one position. \n" + "node_assigned_at_position( Node ) :- position( Node, Pos ).\n" + ":- in_layer( Layer1, Node1 ), not node_assigned_at_position( Node1 ).\n" + "\n" + "\n" + "%%optimization\n" + "%Computing the edges from same layers.\n" + "edge_from_same_layers(Node1,Node2,Node3,Node4):- edge(Node1,Node2), edge(Node3,Node4), Node1 < Node3, Node2 != Node4, in_layer(Layer,Node1), in_layer(Layer,Node3).\n" + "\n" + "%Computing all the crossings.\n" + "crossing(Node1,Node2,Node3,Node4) :- edge_from_same_layers(Node1,Node2,Node3,Node4), antecedent(Node1,Node3), antecedent(Node4,Node2). \n" + "crossing(Node1,Node2,Node3,Node4) :- edge_from_same_layers(Node1,Node2,Node3,Node4), antecedent(Node3,Node1), antecedent(Node2,Node4).\n" + "\n" + "% A node Node1 is an antecedent of a node Node2 if they are in the same layer and the Node1 position is antecedent of the Node2 position.\n" + "antecedent(Node1,Node2):- in_layer(Layer,Node1), in_layer(Layer,Node2), Node1 != Node2, position(Node1,Pos1), position(Node2,Pos2), Pos1 < Pos2.\n" + "\n" + "% Assign a penalty to each violation of the crossing.\n" + ":~ crossing(Node1, Node2, Node3, Node4 ). [1,Node1,Node2,Node3,Node4]\n", {"position("}, {15}))); + } + +// N11: needs queries +// N12: needs queries +// {{{1 O13 Solitaire + + SECTION("aspcomp2013_13") { + // Author: Marcello Balduccini, Yuliya Lierler* + REQUIRE( + "([[move(1,left,6,3),move(2,right,3,3),move(3,up,3,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,right,2,3),move(2,up,2,5),move(3,up,3,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,right,2,3),move(2,up,3,5),move(3,left,4,3),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,right,2,3),move(2,up,3,5),move(3,left,5,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,right,2,3),move(2,up,3,5),move(3,right,1,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,right,2,3),move(2,up,3,5),move(3,up,2,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,up,4,5),move(2,left,6,4),move(3,right,2,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,up,4,5),move(2,right,2,4),move(3,right,2,5),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,up,4,5),move(2,right,2,5),move(3,down,2,3),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,up,4,5),move(2,right,2,5),move(3,left,6,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]," + "[move(1,up,4,5),move(2,right,2,5),move(3,right,2,4),move(4,left,5,5),move(5,left,7,5),move(6,down,7,3)]]," + "[-:56:22-23: info: global variable in tuple of aggregate element:\n T\n" + ",-:51:76-93: info: atom does not occur in any rule head:\n checking_solution\n" + ",-:56:94-111: info: atom does not occur in any rule head:\n checking_solution\n])" == IO::to_string(solve( + "% instance\n" + "\n" + "time(1). time(2). time(3). time(4). time(5). time(6).\n" + "full(3,1). full(4,1). full(5,1). full(3,2). full(4,2). full(5,2).\n" + "full(1,3). full(2,3). full(3,3). empty(4,3). full(5,3). full(6,3).\n" + "full(7,3). full(1,4). full(2,4). full(3,4). full(4,4). full(5,4).\n" + "full(6,4). full(7,4). full(1,5). full(2,5). full(3,5). full(4,5).\n" + "full(5,5). full(6,5). full(7,5). full(3,6). full(4,6). full(5,6).\n" + "full(3,7). full(4,7). full(5,7).\n" + "\n" + ":- not move(6,down,7,3).\n" + ":- not move(4,left,5,5).\n" + "\n" + "% encoding\n" + "\n" + "% 2x2 squares in the corner aren't used\n" + "range(1).\n" + "range(X+1) :- range(X), X < 7.\n" + "\n" + "location(1,X) :- range(X), 3 <= X, X <= 5.\n" + "location(2,X) :- range(X), 3 <= X, X <= 5.\n" + "location(Y,X) :- range(Y), 3 <= X, X <= 5, range(X).\n" + "location(6,X) :- range(X), 3 <= X, X <= 5.\n" + "location(7,X) :- range(X), 3 <= X, X <= 5.\n" + "\n" + "% Moves can be made in one of four directions\n" + "direction(up).\n" + "direction(down).\n" + "direction(left).\n" + "direction(right).\n" + "\n" + "% Each location is either full or empty\n" + "status(full).\n" + "status(empty).\n" + "\n" + "% Can move a full location over a full location to an empty one.\n" + "possibleMove(T,up,X,Y) :- state(T,full,X,Y), state(T,full,X,Y-1), state(T,empty,X,Y-2),\n" + " time(T), location(X,Y), location(X,Y-1), location(X,Y-2).\n" + "\n" + "possibleMove(T,down,X,Y) :- state(T,full,X,Y), state(T,full,X,Y+1), state(T,empty,X,Y+2),\n" + " time(T), location(X,Y), location(X,Y+1), location(X,Y+2).\n" + "\n" + "possibleMove(T,left,X,Y) :- state(T,full,X,Y), state(T,full,X-1,Y), state(T,empty,X-2,Y),\n" + " time(T), location(X,Y), location(X-1,Y), location(X-2,Y).\n" + "\n" + "possibleMove(T,right,X,Y) :- state(T,full,X,Y), state(T,full,X+1,Y), state(T,empty,X+2,Y),\n" + " time(T), location(X,Y), location(X+1,Y), location(X+2,Y).\n" + "\n" + "\n" + "%% At each time step choose a move\n" + "1 <= { move(T,D,X,Y) : direction(D) , location(X,Y) } <= 1 :- time(T), not checking_solution.\n" + "\n" + "%% CHECKER [marcy 011111]\n" + "%% Exactly one move must be present at each step.\n" + "%% Only needed if the choice rule is not enabled.\n" + ":- not 1 <= #count { T,D,X,Y : move(T,D,X,Y) , direction(D) , location(X,Y) } <= 1, time(T), checking_solution.\n" + "\n" + "% A move must be possible\n" + " :- move(T,D,X,Y), not possibleMove(T,D,X,Y), time(T), direction(D), location(X,Y).\n" + "\n" + "% Now need to look at the effect of moves\n" + "% (section location parameter to cut grounding size)\n" + "state(T+1,empty,X,Y) :- move(T,up,X,Y), location(X,Y), time(T).\n" + "state(T+1,empty,X,Y-1) :- move(T,up,X,Y), location(X,Y), location(X,Y-1), time(T).\n" + "state(T+1,full,X,Y-2) :- move(T,up,X,Y), location(X,Y), location(X,Y-2), time(T).\n" + "\n" + "state(T+1,empty,X,Y) :- move(T,down,X,Y), location(X,Y), time(T).\n" + "state(T+1,empty,X,Y+1) :- move(T,down,X,Y), location(X,Y), location(X,Y+1), time(T).\n" + "state(T+1,full,X,Y+2) :- move(T,down,X,Y), location(X,Y), location(X,Y+2), time(T).\n" + "\n" + "state(T+1,empty,X,Y) :- move(T,left,X,Y), location(X,Y), time(T).\n" + "state(T+1,empty,X-1,Y) :- move(T,left,X,Y), location(X,Y), location(X-1,Y), time(T).\n" + "state(T+1,full,X-2,Y) :- move(T,left,X,Y), location(X,Y), location(X-2,Y), time(T).\n" + "\n" + "state(T+1,empty,X,Y) :- move(T,right,X,Y), location(X,Y), time(T).\n" + "state(T+1,empty,X+1,Y) :- move(T,right,X,Y), location(X,Y), location(X+1,Y), time(T).\n" + "state(T+1,full,X+2,Y) :- move(T,right,X,Y), location(X,Y), location(X+2,Y), time(T).\n" + "\n" + "\n" + "changed(T+1,X,Y) :- move(T,up,X,Y), location(X,Y), time(T).\n" + "changed(T+1,X,Y-1) :- move(T,up,X,Y), location(X,Y), location(X,Y-1), time(T).\n" + "changed(T+1,X,Y-2) :- move(T,up,X,Y), location(X,Y), location(X,Y-2), time(T).\n" + "\n" + "changed(T+1,X,Y) :- move(T,down,X,Y), location(X,Y), time(T).\n" + "changed(T+1,X,Y+1) :- move(T,down,X,Y), location(X,Y), location(X,Y+1), time(T).\n" + "changed(T+1,X,Y+2) :- move(T,down,X,Y), location(X,Y), location(X,Y+2), time(T).\n" + "\n" + "changed(T+1,X,Y) :- move(T,left,X,Y), location(X,Y), time(T).\n" + "changed(T+1,X-1,Y) :- move(T,left,X,Y), location(X,Y), location(X-1,Y), time(T).\n" + "changed(T+1,X-2,Y) :- move(T,left,X,Y), location(X,Y), location(X-2,Y), time(T).\n" + "\n" + "changed(T+1,X,Y) :- move(T,right,X,Y), location(X,Y), time(T).\n" + "changed(T+1,X+1,Y) :- move(T,right,X,Y), location(X,Y), location(X+1,Y), time(T).\n" + "changed(T+1,X+2,Y) :- move(T,right,X,Y), location(X,Y), location(X+2,Y), time(T).\n" + "\n" + "state(T+1,S,X,Y) :- not changed(T+1,X,Y), state(T,S,X,Y), status(S), location(X,Y), time(T).\n" + "\n" + "state(1,full,X,Y) :- full(X,Y).\n" + "state(1,empty,X,Y) :- empty(X,Y).\n", {"move("}))); + } + + +// {{{1 O14 Weighted-Sequence Problem + + SECTION("aspcomp2013_14") { + // Author: Marcello Balduccini, Yuliya Lierlier, Shaden Smith + REQUIRE( + "([[leafPos(1,0),leafPos(2,1),leafPos(3,2),posColor(1,blue),posColor(2,red)]," + "[leafPos(1,0),leafPos(2,1),leafPos(3,2),posColor(1,green),posColor(2,red)]," + "[leafPos(1,0),leafPos(2,1),leafPos(3,2),posColor(1,red),posColor(2,red)]," + "[leafPos(1,2),leafPos(2,1),leafPos(3,0),posColor(1,blue),posColor(2,red)]," + "[leafPos(1,2),leafPos(2,1),leafPos(3,0),posColor(1,green),posColor(2,red)]," + "[leafPos(1,2),leafPos(2,1),leafPos(3,0),posColor(1,red),posColor(2,red)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "leafWeightCardinality(1,45,44). leafWeightCardinality(2,21,3). leafWeightCardinality(3,64,74).\n" + "\n" + "innerNode(1). innerNode(2).\n" + "\n" + "num(3). max_total_weight(495).\n" + "\n" + ":- not leafPos(2,1).\n" + ":- not posColor(2,red).\n" + "\n" + "% encoding\n" + "\n" + "color(red).\n" + "color(blue).\n" + "color(green).\n" + "\n" + "leafWeight(X,W) :-leafWeightCardinality(X,W,C).\n" + "\n" + "leafCard(X,C) :-leafWeightCardinality(X,W,C).\n" + "\n" + "leaf(X):-leafWeightCardinality(X,W,C).\n" + "\n" + "%%\n" + "%% Sequence Definition\n" + "%%\n" + "\n" + "coloredPos(1).\n" + "coloredPos(X+1):- coloredPos(X), X < N-1, num(N).\n" + "%coloredPos(X):- X=1..N-1, num(N).\n" + "location(0).\n" + "location(X+1) :- location(X), X < N-1, num(N).\n" + "%location(X):-X=0..N-1, num(N).\n" + "\n" + "1 <= {leafPos(L,N) : location(N) } <= 1 :- leaf(L).\n" + "% No sharing locations\n" + "%:- leafPos(L1, N), leafPos(L2, N), location(N), L1 != L2.\n" + "1 <= { leafPos(L,N) : leaf(L) } <= 1 :- location(N).\n" + "\n" + "%%\n" + "%% each node at colordPos has a unique color\n" + "%%\n" + "1 <= {posColor(P,C):color(C)} <= 1:-coloredPos(P).\n" + "\n" + "% BEGIN Weight T definition\n" + "\n" + "% if color of X is green\n" + "% weight(X) = weight(right child of X) + cardinality(right child of X) \n" + "%\n" + "nWeight(0,W):- leafWeightCardinality(L,W,C), leafPos(L,0).\n" + "\n" + "nWeight(P,W):- W= W1+C, posColor(P,green),\n" + " leafWeight(R,W1), leafCard(R,C),\n" + " coloredPos(P), leafPos(R,P), leaf(R), W<=M, max_total_weight(M).\n" + "\n" + "\n" + "\n" + "\n" + "% if color of X is red\n" + "% weight(X) = weight(right child of X) + weight(left child of X) \n" + "nWeight(P,W):- W= W1+W2, posColor(P,red),\n" + " leafWeight(R,W1),nWeight(P-1,W2),\n" + " coloredPos(P), leafPos(R,P),\n" + " leaf(R), W<=M, max_total_weight(M).\n" + "\n" + "\n" + "\n" + "% if color(X) is blue\n" + "% weight(X) = cardinality(right child of X) + weight(left child of X) \n" + "nWeight(P,W):- W= W1+C, posColor(P,blue),\n" + " leafCard(R,C), nWeight(P-1,W1),\n" + " coloredPos(P),leafPos(R,P), \n" + " leaf(R), W<=M, max_total_weight(M).\n" + "\n" + "%%\n" + "%% Weights related Tests\n" + "%%\n" + "\n" + "%% \n" + "%% definition of a total weight of a prime tree T'\n" + "tWeight(1,W):-nWeight(1,W), coloredPos(1), W<=M, max_total_weight(M).\n" + "tWeight(N,W):-W=W1+W2, tWeight(N-1,W1), nWeight(N,W2),coloredPos(N),N>1, W<=M, max_total_weight(M).\n" + "\n" + "% END Weight T definition\n" + "% --------------------------------------------------------------\n" + "% --------------------------------------------------------------\n" + "% --------------------------------------------------------------\n" + "% exists Definition\n" + "\n" + "exists:-tWeight(N-1,W), W<=M, max_total_weight(M),num(N).\n" + ":-not exists.\n", {"leafPos(", "posColor("}))); + } + +// {{{1 O15 Stable Marriage + + SECTION("aspcomp2013_15") { + // Author: Mario Alviano, Carmine Dodaro, Francesco Ricca + REQUIRE( + "([[match(m_1,w_1),match(m_2,w_3),match(m_3,w_2),match(m_4,w_4)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "manAssignsScore(m_1,w_1,4). manAssignsScore(m_1,w_2,2). manAssignsScore(m_1,w_3,2). manAssignsScore(m_1,w_4,1).\n" + "manAssignsScore(m_2,w_1,2). manAssignsScore(m_2,w_2,1). manAssignsScore(m_2,w_3,4). manAssignsScore(m_2,w_4,3).\n" + "manAssignsScore(m_3,w_1,1). manAssignsScore(m_3,w_2,3). manAssignsScore(m_3,w_3,2). manAssignsScore(m_3,w_4,2).\n" + "manAssignsScore(m_4,w_1,2). manAssignsScore(m_4,w_2,3). manAssignsScore(m_4,w_3,4). manAssignsScore(m_4,w_4,1).\n" + "\n" + "womanAssignsScore(w_1,m_1,3). womanAssignsScore(w_1,m_2,4). womanAssignsScore(w_1,m_3,2). womanAssignsScore(w_1,m_4,1).\n" + "womanAssignsScore(w_2,m_1,1). womanAssignsScore(w_2,m_2,4). womanAssignsScore(w_2,m_3,3). womanAssignsScore(w_2,m_4,2).\n" + "womanAssignsScore(w_3,m_1,4). womanAssignsScore(w_3,m_2,2). womanAssignsScore(w_3,m_3,3). womanAssignsScore(w_3,m_4,1).\n" + "womanAssignsScore(w_4,m_1,3). womanAssignsScore(w_4,m_2,2). womanAssignsScore(w_4,m_3,4). womanAssignsScore(w_4,m_4,1).\n" + "\n" + "% encoding\n" + "\n" + "% guess matching\n" + "match(M,W) :- manAssignsScore(M,_,_), womanAssignsScore(W,_,_), not nonMatch(M,W).\n" + "nonMatch(M,W) :- manAssignsScore(M,_,_), womanAssignsScore(W,_,_), not match(M,W).\n" + "\n" + "% no polygamy\n" + ":- match(M1,W), match(M,W), M <> M1.\n" + ":- match(M,W), match(M,W1), W <> W1.\n" + "\n" + "% no singles\n" + "jailed(M) :- match(M,_).\n" + ":- manAssignsScore(M,_,_), not jailed(M).\n" + "\n" + "% strong stability condition\n" + ":- match(M,W1), manAssignsScore(M,W,Smw), W1 <> W, manAssignsScore(M,W1,Smw1), Smw > Smw1,\n" + " match(M1,W), womanAssignsScore(W,M,Swm), womanAssignsScore(W,M1,Swm1), Swm >= Swm1.\n" + , {"match("}))); + } + +// {{{1 O16 Incremental Scheduling + + SECTION("aspcomp2013_16") { + // Author: Marcello Balduccini, Yuliya Lierler* + REQUIRE( + "([[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,0),penalty(j3,2),start(j1,0),start(j2,4),start(j3,9),tot_penalty(2)]," + "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,1),penalty(j3,0),start(j1,0),start(j2,6),start(j3,2),tot_penalty(1)]," + "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,2),penalty(j3,0),start(j1,0),start(j2,7),start(j3,2),tot_penalty(2)]," + "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,2),penalty(j3,0),start(j1,0),start(j2,7),start(j3,3),tot_penalty(2)]," + "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,3),penalty(j3,0),start(j1,0),start(j2,8),start(j3,2),tot_penalty(3)]," + "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,3),penalty(j3,0),start(j1,0),start(j2,8),start(j3,3),tot_penalty(3)]," + "[on_instance(j1,1),on_instance(j2,2),on_instance(j3,2),penalty(j2,3),penalty(j3,0),start(j1,0),start(j2,8),start(j3,4),tot_penalty(3)]]," + "[-:33:51-68: info: atom does not occur in any rule head:\n checking_solution\n" + ",-:34:83-100: info: atom does not occur in any rule head:\n checking_solution\n])" == IO::to_string(solve( + "% instance\n" + "\n" + "max_value(20).\n" + "device(d1). instances(d1,1).\n" + "device(d2). instances(d2,2).\n" + "offline_instance(d2,1).\n" + "%\n" + "job(j1). job_device(j1,d1). job_len(j1,4).\n" + "job(j2). job_device(j2,d2). job_len(j2,5). deadline(j2,10). importance(j2,1).\n" + "precedes(j1,j2).\n" + "job(j3). job_device(j3,d2). job_len(j3,4). deadline(j3,12). importance(j3,2).\n" + "%\n" + "max_total_penalty(3).\n" + "%\n" + "curr_job_start(j1,0). curr_on_instance(j1,1).\n" + "curr_job_start(j2,4). curr_on_instance(j2,1).\n" + "%\n" + "curr_time(2).\n" + "\n" + "% encoding\n" + "\n" + "time(0).\n" + "time(T+1) :- time(T), T < MT, max_value(MT).\n" + "%time(0..MT) :- max_value(MT).\n" + "\n" + "pen_value(T) :- time(T).\n" + "td_value(T) :- time(T).\n" + "\n" + "instance_of(D,1) :- device(D).\n" + "instance_of(D,I+1) :- device(D), instance_of(D,I), instances(D,N), I < N.\n" + "\n" + "% Pick a unique start time and instance for each job\n" + "1 <= { start(J,S) : time(S) } <= 1 :- job(J), not checking_solution.\n" + "1 <= { on_instance(J,I) : instance_of(D,I) } <= 1 :- job(J), job_device(J,D), not checking_solution.\n" + "\n" + "%----------------------\n" + "% - overlap\n" + "%----------------------\n" + ":- on_instance(J1,I), on_instance(J2,I), J1 != J2,\n" + " job_device(J1,D), job_device(J2,D),\n" + " start(J1,S1), job_len(J1,L1),\n" + " start(J2,S2),\n" + " S1 <= S2, S2 < S1 + L1.\n" + "\n" + "\n" + "%----------------------\n" + "% - order\n" + "%----------------------\n" + ":- precedes(J1,J2),\n" + " start(J1,S1), job_len(J1,L1),\n" + " start(J2,S2),\n" + " S2 < S1 + L1.\n" + "\n" + "\n" + "%-------------------------------------\n" + "% - completion -- total-tardiness\n" + "%-------------------------------------\n" + "td(J,S + L - D) :-\n" + " job(J),\n" + " start(J,S), job_len(J,L),\n" + " deadline(J,D),\n" + " S + L > D.\n" + "\n" + "td(J,0) :-\n" + " job(J),\n" + " start(J,S), job_len(J,L),\n" + " deadline(J,D),\n" + " S + L <= D.\n" + "\n" + "%-------------------------------------\n" + "% - completion -- penalty\n" + "%-------------------------------------\n" + "\n" + "penalty(J,TD * I) :-\n" + " job(J),\n" + " td(J,TD),\n" + " importance(J,I).\n" + "\n" + ":- penalty(J,P),\n" + " max_value(MV),\n" + " P > MV.\n" + "\n" + "tot_penalty(TP) :-\n" + " pen_value(TP),\n" + " TP = #sum{ P,J : penalty(J,P) }.\n" + "\n" + "%\n" + "% If the value of the total penalty would be greater than the\n" + "% maximum allowed value of pen_value(_), the above rule\n" + "% does not define tot_penalty(_).\n" + "% In that case, the solution is not acceptable.\n" + "%\n" + "has_tot_penalty :-\n" + " tot_penalty(TP).\n" + "-has_tot_penalty :-\n" + " not has_tot_penalty.\n" + ":- -has_tot_penalty.\n" + "\n" + ":- pen_value(TP), tot_penalty(TP), max_total_penalty(K),\n" + " TP > K.\n" + "\n" + "%----------------------\n" + "% - instance assignment\n" + "%----------------------\n" + "\n" + ":- on_instance(J1,I), on_instance(J2,I),\n" + " job_device(J1,D), job_device(J2,D),\n" + " instances(D,N), N > 1,\n" + " J1 != J2,\n" + " start(J1,S1), start(J2,S2),\n" + " job_len(J1,L1),\n" + " S1 <= S2, S2 < S1 + L1.\n" + "\n" + ":- on_instance(J,I),\n" + " device(D),\n" + " job(J), job_device(J,D),\n" + " offline_instance(D,I),\n" + " must_schedule(J).\n" + "\n" + "%----------------------\n" + "% - current schedule\n" + "%----------------------\n" + "\n" + "already_started(J) :-\n" + " curr_job_start(J,S),\n" + " curr_time(CT),\n" + " CT > S.\n" + "\n" + "already_finished(J) :-\n" + " curr_job_start(J,S),\n" + " job_len(J,L),\n" + " curr_time(CT),\n" + " CT >= S + L.\n" + "\n" + "must_schedule(J) :-\n" + " job(J),\n" + " not must_not_schedule(J).\n" + "\n" + "must_not_schedule(J) :-\n" + " already_started(J),\n" + " not rescheduled(J).\n" + "\n" + "rescheduled(J) :-\n" + " already_started(J),\n" + " not already_finished(J),\n" + " job_device(J,D),\n" + " curr_on_instance(J,I),\n" + " offline_instance(D,I).\n" + "\n" + ":- start(J,S),\n" + " curr_time(CT),\n" + " S < CT,\n" + " device(D),\n" + " job_device(J,D),\n" + " time(S),\n" + " must_schedule(J).\n" + "\n" + ":- start(J,S),\n" + " curr_job_start(J,CS),\n" + " S != CS,\n" + " job_device(J,D),\n" + " must_not_schedule(J).\n" + "\n" + ":- on_instance(J,I),\n" + " curr_on_instance(J,CI),\n" + " I != CI,\n" + " must_not_schedule(J).\n" + , {"start(","on_instance(","penalty(","tot_penalty(","rescheduled("}))); + } + +// {{{1 N17 Qualitative Spatial Reasoning + + SECTION("aspcomp2013_17") { + // Author: Jason Jingshi Li +#ifndef _MSC_VER + REQUIRE( + "([[label(0,1,rpi),label(0,2,rd),label(1,2,rd)]," + "[label(0,1,rpi),label(0,2,rf),label(1,2,rd)]," + "[label(0,1,rpi),label(0,2,rmi),label(1,2,rd)]," + "[label(0,1,rpi),label(0,2,roi),label(1,2,rd)]," + "[label(0,1,rpi),label(0,2,rpi),label(1,2,rd)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "% Csp\n" + "node1(0..2). node2(0..2).\n" + "% 0 1 ( DC )\n" + "lc(0,1,rEQ). lc(0,1,rEC). lc(0,1,rPO).\n" + "lc(0,1,rTPP). lc(0,1,rNTPP). lc(0,1,rTPPI).\n" + "lc(0,1,rNTPPI).\n" + "% 1 2 ( PO )\n" + "lc(1,2,rEQ). lc(1,2,rDC). lc(1,2,rEC).\n" + "lc(1,2,rTPP). lc(1,2,rNTPP). lc(1,2,rTPPI).\n" + "lc(1,2,rNTPPI).\n" + "\n" + ":- not label(1,2,rd).\n" + ":- not label(0,1,rpi).\n" + "\n" + "% encoding\n" + "\n" + "% A Disjunctive Logic Program for IA Constraint Networks \n" + "\n" + "% relations \n" + "rel(req).\n" + "rel(rp).\n" + "rel(rpi).\n" + "rel(rd).\n" + "rel(rdi).\n" + "rel(ro).\n" + "rel(roi).\n" + "rel(rm).\n" + "rel(rmi).\n" + "rel(rs).\n" + "rel(rsi).\n" + "rel(rf).\n" + "rel(rfi).\n" + "% Choice rule for clasp\n" + "1 <= {label(X,Y,L) : rel(L)} <= 1 :- node1(X), node2(Y), X \n" + "label(X,Z,rpi) :- label(X,Y,req), label(Y,Z,rpi).\n" + "% req o rd = rd \n" + "label(X,Z,rd) :- label(X,Y,req), label(Y,Z,rd).\n" + "% req o rdi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,req), label(Y,Z,rdi).\n" + "% req o rs = rs \n" + "label(X,Z,rs) :- label(X,Y,req), label(Y,Z,rs).\n" + "% req o rsi = rsi \n" + "label(X,Z,rsi) :- label(X,Y,req), label(Y,Z,rsi).\n" + "% req o rf = rf \n" + "label(X,Z,rf) :- label(X,Y,req), label(Y,Z,rf).\n" + "% req o rfi = rfi \n" + "label(X,Z,rfi) :- label(X,Y,req), label(Y,Z,rfi).\n" + "% req o rm = rm \n" + "label(X,Z,rm) :- label(X,Y,req), label(Y,Z,rm).\n" + "% req o rmi = rmi \n" + "label(X,Z,rmi) :- label(X,Y,req), label(Y,Z,rmi).\n" + "% req o ro = ro \n" + "label(X,Z,ro) :- label(X,Y,req), label(Y,Z,ro).\n" + "% req o roi = roi \n" + "label(X,Z,roi) :- label(X,Y,req), label(Y,Z,roi).\n" + "% rp o req = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,req).\n" + "% rp o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rp).\n" + "% rp o rpi = r= < > d di s si f fi m mi o oi \n" + "label(X,Z,req) | label(X,Z,rp) | label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,rmi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rp), label(Y,Z,rpi).\n" + "% rp o rd = r< d s m o \n" + "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,rd).\n" + "% rp o rdi = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rdi).\n" + "% rp o rs = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rs).\n" + "% rp o rsi = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rsi).\n" + "% rp o rf = r< d s m o \n" + "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,rf).\n" + "% rp o rfi = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rfi).\n" + "% rp o rm = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,rm).\n" + "% rp o rmi = r< d s m o \n" + "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,rmi).\n" + "% rp o ro = r< \n" + "label(X,Z,rp) :- label(X,Y,rp), label(Y,Z,ro).\n" + "% rp o roi = r< d s m o \n" + "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rp), label(Y,Z,roi).\n" + "% rpi o req = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,req).\n" + "% rpi o rp = r= < > d di s si f fi m mi o oi \n" + "label(X,Z,req) | label(X,Z,rp) | label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,rmi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rp).\n" + "% rpi o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rpi).\n" + "% rpi o rd = r> d f mi oi \n" + "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rd).\n" + "% rpi o rdi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rdi).\n" + "% rpi o rs = r> d f mi oi \n" + "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rs).\n" + "% rpi o rsi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rsi).\n" + "% rpi o rf = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rf).\n" + "% rpi o rfi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rfi).\n" + "% rpi o rm = r> d f mi oi \n" + "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,rm).\n" + "% rpi o rmi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,rmi).\n" + "% rpi o ro = r> d f mi oi \n" + "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rpi), label(Y,Z,ro).\n" + "% rpi o roi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rpi), label(Y,Z,roi).\n" + "% rd o req = rd \n" + "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,req).\n" + "% rd o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,rd), label(Y,Z,rp).\n" + "% rd o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rd), label(Y,Z,rpi).\n" + "% rd o rd = rd \n" + "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,rd).\n" + "% rd o rdi = r= < > d di s si f fi m mi o oi \n" + "label(X,Z,req) | label(X,Z,rp) | label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,rmi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rd), label(Y,Z,rdi).\n" + "% rd o rs = rd \n" + "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,rs).\n" + "% rd o rsi = r> d f mi oi \n" + "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rd), label(Y,Z,rsi).\n" + "% rd o rf = rd \n" + "label(X,Z,rd) :- label(X,Y,rd), label(Y,Z,rf).\n" + "% rd o rfi = r< d s m o \n" + "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rd), label(Y,Z,rfi).\n" + "% rd o rm = r< \n" + "label(X,Z,rp) :- label(X,Y,rd), label(Y,Z,rm).\n" + "% rd o rmi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rd), label(Y,Z,rmi).\n" + "% rd o ro = r< d s m o \n" + "label(X,Z,rp) | label(X,Z,rd) | label(X,Z,rs) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rd), label(Y,Z,ro).\n" + "% rd o roi = r> d f mi oi \n" + "label(X,Z,rpi) | label(X,Z,rd) | label(X,Z,rf) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rd), label(Y,Z,roi).\n" + "% rdi o req = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,req).\n" + "% rdi o rp = r< di fi m o \n" + "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,rp).\n" + "% rdi o rpi = r> di si mi oi \n" + "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rpi).\n" + "% rdi o rd = r= d di s si f fi o oi \n" + "label(X,Z,req) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rd).\n" + "% rdi o rdi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,rdi).\n" + "% rdi o rs = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,rs).\n" + "% rdi o rsi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,rsi).\n" + "% rdi o rf = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rf).\n" + "% rdi o rfi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rdi), label(Y,Z,rfi).\n" + "% rdi o rm = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,rm).\n" + "% rdi o rmi = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,rmi).\n" + "% rdi o ro = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rdi), label(Y,Z,ro).\n" + "% rdi o roi = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rdi), label(Y,Z,roi).\n" + "% rs o req = rs \n" + "label(X,Z,rs) :- label(X,Y,rs), label(Y,Z,req).\n" + "% rs o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,rs), label(Y,Z,rp).\n" + "% rs o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rs), label(Y,Z,rpi).\n" + "% rs o rd = rd \n" + "label(X,Z,rd) :- label(X,Y,rs), label(Y,Z,rd).\n" + "% rs o rdi = r< di fi m o \n" + "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rs), label(Y,Z,rdi).\n" + "% rs o rs = rs \n" + "label(X,Z,rs) :- label(X,Y,rs), label(Y,Z,rs).\n" + "% rs o rsi = r= s si \n" + "label(X,Z,req) | label(X,Z,rs) | label(X,Z,rsi) :- label(X,Y,rs), label(Y,Z,rsi).\n" + "% rs o rf = rd \n" + "label(X,Z,rd) :- label(X,Y,rs), label(Y,Z,rf).\n" + "% rs o rfi = r< m o \n" + "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rs), label(Y,Z,rfi).\n" + "% rs o rm = r< \n" + "label(X,Z,rp) :- label(X,Y,rs), label(Y,Z,rm).\n" + "% rs o rmi = rmi \n" + "label(X,Z,rmi) :- label(X,Y,rs), label(Y,Z,rmi).\n" + "% rs o ro = r< m o \n" + "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rs), label(Y,Z,ro).\n" + "% rs o roi = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rs), label(Y,Z,roi).\n" + "% rsi o req = rsi \n" + "label(X,Z,rsi) :- label(X,Y,rsi), label(Y,Z,req).\n" + "% rsi o rp = r< di fi m o \n" + "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rsi), label(Y,Z,rp).\n" + "% rsi o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rsi), label(Y,Z,rpi).\n" + "% rsi o rd = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rsi), label(Y,Z,rd).\n" + "% rsi o rdi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rsi), label(Y,Z,rdi).\n" + "% rsi o rs = r= s si \n" + "label(X,Z,req) | label(X,Z,rs) | label(X,Z,rsi) :- label(X,Y,rsi), label(Y,Z,rs).\n" + "% rsi o rsi = rsi \n" + "label(X,Z,rsi) :- label(X,Y,rsi), label(Y,Z,rsi).\n" + "% rsi o rf = roi \n" + "label(X,Z,roi) :- label(X,Y,rsi), label(Y,Z,rf).\n" + "% rsi o rfi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rsi), label(Y,Z,rfi).\n" + "% rsi o rm = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rsi), label(Y,Z,rm).\n" + "% rsi o rmi = rmi \n" + "label(X,Z,rmi) :- label(X,Y,rsi), label(Y,Z,rmi).\n" + "% rsi o ro = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,rsi), label(Y,Z,ro).\n" + "% rsi o roi = roi \n" + "label(X,Z,roi) :- label(X,Y,rsi), label(Y,Z,roi).\n" + "% rf o req = rf \n" + "label(X,Z,rf) :- label(X,Y,rf), label(Y,Z,req).\n" + "% rf o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,rf), label(Y,Z,rp).\n" + "% rf o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rf), label(Y,Z,rpi).\n" + "% rf o rd = rd \n" + "label(X,Z,rd) :- label(X,Y,rf), label(Y,Z,rd).\n" + "% rf o rdi = r> di si mi oi \n" + "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rf), label(Y,Z,rdi).\n" + "% rf o rs = rd \n" + "label(X,Z,rd) :- label(X,Y,rf), label(Y,Z,rs).\n" + "% rf o rsi = r> mi oi \n" + "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rf), label(Y,Z,rsi).\n" + "% rf o rf = rf \n" + "label(X,Z,rf) :- label(X,Y,rf), label(Y,Z,rf).\n" + "% rf o rfi = r= f fi \n" + "label(X,Z,req) | label(X,Z,rf) | label(X,Z,rfi) :- label(X,Y,rf), label(Y,Z,rfi).\n" + "% rf o rm = rm \n" + "label(X,Z,rm) :- label(X,Y,rf), label(Y,Z,rm).\n" + "% rf o rmi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rf), label(Y,Z,rmi).\n" + "% rf o ro = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rf), label(Y,Z,ro).\n" + "% rf o roi = r> mi oi \n" + "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rf), label(Y,Z,roi).\n" + "% rfi o req = rfi \n" + "label(X,Z,rfi) :- label(X,Y,rfi), label(Y,Z,req).\n" + "% rfi o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,rfi), label(Y,Z,rp).\n" + "% rfi o rpi = r> di si mi oi \n" + "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rfi), label(Y,Z,rpi).\n" + "% rfi o rd = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rfi), label(Y,Z,rd).\n" + "% rfi o rdi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rfi), label(Y,Z,rdi).\n" + "% rfi o rs = ro \n" + "label(X,Z,ro) :- label(X,Y,rfi), label(Y,Z,rs).\n" + "% rfi o rsi = rdi \n" + "label(X,Z,rdi) :- label(X,Y,rfi), label(Y,Z,rsi).\n" + "% rfi o rf = r= f fi \n" + "label(X,Z,req) | label(X,Z,rf) | label(X,Z,rfi) :- label(X,Y,rfi), label(Y,Z,rf).\n" + "% rfi o rfi = rfi \n" + "label(X,Z,rfi) :- label(X,Y,rfi), label(Y,Z,rfi).\n" + "% rfi o rm = rm \n" + "label(X,Z,rm) :- label(X,Y,rfi), label(Y,Z,rm).\n" + "% rfi o rmi = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rfi), label(Y,Z,rmi).\n" + "% rfi o ro = ro \n" + "label(X,Z,ro) :- label(X,Y,rfi), label(Y,Z,ro).\n" + "% rfi o roi = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,rfi), label(Y,Z,roi).\n" + "% rm o req = rm \n" + "label(X,Z,rm) :- label(X,Y,rm), label(Y,Z,req).\n" + "% rm o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rp).\n" + "% rm o rpi = r> di si mi oi \n" + "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,rm), label(Y,Z,rpi).\n" + "% rm o rd = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rm), label(Y,Z,rd).\n" + "% rm o rdi = r< \n" + "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rdi).\n" + "% rm o rs = rm \n" + "label(X,Z,rm) :- label(X,Y,rm), label(Y,Z,rs).\n" + "% rm o rsi = rm \n" + "label(X,Z,rm) :- label(X,Y,rm), label(Y,Z,rsi).\n" + "% rm o rf = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rm), label(Y,Z,rf).\n" + "% rm o rfi = r< \n" + "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rfi).\n" + "% rm o rm = r< \n" + "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,rm).\n" + "% rm o rmi = r= f fi \n" + "label(X,Z,req) | label(X,Z,rf) | label(X,Z,rfi) :- label(X,Y,rm), label(Y,Z,rmi).\n" + "% rm o ro = r< \n" + "label(X,Z,rp) :- label(X,Y,rm), label(Y,Z,ro).\n" + "% rm o roi = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,rm), label(Y,Z,roi).\n" + "% rmi o req = rmi \n" + "label(X,Z,rmi) :- label(X,Y,rmi), label(Y,Z,req).\n" + "% rmi o rp = r< di fi m o \n" + "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,rmi), label(Y,Z,rp).\n" + "% rmi o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rpi).\n" + "% rmi o rd = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rmi), label(Y,Z,rd).\n" + "% rmi o rdi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rdi).\n" + "% rmi o rs = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rmi), label(Y,Z,rs).\n" + "% rmi o rsi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rsi).\n" + "% rmi o rf = rmi \n" + "label(X,Z,rmi) :- label(X,Y,rmi), label(Y,Z,rf).\n" + "% rmi o rfi = rmi \n" + "label(X,Z,rmi) :- label(X,Y,rmi), label(Y,Z,rfi).\n" + "% rmi o rm = r= s si \n" + "label(X,Z,req) | label(X,Z,rs) | label(X,Z,rsi) :- label(X,Y,rmi), label(Y,Z,rm).\n" + "% rmi o rmi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,rmi).\n" + "% rmi o ro = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,rmi), label(Y,Z,ro).\n" + "% rmi o roi = r> \n" + "label(X,Z,rpi) :- label(X,Y,rmi), label(Y,Z,roi).\n" + "% ro o req = ro \n" + "label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,req).\n" + "% ro o rp = r< \n" + "label(X,Z,rp) :- label(X,Y,ro), label(Y,Z,rp).\n" + "% ro o rpi = r> di si mi oi \n" + "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,ro), label(Y,Z,rpi).\n" + "% ro o rd = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rd).\n" + "% ro o rdi = r< di fi m o \n" + "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rdi).\n" + "% ro o rs = ro \n" + "label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rs).\n" + "% ro o rsi = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rsi).\n" + "% ro o rf = rd s o \n" + "label(X,Z,rd) | label(X,Z,rs) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rf).\n" + "% ro o rfi = r< m o \n" + "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,rfi).\n" + "% ro o rm = r< \n" + "label(X,Z,rp) :- label(X,Y,ro), label(Y,Z,rm).\n" + "% ro o rmi = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,ro), label(Y,Z,rmi).\n" + "% ro o ro = r< m o \n" + "label(X,Z,rp) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,ro), label(Y,Z,ro).\n" + "% ro o roi = r= d di s si f fi o oi \n" + "label(X,Z,req) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,ro), label(Y,Z,roi).\n" + "% roi o req = roi \n" + "label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,req).\n" + "% roi o rp = r< di fi m o \n" + "label(X,Z,rp) | label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,rm) | label(X,Z,ro) :- label(X,Y,roi), label(Y,Z,rp).\n" + "% roi o rpi = r> \n" + "label(X,Z,rpi) :- label(X,Y,roi), label(Y,Z,rpi).\n" + "% roi o rd = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rd).\n" + "% roi o rdi = r> di si mi oi \n" + "label(X,Z,rpi) | label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rdi).\n" + "% roi o rs = rd f oi \n" + "label(X,Z,rd) | label(X,Z,rf) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rs).\n" + "% roi o rsi = r> mi oi \n" + "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rsi).\n" + "% roi o rf = roi \n" + "label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rf).\n" + "% roi o rfi = rdi si oi \n" + "label(X,Z,rdi) | label(X,Z,rsi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,rfi).\n" + "% roi o rm = rdi fi o \n" + "label(X,Z,rdi) | label(X,Z,rfi) | label(X,Z,ro) :- label(X,Y,roi), label(Y,Z,rm).\n" + "% roi o rmi = r> \n" + "label(X,Z,rpi) :- label(X,Y,roi), label(Y,Z,rmi).\n" + "% roi o ro = r= d di s si f fi o oi \n" + "label(X,Z,req) | label(X,Z,rd) | label(X,Z,rdi) | label(X,Z,rs) | label(X,Z,rsi) | label(X,Z,rf) | label(X,Z,rfi) | label(X,Z,ro) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,ro).\n" + "% roi o roi = r> mi oi \n" + "label(X,Z,rpi) | label(X,Z,rmi) | label(X,Z,roi) :- label(X,Y,roi), label(Y,Z,roi).\n" + , {"label("}))); +#endif + } + +// N18 too big +// {{{1 N19 Abstract Dialectical Frameworks Well-founded Model + + SECTION("aspcomp2013_19") { + // Author: Stefan Ellmauthaler, Johannes Wallner + REQUIRE( + "([[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]," + "[accept(1),accept(2),reject(4)]]," + "[-:74:15-16: info: global variable in tuple of aggregate element:\n I\n" + ",-:82:21-22: info: global variable in tuple of aggregate element:\n I\n])" == IO::to_string(solve( + "% instance\n" + "\n" + "statement(1). statement(2). statement(3). statement(4). \n" + "ac(1,c(v)). ac(2,1). ac(3,or(neg(3),4)). ac(4,c(f)). \n" + "\n" + "% encoding\n" + "\n" + "% splitting a formula into its subformulas\n" + "subformula2(X,F) :- ac(X,F),statement(X).\n" + "subformula2(X,F) :- subformula2(X,and(F,_)).\n" + "subformula2(X,F) :- subformula2(X,and(_,F)).\n" + "subformula2(X,F) :- subformula2(X,or(_,F)).\n" + "subformula2(X,F) :- subformula2(X,or(F,_)).\n" + "subformula2(X,F) :- subformula2(X,neg(F)).\n" + "subformula2(X,F) :- subformula2(X,xor(F,_)).\n" + "subformula2(X,F) :- subformula2(X,xor(_,F)).\n" + "subformula2(X,F) :- subformula2(X,imp(F,_)).\n" + "subformula2(X,F) :- subformula2(X,imp(_,F)).\n" + "subformula2(X,F) :- subformula2(X,iff(F,_)).\n" + "subformula2(X,F) :- subformula2(X,iff(_,F)).\n" + "subformula(F) :- subformula2(_,F).\n" + "\n" + "% decide whether a subformula is an atom or not\n" + "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=and(F1,F2).\n" + "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=or(F1,F2).\n" + "noatom(F) :- subformula(F), subformula(F1), F=neg(F1).\n" + "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=xor(F1,F2).\n" + "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=imp(F1,F2).\n" + "noatom(F) :- subformula(F), subformula(F1), subformula(F2), F=iff(F1,F2).\n" + "\n" + "atom(X) :- subformula(X), not noatom(X).\n" + "atom(X) :- subformula(X), X=c(v).\n" + "atom(X) :- subformula(X), X=c(f).\n" + "\n" + "% check whether an interpretation is a model or not at a specific iteration\n" + "ismodel(X,I) :- atom(X), in(X,I).\n" + "ismodel(X,I) :- atom(X), X=c(v), iteration(I).\n" + "ismodel(F,I) :- subformula(F), subformula(F1), F=neg(F1), nomodel(F1,I).\n" + "ismodel(F,I) :- subformula(F), F=and(F1,F2), ismodel(F1,I), ismodel(F2,I).\n" + "ismodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=or(F1,F2), ismodel(F1,I).\n" + "ismodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=or(F1,F2), ismodel(F2,I).\n" + "ismodel(F,I) :- subformula(F), F=xor(F1,F2), ismodel(F1,I), nomodel(F2,I).\n" + "ismodel(F,I) :- subformula(F), F=xor(F1,F2), ismodel(F2,I), nomodel(F1,I).\n" + "ismodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=imp(F1,F2), nomodel(F1,I).\n" + "ismodel(F,I) :- subformula(F), F=imp(F1,F2), ismodel(F1,I), ismodel(F2,I).\n" + "ismodel(F,I) :- subformula(F), F=iff(F1,F2), ismodel(F1,I), ismodel(F2,I).\n" + "ismodel(F,I) :- subformula(F), F=iff(F1,F2), nomodel(F1,I), nomodel(F2,I).\n" + "\n" + "nomodel(X,I) :- atom(X), out(X,I).\n" + "nomodel(X,I) :- atom(X), X=c(f), iteration(I).\n" + "nomodel(F,I) :- subformula(F), subformula(F1), F=neg(F1), ismodel(F1,I).\n" + "nomodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=and(F1,F2), nomodel(F1,I).\n" + "nomodel(F,I) :- subformula(F), subformula(F1), subformula(F2), F=and(F1,F2), nomodel(F2,I).\n" + "nomodel(F,I) :- subformula(F), F=or(F1,F2), nomodel(F1,I), nomodel(F2,I).\n" + "nomodel(F,I) :- subformula(F), F=xor(F1,F2), ismodel(F1,I), ismodel(F2,I).\n" + "nomodel(F,I) :- subformula(F), F=xor(F1,F2), nomodel(F1,I), nomodel(F2,I).\n" + "nomodel(F,I) :- subformula(F), F=imp(F1,F2), ismodel(F1,I), nomodel(F2,I).\n" + "nomodel(F,I) :- subformula(F), F=iff(F1,F2), nomodel(F1,I), ismodel(F2,I).\n" + "nomodel(F,I) :- subformula(F), F=iff(F1,F2), nomodel(F2,I), ismodel(F1,I).\n" + "\n" + "% get the number of statements and create an ordering\n" + "snum(I) :- I = #count{Y : statement(Y)}.\n" + "iteration(I) :- snum(J), I=J-1.\n" + "iteration(I) :- iteration(J), I=J-1, I>=0.\n" + "\n" + "% create undecided set of variables at the starting point of the function\n" + "undec(X,I) :- snum(I), statement(X).\n" + "\n" + "% iterate the function one step further, and guess an additional element for A or R\n" + "inA(X,I) :- inA(X,J), J=I+1, iteration(I).\n" + "inR(X,I) :- inR(X,J), J=I+1, iteration(I).\n" + "select(X,I) :- not deselect(X,I), statement(X), iteration(I), undec(X,J), J=I+1.\n" + "deselect(X,I) :- not select(X,I), statement(X), iteration(I), undec(X,J), J=I+1.\n" + ":- A=#count { I,X : select(X,I)}, iteration(I), A>1.\n" + "undec(X,I) :- iteration(I), undec(X,J), J=I+1, deselect(X,I).\n" + "% check whether the selected element is in A or not.\n" + "in(X,I) | out(X,I) :- undec(X,J), J=I+1, iteration(I).\n" + "in(X,I) :- iteration(I), J=I+1, inA(X,J).\n" + "out(X,I) :- iteration(I), J=I+1, inR(X,J).\n" + "\n" + "okA(I) :- select(X,I), ac(X,F), ismodel(F,I).\n" + "okA(I) :- A= #count{I,X : select(X,I)}, iteration(I), A=0.\n" + "inA(X,I) :- okA(I), select(X,I).\n" + "\n" + "in(X,I) :- okA(I), undec(X,J), J=I+1, iteration(I).\n" + "out(X,I) :- okA(I), undec(X,J), J=I+1, iteration(I).\n" + "\n" + "\n" + "% check whether the selected element is in R or not.\n" + "okR(I) :- select(X,I), ac(X,F), nomodel(F,I), not okA(I).\n" + "in(X,I) :- okR(I), undec(X,J), J=I+1, iteration(I).\n" + "out(X,I) :- okR(I), undec(X,J), J=I+1, iteration(I).\n" + "inR(X,I) :- okR(I), select(X,I).\n" + "\n" + "ok(I) :- okA(I).\n" + "ok(I) :- okR(I).\n" + "\n" + ":- not ok(I), iteration(I).\n" + "\n" + "accept(X) :- inA(X,0).\n" + "reject(X) :- inR(X,0).\n" + "\n" + ":~ statement(X), not accept(X). [1@2,X]\n" + ":~ statement(X), not reject(X). [1@1,X]\n" + "%#maximize [accept(X)@2].\n" + "%#maximize [reject(X)@1].\n" + , {"accept(", "reject("}, {2, 3}))); + } + +// {{{1 N20 Visit-all + + SECTION("aspcomp2013_20") { + // Author: Giovambattista Ianni,Nir Lipovetzky*, Carlos Linares López* + REQUIRE( + "([[move(x1y1,x2y1,3),move(x2y1,x1y1,2),move(x2y1,x3y1,4),move(x2y2,x2y1,1),move(x2y2,x2y3,7),move(x2y3,x1y3,8),move(x3y1,x3y2,5),move(x3y2,x2y2,6)]," + "[move(x1y1,x2y1,3),move(x2y1,x1y1,2),move(x2y1,x3y1,4),move(x2y2,x2y1,1),move(x2y3,x1y3,8),move(x3y1,x3y2,5),move(x3y2,x3y3,6),move(x3y3,x2y3,7)]," + "[move(x1y1,x2y1,5),move(x2y1,x1y1,4),move(x2y1,x2y2,6),move(x2y2,x2y3,7),move(x2y2,x3y2,1),move(x2y3,x1y3,8),move(x3y1,x2y1,3),move(x3y2,x3y1,2)]," + "[move(x1y3,x2y3,3),move(x2y1,x1y1,8),move(x2y2,x2y3,1),move(x2y2,x3y2,5),move(x2y3,x1y3,2),move(x2y3,x2y2,4),move(x3y1,x2y1,7),move(x3y2,x3y1,6)]," + "[move(x1y3,x2y3,3),move(x2y1,x1y1,8),move(x2y2,x2y3,1),move(x2y3,x1y3,2),move(x2y3,x3y3,4),move(x3y1,x2y1,7),move(x3y2,x3y1,6),move(x3y3,x3y2,5)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "connected(x1y1,x2y1). connected(x2y1,x1y1). \n" + "connected(x2y1,x3y1). connected(x3y1,x2y1).\n" + "\n" + "connected(x2y2,x3y2). connected(x3y2,x2y2).\n" + "\n" + "connected(x1y3,x2y3). connected(x2y3,x1y3). \n" + "connected(x2y3,x3y3). connected(x3y3,x2y3).\n" + "\n" + "connected(x2y1,x2y2). connected(x2y2,x2y1).\n" + "connected(x2y2,x2y3). connected(x2y3,x2y2).\n" + "\n" + "connected(x3y1,x3y2). connected(x3y2,x3y1).\n" + "connected(x3y2,x3y3). connected(x3y3,x3y2).\n" + "\n" + "at(x2y2).\n" + "\n" + "visit(x1y1). visit(x2y1). visit(x3y1).\n" + "visit(x2y2). visit(x3y2).\n" + "visit(x1y3). visit(x2y3).\n" + "\n" + "step(1). step(2). step(3).\n" + "step(4). step(5). step(6).\n" + "step(7). step(8).\n" + "\n" + "% encoding\n" + "\n" + "%\n" + "% initial status\n" + "%\n" + "visited(X) :- at(X).\n" + "atrobot(X,0) :- at(X).\n" + "\n" + "% GENERATE >>>>>\n" + "1 <= { move( Curpos,Nextpos,T ) : connected( Curpos,Nextpos ) , Curpos != Nextpos } <= 1 :- step(T).\n" + "% <<<<< GENERATE\n" + "% \n" + "\n" + "% \n" + "% \n" + "% EFFECTS APPLY >>>>>\n" + "\n" + "% move/3, effects\n" + "atrobot( Nextpos,T ) :- move( Curpos,Nextpos,T ).\n" + "del( atrobot( Curpos ),T ) :- move( Curpos,Nextpos,T ).\n" + "visited( Nextpos ) :- move( Curpos,Nextpos,T ).\n" + "% <<<<< EFFECTS APPLY\n" + "% \n" + "\n" + "% \n" + "% \n" + "% INERTIA >>>>>\n" + "atrobot( X,T ) :- step(T), atrobot( X,T-1 ), not del( atrobot( X ) ,T ).\n" + "%\n" + "% GB: it is not needed to let 'visited' subject to timestamping \n" + "%\n" + "% <<<<< INERTIA\n" + "% \n" + "\n" + "% \n" + "% \n" + "% PRECONDITIONS HOLD >>>>>\n" + "\n" + "% move/3, preconditions\n" + " :- move( Curpos,Nextpos,T ), not atrobot(Curpos, T-1), step(T).\n" + "% <<<<< PRECONDITIONS HOLD\n" + "% \n" + "\n" + "goalreached :- N = #count{ X : visited(X) , visit(X) }, N = #count{ X : visit(X) }.\n" + ":- not goalreached.\n" + "\n" + , {"move("}))); + } + +// {{{1 N21 Complex Optimization of Answer Sets + + SECTION("aspcomp2013_21") { + // Author: Martin Gebser, Roland Kaminski, Torsten Schaub + REQUIRE( + "([[hold(atom(a)),hold(atom(c)),hold(atom(s)),hold(atom(t)),hold(conjunction(2)),hold(conjunction(4)),hold(conjunction(6)),hold(conjunction(7)),hold(conjunction(8))]," + "[hold(atom(a)),hold(atom(d)),hold(atom(p)),hold(atom(r)),hold(conjunction(0)),hold(conjunction(1)),hold(conjunction(3)),hold(conjunction(4))]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "wlist(0,0,pos(atom(q)),1). wlist(0,1,pos(atom(r)),1). \n" + "set(0,neg(atom(c))). rule(pos(sum(0,0,2)),pos(conjunction(0))).\n" + "set(1,pos(atom(r))). rule(pos(atom(a)),pos(conjunction(1))).\n" + "set(2,neg(atom(d))). rule(pos(sum(0,0,2)),pos(conjunction(2))).\n" + "set(3,neg(atom(t))). rule(pos(atom(d)),pos(conjunction(3))).\n" + "wlist(1,0,pos(atom(p)),1). wlist(1,1,pos(atom(t)),1).\n" + "set(4,pos(atom(a))). set(4,neg(atom(b))).\n" + "rule(pos(sum(0,1,2)),pos(conjunction(4))). set(5,pos(atom(t))).\n" + "set(5,neg(atom(r))). set(5,neg(atom(s))).\n" + "rule(pos(atom(b)),pos(conjunction(5))). set(6,neg(atom(r))).\n" + "set(6,neg(atom(q))). rule(pos(atom(s)),pos(conjunction(6))).\n" + "set(7,pos(atom(s))). rule(pos(atom(a)),pos(conjunction(7))).\n" + "rule(pos(atom(a)),pos(conjunction(3))). set(8,neg(atom(p))).\n" + "rule(pos(atom(c)),pos(conjunction(8))). set(9,pos(atom(a))).\n" + "set(9,neg(atom(t))). set(9,neg(atom(b))).\n" + "set(9,neg(atom(p))). rule(pos(false),pos(conjunction(9))).\n" + "set(10,pos(atom(q))). set(10,pos(atom(r))).\n" + "set(10,neg(atom(c))). rule(pos(false),pos(conjunction(10))).\n" + "set(11,pos(atom(q))). set(11,pos(atom(r))). set(11,neg(atom(d))).\n" + "rule(pos(false),pos(conjunction(11))). set(12,pos(atom(r))).\n" + "set(12,pos(atom(t))). set(12,neg(atom(b))). set(12,neg(atom(q))).\n" + "rule(pos(false),pos(conjunction(12))).\n" + "wlist(2,0,pos(atom(q)),1). wlist(2,1,pos(atom(r)),1).\n" + "wlist(2,2,pos(atom(p)),1). wlist(2,3,pos(atom(s)),1).\n" + "\n" + "minimize(1,2). optimize(1,1,incl).\n" + "\n" + ":- not hold(atom(r)), not hold(atom(t)).\n" + "\n" + "% encoding\n" + "\n" + "eleb(P) :- rule(_,pos(P)).\n" + "\n" + "nhold(conjunction(S)) :- eleb(conjunction(S)), not hold(P), set(S,pos(P)).\n" + "nhold(conjunction(S)) :- eleb(conjunction(S)), hold(P), set(S,neg(P)).\n" + " hold(conjunction(S)) :- eleb(conjunction(S)), not nhold(conjunction(S)).\n" + "\n" + "hold(atom(A)) :- rule(pos(atom(A)), pos(B)), hold(B).\n" + " :- rule(pos(false), pos(B)), hold(B).\n" + "{ hold(P) : wlist(S,_,pos(P),_) } :- rule(pos(sum(_,S,_)),pos(B)), hold(B).\n" + "\n" + "elem(E) :- eleb(E).\n" + "elem(E) :- rule(pos(E),_).\n" + "elem(P) :- rule(pos(sum(_,S,_)),_), wlist(S,_,pos(P),_).\n" + "elem(P) :- minimize(J,S), wlist(S,_,pos(P),W).\n" + "\n" + "supp(atom(A),B) :- rule(pos(atom(A)), pos(B)).\n" + "supp(atom(A),B) :- rule(pos(sum(_,S,_)),pos(B)), wlist(S,_,pos(atom(A)),_).\n" + "\n" + "supp(atom(A)) :- supp(atom(A),B).\n" + "\n" + "set(S) :- set(S,E).\n" + "fact(atom(A)) :- rule(pos(atom(A)),pos(conjunction(S))), not set(S).\n" + "\n" + "true(atom(A)) :- fact(atom(A)).\n" + "true(atom(A)) | fail(atom(A)) :- supp(atom(A)), not fact(atom(A)).\n" + " fail(atom(A)) :- elem(atom(A)), not supp(atom(A)).\n" + "\n" + "fail(false).\n" + "\n" + "sett(S,0,P) :- set(S,P).\n" + "sett(S,N+1,P2) :- sett(S,N,P1), sett(S,N,P2), P1 < P2.\n" + "\n" + "setn(S,N,P) :- sett(S,N,P), not sett(S,N+1,P).\n" + "setn(S,N) :- setn(S,N,_).\n" + "\n" + "true(conjunction(S),N+1) :- elem(conjunction(S)), setn(S,N), not setn(S,N+1).\n" + "true(conjunction(S),N) :- elem(conjunction(S)), true(P), setn(S,N,pos(P)), true(conjunction(S),N+1).\n" + "true(conjunction(S),N) :- elem(conjunction(S)), fail(P), setn(S,N,neg(P)), true(conjunction(S),N+1).\n" + "\n" + "true(conjunction(S)) :- true(conjunction(S),0).\n" + "fail(conjunction(S)) :- elem(conjunction(S)), set(S,pos(P)), fail(P).\n" + "fail(conjunction(S)) :- elem(conjunction(S)), set(S,neg(N)), true(N).\n" + "\n" + "suppt(S,0,P) :- supp(S,P).\n" + "suppt(S,N+1,P2) :- suppt(S,N,P1), suppt(S,N,P2), P1 < P2.\n" + "\n" + "suppn(S,N,P) :- suppt(S,N,P), not suppt(S,N+1,P).\n" + "suppn(S,N) :- suppn(S,N,_).\n" + "\n" + "suppf(S,N+1) :- suppn(S,N), not suppn(S,N+1).\n" + "suppf(S,N) :- fail(P), suppn(S,N,P), suppf(S,N+1).\n" + "\n" + "bot :- true(atom(A)), suppf(atom(A),0).\n" + "bot :- rule(pos(H),pos(B)), true(B), fail(H).\n" + "\n" + "true(atom(A)) :- supp(atom(A)), not fact(atom(A)), bot.\n" + "fail(atom(A)) :- supp(atom(A)), not fact(atom(A)), bot.\n" + "\n" + "target(P,N) :- minimize(_,S), wlist(S,N,pos(P),_).\n" + "target(N) :- target(P,N).\n" + "\n" + "equal(N+1) :- target(N), not target(N+1).\n" + "equal(N) :- target(P,N), true(P), hold(P), equal(N+1).\n" + "equal(N) :- target(P,N), fail(P), not hold(P), equal(N+1).\n" + "\n" + "bot :- equal(0).\n" + "bot :- target(P,_), true(P), not hold(P).\n" + "\n" + ":- not bot.\n" + "\n" + , {"hold("}))); + } + +// {{{1 N22 Knight Tour with Holes + + SECTION("aspcomp2013_22") { + // Author: Francesco Calimeri, Neng-Fa Zhou* + REQUIRE( + "([[move(1,1,2,3),move(1,2,3,1),move(1,3,2,1),move(1,4,2,2),move(1,5,2,7),move(1,6,2,8),move(1,7,3,8),move(1,8,3,7),move(2,1,1,3),move(2,2,4,1),move(2,3,3,1),move(2,4,1,6),move(2,5,1,7),move(2,6,3,8),move(2,7,4,8),move(2,8,1,6),move(3,1,2,3),move(3,2,5,1),move(3,3,2,1),move(3,4,1,3),move(3,5,1,6),move(3,6,1,7),move(3,7,5,8),move(3,8,1,7),move(4,1,2,2),move(4,2,2,1),move(4,3,2,2),move(4,4,2,3),move(4,5,3,7),move(4,6,2,7),move(4,7,2,8),move(4,8,2,7),move(5,1,7,2),move(5,2,3,1),move(5,3,7,2),move(5,4,7,3),move(5,5,6,7),move(5,6,4,8),move(5,7,7,8),move(5,8,3,7),move(6,1,8,2),move(6,2,4,1),move(6,3,8,2),move(6,4,8,3),move(6,5,8,6),move(6,6,8,7),move(6,7,4,8),move(6,8,8,7),move(7,1,8,3),move(7,2,5,1),move(7,3,6,1),move(7,4,8,2),move(7,5,8,7),move(7,6,6,8),move(7,7,5,8),move(7,8,8,6),move(8,1,6,2),move(8,2,6,1),move(8,3,6,2),move(8,4,7,2),move(8,5,7,3),move(8,6,7,8),move(8,7,6,8),move(8,8,6,7)]," + "[move(1,1,2,3),move(1,2,3,1),move(1,3,2,1),move(1,4,2,2),move(1,5,2,7),move(1,6,2,8),move(1,7,3,8),move(1,8,3,7),move(2,1,1,3),move(2,2,4,1),move(2,3,3,1),move(2,4,1,6),move(2,5,1,7),move(2,6,3,8),move(2,7,4,8),move(2,8,1,6),move(3,1,2,3),move(3,2,5,1),move(3,3,2,1),move(3,4,1,3),move(3,5,1,6),move(3,6,1,7),move(3,7,5,8),move(3,8,1,7),move(4,1,2,2),move(4,2,2,1),move(4,3,2,2),move(4,4,2,3),move(4,5,3,7),move(4,6,2,7),move(4,7,2,8),move(4,8,6,7),move(5,1,7,2),move(5,2,3,1),move(5,3,7,2),move(5,4,7,3),move(5,5,6,7),move(5,6,4,8),move(5,7,7,8),move(5,8,3,7),move(6,1,8,2),move(6,2,4,1),move(6,3,8,2),move(6,4,8,3),move(6,5,8,6),move(6,6,8,7),move(6,7,4,8),move(6,8,8,7),move(7,1,8,3),move(7,2,5,1),move(7,3,6,1),move(7,4,8,2),move(7,5,8,7),move(7,6,6,8),move(7,7,5,8),move(7,8,8,6),move(8,1,6,2),move(8,2,6,1),move(8,3,6,2),move(8,4,7,2),move(8,5,7,3),move(8,6,7,8),move(8,7,6,8),move(8,8,6,7)]," + "[move(1,1,2,3),move(1,2,3,1),move(1,3,2,1),move(1,4,2,2),move(1,5,2,7),move(1,6,2,8),move(1,7,3,8),move(1,8,3,7),move(2,1,1,3),move(2,2,4,1),move(2,3,3,1),move(2,4,3,6),move(2,5,1,7),move(2,6,3,8),move(2,7,4,8),move(2,8,1,6),move(3,1,2,3),move(3,2,5,1),move(3,3,2,1),move(3,4,1,3),move(3,5,1,6),move(3,6,1,7),move(3,7,5,8),move(3,8,1,7),move(4,1,2,2),move(4,2,2,1),move(4,3,2,2),move(4,4,2,3),move(4,5,3,7),move(4,6,2,7),move(4,7,2,8),move(4,8,3,6),move(5,1,7,2),move(5,2,3,1),move(5,3,7,2),move(5,4,7,3),move(5,5,6,7),move(5,6,4,8),move(5,7,7,8),move(5,8,3,7),move(6,1,8,2),move(6,2,4,1),move(6,3,8,2),move(6,4,8,3),move(6,5,8,6),move(6,6,8,7),move(6,7,4,8),move(6,8,8,7),move(7,1,8,3),move(7,2,5,1),move(7,3,6,1),move(7,4,8,2),move(7,5,8,7),move(7,6,6,8),move(7,7,5,8),move(7,8,8,6),move(8,1,6,2),move(8,2,6,1),move(8,3,6,2),move(8,4,7,2),move(8,5,7,3),move(8,6,7,8),move(8,7,6,8),move(8,8,6,7)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "size(9).\n" + "\n" + "forbidden(1,9). forbidden(2,9). forbidden(3,9). forbidden(4,9). forbidden(5,9). forbidden(6,9). forbidden(7,9). forbidden(8,9). forbidden(9,9).\n" + "\n" + "forbidden(9,1). forbidden(9,2). forbidden(9,3). forbidden(9,4). forbidden(9,5). forbidden(9,6). forbidden(9,7). forbidden(9,8). forbidden(9,9).\n" + "\n" + ":- not move(1,5,2,7).\n" + ":- not move(7,5,8,7).\n" + ":- not move(1,3,2,1).\n" + ":- not move(1,4,2,2).\n" + "%:- not move(2,3,3,1).\n" + ":- not move(7,4,8,2).\n" + ":- not move(7,8,8,6).\n" + ":- not move(2,1,1,3).\n" + "%:- not move(2,4,1,6).\n" + ":- not move(2,5,1,7).\n" + ":- not move(3,1,2,3).\n" + ":- not move(4,5,3,7).\n" + ":- not move(5,6,4,8).\n" + ":- not move(7,6,6,8).\n" + ":- not move(8,6,7,8).\n" + ":- not move(2,8,1,6).\n" + ":- not move(3,3,2,1).\n" + ":- not move(7,3,6,1).\n" + ":- not move(8,4,7,2).\n" + ":- not move(8,5,7,3).\n" + ":- not move(1,7,3,8).\n" + ":- not move(2,7,4,8).\n" + ":- not move(3,7,5,8).\n" + ":- not move(5,1,7,2).\n" + ":- not move(5,7,7,8).\n" + ":- not move(6,1,8,2).\n" + ":- not move(6,5,8,6).\n" + ":- not move(6,6,8,7).\n" + "%:- not move(1,2,3,1).\n" + ":- not move(1,8,3,7).\n" + ":- not move(2,2,4,1).\n" + ":- not move(3,2,5,1).\n" + ":- not move(5,3,7,2).\n" + "%:- not move(5,4,7,3).\n" + ":- not move(6,3,8,2).\n" + ":- not move(6,4,8,3).\n" + ":- not move(6,8,8,7).\n" + ":- not move(3,5,1,6).\n" + ":- not move(3,6,1,7).\n" + ":- not move(4,1,2,2).\n" + ":- not move(4,6,2,7).\n" + "%:- not move(4,7,2,8).\n" + ":- not move(6,7,4,8).\n" + ":- not move(7,7,5,8).\n" + ":- not move(8,1,6,2).\n" + ":- not move(8,7,6,8).\n" + ":- not move(3,4,1,3).\n" + "%:- not move(3,8,1,7).\n" + ":- not move(4,2,2,1).\n" + ":- not move(4,3,2,2).\n" + ":- not move(4,4,2,3).\n" + "%:- not move(4,8,2,7).\n" + ":- not move(5,2,3,1).\n" + ":- not move(5,8,3,7).\n" + ":- not move(6,2,4,1).\n" + "%:- not move(7,2,5,1).\n" + "%:- not move(8,2,6,1).\n" + ":- not move(8,3,6,2).\n" + ":- not move(8,8,6,7).\n" + ":- not move(1,1,2,3).\n" + ":- not move(1,6,2,8).\n" + "%:- not move(2,6,3,8).\n" + ":- not move(5,5,6,7).\n" + ":- not move(7,1,8,3).\n" + "\n" + "% encoding\n" + "\n" + "% Knight Tour\n" + "\n" + "% Input:\n" + "% - size(N), if the chessboard is NxN\n" + "% - forbidden(X,Y), if X,Y cannot be reached by the knight.\n" + "\n" + "% Output:\n" + "% - move(X1,Y1,X2,Y2), if the knight moves from X1,Y1 to X2,Y2.\n" + "\n" + "\n" + "\n" + "\n" + "% Define the chessboard.\n" + "number(X) :- size(X).\n" + "number(X) :- number(Y), X=Y-1, X>0.\n" + "cell(X,Y) :- number(X), number(Y).\n" + "\n" + "% Guess the moves.\n" + "move(X1,Y1,X2,Y2) | non_move(X1,Y1,X2,Y2) :- valid(X1,Y1,X2,Y2), not forbidden(X1,Y1), not forbidden(X2,Y2).\n" + "\n" + "% Compute all valid moves from each cell.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+2, Y1 = Y2+1.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+2, Y2 = Y1+1.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+2, Y1 = Y2+1.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+2, Y2 = Y1+1.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+1, Y1 = Y2+2.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X1 = X2+1, Y2 = Y1+2.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+1, Y1 = Y2+2.\n" + "valid(X1,Y1,X2,Y2) :- cell(X1,Y1), cell(X2,Y2), X2 = X1+1, Y2 = Y1+2.\n" + "\n" + "% Exactly one move entering to each cell.\n" + ":- cell(X,Y), not forbidden(X,Y), not exactlyOneMoveEntering(X,Y).\n" + "exactlyOneMoveEntering(X,Y) :- move(X,Y,X1,Y1), not atLeastTwoMovesEntering(X,Y).\n" + "atLeastTwoMovesEntering(X,Y) :- move(X,Y,X1,Y1), move(X,Y,X2,Y2), X1 != X2.\n" + "atLeastTwoMovesEntering(X,Y) :- move(X,Y,X1,Y1), move(X,Y,X2,Y2), Y1 != Y2.\n" + "\n" + "% Exactly one move leaving each cell.\n" + ":- cell(X,Y), not forbidden(X,Y), exactlyOneMoveLeaving(X,Y).\n" + "exactlyOneMoveLeaving(X,Y) :- move(X1,Y1,X,Y), not atLeastTwoMovesLeaving(X,Y).\n" + "atLeastTwoMovesLeaving(X,Y) :- move(X1,Y1,X,Y), move(X2,Y2,X,Y), X1 != X2.\n" + "atLeastTwoMovesLeaving(X,Y) :- move(X1,Y1,X,Y), move(X2,Y2,X,Y), Y1 != Y2.\n" + "\n" + "% Each non-forbidden cell must be reached by the knight.\n" + "reached(X,Y) :- move(_,_,X,Y).\n" + "reached(X,Y) :- move(X,Y,_,_).\n" + "% reached(X2,Y2) :- reached(X1,Y1), move(X1,Y1,X2,Y2).\n" + ":- cell(X,Y), not forbidden(X,Y), not reached(X,Y).\n" + "\n" + "% Each forbidden cell must remain unreached.\n" + ":- forbidden(X,Y), reached(X,Y).\n" + , {"move("}))); + } + +// {{{1 O23 Maximal Clique Problem + + SECTION("aspcomp2013_23") { + // Author: Guenther Charwat, Martin Kronegger, Johan Wittocx* + REQUIRE( + "([[clique(1),clique(2),clique(5)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "node(1). node(2). node(3). node(4). node(5). node(6). \n" + "edge(1,2). edge(1,5). edge(2,3). edge(2,5). edge(3,4). \n" + "edge(4,5). edge(4,6).\n" + "\n" + "% encoding\n" + "\n" + "% Based on the 2009 ASP Competition encoding \n" + "% submitted by the DLV team\n" + "\n" + "% order edges in order to reduce checks\n" + "uedge(X,Y) :- edge(X,Y), X < Y.\n" + "uedge(Y,X) :- edge(X,Y), Y < X.\n" + "\n" + "% guess the clique\n" + "clique(X) | nonClique(X) :- node(X).\n" + "\n" + "% ensure property\n" + ":- clique(X), clique(Y), not uedge(X,Y), X < Y.\n" + "\n" + "% maximize\n" + ":~ nonClique(X). [1,X]\n" + "\n" + , {"clique("}, {3}))); + } + +// {{{1 O24 Labyrinth + + SECTION("aspcomp2013_24") { + // Author: Carmine Dodaro, Giovambattista Ianni, Martin Gebser* + REQUIRE( + "([[push(1,w,1),push(2,n,2)],[push(1,w,1),push(3,s,2)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "field(1,1).\n" + "field(1,2).\n" + "field(1,3).\n" + "field(1,4).\n" + "field(2,1).\n" + "field(2,2).\n" + "field(2,3).\n" + "field(2,4).\n" + "field(3,1).\n" + "field(3,2).\n" + "field(3,3).\n" + "field(3,4).\n" + "field(4,1).\n" + "field(4,2).\n" + "field(4,3).\n" + "field(4,4).\n" + "init_on(3,2).\n" + "goal_on(1,4).\n" + "connect(1,1,s).\n" + "connect(1,1,w).\n" + "connect(1,2,n).\n" + "connect(1,2,e).\n" + "connect(1,2,w).\n" + "connect(1,3,e).\n" + "connect(1,4,n).\n" + "connect(1,4,w).\n" + "connect(2,1,n).\n" + "connect(2,1,w).\n" + "connect(2,2,n).\n" + "connect(2,2,w).\n" + "connect(2,3,n).\n" + "connect(2,3,s).\n" + "connect(2,4,n).\n" + "connect(2,4,e).\n" + "connect(2,4,w).\n" + "connect(3,1,n).\n" + "connect(3,1,s).\n" + "connect(3,2,n).\n" + "connect(3,2,w).\n" + "connect(3,3,e).\n" + "connect(3,4,n).\n" + "connect(3,4,s).\n" + "connect(3,4,w).\n" + "connect(4,1,n).\n" + "connect(4,1,w).\n" + "connect(4,2,n).\n" + "connect(4,2,s).\n" + "connect(4,2,e).\n" + "connect(4,2,w).\n" + "connect(4,3,n).\n" + "connect(4,3,e).\n" + "connect(4,4,w).\n" + "max_steps(2).\n" + "\n" + "% encoding\n" + "\n" + "dir(e). dir(w). dir(n). dir(s).\n" + "inverse(e,w). inverse(w,e).\n" + "inverse(n,s). inverse(s,n).\n" + "\n" + "row(X) :- field(X,Y).\n" + "col(Y) :- field(X,Y).\n" + "\n" + "num_rows(X) :- row(X), not row(XX), XX = X+1.\n" + "num_cols(Y) :- col(Y), not col(YY), YY = Y+1.\n" + "\n" + "goal(X,Y,0) :- goal_on(X,Y).\n" + "reach(X,Y,0) :- init_on(X,Y).\n" + "conn(X,Y,D,0) :- connect(X,Y,D).\n" + "\n" + "step(S) :- max_steps(S), 0 < S.\n" + "step(T) :- step(S), T = S-1, 1 < S.\n" + "\n" + "%% Direct neighbors\n" + "\n" + "dneighbor(n,X,Y,XX,Y) :- field(X,Y), field(XX,Y), XX = X+1.\n" + "dneighbor(s,X,Y,XX,Y) :- field(X,Y), field(XX,Y), XX = X-1.\n" + "dneighbor(e,X,Y,X,YY) :- field(X,Y), field(X,YY), YY = Y+1.\n" + "dneighbor(w,X,Y,X,YY) :- field(X,Y), field(X,YY), YY = Y-1.\n" + "\n" + "%% All neighboring fields\n" + "\n" + "neighbor(D,X,Y,XX,YY) :- dneighbor(D,X,Y,XX,YY).\n" + "neighbor(n,X,Y, 1, Y) :- field(X,Y), num_rows(X).\n" + "neighbor(s,1,Y, X, Y) :- field(X,Y), num_rows(X).\n" + "neighbor(e,X,Y, X, 1) :- field(X,Y), num_cols(Y).\n" + "neighbor(w,X,1, X, Y) :- field(X,Y), num_cols(Y).\n" + "\n" + "%% Select a row or column to push\n" + "\n" + "neg_goal(T) :- goal(X,Y,T), not reach(X,Y,T).\n" + "\n" + "rrpush(T) :- step(T), neg_goal(S), S = T-1, not ccpush(T).\n" + "ccpush(T) :- step(T), neg_goal(S), S = T-1, not rrpush(T).\n" + "\n" + "orpush(X,T) :- row(X), row(XX), rpush(XX,T), X != XX.\n" + "ocpush(Y,T) :- col(Y), col(YY), cpush(YY,T), Y != YY.\n" + "\n" + "rpush(X,T) :- row(X), rrpush(T), not orpush(X,T).\n" + "cpush(Y,T) :- col(Y), ccpush(T), not ocpush(Y,T).\n" + "\n" + "push(X,e,T) :- rpush(X,T), not push(X,w,T).\n" + "push(X,w,T) :- rpush(X,T), not push(X,e,T).\n" + "push(Y,n,T) :- cpush(Y,T), not push(Y,s,T).\n" + "push(Y,s,T) :- cpush(Y,T), not push(Y,n,T).\n" + "\n" + "%% Determine new position of a (pushed) field\n" + "\n" + "shift(XX,YY,X,Y,T) :- neighbor(e,XX,YY,X,Y), push(XX,e,T), step(T).\n" + "shift(XX,YY,X,Y,T) :- neighbor(w,XX,YY,X,Y), push(XX,w,T), step(T).\n" + "shift(XX,YY,X,Y,T) :- neighbor(n,XX,YY,X,Y), push(YY,n,T), step(T).\n" + "shift(XX,YY,X,Y,T) :- neighbor(s,XX,YY,X,Y), push(YY,s,T), step(T).\n" + "shift( X, Y,X,Y,T) :- field(X,Y), not push(X,e,T), not push(X,w,T), not push(Y,n,T), not push(Y,s,T), step(T).\n" + "\n" + "%% Move connections around\n" + "\n" + "conn(X,Y,D,T) :- conn(XX,YY,D,S), S = T-1, dir(D), shift(XX,YY,X,Y,T), step(T).\n" + "\n" + "%% Location of goal after pushing\n" + "\n" + "goal(X,Y,T) :- goal(XX,YY,S), S = T-1, shift(XX,YY,X,Y,T), step(T).\n" + "\n" + "%% Locations reachable from new position\n" + "\n" + "reach(X,Y,T) :- reach(XX,YY,S), S = T-1, shift(XX,YY,X,Y,T), step(T).\n" + "reach(X,Y,T) :- reach(XX,YY,T), dneighbor(D,XX,YY,X,Y), conn(XX,YY,D,T), conn(X,Y,E,T), inverse(D,E), step(T).\n" + "\n" + "%% Goal must be reached\n" + "\n" + ":- neg_goal(S), max_steps(S).\n" + "\n" + "%% Project output\n" + "\n" + "% #hide.\n" + "% #show push(Z,D,T).\n" + "\n" + , {"push("}))); + } + +// {{{1 O25 Minimal Diagnosis + + SECTION("aspcomp2013_25") { + // Author: Marcello Balduccini, Martin Gebser* + REQUIRE( + "([[active(0),active(3)]]," + "[-:33:30-38: info: atom does not occur in any rule head:\n input(V)\n" + ",-:34:30-38: info: atom does not occur in any rule head:\n input(V)\n" + ",-:36:33-41: info: atom does not occur in any rule head:\n input(V)\n" + ",-:37:33-41: info: atom does not occur in any rule head:\n input(V)\n" + ",-:40:33-41: info: atom does not occur in any rule head:\n input(V)\n" + ",-:41:33-41: info: atom does not occur in any rule head:\n input(V)\n" + ",-:48:43-51: info: atom does not occur in any rule head:\n input(V)\n" + ",-:49:43-51: info: atom does not occur in any rule head:\n input(V)\n" + ",-:57:28-36: info: atom does not occur in any rule head:\n input(V)\n" + ",-:71:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:72:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:73:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:75:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:76:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:84:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:85:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:86:68-76: info: atom does not occur in any rule head:\n input(V)\n" + ",-:99:102-110: info: atom does not occur in any rule head:\n input(V)\n" + ",-:99:116-124: info: atom does not occur in any rule head:\n input(W)\n" + ",-:100:102-110: info: atom does not occur in any rule head:\n input(V)\n" + ",-:100:116-124: info: atom does not occur in any rule head:\n input(W)\n" + ",-:101:102-110: info: atom does not occur in any rule head:\n input(V)\n" + ",-:101:116-124: info: atom does not occur in any rule head:\n input(W)\n])" == IO::to_string(solve( + "% instance\n" + "\n" + "vertex(0). vertex(1). vertex(2). vertex(3). vertex(4). \n" + "obs_vlabel(1,p). obs_vlabel(3,p).\n" + "\n" + "edge(0,1). edge(0,3). edge(0,4).\n" + "obs_elabel(0,1,p). obs_elabel(0,3,m). obs_elabel(0,4,m).\n" + "\n" + "edge(1,0).\n" + "obs_elabel(1,0,p).\n" + "\n" + "edge(1,2).\n" + "obs_elabel(1,2,p).\n" + "\n" + "edge(2,4).\n" + "obs_elabel(2,4,m).\n" + "\n" + "edge(3,1). edge(3,2). edge(3,4).\n" + "obs_elabel(3,1,p). obs_elabel(3,2,p). obs_elabel(3,4,p).\n" + "\n" + "% encoding\n" + "\n" + "%%%%%%%%%%%%%%%%%\n" + "% Preprocessing %\n" + "%%%%%%%%%%%%%%%%%\n" + "\n" + "sign(m). sign(p).\n" + "\n" + "diff(V,V) :- edge(V,V), obs_elabel(V,V,m), not obs_elabel(V,V, p).\n" + "diff(U,V) :- edge(U,V), obs_elabel(U,V,m), not obs_elabel(U,V, p), obs_vlabel(U,S), obs_vlabel(V,S).\n" + "diff(U,V) :- edge(U,V), obs_elabel(U,V, p), not obs_elabel(U,V,m), obs_vlabel(U,S), obs_vlabel(V,T), S != T.\n" + "\n" + "nontriv(V) :- vertex(V), not input(V), edge(U,V), not diff(U,V).\n" + "trivial(V) :- vertex(V), not input(V), not nontriv(V).\n" + "\n" + "btedge(W,U,V) :- vertex(V), not input(V), not trivial(V), edge(W,V), edge(U,V), edge(Z,V), W < Z, Z < U.\n" + "ntedge(W,U,V) :- vertex(V), not input(V), not trivial(V), edge(W,V), edge(U,V), W < U, not btedge(W,U,V).\n" + "nfirst(U,V) :- ntedge(W,U,V).\n" + "nlast(W,V) :- ntedge(W,U,V).\n" + "first(U,V) :- vertex(V), not input(V), not trivial(V), edge(U,V), not nfirst(U,V).\n" + "last(U,V) :- vertex(V), not input(V), not trivial(V), edge(U,V), not nlast(U,V).\n" + "\n" + "\n" + "%%%%%%%%%%%%%\n" + "% Generator %\n" + "%%%%%%%%%%%%%\n" + "\n" + "active(V) | inactive(V) :- vertex(V), not input(V).\n" + "inactive(V) :- vertex(V), not input(V), active(W), trivial(W), V != W.\n" + "singleton :- active(V), trivial(V).\n" + "\n" + "reach(U,V) :- edge(U,V), active(V), not trivial(V).\n" + "reach(V,U) :- edge(U,V), active(V), not trivial(V), not obs_vlabel(U,p), not obs_vlabel(U,m).\n" + "reach(U,W) :- edge(U,V), active(V), not trivial(V), reach(V,W), vertex(W).\n" + "reach(V,W) :- edge(U,V), active(V), not trivial(V), reach(U,W), vertex(W), not obs_vlabel(U,p), not obs_vlabel(U,m).\n" + "\n" + "aedge(V) :- vertex(V), not input(V), not trivial(V), not obs_vlabel(V,p), not obs_vlabel(V,m), active(W), edge(V,W).\n" + "\n" + ":- active(V), not trivial(V), active(W), not trivial(W), not reach(V,W).\n" + ":- active(V), not trivial(V), not obs_vlabel(V,p), not obs_vlabel(V,m), not aedge(V).\n" + "\n" + "\n" + "%%%%%%%%%%%%%%%%%%%%%%\n" + "% Inconsistency Test %\n" + "%%%%%%%%%%%%%%%%%%%%%%\n" + "\n" + "vlabel(V,p) | vlabel(V,m) :- active(V), not trivial(V), not obs_vlabel(V,p), not obs_vlabel(V,m).\n" + "vlabel(U,p) | vlabel(U,m) :- active(V), not trivial(V), edge(U,V), not obs_vlabel(U,p), not obs_vlabel(U,m).\n" + "llabel(U,V,p) | llabel(U,V,m) :- active(V), not trivial(V), edge(U,V), not obs_elabel(U,V,p), not obs_elabel(U,V,m).\n" + "\n" + "vlabel(V,S) :- vertex(V), obs_vlabel(V,S), not trivial(V), not input(V).\n" + "vlabel(U,S) :- edge(U,V), obs_vlabel(U,S), not trivial(V), not input(V).\n" + "llabel(U,V,S) :- edge(U,V), obs_elabel(U,V,S), not trivial(V), not input(V).\n" + "\n" + "oppo(U,V) :- llabel(U,V,m), vlabel(U,S), not trivial(V), not input(V), not obs_elabel(U,V,p), active(V), vlabel(V,S).\n" + "oppo(U,V) :- llabel(U,V,p), vlabel(U,S), not trivial(V), not input(V), not obs_elabel(U,V,m), active(V), vlabel(V,T), S != T.\n" + "\n" + "coppo(U,V) :- oppo(U,V), first(U,V).\n" + "coppo(U,V) :- oppo(U,V), coppo(W,V), ntedge(W,U,V).\n" + "\n" + "bot :- singleton.\n" + "bot :- active(V), coppo(U,V), last(U,V).\n" + "\n" + "vlabel(V,S) :- bot, vertex(V), sign(S), not trivial(V), not input(V), not obs_vlabel(V,p), not obs_vlabel(V,m).\n" + "vlabel(U,S) :- bot, edge(U,V), sign(S), not trivial(V), not input(V), not obs_vlabel(U,p), not obs_vlabel(U,m).\n" + "llabel(U,V,S) :- bot, edge(U,V), sign(S), not trivial(V), not input(V), not obs_elabel(U,V,p), not obs_elabel(U,V,m).\n" + "\n" + ":- not bot.\n" + "\n" + "\n" + "%%%%%%%%%%%%%%%%%%%\n" + "% Minimality Test %\n" + "%%%%%%%%%%%%%%%%%%%\n" + "\n" + "mvlabel(W,V,p) | mvlabel(W,V,m) :- active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n" + "mvlabel(W,U,p) | mvlabel(W,U,m) :- edge(U,V), active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n" + "mllabel(W,U,V,p) | mllabel(W,U,V,m) :- edge(U,V), active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n" + "\n" + "mvlabel(W,V,S) :- obs_vlabel(V,S), vertex(W), not trivial(V), not trivial(W), not input(V), not input(W), W != V.\n" + "mvlabel(W,U,S) :- obs_vlabel(U,S), edge(U,V), vertex(W), not trivial(V), not trivial(W), not input(V), not input(W), W != V.\n" + "mllabel(W,U,V,S) :- obs_elabel(U,V,S), edge(U,V), vertex(W), not trivial(V), not trivial(W), not input(V), not input(W), W != V.\n" + "\n" + "minfl(W,V,p) :- mvlabel(W,U,S), mllabel(W,U,V,S), active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V.\n" + "minfl(W,V,m) :- mvlabel(W,U,S), mllabel(W,U,V,T), active(W), not trivial(V), not trivial(W), active(V), reach(V,W), reach(W,V), W != V, S != T.\n" + "\n" + ":- active(V), active(W), not trivial(V), not trivial(W), W != V, mvlabel(W,V,S), not minfl(W,V,S).\n" + "\n" + "\n" + "%%%%%%%%%%\n" + "% Output %\n" + "%%%%%%%%%%\n" + "\n" + "% #hide.\n" + "% #show active(V).\n" + , {"active("}))); + } + +// {{{1 O26 Hanoi Tower + + SECTION("aspcomp2013_26") { + // Author: Gayathri Namasivayam, Miroslaw Truszczynski, Shaden Smith, Alex Westlund + REQUIRE( + "([[put(0,3,9),put(1,2,8),put(2,8,9)],[put(0,4,9),put(1,2,8),put(2,8,9)]],[])" == IO::to_string(solve( + "% instance\n" + "\n" + "steps(3). time(0). time(1). time(2). time(3). disk(1). disk(2). disk(3). disk(4). disk(5). disk(6). disk(7). disk(8). disk(9). on0(5,1). on0(6,5). on0(7,6). on0(8,7). on0(9,8). ongoal(5,1). ongoal(6,5). ongoal(7,6). ongoal(8,2). ongoal(9,8).\n" + "\n" + "% encoding\n" + "\n" + "% The meaning of the time predicate is self-evident. As for the disk\n" + "% predicate, there are k disks 1,2,...,k. Disks 1, 2, 3, 4 denote pegs. \n" + "% Disks 5, ... are \"movable\". The larger the number of the disk, \n" + "% the \"smaller\" it is.\n" + "%\n" + "% The program uses additional predicates:\n" + "% on(T,N,M), which is true iff at time T, disk M is on disk N\n" + "% move(t,N), which is true iff at time T, it is disk N that will be\n" + "% moved\n" + "% where(T,N), which is true iff at time T, the disk to be moved is moved\n" + "% on top of the disk N.\n" + "% goal, which is true iff the goal state is reached at time t\n" + "% steps(T), which is the number of time steps T, required to reach the goal (provided part of Input data)\n" + "\n" + "% Read in data \n" + " on(0,N1,N) :- on0(N,N1).\n" + " onG(K,N1,N) :- ongoal(N,N1), steps(K).\n" + " \n" + "% Specify valid arrangements of disks\n" + " % Basic condition. Smaller disks are on larger ones\n" + " :- time(T), on(T,N1,N), N1>=N.\n" + " \n" + "% Specify a valid move (only for T. + +// }}} + +#include "tests/term_helper.hh" +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/output/solver_helper.hh" + +namespace Gringo { namespace Output { namespace Test { + +using namespace Gringo::Test; + +// {{{ definition of auxiliary functions + +namespace { + +std::string iground(std::string in, int last = 3) { + std::stringstream ss; + Gringo::Test::TestGringoModule module; + Potassco::TheoryData td; + Output::OutputBase out(td, {}, ss, OutputFormat::INTERMEDIATE); + Input::Program prg; + Defines defs; + Scripts scripts(module); + Input::NongroundProgramBuilder pb(scripts, prg, out, defs); + Input::NonGroundParser parser(pb); + parser.pushStream("-", gringo_make_unique(in), module.logger); + Models models; + parser.parse(module.logger); + prg.rewrite(defs, module.logger); + prg.check(module.logger); + //std::cerr << prg; + // TODO: think about passing params to toGround already... + if (!module.logger.hasError()) { + out.init(true); + { + Ground::Parameters params; + params.add("base", {}); + out.beginStep(); + prg.toGround(out.data, module.logger).ground(params, scripts, out, true, module.logger); + out.reset(); + } + for (int i=1; i < last; ++i) { + Ground::Parameters params; + params.add("step", {NUM(i)}); + out.beginStep(); + prg.toGround(out.data, module.logger).ground(params, scripts, out, true, module.logger); + out.reset(); + } + { + Ground::Parameters params; + params.add("last", {}); + out.beginStep(); + prg.toGround(out.data, module.logger).ground(params, scripts, out, true, module.logger); + out.reset(); + } + } + return ss.str(); +} + +} // namespace + +// }}} +// {{{ definition of TestIncremental + +TEST_CASE("output-incremental", "[output]") { + SECTION("assign") { + REQUIRE( + "asp 1 0 0 incremental\n" + "0\n" + "1 0 1 1 0 0\n" + "4 8 p(1,0,0) 0\n" + "0\n" + "1 0 1 2 0 0\n" + "4 8 p(2,0,0) 0\n" + "0\n" + "0\n" == iground( + "#program base." + "#program step(k)." + "p(k,N,Y) :- N = #sum { Y }, Y = #sum { }." + "#program last.")); + REQUIRE( + "asp 1 0 0 incremental\n" + "0\n" + "1 0 1 1 0 0\n" + "4 8 p(1,2,1) 0\n" + "0\n" + "1 0 1 2 0 0\n" + "4 8 p(2,4,2) 0\n" + "0\n" + "0\n" == iground( + "#program base." + "#program step(k)." + "p(k,N,Y) :- N = #sum { 2*Y }, Y = #sum { k }." + "#program last.")); + } + SECTION("projection") { + REQUIRE( + "asp 1 0 0 incremental\n" + "1 1 1 1 0 0\n" + "1 1 1 2 0 0\n" + "1 1 1 3 0 0\n" + "1 0 1 4 0 1 1\n" + "1 0 1 4 0 1 2\n" + "1 0 1 4 0 1 3\n" + "4 4 p(1) 1 1\n" + "4 4 p(2) 1 2\n" + "4 4 p(3) 1 3\n" + "0\n" + "1 0 1 5 0 1 4\n" + "1 1 1 6 0 1 5\n" + "4 4 q(1) 1 6\n" + "0\n" + "1 0 1 7 0 1 5\n" + "1 1 1 8 0 1 7\n" + "4 4 q(2) 1 8\n" + "0\n" + "1 0 1 9 0 1 7\n" + "0\n" == iground( + "#program base." + "{p(1..3)}." + "#program step(k)." + "{q(k)} :- p(_)." + "#program last.")); + } + + SECTION("lp") { + REQUIRE( + "asp 1 0 0 incremental\n" + "4 4 base 1 -1\n" + "0\n" + "1 0 1 2 0 0\n" + "4 4 r(1) 0\n" + "4 4 p(1) 1 -1\n" + "4 4 q(1) 1 -1\n" + "0\n" + "1 0 1 3 0 0\n" + "4 4 r(2) 0\n" + "4 4 p(2) 1 -1\n" + "4 4 q(2) 1 -1\n" + "0\n" + "4 4 last 1 -1\n" + "0\n" == iground( + "#program base." + "#show base." + "#program step(k)." + "#show p(k)." + "#show q(k)." + "r(k)." + "#program last." + "#show last.")); + REQUIRE( + "asp 1 0 0 incremental\n" + "1 0 1 1 0 0\n" + "4 4 base 0\n" + "0\n" + "1 0 1 2 0 0\n" + "4 7 step(1) 0\n" + "0\n" + "1 0 1 3 0 0\n" + "4 7 step(2) 0\n" + "0\n" + "1 0 1 4 0 0\n" + "4 4 last 0\n" + "0\n" == iground( + "#program base." + "base." + "#program step(k)." + "step(k)." + "#program last." + "last.")); + } + SECTION("csp") { + REQUIRE( + "asp 1 0 0 incremental\n" + "4 6 base=1 0\n" + "0\n" + "1 0 1 1 0 0\n" + "1 1 1 2 0 1 3\n" + "1 1 1 3 0 1 4\n" + "1 1 1 4 0 1 5\n" + "1 1 1 5 0 0\n" + "1 1 1 6 0 1 7\n" + "1 1 1 7 0 1 8\n" + "1 1 1 8 0 0\n" + "1 1 1 9 0 1 10\n" + "1 1 1 10 0 0\n" + "4 4 up=0 1 2\n" + "4 4 up=1 2 3 -2\n" + "4 4 up=2 2 4 -3\n" + "4 4 up=3 2 5 -4\n" + "4 4 up=4 1 -5\n" + "4 4 lo=1 1 6\n" + "4 4 lo=2 2 7 -6\n" + "4 4 lo=3 2 8 -7\n" + "4 4 lo=4 1 -8\n" + "4 4 ib=1 1 9\n" + "4 4 ib=2 2 10 -9\n" + "4 4 ib=3 1 -10\n" + "4 7 step(1) 0\n" + "0\n" + "1 0 1 11 0 0\n" + "1 0 0 0 1 -5\n" + "1 0 0 0 1 6\n" + "1 0 0 0 2 -9 10\n" + "4 7 step(2) 0\n" + "0\n" + "4 6 last=1 0\n" + "0\n" == iground( + "#program base." + "$base$=1." + "#program step(k)." + "step(k)." + "0 $<= $up $<= 5-k." + "k $<= $lo $<= 4." + "1 $<= $ib $<= 3." + "$ib $= 1; $ib $=3 :- k == 2." + "#program last." + "$last$=1.")); + } + + SECTION("projectionBug") { + REQUIRE( + "asp 1 0 0 incremental\n" + "1 1 1 1 0 0\n" + "1 0 1 2 0 1 1\n" + "4 6 p(0,0) 1 1\n" + "0\n" + "1 0 1 3 0 1 2\n" + "1 1 1 4 0 1 3\n" + "1 0 1 5 0 1 4\n" + "4 6 p(1,1) 1 4\n" + "0\n" + "1 0 1 6 0 1 3\n" + "1 0 1 7 0 1 5\n" + "1 1 1 8 0 1 7\n" + "1 0 1 9 0 1 8\n" + "4 6 p(2,2) 1 8\n" + "0\n" + "1 0 1 10 0 1 6\n" + "1 0 1 11 0 1 7\n" + "1 0 1 12 0 1 9\n" + "1 1 1 13 0 0\n" + "1 0 1 10 0 1 13\n" + "1 1 1 14 0 1 10\n" + "1 1 1 15 0 1 11\n" + "1 1 1 16 0 1 12\n" + "4 6 p(1,0) 1 13\n" + "4 4 r(0) 1 14\n" + "4 4 r(1) 1 15\n" + "4 4 r(2) 1 16\n" + "0\n" == iground( + "#program base." + "{p(0,0)}." + "#program step(k)." + "{p(k,k)} :- p(_,k-1)." + "#program last." + "{p(1,0)}." + "{r(X)} :- p(_,X)." + )); + } + + SECTION("mapping") { + Mapping m; + m.add(1,0); + m.add(2,1); + m.add(4,2); + m.add(5,3); + + REQUIRE(InvalidId == m.get(0)); + REQUIRE(Id_t(0) == m.get(1)); + REQUIRE(Id_t(1) == m.get(2)); + REQUIRE(InvalidId == m.get(3)); + REQUIRE(Id_t(2) == m.get(4)); + REQUIRE(Id_t(3) == m.get(5)); + REQUIRE(InvalidId == m.get(6)); + + REQUIRE(Id_t(0) == m.bound(0)); + REQUIRE(Id_t(0) == m.bound(1)); + REQUIRE(Id_t(1) == m.bound(2)); + REQUIRE(Id_t(2) == m.bound(3)); + REQUIRE(Id_t(2) == m.bound(4)); + REQUIRE(Id_t(3) == m.bound(5)); + REQUIRE(Id_t(4) == m.bound(6)); + } +} + +} } } // namespace Test Output Gringo diff --git a/libgringo/tests/output/lparse.cc b/libgringo/tests/output/lparse.cc new file mode 100644 index 0000000..28bb48a --- /dev/null +++ b/libgringo/tests/output/lparse.cc @@ -0,0 +1,1290 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/output/solver_helper.hh" + +namespace Gringo { namespace Output { namespace Test { + +TEST_CASE("output-lparse", "[output]") { + SECTION("bug-classical-negation") { + REQUIRE( + "([],[])" == + IO::to_string(solve( + "p. -p." + )) + ); + REQUIRE( + "([[-p]],[])" == + IO::to_string(solve( + "-p." + )) + ); + } + SECTION("unpool") { + REQUIRE( + "([[a(1),a(2),a(4)]],[])" == + IO::to_string(solve( + "a(X) :- X=(1;2;4)." + )) + ); + REQUIRE( + "([[p(1),p(2),q(3)],[p(1),p(2),q(4)]],[])" == + IO::to_string(solve( + "1 {q(3;4)} 1." + "p(1;2) :- q(3;4)." + )) + ); + REQUIRE( + "([],[])" == + IO::to_string(solve( + "1 {q(3;4)} 1." + "#disjoint { (1;2) : (2;3) : q(3;4) }." + )) + ); + REQUIRE( + "([[a,p(1),q(3)],[a,p(1),q(4)],[a,p(2),q(3)],[a,p(2),q(4)]],[])" == + IO::to_string(solve( + "1 { p(1;2) } 1." + "1 { q(3;4) } 1." + "a :- p(1;2) : q(3;4)." + )) + ); + REQUIRE( + "([[p(1),p(2),q(3)],[p(1),p(2),q(4)]],[])" == + IO::to_string(solve( + "1 { q(3;4) } 1." + "p(1;2) : q(3;4)." + )) + ); + REQUIRE( + "([[a,p(1),q(3)],[a,p(1),q(4)],[a,p(2),q(3)],[a,p(2),q(4)],[q(3)],[q(4)]],[])" == + IO::to_string(solve( + "1 { q(3;4) } 1." + "0 { p(1;2) } 1." + "a :- (1;2) { q(3;4) : p(1;2) }." + )) + ); + REQUIRE( + "([[],[a,p(1)],[a,p(2)]],[])" == + IO::to_string(solve( + "0 { p(1;2) } 1." + "a :- (2;3) #count { q(3;4) : p(1;2) }." + )) + ); + REQUIRE( + "([[p(1),q(3),q(4)],[p(2),q(3),q(4)]],[])" == + IO::to_string(solve( + "0 { p(1;2) } 1." + "(1;2) { q(3;4) : p(1;2) }." + )) + ); + REQUIRE( + "([[p(1),q(3)],[p(1),q(3),q(4)],[p(1),q(4)],[p(2),q(3)],[p(2),q(3),q(4)],[p(2),q(4)]],[])" == + IO::to_string(solve( + "0 { p(1;2) } 1." + "(1;2) #count { t(5;6) : q(3;4) : p(1;2) }." + )) + ); + } + + SECTION("recCondBug") { + REQUIRE( + "([[0,2,4,5,9],[0,2,5,9],[0,4,9],[0,9]],[])" == + IO::to_string(solve( + "holds(atom(A)) :- rule(lit(pos,atom(A)),B); holds(B).\n" + "{ holds(atom(A)) : head_aggregate_element_set(I, head_aggregate_element(_,lit(pos,atom(A)),C))\n" + " , holds(C)\n" + "} :- rule(head_aggregate(left(#inf,less_equal),count,head_aggregate_element_set(I),right(less_equal,#sup)),C)\n" + " ; holds(C)\n" + " .\n" + "% :- rule(lit(pos,false),B); holds(B) .\n" + "% NOTE: there are more heads but this is enough to support --lparse-rewrite\n" + "\n" + "holds(conjunction(I)) :- conjunction(I)\n" + " ; holds(A) : conjunction(I,lit(pos,A))\n" + " ; not holds(A) : conjunction(I,lit(neg,A))\n" + " ; not not holds(A) : conjunction(I,lit(neg_neg,A))\n" + " .\n" + "\n" + "body_aggregate(L,F,S,U) :- conjunction(_,lit(_,body_aggregate(L,F,S,U))). % TODO: generate in meta\n" + "\n" + "holds(body_aggregate(left(#inf,less_equal),sump,body_aggregate_element_set(S),right(greater_equal,U)))\n" + " :- body_aggregate(left(#inf,less_equal),sump,body_aggregate_element_set(S),right(greater_equal,U))\n" + " ; #sum+ { W,T : body_aggregate_element_set(S,body_aggregate_element((W,T),conjunction(C))), holds(C) } >= U % TODO: if the holds is ommitted strange things appear to happen\n" + " .\n" + "% NOTE: there are more body aggregates but this is enough to support --lparse-rewrite\n" + "\n" + "% TODO: handle minimize constraint\n" + "\n" + "#show.\n" + "#show I : holds(conjunction(I)), conjunction(I).\n" + "rule(head_aggregate(left(#inf,less_equal),count,head_aggregate_element_set(0),right(less_equal,#sup)),conjunction(0)).\n" + "conjunction(0).\n" + "head_aggregate_element_set(0).\n" + "head_aggregate_element_set(0,head_aggregate_element((),lit(pos,atom(p(1))),conjunction(0))).\n" + "head_aggregate_element_set(0,head_aggregate_element((),lit(pos,atom(p(2))),conjunction(0))).\n" + "rule(lit(pos,atom(__aux(1))),conjunction(1)).\n" + "conjunction(1).\n" + "conjunction(1,lit(pos,atom(p(2)))).\n" + "conjunction(1,lit(neg,atom(p(2)))).\n" + "rule(lit(pos,atom(__aux(2))),conjunction(2)).\n" + "conjunction(2).\n" + "conjunction(2,lit(pos,atom(p(2)))).\n" + "rule(lit(pos,atom(__aux(2))),conjunction(3)).\n" + "conjunction(3).\n" + "conjunction(3,lit(pos,atom(__aux(1)))).\n" + "rule(lit(pos,atom(__aux(4))),conjunction(6)).\n" + "conjunction(4).\n" + "conjunction(4,lit(pos,atom(p(1)))).\n" + "conjunction(5).\n" + "conjunction(5,lit(pos,atom(__aux(2)))).\n" + "body_aggregate_element_set(0).\n" + "body_aggregate_element_set(0,body_aggregate_element((1,(0,())),conjunction(4))).\n" + "body_aggregate_element_set(0,body_aggregate_element((2,(1,())),conjunction(5))).\n" + "conjunction(6).\n" + "conjunction(6,lit(pos,body_aggregate(left(#inf,less_equal),sump,body_aggregate_element_set(0),right(greater_equal,1)))).\n" + "rule(lit(pos,atom(__aux(5))),conjunction(7)).\n" + "conjunction(7).\n" + "conjunction(7,lit(pos,body_aggregate(left(#inf,less_equal),sump,body_aggregate_element_set(0),right(greater_equal,3)))).\n" + "rule(lit(pos,atom(__aux(3))),conjunction(8)).\n" + "conjunction(8).\n" + "conjunction(8,lit(pos,atom(__aux(4)))).\n" + "conjunction(8,lit(neg,atom(__aux(5)))).\n" + "rule(lit(pos,false),conjunction(9)).\n" + "conjunction(9).\n" + "conjunction(9,lit(neg,atom(__aux(3)))).\n" + "show_atom(p(1)).\n" + "show_atom(p(2)).\n" + )) + ); + } + + SECTION("empty") { + REQUIRE("([[]],[])" == IO::to_string(solve(""))); + } + + SECTION("projectionBug") { + REQUIRE("([[p(1),p(2)]],[])" == IO::to_string(solve( + "q((1,x),2).\n" + "p(A) :- q((A,_),_).\n" + "p(B) :- q((A,_),B).\n" + , {"p("}))); + } + SECTION("aggregateBug") { + REQUIRE( + "([[a(1),a(2),b(1)],[a(1),a(2),b(1),b(2)]],[])" == + IO::to_string(solve( + "a(1)." + "a(2)." + "b(1)." + "{ b(X) } :- a(X)."))); + } + + SECTION("aggregateMinBug") { + REQUIRE( + "([[a(20),a(50),a(60),output(20)],[a(20),a(50),output(20)],[a(50),a(60),output(50)],[a(50),output(50)]],[])" == + IO::to_string(solve( + "a(50)." + "{ a(20) ; a(60) }." + "output(X) :- X = #min { C : a(C) }." + ))); + } + + SECTION("recHeadAggregateBug") { + REQUIRE( + "([" + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),e(r1,v(x7))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),e(r1,v(x7))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),e(r1,v(x7))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),e(r1,v(x3))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,n(a11))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x13),e(r1,v(x7))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x13),e(r1,v(x7))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),e(r1,v(x3))),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x7),n(a11)),r(v(x9),e(r1,n(a11))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x13),n(a11)),r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]," + "[r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3)))]," + "[r(v(x7),e(r1,n(a11))),r(v(x7),e(r1,v(x4))),r(v(x9),e(r1,v(x3))),r(v(x9),e(r1,v(x7)))]" + "],[])" == IO::to_string(solve( + "atom(A) :- hasatom(A,_,_).\n" + "atom(A) :- hasatom(e(_,A),_,_).\n" + "nonvatom(X) :- atom(X), X!=v(V):atom(v(V)).\n" + "\n" + "triviallyfalse(n(X),n(Y)) :- atom(n(X)), atom(n(Y)), X!=Y.\n" + "triviallyfalse(e(R1,C1),e(R2,C2)) :- atom(e(R1,C1)),\n" + " atom(e(R2,C2)), R1!=R2. \n" + "triviallyfalse(n(C),e(R,C1)) :- atom(n(C)), atom(e(R,C1)).\n" + "triviallyfalse(e(R,C1),n(C)) :- atom(n(C)), atom(e(R,C1)).\n" + "\n" + "subs(X,Y) :- subs(e(R,X),e(R,Y)).\n" + "\n" + "1 { subs(Y,X):hasatom(Y,|P-1|,E),not triviallyfalse(Y,X) } :- hasatom(X,P,E), nonvatom(X).\n" + "\n" + "1 { subs(Y,C):hasatom(Y,|P-1|,E),not triviallyfalse(Y,C) } :- subs(X,C), hasatom(X,P,E),\n" + " nonvatom(C), not hasatom(C,PX,E):hasatom(C,PX,E).\n" + "\n" + "subs(X,Z) :- subs(X,Y), subs(Y,Z), X!=Z, X!=Y, Z!=Y.\n" + "\n" + ":- subs(X,Y), triviallyfalse(X,Y).\n" + "\n" + "greater(X,Y) :- subs(v(X),e(R,v(Y))).\n" + ":- greater(X,X).\n" + "greater(X,Z) :- greater(X,Y), greater(Y,Z), X!=Y, X!=Z, Y!=Z.\n" + "\n" + "atom(C) :- diseq(C,D).\n" + "atom(D) :- diseq(C,D).\n" + "\n" + "1 { dissubs(X,Y); dissubs(Y,X) } :- diseq(X,Y).\n" + "ok(C,D) :- dissubs(C,D), subs(D,D'), nonvatom(D'), not subs(C,D'), not subs(C',D'):subs(C,C').\n" + ":- dissubs(C,D), not ok(C,D).\n" + "\n" + "r(v(X),C) :- subs(v(X),C), relevant(X), nonvatom(C).\n" + "\n" + "%equation 1\n" + "hasatom(v(x3), 0, 1).\n" + "hasatom(e(r1, n(a11)), 1, 1).\n" + "\n" + "%equation 2\n" + "hasatom(v(x9), 0, 2).\n" + "hasatom(v(x5), 1, 2).\n" + "hasatom(v(x9), 1, 2).\n" + "\n" + "%equation 3\n" + "hasatom(v(x6), 0, 3).\n" + "hasatom(v(x4), 1, 3).\n" + "hasatom(v(x9), 1, 3).\n" + "\n" + "%equation 4\n" + "hasatom(v(x1), 0, 4).\n" + "hasatom(v(x1), 1, 4).\n" + "hasatom(v(x9), 1, 4).\n" + "\n" + "%equation 5\n" + "hasatom(v(x1), 0, 5).\n" + "hasatom(e(r1, v(x7)), 1, 5).\n" + "\n" + "%equation 6\n" + "hasatom(v(x4), 0, 6).\n" + "hasatom(v(x3), 1, 6).\n" + "hasatom(v(x13), 1, 6).\n" + "\n" + "%equation 7\n" + "hasatom(v(x2), 0, 7).\n" + "hasatom(e(r1, v(x4)), 1, 7).\n" + "\n" + "%equation 8\n" + "hasatom(v(x7), 0, 8).\n" + "hasatom(v(x2), 1, 8).\n" + "hasatom(v(x7), 1, 8).\n" + "\n" + "%equation 9\n" + "hasatom(v(x5), 0, 9).\n" + "hasatom(e(r1, v(x3)), 1, 9).\n" + "\n" + "%disequation 1\n" + "diseq(v(x6), v(x9)).\n" + "\n" + "relevant(x7).\n" + "relevant(x9).\n" + "relevant(x13).\n" + , {"r("}))); + + } + + SECTION("disjunctionBug") { + REQUIRE( + "([],[-:1:21-22: info: atom does not occur in any rule head:\n d\n])" == + IO::to_string(solve( + "b." + "c :- b." + "a :- c." + "c : d :- a." + ))); + } + + SECTION("disjunctionBug2") { + REQUIRE( + "([[b(0),h(0),h(1),p(0)]],[])" == + IO::to_string(solve( + "p(0)." + "h(0;1)." + "b(0)." + "p(X) : h(X) :- p(Y), b(Y)." + ))); + } + + SECTION("aggregateNotNot") { + REQUIRE( + "([[p(2)],[p(2),p(3)],[p(2),p(3),p(4)],[p(2),p(3),p(4),p(5)],[p(2),p(3),p(5)],[p(2),p(4)],[p(2),p(4),p(5)],[p(2),p(5)],[p(4)],[p(4),p(5)]],[])" == + IO::to_string(solve( + "{ p(1..5) }." + ":- not not 2 != #min { X:p(X) } != 4."))); + REQUIRE( + "([[p(2)],[p(2),p(3)],[p(2),p(3),p(4)],[p(2),p(3),p(4),p(5)],[p(2),p(3),p(5)],[p(2),p(4)],[p(2),p(4),p(5)],[p(2),p(5)],[p(4)],[p(4),p(5)]],[])" == + IO::to_string(solve( + "{ p(1..5) }." + ":- 2 != #min { X:p(X) } != 4."))); + REQUIRE( + "([[p(2)],[p(2),p(3)],[p(2),p(3),p(4)],[p(2),p(3),p(4),p(5)],[p(2),p(3),p(5)],[p(2),p(4)],[p(2),p(4),p(5)],[p(2),p(5)],[p(4)],[p(4),p(5)]],[])" == + IO::to_string(solve( + "{ p(1..5) }." + "h :- not 2 != #min { X:p(X) } != 4." + ":- not h.", {"p("}))); + REQUIRE( + "([[p(2)],[p(2),p(3)],[p(2),p(3),p(4)],[p(2),p(3),p(4),p(5)],[p(2),p(3),p(5)],[p(2),p(4)],[p(2),p(4),p(5)],[p(2),p(5)],[p(4)],[p(4),p(5)]],[])" == + IO::to_string(solve( + "{ p(1..5) }." + ":- not 2 = #min { X:p(X) }, not #min { X:p(X) } = 4."))); + } + SECTION("aggregateRecBug") { + REQUIRE( + "([],[])" == + IO::to_string(solve( + "a :- {a}!=1." + ))); + REQUIRE( + "([],[])" == + IO::to_string(solve( + "a :- #sum {1:a}!=1." + ))); + REQUIRE( + "([[b]],[])" == + IO::to_string(solve( + "b :- 0 #sum+ { 1: b }." + ))); + REQUIRE( + "([[b]],[])" == + IO::to_string(solve( + "b :- 0 #sum { 1: b }." + ))); + } + SECTION("symTabBug") { + REQUIRE( + "([[does(a,0),does(a,1)],[does(a,0),does(b,1)]],[])" == + IO::to_string(solve( + "time(0..1).\n" + "1 { does(M,T) : legal(M,T) } 1 :- time(T).\n" + "legal(a,T) :- time(T).\n" + "legal(b,T) :- does(a,0), time(T).\n", + {"does"}))); + } + SECTION("recAntiAggr") { + REQUIRE( + "([[p],[r]],[])" == + IO::to_string(solve( + "r :- #sum { 1:p } < 1.\n" + "p :- not r."))); + REQUIRE( + "([[],[p]],[])" == + IO::to_string(solve("p :- #sum { 1:not p } < 1."))); + REQUIRE( + "([[],[p]],[])" == + IO::to_string(solve("p :- not #sum { 1:p } < 1."))); + REQUIRE( + "([[],[p]],[])" == + IO::to_string(solve("p :- not #sum { 1:not p } > 0."))); + REQUIRE( + "([[],[p]],[])" == + IO::to_string(solve("p :- not not #sum { 1:p } > 0."))); + REQUIRE( + "([[],[p]],[])" == + IO::to_string(solve("p :- not not #sum { 1:not p } < 1."))); + } + SECTION("headAggrPropagateBug") { + REQUIRE( + "([[a(c),a(p),b(c,d),b(c,e),b(c,f),b(c,g),b(p,d),b(p,e),b(p,f),b(p,g)]," + "[a(c),a(p),b(c,d),b(c,e),b(c,g),b(p,d),b(p,e),b(p,g),e(3)]," + "[b(c,d),b(c,e),b(p,d),b(p,e),e(2),e(3)]],[-:1:19-20: info: atom does not occur in any rule head:\n c\n])" == IO::to_string(solve( + "b(S,h) :- b(S,X), c.\n" + "b(c,d).\n" + "b(p,X) :- b(c,X).\n" + "b(c,e).\n" + "a(S) :- b(S,g).\n" + "1 = { e(3); b(S,f) : a(S) } :- b(S,e).\n" + "1 = { e(2); b(S,g) } :- b(S,d).\n"))); + //REQUIRE("[-:1:19-20: info: atom does not occur in any rule head:\n c\n]" == IO::to_string(msg.messages)); + } + SECTION("headAggregateBug") { + REQUIRE("([[q(a),r(a)]],[-:1:18-22: info: atom does not occur in any rule head:\n z(X)\n])" == IO::to_string(solve("1 { q(a); p(X) : z(X) }. r(X) :- q(X)."))); + REQUIRE("([[q(a),r(a)]],[-:1:12-16: info: atom does not occur in any rule head:\n z(X)\n])" == IO::to_string(solve("1 { p(X) : z(X); q(a) }. r(X) :- q(X)."))); + } + SECTION("head") { + REQUIRE("([[],[a],[a,b],[b]],[])" == IO::to_string(solve("{a;b}."))); + REQUIRE("([[a],[b]],[])" == IO::to_string(solve("1{a;b}1."))); + REQUIRE("([[p(1)],[p(1),p(2)],[p(1),p(3)],[p(1),p(4)],[p(2)],[p(2),p(3)],[p(2),p(4)],[p(3)],[p(3),p(4)],[p(4)]],[])" == IO::to_string(solve("1#count{X:p(X):X=1..4}2."))); + REQUIRE("([[p(1)],[p(2)]],[])" == IO::to_string(solve("1#sum+{X:p(X):X=1..4}2."))); + REQUIRE("([[p(1)],[p(2)]],[])" == IO::to_string(solve("1#sum {X:p(X):X=1..4}2."))); + REQUIRE( + "([[p(1)],[p(1),p(2)],[p(1),p(2),p(3)],[p(1),p(2),p(3),p(4)],[p(1),p(2),p(4)],[p(1),p(3)],[p(1),p(3),p(4)],[p(1),p(4)]," + "[p(2)],[p(2),p(3)],[p(2),p(3),p(4)],[p(2),p(4)]],[])" == IO::to_string(solve("1#min{X:p(X):X=1..4}2."))); + REQUIRE("([[p(1)],[p(1),p(2)],[p(2)]],[])" == IO::to_string(solve("1#max{X:p(X):X=1..4}2."))); + REQUIRE("([[c,p]],[])" == IO::to_string(solve("{p}. 1 {c:p}."))); + } + + SECTION("assign") { + REQUIRE("([[p,q(1)],[q(0)]],[])" ==IO::to_string(solve("{p}. q(M):-M=#count{1:p}."))); + REQUIRE("([[p,q(1)],[q(0)]],[])" ==IO::to_string(solve("{p}. q(M):-M=#sum+{1:p}."))); + REQUIRE("([[p,q(1)],[q(0)]],[])" ==IO::to_string(solve("{p}. q(M):-M=#sum{1:p}."))); + REQUIRE("([[p,q(p)],[q(#sup)]],[])" ==IO::to_string(solve("{p}. q(M):-M=#min{p:p}."))); + REQUIRE("([[p,q(p)],[q(#inf)]],[])" ==IO::to_string(solve("{p}. q(M):-M=#max{p:p}."))); + REQUIRE( + "([[p(1),p(2),q(1)]," + "[p(1),p(3),q(1)]," + "[p(1),p(4),q(1)]," + "[p(2),p(3),q(2)]," + "[p(2),p(4),q(2)]," + "[p(3),p(4),q(3)]],[])" == IO::to_string(solve("2{p(1..4)}2. q(M):-M=#min{X:p(X)}."))); + REQUIRE( + "([[p(1),p(2),q(2)]," + "[p(1),p(3),q(3)]," + "[p(1),p(4),q(4)]," + "[p(2),p(3),q(3)]," + "[p(2),p(4),q(4)]," + "[p(3),p(4),q(4)]],[])" == IO::to_string(solve("2{p(1..4)}2. q(M):-M=#max{X:p(X)}."))); + } + + SECTION("conjunction") { + REQUIRE( + "([],[-:1:4-5: info: atom does not occur in any rule head:\n b\n])" == + IO::to_string(solve( + "a:-b:c.\n" + "c:-a.\n"))); + REQUIRE( + "([[a,b,c]],[])" == + IO::to_string(solve( + "a:-b:c.\n" + "c:-a.\n" + "b:-c.\n", {"a", "b", "c"}))); + REQUIRE( + "([[a,b,c,d]],[])" == + IO::to_string(solve( + "a:-b:c,d.\n" + "c:-a.\n" + "d:-a.\n" + "b:-c.\n" + "b:-d.\n", {"a","b","c","d"}))); + REQUIRE( + "([[a(1),a(2),a(3),c,q],[a(3)]],[])" == + IO::to_string(solve( + "{c}.\n" + "a(1):-c.\n" + "a(2):-c.\n" + "a(3).\n" + "q:-a(X):X=1..3.\n"))); + REQUIRE( + "([[p],[q]],[])" == + IO::to_string(solve( + "p :- p:q.\n" + "q :- q:p.\n"))); + REQUIRE( + "([[p,q]],[])" == + IO::to_string(solve( + "p :- p:q.\n" + "q :- q:p.\n" + "p :- q.\n" + "q :- p.\n"))); + REQUIRE( + "([[],[p(1),r,s],[p(2),q,r],[p(3),r,s]],[])" == + IO::to_string(solve( + "{ p(1..3) } 1.\n" + "q :- p(Y..X) : Y = 2, X = 2.\n" + "r :- p(X) : #true.\n" + "s :- p(X-1;2*(X..X+1)-3) : X=2.\n" + ))); + REQUIRE( + "([[d(a),d(b),q(1,a),q(2,a)],[d(a),d(b),q(1,b),q(2,b)]],[])" == + IO::to_string(solve( + "d(a;b).\n" + "2 { q(1,a); q(1,b); q(2,a); q(2,b) } 2.\n" + " :- q(1,A;2,A) : d(A).\n" + ))); + } + SECTION("disjunction") { + REQUIRE( + "([[],[a,b,c,d],[c,x,y]],[])" == + IO::to_string(solve( + "{ y; d } 1.\n" + "c :- y.\n" + "c :- d.\n" + "b :- d.\n" + "x:y | a:b :- c.\n" + "b :- a.\n" + ))); + REQUIRE( + "([[a,b,c,d,x5]],[])" == + IO::to_string(solve( + "x5:-b.\n" + "x5:-not c.\n" + "d:-c.\n" + "c:-d.\n" + "\n" + "x5|d:-not not b.\n" + "a:-x5.\n" + "\n" + "c:-a.\n" + "b:-c.\n" + ))); + + REQUIRE( + "([[a,b,c],[b],[b,c],[c]],[])" == + IO::to_string(solve( + "1{b;c}.\n" + "a:b,c;not a.\n"))); + REQUIRE( + "([[],[p(1)],[p(1),p(2)],[p(2)]],[])" == + IO::to_string(solve( + "q(1..2).\n" + "p(X); not p(X) :- q(X).\n", {"p("}))); + REQUIRE( + "([[],[p(1),r(1)],[r(1)]],[])" == + IO::to_string(solve( + "q(1).\n" + "p(X); not p(X); not r(X) :- q(X).\n" + "r(X); not r(X) :- q(X).\n", {"p(", "r("}))); + REQUIRE( + "([[a,aux,b,c,p,s_b1,s_b2,s_c2]],[])" == + IO::to_string(solve( + "aux :- { a; b; c } > 2.\n" + + "p :- aux.\n" + "p :- not s_c2.\n" + + "s_b1 :- a.\n" + "s_b1 :- b.\n" + "a; b :- s_b1.\n" + + "s_b2 :- a, b.\n" + "a :- s_b2.\n" + "b :- s_b2.\n" + + "s_c2 :- c, s_b1.\n" + "s_c2 :- s_b2.\n" + "c; s_b2 :- s_c2.\n" + "s_b1; s_b2 :- s_c2.\n" + + "p; s_c2 :- not not aux.\n" + + "a :- p.\n" + "b :- p.\n" + "c :- p.\n" + + "p :- a.\n" + "p :- b.\n" + "p :- c.\n"))); + REQUIRE( + "([[p(1,a),p(2,a)],[p(1,b),p(2,b)]],[])" == + IO::to_string(solve( + "d(a;b).\n" + "p(1,A;2,A) : d(A).\n", {"p("}))); + REQUIRE( + "([[],[p(1),p(2)]],[])" == + IO::to_string(solve( + "r(1).\n" + "q(1,2).\n" + "p(1..Y) : q(X,Y) | not p(1..Y) : q(X,Y) :- r(X).\n", {"p("}))); + } + + SECTION("show") { + REQUIRE( + "([" + "[(1,2,3),-q(1),42]," + "[(1,2,3),-q(1),42]," + "[(1,2,3),-q(1),42,p(1)]," + "[(1,2,3),42]," + "[(1,2,3),42]," + "[(1,2,3),42,boo(1)]," + "[(1,2,3),42,boo(1)]," + "[(1,2,3),42,boo(1),p(1)]," + "[(1,2,3),42,p(1)]" + "],[])" == IO::to_string(solve( + "#show p/1.\n" + "#show -q/1.\n" + "#show boo(X):q(X).\n" + "#show -p/-1.\n" + "#show (1,2,3).\n" + "\n" + "{p(1); q(1); -p(1); -q(1)}.\n" + "\n" + "#const p=42.\n"))); + REQUIRE( + "([[a,c,x=1,y=1]],[])" == IO::to_string(solve( + "a. b.\n" + "$x $= 1. $y $= 1. $z $= 1.\n" + "#show a/0.\n" + "#show c.\n" + "#show $x/0.\n" + "#show $y.\n" + ))); + REQUIRE( + "([[x=1],[y=1]],[])" == + IO::to_string(solve( + "{b}.\n" + "$x $= 1. $y $= 1.\n" + "#show.\n" + "#show $x:b.\n" + "#show $y:not b.\n" + ))); + } + + SECTION("aggregates") { + REQUIRE("([[]],[])" == IO::to_string(solve("#sum { 1:b; 2:c } < 1.\n"))); + REQUIRE("([[p(1),p(2)],[p(1),p(3)],[p(2),p(3)]],[])" == IO::to_string(solve("{p(1..3)}.\n:-{p(X)}!=2."))); + REQUIRE("([[],[a,b],[b]],[])" == IO::to_string(solve("#sum { -1:a; 1:b } >= 0."))); + REQUIRE("([[],[a,b],[b]],[])" == IO::to_string(solve("#sum { 1:a; 2:b } != 1."))); + REQUIRE("([],[])" == IO::to_string(solve("a. {a} 0."))); + } + + SECTION("aggregates2") { + REQUIRE( + "([[c]],[])" == IO::to_string(solve( + "a :- not { c } >= 1, not c." + "b :- a, #false." + "c :- not b, {b; not b} >= 1." + ))); + REQUIRE( + "([[c]],[])" == IO::to_string(solve( + "a :- not not { c } >= 1, not c." + "b :- a, #false." + "c :- not b, {b; not b} >= 1." + ))); + } + + SECTION("invert") { + std::string prg = + "p(-1;2).\n" + "q(X) :- p((-(X+3))+2).\n" + "a(a;-b).\n" + "b(X) :- a(---X).\n" + "c(X) :- a(----X).\n"; + REQUIRE("([[a(-b),a(a),b(-a),b(b),c(-b),c(a),p(-1),p(2),q(-3),q(0)]],[])" == IO::to_string(solve(prg))); + } + + SECTION("minimize") { + std::string prg; + prg = + "{a; b; c; d}.\n" + "#minimize {1,a:a; 1,b:b; 1,c:c; 1,d:d}.\n" + "ok :- a, b,not c,not d.\n" + "ok :- not a,b, c, d.\n" + "ok :- a,not b, c, d.\n" + ":- not ok.\n"; + REQUIRE("([[a,b]],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {2}))); + REQUIRE("([],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {1}))); + prg = + "{a; b; c; d}.\n" + ":~ a. [1,a]\n" + ":~ b. [1,b]\n" + ":~ c. [1,c]\n" + ":~ d. [1,d]\n" + "ok :- a, b,not c,not d.\n" + "ok :- not a,b, c, d.\n" + "ok :- a,not b, c, d.\n" + ":- not ok.\n"; + REQUIRE("([[a,b]],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {2}))); + REQUIRE("([],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {1}))); + prg = + "{a; b; c; d}.\n" + "#maximize {-1,a:a; -1,b:b; -1,c:c; -1,d:d}.\n" + "ok :- a, b,not c,not d.\n" + "ok :- not a,b, c, d.\n" + "ok :- a,not b, c, d.\n" + ":- not ok.\n"; + REQUIRE("([[a,b]],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {2}))); + REQUIRE("([],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {1}))); + prg = + "{a; b; c; d}.\n" + "#minimize {3,a:a; 3,b:b; 1,x:c; 1,x:d}.\n" + "ok :- a, b,not c,not d.\n" + "ok :- not a,b, c, d.\n" + "ok :- a,not b, c, d.\n" + ":- not ok.\n" + ; + REQUIRE("([[a,c,d],[b,c,d]],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {4}))); + REQUIRE("([],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {3}))); + prg = + "{a; b; c; d}.\n" + "#minimize {3@2,a:a; 3@2,b:b; 1@2,x:c; 1@2,x:d}.\n" + "#minimize {1@1,x:a; 1@1,x:c; 1@1,y:b}.\n" + "ok :- a, b,not c,not d.\n" + "ok :- not a,b, c, d.\n" + "ok :- a,not b, c, d.\n" + ":- not ok.\n" + ; + REQUIRE("([[a,c,d]],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {4, 1}))); + REQUIRE("([],[])" == IO::to_string(solve(prg, {"a", "b", "c", "d"}, {4, 0}))); + REQUIRE("([[]],[])" == IO::to_string(solve("{p}. #maximize{1:not p}.", {"p"}, {-1}))); + } + + SECTION("csp") { + REQUIRE( + "([[p(1)=1,p(2)=1,x=1],[p(1)=1,p(2)=2,x=1],[p(1)=2,p(2)=1,x=1],[p(1)=2,p(2)=2,x=1]],[])" == + IO::to_string(solve( + "1 $<= $p(1..2) $<= 2.\n" + "$x $= 1.\n" + ))); + REQUIRE( + "([[x=0,y=0,z=2],[x=0,y=0,z=3],[x=0,y=1,z=3],[x=1,y=0,z=3]],[])" == + IO::to_string(solve( + "0 $<= $(x;y;z) $<= 3.\n" + "$x $+ $y $+ -1$*$z $<= -2.\n" + ))); + REQUIRE( + "([[x=0,y=0,z=2],[x=0,y=0,z=3],[x=0,y=1,z=3],[x=1,y=0,z=3]],[])" == + IO::to_string(solve( + "0 $<= $(x;y;z) $<= 3.\n" + "p:-$x $+ $y $+ -1$*$z $<= -2.\n" + ":- not p.\n", {"x", "y", "z"} + ))); + } + + SECTION("cspbound") { + REQUIRE( + "([[x=4],[x=5]],[])" == + IO::to_string(solve( + "$x $<= 5.\n" + ":- $x $<= 3, $x $<=4.\n", {"x="} + ))); + REQUIRE( + "([[x=2],[x=4],[x=6]],[])" == + IO::to_string(solve( + "$x $= 2*X : X = 1..3.\n", {"x="} + ))); + REQUIRE( + "([[x=1],[x=3],[x=7]],[])" == + IO::to_string(solve( + "$x $= 1; $x $= 3 :- $x $!= 7." + , {"x="}))); + } + + SECTION("disjoint") { + REQUIRE( + "([[x,x=2,y=2],[x=2,y=1],[x=2,y=2]],[])" == + IO::to_string(solve( + "1 $<= $x $<= 2.\n" + "1 $<= $y $<= 2.\n" + "{x}.\n" + "#disjoint{ 1:1; 2:$x; 2:$y : x }.\n" + ))); + REQUIRE( + "([[x=2]],[])" == + IO::to_string(solve( + "1 $<= $x $<= 2.\n" + "#disjoint{ 1:1; 2:$x }.\n" + ))); + REQUIRE( + "([[a,x=1],[b,x=1],[x=1]],[])" == + IO::to_string(solve( + "$x $= 1.\n" + "{ a; b }.\n" + "#disjoint{ a:$x:a; b:$x:b }.\n" + ))); + REQUIRE( + "([[a,b,y=2],[a,y=2],[b,y=2],[y=1],[y=2]],[])" == + IO::to_string(solve( + "1 $<= $y $<= 2.\n" + "{ a; b }.\n" + "#disjoint{ 1:1:a; 1:1:b; 2:$y }.\n" + ))); + REQUIRE( + "([[p(1)=1,p(2)=1,p(3)=1,q(1)=2,q(2)=2,q(3)=2],[p(1)=2,p(2)=2,p(3)=2,q(1)=1,q(2)=1,q(3)=1]],[])" == + IO::to_string(solve( + "1 $<= $(p(1..3);q(1..3)) $<= 2.\n" + "#disjoint{ 1:$p(1..3); 2:$q(1..3) }.\n" + ))); + REQUIRE( + "([[x=6,y=35]],[])" == + IO::to_string(solve( + "6 $<= $x $<= 7.\n" + "35 $<= $y $<= 36.\n" + "not #disjoint{ 1:6$*$y; 2:35$*$x }.\n" + ))); + REQUIRE( + "([[x=1,y=1,z=1]" + ",[x=2,y=2,z=2]" + ",[x=3,y=3,z=3]],[])" == + IO::to_string(solve( + "1 $<= $(x;y;z) $<= 3.\n" + "not #disjoint{ 1:2$*$x $+ 3$*$y; 2:2$*$y $+ 3$*$z; 3:2$*$z $+ 3$*$x }.\n" + ))); + REQUIRE( + "([[x=6,y=35]],[])" == + IO::to_string(solve( + "6 $<= $x $<= 7.\n" + "35 $<= $y $<= 36.\n" + "not #disjoint{ 1:6$*$y; 2:35$*$x }.\n" + ))); + REQUIRE( + "([[a],[a,b]],[])" == + IO::to_string(solve( + "{b}.\n" + "a :- #disjoint { 1 : 1 : a; 2 : 2 : a; 3 : 3 : b }.\n" + ))); + REQUIRE( + "([],[])" == + IO::to_string(solve( + "{b}.\n" + "a :- #disjoint { 1 : 1 : a; 2 : 1 : a; 3 : 3 : b }.\n" + ))); + REQUIRE( + "([[a]],[])" == + IO::to_string(solve( + "{b}.\n" + "a :- #disjoint { 1 : 1 : a; 2 : 2 : a; 3 : 2 : b }.\n" + ))); + REQUIRE( + "([[b]],[])" == + IO::to_string(solve( + "{b}.\n" + "a :- #disjoint { 1 : 1 : a; 2 : 1 : a; 3 : 3 : b; 4 : 3 : b }.\n" + ))); + REQUIRE( + 576 == solve( + "#const n = 4.\n" + "row(1..n).\n" + "col(1..n).\n" + "dom(1,n).\n" + "\n" + "L $<= $cell(X,Y) $<= U :- row(X), col(Y), dom(L,U).\n" + ":- col(Y), not #disjoint { X : $cell(X,Y) : row(X) }.\n" + ":- row(X), not #disjoint { Y : $cell(X,Y) : col(Y) }.\n" + ).first.size()); + } + + SECTION("queens") { + REQUIRE( + "([[q(1,2),q(2,4),q(3,6),q(4,1),q(5,3),q(6,5)]," + "[q(1,3),q(2,6),q(3,2),q(4,5),q(5,1),q(6,4)]," + "[q(1,4),q(2,1),q(3,5),q(4,2),q(5,6),q(6,3)]," + "[q(1,5),q(2,3),q(3,1),q(4,6),q(5,4),q(6,2)]],[])" == + IO::to_string(solve( + "#const n = 6.\n" + "n(1..n).\n" + "\n" + "q(X,Y) :- n(X), n(Y), not not q(X,Y).\n" + "\n" + " c(r,X; c,Y) :- q(X,Y).\n" + "not not c(r,N; c,N) :- n(N).\n" + "\n" + "n(r,X,Y-1,X,Y; c,X-1,Y,X,Y; d1,X-1,Y-1,X,Y; d2,X-1,Y+1,X,Y ) :- n(X), n(Y).\n" + "c(r,N,0; c,0,N; d1,N-1,0; d1,0,N-1; d2,N-1,n+1; d2,0,N+1) :- n(N).\n" + "\n" + "c(C,XX,YY) :- c(C,X,Y), n(C,X,Y,XX,YY), not q(XX,YY).\n" + " :- not c(C,X,Y), n(C,X,Y,XX,YY), q(XX,YY).\n", {"q("}))); + REQUIRE( + 48 == solve( + "#const n=4.\n" + "1 $<= $(row(X);col(X)) $<= n :- X=1..n.\n" + "$row(X) $!= $row(Y) :- X=1..n, Y=1..n, X= 2.\n" + "z :- #min { 1:a;2:b;3:c } <= 2.\n"))); + } + + SECTION("nonmon") { + REQUIRE( + "([[true(e,x1,1)]],[])" == + IO::to_string(solve( + "{ true(e,L,C) } :- var(e,L,C).\n" + "true(a,L,C) :- unequal, var(a,L,C).\n" + "unequal :- int(V), #sum{ C,Q,L : true(Q,L,C) } != V.\n" + ":- not unequal.\n" + + "var(e,x1,1).\n" + "var(e,x2,2).\n" + "var(a,y1,2).\n" + "var(a,y2,3).\n" + "int(5).\n", {"true(e"}))); + REQUIRE( + "([[true(e,x1,1)]],[])" == + IO::to_string(solve( + "{ true(e,L,C) } :- var(e,L,C).\n" + "true(a,L,C) :- unequal, var(a,L,C).\n" + "unequal :- int(V), #sum{ C,Q,L : true(Q,L,C) } != V.\n" + ":- not unequal.\n" + + "var(e,x1,1).\n" + "var(e,x2,2).\n" + "var(a,y1,2).\n" + "var(a,y2,3).\n" + "int(5).\n", {"true(e"}))); + + REQUIRE( + "([],[])" == + IO::to_string(solve( + "{ true(e,L,C) } :- var(e,L,C).\n" + "true(a,L,C) :- unequal, var(a,L,C).\n" + "unequal :- int(V), #sum{ C,Q,L : true(Q,L,C) } != V.\n" + ":- not unequal.\n" + + "var(e,x1,2).\n" + "var(e,x2,4).\n" + "var(a,y1,-2).\n" + "var(a,y2,4).\n" + "int(4).\n", {"true(e"}))); + + REQUIRE( + "([[],[true(e,x1,6),true(e,x2,3)]],[])" == + IO::to_string(solve( + "{ true(e,L,C) } :- var(e,L,C).\n" + "true(a,L,C) :- unequal, var(a,L,C).\n" + "unequal :- int(V), #sum{ C,Q,L : true(Q,L,C) } != V.\n" + ":- not unequal.\n" + + "var(e,x1,6).\n" + "var(e,x2,3).\n" + "var(a,y1,-2).\n" + "var(a,y2,1).\n" + "int(4).\n", {"true(e"}))); + } + + SECTION("edge") { + REQUIRE( + "([[path(a,b),path(b,c),path(c,d),path(d,a)]],[])" == + IO::to_string(solve( + "node(a;b;c;d).\n" + "edge(a,b;b,(c;d);c,(a;d);d,a).\n" + "1 { path(X,Y) : edge(X,Y) } 1 :- node(X).\n" + "1 { path(X,Y) : edge(X,Y) } 1 :- node(Y).\n" + "start(X) :- X = #min { Y : node(Y) }.\n" + "#edge (X,Y) : path(X,Y), not start(Y).\n", {"path("}))); + } + + SECTION("bugRewriteCond") { + REQUIRE( + "([[p(1)],[p(1),p(2)],[p(2)]],[])" == + IO::to_string(solve( + "{p(1..2)}.\n" + ":- #false:p(X).\n", {"p("}))); + } + +} + +#ifdef WITH_PYTHON + +TEST_CASE("output-lparse-python", "[output][python]") { + REQUIRE( + "([[p(39),q(\"a\"),q(1),q(2),q(a),r(2),r(3),s((1,2)),s((1,3)),s((2,1))]],[])" == IO::to_string(solve( + "#script (python)\n" + "import clingo\n" + "def conv(a): return a.number if hasattr(a, 'number') else a\n" + "def pygcd(a, b): return b if conv(a) == 0 else pygcd(conv(b) % conv(a), a)\n" + "def pytest(): return [1, 2, clingo.Function(\"a\"), \"a\"]\n" + "def pymatch(): return [(1,2),(1,3),(2,1)]\n" + "#end.\n" + "\n" + "p(@pygcd(2*3*7*13,3*11*13)).\n" + "q(@pytest()).\n" + "r(X) :- (1,X)=@pymatch().\n" + "s(X) :- X=@pymatch().\n" + ))); +} + +#endif // WITH_PYTHON + +#ifdef WITH_LUA + +TEST_CASE("output-lparse-lua", "[output][lua]") { + REQUIRE( + "([[p(39),q(\"a\"),q(1),q(2),q(a),r(2),r(3),s((1,2)),s((1,3)),s((2,1))]],[])" == IO::to_string(solve( + "#script (lua)\n" + "function conv(a) if type(a) == 'number' then return a else return a.number end end\n" + "function luagcd(a, b) if conv(a) == 0 then return b else return luagcd(conv(b) % conv(a), a) end end\n" + "function luatest() return {1, 2, clingo.Function(\"a\"), \"a\"} end\n" + "function luamatch() return {clingo.Tuple{1,2},clingo.Tuple{1,3},clingo.Tuple{2,1}} end\n" + "#end.\n" + "\n" + "p(@luagcd(2*3*7*13,3*11*13)).\n" + "q(@luatest()).\n" + "r(X) :- (1,X)=@luamatch().\n" + "s(X) :- X=@luamatch().\n" + ))); +} +#endif // WITH_LUA + +} } } // namespace Test Output Gringo + diff --git a/libgringo/tests/output/solver_helper.hh b/libgringo/tests/output/solver_helper.hh new file mode 100644 index 0000000..43a635e --- /dev/null +++ b/libgringo/tests/output/solver_helper.hh @@ -0,0 +1,141 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_OUTPUT_TEST_SOLVER_HELPER_HH +#define _GRINGO_OUTPUT_TEST_SOLVER_HELPER_HH + +#include "gringo/logger.hh" +#include "gringo/ground/dependency.hh" +#include "gringo/input/nongroundparser.hh" +#include "gringo/input/program.hh" +#include "gringo/output/output.hh" +#include "gringo/scripts.hh" + +#include "tests/tests.hh" + +#include +#include +#include + + +namespace Gringo { namespace Output { namespace Test { + +// {{{ definition of solve + +using Model = std::vector; +using Filter = std::initializer_list; +using Models = std::vector; +using ModelsAndMessages = std::pair, std::vector>; + +class ModelPrinter : public Clasp::EventHandler { +public: + ModelPrinter(Models &models, Filter &filter) : models(models), filter(filter) {} + bool onModel(const Clasp::Solver& s, const Clasp::Model& m) { + models.emplace_back(); + const Clasp::OutputTable& out = s.outputTable(); + for (Clasp::OutputTable::pred_iterator it = out.pred_begin(); it != out.pred_end(); ++it) { + if (m.isTrue(it->cond)) { + onAtom(it->name.c_str()); + } + } + for (Clasp::OutputTable::fact_iterator it = out.fact_begin(); it != out.fact_end(); ++it) { + onAtom(it->c_str()); + } + std::sort(models.back().begin(), models.back().end()); + return true; + } + void onAtom(std::string&& atom) { + for (auto &x : filter) { + if (atom.compare(0, x.size(), x) == 0) { + models.back().emplace_back(std::move(atom)); + return; + } + } + + } + Models ⊧ + Filter &filter; +}; + +struct ClingoState { + ClingoState() + : out(td, {}, ss, OutputFormat::INTERMEDIATE) + , scripts(module) + , pb(scripts, prg, out, defs) + , parser(pb) { + } + Gringo::Test::TestGringoModule module; + std::stringstream ss; + Potassco::TheoryData td; + OutputBase out; + Input::Program prg; + Defines defs; + Scripts scripts; + Input::NongroundProgramBuilder pb; + Input::NonGroundParser parser; +}; + +inline bool ground(ClingoState &state) { + // grounder: ground + if (!state.module.logger.hasError()) { + Ground::Program gPrg(state.prg.toGround(state.out.data, state.module)); + state.out.init(false); + state.out.beginStep(); + gPrg.ground(state.scripts, state.out, state.module); + return true; + } + return false; +} + +inline Models solve(ClingoState &state, std::string const &str, Filter filter = {""}, std::initializer_list minimize = {}) { + state.parser.pushStream("-", gringo_make_unique(str), state.module); + Models models; + // grounder: parse + state.parser.parse(state.module); + // grounder: preprocess + state.defs.init(state.module); + state.prg.rewrite(state.defs, state.module); + state.prg.check(state.module); + if (ground(state)) { + Clasp::ClaspFacade libclasp; + Clasp::ClaspConfig config; + config.solve.numModels = 0; + config.solve.optMode = Clasp::EnumOptions::OptMode::enumerate; + config.solve.optBound.assign(minimize.begin(), minimize.end()); + Clasp::Asp::LogicProgram &prg = libclasp.startAsp(config); + prg.parseProgram(state.ss); + libclasp.prepare(); + ModelPrinter printer(models, filter); + libclasp.solve(&printer); + } + std::sort(models.begin(), models.end()); + return models; +} + +inline ModelsAndMessages solve(std::string const &str, std::initializer_list filter = {""}, std::initializer_list minimize = {}) { + ClingoState state; + return {solve(state, str, filter, minimize), state.module.messages()}; +} + +// }}} + +} } } // namespace Test Output Gringo + +#endif // _GRINGO_OUTPUT_TEST_SOLVER_HELPER_HH diff --git a/libgringo/tests/output/theory.cc b/libgringo/tests/output/theory.cc new file mode 100644 index 0000000..95aa364 --- /dev/null +++ b/libgringo/tests/output/theory.cc @@ -0,0 +1,240 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/output/solver_helper.hh" +#include "tests/ground/grounder_helper.hh" + +namespace Gringo { namespace Output { namespace Test { + +TEST_CASE("output-theory", "[output]") { + SECTION("directive") { + std::string theory = + "#theory t {" + " group { };" + " &a/0 : group, directive" + "}."; + REQUIRE( + "9 1 0 1 a\n" + "9 5 0 0 0\n" + "0\n" == + Gringo::Ground::Test::groundAspif( + theory + + "&a { }.")); + } + + SECTION("head") { + std::string theory = + "#theory t {" + " group { };" + " &a/0 : group, head" + "}."; + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 5 1 0 0\n" + "0\n" == + Gringo::Ground::Test::groundAspif( + theory + + "&a { }.")); + } + + SECTION("body") { + std::string theory = + "#theory t {" + " group { };" + " &a/0 : group, body" + "}."; + REQUIRE( + "1 0 0 0 1 1\n" + "9 1 0 1 a\n" + "9 5 1 0 0\n" + "0\n" == + Gringo::Ground::Test::groundAspif( + theory + + ":-&a { }.")); + } + + SECTION("guard") { + std::string theory = + "#theory t {\n" + " group { };\n" + " &a/0 : group, {=}, group, directive\n" + "}.\n"; + REQUIRE( + "9 1 0 1 a\n" + "9 1 2 1 =\n" + "9 0 1 1\n" + "9 6 0 0 0 2 1\n" + "0\n" == + Gringo::Ground::Test::groundAspif( + theory + + "&a { } = 1.")); + } + + SECTION("term") { + std::string theory = + "#theory t {\n" + " group {\n" + " + : 4, unary;\n" + " - : 4, unary;\n" + " ^ : 3, binary, right;\n" + " * : 2, binary, left;\n" + " + : 1, binary, left;\n" + " - : 1, binary, left\n" + " };\n" + " &a/0 : group, head\n" + "}.\n"; + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 4 0 0 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { : }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 1 1\n" + "9 4 0 2 1 1 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { 1,1 }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 2 1 -1 0\n" + "9 4 0 1 1 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { () }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 1 1 4 #sup\n" + "9 4 0 1 1 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { #sup }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 1 1 4 #inf\n" + "9 4 0 1 1 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { #inf }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 2 1\n" + "9 1 1 1 f\n" + "9 2 3 1 1 2\n" + "9 4 0 1 3 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { f(1) }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 1 1\n" + "9 2 2 -1 1 1\n" + "9 4 0 1 2 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { (1,) }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 1 1\n" + "9 0 2 2\n" + "9 2 3 -1 2 1 2\n" + "9 4 0 1 3 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { (1,2) }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 1 1\n" + "9 0 2 2\n" + "9 2 3 -2 2 1 2\n" + "9 4 0 1 3 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { {1,2} }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 1 1\n" + "9 0 2 2\n" + "9 2 3 -3 2 1 2\n" + "9 4 0 1 3 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { [1,2] }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 2 1\n" + "9 1 1 1 -\n" + "9 2 3 1 1 2\n" + "9 4 0 1 3 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { (-1) }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 2 1\n" + "9 1 1 1 -\n" + "9 2 3 1 1 2\n" + "9 4 0 1 3 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { X } :- X=-1.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 3 1\n" + "9 1 2 1 +\n" + "9 2 4 2 1 3\n" + "9 1 1 1 -\n" + "9 2 5 1 1 4\n" + "9 4 0 1 5 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { - + 1 }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 2 1\n" + "9 0 3 2\n" + "9 1 1 1 ^\n" + "9 2 4 1 2 2 3\n" + "9 4 0 1 4 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { 1^2 }.")); + REQUIRE( + "1 0 1 1 0 0\n" + "9 1 0 1 a\n" + "9 0 2 1\n" + "9 0 4 2\n" + "9 0 5 3\n" + "9 1 3 1 *\n" + "9 2 6 3 2 4 5\n" + "9 1 1 1 +\n" + "9 2 7 1 2 2 6\n" + "9 4 0 1 7 0\n" + "9 5 1 0 1 0\n" + "0\n" == Gringo::Ground::Test::groundAspif(theory + "&a { 1+2*3 }.")); + } +} + +} } } // namespace Test Output Gringo + diff --git a/libgringo/tests/output/warnings.cc b/libgringo/tests/output/warnings.cc new file mode 100644 index 0000000..3fac793 --- /dev/null +++ b/libgringo/tests/output/warnings.cc @@ -0,0 +1,86 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "tests/term_helper.hh" +#include "tests/output/solver_helper.hh" + +#include "gringo/ground/dependency.hh" +#include "gringo/input/nongroundparser.hh" + +namespace Gringo { namespace Output { namespace Test { + +TEST_CASE("output-warnings", "[output]") { + SECTION("warnings_simplify") { + REQUIRE("([[]],[-:1:3-6: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("p(a+0)."))); + REQUIRE("([[]],[-:1:8-11: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- X=a+0."))); + REQUIRE("([[]],[-:1:8-11: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- p(a+0)."))); + REQUIRE("([[]],[-:1:3-6: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("p(a+0) : #true."))); + REQUIRE("([[]],[-:1:8-11: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- p(a+0) : #true."))); + REQUIRE("([[]],[-:1:6-9: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve(":~ p(a+0). [0]"))); + REQUIRE("([[]],[-:1:7-10: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve(":~ . [a+0]"))); + + REQUIRE("([[]],[-:1:5-8: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("{ p(a+0) }."))); + REQUIRE("([[]],[-:1:9-12: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("{ q : p(a+0) }."))); + REQUIRE("([[]],[-:1:16-19: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("#count { q : p(a+0) }."))); + REQUIRE("([[]],[-:1:12-15: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("#count { p(a+0) : q }."))); + REQUIRE("([[]],[-:1:20-23: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("#count { q : q : p(a+0) }."))); + + REQUIRE("([[q]],[-:1:16-19: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- #true : p(a+0)."))); + REQUIRE("([[q]],[-:1:12-15: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- 0 { p(a+0) } 0."))); + REQUIRE("([[q]],[-:1:16-19: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- 0 { q : p(a+0) } 0."))); + REQUIRE("([[q]],[-:1:19-22: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- 0 #count { p(a+0) } 0."))); + REQUIRE("([[q]],[-:1:23-26: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("q :- 0 #count { q : p(a+0) } 0."))); + + REQUIRE("([],[-:1:11-14: info: operation undefined:\n (a+0)\n])" == IO::to_string(solve("#true : q(a+0)."))); + } + + SECTION("warnings") { + REQUIRE("([[]],[-:1:3-7: info: interval undefined:\n 1..f\n])" == IO::to_string(solve("p(1..f)."))); + REQUIRE("([[p(1)]],[-:1:11-15: info: interval undefined:\n 1..f\n])" == IO::to_string(solve("p(1). :-p(1..f)."))); + REQUIRE("([[p(bot)]],[-:2:3-6: info: operation undefined:\n (1/X)\n])" == IO::to_string(solve("p(bot).\nq(1/X):-p(X).\n"))); + REQUIRE("([[p(bot)]],[-:2:6-7: info: operation undefined:\n (X+0)\n])" == IO::to_string(solve("p(bot).\n#sum{X:q(X):p(X)}.\n"))); + REQUIRE("([[p(bot)]],[-:2:10-11: info: tuple ignored:\n bot\n])" == IO::to_string(solve("p(bot).\nx:-1#sum{X:p(X)}.\n"))); + REQUIRE("([[p(bot)]],[-:2:4-16: info: empty tuple ignored\n])" == IO::to_string(solve("p(bot).\nx:-1#sum{:p(X)}.\n"))); + REQUIRE("([[]],[-:1:1-13: info: no atoms over signature occur in program:\n bot/0\n])" == IO::to_string(solve("#show bot/0.\n"))); + REQUIRE("([[]],[-:1:4-7: info: atom does not occur in any rule head:\n bot\n])" == IO::to_string(solve("x:-bot.\n"))); + REQUIRE("([[p(bot)]],[-:2:11-12: info: tuple ignored:\n bot@0\n])" == IO::to_string(solve("p(bot).\n:~ p(X). [X]\n"))); + REQUIRE("([[a]],[])" == IO::to_string(solve("a:-#sum{-1:a;1:a}>=0.\n"))); + REQUIRE("([[a]],[])" == IO::to_string(solve("a:-#sum{1:a;2:a}!=1.\n"))); + REQUIRE("([[a]],[])" == IO::to_string(solve("a:-X=#sum{-1:a;1:a},X>=0,X<=0.\n"))); + REQUIRE("([],[-:1:1-12: error: cyclic constant definition:\n #const a=b.\n-:2:1-12: note: cycle involves definition:\n #const b=a.\n])" == IO::to_string(solve("#const a=b.\n#const b=a.\n"))); + REQUIRE("([[]],[])" == IO::to_string(solve("#const a=a.\n"))); + REQUIRE("([],[-:2:1-12: error: redefinition of constant:\n #const a=2.\n-:1:1-12: note: constant also defined here\n])" == IO::to_string(solve("#const a=1.\n#const a=2.\np(a).\n"))); +#ifndef _MSC_VER + std::ofstream("/tmp/wincluded.lp"); + REQUIRE("([[]],[-:1:30-59: warning: already included file:\n /tmp/wincluded.lp\n])" == IO::to_string(solve("#include \"/tmp/wincluded.lp\".#include \"/tmp/wincluded.lp\"."))); +#endif + REQUIRE( + "([[x=1,y=-1,z=0]]," + "[warning: unbounded constraint variable:\n domain of 'x' is set to [1,1]\n" + ",warning: unbounded constraint variable:\n domain of 'y' is set to [-1,-1]\n" + ",warning: unbounded constraint variable:\n domain of 'z' is set to [0,0]\n" + "])" == IO::to_string(solve("$x $> 0.\n$y $< 0.\na:-$z $> 0.\n"))); + REQUIRE("([[]],[-:1:1-12: info: no constraint variables over signature occur in program:\n $y/0\n])" == IO::to_string(solve("#show $y/0."))); + REQUIRE("([[]],[info: constraint variable does not occur in program:\n $y\n])" == IO::to_string(solve("#show $y."))); + } +} + +} } } // namespace Test Output Gringo diff --git a/libgringo/tests/python.cc b/libgringo/tests/python.cc new file mode 100644 index 0000000..472e3dc --- /dev/null +++ b/libgringo/tests/python.cc @@ -0,0 +1,171 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifdef WITH_PYTHON + +#include "tests/tests.hh" +#include "gringo/python.hh" + +namespace Gringo { namespace Test { + +using namespace Gringo::IO; +using S = std::string; + +namespace { + +std::string replace(std::string &&x, std::string const &y, std::string const &z) { + size_t index = 0; + while (true) { + index = x.find(y, index); + if (index == std::string::npos) { break; } + x.replace(index, y.size(), z); + index += z.size(); + } + return std::move(x); +} + +} // namspace + +TEST_CASE("python", "[base][python]") { + TestGringoModule module; + SymSpan const empty{nullptr, 0}; + SECTION("parse") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Python py(module); + py.exec(loc, + "import clingo\n" + "def get(): return clingo.parse_term('1')\n" + ); + REQUIRE("[1]" == to_string(py.call(loc, "get", empty, module))); + py.exec(loc, + "import clingo\n" + "def get(): return clingo.parse_term('p(1+2)')\n" + ); + REQUIRE("[p(3)]" == to_string(py.call(loc, "get", empty, module))); + py.exec(loc, + "import clingo\n" + "def get(): return clingo.parse_term('-p')\n" + ); + REQUIRE("[-p]" == to_string(py.call(loc, "get", empty, module))); + py.exec(loc, + "import clingo\n" + "def get(): return clingo.parse_term('-p(1)')\n" + ); + REQUIRE("[-p(1)]" == to_string(py.call(loc, "get", empty, module))); + } + SECTION("values") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Python py(module); + py.exec(loc, + "import clingo\n" + "x = clingo.Function(\"f\", [2, 3, 4])\n" + "y = clingo.Function(\"f\", [2, 3, 4], False)\n" + "def getX(): return x\n" + "def fail(): return clingo.Function(\"g\", [None])\n" + "def none(): return None\n" + "values = [" + "clingo.Function(\"f\", [1, 2, 3])," + "clingo.Supremum," + "clingo.Infimum," + "clingo.Function(\"id\")," + "(1, 2, 3)," + "123," + "\"abc\"," + "tuple(x.arguments)," + "x.name," + "x.negative," + "y.negative," + "x," + "y," + "]\n" + "def getValues(): return values\n" + ); + REQUIRE("[f(2,3,4)]" == to_string(py.call(loc, "getX", empty, module))); + REQUIRE("[f(1,2,3),#sup,#inf,id,(1,2,3),123,\"abc\",(2,3,4),\"f\",0,1,f(2,3,4),-f(2,3,4)]" == to_string(py.call(loc, "getValues", empty, module))); + { + REQUIRE("[]" == to_string(py.call(loc, "none", empty, module))); + REQUIRE( + "[" + "dummy:1:1: info: operation undefined:\n" + " RuntimeError: cannot convert to value: unexpected NoneType() object\n" + "]" == IO::to_string(module)); + } + { + module.reset(); + REQUIRE("[]" == to_string(py.call(loc, "fail", empty, module))); + REQUIRE( + "[" + "dummy:1:1: info: operation undefined:\n" + " Traceback (most recent call last):\n" + " File \"\", line 5, in fail\n" + " RuntimeError: cannot convert to value: unexpected NoneType() object\n" + "]" == IO::to_string(module)); + } + { + module.reset(); + try { + py.exec(loc, "("); + FAIL("no exception"); + } + catch (std::runtime_error const &e) { + REQUIRE( + "dummy:1:1: error: parsing failed:\n" + " File \"\", line 1\n" + " (\n" + " ^\n" + " SyntaxError: unexpected EOF while parsing\n" + "" == replace(e.what(), "column 1", "column 2")); + } + } + } + + SECTION("cmp") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Python py(module); + py.exec(loc, + "import clingo\n" + "def cmp():\n" + " return [" + "int(clingo.Function(\"a\") < clingo.Function(\"b\"))," + "int(clingo.Function(\"b\") < clingo.Function(\"a\"))," + "]\n" + ); + REQUIRE("[1,0]" == to_string(py.call(loc, "cmp", empty, module))); + } + + SECTION("callable") { + Location loc("dummy", 1, 1, "dummy", 1, 1); + Python py(module); + py.exec(loc, + "import clingo\n" + "def a(): pass\n" + "b = 1\n" + ); + REQUIRE(py.callable("a")); + REQUIRE(!py.callable("b")); + REQUIRE(!py.callable("c")); + } + +} + +} } // namespace Test Gringo + +#endif // WITH_PYTHON + diff --git a/libgringo/tests/safetycheck.cc b/libgringo/tests/safetycheck.cc new file mode 100644 index 0000000..f653641 --- /dev/null +++ b/libgringo/tests/safetycheck.cc @@ -0,0 +1,74 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/safetycheck.hh" + +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +#include + +namespace Gringo { namespace Test { + +using namespace Gringo::IO; + +// {{{ definition of auxiliary functions + +namespace { + +typedef SafetyChecker C; +typedef std::tuple, std::vector> T; + +std::string check(std::vector list) { + C dep; + std::unordered_map vars; + auto iv = [&vars, &dep](std::string const &y) -> C::VarNode& { + auto &pVar = vars[y]; + if (!pVar) { pVar = &dep.insertVar(y); } + return *pVar; + }; + for (auto &x : list) { + auto &ent(dep.insertEnt(std::get<0>(x))); + for (auto &y : std::get<1>(x)) { dep.insertEdge(iv(y), ent); } + for (auto &y : std::get<2>(x)) { dep.insertEdge(ent, iv(y)); } + } + std::vector order, open; + for (auto &x : dep.order()) { order.push_back(x->data); } + for (auto &x : dep.open()) { open.push_back(x->data); } + std::sort(open.begin(), open.end()); + return to_string(std::make_pair(std::move(order), std::move(open))); +} + +} // namespace + +// }}} + +TEST_CASE("safetycheck", "[base]") { + SECTION("safety") { + REQUIRE("([Y=1,X=Y],[])" == check({ T{"X=Y",{"Y"},{"X"}}, T{"Y=1",{},{"Y"}} })); + REQUIRE("([],[X,Y])" == check({ T{"0=X+Y",{"X","Y"}, {}} })); + REQUIRE("([A=1,B=A,C=B,D=C],[])" == check({ T{"A=1",{}, {"A"}}, T{"B=A",{"A"}, {"B"}}, T{"C=B",{"B"}, {"C"}}, T{"D=C",{"C"}, {"D"}} })); + REQUIRE("([],[A,B])" == check({ T{"A=B",{"B"}, {"A"}}, T{"B=A",{"A"}, {"B"}} })); + REQUIRE("([A=1,B=A,A=B],[])" == check({ T{"A=B",{"B"}, {"A"}}, T{"B=A",{"A"}, {"B"}}, T{"A=1",{}, {"A"}} })); + REQUIRE("([(X,Y)=(1,1),2=X+Y],[])" == check({ T{"(X,Y)=(1,1)",{}, {"X","Y"}}, T{"2=X+Y",{"X", "Y"}, {}} })); + } +} + +} } // namespace Test Gringo diff --git a/libgringo/tests/symbol.cc b/libgringo/tests/symbol.cc new file mode 100644 index 0000000..a1b63be --- /dev/null +++ b/libgringo/tests/symbol.cc @@ -0,0 +1,204 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "gringo/symbol.hh" + +#include + +namespace Gringo { namespace Test { + +TEST_CASE("symbol", "[base]") { + SymVec args = { Symbol::createNum(42), Symbol::createId("a") }; + SymVec symbols = { + Symbol::createNum(INT_MIN), + Symbol::createNum(INT_MAX), + Symbol::createNum(0), + Symbol::createNum(42), + + Symbol::createId("x"), + Symbol::createId("abc"), + + Symbol::createStr(""), + Symbol::createStr("xyz"), + + Symbol::createInf(), + Symbol::createSup(), + + Symbol::createTuple(Potassco::toSpan(args)), + Symbol::createFun("f", Potassco::toSpan(args)) + }; + + SECTION("types") { + REQUIRE(SymbolType::Num == symbols[0].type()); + REQUIRE(SymbolType::Num == symbols[1].type()); + REQUIRE(SymbolType::Num == symbols[2].type()); + REQUIRE(SymbolType::Num == symbols[3].type()); + + REQUIRE(SymbolType::Fun == symbols[4].type()); + REQUIRE(SymbolType::Fun == symbols[5].type()); + + REQUIRE(SymbolType::Str == symbols[6].type()); + REQUIRE(SymbolType::Str == symbols[7].type()); + + REQUIRE(SymbolType::Inf == symbols[8].type()); + REQUIRE(symbols[9].type() == SymbolType::Sup); + + REQUIRE(SymbolType::Fun == symbols[11].type()); + } + + SECTION("symbols") { + REQUIRE(INT_MIN == symbols[0].num()); + REQUIRE(INT_MAX == symbols[1].num()); + REQUIRE( 0 == symbols[2].num()); + REQUIRE(42 == symbols[3].num()); + + REQUIRE(String("x") == symbols[4].name()); + REQUIRE(String("abc") == symbols[5].name()); + + REQUIRE(String("") == symbols[6].string()); + REQUIRE(String("xyz") == symbols[7].string()); + + REQUIRE(size_t(2u) == symbols[10].args().size); + REQUIRE(42 == symbols[10].args()[0].num()); + REQUIRE(String("a") == symbols[10].args()[1].name()); + + REQUIRE(String("f") == symbols[11].name()); + REQUIRE(42 == symbols[11].args()[0].num()); + REQUIRE(String("a") == symbols[11].args()[1].name()); + } + + SECTION("cmp_num") { + REQUIRE(!(Symbol::createNum(0) < Symbol::createNum(0))); + REQUIRE( (Symbol::createNum(0) < Symbol::createNum(1))); + REQUIRE(!(Symbol::createNum(1) < Symbol::createNum(0))); + + REQUIRE(!(Symbol::createNum(0) > Symbol::createNum(0))); + REQUIRE(!(Symbol::createNum(0) > Symbol::createNum(1))); + REQUIRE( (Symbol::createNum(1) > Symbol::createNum(0))); + + REQUIRE( (Symbol::createNum(0) <= Symbol::createNum(0))); + REQUIRE( (Symbol::createNum(0) <= Symbol::createNum(1))); + REQUIRE(!(Symbol::createNum(1) <= Symbol::createNum(0))); + + REQUIRE( (Symbol::createNum(0) >= Symbol::createNum(0))); + REQUIRE(!(Symbol::createNum(0) >= Symbol::createNum(1))); + REQUIRE( (Symbol::createNum(1) >= Symbol::createNum(0))); + + REQUIRE( (Symbol::createNum(0) == Symbol::createNum(0))); + REQUIRE(!(Symbol::createNum(0) == Symbol::createNum(1))); + REQUIRE(!(Symbol::createNum(1) == Symbol::createNum(0))); + + REQUIRE(!(Symbol::createNum(0) != Symbol::createNum(0))); + REQUIRE( (Symbol::createNum(0) != Symbol::createNum(1))); + REQUIRE( (Symbol::createNum(1) != Symbol::createNum(0))); + } + + SECTION("cmp_type") { + REQUIRE(symbols[8] < symbols[0]); + REQUIRE(symbols[0] < symbols[4]); + REQUIRE(symbols[4] < symbols[6]); + REQUIRE(symbols[6] < symbols[10]); + REQUIRE(symbols[11] < symbols[9]); + } + + SECTION("cmp_other") { + REQUIRE(!(Symbol::createId("a") == Symbol::createId("a").flipSign())); + REQUIRE( (Symbol::createId("a") != Symbol::createId("a").flipSign())); + + REQUIRE(!(Symbol::createId("a") < Symbol::createId("a"))); + REQUIRE( (Symbol::createId("a") < Symbol::createId("a").flipSign())); + REQUIRE( (Symbol::createId("b") < Symbol::createId("a").flipSign())); + REQUIRE( (Symbol::createId("aaa") < Symbol::createId("aab"))); + REQUIRE( (Symbol::createId("a") < Symbol::createId("aa"))); + REQUIRE(!(Symbol::createId("aa") < Symbol::createId("a"))); + + REQUIRE(!(Symbol::createStr("a") < Symbol::createStr("a"))); + REQUIRE( (Symbol::createStr("aaa") < Symbol::createStr("aab"))); + REQUIRE( (Symbol::createStr("a") < Symbol::createStr("aa"))); + REQUIRE(!(Symbol::createStr("aa") < Symbol::createStr("a"))); + + Symbol a = Symbol::createTuple( Potassco::toSpan(SymVec{ Symbol::createNum(1), Symbol::createNum(1) }) ); + Symbol b = Symbol::createTuple( Potassco::toSpan(SymVec{ Symbol::createNum(1) }) ); + Symbol c = Symbol::createTuple( Potassco::toSpan(SymVec{ Symbol::createNum(1), Symbol::createNum(2) }) ); + Symbol d = Symbol::createTuple( Potassco::toSpan(SymVec{ Symbol::createNum(2) }) ); + REQUIRE(((b < a) && !(a < b))); + REQUIRE(((a < c) && !(c < a))); + REQUIRE(((b < d) && !(d < b))); + REQUIRE(((d < a) && !(a < d))); + + Symbol fa = Symbol::createFun( "f", Potassco::toSpan(SymVec{ Symbol::createNum(1), Symbol::createNum(1) }) ); + Symbol ga = Symbol::createFun( "g", Potassco::toSpan(SymVec{ Symbol::createNum(1), Symbol::createNum(1) })); + Symbol fb = Symbol::createFun( "f", Potassco::toSpan(SymVec{ Symbol::createNum(1) }) ); + Symbol fc = Symbol::createFun( "f", Potassco::toSpan(SymVec{ Symbol::createNum(1), Symbol::createNum(2) }) ); + Symbol fd = Symbol::createFun( "f", Potassco::toSpan(SymVec{ Symbol::createNum(2) }) ); + Symbol gd = Symbol::createFun( "g", Potassco::toSpan(SymVec{ Symbol::createNum(2) }) ); + REQUIRE(((fb < fa) && !(fa < fb))); + REQUIRE(((fa < fc) && !(fc < fa))); + REQUIRE(((fb < fd) && !(fd < fb))); + REQUIRE(((fd < fa) && !(fa < fd))); + REQUIRE(((fa < ga) && !(ga < fa))); + REQUIRE(((gd < fa) && !(fa < gd))); + REQUIRE(((fa < fa.flipSign()) && !(fa.flipSign() < fa))); + REQUIRE(((fa < ga.flipSign()) && !(ga.flipSign() < fa))); + } + + SECTION("print") { + std::ostringstream oss; + auto toString = [&oss](Symbol const &val) -> std::string { + oss << val; + std::string str = oss.str(); + oss.str(""); + return str; + + }; + REQUIRE("0" == toString(symbols[2])); + REQUIRE("42" == toString(symbols[3])); + REQUIRE("x" == toString(symbols[4])); + REQUIRE("-x" == toString(symbols[4].flipSign())); + REQUIRE("x" == toString(symbols[4].flipSign().flipSign())); + REQUIRE("abc" == toString(symbols[5])); + REQUIRE("\"\"" == toString(symbols[6])); + REQUIRE("\"xyz\"" == toString(symbols[7])); + REQUIRE("#inf" == toString(symbols[8])); + REQUIRE("#sup" == toString(symbols[9])); + REQUIRE("(42,a)" == toString(symbols[10])); + REQUIRE("f(42,a)" == toString(symbols[11])); + REQUIRE("-f(42,a)" == toString(symbols[11].flipSign())); + REQUIRE("f(42,a)" == toString(symbols[11].flipSign().flipSign())); + REQUIRE("()" == toString(Symbol::createTuple(SymSpan{nullptr, 0}))); + + std::string comp = toString(Symbol::createFun("g", SymSpan{symbols.data() + 2, symbols.size() - 2})); + REQUIRE("g(0,42,x,abc,\"\",\"xyz\",#inf,#sup,(42,a),f(42,a))" == comp); + } + + SECTION("sig") { + std::vector names { "a", "b", "c", "d" }; + for (uint32_t i = 1; i < 1073741824; i*=2) { + String name = names[i % names.size()]; + Sig sig{ name.c_str(), i, false }; + REQUIRE(name == sig.name()); + REQUIRE(i == sig.arity()); + } + } +} + +} } // namespace Test Gringo + diff --git a/libgringo/tests/term.cc b/libgringo/tests/term.cc new file mode 100644 index 0000000..7821e3f --- /dev/null +++ b/libgringo/tests/term.cc @@ -0,0 +1,323 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/bug.hh" +#include "gringo/output/theory.hh" +#include "tests/tests.hh" +#include "tests/term_helper.hh" + +#include +#include +#include + +namespace Gringo { namespace Test { + +using namespace Gringo::IO; + +namespace { + +using S = std::string; + +size_t hash(UTerm const &x) { + return x->gterm()->hash(); +} + +UGTerm gterm(UTerm const &x) { + return x->gterm(); +} + + +} // namespace + +TEST_CASE("term", "[base]") { + TestGringoModule log; + + auto rewriteDots = [&](UTerm &&x) -> std::tuple { + SimplifyState state; + x->simplify(state, true, false, log).update(x); + return std::make_tuple(std::move(x), std::move(state.dots), std::move(state.scripts)); + }; + + auto rewriteProject = [&](UTerm &&x) -> std::string { + UTerm sig{make_locatable(x->loc(), Symbol::createId("#p"))}; + SimplifyState state; + x->simplify(state, true, false, log).update(x); + auto ret(x->project(sig.get() != nullptr, state.gen)); + Term::replace(x, std::move(std::get<0>(ret))); + auto projected(std::move(std::get<1>(ret))); + auto project(std::move(std::get<2>(ret))); + return to_string(std::make_tuple( + std::move(x), + projected ? std::move(projected) : val(Symbol::createStr("#undef")), + project ? std::move(project) : val(Symbol::createStr("#undef")))); + }; + + auto rewriteArithmetics = [&](UTerm &&x) -> std::string { + Term::ArithmeticsMap vec; + vec.emplace_back(); + AuxGen gen; + UTerm y(x->rewriteArithmetics(vec, gen)); + return to_string(std::make_pair(y ? std::move(y) : std::move(x), std::move(vec))); + }; + + auto simplify = [&](UTerm &&x) -> UTerm { + SimplifyState state; + if (x->simplify(state, true, false, log).update(x).undefined()) { + return make_locatable(x->loc(), Symbol::createId("#undefined")); + } + else { + return std::move(x); + } + }; + + auto rewrite = [&] (UTerm &&x) -> std::vector> { + SimplifyState state; + std::vector> res; + for(auto &term : unpool(x)) { + SimplifyState elemState(state); + Term::ArithmeticsMap arith; + arith.emplace_back(); + term->simplify(elemState, true, false, log).update(term); + Term::replace(term, term->rewriteArithmetics(arith, elemState.gen)); + res.emplace_back(std::move(term), std::move(elemState.dots), std::move(arith)); + } + return res; + }; + + auto bindVars = [&](UTerm &&x) -> UTerm { + SimplifyState state; + Term::ArithmeticsMap arith; + Term::VarSet set; + arith.emplace_back(); + x->simplify(state, true, false, log).update(x); + Term::replace(x, x->rewriteArithmetics(arith, state.gen)); + x->bind(set); + return std::move(x); + }; + + SECTION("hash") { + // term + CHECK(val(NUM(1))->hash() == val(NUM(1))->hash()); + CHECK(!(val(NUM(1))->hash() == val(NUM(2))->hash())); + CHECK(var("X")->hash() == var("X")->hash()); + CHECK(!(var("X")->hash() == var("Y")->hash())); + CHECK(binop(BinOp::ADD, val(NUM(1)), val(NUM(2)))->hash() == binop(BinOp::ADD, val(NUM(1)), val(NUM(2)))->hash()); + CHECK(!(binop(BinOp::ADD, val(NUM(1)), val(NUM(2)))->hash() == binop(BinOp::ADD, val(NUM(2)), val(NUM(1)))->hash())); + CHECK(unop(UnOp::NEG, val(NUM(1)))->hash() == unop(UnOp::NEG, val(NUM(1)))->hash()); + CHECK(!(unop(UnOp::NEG, val(NUM(1)))->hash() == unop(UnOp::ABS, val(NUM(1)))->hash())); + CHECK(fun("f", val(NUM(1)), val(NUM(2)))->hash() == fun("f", val(NUM(1)), val(NUM(2)))->hash()); + CHECK(!(fun("f", val(NUM(1)), val(NUM(2)))->hash() == fun("g", val(NUM(1)), val(NUM(2)))->hash())); + CHECK(lua("f", val(NUM(1)), val(NUM(2)))->hash() == lua("f", val(NUM(1)), val(NUM(2)))->hash()); + CHECK(!(lua("f", val(NUM(1)), val(NUM(2)))->hash() == lua("g", val(NUM(1)), val(NUM(2)))->hash())); + CHECK(pool(val(NUM(1)), val(NUM(2)))->hash() == pool(val(NUM(1)), val(NUM(2)))->hash()); + CHECK(!(pool(val(NUM(1)), val(NUM(2)))->hash() == pool(val(NUM(2)), val(NUM(1)))->hash())); + CHECK(dots(val(NUM(1)), val(NUM(2)))->hash() == dots(val(NUM(1)), val(NUM(2)))->hash()); + CHECK(!(dots(val(NUM(1)), val(NUM(2)))->hash() == dots(val(NUM(2)), val(NUM(1)))->hash())); + // gterm + CHECK(hash(val(NUM(1))) == hash(val(NUM(1)))); + CHECK(hash(val(NUM(1))) != hash(val(NUM(2)))); + CHECK(hash(lin("X",2,3)) == hash(lin("X",2,3))); + CHECK(hash(lin("X",2,3)) == hash(lin("Y",2,3))); // Note: intended + CHECK(hash(lin("X",2,3)) != hash(lin("X",1,3))); + CHECK(hash(lin("X",2,3)) != hash(lin("X",2,2))); + CHECK(hash(var("X")) == hash(var("X"))); + CHECK(hash(var("X")) == hash(var("Y"))); // Note: intended + CHECK(hash(fun("f", val(NUM(1)), val(NUM(2)))) == hash(fun("f", val(NUM(1)), val(NUM(2))))); + CHECK(hash(fun("f", val(NUM(1)), val(NUM(2)))) != hash(fun("g", val(NUM(1)), val(NUM(2))))); + CHECK(hash(fun("f", val(NUM(1)), val(NUM(2)))) != hash(fun("f", val(NUM(2)), val(NUM(2))))); + CHECK(hash(fun("f", val(NUM(1)), val(NUM(2)))) != hash(fun("f", val(NUM(1)), val(NUM(1))))); + } + + SECTION("equal") { + // term + REQUIRE(*val(NUM(1)) == *val(NUM(1))); + REQUIRE(!(*val(NUM(1)) == *val(NUM(2)))); + REQUIRE(*var("X") == *var("X")); + REQUIRE(!(*var("X") == *var("Y"))); + REQUIRE(*binop(BinOp::ADD, val(NUM(1)), val(NUM(2))) == *binop(BinOp::ADD, val(NUM(1)), val(NUM(2)))); + REQUIRE(!(*binop(BinOp::ADD, val(NUM(1)), val(NUM(2))) == *binop(BinOp::ADD, val(NUM(2)), val(NUM(1))))); + REQUIRE(*unop(UnOp::NEG, val(NUM(1))) == *unop(UnOp::NEG, val(NUM(1)))); + REQUIRE(!(*unop(UnOp::NEG, val(NUM(1))) == *unop(UnOp::ABS, val(NUM(1))))); + REQUIRE(*fun("f", val(NUM(1)), val(NUM(2))) == *fun("f", val(NUM(1)), val(NUM(2)))); + REQUIRE(!(*fun("f", val(NUM(1)), val(NUM(2))) == *fun("g", val(NUM(1)), val(NUM(2))))); + REQUIRE(*lua("f", val(NUM(1)), val(NUM(2))) == *lua("f", val(NUM(1)), val(NUM(2)))); + REQUIRE(!(*lua("f", val(NUM(1)), val(NUM(2))) == *lua("g", val(NUM(1)), val(NUM(2))))); + REQUIRE(*pool(val(NUM(1)), val(NUM(2))) == *pool(val(NUM(1)), val(NUM(2)))); + REQUIRE(!(*pool(val(NUM(1)), val(NUM(2))) == *pool(val(NUM(2)), val(NUM(1))))); + REQUIRE(!(*dots(val(NUM(1)), val(NUM(2))) == *dots(val(NUM(1)), val(NUM(2))))); // Note: intended + REQUIRE(!(*dots(val(NUM(1)), val(NUM(2))) == *dots(val(NUM(2)), val(NUM(1))))); + // gterm + REQUIRE(*gterm(val(NUM(1))) == *gterm(val(NUM(1)))); + REQUIRE(*gterm(val(NUM(1))) != *gterm(val(NUM(2)))); + REQUIRE(*gterm(lin("X",2,3)) == *gterm(lin("X",2,3))); + REQUIRE(*gterm(lin("X",2,3)) == *gterm(lin("Y",2,3))); // Note: intended + REQUIRE(*gterm(lin("X",2,3)) != *gterm(lin("X",1,3))); + REQUIRE(*gterm(lin("X",2,3)) != *gterm(lin("X",2,2))); + REQUIRE(*gterm(var("X")) == *gterm(var("X"))); + REQUIRE(*gterm(fun("f", var("X"), var("X"))) == *gterm(fun("f", var("X"), var("X", 1)))); // Note: all levels=0 + REQUIRE(*gterm(var("X")) == *gterm(var("Y"))); // Note: intended + REQUIRE(*gterm(fun("f", val(NUM(1)), val(NUM(2)))) == *gterm(fun("f", val(NUM(1)), val(NUM(2))))); + REQUIRE(*gterm(fun("f", val(NUM(1)), val(NUM(2)))) != *gterm(fun("g", val(NUM(1)), val(NUM(2))))); + REQUIRE(*gterm(fun("f", val(NUM(1)), val(NUM(2)))) != *gterm(fun("f", val(NUM(2)), val(NUM(2))))); + REQUIRE(*gterm(fun("f", val(NUM(1)), val(NUM(2)))) != *gterm(fun("f", val(NUM(1)), val(NUM(1))))); + } + + SECTION("eval") { + bool undefined; + REQUIRE(Symbol(NUM(1)) == val(NUM(1))->eval(undefined, log)); + + REQUIRE(NUM(0) == binop(BinOp::DIV, val(NUM(7)), val(NUM(0)))->eval(undefined, log)); + REQUIRE(NUM(1) == binop(BinOp::MOD, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(2) == binop(BinOp::DIV, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(3) == binop(BinOp::AND, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(4) == binop(BinOp::XOR, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(5) == binop(BinOp::SUB, val(NUM(7)), val(NUM(2)))->eval(undefined, log)); + REQUIRE(NUM(7) == binop(BinOp::OR, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(10) == binop(BinOp::ADD, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(21) == binop(BinOp::MUL, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + REQUIRE(NUM(343) == binop(BinOp::POW, val(NUM(7)), val(NUM(3)))->eval(undefined, log)); + + REQUIRE(NUM(-1) == unop(UnOp::NEG, val(NUM(1)))->eval(undefined, log)); + REQUIRE(NUM(1) == unop(UnOp::ABS, val(NUM(-1)))->eval(undefined, log)); + REQUIRE(NUM(-13) == unop(UnOp::NOT, val(NUM(12)))->eval(undefined, log)); + + REQUIRE(FUN("f", {NUM(1), NUM(5)}) == fun("f", val(NUM(1)), binop(BinOp::ADD, val(NUM(2)), val(NUM(3))))->eval(undefined, log)); + + REQUIRE(Symbol::createId("a").flipSign() == unop(UnOp::NEG, val(ID("a")))->eval(undefined, log)); + } + + SECTION("rewriteArithmetics") { + REQUIRE("(#Arith0,[{(X\\Y):#Arith0}])" == rewriteArithmetics(binop(BinOp::MOD, var("X"), var("Y")))); + REQUIRE("(f(#Arith0,1),[{(g(X)\\Y):#Arith0}])" == rewriteArithmetics(fun("f", binop(BinOp::MOD, fun("g", var("X")), var("Y")), val(NUM(1))))); + REQUIRE("(#Arith0,[{@f((@g(X)\\Y)):#Arith0}])" == rewriteArithmetics(lua("f", binop(BinOp::MOD, lua("g", var("X")), var("Y"))))); + REQUIRE("(#Arith0,[{|(X\\Y)|:#Arith0}])" == rewriteArithmetics(unop(UnOp::ABS, binop(BinOp::MOD, var("X"), var("Y"))))); + REQUIRE("((-#Arith0),[{(X\\Y):#Arith0}])" == rewriteArithmetics(unop(UnOp::NEG, binop(BinOp::MOD, var("X"), var("Y"))))); + REQUIRE("(f(#Arith0,#Arith0),[{(X\\Y):#Arith0}])" == rewriteArithmetics(fun("f", binop(BinOp::MOD, var("X"), var("Y")), binop(BinOp::MOD, var("X"), var("Y"))))); + } + + SECTION("rewriteDots") { + REQUIRE("(#Range0,[(#Range0,X,Y)],[])" == to_string(rewriteDots(dots(var("X"), var("Y"))))); + REQUIRE("(#Range0,[(#Range0,1,2)],[])" == to_string(rewriteDots(dots(val(NUM(1)), val(NUM(2)))))); + REQUIRE("(f(#Range0,3),[(#Range0,g(1),2)],[])" == to_string(rewriteDots(fun("f", dots(fun("g", val(NUM(1))), val(NUM(2))), val(NUM(3)))))); + REQUIRE("(#Script2,[(#Range1,#Script0,2)],[(#Script0,g,[X]),(#Script2,f,[#Range1,3])])" == to_string(rewriteDots(lua("f", dots(lua("g", var("X")), val(NUM(2))), val(NUM(3)))))); + REQUIRE("((1*#Range0+4),[(#Range0,3,3)],[])" == to_string(rewriteDots(binop(BinOp::ADD, dots(binop(BinOp::ADD, val(NUM(1)), val(NUM(2))), val(NUM(3))), val(NUM(4)))))); + REQUIRE("(|#Range0|,[(#Range0,1,2)],[])" == to_string(rewriteDots(unop(UnOp::ABS, dots(unop(UnOp::ABS, val(NUM(1))), val(NUM(2))))))); + } + + SECTION("unpool") { + REQUIRE("[X,Y]" == to_string(unpool(pool(var("X"), var("Y"))))); + REQUIRE("[f(X),f(Y)]" == to_string(unpool(fun("f", pool(var("X"), var("Y")))))); + REQUIRE("[f(g(X),h(A)),f(g(Y),h(A)),f(g(X),h(B)),f(g(Y),h(B))]" == to_string(unpool(fun("f", fun("g", pool(var("X"), var("Y"))), fun("h", pool(var("A"), var("B"))))))); + REQUIRE("[@f(@g(X),@h(A)),@f(@g(Y),@h(A)),@f(@g(X),@h(B)),@f(@g(Y),@h(B))]" == to_string(unpool(lua("f", lua("g", pool(var("X"), var("Y"))), lua("h", pool(var("A"), var("B"))))))); + REQUIRE("[(-X),(-Y)]" == to_string(unpool(unop(UnOp::NEG, pool(var("X"), var("Y")))))); + REQUIRE("[(X+A),(X+B),(Y+A),(Y+B)]" == to_string(unpool(binop(BinOp::ADD, pool(var("X"), var("Y")), pool(var("A"), var("B")))))); + REQUIRE("[(1..(2..4)),(1..(3..4)),5]" == to_string(unpool(pool(dots(val(NUM(1)), dots(pool(val(NUM(2)), val(NUM(3))), val(NUM(4)))), val(NUM(5)))))); + } + + SECTION("simplify") { + REQUIRE("(1*X+1)" == to_string(simplify(binop(BinOp::ADD, val(NUM(1)), var("X"))))); + REQUIRE("(1*X+1)" == to_string(simplify(binop(BinOp::ADD, var("X"), val(NUM(1)))))); + REQUIRE("(-1*X+1)" == to_string(simplify(binop(BinOp::SUB, val(NUM(1)), var("X"))))); + REQUIRE("(2*X+0)" == to_string(simplify(binop(BinOp::MUL, val(NUM(2)), var("X"))))); + REQUIRE("(0*X)" == to_string(simplify(binop(BinOp::MUL, val(NUM(0)), var("X"))))); + REQUIRE("#undefined" == to_string(simplify(binop(BinOp::ADD, fun("f", val(NUM(1))), var("X"))))); + REQUIRE("#undefined" == to_string(simplify(fun("f", binop(BinOp::ADD, val(NUM(1)), val(ID("a"))))))); + REQUIRE("X" == to_string(simplify(binop(BinOp::SUB, val(NUM(1)), binop(BinOp::SUB, val(NUM(1)), var("X")))))); + REQUIRE("(1*X+1)" == to_string(simplify(binop(BinOp::SUB, val(NUM(1)), unop(UnOp::NEG, var("X")))))); + REQUIRE("3" == to_string(simplify(binop(BinOp::ADD, val(NUM(1)), val(NUM(2)))))); + REQUIRE("1" == to_string(simplify(unop(UnOp::NEG, val(NUM(-1)))))); + REQUIRE("f((1*X+1))" == to_string(simplify(fun("f", binop(BinOp::ADD, val(NUM(1)), var("X")))))); + } + + SECTION("rewrite()") { + REQUIRE("[(f((1*#Range1+1)),[(#Range0,2,3),(#Range1,1,#Range0)],[{}]),(f((1*#Range3+1)),[(#Range2,2,4),(#Range3,1,#Range2)],[{}]),(f((-1*X+1)),[],[{}])]" == to_string(rewrite(fun("f", pool(binop(BinOp::ADD, dots(val(NUM(1)), dots(val(NUM(2)), pool(val(NUM(3)), val(NUM(4))))), val(NUM(1))), binop(BinOp::SUB, val(NUM(1)), var("X"))))))); + } + + SECTION("undefined") { + bool undefined = false; + REQUIRE(NUM(0) == binop(BinOp::POW, val(ID("a")), val(NUM(1)))->eval(undefined, log)); + REQUIRE(undefined); + REQUIRE("dummy:1:1: info: operation undefined:\n (a**1)\n" == log.messages().back()); + undefined = false; + REQUIRE(NUM(0) == unop(UnOp::NOT, val(ID("a")))->eval(undefined, log)); + REQUIRE(undefined); + REQUIRE("dummy:1:1: info: operation undefined:\n (~a)\n" == log.messages().back()); + } + + SECTION("project") { + REQUIRE("(#p_p(#p),#p_p(#p),p(#P0))" == to_string(rewriteProject(fun("p", var("_"))))); + REQUIRE("(#p_p(#b(X),#p),#p_p(#b(#X0),#p),p(#X0,#P1))" == to_string(rewriteProject(fun("p", var("X"), var("_"))))); + REQUIRE("(#p_p(g(#p)),#p_p(g(#p)),p(g(#P0)))" == to_string(rewriteProject(fun("p", fun("g", var("_")))))); + REQUIRE("(#p_p(#p,f(#b(X),#p),g(#p)),#p_p(#p,f(#b(#X1),#p),g(#p)),p(#P0,f(#X1,#P2),g(#P3)))" == to_string(rewriteProject(fun("p", var("_"), fun("f", var("X"), var("_")), fun("g", var("_")))))); + REQUIRE("(#p_p(#p,f(h(#p),#b((1*X+2)),#p),g(#p)),#p_p(#p,f(h(#p),#b(#X2),#p),g(#p)),p(#P0,f(h(#P1),#X2,#P3),g(#P4)))" == to_string(rewriteProject(fun("p", var("_"), fun("f", fun("h", var("_")), binop(BinOp::ADD, var("X"), val(NUM(2))), var("_")), fun("g", var("_")))))); + REQUIRE("(#p_p(#b((1*#Anon0+1))),#p_p(#b(#X1)),p(#X1))" == to_string(rewriteProject(fun("p", binop(BinOp::ADD, var("_"), val(NUM(1))))))); + } + + SECTION("match") { + REQUIRE(bindVars(val(NUM(1)))->match(NUM(1))); + REQUIRE(!bindVars(val(NUM(1)))->match(NUM(2))); + REQUIRE(bindVars(binop(BinOp::ADD, val(NUM(1)), var("X")))->match(NUM(1))); + REQUIRE(!bindVars(binop(BinOp::ADD, val(NUM(1)), var("X")))->match(ID("a"))); + REQUIRE(bindVars(unop(UnOp::NEG, var("X")))->match(NUM(1))); + REQUIRE(bindVars(unop(UnOp::NEG, var("X")))->match(ID("a").flipSign())); + REQUIRE(bindVars(unop(UnOp::NEG, var("X")))->match(ID("a"))); + REQUIRE(!bindVars(unop(UnOp::NEG, val(ID("a"))))->match(ID("a"))); + REQUIRE(!bindVars(unop(UnOp::NEG, var("X")))->match(STR("a"))); + REQUIRE(bindVars(unop(UnOp::NEG, fun("f", var("X"))))->match(FUN("f", {NUM(0)}).flipSign())); + REQUIRE(!bindVars(unop(UnOp::NEG, fun("f", var("X"))))->match(FUN("f", {NUM(0)}))); + REQUIRE(bindVars(fun("p", var("X"), var("X")))->match(FUN("p", {NUM(1), NUM(1)}))); + REQUIRE(!bindVars(fun("p", var("X"), var("X")))->match(FUN("p", {NUM(1), NUM(2)}))); + REQUIRE(bindVars(fun("p", binop(BinOp::SUB, val(NUM(4)), binop(BinOp::MUL, val(NUM(3)), var("X"))), unop(UnOp::NEG, var("X"))))->match(FUN("p", {NUM(-2), NUM(-2)}))); + REQUIRE(bindVars(fun("p", binop(BinOp::SUB, val(NUM(4)), binop(BinOp::MUL, val(NUM(3)), var("X"))), unop(UnOp::NEG, var("X"))))->match(FUN("p", {NUM(-5), NUM(-3)}))); + REQUIRE(!bindVars(fun("p", binop(BinOp::SUB, val(NUM(4)), binop(BinOp::MUL, val(NUM(3)), var("X"))), unop(UnOp::NEG, var("X"))))->match(FUN("p", {NUM(2), NUM(2)}))); + REQUIRE(!bindVars(fun("p", binop(BinOp::SUB, val(NUM(4)), binop(BinOp::MUL, val(NUM(3)), var("X"))), unop(UnOp::NEG, var("X"))))->match(FUN("p", {NUM(1), NUM(2)}))); + } + + SECTION("theory") { + Potassco::TheoryData td; + Output::TheoryData data(td); + auto T = [&data](Symbol v) { + std::ostringstream out; + data.printTerm(out, data.addTerm(v)); + return out.str(); + }; + Symbol px = Symbol::createId("x", false); + Symbol nx = Symbol::createId("x", true); + Symbol str = Symbol::createStr("x\ny"); + Symbol sup = Symbol::createSup(); + Symbol inf = Symbol::createInf(); + Symbol pf = Symbol::createFun("f", Potassco::toSpan(SymVec{px, nx, str, sup, inf}), false); + Symbol nf = Symbol::createFun("f", Potassco::toSpan(SymVec{px, nx, str, sup, inf}), true); + Symbol t = Symbol::createTuple(Potassco::toSpan(SymVec{px, nx, str, sup, inf})); + Potassco::Id_t nfId = data.addTerm(nf); + REQUIRE("x" == T(px)); + REQUIRE("(-x)" == T(nx)); + REQUIRE("#inf" == T(inf)); + REQUIRE("#sup" == T(sup)); + REQUIRE("\"x\\ny\"" == T(str)); + REQUIRE("f(x,(-x),\"x\\ny\",#sup,#inf)" == T(pf)); + REQUIRE("(-f(x,(-x),\"x\\ny\",#sup,#inf))" == T(nf)); + REQUIRE("(x,(-x),\"x\\ny\",#sup,#inf)" == T(t)); + REQUIRE(nfId == data.addTerm(nf)); + } +} + +} } // namespace Test Gringo + diff --git a/libgringo/tests/term_helper.hh b/libgringo/tests/term_helper.hh new file mode 100644 index 0000000..7351e90 --- /dev/null +++ b/libgringo/tests/term_helper.hh @@ -0,0 +1,101 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TEST_TERM_HELPER_HH +#define _GRINGO_TEST_TERM_HELPER_HH + +#include "tests/tests.hh" +#include "gringo/term.hh" + +namespace Gringo { namespace Test { + +// {{{ definition of functions to create terms + +inline std::unique_ptr val(Symbol v) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, v); +} + +inline std::unique_ptr var(char const *x, int level = 0) { + static std::unordered_map vals; + auto &ret(vals[x]); + if (!ret) { ret = std::make_shared(); } + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + auto var(make_locatable(loc, String(x), ret)); + var->level = level; + return var; +} + +inline std::unique_ptr lin(char const *x, int m, int n) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, *var(x), m, n); +} + +inline std::unique_ptr dots(UTerm &&left, UTerm &&right) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, std::move(left), std::move(right)); +} + +inline std::unique_ptr unop(UnOp op, UTerm &&arg) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, op, std::move(arg)); +} + +inline std::unique_ptr binop(BinOp op, UTerm &&left, UTerm &&right) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, op, std::move(left), std::move(right)); +} + +template +std::unique_ptr fun(char const *name, T&&... args) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, String(name), Test::init(std::forward(args)...)); +} + +template +std::unique_ptr lua(char const *name, T&&... args) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, String(name), Test::init(std::forward(args)...)); +} + +template +std::unique_ptr pool(T&&... args) { + Location loc(String("dummy"), 1, 1, String("dummy"), 1, 1); + return make_locatable(loc, Test::init(std::forward(args)...)); +} + +template +UTermVec termvec(T&&... args) { + return Test::init(std::forward(args)...); +} + +inline Symbol NUM(int num) { return Symbol::createNum(num); } +inline Symbol SUP() { return Symbol::createSup(); } +inline Symbol INF() { return Symbol::createInf(); } +inline Symbol STR(String name) { return Symbol::createStr(name); } +inline Symbol ID(String name, bool sign = false) { return Symbol::createId(name, sign); } +inline Symbol FUN(String name, SymVec args, bool sign = false) { return Symbol::createFun(name, Potassco::toSpan(args), sign); } + +// }}} + +} } // namespace Gringo Test + +#endif // _GRINGO_TEST_TERM_HELPER_HH + diff --git a/libgringo/tests/tests.hh b/libgringo/tests/tests.hh new file mode 100644 index 0000000..35fa188 --- /dev/null +++ b/libgringo/tests/tests.hh @@ -0,0 +1,321 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#ifndef _GRINGO_TEST_TESTS_HH +#define _GRINGO_TEST_TESTS_HH + +#include "catch.hpp" +#include "gringo/utility.hh" +#include "gringo/logger.hh" +#include "gringo/control.hh" +#include "gringo/input/groundtermparser.hh" +#include +#include + +namespace Gringo { + +// {{{ declaration of helpers to print containers + +namespace IO { + +template +std::ostream &operator<<(std::ostream &out, std::unique_ptr const &x); +template +std::ostream &operator<<(std::ostream &out, std::vector const &x); +template +std::ostream &operator<<(std::ostream &out, std::initializer_list const &x); +template +std::ostream &operator<<(std::ostream &out, std::set const &x); +template +std::ostream &operator<<(std::ostream &out, std::pair const &x); +template +std::ostream &operator<<(std::ostream &out, std::tuple const &x); +template +std::ostream &operator<<(std::ostream &out, std::map const &x); +template +std::ostream &operator<<(std::ostream &out, std::unordered_map const &x); +template +std::string to_string(T const &x); + +} // namespace IO + +// }}} + +// {{{ definition of helpers to print containers + +namespace IO { + +template +std::ostream &operator<<(std::ostream &out, std::unique_ptr const &x) { + out << *x; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::pair const &x) { + out << "(" << x.first << "," << x.second << ")"; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::vector const &vec) { + out << "["; + auto it(vec.begin()), end(vec.end()); + if (it != end) { + out << *it; + for (++it; it != end; ++it) { out << "," << *it; } + } + out << "]"; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::initializer_list const &vec) { + out << "["; + auto it(vec.begin()), end(vec.end()); + if (it != end) { + out << *it; + for (++it; it != end; ++it) { out << "," << *it; } + } + out << "]"; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::set const &x) { + out << "{"; + auto it(x.begin()), end(x.end()); + if (it != end) { + out << *it; + for (++it; it != end; ++it) { out << "," << *it; } + } + out << "}"; + return out; +} + + +namespace detail { + template + struct print { + template + void operator()(std::ostream &out, std::tuple const &x) const { + out << std::get(x) << ","; + print()(out, x); + } + }; + template <> + struct print<1> { + template + void operator()(std::ostream &out, std::tuple const &x) const { + out << std::get(x); + } + }; + template <> + struct print<0> { + template + void operator()(std::ostream &, std::tuple const &) const { } + }; +} + +template +std::ostream &operator<<(std::ostream &out, std::tuple const &x) { + out << "("; + detail::print()(out, x); + out << ")"; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::unordered_map const &x) { + std::vector> vals; + for (auto const &y : x) { vals.emplace_back(to_string(y.first), to_string(y.second)); } + std::sort(vals.begin(), vals.end()); + out << "{"; + auto it = vals.begin(), end = vals.end(); + if (it != end) { + out << it->first << ":" << it->second; + for (++it; it != end; ++it) { out << "," << it->first << ":" << it->second; } + } + out << "}"; + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::map const &x) { + out << "{"; + auto it = x.begin(), end = x.end(); + if (it != end) { + out << it->first << ":" << it->second; + for (++it; it != end; ++it) { out << "," << it->first << ":" << it->second; } + } + out << "}"; + return out; +} + +template +std::string to_string(T const &x) { + std::stringstream ss; + ss << x; + return ss.str(); +} + +} // namesapce IO + +// }}} + +inline std::string &replace_all(std::string &haystack, std::string const &needle, std::string const &replace) { + size_t index = 0; + while (true) { + index = haystack.find(needle, index); + if (index == std::string::npos) break; + haystack.replace(index, needle.length(), replace); + index += replace.length(); + } + return haystack; +} + +inline std::string replace_all(std::string &&haystack, std::string const &needle, std::string const &replace) { + replace_all(haystack, needle, replace); + return std::move(haystack); +} + +} + +namespace Gringo { namespace Test { + +// {{{1 definition of helpers to initialize vectors + +namespace Detail { + +template +struct walker; + +template +struct emplacer; + +template +struct emplacer { + void operator()(V& v, A&& a, T&&... args) const { + // reverse + emplacer()(v, std::forward(args)..., std::forward(a)); + } +}; + +template +struct emplacer { + void operator()(V& v, A&&, T&&... args) const { + // drop + emplacer()(v, std::forward(args)...); + } +}; + +template +struct emplacer { + void operator()(V& v, A&& a, T&&... args) const { + // reverse + emplacer()(v, std::forward(args)..., std::forward(a)); + } +}; + +template +struct emplacer { + void operator()(V &v, A&& a, T&&... args) const { + v.emplace_back(std::forward(a), std::forward(args)...); + } +}; + +template +struct walker { + void operator()(V& v, A&&, T&&... args) const { + walker()(v, std::forward(args)...); + } +}; + +template +struct walker { + void operator()(V& v, A&& a, T&&... args) const { + emplacer()(v, std::forward(a), std::forward(args)...); + walker()(v, std::forward(args)...); + } +}; + +// Note: optimization for N=1 +template +struct walker<1, V, 0, A, T...> { + void operator()(V& v, A&& a, T&&... args) const { + v.emplace_back(std::forward(a)); + walker<1, V, 0, T...>()(v, std::forward(args)...); + } +}; + +template +struct walker { + static_assert(N > 0, "think - makes no sense!"); + void operator()(V&) const { } +}; + +} // namespace Detail + +template +V init(T&&... args) { + V v; + Detail::walker<1, V, 0, T...>()(v, std::forward(args)...); + return std::move(v); +} + +template +V init(T&&... args) { + static_assert(N > 0, "think - makes no sense!"); + V v; + Detail::walker()(v, std::forward(args)...); + return std::move(v); +} + +// {{{1 definition of TestLogger + +struct TestGringoModule : Gringo::GringoModule { + TestGringoModule() + : logger([&](clingo_warning_t, char const *msg){ + messages_.emplace_back(msg); + }, std::numeric_limits::max()) { } + + Gringo::Control *newControl(int, char const * const *, Logger::Printer, unsigned) override { throw std::logic_error("TestGringoModule::newControl must not be called"); } + Gringo::Symbol parseValue(std::string const &str, Logger::Printer = nullptr, unsigned = 0) override { + return parser.parse(str, logger); + } + operator Logger &() { return logger; } + void reset() { messages_.clear(); } + std::vector const &messages() const { return messages_; } + Gringo::Input::GroundTermParser parser; + std::vector messages_; + Logger logger; +}; + +inline std::ostream &operator<<(std::ostream &out, TestGringoModule const &mod) { + using Gringo::IO::operator<<; + out << mod.messages(); + return out; +} + +// }}}1 + +} } // namespace Test Gringo + +#endif // _GRINGO_TEST_TESTS_HH diff --git a/libgringo/tests/unique_vec.cc b/libgringo/tests/unique_vec.cc new file mode 100644 index 0000000..3aa51ee --- /dev/null +++ b/libgringo/tests/unique_vec.cc @@ -0,0 +1,55 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "tests/tests.hh" +#include "gringo/hash_set.hh" + +namespace Gringo { namespace Test { + +TEST_CASE("unique_vec", "[base]") { + SECTION("push") { + UniqueVec vec; + REQUIRE( vec.push(1).second); + REQUIRE( vec.push(2).second); + REQUIRE( vec.push(3).second); + REQUIRE( vec.push(4).second); + vec.pop(); + vec.pop(); + REQUIRE(!vec.push(1).second); + REQUIRE(!vec.push(2).second); + REQUIRE( vec.push(3).second); + REQUIRE( vec.push(4).second); + REQUIRE( vec.push(5).second); + REQUIRE( vec.push(6).second); + REQUIRE( vec.push(7).second); + vec.erase([](unsigned val) { return 2 < val && val < 6; }); + REQUIRE(!vec.push(1).second); + REQUIRE(!vec.push(2).second); + REQUIRE( vec.push(3).second); + REQUIRE( vec.push(4).second); + REQUIRE( vec.push(5).second); + REQUIRE(!vec.push(6).second); + REQUIRE(!vec.push(7).second); + } +} + +} } // namespace Test Gringo + + diff --git a/libgringo/tests/utility.cc b/libgringo/tests/utility.cc new file mode 100644 index 0000000..247eeea --- /dev/null +++ b/libgringo/tests/utility.cc @@ -0,0 +1,214 @@ +// {{{ GPL License + +// This file is part of gringo - a grounder for logic programs. +// Copyright (C) 2013 Roland Kaminski + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// }}} + +#include "gringo/utility.hh" +#include "tests/tests.hh" + +namespace Gringo { namespace Test { + +using Gringo::IO::to_string; + +namespace { + +struct CloneMe { + CloneMe(int x) : x(x) { } + CloneMe(CloneMe const &) = delete; + CloneMe(CloneMe &&) = default; + CloneMe *clone() const { return new CloneMe(x); } + int x; +}; + +std::ostream &operator<<(std::ostream &out, CloneMe const &x) { + out << "c" << x.x; + return out; +} + +} // namespace + +TEST_CASE("utility", "[base]") { + SECTION("to_string") { + int x1 { 1 }; + std::unique_ptr x2 { new int(1) }; + std::pair x3 { 1, 2 }; + std::tuple<> x4 { }; + std::tuple x5 { 1 }; + std::tuple x6 { 1, 2, 3 }; + std::vector x7 { 1, 2, 3 }; + std::vector> x8 { {1,2}, {3,4}, {5,6,7}, {8} }; + + REQUIRE("1" == to_string(x1)); + REQUIRE("1" == to_string(x2)); + REQUIRE("(1,2)" == to_string(x3)); + REQUIRE("()" == to_string(x4)); + REQUIRE("(1)" == to_string(x5)); + REQUIRE("(1,2,3)" == to_string(x6)); + REQUIRE("[1,2,3]" == to_string(x7)); + REQUIRE("[[1,2],[3,4],[5,6,7],[8]]" == to_string(x8)); + } + + SECTION("cross_product") { + std::vector> x1 { }; + std::vector> x2 { {} }; + std::vector> x3 { {1} }; + std::vector> x4 { {1,2} }; + std::vector> x5 { {1,2}, {3} }; + std::vector> x6 { {1,2}, {3,4} }; + std::vector> x7 { {1,2}, {3,4}, {} }; + std::vector> x8 { {0,1}, {0,1}, {0,1} }; + std::vector> x9 { {1,2}, {3,4}, {5,6,7}, {8} }; + cross_product(x1); + cross_product(x2); + cross_product(x3); + cross_product(x4); + cross_product(x5); + cross_product(x6); + cross_product(x7); + cross_product(x8); + cross_product(x9); + REQUIRE("[[]]" == to_string(x1)); + REQUIRE("[]" == to_string(x2)); + REQUIRE("[[1]]" == to_string(x3)); + REQUIRE("[[1],[2]]" == to_string(x4)); + REQUIRE("[[1,3],[2,3]]" == to_string(x5)); + REQUIRE("[[1,3],[2,3],[1,4],[2,4]]" == to_string(x6)); + REQUIRE("[]" == to_string(x7)); + REQUIRE("[[0,0,0],[1,0,0],[0,1,0],[1,1,0],[0,0,1],[1,0,1],[0,1,1],[1,1,1]]" == to_string(x8)); + REQUIRE("[[1,3,5,8],[2,3,5,8],[1,4,5,8],[2,4,5,8],[1,3,6,8],[2,3,6,8],[1,4,6,8],[2,4,6,8],[1,3,7,8],[2,3,7,8],[1,4,7,8],[2,4,7,8]]" == to_string(x9)); + } + + SECTION("clone") { + typedef std::unique_ptr U; + CloneMe x1 { 1 }; + auto x2(gringo_make_unique(1)); + auto x3(std::make_pair(gringo_make_unique(1), gringo_make_unique(2))); + std::vector x4; + x4.emplace_back(gringo_make_unique(1)); + x4.emplace_back(gringo_make_unique(2)); + x4.emplace_back(gringo_make_unique(3)); + std::tuple x5 { gringo_make_unique(1), gringo_make_unique(2), gringo_make_unique(3) }; + std::tuple<> x6 { }; + REQUIRE(to_string(1) == to_string(get_clone(1))); + REQUIRE(to_string(x1) == to_string(U(get_clone(&x1)))); + REQUIRE(to_string(x2) == to_string(get_clone(x2))); + REQUIRE(to_string(x3) == to_string(get_clone(x3))); + REQUIRE(to_string(x4) == to_string(get_clone(x4))); + REQUIRE(to_string(x5) == to_string(get_clone(x5))); + REQUIRE(to_string(x6) == to_string(get_clone(x6))); + } + + SECTION("hash") { + std::vector x1 { }; + std::vector x1e { }; + std::vector x2 { 1, 2, 3 }; + std::vector x2e { 1, 2, 3 }; + std::vector x3 { 1, 2, 3, 4 }; + std::vector x3e { 1, 2, 3, 4 }; + std::pair x4 { 1, 2 }; + std::pair x4e { 1, 2 }; + std::pair x5 { 2, 3 }; + std::pair x5e { 2, 3 }; + std::tuple<> x6 { }; + std::tuple<> x6e { }; + std::tuple x7 { 1, 2, 4 }; + std::tuple x7e { 1, 2, 4 }; + std::tuple x8 { 1, 2, 3 }; + std::tuple x8e { 1, 2, 3 }; + std::unique_ptr x9 { new int(1) }; + std::unique_ptr x9e { new int(1) }; + std::unique_ptr x10 { new int(2) }; + std::unique_ptr x10e { new int(2) }; + std::tuple, std::unique_ptr>> x11 { std::make_pair(std::vector {1, 2, 3}, gringo_make_unique(4)) }; + std::tuple, std::unique_ptr>> x11e { std::make_pair(std::vector {1, 2, 3}, gringo_make_unique(4)) }; + std::tuple, std::unique_ptr>> x12 { std::make_pair(std::vector {1, 2, 4}, gringo_make_unique(4)) }; + + + REQUIRE(get_value_hash(1) == get_value_hash(1)); + REQUIRE(get_value_hash(x1) == get_value_hash(x1e)); + REQUIRE(get_value_hash(x2) == get_value_hash(x2e)); + REQUIRE(get_value_hash(x3) == get_value_hash(x3e)); + REQUIRE(get_value_hash(x4) == get_value_hash(x4e)); + REQUIRE(get_value_hash(x5) == get_value_hash(x5e)); + REQUIRE(get_value_hash(x6) == get_value_hash(x6e)); + REQUIRE(get_value_hash(x7) == get_value_hash(x7e)); + REQUIRE(get_value_hash(x8) == get_value_hash(x8e)); + REQUIRE(get_value_hash(x9) == get_value_hash(x9e)); + REQUIRE(get_value_hash(x10) == get_value_hash(x10e)); + REQUIRE(get_value_hash(x11) == get_value_hash(x11e)); + + REQUIRE(get_value_hash(x1) != get_value_hash(x2)); + REQUIRE(get_value_hash(x1) != get_value_hash(x3)); + REQUIRE(get_value_hash(x2) != get_value_hash(x3)); + REQUIRE(get_value_hash(x4) != get_value_hash(x5)); + REQUIRE(get_value_hash(x6) != get_value_hash(x7)); + REQUIRE(get_value_hash(x6) != get_value_hash(x8)); + REQUIRE(get_value_hash(x7) != get_value_hash(x8)); + REQUIRE(get_value_hash(x9) != get_value_hash(x10)); + REQUIRE(get_value_hash(x11) != get_value_hash(x12)); + } + + SECTION("equal_to") { + std::vector x1 { }; + std::vector x1e { }; + std::vector x2 { 1, 2, 3 }; + std::vector x2e { 1, 2, 3 }; + std::vector x3 { 1, 2, 3, 4 }; + std::vector x3e { 1, 2, 3, 4 }; + std::pair x4 { 1, 2 }; + std::pair x4e { 1, 2 }; + std::pair x5 { 2, 3 }; + std::pair x5e { 2, 3 }; + std::tuple<> x6 { }; + std::tuple<> x6e { }; + std::tuple x7 { 1, 2, 4 }; + std::tuple x7e { 1, 2, 4 }; + std::tuple x8 { 1, 2, 3 }; + std::tuple x8e { 1, 2, 3 }; + std::unique_ptr x9 { new int(1) }; + std::unique_ptr x9e { new int(1) }; + std::unique_ptr x10 { new int(2) }; + std::unique_ptr x10e { new int(2) }; + std::tuple, std::unique_ptr>> x11 { std::make_pair(std::vector {1, 2, 3}, gringo_make_unique(4)) }; + std::tuple, std::unique_ptr>> x11e { std::make_pair(std::vector {1, 2, 3}, gringo_make_unique(4)) }; + std::tuple, std::unique_ptr>> x12 { std::make_pair(std::vector {1, 2, 4}, gringo_make_unique(4)) }; + + REQUIRE(is_value_equal_to(x1, x1e)); + REQUIRE(is_value_equal_to(x2, x2e)); + REQUIRE(is_value_equal_to(x3, x3e)); + REQUIRE(is_value_equal_to(x4, x4e)); + REQUIRE(is_value_equal_to(x5, x5e)); + REQUIRE(is_value_equal_to(x6, x6e)); + REQUIRE(is_value_equal_to(x7, x7e)); + REQUIRE(is_value_equal_to(x8, x8e)); + REQUIRE(is_value_equal_to(x9, x9e)); + REQUIRE(is_value_equal_to(x10, x10e)); + REQUIRE(is_value_equal_to(x11, x11e)); + + REQUIRE(!is_value_equal_to(x1, x2)); + REQUIRE(!is_value_equal_to(x1, x3)); + REQUIRE(!is_value_equal_to(x2, x3)); + REQUIRE(!is_value_equal_to(x4, x5)); + REQUIRE(!is_value_equal_to(x7, x8)); + REQUIRE(!is_value_equal_to(x9, x10)); + REQUIRE(!is_value_equal_to(x11, x12)); + } +} + +} } // namespace Test Gringo + diff --git a/liblp/potassco/aspif.h b/liblp/potassco/aspif.h new file mode 100644 index 0000000..5ca002c --- /dev/null +++ b/liblp/potassco/aspif.h @@ -0,0 +1,130 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_ASPIF_H_INCLUDED +#define LIBLP_ASPIF_H_INCLUDED +#include +namespace Potassco { +/*! + * \addtogroup ParseType + */ +///@{ +/*! + * Parses the given program in asp intermediate format and calls ctx on each parsed element. + * The error handler h is called on error. If h is 0, ParseError exceptions are used to signal errors. + */ +int readAspif(std::istream& prg, AbstractProgram& out, ErrorHandler h = 0); + +//! Class for parsing logic programs in asp intermediate format. +class AspifInput : public ProgramReader { +public: + //! Creates a new parser object that calls out on each parsed element. + AspifInput(AbstractProgram& out); + virtual ~AspifInput(); +protected: + //! Checks whether stream starts with aspif header. + virtual bool doAttach(bool& inc); + //! Parses the current step and throws exception on error. + /*! + * The function calls beginStep()/endStep() on the associated + * output object before/after parsing the current step. + */ + virtual bool doParse(); + //! Attempts to parse a theory directive of type t. + /*! + * \see Potassco::Theory_t + */ + virtual void matchTheory(unsigned t); +private: + uint32_t matchAtoms(); + uint32_t matchLits(); + uint32_t matchWLits(int32_t minW); + uint32_t matchString(); + uint32_t matchTermList(); + AbstractProgram& out_; + BasicStack* data_; +}; +///@} + +//! Writes a program in potassco's asp intermediate format to the given output stream. +/*! + * \ingroup WriteType + */ +class AspifOutput : public AbstractProgram { +public: + //! Creates a new object and associates it with the given output stream. + AspifOutput(std::ostream& os); + //! Writes an aspif header to the stream. + virtual void initProgram(bool incremental); + //! Prepares the object for a new program step. + virtual void beginStep(); + //! Writes an aspif rule directive. + virtual void rule(Head_t ht, const AtomSpan& head, const LitSpan& body); + //! Writes an aspif rule directive. + virtual void rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& lits); + //! Writes an aspif minimize directive. + virtual void minimize(Weight_t prio, const WeightLitSpan& lits); + //! Writes an aspif output directive. + virtual void output(const StringSpan& str, const LitSpan& cond); + //! Writes an aspif external directive. + virtual void external(Atom_t a, Value_t v); + //! Writes an aspif assumption directive. + virtual void assume(const LitSpan& lits); + //! Writes an aspif projection directive. + virtual void project(const AtomSpan& atoms); + //! Writes an aspif edge directive. + virtual void acycEdge(int s, int t, const LitSpan& condition); + //! Writes an aspif heuristic directive. + virtual void heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& condition); + + //! Writes an aspif theory number term. + virtual void theoryTerm(Id_t termId, int number); + //! Writes an aspif theory symbolic term. + virtual void theoryTerm(Id_t termId, const StringSpan& name); + //! Writes an aspif theory compound term. + virtual void theoryTerm(Id_t termId, int compound, const IdSpan& args); + //! Writes an aspif theory element directive. + virtual void theoryElement(Id_t elementId, const IdSpan& terms, const LitSpan& cond); + //! Writes an aspif theory atom directive. + virtual void theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements); + //! Writes an aspif theory atom directive with guard. + virtual void theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements, Id_t op, Id_t rhs); + //! Writes the aspif step terminator. + virtual void endStep(); +protected: + //! Starts writing an aspif directive. + AspifOutput& startDir(Directive_t r); + //! Writes x. + AspifOutput& add(int x); + //! Writes size(lits) followed by the elements in lits. + AspifOutput& add(const WeightLitSpan& lits); + //! Writes size(lits) followed by the literals in lits. + AspifOutput& add(const LitSpan& lits); + //! Writes size(atoms) followed by the atoms in atoms. + AspifOutput& add(const AtomSpan& atoms); + //! Writes size(str) followed by the characters in str. + AspifOutput& add(const StringSpan& str); + //! Terminates the active directive by writing a newline. + AspifOutput& endDir(); +private: + AspifOutput(const AspifOutput&); + AspifOutput& operator=(const AspifOutput&); + std::ostream& os_; +}; +} +#endif diff --git a/liblp/potassco/aspif_text.h b/liblp/potassco/aspif_text.h new file mode 100644 index 0000000..5996d87 --- /dev/null +++ b/liblp/potassco/aspif_text.h @@ -0,0 +1,70 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_ASPIF_TEXT_H_INCLUDED +#define LIBLP_ASPIF_TEXT_H_INCLUDED +#include +namespace Potassco { + +//! Class for parsing logic programs in ground text format. +/*! + * \addtogroup ParseType + */ +class AspifTextInput : public ProgramReader { +public: + //! Creates a new object and associates it with the given output if any. + AspifTextInput(AbstractProgram* out); + //! Sets the program to which parsed elements should be output. + void setOutput(AbstractProgram& out); +protected: + //! Checks whether stream starts with a valid token. + virtual bool doAttach(bool& inc); + //! Attempts to parses the current step or throws an exception on error. + /*! + * The function calls beginStep()/endStep() on the associated + * output object before/after parsing the current step. + */ + virtual bool doParse(); + //! Parses statements until next step directive or input is exhausted. + bool parseStatements(); +private: + void skipws(); + bool matchDirective(); + void matchRule(char peek); + void matchAtoms(const char* seps); + void matchLits(); + void matchCondition(); + void matchAgg(); + bool match(const char* ts, bool required = true); + Atom_t matchId(); + Lit_t matchLit(); + int matchInt(); + void matchTerm(); + void matchAtomArg(); + void matchStr(); + void startString(); + void push(char c); + void endString(); + AbstractProgram* out_; + BasicStack data_; + uint32_t strStart_; + uint32_t strPos_; +}; + +} +#endif diff --git a/liblp/potassco/basic_types.h b/liblp/potassco/basic_types.h new file mode 100644 index 0000000..d1d4372 --- /dev/null +++ b/liblp/potassco/basic_types.h @@ -0,0 +1,334 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_BASIC_TYPES_H_INCLUDED +#define LIBLP_BASIC_TYPES_H_INCLUDED +/*! + * \mainpage liblp + * A small library for parsing and converting logic programs in aspif and smodels format. + * + * The library contains parsers and writers for aspif and smodels format + * as well as functions and types for converting between the two formats + * to the extentpossible. + * + * A specification of aspif can be found in Appendix A of: + * http://www.cs.uni-potsdam.de/wv/pdfformat/gekakaosscwa16b.pdf + */ +#include +#include +#include + +//! Root namespace for all types and functions of liblp. +namespace Potassco { + +/*! + * \defgroup WriteType Program writer types + * \brief Types and functions for writing logic programs. + */ + +/*! + * \defgroup ParseType Program parser types + * \brief Types and functions for parsing logic programs. + */ + +/*! + * \defgroup BasicTypes Basic Data Types + * \brief Basic types for working with logic programs. + */ +///@{ + +//! Macro for defining a set of constants similar to a C++11 strong enum. +#define POTASSCO_ENUM_CONSTANTS_T(TypeName, BaseType, minVal, ...) \ + enum E { __VA_ARGS__, __eEnd, eMin = minVal, eMax = __eEnd - 1 };\ + TypeName(E x = eMin) : val_(x) {}\ + explicit TypeName(BaseType x) : val_(static_cast(x)) {assert(x <= eMax);}\ + operator BaseType() const { return static_cast(val_); } \ + E val_ + +//! Macro for defining a set of constants starting at 0. +#define POTASSCO_ENUM_CONSTANTS(TypeName, ...) \ + POTASSCO_ENUM_CONSTANTS_T(TypeName, unsigned, 0u, __VA_ARGS__) + +//! Ids are non-negative integers in the range [0..idMax]. +typedef uint32_t Id_t; +//! Maximum value for ids. +const Id_t idMax = static_cast(-1); +//! Atom ids are positive integers in the range [atomMin..atomMax]. +typedef uint32_t Atom_t; +//! Minimum value for atom ids (must not be 0). +const Atom_t atomMin = static_cast(1); +//! Maximum value for atom ids. +const Atom_t atomMax = static_cast(((1u)<<31)-1); +//! Literals are signed atoms. +typedef int32_t Lit_t; +//! (Literal) weights are integers. +typedef int32_t Weight_t; +//! A literal with an associated weight. +struct WeightLit_t { + Lit_t lit; /**< Literal. */ + Weight_t weight; /**< Associated weight. */ +}; +//! Supported rule head types. +struct Head_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Head_t, Disjunctive = 0, Choice = 1); +}; +//! Supported rule body types. +struct Body_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Body_t, Normal = 0, Sum = 1, Count = 2); +}; +//! Type representing an external value. +struct Value_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Value_t, + Free = 0, True = 1, + False = 2, Release = 3 + ); +}; + +//! A span consists of a starting address and a length. +/*! + * A span does not own the data and it is in general not safe to store a span. + */ +template +struct Span { + //! Iterator type for iterating over the elements of a span. + typedef const T* iterator; + typedef std::size_t size_t; + //! Returns the element at the given position, which shall be < size. + const T& operator[](std::size_t pos) const { assert(pos < size); return first[pos]; } + + const T* first; /**< Pointer to first element of this span. */ + size_t size; /**< Number of elements in this span. */ +}; +typedef Span IdSpan; +typedef Span AtomSpan; +typedef Span LitSpan; +typedef Span WeightLitSpan; +typedef Span StringSpan; + +//! Supported modifications for domain heuristic. +struct Heuristic_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Heuristic_t, + Level = 0, Sign = 1, Factor = 2, + Init = 3, True = 4, False = 5 + ); + static const StringSpan pred; /**< zero-terminated predicate name. */ +}; +//! Supported aspif directives. +struct Directive_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Directive_t, + End = 0, + Rule = 1, Minimize = 2, + Project = 3, Output = 4, + External = 5, Assume = 6, + Heuristic = 7, Edge = 8, + Theory = 9, Comment = 10 + ); +}; + +//! Basic callback interface for constructing a logic program. +class AbstractProgram { +public: + virtual ~AbstractProgram(); + //! Called once to prepare for a new logic program. + virtual void initProgram(bool incremental); + //! Called once before rules and directives of the current program step are added. + virtual void beginStep(); + + //! Add the given rule to the program. + virtual void rule(Head_t ht, const AtomSpan& head, const LitSpan& body) = 0; + //! Add the given sum rule to the program. + virtual void rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) = 0; + //! Add the given minimize statement to the program. + virtual void minimize(Weight_t prio, const WeightLitSpan& lits) = 0; + + /*! + * \name Advanced + * Functions for adding advanced constructs. + * By default, functions in this group throw a std::logic_error() + * to signal that advanced constructs are not supported. + */ + //@{ + //! Mark the given list of atoms as projection atoms. + virtual void project(const AtomSpan& atoms); + //! Output str whenever condition is true in a stable model. + virtual void output(const StringSpan& str, const LitSpan& condition); + //! If v is not equal to Value_t::Release, mark a as external and assume value v. Otherwise, treat a as regular atom. + virtual void external(Atom_t a, Value_t v); + //! Assume the given literals to true during solving. + virtual void assume(const LitSpan& lits); + //! Apply the given heuristic modification to atom a whenever condition is true. + virtual void heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& condition); + //! Assume an edge between s and t whenever condition is true. + virtual void acycEdge(int s, int t, const LitSpan& condition); + //@} + + /*! + * \name Theory data + * Functions for adding theory statements. + * By default, all theory function throw a std::logic_error(). + * Note, ids shall be unique within one step. + */ + //@{ + //! Add a new number term. + virtual void theoryTerm(Id_t termId, int number); + //! Add a new symbolic term. + virtual void theoryTerm(Id_t termId, const StringSpan& name); + //! Add a new compound (function or tuple) term. + virtual void theoryTerm(Id_t termId, int cId, const IdSpan& args); + //! Add a new theory atom element. + virtual void theoryElement(Id_t elementId, const IdSpan& terms, const LitSpan& cond); + //! Add a new theory atom consisting of the given elements, which have to be added eventually. + virtual void theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements); + //! Add a new theory atom with guard and right hand side. + virtual void theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements, Id_t op, Id_t rhs); + //@} + + //! Called once after all rules and directives of the current program step were added. + virtual void endStep(); +}; +typedef int(*ErrorHandler)(int line, const char* what); + +/*! + * \defgroup BasicFunc Basic functions + * \brief Additional functions over with basic types. + * \ingroup BasicTypes + */ +///@{ +//! Returns the id of the given atom. +inline Id_t id(Atom_t a) { return static_cast(a); } +//! Returns the id of the given literal. +inline Id_t id(Lit_t lit) { return static_cast(lit); } +//! Returns the atom of the given literal. +inline Atom_t atom(Lit_t lit) { return static_cast(lit >= 0 ? lit : -lit); } +//! Returns the atom of the given weight literal. +inline Atom_t atom(const WeightLit_t& w) { return atom(w.lit); } +//! Converts the given id back to a literal. +inline Lit_t lit(Id_t a) { return static_cast(a); } +//! Identity function for literals. +inline Lit_t lit(Lit_t lit) { return lit; } +//! Returns the literal of the given weight literal. +inline Lit_t lit(const WeightLit_t& w) { return w.lit; } +//! Returns the negative literal of the given atom. +inline Lit_t neg(Atom_t a) { return -lit(a); } +//! Returns the complement of the given literal. +inline Lit_t neg(Lit_t lit) { return -lit; } +//! Returns the weight of the given atom, which is always 1. +inline Weight_t weight(Atom_t) { return 1; } +//! Returns the weight of the given literal, which is always 1. +inline Weight_t weight(Lit_t) { return 1; } +//! Returns the weight of the given weight literal. +inline Weight_t weight(const WeightLit_t& w) { return w.weight; } +//! Returns whether the given span is empty, i.e. has size 0. +template +inline bool empty(const Span& s) { return s.size == 0; } +//! Returns the size of the given span. +template +inline std::size_t size(const Span& s) { return s.size; } +//! Returns a pointer to the first element of the given span. +template +inline const T* begin(const Span& s) { return s.first; } +//! Returns a pointer one past the end of the given span. +template +inline const T* end(const Span& s) { return begin(s) + s.size; } +//! Returns the element at the given position of the given span. +/*! + * \pre pos < size(s) + */ +template +inline const T& at(const Span& s, std::size_t pos) { return s[pos]; } + +inline bool operator==(const WeightLit_t& lhs, const WeightLit_t& rhs) { return lit(lhs) == lit(rhs) && weight(lhs) == weight(rhs); } +inline bool operator==(Lit_t lhs, const WeightLit_t& rhs) { return lit(lhs) == lit(rhs) && weight(rhs) == 1; } +inline bool operator==(const WeightLit_t& lhs, Lit_t rhs) { return rhs == lhs; } +inline bool operator!=(const WeightLit_t& lhs, const WeightLit_t& rhs) { return !(lhs == rhs); } +inline bool operator!=(Lit_t lhs, const WeightLit_t& rhs) { return !(lhs == rhs); } +inline bool operator!=(const WeightLit_t& lhs, Lit_t rhs) { return rhs != lhs; } +inline bool operator<(const WeightLit_t& lhs, const WeightLit_t& rhs) { return lhs.lit != rhs.lit ? lhs.lit < rhs.lit : lhs.weight < rhs.weight; } + +//! Creates a span from an array of size s. +template +inline Span toSpan(const T* x, std::size_t s) { + Span r = {x, s}; + return r; +} +//! Creates an empty span. +template +inline Span toSpan() { return toSpan(static_cast(0), 0); } +//! Creates a span from a sequential (STL) container c. +template +inline Span toSpan(const C& c) { + return !c.empty() ? toSpan(&c[0], c.size()) : toSpan(); +} +//! Returns the string representation of the given heuristic modifier. +inline const char* toString(Heuristic_t t) { + switch (t) { + case Heuristic_t::Level: return "level"; + case Heuristic_t::Sign: return "sign"; + case Heuristic_t::Factor:return "factor"; + case Heuristic_t::Init: return "init"; + case Heuristic_t::True: return "true"; + case Heuristic_t::False: return "false"; + default: return ""; + } +} + +///@} +///@} + +//! A (dynamic-sized) raw memory stack. +/*! + * \ingroup ParseType + */ +class RawStack { +public: + RawStack(); + RawStack(const RawStack& other); + RawStack& operator=(const RawStack& other); + //! Swaps this and other. + void swap(RawStack& other); + //! Reserves space for at least cap bytes or throws std::bad_alloc on out of memory. + void reserve(uint32_t cap); + //! Returns the current stack capacity in bytes. + uint32_t capacity() const; + //! Returns the top position of the stack. + uint32_t top() const; + //! Returns the data beginning at the given index. + void* get(uint32_t idx) const; + //! Same as pop(top()). + void clear(); + //! Moves top to idx. + void setTop(uint32_t idx); +protected: + ~RawStack(); + //! Pushes n bytes and returns the position of the first byte pushed. + uint32_t push_(uint32_t n); + //! Pops n bytes and returns the new top. + uint32_t pop_(uint32_t n); +private: + unsigned char* mem_; + uint32_t top_; + uint32_t cap_; +}; + +} +#endif diff --git a/liblp/potassco/clingo.h b/liblp/potassco/clingo.h new file mode 100644 index 0000000..bcf2566 --- /dev/null +++ b/liblp/potassco/clingo.h @@ -0,0 +1,211 @@ +// +// Copyright (c) 2015-2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_CLINGO_H_INCLUDED +#define LIBLP_CLINGO_H_INCLUDED +#include +namespace Potassco { + +/*! + * \defgroup Clingo Clingo + * \brief Interfaces for communicating with a solver. + */ +///@{ + +//! Supported clause types in theory propagation. +struct Clause_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Clause_t, + Learnt = 0, /**< Cumulative removable (i.e. subject to nogood deletion) clause. */ + Static = 1, /**< Cumulative unremovable clause. */ + Volatile = 2, /**< Removable clause associated with current solving step. */ + VolatileStatic = 3 /**< Unremovable clause associated with current solving step. */ + ); + //! Returns whether p is either Volatile or VolatileStatic. + static bool isVolatile(Clause_t p) { return (static_cast(p)& static_cast(Volatile)) != 0; } + //! Returns whether p is either Static or VolatileStatic. + static bool isStatic(Clause_t p) { return (static_cast(p)& static_cast(Static)) != 0; } +}; +//! Supported statistics types. +struct Statistics_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Statistics_t, + Empty = 0, /**< Empty (invalid) object. */ + Value = 1, /**< Single statistic value that is convertible to a double. */ + Array = 2, /**< Composite object mapping int keys to statistics types. */ + Map = 3 /**< Composite object mapping string keys to statistics types.*/ + ); +}; + +//! Represents an assignment of a particular solver. +class AbstractAssignment { +public: + typedef Potassco::Value_t Value_t; + typedef Potassco::Lit_t Lit_t; + virtual ~AbstractAssignment(); + //! Returns whether the current assignment is conflicting. + virtual bool hasConflict() const = 0; + //! Returns the number of decision literals in the assignment. + virtual uint32_t level() const = 0; + //! Returns whether lit is a valid literal in this assignment. + virtual bool hasLit(Lit_t lit) const = 0; + //! Returns the truth value that is currently assigned to lit or Value_t::Free if lit is unassigned. + virtual Value_t value(Lit_t lit) const = 0; + //! Returns the decision level on which lit was assigned or uint32_t(-1) if lit is unassigned. + virtual uint32_t level(Lit_t lit) const = 0; + //! Returns the decision literal of the given decision level. + virtual Lit_t decision(uint32_t)const = 0; + //! Returns whether the given literal is irrevocably assigned on the top level. + bool isFixed(Lit_t lit) const; + //! Returns whether the given literal is true wrt the current assignment. + bool isTrue(Lit_t lit) const; + //! Returns whether the given literal is false wrt the current assignment. + bool isFalse(Lit_t lit) const; +}; + +//! Represents one particular solver instance. +class AbstractSolver { +public: + typedef Potassco::Lit_t Lit; + virtual ~AbstractSolver(); + //! Returns the id of the solver that is associated with this object. + virtual Id_t id() const = 0; + //! Returns the current assignment of the solver. + virtual const AbstractAssignment& assignment() const = 0; + + //! Adds the given clause to the solver if possible. + /*! + * If the function is called during propagation, the return value + * indicates whether propagation may continue (true) or shall be + * aborted (false). + * + * \param clause The literals that make up the clause. + * \param prop Properties to be associated with the new clause. + * + * \note If clause contains a volatile variable, i.e., a variable + * that was created with Solver::addVariable(), it is also considered volatile. + * + */ + virtual bool addClause(const Potassco::LitSpan& clause, Clause_t prop = Clause_t::Learnt) = 0; + + //! Adds a new volatile variable to this solver instance. + /*! + * The new variable is volatile, i.e., only valid within the current solving step, + * and only added to this one particular solver instance. + * + * \return The positive literal of the new variable. + */ + virtual Lit addVariable() = 0; + //! Propagates any newly implied literals. + virtual bool propagate() = 0; + + /*! + * \name Propagate control + * \brief Functions that must only be called in the context of a propagator. + * + * @{ */ + + //! Returns whether the active propagator watches lit in this solver instance. + virtual bool hasWatch(Lit lit) const = 0; + + //! Adds the active propagator to the list of propagators to be notified when the given literal is assigned in this solver instance. + /*! + * \post hasWatch(lit) returns true. + */ + virtual void addWatch(Lit lit) = 0; + //! Removes the active propagator from the list of propagators watching p in the given solver. + /*! + * \post hasWatch(lit) returns false. + */ + virtual void removeWatch(Lit lit) = 0; + //@} +}; + +//! Base class for implementing propagators. +class AbstractPropagator { +public: + //! Type for representing a set of literals that have recently changed. + typedef Potassco::LitSpan ChangeList; + virtual ~AbstractPropagator(); + //! Shall propagate the newly assigned literals given in changes. + virtual void propagate(AbstractSolver& solver, const ChangeList& changes) = 0; + //! May update internal state of the newly unassigned literals given in undo. + virtual void undo(const AbstractSolver& solver, const ChangeList& undo) = 0; + //! Similar to propagate but called on total assignment without a list of changes. + virtual void check(AbstractSolver& solver) = 0; +}; + +//! Base class for providing (solver) statistics. +/*! + * Functions in this interface taking a key as parameter + * assume that the key is valid and throw a std::logic_error + * if this precondition is violated. + */ +class AbstractStatistics { +public: + //! Opaque type for representing (sub) keys. + typedef uint64_t Key_t; + + virtual ~AbstractStatistics(); + + //! Returns the root key of this statistic object. + virtual Key_t root() const = 0; + //! Returns the type of the object with the given key. + virtual Statistics_t type(Key_t key) const = 0; + //! Returns the child count of the object with the given key or 0 if it is a value. + virtual size_t size(Key_t key) const = 0; + /*! + * \name Array + * Functions in this group shall only be called on Array objects. + */ + //@{ + //! Returns the element at the given zero-based index. + /*! + * \pre index < size(key) + */ + virtual Key_t at(Key_t arr, size_t index) const = 0; + //@} + + /*! + * \name Map + * Functions in this group shall only be called on Map objects. + */ + //@{ + //! Returns the i'th key of the given map. + /*! + * \pre i < size(mapK) + * \note The order of keys in a map is unspecified and might change + * after a solve operation. + */ + virtual const char* key(Key_t mapK, size_t i) const = 0; + //! Returns the element stored in the map under the given name. + virtual Key_t get(Key_t mapK, const char* at) const = 0; + //@} + /*! + * \name Value + * Functions in this group shall only be called on Value objects. + */ + //@{ + //! Returns the statistic value associated with the given key. + virtual double value(Key_t key) const = 0; + //@} +}; +///@} + +} +#endif diff --git a/liblp/potassco/convert.h b/liblp/potassco/convert.h new file mode 100644 index 0000000..1a92d9b --- /dev/null +++ b/liblp/potassco/convert.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_CONVERT_H_INCLUDED +#define LIBLP_CONVERT_H_INCLUDED + +#include +namespace Potassco { + +//! Converts a given program so that it can be expressed in smodels format. +/*! + * \ingroup WriteType + */ +class SmodelsConvert : public AbstractProgram { +public: + //! Creates a new object that passes converted programs to out. + /*! + * The parameter enableClaspExt determines how heuristic, edge, and external + * directives are handled. + * If true, heuristic and edge directives are converted to _heuristic and + * _edge predicates, while external directives passed to out. + * Otherwise, heuristic and edge directives are not converted but + * directly passed to out, while external directives are mapped to + * choice rules or integrity constraints. + */ + SmodelsConvert(AbstractProgram& out, bool enableClaspExt); + ~SmodelsConvert(); + //! Calls initProgram() on the associated output program. + virtual void initProgram(bool incremental); + //! Calls beginStep() on the associated output program. + virtual void beginStep(); + //! Converts the given rule into one or more smodels rules. + virtual void rule(Head_t t, const AtomSpan& head, const LitSpan& body); + //! Converts the given rule into one or more smodels rules. + virtual void rule(Head_t t, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body); + //! Converts literals associated with a priority to a set of corresponding smodels minimize rules. + virtual void minimize(Weight_t prio, const WeightLitSpan& lits); + //! Adds an atom named str that is equivalent to the condition to the symbol table. + virtual void output(const StringSpan& str, const LitSpan& cond); + //! Marks the atom that is equivalent to a as external. + virtual void external(Atom_t a, Value_t v); + //! Adds an _heuristic predicate over the given atom to the symbol table that is equivalent to condition. + virtual void heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& condition); + //! Adds an _edge(s,t) predicate to the symbol table that is equivalent to condition. + virtual void acycEdge(int s, int t, const LitSpan& condition); + + //! Finalizes conversion and calls endStep() on the associated output program. + virtual void endStep(); + + //! Returns the output literal associated to in. + Lit_t get(Lit_t in) const; + //! Returns the name associated with the given (output) smodels atom or 0 if no name exists. + const char* getName(Atom_t a) const; + //! Returns the max used smodels atom (valid atoms are [1..n]). + unsigned maxAtom() const; +protected: + //! Creates a (named) atom that is equivalent to the given condition. + Atom_t makeAtom(const LitSpan& lits, bool named); + //! Processes all outstanding conversions. + void flush(); + //! Converts external atoms. + void flushExternal(); + //! Converts minimize statements. + void flushMinimize(); + //! Converts heuristic directives to _heuristic predicates. + void flushHeuristic(); + //! Converts (atom,name) pairs to output directives. + void flushSymbols(); +private: + SmodelsConvert(const SmodelsConvert&); + SmodelsConvert& operator=(const SmodelsConvert&); + struct SmData; + AbstractProgram& out_; + SmData* data_; + bool ext_; +}; + +} +#endif diff --git a/liblp/potassco/match_basic_types.h b/liblp/potassco/match_basic_types.h new file mode 100644 index 0000000..c7357cd --- /dev/null +++ b/liblp/potassco/match_basic_types.h @@ -0,0 +1,266 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_MATCH_BASIC_TYPES_H +#define LIBLP_MATCH_BASIC_TYPES_H +#include +#include +#include +#include +#include +namespace Potassco { + +/*! + * \addtogroup ParseType + */ +///@{ + +//! Exception type used to signal errors during parsing. +class ParseError : public std::logic_error { +public: + //! Constructs a ParseError from the given line and message. + ParseError(unsigned a_line, const char* msg); + unsigned line; /**< Line in which error occurred. */ +}; +//! A wrapper around an std::istream that provides buffering and a simple interface for extracting characters and integers. +class BufferedStream { +public: + enum { BUF_SIZE = 4096 }; + //! Creates a new object wrapping the given stream. + explicit BufferedStream(std::istream& str); + ~BufferedStream(); + //! Returns the next character in the input stream, without extracting it. + char peek() const { return buf_[rpos_]; } + //! Returns whether the end of the input stream was reached. + bool end() const { return peek() == 0; } + //! Extracts the next character from the input stream or returns 0 if the end was reached. + char get(); + //! Attempts to put back the given character into the read buffer. + bool unget(char c); + //! Attempts to read an integer from the input stream optionally skipping initial whitespace. + bool match(int64_t& i, bool noSkipWs = false); + //! Attempts to extract the given string from the input stream. + /*! + * If the function returns false, no characters were extracted from the stream. + * \pre std::strlen(tok) <= BUF_SIZE + */ + bool match(const char* tok); + //! Extracts initial whitespace from the input stream. + void skipWs(); + //! Extracts up to max characters from the input stream and copies them into bufferOut. + /*! + * \return The number of characters copied to bufferOut. + */ + int copy(char* bufferOut, int max); + //! Returns the current line number in the input stream, i.e. the number of '\n' characters extracted so far. + unsigned line() const; + //! Returns whether the given character is a decimal digit. + static inline bool isDigit(char c) { return c >= '0' && c <= '9'; } + //! Converts the given character to a decimal digit. + static inline int toDigit(char c) { return static_cast(c - '0'); } +private: + char rget(); + enum { ALLOC_SIZE = BUF_SIZE + 1 }; + BufferedStream& operator=(const BufferedStream&); + void underflow(bool up = true); + typedef char* BufferType; + std::istream& str_; + BufferType buf_; + std::size_t rpos_; + unsigned line_; +}; + +/*! + * \name Match + * Match functions for extracting tokens from a stream/string. + */ +///@{ +//! Attempts to extract the given string from the stream optionally skipping leading whitespace first. +inline bool match(BufferedStream& str, const char* word, bool skipWs) { + if (skipWs) str.skipWs(); + return str.match(word); +} +//! Extracts an int in the given range or throws a ParseError if this fails. +inline int matchInt(BufferedStream& str, int min = INT_MIN, int max = INT_MAX, const char* err = "integer expected") { + int64_t x; + if (str.match(x) && x >= min && x <= max) { return static_cast(x); } + throw ParseError(str.line(), err); +} +//! Extracts a positive integer in the range [0;max] or throws a ParseError if this fails. +inline unsigned matchPos(BufferedStream& str, unsigned max, const char* err) { + int64_t x; + if (str.match(x) && x >= 0 && static_cast(x) <= max) { return static_cast(x); } + throw ParseError(str.line(), err); +} +//! Extracts a positive integer or throws a ParseError if this fails. +inline unsigned matchPos(BufferedStream& str, const char* err = "non-negative integer expected") { + return matchPos(str, static_cast(-1), err); +} +//! Extracts an atom (i.e. a positive integer > 0) or throws a ParseError if this fails. +inline Atom_t matchAtom(BufferedStream& str, unsigned aMax = atomMax, const char* err = "atom expected") { + int64_t x; int64_t max = static_cast(aMax); + if (str.match(x) && x >= atomMin && x <= max) { return static_cast(x); } + throw ParseError(str.line(), err); +} +//! Extracts a literal (i.e. a signed integer != 0) or throws a ParseError if this fails. +inline Lit_t matchLit(BufferedStream& str, unsigned aMax = atomMax, const char* err = "literal expected") { + int64_t x; int64_t max = static_cast(aMax); + if (str.match(x) && x != 0 && x >= -max && x <= max) { return static_cast(x); } + throw ParseError(str.line(), err); +} +//! Extracts a weight literal (i.e. a literal followed by an integer) or throws a ParseError if this fails. +inline WeightLit_t matchWLit(BufferedStream& str, unsigned aMax = atomMax, Weight_t minW = 0, const char* err = "weight literal expected") { + WeightLit_t wl; + wl.lit = matchLit(str, aMax, err); + wl.weight = matchInt(str, minW, INT_MAX, "invalid weight literal weight"); + return wl; +} +//! Returns whether input starts with word and if so sets input to input + std::strlen(word). +bool match(const char*& input, const char* word); +//! Returns whether input starts with a string representation of a heuristic modifier and if so extracts it. +/*! + * \see toString(Heuristic_t) + */ +bool match(const char*& input, Heuristic_t& heuType); +//! Attempts to extract the next argument of a predicate. +bool matchAtomArg(const char*& input, StringSpan& arg); +//! Attempts to extract an integer from input and sets input to the first character after the integer. +bool match(const char*& input, int& out); +//! Tries to match potassco's special _heuristic/3 or _heuristic/4 predicate. +/*! + * \return > 1 on match, 0 if in does not start with _heuristic, < 0 if in has wrong arity or parameters. + */ +int matchDomHeuPred(const char*& in + , StringSpan& atom + , Heuristic_t& type + , int& bias + , unsigned& prio); +//! Tries to match an _edge/2 or _acyc_/0 predicate. +int matchEdgePred(const char*& in, StringSpan& n0, StringSpan& n1); +///@} + +//! Base class for input parsers. +class ProgramReader { +public: + //! Enumeration type for supported read modes. + enum ReadMode { Incremental, Complete }; + //! Creates a reader that is not yet associated with any input stream. + ProgramReader(); + virtual ~ProgramReader(); + //! Associates the reader with the given input stream and returns whether the stream has the right format. + bool accept(std::istream& str); + //! Returns whether the input stream represents an incremental program. + bool incremental() const; + //! Attempts to parse the previously accepted input stream. + /*! + * Depending on the given read mode, the function either parses the complete program + * or only the next incremental step. + */ + bool parse(ReadMode r = Incremental); + //! Returns whether the input stream has more data or is exhausted. + bool more(); + //! Resets this object to the state after default construction. + void reset(); + //! Returns the current line number in the input stream. + unsigned line() const; + //! Sets the largest possible variable number. + /*! + * The given value is used when matching atoms or literals. + * If a larger value is found in the input stream, a ParseError exception + * is thrown. + */ + void setMaxVar(unsigned v) { varMax_ = v; } +protected: + typedef BufferedStream StreamType; + typedef WeightLit_t WLit_t; + //! Shall return true if the format of the input stream is supported by this object. + /*! + * \param[out] inc Whether the input stream represents an incremental program. + */ + virtual bool doAttach(bool& inc) = 0; + //! Shall parse the next program step. + virtual bool doParse() = 0; + //! Shall reset any parsing state. + virtual void doReset(); + //! Returns the associated input stream. + StreamType* stream() const; + //! Returns the next character in the input stream, without extracting it. + char peek(bool skipws) const; + //! Throws a ParseError with the current line and given message if cnd is false. + bool require(bool cnd, const char* msg) const; + //! Attempts to match the given string. + bool match(const char* word, bool skipWs = true) { return Potassco::match(*stream(), word, skipWs); } + //! Extracts an int in the given range or throws a ParseError if this fails. + int matchInt(int min = INT_MIN, int max = INT_MAX, const char* err = "integer expected") { return Potassco::matchInt(*stream(), min, max, err); } + //! Extracts a positive integer in the range [0;max] or throws a ParseError if this fails. + unsigned matchPos(unsigned max = static_cast(-1), const char* err = "unsigned integer expected") { return Potassco::matchPos(*stream(), max, err); } + //! Extracts a positive integer or throws a ParseError if this fails. + unsigned matchPos(const char* err) { return matchPos(static_cast(-1), err); } + //! Extracts an atom (i.e. a positive integer > 0) or throws a ParseError if this fails. + /*! + * \see setMaxVar(unsigned) + */ + Atom_t matchAtom(const char* err = "atom expected") { return Potassco::matchAtom(*stream(), varMax_, err); } + //! Extracts a literal (i.e. a signed integer != 0) or throws a ParseError if this fails. + Lit_t matchLit(const char* err = "literal expected") { return Potassco::matchLit(*stream(), varMax_, err); } + //! Extracts a weight literal (i.e. a literal followed by an integer) or throws a ParseError if this fails. + WLit_t matchWLit(int min, const char* err = "weight literal expected") { return Potassco::matchWLit(*stream(), varMax_, min, err); } + //! Extracts and discards characters up to and including the next newline. + void skipLine(); +private: + ProgramReader(const ProgramReader&); + ProgramReader& operator=(const ProgramReader&); + StreamType* str_; + unsigned varMax_; + bool inc_; +}; + +//! A (dynamic-sized) stack for storing basic types like literals and atoms. +class BasicStack : public RawStack { +public: + //! Pushes the given integer or literal onto the stack. + void push(int32_t x) { push(static_cast(x)); } + //! Pushes the given unsigned integer or atom onto the stack. + void push(uint32_t x); + //! Pushes the given weight literal onto the stack. + void push(WeightLit_t x); + //! Pops an object, which shall be of type T, from the stack. + template T pop() { const T* x; pop(&x, 1); return *x; } + //! Allocates space for len objects of type T on the stack and returns the starting address of the allocated range. + template T* makeSpan(uint32_t len) { T* x; push(&x, len); return x; } + //! Pops a range of len objects of type T from the stack. + template Span popSpan(uint32_t len) { const T* x; pop(&x, len); return toSpan(x, len); } +protected: + //! Pops len objects of type T from the stack. + template + void pop(const T**, uint32_t len); + //! Pops len characters from the stack. + void pop(const char**, uint32_t len); + //! Allocates space for len objects of type T. + template + void push(T**, uint32_t len); + //! Allocates space for len characters. + void push(char**, uint32_t len); +}; + +//! Attaches the given stream to r and calls ProgramReader::parse() with the read mode set to ProgramReader::Complete. +int readProgram(std::istream& str, ProgramReader& r, ErrorHandler err); +} +///@} + +#endif diff --git a/liblp/potassco/rule_utils.h b/liblp/potassco/rule_utils.h new file mode 100644 index 0000000..19254f3 --- /dev/null +++ b/liblp/potassco/rule_utils.h @@ -0,0 +1,142 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_RULE_UTILS_H_INCLUDED +#define LIBLP_RULE_UTILS_H_INCLUDED +#include +#include +namespace Potassco { +/*! + * \addtogroup BasicTypes + */ +///@{ + +//! A sum aggregate with a lower bound. +struct Sum_t { + WeightLitSpan lits; /**< Weight literals of the aggregate. */ + Weight_t bound; /**< Lower bound of the aggregate. */ +}; +//! A type that can represent an aspif rule. +struct Rule_t { + Head_t ht; /**< Head type of the rule. */ + AtomSpan head; /**< Head atoms of the rule. */ + Body_t bt; /**< Type of rule body. */ + union { + LitSpan cond; + Sum_t agg; + }; + //! Named constructor for creating a rule. + static Rule_t normal(Head_t ht, const AtomSpan& head, const LitSpan& body); + //! Named constructor for creating a sum rule. + static Rule_t sum(Head_t ht, const AtomSpan& head, const Sum_t& sum); + //! Named constructor for creating a sum rule. + static Rule_t sum(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& lits); + //! Returns whether the rule has a normal body, i.e. whether the body is a conjunction of literals. + bool normal() const { return bt == Body_t::Normal; } + //! Returns whether the body of the rule is a sum aggregate. + bool sum() const { return bt != Body_t::Normal; } +}; + +//! A builder class for creating a rule. +class RuleBuilder { +public: + RuleBuilder(); + /*! + * \name Start functions + * Functions for starting the definition of a rule's head or body. + * If the active rule is frozen (i.e. end() was called), the active + * rule is discarded. + * \note The body of a rule can be defined before or after its head is defined + * but definitions of head and body must not be mixed. + */ + //@{ + //! Start definition of the rule's head, which can be either disjunctive or a choice. + RuleBuilder& start(Head_t ht = Head_t::Disjunctive); + //! Start definition of a minimize rule. No head allowed. + RuleBuilder& startMinimize(Weight_t prio); + //! Start definition of a conjunction to be used as the rule's body. + RuleBuilder& startBody(); + //! Start definition of a sum aggregate to be used as the rule's body. + RuleBuilder& startSum(Weight_t bound); + //@} + + /*! + * \name Update functions + * Functions for adding elements to the active rule. + * \note Update function shall not be called once a rule is frozen. + * \note Calling an update function implicitly starts the definition of the + * corresponding rule part. + */ + //@{ + //! Add a to the rule's head. + RuleBuilder& addHead(Atom_t a); + //! Add lit to the rule's body. + RuleBuilder& addGoal(Lit_t lit); + //! Add lit with given weight to rule's body if body is a sum aggregate or rule is a minimize rule. + RuleBuilder& addGoal(Lit_t lit, Weight_t w); + RuleBuilder& addGoal(WeightLit_t lit); + //! Update lower bound of sum aggregate. + RuleBuilder& setBound(Weight_t bound); + //@} + + //! Stop definition of rule and add rule to out if given. + /*! + * Once end() was called, the active rule is considered frozen. + */ + RuleBuilder& end(AbstractProgram* out = 0); + //! Discard active rule. + RuleBuilder& clear(); + //! Discard body of active rule but keep head if any. + RuleBuilder& clearBody(); + //! Weaken active sum aggregate body to a normal body or count aggregate. + RuleBuilder& weaken(Body_t to, bool resetWeights = true); + + /*! + * \name Query functions + * Functions for accessing parts of the active rule. + * \note The result of these functions is only valid until the next call to + * an update function. + */ + //@{ + uint32_t headSize() const; + Atom_t* head() const; + uint32_t bodySize() const; + Body_t bodyType() const; + Lit_t* body() const; + WeightLit_t* sum() const; + Weight_t bound() const; + Rule_t rule() const; + //@} +private: + struct RuleInfo; + struct Data : RawStack { + template + T* push() { return new (this->get(this->push_(sizeof(T)))) T(); } + }; + void require(bool, const char*) const; + void endHead(); + void endBody(); + RuleInfo* startBody(Body_t bt, Weight_t bnd); + RuleInfo* init(); + RuleInfo* info() const; + Data data_; +}; +///@} + +} +#endif diff --git a/liblp/potassco/smodels.h b/liblp/potassco/smodels.h new file mode 100644 index 0000000..193f352 --- /dev/null +++ b/liblp/potassco/smodels.h @@ -0,0 +1,188 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_SMODELS_H_INCLUDED +#define LIBLP_SMODELS_H_INCLUDED +#include +namespace Potassco { + +/*! + * \addtogroup ParseType + */ +///@{ + +//! Interface representing an smodels-style symbol table. +class AtomTable { +public: + virtual ~AtomTable(); + //! Associate a name with the given (output) atom. + virtual void add(Atom_t id, const StringSpan& name, bool output) = 0; + //! Return the atom with the given name or 0 if no such atom was previously added. + virtual Atom_t find(const StringSpan& name) = 0; +}; + +//! Class for parsing logic programs in (extended) smodels format. +class SmodelsInput : public ProgramReader { +public: + //! Options for configuring reading of smodels format. + struct Options { + Options() : claspExt(false), cEdge(false), cHeuristic(false), filter(false) {} + //! Enable clasp extensions for handling incremental programs. + Options& enableClaspExt() { claspExt = true; return *this; } + //! Convert _edge/_acyc_ atoms to edge directives. + Options& convertEdges() { cEdge = true; return *this; } + //! Convert _heuristic atoms to heuristic directives. + Options& convertHeuristic() { cHeuristic = true; return *this; } + //! Remove converted atoms from output. + Options& dropConverted() { filter = true; return *this; } + bool claspExt; + bool cEdge; + bool cHeuristic; + bool filter; + }; + //! Creates a new parser object that calls out on each parsed element. + SmodelsInput(AbstractProgram& out, const Options& opts, AtomTable* symTab = 0); + virtual ~SmodelsInput(); +protected: + //! Checks whether stream starts with a valid smodels token. + virtual bool doAttach(bool& inc); + //! Parses the current step and throws exception on error. + /*! + * The function calls beginStep()/endStep() on the associated + * output object before/after parsing the current step. + */ + virtual bool doParse(); + //! Resets internal parsing state. + virtual void doReset(); + //! Reads the current rule block. + virtual bool readRules(); + //! Reads the current smodels symbol table block. + virtual bool readSymbols(); + //! Reads the current part of the compute statement. + virtual bool readCompute(const char* sec, bool val); + //! Reads an optional external block and the number of models. + virtual bool readExtra(); + + //! Pushes literals to stack and returns the number of pushed literals. + uint32_t matchBody(BasicStack& stack); + //! Pushes literals and bound to stack and returns the number of pushed literals. + uint32_t matchSum(BasicStack& stack, bool weights); +private: + struct NodeTab; + struct SymTab; + AbstractProgram& out_; + AtomTable* atoms_; + NodeTab* nodes_; + Options opts_; + bool delSyms_; +}; + +/*! + * Parses the given program in smodels format and calls out on each parsed element. + * The error handler h is called on error. If h is 0, ParseError exceptions are used to signal errors. + */ +int readSmodels(std::istream& prg, AbstractProgram& out, ErrorHandler h = 0, const SmodelsInput::Options& opts = SmodelsInput::Options()); + +///@} + +/*! + * \addtogroup WriteType + */ +///@{ + +//! Returns a non-zero value if head can be represented in smodels format (i.e. is not empty). +int isSmodelsHead(Head_t ht, const AtomSpan& head); +//! Returns a non-zero value if rule can be represented in smodels format. +int isSmodelsRule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body); + +//! Writes a program in smodels numeric format to the given output stream. +/*! + * \note The class only supports program constructs that can be directly + * expressed in smodels numeric format. + */ +class SmodelsOutput : public AbstractProgram { +public: + //! Creates a new object and associates it with the given output stream. + /*! + * If enableClaspExt is true, rules with numbers 90, 91, and 92 + * are used to enable incremental programs and external atoms. + * + * The falseAtom is used to write integrity constraints and can be + * set to 0 if integrity constraints are not used. + */ + SmodelsOutput(std::ostream& os, bool enableClaspExt, Atom_t falseAtom); + //! Prepares the object for a new program. + /*! + * Requires enableClaspExt or inc must be false. + */ + virtual void initProgram(bool inc); + //! Starts a new step. + virtual void beginStep(); + //! Writes the given rule provided that isSmodelsHead(head) returns a non-zero value. + virtual void rule(Head_t t, const AtomSpan& head, const LitSpan& body); + //! Writes the given rule provided that isSmodelsRule(head, bound, body) returns a non-zero value. + virtual void rule(Head_t t, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body); + //! Writes the given minimize rule while ignoring its priority. + virtual void minimize(Weight_t prio, const WeightLitSpan& lits); + //! Writes the entry (a, str) to the symbol table provided that condition equals a. + /*! + * \note Symbols shall only be added once after all rules were added. + */ + virtual void output(const StringSpan& str, const LitSpan& cond); + //! Writes lits as a compute statement. + /*! + * \note The function shall be called at most once per step and only after all rules and symbols were added. + */ + virtual void assume(const LitSpan& lits); + //! Requires enableClaspExt or throws exception. + virtual void external(Atom_t a, Value_t v); + //! Terminates the current step. + virtual void endStep(); +protected: + //! Starts writing an smodels-rule of type rt. + SmodelsOutput& startRule(int rt); + //! Writes the given head. + SmodelsOutput& add(Head_t ht, const AtomSpan& head); + //! Writes the given normal body in smodels format, i.e. size(lits) size(B-) atoms in B- atoms in B+ + SmodelsOutput& add(const LitSpan& lits); + //! Writes the given extended body in smodels format. + SmodelsOutput& add(Weight_t bound, const WeightLitSpan& lits, bool card); + //! Writes i. + SmodelsOutput& add(unsigned i); + //! Terminates the active rule by writing a newline. + SmodelsOutput& endRule(); + //! Throws an std::logic_error if cnd is false. + void require(bool cnd, const char* msg) const; + //! Returns whether the current program is incremental. + bool incremental() const { return inc_; } + //! Returns whether clasp extensions are enabled. + bool extended() const { return ext_; } +private: + SmodelsOutput(const SmodelsOutput&); + SmodelsOutput& operator=(const SmodelsOutput&); + std::ostream& os_; + Atom_t false_; + int sec_; + bool ext_; + bool inc_; + bool fHead_; +}; +///@} + +} +#endif diff --git a/liblp/potassco/theory_data.h b/liblp/potassco/theory_data.h new file mode 100644 index 0000000..e078d82 --- /dev/null +++ b/liblp/potassco/theory_data.h @@ -0,0 +1,408 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifndef LIBLP_THEORY_DATA_H_INCLUDED +#define LIBLP_THEORY_DATA_H_INCLUDED + +#ifdef _MSC_VER +#pragma once +#pragma warning (push) +#pragma warning (disable : 4200) // zero-sized array +#elif __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wzero-length-array" +#elif __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-pedantic" +#endif +#include +#include +#include +#include +namespace Potassco { + +class TheoryData; +struct FuncData; + +/*! + * \addtogroup BasicTypes + */ +///@{ +//! Supported aspif theory directives. +struct Theory_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS(Theory_t, + Number = 0, Symbol = 1, Compound = 2, Reserved = 3, + Element = 4, + Atom = 5, AtomWithGuard = 6 + ); +}; + +//! Supported aspif theory tuple types. +struct Tuple_t { + //! Named constants. + POTASSCO_ENUM_CONSTANTS_T(Tuple_t, int, -3, Bracket = -3, Brace = -2, Paren = -1); +}; +//! Returns starting and ending delimiters of the given tuple type. +inline const char* toString(Tuple_t t) { + static const char* p = "()\0{}\0[]"; + int off = (-static_cast(t)-1) * 3; + return p + off; +} + +//! A term is either a number, symbolic, or compound term (function or tuple). +class TheoryTerm { +public: + //! Iterator type for iterating over arguments of a compound term. + typedef const Id_t* iterator; + //! Creates an invalid term. + TheoryTerm(); + //! Creates a number term. + explicit TheoryTerm(int num); + //! Creates a symbolic term. + explicit TheoryTerm(const char* sym); + //! Creates a compound term. + explicit TheoryTerm(const FuncData* c); + //! Returns whether this object holds a valid number, symbol or compound. + bool valid() const; + //! Returns the type of this term. + Theory_t type() const; + //! Returns the number stored in this or throws if type() != Number. + int number() const; + //! Returns the symbol stored in this or throws if type() != Symbol. + const char* symbol() const; + //! Returns the compound id (either term id or tuple type) stored in this or throws if type() != Compound. + int compound() const; + //! Returns whether this is a function. + bool isFunction() const; + //! Returns the function id stored in this or throws if !isFunction(). + Id_t function() const; + //! Returns whether this is a tuple. + bool isTuple() const; + //! Returns the tuple id stored in this or throws if !isTuple(). + Tuple_t tuple() const; + //! Returns the number of arguments in this term. + uint32_t size() const; + //! Returns an iterator pointing to the first argument of this term. + iterator begin() const; + //! Returns an iterator marking the end of the arguments of this term. + iterator end() const; + //! Returns the range [begin(), end()). + IdSpan terms() const { return toSpan(begin(), size()); } +private: + friend class TheoryData; + uint64_t assertPtr(const void*) const; + void assertType(Theory_t) const; + uintptr_t getPtr() const; + FuncData* func() const; + uint64_t data_; +}; + +//! A basic building block for a theory atom. +class TheoryElement { +public: + //! Iterator type for iterating over the terms of an element. + typedef const Id_t* iterator; + //! Creates a new TheoryElement over the given terms. + static TheoryElement* newElement(const IdSpan& terms, Id_t condition); + //! Destroys the given TheoryElement. + static void destroy(TheoryElement* a); + //! Returns the number of terms belonging to this element. + uint32_t size() const { return nTerms_; } + //! Returns an iterator pointing to the first term of this element. + iterator begin() const { return term_; } + //! Returns an iterator one past the last term of this element. + iterator end() const { return begin() + size(); } + //! Returns the terms of this element. + IdSpan terms() const { return toSpan(begin(), size()); } + //! Returns the condition associated with this element. + Id_t condition() const; +private: + friend class TheoryData; + TheoryElement(const IdSpan& terms, Id_t c); + TheoryElement(const TheoryElement&); + TheoryElement& operator=(const TheoryElement&); + void setCondition(Id_t c); + uint32_t nTerms_ : 31; + uint32_t nCond_ : 1; + Id_t term_[0]; +}; + +//! A theory atom. +class TheoryAtom { +public: + //! Iterator type for iterating over the elements of a theory atom. + typedef const Id_t* iterator; + //! Creates a new theory atom. + static TheoryAtom* newAtom(Id_t atom, Id_t term, const IdSpan& elements); + //! Creates a new theory atom with guard. + static TheoryAtom* newAtom(Id_t atom, Id_t term, const IdSpan& elements, Id_t op, Id_t rhs); + //! Destroys the given theory atom. + static void destroy(TheoryAtom* a); + + //! Returns the associated program atom or 0 if this originated from a directive. + Id_t atom() const { return static_cast(atom_); } + //! Returns the term that is associated with this atom. + Id_t term() const { return termId_; } + //! Returns the number of elements in this atom. + uint32_t size() const { return nTerms_; } + //! Returns an iterator pointing to the first element of this atom. + iterator begin() const { return term_; } + //! Returns an iterator marking the end of elements of this atoms. + iterator end() const { return begin() + size(); } + //! Returns the range [begin(), end()). + IdSpan elements() const { return toSpan(begin(), size()); } + //! Returns a pointer to the id of the theory operator associated with this atom or 0 if atom has no guard. + const Id_t* guard() const; + //! Returns a pointer to the term id of the right hand side of the theory operator or 0 if atom has no guard. + const Id_t* rhs() const; +private: + TheoryAtom(Id_t atom, Id_t term, const IdSpan& elements, Id_t* op, Id_t* rhs); + TheoryAtom(const TheoryAtom&); + TheoryAtom& operator=(const TheoryAtom&); + uint32_t atom_ : 31; + uint32_t guard_: 1; + Id_t termId_; + uint32_t nTerms_; + Id_t term_[0]; +}; + +//! A type for storing and looking up theory atoms and their elements and terms. +class TheoryData { +public: + //! Iterator type for iterating over the theory atoms of a TheoryData object. + typedef const TheoryAtom*const* atom_iterator; + typedef TheoryTerm Term; + typedef TheoryElement Element; + TheoryData(); + ~TheoryData(); + //! Sentinel for marking a condition to be set later. + static const Id_t COND_DEFERRED = static_cast(-1); + + //! Resets this object to the state after default construction. + void reset(); + //! May be called to distinguish between the current and a previous incremental step. + void update(); + + //! Adds a new theory atom. + /*! + * Each element in elements shall be an id associated with an atom element + * eventually added via addElement(). + */ + const TheoryAtom& addAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements); + //! Adds a new theory atom with guard and right hand side. + const TheoryAtom& addAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements, Id_t op, Id_t rhs); + + //! Adds a new theory atom element with the given id. + /*! + * Each element in terms shall be an id of a theory term + * eventually added via one of the addTerm() overloads. + * \note If cond is COND_DEFERRED, the condition may later be changed via a call to setCondition(). + */ + const TheoryElement& addElement(Id_t elementId, const IdSpan& terms, Id_t cond = COND_DEFERRED); + //! Changes the condition of the element with the given id. + /*! + * \pre The element was previously added with condition COND_DEFERRED. + */ + void setCondition(Id_t elementId, Id_t newCond); + + //! Adds a new number term with the given id. + const TheoryTerm& addTerm(Id_t termId, int number); + //! Adds a new symbolic term with the given name and id. + const TheoryTerm& addTerm(Id_t termId, const StringSpan& name); + //! Adds a new symbolic term with the given name and id. + const TheoryTerm& addTerm(Id_t termId, const char* name); + //! Adds a new function term with the given id. + /*! + * The parameter funcSym represents the name of the function and shall be the id of a symbolic term. + * Each element in args shall be an id of a theory term. + */ + const TheoryTerm& addTerm(Id_t termId, Id_t funcSym, const IdSpan& args); + //! Adds a new tuple term with the given id. + const TheoryTerm& addTerm(Id_t termId, Tuple_t type, const IdSpan& args); + + //! Removes the term with the given id. + /*! + * \note It is the caller's responsibility to ensure that the removed term is not referenced + * by any theory element. + * \note The term id of a removed term may be reused in a subsequent call to addTerm(). + */ + void removeTerm(Id_t termId); + + //! Returns the number of stored theory atoms. + uint32_t numAtoms() const; + //! Returns an iterator pointing to the first theory atom. + atom_iterator begin() const; + //! Returns an iterator pointing to the first theory atom added after last call to update. + atom_iterator currBegin() const; + //! Returns an iterator marking the end of the range of theory atoms. + atom_iterator end() const; + //! Returns whether this object stores a term with the given id. + bool hasTerm(Id_t t) const; + //! Returns whether the given term was added after last call to update. + bool isNewTerm(Id_t t) const; + //! Returns whether this object stores an atom element with the given id. + bool hasElement(Id_t e) const; + //! Returns whether the given element was added after last call to update. + bool isNewElement(Id_t e) const; + //! Returns the term with the given id or throws if no such term exists. + const Term& getTerm(Id_t t) const; + //! Returns the element with the given id or throws if no such element exists. + const Element& getElement(Id_t e) const; + + //! Removes all theory atoms a for which f(a) returns true. + template + void filter(const F& f) { + TheoryAtom** j = atoms() + frame_.atom; + uint32_t pop = 0; + for (atom_iterator it = j, end = atoms() + numAtoms(); it != end; ++it) { + Id_t atom = (*it)->atom(); + if (!atom || !f(**it)) { + *j++ = const_cast(*it); + } + else { + pop += sizeof(*it); + TheoryAtom::destroy(const_cast(*it)); + } + } + atoms_.setTop(atoms_.top() - pop); + } + //! Interface for visiting a theory. + class Visitor { + public: + virtual ~Visitor(); + //! Visit a theory term. Should call data.accept(t, *this) to visit any arguments of the term. + virtual void visit(const TheoryData& data, Id_t termId, const TheoryTerm& t) = 0; + //! Visit a theory element. Should call data.accept(e, *this) to visit the terms of the element. + virtual void visit(const TheoryData& data, Id_t elemId, const TheoryElement& e) = 0; + //! Visit the theory atom. Should call data.accept(a, *this) to visit the elements of the atom. + virtual void visit(const TheoryData& data, const TheoryAtom& a) = 0; + }; + //! Calls out.visit(*this, a) for all atoms a in [currBegin(), end()). + void accept(Visitor& out) const; + //! Visits all terms and elements of a added in the current step. + void accept(const TheoryAtom& a, Visitor& out) const; + //! Visits all terms of e added in the current step. + void accept(const TheoryElement& e, Visitor& out) const; + //! If t is a compound term, visits subterms added in the current step. + void accept(const TheoryTerm& t, Visitor& out) const; +private: + struct PtrStack : public RawStack { + typedef void* value_type; + void push(void* ptr) { new (get(push_(sizeof(value_type)))) value_type(ptr); } + }; + struct TermStack : public RawStack { + void push(const TheoryTerm& t) { new (get(push_(sizeof(TheoryTerm)))) TheoryTerm(t); } + }; + TheoryData(const TheoryData&); + TheoryData& operator=(const TheoryData&); + struct DestroyT; + TheoryTerm& setTerm(Id_t); + TheoryTerm* terms() const; + TheoryElement** elems() const; + TheoryAtom** atoms() const; + uint32_t numTerms() const; + uint32_t numElems() const; + PtrStack atoms_; + PtrStack elems_; + TermStack terms_; + struct Up { + Up() : atom(0), term(0), elem(0) {} + uint32_t atom; + uint32_t term; + uint32_t elem; + } frame_; +}; + +/*! + * Adaptor that couples an iterator returned from a theory atom, element, or term + * with a TheoryData object so that dereferencing yields an object instead of an id. + */ +template +class IteratorAdaptor : public std::iterator { +public: + typedef IteratorAdaptor this_type; + typedef std::iterator base_type; + typedef typename base_type::reference reference; + typedef typename base_type::pointer pointer; + IteratorAdaptor(const TheoryData& t, const Id_t* e) : data_(&t), elem_(e) {} + IteratorAdaptor() : data_(0), elem_(0) {} + this_type& operator++() { ++elem_; return *this; } + this_type operator++(int) { + this_type t(*this); + ++*this; + return t; + } + this_type& operator--() { --elem_; return *this; } + this_type operator--(int) { + this_type t(*this); + --*this; + return t; + } + reference operator*() const { return (data_->*get)(*raw()); } + pointer operator->() const { return &**this; } + + friend void swap(this_type& lhs, this_type& rhs) { + std::swap(lhs.data_, rhs.data_); + std::swap(lhs.elem_, rhs.elem_); + } + friend bool operator==(const this_type& lhs, const this_type& rhs) { + return lhs.data_ == rhs.data_ && lhs.elem_ == rhs.elem_; + } + friend bool operator!=(const this_type& lhs, const this_type& rhs) { + return !(lhs == rhs); + } + const Id_t* raw() const { return elem_; } + const TheoryData& theory() const { return *data_; } +private: + const TheoryData* data_; + const Id_t* elem_; +}; + +typedef IteratorAdaptor TheoryElementIterator; +typedef IteratorAdaptor TheoryTermIterator; + +inline TheoryElementIterator begin(const TheoryData& t, const TheoryAtom& a) { return TheoryElementIterator(t, a.begin()); } +inline TheoryElementIterator end(const TheoryData& t, const TheoryAtom& a) { return TheoryElementIterator(t, a.end()); } +inline TheoryTermIterator begin(const TheoryData& t, const TheoryElement& e){ return TheoryTermIterator(t, e.begin()); } +inline TheoryTermIterator end(const TheoryData& t, const TheoryElement& e) { return TheoryTermIterator(t, e.end()); } + +StringSpan toSpan(const char* x); + +inline void print(AbstractProgram& out, Id_t termId, const TheoryTerm& term) { + switch (term.type()) { + case Potassco::Theory_t::Number : out.theoryTerm(termId, term.number()); break; + case Potassco::Theory_t::Symbol : out.theoryTerm(termId, Potassco::toSpan(term.symbol())); break; + case Potassco::Theory_t::Compound: out.theoryTerm(termId, term.compound(), term.terms()); break; + } +} +inline void print(AbstractProgram& out, const TheoryAtom& a) { + if (a.guard()) { out.theoryAtom(a.atom(), a.term(), a.elements(), *a.guard(), *a.rhs()); } + else { out.theoryAtom(a.atom(), a.term(), a.elements()); } +} +///@} +} +#ifdef _MSC_VER +#pragma warning (pop) +#elif __GNUC__ +#pragma GCC diagnostic pop +#endif +#endif diff --git a/liblp/src/aspif.cpp b/liblp/src/aspif.cpp new file mode 100644 index 0000000..152ad1b --- /dev/null +++ b/liblp/src/aspif.cpp @@ -0,0 +1,284 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include +#include +#include +#include +#if defined(_MSC_VER) +#pragma warning (disable : 4996) +#endif +namespace Potassco { +///////////////////////////////////////////////////////////////////////////////////////// +// AspifInput +///////////////////////////////////////////////////////////////////////////////////////// +AspifInput::AspifInput(AbstractProgram& out) : out_(out), data_(0) {} +AspifInput::~AspifInput() { } + +bool AspifInput::doAttach(bool& inc) { + if (!match("asp ")) { return false; } + require(matchPos() == 1, "unsupported major version"); + require(matchPos() == 0, "unsupported minor version"); + matchPos("revision number expected"); + while (match(" ", false)) { ; } + inc = match("incremental", false); + out_.initProgram(inc); + return require(stream()->get() == '\n', "invalid extra characters in problem line"); +} +bool AspifInput::doParse() { +#define CR(r) Directive_t::r + BasicStack data; + data_ = &data; + out_.beginStep(); + for (unsigned rt; (rt = matchPos(Directive_t::eMax, "rule type or 0 expected")) != 0; ) { + data.clear(); + switch (rt) { + default: require(false, "unrecognized rule type"); + {case CR(Rule): + Head_t ht = static_cast(matchPos(Head_t::eMax, "invalid head type")); + uint32_t n = matchAtoms(); + Body_t bt = static_cast(matchPos(Body_t::eMax, "invalid body type")); + if (bt == Body_t::Normal) { + LitSpan body = data.popSpan(matchLits()); + out_.rule(ht, data.popSpan(n), body); + } + else { + Weight_t bound = matchInt(); + WeightLitSpan body = data.popSpan(matchWLits(0)); + out_.rule(ht, data.popSpan(n), bound, body); + } + break;} + {case CR(Minimize): + Weight_t prio = matchInt(); + out_.minimize(prio, data.popSpan(matchWLits(INT_MIN))); + break;} + case CR(Project): + out_.project(data.popSpan(matchAtoms())); + break; + {case CR(Output): + uint32_t len = matchString(); + LitSpan lits = data.popSpan(matchLits()); + out_.output(data.popSpan(len), lits); + break;} + case CR(External): + if (Atom_t atom = matchAtom()) { + Value_t val = static_cast(matchPos(Value_t::eMax, "value expected")); + out_.external(atom, val); + } + break; + case CR(Assume): + out_.assume(data.popSpan(matchLits())); + break; + {case CR(Heuristic): + Heuristic_t type = static_cast(matchPos(Heuristic_t::eMax, "invalid heuristic modifier")); + Atom_t atom = matchAtom(); + int bias = matchInt(); + unsigned prio = matchPos(INT_MAX, "invalid heuristic priority"); + out_.heuristic(atom, type, bias, prio, data.popSpan(matchLits())); + break;} + {case CR(Edge): + unsigned start = matchPos(INT_MAX, "invalid edge, start node expected"); + unsigned end = matchPos(INT_MAX, "invalid edge, end node expected"); + out_.acycEdge((int)start, (int)end, data.popSpan(matchLits())); + break;} + case CR(Theory): matchTheory(matchPos()); break; + case CR(Comment): skipLine(); break; + } + } +#undef CR + out_.endStep(); + data_ = 0; + return true; +} + +uint32_t AspifInput::matchAtoms() { + uint32_t len = matchPos("number of atoms expected"); + for (Atom_t* ptr = data_->makeSpan(len), *end = ptr + len; ptr != end;) { *ptr++ = matchAtom(); } + return len; +} +uint32_t AspifInput::matchLits() { + uint32_t len = matchPos("number of literals expected"); + for (Lit_t* ptr = data_->makeSpan(len), *end = ptr + len; ptr != end;) { *ptr++ = matchLit(); } + return len; +} +uint32_t AspifInput::matchWLits(int32_t minW) { + uint32_t len = matchPos("number of literals expected"); + for (WLit_t* ptr = data_->makeSpan(len), *end = ptr + len; ptr != end;) { *ptr++ = matchWLit(minW); } + return len; +} +uint32_t AspifInput::matchTermList() { + uint32_t len = matchPos("number of terms expected"); + for (Id_t* ptr = data_->makeSpan(len), *end = ptr + len; ptr != end;) { *ptr++ = matchPos(); } + return len; +} +uint32_t AspifInput::matchString() { + uint32_t len = matchPos("non-negative string length expected"); + stream()->get(); + require(stream()->copy(data_->makeSpan(len), (int)len) == (int)len, "invalid string"); + return len; +} + +void AspifInput::matchTheory(unsigned rt) { + Id_t tId = matchPos(); + switch (rt) { + default: require(false, "unrecognized theory directive type"); + case Theory_t::Number: + out_.theoryTerm(tId, matchInt()); + break; + case Theory_t::Symbol: + out_.theoryTerm(tId, data_->popSpan(matchString())); + break; + case Theory_t::Compound: { + int type = matchInt(Tuple_t::eMin, INT_MAX, "unrecognized compound term type"); + out_.theoryTerm(tId, type, data_->popSpan(matchTermList())); + break; + } + case Theory_t::Element: { + uint32_t nt = matchTermList(); + LitSpan lits = data_->popSpan(matchLits()); + out_.theoryElement(tId, data_->popSpan(nt), lits); + break; + } + case Theory_t::Atom: // fall through + case Theory_t::AtomWithGuard: { + Id_t termId = matchPos(); + uint32_t nt = matchTermList(); + if (rt == Theory_t::Atom) { + out_.theoryAtom(tId, termId, data_->popSpan(nt)); + } + else { + Id_t opId = matchPos(); + out_.theoryAtom(tId, termId, data_->popSpan(nt), opId, matchPos()); + } + break; + } + } +} + +int readAspif(std::istream& in, AbstractProgram& out, ErrorHandler err) { + AspifInput reader(out); + return readProgram(in, reader, err); +} +///////////////////////////////////////////////////////////////////////////////////////// +// AspifOutput +///////////////////////////////////////////////////////////////////////////////////////// +AspifOutput::AspifOutput(std::ostream& os) : os_(os) { +} + +AspifOutput& AspifOutput::startDir(Directive_t r) { + os_ << static_cast(r); + return *this; +} +AspifOutput& AspifOutput::add(int x) { + os_ << " " << x; + return *this; +} +AspifOutput& AspifOutput::add(const WeightLitSpan& lits) { + os_ << " " << size(lits); + for (const WeightLit_t* x = begin(lits); x != end(lits); ++x) { + os_ << " " << lit(*x) << " " << weight(*x); + } + return *this; +} +AspifOutput& AspifOutput::add(const LitSpan& lits) { + os_ << " " << size(lits); + for (const Lit_t* x = begin(lits); x != end(lits); ++x) { + os_ << " " << lit(*x); + } + return *this; +} +AspifOutput& AspifOutput::add(const AtomSpan& atoms) { + os_ << " " << size(atoms); + for (const Atom_t* x = begin(atoms); x != end(atoms); ++x) { os_ << " " << *x; } + return *this; +} +AspifOutput& AspifOutput::add(const StringSpan& str) { + os_ << " " << size(str) << " "; + os_.write(begin(str), size(str)); + return *this; +} +AspifOutput& AspifOutput::endDir() { + os_ << "\n"; + return *this; +} +void AspifOutput::initProgram(bool inc) { + os_ << "asp 1 0 0"; + if (inc) os_ << " incremental"; + os_ << "\n"; +} +void AspifOutput::rule(Head_t ht, const AtomSpan& head, const LitSpan& body) { + startDir(Directive_t::Rule).add(static_cast(ht)).add(head) + .add(static_cast(Body_t::Normal)).add(body) + .endDir(); +} +void AspifOutput::rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) { + startDir(Directive_t::Rule).add(static_cast(ht)).add(head) + .add(static_cast(Body_t::Sum)).add(static_cast(bound)).add(body) + .endDir(); +} +void AspifOutput::minimize(Weight_t prio, const WeightLitSpan& lits) { + startDir(Directive_t::Minimize).add(prio).add(lits).endDir(); +} +void AspifOutput::output(const StringSpan& str, const LitSpan& cond) { + startDir(Directive_t::Output).add(str).add(cond).endDir(); +} +void AspifOutput::external(Atom_t a, Value_t v) { + startDir(Directive_t::External).add(static_cast(a)).add(static_cast(v)).endDir(); +} +void AspifOutput::assume(const LitSpan& lits) { + startDir(Directive_t::Assume).add(lits).endDir(); +} +void AspifOutput::project(const AtomSpan& atoms) { + startDir(Directive_t::Project).add(atoms).endDir(); +} +void AspifOutput::acycEdge(int s, int t, const LitSpan& cond) { + startDir(Directive_t::Edge).add(s).add(t).add(cond).endDir(); +} +void AspifOutput::heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& cond) { + startDir(Directive_t::Heuristic).add(static_cast(t)).add(static_cast(a)) + .add(bias).add(static_cast(prio)).add(cond) + .endDir(); +} +void AspifOutput::theoryTerm(Id_t termId, int number) { + startDir(Directive_t::Theory).add(Theory_t::Number).add(termId).add(number).endDir(); +} +void AspifOutput::theoryTerm(Id_t termId, const StringSpan& name) { + startDir(Directive_t::Theory).add(Theory_t::Symbol).add(termId).add(name).endDir(); +} +void AspifOutput::theoryTerm(Id_t termId, int cId, const IdSpan& args) { + startDir(Directive_t::Theory).add(Theory_t::Compound).add(termId).add(cId).add(args).endDir(); +} +void AspifOutput::theoryElement(Id_t elementId, const IdSpan& terms, const LitSpan& cond) { + startDir(Directive_t::Theory).add(Theory_t::Element).add(elementId).add(terms).add(cond).endDir(); +} +void AspifOutput::theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements) { + startDir(Directive_t::Theory).add(Theory_t::Atom).add(atomOrZero).add(termId).add(elements).endDir(); +} +void AspifOutput::theoryAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elements, Id_t op, Id_t rhs) { + startDir(Directive_t::Theory).add(Theory_t::AtomWithGuard).add(atomOrZero).add(termId).add(elements).add(op).add(rhs).endDir(); +} + +void AspifOutput::beginStep() { +} +void AspifOutput::endStep() { + os_ << "0\n"; +} +} diff --git a/liblp/src/aspif_text.cpp b/liblp/src/aspif_text.cpp new file mode 100644 index 0000000..50ef268 --- /dev/null +++ b/liblp/src/aspif_text.cpp @@ -0,0 +1,324 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#include +#include +#include +namespace Potassco { +AspifTextInput::AspifTextInput(AbstractProgram* out) : out_(out), strStart_(0), strPos_(0) {} +bool AspifTextInput::doAttach(bool& inc) { + char n = peek(true); + if (out_ && (!n || std::islower(static_cast(n)) || std::strchr(".#%{:", n))) { + while (n == '%') { + skipLine(); + n = peek(true); + } + inc = match("#incremental", false) && require(match("."), "unrecognized directive"); + out_->initProgram(inc); + return true; + } + return false; +} + +bool AspifTextInput::doParse() { + out_->beginStep(); + if (!parseStatements()) { return false; } + out_->endStep(); + BasicStack().swap(data_); + return true; +} + +bool AspifTextInput::parseStatements() { + require(out_ != 0, "output not set"); + for (char c; (c = peek(true)) != 0;) { + data_.clear(); + if (c == '.') { match("."); } + else if (c == '#') { if (!matchDirective()) break; } + else if (c == '%') { skipLine(); } + else { matchRule(c); } + } + data_.clear(); + return true; +} + +void AspifTextInput::matchRule(char c) { + Head_t ht = Head_t::Disjunctive; + Body_t bt = Body_t::Normal; + if (c != ':') { + if (c == '{') { match("{"); ht = Head_t::Choice; matchAtoms(";,"); match("}"); } + else { matchAtoms(";|"); } + } + else { data_.push(0u); } + if (match(":-", false)) { + c = peek(true); + if (!StreamType::isDigit(c) && c != '-') { + matchLits(); + } + else { + Weight_t bound = matchInt(); + matchAgg(); + data_.push(bound); + bt = Body_t::Sum; + } + } + else { + data_.push(0u); + } + match("."); + if (bt == Body_t::Normal) { + LitSpan body = data_.popSpan(data_.pop()); + AtomSpan head = data_.popSpan(data_.pop()); + out_->rule(ht, head, body); + } + else { + typedef WeightLitSpan WLitSpan; + Weight_t bound = data_.pop(); + WLitSpan body = data_.popSpan(data_.pop()); + AtomSpan head = data_.popSpan(data_.pop()); + out_->rule(ht, head, bound, body); + } +} + +bool AspifTextInput::matchDirective() { + if (match("#minimize", false)) { + matchAgg(); + Weight_t prio = match("@", false) ? matchInt() : 0; + match("."); + out_->minimize(prio, data_.popSpan(data_.pop())); + } + else if (match("#project", false)) { + uint32_t n = 0; + if (match("{", false) && !match("}", false)) { + matchAtoms(","); + match("}"); + n = data_.pop(); + } + match("."); + out_->project(data_.popSpan(n)); + } + else if (match("#output", false)) { + matchTerm(); + matchCondition(); + match("."); + LitSpan cond = data_.popSpan(data_.pop()); + StringSpan str = data_.popSpan(data_.pop()); + out_->output(str, cond); + } + else if (match("#external", false)) { + Atom_t a = matchId(); + Value_t v = Value_t::False; + match("."); + if (match("[", false)) { + if (match("true", false)) { v = Value_t::True; } + else if (match("free", false)) { v = Value_t::Free; } + else if (match("release", false)) { v = Value_t::Release; } + else { match("false"); } + match("]"); + } + out_->external(a, v); + } + else if (match("#assume", false)) { + uint32_t n = 0; + if (match("{", false) && !match("}", false)) { + matchLits(); + match("}"); + n = data_.pop(); + } + match("."); + out_->assume(data_.popSpan(n)); + } + else if (match("#heuristic", false)) { + Atom_t a = matchId(); + matchCondition(); + match("."); + match("["); + int v = matchInt(); + int p = 0; + if (match("@", false)) { p = matchInt(); require(p >= 0, "positive priority expected"); } + match(","); + int h = -1; + for (unsigned x = 0; x <= static_cast(Heuristic_t::eMax); ++x) { + if (match(toString(static_cast(x)), false)) { + h = static_cast(x); + break; + } + } + require(h >= 0, "unrecognized heuristic modification"); + skipws(); + match("]"); + out_->heuristic(a, static_cast(h), v, static_cast(p), data_.popSpan(data_.pop())); + } + else if (match("#edge", false)) { + int s, t; + match("("), s = matchInt(), match(","), t = matchInt(), match(")"); + matchCondition(); + match("."); + out_->acycEdge(s, t, data_.popSpan(data_.pop())); + } + else if (match("#step", false)) { + require(incremental(), "#step requires incremental program"); + match("."); + return false; + } + else if (match("#incremental", false)) { + match("."); + } + else { + require(false, "unrecognized directive"); + } + return true; +} + +void AspifTextInput::skipws() { + stream()->skipWs(); +} +bool AspifTextInput::match(const char* term, bool req) { + if (ProgramReader::match(term, false)) { skipws(); return true; } + else if (!req) { return false; } + else { + startString(); + push('\''); + while (*term) { push(*term++); } + term = "' expected"; + while (*term) { push(*term++); } + push('\0'); + endString(); + return require(false, data_.popSpan(data_.pop()).first); + } +} +void AspifTextInput::matchAtoms(const char* seps) { + for (uint32_t n = 0;;) { + data_.push(matchId()); + ++n; + if (!std::strchr(seps, stream()->peek())) { + data_.push(n); + break; + } + stream()->get(); + skipws(); + } +} +void AspifTextInput::matchLits() { + uint32_t n = 1; + do { + data_.push(matchLit()); + } while (match(",", false) && ++n); + data_.push(n); +} +void AspifTextInput::matchCondition() { + if (match(":", false)) { matchLits(); } + else { data_.push(0u); } +} +void AspifTextInput::matchAgg() { + uint32_t n = 0; + if (match("{") && !match("}", false)) { + do { + WeightLit_t wl = {matchLit(), 1}; + if (match("=", false)) { wl.weight = matchInt(); } + data_.push(wl); + } + while (++n && match(",", false)); + match("}"); + } + data_.push(n); +} + +Lit_t AspifTextInput::matchLit() { + int s = match("not ", false) ? -1 : 1; + return static_cast(matchId()) * s; +} + +int AspifTextInput::matchInt() { + int i = ProgramReader::matchInt(); + skipws(); + return i; +} +Atom_t AspifTextInput::matchId() { + char c = stream()->get(); + char n = stream()->peek(); + require(std::islower(static_cast(c)) != 0, " expected"); + require(std::islower(static_cast(n)) == 0, " expected"); + if (c == 'x' && (BufferedStream::isDigit(n) || n == '_')) { + if (n == '_') { stream()->get(); } + int i = matchInt(); + require(i > 0, " expected"); + return static_cast(i); + } + else { + skipws(); + return static_cast(c - 'a') + 1; + } +} +void AspifTextInput::startString() { + strStart_ = strPos_ = data_.top(); +} +void AspifTextInput::endString() { + data_.push(uint32_t(strPos_ - strStart_)); +} +void AspifTextInput::push(char c) { + if (strPos_ == data_.top()) { data_.push(0); } + *(char*)data_.get(strPos_++) = c; +} + +void AspifTextInput::matchTerm() { + startString(); + char c = stream()->peek(); + if (std::islower(static_cast(c)) != 0 || c == '_') { + do { push(stream()->get()); } while (std::isalnum(static_cast(c = stream()->peek())) != 0 || c == '_'); + skipws(); + if (match("(", false)) { + push('('); + for (;;) { + matchAtomArg(); + if (!match(",", false)) break; + push(','); + } + match(")"); + push(')'); + } + } + else if (c == '"') { matchStr(); } + else { require(false, " expected"); } + skipws(); + endString(); +} +void AspifTextInput::matchAtomArg() { + char c; + for (int p = 0; (c = stream()->peek()) != 0; ) { + if (c == '"') { + matchStr(); + } + else { + if (c == ')' && --p < 0) { break; } + else if (c == ',' && p == 0) { break; } + p += int(c == '('); + push(stream()->get()); + skipws(); + } + } +} +void AspifTextInput::matchStr() { + match("\""), push('"'); + bool quoted = false; + for (char c; (c = stream()->peek()) != 0 && (c != '\"' || quoted);) { + quoted = !quoted && c == '\\'; + push(stream()->get()); + } + match("\""), push('"'); +} +} diff --git a/liblp/src/clingo.cpp b/liblp/src/clingo.cpp new file mode 100644 index 0000000..016f0b2 --- /dev/null +++ b/liblp/src/clingo.cpp @@ -0,0 +1,29 @@ +// +// Copyright (c) 2015-2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#include +namespace Potassco { +AbstractAssignment::~AbstractAssignment() {} +bool AbstractAssignment::isFixed(Lit_t lit) const { return value(lit) != Value_t::Free && level(lit) == 0; } +bool AbstractAssignment::isTrue(Lit_t lit) const { return value(lit) == Value_t::True; } +bool AbstractAssignment::isFalse(Lit_t lit) const { return value(lit) == Value_t::False; } + +AbstractSolver::~AbstractSolver() {} +AbstractPropagator::~AbstractPropagator() {} +AbstractStatistics::~AbstractStatistics() {} + +} diff --git a/liblp/src/convert.cpp b/liblp/src/convert.cpp new file mode 100644 index 0000000..5d02e9f --- /dev/null +++ b/liblp/src/convert.cpp @@ -0,0 +1,325 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#include +#include +#include +#include +#include +#include +#include +#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER > 1500) || (defined(_LIBCPP_VERSION)) +#include +typedef std::unordered_map SymTab; +#else +#if defined(_MSC_VER) +#include +#else +#include +#endif +typedef std::tr1::unordered_map SymTab; +#endif + +#if defined(_MSC_VER) +#pragma warning (disable : 4996) +#define snprintf _snprintf +#endif +namespace Potassco { +///////////////////////////////////////////////////////////////////////////////////////// +// SmodelsConvert::SmData +///////////////////////////////////////////////////////////////////////////////////////// +struct SmodelsConvert::SmData { + struct Atom { + Atom() : smId(0), head(0), show(0), extn(0) {} + operator Atom_t() const { return smId; } + unsigned smId : 28;// corresponding smodels atom + unsigned head : 1; // atom occurs in a head of a rule + unsigned show : 1; // atom has a name + unsigned extn : 2; // value if atom is external + }; + struct Heuristic { + Atom_t atom; + Heuristic_t type; + int bias; + unsigned prio; + unsigned cond; + }; + struct Symbol { + unsigned atom : 31; + unsigned hash : 1; + const char* name; + bool operator<(const Symbol& rhs) const { return atom < rhs.atom; } + }; + typedef std::vector AtomMap; + typedef std::vector AtomVec; + typedef std::vector LitVec; + typedef std::vector WLitVec; + typedef std::vector HeuVec; + typedef std::map MinMap; + typedef std::vector OutVec; + SmData() : next_(2) {} + ~SmData() { + flushStep(); + for (SymTab::iterator it = symTab_.begin(), end = symTab_.end(); it != end; ++it) { + delete [] it->second; + } + } + Atom_t newAtom() { return next_++; } + Atom_t falseAtom() { return 1; } + bool mapped(Atom_t a) const { + return a < atoms_.size() && atoms_[a].smId != 0; + } + Atom& mapAtom(Atom_t a) { + if (mapped(a)) { return atoms_[a]; } + if (a >= atoms_.size()) { atoms_.resize(a + 1); } + atoms_[a].smId = next_++; + return atoms_[a]; + } + Lit_t mapLit(Lit_t in) { + Lit_t x = static_cast(mapAtom(atom(in))); + return in < 0 ? -x : x; + } + WeightLit_t mapLit(WeightLit_t in) { + in.lit = mapLit(in.lit); + return in; + } + Atom_t mapHeadAtom(Atom_t a) { + Atom& x = mapAtom(a); + x.head = 1; + return x; + } + AtomSpan mapHead(const AtomSpan& h); + template + Span mapLits(const Span& in, std::vector& out) { + out.clear(); + for (typename Span::iterator x = begin(in); x != end(in); ++x) { out.push_back(mapLit(*x)); } + return toSpan(out); + } + const char* addOutput(Atom_t atom, const StringSpan&, bool addHash); + void addMinimize(Weight_t prio, const WeightLitSpan& lits) { + WLitVec& body = minimize_[prio]; + body.reserve(body.size() + size(lits)); + for (const WeightLit_t* it = begin(lits); it != end(lits); ++it) { + WeightLit_t x = *it; + if (weight(x) < 0) { + x.lit = -x.lit; + x.weight = -x.weight; + } + body.push_back(x); + } + } + void addExternal(Atom_t a, Value_t v) { + Atom& ma = mapAtom(a); + if (!ma.head) { + ma.extn = static_cast(v); + extern_.push_back(a); + } + } + void addHeuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, Atom_t cond) { + Heuristic h = {a, t, bias, prio, cond}; + heuristic_.push_back(h); + } + void flushStep() { + minimize_.clear(); + AtomVec().swap(extern_); + HeuVec().swap(heuristic_); + for (; !output_.empty(); output_.pop_back()) { + if (!output_.back().hash) { delete [] output_.back().name; } + } + } + AtomMap atoms_; // maps input atoms to output atoms + MinMap minimize_; // maps priorities to minimize statements + AtomVec head_; // active rule head + LitVec lits_; // active body literals + WLitVec wlits_; // active weight body literals + AtomVec extern_; // external atoms + HeuVec heuristic_;// list of heuristic modifications not yet processed + SymTab symTab_; + OutVec output_; // list of output atoms not yet processed + Atom_t next_; // next unused output atom +}; +AtomSpan SmodelsConvert::SmData::mapHead(const AtomSpan& h) { + head_.clear(); + for (const Atom_t* x = begin(h); x != end(h); ++x) { + head_.push_back(mapHeadAtom(*x)); + } + if (head_.empty()) { head_.push_back(falseAtom()); } + return toSpan(head_); +} +const char* SmodelsConvert::SmData::addOutput(Atom_t atom, const StringSpan& str, bool addHash) { + char* n = new char[str.size + 1]; + *std::copy(begin(str), end(str), n) = 0; + Symbol s; s.atom = atom; s.name = n; s.hash = 0; + if (addHash && symTab_.insert(SymTab::value_type(atom, s.name)).second) { + s.hash = 1; + } + output_.push_back(s); + return s.name; +} +///////////////////////////////////////////////////////////////////////////////////////// +// SmodelsConvert +///////////////////////////////////////////////////////////////////////////////////////// +SmodelsConvert::SmodelsConvert(AbstractProgram& out, bool ext) : out_(out), data_(new SmData), ext_(ext) {} +SmodelsConvert::~SmodelsConvert() { + delete data_; +} +Lit_t SmodelsConvert::get(Lit_t in) const { + return data_->mapLit(in); +} +unsigned SmodelsConvert::maxAtom() const { + return data_->next_ - 1; +} +const char* SmodelsConvert::getName(Atom_t a) const { + SymTab::iterator it = data_->symTab_.find(a); + return it != data_->symTab_.end() ? it->second : 0; +} +Atom_t SmodelsConvert::makeAtom(const LitSpan& cond, bool named) { + Atom_t id = 0; + if (size(cond) != 1 || cond[0] < 0 || (data_->mapAtom(atom(cond[0])).show && named)) { + // aux :- cond. + Atom_t aux = (id = data_->newAtom()); + out_.rule(Head_t::Disjunctive, toSpan(&aux, 1), data_->mapLits(cond, data_->lits_)); + } + else { + SmData::Atom& ma = data_->mapAtom(atom(*begin(cond))); + ma.show = static_cast(named); + id = ma.smId; + } + return id; +} +void SmodelsConvert::initProgram(bool inc) { + out_.initProgram(inc); +} +void SmodelsConvert::beginStep() { + out_.beginStep(); +} +void SmodelsConvert::rule(Head_t ht, const AtomSpan& head, const LitSpan& body) { + if (!empty(head) || ht == Head_t::Disjunctive) { + AtomSpan mHead = data_->mapHead(head); + out_.rule(ht, mHead, data_->mapLits(body, data_->lits_)); + } +} +void SmodelsConvert::rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) { + if (!empty(head) || ht == Head_t::Disjunctive) { + AtomSpan mHead = data_->mapHead(head); + WeightLitSpan mBody = data_->mapLits(body, data_->wlits_); + if (isSmodelsRule(ht, mHead, bound, mBody)) { + out_.rule(ht, mHead, bound, mBody); + return; + } + Atom_t aux = data_->newAtom(); + data_->lits_.assign(1, lit(aux)); + out_.rule(Head_t::Disjunctive, toSpan(&aux, 1), bound, mBody); + out_.rule(ht, mHead, toSpan(data_->lits_)); + } +} + +void SmodelsConvert::minimize(Weight_t prio, const WeightLitSpan& lits) { + data_->addMinimize(prio, lits); +} +void SmodelsConvert::output(const StringSpan& str, const LitSpan& cond) { + // create a unique atom for cond and set its name to str + data_->addOutput(makeAtom(cond, true), str, true); +} + +void SmodelsConvert::external(Atom_t a, Value_t v) { + data_->addExternal(a, v); +} +void SmodelsConvert::heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& cond) { + if (!ext_) { out_.heuristic(a, t, bias, prio, cond); } + // create unique atom representing _heuristic(...) + Atom_t heuPred = makeAtom(cond, true); + data_->addHeuristic(a, t, bias, prio, heuPred); +} +void SmodelsConvert::acycEdge(int s, int t, const LitSpan& condition) { + if (!ext_) { out_.acycEdge(s, t, condition); } + char buf[80]; + int n = snprintf(buf, sizeof(buf), "_edge(%d,%d)", s, t); + if (n > 0 && static_cast(n) < sizeof(buf)) { + data_->addOutput(makeAtom(condition, true), toSpan(buf, std::strlen(buf)), false); + } +} + +void SmodelsConvert::flush() { + flushMinimize(); + flushExternal(); + flushHeuristic(); + flushSymbols(); + Lit_t f = -static_cast(data_->falseAtom()); + out_.assume(toSpan(&f, 1)); + data_->flushStep(); +} +void SmodelsConvert::endStep() { + flush(); + out_.endStep(); +} +void SmodelsConvert::flushMinimize() { + for (SmData::MinMap::iterator it = data_->minimize_.begin(), end = data_->minimize_.end(); it != end; ++it) { + out_.minimize(it->first, data_->mapLits(toSpan(it->second), data_->wlits_)); + } +} +void SmodelsConvert::flushExternal() { + LitSpan T = toSpan(); + data_->head_.clear(); + for (SmData::AtomVec::const_iterator it = data_->extern_.begin(), end = data_->extern_.end(); it != end; ++it) { + SmData::Atom& a = data_->mapAtom(*it); + Value_t vt = static_cast(a.extn); + if (!ext_) { + if (a.head) { continue; } + Atom_t at = a; + if (vt == Value_t::Free) { data_->head_.push_back(at); } + else if (vt == Value_t::True) { out_.rule(Head_t::Disjunctive, toSpan(&at, 1), T); } + } + else { + out_.external(a, vt); + } + } + if (!data_->head_.empty()) { + out_.rule(Head_t::Choice, toSpan(data_->head_), T); + } +} +void SmodelsConvert::flushHeuristic() { + for (SmData::HeuVec::const_iterator it = data_->heuristic_.begin(), end = data_->heuristic_.end(); it != end; ++it) { + const SmData::Heuristic& heu = *it; + if (!data_->mapped(heu.atom)) { continue; } + SmData::Atom& ma = data_->mapAtom(heu.atom); + const char* name = ma.show ? getName(ma.smId) : 0; + if (!name) { + ma.show = 1; + char buf[80]; + snprintf(buf, sizeof(buf), "_atom(%u)", ma.smId); + name = data_->addOutput(ma, toSpan(buf, std::strlen(buf)), true); + } + std::string heuPred = "_heuristic("; + heuPred += name; + char buf[80]; + snprintf(buf, sizeof(buf), ",%s,%d,%u)", toString(heu.type), heu.bias, heu.prio); + heuPred.append(buf); + Lit_t c = static_cast(heu.cond); + out_.output(toSpan(heuPred), toSpan(&c, 1)); + } +} +void SmodelsConvert::flushSymbols() { + std::sort(data_->output_.begin(), data_->output_.end()); + for (SmData::OutVec::const_iterator it = data_->output_.begin(), end = data_->output_.end(); it != end; ++it) { + Lit_t x = static_cast(it->atom); + out_.output(toSpan(it->name, std::strlen(it->name)), toSpan(&x, 1)); + } +} + +} diff --git a/liblp/src/match_basic_types.cpp b/liblp/src/match_basic_types.cpp new file mode 100644 index 0000000..0ef0831 --- /dev/null +++ b/liblp/src/match_basic_types.cpp @@ -0,0 +1,380 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifdef _MSC_VER +#pragma warning (disable : 4996) // std::copy unsafe +#endif +#include +#include +#include +#include +#include +#include +namespace Potassco { +static std::string fmterror(const char* msg, unsigned line) { + char buf[80]; + sprintf(buf, "parse error in line %u: ", line); + return std::string(buf).append(msg); +} +AbstractProgram::~AbstractProgram() {} +void AbstractProgram::initProgram(bool) {} +void AbstractProgram::beginStep() {} +void AbstractProgram::project(const AtomSpan&) { throw std::logic_error("projection directive not supported"); } +void AbstractProgram::output(const StringSpan&, const LitSpan&) { throw std::logic_error("output directive not supported"); } +void AbstractProgram::external(Atom_t, Value_t) { throw std::logic_error("external directive not supported"); } +void AbstractProgram::assume(const LitSpan&) { throw std::logic_error("assumption directive not supported"); } +void AbstractProgram::heuristic(Atom_t, Heuristic_t, int, unsigned, const LitSpan&) { throw std::logic_error("heuristic directive not supported"); } +void AbstractProgram::acycEdge(int, int, const LitSpan&) { throw std::logic_error("edge directive not supported"); } +void AbstractProgram::theoryTerm(Id_t, int) { throw std::logic_error("theory data not supported"); } +void AbstractProgram::theoryTerm(Id_t, const StringSpan&) { throw std::logic_error("theory data not supported"); } +void AbstractProgram::theoryTerm(Id_t, int, const IdSpan&) { throw std::logic_error("theory data not supported"); } +void AbstractProgram::theoryElement(Id_t, const IdSpan&, const LitSpan&) { throw std::logic_error("theory data not supported"); } +void AbstractProgram::theoryAtom(Id_t, Id_t, const IdSpan&) { throw std::logic_error("theory data not supported"); } +void AbstractProgram::theoryAtom(Id_t, Id_t, const IdSpan&, Id_t, Id_t) { throw std::logic_error("theory data not supported"); } +void AbstractProgram::endStep() {} +const StringSpan Heuristic_t::pred ={"_heuristic(", 11}; +ParseError::ParseError(unsigned a_line, const char* a_msg) + : std::logic_error(fmterror(a_msg, a_line)) + , line(a_line) { +} +///////////////////////////////////////////////////////////////////////////////////////// +// BufferedStream +///////////////////////////////////////////////////////////////////////////////////////// +BufferedStream::BufferedStream(std::istream& str) : str_(str), rpos_(0), line_(1) { + buf_ = new char[ALLOC_SIZE]; + underflow(); +} +BufferedStream::~BufferedStream() { + delete [] buf_; +} +char BufferedStream::rget() { + char c = peek(); + if (!buf_[++rpos_]) { underflow(); } + return c; +} +char BufferedStream::get() { + if (char c = peek()) { + rget(); + if (c == '\r') { + c = '\n'; + if (peek() == '\n') rget(); + } + if (c == '\n') { ++line_; } + return c; + } + return 0; +} +void BufferedStream::skipWs() { + for (char c; (c = peek()) >= 9 && c < 33;) { get(); } +} + +void BufferedStream::underflow(bool upPos) { + if (!str_) return; + if (upPos && rpos_) { + // keep last char for unget + buf_[0] = buf_[rpos_ - 1]; + rpos_ = 1; + } + std::size_t n = ALLOC_SIZE - (1 + rpos_); + str_.read(buf_ + rpos_, n); + std::size_t r = static_cast(str_.gcount()); + buf_[r + rpos_] = 0; +} +bool BufferedStream::unget(char c) { + if (!rpos_) return false; + if ( (buf_[--rpos_] = c) == '\n') { --line_; } + return true; +} +bool BufferedStream::match(const char* w) { + std::size_t wLen = std::strlen(w); + std::size_t bLen = BUF_SIZE - rpos_; + if (bLen < wLen) { + if (wLen > BUF_SIZE) { throw std::logic_error("Token too long - Increase BUF_SIZE!"); } + std::memcpy(buf_, buf_ + rpos_, bLen); + rpos_ = bLen; + underflow(false); + rpos_ = 0; + } + if (std::strncmp(w, buf_ + rpos_, wLen) == 0) { + if (!buf_[rpos_ += wLen]) { underflow(); } + return true; + } + return false; +} +bool BufferedStream::match(int64_t& res, bool noSkipWs) { + if (!noSkipWs) { skipWs(); } + char s = peek(); + if (s == '+' || s == '-') { rget(); } + if (!isDigit(peek())) { return false; } + for (res = toDigit(rget()); isDigit(peek()); ) { + res *= 10; + res += toDigit(rget()); + } + if (s == '-') { res = -res; } + return true; +} +int BufferedStream::copy(char* out, int max) { + if (max < 0) return max; + std::size_t os = 0; + for (std::size_t n = static_cast(max); n && peek();) { + std::size_t b = (ALLOC_SIZE - rpos_) - 1; + std::size_t m = std::min(n, b); + out = std::copy(buf_ + rpos_, buf_ + rpos_ + m, out); + n -= m; + os += m; + rpos_ += m; + if (!peek()) { underflow(); } + } + return static_cast(os); +} +unsigned BufferedStream::line() const { return line_; } +///////////////////////////////////////////////////////////////////////////////////////// +// ProgramReader +///////////////////////////////////////////////////////////////////////////////////////// +ProgramReader::ProgramReader() : str_(0), varMax_(static_cast(INT_MAX)), inc_(false) {} +ProgramReader::~ProgramReader() { delete str_; } +bool ProgramReader::accept(std::istream& str) { + reset(); + str_ = new StreamType(str); + inc_ = false; + return doAttach(inc_); +} +bool ProgramReader::incremental() const { + return inc_; +} +bool ProgramReader::parse(ReadMode m) { + if (str_ == 0) { throw ParseError(1, "no input stream"); } + do { + if (!doParse()) { return false; } + stream()->skipWs(); + require(!more() || incremental(), "invalid extra input"); + } while (m == Complete && more()); + return true; +} +bool ProgramReader::more() { + return str_ && (str_->skipWs(), !str_->end()); +} +void ProgramReader::reset() { + delete str_; str_ = 0; + doReset(); +} +void ProgramReader::doReset() {} +unsigned ProgramReader::line() const { return str_ ? str_->line() : 1; } +BufferedStream* ProgramReader::stream() const { return str_; } +bool ProgramReader::require(bool cnd, const char* msg) const { return cnd || (throw ParseError(line(), msg), false); } +char ProgramReader::peek(bool skipws) const { if (skipws) str_->skipWs(); return str_->peek(); } +void ProgramReader::skipLine() { + while (str_->peek() && str_->get() != '\n') {} +} +int readProgram(std::istream& str, ProgramReader& reader, ErrorHandler err) { + try { + if (!reader.accept(str) || !reader.parse(ProgramReader::Complete)) { + throw ParseError(reader.line(), "invalid input format"); + } + } + catch (const ParseError& e) { + if (!err) { throw; } + return err(e.line, e.what()); + } + catch (const std::exception& e) { + if (!err) { throw; } + return err(reader.line(), e.what()); + } + return 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// String matching +///////////////////////////////////////////////////////////////////////////////////////// +bool match(const char*& input, const char* word) { + std::size_t len = std::strlen(word); + if (std::strncmp(input, word, len) == 0) { + input += len; + return true; + } + return false; +} +bool matchAtomArg(const char*& input, StringSpan& arg) { + const char* scan = input; + for (int p = 0; *scan; ++scan) { + if (*scan == '(') { ++p; } + else if (*scan == ')') { if (--p < 0) { break; } } + else if (*scan == ',') { if (p == 0) { break; } } + else if (*scan == '"') { + bool quoted = false; + for (++scan; *scan && (*scan != '\"' || quoted); ++scan) { + quoted = !quoted && *scan == '\\'; + } + if (!*scan) { return false; } + } + } + arg = toSpan(input, static_cast(scan - input)); + input = scan; + return arg.size != 0; +} +bool match(const char*& input, Heuristic_t& heuType) { + for (unsigned x = 0; x <= static_cast(Heuristic_t::eMax); ++x) { + if (match(input, toString(static_cast(x)))) { + heuType = static_cast(x); + return true; + } + } + return false; +} + +bool match(const char*& input, int& out) { + char* eptr; + long t = std::strtol(input, &eptr, 10); + if (eptr == input || t < INT_MIN || t > INT_MAX) { + return false; + } + out = static_cast(t); + input = eptr; + return true; +} + +int matchDomHeuPred(const char*& in, StringSpan& atom, Heuristic_t& type, int& bias, unsigned& prio) { + int p; + if (!match(in, begin(Heuristic_t::pred))) { return 0; } + if (!matchAtomArg(in, atom) || !match(in, ",")) { return -1; } + if (!match(in, type) || !match(in, ",")) { return -2; } + if (!match(in, bias)) { return -3; } + prio = static_cast(bias < 0 ? -bias : bias); + if (!match(in, ",")) { return match(in, ")") ? 1 : -3; } + if (!match(in, p) || p < 0) { return -4; } + prio = static_cast(p); + return match(in, ")") ? 1 : -4; +} + +int matchEdgePred(const char*& in, StringSpan& n0, StringSpan& n1) { + int sPos, tPos, ePos = -1; + if (sscanf(in, "_acyc_%*d_%n%*d_%n%*d%n", &sPos, &tPos, &ePos) == 0 && ePos > 0) { + n0 = toSpan(in + sPos, (tPos - sPos) - 1); + n1 = toSpan(in + tPos, ePos - tPos); + in += ePos; + return size(n0) > 0 && size(n1) > 0 ? 1 : -1; + } + else if (match(in, "_edge(")) { + if (!matchAtomArg(in, n0) || !match(in, ",")) { return -1; } + if (!matchAtomArg(in, n1) || !match(in, ")")) { return -2; } + return 1; + } + return 0; +} +///////////////////////////////////////////////////////////////////////////////////////// +// Data stack +///////////////////////////////////////////////////////////////////////////////////////// +RawStack::RawStack() : mem_(0), top_(0), cap_(0) {} +RawStack::~RawStack() { std::free(mem_); } +RawStack::RawStack(const RawStack& other) { + mem_ = (unsigned char*)std::malloc(other.top()); + std::memcpy(mem_, other.mem_, other.top()); + top_ = cap_ = other.top(); +} +RawStack& RawStack::operator=(const RawStack& other) { + RawStack(other).swap(*this); + return *this; +} +void RawStack::swap(RawStack& other) { + std::swap(mem_, other.mem_); + std::swap(top_, other.top_); + std::swap(cap_, other.cap_); +} +uint32_t RawStack::top() const { + return top_; +} +uint32_t RawStack::capacity() const { + return cap_; +} +void RawStack::clear() { + top_ = 0; +} +void RawStack::reserve(uint32_t nc) { + if (nc > capacity()) { + unsigned char* t = (unsigned char*)std::realloc(mem_, nc); + if (!t) throw std::bad_alloc(); + mem_ = t; + cap_ = nc; + } +} + +void RawStack::setTop(uint32_t idx) { + assert(idx <= cap_); + top_ = idx; +} +uint32_t RawStack::pop_(uint32_t sz) { + assert(sz <= top_); + return top_ -= sz; +} +uint32_t RawStack::push_(uint32_t nSize) { + uint32_t ret = top_; + if ((top_ += nSize) >= ret) { + if (top_ > cap_) { + uint32_t nc = (capacity() * 3) >> 1; + if (top_ > nc) { nc = top_ > 64u ? top_ : 64u; } + reserve(nc); + } + return ret; + } + else { + throw std::bad_alloc(); + } +} +void* RawStack::get(uint32_t idx) const { + assert(idx <= cap_); + return mem_ + idx; +} + +void BasicStack::push(uint32_t obj) { + uint32_t* x; push(&x, 1); + *x = obj; +} +void BasicStack::push(WeightLit_t obj) { + WeightLit_t* x; push(&x, 1); + *x = obj; +} +template +void BasicStack::push(T** x, uint32_t len) { + *x = (T*)get(push_(sizeof(T) * len)); +} +void BasicStack::push(char** x, uint32_t len) { + if (uint32_t mod = (len & (sizeof(uint32_t)-1))) { + len += sizeof(uint32_t) - mod; + } + *x = (char*)get(push_(len)); +} +template +void BasicStack::pop(const T** x, uint32_t len) { + this->setTop(this->top() - (sizeof(T) * len)); + *x = (T*)this->get(this->top()); +} +void BasicStack::pop(const char** x, uint32_t len) { + if (uint32_t mod = (len & (sizeof(uint32_t)-1))) { + len += sizeof(uint32_t) - mod; + } + setTop(top() - len); + *x = (char*)this->get(top()); +} +#define INSTANTIATE_STACK(T) \ +template void BasicStack::push(T**, uint32_t);\ +template void BasicStack::pop(const T**, uint32_t) + +INSTANTIATE_STACK(uint32_t); +INSTANTIATE_STACK(int32_t); +INSTANTIATE_STACK(WeightLit_t); +#undef INSTANTIATE_STACK +} diff --git a/liblp/src/rule_utils.cpp b/liblp/src/rule_utils.cpp new file mode 100644 index 0000000..26a968e --- /dev/null +++ b/liblp/src/rule_utils.cpp @@ -0,0 +1,231 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#include +#include +#include +namespace Potassco { +Rule_t Rule_t::normal(Head_t ht, const AtomSpan& head, const LitSpan& body) { + Rule_t r = {ht, head, Body_t::Normal, {body}}; + return r; +} +Rule_t Rule_t::sum(Head_t ht, const AtomSpan& head, const Sum_t& sum) { + Rule_t r = {ht, head, Body_t::Sum, {}}; + r.agg = sum; + return r; +} +Rule_t Rule_t::sum(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& lits) { + Sum_t s = {lits, bound}; + return sum(ht, head, s); +} +///////////////////////////////////////////////////////////////////////////////////////// +// RuleBuilder +///////////////////////////////////////////////////////////////////////////////////////// +struct RuleBuilder::RuleInfo { + enum STATE { active = 1u, done = 2u }; + enum TYPE { rule = 0u, minimize = 1u }; + uint32_t type : 30; + uint32_t state : 2; + uint32_t head : 28; + uint32_t hType : 2; + uint32_t hState : 2; + uint32_t hSize; + uint32_t body : 28; + uint32_t bType : 2; + uint32_t bState : 2; + uint32_t bSize; + Weight_t bound; +}; +RuleBuilder::RuleBuilder() { + clear(); +} +void RuleBuilder::require(bool cnd, const char* msg) const { + if (!cnd) { throw std::logic_error(msg); } +} +RuleBuilder& RuleBuilder::clear() { + data_.clear(); + RuleInfo* r = data_.push(); + std::memset(r, 0, sizeof(RuleInfo)); + r->state = RuleInfo::active; + r->type = Directive_t::Rule; + return *this; +} +RuleBuilder& RuleBuilder::clearBody() { + RuleInfo* r = info(); + if (r->body >= r->head) { + data_.setTop(r->body); + r->bState = 0; + } + r->bSize = 0; + r->bType = Body_t::Normal; + return *this; +} + +RuleBuilder::RuleInfo* RuleBuilder::info() const { + return static_cast(data_.get(0)); +} +RuleBuilder::RuleInfo* RuleBuilder::init() { + RuleInfo* r = info(); + if (r->state == RuleInfo::done) { + clear(); + r = info(); + } + return r; +} +RuleBuilder& RuleBuilder::start(Head_t ht) { + RuleInfo* r = init(); + if (r->hState != RuleInfo::active) { + require(r->hState == 0u && r->type == Directive_t::Rule, "invalid call to start()"); + endBody(); + r->head = data_.top(); + r->hType = ht; + r->hState = RuleInfo::active; + r->hSize = 0; + } + return *this; +} +RuleBuilder& RuleBuilder::addHead(Atom_t a) { + RuleInfo* r = init(); + if (r->hState != RuleInfo::active) { start(); } + ++r->hSize; + *data_.push() = a; + return *this; +} +RuleBuilder& RuleBuilder::startBody() { startBody(Body_t::Normal, -1); return *this; } +RuleBuilder& RuleBuilder::startSum(Weight_t bound) { startBody(Body_t::Sum, bound); return *this; } +RuleBuilder& RuleBuilder::startMinimize(Weight_t prio) { + RuleInfo* r = init(); + require(!r->head && !r->body, "invalid call to startMinimize()"); + r->type = Directive_t::Minimize; + return startSum(prio); +} +RuleBuilder::RuleInfo* RuleBuilder::startBody(Body_t bt, Weight_t bnd) { + RuleInfo* r = init(); + if (r->bState != RuleInfo::active) { + require(r->bState == 0u, "invalid call to startBody()"); + endHead(); + r->body = data_.top(); + r->bType = bt; + r->bState = RuleInfo::active; + r->bound = bnd; + r->bSize = 0; + } + return r; +} +RuleBuilder& RuleBuilder::addGoal(Lit_t lit) { + return addGoal(lit, 1); +} +RuleBuilder& RuleBuilder::addGoal(Lit_t lit, Weight_t w) { + WeightLit_t wl = {lit, w}; + addGoal(wl); + return *this; +} +RuleBuilder& RuleBuilder::addGoal(WeightLit_t lit) { + RuleInfo* r = startBody(Body_t::Normal, -1); + if (lit.weight == 0) { return *this; } + ++r->bSize; + if (r->bType == Body_t::Normal) { + *data_.push() = lit.lit; + } + else { + *data_.push() = lit; + } + return *this; +} +RuleBuilder& RuleBuilder::setBound(Weight_t bound) { + info()->bound = bound; + return *this; +} +void RuleBuilder::endHead() { + RuleInfo* r = init(); + if (r->hState == RuleInfo::active) { r->hState = RuleInfo::done; } +} +void RuleBuilder::endBody() { + RuleInfo* r = init(); + if (r->bState == RuleInfo::active) { r->bState = RuleInfo::done; } +} +RuleBuilder& RuleBuilder::end(AbstractProgram* out) { + RuleInfo* r = info(); + if (r->state != RuleInfo::done) { + if (!r->head && r->type == Directive_t::Rule) { start(); } + endHead(); + if (!r->body) { startBody(); } + endBody(); + r->state = RuleInfo::done; + } + if (!out) { return *this; } + if (r->type == Directive_t::Minimize) { + out->minimize(r->bound, toSpan(static_cast(data_.get(r->body)), r->bSize)); + } + else if (r->bType == Body_t::Normal) { + out->rule(static_cast(r->hType), toSpan(static_cast(data_.get(r->head)), r->hSize), + toSpan(static_cast(data_.get(r->body)), r->bSize)); + } + else { + out->rule(static_cast(r->hType), toSpan(static_cast(data_.get(r->head)), r->hSize), + r->bound, toSpan(static_cast(data_.get(r->body)), r->bSize)); + } + return *this; +} +uint32_t RuleBuilder::bodySize() const { return info()->bSize; } +uint32_t RuleBuilder::headSize() const { return info()->hSize; } +Body_t RuleBuilder::bodyType() const { return static_cast(info()->bType); } +Atom_t* RuleBuilder::head() const { return static_cast(data_.get(info()->head)); } +Lit_t* RuleBuilder::body() const { return static_cast(data_.get(info()->body)); } +WeightLit_t* RuleBuilder::sum() const { return static_cast(data_.get(info()->body)); } +Weight_t RuleBuilder::bound() const { return info()->bound; } +RuleBuilder& RuleBuilder::weaken(Body_t to, bool w) { + RuleInfo* r = info(); + if (r->bType != Body_t::Normal && to != r->bType) { + if (to == Body_t::Normal) { + Lit_t* x = body(); + for (WeightLit_t* w = sum(), *end = w + r->bSize; w != end; ++w) { *x++ = w->lit; } + data_.setTop(r->body + (r->bSize * sizeof(Lit_t))); + r->bType = Body_t::Normal; + } + else if (to == Body_t::Count) { + Weight_t min = 1; + if (w && r->bSize) { + min = sum()->weight; + for (WeightLit_t* it = sum(), *end = it + r->bSize; it != end; ++it) { + if (min > it->weight) { min = it->weight; } + it->weight = 1; + } + } + r->bound = (r->bound+(min-1))/min; + r->bType = Body_t::Count; + } + } + return *this; +} +Rule_t RuleBuilder::rule() const { + RuleInfo* r = info(); + Rule_t ret; + ret.ht = static_cast(r->hType); + ret.head = toSpan(static_cast(data_.get(r->head)), r->hSize); + ret.bt = static_cast(r->bType); + if (r->bType == Body_t::Normal) { + ret.cond = toSpan(static_cast(data_.get(r->body)), r->bSize); + } + else { + ret.agg.bound = r->bound; + ret.agg.lits = toSpan(static_cast(data_.get(r->body)), r->bSize); + } + return ret; +} +} diff --git a/liblp/src/smodels.cpp b/liblp/src/smodels.cpp new file mode 100644 index 0000000..d594b91 --- /dev/null +++ b/liblp/src/smodels.cpp @@ -0,0 +1,385 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#include +#include +#include +#include +#include +#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER > 1500) || (defined(_LIBCPP_VERSION)) +#include +typedef std::unordered_map StrMap; +#else +#if defined(_MSC_VER) +#include +#else +#include +#endif +typedef std::tr1::unordered_map StrMap; +#endif +namespace Potassco { + +enum SmodelsRule { + End = 0, + Basic = 1, Cardinality = 2, Choice = 3, + Generate = 4, Weight = 5, Optimize = 6, + Disjunctive = 8, + ClaspIncrement = 90, ClaspAssignExt = 91, ClaspReleaseExt = 92 +}; +int isSmodelsHead(Head_t t, const AtomSpan& head) { + if (empty(head)) { return End; } + if (t == Head_t::Choice) { return Choice; } + return size(head) == 1 ? Basic : Disjunctive; +} + +int isSmodelsRule(Head_t t, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) { + if (isSmodelsHead(t, head) != Basic || bound < 0) { return End; } + for (WeightLitSpan::iterator it = begin(body), end = Potassco::end(body); it != end; ++it) { + if (weight(*it) != 1) { return Weight; } + } + return Cardinality; +} +AtomTable::~AtomTable() {} +///////////////////////////////////////////////////////////////////////////////////////// +// SmodelsInput +///////////////////////////////////////////////////////////////////////////////////////// +struct SmodelsInput::SymTab : public AtomTable{ + SymTab(AbstractProgram& o) : out(&o) {} + virtual void add(Atom_t id, const StringSpan& name, bool output) { + atoms.insert(StrMap::value_type(std::string(Potassco::begin(name), Potassco::end(name)), id)); + if (output) { + Lit_t lit = static_cast(id); + out->output(name, toSpan(&lit, 1)); + } + } + virtual Atom_t find(const StringSpan& name) { + temp.assign(Potassco::begin(name), Potassco::end(name)); + StrMap::const_iterator it = atoms.find(temp); + return it != atoms.end() ? it->second : 0; + } + struct Heuristic { + std::string atom; + Heuristic_t type; + int bias; + unsigned prio; + Lit_t cond; + }; + StrMap atoms; + std::string temp; + AbstractProgram* out; +}; +struct SmodelsInput::NodeTab { + Id_t add(const StringSpan& n) { + return nodes.insert(StrMap::value_type(std::string(begin(n), end(n)), (Id_t)nodes.size())).first->second; + } + StrMap nodes; +}; +SmodelsInput::SmodelsInput(AbstractProgram& out, const Options& opts, AtomTable* syms) : out_(out), atoms_(syms), nodes_(0), opts_(opts), delSyms_(false) {} +SmodelsInput::~SmodelsInput() { if (delSyms_) delete atoms_; delete nodes_; } +void SmodelsInput::doReset() {} +bool SmodelsInput::doAttach(bool& inc) { + char n = stream()->peek(); + if (BufferedStream::isDigit(n) && ((inc = (n == '9')) == false || opts_.claspExt)) { + out_.initProgram(inc); + return true; + } + return false; +} + +bool SmodelsInput::doParse() { + out_.beginStep(); + if (readRules() && readSymbols() && readCompute("B+", true) && readCompute("B-", false) && readExtra()) { + out_.endStep(); + return true; + } + return false; +} + +uint32_t SmodelsInput::matchBody(BasicStack& stack) { + uint32_t len = matchPos(); + uint32_t neg = matchPos(); + for (Lit_t* x = stack.makeSpan(len), *end = x + len; x != end; ++x) { + *x = lit(matchAtom()); + if (neg) { *x *= -1; --neg; } + } + return len; +} + +uint32_t SmodelsInput::matchSum(BasicStack& stack, bool weights) { + uint32_t bnd = matchPos(); + uint32_t len = matchPos(); + uint32_t neg = matchPos(); + if (!weights) { std::swap(len, bnd); std::swap(bnd, neg); } + WeightLit_t* wl = stack.makeSpan(len); + for (WeightLit_t* x = wl, *end = wl + len; x != end; ++x) { + WeightLit_t lit = {static_cast(matchAtom()), 1}; + if (neg) { lit.lit *= -1; --neg; } + *x = lit; + } + if (weights) { + for (WeightLit_t* x = wl, *end = wl + len; x != end; ++x) { + x->weight = (Weight_t)matchPos("non-negative weight expected"); + } + } + stack.push(bnd); + return len; +} +bool SmodelsInput::readRules() { + BasicStack data; + Weight_t minPrio = 0; + for (unsigned rt; (rt = matchPos("rule type expected")) != 0;) { + data.clear(); + Atom_t rHead; + switch (rt) { + default: require(false, "unrecognized rule type"); + case Choice: case Disjunctive: { // n a1..an + rHead = matchAtom("positive head size expected"); + for (unsigned i = rHead; i--;) { data.push(matchAtom()); } + LitSpan body = data.popSpan(matchBody(data)); + AtomSpan head = data.popSpan(rHead); + out_.rule(rt == Choice ? Head_t::Choice : Head_t::Disjunctive, head, body); + break; } + case Basic: + rHead = matchAtom(); + out_.rule(Head_t::Disjunctive, toSpan(&rHead, 1), data.popSpan(matchBody(data))); + break; + case Cardinality: // fall through + case Weight:{ // fall through + rHead = matchAtom(); + uint32_t nLits = matchSum(data, rt != Cardinality); + Weight_t bound = (Weight_t)data.pop(); + out_.rule(Head_t::Disjunctive, toSpan(&rHead, 1), bound, data.popSpan(nLits)); + break; } + case Optimize: { + uint32_t nLits = matchSum(data, true); + require(data.pop() == 0, "unrecognized type of optimize rule"); + out_.minimize(minPrio++, data.popSpan(nLits)); + break; } + case ClaspIncrement: + require(opts_.claspExt && matchPos() == 0, "unrecognized rule type"); + break; + case ClaspAssignExt: + case ClaspReleaseExt: + require(opts_.claspExt, "unrecognized rule type"); + rHead = matchAtom(); + if (rt == ClaspAssignExt) { + out_.external(rHead, static_cast((matchPos(2, "0..2 expected") ^ 3) - 1)); + } + else { + out_.external(rHead, Value_t::Release); + } + break; + } + } + return true; +} + +bool SmodelsInput::readSymbols() { + std::string name; + if (opts_.cEdge && !nodes_) { nodes_ = new NodeTab; } + if (opts_.cHeuristic && !atoms_) { atoms_ = new SymTab(out_); delSyms_ = true; } + StringSpan n0, n1; + SymTab::Heuristic heu; + std::vector doms; + for (Lit_t atom; (atom = (Lit_t)matchPos()) != 0;) { + name.clear(); + stream()->get(); + for (char c; (c = stream()->get()) != '\n';) { + require(c != 0, "atom name expected!"); + name += c; + } + const char* n = name.c_str(); + bool filter = false; + if (opts_.cEdge && matchEdgePred(n, n0, n1) > 0) { + Id_t s = nodes_->add(n0); + Id_t t = nodes_->add(n1); + out_.acycEdge(static_cast(s), static_cast(t), toSpan(&atom, 1)); + filter = opts_.filter; + } + else if (opts_.cHeuristic && matchDomHeuPred(n, n0, heu.type, heu.bias, heu.prio) > 0) { + heu.cond = atom; + heu.atom.assign(Potassco::begin(n0), Potassco::end(n0)); + doms.push_back(heu); + filter = opts_.filter; + } + if (atoms_) { atoms_->add(atom, toSpan(name), !filter); } + else if (!filter) { out_.output(toSpan(name), toSpan(&atom, 1)); } + } + for (std::vector::const_iterator it = doms.begin(), end = doms.end(); it != end; ++it) { + if (Atom_t x = atoms_->find(toSpan(it->atom))) { + out_.heuristic(x, it->type, it->bias, it->prio, toSpan(&it->cond, 1)); + } + } + if (!incremental()) { + delete nodes_; + if (delSyms_) delete atoms_; + nodes_ = 0; + atoms_ = 0; + } + return true; +} + +bool SmodelsInput::readCompute(const char* comp, bool val) { + require(match(comp) && stream()->get() == '\n', "compute statement expected"); + for (Lit_t x; (x = (Lit_t)matchPos()) != 0;) { + if (val) { x = neg(x); } + out_.rule(Head_t::Disjunctive, toSpan(), toSpan(&x, 1)); + } + return true; +} + +bool SmodelsInput::readExtra() { + if (match("E")) { + for (Atom_t atom; (atom = matchPos()) != 0;) { + out_.external(atom, Value_t::Free); + } + } + matchPos("number of models expected"); + return true; +} + +int readSmodels(std::istream& in, AbstractProgram& out, ErrorHandler err, const SmodelsInput::Options& opts) { + SmodelsInput reader(out, opts); + return readProgram(in, reader, err); +} +///////////////////////////////////////////////////////////////////////////////////////// +// SmodelsOutput +///////////////////////////////////////////////////////////////////////////////////////// +namespace { + struct Atom { template Atom_t operator()(T x) const { return atom(x); } }; + struct SmWeight { uint32_t operator()(const WeightLit_t& x) const { return static_cast(x.weight >= 0 ? x.weight : -x.weight); } }; + inline Lit_t smLit(const WeightLit_t& x) { return x.weight >= 0 ? x.lit : -x.lit; } + inline Lit_t smLit(Lit_t x) { return x; } + template + static unsigned negSize(const Potassco::Span& lits) { + unsigned r = 0; + for (const T* it = Potassco::begin(lits), *end = Potassco::end(lits); it != end; ++it) { r += smLit(*it) < 0; } + return r; + } + template + static void print(std::ostream& os, const Span& span, unsigned neg, unsigned pos, Op op) { + for (const T* it = begin(span); neg; ++it) { if (smLit(*it) < 0) { os << " " << op(*it); --neg; } } + for (const T* it = begin(span); pos; ++it) { if (smLit(*it) >= 0) { os << " " << op(*it); --pos; } } + } +} +SmodelsOutput::SmodelsOutput(std::ostream& os, bool ext, Atom_t fAtom) : os_(os), false_(fAtom), sec_(0), ext_(ext), inc_(false), fHead_(false) {} +SmodelsOutput& SmodelsOutput::startRule(int rt) { os_ << rt; return *this; } +SmodelsOutput& SmodelsOutput::add(unsigned i) { os_ << " " << i; return *this; } +SmodelsOutput& SmodelsOutput::add(Head_t ht, const AtomSpan& head) { + if (ht == Head_t::Choice || size(head) > 1) { add((unsigned)size(head)); } + for (const Atom_t* x = begin(head); x != end(head); ++x) { add(*x); } + return *this; +} + +SmodelsOutput& SmodelsOutput::add(const LitSpan& lits) { + unsigned neg = negSize(lits), size = static_cast(Potassco::size(lits)); + add(size).add(neg); + print(os_, lits, neg, size - neg, Atom()); + return *this; +} +SmodelsOutput& SmodelsOutput::add(Weight_t bnd, const WeightLitSpan& lits, bool card) { + unsigned neg = negSize(lits), size = static_cast(Potassco::size(lits)); + if (!card) { add(static_cast(bnd)); } + add(size).add(neg); + if (card) { add(static_cast(bnd)); } + print(os_, lits, neg, size - neg, Atom()); + if (!card) { print(os_, lits, neg, size - neg, SmWeight()); } + return *this; +} +SmodelsOutput& SmodelsOutput::endRule() { + os_ << "\n"; + return *this; +} +void SmodelsOutput::require(bool cnd, const char* msg) const { + if (!cnd) { throw std::logic_error(msg); } +} +void SmodelsOutput::initProgram(bool b) { + inc_ = b; + require(!inc_ || ext_, "incremental programs not supported in smodels format"); +} +void SmodelsOutput::beginStep() { + if (ext_ && inc_) { startRule(ClaspIncrement).add(0).endRule(); } + sec_ = 0; + fHead_ = false; +} +void SmodelsOutput::rule(Head_t ht, const AtomSpan& head, const LitSpan& body) { + require(sec_ == 0, "adding rules after symbols not supported"); + if (empty(head)) { + if (ht == Head_t::Choice) { return; } + else { + require(false_ != 0, "empty head requires false atom"); + fHead_ = true; + return SmodelsOutput::rule(ht, toSpan(&false_, 1), body); + } + } + SmodelsRule rt = (SmodelsRule)isSmodelsHead(ht, head); + require(rt != End, "unsupported rule type"); + startRule(rt).add(ht, head).add(body).endRule(); +} +void SmodelsOutput::rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) { + require(sec_ == 0, "adding rules after symbols not supported"); + if (empty(head)) { + require(false_ != 0, "empty head requires false atom"); + fHead_ = true; + return SmodelsOutput::rule(ht, toSpan(&false_, 1), bound, body); + } + SmodelsRule rt = (SmodelsRule)isSmodelsRule(ht, head, bound, body); + require(rt != End, "unsupported rule type"); + startRule(rt).add(ht, head).add(bound, body, rt == Cardinality).endRule(); +} +void SmodelsOutput::minimize(Weight_t, const WeightLitSpan& lits) { + startRule(Optimize).add(0, lits, false).endRule(); +} +void SmodelsOutput::output(const StringSpan& str, const LitSpan& cond) { + require(sec_ <= 1, "adding symbols after compute not supported"); + require(size(cond) == 1 && lit(*begin(cond)) > 0, "general output directive not supported in smodels format"); + if (sec_ == 0) { startRule(End).endRule(); sec_ = 1; } + os_ << unsigned(cond[0]) << " "; + os_.write(begin(str), size(str)); + os_ << "\n"; +} +void SmodelsOutput::external(Atom_t a, Value_t t) { + require(ext_, "external directive not supported in smodels format"); + if (t != Value_t::Release) { + startRule(ClaspAssignExt).add(a).add((unsigned(t)^3)-1).endRule(); + } + else { + startRule(ClaspReleaseExt).add(a).endRule(); + } +} +void SmodelsOutput::assume(const LitSpan& lits) { + require(sec_ < 2, "at most one compute statement supported in smodels format"); + while (sec_ != 2) { startRule(End).endRule(); ++sec_; } + os_ << "B+\n"; + for (const Lit_t* x = begin(lits); x != end(lits); ++x) { + if (lit(*x) > 0) { os_ << atom(*x) << "\n"; } + } + os_ << "0\nB-\n"; + for (const Lit_t* x = begin(lits); x != end(lits); ++x) { + if (lit(*x) < 0) { os_ << atom(*x) << "\n"; } + } + if (fHead_ && false_) { + os_ << false_ << "\n"; + } + os_ << "0\n"; +} +void SmodelsOutput::endStep() { + if (sec_ < 2) { SmodelsOutput::assume(Potassco::toSpan()); } + os_ << "1\n"; +} +} diff --git a/liblp/src/theory_data.cpp b/liblp/src/theory_data.cpp new file mode 100644 index 0000000..5d23c0f --- /dev/null +++ b/liblp/src/theory_data.cpp @@ -0,0 +1,328 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// Clasp is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// Clasp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Clasp; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +#ifdef _MSC_VER +#pragma warning (disable : 4996) // std::copy unsafe +#pragma warning (disable : 4200) // zero-sized array +#elif __clang__ +#pragma clang diagnostic ignored "-Wzero-length-array" +#elif __GNUC__ +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-pedantic" +#endif +#include +#include +#include +#include +#include + +#define FAIL_IF(exp, msg) \ + (void)( (!(exp)) || (throw std::logic_error(msg), 0)) + + +namespace Potassco { +template +static std::size_t nBytes(const IdSpan& ids) { + return sizeof(T) + (ids.size * sizeof(Id_t)); +} +struct FuncData { + static FuncData* newFunc(int32_t base, const IdSpan& args); + static void destroy(FuncData*); + int32_t base; + uint32_t size; + Id_t args[0]; +}; +FuncData* FuncData::newFunc(int32_t base, const IdSpan& args) { + std::size_t nb = nBytes(args); + FuncData* f = new (::operator new(nb)) FuncData; + f->base = base; + f->size = static_cast(Potassco::size(args)); + std::memcpy(f->args, begin(args), f->size * sizeof(Id_t)); + return f; +} +void FuncData::destroy(FuncData* f) { + if (f) { f->~FuncData(); ::operator delete(f); } +} +const uint64_t nulTerm = static_cast(-1); +const uint64_t typeMask = static_cast(3); + +TheoryTerm::TheoryTerm() : data_(nulTerm) {} +TheoryTerm::TheoryTerm(int num) { + data_ = (static_cast(num) << 2) | Theory_t::Number; +} +TheoryTerm::TheoryTerm(const char* sym) { + data_ = (assertPtr(sym) | Theory_t::Symbol); + assert(sym == symbol()); +} +TheoryTerm::TheoryTerm(const FuncData* c) { + data_ = (assertPtr(c) | Theory_t::Compound); +} +uint64_t TheoryTerm::assertPtr(const void* p) const { + uint64_t invalid_pointer_size[ (sizeof(uint64_t) >= sizeof(uintptr_t)) ] = { + static_cast(reinterpret_cast(p)) + }; + FAIL_IF((invalid_pointer_size[0] & 3u) != 0u, "Invalid pointer alignment!"); + return invalid_pointer_size[0]; +} +void TheoryTerm::assertType(Theory_t t) const { FAIL_IF(type() != t, "Invalid term cast!"); } +bool TheoryTerm::valid() const { return data_ != nulTerm; } +Theory_t TheoryTerm::type() const { FAIL_IF(!valid(), "Invalid term!"); return static_cast(data_&typeMask); } +int TheoryTerm::number() const { + assertType(Theory_t::Number); + return static_cast(data_ >> 2); +} +uintptr_t TheoryTerm::getPtr() const { + return static_cast(data_ & ~typeMask); +} +const char* TheoryTerm::symbol() const { + assertType(Theory_t::Symbol); + return reinterpret_cast(getPtr()); +} +FuncData* TheoryTerm::func() const { + return reinterpret_cast(getPtr()); +} +int TheoryTerm::compound() const { + assertType(Theory_t::Compound); + return func()->base; +} +bool TheoryTerm::isFunction() const { return type() == Theory_t::Compound && func()->base >= 0; } +bool TheoryTerm::isTuple() const { return type() == Theory_t::Compound && func()->base < 0; } +Id_t TheoryTerm::function() const { FAIL_IF(!isFunction(), "Invalid term cast: not a function!"); return static_cast(func()->base); } +Tuple_t TheoryTerm::tuple() const { FAIL_IF(!isTuple(), "Invalid term cast: not a tuple!"); return static_cast(func()->base); } +uint32_t TheoryTerm::size() const { return type() == Theory_t::Compound ? func()->size : 0; } +TheoryTerm::iterator TheoryTerm::begin() const { return type() == Theory_t::Compound ? func()->args : 0; } +TheoryTerm::iterator TheoryTerm::end() const { return type() == Theory_t::Compound ? func()->args + func()->size : 0; } + +TheoryElement::TheoryElement(const IdSpan& terms, Id_t c) : nTerms_(static_cast(Potassco::size(terms))), nCond_(c != 0) { + std::memcpy(term_, Potassco::begin(terms), nTerms_ * sizeof(Id_t)); + if (nCond_ != 0) { term_[nTerms_] = c; } +} +TheoryElement* TheoryElement::newElement(const IdSpan& terms, Id_t c) { + std::size_t nb = nBytes(terms); + if (c != 0) { nb += sizeof(Id_t); } + return new (::operator new(nb)) TheoryElement(terms, c); +} +void TheoryElement::destroy(TheoryElement* e) { + if (e) { + e->~TheoryElement(); + ::operator delete(e); + } +} +Id_t TheoryElement::condition() const { + return nCond_ == 0 ? 0 : term_[nTerms_]; +} +void TheoryElement::setCondition(Id_t c) { + term_[nTerms_] = c; +} + +TheoryAtom::TheoryAtom(Id_t a, Id_t term, const IdSpan& args, Id_t* op, Id_t* rhs) + : atom_(a) + , guard_(op != 0) + , termId_(term) + , nTerms_(static_cast(Potassco::size(args))) { + std::memcpy(term_, Potassco::begin(args), nTerms_ * sizeof(Id_t)); + if (op) { + term_[nTerms_] = *op; + term_[nTerms_ + 1] = *rhs; + } +} + +TheoryAtom* TheoryAtom::newAtom(Id_t a, Id_t term, const IdSpan& args) { + return new (::operator new(nBytes(args))) TheoryAtom(a, term, args, 0, 0); +} +TheoryAtom* TheoryAtom::newAtom(Id_t a, Id_t term, const IdSpan& args, Id_t op, Id_t rhs) { + std::size_t nb = nBytes(args) + (2*sizeof(Id_t)); + return new (::operator new(nb)) TheoryAtom(a, term, args, &op, &rhs); +} +void TheoryAtom::destroy(TheoryAtom* a) { + if (a) { + a->~TheoryAtom(); + ::operator delete(a); + } +} +const Id_t* TheoryAtom::guard() const { + return guard_ != 0 ? &term_[nTerms_] : 0; +} +const Id_t* TheoryAtom::rhs() const { + return guard_ != 0 ? &term_[nTerms_ + 1] : 0; +} +////////////////////////////////////////////////////////////////////////////////////////////////////// +// TheoryData +////////////////////////////////////////////////////////////////////////////////////////////////////// +struct TheoryData::DestroyT { + template void operator()(T* x) const { return T::destroy(x); } + void operator()(TheoryTerm& t) const { + if (t.valid()) { + if (t.type() == Theory_t::Compound) { + this->operator()(t.func()); + } + else if (t.type() == Theory_t::Symbol) { + delete[] const_cast(t.symbol()); + } + } + } +}; +TheoryData::TheoryData() {} +TheoryData::~TheoryData() { + reset(); +} +const TheoryTerm& TheoryData::addTerm(Id_t termId, int number) { + return setTerm(termId) = TheoryTerm(number); +} +const TheoryTerm& TheoryData::addTerm(Id_t termId, const StringSpan& name) { + char* buf = new char[name.size + 1]; + *std::copy(Potassco::begin(name), Potassco::end(name), buf) = 0; + return setTerm(termId) = TheoryTerm(buf); +} +const TheoryTerm& TheoryData::addTerm(Id_t termId, const char* name) { + return addTerm(termId, Potassco::toSpan(name, name ? std::strlen(name) : 0)); +} +const TheoryTerm& TheoryData::addTerm(Id_t termId, Id_t funcId, const IdSpan& args) { + return setTerm(termId) = TheoryTerm(FuncData::newFunc(static_cast(funcId), args)); +} +const TheoryTerm& TheoryData::addTerm(Id_t termId, Tuple_t type, const IdSpan& args) { + return setTerm(termId) = TheoryTerm(FuncData::newFunc(static_cast(type), args)); +} +void TheoryData::removeTerm(Id_t termId) { + if (hasTerm(termId)) { + DestroyT()(terms()[termId]); + terms()[termId] = Term(); + } +} +const TheoryElement& TheoryData::addElement(Id_t id, const IdSpan& terms, Id_t cId) { + while (numElems() <= id) { elems_.push(static_cast(0)); } + FAIL_IF(elems()[id] != 0, "Redefinition of theory element!"); + return *(elems()[id] = TheoryElement::newElement(terms, cId)); +} + +const TheoryAtom& TheoryData::addAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elems) { + atoms_.push(static_cast(0)); + return *(atoms()[numAtoms()-1] = TheoryAtom::newAtom(atomOrZero, termId, elems)); +} +const TheoryAtom& TheoryData::addAtom(Id_t atomOrZero, Id_t termId, const IdSpan& elems, Id_t op, Id_t rhs) { + atoms_.push(static_cast(0)); + return *(atoms()[numAtoms()-1] = TheoryAtom::newAtom(atomOrZero, termId, elems, op, rhs)); +} + +TheoryTerm& TheoryData::setTerm(Id_t id) { + while (numTerms() <= id) { terms_.push(TheoryTerm()); } + FAIL_IF(terms()[id].valid(), "Redefinition of theory term!"); + return terms()[id]; +} +void TheoryData::setCondition(Id_t elementId, Id_t newCond) { + FAIL_IF(getElement(elementId).condition() != COND_DEFERRED, "Precondition violated!"); + elems()[elementId]->setCondition(newCond); +} + +void TheoryData::reset() { + DestroyT destroy; + std::for_each(terms(), terms() + numTerms(), destroy); + std::for_each(elems(), elems() + numElems(), destroy); + std::for_each(atoms(), atoms() + numAtoms(), destroy); + PtrStack().swap(terms_); + PtrStack().swap(elems_); + TermStack().swap(atoms_); + frame_ = Up(); +} +void TheoryData::update() { + frame_.atom = numAtoms(); + frame_.term = numTerms(); + frame_.elem = numElems(); +} +TheoryTerm* TheoryData::terms() const { + return static_cast(terms_.get(0)); +} +TheoryElement** TheoryData::elems() const { + return static_cast(elems_.get(0)); +} +TheoryAtom** TheoryData::atoms() const { + return static_cast(atoms_.get(0)); +} + +uint32_t TheoryData::numAtoms() const { + return atoms_.top() / sizeof(TheoryAtom*); +} +uint32_t TheoryData::numTerms() const { + return terms_.top() / sizeof(TheoryTerm); +} +uint32_t TheoryData::numElems() const { + return elems_.top() / sizeof(TheoryElement*); +} +TheoryData::atom_iterator TheoryData::begin() const { + return atoms(); +} +TheoryData::atom_iterator TheoryData::currBegin() const { + return begin() + frame_.atom; +} +TheoryData::atom_iterator TheoryData::end() const { + return begin() + numAtoms(); +} +bool TheoryData::hasTerm(Id_t id) const { + return id < numTerms() && terms()[id].valid(); +} +bool TheoryData::isNewTerm(Id_t id) const { + return hasTerm(id) && id >= frame_.term; +} +bool TheoryData::hasElement(Id_t id) const { + return id < numElems() && elems()[id] != 0; +} +bool TheoryData::isNewElement(Id_t id) const { + return hasElement(id) && id >= frame_.elem; +} +const TheoryTerm& TheoryData::getTerm(Id_t id) const { + FAIL_IF(!hasTerm(id), "Invalid term id!"); + return terms()[id]; +} +const TheoryElement& TheoryData::getElement(Id_t id) const { + FAIL_IF(!hasElement(id), "Invalid element id!"); + return *elems()[id]; +} +void TheoryData::accept(Visitor& out) const { + for (atom_iterator aIt = currBegin(), aEnd = end(); aIt != aEnd; ++aIt) { + out.visit(*this, **aIt); + } +} +void TheoryData::accept(const TheoryTerm& t, Visitor& out) const { + if (t.type() == Theory_t::Compound) { + for (TheoryTerm::iterator it = t.begin(), end = t.end(); it != end; ++it) { + if (isNewTerm(*it)) { out.visit(*this, *it, getTerm(*it)); } + } + if (t.isFunction() && isNewTerm(t.function())) { out.visit(*this, t.function(), getTerm(t.function())); } + } +} +void TheoryData::accept(const TheoryElement& e, Visitor& out) const { + for (TheoryElement::iterator it = e.begin(), end = e.end(); it != end; ++it) { + if (isNewTerm(*it)) { out.visit(*this, *it, getTerm(*it)); } + } +} +void TheoryData::accept(const TheoryAtom& a, Visitor& out) const { + if (isNewTerm(a.term())) { out.visit(*this, a.term(), getTerm(a.term())); } + for (TheoryElement::iterator eIt = a.begin(), eEnd = a.end(); eIt != eEnd; ++eIt) { + if (isNewElement(*eIt)) { out.visit(*this, *eIt, getElement(*eIt)); } + } + if (a.guard() && isNewTerm(*a.guard())) { out.visit(*this, *a.guard(), getTerm(*a.guard())); } + if (a.rhs() && isNewTerm(*a.rhs())) { out.visit(*this, *a.rhs(), getTerm(*a.rhs())); } +} +TheoryData::Visitor::~Visitor() {} +StringSpan toSpan(const char* x) { + return Potassco::toSpan(x, std::strlen(x)); +} + +} diff --git a/liblp/tests/CMakeLists.txt b/liblp/tests/CMakeLists.txt new file mode 100644 index 0000000..2c0a1d8 --- /dev/null +++ b/liblp/tests/CMakeLists.txt @@ -0,0 +1,5 @@ +include_directories(${PROJECT_SOURCE_DIR}/liblp/ .) +aux_source_directory(. SRC_LIST) +add_executable(test EXCLUDE_FROM_ALL ${SRC_LIST}) +target_link_libraries(test liblp) + diff --git a/liblp/tests/aspif.cpp b/liblp/tests/aspif.cpp new file mode 100644 index 0000000..6018988 --- /dev/null +++ b/liblp/tests/aspif.cpp @@ -0,0 +1,521 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "catch.hpp" +#include "common.h" +#include +#include +#include +#include +namespace Potassco { +namespace Test { +namespace Aspif { +const Weight_t BOUND_NONE = -1; +static void finalize(std::stringstream& str) { + str << "0\n"; +} +static void rule(std::ostream& os, const Rule& r) { + os << (unsigned)Directive_t::Rule << " " << r.ht << " "; + os << r.head.size(); + for (auto x : r.head) { os << " " << x; } + os << " " << (unsigned)r.bt << " "; + if (r.bt == Body_t::Sum) { + os << r.bnd << " " << r.body.size(); + std::for_each(begin(r.body), end(r.body), [&os](WeightLit_t x) { os << " " << x.lit << " " << x.weight; }); + } + else { + os << r.body.size(); + std::for_each(begin(r.body), end(r.body), [&os](WeightLit_t x) { os << " " << x.lit; }); + } + os << "\n"; +} + +class ReadObserver : public Test::ReadObserver { +public: + virtual void rule(Head_t ht, const AtomSpan& head, const LitSpan& body) override { + rules.push_back({ht, {begin(head), end(head)}, Body_t::Normal, BOUND_NONE, {}}); + Vec& wb = rules.back().body; + std::for_each(begin(body), end(body), [&wb](Lit_t x) {wb.push_back({x, 1}); }); + } + virtual void rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) override { + rules.push_back({ht, {begin(head), end(head)}, Body_t::Sum, bound, {begin(body), end(body)}}); + } + virtual void minimize(Weight_t prio, const WeightLitSpan& lits) override { + min.push_back({prio, {begin(lits), end(lits)}}); + } + virtual void project(const AtomSpan& atoms) override { + projects.insert(projects.end(), begin(atoms), end(atoms)); + } + virtual void output(const StringSpan& str, const LitSpan& cond) override { + shows.push_back({{begin(str), end(str)}, {begin(cond), end(cond)}}); + } + + virtual void external(Atom_t a, Value_t v) override { + externals.push_back({a, v}); + } + virtual void assume(const LitSpan& lits) override { + assumes.insert(assumes.end(), begin(lits), end(lits)); + } + Vec rules; + Vec > > min; + Vec > > shows; + Vec > externals; + Vec projects; + Vec assumes; +}; + +static int compareRead(std::stringstream& input, ReadObserver& observer, const Rule* rules, const std::pair& subset) { + for (unsigned i = 0; i != subset.second; ++i) { rule(input, rules[subset.first + i]); } + finalize(input); + readAspif(input, observer); + if (observer.rules.size() != subset.second) { + return (int)observer.rules.size(); + } + for (unsigned i = 0; i != subset.second; ++i) { + if (!(rules[subset.first + i] == observer.rules[i])) { + return i; + } + } + return subset.second; +} +TEST_CASE("BasicStack", "[stack]") { + BasicStack stack; + SECTION("empty stack is empty") { + REQUIRE(stack.top() == 0u); + } + SECTION("char is aligned to int") { + stack.push('x'); + REQUIRE(stack.top() == sizeof(int32_t)); + } + SECTION("char span is aligned to multiple of int") { + char* x = stack.makeSpan(13); + REQUIRE(stack.top() == 16); + StringSpan y = stack.popSpan(13); + REQUIRE(x == y.first); + } + SECTION("stack push uint") { + stack.push(92u); + REQUIRE(stack.pop() == 92u); + REQUIRE(stack.top() == 0u); + } + SECTION("stack push wlit") { + WeightLit_t wl = {-123, 99}; + stack.push(wl); + REQUIRE(stack.pop() == wl); + REQUIRE(stack.top() == 0u); + } + SECTION("stack make span") { + Lit_t* x = stack.makeSpan(3); + x[0] = 123; + x[1] = -456; + x[2] = 789; + Lit_t cmp[3] = {123, -456, 789}; + LitSpan span = stack.popSpan(3); + REQUIRE(std::equal(Potassco::begin(span), Potassco::end(span), cmp)); + } +} +TEST_CASE("Intermediate Format Reader ", "[aspif]") { + std::stringstream input; + ReadObserver observer; + input << "asp 1 0 0\n"; + SECTION("read empty") { + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.nStep == 1); + REQUIRE(observer.incremental == false); + } + SECTION("read empty rule") { + rule(input, {Head_t::Disjunctive, {}, Body_t::Normal, BOUND_NONE, {}}); + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.rules.size() == 1); + REQUIRE(observer.rules[0].head.empty()); + REQUIRE(observer.rules[0].body.empty()); + } + SECTION("read rules") { + Rule rules[] = { + {Head_t::Disjunctive, {1}, Body_t::Normal, BOUND_NONE, {{-2, 1}, {3, 1}, {-4, 1}}}, + {Head_t::Disjunctive, {1, 2, 3}, Body_t::Normal, BOUND_NONE, {{5, 1}, {-6, 1}}}, + {Head_t::Disjunctive, {}, Body_t::Normal, BOUND_NONE, {{1, 1}, {2, 1}}}, + {Head_t::Choice, {1, 2, 3}, Body_t::Normal, BOUND_NONE, {{5, 1}, {-6, 1}}}, + // weight + {Head_t::Disjunctive, {1}, Body_t::Sum, 1, {{2, 1}, {-3, 2}, {-4, 3}, {5, 1}}}, + {Head_t::Disjunctive, {2}, Body_t::Sum, 1, {{3, 1}, {-4, 1}, {5, 1}}}, + // mixed + {Head_t::Choice, {1, 2}, Body_t::Sum, 1, {{2, 1}, {-3, 2}, {-4, 3}, {5, 1}}}, + {Head_t::Disjunctive, {}, Body_t::Sum, 1, {{2, 1}, {-3, 2}, {-4, 3}, {5, 1}}}, + // negative weights + {Head_t::Disjunctive, {1}, Body_t::Sum, 1, {{2, 1}, {-3, -2}, {-4, 3}, {5, 1}}} + }; + using Pair = std::pair; + Pair basic(0, 4); + Pair weight(4, 2); + Pair mixed(6, 2); + Pair neg(8, 1); + SECTION("simple rules with normal bodies") { + REQUIRE(compareRead(input, observer, rules, basic) == basic.second); + } + SECTION("read rules with weight body") { + REQUIRE(compareRead(input, observer, rules, weight) == weight.second); + } + SECTION("read mixed rules") { + REQUIRE(compareRead(input, observer, rules, mixed) == mixed.second); + } + SECTION("negative weights not allowed in weight rule") { + REQUIRE_THROWS(compareRead(input, observer, rules, neg)); + } + } + SECTION("read minimize rule") { + input << (unsigned)Directive_t::Minimize << " -1 3 4 5 6 1 3 2\n"; + input << (unsigned)Directive_t::Minimize << " 10 3 4 -52 -6 36 3 -20\n"; + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.min.size() == 2); + const auto& mr1 = observer.min[0]; + const auto& mr2 = observer.min[1]; + REQUIRE(mr1.first == -1); + REQUIRE(mr2.first == 10); + auto lits = Vec{{4, 5}, {6, 1}, {3, 2}}; + REQUIRE(mr1.second == lits); + lits = Vec{{4, -52}, {-6, 36}, {3, -20}}; + REQUIRE(mr2.second == lits); + } + SECTION("read output") { + input << (unsigned)Directive_t::Output << " 1 a 1 1\n"; + input << (unsigned)Directive_t::Output << " 10 Hallo Welt 2 1 -2\n"; + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.shows.size() == 2); + const auto& s1 = observer.shows[0]; + const auto& s2 = observer.shows[1]; + REQUIRE(s1.first == "a"); + REQUIRE(s1.second == Vec({1})); + REQUIRE(s2.first == "Hallo Welt"); + REQUIRE(s2.second == Vec({1, -2})); + } + SECTION("read projection") { + input << (unsigned)Directive_t::Project << " 3 1 2 987232\n"; + input << (unsigned)Directive_t::Project << " 1 17\n"; + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.projects == Vec({1, 2, 987232, 17})); + } + SECTION("read external") { + std::pair exp[] = { + {1, Value_t::Free}, + {2, Value_t::True}, + {3, Value_t::False}, + {4, Value_t::Release} + }; + for (auto&& e : exp) { + input << (unsigned)Directive_t::External << " " << e.first << " " << (unsigned)e.second << "\n"; + } + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(std::distance(begin(exp), end(exp)) == observer.externals.size()); + REQUIRE(std::equal(begin(exp), end(exp), observer.externals.begin()) == true); + } + SECTION("read assumptions") { + input << (unsigned)Directive_t::Assume << " 2 1 987232\n"; + input << (unsigned)Directive_t::Assume << " 1 -2\n"; + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.assumes == Vec({1, 987232, -2})); + } + SECTION("read edges") { + input << (unsigned)Directive_t::Edge << " 0 1 2 1 -2\n"; + input << (unsigned)Directive_t::Edge << " 1 0 1 3\n"; + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.edges.size() == 2); + REQUIRE(observer.edges[0].s == 0); + REQUIRE(observer.edges[0].t == 1); + REQUIRE(observer.edges[0].cond == Vec({1, -2})); + REQUIRE(observer.edges[1].s == 1); + REQUIRE(observer.edges[1].t == 0); + REQUIRE(observer.edges[1].cond == Vec({3})); + } + SECTION("read heuristic") { + Heuristic exp[] = { + {1, Heuristic_t::Sign, -1, 1, {10}}, + {2, Heuristic_t::Level, 10, 3, {-1, 10}}, + {1, Heuristic_t::Init, 20, 1, {}}, + {1, Heuristic_t::Factor, 2, 2, {}} + }; + for (auto&& r : exp) { + input << (unsigned)Directive_t::Heuristic << " " << (unsigned)r.type << " " << r.atom << " " << r.bias + << " " << r.prio << " " << r.cond.size(); + for (auto&& p : r.cond) { input << " " << p; } + input << "\n"; + } + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.heuristics.size() == 4); + REQUIRE(std::equal(std::begin(exp), std::end(exp), observer.heuristics.begin()) == true); + } + SECTION("ignore comments") { + input << (unsigned)Directive_t::Comment << "Hello World" << "\n"; + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + } +} +TEST_CASE("Intermediate Format Reader supports incremental programs", "[aspif]") { + std::stringstream input; + ReadObserver observer; + input << "asp 1 0 0 incremental\n"; + SECTION("read empty steps") { + finalize(input); + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.incremental == true); + REQUIRE(observer.nStep == 2); + } + SECTION("read rules in each steps") { + rule(input, {Head_t::Disjunctive, {1,2}, Body_t::Normal, BOUND_NONE, {}}); + finalize(input); + rule(input, {Head_t::Disjunctive, {3, 4}, Body_t::Normal, BOUND_NONE, {}}); + finalize(input); + REQUIRE(readAspif(input, observer) == 0); + REQUIRE(observer.incremental == true); + REQUIRE(observer.nStep == 2); + REQUIRE(observer.rules.size() == 2); + } +} + +TEST_CASE("Intermediate Format Reader requires current version", "[aspif]") { + std::stringstream input; + ReadObserver observer; + input << "asp 1 2 0 incremental\n"; + finalize(input); + REQUIRE_THROWS(readAspif(input, observer)); +} +TEST_CASE("Intermediate Format Reader requires incremental tag for incremental programs", "[aspif]") { + std::stringstream input; + ReadObserver observer; + input << "asp 1 0 0\n"; + finalize(input); + finalize(input); + REQUIRE_THROWS(readAspif(input, observer)); +} + +TEST_CASE("Test AspifOutput", "[aspif]") { + std::stringstream out; + AspifOutput writer(out); + ReadObserver observer; + writer.initProgram(false); + writer.beginStep(); + SECTION("Writer writes rules") { + Rule rules[] = { + {Head_t::Disjunctive, {1}, Body_t::Normal, BOUND_NONE, {{-2, 1}, {3, 1}, {-4, 1}}}, + {Head_t::Disjunctive, {1, 2, 3}, Body_t::Normal, BOUND_NONE, {{5, 1}, {-6, 1}}}, + {Head_t::Disjunctive, {}, Body_t::Normal, BOUND_NONE, {{1, 1}, {2, 1}}}, + {Head_t::Choice, {1, 2, 3}, Body_t::Normal, BOUND_NONE, {{5, 1}, {-6, 1}}}, + // weight + {Head_t::Disjunctive, {1}, Body_t::Sum, 1, {{2, 1}, {-3, 2}, {-4, 3}, {5, 1}}}, + {Head_t::Disjunctive, {2}, Body_t::Sum, 1, {{3, 1}, {-4, 1}, {5, 1}}}, + // mixed + {Head_t::Choice, {1, 2}, Body_t::Sum, 1, {{2, 1}, {-3, 2}, {-4, 3}, {5, 1}}}, + {Head_t::Disjunctive, {}, Body_t::Sum, 1, {{2, 1}, {-3, 2}, {-4, 3}, {5, 1}}}, + }; + Vec temp; + for (auto&& r : rules) { + if (r.bt == Body_t::Normal) { + temp.clear(); + std::transform(r.body.begin(), r.body.end(), std::back_inserter(temp), [](const WeightLit_t& x) { return x.lit; }); + writer.rule(r.ht, toSpan(r.head), toSpan(temp)); + } + else { + writer.rule(r.ht, toSpan(r.head), r.bnd, toSpan(r.body)); + } + } + writer.endStep(); + readAspif(out, observer); + for (auto&& r : rules) { + REQUIRE(std::find(observer.rules.begin(), observer.rules.end(), r) != observer.rules.end()); + } + } + SECTION("Writer writes minimize") { + auto m1 = Vec{{1, -2}, {-3, 2}, {4, 1}}; + auto m2 = Vec{{-10, 1}, {-20, 2}}; + writer.minimize(1, toSpan(m1)); + writer.minimize(-2, toSpan(m2)); + writer.endStep(); + readAspif(out, observer); + REQUIRE(observer.min.size() == 2); + REQUIRE(observer.min[0].first == 1); + REQUIRE(observer.min[1].first == -2); + REQUIRE(observer.min[0].second == m1); + REQUIRE(observer.min[1].second == m2); + } + SECTION("Writer writes output") { + std::pair > exp[] ={ + {"Hallo", {1, -2, 3}}, + {"Fact", {}} + }; + for (auto&& s : exp) { writer.output(toSpan(s.first), toSpan(s.second)); } + writer.endStep(); + readAspif(out, observer); + for (auto&& s : exp) { REQUIRE(std::find(observer.shows.begin(), observer.shows.end(), s) != observer.shows.end()); } + } + SECTION("Writer writes external") { + std::pair exp[] ={ + {1, Value_t::Free}, + {2, Value_t::True}, + {3, Value_t::False}, + {4, Value_t::Release} + }; + for (auto&& e : exp) { + writer.external(e.first, e.second); + } + writer.endStep(); + readAspif(out, observer); + for (auto&& e : exp) { + REQUIRE(std::find(observer.externals.begin(), observer.externals.end(), e) != observer.externals.end()); + } + } + SECTION("Writer writes assumptions") { + Lit_t a[] ={1, 987232, -2}; + writer.assume(toSpan(a, 2)); + writer.assume(toSpan(a+2, 1)); + writer.endStep(); + readAspif(out, observer); + REQUIRE(observer.assumes.size() == 3); + REQUIRE(std::equal(a, a+3, observer.assumes.begin()) == true); + } + SECTION("Writer writes projection") { + Atom_t a[] ={1, 987232, 2}; + writer.project(toSpan(a, 2)); + writer.project(toSpan(a+2, 1)); + writer.endStep(); + readAspif(out, observer); + REQUIRE(observer.projects.size() == 3); + REQUIRE(std::equal(a, a+3, observer.projects.begin()) == true); + } + SECTION("Writer writes acyc edges") { + Edge exp[] ={ + {0, 1, {1, -2}}, + {1, 0, {3}} + }; + for (auto&& e : exp) { writer.acycEdge(e.s, e.t, toSpan(e.cond)); } + writer.endStep(); + readAspif(out, observer); + REQUIRE(observer.edges.size() == std::distance(std::begin(exp), std::end(exp))); + REQUIRE(std::equal(std::begin(exp), std::end(exp), observer.edges.begin()) == true); + } + SECTION("Writer writes heuristics") { + Heuristic exp[] ={ + {1, Heuristic_t::Sign, -1, 1, {10}}, + {2, Heuristic_t::Level, 10, 3, {-1, 10}}, + {1, Heuristic_t::Init, 20, 1, {}}, + {1, Heuristic_t::Factor, 2, 2, {}} + }; + for (auto&& h : exp) { + writer.heuristic(h.atom, h.type, h.bias, h.prio, toSpan(h.cond)); + } + writer.endStep(); + readAspif(out, observer); + REQUIRE(std::equal(std::begin(exp), std::end(exp), observer.heuristics.begin()) == true); + } +} +TEST_CASE("TheoryData", "[aspif]") { + TheoryData data; + SECTION("Destruct invalid term") { + data.addTerm(10, "Foo"); + data.reset(); + } + SECTION("Term 0 is ok") { + data.addTerm(0, 0); + REQUIRE(data.hasTerm(0)); + REQUIRE(data.getTerm(0).type() == Theory_t::Number); + } + + SECTION("Visit theory") { + using Potassco::toSpan; + Id_t tId = 0, s[3], n[5], o[2], f[3], e[4], args[2]; + // primitives + data.addTerm(n[0] = tId++, 1); // (number 1) + data.addTerm(n[1] = tId++, 2); // (number 2) + data.addTerm(n[2] = tId++, 3); // (number 3) + data.addTerm(n[3] = tId++, 4); // (number 4) + data.addTerm(s[0] = tId++, toSpan("x")); // (string x) + data.addTerm(s[1] = tId++, toSpan("z")); // (string z) + // compounds + data.addTerm(o[0] = tId++, toSpan("*")); // (operator *) + data.addTerm(f[0] = tId++, s[0], toSpan(n, 1)); // (function x(1)) + data.addTerm(f[1] = tId++, s[0], toSpan(n+1, 1)); // (function x(2)) + data.addTerm(f[2] = tId++, s[0], toSpan(n+2, 1)); // (function x(3)) + args[0] = n[0]; args[1] = f[0]; + data.addTerm(e[0] = tId++, o[0], toSpan(args, 2)); // (1 * x(1)) + args[0] = n[1]; args[1] = f[1]; + data.addTerm(e[1] = tId++, o[0], toSpan(args, 2)); // (2 * x(2)) + args[0] = n[2]; args[1] = f[2]; + data.addTerm(e[2] = tId++, o[0], toSpan(args, 2)); // (3 * x(3)) + args[0] = n[3]; args[1] = s[1]; + data.addTerm(e[3] = tId++, o[0], toSpan(args, 2)); // (4 * z) + // elements + Id_t elems[4]; + data.addElement(elems[0] = 0, toSpan(&e[0], 1), 0u); // (element 1*x(1):) + data.addElement(elems[1] = 1, toSpan(&e[1], 1), 0u); // (element 2*x(2):) + data.addElement(elems[2] = 2, toSpan(&e[2], 1), 0u); // (element 3*x(3):) + data.addElement(elems[3] = 3, toSpan(&e[3], 1), 0u); // (element 4*z:) + + // atom + data.addTerm(s[2] = tId++, toSpan("sum")); // (string sum) + data.addTerm(o[1] = tId++, toSpan(">=")); // (string >=) + data.addTerm(n[4] = tId++, 42); // (number 42) + data.addAtom(1, s[2], toSpan(elems, 4), o[1], n[4]); // (&sum { 1*x(1); 2*x(2); 3*x(3); 4*z } >= 42) + + struct Visitor : public TheoryData::Visitor { + void visit(const TheoryData& data, Id_t termId, const TheoryTerm& t) override { + if (out.hasTerm(termId)) return; + switch (t.type()) { + case Potassco::Theory_t::Number: out.addTerm(termId, t.number()); break; + case Potassco::Theory_t::Symbol: out.addTerm(termId, t.symbol()); break; + case Potassco::Theory_t::Compound: + data.accept(t, *this); + if (t.isFunction()) { out.addTerm(termId, t.function(), t.terms()); } + else { out.addTerm(termId, t.tuple(), t.terms()); } + break; + } + } + void visit(const TheoryData& data, Id_t elemId, const TheoryElement& e) override { + if (out.hasElement(elemId)) return; + data.accept(e, *this); + out.addElement(elemId, e.terms(), e.condition()); + } + void visit(const TheoryData& data, const TheoryAtom& a) override { + data.accept(a, *this); + if (!a.guard()) { out.addAtom(a.atom(), a.term(), a.elements()); } + else { out.addAtom(a.atom(), a.term(), a.elements(), *a.guard(), *a.rhs()); } + } + TheoryData out; + } th; + data.accept(th); + REQUIRE(data.numAtoms() == th.out.numAtoms()); + for (Id_t id = 0; id != tId; ++id) { + REQUIRE(data.hasTerm(id) == th.out.hasTerm(id)); + REQUIRE(data.getTerm(id).type() == th.out.getTerm(id).type()); + } + for (Id_t id = 0; id != 4; ++id) { + REQUIRE(data.hasElement(id) == th.out.hasElement(id)); + } + } +} + +}}} diff --git a/liblp/tests/catch.hpp b/liblp/tests/catch.hpp new file mode 100644 index 0000000..2964790 --- /dev/null +++ b/liblp/tests/catch.hpp @@ -0,0 +1,9427 @@ +/* + * CATCH v1.1 build 14 (develop branch) + * Generated: 2015-03-04 18:32:24.627737 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +// #included from: internal/catch_suppress_warnings.h + +#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif + +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Much of the following code is based on Boost (1.53) + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ < 3 + +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif + +#elif __GNUC__ >= 3 + +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now + +#endif // __GNUC__ < 3 + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // _MSC_VER + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +# define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +namespace Catch { + + class NonCopyable { +#ifdef CATCH_CPP11_OR_GREATER + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CPP11_OR_GREATER + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const = 0; + + }; +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + registerTestCase( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + void registerTestCase( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x00, + + ContinueOnFailure = 0x01, // Failures fail test, but execution continues + FalseTest = 0x02, // Prefix expression with ! + SuppressFail = 0x04 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CPP11_OR_GREATER + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ); + + template + ExpressionLhs operator->* ( T const& operand ); + ExpressionLhs operator->* ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +// #included from: catch_sfinae.hpp +#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED + +// Try to detect if the current compiler supports SFINAE + +namespace Catch { + + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; + +#ifdef CATCH_CONFIG_SFINAE + + template struct NotABooleanExpression; + + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; + + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; + +#endif // CATCH_CONFIG_SFINAE + +} // end namespace Catch + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CPP11_OR_GREATER +#include +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern std::string unprintableString; + +// SFINAE is currently disabled by default for all compilers. +// If the non SFINAE version of IsStreamInsertable is ambiguous for you +// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE +#ifdef CATCH_CONFIG_SFINAE + + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; + + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); + + public: + typedef SizedIf type; + }; + + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + +#else + + struct BorgType { + template BorgType( T const& ); + }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#endif + +#if defined(CATCH_CPP11_OR_GREATER) + template::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CPP11_OR_GREATER) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CPP11_OR_GREATER + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + ( __catchResult->*expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } + + std::string m_str; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); + } + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + } + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); + } + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } + + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_runner.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual bool forceColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); + + std::streambuf* streamBuf; + + private: + bool isOwned; + }; + + std::ostream& cout(); + std::ostream& cerr(); +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + forceColour( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool forceColour; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; + + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + : m_os( Catch::cout().rdbuf() ) + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_os( Catch::cout().rdbuf() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + m_os.rdbuf( Catch::cout().rdbuf() ); + m_stream.release(); + } + + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() ); + } + + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } + + std::string getReporterName() const { return m_data.reporterName; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual bool forceColour() const { return m_data.forceColour; } + + private: + ConfigData m_data; + + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +# ifdef CATCH_CPP11_OR_GREATER + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +# endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L + typedef std::unique_ptr ArgAutoPtr; +#else + typedef std::auto_ptr ArgAutoPtr; +#endif + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output" ) + .bind( &ConfigData::forceColour ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CPP11_OR_GREATER + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CPP11_OR_GREATER + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CPP11_OR_GREATER + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + }; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map FactoryMap; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_runner_impl.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { +namespace SectionTracking { + + class TrackedSection { + + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; + + }; + + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), + m_completedASectionThisRun( false ) + {} + + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; + } + + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); + } + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; + } + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; + }; + +} // namespace SectionTracking + +using SectionTracking::TestCaseTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& config, Ptr const& reporter ) + : m_runInfo( config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( NULL ), + m_config( config ), + m_reporter( reporter ), + m_prevRunner( m_context.getRunner() ), + m_prevResultCapture( m_context.getResultCapture() ), + m_prevConfig( m_context.getConfig() ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); + } + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + if( std::uncaught_exception() ) { + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + } + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + } + + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) + : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + buildNumber( _buildNumber ), + branchName( _branchName ) + {} + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + class Runner { + + public: + Runner( Ptr const& config ) + : m_config( config ) + { + openStream(); + makeReporter(); + } + + Totals runTests() { + + RunContext context( m_config.get(), m_reporter ); + + Totals totals; + + context.testGroupStarting( "all tests", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); + } + } + std::vector skippedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true ); + + for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); + it != itEnd; + ++it ) + m_reporter->skipTest( *it ); + + context.testGroupEnded( "all tests", totals, 1, 1 ); + return totals; + } + + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); + } + } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); + + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + } + + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; + }; + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + Catch::cout() << " (" << libraryVersion.branchName << " branch)"; + Catch::cout() << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + std::srand( m_configData.rngSeed ); + + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace Catch { + + class TestRegistry : public ITestCaseRegistry { + struct LexSort { + bool operator() (TestCase i,TestCase j) const { return (i const& getAllTests() const { + return m_functionsInOrder; + } + + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } + + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const { + + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ); + if( includeTest != negated ) + matchingTestCases.push_back( *it ); + } + sortTests( config, matchingTestCases ); + } + + private: + + static void sortTests( IConfig const& config, std::vector& matchingTestCases ) { + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + RandomNumberGenerator rng; + std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + } + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + AutoReg::~AutoReg() {} + + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); + } + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + throw; +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); + } + } + + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; + + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() + : streamBuf( NULL ), isOwned( false ) + {} + + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + : streamBuf( _streamBuf ), isOwned( _isOwned ) + {} + + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; + } + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false ); + if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); + + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + return (config && config->forceColour()) || isatty(STDOUT_FILENO) + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = isDebuggerActive() + ? NoColourImpl::instance() + : platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + tags( _tags ), + lineInfo( _lineInfo ), + properties( None ) + { + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); + lcaseTags.insert( lcaseTag ); + } + tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + // These numbers are maintained by a script + Version libraryVersion( 1, 1, 14, "develop" ); +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) + getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + std::string unprintableString = "{?}"; + + namespace { + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + + virtual ~StreamingReporterBase(); + + virtual void noMatchingTestCases( std::string const& ) {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + ~CumulativeReporterBase(); + + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} + + virtual void testCaseStarting( TestCaseInfo const& ) {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) {} + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + +//# ifndef CATCH_CPP11_OR_GREATER +// XmlWriter& operator = ( XmlWriter const& other ) { +// XmlWriter temp( other ); +// swap( temp ); +// return *this; +// } +//# else +// XmlWriter( XmlWriter const& ) = default; +// XmlWriter( XmlWriter && ) = default; +// XmlWriter& operator = ( XmlWriter const& ) = default; +// XmlWriter& operator = ( XmlWriter && ) = default; +//# endif +// +// void swap( XmlWriter& other ) { +// std::swap( m_tagIsOpen, other.m_tagIsOpen ); +// std::swap( m_needsNewline, other.m_needsNewline ); +// std::swap( m_tags, other.m_tags ); +// std::swap( m_indent, other.m_indent ); +// std::swap( m_os, other.m_os ); +// } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; + return *this; + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + {} + + virtual ~XmlReporter(); + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& s ) { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + {} + + ~JunitReporter(); + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * const argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( " Given: " desc, "" ) +#define WHEN( desc ) SECTION( " When: " desc, "" ) +#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) +#define THEN( desc ) SECTION( " Then: " desc, "" ) +#define AND_THEN( desc ) SECTION( " And: " desc, "" ) + +using Catch::Detail::Approx; + +// #included from: internal/catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/liblp/tests/common.h b/liblp/tests/common.h new file mode 100644 index 0000000..17a0cbb --- /dev/null +++ b/liblp/tests/common.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef LIBLP_TEST_COMMON_H_INCLUDED +#define LIBLP_TEST_COMMON_H_INCLUDED +#include +#include +namespace Potassco { +namespace Test { +template +using Vec = std::vector; + +struct Rule { + Head_t ht; + Vec head; + Body_t bt; + Weight_t bnd; + Vec body; + bool operator==(const Rule& rhs) const { + return ht == rhs.ht && head == rhs.head && bt == rhs.bt && bnd == rhs.bnd && body == rhs.body; + } +}; +struct Edge { + int s; + int t; + Vec cond; + bool operator==(const Edge& rhs) const { + return s == rhs.s && t == rhs.t && cond == rhs.cond; + } +}; +struct Heuristic { + Atom_t atom; + Heuristic_t type; + int bias; + unsigned prio; + Vec cond; + bool operator==(const Heuristic& rhs) const { + return atom == rhs.atom && type == rhs.type && bias == rhs.bias && prio == rhs.prio && cond == rhs.cond; + } +}; + +class ReadObserver : public AbstractProgram { +public: + virtual void initProgram(bool inc) override { + incremental = inc; + } + virtual void beginStep() override { + ++nStep; + } + virtual void endStep() override {} + + virtual void heuristic(Atom_t a, Heuristic_t t, int bias, unsigned prio, const LitSpan& cond) override { + heuristics.push_back({a, t, bias, prio, {begin(cond), end(cond)}}); + } + virtual void acycEdge(int s, int t, const LitSpan& cond) override { + edges.push_back({s, t, {begin(cond), end(cond)}}); + } + Vec heuristics; + Vec edges; + int nStep = 0; + bool incremental = false; +}; + + +}} + +#endif diff --git a/liblp/tests/main.cpp b/liblp/tests/main.cpp new file mode 100644 index 0000000..e6d1d56 --- /dev/null +++ b/liblp/tests/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include "catch.hpp" diff --git a/liblp/tests/smodels.cpp b/liblp/tests/smodels.cpp new file mode 100644 index 0000000..61fbf83 --- /dev/null +++ b/liblp/tests/smodels.cpp @@ -0,0 +1,602 @@ +// +// Copyright (c) 2015, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "catch.hpp" +#include "common.h" +#include +#include +#include +#include +#include +namespace Potassco { +namespace Test { +namespace Smodels { +using AtomTab = std::vector; +using LitVec = std::vector; +using RawRule = std::vector; +static void finalize(std::stringstream& str, const AtomTab& atoms = AtomTab(), const std::string& bpos = "", const std::string& bneg = "1") { + str << "0\n"; + for (const auto& s : atoms) str << s << "\n"; + str << "0\nB+\n" << bpos; + if (!bpos.empty() && bpos.back() != '\n') str << "\n"; + str << "0\nB-\n"; + str << bneg; + if (!bneg.empty() && bneg.back() != '\n') str << "\n"; + str << "0\n1\n"; +} + +enum class Rule_t : unsigned { + Basic = 1, Cardinality = 2, Choice = 3, Weight = 5, Optimize = 6, Disjunctive = 8, + ClaspAssignExt = 91, ClaspReleaseExt = 92 +}; + +class ReadObserver : public Test::ReadObserver { +public: + virtual void rule(Head_t ht, const AtomSpan& head, const LitSpan& body) override { + if (empty(head)) { + if (ht == Head_t::Choice) return; + compute.push_back(-lit(body[0])); + } + else { + Rule_t rt = Rule_t::Basic; + std::vector r(1, at(head, 0)); + if (size(head) > 1 || ht == Head_t::Choice) { + r[0] = static_cast(size(head)); + r.insert(r.end(), begin(head), end(head)); + rt = ht == Head_t::Choice ? Rule_t::Choice : Rule_t::Disjunctive; + } + r.insert(r.end(), begin(body), end(body)); + rules[rt].push_back(std::move(r)); + } + } + virtual void rule(Head_t ht, const AtomSpan& head, Weight_t bound, const WeightLitSpan& body) override { + int rt = isSmodelsRule(ht, head, bound, body); + REQUIRE(rt != 0); + REQUIRE(size(head) == 1); + std::vector r(1, at(head, 0)); + r.push_back(bound); + for (auto&& x : body) { + r.push_back(lit(x)); + if (rt == (int)Rule_t::Weight) r.push_back(weight(x)); + } + rules[static_cast(rt)].push_back(std::move(r)); + } + virtual void minimize(Weight_t prio, const WeightLitSpan& lits) override { + std::vector r; r.reserve((size(lits) * 2) + 1); + r.push_back(prio); + for (auto&& x : lits) { + r.push_back(lit(x)); + r.push_back(weight(x)); + } + rules[Rule_t::Optimize].push_back(std::move(r)); + } + virtual void project(const AtomSpan&) override {} + virtual void output(const StringSpan& str, const LitSpan& cond) override { + REQUIRE(size(cond) == 1); + atoms[*begin(cond)].assign(begin(str), end(str)); + } + + virtual void external(Atom_t a, Value_t v) override { + if (v != Value_t::Release) { + rules[Rule_t::ClaspAssignExt].push_back(RawRule{static_cast(a), static_cast(v)}); + } + else { + rules[Rule_t::ClaspReleaseExt].push_back(RawRule{static_cast(a)}); + } + } + virtual void assume(const LitSpan&) override {} + + using RuleMap = std::map > >; + using AtomMap = std::unordered_map; + RuleMap rules; + LitVec compute; + AtomMap atoms; +}; +TEST_CASE("Smodels reader ", "[smodels]") { + std::stringstream input; + ReadObserver observer; + SECTION("read empty") { + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.nStep == 1); + REQUIRE(observer.incremental == false); + REQUIRE(observer.compute.size() == 1); + REQUIRE(observer.compute[0] == -1); + } + SECTION("read basic rule") { + input << "1 2 4 2 4 2 3 5\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + RawRule exp = {2, -4, -2, 3, 5}; + REQUIRE(observer.rules[Rule_t::Basic][0] == exp); + } + SECTION("read choice/disjunctive rule") { + input << "3 2 3 4 2 1 5 6\n"; + input << "8 2 3 4 2 1 5 6\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.rules[Rule_t::Choice].size() == 1); + REQUIRE(observer.rules[Rule_t::Disjunctive].size() == 1); + + RawRule r1 = {2, 3, 4, -5, 6}; + REQUIRE(observer.rules[Rule_t::Choice][0] == r1); + REQUIRE(observer.rules[Rule_t::Disjunctive][0] == r1); + } + SECTION("read card/weight rule") { + input << "2 2 2 1 1 3 4\n"; + input << "5 3 3 3 1 4 5 6 1 2 3\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.rules[Rule_t::Cardinality].size() == 1); + REQUIRE(observer.rules[Rule_t::Weight].size() == 1); + + RawRule r1 = {2, 1, -3, 4}; + RawRule r2 = {3, 3, -4, 1, 5, 2, 6, 3}; + REQUIRE(observer.rules[Rule_t::Cardinality][0] == r1); + REQUIRE(observer.rules[Rule_t::Weight][0] == r2); + } + SECTION("read min rule") { + input << "6 0 3 1 4 5 6 1 3 2\n"; + input << "6 0 3 1 4 5 6 1 3 2\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.rules[Rule_t::Optimize].size() == 2); + RawRule r = {0, -4, 1, 5, 3, 6, 2}; + REQUIRE(observer.rules[Rule_t::Optimize][0] == r); + r[0] = 1; + REQUIRE(observer.rules[Rule_t::Optimize][1] == r); + } + SECTION("read atom names") { + finalize(input, {"1 Foo", "2 Bar", "3 Test(X,Y)"}); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.atoms.size() == 3); + REQUIRE(observer.atoms[1] == "Foo"); + REQUIRE(observer.atoms[2] == "Bar"); + REQUIRE(observer.atoms[3] == "Test(X,Y)"); + } + SECTION("read compute") { + finalize(input, {}, "2\n3", "1\n4\n5"); + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.compute.size() == 5); + const auto& c = observer.compute; + REQUIRE(std::find(c.begin(), c.end(), 2) != c.end()); + REQUIRE(std::find(c.begin(), c.end(), 3) != c.end()); + REQUIRE(std::find(c.begin(), c.end(), -1) != c.end()); + REQUIRE(std::find(c.begin(), c.end(), -4) != c.end()); + REQUIRE(std::find(c.begin(), c.end(), -5) != c.end()); + } + SECTION("read external") { + input << "0\n0\nB+\n0\nB-\n0\nE\n1\n2\n4\n0\n1\n"; + REQUIRE(Potassco::readSmodels(input, observer) == 0); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt].size() == 3); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][0] == RawRule({1, 0})); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][1] == RawRule({2, 0})); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][2] == RawRule({4, 0})); + } +} + +TEST_CASE("SmodelsExtReader ", "[smodels][smodels_ext]") { + std::stringstream input; + ReadObserver observer; + SmodelsInput::Options opts; opts.enableClaspExt(); + SECTION("read incremental") { + input << "90 0\n"; + finalize(input); + input << "90 0\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer, 0, opts) == 0); + REQUIRE(observer.incremental == true); + REQUIRE(observer.nStep == 2); + } + SECTION("read external") { + input << "91 2 0\n"; + input << "91 3 1\n"; + input << "91 4 2\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer, 0, opts) == 0); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt].size() == 3); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][0] == RawRule({2, static_cast(Value_t::False)})); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][1] == RawRule({3, static_cast(Value_t::True)})); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][2] == RawRule({4, static_cast(Value_t::Free)})); + } + SECTION("read release") { + input << "91 2 0\n"; + input << "92 2\n"; + finalize(input); + REQUIRE(Potassco::readSmodels(input, observer, 0, opts) == 0); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt].size() == 1); + REQUIRE(observer.rules[Rule_t::ClaspReleaseExt].size() == 1); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][0] == RawRule({2, static_cast(Value_t::False)})); + REQUIRE(observer.rules[Rule_t::ClaspReleaseExt][0] == RawRule({2})); + } +} + +TEST_CASE("Write smodels", "[smodels]") { + std::stringstream str, exp; + SmodelsOutput writer(str, false, 0); + ReadObserver observer; + writer.initProgram(false); + SECTION("empty program is valid") { + writer.endStep(); + exp << "0\n0\nB+\n0\nB-\n0\n1\n"; + REQUIRE(str.str() == exp.str()); + } + SECTION("body literals are correctly reordered") { + Atom_t a = 1; + Vec body ={2, -3, -4, 5}; + writer.rule(Head_t::Disjunctive, toSpan(&a, 1), toSpan(body)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + RawRule r ={1, -3, -4, 2, 5}; + REQUIRE(observer.rules[Rule_t::Basic][0] == r); + } + SECTION("body literals with weights are correctly reordered") { + Atom_t a = 1; + Vec body ={{2, 2}, {-3, 1}, {-4, 3}, {5, 4}}; + writer.rule(Head_t::Disjunctive, toSpan(&a, 1), 4, toSpan(body)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.rules[Rule_t::Weight].size() == 1); + RawRule r ={1, 4, -3, 1, -4, 3, 2, 2, 5, 4}; + REQUIRE(observer.rules[Rule_t::Weight][0] == r); + } + SECTION("weights are removed from count bodies") { + Atom_t a = 1; + Vec body ={{2, 1}, {-3, 1}, {-4, 1}, {5, 1}}; + writer.rule(Head_t::Disjunctive, toSpan(&a, 1), 3, toSpan(body)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.rules[Rule_t::Cardinality].size() == 1); + RawRule r ={1, 3, -3, -4, 2, 5}; + REQUIRE(observer.rules[Rule_t::Cardinality][0] == r); + } + SECTION("all head atoms are written") { + Vec atoms ={1, 2, 3, 4}; + writer.rule(Head_t::Disjunctive, toSpan(atoms), toSpan()); + writer.rule(Head_t::Choice, toSpan(atoms), toSpan()); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.rules[Rule_t::Disjunctive].size() == 1); + REQUIRE(observer.rules[Rule_t::Choice].size() == 1); + RawRule r ={4, 1, 2, 3, 4}; + REQUIRE(observer.rules[Rule_t::Disjunctive][0] == r); + REQUIRE(observer.rules[Rule_t::Choice][0] == r); + } + SECTION("minimize rules are written without priority") { + Vec body ={{2, 2}, {-3, 1}, {-4, 3}, {5, 4}}; + writer.minimize(10, toSpan(body)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.rules[Rule_t::Optimize].size() == 1); + RawRule r ={0, -3, 1, -4, 3, 2, 2, 5, 4}; + REQUIRE(observer.rules[Rule_t::Optimize][0] == r); + } + SECTION("output is written to symbol table") { + Lit_t a = 1; + std::string an = "Hallo"; + writer.output(toSpan(an), toSpan(&a, 1)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.atoms[a] == an); + } + SECTION("output must be added after rules") { + Lit_t a = 1; + std::string an = "Hallo"; + writer.output(toSpan(an), toSpan(&a, 1)); + Atom_t b = 2; + REQUIRE_THROWS(writer.rule(Head_t::Disjunctive, toSpan(&b, 1), toSpan())); + } + SECTION("compute statement is written via assume") { + Atom_t a = 1; + Vec body ={2, -3, -4, 5}; + writer.rule(Head_t::Disjunctive, toSpan(&a, 1), toSpan(body)); + Lit_t na = -1; + writer.assume(toSpan(&na, 1)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + RawRule r ={1, -3, -4, 2, 5}; + REQUIRE(observer.rules[Rule_t::Basic][0] == r); + REQUIRE(observer.compute.size() == 1); + REQUIRE(observer.compute[0] == na); + } + SECTION("compute statement can contain multiple literals") { + Vec compute ={-1, 2, -3, -4, 5, 6}; + writer.assume(toSpan(compute)); + writer.endStep(); + REQUIRE(readSmodels(str, observer) == 0); + // B+ followed by B- + std::stable_partition(compute.begin(), compute.end(), [](Lit_t x) {return x > 0; }); + REQUIRE(observer.compute == compute); + } + SECTION("only one compute statement supported") { + Lit_t na = -1, b = 2; + writer.assume(toSpan(&na, 1)); + REQUIRE_THROWS(writer.assume(toSpan(&b, 1))); + } + SECTION("complex directives are not supported") { + REQUIRE_THROWS(writer.project(toSpan())); + REQUIRE_THROWS(writer.external(1, Value_t::False)); + REQUIRE_THROWS(writer.heuristic(1, Heuristic_t::Sign, 1, 0, toSpan())); + REQUIRE_THROWS(writer.acycEdge(1, 2, toSpan())); + } +} + +TEST_CASE("Match heuristic predicate", "[smodels]") { + const char* in; + StringSpan atom; + Heuristic_t type; + int bias; unsigned prio; + SECTION("do not match invalid predicate name") { + REQUIRE(0 == matchDomHeuPred(in = "heuristic()", atom, type, bias, prio)); + REQUIRE(0 == matchDomHeuPred(in = "_heu()", atom, type, bias, prio)); + } + SECTION("do not match predicate with wrong arity") { + REQUIRE(-1 == matchDomHeuPred(in = "_heuristic(x)", atom, type, bias, prio)); + REQUIRE(-2 == matchDomHeuPred(in = "_heuristic(x,sign)", atom, type, bias, prio)); + REQUIRE(-4 == matchDomHeuPred(in = "_heuristic(x,sign,1,2,3)", atom, type, bias, prio)); + } + SECTION("do not match predicate with invalid parameter") { + REQUIRE(-2 == matchDomHeuPred(in = "_heuristic(x,invalid,1)", atom, type, bias, prio)); + REQUIRE(-3 == matchDomHeuPred(in = "_heuristic(x,sign,foo)", atom, type, bias, prio)); + REQUIRE(-4 == matchDomHeuPred(in = "_heuristic(x,sign,1,-10)", atom, type, bias, prio)); + REQUIRE(-3 == matchDomHeuPred(in = "_heuristic(x,sign,1a,-10)", atom, type, bias, prio)); + REQUIRE(-2 == matchDomHeuPred(in = "_heuristic(x,sign(),1)", atom, type, bias, prio)); + } + SECTION("match _heuristic/3 and assign implicit priority") { + REQUIRE(1 == matchDomHeuPred(in = "_heuristic(x,level,-10)", atom, type, bias, prio)); + REQUIRE(prio == 10); + REQUIRE(1 == matchDomHeuPred(in = "_heuristic(x,sign,-2147483648)", atom, type, bias, prio)); + REQUIRE(prio == static_cast(2147483647)+1); + REQUIRE(bias == std::numeric_limits::min()); + } + SECTION("match _heuristic/4") { + REQUIRE(1 == matchDomHeuPred(in = "_heuristic(x,level,-10,123)", atom, type, bias, prio)); + REQUIRE(bias == -10); + REQUIRE(prio == 123); + } + SECTION("match complex atom name") { + REQUIRE(1 == matchDomHeuPred(in = "_heuristic(_heuristic(x,y,z),init,1)", atom, type, bias, prio)); + REQUIRE(type == Heuristic_t::Init); + } +} + + +TEST_CASE("SmodelsOutput supports extended programs", "[smodels_ext]") { + std::stringstream str, exp; + SmodelsOutput out(str, true, 0); + SmodelsConvert writer(out, true); + writer.initProgram(true); + writer.beginStep(); + exp << "90 0\n"; + Vec head = {1, 2}; + Vec body = {3, -4}; + Vec min = {{-1, 2}, {2, 1}}; + writer.rule(Head_t::Choice, toSpan(head), toSpan(body)); + exp << (int)Rule_t::Choice << " 2 2 3 2 1 5 4\n"; + writer.external(3, Value_t::False); + writer.external(4, Value_t::False); + writer.minimize(0, toSpan(min)); + writer.heuristic(1, Heuristic_t::Sign, 1, 0, toSpan()); + exp << "1 6 0 0\n"; + exp << (int)Rule_t::Optimize << " 0 2 1 2 3 2 1\n"; + exp << (int)Rule_t::ClaspAssignExt << " 4 0\n"; + exp << (int)Rule_t::ClaspAssignExt << " 5 0\n"; + exp << "0\n6 _heuristic(_atom(2),sign,1,0)\n2 _atom(2)\n0\nB+\n0\nB-\n1\n0\n1\n"; + writer.endStep(); + writer.beginStep(); + exp << "90 0\n"; + head[0] = 3; head[1] = 4; + writer.rule(Head_t::Choice, toSpan(head), toSpan()); + exp << (int)Rule_t::Choice << " 2 4 5 0 0\n"; + writer.endStep(); + exp << "0\n0\nB+\n0\nB-\n1\n0\n1\n"; + REQUIRE(str.str() == exp.str()); +} + + +TEST_CASE("Convert to smodels", "[convert]") { + using BodyLits = std::initializer_list; + using AggLits = std::initializer_list; + ReadObserver observer; + SmodelsConvert convert(observer, true); + convert.initProgram(false); + convert.beginStep(); + SECTION("convert rule") { + Atom_t a = 1; + BodyLits lits = {4, -3, -2, 5}; + convert.rule(Head_t::Disjunctive, {&a, 1}, {begin(lits), lits.size()}); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + RawRule r ={convert.get(a), convert.get(4), convert.get(-3), convert.get(-2), convert.get(5)}; + REQUIRE(observer.rules[Rule_t::Basic][0] == r); + } + SECTION("convert mixed rule") { + std::initializer_list h = {1, 2, 3}; + AggLits lits = {{4, 2}, {-3, 3}, {-2, 1}, {5, 4}}; + convert.rule(Head_t::Choice, {begin(h), h.size()}, 3, {begin(lits), lits.size()}); + REQUIRE(observer.rules[Rule_t::Choice].size() == 1); + REQUIRE(observer.rules[Rule_t::Weight].size() == 1); + int aux = (int)convert.maxAtom(); + RawRule cr = {3, convert.get(1), convert.get(2), convert.get(3), aux}; + RawRule sr = {aux, 3, convert.get(4), 2, convert.get(-3), 3, convert.get(-2), 1, convert.get(5), 4}; + REQUIRE(cr == observer.rules[Rule_t::Choice][0]); + REQUIRE(sr == observer.rules[Rule_t::Weight][0]); + } + + SECTION("convert minimize") { + AggLits m1 = {{4, 1}, {-3, -2}, {-2, 1}, {5, -1}}; + AggLits m2 = {{8, 1}, {-7, 2}, {-6, 1}, {9, 1}}; + convert.minimize(3, {begin(m2), 2}); + convert.minimize(10, {begin(m1), m1.size()}); + convert.minimize(3, {begin(m2)+2, 2}); + REQUIRE(observer.rules[Rule_t::Optimize].size() == 0); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Optimize].size() == 2); + + RawRule m3 = {3, convert.get(8), 1, convert.get(-7), 2, convert.get(-6), 1, convert.get(9), 1}; + RawRule m10 ={10, convert.get(4), 1, convert.get(3), 2, convert.get(-2), 1, convert.get(-5), 1}; + REQUIRE(observer.rules[Rule_t::Optimize][0] == m3); + REQUIRE(observer.rules[Rule_t::Optimize][1] == m10); + } + SECTION("convert output") { + LitVec c = {1, -2, 3}; + convert.output({"Foo", 3}, toSpan(c)); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + REQUIRE(convert.maxAtom() == 5); + Atom_t aux = observer.rules[Rule_t::Basic][0][0]; + REQUIRE(std::strcmp(convert.getName(aux), "Foo") == 0); + } + + SECTION("convert external") { + convert.external(1, Value_t::Free); + convert.external(2, Value_t::True); + convert.external(3, Value_t::False); + convert.external(4, Value_t::Release); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt].size() == 3); + REQUIRE(observer.rules[Rule_t::ClaspReleaseExt].size() == 1); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][0][1] == Value_t::Free); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][1][1] == Value_t::True); + REQUIRE(observer.rules[Rule_t::ClaspAssignExt][2][1] == Value_t::False); + } + SECTION("edges are converted to atoms") { + Lit_t a = 1; + convert.output({"a", 1}, {&a, 1}); + convert.acycEdge(0, 1, {&a, 1}); + LitVec c = {1, 2, 3}; + convert.acycEdge(1, 0, toSpan(c)); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Basic].size() == 2); + REQUIRE(observer.atoms[observer.rules[Rule_t::Basic][0][0]] == "_edge(0,1)"); + REQUIRE(observer.atoms[observer.rules[Rule_t::Basic][1][0]] == "_edge(1,0)"); + } + + SECTION("heuristics are converted to atoms") { + SECTION("empty condition") { + Lit_t a = 1; + convert.heuristic(static_cast(a), Heuristic_t::Factor, 10, 2, toSpan()); + convert.output({"a", 1}, {&a, 1}); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + REQUIRE(convert.maxAtom() == 3); + REQUIRE(observer.atoms[observer.rules[Rule_t::Basic][0][0]] == "_heuristic(a,factor,10,2)"); + } + SECTION("named condition requires aux atom while unnamed does not") { + Lit_t a = 1, b = 2, c = 3; + convert.output({"a", 1}, {&a, 1}); + convert.output({"b", 1}, {&b, 1}); + convert.heuristic(static_cast(a), Heuristic_t::Level, 10, 2, toSpan(&b, 1)); + convert.heuristic(static_cast(a), Heuristic_t::Init, 10, 2, toSpan(&c, 1)); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + REQUIRE(observer.atoms[observer.rules[Rule_t::Basic][0][0]] == "_heuristic(a,level,10,2)"); + REQUIRE(observer.atoms[convert.get(c)] == "_heuristic(a,init,10,2)"); + } + SECTION("unused atom is ignored") { + Lit_t a = 1; + convert.heuristic(static_cast(a), Heuristic_t::Sign, -1, 2, toSpan()); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + REQUIRE(convert.maxAtom() == 2); + REQUIRE(observer.atoms.empty()); + } + SECTION("unnamed atom requires aux name") { + Atom_t a = 1; + convert.rule(Head_t::Choice, {&a, 1}, toSpan()); + convert.heuristic(a, Heuristic_t::Sign, -1, 2, toSpan()); + convert.endStep(); + REQUIRE(observer.rules[Rule_t::Basic].size() == 1); + REQUIRE(convert.maxAtom() == 3); + REQUIRE(observer.atoms[2] == "_atom(2)"); + REQUIRE(observer.atoms[3] == "_heuristic(_atom(2),sign,-1,2)"); + } + } +} +inline StringSpan toSpan(const char* str) { + return Potassco::toSpan(str, std::strlen(str)); +} +using Potassco::toSpan; + +TEST_CASE("Test Atom to directive conversion", "[clasp]") { + ReadObserver observer; + std::stringstream str; + SmodelsOutput writer(str, false, 0); + SmodelsInput::Options opts; opts.enableClaspExt().convertEdges().convertHeuristic(); + std::vector atoms = {1, 2, 3, 4, 5, 6}; + writer.initProgram(false); + writer.beginStep(); + writer.rule(Potassco::Head_t::Choice, Potassco::toSpan(atoms), Potassco::toSpan()); + SECTION("_edge(X,Y) atoms are converted to edges directives") { + Lit_t a = 1, b = 2, c = 3; + writer.output(toSpan("_edge(1,2)"), toSpan(&a, 1)); + writer.output(toSpan("_edge(\"1,2\",\"2,1\")"), toSpan(&b, 1)); + writer.output(toSpan("_edge(\"2,1\",\"1,2\")"), toSpan(&c, 1)); + writer.endStep(); + REQUIRE(readSmodels(str, observer, 0, opts) == 0); + REQUIRE(observer.edges.size() == 3); + REQUIRE(observer.edges[0].cond == Vec({a})); + REQUIRE(observer.edges[0].s == 0); + REQUIRE(observer.edges[0].t == 1); + REQUIRE(observer.edges[1].cond == Vec({b})); + REQUIRE(observer.edges[1].s == observer.edges[2].t); + REQUIRE(observer.edges[2].cond == Vec({c})); + } + SECTION("Test acyc") { + Lit_t a = 1, b = 2; + SECTION("_acyc_ atoms are converted to edge directives") { + writer.output(toSpan("_acyc_1_1234_4321"), toSpan(&a, 1)); + writer.output(toSpan("_acyc_1_4321_1234"), toSpan(&b, 1)); + } + SECTION("_acyc_ and _edge atoms can be mixed") { + writer.output(toSpan("_acyc_1_1234_4321"), toSpan(&a, 1)); + writer.output(toSpan("_edge(4321,1234)"), toSpan(&b, 1)); + } + writer.endStep(); + REQUIRE(readSmodels(str, observer, 0, opts) == 0); + REQUIRE(observer.edges.size() == 2); + REQUIRE(observer.edges[0].cond == Vec({a})); + REQUIRE(observer.edges[1].cond == Vec({b})); + REQUIRE(observer.edges[0].s == observer.edges[1].t); + REQUIRE(observer.edges[0].t == observer.edges[1].s); + } + SECTION("_heuristic atoms are converted to heuristic directive") { + Lit_t a = 1, b = 2, h1 = 3, h2 = 4, h3 = 5, h4 = 6; + writer.output(toSpan("f(a,b,c,d(q(r(s))))"), toSpan(&a, 1)); + writer.output(toSpan("f(\"a,b(c,d)\")"), toSpan(&b, 1)); + writer.output(toSpan("_heuristic(f(a,b,c,d(q(r(s)))),sign,-1)"), toSpan(&h1, 1)); + writer.output(toSpan("_heuristic(f(a,b,c,d(q(r(s)))),true,1)"), toSpan(&h2, 1)); + writer.output(toSpan("_heuristic(f(\"a,b(c,d)\"),level,-1,10)"), toSpan(&h3, 1)); + writer.output(toSpan("_heuristic(f(\"a,b(c,d)\"),factor,2,1)"), toSpan(&h4, 1)); + writer.endStep(); + REQUIRE(readSmodels(str, observer, 0, opts) == 0); + REQUIRE(observer.heuristics.size() == 4); + Heuristic exp[] ={ + {static_cast(a), Heuristic_t::Sign, -1, 1, {h1}}, + {static_cast(a), Heuristic_t::True, 1, 1, {h2}}, + {static_cast(b), Heuristic_t::Level, -1, 10, {h3}}, + {static_cast(b), Heuristic_t::Factor, 2, 1, {h4}} + }; + REQUIRE(std::equal(std::begin(exp), std::end(exp), observer.heuristics.begin()) == true); + } +} + +}}} diff --git a/liblp/tests/text.cpp b/liblp/tests/text.cpp new file mode 100644 index 0000000..b1823b5 --- /dev/null +++ b/liblp/tests/text.cpp @@ -0,0 +1,153 @@ +// +// Copyright (c) 2016, Benjamin Kaufmann +// +// This file is part of Potassco. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "catch.hpp" +#include "common.h" +#include +#include +#include +namespace Potassco { +namespace Test { +namespace Text { + +bool read(AspifTextInput& in, std::stringstream& str) { + return in.accept(str) && in.parse(); +} +TEST_CASE("Text reader ", "[text]") { + std::stringstream input, output; + AspifOutput out(output); + AspifTextInput prg(&out); + + SECTION("read empty") { + REQUIRE(read(prg, input)); + REQUIRE(output.str() == "asp 1 0 0\n0\n"); + } + SECTION("read fact") { + input << "x1."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 0 1 1 0 0") != std::string::npos); + } + SECTION("read basic rule") { + input << "x1 :- not x2."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 0 1 1 0 1 -2") != std::string::npos); + } + SECTION("read choice rule") { + input << "{x1} :- not x2.\n"; + input << "{x2, x3}."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 1 1 1 0 1 -2") != std::string::npos); + REQUIRE(output.str().find("1 1 2 2 3 0 0") != std::string::npos); + } + SECTION("read disjunctive rule") { + input << "x1 | x2 :- not x3."; + input << "x1 ; x2 :- not x4."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 0 2 1 2 0 1 -3") != std::string::npos); + REQUIRE(output.str().find("1 0 2 1 2 0 1 -4") != std::string::npos); + } + SECTION("read weight rule") { + input << "x1 :- 2 {x2, x3=2, not x4 = 3, x5}."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 0 1 1 1 2 4 2 1 3 2 -4 3 5 1") != std::string::npos); + } + SECTION("read alternative atom names") { + input << "a :- not b, x_3."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 0 1 1 0 2 -2 3") != std::string::npos); + } + SECTION("read integrity constraint") { + input << ":- x1, not x2."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("1 0 0 0 2 1 -2") != std::string::npos); + } + SECTION("read minimize constraint") { + input << "#minimize {x1, x2, x3}.\n"; + input << "#minimize {not x1=2, x4, not x5 = 3}@1.\n"; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("2 0 3 1 1 2 1 3 1") != std::string::npos); + REQUIRE(output.str().find("2 1 3 -1 2 4 1 -5 3") != std::string::npos); + } + SECTION("read project") { + input << "#project {a,x2}."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("3 2 1 2") != std::string::npos); + } + SECTION("read output") { + input << "#output foo (1, \"x1, x2\") : x1, x2."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("4 15 foo(1,\"x1, x2\") 2 1 2") != std::string::npos); + } + SECTION("read external") { + input << "#external x1.\n"; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("5 1 2") != std::string::npos); + } + SECTION("read external with value") { + input << "#external x2. [true]\n"; + input << "#external x3. [false]\n"; + input << "#external x4. [free]\n"; + input << "#external x5. [release]\n"; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("5 2 1") != std::string::npos); + REQUIRE(output.str().find("5 3 2") != std::string::npos); + REQUIRE(output.str().find("5 4 0") != std::string::npos); + REQUIRE(output.str().find("5 5 3") != std::string::npos); + } + SECTION("read external with unknown value") { + input << "#external x2. [open]\n"; + REQUIRE_THROWS(read(prg, input)); + } + SECTION("read assume") { + input << "#assume {a, not x2}."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("6 2 1 -2") != std::string::npos); + } + SECTION("read heuristic") { + input << "#heuristic x1. [1, level]"; + input << "#heuristic x2 : x1. [2@1, true]"; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("7 0 1 1 0 0") != std::string::npos); + REQUIRE(output.str().find("7 4 2 2 1 1 1") != std::string::npos); + } + SECTION("read edge") { + input << "#edge (1,2) : x1."; + input << "#edge (2,1)."; + REQUIRE(read(prg, input)); + REQUIRE(output.str().find("8 1 2 1 1") != std::string::npos); + REQUIRE(output.str().find("8 2 1 0") != std::string::npos); + } + SECTION("read incremental") { + input << "#incremental.\n"; + input << "{x1}.\n"; + input << "#step.\n"; + input << "{x2}.\n"; + REQUIRE(read(prg, input)); + REQUIRE(prg.parse()); + REQUIRE(output.str() == + "asp 1 0 0 incremental\n" + "1 1 1 1 0 0\n" + "0\n" + "1 1 1 2 0 0\n" + "0\n"); + } +} + + +}}} diff --git a/libprogram_opts/program_opts/application.h b/libprogram_opts/program_opts/application.h new file mode 100644 index 0000000..e9bf2d0 --- /dev/null +++ b/libprogram_opts/program_opts/application.h @@ -0,0 +1,132 @@ +// +// Copyright (c) Benjamin Kaufmann 2004 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef APP_OPTIONS_H_INCLUDED +#define APP_OPTIONS_H_INCLUDED + +#ifdef _MSC_VER +#pragma warning (disable : 4200) // nonstandard extension used : zero-sized array +#pragma once +#endif + +#include +#include +#include "program_options.h" +#include +#include + +namespace ProgramOptions { +typedef std::vector StringSeq; +///////////////////////////////////////////////////////////////////////////////////////// +// Application base class +///////////////////////////////////////////////////////////////////////////////////////// +#define WRITE_STDERR(type,sys,msg) ( fprintf(stderr, "*** %-5s: (%s): %s\n", (type),(sys),(msg)), fflush(stderr) ) +class Application { +public: + //! Description of and max value for help option. + typedef std::pair HelpOpt; + /*! + * \name Basic functions. + */ + //@{ + //! Returns the name of this application. + virtual const char* getName() const = 0; + //! Returns the version number of this application. + virtual const char* getVersion() const = 0; + //! Returns a null-terminated array of signals that this application handles. + virtual const int* getSignals() const { return 0; } + //! Returns the usage information of this application. + virtual const char* getUsage() const { return "[options]"; } + //! Returns the application's help option and its description. + virtual HelpOpt getHelpOption() const { return HelpOpt("Print help information and exit", 1); } + //! Returns the parser function for handling positional options. + virtual PosOption getPositional() const { return 0; } + //! Prints the given error message to stderr. + virtual void error(const char* msg) const { WRITE_STDERR("ERROR", getName(), msg); } + //! Prints the given info message to stderr. + virtual void info(const char* msg) const { WRITE_STDERR("Info", getName(), msg); } + //! Prints the given warning message to stderr. + virtual void warn(const char* msg) const { WRITE_STDERR("Warn", getName(), msg); } + //@} + + /*! + * \name Main functions. + */ + //@{ + //! Runs this application with the given command-line arguments. + int main(int argc, char** argv); + //! Sets the value that should be returned as the application's exit code. + void setExitCode(int n); + //! Returns the application's exit code. + int getExitCode() const; + //! Returns the application object that is running. + static Application* getInstance(); + //! Prints the application's help information (called if options contain '--help'). + virtual void printHelp(const OptionContext& root); + //! Prints the application's version message (called if options contain '--version'). + virtual void printVersion(); + //! Prints the application's usage message (default is: "usage: getName() getUsage()"). + virtual void printUsage(); + //@} +protected: + /*! + * \name Life cycle and option handling + */ + //@{ + //! Adds all application options to the given context. + virtual void initOptions(OptionContext& root) = 0; + //! Validates parsed options. Shall throw to signal error. + virtual void validateOptions(const OptionContext& root, const ParsedOptions& parsed, const ParsedValues& values) = 0; + //! Called once after option processing is done. + virtual void setup() = 0; + //! Shall run the application. Called after setup and option processing. + virtual void run() = 0; + //! Called after run returned. The default is a noop. + virtual void shutdown(); + //! Called on an exception from run(). The default terminates the application. + virtual void onUnhandledException(); + //! Called when a signal is received. The default terminates the application. + virtual bool onSignal(int); + //@} +protected: + Application(); + virtual ~Application(); + void shutdown(bool hasError); + void exit(int exitCode) const; + unsigned verbose() const; + void setVerbose(unsigned v); + void killAlarm(); + int blockSignals(); + void unblockSignals(bool deliverPending); + void processSignal(int sigNum); +private: + bool getOptions(int argc, char** argv); + int exitCode_; // application's exit code + unsigned timeout_; // active time limit or 0 for no limit + unsigned verbose_; // active verbosity level + bool fastExit_; // force fast exit? + volatile long blocked_; // temporarily block signals? + volatile long pending_; // pending signal or 0 if no pending signal + static Application* instance_s; // running instance (only valid during run()). + static void sigHandler(int sig); // signal/timeout handler +}; + +} +#endif diff --git a/libprogram_opts/program_opts/detail/alarm.h b/libprogram_opts/program_opts/detail/alarm.h new file mode 100644 index 0000000..517f494 --- /dev/null +++ b/libprogram_opts/program_opts/detail/alarm.h @@ -0,0 +1,74 @@ +// +// Copyright (c) Benjamin Kaufmann +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef ALARM_HELPER_H_INCLUDED +#define ALARM_HELPER_H_INCLUDED +///////////////////////////////////////////////////////////////////////////////////////// +// Alarm handling +///////////////////////////////////////////////////////////////////////////////////////// +#include +// Schedules an alarm signal +// The function causes the system to generate a SIGALRM +// signal for the process after the number of real-time seconds +// given in sec. +// +// If seconds is 0, a pending alarm request, if any, is cancelled. +// +// Alarm requests are not stacked; only one SIGALRM generation +// can be scheduled with this function; +// +// setAlarm() returns a value > 0 if the alarm request was set. +// Otherwise it returns 0. +int setAlarm(unsigned sec); + +// Sets the SIGALRM handler +void setAlarmHandler(void(*f)(int)); + +unsigned long initMainThread(); +void resetMainThread(); +void protectMainThread(bool); + +// Implementation: +// - On POSIX-systems setAlarm() calls alarm() and setAlarmHandler() calls signal() +// - On Windows a separate alarm thread is created that +// waits for sec seconds on a termination event and, +// if the event is not signaled, calls the installed alarm handler in the context +// of the alarm thread. +// NOTE: Since the handler is called from a different thread, alarm +// handling is subject to race-conditions. +// USe lockAlarm(), unlockAlarm() to protect functions that +// are not thread-safe and are called by the handler +#if defined(_WIN32) || defined(_WIN64) +void lockAlarm(); +void unlockAlarm(); +#else +inline void lockAlarm() {} +inline void unlockAlarm() {} +#endif + +struct ScopedAlarmLock { + ScopedAlarmLock() { lockAlarm(); } + ~ScopedAlarmLock() { unlockAlarm(); } +}; + +#define SCOPE_ALARM_LOCK() ScopedAlarmLock __alarm_lock__ + + +#if !defined(SIGALRM) +#define SIGALRM 14 +#endif + +#endif diff --git a/libprogram_opts/program_opts/detail/notifier.h b/libprogram_opts/program_opts/detail/notifier.h new file mode 100644 index 0000000..07743b4 --- /dev/null +++ b/libprogram_opts/program_opts/detail/notifier.h @@ -0,0 +1,58 @@ +// +// Copyright (c) Benjamin Kaufmann 2010 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef PROGRAM_OPTIONS_NOTIFIER_H_INCLUDED +#define PROGRAM_OPTIONS_NOTIFIER_H_INCLUDED + +namespace ProgramOptions { namespace detail { + +/////////////////////////////////////////////////////////////////////////////// +// Notifier +/////////////////////////////////////////////////////////////////////////////// +// HACK: +// This should actually be replaced with a proper and typesafe delegate class. +// At least, it should be parametrized on the actual parameter type since +// the invocation of f via the generic func is not strictly conforming. +// Yet, it should work on all major compilers - we do not mess with +// the address and the alignment of void* should be compatible with that of T*. +template +struct Notifier { + typedef bool (*notify_func_type)(void*, const std::string& name, ParamT); + Notifier() : obj(0), func(0) {} + template + Notifier(O* o, bool (*f)(O*, const std::string&, ParamT)) { + obj = o; + func= reinterpret_cast(f); + } + void* obj; + notify_func_type func; + bool notify(const std::string& name, ParamT val) const { + return func(obj, name, val); + } + bool empty() const { return func == 0; } +}; + +template +struct Notify { + typedef bool (*type)(ObjT*, const std::string& name, ParamT); +}; + +} } +#endif diff --git a/libprogram_opts/program_opts/detail/refcountable.h b/libprogram_opts/program_opts/detail/refcountable.h new file mode 100644 index 0000000..ac7ca42 --- /dev/null +++ b/libprogram_opts/program_opts/detail/refcountable.h @@ -0,0 +1,72 @@ +// +// Copyright (c) Benjamin Kaufmann 2010 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef PROGRAM_OPTIONS_REFCOUNTABLE_H_INCLUDED +#define PROGRAM_OPTIONS_REFCOUNTABLE_H_INCLUDED +namespace ProgramOptions { namespace detail { + +class RefCountable { +public: + RefCountable() : refCount_(1) {} + int addRef() { return ++refCount_; } + int release() { return --refCount_; } + int refCount() const { return refCount_; } +private: + int refCount_; +}; + +template +class IntrusiveSharedPtr { +public: + typedef T element_type; + explicit IntrusiveSharedPtr(T* p = 0) throw() + : ptr_(p) { /* NO add ref */ } + IntrusiveSharedPtr(const IntrusiveSharedPtr& o) throw() + : ptr_(o.ptr_) { addRef(); } + ~IntrusiveSharedPtr() throw () { release(); } + IntrusiveSharedPtr& operator=(const IntrusiveSharedPtr& other) { + other.addRef(); + this->release(); + this->ptr_ = other.ptr_; + return *this; + } + T& operator*() const throw() { return *ptr_; } + T* operator->() const throw() { return ptr_; } + T* get() const throw() { return ptr_; } + void reset() throw() { release(); ptr_ = 0; } + bool unique() const throw() { return !ptr_ || ptr_->refCount() == 1; } + int count() const throw() { return ptr_ ? ptr_->refCount() : 0; } + void swap(IntrusiveSharedPtr& b) { + T* temp = ptr_; + ptr_ = b.ptr_; + b.ptr_ = temp; + } +private: + T* ptr_; + void addRef() const { if (ptr_) ptr_->addRef(); } + void release() const { + if (ptr_ && ptr_->release() == 0) { + delete ptr_; + } + } +}; + +}} +#endif diff --git a/libprogram_opts/program_opts/detail/value_store.h b/libprogram_opts/program_opts/detail/value_store.h new file mode 100644 index 0000000..c6f95a1 --- /dev/null +++ b/libprogram_opts/program_opts/detail/value_store.h @@ -0,0 +1,87 @@ +// +// Copyright (c) Benjamin Kaufmann 2010 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef PROGRAM_OPTIONS_VALUE_STORE_IMPL_H_INCLUDED +#define PROGRAM_OPTIONS_VALUE_STORE_IMPL_H_INCLUDED + +#include + +namespace detail { +template +struct VTable { + static void clone(const void* o, void** out) { + *out = new T(*static_cast(o)); + } + static void destroy(const void* o, void** out) { + delete static_cast(o); + *out = 0; + } + static void typeinfo(const void*, void** out) { + *out = const_cast( static_cast(&typeid(T)) ); + } + static vtable_type vtable_s; +}; +template +struct OptVTable { + static void clone(const void* o, void** out) { + new (&*out) T(*static_cast(o)); + } + static void destroy(const void* o, void** out) { + static_cast(o)->~T(); + *out = 0; + } + static vtable_type vtable_s; +}; +template +vtable_type VTable::vtable_s = { + 0 + , &VTable::clone + , &VTable::destroy + , &VTable::typeinfo +}; +template +vtable_type OptVTable::vtable_s = { + (vcall_type)0x1 + , &OptVTable::clone + , &OptVTable::destroy + , &VTable::typeinfo +}; +template struct bool2type {}; +template +inline vptr_type vtable_select(bool2type<0>, const T* = 0) { + return &VTable::vtable_s; +} +template +inline vptr_type vtable_select(bool2type<1>, const T* = 0) { + return &OptVTable::vtable_s; +} +template +inline vptr_type vtable(const T* x) { + return vtable_select(bool2type(), x); +} + +template +inline vptr_type base_vtable(const T* x) { + return vtable_select(bool2type<0>(), x); +} + +} + +#endif diff --git a/libprogram_opts/program_opts/errors.h b/libprogram_opts/program_opts/errors.h new file mode 100644 index 0000000..985306d --- /dev/null +++ b/libprogram_opts/program_opts/errors.h @@ -0,0 +1,109 @@ +// +// Copyright (c) Benjamin Kaufmann 2004 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef PROGRAM_OPTIONS_ERRORS_H_INCLUDED +#define PROGRAM_OPTIONS_ERRORS_H_INCLUDED +#include +#include +namespace ProgramOptions { + +//! Base class for all exceptions. +class Error : public std::logic_error { +public: + explicit Error(const std::string& what) : std::logic_error(what) {} +}; + +//! Used for signaling errors on command-line and in declaring options. +class SyntaxError : public Error { +public: + enum Type { + missing_value, + extra_value, + invalid_format + }; + SyntaxError(Type t, const std::string& key); + ~SyntaxError() throw () {} + Type type() const { return type_; } + const std::string& key() const { return key_; } +private: + std::string key_; + Type type_; +}; + +//! Used for signaling errors in OptionContext. +class ContextError : public Error { +public: + enum Type { + duplicate_option, + unknown_option, + ambiguous_option, + unknown_group, + }; + ContextError(const std::string& ctx, Type t, const std::string& key, const std::string& desc = ""); + ~ContextError() throw () {} + Type type() const { return type_; } + const std::string& key() const { return key_; } + const std::string& ctx() const { return ctx_; } +private: + std::string ctx_; + std::string key_; + Type type_; +}; + +class DuplicateOption : public ContextError { +public: + DuplicateOption(const std::string& ctx, const std::string& key) : ContextError(ctx, ContextError::duplicate_option, key) {} + ~DuplicateOption() throw () {} +}; +class UnknownOption : public ContextError { +public: + UnknownOption(const std::string& ctx, const std::string& key) : ContextError(ctx, ContextError::unknown_option, key) {} + ~UnknownOption() throw () {} +}; +class AmbiguousOption : public ContextError { +public: + AmbiguousOption(const std::string& ctx, const std::string& key, const std::string& alt) : ContextError(ctx, ContextError::ambiguous_option, key, alt) {} + ~AmbiguousOption() throw () {} +}; + +//! Used for signaling validation errors when trying to assign option values. +class ValueError : public Error { +public: + enum Type { + multiple_occurences, + invalid_default, + invalid_value + }; + ValueError(const std::string& ctx, Type t, const std::string& opt, const std::string& value); + ~ValueError() throw () {} + Type type() const { return type_; } + const std::string& key() const { return key_; } + const std::string& ctx() const { return ctx_; } + const std::string& value()const { return value_;} +private: + std::string ctx_; + std::string key_; + std::string value_; + Type type_; +}; + + +} +#endif diff --git a/libprogram_opts/program_opts/mapped_value.h b/libprogram_opts/program_opts/mapped_value.h new file mode 100644 index 0000000..b75a92f --- /dev/null +++ b/libprogram_opts/program_opts/mapped_value.h @@ -0,0 +1,92 @@ +// +// Copyright (c) Benjamin Kaufmann 2010 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef PROGRAM_OPTIONS_MAPPED_VALUE_H_INCLUDED +#define PROGRAM_OPTIONS_MAPPED_VALUE_H_INCLUDED +#ifdef _MSC_VER +#pragma warning (disable : 4786) +#pragma warning (disable : 4503) +#endif +#include "typed_value.h" +#include "value_store.h" +#include +#include +#include +#if defined(_MSC_VER) && _MSC_VER <= 1200 +namespace std { using ::size_t; } +#endif + +namespace ProgramOptions { +/////////////////////////////////////////////////////////////////////////////// +// ValueMap +/////////////////////////////////////////////////////////////////////////////// +//! Type for storing anonymous values +/*! + * Maps option names to their values + */ +class ValueMap { +public: + ValueMap() {} + ~ValueMap(){} + bool empty() const { return map_.empty(); } + size_t size() const { return map_.size(); } + size_t count(const std::string& name) const { return map_.count(name); } + void clear() { map_.clear(); } + const ValueStore& operator[](const std::string& name) const { + MapType::const_iterator it = map_.find(name); + if (it == map_.end()) { + throw UnknownOption("ValueMap", name); + } + return it->second; + } + template + static bool add(ValueMap* this_, const std::string& name, const T* value) { + MapType::iterator it = this_->map_.find(name); + if (it == this_->map_.end()) { + it = this_->map_.insert(it, MapType::value_type(name, ValueStore())); + } + if (it->second.extract_raw() != value) { + it->second.assimilate(const_cast(value)); + } + return true; + } +private: + ValueMap(const ValueMap&); + ValueMap& operator=(const ValueMap&); + typedef std::map MapType; + MapType map_; +}; + +/*! + * Creates a value that is created on demand and stored in a given value map. + * + * \see OptionGroup::addOptions() + */ +template +inline NotifiedValue* store(ValueMap& map, typename detail::Parser::type p = &string_cast) { + return notify(&map, &ValueMap::add, p); +} + +inline NotifiedValue* flag(ValueMap& map, FlagAction a = store_true) { + return flag(&map, &ValueMap::add, a); +} + +} +#endif diff --git a/libprogram_opts/program_opts/program_options.h b/libprogram_opts/program_opts/program_options.h new file mode 100644 index 0000000..2a2c43f --- /dev/null +++ b/libprogram_opts/program_opts/program_options.h @@ -0,0 +1,527 @@ +// +// Copyright (c) Benjamin Kaufmann 2004 +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// +// NOTE: ProgramOptions is inspired by Boost.Program_options +// see: www.boost.org/libs/program_options +// +#ifndef PROGRAM_OPTIONS_PROGRAM_OPTIONS_H_INCLUDED +#define PROGRAM_OPTIONS_PROGRAM_OPTIONS_H_INCLUDED +#include "value.h" +#include "detail/refcountable.h" +#include +#include +#include +#include +#include +#include +namespace ProgramOptions { + +//! Represents one program option. +/*! + * An Option consists of a description (long name, short name, description), + * a (typed) value, and an optional default value. + * + * \note + * When printing an option, occurrences of %D, %I and %A in its description are replaced + * with the option's default value, implicit value and the argument name, + * respectively. + */ +class Option : public detail::RefCountable { +public: + /*! + * \pre longName != "" + * \pre vd != 0 + * \param longName name (and unique key) of the option + * \param shortName possible alias name + * \param description description of the option, used for printing help + * \param value value object to be associated with this option + */ + Option( const std::string& longName, char shortName, + const char* description, Value* value); + + ~Option(); + + const std::string& name() const { return name_; } + char alias() const { return value_->alias(); } + Value* value() const { return value_; } + const char* description() const { return description_; } + const char* argName() const { return value_->arg(); } + bool assignDefault() const; + std::size_t maxColumn() const; + DescriptionLevel descLevel() const { return value_->level(); } +private: + std::string name_; // name (and unique key) of option + const char* description_; // description of the option (used for --help) + Value* value_; // the option's value manager +}; + +typedef detail::IntrusiveSharedPtr